[
  {
    "path": ".arcconfig",
    "content": "{\n  \"project_id\" : \"Meteor framework\",\n  \"conduit_uri\" : \"https://phabricator.meteor.io/\",\n  \"immutable_history\" : false\n}"
  },
  {
    "path": ".eslintignore",
    "content": "android_bundle/\ndev_bundle/\ndocs/\nexamples/\npackages/\nscripts/\ntools/\n!tools/*.js\n!tools/isobuild/*.js\n!tools/catalog/*.js\n!tools/packaging/*.js\n!tools/cli/*.js\n!tools/runners/*.js\n!tools/tool-env/*.js\n!tools/fs/*.js\n\n# Below, files that have yet to be converted to match the linter\ntools/archinfo.js\ntools/auth-client.js\ntools/auth.js\ntools/buildmessage.js\ntools/cleanup.js\ntools/colon-converter.js\ntools/config.js\ntools/console.js\ntools/deploy.js\ntools/fiber-helpers.js\ntools/fs/files.js\ntools/fs/mini-files.js\ntools/func-utils.js\ntools/http-helpers.js\ntools/inspector.js\ntools/index.js\ntools/mongo-exit-codes.js\ntools/processes.js\ntools/progress.js\ntools/project-context.js\ntools/runners/run-log.js\ntools/fs/safe-pathwatcher.js\ntools/selftest.js\ntools/service-connection.js\ntools/shell-client.js\ntools/stats.js\ntools/test-utils.js\ntools/upgraders.js\ntools/utils/utils.js\ntools/fs/watch.js\n\ntools/catalog/catalog-local.js\ntools/catalog/catalog-remote.js\ntools/catalog/catalog.js\ntools/catalog/catalog-utils.js\n\ntools/cli/commands-cordova.js\ntools/cli/commands-packages-query.js\ntools/cli/commands-packages.js\ntools/cli/commands.js\ntools/cli/main.js\n\ntools/tool-env/flush-buffers-on-exit-in-windows.js\ntools/tool-env/install-babel.js\ntools/tool-env/isopackets.js\ntools/tool-env/profile-require.js\ntools/tool-env/profile.js\n\ntools/runners/run-all.js\ntools/runners/run-app.js\ntools/runners/run-mongo.js\ntools/runners/run-proxy.js\ntools/runners/run-selenium.js\ntools/runners/run-updater.js\n\ntools/packaging/package-client.js\ntools/packaging/package-map.js\ntools/packaging/package-version-parser.js\ntools/packaging/release.js\ntools/packaging/tropohouse.js\ntools/packaging/updater.js\ntools/packaging/warehouse.js\n\ntools/isobuild/build-plugin.js\ntools/isobuild/builder.js\ntools/isobuild/bundler.js\ntools/isobuild/compiler-deprecated-compile-step.js\ntools/isobuild/compiler-plugin.js\ntools/isobuild/compiler.js\ntools/isobuild/import-scanner.js\ntools/isobuild/isopack-cache.js\ntools/isobuild/isopack.js\ntools/isobuild/js-analyze.js\ntools/isobuild/linker.js\ntools/isobuild/linter-plugin.js\ntools/isobuild/meteor-npm.js\ntools/isobuild/npm-discards.js\ntools/isobuild/package-api.js\ntools/isobuild/package-source.js\ntools/isobuild/source-arch.js\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "## README and \"Good to know\" section\n\nPlease make sure that you carefully have read the [README](https://github.com/4commerce-technologies-AG/meteor) and especially had a look to its \"Good to know\" section before filing a new issue.\n\n## Guide and tutorial issues\n\nSome of the already known issues may also help as a guide or tutorial. Please check out our [_guide flagged issues_](https://github.com/4commerce-technologies-AG/meteor/issues?q=+label%3Aflag%3Aguide+) if your question may already be answered.\n\n\nThanks for supporting this project\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue.\n\nNote that we are unlikely to accept pull requests that add features without prior discussion. The best way to propose a feature is to open an issue first and discuss your ideas there before implementing them.\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\n/.meteor\n*~\n/dev_bundle\n/dev_bundle*.tar.gz\n/android_bundle\n/android_bundle*.tar.gz\n/node_*.tar.gz\n/mongo_*.tar.gz\n/dist\n\\#*\\#\n.\\#*\n.idea\n*.iml\n*.sublime-project\n*.sublime-workspace\nTAGS\n*.log\n*.out\nnpm-debug.log\nuniverse\n.babel-cache\nmongo-test-output\n"
  },
  {
    "path": ".mailmap",
    "content": "# The presence of this file makes it easier to find GitHub usernames for\n# History.md.\n#\n# This is a git dotfile that affects the output of 'git shortlog'. eg, run:\n#   git shortlog -s release/METEOR@1.0.1..HEAD\n# to get a sorted list of all committers to revisions in HEAD but not\n# in 1.0.1.  To get the list including email addresses (useful for input\n# to the script below) include --email as well.\n#\n# For any emails that show up in the shortlog that aren't in one of\n# these lists, figure out their GitHub username and add them.\n#\n# A command-line way to get the GitHub username for an author:\n#   scripts/admin/find-author-github.sh 'User Name <foo@bar.com>'\n# (Note that this script always outputs GITHUB so you should manually\n# check to see if they are an MDG employee!)\n\nGITHUB: 0a- <a@0a.io>\nGITHUB: adnissen <andrew_nissen@yahoo.com>\nGITHUB: aldeed <eric@dairystatedesigns.com>\nGITHUB: AlexeyMK <alexey@alexeymk.com>\nGITHUB: andylash <andy@squidnet.com>\nGITHUB: ansman <nicklas@ansman.se>\nGITHUB: anstarovoyt <andrey.starovoyt@jetbrains.com>\nGITHUB: apendua <apendua@gmail.com>\nGITHUB: awatson1978 <awatson1978@gmail.com>\nGITHUB: awwx <andrew.wilcox@gmail.com>\nGITHUB: babenzele <tim.p.phillips@gmail.com>\nGITHUB: benweissmann <benweissmann@gmail.com>\nGITHUB: bwhitty <bwhitten518@gmail.com>\nGITHUB: Cangit <fredricendrerud@gmail.com>\nGITHUB: chrisbridgett <me@chrisbridgett.com>\nGITHUB: christianbundy <christianbundy@fraction.io>\nGITHUB: cmather <mather.chris@gmail.com>\nGITHUB: codeinthehole <david.winterbottom@gmail.com>\nGITHUB: colllin <collindo@gmail.com>\nGITHUB: cryptoquick <faustianightmare@gmail.com>\nGITHUB: d4nyll <dan@danyll.com>\nGITHUB: dandv <ddascalescu+github@gmail.com>\nGITHUB: DanielDent <DanielDent@users.noreply.github.com>\nGITHUB: DanielDent <sourcecode@contactdaniel.net>\nGITHUB: DanielDornhardt <daniel@dornhardt.com>\nGITHUB: davegonzalez <gonzalez.dalex@gmail.com>\nGITHUB: DenisGorbachev <Denis.D.Gorbachev@gmail.com>\nGITHUB: DenisGorbachev <Denis.Gorbachev@faster-than-wind.ru>\nGITHUB: ducdigital <duc@ducdigital.com>\nGITHUB: duckspeaker <gallo.j@gmail.com>\nGITHUB: ecwyne <ecwyne@users.noreply.github.com>\nGITHUB: emgee3 <hello@gravitronic.com>\nGITHUB: EOT <eot@gmx.at>\nGITHUB: fay-jai <willson.mock@gmail.com>\nGITHUB: felixrabe <felix@rabe.io>\nGITHUB: FooBarWidget <honglilai@gmail.com>\nGITHUB: FredericoC <frederico.carvalho@3stack.com.au>\nGITHUB: Gaelan <gbs@canishe.com>\nGITHUB: graemian <graeme@graemep.co.za>\nGITHUB: gsuess <garic.suess@gmail.com>\nGITHUB: hwillson <hugh@octonary.com>\nGITHUB: icellan <icellan@icellan.com>\nGITHUB: ImtiazMajeed <imtiazmaj@gmail.com>\nGITHUB: jacott <geoffjacobsen@gmail.com>\nGITHUB: jakozaur <jacek@migdal.pl>\nGITHUB: JamesLefrere <jlefrere@gmail.com>\nGITHUB: jbruni <contato@jbruni.com.br>\nGITHUB: jfhamlin <jfhamlin@gmail.com>\nGITHUB: jperl <perl.jonathan@gmail.com>\nGITHUB: kentonv <temporal@gmail.com>\nGITHUB: kevinchiu <kevin.gc@gmail.com>\nGITHUB: knownasilya <ilya@burstcreations.com>\nGITHUB: LyuGGang <me@lyuwonkyung.com>\nGITHUB: marcandre <github@marc-andre.ca>\nGITHUB: mart-jansink <m.jansink@gmail.com>\nGITHUB: matteodem <mat.demicheli@gmail.com>\nGITHUB: Maxhodges <Max@whiterabbitpress.com>\nGITHUB: MaximDubrovin <maxxdubrovin@gmail.com>\nGITHUB: meawoppl <meawoppl@gmail.com>\nGITHUB: meonkeys <haircut@gmail.com>\nGITHUB: michaelbishop <michael@michaelsplace.net>\nGITHUB: mitar <mitar.git@tnode.com>\nGITHUB: mitar <mitar.github@tnode.com>\nGITHUB: mizzao <mizzao@gmail.com>\nGITHUB: mquandalle <maxime.quandalle@gmail.com>\nGITHUB: mquandalle <maxime@quandalle.com>\nGITHUB: murillo128 <sergio.garcia.murillo@gmail.com>\nGITHUB: musically-ut <musically.ut@gmail.com>\nGITHUB: nathan-muir <ndmuir@gmail.com>\nGITHUB: Neftedollar <oildollar@gmail.com>\nGITHUB: netanelgilad <netanelgilad@gmail.com>\nGITHUB: ogourment <ogourment@smarterportal.com>\nGITHUB: ograycode <jason@theograys.com>\nGITHUB: omeid <public@omeid.me>\nGITHUB: OyoKooN <nathan@sxnlabs.com>\nGITHUB: paulswartz <paulswartz@gmail.com>\nGITHUB: pcjpcj2 <pcjpcj2@gmail.com>\nGITHUB: Pent <jon@empire5design.com>\nGITHUB: physiocoder <ferro.roberto@email.it>\nGITHUB: PooMaster <peter.d.curtis@gmail.com>\nGITHUB: prapicault <pascal@rapicault.net>\nGITHUB: prapicault <pascal@rapicorp.com>\nGITHUB: Primigenus <rchoudhury@gmail.com>\nGITHUB: pscanf <paolo.scanferla@mondora.com>\nGITHUB: queso <joshua.owens@gmail.com>\nGITHUB: rbabayoff <ronen@lavaina.com>\nGITHUB: rcy <rcyeske@gmail.com>\nGITHUB: rdickert <robert.dickert@gmail.com>\nGITHUB: restebanez <restebanez@mdsol.com>\nGITHUB: rgoomar <rishig92@gmail.com>\nGITHUB: rgould <rwgould@gmail.com>\nGITHUB: RichardLitt <richard.littauer@gmail.com>\nGITHUB: richguan <guan.rich@gmail.com>\nGITHUB: rick-golden-healthagen <rick.golden@healthagen.com>\nGITHUB: rissem <rissem@gmail.com>\nGITHUB: rjakobsson <robin@hopjakk.se>\nGITHUB: RobertLowe <robert@iblargz.com>\nGITHUB: romanzolotarev <romanzolotarev@me.com>\nGITHUB: rosh93 <rosh93@gmail.com>\nGITHUB: ryw <ry@rywalker.com>\nGITHUB: rzymek <rzymek@gmail.com>\nGITHUB: sdarnell <stephen@darnell.plus.com>\nGITHUB: Siilwyn <Siilwyn@users.noreply.github.com>\nGITHUB: smallhelm <smallhelm@users.noreply.github.com>\nGITHUB: subhog <hubert@orlikarnia.com>\nGITHUB: svda <svdakker@gmail.com>\nGITHUB: Tarang <Tarang@users.noreply.github.com>\nGITHUB: tbjers <torgny@xorcode.com>\nGITHUB: thatneat <thatneat@users.noreply.github.com>\nGITHUB: timhaines <tmhaines@gmail.com>\nGITHUB: timoabend <timo.abend@liquidmotions.de>\nGITHUB: tmeasday <tom@thesnail.org>\nGITHUB: TomFreudenberg <tom.freudenberg@4commerce.de>\nGITHUB: trusktr <joe@trusktr.io>\nGITHUB: twhy <tom.wanghaiyi@gmail.com>\nGITHUB: Urigo <uri.goldshtein@gmail.com>\nGITHUB: waitingkuo <waitingkuo0527@gmail.com>\nGITHUB: wulfmeister <wulfmeister@users.noreply.github.com>\nGITHUB: yauh <stephan@yauh.de>\nGITHUB: yeputons <egor.suvorov@gmail.com>\nGITHUB: zol <zol@percolatestudio.com>\n\nMETEOR: arbesfeld <arbesfeld@gmail.com>\nMETEOR: avital <avital@thewe.net>\nMETEOR: benjamn <ben@meteor.com>\nMETEOR: benjamn <bn@cs.stanford.edu>\nMETEOR: debergalis <matt@meteor.com>\nMETEOR: dgreensp <dgreenspan@alum.mit.edu>\nMETEOR: ekatek <ekate@meteor.com>\nMETEOR: estark37 <emily@meteor.com>\nMETEOR: estark37 <estark37@gmail.com>\nMETEOR: glasser <glasser@davidglasser.net>\nMETEOR: glasser <glasser@meteor.com>\nMETEOR: gschmidt <geoff@geoffschmidt.com>\nMETEOR: justinsb <justin@fathomdb.com>\nMETEOR: karayu <lele.yu@gmail.com>\nMETEOR: mariapacana <maria.pacana@gmail.com>\nMETEOR: multilinear <mbrewer@meteor.com>\nMETEOR: n1mmy <nim@meteor.com>\nMETEOR: sixolet <naomi@meteor.com>\nMETEOR: Slava <imslavko@gmail.com>\nMETEOR: Slava <slava@meteor.com>\nMETEOR: stubailo <s.stubailo@gmail.com>\nMETEOR: stubailo <sashko@meteor.com>\nMETEOR: stubailo <sashko@mit.edu>\nMETEOR: stubailo <sashko@stubailo.com>\nMETEOR: yyx990803 <yyx990803@gmail.com>\n"
  },
  {
    "path": ".reviewboardrc",
    "content": "REVIEWBOARD_URL = 'https://rbcommons.com/s/meteor/'\nREPOSITORY = 'Meteor framework'\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"0.10\"\ncache:\n  directories:\n    - \"dev_bundle\"\n    - \".meteor\"\n    - \".babel-cache\"\ninstall: ./meteor --get-ready\nscript: TEST_PACKAGES_EXCLUDE=\"less\" ./packages/test-in-console/run.sh\nsudo: false\n"
  },
  {
    "path": "Contributing.md",
    "content": "# Contributing to Meteor universal fork\n\nWe are happy to have your help for building and running the Meteor universal fork. Here's how you can help us with tests, bug reports and new code.\n\n<br/>\n### README and \"Good to know\" section\n\nPlease make sure that you carefully have read the [README](https://github.com/4commerce-technologies-AG/meteor) and especially had a look to its \"Good to know\" section.\n\n<br/>\n### Guide and tutorial issues\n\nSome of the already known issues may also help as a guide or tutorial. Please check out our [_guide flagged issues_](https://github.com/4commerce-technologies-AG/meteor/issues?q=+label%3Aflag%3Aguide+) if your question may already be answered.\n\n<br/>\n### Reporting a bug in Meteor universal fork\n\nWe welcome bug reports. If you've found a new bug in running Meteor universal fork please file a report in [our issue tracker](https://github.com/4commerce-technologies-AG/meteor/issues). Before you file your issue, please look twice to see if it has already been reported or solved. If so, comment, up-vote or +1 the existing, even closed, issue to show that it's affecting multiple people.\n\n\n<br/>\n<br/>\n# Contributing to official Meteor project\n\nPlease check contribution for Meteor at the official project and\n[read about their rules](https://github.com/meteor/meteor/blob/devel/Contributing.md)\n"
  },
  {
    "path": "History.md",
    "content": "## v.NEXT\n\n## v1.3.4.1\n\n* Increased the default HTTP timeout for requests made by the `meteor`\n  command-line tool to 60 seconds (previously 30), and [disabled the\n  timeout completely for Galaxy\n  deploys](https://forums.meteor.com/t/1-3-4-breaks-galaxy-deployment-etimedout/25383/).\n\n* Minor bug fixes: [#7281](https://github.com/meteor/meteor/pull/7281)\n  [#7276](https://github.com/meteor/meteor/pull/7276)\n\n## v1.3.4\n\n* The version of `npm` used by `meteor npm` and when installing\n  `Npm.depends` dependencies of Meteor packages has been upgraded from\n  2.15.1 to **3.9.6**, which should lead to much flatter node_modules\n  dependency trees.\n\n* The `meteor-babel` npm package has been upgraded to 0.11.6, and is now\n  installed using `npm@3.9.6`, fixing bugs arising from Windows path\n  limits, such as [#7247](https://github.com/meteor/meteor/issues/7247).\n\n* The `reify` npm package has been upgraded to 0.3.4, fixing\n  [#7250](https://github.com/meteor/meteor/issues/7250).\n\n* Thanks to caching improvements for the\n  `files.{stat,lstat,readdir,realpath}` methods and\n  `PackageSource#_findSources`, development server restart times are no\n  longer proportional to the number of files in `node_modules`\n  directories. [#7253](https://github.com/meteor/meteor/issues/7253)\n  [#7008](https://github.com/meteor/meteor/issues/7008)\n\n* When installed via `InstallMeteor.exe` on Windows, Meteor can now be\n  easily uninstalled through the \"Programs and Features\" control panel.\n\n* HTTP requests made by the `meteor` command-line tool now have a timeout\n  of 30 seconds, which can be adjusted by the `$TIMEOUT_SCALE_FACTOR`\n  environment variable. [#7143](https://github.com/meteor/meteor/pull/7143)\n\n* The `request` npm dependency of the `http` package has been upgraded\n  from 2.53.0 to 2.72.0.\n\n* The `--headless` option is now supported by `meteor test` and\n  `meteor test-packages`, in addition to `meteor self-test`.\n  [#7245](https://github.com/meteor/meteor/pull/7245)\n\n* Miscellaneous fixed bugs:\n  [#7255](https://github.com/meteor/meteor/pull/7255)\n  [#7239](https://github.com/meteor/meteor/pull/7239)\n\n## v1.3.3.1\n\n* Fixed bugs:\n  [#7226](https://github.com/meteor/meteor/pull/7226)\n  [#7181](https://github.com/meteor/meteor/pull/7181)\n  [#7221](https://github.com/meteor/meteor/pull/7221)\n  [#7215](https://github.com/meteor/meteor/pull/7215)\n  [#7217](https://github.com/meteor/meteor/pull/7217)\n\n* The `node-aes-gcm` npm package used by `oauth-encryption` has been\n  upgraded to 0.1.5. [#7217](https://github.com/meteor/meteor/issues/7217)\n\n* The `reify` module compiler has been upgraded to 0.3.3.\n\n* The `meteor-babel` package has been upgraded to 0.11.4.\n\n* The `pathwatcher` npm package has been upgraded to 6.7.0.\n\n* In CoffeeScript files with raw JavaScript enclosed by backticks, the\n  compiled JS will no longer contain `require` calls inserted by Babel.\n  [#7226](https://github.com/meteor/meteor/issues/7226)\n\n* Code related to the Velocity testing system has been removed.\n  [#7235](https://github.com/meteor/meteor/pull/7235)\n\n* Allow smtps:// in MAIL_URL [#7043](https://github.com/meteor/meteor/pull/7043)\n\n* Adds `Accounts.onLogout()` a hook directly analogous to `Accounts.onLogin()`. [PR #6889](https://github.com/meteor/meteor/pull/6889)\n\n## v1.3.3\n\n* Node has been upgraded from 0.10.43 to 0.10.45.\n\n* `npm` has been upgraded from 2.14.22 to 2.15.1.\n\n* The `fibers` package has been upgraded to 1.0.13.\n\n* The `meteor-babel` package has been upgraded to 0.10.9.\n\n* The `meteor-promise` package has been upgraded to 0.7.1, a breaking\n  change for code that uses `Promise.denodeify`, `Promise.nodeify`,\n  `Function.prototype.async`, or `Function.prototype.asyncApply`, since\n  those APIs have been removed.\n\n* Meteor packages with binary npm dependencies are now automatically\n  rebuilt using `npm rebuild` whenever the version of Node or V8 changes,\n  making it much simpler to use Meteor with different versions of Node.\n  5dc51d39ecc9e8e342884f3b4f8a489f734b4352\n\n* `*.min.js` files are no longer minified during the build process.\n  [PR #6986](https://github.com/meteor/meteor/pull/6986) [Issue #5363](https://github.com/meteor/meteor/issues/5363)\n\n* You can now pick where the `.meteor/local` directory is created by setting the `METEOR_LOCAL_DIR` environment variable. This lets you run multiple instances of the same Meteor app.\n  [PR #6760](https://github.com/meteor/meteor/pull/6760) [Issue #6532](https://github.com/meteor/meteor/issues/6532)\n\n* Allow using authType in Facebook login [PR #5694](https://github.com/meteor/meteor/pull/5694)\n\n* Adds flush() method to Tracker to force recomputation [PR #4710](https://github.com/meteor/meteor/pull/4710)\n\n* Adds `defineMutationMethods` option (default: true) to `new Mongo.Collection` to override default behavior that sets up mutation methods (/collection/[insert|update...]) [PR #5778](https://github.com/meteor/meteor/pull/5778)\n\n* Allow overridding the default warehouse url by specifying `METEOR_WAREHOUSE_URLBASE` [PR #7054](https://github.com/meteor/meteor/pull/7054)\n\n* Allow `_id` in `$setOnInsert` in Minimongo: https://github.com/meteor/meteor/pull/7066\n\n* Added support for `$eq` to Minimongo: https://github.com/meteor/meteor/pull/4235\n\n* Insert a `Date` header into emails by default: https://github.com/meteor/meteor/pull/6916/files\n\n* `meteor test` now supports setting the bind address using `--port IP:PORT` the same as `meteor run` [PR #6964](https://github.com/meteor/meteor/pull/6964) [Issue #6961](https://github.com/meteor/meteor/issues/6961)\n\n* `Meteor.apply` now takes a `noRetry` option to opt-out of automatically retrying non-idempotent methods on connection blips: [PR #6180](https://github.com/meteor/meteor/pull/6180)\n\n* DDP callbacks are now batched on the client side. This means that after a DDP message arrives, the local DDP client will batch changes for a minimum of 5ms (configurable via `bufferedWritesInterval`) and a maximum of 500ms (configurable via `bufferedWritesMaxAge`) before calling any callbacks (such as cursor observe callbacks).\n\n* PhantomJS is no longer included in the Meteor dev bundle (#6905). If you\n  previously relied on PhantomJS for local testing, the `spiderable`\n  package, Velocity tests, or testing Meteor from a checkout, you should\n  now install PhantomJS yourself, by running the following commmand:\n  `meteor npm install -g phantomjs-prebuilt`\n\n* The `babel-compiler` package now looks for `.babelrc` files and\n  `package.json` files with a \"babel\" section. If found, these files may\n  contribute additional Babel transforms that run before the usual\n  `babel-preset-meteor` set of transforms. In other words, if you don't\n  like the way `babel-preset-meteor` handles a particular kind of syntax,\n  you can add your preferred transform plugins to the \"presets\" or\n  \"plugins\" section of your `.babelrc` or `package.json` file. #6351\n\n* When `BabelCompiler` cannot resolve a Babel plugin or preset package in\n  `.babelrc` or `package.json`, it now merely warns instead of\n  crashing. #7179\n\n* Compiler plugins can now import npm packages that are visible to their\n  input files using `inputFile.require(id)`. b16e8d50194b37d3511889b316345f31d689b020\n\n* `import` statements in application modules now declare normal variables\n  for the symbols that are imported, making it significantly easier to\n  inspect imported variables when debugging in the browser console or in\n  `meteor shell`.\n\n* `import` statements in application modules are no longer restricted to\n  the top level, and may now appear inside conditional statements\n  (e.g. `if (Meteor.isServer) { import ... }`) or in nested scopes.\n\n* `import` statements now work as expected in `meteor shell`. #6271\n\n* Commands installed in `dev_bundle/lib/node_modules/.bin` (such as\n  `node-gyp` and `node-pre-gyp`) are now available to scripts run by\n  `meteor npm`. e95dfe410e1b43e8131bc2df9d2c29decdd1eaf6\n\n* When building an application using `meteor build`, \"devDependencies\"\n  listed in `package.json` are no longer copied into the bundle. #6750\n\n* Packages tested with `meteor test-packages` now have access to local\n  `node_modules` directories installed in the parent application or in the\n  package directory itself. #6827\n\n* You no longer need to specify `DEPLOY_HOSTNAME=galaxy.meteor.com` to run\n  `meteor deploy` (and similar commands) against Galaxy. The AWS us-east-1\n  Galaxy is now the default for `DEPLOY_HOSTNAME`. If your app's DNS points to\n  another Galaxy region, `meteor deploy` will detect that automatically as\n  well. #7055\n\n* The `coffeescript` plugin now passes raw JavaScript code enclosed by\n  back-ticks to `BabelCompiler`, enabling all ECMAScript features\n  (including `import` and `export`) within CoffeeScript. #6000 #6691\n\n* The `coffeescript` package now implies the same runtime environment as\n  `ecmascript` (`ecmascript-runtime`, `babel-runtime`, and `promise`, but\n  not `modules`). #7184\n\n* When Meteor packages install `npm` dependencies, the\n  `process.env.NPM_CONFIG_REGISTRY` environment variable is now\n  respected. #7162\n\n* `files.rename` now always executes synchronously. 9856d1d418a4d19c0adf22ec9a92f7ce81a23b05\n\n* \"Bare\" files contained by `client/compatibility/` directories or added\n  with `api.addFiles(path, ..., { bare: true })` are no longer compiled by\n  Babel. https://github.com/meteor/meteor/pull/7033#issuecomment-225126778\n\n* Miscellaneous fixed bugs: #6877 #6843 #6881\n\n## v1.3.2.4\n\n> Meteor 1.3.2.4 was published because publishing 1.3.2.3 failed in an\nunrecoverable way. Meteor 1.3.2.4 contains no additional changes beyond\nthe changes in 1.3.2.3.\n\n## v1.3.2.3\n\n* Reverted accidental changes included in 1.3.2.1 and 1.3.2.2 that\n  improved DDP performance by batching updates, but broke some packages\n  that relied on private methods of the DDP client Connection class. See\n  https://github.com/meteor/meteor/pull/5680 for more details. These\n  changes will be reinstated in 1.3.3.\n\n## v1.3.2.2\n\n* Fixed bugs #6819 and #6831.\n\n## v1.3.2.1\n\n* Fixed faulty comparison of `.sourcePath` and `.targetPath` properties of\n  files scanned by the `ImportScanner`, which caused problems for apps\n  using the `tap:i18n` package. 6e792a7cf25847b8cd5d5664a0ff45c9fffd9e57\n\n## v1.3.2\n\n* The `meteor/meteor` repository now includes a `Roadmap.md` file:\n  https://github.com/meteor/meteor/blob/devel/Roadmap.md\n\n* Running `npm install` in `bundle/programs/server` when deploying an app\n  also rebuilds any binary npm dependencies, fixing #6537. Set\n  METEOR_SKIP_NPM_REBUILD=1 to disable this behavior if necessary.\n\n* Non-.js(on) files in `node_modules` (such as `.less` and `.scss`) are\n  now processed by compiler plugins and may be imported by JS. #6037\n\n* The `jquery` package can now be completely removed from any app (#6563),\n  and uses `<app>/node_modules/jquery` if available (#6626).\n\n* Source maps are once again generated for all bundled JS files, even if\n  they are merely identity mappings, so that the files appear distinct in\n  the browser, and stack traces make more sense. #6639\n\n* All application files in `imports` directories are now considered lazy,\n  regardless of whether the app is using the `modules` package. This could\n  be a breaking change for 1.3.2 apps that do not use `modules` or\n  `ecmascript` but contain `imports` directories. Workaround: move files\n  out of `imports`, or rename `imports` to something else.\n\n* The `npm-bcrypt` package has been upgraded to use the latest version\n  (0.8.5) of the `bcrypt` npm package.\n\n* Compiler plugins can call `addJavaScript({ path })` multiple times with\n  different paths for the same source file, and `module.id` will reflect\n  this `path` instead of the source path, if they are different. #6806\n\n* Fixed bugs: https://github.com/meteor/meteor/milestones/Release%201.3.2\n\n* Fixed unintended change to `Match.Optional` which caused it to behave the same as the new `Match.Maybe` and incorrectly matching `null` where it previously would not have allowed it. #6735\n\n## v1.3.1\n\n* Long isopacket node_modules paths have been shortened, fixing upgrade\n  problems on Windows. #6609\n\n* Version 1.3.1 of Meteor can now publish packages for earlier versions of\n  Meteor, provided those packages do not rely on modules. #6484 #6618\n\n* The meteor-babel npm package used by babel-compiler has been upgraded to\n  version 0.8.4. c8d12aed4e725217efbe86fa35de5d5e56d73c83\n\n* The `meteor node` and `meteor npm` commands now return the same exit\n  codes as their child processes. #6673 #6675\n\n* Missing module warnings are no longer printed for Meteor packages, or\n  for `require` calls when `require` is not a free variable, fixing\n  https://github.com/practicalmeteor/meteor-mocha/issues/19.\n\n* Cordova iOS builds are no longer built by Meteor, but merely prepared\n  for building. 88d43a0f16a484a5716050cb7de8066b126c7b28\n\n* Compiler plugin errors were formerly silenced for files not explicitly\n  added in package.js. Now those errors are reported when/if the files are\n  imported by the ImportScanner. be986fd70926c9dd8eff6d8866205f236c8562c4\n\n## v1.3\n\n### ES2015/Modules\n\n* Enable ES2015 and CommonJS modules in Meteor apps and packages, on\n  both client and server. Also let you install modules in apps and\n  package by running `npm install`. See: https://github.com/meteor/meteor/blob/master/packages/modules/README.md\n\n* Enable ES2015 generators and ES2016 async/await in the `ecmascript`\n  package.\n\n* Inherit static getters and setters in subclasses, when using the\n  `ecmascript` package. #5624\n\n* Report full file paths on compiler errors when using the\n  `ecmascript` package. #5551\n\n* Now possible to `import` or `require` files with a `.json` file\n  extension. #5810\n\n* `process.env.NODE_ENV` is now defined on both client and server as\n  either `development` or `production`, which also determines the boolean\n  flags `Meteor.isDevelopment` and `Meteor.isProduction`.\n\n* Absolute identifiers for app modules no longer have the `/app/` prefix,\n  and absolute identifiers for Meteor packages now have the prefix\n  `/node_modules/meteor/` instead of just `/node_modules/`, meaning you\n  should `import {Blaze} from \"meteor/blaze\"` instead of `from \"blaze\"`.\n\n* Package variables imported by application code are once again exposed\n  globally, allowing them to be accessed from the browser console or from\n  `meteor shell`. #5868\n\n* Fixed global variable assignment analysis during linking. #5870 #5819\n\n* Changes to files in node_modules will now trigger a restart of the\n  development server, just like any other file changes. #5815\n\n* The meteor package now exports a `global` variable (a la Node) that\n  provides a reliable reference to the global object for all Meteor code.\n\n* Packages in local node_modules directories now take precedence over\n  Meteor packages of the same name. #5933\n\n* Upgraded `babel-compiler` to Babel 6, with the following set of plugins:\n  https://github.com/meteor/babel-preset-meteor/blob/master/index.js\n\n* Lazy CSS modules may now be imported by JS: 12c946ee651a93725f243f790c7919de3d445a19\n\n* Packages in the top-level node_modules directory of an app can now be\n  imported by Meteor packages: c631d3ac35f5ca418b93c454f521989855b8ec72\n\n* Added support for wildcard import and export statements. #5872 #5897\n\n* Client-side stubs for built-in Node modules are now provided\n  automatically if the `meteor-node-stubs` npm package is installed. #6056\n\n* Imported file extensions are now optional for file types handled by\n  compiler plugins. #6151\n\n* Upgraded Babel packages to ~6.5.0: 292824da3f8449afd1cd39fcd71acd415c809c0f\n  Note: .babelrc files are now ignored (#6016), but may be reenabled (#6351).\n\n* Polyfills now provided for `process.nextTick` and `process.platform`. #6167 #6198 #6055 efe53de492da6df785f1cbef2799d1d2b492a939\n\n* The `meteor test-app` command is now `meteor test [--full-app]`:\n  ab5ab15768136d55c76d51072e746d80b45ec181\n\n* New apps now include a `package.json` file.\n  c51b8cf7ffd8e7c9ca93768a2df93e4b552c199c\n\n* `require.resolve` is now supported.\n  https://github.com/benjamn/install/commit/ff6b25d6b5511d8a92930da41db73b93eb1d6cf8\n\n* JSX now enabled in `.js` files processed by the `ecmascript` compiler\n  plugin. #6151\n\n* On the server, modules contained within `node_modules` directories are\n  now loaded using the native Node `require` function. #6398\n\n* All `<script>` tag(s) for application and package code now appear at the\n  end of the `<body>` rather than in the `<head>`. #6375\n\n* The client-side version of `process.env.NODE_ENV` (and other environment\n  variables) now matches the corresponding server-side values. #6399\n\n### Performance\n\n* Don't reload package catalog from disk on rebuilds unless package\n  dependencies changed. #5747\n\n* Improve minimongo performance on updating documents when there are\n  many active observes. #5627\n\n### Platform\n\n* Upgrade to Node v0.10.41.\n\n* Allow all types of URLs that npm supports in `Npm.depends`\n  declarations.\n\n* Split up `standard-minifiers` in separate CSS\n  (`standard-minifiers-css`) and JS minifiers\n  (`standard-minifiers-js`). `standard-minifiers` now acts as an\n  umbrella package for these 2 minifiers.\n\n* Allow piping commands to `meteor shell` via STDIN. #5575\n\n* Let users set the CAFILE environment variable to override the SSL\n  root certificate list. #4757 #5523\n\n* `force-ssl` is now marked production only.\n\n### Cordova\n\n* Cordova dependencies have been upgraded to the latest versions\n  (`cordova-lib` 6.0.0, `cordova-ios` 4.0.1, and `cordova-android` 5.1.0).\n\n* iOS apps now require iOS 8 or higher, and building for iOS requires Xcode 7.2\n  to be installed.\n\n* Building for Android now requires Android SDK 23 to be installed. You may also\n  need to create a new AVD for the emulator.\n\n* Building Cordova Android apps on Windows is now supported. #4155\n\n* The Crosswalk plugin has been updated to 1.4.0.\n\n* Cordova core plugins are now pinned to minimal versions known to be compatible\n  with the included platforms. A warning is printed asking people to upgrade\n  their dependencies if they specify an older version, but we'll always use\n  the pinned version regardless.\n\n* The plugin used for file serving and hot code push has been completely\n  rewritten. Among many other improvements, it downloads updates incrementally,\n  can recover from downloading faulty JavaScript code, and is much more\n  reliable and performant.\n  See [`cordova-plugin-meteor-webapp`](https://github.com/meteor/cordova-plugin-meteor-webapp)\n  for more a more detailed description of the new design.\n\n* If the callbacks added with `Meteor.startup()` do not complete within a set\n  time, we consider a downloaded version faulty and will fallback to the last\n  known good version. The default timeout is 20 seconds, but this can be\n  configured by setting `App.setPreference(\"WebAppStartupTimeout\", \"10000\");`\n  (in milliseconds) in `mobile-config.js`.\n\n* We now use `WKWebView` on iOS by default, even on iOS 8 (which works because\n  we do not use `file://` URLs).\n\n* We now use `localhost` instead of `meteor.local` to serve files from. Since\n  `localhost` is considered a secure origin, this means the web view won't\n  disable web platform features that it otherwise would.\n\n* The local server port now lies between 12000-13000 and is chosen based on\n  the `appId`, to both be consistent and lessen the chance of collisions between\n  multiple Meteor Cordova apps installed on the same device.\n\n* The plugin now allows for local file access on both iOS and Android, using a\n  special URL prefix (`http://localhost:<port>/local-filesystem/<path>`).\n\n* App icon and launch image sizes have been updated. Low resolution sizes for\n  now unsupported devices have been deprecated, and higher resolution versions\n  have been added.\n\n* We now support the modern Cordova whitelist mechanism. `App.accessRule` has\n  been updated with new options.\n\n* `meteor build` now supports a `--server-only` option to avoid building\n  the mobile apps when `ios` or `android` platforms have been added. It still\n  builds the `web.cordova` architecture in the server bundle however, so it can\n  be served for hot code pushes.\n\n* `meteor run` now always tries to use an autodetected IP address as the\n  mobile `ROOT_URL`, even if we're not running on a device. This avoids a situation\n  where an app already installed on a device connects to a restarted development\n  server and receives a `localhost` `ROOT_URL`. #5973\n\n* Fixed a discrepancy between the way we calculated client hashes during a mobile\n  build and on the server, which meant a Cordova app would always download a\n  new version the first time it started up.\n\n* In Cordova apps, `Meteor.startup()` now correctly waits for the\n  device to be ready before firing the callback.\n\n### Accounts\n\n* Make `Accounts.forgotPassword` treat emails as case insensitive, as\n  the rest of the accounts system does.\n\n### Blaze\n\n* Don't throw in certain cases when calling a template helper with an\n  empty data context. #5411 #5736\n\n* Improve automatic blocking of URLs in attribute values to also\n  include `vbscript:` URLs.\n\n### Check\n\n* Introduced new matcher `Match.Maybe(type)` which will also match (permit) `null` in addition to `undefined`.  This is a suggested replacement (where appropriate) for `Match.Optional` which did not permit `null`.  This prevents the need to use `Match.OneOf(null, undefined, type)`. #6220\n\n### Testing\n\n* Packages can now be marked as `testOnly` to only run as part of app\n  testing with `meteor test`. This is achieved by setting\n  `testOnly: true` to `Package.describe`.\n\n\n### Uncategorized\n\n* Remove warning in the `simple-todos-react` example app. #5716\n\n* Fix interaction between `browser-policy` and `oauth` packages. #5628\n\n* Add README.md to the `tinytest` package. #5750\n\n* Don't crash when calling `ReactiveDict.prototype.clear` if a\n  property with a value wasn't previously accessed. #5530 #5602\n\n* Move `DDPRateLimiter` to the server only, since it won't work if it\n  is called from the client. It will now error if referenced from the\n  client at all.\n\n* Don't call function more than once when passing a `Match.Where`\n  argument to `check`. #5630 #5651\n\n* Fix empty object argument check in `this.subscribe` in\n  templates. #5620\n\n* Make `HTTP.call` not crash on undefined content. #5565 #5601\n\n* Return observe handle from\n  `Mongo.Collection.prototype._publishCursor`. #4983 #5615\n\n* Add 'Did you mean?' reminders for some CLI commands to help Rails\n  developers. #5593\n\n* Make internal shell scripts compatible with other Unix-like\n  systems. #5585\n\n* Add a `_pollingInterval` option to `coll.find()` that can be used in\n  conjunction with `_disableOplog: true`. #5586\n\n* Expose Tinytest internals which can be used to extend it. #3541\n\n* Improve error message from `check` when passing in null. #5545\n\n* Split up `standard-minifiers` in separate CSS (`standard-minifier-css`) and JS\n  minifiers(`standard-minifier-js`). `standard-minifiers` now acts as an umbrella package for these\n  2 minifiers.\n\n* Detect new Facebook user-agent in the `spiderable` package. #5516\n\n* `Match.ObjectIncluding` now really requires plain objects. #6140\n\n* Allow `git+` URL schemes for npm dependencies. #844\n\n* Expose options `disableOplog`, `pollingIntervalMs`, and\n  `pollingThrottleMs` to `Cursor.find` for tuning observe parameters\n  on the server.\n\n* Expose `dynamicHead` and `dynamicBody` hooks in boilerplate generation allowing code to inject content into the body and head tags from the server. #3860\n\n* Add methods of the form `BrowserPolicy.content.allow<ContentType>BlobUrl()` to BrowserPolicy #5141\n\n* Move `<script>` tags to end of `<body>` to enable 'loading' UI to be inserted into the boilerplate #6375\n\n* Adds WebAppInternals.setBundledJsCssUrlRewriteHook allowing apps to supply a hook function that can create a dynamic bundledJsCssPrefix at runtime. This is useful if you're using a CDN by giving you a way to ensure the CDN won't cache broken js/css resources during an app upgrade.\n\nPatches contributed by GitHub users vereed, mitar, nathan-muir,\nrobfallows, skishore, okland, Primigenus, zimme, welelay, rgoomar,\nbySabi, mbrookes, TomFreudenberg, TechPlexEngineer, zacharydenton,\nAlexeyMK, gwendall, dandv, devgrok, brianlukoff.\n\n\n## v.1.2.1, 2015-Oct-26\n\n* `coll.insert()` now uses a faster (but cryptographically insecure)\n  algorithm to generate document IDs when called outside of a method\n  and an `_id` field is not explicitly passed. With this change, there\n  are no longer two algorithms used to generate document\n  IDs. `Random.id()` can still be used to generate cryptographically\n  secure document IDs. [#5161](https://github.com/meteor/meteor/issues/5161)\n\n* The `ecmascript-collections` package has been renamed to\n  `ecmascript-runtime` and now includes a more complete selection of\n  ES2015 polyfills and shims from [`core-js`](https://www.npmjs.com/package/core-js).\n  The complete list can be found\n  [here](https://github.com/meteor/ecmascript-runtime/blob/master/server.js).\n\n* Check type of `onException` argument to `bindEnvironment`. [#5271](https://github.com/meteor/meteor/issues/5271)\n\n* WebApp's `PORT` environment variable can now be a named pipe to better support\n  deployment on IIS on Windows. [4413](https://github.com/meteor/meteor/issues/4413)\n\n* `Template.dynamic` can be now used as a block helper:\n  `{{#Template.dynamic}} ... {{/Template.dynamic}}` [#4756](https://github.com/meteor/meteor/issues/4756)\n\n* `Collection#allow/deny` now throw errors when passed falsy values. [#5442](https://github.com/meteor/meteor/pull/5442)\n\n* `source-map` has been updated to a newer patch version, which fixes major bugs\n  in particular around loading bundles generated by Webpack. [#5411](https://github.com/meteor/meteor/pull/5411)\n\n* `check` now returns instead of throwing errors internally, which should make\n  it much faster. `check` is used in many core Meteor packages, so this should\n  result in small performance improvements across the framework. [#4584](https://github.com/meteor/meteor/pull/4584)\n\n* The `userEmail` option to `Meteor.loginWithMeteorDeveloperAccount` has been\n  renamed to `loginHint`, and now supports Google accounts as well. The old\n  option still works for backwards compatibility. [#2422](https://github.com/meteor/meteor/issues/2422) [#5313](https://github.com/meteor/meteor/pull/5313)\n\n* The old `addFiles` API for adding package assets no longer throws an error,\n  making it easier to share packages between pre- and post-1.2 versions of\n  Meteor. [#5458](https://github.com/meteor/meteor/issues/5458)\n\n* Normally, you can't deploy to free meteor.com hosting or Galaxy from a\n  non-Linux machine if you have *local* non-published packages with binary\n  dependencies, nor can you run `meteor build --architecture SomeOtherArch`. As\n  a temporary workaround, if you set the `METEOR_BINARY_DEP_WORKAROUND`\n  variable, you will be able to deploy to Galaxy (but not free meteor.com\n  hosting), and tarballs built with `meteor build` will contain a\n  `programs/server/setup.sh` shell script which should be run on the server to\n  install those packages.\n\n## v1.2.0.2, 2015-Sept-28\n\n* Update Crosswalk plugin for Cordova to 1.3.1. [#5267](https://github.com/meteor/meteor/issues/5267)\n\n* Fix `meteor add` for a Cordova plugin using a Git URL with SHA.\n\n* Upgraded the `promise` package to use `meteor-promise@0.5.0`, which uses\n  the global `Promise` constructor in browsers that define it natively.\n\n* Fix error in assigning attributes to `<body>` tag when using Blaze templates\n  or `static-html`. [#5232](https://github.com/meteor/meteor/issues/5232)\n\n## v1.2.0.1, 2015-Sept-22\n\n* Fix incorrect publishing of packages with exports but no source. [#5228](https://github.com/meteor/meteor/issues/5228)\n\n## v1.2, 2015-Sept-21\n\nThere are quite a lot of changes in Meteor 1.2. See the\n[Wiki](https://github.com/meteor/meteor/wiki/Breaking-changes-in-Meteor-1.2) for\na shorter list of breaking changes you should be aware of when upgrading.\n\n### Core Packages\n\n* `meteor-platform` has been deprecated in favor of the smaller `meteor-base`,\n  with apps listing their other dependencies explicitly.  The v1.2 upgrader\n  will rewrite `meteor-platform` in existing apps.  `meteor-base` puts fewer\n  symbols in the global namepsace, so it's no longer true that all apps\n  have symbols like `Random` and `EJSON` in the global namespace.\n\n* New packages: `ecmascript`, `es5-shim`, `ecmascript-collections`, `promise`,\n  `static-html`, `jshint`, `babel-compiler`\n\n* No longer include the `json` package by default, which contains code for\n  `JSON.parse` and `JSON.stringify`.  (The last browser to not support JSON\n  natively was Internet Explorer 7.)\n\n* `autoupdate` has been renamed `hot-code-push`\n\n### Meteor Accounts\n\n* Login attempts are now rate-limited by default.  This can be turned off\n  using `Accounts.removeDefaultRateLimit()`.\n\n* `loginWithPassword` now matches username or email in a case insensitive\n  manner. If there are multiple users with a username or email only differing\n  in case, a case sensitive match is required. [#550](https://github.com/meteor/meteor/issues/550)\n\n* `loginWithGithub` now requests `user:email` scope by default, and attempts\n  to fetch the user's emails. If no public email has been set, we use the\n  primary email instead. We also store the complete list of emails. [#4545](https://github.com/meteor/meteor/issues/4545)\n\n* When an account's email address is verified, deactivate other verification\n  tokens.  [#4626](https://github.com/meteor/meteor/issues/4626)\n\n* Fix bug where blank page is shown when an expired login token is\n  present. [#4825](https://github.com/meteor/meteor/issues/4825)\n\n* Fix `OAuth1Binding.prototype.call` when making requests to Twitter\n  with a large parameter set.\n\n* Directions for setting up Google OAuth in accounts-ui have been updated to\n  match Google's new requirements.\n\n* Add `Accounts.oauth.unregisterService` method, and ensure that users can only\n  log in with currently registered services.  [#4014](https://github.com/meteor/meteor/issues/4014)\n\n* The `accounts-base` now defines reusable `AccountsClient` and\n  `AccountsServer` constructors, so that users can create multiple\n  independent instances of the `Accounts` namespace.  [#4233](https://github.com/meteor/meteor/issues/4233)\n\n* Create an index for `Meteor.users` on\n  `services.email.verificationTokens.token` (instead of\n  `emails.validationTokens.token`, which never was used for anything).  [#4482](https://github.com/meteor/meteor/issues/4482)\n\n* Remove an IE7-specific workaround from accounts-ui.  [#4485](https://github.com/meteor/meteor/issues/4485)\n\n### Livequery\n\n* Improved server performance by reducing overhead of processing oplog after\n  database writes. Improvements are most noticeable in case when a method is\n  doing a lot of writes on collections with plenty of active observers.  [#4694](https://github.com/meteor/meteor/issues/4694)\n\n### Mobile\n\n* The included Cordova tools have been updated to the latest version 5.2.0.\n  This includes Cordova Android 4.1 and Cordova iOS 3.9. These updates may\n  require you to make changes to your app. For details, see the [Cordova release\n  notes] (https://cordova.apache.org/#news) for for the different versions.\n\n* Thanks to Cordova Android's support for pluggable web views, it is now\n  possible to install the [Crosswalk plugin]\n  (https://crosswalk-project.org/documentation/cordova/cordova_4.html), which\n  offers a hugely improved web view on older Android versions.\n  You can add the plugin to your app with `meteor add crosswalk`.\n\n* The bundled Android tools have been removed and a system-wide install of the\n  Android SDK is now required. This should make it easier to keep the\n  development toolchain up to date and helps avoid some difficult to diagnose\n  failures. If you don't have your own Android tools installed already, you can\n  find more information about installing the Android SDK for [Mac] (https://github.com/meteor/meteor/wiki/Mobile-Dev-Install:-Android-on-Mac)\n  or [Linux]\n  (https://github.com/meteor/meteor/wiki/Mobile-Dev-Install:-Android-on-Linux).\n\n* As part of moving to npm, many Cordova plugins have been renamed. Meteor\n  should perform conversions automatically, but you may want to be aware of this\n  to avoid surprises. See [here]\n  (https://cordova.apache.org/announcements/2015/04/21/plugins-release-and-move-to-npm.html)\n  for more information.\n\n* Installing plugins from the local filesystem is now supported using `file://`\n  URLs, which should make developing your own plugins more convenient. It is\n  also needed as a temporary workaround for using the Facebook plugin.\n  Relative references are interpreted relative to the Meteor project directory.\n  (As an example,\n  `meteor add cordova:phonegap-facebook-plugin@file://../phonegap-facebook-plugin`\n  would attempt to install the plugin from the same directory you Meteor project\n  directory is located in.)\n\n* Meteor no longer supports installing Cordova plugins from tarball URLs, but\n  does support Git URLs with a SHA reference (like\n  `https://github.com/apache/cordova-plugin-file#c452f1a67f41cb1165c92555f0e721fbb07329cc`).\n  Existing GitHub tarball URLs are converted automatically.\n\n* Allow specifying a `buildNumber` in `App.info`, which is used to set the\n  `android-versionCode` and `ios-CFBundleVersion` in the `config.xml` of the\n  Cordova project. The build number is used to differentiate between\n  different versions of the app, and should be incremented before distributing\n  a built app to stores or testing services. [#4048](https://github.com/meteor/meteor/issues/4048)\n\n* Other changes include performance enhancements when building and running,\n  and improved requirements checking and error reporting.\n\n* Known issue: we do not currently show logging output when running on the\n  iOS Simulator. As a workaround, you can `meteor run ios-device` to open the\n  project in Xcode and watch the output there.\n\n### Templates/Blaze\n\n* New syntax: Handlebars sub-expressions are now supported -- as in,\n  `{{helper (anotherHelper arg1 arg2)}}` -- as well as new block helper forms\n  `#each .. in ..` and `#let x=y`.  See\n  https://github.com/meteor/meteor/tree/devel/packages/spacebars\n\n* Add a special case for the new `react-template-helper` package -- don't let\n  templates use {{> React}} with siblings since `React.render` assumes it's\n  being rendered into an empty container element. (This lets us throw the error\n  when compiling templates rather than when the app runs.)\n\n* Improve parsing of `<script>` and `<style>` tags.  [#3797](https://github.com/meteor/meteor/issues/3797)\n\n* Fix a bug in `observe-sequence`. The bug was causing unnecessary rerenderings\n  in an instance of `#each` block helper followed by false \"duplicate ids\"\n  warnings. [#4049](https://github.com/meteor/meteor/issues/4049)\n\n* `TemplateInstance#subscribe` now has a new `connection` option, which\n  specifies which connection should be used when making the subscription. The\n  default is `Meteor.connection`, which is the connection used when calling\n  `Meteor.subscribe`.\n\n* Fix external `<script>` tags in body or templates.  [#4415](https://github.com/meteor/meteor/issues/4415)\n\n* Fix memory leak.  [#4289](https://github.com/meteor/meteor/issues/4289)\n\n* Avoid recursion when materializing DOM elements, to avoid stack overflow\n  errors in certain browsers. [#3028](https://github.com/meteor/meteor/issues/3028)\n\n* Blaze and Meteor's built-in templating are now removable using\n  `meteor remove blaze-html-templates`. You can add back support for static\n  `head` and `body` tags in `.html` files by using the `static-html` package.\n\n### DDP\n\n* Websockets now support the\n  [`permessage-deflate`](https://tools.ietf.org/id/draft-ietf-hybi-permessage-compression-19.txt)\n  extension, which compresses data on the wire. It is enabled by default on the\n  server. To disable it, set `$SERVER_WEBSOCKET_COMPRESSION` to `0`. To configure\n  compression options, set `$SERVER_WEBSOCKET_COMPRESSION` to a JSON object that\n  will be used as an argument to\n  [`deflate.configure`](https://github.com/faye/permessage-deflate-node/blob/master/README.md).\n  Compression is supported on the client side by Meteor's Node DDP client and by\n  browsers including Chrome, Safari, and Firefox 37.\n\n* The `ddp` package has been split into `ddp-client` and `ddp-server` packages;\n  using `ddp` is equivalent to using both. This allows you to use the Node DDP\n  client without adding the DDP server to your app.  [#4191](https://github.com/meteor/meteor/issues/4191) [#3452](https://github.com/meteor/meteor/issues/3452)\n\n* On the client, `Meteor.call` now takes a `throwStubExceptions` option; if set,\n  exceptions thrown by method stubs will be thrown instead of logged, and the\n  method will not be invoked on the server.  [#4202](https://github.com/meteor/meteor/issues/4202)\n\n* `sub.ready()` should return true inside that subscription's `onReady`\n  callback.  [#4614](https://github.com/meteor/meteor/issues/4614)\n\n* Fix method calls causing broken state when socket is reconnecting.  [#5104](https://github.com/meteor/meteor/issues/5104)\n\n### Isobuild\n\n* Build plugins will no longer process files whose names match the extension\n  exactly (with no extra dot). If your build plugin needs to match filenames\n  exactly, you should use the new build plugin API in this release which\n  supplies a special `filenames` option. [#3985](https://github.com/meteor/meteor/issues/3985)\n\n* Adding the same file twice in the same package is now an error. Previously,\n  this could either lead to the file being included multiple times, or to a\n  build time crash.\n\n* You may now specify the `bare` option for JavaScript files on the server.\n  Previous versions only allowed this on the client. [#3681](https://github.com/meteor/meteor/issues/3681)\n\n* Ignore `node_modules` directories in apps instead of processing them as Meteor\n  source code.  [#4457](https://github.com/meteor/meteor/issues/4457) [#4452](https://github.com/meteor/meteor/issues/4452)\n\n* Backwards-incompatible change for package authors: Static assets in package.js files must now be\n  explicitly declared by using `addAssets` instead of `addFiles`. Previously,\n  any file that didn't have a source handler was automatically registered as a\n  server-side asset. The `isAsset` option to `addFiles` is also deprecated in\n  favor of `addAssets`.\n\n* Built files are now always annotated with line number comments, to improve the\n  debugging experience in browsers that don't support source maps.\n\n* There is a completely new API for defining build plugins that cache their\n  output. There are now special APIs for defining linters and minifiers in\n  addition to compilers. The core Meteor packages for `less`, `coffee`, `stylus`\n  and `html` files have been updated to use this new API. Read more on the\n  [Wiki page](https://github.com/meteor/meteor/wiki/Build-Plugins-API).\n\n### CSS\n\n* LESS and Stylus now support cross-package imports.\n\n* CSS concatenation and minification is delegated to the `standard-minifiers`\n  package, which is present by default (and added to existing apps by the v1.2\n  upgrader).\n\n* CSS output is now split into multiple stylesheets to avoid hitting limits on\n  rules per stylesheet in certain versions of Internet Explorer. [#1876](https://github.com/meteor/meteor/issues/1876)\n\n### Mongo\n\n* The oplog observe driver now properly updates queries when you drop a\n  database.  [#3847](https://github.com/meteor/meteor/issues/3847)\n\n* MongoID logic has been moved out of `minimongo` into a new package called\n  `mongo-id`.\n\n* Fix Mongo upserts with dotted keys in selector.  [#4522](https://github.com/meteor/meteor/issues/4522)\n\n\n### `meteor` command-line tool\n\n* You can now create three new example apps with the command line tool. These\n  are the apps from the official tutorials at http://meteor.com/tutorials, which\n  demonstrate building the same app with Blaze, Angular, and React. Try these\n  apps with:\n\n  ```sh\n  meteor create --example simple-todos\n  meteor create --example simple-todos-react\n  meteor create --example simple-todos-angular\n  ```\n\n* `meteor shell` no longer crashes when piped from another command.\n\n* Avoid a race condition in `meteor --test` and work with newer versions of the\n  Velocity package.  [#3957](https://github.com/meteor/meteor/issues/3957)\n\n* Improve error handling when publishing packages.  [#3977](https://github.com/meteor/meteor/issues/3977)\n\n* Improve messaging around publishing binary packages.  [#3961](https://github.com/meteor/meteor/issues/3961)\n\n* Preserve the value of `_` in `meteor shell`.  [#4010](https://github.com/meteor/meteor/issues/4010)\n\n* `meteor mongo` now works on OS X when certain non-ASCII characters are in the\n  pathname, as long as the `pgrep` utility is installed (it ships standard with\n  OS X 10.8 and newer).  [#3999](https://github.com/meteor/meteor/issues/3999)\n\n* `meteor run` no longer ignores (and often reverts) external changes to\n  `.meteor/versions` which occur while the process is running.  [#3582](https://github.com/meteor/meteor/issues/3582)\n\n* Fix crash when downloading two builds of the same package version\n  simultaneously.  [#4163](https://github.com/meteor/meteor/issues/4163)\n\n* Improve messages printed by `meteor update`, displaying list of packages\n  that are not at the latest version available.\n\n* When determining file load order, split file paths on path separator\n  before comparing path components alphabetically.  [#4300](https://github.com/meteor/meteor/issues/4300)\n\n* Fix inability to run `mongod` due to lack of locale configuration on some\n  platforms, and improve error message if the failure still occurs.  [#4019](https://github.com/meteor/meteor/issues/4019)\n\n* New `meteor lint` command.\n\n### Minimongo\n\n* The `$push` query modifier now supports a `$position` argument.  [#4312](https://github.com/meteor/meteor/issues/4312)\n\n* `c.update(selector, replacementDoc)` no longer shares mutable state between\n  replacementDoc and Minimongo internals. [#4377](https://github.com/meteor/meteor/issues/4377)\n\n### Email\n\n* `Email.send` now has a new option, `attachments`, in the same style as\n  `mailcomposer`.\n  [Details here.](https://github.com/andris9/mailcomposer#add-attachments)\n\n### Tracker\n\n* New `Tracker.Computation#onStop` method.  [#3915](https://github.com/meteor/meteor/issues/3915)\n\n* `ReactiveDict` has two new methods, `clear` and `all`. `clear` resets\n  the dictionary as if no items had been added, meaning all calls to `get` will\n  return `undefined`. `all` converts the dictionary into a regular JavaScript\n  object with a snapshot of the keys and values. Inside an autorun, `all`\n  registers a dependency on any changes to the dictionary. [#3135](https://github.com/meteor/meteor/issues/3135)\n\n### Utilities\n\n* New `beforeSend` option to `HTTP.call` on the client allows you to directly\n  access the `XMLHttpRequest` object and abort the call.  [#4419](https://github.com/meteor/meteor/issues/4419) [#3243](https://github.com/meteor/meteor/issues/3243) [#3266](https://github.com/meteor/meteor/issues/3266)\n\n* Parse `application/javascript` and `application/x-javascript` HTTP replies as\n  JSON too.  [#4595](https://github.com/meteor/meteor/issues/4595)\n\n* `Match.test` from the `check` package now properly compares boolean literals,\n  just like it does with Numbers and Strings. This applies to the `check`\n  function as well.\n\n* Provide direct access to the `mailcomposer` npm module used by the `email`\n  package on `EmailInternals.NpmModules`. Allow specifying a `MailComposer`\n  object to `Email.send` instead of individual options.  [#4209](https://github.com/meteor/meteor/issues/4209)\n\n* Expose `Spiderable.requestTimeoutMs` from `spiderable` package to\n  allow apps to set the timeout for running phantomjs.\n\n* The `spiderable` package now reports the URL it's trying to fetch on failure.\n\n\n### Other bug fixes and improvements\n\n* Upgraded dependencies:\n\n  - Node: 0.10.40 (from 0.10.36)\n  - uglify-js: 2.4.20 (from 2.4.17)\n  - http-proxy: 1.11.1 (from 1.6.0)\n\n* `Meteor.loginWithGoogle` now supports `prompt`. Choose a prompt to always be\n  displayed on Google login.\n\n* Upgraded `coffeescript` package to depend on NPM packages\n  coffeescript@1.9.2 and source-map@0.4.2. [#4302](https://github.com/meteor/meteor/issues/4302)\n\n* Upgraded `fastclick` to 1.0.6 to fix an issue in iOS Safari. [#4393](https://github.com/meteor/meteor/issues/4393)\n\n* Fix `Error: Can't render headers after they are sent to the client`.  [#4253](https://github.com/meteor/meteor/issues/4253) [#4750](https://github.com/meteor/meteor/issues/4750)\n\n* `Meteor.settings.public` is always available on client and server,\n  and modifications made on the server (for example, during app initialization)\n  affect the value seen by connecting clients. [#4704](https://github.com/meteor/meteor/issues/4704)\n\n### Windows\n\n* Increase the buffer size for `netstat` when looking for running Mongo servers. [#4125](https://github.com/meteor/meteor/issues/4125)\n\n* The Windows installer now always fetches the latest available version of\n  Meteor at runtime, so that it doesn't need to be recompiled for every release.\n\n* Fix crash in `meteor mongo` on Windows.  [#4711](https://github.com/meteor/meteor/issues/4711)\n\n\n## v1.1.0.3, 2015-Aug-03\n\n### Accounts\n\n* When using Facebook API version 2.4, properly fetch `email` and other fields.\n  Facebook recently forced all new apps to use version 2.4 of their API.  [#4743](https://github.com/meteor/meteor/issues/4743)\n\n\n## v1.1.0.2, 2015-Apr-06\n\n### `meteor` command-line tool\n\n* Revert a change in 1.1.0.1 that caused `meteor mongo` to fail on some Linux\n  systems. [#4115](https://github.com/meteor/meteor/issues/4115), [#4124](https://github.com/meteor/meteor/issues/4124), [#4134](https://github.com/meteor/meteor/issues/4134)\n\n\n## v1.1.0.1, 2015-Apr-02\n\n### Blaze\n\n* Fix a regression in 1.1 in Blaze Templates: an error happening when View is\n  invalidated immediately, causing a client-side crash (accessing\n  `destroyMembers` of `undefined`). [#4097](https://github.com/meteor/meteor/issues/4097)\n\n## v1.1, 2015-Mar-31\n\n### Windows Support\n\n* The Meteor command line tool now officially supports Windows 7, Windows 8.1,\n  Windows Server 2008, and Windows Server 2012. It can run from PowerShell or\n  Command Prompt.\n\n* There is a native Windows installer that will be available for download from\n  <https://www.meteor.com/install> starting with this release.\n\n* In this release, Meteor on Windows supports all features available on Linux\n  and Mac except building mobile apps with PhoneGap/Cordova.\n\n* The `meteor admin get-machine` command now supports an additional\n  architecture, `os.windows.x86_32`, which can be used to build binary packages\n  for Windows.\n\n### Version Solver\n\n* The code that selects compatible package versions for `meteor update`\n  and resolves conflicts on `meteor add` has been rewritten from the ground up.\n  The core solver algorithm is now based on MiniSat, an open-source SAT solver,\n  improving performance and maintainability.\n\n* Refresh the catalog instead of downgrading packages when the versions in\n  `.meteor/versions` aren't in the cache.  [#3653](https://github.com/meteor/meteor/issues/3653)\n\n* Don't downgrade packages listed in `.meteor/packages`, or upgrade to a new\n  major version, unless the new flag `--allow-incompatible-update` is passed\n  as an override.\n\n* Error messages are more detailed when constraints are unsatisfiable.\n\n* Prefer \"patched\" versions of new indirect dependencies, and take patches\n  to them on `meteor update` (for example, `1.0.1` or `1.0.0_1` over `1.0.0`).\n\n* Version Solver is instrumented for profiling (`METEOR_PROFILE=1` in the\n  environment).\n\n* Setting the `METEOR_PRINT_CONSTRAINT_SOLVER_INPUT` environment variable\n  prints information useful for diagnosing constraint solver bugs.\n\n### Tracker\n\n* Schedule the flush cycle using a better technique than `setTimeout` when\n  available.  [#3889](https://github.com/meteor/meteor/issues/3889)\n\n* Yield to the event loop during the flush cycle, unless we're executing a\n  synchronous `Tracker.flush()`.  [#3901](https://github.com/meteor/meteor/issues/3901)\n\n* Fix error reporting not being source-mapped properly. [#3655](https://github.com/meteor/meteor/issues/3655)\n\n* Introduce a new option for `Tracker.autorun` - `onError`. This callback can be\n  used to handle errors caught in the reactive computations. [#3822](https://github.com/meteor/meteor/issues/3822)\n\n### Blaze\n\n* Fix stack overflow from nested templates and helpers by avoiding recursion\n  during rendering.  [#3028](https://github.com/meteor/meteor/issues/3028)\n\n### `meteor` command-line tool\n\n* Don't fail if `npm` prints more than 200K.  [#3887](https://github.com/meteor/meteor/issues/3887)\n\n\n### Other bug fixes and improvements\n\n* Upgraded dependencies:\n\n  - uglify-js: 2.4.17 (from 2.4.13)\n\nPatches contributed by GitHub users hwillson, mitar, murillo128, Primigenus,\nrjakobsson, and tmeasday.\n\n\n## v1.0.5, 2015-Mar-25\n\n* This version of Meteor now uses version 2.2 of the Facebook API for\n  authentication, instead of 1.0. If you use additional Facebook API methods\n  beyond login, you may need to request new permissions.\n\n  Facebook will automatically switch all apps to API version 2.0 on April\n  30th, 2015. Please make sure to update your application's permissions and API\n  calls by that date.\n\n  For more details, see\n  https://github.com/meteor/meteor/wiki/Facebook-Graph-API-Upgrade\n\n\n## v1.0.4.2, 2015-Mar-20\n\n* Fix regression in 1.0.4 where using Cordova for the first time in a project\n  with hyphens in its directory name would fail.  [#3950](https://github.com/meteor/meteor/issues/3950)\n\n\n## v1.0.4.1, 2015-Mar-18\n\n* Fix regression in 1.0.4 where `meteor publish-for-arch` only worked for\n  packages without colons in their name.  [#3951](https://github.com/meteor/meteor/issues/3951)\n\n## v1.0.4, 2015-Mar-17\n\n### Mongo Driver\n\n* Meteor is now tested against MongoDB 2.6 by default (and the bundled version\n  used by `meteor run` has been upgraded). It should still work fine with\n  MongoDB 2.4.  Previous versions of Meteor mostly worked with MongoDB 2.6, with\n  a few caveats:\n\n    - Some upsert invocations did not work with MongoDB in previous versions of\n      Meteor.\n    - Previous versions of Meteor required setting up a special \"user-defined\n      role\" with access to the `system.replset` table to use the oplog observe\n      driver with MongoDB 2.6.  These extra permissions are not required with\n      this version of Meteor.\n\n  The MongoDB command needed to set up user permissions for the oplog observe\n  driver is slightly different in MongoDB 2.6; see\n  https://github.com/meteor/meteor/wiki/Oplog-Observe-Driver for details.\n\n  We have also tested Meteor against the recently-released MongoDB 3.0.0.\n  While we are not shipping MongoDB 3.0 with Meteor in this release (preferring\n  to wait until its deployment is more widespread), we believe that Meteor\n  1.0.4 apps will work fine when used with MongoDB 3.0.0 servers.\n\n* Fix 0.8.1 regression where failure to connect to Mongo at startup would log a\n  message but otherwise be ignored. Now it crashes the process, as it did before\n  0.8.1.  [#3038](https://github.com/meteor/meteor/issues/3038)\n\n* Use correct transform for allow/deny rules in `update` when different rules\n  have different transforms.  [#3108](https://github.com/meteor/meteor/issues/3108)\n\n* Provide direct access to the collection and database objects from the npm\n  Mongo driver via new `rawCollection` and `rawDatabase` methods on\n  `Mongo.Collection`.  [#3640](https://github.com/meteor/meteor/issues/3640)\n\n* Observing or publishing an invalid query now throws an error instead of\n  effectively hanging the server.  [#2534](https://github.com/meteor/meteor/issues/2534)\n\n\n### Livequery\n\n* If the oplog observe driver gets too far behind in processing the oplog, skip\n  entries and re-poll queries instead of trying to keep up.  [#2668](https://github.com/meteor/meteor/issues/2668)\n\n* Optimize common cases faced by the \"crossbar\" data structure (used by oplog\n  tailing and DDP method write tracking).  [#3697](https://github.com/meteor/meteor/issues/3697)\n\n* The oplog observe driver recovers from failed attempts to apply the modifier\n  from the oplog (eg, because of empty field names).\n\n\n### Minimongo\n\n* When acting as an insert, `c.upsert({_id: 'x'}, {foo: 1})` now uses the `_id`\n  of `'x'` rather than a random `_id` in the Minimongo implementation of\n  `upsert`, just like it does for `c.upsert({_id: 'x'}, {$set: {foo: 1}})`.\n  (The previous behavior matched a bug in the MongoDB 2.4 implementation of\n  upsert that is fixed in MongoDB 2.6.)  [#2278](https://github.com/meteor/meteor/issues/2278)\n\n* Avoid unnecessary work while paused in minimongo.\n\n* Fix bugs related to observing queries with field filters: `changed` callbacks\n  should not trigger unless a field in the filter has changed, and `changed`\n  callbacks need to trigger when a parent of an included field is\n  unset.  [#2254](https://github.com/meteor/meteor/issues/2254) [#3571](https://github.com/meteor/meteor/issues/3571)\n\n* Disallow setting fields with empty names in minimongo, to match MongoDB 2.6\n  semantics.\n\n\n### DDP\n\n* Subscription handles returned from `Meteor.subscribe` and\n  `TemplateInstance#subscribe` now have a `subscriptionId` property to identify\n  which subscription the handle is for.\n\n* The `onError` callback to `Meteor.subscribe` has been replaced with a more\n  general `onStop` callback that has an error as an optional first argument.\n  The `onStop` callback is called when the subscription is terminated for\n  any reason.  `onError` is still supported for backwards compatibility. [#1461](https://github.com/meteor/meteor/issues/1461)\n\n* The return value from a server-side `Meteor.call` or `Meteor.apply` is now a\n  clone of what the function returned rather than sharing mutable state.  [#3201](https://github.com/meteor/meteor/issues/3201)\n\n* Make it easier to use the Node DDP client implementation without running a web\n  server too.  [#3452](https://github.com/meteor/meteor/issues/3452)\n\n\n### Blaze\n\n* Template instances now have a `subscribe` method that functions exactly like\n  `Meteor.subscribe`, but stops the subscription when the template is destroyed.\n  There is a new method on Template instances called `subscriptionsReady()`\n  which is a reactive function that returns true when all of the subscriptions\n  made with `TemplateInstance#subscribe` are ready. There is also a built-in\n  helper that returns the same thing and can be accessed with\n  `Template.subscriptionsReady` inside any template.\n\n* Add `onRendered`, `onCreated`, and `onDestroyed` methods to\n  `Template`. Assignments to `Template.foo.rendered` and so forth are deprecated\n  but are still supported for backwards compatibility.\n\n* Fix bug where, when a helper or event handler was called from inside a custom\n  block helper,  `Template.instance()` returned the `Template.contentBlock`\n  template instead of the actual user-defined template, making it difficult to\n  use `Template.instance()` for local template state.\n\n* `Template.instance()` now works inside `Template.body`.  [#3631](https://github.com/meteor/meteor/issues/3631)\n\n* Allow specifying attributes on `<body>` tags in templates.\n\n* Improve performance of rendering large arrays.  [#3596](https://github.com/meteor/meteor/issues/3596)\n\n\n### Isobuild\n\n* Support `Npm.require('foo/bar')`.  [#3505](https://github.com/meteor/meteor/issues/3505) [#3526](https://github.com/meteor/meteor/issues/3526)\n\n* In `package.js` files, `Npm.require` can only require built-in Node modules\n  (and dev bundle modules, though you shouldn't depend on that), not the modules\n  from its own `Npm.depends`. Previously, such code would work but only on the\n  second time a `package.js` was executed.\n\n* Ignore vim swap files in the `public` and `private` directories.  [#3322](https://github.com/meteor/meteor/issues/3322)\n\n* Fix regression in 1.0.2 where packages might not be rebuilt when the compiler\n  version changes.\n\n\n### Meteor Accounts\n\n* The `accounts-password` `Accounts.emailTemplates` can now specify arbitrary\n  email `headers`.  The `from` address can now be set separately on the\n  individual templates, and is a function there rather than a static\n  string. [#2858](https://github.com/meteor/meteor/issues/2858) [#2854](https://github.com/meteor/meteor/issues/2854)\n\n* Add login hooks on the client: `Accounts.onLogin` and\n  `Accounts.onLoginFailure`. [#3572](https://github.com/meteor/meteor/issues/3572)\n\n* Add a unique index to the collection that stores OAuth login configuration to\n  ensure that only one configuration exists per service.  [#3514](https://github.com/meteor/meteor/issues/3514)\n\n* On the server, a new option\n  `Accounts.setPassword(user, password, { logout: false })` overrides the\n  default behavior of logging out all logged-in connections for the user.  [#3846](https://github.com/meteor/meteor/issues/3846)\n\n\n### Webapp\n\n* `spiderable` now supports escaped `#!` fragments.  [#2938](https://github.com/meteor/meteor/issues/2938)\n\n* Disable `appcache` on Firefox by default.  [#3248](https://github.com/meteor/meteor/issues/3248)\n\n* Don't overly escape `Meteor.settings.public` and other parts of\n  `__meteor_runtime_config__`.  [#3730](https://github.com/meteor/meteor/issues/3730)\n\n* Reload the client program on `SIGHUP` or Node-specific IPC messages, not\n  `SIGUSR2`.\n\n\n### `meteor` command-line tool\n\n* Enable tab-completion of global variables in `meteor shell`.  [#3227](https://github.com/meteor/meteor/issues/3227)\n\n* Improve the stability of `meteor shell`.  [#3437](https://github.com/meteor/meteor/issues/3437) [#3595](https://github.com/meteor/meteor/issues/3595) [#3591](https://github.com/meteor/meteor/issues/3591)\n\n* `meteor login --email` no longer takes an ignored argument.  [#3532](https://github.com/meteor/meteor/issues/3532)\n\n* Fix regression in 1.0.2 where `meteor run --settings s` would ignore errors\n  reading or parsing the settings file.  [#3757](https://github.com/meteor/meteor/issues/3757)\n\n* Fix crash in `meteor publish` in some cases when the package is inside an\n  app. [#3676](https://github.com/meteor/meteor/issues/3676)\n\n* Fix crashes in `meteor search --show-all` and `meteor search --maintainer`.\n  \\#3636\n\n* Kill PhantomJS processes after `meteor --test`, and only run the app\n  once. [#3205](https://github.com/meteor/meteor/issues/3205) [#3793](https://github.com/meteor/meteor/issues/3793)\n\n* Give a better error when Mongo fails to start up due to a full disk.  [#2378](https://github.com/meteor/meteor/issues/2378)\n\n* After killing existing `mongod` servers, also clear the `mongod.lock` file.\n\n* Stricter validation for package names: they cannot begin with a hyphen, end\n  with a dot, contain two consecutive dots, or start or end with a colon.  (No\n  packages on Atmosphere fail this validation.)  Additionally, `meteor create\n  --package` applies the same validation as `meteor publish` and disallows\n  packages with multiple colons.  (Packages with multiple colons like\n  `local-test:iron:router` are used internally by `meteor test-packages` so that\n  is not a strict validation rule.)\n\n* `meteor create --package` now no longer creates a directory with the full\n  name of the package, since Windows file systems cannot have colon characters\n  in file paths. Instead, the command now creates a directory named the same\n  as the second part of the package name after the colon (without the username\n  prefix).\n\n\n### Meteor Mobile\n\n* Upgrade the Cordova CLI dependency from 3.5.1 to 4.2.0. See the release notes\n  for the 4.x series of the Cordova CLI [on Apache\n  Cordova](http://cordova.apache.org/announcements/2014/10/16/cordova-4.html).\n\n* Related to the recently discovered [attack\n  vectors](http://cordova.apache.org/announcements/2014/08/04/android-351.html)\n  in Android Cordova apps, Meteor Cordova apps no longer allow access to all\n  domains by default. If your app access external resources over XHR, you need\n  to add them to the whitelist of allowed domains with the newly added\n  [`App.accessRule`\n  method](https://docs.meteor.com/#/full/App-accessRule) in your\n  `mobile-config.js` file.\n\n* Upgrade Cordova Plugins dependencies in Meteor Core packages:\n  - `org.apache.cordova.file`: from 1.3.0 to 1.3.3\n  - `org.apache.cordova.file-transfer`: from 0.4.4 to 0.5.0\n  - `org.apache.cordova.splashscreen`: from 0.3.3 to 1.0.0\n  - `org.apache.cordova.console`: from 0.2.10 to 0.2.13\n  - `org.apache.cordova.device`: from 0.2.11 to 0.3.0\n  - `org.apache.cordova.statusbar`: from 0.1.7 to 0.1.10\n  - `org.apache.cordova.inappbrowser`: from 0.5.1 to 0.6.0\n  - `org.apache.cordova.inappbrowser`: from 0.5.1 to 0.6.0\n\n* Use the newer `ios-sim` binary, compiled with Xcode 6 on OS X Mavericks.\n\n\n### Tracker\n\n* Use `Session.set({k1: v1, k2: v2})` to set multiple values at once.\n\n\n### Utilities\n\n* Provide direct access to all options supported by the `request` npm module via\n  the new server-only `npmRequestOptions` option to `HTTP.call`.  [#1703](https://github.com/meteor/meteor/issues/1703)\n\n\n### Other bug fixes and improvements\n\n* Many internal refactorings towards supporting Meteor on Windows are in this\n  release.\n\n* Remove some packages used internally to support legacy MDG systems\n  (`application-configuration`, `ctl`, `ctl-helper`, `follower-livedata`,\n  `dev-bundle-fetcher`, and `star-translate`).\n\n* Provide direct access to some npm modules used by core packages on the\n  `NpmModules` field of `WebAppInternals`, `MongoInternals`, and\n  `HTTPInternals`.\n\n* Upgraded dependencies:\n\n  - node: 0.10.36 (from 0.10.33)\n  - Fibers: 1.0.5 (from 1.0.1)\n  - MongoDB: 2.6.7 (from 2.4.12)\n  - openssl in mongo: 1.0.2 (from 1.0.1j)\n  - MongoDB driver: 1.4.32 (from 1.4.1)\n  - bson: 0.2.18 (from 0.2.7)\n  - request: 2.53.0 (from 2.47.0)\n\n\nPatches contributed by GitHub users 0a-, awatson1978, awwx, bwhitty,\nchristianbundy, d4nyll, dandv, DanielDent, DenisGorbachev, fay-jai, gsuess,\nhwillson, jakozaur, meonkeys, mitar, netanelgilad, queso, rbabayoff, RobertLowe,\nromanzolotarev, Siilwyn, and tmeasday.\n\n\n## v.1.0.3.2, 2015-Feb-25\n\n* Fix regression in 1.0.3 where the `meteor` tool could crash when downloading\n  the second build of a given package version; for example, when running `meteor\n  deploy` on an OSX or 32-bit Linux system for an app containing a binary\n  package.  [#3761](https://github.com/meteor/meteor/issues/3761)\n\n\n## v.1.0.3.1, 2015-Jan-20\n\n* Rewrite `meteor show` and `meteor search` to show package information for\n  local packages and to show if the package is installed for non-local\n  packages. Introduce the `--show-all` flag, and deprecate the\n  `--show-unmigrated` and `--show-old flags`.  Introduce the `--ejson` flag to\n  output an EJSON object.\n\n* Support README.md files in`meteor publish`. Take in the documentation file in\n  `package.js` (set to `README.md` by default) and upload it to the server at\n  publication time. Excerpt the first non-header Markdown section for use in\n  `meteor show`.\n\n* Support updates of package version metadata after that version has been\n  published by running `meteor publish --update` from the package directory.\n\n* Add `meteor test-packages --velocity` (similar to `meteor run --test`).  [#3330](https://github.com/meteor/meteor/issues/3330)\n\n* Fix `meteor update <packageName>` to update `<packageName>` even if it's an\n  indirect dependency of your app.  [#3282](https://github.com/meteor/meteor/issues/3282)\n\n* Fix stack trace when a browser tries to use the server like a proxy.  [#1212](https://github.com/meteor/meteor/issues/1212)\n\n* Fix inaccurate session statistics and possible multiple invocation of\n  Connection.onClose callbacks.\n\n* Switch CLI tool filesystem calls from synchronous to yielding (pro: more\n  concurrency, more responsive to signals; con: could introduce concurrency\n  bugs)\n\n* Don't apply CDN prefix on Cordova. [#3278](https://github.com/meteor/meteor/issues/3278) [#3311](https://github.com/meteor/meteor/issues/3311)\n\n* Don't try to refresh client app in the runner unless the app actually has the\n  autoupdate package. [#3365](https://github.com/meteor/meteor/issues/3365)\n\n* Fix custom release banner logic. [#3353](https://github.com/meteor/meteor/issues/3353)\n\n* Apply HTTP followRedirects option to non-GET requests.  [#2808](https://github.com/meteor/meteor/issues/2808)\n\n* Clean up temporary directories used by package downloads sooner.  [#3324](https://github.com/meteor/meteor/issues/3324)\n\n* If the tool knows about the requested release but doesn't know about the build\n  of its tool for the platform, refresh the catalog rather than failing\n  immediately.  [#3317](https://github.com/meteor/meteor/issues/3317)\n\n* Fix `meteor --get-ready` to not add packages to your app.\n\n* Fix some corner cases in cleaning up app processes in the runner. Drop\n  undocumented `--keepalive` support. [#3315](https://github.com/meteor/meteor/issues/3315)\n\n* Fix CSS autoupdate when `$ROOT_URL` has a non-trivial path.  [#3111](https://github.com/meteor/meteor/issues/3111)\n\n* Save Google OAuth idToken to the User service info object.\n\n* Add git info to `meteor --version`.\n\n* Correctly catch a case of illegal `Tracker.flush` during `Tracker.autorun`.  [#3037](https://github.com/meteor/meteor/issues/3037)\n\n* Upgraded dependencies:\n\n  - jquery: 1.11.2 (from 1.11.0)\n\nPatches by GitHub users DanielDent, DanielDornhardt, PooMaster, Primigenus,\nTarang, TomFreudenberg, adnissen, dandv, fay-jai, knownasilya, mquandalle,\nogourment, restebanez, rissem, smallhelm and tmeasday.\n\n## v1.0.2.1, 2014-Dec-22\n\n* Fix crash in file change watcher.  [#3336](https://github.com/meteor/meteor/issues/3336)\n\n* Allow `meteor test-packages packages/*` even if not all package directories\n  have tests.  [#3334](https://github.com/meteor/meteor/issues/3334)\n\n* Fix typo in `meteor shell` output. [#3326](https://github.com/meteor/meteor/issues/3326)\n\n\n## v1.0.2, 2014-Dec-19\n\n### Improvements to the `meteor` command-line tool\n\n* A new command called `meteor shell` attaches an interactive terminal to\n  an already-running server process, enabling inspection and execution of\n  server-side data and code, with dynamic tab completion of variable names\n  and properties. To see `meteor shell` in action, type `meteor run` in an\n  app directory, then (in another terminal) type `meteor shell` in the\n  same app directory. You do not have to wait for the app to start before\n  typing `meteor shell`, as it will automatically connect when the server\n  is ready. Note that `meteor shell` currently works for local development\n  only, and is not yet supported for apps running on remote hosts.\n\n* We've done a major internal overhaul of the `meteor` command-line tool with an\n  eye to correctness, maintainability, and performance.  Some details include:\n  * Refresh the package catalog for build commands only when an error\n    occurs that could be fixed by a refresh, not for every build command.\n  * Never run the constraint solver to select package versions more than once\n    per build.\n  * Built packages (\"isopacks\") are now cached inside individual app directories\n    instead of inside their source directories.\n  * `meteor run` starts Mongo in parallel with building the application.\n  * The constraint solver no longer leaves a `versions.json` file in your\n    packages source directories; when publishing a package that is not inside an\n    app, it will leave a `.versions` file (with the same format as\n    `.meteor/versions`) which you should check into source control.\n  * The constraint solver's model has been simplified so that plugins must use\n    the same version of packages as their surrounding package when built from\n    local source.\n\n* Using `meteor debug` no longer requires manually continuing the debugger when\n  your app restarts, and it no longer overwrites the symbol `_` inside your app.\n\n* Output from the command-line tool is now word-wrapped to the width of your\n  terminal.\n\n* Remove support for the undocumented earliestCompatibleVersion feature of the\n  package system.\n\n* Reduce CPU usage and disk I/O bandwidth by using kernel file-system change\n  notification events where possible. On file systems that do not support these\n  events (NFS, Vagrant Virtualbox shared folders, etc), file changes will only\n  be detected every 5 seconds; to detect changes more often in these cases (but\n  use more CPU), set the `METEOR_WATCH_FORCE_POLLING` environment\n  variable. [#2135](https://github.com/meteor/meteor/issues/2135)\n\n* Reduce CPU usage by fixing a check for a parent process in `meteor\n  run` that was happening constantly instead of every few seconds. [#3252](https://github.com/meteor/meteor/issues/3252)\n\n* Fix crash when two plugins defined source handlers for the same\n  extension. [#3015](https://github.com/meteor/meteor/issues/3015) [#3180](https://github.com/meteor/meteor/issues/3180)\n\n* Fix bug (introduced in 0.9.3) where the warning about using experimental\n  versions of packages was printed too often.\n\n* Fix bug (introduced in 1.0) where `meteor update --patch` crashed.\n\n* Fix bug (introduced in 0.9.4) where banners about new releases could be\n  printed too many times.\n\n* Fix crash when a package version contained a dot-separated pre-release part\n  with both digits and non-digits. [#3147](https://github.com/meteor/meteor/issues/3147)\n\n* Corporate HTTP proxy support is now implemented using our websocket library's\n  new built-in implementation instead of a custom implementation. [#2515](https://github.com/meteor/meteor/issues/2515)\n\n### Blaze\n\n* Add default behavior for `Template.parentData` with no arguments. This\n  selects the first parent. [#2861](https://github.com/meteor/meteor/issues/2861)\n\n* Fix `Blaze.remove` on a template's view to correctly remove the DOM\n  elements when the template was inserted using\n  `Blaze.renderWithData`. [#3130](https://github.com/meteor/meteor/issues/3130)\n\n* Allow curly braces to be escaped in Spacebars. Use the special\n  sequences `{{|` and `{{{|` to insert a literal `{{` or `{{{`.\n\n### Meteor Accounts\n\n* Allow integration with OAuth1 servers that require additional query\n  parameters to be passed with the access token. [#2894](https://github.com/meteor/meteor/issues/2894)\n\n* Expire a user's password reset and login tokens in all circumstances when\n  their password is changed.\n\n### Other bug fixes and improvements\n\n* Some packages are no longer released as part of the core release process:\n  amplify, backbone, bootstrap, d3, jquery-history, and jquery-layout. This\n  means that new versions of these packages can be published outside of the full\n  Meteor release cycle.\n\n* Require plain objects as the update parameter when doing replacements\n  in server-side collections.\n\n* Fix audit-argument-checks spurious failure when an argument is NaN. [#2914](https://github.com/meteor/meteor/issues/2914)\n\n### Upgraded dependencies\n\n  - node: 0.10.33 (from 0.10.29)\n  - source-map-support: 0.2.8 (from 0.2.5)\n  - semver: 4.1.0 (from 2.2.1)\n  - request: 2.47.0 (from 2.33.0)\n  - tar: 1.0.2 (from 1.0.1)\n  - source-map: 0.1.40 (from 0.1.32)\n  - sqlite3: 3.0.2 (from 3.0.0)\n  - phantomjs npm module: 1.9.12 (from 1.8.1-1)\n  - http-proxy: 1.6.0 (from a fork of 1.0.2)\n  - esprima: 1.2.2 (from an unreleased 1.1-era commit)\n  - escope: 1.0.1 (from 1.0.0)\n  - openssl in mongo: 1.0.1j (from 1.0.1g)\n  - faye-websocket: 0.8.1 (from using websocket-driver instead)\n  - MongoDB: 2.4.12 (from 2.4.9)\n\n\nPatches by GitHub users andylash, anstarovoyt, benweissmann, chrisbridgett,\ncolllin, dandv, ecwyne, graemian, JamesLefrere, kevinchiu, LyuGGang, matteodem,\nmitar, mquandalle, musically-ut, ograycode, pcjpcj2, physiocoder, rgoomar,\ntimhaines, trusktr, Urigo, and zol.\n\n\n## v1.0.1, 2014-Dec-09\n\n* Fix a security issue in allow/deny rules that could result in data\n  loss. If your app uses allow/deny rules, or uses packages that use\n  allow/deny rules, we recommend that you update immediately.\n\n\n## v1.0, 2014-Oct-28\n\n### New Features\n\n* Add the `meteor admin get-machine` command to make it easier to\n  publish packages with binary dependencies for all\n  architectures. `meteor publish` no longer publishes builds\n  automatically if your package has binary NPM dependencies.\n\n* New `localmarket` example, highlighting Meteor's support for mobile\n  app development.\n\n* Restyle the `leaderboard` example, and optimize it for both desktop\n  and mobile.\n\n### Performance\n\n* Reduce unnecessary syncs with the package server, which speeds up\n  startup times for many commands.\n\n* Speed up `meteor deploy` by not bundling unnecessary files and\n  programs.\n\n* To make Meteor easier to use on slow or unreliable network\n  connections, increase timeouts for DDP connections that the Meteor\n  tool uses to communicate with the package server. [#2777](https://github.com/meteor/meteor/issues/2777), [#2789](https://github.com/meteor/meteor/issues/2789).\n\n### Mobile App Support\n\n* Implemented reasonable default behavior for launch screens on mobile\n  apps.\n\n* Don't build for Android when only the iOS build is required, and\n  vice versa.\n\n* Fix bug that could cause mobile apps to stop being able to receive hot\n  code push updates.\n\n* Fix bug where Cordova clients connected to http://example.com instead\n  of https://example.com when https:// was specified in the\n  --mobile-server option. [#2880](https://github.com/meteor/meteor/issues/2880)\n\n* Fix stack traces when attempting to build or run iOS apps on Linux.\n\n* Print a warning when building an app with mobile platforms and\n  outputting the build into the source tree. Outputting a build into the\n  source tree can cause subsequent builds to fail because they will\n  treat the build output as source files.\n\n* Exit from `meteor run` when new Cordova plugins or platforms are\n  added, since we don't support hot code push for new plugins or\n  platforms.\n\n* Fix quoting of arguments to Cordova plugins.\n\n* The `accounts-twitter` package now works in Cordova apps in local\n  development. For workarounds for other login providers in local\n  development mode, see\n  https://github.com/meteor/meteor/wiki/OAuth-for-mobile-Meteor-clients.\n\n### Packaging\n\n* `meteor publish-for-arch` can publish packages built with different Meteor\n  releases.\n\n* Fix default `api.versionsFrom` field in packages created with `meteor\n  create --package`.\n\n* Fix bug where changes in an app's .meteor/versions file would not\n  cause the app to be rebuilt.\n\n### Other bug fixes and improvements\n\n* Use TLSv1 in the `spiderable` package, for compatibility with servers\n  that have disabled SSLv3 in response to the POODLE bug.\n\n* Work around the `meteor run` proxy occasionally running out of sockets.\n\n* Fix bug with regular expressions in minimongo. [#2817](https://github.com/meteor/meteor/issues/2817)\n\n* Add READMEs for several core packages.\n\n* Include protocols in URLs printed by `meteor deploy`.\n\n* Improve error message for limited ordered observe. [#1643](https://github.com/meteor/meteor/issues/1643)\n\n* Fix missing dependency on `random` in the `autoupdate` package. [#2892](https://github.com/meteor/meteor/issues/2892)\n\n* Fix bug where all CSS would be removed from connected clients if a\n  CSS-only change is made between local development server restarts or\n  when deploying with `meteor deploy`.\n\n* Increase height of the Google OAuth popup to the Google-recommended\n  value.\n\n* Fix the layout of the OAuth configuration dialog when used with\n  Bootstrap.\n\n* Allow build plugins to override the 'bare' option on added source\n  files. [#2834](https://github.com/meteor/meteor/issues/2834)\n\nPatches by GitHub users DenisGorbachev, ecwyne, mitar, mquandalle,\nPrimigenus, svda, yauh, and zol.\n\n\n## v0.9.4.1, 2014-Dec-09 (backport)\n\n* Fix a security issue in allow/deny rules that could result in data\n  loss. If your app uses allow/deny rules, or uses packages that use\n  allow/deny rules, we recommend that you update immediately.\n  Backport from 1.0.1.\n\n\n## v0.9.4, 2014-Oct-13\n\n### New Features\n\n* The new `meteor debug` command and `--debug-port` command line option\n  to `meteor run` allow you to easily use node-inspector to debug your\n  server-side code. Add a `debugger` statement to your code to create a\n  breakpoint.\n\n* Add new a `meteor run --test` command that runs\n  [Velocity](https://github.com/meteor-velocity/velocity) tests in your\n  app .\n\n* Add new callbacks `Accounts.onResetPasswordLink`,\n  `Accounts.onEnrollmentLink`, and `Accounts.onEmailVerificationLink`\n  that make it easier to build custom user interfaces on top of the\n  accounts system. These callbacks should be registered before\n  `Meteor.startup` fires, and will be called if the URL matches a link\n  in an email sent by `Accounts.resetPassword`, etc. See\n  https://docs.meteor.com/#Accounts-onResetPasswordLink.\n\n* A new configuration file for mobile apps,\n  `<APP>/mobile-config.js`. This allows you to set app metadata, icons,\n  splash screens, preferences, and PhoneGap/Cordova plugin settings\n  without needing a `cordova_build_override` directory. See\n  https://docs.meteor.com/#mobileconfigjs.\n\n\n### API Changes\n\n* Rename `{{> UI.dynamic}}` to `{{> Template.dynamic}}`, and likewise\n  with `UI.contentBlock` and `UI.elseBlock`. The UI namespace is no\n  longer used anywhere except for backwards compatibility.\n\n* Deprecate the `Template.someTemplate.myHelper = ...` syntax in favor\n  of `Template.someTemplate.helpers(...)`.  Using the older syntax still\n  works, but prints a deprecation warning to the console.\n\n* `Package.registerBuildPlugin` its associated functions have been added\n  to the public API, cleaned up, and documented. The new function is\n  identical to the earlier _transitional_registerBuildPlugin except for\n  minor backwards-compatible API changes. See\n  https://docs.meteor.com/#Package-registerBuildPlugin\n\n* Rename the `showdown` package to `markdown`.\n\n* Deprecate the `amplify`, `backbone`, `bootstrap`, and `d3` integration\n  packages in favor of community alternatives.  These packages will no\n  longer be maintained by MDG.\n\n\n### Tool Changes\n\n* Improved output from `meteor build` to make it easier to publish\n  mobile apps to the App Store and Play Store. See the wiki pages for\n  instructions on how to publish your\n  [iOS](https://github.com/meteor/meteor/wiki/How-to-submit-your-iOS-app-to-App-Store)\n  and\n  [Android](https://github.com/meteor/meteor/wiki/How-to-submit-your-Android-app-to-Play-Store)\n  apps.\n\n* Packages can now be marked as debug-mode only by adding `debugOnly:\n  true` to `Package.describe`. Debug-only packages are not included in\n  the app when it is bundled for production (`meteor build` or `meteor\n  run --production`). This allows package authors to build packages\n  specifically for testing and debugging without increasing the size of\n  the resulting app bundle or causing apps to ship with debug\n  functionality built in.\n\n* Rework the process for installing mobile development SDKs. There is\n  now a `meteor install-sdk` command that automatically install what\n  software it can and points to documentation for the parts that\n  require manual installation.\n\n* The `.meteor/cordova-platforms` file has been renamed to\n  `.meteor/platforms` and now includes the default `server` and\n  `browser` platforms. The default platforms can't currently be removed\n  from a project, though this will be possible in the future. The old\n  file will be automatically migrated to the new one when the app is run\n  with Meteor 0.9.4 or above.\n\n* The `unipackage.json` file inside downloaded packages has been renamed\n  to `isopack.json` and has an improved forwards-compatible format. To\n  maintain backwards compatibility with previous releases, packages will\n  be built with both files.\n\n* The local package metadata cache now uses SQLite, which is much faster\n  than the previous implementation. This improves `meteor` command line\n  tool startup time.\n\n* The constraint solver used by the client to find compatible versions\n  of packages is now much faster.\n\n* The `--port` option to `meteor run` now requires a numeric port\n  (e.g. `meteor run --port example.com` is no longer valid).\n\n* The `--mobile-port` option `meteor run` has been reworked. The option\n  is now `--mobile-server` in `meteor run` and `--server` in `meteor\n  build`. `--server` is required for `meteor build` in apps with mobile\n  platforms installed. `--mobile-server` defaults to an automatically\n  detected IP address on port 3000, and `--server` requires a hostname\n  but defaults to port 80 if a port is not specified.\n\n* Operations that take longer than a few seconds (e.g. downloading\n  packages, installing the Android SDK, etc) now show a progress bar.\n\n* Complete support for using an HTTP proxy in the `meteor` command line\n  tool. Now all DDP connections can work through a proxy.  Use the standard\n  `http_proxy` environment variable to specify your proxy endpoint.  [#2515](https://github.com/meteor/meteor/issues/2515)\n\n\n### Bug Fixes\n\n* Fix behavior of ROOT_URL with path ending in `/`.\n\n* Fix source maps when using a ROOT_URL with a path. [#2627](https://github.com/meteor/meteor/issues/2627)\n\n* Change the mechanism that the Meteor tool uses to clean up app server\n  processes. The new mechanism is more resilient to slow app bundles and\n  other CPU-intensive tasks. [#2536](https://github.com/meteor/meteor/issues/2536), [#2588](https://github.com/meteor/meteor/issues/2588).\n\n\nPatches by GitHub users cryptoquick, Gaelan, jperl, meonkeys, mitar,\nmquandalle, prapicault, pscanf, richguan, rick-golden-healthagen,\nrissem, rosh93, rzymek, and timoabend\n\n\n## v0.9.3.1, 2014-Sep-30\n\n* Don't crash when failing to contact the package server. [#2713](https://github.com/meteor/meteor/issues/2713)\n\n* Allow more than one dash in package versions. [#2715](https://github.com/meteor/meteor/issues/2715)\n\n\n## v0.9.3, 2014-Sep-25\n\n### More Package Version Number Flexibility\n\n* Packages now support relying on multiple major versions of their\n  dependencies (eg `blaze@1.0.0 || 2.0.0`). Additionally, you can now\n  call `api.versionsFrom(<release>)` multiple times, or with an array\n  (eg `api.versionsFrom([<release1>, <release2>])`. Meteor will\n  interpret this to mean that the package will work with packages from\n  all the listed releases.\n\n* Support for \"wrapped package\" version numbers. There is now a `_` field\n  in version numbers. The `_` field must be an integer, and versions with\n  the `_` are sorted after versions without. This allows using the\n  upstream version number as the Meteor package version number and being\n  able to publish multiple version of the Meteor package (e.g.\n  `jquery@1.11.1_2`).\n\nNote: packages using the `||` operator or the `_` symbol in their\nversions or dependencies will be invisible to pre-0.9.3 users. Meteor\nversions 0.9.2 and before do not understand the new version formats and\nwill not be able to use versions of packages that use the new features.\n\n\n### Other Command-line Tool Improvements\n\n* More detailed constraint solver output. Meteor now tells you which\n  constraints prevent upgrading or adding new packages. This will make\n  it much easier to update your app to new versions.\n\n* Better handling of pre-release versions (e.g. versions with\n  `-`). Pre-release packages will now be included in an app if and only\n  if there is no way to meet the app's constraints without using a\n  pre-release package.\n\n* Add `meteor admin set-unmigrated` to allow maintainers to hide\n  pre-0.9.0 packages in `meteor search` and `meteor show`. This will not\n  stop users from continuing to use the package, but it helps prevent\n  new users from finding old non-functional packages.\n\n* Progress bars for time-intensive operations, like downloading large\n  packages.\n\n\n### Other Changes\n\n* Offically support `Meteor.wrapAsync` (renamed from\n  `Meteor._wrapAsync`). Additionally, `Meteor.wrapAsync` now lets you\n  pass an object to bind as `this` in the wrapped call. See\n  https://docs.meteor.com/#meteor_wrapasync.\n\n* The `reactive-dict` package now allows an optional name argument to\n  enable data persistence during hot code push.\n\n\nPatches by GitHub users evliu, meonkeys, mitar, mizzao, mquandalle,\nprapicault, waitingkuo, wulfmeister.\n\n\n\n## v0.9.2.2, 2014-Sep-17\n\n* Fix regression in 0.9.2 that prevented some users from accessing the\n  Meteor development server in their browser. Specifically, 0.9.2\n  unintentionally changed the development mode server's default bind\n  host to localhost instead of 0.0.0.0. [#2596](https://github.com/meteor/meteor/issues/2596)\n\n\n## v0.9.2.1, 2014-Sep-15\n\n* Fix versions of packages that were published with `-cordova` versions\n  in 0.9.2 (appcache, fastclick, htmljs, logging, mobile-status-bar,\n  routepolicy, webapp-hashing).\n\n\n## v0.9.2, 2014-Sep-15\n\nThis release contains our first support for building mobile apps in\nMeteor, for both iOS and Android. This support comes via an\nintegration with Apache's Cordova/PhoneGap project.\n\n  * You can use Cordova/PhoneGap packages in your application or inside\n    a Meteor package to access a device's native functions directly from\n    JavaScript code.\n  * The `meteor add-platform` and `meteor run` commands now let you\n    launch the app in the iOS or Android simulator or run it on an\n    attached hardware device.\n  * This release extends hot code push to support live updates into\n    installed native apps.\n  * The `meteor bundle` command has been renamed to `meteor build` and\n    now outputs build projects for the mobile version of the targeted\n    app.\n  * See\n    https://github.com/meteor/meteor/wiki/Meteor-Cordova-Phonegap-integration\n    for more information about how to get started building mobile apps\n    with Meteor.\n\n* Better mobile support for OAuth login: you can now use a\n  redirect-based flow inside UIWebViews, and the existing popup-based\n  flow has been adapted to work in Cordova/PhoneGap apps.\n\n#### Bug fixes and minor improvements\n\n* Fix sorting on non-trivial keys in Minimongo. [#2439](https://github.com/meteor/meteor/issues/2439)\n\n* Bug fixes and performance improvements for the package system's\n  constraint solver.\n\n* Improved error reporting for misbehaving oplog observe driver. [#2033](https://github.com/meteor/meteor/issues/2033) [#2244](https://github.com/meteor/meteor/issues/2244)\n\n* Drop deprecated source map linking format used for older versions of\n  Firefox.  [#2385](https://github.com/meteor/meteor/issues/2385)\n\n* Allow Meteor tool to run from a symlink. [#2462](https://github.com/meteor/meteor/issues/2462)\n\n* Assets added via a plugin are no longer considered source files. [#2488](https://github.com/meteor/meteor/issues/2488)\n\n* Remove support for long deprecated `SERVER_ID` environment\n  variable. Use `AUTOUPDATE_VERSION` instead.\n\n* Fix bug in reload-safetybelt package that resulted in reload loops in\n  Chrome with cookies disabled.\n\n* Change the paths for static assets served from packages. The `:`\n  character is replaced with the `_` character in package names so as to\n  allow serving on mobile devices and ease operation on Windows. For\n  example, assets from the `abc:bootstrap` package are now served at\n  `/packages/abc_bootstrap` instead of `/packages/abc:bootstrap`.\n\n* Also change the paths within a bundled Meteor app to allow for\n  different client architectures (eg mobile). For example,\n  `bundle/programs/client` is now `bundle/programs/web.browser`.\n\n\nPatches by GitHub users awwx, mizzao, and mquandalle.\n\n\n\n## v0.9.1.1, 2014-Sep-06\n\n* Fix backwards compatibility for packages that had weak dependencies\n  on packages renamed in 0.9.1 (`ui`, `deps`, `livedata`). [#2521](https://github.com/meteor/meteor/issues/2521)\n\n* Fix error when using the `reactive-dict` package without the `mongo`\n  package.\n\n\n## v0.9.1, 2014-Sep-04\n\n#### Organizations in Meteor developer accounts\n\nMeteor 0.9.1 ships with organizations support in Meteor developer\naccounts. Organizations are teams of users that make it easy to\ncollaborate on apps and packages.\n\nCreate an organization at\nhttps://www.meteor.com/account-settings/organizations. Run the `meteor\nauthorized` command in your terminal to give an organization\npermissions to your apps. To add an organization as a maintainer of\nyour packages, use the `meteor admin maintainers` command. You can\nalso publish packages with an organization's name in the package name\nprefix instead of your own username.\n\n\n#### One backwards incompatible change for templates\n\n* Templates can no longer be named \"body\" or \"instance\".\n\n#### Backwards compatible Blaze API changes\n\n* New public and documented APIs:\n  * `Blaze.toHTMLWithData()`\n  * `Template.currentData()`\n  * `Blaze.getView()`\n  * `Template.parentData()` (previously `UI._parentData()`)\n  * `Template.instance()` (previously `UI._templateInstance()`)\n  * `Template.body` (previously `UI.body`)\n  * `new Template` (previously `Template.__create__`)\n  * `Blaze.getData()` (previously `UI.getElementData`, or `Blaze.getCurrentData` with no arguments)\n\n* Deprecate the `ui` package. Instead, use the `blaze` package. The\n  `UI` and `Blaze` symbols are now the same.\n\n* Deprecate `UI.insert`. `UI.render` and `UI.renderWithData` now\n  render a template and place it in the DOM.\n\n* Add an underscore to some undocumented Blaze APIs to make them\n  internal. Notably: `Blaze._materializeView`, `Blaze._createView`,\n  `Blaze._toText`, `Blaze._destroyView`, `Blaze._destroyNode`,\n  `Blaze._withCurrentView`, `Blaze._DOMBackend`,\n  `Blaze._TemplateWith`\n\n* Document Views. Views are the machinery powering DOM updates in\n  Blaze.\n\n* Expose `view` property on template instances.\n\n#### Backwards compatible renames\n\n* Package renames\n  * `livedata` -> `ddp`\n  * `mongo-livedata` -> `mongo`\n  * `standard-app-packages` -> `meteor-platform`\n* Symbol renames\n  * `Meteor.Collection` -> `Mongo.Collection`\n  * `Meteor.Collection.Cursor` -> `Mongo.Cursor`\n  * `Meteor.Collection.ObjectID` -> `Mongo.ObjectID`\n  * `Deps` -> `Tracker`\n\n#### Other\n\n* Add `reactive-var` package. Lets you define a single reactive\n  variable, like a single key in `Session`.\n\n* Don't throw an exception in Chrome when cookies and local storage\n  are blocked.\n\n* Bump DDP version to \"1\". Clients connecting with version \"pre1\" or\n  \"pre2\" should still work.\n\n* Allow query parameters in OAuth1 URLs. [#2404](https://github.com/meteor/meteor/issues/2404)\n\n* Fix `meteor list` if not all packages on server. Fixes [#2468](https://github.com/meteor/meteor/issues/2468)\n\nPatch by GitHub user mitar.\n\n\n## v0.9.0.1, 2014-Aug-27\n\n* Fix issues preventing hot code reload from automatically reloading webapps in\n  two cases: when the old app was a pre-0.9.0 app, and when the app used\n  appcache. (In both cases, an explicit reload still worked.)\n\n* Fix publishing packages containing a plugin with platform-specific code but\n  no platform-specific code in the main package.\n\n* Fix `meteor add package@version` when the package was already added with a\n  different version constraint.\n\n* Improve treatment of pre-release packages (packages with a dash in their\n  version). Guarantee that they will not be chosen by the constraint solver\n  unless explicitly requested.  `meteor list` won't suggest that you update to\n  them.\n\n* Fix slow spiderable executions.\n\n* Fix dev-mode client-only restart when client files changed very soon after\n  server restart.\n\n* Fix stack trace on `meteor add` constraint solver failure.\n\n* Fix \"access-denied\" stack trace when publishing packages.\n\n\n## v0.9.0, 2014-Aug-26\n\nMeteor 0.9.0 introduces the Meteor Package Server. Incorporating lessons from\nour community's Meteorite tool, Meteor 0.9.0 allows users to develop and publish\nMeteor packages to a central repository. The `meteor publish` command is used to\npublish packages. Non-core packages can now be added with `meteor add`, and you\ncan specify version constraints on the packages you use. Binary packages can be\npublished for additional architectures with `meteor publish-for-arch`, which\nallows cross-platform deploys and bundling.  You can search for packages with\n`meteor search` and display information on them with `meteor show`, or you can\nuse the Atmosphere web interface developed by Percolate Studio at\nhttps://atmospherejs.com/\n\nSee https://docs.meteor.com/#writingpackages and\nhttps://docs.meteor.com/#packagejs for more details.\n\nOther packaging-related changes:\n\n* `meteor list` now lists the packages your app is using, which was formerly the\n  behavior of `meteor list --using`. To search for packages you are not\n  currently using, use `meteor search`.  The concept of an \"internal\" package\n  (which did not show up in `meteor list`) no longer exists.\n\n* To prepare a bundle created with `meteor bundle` for execution on a\n  server, you now run `npm install` with no arguments instead of having\n  to specify a few specific npm modules and their versions\n  explicitly. See the README in the generated bundle for more details.\n\n* All `under_score`-style `package.js` APIs (`Package.on_use`, `api.add_files`,\n  etc) have been replaced with `camelCase` names (`Package.onUse`,\n  `api.addFiles`, etc).  The old names continue to work for now.\n\n* There's a new `archMatching` option to `Plugin.registerSourceHandler`, which\n  should be used by any plugin whose output is only for the client or only for\n  the server (eg, CSS and HTML templating packages); this allows Meteor to avoid\n  restarting the server when files processed by these plugins change.\n\nOther changes:\n\n* When running your app with the local development server, changes that only\n  affect the client no longer require restarting the server.  Changes that only\n  affect CSS no longer require the browser to refresh the page, both in local\n  development and in some production environments.  [#490](https://github.com/meteor/meteor/issues/490)\n\n* When a call to `match` fails in a method or subscription, log the\n  failure on the server. (This matches the behavior described in our docs)\n\n* The `appcache` package now defaults to functioning on all browsers\n  that support the AppCache API, rather than a whitelist of browsers.\n  The main effect of this change is that `appcache` is now enabled by\n  default on Firefox, because Firefox no longer makes a confusing\n  popup. You can still disable individual browsers with\n  `AppCache.config`.  [#2241](https://github.com/meteor/meteor/issues/2241)\n\n* The `forceApprovalPrompt` option can now be specified in `Accounts.ui.config`\n  in addition to `Meteor.loginWithGoogle`.  [#2149](https://github.com/meteor/meteor/issues/2149)\n\n* Don't leak websocket clients in server-to-server DDP in some cases (and fix\n  \"Got open from inactive client\"\n  error). https://github.com/faye/websocket-driver-node/pull/8\n\n* Updated OAuth url for login with Meetup.\n\n* Allow minimongo `changed` callbacks to mutate their `oldDocument`\n  argument. [#2231](https://github.com/meteor/meteor/issues/2231)\n\n* Fix upsert called from client with no callback.  [#2413](https://github.com/meteor/meteor/issues/2413)\n\n* Avoid a few harmless exceptions in OplogObserveDriver.\n\n* Refactor `observe-sequence` package.\n\n* Fix `spiderable` race condition.\n\n* Re-apply our fix of NPM bug https://github.com/npm/npm/issues/3265 which got\n  accidentally reverted upstream.\n\n* Workaround for a crash in recent Safari\n  versions. https://github.com/meteor/meteor/commit/e897539adb\n\n* Upgraded dependencies:\n  - less: 1.7.4 (from 1.7.1)\n  - tar: 1.0.1 (from 0.1.19)\n  - fstream: 1.0.2 (from 0.1.25)\n\nPatches by GitHub users Cangit, dandv, ImtiazMajeed, MaximDubrovin, mitar,\nmquandalle, rcy, RichardLitt, thatneat, and twhy.\n\n\n## v0.8.3.1, 2014-Dec-09 (backport)\n\n* Fix a security issue in allow/deny rules that could result in data\n  loss. If your app uses allow/deny rules, or uses packages that use\n  allow/deny rules, we recommend that you update immediately.\n  Backport from 1.0.1.\n\n\n## v0.8.3, 2014-Jul-29\n\n#### Blaze\n\n* Refactor Blaze to simplify internals while preserving the public\n  API. `UI.Component` has been replaced with `Blaze.View.`\n\n* Fix performance issues and memory leaks concerning event handlers.\n\n* Add `UI.remove`, which removes a template after `UI.render`/`UI.insert`.\n\n* Add `this.autorun` to the template instance, which is like `Deps.autorun`\n  but is automatically stopped when the template is destroyed.\n\n* Create `<a>` tags as SVG elements when they have `xlink:href`\n  attributes. (Previously, `<a>` tags inside SVGs were never created as\n  SVG elements.)  [#2178](https://github.com/meteor/meteor/issues/2178)\n\n* Throw an error in `{{foo bar}}` if `foo` is missing or not a function.\n\n* Cursors returned from template helpers for #each should implement\n  the `observeChanges` method and don't have to be Minimongo cursors\n  (allowing new custom data stores for Blaze like Miniredis).\n\n* Remove warnings when {{#each}} iterates over a list of strings,\n  numbers, or other items that contains duplicates.  [#1980](https://github.com/meteor/meteor/issues/1980)\n\n#### Meteor Accounts\n\n* Fix regression in 0.8.2 where an exception would be thrown if\n  `Meteor.loginWithPassword` didn't have a callback. Callbacks to\n  `Meteor.loginWithPassword` are now optional again.  [#2255](https://github.com/meteor/meteor/issues/2255)\n\n* Fix OAuth popup flow in mobile apps that don't support\n  `window.opener`.  [#2302](https://github.com/meteor/meteor/issues/2302)\n\n* Fix \"Email already exists\" error with MongoDB 2.6.  [#2238](https://github.com/meteor/meteor/issues/2238)\n\n\n#### mongo-livedata and minimongo\n\n* Fix performance issue where a large batch of oplog updates could block\n  the node event loop for long periods.  [#2299](https://github.com/meteor/meteor/issues/2299).\n\n* Fix oplog bug resulting in error message \"Buffer inexplicably empty\".  [#2274](https://github.com/meteor/meteor/issues/2274)\n\n* Fix regression from 0.8.2 that caused collections to appear empty in\n  reactive `findOne()` or `fetch` queries that run before a mutator\n  returns.  [#2275](https://github.com/meteor/meteor/issues/2275)\n\n\n#### Miscellaneous\n\n* Stop including code by default that automatically refreshes the page\n  if JavaScript and CSS don't load correctly. While this code is useful\n  in some multi-server deployments, it can cause infinite refresh loops\n  if there are errors on the page. Add the `reload-safetybelt` package\n  to your app if you want to include this code.\n\n* On the server, `Meteor.startup(c)` now calls `c` immediately if the\n  server has already started up, matching the client behavior.  [#2239](https://github.com/meteor/meteor/issues/2239)\n\n* Add support for server-side source maps when debugging with\n  `node-inspector`.\n\n* Add `WebAppInternals.addStaticJs()` for adding static JavaScript code\n  to be served in the app, inline if allowed by `browser-policy`.\n\n* Make the `tinytest/run` method return immediately, so that `wait`\n  method calls from client tests don't block on server tests completing.\n\n* Log errors from method invocations on the client if there is no\n  callback provided.\n\n* Upgraded dependencies:\n  - node: 0.10.29 (from 0.10.28)\n  - less: 1.7.1 (from 1.6.1)\n\nPatches contributed by GitHub users Cangit, cmather, duckspeaker, zol.\n\n\n## v0.8.2, 2014-Jun-23\n\n#### Meteor Accounts\n\n* Switch `accounts-password` to use bcrypt to store passwords on the\n  server. (Previous versions of Meteor used a protocol called SRP.)\n  Users will be transparently transitioned when they log in. This\n  transition is one-way, so you cannot downgrade a production app once\n  you upgrade to 0.8.2. If you are maintaining an authenticating DDP\n  client:\n     - Clients that use the plaintext password login handler (i.e. call\n       the `login` method with argument `{ password: <plaintext\n       password> }`) will continue to work, but users will not be\n       transitioned from SRP to bcrypt when logging in with this login\n       handler.\n     - Clients that use SRP will no longer work. These clients should\n       instead directly call the `login` method, as in\n       `Meteor.loginWithPassword`. The argument to the `login` method\n       can be either:\n         - `{ password: <plaintext password> }`, or\n         - `{ password: { digest: <password hash>, algorithm: \"sha-256\" } }`,\n           where the password hash is the hex-encoded SHA256 hash of the\n           plaintext password.\n\n* Show the display name of the currently logged-in user after following\n  an email verification link or a password reset link in `accounts-ui`.\n\n* Add a `userEmail` option to `Meteor.loginWithMeteorDeveloperAccount`\n  to pre-fill the user's email address in the OAuth popup.\n\n* Ensure that the user object has updated token information before\n  it is passed to email template functions. [#2210](https://github.com/meteor/meteor/issues/2210)\n\n* Export the function that serves the HTTP response at the end of an\n  OAuth flow as `OAuth._endOfLoginResponse`. This function can be\n  overridden to make the OAuth popup flow work in certain mobile\n  environments where `window.opener` is not supported.\n\n* Remove support for OAuth redirect URLs with a `redirect` query\n  parameter. This OAuth flow was never documented and never fully\n  worked.\n\n\n#### Blaze\n\n* Blaze now tracks individual CSS rules in `style` attributes and won't\n  overwrite changes to them made by other JavaScript libraries.\n\n* Add `{{> UI.dynamic}}` to make it easier to dynamically render a\n  template with a data context.\n\n* Add `UI._templateInstance()` for accessing the current template\n  instance from within a block helper.\n\n* Add `UI._parentData(n)` for accessing parent data contexts from\n  within a block helper.\n\n* Add preliminary API for registering hooks to run when Blaze intends to\n  insert, move, or remove DOM elements. For example, you can use these\n  hooks to animate nodes as they are inserted, moved, or removed. To use\n  them, you can set the `_uihooks` property on a container DOM\n  element. `_uihooks` is an object that can have any subset of the\n  following three properties:\n\n    - `insertElement: function (node, next)`: called when Blaze intends\n      to insert the DOM element `node` before the element `next`\n    - `moveElement: function (node, next)`: called when Blaze intends to\n      move the DOM element `node` before the element `next`\n    - `removeElement: function (node)`: called when Blaze intends to\n      remove the DOM element `node`\n\n    Note that when you set one of these functions on a container\n    element, Blaze will not do the actual operation; it's your\n    responsibility to actually insert, move, or remove the node (by\n    calling `$(node).remove()`, for example).\n\n* The `findAll` method on template instances now returns a vanilla\n  array, not a jQuery object. The `$` method continues to\n  return a jQuery object. [#2039](https://github.com/meteor/meteor/issues/2039)\n\n* Fix a Blaze memory leak by cleaning up event handlers when a template\n  instance is destroyed. [#1997](https://github.com/meteor/meteor/issues/1997)\n\n* Fix a bug where helpers used by {{#with}} were still re-running when\n  their reactive data sources changed after they had been removed from\n  the DOM.\n\n* Stop not updating form controls if they're focused. If a field is\n  edited by one user while another user is focused on it, it will just\n  lose its value but maintain its focus. [#1965](https://github.com/meteor/meteor/issues/1965)\n\n* Add `_nestInCurrentComputation` option to `UI.render`, fixing a bug in\n  {{#each}} when an item is added inside a computation that subsequently\n  gets invalidated. [#2156](https://github.com/meteor/meteor/issues/2156)\n\n* Fix bug where \"=\" was not allowed in helper arguments. [#2157](https://github.com/meteor/meteor/issues/2157)\n\n* Fix bug when a template tag immediately follows a Spacebars block\n  comment. [#2175](https://github.com/meteor/meteor/issues/2175)\n\n\n#### Command-line tool\n\n* Add --directory flag to `meteor bundle`. Setting this flag outputs a\n  directory rather than a tarball.\n\n* Speed up updates of NPM modules by upgrading Node to include our fix for\n  https://github.com/npm/npm/issues/3265 instead of passing `--force` to\n  `npm install`.\n\n* Always rebuild on changes to npm-shrinkwrap.json files.  [#1648](https://github.com/meteor/meteor/issues/1648)\n\n* Fix uninformative error message when deploying to long hostnames. [#1208](https://github.com/meteor/meteor/issues/1208)\n\n* Increase a buffer size to avoid failing when running MongoDB due to a\n  large number of processes running on the machine, and fix the error\n  message when the failure does occur. [#2158](https://github.com/meteor/meteor/issues/2158)\n\n* Clarify a `meteor mongo` error message when using the MONGO_URL\n  environment variable. [#1256](https://github.com/meteor/meteor/issues/1256)\n\n\n#### Testing\n\n* Run server tests from multiple clients serially instead of in\n  parallel. This allows testing features that modify global server\n  state.  [#2088](https://github.com/meteor/meteor/issues/2088)\n\n\n#### Security\n\n* Add Content-Type headers on JavaScript and CSS resources.\n\n* Add `X-Content-Type-Options: nosniff` header to\n  `browser-policy-content`'s default policy. If you are using\n  `browser-policy-content` and you don't want your app to send this\n  header, then call `BrowserPolicy.content.allowContentTypeSniffing()`.\n\n* Use `Meteor.absoluteUrl()` to compute the redirect URL in the `force-ssl`\n  package (instead of the host header).\n\n\n#### Miscellaneous\n\n* Allow `check` to work on the server outside of a Fiber. [#2136](https://github.com/meteor/meteor/issues/2136)\n\n* EJSON custom type conversion functions should not be permitted to yield. [#2136](https://github.com/meteor/meteor/issues/2136)\n\n* The legacy polling observe driver handles errors communicating with MongoDB\n  better and no longer gets \"stuck\" in some circumstances.\n\n* Automatically rewind cursors before calls to `fetch`, `forEach`, or `map`. On\n  the client, don't cache the return value of `cursor.count()` (consistently\n  with the server behavior). `cursor.rewind()` is now a no-op. [#2114](https://github.com/meteor/meteor/issues/2114)\n\n* Remove an obsolete hack in reporting line numbers for LESS errors. [#2216](https://github.com/meteor/meteor/issues/2216)\n\n* Avoid exceptions when accessing localStorage in certain Internet\n  Explorer configurations. [#1291](https://github.com/meteor/meteor/issues/1291), [#1688](https://github.com/meteor/meteor/issues/1688).\n\n* Make `handle.ready()` reactively stop, where `handle` is a\n  subscription handle.\n\n* Fix an error message from `audit-argument-checks` after login.\n\n* Make the DDP server send an error if the client sends a connect\n  message with a missing or malformed `support` field. [#2125](https://github.com/meteor/meteor/issues/2125)\n\n* Fix missing `jquery` dependency in the `amplify` package. [#2113](https://github.com/meteor/meteor/issues/2113)\n\n* Ban inserting EJSON custom types as documents. [#2095](https://github.com/meteor/meteor/issues/2095)\n\n* Fix incorrect URL rewrites in stylesheets. [#2106](https://github.com/meteor/meteor/issues/2106)\n\n* Upgraded dependencies:\n  - node: 0.10.28 (from 0.10.26)\n  - uglify-js: 2.4.13 (from 2.4.7)\n  - sockjs server: 0.3.9 (from 0.3.8)\n  - websocket-driver: 0.3.4 (from 0.3.2)\n  - stylus: 0.46.3 (from 0.42.3)\n\nPatches contributed by GitHub users awwx, babenzele, Cangit, dandv,\nducdigital, emgee3, felixrabe, FredericoC, jbruni, kentonv, mizzao,\nmquandalle, subhog, tbjers, tmeasday.\n\n\n## v0.8.1.3, 2014-May-22\n\n* Fix a security issue in the `spiderable` package. `spiderable` now\n  uses the ROOT_URL environment variable instead of the Host header to\n  determine which page to snapshot.\n\n* Fix hardcoded Twitter URL in `oauth1` package. This fixes a regression\n  in 0.8.0.1 that broke Atmosphere packages that do OAuth1\n  logins. [#2154](https://github.com/meteor/meteor/issues/2154).\n\n* Add `credentialSecret` argument to `Google.retrieveCredential`, which\n  was forgotten in a previous release.\n\n* Remove nonexistent `-a` and `-r` aliases for `--add` and `--remove` in\n  `meteor help authorized`. [#2155](https://github.com/meteor/meteor/issues/2155)\n\n* Add missing `underscore` dependency in the `oauth-encryption` package. [#2165](https://github.com/meteor/meteor/issues/2165)\n\n* Work around IE8 bug that caused some apps to fail to render when\n  minified. [#2037](https://github.com/meteor/meteor/issues/2037).\n\n\n## v0.8.1.2, 2014-May-12\n\n* Fix memory leak (introduced in 0.8.1) by making sure to unregister\n  sessions at the server when they are closed due to heartbeat timeout.\n\n* Add `credentialSecret` argument to `Google.retrieveCredential`,\n  `Facebook.retrieveCredential`, etc., which is needed to use them as of\n  0.8.1. [#2118](https://github.com/meteor/meteor/issues/2118)\n\n* Fix 0.8.1 regression that broke apps using a `ROOT_URL` with a path\n  prefix. [#2109](https://github.com/meteor/meteor/issues/2109)\n\n\n## v0.8.1.1, 2014-May-01\n\n* Fix 0.8.1 regression preventing clients from specifying `_id` on insert. [#2097](https://github.com/meteor/meteor/issues/2097)\n\n* Fix handling of malformed URLs when merging CSS files. [#2103](https://github.com/meteor/meteor/issues/2103), [#2093](https://github.com/meteor/meteor/issues/2093)\n\n* Loosen the checks on the `options` argument to `Collection.find` to\n  allow undefined values.\n\n\n## v0.8.1, 2014-Apr-30\n\n#### Meteor Accounts\n\n* Fix a security flaw in OAuth1 and OAuth2 implementations. If you are\n  using any OAuth accounts packages (such as `accounts-google` or\n  `accounts-twitter`), we recommend that you update immediately and log\n  out your users' current sessions with the following MongoDB command:\n\n    $ db.users.update({}, { $set: { 'services.resume.loginTokens': [] } }, { multi: true });\n\n* OAuth redirect URLs are now required to be on the same origin as your app.\n\n* Log out a user's other sessions when they change their password.\n\n* Store pending OAuth login results in the database instead of\n  in-memory, so that an OAuth flow succeeds even if different requests\n  go to different server processes.\n\n* When validateLoginAttempt callbacks return false, don't override a more\n  specific error message.\n\n* Add `Random.secret()` for generating security-critical secrets like\n  login tokens.\n\n* `Meteor.logoutOtherClients` now calls the user callback when other\n  login tokens have actually been removed from the database, not when\n  they have been marked for eventual removal.  [#1915](https://github.com/meteor/meteor/issues/1915)\n\n* Rename `Oauth` to `OAuth`.  `Oauth` is now an alias for backwards\n  compatibility.\n\n* Add `oauth-encryption` package for encrypting sensitive account\n  credentials in the database.\n\n* A validate login hook can now override the exception thrown from\n  `beginPasswordExchange` like it can for other login methods.\n\n* Remove an expensive observe over all users in the `accounts-base`\n  package.\n\n\n#### Blaze\n\n* Disallow `javascript:` URLs in URL attribute values by default, to\n  help prevent cross-site scripting bugs. Call\n  `UI._allowJavascriptUrls()` to allow them.\n\n* Fix `UI.toHTML` on templates containing `{{#with}}`.\n\n* Fix `{{#with}}` over a data context that is mutated.  [#2046](https://github.com/meteor/meteor/issues/2046)\n\n* Clean up autoruns when calling `UI.toHTML`.\n\n* Properly clean up event listeners when removing templates.\n\n* Add support for `{{!-- block comments --}}` in Spacebars. Block comments may\n  contain `}}`, so they are more useful than `{{! normal comments}}` for\n  commenting out sections of Spacebars templates.\n\n* Don't dynamically insert `<tbody>` tags in reactive tables\n\n* When handling a custom jQuery event, additional arguments are\n  no longer lost -- they now come after the template instance\n  argument.  [#1988](https://github.com/meteor/meteor/issues/1988)\n\n\n#### DDP and MongoDB\n\n* Extend latency compensation to support an arbitrary sequence of\n  inserts in methods.  Previously, documents created inside a method\n  stub on the client would eventually be replaced by new documents\n  from the server, causing the screen to flicker.  Calling `insert`\n  inside a method body now generates the same ID on the client (inside\n  the method stub) and on the server.  A sequence of inserts also\n  generates the same sequence of IDs.  Code that wants a random stream\n  that is consistent between method stub and real method execution can\n  get one with `DDP.randomStream`.\n  https://trello.com/c/moiiS2rP/57-pattern-for-creating-multiple-database-records-from-a-method\n\n* The document passed to the `insert` callback of `allow` and `deny` now only\n  has a `_id` field if the client explicitly specified one; this allows you to\n  use `allow`/`deny` rules to prevent clients from specifying their own\n  `_id`. As an exception, `allow`/`deny` rules with a `transform` always have an\n  `_id`.\n\n* DDP now has an implementation of bidirectional heartbeats which is consistent\n  across SockJS and websocket transports. This enables connection keepalive and\n  allows servers and clients to more consistently and efficiently detect\n  disconnection.\n\n* The DDP protocol version number has been incremented to \"pre2\" (adding\n  randomSeed and heartbeats).\n\n* The oplog observe driver handles errors communicating with MongoDB\n  better and knows to re-poll all queries after a MongoDB failover.\n\n* Fix bugs involving mutating DDP method arguments.\n\n\n#### meteor command-line tool\n\n* Move boilerplate HTML from tools to webapp.  Change internal\n  `Webapp.addHtmlAttributeHook` API.\n\n* Add `meteor list-sites` command for listing the sites that you have\n  deployed to meteor.com with your Meteor developer account.\n\n* Third-party template languages can request that their generated source loads\n  before other JavaScript files, just like *.html files, by passing the\n  isTemplate option to Plugin.registerSourceHandler.\n\n* You can specify a particular interface for the dev mode runner to bind to with\n  `meteor -p host:port`.\n\n* Don't include proprietary tar tags in bundle tarballs.\n\n* Convert relative URLs to absolute URLs when merging CSS files.\n\n\n#### Upgraded dependencies\n\n* Node.js from 0.10.25 to 0.10.26.\n* MongoDB driver from 1.3.19 to 1.4.1\n* stylus: 0.42.3 (from 0.42.2)\n* showdown: 0.3.1\n* css-parse: an unreleased version (from 1.7.0)\n* css-stringify: an unreleased version (from 1.4.1)\n\n\nPatches contributed by GitHub users aldeed, apendua, arbesfeld, awwx, dandv,\ndavegonzalez, emgee3, justinsb, mquandalle, Neftedollar, Pent, sdarnell,\nand timhaines.\n\n\n## v0.8.0.1, 2014-Apr-21\n\n* Fix security flaw in OAuth1 implementation. Clients can no longer\n  choose the callback_url for OAuth1 logins.\n\n\n## v0.8.0, 2014-Mar-27\n\nMeteor 0.8.0 introduces Blaze, a total rewrite of our live templating engine,\nreplacing Spark. Advantages of Blaze include:\n\n  * Better interoperability with jQuery plugins and other techniques which\n    directly manipulate the DOM\n  * More fine-grained updates: only the specific elements or attributes that\n    change are touched rather than the entire template\n  * A fully documented templating language\n  * No need for the confusing `{{#constant}}`, `{{#isolate}}`, and `preserve`\n    directives\n  * Uses standard jQuery delegation (`.on`) instead of our custom implementation\n  * Blaze supports live SVG templates that work just like HTML templates\n\nSee\n[the Using Blaze wiki page](https://github.com/meteor/meteor/wiki/Using-Blaze)\nfor full details on upgrading your app to 0.8.0.  This includes:\n\n* The `Template.foo.rendered` callback is now only called once when the template\n  is rendered, rather than repeatedly as it is \"re-rendered\", because templates\n  now directly update changed data instead of fully re-rendering.\n\n* The `accounts-ui` login buttons are now invoked as a `{{> loginButtons}}`\n  rather than as `{{loginButtons}}`.\n\n* Previous versions of Meteor used a heavily modified version of the Handlebars\n  templating language. In 0.8.0, we've given it its own name: Spacebars!\n  Spacebars has an\n  [explicit specification](https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md)\n  instead of being defined as a series of changes to Handlebars. There are some\n  incompatibilities with our previous Handlebars fork, such as a\n  [different way of specifying dynamic element attributes](https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md#in-attribute-values)\n  and a\n  [new way of defining custom block helpers](https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md#custom-block-helpers).\n\n* Your template files must consist of\n  [well-formed HTML](https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md#html-dialect). Invalid\n  HTML is now a compilation failure.  (There is a current limitation in our HTML\n  parser such that it does not support\n  [omitting end tags](http://www.w3.org/TR/html5/syntax.html#syntax-tag-omission)\n  on elements such as `<P>` and `<LI>`.)\n\n* `Template.foo` is no longer a function. It is instead a\n  \"component\". Components render to an intermediate representation of an HTML\n  tree, not a string, so there is no longer an easy way to render a component to\n  a static HTML string.\n\n* `Meteor.render` and `Spark.render` have been removed. Use `UI.render` and\n  `UI.insert` instead.\n\n* The `<body>` tag now defines a template just like the `<template>` tag, which\n  can have helpers and event handlers.  Define them directly on the object\n  `UI.body`.\n\n* Previous versions of Meteor shipped with a synthesized `tap` event,\n  implementing a zero-delay click event on mobile browsers. Unfortunately, this\n  event never worked very well. We're eliminating it. Instead, use one of the\n  excellent third party solutions.\n\n* The `madewith` package (which supported adding a badge to your website\n  displaying its score from http://madewith.meteor.com/) has been removed, as it\n  is not compatible with the new version of that site.\n\n* The internal `spark`, `liverange`, `universal-events`, and `domutils` packages\n  have been removed.\n\n* The `Handlebars` namespace has been deprecated.  `Handlebars.SafeString` is\n  now `Spacebars.SafeString`, and `Handlebars.registerHelper` is now\n  `UI.registerHelper`.\n\nPatches contributed by GitHub users cmather and mart-jansink.\n\n\n## v0.7.2.3, 2014-Dec-09 (backport)\n\n* Fix a security issue in allow/deny rules that could result in data\n  loss. If your app uses allow/deny rules, or uses packages that use\n  allow/deny rules, we recommend that you update immediately.\n  Backport from 1.0.1.\n\n## v0.7.2.2, 2014-Apr-21 (backport)\n\n* Fix a security flaw in OAuth1 and OAuth2 implementations.\n  Backport from 0.8.1; see its entry for recommended actions to take.\n\n## v0.7.2.1, 2014-Apr-30 (backport)\n\n* Fix security flaw in OAuth1 implementation. Clients can no longer\n  choose the callback_url for OAuth1 logins.\n  Backport from 0.8.0.1.\n\n## v0.7.2, 2014-Mar-18\n\n* Support oplog tailing on queries with the `limit` option. All queries\n  except those containing `$near` or `$where` selectors or the `skip`\n  option can now be used with the oplog driver.\n\n* Add hooks to login process: `Accounts.onLogin`,\n  `Accounts.onLoginFailure`, and `Accounts.validateLoginAttempt`. These\n  functions allow for rate limiting login attempts, logging an audit\n  trail, account lockout flags, and more. See:\n  http://docs.meteor.com/#accounts_validateloginattempt [#1815](https://github.com/meteor/meteor/issues/1815)\n\n* Change the `Accounts.registerLoginHandler` API for custom login\n  methods. Login handlers now require a name and no longer have to deal\n  with generating resume tokens. See\n  https://github.com/meteor/meteor/blob/devel/packages/accounts-base/accounts_server.js\n  for details. OAuth based login handlers using the\n  `Oauth.registerService` packages are not affected.\n\n* Add support for HTML email in `Accounts.emailTemplates`.  [#1785](https://github.com/meteor/meteor/issues/1785)\n\n* minimongo: Support `{a: {$elemMatch: {x: 1, $or: [{a: 1}, {b: 1}]}}}`  [#1875](https://github.com/meteor/meteor/issues/1875)\n\n* minimongo: Support `{a: {$regex: '', $options: 'i'}}`  [#1874](https://github.com/meteor/meteor/issues/1874)\n\n* minimongo: Fix sort implementation with multiple sort fields which each look\n  inside an array. eg, ensure that with sort key `{'a.x': 1, 'a.y': 1}`, the\n  document `{a: [{x: 0, y: 4}]}` sorts before\n  `{a: [{x: 0, y: 5}, {x: 1, y: 3}]}`, because the 3 should not be used as a\n  tie-breaker because it is not \"next to\" the tied 0s.\n\n* minimongo: Fix sort implementation when selector and sort key share a field,\n  that field matches an array in the document, and only some values of the array\n  match the selector. eg, ensure that with sort key `{a: 1}` and selector\n  `{a: {$gt: 3}}`, the document `{a: [4, 6]}` sorts before `{a: [1, 5]}`,\n  because the 1 should not be used as a sort key because it does not match the\n  selector. (We only approximate the MongoDB behavior here by only supporting\n  relatively selectors.)\n\n* Use `faye-websocket` (0.7.2) npm module instead of `websocket` (1.0.8) for\n  server-to-server DDP.\n\n* Update Google OAuth package to use new `profile` and `email` scopes\n  instead of deprecated URL-based scopes.  [#1887](https://github.com/meteor/meteor/issues/1887)\n\n* Add `_throwFirstError` option to `Deps.flush`.\n\n* Make `facts` package data available on the server as\n  `Facts._factsByPackage`.\n\n* Fix issue where `LESS` compilation error could crash the `meteor run`\n  process.  [#1877](https://github.com/meteor/meteor/issues/1877)\n\n* Fix crash caused by empty HTTP host header in `meteor run` development\n  server.  [#1871](https://github.com/meteor/meteor/issues/1871)\n\n* Fix hot code reload in private browsing mode in Safari.\n\n* Fix appcache size calculation to avoid erronious warnings. [#1847](https://github.com/meteor/meteor/issues/1847)\n\n* Remove unused `Deps._makeNonReactive` wrapper function. Call\n  `Deps.nonreactive` directly instead.\n\n* Avoid setting the `oplogReplay` on non-oplog collections. Doing so\n  caused mongod to crash.\n\n* Add startup message to `test-in-console` to ease automation. [#1884](https://github.com/meteor/meteor/issues/1884)\n\n* Upgraded dependencies\n  - amplify: 1.1.2 (from 1.1.0)\n\nPatches contributed by GitHub users awwx, dandv, queso, rgould, timhaines, zol\n\n\n## v0.7.1.2, 2014-Feb-27\n\n* Fix bug in tool error handling that caused `meteor` to crash on Mac\n  OSX when no computer name is set.\n\n* Work around a bug that caused MongoDB to fail an assertion when using\n  tailable cursors on non-oplog collections.\n\n\n## v0.7.1.1, 2014-Feb-24\n\n* Integrate with Meteor developer accounts, a new way of managing your\n  meteor.com deployed sites. When you use `meteor deploy`, you will be\n  prompted to create a developer account.\n    - Once you've created a developer account, you can log in and out\n      from the command line with `meteor login` and `meteor logout`.\n    - You can claim legacy sites with `meteor claim`. This command will\n      prompt you for your site password if you are claiming a\n      password-protected site; after claiming it, you will not need to\n      enter the site password again.\n    - You can add or remove authorized users, and view the list of\n      authorized users, for a site with `meteor authorized`.\n    - You can view your current username with `meteor whoami`.\n    - This release also includes the `accounts-meteor-developer` package\n      for building Meteor apps that allow users to log in with their own\n      developer accounts.\n\n* Improve the oplog tailing implementation for getting real-time database\n  updates from MongoDB.\n    - Add support for all operators except `$where` and `$near`. Limit and\n      skip are not supported yet.\n    - Add optimizations to avoid needless data fetches from MongoDB.\n    - Fix an error (\"Cannot call method 'has' of null\") in an oplog\n      callback. [#1767](https://github.com/meteor/meteor/issues/1767)\n\n* Add and improve support for minimongo operators.\n  - Support `$comment`.\n  - Support `obj` name in `$where`.\n  - `$regex` matches actual regexps properly.\n  - Improve support for `$nin`, `$ne`, `$not`.\n  - Support using `{ $in: [/foo/, /bar/] }`. [#1707](https://github.com/meteor/meteor/issues/1707)\n  - Support `{$exists: false}`.\n  - Improve type-checking for selectors.\n  - Support `{x: {$elemMatch: {$gt: 5}}}`.\n  - Match Mongo's behavior better when there are arrays in the document.\n  - Support `$near` with sort.\n  - Implement updates with `{ $set: { 'a.$.b': 5 } }`.\n  - Support `{$type: 4}` queries.\n  - Optimize `remove({})` when observers are paused.\n  - Make update-by-id constant time.\n  - Allow `{$set: {'x._id': 1}}`.  [#1794](https://github.com/meteor/meteor/issues/1794)\n\n* Upgraded dependencies\n  - node: 0.10.25 (from 0.10.22). The workaround for specific Node\n    versions from 0.7.0 is now removed; 0.10.25+ is supported.\n  - jquery: 1.11.0 (from 1.8.2). See\n    http://jquery.com/upgrade-guide/1.9/ for upgrade instructions.\n  - jquery-waypoints: 2.0.4 (from 1.1.7). Contains\n    backwards-incompatible changes.\n  - source-map: 0.3.2 (from 0.3.30) [#1782](https://github.com/meteor/meteor/issues/1782)\n  - websocket-driver: 0.3.2 (from 0.3.1)\n  - http-proxy: 1.0.2 (from a pre-release fork of 1.0)\n  - semver: 2.2.1 (from 2.1.0)\n  - request: 2.33.0 (from 2.27.0)\n  - fstream: 0.1.25 (from 0.1.24)\n  - tar: 0.1.19 (from 0.1.18)\n  - eachline: a fork of 2.4.0 (from 2.3.3)\n  - source-map: 0.1.31 (from 0.1.30)\n  - source-map-support: 0.2.5 (from 0.2.3)\n  - mongo: 2.4.9 (from 2.4.8)\n  - openssl in mongo: 1.0.1f (from 1.0.1e)\n  - kexec: 0.2.0 (from 0.1.1)\n  - less: 1.6.1 (from 1.3.3)\n  - stylus: 0.42.2 (from 0.37.0)\n  - nib: 1.0.2 (from 1.0.0)\n  - coffeescript: 1.7.1 (from 1.6.3)\n\n* CSS preprocessing and sourcemaps:\n  - Add sourcemap support for CSS stylesheet preprocessors. Use\n    sourcemaps for stylesheets compiled with LESS.\n  - Improve CSS minification to deal with `@import` statements correctly.\n  - Lint CSS files for invalid `@` directives.\n  - Change the recommended suffix for imported LESS files from\n    `.lessimport` to `.import.less`. Add `.import.styl` to allow\n    `stylus` imports. `.lessimport` continues to work but is deprecated.\n\n* Add `clientAddress` and `httpHeaders` to `this.connection` in method\n  calls and publish functions.\n\n* Hash login tokens before storing them in the database. Legacy unhashed\n  tokens are upgraded to hashed tokens in the database as they are used\n  in login requests.\n\n* Change default accounts-ui styling and add more CSS classes.\n\n* Refactor command-line tool. Add test harness and better tests. Run\n  `meteor self-test --help` for info on running the tools test suite.\n\n* Speed up application re-build in development mode by re-using file\n  hash computation between file change watching code and application\n  build code..\n\n* Fix issues with documents containing a key named `length` with a\n  numeric value. Underscore treated these as arrays instead of objects,\n  leading to exceptions when . Patch Underscore to not treat plain\n  objects (`x.constructor === Object`) with numeric `length` fields as\n  arrays. [#594](https://github.com/meteor/meteor/issues/594) [#1737](https://github.com/meteor/meteor/issues/1737)\n\n* Deprecate `Accounts.loginServiceConfiguration` in favor of\n  `ServiceConfiguration.configurations`, exported by the\n  `service-configuration` package. `Accounts.loginServiceConfiguration`\n  is maintained for backwards-compatibility, but it is defined in a\n  `Meteor.startup` block and so cannot be used from top-level code.\n\n* Cursors with a field specifier containing `{_id: 0}` can no longer be\n  used with `observeChanges` or `observe`. This includes the implicit\n  calls to these functions that are done when returning a cursor from a\n  publish function or using `{{#each}}`.\n\n* Transform functions must return objects and may not change the `_id`\n  field, though they may leave it out.\n\n* Remove broken IE7 support from the `localstorage` package. Meteor\n  accounts logins no longer persist in IE7.\n\n* Fix the `localstorage` package when used with Safari in private\n  browsing mode. This fixes a problem with login token storage and\n  account login. [#1291](https://github.com/meteor/meteor/issues/1291)\n\n* Types added with `EJSON.addType` now have default `clone` and `equals`\n  implementations. Users may still specify `clone` or `equals` functions\n  to override the default behavior.  [#1745](https://github.com/meteor/meteor/issues/1745)\n\n* Add `frame-src` to `browser-policy-content` and account for\n  cross-browser CSP disparities.\n\n* Deprecate `Oauth.initiateLogin` in favor of `Oauth.showPopup`.\n\n* Add `WebApp.rawConnectHandlers` for adding connect handlers that run\n  before any other Meteor handlers, except `connect.compress()`. Raw\n  connect handlers see the URL's full path (even if ROOT_URL contains a\n  non-empty path) and they run before static assets are served.\n\n* Add `Accounts.connection` to allow using Meteor accounts packages with\n  a non-default DDP connection.\n\n* Detect and reload if minified CSS files fail to load at startup. This\n  prevents the application from running unstyled if the page load occurs\n  while the server is switching versions.\n\n* Allow Npm.depends to specify any http or https URL containing a full\n  40-hex-digit SHA.  [#1686](https://github.com/meteor/meteor/issues/1686)\n\n* Add `retry` package for connection retry with exponential backoff.\n\n* Pass `update` and `remove` return values correctly when using\n  collections validated with `allow` and `deny` rules. [#1759](https://github.com/meteor/meteor/issues/1759)\n\n* If you're using Deps on the server, computations and invalidation\n  functions are not allowed to yield. Throw an error instead of behaving\n  unpredictably.\n\n* Fix namespacing in coffeescript files added to a package with the\n  `bare: true` option. [#1668](https://github.com/meteor/meteor/issues/1668)\n\n* Fix races when calling login and/or logoutOtherClients from multiple\n  tabs. [#1616](https://github.com/meteor/meteor/issues/1616)\n\n* Include oauth_verifier as a header rather than a parameter in\n  the `oauth1` package. [#1825](https://github.com/meteor/meteor/issues/1825)\n\n* Fix `force-ssl` to allow local development with `meteor run` in IPv6\n  environments. [#1751](https://github.com/meteor/meteor/issues/1751)`\n\n* Allow cursors on named local collections to be returned from a publish\n  function in an array.  [#1820](https://github.com/meteor/meteor/issues/1820)\n\n* Fix build failure caused by a directory in `programs/` without a\n  package.js file.\n\n* Do a better job of handling shrinkwrap files when an npm module\n  depends on something that isn't a semver. [#1684](https://github.com/meteor/meteor/issues/1684)\n\n* Fix failures updating npm dependencies when a node_modules directory\n  exists above the project directory.  [#1761](https://github.com/meteor/meteor/issues/1761)\n\n* Preserve permissions (eg, executable bit) on npm files.  [#1808](https://github.com/meteor/meteor/issues/1808)\n\n* SockJS tweak to support relative base URLs.\n\n* Don't leak sockets on error in dev-mode proxy.\n\n* Clone arguments to `added` and `changed` methods in publish\n  functions. This allows callers to reuse objects and prevents already\n  published data from changing after the fact.  [#1750](https://github.com/meteor/meteor/issues/1750)\n\n* Ensure springboarding to a different meteor tools version always uses\n  `exec` to run the old version. This simplifies process management for\n  wrapper scripts.\n\nPatches contributed by GitHub users DenisGorbachev, EOT, OyoKooN, awwx,\ndandv, icellan, jfhamlin, marcandre, michaelbishop, mitar, mizzao,\nmquandalle, paulswartz, rdickert, rzymek, timhaines, and yeputons.\n\n\n## v0.7.0.1, 2013-Dec-20\n\n* Two fixes to `meteor run` Mongo startup bugs that could lead to hangs with the\n  message \"Initializing mongo database... this may take a moment.\".  [#1696](https://github.com/meteor/meteor/issues/1696)\n\n* Apply the Node patch to 0.10.24 as well (see the 0.7.0 section for details).\n\n* Fix gratuitous IE7 incompatibility.  [#1690](https://github.com/meteor/meteor/issues/1690)\n\n\n## v0.7.0, 2013-Dec-17\n\nThis version of Meteor contains a patch for a bug in Node 0.10 which\nmost commonly affects websockets. The patch is against Node version\n0.10.22 and 0.10.23. We strongly recommend using one of these precise\nversions of Node in production so that the patch will be applied. If you\nuse a newer version of Node with this version of Meteor, Meteor will not\napply the patch and will instead disable websockets.\n\n* Rework how Meteor gets realtime database updates from MongoDB. Meteor\n  now reads the MongoDB \"oplog\" -- a special collection that records all\n  the write operations as they are applied to your database. This means\n  changes to the database are instantly noticed and reflected in Meteor,\n  whether they originated from Meteor or from an external database\n  client. Oplog tailing is automatically enabled in development mode\n  with `meteor run`, and can be enabled in production with the\n  `MONGO_OPLOG_URL` environment variable. Currently the only supported\n  selectors are equality checks; `$`-operators, `limit` and `skip`\n  queries fall back to the original poll-and-diff algorithm. See\n  https://github.com/meteor/meteor/wiki/Oplog-Observe-Driver\n  for details.\n\n* Add `Meteor.onConnection` and add `this.connection` to method\n  invocations and publish functions. These can be used to store data\n  associated with individual clients between subscriptions and method\n  calls. See http://docs.meteor.com/#meteor_onconnection for details. [#1611](https://github.com/meteor/meteor/issues/1611)\n\n* Bundler failures cause non-zero exit code in `meteor run`.  [#1515](https://github.com/meteor/meteor/issues/1515)\n\n* Fix error when publish function callbacks are called during session shutdown.\n\n* Rework hot code push. The new `autoupdate` package drives automatic\n  reloads on update using standard DDP messages instead of a hardcoded\n  message at DDP startup. Now the hot code push only triggers when\n  client code changes; server-only code changes will not cause the page\n  to reload.\n\n* New `facts` package publishes internal statistics about Meteor.\n\n* Add an explicit check that publish functions return a cursor, an array\n  of cursors, or a falsey value. This is a safety check to to prevent\n  users from accidentally returning Collection.findOne() or some other\n  value and expecting it to be published.\n\n* Implement `$each`, `$sort`, and `$slice` options for minimongo's `$push`\n  modifier.  [#1492](https://github.com/meteor/meteor/issues/1492)\n\n* Introduce `--raw-logs` option to `meteor run` to disable log\n  coloring and timestamps.\n\n* Add `WebAppInternals.setBundledJsCssPrefix()` to control where the\n  client loads bundled JavaScript and CSS files. This allows serving\n  files from a CDN to decrease page load times and reduce server load.\n\n* Attempt to exit cleanly on `SIGHUP`. Stop accepting incoming\n  connections, kill DDP connections, and finish all outstanding requests\n  for static assets.\n\n* In the HTTP server, only keep sockets with no active HTTP requests alive for 5\n  seconds.\n\n* Fix handling of `fields` option in minimongo when only `_id` is present. [#1651](https://github.com/meteor/meteor/issues/1651)\n\n* Fix issue where setting `process.env.MAIL_URL` in app code would not\n  alter where mail was sent. This was a regression in 0.6.6 from 0.6.5. [#1649](https://github.com/meteor/meteor/issues/1649)\n\n* Use stderr instead of stdout (for easier automation in shell scripts) when\n  prompting for passwords and when downloading the dev bundle. [#1600](https://github.com/meteor/meteor/issues/1600)\n\n* Ensure more downtime during file watching.  [#1506](https://github.com/meteor/meteor/issues/1506)\n\n* Fix `meteor run` with settings files containing non-ASCII characters.  [#1497](https://github.com/meteor/meteor/issues/1497)\n\n* Support `EJSON.clone` for `Meteor.Error`. As a result, they are properly\n  stringified in DDP even if thrown through a `Future`.  [#1482](https://github.com/meteor/meteor/issues/1482)\n\n* Fix passing `transform: null` option to `collection.allow()` to disable\n  transformation in validators.  [#1659](https://github.com/meteor/meteor/issues/1659)\n\n* Fix livedata error on `this.removed` during session shutdown. [#1540](https://github.com/meteor/meteor/issues/1540) [#1553](https://github.com/meteor/meteor/issues/1553)\n\n* Fix incompatibility with Phusion Passenger by removing an unused line. [#1613](https://github.com/meteor/meteor/issues/1613)\n\n* Ensure install script creates /usr/local on machines where it does not\n  exist (eg. fresh install of OSX Mavericks).\n\n* Set x-forwarded-* headers in `meteor run`.\n\n* Clean up package dirs containing only \".build\".\n\n* Check for matching hostname before doing end-of-oauth redirect.\n\n* Only count files that actually go in the cache towards the `appcache`\n  size check. [#1653](https://github.com/meteor/meteor/issues/1653).\n\n* Increase the maximum size spiderable will return for a page from 200kB\n  to 5MB.\n\n* Upgraded dependencies:\n  * SockJS server from 0.3.7 to 0.3.8, including new faye-websocket module.\n  * Node from 0.10.21 to 0.10.22\n  * MongoDB from 2.4.6 to 2.4.8\n  * clean-css from 1.1.2 to 2.0.2\n  * uglify-js from a fork of 2.4.0 to 2.4.7\n  * handlebars npm module no longer available outside of handlebars package\n\nPatches contributed by GitHub users AlexeyMK, awwx, dandv, DenisGorbachev,\nemgee3, FooBarWidget, mitar, mcbain, rzymek, and sdarnell.\n\n\n## v0.6.6.3, 2013-Nov-04\n\n* Fix error when publish function callbacks are called during session\n  shutdown.  [#1540](https://github.com/meteor/meteor/issues/1540) [#1553](https://github.com/meteor/meteor/issues/1553)\n\n* Improve `meteor run` CPU usage in projects with many\n  directories.  [#1506](https://github.com/meteor/meteor/issues/1506)\n\n\n## v0.6.6.2, 2013-Oct-21\n\n* Upgrade Node from 0.10.20 to 0.10.21 (security update).\n\n\n## v0.6.6.1, 2013-Oct-12\n\n* Fix file watching on OSX. Work around Node issue [#6251](https://github.com/meteor/meteor/issues/6251) by not using\n  fs.watch. [#1483](https://github.com/meteor/meteor/issues/1483)\n\n\n## v0.6.6, 2013-Oct-10\n\n\n#### Security\n\n* Add `browser-policy` package for configuring and sending\n  Content-Security-Policy and X-Frame-Options HTTP headers.\n  [See the docs](http://docs.meteor.com/#browserpolicy) for more.\n\n* Use cryptographically strong pseudorandom number generators when available.\n\n#### MongoDB\n\n* Add upsert support. `Collection.update` now supports the `{upsert:\n  true}` option. Additionally, add a `Collection.upsert` method which\n  returns the newly inserted object id if applicable.\n\n* `update` and `remove` now return the number of documents affected.  [#1046](https://github.com/meteor/meteor/issues/1046)\n\n* `$near` operator for `2d` and `2dsphere` indices.\n\n* The `fields` option to the collection methods `find` and `findOne` now works\n  on the client as well.  (Operators such as `$elemMatch` and `$` are not yet\n  supported in `fields` projections.) [#1287](https://github.com/meteor/meteor/issues/1287)\n\n* Pass an index and the cursor itself to the callbacks in `cursor.forEach` and\n  `cursor.map`, just like the corresponding `Array` methods.  [#63](https://github.com/meteor/meteor/issues/63)\n\n* Support `c.find(query, {limit: N}).count()` on the client.  [#654](https://github.com/meteor/meteor/issues/654)\n\n* Improve behavior of `$ne`, `$nin`, and `$not` selectors with objects containing\n  arrays.  [#1451](https://github.com/meteor/meteor/issues/1451)\n\n* Fix various bugs if you had two documents with the same _id field in\n  String and ObjectID form.\n\n#### Accounts\n\n* [Behavior Change] Expire login tokens periodically. Defaults to 90\n  days. Use `Accounts.config({loginExpirationInDays: null})` to disable\n  token expiration.\n\n* [Behavior Change] Write dates generated by Meteor Accounts to Mongo as\n  Date instead of number; existing data can be converted by passing it\n  through `new Date()`. [#1228](https://github.com/meteor/meteor/issues/1228)\n\n* Log out and close connections for users if they are deleted from the\n  database.\n\n* Add Meteor.logoutOtherClients() for logging out other connections\n  logged in as the current user.\n\n* `restrictCreationByEmailDomain` option in `Accounts.config` to restrict new\n  users to emails of specific domain (eg. only users with @meteor.com emails) or\n  a custom validator. [#1332](https://github.com/meteor/meteor/issues/1332)\n\n* Support OAuth1 services that require request token secrets as well as\n  authentication token secrets.  [#1253](https://github.com/meteor/meteor/issues/1253)\n\n* Warn if `Accounts.config` is only called on the client.  [#828](https://github.com/meteor/meteor/issues/828)\n\n* Fix bug where callbacks to login functions could be called multiple\n  times when the client reconnects.\n\n#### DDP\n\n* Fix infinite loop if a client disconnects while a long yielding method is\n  running.\n\n* Unfinished code to support DDP session resumption has been removed. Meteor\n  servers now stop processing messages from clients and reclaim memory\n  associated with them as soon as they are disconnected instead of a few minutes\n  later.\n\n#### Tools\n\n* The pre-0.6.5 `Package.register_extension` API has been removed. Use\n  `Package._transitional_registerBuildPlugin` instead, which was introduced in\n  0.6.5. (A bug prevented the 0.6.5 reimplementation of `register_extension`\n  from working properly anyway.)\n\n* Support using an HTTP proxy in the `meteor` command line tool. This\n  allows the `update`, `deploy`, `logs`, and `mongo` commands to work\n  behind a proxy. Use the standard `http_proxy` environment variable to\n  specify your proxy endpoint.  [#429](https://github.com/meteor/meteor/issues/429), [#689](https://github.com/meteor/meteor/issues/689), [#1338](https://github.com/meteor/meteor/issues/1338)\n\n* Build Linux binaries on an older Linux machine. Meteor now supports\n  running on Linux machines with glibc 2.9 or newer (Ubuntu 10.04+, RHEL\n  and CentOS 6+, Fedora 10+, Debian 6+). Improve error message when running\n  on Linux with unsupported glibc, and include Mongo stderr if it fails\n  to start.\n\n* Install NPM modules with `--force` to avoid corrupted local caches.\n\n* Rebuild NPM modules in packages when upgrading to a version of Meteor that\n  uses a different version of Node.\n\n* Disable the Mongo http interface. This lets you run meteor on two ports\n  differing by 1000 at the same time.\n\n#### Misc\n\n* [Known issue] Breaks support for pre-release OSX 10.9 'Mavericks'.\n  Will be addressed shortly. See issues:\n  https://github.com/joyent/node/issues/6251\n  https://github.com/joyent/node/issues/6296\n\n* `EJSON.stringify` now takes options:\n  - `canonical` causes objects keys to be stringified in sorted order\n  - `indent` allows formatting control over the EJSON stringification\n\n* EJSON now supports `Infinity`, `-Infinity` and `NaN`.\n\n* Check that the argument to `EJSON.parse` is a string.  [#1401](https://github.com/meteor/meteor/issues/1401)\n\n* Better error from functions that use `Meteor._wrapAsync` (eg collection write\n  methods and `HTTP` methods) and in DDP server message processing.  [#1387](https://github.com/meteor/meteor/issues/1387)\n\n* Support `appcache` on Chrome for iOS.\n\n* Support literate CoffeeScript files with the extension `.coffee.md` (in\n  addition to the already-supported `.litcoffee` extension). [#1407](https://github.com/meteor/meteor/issues/1407)\n\n* Make `madewith` package work again (broken in 0.6.5).  [#1448](https://github.com/meteor/meteor/issues/1448)\n\n* Better error when passing a string to `{{#each}}`. [#722](https://github.com/meteor/meteor/issues/722)\n\n* Add support for JSESSIONID cookies for sticky sessions. Set the\n  `USE_JSESSIONID` environment variable to enable placing a JSESSIONID\n  cookie on sockjs requests.\n\n* Simplify the static analysis used to detect package-scope variables.\n\n* Upgraded dependencies:\n  * Node from 0.8.24 to 0.10.20\n  * MongoDB from 2.4.4 to 2.4.6\n  * MongoDB driver from 1.3.17 to 1.3.19\n  * http-proxy from 0.10.1 to a pre-release of 1.0.0\n  * stylus from 0.30.1 to 0.37.0\n  * nib from 0.8.2 to 1.0.0\n  * optimist from 0.3.5 to 0.6.0\n  * semver from 1.1.0 to 2.1.0\n  * request from 2.12.0 to 2.27.0\n  * keypress from 0.1.0 to 0.2.1\n  * underscore from 1.5.1 to 1.5.2\n  * fstream from 0.1.21 to 0.1.24\n  * tar from 0.1.14 to 0.1.18\n  * source-map from 0.1.26 to 0.1.30\n  * source-map-support from a fork of 0.1.8 to 0.2.3\n  * escope from a fork of 0.0.15 to 1.0.0\n  * estraverse from 1.1.2-1 to 1.3.1\n  * simplesmtp from 0.1.25 to 0.3.10\n  * stream-buffers from 0.2.3 to 0.2.5\n  * websocket from 1.0.7 to 1.0.8\n  * cli-color from 0.2.2 to 0.2.3\n  * clean-css from 1.0.11 to 1.1.2\n  * UglifyJS2 from a fork of 2.3.6 to a different fork of 2.4.0\n  * connect from 2.7.10 to 2.9.0\n  * send from 0.1.0 to 0.1.4\n  * useragent from 2.0.1 to 2.0.7\n  * replaced byline with eachline 2.3.3\n\nPatches contributed by GitHub users ansman, awwx, codeinthehole, jacott,\nMaxhodges, meawoppl, mitar, mizzao, mquandalle, nathan-muir, RobertLowe, ryw,\nsdarnell, and timhaines.\n\n\n## v0.6.5.3, 2014-Dec-09 (backport)\n\n* Fix a security issue in allow/deny rules that could result in data\n  loss. If your app uses allow/deny rules, or uses packages that use\n  allow/deny rules, we recommend that you update immediately.\n  Backport from 1.0.1.\n\n\n## v0.6.5.2, 2013-Oct-21\n\n* Upgrade Node from 0.8.24 to 0.8.26 (security patch)\n\n\n## v0.6.5.1, 2013-Aug-28\n\n* Fix syntax errors on lines that end with a backslash. [#1326](https://github.com/meteor/meteor/issues/1326)\n\n* Fix serving static files with special characters in their name. [#1339](https://github.com/meteor/meteor/issues/1339)\n\n* Upgrade `esprima` JavaScript parser to fix bug parsing complex regexps.\n\n* Export `Spiderable` from `spiderable` package to allow users to set\n  `Spiderable.userAgentRegExps` to control what user agents are treated\n  as spiders.\n\n* Add EJSON to standard-app-packages. [#1343](https://github.com/meteor/meteor/issues/1343)\n\n* Fix bug in d3 tab character parsing.\n\n* Fix regression when using Mongo ObjectIDs in Spark templates.\n\n\n## v0.6.5, 2013-Aug-14\n\n* New package system with package compiler and linker:\n\n  * Each package now has it own namespace for variable\n    declarations. Global variables used in a package are limited to\n    package scope.\n\n  * Packages must explicitly declare which symbols they export with\n    `api.export` in `package.js`.\n\n  * Apps and packages only see the exported symbols from packages they\n    explicitly use. For example, if your app uses package A which in\n    turn depends on package B, only package A's symbols will be\n    available in the app.\n\n  * Package names can only contain alphanumeric characters, dashes, and\n    dots. Packages with spaces and underscores must be renamed.\n\n  * Remove hardcoded list of required packages. New default\n    `standard-app-packages` package adds dependencies on the core Meteor\n    stack. This package can be removed to make an app with only parts of\n    the Meteor stack. `standard-app-packages` will be automatically\n    added to a project when it is updated to Meteor 0.6.5.\n\n  * Custom app packages in the `packages` directory are no longer\n    automatically used. They must be explicitly added to the app with\n    `meteor add <packagename>`. To help with the transition, all\n    packages in the `packages` directory will be automatically added to\n    the project when it is updated to Meteor 0.6.5.\n\n  * New \"unipackage\" on-disk format for built packages. Compiled packages are\n    cached and rebuilt only when their source or dependencies change.\n\n  * Add \"unordered\" and \"weak\" package dependency modes to allow\n    circular package dependencies and conditional code inclusion.\n\n  * New API (`_transitional_registerBuildPlugin`) for declaring\n    compilers, preprocessors, and file extension handlers. These new\n    build plugins are full compilation targets in their own right, and\n    have their own namespace, source files, NPM requirements, and package\n    dependencies. The old `register_extension` API is deprecated. Please\n    note that the `package.js` format and especially\n    `_transitional_registerBuildPlugin` are not frozen interfaces and\n    are subject to change in future releases.\n\n  * Add `api.imply`, which allows one package to \"imply\" another. If\n    package A implies package B, then anything that depends on package\n    A automatically depends on package B as well (and receives package\n    B's imports). This is useful for creating umbrella packages\n    (`standard-app-packages`) or sometimes for factoring common code\n    out of related packages (`accounts-base`).\n\n* Move HTTP serving out of the server bootstrap and into the `webapp`\n  package. This allows building Meteor apps that are not web servers\n  (eg. command line tools, DDP clients, etc.). Connect middlewares can\n  now be registered on the new `WebApp.connectHandlers` instead of the\n  old `__meteor_bootstrap__.app`.\n\n* The entire Meteor build process now has first-class source map\n  support. A source map is maintained for every source file as it\n  passes through the build pipeline. Currently, the source maps are\n  only served in development mode. Not all web browsers support source\n  maps yet and for those that do, you may have to turn on an option to\n  enable them. Source maps will always be used when reporting\n  exceptions on the server.\n\n* Update the `coffeescript` package to generate source maps.\n\n* Add new `Assets` API and `private` subdirectory for including and\n  accessing static assets on the server. http://docs.meteor.com/#assets\n\n* Add `Meteor.disconnect`. Call this to disconnect from the\n  server and stop all live data updates. [#1151](https://github.com/meteor/meteor/issues/1151)\n\n* Add `Match.Integer` to `check` for 32-bit signed integers.\n\n* `Meteor.connect` has been renamed to `DDP.connect` and is now fully\n  supported on the server. Server-to-server DDP connections use\n  websockets, and can be used for both method calls and subscriptions.\n\n* Rename `Meteor.default_connection` to `Meteor.connection` and\n  `Meteor.default_server` to `Meteor.server`.\n\n* Rename `Meteor.http` to `HTTP`.\n\n* `ROOT_URL` may now have a path part. This allows serving multiple\n  Meteor apps on the same domain.\n\n* Support creating named unmanaged collections with\n  `new Meteor.Collection(\"name\", {connection: null})`.\n\n* New `Log` function in the `logging` package which prints with\n  timestamps, color, filenames and linenumbers.\n\n* Include http response in errors from oauth providers. [#1246](https://github.com/meteor/meteor/issues/1246)\n\n* The `observe` callback `movedTo` now has a fourth argument `before`.\n\n* Move NPM control files for packages from `.npm` to\n  `.npm/package`. This is to allow build plugins such as `coffeescript`\n  to depend on NPM packages. Also, when removing the last NPM\n  dependency, clean up the `.npm` dir.\n\n* Remove deprecated `Meteor.is_client` and `Meteor.is_server` variables.\n\n* Implement \"meteor bundle --debug\" [#748](https://github.com/meteor/meteor/issues/748)\n\n* Add `forceApprovalPrompt` option to `Meteor.loginWithGoogle`. [#1226](https://github.com/meteor/meteor/issues/1226)\n\n* Make server-side Mongo `insert`s, `update`s, and `remove`s run\n  asynchronously when a callback is passed.\n\n* Improve memory usage when calling `findOne()` on the server.\n\n* Delete login tokens from server when user logs out.\n\n* Rename package compatibility mode option to `add_files` from `raw` to\n  `bare`.\n\n* Fix Mongo selectors of the form: {$regex: /foo/}.\n\n* Fix Spark memory leak.  [#1157](https://github.com/meteor/meteor/issues/1157)\n\n* Fix EPIPEs during dev mode hot code reload.\n\n* Fix bug where we would never quiesce if we tried to revive subs that errored\n  out (5e7138d)\n\n* Fix bug where `this.fieldname` in handlebars template might refer to a\n  helper instead of a property of the current data context. [#1143](https://github.com/meteor/meteor/issues/1143)\n\n* Fix submit events on IE8. [#1191](https://github.com/meteor/meteor/issues/1191)\n\n* Handle `Meteor.loginWithX` being called with a callback but no options. [#1181](https://github.com/meteor/meteor/issues/1181)\n\n* Work around a Chrome bug where hitting reload could cause a tab to\n  lose the DDP connection and never recover. [#1244](https://github.com/meteor/meteor/issues/1244)\n\n* Upgraded dependencies:\n  * Node from 0.8.18 to 0.8.24\n  * MongoDB from 2.4.3 to 2.4.4, now with SSL support\n  * CleanCSS from 0.8.3 to 1.0.11\n  * Underscore from 1.4.4 to 1.5.1\n  * Fibers from 1.0.0 to 1.0.1\n  * MongoDB Driver from 1.3.7 to 1.3.17\n\nPatches contributed by GitHub users btipling, mizzao, timhaines and zol.\n\n\n## v0.6.4.1, 2013-Jul-19\n\n* Update mongodb driver to use version 0.2.1 of the bson module.\n\n\n## v0.6.4, 2013-Jun-10\n\n* Separate OAuth flow logic from Accounts into separate packages. The\n  `facebook`, `github`, `google`, `meetup`, `twitter`, and `weibo`\n  packages can be used to perform an OAuth exchange without creating an\n  account and logging in.  [#1024](https://github.com/meteor/meteor/issues/1024)\n\n* If you set the `DISABLE_WEBSOCKETS` environment variable, browsers will not\n  attempt to connect to your app using Websockets. Use this if you know your\n  server environment does not properly proxy Websockets to reduce connection\n  startup time.\n\n* Make `Meteor.defer` work in an inactive tab in iOS.  [#1023](https://github.com/meteor/meteor/issues/1023)\n\n* Allow new `Random` instances to be constructed with specified seed. This\n  can be used to create repeatable test cases for code that picks random\n  values.  [#1033](https://github.com/meteor/meteor/issues/1033)\n\n* Fix CoffeeScript error reporting to include source file and line\n  number again.  [#1052](https://github.com/meteor/meteor/issues/1052)\n\n* Fix Mongo queries which nested JavaScript RegExp objects inside `$or`.  [#1089](https://github.com/meteor/meteor/issues/1089)\n\n* Upgraded dependencies:\n  * Underscore from 1.4.2 to 1.4.4  [#776](https://github.com/meteor/meteor/issues/776)\n  * http-proxy from 0.8.5 to 0.10.1  [#513](https://github.com/meteor/meteor/issues/513)\n  * connect from 1.9.2 to 2.7.10\n  * Node mongodb client from 1.2.13 to 1.3.7  [#1060](https://github.com/meteor/meteor/issues/1060)\n\nPatches contributed by GitHub users awwx, johnston, and timhaines.\n\n\n## v0.6.3, 2013-May-15\n\n* Add new `check` package for ensuring that a value matches a required\n  type and structure. This is used to validate untrusted input from the\n  client. See http://docs.meteor.com/#match for details.\n\n* Use Websockets by default on supported browsers. This reduces latency\n  and eliminates the constant network spinner on iOS devices.\n\n* With `autopublish` on, publish many useful fields on `Meteor.users`.\n\n* Files in the `client/compatibility/` subdirectory of a Meteor app do\n  not get wrapped in a new variable scope. This is useful for\n  third-party libraries which expect `var` statements at the outermost\n  level to be global.\n\n* Add synthetic `tap` event for use on touch enabled devices. This is a\n  replacement for `click` that fires immediately.\n\n* When using the `http` package synchronously on the server, errors\n  are thrown rather than passed in `result.error`\n\n* The `manager` option to the `Meteor.Collection` constructor is now called\n  `connection`. The old name still works for now.  [#987](https://github.com/meteor/meteor/issues/987)\n\n* The `localstorage-polyfill` smart package has been replaced by a\n  `localstorage` package, which defines a `Meteor._localStorage` API instead of\n  trying to replace the DOM `window.localStorage` facility. (Now, apps can use\n  the existence of `window.localStorage` to detect if the full localStorage API\n  is supported.)  [#979](https://github.com/meteor/meteor/issues/979)\n\n* Upgrade MongoDB from 2.2.1 to 2.4.3.\n\n* Upgrade CoffeeScript from 1.5.0 to 1.6.2.  [#972](https://github.com/meteor/meteor/issues/972)\n\n* Faster reconnects when regaining connectivity.  [#696](https://github.com/meteor/meteor/issues/696)\n\n* `Email.send` has a new `headers` option to set arbitrary headers.  [#963](https://github.com/meteor/meteor/issues/963)\n\n* Cursor transform functions on the server no longer are required to return\n  objects with correct `_id` fields.  [#974](https://github.com/meteor/meteor/issues/974)\n\n* Rework `observe()` callback ordering in minimongo to improve fiber\n  safety on the server. This makes subscriptions on server to server DDP\n  more usable.\n\n* Use binary search in minimongo when updating ordered queries.  [#969](https://github.com/meteor/meteor/issues/969)\n\n* Fix EJSON base64 decoding bug.  [#1001](https://github.com/meteor/meteor/issues/1001)\n\n* Support `appcache` on Chromium.  [#958](https://github.com/meteor/meteor/issues/958)\n\nPatches contributed by GitHub users awwx, jagill, spang, and timhaines.\n\n\n## v0.6.2.1, 2013-Apr-24\n\n* When authenticating with GitHub, include a user agent string. This\n  unbreaks \"Sign in with GitHub\"\n\nPatch contributed by GitHub user pmark.\n\n\n## v0.6.2, 2013-Apr-16\n\n* Better error reporting:\n  * Capture real stack traces for `Meteor.Error`.\n  * Report better errors with misconfigured OAuth services.\n\n* Add per-package upgrade notices to `meteor update`.\n\n* Experimental server-to-server DDP support: `Meteor.connect` on the\n  server will connect to a remote DDP endpoint via WebSockets. Method\n  calls should work fine, but subscriptions and minimongo on the server\n  are still a work in progress.\n\n* Upgrade d3 from 2.x to 3.1.4. See\n  https://github.com/mbostock/d3/wiki/Upgrading-to-3.0 for compatibility notes.\n\n* Allow CoffeeScript to set global variables when using `use strict`. [#933](https://github.com/meteor/meteor/issues/933)\n\n* Return the inserted documented ID from `LocalCollection.insert`. [#908](https://github.com/meteor/meteor/issues/908)\n\n* Add Weibo token expiration time to `services.weibo.expiresAt`.\n\n* `Spiderable.userAgentRegExps` can now be modified to change what user agents\n  are treated as spiders by the `spiderable` package.\n\n* Prevent observe callbacks from affecting the arguments to identical\n  observes. [#855](https://github.com/meteor/meteor/issues/855)\n\n* Fix meteor command line tool when run from a home directory with\n  spaces in its name. If you previously installed meteor release 0.6.0\n  or 0.6.1 you'll need to uninstall and reinstall meteor to support\n  users with spaces in their usernames (see\n  https://github.com/meteor/meteor/blob/master/README.md#uninstalling-meteor)\n\nPatches contributed by GitHub users andreas-karlsson, awwx, jacott,\njoshuaconner, and timhaines.\n\n\n## v0.6.1, 2013-Apr-08\n\n* Correct NPM behavior in packages in case there is a `node_modules` directory\n  somewhere above the app directory. [#927](https://github.com/meteor/meteor/issues/927)\n\n* Small bug fix in the low-level `routepolicy` package.\n\nPatches contributed by GitHub users andreas-karlsson and awwx.\n\n\n## v0.6.0, 2013-Apr-04\n\n* Meteor has a brand new distribution system! In this new system, code-named\n  Engine, packages are downloaded individually and on demand. All of the\n  packages in each official Meteor release are prefetched and cached so you can\n  still use Meteor while offline. You can have multiple releases of Meteor\n  installed simultaneously; apps are pinned to specific Meteor releases.\n  All `meteor` commands accept a `--release` argument to specify which release\n  to use; `meteor update` changes what release the app is pinned to.\n  Inside an app, the name of the release is available at `Meteor.release`.\n  When running Meteor directly from a git checkout, the release is ignored.\n\n* Variables declared with `var` at the outermost level of a JavaScript\n  source file are now private to that file. Remove the `var` to share\n  a value between files.\n\n* Meteor now supports any x86 (32- or 64-bit) Linux system, not just those which\n  use Debian or RedHat package management.\n\n* Apps may contain packages inside a top-level directory named `packages`.\n\n* Packages may depend on [NPM modules](https://npmjs.org), using the new\n  `Npm.depends` directive in their `package.js` file. (Note: if the NPM module\n  has architecture-specific binary components, bundles built with `meteor\n  bundle` or `meteor deploy` will contain the components as built for the\n  developer's platform and may not run on other platforms.)\n\n* Meteor's internal package tests (as well as tests you add to your app's\n  packages with the unsupported `Tinytest` framework) are now run with the new\n  command `meteor test-packages`.\n\n* `{{#each}}` helper can now iterate over falsey values without throwing an\n  exception. [#815](https://github.com/meteor/meteor/issues/815), [#801](https://github.com/meteor/meteor/issues/801)\n\n* `{{#with}}` helper now only includes its block if its argument is not falsey,\n  and runs an `{{else}}` block if provided if the argument is falsey. [#770](https://github.com/meteor/meteor/issues/770), [#866](https://github.com/meteor/meteor/issues/866)\n\n* Twitter login now stores `profile_image_url` and `profile_image_url_https`\n  attributes in the `user.services.twitter` namespace. [#788](https://github.com/meteor/meteor/issues/788)\n\n* Allow packages to register file extensions with dots in the filename.\n\n* When calling `this.changed` in a publish function, it is no longer an error to\n  clear a field which was never set. [#850](https://github.com/meteor/meteor/issues/850)\n\n* Deps API\n  * Add `dep.depend()`, deprecate `Deps.depend(dep)` and\n    `dep.addDependent()`.\n  * If first run of `Deps.autorun` throws an exception, stop it and don't\n    rerun.  This prevents a Spark exception when template rendering fails\n    (\"Can't call 'firstNode' of undefined\").\n  * If an exception is thrown during `Deps.flush` with no stack, the\n    message is logged instead. [#822](https://github.com/meteor/meteor/issues/822)\n\n* When connecting to MongoDB, use the JavaScript BSON parser unless specifically\n  requested in `MONGO_URL`; the native BSON parser sometimes segfaults. (Meteor\n  only started using the native parser in 0.5.8.)\n\n* Calls to the `update` collection function in untrusted code may only use a\n  whitelisted list of modifier operators.\n\nPatches contributed by GitHub users awwx, blackcoat, cmather, estark37,\nmquandalle, Primigenus, raix, reustle, and timhaines.\n\n\n## v0.5.9, 2013-Mar-14\n\n* Fix regression in 0.5.8 that prevented users from editing their own\n  profile. [#809](https://github.com/meteor/meteor/issues/809)\n\n* Fix regression in 0.5.8 where `Meteor.loggingIn()` would not update\n  reactively. [#811](https://github.com/meteor/meteor/issues/811)\n\n\n## v0.5.8, 2013-Mar-13\n\n* Calls to the `update` and `remove` collection functions in untrusted code may\n  no longer use arbitrary selectors. You must specify a single document ID when\n  invoking these functions from the client (other than in a method stub).\n\n  You may still use other selectors when calling `update` and `remove` on the\n  server and from client method stubs, so you can replace calls that are no\n  longer supported (eg, in event handlers) with custom method calls.\n\n  The corresponding `update` and `remove` callbacks passed to `allow` and `deny`\n  now take a single document instead of an array.\n\n* Add new `appcache` package. Add this package to your project to speed\n  up page load and make hot code reload smoother using the HTML5\n  AppCache API. See http://docs.meteor.com/#appcache for details.\n\n* Rewrite reactivity library. `Meteor.deps` is now `Deps` and has a new\n  API. `Meteor.autorun` and `Meteor.flush` are now called `Deps.autorun` and\n  `Deps.flush` (the old names still work for now). The other names under\n  `Meteor.deps` such as `Context` no longer exist. The new API is documented at\n  http://docs.meteor.com/#deps\n\n* You can now provide a `transform` option to collections, which is a\n  function that documents coming out of that collection are passed\n  through. `find`, `findOne`, `allow`, and `deny` now take `transform` options,\n  which may override the Collection's `transform`.  Specifying a `transform`\n  of `null` causes you to receive the documents unmodified.\n\n* Publish functions may now return an array of cursors to publish. Currently,\n  the cursors must all be from different collections. [#716](https://github.com/meteor/meteor/issues/716)\n\n* User documents have id's when `onCreateUser` and `validateNewUser` hooks run.\n\n* Encode and store custom EJSON types in MongoDB.\n\n* Support literate CoffeeScript files with the extension `.litcoffee`. [#766](https://github.com/meteor/meteor/issues/766)\n\n* Add new login service provider for Meetup.com in `accounts-meetup` package.\n\n* If you call `observe` or `observeChanges` on a cursor created with the\n  `reactive: false` option, it now only calls initial add callbacks and\n  does not continue watching the query. [#771](https://github.com/meteor/meteor/issues/771)\n\n* In an event handler, if the data context is falsey, default it to `{}`\n  rather than to the global object. [#777](https://github.com/meteor/meteor/issues/777)\n\n* Allow specifying multiple event handlers for the same selector. [#753](https://github.com/meteor/meteor/issues/753)\n\n* Revert caching header change from 0.5.5. This fixes image flicker on redraw.\n\n* Stop making `Session` available on the server; it's not useful there. [#751](https://github.com/meteor/meteor/issues/751)\n\n* Force URLs in stack traces in browser consoles to be hyperlinks. [#725](https://github.com/meteor/meteor/issues/725)\n\n* Suppress spurious `changed` callbacks with empty `fields` from\n  `Cursor.observeChanges`.\n\n* Fix logic bug in template branch matching. [#724](https://github.com/meteor/meteor/issues/724)\n\n* Make `spiderable` user-agent test case insensitive. [#721](https://github.com/meteor/meteor/issues/721)\n\n* Fix several bugs in EJSON type support:\n  * Fix `{$type: 5}` selectors for binary values on browsers that do\n    not support `Uint8Array`.\n  * Fix EJSON equality on falsey values.\n  * Fix for returning a scalar EJSON type from a method. [#731](https://github.com/meteor/meteor/issues/731)\n\n* Upgraded dependencies:\n  * mongodb driver to version 1.2.13 (from 0.1.11)\n  * mime module removed (it was unused)\n\n\nPatches contributed by GitHub users awwx, cmather, graemian, jagill,\njmhredsox, kevinxucs, krizka, mitar, raix, and rasmuserik.\n\n\n## v0.5.7, 2013-Feb-21\n\n* The DDP wire protocol has been redesigned.\n\n  * The handshake message is now versioned. This breaks backwards\n    compatibility between sites with `Meteor.connect()`. Older meteor\n    apps can not talk to new apps and vice versa. This includes the\n    `madewith` package, apps using `madewith` must upgrade.\n\n  * New [EJSON](http://docs.meteor.com/#ejson) package allows you to use\n    Dates, Mongo ObjectIDs, and binary data in your collections and\n    Session variables.  You can also add your own custom datatypes.\n\n  * Meteor now correctly represents empty documents in Collections.\n\n  * There is an informal specification in `packages/livedata/DDP.md`.\n\n\n* Breaking API changes\n\n  * Changed the API for `observe`.  Observing with `added`, `changed`\n    and `removed` callbacks is now unordered; for ordering information\n    use `addedAt`, `changedAt`, `removedAt`, and `movedTo`. Full\n    documentation is in the [`observe` docs](http://docs.meteor.com/#observe).\n    All callers of `observe` need to be updated.\n\n  * Changed the API for publish functions that do not return a cursor\n    (ie functions that call `this.set` and `this.unset`). See the\n    [`publish` docs](http://docs.meteor.com/#meteor_publish) for the new\n    API.\n\n\n* New Features\n\n  * Added new [`observeChanges`](http://docs.meteor.com/#observe_changes)\n    API for keeping track of the contents of a cursor more efficiently.\n\n  * There is a new reactive function on subscription handles: `ready()`\n    returns true when the subscription has received all of its initial\n    documents.\n\n  * Added `Session.setDefault(key, value)` so you can easily provide\n    initial values for session variables that will not be clobbered on\n    hot code push.\n\n  * You can specify that a collection should use MongoDB ObjectIDs as\n    its `_id` fields for inserts instead of strings. This allows you to\n    use Meteor with existing MongoDB databases that have ObjectID\n    `_id`s. If you do this, you must use `EJSON.equals()` for comparing\n    equality instead of `===`. See http://docs.meteor.com/#meteor_collection.\n\n  * New [`random` package](http://docs.meteor.com/#random) provides\n    several functions for generating random values. The new\n    `Random.id()` function is used to provide shorter string IDs for\n    MongoDB documents. `Meteor.uuid()` is deprecated.\n\n  * `Meteor.status()` can return the status `failed` if DDP version\n    negotiation fails.\n\n\n* Major Performance Enhancements\n\n  * Rewrote subscription duplication detection logic to use a more\n    efficient algorithm. This significantly reduces CPU usage on the\n    server during initial page load and when dealing with large amounts\n    of data.\n\n  * Reduced unnecessary MongoDB re-polling of live queries. Meteor no\n    longer polls for changes on queries that specify `_id` when\n    updates for a different specific `_id` are processed. This\n    drastically improves performance when dealing with many\n    subscriptions and updates to individual objects, such as those\n    generated by the `accounts-base` package on the `Meteor.users`\n    collection.\n\n\n* Upgraded UglifyJS2 to version 2.2.5\n\n\nPatches contributed by GitHub users awwx and michaelglenadams.\n\n\n## v0.5.6, 2013-Feb-15\n\n* Fix 0.5.5 regression: Minimongo selectors matching subdocuments under arrays\n  did not work correctly.\n\n* Some Bootstrap icons should have appeared white.\n\nPatches contributed by GitHub user benjaminchelli.\n\n## v0.5.5, 2013-Feb-13\n\n* Deprecate `Meteor.autosubscribe`. `Meteor.subscribe` now works within\n  `Meteor.autorun`.\n\n* Allow access to `Meteor.settings.public` on the client. If the JSON\n  file you gave to `meteor --settings` includes a field called `public`,\n  that field will be available on the client as well as the server.\n\n* `@import` works in `less`. Use the `.lessimport` file extension to\n  make a less file that is ignored by preprocessor so as to avoid double\n  processing. [#203](https://github.com/meteor/meteor/issues/203)\n\n* Upgrade Fibers to version 1.0.0. The `Fiber` and `Future` symbols are\n  no longer exposed globally. To use fibers directly you can use:\n   `var Fiber = __meteor_bootstrap__.require('fibers');` and\n   `var Future = __meteor_bootstrap__.require('fibers/future');`\n\n* Call version 1.1 of the Twitter API when authenticating with\n  OAuth. `accounts-twitter` users have until March 5th, 2013 to\n  upgrade before Twitter disables the old API. [#527](https://github.com/meteor/meteor/issues/527)\n\n* Treat Twitter ids as strings, not numbers, as recommended by\n  Twitter. [#629](https://github.com/meteor/meteor/issues/629)\n\n* You can now specify the `_id` field of a document passed to `insert`.\n  Meteor still auto-generates `_id` if it is not present.\n\n* Expose an `invalidated` flag on `Meteor.deps.Context`.\n\n* Populate user record with additional data from Facebook and Google. [#664](https://github.com/meteor/meteor/issues/664)\n\n* Add Facebook token expiration time to `services.facebook.expiresAt`. [#576](https://github.com/meteor/meteor/issues/576)\n\n* Allow piping a password to `meteor deploy` on `stdin`. [#623](https://github.com/meteor/meteor/issues/623)\n\n* Correctly type cast arguments to handlebars helper. [#617](https://github.com/meteor/meteor/issues/617)\n\n* Fix leaked global `userId` symbol.\n\n* Terminate `phantomjs` properly on error when using the `spiderable`\n  package. [#571](https://github.com/meteor/meteor/issues/571)\n\n* Stop serving non-cachable files with caching headers. [#631](https://github.com/meteor/meteor/issues/631)\n\n* Fix race condition if server restarted between page load and initial\n  DDP connection. [#653](https://github.com/meteor/meteor/issues/653)\n\n* Resolve issue where login methods sometimes blocked future methods. [#555](https://github.com/meteor/meteor/issues/555)\n\n* Fix `Meteor.http` parsing of JSON responses on Firefox. [#553](https://github.com/meteor/meteor/issues/553)\n\n* Minimongo no longer uses `eval`. [#480](https://github.com/meteor/meteor/issues/480)\n\n* Serve 404 for `/app.manifest`. This allows experimenting with the\n  upcoming `appcache` smart package. [#628](https://github.com/meteor/meteor/issues/628)\n\n* Upgraded many dependencies, including:\n  * node.js to version 0.8.18\n  * jquery-layout to version 1.3.0RC\n  * Twitter Bootstrap to version 2.3.0\n  * Less to version 1.3.3\n  * Uglify to version 2.2.3\n  * useragent to version 2.0.1\n\nPatches contributed by GitHub users awwx, bminer, bramp, crunchie84,\ndanawoodman, dbimmler, Ed-von-Schleck, geoffd123, jperl, kevee,\nmilesmatthias, Primigenus, raix, timhaines, and xenolf.\n\n\n## v0.5.4, 2013-Jan-08\n\n* Fix 0.5.3 regression: `meteor run` could fail on OSX 10.8 if environment\n  variables such as `DYLD_LIBRARY_PATH` are set.\n\n\n## v0.5.3, 2013-Jan-07\n\n* Add `--settings` argument to `meteor deploy` and `meteor run`. This\n  allows you to specify deployment-specific information made available\n  to server code in the variable `Meteor.settings`.\n\n* Support unlimited open tabs in a single browser. Work around the\n  browser per-hostname connection limit by using randomized hostnames\n  for deployed apps. [#131](https://github.com/meteor/meteor/issues/131)\n\n* minimongo improvements:\n  * Allow observing cursors with `skip` or `limit`.  [#528](https://github.com/meteor/meteor/issues/528)\n  * Allow sorting on `dotted.sub.keys`.  [#533](https://github.com/meteor/meteor/issues/533)\n  * Allow querying specific array elements (`foo.1.bar`).\n  * `$and`, `$or`, and `$nor` no longer accept empty arrays (for consistency\n    with Mongo)\n\n* Re-rendering a template with Spark no longer reverts changes made by\n  users to a `preserve`d form element. Instead, the newly rendered value\n  is only applied if it is different from the previously rendered value.\n  Additionally, `<INPUT>` elements with type other than TEXT can now have\n  reactive values (eg, the labels on submit buttons can now be\n  reactive).  [#510](https://github.com/meteor/meteor/issues/510) [#514](https://github.com/meteor/meteor/issues/514) [#523](https://github.com/meteor/meteor/issues/523) [#537](https://github.com/meteor/meteor/issues/537) [#558](https://github.com/meteor/meteor/issues/558)\n\n* Support JavaScript RegExp objects in selectors in Collection write\n  methods on the client, eg `myCollection.remove({foo: /bar/})`.  [#346](https://github.com/meteor/meteor/issues/346)\n\n* `meteor` command-line improvements:\n  * Improve error message when mongod fails to start.\n  * The `NODE_OPTIONS` environment variable can be used to pass command-line\n    flags to node (eg, `--debug` or `--debug-brk` to enable the debugger).\n  * Die with error if an app name is mistakenly passed to `meteor reset`.\n\n* Add support for \"offline\" access tokens with Google login. [#464](https://github.com/meteor/meteor/issues/464) [#525](https://github.com/meteor/meteor/issues/525)\n\n* Don't remove `serviceData` fields from previous logins when logging in\n  with an external service.\n\n* Improve `OAuth1Binding` to allow making authenticated API calls to\n  OAuth1 providers (eg Twitter).  [#539](https://github.com/meteor/meteor/issues/539)\n\n* New login providers automatically work with `{{loginButtons}}` without\n  needing to edit the `accounts-ui-unstyled` package.  [#572](https://github.com/meteor/meteor/issues/572)\n\n* Use `Content-Type: application/json` by default when sending JSON data\n  with `Meteor.http`.\n\n* Improvements to `jsparse`: hex literals, keywords as property names, ES5 line\n  continuations, trailing commas in object literals, line numbers in error\n  messages, decimal literals starting with `.`, regex character classes with\n  slashes.\n\n* Spark improvements:\n  * Improve rendering of `<SELECT>` elements on IE.  [#496](https://github.com/meteor/meteor/issues/496)\n  * Don't lose nested data contexts in IE9/10 after two seconds.  [#458](https://github.com/meteor/meteor/issues/458)\n  * Don't print a stack trace if DOM nodes are manually removed\n    from the document without calling `Spark.finalize`.  [#392](https://github.com/meteor/meteor/issues/392)\n\n* Always use the `autoReconnect` flag when connecting to Mongo.  [#425](https://github.com/meteor/meteor/issues/425)\n\n* Fix server-side `observe` with no `added` callback.  [#589](https://github.com/meteor/meteor/issues/589)\n\n* Fix re-sending method calls on reconnect.  [#538](https://github.com/meteor/meteor/issues/538)\n\n* Remove deprecated `/sockjs` URL support from `Meteor.connect`.\n\n* Avoid losing a few bits of randomness in UUID v4 creation.  [#519](https://github.com/meteor/meteor/issues/519)\n\n* Update clean-css package from 0.8.2 to 0.8.3, fixing minification of `0%`\n  values in `hsl` colors.  [#515](https://github.com/meteor/meteor/issues/515)\n\nPatches contributed by GitHub users Ed-von-Schleck, egtann, jwulf, lvbreda,\nmartin-naumann, meawoppl, nwmartin, timhaines, and zealoushacker.\n\n\n## v0.5.2, 2012-Nov-27\n\n* Fix 0.5.1 regression: Cursor `observe` works during server startup.  [#507](https://github.com/meteor/meteor/issues/507)\n\n## v0.5.1, 2012-Nov-20\n\n* Speed up server-side subscription handling by avoiding redundant work\n  when the same Mongo query is observed multiple times concurrently (eg,\n  by multiple users subscribing to the same subscription), and by using\n  a simpler \"unordered\" algorithm.\n\n* Meteor now waits to invoke method callbacks until all the data written by the\n  method is available in the local cache. This way, method callbacks can see the\n  full effects of their writes. This includes the callbacks passed to\n  `Meteor.call` and `Meteor.apply`, as well as to the `Meteor.Collection`\n  `insert`/`update`/`remove` methods.\n\n  If you want to process the method's result as soon as it arrives from the\n  server, even if the method's writes are not available yet, you can now specify\n  an `onResultReceived` callback to `Meteor.apply`.\n\n* Rework latency compensation to show server data changes sooner. Previously, as\n  long as any method calls were in progress, Meteor would buffer all data\n  changes sent from the server until all methods finished. Meteor now only\n  buffers writes to documents written by client stubs, and applies the writes as\n  soon as all methods that wrote that document have finished.\n\n* `Meteor.userLoaded()` and `{{currentUserLoaded}}` have been removed.\n  Previously, during the login process on the client, `Meteor.userId()` could be\n  set but the document at `Meteor.user()` could be incomplete. Meteor provided\n  the function `Meteor.userLoaded()` to differentiate between these states. Now,\n  this in-between state does not occur: when a user logs in, `Meteor.userId()`\n  only is set once `Meteor.user()` is fully loaded.\n\n* New reactive function `Meteor.loggingIn()` and template helper\n  `{{loggingIn}}`; they are true whenever some login method is in progress.\n  `accounts-ui` now uses this to show an animation during login.\n\n* The `sass` CSS preprocessor package has been removed. It was based on an\n  unmaintained NPM module which did not implement recent versions of the Sass\n  language and had no error handling.  Consider using the `less` or `stylus`\n  packages instead.  [#143](https://github.com/meteor/meteor/issues/143)\n\n* `Meteor.setPassword` is now called `Accounts.setPassword`, matching the\n  documentation and original intention.  [#454](https://github.com/meteor/meteor/issues/454)\n\n* Passing the `wait` option to `Meteor.apply` now waits for all in-progress\n  method calls to finish before sending the method, instead of only guaranteeing\n  that its callback occurs after the callbacks of in-progress methods.\n\n* New function `Accounts.callLoginMethod` which should be used to call custom\n  login handlers (such as those registered with\n  `Accounts.registerLoginHandler`).\n\n* The callbacks for `Meteor.loginWithToken` and `Accounts.createUser` now match\n  the other login callbacks: they are called with error on error or with no\n  arguments on success.\n\n* Fix bug where method calls could be dropped during a brief disconnection. [#339](https://github.com/meteor/meteor/issues/339)\n\n* Prevent running the `meteor` command-line tool and server on unsupported Node\n  versions.\n\n* Fix Minimongo query bug with nested objects.  [#455](https://github.com/meteor/meteor/issues/455)\n\n* In `accounts-ui`, stop page layout from changing during login.\n\n* Use `path.join` instead of `/` in paths (helpful for the unofficial Windows\n  port) [#303](https://github.com/meteor/meteor/issues/303)\n\n* The `spiderable` package serves pages to\n  [`facebookexternalhit`](https://www.facebook.com/externalhit_uatext.php) [#411](https://github.com/meteor/meteor/issues/411)\n\n* Fix error on Firefox with DOM Storage disabled.\n\n* Avoid invalidating listeners if setUserId is called with current value.\n\n* Upgrade many dependencies, including:\n  * MongoDB 2.2.1 (from 2.2.0)\n  * underscore 1.4.2 (from 1.3.3)\n  * bootstrap 2.2.1 (from 2.1.1)\n  * jQuery 1.8.2 (from 1.7.2)\n  * less 1.3.1 (from 1.3.0)\n  * stylus 0.30.1 (from 0.29.0)\n  * coffee-script 1.4.0 (from 1.3.3)\n\nPatches contributed by GitHub users ayal, dandv, possibilities, TomWij,\ntmeasday, and workmad3.\n\n## v0.5.0, 2012-Oct-17\n\n* This release introduces Meteor Accounts, a full-featured auth system that supports\n  - fine-grained user-based control over database reads and writes\n  - federated login with any OAuth provider (with built-in support for\n    Facebook, GitHub, Google, Twitter, and Weibo)\n  - secure password login\n  - email validation and password recovery\n  - an optional set of UI widgets implementing standard login/signup/password\n    change/logout flows\n\n  When you upgrade to Meteor 0.5.0, existing apps will lose the ability to write\n  to the database from the client. To restore this, either:\n  - configure each of your collections with\n    [`collection.allow`](http://docs.meteor.com/#allow) and\n    [`collection.deny`](http://docs.meteor.com/#deny) calls to specify which\n    users can perform which write operations, or\n  - add the `insecure` smart package (which is included in new apps by default)\n    to restore the old behavior where anyone can write to any collection which\n    has not been configured with `allow` or `deny`\n\n  For more information on Meteor Accounts, see\n  http://docs.meteor.com/#dataandsecurity and\n  http://docs.meteor.com/#accounts_api\n\n* The new function `Meteor.autorun` allows you run any code in a reactive\n  context. See http://docs.meteor.com/#meteor_autorun\n\n* Arrays and objects can now be stored in the `Session`; mutating the value you\n  retrieve with `Session.get` does not affect the value in the session.\n\n* On the client, `Meteor.apply` takes a new `wait` option, which ensures that no\n  further method calls are sent to the server until this method is finished; it\n  is used for login and logout methods in order to keep the user ID\n  well-defined. You can also specifiy an `onReconnect` handler which is run when\n  re-establishing a connection; Meteor Accounts uses this to log back in on\n  reconnect.\n\n* Meteor now provides a compatible replacement for the DOM `localStorage`\n  facility that works in IE7, in the `localstorage-polyfill` smart package.\n\n* Meteor now packages the D3 library for manipulating documents based on data in\n  a smart package called `d3`.\n\n* `Meteor.Collection` now takes its optional `manager` argument (used to\n  associate a collection with a server you've connected to with\n  `Meteor.connect`) as a named option. (The old call syntax continues to work\n  for now.)\n\n* Fix a bug where trying to immediately resubscribe to a record set after\n  unsubscribing could fail silently.\n\n* Better error handling for failed Mongo writes from inside methods; previously,\n  errors here could cause clients to stop processing data from the server.\n\n\nPatches contributed by GitHub users bradens, dandv, dybskiy, possibilities,\nzhangcheng, and 75lb.\n\n\n## v0.4.2, 2012-Oct-02\n\n* Fix connection failure on iOS6. SockJS 0.3.3 includes this fix.\n\n* The new `preserve-inputs` package, included by default in new Meteor apps,\n  restores the pre-v0.4.0 behavior of \"preserving\" all form input elements by ID\n  and name during re-rendering; users who want more precise control over\n  preservation can still use the APIs added in v0.4.0.\n\n* A few changes to the `Meteor.absoluteUrl` function:\n  - Added a `replaceLocalhost` option.\n  - The `ROOT_URL` environment variable is respected by `meteor run`.\n  - It is now included in all apps via the `meteor` package. Apps that\n    explicitly added the now-deprecated `absolute-url` smart package will log a\n    deprecation warning.\n\n* Upgrade Node from 0.8.8 to 0.8.11.\n\n* If a Handlebars helper function `foo` returns null, you can now run do\n  `{{foo.bar}}` without error, just like when `foo` is a non-existent property.\n\n* If you pass a non-scalar object to `Session.set`, an error will now be thrown\n  (matching the behavior of `Session.equals`). [#215](https://github.com/meteor/meteor/issues/215)\n\n* HTML pages are now served with a `charset=utf-8` Content-Type header. [#264](https://github.com/meteor/meteor/issues/264)\n\n* The contents of `<select>` tags can now be reactive even in IE 7 and 8.\n\n* The `meteor` tool no longer gets confused if a parent directory of your\n  project is named `public`. [#352](https://github.com/meteor/meteor/issues/352)\n\n* Fix a race condition in the `spiderable` package which could include garbage\n  in the spidered page.\n\n* The REPL run by `admin/node.sh` no longer crashes Emacs M-x shell on exit.\n\n* Refactor internal `reload` API.\n\n* New internal `jsparse` smart package. Not yet exposed publicly.\n\n\nPatch contributed by GitHub user yanivoliver.\n\n\n## v0.4.1, 2012-Sep-24\n\n* New `email` smart package, with [`Email.send`](http://docs.meteor.com/#email)\n  API.\n\n* Upgrade Node from 0.6.17 to 0.8.8, as well as many Node modules in the dev\n  bundle; those that are user-exposed are:\n  * coffee-script: 1.3.3 (from 1.3.1)\n  * stylus: 0.29.0 (from 0.28.1)\n  * nib: 0.8.2 (from 0.7.0)\n\n* All publicly documented APIs now use `camelCase` rather than\n  `under_scores`. The old spellings continue to work for now. New names are:\n  - `Meteor.isClient`/`isServer`\n  - `this.isSimulation` inside a method invocation\n  - `Meteor.deps.Context.onInvalidate`\n  - `Meteor.status().retryCount`/`retryTime`\n\n* Spark improvements\n  * Optimize selector matching for event maps.\n  * Fix `Spark._currentRenderer` behavior in timer callbacks.\n  * Fix bug caused by interaction between `Template.foo.preserve` and\n    `{{#constant}}`. [#323](https://github.com/meteor/meteor/issues/323)\n  * Allow `{{#each}}` over a collection of objects without `_id`. [#281](https://github.com/meteor/meteor/issues/281)\n  * Spark now supports Firefox 3.6.\n  * Added a script to build a standalone spark.js that does not depend on\n    Meteor (it depends on jQuery or Sizzle if you need IE7 support,\n    and otherwise is fully standalone).\n\n* Database writes from within `Meteor.setTimeout`/`setInterval`/`defer` will be\n  batched with other writes from the current method invocation if they start\n  before the method completes.\n\n* Make `Meteor.Cursor.forEach` fully synchronous even if the user's callback\n  yields. [#321](https://github.com/meteor/meteor/issues/321).\n\n* Recover from exceptions thrown in `Meteor.publish` handlers.\n\n* Upgrade bootstrap to version 2.1.1. [#336](https://github.com/meteor/meteor/issues/336), [#337](https://github.com/meteor/meteor/issues/337), [#288](https://github.com/meteor/meteor/issues/288), [#293](https://github.com/meteor/meteor/issues/293)\n\n* Change the implementation of the `meteor deploy` password prompt to not crash\n  Emacs M-x shell.\n\n* Optimize `LocalCollection.remove(id)` to be O(1) rather than O(n).\n\n* Optimize client-side database performance when receiving updated data from the\n  server outside of method calls.\n\n* Better error reporting when a package in `.meteor/packages` does not exist.\n\n* Better error reporting for coffeescript. [#331](https://github.com/meteor/meteor/issues/331)\n\n* Better error handling in `Handlebars.Exception`.\n\n\nPatches contributed by GitHub users fivethirty, tmeasday, and xenolf.\n\n\n## v0.4.0, 2012-Aug-30\n\n* Merge Spark, a new live page update engine\n  * Breaking API changes\n     * Input elements no longer preserved based on `id` and `name`\n       attributes. Use [`preserve`](http://docs.meteor.com/#template_preserve)\n       instead.\n     * All `Meteor.ui` functions removed. Use `Meteor.render`,\n       `Meteor.renderList`, and\n       [Spark](https://github.com/meteor/meteor/wiki/Spark) functions instead.\n     * New template functions (eg. `created`, `rendered`, etc) may collide with\n       existing helpers. Use `Template.foo.helpers()` to avoid conflicts.\n     * New syntax for declaring event maps. Use\n       `Template.foo.events({...})`. For backwards compatibility, both syntaxes\n       are allowed for now.\n  * New Template features\n     * Allow embedding non-Meteor widgets (eg. Google Maps) using\n       [`{{#constant}}`](http://docs.meteor.com/#constant)\n     * Callbacks when templates are rendered. See\n       http://docs.meteor.com/#template_rendered\n     * Explicit control of which nodes are preserved during re-rendering. See\n       http://docs.meteor.com/#template_preserve\n     * Easily find nodes within a template in event handlers and callbacks. See\n       http://docs.meteor.com/#template_find\n     * Allow parts of a template to be independently reactive with the\n       [`{{#isolate}}`](http://docs.meteor.com/#isolate) block helper.\n\n* Use PACKAGE_DIRS environment variable to override package location. [#227](https://github.com/meteor/meteor/issues/227)\n\n* Add `absolute-url` package to construct URLs pointing to the application.\n\n* Allow modifying documents returned by `observe` callbacks. [#209](https://github.com/meteor/meteor/issues/209)\n\n* Fix periodic crash after client disconnect. [#212](https://github.com/meteor/meteor/issues/212)\n\n* Fix minimingo crash on dotted queries with undefined keys. [#126](https://github.com/meteor/meteor/issues/126)\n\n\n## v0.3.9, 2012-Aug-07\n\n* Add `spiderable` package to allow web crawlers to index Meteor apps.\n\n* `meteor deploy` uses SSL to protect application deployment.\n\n* Fix `stopImmediatePropagation()`. [#205](https://github.com/meteor/meteor/issues/205)\n\n\n## v0.3.8, 2012-Jul-12\n\n* HTTPS support\n  * Add `force-ssl` package to require site to load over HTTPS.\n  * Use HTTPS for install script and `meteor update`.\n  * Allow runtime configuration of default DDP endpoint.\n\n* Handlebars improvements\n  * Implement dotted path traversal for helpers and methods.\n  * Allow functions in helper arguments.\n  * Change helper nesting rules to allow functions as arguments.\n  * Fix `{{this.foo}}` to never invoke helper `foo`.\n  * Make event handler `this` reflect the node that matched the selector instead\n    of the event target node.\n  * Fix keyword arguments to helpers.\n\n* Add `nib` support to stylus package. [#175](https://github.com/meteor/meteor/issues/175)\n\n* Upgrade bootstrap to version 2.0.4. [#173](https://github.com/meteor/meteor/issues/173)\n\n* Print changelog after `meteor update`.\n\n* Fix mouseenter and mouseleave events. [#224](https://github.com/meteor/meteor/issues/224)\n\n* Fix issue with spurious heartbeat failures on busy connections.\n\n* Fix exception in minimongo when matching non-arrays using `$all`. [#183](https://github.com/meteor/meteor/issues/183)\n\n* Fix serving an empty file when no cacheable assets exist. [#179](https://github.com/meteor/meteor/issues/179)\n\n\n## v0.3.7, 2012-Jun-06\n\n* Better parsing of `.html` template files\n  * Allow HTML comments (`<!-- -->`) at top level\n  * Allow whitespace anywhere in open/close tag\n  * Provide names and line numbers on error\n  * More helpful error messages\n\n* Form control improvements\n  * Fix reactive radio buttons in Internet Explorer.\n  * Fix reactive textareas to update consistently across browsers, matching text\n    field behavior.\n\n* `http` package bug fixes:\n  * Send correct Content-Type when POSTing `params` from the server. [#172](https://github.com/meteor/meteor/issues/172)\n  * Correctly detect JSON response Content-Type when a charset is present.\n\n* Support `Handlebars.SafeString`. [#160](https://github.com/meteor/meteor/issues/160)\n\n* Fix intermittent \"Cursor is closed\" mongo error.\n\n* Fix \"Cannot read property 'nextSibling' of null\" error in certain nested\n  templates. [#142](https://github.com/meteor/meteor/issues/142)\n\n* Add heartbeat timer on the client to notice when the server silently goes\n  away.\n\n\n## v0.3.6, 2012-May-16\n\n* Rewrite event handling. `this` in event handlers now refers to the data\n  context of the element that generated the event, *not* the top-level data\n  context of the template where the event is declared.\n\n* Add /websocket endpoint for raw websockets. Pass websockets through\n  development mode proxy.\n\n* Simplified API for Meteor.connect, which now receives a URL to a Meteor app\n  rather than to a sockjs endpoint.\n\n* Fix livedata to support subscriptions with overlapping documents.\n\n* Update node.js to 0.6.17 to fix potential security issue.\n\n\n## v0.3.5, 2012-Apr-28\n\n* Fix 0.3.4 regression: Call event map handlers on bubbled events. [#107](https://github.com/meteor/meteor/issues/107)\n\n\n## v0.3.4, 2012-Apr-27\n\n* Add Twitter `bootstrap` package. [#84](https://github.com/meteor/meteor/issues/84)\n\n* Add packages for `sass` and `stylus` CSS pre-processors. [#40](https://github.com/meteor/meteor/issues/40), [#50](https://github.com/meteor/meteor/issues/50)\n\n* Bind events correctly on top level elements in a template.\n\n* Fix dotted path selectors in minimongo. [#88](https://github.com/meteor/meteor/issues/88)\n\n* Make `backbone` package also run on the server.\n\n* Add `bare` option to coffee-script compilation so variables can be shared\n  between multiple coffee-script file. [#85](https://github.com/meteor/meteor/issues/85)\n\n* Upgrade many dependency versions. User visible highlights:\n * node.js 0.6.15\n * coffee-script 1.3.1\n * less 1.3.0\n * sockjs 0.3.1\n * underscore 1.3.3\n * backbone 0.9.2\n\n* Several documentation fixes and test coverage improvements.\n\n\n## v0.3.3, 2012-Apr-20\n\n* Add `http` package for making HTTP requests to remote servers.\n\n* Add `madewith` package to put a live-updating Made with Meteor badge on apps.\n\n* Reduce size of mongo database on disk (--smallfiles).\n\n* Prevent unnecessary hot-code pushes on deployed apps during server migration.\n\n* Fix issue with spaces in directory names. [#39](https://github.com/meteor/meteor/issues/39)\n\n* Workaround browser caching issues in development mode by using query\n  parameters on all JavaScript and CSS requests.\n\n* Many documentation and test fixups.\n\n\n## v0.3.2, 2012-Apr-10\n\n* Initial public launch\n"
  },
  {
    "path": "IssueTriage.md",
    "content": "# Issue Triage\n\nThis document describes the process Meteor contributors use to organize issues. We use Github [issues](https://github.com/meteor/meteor/issues) to track bugs and feature requests. Our goal is to maintain a list of issues that are relevant and well-defined (and [labeled](https://github.com/meteor/meteor/labels)) such that a contributor can immediately begin working on the code for a fix or feature request. Contributors who want to dive in and write code aren't likely to prioritize working on issues that are ambiguous and have low impact.\n\nWe would love to have more contributors who are willing to help out with triaging issues. You can begin by helping issue requesters create good reproductions and by confirming those reproductions on your own machine. It won't be long before the core maintainers notice your work and ask whether you'd like to be promoted to an issue maintainer.\n\n- [Issue lifecycle](#issue-lifecycle)\n  - [Bugs](#bugs)\n  - [Help questions](#help-questions)\n  - [Feature requests](#feature-requests)\n- [Classification](#classification)\n  - [Severity](#severity)\n  - [Impact](#impact)\n- [Issues ready to claim](#issues-ready-to-claim)\n\n## Issue lifecycle\n\nAll issues follow the flow outlined below. Your job as an issue maintainer is to work with the requester and others within the community towards the goal of having an issue either become 'claimable' or closed. Read on for more details on the process.\n\n![Flowchart](IssueTriageFlow.png \"Issue Lifecycle\")\n\nThe first step is in determining whether the issue is a bug, help question or feature request. Read on for more details.\n\n### Bugs\n\n1. Duplicates should be closed and marked as such.\n2. Add the `bug` label and `Project:*` labels that apply (a best guess on the `Project:` is fine; sometimes it's hard to tell exactly which project the issue falls under).\n3. Bugs should have a high-quality reproduction as described [here](Contributing.md#reporting-bug). You may need to help the reporter reduce their bug to a minimal reproduction. Leave the issue open.\n4. A reproduction should be confirmed by at least one person other than the original reporter. Run the reproduction and validate that the bug exists; then make a note of your findings on the issue. If a reproduction is supplied but doesn't work, add the `can't-reproduce` label and make a comment describing what happened.\n5. Finally, once you've confirmed the reproduction add the `confirmed` label and [classify](#classification) the issue (removing the `can't-reproduce` label if it exists).\n\n### Help questions\n\n[Stack Overflow](http://stackoverflow.com/questions/tagged/meteor) and our [forums](https://forums.meteor.com/c/help) are the place to ask for help on using the framework. Close issues that are help requests and politely refer the author to the above locations.\n\n### Feature requests\n\n1. For reasons described [here](Contributing.md#feature-requests), we would prefer features to be built as separate packages. If the feature can clearly be built as a package, explain this to the requester and close the issue.\n> - If the feature could be built as a package and serves a particular need, encourage the user to contribute it themselves.\n>- If the underlying issue could be better solved by existing technology, encourage them to seek help in the [forums](https://forums.meteor.com/c/help) or on [Stack Overflow](http://stackoverflow.com/questions/tagged/meteor).\n2. If you haven't closed the issue, add the `feature` label and `Project:*` labels that apply (a best guess on the `Project:` is fine, sometimes it's hard to tell exactly which project the issue falls under).\n3. If it's not possible to build the feature as a package (as you identified in step 1), explore whether creating hooks in core would make it possible to do so. If it would, redefine the issue as a request to create those hooks.\n4. Work with the requester and others in the community to build a clear specification for the feature and update the issue description accordingly.\n5. Finally, add the `confirmed` label and [classify](#classification) the issue.\n\nCore contributors may add the `pull-requests-encouraged` label to feature requests. This indicates the feature is aligned with the project roadmap and a high-quality pull request will almost certainly be merged.\n\n<h2 id=\"classification\">Classification</h2>\n\nAssign a classification (via GH labels) that enables the community to determine how to prioritize which issues to work on. The classification is based on *Severity x Impact* .\n\n### Severity\n_[Severity:has-workaround, Severity:production, Severity:blocks-development]_\n\n- If there is a workaround, apply the `Severity:has-workaround` label.\n- If the issue affects production apps, apply the `Severity:production` label.\n- If the issue blocks development (e.g `meteor run` is broken), apply the `Severity:blocks-development` label.\n\n### Impact\n_[Impact:few, Impact:some, Impact:most]_\n\nThis is a somewhat subjective label and is interpreted in conjunction with Github's upvotes. As a general guideline:\n\n- `Impact:few` issues would go unnoticed by almost all users, apart from those using a very niche feature, or a feature in an unusual way.\n- `Impact:some` issues would impact users using a feature that is commonly but not universally used.\n- `Impact:most` issues would impact more or less every user of the framework.\n\n## Issues ready to claim\n\nThis state indicates that bugs/feature requests have reached the level of quality\nrequired for a contributor to begin writing code against (you can easily [filter for this list](https://github.com/meteor/meteor/labels/confirmed) by using the `confirmed` label).\n\nAlthough this should have already been done by this stage, ensure the issue is\ncorrectly labeled and the title/description have been updated to reflect an\naccurate summary of the issue.\n\nContributors should comment on and/or assign themselves an issue if they begin working on it so that others know work is in progress.\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "========================================\nMeteor is licensed under the MIT License\n========================================\n\nCopyright (C) 2011--2016 Meteor Development Group\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\n\n====================================================================\nThis license applies to all code in Meteor that is not an externally\nmaintained library. Externally maintained libraries have their own\nlicenses, included in the LICENSES directory.\n====================================================================\n"
  },
  {
    "path": "LICENSES/Apache.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\nThe following libraries are licensed under the Apache License, version 2.0:\n\n\"\"\"\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n\"\"\"\n\n----------\nmongodb: (Node driver) https://github.com/mongodb/node-mongodb-native\nkerberos: https://github.com/christkv/kerberos\n----------\n\nCopyright 2009 - 2010 Christian Amor Kvalheim.\n\n\n----------\nless: https://github.com/cloudhead/less.js\n----------\n\nCopyright (c) 2009-2010 Alexis Sellier\n\n\n----------\nuseragent: https://github.com/fintanf/node-useragent\n----------\n\nThis parser is based on the user agent parser; code.google.com/p/ua-parser/\nwhich is released under Apache license:\n\nCopyright 2009 Google Inc.\n\n\n----------\nrequest: https://github.com/mikeal/request\naws-sign2: https://github.com/mikeal/aws-sign\ncookie-jar: https://github.com/mikeal/cookie-jar\nforever-agent: https://github.com/mikeal/forever-agent\noauth-sign: https://github.com/mikeal/oauth-sign\ntunnel-agent: https://github.com/mikeal/tunnel-agent\ncaseless: https://github.com/request/caseless\n----------\n\nCopyright (c) 2011, 2012, 2013 Mikeal Rogers\n\n\n----------\ncode-prettify: http://code.google.com/p/google-code-prettify/\n----------\n\nCopyright 2011 Mike Samuel et al\n\n\n----------\nbootstrap: https://github.com/twitter/bootstrap\n----------\n\nCopyright 2012 Twitter, Inc.\n\n\n----------\nbson: https://github.com/mongodb/js-bson\n----------\n\nCopyright (c) 2012 Christian Amor Kvalheim <christkv@gmail.com>\n\n\n----------\nwebsocket: https://github.com/Worlize/WebSocket-Node/blob/master/LICENSE\n----------\n\nBrian McKelvey\n\n\n----------\namdefine: https://github.com/jrburke/amdefine\n----------\n\nCopyright (c) 2011, The Dojo Foundation\n\n\n----------\nnlogger: https://github.com/igo/nlogger\n----------\n\nCopyright (c) 2010 by Igor Urmincek\n\n\n----------\nDiff Match and Patch: http://code.google.com/p/google-diff-match-patch/\n----------\n\nCopyright 2006 Google Inc.\n\n\n----------\nansicolors: https://github.com/thlorenz/ansicolors\nansistyles: https://github.com/thlorenz/ansistyles\ncombine-source-map: https://github.com/thlorenz/combine-source-map\nconvert-source-map: https://github.com/thlorenz/convert-source-map\ninline-source-map: https://github.com/thlorenz/inline-source-map\n----------\n\nCopyright 2013 Thorsten Lorenz. All rights reserved.\n\n\n----------\ncolumnify: https://github.com/timoxley/columnify\n----------\n\nCopyright Tim Oxley\n\n\n----------\neventemitter3: https://github.com/3rd-Eden/EventEmitter3\n----------\n\nCopyright Arnout Kazemier\n\n\n----------\npunycode: https://github.com/bestiejs/punycode.js\n----------\n\nCopyright Mathias Bynens <http://mathiasbynens.be/>\n\n\n----------\nbrowserstack-webdriver: https://github.com/browserstack/selenium-webdriver-nodejs\n----------\n\nCopyright 2009-2014 Software Freedom Conservancy\n\n\n----------\nnode-inspector: https://github.com/node-inspector/node-inspector\n----------\n\nCopyright (c) 2011, Danny Coates\n\n\n----------\nphantomjs: https://github.com/Medium/phantomjs (npm installer)\n----------\n\nCopyright 2012 The Obvious Corporation.\n\n\n----------\nelementtree: https://github.com/racker/node-elementtree\n----------\n\nCopyright (c) 2011, Rackspace, Inc.\nThe ElementTree toolkit is Copyright (c) 1999-2007 by Fredrik Lundh\n\n\n----------\nxcode: https://github.com/alunny/node-xcode\n----------\n\nCopyright 2012 Andrew Lunny, Adobe Systems\n\n\n----------\ncordova: https://git-wip-us.apache.org/repos/asf/cordova-cli.git\ncordova-js: https://git-wip-us.apache.org/repos/asf/cordova-js.git\ncordova-lib: https://git-wip-us.apache.org/repos/asf/cordova-lib.git\n----------\n\nApache Cordova\nCopyright 2012 The Apache Software Foundation\n\nThis product includes software developed at\nThe Apache Software Foundation (http://www.apache.org/).\n\n\n----------\nip: https://github.com/indutny/node-ip\n----------\n\nCopyright Fedor Indutny, 2012\n\n\n----------\nkew: https://github.com/Medium/kew\n----------\n\nCopyright 2012 The Obvious Corporation.\nhttp://obvious.com/\n\n\n----------\nvalid-identifier: https://github.com/purplecabbage/valid-identifier\n----------\n\nJesse MacFadyen\n"
  },
  {
    "path": "LICENSES/Artistic.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n\n----------\nstrong-data-uri: https://github.com/strongloop/strong-data-uri\n----------\n\nRedistributed under the terms of the Artistic License, version 2.0.\n\nhttp://opensource.org/licenses/Artistic-2.0\n"
  },
  {
    "path": "LICENSES/BSD.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n\n----------\ntar-pack: https://github.com/ForbesLindesay/tar-pack\n----------\n\nCopyright (c) 2014, Forbes Lindesay\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nsqlite3: https://github.com/mapbox/node-sqlite3\n----------\n\nCopyright (c) MapBox\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n- Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n- Redistributions in binary form must reproduce the above copyright notice, this\n  list of conditions and the following disclaimer in the documentation and/or\n  other materials provided with the distribution.\n- Neither the name \"MapBox\" nor the names of its contributors may be\n  used to endorse or promote products derived from this software without\n  specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nnode-pre-gyp: https://github.com/mapbox/node-pre-gyp\n----------\n\nCopyright (c), Mapbox\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright notice,\n      this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright notice,\n      this list of conditions and the following disclaimer in the documentation\n      and/or other materials provided with the distribution.\n    * Neither the name of node-pre-gyp nor the names of its contributors\n      may be used to endorse or promote products derived from this software\n      without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nuglify-js: https://github.com/mishoo/UglifyJS2\n----------\n\nCopyright 2012-2013 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n    * Redistributions of source code must retain the above\n      copyright notice, this list of conditions and the following\n      disclaimer.\n\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials\n      provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n\n\n----------\nopenssl: http://www.openssl.org/\n----------\n\n/* ====================================================================\n * Copyright (c) 1998-2011 The OpenSSL Project.  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\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n\n---------\nshowdown: http://www.attacklab.net/\n---------\n\nCopyright (c) 2007, John Fraser\n<http://www.attacklab.net/>\nAll rights reserved.\n\nOriginal Markdown copyright (c) 2004, John Gruber\n<http://daringfireball.net/>\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n* Redistributions of source code must retain the above copyright notice,\n  this list of conditions and the following disclaimer.\n\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* Neither the name \"Markdown\" nor the names of its contributors may\n  be used to endorse or promote products derived from this software\n  without specific prior written permission.\n\nThis software is provided by the copyright holders and contributors \"as\nis\" and any express or implied warranties, including, but not limited\nto, the implied warranties of merchantability and fitness for a\nparticular purpose are disclaimed. In no event shall the copyright owner\nor contributors be liable for any direct, indirect, incidental, special,\nexemplary, or consequential damages (including, but not limited to,\nprocurement of substitute goods or services; loss of use, data, or\nprofits; or business interruption) however caused and on any theory of\nliability, whether in contract, strict liability, or tort (including\nnegligence or otherwise) arising in any way out of the use of this\nsoftware, even if advised of the possibility of such damage.\n\n\n----------\nhistory.js: https://github.com/balupton/History.js/\n----------\n\nCopyright (c) 2011, Benjamin Arthur Lupton\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n  * Neither the name of Benjamin Arthur Lupton nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\ntar: https://github.com/isaacs/node-tar\nfstream: https://github.com/isaacs/fstream\nfstream-npm: https://github.com/isaacs/fstream-npm\nfstream-ignore: https://github.com/isaacs/fstream-ignore\nread: https://github.com/isaacs/read\nblock-stream: https://github.com/isaacs/block-stream\nglob: https://github.com/isaacs/node-glob\nchownr: https://github.com/isaacs/chownr\nuid-number: https://github.com/isaacs/uid-number\nsigmund: https://github.com/isaacs/sigmund\n----------\n\nCopyright (c) Isaac Z. Schlueter\nAll rights reserved.\n\nThe BSD License\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n1. Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n2. 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\nTHIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS\n``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\nTO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\nINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nlockfile: https://github.com/isaacs/lockfile\nnpm-registry-client: https://github.com/isaacs/npm-registry-client\nnpmlog: https://github.com/isaacs/npmlog\nonce: https://github.com/isaacs/once\nosenv: https://github.com/isaacs/osenv\nmute-stream: https://github.com/isaacs/mute-stream\ncouch-login: https://github.com/isaacs/couch-login\nnpmconf: https://github.com/isaacs/npmconf\nread-installed: https://github.com/isaacs/read-installed\nread-package-json: https://github.com/isaacs/read-package-json\npromzard: https://github.com/isaacs/promzard\nchmodr: https://github.com/isaacs/chmodr\ncmd-shim: https://github.com/ForbesLindesay/cmd-shim\njson-stringify-safe: https://github.com/isaacs/json-stringify-safe\nsax: https://github.com/isaacs/sax-js\n----------\n\nCopyright (c) Isaac Z. Schlueter (\"Author\")\nAll rights reserved.\n\nThe BSD License\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n1. Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n\n2. 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\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN\nIF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nD3: https://github.com/mbostock/d3\n----------\n\nCopyright (c) 2012, Michael Bostock\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* The name Michael Bostock may not be used to endorse or promote products\n  derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\nBUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\nOF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\njsbn: http://www-cs-students.stanford.edu/~tjw/jsbn/\n----------\n\nCopyright (c) 2003-2005  Tom Wu\nAll Rights Reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS-IS\" AND WITHOUT WARRANTY OF ANY KIND,\nEXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY\nWARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.\n\nIN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,\nINDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER\nRESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF\nTHE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT\nOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\nIn addition, the following condition applies:\n\nAll redistributions must retain an intact copy of this copyright notice\nand disclaimer.\n\n\n----------\njsSHA2: http://anmar.eu.org/projects/jssha2/\nwith Unicode support (Utf8Encode function) added by\n  http://www.webtoolkit.info/javascript-sha256.html\n----------\n\nCopyright (c) 2003-2004, Angel Marin\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n * Neither the name of the <ORGANIZATION> nor the names of its contributors may\n   be used to endorse or promote products derived from this software without\n   specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\nIN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\nBUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\nOF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nycssmin: https://github.com/yui/ycssmin\n----------\n\nCopyright 2012 Yahoo! Inc.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\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    * Neither the name of the Yahoo! Inc. nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL YAHOO! INC. BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON 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 THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nsource-map: https://github.com/mozilla/source-map\n----------\n\nCopyright (c) 2009-2011, Mozilla Foundation and contributors\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the names of the Mozilla Foundation nor the names of project\n  contributors may be used to endorse or promote products derived from this\n  software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nboom: https://github.com/spumko/boom\n----------\n\nCopyright (c) 2012-2013, Walmart.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\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    * Neither the name of Walmart nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL WALMART BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON 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 THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nhoek: https://github.com/spumko/hoek\n----------\n\nCopyright (c) 2011-2013, Walmart.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\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    * Neither the name of Walmart nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL WALMART BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON 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 THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n                                  *   *   *\n\n\nPortions of this project were initially based on Postmile, Copyright (c) 2011, Yahoo Inc.\nPostmile is published at https://github.com/yahoo/postmile and its licensing terms are\npublished at https://github.com/yahoo/postmile/blob/master/LICENSE.\n\n\n----------\ncryptiles: https://github.com/hueniverse/cryptiles\nhawk: https://github.com/hueniverse/hawk\nsntp: https://github.com/hueniverse/sntp\n----------\n\nCopyright (c) 2012-2013, Eran Hammer.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\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    * Neither the name of Eran Hammer nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL ERAN HAMMER BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON 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 THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\ndiff: https://github.com/kpdecker/jsdiff\n----------\n\nSoftware License Agreement (BSD License)\n\nCopyright (c) 2009-2011, Kevin Decker <kpdecker@gmail.com>\n\nAll rights reserved.\n\nRedistribution and use of this software in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above\n  copyright notice, this list of conditions and the\n  following disclaimer.\n\n* Redistributions in binary form must reproduce the above\n  copyright notice, this list of conditions and the\n  following disclaimer in the documentation and/or other\n  materials provided with the distribution.\n\n* Neither the name of Kevin Decker nor the names of its\n  contributors may be used to endorse or promote products\n  derived from this software without specific prior\n  written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER\nIN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT\nOF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nescope: https://github.com/Constellation/escope\nestraverse: https://github.com/Constellation/estraverse\nesutils: https://github.com/Constellation/esutils\nescodegen: http://github.com/Constellation/escodegen\n----------\n\nRedistribution and use in source and binary forms, with or without\nmodification, 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\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON 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\nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nesprima: https://github.com/ariya/esprima\nesprima-fb: https://github.com/facebook/esprima/tree/fb-harmony\nesrefactor: https://github.com/ariya/esrefactor\n----------\n\nRedistribution and use in source and binary forms, with or without\nmodification, 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\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON 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\nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nnormalize-package-data: https://github.com/meryn/normalize-package-data\n----------\n\nThis package contains code originally written by Isaac Z. Schlueter. \nUsed with permission.\n\nCopyright (c) Meryn Stol (\"Author\")\nAll rights reserved.\n\nThe BSD License\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n1. Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n\n2. 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\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN\nIF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nnpm-user-validate: https://github.com/robertkowalski/npm-user-validate\ngithub-url-from-username-repo: https://github.com/robertkowalski/github-url-from-username-repo\n----------\n\nCopyright (c) Robert Kowalski\nAll rights reserved.\n\nThe BSD License\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n1. Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n\n2. 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\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN\nIF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nphantomjs: http://phantomjs.org/\n----------\n\nCopyright 2010-2014 Ariya Hidayat\n\n\n----------\nshelljs: http://github.com/arturadib/shelljs\n----------\n\nCopyright (c) 2012, Artur Adib <aadib@mozilla.com>\nAll rights reserved.\n\nYou may use this project under the terms of the New BSD license as follows:\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\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    * Neither the name of Artur Adib nor the\n      names of the contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" \nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \nARE DISCLAIMED. IN NO EVENT SHALL ARTUR ADIB BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON 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 \nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\ntaffydb: https://github.com/typicaljoe/taffydb\n----------\n\nCopyright (c) All rights reserved.\n\nRedistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following condition is met:\n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n\n\n----------\nnpm-install-checks: https://github.com/npm/npm-install-checks\n----------\n\nCopyright (c) Robert Kowalski and Isaac Z. Schlueter (\"Authors\")\nAll rights reserved.\n\nThe BSD License\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n1. Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n\n2. 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\nTHIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN\nIF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\ncanonical-json: https://github.com/mirkokiefer/canonical-json\n----------\n\nMirko Kiefer\n\n\n----------\ncoffeestack: https://github.com/kevinsawicki/coffeestack\n----------\n\nKevin Sawicki\n\n\n----------\nduplexer2: https://github.com/deoxxa/duplexer2\n----------\n\nCopyright (c) 2013, Deoxxa Development\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n3. Neither the name of Deoxxa Development nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY DEOXXA DEVELOPMENT ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DEOXXA DEVELOPMENT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n----------\nripemd160: https://github.com/crypto-browserify/ripemd160\n----------\n\nLicensed: BSD3-Clause\n\n"
  },
  {
    "path": "LICENSES/CDDL.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n----------\njsstyle\n----------\n\nThe contents of this file are subject to the terms of the\nCommon Development and Distribution License (the \"License\").\nYou may not use this file except in compliance with the License.\n\nYou can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE\nor http://www.opensolaris.org/os/licensing.\nSee the License for the specific language governing permissions\nand limitations under the License.\n\nWhen distributing Covered Code, include this CDDL HEADER in each\nfile and include the License file at usr/src/OPENSOLARIS.LICENSE.\nIf applicable, add the following below this CDDL HEADER, with the\nfields enclosed by brackets \"[]\" replaced with your own identifying\ninformation: Portions Copyright [yyyy] [name of copyright owner]\n\n\nCopyright 2008 Sun Microsystems, Inc.  All rights reserved.\nUse is subject to license terms.\n\nCopyright 2011 Joyent, Inc. All rights reserved.\n"
  },
  {
    "path": "LICENSES/DWTFYWT.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\nThe following librararies are licensed under the DO WHAT THE FUCK YOU WANT TO\nPUBLIC LICENSE, Version 2:\n\n\n\"\"\"\n            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE\n                    Version 2, December 2004\n\n Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>\n\n Everyone is permitted to copy and distribute verbatim or modified\n copies of this license document, and changing it is allowed as long\n as the name is changed.\n\n            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. You just DO WHAT THE FUCK YOU WANT TO.\n\"\"\"\n\n\n----------\ninherits: https://github.com/isaacs/inherits\n----------\n\nBy Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)\n\n\n\n----------\nBase64: https://github.com/davidchambers/Base64.js\n----------\n\n Copyright (c) 2011..2012 David Chambers <dc@hashify.me>\n\n\n----------\nopener: https://github.com/domenic/opener\npath-is-inside: https://github.com/domenic/path-is-inside\nsorted-object: https://github.com/domenic/sorted-object\n----------\n\n Copyright (C) 2012 Domenic Denicola <domenic@domenicdenicola.com>\n"
  },
  {
    "path": "LICENSES/Eclipse.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\nThe following libraries are licensed under the Eclipse Public License, version 1.0:\n\n\"\"\"\nEclipse Public License - v 1.0\n\nTHE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE (\"AGREEMENT\"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.\n\n1. DEFINITIONS\n\n\"Contribution\" means:\n\na) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and\nb) in the case of each subsequent Contributor:\ni) changes to the Program, and\nii) additions to the Program;\nwhere such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.\n\"Contributor\" means any person or entity that distributes the Program.\n\n\"Licensed Patents\" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.\n\n\"Program\" means the Contributions distributed in accordance with this Agreement.\n\n\"Recipient\" means anyone who receives the Program under this Agreement, including all Contributors.\n\n2. GRANT OF RIGHTS\n\na) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.\nb) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.\nc) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.\nd) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.\n3. REQUIREMENTS\n\nA Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:\n\na) it complies with the terms and conditions of this Agreement; and\nb) its license agreement:\ni) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;\nii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;\niii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and\niv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.\nWhen the Program is made available in source code form:\n\na) it must be made available under this Agreement; and\nb) a copy of this Agreement must be included with each copy of the Program.\nContributors may not remove or alter any copyright notices contained within the Program.\n\nEach Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.\n\n4. COMMERCIAL DISTRIBUTION\n\nCommercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor (\"Commercial Contributor\") hereby agrees to defend and indemnify every other Contributor (\"Indemnified Contributor\") against any losses, damages and costs (collectively \"Losses\") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.\n\nFor example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.\n\n5. NO WARRANTY\n\nEXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.\n\n6. DISCLAIMER OF LIABILITY\n\nEXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n\n7. GENERAL\n\nIf any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.\n\nIf Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.\n\nAll Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.\n\nEveryone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.\n\nThis Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.\n\"\"\"\n\n----------\nmori: https://github.com/swannodette/mori\n----------\n\nCopyright (C) 2013 David Nolen and contributors\n\n"
  },
  {
    "path": "LICENSES/ISC.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\nThe following libraries are licensed under the ISC License:\n\n\"\"\"\nThe ISC License\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\nIN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\"\"\"\n\n\n----------\nchar-spinner: https://github.com/isaacs/char-spinner\ninflight: https://github.com/isaacs/inflight\n----------\n\nCopyright (c) Isaac Z. Schlueter\n\n\n----------\nnpm-cache-filename: https://github.com/npm/npm-cache-filename\n----------\n\nCopyright (c) npm, Inc. and Contributors\n\n\n----------\nwrappy: https://github.com/npm/wrappy\n----------\n\nCopyright (c) Isaac Z. Schlueter and Contributors\n\n\n----------\nbrowserify-sign: https://github.com/crypto-browserify/browserify-sign\nminimalistic-assert: https://github.com/calvinmetcalf/minimalistic-assert\nparse-asn1: https://github.com/crypto-browserify/parse-asn1\n----------\n\nCalvin Metcalf\n\n\n----------\npemstrip: https://github.com/apatil/pemstrip\n----------\n\nAnand Patil\n"
  },
  {
    "path": "LICENSES/IntelHAXM.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n\n\n----------\nIntel HAXM\n----------\n\nIntel® Hardware Accelerated Execution Manager End-User License Agreement\n\nLast Updated April 15, 2014\n\nCopyright© 2013 Intel Corporation.\nAll rights reserved.\n\nRedistribution. Redistribution and use in binary form, without modification, are permitted provided that the following conditions are met:\n\n1. Redistributions must reproduce the above copyright notice and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n2. Neither the name of Intel Corporation nor the names of its suppliers may be used to endorse or promote products derived from this software without specific prior written permission.\n\n3. No reverse engineering, de-compilation, or disassembly of this software is permitted. Limited patent license. Intel Corporation grants a world-wide, royalty-free, non-exclusive license under patents it now or hereafter owns or controls to make, have made, use, import, offer to sell and sell (\"Utilize\") this software, but solely to the extent that any such patent is necessary to Utilize the software alone. The patent license shall not apply to any combinations which include this software. No hardware per se is licensed hereunder.\n\nDISCLAIMER.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n"
  },
  {
    "path": "LICENSES/MIT.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\nThe following libraries are licensed under the MIT License:\n\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\"\"\"\n\nAlthough they are distributed under the same license as Meteor, they\nretain the copyright of the original author.\n\n\n\n\n----------\nconnect: https://github.com/senchalabs/connect\n----------\n\nCopyright (c) 2010 Sencha Inc.\nCopyright (c) 2011 LearnBoost\nCopyright (c) 2011 TJ Holowaychuk\n\n----------\ngzippo: https://github.com/tomgco/gzippo\n----------\n\nCopyright (c) 2011 Tom Gallacher <http://www.tomg.co>\n\n\n----------\ncoffee-script: https://github.com/jashkenas/coffee-script\n----------\n\nCopyright (c) 2009-2012 Jeremy Ashkenas\n\n\n----------\nmime: https://github.com/bentomas/node-mime\n----------\n\nCopyright (c) 2010 Benjamin Thomas, Robert Kieffer\n\n\n----------\nhandlebars: https://github.com/wycats/handlebars.js/\n----------\n\nCopyright (C) 2011 by Yehuda Katz\n\n\n----------\nclean-css: https://github.com/GoalSmashers/clean-css\n----------\n\nCopyright (c) 2011 GoalSmashers.com\n\n\n----------\nprogress: https://github.com/visionmedia/node-progress\nqs: https://github.com/visionmedia/node-querystring\ndebug: https://github.com/visionmedia/debug\nnib: https://github.com/visionmedia/nib\nbytes: https://github.com/visionmedia/bytes.js\ncommander: https://github.com/visionmedia/commander.js\nfresh: https://github.com/visionmedia/node-fresh\ngithub-url-from-git: https://github.com/visionmedia/node-github-url-from-git\npause: https://github.com/visionmedia/node-pause\nrange-parser: https://github.com/visionmedia/node-range-parser\nsend: https://github.com/visionmedia/send\nmethods: https://github.com/visionmedia/node-methods\ncss-parse: https://github.com/reworkcss/css-parse\ncss-stringify: https://github.com/reworkcss/css-stringify\ncallsite: https://github.com/visionmedia/callsite\nindexof: https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz\nescape-html: https://github.com/component/escape-html\nexpress: https://github.com/strongloop/express\n----------\n\nCopyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca>\nCopyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>\nCopyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>\nCopyright (c) 2013 TJ Holowaychuk <tj@vision-media.ca>\nCopyright (c) 2011, 2013 TJ Holowaychuk <tj@vision-media.ca>\nCopyright (c) 2009-2014 TJ Holowaychuk <tj@vision-media.ca>\n\n\n----------\nfibers: https://github.com/laverdet/node-fibers\n----------\n\nCopyright 2011 Marcel Laverdet\n\n\n----------\nhttp-proxy: https://github.com/nodejitsu/node-http-proxy\n----------\n\nCopyright (c) 2010 Charlie Robbins, Mikeal Rogers, Fedor Indutny, & Marak Squires\n\n\n----------\nsockjs: https://github.com/sockjs/sockjs-client\n----------\n\nCopyright (C) 2011 VMware, Inc.\n\n\n----------\nalea: http://baagoe.org/en/wiki/Better_random_numbers_for_javascript\n----------\n\nCopyright (C) 2010 by Johannes Baagøe <baagoe@baagoe.org>\n\n\n----------\njquery: https://github.com/jquery/jquery\n----------\n\nCopyright (c) 2011 John Resig, http://jquery.com/\n\n\n----------\nunderscore: https://github.com/documentcloud/underscore\nbackbone: https://github.com/documentcloud/backbone/\nunderscore-contrib: https://github.com/documentcloud/underscore-contrib\n----------\n\nCopyright (c) 2009-2012 Jeremy Ashkenas, DocumentCloud\nCopyright (c) 2013 Jeremy Ashkenas, Michael Fogus, DocumentCloud and Investigative Reporters & Editors\n\n\n----------\namplify: https://github.com/appendto/amplify\n----------\n\nCopyright 2011 appendTo LLC. (http://appendto.com/team)\n\n\n----------\nconnect-gzip: https://github.com/nateps/connect-gzip\n----------\n\nCopyright (c) 2011 Nate Smith <nate@nateps.com>\n\n\n----------\nsocket.io: https://github.com/learnboost/socket.io\nms: https://github.com/guille/ms.js\n----------\n\nCopyright (c) 2011 Guillermo Rauch <guillermo@learnboost.com>\n\n\n----------\nstylus: https://github.com/learnboost/stylus\n----------\n\nCopyright (c) 2010 LearnBoost <dev@learnboost.com>\n\n\n----------\njquery-waypoints: https://github.com/imakewebthings/jquery-waypoints\n----------\n\nCopyright (c) 2011-2012 Caleb Troughton\n\n\n----------\njquery-layout: http://layout.jquery-dev.net/\n----------\n\nCopyright (c) 2008\n  Fabrizio Balliano (http://www.fabrizioballiano.net)\n  Kevin Dalman (http://allpro.net)\n\n\n----------\nrbytes: https://github.com/akdubya/rbytes\n----------\n\nCopyright (c) 2010 Aleksander Williams\n\n\n----------\ncolors: https://github.com/Marak/colors.js\n----------\n\nCopyright (c) 2010\nMarak Squires\nAlexis Sellier (cloudhead)\n\n\n----------\npkginfo: https://github.com/indexzero/node-pkginfo\n----------\n\nCopyright (c) 2010 Charlie Robbins.\n\n----------\nunderscore.string: https://github.com/epeli/underscore.string\n----------\n\nCopyright (c) 2011 Esa-Matti Suuronen esa-matti@suuronen.org\n\n\n----------\nnode-gyp: https://github.com/TooTallNate/node-gyp\nkeypress: https://github.com/TooTallNate/keypress\nbindings: https://github.com/TooTallNate/node-bindings\nplist-with-patches: https://github.com/agrieve/node-plist\nutil-deprecate: https://github.com/TooTallNate/util-deprecate\n----------\n\nCopyright (c) 2010-2011- Nathan Rajlich\nCopyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net>\n\n\n\n----------\nnode-uuid: https://github.com/broofa/node-uuid\n----------\n\nCopyright (c) 2010 Robert Kieffer\n\n\n----------\nansi: https://github.com/TooTallNate/ansi.js\nplist: https://github.com/TooTallNate/plist.js\n----------\n\nCopyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net>\n\n\n----------\nfaye-websocket: https://github.com/faye/faye-websocket-node\nwebsocket-driver: https://github.com/faye/websocket-driver-node\n----------\n\nCopyright (c) 2009-2013 James Coglan\nCopyright (c) 2010-2013 James Coglan\n\n\n----------\ncssom: https://github.com/NV/CSSOM\n----------\n\nCopyright (c) Nikita Vasilyev\n\n\n----------\nyamlparser: https://github.com/h4evr/commonjs-javascript-yaml-parser\n----------\n\nCopyright (c) 2011 Diogo Costa (costa.h4evr@gmail.com)\n\n\n----------\nsemver: https://github.com/isaacs/node-semver\nabbrev: https://github.com/isaacs/abbrev-js\ngraceful-fs: https://github.com/isaacs/node-graceful-fs\nlru-cache: https://github.com/isaacs/node-lru-cache\nproto-list: https://github.com/isaacs/proto-list\nrimraf: https://github.com/isaacs/rimraf\nminimatch: https://github.com/isaacs/minimatch\nini: https://github.com/isaacs/ini\nnopt: https://github.com/isaacs/nopt\nslide: https://github.com/isaacs/slide-flow-control\nwhich: https://github.com/isaacs/node-which\nminimatch: https://github.com/isaacs/minimatch\ncore-util-is: https://github.com/isaacs/core-util-is\nrimraf: https://github.com/isaacs/rimraf\n----------\n\nCopyright 2009, 2010, 2011 Isaac Z. Schlueter.\nAll rights reserved.\n\n\n----------\narchy: https://github.com/substack/node-archy\nastw: https://github.com/substack/astw\nbinary: https://github.com/substack/node-binary\nbrowser-pack: https://github.com/substack/browser-pack\nbuffers: https://github.com/substack/node-buffers\nchainsaw: https://github.com/substack/node-chainsaw\ncommondir: https://github.com/substack/node-commondir\ndeep-equal: https://github.com/substack/node-deep-equal\ndefined: https://github.com/substack/defined\ndeps-sort: https://github.com/substack/deps-sort\ndetective: https://github.com/substack/node-detective\neditor: https://github.com/substack/node-editor\nhttp-browserify: https://github.com/substack/http-browserify\nhttps-browserify: https://github.com/substack/https-browserify\ninsert-module-globals: https://github.com/substack/insert-module-globals\nlexical-scope: https://github.com/substack/lexical-scope\nminimist: https://github.com/substack/minimist\nmkdirp: https://github.com/substack/node-mkdirp\nmodule-deps: https://github.com/substack/module-deps\noptimist: https://github.com/substack/node-optimist\nparents: https://github.com/substack/node-parents\npath-browserify: https://github.com/substack/path-browserify\nquotemeta: https://github.com/substack/quotemeta\nresolve: https://github.com/substack/node-resolve\nshallow-copy: https://github.com/substack/shallow-copy\nshell-quote: https://github.com/substack/node-shell-quote\nstream-browserify: https://github.com/substack/stream-browserify\nsubarg: https://github.com/substack/subarg\nsyntax-error: https://github.com/substack/node-syntax-error\ntext-table: https://github.com/substack/text-table\ntraverse: https://github.com/substack/js-traverse\ntty-browserify: https://github.com/substack/tty-browserify\ntypedarray: https://github.com/substack/typedarray\nvm-browserify: https://github.com/substack/vm-browserify\nwordwrap: https://github.com/substack/node-wordwrap\nyargs: https://github.com/chevex/yargs\njson-stable-stringify: https://github.com/substack/json-stable-stringify\nlabeled-stream-splicer: https://github.com/substack/labeled-stream-splicer\nstream-splicer: https://github.com/substack/stream-splicer\n----------\n\nCopyright 2010, 2011, 2012, 2013 James Halliday (mail@substack.net)\n\n\n----------\nconfig-chain: https://github.com/dominictarr/config-chain\nJSONStream: https://github.com/dominictarr/JSONStream/\ncrypto-browserify: https://github.com/dominictarr/crypto-browserify\nrc: https://github.com/dominictarr/rc\nstream-combiner: https://github.com/dominictarr/stream-combiner\nthrough: http://github.com/dominictarr/through\nshasum: https://github.com/dominictarr/shasum\nstream-combiner2: https://github.com/substack/stream-combiner2\n----------\n\nCopyright (c) 2011 Dominic Tarr\nCopyright (c) 2012 'Dominic Tarr'\nCopyright (c) 2013 Dominic Tarr\n\n\n\n----------\nasync: https://github.com/caolan/async\n----------\n\nCopyright (c) 2010 Caolan McMahon\n\n\n----------\ncombined-stream: https://github.com/felixge/node-combined-stream\ndelayed-stream: https://github.com/felixge/node-delayed-stream\n----------\n\nCopyright (c) 2011 Debuggable Limited <felix@debuggable.com>\n\n\n----------\nretry: https://github.com/felixge/node-retry\n----------\n\nCopyright (c) 2011:\nTim Koschützki (tim@debuggable.com)\nFelix Geisendörfer (felix@debuggable.com)\n\n----------\nform-data: https://github.com/felixge/node-form-data\nmultiparty: https://github.com/superjoe30/node-multiparty\n----------\n\nCopyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors\n\n\n----------\nkexec: https://github.com/jprichardson/node-kexec\n----------\n\nCopyright (c) 2011-2012 JP Richardson\n\n\n----------\nsetimmediate: https://github.com/NobleJS/setImmediate\n----------\n\nCopyright (c) 2012 Barnesandnoble.com, llc, Donavon West, and Domenic Denicola\n\n\n----------\nasn1: https://github.com/mcavage/node-asn1\nassert-plus: https://github.com/mcavage/node-assert-plus\n----------\n\nCopyright (c) 2011 Mark Cavage, All rights reserved.\n\n\n----------\nawssum: https://github.com/awssum/awssum\n----------\n\nCopyright 2011-2013 Apps Attic Ltd.  All rights reserved.\nCopyright 2013 Andrew Chilton.  All rights reserved.\n\n\n----------\ndata2xml: https://github.com/chilts/data2xml\n----------\n\nCopyright 2011-2012 Apps Attic Ltd.  All rights reserved.\n\n\n----------\nbuffer-crc32: https://github.com/brianloveswords/buffer-crc32\n----------\n\nCopyright (c) 2013 Brian J. Brennan\n\n\n----------\nchild-process-close: https://github.com/piscisaureus/child-process-close\n----------\n\nCopyright (C) 2012 Bert Belder\n\n\n----------\ncli-color: https://github.com/medikoo/cli-color\nes5-ext: https://github.com/medikoo/es5-ext\nevent-emitter: https://github.com/medikoo/event-emitter\nmemoizee: https://github.com/medikoo/memoize\nnext-tick: https://github.com/medikoo/next-tick\nd: https://github.com/medikoo/d\nes6-iterator: https://github.com/medikoo/es6-iterator\nes6-symbol: https://github.com/medikoo/es6-symbol\nes6-weak-map: https://github.com/medikoo/es6-weak-map\n----------\n\nCopyright (C) 2011, 2012 Mariusz Nowak (www.medikoo.com)\n\n\n----------\nconnect-jsonp: https://github.com/steelThread/connect-jsonp\n----------\n\nCopyright (c) 2010 Sean McDaniel\n\n\n----------\ncookie: https://github.com/shtylman/node-cookie\nprocess: https://github.com/shtylman/node-process\n----------\n\nCopyright (C) Roman Shtylman <shtylman@gmail.com>\nCopyright (c) 2013 Roman Shtylman <shtylman@gmail.com>\n\n\n----------\ncookie-signature: https://github.com/visionmedia/node-cookie-signature\n----------\n\nCopyright (c) 2012 LearnBoost <tj@learnboost.com>\n\n\n----------\ndateformat: https://github.com/felixge/node-dateformat\n----------\n\n(c) 2007-2009 Steven Levithan <stevenlevithan.com>\n\n\n----------\neyes: https://github.com/cloudhead/eyes.js\nvows: https://github.com/cloudhead/vows\n----------\n\nCopyright (c) 2009 cloudhead\n\n\n----------\nfmt: https://github.com/appsattic/fmt\n----------\n\nCopyright © 2012-2013 AppsAttic Ltd <chilts@appsattic.com>\n\n\n----------\nhttp-signature: https://github.com/joyent/node-http-signature\n----------\n\nCopyright Joyent, Inc. All rights reserved.\n\n\n----------\ni: https://github.com/pksunkara/inflect\n----------\n\nCopyright Pavan Kumar Sunkara (pavan.sss1991@gmail.com)\n\n\n----------\nncp: https://github.com/AvianFlu/ncp\n----------\n\nCopyright (C) 2011 by Charlie McConnell\n\n\n----------\npassgen: https://github.com/SDA/passgen\n----------\n\nCopyright (c) 2011 SDA Software Associates Inc.\n\n\n----------\nsha: https://github.com/ForbesLindesay/sha\ntype-of: https://github.com/ForbesLindesay/type-of\nuglify-to-browserify: https://github.com/ForbesLindesay/uglify-to-browserify\numd: https://github.com/ForbesLindesay/umd\nrfile: https://github.com/ForbesLindesay/rfile\nruglify: https://github.com/ForbesLindesay/ruglify\n----------\n\nCopyright (c) 2013 Forbes Lindesay\n\n\n----------\nsource-map-support: https://github.com/evanw/node-source-map-support\n----------\n\nCopyright Evan Wallace\n\n\n----------\nutile: https://github.com/flatiron/utile\n----------\n\nCopyright (c) 2010 Nodejitsu Inc.\n\n\n----------\nxml: https://github.com/dylang/node-xml\n----------\n\nCopyright (c) 2011 Dylan Greene <dylang@gmail.com>\n\n\n----------\nxml2js: https://github.com/Leonidas-from-XIV/node-xml2js\n----------\n\nCopyright 2010, 2011, 2012, 2013. All rights reserved.\n\n\n----------\nctype: https://github.com/rmustacc/node-ctype\n----------\n\nCopyright 2011, Robert Mustacchi. All rights reserved.\nCopyright 2011, Joyent, Inc. All rights reserved.\n\n\n----------\neachline: https://github.com/williamwicks/node-eachline\n----------\n\nCopyright (c) 2013 William Wicks\n\n\n----------\neventemitter2: https://github.com/hij1nx/EventEmitter2\n----------\n\nCopyright (c) 2011 hij1nx http://www.twitter.com/hij1nx\n\n\n----------\nstream-counter: https://github.com/superjoe30/node-stream-counter\n----------\n\nCopyright (c) 2013 Andrew Kelley\n\n----------\nuid2: https://github.com/coreh/uid2\n----------\n\nCopyright (c) 2013 Marco Aurelio\n\n----------\ngeojson-utils: https://github.com/maxogden/geojson-js-utils\nconcat-stream: https://github.com/maxogden/concat-stream\n----------\n\nCopyright (c) 2010 Max Ogden\nCopyright (c) 2013 Max Ogden\n\n\n----------\nbcrypt: https://github.com/ncb000gt/node.bcrypt.js\n----------\n\nCopyright (c) 2010 Nicholas Campbell\n\n\n----------\nhtml5: https://github.com/aredridel/html5\n----------\n\nCopyright (c) 2010 Aria Stewart <aredridel@nbtsc.org>\n\n\n----------\nnode-aes-gcm: https://github.com/xorbit/node-aes-gcm\n----------\n\nCopyright (c) 2013 Patrick Van Oosterwijck\n\n\n----------\nisarray: https://github.com/juliangruber/isarray\nbuiltins: https://github.com/juliangruber/builtins\nconstants-browserify: https://github.com/juliangruber/constants-browserify\n----------\n\nCopyright (c) 2013 Julian Gruber <julian@juliangruber.com>\n\n\n----------\nkeep-alive-agent: https://github.com/ceejbot/keep-alive-agent\n----------\n\nCopyright (c) 2012 C J Silverio\n\n\n----------\nmatch-stream: https://github.com/EvanOxfeld/match-stream\nslice-stream: https://github.com/EvanOxfeld/slice-stream\n----------\n\nCopyright (c) 2013 Evan Oxfeld\n\n\n----------\nunzip: https://github.com/joeferner/node-unzip\nover: https://github.com/joeferner/node-over\npullstream: https://github.com/EvanOxfeld/node-pullstream\nbplist-parser: https://github.com/joeferner/node-bplist-parser\n----------\n\nCopyright (c) 2012 Near Infinity Corporation\n\n\n----------\nassert: https://github.com/defunctzombie/commonjs-assert\nbrowser-resolve: https://github.com/defunctzombie/node-browser-resolve\nevents: https://github.com/Gozala/events\nurl: https://github.com/defunctzombie/node-url\nutil: https://github.com/defunctzombie/node-util\n----------\n\nCopyright Joyent, Inc. and other Node contributors. All rights reserved.\n\n\n----------\naws-sign: https://github.com/egorFiNE/node-aws-sign\n----------\n\nEgor Egorov, me@egorfine.com.\n\n\n----------\nbase64-js: https://github.com/beatgammit/base64-js\n----------\n\nCopyright (c) 2014\n\n\n----------\nbeep: https://github.com/mscdex/beepjs\n----------\n\nCopyright Brian White. All rights reserved.\n\n\n----------\nbrowserify-zlib: https://github.com/devongovett/browserify-zlib\n----------\n\nDevon Govett <devongovett@gmail.com>\n\n\n----------\nbuffer: https://github.com/feross/buffer/\n----------\n\nCopyright (c) Feross Aboukhadijeh, and other contributors.\n\n\n----------\ncatharsis: https://github.com/hegemonic/catharsis\nrequizzle: https://github.com/hegemonic/requizzle\n----------\n\nCopyright (c) 2014 Google Inc.\nCopyright (c) 2012-2014 Jeff Williams\nCopyright (c) 2012-2013 Johannes Ewald\n\n\n----------\nconsole-browserify: https://github.com/Raynos/console-browserify\nduplexer: https://github.com/Raynos/duplexer\nxtend: https://github.com/Raynos/xtend\n----------\n\nCopyright (c) 2012 Raynos.\nCopyright (c) 2012-2014 Raynos.\n\n----------\ndeep-extend: https://github.com/unclechu/node-deep-extend\n----------\n\nCopyright (c) 2013 Viacheslav Lotsmanov\n\n\n----------\ndep-graph: http://github.com/TrevorBurnham/dep-graph\n----------\n\n©2011 Trevor Burnham\n\n\n----------\nderequire: https://github.com/calvinmetcalf/derequire\nbrowserify-aes: https://github.com/crypto-browserify/browserify-aes\nbrowserify-rsa: https://github.com/calvinmetcalf/browserify-rsa\ncreate-ecdh: https://github.com/crypto-browserify/createECDH\ncreate-hash: https://github.com/crypto-browserify/createHash\ncreate-hmac: https://github.com/crypto-browserify/createHMAC\ndiffie-hellman: https://github.com/crypto-browserify/diffie-hellman\npbkdf2-compat: https://github.com/crypto-browserify/pbkdf2\npublic-encrypt: https://github.com/crypto-browserify/publicEncrypt\nrandombytes: https://github.com/crypto-browserify/randombytes\n----------\n\nCalvin Metcalf\n\n\n----------\ndomain-browser: https://github.com/bevry/domain-browser\n----------\n\nCopyright © Bevry Pty Ltd us@bevry.me (http://bevry.me)\n\n\n----------\njsonparse: https://github.com/creationix/jsonparse\n----------\n\nCopyright (c) 2012 Tim Caswell\n\n\n----------\nmarked: https://github.com/chjj/marked\n----------\n\nCopyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)\n\n\n----------\nobject-keys: https://github.com/ljharb/object-keys\n----------\n\nCopyright (C) 2013 Jordan Harband\n\n\n----------\nos-browserify: https://github.com/drewyoung1/os-browserify\n----------\n\nCopyright (c) 2014 Drew Young\n\n\n----------\npako: https://github.com/nodeca/pako\n----------\n\nCopyright (C) 2014 by Vitaly Puzrin\n\n\n----------\nq: https://github.com/kriskowal/q\n----------\n\nCopyright 2009–2014 Kristopher Michael Kowal. All rights reserved.\n\n\n----------\nquerystring-es3: https://github.com/mike-spainhower/querystring\n----------\n\nCopyright 2012 Irakli Gozalishvili. All rights reserved. \n\n\n----------\nansi-regex:             https://github.com/sindresorhus/ansi-regex\nansi-styles:            https://github.com/sindresorhus/ansi-styles\nescape-string-regexp:   https://github.com/sindresorhus/escape-string-regexp\nchalk:                  https://github.com/sindresorhus/chalk\nget-stdin:              https://github.com/sindresorhus/get-stdin\nhas-ansi:               https://github.com/sindresorhus/has-ansi\nstrip-ansi:             https://github.com/sindresorhus/strip-ansi\nstrip-json-comments:    https://github.com/sindresorhus/strip-json-comments\nsupports-color:         https://github.com/sindresorhus/supports-color\n----------\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\n----------\ntimers-browserify: https://github.com/jryans/timers-browserify\n----------\n\nCopyright © 2012 J. Ryan Stinnett <jryans@gmail.com>\n\n\n----------\nwrench: https://github.com/ryanmcgrath/wrench-js\n----------\n\nCopyright (c) 2010 Ryan McGrath\n\n\n----------\nxmlbuilder: http://github.com/oozcitak/xmlbuilder-js\n----------\n\nCopyright (c) 2013 Ozgur Ozcitak\n\n\n----------\nxmldom: https://github.com/jindw/xmldom\n----------\n\njindw <jindw@xidea.org> (http://www.xidea.org)\n\n\n----------\nproperties-parser: https://github.com/xavi-/node-properties-parser\n----------\n\nXavi Ramirez\n\n----------\njs2xmlparser: https://github.com/michaelkourlas/node-js2xmlparser/\n----------\n\nCopyright © 2012 Michael Kourlas and other contributors\n\n\n----------\npegjs: https://github.com/dmajda/pegjs\n----------\nCopyright (c) 2010-2013 David Majda\n\n----------\nfoo: https://github.com/coolaj86/node-pakman\n----------\n\nCopyright (c) 2011 AJ ONeal\n\n\n----------\nios-sim: https://github.com/phonegap/ios-sim\n----------\n\nAuthor: Landon Fuller <landonf@plausiblelabs.com>\nCopyright (c) 2008-2011 Plausible Labs Cooperative, Inc.\nAll rights reserved.\n\nModifications made by the following entities are licensed as above:\n- Jeff Haynie, Appcelerator, Inc.\n- https://github.com/hborders\n- http://pivotallabs.com/users/scoward/blog\n- Eloy Duran, Fingertips <eloy@fngtps.com>\n\n\n----------\naccepts: https://github.com/jshttp/accepts\nmerge-descriptors: https://github.com/component/merge-descriptors\ntype-is: https://github.com/jshttp/type-is\nmime-types: https://github.com/jshttp/mime-types\nmime-db: https://github.com/jshttp/mime-db\n----------\n\nCopyright (c) 2013 Jonathan Ong me@jongleberry.com\nCopyright (c) 2014 Jonathan Ong <me@jongleberry.com>\n\n\n----------\nparseurl: https://github.com/expressjs/parseurl\n----------\n\nCopyright (c) 2014 Jonathan Ong <me@jongleberry.com>\nCopyright (c) 2014 Douglas Christopher Wilson <doug@somethingdoug.com>\n\n\n----------\nserve-static: https://github.com/expressjs/serve-static\n----------\n\nCopyright (c) 2010 Sencha Inc.\nCopyright (c) 2011 LearnBoost\nCopyright (c) 2011 TJ Holowaychuk\nCopyright (c) 2014 Douglas Christopher Wilson\n\n\n----------\nnegotiator: https://github.com/jshttp/negotiator\n----------\n\nOriginal \"Negotiator\" program Copyright Federico Romero\nPort to JavaScript Copyright Isaac Z. Schlueter\n\n\n----------\noptions: https://github.com/einaros/options.js\ntinycolor: https://github.com/einaros/tinycolor\nws: https://github.com/einaros/ws\n----------\n\nCopyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>\nCopyright (c) 2012 Einar Otto Stangvik <einaros@gmail.com>\n\n\n----------\npath-to-regexp: https://github.com/component/path-to-regexp\n----------\n\nCopyright (c) 2014 Blake Embrey (hello@blakeembrey.com)\n\n\n----------\ntruncate: https://github.com/FGRibreau/node-truncate\n----------\n\nCopyright (c) 2013 Francois-Guillaume Ribreau\n\n\n----------\nutils-merge: https://github.com/jaredhanson/utils-merge\n----------\n\nCopyright (c) 2013 Jared Hanson\n\n\n----------\nbl: https://github.com/rvagg/bl\n----------\n\nCopyright (c) 2014 bl contributors\nbl contributors listed at https://github.com/rvagg/bl#contributors\n\n\n----------\nisstream: https://github.com/rvagg/isstream\n----------\n\nCopyright (c) 2015 Rod Vagg\n\n\n----------\nlodash-node: https://github.com/lodash/lodash-node\n----------\n\nCopyright 2012-2014 The Dojo Foundation <http://dojofoundation.org/>\nBased on Underscore.js 1.6.0, copyright 2009-2014 Jeremy Ashkenas,\nDocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>\n\n\n----------\nnetroute: https://github.com/indutny/node-netroute\nasn1.js: https://github.com/indutny/asn1.js\nasn1.js-rfc3280: https://github.com/indutny/asn1.js\nbn.js: https://github.com/indutny/bn.js\nbrorand: https://github.com/indutny/brorand.js\nelliptic: https://github.com/indutny/elliptic\nhash.js: https://github.com/indutny/hash.js\nmiller-rabin: https://github.com/indutny/miller-rabin\n----------\n\nCopyright Fedor Indutny, 2012.\n\n\n----------\nstringstream: https://github.com/mhart/StringStream\n----------\n\nCopyright 2012 Michael Hart (michael.hart.au@gmail.com)\n\n\n----------\nclone: https://github.com/pvorb/node-clone\n----------\n\nCopyright © 2011-2014 Paul Vorbach <paul@vorba.ch>\n\n\n----------\ndefaults: https://github.com/tmpvar/defaults\n----------\n\n----------\nthrottleit: https://github.com/component/throttle\n----------\n\n\n----------\nemissary: https://github.com/atom/emissary\nevent-kit: https://github.com/atom/event-kit\nfs-plus: https://github.com/atom/fs-plus\ngrim: https://github.com/atom/grim\nmixto: https://github.com/atom/mixto\npathwatcher: https://github.com/atom/node-pathwatcher\nproperty-accessors: https://github.com/atom/property-accessors\nrunas: https://github.com/atom/node-runas\nunderscore-plus: https://github.com/atom/underscore-plus\n----------\n\nCopyright (c) 2013 GitHub Inc.\nCopyright (c) 2014 GitHub Inc.\n\n\n----------\nharmony-collections: https://github.com/Benvie/harmony-collections\n----------\n\nCopyright (c) 2012 Brandon Benvie http://bbenvie.com\n\n\n----------\niconv-lite: https://github.com/ashtuchkin/iconv-lite\n----------\n\nCopyright (c) 2011 Alexander Shtuchkin\n\n\n----------\nrequest-progress: https://github.com/IndigoUnited/node-request-progress\n----------\n\nCopyright (c) 2012 IndigoUnited\n\n\n----------\nwcwidth: https://github.com/mycoboco/wcwidth.js\n----------\n\nCopyright (C) 2012-2014 by Jun Woong and Tim Oxley.\n\n\n----------\nadm-zip: https://github.com/cthackers/adm-zip\n----------\n\nCopyright (c) 2012 Another-D-Mention Software and other contributors, \nhttp://www.another-d-mention.ro/\n\n\n----------\nnode-exit: https://github.com/cowboy/node-exit\n----------\n\nCopyright (c) 2013 \"Cowboy\" Ben Alman\nLicensed under the MIT license.\n\n\n----------\nacorn: http://marijnhaverbeke.nl/git/acorn\n----------\n\nCopyright (C) 2012-2014 by various contributors (see AUTHORS)\n\n\n----------\nd8: https://github.com/constantology/d8\nm8: https://github.com/constantology/m8\n----------\n\nCopyright (c) 2011 christos \"constantology\" constandinou http://muigui.com\n\n\n----------\ndate-now: https://github.com/Raynos/date-now\n----------\n\nCopyright (c) 2012 Colingo.\n\n\n----------\ndeep-is: https://github.com/thlorenz/deep-is\n----------\n\nCopyright (c) 2012, 2013 Thorsten Lorenz <thlorenz@gmx.de>\nCopyright (c) 2012 James Halliday <mail@substack.net>\nCopyright (c) 2009 Thomas Robinson <280north.com>\n\n\n----------\nfast-levenshtein: https://github.com/hiddentao/fast-levenshtein\n----------\n\nCopyright (c) 2013 Ramesh Nair\n\n\n----------\nis-array: https://github.com/retrofox/is-array\n----------\n\nDamián Suárez\n\n\n----------\nlevn: https://github.com/gkz/levn\noptionator: https://github.com/gkz/optionator\nprelude-ls: https://github.com/gkz/prelude-ls\ntype-check: https://github.com/gkz/type-check\n----------\n\nCopyright (c) George Zahariev\n\n\n----------\nmoment: https://github.com/moment/moment\n----------\n\nCopyright (c) 2011-2014 Tim Wood, Iskren Chernev, Moment.js contributors\n\n\n----------\nmongodb-uri: https://github.com/mongolab/mongodb-uri-node\n----------\n\nCopyright (c) 2013 ObjectLabs Corporation\n\n\n----------\nquerystring: https://github.com/Gozala/querystring\n----------\n\nCopyright 2012 Irakli Gozalishvili.\n\n\n----------\nsha.js: https://github.com/crypto-browserify/sha.js\n----------\n\nCopyright (c) 2013-2014 sha.js contributors\n"
  },
  {
    "path": "LICENSES/MongoDB.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n----------\nMongoDB: http://www.mongodb.org/\n----------\n\nLICENSE\n\n  Most MongoDB source files are made available under the terms of the\n  GNU Affero General Public License (AGPL).  See individual files for\n  details.\n\n  As an exception, the files in the client/, debian/, rpm/,\n  utils/mongoutils, and all subdirectories thereof are made available under\n  the terms of the Apache License, version 2.0.\n\nhttp://www.gnu.org/licenses/agpl-3.0.html\nhttp://www.apache.org/licenses/LICENSE-2.0\n\n\nMongoDB uses third-party libraries or other resources that may\nbe distributed under licenses different than the MongoDB software.\n\nIn the event that we accidentally failed to list a required notice,\nplease bring it to our attention through any of the ways detailed here :\n\n           mongodb-dev@googlegroups.com\n\nThe attached notices are provided for information only.\n\n\n1) License Notice for Boost\n---------------------------\n\nhttp://www.boost.org/LICENSE_1_0.txt\n\nBoost Software License - Version 1.0 - August 17th, 2003\n\nPermission is hereby granted, free of charge, to any person or organization\nobtaining a copy of the software and accompanying documentation covered by\nthis license (the \"Software\") to use, reproduce, display, distribute,\nexecute, and transmit the Software, and to prepare derivative works of the\nSoftware, and to permit third-parties to whom the Software is furnished to\ndo so, all subject to the following:\n\nThe copyright notices in the Software and this entire statement, including\nthe above license grant, this restriction and the following disclaimer,\nmust be included in all copies of the Software, in whole or in part, and\nall derivative works of the Software, unless such copies or derivative\nworks are solely in the form of machine-executable object code generated by\na source language processor.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\nSHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\nFOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n\n\n2) License Notice for V8\n-------------------------\n\nhttp://code.google.com/p/v8/source/browse/trunk/LICENSE\n\nThis license applies to all parts of V8 that are not externally\nmaintained libraries.  The externally maintained libraries used by V8\nare:\n\n  - Jscre, located under third_party/jscre.  This code is copyrighted\n    by the University of Cambridge and Apple Inc. and released under a\n    2-clause BSD license.\n\n  - Dtoa, located under third_party/dtoa.  This code is copyrighted by\n    David M. Gay and released under an MIT license.\n\n  - Strongtalk assembler, the basis of the files assembler-arm-inl.h,\n    assembler-arm.cc, assembler-arm.h, assembler-ia32-inl.h,\n    assembler-ia32.cc, assembler-ia32.h, assembler.cc and assembler.h.\n    This code is copyrighted by Sun Microsystems Inc. and released\n    under a 3-clause BSD license.\n\nThese libraries have their own licenses; we recommend you read them,\nas their terms may differ from the terms below.\n\nCopyright 2006-2008, Google Inc. All rights reserved.\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\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\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials provided\n      with the distribution.\n    * Neither the name of Google Inc. nor the names of its\n      contributors may be used to endorse or promote products derived\n      from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n3) License Notice for PCRE\n--------------------------\n\nhttp://www.pcre.org/licence.txt\n\nPCRE LICENCE\n------------\n\nPCRE is a library of functions to support regular expressions whose syntax\nand semantics are as close as possible to those of the Perl 5 language.\n\nRelease 7 of PCRE is distributed under the terms of the \"BSD\" licence, as\nspecified below. The documentation for PCRE, supplied in the \"doc\"\ndirectory, is distributed under the same terms as the software itself.\n\nThe basic library functions are written in C and are freestanding. Also\nincluded in the distribution is a set of C++ wrapper functions.\n\n\nTHE BASIC LIBRARY FUNCTIONS\n---------------------------\n\nWritten by:       Philip Hazel\nEmail local part: ph10\nEmail domain:     cam.ac.uk\n\nUniversity of Cambridge Computing Service,\nCambridge, England.\n\nCopyright (c) 1997-2008 University of Cambridge\nAll rights reserved.\n\n\nTHE C++ WRAPPER FUNCTIONS\n-------------------------\n\nContributed by:   Google Inc.\n\nCopyright (c) 2007-2008, Google Inc.\nAll rights reserved.\n\n\nTHE \"BSD\" LICENCE\n-----------------\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright notice,\n      this list of conditions and the following disclaimer.\n\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    * Neither the name of the University of Cambridge nor the name of Google\n      Inc. nor the names of their contributors may be used to endorse or\n      promote products derived from this software without specific prior\n      written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\nINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.\n\n\n4) License notice for Aladdin MD5\n---------------------------------\n\nCopyright (C) 1999, 2002 Aladdin Enterprises.  All rights reserved.\n\nThis software is provided 'as-is', without any express or implied\nwarranty.  In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\n   claim that you wrote the original software. If you use this software\n   in a product, an acknowledgment in the product documentation would be\n   appreciated but is not required.\n2. Altered source versions must be plainly marked as such, and must not be\n   misrepresented as being the original software.\n3. This notice may not be removed or altered from any source distribution.\n\nL. Peter Deutsch\nghost@aladdin.com\n\n5) License notice for Snappy - http://code.google.com/p/snappy/\n---------------------------------\n Copyright 2005 and onwards Google Inc.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n 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\n copyright notice, this list of conditions and the following disclaimer\n in the documentation and/or other materials provided with the\n distribution.\n     * Neither the name of Google Inc. nor the names of its\n contributors may be used to endorse or promote products derived from\n this software without specific prior written 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\n OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n A light-weight compression algorithm.  It is designed for speed of\n compression and decompression, rather than for the utmost in space\n savings.\n\n For getting better compression ratios when you are compressing data\n with long repeated sequences or compressing data that is similar to\n other data, while still compressing fast, you might look at first\n using BMDiff and then compressing the output of BMDiff with\n Snappy.\n\n\n\nEnd\n"
  },
  {
    "path": "LICENSES/Node.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n----------\nnodejs: http://nodejs.org/\nreadable-stream: https://github.com/isaacs/readable-stream\nnpm: https://github.com/isaacs/npm\ninit-package-json: https://github.com/isaacs/init-package-json\nstring_decoder: https://github.com/rvagg/string_decoder\nutil-extend: https://github.com/isaacs/util-extend\npath-platform: https://github.com/tjfontaine/node-path-platform\nreadable-wrap: https://github.com/substack/readable-wrap\n----------\n\n\nNode's license follows:\n\n====\n\nCopyright Joyent, Inc. and other Node contributors. All rights reserved.\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n\n====\n\nThis license applies to all parts of Node that are not externally\nmaintained libraries. The externally maintained libraries used by Node are:\n\n- V8, located at deps/v8. V8's license follows:\n  \"\"\"\n    This license applies to all parts of V8 that are not externally\n    maintained libraries.  The externally maintained libraries used by V8\n    are:\n\n      - PCRE test suite, located in\n        test/mjsunit/third_party/regexp-pcre.js.  This is based on the\n        test suite from PCRE-7.3, which is copyrighted by the University\n        of Cambridge and Google, Inc.  The copyright notice and license\n        are embedded in regexp-pcre.js.\n\n      - Layout tests, located in test/mjsunit/third_party.  These are\n        based on layout tests from webkit.org which are copyrighted by\n        Apple Computer, Inc. and released under a 3-clause BSD license.\n\n      - Strongtalk assembler, the basis of the files assembler-arm-inl.h,\n        assembler-arm.cc, assembler-arm.h, assembler-ia32-inl.h,\n        assembler-ia32.cc, assembler-ia32.h, assembler-x64-inl.h,\n        assembler-x64.cc, assembler-x64.h, assembler-mips-inl.h,\n        assembler-mips.cc, assembler-mips.h, assembler.cc and assembler.h.\n        This code is copyrighted by Sun Microsystems Inc. and released\n        under a 3-clause BSD license.\n\n      - Valgrind client API header, located at third_party/valgrind/valgrind.h\n        This is release under the BSD license.\n\n    These libraries have their own licenses; we recommend you read them,\n    as their terms may differ from the terms below.\n\n    Copyright 2006-2012, the V8 project authors. All rights reserved.\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    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\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials provided\n          with the distribution.\n        * Neither the name of Google Inc. nor the names of its\n          contributors may be used to endorse or promote products derived\n          from this software without specific prior written 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\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n  \"\"\"\n\n- libev, located at deps/uv/src/unix/ev. libev's license follows:\n  \"\"\"\n    All files in libev are Copyright (C)2007,2008,2009 Marc Alexander Lehmann.\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n\n        * Redistributions of source code must retain the above copyright\n          notice, this list of conditions and the following disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials provided\n          with the distribution.\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\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    Alternatively, the contents of this package may be used under the terms\n    of the GNU General Public License (\"GPL\") version 2 or any later version,\n    in which case the provisions of the GPL are applicable instead of the\n    above. If you wish to allow the use of your version of this package only\n    under the terms of the GPL and not to allow others to use your version of\n    this file under the BSD license, indicate your decision by deleting the\n    provisions above and replace them with the notice and other provisions\n    required by the GPL in this and the other files of this package. If you do\n    not delete the provisions above, a recipient may use your version of this\n    file under either the BSD or the GPL.\n  \"\"\"\n\n- libeio, located at deps/uv/src/unix/eio. libeio's license follows:\n  \"\"\"\n    All files in libeio are Copyright (C)2007,2008 Marc Alexander Lehmann.\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n\n        * Redistributions of source code must retain the above copyright\n          notice, this list of conditions and the following disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials provided\n          with the distribution.\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\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    Alternatively, the contents of this package may be used under the terms\n    of the GNU General Public License (\"GPL\") version 2 or any later version,\n    in which case the provisions of the GPL are applicable instead of the\n    above. If you wish to allow the use of your version of this package only\n    under the terms of the GPL and not to allow others to use your version of\n    this file under the BSD license, indicate your decision by deleting the\n    provisions above and replace them with the notice and other provisions\n    required by the GPL in this and the other files of this package. If you do\n    not delete the provisions above, a recipient may use your version of this\n    file under either the BSD or the GPL.\n  \"\"\"\n\n- WAF build system, located at tools/waf*. WAF's license follows:\n  \"\"\"\n    Copyright Thomas Nagy, 2005-2011\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 name of the author may not be used to endorse or promote products\n       derived from this software without specific prior written permission.\n\n    THIS SOFTWARE IS PROVIDED BY THE AUTHOR \"AS IS\" AND ANY EXPRESS OR\n    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n    DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\n    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n    POSSIBILITY OF SUCH DAMAGE.\n  \"\"\"\n\n- C-Ares, an asynchronous DNS client, located at deps/uv/src/ares. C-Ares license\n  follows\n  \"\"\"\n    /* Copyright 1998 by the Massachusetts Institute of Technology.\n     *\n     * Permission to use, copy, modify, and distribute this\n     * software and its documentation for any purpose and without\n     * fee is hereby granted, provided that the above copyright\n     * notice appear in all copies and that both that copyright\n     * notice and this permission notice appear in supporting\n     * documentation, and that the name of M.I.T. not be used in\n     * advertising or publicity pertaining to distribution of the\n     * software without specific, written prior permission.\n     * M.I.T. makes no representations about the suitability of\n     * this software for any purpose.  It is provided \"as is\"\n     * without express or implied warranty.\n  \"\"\"\n\n- OpenSSL located at deps/openssl. OpenSSL is cryptographic software written\n  by Eric Young (eay@cryptsoft.com) to provide SSL/TLS encryption. OpenSSL's\n  license follows\n  \"\"\"\n    /* ====================================================================\n     * Copyright (c) 1998-2011 The OpenSSL Project.  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\n     *    the documentation and/or other materials provided with the\n     *    distribution.\n     *\n     * 3. All advertising materials mentioning features or use of this\n     *    software must display the following acknowledgment:\n     *    \"This product includes software developed by the OpenSSL Project\n     *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n     *\n     * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n     *    endorse or promote products derived from this software without\n     *    prior written permission. For written permission, please contact\n     *    openssl-core@openssl.org.\n     *\n     * 5. Products derived from this software may not be called \"OpenSSL\"\n     *    nor may \"OpenSSL\" appear in their names without prior written\n     *    permission of the OpenSSL Project.\n     *\n     * 6. Redistributions of any form whatsoever must retain the following\n     *    acknowledgment:\n     *    \"This product includes software developed by the OpenSSL Project\n     *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n     *\n     * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n     * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n     * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n     * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n     * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n     * OF THE POSSIBILITY OF SUCH DAMAGE.\n     * ====================================================================\n     *\n     * This product includes cryptographic software written by Eric Young\n     * (eay@cryptsoft.com).  This product includes software written by Tim\n     * Hudson (tjh@cryptsoft.com).\n     *\n     */\n  \"\"\"\n\n- HTTP Parser, located at deps/http_parser. HTTP Parser's license follows:\n  \"\"\"\n    http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright\n    Igor Sysoev.\n\n    Additional changes are licensed under the same terms as NGINX and\n    copyright Joyent, Inc. and other Node contributors. All rights reserved.\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to\n    deal in the Software without restriction, including without limitation the\n    rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n    sell copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n    IN THE SOFTWARE.\n  \"\"\"\n\n- Closure Linter is located at tools/closure_linter. Closure's license\n  follows\n  \"\"\"\n    # Copyright (c) 2007, Google Inc.\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 are\n    # 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\n    # copyright notice, this list of conditions and the following disclaimer\n    # in the documentation and/or other materials provided with the\n    # distribution.\n    #     * Neither the name of Google Inc. nor the names of its\n    # contributors may be used to endorse or promote products derived from\n    # this software without specific prior written 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\n    # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n  \"\"\"\n\n- tools/cpplint.py is a C++ linter. Its license follows:\n  \"\"\"\n    # Copyright (c) 2009 Google Inc. 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 are\n    # 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\n    # copyright notice, this list of conditions and the following disclaimer\n    # in the documentation and/or other materials provided with the\n    # distribution.\n    #    * Neither the name of Google Inc. nor the names of its\n    # contributors may be used to endorse or promote products derived from\n    # this software without specific prior written 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\n    # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n  \"\"\"\n\n- lib/buffer_ieee754.js. Its license follows:\n  \"\"\"\n    // Copyright (c) 2008, Fair Oaks Labs, Inc.\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 are met:\n    //\n    //  * Redistributions of source code must retain the above copyright notice,\n    //    this list of conditions and the following disclaimer.\n    //\n    //  * Redistributions in binary form must reproduce the above copyright notice,\n    //    this list of conditions and the following disclaimer in the documentation\n    //    and/or other materials provided with the distribution.\n    //\n    //  * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors\n    //    may be used to endorse or promote products derived from this software\n    //    without specific prior written permission.\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 THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n    // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n    // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n    // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n    // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n    // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n    // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n    // POSSIBILITY OF SUCH DAMAGE.\n  \"\"\"\n\n- lib/punycode.js is copyright 2011 Mathias Bynens <http://mathiasbynens.be/>\n  and released under the MIT license.\n  \"\"\"\n    * Punycode.js <http://mths.be/punycode>\n    * Copyright 2011 Mathias Bynens <http://mathiasbynens.be/>\n    * Available under MIT license <http://mths.be/mit>\n  \"\"\"\n\n- tools/gyp GYP is a meta-build system. GYP's license follows:\n  \"\"\"\n    Copyright (c) 2009 Google Inc. 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 are\n    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\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n       * Neither the name of Google Inc. nor the names of its\n    contributors may be used to endorse or promote products derived from\n    this software without specific prior written 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\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n  \"\"\"\n\n- Zlib at deps/zlib. zlib's license follows\n  \"\"\"\n    /* zlib.h -- interface of the 'zlib' general purpose compression library\n      version 1.2.4, March 14th, 2010\n\n      Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler\n\n      This software is provided 'as-is', without any express or implied\n      warranty.  In no event will the authors be held liable for any damages\n      arising from the use of this software.\n\n      Permission is granted to anyone to use this software for any purpose,\n      including commercial applications, and to alter it and redistribute it\n      freely, subject to the following restrictions:\n\n      1. The origin of this software must not be misrepresented; you must not\n         claim that you wrote the original software. If you use this software\n         in a product, an acknowledgment in the product documentation would be\n         appreciated but is not required.\n      2. Altered source versions must be plainly marked as such, and must not be\n         misrepresented as being the original software.\n      3. This notice may not be removed or altered from any source distribution.\n\n      Jean-loup Gailly\n      Mark Adler\n\n    */\n  \"\"\"\n\n- npm is a package manager program located at deps/npm.\n  npm's license follows:\n  \"\"\"\n    Copyright 2009-2012, Isaac Z. Schlueter (the \"Original Author\")\n    All rights reserved.\n\n    MIT +no-false-attribs License\n\n    Permission is hereby granted, free of charge, to any person\n    obtaining a copy of this software and associated documentation\n    files (the \"Software\"), to deal in the Software without\n    restriction, including without limitation the rights to use,\n    copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the\n    Software is furnished to do so, subject to the following\n    conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Distributions of all or part of the Software intended to be used\n    by the recipients as they would use the unmodified Software,\n    containing modifications that substantially alter, remove, or\n    disable functionality of the Software, outside of the documented\n    configuration mechanisms provided by the Software, shall be\n    modified such that the Original Author's bug reporting email\n    addresses and urls are either replaced with the contact information\n    of the parties responsible for the changes, or removed entirely.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n    OTHER DEALINGS IN THE SOFTWARE.\n\n\n    Except where noted, this license applies to any and all software\n    programs and associated documentation files created by the\n    Original Author, when distributed with the Software.\n\n    \"Node.js\" and \"node\" trademark Joyent, Inc. npm is not officially\n    part of the Node.js project, and is neither owned by nor\n    officially affiliated with Joyent, Inc.\n\n    Packages published in the npm registry are not part of npm\n    itself, are the sole property of their respective maintainers,\n    and are not covered by this license.\n\n    \"npm Logo\" created by Mathias Pettersson and Brian Hammond,\n    used with permission.\n\n    This program uses \"node-uuid\", Copyright (c) 2010 Robert Kieffer,\n    according to the terms of the MIT license.\n\n    This program uses \"request\", Copyright (c) 2011 Mikeal Rogers,\n    according to the terms of the Apache license.\n\n    This program uses \"mkdirp\",  Copyright (c) 2010 James Halliday,\n    according to the terms of the MIT/X11 license.\n  \"\"\"\n\n- tools/doc/node_modules/marked Marked is a Markdown parser. Marked's\n  license follows\n  \"\"\"\n    Copyright (c) 2011-2012, Christopher Jeffrey (https://github.com/chjj/)\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n  \"\"\"\n"
  },
  {
    "path": "LICENSES/PublicDomain.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n\n----------\njson2: https://github.com/douglascrockford/JSON-js\n----------\n\nBy Douglas Crockford\n2011-10-19\n\nPublic Domain.\n\nNO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n\n\n----------\nmeyerweb-reset: http://meyerweb.com/eric/tools/css/reset/\n----------\n\nBy Eric A. Meyer\nv2.0 | 20110126\nLicense: none (public domain)\n\n\n----------\nenable2k word list: http://personal.riverusers.com/~thegrendel/software.html\n----------\n\nThe ENABLE list has been placed in the Public Domain. This means it is free\nand freely distributable. No fees, registrations, or \"contributions\" are\nrequired for its use.\n\n\n\n----------\nstream-buffers: https://github.com/samcday/node-stream-buffer\n----------\n\nThis is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <http://unlicense.org/>\n\n\n----------\njsonify: https://github.com/substack/jsonify\n----------\n\npublic domain\n"
  },
  {
    "path": "LICENSES/andris9.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n\n----------\nmimelib-noiconv: https://github.com/andris9/mimelib\nmailcomposer: https://github.com/andris9/mailcomposer\nsimplesmtp: https://github.com/andris9/simplesmtp\nrai: https://github.com/andris9/rai\nxoauth2: https://github.com/andris9/xoauth2\n----------\n\nCopyright (c) 2012 Andris Reinman\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "LICENSES/browserify.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n\n----------\nbrowserify: https://github.com/substack/node-browserify\n----------\n\nMIT\n\nSome pieces from builtins/ taken from node core under this license:\n\n----\n\nCopyright Joyent, Inc. and other Node contributors.\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to permit\npersons to whom the Software is furnished to do so, subject to the\nfollowing conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\nNO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\nDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\nUSE OR OTHER DEALINGS IN THE SOFTWARE.\n\n----\n\nbuffer_ieee754.js has this license in it:\n\n----\n\nCopyright (c) 2008-2014, Fair Oaks Labs, Inc.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n * Redistributions of source code must retain the above copyright notice,\n   this list of conditions and the following disclaimer.\n\n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\n * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\nINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.\n\nModifications to writeIEEE754 to support negative zeroes made by Brian White\n\n"
  },
  {
    "path": "LICENSES/commonmark.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n----------\ncommonmark: https://github.com/jgm/commonmark.js\n----------\n\nCopyright (c) 2014, John MacFarlane\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, 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\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials provided\n      with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n---\n\nlib/encode.js and lib/decode.js come from\nhttps://github.com/markdown-it/mdurl\n\nCopyright (c) 2015 Vitaly Puzrin, Alex Kocharin.\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n---\n\nlib/normalize-reference.js is a slightly modified version of\nhttps://github.com/dmoscrop/fold-case:\n\nCopyright Mathias Bynens <https://mathiasbynens.be/>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---\n\nlib/from-code-point.js is derived from a polyfill\nCopyright Mathias Bynens <http://mathiasbynens.be/>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---\n\nbench/samples/*.md:\n\nWith the exception of `bench/samples/README.md`, the samples in\n`bench/samples` are taken from https://github.com/markdown-it/markdown-it.\n\nCopyright (c) 2014 Vitaly Puzrin, Alex Kocharin.\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n---\n\nThe CommonMark spec (spec.txt) in test/ is\n\nCopyright (C) 2014-15 John MacFarlane\n\nReleased under the Creative Commons CC-BY-SA 4.0 license:\n<http://creativecommons.org/licenses/by-sa/4.0/>.\n"
  },
  {
    "path": "LICENSES/heapdump.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n\n----------\nheapdump: https://github.com/bnoordhuis/node-heapdump\n----------\n\nCopyright (c) 2012, Ben Noordhuis <info@bnoordhuis.nl>\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n"
  },
  {
    "path": "LICENSES/ieee754.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n----------\nieee754: https://github.com/feross/ieee754\n----------\n\nThe MIT License (MIT)\n\nCopyright (c) Feross Aboukhadijeh\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n===========================================\nieee754 originally contained this license:\n===========================================\n\nCopyright (c) 2008, Fair Oaks Labs, Inc.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n * Redistributions of source code must retain the above copyright notice,\n   this list of conditions and the following disclaimer.\n\n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\n * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\nINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.\n\nModifications to writeIEEE754 to support negative zeroes made by Brian White.\n\n"
  },
  {
    "path": "LICENSES/jsdoc.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n----------\njsdoc: https://github.com/jsdoc3/jsdoc\n----------\n\n# License #\n\nJSDoc 3 is free software, licensed under the Apache License, Version 2.0 (the\n\"License\"). Commercial and non-commercial use are permitted in compliance with\nthe License.\n\nCopyright (c) 2011-2014 Michael Mathews <micmath@gmail.com> and the\n[contributors to JSDoc](https://github.com/jsdoc3/jsdoc/graphs/contributors).\nAll rights reserved.\n\nYou may obtain a copy of the License at:\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nIn addition, a copy of the License is included with this distribution.\n\nAs stated in Section 7, \"Disclaimer of Warranty,\" of the License:\n\n> Licensor provides the Work (and each Contributor provides its Contributions)\n> on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either\n> express or implied, including, without limitation, any warranties or\n> conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n> PARTICULAR PURPOSE. You are solely responsible for determining the\n> appropriateness of using or redistributing the Work and assume any risks\n> associated with Your exercise of permissions under this License.\n\nThe source code for JSDoc 3 is available at:\nhttps://github.com/jsdoc3/jsdoc\n\n# Third-Party Software #\n\nJSDoc 3 includes or depends upon the following third-party software, either in\nwhole or in part. Each third-party software package is provided under its own\nlicense.\n\n## MIT License ##\n\nSeveral of the following software packages are distributed under the MIT\nlicense, which is reproduced below:\n\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n## Acorn ##\n\nPortions of the Acorn source code are incorporated into the following files:\n\n- `lib/jsdoc/src/walker.js`\n\nAcorn is distributed under the MIT license, which is reproduced above.\n\nCopyright (C) 2012 Marijn Haverbeke <marijnh@gmail.com>.\n\nThe source code for Acorn is available at:\nhttps://github.com/marijnh/acorn\n\n## Async.js ##\n\nAsync.js is distributed under the MIT license, which is reproduced above.\n\nCopyright (c) 2010 Caolan McMahon.\n\nThe source code for Async.js is available at:\nhttps://github.com/caolan/async\n\n## Catharsis ##\n\nCatharsis is distributed under the MIT license, which is reproduced above.\n\nCopyright (c) 2012-2014 Jeff Williams.\n\nThe source code for Catharsis is available at:\nhttps://github.com/hegemonic/catharsis\n\n## crypto-browserify ##\n\ncrypto-browserify is distributed under the MIT license, which is reproduced\nabove.\n\nCopyright (c) 2013 Dominic Tarr.\n\nThe source code for crypto-browserify is available at:\nhttps://github.com/dominictarr/crypto-browserify\n\n## escape-string-regexp ##\n\nescape-string-regexp is distributed under the MIT License, which is reproduced\nabove.\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com>.\n\nThe source code for escape-string-regexp is available at:\nhttps://github.com/sindresorhus/escape-string-regexp\n\n## Esprima ##\n\nEsprima is distributed under the BSD 2-clause license:\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 notice,\n>   this list of conditions and the following disclaimer.\n> - Redistributions in binary form must reproduce the above copyright notice,\n>   this list of conditions and the following disclaimer in the documentation\n>   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\nCopyright (c) 2011-2013 Ariya Hidayat and other Esprima contributors.\n\nThe source code for Esprima is available at:\nhttps://github.com/ariya/esprima\n\n## events ##\n\nPortions of the events source code are incorporated into the following files:\n\n+ `rhino/events.js`\n\nevents is distributed under the MIT license, which is reproduced above.\n\nCopyright Joyent, Inc. and other Node contributors. All rights reserved.\n\nThe source code for events is available at:\nhttps://github.com/Gozala/events\n\n## github-flavored-markdown ##\n\ngithub-flavored-markdown is distributed under the BSD 3-clause license:\n\n> Copyright (c) 2007, John Fraser <http://www.attacklab.net/> All rights\n> reserved.\n>\n> Original Markdown copyright (c) 2004, John Gruber <http://daringfireball.net/>\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 are met:\n>\n> - Redistributions of source code must retain the above copyright notice,\n>   this list of conditions and the following disclaimer.\n>\n> - Redistributions in binary form must reproduce the above copyright notice,\n>   this list of conditions and the following disclaimer in the documentation\n>   and/or other materials provided with the distribution.\n\n> - Neither the name \"Markdown\" nor the names of its contributors may be used\n>   to endorse or promote products derived from this software without specific\n>   prior written permission.\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 are\n> disclaimed. In no event shall the copyright owner or contributors be liable\n> for any direct, indirect, incidental, special, exemplary, or consequential\n> damages (including, but not limited to, procurement of substitute goods or\n> services; loss of use, data, or profits; or business interruption) however\n> caused and on any theory of liability, whether in contract, strict liability,\n> or tort (including negligence or otherwise) arising in any way out of the use\n> of this software, even if advised of the possibility of such damage.\n\nThe source code for github-flavored-markdown is available at:\nhttps://github.com/hegemonic/github-flavored-markdown\n\n## Google Code Prettify ##\n\nGoogle Code Prettify is distributed under the Apache License 2.0, which is\nincluded with this package.\n\nCopyright (c) 2006 Google Inc.\n\nThe source code for Google Code Prettify is available at:\nhttps://code.google.com/p/google-code-prettify/\n\n## Jasmine ##\n\nJasmine is distributed under the MIT license, which is reproduced above.\n\nCopyright (c) 2008-2011 Pivotal Labs.\n\nThe source code for Jasmine is available at:\nhttps://github.com/pivotal/jasmine\n\n## jasmine-node ##\n\njasmine-node is distributed under the MIT license, which is reproduced above.\n\nCopyright (c) 2010 Adam Abrons and Misko Hevery (http://getangular.com).\n\nThe source code for jasmine-node is available at:\nhttps://github.com/mhevery/jasmine-node\n\n## js2xmlparser ##\n\njs2xmlparser is distributed under the MIT license, which is reproduced above.\n\nCopyright (c) 2012 Michael Kourlas.\n\nThe source code for js2xmlparser is available at:\nhttps://github.com/michaelkourlas/node-js2xmlparser\n\n## Node.js ##\n\nPortions of the Node.js source code are incorporated into the following files:\n\n- `rhino/fs.js`\n- `rhino/path.js`\n- `rhino/querystring.js`\n- `rhino/util.js`\n\nNode.js is distributed under the MIT license, which is reproduced above.\n\nCopyright Joyent, Inc. and other Node contributors. All rights reserved.\n\nThe source code for Node.js is available at:\nhttps://github.com/joyent/node\n\n## node-browser-builtins ##\n\nPortions of the node-browser-builtins source code are incorporated into the\nfollowing files:\n\n- `rhino/assert.js`\n- `rhino/rhino-shim.js`\n\nnode-browser-builtins is distributed under the MIT license, which is reproduced\nabove.\n\nThe source code for node-browser-builtins is available at:\nhttps://github.com/alexgorbatchev/node-browser-builtins\n\n## Requizzle ##\n\nRequizzle is distributed under the MIT license, which is reproduced above.\n\nCopyright (c) 2014 Google Inc. All rights reserved.\nCopyright (c) 2012-2013 Johannes Ewald.\n\nThe source code for Requizzle is available at:\nhttps://github.com/hegemonic/requizzle\n\n## Rhino ##\n\nRhino is distributed under the following licenses:\n\n### MPL 2.0 License ###\nThe majority of the source code for Rhino is available under the Mozilla Public\nLicense (MPL) 2.0, which is included in this distribution.\n\n### License for portions of the Rhino debugger ###\nAdditionally, some files are available under the BSD 3-clause license:\n\n> Copyright 1997, 1998 Sun Microsystems, Inc.  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 are met:\n>\n> - Redistributions of source code must retain the above copyright notice,\n>   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> - Neither the name of Sun Microsystems nor the names of its contributors\n>   may be used to endorse or promote products derived from this software\n>   without specific prior written permission.\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 ARE\n> DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\n> FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n> DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n> SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n> OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n> OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n### Source Code ###\nThe source code for Rhino is available at:\nhttps://github.com/jsdoc3/rhino\n\n## TaffyDB ##\n\nTaffyDB is distributed under a modified BSD license:\n\n> All rights reserved.\n>\n> Redistribution and use of this software in source and binary forms, with or\n> without modification, are permitted provided that the following condition is\n> met:\n>\n> Redistributions of source code must retain the above copyright notice, this\n> list of conditions and the following disclaimer.\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 THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n> LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n> CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n> SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n> INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n> CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n> ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n> POSSIBILITY OF SUCH DAMAGE.\n\nThe source code for TaffyDB is available at:\nhttps://github.com/hegemonic/taffydb\n\n## Tomorrow Theme for Google Code Prettify ##\n\nLicense information for the Tomorrow Theme for Google Code Prettify is not\navailable. It is assumed that the package is distributed under an open source\nlicense that is compatible with the Apache License 2.0.\n\nCopyright (c) Yoshihide Jimbo.\n\nThe source code for the Tomorrow Theme is available at:\nhttps://github.com/jmblog/color-themes-for-google-code-prettify\n\n## tv4 ##\n\ntv4 is in the public domain. It is also distributed under the MIT license, which\nis reproduced above.\n\nThe source code for tv4 is available at:\nhttps://github.com/geraintluff/tv4\n\n## Underscore.js ##\n\nUnderscore.js is distributed under the MIT license, which is reproduced above.\n\nCopyright (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative\nReporters & Editors.\n\nThe source code for Underscore.js is available at:\nhttps://github.com/jashkenas/underscore\n\n## wrench-js ##\n\nwrench-js is distributed under the MIT license, which is reproduced above.\n\nCopyright (c) 2010 Ryan McGrath.\n\nThe source code for wrench-js is available at:\nhttps://github.com/ryanmcgrath/wrench-js\n"
  },
  {
    "path": "LICENSES/libuv.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n----------\nlibuv: https://github.com/joyent/libuv\n----------\n\nlibuv is part of the Node project: http://nodejs.org/\nlibuv may be distributed alone under Node's license:\n\n====\n\nCopyright Joyent, Inc. and other Node contributors. All rights reserved.\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n\n====\n\nThis license applies to all parts of libuv that are not externally\nmaintained libraries.\n\nThe externally maintained libraries used by libuv are:\n\n  - tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license.\n\n  - ngx_queue.h (from Nginx), copyright Igor Sysoev. Two clause BSD license.\n\n  - c-ares, copyright Daniel Stenberg and others. MIT licensed.\n\n  - libev, located at ev/ is copyright Marc Alexander Lehmann, and\n    dual-licensed under the MIT license and GPL2.\n\n  - libeio, located at eio/ is copyright Marc Alexander Lehmann, and\n    dual-licensed under the MIT license and GPL2.\n\n"
  },
  {
    "path": "LICENSES/nan.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n----------\nnan: https://github.com/rvagg/nan\n----------\n\nCopyright 2013, NAN contributors:\n  - Rod Vagg <https://github.com/rvagg>\n  - Benjamin Byholm <https://github.com/kkoopa>\n  - Trevor Norris <https://github.com/trevnorris>\n  - Nathan Rajlich <https://github.com/TooTallNate>\n  - Brett Lawson <https://github.com/brett19>\n  - Ben Noordhuis <https://github.com/bnoordhuis>\n(the \"Original Author\")\nAll rights reserved.\n\nMIT +no-false-attribs License\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nDistributions of all or part of the Software intended to be used\nby the recipients as they would use the unmodified Software,\ncontaining modifications that substantially alter, remove, or\ndisable functionality of the Software, outside of the documented\nconfiguration mechanisms provided by the Software, shall be\nmodified such that the Original Author's bug reporting email\naddresses and urls are either replaced with the contact information\nof the parties responsible for the changes, or removed entirely.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n\nExcept where noted, this license applies to any and all software\nprograms and associated documentation files created by the\nOriginal Author, when distributed with the Software.\n"
  },
  {
    "path": "LICENSES/through2.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n\n\n----------\nthrough2: https://github.com/rvagg/through2\n----------\n\nCopyright 2013, Rod Vagg (the \"Original Author\")\nAll rights reserved.\n\nMIT +no-false-attribs License\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nDistributions of all or part of the Software intended to be used\nby the recipients as they would use the unmodified Software,\ncontaining modifications that substantially alter, remove, or\ndisable functionality of the Software, outside of the documented\nconfiguration mechanisms provided by the Software, shall be\nmodified such that the Original Author's bug reporting email\naddresses and urls are either replaced with the contact information\nof the parties responsible for the changes, or removed entirely.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n\nExcept where noted, this license applies to any and all software\nprograms and associated documentation files created by the\nOriginal Author, when distributed with the Software.\n"
  },
  {
    "path": "LICENSES/tough-cookie.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n\n\n----------\ntough-cookie: https://github.com/goinstant/tough-cookie\n----------\n\nCopyright GoInstant, Inc. and other contributors. All rights reserved.\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n\nThe following exceptions apply:\n\n===\n\n`pubSufTest()` of generate-pubsuffix.js is in the public domain.\n\n  // Any copyright is dedicated to the Public Domain.\n  // http://creativecommons.org/publicdomain/zero/1.0/\n\n===\n\n`public-suffix.txt` was obtained from\n<https://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1>\nvia <http://publicsuffix.org>.\n\nThat file contains the usual Mozilla triple-license, for which this project uses it\nunder the terms of the MPL 1.1:\n\n    // ***** BEGIN LICENSE BLOCK *****\n    // Version: MPL 1.1/GPL 2.0/LGPL 2.1\n    //\n    // The contents of this file are subject to the Mozilla Public License Version\n    // 1.1 (the \"License\"); you may not use this file except in compliance with\n    // the License. You may obtain a copy of the License at\n    // http://www.mozilla.org/MPL/\n    //\n    // Software distributed under the License is distributed on an \"AS IS\" basis,\n    // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n    // for the specific language governing rights and limitations under the\n    // License.\n    //\n    // The Original Code is the Public Suffix List.\n    //\n    // The Initial Developer of the Original Code is\n    // Jo Hermans <jo.hermans@gmail.com>.\n    // Portions created by the Initial Developer are Copyright (C) 2007\n    // the Initial Developer. All Rights Reserved.\n    //\n    // Contributor(s):\n    //   Ruben Arakelyan <ruben@rubenarakelyan.com>\n    //   Gervase Markham <gerv@gerv.net>\n    //   Pamela Greene <pamg.bugs@gmail.com>\n    //   David Triendl <david@triendl.name>\n    //   Jothan Frakes <jothan@gmail.com>\n    //   The kind representatives of many TLD registries\n    //\n    // Alternatively, the contents of this file may be used under the terms of\n    // either the GNU General Public License Version 2 or later (the \"GPL\"), or\n    // the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n    // in which case the provisions of the GPL or the LGPL are applicable instead\n    // of those above. If you wish to allow use of your version of this file only\n    // under the terms of either the GPL or the LGPL, and not to allow others to\n    // use your version of this file under the terms of the MPL, indicate your\n    // decision by deleting the provisions above and replace them with the notice\n    // and other provisions required by the GPL or the LGPL. If you do not delete\n    // the provisions above, a recipient may use your version of this file under\n    // the terms of any one of the MPL, the GPL or the LGPL.\n    //\n    // ***** END LICENSE BLOCK *****\n\n"
  },
  {
    "path": "LICENSES/unorm.txt",
    "content": "====================================================================\nFor the license for Meteor itself, see LICENSE.txt in the root of\nthe repository.  This file contains the licenses for externally\nmaintained libraries.\n====================================================================\n\n\n\n----------\nunorm: https://github.com/walling/unorm\n----------\n\nThe software dual licensed under the MIT and GPL licenses. MIT license:\n\nCopyright (c) 2008-2013 Matsuza <matsuza@gmail.com>, Bjarke Walling <bwp@bwp.dk>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\nGPL notice (please read the full GPL license online):\n\nCopyright (C) 2008-2013 Matsuza <matsuza@gmail.com>, Bjarke Walling <bwp@bwp.dk>\n\nThis program is free software; you can redistribute it and/or\nmodify it under the terms of the GNU General Public License\nas published by the Free Software Foundation; either version 2\nof the License, or (at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n"
  },
  {
    "path": "README.md",
    "content": "![meteor-universal-logo meteorjs arm cortex udoo raspberrypi odroid](https://cloud.githubusercontent.com/assets/410087/10517017/2c32e7d6-735b-11e5-9677-3caf479af53a.png)\n\n\n\n# Meteor\n\nMeteor is an ultra-simple environment for building modern web\napplications.\n\nWith Meteor you write apps:\n\n* in pure JavaScript\n* that send data over the wire, rather than HTML\n* using your choice of popular open-source libraries\n\nTry the getting started [tutorial](https://www.meteor.com/try).\n\nNext, read the [guide](http://guide.meteor.com) or the reference documentation at http://docs.meteor.com/.\n\n<br/>\n\n# Meteor universal fork\n\n## enable the yet unsupported architectures\n\nThe meteor universal fork allows to run meteorjs on yet not officially\nsupported architectures. Especially ARM processors ARMv6 and ARMv7 \n(UDOO, Raspberry Pi, Banana Pi, ODroid etc.) are provided due to our \npre-built dev_bundles.\n\nThe universal fork will try use any official meteor binaries as long as \nthey does support the target architecture. All universal pre-built \nbundles are available at our [BINTRAY Repository](https://bintray.com/4commerce-technologies-ag/meteor-universal)\n\n<br/>\n\n##### This fork is known to work on:\n\n1. UDOO Dual, Quad, Neo (Lubuntu 12.04, Debian Jessie, UDOObuntu 2, Ubuntu Core 14.04)\n1. Raspberry Pi 1B + Pi 2 (Raspbian wheezy + jessie, Ubuntu 14.04)\n1. ODROID C1 + U3 (Lubuntu 14.04)\n1. BeagleBone Black (Ubuntu 14.04)\n1. PcDuino v3 (Ubuntu 14.04)\n1. Scaleway.com Server (Debian, Ubuntu 14.04)\n1. ARM Chromebook\n1. Nexus 7 (Ubuntu 14.04)\n1. FreeBSD 10.2 (i686, x86_64, amd64)\n1. OpenBSD 5.7 (i686, x86_64, amd64)\n\n_... plus an uncounted number of compatible OSs driven devices_\n\n<br/>\n\n## Quick Start\n\n... on supported architectures like ARMv6, ARMv7, i686, x86_64, amd64 and OSs like\nDebian (derivates), Ubuntu, Arch, CentOS, OSX, FreeBSD, OpenBSD and Windows.\n\nPlease read section [\"Preparing yet unsupported\"](#preparing-yet-unsupported) for tips on installing and running\nmeteor on yet unsupported architectures and OSs.\n\n<br/>\n##### Get Meteor (e.g. into your $HOME):\n\n```bash\ncd $HOME\n\ngit clone --depth 1 https://github.com/4commerce-technologies-AG/meteor.git\n```\n\n<br/>\n##### Check installed version:\n\n```bash\n$HOME/meteor/meteor --version\n```\n\n> Running the above command for the first time will try to download\n> a compatible pre-built dev_bundle and finish the installation.\n> Depending on your hardware this may take some time.\n\n<br/>\n##### Create and run a \"Hello World\" example (optionally):\n\n```bash\ncd $HOME\n\n$HOME/meteor/meteor create hello-world\n\ncd hello-world\n\n$HOME/meteor/meteor\n```\n\n<br/>\n##### Create and run a \"reactJS\" example (optionally):\n\n```bash\ncd $HOME\n\n# get the command line to checkout the meteor example\n$HOME/meteor/meteor create --example simple-todos-react\n\n# this is what you will receive as command hint, so put it in\ngit clone https://github.com/meteor/simple-todos-react\n\n# jump into the project folder\ncd simple-todos-react\n\n# get necessary npm stuff\n$HOME/meteor/meteor npm install\n\n# bring that project up to latest module updates\n$HOME/meteor/meteor update --packages-only\n\n# add one package to avoid counting of modules usage and DDP error message on start\n$HOME/meteor/meteor add package-stats-opt-out\n\n# run that app\n$HOME/meteor/meteor\n```\n\n<br/>\n\n## Slow Start\n\n... if looking for self building your dev_bundles or on not getting a\npre-built dev_bundle for your platform.\n\nIf you're the sort of person who needs to build meteor on unsupported\narchitectures you can build all the Meteor stuff with the provided scripts.\nThis requires git, a C and C++ compiler, autotools and scons etc.\n\nYou may also decide to build the bundled node and mongodb sources for your platform\nor to use the system wide installed packages of them. We suggest to build \nat least the bundle nodejs sources if possible, to be sure that these versions\nare compatible. We have ported the bundled mongodb sources to ARM architecture\nyet, so this might not be be able to compile on your architecture. We\nsuggest to use and install the system available binaries for mongo in\nany case that pre-built dev_bundle are not available. Please have a look\nat our [Meteor Universal Blog](http://meteor-universal.tumblr.com) for\na lot of documentation about setting up your system to build the sources.\n\n\n<br/>\n##### Get Meteor (e.g. into your $HOME):\n\n```bash\ncd $HOME\n\ngit clone --depth 1 https://github.com/4commerce-technologies-AG/meteor.git\n\ncd meteor\n```\n\n<br/>\n##### Build bundled node:\n\n```bash\nscripts/build-node-for-dev-bundle.sh\n```\n\n<br/>\n##### Get mongodb installation from OS (e.g. Debian based):\n\n```bash\nsudo apt-get install mongodb\n```\n\n<br/>\n##### Optional (long runner) build bundled mongo:\n\n```bash\nscripts/build-node-for-dev-bundle.sh\n```\n\n> Beneath the compiler and development tools and standard libaries, you have to also\n> install the zlib1g-dev (or whatever it's named on your OS) library sources.\n> Otherwise the mongo build will fail with an error like \"-lz is missing\"\n\n<br/>\n##### Build meteor dev_bundle:\n\n```bash\nscripts/generate-dev-bundle.sh\n```\n\n<br/>\n##### Check installed version:\n\n```bash\n$HOME/meteor/meteor --version\n```\n\n> If you were successful in building your dev_bundles, you created\n> your local dev_bundle tarballs. Now running the above command for\n> the first time will use this local tarballs and finish the meteor\n> installation. Depending on your hardware this may take some time.\n\n<br/>\n##### Create and run Hello World:\n\nIf all was successfully build and installed, you may continue with\nyour first meteor example.\n\n```bash\ncd $HOME\n\n$HOME/meteor/meteor create hello-world\n\ncd hello-world\n\n$HOME/meteor/meteor\n```\n\n<br/>\n## Preparing yet unsupported\n\nIn some cases you need to install additional packages from your OSs to be ready for meteor. Read below preparations on different architectures and OSs.\n\n<br/>\n##### Install compiler and dependent packages on Debian(-based)\n\n```bash\nsudo apt-get install build-essential debian-keyring autoconf automake libtool flex bison scons git mongodb\n```\n\n<br/>\n##### Install compiler and dependent packages on FreeBSD\n\n```bash\nsudo pkg install -y bash gmake git mongodb\n```\n\n<br/>\n##### Install compiler and dependent packages on OpenBSD\n\n```bash\nsudo pkg_add bash gmake flock git mongodb\n```\n\nCheck that python is available on _standard_ env location\n\n```bash\nenv python --version\n```\n\nIf that fails please link the installed python release as default (e.g. python2.7):\n\n```bash\nsudo ln -s /usr/local/bin/python2.7 /usr/local/bin/python\n```\n\n<br/>\n## Good to know\n\n<br/>\n##### Meteor starter\n\nFor your comfort, you should set an alias or update your $PATH to run meteor from everywhere.\n\n```bash\nalias meteor=\"$HOME/meteor/meteor\"\n```\n\n<br/>\n##### Non-core packages\n\nAfter checkout there are some non-core packages not available like e.g. `npm-bcrypt`. This fork sets the ENV VAR `PACKAGE_DIRS` to include the non-core packages automatically. If you have a special concern you have to set this ENV VAR with your preferred values before calling meteor. In that case the meteor starter will NOT add the non-core packages. Some meteor examples and applications may not work properly without those packages.\n\nIf interested in details you find some more information about non-core packages at [meteor universal blog](http://meteor-universal.tumblr.com/post/111435518849/use-non-core-packages-for-your-meteor-apps)\n\n<br/>\n##### Avoid connection error on first start or if offline\n\nMeteor tries to count usage of packages when you build your app and start it for the first\ntime or after a `meteor reset`. You may decide yourself if you like that or not but sometimes\nthis will prevent to run your application. If e.g. running your device offline and start\n`meteor` you may get the error: _\"Failed to record package usage.\"_\n\nYou can disable recording by just adding a package from meteors embedded packages:\n\n```bash\n# starting in your apps home\ncd <path to your meteor app>\n\n# add the package\nmeteor add package-stats-opt-out\n```\n\nIf interested in details you find some [more information at this issue](https://github.com/4commerce-technologies-AG/meteor/issues/46).\n\n<br/>\n##### Local documentation\n\nFrom your checkout, you can read the docs locally. The `/docs` directory is a\nmeteor application, so simply change into the `/docs` directory and launch\nthe app:\n\n```bash\ncd $HOME/meteor/docs\n\n$HOME/meteor/meteor\n```\n\nYou'll be able to read the docs locally in your browser at\n\n```\nhttp://localhost:3000/\n```\n\n<br/>\n##### Running special releases\n\nNote that if you run Meteor from a git checkout, you cannot pin apps to specific\nMeteor releases or run using different Meteor releases using `--release`.\n\nBut you may checkout different releases of meteor in seperate directories to\nrun special releases. Therefor each universal release has its own tag named by pattern \"release/version.id-universal\". To get e.g. release 1.3.4.1 you may use:\n\n```bash\ncd $HOME\n\ngit clone --depth 1 -b \"release-1.3.4.1-universal\" https://github.com/4commerce-technologies-AG/meteor.git meteor-1.3.4.1-universal\n\n$HOME/meteor-1.3.4.1-universal/meteor --version\n```\n\n> Only since release 1.2.0.2 we provide the pre-built dev_bundles for ARM\n> if you need to use previous realeases, you have to build the dev_bundles\n> once by yourself.\n\n<br/>\n##### Curl (60) SSL certificate problem on installation\n\nIf you get an error like _\"curl: unable to get local issuer certificate\"_\nyou will find the work-around [documented in this issue comment](https://github.com/4commerce-technologies-AG/meteor/issues/37#issuecomment-184310053). Hopefully the Debian project will close that issue once!\n\n<br/>\n##### Mongo locale error on starting meteor\n\nIf you get an error like _\"Looks like MongoDB doesn't understand your locale settings.\"_\nyou will find the solution [documented in this issue](https://github.com/4commerce-technologies-AG/meteor/issues/28).\n\n<br/>\n##### Fibers or Bcrypt missing error on running a builded app\n\nBefore running your app first time after `meteor build` you have to install and\nbuild the necessary node modules. You may run your build process as follows:\n\n```bash\n# starting in your apps home\ncd <path to your meteor app>\n\n# running the build process\nmeteor build --directory ../my-app-build\n\n# go into builds bundle home\ncd ../my-app-build/bundle\n\n# install server side npms\ncd programs/server\nnpm install\n\n# back to builds bundle home\ncd ../..\n\n# run main.js (look at README file in your builds bundle home)\nnode main.js\n```\n\n<br/>\n##### Guide and tutorial issues\n\nSome of the already known issues may also help as a guide or tutorial. Please check out our [_guide flagged issues_](https://github.com/4commerce-technologies-AG/meteor/issues?q=+label%3Aflag%3Aguide+) if your question may already be answered.\n\n<br/>\n## Uninstalling Meteor\n\nThis meteor fork will not install or create any global files – except your developments\nall will stay inside the local meteor directory. To uninstall Meteor, just drop that directory (e.g.):\n\n```bash\nrm -r $HOME/meteor\n```\n\n<br/>\n## Pre-builds for ARM\n\nSince meteor stable release 1.2.0.2 we provide pre-builds for ARMv6 and ARMv7 at our \n[BINTRAY Repository](https://bintray.com/4commerce-technologies-ag/meteor-universal). \nThe embedded installer inside the meteor launcher will try to download the correct\npre-built dev_bundle automatically.\n\nIf you are looking for compatible node packages they are also available at BINTRAY.\n\n<br/>\n## Pre-builds for FreeBSD, OpenBSD\n\nSince meteor stable release 1.2.1 we provide pre-builds for the xBSD OSs at our \n[BINTRAY Repository](https://bintray.com/4commerce-technologies-ag/meteor-universal). \nThe embedded installer inside the meteor launcher will try to download the correct\npre-built dev_bundle automatically.\n\nIf you are looking for compatible node packages they are also available at BINTRAY.\n\n<br/>\n## Developer Resources\n\n<br/>\n##### Building an application with Meteor?\n\n* Announcement list: sign up at http://www.meteor.com/\n* Having problems? Ask for help at: http://stackoverflow.com/questions/tagged/meteor\n* Discussion forums: https://forums.meteor.com/\n* Docs full API: http://docs.meteor.com/#/full/\n* In-depth wiki: https://github.com/meteor/meteor/wiki\n\n<br/>\n##### Interested in Meteor Universal?\n\n* Issue tracker: https://github.com/4commerce-technologies-AG/meteor/issues\n* Knowledge base: http://meteor-universal.tumblr.com\n* Binary repositories: [https://bintray.com/4commerce-technologies-ag/meteor-universal](https://bintray.com/4commerce-technologies-ag/meteor-universal)\n* Meteor forum: [search for meteor universal fork](https://forums.meteor.com/search?q=meteor%20universal%20fork)\n\n<br/>\n##### Interested in updated forks for ARM support?\n\n* Meteor bundled mongodb: [https://github.com/4commerce-technologies-AG/mongo](https://github.com/4commerce-technologies-AG/mongo/commits/ssl-r2.6.7)\n* Meteor bundled node-fibers: [https://github.com/4commerce-technologies-AG/node-fibers](https://github.com/4commerce-technologies-AG/node-fibers/commits/master)\n\n<br/>\n##### Interested in contributing to Meteor?\n\n* Issue tracker: https://github.com/meteor/meteor/issues\n* Contribution guidelines: https://github.com/meteor/meteor/tree/devel/Contributing.md\n\n<br/>\n##### Original Meteor project\n\n* Visit https://github.com/meteor/meteor\n\n<br/>\n\n## Author & Credits\n\nThis fork is supported by [Tom Freudenberg](http://about.me/tom.freudenberg) and the people from [4commerce technologies AG](http://www.4commerce.de/). All work is released under the MIT license\n\nThanks to [Meteor Development Group](https://www.meteor.com) for having initiated this project.\n"
  },
  {
    "path": "Roadmap.md",
    "content": "Meteor Roadmap\n==============\n\nThis document describes the high level features the project has decided to prioritize in the near to medium term future. A large fraction of the MDG core engineering team's time will be dedicated to working on the features described here.\n\nContributors are encouraged to focus their efforts on work that aligns with the roadmap as maintainers will prioritize their time around these contributions. This however does not mean that PR's against other features and bugs will be automatically rejected.\n\nFor the meantime, MDG won't be accepting PR's for changes to the roadmap. We hope to change this in the future as we figure out strategies to decentralize Meteor development.\n\n## MongoDB updates\n\nThe mongo driver that currently ships with Meteor is old and doesn’t reliably work with connecting to MongoDB 3.2 databases (e.g [#6258](https://github.com/meteor/meteor/issues/6258)). We want to update to the latest driver [#5763](https://github.com/meteor/meteor/issues/5763).\n\nIn addition, we'd like to update the dev bundle to ship with the latest stable version of MongoDB (3.2) [#5809](https://github.com/meteor/meteor/issues/5809) as MongoDB 2.6 will be officially sunsetted at the end of October, 2016.\n\n## Support for Node 4 and beyond\n\nWe want to be able to update the version of Node that ships with Meteor to 4 and eventually 6  [#5124](https://github.com/meteor/meteor/issues/5124). [#6537](https://github.com/meteor/meteor/issues/6537) lays the groundwork to overcome the main blocker for updating to Node 4, that is, needing to rebuild all existing Meteor packages that contain binary dependencies.\n\n## Full transition to npm\n\nThe community has rallied around npm as the de-facto standard package manager for JavaScript. We believe committing fully to npm will strengthen the entire JavaScript ecosystem by removing fragmentation, will benefit existing Meteor developers by making it seamless to use any JavaScript package and increase Meteor adoption by aligning it with JavaScript best practices.\n\n1.3 introduced `npm install` support along with ES2015 modules. With 1.4, we would like to transition the Meteor package ecosystem over entirely from Atmosphere to npm. We are still in the early conceptual design phase and expect to update the roadmap once we have a design in place that will underpin further development.\n\n\n## Testing updates\n\nMeteor 1.3 shipped with two new testing modes and many developers are writing test suites and building test drivers as part of migrating to 1.3. We’re looking at improving the feature in upcoming releases, especially our support for continuous integration mode (see [#6755](https://github.com/meteor/meteor/issues/6755) and [#6809](https://github.com/meteor/meteor/issues/6809)).\n\n## Project Governance/Community Contribution\n\nCurrently, it’s difficult for external developers to make meaningful contributions to Meteor as there is no clear guidance on what to work on, how best to do that work and signals around what will/won’t get merged. We plan on fixing this by creating tight documentation around how the project is developed (e.g the [Swift contribution guidelines](https://swift.org/contributing/)) and giving contributors a path towards earning increased privileges that culminate in full commit access. We’re also aiming to move more sub-projects into their own repositories that can be released on their own release schedule and more easily maintained by the community.\n\n## Data (SQL, REST, Performance)\n\nWe're building the next generation data stack for modern applications called [Apollo](https://github.com/apollostack/apollo). We believe the data part of the Meteor stack is impactful enough to deserve it's own fully fledged sub-project that will be compatible with other languages and frameworks. Apollo is born from the Meteor project and is naturally designed to work perfectly with Meteor. It is GraphQL based and will work with multiple data sources starting with REST. Apollo is our answer to bringing SQL and improved performance analysis to Meteor.\n\n\n## View Layer\n\nOur plans around the view layer are to maintain strong integrations (along with guidance) with React, Angular and Blaze. We'll make essential fixes to Blaze but most likely won't be adding new features ourselves. We encourage you to help build the features you need at the [meteor/blaze](https://github.com/meteor/blaze) repository.\n"
  },
  {
    "path": "circle.yml",
    "content": "dependencies:\n  cache_directories:\n    - \"dev_bundle\"\n    - \".meteor\"\n    - \".babel-cache\"\n  override:\n    - ./meteor --get-ready\n\ntest:\n  override:\n    - ./scripts/ci.sh :\n        parallel: true\n        timeout: 1200\n"
  },
  {
    "path": "examples/.gitignore",
    "content": "# Each individual example should include 'local' in foo/.meteor/.gitignore.\n# However, we also include this top-level .gitignore so that the following\n# situation:\n#    $ git checkout some-branch-with-a-new-example\n#    $ (cd examples/unfinished/new-example; meteor)\n#    $ git checkout devel\n# doesn't leave you with tons of files in\n# examples/unfinished/new-example/.meteor/local showing up in your 'git status'.\n\n*/.meteor/local\n*/*/.meteor/local\n\n# We don't want to check example project id files into the main meteor\n# repo... but we do want users who create apps from the examples to check\n# *their* project id files into their repos, so we put this ignore line\n# here rather than in the examples/FOO/.meteor/.gitignore.\n*/.meteor/.id\n"
  },
  {
    "path": "examples/other/benchmark/.meteor/release",
    "content": "0.6.0\n"
  },
  {
    "path": "examples/other/client-info/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/other/client-info/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nstandard-app-packages\ninsecure\npreserve-inputs\n"
  },
  {
    "path": "examples/other/client-info/.meteor/release",
    "content": "0.7.0.1\n"
  },
  {
    "path": "examples/other/client-info/client-info.html",
    "content": "<head>\n  <title>Client Info</title>\n</head>\n\n<body>\n  {{> info}}\n</body>\n\n<template name=\"info\">\n  <h1>Client Info</h1>\n\n  <p>Information about this client available on the server:</p>\n\n  <pre>{{info}}</pre>\n</template>\n"
  },
  {
    "path": "examples/other/client-info/client-info.js",
    "content": "if (Meteor.isServer) {\n  Meteor.publish(\"clientInfo\", function () {\n    var self = this;\n    self.added(\"clientInfo\", \"info\", {\n      clientAddress: self.connection.clientAddress,\n      httpHeaders: self.connection.httpHeaders\n    });\n    self.ready();\n  });\n}\n\nif (Meteor.isClient) {\n  Meteor.subscribe(\"clientInfo\");\n  var ClientInfo = new Mongo.Collection(\"clientInfo\");\n\n  Template.info.info = function () {\n    return EJSON.stringify(ClientInfo.findOne(\"info\"), {indent: true});\n  };\n}\n"
  },
  {
    "path": "examples/other/controllers-demo/.meteor/release",
    "content": "0.6.0\n"
  },
  {
    "path": "examples/other/defer-in-inactive-tab/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/other/defer-in-inactive-tab/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nstandard-app-packages\n"
  },
  {
    "path": "examples/other/defer-in-inactive-tab/README.md",
    "content": "# Defer in Inactive Tab\n\nTests that `Meteor.defer` works in an inactive tab in iOS Safari.\n\n(`setTimeout` and `setInterval` events aren't delivered to inactive\ntabs in iOS Safari until they become active again).\n\nSadly we have to run the test manually because scripts aren't allowed\nto open windows themselves except in response to user events.\n\nThis test will not run on Chrome for iOS because the storage event is\nnot implemented in that browser.  Also doesn't attempt to run on\nversions of IE that don't support `window.addEventListener`.\n"
  },
  {
    "path": "examples/other/defer-in-inactive-tab/test.html",
    "content": "<head>\n  <title>defer in inactive tab</title>\n  <meta name=\"viewport\" content=\"width=device-width\">\n</head>\n\n<body>\n  {{> route}}\n</body>\n\n<template name=\"route\">\n  {{#if isParent}}\n    {{> parent}}\n  {{else}}\n    {{> child}}\n  {{/if}}\n</template>\n\n<template name=\"parent\">\n  <h1>Test Defer in Inactive Tab</h1>\n\n  <p>\n    Step one: open second tab:\n    <button id=\"openTab\">Open Tab</button>\n  </p>\n\n  <p>\n    Step two: run test:\n    <button id=\"runTest\">Run Test</button>\n  </p>\n\n  <p>\n    In a successful test the test status will immediately change to\n    \"test successful\".  (If you switch to the child tab yourself and\n    that makes the test claim to be successful, that's actually an\n    invalid test because you're letting the child tab become the\n    active tab).\n  </p>\n\n  <p style=\"padding: 1em; outline: 1px solid gray\">\n    Test status: <b>{{testStatus}}</b>\n  </p>\n\n  <p>\n    After the test has run successfully you can close the child tab.\n  </p>\n\n</template>\n\n<template name=\"child\">\n  <p>This is the child.</p>\n  <p>Switch back to the first tab and run the test.</p>\n</template>\n"
  },
  {
    "path": "examples/other/defer-in-inactive-tab/test.js",
    "content": "if (Meteor.isClient) {\n  \n  var isParent = (window.location.pathname === '/');\n  var isChild = ! isParent;\n\n  Template.route.isParent = function () {\n    return isParent;\n  };\n\n  Template.parent.testStatus = function () {\n    return Session.get('testStatus');\n  };\n\n  Template.parent.events({\n    'click #openTab': function () {\n      window.open('/child');\n    },\n    \n    'click #runTest': function () {\n      if (localStorage.getItem('ping') === '!' ||\n          localStorage.getItem('pong') === '!') {\n        Session.set('testStatus', 'Test already run.  Close the second tab (if open), refresh this page, and run again.');\n      }\n      else {\n        localStorage.setItem('ping', '!');\n      }\n    }\n  });\n\n  if (isParent) {\n    Session.set('testStatus', '');\n\n    Meteor.startup(function () {\n      localStorage.setItem('ping', null);\n      localStorage.setItem('pong', null);\n    });\n    window.addEventListener('storage', function (event) {\n      if (event.key === 'pong' && event.newValue === '!') {\n        Session.set('testStatus', 'test successful');\n      }\n    });\n  }\n\n  if (isChild) {\n    window.addEventListener('storage', function (event) {\n      if (event.key === 'ping' && event.newValue === '!') {\n        // If we used setTimeout here in iOS Safari it wouldn't\n        // work (unless we switched tabs) because setTimeout and\n        // setInterval events don't fire in inactive tabs.\n        Meteor.defer(function () {\n          localStorage.setItem('pong', '!');\n        });\n      }\n    });\n  }\n\n}\n"
  },
  {
    "path": "examples/other/domrange-grid/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/other/domrange-grid/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nstandard-app-packages\nautopublish\ninsecure\npreserve-inputs\nui\n"
  },
  {
    "path": "examples/other/domrange-grid/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "examples/other/domrange-grid/domrange-grid.css",
    "content": "/* CSS declarations go here */\n\n\n* { margin: 0; padding: 0 }\n\n#grid td {\n  width: 20px;\n  height: 20px;\n  vertical-align: middle;\n  text-align: center;\n}\n\n.color0 { background: #eee; }\n.color1 { background: #d8f; }\n.color2 { background: #8c3; }\n.color3 { background: #39d; }\n.color4 { background: #d96; }\n.color5 { background: #a95; }\n"
  },
  {
    "path": "examples/other/domrange-grid/domrange-grid.html",
    "content": "<head>\n  <title>domrange-grid</title>\n</head>\n\n<body>\n\n</body>\n"
  },
  {
    "path": "examples/other/domrange-grid/domrange-grid.js",
    "content": "if (Meteor.isClient) {\n  Meteor.startup(function () {\n    var N = 10;\n    var numColors = 6;\n    var colors = [];\n    for(var z = 0; z < numColors; z++)\n      colors[z] = z;\n\n    var guid = 1;\n\n    var table = $('<table id=\"grid\"></table>');\n    $(table).appendTo(\"body\");\n    var rows = [];\n    var tableContent = new UI.DomRange;\n    var makeCell = function (row) {\n      var cells = row.cells;\n      var tr = row.dom.elements()[0];\n      var cell = {color: Random.choice(colors),\n                  guid: String(guid++)};\n      cell.dom = new UI.DomRange(cell);\n      cells.push(cell);\n      cell.dom.add(cell.guid, $('<td class=\"color' +\n                                cell.color + '\">' +\n                                cell.color + '</td>'));\n      row.content.add(cell.guid, cell);\n    };\n    var makeRow = function () {\n      var row = {cells: [], guid: String(guid++),\n                 content: new UI.DomRange};\n      row.dom = new UI.DomRange(row);\n      rows.push(row);\n      tableContent.add(row.guid, row);\n      var tr = $(\"<tr></tr>\")[0];\n      row.dom.add(tr);\n      UI.DomRange.insert(row.content, tr);\n      var cells = row.cells;\n      for(var c = 0; c < N; c++)\n        makeCell(row);\n    };\n    for (var r = 0; r < N; r++)\n      makeRow();\n\n    UI.DomRange.insert(tableContent, table[0]);\n\n    $(document).on('keydown', function (evt) {\n      var deltaN = 0;\n      var deltaC = 0;\n      if (evt.which === 38) {\n        deltaN = 1; // up\n      } else if (evt.which === 40) {\n        deltaN = -1; // down\n      } else if (evt.which === 37) {\n        deltaC = -1; // left\n      } else if (evt.which === 39) {\n        deltaC = 1; // right\n      } else if (evt.which === 32) {\n        // spacebar\n        var row0 = rows.shift();\n        rows.push(row0);\n        tableContent.moveBefore(row0.guid, null);\n        for (var i = 0; i < rows.length; i++) {\n          var row = rows[i];\n          var cell0 = row.cells.shift();\n          row.cells.push(cell0);\n          row.content.moveBefore(cell0.guid, null);\n        }\n      }\n\n      if (deltaN === 1) {\n        N += 1;\n        for (var i = 0; i < N - 1; i++)\n          // lengthen old rows\n          makeCell(rows[i]);\n        makeRow();\n      } else if (deltaN === -1) {\n        if (N === 0)\n          return;\n        N -= 1;\n        tableContent.remove(rows[N].guid);\n        rows.length = N;\n        for (var i = 0; i < N; i++) {\n          var row = rows[i];\n          row.content.remove(row.cells[N].guid);\n          rows[i].cells.length = N;\n        }\n      }\n\n      if (deltaC) {\n        for (var r = 0; r < N; r++) {\n          var row = rows[r];\n          for (var c = 0; c < N; c++) {\n            var cell = row.cells[c];\n            var td = cell.dom.elements()[0];\n            var color =\n                  (cell.color =\n                   (cell.color + deltaC + numColors)\n                   % numColors);\n            td.innerHTML = color;\n            td.className = 'color' + color;\n          }\n        }\n      }\n    });\n  });\n}\n"
  },
  {
    "path": "examples/other/login-demo/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/other/login-demo/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\npreserve-inputs\naccounts-google\nstandard-app-packages\n"
  },
  {
    "path": "examples/other/login-demo/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "examples/other/login-demo/login-demo.css",
    "content": "\n* { padding: 0; margin: 0; }\n\n#main {\n  margin: 50px;\n  text-align: center;\n  font-size: 24px;\n}\n\n.msgDiv {\n  margin: 30px;\n}\n\na {\n  padding: 5px;\n  background: #ddd;\n}\n\n#readme {\n  margin: 20px;\n  border: 1px solid #ccc;\n  width: 500px;\n}\n\np {\n  margin: 16px;\n}\n\nul {\n  margin: 16px;\n  padding-left: 30px;\n}\n"
  },
  {
    "path": "examples/other/login-demo/login-demo.html",
    "content": "<head>\n  <title>login-demo</title>\n</head>\n\n<body>\n  <div id=\"main\">\n    {{> main}}\n  </div>\n  <div id=\"readme\">\n    <p>This is a minimal app where you need to log in to see the database.  There's also a loading screen while logging in and until the initial data is loaded.</p>\n    <p>There are three top-level screens corresponding to the three possible states of the app:</p>\n    <ul>\n      <li>Logging in / Loading &mdash; when <code>&#123;{loggingIn}}</code> is true</li>\n      <li>Logged in &mdash; when there is a <code>&#123;{currentUser}}</code></li>\n      <li>Logged out &mdash; otherwise</li>\n    </ul>\n    <p>If you reload the page while logged in, you'll start in the \"logging in\" state and see the \"Loading...\" message until the data loads.  Because logging in doesn't complete until all subscriptions have been rerun and finished loading, and the app only serves data when you're logged in, the \"logging in\" state encompasses loading the initial data for all subscriptions and is the only loading screen we need.</p>\n    <p>To configure this app for Google auth, the easiest way is to add the <code>accounts-ui</code> package, add <code>&#123;{> loginButtons}}</code> to the end of the body, and use the configuration wizard.</p>\n  </div>\n</body>\n\n<template name=\"main\">\n  {{#if loggingIn}}\n    <div class=\"loading\">Loading...</div>\n  {{else}}\n    {{#if currentUser}}\n      <div class=\"msgDiv\">\n        Signed in as: {{currentUser.services.google.email}}\n      </div>\n      <a href=\"#\" id=\"logout\">Sign out</a>\n    {{else}}\n      <a href=\"#\" id=\"login\">Sign In With Google</a>\n    {{/if}}\n  {{/if}}\n  <div class=\"msgDiv\">\n    Client can see {{numGizmos}} gizmos.\n  </div>\n</template>\n"
  },
  {
    "path": "examples/other/login-demo/login-demo.js",
    "content": "Gizmos = new Mongo.Collection(\"gizmos\");\n\nif (Meteor.isClient) {\n\n  var allGizmos = Meteor.subscribe(\"allGizmos\");\n\n  Template.main.numGizmos = function () {\n    return Gizmos.find().count();\n  };\n\n  Template.main.events({\n    'click #login': function (evt) {\n      Meteor.loginWithGoogle(function (err) {\n        if (err)\n          Meteor._debug(err);\n      });\n      evt.preventDefault();\n    },\n    'click #logout': function (evt) {\n      Meteor.logout(function (err) {\n        if (err)\n          Meteor._debug(err);\n      });\n      evt.preventDefault();\n    }\n  });\n}\n\nif (Meteor.isServer) {\n\n  Meteor.startup(function () {\n    // populate the Gizmos collection if it's empty on startup\n    if (Gizmos.find().count() === 0) {\n      for (var i = 0; i < 1000; i++)\n        Gizmos.insert({ name: \"Gizmo \" + i });\n    }\n  });\n\n  Meteor.publish(\"allGizmos\", function () {\n    // Only publish the Gizmos if user is logged in.\n    var user = this.userId && Meteor.users.findOne(this.userId);\n    if (user) {\n      // potentially put other conditions on user here...\n      return Gizmos.find({});\n    }\n    return [];\n  });\n\n  Meteor.publish(null, function () {\n    // If logged in, autopublish the current user's Google email\n    // to the client (which isn't published by default).\n    return this.userId &&\n      Meteor.users.find(this.userId,\n                        {fields: {'services.google.email': 1}});\n  });\n\n}\n"
  },
  {
    "path": "examples/other/parties/.meteor/.finished-upgraders",
    "content": "# This file contains information which helps Meteor properly upgrade your\n# app when you run 'meteor update'. You should check it into version control\n# with your project.\n\nnotices-for-0.9.0\nnotices-for-0.9.1\n0.9.4-platform-file\n"
  },
  {
    "path": "examples/other/parties/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/other/parties/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nstandard-app-packages\naccounts-ui\naccounts-password\nd3\nbootstrap\nemail\naccounts-facebook\naccounts-twitter\naudit-argument-checks\n"
  },
  {
    "path": "examples/other/parties/.meteor/platforms",
    "content": "server\nbrowser\n"
  },
  {
    "path": "examples/other/parties/.meteor/release",
    "content": "METEOR@0.9.4\n"
  },
  {
    "path": "examples/other/parties/.meteor/versions",
    "content": "accounts-base@1.1.2\naccounts-facebook@1.0.2\naccounts-oauth@1.1.2\naccounts-password@1.0.3\naccounts-twitter@1.0.2\naccounts-ui-unstyled@1.1.3\naccounts-ui@1.1.2\napplication-configuration@1.0.3\naudit-argument-checks@1.0.1\nautoupdate@1.1.2\nbase64@1.0.1\nbinary-heap@1.0.1\nblaze-tools@1.0.1\nblaze@2.0.2\nboilerplate-generator@1.0.1\nbootstrap@1.0.1\ncallback-hook@1.0.1\ncheck@1.0.2\nctl-helper@1.0.4\nctl@1.0.2\nd3@1.0.0\nddp@1.0.10\ndeps@1.0.5\nejson@1.0.4\nemail@1.0.4\nfacebook@1.1.1\nfastclick@1.0.1\nfollower-livedata@1.0.2\ngeojson-utils@1.0.1\nhtml-tools@1.0.2\nhtmljs@1.0.2\nhttp@1.0.7\nid-map@1.0.1\njquery@1.0.1\njson@1.0.1\nless@1.0.10\nlivedata@1.0.11\nlocalstorage@1.0.1\nlogging@1.0.4\nmeteor-platform@1.1.2\nmeteor@1.1.2\nminifiers@1.1.1\nminimongo@1.0.4\nmobile-status-bar@1.0.1\nmongo@1.0.7\nnpm-bcrypt@0.7.7\noauth1@1.1.1\noauth2@1.1.1\noauth@1.1.1\nobserve-sequence@1.0.3\nordered-dict@1.0.1\nrandom@1.0.1\nreactive-dict@1.0.4\nreactive-var@1.0.3\nreload@1.1.1\nretry@1.0.1\nroutepolicy@1.0.2\nservice-configuration@1.0.2\nsession@1.0.3\nsha@1.0.1\nspacebars-compiler@1.0.3\nspacebars@1.0.3\nsrp@1.0.1\nstandard-app-packages@1.0.3\ntemplating@1.0.8\ntracker@1.0.3\ntwitter@1.1.1\nui@1.0.4\nunderscore@1.0.1\nurl@1.0.1\nwebapp-hashing@1.0.1\nwebapp@1.1.3\n"
  },
  {
    "path": "examples/other/parties/client/client.js",
    "content": "// All Tomorrow's Parties -- client\n\nMeteor.subscribe(\"directory\");\nMeteor.subscribe(\"parties\");\n\n// If no party selected, or if the selected party was deleted, select one.\nMeteor.startup(function () {\n  Tracker.autorun(function () {\n    var selected = Session.get(\"selected\");\n    if (! selected || ! Parties.findOne(selected)) {\n      var party = Parties.findOne();\n      if (party)\n        Session.set(\"selected\", party._id);\n      else\n        Session.set(\"selected\", null);\n    }\n  });\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// Party details sidebar\n\nTemplate.details.helpers({\n  party: function () {\n    return Parties.findOne(Session.get(\"selected\"));\n  },\n  anyParties: function () {\n    return Parties.find().count() > 0;\n  },\n  creatorName: function () {\n    var owner = Meteor.users.findOne(this.owner);\n    if (owner._id === Meteor.userId())\n      return \"me\";\n    return displayName(owner);\n  },\n  canRemove: function () {\n    return this.owner === Meteor.userId() && attending(this) === 0;\n  },\n  maybeChosen: function (what) {\n    var myRsvp = _.find(this.rsvps, function (r) {\n      return r.user === Meteor.userId();\n    }) || {};\n\n    return what == myRsvp.rsvp ? \"chosen btn-inverse\" : \"\";\n  }\n});\n\nTemplate.details.events({\n  'click .rsvp_yes': function () {\n    Meteor.call(\"rsvp\", Session.get(\"selected\"), \"yes\");\n    return false;\n  },\n  'click .rsvp_maybe': function () {\n    Meteor.call(\"rsvp\", Session.get(\"selected\"), \"maybe\");\n    return false;\n  },\n  'click .rsvp_no': function () {\n    Meteor.call(\"rsvp\", Session.get(\"selected\"), \"no\");\n    return false;\n  },\n  'click .invite': function () {\n    openInviteDialog();\n    return false;\n  },\n  'click .remove': function () {\n    Parties.remove(this._id);\n    return false;\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// Party attendance widget\n\nTemplate.attendance.helpers({\n  rsvpName: function () {\n    var user = Meteor.users.findOne(this.user);\n    return displayName(user);\n  },\n\n  outstandingInvitations: function () {\n    var party = Parties.findOne(this._id);\n    return Meteor.users.find({$and: [\n      {_id: {$in: party.invited}}, // they're invited\n      {_id: {$nin: _.pluck(party.rsvps, 'user')}} // but haven't RSVP'd\n    ]});\n  },\n\n  invitationName: function () {\n    return displayName(this);\n  },\n\n  rsvpIs: function (what) {\n    return this.rsvp === what;\n  },\n\n  nobody: function () {\n    return ! this.public && (this.rsvps.length + this.invited.length === 0);\n  },\n\n  canInvite: function () {\n    return ! this.public && this.owner === Meteor.userId();\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// Map display\n\n// Use jquery to get the position clicked relative to the map element.\nvar coordsRelativeToElement = function (element, event) {\n  var offset = $(element).offset();\n  var x = event.pageX - offset.left;\n  var y = event.pageY - offset.top;\n  return { x: x, y: y };\n};\n\nTemplate.map.events({\n  'mousedown circle, mousedown text': function (event, template) {\n    Session.set(\"selected\", event.currentTarget.id);\n  },\n  'dblclick .map': function (event, template) {\n    if (! Meteor.userId()) // must be logged in to create events\n      return;\n    var coords = coordsRelativeToElement(event.currentTarget, event);\n    openCreateDialog(coords.x / 500, coords.y / 500);\n  }\n});\n\nTemplate.map.onRendered(function () {\n  var self = this;\n  self.node = self.find(\"svg\");\n\n  if (! self.handle) {\n    self.handle = Tracker.autorun(function () {\n      var selected = Session.get('selected');\n      var selectedParty = selected && Parties.findOne(selected);\n      var radius = function (party) {\n        return 10 + Math.sqrt(attending(party)) * 10;\n      };\n\n      // Draw a circle for each party\n      var updateCircles = function (group) {\n        group.attr(\"id\", function (party) { return party._id; })\n        .attr(\"cx\", function (party) { return party.x * 500; })\n        .attr(\"cy\", function (party) { return party.y * 500; })\n        .attr(\"r\", radius)\n        .attr(\"class\", function (party) {\n          return party.public ? \"public\" : \"private\";\n        })\n        .style('opacity', function (party) {\n          return selected === party._id ? 1 : 0.6;\n        });\n      };\n\n      var circles = d3.select(self.node).select(\".circles\").selectAll(\"circle\")\n        .data(Parties.find().fetch(), function (party) { return party._id; });\n\n      updateCircles(circles.enter().append(\"circle\"));\n      updateCircles(circles.transition().duration(250).ease(\"cubic-out\"));\n      circles.exit().transition().duration(250).attr(\"r\", 0).remove();\n\n      // Label each with the current attendance count\n      var updateLabels = function (group) {\n        group.attr(\"id\", function (party) { return party._id; })\n        .text(function (party) {return attending(party) || '';})\n        .attr(\"x\", function (party) { return party.x * 500; })\n        .attr(\"y\", function (party) { return party.y * 500 + radius(party)/2 })\n        .style('font-size', function (party) {\n          return radius(party) * 1.25 + \"px\";\n        });\n      };\n\n      var labels = d3.select(self.node).select(\".labels\").selectAll(\"text\")\n        .data(Parties.find().fetch(), function (party) { return party._id; });\n\n      updateLabels(labels.enter().append(\"text\"));\n      updateLabels(labels.transition().duration(250).ease(\"cubic-out\"));\n      labels.exit().remove();\n\n      // Draw a dashed circle around the currently selected party, if any\n      var callout = d3.select(self.node).select(\"circle.callout\")\n        .transition().duration(250).ease(\"cubic-out\");\n      if (selectedParty)\n        callout.attr(\"cx\", selectedParty.x * 500)\n        .attr(\"cy\", selectedParty.y * 500)\n        .attr(\"r\", radius(selectedParty) + 10)\n        .attr(\"class\", \"callout\")\n        .attr(\"display\", '');\n      else\n        callout.attr(\"display\", 'none');\n    });\n  }\n});\n\nTemplate.map.onDestroyed = function () {\n  this.handle && this.handle.stop();\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Create Party dialog\n\nvar openCreateDialog = function (x, y) {\n  Session.set(\"createCoords\", {x: x, y: y});\n  Session.set(\"createError\", null);\n  Session.set(\"showCreateDialog\", true);\n};\n\nTemplate.page.helpers({\n  showCreateDialog: function () {\n    return Session.get(\"showCreateDialog\");\n  }\n});\n\nTemplate.createDialog.events({\n  'click .save': function (event, template) {\n    var title = template.find(\".title\").value;\n    var description = template.find(\".description\").value;\n    var public = ! template.find(\".private\").checked;\n    var coords = Session.get(\"createCoords\");\n\n    if (title.length && description.length) {\n      var id = createParty({\n        title: title,\n        description: description,\n        x: coords.x,\n        y: coords.y,\n        public: public\n      });\n\n      Session.set(\"selected\", id);\n      if (! public && Meteor.users.find().count() > 1)\n        openInviteDialog();\n      Session.set(\"showCreateDialog\", false);\n    } else {\n      Session.set(\"createError\",\n                  \"It needs a title and a description, or why bother?\");\n    }\n  },\n\n  'click .cancel': function () {\n    Session.set(\"showCreateDialog\", false);\n  }\n});\n\nTemplate.createDialog.helpers({\n  error: function () {\n    return Session.get(\"createError\");\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// Invite dialog\n\nvar openInviteDialog = function () {\n  Session.set(\"showInviteDialog\", true);\n};\n\nTemplate.page.helpers({\n  showInviteDialog: function () {\n    return Session.get(\"showInviteDialog\");\n  }\n});\n\nTemplate.inviteDialog.events({\n  'click .invite': function (event, template) {\n    Meteor.call('invite', Session.get(\"selected\"), this._id);\n  },\n  'click .done': function (event, template) {\n    Session.set(\"showInviteDialog\", false);\n    return false;\n  }\n});\n\nTemplate.inviteDialog.helpers({\n  uninvited: function () {\n    var party = Parties.findOne(Session.get(\"selected\"));\n    if (! party)\n      return []; // party hasn't loaded yet\n    return Meteor.users.find({$nor: [{_id: {$in: party.invited}},\n                                     {_id: party.owner}]});\n  },\n\n  displayName: function () {\n    return displayName(this);\n  }\n});\n"
  },
  {
    "path": "examples/other/parties/client/parties.css",
    "content": ".header {\n    padding: 20px 0;\n}\n\n.details {\n    margin-top: -18px;\n}\n\n.mask {\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    top: 0px;\n    left: 0px;\n    background-color: #000000;\n    opacity: .4;\n    z-index: 1;\n}\n\n.invite-row .invite {\n    margin: 10px 10px 10px 0;\n}\n\n.rsvp-buttons {\n    text-align: center;\n    margin: 40px 0 40px 0;\n}\n\n.description {\n    margin: 20px 0 20px 0;\n}\n\n.attendance .who {\n    margin-bottom: 5px;\n}\n\n.attendance .invite {\n    text-align: center;\n}\n\ninput.chosen {\n    font-weight: bold;\n}\n\n.map {\n    position: relative;\n    background-image: url('/soma.png');\n    background-position: -20px -20px;\n    width: 500px;\n    height: 500px;\n}\n\n.map circle.public {\n    fill: #49AFCD;\n}\n\n.map circle.private {\n    fill: #DA4F49;\n}\n\n.map text {\n    text-anchor: middle;\n    fill: white;\n    font-weight: bold;\n}\n\n.map circle.callout {\n    stroke-width: 5px;\n    stroke-dasharray: 9, 5;\n    stroke-opacity: .8;\n    fill: none;\n    stroke: red;\n}\n\n.attribution {\n    position: absolute;\n    bottom: 0;\n    background-color: white;\n    padding: 3px;\n    padding-bottom: 0;\n}\n"
  },
  {
    "path": "examples/other/parties/client/parties.html",
    "content": "<head>\n  <title>All Tomorrow's Parties</title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n</head>\n\n<body>\n  {{> page}}\n</body>\n\n<template name=\"page\">\n  {{#if showCreateDialog}}\n    {{> createDialog}}\n  {{/if}}\n\n  {{#if showInviteDialog}}\n    {{> inviteDialog}}\n  {{/if}}\n\n  <div class=\"container\">\n    <div class=\"row\">\n      <div class=\"span1\"> </div>\n\n      <div class=\"span10\">\n        <div class=\"header row\">\n          <div class=\"span5\">\n            <h3 style=\"margin-bottom: 0px\">All Tomorrow's Parties</h3>\n          </div>\n          <div class=\"span5\">\n            <div style=\"float: right\">\n              {{> loginButtons align=\"right\"}}\n            </div>\n          </div>\n        </div>\n\n        <div class=\"row\">\n          <div class=\"span6\">\n            {{> map}}\n            {{#if currentUser}}\n            <div class=\"pagination-centered\">\n              <em><small>Double click the map to post a party!</small></em>\n            </div>\n            {{/if}}\n          </div>\n          <div class=\"span4\">\n            {{> details}}\n          </div>\n        </div>\n      </div>\n\n      <div class=\"span1\"> </div>\n    </div>\n  </div>\n</template>\n\n<template name=\"map\">\n  <div class=\"map\">\n    <svg width=\"500\" height=\"500\">\n      <circle class=\"callout\" cx=-100 cy=-100></circle>\n      <g class=\"circles\"></g>\n      <g class=\"labels\"></g>\n    </svg>\n    <div>\n      <small class=\"attribution muted\">&copy;\n        <a href=\"http://www.openstreetmap.org/?lat=37.78212&lon=-122.40146&zoom=15&layers=M\"\n           target=\"_blank\">OpenStreetMap</a> contributors</small>\n    </div>\n  </div>\n</template>\n\n<template name=\"details\">\n  <div class=\"details\">\n    {{#if party}}\n      {{#with party}}\n        <h1>{{title}}</h1>\n\n        <div class=\"description\">{{description}}</div>\n\n        {{> attendance}}\n\n        <div class=\"rsvp-buttons\">\n          {{#if currentUser}}\n            <input type=\"button\" value=\"I'm going!\"\n                   class=\"btn btn-small rsvp_yes {{maybeChosen \"yes\"}}\">\n            <input type=\"button\" value=\"Maybe\"\n                   class=\"btn btn-small rsvp_maybe {{maybeChosen \"maybe\"}}\">\n            <input type=\"button\" value=\"No\"\n                   class=\"btn btn-small rsvp_no {{maybeChosen \"no\"}}\">\n          {{else}}\n            <i>Sign in to RSVP for this party.</i>\n          {{/if}}\n          <p><small>Posted by {{creatorName}}</small></p>\n        </div>\n\n        {{#if canRemove}}\n          <div class=\"alert alert-info\"><small>\n              You posted this party and nobody is signed up to go, so if\n              you like, you could\n              <b><a href=\"#\" class=\"remove\">delete this listing</a></b>.\n          </small></div>\n        {{/if}}\n      {{/with}}\n    {{else}}\n      <h1 class=\"muted pagination-centered\">\n        {{#if anyParties}}\n          Click a party to select it\n        {{else}}\n          Sign in and double click the map to post a party\n        {{/if}}\n      </h1>\n    {{/if}}\n  </div>\n</template>\n\n<template name=\"attendance\">\n  <div class=\"attendance well well-small\">\n    <div class=\"muted who\"><b>Who</b></div>\n    {{#if public}}\n      <div>\n        <b>Everyone</b>\n        <span class=\"label label-inverse pull-right\">Invited</span>\n      </div>\n    {{/if}}\n\n    {{#each rsvps}}\n      <div>\n        {{rsvpName}}\n        {{#if rsvpIs \"yes\"}}\n          <span class=\"label label-success pull-right\">Going</span>\n        {{/if}}\n        {{#if rsvpIs \"maybe\"}}\n          <span class=\"label label-info pull-right\">Maybe</span>\n        {{/if}}\n        {{#if rsvpIs \"no\"}}\n          <span class=\"label label pull-right\">No</span>\n        {{/if}}\n      </div>\n    {{/each}}\n\n    {{#unless public}}\n      {{#each outstandingInvitations}}\n        <div>\n          {{invitationName}}\n          <span class=\"label label-inverse pull-right\">Invited</span>\n        </div>\n      {{/each}}\n    {{/unless}}\n\n    {{#if nobody}}\n      <div>Nobody.</div>\n    {{/if}}\n\n    {{#if canInvite}}\n      <div class=\"invite\">\n        <a href=\"#\" class=\"btn btn-mini invite\">Invite people</a>\n      </div>\n    {{/if}}\n  </div>\n</template>\n\n<template name=\"createDialog\">\n  <div class=\"mask\"> </div>\n  <div class=\"modal\">\n    <div class=\"modal-header\">\n      <button type=\"button\" class=\"close cancel\">&times;</button>\n      <h3>Add party</h3>\n    </div>\n\n    <div class=\"modal-body\">\n      {{#if error}}\n        <div class=\"alert alert-error\">{{error}}</div>\n      {{/if}}\n\n      <label>Title</label>\n      <input type=\"text\" class=\"title span5\">\n\n      <label>Description</label>\n      <textarea class=\"description span5\"></textarea>\n\n      <label class=\"checkbox\">\n        <input type=\"checkbox\" class=\"private\">\n        Private party &mdash; invitees only\n      </label>\n    </div>\n\n    <div class=\"modal-footer\">\n      <a href=\"#\" class=\"btn cancel\">Cancel</a>\n      <a href=\"#\" class=\"btn btn-primary save\">Add party</a>\n    </div>\n  </div>\n</template>\n\n<template name=\"inviteDialog\">\n  <div class=\"mask\"> </div>\n  <div class=\"modal\">\n    <div class=\"modal-header\">\n      <button type=\"button\" class=\"close done\">&times;</button>\n      <h3>Invite people</h3>\n    </div>\n\n    <div class=\"modal-body\">\n      {{#each uninvited}}\n        <div class=\"invite-row\">\n          <a href=\"#\" class=\"btn invite\">Invite</a>\n          {{displayName}}\n        </div>\n      {{else}}\n        Everyone on the site has already been invited.\n      {{/each}}\n    </div>\n\n    <div class=\"modal-footer\">\n      <a href=\"#\" class=\"btn btn-primary done\">Done</a>\n    </div>\n  </div>\n</template>\n\n"
  },
  {
    "path": "examples/other/parties/model.js",
    "content": "// All Tomorrow's Parties -- data model\n// Loaded on both the client and the server\n\n///////////////////////////////////////////////////////////////////////////////\n// Parties\n\n/*\n  Each party is represented by a document in the Parties collection:\n    owner: user id\n    x, y: Number (screen coordinates in the interval [0, 1])\n    title, description: String\n    public: Boolean\n    invited: Array of user id's that are invited (only if !public)\n    rsvps: Array of objects like {user: userId, rsvp: \"yes\"} (or \"no\"/\"maybe\")\n*/\nParties = new Mongo.Collection(\"parties\");\n\nParties.allow({\n  insert: function (userId, party) {\n    return false; // no cowboy inserts -- use createParty method\n  },\n  update: function (userId, party, fields, modifier) {\n    if (userId !== party.owner)\n      return false; // not the owner\n\n    var allowed = [\"title\", \"description\", \"x\", \"y\"];\n    if (_.difference(fields, allowed).length)\n      return false; // tried to write to forbidden field\n\n    // A good improvement would be to validate the type of the new\n    // value of the field (and if a string, the length.) In the\n    // future Meteor will have a schema system to makes that easier.\n    return true;\n  },\n  remove: function (userId, party) {\n    // You can only remove parties that you created and nobody is going to.\n    return party.owner === userId && attending(party) === 0;\n  }\n});\n\nattending = function (party) {\n  return (_.groupBy(party.rsvps, 'rsvp').yes || []).length;\n};\n\nvar NonEmptyString = Match.Where(function (x) {\n  check(x, String);\n  return x.length !== 0;\n});\n\nvar Coordinate = Match.Where(function (x) {\n  check(x, Number);\n  return x >= 0 && x <= 1;\n});\n\ncreateParty = function (options) {\n  var id = Random.id();\n  Meteor.call('createParty', _.extend({ _id: id }, options));\n  return id;\n};\n\nMeteor.methods({\n  // options should include: title, description, x, y, public\n  createParty: function (options) {\n    check(options, {\n      title: NonEmptyString,\n      description: NonEmptyString,\n      x: Coordinate,\n      y: Coordinate,\n      public: Match.Optional(Boolean),\n      _id: Match.Optional(NonEmptyString)\n    });\n\n    if (options.title.length > 100)\n      throw new Meteor.Error(413, \"Title too long\");\n    if (options.description.length > 1000)\n      throw new Meteor.Error(413, \"Description too long\");\n    if (! this.userId)\n      throw new Meteor.Error(403, \"You must be logged in\");\n\n    var id = options._id || Random.id();\n    Parties.insert({\n      _id: id,\n      owner: this.userId,\n      x: options.x,\n      y: options.y,\n      title: options.title,\n      description: options.description,\n      public: !! options.public,\n      invited: [],\n      rsvps: []\n    });\n    return id;\n  },\n\n  invite: function (partyId, userId) {\n    check(partyId, String);\n    check(userId, String);\n    var party = Parties.findOne(partyId);\n    if (! party || party.owner !== this.userId)\n      throw new Meteor.Error(404, \"No such party\");\n    if (party.public)\n      throw new Meteor.Error(400,\n                             \"That party is public. No need to invite people.\");\n    if (userId !== party.owner && ! _.contains(party.invited, userId)) {\n      Parties.update(partyId, { $addToSet: { invited: userId } });\n\n      var from = contactEmail(Meteor.users.findOne(this.userId));\n      var to = contactEmail(Meteor.users.findOne(userId));\n      if (Meteor.isServer && to) {\n        // This code only runs on the server. If you didn't want clients\n        // to be able to see it, you could move it to a separate file.\n        Email.send({\n          from: \"noreply@example.com\",\n          to: to,\n          replyTo: from || undefined,\n          subject: \"PARTY: \" + party.title,\n          text:\n\"Hey, I just invited you to '\" + party.title + \"' on All Tomorrow's Parties.\" +\n\"\\n\\nCome check it out: \" + Meteor.absoluteUrl() + \"\\n\"\n        });\n      }\n    }\n  },\n\n  rsvp: function (partyId, rsvp) {\n    check(partyId, String);\n    check(rsvp, String);\n    if (! this.userId)\n      throw new Meteor.Error(403, \"You must be logged in to RSVP\");\n    if (! _.contains(['yes', 'no', 'maybe'], rsvp))\n      throw new Meteor.Error(400, \"Invalid RSVP\");\n    var party = Parties.findOne(partyId);\n    if (! party)\n      throw new Meteor.Error(404, \"No such party\");\n    if (! party.public && party.owner !== this.userId &&\n        !_.contains(party.invited, this.userId))\n      // private, but let's not tell this to the user\n      throw new Meteor.Error(403, \"No such party\");\n\n    var rsvpIndex = _.indexOf(_.pluck(party.rsvps, 'user'), this.userId);\n    if (rsvpIndex !== -1) {\n      // update existing rsvp entry\n\n      if (Meteor.isServer) {\n        // update the appropriate rsvp entry with $\n        Parties.update(\n          {_id: partyId, \"rsvps.user\": this.userId},\n          {$set: {\"rsvps.$.rsvp\": rsvp}});\n      } else {\n        // minimongo doesn't yet support $ in modifier. as a temporary\n        // workaround, make a modifier that uses an index. this is\n        // safe on the client since there's only one thread.\n        var modifier = {$set: {}};\n        modifier.$set[\"rsvps.\" + rsvpIndex + \".rsvp\"] = rsvp;\n        Parties.update(partyId, modifier);\n      }\n\n      // Possible improvement: send email to the other people that are\n      // coming to the party.\n    } else {\n      // add new rsvp entry\n      Parties.update(partyId,\n                     {$push: {rsvps: {user: this.userId, rsvp: rsvp}}});\n    }\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// Users\n\ndisplayName = function (user) {\n  if (user.profile && user.profile.name)\n    return user.profile.name;\n  return user.emails[0].address;\n};\n\nvar contactEmail = function (user) {\n  if (user.emails && user.emails.length)\n    return user.emails[0].address;\n  if (user.services && user.services.facebook && user.services.facebook.email)\n    return user.services.facebook.email;\n  return null;\n};\n"
  },
  {
    "path": "examples/other/parties/server/server.js",
    "content": "// All Tomorrow's Parties -- server\n\nMeteor.publish(\"directory\", function () {\n  return Meteor.users.find({}, {fields: {emails: 1, profile: 1}});\n});\n\nMeteor.publish(\"parties\", function () {\n  return Parties.find(\n    {$or: [{\"public\": true}, {invited: this.userId}, {owner: this.userId}]});\n});\n"
  },
  {
    "path": "examples/other/quiescence/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/other/quiescence/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\ninsecure\npreserve-inputs\nrandom\nstandard-app-packages\n"
  },
  {
    "path": "examples/other/quiescence/.meteor/release",
    "content": "0.6.0\n"
  },
  {
    "path": "examples/other/quiescence/quiescence.html",
    "content": "<head>\n  <title>quiescence</title>\n</head>\n\n<body>\n  {{> clock}}\n  {{> updated}}\n  {{> stream}}\n</body>\n\n<template name=\"clock\">\n  <h1>Current time</h1>\n  <p>{{time}}</p>\n</template>\n\n<template name=\"updated\">\n  <h1>Update object</h1>\n  <p>The magic number is {{magic}}. Click the button to set it to a random\n     integer in the client stub. The server will add 0.5 the that integer.</p>\n  <button id='update-button'>Update</button>\n</template>\n\n<template name=\"stream\">\n  <h1>Stream in results</h1>\n  <p>Click the button. Note that the results stream in instead of appearing all\n     at once. Note that the clock continues to tick while the streaming method\n     is running. Note that the \"update\" button above works while the streaming\n     method is running (ie, the server's \"add 0.5\" is processed).</p>\n  <button id='stream-button'>Stream</button>\n  <ul>\n    {{#each results}}\n      <li>{{text}}</li>\n    {{/each}}\n  </ul>\n</template>\n"
  },
  {
    "path": "examples/other/quiescence/quiescence.js",
    "content": "Time = new Mongo.Collection(\"time\");\nResults = new Mongo.Collection(\"results\");\nMagic = new Mongo.Collection(\"magic\");\n\nif (Meteor.isServer) {\n  Meteor.publish(\"time\", function () {\n    var self = this;\n    var publishTime = function () {\n      var when = + new Date;\n      self.changed(\"time\", \"now\", {timestamp: when});\n    };\n    self.added(\"time\", \"now\", {});\n    publishTime();\n    self.ready();\n    var interval = Meteor.setInterval(publishTime, 1000);\n    self.onStop(function () {\n      Meteor.clearInterval(interval);\n    });\n  });\n  Meteor.publish(\"results\", function () {\n    return Results.find();\n  });\n  Meteor.publish(\"magic\", function () {\n    return Magic.find();\n  });\n\n  Meteor.startup(function () {\n    if (Magic.find().count() === 0) {\n      Magic.insert({number: 42});\n    }\n  });\n\n  var Fiber = Npm.require('fibers');\n\n  var sleep = function (ms) {\n    var fiber = Fiber.current;\n    setTimeout(function() {\n      fiber.run();\n    }, ms);\n    Fiber.yield();\n  };\n\n  Meteor.methods({\n    getResults: function () {\n      this.unblock();\n      Results.remove({});\n      for (var i = 0; i < 5; ++i) {\n        sleep(1000);\n        Results.insert({i: i, text: 'result ' + i});\n      }\n    }});\n} else {\n  Meteor.subscribe(\"time\");\n  Meteor.subscribe(\"results\");\n  Meteor.subscribe(\"magic\");\n\n  Template.clock.time = function () {\n    var now = Time.findOne('now');\n    if (!now)\n      return \"(loading)\";\n    return new Date(now.timestamp).toTimeString();\n  };\n\n  Template.updated.magic = function () {\n    var singleton = Magic.findOne();\n    if (!singleton)\n      return \"(loading)\";\n    return singleton.number;\n  };\n  Template.updated.events({\n    'click #update-button': function () {\n      var num = Math.round(Random.fraction()*100);\n      Meteor.call('setMagic', num);\n    }\n  });\n\n  Template.stream.events({\n    'click #stream-button': function () {\n      Meteor.call('getResults');\n    }\n  });\n\n  Template.stream.results = function () {\n    return Results.find({}, {sort: ['i']});\n  };\n}\n\nMeteor.methods({\n  setMagic: function (num) {\n    if (this.isSimulation) {\n      Magic.update({}, {$set: {number: num}});\n    } else {\n      Magic.update({}, {$set: {number: num + 0.5}});\n    }\n  }\n});\n"
  },
  {
    "path": "examples/other/template-demo/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/other/template-demo/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nautopublish\nstandard-app-packages\n"
  },
  {
    "path": "examples/other/template-demo/.meteor/release",
    "content": "0.6.0\n"
  },
  {
    "path": "examples/other/template-demo/client/d3.v2.js",
    "content": "(function() {\n  if (!Date.now) Date.now = function() {\n    return +(new Date);\n  };\n  try {\n    document.createElement(\"div\").style.setProperty(\"opacity\", 0, \"\");\n  } catch (error) {\n    var d3_style_prototype = CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;\n    d3_style_prototype.setProperty = function(name, value, priority) {\n      d3_style_setProperty.call(this, name, value + \"\", priority);\n    };\n  }\n  d3 = {\n    version: \"2.10.0\"\n  };\n  function d3_class(ctor, properties) {\n    try {\n      for (var key in properties) {\n        Object.defineProperty(ctor.prototype, key, {\n          value: properties[key],\n          enumerable: false\n        });\n      }\n    } catch (e) {\n      ctor.prototype = properties;\n    }\n  }\n  var d3_array = d3_arraySlice;\n  function d3_arrayCopy(pseudoarray) {\n    var i = -1, n = pseudoarray.length, array = [];\n    while (++i < n) array.push(pseudoarray[i]);\n    return array;\n  }\n  function d3_arraySlice(pseudoarray) {\n    return Array.prototype.slice.call(pseudoarray);\n  }\n  try {\n    d3_array(document.documentElement.childNodes)[0].nodeType;\n  } catch (e) {\n    d3_array = d3_arrayCopy;\n  }\n  var d3_arraySubclass = [].__proto__ ? function(array, prototype) {\n    array.__proto__ = prototype;\n  } : function(array, prototype) {\n    for (var property in prototype) array[property] = prototype[property];\n  };\n  d3.map = function(object) {\n    var map = new d3_Map;\n    for (var key in object) map.set(key, object[key]);\n    return map;\n  };\n  function d3_Map() {}\n  d3_class(d3_Map, {\n    has: function(key) {\n      return d3_map_prefix + key in this;\n    },\n    get: function(key) {\n      return this[d3_map_prefix + key];\n    },\n    set: function(key, value) {\n      return this[d3_map_prefix + key] = value;\n    },\n    remove: function(key) {\n      key = d3_map_prefix + key;\n      return key in this && delete this[key];\n    },\n    keys: function() {\n      var keys = [];\n      this.forEach(function(key) {\n        keys.push(key);\n      });\n      return keys;\n    },\n    values: function() {\n      var values = [];\n      this.forEach(function(key, value) {\n        values.push(value);\n      });\n      return values;\n    },\n    entries: function() {\n      var entries = [];\n      this.forEach(function(key, value) {\n        entries.push({\n          key: key,\n          value: value\n        });\n      });\n      return entries;\n    },\n    forEach: function(f) {\n      for (var key in this) {\n        if (key.charCodeAt(0) === d3_map_prefixCode) {\n          f.call(this, key.substring(1), this[key]);\n        }\n      }\n    }\n  });\n  var d3_map_prefix = \"\\0\", d3_map_prefixCode = d3_map_prefix.charCodeAt(0);\n  function d3_identity(d) {\n    return d;\n  }\n  function d3_this() {\n    return this;\n  }\n  function d3_true() {\n    return true;\n  }\n  function d3_functor(v) {\n    return typeof v === \"function\" ? v : function() {\n      return v;\n    };\n  }\n  d3.functor = d3_functor;\n  d3.rebind = function(target, source) {\n    var i = 1, n = arguments.length, method;\n    while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);\n    return target;\n  };\n  function d3_rebind(target, source, method) {\n    return function() {\n      var value = method.apply(source, arguments);\n      return arguments.length ? target : value;\n    };\n  }\n  d3.ascending = function(a, b) {\n    return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;\n  };\n  d3.descending = function(a, b) {\n    return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;\n  };\n  d3.mean = function(array, f) {\n    var n = array.length, a, m = 0, i = -1, j = 0;\n    if (arguments.length === 1) {\n      while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;\n    } else {\n      while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;\n    }\n    return j ? m : undefined;\n  };\n  d3.median = function(array, f) {\n    if (arguments.length > 1) array = array.map(f);\n    array = array.filter(d3_number);\n    return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined;\n  };\n  d3.min = function(array, f) {\n    var i = -1, n = array.length, a, b;\n    if (arguments.length === 1) {\n      while (++i < n && ((a = array[i]) == null || a != a)) a = undefined;\n      while (++i < n) if ((b = array[i]) != null && a > b) a = b;\n    } else {\n      while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined;\n      while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;\n    }\n    return a;\n  };\n  d3.max = function(array, f) {\n    var i = -1, n = array.length, a, b;\n    if (arguments.length === 1) {\n      while (++i < n && ((a = array[i]) == null || a != a)) a = undefined;\n      while (++i < n) if ((b = array[i]) != null && b > a) a = b;\n    } else {\n      while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined;\n      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;\n    }\n    return a;\n  };\n  d3.extent = function(array, f) {\n    var i = -1, n = array.length, a, b, c;\n    if (arguments.length === 1) {\n      while (++i < n && ((a = c = array[i]) == null || a != a)) a = c = undefined;\n      while (++i < n) if ((b = array[i]) != null) {\n        if (a > b) a = b;\n        if (c < b) c = b;\n      }\n    } else {\n      while (++i < n && ((a = c = f.call(array, array[i], i)) == null || a != a)) a = undefined;\n      while (++i < n) if ((b = f.call(array, array[i], i)) != null) {\n        if (a > b) a = b;\n        if (c < b) c = b;\n      }\n    }\n    return [ a, c ];\n  };\n  d3.random = {\n    normal: function(µ, σ) {\n      var n = arguments.length;\n      if (n < 2) σ = 1;\n      if (n < 1) µ = 0;\n      return function() {\n        var x, y, r;\n        do {\n          x = Math.random() * 2 - 1;\n          y = Math.random() * 2 - 1;\n          r = x * x + y * y;\n        } while (!r || r > 1);\n        return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);\n      };\n    },\n    logNormal: function(µ, σ) {\n      var n = arguments.length;\n      if (n < 2) σ = 1;\n      if (n < 1) µ = 0;\n      var random = d3.random.normal();\n      return function() {\n        return Math.exp(µ + σ * random());\n      };\n    },\n    irwinHall: function(m) {\n      return function() {\n        for (var s = 0, j = 0; j < m; j++) s += Math.random();\n        return s / m;\n      };\n    }\n  };\n  function d3_number(x) {\n    return x != null && !isNaN(x);\n  }\n  d3.sum = function(array, f) {\n    var s = 0, n = array.length, a, i = -1;\n    if (arguments.length === 1) {\n      while (++i < n) if (!isNaN(a = +array[i])) s += a;\n    } else {\n      while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a;\n    }\n    return s;\n  };\n  d3.quantile = function(values, p) {\n    var H = (values.length - 1) * p + 1, h = Math.floor(H), v = values[h - 1], e = H - h;\n    return e ? v + e * (values[h] - v) : v;\n  };\n  d3.transpose = function(matrix) {\n    return d3.zip.apply(d3, matrix);\n  };\n  d3.zip = function() {\n    if (!(n = arguments.length)) return [];\n    for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) {\n      for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) {\n        zip[j] = arguments[j][i];\n      }\n    }\n    return zips;\n  };\n  function d3_zipLength(d) {\n    return d.length;\n  }\n  d3.bisector = function(f) {\n    return {\n      left: function(a, x, lo, hi) {\n        if (arguments.length < 3) lo = 0;\n        if (arguments.length < 4) hi = a.length;\n        while (lo < hi) {\n          var mid = lo + hi >>> 1;\n          if (f.call(a, a[mid], mid) < x) lo = mid + 1; else hi = mid;\n        }\n        return lo;\n      },\n      right: function(a, x, lo, hi) {\n        if (arguments.length < 3) lo = 0;\n        if (arguments.length < 4) hi = a.length;\n        while (lo < hi) {\n          var mid = lo + hi >>> 1;\n          if (x < f.call(a, a[mid], mid)) hi = mid; else lo = mid + 1;\n        }\n        return lo;\n      }\n    };\n  };\n  var d3_bisector = d3.bisector(function(d) {\n    return d;\n  });\n  d3.bisectLeft = d3_bisector.left;\n  d3.bisect = d3.bisectRight = d3_bisector.right;\n  d3.first = function(array, f) {\n    var i = 0, n = array.length, a = array[0], b;\n    if (arguments.length === 1) f = d3.ascending;\n    while (++i < n) {\n      if (f.call(array, a, b = array[i]) > 0) {\n        a = b;\n      }\n    }\n    return a;\n  };\n  d3.last = function(array, f) {\n    var i = 0, n = array.length, a = array[0], b;\n    if (arguments.length === 1) f = d3.ascending;\n    while (++i < n) {\n      if (f.call(array, a, b = array[i]) <= 0) {\n        a = b;\n      }\n    }\n    return a;\n  };\n  d3.nest = function() {\n    var nest = {}, keys = [], sortKeys = [], sortValues, rollup;\n    function map(array, depth) {\n      if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;\n      var i = -1, n = array.length, key = keys[depth++], keyValue, object, valuesByKey = new d3_Map, values, o = {};\n      while (++i < n) {\n        if (values = valuesByKey.get(keyValue = key(object = array[i]))) {\n          values.push(object);\n        } else {\n          valuesByKey.set(keyValue, [ object ]);\n        }\n      }\n      valuesByKey.forEach(function(keyValue) {\n        o[keyValue] = map(valuesByKey.get(keyValue), depth);\n      });\n      return o;\n    }\n    function entries(map, depth) {\n      if (depth >= keys.length) return map;\n      var a = [], sortKey = sortKeys[depth++], key;\n      for (key in map) {\n        a.push({\n          key: key,\n          values: entries(map[key], depth)\n        });\n      }\n      if (sortKey) a.sort(function(a, b) {\n        return sortKey(a.key, b.key);\n      });\n      return a;\n    }\n    nest.map = function(array) {\n      return map(array, 0);\n    };\n    nest.entries = function(array) {\n      return entries(map(array, 0), 0);\n    };\n    nest.key = function(d) {\n      keys.push(d);\n      return nest;\n    };\n    nest.sortKeys = function(order) {\n      sortKeys[keys.length - 1] = order;\n      return nest;\n    };\n    nest.sortValues = function(order) {\n      sortValues = order;\n      return nest;\n    };\n    nest.rollup = function(f) {\n      rollup = f;\n      return nest;\n    };\n    return nest;\n  };\n  d3.keys = function(map) {\n    var keys = [];\n    for (var key in map) keys.push(key);\n    return keys;\n  };\n  d3.values = function(map) {\n    var values = [];\n    for (var key in map) values.push(map[key]);\n    return values;\n  };\n  d3.entries = function(map) {\n    var entries = [];\n    for (var key in map) entries.push({\n      key: key,\n      value: map[key]\n    });\n    return entries;\n  };\n  d3.permute = function(array, indexes) {\n    var permutes = [], i = -1, n = indexes.length;\n    while (++i < n) permutes[i] = array[indexes[i]];\n    return permutes;\n  };\n  d3.merge = function(arrays) {\n    return Array.prototype.concat.apply([], arrays);\n  };\n  d3.split = function(array, f) {\n    var arrays = [], values = [], value, i = -1, n = array.length;\n    if (arguments.length < 2) f = d3_splitter;\n    while (++i < n) {\n      if (f.call(values, value = array[i], i)) {\n        values = [];\n      } else {\n        if (!values.length) arrays.push(values);\n        values.push(value);\n      }\n    }\n    return arrays;\n  };\n  function d3_splitter(d) {\n    return d == null;\n  }\n  function d3_collapse(s) {\n    return s.trim().replace(/\\s+/g, \" \");\n  }\n  d3.range = function(start, stop, step) {\n    if (arguments.length < 3) {\n      step = 1;\n      if (arguments.length < 2) {\n        stop = start;\n        start = 0;\n      }\n    }\n    if ((stop - start) / step === Infinity) throw new Error(\"infinite range\");\n    var range = [], k = d3_range_integerScale(Math.abs(step)), i = -1, j;\n    start *= k, stop *= k, step *= k;\n    if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k);\n    return range;\n  };\n  function d3_range_integerScale(x) {\n    var k = 1;\n    while (x * k % 1) k *= 10;\n    return k;\n  }\n  d3.requote = function(s) {\n    return s.replace(d3_requote_re, \"\\\\$&\");\n  };\n  var d3_requote_re = /[\\\\\\^\\$\\*\\+\\?\\|\\[\\]\\(\\)\\.\\{\\}]/g;\n  d3.round = function(x, n) {\n    return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);\n  };\n  d3.xhr = function(url, mime, callback) {\n    var req = new XMLHttpRequest;\n    if (arguments.length < 3) callback = mime, mime = null; else if (mime && req.overrideMimeType) req.overrideMimeType(mime);\n    req.open(\"GET\", url, true);\n    if (mime) req.setRequestHeader(\"Accept\", mime);\n    req.onreadystatechange = function() {\n      if (req.readyState === 4) {\n        var s = req.status;\n        callback(!s && req.response || s >= 200 && s < 300 || s === 304 ? req : null);\n      }\n    };\n    req.send(null);\n  };\n  d3.text = function(url, mime, callback) {\n    function ready(req) {\n      callback(req && req.responseText);\n    }\n    if (arguments.length < 3) {\n      callback = mime;\n      mime = null;\n    }\n    d3.xhr(url, mime, ready);\n  };\n  d3.json = function(url, callback) {\n    d3.text(url, \"application/json\", function(text) {\n      callback(text ? JSON.parse(text) : null);\n    });\n  };\n  d3.html = function(url, callback) {\n    d3.text(url, \"text/html\", function(text) {\n      if (text != null) {\n        var range = document.createRange();\n        range.selectNode(document.body);\n        text = range.createContextualFragment(text);\n      }\n      callback(text);\n    });\n  };\n  d3.xml = function(url, mime, callback) {\n    function ready(req) {\n      callback(req && req.responseXML);\n    }\n    if (arguments.length < 3) {\n      callback = mime;\n      mime = null;\n    }\n    d3.xhr(url, mime, ready);\n  };\n  var d3_nsPrefix = {\n    svg: \"http://www.w3.org/2000/svg\",\n    xhtml: \"http://www.w3.org/1999/xhtml\",\n    xlink: \"http://www.w3.org/1999/xlink\",\n    xml: \"http://www.w3.org/XML/1998/namespace\",\n    xmlns: \"http://www.w3.org/2000/xmlns/\"\n  };\n  d3.ns = {\n    prefix: d3_nsPrefix,\n    qualify: function(name) {\n      var i = name.indexOf(\":\"), prefix = name;\n      if (i >= 0) {\n        prefix = name.substring(0, i);\n        name = name.substring(i + 1);\n      }\n      return d3_nsPrefix.hasOwnProperty(prefix) ? {\n        space: d3_nsPrefix[prefix],\n        local: name\n      } : name;\n    }\n  };\n  d3.dispatch = function() {\n    var dispatch = new d3_dispatch, i = -1, n = arguments.length;\n    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);\n    return dispatch;\n  };\n  function d3_dispatch() {}\n  d3_dispatch.prototype.on = function(type, listener) {\n    var i = type.indexOf(\".\"), name = \"\";\n    if (i > 0) {\n      name = type.substring(i + 1);\n      type = type.substring(0, i);\n    }\n    return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);\n  };\n  function d3_dispatch_event(dispatch) {\n    var listeners = [], listenerByName = new d3_Map;\n    function event() {\n      var z = listeners, i = -1, n = z.length, l;\n      while (++i < n) if (l = z[i].on) l.apply(this, arguments);\n      return dispatch;\n    }\n    event.on = function(name, listener) {\n      var l = listenerByName.get(name), i;\n      if (arguments.length < 2) return l && l.on;\n      if (l) {\n        l.on = null;\n        listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));\n        listenerByName.remove(name);\n      }\n      if (listener) listeners.push(listenerByName.set(name, {\n        on: listener\n      }));\n      return dispatch;\n    };\n    return event;\n  }\n  d3.format = function(specifier) {\n    var match = d3_format_re.exec(specifier), fill = match[1] || \" \", sign = match[3] || \"\", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, suffix = \"\", integer = false;\n    if (precision) precision = +precision.substring(1);\n    if (zfill) {\n      fill = \"0\";\n      if (comma) width -= Math.floor((width - 1) / 4);\n    }\n    switch (type) {\n     case \"n\":\n      comma = true;\n      type = \"g\";\n      break;\n     case \"%\":\n      scale = 100;\n      suffix = \"%\";\n      type = \"f\";\n      break;\n     case \"p\":\n      scale = 100;\n      suffix = \"%\";\n      type = \"r\";\n      break;\n     case \"d\":\n      integer = true;\n      precision = 0;\n      break;\n     case \"s\":\n      scale = -1;\n      type = \"r\";\n      break;\n    }\n    if (type == \"r\" && !precision) type = \"g\";\n    type = d3_format_types.get(type) || d3_format_typeDefault;\n    return function(value) {\n      if (integer && value % 1) return \"\";\n      var negative = value < 0 && (value = -value) ? \"-\" : sign;\n      if (scale < 0) {\n        var prefix = d3.formatPrefix(value, precision);\n        value = prefix.scale(value);\n        suffix = prefix.symbol;\n      } else {\n        value *= scale;\n      }\n      value = type(value, precision);\n      if (zfill) {\n        var length = value.length + negative.length;\n        if (length < width) value = (new Array(width - length + 1)).join(fill) + value;\n        if (comma) value = d3_format_group(value);\n        value = negative + value;\n      } else {\n        if (comma) value = d3_format_group(value);\n        value = negative + value;\n        var length = value.length;\n        if (length < width) value = (new Array(width - length + 1)).join(fill) + value;\n      }\n      return value + suffix;\n    };\n  };\n  var d3_format_re = /(?:([^{])?([<>=^]))?([+\\- ])?(#)?(0)?([0-9]+)?(,)?(\\.[0-9]+)?([a-zA-Z%])?/;\n  var d3_format_types = d3.map({\n    g: function(x, p) {\n      return x.toPrecision(p);\n    },\n    e: function(x, p) {\n      return x.toExponential(p);\n    },\n    f: function(x, p) {\n      return x.toFixed(p);\n    },\n    r: function(x, p) {\n      return d3.round(x, p = d3_format_precision(x, p)).toFixed(Math.max(0, Math.min(20, p)));\n    }\n  });\n  function d3_format_precision(x, p) {\n    return p - (x ? 1 + Math.floor(Math.log(x + Math.pow(10, 1 + Math.floor(Math.log(x) / Math.LN10) - p)) / Math.LN10) : 1);\n  }\n  function d3_format_typeDefault(x) {\n    return x + \"\";\n  }\n  function d3_format_group(value) {\n    var i = value.lastIndexOf(\".\"), f = i >= 0 ? value.substring(i) : (i = value.length, \"\"), t = [];\n    while (i > 0) t.push(value.substring(i -= 3, i + 3));\n    return t.reverse().join(\",\") + f;\n  }\n  var d3_formatPrefixes = [ \"y\", \"z\", \"a\", \"f\", \"p\", \"n\", \"μ\", \"m\", \"\", \"k\", \"M\", \"G\", \"T\", \"P\", \"E\", \"Z\", \"Y\" ].map(d3_formatPrefix);\n  d3.formatPrefix = function(value, precision) {\n    var i = 0;\n    if (value) {\n      if (value < 0) value *= -1;\n      if (precision) value = d3.round(value, d3_format_precision(value, precision));\n      i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);\n      i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3));\n    }\n    return d3_formatPrefixes[8 + i / 3];\n  };\n  function d3_formatPrefix(d, i) {\n    var k = Math.pow(10, Math.abs(8 - i) * 3);\n    return {\n      scale: i > 8 ? function(d) {\n        return d / k;\n      } : function(d) {\n        return d * k;\n      },\n      symbol: d\n    };\n  }\n  var d3_ease_quad = d3_ease_poly(2), d3_ease_cubic = d3_ease_poly(3), d3_ease_default = function() {\n    return d3_ease_identity;\n  };\n  var d3_ease = d3.map({\n    linear: d3_ease_default,\n    poly: d3_ease_poly,\n    quad: function() {\n      return d3_ease_quad;\n    },\n    cubic: function() {\n      return d3_ease_cubic;\n    },\n    sin: function() {\n      return d3_ease_sin;\n    },\n    exp: function() {\n      return d3_ease_exp;\n    },\n    circle: function() {\n      return d3_ease_circle;\n    },\n    elastic: d3_ease_elastic,\n    back: d3_ease_back,\n    bounce: function() {\n      return d3_ease_bounce;\n    }\n  });\n  var d3_ease_mode = d3.map({\n    \"in\": d3_ease_identity,\n    out: d3_ease_reverse,\n    \"in-out\": d3_ease_reflect,\n    \"out-in\": function(f) {\n      return d3_ease_reflect(d3_ease_reverse(f));\n    }\n  });\n  d3.ease = function(name) {\n    var i = name.indexOf(\"-\"), t = i >= 0 ? name.substring(0, i) : name, m = i >= 0 ? name.substring(i + 1) : \"in\";\n    t = d3_ease.get(t) || d3_ease_default;\n    m = d3_ease_mode.get(m) || d3_ease_identity;\n    return d3_ease_clamp(m(t.apply(null, Array.prototype.slice.call(arguments, 1))));\n  };\n  function d3_ease_clamp(f) {\n    return function(t) {\n      return t <= 0 ? 0 : t >= 1 ? 1 : f(t);\n    };\n  }\n  function d3_ease_reverse(f) {\n    return function(t) {\n      return 1 - f(1 - t);\n    };\n  }\n  function d3_ease_reflect(f) {\n    return function(t) {\n      return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));\n    };\n  }\n  function d3_ease_identity(t) {\n    return t;\n  }\n  function d3_ease_poly(e) {\n    return function(t) {\n      return Math.pow(t, e);\n    };\n  }\n  function d3_ease_sin(t) {\n    return 1 - Math.cos(t * Math.PI / 2);\n  }\n  function d3_ease_exp(t) {\n    return Math.pow(2, 10 * (t - 1));\n  }\n  function d3_ease_circle(t) {\n    return 1 - Math.sqrt(1 - t * t);\n  }\n  function d3_ease_elastic(a, p) {\n    var s;\n    if (arguments.length < 2) p = .45;\n    if (arguments.length < 1) {\n      a = 1;\n      s = p / 4;\n    } else s = p / (2 * Math.PI) * Math.asin(1 / a);\n    return function(t) {\n      return 1 + a * Math.pow(2, 10 * -t) * Math.sin((t - s) * 2 * Math.PI / p);\n    };\n  }\n  function d3_ease_back(s) {\n    if (!s) s = 1.70158;\n    return function(t) {\n      return t * t * ((s + 1) * t - s);\n    };\n  }\n  function d3_ease_bounce(t) {\n    return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;\n  }\n  d3.event = null;\n  function d3_eventCancel() {\n    d3.event.stopPropagation();\n    d3.event.preventDefault();\n  }\n  function d3_eventSource() {\n    var e = d3.event, s;\n    while (s = e.sourceEvent) e = s;\n    return e;\n  }\n  function d3_eventDispatch(target) {\n    var dispatch = new d3_dispatch, i = 0, n = arguments.length;\n    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);\n    dispatch.of = function(thiz, argumentz) {\n      return function(e1) {\n        try {\n          var e0 = e1.sourceEvent = d3.event;\n          e1.target = target;\n          d3.event = e1;\n          dispatch[e1.type].apply(thiz, argumentz);\n        } finally {\n          d3.event = e0;\n        }\n      };\n    };\n    return dispatch;\n  }\n  d3.transform = function(string) {\n    var g = document.createElementNS(d3.ns.prefix.svg, \"g\");\n    return (d3.transform = function(string) {\n      g.setAttribute(\"transform\", string);\n      var t = g.transform.baseVal.consolidate();\n      return new d3_transform(t ? t.matrix : d3_transformIdentity);\n    })(string);\n  };\n  function d3_transform(m) {\n    var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;\n    if (r0[0] * r1[1] < r1[0] * r0[1]) {\n      r0[0] *= -1;\n      r0[1] *= -1;\n      kx *= -1;\n      kz *= -1;\n    }\n    this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_transformDegrees;\n    this.translate = [ m.e, m.f ];\n    this.scale = [ kx, ky ];\n    this.skew = ky ? Math.atan2(kz, ky) * d3_transformDegrees : 0;\n  }\n  d3_transform.prototype.toString = function() {\n    return \"translate(\" + this.translate + \")rotate(\" + this.rotate + \")skewX(\" + this.skew + \")scale(\" + this.scale + \")\";\n  };\n  function d3_transformDot(a, b) {\n    return a[0] * b[0] + a[1] * b[1];\n  }\n  function d3_transformNormalize(a) {\n    var k = Math.sqrt(d3_transformDot(a, a));\n    if (k) {\n      a[0] /= k;\n      a[1] /= k;\n    }\n    return k;\n  }\n  function d3_transformCombine(a, b, k) {\n    a[0] += k * b[0];\n    a[1] += k * b[1];\n    return a;\n  }\n  var d3_transformDegrees = 180 / Math.PI, d3_transformIdentity = {\n    a: 1,\n    b: 0,\n    c: 0,\n    d: 1,\n    e: 0,\n    f: 0\n  };\n  d3.interpolate = function(a, b) {\n    var i = d3.interpolators.length, f;\n    while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;\n    return f;\n  };\n  d3.interpolateNumber = function(a, b) {\n    b -= a;\n    return function(t) {\n      return a + b * t;\n    };\n  };\n  d3.interpolateRound = function(a, b) {\n    b -= a;\n    return function(t) {\n      return Math.round(a + b * t);\n    };\n  };\n  d3.interpolateString = function(a, b) {\n    var m, i, j, s0 = 0, s1 = 0, s = [], q = [], n, o;\n    d3_interpolate_number.lastIndex = 0;\n    for (i = 0; m = d3_interpolate_number.exec(b); ++i) {\n      if (m.index) s.push(b.substring(s0, s1 = m.index));\n      q.push({\n        i: s.length,\n        x: m[0]\n      });\n      s.push(null);\n      s0 = d3_interpolate_number.lastIndex;\n    }\n    if (s0 < b.length) s.push(b.substring(s0));\n    for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) {\n      o = q[i];\n      if (o.x == m[0]) {\n        if (o.i) {\n          if (s[o.i + 1] == null) {\n            s[o.i - 1] += o.x;\n            s.splice(o.i, 1);\n            for (j = i + 1; j < n; ++j) q[j].i--;\n          } else {\n            s[o.i - 1] += o.x + s[o.i + 1];\n            s.splice(o.i, 2);\n            for (j = i + 1; j < n; ++j) q[j].i -= 2;\n          }\n        } else {\n          if (s[o.i + 1] == null) {\n            s[o.i] = o.x;\n          } else {\n            s[o.i] = o.x + s[o.i + 1];\n            s.splice(o.i + 1, 1);\n            for (j = i + 1; j < n; ++j) q[j].i--;\n          }\n        }\n        q.splice(i, 1);\n        n--;\n        i--;\n      } else {\n        o.x = d3.interpolateNumber(parseFloat(m[0]), parseFloat(o.x));\n      }\n    }\n    while (i < n) {\n      o = q.pop();\n      if (s[o.i + 1] == null) {\n        s[o.i] = o.x;\n      } else {\n        s[o.i] = o.x + s[o.i + 1];\n        s.splice(o.i + 1, 1);\n      }\n      n--;\n    }\n    if (s.length === 1) {\n      return s[0] == null ? q[0].x : function() {\n        return b;\n      };\n    }\n    return function(t) {\n      for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t);\n      return s.join(\"\");\n    };\n  };\n  d3.interpolateTransform = function(a, b) {\n    var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale;\n    if (ta[0] != tb[0] || ta[1] != tb[1]) {\n      s.push(\"translate(\", null, \",\", null, \")\");\n      q.push({\n        i: 1,\n        x: d3.interpolateNumber(ta[0], tb[0])\n      }, {\n        i: 3,\n        x: d3.interpolateNumber(ta[1], tb[1])\n      });\n    } else if (tb[0] || tb[1]) {\n      s.push(\"translate(\" + tb + \")\");\n    } else {\n      s.push(\"\");\n    }\n    if (ra != rb) {\n      if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;\n      q.push({\n        i: s.push(s.pop() + \"rotate(\", null, \")\") - 2,\n        x: d3.interpolateNumber(ra, rb)\n      });\n    } else if (rb) {\n      s.push(s.pop() + \"rotate(\" + rb + \")\");\n    }\n    if (wa != wb) {\n      q.push({\n        i: s.push(s.pop() + \"skewX(\", null, \")\") - 2,\n        x: d3.interpolateNumber(wa, wb)\n      });\n    } else if (wb) {\n      s.push(s.pop() + \"skewX(\" + wb + \")\");\n    }\n    if (ka[0] != kb[0] || ka[1] != kb[1]) {\n      n = s.push(s.pop() + \"scale(\", null, \",\", null, \")\");\n      q.push({\n        i: n - 4,\n        x: d3.interpolateNumber(ka[0], kb[0])\n      }, {\n        i: n - 2,\n        x: d3.interpolateNumber(ka[1], kb[1])\n      });\n    } else if (kb[0] != 1 || kb[1] != 1) {\n      s.push(s.pop() + \"scale(\" + kb + \")\");\n    }\n    n = q.length;\n    return function(t) {\n      var i = -1, o;\n      while (++i < n) s[(o = q[i]).i] = o.x(t);\n      return s.join(\"\");\n    };\n  };\n  d3.interpolateRgb = function(a, b) {\n    a = d3.rgb(a);\n    b = d3.rgb(b);\n    var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;\n    return function(t) {\n      return \"#\" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));\n    };\n  };\n  d3.interpolateHsl = function(a, b) {\n    a = d3.hsl(a);\n    b = d3.hsl(b);\n    var h0 = a.h, s0 = a.s, l0 = a.l, h1 = b.h - h0, s1 = b.s - s0, l1 = b.l - l0;\n    if (h1 > 180) h1 -= 360; else if (h1 < -180) h1 += 360;\n    return function(t) {\n      return d3_hsl_rgb(h0 + h1 * t, s0 + s1 * t, l0 + l1 * t) + \"\";\n    };\n  };\n  d3.interpolateLab = function(a, b) {\n    a = d3.lab(a);\n    b = d3.lab(b);\n    var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;\n    return function(t) {\n      return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + \"\";\n    };\n  };\n  d3.interpolateHcl = function(a, b) {\n    a = d3.hcl(a);\n    b = d3.hcl(b);\n    var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;\n    if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;\n    return function(t) {\n      return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + \"\";\n    };\n  };\n  d3.interpolateArray = function(a, b) {\n    var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;\n    for (i = 0; i < n0; ++i) x.push(d3.interpolate(a[i], b[i]));\n    for (; i < na; ++i) c[i] = a[i];\n    for (; i < nb; ++i) c[i] = b[i];\n    return function(t) {\n      for (i = 0; i < n0; ++i) c[i] = x[i](t);\n      return c;\n    };\n  };\n  d3.interpolateObject = function(a, b) {\n    var i = {}, c = {}, k;\n    for (k in a) {\n      if (k in b) {\n        i[k] = d3_interpolateByName(k)(a[k], b[k]);\n      } else {\n        c[k] = a[k];\n      }\n    }\n    for (k in b) {\n      if (!(k in a)) {\n        c[k] = b[k];\n      }\n    }\n    return function(t) {\n      for (k in i) c[k] = i[k](t);\n      return c;\n    };\n  };\n  var d3_interpolate_number = /[-+]?(?:\\d+\\.?\\d*|\\.?\\d+)(?:[eE][-+]?\\d+)?/g;\n  function d3_interpolateByName(name) {\n    return name == \"transform\" ? d3.interpolateTransform : d3.interpolate;\n  }\n  d3.interpolators = [ d3.interpolateObject, function(a, b) {\n    return b instanceof Array && d3.interpolateArray(a, b);\n  }, function(a, b) {\n    return (typeof a === \"string\" || typeof b === \"string\") && d3.interpolateString(a + \"\", b + \"\");\n  }, function(a, b) {\n    return (typeof b === \"string\" ? d3_rgb_names.has(b) || /^(#|rgb\\(|hsl\\()/.test(b) : b instanceof d3_Rgb || b instanceof d3_Hsl) && d3.interpolateRgb(a, b);\n  }, function(a, b) {\n    return !isNaN(a = +a) && !isNaN(b = +b) && d3.interpolateNumber(a, b);\n  } ];\n  function d3_uninterpolateNumber(a, b) {\n    b = b - (a = +a) ? 1 / (b - a) : 0;\n    return function(x) {\n      return (x - a) * b;\n    };\n  }\n  function d3_uninterpolateClamp(a, b) {\n    b = b - (a = +a) ? 1 / (b - a) : 0;\n    return function(x) {\n      return Math.max(0, Math.min(1, (x - a) * b));\n    };\n  }\n  d3.rgb = function(r, g, b) {\n    return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse(\"\" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b);\n  };\n  function d3_rgb(r, g, b) {\n    return new d3_Rgb(r, g, b);\n  }\n  function d3_Rgb(r, g, b) {\n    this.r = r;\n    this.g = g;\n    this.b = b;\n  }\n  d3_Rgb.prototype.brighter = function(k) {\n    k = Math.pow(.7, arguments.length ? k : 1);\n    var r = this.r, g = this.g, b = this.b, i = 30;\n    if (!r && !g && !b) return d3_rgb(i, i, i);\n    if (r && r < i) r = i;\n    if (g && g < i) g = i;\n    if (b && b < i) b = i;\n    return d3_rgb(Math.min(255, Math.floor(r / k)), Math.min(255, Math.floor(g / k)), Math.min(255, Math.floor(b / k)));\n  };\n  d3_Rgb.prototype.darker = function(k) {\n    k = Math.pow(.7, arguments.length ? k : 1);\n    return d3_rgb(Math.floor(k * this.r), Math.floor(k * this.g), Math.floor(k * this.b));\n  };\n  d3_Rgb.prototype.hsl = function() {\n    return d3_rgb_hsl(this.r, this.g, this.b);\n  };\n  d3_Rgb.prototype.toString = function() {\n    return \"#\" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);\n  };\n  function d3_rgb_hex(v) {\n    return v < 16 ? \"0\" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);\n  }\n  function d3_rgb_parse(format, rgb, hsl) {\n    var r = 0, g = 0, b = 0, m1, m2, name;\n    m1 = /([a-z]+)\\((.*)\\)/i.exec(format);\n    if (m1) {\n      m2 = m1[2].split(\",\");\n      switch (m1[1]) {\n       case \"hsl\":\n        {\n          return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);\n        }\n       case \"rgb\":\n        {\n          return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));\n        }\n      }\n    }\n    if (name = d3_rgb_names.get(format)) return rgb(name.r, name.g, name.b);\n    if (format != null && format.charAt(0) === \"#\") {\n      if (format.length === 4) {\n        r = format.charAt(1);\n        r += r;\n        g = format.charAt(2);\n        g += g;\n        b = format.charAt(3);\n        b += b;\n      } else if (format.length === 7) {\n        r = format.substring(1, 3);\n        g = format.substring(3, 5);\n        b = format.substring(5, 7);\n      }\n      r = parseInt(r, 16);\n      g = parseInt(g, 16);\n      b = parseInt(b, 16);\n    }\n    return rgb(r, g, b);\n  }\n  function d3_rgb_hsl(r, g, b) {\n    var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;\n    if (d) {\n      s = l < .5 ? d / (max + min) : d / (2 - max - min);\n      if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;\n      h *= 60;\n    } else {\n      s = h = 0;\n    }\n    return d3_hsl(h, s, l);\n  }\n  function d3_rgb_lab(r, g, b) {\n    r = d3_rgb_xyz(r);\n    g = d3_rgb_xyz(g);\n    b = d3_rgb_xyz(b);\n    var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);\n    return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));\n  }\n  function d3_rgb_xyz(r) {\n    return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);\n  }\n  function d3_rgb_parseNumber(c) {\n    var f = parseFloat(c);\n    return c.charAt(c.length - 1) === \"%\" ? Math.round(f * 2.55) : f;\n  }\n  var d3_rgb_names = d3.map({\n    aliceblue: \"#f0f8ff\",\n    antiquewhite: \"#faebd7\",\n    aqua: \"#00ffff\",\n    aquamarine: \"#7fffd4\",\n    azure: \"#f0ffff\",\n    beige: \"#f5f5dc\",\n    bisque: \"#ffe4c4\",\n    black: \"#000000\",\n    blanchedalmond: \"#ffebcd\",\n    blue: \"#0000ff\",\n    blueviolet: \"#8a2be2\",\n    brown: \"#a52a2a\",\n    burlywood: \"#deb887\",\n    cadetblue: \"#5f9ea0\",\n    chartreuse: \"#7fff00\",\n    chocolate: \"#d2691e\",\n    coral: \"#ff7f50\",\n    cornflowerblue: \"#6495ed\",\n    cornsilk: \"#fff8dc\",\n    crimson: \"#dc143c\",\n    cyan: \"#00ffff\",\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: \"#ff00ff\",\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: \"#778899\",\n    lightslategrey: \"#778899\",\n    lightsteelblue: \"#b0c4de\",\n    lightyellow: \"#ffffe0\",\n    lime: \"#00ff00\",\n    limegreen: \"#32cd32\",\n    linen: \"#faf0e6\",\n    magenta: \"#ff00ff\",\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: \"#ff0000\",\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: \"#ffffff\",\n    whitesmoke: \"#f5f5f5\",\n    yellow: \"#ffff00\",\n    yellowgreen: \"#9acd32\"\n  });\n  d3_rgb_names.forEach(function(key, value) {\n    d3_rgb_names.set(key, d3_rgb_parse(value, d3_rgb, d3_hsl_rgb));\n  });\n  d3.hsl = function(h, s, l) {\n    return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse(\"\" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l);\n  };\n  function d3_hsl(h, s, l) {\n    return new d3_Hsl(h, s, l);\n  }\n  function d3_Hsl(h, s, l) {\n    this.h = h;\n    this.s = s;\n    this.l = l;\n  }\n  d3_Hsl.prototype.brighter = function(k) {\n    k = Math.pow(.7, arguments.length ? k : 1);\n    return d3_hsl(this.h, this.s, this.l / k);\n  };\n  d3_Hsl.prototype.darker = function(k) {\n    k = Math.pow(.7, arguments.length ? k : 1);\n    return d3_hsl(this.h, this.s, k * this.l);\n  };\n  d3_Hsl.prototype.rgb = function() {\n    return d3_hsl_rgb(this.h, this.s, this.l);\n  };\n  d3_Hsl.prototype.toString = function() {\n    return this.rgb().toString();\n  };\n  function d3_hsl_rgb(h, s, l) {\n    var m1, m2;\n    h = h % 360;\n    if (h < 0) h += 360;\n    s = s < 0 ? 0 : s > 1 ? 1 : s;\n    l = l < 0 ? 0 : l > 1 ? 1 : l;\n    m2 = l <= .5 ? l * (1 + s) : l + s - l * s;\n    m1 = 2 * l - m2;\n    function v(h) {\n      if (h > 360) h -= 360; else if (h < 0) h += 360;\n      if (h < 60) return m1 + (m2 - m1) * h / 60;\n      if (h < 180) return m2;\n      if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;\n      return m1;\n    }\n    function vv(h) {\n      return Math.round(v(h) * 255);\n    }\n    return d3_rgb(vv(h + 120), vv(h), vv(h - 120));\n  }\n  d3.hcl = function(h, c, l) {\n    return arguments.length === 1 ? h instanceof d3_Hcl ? d3_hcl(h.h, h.c, h.l) : h instanceof d3_Lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : d3_hcl(+h, +c, +l);\n  };\n  function d3_hcl(h, c, l) {\n    return new d3_Hcl(h, c, l);\n  }\n  function d3_Hcl(h, c, l) {\n    this.h = h;\n    this.c = c;\n    this.l = l;\n  }\n  d3_Hcl.prototype.brighter = function(k) {\n    return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));\n  };\n  d3_Hcl.prototype.darker = function(k) {\n    return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));\n  };\n  d3_Hcl.prototype.rgb = function() {\n    return d3_hcl_lab(this.h, this.c, this.l).rgb();\n  };\n  d3_Hcl.prototype.toString = function() {\n    return this.rgb() + \"\";\n  };\n  function d3_hcl_lab(h, c, l) {\n    return d3_lab(l, Math.cos(h *= Math.PI / 180) * c, Math.sin(h) * c);\n  }\n  d3.lab = function(l, a, b) {\n    return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b);\n  };\n  function d3_lab(l, a, b) {\n    return new d3_Lab(l, a, b);\n  }\n  function d3_Lab(l, a, b) {\n    this.l = l;\n    this.a = a;\n    this.b = b;\n  }\n  var d3_lab_K = 18;\n  var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;\n  d3_Lab.prototype.brighter = function(k) {\n    return d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);\n  };\n  d3_Lab.prototype.darker = function(k) {\n    return d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);\n  };\n  d3_Lab.prototype.rgb = function() {\n    return d3_lab_rgb(this.l, this.a, this.b);\n  };\n  d3_Lab.prototype.toString = function() {\n    return this.rgb() + \"\";\n  };\n  function d3_lab_rgb(l, a, b) {\n    var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;\n    x = d3_lab_xyz(x) * d3_lab_X;\n    y = d3_lab_xyz(y) * d3_lab_Y;\n    z = d3_lab_xyz(z) * d3_lab_Z;\n    return d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));\n  }\n  function d3_lab_hcl(l, a, b) {\n    return d3_hcl(Math.atan2(b, a) / Math.PI * 180, Math.sqrt(a * a + b * b), l);\n  }\n  function d3_lab_xyz(x) {\n    return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;\n  }\n  function d3_xyz_lab(x) {\n    return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;\n  }\n  function d3_xyz_rgb(r) {\n    return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));\n  }\n  function d3_selection(groups) {\n    d3_arraySubclass(groups, d3_selectionPrototype);\n    return groups;\n  }\n  var d3_select = function(s, n) {\n    return n.querySelector(s);\n  }, d3_selectAll = function(s, n) {\n    return n.querySelectorAll(s);\n  }, d3_selectRoot = document.documentElement, d3_selectMatcher = d3_selectRoot.matchesSelector || d3_selectRoot.webkitMatchesSelector || d3_selectRoot.mozMatchesSelector || d3_selectRoot.msMatchesSelector || d3_selectRoot.oMatchesSelector, d3_selectMatches = function(n, s) {\n    return d3_selectMatcher.call(n, s);\n  };\n  if (typeof Sizzle === \"function\") {\n    d3_select = function(s, n) {\n      return Sizzle(s, n)[0] || null;\n    };\n    d3_selectAll = function(s, n) {\n      return Sizzle.uniqueSort(Sizzle(s, n));\n    };\n    d3_selectMatches = Sizzle.matchesSelector;\n  }\n  var d3_selectionPrototype = [];\n  d3.selection = function() {\n    return d3_selectionRoot;\n  };\n  d3.selection.prototype = d3_selectionPrototype;\n  d3_selectionPrototype.select = function(selector) {\n    var subgroups = [], subgroup, subnode, group, node;\n    if (typeof selector !== \"function\") selector = d3_selection_selector(selector);\n    for (var j = -1, m = this.length; ++j < m; ) {\n      subgroups.push(subgroup = []);\n      subgroup.parentNode = (group = this[j]).parentNode;\n      for (var i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) {\n          subgroup.push(subnode = selector.call(node, node.__data__, i));\n          if (subnode && \"__data__\" in node) subnode.__data__ = node.__data__;\n        } else {\n          subgroup.push(null);\n        }\n      }\n    }\n    return d3_selection(subgroups);\n  };\n  function d3_selection_selector(selector) {\n    return function() {\n      return d3_select(selector, this);\n    };\n  }\n  d3_selectionPrototype.selectAll = function(selector) {\n    var subgroups = [], subgroup, node;\n    if (typeof selector !== \"function\") selector = d3_selection_selectorAll(selector);\n    for (var j = -1, m = this.length; ++j < m; ) {\n      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) {\n          subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i)));\n          subgroup.parentNode = node;\n        }\n      }\n    }\n    return d3_selection(subgroups);\n  };\n  function d3_selection_selectorAll(selector) {\n    return function() {\n      return d3_selectAll(selector, this);\n    };\n  }\n  d3_selectionPrototype.attr = function(name, value) {\n    if (arguments.length < 2) {\n      if (typeof name === \"string\") {\n        var node = this.node();\n        name = d3.ns.qualify(name);\n        return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);\n      }\n      for (value in name) this.each(d3_selection_attr(value, name[value]));\n      return this;\n    }\n    return this.each(d3_selection_attr(name, value));\n  };\n  function d3_selection_attr(name, value) {\n    name = d3.ns.qualify(name);\n    function attrNull() {\n      this.removeAttribute(name);\n    }\n    function attrNullNS() {\n      this.removeAttributeNS(name.space, name.local);\n    }\n    function attrConstant() {\n      this.setAttribute(name, value);\n    }\n    function attrConstantNS() {\n      this.setAttributeNS(name.space, name.local, value);\n    }\n    function attrFunction() {\n      var x = value.apply(this, arguments);\n      if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);\n    }\n    function attrFunctionNS() {\n      var x = value.apply(this, arguments);\n      if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);\n    }\n    return value == null ? name.local ? attrNullNS : attrNull : typeof value === \"function\" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;\n  }\n  d3_selectionPrototype.classed = function(name, value) {\n    if (arguments.length < 2) {\n      if (typeof name === \"string\") {\n        var node = this.node(), n = (name = name.trim().split(/^|\\s+/g)).length, i = -1;\n        if (value = node.classList) {\n          while (++i < n) if (!value.contains(name[i])) return false;\n        } else {\n          value = node.className;\n          if (value.baseVal != null) value = value.baseVal;\n          while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;\n        }\n        return true;\n      }\n      for (value in name) this.each(d3_selection_classed(value, name[value]));\n      return this;\n    }\n    return this.each(d3_selection_classed(name, value));\n  };\n  function d3_selection_classedRe(name) {\n    return new RegExp(\"(?:^|\\\\s+)\" + d3.requote(name) + \"(?:\\\\s+|$)\", \"g\");\n  }\n  function d3_selection_classed(name, value) {\n    name = name.trim().split(/\\s+/).map(d3_selection_classedName);\n    var n = name.length;\n    function classedConstant() {\n      var i = -1;\n      while (++i < n) name[i](this, value);\n    }\n    function classedFunction() {\n      var i = -1, x = value.apply(this, arguments);\n      while (++i < n) name[i](this, x);\n    }\n    return typeof value === \"function\" ? classedFunction : classedConstant;\n  }\n  function d3_selection_classedName(name) {\n    var re = d3_selection_classedRe(name);\n    return function(node, value) {\n      if (c = node.classList) return value ? c.add(name) : c.remove(name);\n      var c = node.className, cb = c.baseVal != null, cv = cb ? c.baseVal : c;\n      if (value) {\n        re.lastIndex = 0;\n        if (!re.test(cv)) {\n          cv = d3_collapse(cv + \" \" + name);\n          if (cb) c.baseVal = cv; else node.className = cv;\n        }\n      } else if (cv) {\n        cv = d3_collapse(cv.replace(re, \" \"));\n        if (cb) c.baseVal = cv; else node.className = cv;\n      }\n    };\n  }\n  d3_selectionPrototype.style = function(name, value, priority) {\n    var n = arguments.length;\n    if (n < 3) {\n      if (typeof name !== \"string\") {\n        if (n < 2) value = \"\";\n        for (priority in name) this.each(d3_selection_style(priority, name[priority], value));\n        return this;\n      }\n      if (n < 2) return window.getComputedStyle(this.node(), null).getPropertyValue(name);\n      priority = \"\";\n    }\n    return this.each(d3_selection_style(name, value, priority));\n  };\n  function d3_selection_style(name, value, priority) {\n    function styleNull() {\n      this.style.removeProperty(name);\n    }\n    function styleConstant() {\n      this.style.setProperty(name, value, priority);\n    }\n    function styleFunction() {\n      var x = value.apply(this, arguments);\n      if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);\n    }\n    return value == null ? styleNull : typeof value === \"function\" ? styleFunction : styleConstant;\n  }\n  d3_selectionPrototype.property = function(name, value) {\n    if (arguments.length < 2) {\n      if (typeof name === \"string\") return this.node()[name];\n      for (value in name) this.each(d3_selection_property(value, name[value]));\n      return this;\n    }\n    return this.each(d3_selection_property(name, value));\n  };\n  function d3_selection_property(name, value) {\n    function propertyNull() {\n      delete this[name];\n    }\n    function propertyConstant() {\n      this[name] = value;\n    }\n    function propertyFunction() {\n      var x = value.apply(this, arguments);\n      if (x == null) delete this[name]; else this[name] = x;\n    }\n    return value == null ? propertyNull : typeof value === \"function\" ? propertyFunction : propertyConstant;\n  }\n  d3_selectionPrototype.text = function(value) {\n    return arguments.length < 1 ? this.node().textContent : this.each(typeof value === \"function\" ? function() {\n      var v = value.apply(this, arguments);\n      this.textContent = v == null ? \"\" : v;\n    } : value == null ? function() {\n      this.textContent = \"\";\n    } : function() {\n      this.textContent = value;\n    });\n  };\n  d3_selectionPrototype.html = function(value) {\n    return arguments.length < 1 ? this.node().innerHTML : this.each(typeof value === \"function\" ? function() {\n      var v = value.apply(this, arguments);\n      this.innerHTML = v == null ? \"\" : v;\n    } : value == null ? function() {\n      this.innerHTML = \"\";\n    } : function() {\n      this.innerHTML = value;\n    });\n  };\n  d3_selectionPrototype.append = function(name) {\n    name = d3.ns.qualify(name);\n    function append() {\n      return this.appendChild(document.createElementNS(this.namespaceURI, name));\n    }\n    function appendNS() {\n      return this.appendChild(document.createElementNS(name.space, name.local));\n    }\n    return this.select(name.local ? appendNS : append);\n  };\n  d3_selectionPrototype.insert = function(name, before) {\n    name = d3.ns.qualify(name);\n    function insert() {\n      return this.insertBefore(document.createElementNS(this.namespaceURI, name), d3_select(before, this));\n    }\n    function insertNS() {\n      return this.insertBefore(document.createElementNS(name.space, name.local), d3_select(before, this));\n    }\n    return this.select(name.local ? insertNS : insert);\n  };\n  d3_selectionPrototype.remove = function() {\n    return this.each(function() {\n      var parent = this.parentNode;\n      if (parent) parent.removeChild(this);\n    });\n  };\n  d3_selectionPrototype.data = function(value, key) {\n    var i = -1, n = this.length, group, node;\n    if (!arguments.length) {\n      value = new Array(n = (group = this[0]).length);\n      while (++i < n) {\n        if (node = group[i]) {\n          value[i] = node.__data__;\n        }\n      }\n      return value;\n    }\n    function bind(group, groupData) {\n      var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), n1 = Math.max(n, m), updateNodes = [], enterNodes = [], exitNodes = [], node, nodeData;\n      if (key) {\n        var nodeByKeyValue = new d3_Map, keyValues = [], keyValue, j = groupData.length;\n        for (i = -1; ++i < n; ) {\n          keyValue = key.call(node = group[i], node.__data__, i);\n          if (nodeByKeyValue.has(keyValue)) {\n            exitNodes[j++] = node;\n          } else {\n            nodeByKeyValue.set(keyValue, node);\n          }\n          keyValues.push(keyValue);\n        }\n        for (i = -1; ++i < m; ) {\n          keyValue = key.call(groupData, nodeData = groupData[i], i);\n          if (nodeByKeyValue.has(keyValue)) {\n            updateNodes[i] = node = nodeByKeyValue.get(keyValue);\n            node.__data__ = nodeData;\n            enterNodes[i] = exitNodes[i] = null;\n          } else {\n            enterNodes[i] = d3_selection_dataNode(nodeData);\n            updateNodes[i] = exitNodes[i] = null;\n          }\n          nodeByKeyValue.remove(keyValue);\n        }\n        for (i = -1; ++i < n; ) {\n          if (nodeByKeyValue.has(keyValues[i])) {\n            exitNodes[i] = group[i];\n          }\n        }\n      } else {\n        for (i = -1; ++i < n0; ) {\n          node = group[i];\n          nodeData = groupData[i];\n          if (node) {\n            node.__data__ = nodeData;\n            updateNodes[i] = node;\n            enterNodes[i] = exitNodes[i] = null;\n          } else {\n            enterNodes[i] = d3_selection_dataNode(nodeData);\n            updateNodes[i] = exitNodes[i] = null;\n          }\n        }\n        for (; i < m; ++i) {\n          enterNodes[i] = d3_selection_dataNode(groupData[i]);\n          updateNodes[i] = exitNodes[i] = null;\n        }\n        for (; i < n1; ++i) {\n          exitNodes[i] = group[i];\n          enterNodes[i] = updateNodes[i] = null;\n        }\n      }\n      enterNodes.update = updateNodes;\n      enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;\n      enter.push(enterNodes);\n      update.push(updateNodes);\n      exit.push(exitNodes);\n    }\n    var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);\n    if (typeof value === \"function\") {\n      while (++i < n) {\n        bind(group = this[i], value.call(group, group.parentNode.__data__, i));\n      }\n    } else {\n      while (++i < n) {\n        bind(group = this[i], value);\n      }\n    }\n    update.enter = function() {\n      return enter;\n    };\n    update.exit = function() {\n      return exit;\n    };\n    return update;\n  };\n  function d3_selection_dataNode(data) {\n    return {\n      __data__: data\n    };\n  }\n  d3_selectionPrototype.datum = d3_selectionPrototype.map = function(value) {\n    return arguments.length < 1 ? this.property(\"__data__\") : this.property(\"__data__\", value);\n  };\n  d3_selectionPrototype.filter = function(filter) {\n    var subgroups = [], subgroup, group, node;\n    if (typeof filter !== \"function\") filter = d3_selection_filter(filter);\n    for (var j = 0, m = this.length; j < m; j++) {\n      subgroups.push(subgroup = []);\n      subgroup.parentNode = (group = this[j]).parentNode;\n      for (var i = 0, n = group.length; i < n; i++) {\n        if ((node = group[i]) && filter.call(node, node.__data__, i)) {\n          subgroup.push(node);\n        }\n      }\n    }\n    return d3_selection(subgroups);\n  };\n  function d3_selection_filter(selector) {\n    return function() {\n      return d3_selectMatches(this, selector);\n    };\n  }\n  d3_selectionPrototype.order = function() {\n    for (var j = -1, m = this.length; ++j < m; ) {\n      for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {\n        if (node = group[i]) {\n          if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);\n          next = node;\n        }\n      }\n    }\n    return this;\n  };\n  d3_selectionPrototype.sort = function(comparator) {\n    comparator = d3_selection_sortComparator.apply(this, arguments);\n    for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);\n    return this.order();\n  };\n  function d3_selection_sortComparator(comparator) {\n    if (!arguments.length) comparator = d3.ascending;\n    return function(a, b) {\n      return comparator(a && a.__data__, b && b.__data__);\n    };\n  }\n  d3_selectionPrototype.on = function(type, listener, capture) {\n    var n = arguments.length;\n    if (n < 3) {\n      if (typeof type !== \"string\") {\n        if (n < 2) listener = false;\n        for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));\n        return this;\n      }\n      if (n < 2) return (n = this.node()[\"__on\" + type]) && n._;\n      capture = false;\n    }\n    return this.each(d3_selection_on(type, listener, capture));\n  };\n  function d3_selection_on(type, listener, capture) {\n    var name = \"__on\" + type, i = type.indexOf(\".\");\n    if (i > 0) type = type.substring(0, i);\n    function onRemove() {\n      var wrapper = this[name];\n      if (wrapper) {\n        this.removeEventListener(type, wrapper, wrapper.$);\n        delete this[name];\n      }\n    }\n    function onAdd() {\n      var node = this, args = arguments;\n      onRemove.call(this);\n      this.addEventListener(type, this[name] = wrapper, wrapper.$ = capture);\n      wrapper._ = listener;\n      function wrapper(e) {\n        var o = d3.event;\n        d3.event = e;\n        args[0] = node.__data__;\n        try {\n          listener.apply(node, args);\n        } finally {\n          d3.event = o;\n        }\n      }\n    }\n    return listener ? onAdd : onRemove;\n  }\n  d3_selectionPrototype.each = function(callback) {\n    return d3_selection_each(this, function(node, i, j) {\n      callback.call(node, node.__data__, i, j);\n    });\n  };\n  function d3_selection_each(groups, callback) {\n    for (var j = 0, m = groups.length; j < m; j++) {\n      for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {\n        if (node = group[i]) callback(node, i, j);\n      }\n    }\n    return groups;\n  }\n  d3_selectionPrototype.call = function(callback) {\n    callback.apply(this, (arguments[0] = this, arguments));\n    return this;\n  };\n  d3_selectionPrototype.empty = function() {\n    return !this.node();\n  };\n  d3_selectionPrototype.node = function(callback) {\n    for (var j = 0, m = this.length; j < m; j++) {\n      for (var group = this[j], i = 0, n = group.length; i < n; i++) {\n        var node = group[i];\n        if (node) return node;\n      }\n    }\n    return null;\n  };\n  d3_selectionPrototype.transition = function() {\n    var subgroups = [], subgroup, node;\n    for (var j = -1, m = this.length; ++j < m; ) {\n      subgroups.push(subgroup = []);\n      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {\n        subgroup.push((node = group[i]) ? {\n          node: node,\n          delay: d3_transitionDelay,\n          duration: d3_transitionDuration\n        } : null);\n      }\n    }\n    return d3_transition(subgroups, d3_transitionId || ++d3_transitionNextId, Date.now());\n  };\n  var d3_selectionRoot = d3_selection([ [ document ] ]);\n  d3_selectionRoot[0].parentNode = d3_selectRoot;\n  d3.select = function(selector) {\n    return typeof selector === \"string\" ? d3_selectionRoot.select(selector) : d3_selection([ [ selector ] ]);\n  };\n  d3.selectAll = function(selector) {\n    return typeof selector === \"string\" ? d3_selectionRoot.selectAll(selector) : d3_selection([ d3_array(selector) ]);\n  };\n  function d3_selection_enter(selection) {\n    d3_arraySubclass(selection, d3_selection_enterPrototype);\n    return selection;\n  }\n  var d3_selection_enterPrototype = [];\n  d3.selection.enter = d3_selection_enter;\n  d3.selection.enter.prototype = d3_selection_enterPrototype;\n  d3_selection_enterPrototype.append = d3_selectionPrototype.append;\n  d3_selection_enterPrototype.insert = d3_selectionPrototype.insert;\n  d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;\n  d3_selection_enterPrototype.node = d3_selectionPrototype.node;\n  d3_selection_enterPrototype.select = function(selector) {\n    var subgroups = [], subgroup, subnode, upgroup, group, node;\n    for (var j = -1, m = this.length; ++j < m; ) {\n      upgroup = (group = this[j]).update;\n      subgroups.push(subgroup = []);\n      subgroup.parentNode = group.parentNode;\n      for (var i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) {\n          subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i));\n          subnode.__data__ = node.__data__;\n        } else {\n          subgroup.push(null);\n        }\n      }\n    }\n    return d3_selection(subgroups);\n  };\n  function d3_transition(groups, id, time) {\n    d3_arraySubclass(groups, d3_transitionPrototype);\n    var tweens = new d3_Map, event = d3.dispatch(\"start\", \"end\"), ease = d3_transitionEase;\n    groups.id = id;\n    groups.time = time;\n    groups.tween = function(name, tween) {\n      if (arguments.length < 2) return tweens.get(name);\n      if (tween == null) tweens.remove(name); else tweens.set(name, tween);\n      return groups;\n    };\n    groups.ease = function(value) {\n      if (!arguments.length) return ease;\n      ease = typeof value === \"function\" ? value : d3.ease.apply(d3, arguments);\n      return groups;\n    };\n    groups.each = function(type, listener) {\n      if (arguments.length < 2) return d3_transition_each.call(groups, type);\n      event.on(type, listener);\n      return groups;\n    };\n    d3.timer(function(elapsed) {\n      return d3_selection_each(groups, function(node, i, j) {\n        var tweened = [], delay = node.delay, duration = node.duration, lock = (node = node.node).__transition__ || (node.__transition__ = {\n          active: 0,\n          count: 0\n        }), d = node.__data__;\n        ++lock.count;\n        delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time);\n        function start(elapsed) {\n          if (lock.active > id) return stop();\n          lock.active = id;\n          tweens.forEach(function(key, value) {\n            if (value = value.call(node, d, i)) {\n              tweened.push(value);\n            }\n          });\n          event.start.call(node, d, i);\n          if (!tick(elapsed)) d3.timer(tick, 0, time);\n          return 1;\n        }\n        function tick(elapsed) {\n          if (lock.active !== id) return stop();\n          var t = (elapsed - delay) / duration, e = ease(t), n = tweened.length;\n          while (n > 0) {\n            tweened[--n].call(node, e);\n          }\n          if (t >= 1) {\n            stop();\n            d3_transitionId = id;\n            event.end.call(node, d, i);\n            d3_transitionId = 0;\n            return 1;\n          }\n        }\n        function stop() {\n          if (!--lock.count) delete node.__transition__;\n          return 1;\n        }\n      });\n    }, 0, time);\n    return groups;\n  }\n  var d3_transitionPrototype = [], d3_transitionNextId = 0, d3_transitionId = 0, d3_transitionDefaultDelay = 0, d3_transitionDefaultDuration = 250, d3_transitionDefaultEase = d3.ease(\"cubic-in-out\"), d3_transitionDelay = d3_transitionDefaultDelay, d3_transitionDuration = d3_transitionDefaultDuration, d3_transitionEase = d3_transitionDefaultEase;\n  d3_transitionPrototype.call = d3_selectionPrototype.call;\n  d3.transition = function(selection) {\n    return arguments.length ? d3_transitionId ? selection.transition() : selection : d3_selectionRoot.transition();\n  };\n  d3.transition.prototype = d3_transitionPrototype;\n  d3_transitionPrototype.select = function(selector) {\n    var subgroups = [], subgroup, subnode, node;\n    if (typeof selector !== \"function\") selector = d3_selection_selector(selector);\n    for (var j = -1, m = this.length; ++j < m; ) {\n      subgroups.push(subgroup = []);\n      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {\n        if ((node = group[i]) && (subnode = selector.call(node.node, node.node.__data__, i))) {\n          if (\"__data__\" in node.node) subnode.__data__ = node.node.__data__;\n          subgroup.push({\n            node: subnode,\n            delay: node.delay,\n            duration: node.duration\n          });\n        } else {\n          subgroup.push(null);\n        }\n      }\n    }\n    return d3_transition(subgroups, this.id, this.time).ease(this.ease());\n  };\n  d3_transitionPrototype.selectAll = function(selector) {\n    var subgroups = [], subgroup, subnodes, node;\n    if (typeof selector !== \"function\") selector = d3_selection_selectorAll(selector);\n    for (var j = -1, m = this.length; ++j < m; ) {\n      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) {\n          subnodes = selector.call(node.node, node.node.__data__, i);\n          subgroups.push(subgroup = []);\n          for (var k = -1, o = subnodes.length; ++k < o; ) {\n            subgroup.push({\n              node: subnodes[k],\n              delay: node.delay,\n              duration: node.duration\n            });\n          }\n        }\n      }\n    }\n    return d3_transition(subgroups, this.id, this.time).ease(this.ease());\n  };\n  d3_transitionPrototype.filter = function(filter) {\n    var subgroups = [], subgroup, group, node;\n    if (typeof filter !== \"function\") filter = d3_selection_filter(filter);\n    for (var j = 0, m = this.length; j < m; j++) {\n      subgroups.push(subgroup = []);\n      for (var group = this[j], i = 0, n = group.length; i < n; i++) {\n        if ((node = group[i]) && filter.call(node.node, node.node.__data__, i)) {\n          subgroup.push(node);\n        }\n      }\n    }\n    return d3_transition(subgroups, this.id, this.time).ease(this.ease());\n  };\n  d3_transitionPrototype.attr = function(name, value) {\n    if (arguments.length < 2) {\n      for (value in name) this.attrTween(value, d3_tweenByName(name[value], value));\n      return this;\n    }\n    return this.attrTween(name, d3_tweenByName(value, name));\n  };\n  d3_transitionPrototype.attrTween = function(nameNS, tween) {\n    var name = d3.ns.qualify(nameNS);\n    function attrTween(d, i) {\n      var f = tween.call(this, d, i, this.getAttribute(name));\n      return f === d3_tweenRemove ? (this.removeAttribute(name), null) : f && function(t) {\n        this.setAttribute(name, f(t));\n      };\n    }\n    function attrTweenNS(d, i) {\n      var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));\n      return f === d3_tweenRemove ? (this.removeAttributeNS(name.space, name.local), null) : f && function(t) {\n        this.setAttributeNS(name.space, name.local, f(t));\n      };\n    }\n    return this.tween(\"attr.\" + nameNS, name.local ? attrTweenNS : attrTween);\n  };\n  d3_transitionPrototype.style = function(name, value, priority) {\n    var n = arguments.length;\n    if (n < 3) {\n      if (typeof name !== \"string\") {\n        if (n < 2) value = \"\";\n        for (priority in name) this.styleTween(priority, d3_tweenByName(name[priority], priority), value);\n        return this;\n      }\n      priority = \"\";\n    }\n    return this.styleTween(name, d3_tweenByName(value, name), priority);\n  };\n  d3_transitionPrototype.styleTween = function(name, tween, priority) {\n    if (arguments.length < 3) priority = \"\";\n    return this.tween(\"style.\" + name, function(d, i) {\n      var f = tween.call(this, d, i, window.getComputedStyle(this, null).getPropertyValue(name));\n      return f === d3_tweenRemove ? (this.style.removeProperty(name), null) : f && function(t) {\n        this.style.setProperty(name, f(t), priority);\n      };\n    });\n  };\n  d3_transitionPrototype.text = function(value) {\n    return this.tween(\"text\", function(d, i) {\n      this.textContent = typeof value === \"function\" ? value.call(this, d, i) : value;\n    });\n  };\n  d3_transitionPrototype.remove = function() {\n    return this.each(\"end.transition\", function() {\n      var p;\n      if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this);\n    });\n  };\n  d3_transitionPrototype.delay = function(value) {\n    return d3_selection_each(this, typeof value === \"function\" ? function(node, i, j) {\n      node.delay = value.call(node = node.node, node.__data__, i, j) | 0;\n    } : (value = value | 0, function(node) {\n      node.delay = value;\n    }));\n  };\n  d3_transitionPrototype.duration = function(value) {\n    return d3_selection_each(this, typeof value === \"function\" ? function(node, i, j) {\n      node.duration = Math.max(1, value.call(node = node.node, node.__data__, i, j) | 0);\n    } : (value = Math.max(1, value | 0), function(node) {\n      node.duration = value;\n    }));\n  };\n  function d3_transition_each(callback) {\n    var id = d3_transitionId, ease = d3_transitionEase, delay = d3_transitionDelay, duration = d3_transitionDuration;\n    d3_transitionId = this.id;\n    d3_transitionEase = this.ease();\n    d3_selection_each(this, function(node, i, j) {\n      d3_transitionDelay = node.delay;\n      d3_transitionDuration = node.duration;\n      callback.call(node = node.node, node.__data__, i, j);\n    });\n    d3_transitionId = id;\n    d3_transitionEase = ease;\n    d3_transitionDelay = delay;\n    d3_transitionDuration = duration;\n    return this;\n  }\n  d3_transitionPrototype.transition = function() {\n    return this.select(d3_this);\n  };\n  d3.tween = function(b, interpolate) {\n    function tweenFunction(d, i, a) {\n      var v = b.call(this, d, i);\n      return v == null ? a != \"\" && d3_tweenRemove : a != v && interpolate(a, v);\n    }\n    function tweenString(d, i, a) {\n      return a != b && interpolate(a, b);\n    }\n    return typeof b === \"function\" ? tweenFunction : b == null ? d3_tweenNull : (b += \"\", tweenString);\n  };\n  var d3_tweenRemove = {};\n  function d3_tweenNull(d, i, a) {\n    return a != \"\" && d3_tweenRemove;\n  }\n  function d3_tweenByName(b, name) {\n    return d3.tween(b, d3_interpolateByName(name));\n  }\n  var d3_timer_queue = null, d3_timer_interval, d3_timer_timeout;\n  d3.timer = function(callback, delay, then) {\n    var found = false, t0, t1 = d3_timer_queue;\n    if (arguments.length < 3) {\n      if (arguments.length < 2) delay = 0; else if (!isFinite(delay)) return;\n      then = Date.now();\n    }\n    while (t1) {\n      if (t1.callback === callback) {\n        t1.then = then;\n        t1.delay = delay;\n        found = true;\n        break;\n      }\n      t0 = t1;\n      t1 = t1.next;\n    }\n    if (!found) d3_timer_queue = {\n      callback: callback,\n      then: then,\n      delay: delay,\n      next: d3_timer_queue\n    };\n    if (!d3_timer_interval) {\n      d3_timer_timeout = clearTimeout(d3_timer_timeout);\n      d3_timer_interval = 1;\n      d3_timer_frame(d3_timer_step);\n    }\n  };\n  function d3_timer_step() {\n    var elapsed, now = Date.now(), t1 = d3_timer_queue;\n    while (t1) {\n      elapsed = now - t1.then;\n      if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed);\n      t1 = t1.next;\n    }\n    var delay = d3_timer_flush() - now;\n    if (delay > 24) {\n      if (isFinite(delay)) {\n        clearTimeout(d3_timer_timeout);\n        d3_timer_timeout = setTimeout(d3_timer_step, delay);\n      }\n      d3_timer_interval = 0;\n    } else {\n      d3_timer_interval = 1;\n      d3_timer_frame(d3_timer_step);\n    }\n  }\n  d3.timer.flush = function() {\n    var elapsed, now = Date.now(), t1 = d3_timer_queue;\n    while (t1) {\n      elapsed = now - t1.then;\n      if (!t1.delay) t1.flush = t1.callback(elapsed);\n      t1 = t1.next;\n    }\n    d3_timer_flush();\n  };\n  function d3_timer_flush() {\n    var t0 = null, t1 = d3_timer_queue, then = Infinity;\n    while (t1) {\n      if (t1.flush) {\n        t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next;\n      } else {\n        then = Math.min(then, t1.then + t1.delay);\n        t1 = (t0 = t1).next;\n      }\n    }\n    return then;\n  }\n  var d3_timer_frame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {\n    setTimeout(callback, 17);\n  };\n  d3.mouse = function(container) {\n    return d3_mousePoint(container, d3_eventSource());\n  };\n  var d3_mouse_bug44083 = /WebKit/.test(navigator.userAgent) ? -1 : 0;\n  function d3_mousePoint(container, e) {\n    var svg = container.ownerSVGElement || container;\n    if (svg.createSVGPoint) {\n      var point = svg.createSVGPoint();\n      if (d3_mouse_bug44083 < 0 && (window.scrollX || window.scrollY)) {\n        svg = d3.select(document.body).append(\"svg\").style(\"position\", \"absolute\").style(\"top\", 0).style(\"left\", 0);\n        var ctm = svg[0][0].getScreenCTM();\n        d3_mouse_bug44083 = !(ctm.f || ctm.e);\n        svg.remove();\n      }\n      if (d3_mouse_bug44083) {\n        point.x = e.pageX;\n        point.y = e.pageY;\n      } else {\n        point.x = e.clientX;\n        point.y = e.clientY;\n      }\n      point = point.matrixTransform(container.getScreenCTM().inverse());\n      return [ point.x, point.y ];\n    }\n    var rect = container.getBoundingClientRect();\n    return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];\n  }\n  d3.touches = function(container, touches) {\n    if (arguments.length < 2) touches = d3_eventSource().touches;\n    return touches ? d3_array(touches).map(function(touch) {\n      var point = d3_mousePoint(container, touch);\n      point.identifier = touch.identifier;\n      return point;\n    }) : [];\n  };\n  function d3_noop() {}\n  d3.scale = {};\n  function d3_scaleExtent(domain) {\n    var start = domain[0], stop = domain[domain.length - 1];\n    return start < stop ? [ start, stop ] : [ stop, start ];\n  }\n  function d3_scaleRange(scale) {\n    return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());\n  }\n  function d3_scale_nice(domain, nice) {\n    var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;\n    if (x1 < x0) {\n      dx = i0, i0 = i1, i1 = dx;\n      dx = x0, x0 = x1, x1 = dx;\n    }\n    if (nice = nice(x1 - x0)) {\n      domain[i0] = nice.floor(x0);\n      domain[i1] = nice.ceil(x1);\n    }\n    return domain;\n  }\n  function d3_scale_niceDefault() {\n    return Math;\n  }\n  d3.scale.linear = function() {\n    return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3.interpolate, false);\n  };\n  function d3_scale_linear(domain, range, interpolate, clamp) {\n    var output, input;\n    function rescale() {\n      var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;\n      output = linear(domain, range, uninterpolate, interpolate);\n      input = linear(range, domain, uninterpolate, d3.interpolate);\n      return scale;\n    }\n    function scale(x) {\n      return output(x);\n    }\n    scale.invert = function(y) {\n      return input(y);\n    };\n    scale.domain = function(x) {\n      if (!arguments.length) return domain;\n      domain = x.map(Number);\n      return rescale();\n    };\n    scale.range = function(x) {\n      if (!arguments.length) return range;\n      range = x;\n      return rescale();\n    };\n    scale.rangeRound = function(x) {\n      return scale.range(x).interpolate(d3.interpolateRound);\n    };\n    scale.clamp = function(x) {\n      if (!arguments.length) return clamp;\n      clamp = x;\n      return rescale();\n    };\n    scale.interpolate = function(x) {\n      if (!arguments.length) return interpolate;\n      interpolate = x;\n      return rescale();\n    };\n    scale.ticks = function(m) {\n      return d3_scale_linearTicks(domain, m);\n    };\n    scale.tickFormat = function(m) {\n      return d3_scale_linearTickFormat(domain, m);\n    };\n    scale.nice = function() {\n      d3_scale_nice(domain, d3_scale_linearNice);\n      return rescale();\n    };\n    scale.copy = function() {\n      return d3_scale_linear(domain, range, interpolate, clamp);\n    };\n    return rescale();\n  }\n  function d3_scale_linearRebind(scale, linear) {\n    return d3.rebind(scale, linear, \"range\", \"rangeRound\", \"interpolate\", \"clamp\");\n  }\n  function d3_scale_linearNice(dx) {\n    dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1);\n    return dx && {\n      floor: function(x) {\n        return Math.floor(x / dx) * dx;\n      },\n      ceil: function(x) {\n        return Math.ceil(x / dx) * dx;\n      }\n    };\n  }\n  function d3_scale_linearTickRange(domain, m) {\n    var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;\n    if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;\n    extent[0] = Math.ceil(extent[0] / step) * step;\n    extent[1] = Math.floor(extent[1] / step) * step + step * .5;\n    extent[2] = step;\n    return extent;\n  }\n  function d3_scale_linearTicks(domain, m) {\n    return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));\n  }\n  function d3_scale_linearTickFormat(domain, m) {\n    return d3.format(\",.\" + Math.max(0, -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01)) + \"f\");\n  }\n  function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {\n    var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);\n    return function(x) {\n      return i(u(x));\n    };\n  }\n  function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {\n    var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;\n    if (domain[k] < domain[0]) {\n      domain = domain.slice().reverse();\n      range = range.slice().reverse();\n    }\n    while (++j <= k) {\n      u.push(uninterpolate(domain[j - 1], domain[j]));\n      i.push(interpolate(range[j - 1], range[j]));\n    }\n    return function(x) {\n      var j = d3.bisect(domain, x, 1, k) - 1;\n      return i[j](u[j](x));\n    };\n  }\n  d3.scale.log = function() {\n    return d3_scale_log(d3.scale.linear(), d3_scale_logp);\n  };\n  function d3_scale_log(linear, log) {\n    var pow = log.pow;\n    function scale(x) {\n      return linear(log(x));\n    }\n    scale.invert = function(x) {\n      return pow(linear.invert(x));\n    };\n    scale.domain = function(x) {\n      if (!arguments.length) return linear.domain().map(pow);\n      log = x[0] < 0 ? d3_scale_logn : d3_scale_logp;\n      pow = log.pow;\n      linear.domain(x.map(log));\n      return scale;\n    };\n    scale.nice = function() {\n      linear.domain(d3_scale_nice(linear.domain(), d3_scale_niceDefault));\n      return scale;\n    };\n    scale.ticks = function() {\n      var extent = d3_scaleExtent(linear.domain()), ticks = [];\n      if (extent.every(isFinite)) {\n        var i = Math.floor(extent[0]), j = Math.ceil(extent[1]), u = pow(extent[0]), v = pow(extent[1]);\n        if (log === d3_scale_logn) {\n          ticks.push(pow(i));\n          for (; i++ < j; ) for (var k = 9; k > 0; k--) ticks.push(pow(i) * k);\n        } else {\n          for (; i < j; i++) for (var k = 1; k < 10; k++) ticks.push(pow(i) * k);\n          ticks.push(pow(i));\n        }\n        for (i = 0; ticks[i] < u; i++) {}\n        for (j = ticks.length; ticks[j - 1] > v; j--) {}\n        ticks = ticks.slice(i, j);\n      }\n      return ticks;\n    };\n    scale.tickFormat = function(n, format) {\n      if (arguments.length < 2) format = d3_scale_logFormat;\n      if (arguments.length < 1) return format;\n      var k = Math.max(.1, n / scale.ticks().length), f = log === d3_scale_logn ? (e = -1e-12, Math.floor) : (e = 1e-12, Math.ceil), e;\n      return function(d) {\n        return d / pow(f(log(d) + e)) <= k ? format(d) : \"\";\n      };\n    };\n    scale.copy = function() {\n      return d3_scale_log(linear.copy(), log);\n    };\n    return d3_scale_linearRebind(scale, linear);\n  }\n  var d3_scale_logFormat = d3.format(\".0e\");\n  function d3_scale_logp(x) {\n    return Math.log(x < 0 ? 0 : x) / Math.LN10;\n  }\n  function d3_scale_logn(x) {\n    return -Math.log(x > 0 ? 0 : -x) / Math.LN10;\n  }\n  d3_scale_logp.pow = function(x) {\n    return Math.pow(10, x);\n  };\n  d3_scale_logn.pow = function(x) {\n    return -Math.pow(10, -x);\n  };\n  d3.scale.pow = function() {\n    return d3_scale_pow(d3.scale.linear(), 1);\n  };\n  function d3_scale_pow(linear, exponent) {\n    var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);\n    function scale(x) {\n      return linear(powp(x));\n    }\n    scale.invert = function(x) {\n      return powb(linear.invert(x));\n    };\n    scale.domain = function(x) {\n      if (!arguments.length) return linear.domain().map(powb);\n      linear.domain(x.map(powp));\n      return scale;\n    };\n    scale.ticks = function(m) {\n      return d3_scale_linearTicks(scale.domain(), m);\n    };\n    scale.tickFormat = function(m) {\n      return d3_scale_linearTickFormat(scale.domain(), m);\n    };\n    scale.nice = function() {\n      return scale.domain(d3_scale_nice(scale.domain(), d3_scale_linearNice));\n    };\n    scale.exponent = function(x) {\n      if (!arguments.length) return exponent;\n      var domain = scale.domain();\n      powp = d3_scale_powPow(exponent = x);\n      powb = d3_scale_powPow(1 / exponent);\n      return scale.domain(domain);\n    };\n    scale.copy = function() {\n      return d3_scale_pow(linear.copy(), exponent);\n    };\n    return d3_scale_linearRebind(scale, linear);\n  }\n  function d3_scale_powPow(e) {\n    return function(x) {\n      return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);\n    };\n  }\n  d3.scale.sqrt = function() {\n    return d3.scale.pow().exponent(.5);\n  };\n  d3.scale.ordinal = function() {\n    return d3_scale_ordinal([], {\n      t: \"range\",\n      a: [ [] ]\n    });\n  };\n  function d3_scale_ordinal(domain, ranger) {\n    var index, range, rangeBand;\n    function scale(x) {\n      return range[((index.get(x) || index.set(x, domain.push(x))) - 1) % range.length];\n    }\n    function steps(start, step) {\n      return d3.range(domain.length).map(function(i) {\n        return start + step * i;\n      });\n    }\n    scale.domain = function(x) {\n      if (!arguments.length) return domain;\n      domain = [];\n      index = new d3_Map;\n      var i = -1, n = x.length, xi;\n      while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));\n      return scale[ranger.t].apply(scale, ranger.a);\n    };\n    scale.range = function(x) {\n      if (!arguments.length) return range;\n      range = x;\n      rangeBand = 0;\n      ranger = {\n        t: \"range\",\n        a: arguments\n      };\n      return scale;\n    };\n    scale.rangePoints = function(x, padding) {\n      if (arguments.length < 2) padding = 0;\n      var start = x[0], stop = x[1], step = (stop - start) / (domain.length - 1 + padding);\n      range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step);\n      rangeBand = 0;\n      ranger = {\n        t: \"rangePoints\",\n        a: arguments\n      };\n      return scale;\n    };\n    scale.rangeBands = function(x, padding, outerPadding) {\n      if (arguments.length < 2) padding = 0;\n      if (arguments.length < 3) outerPadding = padding;\n      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);\n      range = steps(start + step * outerPadding, step);\n      if (reverse) range.reverse();\n      rangeBand = step * (1 - padding);\n      ranger = {\n        t: \"rangeBands\",\n        a: arguments\n      };\n      return scale;\n    };\n    scale.rangeRoundBands = function(x, padding, outerPadding) {\n      if (arguments.length < 2) padding = 0;\n      if (arguments.length < 3) outerPadding = padding;\n      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step;\n      range = steps(start + Math.round(error / 2), step);\n      if (reverse) range.reverse();\n      rangeBand = Math.round(step * (1 - padding));\n      ranger = {\n        t: \"rangeRoundBands\",\n        a: arguments\n      };\n      return scale;\n    };\n    scale.rangeBand = function() {\n      return rangeBand;\n    };\n    scale.rangeExtent = function() {\n      return d3_scaleExtent(ranger.a[0]);\n    };\n    scale.copy = function() {\n      return d3_scale_ordinal(domain, ranger);\n    };\n    return scale.domain(domain);\n  }\n  d3.scale.category10 = function() {\n    return d3.scale.ordinal().range(d3_category10);\n  };\n  d3.scale.category20 = function() {\n    return d3.scale.ordinal().range(d3_category20);\n  };\n  d3.scale.category20b = function() {\n    return d3.scale.ordinal().range(d3_category20b);\n  };\n  d3.scale.category20c = function() {\n    return d3.scale.ordinal().range(d3_category20c);\n  };\n  var d3_category10 = [ \"#1f77b4\", \"#ff7f0e\", \"#2ca02c\", \"#d62728\", \"#9467bd\", \"#8c564b\", \"#e377c2\", \"#7f7f7f\", \"#bcbd22\", \"#17becf\" ];\n  var d3_category20 = [ \"#1f77b4\", \"#aec7e8\", \"#ff7f0e\", \"#ffbb78\", \"#2ca02c\", \"#98df8a\", \"#d62728\", \"#ff9896\", \"#9467bd\", \"#c5b0d5\", \"#8c564b\", \"#c49c94\", \"#e377c2\", \"#f7b6d2\", \"#7f7f7f\", \"#c7c7c7\", \"#bcbd22\", \"#dbdb8d\", \"#17becf\", \"#9edae5\" ];\n  var d3_category20b = [ \"#393b79\", \"#5254a3\", \"#6b6ecf\", \"#9c9ede\", \"#637939\", \"#8ca252\", \"#b5cf6b\", \"#cedb9c\", \"#8c6d31\", \"#bd9e39\", \"#e7ba52\", \"#e7cb94\", \"#843c39\", \"#ad494a\", \"#d6616b\", \"#e7969c\", \"#7b4173\", \"#a55194\", \"#ce6dbd\", \"#de9ed6\" ];\n  var d3_category20c = [ \"#3182bd\", \"#6baed6\", \"#9ecae1\", \"#c6dbef\", \"#e6550d\", \"#fd8d3c\", \"#fdae6b\", \"#fdd0a2\", \"#31a354\", \"#74c476\", \"#a1d99b\", \"#c7e9c0\", \"#756bb1\", \"#9e9ac8\", \"#bcbddc\", \"#dadaeb\", \"#636363\", \"#969696\", \"#bdbdbd\", \"#d9d9d9\" ];\n  d3.scale.quantile = function() {\n    return d3_scale_quantile([], []);\n  };\n  function d3_scale_quantile(domain, range) {\n    var thresholds;\n    function rescale() {\n      var k = 0, n = domain.length, q = range.length;\n      thresholds = [];\n      while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);\n      return scale;\n    }\n    function scale(x) {\n      if (isNaN(x = +x)) return NaN;\n      return range[d3.bisect(thresholds, x)];\n    }\n    scale.domain = function(x) {\n      if (!arguments.length) return domain;\n      domain = x.filter(function(d) {\n        return !isNaN(d);\n      }).sort(d3.ascending);\n      return rescale();\n    };\n    scale.range = function(x) {\n      if (!arguments.length) return range;\n      range = x;\n      return rescale();\n    };\n    scale.quantiles = function() {\n      return thresholds;\n    };\n    scale.copy = function() {\n      return d3_scale_quantile(domain, range);\n    };\n    return rescale();\n  }\n  d3.scale.quantize = function() {\n    return d3_scale_quantize(0, 1, [ 0, 1 ]);\n  };\n  function d3_scale_quantize(x0, x1, range) {\n    var kx, i;\n    function scale(x) {\n      return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];\n    }\n    function rescale() {\n      kx = range.length / (x1 - x0);\n      i = range.length - 1;\n      return scale;\n    }\n    scale.domain = function(x) {\n      if (!arguments.length) return [ x0, x1 ];\n      x0 = +x[0];\n      x1 = +x[x.length - 1];\n      return rescale();\n    };\n    scale.range = function(x) {\n      if (!arguments.length) return range;\n      range = x;\n      return rescale();\n    };\n    scale.copy = function() {\n      return d3_scale_quantize(x0, x1, range);\n    };\n    return rescale();\n  }\n  d3.scale.threshold = function() {\n    return d3_scale_threshold([ .5 ], [ 0, 1 ]);\n  };\n  function d3_scale_threshold(domain, range) {\n    function scale(x) {\n      return range[d3.bisect(domain, x)];\n    }\n    scale.domain = function(_) {\n      if (!arguments.length) return domain;\n      domain = _;\n      return scale;\n    };\n    scale.range = function(_) {\n      if (!arguments.length) return range;\n      range = _;\n      return scale;\n    };\n    scale.copy = function() {\n      return d3_scale_threshold(domain, range);\n    };\n    return scale;\n  }\n  d3.scale.identity = function() {\n    return d3_scale_identity([ 0, 1 ]);\n  };\n  function d3_scale_identity(domain) {\n    function identity(x) {\n      return +x;\n    }\n    identity.invert = identity;\n    identity.domain = identity.range = function(x) {\n      if (!arguments.length) return domain;\n      domain = x.map(identity);\n      return identity;\n    };\n    identity.ticks = function(m) {\n      return d3_scale_linearTicks(domain, m);\n    };\n    identity.tickFormat = function(m) {\n      return d3_scale_linearTickFormat(domain, m);\n    };\n    identity.copy = function() {\n      return d3_scale_identity(domain);\n    };\n    return identity;\n  }\n  d3.svg = {};\n  d3.svg.arc = function() {\n    var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;\n    function arc() {\n      var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0, a0 = a1, a1 = da), a1 - a0), df = da < Math.PI ? \"0\" : \"1\", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1);\n      return da >= d3_svg_arcMax ? r0 ? \"M0,\" + r1 + \"A\" + r1 + \",\" + r1 + \" 0 1,1 0,\" + -r1 + \"A\" + r1 + \",\" + r1 + \" 0 1,1 0,\" + r1 + \"M0,\" + r0 + \"A\" + r0 + \",\" + r0 + \" 0 1,0 0,\" + -r0 + \"A\" + r0 + \",\" + r0 + \" 0 1,0 0,\" + r0 + \"Z\" : \"M0,\" + r1 + \"A\" + r1 + \",\" + r1 + \" 0 1,1 0,\" + -r1 + \"A\" + r1 + \",\" + r1 + \" 0 1,1 0,\" + r1 + \"Z\" : r0 ? \"M\" + r1 * c0 + \",\" + r1 * s0 + \"A\" + r1 + \",\" + r1 + \" 0 \" + df + \",1 \" + r1 * c1 + \",\" + r1 * s1 + \"L\" + r0 * c1 + \",\" + r0 * s1 + \"A\" + r0 + \",\" + r0 + \" 0 \" + df + \",0 \" + r0 * c0 + \",\" + r0 * s0 + \"Z\" : \"M\" + r1 * c0 + \",\" + r1 * s0 + \"A\" + r1 + \",\" + r1 + \" 0 \" + df + \",1 \" + r1 * c1 + \",\" + r1 * s1 + \"L0,0\" + \"Z\";\n    }\n    arc.innerRadius = function(v) {\n      if (!arguments.length) return innerRadius;\n      innerRadius = d3_functor(v);\n      return arc;\n    };\n    arc.outerRadius = function(v) {\n      if (!arguments.length) return outerRadius;\n      outerRadius = d3_functor(v);\n      return arc;\n    };\n    arc.startAngle = function(v) {\n      if (!arguments.length) return startAngle;\n      startAngle = d3_functor(v);\n      return arc;\n    };\n    arc.endAngle = function(v) {\n      if (!arguments.length) return endAngle;\n      endAngle = d3_functor(v);\n      return arc;\n    };\n    arc.centroid = function() {\n      var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;\n      return [ Math.cos(a) * r, Math.sin(a) * r ];\n    };\n    return arc;\n  };\n  var d3_svg_arcOffset = -Math.PI / 2, d3_svg_arcMax = 2 * Math.PI - 1e-6;\n  function d3_svg_arcInnerRadius(d) {\n    return d.innerRadius;\n  }\n  function d3_svg_arcOuterRadius(d) {\n    return d.outerRadius;\n  }\n  function d3_svg_arcStartAngle(d) {\n    return d.startAngle;\n  }\n  function d3_svg_arcEndAngle(d) {\n    return d.endAngle;\n  }\n  function d3_svg_line(projection) {\n    var x = d3_svg_lineX, y = d3_svg_lineY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;\n    function line(data) {\n      var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);\n      function segment() {\n        segments.push(\"M\", interpolate(projection(points), tension));\n      }\n      while (++i < n) {\n        if (defined.call(this, d = data[i], i)) {\n          points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);\n        } else if (points.length) {\n          segment();\n          points = [];\n        }\n      }\n      if (points.length) segment();\n      return segments.length ? segments.join(\"\") : null;\n    }\n    line.x = function(_) {\n      if (!arguments.length) return x;\n      x = _;\n      return line;\n    };\n    line.y = function(_) {\n      if (!arguments.length) return y;\n      y = _;\n      return line;\n    };\n    line.defined = function(_) {\n      if (!arguments.length) return defined;\n      defined = _;\n      return line;\n    };\n    line.interpolate = function(_) {\n      if (!arguments.length) return interpolateKey;\n      if (typeof _ === \"function\") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;\n      return line;\n    };\n    line.tension = function(_) {\n      if (!arguments.length) return tension;\n      tension = _;\n      return line;\n    };\n    return line;\n  }\n  d3.svg.line = function() {\n    return d3_svg_line(d3_identity);\n  };\n  function d3_svg_lineX(d) {\n    return d[0];\n  }\n  function d3_svg_lineY(d) {\n    return d[1];\n  }\n  var d3_svg_lineInterpolators = d3.map({\n    linear: d3_svg_lineLinear,\n    \"linear-closed\": d3_svg_lineLinearClosed,\n    \"step-before\": d3_svg_lineStepBefore,\n    \"step-after\": d3_svg_lineStepAfter,\n    basis: d3_svg_lineBasis,\n    \"basis-open\": d3_svg_lineBasisOpen,\n    \"basis-closed\": d3_svg_lineBasisClosed,\n    bundle: d3_svg_lineBundle,\n    cardinal: d3_svg_lineCardinal,\n    \"cardinal-open\": d3_svg_lineCardinalOpen,\n    \"cardinal-closed\": d3_svg_lineCardinalClosed,\n    monotone: d3_svg_lineMonotone\n  });\n  d3_svg_lineInterpolators.forEach(function(key, value) {\n    value.key = key;\n    value.closed = /-closed$/.test(key);\n  });\n  function d3_svg_lineLinear(points) {\n    return points.join(\"L\");\n  }\n  function d3_svg_lineLinearClosed(points) {\n    return d3_svg_lineLinear(points) + \"Z\";\n  }\n  function d3_svg_lineStepBefore(points) {\n    var i = 0, n = points.length, p = points[0], path = [ p[0], \",\", p[1] ];\n    while (++i < n) path.push(\"V\", (p = points[i])[1], \"H\", p[0]);\n    return path.join(\"\");\n  }\n  function d3_svg_lineStepAfter(points) {\n    var i = 0, n = points.length, p = points[0], path = [ p[0], \",\", p[1] ];\n    while (++i < n) path.push(\"H\", (p = points[i])[0], \"V\", p[1]);\n    return path.join(\"\");\n  }\n  function d3_svg_lineCardinalOpen(points, tension) {\n    return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension));\n  }\n  function d3_svg_lineCardinalClosed(points, tension) {\n    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));\n  }\n  function d3_svg_lineCardinal(points, tension, closed) {\n    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));\n  }\n  function d3_svg_lineHermite(points, tangents) {\n    if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {\n      return d3_svg_lineLinear(points);\n    }\n    var quad = points.length != tangents.length, path = \"\", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;\n    if (quad) {\n      path += \"Q\" + (p[0] - t0[0] * 2 / 3) + \",\" + (p[1] - t0[1] * 2 / 3) + \",\" + p[0] + \",\" + p[1];\n      p0 = points[1];\n      pi = 2;\n    }\n    if (tangents.length > 1) {\n      t = tangents[1];\n      p = points[pi];\n      pi++;\n      path += \"C\" + (p0[0] + t0[0]) + \",\" + (p0[1] + t0[1]) + \",\" + (p[0] - t[0]) + \",\" + (p[1] - t[1]) + \",\" + p[0] + \",\" + p[1];\n      for (var i = 2; i < tangents.length; i++, pi++) {\n        p = points[pi];\n        t = tangents[i];\n        path += \"S\" + (p[0] - t[0]) + \",\" + (p[1] - t[1]) + \",\" + p[0] + \",\" + p[1];\n      }\n    }\n    if (quad) {\n      var lp = points[pi];\n      path += \"Q\" + (p[0] + t[0] * 2 / 3) + \",\" + (p[1] + t[1] * 2 / 3) + \",\" + lp[0] + \",\" + lp[1];\n    }\n    return path;\n  }\n  function d3_svg_lineCardinalTangents(points, tension) {\n    var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;\n    while (++i < n) {\n      p0 = p1;\n      p1 = p2;\n      p2 = points[i];\n      tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);\n    }\n    return tangents;\n  }\n  function d3_svg_lineBasis(points) {\n    if (points.length < 3) return d3_svg_lineLinear(points);\n    var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, \",\", y0 ];\n    d3_svg_lineBasisBezier(path, px, py);\n    while (++i < n) {\n      pi = points[i];\n      px.shift();\n      px.push(pi[0]);\n      py.shift();\n      py.push(pi[1]);\n      d3_svg_lineBasisBezier(path, px, py);\n    }\n    i = -1;\n    while (++i < 2) {\n      px.shift();\n      px.push(pi[0]);\n      py.shift();\n      py.push(pi[1]);\n      d3_svg_lineBasisBezier(path, px, py);\n    }\n    return path.join(\"\");\n  }\n  function d3_svg_lineBasisOpen(points) {\n    if (points.length < 4) return d3_svg_lineLinear(points);\n    var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];\n    while (++i < 3) {\n      pi = points[i];\n      px.push(pi[0]);\n      py.push(pi[1]);\n    }\n    path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + \",\" + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));\n    --i;\n    while (++i < n) {\n      pi = points[i];\n      px.shift();\n      px.push(pi[0]);\n      py.shift();\n      py.push(pi[1]);\n      d3_svg_lineBasisBezier(path, px, py);\n    }\n    return path.join(\"\");\n  }\n  function d3_svg_lineBasisClosed(points) {\n    var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];\n    while (++i < 4) {\n      pi = points[i % n];\n      px.push(pi[0]);\n      py.push(pi[1]);\n    }\n    path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];\n    --i;\n    while (++i < m) {\n      pi = points[i % n];\n      px.shift();\n      px.push(pi[0]);\n      py.shift();\n      py.push(pi[1]);\n      d3_svg_lineBasisBezier(path, px, py);\n    }\n    return path.join(\"\");\n  }\n  function d3_svg_lineBundle(points, tension) {\n    var n = points.length - 1;\n    if (n) {\n      var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;\n      while (++i <= n) {\n        p = points[i];\n        t = i / n;\n        p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);\n        p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);\n      }\n    }\n    return d3_svg_lineBasis(points);\n  }\n  function d3_svg_lineDot4(a, b) {\n    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];\n  }\n  var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];\n  function d3_svg_lineBasisBezier(path, x, y) {\n    path.push(\"C\", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));\n  }\n  function d3_svg_lineSlope(p0, p1) {\n    return (p1[1] - p0[1]) / (p1[0] - p0[0]);\n  }\n  function d3_svg_lineFiniteDifferences(points) {\n    var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);\n    while (++i < j) {\n      m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;\n    }\n    m[i] = d;\n    return m;\n  }\n  function d3_svg_lineMonotoneTangents(points) {\n    var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;\n    while (++i < j) {\n      d = d3_svg_lineSlope(points[i], points[i + 1]);\n      if (Math.abs(d) < 1e-6) {\n        m[i] = m[i + 1] = 0;\n      } else {\n        a = m[i] / d;\n        b = m[i + 1] / d;\n        s = a * a + b * b;\n        if (s > 9) {\n          s = d * 3 / Math.sqrt(s);\n          m[i] = s * a;\n          m[i + 1] = s * b;\n        }\n      }\n    }\n    i = -1;\n    while (++i <= j) {\n      s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));\n      tangents.push([ s || 0, m[i] * s || 0 ]);\n    }\n    return tangents;\n  }\n  function d3_svg_lineMonotone(points) {\n    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));\n  }\n  d3.svg.line.radial = function() {\n    var line = d3_svg_line(d3_svg_lineRadial);\n    line.radius = line.x, delete line.x;\n    line.angle = line.y, delete line.y;\n    return line;\n  };\n  function d3_svg_lineRadial(points) {\n    var point, i = -1, n = points.length, r, a;\n    while (++i < n) {\n      point = points[i];\n      r = point[0];\n      a = point[1] + d3_svg_arcOffset;\n      point[0] = r * Math.cos(a);\n      point[1] = r * Math.sin(a);\n    }\n    return points;\n  }\n  function d3_svg_area(projection) {\n    var x0 = d3_svg_lineX, x1 = d3_svg_lineX, y0 = 0, y1 = d3_svg_lineY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = \"L\", tension = .7;\n    function area(data) {\n      var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {\n        return x;\n      } : d3_functor(x1), fy1 = y0 === y1 ? function() {\n        return y;\n      } : d3_functor(y1), x, y;\n      function segment() {\n        segments.push(\"M\", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), \"Z\");\n      }\n      while (++i < n) {\n        if (defined.call(this, d = data[i], i)) {\n          points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);\n          points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);\n        } else if (points0.length) {\n          segment();\n          points0 = [];\n          points1 = [];\n        }\n      }\n      if (points0.length) segment();\n      return segments.length ? segments.join(\"\") : null;\n    }\n    area.x = function(_) {\n      if (!arguments.length) return x1;\n      x0 = x1 = _;\n      return area;\n    };\n    area.x0 = function(_) {\n      if (!arguments.length) return x0;\n      x0 = _;\n      return area;\n    };\n    area.x1 = function(_) {\n      if (!arguments.length) return x1;\n      x1 = _;\n      return area;\n    };\n    area.y = function(_) {\n      if (!arguments.length) return y1;\n      y0 = y1 = _;\n      return area;\n    };\n    area.y0 = function(_) {\n      if (!arguments.length) return y0;\n      y0 = _;\n      return area;\n    };\n    area.y1 = function(_) {\n      if (!arguments.length) return y1;\n      y1 = _;\n      return area;\n    };\n    area.defined = function(_) {\n      if (!arguments.length) return defined;\n      defined = _;\n      return area;\n    };\n    area.interpolate = function(_) {\n      if (!arguments.length) return interpolateKey;\n      if (typeof _ === \"function\") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;\n      interpolateReverse = interpolate.reverse || interpolate;\n      L = interpolate.closed ? \"M\" : \"L\";\n      return area;\n    };\n    area.tension = function(_) {\n      if (!arguments.length) return tension;\n      tension = _;\n      return area;\n    };\n    return area;\n  }\n  d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;\n  d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;\n  d3.svg.area = function() {\n    return d3_svg_area(d3_identity);\n  };\n  d3.svg.area.radial = function() {\n    var area = d3_svg_area(d3_svg_lineRadial);\n    area.radius = area.x, delete area.x;\n    area.innerRadius = area.x0, delete area.x0;\n    area.outerRadius = area.x1, delete area.x1;\n    area.angle = area.y, delete area.y;\n    area.startAngle = area.y0, delete area.y0;\n    area.endAngle = area.y1, delete area.y1;\n    return area;\n  };\n  d3.svg.chord = function() {\n    var source = d3_svg_chordSource, target = d3_svg_chordTarget, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;\n    function chord(d, i) {\n      var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);\n      return \"M\" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + \"Z\";\n    }\n    function subgroup(self, f, d, i) {\n      var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;\n      return {\n        r: r,\n        a0: a0,\n        a1: a1,\n        p0: [ r * Math.cos(a0), r * Math.sin(a0) ],\n        p1: [ r * Math.cos(a1), r * Math.sin(a1) ]\n      };\n    }\n    function equals(a, b) {\n      return a.a0 == b.a0 && a.a1 == b.a1;\n    }\n    function arc(r, p, a) {\n      return \"A\" + r + \",\" + r + \" 0 \" + +(a > Math.PI) + \",1 \" + p;\n    }\n    function curve(r0, p0, r1, p1) {\n      return \"Q 0,0 \" + p1;\n    }\n    chord.radius = function(v) {\n      if (!arguments.length) return radius;\n      radius = d3_functor(v);\n      return chord;\n    };\n    chord.source = function(v) {\n      if (!arguments.length) return source;\n      source = d3_functor(v);\n      return chord;\n    };\n    chord.target = function(v) {\n      if (!arguments.length) return target;\n      target = d3_functor(v);\n      return chord;\n    };\n    chord.startAngle = function(v) {\n      if (!arguments.length) return startAngle;\n      startAngle = d3_functor(v);\n      return chord;\n    };\n    chord.endAngle = function(v) {\n      if (!arguments.length) return endAngle;\n      endAngle = d3_functor(v);\n      return chord;\n    };\n    return chord;\n  };\n  function d3_svg_chordSource(d) {\n    return d.source;\n  }\n  function d3_svg_chordTarget(d) {\n    return d.target;\n  }\n  function d3_svg_chordRadius(d) {\n    return d.radius;\n  }\n  function d3_svg_chordStartAngle(d) {\n    return d.startAngle;\n  }\n  function d3_svg_chordEndAngle(d) {\n    return d.endAngle;\n  }\n  d3.svg.diagonal = function() {\n    var source = d3_svg_chordSource, target = d3_svg_chordTarget, projection = d3_svg_diagonalProjection;\n    function diagonal(d, i) {\n      var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {\n        x: p0.x,\n        y: m\n      }, {\n        x: p3.x,\n        y: m\n      }, p3 ];\n      p = p.map(projection);\n      return \"M\" + p[0] + \"C\" + p[1] + \" \" + p[2] + \" \" + p[3];\n    }\n    diagonal.source = function(x) {\n      if (!arguments.length) return source;\n      source = d3_functor(x);\n      return diagonal;\n    };\n    diagonal.target = function(x) {\n      if (!arguments.length) return target;\n      target = d3_functor(x);\n      return diagonal;\n    };\n    diagonal.projection = function(x) {\n      if (!arguments.length) return projection;\n      projection = x;\n      return diagonal;\n    };\n    return diagonal;\n  };\n  function d3_svg_diagonalProjection(d) {\n    return [ d.x, d.y ];\n  }\n  d3.svg.diagonal.radial = function() {\n    var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;\n    diagonal.projection = function(x) {\n      return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;\n    };\n    return diagonal;\n  };\n  function d3_svg_diagonalRadialProjection(projection) {\n    return function() {\n      var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset;\n      return [ r * Math.cos(a), r * Math.sin(a) ];\n    };\n  }\n  d3.svg.mouse = d3.mouse;\n  d3.svg.touches = d3.touches;\n  d3.svg.symbol = function() {\n    var type = d3_svg_symbolType, size = d3_svg_symbolSize;\n    function symbol(d, i) {\n      return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));\n    }\n    symbol.type = function(x) {\n      if (!arguments.length) return type;\n      type = d3_functor(x);\n      return symbol;\n    };\n    symbol.size = function(x) {\n      if (!arguments.length) return size;\n      size = d3_functor(x);\n      return symbol;\n    };\n    return symbol;\n  };\n  function d3_svg_symbolSize() {\n    return 64;\n  }\n  function d3_svg_symbolType() {\n    return \"circle\";\n  }\n  function d3_svg_symbolCircle(size) {\n    var r = Math.sqrt(size / Math.PI);\n    return \"M0,\" + r + \"A\" + r + \",\" + r + \" 0 1,1 0,\" + -r + \"A\" + r + \",\" + r + \" 0 1,1 0,\" + r + \"Z\";\n  }\n  var d3_svg_symbols = d3.map({\n    circle: d3_svg_symbolCircle,\n    cross: function(size) {\n      var r = Math.sqrt(size / 5) / 2;\n      return \"M\" + -3 * r + \",\" + -r + \"H\" + -r + \"V\" + -3 * r + \"H\" + r + \"V\" + -r + \"H\" + 3 * r + \"V\" + r + \"H\" + r + \"V\" + 3 * r + \"H\" + -r + \"V\" + r + \"H\" + -3 * r + \"Z\";\n    },\n    diamond: function(size) {\n      var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;\n      return \"M0,\" + -ry + \"L\" + rx + \",0\" + \" 0,\" + ry + \" \" + -rx + \",0\" + \"Z\";\n    },\n    square: function(size) {\n      var r = Math.sqrt(size) / 2;\n      return \"M\" + -r + \",\" + -r + \"L\" + r + \",\" + -r + \" \" + r + \",\" + r + \" \" + -r + \",\" + r + \"Z\";\n    },\n    \"triangle-down\": function(size) {\n      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;\n      return \"M0,\" + ry + \"L\" + rx + \",\" + -ry + \" \" + -rx + \",\" + -ry + \"Z\";\n    },\n    \"triangle-up\": function(size) {\n      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;\n      return \"M0,\" + -ry + \"L\" + rx + \",\" + ry + \" \" + -rx + \",\" + ry + \"Z\";\n    }\n  });\n  d3.svg.symbolTypes = d3_svg_symbols.keys();\n  var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * Math.PI / 180);\n  d3.svg.axis = function() {\n    var scale = d3.scale.linear(), orient = \"bottom\", tickMajorSize = 6, tickMinorSize = 6, tickEndSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_, tickSubdivide = 0;\n    function axis(g) {\n      g.each(function() {\n        var g = d3.select(this);\n        var ticks = tickValues == null ? scale.ticks ? scale.ticks.apply(scale, tickArguments_) : scale.domain() : tickValues, tickFormat = tickFormat_ == null ? scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments_) : String : tickFormat_;\n        var subticks = d3_svg_axisSubdivide(scale, ticks, tickSubdivide), subtick = g.selectAll(\".minor\").data(subticks, String), subtickEnter = subtick.enter().insert(\"line\", \"g\").attr(\"class\", \"tick minor\").style(\"opacity\", 1e-6), subtickExit = d3.transition(subtick.exit()).style(\"opacity\", 1e-6).remove(), subtickUpdate = d3.transition(subtick).style(\"opacity\", 1);\n        var tick = g.selectAll(\"g\").data(ticks, String), tickEnter = tick.enter().insert(\"g\", \"path\").style(\"opacity\", 1e-6), tickExit = d3.transition(tick.exit()).style(\"opacity\", 1e-6).remove(), tickUpdate = d3.transition(tick).style(\"opacity\", 1), tickTransform;\n        var range = d3_scaleRange(scale), path = g.selectAll(\".domain\").data([ 0 ]), pathEnter = path.enter().append(\"path\").attr(\"class\", \"domain\"), pathUpdate = d3.transition(path);\n        var scale1 = scale.copy(), scale0 = this.__chart__ || scale1;\n        this.__chart__ = scale1;\n        tickEnter.append(\"line\").attr(\"class\", \"tick\");\n        tickEnter.append(\"text\");\n        var lineEnter = tickEnter.select(\"line\"), lineUpdate = tickUpdate.select(\"line\"), text = tick.select(\"text\").text(tickFormat), textEnter = tickEnter.select(\"text\"), textUpdate = tickUpdate.select(\"text\");\n        switch (orient) {\n         case \"bottom\":\n          {\n            tickTransform = d3_svg_axisX;\n            subtickEnter.attr(\"y2\", tickMinorSize);\n            subtickUpdate.attr(\"x2\", 0).attr(\"y2\", tickMinorSize);\n            lineEnter.attr(\"y2\", tickMajorSize);\n            textEnter.attr(\"y\", Math.max(tickMajorSize, 0) + tickPadding);\n            lineUpdate.attr(\"x2\", 0).attr(\"y2\", tickMajorSize);\n            textUpdate.attr(\"x\", 0).attr(\"y\", Math.max(tickMajorSize, 0) + tickPadding);\n            text.attr(\"dy\", \".71em\").attr(\"text-anchor\", \"middle\");\n            pathUpdate.attr(\"d\", \"M\" + range[0] + \",\" + tickEndSize + \"V0H\" + range[1] + \"V\" + tickEndSize);\n            break;\n          }\n         case \"top\":\n          {\n            tickTransform = d3_svg_axisX;\n            subtickEnter.attr(\"y2\", -tickMinorSize);\n            subtickUpdate.attr(\"x2\", 0).attr(\"y2\", -tickMinorSize);\n            lineEnter.attr(\"y2\", -tickMajorSize);\n            textEnter.attr(\"y\", -(Math.max(tickMajorSize, 0) + tickPadding));\n            lineUpdate.attr(\"x2\", 0).attr(\"y2\", -tickMajorSize);\n            textUpdate.attr(\"x\", 0).attr(\"y\", -(Math.max(tickMajorSize, 0) + tickPadding));\n            text.attr(\"dy\", \"0em\").attr(\"text-anchor\", \"middle\");\n            pathUpdate.attr(\"d\", \"M\" + range[0] + \",\" + -tickEndSize + \"V0H\" + range[1] + \"V\" + -tickEndSize);\n            break;\n          }\n         case \"left\":\n          {\n            tickTransform = d3_svg_axisY;\n            subtickEnter.attr(\"x2\", -tickMinorSize);\n            subtickUpdate.attr(\"x2\", -tickMinorSize).attr(\"y2\", 0);\n            lineEnter.attr(\"x2\", -tickMajorSize);\n            textEnter.attr(\"x\", -(Math.max(tickMajorSize, 0) + tickPadding));\n            lineUpdate.attr(\"x2\", -tickMajorSize).attr(\"y2\", 0);\n            textUpdate.attr(\"x\", -(Math.max(tickMajorSize, 0) + tickPadding)).attr(\"y\", 0);\n            text.attr(\"dy\", \".32em\").attr(\"text-anchor\", \"end\");\n            pathUpdate.attr(\"d\", \"M\" + -tickEndSize + \",\" + range[0] + \"H0V\" + range[1] + \"H\" + -tickEndSize);\n            break;\n          }\n         case \"right\":\n          {\n            tickTransform = d3_svg_axisY;\n            subtickEnter.attr(\"x2\", tickMinorSize);\n            subtickUpdate.attr(\"x2\", tickMinorSize).attr(\"y2\", 0);\n            lineEnter.attr(\"x2\", tickMajorSize);\n            textEnter.attr(\"x\", Math.max(tickMajorSize, 0) + tickPadding);\n            lineUpdate.attr(\"x2\", tickMajorSize).attr(\"y2\", 0);\n            textUpdate.attr(\"x\", Math.max(tickMajorSize, 0) + tickPadding).attr(\"y\", 0);\n            text.attr(\"dy\", \".32em\").attr(\"text-anchor\", \"start\");\n            pathUpdate.attr(\"d\", \"M\" + tickEndSize + \",\" + range[0] + \"H0V\" + range[1] + \"H\" + tickEndSize);\n            break;\n          }\n        }\n        if (scale.ticks) {\n          tickEnter.call(tickTransform, scale0);\n          tickUpdate.call(tickTransform, scale1);\n          tickExit.call(tickTransform, scale1);\n          subtickEnter.call(tickTransform, scale0);\n          subtickUpdate.call(tickTransform, scale1);\n          subtickExit.call(tickTransform, scale1);\n        } else {\n          var dx = scale1.rangeBand() / 2, x = function(d) {\n            return scale1(d) + dx;\n          };\n          tickEnter.call(tickTransform, x);\n          tickUpdate.call(tickTransform, x);\n        }\n      });\n    }\n    axis.scale = function(x) {\n      if (!arguments.length) return scale;\n      scale = x;\n      return axis;\n    };\n    axis.orient = function(x) {\n      if (!arguments.length) return orient;\n      orient = x;\n      return axis;\n    };\n    axis.ticks = function() {\n      if (!arguments.length) return tickArguments_;\n      tickArguments_ = arguments;\n      return axis;\n    };\n    axis.tickValues = function(x) {\n      if (!arguments.length) return tickValues;\n      tickValues = x;\n      return axis;\n    };\n    axis.tickFormat = function(x) {\n      if (!arguments.length) return tickFormat_;\n      tickFormat_ = x;\n      return axis;\n    };\n    axis.tickSize = function(x, y, z) {\n      if (!arguments.length) return tickMajorSize;\n      var n = arguments.length - 1;\n      tickMajorSize = +x;\n      tickMinorSize = n > 1 ? +y : tickMajorSize;\n      tickEndSize = n > 0 ? +arguments[n] : tickMajorSize;\n      return axis;\n    };\n    axis.tickPadding = function(x) {\n      if (!arguments.length) return tickPadding;\n      tickPadding = +x;\n      return axis;\n    };\n    axis.tickSubdivide = function(x) {\n      if (!arguments.length) return tickSubdivide;\n      tickSubdivide = +x;\n      return axis;\n    };\n    return axis;\n  };\n  function d3_svg_axisX(selection, x) {\n    selection.attr(\"transform\", function(d) {\n      return \"translate(\" + x(d) + \",0)\";\n    });\n  }\n  function d3_svg_axisY(selection, y) {\n    selection.attr(\"transform\", function(d) {\n      return \"translate(0,\" + y(d) + \")\";\n    });\n  }\n  function d3_svg_axisSubdivide(scale, ticks, m) {\n    subticks = [];\n    if (m && ticks.length > 1) {\n      var extent = d3_scaleExtent(scale.domain()), subticks, i = -1, n = ticks.length, d = (ticks[1] - ticks[0]) / ++m, j, v;\n      while (++i < n) {\n        for (j = m; --j > 0; ) {\n          if ((v = +ticks[i] - j * d) >= extent[0]) {\n            subticks.push(v);\n          }\n        }\n      }\n      for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1]; ) {\n        subticks.push(v);\n      }\n    }\n    return subticks;\n  }\n  d3.svg.brush = function() {\n    var event = d3_eventDispatch(brush, \"brushstart\", \"brush\", \"brushend\"), x = null, y = null, resizes = d3_svg_brushResizes[0], extent = [ [ 0, 0 ], [ 0, 0 ] ], extentDomain;\n    function brush(g) {\n      g.each(function() {\n        var g = d3.select(this), bg = g.selectAll(\".background\").data([ 0 ]), fg = g.selectAll(\".extent\").data([ 0 ]), tz = g.selectAll(\".resize\").data(resizes, String), e;\n        g.style(\"pointer-events\", \"all\").on(\"mousedown.brush\", brushstart).on(\"touchstart.brush\", brushstart);\n        bg.enter().append(\"rect\").attr(\"class\", \"background\").style(\"visibility\", \"hidden\").style(\"cursor\", \"crosshair\");\n        fg.enter().append(\"rect\").attr(\"class\", \"extent\").style(\"cursor\", \"move\");\n        tz.enter().append(\"g\").attr(\"class\", function(d) {\n          return \"resize \" + d;\n        }).style(\"cursor\", function(d) {\n          return d3_svg_brushCursor[d];\n        }).append(\"rect\").attr(\"x\", function(d) {\n          return /[ew]$/.test(d) ? -3 : null;\n        }).attr(\"y\", function(d) {\n          return /^[ns]/.test(d) ? -3 : null;\n        }).attr(\"width\", 6).attr(\"height\", 6).style(\"visibility\", \"hidden\");\n        tz.style(\"display\", brush.empty() ? \"none\" : null);\n        tz.exit().remove();\n        if (x) {\n          e = d3_scaleRange(x);\n          bg.attr(\"x\", e[0]).attr(\"width\", e[1] - e[0]);\n          redrawX(g);\n        }\n        if (y) {\n          e = d3_scaleRange(y);\n          bg.attr(\"y\", e[0]).attr(\"height\", e[1] - e[0]);\n          redrawY(g);\n        }\n        redraw(g);\n      });\n    }\n    function redraw(g) {\n      g.selectAll(\".resize\").attr(\"transform\", function(d) {\n        return \"translate(\" + extent[+/e$/.test(d)][0] + \",\" + extent[+/^s/.test(d)][1] + \")\";\n      });\n    }\n    function redrawX(g) {\n      g.select(\".extent\").attr(\"x\", extent[0][0]);\n      g.selectAll(\".extent,.n>rect,.s>rect\").attr(\"width\", extent[1][0] - extent[0][0]);\n    }\n    function redrawY(g) {\n      g.select(\".extent\").attr(\"y\", extent[0][1]);\n      g.selectAll(\".extent,.e>rect,.w>rect\").attr(\"height\", extent[1][1] - extent[0][1]);\n    }\n    function brushstart() {\n      var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed(\"extent\"), center, origin = mouse(), offset;\n      var w = d3.select(window).on(\"mousemove.brush\", brushmove).on(\"mouseup.brush\", brushend).on(\"touchmove.brush\", brushmove).on(\"touchend.brush\", brushend).on(\"keydown.brush\", keydown).on(\"keyup.brush\", keyup);\n      if (dragging) {\n        origin[0] = extent[0][0] - origin[0];\n        origin[1] = extent[0][1] - origin[1];\n      } else if (resizing) {\n        var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);\n        offset = [ extent[1 - ex][0] - origin[0], extent[1 - ey][1] - origin[1] ];\n        origin[0] = extent[ex][0];\n        origin[1] = extent[ey][1];\n      } else if (d3.event.altKey) center = origin.slice();\n      g.style(\"pointer-events\", \"none\").selectAll(\".resize\").style(\"display\", null);\n      d3.select(\"body\").style(\"cursor\", eventTarget.style(\"cursor\"));\n      event_({\n        type: \"brushstart\"\n      });\n      brushmove();\n      d3_eventCancel();\n      function mouse() {\n        var touches = d3.event.changedTouches;\n        return touches ? d3.touches(target, touches)[0] : d3.mouse(target);\n      }\n      function keydown() {\n        if (d3.event.keyCode == 32) {\n          if (!dragging) {\n            center = null;\n            origin[0] -= extent[1][0];\n            origin[1] -= extent[1][1];\n            dragging = 2;\n          }\n          d3_eventCancel();\n        }\n      }\n      function keyup() {\n        if (d3.event.keyCode == 32 && dragging == 2) {\n          origin[0] += extent[1][0];\n          origin[1] += extent[1][1];\n          dragging = 0;\n          d3_eventCancel();\n        }\n      }\n      function brushmove() {\n        var point = mouse(), moved = false;\n        if (offset) {\n          point[0] += offset[0];\n          point[1] += offset[1];\n        }\n        if (!dragging) {\n          if (d3.event.altKey) {\n            if (!center) center = [ (extent[0][0] + extent[1][0]) / 2, (extent[0][1] + extent[1][1]) / 2 ];\n            origin[0] = extent[+(point[0] < center[0])][0];\n            origin[1] = extent[+(point[1] < center[1])][1];\n          } else center = null;\n        }\n        if (resizingX && move1(point, x, 0)) {\n          redrawX(g);\n          moved = true;\n        }\n        if (resizingY && move1(point, y, 1)) {\n          redrawY(g);\n          moved = true;\n        }\n        if (moved) {\n          redraw(g);\n          event_({\n            type: \"brush\",\n            mode: dragging ? \"move\" : \"resize\"\n          });\n        }\n      }\n      function move1(point, scale, i) {\n        var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], size = extent[1][i] - extent[0][i], min, max;\n        if (dragging) {\n          r0 -= position;\n          r1 -= size + position;\n        }\n        min = Math.max(r0, Math.min(r1, point[i]));\n        if (dragging) {\n          max = (min += position) + size;\n        } else {\n          if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));\n          if (position < min) {\n            max = min;\n            min = position;\n          } else {\n            max = position;\n          }\n        }\n        if (extent[0][i] !== min || extent[1][i] !== max) {\n          extentDomain = null;\n          extent[0][i] = min;\n          extent[1][i] = max;\n          return true;\n        }\n      }\n      function brushend() {\n        brushmove();\n        g.style(\"pointer-events\", \"all\").selectAll(\".resize\").style(\"display\", brush.empty() ? \"none\" : null);\n        d3.select(\"body\").style(\"cursor\", null);\n        w.on(\"mousemove.brush\", null).on(\"mouseup.brush\", null).on(\"touchmove.brush\", null).on(\"touchend.brush\", null).on(\"keydown.brush\", null).on(\"keyup.brush\", null);\n        event_({\n          type: \"brushend\"\n        });\n        d3_eventCancel();\n      }\n    }\n    brush.x = function(z) {\n      if (!arguments.length) return x;\n      x = z;\n      resizes = d3_svg_brushResizes[!x << 1 | !y];\n      return brush;\n    };\n    brush.y = function(z) {\n      if (!arguments.length) return y;\n      y = z;\n      resizes = d3_svg_brushResizes[!x << 1 | !y];\n      return brush;\n    };\n    brush.extent = function(z) {\n      var x0, x1, y0, y1, t;\n      if (!arguments.length) {\n        z = extentDomain || extent;\n        if (x) {\n          x0 = z[0][0], x1 = z[1][0];\n          if (!extentDomain) {\n            x0 = extent[0][0], x1 = extent[1][0];\n            if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);\n            if (x1 < x0) t = x0, x0 = x1, x1 = t;\n          }\n        }\n        if (y) {\n          y0 = z[0][1], y1 = z[1][1];\n          if (!extentDomain) {\n            y0 = extent[0][1], y1 = extent[1][1];\n            if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);\n            if (y1 < y0) t = y0, y0 = y1, y1 = t;\n          }\n        }\n        return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];\n      }\n      extentDomain = [ [ 0, 0 ], [ 0, 0 ] ];\n      if (x) {\n        x0 = z[0], x1 = z[1];\n        if (y) x0 = x0[0], x1 = x1[0];\n        extentDomain[0][0] = x0, extentDomain[1][0] = x1;\n        if (x.invert) x0 = x(x0), x1 = x(x1);\n        if (x1 < x0) t = x0, x0 = x1, x1 = t;\n        extent[0][0] = x0 | 0, extent[1][0] = x1 | 0;\n      }\n      if (y) {\n        y0 = z[0], y1 = z[1];\n        if (x) y0 = y0[1], y1 = y1[1];\n        extentDomain[0][1] = y0, extentDomain[1][1] = y1;\n        if (y.invert) y0 = y(y0), y1 = y(y1);\n        if (y1 < y0) t = y0, y0 = y1, y1 = t;\n        extent[0][1] = y0 | 0, extent[1][1] = y1 | 0;\n      }\n      return brush;\n    };\n    brush.clear = function() {\n      extentDomain = null;\n      extent[0][0] = extent[0][1] = extent[1][0] = extent[1][1] = 0;\n      return brush;\n    };\n    brush.empty = function() {\n      return x && extent[0][0] === extent[1][0] || y && extent[0][1] === extent[1][1];\n    };\n    return d3.rebind(brush, event, \"on\");\n  };\n  var d3_svg_brushCursor = {\n    n: \"ns-resize\",\n    e: \"ew-resize\",\n    s: \"ns-resize\",\n    w: \"ew-resize\",\n    nw: \"nwse-resize\",\n    ne: \"nesw-resize\",\n    se: \"nwse-resize\",\n    sw: \"nesw-resize\"\n  };\n  var d3_svg_brushResizes = [ [ \"n\", \"e\", \"s\", \"w\", \"nw\", \"ne\", \"se\", \"sw\" ], [ \"e\", \"w\" ], [ \"n\", \"s\" ], [] ];\n  d3.behavior = {};\n  d3.behavior.drag = function() {\n    var event = d3_eventDispatch(drag, \"drag\", \"dragstart\", \"dragend\"), origin = null;\n    function drag() {\n      this.on(\"mousedown.drag\", mousedown).on(\"touchstart.drag\", mousedown);\n    }\n    function mousedown() {\n      var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, offset, origin_ = point(), moved = 0;\n      var w = d3.select(window).on(\"mousemove.drag\", dragmove).on(\"touchmove.drag\", dragmove).on(\"mouseup.drag\", dragend, true).on(\"touchend.drag\", dragend, true);\n      if (origin) {\n        offset = origin.apply(target, arguments);\n        offset = [ offset.x - origin_[0], offset.y - origin_[1] ];\n      } else {\n        offset = [ 0, 0 ];\n      }\n      d3_eventCancel();\n      event_({\n        type: \"dragstart\"\n      });\n      function point() {\n        var p = target.parentNode, t = d3.event.changedTouches;\n        return t ? d3.touches(p, t)[0] : d3.mouse(p);\n      }\n      function dragmove() {\n        if (!target.parentNode) return dragend();\n        var p = point(), dx = p[0] - origin_[0], dy = p[1] - origin_[1];\n        moved |= dx | dy;\n        origin_ = p;\n        d3_eventCancel();\n        event_({\n          type: \"drag\",\n          x: p[0] + offset[0],\n          y: p[1] + offset[1],\n          dx: dx,\n          dy: dy\n        });\n      }\n      function dragend() {\n        event_({\n          type: \"dragend\"\n        });\n        if (moved) {\n          d3_eventCancel();\n          if (d3.event.target === eventTarget) w.on(\"click.drag\", click, true);\n        }\n        w.on(\"mousemove.drag\", null).on(\"touchmove.drag\", null).on(\"mouseup.drag\", null).on(\"touchend.drag\", null);\n      }\n      function click() {\n        d3_eventCancel();\n        w.on(\"click.drag\", null);\n      }\n    }\n    drag.origin = function(x) {\n      if (!arguments.length) return origin;\n      origin = x;\n      return drag;\n    };\n    return d3.rebind(drag, event, \"on\");\n  };\n  d3.behavior.zoom = function() {\n    var translate = [ 0, 0 ], translate0, scale = 1, scale0, scaleExtent = d3_behavior_zoomInfinity, event = d3_eventDispatch(zoom, \"zoom\"), x0, x1, y0, y1, touchtime;\n    function zoom() {\n      this.on(\"mousedown.zoom\", mousedown).on(\"mousewheel.zoom\", mousewheel).on(\"mousemove.zoom\", mousemove).on(\"DOMMouseScroll.zoom\", mousewheel).on(\"dblclick.zoom\", dblclick).on(\"touchstart.zoom\", touchstart).on(\"touchmove.zoom\", touchmove).on(\"touchend.zoom\", touchstart);\n    }\n    zoom.translate = function(x) {\n      if (!arguments.length) return translate;\n      translate = x.map(Number);\n      return zoom;\n    };\n    zoom.scale = function(x) {\n      if (!arguments.length) return scale;\n      scale = +x;\n      return zoom;\n    };\n    zoom.scaleExtent = function(x) {\n      if (!arguments.length) return scaleExtent;\n      scaleExtent = x == null ? d3_behavior_zoomInfinity : x.map(Number);\n      return zoom;\n    };\n    zoom.x = function(z) {\n      if (!arguments.length) return x1;\n      x1 = z;\n      x0 = z.copy();\n      return zoom;\n    };\n    zoom.y = function(z) {\n      if (!arguments.length) return y1;\n      y1 = z;\n      y0 = z.copy();\n      return zoom;\n    };\n    function location(p) {\n      return [ (p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale ];\n    }\n    function point(l) {\n      return [ l[0] * scale + translate[0], l[1] * scale + translate[1] ];\n    }\n    function scaleTo(s) {\n      scale = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));\n    }\n    function translateTo(p, l) {\n      l = point(l);\n      translate[0] += p[0] - l[0];\n      translate[1] += p[1] - l[1];\n    }\n    function dispatch(event) {\n      if (x1) x1.domain(x0.range().map(function(x) {\n        return (x - translate[0]) / scale;\n      }).map(x0.invert));\n      if (y1) y1.domain(y0.range().map(function(y) {\n        return (y - translate[1]) / scale;\n      }).map(y0.invert));\n      d3.event.preventDefault();\n      event({\n        type: \"zoom\",\n        scale: scale,\n        translate: translate\n      });\n    }\n    function mousedown() {\n      var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, moved = 0, w = d3.select(window).on(\"mousemove.zoom\", mousemove).on(\"mouseup.zoom\", mouseup), l = location(d3.mouse(target));\n      window.focus();\n      d3_eventCancel();\n      function mousemove() {\n        moved = 1;\n        translateTo(d3.mouse(target), l);\n        dispatch(event_);\n      }\n      function mouseup() {\n        if (moved) d3_eventCancel();\n        w.on(\"mousemove.zoom\", null).on(\"mouseup.zoom\", null);\n        if (moved && d3.event.target === eventTarget) w.on(\"click.zoom\", click, true);\n      }\n      function click() {\n        d3_eventCancel();\n        w.on(\"click.zoom\", null);\n      }\n    }\n    function mousewheel() {\n      if (!translate0) translate0 = location(d3.mouse(this));\n      scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * scale);\n      translateTo(d3.mouse(this), translate0);\n      dispatch(event.of(this, arguments));\n    }\n    function mousemove() {\n      translate0 = null;\n    }\n    function dblclick() {\n      var p = d3.mouse(this), l = location(p);\n      scaleTo(d3.event.shiftKey ? scale / 2 : scale * 2);\n      translateTo(p, l);\n      dispatch(event.of(this, arguments));\n    }\n    function touchstart() {\n      var touches = d3.touches(this), now = Date.now();\n      scale0 = scale;\n      translate0 = {};\n      touches.forEach(function(t) {\n        translate0[t.identifier] = location(t);\n      });\n      d3_eventCancel();\n      if (touches.length === 1) {\n        if (now - touchtime < 500) {\n          var p = touches[0], l = location(touches[0]);\n          scaleTo(scale * 2);\n          translateTo(p, l);\n          dispatch(event.of(this, arguments));\n        }\n        touchtime = now;\n      }\n    }\n    function touchmove() {\n      var touches = d3.touches(this), p0 = touches[0], l0 = translate0[p0.identifier];\n      if (p1 = touches[1]) {\n        var p1, l1 = translate0[p1.identifier];\n        p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];\n        l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];\n        scaleTo(d3.event.scale * scale0);\n      }\n      translateTo(p0, l0);\n      touchtime = null;\n      dispatch(event.of(this, arguments));\n    }\n    return d3.rebind(zoom, event, \"on\");\n  };\n  var d3_behavior_zoomDiv, d3_behavior_zoomInfinity = [ 0, Infinity ];\n  function d3_behavior_zoomDelta() {\n    if (!d3_behavior_zoomDiv) {\n      d3_behavior_zoomDiv = d3.select(\"body\").append(\"div\").style(\"visibility\", \"hidden\").style(\"top\", 0).style(\"height\", 0).style(\"width\", 0).style(\"overflow-y\", \"scroll\").append(\"div\").style(\"height\", \"2000px\").node().parentNode;\n    }\n    var e = d3.event, delta;\n    try {\n      d3_behavior_zoomDiv.scrollTop = 1e3;\n      d3_behavior_zoomDiv.dispatchEvent(e);\n      delta = 1e3 - d3_behavior_zoomDiv.scrollTop;\n    } catch (error) {\n      delta = e.wheelDelta || -e.detail * 5;\n    }\n    return delta;\n  }\n  d3.layout = {};\n  d3.layout.bundle = function() {\n    return function(links) {\n      var paths = [], i = -1, n = links.length;\n      while (++i < n) paths.push(d3_layout_bundlePath(links[i]));\n      return paths;\n    };\n  };\n  function d3_layout_bundlePath(link) {\n    var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ];\n    while (start !== lca) {\n      start = start.parent;\n      points.push(start);\n    }\n    var k = points.length;\n    while (end !== lca) {\n      points.splice(k, 0, end);\n      end = end.parent;\n    }\n    return points;\n  }\n  function d3_layout_bundleAncestors(node) {\n    var ancestors = [], parent = node.parent;\n    while (parent != null) {\n      ancestors.push(node);\n      node = parent;\n      parent = parent.parent;\n    }\n    ancestors.push(node);\n    return ancestors;\n  }\n  function d3_layout_bundleLeastCommonAncestor(a, b) {\n    if (a === b) return a;\n    var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null;\n    while (aNode === bNode) {\n      sharedNode = aNode;\n      aNode = aNodes.pop();\n      bNode = bNodes.pop();\n    }\n    return sharedNode;\n  }\n  d3.layout.chord = function() {\n    var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords;\n    function relayout() {\n      var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j;\n      chords = [];\n      groups = [];\n      k = 0, i = -1;\n      while (++i < n) {\n        x = 0, j = -1;\n        while (++j < n) {\n          x += matrix[i][j];\n        }\n        groupSums.push(x);\n        subgroupIndex.push(d3.range(n));\n        k += x;\n      }\n      if (sortGroups) {\n        groupIndex.sort(function(a, b) {\n          return sortGroups(groupSums[a], groupSums[b]);\n        });\n      }\n      if (sortSubgroups) {\n        subgroupIndex.forEach(function(d, i) {\n          d.sort(function(a, b) {\n            return sortSubgroups(matrix[i][a], matrix[i][b]);\n          });\n        });\n      }\n      k = (2 * Math.PI - padding * n) / k;\n      x = 0, i = -1;\n      while (++i < n) {\n        x0 = x, j = -1;\n        while (++j < n) {\n          var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k;\n          subgroups[di + \"-\" + dj] = {\n            index: di,\n            subindex: dj,\n            startAngle: a0,\n            endAngle: a1,\n            value: v\n          };\n        }\n        groups[di] = {\n          index: di,\n          startAngle: x0,\n          endAngle: x,\n          value: (x - x0) / k\n        };\n        x += padding;\n      }\n      i = -1;\n      while (++i < n) {\n        j = i - 1;\n        while (++j < n) {\n          var source = subgroups[i + \"-\" + j], target = subgroups[j + \"-\" + i];\n          if (source.value || target.value) {\n            chords.push(source.value < target.value ? {\n              source: target,\n              target: source\n            } : {\n              source: source,\n              target: target\n            });\n          }\n        }\n      }\n      if (sortChords) resort();\n    }\n    function resort() {\n      chords.sort(function(a, b) {\n        return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2);\n      });\n    }\n    chord.matrix = function(x) {\n      if (!arguments.length) return matrix;\n      n = (matrix = x) && matrix.length;\n      chords = groups = null;\n      return chord;\n    };\n    chord.padding = function(x) {\n      if (!arguments.length) return padding;\n      padding = x;\n      chords = groups = null;\n      return chord;\n    };\n    chord.sortGroups = function(x) {\n      if (!arguments.length) return sortGroups;\n      sortGroups = x;\n      chords = groups = null;\n      return chord;\n    };\n    chord.sortSubgroups = function(x) {\n      if (!arguments.length) return sortSubgroups;\n      sortSubgroups = x;\n      chords = null;\n      return chord;\n    };\n    chord.sortChords = function(x) {\n      if (!arguments.length) return sortChords;\n      sortChords = x;\n      if (chords) resort();\n      return chord;\n    };\n    chord.chords = function() {\n      if (!chords) relayout();\n      return chords;\n    };\n    chord.groups = function() {\n      if (!groups) relayout();\n      return groups;\n    };\n    return chord;\n  };\n  d3.layout.force = function() {\n    var force = {}, event = d3.dispatch(\"start\", \"tick\", \"end\"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, gravity = .1, theta = .8, interval, nodes = [], links = [], distances, strengths, charges;\n    function repulse(node) {\n      return function(quad, x1, y1, x2, y2) {\n        if (quad.point !== node) {\n          var dx = quad.cx - node.x, dy = quad.cy - node.y, dn = 1 / Math.sqrt(dx * dx + dy * dy);\n          if ((x2 - x1) * dn < theta) {\n            var k = quad.charge * dn * dn;\n            node.px -= dx * k;\n            node.py -= dy * k;\n            return true;\n          }\n          if (quad.point && isFinite(dn)) {\n            var k = quad.pointCharge * dn * dn;\n            node.px -= dx * k;\n            node.py -= dy * k;\n          }\n        }\n        return !quad.charge;\n      };\n    }\n    force.tick = function() {\n      if ((alpha *= .99) < .005) {\n        event.end({\n          type: \"end\",\n          alpha: alpha = 0\n        });\n        return true;\n      }\n      var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y;\n      for (i = 0; i < m; ++i) {\n        o = links[i];\n        s = o.source;\n        t = o.target;\n        x = t.x - s.x;\n        y = t.y - s.y;\n        if (l = x * x + y * y) {\n          l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;\n          x *= l;\n          y *= l;\n          t.x -= x * (k = s.weight / (t.weight + s.weight));\n          t.y -= y * k;\n          s.x += x * (k = 1 - k);\n          s.y += y * k;\n        }\n      }\n      if (k = alpha * gravity) {\n        x = size[0] / 2;\n        y = size[1] / 2;\n        i = -1;\n        if (k) while (++i < n) {\n          o = nodes[i];\n          o.x += (x - o.x) * k;\n          o.y += (y - o.y) * k;\n        }\n      }\n      if (charge) {\n        d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges);\n        i = -1;\n        while (++i < n) {\n          if (!(o = nodes[i]).fixed) {\n            q.visit(repulse(o));\n          }\n        }\n      }\n      i = -1;\n      while (++i < n) {\n        o = nodes[i];\n        if (o.fixed) {\n          o.x = o.px;\n          o.y = o.py;\n        } else {\n          o.x -= (o.px - (o.px = o.x)) * friction;\n          o.y -= (o.py - (o.py = o.y)) * friction;\n        }\n      }\n      event.tick({\n        type: \"tick\",\n        alpha: alpha\n      });\n    };\n    force.nodes = function(x) {\n      if (!arguments.length) return nodes;\n      nodes = x;\n      return force;\n    };\n    force.links = function(x) {\n      if (!arguments.length) return links;\n      links = x;\n      return force;\n    };\n    force.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return force;\n    };\n    force.linkDistance = function(x) {\n      if (!arguments.length) return linkDistance;\n      linkDistance = d3_functor(x);\n      return force;\n    };\n    force.distance = force.linkDistance;\n    force.linkStrength = function(x) {\n      if (!arguments.length) return linkStrength;\n      linkStrength = d3_functor(x);\n      return force;\n    };\n    force.friction = function(x) {\n      if (!arguments.length) return friction;\n      friction = x;\n      return force;\n    };\n    force.charge = function(x) {\n      if (!arguments.length) return charge;\n      charge = typeof x === \"function\" ? x : +x;\n      return force;\n    };\n    force.gravity = function(x) {\n      if (!arguments.length) return gravity;\n      gravity = x;\n      return force;\n    };\n    force.theta = function(x) {\n      if (!arguments.length) return theta;\n      theta = x;\n      return force;\n    };\n    force.alpha = function(x) {\n      if (!arguments.length) return alpha;\n      if (alpha) {\n        if (x > 0) alpha = x; else alpha = 0;\n      } else if (x > 0) {\n        event.start({\n          type: \"start\",\n          alpha: alpha = x\n        });\n        d3.timer(force.tick);\n      }\n      return force;\n    };\n    force.start = function() {\n      var i, j, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;\n      for (i = 0; i < n; ++i) {\n        (o = nodes[i]).index = i;\n        o.weight = 0;\n      }\n      distances = [];\n      strengths = [];\n      for (i = 0; i < m; ++i) {\n        o = links[i];\n        if (typeof o.source == \"number\") o.source = nodes[o.source];\n        if (typeof o.target == \"number\") o.target = nodes[o.target];\n        distances[i] = linkDistance.call(this, o, i);\n        strengths[i] = linkStrength.call(this, o, i);\n        ++o.source.weight;\n        ++o.target.weight;\n      }\n      for (i = 0; i < n; ++i) {\n        o = nodes[i];\n        if (isNaN(o.x)) o.x = position(\"x\", w);\n        if (isNaN(o.y)) o.y = position(\"y\", h);\n        if (isNaN(o.px)) o.px = o.x;\n        if (isNaN(o.py)) o.py = o.y;\n      }\n      charges = [];\n      if (typeof charge === \"function\") {\n        for (i = 0; i < n; ++i) {\n          charges[i] = +charge.call(this, nodes[i], i);\n        }\n      } else {\n        for (i = 0; i < n; ++i) {\n          charges[i] = charge;\n        }\n      }\n      function position(dimension, size) {\n        var neighbors = neighbor(i), j = -1, m = neighbors.length, x;\n        while (++j < m) if (!isNaN(x = neighbors[j][dimension])) return x;\n        return Math.random() * size;\n      }\n      function neighbor() {\n        if (!neighbors) {\n          neighbors = [];\n          for (j = 0; j < n; ++j) {\n            neighbors[j] = [];\n          }\n          for (j = 0; j < m; ++j) {\n            var o = links[j];\n            neighbors[o.source.index].push(o.target);\n            neighbors[o.target.index].push(o.source);\n          }\n        }\n        return neighbors[i];\n      }\n      return force.resume();\n    };\n    force.resume = function() {\n      return force.alpha(.1);\n    };\n    force.stop = function() {\n      return force.alpha(0);\n    };\n    force.drag = function() {\n      if (!drag) drag = d3.behavior.drag().origin(d3_identity).on(\"dragstart\", dragstart).on(\"drag\", d3_layout_forceDrag).on(\"dragend\", d3_layout_forceDragEnd);\n      this.on(\"mouseover.force\", d3_layout_forceDragOver).on(\"mouseout.force\", d3_layout_forceDragOut).call(drag);\n    };\n    function dragstart(d) {\n      d3_layout_forceDragOver(d3_layout_forceDragNode = d);\n      d3_layout_forceDragForce = force;\n    }\n    return d3.rebind(force, event, \"on\");\n  };\n  var d3_layout_forceDragForce, d3_layout_forceDragNode;\n  function d3_layout_forceDragOver(d) {\n    d.fixed |= 2;\n  }\n  function d3_layout_forceDragOut(d) {\n    if (d !== d3_layout_forceDragNode) d.fixed &= 1;\n  }\n  function d3_layout_forceDragEnd() {\n    d3_layout_forceDragNode.fixed &= 1;\n    d3_layout_forceDragForce = d3_layout_forceDragNode = null;\n  }\n  function d3_layout_forceDrag() {\n    d3_layout_forceDragNode.px = d3.event.x;\n    d3_layout_forceDragNode.py = d3.event.y;\n    d3_layout_forceDragForce.resume();\n  }\n  function d3_layout_forceAccumulate(quad, alpha, charges) {\n    var cx = 0, cy = 0;\n    quad.charge = 0;\n    if (!quad.leaf) {\n      var nodes = quad.nodes, n = nodes.length, i = -1, c;\n      while (++i < n) {\n        c = nodes[i];\n        if (c == null) continue;\n        d3_layout_forceAccumulate(c, alpha, charges);\n        quad.charge += c.charge;\n        cx += c.charge * c.cx;\n        cy += c.charge * c.cy;\n      }\n    }\n    if (quad.point) {\n      if (!quad.leaf) {\n        quad.point.x += Math.random() - .5;\n        quad.point.y += Math.random() - .5;\n      }\n      var k = alpha * charges[quad.point.index];\n      quad.charge += quad.pointCharge = k;\n      cx += k * quad.point.x;\n      cy += k * quad.point.y;\n    }\n    quad.cx = cx / quad.charge;\n    quad.cy = cy / quad.charge;\n  }\n  function d3_layout_forceLinkDistance(link) {\n    return 20;\n  }\n  function d3_layout_forceLinkStrength(link) {\n    return 1;\n  }\n  d3.layout.partition = function() {\n    var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];\n    function position(node, x, dx, dy) {\n      var children = node.children;\n      node.x = x;\n      node.y = node.depth * dy;\n      node.dx = dx;\n      node.dy = dy;\n      if (children && (n = children.length)) {\n        var i = -1, n, c, d;\n        dx = node.value ? dx / node.value : 0;\n        while (++i < n) {\n          position(c = children[i], x, d = c.value * dx, dy);\n          x += d;\n        }\n      }\n    }\n    function depth(node) {\n      var children = node.children, d = 0;\n      if (children && (n = children.length)) {\n        var i = -1, n;\n        while (++i < n) d = Math.max(d, depth(children[i]));\n      }\n      return 1 + d;\n    }\n    function partition(d, i) {\n      var nodes = hierarchy.call(this, d, i);\n      position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));\n      return nodes;\n    }\n    partition.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return partition;\n    };\n    return d3_layout_hierarchyRebind(partition, hierarchy);\n  };\n  d3.layout.pie = function() {\n    var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = 2 * Math.PI;\n    function pie(data, i) {\n      var values = data.map(function(d, i) {\n        return +value.call(pie, d, i);\n      });\n      var a = +(typeof startAngle === \"function\" ? startAngle.apply(this, arguments) : startAngle);\n      var k = ((typeof endAngle === \"function\" ? endAngle.apply(this, arguments) : endAngle) - startAngle) / d3.sum(values);\n      var index = d3.range(data.length);\n      if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {\n        return values[j] - values[i];\n      } : function(i, j) {\n        return sort(data[i], data[j]);\n      });\n      var arcs = [];\n      index.forEach(function(i) {\n        var d;\n        arcs[i] = {\n          data: data[i],\n          value: d = values[i],\n          startAngle: a,\n          endAngle: a += d * k\n        };\n      });\n      return arcs;\n    }\n    pie.value = function(x) {\n      if (!arguments.length) return value;\n      value = x;\n      return pie;\n    };\n    pie.sort = function(x) {\n      if (!arguments.length) return sort;\n      sort = x;\n      return pie;\n    };\n    pie.startAngle = function(x) {\n      if (!arguments.length) return startAngle;\n      startAngle = x;\n      return pie;\n    };\n    pie.endAngle = function(x) {\n      if (!arguments.length) return endAngle;\n      endAngle = x;\n      return pie;\n    };\n    return pie;\n  };\n  var d3_layout_pieSortByValue = {};\n  d3.layout.stack = function() {\n    var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;\n    function stack(data, index) {\n      var series = data.map(function(d, i) {\n        return values.call(stack, d, i);\n      });\n      var points = series.map(function(d, i) {\n        return d.map(function(v, i) {\n          return [ x.call(stack, v, i), y.call(stack, v, i) ];\n        });\n      });\n      var orders = order.call(stack, points, index);\n      series = d3.permute(series, orders);\n      points = d3.permute(points, orders);\n      var offsets = offset.call(stack, points, index);\n      var n = series.length, m = series[0].length, i, j, o;\n      for (j = 0; j < m; ++j) {\n        out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);\n        for (i = 1; i < n; ++i) {\n          out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);\n        }\n      }\n      return data;\n    }\n    stack.values = function(x) {\n      if (!arguments.length) return values;\n      values = x;\n      return stack;\n    };\n    stack.order = function(x) {\n      if (!arguments.length) return order;\n      order = typeof x === \"function\" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;\n      return stack;\n    };\n    stack.offset = function(x) {\n      if (!arguments.length) return offset;\n      offset = typeof x === \"function\" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;\n      return stack;\n    };\n    stack.x = function(z) {\n      if (!arguments.length) return x;\n      x = z;\n      return stack;\n    };\n    stack.y = function(z) {\n      if (!arguments.length) return y;\n      y = z;\n      return stack;\n    };\n    stack.out = function(z) {\n      if (!arguments.length) return out;\n      out = z;\n      return stack;\n    };\n    return stack;\n  };\n  function d3_layout_stackX(d) {\n    return d.x;\n  }\n  function d3_layout_stackY(d) {\n    return d.y;\n  }\n  function d3_layout_stackOut(d, y0, y) {\n    d.y0 = y0;\n    d.y = y;\n  }\n  var d3_layout_stackOrders = d3.map({\n    \"inside-out\": function(data) {\n      var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {\n        return max[a] - max[b];\n      }), top = 0, bottom = 0, tops = [], bottoms = [];\n      for (i = 0; i < n; ++i) {\n        j = index[i];\n        if (top < bottom) {\n          top += sums[j];\n          tops.push(j);\n        } else {\n          bottom += sums[j];\n          bottoms.push(j);\n        }\n      }\n      return bottoms.reverse().concat(tops);\n    },\n    reverse: function(data) {\n      return d3.range(data.length).reverse();\n    },\n    \"default\": d3_layout_stackOrderDefault\n  });\n  var d3_layout_stackOffsets = d3.map({\n    silhouette: function(data) {\n      var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];\n      for (j = 0; j < m; ++j) {\n        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];\n        if (o > max) max = o;\n        sums.push(o);\n      }\n      for (j = 0; j < m; ++j) {\n        y0[j] = (max - sums[j]) / 2;\n      }\n      return y0;\n    },\n    wiggle: function(data) {\n      var n = data.length, x = data[0], m = x.length, max = 0, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];\n      y0[0] = o = o0 = 0;\n      for (j = 1; j < m; ++j) {\n        for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];\n        for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {\n          for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {\n            s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;\n          }\n          s2 += s3 * data[i][j][1];\n        }\n        y0[j] = o -= s1 ? s2 / s1 * dx : 0;\n        if (o < o0) o0 = o;\n      }\n      for (j = 0; j < m; ++j) y0[j] -= o0;\n      return y0;\n    },\n    expand: function(data) {\n      var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];\n      for (j = 0; j < m; ++j) {\n        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];\n        if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k;\n      }\n      for (j = 0; j < m; ++j) y0[j] = 0;\n      return y0;\n    },\n    zero: d3_layout_stackOffsetZero\n  });\n  function d3_layout_stackOrderDefault(data) {\n    return d3.range(data.length);\n  }\n  function d3_layout_stackOffsetZero(data) {\n    var j = -1, m = data[0].length, y0 = [];\n    while (++j < m) y0[j] = 0;\n    return y0;\n  }\n  function d3_layout_stackMaxIndex(array) {\n    var i = 1, j = 0, v = array[0][1], k, n = array.length;\n    for (; i < n; ++i) {\n      if ((k = array[i][1]) > v) {\n        j = i;\n        v = k;\n      }\n    }\n    return j;\n  }\n  function d3_layout_stackReduceSum(d) {\n    return d.reduce(d3_layout_stackSum, 0);\n  }\n  function d3_layout_stackSum(p, d) {\n    return p + d[1];\n  }\n  d3.layout.histogram = function() {\n    var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;\n    function histogram(data, i) {\n      var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;\n      while (++i < m) {\n        bin = bins[i] = [];\n        bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);\n        bin.y = 0;\n      }\n      if (m > 0) {\n        i = -1;\n        while (++i < n) {\n          x = values[i];\n          if (x >= range[0] && x <= range[1]) {\n            bin = bins[d3.bisect(thresholds, x, 1, m) - 1];\n            bin.y += k;\n            bin.push(data[i]);\n          }\n        }\n      }\n      return bins;\n    }\n    histogram.value = function(x) {\n      if (!arguments.length) return valuer;\n      valuer = x;\n      return histogram;\n    };\n    histogram.range = function(x) {\n      if (!arguments.length) return ranger;\n      ranger = d3_functor(x);\n      return histogram;\n    };\n    histogram.bins = function(x) {\n      if (!arguments.length) return binner;\n      binner = typeof x === \"number\" ? function(range) {\n        return d3_layout_histogramBinFixed(range, x);\n      } : d3_functor(x);\n      return histogram;\n    };\n    histogram.frequency = function(x) {\n      if (!arguments.length) return frequency;\n      frequency = !!x;\n      return histogram;\n    };\n    return histogram;\n  };\n  function d3_layout_histogramBinSturges(range, values) {\n    return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));\n  }\n  function d3_layout_histogramBinFixed(range, n) {\n    var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];\n    while (++x <= n) f[x] = m * x + b;\n    return f;\n  }\n  function d3_layout_histogramRange(values) {\n    return [ d3.min(values), d3.max(values) ];\n  }\n  d3.layout.hierarchy = function() {\n    var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;\n    function recurse(data, depth, nodes) {\n      var childs = children.call(hierarchy, data, depth), node = d3_layout_hierarchyInline ? data : {\n        data: data\n      };\n      node.depth = depth;\n      nodes.push(node);\n      if (childs && (n = childs.length)) {\n        var i = -1, n, c = node.children = [], v = 0, j = depth + 1, d;\n        while (++i < n) {\n          d = recurse(childs[i], j, nodes);\n          d.parent = node;\n          c.push(d);\n          v += d.value;\n        }\n        if (sort) c.sort(sort);\n        if (value) node.value = v;\n      } else if (value) {\n        node.value = +value.call(hierarchy, data, depth) || 0;\n      }\n      return node;\n    }\n    function revalue(node, depth) {\n      var children = node.children, v = 0;\n      if (children && (n = children.length)) {\n        var i = -1, n, j = depth + 1;\n        while (++i < n) v += revalue(children[i], j);\n      } else if (value) {\n        v = +value.call(hierarchy, d3_layout_hierarchyInline ? node : node.data, depth) || 0;\n      }\n      if (value) node.value = v;\n      return v;\n    }\n    function hierarchy(d) {\n      var nodes = [];\n      recurse(d, 0, nodes);\n      return nodes;\n    }\n    hierarchy.sort = function(x) {\n      if (!arguments.length) return sort;\n      sort = x;\n      return hierarchy;\n    };\n    hierarchy.children = function(x) {\n      if (!arguments.length) return children;\n      children = x;\n      return hierarchy;\n    };\n    hierarchy.value = function(x) {\n      if (!arguments.length) return value;\n      value = x;\n      return hierarchy;\n    };\n    hierarchy.revalue = function(root) {\n      revalue(root, 0);\n      return root;\n    };\n    return hierarchy;\n  };\n  function d3_layout_hierarchyRebind(object, hierarchy) {\n    d3.rebind(object, hierarchy, \"sort\", \"children\", \"value\");\n    object.links = d3_layout_hierarchyLinks;\n    object.nodes = function(d) {\n      d3_layout_hierarchyInline = true;\n      return (object.nodes = object)(d);\n    };\n    return object;\n  }\n  function d3_layout_hierarchyChildren(d) {\n    return d.children;\n  }\n  function d3_layout_hierarchyValue(d) {\n    return d.value;\n  }\n  function d3_layout_hierarchySort(a, b) {\n    return b.value - a.value;\n  }\n  function d3_layout_hierarchyLinks(nodes) {\n    return d3.merge(nodes.map(function(parent) {\n      return (parent.children || []).map(function(child) {\n        return {\n          source: parent,\n          target: child\n        };\n      });\n    }));\n  }\n  var d3_layout_hierarchyInline = false;\n  d3.layout.pack = function() {\n    var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ];\n    function pack(d, i) {\n      var nodes = hierarchy.call(this, d, i), root = nodes[0];\n      root.x = 0;\n      root.y = 0;\n      d3_layout_treeVisitAfter(root, function(d) {\n        d.r = Math.sqrt(d.value);\n      });\n      d3_layout_treeVisitAfter(root, d3_layout_packSiblings);\n      var w = size[0], h = size[1], k = Math.max(2 * root.r / w, 2 * root.r / h);\n      if (padding > 0) {\n        var dr = padding * k / 2;\n        d3_layout_treeVisitAfter(root, function(d) {\n          d.r += dr;\n        });\n        d3_layout_treeVisitAfter(root, d3_layout_packSiblings);\n        d3_layout_treeVisitAfter(root, function(d) {\n          d.r -= dr;\n        });\n        k = Math.max(2 * root.r / w, 2 * root.r / h);\n      }\n      d3_layout_packTransform(root, w / 2, h / 2, 1 / k);\n      return nodes;\n    }\n    pack.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return pack;\n    };\n    pack.padding = function(_) {\n      if (!arguments.length) return padding;\n      padding = +_;\n      return pack;\n    };\n    return d3_layout_hierarchyRebind(pack, hierarchy);\n  };\n  function d3_layout_packSort(a, b) {\n    return a.value - b.value;\n  }\n  function d3_layout_packInsert(a, b) {\n    var c = a._pack_next;\n    a._pack_next = b;\n    b._pack_prev = a;\n    b._pack_next = c;\n    c._pack_prev = b;\n  }\n  function d3_layout_packSplice(a, b) {\n    a._pack_next = b;\n    b._pack_prev = a;\n  }\n  function d3_layout_packIntersects(a, b) {\n    var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;\n    return dr * dr - dx * dx - dy * dy > .001;\n  }\n  function d3_layout_packSiblings(node) {\n    if (!(nodes = node.children) || !(n = nodes.length)) return;\n    var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;\n    function bound(node) {\n      xMin = Math.min(node.x - node.r, xMin);\n      xMax = Math.max(node.x + node.r, xMax);\n      yMin = Math.min(node.y - node.r, yMin);\n      yMax = Math.max(node.y + node.r, yMax);\n    }\n    nodes.forEach(d3_layout_packLink);\n    a = nodes[0];\n    a.x = -a.r;\n    a.y = 0;\n    bound(a);\n    if (n > 1) {\n      b = nodes[1];\n      b.x = b.r;\n      b.y = 0;\n      bound(b);\n      if (n > 2) {\n        c = nodes[2];\n        d3_layout_packPlace(a, b, c);\n        bound(c);\n        d3_layout_packInsert(a, c);\n        a._pack_prev = c;\n        d3_layout_packInsert(c, b);\n        b = a._pack_next;\n        for (i = 3; i < n; i++) {\n          d3_layout_packPlace(a, b, c = nodes[i]);\n          var isect = 0, s1 = 1, s2 = 1;\n          for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {\n            if (d3_layout_packIntersects(j, c)) {\n              isect = 1;\n              break;\n            }\n          }\n          if (isect == 1) {\n            for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {\n              if (d3_layout_packIntersects(k, c)) {\n                break;\n              }\n            }\n          }\n          if (isect) {\n            if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);\n            i--;\n          } else {\n            d3_layout_packInsert(a, c);\n            b = c;\n            bound(c);\n          }\n        }\n      }\n    }\n    var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;\n    for (i = 0; i < n; i++) {\n      c = nodes[i];\n      c.x -= cx;\n      c.y -= cy;\n      cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));\n    }\n    node.r = cr;\n    nodes.forEach(d3_layout_packUnlink);\n  }\n  function d3_layout_packLink(node) {\n    node._pack_next = node._pack_prev = node;\n  }\n  function d3_layout_packUnlink(node) {\n    delete node._pack_next;\n    delete node._pack_prev;\n  }\n  function d3_layout_packTransform(node, x, y, k) {\n    var children = node.children;\n    node.x = x += k * node.x;\n    node.y = y += k * node.y;\n    node.r *= k;\n    if (children) {\n      var i = -1, n = children.length;\n      while (++i < n) d3_layout_packTransform(children[i], x, y, k);\n    }\n  }\n  function d3_layout_packPlace(a, b, c) {\n    var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;\n    if (db && (dx || dy)) {\n      var da = b.r + c.r, dc = dx * dx + dy * dy;\n      da *= da;\n      db *= db;\n      var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);\n      c.x = a.x + x * dx + y * dy;\n      c.y = a.y + x * dy - y * dx;\n    } else {\n      c.x = a.x + db;\n      c.y = a.y;\n    }\n  }\n  d3.layout.cluster = function() {\n    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];\n    function cluster(d, i) {\n      var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0, kx, ky;\n      d3_layout_treeVisitAfter(root, function(node) {\n        var children = node.children;\n        if (children && children.length) {\n          node.x = d3_layout_clusterX(children);\n          node.y = d3_layout_clusterY(children);\n        } else {\n          node.x = previousNode ? x += separation(node, previousNode) : 0;\n          node.y = 0;\n          previousNode = node;\n        }\n      });\n      var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;\n      d3_layout_treeVisitAfter(root, function(node) {\n        node.x = (node.x - x0) / (x1 - x0) * size[0];\n        node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];\n      });\n      return nodes;\n    }\n    cluster.separation = function(x) {\n      if (!arguments.length) return separation;\n      separation = x;\n      return cluster;\n    };\n    cluster.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return cluster;\n    };\n    return d3_layout_hierarchyRebind(cluster, hierarchy);\n  };\n  function d3_layout_clusterY(children) {\n    return 1 + d3.max(children, function(child) {\n      return child.y;\n    });\n  }\n  function d3_layout_clusterX(children) {\n    return children.reduce(function(x, child) {\n      return x + child.x;\n    }, 0) / children.length;\n  }\n  function d3_layout_clusterLeft(node) {\n    var children = node.children;\n    return children && children.length ? d3_layout_clusterLeft(children[0]) : node;\n  }\n  function d3_layout_clusterRight(node) {\n    var children = node.children, n;\n    return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;\n  }\n  d3.layout.tree = function() {\n    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];\n    function tree(d, i) {\n      var nodes = hierarchy.call(this, d, i), root = nodes[0];\n      function firstWalk(node, previousSibling) {\n        var children = node.children, layout = node._tree;\n        if (children && (n = children.length)) {\n          var n, firstChild = children[0], previousChild, ancestor = firstChild, child, i = -1;\n          while (++i < n) {\n            child = children[i];\n            firstWalk(child, previousChild);\n            ancestor = apportion(child, previousChild, ancestor);\n            previousChild = child;\n          }\n          d3_layout_treeShift(node);\n          var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);\n          if (previousSibling) {\n            layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);\n            layout.mod = layout.prelim - midpoint;\n          } else {\n            layout.prelim = midpoint;\n          }\n        } else {\n          if (previousSibling) {\n            layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);\n          }\n        }\n      }\n      function secondWalk(node, x) {\n        node.x = node._tree.prelim + x;\n        var children = node.children;\n        if (children && (n = children.length)) {\n          var i = -1, n;\n          x += node._tree.mod;\n          while (++i < n) {\n            secondWalk(children[i], x);\n          }\n        }\n      }\n      function apportion(node, previousSibling, ancestor) {\n        if (previousSibling) {\n          var vip = node, vop = node, vim = previousSibling, vom = node.parent.children[0], sip = vip._tree.mod, sop = vop._tree.mod, sim = vim._tree.mod, som = vom._tree.mod, shift;\n          while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {\n            vom = d3_layout_treeLeft(vom);\n            vop = d3_layout_treeRight(vop);\n            vop._tree.ancestor = node;\n            shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);\n            if (shift > 0) {\n              d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);\n              sip += shift;\n              sop += shift;\n            }\n            sim += vim._tree.mod;\n            sip += vip._tree.mod;\n            som += vom._tree.mod;\n            sop += vop._tree.mod;\n          }\n          if (vim && !d3_layout_treeRight(vop)) {\n            vop._tree.thread = vim;\n            vop._tree.mod += sim - sop;\n          }\n          if (vip && !d3_layout_treeLeft(vom)) {\n            vom._tree.thread = vip;\n            vom._tree.mod += sip - som;\n            ancestor = node;\n          }\n        }\n        return ancestor;\n      }\n      d3_layout_treeVisitAfter(root, function(node, previousSibling) {\n        node._tree = {\n          ancestor: node,\n          prelim: 0,\n          mod: 0,\n          change: 0,\n          shift: 0,\n          number: previousSibling ? previousSibling._tree.number + 1 : 0\n        };\n      });\n      firstWalk(root);\n      secondWalk(root, -root._tree.prelim);\n      var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost), right = d3_layout_treeSearch(root, d3_layout_treeRightmost), deep = d3_layout_treeSearch(root, d3_layout_treeDeepest), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2, y1 = deep.depth || 1;\n      d3_layout_treeVisitAfter(root, function(node) {\n        node.x = (node.x - x0) / (x1 - x0) * size[0];\n        node.y = node.depth / y1 * size[1];\n        delete node._tree;\n      });\n      return nodes;\n    }\n    tree.separation = function(x) {\n      if (!arguments.length) return separation;\n      separation = x;\n      return tree;\n    };\n    tree.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return tree;\n    };\n    return d3_layout_hierarchyRebind(tree, hierarchy);\n  };\n  function d3_layout_treeSeparation(a, b) {\n    return a.parent == b.parent ? 1 : 2;\n  }\n  function d3_layout_treeLeft(node) {\n    var children = node.children;\n    return children && children.length ? children[0] : node._tree.thread;\n  }\n  function d3_layout_treeRight(node) {\n    var children = node.children, n;\n    return children && (n = children.length) ? children[n - 1] : node._tree.thread;\n  }\n  function d3_layout_treeSearch(node, compare) {\n    var children = node.children;\n    if (children && (n = children.length)) {\n      var child, n, i = -1;\n      while (++i < n) {\n        if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {\n          node = child;\n        }\n      }\n    }\n    return node;\n  }\n  function d3_layout_treeRightmost(a, b) {\n    return a.x - b.x;\n  }\n  function d3_layout_treeLeftmost(a, b) {\n    return b.x - a.x;\n  }\n  function d3_layout_treeDeepest(a, b) {\n    return a.depth - b.depth;\n  }\n  function d3_layout_treeVisitAfter(node, callback) {\n    function visit(node, previousSibling) {\n      var children = node.children;\n      if (children && (n = children.length)) {\n        var child, previousChild = null, i = -1, n;\n        while (++i < n) {\n          child = children[i];\n          visit(child, previousChild);\n          previousChild = child;\n        }\n      }\n      callback(node, previousSibling);\n    }\n    visit(node, null);\n  }\n  function d3_layout_treeShift(node) {\n    var shift = 0, change = 0, children = node.children, i = children.length, child;\n    while (--i >= 0) {\n      child = children[i]._tree;\n      child.prelim += shift;\n      child.mod += shift;\n      shift += child.shift + (change += child.change);\n    }\n  }\n  function d3_layout_treeMove(ancestor, node, shift) {\n    ancestor = ancestor._tree;\n    node = node._tree;\n    var change = shift / (node.number - ancestor.number);\n    ancestor.change += change;\n    node.change -= change;\n    node.shift += shift;\n    node.prelim += shift;\n    node.mod += shift;\n  }\n  function d3_layout_treeAncestor(vim, node, ancestor) {\n    return vim._tree.ancestor.parent == node.parent ? vim._tree.ancestor : ancestor;\n  }\n  d3.layout.treemap = function() {\n    var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, ratio = .5 * (1 + Math.sqrt(5));\n    function scale(children, k) {\n      var i = -1, n = children.length, child, area;\n      while (++i < n) {\n        area = (child = children[i]).value * (k < 0 ? 0 : k);\n        child.area = isNaN(area) || area <= 0 ? 0 : area;\n      }\n    }\n    function squarify(node) {\n      var children = node.children;\n      if (children && children.length) {\n        var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = Math.min(rect.dx, rect.dy), n;\n        scale(remaining, rect.dx * rect.dy / node.value);\n        row.area = 0;\n        while ((n = remaining.length) > 0) {\n          row.push(child = remaining[n - 1]);\n          row.area += child.area;\n          if ((score = worst(row, u)) <= best) {\n            remaining.pop();\n            best = score;\n          } else {\n            row.area -= row.pop().area;\n            position(row, u, rect, false);\n            u = Math.min(rect.dx, rect.dy);\n            row.length = row.area = 0;\n            best = Infinity;\n          }\n        }\n        if (row.length) {\n          position(row, u, rect, true);\n          row.length = row.area = 0;\n        }\n        children.forEach(squarify);\n      }\n    }\n    function stickify(node) {\n      var children = node.children;\n      if (children && children.length) {\n        var rect = pad(node), remaining = children.slice(), child, row = [];\n        scale(remaining, rect.dx * rect.dy / node.value);\n        row.area = 0;\n        while (child = remaining.pop()) {\n          row.push(child);\n          row.area += child.area;\n          if (child.z != null) {\n            position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);\n            row.length = row.area = 0;\n          }\n        }\n        children.forEach(stickify);\n      }\n    }\n    function worst(row, u) {\n      var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;\n      while (++i < n) {\n        if (!(r = row[i].area)) continue;\n        if (r < rmin) rmin = r;\n        if (r > rmax) rmax = r;\n      }\n      s *= s;\n      u *= u;\n      return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;\n    }\n    function position(row, u, rect, flush) {\n      var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;\n      if (u == rect.dx) {\n        if (flush || v > rect.dy) v = rect.dy;\n        while (++i < n) {\n          o = row[i];\n          o.x = x;\n          o.y = y;\n          o.dy = v;\n          x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);\n        }\n        o.z = true;\n        o.dx += rect.x + rect.dx - x;\n        rect.y += v;\n        rect.dy -= v;\n      } else {\n        if (flush || v > rect.dx) v = rect.dx;\n        while (++i < n) {\n          o = row[i];\n          o.x = x;\n          o.y = y;\n          o.dx = v;\n          y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);\n        }\n        o.z = false;\n        o.dy += rect.y + rect.dy - y;\n        rect.x += v;\n        rect.dx -= v;\n      }\n    }\n    function treemap(d) {\n      var nodes = stickies || hierarchy(d), root = nodes[0];\n      root.x = 0;\n      root.y = 0;\n      root.dx = size[0];\n      root.dy = size[1];\n      if (stickies) hierarchy.revalue(root);\n      scale([ root ], root.dx * root.dy / root.value);\n      (stickies ? stickify : squarify)(root);\n      if (sticky) stickies = nodes;\n      return nodes;\n    }\n    treemap.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return treemap;\n    };\n    treemap.padding = function(x) {\n      if (!arguments.length) return padding;\n      function padFunction(node) {\n        var p = x.call(treemap, node, node.depth);\n        return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === \"number\" ? [ p, p, p, p ] : p);\n      }\n      function padConstant(node) {\n        return d3_layout_treemapPad(node, x);\n      }\n      var type;\n      pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === \"function\" ? padFunction : type === \"number\" ? (x = [ x, x, x, x ], padConstant) : padConstant;\n      return treemap;\n    };\n    treemap.round = function(x) {\n      if (!arguments.length) return round != Number;\n      round = x ? Math.round : Number;\n      return treemap;\n    };\n    treemap.sticky = function(x) {\n      if (!arguments.length) return sticky;\n      sticky = x;\n      stickies = null;\n      return treemap;\n    };\n    treemap.ratio = function(x) {\n      if (!arguments.length) return ratio;\n      ratio = x;\n      return treemap;\n    };\n    return d3_layout_hierarchyRebind(treemap, hierarchy);\n  };\n  function d3_layout_treemapPadNull(node) {\n    return {\n      x: node.x,\n      y: node.y,\n      dx: node.dx,\n      dy: node.dy\n    };\n  }\n  function d3_layout_treemapPad(node, padding) {\n    var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];\n    if (dx < 0) {\n      x += dx / 2;\n      dx = 0;\n    }\n    if (dy < 0) {\n      y += dy / 2;\n      dy = 0;\n    }\n    return {\n      x: x,\n      y: y,\n      dx: dx,\n      dy: dy\n    };\n  }\n  function d3_dsv(delimiter, mimeType) {\n    var reParse = new RegExp(\"\\r\\n|[\" + delimiter + \"\\r\\n]\", \"g\"), reFormat = new RegExp('[\"' + delimiter + \"\\n]\"), delimiterCode = delimiter.charCodeAt(0);\n    function dsv(url, callback) {\n      d3.text(url, mimeType, function(text) {\n        callback(text && dsv.parse(text));\n      });\n    }\n    dsv.parse = function(text) {\n      var header;\n      return dsv.parseRows(text, function(row, i) {\n        if (i) {\n          var o = {}, j = -1, m = header.length;\n          while (++j < m) o[header[j]] = row[j];\n          return o;\n        } else {\n          header = row;\n          return null;\n        }\n      });\n    };\n    dsv.parseRows = function(text, f) {\n      var EOL = {}, EOF = {}, rows = [], n = 0, t, eol;\n      reParse.lastIndex = 0;\n      function token() {\n        if (reParse.lastIndex >= text.length) return EOF;\n        if (eol) {\n          eol = false;\n          return EOL;\n        }\n        var j = reParse.lastIndex;\n        if (text.charCodeAt(j) === 34) {\n          var i = j;\n          while (i++ < text.length) {\n            if (text.charCodeAt(i) === 34) {\n              if (text.charCodeAt(i + 1) !== 34) break;\n              i++;\n            }\n          }\n          reParse.lastIndex = i + 2;\n          var c = text.charCodeAt(i + 1);\n          if (c === 13) {\n            eol = true;\n            if (text.charCodeAt(i + 2) === 10) reParse.lastIndex++;\n          } else if (c === 10) {\n            eol = true;\n          }\n          return text.substring(j + 1, i).replace(/\"\"/g, '\"');\n        }\n        var m = reParse.exec(text);\n        if (m) {\n          eol = m[0].charCodeAt(0) !== delimiterCode;\n          return text.substring(j, m.index);\n        }\n        reParse.lastIndex = text.length;\n        return text.substring(j);\n      }\n      while ((t = token()) !== EOF) {\n        var a = [];\n        while (t !== EOL && t !== EOF) {\n          a.push(t);\n          t = token();\n        }\n        if (f && !(a = f(a, n++))) continue;\n        rows.push(a);\n      }\n      return rows;\n    };\n    dsv.format = function(rows) {\n      return rows.map(formatRow).join(\"\\n\");\n    };\n    function formatRow(row) {\n      return row.map(formatValue).join(delimiter);\n    }\n    function formatValue(text) {\n      return reFormat.test(text) ? '\"' + text.replace(/\\\"/g, '\"\"') + '\"' : text;\n    }\n    return dsv;\n  }\n  d3.csv = d3_dsv(\",\", \"text/csv\");\n  d3.tsv = d3_dsv(\"\\t\", \"text/tab-separated-values\");\n  d3.geo = {};\n  var d3_geo_radians = Math.PI / 180;\n  d3.geo.azimuthal = function() {\n    var mode = \"orthographic\", origin, scale = 200, translate = [ 480, 250 ], x0, y0, cy0, sy0;\n    function azimuthal(coordinates) {\n      var x1 = coordinates[0] * d3_geo_radians - x0, y1 = coordinates[1] * d3_geo_radians, cx1 = Math.cos(x1), sx1 = Math.sin(x1), cy1 = Math.cos(y1), sy1 = Math.sin(y1), cc = mode !== \"orthographic\" ? sy0 * sy1 + cy0 * cy1 * cx1 : null, c, k = mode === \"stereographic\" ? 1 / (1 + cc) : mode === \"gnomonic\" ? 1 / cc : mode === \"equidistant\" ? (c = Math.acos(cc), c ? c / Math.sin(c) : 0) : mode === \"equalarea\" ? Math.sqrt(2 / (1 + cc)) : 1, x = k * cy1 * sx1, y = k * (sy0 * cy1 * cx1 - cy0 * sy1);\n      return [ scale * x + translate[0], scale * y + translate[1] ];\n    }\n    azimuthal.invert = function(coordinates) {\n      var x = (coordinates[0] - translate[0]) / scale, y = (coordinates[1] - translate[1]) / scale, p = Math.sqrt(x * x + y * y), c = mode === \"stereographic\" ? 2 * Math.atan(p) : mode === \"gnomonic\" ? Math.atan(p) : mode === \"equidistant\" ? p : mode === \"equalarea\" ? 2 * Math.asin(.5 * p) : Math.asin(p), sc = Math.sin(c), cc = Math.cos(c);\n      return [ (x0 + Math.atan2(x * sc, p * cy0 * cc + y * sy0 * sc)) / d3_geo_radians, Math.asin(cc * sy0 - (p ? y * sc * cy0 / p : 0)) / d3_geo_radians ];\n    };\n    azimuthal.mode = function(x) {\n      if (!arguments.length) return mode;\n      mode = x + \"\";\n      return azimuthal;\n    };\n    azimuthal.origin = function(x) {\n      if (!arguments.length) return origin;\n      origin = x;\n      x0 = origin[0] * d3_geo_radians;\n      y0 = origin[1] * d3_geo_radians;\n      cy0 = Math.cos(y0);\n      sy0 = Math.sin(y0);\n      return azimuthal;\n    };\n    azimuthal.scale = function(x) {\n      if (!arguments.length) return scale;\n      scale = +x;\n      return azimuthal;\n    };\n    azimuthal.translate = function(x) {\n      if (!arguments.length) return translate;\n      translate = [ +x[0], +x[1] ];\n      return azimuthal;\n    };\n    return azimuthal.origin([ 0, 0 ]);\n  };\n  d3.geo.albers = function() {\n    var origin = [ -98, 38 ], parallels = [ 29.5, 45.5 ], scale = 1e3, translate = [ 480, 250 ], lng0, n, C, p0;\n    function albers(coordinates) {\n      var t = n * (d3_geo_radians * coordinates[0] - lng0), p = Math.sqrt(C - 2 * n * Math.sin(d3_geo_radians * coordinates[1])) / n;\n      return [ scale * p * Math.sin(t) + translate[0], scale * (p * Math.cos(t) - p0) + translate[1] ];\n    }\n    albers.invert = function(coordinates) {\n      var x = (coordinates[0] - translate[0]) / scale, y = (coordinates[1] - translate[1]) / scale, p0y = p0 + y, t = Math.atan2(x, p0y), p = Math.sqrt(x * x + p0y * p0y);\n      return [ (lng0 + t / n) / d3_geo_radians, Math.asin((C - p * p * n * n) / (2 * n)) / d3_geo_radians ];\n    };\n    function reload() {\n      var phi1 = d3_geo_radians * parallels[0], phi2 = d3_geo_radians * parallels[1], lat0 = d3_geo_radians * origin[1], s = Math.sin(phi1), c = Math.cos(phi1);\n      lng0 = d3_geo_radians * origin[0];\n      n = .5 * (s + Math.sin(phi2));\n      C = c * c + 2 * n * s;\n      p0 = Math.sqrt(C - 2 * n * Math.sin(lat0)) / n;\n      return albers;\n    }\n    albers.origin = function(x) {\n      if (!arguments.length) return origin;\n      origin = [ +x[0], +x[1] ];\n      return reload();\n    };\n    albers.parallels = function(x) {\n      if (!arguments.length) return parallels;\n      parallels = [ +x[0], +x[1] ];\n      return reload();\n    };\n    albers.scale = function(x) {\n      if (!arguments.length) return scale;\n      scale = +x;\n      return albers;\n    };\n    albers.translate = function(x) {\n      if (!arguments.length) return translate;\n      translate = [ +x[0], +x[1] ];\n      return albers;\n    };\n    return reload();\n  };\n  d3.geo.albersUsa = function() {\n    var lower48 = d3.geo.albers();\n    var alaska = d3.geo.albers().origin([ -160, 60 ]).parallels([ 55, 65 ]);\n    var hawaii = d3.geo.albers().origin([ -160, 20 ]).parallels([ 8, 18 ]);\n    var puertoRico = d3.geo.albers().origin([ -60, 10 ]).parallels([ 8, 18 ]);\n    function albersUsa(coordinates) {\n      var lon = coordinates[0], lat = coordinates[1];\n      return (lat > 50 ? alaska : lon < -140 ? hawaii : lat < 21 ? puertoRico : lower48)(coordinates);\n    }\n    albersUsa.scale = function(x) {\n      if (!arguments.length) return lower48.scale();\n      lower48.scale(x);\n      alaska.scale(x * .6);\n      hawaii.scale(x);\n      puertoRico.scale(x * 1.5);\n      return albersUsa.translate(lower48.translate());\n    };\n    albersUsa.translate = function(x) {\n      if (!arguments.length) return lower48.translate();\n      var dz = lower48.scale() / 1e3, dx = x[0], dy = x[1];\n      lower48.translate(x);\n      alaska.translate([ dx - 400 * dz, dy + 170 * dz ]);\n      hawaii.translate([ dx - 190 * dz, dy + 200 * dz ]);\n      puertoRico.translate([ dx + 580 * dz, dy + 430 * dz ]);\n      return albersUsa;\n    };\n    return albersUsa.scale(lower48.scale());\n  };\n  d3.geo.bonne = function() {\n    var scale = 200, translate = [ 480, 250 ], x0, y0, y1, c1;\n    function bonne(coordinates) {\n      var x = coordinates[0] * d3_geo_radians - x0, y = coordinates[1] * d3_geo_radians - y0;\n      if (y1) {\n        var p = c1 + y1 - y, E = x * Math.cos(y) / p;\n        x = p * Math.sin(E);\n        y = p * Math.cos(E) - c1;\n      } else {\n        x *= Math.cos(y);\n        y *= -1;\n      }\n      return [ scale * x + translate[0], scale * y + translate[1] ];\n    }\n    bonne.invert = function(coordinates) {\n      var x = (coordinates[0] - translate[0]) / scale, y = (coordinates[1] - translate[1]) / scale;\n      if (y1) {\n        var c = c1 + y, p = Math.sqrt(x * x + c * c);\n        y = c1 + y1 - p;\n        x = x0 + p * Math.atan2(x, c) / Math.cos(y);\n      } else {\n        y *= -1;\n        x /= Math.cos(y);\n      }\n      return [ x / d3_geo_radians, y / d3_geo_radians ];\n    };\n    bonne.parallel = function(x) {\n      if (!arguments.length) return y1 / d3_geo_radians;\n      c1 = 1 / Math.tan(y1 = x * d3_geo_radians);\n      return bonne;\n    };\n    bonne.origin = function(x) {\n      if (!arguments.length) return [ x0 / d3_geo_radians, y0 / d3_geo_radians ];\n      x0 = x[0] * d3_geo_radians;\n      y0 = x[1] * d3_geo_radians;\n      return bonne;\n    };\n    bonne.scale = function(x) {\n      if (!arguments.length) return scale;\n      scale = +x;\n      return bonne;\n    };\n    bonne.translate = function(x) {\n      if (!arguments.length) return translate;\n      translate = [ +x[0], +x[1] ];\n      return bonne;\n    };\n    return bonne.origin([ 0, 0 ]).parallel(45);\n  };\n  d3.geo.equirectangular = function() {\n    var scale = 500, translate = [ 480, 250 ];\n    function equirectangular(coordinates) {\n      var x = coordinates[0] / 360, y = -coordinates[1] / 360;\n      return [ scale * x + translate[0], scale * y + translate[1] ];\n    }\n    equirectangular.invert = function(coordinates) {\n      var x = (coordinates[0] - translate[0]) / scale, y = (coordinates[1] - translate[1]) / scale;\n      return [ 360 * x, -360 * y ];\n    };\n    equirectangular.scale = function(x) {\n      if (!arguments.length) return scale;\n      scale = +x;\n      return equirectangular;\n    };\n    equirectangular.translate = function(x) {\n      if (!arguments.length) return translate;\n      translate = [ +x[0], +x[1] ];\n      return equirectangular;\n    };\n    return equirectangular;\n  };\n  d3.geo.mercator = function() {\n    var scale = 500, translate = [ 480, 250 ];\n    function mercator(coordinates) {\n      var x = coordinates[0] / 360, y = -(Math.log(Math.tan(Math.PI / 4 + coordinates[1] * d3_geo_radians / 2)) / d3_geo_radians) / 360;\n      return [ scale * x + translate[0], scale * Math.max(-.5, Math.min(.5, y)) + translate[1] ];\n    }\n    mercator.invert = function(coordinates) {\n      var x = (coordinates[0] - translate[0]) / scale, y = (coordinates[1] - translate[1]) / scale;\n      return [ 360 * x, 2 * Math.atan(Math.exp(-360 * y * d3_geo_radians)) / d3_geo_radians - 90 ];\n    };\n    mercator.scale = function(x) {\n      if (!arguments.length) return scale;\n      scale = +x;\n      return mercator;\n    };\n    mercator.translate = function(x) {\n      if (!arguments.length) return translate;\n      translate = [ +x[0], +x[1] ];\n      return mercator;\n    };\n    return mercator;\n  };\n  function d3_geo_type(types, defaultValue) {\n    return function(object) {\n      return object && types.hasOwnProperty(object.type) ? types[object.type](object) : defaultValue;\n    };\n  }\n  d3.geo.path = function() {\n    var pointRadius = 4.5, pointCircle = d3_path_circle(pointRadius), projection = d3.geo.albersUsa(), buffer = [];\n    function path(d, i) {\n      if (typeof pointRadius === \"function\") pointCircle = d3_path_circle(pointRadius.apply(this, arguments));\n      pathType(d);\n      var result = buffer.length ? buffer.join(\"\") : null;\n      buffer = [];\n      return result;\n    }\n    function project(coordinates) {\n      return projection(coordinates).join(\",\");\n    }\n    var pathType = d3_geo_type({\n      FeatureCollection: function(o) {\n        var features = o.features, i = -1, n = features.length;\n        while (++i < n) buffer.push(pathType(features[i].geometry));\n      },\n      Feature: function(o) {\n        pathType(o.geometry);\n      },\n      Point: function(o) {\n        buffer.push(\"M\", project(o.coordinates), pointCircle);\n      },\n      MultiPoint: function(o) {\n        var coordinates = o.coordinates, i = -1, n = coordinates.length;\n        while (++i < n) buffer.push(\"M\", project(coordinates[i]), pointCircle);\n      },\n      LineString: function(o) {\n        var coordinates = o.coordinates, i = -1, n = coordinates.length;\n        buffer.push(\"M\");\n        while (++i < n) buffer.push(project(coordinates[i]), \"L\");\n        buffer.pop();\n      },\n      MultiLineString: function(o) {\n        var coordinates = o.coordinates, i = -1, n = coordinates.length, subcoordinates, j, m;\n        while (++i < n) {\n          subcoordinates = coordinates[i];\n          j = -1;\n          m = subcoordinates.length;\n          buffer.push(\"M\");\n          while (++j < m) buffer.push(project(subcoordinates[j]), \"L\");\n          buffer.pop();\n        }\n      },\n      Polygon: function(o) {\n        var coordinates = o.coordinates, i = -1, n = coordinates.length, subcoordinates, j, m;\n        while (++i < n) {\n          subcoordinates = coordinates[i];\n          j = -1;\n          if ((m = subcoordinates.length - 1) > 0) {\n            buffer.push(\"M\");\n            while (++j < m) buffer.push(project(subcoordinates[j]), \"L\");\n            buffer[buffer.length - 1] = \"Z\";\n          }\n        }\n      },\n      MultiPolygon: function(o) {\n        var coordinates = o.coordinates, i = -1, n = coordinates.length, subcoordinates, j, m, subsubcoordinates, k, p;\n        while (++i < n) {\n          subcoordinates = coordinates[i];\n          j = -1;\n          m = subcoordinates.length;\n          while (++j < m) {\n            subsubcoordinates = subcoordinates[j];\n            k = -1;\n            if ((p = subsubcoordinates.length - 1) > 0) {\n              buffer.push(\"M\");\n              while (++k < p) buffer.push(project(subsubcoordinates[k]), \"L\");\n              buffer[buffer.length - 1] = \"Z\";\n            }\n          }\n        }\n      },\n      GeometryCollection: function(o) {\n        var geometries = o.geometries, i = -1, n = geometries.length;\n        while (++i < n) buffer.push(pathType(geometries[i]));\n      }\n    });\n    var areaType = path.area = d3_geo_type({\n      FeatureCollection: function(o) {\n        var area = 0, features = o.features, i = -1, n = features.length;\n        while (++i < n) area += areaType(features[i]);\n        return area;\n      },\n      Feature: function(o) {\n        return areaType(o.geometry);\n      },\n      Polygon: function(o) {\n        return polygonArea(o.coordinates);\n      },\n      MultiPolygon: function(o) {\n        var sum = 0, coordinates = o.coordinates, i = -1, n = coordinates.length;\n        while (++i < n) sum += polygonArea(coordinates[i]);\n        return sum;\n      },\n      GeometryCollection: function(o) {\n        var sum = 0, geometries = o.geometries, i = -1, n = geometries.length;\n        while (++i < n) sum += areaType(geometries[i]);\n        return sum;\n      }\n    }, 0);\n    function polygonArea(coordinates) {\n      var sum = area(coordinates[0]), i = 0, n = coordinates.length;\n      while (++i < n) sum -= area(coordinates[i]);\n      return sum;\n    }\n    function polygonCentroid(coordinates) {\n      var polygon = d3.geom.polygon(coordinates[0].map(projection)), area = polygon.area(), centroid = polygon.centroid(area < 0 ? (area *= -1, 1) : -1), x = centroid[0], y = centroid[1], z = area, i = 0, n = coordinates.length;\n      while (++i < n) {\n        polygon = d3.geom.polygon(coordinates[i].map(projection));\n        area = polygon.area();\n        centroid = polygon.centroid(area < 0 ? (area *= -1, 1) : -1);\n        x -= centroid[0];\n        y -= centroid[1];\n        z -= area;\n      }\n      return [ x, y, 6 * z ];\n    }\n    var centroidType = path.centroid = d3_geo_type({\n      Feature: function(o) {\n        return centroidType(o.geometry);\n      },\n      Polygon: function(o) {\n        var centroid = polygonCentroid(o.coordinates);\n        return [ centroid[0] / centroid[2], centroid[1] / centroid[2] ];\n      },\n      MultiPolygon: function(o) {\n        var area = 0, coordinates = o.coordinates, centroid, x = 0, y = 0, z = 0, i = -1, n = coordinates.length;\n        while (++i < n) {\n          centroid = polygonCentroid(coordinates[i]);\n          x += centroid[0];\n          y += centroid[1];\n          z += centroid[2];\n        }\n        return [ x / z, y / z ];\n      }\n    });\n    function area(coordinates) {\n      return Math.abs(d3.geom.polygon(coordinates.map(projection)).area());\n    }\n    path.projection = function(x) {\n      projection = x;\n      return path;\n    };\n    path.pointRadius = function(x) {\n      if (typeof x === \"function\") pointRadius = x; else {\n        pointRadius = +x;\n        pointCircle = d3_path_circle(pointRadius);\n      }\n      return path;\n    };\n    return path;\n  };\n  function d3_path_circle(radius) {\n    return \"m0,\" + radius + \"a\" + radius + \",\" + radius + \" 0 1,1 0,\" + -2 * radius + \"a\" + radius + \",\" + radius + \" 0 1,1 0,\" + +2 * radius + \"z\";\n  }\n  d3.geo.bounds = function(feature) {\n    var left = Infinity, bottom = Infinity, right = -Infinity, top = -Infinity;\n    d3_geo_bounds(feature, function(x, y) {\n      if (x < left) left = x;\n      if (x > right) right = x;\n      if (y < bottom) bottom = y;\n      if (y > top) top = y;\n    });\n    return [ [ left, bottom ], [ right, top ] ];\n  };\n  function d3_geo_bounds(o, f) {\n    if (d3_geo_boundsTypes.hasOwnProperty(o.type)) d3_geo_boundsTypes[o.type](o, f);\n  }\n  var d3_geo_boundsTypes = {\n    Feature: d3_geo_boundsFeature,\n    FeatureCollection: d3_geo_boundsFeatureCollection,\n    GeometryCollection: d3_geo_boundsGeometryCollection,\n    LineString: d3_geo_boundsLineString,\n    MultiLineString: d3_geo_boundsMultiLineString,\n    MultiPoint: d3_geo_boundsLineString,\n    MultiPolygon: d3_geo_boundsMultiPolygon,\n    Point: d3_geo_boundsPoint,\n    Polygon: d3_geo_boundsPolygon\n  };\n  function d3_geo_boundsFeature(o, f) {\n    d3_geo_bounds(o.geometry, f);\n  }\n  function d3_geo_boundsFeatureCollection(o, f) {\n    for (var a = o.features, i = 0, n = a.length; i < n; i++) {\n      d3_geo_bounds(a[i].geometry, f);\n    }\n  }\n  function d3_geo_boundsGeometryCollection(o, f) {\n    for (var a = o.geometries, i = 0, n = a.length; i < n; i++) {\n      d3_geo_bounds(a[i], f);\n    }\n  }\n  function d3_geo_boundsLineString(o, f) {\n    for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {\n      f.apply(null, a[i]);\n    }\n  }\n  function d3_geo_boundsMultiLineString(o, f) {\n    for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {\n      for (var b = a[i], j = 0, m = b.length; j < m; j++) {\n        f.apply(null, b[j]);\n      }\n    }\n  }\n  function d3_geo_boundsMultiPolygon(o, f) {\n    for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {\n      for (var b = a[i][0], j = 0, m = b.length; j < m; j++) {\n        f.apply(null, b[j]);\n      }\n    }\n  }\n  function d3_geo_boundsPoint(o, f) {\n    f.apply(null, o.coordinates);\n  }\n  function d3_geo_boundsPolygon(o, f) {\n    for (var a = o.coordinates[0], i = 0, n = a.length; i < n; i++) {\n      f.apply(null, a[i]);\n    }\n  }\n  d3.geo.circle = function() {\n    var origin = [ 0, 0 ], degrees = 90 - .01, radians = degrees * d3_geo_radians, arc = d3.geo.greatArc().source(origin).target(d3_identity);\n    function circle() {}\n    function visible(point) {\n      return arc.distance(point) < radians;\n    }\n    circle.clip = function(d) {\n      if (typeof origin === \"function\") arc.source(origin.apply(this, arguments));\n      return clipType(d) || null;\n    };\n    var clipType = d3_geo_type({\n      FeatureCollection: function(o) {\n        var features = o.features.map(clipType).filter(d3_identity);\n        return features && (o = Object.create(o), o.features = features, o);\n      },\n      Feature: function(o) {\n        var geometry = clipType(o.geometry);\n        return geometry && (o = Object.create(o), o.geometry = geometry, o);\n      },\n      Point: function(o) {\n        return visible(o.coordinates) && o;\n      },\n      MultiPoint: function(o) {\n        var coordinates = o.coordinates.filter(visible);\n        return coordinates.length && {\n          type: o.type,\n          coordinates: coordinates\n        };\n      },\n      LineString: function(o) {\n        var coordinates = clip(o.coordinates);\n        return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o);\n      },\n      MultiLineString: function(o) {\n        var coordinates = o.coordinates.map(clip).filter(function(d) {\n          return d.length;\n        });\n        return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o);\n      },\n      Polygon: function(o) {\n        var coordinates = o.coordinates.map(clip);\n        return coordinates[0].length && (o = Object.create(o), o.coordinates = coordinates, o);\n      },\n      MultiPolygon: function(o) {\n        var coordinates = o.coordinates.map(function(d) {\n          return d.map(clip);\n        }).filter(function(d) {\n          return d[0].length;\n        });\n        return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o);\n      },\n      GeometryCollection: function(o) {\n        var geometries = o.geometries.map(clipType).filter(d3_identity);\n        return geometries.length && (o = Object.create(o), o.geometries = geometries, o);\n      }\n    });\n    function clip(coordinates) {\n      var i = -1, n = coordinates.length, clipped = [], p0, p1, p2, d0, d1;\n      while (++i < n) {\n        d1 = arc.distance(p2 = coordinates[i]);\n        if (d1 < radians) {\n          if (p1) clipped.push(d3_geo_greatArcInterpolate(p1, p2)((d0 - radians) / (d0 - d1)));\n          clipped.push(p2);\n          p0 = p1 = null;\n        } else {\n          p1 = p2;\n          if (!p0 && clipped.length) {\n            clipped.push(d3_geo_greatArcInterpolate(clipped[clipped.length - 1], p1)((radians - d0) / (d1 - d0)));\n            p0 = p1;\n          }\n        }\n        d0 = d1;\n      }\n      p0 = coordinates[0];\n      p1 = clipped[0];\n      if (p1 && p2[0] === p0[0] && p2[1] === p0[1] && !(p2[0] === p1[0] && p2[1] === p1[1])) {\n        clipped.push(p1);\n      }\n      return resample(clipped);\n    }\n    function resample(coordinates) {\n      var i = 0, n = coordinates.length, j, m, resampled = n ? [ coordinates[0] ] : coordinates, resamples, origin = arc.source();\n      while (++i < n) {\n        resamples = arc.source(coordinates[i - 1])(coordinates[i]).coordinates;\n        for (j = 0, m = resamples.length; ++j < m; ) resampled.push(resamples[j]);\n      }\n      arc.source(origin);\n      return resampled;\n    }\n    circle.origin = function(x) {\n      if (!arguments.length) return origin;\n      origin = x;\n      if (typeof origin !== \"function\") arc.source(origin);\n      return circle;\n    };\n    circle.angle = function(x) {\n      if (!arguments.length) return degrees;\n      radians = (degrees = +x) * d3_geo_radians;\n      return circle;\n    };\n    return d3.rebind(circle, arc, \"precision\");\n  };\n  d3.geo.greatArc = function() {\n    var source = d3_geo_greatArcSource, p0, target = d3_geo_greatArcTarget, p1, precision = 6 * d3_geo_radians, interpolate = d3_geo_greatArcInterpolator();\n    function greatArc() {\n      var d = greatArc.distance.apply(this, arguments), t = 0, dt = precision / d, coordinates = [ p0 ];\n      while ((t += dt) < 1) coordinates.push(interpolate(t));\n      coordinates.push(p1);\n      return {\n        type: \"LineString\",\n        coordinates: coordinates\n      };\n    }\n    greatArc.distance = function() {\n      if (typeof source === \"function\") interpolate.source(p0 = source.apply(this, arguments));\n      if (typeof target === \"function\") interpolate.target(p1 = target.apply(this, arguments));\n      return interpolate.distance();\n    };\n    greatArc.source = function(_) {\n      if (!arguments.length) return source;\n      source = _;\n      if (typeof source !== \"function\") interpolate.source(p0 = source);\n      return greatArc;\n    };\n    greatArc.target = function(_) {\n      if (!arguments.length) return target;\n      target = _;\n      if (typeof target !== \"function\") interpolate.target(p1 = target);\n      return greatArc;\n    };\n    greatArc.precision = function(_) {\n      if (!arguments.length) return precision / d3_geo_radians;\n      precision = _ * d3_geo_radians;\n      return greatArc;\n    };\n    return greatArc;\n  };\n  function d3_geo_greatArcSource(d) {\n    return d.source;\n  }\n  function d3_geo_greatArcTarget(d) {\n    return d.target;\n  }\n  function d3_geo_greatArcInterpolator() {\n    var x0, y0, cy0, sy0, kx0, ky0, x1, y1, cy1, sy1, kx1, ky1, d, k;\n    function interpolate(t) {\n      var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;\n      return [ Math.atan2(y, x) / d3_geo_radians, Math.atan2(z, Math.sqrt(x * x + y * y)) / d3_geo_radians ];\n    }\n    interpolate.distance = function() {\n      if (d == null) k = 1 / Math.sin(d = Math.acos(Math.max(-1, Math.min(1, sy0 * sy1 + cy0 * cy1 * Math.cos(x1 - x0)))));\n      return d;\n    };\n    interpolate.source = function(_) {\n      var cx0 = Math.cos(x0 = _[0] * d3_geo_radians), sx0 = Math.sin(x0);\n      cy0 = Math.cos(y0 = _[1] * d3_geo_radians);\n      sy0 = Math.sin(y0);\n      kx0 = cy0 * cx0;\n      ky0 = cy0 * sx0;\n      d = null;\n      return interpolate;\n    };\n    interpolate.target = function(_) {\n      var cx1 = Math.cos(x1 = _[0] * d3_geo_radians), sx1 = Math.sin(x1);\n      cy1 = Math.cos(y1 = _[1] * d3_geo_radians);\n      sy1 = Math.sin(y1);\n      kx1 = cy1 * cx1;\n      ky1 = cy1 * sx1;\n      d = null;\n      return interpolate;\n    };\n    return interpolate;\n  }\n  function d3_geo_greatArcInterpolate(a, b) {\n    var i = d3_geo_greatArcInterpolator().source(a).target(b);\n    i.distance();\n    return i;\n  }\n  d3.geo.greatCircle = d3.geo.circle;\n  d3.geom = {};\n  d3.geom.contour = function(grid, start) {\n    var s = start || d3_geom_contourStart(grid), c = [], x = s[0], y = s[1], dx = 0, dy = 0, pdx = NaN, pdy = NaN, i = 0;\n    do {\n      i = 0;\n      if (grid(x - 1, y - 1)) i += 1;\n      if (grid(x, y - 1)) i += 2;\n      if (grid(x - 1, y)) i += 4;\n      if (grid(x, y)) i += 8;\n      if (i === 6) {\n        dx = pdy === -1 ? -1 : 1;\n        dy = 0;\n      } else if (i === 9) {\n        dx = 0;\n        dy = pdx === 1 ? -1 : 1;\n      } else {\n        dx = d3_geom_contourDx[i];\n        dy = d3_geom_contourDy[i];\n      }\n      if (dx != pdx && dy != pdy) {\n        c.push([ x, y ]);\n        pdx = dx;\n        pdy = dy;\n      }\n      x += dx;\n      y += dy;\n    } while (s[0] != x || s[1] != y);\n    return c;\n  };\n  var d3_geom_contourDx = [ 1, 0, 1, 1, -1, 0, -1, 1, 0, 0, 0, 0, -1, 0, -1, NaN ], d3_geom_contourDy = [ 0, -1, 0, 0, 0, -1, 0, 0, 1, -1, 1, 1, 0, -1, 0, NaN ];\n  function d3_geom_contourStart(grid) {\n    var x = 0, y = 0;\n    while (true) {\n      if (grid(x, y)) {\n        return [ x, y ];\n      }\n      if (x === 0) {\n        x = y + 1;\n        y = 0;\n      } else {\n        x = x - 1;\n        y = y + 1;\n      }\n    }\n  }\n  d3.geom.hull = function(vertices) {\n    if (vertices.length < 3) return [];\n    var len = vertices.length, plen = len - 1, points = [], stack = [], i, j, h = 0, x1, y1, x2, y2, u, v, a, sp;\n    for (i = 1; i < len; ++i) {\n      if (vertices[i][1] < vertices[h][1]) {\n        h = i;\n      } else if (vertices[i][1] == vertices[h][1]) {\n        h = vertices[i][0] < vertices[h][0] ? i : h;\n      }\n    }\n    for (i = 0; i < len; ++i) {\n      if (i === h) continue;\n      y1 = vertices[i][1] - vertices[h][1];\n      x1 = vertices[i][0] - vertices[h][0];\n      points.push({\n        angle: Math.atan2(y1, x1),\n        index: i\n      });\n    }\n    points.sort(function(a, b) {\n      return a.angle - b.angle;\n    });\n    a = points[0].angle;\n    v = points[0].index;\n    u = 0;\n    for (i = 1; i < plen; ++i) {\n      j = points[i].index;\n      if (a == points[i].angle) {\n        x1 = vertices[v][0] - vertices[h][0];\n        y1 = vertices[v][1] - vertices[h][1];\n        x2 = vertices[j][0] - vertices[h][0];\n        y2 = vertices[j][1] - vertices[h][1];\n        if (x1 * x1 + y1 * y1 >= x2 * x2 + y2 * y2) {\n          points[i].index = -1;\n        } else {\n          points[u].index = -1;\n          a = points[i].angle;\n          u = i;\n          v = j;\n        }\n      } else {\n        a = points[i].angle;\n        u = i;\n        v = j;\n      }\n    }\n    stack.push(h);\n    for (i = 0, j = 0; i < 2; ++j) {\n      if (points[j].index !== -1) {\n        stack.push(points[j].index);\n        i++;\n      }\n    }\n    sp = stack.length;\n    for (; j < plen; ++j) {\n      if (points[j].index === -1) continue;\n      while (!d3_geom_hullCCW(stack[sp - 2], stack[sp - 1], points[j].index, vertices)) {\n        --sp;\n      }\n      stack[sp++] = points[j].index;\n    }\n    var poly = [];\n    for (i = 0; i < sp; ++i) {\n      poly.push(vertices[stack[i]]);\n    }\n    return poly;\n  };\n  function d3_geom_hullCCW(i1, i2, i3, v) {\n    var t, a, b, c, d, e, f;\n    t = v[i1];\n    a = t[0];\n    b = t[1];\n    t = v[i2];\n    c = t[0];\n    d = t[1];\n    t = v[i3];\n    e = t[0];\n    f = t[1];\n    return (f - b) * (c - a) - (d - b) * (e - a) > 0;\n  }\n  d3.geom.polygon = function(coordinates) {\n    coordinates.area = function() {\n      var i = 0, n = coordinates.length, a = coordinates[n - 1][0] * coordinates[0][1], b = coordinates[n - 1][1] * coordinates[0][0];\n      while (++i < n) {\n        a += coordinates[i - 1][0] * coordinates[i][1];\n        b += coordinates[i - 1][1] * coordinates[i][0];\n      }\n      return (b - a) * .5;\n    };\n    coordinates.centroid = function(k) {\n      var i = -1, n = coordinates.length, x = 0, y = 0, a, b = coordinates[n - 1], c;\n      if (!arguments.length) k = -1 / (6 * coordinates.area());\n      while (++i < n) {\n        a = b;\n        b = coordinates[i];\n        c = a[0] * b[1] - b[0] * a[1];\n        x += (a[0] + b[0]) * c;\n        y += (a[1] + b[1]) * c;\n      }\n      return [ x * k, y * k ];\n    };\n    coordinates.clip = function(subject) {\n      var input, i = -1, n = coordinates.length, j, m, a = coordinates[n - 1], b, c, d;\n      while (++i < n) {\n        input = subject.slice();\n        subject.length = 0;\n        b = coordinates[i];\n        c = input[(m = input.length) - 1];\n        j = -1;\n        while (++j < m) {\n          d = input[j];\n          if (d3_geom_polygonInside(d, a, b)) {\n            if (!d3_geom_polygonInside(c, a, b)) {\n              subject.push(d3_geom_polygonIntersect(c, d, a, b));\n            }\n            subject.push(d);\n          } else if (d3_geom_polygonInside(c, a, b)) {\n            subject.push(d3_geom_polygonIntersect(c, d, a, b));\n          }\n          c = d;\n        }\n        a = b;\n      }\n      return subject;\n    };\n    return coordinates;\n  };\n  function d3_geom_polygonInside(p, a, b) {\n    return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);\n  }\n  function d3_geom_polygonIntersect(c, d, a, b) {\n    var x1 = c[0], x2 = d[0], x3 = a[0], x4 = b[0], y1 = c[1], y2 = d[1], y3 = a[1], y4 = b[1], x13 = x1 - x3, x21 = x2 - x1, x43 = x4 - x3, y13 = y1 - y3, y21 = y2 - y1, y43 = y4 - y3, ua = (x43 * y13 - y43 * x13) / (y43 * x21 - x43 * y21);\n    return [ x1 + ua * x21, y1 + ua * y21 ];\n  }\n  d3.geom.voronoi = function(vertices) {\n    var polygons = vertices.map(function() {\n      return [];\n    });\n    d3_voronoi_tessellate(vertices, function(e) {\n      var s1, s2, x1, x2, y1, y2;\n      if (e.a === 1 && e.b >= 0) {\n        s1 = e.ep.r;\n        s2 = e.ep.l;\n      } else {\n        s1 = e.ep.l;\n        s2 = e.ep.r;\n      }\n      if (e.a === 1) {\n        y1 = s1 ? s1.y : -1e6;\n        x1 = e.c - e.b * y1;\n        y2 = s2 ? s2.y : 1e6;\n        x2 = e.c - e.b * y2;\n      } else {\n        x1 = s1 ? s1.x : -1e6;\n        y1 = e.c - e.a * x1;\n        x2 = s2 ? s2.x : 1e6;\n        y2 = e.c - e.a * x2;\n      }\n      var v1 = [ x1, y1 ], v2 = [ x2, y2 ];\n      polygons[e.region.l.index].push(v1, v2);\n      polygons[e.region.r.index].push(v1, v2);\n    });\n    return polygons.map(function(polygon, i) {\n      var cx = vertices[i][0], cy = vertices[i][1];\n      polygon.forEach(function(v) {\n        v.angle = Math.atan2(v[0] - cx, v[1] - cy);\n      });\n      return polygon.sort(function(a, b) {\n        return a.angle - b.angle;\n      }).filter(function(d, i) {\n        return !i || d.angle - polygon[i - 1].angle > 1e-10;\n      });\n    });\n  };\n  var d3_voronoi_opposite = {\n    l: \"r\",\n    r: \"l\"\n  };\n  function d3_voronoi_tessellate(vertices, callback) {\n    var Sites = {\n      list: vertices.map(function(v, i) {\n        return {\n          index: i,\n          x: v[0],\n          y: v[1]\n        };\n      }).sort(function(a, b) {\n        return a.y < b.y ? -1 : a.y > b.y ? 1 : a.x < b.x ? -1 : a.x > b.x ? 1 : 0;\n      }),\n      bottomSite: null\n    };\n    var EdgeList = {\n      list: [],\n      leftEnd: null,\n      rightEnd: null,\n      init: function() {\n        EdgeList.leftEnd = EdgeList.createHalfEdge(null, \"l\");\n        EdgeList.rightEnd = EdgeList.createHalfEdge(null, \"l\");\n        EdgeList.leftEnd.r = EdgeList.rightEnd;\n        EdgeList.rightEnd.l = EdgeList.leftEnd;\n        EdgeList.list.unshift(EdgeList.leftEnd, EdgeList.rightEnd);\n      },\n      createHalfEdge: function(edge, side) {\n        return {\n          edge: edge,\n          side: side,\n          vertex: null,\n          l: null,\n          r: null\n        };\n      },\n      insert: function(lb, he) {\n        he.l = lb;\n        he.r = lb.r;\n        lb.r.l = he;\n        lb.r = he;\n      },\n      leftBound: function(p) {\n        var he = EdgeList.leftEnd;\n        do {\n          he = he.r;\n        } while (he != EdgeList.rightEnd && Geom.rightOf(he, p));\n        he = he.l;\n        return he;\n      },\n      del: function(he) {\n        he.l.r = he.r;\n        he.r.l = he.l;\n        he.edge = null;\n      },\n      right: function(he) {\n        return he.r;\n      },\n      left: function(he) {\n        return he.l;\n      },\n      leftRegion: function(he) {\n        return he.edge == null ? Sites.bottomSite : he.edge.region[he.side];\n      },\n      rightRegion: function(he) {\n        return he.edge == null ? Sites.bottomSite : he.edge.region[d3_voronoi_opposite[he.side]];\n      }\n    };\n    var Geom = {\n      bisect: function(s1, s2) {\n        var newEdge = {\n          region: {\n            l: s1,\n            r: s2\n          },\n          ep: {\n            l: null,\n            r: null\n          }\n        };\n        var dx = s2.x - s1.x, dy = s2.y - s1.y, adx = dx > 0 ? dx : -dx, ady = dy > 0 ? dy : -dy;\n        newEdge.c = s1.x * dx + s1.y * dy + (dx * dx + dy * dy) * .5;\n        if (adx > ady) {\n          newEdge.a = 1;\n          newEdge.b = dy / dx;\n          newEdge.c /= dx;\n        } else {\n          newEdge.b = 1;\n          newEdge.a = dx / dy;\n          newEdge.c /= dy;\n        }\n        return newEdge;\n      },\n      intersect: function(el1, el2) {\n        var e1 = el1.edge, e2 = el2.edge;\n        if (!e1 || !e2 || e1.region.r == e2.region.r) {\n          return null;\n        }\n        var d = e1.a * e2.b - e1.b * e2.a;\n        if (Math.abs(d) < 1e-10) {\n          return null;\n        }\n        var xint = (e1.c * e2.b - e2.c * e1.b) / d, yint = (e2.c * e1.a - e1.c * e2.a) / d, e1r = e1.region.r, e2r = e2.region.r, el, e;\n        if (e1r.y < e2r.y || e1r.y == e2r.y && e1r.x < e2r.x) {\n          el = el1;\n          e = e1;\n        } else {\n          el = el2;\n          e = e2;\n        }\n        var rightOfSite = xint >= e.region.r.x;\n        if (rightOfSite && el.side === \"l\" || !rightOfSite && el.side === \"r\") {\n          return null;\n        }\n        return {\n          x: xint,\n          y: yint\n        };\n      },\n      rightOf: function(he, p) {\n        var e = he.edge, topsite = e.region.r, rightOfSite = p.x > topsite.x;\n        if (rightOfSite && he.side === \"l\") {\n          return 1;\n        }\n        if (!rightOfSite && he.side === \"r\") {\n          return 0;\n        }\n        if (e.a === 1) {\n          var dyp = p.y - topsite.y, dxp = p.x - topsite.x, fast = 0, above = 0;\n          if (!rightOfSite && e.b < 0 || rightOfSite && e.b >= 0) {\n            above = fast = dyp >= e.b * dxp;\n          } else {\n            above = p.x + p.y * e.b > e.c;\n            if (e.b < 0) {\n              above = !above;\n            }\n            if (!above) {\n              fast = 1;\n            }\n          }\n          if (!fast) {\n            var dxs = topsite.x - e.region.l.x;\n            above = e.b * (dxp * dxp - dyp * dyp) < dxs * dyp * (1 + 2 * dxp / dxs + e.b * e.b);\n            if (e.b < 0) {\n              above = !above;\n            }\n          }\n        } else {\n          var yl = e.c - e.a * p.x, t1 = p.y - yl, t2 = p.x - topsite.x, t3 = yl - topsite.y;\n          above = t1 * t1 > t2 * t2 + t3 * t3;\n        }\n        return he.side === \"l\" ? above : !above;\n      },\n      endPoint: function(edge, side, site) {\n        edge.ep[side] = site;\n        if (!edge.ep[d3_voronoi_opposite[side]]) return;\n        callback(edge);\n      },\n      distance: function(s, t) {\n        var dx = s.x - t.x, dy = s.y - t.y;\n        return Math.sqrt(dx * dx + dy * dy);\n      }\n    };\n    var EventQueue = {\n      list: [],\n      insert: function(he, site, offset) {\n        he.vertex = site;\n        he.ystar = site.y + offset;\n        for (var i = 0, list = EventQueue.list, l = list.length; i < l; i++) {\n          var next = list[i];\n          if (he.ystar > next.ystar || he.ystar == next.ystar && site.x > next.vertex.x) {\n            continue;\n          } else {\n            break;\n          }\n        }\n        list.splice(i, 0, he);\n      },\n      del: function(he) {\n        for (var i = 0, ls = EventQueue.list, l = ls.length; i < l && ls[i] != he; ++i) {}\n        ls.splice(i, 1);\n      },\n      empty: function() {\n        return EventQueue.list.length === 0;\n      },\n      nextEvent: function(he) {\n        for (var i = 0, ls = EventQueue.list, l = ls.length; i < l; ++i) {\n          if (ls[i] == he) return ls[i + 1];\n        }\n        return null;\n      },\n      min: function() {\n        var elem = EventQueue.list[0];\n        return {\n          x: elem.vertex.x,\n          y: elem.ystar\n        };\n      },\n      extractMin: function() {\n        return EventQueue.list.shift();\n      }\n    };\n    EdgeList.init();\n    Sites.bottomSite = Sites.list.shift();\n    var newSite = Sites.list.shift(), newIntStar;\n    var lbnd, rbnd, llbnd, rrbnd, bisector;\n    var bot, top, temp, p, v;\n    var e, pm;\n    while (true) {\n      if (!EventQueue.empty()) {\n        newIntStar = EventQueue.min();\n      }\n      if (newSite && (EventQueue.empty() || newSite.y < newIntStar.y || newSite.y == newIntStar.y && newSite.x < newIntStar.x)) {\n        lbnd = EdgeList.leftBound(newSite);\n        rbnd = EdgeList.right(lbnd);\n        bot = EdgeList.rightRegion(lbnd);\n        e = Geom.bisect(bot, newSite);\n        bisector = EdgeList.createHalfEdge(e, \"l\");\n        EdgeList.insert(lbnd, bisector);\n        p = Geom.intersect(lbnd, bisector);\n        if (p) {\n          EventQueue.del(lbnd);\n          EventQueue.insert(lbnd, p, Geom.distance(p, newSite));\n        }\n        lbnd = bisector;\n        bisector = EdgeList.createHalfEdge(e, \"r\");\n        EdgeList.insert(lbnd, bisector);\n        p = Geom.intersect(bisector, rbnd);\n        if (p) {\n          EventQueue.insert(bisector, p, Geom.distance(p, newSite));\n        }\n        newSite = Sites.list.shift();\n      } else if (!EventQueue.empty()) {\n        lbnd = EventQueue.extractMin();\n        llbnd = EdgeList.left(lbnd);\n        rbnd = EdgeList.right(lbnd);\n        rrbnd = EdgeList.right(rbnd);\n        bot = EdgeList.leftRegion(lbnd);\n        top = EdgeList.rightRegion(rbnd);\n        v = lbnd.vertex;\n        Geom.endPoint(lbnd.edge, lbnd.side, v);\n        Geom.endPoint(rbnd.edge, rbnd.side, v);\n        EdgeList.del(lbnd);\n        EventQueue.del(rbnd);\n        EdgeList.del(rbnd);\n        pm = \"l\";\n        if (bot.y > top.y) {\n          temp = bot;\n          bot = top;\n          top = temp;\n          pm = \"r\";\n        }\n        e = Geom.bisect(bot, top);\n        bisector = EdgeList.createHalfEdge(e, pm);\n        EdgeList.insert(llbnd, bisector);\n        Geom.endPoint(e, d3_voronoi_opposite[pm], v);\n        p = Geom.intersect(llbnd, bisector);\n        if (p) {\n          EventQueue.del(llbnd);\n          EventQueue.insert(llbnd, p, Geom.distance(p, bot));\n        }\n        p = Geom.intersect(bisector, rrbnd);\n        if (p) {\n          EventQueue.insert(bisector, p, Geom.distance(p, bot));\n        }\n      } else {\n        break;\n      }\n    }\n    for (lbnd = EdgeList.right(EdgeList.leftEnd); lbnd != EdgeList.rightEnd; lbnd = EdgeList.right(lbnd)) {\n      callback(lbnd.edge);\n    }\n  }\n  d3.geom.delaunay = function(vertices) {\n    var edges = vertices.map(function() {\n      return [];\n    }), triangles = [];\n    d3_voronoi_tessellate(vertices, function(e) {\n      edges[e.region.l.index].push(vertices[e.region.r.index]);\n    });\n    edges.forEach(function(edge, i) {\n      var v = vertices[i], cx = v[0], cy = v[1];\n      edge.forEach(function(v) {\n        v.angle = Math.atan2(v[0] - cx, v[1] - cy);\n      });\n      edge.sort(function(a, b) {\n        return a.angle - b.angle;\n      });\n      for (var j = 0, m = edge.length - 1; j < m; j++) {\n        triangles.push([ v, edge[j], edge[j + 1] ]);\n      }\n    });\n    return triangles;\n  };\n  d3.geom.quadtree = function(points, x1, y1, x2, y2) {\n    var p, i = -1, n = points.length;\n    if (n && isNaN(points[0].x)) points = points.map(d3_geom_quadtreePoint);\n    if (arguments.length < 5) {\n      if (arguments.length === 3) {\n        y2 = x2 = y1;\n        y1 = x1;\n      } else {\n        x1 = y1 = Infinity;\n        x2 = y2 = -Infinity;\n        while (++i < n) {\n          p = points[i];\n          if (p.x < x1) x1 = p.x;\n          if (p.y < y1) y1 = p.y;\n          if (p.x > x2) x2 = p.x;\n          if (p.y > y2) y2 = p.y;\n        }\n        var dx = x2 - x1, dy = y2 - y1;\n        if (dx > dy) y2 = y1 + dx; else x2 = x1 + dy;\n      }\n    }\n    function insert(n, p, x1, y1, x2, y2) {\n      if (isNaN(p.x) || isNaN(p.y)) return;\n      if (n.leaf) {\n        var v = n.point;\n        if (v) {\n          if (Math.abs(v.x - p.x) + Math.abs(v.y - p.y) < .01) {\n            insertChild(n, p, x1, y1, x2, y2);\n          } else {\n            n.point = null;\n            insertChild(n, v, x1, y1, x2, y2);\n            insertChild(n, p, x1, y1, x2, y2);\n          }\n        } else {\n          n.point = p;\n        }\n      } else {\n        insertChild(n, p, x1, y1, x2, y2);\n      }\n    }\n    function insertChild(n, p, x1, y1, x2, y2) {\n      var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = p.x >= sx, bottom = p.y >= sy, i = (bottom << 1) + right;\n      n.leaf = false;\n      n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());\n      if (right) x1 = sx; else x2 = sx;\n      if (bottom) y1 = sy; else y2 = sy;\n      insert(n, p, x1, y1, x2, y2);\n    }\n    var root = d3_geom_quadtreeNode();\n    root.add = function(p) {\n      insert(root, p, x1, y1, x2, y2);\n    };\n    root.visit = function(f) {\n      d3_geom_quadtreeVisit(f, root, x1, y1, x2, y2);\n    };\n    points.forEach(root.add);\n    return root;\n  };\n  function d3_geom_quadtreeNode() {\n    return {\n      leaf: true,\n      nodes: [],\n      point: null\n    };\n  }\n  function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {\n    if (!f(node, x1, y1, x2, y2)) {\n      var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;\n      if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);\n      if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);\n      if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);\n      if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);\n    }\n  }\n  function d3_geom_quadtreePoint(p) {\n    return {\n      x: p[0],\n      y: p[1]\n    };\n  }\n  d3.time = {};\n  var d3_time = Date, d3_time_daySymbols = [ \"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\" ];\n  function d3_time_utc() {\n    this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]);\n  }\n  d3_time_utc.prototype = {\n    getDate: function() {\n      return this._.getUTCDate();\n    },\n    getDay: function() {\n      return this._.getUTCDay();\n    },\n    getFullYear: function() {\n      return this._.getUTCFullYear();\n    },\n    getHours: function() {\n      return this._.getUTCHours();\n    },\n    getMilliseconds: function() {\n      return this._.getUTCMilliseconds();\n    },\n    getMinutes: function() {\n      return this._.getUTCMinutes();\n    },\n    getMonth: function() {\n      return this._.getUTCMonth();\n    },\n    getSeconds: function() {\n      return this._.getUTCSeconds();\n    },\n    getTime: function() {\n      return this._.getTime();\n    },\n    getTimezoneOffset: function() {\n      return 0;\n    },\n    valueOf: function() {\n      return this._.valueOf();\n    },\n    setDate: function() {\n      d3_time_prototype.setUTCDate.apply(this._, arguments);\n    },\n    setDay: function() {\n      d3_time_prototype.setUTCDay.apply(this._, arguments);\n    },\n    setFullYear: function() {\n      d3_time_prototype.setUTCFullYear.apply(this._, arguments);\n    },\n    setHours: function() {\n      d3_time_prototype.setUTCHours.apply(this._, arguments);\n    },\n    setMilliseconds: function() {\n      d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);\n    },\n    setMinutes: function() {\n      d3_time_prototype.setUTCMinutes.apply(this._, arguments);\n    },\n    setMonth: function() {\n      d3_time_prototype.setUTCMonth.apply(this._, arguments);\n    },\n    setSeconds: function() {\n      d3_time_prototype.setUTCSeconds.apply(this._, arguments);\n    },\n    setTime: function() {\n      d3_time_prototype.setTime.apply(this._, arguments);\n    }\n  };\n  var d3_time_prototype = Date.prototype;\n  var d3_time_formatDateTime = \"%a %b %e %H:%M:%S %Y\", d3_time_formatDate = \"%m/%d/%y\", d3_time_formatTime = \"%H:%M:%S\";\n  var d3_time_days = d3_time_daySymbols, d3_time_dayAbbreviations = d3_time_days.map(d3_time_formatAbbreviate), d3_time_months = [ \"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\" ], d3_time_monthAbbreviations = d3_time_months.map(d3_time_formatAbbreviate);\n  function d3_time_formatAbbreviate(name) {\n    return name.substring(0, 3);\n  }\n  d3.time.format = function(template) {\n    var n = template.length;\n    function format(date) {\n      var string = [], i = -1, j = 0, c, f;\n      while (++i < n) {\n        if (template.charCodeAt(i) == 37) {\n          string.push(template.substring(j, i), (f = d3_time_formats[c = template.charAt(++i)]) ? f(date) : c);\n          j = i + 1;\n        }\n      }\n      string.push(template.substring(j, i));\n      return string.join(\"\");\n    }\n    format.parse = function(string) {\n      var d = {\n        y: 1900,\n        m: 0,\n        d: 1,\n        H: 0,\n        M: 0,\n        S: 0,\n        L: 0\n      }, i = d3_time_parse(d, template, string, 0);\n      if (i != string.length) return null;\n      if (\"p\" in d) d.H = d.H % 12 + d.p * 12;\n      var date = new d3_time;\n      date.setFullYear(d.y, d.m, d.d);\n      date.setHours(d.H, d.M, d.S, d.L);\n      return date;\n    };\n    format.toString = function() {\n      return template;\n    };\n    return format;\n  };\n  function d3_time_parse(date, template, string, j) {\n    var c, p, i = 0, n = template.length, m = string.length;\n    while (i < n) {\n      if (j >= m) return -1;\n      c = template.charCodeAt(i++);\n      if (c == 37) {\n        p = d3_time_parsers[template.charAt(i++)];\n        if (!p || (j = p(date, string, j)) < 0) return -1;\n      } else if (c != string.charCodeAt(j++)) {\n        return -1;\n      }\n    }\n    return j;\n  }\n  function d3_time_formatRe(names) {\n    return new RegExp(\"^(?:\" + names.map(d3.requote).join(\"|\") + \")\", \"i\");\n  }\n  function d3_time_formatLookup(names) {\n    var map = new d3_Map, i = -1, n = names.length;\n    while (++i < n) map.set(names[i].toLowerCase(), i);\n    return map;\n  }\n  var d3_time_zfill2 = d3.format(\"02d\"), d3_time_zfill3 = d3.format(\"03d\"), d3_time_zfill4 = d3.format(\"04d\"), d3_time_sfill2 = d3.format(\"2d\");\n  var d3_time_dayRe = d3_time_formatRe(d3_time_days), d3_time_dayAbbrevRe = d3_time_formatRe(d3_time_dayAbbreviations), d3_time_monthRe = d3_time_formatRe(d3_time_months), d3_time_monthLookup = d3_time_formatLookup(d3_time_months), d3_time_monthAbbrevRe = d3_time_formatRe(d3_time_monthAbbreviations), d3_time_monthAbbrevLookup = d3_time_formatLookup(d3_time_monthAbbreviations);\n  var d3_time_formats = {\n    a: function(d) {\n      return d3_time_dayAbbreviations[d.getDay()];\n    },\n    A: function(d) {\n      return d3_time_days[d.getDay()];\n    },\n    b: function(d) {\n      return d3_time_monthAbbreviations[d.getMonth()];\n    },\n    B: function(d) {\n      return d3_time_months[d.getMonth()];\n    },\n    c: d3.time.format(d3_time_formatDateTime),\n    d: function(d) {\n      return d3_time_zfill2(d.getDate());\n    },\n    e: function(d) {\n      return d3_time_sfill2(d.getDate());\n    },\n    H: function(d) {\n      return d3_time_zfill2(d.getHours());\n    },\n    I: function(d) {\n      return d3_time_zfill2(d.getHours() % 12 || 12);\n    },\n    j: function(d) {\n      return d3_time_zfill3(1 + d3.time.dayOfYear(d));\n    },\n    L: function(d) {\n      return d3_time_zfill3(d.getMilliseconds());\n    },\n    m: function(d) {\n      return d3_time_zfill2(d.getMonth() + 1);\n    },\n    M: function(d) {\n      return d3_time_zfill2(d.getMinutes());\n    },\n    p: function(d) {\n      return d.getHours() >= 12 ? \"PM\" : \"AM\";\n    },\n    S: function(d) {\n      return d3_time_zfill2(d.getSeconds());\n    },\n    U: function(d) {\n      return d3_time_zfill2(d3.time.sundayOfYear(d));\n    },\n    w: function(d) {\n      return d.getDay();\n    },\n    W: function(d) {\n      return d3_time_zfill2(d3.time.mondayOfYear(d));\n    },\n    x: d3.time.format(d3_time_formatDate),\n    X: d3.time.format(d3_time_formatTime),\n    y: function(d) {\n      return d3_time_zfill2(d.getFullYear() % 100);\n    },\n    Y: function(d) {\n      return d3_time_zfill4(d.getFullYear() % 1e4);\n    },\n    Z: d3_time_zone,\n    \"%\": function(d) {\n      return \"%\";\n    }\n  };\n  var d3_time_parsers = {\n    a: d3_time_parseWeekdayAbbrev,\n    A: d3_time_parseWeekday,\n    b: d3_time_parseMonthAbbrev,\n    B: d3_time_parseMonth,\n    c: d3_time_parseLocaleFull,\n    d: d3_time_parseDay,\n    e: d3_time_parseDay,\n    H: d3_time_parseHour24,\n    I: d3_time_parseHour24,\n    L: d3_time_parseMilliseconds,\n    m: d3_time_parseMonthNumber,\n    M: d3_time_parseMinutes,\n    p: d3_time_parseAmPm,\n    S: d3_time_parseSeconds,\n    x: d3_time_parseLocaleDate,\n    X: d3_time_parseLocaleTime,\n    y: d3_time_parseYear,\n    Y: d3_time_parseFullYear\n  };\n  function d3_time_parseWeekdayAbbrev(date, string, i) {\n    d3_time_dayAbbrevRe.lastIndex = 0;\n    var n = d3_time_dayAbbrevRe.exec(string.substring(i));\n    return n ? i += n[0].length : -1;\n  }\n  function d3_time_parseWeekday(date, string, i) {\n    d3_time_dayRe.lastIndex = 0;\n    var n = d3_time_dayRe.exec(string.substring(i));\n    return n ? i += n[0].length : -1;\n  }\n  function d3_time_parseMonthAbbrev(date, string, i) {\n    d3_time_monthAbbrevRe.lastIndex = 0;\n    var n = d3_time_monthAbbrevRe.exec(string.substring(i));\n    return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i += n[0].length) : -1;\n  }\n  function d3_time_parseMonth(date, string, i) {\n    d3_time_monthRe.lastIndex = 0;\n    var n = d3_time_monthRe.exec(string.substring(i));\n    return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i += n[0].length) : -1;\n  }\n  function d3_time_parseLocaleFull(date, string, i) {\n    return d3_time_parse(date, d3_time_formats.c.toString(), string, i);\n  }\n  function d3_time_parseLocaleDate(date, string, i) {\n    return d3_time_parse(date, d3_time_formats.x.toString(), string, i);\n  }\n  function d3_time_parseLocaleTime(date, string, i) {\n    return d3_time_parse(date, d3_time_formats.X.toString(), string, i);\n  }\n  function d3_time_parseFullYear(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 4));\n    return n ? (date.y = +n[0], i += n[0].length) : -1;\n  }\n  function d3_time_parseYear(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 2));\n    return n ? (date.y = d3_time_expandYear(+n[0]), i += n[0].length) : -1;\n  }\n  function d3_time_expandYear(d) {\n    return d + (d > 68 ? 1900 : 2e3);\n  }\n  function d3_time_parseMonthNumber(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 2));\n    return n ? (date.m = n[0] - 1, i += n[0].length) : -1;\n  }\n  function d3_time_parseDay(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 2));\n    return n ? (date.d = +n[0], i += n[0].length) : -1;\n  }\n  function d3_time_parseHour24(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 2));\n    return n ? (date.H = +n[0], i += n[0].length) : -1;\n  }\n  function d3_time_parseMinutes(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 2));\n    return n ? (date.M = +n[0], i += n[0].length) : -1;\n  }\n  function d3_time_parseSeconds(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 2));\n    return n ? (date.S = +n[0], i += n[0].length) : -1;\n  }\n  function d3_time_parseMilliseconds(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 3));\n    return n ? (date.L = +n[0], i += n[0].length) : -1;\n  }\n  var d3_time_numberRe = /^\\s*\\d+/;\n  function d3_time_parseAmPm(date, string, i) {\n    var n = d3_time_amPmLookup.get(string.substring(i, i += 2).toLowerCase());\n    return n == null ? -1 : (date.p = n, i);\n  }\n  var d3_time_amPmLookup = d3.map({\n    am: 0,\n    pm: 1\n  });\n  function d3_time_zone(d) {\n    var z = d.getTimezoneOffset(), zs = z > 0 ? \"-\" : \"+\", zh = ~~(Math.abs(z) / 60), zm = Math.abs(z) % 60;\n    return zs + d3_time_zfill2(zh) + d3_time_zfill2(zm);\n  }\n  d3.time.format.utc = function(template) {\n    var local = d3.time.format(template);\n    function format(date) {\n      try {\n        d3_time = d3_time_utc;\n        var utc = new d3_time;\n        utc._ = date;\n        return local(utc);\n      } finally {\n        d3_time = Date;\n      }\n    }\n    format.parse = function(string) {\n      try {\n        d3_time = d3_time_utc;\n        var date = local.parse(string);\n        return date && date._;\n      } finally {\n        d3_time = Date;\n      }\n    };\n    format.toString = local.toString;\n    return format;\n  };\n  var d3_time_formatIso = d3.time.format.utc(\"%Y-%m-%dT%H:%M:%S.%LZ\");\n  d3.time.format.iso = Date.prototype.toISOString ? d3_time_formatIsoNative : d3_time_formatIso;\n  function d3_time_formatIsoNative(date) {\n    return date.toISOString();\n  }\n  d3_time_formatIsoNative.parse = function(string) {\n    var date = new Date(string);\n    return isNaN(date) ? null : date;\n  };\n  d3_time_formatIsoNative.toString = d3_time_formatIso.toString;\n  function d3_time_interval(local, step, number) {\n    function round(date) {\n      var d0 = local(date), d1 = offset(d0, 1);\n      return date - d0 < d1 - date ? d0 : d1;\n    }\n    function ceil(date) {\n      step(date = local(new d3_time(date - 1)), 1);\n      return date;\n    }\n    function offset(date, k) {\n      step(date = new d3_time(+date), k);\n      return date;\n    }\n    function range(t0, t1, dt) {\n      var time = ceil(t0), times = [];\n      if (dt > 1) {\n        while (time < t1) {\n          if (!(number(time) % dt)) times.push(new Date(+time));\n          step(time, 1);\n        }\n      } else {\n        while (time < t1) times.push(new Date(+time)), step(time, 1);\n      }\n      return times;\n    }\n    function range_utc(t0, t1, dt) {\n      try {\n        d3_time = d3_time_utc;\n        var utc = new d3_time_utc;\n        utc._ = t0;\n        return range(utc, t1, dt);\n      } finally {\n        d3_time = Date;\n      }\n    }\n    local.floor = local;\n    local.round = round;\n    local.ceil = ceil;\n    local.offset = offset;\n    local.range = range;\n    var utc = local.utc = d3_time_interval_utc(local);\n    utc.floor = utc;\n    utc.round = d3_time_interval_utc(round);\n    utc.ceil = d3_time_interval_utc(ceil);\n    utc.offset = d3_time_interval_utc(offset);\n    utc.range = range_utc;\n    return local;\n  }\n  function d3_time_interval_utc(method) {\n    return function(date, k) {\n      try {\n        d3_time = d3_time_utc;\n        var utc = new d3_time_utc;\n        utc._ = date;\n        return method(utc, k)._;\n      } finally {\n        d3_time = Date;\n      }\n    };\n  }\n  d3.time.second = d3_time_interval(function(date) {\n    return new d3_time(Math.floor(date / 1e3) * 1e3);\n  }, function(date, offset) {\n    date.setTime(date.getTime() + Math.floor(offset) * 1e3);\n  }, function(date) {\n    return date.getSeconds();\n  });\n  d3.time.seconds = d3.time.second.range;\n  d3.time.seconds.utc = d3.time.second.utc.range;\n  d3.time.minute = d3_time_interval(function(date) {\n    return new d3_time(Math.floor(date / 6e4) * 6e4);\n  }, function(date, offset) {\n    date.setTime(date.getTime() + Math.floor(offset) * 6e4);\n  }, function(date) {\n    return date.getMinutes();\n  });\n  d3.time.minutes = d3.time.minute.range;\n  d3.time.minutes.utc = d3.time.minute.utc.range;\n  d3.time.hour = d3_time_interval(function(date) {\n    var timezone = date.getTimezoneOffset() / 60;\n    return new d3_time((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);\n  }, function(date, offset) {\n    date.setTime(date.getTime() + Math.floor(offset) * 36e5);\n  }, function(date) {\n    return date.getHours();\n  });\n  d3.time.hours = d3.time.hour.range;\n  d3.time.hours.utc = d3.time.hour.utc.range;\n  d3.time.day = d3_time_interval(function(date) {\n    var day = new d3_time(0, date.getMonth(), date.getDate());\n    day.setFullYear(date.getFullYear());\n    return day;\n  }, function(date, offset) {\n    date.setDate(date.getDate() + offset);\n  }, function(date) {\n    return date.getDate() - 1;\n  });\n  d3.time.days = d3.time.day.range;\n  d3.time.days.utc = d3.time.day.utc.range;\n  d3.time.dayOfYear = function(date) {\n    var year = d3.time.year(date);\n    return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);\n  };\n  d3_time_daySymbols.forEach(function(day, i) {\n    day = day.toLowerCase();\n    i = 7 - i;\n    var interval = d3.time[day] = d3_time_interval(function(date) {\n      (date = d3.time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);\n      return date;\n    }, function(date, offset) {\n      date.setDate(date.getDate() + Math.floor(offset) * 7);\n    }, function(date) {\n      var day = d3.time.year(date).getDay();\n      return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);\n    });\n    d3.time[day + \"s\"] = interval.range;\n    d3.time[day + \"s\"].utc = interval.utc.range;\n    d3.time[day + \"OfYear\"] = function(date) {\n      var day = d3.time.year(date).getDay();\n      return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7);\n    };\n  });\n  d3.time.week = d3.time.sunday;\n  d3.time.weeks = d3.time.sunday.range;\n  d3.time.weeks.utc = d3.time.sunday.utc.range;\n  d3.time.weekOfYear = d3.time.sundayOfYear;\n  d3.time.month = d3_time_interval(function(date) {\n    date = d3.time.day(date);\n    date.setDate(1);\n    return date;\n  }, function(date, offset) {\n    date.setMonth(date.getMonth() + offset);\n  }, function(date) {\n    return date.getMonth();\n  });\n  d3.time.months = d3.time.month.range;\n  d3.time.months.utc = d3.time.month.utc.range;\n  d3.time.year = d3_time_interval(function(date) {\n    date = d3.time.day(date);\n    date.setMonth(0, 1);\n    return date;\n  }, function(date, offset) {\n    date.setFullYear(date.getFullYear() + offset);\n  }, function(date) {\n    return date.getFullYear();\n  });\n  d3.time.years = d3.time.year.range;\n  d3.time.years.utc = d3.time.year.utc.range;\n  function d3_time_scale(linear, methods, format) {\n    function scale(x) {\n      return linear(x);\n    }\n    scale.invert = function(x) {\n      return d3_time_scaleDate(linear.invert(x));\n    };\n    scale.domain = function(x) {\n      if (!arguments.length) return linear.domain().map(d3_time_scaleDate);\n      linear.domain(x);\n      return scale;\n    };\n    scale.nice = function(m) {\n      return scale.domain(d3_scale_nice(scale.domain(), function() {\n        return m;\n      }));\n    };\n    scale.ticks = function(m, k) {\n      var extent = d3_time_scaleExtent(scale.domain());\n      if (typeof m !== \"function\") {\n        var span = extent[1] - extent[0], target = span / m, i = d3.bisect(d3_time_scaleSteps, target);\n        if (i == d3_time_scaleSteps.length) return methods.year(extent, m);\n        if (!i) return linear.ticks(m).map(d3_time_scaleDate);\n        if (Math.log(target / d3_time_scaleSteps[i - 1]) < Math.log(d3_time_scaleSteps[i] / target)) --i;\n        m = methods[i];\n        k = m[1];\n        m = m[0].range;\n      }\n      return m(extent[0], new Date(+extent[1] + 1), k);\n    };\n    scale.tickFormat = function() {\n      return format;\n    };\n    scale.copy = function() {\n      return d3_time_scale(linear.copy(), methods, format);\n    };\n    return d3.rebind(scale, linear, \"range\", \"rangeRound\", \"interpolate\", \"clamp\");\n  }\n  function d3_time_scaleExtent(domain) {\n    var start = domain[0], stop = domain[domain.length - 1];\n    return start < stop ? [ start, stop ] : [ stop, start ];\n  }\n  function d3_time_scaleDate(t) {\n    return new Date(t);\n  }\n  function d3_time_scaleFormat(formats) {\n    return function(date) {\n      var i = formats.length - 1, f = formats[i];\n      while (!f[1](date)) f = formats[--i];\n      return f[0](date);\n    };\n  }\n  function d3_time_scaleSetYear(y) {\n    var d = new Date(y, 0, 1);\n    d.setFullYear(y);\n    return d;\n  }\n  function d3_time_scaleGetYear(d) {\n    var y = d.getFullYear(), d0 = d3_time_scaleSetYear(y), d1 = d3_time_scaleSetYear(y + 1);\n    return y + (d - d0) / (d1 - d0);\n  }\n  var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ];\n  var d3_time_scaleLocalMethods = [ [ d3.time.second, 1 ], [ d3.time.second, 5 ], [ d3.time.second, 15 ], [ d3.time.second, 30 ], [ d3.time.minute, 1 ], [ d3.time.minute, 5 ], [ d3.time.minute, 15 ], [ d3.time.minute, 30 ], [ d3.time.hour, 1 ], [ d3.time.hour, 3 ], [ d3.time.hour, 6 ], [ d3.time.hour, 12 ], [ d3.time.day, 1 ], [ d3.time.day, 2 ], [ d3.time.week, 1 ], [ d3.time.month, 1 ], [ d3.time.month, 3 ], [ d3.time.year, 1 ] ];\n  var d3_time_scaleLocalFormats = [ [ d3.time.format(\"%Y\"), function(d) {\n    return true;\n  } ], [ d3.time.format(\"%B\"), function(d) {\n    return d.getMonth();\n  } ], [ d3.time.format(\"%b %d\"), function(d) {\n    return d.getDate() != 1;\n  } ], [ d3.time.format(\"%a %d\"), function(d) {\n    return d.getDay() && d.getDate() != 1;\n  } ], [ d3.time.format(\"%I %p\"), function(d) {\n    return d.getHours();\n  } ], [ d3.time.format(\"%I:%M\"), function(d) {\n    return d.getMinutes();\n  } ], [ d3.time.format(\":%S\"), function(d) {\n    return d.getSeconds();\n  } ], [ d3.time.format(\".%L\"), function(d) {\n    return d.getMilliseconds();\n  } ] ];\n  var d3_time_scaleLinear = d3.scale.linear(), d3_time_scaleLocalFormat = d3_time_scaleFormat(d3_time_scaleLocalFormats);\n  d3_time_scaleLocalMethods.year = function(extent, m) {\n    return d3_time_scaleLinear.domain(extent.map(d3_time_scaleGetYear)).ticks(m).map(d3_time_scaleSetYear);\n  };\n  d3.time.scale = function() {\n    return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);\n  };\n  var d3_time_scaleUTCMethods = d3_time_scaleLocalMethods.map(function(m) {\n    return [ m[0].utc, m[1] ];\n  });\n  var d3_time_scaleUTCFormats = [ [ d3.time.format.utc(\"%Y\"), function(d) {\n    return true;\n  } ], [ d3.time.format.utc(\"%B\"), function(d) {\n    return d.getUTCMonth();\n  } ], [ d3.time.format.utc(\"%b %d\"), function(d) {\n    return d.getUTCDate() != 1;\n  } ], [ d3.time.format.utc(\"%a %d\"), function(d) {\n    return d.getUTCDay() && d.getUTCDate() != 1;\n  } ], [ d3.time.format.utc(\"%I %p\"), function(d) {\n    return d.getUTCHours();\n  } ], [ d3.time.format.utc(\"%I:%M\"), function(d) {\n    return d.getUTCMinutes();\n  } ], [ d3.time.format.utc(\":%S\"), function(d) {\n    return d.getUTCSeconds();\n  } ], [ d3.time.format.utc(\".%L\"), function(d) {\n    return d.getUTCMilliseconds();\n  } ] ];\n  var d3_time_scaleUTCFormat = d3_time_scaleFormat(d3_time_scaleUTCFormats);\n  function d3_time_scaleUTCSetYear(y) {\n    var d = new Date(Date.UTC(y, 0, 1));\n    d.setUTCFullYear(y);\n    return d;\n  }\n  function d3_time_scaleUTCGetYear(d) {\n    var y = d.getUTCFullYear(), d0 = d3_time_scaleUTCSetYear(y), d1 = d3_time_scaleUTCSetYear(y + 1);\n    return y + (d - d0) / (d1 - d0);\n  }\n  d3_time_scaleUTCMethods.year = function(extent, m) {\n    return d3_time_scaleLinear.domain(extent.map(d3_time_scaleUTCGetYear)).ticks(m).map(d3_time_scaleUTCSetYear);\n  };\n  d3.time.scale.utc = function() {\n    return d3_time_scale(d3.scale.linear(), d3_time_scaleUTCMethods, d3_time_scaleUTCFormat);\n  };\n})();\n"
  },
  {
    "path": "examples/other/template-demo/client/template-demo.css",
    "content": "body {\n    font-family: 'Helvetica Neue', Helvetica, Arial, san-serif;\n    width: 600px;\n    margin: auto;\n    padding: 25px 50px;\n    border: 5px dashed #ccc;\n    border-style: none dashed;\n}\n\nh2 {\n    margin-top: 50px;\n    text-decoration: underline;\n}\n\n.clearboth {\n    clear: both;\n}\n\n@-webkit-keyframes spinForward {\n    from {-webkit-transform: rotate(0deg);}\n    to {-webkit-transform: rotate(360deg);}\n}\n\n@-webkit-keyframes spinBackward {\n    from {-webkit-transform: rotate(360deg);}\n    to {-webkit-transform: rotate(0deg);}\n}\n\n.spinner {\n    width: 100px;\n    border: 2px solid black;\n    font-weight: bold;\n    text-align: center;\n    background: white;\n}\n\n.circles {\n    float: left;\n    padding-right: 20px;\n}\n\n.circles svg {\n    border: 2px solid #333;\n}"
  },
  {
    "path": "examples/other/template-demo/client/template-demo.html",
    "content": "<head>\n  <title>Advanced Template Demo</title>\n</head>\n\n<body>\n  {{> page}}\n</body>\n\n<template name=\"page\">\n  <h1>Advanced Template Demo</h1>\n  <p>\n    This demo shows off the advanced features of Meteor's optional\n    Spark-based templating system, including constant regions, node\n    preservation, per-template state, and template lifecycle\n    callbacks.\n  </p>\n\n  {{> preserveDemo }}\n  {{> constantDemo }}\n  {{> stateDemo }}\n  {{> d3Demo }}\n</template>\n\n<template name=\"preserveDemo\">\n  <h2>Element preservation</h2>\n\n  <input type=\"button\" value=\"X++\" class=\"x\">\n\n  <p>\n    Elements can be <em>preserved</em>, meaning that they will not be\n    disturbed even as their attributes, children, or siblings\n    change. In this example, when you press the X++ button, the CSS\n    animation continues uninterrupted.\n  </p>\n\n\nX={{x}}<br>\n  <div class=\"spinner\" style=\"-webkit-animation: {{spinAnim}} 2s infinite linear\">\n    X={{x}}\n  </div>\n  <div>\n    <input type=\"checkbox\" class=\"spinforward\" {{spinForwardChecked}}>\n    Spin Forward\n  </div>\n  X={{x}}\n</template>\n\n<template name=\"constantDemo\">\n  <h2>Constant regions</h2>\n\n  <div>\n    <input type=\"button\" value=\"X++\" class=\"x\"> <br>\n    <input type=\"checkbox\" class=\"remove\" which=\"1\" {{checked 1}}>\n    Remove map 1<br>\n    <input type=\"checkbox\" class=\"remove\" which=\"2\" {{checked 2}}>\n    Remove map 2\n  </div>\n  <br>\n\n  <p>\n    Parts of a template can be marked as <em>constant</em>, meaning\n    that Meteor will leave the entire region alone (even as its\n    siblings change.) This is great for embedding non-Meteor\n    widgets. Try scrolling the two Google Maps embeds below. When you\n    press X++, the maps stay where they are.\n  </p>\n\n  <p>\n    Try using the checkboxes to remove either or both of the\n    maps. When you remove a map, Spark tracks the <em>identity</em> of\n    the constant regions so that it knows which DOM nodes to keep and\n    which DOM nodes to throw away. In the case of the Handlebars\n    package, the identity is based on the actual template call stack\n    that rendered the constant region.\n  </p>\n\n  X={{x}}<br>\n\n  {{#if show 1}}\n    {{#constant}}\n<div style=\"float: left; padding-right: 20px;\">\n<iframe width=\"290\" height=\"290\" frameborder=\"0\" scrolling=\"no\" marginheight=\"0\" marginwidth=\"0\" src=\"https://maps.google.com/maps?f=q&amp;source=s_q&amp;hl=en&amp;geocode=&amp;q=140+10th+Street,+San+Francisco,+CA&amp;aq=0&amp;oq=140+10th+s&amp;sll=37.7577,-122.4376&amp;sspn=0.166931,0.329247&amp;ie=UTF8&amp;hq=&amp;hnear=140+10th+St,+San+Francisco,+California+94103&amp;t=m&amp;ll=37.774921,-122.415419&amp;spn=0.013569,0.017252&amp;z=14&amp;iwloc=A&amp;output=embed\"></iframe><br /><small><a href=\"https://maps.google.com/maps?f=q&amp;source=embed&amp;hl=en&amp;geocode=&amp;q=140+10th+Street,+San+Francisco,+CA&amp;aq=0&amp;oq=140+10th+s&amp;sll=37.7577,-122.4376&amp;sspn=0.166931,0.329247&amp;ie=UTF8&amp;hq=&amp;hnear=140+10th+St,+San+Francisco,+California+94103&amp;t=m&amp;ll=37.774921,-122.415419&amp;spn=0.013569,0.017252&amp;z=14&amp;iwloc=A\" style=\"color:#0000FF;text-align:left\">View Larger Map</a></small>\n</div>\n    {{/constant}}\n  {{/if}}\n\n  {{#if show 2}}\n    {{#constant}}\n<div>\n<iframe width=\"290\" height=\"290\" frameborder=\"0\" scrolling=\"no\" marginheight=\"0\" marginwidth=\"0\" src=\"https://maps.google.com/maps?f=q&amp;source=s_q&amp;hl=en&amp;geocode=&amp;q=880+Harrison+Street,+San+Francisco,+CA&amp;aq=0&amp;oq=880+harrison&amp;sll=37.7577,-122.4376&amp;sspn=0.166931,0.329247&amp;ie=UTF8&amp;hq=&amp;hnear=880+Harrison+St,+San+Francisco,+California+94107&amp;t=m&amp;ll=37.779534,-122.411213&amp;spn=0.013568,0.01708&amp;z=14&amp;iwloc=A&amp;output=embed\"></iframe><br /><small><a href=\"https://maps.google.com/maps?f=q&amp;source=embed&amp;hl=en&amp;geocode=&amp;q=880+Harrison+Street,+San+Francisco,+CA&amp;aq=0&amp;oq=880+harrison&amp;sll=37.7577,-122.4376&amp;sspn=0.166931,0.329247&amp;ie=UTF8&amp;hq=&amp;hnear=880+Harrison+St,+San+Francisco,+California+94107&amp;t=m&amp;ll=37.779534,-122.411213&amp;spn=0.013568,0.01708&amp;z=14&amp;iwloc=A\" style=\"color:#0000FF;text-align:left\">View Larger Map</a></small>\n</div>\n    {{/constant}}\n  {{/if}}\n\n  <div class=\"clearboth\"> </div>\n\n  X={{x}}\n</template>\n\n<template name=\"stateDemo\">\n  <h2>Template callbacks</h2>\n\n  <p>\n    <input type=\"button\" value=\"X++\" class=\"x\">\n    <input type=\"button\" value=\"Y++\" class=\"y\">\n    <input type=\"button\" value=\"Z++\" class=\"z\">\n  </p>\n\n  <p>\n    You can get a <em>created</em> callback when a template is\n    initially rendered; a <em>rendered</em> when a template is placed on\n    the screen and when any part of the template is redrawn; and\n    a <em>destroyed</em> callback when a template is taken across the\n    screen. All of these callbacks receive a common <em>template state\n    object</em> in 'this' which allows you to attach data to each\n    particular instance of a template.\n  </p>\n\n  <p>\n    In this case, <em>created</em> is used to create a new JavaScript\n    timer that updates the text of a &lt;span&gt; element every\n    second. <em>rendered</em> is used to find the &lt;span&gt; when it\n    appears on the screen, and update the pointer when the\n    &lt;span&gt; is redraw (say, when you press Y++ &mdash; since it\n    is not marked to be preserved.) <em>destroyed</em> is used to cancel\n    the timer when the template goes off the screen.\n  </p>\n\n  <p>\n    The template state is used to hold the current time count and a\n    reference to the &lt;span&gt; object to update. That's why there\n    can be multiple copies of the same template, each with a different\n    value for the counter.\n  </p>\n\n  X={{x}}<br>\n  <input type=\"button\" value=\"Create a timer\" class=\"create\"><br>\n  {{#each timers}}\n    <div>\n      {{> timer}}\n      Z={{z}}\n    </div>\n  {{/each}}\n  X={{x}}\n</template>\n\n<template name=\"timer\">\n  <span class=\"elapsed\"></span>\n  <input type=\"button\" value=\"Reset\" class=\"reset\">\n  <input type=\"button\" value=\"Delete\" class=\"delete\">\n  Y={{y}}\n</template>\n\n<template name=\"d3Demo\">\n  <h2>Simple d3.js integration</h2>\n  <p>\n    Meteor fits naturally with the popular d3.js data visualization\n    library by Michael Bostock. Just set up d3 from your\n    template's <em>rendered</em> callback. With Meteor, you can pass\n    data directly out of a Mongo query into d3, and your d3\n    visualization will update in realtime, with no extra code! Try\n    opening this page in two browser windows.\n  </p>\n\n  {{> circles left}}\n  {{> circles right}}\n  <div class=\"clearboth\"> </div>\n\n</template>\n\n<template name=\"circles\">\n  <div class=\"circles\">\n    {{#constant}}\n      <svg width=\"272\" height=\"272\"></svg>\n    {{/constant}}\n    <br>\n    {{count}} circles<br>\n    <input type=\"button\" value=\"Add\" class=\"add\">\n    <input type=\"button\" value=\"Remove\" class=\"remove\" {{disabled}}>\n    <input type=\"button\" value=\"Scram\" class=\"scram\">\n    <input type=\"button\" value=\"Clear\" class=\"clear\">\n  </div>\n</template>\n"
  },
  {
    "path": "examples/other/template-demo/client/template-demo.js",
    "content": "Timers = new Mongo.Collection(null);\n\n///////////////////////////////////////////////////////////////////////////////\n\nif (! Session.get(\"x\")) {\n  Session.set(\"x\", 1);\n}\n\nif (! Session.get(\"y\")) {\n  Session.set(\"y\", 1);\n}\n\nif (! Session.get(\"z\")) {\n  Session.set(\"z\", 1);\n}\n\nTemplate.preserveDemo.x =\nTemplate.constantDemo.x =\nTemplate.stateDemo.x =\nfunction () {\n  return Session.get(\"x\");\n};\n\nTemplate.timer.y = function () {\n  return Session.get(\"y\");\n};\n\nTemplate.stateDemo.z =\nfunction () {\n  return Session.get(\"z\");\n};\n\nTemplate.page.events({\n  'click input.x': function () {\n    Session.set(\"x\", Session.get(\"x\") + 1);\n  },\n\n  'click input.y': function () {\n    Session.set(\"y\", Session.get(\"y\") + 1);\n  },\n\n  'click input.z': function () {\n    Session.set(\"z\", Session.get(\"z\") + 1);\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n\nif (typeof Session.get(\"spinForward\") !== 'boolean') {\n  Session.set(\"spinForward\", true);\n}\n\nTemplate.preserveDemo.preserve([ '.spinner', '.spinforward' ]);\n\nTemplate.preserveDemo.spinForwardChecked = function () {\n  return Session.get('spinForward') ? 'checked' : '';\n};\n\nTemplate.preserveDemo.spinAnim = function () {\n  return Session.get('spinForward') ? 'spinForward' : 'spinBackward';\n};\n\nTemplate.preserveDemo.events({\n  'change .spinforward' : function (event) {\n    Session.set('spinForward', event.currentTarget.checked);\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n\nTemplate.constantDemo.checked = function (which) {\n  return Session.get('mapchecked' + which) ? 'checked' : '';\n};\n\nTemplate.constantDemo.show = function (which) {\n  return ! Session.get('mapchecked' + which);\n};\n\nTemplate.constantDemo.events({\n  'change .remove' : function (event) {\n    var tgt = event.currentTarget;\n    Session.set('mapchecked' + tgt.getAttribute(\"which\"), tgt.checked);\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n\nTemplate.stateDemo.events({\n  'click .create': function () {\n    Timers.insert({});\n  }\n});\n\nTemplate.stateDemo.timers = function () {\n  return Timers.find();\n};\n\nTemplate.timer.events({\n  'click .reset': function (event, template) {\n    template.elapsed = 0;\n    updateTimer(template);\n  },\n  'click .delete': function () {\n    Timers.remove(this._id);\n  }\n});\n\nvar updateTimer = function (timer) {\n  timer.node.innerHTML = timer.elapsed + \" second\" +\n    ((timer.elapsed === 1) ? \"\" : \"s\");\n};\n\nTemplate.timer.onCreated(function () {\n  var self = this;\n  self.elapsed = 0;\n  self.node = null;\n});\n\nTemplate.timer.onRendered(function () {\n  var self = this;\n  self.node = this.find(\".elapsed\");\n  updateTimer(self);\n\n  if (! self.timer) {\n    var tick = function () {\n      self.elapsed++;\n      self.timer = setTimeout(tick, 1000);\n      updateTimer(self);\n    };\n    tick();\n  }\n});\n\nTemplate.timer.onDestroyed(function () {\n  clearInterval(this.timer);\n});\n\n///////////////////////////////////////////////////////////////////////////////\n\nTemplate.d3Demo.left = function () {\n  return { group: \"left\" };\n};\n\nTemplate.d3Demo.right = function () {\n  return { group: \"right\" };\n};\n\nTemplate.circles.events({\n  'mousedown circle': function (evt, template) {\n    Session.set(\"selectedCircle:\" + this.group, evt.currentTarget.id);\n  },\n  'click .add': function () {\n    Circles.insert({x: Random.fraction(), y: Random.fraction(),\n                    r: Random.fraction() * .1 + .02,\n                    color: {\n                      r: Random.fraction(),\n                      g: Random.fraction(),\n                      b: Random.fraction()\n                    },\n                    group: this.group\n                   });\n  },\n  'click .remove': function () {\n    var selected = Session.get(\"selectedCircle:\" + this.group);\n    if (selected) {\n      Circles.remove(selected);\n      Session.set(\"selectedCircle:\" + this.group, null);\n    }\n  },\n  'click .scram': function () {\n    Circles.find({group: this.group}).forEach(function (r) {\n      Circles.update(r._id, {\n        $set: {\n          x: Random.fraction(), y: Random.fraction(), r: Random.fraction() * .1 + .02\n        }\n      });\n    });\n  },\n  'click .clear': function () {\n    Circles.remove({group: this.group});\n  }\n});\n\nvar colorToString = function (color) {\n  var f = function (x) { return Math.floor(x * 256); };\n  return \"rgb(\" + f(color.r) + \",\" +\n    + f(color.g) + \",\" + + f(color.b) + \")\";\n};\n\nTemplate.circles.count = function () {\n  return Circles.find({group: this.group}).count();\n};\n\nTemplate.circles.disabled = function () {\n  return Session.get(\"selectedCircle:\" + this.group) ?\n    '' : 'disabled';\n};\n\nTemplate.circles.onCreated(function () {\n});\n\nTemplate.circles.onRendered(function () {\n  var self = this;\n  self.node = self.find(\"svg\");\n\n  var data = self.data;\n\n  if (! self.handle) {\n    d3.select(self.node).append(\"rect\");\n    self.handle = Deps.autorun(function () {\n      var circle = d3.select(self.node).selectAll(\"circle\")\n        .data(Circles.find({group: data.group}).fetch(),\n              function (d) { return d._id; });\n\n      circle.enter().append(\"circle\")\n        .attr(\"id\", function (d) {\n          return d._id;\n        })\n        .attr(\"cx\", function (d) {\n          return d.x * 272;\n        })\n        .attr(\"cy\", function (d) {\n          return d.y * 272;\n        })\n        .attr(\"r\", 50)\n        .style(\"fill\", function (d) {\n          return colorToString(d.color);\n        })\n        .style(\"opacity\", 0);\n\n      circle.transition()\n        .duration(250)\n        .attr(\"cx\", function (d) {\n          return d.x * 272;\n        })\n        .attr(\"cy\", function (d) {\n          return d.y * 272;\n        })\n        .attr(\"r\", function (d) {\n          return d.r * 272;\n        })\n        .style(\"fill\", function (d) {\n          return colorToString(d.color);\n        })\n        .style(\"opacity\", .9)\n        .ease(\"cubic-out\");\n\n      circle.exit().transition()\n        .duration(250)\n        .attr(\"r\", 0)\n        .remove();\n\n      var selectionId = Session.get(\"selectedCircle:\" + data.group);\n      var s = selectionId && Circles.findOne(selectionId);\n      var rect = d3.select(self.node).select(\"rect\");\n      if (s)\n        rect.attr(\"x\", (s.x - s.r) * 272)\n        .attr(\"y\", (s.y - s.r) * 272)\n        .attr(\"width\", s.r * 2 * 272)\n        .attr(\"height\", s.r * 2 * 272)\n        .attr(\"display\", '')\n        .style(\"fill\", \"none\")\n        .style(\"stroke\", \"red\")\n        .style(\"stroke-width\", 3);\n      else\n        rect.attr(\"display\", 'none');\n    });\n  }\n});\n\nTemplate.circles.onDestroyed(function () {\n  this.handle && this.handle.stop();\n});\n"
  },
  {
    "path": "examples/other/template-demo/model.js",
    "content": "Circles = new Mongo.Collection(\"circles\");\n"
  },
  {
    "path": "examples/other/wordplay/.meteor/.finished-upgraders",
    "content": "# This file contains information which helps Meteor properly upgrade your\n# app when you run 'meteor update'. You should check it into version control\n# with your project.\n\nnotices-for-0.9.0\nnotices-for-0.9.1\n0.9.4-platform-file\n"
  },
  {
    "path": "examples/other/wordplay/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/other/wordplay/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nstandard-app-packages\ninsecure\njquery\n"
  },
  {
    "path": "examples/other/wordplay/.meteor/platforms",
    "content": "server\nbrowser\n"
  },
  {
    "path": "examples/other/wordplay/.meteor/release",
    "content": "METEOR@0.9.4\n"
  },
  {
    "path": "examples/other/wordplay/.meteor/versions",
    "content": "application-configuration@1.0.3\nautoupdate@1.1.2\nbase64@1.0.1\nbinary-heap@1.0.1\nblaze-tools@1.0.1\nblaze@2.0.2\nboilerplate-generator@1.0.1\ncallback-hook@1.0.1\ncheck@1.0.2\nctl-helper@1.0.4\nctl@1.0.2\nddp@1.0.10\ndeps@1.0.5\nejson@1.0.4\nfastclick@1.0.1\nfollower-livedata@1.0.2\ngeojson-utils@1.0.1\nhtml-tools@1.0.2\nhtmljs@1.0.2\nhttp@1.0.7\nid-map@1.0.1\ninsecure@1.0.1\njquery@1.0.1\njson@1.0.1\nlivedata@1.0.11\nlogging@1.0.4\nmeteor-platform@1.1.2\nmeteor@1.1.2\nminifiers@1.1.1\nminimongo@1.0.4\nmobile-status-bar@1.0.1\nmongo@1.0.7\nobserve-sequence@1.0.3\nordered-dict@1.0.1\nrandom@1.0.1\nreactive-dict@1.0.4\nreactive-var@1.0.3\nreload@1.1.1\nretry@1.0.1\nroutepolicy@1.0.2\nsession@1.0.3\nspacebars-compiler@1.0.3\nspacebars@1.0.3\nstandard-app-packages@1.0.3\ntemplating@1.0.8\ntracker@1.0.3\nui@1.0.4\nunderscore@1.0.1\nurl@1.0.1\nwebapp-hashing@1.0.1\nwebapp@1.1.3\n"
  },
  {
    "path": "examples/other/wordplay/TODO",
    "content": "TODOS\nstrip spaces on input box\nfocus input on game start\nstyling\neliminate extra divs\n\nPOSSIBLE EXTENSIONS\npublish remaining words at end of game\nUI that works on touch devices sans keyboard\nspinny while word is getting scored\nsupport clicking on board instead of text box\n\n"
  },
  {
    "path": "examples/other/wordplay/client/wordplay.css",
    "content": "body {\n    margin: 0px;\n    background-color: #f4f4f4;\n    font-family: Helvetica, Arial, sans-serif;\n}\n\n/* base styles */\n\ninput {\n    height: 50px;\n    width: 300px;\n    font-size: 2em;\n    border: 2px solid black;\n    padding: 5px;\n}\n\nbutton {\n    position: relative;\n    bottom: 3px;\n    margin: 10px;\n    height: 50px;\n    background-color:#E6EFC2;\n    border:1px solid #dedede;\n    font-weight:bold;\n    cursor:pointer;\n    font-size: 1.5em;\n}\n\nbutton:hover {\n    background-color:#D6DFb2;\n    border:1px solid #C6D880;\n}\n\nbutton:active {\n    background-color:#529214;\n    border:1px solid #529214;\n    color:#fff;\n}\n\n/*******/\n\n#main {\n    margin: 20px;\n}\n\n#left {\n    float: left;\n    width: 40%;\n}\n\n#right {\n    float: left;\n    width: 50%;\n}\n\n#clock {\n    width: 100%;\n    height: 100px;\n    text-align: center;\n    font-size: 3em;\n}\n\n#board {\n    margin: auto;\n    border:4px solid #999999;\n    border-radius: 4px;\n    -moz-border-radius: 4px;\n    padding:2px;\n\n    width:400px;\n    height:400px;\n    background-color:#999999;\n}\n\n.square {\n    cursor: pointer;\n    width:84px;\n    height:84px;\n    border:4px solid #eeeee8;\n    border-radius: 4px;\n    -moz-border-radius: 4px;\n    margin: 4px;\n    float:left;\n    text-align: center;\n    background-color:#eeeee8;\n    font-size: 65px;\n}\n\n.square.last_in_path {\n    color: #ff0000;\n}\n\n.square.in_path {\n    color: #990000;\n}\n\n#login {\n    margin: 100px auto;\n    text-align: center;\n}\n\n#login .error {\n    color: red;\n}\n\n#lobby {\n    margin: 100px auto;\n    text-align: center;\n}\n\n#postgame {\n    height: 100px;\n    text-align: center;\n}\n\n#scratchpad {\n    height: 100px;\n}\n\n#scratchpad input {\n    width: 70%;\n}\n\n#scratchpad h1 {\n    float: left;\n}\n\n#scores {\n    float: left;\n    width: 100%;\n    background-color: #eeeee8;\n    border: 1px solid black;\n    padding: 0.5em;\n}\n\n#scores .player {\n    float: left;\n    width: 100%;\n}\n\n#scores .header {\n    font-size: 1.25em;\n}\n\n#scores .unnamed {\n    color: #444;\n    font-style: italic;\n}\n\n#scores .winner {\n    background-color: yellow;\n}\n\n#scores .winner_text {\n    float: right;\n}\n\n#scores .word {\n    float: left;\n    font-size: 1.25em;\n    padding: 0.25em;\n    margin: 0.5em;\n    border: 1px solid #030;\n}\n\n#scores .word.good {\n    background-color: #0a0;\n}\n\n#scores .word.bad {\n    text-decoration: line-through;\n}\n\n#scores .word span.score {\n    width: 1em;\n}\n\n#scores .word.bad span.score {\n    background-image: 'circle-ball-dark-antialiased.gif';\n}\n"
  },
  {
    "path": "examples/other/wordplay/client/wordplay.html",
    "content": "<head>\n  <title>Word play!</title>\n</head>\n\n<body>\n  {{> page}}\n</body>\n\n<template name=\"page\">\n  <div id=\"main\">\n    <div id=\"left\">\n      {{> board }}\n    </div>\n    <div id=\"right\">\n      {{> lobby }}\n      {{> scratchpad }}\n      {{> postgame }}\n      {{> scores }}\n    </div>\n  </div>\n</template>\n\n<template name=\"board\">\n  <div id=\"clock\">\n    {{ clock }}\n  </div>\n  <div id=\"board\">\n    <div>\n      <div class=\"square {{ selected 0 }}\">{{ square 0 }}</div>\n      <div class=\"square {{ selected 1 }}\">{{ square 1 }}</div>\n      <div class=\"square {{ selected 2 }}\">{{ square 2 }}</div>\n      <div class=\"square {{ selected 3 }}\">{{ square 3 }}</div>\n    </div>\n    <div>\n      <div class=\"square {{ selected 4 }}\">{{ square 4 }}</div>\n      <div class=\"square {{ selected 5 }}\">{{ square 5 }}</div>\n      <div class=\"square {{ selected 6 }}\">{{ square 6 }}</div>\n      <div class=\"square {{ selected 7 }}\">{{ square 7 }}</div>\n    </div>\n    <div>\n      <div class=\"square {{ selected 8 }}\">{{ square 8 }}</div>\n      <div class=\"square {{ selected 9 }}\">{{ square 9 }}</div>\n      <div class=\"square {{ selected 10 }}\">{{ square 10 }}</div>\n      <div class=\"square {{ selected 11 }}\">{{ square 11 }}</div>\n    </div>\n    <div>\n      <div class=\"square {{ selected 12 }}\">{{ square 12 }}</div>\n      <div class=\"square {{ selected 13 }}\">{{ square 13 }}</div>\n      <div class=\"square {{ selected 14 }}\">{{ square 14 }}</div>\n      <div class=\"square {{ selected 15 }}\">{{ square 15 }}</div>\n    </div>\n  </div>\n</template>\n\n<template name=\"lobby\">\n  <div>\n    {{#if show }}\n    <div id=\"lobby\">\n      <h1>What's your name?</h1>\n      <input id=\"myname\" type=\"text\" />\n      {{#if count}}\n      <h1>{{count}} other players are in the lobby:</h1>\n      {{#each waiting }}\n      <div class=\"player\">{{name}}</div>\n      {{/each}}\n      {{/if}}\n      <div>\n        <button id=\"startgame\" class=\"startgame\" {{disabled}}>\n          {{#if count}} It's on! {{else}} Play solo {{/if}}\n        </button>\n      </div>\n    </div>\n    {{/if}}\n  </div>\n</template>\n\n<template name=\"scratchpad\">\n  {{#if show}}\n  <div id=\"scratchpad\">\n    <input id=\"scratchpad_input\" type=\"text\" />\n    <button name=\"submit\" class=\"submit\">Submit</button>\n  </div>\n  {{/if}}\n</template>\n\n<template name=\"postgame\">\n  <div>\n    {{#if show}}\n    <div id=\"postgame\">\n      <button name=\"backtolobby\" class=\"lobby\">Back to lobby</button>\n    </div>\n    {{/if}}\n  </div>\n</template>\n\n<template name=\"scores\">\n  <div>\n    {{#if show}}\n    <div id=\"scores\">\n      {{#each players}}\n        {{> player }}\n      {{/each}}\n    </div>\n    {{/if}}\n  </div>\n</template>\n\n<template name=\"player\">\n  <div class=\"player\">\n    <div class=\"header {{winner}}\">\n      {{#if name}}\n        {{name}}\n      {{else}}\n        <span class=\"unnamed\">no name</span>\n      {{/if}}\n      <span class=\"score\">{{total_score}}</span>\n      {{#if winner}}\n        <span class=\"winner_text\">Winner!</span>\n      {{/if}}\n    </div>\n    {{> words}}\n  </div>\n</template>\n\n<template name=\"words\">\n  <div class=\"words\">\n    {{#each words}}\n    <div id=\"word_{{_id}}\" class=\"word {{state}}\">\n      <span class=\"score\">\n        {{score}}\n      </span>\n      {{word}}\n    </div>\n    {{/each}}\n  </div>\n</template>\n"
  },
  {
    "path": "examples/other/wordplay/client/wordplay.js",
    "content": "////////// Main client application logic //////////\n\n//////\n////// Utility functions\n//////\n\nvar player = function () {\n  return Players.findOne(Session.get('player_id'));\n};\n\nvar game = function () {\n  var me = player();\n  return me && me.game_id && Games.findOne(me.game_id);\n};\n\nvar set_selected_positions = function (word) {\n  var paths = paths_for_word(game().board, word.toUpperCase());\n  var in_a_path = [];\n  var last_in_a_path = [];\n\n  for (var i = 0; i < paths.length; i++) {\n    in_a_path = in_a_path.concat(paths[i]);\n    last_in_a_path.push(paths[i].slice(-1)[0]);\n  }\n\n  for (var pos = 0; pos < 16; pos++) {\n    if (_.indexOf(last_in_a_path, pos) !== -1)\n      Session.set('selected_' + pos, 'last_in_path');\n    else if (_.indexOf(in_a_path, pos) !== -1)\n      Session.set('selected_' + pos, 'in_path');\n    else\n      Session.set('selected_' + pos, false);\n  }\n};\n\nvar clear_selected_positions = function () {\n  for (var pos = 0; pos < 16; pos++)\n    Session.set('selected_' + pos, false);\n};\n\n//////\n////// lobby template: shows everyone not currently playing, and\n////// offers a button to start a fresh game.\n//////\n\nTemplate.lobby.helpers({\n  show: function () {\n    // only show lobby if we're not in a game\n    return !game();\n  },\n\n  waiting: function () {\n    var players = Players.find({_id: {$ne: Session.get('player_id')},\n                                name: {$ne: ''},\n                                game_id: {$exists: false}});\n\n    return players;\n  },\n\n  count: function () {\n    var players = Players.find({_id: {$ne: Session.get('player_id')},\n                                name: {$ne: ''},\n                                game_id: {$exists: false}});\n\n    return players.count();\n  },\n\n  disabled: function () {\n    var me = player();\n    if (me && me.name)\n      return '';\n    return 'disabled';\n  }\n});\n\nvar trim = function (string) { return string.replace(/^\\s+|\\s+$/g, ''); };\n\nTemplate.lobby.events({\n  'keyup input#myname': function (evt) {\n    var name = trim($('#lobby input#myname').val());\n    Players.update(Session.get('player_id'), {$set: {name: name}});\n  },\n  'click button.startgame': function () {\n    Meteor.call('start_new_game');\n  }\n});\n\n//////\n////// board template: renders the board and the clock given the\n////// current game.  if there is no game, show a splash screen.\n//////\nvar SPLASH = ['','','','',\n              'W', 'O', 'R', 'D',\n              'P', 'L', 'A', 'Y',\n              '','','',''];\n\nTemplate.board.helpers({\n  square: function (i) {\n    var g = game();\n    return g && g.board && g.board[i] || SPLASH[i];\n  },\n\n  selected: function (i) {\n    return Session.get('selected_' + i);\n  },\n\n  clock: function () {\n    var clock = game() && game().clock;\n\n    if (!clock || clock === 0)\n      return;\n\n    // format into M:SS\n    var min = Math.floor(clock / 60);\n    var sec = clock % 60;\n    return min + ':' + (sec < 10 ? ('0' + sec) : sec);\n  }\n});\n\nTemplate.board.events({\n  'click .square': function (evt) {\n    var textbox = $('#scratchpad input');\n    // Note: Getting the letter out of the DOM is kind of a hack\n    var letter = evt.target.textContent || evt.target.innerText;\n    textbox.val(textbox.val() + letter);\n    textbox.focus();\n  }\n});\n\n//////\n////// scratchpad is where we enter new words.\n//////\n\nTemplate.scratchpad.helpers({\n  show: function () {\n    return game() && game().clock > 0;\n  }\n});\n\nTemplate.scratchpad.events({\n  'click button, keyup input': function (evt) {\n    var textbox = $('#scratchpad input');\n    // if we clicked the button or hit enter\n    if ((evt.type === \"click\" || (evt.type === \"keyup\" && evt.which === 13))\n        && textbox.val()) {\n      var word_id = Words.insert({player_id: Session.get('player_id'),\n                                  game_id: game() && game()._id,\n                                  word: textbox.val().toUpperCase(),\n                                  state: 'pending'});\n      Meteor.call('score_word', word_id);\n      textbox.val('');\n      textbox.focus();\n      clear_selected_positions();\n    } else {\n      set_selected_positions(textbox.val());\n    }\n  }\n});\n\nTemplate.postgame.helpers({\n  show: function () {\n    return game() && game().clock === 0;\n  }\n});\n\nTemplate.postgame.events({\n  'click button': function (evt) {\n    Players.update(Session.get('player_id'), {$set: {game_id: null}});\n  }\n});\n\n//////\n////// scores shows everyone's score and word list.\n//////\n\nTemplate.scores.helpers({\n  show: function () {\n    return !!game();\n  },\n\n  players: function () {\n    return game() && game().players;\n  }\n});\n\nTemplate.player.helpers({\n  winner: function () {\n    var g = game();\n    if (g.winners && _.include(g.winners, this._id))\n      return 'winner';\n    return '';\n  },\n\n  total_score: function () {\n    var words = Words.find({game_id: game() && game()._id,\n                            player_id: this._id});\n\n    var score = 0;\n    words.forEach(function (word) {\n      if (word.score)\n        score += word.score;\n    });\n    return score;\n  }\n});\n\nTemplate.words.helpers({\n  words: function () {\n    return Words.find({game_id: game() && game()._id,\n                       player_id: this._id});\n  }\n});\n\n\n//////\n////// Initialization\n//////\n\nMeteor.startup(function () {\n  // Allocate a new player id.\n  //\n  // XXX this does not handle hot reload. In the reload case,\n  // Session.get('player_id') will return a real id. We should check for\n  // a pre-existing player, and if it exists, make sure the server still\n  // knows about us.\n  var player_id = Players.insert({name: '', idle: false});\n  Session.set('player_id', player_id);\n\n  // subscribe to all the players, the game i'm in, and all\n  // the words in that game.\n  Tracker.autorun(function () {\n    Meteor.subscribe('players');\n\n    if (Session.get('player_id')) {\n      var me = player();\n      if (me && me.game_id) {\n        Meteor.subscribe('games', me.game_id);\n        Meteor.subscribe('words', me.game_id, Session.get('player_id'));\n      }\n    }\n  });\n\n  // send keepalives so the server can tell when we go away.\n  //\n  // XXX this is not a great idiom. meteor server does not yet have a\n  // way to expose connection status to user code. Once it does, this\n  // code can go away.\n  Meteor.setInterval(function() {\n    if (Meteor.status().connected)\n      Meteor.call('keepalive', Session.get('player_id'));\n  }, 20*1000);\n});\n"
  },
  {
    "path": "examples/other/wordplay/model.js",
    "content": "////////// Shared code (client and server) //////////\n\nGames = new Mongo.Collection('games');\n// { board: ['A','I',...], clock: 60,\n//   players: [{player_id, name}], winners: [player_id] }\n\nWords = new Mongo.Collection('words');\n// {player_id: 10, game_id: 123, word: 'hello', state: 'good', score: 4}\n\nPlayers = new Mongo.Collection('players');\n// {name: 'matt', game_id: 123}\n\n// 6 faces per die, 16 dice.  Q really means Qu.\nvar DICE = ['PCHOAS', 'OATTOW', 'LRYTTE', 'VTHRWE',\n            'EGHWNE', 'SEOTIS', 'ANAEEG', 'IDSYTT',\n            'MTOICU', 'AFPKFS', 'XLDERI', 'ENSIEU',\n            'YLDEVR', 'ZNRNHL', 'NMIQHU', 'OBBAOJ'];\n\nvar DICTIONARY = null;\n\n// board is an array of length 16, in row-major order.  ADJACENCIES\n// lists the board positions adjacent to each board position.\nvar ADJACENCIES = [\n  [1,4,5],\n  [0,2,4,5,6],\n  [1,3,5,6,7],\n  [2,6,7],\n  [0,1,5,8,9],\n  [0,1,2,4,6,8,9,10],\n  [1,2,3,5,7,9,10,11],\n  [2,3,6,10,11],\n  [4,5,9,12,13],\n  [4,5,6,8,10,12,13,14],\n  [5,6,7,9,11,13,14,15],\n  [6,7,10,14,15],\n  [8,9,13],\n  [8,9,10,12,14],\n  [9,10,11,13,15],\n  [10,11,14]\n];\n\n// generate a new random selection of letters.\nnew_board = function () {\n  var board = [];\n  var i;\n\n  // pick random letter from each die\n  for (i = 0; i < 16; i += 1) {\n    board[i] = Random.choice(DICE[i]);\n  }\n\n  // knuth shuffle\n  for (i = 15; i > 0; i -= 1) {\n    var j = Math.floor(Math.random() * (i + 1));\n    var tmp = board[i];\n    board[i] = board[j];\n    board[j] = tmp;\n  }\n\n  return board;\n};\n\n// returns an array of valid paths to make the specified word on the\n// board.  each path is an array of board positions 0-15.  a valid\n// path can use each position only once, and each position must be\n// adjacent to the previous position.\npaths_for_word = function (board, word) {\n  var valid_paths = [];\n\n  var check_path = function (word, path, positions_to_try) {\n    // base case: the whole word has been consumed.  path is valid.\n    if (word.length === 0) {\n      valid_paths.push(path);\n      return;\n    }\n\n    // otherwise, try to match each available position against the\n    // first letter of the word, avoiding any positions that are\n    // already used by the path.  for each of those matches, descend\n    // recursively, passing the remainder of the word, the accumulated\n    // path, and the positions adjacent to the match.\n\n    for (var i = 0; i < positions_to_try.length; i++) {\n      var pos = positions_to_try[i];\n      if (board[pos] === word[0] && _.indexOf(path, pos) === -1)\n        check_path(word.slice(1),      // cdr of word\n                   path.concat([pos]), // append matching loc to path\n                   ADJACENCIES[pos]);  // only look at surrounding tiles\n    }\n  };\n\n  // start recursive search w/ full word, empty path, and all tiles\n  // available for the first letter.\n  check_path(word, [], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]);\n\n  return valid_paths;\n};\n\nMeteor.methods({\n  score_word: function (word_id) {\n    check(word_id, String);\n    var word = Words.findOne(word_id);\n    var game = Games.findOne(word.game_id);\n\n    // client and server can both check that the game has time remaining, and\n    // that the word is at least three chars, isn't already used, and is\n    // possible to make on the board.\n    if (game.clock === 0\n        || !word.word\n        || word.word.length < 3\n        || Words.find({game_id: word.game_id, word: word.word}).count() > 1\n        || paths_for_word(game.board, word.word).length === 0) {\n      Words.update(word._id, {$set: {score: 0, state: 'bad'}});\n      return;\n    }\n\n    // now only on the server, check against dictionary and score it.\n    if (Meteor.isServer) {\n      if (_.has(DICTIONARY, word.word.toLowerCase())) {\n        var score = Math.pow(2, word.word.length - 3);\n        Words.update(word._id, {$set: {score: score, state: 'good'}});\n      } else {\n        Words.update(word._id, {$set: {score: 0, state: 'bad'}});\n      }\n    }\n  }\n});\n\n\nif (Meteor.isServer) {\n  DICTIONARY = {};\n  _.each(Assets.getText(\"enable2k.txt\").split(\"\\n\"), function (line) {\n    // Skip blanks and comment lines\n    if (line && line.indexOf(\"//\") !== 0) {\n      DICTIONARY[line] = true;\n    }\n  });\n\n  // publish all the non-idle players.\n  Meteor.publish('players', function () {\n    return Players.find({idle: false});\n  });\n\n  // publish single games\n  Meteor.publish('games', function (id) {\n    check(id, String);\n    return Games.find({_id: id});\n  });\n\n  // publish all my words and opponents' words that the server has\n  // scored as good.\n  Meteor.publish('words', function (game_id, player_id) {\n    check(game_id, String);\n    check(player_id, String);\n    return Words.find({$or: [{game_id: game_id, state: 'good'},\n                             {player_id: player_id}]});\n  });\n}\n"
  },
  {
    "path": "examples/other/wordplay/private/enable2k.txt",
    "content": "// enable2k dictionary courtesy of http://www.morewords.com/, public\n// domain.  includes standard inflections, which are missing in\n// /usr/share/dict/words.\naa\naah\naahed\naahing\naahs\naal\naalii\naaliis\naals\naardvark\naardvarks\naardwolf\naardwolves\naargh\naarrgh\naarrghh\naas\naasvogel\naasvogels\nab\naba\nabaca\nabacas\nabaci\naback\nabacterial\nabacus\nabacuses\nabaft\nabaka\nabakas\nabalone\nabalones\nabamp\nabampere\nabamperes\nabamps\nabandon\nabandoned\nabandoner\nabandoners\nabandoning\nabandonment\nabandonments\nabandons\nabapical\nabas\nabase\nabased\nabasedly\nabasement\nabasements\nabaser\nabasers\nabases\nabash\nabashed\nabashes\nabashing\nabashment\nabashments\nabasia\nabasias\nabasing\nabatable\nabate\nabated\nabatement\nabatements\nabater\nabaters\nabates\nabating\nabatis\nabatises\nabator\nabators\nabattis\nabattises\nabattoir\nabattoirs\nabaxial\nabaxile\nabba\nabbacies\nabbacy\nabbas\nabbatial\nabbe\nabbes\nabbess\nabbesses\nabbey\nabbeys\nabbot\nabbotcies\nabbotcy\nabbots\nabbreviate\nabbreviated\nabbreviates\nabbreviating\nabbreviation\nabbreviations\nabbreviator\nabbreviators\nabdicable\nabdicate\nabdicated\nabdicates\nabdicating\nabdication\nabdications\nabdicator\nabdicators\nabdomen\nabdomens\nabdomina\nabdominal\nabdominally\nabduce\nabduced\nabducens\nabducent\nabducentes\nabduces\nabducing\nabduct\nabducted\nabductee\nabductees\nabducting\nabduction\nabductions\nabductor\nabductores\nabductors\nabducts\nabeam\nabecedarian\nabecedarians\nabed\nabele\nabeles\nabelia\nabelian\nabelias\nabelmosk\nabelmosks\naberrance\naberrances\naberrancies\naberrancy\naberrant\naberrantly\naberrants\naberrated\naberration\naberrational\naberrations\nabet\nabetment\nabetments\nabets\nabettal\nabettals\nabetted\nabetter\nabetters\nabetting\nabettor\nabettors\nabeyance\nabeyances\nabeyancies\nabeyancy\nabeyant\nabfarad\nabfarads\nabhenries\nabhenry\nabhenrys\nabhor\nabhorred\nabhorrence\nabhorrences\nabhorrent\nabhorrently\nabhorrer\nabhorrers\nabhorring\nabhors\nabidance\nabidances\nabide\nabided\nabider\nabiders\nabides\nabiding\nabidingly\nabigail\nabigails\nabilities\nability\nabiogeneses\nabiogenesis\nabiogenic\nabiogenically\nabiogenist\nabiogenists\nabiological\nabioses\nabiosis\nabiotic\nabiotically\nabject\nabjection\nabjections\nabjectly\nabjectness\nabjectnesses\nabjuration\nabjurations\nabjure\nabjured\nabjurer\nabjurers\nabjures\nabjuring\nablate\nablated\nablates\nablating\nablation\nablations\nablative\nablatively\nablatives\nablaut\nablauts\nablaze\nable\nablegate\nablegates\nabler\nables\nablest\nablings\nablins\nabloom\nabluent\nabluents\nablush\nabluted\nablution\nablutionary\nablutions\nably\nabmho\nabmhos\nabnegate\nabnegated\nabnegates\nabnegating\nabnegation\nabnegations\nabnegator\nabnegators\nabnormal\nabnormalities\nabnormality\nabnormally\nabnormals\nabo\naboard\nabode\naboded\nabodes\naboding\nabohm\nabohms\naboideau\naboideaus\naboideaux\naboil\naboiteau\naboiteaus\naboiteaux\nabolish\nabolishable\nabolished\nabolisher\nabolishers\nabolishes\nabolishing\nabolishment\nabolishments\nabolition\nabolitionary\nabolitionism\nabolitionisms\nabolitionist\nabolitionists\nabolitions\nabolla\nabollae\naboma\nabomas\nabomasa\nabomasal\nabomasi\nabomasum\nabomasus\nabominable\nabominably\nabominate\nabominated\nabominates\nabominating\nabomination\nabominations\nabominator\nabominators\naboon\naboral\naborally\naboriginal\naboriginally\naboriginals\naborigine\naborigines\naborning\nabort\naborted\naborter\naborters\nabortifacient\nabortifacients\naborting\nabortion\nabortionist\nabortionists\nabortions\nabortive\nabortively\nabortiveness\nabortivenesses\naborts\nabos\nabought\naboulia\naboulias\naboulic\nabound\nabounded\nabounding\nabounds\nabout\nabove\naboveboard\naboveground\naboves\nabracadabra\nabracadabras\nabrachia\nabrachias\nabradable\nabradant\nabradants\nabrade\nabraded\nabrader\nabraders\nabrades\nabrading\nabrasion\nabrasions\nabrasive\nabrasively\nabrasiveness\nabrasivenesses\nabrasives\nabreact\nabreacted\nabreacting\nabreaction\nabreactions\nabreacts\nabreast\nabri\nabridge\nabridged\nabridgement\nabridgements\nabridger\nabridgers\nabridges\nabridging\nabridgment\nabridgments\nabris\nabroach\nabroad\nabrogate\nabrogated\nabrogates\nabrogating\nabrogation\nabrogations\nabrosia\nabrosias\nabrupt\nabrupter\nabruptest\nabruption\nabruptions\nabruptly\nabruptness\nabruptnesses\nabs\nabscess\nabscessed\nabscesses\nabscessing\nabscise\nabscised\nabscises\nabscisin\nabscising\nabscisins\nabscissa\nabscissae\nabscissas\nabscission\nabscissions\nabscond\nabsconded\nabsconder\nabsconders\nabsconding\nabsconds\nabseil\nabseiled\nabseiling\nabseils\nabsence\nabsences\nabsent\nabsented\nabsentee\nabsenteeism\nabsenteeisms\nabsentees\nabsenter\nabsenters\nabsenting\nabsently\nabsentminded\nabsentmindedly\nabsentmindedness\nabsentmindednesses\nabsents\nabsinth\nabsinthe\nabsinthes\nabsinths\nabsolute\nabsolutely\nabsoluteness\nabsolutenesses\nabsoluter\nabsolutes\nabsolutest\nabsolution\nabsolutions\nabsolutism\nabsolutisms\nabsolutist\nabsolutistic\nabsolutists\nabsolutive\nabsolutize\nabsolutized\nabsolutizes\nabsolutizing\nabsolve\nabsolved\nabsolver\nabsolvers\nabsolves\nabsolving\nabsonant\nabsorb\nabsorbabilities\nabsorbability\nabsorbable\nabsorbance\nabsorbances\nabsorbancies\nabsorbancy\nabsorbant\nabsorbants\nabsorbed\nabsorbencies\nabsorbency\nabsorbent\nabsorbents\nabsorber\nabsorbers\nabsorbing\nabsorbingly\nabsorbs\nabsorptance\nabsorptances\nabsorption\nabsorptions\nabsorptive\nabsorptivities\nabsorptivity\nabsquatulate\nabsquatulated\nabsquatulates\nabsquatulating\nabstain\nabstained\nabstainer\nabstainers\nabstaining\nabstains\nabstemious\nabstemiously\nabstemiousness\nabstemiousnesses\nabstention\nabstentions\nabstentious\nabsterge\nabsterged\nabsterges\nabsterging\nabstinence\nabstinences\nabstinent\nabstinently\nabstract\nabstractable\nabstracted\nabstractedly\nabstractedness\nabstractednesses\nabstracter\nabstracters\nabstractest\nabstracting\nabstraction\nabstractional\nabstractionism\nabstractionisms\nabstractionist\nabstractionists\nabstractions\nabstractive\nabstractly\nabstractness\nabstractnesses\nabstractor\nabstractors\nabstracts\nabstrict\nabstricted\nabstricting\nabstricts\nabstruse\nabstrusely\nabstruseness\nabstrusenesses\nabstruser\nabstrusest\nabstrusities\nabstrusity\nabsurd\nabsurder\nabsurdest\nabsurdism\nabsurdisms\nabsurdist\nabsurdists\nabsurdities\nabsurdity\nabsurdly\nabsurdness\nabsurdnesses\nabsurds\nabubble\nabuilding\nabulia\nabulias\nabulic\nabundance\nabundances\nabundant\nabundantly\nabusable\nabuse\nabused\nabuser\nabusers\nabuses\nabusing\nabusive\nabusively\nabusiveness\nabusivenesses\nabut\nabutilon\nabutilons\nabutment\nabutments\nabuts\nabuttal\nabuttals\nabutted\nabutter\nabutters\nabutting\nabuzz\nabvolt\nabvolts\nabwatt\nabwatts\naby\nabye\nabyes\nabying\nabys\nabysm\nabysmal\nabysmally\nabysms\nabyss\nabyssal\nabysses\nacacia\nacacias\nacademe\nacademes\nacademia\nacademias\nacademic\nacademical\nacademically\nacademician\nacademicians\nacademicism\nacademicisms\nacademics\nacademies\nacademism\nacademisms\nacademy\nacajou\nacajous\nacaleph\nacalephae\nacalephe\nacalephes\nacalephs\nacanthi\nacanthocephalan\nacanthocephalans\nacanthus\nacanthuses\nacapnia\nacapnias\nacari\nacariases\nacariasis\nacaricidal\nacaricide\nacaricides\nacarid\nacaridan\nacaridans\nacarids\nacarine\nacarines\nacaroid\nacarpous\nacarus\nacatalectic\nacatalectics\nacaudal\nacaudate\nacaulescent\nacauline\nacaulose\nacaulous\naccede\nacceded\nacceder\nacceders\naccedes\nacceding\naccelerando\naccelerandos\naccelerant\naccelerants\naccelerate\naccelerated\naccelerates\naccelerating\nacceleratingly\nacceleration\naccelerations\naccelerative\naccelerator\naccelerators\naccelerometer\naccelerometers\naccent\naccented\naccenting\naccentless\naccentor\naccentors\naccents\naccentual\naccentually\naccentuate\naccentuated\naccentuates\naccentuating\naccentuation\naccentuations\naccept\nacceptabilities\nacceptability\nacceptable\nacceptableness\nacceptablenesses\nacceptably\nacceptance\nacceptances\nacceptant\nacceptation\nacceptations\naccepted\nacceptedly\nacceptee\nacceptees\naccepter\naccepters\naccepting\nacceptingly\nacceptingness\nacceptingnesses\nacceptive\nacceptor\nacceptors\naccepts\naccess\naccessaries\naccessary\naccessed\naccesses\naccessibilities\naccessibility\naccessible\naccessibleness\naccessiblenesses\naccessibly\naccessing\naccession\naccessional\naccessioned\naccessioning\naccessions\naccessorial\naccessories\naccessorise\naccessorised\naccessorises\naccessorising\naccessorize\naccessorized\naccessorizes\naccessorizing\naccessory\nacciaccatura\nacciaccaturas\nacciaccature\naccidence\naccidences\naccident\naccidental\naccidentally\naccidentalness\naccidentalnesses\naccidentals\naccidently\naccidents\naccidia\naccidias\naccidie\naccidies\naccipiter\naccipiters\naccipitrine\naccipitrines\nacclaim\nacclaimed\nacclaimer\nacclaimers\nacclaiming\nacclaims\nacclamation\nacclamations\nacclimate\nacclimated\nacclimates\nacclimating\nacclimation\nacclimations\nacclimatise\nacclimatised\nacclimatises\nacclimatising\nacclimatization\nacclimatizations\nacclimatize\nacclimatized\nacclimatizer\nacclimatizers\nacclimatizes\nacclimatizing\nacclivities\nacclivity\naccolade\naccolades\naccommodate\naccommodated\naccommodates\naccommodating\naccommodatingly\naccommodation\naccommodational\naccommodationist\naccommodationists\naccommodations\naccommodative\naccommodativeness\naccommodativenesses\naccommodator\naccommodators\naccompanied\naccompanies\naccompaniment\naccompaniments\naccompanist\naccompanists\naccompany\naccompanying\naccomplice\naccomplices\naccomplish\naccomplishable\naccomplished\naccomplisher\naccomplishers\naccomplishes\naccomplishing\naccomplishment\naccomplishments\naccord\naccordance\naccordances\naccordant\naccordantly\naccorded\naccorder\naccorders\naccording\naccordingly\naccordion\naccordionist\naccordionists\naccordions\naccords\naccost\naccosted\naccosting\naccosts\naccouchement\naccouchements\naccoucheur\naccoucheurs\naccount\naccountabilities\naccountability\naccountable\naccountableness\naccountablenesses\naccountably\naccountancies\naccountancy\naccountant\naccountants\naccountantship\naccountantships\naccounted\naccounting\naccountings\naccounts\naccouter\naccoutered\naccoutering\naccouterment\naccouterments\naccouters\naccoutre\naccoutred\naccoutrement\naccoutrements\naccoutres\naccoutring\naccredit\naccreditable\naccreditation\naccreditations\naccredited\naccrediting\naccredits\naccrete\naccreted\naccretes\naccreting\naccretion\naccretionary\naccretions\naccretive\naccruable\naccrual\naccruals\naccrue\naccrued\naccruement\naccruements\naccrues\naccruing\nacculturate\nacculturated\nacculturates\nacculturating\nacculturation\nacculturational\nacculturations\nacculturative\naccumulate\naccumulated\naccumulates\naccumulating\naccumulation\naccumulations\naccumulative\naccumulatively\naccumulativeness\naccumulativenesses\naccumulator\naccumulators\naccuracies\naccuracy\naccurate\naccurately\naccurateness\naccuratenesses\naccursed\naccursedly\naccursedness\naccursednesses\naccurst\naccusal\naccusals\naccusant\naccusants\naccusation\naccusations\naccusative\naccusatives\naccusatory\naccuse\naccused\naccuser\naccusers\naccuses\naccusing\naccusingly\naccustom\naccustomation\naccustomations\naccustomed\naccustomedness\naccustomednesses\naccustoming\naccustoms\nace\naced\nacedia\nacedias\naceldama\naceldamas\nacellular\nacentric\nacephalous\nacequia\nacequias\nacerate\nacerated\nacerb\nacerbate\nacerbated\nacerbates\nacerbating\nacerber\nacerbest\nacerbic\nacerbically\nacerbities\nacerbity\nacerola\nacerolas\nacerose\nacerous\nacervate\nacervuli\nacervulus\naces\nacescent\nacescents\naceta\nacetabula\nacetabular\nacetabulum\nacetabulums\nacetal\nacetaldehyde\nacetaldehydes\nacetals\nacetamid\nacetamide\nacetamides\nacetamids\nacetaminophen\nacetaminophens\nacetanilid\nacetanilide\nacetanilides\nacetanilids\nacetate\nacetated\nacetates\nacetazolamide\nacetazolamides\nacetic\nacetification\nacetifications\nacetified\nacetifies\nacetify\nacetifying\nacetin\nacetins\nacetone\nacetones\nacetonic\nacetonitrile\nacetonitriles\nacetophenetidin\nacetophenetidins\nacetose\nacetous\nacetoxyl\nacetoxyls\nacetum\nacetyl\nacetylate\nacetylated\nacetylates\nacetylating\nacetylation\nacetylations\nacetylative\nacetylcholine\nacetylcholines\nacetylcholinesterase\nacetylcholinesterases\nacetylene\nacetylenes\nacetylenic\nacetylic\nacetyls\nacetylsalicylate\nacetylsalicylates\nachalasia\nachalasias\nache\nached\nachene\nachenes\nachenial\naches\nachier\nachiest\nachievable\nachieve\nachieved\nachievement\nachievements\nachiever\nachievers\nachieves\nachieving\nachillea\nachilleas\nachiness\nachinesses\naching\nachingly\nachiote\nachiotes\nachlorhydria\nachlorhydrias\nachlorhydric\nacholia\nacholias\nachondrite\nachondrites\nachondritic\nachondroplasia\nachondroplasias\nachondroplastic\nachoo\nachromat\nachromatic\nachromatically\nachromatism\nachromatisms\nachromatize\nachromatized\nachromatizes\nachromatizing\nachromats\nachromic\nachy\nacicula\naciculae\nacicular\naciculas\naciculum\naciculums\nacid\nacidemia\nacidemias\nacidhead\nacidheads\nacidic\nacidification\nacidifications\nacidified\nacidifier\nacidifiers\nacidifies\nacidify\nacidifying\nacidimeter\nacidimeters\nacidimetric\nacidimetries\nacidimetry\nacidities\nacidity\nacidly\nacidness\nacidnesses\nacidophil\nacidophile\nacidophiles\nacidophilic\nacidophils\nacidoses\nacidosis\nacidotic\nacids\nacidulate\nacidulated\nacidulates\nacidulating\nacidulation\nacidulations\nacidulent\nacidulous\naciduria\nacidurias\nacidy\nacierate\nacierated\nacierates\nacierating\naciform\nacinar\nacing\nacini\nacinic\nacinose\nacinous\nacinus\nackee\nackees\nacknowledge\nacknowledged\nacknowledgedly\nacknowledgement\nacknowledgements\nacknowledges\nacknowledging\nacknowledgment\nacknowledgments\naclinic\nacmatic\nacme\nacmes\nacmic\nacne\nacned\nacnes\nacnode\nacnodes\nacock\nacoelomate\nacoelomates\nacold\nacolyte\nacolytes\naconite\naconites\naconitic\naconitum\naconitums\nacorn\nacorns\nacoustic\nacoustical\nacoustically\nacoustician\nacousticians\nacoustics\nacquaint\nacquaintance\nacquaintances\nacquaintanceship\nacquaintanceships\nacquainted\nacquainting\nacquaints\nacquest\nacquests\nacquiesce\nacquiesced\nacquiescence\nacquiescences\nacquiescent\nacquiescently\nacquiesces\nacquiescing\nacquirable\nacquire\nacquired\nacquirement\nacquirements\nacquirer\nacquirers\nacquires\nacquiring\nacquisition\nacquisitional\nacquisitions\nacquisitive\nacquisitively\nacquisitiveness\nacquisitivenesses\nacquisitor\nacquisitors\nacquit\nacquits\nacquittal\nacquittals\nacquittance\nacquittances\nacquitted\nacquitter\nacquitters\nacquitting\nacrasia\nacrasias\nacrasin\nacrasins\nacre\nacreage\nacreages\nacred\nacres\nacrid\nacrider\nacridest\nacridine\nacridines\nacridities\nacridity\nacridly\nacridness\nacridnesses\nacriflavine\nacriflavines\nacrimonies\nacrimonious\nacrimoniously\nacrimoniousness\nacrimoniousnesses\nacrimony\nacritarch\nacritarchs\nacrobat\nacrobatic\nacrobatically\nacrobatics\nacrobats\nacrocentric\nacrocentrics\nacrodont\nacrodonts\nacrogen\nacrogens\nacrolect\nacrolects\nacrolein\nacroleins\nacrolith\nacroliths\nacromegalic\nacromegalics\nacromegalies\nacromegaly\nacromia\nacromial\nacromion\nacromions\nacronic\nacronym\nacronymic\nacronymically\nacronyms\nacropetal\nacropetally\nacrophobe\nacrophobes\nacrophobia\nacrophobias\nacropolis\nacropolises\nacrosomal\nacrosome\nacrosomes\nacross\nacrostic\nacrostical\nacrostically\nacrostics\nacrotic\nacrotism\nacrotisms\nacrylamide\nacrylamides\nacrylate\nacrylates\nacrylic\nacrylics\nacrylonitrile\nacrylonitriles\nact\nacta\nactabilities\nactability\nactable\nacted\nactin\nactinal\nacting\nactings\nactinia\nactiniae\nactinian\nactinians\nactinias\nactinic\nactinically\nactinide\nactinides\nactinism\nactinisms\nactinium\nactiniums\nactinoid\nactinoids\nactinolite\nactinolites\nactinometer\nactinometers\nactinometric\nactinometries\nactinometry\nactinomorphic\nactinomorphies\nactinomorphy\nactinomyces\nactinomycete\nactinomycetes\nactinomycetous\nactinomycin\nactinomycins\nactinomycoses\nactinomycosis\nactinomycotic\nactinon\nactinons\nactins\naction\nactionable\nactionably\nactionless\nactions\nactivate\nactivated\nactivates\nactivating\nactivation\nactivations\nactivator\nactivators\nactive\nactively\nactiveness\nactivenesses\nactives\nactivism\nactivisms\nactivist\nactivistic\nactivists\nactivities\nactivity\nactivize\nactivized\nactivizes\nactivizing\nactomyosin\nactomyosins\nactor\nactorish\nactors\nactress\nactresses\nactressy\nacts\nactual\nactualities\nactuality\nactualization\nactualizations\nactualize\nactualized\nactualizes\nactualizing\nactually\nactuarial\nactuarially\nactuaries\nactuary\nactuate\nactuated\nactuates\nactuating\nactuation\nactuations\nactuator\nactuators\nacuate\nacuities\nacuity\naculeate\naculei\naculeus\nacumen\nacumens\nacuminate\nacupressure\nacupressures\nacupuncture\nacupunctures\nacupuncturist\nacupuncturists\nacutance\nacutances\nacute\nacutely\nacuteness\nacutenesses\nacuter\nacutes\nacutest\nacyclic\nacyclovir\nacyclovirs\nacyl\nacylate\nacylated\nacylates\nacylating\nacylation\nacylations\nacyloin\nacyloins\nacyls\nad\nadage\nadages\nadagial\nadagio\nadagios\nadamance\nadamances\nadamancies\nadamancy\nadamant\nadamantine\nadamantly\nadamants\nadamsite\nadamsites\nadapt\nadaptabilities\nadaptability\nadaptable\nadaptation\nadaptational\nadaptationally\nadaptations\nadapted\nadaptedness\nadaptednesses\nadapter\nadapters\nadapting\nadaption\nadaptions\nadaptive\nadaptively\nadaptiveness\nadaptivenesses\nadaptivities\nadaptivity\nadaptor\nadaptors\nadapts\nadaxial\nadd\naddable\naddax\naddaxes\nadded\naddedly\naddend\naddenda\naddends\naddendum\nadder\nadders\naddible\naddict\naddicted\naddicting\naddiction\naddictions\naddictive\naddicts\nadding\naddition\nadditional\nadditionally\nadditions\nadditive\nadditively\nadditives\nadditivities\nadditivity\nadditory\naddle\naddled\naddlepated\naddles\naddling\naddress\naddressabilities\naddressability\naddressable\naddressed\naddressee\naddressees\naddresser\naddressers\naddresses\naddressing\naddrest\nadds\nadduce\nadduced\nadducent\nadducer\nadducers\nadduces\nadducing\nadduct\nadducted\nadducting\nadduction\nadductions\nadductive\nadductor\nadductors\nadducts\nadeem\nadeemed\nadeeming\nadeems\nadenine\nadenines\nadenitis\nadenitises\nadenocarcinoma\nadenocarcinomas\nadenocarcinomata\nadenocarcinomatous\nadenohypophyseal\nadenohypophyses\nadenohypophysial\nadenohypophysis\nadenoid\nadenoidal\nadenoids\nadenoma\nadenomas\nadenomata\nadenomatous\nadenoses\nadenosine\nadenosines\nadenosis\nadenoviral\nadenovirus\nadenoviruses\nadenyl\nadenyls\nadept\nadepter\nadeptest\nadeptly\nadeptness\nadeptnesses\nadepts\nadequacies\nadequacy\nadequate\nadequately\nadequateness\nadequatenesses\nadhere\nadhered\nadherence\nadherences\nadherend\nadherends\nadherent\nadherently\nadherents\nadherer\nadherers\nadheres\nadhering\nadhesion\nadhesional\nadhesions\nadhesive\nadhesively\nadhesiveness\nadhesivenesses\nadhesives\nadhibit\nadhibited\nadhibiting\nadhibits\nadiabatic\nadiabatically\nadieu\nadieus\nadieux\nadios\nadipic\nadipocyte\nadipocytes\nadipose\nadiposes\nadiposis\nadiposities\nadiposity\nadipous\nadit\nadits\nadjacencies\nadjacency\nadjacent\nadjacently\nadjectival\nadjectivally\nadjective\nadjectively\nadjectives\nadjoin\nadjoined\nadjoining\nadjoins\nadjoint\nadjoints\nadjourn\nadjourned\nadjourning\nadjournment\nadjournments\nadjourns\nadjudge\nadjudged\nadjudges\nadjudging\nadjudicate\nadjudicated\nadjudicates\nadjudicating\nadjudication\nadjudications\nadjudicative\nadjudicator\nadjudicators\nadjudicatory\nadjunct\nadjunction\nadjunctions\nadjunctive\nadjunctly\nadjuncts\nadjuration\nadjurations\nadjuratory\nadjure\nadjured\nadjurer\nadjurers\nadjures\nadjuring\nadjuror\nadjurors\nadjust\nadjustabilities\nadjustability\nadjustable\nadjusted\nadjuster\nadjusters\nadjusting\nadjustive\nadjustment\nadjustmental\nadjustments\nadjustor\nadjustors\nadjusts\nadjutancies\nadjutancy\nadjutant\nadjutants\nadjuvant\nadjuvants\nadman\nadmass\nadmasses\nadmeasure\nadmeasured\nadmeasurement\nadmeasurements\nadmeasures\nadmeasuring\nadmen\nadminister\nadministered\nadministering\nadministers\nadministrable\nadministrant\nadministrants\nadministrate\nadministrated\nadministrates\nadministrating\nadministration\nadministrations\nadministrative\nadministratively\nadministrator\nadministrators\nadministratrices\nadministratrix\nadmirabilities\nadmirability\nadmirable\nadmirableness\nadmirablenesses\nadmirably\nadmiral\nadmirals\nadmiralties\nadmiralty\nadmiration\nadmirations\nadmire\nadmired\nadmirer\nadmirers\nadmires\nadmiring\nadmiringly\nadmissibilities\nadmissibility\nadmissible\nadmission\nadmissions\nadmissive\nadmit\nadmits\nadmittance\nadmittances\nadmitted\nadmittedly\nadmitter\nadmitters\nadmitting\nadmix\nadmixed\nadmixes\nadmixing\nadmixt\nadmixture\nadmixtures\nadmonish\nadmonished\nadmonisher\nadmonishers\nadmonishes\nadmonishing\nadmonishingly\nadmonishment\nadmonishments\nadmonition\nadmonitions\nadmonitorily\nadmonitory\nadnate\nadnation\nadnations\nadnexa\nadnexal\nadnoun\nadnouns\nado\nadobe\nadobelike\nadobes\nadobo\nadobos\nadolescence\nadolescences\nadolescent\nadolescently\nadolescents\nadonis\nadonises\nadopt\nadoptabilities\nadoptability\nadoptable\nadopted\nadoptee\nadoptees\nadopter\nadopters\nadoptianism\nadoptianisms\nadopting\nadoption\nadoptionism\nadoptionisms\nadoptionist\nadoptionists\nadoptions\nadoptive\nadoptively\nadopts\nadorabilities\nadorability\nadorable\nadorableness\nadorablenesses\nadorably\nadoration\nadorations\nadore\nadored\nadorer\nadorers\nadores\nadoring\nadoringly\nadorn\nadorned\nadorner\nadorners\nadorning\nadornment\nadornments\nadorns\nados\nadown\nadoze\nadrenal\nadrenalectomies\nadrenalectomized\nadrenalectomy\nadrenaline\nadrenalines\nadrenalized\nadrenals\nadrenergic\nadrenergically\nadrenochrome\nadrenochromes\nadrenocortical\nadrenocorticosteroid\nadrenocorticosteroids\nadrenocorticotrophic\nadrenocorticotrophin\nadrenocorticotrophins\nadrenocorticotropic\nadrenocorticotropin\nadrenocorticotropins\nadrift\nadroit\nadroiter\nadroitest\nadroitly\nadroitness\nadroitnesses\nads\nadscititious\nadscript\nadscripts\nadsorb\nadsorbable\nadsorbate\nadsorbates\nadsorbed\nadsorbent\nadsorbents\nadsorber\nadsorbers\nadsorbing\nadsorbs\nadsorption\nadsorptions\nadsorptive\nadularia\nadularias\nadulate\nadulated\nadulates\nadulating\nadulation\nadulations\nadulator\nadulators\nadulatory\nadult\nadulterant\nadulterants\nadulterate\nadulterated\nadulterates\nadulterating\nadulteration\nadulterations\nadulterator\nadulterators\nadulterer\nadulterers\nadulteress\nadulteresses\nadulteries\nadulterine\nadulterous\nadulterously\nadultery\nadulthood\nadulthoods\nadultlike\nadultly\nadultness\nadultnesses\nadults\nadumbral\nadumbrate\nadumbrated\nadumbrates\nadumbrating\nadumbration\nadumbrations\nadumbrative\nadumbratively\nadunc\naduncate\naduncous\nadust\nadvance\nadvanced\nadvancement\nadvancements\nadvancer\nadvancers\nadvances\nadvancing\nadvantage\nadvantaged\nadvantageous\nadvantageously\nadvantageousness\nadvantageousnesses\nadvantages\nadvantaging\nadvect\nadvected\nadvecting\nadvection\nadvections\nadvective\nadvects\nadvent\nadventitia\nadventitial\nadventitias\nadventitious\nadventitiously\nadventive\nadventives\nadvents\nadventure\nadventured\nadventurer\nadventurers\nadventures\nadventuresome\nadventuresomeness\nadventuresomenesses\nadventuress\nadventuresses\nadventuring\nadventurism\nadventurisms\nadventurist\nadventuristic\nadventurists\nadventurous\nadventurously\nadventurousness\nadventurousnesses\nadverb\nadverbial\nadverbially\nadverbials\nadverbs\nadversarial\nadversaries\nadversariness\nadversarinesses\nadversary\nadversative\nadversatively\nadversatives\nadverse\nadversely\nadverseness\nadversenesses\nadversities\nadversity\nadvert\nadverted\nadvertence\nadvertences\nadvertencies\nadvertency\nadvertent\nadvertently\nadverting\nadvertise\nadvertised\nadvertisement\nadvertisements\nadvertiser\nadvertisers\nadvertises\nadvertising\nadvertisings\nadvertize\nadvertized\nadvertizement\nadvertizements\nadvertizes\nadvertizing\nadvertorial\nadvertorials\nadverts\nadvice\nadvices\nadvisabilities\nadvisability\nadvisable\nadvisableness\nadvisablenesses\nadvisably\nadvise\nadvised\nadvisedly\nadvisee\nadvisees\nadvisement\nadvisements\nadviser\nadvisers\nadvises\nadvising\nadvisor\nadvisories\nadvisors\nadvisory\nadvocacies\nadvocacy\nadvocate\nadvocated\nadvocates\nadvocating\nadvocation\nadvocations\nadvocative\nadvocator\nadvocators\nadvowson\nadvowsons\nadynamia\nadynamias\nadynamic\nadyta\nadytum\nadz\nadze\nadzes\nadzuki\nadzukis\nae\naecia\naecial\naecidia\naecidial\naecidium\naeciospore\naeciospores\naecium\naedes\naedile\naediles\naedine\naegis\naegises\naeneous\naeneus\naeolian\naeon\naeonian\naeonic\naeons\naepyornis\naepyornises\naequorin\naequorins\naerate\naerated\naerates\naerating\naeration\naerations\naerator\naerators\naerenchyma\naerenchymas\naerenchymata\naerial\naerialist\naerialists\naerially\naerials\naerie\naeried\naerier\naeries\naeriest\naerified\naerifies\naeriform\naerify\naerifying\naerily\naero\naerobatic\naerobatics\naerobe\naerobes\naerobia\naerobic\naerobically\naerobicize\naerobicized\naerobicizes\naerobicizing\naerobics\naerobiological\naerobiologies\naerobiology\naerobioses\naerobiosis\naerobium\naerobrake\naerobraked\naerobrakes\naerobraking\naerodrome\naerodromes\naeroduct\naeroducts\naerodynamic\naerodynamical\naerodynamically\naerodynamicist\naerodynamicists\naerodynamics\naerodyne\naerodynes\naeroelastic\naeroelasticities\naeroelasticity\naeroembolism\naeroembolisms\naerofoil\naerofoils\naerogel\naerogels\naerogram\naerogramme\naerogrammes\naerograms\naerolite\naerolites\naerolith\naeroliths\naerologies\naerology\naeromagnetic\naeromechanics\naeromedical\naeromedicine\naeromedicines\naerometer\naerometers\naeronaut\naeronautic\naeronautical\naeronautically\naeronautics\naeronauts\naeronomer\naeronomers\naeronomic\naeronomical\naeronomies\naeronomist\naeronomists\naeronomy\naeroplane\naeroplanes\naerosat\naerosats\naerosol\naerosolization\naerosolizations\naerosolize\naerosolized\naerosolizes\naerosolizing\naerosols\naerospace\naerospaces\naerostat\naerostatics\naerostats\naerothermodynamic\naerothermodynamics\naerugo\naerugos\naery\naesthete\naesthetes\naesthetic\naesthetical\naesthetically\naesthetician\naestheticians\naestheticism\naestheticisms\naestheticize\naestheticized\naestheticizes\naestheticizing\naesthetics\naestival\naestivate\naestivated\naestivates\naestivating\naestivation\naestivations\naether\naetheric\naethers\naetiologies\naetiology\nafar\nafars\nafeard\nafeared\nafebrile\naff\naffabilities\naffability\naffable\naffably\naffair\naffaire\naffaires\naffairs\naffect\naffectabilities\naffectability\naffectable\naffectation\naffectations\naffected\naffectedly\naffectedness\naffectednesses\naffecter\naffecters\naffecting\naffectingly\naffection\naffectional\naffectionally\naffectionate\naffectionately\naffectioned\naffectionless\naffections\naffective\naffectively\naffectivities\naffectivity\naffectless\naffectlessness\naffectlessnesses\naffects\naffenpinscher\naffenpinschers\nafferent\nafferently\nafferents\naffiance\naffianced\naffiances\naffiancing\naffiant\naffiants\naffiche\naffiches\nafficionado\nafficionados\naffidavit\naffidavits\naffiliate\naffiliated\naffiliates\naffiliating\naffiliation\naffiliations\naffinal\naffine\naffined\naffinely\naffines\naffinities\naffinity\naffirm\naffirmable\naffirmance\naffirmances\naffirmation\naffirmations\naffirmative\naffirmatively\naffirmatives\naffirmed\naffirmer\naffirmers\naffirming\naffirms\naffix\naffixable\naffixal\naffixation\naffixations\naffixed\naffixer\naffixers\naffixes\naffixial\naffixing\naffixment\naffixments\nafflatus\nafflatuses\nafflict\nafflicted\nafflicting\naffliction\nafflictions\nafflictive\nafflictively\nafflicts\naffluence\naffluences\naffluencies\naffluency\naffluent\naffluently\naffluents\nafflux\naffluxes\nafford\naffordabilities\naffordability\naffordable\naffordably\nafforded\naffording\naffords\nafforest\nafforestation\nafforestations\nafforested\nafforesting\nafforests\naffray\naffrayed\naffrayer\naffrayers\naffraying\naffrays\naffricate\naffricates\naffricative\naffricatives\naffright\naffrighted\naffrighting\naffrights\naffront\naffronted\naffronting\naffronts\naffusion\naffusions\nafghan\nafghani\nafghanis\nafghans\naficionada\naficionadas\naficionado\naficionados\nafield\nafire\naflame\naflatoxin\naflatoxins\nafloat\naflutter\nafoot\nafore\naforementioned\naforesaid\naforethought\nafoul\nafraid\nafreet\nafreets\nafresh\nafrit\nafrits\naft\nafter\nafterbirth\nafterbirths\nafterburner\nafterburners\naftercare\naftercares\nafterclap\nafterclaps\nafterdeck\nafterdecks\naftereffect\naftereffects\nafterglow\nafterglows\nafterimage\nafterimages\nafterlife\nafterlives\naftermarket\naftermarkets\naftermath\naftermaths\naftermost\nafternoon\nafternoons\nafterpiece\nafterpieces\nafters\naftershave\naftershaves\naftershock\naftershocks\naftertaste\naftertastes\naftertax\nafterthought\nafterthoughts\naftertime\naftertimes\nafterward\nafterwards\nafterword\nafterwords\nafterworld\nafterworlds\naftmost\naftosa\naftosas\nag\naga\nagain\nagainst\nagalloch\nagallochs\nagalwood\nagalwoods\nagama\nagamas\nagamete\nagametes\nagamic\nagammaglobulinemia\nagammaglobulinemias\nagammaglobulinemic\nagamospermies\nagamospermy\nagamous\nagapae\nagapai\nagapanthus\nagapanthuses\nagape\nagapeic\nagar\nagaric\nagarics\nagarose\nagaroses\nagars\nagas\nagate\nagates\nagatize\nagatized\nagatizes\nagatizing\nagatoid\nagave\nagaves\nagaze\nage\naged\nagedly\nagedness\nagednesses\nagee\nageing\nageings\nageism\nageisms\nageist\nageists\nageless\nagelessly\nagelessness\nagelessnesses\nagelong\nagencies\nagency\nagenda\nagendaless\nagendas\nagendum\nagendums\nagene\nagenes\nageneses\nagenesia\nagenesias\nagenesis\nagenetic\nagenize\nagenized\nagenizes\nagenizing\nagent\nagential\nagenting\nagentings\nagentive\nagentives\nagentries\nagentry\nagents\nager\nageratum\nageratums\nagers\nages\naggadic\nagger\naggers\naggie\naggies\naggiornamento\naggiornamentos\nagglomerate\nagglomerated\nagglomerates\nagglomerating\nagglomeration\nagglomerations\nagglomerative\nagglutinabilities\nagglutinability\nagglutinable\nagglutinate\nagglutinated\nagglutinates\nagglutinating\nagglutination\nagglutinations\nagglutinative\nagglutinin\nagglutinins\nagglutinogen\nagglutinogenic\nagglutinogens\naggradation\naggradations\naggrade\naggraded\naggrades\naggrading\naggrandise\naggrandised\naggrandises\naggrandising\naggrandize\naggrandized\naggrandizement\naggrandizements\naggrandizer\naggrandizers\naggrandizes\naggrandizing\naggravate\naggravated\naggravates\naggravating\naggravation\naggravations\naggregate\naggregated\naggregately\naggregateness\naggregatenesses\naggregates\naggregating\naggregation\naggregational\naggregations\naggregative\naggregatively\naggress\naggressed\naggresses\naggressing\naggression\naggressions\naggressive\naggressively\naggressiveness\naggressivenesses\naggressivities\naggressivity\naggressor\naggressors\naggrieve\naggrieved\naggrievedly\naggrievement\naggrievements\naggrieves\naggrieving\naggro\naggros\nagha\naghas\naghast\nagile\nagilely\nagilities\nagility\nagin\naging\nagings\naginner\naginners\nagio\nagios\nagiotage\nagiotages\nagism\nagisms\nagist\nagisted\nagisting\nagists\nagitable\nagitate\nagitated\nagitatedly\nagitates\nagitating\nagitation\nagitational\nagitations\nagitative\nagitato\nagitator\nagitators\nagitprop\nagitprops\naglare\nagleam\naglee\naglet\naglets\nagley\naglimmer\naglitter\naglow\nagly\naglycon\naglycone\naglycones\naglycons\nagma\nagmas\nagminate\nagnail\nagnails\nagnate\nagnates\nagnatic\nagnation\nagnations\nagnize\nagnized\nagnizes\nagnizing\nagnomen\nagnomens\nagnomina\nagnosia\nagnosias\nagnostic\nagnosticism\nagnosticisms\nagnostics\nago\nagog\nagon\nagonal\nagone\nagones\nagonic\nagonies\nagonise\nagonised\nagonises\nagonising\nagonist\nagonistes\nagonistic\nagonistically\nagonists\nagonize\nagonized\nagonizes\nagonizing\nagonizingly\nagons\nagony\nagora\nagorae\nagoraphobe\nagoraphobes\nagoraphobia\nagoraphobias\nagoraphobic\nagoraphobics\nagoras\nagorot\nagoroth\nagouti\nagouties\nagoutis\nagouty\nagrafe\nagrafes\nagraffe\nagraffes\nagranulocyte\nagranulocytes\nagranulocytoses\nagranulocytosis\nagrapha\nagraphia\nagraphias\nagraphic\nagrarian\nagrarianism\nagrarianisms\nagrarians\nagravic\nagree\nagreeabilities\nagreeability\nagreeable\nagreeableness\nagreeablenesses\nagreeably\nagreed\nagreeing\nagreement\nagreements\nagrees\nagrestal\nagrestic\nagria\nagrias\nagribusiness\nagribusinesses\nagribusinessman\nagribusinessmen\nagrichemical\nagrichemicals\nagricultural\nagriculturalist\nagriculturalists\nagriculturally\nagriculture\nagricultures\nagriculturist\nagriculturists\nagrimonies\nagrimony\nagrochemical\nagrochemicals\nagroforester\nagroforesters\nagroforestries\nagroforestry\nagrologies\nagrology\nagronomic\nagronomically\nagronomies\nagronomist\nagronomists\nagronomy\naground\nagrypnia\nagrypnias\nague\naguelike\nagues\nagueweed\nagueweeds\naguish\naguishly\nah\naha\nahchoo\nahead\nahem\nahimsa\nahimsas\nahistoric\nahistorical\nahold\naholds\nahorse\nahoy\nahull\nai\naiblins\naid\naide\naided\naider\naiders\naides\naidful\naiding\naidless\naidman\naidmen\naids\naiglet\naiglets\naigret\naigrets\naigrette\naigrettes\naiguille\naiguilles\naiguillette\naiguillettes\naikido\naikidos\nail\nailanthus\nailanthuses\nailed\naileron\nailerons\nailing\nailment\nailments\nails\nailurophile\nailurophiles\nailurophobe\nailurophobes\nailurophobia\nailurophobias\naim\naimed\naimer\naimers\naimful\naimfully\naiming\naimless\naimlessly\naimlessness\naimlessnesses\naims\nain\nains\nainsell\nainsells\naioli\naiolis\nair\nairbag\nairbags\nairboat\nairboats\nairborne\nairbound\nairbrush\nairbrushed\nairbrushes\nairbrushing\nairburst\nairbursts\nairbus\nairbuses\nairbusses\naircheck\nairchecks\naircoach\naircoaches\naircraft\naircrew\naircrews\nairdate\nairdates\nairdrome\nairdromes\nairdrop\nairdropped\nairdropping\nairdrops\naired\nairer\nairers\nairest\nairfare\nairfares\nairfield\nairfields\nairflow\nairflows\nairfoil\nairfoils\nairframe\nairframes\nairfreight\nairfreighted\nairfreighting\nairfreights\nairglow\nairglows\nairhead\nairheaded\nairheads\nairhole\nairholes\nairier\nairiest\nairily\nairiness\nairinesses\nairing\nairings\nairless\nairlessness\nairlessnesses\nairlift\nairlifted\nairlifting\nairlifts\nairlike\nairline\nairliner\nairliners\nairlines\nairmail\nairmailed\nairmailing\nairmails\nairman\nairmanship\nairmanships\nairmen\nairmobile\nairn\nairns\nairpark\nairparks\nairplane\nairplanes\nairplay\nairplays\nairport\nairports\nairpost\nairposts\nairpower\nairpowers\nairproof\nairproofed\nairproofing\nairproofs\nairs\nairscape\nairscapes\nairscrew\nairscrews\nairshed\nairsheds\nairship\nairships\nairsick\nairsickness\nairsicknesses\nairspace\nairspaces\nairspeed\nairspeeds\nairstream\nairstreams\nairstrike\nairstrikes\nairstrip\nairstrips\nairt\nairted\nairth\nairthed\nairthing\nairths\nairtight\nairtightness\nairtightnesses\nairtime\nairtimes\nairting\nairts\nairward\nairwave\nairwaves\nairway\nairways\nairwise\nairwoman\nairwomen\nairworthier\nairworthiest\nairworthiness\nairworthinesses\nairworthy\nairy\nais\naisle\naisled\naisles\naisleway\naisleways\nait\naitch\naitchbone\naitchbones\naitches\naits\naiver\naivers\najar\najee\najiva\najivas\najowan\najowans\najuga\najugas\nakee\nakees\nakela\nakelas\nakene\nakenes\nakimbo\nakin\nakvavit\nakvavits\nal\nala\nalabaster\nalabasters\nalabastrine\nalack\nalacrities\nalacritous\nalacrity\nalae\nalameda\nalamedas\nalamo\nalamode\nalamodes\nalamos\nalan\naland\nalands\nalane\nalang\nalanin\nalanine\nalanines\nalanins\nalans\nalant\nalants\nalanyl\nalanyls\nalar\nalarm\nalarmed\nalarming\nalarmingly\nalarmism\nalarmisms\nalarmist\nalarmists\nalarms\nalarum\nalarumed\nalaruming\nalarums\nalary\nalas\nalaska\nalaskas\nalastor\nalastors\nalate\nalated\nalates\nalation\nalations\nalb\nalba\nalbacore\nalbacores\nalbas\nalbata\nalbatas\nalbatross\nalbatrosses\nalbedo\nalbedoes\nalbedos\nalbeit\nalbicore\nalbicores\nalbinal\nalbinic\nalbinism\nalbinisms\nalbinistic\nalbino\nalbinos\nalbinotic\nalbite\nalbites\nalbitic\nalbizia\nalbizias\nalbizzia\nalbizzias\nalbs\nalbum\nalbumen\nalbumens\nalbumin\nalbuminous\nalbumins\nalbuminuria\nalbuminurias\nalbuminuric\nalbumose\nalbumoses\nalbums\nalburnum\nalburnums\nalcade\nalcades\nalcahest\nalcahests\nalcaic\nalcaics\nalcaide\nalcaides\nalcalde\nalcaldes\nalcayde\nalcaydes\nalcazar\nalcazars\nalchemic\nalchemical\nalchemically\nalchemies\nalchemist\nalchemistic\nalchemistical\nalchemists\nalchemize\nalchemized\nalchemizes\nalchemizing\nalchemy\nalchymies\nalchymy\nalcid\nalcidine\nalcids\nalcohol\nalcoholic\nalcoholically\nalcoholics\nalcoholism\nalcoholisms\nalcohols\nalcove\nalcoved\nalcoves\nalcyonarian\nalcyonarians\naldehyde\naldehydes\naldehydic\nalder\nalderflies\nalderfly\nalderman\naldermanic\naldermen\nalders\nalderwoman\nalderwomen\naldol\naldolase\naldolases\naldolization\naldolizations\naldols\naldose\naldoses\naldosterone\naldosterones\naldosteronism\naldosteronisms\naldrin\naldrins\nale\naleatoric\naleatory\nalec\nalecs\nalee\nalef\nalefs\nalegar\nalegars\nalehouse\nalehouses\nalembic\nalembics\nalencon\nalencons\naleph\nalephs\nalert\nalerted\nalerter\nalertest\nalerting\nalertly\nalertness\nalertnesses\nalerts\nales\naleuron\naleurone\naleurones\naleurons\nalevin\nalevins\nalewife\nalewives\nalexander\nalexanders\nalexandrine\nalexandrines\nalexandrite\nalexandrites\nalexia\nalexias\nalexin\nalexine\nalexines\nalexins\nalfa\nalfaki\nalfakis\nalfalfa\nalfalfas\nalfaqui\nalfaquin\nalfaquins\nalfaquis\nalfas\nalfilaria\nalfilarias\nalforja\nalforjas\nalfresco\nalga\nalgae\nalgaecide\nalgaecides\nalgal\nalgaroba\nalgarobas\nalgarroba\nalgarrobas\nalgas\nalgebra\nalgebraic\nalgebraically\nalgebraist\nalgebraists\nalgebras\nalgerine\nalgerines\nalgicidal\nalgicide\nalgicides\nalgid\nalgidities\nalgidity\nalgin\nalginate\nalginates\nalgins\nalgoid\nalgolagnia\nalgolagniac\nalgolagniacs\nalgolagnias\nalgological\nalgologies\nalgologist\nalgologists\nalgology\nalgor\nalgorism\nalgorisms\nalgorithm\nalgorithmic\nalgorithmically\nalgorithms\nalgors\nalgum\nalgums\nalias\naliases\nalibi\nalibied\nalibies\nalibiing\nalibis\nalible\nalicyclic\nalidad\nalidade\nalidades\nalidads\nalien\nalienabilities\nalienability\nalienable\nalienage\nalienages\nalienate\nalienated\nalienates\nalienating\nalienation\nalienations\nalienator\nalienators\naliened\nalienee\nalienees\naliener\nalieners\naliening\nalienism\nalienisms\nalienist\nalienists\nalienly\nalienness\naliennesses\nalienor\nalienors\naliens\nalif\naliform\nalifs\nalight\nalighted\nalighting\nalightment\nalightments\nalights\nalign\naligned\naligner\naligners\naligning\nalignment\nalignments\naligns\nalike\nalikeness\nalikenesses\naliment\nalimentary\nalimentation\nalimentations\nalimented\nalimenting\naliments\nalimonies\nalimony\naline\nalined\nalinement\nalinements\naliner\naliners\nalines\nalining\naliped\nalipeds\naliphatic\naliquant\naliquot\naliquots\nalist\nalit\naliteracies\naliteracy\naliterate\naliterates\naliunde\nalive\naliveness\nalivenesses\naliya\naliyah\naliyahs\naliyas\naliyos\naliyot\naliyoth\nalizarin\nalizarins\nalkahest\nalkahestic\nalkahests\nalkali\nalkalic\nalkalies\nalkalified\nalkalifies\nalkalify\nalkalifying\nalkalimeter\nalkalimeters\nalkalimetries\nalkalimetry\nalkalin\nalkaline\nalkalinities\nalkalinity\nalkalinization\nalkalinizations\nalkalinize\nalkalinized\nalkalinizes\nalkalinizing\nalkalis\nalkalise\nalkalised\nalkalises\nalkalising\nalkalize\nalkalized\nalkalizes\nalkalizing\nalkaloid\nalkaloidal\nalkaloids\nalkaloses\nalkalosis\nalkalotic\nalkane\nalkanes\nalkanet\nalkanets\nalkene\nalkenes\nalkies\nalkine\nalkines\nalkoxide\nalkoxides\nalkoxy\nalky\nalkyd\nalkyds\nalkyl\nalkylate\nalkylated\nalkylates\nalkylating\nalkylation\nalkylations\nalkylic\nalkyls\nalkyne\nalkynes\nall\nallanite\nallanites\nallantoic\nallantoides\nallantoin\nallantoins\nallantois\nallargando\nallay\nallayed\nallayer\nallayers\nallaying\nallays\nallee\nallees\nallegation\nallegations\nallege\nalleged\nallegedly\nalleger\nallegers\nalleges\nallegiance\nallegiances\nallegiant\nalleging\nallegorical\nallegorically\nallegoricalness\nallegoricalnesses\nallegories\nallegorise\nallegorised\nallegorises\nallegorising\nallegorist\nallegorists\nallegorization\nallegorizations\nallegorize\nallegorized\nallegorizer\nallegorizers\nallegorizes\nallegorizing\nallegory\nallegretto\nallegrettos\nallegro\nallegros\nallele\nalleles\nallelic\nallelism\nallelisms\nallelomorph\nallelomorphic\nallelomorphism\nallelomorphisms\nallelomorphs\nallelopathic\nallelopathies\nallelopathy\nalleluia\nalleluias\nallemande\nallemandes\nallergen\nallergenic\nallergenicities\nallergenicity\nallergens\nallergic\nallergies\nallergin\nallergins\nallergist\nallergists\nallergy\nallethrin\nallethrins\nalleviate\nalleviated\nalleviates\nalleviating\nalleviation\nalleviations\nalleviator\nalleviators\nalley\nalleys\nalleyway\nalleyways\nallheal\nallheals\nalliable\nalliaceous\nalliance\nalliances\nallicin\nallicins\nallied\nallies\nalligator\nalligators\nalliterate\nalliterated\nalliterates\nalliterating\nalliteration\nalliterations\nalliterative\nalliteratively\nallium\nalliums\nalloantibodies\nalloantibody\nalloantigen\nalloantigens\nallobar\nallobars\nallocable\nallocatable\nallocate\nallocated\nallocates\nallocating\nallocation\nallocations\nallocator\nallocators\nallocution\nallocutions\nallod\nallodia\nallodial\nallodium\nallods\nallogamies\nallogamous\nallogamy\nallogeneic\nallogenic\nallograft\nallografted\nallografting\nallografts\nallograph\nallographic\nallographs\nallometric\nallometries\nallometry\nallomorph\nallomorphic\nallomorphism\nallomorphisms\nallomorphs\nallonge\nallonges\nallonym\nallonyms\nallopath\nallopaths\nallopatric\nallopatrically\nallopatries\nallopatry\nallophane\nallophanes\nallophone\nallophones\nallophonic\nallopolyploid\nallopolyploidies\nallopolyploids\nallopolyploidy\nallopurinol\nallopurinols\nallosaurus\nallosauruses\nallosteric\nallosterically\nallosteries\nallostery\nallot\nallotetraploid\nallotetraploidies\nallotetraploids\nallotetraploidy\nallotment\nallotments\nallotrope\nallotropes\nallotropic\nallotropies\nallotropy\nallots\nallotted\nallottee\nallottees\nallotter\nallotters\nallotting\nallotype\nallotypes\nallotypic\nallotypically\nallotypies\nallotypy\nallover\nallovers\nallow\nallowable\nallowably\nallowance\nallowanced\nallowances\nallowancing\nallowed\nallowedly\nallowing\nallows\nalloxan\nalloxans\nalloy\nalloyed\nalloying\nalloys\nalls\nallseed\nallseeds\nallspice\nallspices\nallude\nalluded\nalludes\nalluding\nallure\nallured\nallurement\nallurements\nallurer\nallurers\nallures\nalluring\nalluringly\nallusion\nallusions\nallusive\nallusively\nallusiveness\nallusivenesses\nalluvia\nalluvial\nalluvials\nalluvion\nalluvions\nalluvium\nalluviums\nally\nallying\nallyl\nallylic\nallyls\nalma\nalmagest\nalmagests\nalmah\nalmahs\nalmanac\nalmanacs\nalmandine\nalmandines\nalmandite\nalmandites\nalmas\nalme\nalmeh\nalmehs\nalmemar\nalmemars\nalmes\nalmightiness\nalmightinesses\nalmighty\nalmner\nalmners\nalmond\nalmonds\nalmoner\nalmoners\nalmonries\nalmonry\nalmost\nalms\nalmsgiver\nalmsgivers\nalmsgiving\nalmsgivings\nalmshouse\nalmshouses\nalmsman\nalmsmen\nalmuce\nalmuces\nalmud\nalmude\nalmudes\nalmuds\nalmug\nalmugs\nalnico\nalnicoes\nalnicos\nalodia\nalodial\nalodium\naloe\naloes\naloetic\naloft\nalogical\nalogically\naloha\nalohas\naloin\naloins\nalone\naloneness\nalonenesses\nalong\nalongshore\nalongside\naloof\naloofly\naloofness\naloofnesses\nalopecia\nalopecias\nalopecic\naloud\nalow\nalp\nalpaca\nalpacas\nalpenglow\nalpenglows\nalpenhorn\nalpenhorns\nalpenstock\nalpenstocks\nalpha\nalphabet\nalphabeted\nalphabetic\nalphabetical\nalphabetically\nalphabeting\nalphabetization\nalphabetizations\nalphabetize\nalphabetized\nalphabetizer\nalphabetizers\nalphabetizes\nalphabetizing\nalphabets\nalphameric\nalphanumeric\nalphanumerical\nalphanumerically\nalphanumerics\nalphas\nalphorn\nalphorns\nalphosis\nalphosises\nalphyl\nalphyls\nalpine\nalpinely\nalpines\nalpinism\nalpinisms\nalpinist\nalpinists\nalps\nalready\nalright\nals\nalsike\nalsikes\nalso\nalt\naltar\naltarpiece\naltarpieces\naltars\naltazimuth\naltazimuths\nalter\nalterabilities\nalterability\nalterable\nalterably\nalterant\nalterants\nalteration\nalterations\naltercate\naltercated\naltercates\naltercating\naltercation\naltercations\naltered\nalterer\nalterers\naltering\nalternate\nalternated\nalternately\nalternates\nalternating\nalternation\nalternations\nalternative\nalternatively\nalternativeness\nalternativenesses\nalternatives\nalternator\nalternators\nalters\nalthaea\nalthaeas\nalthea\naltheas\naltho\nalthorn\nalthorns\nalthough\naltimeter\naltimeters\naltimetries\naltimetry\naltiplano\naltiplanos\naltitude\naltitudes\naltitudinal\naltitudinous\nalto\naltocumuli\naltocumulus\naltogether\naltogethers\naltoist\naltoists\naltos\naltostrati\naltostratus\naltricial\naltruism\naltruisms\naltruist\naltruistic\naltruistically\naltruists\nalts\naludel\naludels\nalula\nalulae\nalular\nalum\nalumin\nalumina\naluminas\naluminate\naluminates\nalumine\nalumines\naluminic\naluminium\naluminiums\naluminize\naluminized\naluminizes\naluminizing\naluminosilicate\naluminosilicates\naluminous\nalumins\naluminum\naluminums\nalumna\nalumnae\nalumni\nalumnus\nalumroot\nalumroots\nalums\nalunite\nalunites\nalveolar\nalveolarly\nalveolars\nalveolate\nalveoli\nalveolus\nalvine\nalway\nalways\nalyssum\nalyssums\nam\nama\namadavat\namadavats\namadou\namadous\namah\namahs\namain\namalgam\namalgamate\namalgamated\namalgamates\namalgamating\namalgamation\namalgamations\namalgamator\namalgamators\namalgams\namandine\namanita\namanitas\namanitin\namanitins\namantadine\namantadines\namanuenses\namanuensis\namaranth\namaranthine\namaranths\namarelle\namarelles\namaretti\namaretto\namarettos\namarna\namaryllis\namaryllises\namas\namass\namassed\namasser\namassers\namasses\namassing\namassment\namassments\namateur\namateurish\namateurishly\namateurishness\namateurishnesses\namateurism\namateurisms\namateurs\namative\namatively\namativeness\namativenesses\namatol\namatols\namatory\namauroses\namaurosis\namaurotic\namaze\namazed\namazedly\namazement\namazements\namazes\namazing\namazingly\namazon\namazonite\namazonites\namazons\namazonstone\namazonstones\nambage\nambages\nambari\nambaries\nambaris\nambary\nambassador\nambassadorial\nambassadors\nambassadorship\nambassadorships\nambassadress\nambassadresses\nambeer\nambeers\namber\nambergris\nambergrises\namberies\namberina\namberinas\namberjack\namberjacks\namberoid\namberoids\nambers\nambery\nambiance\nambiances\nambidexterities\nambidexterity\nambidextrous\nambidextrously\nambience\nambiences\nambient\nambients\nambiguities\nambiguity\nambiguous\nambiguously\nambiguousness\nambiguousnesses\nambisexual\nambisexualities\nambisexuality\nambisexuals\nambit\nambition\nambitioned\nambitioning\nambitionless\nambitions\nambitious\nambitiously\nambitiousness\nambitiousnesses\nambits\nambivalence\nambivalences\nambivalent\nambivalently\nambiversion\nambiversions\nambivert\nambiverts\namble\nambled\nambler\namblers\nambles\nambling\namblygonite\namblygonites\namblyopia\namblyopias\namblyopic\nambo\namboina\namboinas\nambones\nambos\namboyna\namboynas\nambries\nambroid\nambroids\nambrosia\nambrosial\nambrosially\nambrosias\nambrotype\nambrotypes\nambry\nambsace\nambsaces\nambulacra\nambulacral\nambulacrum\nambulance\nambulances\nambulant\nambulate\nambulated\nambulates\nambulating\nambulation\nambulations\nambulatories\nambulatorily\nambulatory\nambuscade\nambuscaded\nambuscader\nambuscaders\nambuscades\nambuscading\nambush\nambushed\nambusher\nambushers\nambushes\nambushing\nambushment\nambushments\nameba\namebae\nameban\namebas\namebean\namebiases\namebiasis\namebic\namebocyte\namebocytes\nameboid\nameer\nameerate\nameerates\nameers\namelcorn\namelcorns\nameliorate\nameliorated\nameliorates\nameliorating\namelioration\nameliorations\nameliorative\nameliorator\nameliorators\namelioratory\nameloblast\nameloblasts\namen\namenabilities\namenability\namenable\namenably\namend\namendable\namendatory\namended\namender\namenders\namending\namendment\namendments\namends\namenities\namenity\namenorrhea\namenorrheas\namenorrheic\namens\nament\namentia\namentias\namentiferous\naments\namerce\namerced\namercement\namercements\namercer\namercers\namerces\namerciable\namercing\namericium\namericiums\namesace\namesaces\namethyst\namethystine\namethysts\nametropia\nametropias\nametropic\nami\namia\namiabilities\namiability\namiable\namiableness\namiablenesses\namiably\namiantus\namiantuses\namias\namicabilities\namicability\namicable\namicableness\namicablenesses\namicably\namice\namices\namici\namicus\namid\namidase\namidases\namide\namides\namidic\namidin\namidine\namidines\namidins\namido\namidogen\namidogens\namidol\namidols\namidone\namidones\namids\namidship\namidships\namidst\namie\namies\namiga\namigas\namigo\namigos\namin\namine\namines\naminic\naminities\naminity\namino\naminoaciduria\naminoacidurias\naminopeptidase\naminopeptidases\naminophylline\naminophyllines\naminopterin\naminopterins\naminopyrine\naminopyrines\naminotransferase\naminotransferases\namins\namir\namirate\namirates\namirs\namis\namiss\namities\namitoses\namitosis\namitotic\namitotically\namitriptyline\namitriptylines\namitrole\namitroles\namity\nammeter\nammeters\nammine\nammines\nammino\nammo\nammocete\nammocetes\nammonal\nammonals\nammonia\nammoniac\nammoniacal\nammoniacs\nammonias\nammoniate\nammoniated\nammoniates\nammoniating\nammoniation\nammoniations\nammonic\nammonification\nammonifications\nammonified\nammonifies\nammonify\nammonifying\nammonite\nammonites\nammonitic\nammonium\nammoniums\nammono\nammonoid\nammonoids\nammos\nammunition\nammunitions\namnesia\namnesiac\namnesiacs\namnesias\namnesic\namnesics\namnestic\namnestied\namnesties\namnesty\namnestying\namnia\namnic\namnio\namniocenteses\namniocentesis\namnion\namnionic\namnions\namnios\namniote\namniotes\namniotic\namobarbital\namobarbitals\namoeba\namoebae\namoeban\namoebas\namoebean\namoebiases\namoebiasis\namoebic\namoebocyte\namoebocytes\namoeboid\namok\namoks\namole\namoles\namong\namongst\namontillado\namontillados\namoral\namoralism\namoralisms\namoralities\namorality\namorally\namoretti\namoretto\namorettos\namorini\namorino\namorist\namoristic\namorists\namoroso\namorous\namorously\namorousness\namorousnesses\namorphous\namorphously\namorphousness\namorphousnesses\namort\namortise\namortised\namortises\namortising\namortizable\namortization\namortizations\namortize\namortized\namortizes\namortizing\namosite\namosites\namotion\namotions\namount\namounted\namounting\namounts\namour\namours\namoxicillin\namoxicillins\namoxycillin\namoxycillins\namp\namperage\namperages\nampere\namperes\namperometric\nampersand\nampersands\namphetamine\namphetamines\namphibia\namphibian\namphibians\namphibious\namphibiously\namphibiousness\namphibiousnesses\namphibole\namphiboles\namphibolies\namphibolite\namphibolites\namphibologies\namphibology\namphiboly\namphibrach\namphibrachic\namphibrachs\namphictyonic\namphictyonies\namphictyony\namphidiploid\namphidiploidies\namphidiploids\namphidiploidy\namphimacer\namphimacers\namphimixes\namphimixis\namphioxi\namphioxus\namphioxuses\namphipathic\namphiphile\namphiphiles\namphiphilic\namphiploid\namphiploidies\namphiploids\namphiploidy\namphipod\namphipods\namphiprostyle\namphiprostyles\namphisbaena\namphisbaenae\namphisbaenas\namphisbaenic\namphitheater\namphitheaters\namphitheatric\namphitheatrical\namphitheatrically\namphora\namphorae\namphoral\namphoras\namphoteric\nampicillin\nampicillins\nample\nampleness\namplenesses\nampler\namplest\namplexus\namplexuses\namplidyne\namplidynes\namplification\namplifications\namplified\namplifier\namplifiers\namplifies\namplify\namplifying\namplitude\namplitudes\namply\nampoule\nampoules\namps\nampul\nampule\nampules\nampulla\nampullae\nampullar\nampullary\nampuls\namputate\namputated\namputates\namputating\namputation\namputations\namputee\namputees\namreeta\namreetas\namrita\namritas\namtrac\namtrack\namtracks\namtracs\namu\namuck\namucks\namulet\namulets\namus\namusable\namuse\namused\namusedly\namusement\namusements\namuser\namusers\namuses\namusia\namusias\namusing\namusingly\namusingness\namusingnesses\namusive\namygdala\namygdalae\namygdale\namygdales\namygdalin\namygdalins\namygdaloid\namygdaloidal\namygdaloids\namygdule\namygdules\namyl\namylase\namylases\namylene\namylenes\namylic\namylogen\namylogens\namyloid\namyloidoses\namyloidosis\namyloids\namylolytic\namylopectin\namylopectins\namyloplast\namyloplasts\namylopsin\namylopsins\namylose\namyloses\namyls\namylum\namylums\namyotonia\namyotonias\nan\nana\nanabaena\nanabaenas\nanabaptism\nanabaptisms\nanabas\nanabases\nanabasis\nanabatic\nanableps\nanablepses\nanabolic\nanabolism\nanabolisms\nanachronic\nanachronism\nanachronisms\nanachronistic\nanachronistically\nanachronous\nanachronously\nanaclitic\nanacolutha\nanacoluthic\nanacoluthically\nanacoluthon\nanacoluthons\nanaconda\nanacondas\nanacreontic\nanacreontics\nanacruses\nanacrusis\nanadem\nanadems\nanadiploses\nanadiplosis\nanadromous\nanaemia\nanaemias\nanaemic\nanaerobe\nanaerobes\nanaerobic\nanaerobically\nanaerobioses\nanaerobiosis\nanaesthesia\nanaesthesias\nanaesthetic\nanaesthetics\nanageneses\nanagenesis\nanaglyph\nanaglyphic\nanaglyphs\nanagnorises\nanagnorisis\nanagoge\nanagoges\nanagogic\nanagogical\nanagogically\nanagogies\nanagogy\nanagram\nanagrammatic\nanagrammatical\nanagrammatically\nanagrammatization\nanagrammatizations\nanagrammatize\nanagrammatized\nanagrammatizes\nanagrammatizing\nanagrammed\nanagramming\nanagrams\nanal\nanalcime\nanalcimes\nanalcite\nanalcites\nanalecta\nanalects\nanalemma\nanalemmas\nanalemmata\nanalemmatic\nanaleptic\nanaleptics\nanalgesia\nanalgesias\nanalgesic\nanalgesics\nanalgetic\nanalgetics\nanalgia\nanalgias\nanalities\nanality\nanally\nanalog\nanalogic\nanalogical\nanalogically\nanalogies\nanalogist\nanalogists\nanalogize\nanalogized\nanalogizes\nanalogizing\nanalogous\nanalogously\nanalogousness\nanalogousnesses\nanalogs\nanalogue\nanalogues\nanalogy\nanalphabet\nanalphabetic\nanalphabetics\nanalphabetism\nanalphabetisms\nanalphabets\nanalysand\nanalysands\nanalyse\nanalysed\nanalyser\nanalysers\nanalyses\nanalysing\nanalysis\nanalyst\nanalysts\nanalytic\nanalytical\nanalytically\nanalyticities\nanalyticity\nanalytics\nanalyzabilities\nanalyzability\nanalyzable\nanalyzation\nanalyzations\nanalyze\nanalyzed\nanalyzer\nanalyzers\nanalyzes\nanalyzing\nanamneses\nanamnesis\nanamnestic\nanamorphic\nananke\nanankes\nanapaest\nanapaests\nanapest\nanapestic\nanapestics\nanapests\nanaphase\nanaphases\nanaphasic\nanaphor\nanaphora\nanaphoras\nanaphoric\nanaphorically\nanaphors\nanaphrodisiac\nanaphrodisiacs\nanaphylactic\nanaphylactically\nanaphylactoid\nanaphylaxes\nanaphylaxis\nanaplasia\nanaplasias\nanaplasmoses\nanaplasmosis\nanaplastic\nanarch\nanarchic\nanarchical\nanarchically\nanarchies\nanarchism\nanarchisms\nanarchist\nanarchistic\nanarchists\nanarchs\nanarchy\nanas\nanasarca\nanasarcas\nanasarcous\nanastigmat\nanastigmatic\nanastigmats\nanastomose\nanastomosed\nanastomoses\nanastomosing\nanastomosis\nanastomotic\nanastrophe\nanastrophes\nanatase\nanatases\nanathema\nanathemas\nanathemata\nanathematize\nanathematized\nanathematizes\nanathematizing\nanatomic\nanatomical\nanatomically\nanatomies\nanatomise\nanatomised\nanatomises\nanatomising\nanatomist\nanatomists\nanatomize\nanatomized\nanatomizes\nanatomizing\nanatomy\nanatoxin\nanatoxins\nanatropous\nanatto\nanattos\nancestor\nancestored\nancestoring\nancestors\nancestral\nancestrally\nancestress\nancestresses\nancestries\nancestry\nanchor\nanchorage\nanchorages\nanchored\nanchoress\nanchoresses\nanchoret\nanchorets\nanchoring\nanchorite\nanchorites\nanchoritic\nanchoritically\nanchorless\nanchorman\nanchormen\nanchorpeople\nanchorperson\nanchorpersons\nanchors\nanchorwoman\nanchorwomen\nanchoveta\nanchovetas\nanchovetta\nanchovettas\nanchovies\nanchovy\nanchusa\nanchusas\nanchusin\nanchusins\nancient\nancienter\nancientest\nanciently\nancientness\nancientnesses\nancientries\nancientry\nancients\nancilla\nancillae\nancillaries\nancillary\nancillas\nancon\nanconal\nancone\nanconeal\nancones\nanconoid\nancress\nancresses\nancylostomiases\nancylostomiasis\nand\nandalusite\nandalusites\nandante\nandantes\nandantino\nandantinos\nandesite\nandesites\nandesitic\nandesyte\nandesytes\nandiron\nandirons\nandouille\nandouilles\nandouillette\nandouillettes\nandradite\nandradites\nandrocentric\nandroecia\nandroecium\nandrogen\nandrogeneses\nandrogenesis\nandrogenetic\nandrogenic\nandrogens\nandrogyne\nandrogynes\nandrogynies\nandrogynous\nandrogyny\nandroid\nandroids\nandromeda\nandromedas\nandrosterone\nandrosterones\nands\nane\nanear\naneared\nanearing\nanears\nanecdota\nanecdotage\nanecdotages\nanecdotal\nanecdotalism\nanecdotalisms\nanecdotalist\nanecdotalists\nanecdotally\nanecdote\nanecdotes\nanecdotic\nanecdotical\nanecdotically\nanecdotist\nanecdotists\nanechoic\nanelastic\nanelasticities\nanelasticity\nanele\naneled\naneles\naneling\nanemia\nanemias\nanemic\nanemically\nanemograph\nanemographs\nanemometer\nanemometers\nanemometries\nanemometry\nanemone\nanemones\nanemophilous\nanemoses\nanemosis\nanencephalic\nanencephalies\nanencephaly\nanenst\nanent\nanergia\nanergias\nanergic\nanergies\nanergy\naneroid\naneroids\nanes\nanesthesia\nanesthesias\nanesthesiologies\nanesthesiologist\nanesthesiologists\nanesthesiology\nanesthetic\nanesthetically\nanesthetics\nanesthetist\nanesthetists\nanesthetize\nanesthetized\nanesthetizes\nanesthetizing\nanestri\nanestrous\nanestrus\nanestruses\nanethol\nanethole\nanetholes\nanethols\naneuploid\naneuploidies\naneuploids\naneuploidy\naneurin\naneurins\naneurism\naneurisms\naneurysm\naneurysmal\naneurysms\nanew\nanfractuosities\nanfractuosity\nanfractuous\nanga\nangakok\nangakoks\nangaria\nangarias\nangaries\nangary\nangas\nangel\nangeled\nangelfish\nangelfishes\nangelic\nangelica\nangelical\nangelically\nangelicas\nangeling\nangelologies\nangelologist\nangelologists\nangelology\nangels\nangelus\nangeluses\nanger\nangered\nangering\nangerless\nangerly\nangers\nangina\nanginal\nanginas\nanginose\nanginous\nangiocardiographic\nangiocardiographies\nangiocardiography\nangiogeneses\nangiogenesis\nangiogenic\nangiogram\nangiograms\nangiographic\nangiographies\nangiography\nangioma\nangiomas\nangiomata\nangiomatous\nangioplasties\nangioplasty\nangiosperm\nangiospermous\nangiosperms\nangiotensin\nangiotensins\nangle\nangled\nanglepod\nanglepods\nangler\nanglerfish\nanglerfishes\nanglers\nangles\nanglesite\nanglesites\nangleworm\nangleworms\nanglice\nanglicise\nanglicised\nanglicises\nanglicising\nanglicism\nanglicisms\nanglicization\nanglicizations\nanglicize\nanglicized\nanglicizes\nanglicizing\nangling\nanglings\nanglophone\nangora\nangoras\nangrier\nangriest\nangrily\nangriness\nangrinesses\nangry\nangst\nangstrom\nangstroms\nangsts\nanguine\nanguish\nanguished\nanguishes\nanguishing\nangular\nangularities\nangularity\nangularly\nangulate\nangulated\nangulates\nangulating\nangulation\nangulations\nangulose\nangulous\nanhedonia\nanhedonias\nanhedonic\nanhinga\nanhingas\nanhydride\nanhydrides\nanhydrite\nanhydrites\nanhydrous\nani\nanil\nanile\nanilin\nanilinctus\nanilinctuses\naniline\nanilines\nanilingus\nanilinguses\nanilins\nanilities\nanility\nanils\nanima\nanimadversion\nanimadversions\nanimadvert\nanimadverted\nanimadverting\nanimadverts\nanimal\nanimalcula\nanimalcule\nanimalcules\nanimalculum\nanimalic\nanimalier\nanimaliers\nanimalism\nanimalisms\nanimalistic\nanimalities\nanimality\nanimalization\nanimalizations\nanimalize\nanimalized\nanimalizes\nanimalizing\nanimallike\nanimally\nanimals\nanimas\nanimate\nanimated\nanimatedly\nanimately\nanimateness\nanimatenesses\nanimater\nanimaters\nanimates\nanimating\nanimation\nanimations\nanimato\nanimator\nanimators\nanime\nanimes\nanimi\nanimis\nanimism\nanimisms\nanimist\nanimistic\nanimists\nanimosities\nanimosity\nanimus\nanimuses\nanion\nanionic\nanions\nanis\nanise\naniseed\naniseeds\naniseikonia\naniseikonias\naniseikonic\nanises\nanisette\nanisettes\nanisic\nanisogamies\nanisogamous\nanisogamy\nanisole\nanisoles\nanisometropia\nanisometropias\nanisometropic\nanisotropic\nanisotropically\nanisotropies\nanisotropism\nanisotropisms\nanisotropy\nankerite\nankerites\nankh\nankhs\nankle\nanklebone\nanklebones\nankled\nankles\nanklet\nanklets\nankling\nankus\nankuses\nankush\nankushes\nankylosaur\nankylosaurs\nankylosaurus\nankylosauruses\nankylose\nankylosed\nankyloses\nankylosing\nankylosis\nankylostomiases\nankylostomiasis\nankylotic\nanlace\nanlaces\nanlage\nanlagen\nanlages\nanlas\nanlases\nanna\nannal\nannalist\nannalistic\nannalists\nannals\nannas\nannates\nannatto\nannattos\nanneal\nannealed\nannealer\nannealers\nannealing\nanneals\nannelid\nannelidan\nannelidans\nannelids\nannex\nannexation\nannexational\nannexationist\nannexationists\nannexations\nannexe\nannexed\nannexes\nannexing\nannihilate\nannihilated\nannihilates\nannihilating\nannihilation\nannihilations\nannihilator\nannihilators\nannihilatory\nanniversaries\nanniversary\nannotate\nannotated\nannotates\nannotating\nannotation\nannotations\nannotative\nannotator\nannotators\nannounce\nannounced\nannouncement\nannouncements\nannouncer\nannouncers\nannounces\nannouncing\nannoy\nannoyance\nannoyances\nannoyed\nannoyer\nannoyers\nannoying\nannoyingly\nannoys\nannual\nannualize\nannualized\nannualizes\nannualizing\nannually\nannuals\nannuitant\nannuitants\nannuities\nannuity\nannul\nannular\nannulate\nannulation\nannulations\nannulet\nannulets\nannuli\nannulled\nannulling\nannulment\nannulments\nannulose\nannuls\nannulus\nannuluses\nannunciate\nannunciated\nannunciates\nannunciating\nannunciation\nannunciations\nannunciator\nannunciators\nannunciatory\nanoa\nanoas\nanodal\nanodally\nanode\nanodes\nanodic\nanodically\nanodization\nanodizations\nanodize\nanodized\nanodizes\nanodizing\nanodyne\nanodynes\nanodynic\nanoint\nanointed\nanointer\nanointers\nanointing\nanointment\nanointments\nanoints\nanole\nanoles\nanolyte\nanolytes\nanomalies\nanomalous\nanomalously\nanomalousness\nanomalousnesses\nanomaly\nanomic\nanomie\nanomies\nanomy\nanon\nanonym\nanonymities\nanonymity\nanonymous\nanonymously\nanonymousness\nanonymousnesses\nanonyms\nanoopsia\nanoopsias\nanopheles\nanopheline\nanophelines\nanopia\nanopias\nanopsia\nanopsias\nanorak\nanoraks\nanorectic\nanorectics\nanoretic\nanoretics\nanorexia\nanorexias\nanorexic\nanorexics\nanorexies\nanorexigenic\nanorexy\nanorthic\nanorthite\nanorthites\nanorthitic\nanorthosite\nanorthosites\nanorthositic\nanosmia\nanosmias\nanosmic\nanother\nanovular\nanovulatory\nanoxemia\nanoxemias\nanoxemic\nanoxia\nanoxias\nanoxic\nansa\nansae\nansate\nansated\nanserine\nanserines\nanserous\nanswer\nanswerable\nanswered\nanswerer\nanswerers\nanswering\nanswers\nant\nanta\nantacid\nantacids\nantae\nantagonism\nantagonisms\nantagonist\nantagonistic\nantagonistically\nantagonists\nantagonize\nantagonized\nantagonizes\nantagonizing\nantalgic\nantalgics\nantarctic\nantas\nantbear\nantbears\nante\nanteater\nanteaters\nantebellum\nantecede\nanteceded\nantecedence\nantecedences\nantecedent\nantecedently\nantecedents\nantecedes\nanteceding\nantecessor\nantecessors\nantechamber\nantechambers\nantechapel\nantechapels\nantechoir\nantechoirs\nanted\nantedate\nantedated\nantedates\nantedating\nantediluvian\nantediluvians\nanteed\nantefix\nantefixa\nantefixae\nantefixes\nanteing\nantelope\nantelopes\nantemortem\nantenatal\nantenatally\nantenna\nantennae\nantennal\nantennas\nantennular\nantennule\nantennules\nantenuptial\nantepast\nantepasts\nantependia\nantependium\nantependiums\nantepenult\nantepenultima\nantepenultimas\nantepenultimate\nantepenultimates\nantepenults\nanterior\nanteriorly\nanteroom\nanterooms\nantes\nantetype\nantetypes\nantevert\nanteverted\nanteverting\nanteverts\nanthelia\nanthelices\nanthelion\nanthelions\nanthelix\nanthelixes\nanthelmintic\nanthelmintics\nanthem\nanthemed\nanthemia\nantheming\nanthemion\nanthems\nanther\nantheral\nantherid\nantheridia\nantheridial\nantheridium\nantherids\nanthers\nantheses\nanthesis\nanthill\nanthills\nanthocyan\nanthocyanin\nanthocyanins\nanthocyans\nanthodia\nanthodium\nanthoid\nanthological\nanthologies\nanthologist\nanthologists\nanthologize\nanthologized\nanthologizer\nanthologizers\nanthologizes\nanthologizing\nanthology\nanthophilous\nanthophyllite\nanthophyllites\nanthozoan\nanthozoans\nanthracene\nanthracenes\nanthraces\nanthracite\nanthracites\nanthracitic\nanthracnose\nanthracnoses\nanthranilate\nanthranilates\nanthraquinone\nanthraquinones\nanthrax\nanthropic\nanthropical\nanthropocentric\nanthropocentrically\nanthropocentricities\nanthropocentricity\nanthropocentrism\nanthropocentrisms\nanthropogenic\nanthropoid\nanthropoids\nanthropological\nanthropologically\nanthropologies\nanthropologist\nanthropologists\nanthropology\nanthropometric\nanthropometries\nanthropometry\nanthropomorph\nanthropomorphic\nanthropomorphically\nanthropomorphism\nanthropomorphisms\nanthropomorphist\nanthropomorphists\nanthropomorphization\nanthropomorphizations\nanthropomorphize\nanthropomorphized\nanthropomorphizes\nanthropomorphizing\nanthropomorphs\nanthropopathism\nanthropopathisms\nanthropophagi\nanthropophagies\nanthropophagous\nanthropophagus\nanthropophagy\nanthroposophies\nanthroposophy\nanthurium\nanthuriums\nanti\nantiabortion\nantiabortionist\nantiabortionists\nantiacademic\nantiacademics\nantiadministration\nantiaggression\nantiaging\nantiair\nantiaircraft\nantiaircrafts\nantialcohol\nantialcoholism\nantialcoholisms\nantialien\nantiallergenic\nantiallergenics\nantianemia\nantianxiety\nantiapartheid\nantiapartheids\nantiaphrodisiac\nantiaphrodisiacs\nantiar\nantiarin\nantiarins\nantiaristocratic\nantiarrhythmic\nantiarrhythmics\nantiars\nantiarthritic\nantiarthritics\nantiarthritis\nantiassimilation\nantiassimilations\nantiasthma\nantiatom\nantiatoms\nantiauthoritarian\nantiauthoritarianism\nantiauthoritarianisms\nantiauthority\nantiauxin\nantiauxins\nantibacklash\nantibacterial\nantibacterials\nantibaryon\nantibaryons\nantibias\nantibillboard\nantibioses\nantibiosis\nantibiotic\nantibiotically\nantibiotics\nantiblack\nantiblackism\nantiblackisms\nantibodies\nantibody\nantiboss\nantibourgeois\nantiboycott\nantiboycotts\nantibug\nantibureaucratic\nantiburglar\nantiburglary\nantibusiness\nantibusing\nantic\nanticaking\nantically\nanticancer\nanticapitalism\nanticapitalisms\nanticapitalist\nanticapitalists\nanticar\nanticarcinogen\nanticarcinogenic\nanticarcinogens\nanticaries\nanticatalyst\nanticatalysts\nanticathode\nanticathodes\nanticellulite\nanticensorship\nanticholesterol\nanticholinergic\nanticholinergics\nanticholinesterase\nanticholinesterases\nantichurch\nanticigarette\nanticipant\nanticipants\nanticipatable\nanticipate\nanticipated\nanticipates\nanticipating\nanticipation\nanticipations\nanticipator\nanticipators\nanticipatory\nanticity\nantick\nanticked\nanticking\nanticks\nanticlassical\nanticlerical\nanticlericalism\nanticlericalisms\nanticlericalist\nanticlericalists\nanticlericals\nanticlimactic\nanticlimactical\nanticlimactically\nanticlimax\nanticlimaxes\nanticlinal\nanticline\nanticlines\nanticling\nanticlockwise\nanticlotting\nanticly\nanticoagulant\nanticoagulants\nanticodon\nanticodons\nanticold\nanticollision\nanticolonial\nanticolonialism\nanticolonialisms\nanticolonialist\nanticolonialists\nanticolonials\nanticommercial\nanticommercialism\nanticommercialisms\nanticommunism\nanticommunisms\nanticommunist\nanticommunists\nanticompetitive\nanticonglomerate\nanticonservation\nanticonservationist\nanticonservationists\nanticonservations\nanticonsumer\nanticonsumers\nanticonventional\nanticonvulsant\nanticonvulsants\nanticonvulsive\nanticonvulsives\nanticorporate\nanticorrosion\nanticorrosive\nanticorrosives\nanticorruption\nanticorruptions\nanticounterfeiting\nanticrack\nanticreative\nanticrime\nanticruelty\nantics\nanticult\nanticultural\nanticyclone\nanticyclones\nanticyclonic\nantidandruff\nantidefamation\nantidemocratic\nantidepressant\nantidepressants\nantidepression\nantidepressions\nantiderivative\nantiderivatives\nantidesegregation\nantidesertification\nantidesiccant\nantidesiccants\nantidevelopment\nantidiabetic\nantidiabetics\nantidiarrheal\nantidilution\nantidiscrimination\nantidogmatic\nantidora\nantidotal\nantidotally\nantidote\nantidoted\nantidotes\nantidoting\nantidraft\nantidromic\nantidromically\nantidrug\nantidumping\nantieconomic\nantieducational\nantiegalitarian\nantielectron\nantielectrons\nantielite\nantielites\nantielitism\nantielitisms\nantielitist\nantielitists\nantiemetic\nantiemetics\nantientropic\nantiepilepsy\nantiepileptic\nantiepileptics\nantierotic\nantiestablishment\nantiestrogen\nantiestrogens\nantievolution\nantievolutionary\nantievolutionism\nantievolutionisms\nantievolutionist\nantievolutionists\nantifamily\nantifascism\nantifascisms\nantifascist\nantifascists\nantifashion\nantifashionable\nantifashions\nantifat\nantifatigue\nantifederalist\nantifederalists\nantifemale\nantifeminine\nantifeminism\nantifeminisms\nantifeminist\nantifeminists\nantiferromagnet\nantiferromagnetic\nantiferromagnetically\nantiferromagnetism\nantiferromagnetisms\nantiferromagnets\nantifertility\nantifilibuster\nantifilibusters\nantiflu\nantifluoridationist\nantifluoridationists\nantifoam\nantifoaming\nantifogging\nantiforeclosure\nantiforeign\nantiforeigner\nantiformalist\nantiformalists\nantifouling\nantifraud\nantifreeze\nantifreezes\nantifriction\nantifrictions\nantifungal\nantifungals\nantifur\nantigambling\nantigay\nantigen\nantigene\nantigenes\nantigenic\nantigenically\nantigenicities\nantigenicity\nantigens\nantiglare\nantiglobulin\nantiglobulins\nantigovernment\nantigravities\nantigravity\nantigrowth\nantiguerrilla\nantiguerrillas\nantigun\nantihero\nantiheroes\nantiheroic\nantiheroine\nantiheroines\nantiherpes\nantihierarchical\nantihijack\nantihistamine\nantihistamines\nantihistaminic\nantihistaminics\nantihistorical\nantihomosexual\nantihuman\nantihumanism\nantihumanisms\nantihumanistic\nantihumanitarian\nantihumanitarians\nantihunter\nantihunting\nantihuntings\nantihypertensive\nantihypertensives\nantihysteric\nantihysterics\nantijam\nantijamming\nantikickback\nantiking\nantikings\nantiknock\nantiknocks\nantilabor\nantileak\nantileft\nantileprosy\nantilepton\nantileptons\nantileukemic\nantiliberal\nantiliberalism\nantiliberalisms\nantiliberals\nantilibertarian\nantilibertarians\nantilife\nantiliterate\nantiliterates\nantilitter\nantilittering\nantilock\nantilog\nantilogarithm\nantilogarithmic\nantilogarithms\nantilogical\nantilogies\nantilogs\nantilogy\nantilynching\nantimacassar\nantimacassars\nantimacho\nantimagnetic\nantimalaria\nantimalarial\nantimalarials\nantimale\nantiman\nantimanagement\nantimanagements\nantimarijuana\nantimarket\nantimask\nantimasks\nantimaterialism\nantimaterialisms\nantimaterialist\nantimaterialists\nantimatter\nantimatters\nantimechanist\nantimechanists\nantimere\nantimeres\nantimerger\nantimetabolic\nantimetabolics\nantimetabolite\nantimetabolites\nantimetaphysical\nantimicrobial\nantimicrobials\nantimilitarism\nantimilitarisms\nantimilitarist\nantimilitarists\nantimilitary\nantimiscegenation\nantimissile\nantimissiles\nantimitotic\nantimitotics\nantimodern\nantimodernist\nantimodernists\nantimoderns\nantimonarchical\nantimonarchist\nantimonarchists\nantimonial\nantimonials\nantimonide\nantimonides\nantimonies\nantimonopolist\nantimonopolists\nantimonopoly\nantimony\nantimosquito\nantimusical\nantimycin\nantimycins\nantinarrative\nantinational\nantinationalist\nantinationalists\nantinatural\nantinature\nantinatures\nantinausea\nantineoplastic\nantinepotism\nantinepotisms\nantineutrino\nantineutrinos\nantineutron\nantineutrons\nanting\nantings\nantinodal\nantinode\nantinodes\nantinoise\nantinomian\nantinomianism\nantinomianisms\nantinomians\nantinomic\nantinomies\nantinomy\nantinovel\nantinovelist\nantinovelists\nantinovels\nantinuclear\nantinucleon\nantinucleons\nantinuke\nantiobesities\nantiobesity\nantiobscenities\nantiobscenity\nantiorganization\nantiorganizations\nantioxidant\nantioxidants\nantiozonant\nantiozonants\nantipapal\nantiparallel\nantiparasitic\nantiparasitics\nantiparticle\nantiparticles\nantiparty\nantipasti\nantipasto\nantipastos\nantipathetic\nantipathetically\nantipathies\nantipathy\nantiperiodic\nantipersonnel\nantiperspirant\nantiperspirants\nantipesticide\nantiphlogistic\nantiphon\nantiphonal\nantiphonally\nantiphonals\nantiphonaries\nantiphonary\nantiphonies\nantiphons\nantiphony\nantiphrases\nantiphrasis\nantipill\nantipiracies\nantipiracy\nantiplague\nantiplagues\nantiplaque\nantipleasure\nantipleasures\nantipoaching\nantipodal\nantipodals\nantipode\nantipodean\nantipodeans\nantipodes\nantipoetic\nantipole\nantipoles\nantipolice\nantipolitical\nantipolitics\nantipollution\nantipollutions\nantipope\nantipopes\nantipopular\nantiporn\nantipornographic\nantipornography\nantipot\nantipoverty\nantipredator\nantipredators\nantipress\nantiprofiteering\nantiprogressive\nantiprostitution\nantiproton\nantiprotons\nantipruritic\nantipruritics\nantipsychotic\nantipsychotics\nantipyic\nantipyics\nantipyreses\nantipyresis\nantipyretic\nantipyretics\nantipyrine\nantipyrines\nantiquarian\nantiquarianism\nantiquarianisms\nantiquarians\nantiquaries\nantiquark\nantiquarks\nantiquary\nantiquate\nantiquated\nantiquates\nantiquating\nantiquation\nantiquations\nantique\nantiqued\nantiquer\nantiquers\nantiques\nantiquing\nantiquities\nantiquity\nantirabies\nantirachitic\nantiracism\nantiracisms\nantiracist\nantiracists\nantiracketeering\nantiradar\nantiradical\nantiradicalism\nantiradicalisms\nantirape\nantirational\nantirationalism\nantirationalisms\nantirationalist\nantirationalists\nantirationalities\nantirationality\nantirealism\nantirealisms\nantirealist\nantirealists\nantirecession\nantirecessionary\nantirecessions\nantired\nantireductionism\nantireductionisms\nantireductionist\nantireductionists\nantireflection\nantireflective\nantireform\nantiregulatory\nantirejection\nantireligion\nantireligious\nantirevolutionaries\nantirevolutionary\nantirheumatic\nantirheumatics\nantiriot\nantiritualism\nantiritualisms\nantirock\nantiroll\nantiromantic\nantiromanticism\nantiromanticisms\nantiromantics\nantiroyalist\nantiroyalists\nantirrhinum\nantirrhinums\nantirust\nantirusts\nantis\nantisag\nantisatellite\nantischizophrenia\nantischizophrenic\nantiscience\nantisciences\nantiscientific\nantiscorbutic\nantiscorbutics\nantisecrecy\nantisegregation\nantiseizure\nantisense\nantisentimental\nantiseparatist\nantiseparatists\nantisepses\nantisepsis\nantiseptic\nantiseptically\nantiseptics\nantisera\nantiserum\nantiserums\nantisex\nantisexist\nantisexists\nantisexual\nantisexualities\nantisexuality\nantishark\nantiship\nantishock\nantishoplifting\nantiskid\nantislaveries\nantislavery\nantisleep\nantislip\nantismog\nantismoke\nantismoker\nantismokers\nantismoking\nantismuggling\nantismut\nantisnob\nantisocial\nantisocialist\nantisocialists\nantisocially\nantisolar\nantispasmodic\nantispasmodics\nantispeculation\nantispeculative\nantispending\nantistat\nantistate\nantistatic\nantistick\nantistories\nantistory\nantistress\nantistrike\nantistrophe\nantistrophes\nantistrophic\nantistrophically\nantistudent\nantisubmarine\nantisubsidy\nantisubversion\nantisubversions\nantisubversive\nantisubversives\nantisuicide\nantisymmetric\nantisyphilitic\nantisyphilitics\nantitakeover\nantitank\nantitarnish\nantitax\nantitechnological\nantitechnologies\nantitechnology\nantiterrorism\nantiterrorisms\nantiterrorist\nantiterrorists\nantitheft\nantitheoretical\nantitheses\nantithesis\nantithetic\nantithetical\nantithetically\nantithrombin\nantithrombins\nantithyroid\nantitobacco\nantitotalitarian\nantitoxic\nantitoxin\nantitoxins\nantitrades\nantitraditional\nantitrust\nantitruster\nantitrusters\nantitubercular\nantituberculosis\nantituberculous\nantitumor\nantitumoral\nantitussive\nantitussives\nantitype\nantitypes\nantityphoid\nantiulcer\nantiunemployment\nantiunion\nantiuniversities\nantiuniversity\nantiurban\nantivenin\nantivenins\nantiviolence\nantiviral\nantivirus\nantivitamin\nantivitamins\nantivivisection\nantivivisectionist\nantivivisectionists\nantiwar\nantiwear\nantiweed\nantiwelfare\nantiwhaling\nantiwhite\nantiwoman\nantiwrinkle\nantler\nantlered\nantlers\nantlike\nantlion\nantlions\nantonomasia\nantonomasias\nantonym\nantonymic\nantonymies\nantonymous\nantonyms\nantonymy\nantra\nantral\nantre\nantres\nantrorse\nantrum\nantrums\nants\nantsier\nantsiest\nantsy\nanural\nanuran\nanurans\nanureses\nanuresis\nanuretic\nanuria\nanurias\nanuric\nanurous\nanus\nanuses\nanvil\nanviled\nanviling\nanvilled\nanvilling\nanvils\nanviltop\nanviltops\nanxieties\nanxiety\nanxiolytic\nanxiolytics\nanxious\nanxiously\nanxiousness\nanxiousnesses\nany\nanybodies\nanybody\nanyhow\nanymore\nanyone\nanyplace\nanything\nanythings\nanytime\nanyway\nanyways\nanywhere\nanywheres\nanywise\naorist\naoristic\naoristically\naorists\naorta\naortae\naortal\naortas\naortic\naortographic\naortographies\naortography\naoudad\naoudads\napace\napache\napaches\napagoge\napagoges\napagogic\napanage\napanages\naparejo\naparejos\napart\napartheid\napartheids\napartment\napartmental\napartments\napartness\napartnesses\napatetic\napathetic\napathetically\napathies\napathy\napatite\napatites\napatosaurus\napatosauruses\nape\napeak\naped\napeek\napelike\naper\napercu\napercus\naperient\naperients\naperies\naperiodic\naperiodically\naperiodicities\naperiodicity\naperitif\naperitifs\napers\naperture\napertures\napery\napes\napetalies\napetalous\napetaly\napex\napexes\naphaereses\naphaeresis\naphaeretic\naphagia\naphagias\naphanite\naphanites\naphanitic\naphasia\naphasiac\naphasiacs\naphasias\naphasic\naphasics\naphelia\naphelian\naphelion\naphelions\naphereses\napheresis\napheses\naphesis\naphetic\naphetically\naphid\naphides\naphidian\naphidians\naphids\naphis\napholate\napholates\naphonia\naphonias\naphonic\naphonics\naphorise\naphorised\naphorises\naphorising\naphorism\naphorisms\naphorist\naphoristic\naphoristically\naphorists\naphorize\naphorized\naphorizes\naphorizing\naphotic\naphrodisiac\naphrodisiacal\naphrodisiacs\naphtha\naphthae\naphthous\naphyllies\naphylly\napian\napiarian\napiarians\napiaries\napiarist\napiarists\napiary\napical\napically\napicals\napices\napiculate\napiculi\napicultural\napiculture\napicultures\napiculturist\napiculturists\napiculus\napiece\napimania\napimanias\naping\napiologies\napiology\napish\napishly\napishness\napishnesses\naplanatic\naplasia\naplasias\naplastic\naplenty\naplite\naplites\naplitic\naplomb\naplombs\napnea\napneal\napneas\napneic\napnoea\napnoeal\napnoeas\napnoeic\napoapsides\napoapsis\napocalypse\napocalypses\napocalyptic\napocalyptical\napocalyptically\napocalypticism\napocalypticisms\napocalyptism\napocalyptisms\napocalyptist\napocalyptists\napocarp\napocarpies\napocarps\napocarpy\napochromatic\napocope\napocopes\napocopic\napocrine\napocrypha\napocryphal\napocryphally\napocryphalness\napocryphalnesses\napod\napodal\napodeictic\napodictic\napodictically\napodoses\napodosis\napodous\napods\napoenzyme\napoenzymes\napogamic\napogamies\napogamous\napogamy\napogeal\napogean\napogee\napogees\napogeic\napolipoprotein\napolipoproteins\napolitical\napolitically\napollo\napollos\napolog\napologal\napologetic\napologetically\napologetics\napologia\napologiae\napologias\napologies\napologise\napologised\napologises\napologising\napologist\napologists\napologize\napologized\napologizer\napologizers\napologizes\napologizing\napologs\napologue\napologues\napology\napolune\napolunes\napomict\napomictic\napomictically\napomicts\napomixes\napomixis\napomorphine\napomorphines\naponeuroses\naponeurosis\naponeurotic\napophonies\napophony\napophthegm\napophthegms\napophyge\napophyges\napophyllite\napophyllites\napophyseal\napophyses\napophysis\napoplectic\napoplectically\napoplexies\napoplexy\napoptoses\napoptosis\napoptotic\naport\naposematic\naposematically\naposiopeses\naposiopesis\naposiopetic\napospories\naposporous\napospory\napostacies\napostacy\napostasies\napostasy\napostate\napostates\napostatise\napostatised\napostatises\napostatising\napostatize\napostatized\napostatizes\napostatizing\napostil\napostils\napostle\napostles\napostleship\napostleships\napostolate\napostolates\napostolic\napostolicities\napostolicity\napostrophe\napostrophes\napostrophic\napostrophise\napostrophised\napostrophises\napostrophising\napostrophize\napostrophized\napostrophizes\napostrophizing\napothecaries\napothecary\napothece\napotheces\napothecia\napothecial\napothecium\napothegm\napothegmatic\napothegms\napothem\napothems\napotheoses\napotheosis\napotheosize\napotheosized\napotheosizes\napotheosizing\napotropaic\napotropaically\nappal\nappall\nappalled\nappalling\nappallingly\nappalls\nappals\nappanage\nappanages\napparat\napparatchik\napparatchiki\napparatchiks\napparats\napparatus\napparatuses\napparel\nappareled\nappareling\napparelled\napparelling\napparels\napparent\napparently\napparentness\napparentnesses\napparition\napparitional\napparitions\napparitor\napparitors\nappeal\nappealabilities\nappealability\nappealable\nappealed\nappealer\nappealers\nappealing\nappealingly\nappeals\nappear\nappearance\nappearances\nappeared\nappearing\nappears\nappeasable\nappease\nappeased\nappeasement\nappeasements\nappeaser\nappeasers\nappeases\nappeasing\nappel\nappellant\nappellants\nappellate\nappellation\nappellations\nappellative\nappellatively\nappellatives\nappellee\nappellees\nappellor\nappellors\nappels\nappend\nappendage\nappendages\nappendant\nappendants\nappendectomies\nappendectomy\nappended\nappendicectomies\nappendicectomy\nappendices\nappendicitis\nappendicitises\nappendicular\nappending\nappendix\nappendixes\nappends\napperceive\napperceived\napperceives\napperceiving\napperception\napperceptions\napperceptive\nappertain\nappertained\nappertaining\nappertains\nappestat\nappestats\nappetence\nappetences\nappetencies\nappetency\nappetent\nappetiser\nappetisers\nappetising\nappetite\nappetites\nappetitive\nappetizer\nappetizers\nappetizing\nappetizingly\napplaud\napplaudable\napplaudably\napplauded\napplauder\napplauders\napplauding\napplauds\napplause\napplauses\napple\napplecart\napplecarts\napplejack\napplejacks\napples\napplesauce\napplesauces\nappliance\nappliances\napplicabilities\napplicability\napplicable\napplicant\napplicants\napplication\napplications\napplicative\napplicatively\napplicator\napplicators\napplicatory\napplied\napplier\nappliers\napplies\napplique\nappliqued\nappliqueing\nappliques\napply\napplying\nappoggiatura\nappoggiaturas\nappoint\nappointed\nappointee\nappointees\nappointing\nappointive\nappointment\nappointments\nappoints\napportion\napportionable\napportioned\napportioning\napportionment\napportionments\napportions\nappose\napposed\napposer\napposers\napposes\napposing\napposite\nappositely\nappositeness\nappositenesses\napposition\nappositional\nappositions\nappositive\nappositively\nappositives\nappraisal\nappraisals\nappraise\nappraised\nappraisee\nappraisees\nappraisement\nappraisements\nappraiser\nappraisers\nappraises\nappraising\nappraisingly\nappraisive\nappreciable\nappreciably\nappreciate\nappreciated\nappreciates\nappreciating\nappreciation\nappreciations\nappreciative\nappreciatively\nappreciativeness\nappreciativenesses\nappreciator\nappreciators\nappreciatory\napprehend\napprehended\napprehending\napprehends\napprehensible\napprehensibly\napprehension\napprehensions\napprehensive\napprehensively\napprehensiveness\napprehensivenesses\napprentice\napprenticed\napprentices\napprenticeship\napprenticeships\napprenticing\nappressed\nappressoria\nappressorium\napprise\napprised\nappriser\napprisers\napprises\napprising\napprize\napprized\napprizer\napprizers\napprizes\napprizing\napproach\napproachabilities\napproachability\napproachable\napproached\napproaches\napproaching\napprobate\napprobated\napprobates\napprobating\napprobation\napprobations\napprobatory\nappropriable\nappropriate\nappropriated\nappropriately\nappropriateness\nappropriatenesses\nappropriates\nappropriating\nappropriation\nappropriations\nappropriative\nappropriator\nappropriators\napprovable\napprovably\napproval\napprovals\napprove\napproved\napprover\napprovers\napproves\napproving\napprovingly\napproximate\napproximated\napproximately\napproximates\napproximating\napproximation\napproximations\napproximative\nappulse\nappulses\nappurtenance\nappurtenances\nappurtenant\nappurtenants\napractic\napraxia\napraxias\napraxic\napres\napricot\napricots\napriorities\napriority\napron\naproned\naproning\naprons\napropos\naprotic\napse\napses\napsidal\napsides\napsis\napt\napter\napteral\napteria\napterium\napterous\napteryx\napteryxes\naptest\naptitude\naptitudes\naptitudinal\naptitudinally\naptly\naptness\naptnesses\napyrase\napyrases\napyretic\naqua\naquacade\naquacades\naquacultural\naquaculture\naquacultures\naquaculturist\naquaculturists\naquae\naquamarine\naquamarines\naquanaut\naquanauts\naquaplane\naquaplaned\naquaplaner\naquaplaners\naquaplanes\naquaplaning\naquarelle\naquarelles\naquarellist\naquarellists\naquaria\naquarial\naquarian\naquarians\naquarist\naquarists\naquarium\naquariums\naquas\naquatic\naquatically\naquatics\naquatint\naquatinted\naquatinter\naquatinters\naquatinting\naquatintist\naquatintists\naquatints\naquatone\naquatones\naquavit\naquavits\naqueduct\naqueducts\naqueous\naquiculture\naquicultures\naquifer\naquiferous\naquifers\naquilegia\naquilegias\naquiline\naquilinities\naquilinity\naquiver\nar\narabesk\narabesks\narabesque\narabesques\narabic\narabica\narabicas\narabicization\narabicizations\narabicize\narabicized\narabicizes\narabicizing\narabilities\narability\narabinose\narabinoses\narabinoside\narabinosides\narabize\narabized\narabizes\narabizing\narable\narables\naraceous\narachnid\narachnids\narachnoid\narachnoids\naragonite\naragonites\naragonitic\narak\naraks\naramid\naramids\naraneid\naraneids\narapaima\narapaimas\nararoba\nararobas\naraucaria\naraucarian\naraucarias\narb\narbalest\narbalests\narbalist\narbalists\narbelest\narbelests\narbiter\narbiters\narbitrable\narbitrage\narbitraged\narbitrager\narbitragers\narbitrages\narbitrageur\narbitrageurs\narbitraging\narbitral\narbitrament\narbitraments\narbitrarily\narbitrariness\narbitrarinesses\narbitrary\narbitrate\narbitrated\narbitrates\narbitrating\narbitration\narbitrational\narbitrations\narbitrative\narbitrator\narbitrators\narbor\narboreal\narboreally\narbored\narboreous\narbores\narborescence\narborescences\narborescent\narboreta\narboretum\narboretums\narboricultural\narboriculture\narboricultures\narborist\narborists\narborization\narborizations\narborize\narborized\narborizes\narborizing\narborous\narbors\narborvitae\narborvitaes\narbour\narboured\narbours\narbovirus\narboviruses\narbs\narbuscle\narbuscles\narbute\narbutean\narbutes\narbutus\narbutuses\narc\narcade\narcaded\narcades\narcadia\narcadian\narcadians\narcadias\narcading\narcadings\narcana\narcane\narcanum\narcanums\narcature\narcatures\narccosine\narccosines\narced\narch\narchaea\narchaeal\narchaean\narchaeans\narchaebacteria\narchaebacterium\narchaeoastronomies\narchaeoastronomy\narchaeological\narchaeologically\narchaeologies\narchaeologist\narchaeologists\narchaeology\narchaeopteryx\narchaeopteryxes\narchaic\narchaically\narchaise\narchaised\narchaises\narchaising\narchaism\narchaisms\narchaist\narchaistic\narchaists\narchaize\narchaized\narchaizes\narchaizing\narchangel\narchangelic\narchangels\narchbishop\narchbishopric\narchbishoprics\narchbishops\narchconservative\narchconservatives\narchdeacon\narchdeaconries\narchdeaconry\narchdeacons\narchdiocesan\narchdiocese\narchdioceses\narchducal\narchduchess\narchduchesses\narchduchies\narchduchy\narchduke\narchdukedom\narchdukedoms\narchdukes\narched\narchegonia\narchegonial\narchegoniate\narchegoniates\narchegonium\narchenemies\narchenemy\narchentera\narchenteron\narchenterons\narcheological\narcheologically\narcheologies\narcheologist\narcheologists\narcheology\narcher\narcherfish\narcherfishes\narcheries\narchers\narchery\narches\narchesporia\narchesporial\narchesporium\narchetypal\narchetypally\narchetype\narchetypes\narchetypical\narchfiend\narchfiends\narchidiaconal\narchiepiscopal\narchiepiscopally\narchiepiscopate\narchiepiscopates\narchil\narchils\narchimandrite\narchimandrites\narchine\narchines\narching\narchings\narchipelagic\narchipelago\narchipelagoes\narchipelagos\narchitect\narchitectonic\narchitectonically\narchitectonics\narchitects\narchitectural\narchitecturally\narchitecture\narchitectures\narchitrave\narchitraves\narchival\narchive\narchived\narchives\narchiving\narchivist\narchivists\narchivolt\narchivolts\narchly\narchness\narchnesses\narchon\narchons\narchosaur\narchosaurian\narchosaurs\narchpriest\narchpriests\narchway\narchways\narciform\narcing\narcked\narcking\narco\narcs\narcsine\narcsines\narctangent\narctangents\narctic\narctically\narctics\narcuate\narcuated\narcuately\narcus\narcuses\nardeb\nardebs\nardencies\nardency\nardent\nardently\nardor\nardors\nardour\nardours\narduous\narduously\narduousness\narduousnesses\nare\narea\nareae\nareal\nareally\nareas\nareaway\nareaways\nareca\narecas\narecoline\narecolines\nareic\narena\narenaceous\narenas\narenicolous\narenite\narenites\narenose\narenous\nareocentric\nareola\nareolae\nareolar\nareolas\nareolate\nareole\nareoles\nareologies\nareology\nares\narete\naretes\narethusa\narethusas\narf\narfs\nargal\nargala\nargalas\nargali\nargalis\nargals\nargent\nargental\nargentic\nargentiferous\nargentine\nargentines\nargentite\nargentites\nargents\nargentum\nargentums\nargil\nargillaceous\nargillite\nargillites\nargils\narginase\narginases\narginine\narginines\nargle\nargled\nargles\nargling\nargol\nargols\nargon\nargonaut\nargonauts\nargons\nargosies\nargosy\nargot\nargotic\nargots\narguable\narguably\nargue\nargued\narguer\narguers\nargues\nargufied\nargufier\nargufiers\nargufies\nargufy\nargufying\narguing\nargument\nargumenta\nargumentation\nargumentations\nargumentative\nargumentatively\nargumentive\narguments\nargumentum\nargus\narguses\nargyle\nargyles\nargyll\nargylls\narhat\narhats\narhatship\narhatships\naria\narias\nariboflavinoses\nariboflavinosis\narid\narider\naridest\naridities\naridity\naridly\naridness\naridnesses\nariel\nariels\narietta\nariettas\nariette\nariettes\naright\naril\nariled\narillate\narillode\narillodes\narilloid\narils\nariose\nariosi\narioso\nariosos\narise\narisen\narises\narising\narista\naristae\naristas\naristate\naristo\naristocracies\naristocracy\naristocrat\naristocratic\naristocratically\naristocrats\naristos\narithmetic\narithmetical\narithmetically\narithmetician\narithmeticians\narithmetics\nark\narkose\narkoses\narkosic\narks\narles\narm\narmada\narmadas\narmadillo\narmadillos\narmagnac\narmagnacs\narmament\narmamentaria\narmamentarium\narmamentariums\narmaments\narmature\narmatured\narmatures\narmaturing\narmband\narmbands\narmchair\narmchairs\narmed\narmer\narmers\narmet\narmets\narmful\narmfuls\narmhole\narmholes\narmies\narmiger\narmigeral\narmigero\narmigeros\narmigerous\narmigers\narmilla\narmillae\narmillas\narming\narmings\narmistice\narmistices\narmless\narmlet\narmlets\narmlike\narmload\narmloads\narmlock\narmlocks\narmoire\narmoires\narmonica\narmonicas\narmor\narmored\narmorer\narmorers\narmorial\narmorially\narmorials\narmories\narmoring\narmorless\narmors\narmory\narmour\narmoured\narmourer\narmourers\narmouries\narmouring\narmours\narmoury\narmpit\narmpits\narmrest\narmrests\narms\narmsful\narmure\narmures\narmy\narmyworm\narmyworms\narnatto\narnattos\narnica\narnicas\narnotto\narnottos\naroid\naroids\naroint\narointed\narointing\naroints\naroma\naromas\naromatherapies\naromatherapist\naromatherapists\naromatherapy\naromatic\naromatically\naromaticities\naromaticity\naromatics\naromatization\naromatizations\naromatize\naromatized\naromatizes\naromatizing\narose\naround\narousal\narousals\narouse\naroused\narouser\narousers\narouses\narousing\naroynt\naroynted\naroynting\naroynts\narpeggiate\narpeggiated\narpeggiates\narpeggiating\narpeggio\narpeggios\narpen\narpens\narpent\narpents\narquebus\narquebuses\narrack\narracks\narraign\narraigned\narraigning\narraignment\narraignments\narraigns\narrange\narranged\narrangement\narrangements\narranger\narrangers\narranges\narranging\narrant\narrantly\narras\narrased\narrases\narray\narrayal\narrayals\narrayed\narrayer\narrayers\narraying\narrays\narrear\narrearage\narrearages\narrears\narrest\narrestant\narrestants\narrested\narrestee\narrestees\narrester\narresters\narresting\narrestingly\narrestment\narrestments\narrestor\narrestors\narrests\narrhizal\narrhythmia\narrhythmias\narrhythmic\narris\narrises\narrival\narrivals\narrive\narrived\narriver\narrivers\narrives\narriving\narriviste\narrivistes\narroba\narrobas\narrogance\narrogances\narrogant\narrogantly\narrogate\narrogated\narrogates\narrogating\narrogation\narrogations\narrondissement\narrondissements\narrow\narrowed\narrowhead\narrowheads\narrowing\narrowroot\narrowroots\narrows\narrowwood\narrowwoods\narrowworm\narrowworms\narrowy\narroyo\narroyos\nars\narse\narsenal\narsenals\narsenate\narsenates\narsenic\narsenical\narsenicals\narsenics\narsenide\narsenides\narsenious\narsenite\narsenites\narseno\narsenopyrite\narsenopyrites\narsenous\narses\narshin\narshins\narsine\narsines\narsino\narsis\narson\narsonist\narsonists\narsonous\narsons\narsphenamine\narsphenamines\nart\nartal\nartefact\nartefacts\nartel\nartels\nartemisia\nartemisias\narterial\narterially\narterials\narteries\narteriogram\narteriograms\narteriographic\narteriographies\narteriography\narteriolar\narteriole\narterioles\narterioscleroses\narteriosclerosis\narteriosclerotic\narteriosclerotics\narteriovenous\narteritides\narteritis\narteritises\nartery\nartful\nartfully\nartfulness\nartfulnesses\narthralgia\narthralgias\narthralgic\narthritic\narthritically\narthritics\narthritides\narthritis\narthrodeses\narthrodesis\narthropathies\narthropathy\narthropod\narthropodan\narthropods\narthroscope\narthroscopes\narthroscopic\narthroscopies\narthroscopy\narthroses\narthrosis\narthrospore\narthrospores\nartichoke\nartichokes\narticle\narticled\narticles\narticling\narticulable\narticulacies\narticulacy\narticular\narticulate\narticulated\narticulately\narticulateness\narticulatenesses\narticulates\narticulating\narticulation\narticulations\narticulative\narticulator\narticulators\narticulatory\nartier\nartiest\nartifact\nartifacts\nartifactual\nartifice\nartificer\nartificers\nartifices\nartificial\nartificialities\nartificiality\nartificially\nartificialness\nartificialnesses\nartilleries\nartillerist\nartillerists\nartillery\nartilleryman\nartillerymen\nartily\nartiness\nartinesses\nartiodactyl\nartiodactyls\nartisan\nartisanal\nartisans\nartisanship\nartisanships\nartist\nartiste\nartistes\nartistic\nartistically\nartistries\nartistry\nartists\nartless\nartlessly\nartlessness\nartlessnesses\narts\nartsier\nartsiest\nartsy\nartwork\nartworks\narty\narugola\narugolas\narugula\narugulas\narum\narums\naruspex\naruspices\narval\narvo\narvos\naryl\naryls\narytenoid\narytenoids\narythmia\narythmias\narythmic\nas\nasafetida\nasafetidas\nasafoetida\nasafoetidas\nasana\nasanas\nasarum\nasarums\nasbestic\nasbestos\nasbestoses\nasbestosis\nasbestus\nasbestuses\nascariases\nascariasis\nascarid\nascarides\nascarids\nascaris\nascend\nascendable\nascendance\nascendances\nascendancies\nascendancy\nascendant\nascendantly\nascendants\nascended\nascendence\nascendences\nascendencies\nascendency\nascendent\nascendents\nascender\nascenders\nascendible\nascending\nascends\nascension\nascensional\nascensions\nascensive\nascent\nascents\nascertain\nascertainable\nascertained\nascertaining\nascertainment\nascertainments\nascertains\nasceses\nascesis\nascetic\nascetical\nascetically\nasceticism\nasceticisms\nascetics\nasci\nascidia\nascidian\nascidians\nascidium\nascites\nascitic\nasclepiad\nasclepiads\nascocarp\nascocarpic\nascocarps\nascogonia\nascogonium\nascomycete\nascomycetes\nascomycetous\nascorbate\nascorbates\nascorbic\nascospore\nascospores\nascosporic\nascot\nascots\nascribable\nascribe\nascribed\nascribes\nascribing\nascription\nascriptions\nascriptive\nascus\nasdic\nasdics\nasea\nasepses\nasepsis\naseptic\naseptically\nasexual\nasexualities\nasexuality\nasexually\nash\nashamed\nashamedly\nashcan\nashcans\nashed\nashen\nashes\nashfall\nashfalls\nashier\nashiest\nashiness\nashinesses\nashing\nashlar\nashlared\nashlaring\nashlars\nashler\nashlered\nashlering\nashlers\nashless\nashman\nashmen\nashore\nashplant\nashplants\nashram\nashrams\nashtray\nashtrays\nashy\naside\nasides\nasinine\nasininely\nasininities\nasininity\nask\naskance\naskant\nasked\nasker\naskers\naskeses\naskesis\naskew\naskewness\naskewnesses\nasking\naskings\naskoi\naskos\nasks\naslant\nasleep\naslope\nasocial\nasp\nasparagine\nasparagines\nasparagus\nasparkle\naspartame\naspartames\naspartate\naspartates\naspect\naspects\naspectual\naspen\naspens\nasper\nasperate\nasperated\nasperates\nasperating\nasperges\naspergilla\naspergilli\naspergilloses\naspergillosis\naspergillum\naspergillums\naspergillus\nasperities\nasperity\naspers\nasperse\naspersed\nasperser\naspersers\nasperses\naspersing\naspersion\naspersions\naspersor\naspersors\nasphalt\nasphalted\nasphaltic\nasphalting\nasphaltite\nasphaltites\nasphalts\nasphaltum\nasphaltums\naspheric\naspherical\nasphodel\nasphodels\nasphyxia\nasphyxias\nasphyxiate\nasphyxiated\nasphyxiates\nasphyxiating\nasphyxiation\nasphyxiations\nasphyxies\nasphyxy\naspic\naspics\naspidistra\naspidistras\naspirant\naspirants\naspirata\naspiratae\naspirate\naspirated\naspirates\naspirating\naspiration\naspirational\naspirations\naspirator\naspirators\naspire\naspired\naspirer\naspirers\naspires\naspirin\naspiring\naspirins\naspis\naspises\naspish\nasps\nasquint\nasrama\nasramas\nass\nassagai\nassagaied\nassagaiing\nassagais\nassai\nassail\nassailable\nassailant\nassailants\nassailed\nassailer\nassailers\nassailing\nassails\nassais\nassassin\nassassinate\nassassinated\nassassinates\nassassinating\nassassination\nassassinations\nassassinator\nassassinators\nassassins\nassault\nassaulted\nassaulter\nassaulters\nassaulting\nassaultive\nassaultively\nassaultiveness\nassaultivenesses\nassaults\nassay\nassayed\nassayer\nassayers\nassaying\nassays\nassed\nassegai\nassegaied\nassegaiing\nassegais\nassemblage\nassemblages\nassemblagist\nassemblagists\nassemble\nassembled\nassembler\nassemblers\nassembles\nassemblies\nassembling\nassembly\nassemblyman\nassemblymen\nassemblywoman\nassemblywomen\nassent\nassentation\nassentations\nassented\nassenter\nassenters\nassenting\nassentor\nassentors\nassents\nassert\nasserted\nassertedly\nasserter\nasserters\nasserting\nassertion\nassertions\nassertive\nassertively\nassertiveness\nassertivenesses\nassertor\nassertors\nasserts\nasses\nassess\nassessable\nassessed\nassesses\nassessing\nassessment\nassessments\nassessor\nassessors\nasset\nassets\nasseverate\nasseverated\nasseverates\nasseverating\nasseveration\nasseverations\nasseverative\nasshole\nassholes\nassiduities\nassiduity\nassiduous\nassiduously\nassiduousness\nassiduousnesses\nassign\nassignabilities\nassignability\nassignable\nassignat\nassignation\nassignations\nassignats\nassigned\nassignee\nassignees\nassigner\nassigners\nassigning\nassignment\nassignments\nassignor\nassignors\nassigns\nassimilabilities\nassimilability\nassimilable\nassimilate\nassimilated\nassimilates\nassimilating\nassimilation\nassimilationism\nassimilationisms\nassimilationist\nassimilationists\nassimilations\nassimilative\nassimilator\nassimilators\nassimilatory\nassist\nassistance\nassistances\nassistant\nassistants\nassistantship\nassistantships\nassisted\nassister\nassisters\nassisting\nassistor\nassistors\nassists\nassize\nassizes\nasslike\nassociate\nassociated\nassociates\nassociateship\nassociateships\nassociating\nassociation\nassociational\nassociationism\nassociationisms\nassociationist\nassociationistic\nassociationists\nassociations\nassociative\nassociatively\nassociativities\nassociativity\nassoil\nassoiled\nassoiling\nassoilment\nassoilments\nassoils\nassonance\nassonances\nassonant\nassonantal\nassonants\nassort\nassortative\nassortatively\nassorted\nassorter\nassorters\nassorting\nassortment\nassortments\nassorts\nassuage\nassuaged\nassuagement\nassuagements\nassuages\nassuaging\nassuasive\nassumabilities\nassumability\nassumable\nassumably\nassume\nassumed\nassumer\nassumers\nassumes\nassuming\nassumpsit\nassumpsits\nassumption\nassumptions\nassumptive\nassurance\nassurances\nassure\nassured\nassuredly\nassuredness\nassurednesses\nassureds\nassurer\nassurers\nassures\nassurgent\nassuring\nassuror\nassurors\nasswage\nasswaged\nasswages\nasswaging\nastarboard\nastasia\nastasias\nastatic\nastatine\nastatines\naster\nasteria\nasterias\nasteriated\nasterisk\nasterisked\nasterisking\nasteriskless\nasterisks\nasterism\nasterisms\nastern\nasternal\nasteroid\nasteroidal\nasteroids\nasters\nasthenia\nasthenias\nasthenic\nasthenics\nasthenies\nasthenosphere\nasthenospheres\nasthenospheric\nastheny\nasthma\nasthmas\nasthmatic\nasthmatically\nasthmatics\nastigmatic\nastigmatics\nastigmatism\nastigmatisms\nastigmia\nastigmias\nastilbe\nastilbes\nastir\nastomous\nastonied\nastonies\nastonish\nastonished\nastonishes\nastonishing\nastonishingly\nastonishment\nastonishments\nastony\nastonying\nastound\nastounded\nastounding\nastoundingly\nastounds\nastraddle\nastragal\nastragals\nastrakhan\nastrakhans\nastral\nastrally\nastrals\nastray\nastrict\nastricted\nastricting\nastricts\nastride\nastringe\nastringed\nastringencies\nastringency\nastringent\nastringently\nastringents\nastringes\nastringing\nastrobiologies\nastrobiologist\nastrobiologists\nastrobiology\nastrocyte\nastrocytes\nastrocytic\nastrocytoma\nastrocytomas\nastrocytomata\nastrodome\nastrodomes\nastrolabe\nastrolabes\nastrologer\nastrologers\nastrological\nastrologically\nastrologies\nastrology\nastrometric\nastrometries\nastrometry\nastronaut\nastronautic\nastronautical\nastronautically\nastronautics\nastronauts\nastronomer\nastronomers\nastronomic\nastronomical\nastronomically\nastronomies\nastronomy\nastrophotograph\nastrophotographer\nastrophotographers\nastrophotographies\nastrophotographs\nastrophotography\nastrophysical\nastrophysically\nastrophysicist\nastrophysicists\nastrophysics\nastute\nastutely\nastuteness\nastutenesses\nastylar\nasunder\naswarm\naswirl\naswoon\nasyla\nasylum\nasylums\nasymmetric\nasymmetrical\nasymmetrically\nasymmetries\nasymmetry\nasymptomatic\nasymptomatically\nasymptote\nasymptotes\nasymptotic\nasymptotically\nasynapses\nasynapsis\nasynchronies\nasynchronism\nasynchronisms\nasynchronous\nasynchronously\nasynchrony\nasyndeta\nasyndetic\nasyndetically\nasyndeton\nasyndetons\nat\natabal\natabals\natactic\nataghan\nataghans\natalaya\natalayas\nataman\natamans\natamasco\natamascos\natap\nataps\nataractic\nataractics\nataraxia\nataraxias\nataraxic\nataraxics\nataraxies\nataraxy\natavic\natavism\natavisms\natavist\natavistic\natavistically\natavists\nataxia\nataxias\nataxic\nataxics\nataxies\nataxy\nate\natechnic\natelectases\natelectasis\natelic\natelier\nateliers\natemoya\natemoyas\natemporal\nates\nathanasies\nathanasy\natheism\natheisms\natheist\natheistic\natheistical\natheistically\natheists\natheling\nathelings\nathenaeum\nathenaeums\natheneum\natheneums\natheoretical\natherogeneses\natherogenesis\natherogenic\natheroma\natheromas\natheromata\natheromatous\natheroscleroses\natherosclerosis\natherosclerotic\nathetoid\nathirst\nathlete\nathletes\nathletic\nathletically\nathleticism\nathleticisms\nathletics\nathodyd\nathodyds\nathrocyte\nathrocytes\nathwart\nathwartship\nathwartships\natilt\natingle\natlantes\natlas\natlases\natlatl\natlatls\natma\natman\natmans\natmas\natmometer\natmometers\natmosphere\natmosphered\natmospheres\natmospheric\natmospherically\natmospherics\natoll\natolls\natom\natomic\natomical\natomically\natomics\natomies\natomise\natomised\natomiser\natomisers\natomises\natomising\natomism\natomisms\natomist\natomistic\natomistically\natomists\natomization\natomizations\natomize\natomized\natomizer\natomizers\natomizes\natomizing\natoms\natomy\natonable\natonal\natonalism\natonalisms\natonalist\natonalists\natonalities\natonality\natonally\natone\natoned\natonement\natonements\natoner\natoners\natones\natonic\natonics\natonies\natoning\natony\natop\natopic\natopies\natopy\natrabilious\natrabiliousness\natrabiliousnesses\natrazine\natrazines\natremble\natresia\natresias\natria\natrial\natrioventricular\natrip\natrium\natriums\natrocious\natrociously\natrociousness\natrociousnesses\natrocities\natrocity\natrophia\natrophias\natrophic\natrophied\natrophies\natrophy\natrophying\natropin\natropine\natropines\natropins\natropism\natropisms\natt\nattaboy\nattach\nattachable\nattache\nattached\nattacher\nattachers\nattaches\nattaching\nattachment\nattachments\nattack\nattacked\nattacker\nattackers\nattacking\nattackman\nattackmen\nattacks\nattain\nattainabilities\nattainability\nattainable\nattainder\nattainders\nattained\nattainer\nattainers\nattaining\nattainment\nattainments\nattains\nattaint\nattainted\nattainting\nattaints\nattar\nattars\nattemper\nattempered\nattempering\nattempers\nattempt\nattemptable\nattempted\nattempting\nattempts\nattend\nattendance\nattendances\nattendant\nattendants\nattended\nattendee\nattendees\nattender\nattenders\nattending\nattends\nattent\nattention\nattentional\nattentions\nattentive\nattentively\nattentiveness\nattentivenesses\nattenuate\nattenuated\nattenuates\nattenuating\nattenuation\nattenuations\nattenuator\nattenuators\nattest\nattestation\nattestations\nattested\nattester\nattesters\nattesting\nattestor\nattestors\nattests\nattic\natticism\natticisms\natticist\natticists\nattics\nattire\nattired\nattires\nattiring\nattitude\nattitudes\nattitudinal\nattitudinally\nattitudinise\nattitudinised\nattitudinises\nattitudinising\nattitudinize\nattitudinized\nattitudinizes\nattitudinizing\nattorn\nattorned\nattorney\nattorneys\nattorneyship\nattorneyships\nattorning\nattornment\nattornments\nattorns\nattract\nattractance\nattractances\nattractancies\nattractancy\nattractant\nattractants\nattracted\nattracting\nattraction\nattractions\nattractive\nattractively\nattractiveness\nattractivenesses\nattractor\nattractors\nattracts\nattributable\nattribute\nattributed\nattributes\nattributing\nattribution\nattributional\nattributions\nattributive\nattributively\nattributives\nattrite\nattrited\nattrition\nattritional\nattritions\nattune\nattuned\nattunement\nattunements\nattunes\nattuning\natwain\natween\natwitter\natypic\natypical\natypicalities\natypicality\natypically\naubade\naubades\nauberge\nauberges\naubergine\naubergines\naubretia\naubretias\naubrieta\naubrietas\nauburn\nauburns\nauction\nauctioned\nauctioneer\nauctioneers\nauctioning\nauctions\nauctorial\naucuba\naucubas\naudacious\naudaciously\naudaciousness\naudaciousnesses\naudacities\naudacity\naudad\naudads\naudial\naudibilities\naudibility\naudible\naudibles\naudibly\naudience\naudiences\naudient\naudients\naudile\naudiles\nauding\naudings\naudio\naudiobook\naudiobooks\naudiocassette\naudiocassettes\naudiogenic\naudiogram\naudiograms\naudiologic\naudiological\naudiologies\naudiologist\naudiologists\naudiology\naudiometer\naudiometers\naudiometric\naudiometries\naudiometry\naudiophile\naudiophiles\naudios\naudiotape\naudiotapes\naudiovisual\naudiovisuals\naudit\nauditable\naudited\nauditing\naudition\nauditioned\nauditioning\nauditions\nauditive\nauditives\nauditor\nauditoria\nauditories\nauditorily\nauditorium\nauditoriums\nauditors\nauditory\naudits\naugend\naugends\nauger\naugers\naught\naughts\naugite\naugites\naugitic\naugment\naugmentation\naugmentations\naugmentative\naugmentatives\naugmented\naugmenter\naugmenters\naugmenting\naugmentor\naugmentors\naugments\naugur\naugural\naugured\naugurer\naugurers\nauguries\nauguring\naugurs\naugury\naugust\nauguster\naugustest\naugustly\naugustness\naugustnesses\nauk\nauklet\nauklets\nauks\nauld\naulder\nauldest\naulic\naunt\naunthood\naunthoods\nauntie\naunties\nauntlier\nauntliest\nauntlike\nauntly\naunts\naunty\naura\naurae\naural\naurally\naurar\nauras\naurate\naurated\naureate\naurei\naureola\naureolae\naureolas\naureole\naureoled\naureoles\naureoling\naures\naureus\nauric\nauricle\nauricled\nauricles\nauricula\nauriculae\nauricular\nauriculas\nauriculate\nauriferous\nauriform\nauris\naurist\naurists\naurochs\naurochses\naurora\naurorae\nauroral\nauroras\naurorean\naurous\naurum\naurums\nauscultate\nauscultated\nauscultates\nauscultating\nauscultation\nauscultations\nauscultatory\nausform\nausformed\nausforming\nausforms\nauslander\nauslanders\nauspex\nauspice\nauspices\nauspicious\nauspiciously\nauspiciousness\nauspiciousnesses\naustenite\naustenites\naustenitic\naustere\nausterely\naustereness\nausterenesses\nausterer\nausterest\nausterities\nausterity\naustral\naustrales\naustralopithecine\naustralopithecines\naustrals\nausubo\nausubos\nautacoid\nautacoids\nautarchic\nautarchical\nautarchies\nautarchy\nautarkic\nautarkical\nautarkies\nautarky\nautecism\nautecisms\nautecological\nautecologies\nautecology\nauteur\nauteurist\nauteurists\nauteurs\nauthentic\nauthentically\nauthenticate\nauthenticated\nauthenticates\nauthenticating\nauthentication\nauthentications\nauthenticator\nauthenticators\nauthenticities\nauthenticity\nauthor\nauthored\nauthoress\nauthoresses\nauthorial\nauthoring\nauthorise\nauthorised\nauthorises\nauthorising\nauthoritarian\nauthoritarianism\nauthoritarianisms\nauthoritarians\nauthoritative\nauthoritatively\nauthoritativeness\nauthoritativenesses\nauthorities\nauthority\nauthorization\nauthorizations\nauthorize\nauthorized\nauthorizer\nauthorizers\nauthorizes\nauthorizing\nauthors\nauthorship\nauthorships\nautism\nautisms\nautistic\nautistically\nautistics\nauto\nautoantibodies\nautoantibody\nautobahn\nautobahnen\nautobahns\nautobiographer\nautobiographers\nautobiographic\nautobiographical\nautobiographically\nautobiographies\nautobiography\nautobus\nautobuses\nautobusses\nautocade\nautocades\nautocatalyses\nautocatalysis\nautocatalytic\nautocatalytically\nautocephalies\nautocephalous\nautocephaly\nautochthon\nautochthones\nautochthonous\nautochthonously\nautochthons\nautoclave\nautoclaved\nautoclaves\nautoclaving\nautocoid\nautocoids\nautocorrelation\nautocorrelations\nautocracies\nautocracy\nautocrat\nautocratic\nautocratical\nautocratically\nautocrats\nautocross\nautocrosses\nautodidact\nautodidactic\nautodidacts\nautodyne\nautodynes\nautoecious\nautoeciously\nautoecism\nautoecisms\nautoed\nautoerotic\nautoeroticism\nautoeroticisms\nautoerotism\nautoerotisms\nautogamies\nautogamous\nautogamy\nautogenic\nautogenies\nautogenous\nautogenously\nautogeny\nautogiro\nautogiros\nautograft\nautografted\nautografting\nautografts\nautograph\nautographed\nautographic\nautographically\nautographies\nautographing\nautographs\nautography\nautogyro\nautogyros\nautohypnoses\nautohypnosis\nautohypnotic\nautoimmune\nautoimmunities\nautoimmunity\nautoimmunization\nautoimmunizations\nautoinfection\nautoinfections\nautoing\nautointoxication\nautointoxications\nautoloading\nautologous\nautolysate\nautolysates\nautolyse\nautolysed\nautolyses\nautolysing\nautolysis\nautolytic\nautolyzate\nautolyzates\nautolyze\nautolyzed\nautolyzes\nautolyzing\nautomaker\nautomakers\nautoman\nautomata\nautomatable\nautomate\nautomated\nautomates\nautomatic\nautomatically\nautomaticities\nautomaticity\nautomatics\nautomating\nautomation\nautomations\nautomatism\nautomatisms\nautomatist\nautomatists\nautomatization\nautomatizations\nautomatize\nautomatized\nautomatizes\nautomatizing\nautomaton\nautomatons\nautomen\nautomobile\nautomobiled\nautomobiles\nautomobiling\nautomobilist\nautomobilists\nautomobilities\nautomobility\nautomorphism\nautomorphisms\nautomotive\nautonomic\nautonomically\nautonomies\nautonomist\nautonomists\nautonomous\nautonomously\nautonomy\nautopilot\nautopilots\nautopolyploid\nautopolyploidies\nautopolyploids\nautopolyploidy\nautopsic\nautopsied\nautopsies\nautopsy\nautopsying\nautoradiogram\nautoradiograms\nautoradiograph\nautoradiographic\nautoradiographies\nautoradiographs\nautoradiography\nautorotate\nautorotated\nautorotates\nautorotating\nautorotation\nautorotations\nautoroute\nautoroutes\nautos\nautosexing\nautosomal\nautosomally\nautosome\nautosomes\nautostrada\nautostradas\nautostrade\nautosuggest\nautosuggested\nautosuggesting\nautosuggestion\nautosuggestions\nautosuggests\nautotelic\nautotetraploid\nautotetraploidies\nautotetraploids\nautotetraploidy\nautotomies\nautotomize\nautotomized\nautotomizes\nautotomizing\nautotomous\nautotomy\nautotransformer\nautotransformers\nautotransfusion\nautotransfusions\nautotroph\nautotrophic\nautotrophically\nautotrophies\nautotrophs\nautotrophy\nautotype\nautotypes\nautotypies\nautotypy\nautoworker\nautoworkers\nautoxidation\nautoxidations\nautumn\nautumnal\nautumnally\nautumns\nautunite\nautunites\nauxeses\nauxesis\nauxetic\nauxetics\nauxiliaries\nauxiliary\nauxin\nauxinic\nauxins\nauxotroph\nauxotrophic\nauxotrophies\nauxotrophs\nauxotrophy\nava\navadavat\navadavats\navail\navailabilities\navailability\navailable\navailableness\navailablenesses\navailably\navailed\navailing\navails\navalanche\navalanched\navalanches\navalanching\navant\navarice\navarices\navaricious\navariciously\navariciousness\navariciousnesses\navascular\navascularities\navascularity\navast\navatar\navatars\navaunt\nave\navellan\navellane\navenge\navenged\navenger\navengers\navenges\navenging\navens\navenses\naventail\naventails\naventurine\naventurines\navenue\navenues\naver\naverage\naveraged\naveragely\naverageness\naveragenesses\naverages\naveraging\naverment\naverments\naverred\naverring\navers\naverse\naversely\naverseness\naversenesses\naversion\naversions\naversive\naversively\naversiveness\naversivenesses\navert\naverted\naverting\naverts\naves\navgas\navgases\navgasses\navgolemono\navgolemonos\navian\navianize\navianized\navianizes\navianizing\navians\naviaries\naviarist\naviarists\naviary\naviate\naviated\naviates\naviating\naviation\naviations\naviator\naviators\naviatrices\naviatrix\naviatrixes\navicular\naviculture\navicultures\naviculturist\naviculturists\navid\navidin\navidins\navidities\navidity\navidly\navidness\navidnesses\navifauna\navifaunae\navifaunal\navifaunas\navigator\navigators\navion\navionic\navionics\navions\navirulent\naviso\navisos\navitaminoses\navitaminosis\navitaminotic\navo\navocado\navocadoes\navocados\navocation\navocational\navocationally\navocations\navocet\navocets\navodire\navodires\navoid\navoidable\navoidably\navoidance\navoidances\navoided\navoider\navoiders\navoiding\navoids\navoirdupois\navoirdupoises\navos\navoset\navosets\navouch\navouched\navoucher\navouchers\navouches\navouching\navouchment\navouchments\navow\navowable\navowably\navowal\navowals\navowed\navowedly\navower\navowers\navowing\navows\navulse\navulsed\navulses\navulsing\navulsion\navulsions\navuncular\navuncularities\navuncularity\navuncularly\naw\nawa\nawait\nawaited\nawaiter\nawaiters\nawaiting\nawaits\nawake\nawaked\nawaken\nawakened\nawakener\nawakeners\nawakening\nawakens\nawakes\nawaking\naward\nawardable\nawarded\nawardee\nawardees\nawarder\nawarders\nawarding\nawards\naware\nawareness\nawarenesses\nawash\naway\nawayness\nawaynesses\nawe\naweary\naweather\nawed\nawee\naweigh\naweing\naweless\nawes\nawesome\nawesomely\nawesomeness\nawesomenesses\nawestricken\nawestruck\nawful\nawfuller\nawfullest\nawfully\nawfulness\nawfulnesses\nawhile\nawhirl\nawing\nawkward\nawkwarder\nawkwardest\nawkwardly\nawkwardness\nawkwardnesses\nawl\nawless\nawls\nawlwort\nawlworts\nawmous\nawn\nawned\nawning\nawninged\nawnings\nawnless\nawns\nawny\nawoke\nawoken\nawol\nawols\nawry\nax\naxal\naxe\naxed\naxel\naxels\naxeman\naxemen\naxenic\naxenically\naxes\naxial\naxialities\naxiality\naxially\naxil\naxile\naxilla\naxillae\naxillar\naxillaries\naxillars\naxillary\naxillas\naxils\naxing\naxiological\naxiologically\naxiologies\naxiology\naxiom\naxiomatic\naxiomatically\naxiomatisation\naxiomatisations\naxiomatization\naxiomatizations\naxiomatize\naxiomatized\naxiomatizes\naxiomatizing\naxioms\naxion\naxions\naxis\naxised\naxises\naxisymmetric\naxisymmetrical\naxisymmetries\naxisymmetry\naxite\naxites\naxle\naxled\naxles\naxletree\naxletrees\naxlike\naxman\naxmen\naxolotl\naxolotls\naxon\naxonal\naxone\naxonemal\naxoneme\naxonemes\naxones\naxonic\naxonometric\naxons\naxoplasm\naxoplasmic\naxoplasms\naxseed\naxseeds\nay\nayah\nayahs\nayahuasca\nayahuascas\nayatollah\nayatollahs\naye\nayes\nayin\nayins\nays\nayurveda\nayurvedas\nazalea\nazaleas\nazan\nazans\nazathioprine\nazathioprines\nazeotrope\nazeotropes\nazerty\nazide\nazides\nazido\nazidothymidine\nazidothymidines\nazimuth\nazimuthal\nazimuthally\nazimuths\nazine\nazines\nazlon\nazlons\nazo\nazoic\nazole\nazoles\nazon\nazonal\nazonic\nazons\nazoospermia\nazoospermias\nazote\nazoted\nazotemia\nazotemias\nazotemic\nazotes\nazoth\nazoths\nazotic\nazotise\nazotised\nazotises\nazotising\nazotize\nazotized\nazotizes\nazotizing\nazotobacter\nazotobacters\nazoturia\nazoturias\nazure\nazures\nazurite\nazurites\nazygos\nazygoses\nazygous\nba\nbaa\nbaaed\nbaaing\nbaal\nbaalim\nbaalism\nbaalisms\nbaals\nbaas\nbaases\nbaaskaap\nbaaskaaps\nbaba\nbabas\nbabassu\nbabassus\nbabbitt\nbabbitted\nbabbitting\nbabbitts\nbabble\nbabbled\nbabblement\nbabblements\nbabbler\nbabblers\nbabbles\nbabbling\nbabblings\nbabe\nbabel\nbabels\nbabes\nbabesia\nbabesias\nbabesioses\nbabesiosis\nbabiche\nbabiches\nbabied\nbabies\nbabirusa\nbabirusas\nbabka\nbabkas\nbaboo\nbabool\nbabools\nbaboon\nbaboons\nbaboos\nbabu\nbabul\nbabuls\nbabus\nbabushka\nbabushkas\nbaby\nbabyhood\nbabyhoods\nbabying\nbabyish\nbabysat\nbabysit\nbabysits\nbabysitter\nbabysitters\nbabysitting\nbacalao\nbacalaos\nbacca\nbaccae\nbaccalaureate\nbaccalaureates\nbaccara\nbaccaras\nbaccarat\nbaccarats\nbaccate\nbaccated\nbacchanal\nbacchanalia\nbacchanalian\nbacchanalians\nbacchanalias\nbacchanals\nbacchant\nbacchante\nbacchantes\nbacchants\nbacchic\nbacchii\nbacchius\nbach\nbached\nbachelor\nbachelordom\nbachelordoms\nbachelorette\nbachelorettes\nbachelorhood\nbachelorhoods\nbachelors\nbaches\nbaching\nbacillar\nbacillary\nbacilli\nbacillus\nbacitracin\nbacitracins\nback\nbackache\nbackaches\nbackbeat\nbackbeats\nbackbench\nbackbencher\nbackbenchers\nbackbenches\nbackbend\nbackbends\nbackbit\nbackbite\nbackbiter\nbackbiters\nbackbites\nbackbiting\nbackbitings\nbackbitten\nbackblock\nbackblocks\nbackboard\nbackboards\nbackbone\nbackbones\nbackbreaker\nbackbreakers\nbackbreaking\nbackcast\nbackcasts\nbackchat\nbackchats\nbackcloth\nbackcloths\nbackcountries\nbackcountry\nbackcourt\nbackcourtman\nbackcourtmen\nbackcourts\nbackcross\nbackcrossed\nbackcrosses\nbackcrossing\nbackdate\nbackdated\nbackdates\nbackdating\nbackdoor\nbackdrop\nbackdropped\nbackdropping\nbackdrops\nbackdropt\nbacked\nbacker\nbackers\nbackfield\nbackfields\nbackfill\nbackfilled\nbackfilling\nbackfills\nbackfire\nbackfired\nbackfires\nbackfiring\nbackfit\nbackfits\nbackfitted\nbackfitting\nbackflow\nbackflows\nbackgammon\nbackgammons\nbackground\nbackgrounded\nbackgrounder\nbackgrounders\nbackgrounding\nbackgrounds\nbackhand\nbackhanded\nbackhandedly\nbackhander\nbackhanders\nbackhanding\nbackhands\nbackhaul\nbackhauled\nbackhauling\nbackhauls\nbackhoe\nbackhoes\nbackhouse\nbackhouses\nbacking\nbackings\nbackland\nbacklands\nbacklash\nbacklashed\nbacklasher\nbacklashers\nbacklashes\nbacklashing\nbackless\nbacklight\nbacklighted\nbacklighting\nbacklights\nbacklist\nbacklisted\nbacklisting\nbacklists\nbacklit\nbacklog\nbacklogged\nbacklogging\nbacklogs\nbackmost\nbackout\nbackouts\nbackpack\nbackpacked\nbackpacker\nbackpackers\nbackpacking\nbackpacks\nbackpedal\nbackpedaled\nbackpedaling\nbackpedalled\nbackpedalling\nbackpedals\nbackrest\nbackrests\nbackroom\nbackrooms\nbackrush\nbackrushes\nbacks\nbacksaw\nbacksaws\nbackscatter\nbackscattered\nbackscattering\nbackscatterings\nbackscatters\nbackseat\nbackseats\nbackset\nbacksets\nbackside\nbacksides\nbackslap\nbackslapped\nbackslapper\nbackslappers\nbackslapping\nbackslaps\nbackslash\nbackslashes\nbackslid\nbackslidden\nbackslide\nbackslider\nbacksliders\nbackslides\nbacksliding\nbackspace\nbackspaced\nbackspaces\nbackspacing\nbackspin\nbackspins\nbacksplash\nbacksplashes\nbackstab\nbackstabbed\nbackstabber\nbackstabbers\nbackstabbing\nbackstabbings\nbackstabs\nbackstage\nbackstairs\nbackstay\nbackstays\nbackstitch\nbackstitched\nbackstitches\nbackstitching\nbackstop\nbackstopped\nbackstopping\nbackstops\nbackstreet\nbackstreets\nbackstretch\nbackstretches\nbackstroke\nbackstrokes\nbackswept\nbackswing\nbackswings\nbacksword\nbackswords\nbacktalk\nbacktalks\nbacktrack\nbacktracked\nbacktracking\nbacktracks\nbackup\nbackups\nbackward\nbackwardly\nbackwardness\nbackwardnesses\nbackwards\nbackwash\nbackwashed\nbackwashes\nbackwashing\nbackwater\nbackwaters\nbackwood\nbackwoods\nbackwoodsman\nbackwoodsmen\nbackwoodsy\nbackwrap\nbackwraps\nbackyard\nbackyards\nbacon\nbacons\nbacteremia\nbacteremias\nbacteremic\nbacteria\nbacterial\nbacterially\nbacterias\nbactericidal\nbactericidally\nbactericide\nbactericides\nbacterin\nbacterins\nbacteriochlorophyll\nbacteriochlorophylls\nbacteriocin\nbacteriocins\nbacteriologic\nbacteriological\nbacteriologically\nbacteriologies\nbacteriologist\nbacteriologists\nbacteriology\nbacteriolyses\nbacteriolysis\nbacteriolytic\nbacteriophage\nbacteriophages\nbacteriophagies\nbacteriophagy\nbacteriorhodopsin\nbacteriorhodopsins\nbacteriostases\nbacteriostasis\nbacteriostat\nbacteriostatic\nbacteriostats\nbacterium\nbacteriuria\nbacteriurias\nbacterization\nbacterizations\nbacterize\nbacterized\nbacterizes\nbacterizing\nbacteroid\nbacteroids\nbacula\nbaculine\nbaculum\nbaculums\nbad\nbadass\nbadassed\nbadasses\nbadder\nbaddest\nbaddie\nbaddies\nbaddy\nbade\nbadge\nbadged\nbadger\nbadgered\nbadgering\nbadgerly\nbadgers\nbadges\nbadging\nbadinage\nbadinaged\nbadinages\nbadinaging\nbadland\nbadlands\nbadly\nbadman\nbadmen\nbadminton\nbadmintons\nbadmouth\nbadmouthed\nbadmouthing\nbadmouths\nbadness\nbadnesses\nbads\nbaff\nbaffed\nbaffies\nbaffing\nbaffle\nbaffled\nbafflegab\nbafflegabs\nbafflement\nbafflements\nbaffler\nbafflers\nbaffles\nbaffling\nbafflingly\nbaffs\nbaffy\nbag\nbagass\nbagasse\nbagasses\nbagatelle\nbagatelles\nbagel\nbagels\nbagful\nbagfuls\nbaggage\nbaggages\nbagged\nbagger\nbaggers\nbaggie\nbaggier\nbaggies\nbaggiest\nbaggily\nbagginess\nbagginesses\nbagging\nbaggings\nbaggy\nbaghouse\nbaghouses\nbagman\nbagmen\nbagnio\nbagnios\nbagpipe\nbagpiper\nbagpipers\nbagpipes\nbags\nbagsful\nbaguet\nbaguets\nbaguette\nbaguettes\nbagwig\nbagwigs\nbagworm\nbagworms\nbah\nbahadur\nbahadurs\nbaht\nbahts\nbaidarka\nbaidarkas\nbail\nbailable\nbailed\nbailee\nbailees\nbailer\nbailers\nbailey\nbaileys\nbailie\nbailies\nbailiff\nbailiffs\nbailiffship\nbailiffships\nbailing\nbailiwick\nbailiwicks\nbailment\nbailments\nbailor\nbailors\nbailout\nbailouts\nbails\nbailsman\nbailsmen\nbairn\nbairnish\nbairnlier\nbairnliest\nbairnly\nbairns\nbait\nbaited\nbaiter\nbaiters\nbaith\nbaiting\nbaits\nbaiza\nbaizas\nbaize\nbaizes\nbake\nbaked\nbakemeat\nbakemeats\nbaker\nbakeries\nbakers\nbakery\nbakes\nbakeshop\nbakeshops\nbaking\nbakings\nbaklava\nbaklavas\nbaklawa\nbaklawas\nbaksheesh\nbaksheeshes\nbakshish\nbakshished\nbakshishes\nbakshishing\nbal\nbalaclava\nbalaclavas\nbalalaika\nbalalaikas\nbalance\nbalanced\nbalancer\nbalancers\nbalances\nbalancing\nbalas\nbalases\nbalata\nbalatas\nbalboa\nbalboas\nbalbriggan\nbalbriggans\nbalconied\nbalconies\nbalcony\nbald\nbaldachin\nbaldachino\nbaldachinos\nbaldachins\nbalded\nbalder\nbalderdash\nbalderdashes\nbaldest\nbaldhead\nbaldheaded\nbaldheads\nbaldies\nbalding\nbaldish\nbaldly\nbaldness\nbaldnesses\nbaldpate\nbaldpates\nbaldric\nbaldrick\nbaldricks\nbaldrics\nbalds\nbaldy\nbale\nbaled\nbaleen\nbaleens\nbalefire\nbalefires\nbaleful\nbalefully\nbalefulness\nbalefulnesses\nbaler\nbalers\nbales\nbaling\nbalisaur\nbalisaurs\nbalk\nbalkanization\nbalkanizations\nbalkanize\nbalkanized\nbalkanizes\nbalkanizing\nbalked\nbalker\nbalkers\nbalkier\nbalkiest\nbalkily\nbalkiness\nbalkinesses\nbalking\nbalkline\nbalklines\nbalks\nbalky\nball\nballad\nballade\nballadeer\nballadeers\nballades\nballadic\nballadist\nballadists\nballadries\nballadry\nballads\nballast\nballasted\nballasting\nballasts\nballcarrier\nballcarriers\nballed\nballer\nballerina\nballerinas\nballers\nballet\nballetic\nballetomane\nballetomanes\nballetomania\nballetomanias\nballets\nballgame\nballgames\nballhandling\nballhandlings\nballhawk\nballhawks\nballies\nballing\nballista\nballistae\nballistic\nballistically\nballistics\nballon\nballonet\nballonets\nballonne\nballonnes\nballons\nballoon\nballooned\nballooning\nballoonings\nballoonist\nballoonists\nballoons\nballot\nballoted\nballoter\nballoters\nballoting\nballots\nballpark\nballparks\nballplayer\nballplayers\nballpoint\nballpoints\nballroom\nballrooms\nballs\nballsier\nballsiest\nballsy\nballute\nballutes\nbally\nballyhoo\nballyhooed\nballyhooing\nballyhoos\nballyrag\nballyragged\nballyragging\nballyrags\nbalm\nbalmacaan\nbalmacaans\nbalmier\nbalmiest\nbalmily\nbalminess\nbalminesses\nbalmlike\nbalmoral\nbalmorals\nbalms\nbalmy\nbalneal\nbalneologies\nbalneology\nbaloney\nbaloneys\nbals\nbalsa\nbalsam\nbalsamed\nbalsamic\nbalsaming\nbalsams\nbalsas\nbaluster\nbalusters\nbalustrade\nbalustraded\nbalustrades\nbam\nbambini\nbambino\nbambinos\nbamboo\nbamboos\nbamboozle\nbamboozled\nbamboozlement\nbamboozlements\nbamboozles\nbamboozling\nbammed\nbamming\nbams\nban\nbanal\nbanalities\nbanality\nbanalize\nbanalized\nbanalizes\nbanalizing\nbanally\nbanana\nbananas\nbanausic\nbanco\nbancos\nband\nbandage\nbandaged\nbandager\nbandagers\nbandages\nbandaging\nbandaid\nbandaids\nbandana\nbandanas\nbandanna\nbandannas\nbandbox\nbandboxes\nbandeau\nbandeaus\nbandeaux\nbanded\nbander\nbanderilla\nbanderillas\nbanderillero\nbanderilleros\nbanderol\nbanderole\nbanderoles\nbanderols\nbanders\nbandicoot\nbandicoots\nbandied\nbandies\nbanding\nbandit\nbanditries\nbanditry\nbandits\nbanditti\nbandleader\nbandleaders\nbandmaster\nbandmasters\nbandog\nbandogs\nbandoleer\nbandoleers\nbandolier\nbandoliers\nbandora\nbandoras\nbandore\nbandores\nbands\nbandsman\nbandsmen\nbandstand\nbandstands\nbandwagon\nbandwagons\nbandwidth\nbandwidths\nbandy\nbandying\nbane\nbaneberries\nbaneberry\nbaned\nbaneful\nbanefully\nbanes\nbang\nbanged\nbanger\nbangers\nbanging\nbangkok\nbangkoks\nbangle\nbangles\nbangs\nbangtail\nbangtails\nbani\nbanian\nbanians\nbaning\nbanish\nbanished\nbanisher\nbanishers\nbanishes\nbanishing\nbanishment\nbanishments\nbanister\nbanistered\nbanisters\nbanjax\nbanjaxed\nbanjaxes\nbanjaxing\nbanjo\nbanjoes\nbanjoist\nbanjoists\nbanjos\nbank\nbankabilities\nbankability\nbankable\nbankbook\nbankbooks\nbankcard\nbankcards\nbanked\nbanker\nbankerly\nbankers\nbanking\nbankings\nbanknote\nbanknotes\nbankroll\nbankrolled\nbankroller\nbankrollers\nbankrolling\nbankrolls\nbankrupt\nbankruptcies\nbankruptcy\nbankrupted\nbankrupting\nbankrupts\nbanks\nbanksia\nbanksias\nbankside\nbanksides\nbanned\nbanner\nbannered\nbanneret\nbannerets\nbannerette\nbannerettes\nbannering\nbannerol\nbannerols\nbanners\nbannet\nbannets\nbanning\nbannister\nbannisters\nbannock\nbannocks\nbanns\nbanquet\nbanqueted\nbanqueter\nbanqueters\nbanqueting\nbanquets\nbanquette\nbanquettes\nbans\nbanshee\nbanshees\nbanshie\nbanshies\nbantam\nbantams\nbantamweight\nbantamweights\nbanteng\nbantengs\nbanter\nbantered\nbanterer\nbanterers\nbantering\nbanteringly\nbanters\nbanties\nbantling\nbantlings\nbanty\nbanyan\nbanyans\nbanzai\nbanzais\nbaobab\nbaobabs\nbap\nbaps\nbaptise\nbaptised\nbaptises\nbaptisia\nbaptisias\nbaptising\nbaptism\nbaptismal\nbaptismally\nbaptisms\nbaptist\nbaptisteries\nbaptistery\nbaptistries\nbaptistry\nbaptists\nbaptize\nbaptized\nbaptizer\nbaptizers\nbaptizes\nbaptizing\nbar\nbarathea\nbaratheas\nbarb\nbarbal\nbarbarian\nbarbarianism\nbarbarianisms\nbarbarians\nbarbaric\nbarbarically\nbarbarism\nbarbarisms\nbarbarities\nbarbarity\nbarbarization\nbarbarizations\nbarbarize\nbarbarized\nbarbarizes\nbarbarizing\nbarbarous\nbarbarously\nbarbarousness\nbarbarousnesses\nbarbasco\nbarbascoes\nbarbascos\nbarbate\nbarbe\nbarbecue\nbarbecued\nbarbecuer\nbarbecuers\nbarbecues\nbarbecuing\nbarbed\nbarbel\nbarbell\nbarbells\nbarbels\nbarbeque\nbarbequed\nbarbeques\nbarbequing\nbarber\nbarbered\nbarbering\nbarberries\nbarberry\nbarbers\nbarbershop\nbarbershops\nbarbes\nbarbet\nbarbets\nbarbette\nbarbettes\nbarbican\nbarbicans\nbarbicel\nbarbicels\nbarbing\nbarbital\nbarbitals\nbarbitone\nbarbitones\nbarbiturate\nbarbiturates\nbarbless\nbarbs\nbarbule\nbarbules\nbarbut\nbarbuts\nbarbwire\nbarbwires\nbarcarole\nbarcaroles\nbarcarolle\nbarcarolles\nbarchan\nbarchans\nbard\nbarde\nbarded\nbardes\nbardic\nbarding\nbardolater\nbardolaters\nbardolatries\nbardolatry\nbards\nbare\nbareback\nbarebacked\nbareboat\nbareboats\nbared\nbarefaced\nbarefacedly\nbarefacedness\nbarefacednesses\nbarefit\nbarefoot\nbarefooted\nbarege\nbareges\nbarehanded\nbarehead\nbareheaded\nbarely\nbareness\nbarenesses\nbarer\nbares\nbaresark\nbaresarks\nbarest\nbarf\nbarfed\nbarfing\nbarflies\nbarfly\nbarfs\nbargain\nbargained\nbargainer\nbargainers\nbargaining\nbargains\nbarge\nbargeboard\nbargeboards\nbarged\nbargee\nbargees\nbargello\nbargellos\nbargeman\nbargemen\nbarges\nbarghest\nbarghests\nbarging\nbarguest\nbarguests\nbarhop\nbarhopped\nbarhopping\nbarhops\nbaric\nbarilla\nbarillas\nbaring\nbarite\nbarites\nbaritonal\nbaritone\nbaritones\nbarium\nbariums\nbark\nbarked\nbarkeep\nbarkeeper\nbarkeepers\nbarkeeps\nbarkentine\nbarkentines\nbarker\nbarkers\nbarkier\nbarkiest\nbarking\nbarkless\nbarks\nbarky\nbarleduc\nbarleducs\nbarless\nbarley\nbarleycorn\nbarleycorns\nbarleys\nbarlow\nbarlows\nbarm\nbarmaid\nbarmaids\nbarman\nbarmen\nbarmie\nbarmier\nbarmiest\nbarms\nbarmy\nbarn\nbarnacle\nbarnacled\nbarnacles\nbarnier\nbarniest\nbarnlike\nbarns\nbarnstorm\nbarnstormed\nbarnstormer\nbarnstormers\nbarnstorming\nbarnstorms\nbarny\nbarnyard\nbarnyards\nbaroceptor\nbaroceptors\nbarogram\nbarograms\nbarograph\nbarographic\nbarographs\nbarometer\nbarometers\nbarometric\nbarometrically\nbarometries\nbarometry\nbaron\nbaronage\nbaronages\nbaroness\nbaronesses\nbaronet\nbaronetage\nbaronetages\nbaronetcies\nbaronetcy\nbaronets\nbarong\nbarongs\nbaronial\nbaronies\nbaronne\nbaronnes\nbarons\nbarony\nbaroque\nbaroquely\nbaroques\nbaroreceptor\nbaroreceptors\nbarouche\nbarouches\nbarque\nbarquentine\nbarquentines\nbarques\nbarquette\nbarquettes\nbarrable\nbarrack\nbarracked\nbarracker\nbarrackers\nbarracking\nbarracks\nbarracoon\nbarracoons\nbarracouta\nbarracoutas\nbarracuda\nbarracudas\nbarrage\nbarraged\nbarrages\nbarraging\nbarramunda\nbarramundas\nbarramundi\nbarramundies\nbarramundis\nbarranca\nbarrancas\nbarranco\nbarrancos\nbarrater\nbarraters\nbarrator\nbarrators\nbarratries\nbarratry\nbarre\nbarred\nbarrel\nbarrelage\nbarrelages\nbarreled\nbarrelful\nbarrelfuls\nbarrelhead\nbarrelheads\nbarrelhouse\nbarrelhouses\nbarreling\nbarrelled\nbarrelling\nbarrels\nbarrelsful\nbarren\nbarrener\nbarrenest\nbarrenly\nbarrenness\nbarrennesses\nbarrens\nbarres\nbarret\nbarretor\nbarretors\nbarretries\nbarretry\nbarrets\nbarrette\nbarrettes\nbarricade\nbarricaded\nbarricades\nbarricading\nbarricado\nbarricadoed\nbarricadoes\nbarricadoing\nbarrier\nbarriers\nbarring\nbarrio\nbarrios\nbarrister\nbarristers\nbarroom\nbarrooms\nbarrow\nbarrows\nbars\nbarstool\nbarstools\nbartend\nbartended\nbartender\nbartenders\nbartending\nbartends\nbarter\nbartered\nbarterer\nbarterers\nbartering\nbarters\nbartisan\nbartisans\nbartizan\nbartizans\nbarware\nbarwares\nbarye\nbaryes\nbaryon\nbaryonic\nbaryons\nbaryta\nbarytas\nbaryte\nbarytes\nbarytic\nbarytone\nbarytones\nbas\nbasal\nbasally\nbasalt\nbasaltes\nbasaltic\nbasalts\nbascule\nbascules\nbase\nbaseball\nbaseballs\nbaseboard\nbaseboards\nbaseborn\nbased\nbaseless\nbaseline\nbaseliner\nbaseliners\nbaselines\nbasely\nbaseman\nbasemen\nbasement\nbasementless\nbasements\nbaseness\nbasenesses\nbasenji\nbasenjis\nbaser\nbaserunning\nbaserunnings\nbases\nbasest\nbash\nbashaw\nbashaws\nbashed\nbasher\nbashers\nbashes\nbashful\nbashfully\nbashfulness\nbashfulnesses\nbashing\nbashlyk\nbashlyks\nbasic\nbasically\nbasicities\nbasicity\nbasics\nbasidia\nbasidial\nbasidiomycete\nbasidiomycetes\nbasidiomycetous\nbasidiospore\nbasidiospores\nbasidium\nbasification\nbasifications\nbasified\nbasifier\nbasifiers\nbasifies\nbasify\nbasifying\nbasil\nbasilar\nbasilary\nbasilic\nbasilica\nbasilicae\nbasilican\nbasilicas\nbasilisk\nbasilisks\nbasils\nbasin\nbasinal\nbasined\nbasinet\nbasinets\nbasinful\nbasinfuls\nbasing\nbasins\nbasion\nbasions\nbasipetal\nbasipetally\nbasis\nbask\nbasked\nbasket\nbasketball\nbasketballs\nbasketful\nbasketfuls\nbasketlike\nbasketries\nbasketry\nbaskets\nbasketsful\nbasketwork\nbasketworks\nbasking\nbasks\nbasmati\nbasmatis\nbasophil\nbasophile\nbasophiles\nbasophilia\nbasophilias\nbasophilic\nbasophils\nbasque\nbasques\nbass\nbasses\nbasset\nbasseted\nbasseting\nbassets\nbassetted\nbassetting\nbassi\nbassinet\nbassinets\nbassist\nbassists\nbassly\nbassness\nbassnesses\nbasso\nbassoon\nbassoonist\nbassoonists\nbassoons\nbassos\nbasswood\nbasswoods\nbassy\nbast\nbastard\nbastardies\nbastardise\nbastardised\nbastardises\nbastardising\nbastardization\nbastardizations\nbastardize\nbastardized\nbastardizes\nbastardizing\nbastardly\nbastards\nbastardy\nbaste\nbasted\nbaster\nbasters\nbastes\nbastile\nbastiles\nbastille\nbastilles\nbastinade\nbastinades\nbastinado\nbastinadoed\nbastinadoes\nbastinadoing\nbasting\nbastings\nbastion\nbastioned\nbastions\nbasts\nbat\nbatboy\nbatboys\nbatch\nbatched\nbatcher\nbatchers\nbatches\nbatching\nbate\nbateau\nbateaux\nbated\nbates\nbatfish\nbatfishes\nbatfowl\nbatfowled\nbatfowling\nbatfowls\nbath\nbathe\nbathed\nbather\nbathers\nbathes\nbathetic\nbathetically\nbathhouse\nbathhouses\nbathing\nbathless\nbathmat\nbathmats\nbatholith\nbatholithic\nbatholiths\nbathos\nbathoses\nbathrobe\nbathrobes\nbathroom\nbathrooms\nbaths\nbathtub\nbathtubs\nbathwater\nbathwaters\nbathyal\nbathymetric\nbathymetrical\nbathymetrically\nbathymetries\nbathymetry\nbathypelagic\nbathyscaph\nbathyscaphe\nbathyscaphes\nbathyscaphs\nbathysphere\nbathyspheres\nbathythermograph\nbathythermographs\nbatik\nbatiks\nbating\nbatiste\nbatistes\nbatlike\nbatman\nbatmen\nbaton\nbatons\nbatrachian\nbatrachians\nbats\nbatsman\nbatsmen\nbatt\nbattailous\nbattalia\nbattalias\nbattalion\nbattalions\nbatteau\nbatteaux\nbatted\nbattement\nbattements\nbatten\nbattened\nbattener\nbatteners\nbattening\nbattens\nbatter\nbattered\nbatterie\nbatteries\nbattering\nbatters\nbattery\nbattier\nbattiest\nbattik\nbattiks\nbattiness\nbattinesses\nbatting\nbattings\nbattle\nbattled\nbattlefield\nbattlefields\nbattlefront\nbattlefronts\nbattleground\nbattlegrounds\nbattlement\nbattlemented\nbattlements\nbattler\nbattlers\nbattles\nbattleship\nbattleships\nbattlewagon\nbattlewagons\nbattling\nbatts\nbattu\nbattue\nbattues\nbatty\nbatwing\nbaubee\nbaubees\nbauble\nbaubles\nbaud\nbaudekin\nbaudekins\nbaudrons\nbaudronses\nbauds\nbauhinia\nbauhinias\nbaulk\nbaulked\nbaulkier\nbaulkiest\nbaulking\nbaulks\nbaulky\nbausond\nbauxite\nbauxites\nbauxitic\nbawbee\nbawbees\nbawcock\nbawcocks\nbawd\nbawdier\nbawdies\nbawdiest\nbawdily\nbawdiness\nbawdinesses\nbawdric\nbawdrics\nbawdries\nbawdry\nbawds\nbawdy\nbawdyhouse\nbawdyhouses\nbawl\nbawled\nbawler\nbawlers\nbawling\nbawls\nbawsunt\nbawtie\nbawties\nbawty\nbay\nbayadeer\nbayadeers\nbayadere\nbayaderes\nbayamo\nbayamos\nbayard\nbayards\nbayberries\nbayberry\nbayed\nbaying\nbayman\nbaymen\nbayonet\nbayoneted\nbayoneting\nbayonets\nbayonetted\nbayonetting\nbayou\nbayous\nbays\nbaywood\nbaywoods\nbazaar\nbazaars\nbazar\nbazars\nbazoo\nbazooka\nbazookas\nbazooms\nbazoos\nbdellium\nbdelliums\nbe\nbeach\nbeachboy\nbeachboys\nbeachcomb\nbeachcombed\nbeachcomber\nbeachcombers\nbeachcombing\nbeachcombs\nbeached\nbeaches\nbeachfront\nbeachfronts\nbeachgoer\nbeachgoers\nbeachhead\nbeachheads\nbeachier\nbeachiest\nbeaching\nbeachside\nbeachwear\nbeachy\nbeacon\nbeaconed\nbeaconing\nbeacons\nbead\nbeaded\nbeadier\nbeadiest\nbeadily\nbeading\nbeadings\nbeadle\nbeadles\nbeadlike\nbeadman\nbeadmen\nbeadroll\nbeadrolls\nbeads\nbeadsman\nbeadsmen\nbeadwork\nbeadworks\nbeady\nbeagle\nbeagles\nbeak\nbeaked\nbeaker\nbeakers\nbeakier\nbeakiest\nbeakless\nbeaklike\nbeaks\nbeaky\nbeam\nbeamed\nbeamier\nbeamiest\nbeamily\nbeaming\nbeamish\nbeamishly\nbeamless\nbeamlike\nbeams\nbeamy\nbean\nbeanbag\nbeanbags\nbeanball\nbeanballs\nbeaned\nbeaneries\nbeanery\nbeanie\nbeanies\nbeaning\nbeanlike\nbeano\nbeanos\nbeanpole\nbeanpoles\nbeans\nbeanstalk\nbeanstalks\nbear\nbearabilities\nbearability\nbearable\nbearably\nbearbaiting\nbearbaitings\nbearberries\nbearberry\nbearcat\nbearcats\nbeard\nbearded\nbeardedness\nbeardednesses\nbearding\nbeardless\nbeards\nbeardtongue\nbeardtongues\nbearer\nbearers\nbearhug\nbearhugs\nbearing\nbearings\nbearish\nbearishly\nbearishness\nbearishnesses\nbearlike\nbears\nbearskin\nbearskins\nbearwood\nbearwoods\nbeast\nbeastie\nbeasties\nbeastings\nbeastlier\nbeastliest\nbeastliness\nbeastlinesses\nbeastly\nbeasts\nbeat\nbeatable\nbeaten\nbeater\nbeaters\nbeatific\nbeatifically\nbeatification\nbeatifications\nbeatified\nbeatifies\nbeatify\nbeatifying\nbeating\nbeatings\nbeatitude\nbeatitudes\nbeatless\nbeatnik\nbeatniks\nbeats\nbeau\nbeaucoup\nbeauish\nbeaus\nbeaut\nbeauteous\nbeauteously\nbeauteousness\nbeauteousnesses\nbeautician\nbeauticians\nbeauties\nbeautification\nbeautifications\nbeautified\nbeautifier\nbeautifiers\nbeautifies\nbeautiful\nbeautifuler\nbeautifulest\nbeautifully\nbeautifulness\nbeautifulnesses\nbeautify\nbeautifying\nbeauts\nbeauty\nbeaux\nbeaver\nbeaverboard\nbeaverboards\nbeavered\nbeavering\nbeavers\nbebeeru\nbebeerus\nbeblood\nbeblooded\nbeblooding\nbebloods\nbebop\nbebopper\nbeboppers\nbebops\nbecalm\nbecalmed\nbecalming\nbecalms\nbecame\nbecap\nbecapped\nbecapping\nbecaps\nbecarpet\nbecarpeted\nbecarpeting\nbecarpets\nbecause\nbechalk\nbechalked\nbechalking\nbechalks\nbechamel\nbechamels\nbechance\nbechanced\nbechances\nbechancing\nbecharm\nbecharmed\nbecharming\nbecharms\nbeck\nbecked\nbecket\nbeckets\nbecking\nbeckon\nbeckoned\nbeckoner\nbeckoners\nbeckoning\nbeckons\nbecks\nbeclamor\nbeclamored\nbeclamoring\nbeclamors\nbeclasp\nbeclasped\nbeclasping\nbeclasps\nbecloak\nbecloaked\nbecloaking\nbecloaks\nbeclog\nbeclogged\nbeclogging\nbeclogs\nbeclothe\nbeclothed\nbeclothes\nbeclothing\nbecloud\nbeclouded\nbeclouding\nbeclouds\nbeclown\nbeclowned\nbeclowning\nbeclowns\nbecome\nbecomes\nbecoming\nbecomingly\nbecomings\nbecoward\nbecowarded\nbecowarding\nbecowards\nbecrawl\nbecrawled\nbecrawling\nbecrawls\nbecrime\nbecrimed\nbecrimes\nbecriming\nbecrowd\nbecrowded\nbecrowding\nbecrowds\nbecrust\nbecrusted\nbecrusting\nbecrusts\nbecudgel\nbecudgeled\nbecudgeling\nbecudgelled\nbecudgelling\nbecudgels\nbecurse\nbecursed\nbecurses\nbecursing\nbecurst\nbed\nbedabble\nbedabbled\nbedabbles\nbedabbling\nbedamn\nbedamned\nbedamning\nbedamns\nbedarken\nbedarkened\nbedarkening\nbedarkens\nbedaub\nbedaubed\nbedaubing\nbedaubs\nbedazzle\nbedazzled\nbedazzlement\nbedazzlements\nbedazzles\nbedazzling\nbedbug\nbedbugs\nbedchair\nbedchairs\nbedchamber\nbedchambers\nbedclothes\nbedcover\nbedcovering\nbedcoverings\nbedcovers\nbeddable\nbedded\nbedder\nbedders\nbedding\nbeddings\nbedeafen\nbedeafened\nbedeafening\nbedeafens\nbedeck\nbedecked\nbedecking\nbedecks\nbedel\nbedell\nbedells\nbedels\nbedeman\nbedemen\nbedesman\nbedesmen\nbedevil\nbedeviled\nbedeviling\nbedevilled\nbedevilling\nbedevilment\nbedevilments\nbedevils\nbedew\nbedewed\nbedewing\nbedews\nbedfast\nbedfellow\nbedfellows\nbedframe\nbedframes\nbedgown\nbedgowns\nbediaper\nbediapered\nbediapering\nbediapers\nbedight\nbedighted\nbedighting\nbedights\nbedim\nbedimmed\nbedimming\nbedimple\nbedimpled\nbedimples\nbedimpling\nbedims\nbedirtied\nbedirties\nbedirty\nbedirtying\nbedizen\nbedizened\nbedizening\nbedizenment\nbedizenments\nbedizens\nbedlam\nbedlamite\nbedlamites\nbedlamp\nbedlamps\nbedlams\nbedless\nbedlike\nbedmaker\nbedmakers\nbedmate\nbedmates\nbedotted\nbedouin\nbedouins\nbedpan\nbedpans\nbedplate\nbedplates\nbedpost\nbedposts\nbedquilt\nbedquilts\nbedraggle\nbedraggled\nbedraggles\nbedraggling\nbedrail\nbedrails\nbedrape\nbedraped\nbedrapes\nbedraping\nbedrench\nbedrenched\nbedrenches\nbedrenching\nbedrid\nbedridden\nbedrivel\nbedriveled\nbedriveling\nbedrivelled\nbedrivelling\nbedrivels\nbedrock\nbedrocks\nbedroll\nbedrolls\nbedroom\nbedroomed\nbedrooms\nbedrug\nbedrugged\nbedrugging\nbedrugs\nbeds\nbedsheet\nbedsheets\nbedside\nbedsides\nbedsit\nbedsits\nbedsonia\nbedsoniae\nbedsonias\nbedsore\nbedsores\nbedspread\nbedspreads\nbedspring\nbedsprings\nbedstand\nbedstands\nbedstead\nbedsteads\nbedstraw\nbedstraws\nbedtick\nbedticks\nbedtime\nbedtimes\nbedu\nbeduin\nbeduins\nbedumb\nbedumbed\nbedumbing\nbedumbs\nbedunce\nbedunced\nbedunces\nbeduncing\nbedward\nbedwards\nbedwarf\nbedwarfed\nbedwarfing\nbedwarfs\nbedwetter\nbedwetters\nbee\nbeebee\nbeebees\nbeebread\nbeebreads\nbeech\nbeechdrops\nbeechen\nbeeches\nbeechier\nbeechiest\nbeechnut\nbeechnuts\nbeechy\nbeef\nbeefalo\nbeefaloes\nbeefalos\nbeefcake\nbeefcakes\nbeefeater\nbeefeaters\nbeefed\nbeefier\nbeefiest\nbeefily\nbeefing\nbeefless\nbeefs\nbeefsteak\nbeefsteaks\nbeefwood\nbeefwoods\nbeefy\nbeehive\nbeehives\nbeekeeper\nbeekeepers\nbeekeeping\nbeekeepings\nbeelike\nbeeline\nbeelined\nbeelines\nbeelining\nbeen\nbeep\nbeeped\nbeeper\nbeepers\nbeeping\nbeeps\nbeer\nbeerier\nbeeriest\nbeers\nbeery\nbees\nbeestings\nbeeswax\nbeeswaxes\nbeeswing\nbeeswings\nbeet\nbeetle\nbeetled\nbeetler\nbeetlers\nbeetles\nbeetling\nbeetroot\nbeetroots\nbeets\nbeeves\nbeeyard\nbeeyards\nbeezer\nbeezers\nbefall\nbefallen\nbefalling\nbefalls\nbefell\nbefinger\nbefingered\nbefingering\nbefingers\nbefit\nbefits\nbefitted\nbefitting\nbefittingly\nbeflag\nbeflagged\nbeflagging\nbeflags\nbeflea\nbefleaed\nbefleaing\nbefleas\nbefleck\nbeflecked\nbeflecking\nbeflecks\nbeflower\nbeflowered\nbeflowering\nbeflowers\nbefog\nbefogged\nbefogging\nbefogs\nbefool\nbefooled\nbefooling\nbefools\nbefore\nbeforehand\nbeforetime\nbefoul\nbefouled\nbefouler\nbefoulers\nbefouling\nbefouls\nbefret\nbefrets\nbefretted\nbefretting\nbefriend\nbefriended\nbefriending\nbefriends\nbefringe\nbefringed\nbefringes\nbefringing\nbefuddle\nbefuddled\nbefuddlement\nbefuddlements\nbefuddles\nbefuddling\nbeg\nbegall\nbegalled\nbegalling\nbegalls\nbegan\nbegat\nbegaze\nbegazed\nbegazes\nbegazing\nbeget\nbegets\nbegetter\nbegetters\nbegetting\nbeggar\nbeggared\nbeggaries\nbeggaring\nbeggarliness\nbeggarlinesses\nbeggarly\nbeggars\nbeggarweed\nbeggarweeds\nbeggary\nbegged\nbegging\nbegin\nbeginner\nbeginners\nbeginning\nbeginnings\nbegins\nbegird\nbegirded\nbegirding\nbegirdle\nbegirdled\nbegirdles\nbegirdling\nbegirds\nbegirt\nbeglad\nbegladded\nbegladding\nbeglads\nbeglamor\nbeglamored\nbeglamoring\nbeglamors\nbeglamour\nbeglamoured\nbeglamouring\nbeglamours\nbegloom\nbegloomed\nbeglooming\nbeglooms\nbegone\nbegonia\nbegonias\nbegorah\nbegorra\nbegorrah\nbegot\nbegotten\nbegrim\nbegrime\nbegrimed\nbegrimes\nbegriming\nbegrimmed\nbegrimming\nbegrims\nbegroan\nbegroaned\nbegroaning\nbegroans\nbegrudge\nbegrudged\nbegrudges\nbegrudging\nbegrudgingly\nbegs\nbeguile\nbeguiled\nbeguilement\nbeguilements\nbeguiler\nbeguilers\nbeguiles\nbeguiling\nbeguilingly\nbeguine\nbeguines\nbegulf\nbegulfed\nbegulfing\nbegulfs\nbegum\nbegums\nbegun\nbehalf\nbehalves\nbehave\nbehaved\nbehaver\nbehavers\nbehaves\nbehaving\nbehavior\nbehavioral\nbehaviorally\nbehaviorism\nbehaviorisms\nbehaviorist\nbehavioristic\nbehaviorists\nbehaviors\nbehaviour\nbehaviours\nbehead\nbeheaded\nbeheading\nbeheadings\nbeheads\nbeheld\nbehemoth\nbehemoths\nbehest\nbehests\nbehind\nbehindhand\nbehinds\nbehold\nbeholden\nbeholder\nbeholders\nbeholding\nbeholds\nbehoof\nbehoove\nbehooved\nbehooves\nbehooving\nbehove\nbehoved\nbehoves\nbehoving\nbehowl\nbehowled\nbehowling\nbehowls\nbeige\nbeiges\nbeignet\nbeignets\nbeigy\nbeing\nbeings\nbejabers\nbejeezus\nbejesus\nbejewel\nbejeweled\nbejeweling\nbejewelled\nbejewelling\nbejewels\nbejumble\nbejumbled\nbejumbles\nbejumbling\nbekiss\nbekissed\nbekisses\nbekissing\nbeknight\nbeknighted\nbeknighting\nbeknights\nbeknot\nbeknots\nbeknotted\nbeknotting\nbel\nbelabor\nbelabored\nbelaboring\nbelabors\nbelabour\nbelaboured\nbelabouring\nbelabours\nbelaced\nbeladied\nbeladies\nbelady\nbeladying\nbelated\nbelatedly\nbelatedness\nbelatednesses\nbelaud\nbelauded\nbelauding\nbelauds\nbelay\nbelayed\nbelaying\nbelays\nbelch\nbelched\nbelcher\nbelchers\nbelches\nbelching\nbeldam\nbeldame\nbeldames\nbeldams\nbeleaguer\nbeleaguered\nbeleaguering\nbeleaguerment\nbeleaguerments\nbeleaguers\nbeleap\nbeleaped\nbeleaping\nbeleaps\nbeleapt\nbelemnite\nbelemnites\nbelfried\nbelfries\nbelfry\nbelga\nbelgas\nbelie\nbelied\nbelief\nbeliefs\nbelier\nbeliers\nbelies\nbelievabilities\nbelievability\nbelievable\nbelievably\nbelieve\nbelieved\nbeliever\nbelievers\nbelieves\nbelieving\nbelike\nbeliquor\nbeliquored\nbeliquoring\nbeliquors\nbelittle\nbelittled\nbelittlement\nbelittlements\nbelittler\nbelittlers\nbelittles\nbelittling\nbelive\nbell\nbelladonna\nbelladonnas\nbellbird\nbellbirds\nbellboy\nbellboys\nbelle\nbelled\nbelleek\nbelleeks\nbelles\nbelletrist\nbelletristic\nbelletrists\nbellflower\nbellflowers\nbellhop\nbellhops\nbellicose\nbellicosely\nbellicosities\nbellicosity\nbellied\nbellies\nbelligerence\nbelligerences\nbelligerencies\nbelligerency\nbelligerent\nbelligerently\nbelligerents\nbelling\nbellman\nbellmen\nbellow\nbellowed\nbellower\nbellowers\nbellowing\nbellows\nbellpull\nbellpulls\nbells\nbellwether\nbellwethers\nbellwort\nbellworts\nbelly\nbellyache\nbellyached\nbellyacher\nbellyachers\nbellyaches\nbellyaching\nbellyband\nbellybands\nbellybutton\nbellybuttons\nbellyful\nbellyfuls\nbellying\nbelong\nbelonged\nbelonging\nbelongingness\nbelongingnesses\nbelongings\nbelongs\nbeloved\nbeloveds\nbelow\nbelowdecks\nbelowground\nbelows\nbels\nbelt\nbelted\nbelter\nbelters\nbelting\nbeltings\nbeltless\nbeltline\nbeltlines\nbelts\nbeltway\nbeltways\nbeluga\nbelugas\nbelvedere\nbelvederes\nbelying\nbema\nbemadam\nbemadamed\nbemadaming\nbemadams\nbemadden\nbemaddened\nbemaddening\nbemaddens\nbemas\nbemata\nbemean\nbemeaned\nbemeaning\nbemeans\nbemedaled\nbemedalled\nbemingle\nbemingled\nbemingles\nbemingling\nbemire\nbemired\nbemires\nbemiring\nbemist\nbemisted\nbemisting\nbemists\nbemix\nbemixed\nbemixes\nbemixing\nbemixt\nbemoan\nbemoaned\nbemoaning\nbemoans\nbemock\nbemocked\nbemocking\nbemocks\nbemuddle\nbemuddled\nbemuddles\nbemuddling\nbemurmur\nbemurmured\nbemurmuring\nbemurmurs\nbemuse\nbemused\nbemusedly\nbemusement\nbemusements\nbemuses\nbemusing\nbemuzzle\nbemuzzled\nbemuzzles\nbemuzzling\nben\nbename\nbenamed\nbenames\nbenaming\nbench\nbenched\nbencher\nbenchers\nbenches\nbenching\nbenchland\nbenchlands\nbenchmark\nbenchmarking\nbenchmarkings\nbenchmarks\nbenchwarmer\nbenchwarmers\nbend\nbendable\nbenday\nbendayed\nbendaying\nbendays\nbended\nbendee\nbendees\nbender\nbenders\nbending\nbends\nbendways\nbendwise\nbendy\nbendys\nbene\nbeneath\nbenedick\nbenedicks\nbenedict\nbenediction\nbenedictions\nbenedictory\nbenedicts\nbenefaction\nbenefactions\nbenefactor\nbenefactors\nbenefactress\nbenefactresses\nbenefic\nbenefice\nbeneficed\nbeneficence\nbeneficences\nbeneficent\nbeneficently\nbenefices\nbeneficial\nbeneficially\nbeneficialness\nbeneficialnesses\nbeneficiaries\nbeneficiary\nbeneficiate\nbeneficiated\nbeneficiates\nbeneficiating\nbeneficiation\nbeneficiations\nbeneficing\nbenefit\nbenefited\nbenefiter\nbenefiters\nbenefiting\nbenefits\nbenefitted\nbenefitting\nbenempt\nbenempted\nbenes\nbenevolence\nbenevolences\nbenevolent\nbenevolently\nbenevolentness\nbenevolentnesses\nbengaline\nbengalines\nbenighted\nbenightedly\nbenightedness\nbenightednesses\nbenign\nbenignancies\nbenignancy\nbenignant\nbenignantly\nbenignities\nbenignity\nbenignly\nbenison\nbenisons\nbenjamin\nbenjamins\nbenne\nbennes\nbennet\nbennets\nbenni\nbennies\nbennis\nbenny\nbenomyl\nbenomyls\nbens\nbent\nbenthal\nbenthic\nbenthonic\nbenthos\nbenthoses\nbentonite\nbentonites\nbentonitic\nbents\nbentwood\nbentwoods\nbenumb\nbenumbed\nbenumbing\nbenumbs\nbenzal\nbenzaldehyde\nbenzaldehydes\nbenzanthracene\nbenzanthracenes\nbenzene\nbenzenes\nbenzenoid\nbenzidin\nbenzidine\nbenzidines\nbenzidins\nbenzimidazole\nbenzimidazoles\nbenzin\nbenzine\nbenzines\nbenzins\nbenzoapyrene\nbenzoapyrenes\nbenzoate\nbenzoates\nbenzocaine\nbenzocaines\nbenzodiazepine\nbenzodiazepines\nbenzofuran\nbenzofurans\nbenzoic\nbenzoin\nbenzoins\nbenzol\nbenzole\nbenzoles\nbenzols\nbenzophenone\nbenzophenones\nbenzoyl\nbenzoyls\nbenzyl\nbenzylic\nbenzyls\nbepaint\nbepainted\nbepainting\nbepaints\nbepimple\nbepimpled\nbepimples\nbepimpling\nbequeath\nbequeathal\nbequeathals\nbequeathed\nbequeathing\nbequeaths\nbequest\nbequests\nberake\nberaked\nberakes\nberaking\nberascal\nberascaled\nberascaling\nberascals\nberate\nberated\nberates\nberating\nberberin\nberberine\nberberines\nberberins\nberberis\nberberises\nberceuse\nberceuses\nberdache\nberdaches\nbereave\nbereaved\nbereavement\nbereavements\nbereaver\nbereavers\nbereaves\nbereaving\nbereft\nberet\nberets\nberetta\nberettas\nberg\nbergamot\nbergamots\nbergere\nbergeres\nbergs\nberhyme\nberhymed\nberhymes\nberhyming\nberibboned\nberiberi\nberiberis\nberime\nberimed\nberimes\nberiming\nberinged\nberkelium\nberkeliums\nberlin\nberline\nberlines\nberlins\nberm\nberme\nbermes\nberms\nbermudas\nbernicle\nbernicles\nberobed\nberouged\nberretta\nberrettas\nberried\nberries\nberry\nberrying\nberrylike\nberseem\nberseems\nberserk\nberserker\nberserkers\nberserkly\nberserks\nberth\nbertha\nberthas\nberthed\nberthing\nberths\nberyl\nberyline\nberyllium\nberylliums\nberyls\nbescorch\nbescorched\nbescorches\nbescorching\nbescour\nbescoured\nbescouring\nbescours\nbescreen\nbescreened\nbescreening\nbescreens\nbeseech\nbeseeched\nbeseeches\nbeseeching\nbeseechingly\nbeseem\nbeseemed\nbeseeming\nbeseems\nbeset\nbesetment\nbesetments\nbesets\nbesetter\nbesetters\nbesetting\nbeshadow\nbeshadowed\nbeshadowing\nbeshadows\nbeshame\nbeshamed\nbeshames\nbeshaming\nbeshiver\nbeshivered\nbeshivering\nbeshivers\nbeshout\nbeshouted\nbeshouting\nbeshouts\nbeshrew\nbeshrewed\nbeshrewing\nbeshrews\nbeshroud\nbeshrouded\nbeshrouding\nbeshrouds\nbeside\nbesides\nbesiege\nbesieged\nbesieger\nbesiegers\nbesieges\nbesieging\nbeslaved\nbeslime\nbeslimed\nbeslimes\nbesliming\nbesmear\nbesmeared\nbesmearing\nbesmears\nbesmile\nbesmiled\nbesmiles\nbesmiling\nbesmirch\nbesmirched\nbesmirches\nbesmirching\nbesmoke\nbesmoked\nbesmokes\nbesmoking\nbesmooth\nbesmoothed\nbesmoothing\nbesmooths\nbesmudge\nbesmudged\nbesmudges\nbesmudging\nbesmut\nbesmuts\nbesmutted\nbesmutting\nbesnow\nbesnowed\nbesnowing\nbesnows\nbesom\nbesoms\nbesoothe\nbesoothed\nbesoothes\nbesoothing\nbesot\nbesots\nbesotted\nbesotting\nbesought\nbespake\nbespatter\nbespattered\nbespattering\nbespatters\nbespeak\nbespeaking\nbespeaks\nbespectacled\nbespoke\nbespoken\nbespouse\nbespoused\nbespouses\nbespousing\nbespread\nbespreading\nbespreads\nbesprent\nbesprinkle\nbesprinkled\nbesprinkles\nbesprinkling\nbest\nbestead\nbesteaded\nbesteading\nbesteads\nbested\nbestial\nbestialities\nbestiality\nbestialize\nbestialized\nbestializes\nbestializing\nbestially\nbestiaries\nbestiary\nbesting\nbestir\nbestirred\nbestirring\nbestirs\nbestow\nbestowal\nbestowals\nbestowed\nbestowing\nbestows\nbestrew\nbestrewed\nbestrewing\nbestrewn\nbestrews\nbestrid\nbestridden\nbestride\nbestrides\nbestriding\nbestrode\nbestrow\nbestrowed\nbestrowing\nbestrown\nbestrows\nbests\nbestseller\nbestsellerdom\nbestsellerdoms\nbestsellers\nbestud\nbestudded\nbestudding\nbestuds\nbeswarm\nbeswarmed\nbeswarming\nbeswarms\nbet\nbeta\nbetaine\nbetaines\nbetake\nbetaken\nbetakes\nbetaking\nbetas\nbetatron\nbetatrons\nbetatter\nbetattered\nbetattering\nbetatters\nbetaxed\nbetel\nbetelnut\nbetelnuts\nbetels\nbeth\nbethank\nbethanked\nbethanking\nbethanks\nbethel\nbethels\nbethesda\nbethesdas\nbethink\nbethinking\nbethinks\nbethorn\nbethorned\nbethorning\nbethorns\nbethought\nbeths\nbethump\nbethumped\nbethumping\nbethumps\nbetide\nbetided\nbetides\nbetiding\nbetime\nbetimes\nbetise\nbetises\nbetoken\nbetokened\nbetokening\nbetokens\nbeton\nbetonies\nbetons\nbetony\nbetook\nbetray\nbetrayal\nbetrayals\nbetrayed\nbetrayer\nbetrayers\nbetraying\nbetrays\nbetroth\nbetrothal\nbetrothals\nbetrothed\nbetrotheds\nbetrothing\nbetroths\nbets\nbetta\nbettas\nbetted\nbetter\nbettered\nbettering\nbetterment\nbetterments\nbetters\nbetting\nbettor\nbettors\nbetween\nbetweenbrain\nbetweenbrains\nbetweenness\nbetweennesses\nbetweentimes\nbetweenwhiles\nbetwixt\nbeuncled\nbevatron\nbevatrons\nbevel\nbeveled\nbeveler\nbevelers\nbeveling\nbevelled\nbeveller\nbevellers\nbevelling\nbevels\nbeverage\nbeverages\nbevies\nbevomit\nbevomited\nbevomiting\nbevomits\nbevor\nbevors\nbevy\nbewail\nbewailed\nbewailer\nbewailers\nbewailing\nbewails\nbeware\nbewared\nbewares\nbewaring\nbewearied\nbewearies\nbeweary\nbewearying\nbeweep\nbeweeping\nbeweeps\nbewept\nbewhiskered\nbewig\nbewigged\nbewigging\nbewigs\nbewilder\nbewildered\nbewilderedly\nbewilderedness\nbewilderednesses\nbewildering\nbewilderingly\nbewilderment\nbewilderments\nbewilders\nbewinged\nbewitch\nbewitched\nbewitcheries\nbewitchery\nbewitches\nbewitching\nbewitchingly\nbewitchment\nbewitchments\nbeworm\nbewormed\nbeworming\nbeworms\nbeworried\nbeworries\nbeworry\nbeworrying\nbewrap\nbewrapped\nbewrapping\nbewraps\nbewrapt\nbewray\nbewrayed\nbewrayer\nbewrayers\nbewraying\nbewrays\nbey\nbeylic\nbeylics\nbeylik\nbeyliks\nbeyond\nbeyonds\nbeys\nbezant\nbezants\nbezazz\nbezazzes\nbezel\nbezels\nbezil\nbezils\nbezique\nbeziques\nbezoar\nbezoars\nbezzant\nbezzants\nbhakta\nbhaktas\nbhakti\nbhaktis\nbhang\nbhangs\nbharal\nbharals\nbheestie\nbheesties\nbheesty\nbhistie\nbhisties\nbhoot\nbhoots\nbhut\nbhuts\nbi\nbiacetyl\nbiacetyls\nbiali\nbialies\nbialis\nbialy\nbialys\nbiannual\nbiannually\nbias\nbiased\nbiasedly\nbiases\nbiasing\nbiasness\nbiasnesses\nbiassed\nbiasses\nbiassing\nbiathlete\nbiathletes\nbiathlon\nbiathlons\nbiaxal\nbiaxial\nbiaxially\nbib\nbibasic\nbibb\nbibbed\nbibber\nbibberies\nbibbers\nbibbery\nbibbing\nbibbs\nbibcock\nbibcocks\nbibelot\nbibelots\nbible\nbibles\nbibless\nbiblical\nbiblically\nbiblicism\nbiblicisms\nbiblicist\nbiblicists\nbiblike\nbibliographer\nbibliographers\nbibliographic\nbibliographical\nbibliographically\nbibliographies\nbibliography\nbibliolater\nbibliolaters\nbibliolatries\nbibliolatrous\nbibliolatry\nbibliologies\nbibliology\nbibliomania\nbibliomaniac\nbibliomaniacal\nbibliomaniacs\nbibliomanias\nbibliopegic\nbibliopegies\nbibliopegist\nbibliopegists\nbibliopegy\nbibliophile\nbibliophiles\nbibliophilic\nbibliophilies\nbibliophilism\nbibliophilisms\nbibliophily\nbibliopole\nbibliopoles\nbibliopolist\nbibliopolists\nbibliotheca\nbibliothecae\nbibliothecal\nbibliothecas\nbibliotherapies\nbibliotherapy\nbibliotic\nbibliotics\nbibliotist\nbibliotists\nbiblist\nbiblists\nbibs\nbibulous\nbibulously\nbibulousness\nbibulousnesses\nbicameral\nbicameralism\nbicameralisms\nbicarb\nbicarbonate\nbicarbonates\nbicarbs\nbicaudal\nbice\nbicentenaries\nbicentenary\nbicentennial\nbicentennials\nbiceps\nbicepses\nbices\nbichromate\nbichromated\nbichromates\nbichrome\nbicipital\nbicker\nbickered\nbickerer\nbickerers\nbickering\nbickers\nbicoastal\nbicolor\nbicolored\nbicolors\nbicolour\nbicolours\nbicomponent\nbiconcave\nbiconcavities\nbiconcavity\nbiconditional\nbiconditionals\nbiconvex\nbiconvexities\nbiconvexity\nbicorn\nbicorne\nbicornes\nbicron\nbicrons\nbicultural\nbiculturalism\nbiculturalisms\nbicuspid\nbicuspids\nbicycle\nbicycled\nbicycler\nbicyclers\nbicycles\nbicyclic\nbicycling\nbicyclist\nbicyclists\nbid\nbidarka\nbidarkas\nbidarkee\nbidarkees\nbiddabilities\nbiddability\nbiddable\nbiddably\nbidden\nbidder\nbidders\nbiddies\nbidding\nbiddings\nbiddy\nbide\nbided\nbidental\nbider\nbiders\nbides\nbidet\nbidets\nbidialectal\nbidialectalism\nbidialectalisms\nbiding\nbidirectional\nbidirectionally\nbidonville\nbidonvilles\nbids\nbield\nbielded\nbielding\nbields\nbiennale\nbiennales\nbiennia\nbiennial\nbiennially\nbiennials\nbiennium\nbienniums\nbier\nbiers\nbiface\nbifaces\nbifacial\nbifacially\nbiff\nbiffed\nbiffies\nbiffin\nbiffing\nbiffins\nbiffs\nbiffy\nbifid\nbifidities\nbifidity\nbifidly\nbifilar\nbifilarly\nbiflagellate\nbiflex\nbifocal\nbifocals\nbifold\nbiforate\nbiforked\nbiform\nbiformed\nbifunctional\nbifurcate\nbifurcated\nbifurcates\nbifurcating\nbifurcation\nbifurcations\nbig\nbigamies\nbigamist\nbigamists\nbigamous\nbigamously\nbigamy\nbigarade\nbigarades\nbigaroon\nbigaroons\nbigeminal\nbigeminies\nbigeminy\nbigeneric\nbigeye\nbigeyes\nbigfeet\nbigfoot\nbigfoots\nbigger\nbiggest\nbiggety\nbiggie\nbiggies\nbiggin\nbigging\nbiggings\nbiggins\nbiggish\nbiggity\nbighead\nbigheaded\nbigheads\nbighearted\nbigheartedly\nbigheartedness\nbigheartednesses\nbighorn\nbighorns\nbight\nbighted\nbighting\nbights\nbigly\nbigmouth\nbigmouthed\nbigmouths\nbigness\nbignesses\nbignonia\nbignonias\nbigot\nbigoted\nbigotedly\nbigotries\nbigotry\nbigots\nbigs\nbigshot\nbigshots\nbigwig\nbigwigs\nbihourly\nbijection\nbijections\nbijective\nbijou\nbijous\nbijouterie\nbijouteries\nbijoux\nbijugate\nbijugous\nbike\nbiked\nbiker\nbikers\nbikes\nbikeway\nbikeways\nbikie\nbikies\nbiking\nbikini\nbikinied\nbikinis\nbilabial\nbilabials\nbilabiate\nbilander\nbilanders\nbilateral\nbilateralism\nbilateralisms\nbilaterally\nbilayer\nbilayers\nbilberries\nbilberry\nbilbo\nbilboa\nbilboas\nbilboes\nbilbos\nbildungsroman\nbildungsromane\nbildungsromans\nbile\nbiles\nbilge\nbilged\nbilges\nbilgewater\nbilgewaters\nbilgier\nbilgiest\nbilging\nbilgy\nbilharzia\nbilharzial\nbilharzias\nbilharziases\nbilharziasis\nbiliary\nbilinear\nbilingual\nbilingualism\nbilingualisms\nbilingually\nbilinguals\nbilious\nbiliously\nbiliousness\nbiliousnesses\nbilirubin\nbilirubins\nbiliverdin\nbiliverdins\nbilk\nbilked\nbilker\nbilkers\nbilking\nbilks\nbill\nbillable\nbillabong\nbillabongs\nbillboard\nbillboarded\nbillboarding\nbillboards\nbillbug\nbillbugs\nbilled\nbiller\nbillers\nbillet\nbilleted\nbilleter\nbilleters\nbilleting\nbillets\nbillfish\nbillfishes\nbillfold\nbillfolds\nbillhead\nbillheads\nbillhook\nbillhooks\nbilliard\nbilliards\nbillie\nbillies\nbilling\nbillings\nbillingsgate\nbillingsgates\nbillion\nbillionaire\nbillionaires\nbillions\nbillionth\nbillionths\nbillon\nbillons\nbillow\nbillowed\nbillowier\nbillowiest\nbillowing\nbillows\nbillowy\nbills\nbilly\nbillycan\nbillycans\nbillycock\nbillycocks\nbilobate\nbilobed\nbilocation\nbilocations\nbilsted\nbilsteds\nbiltong\nbiltongs\nbima\nbimah\nbimahs\nbimanous\nbimanual\nbimanually\nbimas\nbimbo\nbimboes\nbimbos\nbimensal\nbimester\nbimesters\nbimetal\nbimetallic\nbimetallics\nbimetallism\nbimetallisms\nbimetallist\nbimetallistic\nbimetallists\nbimetals\nbimethyl\nbimethyls\nbimillenaries\nbimillenary\nbimillennial\nbimillennials\nbimodal\nbimodalities\nbimodality\nbimolecular\nbimolecularly\nbimonthlies\nbimonthly\nbimorph\nbimorphemic\nbimorphs\nbin\nbinal\nbinaries\nbinary\nbinate\nbinately\nbinational\nbinaural\nbinaurally\nbind\nbindable\nbinder\nbinderies\nbinders\nbindery\nbindi\nbinding\nbindingly\nbindingness\nbindingnesses\nbindings\nbindis\nbindle\nbindles\nbinds\nbindweed\nbindweeds\nbine\nbines\nbinge\nbinged\nbingeing\nbinger\nbingers\nbinges\nbinging\nbingo\nbingos\nbinit\nbinits\nbinnacle\nbinnacles\nbinned\nbinning\nbinocle\nbinocles\nbinocs\nbinocular\nbinocularities\nbinocularity\nbinocularly\nbinoculars\nbinomial\nbinomially\nbinomials\nbins\nbint\nbints\nbinucleate\nbinucleated\nbio\nbioacoustics\nbioactive\nbioactivities\nbioactivity\nbioassay\nbioassayed\nbioassaying\nbioassays\nbioavailabilities\nbioavailability\nbioavailable\nbiocenoses\nbiocenosis\nbiochemical\nbiochemically\nbiochemicals\nbiochemist\nbiochemistries\nbiochemistry\nbiochemists\nbiochip\nbiochips\nbiocidal\nbiocide\nbiocides\nbioclean\nbioclimatic\nbiocoenoses\nbiocoenosis\nbiocompatibilities\nbiocompatibility\nbiocompatible\nbiocontrol\nbiocontrols\nbioconversion\nbioconversions\nbiocycle\nbiocycles\nbiodegradabilities\nbiodegradability\nbiodegradable\nbiodegradation\nbiodegradations\nbiodegrade\nbiodegraded\nbiodegrades\nbiodegrading\nbiodeterioration\nbiodeteriorations\nbiodiversities\nbiodiversity\nbiodynamic\nbioelectric\nbioelectrical\nbioelectricities\nbioelectricity\nbioenergetic\nbioenergetics\nbioengineer\nbioengineered\nbioengineering\nbioengineerings\nbioengineers\nbioethic\nbioethical\nbioethicist\nbioethicists\nbioethics\nbiofeedback\nbiofeedbacks\nbiofouling\nbiofoulings\nbiogas\nbiogases\nbiogasses\nbiogen\nbiogeneses\nbiogenesis\nbiogenetic\nbiogenetically\nbiogenic\nbiogenies\nbiogenous\nbiogens\nbiogeny\nbiogeochemical\nbiogeochemicals\nbiogeochemistries\nbiogeochemistry\nbiogeographer\nbiogeographers\nbiogeographic\nbiogeographical\nbiogeographies\nbiogeography\nbiographee\nbiographees\nbiographer\nbiographers\nbiographic\nbiographical\nbiographically\nbiographies\nbiography\nbiohazard\nbiohazards\nbioherm\nbioherms\nbiologic\nbiological\nbiologically\nbiologicals\nbiologics\nbiologies\nbiologism\nbiologisms\nbiologist\nbiologistic\nbiologists\nbiology\nbioluminescence\nbioluminescences\nbioluminescent\nbiolyses\nbiolysis\nbiolytic\nbiomarker\nbiomarkers\nbiomass\nbiomasses\nbiomaterial\nbiomaterials\nbiomathematical\nbiomathematician\nbiomathematicians\nbiomathematics\nbiome\nbiomechanical\nbiomechanically\nbiomechanics\nbiomedical\nbiomedicine\nbiomedicines\nbiomes\nbiometeorological\nbiometeorologies\nbiometeorology\nbiometric\nbiometrical\nbiometrician\nbiometricians\nbiometrics\nbiometries\nbiometry\nbiomolecular\nbiomolecule\nbiomolecules\nbiomorphic\nbionic\nbionics\nbionomic\nbionomics\nbionomies\nbionomy\nbiont\nbiontic\nbionts\nbiophysical\nbiophysicist\nbiophysicists\nbiophysics\nbiopic\nbiopics\nbioplasm\nbioplasms\nbiopolymer\nbiopolymers\nbiopsic\nbiopsied\nbiopsies\nbiopsy\nbiopsying\nbioptic\nbioreactor\nbioreactors\nbioregion\nbioregional\nbioregionalism\nbioregionalisms\nbioregionalist\nbioregionalists\nbioregions\nbioremediation\nbioremediations\nbiorhythm\nbiorhythmic\nbiorhythms\nbios\nbiosafeties\nbiosafety\nbioscience\nbiosciences\nbioscientific\nbioscientist\nbioscientists\nbioscope\nbioscopes\nbioscopies\nbioscopy\nbiosensor\nbiosensors\nbiosocial\nbiosocially\nbiosolid\nbiosolids\nbiosphere\nbiospheres\nbiospheric\nbiostatistical\nbiostatistician\nbiostatisticians\nbiostatistics\nbiostratigraphic\nbiostratigraphies\nbiostratigraphy\nbiosyntheses\nbiosynthesis\nbiosynthetic\nbiosynthetically\nbiosystematic\nbiosystematics\nbiosystematist\nbiosystematists\nbiota\nbiotas\nbiotech\nbiotechnical\nbiotechnological\nbiotechnologies\nbiotechnologist\nbiotechnologists\nbiotechnology\nbiotechs\nbiotelemetric\nbiotelemetries\nbiotelemetry\nbiotic\nbiotical\nbiotics\nbiotin\nbiotins\nbiotite\nbiotites\nbiotitic\nbiotope\nbiotopes\nbiotoxin\nbiotoxins\nbiotransformation\nbiotransformations\nbiotron\nbiotrons\nbiotype\nbiotypes\nbiotypic\nbiovular\nbipack\nbipacks\nbiparental\nbiparentally\nbiparous\nbiparted\nbipartisan\nbipartisanism\nbipartisanisms\nbipartisanship\nbipartisanships\nbipartite\nbipartitely\nbipartition\nbipartitions\nbiparty\nbiped\nbipedal\nbipedalism\nbipedalisms\nbipedalities\nbipedality\nbipedally\nbipeds\nbiphasic\nbiphenyl\nbiphenyls\nbipinnate\nbipinnately\nbiplane\nbiplanes\nbipod\nbipods\nbipolar\nbipolarities\nbipolarity\nbipolarization\nbipolarizations\nbipolarize\nbipolarized\nbipolarizes\nbipolarizing\nbipropellant\nbipropellants\nbipyramid\nbipyramidal\nbipyramids\nbiquadratic\nbiquadratics\nbiracial\nbiracialism\nbiracialisms\nbiradial\nbiramose\nbiramous\nbirch\nbirched\nbirchen\nbirches\nbirching\nbird\nbirdbath\nbirdbaths\nbirdbrain\nbirdbrained\nbirdbrains\nbirdcage\nbirdcages\nbirdcall\nbirdcalls\nbirded\nbirder\nbirders\nbirdfarm\nbirdfarms\nbirdhouse\nbirdhouses\nbirdie\nbirdied\nbirdieing\nbirdies\nbirding\nbirdings\nbirdlike\nbirdlime\nbirdlimed\nbirdlimes\nbirdliming\nbirdman\nbirdmen\nbirds\nbirdseed\nbirdseeds\nbirdseye\nbirdseyes\nbirdshot\nbirdshots\nbirdsong\nbirdsongs\nbirdwatcher\nbirdwatchers\nbirefringence\nbirefringences\nbirefringent\nbireme\nbiremes\nbiretta\nbirettas\nbirk\nbirkie\nbirkies\nbirks\nbirl\nbirle\nbirled\nbirler\nbirlers\nbirles\nbirling\nbirlings\nbirls\nbirr\nbirred\nbirretta\nbirrettas\nbirring\nbirrotch\nbirrs\nbirse\nbirses\nbirth\nbirthdate\nbirthdates\nbirthday\nbirthdays\nbirthed\nbirthing\nbirthmark\nbirthmarks\nbirthplace\nbirthplaces\nbirthrate\nbirthrates\nbirthright\nbirthrights\nbirthroot\nbirthroots\nbirths\nbirthstone\nbirthstones\nbirthwort\nbirthworts\nbis\nbiscuit\nbiscuits\nbise\nbisect\nbisected\nbisecting\nbisection\nbisectional\nbisectionally\nbisections\nbisector\nbisectors\nbisects\nbises\nbisexual\nbisexualities\nbisexuality\nbisexually\nbisexuals\nbishop\nbishoped\nbishoping\nbishopric\nbishoprics\nbishops\nbisk\nbisks\nbismuth\nbismuthic\nbismuths\nbisnaga\nbisnagas\nbison\nbisons\nbisontine\nbisque\nbisques\nbistate\nbister\nbistered\nbisters\nbistort\nbistorts\nbistouries\nbistoury\nbistre\nbistred\nbistres\nbistro\nbistroic\nbistros\nbisulfate\nbisulfates\nbisulfide\nbisulfides\nbisulfite\nbisulfites\nbit\nbitable\nbitartrate\nbitartrates\nbitch\nbitched\nbitcheries\nbitchery\nbitches\nbitchier\nbitchiest\nbitchily\nbitchiness\nbitchinesses\nbitching\nbitchy\nbite\nbiteable\nbiter\nbiters\nbites\nbitewing\nbitewings\nbiting\nbitingly\nbits\nbitstock\nbitstocks\nbitsy\nbitt\nbitted\nbitten\nbitter\nbitterbrush\nbitterbrushes\nbittered\nbitterer\nbitterest\nbittering\nbitterish\nbitterly\nbittern\nbitterness\nbitternesses\nbitterns\nbitterroot\nbitterroots\nbitters\nbittersweet\nbittersweetly\nbittersweetness\nbittersweetnesses\nbittersweets\nbitterweed\nbitterweeds\nbittier\nbittiest\nbitting\nbittings\nbittock\nbittocks\nbitts\nbitty\nbitumen\nbitumens\nbituminization\nbituminizations\nbituminize\nbituminized\nbituminizes\nbituminizing\nbituminous\nbiunique\nbiuniqueness\nbiuniquenesses\nbivalent\nbivalents\nbivalve\nbivalved\nbivalves\nbivariate\nbivinyl\nbivinyls\nbivouac\nbivouacked\nbivouacking\nbivouacks\nbivouacs\nbiweeklies\nbiweekly\nbiyearly\nbiz\nbizarre\nbizarrely\nbizarreness\nbizarrenesses\nbizarrerie\nbizarreries\nbizarres\nbize\nbizes\nbiznaga\nbiznagas\nbizonal\nbizone\nbizones\nbizzes\nblab\nblabbed\nblabber\nblabbered\nblabbering\nblabbermouth\nblabbermouths\nblabbers\nblabbing\nblabby\nblabs\nblack\nblackamoor\nblackamoors\nblackball\nblackballed\nblackballing\nblackballs\nblackberries\nblackberry\nblackbird\nblackbirded\nblackbirder\nblackbirders\nblackbirding\nblackbirds\nblackboard\nblackboards\nblackbodies\nblackbody\nblackboy\nblackboys\nblackcap\nblackcaps\nblackcock\nblackcocks\nblacked\nblacken\nblackened\nblackener\nblackeners\nblackening\nblackenings\nblackens\nblacker\nblackest\nblackface\nblackfaces\nblackfin\nblackfins\nblackfish\nblackfishes\nblackflies\nblackfly\nblackguard\nblackguarded\nblackguarding\nblackguardism\nblackguardisms\nblackguardly\nblackguards\nblackgum\nblackgums\nblackhander\nblackhanders\nblackhead\nblackheads\nblackheart\nblackhearts\nblacking\nblackings\nblackish\nblackjack\nblackjacked\nblackjacking\nblackjacks\nblackland\nblacklands\nblacklead\nblackleads\nblackleg\nblacklegs\nblacklist\nblacklisted\nblacklister\nblacklisters\nblacklisting\nblacklists\nblackly\nblackmail\nblackmailed\nblackmailer\nblackmailers\nblackmailing\nblackmails\nblackness\nblacknesses\nblackout\nblackouts\nblackpoll\nblackpolls\nblacks\nblacksmith\nblacksmithing\nblacksmithings\nblacksmiths\nblacksnake\nblacksnakes\nblacktail\nblacktails\nblackthorn\nblackthorns\nblacktop\nblacktopped\nblacktopping\nblacktops\nblackwater\nblackwaters\nblackwood\nblackwoods\nbladder\nbladderlike\nbladdernut\nbladdernuts\nbladders\nbladderwort\nbladderworts\nbladdery\nblade\nbladed\nbladelike\nblades\nblae\nblaeberries\nblaeberry\nblah\nblahs\nblain\nblains\nblam\nblamable\nblamably\nblame\nblamed\nblameful\nblamefully\nblameless\nblamelessly\nblamelessness\nblamelessnesses\nblamer\nblamers\nblames\nblameworthiness\nblameworthinesses\nblameworthy\nblaming\nblams\nblanch\nblanched\nblancher\nblanchers\nblanches\nblanching\nblancmange\nblancmanges\nbland\nblander\nblandest\nblandish\nblandished\nblandisher\nblandishers\nblandishes\nblandishing\nblandishment\nblandishments\nblandly\nblandness\nblandnesses\nblank\nblanked\nblanker\nblankest\nblanket\nblanketed\nblanketflower\nblanketflowers\nblanketing\nblanketlike\nblankets\nblanking\nblankly\nblankness\nblanknesses\nblanks\nblanquette\nblanquettes\nblare\nblared\nblares\nblaring\nblarney\nblarneyed\nblarneying\nblarneys\nblase\nblaspheme\nblasphemed\nblasphemer\nblasphemers\nblasphemes\nblasphemies\nblaspheming\nblasphemous\nblasphemously\nblasphemousness\nblasphemousnesses\nblasphemy\nblast\nblasted\nblastema\nblastemal\nblastemas\nblastemata\nblastematic\nblaster\nblasters\nblastie\nblastier\nblasties\nblastiest\nblasting\nblastings\nblastment\nblastments\nblastocoel\nblastocoele\nblastocoeles\nblastocoelic\nblastocoels\nblastocyst\nblastocysts\nblastoderm\nblastoderms\nblastodisc\nblastodiscs\nblastoff\nblastoffs\nblastoma\nblastomas\nblastomata\nblastomere\nblastomeres\nblastomycoses\nblastomycosis\nblastopore\nblastopores\nblastoporic\nblastospore\nblastospores\nblasts\nblastula\nblastulae\nblastulas\nblastulation\nblastulations\nblasty\nblat\nblatancies\nblatancy\nblatant\nblatantly\nblate\nblather\nblathered\nblatherer\nblatherers\nblathering\nblathers\nblatherskite\nblatherskites\nblats\nblatted\nblatter\nblattered\nblattering\nblatters\nblatting\nblaubok\nblauboks\nblaw\nblawed\nblawing\nblawn\nblaws\nblaxploitation\nblaxploitations\nblaze\nblazed\nblazer\nblazers\nblazes\nblazing\nblazingly\nblazon\nblazoned\nblazoner\nblazoners\nblazoning\nblazonings\nblazonries\nblazonry\nblazons\nbleach\nbleachable\nbleached\nbleacher\nbleacherite\nbleacherites\nbleachers\nbleaches\nbleaching\nbleak\nbleaker\nbleakest\nbleakish\nbleakly\nbleakness\nbleaknesses\nbleaks\nblear\nbleared\nblearier\nbleariest\nblearily\nbleariness\nblearinesses\nblearing\nblears\nbleary\nbleat\nbleated\nbleater\nbleaters\nbleating\nbleats\nbleb\nblebby\nblebs\nbled\nbleed\nbleeder\nbleeders\nbleeding\nbleedings\nbleeds\nbleep\nbleeped\nbleeping\nbleeps\nblellum\nblellums\nblemish\nblemished\nblemishes\nblemishing\nblench\nblenched\nblencher\nblenchers\nblenches\nblenching\nblend\nblende\nblended\nblender\nblenders\nblendes\nblending\nblends\nblennies\nblenny\nblent\nblepharoplast\nblepharoplasties\nblepharoplasts\nblepharoplasty\nblepharospasm\nblepharospasms\nblesbok\nblesboks\nblesbuck\nblesbucks\nbless\nblessed\nblesseder\nblessedest\nblessedly\nblessedness\nblessednesses\nblesser\nblessers\nblesses\nblessing\nblessings\nblest\nblet\nblether\nblethered\nblethering\nblethers\nblets\nblew\nblight\nblighted\nblighter\nblighters\nblighties\nblighting\nblights\nblighty\nblimey\nblimp\nblimpish\nblimpishly\nblimpishness\nblimpishnesses\nblimps\nblimy\nblin\nblind\nblindage\nblindages\nblinded\nblinder\nblinders\nblindest\nblindfish\nblindfishes\nblindfold\nblindfolded\nblindfolding\nblindfolds\nblinding\nblindingly\nblindly\nblindness\nblindnesses\nblinds\nblindside\nblindsided\nblindsides\nblindsiding\nblindworm\nblindworms\nblini\nblinis\nblink\nblinkard\nblinkards\nblinked\nblinker\nblinkered\nblinkering\nblinkers\nblinking\nblinks\nblintz\nblintze\nblintzes\nblip\nblipped\nblipping\nblips\nbliss\nblissed\nblisses\nblissful\nblissfully\nblissfulness\nblissfulnesses\nblissing\nblister\nblistered\nblistering\nblisteringly\nblisters\nblistery\nblite\nblites\nblithe\nblithely\nblither\nblithered\nblithering\nblithers\nblithesome\nblithesomely\nblithest\nblitz\nblitzed\nblitzes\nblitzing\nblitzkrieg\nblitzkriegs\nblivet\nblivets\nblizzard\nblizzardly\nblizzards\nblizzardy\nbloat\nbloated\nbloater\nbloaters\nbloating\nbloats\nblob\nblobbed\nblobbing\nblobs\nbloc\nblock\nblockade\nblockaded\nblockader\nblockaders\nblockades\nblockading\nblockage\nblockages\nblockbuster\nblockbusters\nblockbusting\nblockbustings\nblocked\nblocker\nblockers\nblockhead\nblockheads\nblockhouse\nblockhouses\nblockier\nblockiest\nblocking\nblockish\nblocks\nblocky\nblocs\nbloke\nblokes\nblond\nblonde\nblonder\nblondes\nblondest\nblondish\nblonds\nblood\nbloodbath\nbloodbaths\nbloodcurdling\nblooded\nbloodfin\nbloodfins\nbloodguilt\nbloodguiltiness\nbloodguiltinesses\nbloodguilts\nbloodguilty\nbloodhound\nbloodhounds\nbloodied\nbloodier\nbloodies\nbloodiest\nbloodily\nbloodiness\nbloodinesses\nblooding\nbloodings\nbloodless\nbloodlessly\nbloodlessness\nbloodlessnesses\nbloodletting\nbloodlettings\nbloodline\nbloodlines\nbloodmobile\nbloodmobiles\nbloodred\nbloodroot\nbloodroots\nbloods\nbloodshed\nbloodsheds\nbloodshot\nbloodstain\nbloodstained\nbloodstains\nbloodstock\nbloodstocks\nbloodstone\nbloodstones\nbloodstream\nbloodstreams\nbloodsucker\nbloodsuckers\nbloodsucking\nbloodthirstily\nbloodthirstiness\nbloodthirstinesses\nbloodthirsty\nbloodworm\nbloodworms\nbloody\nbloodying\nblooey\nblooie\nbloom\nbloomed\nbloomer\nbloomeries\nbloomers\nbloomery\nbloomier\nbloomiest\nblooming\nblooms\nbloomy\nbloop\nblooped\nblooper\nbloopers\nblooping\nbloops\nblossom\nblossomed\nblossoming\nblossoms\nblossomy\nblot\nblotch\nblotched\nblotches\nblotchier\nblotchiest\nblotchily\nblotching\nblotchy\nblotless\nblots\nblotted\nblotter\nblotters\nblottier\nblottiest\nblotting\nblotto\nblotty\nblouse\nbloused\nblouses\nblousier\nblousiest\nblousily\nblousing\nblouson\nblousons\nblousy\nbloviate\nbloviated\nbloviates\nbloviating\nbloviation\nbloviations\nblow\nblowback\nblowbacks\nblowball\nblowballs\nblowby\nblowbys\nblowdown\nblowdowns\nblowed\nblower\nblowers\nblowfish\nblowfishes\nblowflies\nblowfly\nblowgun\nblowguns\nblowhard\nblowhards\nblowhole\nblowholes\nblowier\nblowiest\nblowing\nblowjob\nblowjobs\nblown\nblowoff\nblowoffs\nblowout\nblowouts\nblowpipe\nblowpipes\nblows\nblowsed\nblowsier\nblowsiest\nblowsily\nblowsy\nblowtorch\nblowtorches\nblowtube\nblowtubes\nblowup\nblowups\nblowy\nblowzed\nblowzier\nblowziest\nblowzily\nblowzy\nblub\nblubbed\nblubber\nblubbered\nblubbering\nblubbers\nblubbery\nblubbing\nblubs\nblucher\nbluchers\nbludgeon\nbludgeoned\nbludgeoning\nbludgeons\nbludger\nbludgers\nblue\nblueball\nblueballs\nbluebeard\nbluebeards\nbluebell\nbluebells\nblueberries\nblueberry\nbluebill\nbluebills\nbluebird\nbluebirds\nblueblood\nbluebloods\nbluebonnet\nbluebonnets\nbluebook\nbluebooks\nbluebottle\nbluebottles\nbluecap\nbluecaps\nbluecoat\nbluecoats\nblued\nbluefin\nbluefins\nbluefish\nbluefishes\nbluegill\nbluegills\nbluegrass\nbluegrasses\nbluegum\nbluegums\nbluehead\nblueheads\nblueing\nblueings\nblueish\nbluejack\nbluejacket\nbluejackets\nbluejacks\nbluejay\nbluejays\nbluejeans\nblueline\nbluelines\nbluely\nblueness\nbluenesses\nbluenose\nbluenoses\nbluepoint\nbluepoints\nblueprint\nblueprinted\nblueprinting\nblueprints\nbluer\nblues\nblueshift\nblueshifted\nblueshifts\nbluesier\nbluesiest\nbluesman\nbluesmen\nbluest\nbluestem\nbluestems\nbluestocking\nbluestockings\nbluestone\nbluestones\nbluesy\nbluet\nbluetick\nblueticks\nbluetongue\nbluetongues\nbluets\nblueweed\nblueweeds\nbluewood\nbluewoods\nbluey\nblueys\nbluff\nbluffed\nbluffer\nbluffers\nbluffest\nbluffing\nbluffly\nbluffness\nbluffnesses\nbluffs\nbluing\nbluings\nbluish\nbluishness\nbluishnesses\nblume\nblumed\nblumes\nbluming\nblunder\nblunderbuss\nblunderbusses\nblundered\nblunderer\nblunderers\nblundering\nblunderingly\nblunders\nblunge\nblunged\nblunger\nblungers\nblunges\nblunging\nblunt\nblunted\nblunter\nbluntest\nblunting\nbluntly\nbluntness\nbluntnesses\nblunts\nblur\nblurb\nblurbed\nblurbing\nblurbs\nblurred\nblurrier\nblurriest\nblurrily\nblurriness\nblurrinesses\nblurring\nblurringly\nblurry\nblurs\nblurt\nblurted\nblurter\nblurters\nblurting\nblurts\nblush\nblushed\nblusher\nblushers\nblushes\nblushful\nblushing\nblushingly\nbluster\nblustered\nblusterer\nblusterers\nblustering\nblusteringly\nblusterous\nblusters\nblustery\nblype\nblypes\nbo\nboa\nboar\nboard\nboarded\nboarder\nboarders\nboarding\nboardinghouse\nboardinghouses\nboardings\nboardlike\nboardman\nboardmen\nboardroom\nboardrooms\nboards\nboardsailing\nboardsailings\nboardsailor\nboardsailors\nboardwalk\nboardwalks\nboarfish\nboarfishes\nboarish\nboars\nboart\nboarts\nboas\nboast\nboasted\nboaster\nboasters\nboastful\nboastfully\nboastfulness\nboastfulnesses\nboasting\nboasts\nboat\nboatable\nboatbill\nboatbills\nboatbuilder\nboatbuilders\nboatbuilding\nboatbuildings\nboated\nboatel\nboatels\nboater\nboaters\nboatful\nboatfuls\nboathook\nboathooks\nboathouse\nboathouses\nboating\nboatings\nboatlike\nboatload\nboatloads\nboatman\nboatmen\nboats\nboatsman\nboatsmen\nboatswain\nboatswains\nboatyard\nboatyards\nbob\nbobbed\nbobber\nbobberies\nbobbers\nbobbery\nbobbies\nbobbin\nbobbinet\nbobbinets\nbobbing\nbobbins\nbobble\nbobbled\nbobbles\nbobbling\nbobby\nbobcat\nbobcats\nbobeche\nbobeches\nbobolink\nbobolinks\nbobs\nbobsled\nbobsledded\nbobsledder\nbobsledders\nbobsledding\nbobsleddings\nbobsleds\nbobstay\nbobstays\nbobtail\nbobtailed\nbobtailing\nbobtails\nbobwhite\nbobwhites\nbocaccio\nbocaccios\nbocce\nbocces\nbocci\nboccia\nboccias\nboccie\nboccies\nboccis\nboche\nboches\nbock\nbocks\nbod\nbodacious\nbodaciously\nboddhisattva\nboddhisattvas\nbode\nboded\nbodega\nbodegas\nbodement\nbodements\nbodes\nbodhisattva\nbodhisattvas\nbodhran\nbodhrans\nbodice\nbodices\nbodied\nbodies\nbodiless\nbodily\nboding\nbodingly\nbodings\nbodkin\nbodkins\nbods\nbody\nbodybuilder\nbodybuilders\nbodybuilding\nbodybuildings\nbodycheck\nbodychecked\nbodychecking\nbodychecks\nbodyguard\nbodyguards\nbodying\nbodysuit\nbodysuits\nbodysurf\nbodysurfed\nbodysurfer\nbodysurfers\nbodysurfing\nbodysurfs\nbodywork\nbodyworks\nboehmite\nboehmites\nboff\nboffed\nboffin\nboffing\nboffins\nboffo\nboffola\nboffolas\nboffos\nboffs\nbog\nbogan\nbogans\nbogbean\nbogbeans\nbogey\nbogeyed\nbogeying\nbogeyman\nbogeymen\nbogeys\nbogged\nboggier\nboggiest\nbogging\nboggish\nboggle\nboggled\nboggler\nbogglers\nboggles\nboggling\nboggy\nbogie\nbogies\nbogle\nbogles\nbogs\nbogus\nbogwood\nbogwoods\nbogy\nbogyism\nbogyisms\nbogyman\nbogymen\nbohea\nboheas\nbohemia\nbohemian\nbohemianism\nbohemianisms\nbohemians\nbohemias\nbohrium\nbohriums\nbohunk\nbohunks\nboil\nboilable\nboiled\nboiler\nboilermaker\nboilermakers\nboilerplate\nboilerplates\nboilers\nboilersuit\nboilersuits\nboiling\nboiloff\nboiloffs\nboils\nboing\nboiserie\nboiseries\nboisterous\nboisterously\nboisterousness\nboisterousnesses\nboite\nboites\nbola\nbolar\nbolas\nbolases\nbold\nbolder\nboldest\nboldface\nboldfaced\nboldfaces\nboldfacing\nboldly\nboldness\nboldnesses\nbolds\nbole\nbolero\nboleros\nboles\nbolete\nboletes\nboleti\nboletus\nboletuses\nbolide\nbolides\nbolivar\nbolivares\nbolivars\nbolivia\nboliviano\nbolivianos\nbolivias\nboll\nbollard\nbollards\nbolled\nbolling\nbollix\nbollixed\nbollixes\nbollixing\nbollocks\nbollox\nbolloxed\nbolloxes\nbolloxing\nbolls\nbollworm\nbollworms\nbolo\nbologna\nbolognas\nbolometer\nbolometers\nbolometric\nbolometrically\nboloney\nboloneys\nbolos\nbolshevism\nbolshevisms\nbolshevize\nbolshevized\nbolshevizes\nbolshevizing\nbolshie\nbolshies\nbolshy\nbolson\nbolsons\nbolster\nbolstered\nbolsterer\nbolsterers\nbolstering\nbolsters\nbolt\nbolted\nbolter\nbolters\nbolthead\nboltheads\nbolthole\nboltholes\nbolting\nboltonia\nboltonias\nboltrope\nboltropes\nbolts\nbolus\nboluses\nbomb\nbombard\nbombarded\nbombardier\nbombardiers\nbombarding\nbombardment\nbombardments\nbombardon\nbombardons\nbombards\nbombast\nbombastic\nbombastically\nbombasts\nbombax\nbombazine\nbombazines\nbombe\nbombed\nbomber\nbombers\nbombes\nbombesin\nbombesins\nbombinate\nbombinated\nbombinates\nbombinating\nbombination\nbombinations\nbombing\nbombings\nbombload\nbombloads\nbombproof\nbombs\nbombshell\nbombshells\nbombsight\nbombsights\nbombycid\nbombycids\nbombyx\nbombyxes\nbonaci\nbonacis\nbonanza\nbonanzas\nbonbon\nbonbons\nbond\nbondable\nbondage\nbondages\nbonded\nbonder\nbonders\nbondholder\nbondholders\nbonding\nbondings\nbondmaid\nbondmaids\nbondman\nbondmen\nbonds\nbondsman\nbondsmen\nbondstone\nbondstones\nbonduc\nbonducs\nbondwoman\nbondwomen\nbone\nboned\nbonefish\nbonefishes\nbonefishing\nbonefishings\nbonehead\nboneheaded\nboneheadedness\nboneheadednesses\nboneheads\nboneless\nbonemeal\nbonemeals\nboner\nboners\nbones\nboneset\nbonesets\nbonesetter\nbonesetters\nboney\nboneyard\nboneyards\nbonfire\nbonfires\nbong\nbonged\nbonging\nbongo\nbongoes\nbongoist\nbongoists\nbongos\nbongs\nbonhomie\nbonhomies\nbonhomous\nbonier\nboniest\nboniface\nbonifaces\nboniness\nboninesses\nboning\nbonita\nbonitas\nbonito\nbonitoes\nbonitos\nbonk\nbonked\nbonkers\nbonking\nbonks\nbonne\nbonnes\nbonnet\nbonneted\nbonneting\nbonnets\nbonnie\nbonnier\nbonniest\nbonnily\nbonnock\nbonnocks\nbonny\nbonnyclabber\nbonnyclabbers\nbonsai\nbonsais\nbonspell\nbonspells\nbonspiel\nbonspiels\nbontebok\nbonteboks\nbonus\nbonuses\nbony\nbonze\nbonzer\nbonzes\nboo\nboob\nboobed\nboobie\nboobies\nboobing\nboobish\nbooboisie\nbooboisies\nbooboo\nbooboos\nboobs\nbooby\nboodle\nboodled\nboodler\nboodlers\nboodles\nboodling\nbooed\nbooger\nboogerman\nboogermen\nboogers\nboogey\nboogeyed\nboogeying\nboogeyman\nboogeymen\nboogeys\nboogie\nboogied\nboogieing\nboogies\nboogy\nboogying\nboogyman\nboogymen\nboohoo\nboohooed\nboohooing\nboohoos\nbooing\nbook\nbookable\nbookbinder\nbookbinderies\nbookbinders\nbookbindery\nbookbinding\nbookbindings\nbookcase\nbookcases\nbooked\nbookend\nbookends\nbooker\nbookers\nbookful\nbookfuls\nbookie\nbookies\nbooking\nbookings\nbookish\nbookishly\nbookishness\nbookishnesses\nbookkeeper\nbookkeepers\nbookkeeping\nbookkeepings\nbooklet\nbooklets\nbooklice\nbooklore\nbooklores\nbooklouse\nbookmaker\nbookmakers\nbookmaking\nbookmakings\nbookman\nbookmark\nbookmarked\nbookmarker\nbookmarkers\nbookmarking\nbookmarks\nbookmen\nbookmobile\nbookmobiles\nbookplate\nbookplates\nbookrack\nbookracks\nbookrest\nbookrests\nbooks\nbookseller\nbooksellers\nbookselling\nbooksellings\nbookshelf\nbookshelves\nbookshop\nbookshops\nbookstall\nbookstalls\nbookstore\nbookstores\nbookworm\nbookworms\nboom\nboombox\nboomboxes\nboomed\nboomer\nboomerang\nboomeranged\nboomeranging\nboomerangs\nboomers\nboomier\nboomiest\nbooming\nboomkin\nboomkins\nboomlet\nboomlets\nbooms\nboomtown\nboomtowns\nboomy\nboon\nboondock\nboondocks\nboondoggle\nboondoggled\nboondoggler\nboondogglers\nboondoggles\nboondoggling\nboonies\nboons\nboor\nboorish\nboorishly\nboorishness\nboorishnesses\nboors\nboos\nboost\nboosted\nbooster\nboosterism\nboosterisms\nboosters\nboosting\nboosts\nboot\nbootable\nbootblack\nbootblacks\nbooted\nbootee\nbootees\nbooteries\nbootery\nbooth\nbooths\nbootie\nbooties\nbooting\nbootjack\nbootjacks\nbootlace\nbootlaces\nbootleg\nbootlegged\nbootlegger\nbootleggers\nbootlegging\nbootlegs\nbootless\nbootlessly\nbootlessness\nbootlessnesses\nbootlick\nbootlicked\nbootlicker\nbootlickers\nbootlicking\nbootlicks\nboots\nbootstrap\nbootstrapped\nbootstrapping\nbootstraps\nbooty\nbooze\nboozed\nboozer\nboozers\nboozes\nboozier\nbooziest\nboozily\nboozing\nboozy\nbop\nbopeep\nbopeeps\nbopped\nbopper\nboppers\nbopping\nbops\nbora\nboraces\nboracic\nboracite\nboracites\nborage\nborages\nboral\nborals\nborane\nboranes\nboras\nborate\nborated\nborates\nborating\nborax\nboraxes\nborborygmi\nborborygmus\nbordeaux\nbordel\nbordello\nbordellos\nbordels\nborder\nbordereau\nbordereaux\nbordered\nborderer\nborderers\nbordering\nborderland\nborderlands\nborderline\nborderlines\nborders\nbordure\nbordures\nbore\nboreal\nborecole\nborecoles\nbored\nboredom\nboredoms\nboreen\nboreens\nborehole\nboreholes\nborer\nborers\nbores\nborescope\nborescopes\nboresome\nboric\nboride\nborides\nboring\nboringly\nboringness\nboringnesses\nborings\nborn\nborne\nborneol\nborneols\nbornite\nbornites\nborohydride\nborohydrides\nboron\nboronic\nborons\nborosilicate\nborosilicates\nborough\nboroughs\nborrow\nborrowed\nborrower\nborrowers\nborrowing\nborrowings\nborrows\nborsch\nborsches\nborscht\nborschts\nborsht\nborshts\nborstal\nborstals\nbort\nborts\nborty\nbortz\nbortzes\nborzoi\nborzois\nbos\nboscage\nboscages\nboschbok\nboschboks\nbosh\nboshbok\nboshboks\nboshes\nboshvark\nboshvarks\nbosk\nboskage\nboskages\nbosker\nbosket\nboskets\nboskier\nboskiest\nbosks\nbosky\nbosom\nbosomed\nbosoming\nbosoms\nbosomy\nboson\nbosons\nbosque\nbosques\nbosquet\nbosquets\nboss\nbossdom\nbossdoms\nbossed\nbosses\nbossier\nbossies\nbossiest\nbossily\nbossiness\nbossinesses\nbossing\nbossism\nbossisms\nbossy\nboston\nbostons\nbosun\nbosuns\nbot\nbota\nbotanic\nbotanica\nbotanical\nbotanically\nbotanicals\nbotanicas\nbotanies\nbotanise\nbotanised\nbotanises\nbotanising\nbotanist\nbotanists\nbotanize\nbotanized\nbotanizes\nbotanizing\nbotany\nbotas\nbotch\nbotched\nbotcher\nbotcheries\nbotchers\nbotchery\nbotches\nbotchier\nbotchiest\nbotchily\nbotching\nbotchy\nbotel\nbotels\nbotflies\nbotfly\nboth\nbother\nbotheration\nbotherations\nbothered\nbothering\nbothers\nbothersome\nbothies\nbothria\nbothrium\nbothriums\nbothy\nbotonee\nbotonnee\nbotryoid\nbotryoidal\nbotryose\nbotrytis\nbotrytises\nbots\nbott\nbottle\nbottlebrush\nbottlebrushes\nbottled\nbottleful\nbottlefuls\nbottleneck\nbottlenecked\nbottlenecking\nbottlenecks\nbottler\nbottlers\nbottles\nbottling\nbottlings\nbottom\nbottomed\nbottomer\nbottomers\nbottoming\nbottomland\nbottomlands\nbottomless\nbottomlessly\nbottomlessness\nbottomlessnesses\nbottommost\nbottomries\nbottomry\nbottoms\nbotts\nbotulin\nbotulinal\nbotulins\nbotulinum\nbotulinums\nbotulinus\nbotulinuses\nbotulism\nbotulisms\nboubou\nboubous\nbouchee\nbouchees\nboucle\nboucles\nboudoir\nboudoirs\nbouffant\nbouffants\nbouffe\nbouffes\nbougainvillaea\nbougainvillaeas\nbougainvillea\nbougainvilleas\nbough\nboughed\nboughpot\nboughpots\nboughs\nbought\nboughten\nbougie\nbougies\nbouillabaisse\nbouillabaisses\nbouillon\nbouillons\nboulder\nbouldered\nboulders\nbouldery\nboule\nboules\nboulevard\nboulevardier\nboulevardiers\nboulevards\nbouleversement\nbouleversements\nboulle\nboulles\nbounce\nbounced\nbouncer\nbouncers\nbounces\nbouncier\nbounciest\nbouncily\nbouncing\nbouncingly\nbouncy\nbound\nboundaries\nboundary\nbounded\nboundedness\nboundednesses\nbounden\nbounder\nbounderish\nbounders\nbounding\nboundless\nboundlessly\nboundlessness\nboundlessnesses\nbounds\nbounteous\nbounteously\nbounteousness\nbounteousnesses\nbountied\nbounties\nbountiful\nbountifully\nbountifulness\nbountifulnesses\nbounty\nbouquet\nbouquets\nbourbon\nbourbonism\nbourbonisms\nbourbons\nbourdon\nbourdons\nbourg\nbourgeois\nbourgeoise\nbourgeoises\nbourgeoisie\nbourgeoisies\nbourgeoisification\nbourgeoisifications\nbourgeoisified\nbourgeoisifies\nbourgeoisify\nbourgeoisifying\nbourgeon\nbourgeoned\nbourgeoning\nbourgeons\nbourgs\nbourguignon\nbourguignonne\nbourn\nbourne\nbournes\nbourns\nbourree\nbourrees\nbourride\nbourrides\nbourse\nbourses\nbourtree\nbourtrees\nbouse\nboused\nbouses\nbousing\nbousouki\nbousoukia\nbousoukis\nboustrophedon\nboustrophedonic\nboustrophedons\nbousy\nbout\nboutique\nboutiques\nbouton\nboutonniere\nboutonnieres\nboutons\nbouts\nbouvier\nbouviers\nbouzouki\nbouzoukia\nbouzoukis\nbovid\nbovids\nbovine\nbovinely\nbovines\nbovinities\nbovinity\nbow\nbowdlerise\nbowdlerised\nbowdlerises\nbowdlerising\nbowdlerization\nbowdlerizations\nbowdlerize\nbowdlerized\nbowdlerizer\nbowdlerizers\nbowdlerizes\nbowdlerizing\nbowed\nbowel\nboweled\nboweling\nbowelled\nbowelless\nbowelling\nbowels\nbower\nbowerbird\nbowerbirds\nbowered\nboweries\nbowering\nbowers\nbowery\nbowfin\nbowfins\nbowfront\nbowhead\nbowheads\nbowing\nbowingly\nbowings\nbowknot\nbowknots\nbowl\nbowlder\nbowlders\nbowled\nbowleg\nbowlegged\nbowlegs\nbowler\nbowlers\nbowless\nbowlful\nbowlfuls\nbowlike\nbowline\nbowlines\nbowling\nbowlings\nbowllike\nbowls\nbowman\nbowmen\nbowpot\nbowpots\nbows\nbowse\nbowsed\nbowses\nbowshot\nbowshots\nbowsing\nbowsprit\nbowsprits\nbowstring\nbowstrings\nbowwow\nbowwowed\nbowwowing\nbowwows\nbowyer\nbowyers\nbox\nboxberries\nboxberry\nboxboard\nboxboards\nboxcar\nboxcars\nboxed\nboxer\nboxers\nboxes\nboxfish\nboxfishes\nboxful\nboxfuls\nboxhaul\nboxhauled\nboxhauling\nboxhauls\nboxier\nboxiest\nboxiness\nboxinesses\nboxing\nboxings\nboxlike\nboxthorn\nboxthorns\nboxwood\nboxwoods\nboxy\nboy\nboyar\nboyard\nboyards\nboyarism\nboyarisms\nboyars\nboychick\nboychicks\nboychik\nboychiks\nboycott\nboycotted\nboycotter\nboycotters\nboycotting\nboycotts\nboyfriend\nboyfriends\nboyhood\nboyhoods\nboyish\nboyishly\nboyishness\nboyishnesses\nboyla\nboylas\nboyo\nboyos\nboys\nboysenberries\nboysenberry\nbozo\nbozos\nbra\nbrabble\nbrabbled\nbrabbler\nbrabblers\nbrabbles\nbrabbling\nbrace\nbraced\nbracelet\nbracelets\nbracer\nbracero\nbraceros\nbracers\nbraces\nbrach\nbraches\nbrachet\nbrachets\nbrachia\nbrachial\nbrachials\nbrachiate\nbrachiated\nbrachiates\nbrachiating\nbrachiation\nbrachiations\nbrachiator\nbrachiators\nbrachiopod\nbrachiopods\nbrachium\nbrachs\nbrachycephalic\nbrachycephalies\nbrachycephaly\nbrachypterous\nbracing\nbracingly\nbracings\nbraciola\nbraciolas\nbraciole\nbracioles\nbracken\nbrackens\nbracket\nbracketed\nbracketing\nbrackets\nbrackish\nbrackishness\nbrackishnesses\nbraconid\nbraconids\nbract\nbracteal\nbracteate\nbracted\nbracteole\nbracteoles\nbractlet\nbractlets\nbracts\nbrad\nbradawl\nbradawls\nbradded\nbradding\nbradoon\nbradoons\nbrads\nbradycardia\nbradycardias\nbradykinin\nbradykinins\nbrae\nbraes\nbrag\nbraggadocio\nbraggadocios\nbraggart\nbraggarts\nbragged\nbragger\nbraggers\nbraggest\nbraggier\nbraggiest\nbragging\nbraggy\nbrags\nbrahma\nbrahmas\nbraid\nbraided\nbraider\nbraiders\nbraiding\nbraidings\nbraids\nbrail\nbrailed\nbrailing\nbraille\nbrailled\nbrailles\nbraillewriter\nbraillewriters\nbrailling\nbraillist\nbraillists\nbrails\nbrain\nbraincase\nbraincases\nbrainchild\nbrainchildren\nbrained\nbrainiac\nbrainiacs\nbrainier\nbrainiest\nbrainily\nbraininess\nbraininesses\nbraining\nbrainish\nbrainless\nbrainlessly\nbrainlessness\nbrainlessnesses\nbrainpan\nbrainpans\nbrainpower\nbrainpowers\nbrains\nbrainsick\nbrainsickly\nbrainstorm\nbrainstormed\nbrainstormer\nbrainstormers\nbrainstorming\nbrainstormings\nbrainstorms\nbrainteaser\nbrainteasers\nbrainwash\nbrainwashed\nbrainwasher\nbrainwashers\nbrainwashes\nbrainwashing\nbrainwashings\nbrainy\nbraise\nbraised\nbraises\nbraising\nbraize\nbraizes\nbrake\nbrakeage\nbrakeages\nbraked\nbrakeless\nbrakeman\nbrakemen\nbrakes\nbrakier\nbrakiest\nbraking\nbraky\nbraless\nbramble\nbrambled\nbrambles\nbramblier\nbrambliest\nbrambling\nbrambly\nbran\nbranch\nbranched\nbranches\nbranchia\nbranchiae\nbranchial\nbranchier\nbranchiest\nbranching\nbranchiopod\nbranchiopods\nbranchless\nbranchlet\nbranchlets\nbranchline\nbranchlines\nbranchy\nbrand\nbranded\nbrander\nbranders\nbrandied\nbrandies\nbranding\nbrandish\nbrandished\nbrandishes\nbrandishing\nbrands\nbrandy\nbrandying\nbrank\nbranks\nbranned\nbranner\nbranners\nbrannier\nbranniest\nbrannigan\nbrannigans\nbranning\nbranny\nbrans\nbrant\nbrantail\nbrantails\nbrants\nbras\nbrash\nbrasher\nbrashes\nbrashest\nbrashier\nbrashiest\nbrashly\nbrashness\nbrashnesses\nbrashy\nbrasier\nbrasiers\nbrasil\nbrasilin\nbrasilins\nbrasils\nbrass\nbrassage\nbrassages\nbrassard\nbrassards\nbrassart\nbrassarts\nbrassbound\nbrassed\nbrasserie\nbrasseries\nbrasses\nbrassica\nbrassicas\nbrassie\nbrassier\nbrassiere\nbrassieres\nbrassies\nbrassiest\nbrassily\nbrassiness\nbrassinesses\nbrassing\nbrassish\nbrassy\nbrat\nbrats\nbrattice\nbratticed\nbrattices\nbratticing\nbrattier\nbrattiest\nbrattiness\nbrattinesses\nbrattish\nbrattle\nbrattled\nbrattles\nbrattling\nbratty\nbratwurst\nbratwursts\nbraunite\nbraunites\nbraunschweiger\nbraunschweigers\nbrava\nbravado\nbravadoes\nbravados\nbravas\nbrave\nbraved\nbravely\nbraver\nbraveries\nbravers\nbravery\nbraves\nbravest\nbravi\nbraving\nbravo\nbravoed\nbravoes\nbravoing\nbravos\nbravura\nbravuras\nbravure\nbraw\nbrawer\nbrawest\nbrawl\nbrawled\nbrawler\nbrawlers\nbrawlie\nbrawlier\nbrawliest\nbrawling\nbrawls\nbrawly\nbrawn\nbrawnier\nbrawniest\nbrawnily\nbrawniness\nbrawninesses\nbrawns\nbrawny\nbraws\nbraxies\nbraxy\nbray\nbrayed\nbrayer\nbrayers\nbraying\nbrays\nbraza\nbrazas\nbraze\nbrazed\nbrazen\nbrazened\nbrazening\nbrazenly\nbrazenness\nbrazennesses\nbrazens\nbrazer\nbrazers\nbrazes\nbrazier\nbraziers\nbrazil\nbrazilin\nbrazilins\nbrazils\nbrazilwood\nbrazilwoods\nbrazing\nbreach\nbreached\nbreacher\nbreachers\nbreaches\nbreaching\nbread\nbreadbasket\nbreadbaskets\nbreadboard\nbreadboarded\nbreadboarding\nbreadboards\nbreadbox\nbreadboxes\nbreadcrumb\nbreadcrumbs\nbreaded\nbreadfruit\nbreadfruits\nbreading\nbreadline\nbreadlines\nbreadnut\nbreadnuts\nbreads\nbreadstick\nbreadsticks\nbreadstuff\nbreadstuffs\nbreadth\nbreadths\nbreadthwise\nbreadwinner\nbreadwinners\nbreadwinning\nbreadwinnings\nbready\nbreak\nbreakable\nbreakables\nbreakage\nbreakages\nbreakaway\nbreakaways\nbreakdown\nbreakdowns\nbreaker\nbreakers\nbreakeven\nbreakevens\nbreakfast\nbreakfasted\nbreakfaster\nbreakfasters\nbreakfasting\nbreakfasts\nbreakfront\nbreakfronts\nbreaking\nbreakings\nbreakneck\nbreakout\nbreakouts\nbreaks\nbreaksaway\nbreakthrough\nbreakthroughs\nbreakup\nbreakups\nbreakwater\nbreakwaters\nbream\nbreamed\nbreaming\nbreams\nbreast\nbreastbone\nbreastbones\nbreasted\nbreasting\nbreastplate\nbreastplates\nbreasts\nbreaststroke\nbreaststroker\nbreaststrokers\nbreaststrokes\nbreastwork\nbreastworks\nbreath\nbreathabilities\nbreathability\nbreathable\nbreathe\nbreathed\nbreather\nbreathers\nbreathes\nbreathier\nbreathiest\nbreathily\nbreathiness\nbreathinesses\nbreathing\nbreathings\nbreathless\nbreathlessly\nbreathlessness\nbreathlessnesses\nbreaths\nbreathtaking\nbreathtakingly\nbreathy\nbreccia\nbreccial\nbreccias\nbrecciate\nbrecciated\nbrecciates\nbrecciating\nbrecciation\nbrecciations\nbrecham\nbrechams\nbrechan\nbrechans\nbred\nbrede\nbredes\nbree\nbreech\nbreechblock\nbreechblocks\nbreechcloth\nbreechcloths\nbreechclout\nbreechclouts\nbreeched\nbreeches\nbreeching\nbreechings\nbreechloader\nbreechloaders\nbreed\nbreeder\nbreeders\nbreeding\nbreedings\nbreeds\nbreeks\nbrees\nbreeze\nbreezed\nbreezeless\nbreezes\nbreezeway\nbreezeways\nbreezier\nbreeziest\nbreezily\nbreeziness\nbreezinesses\nbreezing\nbreezy\nbregma\nbregmata\nbregmate\nbremsstrahlung\nbremsstrahlungs\nbren\nbrens\nbrent\nbrents\nbrethren\nbreve\nbreves\nbrevet\nbrevetcies\nbrevetcy\nbreveted\nbreveting\nbrevets\nbrevetted\nbrevetting\nbreviaries\nbreviary\nbrevier\nbreviers\nbrevities\nbrevity\nbrew\nbrewage\nbrewages\nbrewed\nbrewer\nbreweries\nbrewers\nbrewery\nbrewing\nbrewings\nbrewis\nbrewises\nbrewpub\nbrewpubs\nbrews\nbriar\nbriard\nbriards\nbriars\nbriary\nbribable\nbribe\nbribed\nbribee\nbribees\nbriber\nbriberies\nbribers\nbribery\nbribes\nbribing\nbrick\nbrickbat\nbrickbats\nbricked\nbrickfield\nbrickfields\nbrickier\nbrickiest\nbricking\nbricklayer\nbricklayers\nbricklaying\nbricklayings\nbrickle\nbrickles\nbricks\nbrickwork\nbrickworks\nbricky\nbrickyard\nbrickyards\nbricolage\nbricolages\nbricole\nbricoles\nbridal\nbridally\nbridals\nbride\nbridegroom\nbridegrooms\nbrides\nbridesmaid\nbridesmaids\nbridewell\nbridewells\nbridge\nbridgeable\nbridged\nbridgehead\nbridgeheads\nbridgeless\nbridges\nbridgework\nbridgeworks\nbridging\nbridgings\nbridle\nbridled\nbridler\nbridlers\nbridles\nbridling\nbridoon\nbridoons\nbrie\nbrief\nbriefcase\nbriefcases\nbriefed\nbriefer\nbriefers\nbriefest\nbriefing\nbriefings\nbriefless\nbriefly\nbriefness\nbriefnesses\nbriefs\nbrier\nbriers\nbriery\nbries\nbrig\nbrigade\nbrigaded\nbrigades\nbrigadier\nbrigadiers\nbrigading\nbrigand\nbrigandage\nbrigandages\nbrigandine\nbrigandines\nbrigands\nbrigantine\nbrigantines\nbright\nbrighten\nbrightened\nbrightener\nbrighteners\nbrightening\nbrightens\nbrighter\nbrightest\nbrightly\nbrightness\nbrightnesses\nbrights\nbrightwork\nbrightworks\nbrigs\nbrill\nbrilliance\nbrilliances\nbrilliancies\nbrilliancy\nbrilliant\nbrilliantine\nbrilliantines\nbrilliantly\nbrilliants\nbrills\nbrim\nbrimful\nbrimfull\nbrimless\nbrimmed\nbrimmer\nbrimmers\nbrimming\nbrims\nbrimstone\nbrimstones\nbrin\nbrinded\nbrindle\nbrindled\nbrindles\nbrine\nbrined\nbriner\nbriners\nbrines\nbring\nbringdown\nbringdowns\nbringer\nbringers\nbringing\nbrings\nbrinier\nbrinies\nbriniest\nbrininess\nbrininesses\nbrining\nbrinish\nbrink\nbrinkmanship\nbrinkmanships\nbrinks\nbrinksmanship\nbrinksmanships\nbrins\nbriny\nbrio\nbrioche\nbrioches\nbriolette\nbriolettes\nbrionies\nbriony\nbrios\nbriquet\nbriquets\nbriquette\nbriquetted\nbriquettes\nbriquetting\nbris\nbrisance\nbrisances\nbrisant\nbrisk\nbrisked\nbrisker\nbriskest\nbrisket\nbriskets\nbrisking\nbriskly\nbriskness\nbrisknesses\nbrisks\nbrisling\nbrislings\nbrisses\nbristle\nbristled\nbristlelike\nbristles\nbristletail\nbristletails\nbristlier\nbristliest\nbristling\nbristly\nbristol\nbristols\nbrit\nbritches\nbrits\nbritska\nbritskas\nbritt\nbrittle\nbrittled\nbrittlely\nbrittleness\nbrittlenesses\nbrittler\nbrittles\nbrittlest\nbrittling\nbrittly\nbritts\nbritzka\nbritzkas\nbritzska\nbritzskas\nbro\nbroach\nbroached\nbroacher\nbroachers\nbroaches\nbroaching\nbroad\nbroadax\nbroadaxe\nbroadaxes\nbroadband\nbroadcast\nbroadcasted\nbroadcaster\nbroadcasters\nbroadcasting\nbroadcasts\nbroadcloth\nbroadcloths\nbroaden\nbroadened\nbroadening\nbroadens\nbroader\nbroadest\nbroadish\nbroadleaf\nbroadloom\nbroadlooms\nbroadly\nbroadness\nbroadnesses\nbroads\nbroadscale\nbroadsheet\nbroadsheets\nbroadside\nbroadsided\nbroadsides\nbroadsiding\nbroadsword\nbroadswords\nbroadtail\nbroadtails\nbrocade\nbrocaded\nbrocades\nbrocading\nbrocatel\nbrocatelle\nbrocatelles\nbrocatels\nbroccoli\nbroccolis\nbroche\nbrochette\nbrochettes\nbrochure\nbrochures\nbrock\nbrockage\nbrockages\nbrocket\nbrockets\nbrocks\nbrocoli\nbrocolis\nbrogan\nbrogans\nbrogue\nbrogueries\nbroguery\nbrogues\nbroguish\nbroider\nbroidered\nbroideries\nbroidering\nbroiders\nbroidery\nbroil\nbroiled\nbroiler\nbroilers\nbroiling\nbroils\nbrokage\nbrokages\nbroke\nbroken\nbrokenhearted\nbrokenly\nbrokenness\nbrokennesses\nbroker\nbrokerage\nbrokerages\nbrokered\nbrokering\nbrokerings\nbrokers\nbroking\nbrokings\nbrollies\nbrolly\nbromal\nbromals\nbromate\nbromated\nbromates\nbromating\nbrome\nbromegrass\nbromegrasses\nbromelain\nbromelains\nbromeliad\nbromeliads\nbromelin\nbromelins\nbromes\nbromic\nbromid\nbromide\nbromides\nbromidic\nbromids\nbromin\nbrominate\nbrominated\nbrominates\nbrominating\nbromination\nbrominations\nbromine\nbromines\nbromins\nbromism\nbromisms\nbromize\nbromized\nbromizes\nbromizing\nbromo\nbromocriptine\nbromocriptines\nbromos\nbromouracil\nbromouracils\nbronc\nbronchi\nbronchia\nbronchial\nbronchially\nbronchiectases\nbronchiectasis\nbronchiolar\nbronchiole\nbronchioles\nbronchitic\nbronchitis\nbronchitises\nbronchium\nbroncho\nbronchodilator\nbronchodilators\nbronchogenic\nbronchopneumonia\nbronchopneumonias\nbronchos\nbronchoscope\nbronchoscopes\nbronchoscopic\nbronchoscopies\nbronchoscopist\nbronchoscopists\nbronchoscopy\nbronchospasm\nbronchospasms\nbronchospastic\nbronchus\nbronco\nbroncobuster\nbroncobusters\nbroncos\nbroncs\nbrontosaur\nbrontosaurs\nbrontosaurus\nbrontosauruses\nbronze\nbronzed\nbronzer\nbronzers\nbronzes\nbronzier\nbronziest\nbronzing\nbronzings\nbronzy\nbroo\nbrooch\nbrooches\nbrood\nbrooded\nbrooder\nbrooders\nbroodier\nbroodiest\nbroodily\nbroodiness\nbroodinesses\nbrooding\nbroodingly\nbroodmare\nbroodmares\nbroods\nbroody\nbrook\nbrooked\nbrookie\nbrookies\nbrooking\nbrookite\nbrookites\nbrooklet\nbrooklets\nbrooks\nbroom\nbroomball\nbroomballer\nbroomballers\nbroomballs\nbroomcorn\nbroomcorns\nbroomed\nbroomier\nbroomiest\nbrooming\nbroomrape\nbroomrapes\nbrooms\nbroomstick\nbroomsticks\nbroomy\nbroos\nbros\nbrose\nbroses\nbrosy\nbroth\nbrothel\nbrothels\nbrother\nbrothered\nbrotherhood\nbrotherhoods\nbrothering\nbrotherliness\nbrotherlinesses\nbrotherly\nbrothers\nbroths\nbrothy\nbrougham\nbroughams\nbrought\nbrouhaha\nbrouhahas\nbrow\nbrowband\nbrowbands\nbrowbeat\nbrowbeaten\nbrowbeating\nbrowbeats\nbrowed\nbrowless\nbrown\nbrowned\nbrowner\nbrownest\nbrownfield\nbrownfields\nbrownie\nbrownier\nbrownies\nbrowniest\nbrowning\nbrownish\nbrownnose\nbrownnosed\nbrownnoser\nbrownnosers\nbrownnoses\nbrownnosing\nbrownout\nbrownouts\nbrowns\nbrownshirt\nbrownshirts\nbrownstone\nbrownstones\nbrowny\nbrowridge\nbrowridges\nbrows\nbrowse\nbrowsed\nbrowser\nbrowsers\nbrowses\nbrowsing\nbrr\nbrrr\nbrucella\nbrucellae\nbrucellas\nbrucelloses\nbrucellosis\nbrucin\nbrucine\nbrucines\nbrucins\nbrugh\nbrughs\nbruin\nbruins\nbruise\nbruised\nbruiser\nbruisers\nbruises\nbruising\nbruit\nbruited\nbruiter\nbruiters\nbruiting\nbruits\nbrulot\nbrulots\nbrulyie\nbrulyies\nbrulzie\nbrulzies\nbrumal\nbrumbies\nbrumby\nbrume\nbrumes\nbrummagem\nbrummagems\nbrumous\nbrunch\nbrunched\nbrunches\nbrunching\nbrunet\nbrunets\nbrunette\nbrunettes\nbrunizem\nbrunizems\nbrunt\nbrunts\nbrush\nbrushabilities\nbrushability\nbrushback\nbrushbacks\nbrushed\nbrusher\nbrushers\nbrushes\nbrushfire\nbrushfires\nbrushier\nbrushiest\nbrushing\nbrushland\nbrushlands\nbrushoff\nbrushoffs\nbrushup\nbrushups\nbrushwood\nbrushwoods\nbrushwork\nbrushworks\nbrushy\nbrusk\nbrusker\nbruskest\nbrusque\nbrusquely\nbrusqueness\nbrusquenesses\nbrusquer\nbrusquerie\nbrusqueries\nbrusquest\nbrut\nbrutal\nbrutalise\nbrutalised\nbrutalises\nbrutalising\nbrutalities\nbrutality\nbrutalization\nbrutalizations\nbrutalize\nbrutalized\nbrutalizes\nbrutalizing\nbrutally\nbrute\nbruted\nbrutely\nbrutes\nbrutified\nbrutifies\nbrutify\nbrutifying\nbruting\nbrutish\nbrutishly\nbrutishness\nbrutishnesses\nbrutism\nbrutisms\nbruxism\nbruxisms\nbryological\nbryologies\nbryologist\nbryologists\nbryology\nbryonies\nbryony\nbryophyllum\nbryophyllums\nbryophyte\nbryophytes\nbryophytic\nbryozoan\nbryozoans\nbub\nbubal\nbubale\nbubales\nbubaline\nbubalis\nbubalises\nbubals\nbubbies\nbubble\nbubbled\nbubblegum\nbubblegums\nbubblehead\nbubbleheaded\nbubbleheads\nbubbler\nbubblers\nbubbles\nbubblier\nbubblies\nbubbliest\nbubbling\nbubbly\nbubby\nbubinga\nbubingas\nbubo\nbuboed\nbuboes\nbubonic\nbubs\nbuccal\nbuccally\nbuccaneer\nbuccaneered\nbuccaneering\nbuccaneerish\nbuccaneers\nbuccinator\nbuccinators\nbuck\nbuckaroo\nbuckaroos\nbuckayro\nbuckayros\nbuckbean\nbuckbeans\nbuckboard\nbuckboards\nbucked\nbuckeen\nbuckeens\nbucker\nbuckeroo\nbuckeroos\nbuckers\nbucket\nbucketed\nbucketful\nbucketfuls\nbucketing\nbuckets\nbucketsful\nbuckeye\nbuckeyes\nbucking\nbuckish\nbuckle\nbuckled\nbuckler\nbucklered\nbucklering\nbucklers\nbuckles\nbuckling\nbuckminsterfullerene\nbuckminsterfullerenes\nbucko\nbuckoes\nbuckos\nbuckra\nbuckram\nbuckramed\nbuckraming\nbuckrams\nbuckras\nbucks\nbucksaw\nbucksaws\nbuckshee\nbuckshees\nbuckshot\nbuckshots\nbuckskin\nbuckskinned\nbuckskins\nbucktail\nbucktails\nbuckteeth\nbuckthorn\nbuckthorns\nbucktooth\nbucktoothed\nbuckwheat\nbuckwheats\nbuckyball\nbuckyballs\nbucolic\nbucolically\nbucolics\nbud\nbudded\nbudder\nbudders\nbuddied\nbuddies\nbudding\nbuddings\nbuddle\nbuddleia\nbuddleias\nbuddles\nbuddy\nbuddying\nbudge\nbudged\nbudger\nbudgerigar\nbudgerigars\nbudgers\nbudges\nbudget\nbudgetary\nbudgeted\nbudgeteer\nbudgeteers\nbudgeter\nbudgeters\nbudgeting\nbudgets\nbudgie\nbudgies\nbudging\nbudless\nbudlike\nbuds\nbudworm\nbudworms\nbuff\nbuffable\nbuffalo\nbuffaloberries\nbuffaloberry\nbuffaloed\nbuffaloes\nbuffalofish\nbuffalofishes\nbuffaloing\nbuffalos\nbuffed\nbuffer\nbuffered\nbuffering\nbuffers\nbuffet\nbuffeted\nbuffeter\nbuffeters\nbuffeting\nbuffets\nbuffi\nbuffier\nbuffiest\nbuffing\nbufflehead\nbuffleheads\nbuffo\nbuffoon\nbuffooneries\nbuffoonery\nbuffoonish\nbuffoons\nbuffos\nbuffs\nbuffy\nbug\nbugaboo\nbugaboos\nbugbane\nbugbanes\nbugbear\nbugbears\nbugeye\nbugeyes\nbugged\nbugger\nbuggered\nbuggeries\nbuggering\nbuggers\nbuggery\nbuggier\nbuggies\nbuggiest\nbugging\nbuggy\nbughouse\nbughouses\nbugle\nbugled\nbugler\nbuglers\nbugles\nbugleweed\nbugleweeds\nbugling\nbugloss\nbuglosses\nbugs\nbugseed\nbugseeds\nbugsha\nbugshas\nbuhl\nbuhls\nbuhlwork\nbuhlworks\nbuhr\nbuhrs\nbuhrstone\nbuhrstones\nbuild\nbuildable\nbuilded\nbuilder\nbuilders\nbuilding\nbuildings\nbuilds\nbuildup\nbuildups\nbuilt\nbuirdly\nbulb\nbulbar\nbulbed\nbulbel\nbulbels\nbulbil\nbulbils\nbulblet\nbulblets\nbulbous\nbulbously\nbulbs\nbulbul\nbulbuls\nbulge\nbulged\nbulger\nbulgers\nbulges\nbulgier\nbulgiest\nbulging\nbulgur\nbulgurs\nbulgy\nbulimia\nbulimiac\nbulimias\nbulimic\nbulimics\nbulk\nbulkage\nbulkages\nbulked\nbulkhead\nbulkheads\nbulkier\nbulkiest\nbulkily\nbulkiness\nbulkinesses\nbulking\nbulks\nbulky\nbull\nbulla\nbullace\nbullaces\nbullae\nbullate\nbullbaiting\nbullbaitings\nbullbat\nbullbats\nbulldog\nbulldogged\nbulldogger\nbulldoggers\nbulldogging\nbulldoggings\nbulldogs\nbulldoze\nbulldozed\nbulldozer\nbulldozers\nbulldozes\nbulldozing\nbulled\nbullet\nbulleted\nbulletin\nbulletined\nbulleting\nbulletining\nbulletins\nbulletproof\nbullets\nbullfight\nbullfighter\nbullfighters\nbullfighting\nbullfightings\nbullfights\nbullfinch\nbullfinches\nbullfrog\nbullfrogs\nbullhead\nbullheaded\nbullheadedly\nbullheadedness\nbullheadednesses\nbullheads\nbullhorn\nbullhorns\nbullied\nbullier\nbullies\nbulliest\nbulling\nbullion\nbullions\nbullish\nbullishly\nbullishness\nbullishnesses\nbullmastiff\nbullmastiffs\nbullneck\nbullnecked\nbullnecks\nbullnose\nbullnoses\nbullock\nbullocks\nbullocky\nbullous\nbullpen\nbullpens\nbullpout\nbullpouts\nbullring\nbullrings\nbullrush\nbullrushes\nbulls\nbullshit\nbullshits\nbullshitted\nbullshitting\nbullshot\nbullshots\nbullterrier\nbullterriers\nbullweed\nbullweeds\nbullwhip\nbullwhipped\nbullwhipping\nbullwhips\nbully\nbullyboy\nbullyboys\nbullying\nbullyrag\nbullyragged\nbullyragging\nbullyrags\nbulrush\nbulrushes\nbulwark\nbulwarked\nbulwarking\nbulwarks\nbum\nbumbershoot\nbumbershoots\nbumble\nbumblebee\nbumblebees\nbumbled\nbumbler\nbumblers\nbumbles\nbumbling\nbumblingly\nbumblings\nbumboat\nbumboats\nbumf\nbumfs\nbumkin\nbumkins\nbummed\nbummer\nbummers\nbummest\nbumming\nbump\nbumped\nbumper\nbumpered\nbumpering\nbumpers\nbumph\nbumphs\nbumpier\nbumpiest\nbumpily\nbumpiness\nbumpinesses\nbumping\nbumpkin\nbumpkinish\nbumpkinly\nbumpkins\nbumps\nbumptious\nbumptiously\nbumptiousness\nbumptiousnesses\nbumpy\nbums\nbun\nbunch\nbunchberries\nbunchberry\nbunched\nbunches\nbunchgrass\nbunchgrasses\nbunchier\nbunchiest\nbunchily\nbunching\nbunchy\nbunco\nbuncoed\nbuncoes\nbuncoing\nbuncombe\nbuncombes\nbuncos\nbund\nbundist\nbundists\nbundle\nbundled\nbundler\nbundlers\nbundles\nbundling\nbundlings\nbunds\nbundt\nbundts\nbung\nbungalow\nbungalows\nbunged\nbungee\nbungees\nbunghole\nbungholes\nbunging\nbungle\nbungled\nbungler\nbunglers\nbungles\nbunglesome\nbungling\nbunglingly\nbunglings\nbungs\nbunion\nbunions\nbunk\nbunked\nbunker\nbunkered\nbunkering\nbunkers\nbunkhouse\nbunkhouses\nbunking\nbunkmate\nbunkmates\nbunko\nbunkoed\nbunkoes\nbunkoing\nbunkos\nbunks\nbunkum\nbunkums\nbunn\nbunnies\nbunns\nbunny\nbunraku\nbunrakus\nbuns\nbunt\nbunted\nbunter\nbunters\nbunting\nbuntings\nbuntline\nbuntlines\nbunts\nbunya\nbunyas\nbuoy\nbuoyage\nbuoyages\nbuoyance\nbuoyances\nbuoyancies\nbuoyancy\nbuoyant\nbuoyantly\nbuoyed\nbuoying\nbuoys\nbuppie\nbuppies\nbuqsha\nbuqshas\nbur\nbura\nburan\nburans\nburas\nburble\nburbled\nburbler\nburblers\nburbles\nburblier\nburbliest\nburbling\nburbly\nburbot\nburbots\nburbs\nburd\nburden\nburdened\nburdener\nburdeners\nburdening\nburdens\nburdensome\nburdie\nburdies\nburdock\nburdocks\nburds\nbureau\nbureaucracies\nbureaucracy\nbureaucrat\nbureaucratese\nbureaucrateses\nbureaucratic\nbureaucratically\nbureaucratise\nbureaucratised\nbureaucratises\nbureaucratising\nbureaucratism\nbureaucratisms\nbureaucratization\nbureaucratizations\nbureaucratize\nbureaucratized\nbureaucratizes\nbureaucratizing\nbureaucrats\nbureaus\nbureaux\nburet\nburets\nburette\nburettes\nburg\nburgage\nburgages\nburgee\nburgees\nburgeon\nburgeoned\nburgeoning\nburgeons\nburger\nburgers\nburgess\nburgesses\nburgh\nburghal\nburgher\nburghers\nburghs\nburglar\nburglaries\nburglarious\nburglariously\nburglarize\nburglarized\nburglarizes\nburglarizing\nburglarproof\nburglars\nburglary\nburgle\nburgled\nburgles\nburgling\nburgomaster\nburgomasters\nburgonet\nburgonets\nburgoo\nburgoos\nburgout\nburgouts\nburgrave\nburgraves\nburgs\nburgundies\nburgundy\nburial\nburials\nburied\nburier\nburiers\nburies\nburin\nburins\nburke\nburked\nburker\nburkers\nburkes\nburking\nburkite\nburkites\nburl\nburladero\nburladeros\nburlap\nburlaps\nburled\nburler\nburlers\nburlesk\nburlesks\nburlesque\nburlesqued\nburlesquely\nburlesquer\nburlesquers\nburlesques\nburlesquing\nburley\nburleys\nburlier\nburliest\nburlily\nburliness\nburlinesses\nburling\nburls\nburly\nburn\nburnable\nburnables\nburned\nburner\nburners\nburnet\nburnets\nburnie\nburnies\nburning\nburningly\nburnings\nburnish\nburnished\nburnisher\nburnishers\nburnishes\nburnishing\nburnishings\nburnoose\nburnoosed\nburnooses\nburnous\nburnouses\nburnout\nburnouts\nburns\nburnsides\nburnt\nburp\nburped\nburping\nburps\nburr\nburred\nburrer\nburrers\nburrier\nburriest\nburring\nburrito\nburritos\nburro\nburros\nburrow\nburrowed\nburrower\nburrowers\nburrowing\nburrows\nburrs\nburrstone\nburrstones\nburry\nburs\nbursa\nbursae\nbursal\nbursar\nbursaries\nbursars\nbursary\nbursas\nbursate\nburse\nburseed\nburseeds\nbursera\nburses\nbursitis\nbursitises\nburst\nbursted\nburster\nbursters\nbursting\nburstone\nburstones\nbursts\nburthen\nburthened\nburthening\nburthens\nburton\nburtons\nburweed\nburweeds\nbury\nburying\nbus\nbusbar\nbusbars\nbusbies\nbusboy\nbusboys\nbusby\nbused\nbuses\nbush\nbushbuck\nbushbucks\nbushed\nbushel\nbusheled\nbusheler\nbushelers\nbusheling\nbushelled\nbushelling\nbushels\nbusher\nbushers\nbushes\nbushfire\nbushfires\nbushgoat\nbushgoats\nbushido\nbushidos\nbushier\nbushiest\nbushily\nbushiness\nbushinesses\nbushing\nbushings\nbushland\nbushlands\nbushless\nbushlike\nbushman\nbushmaster\nbushmasters\nbushmen\nbushpig\nbushpigs\nbushranger\nbushrangers\nbushranging\nbushrangings\nbushtit\nbushtits\nbushwa\nbushwah\nbushwahs\nbushwas\nbushwhack\nbushwhacked\nbushwhacker\nbushwhackers\nbushwhacking\nbushwhacks\nbushy\nbusied\nbusier\nbusies\nbusiest\nbusily\nbusiness\nbusinesses\nbusinesslike\nbusinessman\nbusinessmen\nbusinesspeople\nbusinessperson\nbusinesspersons\nbusinesswoman\nbusinesswomen\nbusing\nbusings\nbusk\nbusked\nbusker\nbuskers\nbuskin\nbuskined\nbusking\nbuskins\nbusks\nbusload\nbusloads\nbusman\nbusmen\nbuss\nbussed\nbusses\nbussing\nbussings\nbust\nbustard\nbustards\nbusted\nbuster\nbusters\nbustic\nbustics\nbustier\nbustiers\nbustiest\nbusting\nbustle\nbustled\nbustles\nbustline\nbustlines\nbustling\nbustlingly\nbusts\nbusty\nbusulfan\nbusulfans\nbusy\nbusybodies\nbusybody\nbusying\nbusyness\nbusynesses\nbusywork\nbusyworks\nbut\nbutadiene\nbutadienes\nbutane\nbutanes\nbutanol\nbutanols\nbutanone\nbutanones\nbutch\nbutcher\nbutchered\nbutcheries\nbutchering\nbutcherly\nbutchers\nbutchery\nbutches\nbute\nbutene\nbutenes\nbuteo\nbuteos\nbutes\nbutle\nbutled\nbutler\nbutleries\nbutlers\nbutlery\nbutles\nbutling\nbuts\nbutt\nbuttals\nbutte\nbutted\nbutter\nbutterball\nbutterballs\nbuttercup\nbuttercups\nbuttered\nbutterfat\nbutterfats\nbutterfingered\nbutterfingers\nbutterfish\nbutterfishes\nbutterflied\nbutterflies\nbutterfly\nbutterflyer\nbutterflyers\nbutterflying\nbutterier\nbutteries\nbutteriest\nbuttering\nbutterless\nbuttermilk\nbuttermilks\nbutternut\nbutternuts\nbutters\nbutterscotch\nbutterscotches\nbutterweed\nbutterweeds\nbutterwort\nbutterworts\nbuttery\nbuttes\nbutties\nbutting\nbuttinski\nbuttinskies\nbuttinsky\nbuttock\nbuttocks\nbutton\nbuttonball\nbuttonballs\nbuttonbush\nbuttonbushes\nbuttoned\nbuttoner\nbuttoners\nbuttonhole\nbuttonholed\nbuttonholer\nbuttonholers\nbuttonholes\nbuttonholing\nbuttonhook\nbuttonhooked\nbuttonhooking\nbuttonhooks\nbuttoning\nbuttonless\nbuttons\nbuttonwood\nbuttonwoods\nbuttony\nbuttress\nbuttressed\nbuttresses\nbuttressing\nbutts\nbuttstock\nbuttstocks\nbutty\nbutut\nbututs\nbutyl\nbutylate\nbutylated\nbutylates\nbutylating\nbutylation\nbutylations\nbutylene\nbutylenes\nbutyls\nbutyral\nbutyraldehyde\nbutyraldehydes\nbutyrals\nbutyrate\nbutyrates\nbutyric\nbutyrin\nbutyrins\nbutyrophenone\nbutyrophenones\nbutyrous\nbutyryl\nbutyryls\nbuxom\nbuxomer\nbuxomest\nbuxomly\nbuxomness\nbuxomnesses\nbuy\nbuyable\nbuyback\nbuybacks\nbuyer\nbuyers\nbuying\nbuyout\nbuyouts\nbuys\nbuzuki\nbuzukia\nbuzukis\nbuzz\nbuzzard\nbuzzards\nbuzzed\nbuzzer\nbuzzers\nbuzzes\nbuzzing\nbuzzwig\nbuzzwigs\nbuzzword\nbuzzwords\nbwana\nbwanas\nby\nbye\nbyelaw\nbyelaws\nbyes\nbygone\nbygones\nbylaw\nbylaws\nbyline\nbylined\nbyliner\nbyliners\nbylines\nbylining\nbyname\nbynames\nbypass\nbypassed\nbypasses\nbypassing\nbypast\nbypath\nbypaths\nbyplay\nbyplays\nbyproduct\nbyproducts\nbyre\nbyres\nbyrl\nbyrled\nbyrling\nbyrls\nbyrnie\nbyrnies\nbyroad\nbyroads\nbys\nbyssi\nbyssinoses\nbyssinosis\nbyssus\nbyssuses\nbystander\nbystanders\nbystreet\nbystreets\nbytalk\nbytalks\nbyte\nbytes\nbyway\nbyways\nbyword\nbywords\nbywork\nbyworks\nbyzant\nbyzantine\nbyzants\ncab\ncabal\ncabala\ncabalas\ncabaletta\ncabalettas\ncabalism\ncabalisms\ncabalist\ncabalistic\ncabalists\ncaballed\ncaballero\ncaballeros\ncaballing\ncabals\ncabana\ncabanas\ncabaret\ncabarets\ncabbage\ncabbaged\ncabbages\ncabbageworm\ncabbageworms\ncabbaging\ncabbala\ncabbalah\ncabbalahs\ncabbalas\ncabbed\ncabbie\ncabbies\ncabbing\ncabby\ncabdriver\ncabdrivers\ncaber\ncabernet\ncabernets\ncabers\ncabestro\ncabestros\ncabezon\ncabezone\ncabezones\ncabezons\ncabildo\ncabildos\ncabin\ncabined\ncabinet\ncabinetmaker\ncabinetmakers\ncabinetmaking\ncabinetmakings\ncabinetries\ncabinetry\ncabinets\ncabinetwork\ncabinetworks\ncabining\ncabins\ncable\ncabled\ncablegram\ncablegrams\ncables\ncablet\ncablets\ncableway\ncableways\ncabling\ncabman\ncabmen\ncabob\ncabobs\ncaboched\ncabochon\ncabochons\ncabomba\ncabombas\ncaboodle\ncaboodles\ncaboose\ncabooses\ncaboshed\ncabotage\ncabotages\ncabresta\ncabrestas\ncabresto\ncabrestos\ncabretta\ncabrettas\ncabrilla\ncabrillas\ncabriole\ncabrioles\ncabriolet\ncabriolets\ncabs\ncabstand\ncabstands\ncaca\ncacao\ncacaos\ncacas\ncacciatore\ncachalot\ncachalots\ncache\ncachectic\ncached\ncachepot\ncachepots\ncaches\ncachet\ncacheted\ncacheting\ncachets\ncachexia\ncachexias\ncachexic\ncachexies\ncachexy\ncaching\ncachinnate\ncachinnated\ncachinnates\ncachinnating\ncachinnation\ncachinnations\ncachou\ncachous\ncachucha\ncachuchas\ncacique\ncaciques\ncaciquism\ncaciquisms\ncackle\ncackled\ncackler\ncacklers\ncackles\ncackling\ncacodemon\ncacodemonic\ncacodemons\ncacodyl\ncacodyls\ncacoethes\ncacographical\ncacographies\ncacography\ncacomistle\ncacomistles\ncacomixl\ncacomixls\ncacophonies\ncacophonous\ncacophonously\ncacophony\ncacti\ncactoid\ncactus\ncactuses\ncacuminal\ncad\ncadaster\ncadasters\ncadastral\ncadastrally\ncadastre\ncadastres\ncadaver\ncadaveric\ncadaverine\ncadaverines\ncadaverous\ncadaverously\ncadavers\ncaddice\ncaddices\ncaddie\ncaddied\ncaddies\ncaddis\ncaddises\ncaddish\ncaddishly\ncaddishness\ncaddishnesses\ncaddisworm\ncaddisworms\ncaddy\ncaddying\ncade\ncadelle\ncadelles\ncadence\ncadenced\ncadences\ncadencies\ncadencing\ncadency\ncadent\ncadential\ncadenza\ncadenzas\ncades\ncadet\ncadets\ncadetship\ncadetships\ncadge\ncadged\ncadger\ncadgers\ncadges\ncadging\ncadgy\ncadi\ncadis\ncadmic\ncadmium\ncadmiums\ncadre\ncadres\ncads\ncaducean\ncaducei\ncaduceus\ncaducities\ncaducity\ncaducous\ncaeca\ncaecal\ncaecally\ncaecilian\ncaecilians\ncaecum\ncaeoma\ncaeomas\ncaesar\ncaesarean\ncaesareans\ncaesarian\ncaesarians\ncaesars\ncaesium\ncaesiums\ncaespitose\ncaestus\ncaestuses\ncaesura\ncaesurae\ncaesural\ncaesuras\ncaesuric\ncafe\ncafes\ncafeteria\ncafeterias\ncafetoria\ncafetorium\ncafetoriums\ncaff\ncaffein\ncaffeinated\ncaffeine\ncaffeines\ncaffeins\ncaffs\ncaftan\ncaftans\ncage\ncaged\ncageful\ncagefuls\ncageling\ncagelings\ncager\ncagers\ncages\ncagey\ncageyness\ncageynesses\ncagier\ncagiest\ncagily\ncaginess\ncaginesses\ncaging\ncagy\ncahier\ncahiers\ncahoot\ncahoots\ncahow\ncahows\ncaid\ncaids\ncaiman\ncaimans\ncain\ncains\ncaique\ncaiques\ncaird\ncairds\ncairn\ncairned\ncairngorm\ncairngorms\ncairns\ncairny\ncaisson\ncaissons\ncaitiff\ncaitiffs\ncajaput\ncajaputs\ncajeput\ncajeputs\ncajole\ncajoled\ncajolement\ncajolements\ncajoler\ncajoleries\ncajolers\ncajolery\ncajoles\ncajoling\ncajon\ncajones\ncajuput\ncajuputs\ncake\ncaked\ncakes\ncakewalk\ncakewalked\ncakewalker\ncakewalkers\ncakewalking\ncakewalks\ncakey\ncakier\ncakiest\ncaking\ncaky\ncalabash\ncalabashes\ncalaboose\ncalabooses\ncaladium\ncaladiums\ncalamander\ncalamanders\ncalamar\ncalamari\ncalamaries\ncalamaris\ncalamars\ncalamary\ncalami\ncalamine\ncalamined\ncalamines\ncalamining\ncalamint\ncalamints\ncalamite\ncalamites\ncalamities\ncalamitous\ncalamitously\ncalamity\ncalamondin\ncalamondins\ncalamus\ncalando\ncalash\ncalashes\ncalathi\ncalathos\ncalathus\ncalcanea\ncalcaneal\ncalcanei\ncalcaneum\ncalcaneus\ncalcar\ncalcareous\ncalcareously\ncalcaria\ncalcars\ncalceate\ncalces\ncalcic\ncalcicole\ncalcicoles\ncalcicolous\ncalciferol\ncalciferols\ncalciferous\ncalcific\ncalcification\ncalcifications\ncalcified\ncalcifies\ncalcifuge\ncalcifuges\ncalcifugous\ncalcify\ncalcifying\ncalcimine\ncalcimined\ncalcimines\ncalcimining\ncalcination\ncalcinations\ncalcine\ncalcined\ncalcines\ncalcining\ncalcinoses\ncalcinosis\ncalcite\ncalcites\ncalcitic\ncalcitonin\ncalcitonins\ncalcium\ncalciums\ncalcspar\ncalcspars\ncalctufa\ncalctufas\ncalctuff\ncalctuffs\ncalculable\ncalculate\ncalculated\ncalculatedly\ncalculatedness\ncalculatednesses\ncalculates\ncalculating\ncalculatingly\ncalculation\ncalculational\ncalculations\ncalculator\ncalculators\ncalculi\ncalculous\ncalculus\ncalculuses\ncaldaria\ncaldarium\ncaldera\ncalderas\ncaldron\ncaldrons\ncaleche\ncaleches\ncalefactories\ncalefactory\ncalendal\ncalendar\ncalendared\ncalendaring\ncalendars\ncalender\ncalendered\ncalenderer\ncalenderers\ncalendering\ncalenders\ncalendric\ncalendrical\ncalends\ncalendula\ncalendulas\ncalenture\ncalentures\ncalesa\ncalesas\ncalf\ncalflike\ncalfs\ncalfskin\ncalfskins\ncaliber\ncalibers\ncalibrate\ncalibrated\ncalibrates\ncalibrating\ncalibration\ncalibrations\ncalibrator\ncalibrators\ncalibre\ncalibred\ncalibres\ncalices\ncaliche\ncaliches\ncalicle\ncalicles\ncalico\ncalicoes\ncalicos\ncalif\ncalifate\ncalifates\ncalifornium\ncaliforniums\ncalifs\ncaliginous\ncalipash\ncalipashes\ncalipee\ncalipees\ncaliper\ncalipered\ncalipering\ncalipers\ncaliph\ncaliphal\ncaliphate\ncaliphates\ncaliphs\ncalisaya\ncalisayas\ncalisthenic\ncalisthenics\ncalix\ncalk\ncalked\ncalker\ncalkers\ncalkin\ncalking\ncalkins\ncalks\ncall\ncalla\ncallable\ncallaloo\ncallaloos\ncallan\ncallans\ncallant\ncallants\ncallas\ncallback\ncallbacks\ncallboy\ncallboys\ncalled\ncaller\ncallers\ncallet\ncallets\ncalligrapher\ncalligraphers\ncalligraphic\ncalligraphically\ncalligraphies\ncalligraphist\ncalligraphists\ncalligraphy\ncalling\ncallings\ncalliope\ncalliopes\ncallipee\ncallipees\ncalliper\ncallipered\ncallipering\ncallipers\ncallipygian\ncallipygous\ncallithump\ncallithumpian\ncallithumps\ncallose\ncalloses\ncallosities\ncallosity\ncallous\ncalloused\ncallouses\ncallousing\ncallously\ncallousness\ncallousnesses\ncallow\ncallower\ncallowest\ncallowness\ncallownesses\ncalls\ncallus\ncallused\ncalluses\ncallusing\ncalm\ncalmative\ncalmatives\ncalmed\ncalmer\ncalmest\ncalming\ncalmly\ncalmness\ncalmnesses\ncalmodulin\ncalmodulins\ncalms\ncalo\ncalomel\ncalomels\ncaloric\ncalorically\ncalorics\ncalorie\ncalories\ncalorific\ncalorimeter\ncalorimeters\ncalorimetric\ncalorimetrically\ncalorimetries\ncalorimetry\ncalorize\ncalorized\ncalorizes\ncalorizing\ncalory\ncalos\ncalotte\ncalottes\ncalotype\ncalotypes\ncaloyer\ncaloyers\ncalpac\ncalpack\ncalpacks\ncalpacs\ncalque\ncalqued\ncalques\ncalquing\ncalthrop\ncalthrops\ncaltrap\ncaltraps\ncaltrop\ncaltrops\ncalumet\ncalumets\ncalumniate\ncalumniated\ncalumniates\ncalumniating\ncalumniation\ncalumniations\ncalumniator\ncalumniators\ncalumnies\ncalumnious\ncalumniously\ncalumny\ncalutron\ncalutrons\ncalvados\ncalvadoses\ncalvaria\ncalvarias\ncalvaries\ncalvarium\ncalvariums\ncalvary\ncalve\ncalved\ncalves\ncalving\ncalx\ncalxes\ncalycate\ncalyceal\ncalyces\ncalycine\ncalycle\ncalycles\ncalyculi\ncalyculus\ncalypso\ncalypsoes\ncalypsonian\ncalypsonians\ncalypsos\ncalypter\ncalypters\ncalyptra\ncalyptras\ncalyx\ncalyxes\ncalzone\ncalzones\ncam\ncamail\ncamailed\ncamails\ncamaraderie\ncamaraderies\ncamarilla\ncamarillas\ncamas\ncamases\ncamass\ncamasses\ncamber\ncambered\ncambering\ncambers\ncambia\ncambial\ncambism\ncambisms\ncambist\ncambists\ncambium\ncambiums\ncambogia\ncambogias\ncambric\ncambrics\ncamcorder\ncamcorders\ncame\ncamel\ncamelback\ncamelbacks\ncameleer\ncameleers\ncamelia\ncamelias\ncamellia\ncamellias\ncamelopard\ncamelopards\ncamels\ncameo\ncameoed\ncameoing\ncameos\ncamera\ncamerae\ncameral\ncameraman\ncameramen\ncameraperson\ncamerapersons\ncameras\ncamerawoman\ncamerawomen\ncamerlengo\ncamerlengos\ncames\ncamion\ncamions\ncamisa\ncamisade\ncamisades\ncamisado\ncamisadoes\ncamisados\ncamisas\ncamise\ncamises\ncamisia\ncamisias\ncamisole\ncamisoles\ncamlet\ncamlets\ncamomile\ncamomiles\ncamorra\ncamorras\ncamorrista\ncamorristi\ncamouflage\ncamouflageable\ncamouflaged\ncamouflages\ncamouflagic\ncamouflaging\ncamp\ncampagna\ncampagne\ncampaign\ncampaigned\ncampaigner\ncampaigners\ncampaigning\ncampaigns\ncampanile\ncampaniles\ncampanili\ncampanologies\ncampanologist\ncampanologists\ncampanology\ncampanula\ncampanulas\ncampanulate\ncampcraft\ncampcrafts\ncamped\ncamper\ncampers\ncampesino\ncampesinos\ncampestral\ncampfire\ncampfires\ncampground\ncampgrounds\ncamphene\ncamphenes\ncamphine\ncamphines\ncamphire\ncamphires\ncamphol\ncamphols\ncamphor\ncamphoraceous\ncamphorate\ncamphorated\ncamphorates\ncamphorating\ncamphors\ncampi\ncampier\ncampiest\ncampily\ncampiness\ncampinesses\ncamping\ncampings\ncampion\ncampions\ncampo\ncampong\ncampongs\ncamporee\ncamporees\ncampos\ncamps\ncampsite\ncampsites\ncampus\ncampused\ncampuses\ncampusing\ncampy\ncampylobacter\ncampylobacters\ncampylotropous\ncams\ncamshaft\ncamshafts\ncan\ncanaille\ncanailles\ncanakin\ncanakins\ncanal\ncanaled\ncanalicular\ncanaliculi\ncanaliculus\ncanaling\ncanalise\ncanalised\ncanalises\ncanalising\ncanalization\ncanalizations\ncanalize\ncanalized\ncanalizes\ncanalizing\ncanalled\ncanaller\ncanallers\ncanalling\ncanals\ncanape\ncanapes\ncanard\ncanards\ncanaries\ncanary\ncanasta\ncanastas\ncancan\ncancans\ncancel\ncancelable\ncancelation\ncancelations\ncanceled\ncanceler\ncancelers\ncanceling\ncancellable\ncancellation\ncancellations\ncancelled\ncanceller\ncancellers\ncancelling\ncancellous\ncancels\ncancer\ncancerous\ncancerously\ncancers\ncancha\ncanchas\ncancroid\ncancroids\ncandela\ncandelabra\ncandelabras\ncandelabrum\ncandelabrums\ncandelas\ncandent\ncandescence\ncandescences\ncandescent\ncandid\ncandida\ncandidacies\ncandidacy\ncandidas\ncandidate\ncandidates\ncandidature\ncandidatures\ncandider\ncandidest\ncandidiases\ncandidiasis\ncandidly\ncandidness\ncandidnesses\ncandids\ncandied\ncandies\ncandle\ncandleberries\ncandleberry\ncandled\ncandlefish\ncandlefishes\ncandleholder\ncandleholders\ncandlelight\ncandlelighted\ncandlelighter\ncandlelighters\ncandlelights\ncandlelit\ncandlenut\ncandlenuts\ncandlepin\ncandlepins\ncandlepower\ncandlepowers\ncandler\ncandlers\ncandles\ncandlesnuffer\ncandlesnuffers\ncandlestick\ncandlesticks\ncandlewick\ncandlewicks\ncandlewood\ncandlewoods\ncandling\ncandor\ncandors\ncandour\ncandours\ncandy\ncandyfloss\ncandyflosses\ncandygram\ncandygrams\ncandying\ncandytuft\ncandytufts\ncane\ncanebrake\ncanebrakes\ncaned\ncanella\ncanellas\ncanephor\ncanephors\ncaner\ncaners\ncanes\ncanescent\ncaneware\ncanewares\ncanfield\ncanfields\ncanful\ncanfuls\ncangue\ncangues\ncanicular\ncanid\ncanids\ncanikin\ncanikins\ncanine\ncanines\ncaning\ncaninities\ncaninity\ncanister\ncanisters\ncanities\ncanker\ncankered\ncankering\ncankerous\ncankers\ncankerworm\ncankerworms\ncanna\ncannabic\ncannabin\ncannabinoid\ncannabinoids\ncannabinol\ncannabinols\ncannabins\ncannabis\ncannabises\ncannas\ncanned\ncannel\ncannelloni\ncannelon\ncannelons\ncannels\ncanner\ncanneries\ncanners\ncannery\ncannibal\ncannibalise\ncannibalised\ncannibalises\ncannibalising\ncannibalism\ncannibalisms\ncannibalistic\ncannibalization\ncannibalizations\ncannibalize\ncannibalized\ncannibalizes\ncannibalizing\ncannibals\ncannie\ncannier\ncanniest\ncannikin\ncannikins\ncannily\ncanniness\ncanninesses\ncanning\ncannings\ncannister\ncannisters\ncannoli\ncannolis\ncannon\ncannonade\ncannonaded\ncannonades\ncannonading\ncannonball\ncannonballed\ncannonballing\ncannonballs\ncannoned\ncannoneer\ncannoneers\ncannoning\ncannonries\ncannonry\ncannons\ncannot\ncannula\ncannulae\ncannular\ncannulas\ncanny\ncanoe\ncanoeable\ncanoed\ncanoeing\ncanoeist\ncanoeists\ncanoes\ncanola\ncanolas\ncanon\ncanoness\ncanonesses\ncanonic\ncanonical\ncanonically\ncanonicals\ncanonicities\ncanonicity\ncanonise\ncanonised\ncanonises\ncanonising\ncanonist\ncanonists\ncanonization\ncanonizations\ncanonize\ncanonized\ncanonizes\ncanonizing\ncanonries\ncanonry\ncanons\ncanoodle\ncanoodled\ncanoodles\ncanoodling\ncanopied\ncanopies\ncanopy\ncanopying\ncanorous\ncanorously\ncanorousness\ncanorousnesses\ncans\ncansful\ncanso\ncansos\ncanst\ncant\ncantabile\ncantala\ncantalas\ncantaloup\ncantaloupe\ncantaloupes\ncantaloups\ncantankerous\ncantankerously\ncantankerousness\ncantankerousnesses\ncantata\ncantatas\ncantatrice\ncantatrices\ncantatrici\ncantdog\ncantdogs\ncanted\ncanteen\ncanteens\ncanter\ncantered\ncantering\ncanters\ncanthal\ncantharides\ncantharidin\ncantharidins\ncantharis\ncanthaxanthin\ncanthaxanthins\ncanthi\ncanthus\ncantic\ncanticle\ncanticles\ncantilena\ncantilenas\ncantilever\ncantilevered\ncantilevering\ncantilevers\ncantillate\ncantillated\ncantillates\ncantillating\ncantillation\ncantillations\ncantina\ncantinas\ncanting\ncantle\ncantles\ncanto\ncanton\ncantonal\ncantoned\ncantoning\ncantonment\ncantonments\ncantons\ncantor\ncantorial\ncantors\ncantos\ncantraip\ncantraips\ncantrap\ncantraps\ncantrip\ncantrips\ncants\ncantus\ncanty\ncanula\ncanulae\ncanulas\ncanulate\ncanulated\ncanulates\ncanulating\ncanvas\ncanvasback\ncanvasbacks\ncanvased\ncanvaser\ncanvasers\ncanvases\ncanvasing\ncanvaslike\ncanvass\ncanvassed\ncanvasser\ncanvassers\ncanvasses\ncanvassing\ncanyon\ncanyons\ncanzona\ncanzonas\ncanzone\ncanzones\ncanzonet\ncanzonets\ncanzoni\ncaoutchouc\ncaoutchoucs\ncap\ncapabilities\ncapability\ncapable\ncapableness\ncapablenesses\ncapabler\ncapablest\ncapably\ncapacious\ncapaciously\ncapaciousness\ncapaciousnesses\ncapacitance\ncapacitances\ncapacitate\ncapacitated\ncapacitates\ncapacitating\ncapacitation\ncapacitations\ncapacities\ncapacitive\ncapacitively\ncapacitor\ncapacitors\ncapacity\ncaparison\ncaparisoned\ncaparisoning\ncaparisons\ncape\ncaped\ncapelan\ncapelans\ncapelet\ncapelets\ncapelin\ncapelins\ncaper\ncapercaillie\ncapercaillies\ncapercailzie\ncapercailzies\ncapered\ncaperer\ncaperers\ncapering\ncapers\ncapes\ncapeskin\ncapeskins\ncapework\ncapeworks\ncapful\ncapfuls\ncaph\ncaphs\ncapias\ncapiases\ncapillaries\ncapillarities\ncapillarity\ncapillary\ncapita\ncapital\ncapitalise\ncapitalised\ncapitalises\ncapitalising\ncapitalism\ncapitalisms\ncapitalist\ncapitalistic\ncapitalistically\ncapitalists\ncapitalization\ncapitalizations\ncapitalize\ncapitalized\ncapitalizes\ncapitalizing\ncapitally\ncapitals\ncapitate\ncapitation\ncapitations\ncapitol\ncapitols\ncapitula\ncapitular\ncapitularies\ncapitulary\ncapitulate\ncapitulated\ncapitulates\ncapitulating\ncapitulation\ncapitulations\ncapitulum\ncapless\ncaplet\ncaplets\ncaplin\ncaplins\ncapmaker\ncapmakers\ncapo\ncapon\ncaponata\ncaponatas\ncaponier\ncaponiers\ncaponize\ncaponized\ncaponizes\ncaponizing\ncapons\ncaporal\ncaporals\ncapos\ncapote\ncapotes\ncapouch\ncapouches\ncapped\ncappelletti\ncapper\ncappers\ncapping\ncappings\ncappuccino\ncappuccinos\ncapric\ncapricci\ncapriccio\ncapriccios\ncaprice\ncaprices\ncapricious\ncapriciously\ncapriciousness\ncapriciousnesses\ncaprification\ncaprifications\ncaprifig\ncaprifigs\ncaprine\ncapriole\ncaprioled\ncaprioles\ncaprioling\ncapris\ncaprock\ncaprocks\ncaprolactam\ncaprolactams\ncaps\ncapsaicin\ncapsaicins\ncapsicin\ncapsicins\ncapsicum\ncapsicums\ncapsid\ncapsidal\ncapsids\ncapsize\ncapsized\ncapsizes\ncapsizing\ncapsomer\ncapsomers\ncapstan\ncapstans\ncapstone\ncapstones\ncapsular\ncapsulated\ncapsule\ncapsuled\ncapsules\ncapsuling\ncapsulize\ncapsulized\ncapsulizes\ncapsulizing\ncaptain\ncaptaincies\ncaptaincy\ncaptained\ncaptaining\ncaptains\ncaptainship\ncaptainships\ncaptan\ncaptans\ncaption\ncaptioned\ncaptioning\ncaptionless\ncaptions\ncaptious\ncaptiously\ncaptiousness\ncaptiousnesses\ncaptivate\ncaptivated\ncaptivates\ncaptivating\ncaptivation\ncaptivations\ncaptivator\ncaptivators\ncaptive\ncaptives\ncaptivities\ncaptivity\ncaptopril\ncaptoprils\ncaptor\ncaptors\ncapture\ncaptured\ncapturer\ncapturers\ncaptures\ncapturing\ncapuche\ncapuched\ncapuches\ncapuchin\ncapuchins\ncaput\ncapybara\ncapybaras\ncar\ncarabao\ncarabaos\ncarabid\ncarabids\ncarabin\ncarabine\ncarabineer\ncarabineers\ncarabiner\ncarabinero\ncarabineros\ncarabiners\ncarabines\ncarabinier\ncarabiniere\ncarabinieri\ncarabiniers\ncarabins\ncaracal\ncaracals\ncaracara\ncaracaras\ncarack\ncaracks\ncaracol\ncaracole\ncaracoled\ncaracoles\ncaracoling\ncaracolled\ncaracolling\ncaracols\ncaracul\ncaraculs\ncarafe\ncarafes\ncaragana\ncaraganas\ncarageen\ncarageens\ncaramba\ncarambola\ncarambolas\ncaramel\ncaramelise\ncaramelised\ncaramelises\ncaramelising\ncaramelize\ncaramelized\ncaramelizes\ncaramelizing\ncaramels\ncarangid\ncarangids\ncarapace\ncarapaces\ncarapax\ncarapaxes\ncarassow\ncarassows\ncarat\ncarate\ncarates\ncarats\ncaravan\ncaravaned\ncaravaner\ncaravaners\ncaravaning\ncaravanned\ncaravanner\ncaravanners\ncaravanning\ncaravans\ncaravansaries\ncaravansary\ncaravanserai\ncaravanserais\ncaravel\ncaravels\ncaraway\ncaraways\ncarb\ncarbachol\ncarbachols\ncarbamate\ncarbamates\ncarbamic\ncarbamide\ncarbamides\ncarbamino\ncarbamyl\ncarbamyls\ncarbanion\ncarbanions\ncarbarn\ncarbarns\ncarbaryl\ncarbaryls\ncarbazole\ncarbazoles\ncarbide\ncarbides\ncarbine\ncarbines\ncarbinol\ncarbinols\ncarbo\ncarbocyclic\ncarbohydrase\ncarbohydrases\ncarbohydrate\ncarbohydrates\ncarbolic\ncarbolics\ncarbon\ncarbonaceous\ncarbonade\ncarbonades\ncarbonado\ncarbonadoed\ncarbonadoes\ncarbonadoing\ncarbonados\ncarbonara\ncarbonaras\ncarbonate\ncarbonated\ncarbonates\ncarbonating\ncarbonation\ncarbonations\ncarbonic\ncarboniferous\ncarbonization\ncarbonizations\ncarbonize\ncarbonized\ncarbonizes\ncarbonizing\ncarbonless\ncarbonnade\ncarbonnades\ncarbons\ncarbonyl\ncarbonylation\ncarbonylations\ncarbonylic\ncarbonyls\ncarbora\ncarboras\ncarbos\ncarboxyl\ncarboxylase\ncarboxylases\ncarboxylate\ncarboxylated\ncarboxylates\ncarboxylating\ncarboxylation\ncarboxylations\ncarboxylic\ncarboxyls\ncarboxymethylcellulose\ncarboxymethylcelluloses\ncarboxypeptidase\ncarboxypeptidases\ncarboy\ncarboyed\ncarboys\ncarbs\ncarbuncle\ncarbuncled\ncarbuncles\ncarbuncular\ncarburet\ncarbureted\ncarbureting\ncarburetion\ncarburetions\ncarburetor\ncarburetors\ncarburets\ncarburetted\ncarburetter\ncarburetters\ncarburetting\ncarburettor\ncarburettors\ncarburise\ncarburised\ncarburises\ncarburising\ncarburization\ncarburizations\ncarburize\ncarburized\ncarburizes\ncarburizing\ncarcajou\ncarcajous\ncarcanet\ncarcanets\ncarcase\ncarcases\ncarcass\ncarcasses\ncarcel\ncarcels\ncarcinogen\ncarcinogeneses\ncarcinogenesis\ncarcinogenic\ncarcinogenicities\ncarcinogenicity\ncarcinogens\ncarcinoid\ncarcinoids\ncarcinoma\ncarcinomas\ncarcinomata\ncarcinomatoses\ncarcinomatosis\ncarcinomatous\ncarcinosarcoma\ncarcinosarcomas\ncarcinosarcomata\ncard\ncardamom\ncardamoms\ncardamon\ncardamons\ncardamum\ncardamums\ncardboard\ncardboards\ncardcase\ncardcases\ncarded\ncarder\ncarders\ncardholder\ncardholders\ncardia\ncardiac\ncardiacs\ncardiae\ncardias\ncardigan\ncardigans\ncardinal\ncardinalate\ncardinalates\ncardinalities\ncardinality\ncardinally\ncardinals\ncardinalship\ncardinalships\ncarding\ncardings\ncardiogenic\ncardiogram\ncardiograms\ncardiograph\ncardiographic\ncardiographies\ncardiographs\ncardiography\ncardioid\ncardioids\ncardiological\ncardiologies\ncardiologist\ncardiologists\ncardiology\ncardiomyopathies\ncardiomyopathy\ncardiopathies\ncardiopathy\ncardiopulmonary\ncardiorespiratory\ncardiothoracic\ncardiotonic\ncardiotonics\ncardiovascular\ncarditic\ncarditides\ncarditis\ncarditises\ncardoon\ncardoons\ncardplayer\ncardplayers\ncards\ncardsharp\ncardsharper\ncardsharpers\ncardsharps\ncare\ncared\ncareen\ncareened\ncareener\ncareeners\ncareening\ncareens\ncareer\ncareered\ncareerer\ncareerers\ncareering\ncareerism\ncareerisms\ncareerist\ncareerists\ncareers\ncarefree\ncareful\ncarefuller\ncarefullest\ncarefully\ncarefulness\ncarefulnesses\ncaregiver\ncaregivers\ncaregiving\ncaregivings\ncareless\ncarelessly\ncarelessness\ncarelessnesses\ncarer\ncarers\ncares\ncaress\ncaressed\ncaresser\ncaressers\ncaresses\ncaressing\ncaressingly\ncaressive\ncaressively\ncaret\ncaretake\ncaretaken\ncaretaker\ncaretakers\ncaretakes\ncaretaking\ncaretakings\ncaretook\ncarets\ncareworn\ncarex\ncarfare\ncarfares\ncarful\ncarfuls\ncargo\ncargoes\ncargos\ncarhop\ncarhops\ncaribe\ncaribes\ncaribou\ncaribous\ncaricatural\ncaricature\ncaricatured\ncaricatures\ncaricaturing\ncaricaturist\ncaricaturists\ncarices\ncaried\ncaries\ncarillon\ncarillonned\ncarillonneur\ncarillonneurs\ncarillonning\ncarillons\ncarina\ncarinae\ncarinal\ncarinas\ncarinate\ncarinated\ncaring\ncarioca\ncariocas\ncariogenic\ncariole\ncarioles\ncarious\ncaritas\ncaritases\ncarjacker\ncarjackers\ncarjacking\ncarjackings\ncark\ncarked\ncarking\ncarks\ncarl\ncarle\ncarles\ncarless\ncarlin\ncarline\ncarlines\ncarling\ncarlings\ncarlins\ncarlish\ncarload\ncarloads\ncarls\ncarmagnole\ncarmagnoles\ncarmaker\ncarmakers\ncarman\ncarmen\ncarminative\ncarminatives\ncarmine\ncarmines\ncarn\ncarnage\ncarnages\ncarnal\ncarnalities\ncarnality\ncarnallite\ncarnallites\ncarnally\ncarnassial\ncarnassials\ncarnation\ncarnations\ncarnauba\ncarnaubas\ncarnelian\ncarnelians\ncarnet\ncarnets\ncarney\ncarneys\ncarnie\ncarnies\ncarnified\ncarnifies\ncarnify\ncarnifying\ncarnitine\ncarnitines\ncarnival\ncarnivals\ncarnivora\ncarnivore\ncarnivores\ncarnivorous\ncarnivorously\ncarnivorousness\ncarnivorousnesses\ncarnotite\ncarnotites\ncarns\ncarny\ncaroach\ncaroaches\ncarob\ncarobs\ncaroch\ncaroche\ncaroches\ncarol\ncaroled\ncaroler\ncarolers\ncaroli\ncaroling\ncarolled\ncaroller\ncarollers\ncarolling\ncarols\ncarolus\ncaroluses\ncarom\ncaromed\ncaroming\ncaroms\ncarotene\ncarotenes\ncarotenoid\ncarotenoids\ncarotid\ncarotids\ncarotin\ncarotinoid\ncarotinoids\ncarotins\ncarousal\ncarousals\ncarouse\ncaroused\ncarousel\ncarousels\ncarouser\ncarousers\ncarouses\ncarousing\ncarp\ncarpaccio\ncarpaccios\ncarpal\ncarpale\ncarpalia\ncarpals\ncarped\ncarpel\ncarpellary\ncarpellate\ncarpels\ncarpenter\ncarpentered\ncarpentering\ncarpenters\ncarpentries\ncarpentry\ncarper\ncarpers\ncarpet\ncarpetbag\ncarpetbagger\ncarpetbaggeries\ncarpetbaggers\ncarpetbaggery\ncarpetbagging\ncarpetbags\ncarpeted\ncarpeting\ncarpetings\ncarpets\ncarpetweed\ncarpetweeds\ncarpi\ncarping\ncarpingly\ncarpings\ncarpogonia\ncarpogonial\ncarpogonium\ncarpool\ncarpooled\ncarpooler\ncarpoolers\ncarpooling\ncarpools\ncarpophore\ncarpophores\ncarport\ncarports\ncarpospore\ncarpospores\ncarps\ncarpus\ncarr\ncarrack\ncarracks\ncarrageen\ncarrageenan\ncarrageenans\ncarrageenin\ncarrageenins\ncarrageens\ncarragheen\ncarragheens\ncarrefour\ncarrefours\ncarrel\ncarrell\ncarrells\ncarrels\ncarriage\ncarriages\ncarriageway\ncarriageways\ncarried\ncarrier\ncarriers\ncarries\ncarriole\ncarrioles\ncarrion\ncarrions\ncarritch\ncarritches\ncarroch\ncarroches\ncarrom\ncarromed\ncarroming\ncarroms\ncarronade\ncarronades\ncarrot\ncarrotier\ncarrotiest\ncarrotin\ncarrotins\ncarrots\ncarrottop\ncarrottopped\ncarrottops\ncarroty\ncarrousel\ncarrousels\ncarrs\ncarry\ncarryall\ncarryalls\ncarryback\ncarrybacks\ncarryforward\ncarryforwards\ncarrying\ncarryon\ncarryons\ncarryout\ncarryouts\ncarryover\ncarryovers\ncars\ncarse\ncarses\ncarsick\ncarsickness\ncarsicknesses\ncart\ncartable\ncartage\ncartages\ncarte\ncarted\ncartel\ncartelise\ncartelised\ncartelises\ncartelising\ncartelization\ncartelizations\ncartelize\ncartelized\ncartelizes\ncartelizing\ncartels\ncarter\ncarters\ncartes\ncartilage\ncartilages\ncartilaginous\ncarting\ncartload\ncartloads\ncartographer\ncartographers\ncartographic\ncartographical\ncartographically\ncartographies\ncartography\ncarton\ncartoned\ncartoning\ncartons\ncartoon\ncartooned\ncartooning\ncartoonings\ncartoonish\ncartoonishly\ncartoonist\ncartoonists\ncartoonlike\ncartoons\ncartoony\ncartop\ncartopper\ncartoppers\ncartouch\ncartouche\ncartouches\ncartridge\ncartridges\ncarts\ncartularies\ncartulary\ncartwheel\ncartwheeled\ncartwheeler\ncartwheelers\ncartwheeling\ncartwheels\ncaruncle\ncaruncles\ncarvacrol\ncarvacrols\ncarve\ncarved\ncarvel\ncarvels\ncarven\ncarver\ncarvers\ncarves\ncarving\ncarvings\ncarwash\ncarwashes\ncaryatic\ncaryatid\ncaryatides\ncaryatids\ncaryopses\ncaryopsides\ncaryopsis\ncaryotin\ncaryotins\ncasa\ncasaba\ncasabas\ncasas\ncasava\ncasavas\ncasbah\ncasbahs\ncascabel\ncascabels\ncascable\ncascables\ncascade\ncascaded\ncascades\ncascading\ncascara\ncascaras\ncascarilla\ncascarillas\ncase\ncasease\ncaseases\ncaseate\ncaseated\ncaseates\ncaseating\ncaseation\ncaseations\ncasebearer\ncasebearers\ncasebook\ncasebooks\ncased\ncasefied\ncasefies\ncasefy\ncasefying\ncaseic\ncasein\ncaseinate\ncaseinates\ncaseins\ncaseload\ncaseloads\ncasemate\ncasemates\ncasement\ncasements\ncaseose\ncaseoses\ncaseous\ncasern\ncaserne\ncasernes\ncaserns\ncases\ncasette\ncasettes\ncasework\ncaseworker\ncaseworkers\ncaseworks\ncaseworm\ncaseworms\ncash\ncashable\ncashaw\ncashaws\ncashbook\ncashbooks\ncashbox\ncashboxes\ncashed\ncashes\ncashew\ncashews\ncashier\ncashiered\ncashiering\ncashiers\ncashing\ncashless\ncashmere\ncashmeres\ncashoo\ncashoos\ncasimere\ncasimeres\ncasimire\ncasimires\ncasing\ncasings\ncasini\ncasino\ncasinos\ncasita\ncasitas\ncask\ncasked\ncasket\ncasketed\ncasketing\ncaskets\ncasking\ncasks\ncasky\ncasque\ncasqued\ncasques\ncassaba\ncassabas\ncassata\ncassatas\ncassava\ncassavas\ncasserole\ncasseroles\ncassette\ncassettes\ncassia\ncassias\ncassimere\ncassimeres\ncassino\ncassinos\ncassis\ncassises\ncassiterite\ncassiterites\ncassock\ncassocks\ncassoulet\ncassoulets\ncassowaries\ncassowary\ncast\ncastabilities\ncastability\ncastable\ncastanet\ncastanets\ncastaway\ncastaways\ncaste\ncasteism\ncasteisms\ncastellan\ncastellans\ncastellated\ncaster\ncasters\ncastes\ncastigate\ncastigated\ncastigates\ncastigating\ncastigation\ncastigations\ncastigator\ncastigators\ncasting\ncastings\ncastle\ncastled\ncastles\ncastling\ncastoff\ncastoffs\ncastor\ncastoreum\ncastoreums\ncastors\ncastrate\ncastrated\ncastrates\ncastrati\ncastrating\ncastration\ncastrations\ncastrato\ncastrator\ncastrators\ncastratory\ncastratos\ncasts\ncasual\ncasually\ncasualness\ncasualnesses\ncasuals\ncasualties\ncasualty\ncasuarina\ncasuarinas\ncasuist\ncasuistic\ncasuistical\ncasuistries\ncasuistry\ncasuists\ncasus\ncat\ncatabolic\ncatabolically\ncatabolism\ncatabolisms\ncatabolite\ncatabolites\ncatabolize\ncatabolized\ncatabolizes\ncatabolizing\ncatachreses\ncatachresis\ncatachrestic\ncatachrestical\ncatachrestically\ncataclysm\ncataclysmal\ncataclysmic\ncataclysmically\ncataclysms\ncatacomb\ncatacombs\ncatadioptric\ncatadromous\ncatafalque\ncatafalques\ncatalase\ncatalases\ncatalatic\ncatalectic\ncatalectics\ncatalepsies\ncatalepsy\ncataleptic\ncataleptically\ncataleptics\ncatalexes\ncatalexis\ncatalo\ncataloes\ncatalog\ncataloged\ncataloger\ncatalogers\ncataloging\ncatalogs\ncatalogue\ncatalogued\ncataloguer\ncataloguers\ncatalogues\ncataloguing\ncatalos\ncatalpa\ncatalpas\ncatalyses\ncatalysis\ncatalyst\ncatalysts\ncatalytic\ncatalytically\ncatalyze\ncatalyzed\ncatalyzer\ncatalyzers\ncatalyzes\ncatalyzing\ncatamaran\ncatamarans\ncatamenia\ncatamenial\ncatamite\ncatamites\ncatamount\ncatamounts\ncataphora\ncataphoras\ncataphoreses\ncataphoresis\ncataphoretic\ncataphoretically\ncataphoric\ncataplasm\ncataplasms\ncataplexies\ncataplexy\ncatapult\ncatapulted\ncatapulting\ncatapults\ncataract\ncataractous\ncataracts\ncatarrh\ncatarrhal\ncatarrhally\ncatarrhine\ncatarrhines\ncatarrhs\ncatastrophe\ncatastrophes\ncatastrophic\ncatastrophically\ncatastrophism\ncatastrophisms\ncatastrophist\ncatastrophists\ncatatonia\ncatatonias\ncatatonic\ncatatonically\ncatatonics\ncatawba\ncatawbas\ncatbird\ncatbirds\ncatboat\ncatboats\ncatbrier\ncatbriers\ncatcall\ncatcalled\ncatcalling\ncatcalls\ncatch\ncatchable\ncatchall\ncatchalls\ncatcher\ncatchers\ncatches\ncatchflies\ncatchfly\ncatchier\ncatchiest\ncatching\ncatchment\ncatchments\ncatchpenny\ncatchphrase\ncatchphrases\ncatchpole\ncatchpoles\ncatchpoll\ncatchpolls\ncatchup\ncatchups\ncatchword\ncatchwords\ncatchy\ncatclaw\ncatclaws\ncate\ncatecheses\ncatechesis\ncatechetical\ncatechin\ncatechins\ncatechism\ncatechismal\ncatechisms\ncatechist\ncatechistic\ncatechists\ncatechization\ncatechizations\ncatechize\ncatechized\ncatechizer\ncatechizers\ncatechizes\ncatechizing\ncatechol\ncatecholamine\ncatecholaminergic\ncatecholamines\ncatechols\ncatechu\ncatechumen\ncatechumens\ncatechus\ncategoric\ncategorical\ncategorically\ncategories\ncategorise\ncategorised\ncategorises\ncategorising\ncategorization\ncategorizations\ncategorize\ncategorized\ncategorizes\ncategorizing\ncategory\ncatena\ncatenae\ncatenaries\ncatenary\ncatenas\ncatenate\ncatenated\ncatenates\ncatenating\ncatenation\ncatenations\ncatenoid\ncatenoids\ncater\ncateran\ncaterans\ncatercorner\ncatercornered\ncatered\ncaterer\ncaterers\ncateress\ncateresses\ncatering\ncaterpillar\ncaterpillars\ncaters\ncaterwaul\ncaterwauled\ncaterwauling\ncaterwauls\ncates\ncatface\ncatfaces\ncatfacing\ncatfacings\ncatfall\ncatfalls\ncatfight\ncatfights\ncatfish\ncatfishes\ncatgut\ncatguts\ncatharses\ncatharsis\ncathartic\ncathartics\ncathead\ncatheads\ncathect\ncathected\ncathectic\ncathecting\ncathects\ncathedra\ncathedrae\ncathedral\ncathedrals\ncathedras\ncathepsin\ncathepsins\ncatheter\ncatheterization\ncatheterizations\ncatheterize\ncatheterized\ncatheterizes\ncatheterizing\ncatheters\ncathexes\ncathexis\ncathodal\ncathodally\ncathode\ncathodes\ncathodic\ncathodically\ncatholic\ncatholically\ncatholicate\ncatholicates\ncatholicities\ncatholicity\ncatholicize\ncatholicized\ncatholicizes\ncatholicizing\ncatholicoi\ncatholicon\ncatholicons\ncatholicos\ncatholicoses\ncatholics\ncathouse\ncathouses\ncation\ncationic\ncationically\ncations\ncatkin\ncatkins\ncatlike\ncatlin\ncatling\ncatlings\ncatlins\ncatmint\ncatmints\ncatnap\ncatnaper\ncatnapers\ncatnapped\ncatnapper\ncatnappers\ncatnapping\ncatnaps\ncatnip\ncatnips\ncatoptric\ncats\ncatspaw\ncatspaws\ncatsup\ncatsups\ncattail\ncattails\ncattalo\ncattaloes\ncattalos\ncatted\ncatteries\ncattery\ncattie\ncattier\ncatties\ncattiest\ncattily\ncattiness\ncattinesses\ncatting\ncattish\ncattle\ncattleman\ncattlemen\ncattleya\ncattleyas\ncatty\ncatwalk\ncatwalks\ncaucus\ncaucused\ncaucuses\ncaucusing\ncaucussed\ncaucusses\ncaucussing\ncaudad\ncaudal\ncaudally\ncaudate\ncaudated\ncaudates\ncaudex\ncaudexes\ncaudices\ncaudillismo\ncaudillismos\ncaudillo\ncaudillos\ncaudle\ncaudles\ncaught\ncaul\ncauld\ncauldron\ncauldrons\ncaulds\ncaules\ncaulicle\ncaulicles\ncauliflower\ncaulifloweret\ncauliflowerets\ncauliflowers\ncauline\ncaulis\ncaulk\ncaulked\ncaulker\ncaulkers\ncaulking\ncaulkings\ncaulks\ncauls\ncausable\ncausal\ncausalgia\ncausalgias\ncausalgic\ncausalities\ncausality\ncausally\ncausals\ncausation\ncausations\ncausative\ncausatively\ncausatives\ncause\ncaused\ncauseless\ncauser\ncauserie\ncauseries\ncausers\ncauses\ncauseway\ncausewayed\ncausewaying\ncauseways\ncausey\ncauseys\ncausing\ncaustic\ncaustically\ncausticities\ncausticity\ncaustics\ncauteries\ncauterization\ncauterizations\ncauterize\ncauterized\ncauterizes\ncauterizing\ncautery\ncaution\ncautionary\ncautioned\ncautioning\ncautions\ncautious\ncautiously\ncautiousness\ncautiousnesses\ncavalcade\ncavalcades\ncavalero\ncavaleros\ncavaletti\ncavalier\ncavaliered\ncavaliering\ncavalierism\ncavalierisms\ncavalierly\ncavaliers\ncavalla\ncavallas\ncavalletti\ncavallies\ncavally\ncavalries\ncavalry\ncavalryman\ncavalrymen\ncavatina\ncavatinas\ncavatine\ncave\ncaveat\ncaveated\ncaveating\ncaveator\ncaveators\ncaveats\ncaved\ncavefish\ncavefishes\ncavelike\ncaveman\ncavemen\ncaver\ncavern\ncaverned\ncavernicolous\ncaverning\ncavernous\ncavernously\ncaverns\ncavers\ncaves\ncavetti\ncavetto\ncavettos\ncaviar\ncaviare\ncaviares\ncaviars\ncavicorn\ncavie\ncavies\ncavil\ncaviled\ncaviler\ncavilers\ncaviling\ncavilled\ncaviller\ncavillers\ncavilling\ncavils\ncaving\ncavings\ncavitary\ncavitate\ncavitated\ncavitates\ncavitating\ncavitation\ncavitations\ncavitied\ncavities\ncavity\ncavort\ncavorted\ncavorter\ncavorters\ncavorting\ncavorts\ncavy\ncaw\ncawed\ncawing\ncaws\ncay\ncayenne\ncayenned\ncayennes\ncayman\ncaymans\ncays\ncayuse\ncayuses\ncazique\ncaziques\nceanothus\nceanothuses\ncease\nceased\nceasefire\nceasefires\nceaseless\nceaselessly\nceaselessness\nceaselessnesses\nceases\nceasing\ncebid\ncebids\nceboid\nceboids\nceca\ncecal\ncecally\ncecum\ncedar\ncedarbird\ncedarbirds\ncedarn\ncedars\ncedarwood\ncedarwoods\ncede\nceded\nceder\nceders\ncedes\ncedi\ncedilla\ncedillas\nceding\ncedis\ncedula\ncedulas\ncee\ncees\nceiba\nceibas\nceil\nceiled\nceiler\nceilers\nceiling\nceilinged\nceilings\nceilometer\nceilometers\nceils\nceinture\nceintures\ncel\nceladon\nceladons\ncelandine\ncelandines\nceleb\ncelebrant\ncelebrants\ncelebrate\ncelebrated\ncelebratedness\ncelebratednesses\ncelebrates\ncelebrating\ncelebration\ncelebrations\ncelebrator\ncelebrators\ncelebratory\ncelebrities\ncelebrity\ncelebs\nceleriac\nceleriacs\nceleries\ncelerities\ncelerity\ncelery\ncelesta\ncelestas\nceleste\ncelestes\ncelestial\ncelestially\ncelestials\ncelestite\ncelestites\nceliac\nceliacs\ncelibacies\ncelibacy\ncelibate\ncelibates\ncell\ncella\ncellae\ncellar\ncellarage\ncellarages\ncellared\ncellarer\ncellarers\ncellaret\ncellarets\ncellarette\ncellarettes\ncellaring\ncellars\ncellblock\ncellblocks\ncelled\ncelli\ncelling\ncellist\ncellists\ncellmate\ncellmates\ncello\ncellobiose\ncellobioses\ncelloidin\ncelloidins\ncellophane\ncellophanes\ncellos\ncellphone\ncellphones\ncells\ncellular\ncellularities\ncellularity\ncellulase\ncellulases\ncellule\ncellules\ncellulite\ncellulites\ncellulitis\ncellulitises\ncelluloid\ncelluloids\ncellulolytic\ncellulose\ncelluloses\ncellulosic\ncellulosics\ncelom\ncelomata\nceloms\ncelosia\ncelosias\ncels\ncelt\ncelts\ncembali\ncembalo\ncembalos\ncement\ncementa\ncementation\ncementations\ncemented\ncementer\ncementers\ncementing\ncementite\ncementites\ncementitious\ncements\ncementum\ncementums\ncemeteries\ncemetery\ncenacle\ncenacles\ncenobite\ncenobites\ncenobitic\ncenospecies\ncenotaph\ncenotaphs\ncenote\ncenotes\ncense\ncensed\ncenser\ncensers\ncenses\ncensing\ncensor\ncensored\ncensorial\ncensoring\ncensorious\ncensoriously\ncensoriousness\ncensoriousnesses\ncensors\ncensorship\ncensorships\ncensual\ncensurable\ncensure\ncensured\ncensurer\ncensurers\ncensures\ncensuring\ncensus\ncensused\ncensuses\ncensusing\ncent\ncentai\ncental\ncentals\ncentare\ncentares\ncentas\ncentaur\ncentaurea\ncentaureas\ncentauries\ncentaurs\ncentaury\ncentavo\ncentavos\ncentenarian\ncentenarians\ncentenaries\ncentenary\ncentennial\ncentennially\ncentennials\ncenter\ncenterboard\ncenterboards\ncentered\ncenteredness\ncenterednesses\ncenterfold\ncenterfolds\ncentering\ncenterless\ncenterline\ncenterlines\ncenterpiece\ncenterpieces\ncenters\ncenteses\ncentesimal\ncentesimi\ncentesimo\ncentesimos\ncentesis\ncentiare\ncentiares\ncentigrade\ncentigram\ncentigrams\ncentile\ncentiles\ncentiliter\ncentiliters\ncentillion\ncentillions\ncentime\ncentimes\ncentimeter\ncentimeters\ncentimo\ncentimorgan\ncentimorgans\ncentimos\ncentipede\ncentipedes\ncentner\ncentners\ncento\ncentones\ncentos\ncentra\ncentral\ncentraler\ncentralest\ncentralise\ncentralised\ncentralises\ncentralising\ncentralism\ncentralisms\ncentralist\ncentralistic\ncentralists\ncentralities\ncentrality\ncentralization\ncentralizations\ncentralize\ncentralized\ncentralizer\ncentralizers\ncentralizes\ncentralizing\ncentrally\ncentrals\ncentre\ncentred\ncentres\ncentric\ncentrically\ncentricities\ncentricity\ncentrifugal\ncentrifugally\ncentrifugals\ncentrifugation\ncentrifugations\ncentrifuge\ncentrifuged\ncentrifuges\ncentrifuging\ncentring\ncentrings\ncentriole\ncentrioles\ncentripetal\ncentripetally\ncentrism\ncentrisms\ncentrist\ncentrists\ncentroid\ncentroids\ncentromere\ncentromeres\ncentromeric\ncentrosome\ncentrosomes\ncentrosymmetric\ncentrum\ncentrums\ncents\ncentu\ncentum\ncentums\ncentuple\ncentupled\ncentuples\ncentupling\ncenturies\ncenturion\ncenturions\ncentury\nceorl\nceorlish\nceorls\ncep\ncepe\ncepes\ncephalad\ncephalexin\ncephalexins\ncephalic\ncephalically\ncephalin\ncephalins\ncephalization\ncephalizations\ncephalometric\ncephalometries\ncephalometry\ncephalopod\ncephalopods\ncephaloridine\ncephaloridines\ncephalosporin\ncephalosporins\ncephalothin\ncephalothins\ncephalothoraces\ncephalothorax\ncephalothoraxes\ncepheid\ncepheids\nceps\nceramal\nceramals\nceramic\nceramicist\nceramicists\nceramics\nceramist\nceramists\ncerastes\ncerate\ncerated\ncerates\nceratin\nceratins\nceratoid\nceratopsian\nceratopsians\ncercaria\ncercariae\ncercarial\ncercarias\ncerci\ncercis\ncercises\ncercus\ncere\ncereal\ncereals\ncerebella\ncerebellar\ncerebellum\ncerebellums\ncerebra\ncerebral\ncerebrally\ncerebrals\ncerebrate\ncerebrated\ncerebrates\ncerebrating\ncerebration\ncerebrations\ncerebric\ncerebroside\ncerebrosides\ncerebrospinal\ncerebrovascular\ncerebrum\ncerebrums\ncerecloth\ncerecloths\ncered\ncerement\ncerements\nceremonial\nceremonialism\nceremonialisms\nceremonialist\nceremonialists\nceremonially\nceremonials\nceremonies\nceremonious\nceremoniously\nceremoniousness\nceremoniousnesses\nceremony\nceres\ncereus\ncereuses\nceria\ncerias\nceric\ncering\nceriph\nceriphs\ncerise\ncerises\ncerite\ncerites\ncerium\nceriums\ncermet\ncermets\ncernuous\ncero\nceros\ncerotic\ncerotype\ncerotypes\ncerous\ncertain\ncertainer\ncertainest\ncertainly\ncertainties\ncertainty\ncertes\ncertifiable\ncertifiably\ncertificate\ncertificated\ncertificates\ncertificating\ncertification\ncertifications\ncertificatory\ncertified\ncertifier\ncertifiers\ncertifies\ncertify\ncertifying\ncertiorari\ncertioraris\ncertitude\ncertitudes\ncerulean\nceruleans\nceruloplasmin\nceruloplasmins\ncerumen\ncerumens\nceruminous\nceruse\nceruses\ncerusite\ncerusites\ncerussite\ncerussites\ncervelas\ncervelases\ncervelat\ncervelats\ncervical\ncervices\ncervicitis\ncervicitises\ncervid\ncervine\ncervix\ncervixes\ncesarean\ncesareans\ncesarian\ncesarians\ncesium\ncesiums\ncess\ncessation\ncessations\ncessed\ncesses\ncessing\ncession\ncessions\ncesspit\ncesspits\ncesspool\ncesspools\ncesta\ncestas\ncesti\ncestode\ncestodes\ncestoi\ncestoid\ncestoids\ncestos\ncestus\ncestuses\ncesura\ncesurae\ncesuras\ncetacean\ncetaceans\ncetaceous\ncetane\ncetanes\ncete\ncetes\ncetologies\ncetologist\ncetologists\ncetology\nceviche\nceviches\nchablis\nchabouk\nchabouks\nchabuk\nchabuks\nchacma\nchacmas\nchaconne\nchaconnes\nchad\nchadar\nchadarim\nchadars\nchadless\nchador\nchadors\nchadri\nchads\nchaeta\nchaetae\nchaetal\nchaetognath\nchaetognaths\nchafe\nchafed\nchafer\nchafers\nchafes\nchaff\nchaffed\nchaffer\nchaffered\nchafferer\nchafferers\nchaffering\nchaffers\nchaffier\nchaffiest\nchaffinch\nchaffinches\nchaffing\nchaffs\nchaffy\nchafing\nchagrin\nchagrined\nchagrining\nchagrinned\nchagrinning\nchagrins\nchain\nchaine\nchained\nchaines\nchaining\nchainman\nchainmen\nchains\nchainsaw\nchainsawed\nchainsawing\nchainsaws\nchainwheel\nchainwheels\nchair\nchaired\nchairing\nchairlift\nchairlifts\nchairman\nchairmaned\nchairmaning\nchairmanned\nchairmanning\nchairmans\nchairmanship\nchairmanships\nchairmen\nchairperson\nchairpersons\nchairs\nchairwoman\nchairwomen\nchaise\nchaises\nchakra\nchakras\nchalah\nchalahs\nchalaza\nchalazae\nchalazal\nchalazas\nchalazia\nchalazion\nchalazions\nchalcedonic\nchalcedonies\nchalcedony\nchalcid\nchalcids\nchalcocite\nchalcocites\nchalcogen\nchalcogenide\nchalcogenides\nchalcogens\nchalcopyrite\nchalcopyrites\nchaldron\nchaldrons\nchaleh\nchalehs\nchalet\nchalets\nchalice\nchaliced\nchalices\nchalk\nchalkboard\nchalkboards\nchalked\nchalkier\nchalkiest\nchalking\nchalks\nchalky\nchalla\nchallah\nchallahs\nchallas\nchallenge\nchallenged\nchallenger\nchallengers\nchallenges\nchallenging\nchallengingly\nchallie\nchallies\nchallis\nchallises\nchallot\nchalloth\nchally\nchalone\nchalones\nchalot\nchaloth\nchalutz\nchalutzim\nchalybeate\nchalybeates\ncham\nchamade\nchamades\nchamaephyte\nchamaephytes\nchamber\nchambered\nchambering\nchamberlain\nchamberlains\nchambermaid\nchambermaids\nchambers\nchambray\nchambrays\nchameleon\nchameleonic\nchameleonlike\nchameleons\nchamfer\nchamfered\nchamfering\nchamfers\nchamfron\nchamfrons\nchamise\nchamises\nchamiso\nchamisos\nchammied\nchammies\nchammy\nchammying\nchamois\nchamoised\nchamoises\nchamoising\nchamoix\nchamomile\nchamomiles\nchamp\nchampac\nchampacs\nchampagne\nchampagnes\nchampaign\nchampaigns\nchampak\nchampaks\nchamped\nchamper\nchampers\nchamperties\nchampertous\nchamperty\nchampignon\nchampignons\nchamping\nchampion\nchampioned\nchampioning\nchampions\nchampionship\nchampionships\nchampleve\nchampleves\nchamps\nchampy\nchams\nchance\nchanced\nchanceful\nchancel\nchancelleries\nchancellery\nchancellor\nchancellories\nchancellors\nchancellorship\nchancellorships\nchancellory\nchancels\nchanceries\nchancery\nchances\nchancier\nchanciest\nchancily\nchanciness\nchancinesses\nchancing\nchancre\nchancres\nchancroid\nchancroidal\nchancroids\nchancrous\nchancy\nchandelier\nchandeliered\nchandeliers\nchandelle\nchandelled\nchandelles\nchandelling\nchandler\nchandleries\nchandlers\nchandlery\nchanfron\nchanfrons\nchang\nchange\nchangeabilities\nchangeability\nchangeable\nchangeableness\nchangeablenesses\nchangeably\nchanged\nchangeful\nchangefully\nchangefulness\nchangefulnesses\nchangeless\nchangelessly\nchangelessness\nchangelessnesses\nchangeling\nchangelings\nchangeover\nchangeovers\nchanger\nchangers\nchanges\nchanging\nchangs\nchannel\nchanneled\nchanneler\nchannelers\nchanneling\nchannelization\nchannelizations\nchannelize\nchannelized\nchannelizes\nchannelizing\nchannelled\nchannelling\nchannels\nchanson\nchansonnier\nchansonniers\nchansons\nchant\nchantage\nchantages\nchanted\nchanter\nchanterelle\nchanterelles\nchanters\nchanteuse\nchanteuses\nchantey\nchanteys\nchanticleer\nchanticleers\nchanties\nchanting\nchantor\nchantors\nchantries\nchantry\nchants\nchanty\nchao\nchaos\nchaoses\nchaotic\nchaotically\nchap\nchaparajos\nchaparejos\nchaparral\nchaparrals\nchapati\nchapaties\nchapatis\nchapatti\nchapatties\nchapattis\nchapbook\nchapbooks\nchape\nchapeau\nchapeaus\nchapeaux\nchapel\nchapels\nchaperon\nchaperonage\nchaperonages\nchaperone\nchaperoned\nchaperones\nchaperoning\nchaperons\nchapes\nchapfallen\nchapiter\nchapiters\nchaplain\nchaplaincies\nchaplaincy\nchaplains\nchaplet\nchapleted\nchaplets\nchapman\nchapmen\nchappati\nchappatis\nchapped\nchapping\nchaps\nchapt\nchapter\nchaptered\nchaptering\nchapters\nchaqueta\nchaquetas\nchar\ncharabanc\ncharabancs\ncharacid\ncharacids\ncharacin\ncharacins\ncharacter\ncharactered\ncharacterful\ncharacteries\ncharactering\ncharacteristic\ncharacteristically\ncharacteristics\ncharacterization\ncharacterizations\ncharacterize\ncharacterized\ncharacterizes\ncharacterizing\ncharacterless\ncharacterological\ncharacterologically\ncharacters\ncharactery\ncharade\ncharades\ncharas\ncharases\ncharbroil\ncharbroiled\ncharbroiler\ncharbroilers\ncharbroiling\ncharbroils\ncharcoal\ncharcoaled\ncharcoaling\ncharcoals\ncharcuterie\ncharcuteries\nchard\nchardonnay\nchardonnays\nchards\nchare\nchared\nchares\ncharge\nchargeable\ncharged\nchargehand\nchargehands\ncharger\nchargers\ncharges\ncharging\ncharier\nchariest\ncharily\nchariness\ncharinesses\ncharing\nchariot\ncharioted\ncharioteer\ncharioteers\ncharioting\nchariots\ncharism\ncharisma\ncharismata\ncharismatic\ncharismatics\ncharisms\ncharitable\ncharitableness\ncharitablenesses\ncharitably\ncharities\ncharity\ncharivari\ncharivaris\nchark\ncharka\ncharkas\ncharked\ncharkha\ncharkhas\ncharking\ncharks\ncharladies\ncharlady\ncharlatan\ncharlatanism\ncharlatanisms\ncharlatanries\ncharlatanry\ncharlatans\ncharley\ncharleys\ncharlie\ncharlies\ncharlock\ncharlocks\ncharlotte\ncharlottes\ncharm\ncharmed\ncharmer\ncharmers\ncharmeuse\ncharmeuses\ncharming\ncharminger\ncharmingest\ncharmingly\ncharmless\ncharms\ncharnel\ncharnels\ncharpai\ncharpais\ncharpoy\ncharpoys\ncharqui\ncharquid\ncharquis\ncharr\ncharred\ncharrier\ncharriest\ncharring\ncharro\ncharros\ncharrs\ncharry\nchars\nchart\ncharted\ncharter\nchartered\ncharterer\ncharterers\nchartering\ncharters\ncharting\nchartist\nchartists\nchartreuse\nchartreuses\ncharts\nchartularies\nchartulary\ncharwoman\ncharwomen\nchary\nchase\nchased\nchaser\nchasers\nchases\nchasing\nchasings\nchasm\nchasmal\nchasmed\nchasmic\nchasms\nchasmy\nchasse\nchassed\nchasseing\nchassepot\nchassepots\nchasses\nchasseur\nchasseurs\nchassis\nchaste\nchastely\nchasten\nchastened\nchastener\nchasteners\nchasteness\nchastenesses\nchastening\nchastens\nchaster\nchastest\nchastise\nchastised\nchastisement\nchastisements\nchastiser\nchastisers\nchastises\nchastising\nchastities\nchastity\nchasuble\nchasubles\nchat\nchatchka\nchatchkas\nchatchke\nchatchkes\nchateau\nchateaubriand\nchateaubriands\nchateaus\nchateaux\nchatelain\nchatelaine\nchatelaines\nchatelains\nchatoyance\nchatoyances\nchatoyancies\nchatoyancy\nchatoyant\nchatoyants\nchats\nchatted\nchattel\nchattels\nchatter\nchatterbox\nchatterboxes\nchattered\nchatterer\nchatterers\nchattering\nchatters\nchattery\nchattier\nchattiest\nchattily\nchattiness\nchattinesses\nchatting\nchatty\nchaufer\nchaufers\nchauffer\nchauffers\nchauffeur\nchauffeured\nchauffeuring\nchauffeurs\nchaulmoogra\nchaulmoogras\nchaunt\nchaunted\nchaunter\nchaunters\nchaunting\nchaunts\nchausses\nchaussure\nchaussures\nchautauqua\nchautauquas\nchauvinism\nchauvinisms\nchauvinist\nchauvinistic\nchauvinistically\nchauvinists\nchaw\nchawbacon\nchawbacons\nchawed\nchawer\nchawers\nchawing\nchaws\nchay\nchayote\nchayotes\nchays\nchazan\nchazanim\nchazans\nchazzan\nchazzanim\nchazzans\nchazzen\nchazzenim\nchazzens\ncheap\ncheapen\ncheapened\ncheapening\ncheapens\ncheaper\ncheapest\ncheapie\ncheapies\ncheapish\ncheapishly\ncheapjack\ncheapjacks\ncheaply\ncheapness\ncheapnesses\ncheapo\ncheapos\ncheaps\ncheapskate\ncheapskates\ncheat\ncheated\ncheater\ncheaters\ncheating\ncheats\nchebec\nchebecs\nchechako\nchechakos\ncheck\ncheckable\ncheckbook\ncheckbooks\nchecked\nchecker\ncheckerberries\ncheckerberry\ncheckerboard\ncheckerboards\ncheckered\ncheckering\ncheckers\nchecking\ncheckless\nchecklist\nchecklists\ncheckmark\ncheckmarked\ncheckmarking\ncheckmarks\ncheckmate\ncheckmated\ncheckmates\ncheckmating\ncheckoff\ncheckoffs\ncheckout\ncheckouts\ncheckpoint\ncheckpoints\ncheckrein\ncheckreins\ncheckroom\ncheckrooms\ncheckrow\ncheckrowed\ncheckrowing\ncheckrows\nchecks\ncheckup\ncheckups\nchedarim\ncheddar\ncheddars\ncheddite\ncheddites\ncheder\ncheders\nchedite\nchedites\ncheechako\ncheechakos\ncheek\ncheekbone\ncheekbones\ncheeked\ncheekful\ncheekfuls\ncheekier\ncheekiest\ncheekily\ncheekiness\ncheekinesses\ncheeking\ncheeks\ncheeky\ncheep\ncheeped\ncheeper\ncheepers\ncheeping\ncheeps\ncheer\ncheered\ncheerer\ncheerers\ncheerful\ncheerfuller\ncheerfullest\ncheerfully\ncheerfulness\ncheerfulnesses\ncheerier\ncheeriest\ncheerily\ncheeriness\ncheerinesses\ncheering\ncheerio\ncheerios\ncheerlead\ncheerleader\ncheerleaders\ncheerleading\ncheerleads\ncheerled\ncheerless\ncheerlessly\ncheerlessness\ncheerlessnesses\ncheerly\ncheero\ncheeros\ncheers\ncheery\ncheese\ncheeseburger\ncheeseburgers\ncheesecake\ncheesecakes\ncheesecloth\ncheesecloths\ncheesed\ncheeseparing\ncheeseparings\ncheeses\ncheesier\ncheesiest\ncheesily\ncheesiness\ncheesinesses\ncheesing\ncheesy\ncheetah\ncheetahs\nchef\nchefdom\nchefdoms\ncheffed\ncheffing\nchefs\nchegoe\nchegoes\nchela\nchelae\nchelas\nchelatable\nchelate\nchelated\nchelates\nchelating\nchelation\nchelations\nchelator\nchelators\nchelicera\nchelicerae\ncheliceral\ncheliped\nchelipeds\ncheloid\ncheloids\nchelonian\nchelonians\nchemic\nchemical\nchemically\nchemicals\nchemics\nchemiluminescence\nchemiluminescences\nchemiluminescent\nchemiosmotic\nchemise\nchemises\nchemisette\nchemisettes\nchemism\nchemisms\nchemisorb\nchemisorbed\nchemisorbing\nchemisorbs\nchemisorption\nchemisorptions\nchemist\nchemistries\nchemistry\nchemists\nchemo\nchemoautotrophic\nchemoautotrophies\nchemoautotrophy\nchemoprophylactic\nchemoprophylaxes\nchemoprophylaxis\nchemoreception\nchemoreceptions\nchemoreceptive\nchemoreceptor\nchemoreceptors\nchemos\nchemosurgeries\nchemosurgery\nchemosurgical\nchemosyntheses\nchemosynthesis\nchemosynthetic\nchemotactic\nchemotactically\nchemotaxes\nchemotaxis\nchemotaxonomic\nchemotaxonomies\nchemotaxonomist\nchemotaxonomists\nchemotaxonomy\nchemotherapeutic\nchemotherapeutically\nchemotherapeutics\nchemotherapies\nchemotherapist\nchemotherapists\nchemotherapy\nchemotropism\nchemotropisms\nchemurgies\nchemurgy\nchenille\nchenilles\nchenopod\nchenopods\ncheongsam\ncheongsams\ncheque\nchequer\nchequered\nchequering\nchequers\ncheques\ncherimoya\ncherimoyas\ncherish\ncherishable\ncherished\ncherisher\ncherishers\ncherishes\ncherishing\nchernozem\nchernozemic\nchernozems\ncheroot\ncheroots\ncherries\ncherry\ncherrylike\ncherrystone\ncherrystones\nchert\nchertier\nchertiest\ncherts\ncherty\ncherub\ncherubic\ncherubically\ncherubim\ncherubims\ncherublike\ncherubs\nchervil\nchervils\nchess\nchessboard\nchessboards\nchesses\nchessman\nchessmen\nchest\nchested\nchesterfield\nchesterfields\nchestful\nchestfuls\nchestier\nchestiest\nchestnut\nchestnuts\nchests\nchesty\nchetah\nchetahs\ncheth\ncheths\nchetrum\nchetrums\nchevalet\nchevalets\nchevalier\nchevaliers\nchevelure\nchevelures\ncheveron\ncheverons\nchevied\nchevies\ncheviot\ncheviots\nchevre\nchevres\nchevron\nchevrons\nchevy\nchevying\nchew\nchewable\nchewed\nchewer\nchewers\nchewier\nchewiest\nchewing\nchewink\nchewinks\nchews\nchewy\nchez\nchi\nchia\nchiao\nchiaroscurist\nchiaroscurists\nchiaroscuro\nchiaroscuros\nchias\nchiasm\nchiasma\nchiasmal\nchiasmas\nchiasmata\nchiasmatic\nchiasmi\nchiasmic\nchiasms\nchiasmus\nchiastic\nchiaus\nchiauses\nchibouk\nchibouks\nchibouque\nchibouques\nchic\nchicane\nchicaned\nchicaner\nchicaneries\nchicaners\nchicanery\nchicanes\nchicaning\nchicano\nchicanos\nchiccories\nchiccory\nchicer\nchicest\nchichi\nchichis\nchick\nchickadee\nchickadees\nchickaree\nchickarees\nchickee\nchickees\nchicken\nchickened\nchickenhearted\nchickening\nchickenpox\nchickenpoxes\nchickens\nchickenshit\nchickenshits\nchickories\nchickory\nchickpea\nchickpeas\nchicks\nchickweed\nchickweeds\nchicle\nchicles\nchicly\nchicness\nchicnesses\nchico\nchicories\nchicory\nchicos\nchics\nchid\nchidden\nchide\nchided\nchider\nchiders\nchides\nchiding\nchief\nchiefdom\nchiefdoms\nchiefer\nchiefest\nchiefly\nchiefs\nchiefship\nchiefships\nchieftain\nchieftaincies\nchieftaincy\nchieftains\nchieftainship\nchieftainships\nchiel\nchield\nchields\nchiels\nchiffchaff\nchiffchaffs\nchiffon\nchiffonade\nchiffonades\nchiffonier\nchiffoniers\nchiffons\nchifforobe\nchifforobes\nchigetai\nchigetais\nchigger\nchiggers\nchignon\nchignons\nchigoe\nchigoes\nchihuahua\nchihuahuas\nchilblain\nchilblains\nchild\nchildbearing\nchildbearings\nchildbed\nchildbeds\nchildbirth\nchildbirths\nchilde\nchildes\nchildhood\nchildhoods\nchilding\nchildish\nchildishly\nchildishness\nchildishnesses\nchildless\nchildlessness\nchildlessnesses\nchildlier\nchildliest\nchildlike\nchildlikeness\nchildlikenesses\nchildly\nchildproof\nchildproofed\nchildproofing\nchildproofs\nchildren\nchile\nchiles\nchili\nchiliad\nchiliads\nchiliasm\nchiliasms\nchiliast\nchiliastic\nchiliasts\nchilidog\nchilidogs\nchilies\nchilis\nchill\nchilled\nchiller\nchillers\nchillest\nchilli\nchillier\nchillies\nchilliest\nchillily\nchilliness\nchillinesses\nchilling\nchillingly\nchillness\nchillnesses\nchills\nchillum\nchillums\nchilly\nchilopod\nchilopods\nchimaera\nchimaeras\nchimaeric\nchimaerism\nchimaerisms\nchimar\nchimars\nchimb\nchimbley\nchimbleys\nchimblies\nchimbly\nchimbs\nchime\nchimed\nchimer\nchimera\nchimeras\nchimere\nchimeres\nchimeric\nchimerical\nchimerically\nchimerism\nchimerisms\nchimers\nchimes\nchimichanga\nchimichangas\nchiming\nchimla\nchimlas\nchimley\nchimleys\nchimney\nchimneylike\nchimneypiece\nchimneypieces\nchimneys\nchimp\nchimpanzee\nchimpanzees\nchimps\nchin\nchina\nchinaberries\nchinaberry\nchinas\nchinaware\nchinawares\nchinbone\nchinbones\nchinch\nchincherinchee\nchincherinchees\nchinches\nchinchier\nchinchiest\nchinchilla\nchinchillas\nchinchy\nchine\nchined\nchines\nchining\nchink\nchinkapin\nchinkapins\nchinked\nchinkier\nchinkiest\nchinking\nchinks\nchinky\nchinless\nchinned\nchinning\nchino\nchinoiserie\nchinoiseries\nchinone\nchinones\nchinook\nchinooks\nchinos\nchinquapin\nchinquapins\nchins\nchints\nchintses\nchintz\nchintzes\nchintzier\nchintziest\nchintzy\nchionodoxa\nchionodoxas\nchip\nchipboard\nchipboards\nchipmuck\nchipmucks\nchipmunk\nchipmunks\nchipped\nchipper\nchippered\nchippering\nchippers\nchippie\nchippier\nchippies\nchippiest\nchipping\nchippy\nchips\nchiral\nchiralities\nchirality\nchirimoya\nchirimoyas\nchirk\nchirked\nchirker\nchirkest\nchirking\nchirks\nchirm\nchirmed\nchirming\nchirms\nchiro\nchirographer\nchirographers\nchirographic\nchirographical\nchirographies\nchirography\nchiromancer\nchiromancers\nchiromancies\nchiromancy\nchironomid\nchironomids\nchiropodies\nchiropodist\nchiropodists\nchiropody\nchiropractic\nchiropractics\nchiropractor\nchiropractors\nchiropteran\nchiropterans\nchiros\nchirp\nchirped\nchirper\nchirpers\nchirpier\nchirpiest\nchirpily\nchirping\nchirps\nchirpy\nchirr\nchirre\nchirred\nchirres\nchirring\nchirrs\nchirrup\nchirruped\nchirruping\nchirrups\nchirrupy\nchirurgeon\nchirurgeons\nchis\nchisel\nchiseled\nchiseler\nchiselers\nchiseling\nchiselled\nchiseller\nchisellers\nchiselling\nchisels\nchit\nchital\nchitals\nchitchat\nchitchats\nchitchatted\nchitchatting\nchitin\nchitinous\nchitins\nchitlin\nchitling\nchitlings\nchitlins\nchiton\nchitons\nchitosan\nchitosans\nchits\nchitter\nchittered\nchittering\nchitterlings\nchitters\nchitties\nchitty\nchivalric\nchivalries\nchivalrous\nchivalrously\nchivalrousness\nchivalrousnesses\nchivalry\nchivaree\nchivareed\nchivareeing\nchivarees\nchivari\nchivaried\nchivaries\nchivariing\nchive\nchives\nchivied\nchivies\nchivvied\nchivvies\nchivvy\nchivvying\nchivy\nchivying\nchlamydes\nchlamydia\nchlamydiae\nchlamydial\nchlamydospore\nchlamydospores\nchlamys\nchlamyses\nchloasma\nchloasmata\nchloracne\nchloracnes\nchloral\nchloralose\nchloralosed\nchloraloses\nchlorals\nchloramine\nchloramines\nchloramphenicol\nchloramphenicols\nchlorate\nchlorates\nchlordan\nchlordane\nchlordanes\nchlordans\nchlordiazepoxide\nchlordiazepoxides\nchlorella\nchlorellas\nchlorenchyma\nchlorenchymas\nchlorenchymata\nchloric\nchlorid\nchloride\nchlorides\nchlorids\nchlorin\nchlorinate\nchlorinated\nchlorinates\nchlorinating\nchlorination\nchlorinations\nchlorinator\nchlorinators\nchlorine\nchlorines\nchlorinities\nchlorinity\nchlorins\nchlorite\nchlorites\nchloritic\nchlorobenzene\nchlorobenzenes\nchlorofluorocarbon\nchlorofluorocarbons\nchlorofluoromethane\nchlorofluoromethanes\nchloroform\nchloroformed\nchloroforming\nchloroforms\nchlorohydrin\nchlorohydrins\nchlorophyll\nchlorophyllous\nchlorophylls\nchloropicrin\nchloropicrins\nchloroplast\nchloroplastic\nchloroplasts\nchloroprene\nchloroprenes\nchloroquine\nchloroquines\nchloroses\nchlorosis\nchlorothiazide\nchlorothiazides\nchlorotic\nchlorous\nchlorpromazine\nchlorpromazines\nchlorpropamide\nchlorpropamides\nchlortetracycline\nchlortetracyclines\nchoana\nchoanae\nchoanocyte\nchoanocytes\nchock\nchockablock\nchocked\nchockful\nchocking\nchocks\nchocoholic\nchocoholics\nchocolate\nchocolates\nchocolatey\nchocolatier\nchocolatiers\nchocolaty\nchoice\nchoicely\nchoiceness\nchoicenesses\nchoicer\nchoices\nchoicest\nchoir\nchoirboy\nchoirboys\nchoired\nchoiring\nchoirmaster\nchoirmasters\nchoirs\nchoke\nchokeberries\nchokeberry\nchokecherries\nchokecherry\nchoked\nchokehold\nchokeholds\nchoker\nchokers\nchokes\nchokey\nchokier\nchokiest\nchoking\nchokingly\nchoky\ncholangiogram\ncholangiograms\ncholangiographic\ncholangiographies\ncholangiography\ncholate\ncholates\ncholecalciferol\ncholecalciferols\ncholecystectomies\ncholecystectomized\ncholecystectomy\ncholecystitides\ncholecystitis\ncholecystokinin\ncholecystokinins\ncholelithiases\ncholelithiasis\ncholent\ncholents\ncholer\ncholera\ncholeras\ncholeric\ncholerically\ncholers\ncholestases\ncholestasis\ncholestatic\ncholesteric\ncholesterol\ncholesterols\ncholestyramine\ncholestyramines\ncholine\ncholinergic\ncholinergically\ncholines\ncholinesterase\ncholinesterases\ncholla\nchollas\ncholo\ncholos\nchomp\nchomped\nchomper\nchompers\nchomping\nchomps\nchon\nchondriosome\nchondriosomes\nchondrite\nchondrites\nchondritic\nchondrocrania\nchondrocranium\nchondrocraniums\nchondroitin\nchondroitins\nchondrule\nchondrules\nchook\nchooks\nchoose\nchooser\nchoosers\nchooses\nchoosey\nchoosier\nchoosiest\nchoosing\nchoosy\nchop\nchopfallen\nchophouse\nchophouses\nchopin\nchopine\nchopines\nchopins\nchoplogic\nchoplogics\nchopped\nchopper\nchoppered\nchoppering\nchoppers\nchoppier\nchoppiest\nchoppily\nchoppiness\nchoppinesses\nchopping\nchoppy\nchops\nchopstick\nchopsticks\nchoragi\nchoragic\nchoragus\nchoraguses\nchoral\nchorale\nchorales\nchorally\nchorals\nchord\nchordal\nchordamesoderm\nchordamesodermal\nchordamesoderms\nchordate\nchordates\nchorded\nchording\nchords\nchore\nchorea\nchoreal\nchoreas\nchored\nchoregi\nchoregus\nchoreguses\nchoreic\nchoreiform\nchoreman\nchoremen\nchoreograph\nchoreographed\nchoreographer\nchoreographers\nchoreographic\nchoreographically\nchoreographies\nchoreographing\nchoreographs\nchoreography\nchoreoid\nchores\nchorial\nchoriamb\nchoriambs\nchoric\nchorine\nchorines\nchoring\nchorioallantoic\nchorioallantoides\nchorioallantois\nchoriocarcinoma\nchoriocarcinomas\nchoriocarcinomata\nchorioid\nchorioids\nchorion\nchorionic\nchorions\nchorister\nchoristers\nchorizo\nchorizos\nchorographer\nchorographers\nchorographic\nchorographies\nchorography\nchoroid\nchoroidal\nchoroids\nchortle\nchortled\nchortler\nchortlers\nchortles\nchortling\nchorus\nchorused\nchoruses\nchorusing\nchorussed\nchorusses\nchorussing\nchose\nchosen\nchoses\nchott\nchotts\nchough\nchoughs\nchouse\nchoused\nchouser\nchousers\nchouses\nchoush\nchoushes\nchousing\nchow\nchowchow\nchowchows\nchowder\nchowdered\nchowderhead\nchowderheaded\nchowderheads\nchowdering\nchowders\nchowed\nchowhound\nchowhounds\nchowing\nchows\nchowse\nchowsed\nchowses\nchowsing\nchowtime\nchowtimes\nchresard\nchresards\nchrestomathies\nchrestomathy\nchrism\nchrisma\nchrismal\nchrismation\nchrismations\nchrismon\nchrismons\nchrisms\nchrisom\nchrisoms\nchristen\nchristened\nchristening\nchristenings\nchristens\nchristiania\nchristianias\nchristie\nchristies\nchristy\nchroma\nchromaffin\nchromas\nchromate\nchromates\nchromatic\nchromatically\nchromaticism\nchromaticisms\nchromaticities\nchromaticity\nchromatics\nchromatid\nchromatids\nchromatin\nchromatinic\nchromatins\nchromatogram\nchromatograms\nchromatograph\nchromatographed\nchromatographer\nchromatographers\nchromatographic\nchromatographically\nchromatographies\nchromatographing\nchromatographs\nchromatography\nchromatolyses\nchromatolysis\nchromatolytic\nchromatophore\nchromatophores\nchrome\nchromed\nchromes\nchromic\nchromide\nchromides\nchrominance\nchrominances\nchroming\nchromings\nchromite\nchromites\nchromium\nchromiums\nchromize\nchromized\nchromizes\nchromizing\nchromo\nchromocenter\nchromocenters\nchromodynamics\nchromogen\nchromogenic\nchromogens\nchromolithograph\nchromolithographed\nchromolithographer\nchromolithographers\nchromolithographic\nchromolithographies\nchromolithographing\nchromolithographs\nchromolithography\nchromomere\nchromomeres\nchromomeric\nchromonema\nchromonemata\nchromonematic\nchromophil\nchromophobe\nchromophore\nchromophores\nchromophoric\nchromoplast\nchromoplasts\nchromoprotein\nchromoproteins\nchromos\nchromosomal\nchromosomally\nchromosome\nchromosomes\nchromosphere\nchromospheres\nchromospheric\nchromous\nchromyl\nchromyls\nchronaxie\nchronaxies\nchronaxy\nchronic\nchronically\nchronicities\nchronicity\nchronicle\nchronicled\nchronicler\nchroniclers\nchronicles\nchronicling\nchronics\nchronobiologic\nchronobiological\nchronobiologies\nchronobiologist\nchronobiologists\nchronobiology\nchronogram\nchronograms\nchronograph\nchronographic\nchronographies\nchronographs\nchronography\nchronologer\nchronologers\nchronologic\nchronological\nchronologically\nchronologies\nchronologist\nchronologists\nchronology\nchronometer\nchronometers\nchronometric\nchronometrical\nchronometrically\nchronometries\nchronometry\nchronon\nchronons\nchronotherapies\nchronotherapy\nchrysalid\nchrysalides\nchrysalids\nchrysalis\nchrysalises\nchrysanthemum\nchrysanthemums\nchrysarobin\nchrysarobins\nchrysoberyl\nchrysoberyls\nchrysolite\nchrysolites\nchrysomelid\nchrysomelids\nchrysophyte\nchrysophytes\nchrysoprase\nchrysoprases\nchrysotile\nchrysotiles\nchthonian\nchthonic\nchub\nchubasco\nchubascos\nchubbier\nchubbiest\nchubbily\nchubbiness\nchubbinesses\nchubby\nchubs\nchuck\nchuckawalla\nchuckawallas\nchucked\nchuckhole\nchuckholes\nchuckies\nchucking\nchuckle\nchuckled\nchucklehead\nchuckleheaded\nchuckleheads\nchuckler\nchucklers\nchuckles\nchucklesome\nchuckling\nchucklingly\nchucks\nchuckwalla\nchuckwallas\nchucky\nchuddah\nchuddahs\nchuddar\nchuddars\nchudder\nchudders\nchufa\nchufas\nchuff\nchuffed\nchuffer\nchuffest\nchuffier\nchuffiest\nchuffing\nchuffs\nchuffy\nchug\nchugalug\nchugalugged\nchugalugging\nchugalugs\nchugged\nchugger\nchuggers\nchugging\nchugs\nchukar\nchukars\nchukka\nchukkar\nchukkars\nchukkas\nchukker\nchukkers\nchum\nchummed\nchummier\nchummiest\nchummily\nchumminess\nchumminesses\nchumming\nchummy\nchump\nchumped\nchumping\nchumps\nchums\nchumship\nchumships\nchunk\nchunked\nchunkier\nchunkiest\nchunkily\nchunking\nchunks\nchunky\nchunter\nchuntered\nchuntering\nchunters\nchurch\nchurched\nchurches\nchurchgoer\nchurchgoers\nchurchgoing\nchurchgoings\nchurchianities\nchurchianity\nchurchier\nchurchiest\nchurching\nchurchings\nchurchless\nchurchlier\nchurchliest\nchurchliness\nchurchlinesses\nchurchly\nchurchman\nchurchmanship\nchurchmanships\nchurchmen\nchurchwarden\nchurchwardens\nchurchwoman\nchurchwomen\nchurchy\nchurchyard\nchurchyards\nchurl\nchurlish\nchurlishly\nchurlishness\nchurlishnesses\nchurls\nchurn\nchurned\nchurner\nchurners\nchurning\nchurnings\nchurns\nchurr\nchurred\nchurrigueresque\nchurring\nchurrs\nchute\nchuted\nchutes\nchuting\nchutist\nchutists\nchutnee\nchutnees\nchutney\nchutneys\nchutzpa\nchutzpah\nchutzpahs\nchutzpas\nchyle\nchyles\nchylomicron\nchylomicrons\nchylous\nchyme\nchymes\nchymic\nchymics\nchymist\nchymists\nchymosin\nchymosins\nchymotrypsin\nchymotrypsinogen\nchymotrypsinogens\nchymotrypsins\nchymotryptic\nchymous\nciao\ncibol\ncibols\nciboria\nciborium\nciboule\nciboules\ncicada\ncicadae\ncicadas\ncicala\ncicalas\ncicale\ncicatrices\ncicatricial\ncicatrix\ncicatrixes\ncicatrization\ncicatrizations\ncicatrize\ncicatrized\ncicatrizes\ncicatrizing\ncicelies\ncicely\ncicero\ncicerone\ncicerones\nciceroni\nciceros\ncichlid\ncichlidae\ncichlids\ncicisbei\ncicisbeism\ncicisbeisms\ncicisbeo\ncicisbeos\ncicoree\ncicorees\ncider\nciders\ncig\ncigar\ncigaret\ncigarets\ncigarette\ncigarettes\ncigarillo\ncigarillos\ncigars\ncigs\nciguatera\nciguateras\ncilantro\ncilantros\ncilia\nciliary\nciliate\nciliated\nciliates\nciliation\nciliations\ncilice\ncilices\ncilium\ncimbalom\ncimbaloms\ncimetidine\ncimetidines\ncimex\ncimices\ncinch\ncinched\ncinches\ncinching\ncinchona\ncinchonas\ncinchonine\ncinchonines\ncinchonism\ncinchonisms\ncincture\ncinctured\ncinctures\ncincturing\ncinder\ncinderblock\ncinderblocks\ncindered\ncindering\ncinders\ncindery\ncine\ncineast\ncineaste\ncineastes\ncineasts\ncinema\ncinemagoer\ncinemagoers\ncinemas\ncinematheque\ncinematheques\ncinematic\ncinematically\ncinematize\ncinematized\ncinematizes\ncinematizing\ncinematograph\ncinematographer\ncinematographers\ncinematographic\ncinematographically\ncinematographies\ncinematographs\ncinematography\ncineol\ncineole\ncineoles\ncineols\ncineplex\ncineplexes\ncineraria\ncinerarias\ncinerarium\ncinerary\ncinereous\ncinerin\ncinerins\ncines\ncingula\ncingulate\ncingulum\ncinnabar\ncinnabarine\ncinnabars\ncinnamic\ncinnamon\ncinnamons\ncinnamyl\ncinnamyls\ncinquain\ncinquains\ncinque\ncinquecentist\ncinquecentisti\ncinquecentists\ncinquecento\ncinquecentos\ncinquefoil\ncinquefoils\ncinques\ncion\ncions\ncioppino\ncioppinos\ncipher\nciphered\nciphering\nciphers\nciphertext\nciphertexts\nciphonies\nciphony\ncipolin\ncipolins\ncirca\ncircadian\ncircinate\ncircinately\ncircle\ncircled\ncircler\ncirclers\ncircles\ncirclet\ncirclets\ncircling\ncircuit\ncircuital\ncircuited\ncircuities\ncircuiting\ncircuitous\ncircuitously\ncircuitousness\ncircuitousnesses\ncircuitries\ncircuitry\ncircuits\ncircuity\ncircular\ncircularise\ncircularised\ncircularises\ncircularising\ncircularities\ncircularity\ncircularization\ncircularizations\ncircularize\ncircularized\ncircularizes\ncircularizing\ncircularly\ncircularness\ncircularnesses\ncirculars\ncirculatable\ncirculate\ncirculated\ncirculates\ncirculating\ncirculation\ncirculations\ncirculative\ncirculator\ncirculators\ncirculatory\ncircumambient\ncircumambiently\ncircumambulate\ncircumambulated\ncircumambulates\ncircumambulating\ncircumambulation\ncircumambulations\ncircumcenter\ncircumcenters\ncircumcircle\ncircumcircles\ncircumcise\ncircumcised\ncircumciser\ncircumcisers\ncircumcises\ncircumcising\ncircumcision\ncircumcisions\ncircumference\ncircumferences\ncircumferential\ncircumflex\ncircumflexes\ncircumfluent\ncircumfluous\ncircumfuse\ncircumfused\ncircumfuses\ncircumfusing\ncircumfusion\ncircumfusions\ncircumjacent\ncircumlocution\ncircumlocutions\ncircumlocutory\ncircumlunar\ncircumnavigate\ncircumnavigated\ncircumnavigates\ncircumnavigating\ncircumnavigation\ncircumnavigations\ncircumnavigator\ncircumnavigators\ncircumpolar\ncircumscissile\ncircumscribe\ncircumscribed\ncircumscribes\ncircumscribing\ncircumscription\ncircumscriptions\ncircumspect\ncircumspection\ncircumspections\ncircumspectly\ncircumstance\ncircumstanced\ncircumstances\ncircumstantial\ncircumstantialities\ncircumstantiality\ncircumstantially\ncircumstantiate\ncircumstantiated\ncircumstantiates\ncircumstantiating\ncircumstellar\ncircumvallate\ncircumvallated\ncircumvallates\ncircumvallating\ncircumvallation\ncircumvallations\ncircumvent\ncircumvented\ncircumventing\ncircumvention\ncircumventions\ncircumvents\ncircumvolution\ncircumvolutions\ncircus\ncircuses\ncircusy\ncire\ncires\ncirque\ncirques\ncirrate\ncirrhoses\ncirrhosis\ncirrhotic\ncirrhotics\ncirri\ncirriped\ncirripeds\ncirrocumuli\ncirrocumulus\ncirrose\ncirrostrati\ncirrostratus\ncirrous\ncirrus\ncirsoid\ncis\ncisalpine\ncisco\nciscoes\nciscos\ncislunar\ncisplatin\ncisplatins\ncissies\ncissoid\ncissoids\ncissy\ncist\ncistern\ncisterna\ncisternae\ncisternal\ncisterns\ncistron\ncistronic\ncistrons\ncists\ncistus\ncistuses\ncitable\ncitadel\ncitadels\ncitation\ncitational\ncitations\ncitator\ncitators\ncitatory\ncite\nciteable\ncited\nciter\nciters\ncites\ncithara\ncitharas\ncither\ncithern\ncitherns\ncithers\ncithren\ncithrens\ncitied\ncities\ncitification\ncitifications\ncitified\ncitifies\ncitify\ncitifying\nciting\ncitizen\ncitizeness\ncitizenesses\ncitizenly\ncitizenries\ncitizenry\ncitizens\ncitizenship\ncitizenships\ncitola\ncitolas\ncitole\ncitoles\ncitral\ncitrals\ncitrate\ncitrated\ncitrates\ncitreous\ncitric\ncitriculture\ncitricultures\ncitriculturist\ncitriculturists\ncitrin\ncitrine\ncitrines\ncitrinin\ncitrinins\ncitrins\ncitron\ncitronella\ncitronellal\ncitronellals\ncitronellas\ncitronellol\ncitronellols\ncitrons\ncitrous\ncitrulline\ncitrullines\ncitrus\ncitruses\ncitrusy\ncittern\ncitterns\ncity\ncityfied\ncityscape\ncityscapes\ncityward\ncitywide\ncivet\ncivets\ncivic\ncivically\ncivicism\ncivicisms\ncivics\ncivie\ncivies\ncivil\ncivilian\ncivilianization\ncivilianizations\ncivilianize\ncivilianized\ncivilianizes\ncivilianizing\ncivilians\ncivilisation\ncivilisations\ncivilise\ncivilised\ncivilises\ncivilising\ncivilities\ncivility\ncivilization\ncivilizational\ncivilizations\ncivilize\ncivilized\ncivilizer\ncivilizers\ncivilizes\ncivilizing\ncivilly\ncivism\ncivisms\ncivvies\ncivvy\nclabber\nclabbered\nclabbering\nclabbers\nclach\nclachan\nclachans\nclachs\nclack\nclacked\nclacker\nclackers\nclacking\nclacks\nclad\ncladding\ncladdings\nclade\nclades\ncladist\ncladistic\ncladistically\ncladistics\ncladists\ncladoceran\ncladocerans\ncladode\ncladodes\ncladodial\ncladogeneses\ncladogenesis\ncladogenetic\ncladogenetically\ncladogram\ncladograms\ncladophyll\ncladophylla\ncladophylls\ncladophyllum\nclads\nclag\nclagged\nclagging\nclags\nclaim\nclaimable\nclaimant\nclaimants\nclaimed\nclaimer\nclaimers\nclaiming\nclaims\nclairaudience\nclairaudiences\nclairaudient\nclairaudiently\nclairvoyance\nclairvoyances\nclairvoyant\nclairvoyantly\nclairvoyants\nclam\nclamant\nclamantly\nclambake\nclambakes\nclamber\nclambered\nclamberer\nclamberers\nclambering\nclambers\nclammed\nclammer\nclammers\nclammier\nclammiest\nclammily\nclamminess\nclamminesses\nclamming\nclammy\nclamor\nclamored\nclamorer\nclamorers\nclamoring\nclamorous\nclamorously\nclamorousness\nclamorousnesses\nclamors\nclamour\nclamoured\nclamouring\nclamours\nclamp\nclampdown\nclampdowns\nclamped\nclamper\nclampers\nclamping\nclamps\nclams\nclamshell\nclamshells\nclamworm\nclamworms\nclan\nclandestine\nclandestinely\nclandestineness\nclandestinenesses\nclandestinities\nclandestinity\nclang\nclanged\nclanger\nclangers\nclanging\nclangor\nclangored\nclangoring\nclangorous\nclangorously\nclangors\nclangour\nclangoured\nclangouring\nclangours\nclangs\nclank\nclanked\nclanking\nclankingly\nclanks\nclannish\nclannishly\nclannishness\nclannishnesses\nclans\nclansman\nclansmen\nclap\nclapboard\nclapboarded\nclapboarding\nclapboards\nclapped\nclapper\nclapperclaw\nclapperclawed\nclapperclawing\nclapperclaws\nclappers\nclapping\nclaps\nclapt\nclaptrap\nclaptraps\nclaque\nclaquer\nclaquers\nclaques\nclaqueur\nclaqueurs\nclarence\nclarences\nclaret\nclarets\nclaries\nclarification\nclarifications\nclarified\nclarifier\nclarifiers\nclarifies\nclarify\nclarifying\nclarinet\nclarinetist\nclarinetists\nclarinets\nclarinettist\nclarinettists\nclarion\nclarioned\nclarioning\nclarions\nclarities\nclarity\nclarkia\nclarkias\nclaro\nclaroes\nclaros\nclary\nclash\nclashed\nclasher\nclashers\nclashes\nclashing\nclasp\nclasped\nclasper\nclaspers\nclasping\nclasps\nclaspt\nclass\nclassed\nclasser\nclassers\nclasses\nclassic\nclassical\nclassicalities\nclassicality\nclassically\nclassicism\nclassicisms\nclassicist\nclassicistic\nclassicists\nclassicize\nclassicized\nclassicizes\nclassicizing\nclassico\nclassics\nclassier\nclassiest\nclassifiable\nclassification\nclassifications\nclassificatory\nclassified\nclassifieds\nclassifier\nclassifiers\nclassifies\nclassify\nclassifying\nclassily\nclassiness\nclassinesses\nclassing\nclassis\nclassism\nclassisms\nclassist\nclassists\nclassless\nclasslessness\nclasslessnesses\nclassmate\nclassmates\nclassroom\nclassrooms\nclassy\nclast\nclastic\nclastics\nclasts\nclathrate\nclathrates\nclatter\nclattered\nclatterer\nclatterers\nclattering\nclatteringly\nclatters\nclattery\nclaucht\nclaudication\nclaudications\nclaught\nclaughted\nclaughting\nclaughts\nclausal\nclause\nclauses\nclaustra\nclaustral\nclaustrophobe\nclaustrophobes\nclaustrophobia\nclaustrophobias\nclaustrophobic\nclaustrophobically\nclaustrum\nclavate\nclave\nclaver\nclavered\nclavering\nclavers\nclaves\nclavi\nclavichord\nclavichordist\nclavichordists\nclavichords\nclavicle\nclavicles\nclavicular\nclavier\nclavierist\nclavieristic\nclavierists\nclaviers\nclavus\nclaw\nclawed\nclawer\nclawers\nclawhammer\nclawing\nclawless\nclawlike\nclaws\nclaxon\nclaxons\nclay\nclaybank\nclaybanks\nclayed\nclayey\nclayier\nclayiest\nclaying\nclayish\nclaylike\nclaymore\nclaymores\nclaypan\nclaypans\nclays\nclayware\nclaywares\nclean\ncleanabilities\ncleanability\ncleanable\ncleaned\ncleaner\ncleaners\ncleanest\ncleanhanded\ncleaning\ncleanlier\ncleanliest\ncleanliness\ncleanlinesses\ncleanly\ncleanness\ncleannesses\ncleans\ncleanse\ncleansed\ncleanser\ncleansers\ncleanses\ncleansing\ncleanup\ncleanups\nclear\nclearable\nclearance\nclearances\ncleared\nclearer\nclearers\nclearest\nclearheaded\nclearheadedly\nclearheadedness\nclearheadednesses\nclearing\nclearinghouse\nclearinghouses\nclearings\nclearly\nclearness\nclearnesses\nclears\nclearstories\nclearstory\nclearwing\nclearwings\ncleat\ncleated\ncleating\ncleats\ncleavable\ncleavage\ncleavages\ncleave\ncleaved\ncleaver\ncleavers\ncleaves\ncleaving\ncleek\ncleeked\ncleeking\ncleeks\nclef\nclefs\ncleft\nclefted\nclefting\nclefts\ncleidoic\ncleistogamic\ncleistogamies\ncleistogamous\ncleistogamously\ncleistogamy\nclematis\nclematises\nclemencies\nclemency\nclement\nclemently\nclench\nclenched\nclencher\nclenchers\nclenches\nclenching\ncleome\ncleomes\nclepe\ncleped\nclepes\ncleping\nclepsydra\nclepsydrae\nclepsydras\nclept\nclerestories\nclerestory\nclergies\nclergy\nclergyman\nclergymen\nclergywoman\nclergywomen\ncleric\nclerical\nclericalism\nclericalisms\nclericalist\nclericalists\nclerically\nclericals\nclerics\nclerid\nclerids\nclerihew\nclerihews\nclerisies\nclerisy\nclerk\nclerkdom\nclerkdoms\nclerked\nclerking\nclerkish\nclerklier\nclerkliest\nclerkly\nclerks\nclerkship\nclerkships\ncleveite\ncleveites\nclever\ncleverer\ncleverest\ncleverish\ncleverly\ncleverness\nclevernesses\nclevis\nclevises\nclew\nclewed\nclewing\nclews\ncliche\ncliched\ncliches\nclick\nclicked\nclicker\nclickers\nclicking\nclicks\nclient\nclientage\nclientages\ncliental\nclientele\nclienteles\nclientless\nclients\ncliff\ncliffhanger\ncliffhangers\ncliffier\ncliffiest\ncliffs\ncliffy\nclift\nclifts\nclimacteric\nclimacterics\nclimactic\nclimactically\nclimatal\nclimate\nclimates\nclimatic\nclimatically\nclimatological\nclimatologically\nclimatologies\nclimatologist\nclimatologists\nclimatology\nclimax\nclimaxed\nclimaxes\nclimaxing\nclimaxless\nclimb\nclimbable\nclimbed\nclimber\nclimbers\nclimbing\nclimbs\nclime\nclimes\nclinal\nclinally\nclinch\nclinched\nclincher\nclinchers\nclinches\nclinching\nclinchingly\ncline\nclines\ncling\nclinged\nclinger\nclingers\nclingier\nclingiest\nclinging\nclings\nclingstone\nclingstones\nclingy\nclinic\nclinical\nclinically\nclinician\nclinicians\nclinicopathologic\nclinicopathological\nclinicopathologically\nclinics\nclink\nclinked\nclinker\nclinkered\nclinkering\nclinkers\nclinking\nclinks\nclinometer\nclinometers\nclinquant\nclinquants\nclintonia\nclintonias\ncliometric\ncliometrician\ncliometricians\ncliometrics\nclip\nclipboard\nclipboards\nclipped\nclipper\nclippers\nclipping\nclippings\nclips\nclipsheet\nclipsheets\nclipt\nclique\ncliqued\ncliques\ncliquey\ncliquier\ncliquiest\ncliquing\ncliquish\ncliquishly\ncliquishness\ncliquishnesses\ncliquy\nclit\nclitella\nclitellum\nclitic\nclitics\nclitoral\nclitorectomies\nclitorectomy\nclitoric\nclitoridectomies\nclitoridectomy\nclitorides\nclitoris\nclitorises\nclits\nclivers\nclivia\nclivias\ncloaca\ncloacae\ncloacal\ncloacas\ncloak\ncloaked\ncloaking\ncloakroom\ncloakrooms\ncloaks\nclobber\nclobbered\nclobbering\nclobbers\nclochard\nclochards\ncloche\ncloches\nclock\nclocked\nclocker\nclockers\nclocking\nclocklike\nclocks\nclockwise\nclockwork\nclockworks\nclod\ncloddier\ncloddiest\ncloddish\ncloddishness\ncloddishnesses\ncloddy\nclodhopper\nclodhoppers\nclodhopping\nclodpate\nclodpates\nclodpole\nclodpoles\nclodpoll\nclodpolls\nclods\nclofibrate\nclofibrates\nclog\nclogged\nclogger\ncloggers\ncloggier\ncloggiest\nclogging\ncloggy\nclogs\ncloisonne\ncloisonnes\ncloister\ncloistered\ncloistering\ncloisters\ncloistral\ncloistress\ncloistresses\nclomb\nclomiphene\nclomiphenes\nclomp\nclomped\nclomping\nclomps\nclon\nclonal\nclonally\nclone\ncloned\ncloner\ncloners\nclones\nclonic\nclonicities\nclonicity\nclonidine\nclonidines\ncloning\nclonings\nclonism\nclonisms\nclonk\nclonked\nclonking\nclonks\nclons\nclonus\nclonuses\ncloot\ncloots\nclop\nclopped\nclopping\nclops\ncloque\ncloques\nclosable\nclose\ncloseable\nclosed\nclosedown\nclosedowns\nclosefisted\nclosely\nclosemouthed\ncloseness\nclosenesses\ncloseout\ncloseouts\ncloser\nclosers\ncloses\nclosest\nclosestool\nclosestools\ncloset\ncloseted\nclosetful\nclosetfuls\ncloseting\nclosets\ncloseup\ncloseups\nclosing\nclosings\nclostridia\nclostridial\nclostridium\nclosure\nclosured\nclosures\nclosuring\nclot\ncloth\nclothbound\nclothe\nclothed\nclothes\nclotheshorse\nclotheshorses\nclothesline\nclotheslined\nclotheslines\nclotheslining\nclothespin\nclothespins\nclothespress\nclothespresses\nclothier\nclothiers\nclothing\nclothings\ncloths\nclots\nclotted\nclotting\nclotty\ncloture\nclotured\nclotures\ncloturing\ncloud\ncloudberries\ncloudberry\ncloudburst\ncloudbursts\nclouded\ncloudier\ncloudiest\ncloudily\ncloudiness\ncloudinesses\nclouding\ncloudland\ncloudlands\ncloudless\ncloudlessly\ncloudlessness\ncloudlessnesses\ncloudlet\ncloudlets\nclouds\ncloudscape\ncloudscapes\ncloudy\nclough\ncloughs\nclour\ncloured\nclouring\nclours\nclout\nclouted\nclouter\nclouters\nclouting\nclouts\nclove\ncloven\nclover\ncloverleaf\ncloverleafs\ncloverleaves\nclovers\ncloves\nclowder\nclowders\nclown\nclowned\nclowneries\nclownery\nclowning\nclownish\nclownishly\nclownishness\nclownishnesses\nclowns\ncloxacillin\ncloxacillins\ncloy\ncloyed\ncloying\ncloyingly\ncloys\ncloze\nclozes\nclub\nclubable\nclubbable\nclubbed\nclubber\nclubbers\nclubbier\nclubbiest\nclubbiness\nclubbinesses\nclubbing\nclubbish\nclubby\nclubfeet\nclubfoot\nclubfooted\nclubhand\nclubhands\nclubhaul\nclubhauled\nclubhauling\nclubhauls\nclubhouse\nclubhouses\nclubman\nclubmen\nclubroom\nclubrooms\nclubroot\nclubroots\nclubs\ncluck\nclucked\nclucking\nclucks\nclue\nclued\nclueing\nclueless\nclues\ncluing\nclumber\nclumbers\nclump\nclumped\nclumpier\nclumpiest\nclumping\nclumpish\nclumps\nclumpy\nclumsier\nclumsiest\nclumsily\nclumsiness\nclumsinesses\nclumsy\nclung\nclunk\nclunked\nclunker\nclunkers\nclunkier\nclunkiest\nclunking\nclunks\nclunky\nclupeid\nclupeids\nclupeoid\nclupeoids\ncluster\nclustered\nclustering\nclusters\nclustery\nclutch\nclutched\nclutches\nclutching\nclutchy\nclutter\ncluttered\ncluttering\nclutters\ncluttery\nclypeal\nclypeate\nclypei\nclypeus\nclyster\nclysters\ncnidarian\ncnidarians\ncoacervate\ncoacervates\ncoacervation\ncoacervations\ncoach\ncoachable\ncoached\ncoacher\ncoachers\ncoaches\ncoaching\ncoachman\ncoachmen\ncoachwork\ncoachworks\ncoact\ncoacted\ncoacting\ncoaction\ncoactions\ncoactive\ncoactor\ncoactors\ncoacts\ncoadaptation\ncoadaptations\ncoadapted\ncoadjutor\ncoadjutors\ncoadjutrices\ncoadjutrix\ncoadministration\ncoadministrations\ncoadmire\ncoadmired\ncoadmires\ncoadmiring\ncoadmit\ncoadmits\ncoadmitted\ncoadmitting\ncoaeval\ncoaevals\ncoagencies\ncoagency\ncoagent\ncoagents\ncoagula\ncoagulabilities\ncoagulability\ncoagulable\ncoagulant\ncoagulants\ncoagulase\ncoagulases\ncoagulate\ncoagulated\ncoagulates\ncoagulating\ncoagulation\ncoagulations\ncoagulum\ncoagulums\ncoal\ncoala\ncoalas\ncoalbin\ncoalbins\ncoalbox\ncoalboxes\ncoaled\ncoaler\ncoalers\ncoalesce\ncoalesced\ncoalescence\ncoalescences\ncoalescent\ncoalesces\ncoalescing\ncoalfield\ncoalfields\ncoalfish\ncoalfishes\ncoalhole\ncoalholes\ncoalier\ncoaliest\ncoalification\ncoalifications\ncoalified\ncoalifies\ncoalify\ncoalifying\ncoaling\ncoalition\ncoalitionist\ncoalitionists\ncoalitions\ncoalless\ncoalpit\ncoalpits\ncoals\ncoalsack\ncoalsacks\ncoalshed\ncoalsheds\ncoaly\ncoalyard\ncoalyards\ncoaming\ncoamings\ncoanchor\ncoanchored\ncoanchoring\ncoanchors\ncoannex\ncoannexed\ncoannexes\ncoannexing\ncoappear\ncoappeared\ncoappearing\ncoappears\ncoapt\ncoaptation\ncoaptations\ncoapted\ncoapting\ncoapts\ncoarctation\ncoarctations\ncoarse\ncoarsely\ncoarsen\ncoarsened\ncoarseness\ncoarsenesses\ncoarsening\ncoarsens\ncoarser\ncoarsest\ncoassist\ncoassisted\ncoassisting\ncoassists\ncoassume\ncoassumed\ncoassumes\ncoassuming\ncoast\ncoastal\ncoasted\ncoaster\ncoasters\ncoastguard\ncoastguardman\ncoastguardmen\ncoastguards\ncoastguardsman\ncoastguardsmen\ncoasting\ncoastings\ncoastland\ncoastlands\ncoastline\ncoastlines\ncoasts\ncoastward\ncoastwards\ncoastwise\ncoat\ncoatdress\ncoatdresses\ncoated\ncoatee\ncoatees\ncoater\ncoaters\ncoati\ncoatimundi\ncoatimundis\ncoating\ncoatings\ncoatis\ncoatless\ncoatrack\ncoatracks\ncoatroom\ncoatrooms\ncoats\ncoattail\ncoattails\ncoattend\ncoattended\ncoattending\ncoattends\ncoattest\ncoattested\ncoattesting\ncoattests\ncoauthor\ncoauthored\ncoauthoring\ncoauthors\ncoauthorship\ncoauthorships\ncoax\ncoaxal\ncoaxed\ncoaxer\ncoaxers\ncoaxes\ncoaxial\ncoaxially\ncoaxing\ncob\ncobalamin\ncobalamins\ncobalt\ncobaltic\ncobaltine\ncobaltines\ncobaltite\ncobaltites\ncobaltous\ncobalts\ncobb\ncobber\ncobbers\ncobbier\ncobbiest\ncobble\ncobbled\ncobbler\ncobblers\ncobbles\ncobblestone\ncobblestoned\ncobblestones\ncobbling\ncobbs\ncobby\ncobelligerent\ncobelligerents\ncobia\ncobias\ncoble\ncobles\ncobnut\ncobnuts\ncobra\ncobras\ncobs\ncobweb\ncobwebbed\ncobwebbier\ncobwebbiest\ncobwebbing\ncobwebby\ncobwebs\ncoca\ncocain\ncocaine\ncocaines\ncocainization\ncocainizations\ncocainize\ncocainized\ncocainizes\ncocainizing\ncocains\ncocaptain\ncocaptained\ncocaptaining\ncocaptains\ncocarboxylase\ncocarboxylases\ncocarcinogen\ncocarcinogenic\ncocarcinogens\ncocas\ncocatalyst\ncocatalysts\ncoccal\ncocci\ncoccic\ncoccid\ncoccidia\ncoccidioidomycoses\ncoccidioidomycosis\ncoccidioses\ncoccidiosis\ncoccidium\ncoccids\ncoccoid\ncoccoids\ncoccous\ncoccus\ncoccygeal\ncoccyges\ncoccyx\ncoccyxes\ncochair\ncochaired\ncochairing\ncochairman\ncochairmen\ncochairperson\ncochairpersons\ncochairs\ncochairwoman\ncochairwomen\ncochampion\ncochampions\ncochin\ncochineal\ncochineals\ncochins\ncochlea\ncochleae\ncochlear\ncochleas\ncocinera\ncocineras\ncock\ncockade\ncockaded\ncockades\ncockalorum\ncockalorums\ncockamamie\ncockamamy\ncockapoo\ncockapoos\ncockatiel\ncockatiels\ncockatoo\ncockatoos\ncockatrice\ncockatrices\ncockbill\ncockbilled\ncockbilling\ncockbills\ncockboat\ncockboats\ncockchafer\ncockchafers\ncockcrow\ncockcrows\ncocked\ncocker\ncockered\ncockerel\ncockerels\ncockering\ncockers\ncockeye\ncockeyed\ncockeyedly\ncockeyedness\ncockeyednesses\ncockeyes\ncockfight\ncockfighting\ncockfightings\ncockfights\ncockhorse\ncockhorses\ncockier\ncockiest\ncockily\ncockiness\ncockinesses\ncocking\ncockish\ncockle\ncocklebur\ncockleburs\ncockled\ncockles\ncockleshell\ncockleshells\ncocklike\ncockling\ncockloft\ncocklofts\ncockney\ncockneyfied\ncockneyfies\ncockneyfy\ncockneyfying\ncockneyish\ncockneyism\ncockneyisms\ncockneys\ncockpit\ncockpits\ncockroach\ncockroaches\ncocks\ncockscomb\ncockscombs\ncocksfoot\ncocksfoots\ncockshies\ncockshut\ncockshuts\ncockshy\ncockspur\ncockspurs\ncocksucker\ncocksuckers\ncocksure\ncocksurely\ncocksureness\ncocksurenesses\ncocktail\ncocktailed\ncocktailing\ncocktails\ncockup\ncockups\ncocky\ncoco\ncocoa\ncocoanut\ncocoanuts\ncocoas\ncocobola\ncocobolas\ncocobolo\ncocobolos\ncocomat\ncocomats\ncocomposer\ncocomposers\ncoconspirator\ncoconspirators\ncoconut\ncoconuts\ncocoon\ncocooned\ncocooning\ncocoonings\ncocoons\ncocos\ncocotte\ncocottes\ncocounsel\ncocounseled\ncocounseling\ncocounselled\ncocounselling\ncocounsels\ncocoyam\ncocoyams\ncocreate\ncocreated\ncocreates\ncocreating\ncocreator\ncocreators\ncocultivate\ncocultivated\ncocultivates\ncocultivating\ncocultivation\ncocultivations\ncoculture\ncocultured\ncocultures\ncoculturing\ncocurator\ncocurators\ncocurricular\ncod\ncoda\ncodable\ncodas\ncodded\ncodder\ncodders\ncodding\ncoddle\ncoddled\ncoddler\ncoddlers\ncoddles\ncoddling\ncode\ncodebook\ncodebooks\ncodebtor\ncodebtors\ncodec\ncodecs\ncoded\ncodefendant\ncodefendants\ncodeia\ncodeias\ncodein\ncodeina\ncodeinas\ncodeine\ncodeines\ncodeins\ncodeless\ncoden\ncodens\ncodependence\ncodependences\ncodependencies\ncodependency\ncodependent\ncodependents\ncoder\ncoderive\ncoderived\ncoderives\ncoderiving\ncoders\ncodes\ncodesign\ncodesigned\ncodesigning\ncodesigns\ncodetermination\ncodeterminations\ncodevelop\ncodeveloped\ncodeveloper\ncodevelopers\ncodeveloping\ncodevelops\ncodex\ncodfish\ncodfishes\ncodger\ncodgers\ncodices\ncodicil\ncodicillary\ncodicils\ncodicological\ncodicologies\ncodicology\ncodifiabilities\ncodifiability\ncodification\ncodifications\ncodified\ncodifier\ncodifiers\ncodifies\ncodify\ncodifying\ncoding\ncodirect\ncodirected\ncodirecting\ncodirection\ncodirections\ncodirector\ncodirectors\ncodirects\ncodiscover\ncodiscovered\ncodiscoverer\ncodiscoverers\ncodiscovering\ncodiscovers\ncodlin\ncodling\ncodlings\ncodlins\ncodominant\ncodominants\ncodon\ncodons\ncodpiece\ncodpieces\ncodrive\ncodriven\ncodriver\ncodrivers\ncodrives\ncodriving\ncodrove\ncods\ncodswallop\ncodswallops\ncoed\ncoedit\ncoedited\ncoediting\ncoeditor\ncoeditors\ncoedits\ncoeds\ncoeducation\ncoeducational\ncoeducationally\ncoeducations\ncoeffect\ncoeffects\ncoefficient\ncoefficients\ncoelacanth\ncoelacanths\ncoelentera\ncoelenterate\ncoelenterates\ncoelenteron\ncoeliac\ncoelom\ncoelomata\ncoelomate\ncoelomates\ncoelome\ncoelomes\ncoelomic\ncoeloms\ncoembodied\ncoembodies\ncoembody\ncoembodying\ncoemploy\ncoemployed\ncoemploying\ncoemploys\ncoempt\ncoempted\ncoempting\ncoempts\ncoenact\ncoenacted\ncoenacting\ncoenacts\ncoenamor\ncoenamored\ncoenamoring\ncoenamors\ncoendure\ncoendured\ncoendures\ncoenduring\ncoenobite\ncoenobites\ncoenocyte\ncoenocytes\ncoenocytic\ncoenure\ncoenures\ncoenuri\ncoenurus\ncoenzymatic\ncoenzymatically\ncoenzyme\ncoenzymes\ncoequal\ncoequalities\ncoequality\ncoequally\ncoequals\ncoequate\ncoequated\ncoequates\ncoequating\ncoerce\ncoerced\ncoercer\ncoercers\ncoerces\ncoercible\ncoercing\ncoercion\ncoercions\ncoercive\ncoercively\ncoerciveness\ncoercivenesses\ncoercivities\ncoercivity\ncoerect\ncoerected\ncoerecting\ncoerects\ncoesite\ncoesites\ncoetaneous\ncoeternal\ncoeval\ncoevalities\ncoevality\ncoevally\ncoevals\ncoevolution\ncoevolutionary\ncoevolutions\ncoevolve\ncoevolved\ncoevolves\ncoevolving\ncoexecutor\ncoexecutors\ncoexert\ncoexerted\ncoexerting\ncoexerts\ncoexist\ncoexisted\ncoexistence\ncoexistences\ncoexistent\ncoexisting\ncoexists\ncoextend\ncoextended\ncoextending\ncoextends\ncoextensive\ncoextensively\ncofactor\ncofactors\ncofavorite\ncofavorites\ncofeature\ncofeatured\ncofeatures\ncofeaturing\ncoff\ncoffee\ncoffeecake\ncoffeecakes\ncoffeehouse\ncoffeehouses\ncoffeemaker\ncoffeemakers\ncoffeepot\ncoffeepots\ncoffees\ncoffer\ncofferdam\ncofferdams\ncoffered\ncoffering\ncoffers\ncoffin\ncoffined\ncoffing\ncoffining\ncoffins\ncoffle\ncoffled\ncoffles\ncoffling\ncoffret\ncoffrets\ncoffs\ncofinance\ncofinanced\ncofinances\ncofinancing\ncofound\ncofounded\ncofounder\ncofounders\ncofounding\ncofounds\ncoft\ncofunction\ncofunctions\ncog\ncogencies\ncogency\ncogeneration\ncogenerations\ncogenerator\ncogenerators\ncogent\ncogently\ncogged\ncogging\ncogitable\ncogitate\ncogitated\ncogitates\ncogitating\ncogitation\ncogitations\ncogitative\ncogito\ncogitos\ncognac\ncognacs\ncognate\ncognately\ncognates\ncognation\ncognations\ncognise\ncognised\ncognises\ncognising\ncognition\ncognitional\ncognitions\ncognitive\ncognitively\ncognizable\ncognizably\ncognizance\ncognizances\ncognizant\ncognize\ncognized\ncognizer\ncognizers\ncognizes\ncognizing\ncognomen\ncognomens\ncognomina\ncognominal\ncognoscente\ncognoscenti\ncognoscible\ncognovit\ncognovits\ncogon\ncogons\ncogs\ncogway\ncogways\ncogwheel\ncogwheels\ncohabit\ncohabitant\ncohabitants\ncohabitation\ncohabitations\ncohabited\ncohabiting\ncohabits\ncohead\ncoheaded\ncoheading\ncoheads\ncoheir\ncoheiress\ncoheiresses\ncoheirs\ncohere\ncohered\ncoherence\ncoherences\ncoherencies\ncoherency\ncoherent\ncoherently\ncoherer\ncoherers\ncoheres\ncohering\ncohesion\ncohesionless\ncohesions\ncohesive\ncohesively\ncohesiveness\ncohesivenesses\ncoho\ncohobate\ncohobated\ncohobates\ncohobating\ncohog\ncohogs\ncoholder\ncoholders\ncohomological\ncohomologies\ncohomology\ncohort\ncohorts\ncohos\ncohosh\ncohoshes\ncohost\ncohosted\ncohostess\ncohostessed\ncohostesses\ncohostessing\ncohosting\ncohosts\ncohune\ncohunes\ncoif\ncoifed\ncoiffe\ncoiffed\ncoiffes\ncoiffeur\ncoiffeurs\ncoiffeuse\ncoiffeuses\ncoiffing\ncoiffure\ncoiffured\ncoiffures\ncoiffuring\ncoifing\ncoifs\ncoign\ncoigne\ncoigned\ncoignes\ncoigning\ncoigns\ncoil\ncoilabilities\ncoilability\ncoiled\ncoiler\ncoilers\ncoiling\ncoils\ncoin\ncoinable\ncoinage\ncoinages\ncoincide\ncoincided\ncoincidence\ncoincidences\ncoincident\ncoincidental\ncoincidentally\ncoincidently\ncoincides\ncoinciding\ncoined\ncoiner\ncoiners\ncoinfer\ncoinferred\ncoinferring\ncoinfers\ncoinhere\ncoinhered\ncoinheres\ncoinhering\ncoining\ncoinmate\ncoinmates\ncoins\ncoinsurance\ncoinsurances\ncoinsure\ncoinsured\ncoinsurer\ncoinsurers\ncoinsures\ncoinsuring\ncointer\ncointerred\ncointerring\ncointers\ncoinvent\ncoinvented\ncoinventing\ncoinventor\ncoinventors\ncoinvents\ncoinvestigator\ncoinvestigators\ncoinvestor\ncoinvestors\ncoir\ncoirs\ncoistrel\ncoistrels\ncoistril\ncoistrils\ncoital\ncoitally\ncoition\ncoitional\ncoitions\ncoitus\ncoituses\ncojoin\ncojoined\ncojoining\ncojoins\ncojones\ncoke\ncoked\ncokehead\ncokeheads\ncokes\ncoking\ncol\ncola\ncolander\ncolanders\ncolas\ncolatitude\ncolatitudes\ncolcannon\ncolcannons\ncolchicine\ncolchicines\ncolchicum\ncolchicums\ncold\ncoldblood\ncoldblooded\ncoldcock\ncoldcocked\ncoldcocking\ncoldcocks\ncolder\ncoldest\ncoldhearted\ncoldheartedly\ncoldheartedness\ncoldheartednesses\ncoldish\ncoldly\ncoldness\ncoldnesses\ncolds\ncole\ncolead\ncoleader\ncoleaders\ncoleading\ncoleads\ncoled\ncolemanite\ncolemanites\ncoleoptera\ncoleopteran\ncoleopterans\ncoleopterist\ncoleopterists\ncoleopterous\ncoleoptile\ncoleoptiles\ncoleorhiza\ncoleorhizae\ncoles\ncoleseed\ncoleseeds\ncoleslaw\ncoleslaws\ncolessee\ncolessees\ncolessor\ncolessors\ncoleus\ncoleuses\ncolewort\ncoleworts\ncolic\ncolicin\ncolicine\ncolicines\ncolicins\ncolicky\ncolicroot\ncolicroots\ncolics\ncolies\ncoliform\ncoliforms\ncolin\ncolinear\ncolinearities\ncolinearity\ncolins\ncoliphage\ncoliphages\ncoliseum\ncoliseums\ncolistin\ncolistins\ncolitic\ncolitis\ncolitises\ncollaborate\ncollaborated\ncollaborates\ncollaborating\ncollaboration\ncollaborationism\ncollaborationisms\ncollaborationist\ncollaborationists\ncollaborations\ncollaborative\ncollaboratively\ncollaboratives\ncollaborator\ncollaborators\ncollage\ncollaged\ncollagen\ncollagenase\ncollagenases\ncollagenous\ncollagens\ncollages\ncollaging\ncollagist\ncollagists\ncollapse\ncollapsed\ncollapses\ncollapsibilities\ncollapsibility\ncollapsible\ncollapsing\ncollar\ncollarbone\ncollarbones\ncollard\ncollards\ncollared\ncollaret\ncollarets\ncollaring\ncollarless\ncollars\ncollate\ncollated\ncollateral\ncollateralities\ncollaterality\ncollateralize\ncollateralized\ncollateralizes\ncollateralizing\ncollaterally\ncollaterals\ncollates\ncollating\ncollation\ncollations\ncollator\ncollators\ncolleague\ncolleagues\ncolleagueship\ncolleagueships\ncollect\ncollectable\ncollectables\ncollectanea\ncollected\ncollectedly\ncollectedness\ncollectednesses\ncollectible\ncollectibles\ncollecting\ncollection\ncollections\ncollective\ncollectively\ncollectives\ncollectivise\ncollectivised\ncollectivises\ncollectivising\ncollectivism\ncollectivisms\ncollectivist\ncollectivistic\ncollectivistically\ncollectivists\ncollectivities\ncollectivity\ncollectivization\ncollectivizations\ncollectivize\ncollectivized\ncollectivizes\ncollectivizing\ncollector\ncollectors\ncollectorship\ncollectorships\ncollects\ncolleen\ncolleens\ncollege\ncolleger\ncollegers\ncolleges\ncollegia\ncollegial\ncollegialities\ncollegiality\ncollegially\ncollegian\ncollegians\ncollegiate\ncollegiately\ncollegium\ncollegiums\ncollembolan\ncollembolans\ncollembolous\ncollenchyma\ncollenchymas\ncollenchymata\ncollenchymatous\ncollet\ncolleted\ncolleting\ncollets\ncollide\ncollided\ncollider\ncolliders\ncollides\ncolliding\ncollie\ncollied\ncollier\ncollieries\ncolliers\ncolliery\ncollies\ncollieshangie\ncollieshangies\ncolligate\ncolligated\ncolligates\ncolligating\ncolligation\ncolligations\ncolligative\ncollimate\ncollimated\ncollimates\ncollimating\ncollimation\ncollimations\ncollimator\ncollimators\ncollinear\ncollinearities\ncollinearity\ncollins\ncollinses\ncollision\ncollisional\ncollisionally\ncollisions\ncollocate\ncollocated\ncollocates\ncollocating\ncollocation\ncollocational\ncollocations\ncollodion\ncollodions\ncollogue\ncollogued\ncollogues\ncolloguing\ncolloid\ncolloidal\ncolloidally\ncolloids\ncollop\ncollops\ncolloquia\ncolloquial\ncolloquialism\ncolloquialisms\ncolloquialities\ncolloquiality\ncolloquially\ncolloquials\ncolloquies\ncolloquist\ncolloquists\ncolloquium\ncolloquiums\ncolloquy\ncollotype\ncollotypes\ncollude\ncolluded\ncolluder\ncolluders\ncolludes\ncolluding\ncollusion\ncollusions\ncollusive\ncollusively\ncolluvia\ncolluvial\ncolluvium\ncolluviums\ncolly\ncollying\ncollyria\ncollyrium\ncollyriums\ncollywobbles\ncolobi\ncoloboma\ncolobomata\ncolobus\ncolobuses\ncolocate\ncolocated\ncolocates\ncolocating\ncolocynth\ncolocynths\ncolog\ncologarithm\ncologarithms\ncologne\ncologned\ncolognes\ncologs\ncolon\ncolone\ncolonel\ncolonelcies\ncolonelcy\ncolonels\ncolones\ncoloni\ncolonial\ncolonialism\ncolonialisms\ncolonialist\ncolonialistic\ncolonialists\ncolonialize\ncolonialized\ncolonializes\ncolonializing\ncolonially\ncolonialness\ncolonialnesses\ncolonials\ncolonic\ncolonics\ncolonies\ncolonisation\ncolonisations\ncolonise\ncolonised\ncolonises\ncolonising\ncolonist\ncolonists\ncolonization\ncolonizationist\ncolonizationists\ncolonizations\ncolonize\ncolonized\ncolonizer\ncolonizers\ncolonizes\ncolonizing\ncolonnade\ncolonnaded\ncolonnades\ncolons\ncolonus\ncolony\ncolophon\ncolophonies\ncolophons\ncolophony\ncolor\ncolorable\ncolorably\ncolorado\ncolorant\ncolorants\ncoloration\ncolorations\ncoloratura\ncoloraturas\ncolorblind\ncolorblindness\ncolorblindnesses\ncolorbred\ncolorectal\ncolored\ncoloreds\ncolorer\ncolorers\ncolorfast\ncolorfastness\ncolorfastnesses\ncolorful\ncolorfully\ncolorfulness\ncolorfulnesses\ncolorific\ncolorimeter\ncolorimeters\ncolorimetric\ncolorimetrically\ncolorimetries\ncolorimetry\ncoloring\ncolorings\ncolorism\ncolorisms\ncolorist\ncoloristic\ncoloristically\ncolorists\ncolorization\ncolorizations\ncolorize\ncolorized\ncolorizes\ncolorizing\ncolorless\ncolorlessly\ncolorlessness\ncolorlessnesses\ncolorman\ncolormen\ncolorpoint\ncolorpoints\ncolors\ncolossal\ncolossally\ncolosseum\ncolosseums\ncolossi\ncolossus\ncolossuses\ncolostomies\ncolostomy\ncolostral\ncolostrum\ncolostrums\ncolotomies\ncolotomy\ncolour\ncoloured\ncolourer\ncolourers\ncolouring\ncolours\ncolpitis\ncolpitises\ncolportage\ncolportages\ncolporteur\ncolporteurs\ncols\ncolt\ncolter\ncolters\ncoltish\ncoltishly\ncoltishness\ncoltishnesses\ncolts\ncoltsfoot\ncoltsfoots\ncolubrid\ncolubrids\ncolubrine\ncolugo\ncolugos\ncolumbaria\ncolumbarium\ncolumbic\ncolumbine\ncolumbines\ncolumbite\ncolumbites\ncolumbium\ncolumbiums\ncolumel\ncolumella\ncolumellae\ncolumellar\ncolumels\ncolumn\ncolumnal\ncolumnar\ncolumned\ncolumniation\ncolumniations\ncolumnist\ncolumnistic\ncolumnists\ncolumns\ncolure\ncolures\ncoly\ncolza\ncolzas\ncoma\ncomade\ncomae\ncomake\ncomaker\ncomakers\ncomakes\ncomaking\ncomal\ncomanage\ncomanaged\ncomanagement\ncomanagements\ncomanager\ncomanagers\ncomanages\ncomanaging\ncomas\ncomate\ncomates\ncomatic\ncomatik\ncomatiks\ncomatose\ncomatula\ncomatulae\ncomb\ncombat\ncombatant\ncombatants\ncombated\ncombater\ncombaters\ncombating\ncombative\ncombatively\ncombativeness\ncombativenesses\ncombats\ncombatted\ncombatting\ncombe\ncombed\ncomber\ncombers\ncombes\ncombinable\ncombination\ncombinational\ncombinations\ncombinative\ncombinatorial\ncombinatorially\ncombinatorics\ncombinatory\ncombine\ncombined\ncombiner\ncombiners\ncombines\ncombing\ncombings\ncombining\ncomblike\ncombo\ncombos\ncombs\ncombust\ncombusted\ncombustibilities\ncombustibility\ncombustible\ncombustibles\ncombustibly\ncombusting\ncombustion\ncombustions\ncombustive\ncombustor\ncombustors\ncombusts\ncome\ncomeback\ncomebacks\ncomedian\ncomedians\ncomedic\ncomedically\ncomedienne\ncomediennes\ncomedies\ncomedo\ncomedones\ncomedos\ncomedown\ncomedowns\ncomedy\ncomelier\ncomeliest\ncomelily\ncomeliness\ncomelinesses\ncomely\ncomember\ncomembers\ncomer\ncomers\ncomes\ncomestible\ncomestibles\ncomet\ncometary\ncometh\ncomether\ncomethers\ncometic\ncomets\ncomeuppance\ncomeuppances\ncomfier\ncomfiest\ncomfit\ncomfits\ncomfort\ncomfortable\ncomfortableness\ncomfortablenesses\ncomfortably\ncomforted\ncomforter\ncomforters\ncomforting\ncomfortingly\ncomfortless\ncomforts\ncomfrey\ncomfreys\ncomfy\ncomic\ncomical\ncomicalities\ncomicality\ncomically\ncomics\ncoming\ncomingle\ncomingled\ncomingles\ncomingling\ncomings\ncomitia\ncomitial\ncomities\ncomity\ncomix\ncomma\ncommand\ncommandable\ncommandant\ncommandants\ncommanded\ncommandeer\ncommandeered\ncommandeering\ncommandeers\ncommander\ncommanderies\ncommanders\ncommandership\ncommanderships\ncommandery\ncommanding\ncommandingly\ncommandment\ncommandments\ncommando\ncommandoes\ncommandos\ncommands\ncommas\ncommata\ncommemorate\ncommemorated\ncommemorates\ncommemorating\ncommemoration\ncommemorations\ncommemorative\ncommemoratively\ncommemoratives\ncommemorator\ncommemorators\ncommence\ncommenced\ncommencement\ncommencements\ncommencer\ncommencers\ncommences\ncommencing\ncommend\ncommendable\ncommendably\ncommendation\ncommendations\ncommendatory\ncommended\ncommender\ncommenders\ncommending\ncommends\ncommensal\ncommensalism\ncommensalisms\ncommensally\ncommensals\ncommensurabilities\ncommensurability\ncommensurable\ncommensurably\ncommensurate\ncommensurately\ncommensuration\ncommensurations\ncomment\ncommentaries\ncommentary\ncommentate\ncommentated\ncommentates\ncommentating\ncommentator\ncommentators\ncommented\ncommenting\ncomments\ncommerce\ncommerced\ncommerces\ncommercial\ncommercialise\ncommercialised\ncommercialises\ncommercialising\ncommercialism\ncommercialisms\ncommercialist\ncommercialistic\ncommercialists\ncommercialities\ncommerciality\ncommercialization\ncommercializations\ncommercialize\ncommercialized\ncommercializes\ncommercializing\ncommercially\ncommercials\ncommercing\ncommie\ncommies\ncommination\ncomminations\ncomminatory\ncommingle\ncommingled\ncommingles\ncommingling\ncomminute\ncomminuted\ncomminutes\ncomminuting\ncomminution\ncomminutions\ncommiserate\ncommiserated\ncommiserates\ncommiserating\ncommiseratingly\ncommiseration\ncommiserations\ncommiserative\ncommissar\ncommissarial\ncommissariat\ncommissariats\ncommissaries\ncommissars\ncommissary\ncommission\ncommissionaire\ncommissionaires\ncommissioned\ncommissioner\ncommissioners\ncommissionership\ncommissionerships\ncommissioning\ncommissions\ncommissural\ncommissure\ncommissures\ncommit\ncommitment\ncommitments\ncommits\ncommittable\ncommittal\ncommittals\ncommitted\ncommittee\ncommitteeman\ncommitteemen\ncommittees\ncommitteewoman\ncommitteewomen\ncommitting\ncommix\ncommixed\ncommixes\ncommixing\ncommixt\ncommixture\ncommixtures\ncommode\ncommodes\ncommodification\ncommodifications\ncommodified\ncommodifies\ncommodify\ncommodifying\ncommodious\ncommodiously\ncommodiousness\ncommodiousnesses\ncommodities\ncommodity\ncommodore\ncommodores\ncommon\ncommonage\ncommonages\ncommonalities\ncommonality\ncommonalties\ncommonalty\ncommoner\ncommoners\ncommonest\ncommonly\ncommonness\ncommonnesses\ncommonplace\ncommonplaceness\ncommonplacenesses\ncommonplaces\ncommons\ncommonsense\ncommonsensible\ncommonsensical\ncommonsensically\ncommonweal\ncommonweals\ncommonwealth\ncommonwealths\ncommotion\ncommotions\ncommove\ncommoved\ncommoves\ncommoving\ncommunal\ncommunalism\ncommunalisms\ncommunalist\ncommunalists\ncommunalities\ncommunality\ncommunalize\ncommunalized\ncommunalizes\ncommunalizing\ncommunally\ncommunard\ncommunards\ncommune\ncommuned\ncommunes\ncommunicabilities\ncommunicability\ncommunicable\ncommunicableness\ncommunicablenesses\ncommunicably\ncommunicant\ncommunicants\ncommunicate\ncommunicated\ncommunicatee\ncommunicatees\ncommunicates\ncommunicating\ncommunication\ncommunicational\ncommunications\ncommunicative\ncommunicatively\ncommunicativeness\ncommunicativenesses\ncommunicator\ncommunicators\ncommunicatory\ncommuning\ncommunion\ncommunions\ncommunique\ncommuniques\ncommunise\ncommunised\ncommunises\ncommunising\ncommunism\ncommunisms\ncommunist\ncommunistic\ncommunistically\ncommunists\ncommunitarian\ncommunitarianism\ncommunitarianisms\ncommunitarians\ncommunities\ncommunity\ncommunization\ncommunizations\ncommunize\ncommunized\ncommunizes\ncommunizing\ncommutable\ncommutate\ncommutated\ncommutates\ncommutating\ncommutation\ncommutations\ncommutative\ncommutativities\ncommutativity\ncommutator\ncommutators\ncommute\ncommuted\ncommuter\ncommuters\ncommutes\ncommuting\ncommy\ncomonomer\ncomonomers\ncomose\ncomous\ncomp\ncompact\ncompacted\ncompacter\ncompacters\ncompactest\ncompactible\ncompacting\ncompaction\ncompactions\ncompactly\ncompactness\ncompactnesses\ncompactor\ncompactors\ncompacts\ncompadre\ncompadres\ncompanied\ncompanies\ncompanion\ncompanionabilities\ncompanionability\ncompanionable\ncompanionableness\ncompanionablenesses\ncompanionably\ncompanionate\ncompanioned\ncompanioning\ncompanions\ncompanionship\ncompanionships\ncompanionway\ncompanionways\ncompany\ncompanying\ncomparabilities\ncomparability\ncomparable\ncomparableness\ncomparablenesses\ncomparably\ncomparatist\ncomparatists\ncomparative\ncomparatively\ncomparativeness\ncomparativenesses\ncomparatives\ncomparativist\ncomparativists\ncomparator\ncomparators\ncompare\ncompared\ncomparer\ncomparers\ncompares\ncomparing\ncomparison\ncomparisons\ncompart\ncomparted\ncomparting\ncompartment\ncompartmental\ncompartmentalise\ncompartmentalised\ncompartmentalises\ncompartmentalising\ncompartmentalization\ncompartmentalizations\ncompartmentalize\ncompartmentalized\ncompartmentalizes\ncompartmentalizing\ncompartmentation\ncompartmentations\ncompartmented\ncompartmenting\ncompartments\ncomparts\ncompass\ncompassable\ncompassed\ncompasses\ncompassing\ncompassion\ncompassionate\ncompassionated\ncompassionately\ncompassionateness\ncompassionatenesses\ncompassionates\ncompassionating\ncompassionless\ncompassions\ncompatibilities\ncompatibility\ncompatible\ncompatibleness\ncompatiblenesses\ncompatibles\ncompatibly\ncompatriot\ncompatriotic\ncompatriots\ncomped\ncompeer\ncompeered\ncompeering\ncompeers\ncompel\ncompellable\ncompellation\ncompellations\ncompelled\ncompelling\ncompellingly\ncompels\ncompend\ncompendia\ncompendious\ncompendiously\ncompendiousness\ncompendiousnesses\ncompendium\ncompendiums\ncompends\ncompensabilities\ncompensability\ncompensable\ncompensate\ncompensated\ncompensates\ncompensating\ncompensation\ncompensational\ncompensations\ncompensative\ncompensator\ncompensators\ncompensatory\ncompere\ncompered\ncomperes\ncompering\ncompete\ncompeted\ncompetence\ncompetences\ncompetencies\ncompetency\ncompetent\ncompetently\ncompetes\ncompeting\ncompetition\ncompetitions\ncompetitive\ncompetitively\ncompetitiveness\ncompetitivenesses\ncompetitor\ncompetitors\ncompilation\ncompilations\ncompile\ncompiled\ncompiler\ncompilers\ncompiles\ncompiling\ncomping\ncomplacence\ncomplacences\ncomplacencies\ncomplacency\ncomplacent\ncomplacently\ncomplain\ncomplainant\ncomplainants\ncomplained\ncomplainer\ncomplainers\ncomplaining\ncomplainingly\ncomplains\ncomplaint\ncomplaints\ncomplaisance\ncomplaisances\ncomplaisant\ncomplaisantly\ncompleat\ncomplect\ncomplected\ncomplecting\ncomplects\ncomplement\ncomplemental\ncomplementaries\ncomplementarily\ncomplementariness\ncomplementarinesses\ncomplementarities\ncomplementarity\ncomplementary\ncomplementation\ncomplementations\ncomplemented\ncomplementing\ncomplementizer\ncomplementizers\ncomplements\ncomplete\ncompleted\ncompletely\ncompleteness\ncompletenesses\ncompleter\ncompletes\ncompletest\ncompleting\ncompletion\ncompletions\ncompletist\ncompletists\ncompletive\ncomplex\ncomplexation\ncomplexations\ncomplexed\ncomplexer\ncomplexes\ncomplexest\ncomplexified\ncomplexifies\ncomplexify\ncomplexifying\ncomplexing\ncomplexion\ncomplexional\ncomplexioned\ncomplexions\ncomplexities\ncomplexity\ncomplexly\ncomplexness\ncomplexnesses\ncompliance\ncompliances\ncompliancies\ncompliancy\ncompliant\ncompliantly\ncomplicacies\ncomplicacy\ncomplicate\ncomplicated\ncomplicatedly\ncomplicatedness\ncomplicatednesses\ncomplicates\ncomplicating\ncomplication\ncomplications\ncomplice\ncomplices\ncomplicit\ncomplicities\ncomplicitous\ncomplicity\ncomplied\ncomplier\ncompliers\ncomplies\ncompliment\ncomplimentarily\ncomplimentary\ncomplimented\ncomplimenting\ncompliments\ncomplin\ncompline\ncomplines\ncomplins\ncomplot\ncomplots\ncomplotted\ncomplotting\ncomply\ncomplying\ncompo\ncompone\ncomponent\ncomponential\ncomponents\ncompony\ncomport\ncomported\ncomporting\ncomportment\ncomportments\ncomports\ncompos\ncompose\ncomposed\ncomposedly\ncomposedness\ncomposednesses\ncomposer\ncomposers\ncomposes\ncomposing\ncomposite\ncomposited\ncompositely\ncomposites\ncompositing\ncomposition\ncompositional\ncompositionally\ncompositions\ncompositor\ncompositors\ncompost\ncomposted\ncomposting\ncomposts\ncomposure\ncomposures\ncompote\ncompotes\ncompound\ncompoundable\ncompounded\ncompounder\ncompounders\ncompounding\ncompounds\ncomprador\ncompradore\ncompradores\ncompradors\ncomprehend\ncomprehended\ncomprehendible\ncomprehending\ncomprehends\ncomprehensibilities\ncomprehensibility\ncomprehensible\ncomprehensibleness\ncomprehensiblenesses\ncomprehensibly\ncomprehension\ncomprehensions\ncomprehensive\ncomprehensively\ncomprehensiveness\ncomprehensivenesses\ncompress\ncompressed\ncompressedly\ncompresses\ncompressibilities\ncompressibility\ncompressible\ncompressing\ncompression\ncompressional\ncompressions\ncompressive\ncompressively\ncompressor\ncompressors\ncomprise\ncomprised\ncomprises\ncomprising\ncomprize\ncomprized\ncomprizes\ncomprizing\ncompromise\ncompromised\ncompromiser\ncompromisers\ncompromises\ncompromising\ncomps\ncompt\ncompted\ncompting\ncomptroller\ncomptrollers\ncomptrollership\ncomptrollerships\ncompts\ncompulsion\ncompulsions\ncompulsive\ncompulsively\ncompulsiveness\ncompulsivenesses\ncompulsives\ncompulsivities\ncompulsivity\ncompulsorily\ncompulsory\ncompunction\ncompunctions\ncompunctious\ncompurgation\ncompurgations\ncompurgator\ncompurgators\ncomputabilities\ncomputability\ncomputable\ncomputation\ncomputational\ncomputationally\ncomputations\ncompute\ncomputed\ncomputer\ncomputerdom\ncomputerdoms\ncomputerese\ncomputereses\ncomputerise\ncomputerised\ncomputerises\ncomputerising\ncomputerist\ncomputerists\ncomputerizable\ncomputerization\ncomputerizations\ncomputerize\ncomputerized\ncomputerizes\ncomputerizing\ncomputerless\ncomputerlike\ncomputernik\ncomputerniks\ncomputerphobe\ncomputerphobes\ncomputerphobia\ncomputerphobias\ncomputerphobic\ncomputers\ncomputes\ncomputing\ncomrade\ncomradeliness\ncomradelinesses\ncomradely\ncomraderies\ncomradery\ncomrades\ncomradeship\ncomradeships\ncomsymp\ncomsymps\ncomte\ncomtes\ncon\nconation\nconations\nconative\nconatus\nconcanavalin\nconcanavalins\nconcatenate\nconcatenated\nconcatenates\nconcatenating\nconcatenation\nconcatenations\nconcave\nconcaved\nconcaves\nconcaving\nconcavities\nconcavity\nconceal\nconcealable\nconcealed\nconcealer\nconcealers\nconcealing\nconcealingly\nconcealment\nconcealments\nconceals\nconcede\nconceded\nconcededly\nconceder\nconceders\nconcedes\nconceding\nconceit\nconceited\nconceitedly\nconceitedness\nconceitednesses\nconceiting\nconceits\nconceivabilities\nconceivability\nconceivable\nconceivableness\nconceivablenesses\nconceivably\nconceive\nconceived\nconceiver\nconceivers\nconceives\nconceiving\nconcelebrant\nconcelebrants\nconcelebrate\nconcelebrated\nconcelebrates\nconcelebrating\nconcelebration\nconcelebrations\nconcent\nconcenter\nconcentered\nconcentering\nconcenters\nconcentrate\nconcentrated\nconcentratedly\nconcentrates\nconcentrating\nconcentration\nconcentrations\nconcentrative\nconcentrator\nconcentrators\nconcentric\nconcentrically\nconcentricities\nconcentricity\nconcents\nconcept\nconceptacle\nconceptacles\nconception\nconceptional\nconceptions\nconceptive\nconcepts\nconceptual\nconceptualise\nconceptualised\nconceptualises\nconceptualising\nconceptualism\nconceptualisms\nconceptualist\nconceptualistic\nconceptualistically\nconceptualists\nconceptualities\nconceptuality\nconceptualization\nconceptualizations\nconceptualize\nconceptualized\nconceptualizer\nconceptualizers\nconceptualizes\nconceptualizing\nconceptually\nconceptus\nconceptuses\nconcern\nconcerned\nconcerning\nconcernment\nconcernments\nconcerns\nconcert\nconcerted\nconcertedly\nconcertedness\nconcertednesses\nconcertgoer\nconcertgoers\nconcertgoing\nconcertgoings\nconcerti\nconcertina\nconcertinas\nconcerting\nconcertini\nconcertino\nconcertinos\nconcertize\nconcertized\nconcertizes\nconcertizing\nconcertmaster\nconcertmasters\nconcertmeister\nconcertmeisters\nconcerto\nconcertos\nconcerts\nconcession\nconcessionaire\nconcessionaires\nconcessional\nconcessionary\nconcessioner\nconcessioners\nconcessions\nconcessive\nconcessively\nconch\nconcha\nconchae\nconchal\nconches\nconchie\nconchies\nconchoid\nconchoidal\nconchoidally\nconchoids\nconchologies\nconchologist\nconchologists\nconchology\nconchs\nconchy\nconcierge\nconcierges\nconciliar\nconciliarly\nconciliate\nconciliated\nconciliates\nconciliating\nconciliation\nconciliations\nconciliative\nconciliator\nconciliators\nconciliatory\nconcinnities\nconcinnity\nconcise\nconcisely\nconciseness\nconcisenesses\nconciser\nconcisest\nconcision\nconcisions\nconclave\nconclaves\nconclude\nconcluded\nconcluder\nconcluders\nconcludes\nconcluding\nconclusion\nconclusionary\nconclusions\nconclusive\nconclusively\nconclusiveness\nconclusivenesses\nconclusory\nconcoct\nconcocted\nconcocter\nconcocters\nconcocting\nconcoction\nconcoctions\nconcoctive\nconcocts\nconcomitance\nconcomitances\nconcomitant\nconcomitantly\nconcomitants\nconcord\nconcordance\nconcordances\nconcordant\nconcordantly\nconcordat\nconcordats\nconcords\nconcourse\nconcourses\nconcrescence\nconcrescences\nconcrescent\nconcrete\nconcreted\nconcretely\nconcreteness\nconcretenesses\nconcretes\nconcreting\nconcretion\nconcretionary\nconcretions\nconcretism\nconcretisms\nconcretist\nconcretists\nconcretization\nconcretizations\nconcretize\nconcretized\nconcretizes\nconcretizing\nconcubinage\nconcubinages\nconcubine\nconcubines\nconcupiscence\nconcupiscences\nconcupiscent\nconcupiscible\nconcur\nconcurred\nconcurrence\nconcurrences\nconcurrencies\nconcurrency\nconcurrent\nconcurrently\nconcurrents\nconcurring\nconcurs\nconcuss\nconcussed\nconcusses\nconcussing\nconcussion\nconcussions\nconcussive\ncondemn\ncondemnable\ncondemnation\ncondemnations\ncondemnatory\ncondemned\ncondemner\ncondemners\ncondemning\ncondemnor\ncondemnors\ncondemns\ncondensable\ncondensate\ncondensates\ncondensation\ncondensational\ncondensations\ncondense\ncondensed\ncondenser\ncondensers\ncondenses\ncondensible\ncondensing\ncondescend\ncondescended\ncondescendence\ncondescendences\ncondescending\ncondescendingly\ncondescends\ncondescension\ncondescensions\ncondign\ncondignly\ncondiment\ncondimental\ncondiments\ncondition\nconditionable\nconditional\nconditionalities\nconditionality\nconditionally\nconditionals\nconditioned\nconditioner\nconditioners\nconditioning\nconditions\ncondo\ncondoes\ncondolatory\ncondole\ncondoled\ncondolence\ncondolences\ncondoler\ncondolers\ncondoles\ncondoling\ncondom\ncondominium\ncondominiums\ncondoms\ncondonable\ncondonation\ncondonations\ncondone\ncondoned\ncondoner\ncondoners\ncondones\ncondoning\ncondor\ncondores\ncondors\ncondos\ncondottiere\ncondottieri\nconduce\nconduced\nconducer\nconducers\nconduces\nconducing\nconducive\nconduciveness\nconducivenesses\nconduct\nconductance\nconductances\nconducted\nconductibilities\nconductibility\nconductible\nconductimetric\nconducting\nconduction\nconductions\nconductive\nconductivities\nconductivity\nconductometric\nconductor\nconductorial\nconductors\nconductress\nconductresses\nconducts\nconduit\nconduits\nconduplicate\ncondylar\ncondyle\ncondyles\ncondyloid\ncondyloma\ncondylomas\ncondylomata\ncondylomatous\ncone\nconed\nconeflower\nconeflowers\nconelrad\nconelrads\nconenose\nconenoses\nconepate\nconepates\nconepatl\nconepatls\ncones\nconey\nconeys\nconfab\nconfabbed\nconfabbing\nconfabs\nconfabulate\nconfabulated\nconfabulates\nconfabulating\nconfabulation\nconfabulations\nconfabulator\nconfabulators\nconfabulatory\nconfect\nconfected\nconfecting\nconfection\nconfectionaries\nconfectionary\nconfectioner\nconfectioneries\nconfectioners\nconfectionery\nconfections\nconfects\nconfederacies\nconfederacy\nconfederal\nconfederate\nconfederated\nconfederates\nconfederating\nconfederation\nconfederations\nconfederative\nconfer\nconferee\nconferees\nconference\nconferences\nconferencing\nconferencings\nconferential\nconferment\nconferments\nconferrable\nconferral\nconferrals\nconferred\nconferrence\nconferrences\nconferrer\nconferrers\nconferring\nconfers\nconferva\nconfervae\nconfervas\nconfess\nconfessable\nconfessed\nconfessedly\nconfesses\nconfessing\nconfession\nconfessional\nconfessionalism\nconfessionalisms\nconfessionalist\nconfessionalists\nconfessionally\nconfessionals\nconfessions\nconfessor\nconfessors\nconfetti\nconfetto\nconfidant\nconfidante\nconfidantes\nconfidants\nconfide\nconfided\nconfidence\nconfidences\nconfident\nconfidential\nconfidentialities\nconfidentiality\nconfidentially\nconfidently\nconfider\nconfiders\nconfides\nconfiding\nconfidingly\nconfidingness\nconfidingnesses\nconfiguration\nconfigurational\nconfigurationally\nconfigurations\nconfigurative\nconfigure\nconfigured\nconfigures\nconfiguring\nconfine\nconfined\nconfinement\nconfinements\nconfiner\nconfiners\nconfines\nconfining\nconfirm\nconfirmabilities\nconfirmability\nconfirmable\nconfirmand\nconfirmands\nconfirmation\nconfirmational\nconfirmations\nconfirmatory\nconfirmed\nconfirmedly\nconfirmedness\nconfirmednesses\nconfirming\nconfirms\nconfiscable\nconfiscatable\nconfiscate\nconfiscated\nconfiscates\nconfiscating\nconfiscation\nconfiscations\nconfiscator\nconfiscators\nconfiscatory\nconfit\nconfiteor\nconfiteors\nconfits\nconfiture\nconfitures\nconflagrant\nconflagration\nconflagrations\nconflate\nconflated\nconflates\nconflating\nconflation\nconflations\nconflict\nconflicted\nconflictful\nconflicting\nconflictingly\nconfliction\nconflictions\nconflictive\nconflicts\nconflictual\nconfluence\nconfluences\nconfluent\nconfluents\nconflux\nconfluxes\nconfocal\nconfocally\nconform\nconformable\nconformably\nconformal\nconformance\nconformances\nconformation\nconformational\nconformations\nconformed\nconformer\nconformers\nconforming\nconformism\nconformisms\nconformist\nconformists\nconformities\nconformity\nconforms\nconfound\nconfounded\nconfoundedly\nconfounder\nconfounders\nconfounding\nconfoundingly\nconfounds\nconfraternities\nconfraternity\nconfrere\nconfreres\nconfront\nconfrontal\nconfrontals\nconfrontation\nconfrontational\nconfrontationist\nconfrontationists\nconfrontations\nconfronted\nconfronter\nconfronters\nconfronting\nconfronts\nconfuse\nconfused\nconfusedly\nconfusedness\nconfusednesses\nconfuses\nconfusing\nconfusingly\nconfusion\nconfusional\nconfusions\nconfutation\nconfutations\nconfutative\nconfute\nconfuted\nconfuter\nconfuters\nconfutes\nconfuting\nconga\ncongaed\ncongaing\ncongas\nconge\ncongeal\ncongealed\ncongealing\ncongealment\ncongealments\ncongeals\ncongee\ncongeed\ncongeeing\ncongees\ncongelation\ncongelations\ncongener\ncongeneric\ncongenerous\ncongeners\ncongenial\ncongenialities\ncongeniality\ncongenially\ncongenital\ncongenitally\nconger\ncongeries\ncongers\nconges\ncongest\ncongested\ncongesting\ncongestion\ncongestions\ncongestive\ncongests\ncongii\ncongius\nconglobate\nconglobated\nconglobates\nconglobating\nconglobation\nconglobations\nconglobe\nconglobed\nconglobes\nconglobing\nconglomerate\nconglomerated\nconglomerates\nconglomerateur\nconglomerateurs\nconglomeratic\nconglomerating\nconglomeration\nconglomerations\nconglomerative\nconglomerator\nconglomerators\nconglutinate\nconglutinated\nconglutinates\nconglutinating\nconglutination\nconglutinations\ncongo\ncongoes\ncongos\ncongou\ncongous\ncongrats\ncongratulate\ncongratulated\ncongratulates\ncongratulating\ncongratulation\ncongratulations\ncongratulator\ncongratulators\ncongratulatory\ncongregant\ncongregants\ncongregate\ncongregated\ncongregates\ncongregating\ncongregation\ncongregational\ncongregationalism\ncongregationalisms\ncongregationalist\ncongregationalists\ncongregations\ncongregator\ncongregators\ncongress\ncongressed\ncongresses\ncongressing\ncongressional\ncongressionally\ncongressman\ncongressmen\ncongresspeople\ncongressperson\ncongresspersons\ncongresswoman\ncongresswomen\ncongruence\ncongruences\ncongruencies\ncongruency\ncongruent\ncongruently\ncongruities\ncongruity\ncongruous\ncongruously\ncongruousness\ncongruousnesses\nconi\nconic\nconical\nconically\nconicities\nconicity\nconics\nconidia\nconidial\nconidian\nconidiophore\nconidiophores\nconidium\nconies\nconifer\nconiferous\nconifers\nconiine\nconiines\nconin\nconine\nconines\nconing\nconins\nconioses\nconiosis\nconium\nconiums\nconjectural\nconjecturally\nconjecture\nconjectured\nconjecturer\nconjecturers\nconjectures\nconjecturing\nconjoin\nconjoined\nconjoining\nconjoins\nconjoint\nconjointly\nconjugal\nconjugalities\nconjugality\nconjugally\nconjugant\nconjugants\nconjugate\nconjugated\nconjugately\nconjugateness\nconjugatenesses\nconjugates\nconjugating\nconjugation\nconjugational\nconjugationally\nconjugations\nconjunct\nconjunction\nconjunctional\nconjunctionally\nconjunctions\nconjunctiva\nconjunctivae\nconjunctival\nconjunctivas\nconjunctive\nconjunctively\nconjunctives\nconjunctivitis\nconjunctivitises\nconjuncts\nconjuncture\nconjunctures\nconjuration\nconjurations\nconjure\nconjured\nconjurer\nconjurers\nconjures\nconjuring\nconjuror\nconjurors\nconk\nconked\nconker\nconkers\nconking\nconks\nconky\nconn\nconnate\nconnately\nconnatural\nconnaturalities\nconnaturality\nconnaturally\nconnect\nconnectable\nconnected\nconnectedly\nconnectedness\nconnectednesses\nconnecter\nconnecters\nconnectible\nconnecting\nconnection\nconnectional\nconnections\nconnective\nconnectively\nconnectives\nconnectivities\nconnectivity\nconnector\nconnectors\nconnects\nconned\nconner\nconners\nconnexion\nconnexions\nconning\nconniption\nconniptions\nconnivance\nconnivances\nconnive\nconnived\nconnivent\nconniver\nconnivers\nconnives\nconniving\nconnoisseur\nconnoisseurs\nconnoisseurship\nconnoisseurships\nconnotation\nconnotational\nconnotations\nconnotative\nconnotatively\nconnote\nconnoted\nconnotes\nconnoting\nconns\nconnubial\nconnubialism\nconnubialisms\nconnubialities\nconnubiality\nconnubially\nconodont\nconodonts\nconoid\nconoidal\nconoids\nconominee\nconominees\nconquer\nconquered\nconquering\nconqueror\nconquerors\nconquers\nconquest\nconquests\nconquian\nconquians\nconquistador\nconquistadores\nconquistadors\ncons\nconsanguine\nconsanguineous\nconsanguineously\nconsanguinities\nconsanguinity\nconscience\nconscienceless\nconsciences\nconscientious\nconscientiously\nconscientiousness\nconscientiousnesses\nconscionable\nconscious\nconsciouses\nconsciously\nconsciousness\nconsciousnesses\nconscribe\nconscribed\nconscribes\nconscribing\nconscript\nconscripted\nconscripting\nconscription\nconscriptions\nconscripts\nconsecrate\nconsecrated\nconsecrates\nconsecrating\nconsecration\nconsecrations\nconsecrative\nconsecrator\nconsecrators\nconsecratory\nconsecution\nconsecutions\nconsecutive\nconsecutively\nconsecutiveness\nconsecutivenesses\nconsensual\nconsensually\nconsensus\nconsensuses\nconsent\nconsentaneous\nconsentaneously\nconsented\nconsenter\nconsenters\nconsenting\nconsentingly\nconsents\nconsequence\nconsequences\nconsequent\nconsequential\nconsequentialities\nconsequentiality\nconsequentially\nconsequentialness\nconsequentialnesses\nconsequently\nconsequents\nconservancies\nconservancy\nconservation\nconservational\nconservationist\nconservationists\nconservations\nconservatism\nconservatisms\nconservative\nconservatively\nconservativeness\nconservativenesses\nconservatives\nconservatize\nconservatized\nconservatizes\nconservatizing\nconservatoire\nconservatoires\nconservator\nconservatorial\nconservatories\nconservators\nconservatorship\nconservatorships\nconservatory\nconserve\nconserved\nconserver\nconservers\nconserves\nconserving\nconsider\nconsiderable\nconsiderables\nconsiderably\nconsiderate\nconsiderately\nconsiderateness\nconsideratenesses\nconsideration\nconsiderations\nconsidered\nconsidering\nconsiders\nconsigliere\nconsiglieri\nconsign\nconsignable\nconsignation\nconsignations\nconsigned\nconsignee\nconsignees\nconsigning\nconsignment\nconsignments\nconsignor\nconsignors\nconsigns\nconsist\nconsisted\nconsistence\nconsistences\nconsistencies\nconsistency\nconsistent\nconsistently\nconsisting\nconsistorial\nconsistories\nconsistory\nconsists\nconsociate\nconsociated\nconsociates\nconsociating\nconsociation\nconsociational\nconsociations\nconsol\nconsolation\nconsolations\nconsolatory\nconsole\nconsoled\nconsoler\nconsolers\nconsoles\nconsolidate\nconsolidated\nconsolidates\nconsolidating\nconsolidation\nconsolidations\nconsolidator\nconsolidators\nconsoling\nconsolingly\nconsols\nconsomme\nconsommes\nconsonance\nconsonances\nconsonancies\nconsonancy\nconsonant\nconsonantal\nconsonantly\nconsonants\nconsort\nconsorted\nconsortia\nconsorting\nconsortium\nconsortiums\nconsorts\nconspecific\nconspecifics\nconspectus\nconspectuses\nconspicuities\nconspicuity\nconspicuous\nconspicuously\nconspicuousness\nconspicuousnesses\nconspiracies\nconspiracy\nconspiration\nconspirational\nconspirations\nconspirator\nconspiratorial\nconspiratorially\nconspirators\nconspire\nconspired\nconspires\nconspiring\nconstable\nconstables\nconstabularies\nconstabulary\nconstancies\nconstancy\nconstant\nconstantan\nconstantans\nconstantly\nconstants\nconstative\nconstatives\nconstellate\nconstellated\nconstellates\nconstellating\nconstellation\nconstellations\nconstellatory\nconsternate\nconsternated\nconsternates\nconsternating\nconsternation\nconsternations\nconstipate\nconstipated\nconstipates\nconstipating\nconstipation\nconstipations\nconstituencies\nconstituency\nconstituent\nconstituently\nconstituents\nconstitute\nconstituted\nconstitutes\nconstituting\nconstitution\nconstitutional\nconstitutionalism\nconstitutionalisms\nconstitutionalist\nconstitutionalists\nconstitutionalities\nconstitutionality\nconstitutionalization\nconstitutionalizations\nconstitutionalize\nconstitutionalized\nconstitutionalizes\nconstitutionalizing\nconstitutionally\nconstitutionals\nconstitutionless\nconstitutions\nconstitutive\nconstitutively\nconstrain\nconstrained\nconstrainedly\nconstraining\nconstrains\nconstraint\nconstraints\nconstrict\nconstricted\nconstricting\nconstriction\nconstrictions\nconstrictive\nconstrictor\nconstrictors\nconstricts\nconstringe\nconstringed\nconstringent\nconstringes\nconstringing\nconstruable\nconstruct\nconstructed\nconstructible\nconstructing\nconstruction\nconstructional\nconstructionally\nconstructionist\nconstructionists\nconstructions\nconstructive\nconstructively\nconstructiveness\nconstructivenesses\nconstructivism\nconstructivisms\nconstructivist\nconstructivists\nconstructor\nconstructors\nconstructs\nconstrue\nconstrued\nconstrues\nconstruing\nconsubstantial\nconsubstantiation\nconsubstantiations\nconsuetude\nconsuetudes\nconsuetudinary\nconsul\nconsular\nconsulate\nconsulates\nconsuls\nconsulship\nconsulships\nconsult\nconsultancies\nconsultancy\nconsultant\nconsultants\nconsultantship\nconsultantships\nconsultation\nconsultations\nconsultative\nconsulted\nconsulter\nconsulters\nconsulting\nconsultive\nconsultor\nconsultors\nconsults\nconsumable\nconsumables\nconsume\nconsumed\nconsumedly\nconsumer\nconsumerism\nconsumerisms\nconsumerist\nconsumeristic\nconsumerists\nconsumers\nconsumership\nconsumerships\nconsumes\nconsuming\nconsummate\nconsummated\nconsummately\nconsummates\nconsummating\nconsummation\nconsummations\nconsummative\nconsummator\nconsummators\nconsummatory\nconsumption\nconsumptions\nconsumptive\nconsumptively\nconsumptives\ncontact\ncontacted\ncontactee\ncontactees\ncontacting\ncontacts\ncontagia\ncontagion\ncontagions\ncontagious\ncontagiously\ncontagiousness\ncontagiousnesses\ncontagium\ncontain\ncontainable\ncontained\ncontainer\ncontainerboard\ncontainerboards\ncontainerisation\ncontainerisations\ncontainerise\ncontainerised\ncontainerises\ncontainerising\ncontainerization\ncontainerizations\ncontainerize\ncontainerized\ncontainerizes\ncontainerizing\ncontainerless\ncontainerport\ncontainerports\ncontainers\ncontainership\ncontainerships\ncontaining\ncontainment\ncontainments\ncontains\ncontaminant\ncontaminants\ncontaminate\ncontaminated\ncontaminates\ncontaminating\ncontamination\ncontaminations\ncontaminative\ncontaminator\ncontaminators\nconte\ncontemn\ncontemned\ncontemner\ncontemners\ncontemning\ncontemnor\ncontemnors\ncontemns\ncontemplate\ncontemplated\ncontemplates\ncontemplating\ncontemplation\ncontemplations\ncontemplative\ncontemplatively\ncontemplativeness\ncontemplativenesses\ncontemplatives\ncontemplator\ncontemplators\ncontemporaneities\ncontemporaneity\ncontemporaneous\ncontemporaneously\ncontemporaneousness\ncontemporaneousnesses\ncontemporaries\ncontemporarily\ncontemporary\ncontemporize\ncontemporized\ncontemporizes\ncontemporizing\ncontempt\ncontemptibilities\ncontemptibility\ncontemptible\ncontemptibleness\ncontemptiblenesses\ncontemptibly\ncontempts\ncontemptuous\ncontemptuously\ncontemptuousness\ncontemptuousnesses\ncontend\ncontended\ncontender\ncontenders\ncontending\ncontends\ncontent\ncontented\ncontentedly\ncontentedness\ncontentednesses\ncontenting\ncontention\ncontentions\ncontentious\ncontentiously\ncontentiousness\ncontentiousnesses\ncontentment\ncontentments\ncontents\nconterminous\nconterminously\ncontes\ncontest\ncontestable\ncontestant\ncontestants\ncontestation\ncontestations\ncontested\ncontester\ncontesters\ncontesting\ncontests\ncontext\ncontextless\ncontexts\ncontextual\ncontextualize\ncontextualized\ncontextualizes\ncontextualizing\ncontextually\ncontexture\ncontextures\ncontiguities\ncontiguity\ncontiguous\ncontiguously\ncontiguousness\ncontiguousnesses\ncontinence\ncontinences\ncontinent\ncontinental\ncontinentally\ncontinentals\ncontinently\ncontinents\ncontingence\ncontingences\ncontingencies\ncontingency\ncontingent\ncontingently\ncontingents\ncontinua\ncontinual\ncontinually\ncontinuance\ncontinuances\ncontinuant\ncontinuants\ncontinuate\ncontinuation\ncontinuations\ncontinuative\ncontinuator\ncontinuators\ncontinue\ncontinued\ncontinuer\ncontinuers\ncontinues\ncontinuing\ncontinuingly\ncontinuities\ncontinuity\ncontinuo\ncontinuos\ncontinuous\ncontinuously\ncontinuousness\ncontinuousnesses\ncontinuum\ncontinuums\nconto\ncontort\ncontorted\ncontorting\ncontortion\ncontortionist\ncontortionistic\ncontortionists\ncontortions\ncontortive\ncontorts\ncontos\ncontour\ncontoured\ncontouring\ncontours\ncontra\ncontraband\ncontrabandist\ncontrabandists\ncontrabands\ncontrabass\ncontrabasses\ncontrabassist\ncontrabassists\ncontrabassoon\ncontrabassoons\ncontraception\ncontraceptions\ncontraceptive\ncontraceptives\ncontract\ncontracted\ncontractibilities\ncontractibility\ncontractible\ncontractile\ncontractilities\ncontractility\ncontracting\ncontraction\ncontractional\ncontractionary\ncontractions\ncontractive\ncontractor\ncontractors\ncontracts\ncontractual\ncontractually\ncontracture\ncontractures\ncontradict\ncontradictable\ncontradicted\ncontradicting\ncontradiction\ncontradictions\ncontradictious\ncontradictor\ncontradictories\ncontradictorily\ncontradictoriness\ncontradictorinesses\ncontradictors\ncontradictory\ncontradicts\ncontradistinction\ncontradistinctions\ncontradistinctive\ncontradistinctively\ncontradistinguish\ncontradistinguished\ncontradistinguishes\ncontradistinguishing\ncontrail\ncontrails\ncontraindicate\ncontraindicated\ncontraindicates\ncontraindicating\ncontraindication\ncontraindications\ncontralateral\ncontralto\ncontraltos\ncontraoctave\ncontraoctaves\ncontraposition\ncontrapositions\ncontrapositive\ncontrapositives\ncontraption\ncontraptions\ncontrapuntal\ncontrapuntally\ncontrapuntist\ncontrapuntists\ncontrarian\ncontrarians\ncontraries\ncontrarieties\ncontrariety\ncontrarily\ncontrariness\ncontrarinesses\ncontrarious\ncontrariwise\ncontrary\ncontras\ncontrast\ncontrastable\ncontrasted\ncontrasting\ncontrastive\ncontrastively\ncontrasts\ncontrasty\ncontravene\ncontravened\ncontravener\ncontraveners\ncontravenes\ncontravening\ncontravention\ncontraventions\ncontredanse\ncontredanses\ncontretemps\ncontribute\ncontributed\ncontributes\ncontributing\ncontribution\ncontributions\ncontributive\ncontributively\ncontributor\ncontributors\ncontributory\ncontrite\ncontritely\ncontriteness\ncontritenesses\ncontrition\ncontritions\ncontrivance\ncontrivances\ncontrive\ncontrived\ncontriver\ncontrivers\ncontrives\ncontriving\ncontrol\ncontrollabilities\ncontrollability\ncontrollable\ncontrolled\ncontroller\ncontrollers\ncontrollership\ncontrollerships\ncontrolling\ncontrolment\ncontrolments\ncontrols\ncontroversial\ncontroversialism\ncontroversialisms\ncontroversialist\ncontroversialists\ncontroversially\ncontroversies\ncontroversy\ncontrovert\ncontroverted\ncontroverter\ncontroverters\ncontrovertible\ncontroverting\ncontroverts\ncontumacies\ncontumacious\ncontumaciously\ncontumacy\ncontumelies\ncontumelious\ncontumeliously\ncontumely\ncontuse\ncontused\ncontuses\ncontusing\ncontusion\ncontusions\nconundrum\nconundrums\nconurbation\nconurbations\nconus\nconvalesce\nconvalesced\nconvalescence\nconvalescences\nconvalescent\nconvalescents\nconvalesces\nconvalescing\nconvect\nconvected\nconvecting\nconvection\nconvectional\nconvections\nconvective\nconvector\nconvectors\nconvects\nconvene\nconvened\nconvener\nconveners\nconvenes\nconvenience\nconveniences\nconveniencies\nconveniency\nconvenient\nconveniently\nconvening\nconvenor\nconvenors\nconvent\nconvented\nconventicle\nconventicler\nconventiclers\nconventicles\nconventing\nconvention\nconventional\nconventionalism\nconventionalisms\nconventionalist\nconventionalists\nconventionalities\nconventionality\nconventionalization\nconventionalizations\nconventionalize\nconventionalized\nconventionalizes\nconventionalizing\nconventionally\nconventioneer\nconventioneers\nconventions\nconvents\nconventual\nconventually\nconventuals\nconverge\nconverged\nconvergence\nconvergences\nconvergencies\nconvergency\nconvergent\nconverges\nconverging\nconversable\nconversance\nconversances\nconversancies\nconversancy\nconversant\nconversation\nconversational\nconversationalist\nconversationalists\nconversationally\nconversations\nconversazione\nconversaziones\nconversazioni\nconverse\nconversed\nconversely\nconverser\nconversers\nconverses\nconversing\nconversion\nconversional\nconversions\nconvert\nconvertaplane\nconvertaplanes\nconverted\nconverter\nconverters\nconvertibilities\nconvertibility\nconvertible\nconvertibleness\nconvertiblenesses\nconvertibles\nconvertibly\nconverting\nconvertiplane\nconvertiplanes\nconvertor\nconvertors\nconverts\nconvex\nconvexes\nconvexities\nconvexity\nconvexly\nconvey\nconveyance\nconveyancer\nconveyancers\nconveyances\nconveyancing\nconveyancings\nconveyed\nconveyer\nconveyers\nconveying\nconveyor\nconveyorise\nconveyorised\nconveyorises\nconveyorising\nconveyorization\nconveyorizations\nconveyorize\nconveyorized\nconveyorizes\nconveyorizing\nconveyors\nconveys\nconvict\nconvicted\nconvicting\nconviction\nconvictions\nconvicts\nconvince\nconvinced\nconvincer\nconvincers\nconvinces\nconvincing\nconvincingly\nconvincingness\nconvincingnesses\nconvivial\nconvivialities\nconviviality\nconvivially\nconvocation\nconvocational\nconvocations\nconvoke\nconvoked\nconvoker\nconvokers\nconvokes\nconvoking\nconvolute\nconvoluted\nconvolutes\nconvoluting\nconvolution\nconvolutions\nconvolve\nconvolved\nconvolves\nconvolving\nconvolvuli\nconvolvulus\nconvolvuluses\nconvoy\nconvoyed\nconvoying\nconvoys\nconvulsant\nconvulsants\nconvulse\nconvulsed\nconvulses\nconvulsing\nconvulsion\nconvulsionary\nconvulsions\nconvulsive\nconvulsively\nconvulsiveness\nconvulsivenesses\ncony\ncoo\ncooch\ncooches\ncoocoo\ncooed\ncooee\ncooeed\ncooeeing\ncooees\ncooer\ncooers\ncooey\ncooeyed\ncooeying\ncooeys\ncoof\ncoofs\ncooing\ncooingly\ncook\ncookable\ncookbook\ncookbooks\ncooked\ncooker\ncookeries\ncookers\ncookery\ncookey\ncookeys\ncookhouse\ncookhouses\ncookie\ncookies\ncooking\ncookings\ncookless\ncookoff\ncookoffs\ncookout\ncookouts\ncooks\ncookshack\ncookshacks\ncookshop\ncookshops\ncookstove\ncookstoves\ncooktop\ncooktops\ncookware\ncookwares\ncooky\ncool\ncoolant\ncoolants\ncooldown\ncooldowns\ncooled\ncooler\ncoolers\ncoolest\ncoolheaded\ncoolie\ncoolies\ncooling\ncoolish\ncoolly\ncoolness\ncoolnesses\ncools\ncoolth\ncoolths\ncooly\ncoomb\ncoombe\ncoombes\ncoombs\ncoon\ncooncan\ncooncans\ncoonhound\ncoonhounds\ncoons\ncoonskin\ncoonskins\ncoontie\ncoonties\ncoop\ncooped\ncooper\ncooperage\ncooperages\ncooperate\ncooperated\ncooperates\ncooperating\ncooperation\ncooperationist\ncooperationists\ncooperations\ncooperative\ncooperatively\ncooperativeness\ncooperativenesses\ncooperatives\ncooperator\ncooperators\ncoopered\ncooperies\ncoopering\ncoopers\ncoopery\ncooping\ncoops\ncoopt\ncoopted\ncoopting\ncooption\ncooptions\ncoopts\ncoordinate\ncoordinated\ncoordinately\ncoordinateness\ncoordinatenesses\ncoordinates\ncoordinating\ncoordination\ncoordinations\ncoordinative\ncoordinator\ncoordinators\ncoos\ncoot\ncooter\ncooters\ncootie\ncooties\ncoots\ncop\ncopacetic\ncopaiba\ncopaibas\ncopal\ncopalm\ncopalms\ncopals\ncoparcenaries\ncoparcenary\ncoparcener\ncoparceners\ncoparent\ncoparents\ncopartner\ncopartnered\ncopartnering\ncopartners\ncopartnership\ncopartnerships\ncopasetic\ncopastor\ncopastors\ncopatron\ncopatrons\ncopayment\ncopayments\ncope\ncopeck\ncopecks\ncoped\ncopemate\ncopemates\ncopen\ncopens\ncopepod\ncopepods\ncoper\ncopers\ncopes\ncopesetic\ncopestone\ncopestones\ncopied\ncopier\ncopiers\ncopies\ncopihue\ncopihues\ncopilot\ncopilots\ncoping\ncopings\ncopingstone\ncopingstones\ncopious\ncopiously\ncopiousness\ncopiousnesses\ncoplanar\ncoplanarities\ncoplanarity\ncoplot\ncoplots\ncoplotted\ncoplotting\ncopolymer\ncopolymeric\ncopolymerization\ncopolymerizations\ncopolymerize\ncopolymerized\ncopolymerizes\ncopolymerizing\ncopolymers\ncopout\ncopouts\ncopped\ncopper\ncopperah\ncopperahs\ncopperas\ncopperases\ncoppered\ncopperhead\ncopperheads\ncoppering\ncopperplate\ncopperplates\ncoppers\ncoppersmith\ncoppersmiths\ncoppery\ncoppice\ncoppiced\ncoppices\ncoppicing\ncopping\ncoppra\ncoppras\ncopra\ncoprah\ncoprahs\ncopras\ncopremia\ncopremias\ncopremic\ncopresent\ncopresented\ncopresenting\ncopresents\ncopresident\ncopresidents\ncoprince\ncoprinces\ncoprincipal\ncoprincipals\ncoprisoner\ncoprisoners\ncoprocessing\ncoprocessings\ncoprocessor\ncoprocessors\ncoproduce\ncoproduced\ncoproducer\ncoproducers\ncoproduces\ncoproducing\ncoproduct\ncoproduction\ncoproductions\ncoproducts\ncoprolite\ncoprolites\ncoprolitic\ncopromoter\ncopromoters\ncoprophagies\ncoprophagous\ncoprophagy\ncoprophilia\ncoprophiliac\ncoprophiliacs\ncoprophilias\ncoprophilous\ncoproprietor\ncoproprietors\ncoproprietorship\ncoproprietorships\ncoprosperities\ncoprosperity\ncops\ncopse\ncopses\ncopter\ncopters\ncopublish\ncopublished\ncopublisher\ncopublishers\ncopublishes\ncopublishing\ncopula\ncopulae\ncopular\ncopulas\ncopulate\ncopulated\ncopulates\ncopulating\ncopulation\ncopulations\ncopulative\ncopulatives\ncopulatory\ncopurified\ncopurifies\ncopurify\ncopurifying\ncopy\ncopybook\ncopybooks\ncopyboy\ncopyboys\ncopycat\ncopycats\ncopycatted\ncopycatting\ncopydesk\ncopydesks\ncopyedit\ncopyedited\ncopyediting\ncopyedits\ncopyhold\ncopyholder\ncopyholders\ncopyholds\ncopying\ncopyist\ncopyists\ncopyread\ncopyreader\ncopyreaders\ncopyreading\ncopyreads\ncopyright\ncopyrightable\ncopyrighted\ncopyrighting\ncopyrights\ncopywriter\ncopywriters\ncoquet\ncoquetries\ncoquetry\ncoquets\ncoquette\ncoquetted\ncoquettes\ncoquetting\ncoquettish\ncoquettishly\ncoquettishness\ncoquettishnesses\ncoquille\ncoquilles\ncoquina\ncoquinas\ncoquito\ncoquitos\ncor\ncoracle\ncoracles\ncoracoid\ncoracoids\ncoral\ncoralbells\ncoralberries\ncoralberry\ncoralline\ncorallines\ncoralloid\ncorals\ncoranto\ncorantoes\ncorantos\ncorban\ncorbans\ncorbeil\ncorbeille\ncorbeilles\ncorbeils\ncorbel\ncorbeled\ncorbeling\ncorbelings\ncorbelled\ncorbelling\ncorbels\ncorbicula\ncorbiculae\ncorbie\ncorbies\ncorbina\ncorbinas\ncorby\ncord\ncordage\ncordages\ncordate\ncordately\ncorded\ncordelle\ncordelled\ncordelles\ncordelling\ncorder\ncorders\ncordgrass\ncordgrasses\ncordial\ncordialities\ncordiality\ncordially\ncordialness\ncordialnesses\ncordials\ncordierite\ncordierites\ncordiform\ncordillera\ncordilleran\ncordilleras\ncording\ncordings\ncordite\ncordites\ncordless\ncordlike\ncordoba\ncordobas\ncordon\ncordoned\ncordoning\ncordons\ncordovan\ncordovans\ncords\ncorduroy\ncorduroyed\ncorduroying\ncorduroys\ncordwain\ncordwainer\ncordwaineries\ncordwainers\ncordwainery\ncordwains\ncordwood\ncordwoods\ncore\ncorecipient\ncorecipients\ncored\ncoredeem\ncoredeemed\ncoredeeming\ncoredeems\ncoreign\ncoreigns\ncorelate\ncorelated\ncorelates\ncorelating\ncoreless\ncoreligionist\ncoreligionists\ncoremia\ncoremium\ncoreopsis\ncorepressor\ncorepressors\ncorequisite\ncorequisites\ncorer\ncorers\ncores\ncoresearcher\ncoresearchers\ncoresident\ncoresidential\ncoresidents\ncorespondent\ncorespondents\ncorf\ncorgi\ncorgis\ncoria\ncoriaceous\ncoriander\ncorianders\ncoring\ncorium\ncork\ncorkage\ncorkages\ncorkboard\ncorkboards\ncorked\ncorker\ncorkers\ncorkier\ncorkiest\ncorkiness\ncorkinesses\ncorking\ncorklike\ncorks\ncorkscrew\ncorkscrewed\ncorkscrewing\ncorkscrews\ncorkwood\ncorkwoods\ncorky\ncorm\ncormel\ncormels\ncormlike\ncormoid\ncormorant\ncormorants\ncormous\ncorms\ncorn\ncornball\ncornballs\ncornbread\ncornbreads\ncorncake\ncorncakes\ncorncob\ncorncobs\ncorncrake\ncorncrakes\ncorncrib\ncorncribs\ncornea\ncorneae\ncorneal\ncorneas\ncorned\ncornel\ncornelian\ncornelians\ncornels\ncorneous\ncorner\ncornerback\ncornerbacks\ncornered\ncornering\ncornerman\ncornermen\ncorners\ncornerstone\ncornerstones\ncornerways\ncornerwise\ncornet\ncornetcies\ncornetcy\ncornetist\ncornetists\ncornets\ncornettist\ncornettists\ncornfed\ncornfield\ncornfields\ncornflakes\ncornflower\ncornflowers\ncornhusk\ncornhusker\ncornhuskers\ncornhusking\ncornhuskings\ncornhusks\ncornice\ncorniced\ncornices\ncorniche\ncorniches\ncornicing\ncornicle\ncornicles\ncornier\ncorniest\ncornification\ncornifications\ncornily\ncorniness\ncorninesses\ncorning\ncornmeal\ncornmeals\ncornpone\ncornpones\ncornrow\ncornrowed\ncornrowing\ncornrows\ncorns\ncornstalk\ncornstalks\ncornstarch\ncornstarches\ncornu\ncornua\ncornual\ncornucopia\ncornucopian\ncornucopias\ncornus\ncornuses\ncornute\ncornuted\ncornuto\ncornutos\ncorny\ncorodies\ncorody\ncorolla\ncorollaries\ncorollary\ncorollas\ncorollate\ncoromandel\ncoromandels\ncorona\ncoronach\ncoronachs\ncoronae\ncoronagraph\ncoronagraphs\ncoronal\ncoronals\ncoronaries\ncoronary\ncoronas\ncoronate\ncoronated\ncoronates\ncoronating\ncoronation\ncoronations\ncoronel\ncoronels\ncoroner\ncoroners\ncoronet\ncoronets\ncoronograph\ncoronographs\ncoronoid\ncorotate\ncorotated\ncorotates\ncorotating\ncorotation\ncorotations\ncorpora\ncorporal\ncorporalities\ncorporality\ncorporally\ncorporals\ncorporate\ncorporately\ncorporation\ncorporations\ncorporatism\ncorporatisms\ncorporatist\ncorporative\ncorporativism\ncorporativisms\ncorporator\ncorporators\ncorporeal\ncorporealities\ncorporeality\ncorporeally\ncorporealness\ncorporealnesses\ncorporeities\ncorporeity\ncorposant\ncorposants\ncorps\ncorpse\ncorpses\ncorpsman\ncorpsmen\ncorpulence\ncorpulences\ncorpulencies\ncorpulency\ncorpulent\ncorpulently\ncorpus\ncorpuscle\ncorpuscles\ncorpuscular\ncorpuses\ncorrade\ncorraded\ncorrades\ncorrading\ncorral\ncorralled\ncorralling\ncorrals\ncorrasion\ncorrasions\ncorrasive\ncorrect\ncorrectable\ncorrected\ncorrecter\ncorrectest\ncorrecting\ncorrection\ncorrectional\ncorrections\ncorrectitude\ncorrectitudes\ncorrective\ncorrectively\ncorrectives\ncorrectly\ncorrectness\ncorrectnesses\ncorrector\ncorrectors\ncorrects\ncorrelatable\ncorrelate\ncorrelated\ncorrelates\ncorrelating\ncorrelation\ncorrelational\ncorrelations\ncorrelative\ncorrelatively\ncorrelatives\ncorrelator\ncorrelators\ncorrespond\ncorresponded\ncorrespondence\ncorrespondences\ncorrespondencies\ncorrespondency\ncorrespondent\ncorrespondents\ncorresponding\ncorrespondingly\ncorresponds\ncorresponsive\ncorrida\ncorridas\ncorridor\ncorridors\ncorrie\ncorries\ncorrigenda\ncorrigendum\ncorrigibilities\ncorrigibility\ncorrigible\ncorrival\ncorrivals\ncorroborant\ncorroborate\ncorroborated\ncorroborates\ncorroborating\ncorroboration\ncorroborations\ncorroborative\ncorroborator\ncorroborators\ncorroboratory\ncorroboree\ncorroborees\ncorrode\ncorroded\ncorrodes\ncorrodible\ncorrodies\ncorroding\ncorrody\ncorrosion\ncorrosions\ncorrosive\ncorrosively\ncorrosiveness\ncorrosivenesses\ncorrosives\ncorrugate\ncorrugated\ncorrugates\ncorrugating\ncorrugation\ncorrugations\ncorrupt\ncorrupted\ncorrupter\ncorrupters\ncorruptest\ncorruptibilities\ncorruptibility\ncorruptible\ncorruptibly\ncorrupting\ncorruption\ncorruptionist\ncorruptionists\ncorruptions\ncorruptive\ncorruptively\ncorruptly\ncorruptness\ncorruptnesses\ncorruptor\ncorruptors\ncorrupts\ncors\ncorsac\ncorsacs\ncorsage\ncorsages\ncorsair\ncorsairs\ncorse\ncorselet\ncorselets\ncorselette\ncorselettes\ncorses\ncorset\ncorseted\ncorsetiere\ncorsetieres\ncorseting\ncorsetries\ncorsetry\ncorsets\ncorslet\ncorslets\ncortege\ncorteges\ncortex\ncortexes\ncortical\ncortically\ncortices\ncorticoid\ncorticoids\ncorticosteroid\ncorticosteroids\ncorticosterone\ncorticosterones\ncorticotrophin\ncorticotrophins\ncorticotropin\ncorticotropins\ncortin\ncortins\ncortisol\ncortisols\ncortisone\ncortisones\ncoruler\ncorulers\ncorundum\ncorundums\ncoruscant\ncoruscate\ncoruscated\ncoruscates\ncoruscating\ncoruscation\ncoruscations\ncorvee\ncorvees\ncorves\ncorvet\ncorvets\ncorvette\ncorvettes\ncorvina\ncorvinas\ncorvine\ncory\ncorybant\ncorybantes\ncorybantic\ncorybants\ncorydalis\ncorydalises\ncorymb\ncorymbed\ncorymbose\ncorymbosely\ncorymbs\ncorynebacteria\ncorynebacterial\ncorynebacterium\ncoryneform\ncoryphaei\ncoryphaeus\ncoryphee\ncoryphees\ncoryza\ncoryzal\ncoryzas\ncos\ncoscript\ncoscripted\ncoscripting\ncoscripts\ncosec\ncosecant\ncosecants\ncosecs\ncoses\ncoset\ncosets\ncosey\ncoseys\ncosh\ncoshed\ncosher\ncoshered\ncoshering\ncoshers\ncoshes\ncoshing\ncosie\ncosied\ncosier\ncosies\ncosiest\ncosign\ncosignatories\ncosignatory\ncosigned\ncosigner\ncosigners\ncosigning\ncosigns\ncosily\ncosine\ncosines\ncosiness\ncosinesses\ncosmetic\ncosmetically\ncosmetician\ncosmeticians\ncosmeticize\ncosmeticized\ncosmeticizes\ncosmeticizing\ncosmetics\ncosmetologies\ncosmetologist\ncosmetologists\ncosmetology\ncosmic\ncosmical\ncosmically\ncosmism\ncosmisms\ncosmist\ncosmists\ncosmochemical\ncosmochemist\ncosmochemistries\ncosmochemistry\ncosmochemists\ncosmogenic\ncosmogonic\ncosmogonical\ncosmogonies\ncosmogonist\ncosmogonists\ncosmogony\ncosmographer\ncosmographers\ncosmographic\ncosmographical\ncosmographies\ncosmography\ncosmological\ncosmologically\ncosmologies\ncosmologist\ncosmologists\ncosmology\ncosmonaut\ncosmonauts\ncosmopolis\ncosmopolises\ncosmopolitan\ncosmopolitanism\ncosmopolitanisms\ncosmopolitans\ncosmopolite\ncosmopolites\ncosmopolitism\ncosmopolitisms\ncosmos\ncosmoses\ncosponsor\ncosponsored\ncosponsoring\ncosponsors\ncosponsorship\ncosponsorships\ncoss\ncossack\ncossacks\ncosset\ncosseted\ncosseting\ncossets\ncost\ncosta\ncostae\ncostal\ncostar\ncostard\ncostards\ncostarred\ncostarring\ncostars\ncostate\ncosted\ncoster\ncostermonger\ncostermongers\ncosters\ncosting\ncostive\ncostively\ncostiveness\ncostivenesses\ncostless\ncostlessly\ncostlier\ncostliest\ncostliness\ncostlinesses\ncostly\ncostmaries\ncostmary\ncostrel\ncostrels\ncosts\ncostume\ncostumed\ncostumer\ncostumeries\ncostumers\ncostumery\ncostumes\ncostumey\ncostumier\ncostumiers\ncostuming\ncosurfactant\ncosurfactants\ncosy\ncosying\ncot\ncotan\ncotangent\ncotangents\ncotans\ncote\ncoteau\ncoteaus\ncoteaux\ncoted\ncotenant\ncotenants\ncoterie\ncoteries\ncoterminous\ncoterminously\ncotes\ncothurn\ncothurni\ncothurns\ncothurnus\ncotidal\ncotillion\ncotillions\ncotillon\ncotillons\ncoting\ncotoneaster\ncotoneasters\ncotquean\ncotqueans\ncotransduce\ncotransduced\ncotransduces\ncotransducing\ncotransduction\ncotransductions\ncotransfer\ncotransferred\ncotransferring\ncotransfers\ncotransport\ncotransported\ncotransporting\ncotransports\ncotrustee\ncotrustees\ncots\ncotta\ncottae\ncottage\ncottager\ncottagers\ncottages\ncottagey\ncottar\ncottars\ncottas\ncotter\ncottered\ncotterless\ncotters\ncottier\ncottiers\ncotton\ncottoned\ncottoning\ncottonmouth\ncottonmouths\ncottons\ncottonseed\ncottonseeds\ncottontail\ncottontails\ncottonweed\ncottonweeds\ncottonwood\ncottonwoods\ncottony\ncotyledon\ncotyledonary\ncotyledons\ncotyloid\ncotylosaur\ncotylosaurs\ncotype\ncotypes\ncouch\ncouchant\ncouched\ncoucher\ncouchers\ncouches\ncouching\ncouchings\ncoude\ncougar\ncougars\ncough\ncoughed\ncougher\ncoughers\ncoughing\ncoughs\ncould\ncouldest\ncouldst\ncoulee\ncoulees\ncoulis\ncoulises\ncoulisse\ncoulisses\ncouloir\ncouloirs\ncoulomb\ncoulombic\ncoulombs\ncoulometer\ncoulometers\ncoulometric\ncoulometrically\ncoulometries\ncoulometry\ncoulter\ncoulters\ncoumaric\ncoumarin\ncoumarins\ncoumarou\ncoumarous\ncouncil\ncouncillor\ncouncillors\ncouncillorship\ncouncillorships\ncouncilman\ncouncilmanic\ncouncilmen\ncouncilor\ncouncilors\ncouncils\ncouncilwoman\ncouncilwomen\ncounsel\ncounseled\ncounselee\ncounselees\ncounseling\ncounselings\ncounselled\ncounselling\ncounsellings\ncounsellor\ncounsellors\ncounselor\ncounselors\ncounselorship\ncounselorships\ncounsels\ncount\ncountabilities\ncountability\ncountable\ncountably\ncountdown\ncountdowns\ncounted\ncountenance\ncountenanced\ncountenancer\ncountenancers\ncountenances\ncountenancing\ncounter\ncounteraccusation\ncounteraccusations\ncounteract\ncounteracted\ncounteracting\ncounteraction\ncounteractions\ncounteractive\ncounteracts\ncounteradaptation\ncounteradaptations\ncounteradvertising\ncounteradvertisings\ncounteragent\ncounteragents\ncounteraggression\ncounteraggressions\ncounterargue\ncounterargued\ncounterargues\ncounterarguing\ncounterargument\ncounterarguments\ncounterassault\ncounterassaults\ncounterattack\ncounterattacked\ncounterattacker\ncounterattackers\ncounterattacking\ncounterattacks\ncounterbade\ncounterbalance\ncounterbalanced\ncounterbalances\ncounterbalancing\ncounterbid\ncounterbidden\ncounterbidding\ncounterbids\ncounterblast\ncounterblasts\ncounterblockade\ncounterblockaded\ncounterblockades\ncounterblockading\ncounterblow\ncounterblows\ncountercampaign\ncountercampaigns\ncounterchange\ncounterchanged\ncounterchanges\ncounterchanging\ncountercharge\ncountercharged\ncountercharges\ncountercharging\ncountercheck\ncounterchecked\ncounterchecking\ncounterchecks\ncounterclaim\ncounterclaimed\ncounterclaiming\ncounterclaims\ncounterclockwise\ncountercommercial\ncountercomplaint\ncountercomplaints\ncounterconditioning\ncounterconditionings\ncounterconspiracies\ncounterconspiracy\ncounterconvention\ncounterconventions\ncountercountermeasure\ncountercountermeasures\ncountercoup\ncountercoups\ncountercries\ncountercriticism\ncountercriticisms\ncountercry\ncountercultural\ncounterculturalism\ncounterculturalisms\ncounterculture\ncountercultures\ncounterculturist\ncounterculturists\ncountercurrent\ncountercurrently\ncountercurrents\ncountercyclical\ncountercyclically\ncounterdemand\ncounterdemands\ncounterdemonstrate\ncounterdemonstrated\ncounterdemonstrates\ncounterdemonstrating\ncounterdemonstration\ncounterdemonstrations\ncounterdemonstrator\ncounterdemonstrators\ncounterdeployment\ncounterdeployments\ncountered\ncountereducational\ncountereffort\ncounterefforts\ncounterespionage\ncounterespionages\ncounterevidence\ncounterevidences\ncounterexample\ncounterexamples\ncounterfactual\ncounterfeit\ncounterfeited\ncounterfeiter\ncounterfeiters\ncounterfeiting\ncounterfeits\ncounterfire\ncounterfired\ncounterfires\ncounterfiring\ncounterflow\ncounterflows\ncounterfoil\ncounterfoils\ncounterforce\ncounterforces\ncountergovernment\ncountergovernments\ncounterguerilla\ncounterguerillas\ncounterguerrilla\ncounterguerrillas\ncounterhypotheses\ncounterhypothesis\ncounterimage\ncounterimages\ncounterincentive\ncounterincentives\ncounterinflation\ncounterinflationary\ncounterinfluence\ncounterinfluenced\ncounterinfluences\ncounterinfluencing\ncountering\ncounterinstance\ncounterinstances\ncounterinstitution\ncounterinstitutions\ncounterinsurgencies\ncounterinsurgency\ncounterinsurgent\ncounterinsurgents\ncounterintelligence\ncounterintelligences\ncounterinterpretation\ncounterinterpretations\ncounterintuitive\ncounterintuitively\ncounterion\ncounterions\ncounterirritant\ncounterirritants\ncounterman\ncountermand\ncountermanded\ncountermanding\ncountermands\ncountermarch\ncountermarched\ncountermarches\ncountermarching\ncountermeasure\ncountermeasures\ncountermelodies\ncountermelody\ncountermemo\ncountermemos\ncountermen\ncountermine\ncountermined\ncountermines\ncountermining\ncountermobilization\ncountermobilizations\ncountermove\ncountermoved\ncountermovement\ncountermovements\ncountermoves\ncountermoving\ncountermyth\ncountermyths\ncounteroffensive\ncounteroffensives\ncounteroffer\ncounteroffers\ncounterorder\ncounterordered\ncounterordering\ncounterorders\ncounterpane\ncounterpanes\ncounterpart\ncounterparts\ncounterpetition\ncounterpetitioned\ncounterpetitioning\ncounterpetitions\ncounterpicket\ncounterpicketed\ncounterpicketing\ncounterpickets\ncounterplan\ncounterplans\ncounterplay\ncounterplayer\ncounterplayers\ncounterplays\ncounterplea\ncounterpleas\ncounterplot\ncounterplots\ncounterplotted\ncounterplotting\ncounterploy\ncounterploys\ncounterpoint\ncounterpointed\ncounterpointing\ncounterpoints\ncounterpoise\ncounterpoised\ncounterpoises\ncounterpoising\ncounterpose\ncounterposed\ncounterposes\ncounterposing\ncounterpower\ncounterpowers\ncounterpressure\ncounterpressures\ncounterproductive\ncounterprogramming\ncounterprogrammings\ncounterproject\ncounterprojects\ncounterpropaganda\ncounterpropagandas\ncounterproposal\ncounterproposals\ncounterprotest\ncounterprotests\ncounterpunch\ncounterpunched\ncounterpuncher\ncounterpunchers\ncounterpunches\ncounterpunching\ncounterquestion\ncounterquestioned\ncounterquestioning\ncounterquestions\ncounterraid\ncounterraided\ncounterraiding\ncounterraids\ncounterrallied\ncounterrallies\ncounterrally\ncounterrallying\ncounterreaction\ncounterreactions\ncounterreform\ncounterreformation\ncounterreformations\ncounterreformer\ncounterreformers\ncounterreforms\ncounterresponse\ncounterresponses\ncounterretaliation\ncounterretaliations\ncounterrevolution\ncounterrevolutionaries\ncounterrevolutionary\ncounterrevolutions\ncounters\ncounterscientific\ncountershading\ncountershadings\ncountershot\ncountershots\ncountersign\ncountersignature\ncountersignatures\ncountersigned\ncountersigning\ncountersigns\ncountersink\ncountersinking\ncountersinks\ncountersniper\ncountersnipers\ncounterspell\ncounterspells\ncounterspies\ncounterspy\ncounterstain\ncounterstained\ncounterstaining\ncounterstains\ncounterstate\ncounterstated\ncounterstatement\ncounterstatements\ncounterstates\ncounterstating\ncounterstep\ncounterstepped\ncounterstepping\ncountersteps\ncounterstrategies\ncounterstrategist\ncounterstrategists\ncounterstrategy\ncounterstream\ncounterstreams\ncounterstrike\ncounterstrikes\ncounterstroke\ncounterstrokes\ncounterstyle\ncounterstyles\ncountersue\ncountersued\ncountersues\ncountersuggestion\ncountersuggestions\ncountersuing\ncountersuit\ncountersuits\ncountersunk\ncountersurveillance\ncountersurveillances\ncountertactics\ncountertendencies\ncountertendency\ncountertenor\ncountertenors\ncounterterror\ncounterterrorism\ncounterterrorisms\ncounterterrorist\ncounterterrorists\ncounterterrors\ncounterthreat\ncounterthreats\ncounterthrust\ncounterthrusts\ncountertop\ncountertops\ncountertrade\ncountertrades\ncountertradition\ncountertraditions\ncountertransference\ncountertransferences\ncountertrend\ncountertrends\ncountervail\ncountervailed\ncountervailing\ncountervails\ncounterview\ncounterviews\ncounterviolence\ncounterviolences\ncounterweight\ncounterweighted\ncounterweighting\ncounterweights\ncounterworld\ncounterworlds\ncountess\ncountesses\ncountian\ncountians\ncounties\ncounting\ncountinghouse\ncountinghouses\ncountless\ncountlessly\ncountries\ncountrified\ncountry\ncountryfied\ncountryish\ncountryman\ncountrymen\ncountryseat\ncountryseats\ncountryside\ncountrysides\ncountrywide\ncountrywoman\ncountrywomen\ncounts\ncounty\ncoup\ncoupe\ncouped\ncoupes\ncouping\ncouple\ncoupled\ncouplement\ncouplements\ncoupler\ncouplers\ncouples\ncouplet\ncouplets\ncoupling\ncouplings\ncoupon\ncouponing\ncouponings\ncoupons\ncoups\ncourage\ncourageous\ncourageously\ncourageousness\ncourageousnesses\ncourages\ncourant\ncourante\ncourantes\ncouranto\ncourantoes\ncourantos\ncourants\ncourgette\ncourgettes\ncourier\ncouriers\ncourlan\ncourlans\ncourse\ncoursed\ncourser\ncoursers\ncourses\ncourseware\ncoursewares\ncoursing\ncoursings\ncourt\ncourted\ncourteous\ncourteously\ncourteousness\ncourteousnesses\ncourter\ncourters\ncourtesan\ncourtesans\ncourtesied\ncourtesies\ncourtesy\ncourtesying\ncourthouse\ncourthouses\ncourtier\ncourtiers\ncourting\ncourtlier\ncourtliest\ncourtliness\ncourtlinesses\ncourtly\ncourtroom\ncourtrooms\ncourts\ncourtship\ncourtships\ncourtside\ncourtsides\ncourtyard\ncourtyards\ncouscous\ncouscouses\ncousin\ncousinage\ncousinages\ncousinhood\ncousinhoods\ncousinly\ncousinries\ncousinry\ncousins\ncousinship\ncousinships\ncouteau\ncouteaux\ncouter\ncouters\ncouth\ncouther\ncouthest\ncouthie\ncouthier\ncouthiest\ncouths\ncouture\ncoutures\ncouturier\ncouturiere\ncouturieres\ncouturiers\ncouvade\ncouvades\ncovalence\ncovalences\ncovalencies\ncovalency\ncovalent\ncovalently\ncovariance\ncovariances\ncovariant\ncovariation\ncovariations\ncove\ncoved\ncovelline\ncovellines\ncovellite\ncovellites\ncoven\ncovenant\ncovenantal\ncovenanted\ncovenantee\ncovenantees\ncovenanter\ncovenanters\ncovenanting\ncovenantor\ncovenantors\ncovenants\ncovens\ncover\ncoverable\ncoverage\ncoverages\ncoverall\ncoveralled\ncoveralls\ncovered\ncoverer\ncoverers\ncovering\ncoverings\ncoverless\ncoverlet\ncoverlets\ncoverlid\ncoverlids\ncovers\ncoverslip\ncoverslips\ncovert\ncovertly\ncovertness\ncovertnesses\ncoverts\ncoverture\ncovertures\ncoverup\ncoverups\ncoves\ncovet\ncovetable\ncoveted\ncoveter\ncoveters\ncoveting\ncovetingly\ncovetous\ncovetously\ncovetousness\ncovetousnesses\ncovets\ncovey\ncoveys\ncovin\ncoving\ncovings\ncovins\ncow\ncowage\ncowages\ncoward\ncowardice\ncowardices\ncowardliness\ncowardlinesses\ncowardly\ncowards\ncowbane\ncowbanes\ncowbell\ncowbells\ncowberries\ncowberry\ncowbind\ncowbinds\ncowbird\ncowbirds\ncowboy\ncowboys\ncowcatcher\ncowcatchers\ncowed\ncowedly\ncower\ncowered\ncowering\ncowers\ncowfish\ncowfishes\ncowflap\ncowflaps\ncowflop\ncowflops\ncowgirl\ncowgirls\ncowhage\ncowhages\ncowhand\ncowhands\ncowherb\ncowherbs\ncowherd\ncowherds\ncowhide\ncowhided\ncowhides\ncowhiding\ncowier\ncowiest\ncowing\ncowinner\ncowinners\ncowl\ncowled\ncowlick\ncowlicks\ncowling\ncowlings\ncowls\ncowlstaff\ncowlstaffs\ncowlstaves\ncowman\ncowmen\ncoworker\ncoworkers\ncowpat\ncowpats\ncowpea\ncowpeas\ncowpie\ncowpies\ncowplop\ncowplops\ncowpoke\ncowpokes\ncowpox\ncowpoxes\ncowpuncher\ncowpunchers\ncowrie\ncowries\ncowrite\ncowrites\ncowriting\ncowritten\ncowrote\ncowry\ncows\ncowshed\ncowsheds\ncowskin\ncowskins\ncowslip\ncowslips\ncowy\ncox\ncoxa\ncoxae\ncoxal\ncoxalgia\ncoxalgias\ncoxalgic\ncoxalgies\ncoxalgy\ncoxcomb\ncoxcombical\ncoxcombries\ncoxcombry\ncoxcombs\ncoxed\ncoxes\ncoxing\ncoxitides\ncoxitis\ncoxswain\ncoxswained\ncoxswaining\ncoxswains\ncoy\ncoydog\ncoydogs\ncoyed\ncoyer\ncoyest\ncoying\ncoyish\ncoyly\ncoyness\ncoynesses\ncoyote\ncoyotes\ncoyotillo\ncoyotillos\ncoypou\ncoypous\ncoypu\ncoypus\ncoys\ncoz\ncozen\ncozenage\ncozenages\ncozened\ncozener\ncozeners\ncozening\ncozens\ncozes\ncozey\ncozeys\ncozie\ncozied\ncozier\ncozies\ncoziest\ncozily\ncoziness\ncozinesses\ncozy\ncozying\ncozzes\ncraal\ncraaled\ncraaling\ncraals\ncrab\ncrabbed\ncrabbedness\ncrabbednesses\ncrabber\ncrabbers\ncrabbier\ncrabbiest\ncrabbily\ncrabbing\ncrabby\ncrabgrass\ncrabgrasses\ncrabmeat\ncrabmeats\ncrabs\ncrabstick\ncrabsticks\ncrabwise\ncrack\ncrackajack\ncrackajacks\ncrackback\ncrackbacks\ncrackbrain\ncrackbrained\ncrackbrains\ncrackdown\ncrackdowns\ncracked\ncracker\ncrackerjack\ncrackerjacks\ncrackers\ncracking\ncrackings\ncrackle\ncrackled\ncrackles\ncrackleware\ncracklewares\ncracklier\ncrackliest\ncrackling\ncracklings\ncrackly\ncracknel\ncracknels\ncrackpot\ncrackpots\ncracks\ncracksman\ncracksmen\ncrackup\ncrackups\ncracky\ncradle\ncradled\ncradler\ncradlers\ncradles\ncradlesong\ncradlesongs\ncradling\ncraft\ncrafted\ncraftier\ncraftiest\ncraftily\ncraftiness\ncraftinesses\ncrafting\ncrafts\ncraftsman\ncraftsmanlike\ncraftsmanly\ncraftsmanship\ncraftsmanships\ncraftsmen\ncraftspeople\ncraftsperson\ncraftspersons\ncraftswoman\ncraftswomen\ncrafty\ncrag\ncragged\ncraggier\ncraggiest\ncraggily\ncragginess\ncragginesses\ncraggy\ncrags\ncragsman\ncragsmen\ncrake\ncrakes\ncram\ncrambe\ncrambes\ncrambo\ncramboes\ncrambos\ncrammed\ncrammer\ncrammers\ncramming\ncramoisie\ncramoisies\ncramoisy\ncramp\ncramped\ncramping\ncrampit\ncrampits\ncrampon\ncrampons\ncrampoon\ncrampoons\ncramps\ncrams\ncranberries\ncranberry\ncranch\ncranched\ncranches\ncranching\ncrane\ncraned\ncranes\ncranesbill\ncranesbills\ncrania\ncranial\ncranially\ncraniate\ncraniates\ncraning\ncraniocerebral\ncraniofacial\ncraniologies\ncraniology\ncraniometries\ncraniometry\ncraniosacral\ncraniotomies\ncraniotomy\ncranium\ncraniums\ncrank\ncrankcase\ncrankcases\ncranked\ncranker\ncrankest\ncrankier\ncrankiest\ncrankily\ncrankiness\ncrankinesses\ncranking\ncrankish\ncrankle\ncrankled\ncrankles\ncrankling\ncrankly\ncrankous\ncrankpin\ncrankpins\ncranks\ncrankshaft\ncrankshafts\ncranky\ncrannied\ncrannies\ncrannog\ncrannoge\ncrannoges\ncrannogs\ncranny\ncranreuch\ncranreuchs\ncrap\ncrape\ncraped\ncrapes\ncraping\ncrapped\ncrapper\ncrappers\ncrappie\ncrappier\ncrappies\ncrappiest\ncrapping\ncrappy\ncraps\ncrapshoot\ncrapshooter\ncrapshooters\ncrapshoots\ncrapulous\ncrases\ncrash\ncrashed\ncrasher\ncrashers\ncrashes\ncrashing\ncrashingly\ncrashworthiness\ncrashworthinesses\ncrashworthy\ncrasis\ncrass\ncrasser\ncrassest\ncrassitude\ncrassitudes\ncrassly\ncrassness\ncrassnesses\ncratch\ncratches\ncrate\ncrated\ncrater\ncratered\ncratering\ncraterlet\ncraterlets\ncraterlike\ncraters\ncrates\ncrating\ncraton\ncratonic\ncratons\ncraunch\ncraunched\ncraunches\ncraunching\ncravat\ncravats\ncrave\ncraved\ncraven\ncravened\ncravening\ncravenly\ncravenness\ncravennesses\ncravens\ncraver\ncravers\ncraves\ncraving\ncravings\ncraw\ncrawdad\ncrawdads\ncrawfish\ncrawfished\ncrawfishes\ncrawfishing\ncrawl\ncrawled\ncrawler\ncrawlers\ncrawlier\ncrawliest\ncrawling\ncrawls\ncrawlspace\ncrawlspaces\ncrawlway\ncrawlways\ncrawly\ncraws\ncrayfish\ncrayfishes\ncrayola\ncrayolas\ncrayon\ncrayoned\ncrayoning\ncrayonist\ncrayonists\ncrayons\ncraze\ncrazed\ncrazes\ncrazier\ncrazies\ncraziest\ncrazily\ncraziness\ncrazinesses\ncrazing\ncrazy\ncrazyweed\ncrazyweeds\ncreak\ncreaked\ncreakier\ncreakiest\ncreakily\ncreakiness\ncreakinesses\ncreaking\ncreaks\ncreaky\ncream\ncreamcups\ncreamed\ncreamer\ncreameries\ncreamers\ncreamery\ncreamier\ncreamiest\ncreamily\ncreaminess\ncreaminesses\ncreaming\ncreampuff\ncreampuffs\ncreams\ncreamware\ncreamwares\ncreamy\ncrease\ncreased\ncreaseless\ncreaser\ncreasers\ncreases\ncreasier\ncreasiest\ncreasing\ncreasy\ncreate\ncreated\ncreates\ncreatin\ncreatine\ncreatines\ncreating\ncreatinine\ncreatinines\ncreatins\ncreation\ncreationism\ncreationisms\ncreationist\ncreationists\ncreations\ncreative\ncreatively\ncreativeness\ncreativenesses\ncreativities\ncreativity\ncreator\ncreators\ncreatural\ncreature\ncreaturehood\ncreaturehoods\ncreatureliness\ncreaturelinesses\ncreaturely\ncreatures\ncreche\ncreches\ncredal\ncredence\ncredences\ncredenda\ncredendum\ncredent\ncredential\ncredentialed\ncredentialing\ncredentialism\ncredentialisms\ncredentialled\ncredentialling\ncredentials\ncredenza\ncredenzas\ncredibilities\ncredibility\ncredible\ncredibly\ncredit\ncreditabilities\ncreditability\ncreditable\ncreditableness\ncreditablenesses\ncreditably\ncredited\ncrediting\ncreditor\ncreditors\ncredits\ncreditworthiness\ncreditworthinesses\ncreditworthy\ncredo\ncredos\ncredulities\ncredulity\ncredulous\ncredulously\ncredulousness\ncredulousnesses\ncreed\ncreedal\ncreeds\ncreek\ncreeks\ncreel\ncreeled\ncreeling\ncreels\ncreep\ncreepage\ncreepages\ncreeper\ncreepers\ncreepie\ncreepier\ncreepies\ncreepiest\ncreepily\ncreepiness\ncreepinesses\ncreeping\ncreeps\ncreepy\ncreese\ncreeses\ncreesh\ncreeshed\ncreeshes\ncreeshing\ncremains\ncremate\ncremated\ncremates\ncremating\ncremation\ncremations\ncremator\ncrematoria\ncrematories\ncrematorium\ncrematoriums\ncremators\ncrematory\ncreme\ncremes\ncrenate\ncrenated\ncrenation\ncrenations\ncrenel\ncrenelated\ncrenelation\ncrenelations\ncreneled\ncreneling\ncrenellated\ncrenellation\ncrenellations\ncrenelle\ncrenelled\ncrenelles\ncrenelling\ncrenels\ncrenulate\ncrenulated\ncrenulation\ncrenulations\ncreodont\ncreodonta\ncreodonts\ncreole\ncreoles\ncreolise\ncreolised\ncreolises\ncreolising\ncreolization\ncreolizations\ncreolize\ncreolized\ncreolizes\ncreolizing\ncreosol\ncreosols\ncreosote\ncreosoted\ncreosotes\ncreosoting\ncrepe\ncreped\ncrepes\ncrepey\ncrepier\ncrepiest\ncreping\ncrepitant\ncrepitate\ncrepitated\ncrepitates\ncrepitating\ncrepitation\ncrepitations\ncrepon\ncrepons\ncrept\ncrepuscle\ncrepuscles\ncrepuscular\ncrepuscule\ncrepuscules\ncrepy\ncrescendi\ncrescendo\ncrescendoed\ncrescendoes\ncrescendoing\ncrescendos\ncrescent\ncrescentic\ncrescents\ncrescive\ncrescively\ncresol\ncresols\ncress\ncresses\ncresset\ncressets\ncrest\ncrestal\ncrested\ncrestfallen\ncrestfallenly\ncrestfallenness\ncrestfallennesses\ncresting\ncrestings\ncrestless\ncrests\ncresyl\ncresylic\ncresyls\ncretic\ncretics\ncretin\ncretinism\ncretinisms\ncretinous\ncretins\ncretonne\ncretonnes\ncrevalle\ncrevalles\ncrevasse\ncrevassed\ncrevasses\ncrevassing\ncrevice\ncreviced\ncrevices\ncrew\ncrewcut\ncrewcuts\ncrewed\ncrewel\ncrewels\ncrewelwork\ncrewelworks\ncrewing\ncrewless\ncrewman\ncrewmate\ncrewmates\ncrewmen\ncrewneck\ncrewnecks\ncrews\ncrib\ncribbage\ncribbages\ncribbed\ncribber\ncribbers\ncribbing\ncribbings\ncribbled\ncribriform\ncribrous\ncribs\ncribwork\ncribworks\ncricetid\ncricetids\ncrick\ncricked\ncricket\ncricketed\ncricketer\ncricketers\ncricketing\ncrickets\ncrickey\ncricking\ncricks\ncricoid\ncricoids\ncried\ncrier\ncriers\ncries\ncrikey\ncrime\ncrimeless\ncrimes\ncriminal\ncriminalistics\ncriminalities\ncriminality\ncriminalization\ncriminalizations\ncriminalize\ncriminalized\ncriminalizes\ncriminalizing\ncriminally\ncriminals\ncriminate\ncriminated\ncriminates\ncriminating\ncrimination\ncriminations\ncriminological\ncriminologically\ncriminologies\ncriminologist\ncriminologists\ncriminology\ncriminous\ncrimmer\ncrimmers\ncrimp\ncrimped\ncrimper\ncrimpers\ncrimpier\ncrimpiest\ncrimping\ncrimple\ncrimpled\ncrimples\ncrimpling\ncrimps\ncrimpy\ncrimson\ncrimsoned\ncrimsoning\ncrimsons\ncringe\ncringed\ncringer\ncringers\ncringes\ncringing\ncringle\ncringles\ncrinite\ncrinites\ncrinkle\ncrinkled\ncrinkles\ncrinklier\ncrinkliest\ncrinkling\ncrinkly\ncrinoid\ncrinoids\ncrinoline\ncrinolined\ncrinolines\ncrinum\ncrinums\ncriollo\ncriollos\ncripe\ncripes\ncripple\ncrippled\ncrippler\ncripplers\ncripples\ncrippling\ncripplingly\ncris\ncrises\ncrisic\ncrisis\ncrisp\ncrispate\ncrispbread\ncrispbreads\ncrisped\ncrispen\ncrispened\ncrispening\ncrispens\ncrisper\ncrispers\ncrispest\ncrispier\ncrispiest\ncrispily\ncrispiness\ncrispinesses\ncrisping\ncrisply\ncrispness\ncrispnesses\ncrisps\ncrispy\ncrissa\ncrissal\ncrisscross\ncrisscrossed\ncrisscrosses\ncrisscrossing\ncrissum\ncrista\ncristae\ncristate\ncriteria\ncriterion\ncriterions\ncriterium\ncriteriums\ncritic\ncritical\ncriticalities\ncriticality\ncritically\ncriticalness\ncriticalnesses\ncriticaster\ncriticasters\ncriticise\ncriticised\ncriticises\ncriticising\ncriticism\ncriticisms\ncriticizable\ncriticize\ncriticized\ncriticizer\ncriticizers\ncriticizes\ncriticizing\ncritics\ncritique\ncritiqued\ncritiques\ncritiquing\ncritter\ncritters\ncrittur\ncritturs\ncroak\ncroaked\ncroaker\ncroakers\ncroakier\ncroakiest\ncroakily\ncroaking\ncroaks\ncroaky\ncroc\ncrocein\ncroceine\ncroceines\ncroceins\ncrochet\ncrocheted\ncrocheter\ncrocheters\ncrocheting\ncrochets\ncroci\ncrocidolite\ncrocidolites\ncrocine\ncrock\ncrocked\ncrockeries\ncrockery\ncrocket\ncrocketed\ncrockets\ncrocking\ncrocks\ncrocodile\ncrocodiles\ncrocodilian\ncrocodilians\ncrocoite\ncrocoites\ncrocs\ncrocus\ncrocuses\ncroft\ncrofter\ncrofters\ncrofts\ncroissant\ncroissants\ncrojik\ncrojiks\ncromlech\ncromlechs\ncrone\ncrones\ncronies\ncrony\ncronyism\ncronyisms\ncrook\ncrookback\ncrookbacked\ncrookbacks\ncrooked\ncrookeder\ncrookedest\ncrookedly\ncrookedness\ncrookednesses\ncrookeries\ncrookery\ncrooking\ncrookneck\ncrooknecks\ncrooks\ncroon\ncrooned\ncrooner\ncrooners\ncrooning\ncroons\ncrop\ncropland\ncroplands\ncropless\ncropped\ncropper\ncroppers\ncroppie\ncroppies\ncropping\ncrops\ncroquet\ncroqueted\ncroqueting\ncroquets\ncroquette\ncroquettes\ncroquignole\ncroquignoles\ncroquis\ncrore\ncrores\ncrosier\ncrosiers\ncross\ncrossabilities\ncrossability\ncrossable\ncrossarm\ncrossarms\ncrossbanded\ncrossbanding\ncrossbandings\ncrossbar\ncrossbarred\ncrossbarring\ncrossbars\ncrossbeam\ncrossbeams\ncrossbearer\ncrossbearers\ncrossbill\ncrossbills\ncrossbones\ncrossbow\ncrossbowman\ncrossbowmen\ncrossbows\ncrossbred\ncrossbreds\ncrossbreed\ncrossbreeding\ncrossbreeds\ncrosscheck\ncrosschecked\ncrosschecking\ncrosschecks\ncrosscourt\ncrosscurrent\ncrosscurrents\ncrosscut\ncrosscuts\ncrosscutting\ncrosscuttings\ncrosse\ncrossed\ncrosser\ncrossers\ncrosses\ncrossest\ncrossfire\ncrossfires\ncrosshair\ncrosshairs\ncrosshatch\ncrosshatched\ncrosshatches\ncrosshatching\ncrosshead\ncrossheads\ncrossing\ncrossings\ncrosslet\ncrosslets\ncrosslinguistic\ncrosslinguistically\ncrossly\ncrossness\ncrossnesses\ncrossopterygian\ncrossopterygians\ncrossover\ncrossovers\ncrosspatch\ncrosspatches\ncrosspiece\ncrosspieces\ncrossroad\ncrossroads\ncrossruff\ncrossruffed\ncrossruffing\ncrossruffs\ncrosstalk\ncrosstalks\ncrosstie\ncrossties\ncrosstown\ncrosstrees\ncrosswalk\ncrosswalks\ncrossway\ncrossways\ncrosswind\ncrosswinds\ncrosswise\ncrossword\ncrosswords\ncrotch\ncrotched\ncrotches\ncrotchet\ncrotchetiness\ncrotchetinesses\ncrotchets\ncrotchety\ncroton\ncrotons\ncrouch\ncrouched\ncrouches\ncrouching\ncroup\ncroupe\ncroupes\ncroupier\ncroupiers\ncroupiest\ncroupily\ncroupous\ncroups\ncroupy\ncrouse\ncrousely\ncroustade\ncroustades\ncrouton\ncroutons\ncrow\ncrowbar\ncrowbarred\ncrowbarring\ncrowbars\ncrowberries\ncrowberry\ncrowd\ncrowded\ncrowdedness\ncrowdednesses\ncrowder\ncrowders\ncrowdie\ncrowdies\ncrowding\ncrowds\ncrowdy\ncrowed\ncrower\ncrowers\ncrowfeet\ncrowfoot\ncrowfoots\ncrowing\ncrowkeeper\ncrowkeepers\ncrown\ncrowned\ncrowner\ncrowners\ncrownet\ncrownets\ncrowning\ncrownless\ncrowns\ncrows\ncrowstep\ncrowstepped\ncrowsteps\ncroze\ncrozer\ncrozers\ncrozes\ncrozier\ncroziers\ncruces\ncrucial\ncrucially\ncrucian\ncrucians\ncruciate\ncrucible\ncrucibles\ncrucifer\ncruciferous\ncrucifers\ncrucified\ncrucifies\ncrucifix\ncrucifixes\ncrucifixion\ncrucifixions\ncruciform\ncruciforms\ncrucify\ncrucifying\ncruciverbalist\ncruciverbalists\ncruck\ncrucks\ncrud\ncrudded\ncruddier\ncruddiest\ncrudding\ncruddy\ncrude\ncrudely\ncrudeness\ncrudenesses\ncruder\ncrudes\ncrudest\ncrudites\ncrudities\ncrudity\ncruds\ncruel\ncrueler\ncruelest\ncrueller\ncruellest\ncruelly\ncruelness\ncruelnesses\ncruelties\ncruelty\ncruet\ncruets\ncruise\ncruised\ncruiser\ncruisers\ncruiserweight\ncruiserweights\ncruises\ncruising\ncruisings\ncruller\ncrullers\ncrumb\ncrumbed\ncrumber\ncrumbers\ncrumbier\ncrumbiest\ncrumbing\ncrumble\ncrumbled\ncrumbles\ncrumblier\ncrumbliest\ncrumbliness\ncrumblinesses\ncrumbling\ncrumblings\ncrumbly\ncrumbs\ncrumbum\ncrumbums\ncrumby\ncrumhorn\ncrumhorns\ncrummie\ncrummier\ncrummies\ncrummiest\ncrumminess\ncrumminesses\ncrummy\ncrump\ncrumped\ncrumpet\ncrumpets\ncrumping\ncrumple\ncrumpled\ncrumples\ncrumplier\ncrumpliest\ncrumpling\ncrumply\ncrumps\ncrunch\ncrunchable\ncrunched\ncruncher\ncrunchers\ncrunches\ncrunchier\ncrunchiest\ncrunchily\ncrunchiness\ncrunchinesses\ncrunching\ncrunchy\ncrunodal\ncrunode\ncrunodes\ncruor\ncruors\ncrupper\ncruppers\ncrura\ncrural\ncrus\ncrusade\ncrusaded\ncrusader\ncrusaders\ncrusades\ncrusading\ncrusado\ncrusadoes\ncrusados\ncruse\ncruses\ncruset\ncrusets\ncrush\ncrushable\ncrushed\ncrusher\ncrushers\ncrushes\ncrushing\ncrushingly\ncrushproof\ncrusily\ncrust\ncrustacea\ncrustacean\ncrustaceans\ncrustaceous\ncrustal\ncrusted\ncrustier\ncrustiest\ncrustily\ncrustiness\ncrustinesses\ncrusting\ncrustless\ncrustose\ncrusts\ncrusty\ncrutch\ncrutched\ncrutches\ncrutching\ncrux\ncruxes\ncruzado\ncruzadoes\ncruzados\ncruzeiro\ncruzeiros\ncrwth\ncrwths\ncry\ncrybabies\ncrybaby\ncrying\ncryingly\ncryobiological\ncryobiologies\ncryobiologist\ncryobiologists\ncryobiology\ncryogen\ncryogenic\ncryogenically\ncryogenics\ncryogenies\ncryogens\ncryogeny\ncryolite\ncryolites\ncryonic\ncryonics\ncryophilic\ncryopreservation\ncryopreservations\ncryopreserve\ncryopreserved\ncryopreserves\ncryopreserving\ncryoprobe\ncryoprobes\ncryoprotectant\ncryoprotectants\ncryoprotective\ncryoscope\ncryoscopes\ncryoscopic\ncryoscopies\ncryoscopy\ncryostat\ncryostatic\ncryostats\ncryosurgeon\ncryosurgeons\ncryosurgeries\ncryosurgery\ncryosurgical\ncryotherapies\ncryotherapy\ncryotron\ncryotrons\ncrypt\ncryptal\ncryptanalyses\ncryptanalysis\ncryptanalyst\ncryptanalysts\ncryptanalytic\ncryptanalytical\ncryptarithm\ncryptarithms\ncryptic\ncryptically\ncrypto\ncryptococcal\ncryptococci\ncryptococcoses\ncryptococcosis\ncryptococcus\ncryptocrystalline\ncryptogam\ncryptogamic\ncryptogamous\ncryptogams\ncryptogenic\ncryptogram\ncryptograms\ncryptograph\ncryptographer\ncryptographers\ncryptographic\ncryptographically\ncryptographies\ncryptographs\ncryptography\ncryptologic\ncryptological\ncryptologies\ncryptologist\ncryptologists\ncryptology\ncryptomeria\ncryptomerias\ncryptonym\ncryptonyms\ncryptorchid\ncryptorchidism\ncryptorchidisms\ncryptorchids\ncryptorchism\ncryptorchisms\ncryptos\ncryptozoologies\ncryptozoologist\ncryptozoologists\ncryptozoology\ncrypts\ncrystal\ncrystalize\ncrystalized\ncrystalizes\ncrystalizing\ncrystalline\ncrystallinities\ncrystallinity\ncrystallise\ncrystallised\ncrystallises\ncrystallising\ncrystallite\ncrystallites\ncrystallizable\ncrystallization\ncrystallizations\ncrystallize\ncrystallized\ncrystallizer\ncrystallizers\ncrystallizes\ncrystallizing\ncrystallographer\ncrystallographers\ncrystallographic\ncrystallographically\ncrystallographies\ncrystallography\ncrystalloid\ncrystalloidal\ncrystalloids\ncrystals\nctenidia\nctenidium\nctenoid\nctenophoran\nctenophorans\nctenophore\nctenophores\ncuadrilla\ncuadrillas\ncub\ncubage\ncubages\ncubature\ncubatures\ncubbies\ncubbish\ncubby\ncubbyhole\ncubbyholes\ncube\ncubeb\ncubebs\ncubed\ncuber\ncubers\ncubes\ncubic\ncubical\ncubically\ncubicities\ncubicity\ncubicle\ncubicles\ncubicly\ncubics\ncubicula\ncubiculum\ncubiform\ncubing\ncubism\ncubisms\ncubist\ncubistic\ncubists\ncubit\ncubital\ncubits\ncuboid\ncuboidal\ncuboids\ncubs\ncuckold\ncuckolded\ncuckolding\ncuckoldries\ncuckoldry\ncuckolds\ncuckoo\ncuckooed\ncuckooflower\ncuckooflowers\ncuckooing\ncuckoopint\ncuckoopints\ncuckoos\ncucullate\ncucumber\ncucumbers\ncucurbit\ncucurbits\ncud\ncudbear\ncudbears\ncuddie\ncuddies\ncuddle\ncuddled\ncuddler\ncuddlers\ncuddles\ncuddlesome\ncuddlier\ncuddliest\ncuddling\ncuddly\ncuddy\ncudgel\ncudgeled\ncudgeler\ncudgelers\ncudgeling\ncudgelled\ncudgelling\ncudgels\ncuds\ncudweed\ncudweeds\ncue\ncued\ncueing\ncues\ncuesta\ncuestas\ncuff\ncuffed\ncuffing\ncuffless\ncufflink\ncufflinks\ncuffs\ncuif\ncuifs\ncuing\ncuirass\ncuirassed\ncuirasses\ncuirassier\ncuirassiers\ncuirassing\ncuish\ncuishes\ncuisine\ncuisines\ncuisse\ncuisses\ncuittle\ncuittled\ncuittles\ncuittling\ncuke\ncukes\nculch\nculches\nculet\nculets\nculex\nculexes\nculices\nculicid\nculicids\nculicine\nculicines\nculinarian\nculinarians\nculinarily\nculinary\ncull\ncullay\ncullays\nculled\ncullender\ncullenders\nculler\ncullers\ncullet\ncullets\ncullied\ncullies\nculling\ncullion\ncullions\ncullis\ncullises\nculls\ncully\ncullying\nculm\nculmed\nculminant\nculminate\nculminated\nculminates\nculminating\nculmination\nculminations\nculming\nculms\nculotte\nculottes\nculpa\nculpabilities\nculpability\nculpable\nculpableness\nculpablenesses\nculpably\nculpae\nculprit\nculprits\ncult\ncultch\ncultches\nculti\ncultic\ncultigen\ncultigens\ncultish\ncultishly\ncultishness\ncultishnesses\ncultism\ncultisms\ncultist\ncultists\ncultivabilities\ncultivability\ncultivable\ncultivar\ncultivars\ncultivatable\ncultivate\ncultivated\ncultivates\ncultivating\ncultivation\ncultivations\ncultivator\ncultivators\ncultlike\ncultrate\ncults\ncultural\nculturally\nculturati\nculture\ncultured\ncultures\nculturing\ncultus\ncultuses\nculver\nculverin\nculverins\nculvers\nculvert\nculverts\ncum\ncumarin\ncumarins\ncumber\ncumberbund\ncumberbunds\ncumbered\ncumberer\ncumberers\ncumbering\ncumbers\ncumbersome\ncumbersomely\ncumbersomeness\ncumbersomenesses\ncumbrous\ncumbrously\ncumbrousness\ncumbrousnesses\ncumin\ncumins\ncummer\ncummerbund\ncummerbunds\ncummers\ncummin\ncummins\ncumquat\ncumquats\ncumshaw\ncumshaws\ncumulate\ncumulated\ncumulates\ncumulating\ncumulation\ncumulations\ncumulative\ncumulatively\ncumulativeness\ncumulativenesses\ncumuli\ncumuliform\ncumulonimbi\ncumulonimbus\ncumulonimbuses\ncumulous\ncumulus\ncunctation\ncunctations\ncunctative\ncundum\ncundums\ncuneal\ncuneate\ncuneated\ncuneatic\ncuneiform\ncuneiforms\ncuniform\ncuniforms\ncunner\ncunners\ncunnilinctus\ncunnilinctuses\ncunnilingus\ncunnilinguses\ncunning\ncunninger\ncunningest\ncunningly\ncunningness\ncunningnesses\ncunnings\ncunt\ncunts\ncup\ncupbearer\ncupbearers\ncupboard\ncupboards\ncupcake\ncupcakes\ncupel\ncupeled\ncupeler\ncupelers\ncupeling\ncupellation\ncupellations\ncupelled\ncupeller\ncupellers\ncupelling\ncupels\ncupful\ncupfuls\ncupid\ncupidities\ncupidity\ncupids\ncuplike\ncupola\ncupolaed\ncupolaing\ncupolas\ncuppa\ncuppas\ncupped\ncupper\ncuppers\ncuppier\ncuppiest\ncupping\ncuppings\ncuppy\ncupreous\ncupric\ncupriferous\ncuprite\ncuprites\ncupronickel\ncupronickels\ncuprous\ncuprum\ncuprums\ncups\ncupsful\ncupula\ncupulae\ncupular\ncupulate\ncupule\ncupules\ncur\ncurabilities\ncurability\ncurable\ncurableness\ncurablenesses\ncurably\ncuracao\ncuracaos\ncuracies\ncuracoa\ncuracoas\ncuracy\ncuragh\ncuraghs\ncurara\ncuraras\ncurare\ncurares\ncurari\ncurarine\ncurarines\ncuraris\ncurarization\ncurarizations\ncurarize\ncurarized\ncurarizes\ncurarizing\ncurassow\ncurassows\ncurate\ncurated\ncurates\ncurating\ncurative\ncuratively\ncuratives\ncurator\ncuratorial\ncurators\ncuratorship\ncuratorships\ncurb\ncurbable\ncurbed\ncurber\ncurbers\ncurbing\ncurbings\ncurbs\ncurbside\ncurbsides\ncurbstone\ncurbstones\ncurch\ncurches\ncurculio\ncurculios\ncurcuma\ncurcumas\ncurd\ncurded\ncurdier\ncurdiest\ncurding\ncurdle\ncurdled\ncurdler\ncurdlers\ncurdles\ncurdling\ncurds\ncurdy\ncure\ncured\ncureless\ncurer\ncurers\ncures\ncuret\ncurets\ncurettage\ncurettages\ncurette\ncuretted\ncurettement\ncurettements\ncurettes\ncuretting\ncurf\ncurfew\ncurfews\ncurfs\ncuria\ncuriae\ncurial\ncurie\ncuries\ncuring\ncurio\ncurios\ncuriosa\ncuriosities\ncuriosity\ncurious\ncuriouser\ncuriousest\ncuriously\ncuriousness\ncuriousnesses\ncurite\ncurites\ncurium\ncuriums\ncurl\ncurled\ncurler\ncurlers\ncurlew\ncurlews\ncurlicue\ncurlicued\ncurlicues\ncurlicuing\ncurlier\ncurliest\ncurlily\ncurliness\ncurlinesses\ncurling\ncurlings\ncurlpaper\ncurlpapers\ncurls\ncurly\ncurlycue\ncurlycues\ncurmudgeon\ncurmudgeonliness\ncurmudgeonlinesses\ncurmudgeonly\ncurmudgeons\ncurn\ncurns\ncurr\ncurrach\ncurrachs\ncurragh\ncurraghs\ncurran\ncurrans\ncurrant\ncurrants\ncurred\ncurrencies\ncurrency\ncurrent\ncurrently\ncurrentness\ncurrentnesses\ncurrents\ncurricle\ncurricles\ncurricula\ncurricular\ncurriculum\ncurriculums\ncurrie\ncurried\ncurrier\ncurrieries\ncurriers\ncurriery\ncurries\ncurring\ncurrish\ncurrishly\ncurrs\ncurry\ncurrycomb\ncurrycombed\ncurrycombing\ncurrycombs\ncurrying\ncurs\ncurse\ncursed\ncurseder\ncursedest\ncursedly\ncursedness\ncursednesses\ncurser\ncursers\ncurses\ncursing\ncursive\ncursively\ncursiveness\ncursivenesses\ncursives\ncursor\ncursorial\ncursorily\ncursoriness\ncursorinesses\ncursors\ncursory\ncurst\ncurt\ncurtail\ncurtailed\ncurtailer\ncurtailers\ncurtailing\ncurtailment\ncurtailments\ncurtails\ncurtain\ncurtained\ncurtaining\ncurtainless\ncurtains\ncurtal\ncurtalax\ncurtalaxes\ncurtals\ncurtate\ncurter\ncurtesies\ncurtest\ncurtesy\ncurtilage\ncurtilages\ncurtly\ncurtness\ncurtnesses\ncurtsey\ncurtseyed\ncurtseying\ncurtseys\ncurtsied\ncurtsies\ncurtsy\ncurtsying\ncurule\ncurvaceous\ncurvacious\ncurvature\ncurvatures\ncurve\ncurveball\ncurveballed\ncurveballing\ncurveballs\ncurved\ncurvedly\ncurves\ncurvet\ncurveted\ncurveting\ncurvets\ncurvetted\ncurvetting\ncurvey\ncurvier\ncurviest\ncurvilinear\ncurvilinearities\ncurvilinearity\ncurving\ncurvy\ncuscus\ncuscuses\ncusec\ncusecs\ncushat\ncushats\ncushaw\ncushaws\ncushier\ncushiest\ncushily\ncushion\ncushioned\ncushioning\ncushionless\ncushions\ncushiony\ncushy\ncusk\ncusks\ncusp\ncuspate\ncuspated\ncusped\ncuspid\ncuspidal\ncuspidate\ncuspidation\ncuspidations\ncuspides\ncuspidor\ncuspidors\ncuspids\ncuspis\ncusps\ncuss\ncussed\ncussedly\ncussedness\ncussednesses\ncusser\ncussers\ncusses\ncussing\ncusso\ncussos\ncussword\ncusswords\ncustard\ncustards\ncustardy\ncustodes\ncustodial\ncustodian\ncustodians\ncustodianship\ncustodianships\ncustodies\ncustody\ncustom\ncustomarily\ncustomariness\ncustomarinesses\ncustomary\ncustomer\ncustomers\ncustomhouse\ncustomhouses\ncustomise\ncustomised\ncustomises\ncustomising\ncustomization\ncustomizations\ncustomize\ncustomized\ncustomizer\ncustomizers\ncustomizes\ncustomizing\ncustoms\ncustomshouse\ncustomshouses\ncustos\ncustumal\ncustumals\ncut\ncutabilities\ncutability\ncutaneous\ncutaneously\ncutaway\ncutaways\ncutback\ncutbacks\ncutbank\ncutbanks\ncutch\ncutcheries\ncutchery\ncutches\ncutdown\ncutdowns\ncute\ncutely\ncuteness\ncutenesses\ncuter\ncutes\ncutesie\ncutesier\ncutesiest\ncutest\ncutesy\ncutey\ncuteys\ncutgrass\ncutgrasses\ncuticle\ncuticles\ncuticula\ncuticulae\ncuticular\ncutie\ncuties\ncutin\ncutinise\ncutinised\ncutinises\ncutinising\ncutinize\ncutinized\ncutinizes\ncutinizing\ncutins\ncutis\ncutises\ncutlas\ncutlases\ncutlass\ncutlasses\ncutler\ncutleries\ncutlers\ncutlery\ncutlet\ncutlets\ncutline\ncutlines\ncutoff\ncutoffs\ncutout\ncutouts\ncutover\ncutovers\ncutpurse\ncutpurses\ncuts\ncuttable\ncuttage\ncuttages\ncutter\ncutters\ncutthroat\ncutthroats\ncutties\ncutting\ncuttingly\ncuttings\ncuttle\ncuttlebone\ncuttlebones\ncuttled\ncuttlefish\ncuttlefishes\ncuttles\ncuttling\ncutty\ncutup\ncutups\ncutwater\ncutwaters\ncutwork\ncutworks\ncutworm\ncutworms\ncuvette\ncuvettes\ncwm\ncwms\ncyan\ncyanamid\ncyanamide\ncyanamides\ncyanamids\ncyanate\ncyanates\ncyanic\ncyanid\ncyanide\ncyanided\ncyanides\ncyaniding\ncyanids\ncyanin\ncyanine\ncyanines\ncyanins\ncyanite\ncyanites\ncyanitic\ncyano\ncyanoacrylate\ncyanoacrylates\ncyanobacteria\ncyanobacterium\ncyanocobalamin\ncyanocobalamine\ncyanocobalamines\ncyanocobalamins\ncyanoethylate\ncyanoethylated\ncyanoethylates\ncyanoethylating\ncyanoethylation\ncyanoethylations\ncyanogen\ncyanogeneses\ncyanogenesis\ncyanogenetic\ncyanogenic\ncyanogens\ncyanohydrin\ncyanohydrins\ncyanosed\ncyanoses\ncyanosis\ncyanotic\ncyans\ncybernated\ncybernation\ncybernations\ncybernetic\ncybernetical\ncybernetically\ncybernetician\ncyberneticians\ncyberneticist\ncyberneticists\ncybernetics\ncyberpunk\ncyberpunks\ncyberspace\ncyberspaces\ncyborg\ncyborgs\ncycad\ncycadeoid\ncycadeoids\ncycadophyte\ncycadophytes\ncycads\ncycas\ncycases\ncycasin\ncycasins\ncyclamate\ncyclamates\ncyclamen\ncyclamens\ncyclase\ncyclases\ncyclazocine\ncyclazocines\ncycle\ncyclecar\ncyclecars\ncycled\ncycler\ncycleries\ncyclers\ncyclery\ncycles\ncyclic\ncyclical\ncyclicalities\ncyclicality\ncyclically\ncyclicals\ncyclicities\ncyclicity\ncyclicly\ncycling\ncyclings\ncyclist\ncyclists\ncyclitol\ncyclitols\ncyclization\ncyclizations\ncyclize\ncyclized\ncyclizes\ncyclizing\ncyclo\ncycloaddition\ncycloadditions\ncycloaliphatic\ncyclodextrin\ncyclodextrins\ncyclodiene\ncyclodienes\ncyclogeneses\ncyclogenesis\ncyclohexane\ncyclohexanes\ncyclohexanone\ncyclohexanones\ncycloheximide\ncycloheximides\ncyclohexylamine\ncyclohexylamines\ncycloid\ncycloidal\ncycloids\ncyclometer\ncyclometers\ncyclonal\ncyclone\ncyclones\ncyclonic\ncyclonically\ncycloolefin\ncycloolefinic\ncycloolefins\ncyclopaedia\ncyclopaedias\ncycloparaffin\ncycloparaffins\ncyclopean\ncyclopedia\ncyclopedias\ncyclopedic\ncyclopes\ncyclophosphamide\ncyclophosphamides\ncyclopropane\ncyclopropanes\ncyclops\ncyclorama\ncycloramas\ncycloramic\ncyclos\ncycloserine\ncycloserines\ncycloses\ncyclosis\ncyclosporine\ncyclosporines\ncyclostome\ncyclostomes\ncyclostyle\ncyclostyled\ncyclostyles\ncyclostyling\ncyclothymia\ncyclothymias\ncyclothymic\ncyclotomic\ncyclotron\ncyclotrons\ncyder\ncyders\ncyeses\ncyesis\ncygnet\ncygnets\ncylices\ncylinder\ncylindered\ncylindering\ncylinders\ncylindric\ncylindrical\ncylindrically\ncylix\ncyma\ncymae\ncymar\ncymars\ncymas\ncymatia\ncymatium\ncymbal\ncymbaler\ncymbalers\ncymbalist\ncymbalists\ncymbalom\ncymbaloms\ncymbals\ncymbidia\ncymbidium\ncymbidiums\ncymbling\ncymblings\ncyme\ncymene\ncymenes\ncymes\ncymlin\ncymling\ncymlings\ncymlins\ncymogene\ncymogenes\ncymoid\ncymol\ncymols\ncymophane\ncymophanes\ncymose\ncymosely\ncymous\ncynic\ncynical\ncynically\ncynicism\ncynicisms\ncynics\ncynosure\ncynosures\ncypher\ncyphered\ncyphering\ncyphers\ncypres\ncypreses\ncypress\ncypresses\ncyprian\ncyprians\ncyprinid\ncyprinids\ncypripedia\ncypripedium\ncypripediums\ncyproheptadine\ncyproheptadines\ncyproterone\ncyproterones\ncyprus\ncypruses\ncypsela\ncypselae\ncyst\ncysteamine\ncysteamines\ncystein\ncysteine\ncysteines\ncysteins\ncystic\ncysticerci\ncysticercoid\ncysticercoids\ncysticercoses\ncysticercosis\ncysticercus\ncystine\ncystines\ncystinuria\ncystinurias\ncystitides\ncystitis\ncystocarp\ncystocarps\ncystoid\ncystoids\ncystolith\ncystoliths\ncystoscope\ncystoscopes\ncystoscopic\ncystoscopies\ncystoscopy\ncysts\ncytaster\ncytasters\ncytidine\ncytidines\ncytochalasin\ncytochalasins\ncytochemical\ncytochemistries\ncytochemistry\ncytochrome\ncytochromes\ncytodifferentiation\ncytodifferentiations\ncytogenetic\ncytogenetical\ncytogenetically\ncytogeneticist\ncytogeneticists\ncytogenetics\ncytogenies\ncytogeny\ncytokine\ncytokines\ncytokineses\ncytokinesis\ncytokinetic\ncytokinin\ncytokinins\ncytologic\ncytological\ncytologically\ncytologies\ncytologist\ncytologists\ncytology\ncytolyses\ncytolysin\ncytolysins\ncytolysis\ncytolytic\ncytomegalic\ncytomegalovirus\ncytomegaloviruses\ncytomembrane\ncytomembranes\ncyton\ncytons\ncytopathic\ncytopathogenic\ncytopathogenicities\ncytopathogenicity\ncytophilic\ncytophotometric\ncytophotometries\ncytophotometry\ncytoplasm\ncytoplasmic\ncytoplasmically\ncytoplasms\ncytosine\ncytosines\ncytoskeletal\ncytoskeleton\ncytoskeletons\ncytosol\ncytosolic\ncytosols\ncytostatic\ncytostatically\ncytostatics\ncytotaxonomic\ncytotaxonomically\ncytotaxonomies\ncytotaxonomy\ncytotechnologies\ncytotechnologist\ncytotechnologists\ncytotechnology\ncytotoxic\ncytotoxicities\ncytotoxicity\ncytotoxin\ncytotoxins\nczar\nczardas\nczardases\nczardom\nczardoms\nczarevitch\nczarevitches\nczarevna\nczarevnas\nczarina\nczarinas\nczarism\nczarisms\nczarist\nczarists\nczaritza\nczaritzas\nczars\ndab\ndabbed\ndabber\ndabbers\ndabbing\ndabble\ndabbled\ndabbler\ndabblers\ndabbles\ndabbling\ndabblings\ndabchick\ndabchicks\ndabs\ndabster\ndabsters\ndace\ndaces\ndacha\ndachas\ndachshund\ndachshunds\ndacker\ndackered\ndackering\ndackers\ndacoit\ndacoities\ndacoits\ndacoity\ndactyl\ndactyli\ndactylic\ndactylics\ndactylologies\ndactylology\ndactyls\ndactylus\ndad\ndada\ndadaism\ndadaisms\ndadaist\ndadaistic\ndadaists\ndadas\ndaddies\ndaddle\ndaddled\ndaddles\ndaddling\ndaddy\ndado\ndadoed\ndadoes\ndadoing\ndados\ndads\ndaedal\ndaemon\ndaemones\ndaemonic\ndaemons\ndaff\ndaffed\ndaffier\ndaffiest\ndaffily\ndaffing\ndaffodil\ndaffodils\ndaffs\ndaffy\ndaft\ndafter\ndaftest\ndaftly\ndaftness\ndaftnesses\ndag\ndagga\ndaggas\ndagger\ndaggered\ndaggering\ndaggerlike\ndaggers\ndaggle\ndaggled\ndaggles\ndaggling\ndaglock\ndaglocks\ndago\ndagoba\ndagobas\ndagoes\ndagos\ndags\ndaguerreotype\ndaguerreotyped\ndaguerreotypes\ndaguerreotypies\ndaguerreotyping\ndaguerreotypist\ndaguerreotypists\ndaguerreotypy\ndagwood\ndagwoods\ndah\ndahabeah\ndahabeahs\ndahabiah\ndahabiahs\ndahabieh\ndahabiehs\ndahabiya\ndahabiyas\ndahl\ndahlia\ndahlias\ndahls\ndahoon\ndahoons\ndahs\ndaiker\ndaikered\ndaikering\ndaikers\ndaikon\ndaikons\ndailies\ndailiness\ndailinesses\ndaily\ndaimen\ndaimio\ndaimios\ndaimon\ndaimones\ndaimonic\ndaimons\ndaimyo\ndaimyos\ndaintier\ndainties\ndaintiest\ndaintily\ndaintiness\ndaintinesses\ndainty\ndaiquiri\ndaiquiris\ndairies\ndairy\ndairying\ndairyings\ndairymaid\ndairymaids\ndairyman\ndairymen\ndais\ndaises\ndaishiki\ndaishikis\ndaisied\ndaisies\ndaisy\ndak\ndakerhen\ndakerhens\ndakoit\ndakoities\ndakoits\ndakoity\ndaks\ndal\ndalapon\ndalapons\ndalasi\ndalasis\ndale\ndaledh\ndaledhs\ndales\ndalesman\ndalesmen\ndaleth\ndaleths\ndalles\ndalliance\ndalliances\ndallied\ndallier\ndalliers\ndallies\ndally\ndallying\ndalmatian\ndalmatians\ndalmatic\ndalmatics\ndals\ndalton\ndaltonic\ndaltons\ndam\ndamage\ndamageabilities\ndamageability\ndamaged\ndamager\ndamagers\ndamages\ndamaging\ndamagingly\ndaman\ndamans\ndamar\ndamars\ndamascene\ndamascened\ndamascenes\ndamascening\ndamask\ndamasked\ndamasking\ndamasks\ndame\ndames\ndamewort\ndameworts\ndammar\ndammars\ndammed\ndammer\ndammers\ndamming\ndamn\ndamnable\ndamnableness\ndamnablenesses\ndamnably\ndamnation\ndamnations\ndamnatory\ndamndest\ndamndests\ndamned\ndamneder\ndamnedest\ndamnedests\ndamner\ndamners\ndamnified\ndamnifies\ndamnify\ndamnifying\ndamning\ndamningly\ndamns\ndamosel\ndamosels\ndamozel\ndamozels\ndamp\ndamped\ndampen\ndampened\ndampener\ndampeners\ndampening\ndampens\ndamper\ndampers\ndampest\ndamping\ndampings\ndampish\ndamply\ndampness\ndampnesses\ndamps\ndams\ndamsel\ndamselfish\ndamselfishes\ndamselflies\ndamselfly\ndamsels\ndamson\ndamsons\ndance\ndanceable\ndanced\ndancer\ndancers\ndances\ndancing\ndandelion\ndandelions\ndander\ndandered\ndandering\ndanders\ndandiacal\ndandier\ndandies\ndandiest\ndandification\ndandifications\ndandified\ndandifies\ndandify\ndandifying\ndandily\ndandle\ndandled\ndandler\ndandlers\ndandles\ndandling\ndandriff\ndandriffs\ndandruff\ndandruffs\ndandruffy\ndandy\ndandyish\ndandyishly\ndandyism\ndandyisms\ndanegeld\ndanegelds\ndaneweed\ndaneweeds\ndanewort\ndaneworts\ndang\ndanged\ndanger\ndangered\ndangering\ndangerous\ndangerously\ndangerousness\ndangerousnesses\ndangers\ndanging\ndangle\ndangled\ndangler\ndanglers\ndangles\ndangling\ndangs\ndanio\ndanios\ndanish\ndank\ndanker\ndankest\ndankly\ndankness\ndanknesses\ndanseur\ndanseurs\ndanseuse\ndanseuses\ndap\ndaphne\ndaphnes\ndaphnia\ndaphnias\ndapped\ndapper\ndapperer\ndapperest\ndapperly\ndapperness\ndappernesses\ndapping\ndapple\ndappled\ndapples\ndappling\ndaps\ndapsone\ndapsones\ndarb\ndarbies\ndarbs\ndare\ndared\ndaredevil\ndaredevilries\ndaredevilry\ndaredevils\ndaredeviltries\ndaredeviltry\ndareful\ndarer\ndarers\ndares\ndaresay\ndaric\ndarics\ndaring\ndaringly\ndaringness\ndaringnesses\ndarings\ndariole\ndarioles\ndark\ndarked\ndarken\ndarkened\ndarkener\ndarkeners\ndarkening\ndarkens\ndarker\ndarkest\ndarkey\ndarkeys\ndarkie\ndarkies\ndarking\ndarkish\ndarkle\ndarkled\ndarkles\ndarklier\ndarkliest\ndarkling\ndarkly\ndarkness\ndarknesses\ndarkroom\ndarkrooms\ndarks\ndarksome\ndarky\ndarling\ndarlingly\ndarlingness\ndarlingnesses\ndarlings\ndarn\ndarndest\ndarndests\ndarned\ndarneder\ndarnedest\ndarnel\ndarnels\ndarner\ndarners\ndarning\ndarnings\ndarns\ndarshan\ndarshans\ndart\ndartboard\ndartboards\ndarted\ndarter\ndarters\ndarting\ndartle\ndartled\ndartles\ndartling\ndarts\ndash\ndashboard\ndashboards\ndashed\ndasheen\ndasheens\ndasher\ndashers\ndashes\ndashi\ndashier\ndashiest\ndashiki\ndashikis\ndashing\ndashingly\ndashis\ndashpot\ndashpots\ndashy\ndassie\ndassies\ndastard\ndastardliness\ndastardlinesses\ndastardly\ndastards\ndasyure\ndasyures\ndata\ndatabank\ndatabanks\ndatabase\ndatabases\ndatable\ndataries\ndatary\ndatcha\ndatchas\ndate\ndateable\ndatebook\ndatebooks\ndated\ndatedly\ndatedness\ndatednesses\ndateless\ndateline\ndatelined\ndatelines\ndatelining\ndater\ndaters\ndates\ndating\ndatival\ndative\ndatively\ndatives\ndato\ndatos\ndatto\ndattos\ndatum\ndatums\ndatura\ndaturas\ndaturic\ndaub\ndaube\ndaubed\ndauber\ndauberies\ndaubers\ndaubery\ndaubes\ndaubier\ndaubiest\ndaubing\ndaubries\ndaubry\ndaubs\ndauby\ndaughter\ndaughterless\ndaughters\ndaunder\ndaundered\ndaundering\ndaunders\ndaunomycin\ndaunomycins\ndaunorubicin\ndaunorubicins\ndaunt\ndaunted\ndaunter\ndaunters\ndaunting\ndauntingly\ndauntless\ndauntlessly\ndauntlessness\ndauntlessnesses\ndaunts\ndauphin\ndauphine\ndauphines\ndauphins\ndaut\ndauted\ndautie\ndauties\ndauting\ndauts\ndaven\ndavened\ndavening\ndavenport\ndavenports\ndavens\ndavies\ndavit\ndavits\ndavy\ndaw\ndawdle\ndawdled\ndawdler\ndawdlers\ndawdles\ndawdling\ndawed\ndawen\ndawing\ndawk\ndawks\ndawn\ndawned\ndawning\ndawnlike\ndawns\ndaws\ndawsonite\ndawsonites\ndawt\ndawted\ndawtie\ndawties\ndawting\ndawts\nday\ndaybed\ndaybeds\ndaybook\ndaybooks\ndaybreak\ndaybreaks\ndaydream\ndaydreamed\ndaydreamer\ndaydreamers\ndaydreaming\ndaydreamlike\ndaydreams\ndaydreamt\ndayflies\ndayflower\ndayflowers\ndayfly\ndayglow\ndayglows\ndaylight\ndaylighted\ndaylighting\ndaylightings\ndaylights\ndaylilies\ndaylily\ndaylit\ndaylong\ndaymare\ndaymares\ndayroom\ndayrooms\ndays\ndayshift\ndayshifts\ndayside\ndaysides\ndaysman\ndaysmen\ndaystar\ndaystars\ndaytime\ndaytimes\ndaytrader\ndaytraders\ndaywork\ndayworks\ndaze\ndazed\ndazedly\ndazedness\ndazednesses\ndazes\ndazing\ndazzle\ndazzled\ndazzler\ndazzlers\ndazzles\ndazzling\ndazzlingly\nde\ndeacidification\ndeacidifications\ndeacidified\ndeacidifies\ndeacidify\ndeacidifying\ndeacon\ndeaconed\ndeaconess\ndeaconesses\ndeaconing\ndeaconries\ndeaconry\ndeacons\ndeactivate\ndeactivated\ndeactivates\ndeactivating\ndeactivation\ndeactivations\ndeactivator\ndeactivators\ndead\ndeadbeat\ndeadbeats\ndeadbolt\ndeadbolts\ndeaden\ndeadened\ndeadener\ndeadeners\ndeadening\ndeadeningly\ndeadenings\ndeadens\ndeader\ndeadest\ndeadeye\ndeadeyes\ndeadfall\ndeadfalls\ndeadhead\ndeadheaded\ndeadheading\ndeadheads\ndeadlier\ndeadliest\ndeadlift\ndeadlifted\ndeadlifting\ndeadlifts\ndeadlight\ndeadlights\ndeadline\ndeadlines\ndeadliness\ndeadlinesses\ndeadlock\ndeadlocked\ndeadlocking\ndeadlocks\ndeadly\ndeadness\ndeadnesses\ndeadpan\ndeadpanned\ndeadpanner\ndeadpanners\ndeadpanning\ndeadpans\ndeads\ndeadweight\ndeadweights\ndeadwood\ndeadwoods\ndeaerate\ndeaerated\ndeaerates\ndeaerating\ndeaeration\ndeaerations\ndeaerator\ndeaerators\ndeaf\ndeafen\ndeafened\ndeafening\ndeafeningly\ndeafens\ndeafer\ndeafest\ndeafish\ndeafly\ndeafness\ndeafnesses\ndeair\ndeaired\ndeairing\ndeairs\ndeal\ndealate\ndealated\ndealates\ndealation\ndealations\ndealer\ndealers\ndealership\ndealerships\ndealfish\ndealfishes\ndealing\ndealings\ndeals\ndealt\ndeaminase\ndeaminases\ndeaminate\ndeaminated\ndeaminates\ndeaminating\ndeamination\ndeaminations\ndean\ndeaned\ndeaneries\ndeanery\ndeaning\ndeans\ndeanship\ndeanships\ndear\ndearer\ndearest\ndearie\ndearies\ndearly\ndearness\ndearnesses\ndears\ndearth\ndearths\ndeary\ndeash\ndeashed\ndeashes\ndeashing\ndeasil\ndeath\ndeathbed\ndeathbeds\ndeathblow\ndeathblows\ndeathcup\ndeathcups\ndeathful\ndeathless\ndeathlessly\ndeathlessness\ndeathlessnesses\ndeathlike\ndeathly\ndeaths\ndeathsman\ndeathsmen\ndeathtrap\ndeathtraps\ndeathwatch\ndeathwatches\ndeathy\ndeave\ndeaved\ndeaves\ndeaving\ndeb\ndebacle\ndebacles\ndebar\ndebark\ndebarkation\ndebarkations\ndebarked\ndebarking\ndebarks\ndebarment\ndebarments\ndebarred\ndebarring\ndebars\ndebase\ndebased\ndebasement\ndebasements\ndebaser\ndebasers\ndebases\ndebasing\ndebatable\ndebate\ndebated\ndebatement\ndebatements\ndebater\ndebaters\ndebates\ndebating\ndebauch\ndebauched\ndebauchee\ndebauchees\ndebaucher\ndebaucheries\ndebauchers\ndebauchery\ndebauches\ndebauching\ndebeak\ndebeaked\ndebeaking\ndebeaks\ndebenture\ndebentures\ndebilitate\ndebilitated\ndebilitates\ndebilitating\ndebilitation\ndebilitations\ndebilities\ndebility\ndebit\ndebited\ndebiting\ndebits\ndebonair\ndebonairly\ndebonairness\ndebonairnesses\ndebone\ndeboned\ndeboner\ndeboners\ndebones\ndeboning\ndebouch\ndebouche\ndebouched\ndebouches\ndebouching\ndebouchment\ndebouchments\ndebride\ndebrided\ndebridement\ndebridements\ndebrides\ndebriding\ndebrief\ndebriefed\ndebriefing\ndebriefings\ndebriefs\ndebris\ndebruise\ndebruised\ndebruises\ndebruising\ndebs\ndebt\ndebtless\ndebtor\ndebtors\ndebts\ndebug\ndebugged\ndebugger\ndebuggers\ndebugging\ndebugs\ndebunk\ndebunked\ndebunker\ndebunkers\ndebunking\ndebunks\ndebut\ndebutant\ndebutante\ndebutantes\ndebutants\ndebuted\ndebuting\ndebuts\ndebye\ndebyes\ndecadal\ndecade\ndecadence\ndecadences\ndecadencies\ndecadency\ndecadent\ndecadently\ndecadents\ndecades\ndecaf\ndecaffeinate\ndecaffeinated\ndecaffeinates\ndecaffeinating\ndecaffeination\ndecaffeinations\ndecafs\ndecagon\ndecagons\ndecagram\ndecagrams\ndecahedra\ndecahedron\ndecahedrons\ndecal\ndecalcification\ndecalcifications\ndecalcified\ndecalcifies\ndecalcify\ndecalcifying\ndecalcomania\ndecalcomanias\ndecaliter\ndecaliters\ndecalog\ndecalogs\ndecalogue\ndecalogues\ndecals\ndecameter\ndecameters\ndecamethonium\ndecamethoniums\ndecametric\ndecamp\ndecamped\ndecamping\ndecampment\ndecampments\ndecamps\ndecanal\ndecane\ndecanes\ndecant\ndecantation\ndecantations\ndecanted\ndecanter\ndecanters\ndecanting\ndecants\ndecapitate\ndecapitated\ndecapitates\ndecapitating\ndecapitation\ndecapitations\ndecapitator\ndecapitators\ndecapod\ndecapodan\ndecapodans\ndecapodous\ndecapods\ndecarbonate\ndecarbonated\ndecarbonates\ndecarbonating\ndecarbonation\ndecarbonations\ndecarbonize\ndecarbonized\ndecarbonizer\ndecarbonizers\ndecarbonizes\ndecarbonizing\ndecarboxylase\ndecarboxylases\ndecarboxylate\ndecarboxylated\ndecarboxylates\ndecarboxylating\ndecarboxylation\ndecarboxylations\ndecarburization\ndecarburizations\ndecarburize\ndecarburized\ndecarburizes\ndecarburizing\ndecare\ndecares\ndecasualization\ndecasualizations\ndecasyllabic\ndecasyllabics\ndecasyllable\ndecasyllables\ndecathlete\ndecathletes\ndecathlon\ndecathlons\ndecay\ndecayed\ndecayer\ndecayers\ndecaying\ndecays\ndecease\ndeceased\ndeceases\ndeceasing\ndecedent\ndecedents\ndeceit\ndeceitful\ndeceitfully\ndeceitfulness\ndeceitfulnesses\ndeceits\ndeceivable\ndeceive\ndeceived\ndeceiver\ndeceivers\ndeceives\ndeceiving\ndeceivingly\ndecelerate\ndecelerated\ndecelerates\ndecelerating\ndeceleration\ndecelerations\ndecelerator\ndecelerators\ndecemvir\ndecemviral\ndecemvirate\ndecemvirates\ndecemviri\ndecemvirs\ndecenaries\ndecenary\ndecencies\ndecency\ndecennia\ndecennial\ndecennially\ndecennials\ndecennium\ndecenniums\ndecent\ndecenter\ndecentered\ndecentering\ndecenters\ndecentest\ndecently\ndecentralization\ndecentralizations\ndecentralize\ndecentralized\ndecentralizes\ndecentralizing\ndecentre\ndecentred\ndecentres\ndecentring\ndeception\ndeceptional\ndeceptions\ndeceptive\ndeceptively\ndeceptiveness\ndeceptivenesses\ndecerebrate\ndecerebrated\ndecerebrates\ndecerebrating\ndecerebration\ndecerebrations\ndecern\ndecerned\ndecerning\ndecerns\ndecertification\ndecertifications\ndecertified\ndecertifies\ndecertify\ndecertifying\ndechlorinate\ndechlorinated\ndechlorinates\ndechlorinating\ndechlorination\ndechlorinations\ndeciare\ndeciares\ndecibel\ndecibels\ndecidabilities\ndecidability\ndecidable\ndecide\ndecided\ndecidedly\ndecidedness\ndecidednesses\ndecider\ndeciders\ndecides\ndeciding\ndecidua\ndeciduae\ndecidual\ndeciduas\ndeciduate\ndeciduous\ndeciduousness\ndeciduousnesses\ndecigram\ndecigrams\ndecile\ndeciles\ndeciliter\ndeciliters\ndecillion\ndecillions\ndecimal\ndecimalization\ndecimalizations\ndecimalize\ndecimalized\ndecimalizes\ndecimalizing\ndecimally\ndecimals\ndecimate\ndecimated\ndecimates\ndecimating\ndecimation\ndecimations\ndecimeter\ndecimeters\ndecipher\ndecipherable\ndeciphered\ndecipherer\ndecipherers\ndeciphering\ndecipherment\ndecipherments\ndeciphers\ndecision\ndecisional\ndecisioned\ndecisioning\ndecisions\ndecisive\ndecisively\ndecisiveness\ndecisivenesses\ndeck\ndecked\ndeckel\ndeckels\ndecker\ndeckers\ndeckhand\ndeckhands\ndeckhouse\ndeckhouses\ndecking\ndeckings\ndeckle\ndeckles\ndecks\ndeclaim\ndeclaimed\ndeclaimer\ndeclaimers\ndeclaiming\ndeclaims\ndeclamation\ndeclamations\ndeclamatory\ndeclarable\ndeclarant\ndeclarants\ndeclaration\ndeclarations\ndeclarative\ndeclaratively\ndeclaratory\ndeclare\ndeclared\ndeclarer\ndeclarers\ndeclares\ndeclaring\ndeclass\ndeclasse\ndeclassed\ndeclasses\ndeclassification\ndeclassifications\ndeclassified\ndeclassifies\ndeclassify\ndeclassifying\ndeclassing\ndeclaw\ndeclawed\ndeclawing\ndeclaws\ndeclension\ndeclensional\ndeclensions\ndeclinable\ndeclination\ndeclinational\ndeclinations\ndecline\ndeclined\ndecliner\ndecliners\ndeclines\ndeclining\ndeclivities\ndeclivitous\ndeclivity\ndeco\ndecoct\ndecocted\ndecocting\ndecoction\ndecoctions\ndecocts\ndecode\ndecoded\ndecoder\ndecoders\ndecodes\ndecoding\ndecollate\ndecollated\ndecollates\ndecollating\ndecollation\ndecollations\ndecolletage\ndecolletages\ndecollete\ndecolletes\ndecolonization\ndecolonizations\ndecolonize\ndecolonized\ndecolonizes\ndecolonizing\ndecolor\ndecolored\ndecoloring\ndecolorization\ndecolorizations\ndecolorize\ndecolorized\ndecolorizer\ndecolorizers\ndecolorizes\ndecolorizing\ndecolors\ndecolour\ndecoloured\ndecolouring\ndecolours\ndecommission\ndecommissioned\ndecommissioning\ndecommissions\ndecompensate\ndecompensated\ndecompensates\ndecompensating\ndecompensation\ndecompensations\ndecomposabilities\ndecomposability\ndecomposable\ndecompose\ndecomposed\ndecomposer\ndecomposers\ndecomposes\ndecomposing\ndecomposition\ndecompositions\ndecompound\ndecompress\ndecompressed\ndecompresses\ndecompressing\ndecompression\ndecompressions\ndeconcentrate\ndeconcentrated\ndeconcentrates\ndeconcentrating\ndeconcentration\ndeconcentrations\ndecondition\ndeconditioned\ndeconditioning\ndeconditions\ndecongest\ndecongestant\ndecongestants\ndecongested\ndecongesting\ndecongestion\ndecongestions\ndecongestive\ndecongests\ndeconsecrate\ndeconsecrated\ndeconsecrates\ndeconsecrating\ndeconsecration\ndeconsecrations\ndeconstruct\ndeconstructed\ndeconstructing\ndeconstruction\ndeconstructionist\ndeconstructionists\ndeconstructions\ndeconstructive\ndeconstructor\ndeconstructors\ndeconstructs\ndecontaminate\ndecontaminated\ndecontaminates\ndecontaminating\ndecontamination\ndecontaminations\ndecontaminator\ndecontaminators\ndecontrol\ndecontrolled\ndecontrolling\ndecontrols\ndecor\ndecorate\ndecorated\ndecorates\ndecorating\ndecoration\ndecorations\ndecorative\ndecoratively\ndecorativeness\ndecorativenesses\ndecorator\ndecorators\ndecorous\ndecorously\ndecorousness\ndecorousnesses\ndecors\ndecorticate\ndecorticated\ndecorticates\ndecorticating\ndecortication\ndecortications\ndecorticator\ndecorticators\ndecorum\ndecorums\ndecos\ndecoupage\ndecoupaged\ndecoupages\ndecoupaging\ndecouple\ndecoupled\ndecouples\ndecoupling\ndecoy\ndecoyed\ndecoyer\ndecoyers\ndecoying\ndecoys\ndecrease\ndecreased\ndecreases\ndecreasing\ndecreasingly\ndecree\ndecreed\ndecreeing\ndecreer\ndecreers\ndecrees\ndecrement\ndecremental\ndecremented\ndecrementing\ndecrements\ndecrepit\ndecrepitate\ndecrepitated\ndecrepitates\ndecrepitating\ndecrepitation\ndecrepitations\ndecrepitly\ndecrepitude\ndecrepitudes\ndecrescendo\ndecrescendos\ndecrescent\ndecretal\ndecretals\ndecretive\ndecretory\ndecrial\ndecrials\ndecried\ndecrier\ndecriers\ndecries\ndecriminalization\ndecriminalizations\ndecriminalize\ndecriminalized\ndecriminalizes\ndecriminalizing\ndecrown\ndecrowned\ndecrowning\ndecrowns\ndecry\ndecrying\ndecrypt\ndecrypted\ndecrypting\ndecryption\ndecryptions\ndecrypts\ndecuman\ndecumbent\ndecuple\ndecupled\ndecuples\ndecupling\ndecuries\ndecurion\ndecurions\ndecurrent\ndecurve\ndecurved\ndecurves\ndecurving\ndecury\ndecussate\ndecussated\ndecussates\ndecussating\ndecussation\ndecussations\ndedal\ndedans\ndedicate\ndedicated\ndedicatedly\ndedicatee\ndedicatees\ndedicates\ndedicating\ndedication\ndedications\ndedicator\ndedicators\ndedicatory\ndedifferentiate\ndedifferentiated\ndedifferentiates\ndedifferentiating\ndedifferentiation\ndedifferentiations\ndeduce\ndeduced\ndeduces\ndeducible\ndeducing\ndeduct\ndeducted\ndeductibilities\ndeductibility\ndeductible\ndeductibles\ndeducting\ndeduction\ndeductions\ndeductive\ndeductively\ndeducts\ndee\ndeed\ndeeded\ndeedier\ndeediest\ndeeding\ndeedless\ndeeds\ndeedy\ndeejay\ndeejays\ndeem\ndeemed\ndeeming\ndeemphasize\ndeemphasized\ndeemphasizes\ndeemphasizing\ndeems\ndeemster\ndeemsters\ndeep\ndeepen\ndeepened\ndeepener\ndeepeners\ndeepening\ndeepens\ndeeper\ndeepest\ndeeply\ndeepness\ndeepnesses\ndeeps\ndeepwater\ndeer\ndeerberries\ndeerberry\ndeerflies\ndeerfly\ndeerhound\ndeerhounds\ndeerlike\ndeers\ndeerskin\ndeerskins\ndeerstalker\ndeerstalkers\ndeerweed\ndeerweeds\ndeeryard\ndeeryards\ndees\ndeescalate\ndeescalated\ndeescalates\ndeescalating\ndeescalation\ndeescalations\ndeet\ndeets\ndeewan\ndeewans\ndeface\ndefaced\ndefacement\ndefacements\ndefacer\ndefacers\ndefaces\ndefacing\ndefalcate\ndefalcated\ndefalcates\ndefalcating\ndefalcation\ndefalcations\ndefalcator\ndefalcators\ndefamation\ndefamations\ndefamatory\ndefame\ndefamed\ndefamer\ndefamers\ndefames\ndefaming\ndefang\ndefanged\ndefanging\ndefangs\ndefat\ndefats\ndefatted\ndefatting\ndefault\ndefaulted\ndefaulter\ndefaulters\ndefaulting\ndefaults\ndefeasance\ndefeasances\ndefeasibilities\ndefeasibility\ndefeasible\ndefeat\ndefeated\ndefeater\ndefeaters\ndefeating\ndefeatism\ndefeatisms\ndefeatist\ndefeatists\ndefeats\ndefeature\ndefeatures\ndefecate\ndefecated\ndefecates\ndefecating\ndefecation\ndefecations\ndefect\ndefected\ndefecting\ndefection\ndefections\ndefective\ndefectively\ndefectiveness\ndefectivenesses\ndefectives\ndefector\ndefectors\ndefects\ndefeminization\ndefeminizations\ndefeminize\ndefeminized\ndefeminizes\ndefeminizing\ndefence\ndefenceman\ndefencemen\ndefences\ndefend\ndefendable\ndefendant\ndefendants\ndefended\ndefender\ndefenders\ndefending\ndefends\ndefenestrate\ndefenestrated\ndefenestrates\ndefenestrating\ndefenestration\ndefenestrations\ndefense\ndefensed\ndefenseless\ndefenselessly\ndefenselessness\ndefenselessnesses\ndefenseman\ndefensemen\ndefenses\ndefensibilities\ndefensibility\ndefensible\ndefensibly\ndefensing\ndefensive\ndefensively\ndefensiveness\ndefensivenesses\ndefensives\ndefer\ndeference\ndeferences\ndeferent\ndeferential\ndeferentially\ndeferents\ndeferment\ndeferments\ndeferrable\ndeferrables\ndeferral\ndeferrals\ndeferred\ndeferrer\ndeferrers\ndeferring\ndefers\ndefervescence\ndefervescences\ndefi\ndefiance\ndefiances\ndefiant\ndefiantly\ndefibrillate\ndefibrillated\ndefibrillates\ndefibrillating\ndefibrillation\ndefibrillations\ndefibrillator\ndefibrillators\ndefibrinate\ndefibrinated\ndefibrinates\ndefibrinating\ndefibrination\ndefibrinations\ndeficiencies\ndeficiency\ndeficient\ndeficiently\ndeficients\ndeficit\ndeficits\ndefied\ndefier\ndefiers\ndefies\ndefilade\ndefiladed\ndefilades\ndefilading\ndefile\ndefiled\ndefilement\ndefilements\ndefiler\ndefilers\ndefiles\ndefiling\ndefinable\ndefinably\ndefine\ndefined\ndefinement\ndefinements\ndefiner\ndefiners\ndefines\ndefinienda\ndefiniendum\ndefiniens\ndefinientia\ndefining\ndefinite\ndefinitely\ndefiniteness\ndefinitenesses\ndefinition\ndefinitional\ndefinitions\ndefinitive\ndefinitively\ndefinitiveness\ndefinitivenesses\ndefinitives\ndefinitize\ndefinitized\ndefinitizes\ndefinitizing\ndefinitude\ndefinitudes\ndefis\ndeflagrate\ndeflagrated\ndeflagrates\ndeflagrating\ndeflagration\ndeflagrations\ndeflate\ndeflated\ndeflater\ndeflaters\ndeflates\ndeflating\ndeflation\ndeflationary\ndeflations\ndeflator\ndeflators\ndeflea\ndefleaed\ndefleaing\ndefleas\ndeflect\ndeflectable\ndeflected\ndeflecting\ndeflection\ndeflections\ndeflective\ndeflector\ndeflectors\ndeflects\ndeflexed\ndefloration\ndeflorations\ndeflower\ndeflowered\ndeflowerer\ndeflowerers\ndeflowering\ndeflowers\ndefoam\ndefoamed\ndefoamer\ndefoamers\ndefoaming\ndefoams\ndefocus\ndefocused\ndefocuses\ndefocusing\ndefocussed\ndefocusses\ndefocussing\ndefog\ndefogged\ndefogger\ndefoggers\ndefogging\ndefogs\ndefoliant\ndefoliants\ndefoliate\ndefoliated\ndefoliates\ndefoliating\ndefoliation\ndefoliations\ndefoliator\ndefoliators\ndeforce\ndeforced\ndeforcement\ndeforcements\ndeforces\ndeforcing\ndeforest\ndeforestation\ndeforestations\ndeforested\ndeforesting\ndeforests\ndeform\ndeformable\ndeformalize\ndeformalized\ndeformalizes\ndeformalizing\ndeformation\ndeformational\ndeformations\ndeformative\ndeformed\ndeformer\ndeformers\ndeforming\ndeformities\ndeformity\ndeforms\ndefraud\ndefrauded\ndefrauder\ndefrauders\ndefrauding\ndefrauds\ndefray\ndefrayable\ndefrayal\ndefrayals\ndefrayed\ndefrayer\ndefrayers\ndefraying\ndefrays\ndefrock\ndefrocked\ndefrocking\ndefrocks\ndefrost\ndefrosted\ndefroster\ndefrosters\ndefrosting\ndefrosts\ndeft\ndefter\ndeftest\ndeftly\ndeftness\ndeftnesses\ndefunct\ndefund\ndefunded\ndefunding\ndefunds\ndefuse\ndefused\ndefuses\ndefusing\ndefuze\ndefuzed\ndefuzes\ndefuzing\ndefy\ndefying\ndegage\ndegame\ndegames\ndegami\ndegamis\ndegas\ndegases\ndegassed\ndegasser\ndegassers\ndegasses\ndegassing\ndegauss\ndegaussed\ndegausser\ndegaussers\ndegausses\ndegaussing\ndegeneracies\ndegeneracy\ndegenerate\ndegenerated\ndegenerately\ndegenerateness\ndegeneratenesses\ndegenerates\ndegenerating\ndegeneration\ndegenerations\ndegenerative\ndegerm\ndegermed\ndegerming\ndegerms\ndeglaciated\ndeglaciation\ndeglaciations\ndeglamorization\ndeglamorizations\ndeglamorize\ndeglamorized\ndeglamorizes\ndeglamorizing\ndeglaze\ndeglazed\ndeglazes\ndeglazing\ndeglutition\ndeglutitions\ndegradable\ndegradation\ndegradations\ndegradative\ndegrade\ndegraded\ndegradedly\ndegrader\ndegraders\ndegrades\ndegrading\ndegradingly\ndegranulation\ndegranulations\ndegrease\ndegreased\ndegreaser\ndegreasers\ndegreases\ndegreasing\ndegree\ndegreed\ndegrees\ndegressive\ndegressively\ndegringolade\ndegringolades\ndegum\ndegummed\ndegumming\ndegums\ndegust\ndegustation\ndegustations\ndegusted\ndegusting\ndegusts\ndehisce\ndehisced\ndehiscence\ndehiscences\ndehiscent\ndehisces\ndehiscing\ndehorn\ndehorned\ndehorner\ndehorners\ndehorning\ndehorns\ndehort\ndehorted\ndehorting\ndehorts\ndehumanization\ndehumanizations\ndehumanize\ndehumanized\ndehumanizes\ndehumanizing\ndehumidification\ndehumidifications\ndehumidified\ndehumidifier\ndehumidifiers\ndehumidifies\ndehumidify\ndehumidifying\ndehydrate\ndehydrated\ndehydrates\ndehydrating\ndehydration\ndehydrations\ndehydrator\ndehydrators\ndehydrochlorinase\ndehydrochlorinases\ndehydrochlorinate\ndehydrochlorinated\ndehydrochlorinates\ndehydrochlorinating\ndehydrochlorination\ndehydrochlorinations\ndehydrogenase\ndehydrogenases\ndehydrogenate\ndehydrogenated\ndehydrogenates\ndehydrogenating\ndehydrogenation\ndehydrogenations\ndeice\ndeiced\ndeicer\ndeicers\ndeices\ndeicidal\ndeicide\ndeicides\ndeicing\ndeictic\ndeific\ndeifical\ndeification\ndeifications\ndeified\ndeifier\ndeifiers\ndeifies\ndeiform\ndeify\ndeifying\ndeign\ndeigned\ndeigning\ndeigns\ndeil\ndeils\ndeindustrialization\ndeindustrializations\ndeindustrialize\ndeindustrialized\ndeindustrializes\ndeindustrializing\ndeinonychus\ndeinonychuses\ndeinstitutionalization\ndeinstitutionalizations\ndeinstitutionalize\ndeinstitutionalized\ndeinstitutionalizes\ndeinstitutionalizing\ndeionization\ndeionizations\ndeionize\ndeionized\ndeionizer\ndeionizers\ndeionizes\ndeionizing\ndeism\ndeisms\ndeist\ndeistic\ndeistical\ndeistically\ndeists\ndeities\ndeity\ndeixis\ndeixises\ndeject\ndejecta\ndejected\ndejectedly\ndejectedness\ndejectednesses\ndejecting\ndejection\ndejections\ndejects\ndejeuner\ndejeuners\ndekagram\ndekagrams\ndekaliter\ndekaliters\ndekameter\ndekameters\ndekametric\ndekare\ndekares\ndeke\ndeked\ndekes\ndeking\ndekko\ndekkos\ndel\ndelaine\ndelaines\ndelaminate\ndelaminated\ndelaminates\ndelaminating\ndelamination\ndelaminations\ndelate\ndelated\ndelates\ndelating\ndelation\ndelations\ndelator\ndelators\ndelay\ndelayed\ndelayer\ndelayers\ndelaying\ndelays\ndele\ndelead\ndeleaded\ndeleading\ndeleads\ndeleave\ndeleaved\ndeleaves\ndeleaving\ndelectabilities\ndelectability\ndelectable\ndelectables\ndelectably\ndelectation\ndelectations\ndeled\ndelegable\ndelegacies\ndelegacy\ndelegate\ndelegated\ndelegatee\ndelegatees\ndelegates\ndelegating\ndelegation\ndelegations\ndelegator\ndelegators\ndelegitimation\ndelegitimations\ndeleing\ndeles\ndelete\ndeleted\ndeleterious\ndeleteriously\ndeleteriousness\ndeleteriousnesses\ndeletes\ndeleting\ndeletion\ndeletions\ndelf\ndelfs\ndelft\ndelfts\ndelftware\ndelftwares\ndeli\ndeliberate\ndeliberated\ndeliberately\ndeliberateness\ndeliberatenesses\ndeliberates\ndeliberating\ndeliberation\ndeliberations\ndeliberative\ndeliberatively\ndeliberativeness\ndeliberativenesses\ndelicacies\ndelicacy\ndelicate\ndelicately\ndelicates\ndelicatessen\ndelicatessens\ndelicious\ndeliciously\ndeliciousness\ndeliciousnesses\ndelict\ndelicts\ndelight\ndelighted\ndelightedly\ndelightedness\ndelightednesses\ndelighter\ndelighters\ndelightful\ndelightfully\ndelightfulness\ndelightfulnesses\ndelighting\ndelights\ndelightsome\ndelime\ndelimed\ndelimes\ndeliming\ndelimit\ndelimitation\ndelimitations\ndelimited\ndelimiter\ndelimiters\ndelimiting\ndelimits\ndelineate\ndelineated\ndelineates\ndelineating\ndelineation\ndelineations\ndelineative\ndelineator\ndelineators\ndelinquencies\ndelinquency\ndelinquent\ndelinquently\ndelinquents\ndeliquesce\ndeliquesced\ndeliquescence\ndeliquescences\ndeliquescent\ndeliquesces\ndeliquescing\ndeliria\ndelirious\ndeliriously\ndeliriousness\ndeliriousnesses\ndelirium\ndeliriums\ndelis\ndelist\ndelisted\ndelisting\ndelists\ndeliver\ndeliverabilities\ndeliverability\ndeliverable\ndeliverance\ndeliverances\ndelivered\ndeliverer\ndeliverers\ndeliveries\ndelivering\ndelivers\ndelivery\ndeliveryman\ndeliverymen\ndell\ndellies\ndells\ndelly\ndelocalization\ndelocalizations\ndelocalize\ndelocalized\ndelocalizes\ndelocalizing\ndelouse\ndeloused\ndelouser\ndelousers\ndelouses\ndelousing\ndelphic\ndelphically\ndelphinium\ndelphiniums\ndels\ndelt\ndelta\ndeltaic\ndeltas\ndeltic\ndeltoid\ndeltoidei\ndeltoideus\ndeltoids\ndelts\ndelude\ndeluded\ndeluder\ndeluders\ndeludes\ndeluding\ndeluge\ndeluged\ndeluges\ndeluging\ndelusion\ndelusional\ndelusionary\ndelusions\ndelusive\ndelusively\ndelusiveness\ndelusivenesses\ndelusory\ndeluster\ndelustered\ndelustering\ndelusters\ndeluxe\ndelve\ndelved\ndelver\ndelvers\ndelves\ndelving\ndemagnetization\ndemagnetizations\ndemagnetize\ndemagnetized\ndemagnetizer\ndemagnetizers\ndemagnetizes\ndemagnetizing\ndemagog\ndemagoged\ndemagogic\ndemagogically\ndemagogies\ndemagoging\ndemagogs\ndemagogue\ndemagogued\ndemagogueries\ndemagoguery\ndemagogues\ndemagoguing\ndemagogy\ndemand\ndemandable\ndemandant\ndemandants\ndemanded\ndemander\ndemanders\ndemanding\ndemandingly\ndemandingness\ndemandingnesses\ndemands\ndemantoid\ndemantoids\ndemarcate\ndemarcated\ndemarcates\ndemarcating\ndemarcation\ndemarcations\ndemarche\ndemarches\ndemark\ndemarked\ndemarking\ndemarks\ndemast\ndemasted\ndemasting\ndemasts\ndematerialization\ndematerializations\ndematerialize\ndematerialized\ndematerializes\ndematerializing\ndeme\ndemean\ndemeaned\ndemeaning\ndemeanor\ndemeanors\ndemeanour\ndemeanours\ndemeans\ndement\ndemented\ndementedly\ndementedness\ndementednesses\ndementia\ndemential\ndementias\ndementing\ndements\ndemerara\ndemeraras\ndemerge\ndemerged\ndemerger\ndemergered\ndemergering\ndemergers\ndemerges\ndemerging\ndemerit\ndemerited\ndemeriting\ndemerits\ndemersal\ndemes\ndemesne\ndemesnes\ndemeton\ndemetons\ndemies\ndemigod\ndemigoddess\ndemigoddesses\ndemigods\ndemijohn\ndemijohns\ndemilitarization\ndemilitarizations\ndemilitarize\ndemilitarized\ndemilitarizes\ndemilitarizing\ndemilune\ndemilunes\ndemimondaine\ndemimondaines\ndemimonde\ndemimondes\ndemineralization\ndemineralizations\ndemineralize\ndemineralized\ndemineralizer\ndemineralizers\ndemineralizes\ndemineralizing\ndemirep\ndemireps\ndemise\ndemised\ndemisemiquaver\ndemisemiquavers\ndemises\ndemising\ndemission\ndemissions\ndemit\ndemitasse\ndemitasses\ndemits\ndemitted\ndemitting\ndemiurge\ndemiurges\ndemiurgic\ndemiurgical\ndemivolt\ndemivolts\ndemiworld\ndemiworlds\ndemo\ndemob\ndemobbed\ndemobbing\ndemobilization\ndemobilizations\ndemobilize\ndemobilized\ndemobilizes\ndemobilizing\ndemobs\ndemocracies\ndemocracy\ndemocrat\ndemocratic\ndemocratically\ndemocratization\ndemocratizations\ndemocratize\ndemocratized\ndemocratizer\ndemocratizers\ndemocratizes\ndemocratizing\ndemocrats\ndemode\ndemoded\ndemodulate\ndemodulated\ndemodulates\ndemodulating\ndemodulation\ndemodulations\ndemodulator\ndemodulators\ndemoed\ndemographer\ndemographers\ndemographic\ndemographical\ndemographically\ndemographics\ndemographies\ndemography\ndemoing\ndemoiselle\ndemoiselles\ndemolish\ndemolished\ndemolisher\ndemolishers\ndemolishes\ndemolishing\ndemolishment\ndemolishments\ndemolition\ndemolitionist\ndemolitionists\ndemolitions\ndemon\ndemoness\ndemonesses\ndemonetization\ndemonetizations\ndemonetize\ndemonetized\ndemonetizes\ndemonetizing\ndemoniac\ndemoniacal\ndemoniacally\ndemoniacs\ndemonian\ndemonic\ndemonical\ndemonically\ndemonise\ndemonised\ndemonises\ndemonising\ndemonism\ndemonisms\ndemonist\ndemonists\ndemonization\ndemonizations\ndemonize\ndemonized\ndemonizes\ndemonizing\ndemonological\ndemonologies\ndemonologist\ndemonologists\ndemonology\ndemons\ndemonstrabilities\ndemonstrability\ndemonstrable\ndemonstrably\ndemonstrate\ndemonstrated\ndemonstrates\ndemonstrating\ndemonstration\ndemonstrational\ndemonstrations\ndemonstrative\ndemonstratively\ndemonstrativeness\ndemonstrativenesses\ndemonstratives\ndemonstrator\ndemonstrators\ndemoralization\ndemoralizations\ndemoralize\ndemoralized\ndemoralizer\ndemoralizers\ndemoralizes\ndemoralizing\ndemoralizingly\ndemos\ndemoses\ndemote\ndemoted\ndemotes\ndemotic\ndemotics\ndemoting\ndemotion\ndemotions\ndemotist\ndemotists\ndemount\ndemountable\ndemounted\ndemounting\ndemounts\ndempster\ndempsters\ndemulcent\ndemulcents\ndemultiplexer\ndemultiplexers\ndemur\ndemure\ndemurely\ndemureness\ndemurenesses\ndemurer\ndemurest\ndemurrage\ndemurrages\ndemurral\ndemurrals\ndemurred\ndemurrer\ndemurrers\ndemurring\ndemurs\ndemy\ndemyelinating\ndemyelination\ndemyelinations\ndemystification\ndemystifications\ndemystified\ndemystifies\ndemystify\ndemystifying\ndemythologization\ndemythologizations\ndemythologize\ndemythologized\ndemythologizer\ndemythologizers\ndemythologizes\ndemythologizing\nden\ndenar\ndenari\ndenarii\ndenarius\ndenars\ndenary\ndenationalization\ndenationalizations\ndenationalize\ndenationalized\ndenationalizes\ndenationalizing\ndenaturalization\ndenaturalizations\ndenaturalize\ndenaturalized\ndenaturalizes\ndenaturalizing\ndenaturant\ndenaturants\ndenaturation\ndenaturations\ndenature\ndenatured\ndenatures\ndenaturing\ndenazification\ndenazifications\ndenazified\ndenazifies\ndenazify\ndenazifying\ndendriform\ndendrite\ndendrites\ndendritic\ndendrochronological\ndendrochronologically\ndendrochronologies\ndendrochronologist\ndendrochronologists\ndendrochronology\ndendrogram\ndendrograms\ndendroid\ndendrologic\ndendrological\ndendrologies\ndendrologist\ndendrologists\ndendrology\ndendron\ndendrons\ndene\ndenegation\ndenegations\ndenervate\ndenervated\ndenervates\ndenervating\ndenervation\ndenervations\ndenes\ndengue\ndengues\ndeni\ndeniabilities\ndeniability\ndeniable\ndeniably\ndenial\ndenials\ndenied\ndenier\ndeniers\ndenies\ndenigrate\ndenigrated\ndenigrates\ndenigrating\ndenigration\ndenigrations\ndenigrative\ndenigrator\ndenigrators\ndenigratory\ndenim\ndenims\ndenitrification\ndenitrifications\ndenitrified\ndenitrifier\ndenitrifiers\ndenitrifies\ndenitrify\ndenitrifying\ndenizen\ndenizened\ndenizening\ndenizens\ndenned\ndenning\ndenominal\ndenominate\ndenominated\ndenominates\ndenominating\ndenomination\ndenominational\ndenominationalism\ndenominationalisms\ndenominations\ndenominative\ndenominatives\ndenominator\ndenominators\ndenotation\ndenotations\ndenotative\ndenote\ndenoted\ndenotement\ndenotements\ndenotes\ndenoting\ndenotive\ndenouement\ndenouements\ndenounce\ndenounced\ndenouncement\ndenouncements\ndenouncer\ndenouncers\ndenounces\ndenouncing\ndens\ndense\ndensely\ndenseness\ndensenesses\ndenser\ndensest\ndensification\ndensifications\ndensified\ndensifies\ndensify\ndensifying\ndensities\ndensitometer\ndensitometers\ndensitometric\ndensitometries\ndensitometry\ndensity\ndent\ndental\ndentalia\ndentalium\ndentaliums\ndentally\ndentals\ndentate\ndentated\ndented\ndenticle\ndenticles\ndenticulate\ndenticulated\ndenticulation\ndenticulations\ndentiform\ndentifrice\ndentifrices\ndentil\ndentiled\ndentils\ndentin\ndentinal\ndentine\ndentines\ndenting\ndentins\ndentist\ndentistries\ndentistry\ndentists\ndentition\ndentitions\ndentoid\ndents\ndentulous\ndentural\ndenture\ndentures\ndenturist\ndenturists\ndenuclearization\ndenuclearizations\ndenuclearize\ndenuclearized\ndenuclearizes\ndenuclearizing\ndenudate\ndenudated\ndenudates\ndenudating\ndenudation\ndenudations\ndenude\ndenuded\ndenudement\ndenudements\ndenuder\ndenuders\ndenudes\ndenuding\ndenumerabilities\ndenumerability\ndenumerable\ndenumerably\ndenunciation\ndenunciations\ndenunciative\ndenunciatory\ndeny\ndenying\ndenyingly\ndeodand\ndeodands\ndeodar\ndeodara\ndeodaras\ndeodars\ndeodorant\ndeodorants\ndeodorization\ndeodorizations\ndeodorize\ndeodorized\ndeodorizer\ndeodorizers\ndeodorizes\ndeodorizing\ndeontic\ndeontological\ndeontologies\ndeontologist\ndeontologists\ndeontology\ndeorbit\ndeorbited\ndeorbiting\ndeorbits\ndeoxidation\ndeoxidations\ndeoxidize\ndeoxidized\ndeoxidizer\ndeoxidizers\ndeoxidizes\ndeoxidizing\ndeoxy\ndeoxygenate\ndeoxygenated\ndeoxygenates\ndeoxygenating\ndeoxygenation\ndeoxygenations\ndeoxyribonuclease\ndeoxyribonucleases\ndeoxyribonucleotide\ndeoxyribonucleotides\ndeoxyribose\ndeoxyriboses\ndepaint\ndepainted\ndepainting\ndepaints\ndepart\ndeparted\ndepartee\ndepartees\ndeparting\ndepartment\ndepartmental\ndepartmentalization\ndepartmentalizations\ndepartmentalize\ndepartmentalized\ndepartmentalizes\ndepartmentalizing\ndepartmentally\ndepartments\ndeparts\ndeparture\ndepartures\ndepauperate\ndepend\ndependabilities\ndependability\ndependable\ndependableness\ndependablenesses\ndependably\ndependance\ndependances\ndependant\ndependants\ndepended\ndependence\ndependences\ndependencies\ndependency\ndependent\ndependently\ndependents\ndepending\ndepends\ndeperm\ndepermed\ndeperming\ndeperms\ndepersonalization\ndepersonalizations\ndepersonalize\ndepersonalized\ndepersonalizes\ndepersonalizing\ndephosphorylate\ndephosphorylated\ndephosphorylates\ndephosphorylating\ndephosphorylation\ndephosphorylations\ndepict\ndepicted\ndepicter\ndepicters\ndepicting\ndepiction\ndepictions\ndepictor\ndepictors\ndepicts\ndepigmentation\ndepigmentations\ndepilate\ndepilated\ndepilates\ndepilating\ndepilation\ndepilations\ndepilatories\ndepilatory\ndeplane\ndeplaned\ndeplanes\ndeplaning\ndepletable\ndeplete\ndepleted\ndepletes\ndepleting\ndepletion\ndepletions\ndepletive\ndeplorable\ndeplorableness\ndeplorablenesses\ndeplorably\ndeplore\ndeplored\ndeplorer\ndeplorers\ndeplores\ndeploring\ndeploringly\ndeploy\ndeployable\ndeployed\ndeploying\ndeployment\ndeployments\ndeploys\ndeplume\ndeplumed\ndeplumes\ndepluming\ndepolarization\ndepolarizations\ndepolarize\ndepolarized\ndepolarizer\ndepolarizers\ndepolarizes\ndepolarizing\ndepolish\ndepolished\ndepolishes\ndepolishing\ndepoliticization\ndepoliticizations\ndepoliticize\ndepoliticized\ndepoliticizes\ndepoliticizing\ndepolymerization\ndepolymerizations\ndepolymerize\ndepolymerized\ndepolymerizes\ndepolymerizing\ndepone\ndeponed\ndeponent\ndeponents\ndepones\ndeponing\ndepopulate\ndepopulated\ndepopulates\ndepopulating\ndepopulation\ndepopulations\ndeport\ndeportable\ndeportation\ndeportations\ndeported\ndeportee\ndeportees\ndeporting\ndeportment\ndeportments\ndeports\ndeposal\ndeposals\ndepose\ndeposed\ndeposer\ndeposers\ndeposes\ndeposing\ndeposit\ndepositaries\ndepositary\ndeposited\ndepositing\ndeposition\ndepositional\ndepositions\ndepositor\ndepositories\ndepositors\ndepository\ndeposits\ndepot\ndepots\ndepravation\ndepravations\ndeprave\ndepraved\ndepravedly\ndepravedness\ndepravednesses\ndepravement\ndepravements\ndepraver\ndepravers\ndepraves\ndepraving\ndepravities\ndepravity\ndeprecate\ndeprecated\ndeprecates\ndeprecating\ndeprecatingly\ndeprecation\ndeprecations\ndeprecatorily\ndeprecatory\ndepreciable\ndepreciate\ndepreciated\ndepreciates\ndepreciating\ndepreciatingly\ndepreciation\ndepreciations\ndepreciative\ndepreciator\ndepreciators\ndepreciatory\ndepredate\ndepredated\ndepredates\ndepredating\ndepredation\ndepredations\ndepredator\ndepredators\ndepredatory\ndepress\ndepressant\ndepressants\ndepressed\ndepresses\ndepressible\ndepressing\ndepressingly\ndepression\ndepressions\ndepressive\ndepressively\ndepressives\ndepressor\ndepressors\ndepressurization\ndepressurizations\ndepressurize\ndepressurized\ndepressurizes\ndepressurizing\ndeprival\ndeprivals\ndeprivation\ndeprivations\ndeprive\ndeprived\ndepriver\ndeprivers\ndeprives\ndepriving\ndeprogram\ndeprogramed\ndeprograming\ndeprogrammed\ndeprogrammer\ndeprogrammers\ndeprogramming\ndeprograms\ndepside\ndepsides\ndepth\ndepthless\ndepths\ndepurate\ndepurated\ndepurates\ndepurating\ndeputation\ndeputations\ndepute\ndeputed\ndeputes\ndeputies\ndeputing\ndeputization\ndeputizations\ndeputize\ndeputized\ndeputizes\ndeputizing\ndeputy\nderacinate\nderacinated\nderacinates\nderacinating\nderacination\nderacinations\nderaign\nderaigned\nderaigning\nderaigns\nderail\nderailed\nderailing\nderailleur\nderailleurs\nderailment\nderailments\nderails\nderange\nderanged\nderangement\nderangements\nderanges\nderanging\nderat\nderate\nderated\nderates\nderating\nderats\nderatted\nderatting\nderay\nderays\nderbies\nderby\ndere\nderealization\nderealizations\nderegulate\nderegulated\nderegulates\nderegulating\nderegulation\nderegulations\nderelict\ndereliction\nderelictions\nderelicts\nderepress\nderepressed\nderepresses\nderepressing\nderepression\nderepressions\nderide\nderided\nderider\nderiders\nderides\nderiding\nderidingly\nderinger\nderingers\nderision\nderisions\nderisive\nderisively\nderisiveness\nderisivenesses\nderisory\nderivable\nderivate\nderivates\nderivation\nderivational\nderivations\nderivative\nderivatively\nderivativeness\nderivativenesses\nderivatives\nderivatization\nderivatizations\nderivatize\nderivatized\nderivatizes\nderivatizing\nderive\nderived\nderiver\nderivers\nderives\nderiving\nderm\nderma\ndermabrasion\ndermabrasions\ndermal\ndermas\ndermatitides\ndermatitis\ndermatitises\ndermatogen\ndermatogens\ndermatoglyphic\ndermatoglyphics\ndermatologic\ndermatological\ndermatologies\ndermatologist\ndermatologists\ndermatology\ndermatomal\ndermatome\ndermatomes\ndermatophyte\ndermatophytes\ndermatoses\ndermatosis\ndermestid\ndermestids\ndermic\ndermis\ndermises\ndermoid\ndermoids\nderms\ndernier\nderogate\nderogated\nderogates\nderogating\nderogation\nderogations\nderogative\nderogatively\nderogatorily\nderogatory\nderrick\nderricks\nderriere\nderrieres\nderries\nderringer\nderringers\nderris\nderrises\nderry\ndervish\ndervishes\ndesacralization\ndesacralizations\ndesacralize\ndesacralized\ndesacralizes\ndesacralizing\ndesalinate\ndesalinated\ndesalinates\ndesalinating\ndesalination\ndesalinations\ndesalinator\ndesalinators\ndesalinization\ndesalinizations\ndesalinize\ndesalinized\ndesalinizes\ndesalinizing\ndesalt\ndesalted\ndesalter\ndesalters\ndesalting\ndesalts\ndesand\ndesanded\ndesanding\ndesands\ndescant\ndescanted\ndescanting\ndescants\ndescend\ndescendant\ndescendants\ndescended\ndescendent\ndescendents\ndescender\ndescenders\ndescendible\ndescending\ndescends\ndescension\ndescensions\ndescent\ndescents\ndescramble\ndescrambled\ndescrambler\ndescramblers\ndescrambles\ndescrambling\ndescribable\ndescribe\ndescribed\ndescriber\ndescribers\ndescribes\ndescribing\ndescried\ndescrier\ndescriers\ndescries\ndescription\ndescriptions\ndescriptive\ndescriptively\ndescriptiveness\ndescriptivenesses\ndescriptor\ndescriptors\ndescry\ndescrying\ndesecrate\ndesecrated\ndesecrater\ndesecraters\ndesecrates\ndesecrating\ndesecration\ndesecrations\ndesecrator\ndesecrators\ndesegregate\ndesegregated\ndesegregates\ndesegregating\ndesegregation\ndesegregations\ndeselect\ndeselected\ndeselecting\ndeselects\ndesensitization\ndesensitizations\ndesensitize\ndesensitized\ndesensitizer\ndesensitizers\ndesensitizes\ndesensitizing\ndesert\ndeserted\ndeserter\ndeserters\ndesertic\ndesertification\ndesertifications\ndeserting\ndesertion\ndesertions\ndeserts\ndeserve\ndeserved\ndeservedly\ndeservedness\ndeservednesses\ndeserver\ndeservers\ndeserves\ndeserving\ndeservings\ndesex\ndesexed\ndesexes\ndesexing\ndesexualization\ndesexualizations\ndesexualize\ndesexualized\ndesexualizes\ndesexualizing\ndeshabille\ndeshabilles\ndesiccant\ndesiccants\ndesiccate\ndesiccated\ndesiccates\ndesiccating\ndesiccation\ndesiccations\ndesiccative\ndesiccator\ndesiccators\ndesiderata\ndesiderate\ndesiderated\ndesiderates\ndesiderating\ndesideration\ndesiderations\ndesiderative\ndesideratum\ndesign\ndesignate\ndesignated\ndesignates\ndesignating\ndesignation\ndesignations\ndesignative\ndesignator\ndesignators\ndesignatory\ndesigned\ndesignedly\ndesignee\ndesignees\ndesigner\ndesigners\ndesigning\ndesignment\ndesignments\ndesigns\ndesilver\ndesilvered\ndesilvering\ndesilvers\ndesinent\ndesipramine\ndesipramines\ndesirabilities\ndesirability\ndesirable\ndesirableness\ndesirablenesses\ndesirables\ndesirably\ndesire\ndesired\ndesirer\ndesirers\ndesires\ndesiring\ndesirous\ndesirously\ndesirousness\ndesirousnesses\ndesist\ndesistance\ndesistances\ndesisted\ndesisting\ndesists\ndesk\ndeskbound\ndeskman\ndeskmen\ndesks\ndesktop\ndesktops\ndesman\ndesmans\ndesmid\ndesmids\ndesmoid\ndesmoids\ndesmosomal\ndesmosome\ndesmosomes\ndesolate\ndesolated\ndesolately\ndesolateness\ndesolatenesses\ndesolater\ndesolaters\ndesolates\ndesolating\ndesolatingly\ndesolation\ndesolations\ndesolator\ndesolators\ndesorb\ndesorbed\ndesorbing\ndesorbs\ndesorption\ndesorptions\ndesoxy\ndespair\ndespaired\ndespairer\ndespairers\ndespairing\ndespairingly\ndespairs\ndespatch\ndespatched\ndespatches\ndespatching\ndesperado\ndesperadoes\ndesperados\ndesperate\ndesperately\ndesperateness\ndesperatenesses\ndesperation\ndesperations\ndespicable\ndespicableness\ndespicablenesses\ndespicably\ndespiritualize\ndespiritualized\ndespiritualizes\ndespiritualizing\ndespise\ndespised\ndespisement\ndespisements\ndespiser\ndespisers\ndespises\ndespising\ndespite\ndespited\ndespiteful\ndespitefully\ndespitefulness\ndespitefulnesses\ndespiteous\ndespiteously\ndespites\ndespiting\ndespoil\ndespoiled\ndespoiler\ndespoilers\ndespoiling\ndespoilment\ndespoilments\ndespoils\ndespoliation\ndespoliations\ndespond\ndesponded\ndespondence\ndespondences\ndespondencies\ndespondency\ndespondent\ndespondently\ndesponding\ndesponds\ndespot\ndespotic\ndespotically\ndespotism\ndespotisms\ndespots\ndesquamate\ndesquamated\ndesquamates\ndesquamating\ndesquamation\ndesquamations\ndessert\ndesserts\ndessertspoon\ndessertspoonful\ndessertspoonfuls\ndessertspoons\ndessertspoonsful\ndestabilization\ndestabilizations\ndestabilize\ndestabilized\ndestabilizes\ndestabilizing\ndestain\ndestained\ndestaining\ndestains\ndestination\ndestinations\ndestine\ndestined\ndestines\ndestinies\ndestining\ndestiny\ndestitute\ndestituteness\ndestitutenesses\ndestitution\ndestitutions\ndestrier\ndestriers\ndestroy\ndestroyed\ndestroyer\ndestroyers\ndestroying\ndestroys\ndestruct\ndestructed\ndestructibilities\ndestructibility\ndestructible\ndestructing\ndestruction\ndestructionist\ndestructionists\ndestructions\ndestructive\ndestructively\ndestructiveness\ndestructivenesses\ndestructivities\ndestructivity\ndestructs\ndesuetude\ndesuetudes\ndesugar\ndesugared\ndesugaring\ndesugars\ndesulfur\ndesulfured\ndesulfuring\ndesulfurization\ndesulfurizations\ndesulfurize\ndesulfurized\ndesulfurizes\ndesulfurizing\ndesulfurs\ndesultorily\ndesultoriness\ndesultorinesses\ndesultory\ndetach\ndetachabilities\ndetachability\ndetachable\ndetachably\ndetached\ndetachedly\ndetachedness\ndetachednesses\ndetacher\ndetachers\ndetaches\ndetaching\ndetachment\ndetachments\ndetail\ndetailed\ndetailedly\ndetailedness\ndetailednesses\ndetailer\ndetailers\ndetailing\ndetails\ndetain\ndetained\ndetainee\ndetainees\ndetainer\ndetainers\ndetaining\ndetainment\ndetainments\ndetains\ndetassel\ndetasseled\ndetasseling\ndetasselled\ndetasselling\ndetassels\ndetect\ndetectabilities\ndetectability\ndetectable\ndetected\ndetecter\ndetecters\ndetecting\ndetection\ndetections\ndetective\ndetectivelike\ndetectives\ndetector\ndetectors\ndetects\ndetent\ndetente\ndetentes\ndetention\ndetentions\ndetents\ndeter\ndeterge\ndeterged\ndetergencies\ndetergency\ndetergent\ndetergents\ndeterger\ndetergers\ndeterges\ndeterging\ndeteriorate\ndeteriorated\ndeteriorates\ndeteriorating\ndeterioration\ndeteriorations\ndeteriorative\ndeterment\ndeterments\ndeterminable\ndeterminableness\ndeterminablenesses\ndeterminably\ndeterminacies\ndeterminacy\ndeterminant\ndeterminantal\ndeterminants\ndeterminate\ndeterminately\ndeterminateness\ndeterminatenesses\ndetermination\ndeterminations\ndeterminative\ndeterminatives\ndeterminator\ndeterminators\ndetermine\ndetermined\ndeterminedly\ndeterminedness\ndeterminednesses\ndeterminer\ndeterminers\ndetermines\ndetermining\ndeterminism\ndeterminisms\ndeterminist\ndeterministic\ndeterministically\ndeterminists\ndeterrabilities\ndeterrability\ndeterrable\ndeterred\ndeterrence\ndeterrences\ndeterrent\ndeterrently\ndeterrents\ndeterrer\ndeterrers\ndeterring\ndeters\ndetersive\ndetersives\ndetest\ndetestable\ndetestableness\ndetestablenesses\ndetestably\ndetestation\ndetestations\ndetested\ndetester\ndetesters\ndetesting\ndetests\ndethrone\ndethroned\ndethronement\ndethronements\ndethroner\ndethroners\ndethrones\ndethroning\ndetick\ndeticked\ndeticker\ndetickers\ndeticking\ndeticks\ndetinue\ndetinues\ndetonabilities\ndetonability\ndetonable\ndetonatable\ndetonate\ndetonated\ndetonates\ndetonating\ndetonation\ndetonations\ndetonative\ndetonator\ndetonators\ndetour\ndetoured\ndetouring\ndetours\ndetox\ndetoxed\ndetoxes\ndetoxicant\ndetoxicants\ndetoxicate\ndetoxicated\ndetoxicates\ndetoxicating\ndetoxication\ndetoxications\ndetoxification\ndetoxifications\ndetoxified\ndetoxifies\ndetoxify\ndetoxifying\ndetoxing\ndetract\ndetracted\ndetracting\ndetraction\ndetractions\ndetractive\ndetractively\ndetractor\ndetractors\ndetracts\ndetrain\ndetrained\ndetraining\ndetrainment\ndetrainments\ndetrains\ndetribalization\ndetribalizations\ndetribalize\ndetribalized\ndetribalizes\ndetribalizing\ndetriment\ndetrimental\ndetrimentally\ndetrimentals\ndetriments\ndetrital\ndetrition\ndetritions\ndetritus\ndetrude\ndetruded\ndetrudes\ndetruding\ndetumescence\ndetumescences\ndetumescent\ndeuce\ndeuced\ndeucedly\ndeuces\ndeucing\ndeuteragonist\ndeuteragonists\ndeuteranomalies\ndeuteranomalous\ndeuteranomaly\ndeuteranope\ndeuteranopes\ndeuteranopia\ndeuteranopias\ndeuteranopic\ndeuterate\ndeuterated\ndeuterates\ndeuterating\ndeuteration\ndeuterations\ndeuteric\ndeuterium\ndeuteriums\ndeuterocanonical\ndeuteron\ndeuterons\ndeuterostome\ndeuterostomes\ndeutoplasm\ndeutoplasms\ndeutzia\ndeutzias\ndev\ndeva\ndevaluate\ndevaluated\ndevaluates\ndevaluating\ndevaluation\ndevaluations\ndevalue\ndevalued\ndevalues\ndevaluing\ndevas\ndevastate\ndevastated\ndevastates\ndevastating\ndevastatingly\ndevastation\ndevastations\ndevastative\ndevastator\ndevastators\ndevein\ndeveined\ndeveining\ndeveins\ndevel\ndeveled\ndeveling\ndevelop\ndevelopable\ndevelope\ndeveloped\ndeveloper\ndevelopers\ndevelopes\ndeveloping\ndevelopment\ndevelopmental\ndevelopmentally\ndevelopments\ndevelops\ndevels\ndeverbal\ndeverbative\ndeverbatives\ndevest\ndevested\ndevesting\ndevests\ndeviance\ndeviances\ndeviancies\ndeviancy\ndeviant\ndeviants\ndeviate\ndeviated\ndeviates\ndeviating\ndeviation\ndeviationism\ndeviationisms\ndeviationist\ndeviationists\ndeviations\ndeviator\ndeviators\ndeviatory\ndevice\ndevices\ndevil\ndeviled\ndevilfish\ndevilfishes\ndeviling\ndevilish\ndevilishly\ndevilishness\ndevilishnesses\ndevilkin\ndevilkins\ndevilled\ndevilling\ndevilment\ndevilments\ndevilries\ndevilry\ndevils\ndeviltries\ndeviltry\ndevilwood\ndevilwoods\ndevious\ndeviously\ndeviousness\ndeviousnesses\ndevisable\ndevisal\ndevisals\ndevise\ndevised\ndevisee\ndevisees\ndeviser\ndevisers\ndevises\ndevising\ndevisor\ndevisors\ndevitalize\ndevitalized\ndevitalizes\ndevitalizing\ndevitrification\ndevitrifications\ndevitrified\ndevitrifies\ndevitrify\ndevitrifying\ndevocalize\ndevocalized\ndevocalizes\ndevocalizing\ndevoice\ndevoiced\ndevoices\ndevoicing\ndevoid\ndevoir\ndevoirs\ndevolution\ndevolutionary\ndevolutionist\ndevolutionists\ndevolutions\ndevolve\ndevolved\ndevolves\ndevolving\ndevon\ndevons\ndevote\ndevoted\ndevotedly\ndevotedness\ndevotednesses\ndevotee\ndevotees\ndevotement\ndevotements\ndevotes\ndevoting\ndevotion\ndevotional\ndevotionally\ndevotionals\ndevotions\ndevour\ndevoured\ndevourer\ndevourers\ndevouring\ndevours\ndevout\ndevouter\ndevoutest\ndevoutly\ndevoutness\ndevoutnesses\ndevs\ndew\ndewan\ndewans\ndewar\ndewars\ndewater\ndewatered\ndewaterer\ndewaterers\ndewatering\ndewaters\ndewax\ndewaxed\ndewaxes\ndewaxing\ndewberries\ndewberry\ndewclaw\ndewclaws\ndewdrop\ndewdrops\ndewed\ndewfall\ndewfalls\ndewier\ndewiest\ndewily\ndewiness\ndewinesses\ndewing\ndewlap\ndewlapped\ndewlaps\ndewless\ndewool\ndewooled\ndewooling\ndewools\ndeworm\ndewormed\ndewormer\ndewormers\ndeworming\ndeworms\ndews\ndewy\ndex\ndexamethasone\ndexamethasones\ndexes\ndexie\ndexies\ndexter\ndexterities\ndexterity\ndexterous\ndexterously\ndexterousness\ndexterousnesses\ndextral\ndextran\ndextranase\ndextranases\ndextrans\ndextrin\ndextrine\ndextrines\ndextrins\ndextro\ndextroamphetamine\ndextroamphetamines\ndextrorotary\ndextrorotatory\ndextrose\ndextroses\ndextrous\ndexy\ndey\ndeys\ndezinc\ndezinced\ndezincing\ndezincked\ndezincking\ndezincs\ndhak\ndhaks\ndhal\ndhals\ndharma\ndharmas\ndharmic\ndharna\ndharnas\ndhobi\ndhobis\ndhole\ndholes\ndhoolies\ndhooly\ndhoora\ndhooras\ndhooti\ndhootie\ndhooties\ndhootis\ndhoti\ndhotis\ndhourra\ndhourras\ndhow\ndhows\ndhurna\ndhurnas\ndhurrie\ndhurries\ndhuti\ndhutis\ndiabase\ndiabases\ndiabasic\ndiabetes\ndiabetic\ndiabetics\ndiabetogenic\ndiabetologist\ndiabetologists\ndiablerie\ndiableries\ndiablery\ndiabolic\ndiabolical\ndiabolically\ndiabolicalness\ndiabolicalnesses\ndiabolism\ndiabolisms\ndiabolist\ndiabolists\ndiabolize\ndiabolized\ndiabolizes\ndiabolizing\ndiabolo\ndiabolos\ndiacetyl\ndiacetyls\ndiachronic\ndiachronically\ndiachronies\ndiachrony\ndiacid\ndiacidic\ndiacids\ndiaconal\ndiaconate\ndiaconates\ndiacritic\ndiacritical\ndiacritics\ndiadelphous\ndiadem\ndiademed\ndiademing\ndiadems\ndiadromous\ndiaereses\ndiaeresis\ndiaeretic\ndiageneses\ndiagenesis\ndiagenetic\ndiagenetically\ndiageotropic\ndiagnosable\ndiagnose\ndiagnoseable\ndiagnosed\ndiagnoses\ndiagnosing\ndiagnosis\ndiagnostic\ndiagnostical\ndiagnostically\ndiagnostician\ndiagnosticians\ndiagnostics\ndiagonal\ndiagonalizable\ndiagonalization\ndiagonalizations\ndiagonalize\ndiagonalized\ndiagonalizes\ndiagonalizing\ndiagonally\ndiagonals\ndiagram\ndiagramed\ndiagraming\ndiagrammable\ndiagrammatic\ndiagrammatical\ndiagrammatically\ndiagrammed\ndiagramming\ndiagrams\ndiagraph\ndiagraphs\ndiakineses\ndiakinesis\ndial\ndialect\ndialectal\ndialectally\ndialectic\ndialectical\ndialectically\ndialectician\ndialecticians\ndialectics\ndialectological\ndialectologically\ndialectologies\ndialectologist\ndialectologists\ndialectology\ndialects\ndialed\ndialer\ndialers\ndialing\ndialings\ndialist\ndialists\ndiallage\ndiallages\ndialled\ndiallel\ndialler\ndiallers\ndialling\ndiallings\ndiallist\ndiallists\ndialog\ndialoged\ndialoger\ndialogers\ndialogic\ndialogical\ndialogically\ndialoging\ndialogist\ndialogistic\ndialogists\ndialogs\ndialogue\ndialogued\ndialogues\ndialoguing\ndials\ndialysate\ndialysates\ndialyse\ndialysed\ndialyser\ndialysers\ndialyses\ndialysing\ndialysis\ndialytic\ndialyzable\ndialyzate\ndialyzates\ndialyze\ndialyzed\ndialyzer\ndialyzers\ndialyzes\ndialyzing\ndiamagnetic\ndiamagnetism\ndiamagnetisms\ndiamante\ndiamantes\ndiameter\ndiameters\ndiametral\ndiametric\ndiametrical\ndiametrically\ndiamide\ndiamides\ndiamin\ndiamine\ndiamines\ndiamins\ndiamond\ndiamondback\ndiamondbacks\ndiamonded\ndiamondiferous\ndiamonding\ndiamonds\ndianthus\ndianthuses\ndiapason\ndiapasons\ndiapause\ndiapaused\ndiapauses\ndiapausing\ndiapedeses\ndiapedesis\ndiaper\ndiapered\ndiapering\ndiapers\ndiaphaneities\ndiaphaneity\ndiaphanous\ndiaphanously\ndiaphanousness\ndiaphanousnesses\ndiaphone\ndiaphones\ndiaphonies\ndiaphony\ndiaphorase\ndiaphorases\ndiaphoreses\ndiaphoresis\ndiaphoretic\ndiaphoretics\ndiaphragm\ndiaphragmatic\ndiaphragmatically\ndiaphragms\ndiaphyseal\ndiaphyses\ndiaphysial\ndiaphysis\ndiapir\ndiapiric\ndiapirs\ndiapositive\ndiapositives\ndiapsid\ndiarchic\ndiarchies\ndiarchy\ndiaries\ndiarist\ndiarists\ndiarrhea\ndiarrheal\ndiarrheas\ndiarrheic\ndiarrhetic\ndiarrhoea\ndiarrhoeas\ndiarthroses\ndiarthrosis\ndiary\ndiaspora\ndiasporas\ndiaspore\ndiaspores\ndiastase\ndiastases\ndiastatic\ndiastem\ndiastema\ndiastemata\ndiastems\ndiaster\ndiastereoisomer\ndiastereoisomeric\ndiastereoisomerism\ndiastereoisomerisms\ndiastereoisomers\ndiastereomer\ndiastereomeric\ndiastereomers\ndiasters\ndiastole\ndiastoles\ndiastolic\ndiastral\ndiastrophic\ndiastrophically\ndiastrophism\ndiastrophisms\ndiatessaron\ndiatessarons\ndiathermanous\ndiathermic\ndiathermies\ndiathermy\ndiatheses\ndiathesis\ndiathetic\ndiatom\ndiatomaceous\ndiatomic\ndiatomite\ndiatomites\ndiatoms\ndiatonic\ndiatonically\ndiatribe\ndiatribes\ndiatron\ndiatrons\ndiazepam\ndiazepams\ndiazin\ndiazine\ndiazines\ndiazinon\ndiazinons\ndiazins\ndiazo\ndiazole\ndiazoles\ndiazonium\ndiazoniums\ndiazotization\ndiazotizations\ndiazotize\ndiazotized\ndiazotizes\ndiazotizing\ndib\ndibasic\ndibbed\ndibber\ndibbers\ndibbing\ndibble\ndibbled\ndibbler\ndibblers\ndibbles\ndibbling\ndibbuk\ndibbukim\ndibbuks\ndibenzofuran\ndibenzofurans\ndibs\ndicarboxylic\ndicast\ndicastic\ndicasts\ndice\ndiced\ndicentra\ndicentras\ndicentric\ndicentrics\ndicer\ndicers\ndices\ndicey\ndichasia\ndichasium\ndichlorobenzene\ndichlorobenzenes\ndichlorodifluoromethane\ndichlorodifluoromethanes\ndichloroethane\ndichloroethanes\ndichlorvos\ndichlorvoses\ndichogamies\ndichogamous\ndichogamy\ndichondra\ndichondras\ndichotic\ndichotically\ndichotomies\ndichotomist\ndichotomists\ndichotomization\ndichotomizations\ndichotomize\ndichotomized\ndichotomizes\ndichotomizing\ndichotomous\ndichotomously\ndichotomousness\ndichotomousnesses\ndichotomy\ndichroic\ndichroism\ndichroisms\ndichromat\ndichromate\ndichromates\ndichromatic\ndichromatism\ndichromatisms\ndichromats\ndichroscope\ndichroscopes\ndicier\ndiciest\ndicing\ndick\ndickcissel\ndickcissels\ndicked\ndickens\ndickenses\ndicker\ndickered\ndickering\ndickers\ndickey\ndickeys\ndickie\ndickier\ndickies\ndickiest\ndicking\ndicks\ndicky\ndickys\ndiclinies\ndiclinous\ndicliny\ndicot\ndicots\ndicotyl\ndicotyledon\ndicotyledonous\ndicotyledons\ndicotyls\ndicoumarin\ndicoumarins\ndicoumarol\ndicoumarols\ndicrotal\ndicrotic\ndicrotism\ndicrotisms\ndicta\ndictate\ndictated\ndictates\ndictating\ndictation\ndictations\ndictator\ndictatorial\ndictatorially\ndictatorialness\ndictatorialnesses\ndictators\ndictatorship\ndictatorships\ndictier\ndictiest\ndiction\ndictional\ndictionally\ndictionaries\ndictionary\ndictions\ndictum\ndictums\ndicty\ndictyosome\ndictyosomes\ndictyostele\ndictyosteles\ndicumarol\ndicumarols\ndicyclic\ndicyclies\ndicycly\ndicynodont\ndicynodonts\ndid\ndidact\ndidactic\ndidactical\ndidactically\ndidacticism\ndidacticisms\ndidactics\ndidacts\ndidactyl\ndidapper\ndidappers\ndiddle\ndiddled\ndiddler\ndiddlers\ndiddles\ndiddley\ndiddleys\ndiddlies\ndiddling\ndiddly\ndiddlysquat\ndidgeridoo\ndidgeridoos\ndidie\ndidies\ndidjeridoo\ndidjeridoos\ndido\ndidoes\ndidos\ndidst\ndidy\ndidymium\ndidymiums\ndidymous\ndidynamies\ndidynamy\ndie\ndieback\ndiebacks\ndiecious\ndied\ndieffenbachia\ndieffenbachias\ndiehard\ndiehards\ndieing\ndiel\ndieldrin\ndieldrins\ndielectric\ndielectrics\ndiemaker\ndiemakers\ndiencephala\ndiencephalic\ndiencephalon\ndiencephalons\ndiene\ndienes\ndiereses\ndieresis\ndieretic\ndies\ndiesel\ndieseled\ndieseling\ndieselings\ndieselization\ndieselizations\ndieselize\ndieselized\ndieselizes\ndieselizing\ndiesels\ndieses\ndiesis\ndiester\ndiesters\ndiestock\ndiestocks\ndiestrous\ndiestrum\ndiestrums\ndiestrus\ndiestruses\ndiet\ndietaries\ndietarily\ndietary\ndieted\ndieter\ndieters\ndietetic\ndietetically\ndietetics\ndiether\ndiethers\ndiethylcarbamazine\ndiethylcarbamazines\ndiethylstilbestrol\ndiethylstilbestrols\ndietician\ndieticians\ndieting\ndietitian\ndietitians\ndiets\ndiffer\ndiffered\ndifference\ndifferenced\ndifferences\ndifferencing\ndifferent\ndifferentia\ndifferentiabilities\ndifferentiability\ndifferentiable\ndifferentiae\ndifferential\ndifferentially\ndifferentials\ndifferentiate\ndifferentiated\ndifferentiates\ndifferentiating\ndifferentiation\ndifferentiations\ndifferently\ndifferentness\ndifferentnesses\ndiffering\ndiffers\ndifficile\ndifficult\ndifficulties\ndifficultly\ndifficulty\ndiffidence\ndiffidences\ndiffident\ndiffidently\ndiffract\ndiffracted\ndiffracting\ndiffraction\ndiffractions\ndiffractometer\ndiffractometers\ndiffractometric\ndiffractometries\ndiffractometry\ndiffracts\ndiffuse\ndiffused\ndiffusely\ndiffuseness\ndiffusenesses\ndiffuser\ndiffusers\ndiffuses\ndiffusible\ndiffusing\ndiffusion\ndiffusional\ndiffusionism\ndiffusionisms\ndiffusionist\ndiffusionists\ndiffusions\ndiffusive\ndiffusively\ndiffusiveness\ndiffusivenesses\ndiffusivities\ndiffusivity\ndiffusor\ndiffusors\ndifunctional\ndig\ndigamies\ndigamist\ndigamists\ndigamma\ndigammas\ndigamous\ndigamy\ndigastric\ndigenetic\ndigest\ndigested\ndigester\ndigesters\ndigestibilities\ndigestibility\ndigestible\ndigesting\ndigestion\ndigestions\ndigestive\ndigestively\ndigestives\ndigestor\ndigestors\ndigests\ndigged\ndigger\ndiggers\ndigging\ndiggings\ndight\ndighted\ndighting\ndights\ndigit\ndigital\ndigitalin\ndigitalins\ndigitalis\ndigitalises\ndigitalization\ndigitalizations\ndigitalize\ndigitalized\ndigitalizes\ndigitalizing\ndigitally\ndigitals\ndigitate\ndigitately\ndigitigrade\ndigitization\ndigitizations\ndigitize\ndigitized\ndigitizer\ndigitizers\ndigitizes\ndigitizing\ndigitonin\ndigitonins\ndigitoxigenin\ndigitoxigenins\ndigitoxin\ndigitoxins\ndigits\ndiglot\ndiglots\ndiglyceride\ndiglycerides\ndignified\ndignifies\ndignify\ndignifying\ndignitaries\ndignitary\ndignities\ndignity\ndigoxin\ndigoxins\ndigraph\ndigraphic\ndigraphically\ndigraphs\ndigress\ndigressed\ndigresses\ndigressing\ndigression\ndigressional\ndigressionary\ndigressions\ndigressive\ndigressively\ndigressiveness\ndigressivenesses\ndigs\ndihedral\ndihedrals\ndihedron\ndihedrons\ndihybrid\ndihybrids\ndihydric\ndihydroergotamine\ndihydroergotamines\ndihydroxyacetone\ndihydroxyacetones\ndikdik\ndikdiks\ndike\ndiked\ndiker\ndikers\ndikes\ndikey\ndiking\ndiktat\ndiktats\ndilapidate\ndilapidated\ndilapidates\ndilapidating\ndilapidation\ndilapidations\ndilatabilities\ndilatability\ndilatable\ndilatancies\ndilatancy\ndilatant\ndilatants\ndilatate\ndilatation\ndilatational\ndilatations\ndilate\ndilated\ndilater\ndilaters\ndilates\ndilating\ndilation\ndilations\ndilative\ndilatometer\ndilatometers\ndilatometric\ndilatometries\ndilatometry\ndilator\ndilatorily\ndilatoriness\ndilatorinesses\ndilators\ndilatory\ndildo\ndildoe\ndildoes\ndildos\ndilemma\ndilemmas\ndilemmatic\ndilemmic\ndilettante\ndilettantes\ndilettanti\ndilettantish\ndilettantism\ndilettantisms\ndiligence\ndiligences\ndiligent\ndiligently\ndill\ndilled\ndillies\ndills\ndilly\ndillydallied\ndillydallies\ndillydally\ndillydallying\ndiluent\ndiluents\ndilute\ndiluted\ndiluteness\ndilutenesses\ndiluter\ndiluters\ndilutes\ndiluting\ndilution\ndilutions\ndilutive\ndilutor\ndilutors\ndiluvia\ndiluvial\ndiluvian\ndiluvion\ndiluvions\ndiluvium\ndiluviums\ndim\ndime\ndimenhydrinate\ndimenhydrinates\ndimension\ndimensional\ndimensionalities\ndimensionality\ndimensionally\ndimensioned\ndimensioning\ndimensionless\ndimensions\ndimer\ndimercaprol\ndimercaprols\ndimeric\ndimerism\ndimerisms\ndimerization\ndimerizations\ndimerize\ndimerized\ndimerizes\ndimerizing\ndimerous\ndimers\ndimes\ndimeter\ndimeters\ndimethoate\ndimethoates\ndimethyl\ndimethylhydrazine\ndimethylhydrazines\ndimethylnitrosamine\ndimethylnitrosamines\ndimethyls\ndimethyltryptamine\ndimethyltryptamines\ndimetric\ndiminish\ndiminishable\ndiminished\ndiminishes\ndiminishing\ndiminishment\ndiminishments\ndiminuendo\ndiminuendos\ndiminution\ndiminutions\ndiminutive\ndiminutively\ndiminutiveness\ndiminutivenesses\ndiminutives\ndimities\ndimity\ndimly\ndimmable\ndimmed\ndimmer\ndimmers\ndimmest\ndimming\ndimness\ndimnesses\ndimorph\ndimorphic\ndimorphism\ndimorphisms\ndimorphous\ndimorphs\ndimout\ndimouts\ndimple\ndimpled\ndimples\ndimplier\ndimpliest\ndimpling\ndimply\ndims\ndimwit\ndimwits\ndimwitted\ndin\ndinar\ndinars\ndindle\ndindled\ndindles\ndindling\ndine\ndined\ndiner\ndineric\ndinero\ndineros\ndiners\ndines\ndinette\ndinettes\nding\ndingbat\ndingbats\ndingdong\ndingdonged\ndingdonging\ndingdongs\ndinge\ndinged\ndinger\ndingers\ndinges\ndingey\ndingeys\ndinghies\ndinghy\ndingier\ndingies\ndingiest\ndingily\ndinginess\ndinginesses\ndinging\ndingle\ndingleberries\ndingleberry\ndingles\ndingo\ndingoes\ndings\ndingus\ndinguses\ndingy\ndining\ndinitro\ndinitrobenzene\ndinitrobenzenes\ndinitrophenol\ndinitrophenols\ndink\ndinked\ndinkey\ndinkeys\ndinkier\ndinkies\ndinkiest\ndinking\ndinkly\ndinks\ndinkum\ndinkums\ndinky\ndinned\ndinner\ndinnerless\ndinners\ndinnertime\ndinnertimes\ndinnerware\ndinnerwares\ndinning\ndinoflagellate\ndinoflagellates\ndinosaur\ndinosaurian\ndinosaurs\ndins\ndint\ndinted\ndinting\ndints\ndinucleotide\ndinucleotides\ndiobol\ndiobolon\ndiobolons\ndiobols\ndiocesan\ndiocesans\ndiocese\ndioceses\ndiode\ndiodes\ndioecies\ndioecious\ndioecism\ndioecisms\ndioecy\ndioicous\ndiol\ndiolefin\ndiolefins\ndiols\ndiopside\ndiopsides\ndiopsidic\ndioptase\ndioptases\ndiopter\ndiopters\ndioptral\ndioptre\ndioptres\ndioptric\ndiorama\ndioramas\ndioramic\ndiorite\ndiorites\ndioritic\ndioxan\ndioxane\ndioxanes\ndioxans\ndioxid\ndioxide\ndioxides\ndioxids\ndioxin\ndioxins\ndip\ndipeptidase\ndipeptidases\ndipeptide\ndipeptides\ndiphase\ndiphasic\ndiphenhydramine\ndiphenhydramines\ndiphenyl\ndiphenylamine\ndiphenylamines\ndiphenylhydantoin\ndiphenylhydantoins\ndiphenyls\ndiphosgene\ndiphosgenes\ndiphosphate\ndiphosphates\ndiphtheria\ndiphtherial\ndiphtherias\ndiphtheritic\ndiphtheroid\ndiphtheroids\ndiphthong\ndiphthongal\ndiphthongization\ndiphthongizations\ndiphthongize\ndiphthongized\ndiphthongizes\ndiphthongizing\ndiphthongs\ndiphyletic\ndiphyodont\ndiplegia\ndiplegias\ndiplex\ndiplexer\ndiplexers\ndiploblastic\ndiplococci\ndiplococcus\ndiplodocus\ndiplodocuses\ndiploe\ndiploes\ndiploic\ndiploid\ndiploidies\ndiploids\ndiploidy\ndiploma\ndiplomacies\ndiplomacy\ndiplomaed\ndiplomaing\ndiplomas\ndiplomat\ndiplomata\ndiplomate\ndiplomates\ndiplomatic\ndiplomatically\ndiplomatist\ndiplomatists\ndiplomats\ndiplont\ndiplontic\ndiplonts\ndiplophase\ndiplophases\ndiplopia\ndiplopias\ndiplopic\ndiplopod\ndiplopods\ndiploses\ndiplosis\ndiplotene\ndiplotenes\ndipnet\ndipnets\ndipnetted\ndipnetting\ndipnoan\ndipnoans\ndipodic\ndipodies\ndipody\ndipolar\ndipole\ndipoles\ndippable\ndipped\ndipper\ndipperful\ndipperfuls\ndippers\ndippier\ndippiest\ndipping\ndippy\ndips\ndipsades\ndipsas\ndipso\ndipsomania\ndipsomaniac\ndipsomaniacal\ndipsomaniacs\ndipsomanias\ndipsos\ndipstick\ndipsticks\ndipt\ndiptera\ndipteral\ndipteran\ndipterans\ndipterocarp\ndipterocarps\ndipteron\ndipterous\ndiptyca\ndiptycas\ndiptych\ndiptychs\ndiquat\ndiquats\ndirdum\ndirdums\ndire\ndirect\ndirected\ndirectedness\ndirectednesses\ndirecter\ndirectest\ndirecting\ndirection\ndirectional\ndirectionalities\ndirectionality\ndirectionless\ndirectionlessness\ndirectionlessnesses\ndirections\ndirective\ndirectives\ndirectivities\ndirectivity\ndirectly\ndirectness\ndirectnesses\ndirector\ndirectorate\ndirectorates\ndirectorial\ndirectories\ndirectors\ndirectorship\ndirectorships\ndirectory\ndirectress\ndirectresses\ndirectrice\ndirectrices\ndirectrix\ndirectrixes\ndirects\ndireful\ndirefully\ndirely\ndireness\ndirenesses\ndirer\ndirest\ndirge\ndirgeful\ndirgelike\ndirges\ndirham\ndirhams\ndirigible\ndirigibles\ndirigisme\ndirigismes\ndirigiste\ndiriment\ndirk\ndirked\ndirking\ndirks\ndirl\ndirled\ndirling\ndirls\ndirndl\ndirndls\ndirt\ndirtbag\ndirtbags\ndirtied\ndirtier\ndirties\ndirtiest\ndirtily\ndirtiness\ndirtinesses\ndirts\ndirty\ndirtying\ndis\ndisabilities\ndisability\ndisable\ndisabled\ndisablement\ndisablements\ndisables\ndisabling\ndisabuse\ndisabused\ndisabuses\ndisabusing\ndisaccharidase\ndisaccharidases\ndisaccharide\ndisaccharides\ndisaccord\ndisaccorded\ndisaccording\ndisaccords\ndisaccustom\ndisaccustomed\ndisaccustoming\ndisaccustoms\ndisadvantage\ndisadvantaged\ndisadvantagedness\ndisadvantagednesses\ndisadvantageous\ndisadvantageously\ndisadvantageousness\ndisadvantageousnesses\ndisadvantages\ndisadvantaging\ndisaffect\ndisaffected\ndisaffecting\ndisaffection\ndisaffections\ndisaffects\ndisaffiliate\ndisaffiliated\ndisaffiliates\ndisaffiliating\ndisaffiliation\ndisaffiliations\ndisaffirm\ndisaffirmance\ndisaffirmances\ndisaffirmed\ndisaffirming\ndisaffirms\ndisaggregate\ndisaggregated\ndisaggregates\ndisaggregating\ndisaggregation\ndisaggregations\ndisaggregative\ndisagree\ndisagreeable\ndisagreeableness\ndisagreeablenesses\ndisagreeably\ndisagreed\ndisagreeing\ndisagreement\ndisagreements\ndisagrees\ndisallow\ndisallowance\ndisallowances\ndisallowed\ndisallowing\ndisallows\ndisambiguate\ndisambiguated\ndisambiguates\ndisambiguating\ndisambiguation\ndisambiguations\ndisannul\ndisannulled\ndisannulling\ndisannuls\ndisappear\ndisappearance\ndisappearances\ndisappeared\ndisappearing\ndisappears\ndisappoint\ndisappointed\ndisappointedly\ndisappointing\ndisappointingly\ndisappointment\ndisappointments\ndisappoints\ndisapprobation\ndisapprobations\ndisapproval\ndisapprovals\ndisapprove\ndisapproved\ndisapprover\ndisapprovers\ndisapproves\ndisapproving\ndisapprovingly\ndisarm\ndisarmament\ndisarmaments\ndisarmed\ndisarmer\ndisarmers\ndisarming\ndisarmingly\ndisarms\ndisarrange\ndisarranged\ndisarrangement\ndisarrangements\ndisarranges\ndisarranging\ndisarray\ndisarrayed\ndisarraying\ndisarrays\ndisarticulate\ndisarticulated\ndisarticulates\ndisarticulating\ndisarticulation\ndisarticulations\ndisassemble\ndisassembled\ndisassembles\ndisassemblies\ndisassembling\ndisassembly\ndisassociate\ndisassociated\ndisassociates\ndisassociating\ndisassociation\ndisassociations\ndisaster\ndisasters\ndisastrous\ndisastrously\ndisavow\ndisavowable\ndisavowal\ndisavowals\ndisavowed\ndisavowing\ndisavows\ndisband\ndisbanded\ndisbanding\ndisbandment\ndisbandments\ndisbands\ndisbar\ndisbarment\ndisbarments\ndisbarred\ndisbarring\ndisbars\ndisbelief\ndisbeliefs\ndisbelieve\ndisbelieved\ndisbeliever\ndisbelievers\ndisbelieves\ndisbelieving\ndisbenefit\ndisbenefits\ndisbosom\ndisbosomed\ndisbosoming\ndisbosoms\ndisbound\ndisbowel\ndisboweled\ndisboweling\ndisbowelled\ndisbowelling\ndisbowels\ndisbud\ndisbudded\ndisbudding\ndisbuds\ndisburden\ndisburdened\ndisburdening\ndisburdenment\ndisburdenments\ndisburdens\ndisburse\ndisbursed\ndisbursement\ndisbursements\ndisburser\ndisbursers\ndisburses\ndisbursing\ndisc\ndiscalced\ndiscant\ndiscanted\ndiscanting\ndiscants\ndiscard\ndiscardable\ndiscarded\ndiscarder\ndiscarders\ndiscarding\ndiscards\ndiscarnate\ndiscase\ndiscased\ndiscases\ndiscasing\ndisced\ndiscept\ndiscepted\ndiscepting\ndiscepts\ndiscern\ndiscernable\ndiscerned\ndiscerner\ndiscerners\ndiscernible\ndiscernibly\ndiscerning\ndiscerningly\ndiscernment\ndiscernments\ndiscerns\ndischarge\ndischargeable\ndischarged\ndischargee\ndischargees\ndischarger\ndischargers\ndischarges\ndischarging\ndisci\ndisciform\ndiscing\ndisciple\ndiscipled\ndisciples\ndiscipleship\ndiscipleships\ndisciplinable\ndisciplinal\ndisciplinarian\ndisciplinarians\ndisciplinarily\ndisciplinarities\ndisciplinarity\ndisciplinary\ndiscipline\ndisciplined\ndiscipliner\ndiscipliners\ndisciplines\ndiscipling\ndisciplining\ndisclaim\ndisclaimed\ndisclaimer\ndisclaimers\ndisclaiming\ndisclaims\ndisclamation\ndisclamations\ndisclike\ndisclimax\ndisclimaxes\ndisclose\ndisclosed\ndiscloser\ndisclosers\ndiscloses\ndisclosing\ndisclosure\ndisclosures\ndisco\ndiscoed\ndiscographer\ndiscographers\ndiscographic\ndiscographical\ndiscographies\ndiscography\ndiscoid\ndiscoidal\ndiscoids\ndiscoing\ndiscolor\ndiscoloration\ndiscolorations\ndiscolored\ndiscoloring\ndiscolors\ndiscombobulate\ndiscombobulated\ndiscombobulates\ndiscombobulating\ndiscombobulation\ndiscombobulations\ndiscomfit\ndiscomfited\ndiscomfiting\ndiscomfits\ndiscomfiture\ndiscomfitures\ndiscomfort\ndiscomfortable\ndiscomforted\ndiscomforting\ndiscomforts\ndiscommend\ndiscommended\ndiscommending\ndiscommends\ndiscommode\ndiscommoded\ndiscommodes\ndiscommoding\ndiscompose\ndiscomposed\ndiscomposes\ndiscomposing\ndiscomposure\ndiscomposures\ndisconcert\ndisconcerted\ndisconcerting\ndisconcertingly\ndisconcertment\ndisconcertments\ndisconcerts\ndisconfirm\ndisconfirmed\ndisconfirming\ndisconfirms\ndisconformities\ndisconformity\ndisconnect\ndisconnected\ndisconnectedly\ndisconnectedness\ndisconnectednesses\ndisconnecting\ndisconnection\ndisconnections\ndisconnects\ndisconsolate\ndisconsolately\ndisconsolateness\ndisconsolatenesses\ndisconsolation\ndisconsolations\ndiscontent\ndiscontented\ndiscontentedly\ndiscontentedness\ndiscontentednesses\ndiscontenting\ndiscontentment\ndiscontentments\ndiscontents\ndiscontinuance\ndiscontinuances\ndiscontinuation\ndiscontinuations\ndiscontinue\ndiscontinued\ndiscontinues\ndiscontinuing\ndiscontinuities\ndiscontinuity\ndiscontinuous\ndiscontinuously\ndiscophile\ndiscophiles\ndiscord\ndiscordance\ndiscordances\ndiscordancies\ndiscordancy\ndiscordant\ndiscordantly\ndiscorded\ndiscording\ndiscords\ndiscos\ndiscotheque\ndiscotheques\ndiscount\ndiscountable\ndiscounted\ndiscountenance\ndiscountenanced\ndiscountenances\ndiscountenancing\ndiscounter\ndiscounters\ndiscounting\ndiscounts\ndiscourage\ndiscourageable\ndiscouraged\ndiscouragement\ndiscouragements\ndiscourager\ndiscouragers\ndiscourages\ndiscouraging\ndiscouragingly\ndiscourse\ndiscoursed\ndiscourser\ndiscoursers\ndiscourses\ndiscoursing\ndiscourteous\ndiscourteously\ndiscourteousness\ndiscourteousnesses\ndiscourtesies\ndiscourtesy\ndiscover\ndiscoverable\ndiscovered\ndiscoverer\ndiscoverers\ndiscoveries\ndiscovering\ndiscovers\ndiscovery\ndiscredit\ndiscreditable\ndiscreditably\ndiscredited\ndiscrediting\ndiscredits\ndiscreet\ndiscreeter\ndiscreetest\ndiscreetly\ndiscreetness\ndiscreetnesses\ndiscrepancies\ndiscrepancy\ndiscrepant\ndiscrepantly\ndiscrete\ndiscretely\ndiscreteness\ndiscretenesses\ndiscretion\ndiscretionary\ndiscretions\ndiscriminabilities\ndiscriminability\ndiscriminable\ndiscriminably\ndiscriminant\ndiscriminants\ndiscriminate\ndiscriminated\ndiscriminates\ndiscriminating\ndiscriminatingly\ndiscrimination\ndiscriminational\ndiscriminations\ndiscriminative\ndiscriminator\ndiscriminatorily\ndiscriminators\ndiscriminatory\ndiscrown\ndiscrowned\ndiscrowning\ndiscrowns\ndiscs\ndiscursive\ndiscursively\ndiscursiveness\ndiscursivenesses\ndiscus\ndiscuses\ndiscuss\ndiscussable\ndiscussant\ndiscussants\ndiscussed\ndiscusser\ndiscussers\ndiscusses\ndiscussible\ndiscussing\ndiscussion\ndiscussions\ndisdain\ndisdained\ndisdainful\ndisdainfully\ndisdainfulness\ndisdainfulnesses\ndisdaining\ndisdains\ndisease\ndiseased\ndiseases\ndiseasing\ndiseconomies\ndiseconomy\ndisembark\ndisembarkation\ndisembarkations\ndisembarked\ndisembarking\ndisembarks\ndisembarrass\ndisembarrassed\ndisembarrasses\ndisembarrassing\ndisembodied\ndisembodies\ndisembody\ndisembodying\ndisembogue\ndisembogued\ndisembogues\ndisemboguing\ndisembowel\ndisemboweled\ndisemboweling\ndisembowelled\ndisembowelling\ndisembowelment\ndisembowelments\ndisembowels\ndisenchant\ndisenchanted\ndisenchanter\ndisenchanters\ndisenchanting\ndisenchantingly\ndisenchantment\ndisenchantments\ndisenchants\ndisencumber\ndisencumbered\ndisencumbering\ndisencumbers\ndisendow\ndisendowed\ndisendower\ndisendowers\ndisendowing\ndisendowment\ndisendowments\ndisendows\ndisenfranchise\ndisenfranchised\ndisenfranchisement\ndisenfranchisements\ndisenfranchises\ndisenfranchising\ndisengage\ndisengaged\ndisengagement\ndisengagements\ndisengages\ndisengaging\ndisentail\ndisentailed\ndisentailing\ndisentails\ndisentangle\ndisentangled\ndisentanglement\ndisentanglements\ndisentangles\ndisentangling\ndisenthral\ndisenthrall\ndisenthralled\ndisenthralling\ndisenthralls\ndisenthrals\ndisentitle\ndisentitled\ndisentitles\ndisentitling\ndisequilibrate\ndisequilibrated\ndisequilibrates\ndisequilibrating\ndisequilibration\ndisequilibrations\ndisequilibria\ndisequilibrium\ndisequilibriums\ndisestablish\ndisestablished\ndisestablishes\ndisestablishing\ndisestablishment\ndisestablishmentarian\ndisestablishmentarians\ndisestablishments\ndisesteem\ndisesteemed\ndisesteeming\ndisesteems\ndiseuse\ndiseuses\ndisfavor\ndisfavored\ndisfavoring\ndisfavors\ndisfigure\ndisfigured\ndisfigurement\ndisfigurements\ndisfigures\ndisfiguring\ndisfranchise\ndisfranchised\ndisfranchisement\ndisfranchisements\ndisfranchises\ndisfranchising\ndisfrock\ndisfrocked\ndisfrocking\ndisfrocks\ndisfunction\ndisfunctional\ndisfunctions\ndisfurnish\ndisfurnished\ndisfurnishes\ndisfurnishing\ndisfurnishment\ndisfurnishments\ndisgorge\ndisgorged\ndisgorges\ndisgorging\ndisgrace\ndisgraced\ndisgraceful\ndisgracefully\ndisgracefulness\ndisgracefulnesses\ndisgracer\ndisgracers\ndisgraces\ndisgracing\ndisgruntle\ndisgruntled\ndisgruntlement\ndisgruntlements\ndisgruntles\ndisgruntling\ndisguise\ndisguised\ndisguisedly\ndisguisement\ndisguisements\ndisguiser\ndisguisers\ndisguises\ndisguising\ndisgust\ndisgusted\ndisgustedly\ndisgustful\ndisgustfully\ndisgusting\ndisgustingly\ndisgusts\ndish\ndishabille\ndishabilles\ndisharmonies\ndisharmonious\ndisharmonize\ndisharmonized\ndisharmonizes\ndisharmonizing\ndisharmony\ndishcloth\ndishcloths\ndishclout\ndishclouts\ndishearten\ndisheartened\ndisheartening\ndishearteningly\ndisheartenment\ndisheartenments\ndisheartens\ndished\ndishelm\ndishelmed\ndishelming\ndishelms\ndisherit\ndisherited\ndisheriting\ndisherits\ndishes\ndishevel\ndisheveled\ndisheveling\ndishevelled\ndishevelling\ndishevels\ndishful\ndishfuls\ndishier\ndishiest\ndishing\ndishlike\ndishonest\ndishonesties\ndishonestly\ndishonesty\ndishonor\ndishonorable\ndishonorableness\ndishonorablenesses\ndishonorably\ndishonored\ndishonorer\ndishonorers\ndishonoring\ndishonors\ndishpan\ndishpans\ndishrag\ndishrags\ndishtowel\ndishtowels\ndishware\ndishwares\ndishwasher\ndishwashers\ndishwater\ndishwaters\ndishy\ndisillusion\ndisillusioned\ndisillusioning\ndisillusionment\ndisillusionments\ndisillusions\ndisincentive\ndisincentives\ndisinclination\ndisinclinations\ndisincline\ndisinclined\ndisinclines\ndisinclining\ndisinfect\ndisinfectant\ndisinfectants\ndisinfected\ndisinfecting\ndisinfection\ndisinfections\ndisinfects\ndisinfest\ndisinfestant\ndisinfestants\ndisinfestation\ndisinfestations\ndisinfested\ndisinfesting\ndisinfests\ndisinflation\ndisinflationary\ndisinflations\ndisinformation\ndisinformations\ndisingenuous\ndisingenuously\ndisingenuousness\ndisingenuousnesses\ndisinherit\ndisinheritance\ndisinheritances\ndisinherited\ndisinheriting\ndisinherits\ndisinhibit\ndisinhibited\ndisinhibiting\ndisinhibition\ndisinhibitions\ndisinhibits\ndisintegrate\ndisintegrated\ndisintegrates\ndisintegrating\ndisintegration\ndisintegrations\ndisintegrative\ndisintegrator\ndisintegrators\ndisinter\ndisinterest\ndisinterested\ndisinterestedly\ndisinterestedness\ndisinterestednesses\ndisinteresting\ndisinterests\ndisintermediation\ndisintermediations\ndisinterment\ndisinterments\ndisinterred\ndisinterring\ndisinters\ndisintoxicate\ndisintoxicated\ndisintoxicates\ndisintoxicating\ndisintoxication\ndisintoxications\ndisinvest\ndisinvested\ndisinvesting\ndisinvestment\ndisinvestments\ndisinvests\ndisinvite\ndisinvited\ndisinvites\ndisinviting\ndisject\ndisjected\ndisjecting\ndisjects\ndisjoin\ndisjoined\ndisjoining\ndisjoins\ndisjoint\ndisjointed\ndisjointedly\ndisjointedness\ndisjointednesses\ndisjointing\ndisjoints\ndisjunct\ndisjunction\ndisjunctions\ndisjunctive\ndisjunctively\ndisjunctives\ndisjuncts\ndisjuncture\ndisjunctures\ndisk\ndisked\ndiskette\ndiskettes\ndisking\ndisklike\ndisks\ndislikable\ndislike\ndislikeable\ndisliked\ndisliker\ndislikers\ndislikes\ndisliking\ndislimn\ndislimned\ndislimning\ndislimns\ndislocate\ndislocated\ndislocates\ndislocating\ndislocation\ndislocations\ndislodge\ndislodged\ndislodgement\ndislodgements\ndislodges\ndislodging\ndislodgment\ndislodgments\ndisloyal\ndisloyally\ndisloyalties\ndisloyalty\ndismal\ndismaler\ndismalest\ndismally\ndismalness\ndismalnesses\ndismals\ndismantle\ndismantled\ndismantlement\ndismantlements\ndismantles\ndismantling\ndismast\ndismasted\ndismasting\ndismasts\ndismay\ndismayed\ndismaying\ndismayingly\ndismays\ndisme\ndismember\ndismembered\ndismembering\ndismemberment\ndismemberments\ndismembers\ndismes\ndismiss\ndismissal\ndismissals\ndismissed\ndismisses\ndismissing\ndismission\ndismissions\ndismissive\ndismissively\ndismount\ndismounted\ndismounting\ndismounts\ndisobedience\ndisobediences\ndisobedient\ndisobediently\ndisobey\ndisobeyed\ndisobeyer\ndisobeyers\ndisobeying\ndisobeys\ndisoblige\ndisobliged\ndisobliges\ndisobliging\ndisomic\ndisorder\ndisordered\ndisorderedly\ndisorderedness\ndisorderednesses\ndisordering\ndisorderliness\ndisorderlinesses\ndisorderly\ndisorders\ndisorganization\ndisorganizations\ndisorganize\ndisorganized\ndisorganizes\ndisorganizing\ndisorient\ndisorientate\ndisorientated\ndisorientates\ndisorientating\ndisorientation\ndisorientations\ndisoriented\ndisorienting\ndisorients\ndisown\ndisowned\ndisowning\ndisownment\ndisownments\ndisowns\ndisparage\ndisparaged\ndisparagement\ndisparagements\ndisparager\ndisparagers\ndisparages\ndisparaging\ndisparagingly\ndisparate\ndisparately\ndisparateness\ndisparatenesses\ndisparities\ndisparity\ndispart\ndisparted\ndisparting\ndisparts\ndispassion\ndispassionate\ndispassionately\ndispassionateness\ndispassionatenesses\ndispassions\ndispatch\ndispatched\ndispatcher\ndispatchers\ndispatches\ndispatching\ndispel\ndispelled\ndispelling\ndispels\ndispend\ndispended\ndispending\ndispends\ndispensabilities\ndispensability\ndispensable\ndispensaries\ndispensary\ndispensation\ndispensational\ndispensations\ndispensatories\ndispensatory\ndispense\ndispensed\ndispenser\ndispensers\ndispenses\ndispensing\ndispeople\ndispeopled\ndispeoples\ndispeopling\ndispersal\ndispersals\ndispersant\ndispersants\ndisperse\ndispersed\ndispersedly\ndisperser\ndispersers\ndisperses\ndispersible\ndispersing\ndispersion\ndispersions\ndispersive\ndispersively\ndispersiveness\ndispersivenesses\ndispersoid\ndispersoids\ndispirit\ndispirited\ndispiritedly\ndispiritedness\ndispiritednesses\ndispiriting\ndispirits\ndispiteous\ndisplace\ndisplaceable\ndisplaced\ndisplacement\ndisplacements\ndisplaces\ndisplacing\ndisplant\ndisplanted\ndisplanting\ndisplants\ndisplay\ndisplayable\ndisplayed\ndisplaying\ndisplays\ndisplease\ndispleased\ndispleases\ndispleasing\ndispleasure\ndispleasures\ndisplode\ndisploded\ndisplodes\ndisploding\ndisplosion\ndisplosions\ndisplume\ndisplumed\ndisplumes\ndispluming\ndisport\ndisported\ndisporting\ndisportment\ndisportments\ndisports\ndisposabilities\ndisposability\ndisposable\ndisposables\ndisposal\ndisposals\ndispose\ndisposed\ndisposer\ndisposers\ndisposes\ndisposing\ndisposition\ndispositional\ndispositions\ndispositive\ndispossess\ndispossessed\ndispossesses\ndispossessing\ndispossession\ndispossessions\ndispossessor\ndispossessors\ndisposure\ndisposures\ndispraise\ndispraised\ndispraiser\ndispraisers\ndispraises\ndispraising\ndispraisingly\ndispread\ndispreading\ndispreads\ndisprize\ndisprized\ndisprizes\ndisprizing\ndisproof\ndisproofs\ndisproportion\ndisproportional\ndisproportionate\ndisproportionated\ndisproportionately\ndisproportionates\ndisproportionating\ndisproportionation\ndisproportionations\ndisproportioned\ndisproportioning\ndisproportions\ndisprovable\ndisprove\ndisproved\ndisproven\ndisproves\ndisproving\ndisputable\ndisputably\ndisputant\ndisputants\ndisputation\ndisputations\ndisputatious\ndisputatiously\ndisputatiousness\ndisputatiousnesses\ndispute\ndisputed\ndisputer\ndisputers\ndisputes\ndisputing\ndisqualification\ndisqualifications\ndisqualified\ndisqualifies\ndisqualify\ndisqualifying\ndisquantitied\ndisquantities\ndisquantity\ndisquantitying\ndisquiet\ndisquieted\ndisquieting\ndisquietingly\ndisquietly\ndisquiets\ndisquietude\ndisquietudes\ndisquisition\ndisquisitions\ndisrate\ndisrated\ndisrates\ndisrating\ndisregard\ndisregarded\ndisregardful\ndisregarding\ndisregards\ndisrelated\ndisrelation\ndisrelations\ndisrelish\ndisrelished\ndisrelishes\ndisrelishing\ndisremember\ndisremembered\ndisremembering\ndisremembers\ndisrepair\ndisrepairs\ndisreputabilities\ndisreputability\ndisreputable\ndisreputableness\ndisreputablenesses\ndisreputably\ndisrepute\ndisreputes\ndisrespect\ndisrespectabilities\ndisrespectability\ndisrespectable\ndisrespected\ndisrespectful\ndisrespectfully\ndisrespectfulness\ndisrespectfulnesses\ndisrespecting\ndisrespects\ndisrobe\ndisrobed\ndisrober\ndisrobers\ndisrobes\ndisrobing\ndisroot\ndisrooted\ndisrooting\ndisroots\ndisrupt\ndisrupted\ndisrupter\ndisrupters\ndisrupting\ndisruption\ndisruptions\ndisruptive\ndisruptively\ndisruptiveness\ndisruptivenesses\ndisrupts\ndiss\ndissatisfaction\ndissatisfactions\ndissatisfactory\ndissatisfied\ndissatisfies\ndissatisfy\ndissatisfying\ndissave\ndissaved\ndissaves\ndissaving\ndisseat\ndisseated\ndisseating\ndisseats\ndissect\ndissected\ndissecting\ndissection\ndissections\ndissector\ndissectors\ndissects\ndissed\ndisseise\ndisseised\ndisseises\ndisseisin\ndisseising\ndisseisins\ndisseisor\ndisseisors\ndisseize\ndisseized\ndisseizes\ndisseizin\ndisseizing\ndisseizins\ndissemble\ndissembled\ndissembler\ndissemblers\ndissembles\ndissembling\ndisseminate\ndisseminated\ndisseminates\ndisseminating\ndissemination\ndisseminations\ndisseminator\ndisseminators\ndisseminule\ndisseminules\ndissension\ndissensions\ndissensus\ndissensuses\ndissent\ndissented\ndissenter\ndissenters\ndissentient\ndissentients\ndissenting\ndissention\ndissentions\ndissentious\ndissents\ndissepiment\ndissepiments\ndissert\ndissertate\ndissertated\ndissertates\ndissertating\ndissertation\ndissertational\ndissertations\ndissertator\ndissertators\ndisserted\ndisserting\ndisserts\ndisserve\ndisserved\ndisserves\ndisservice\ndisserviceable\ndisservices\ndisserving\ndisses\ndissever\ndisseverance\ndisseverances\ndissevered\ndissevering\ndisseverment\ndisseverments\ndissevers\ndissidence\ndissidences\ndissident\ndissidents\ndissimilar\ndissimilarities\ndissimilarity\ndissimilarly\ndissimilars\ndissimilate\ndissimilated\ndissimilates\ndissimilating\ndissimilation\ndissimilations\ndissimilatory\ndissimilitude\ndissimilitudes\ndissimulate\ndissimulated\ndissimulates\ndissimulating\ndissimulation\ndissimulations\ndissimulator\ndissimulators\ndissing\ndissipate\ndissipated\ndissipatedly\ndissipatedness\ndissipatednesses\ndissipater\ndissipaters\ndissipates\ndissipating\ndissipation\ndissipations\ndissipative\ndissociabilities\ndissociability\ndissociable\ndissocial\ndissociate\ndissociated\ndissociates\ndissociating\ndissociation\ndissociations\ndissociative\ndissoluble\ndissolute\ndissolutely\ndissoluteness\ndissolutenesses\ndissolution\ndissolutions\ndissolvable\ndissolve\ndissolved\ndissolvent\ndissolvents\ndissolver\ndissolvers\ndissolves\ndissolving\ndissonance\ndissonances\ndissonant\ndissonantly\ndissuade\ndissuaded\ndissuader\ndissuaders\ndissuades\ndissuading\ndissuasion\ndissuasions\ndissuasive\ndissuasively\ndissuasiveness\ndissuasivenesses\ndissyllable\ndissyllables\ndissymmetric\ndissymmetries\ndissymmetry\ndistaff\ndistaffs\ndistain\ndistained\ndistaining\ndistains\ndistal\ndistally\ndistance\ndistanced\ndistances\ndistancing\ndistant\ndistantly\ndistantness\ndistantnesses\ndistaste\ndistasted\ndistasteful\ndistastefully\ndistastefulness\ndistastefulnesses\ndistastes\ndistasting\ndistaves\ndistelfink\ndistelfinks\ndistemper\ndistemperate\ndistemperature\ndistemperatures\ndistempered\ndistempering\ndistempers\ndistend\ndistended\ndistending\ndistends\ndistensibilities\ndistensibility\ndistensible\ndistension\ndistensions\ndistent\ndistention\ndistentions\ndistich\ndistichous\ndistichs\ndistil\ndistill\ndistillate\ndistillates\ndistillation\ndistillations\ndistilled\ndistiller\ndistilleries\ndistillers\ndistillery\ndistilling\ndistills\ndistils\ndistinct\ndistincter\ndistinctest\ndistinction\ndistinctions\ndistinctive\ndistinctively\ndistinctiveness\ndistinctivenesses\ndistinctly\ndistinctness\ndistinctnesses\ndistingue\ndistinguish\ndistinguishabilities\ndistinguishability\ndistinguishable\ndistinguishably\ndistinguished\ndistinguishes\ndistinguishing\ndistome\ndistomes\ndistort\ndistorted\ndistorter\ndistorters\ndistorting\ndistortion\ndistortional\ndistortions\ndistorts\ndistract\ndistractable\ndistracted\ndistractedly\ndistractibilities\ndistractibility\ndistractible\ndistracting\ndistractingly\ndistraction\ndistractions\ndistractive\ndistracts\ndistrain\ndistrainable\ndistrained\ndistrainer\ndistrainers\ndistraining\ndistrainor\ndistrainors\ndistrains\ndistraint\ndistraints\ndistrait\ndistraite\ndistraught\ndistraughtly\ndistress\ndistressed\ndistresses\ndistressful\ndistressfully\ndistressfulness\ndistressfulnesses\ndistressing\ndistressingly\ndistributaries\ndistributary\ndistribute\ndistributed\ndistributee\ndistributees\ndistributes\ndistributing\ndistribution\ndistributional\ndistributions\ndistributive\ndistributively\ndistributivities\ndistributivity\ndistributor\ndistributors\ndistributorship\ndistributorships\ndistrict\ndistricted\ndistricting\ndistricts\ndistrust\ndistrusted\ndistrustful\ndistrustfully\ndistrustfulness\ndistrustfulnesses\ndistrusting\ndistrusts\ndisturb\ndisturbance\ndisturbances\ndisturbed\ndisturber\ndisturbers\ndisturbing\ndisturbingly\ndisturbs\ndisubstituted\ndisulfid\ndisulfide\ndisulfides\ndisulfids\ndisulfiram\ndisulfirams\ndisulfoton\ndisulfotons\ndisunion\ndisunionist\ndisunionists\ndisunions\ndisunite\ndisunited\ndisunites\ndisunities\ndisuniting\ndisunity\ndisuse\ndisused\ndisuses\ndisusing\ndisutilities\ndisutility\ndisvalue\ndisvalued\ndisvalues\ndisvaluing\ndisyllabic\ndisyllable\ndisyllables\ndisyoke\ndisyoked\ndisyokes\ndisyoking\ndit\ndita\nditas\nditch\nditchdigger\nditchdiggers\nditched\nditcher\nditchers\nditches\nditching\ndite\ndites\nditheism\nditheisms\nditheist\nditheists\ndither\ndithered\nditherer\nditherers\ndithering\ndithers\ndithery\ndithiocarbamate\ndithiocarbamates\ndithiol\ndithyramb\ndithyrambic\ndithyrambically\ndithyrambs\nditransitive\nditransitives\ndits\nditsier\nditsiest\nditsy\ndittanies\ndittany\nditties\nditto\ndittoed\ndittoing\ndittos\nditty\nditz\nditzes\nditzier\nditziest\nditzy\ndiureses\ndiuresis\ndiuretic\ndiuretically\ndiuretics\ndiurnal\ndiurnally\ndiurnals\ndiuron\ndiurons\ndiva\ndivagate\ndivagated\ndivagates\ndivagating\ndivagation\ndivagations\ndivalent\ndivan\ndivans\ndivaricate\ndivaricated\ndivaricates\ndivaricating\ndivarication\ndivarications\ndivas\ndive\ndivebomb\ndivebombed\ndivebombing\ndivebombs\ndived\ndiver\ndiverge\ndiverged\ndivergence\ndivergences\ndivergencies\ndivergency\ndivergent\ndivergently\ndiverges\ndiverging\ndivers\ndiverse\ndiversely\ndiverseness\ndiversenesses\ndiversification\ndiversifications\ndiversified\ndiversifier\ndiversifiers\ndiversifies\ndiversify\ndiversifying\ndiversion\ndiversionary\ndiversionist\ndiversionists\ndiversions\ndiversities\ndiversity\ndivert\ndiverted\ndiverter\ndiverters\ndiverticula\ndiverticular\ndiverticulitis\ndiverticulitises\ndiverticuloses\ndiverticulosis\ndiverticulum\ndivertimenti\ndivertimento\ndivertimentos\ndiverting\ndivertissement\ndivertissements\ndiverts\ndives\ndivest\ndivested\ndivesting\ndivestiture\ndivestitures\ndivestment\ndivestments\ndivests\ndividable\ndivide\ndivided\ndividedly\ndividedness\ndividednesses\ndividend\ndividendless\ndividends\ndivider\ndividers\ndivides\ndividing\ndividual\ndivination\ndivinations\ndivinatory\ndivine\ndivined\ndivinely\ndiviner\ndiviners\ndivines\ndivinest\ndiving\ndivining\ndivinise\ndivinised\ndivinises\ndivinising\ndivinities\ndivinity\ndivinize\ndivinized\ndivinizes\ndivinizing\ndivisibilities\ndivisibility\ndivisible\ndivision\ndivisional\ndivisionism\ndivisionisms\ndivisionist\ndivisionists\ndivisions\ndivisive\ndivisively\ndivisiveness\ndivisivenesses\ndivisor\ndivisors\ndivorce\ndivorced\ndivorcee\ndivorcees\ndivorcement\ndivorcements\ndivorcer\ndivorcers\ndivorces\ndivorcing\ndivot\ndivots\ndivulge\ndivulged\ndivulgence\ndivulgences\ndivulger\ndivulgers\ndivulges\ndivulging\ndivvied\ndivvies\ndivvy\ndivvying\ndiwan\ndiwans\ndixit\ndixits\ndizen\ndizened\ndizening\ndizens\ndizygotic\ndizygous\ndizzied\ndizzier\ndizzies\ndizziest\ndizzily\ndizziness\ndizzinesses\ndizzy\ndizzying\ndizzyingly\ndjebel\ndjebels\ndjellaba\ndjellabah\ndjellabahs\ndjellabas\ndjin\ndjinn\ndjinni\ndjinns\ndjinny\ndjins\ndo\ndoable\ndoat\ndoated\ndoating\ndoats\ndobber\ndobbers\ndobbies\ndobbin\ndobbins\ndobby\ndobie\ndobies\ndobla\ndoblas\ndoblon\ndoblones\ndoblons\ndobra\ndobras\ndobro\ndobros\ndobson\ndobsonflies\ndobsonfly\ndobsons\ndoby\ndoc\ndocent\ndocents\ndocetic\ndocile\ndocilely\ndocilities\ndocility\ndock\ndockage\ndockages\ndocked\ndocker\ndockers\ndocket\ndocketed\ndocketing\ndockets\ndockhand\ndockhands\ndocking\ndockland\ndocklands\ndockmaster\ndockmasters\ndocks\ndockside\ndocksides\ndockworker\ndockworkers\ndockyard\ndockyards\ndocs\ndoctor\ndoctoral\ndoctorate\ndoctorates\ndoctored\ndoctoring\ndoctorless\ndoctors\ndoctorship\ndoctorships\ndoctrinaire\ndoctrinaires\ndoctrinairism\ndoctrinairisms\ndoctrinal\ndoctrinally\ndoctrine\ndoctrines\ndocudrama\ndocudramas\ndocument\ndocumentable\ndocumental\ndocumentalist\ndocumentalists\ndocumentarian\ndocumentarians\ndocumentaries\ndocumentarily\ndocumentarist\ndocumentarists\ndocumentary\ndocumentation\ndocumentational\ndocumentations\ndocumented\ndocumenter\ndocumenters\ndocumenting\ndocuments\ndodder\ndoddered\ndodderer\ndodderers\ndoddering\ndodders\ndoddery\ndodecagon\ndodecagons\ndodecahedra\ndodecahedral\ndodecahedron\ndodecahedrons\ndodecaphonic\ndodecaphonically\ndodecaphonies\ndodecaphonist\ndodecaphonists\ndodecaphony\ndodge\ndodgeball\ndodgeballs\ndodged\ndodgem\ndodgems\ndodger\ndodgeries\ndodgers\ndodgery\ndodges\ndodgier\ndodgiest\ndodginess\ndodginesses\ndodging\ndodgy\ndodo\ndodoes\ndodoism\ndodoisms\ndodos\ndoe\ndoer\ndoers\ndoes\ndoeskin\ndoeskins\ndoest\ndoeth\ndoff\ndoffed\ndoffer\ndoffers\ndoffing\ndoffs\ndog\ndogbane\ndogbanes\ndogberries\ndogberry\ndogcart\ndogcarts\ndogcatcher\ndogcatchers\ndogdom\ndogdoms\ndoge\ndogear\ndogeared\ndogearing\ndogears\ndogedom\ndogedoms\ndoges\ndogeship\ndogeships\ndogey\ndogeys\ndogface\ndogfaces\ndogfight\ndogfighting\ndogfights\ndogfish\ndogfishes\ndogfought\ndogged\ndoggedly\ndoggedness\ndoggednesses\ndogger\ndoggerel\ndoggerels\ndoggeries\ndoggers\ndoggery\ndoggie\ndoggier\ndoggies\ndoggiest\ndogging\ndoggish\ndoggishly\ndoggishness\ndoggishnesses\ndoggo\ndoggone\ndoggoned\ndoggoneder\ndoggonedest\ndoggoner\ndoggones\ndoggonest\ndoggoning\ndoggrel\ndoggrels\ndoggy\ndoghouse\ndoghouses\ndogie\ndogies\ndogleg\ndoglegged\ndoglegging\ndoglegs\ndoglike\ndogma\ndogmas\ndogmata\ndogmatic\ndogmatical\ndogmatically\ndogmaticalness\ndogmaticalnesses\ndogmatics\ndogmatism\ndogmatisms\ndogmatist\ndogmatists\ndogmatization\ndogmatizations\ndogmatize\ndogmatized\ndogmatizer\ndogmatizers\ndogmatizes\ndogmatizing\ndognap\ndognaped\ndognaper\ndognapers\ndognaping\ndognapped\ndognapper\ndognappers\ndognapping\ndognaps\ndogs\ndogsbodies\ndogsbody\ndogsled\ndogsledded\ndogsledder\ndogsledders\ndogsledding\ndogsleds\ndogteeth\ndogtooth\ndogtrot\ndogtrots\ndogtrotted\ndogtrotting\ndogvane\ndogvanes\ndogwatch\ndogwatches\ndogwood\ndogwoods\ndogy\ndoiled\ndoilies\ndoily\ndoing\ndoings\ndoit\ndoited\ndoits\ndojo\ndojos\ndol\ndolce\ndolci\ndoldrums\ndole\ndoled\ndoleful\ndolefuller\ndolefullest\ndolefully\ndolefulness\ndolefulnesses\ndolerite\ndolerites\ndoleritic\ndoles\ndolesome\ndolichocephalic\ndolichocephalies\ndolichocephaly\ndoling\ndoll\ndollar\ndollars\ndolled\ndollhouse\ndollhouses\ndollied\ndollies\ndolling\ndollish\ndollishly\ndollishness\ndollishnesses\ndollop\ndolloped\ndolloping\ndollops\ndolls\ndolly\ndollying\ndolma\ndolmades\ndolman\ndolmans\ndolmas\ndolmen\ndolmens\ndolomite\ndolomites\ndolomitic\ndolomitization\ndolomitizations\ndolomitize\ndolomitized\ndolomitizes\ndolomitizing\ndolor\ndoloroso\ndolorous\ndolorously\ndolorousness\ndolorousnesses\ndolors\ndolour\ndolours\ndolphin\ndolphinfish\ndolphinfishes\ndolphins\ndols\ndolt\ndoltish\ndoltishly\ndoltishness\ndoltishnesses\ndolts\ndom\ndomain\ndomains\ndomal\ndome\ndomed\ndomelike\ndomes\ndomesday\ndomesdays\ndomestic\ndomestically\ndomesticate\ndomesticated\ndomesticates\ndomesticating\ndomestication\ndomestications\ndomesticities\ndomesticity\ndomestics\ndomic\ndomical\ndomicil\ndomicile\ndomiciled\ndomiciles\ndomiciliary\ndomiciliate\ndomiciliated\ndomiciliates\ndomiciliating\ndomiciliation\ndomiciliations\ndomiciling\ndomicils\ndominance\ndominances\ndominant\ndominantly\ndominants\ndominate\ndominated\ndominates\ndominating\ndomination\ndominations\ndominative\ndominator\ndominators\ndominatrices\ndominatrix\ndominatrixes\ndomine\ndomineer\ndomineered\ndomineering\ndomineeringly\ndomineeringness\ndomineeringnesses\ndomineers\ndomines\ndoming\ndominical\ndominick\ndominicker\ndominickers\ndominicks\ndominie\ndominies\ndominion\ndominions\ndominique\ndominiques\ndominium\ndominiums\ndomino\ndominoes\ndominos\ndoms\ndon\ndona\ndonas\ndonate\ndonated\ndonates\ndonating\ndonation\ndonations\ndonative\ndonatives\ndonator\ndonators\ndone\ndonee\ndonees\ndoneness\ndonenesses\ndong\ndonga\ndongas\ndongle\ndongles\ndongola\ndongolas\ndongs\ndonjon\ndonjons\ndonkey\ndonkeys\ndonkeywork\ndonkeyworks\ndonna\ndonnas\ndonne\ndonned\ndonnee\ndonnees\ndonnerd\ndonnered\ndonnert\ndonnicker\ndonnickers\ndonniker\ndonnikers\ndonning\ndonnish\ndonnishly\ndonnishness\ndonnishnesses\ndonnybrook\ndonnybrooks\ndonor\ndonors\ndons\ndonsie\ndonsy\ndonut\ndonuts\ndonzel\ndonzels\ndoodad\ndoodads\ndoodle\ndoodlebug\ndoodlebugs\ndoodled\ndoodler\ndoodlers\ndoodles\ndoodling\ndoofus\ndoofuses\ndoohickey\ndoohickeys\ndoohickies\ndoolee\ndoolees\ndoolie\ndoolies\ndooly\ndoom\ndoomed\ndoomful\ndoomfully\ndoomily\ndooming\ndooms\ndoomsayer\ndoomsayers\ndoomsaying\ndoomsayings\ndoomsday\ndoomsdayer\ndoomsdayers\ndoomsdays\ndoomster\ndoomsters\ndoomy\ndoor\ndoorbell\ndoorbells\ndoorjamb\ndoorjambs\ndoorkeeper\ndoorkeepers\ndoorknob\ndoorknobs\ndoorless\ndoorman\ndoormat\ndoormats\ndoormen\ndoornail\ndoornails\ndoorplate\ndoorplates\ndoorpost\ndoorposts\ndoors\ndoorsill\ndoorsills\ndoorstep\ndoorsteps\ndoorstop\ndoorstops\ndoorway\ndoorways\ndooryard\ndooryards\ndoozer\ndoozers\ndoozie\ndoozies\ndoozy\ndopa\ndopamine\ndopaminergic\ndopamines\ndopant\ndopants\ndopas\ndope\ndoped\ndopehead\ndopeheads\ndoper\ndopers\ndopes\ndopester\ndopesters\ndopey\ndopier\ndopiest\ndopiness\ndopinesses\ndoping\ndoppelganger\ndoppelgangers\ndopy\ndor\ndorado\ndorados\ndorbug\ndorbugs\ndore\ndorhawk\ndorhawks\ndories\ndork\ndorkier\ndorkiest\ndorks\ndorky\ndorm\ndormancies\ndormancy\ndormant\ndormer\ndormers\ndormice\ndormie\ndormient\ndormin\ndormins\ndormitories\ndormitory\ndormouse\ndorms\ndormy\ndorneck\ndornecks\ndornick\ndornicks\ndornock\ndornocks\ndoronicum\ndoronicums\ndorp\ndorper\ndorpers\ndorps\ndorr\ndorrs\ndors\ndorsa\ndorsad\ndorsal\ndorsally\ndorsals\ndorsel\ndorsels\ndorser\ndorsers\ndorsiventral\ndorsiventralities\ndorsiventrality\ndorsiventrally\ndorsolateral\ndorsoventral\ndorsoventralities\ndorsoventrality\ndorsoventrally\ndorsum\ndorty\ndory\ndos\ndosage\ndosages\ndose\ndosed\ndoser\ndosers\ndoses\ndosimeter\ndosimeters\ndosimetric\ndosimetries\ndosimetry\ndosing\ndoss\ndossal\ndossals\ndossed\ndossel\ndossels\ndosser\ndosseret\ndosserets\ndossers\ndosses\ndossier\ndossiers\ndossil\ndossils\ndossing\ndost\ndot\ndotage\ndotages\ndotal\ndotard\ndotardly\ndotards\ndotation\ndotations\ndote\ndoted\ndoter\ndoters\ndotes\ndoth\ndotier\ndotiest\ndoting\ndotingly\ndots\ndotted\ndottel\ndottels\ndotter\ndotterel\ndotterels\ndotters\ndottier\ndottiest\ndottily\ndottiness\ndottinesses\ndotting\ndottle\ndottles\ndottrel\ndottrels\ndotty\ndoty\ndouble\ndoubled\ndoubleheader\ndoubleheaders\ndoubleness\ndoublenesses\ndoubler\ndoublers\ndoubles\ndoublespeak\ndoublespeaker\ndoublespeakers\ndoublespeaks\ndoublet\ndoublethink\ndoublethinks\ndoubleton\ndoubletons\ndoublets\ndoubling\ndoubloon\ndoubloons\ndoublure\ndoublures\ndoubly\ndoubt\ndoubtable\ndoubted\ndoubter\ndoubters\ndoubtful\ndoubtfully\ndoubtfulness\ndoubtfulnesses\ndoubting\ndoubtingly\ndoubtless\ndoubtlessly\ndoubtlessness\ndoubtlessnesses\ndoubts\ndouce\ndoucely\ndouceur\ndouceurs\ndouche\ndouched\ndouches\ndouching\ndough\ndoughboy\ndoughboys\ndoughface\ndoughfaces\ndoughier\ndoughiest\ndoughlike\ndoughnut\ndoughnutlike\ndoughnuts\ndoughs\ndought\ndoughtier\ndoughtiest\ndoughtily\ndoughtiness\ndoughtinesses\ndoughty\ndoughy\ndoum\ndouma\ndoumas\ndoums\ndoupioni\ndoupionis\ndour\ndoura\ndourah\ndourahs\ndouras\ndourer\ndourest\ndourine\ndourines\ndourly\ndourness\ndournesses\ndouroucouli\ndouroucoulis\ndouse\ndoused\ndouser\ndousers\ndouses\ndousing\ndoux\ndouzeper\ndouzepers\ndove\ndovecot\ndovecote\ndovecotes\ndovecots\ndovekey\ndovekeys\ndovekie\ndovekies\ndovelike\ndoven\ndovened\ndovening\ndovens\ndoves\ndovetail\ndovetailed\ndovetailing\ndovetails\ndovish\ndovishness\ndovishnesses\ndow\ndowable\ndowager\ndowagers\ndowdier\ndowdies\ndowdiest\ndowdily\ndowdiness\ndowdinesses\ndowdy\ndowdyish\ndowed\ndowel\ndoweled\ndoweling\ndowelled\ndowelling\ndowels\ndower\ndowered\ndoweries\ndowering\ndowers\ndowery\ndowie\ndowing\ndowitcher\ndowitchers\ndown\ndownbeat\ndownbeats\ndownburst\ndownbursts\ndowncast\ndowncasts\ndowncome\ndowncomes\ndowncourt\ndowndraft\ndowndrafts\ndowned\ndowner\ndowners\ndownfall\ndownfallen\ndownfalls\ndownfield\ndowngrade\ndowngraded\ndowngrades\ndowngrading\ndownhaul\ndownhauls\ndownhearted\ndownheartedly\ndownheartedness\ndownheartednesses\ndownhill\ndownhiller\ndownhillers\ndownhills\ndownier\ndowniest\ndowning\ndownland\ndownlands\ndownlink\ndownlinks\ndownload\ndownloadable\ndownloaded\ndownloading\ndownloads\ndownpipe\ndownpipes\ndownplay\ndownplayed\ndownplaying\ndownplays\ndownpour\ndownpours\ndownrange\ndownright\ndownrightly\ndownrightness\ndownrightnesses\ndownriver\ndowns\ndownscale\ndownscaled\ndownscales\ndownscaling\ndownshift\ndownshifted\ndownshifting\ndownshifts\ndownside\ndownsides\ndownsize\ndownsized\ndownsizes\ndownsizing\ndownslide\ndownslides\ndownslope\ndownspout\ndownspouts\ndownstage\ndownstages\ndownstairs\ndownstate\ndownstater\ndownstaters\ndownstates\ndownstream\ndownstroke\ndownstrokes\ndownswing\ndownswings\ndowntick\ndownticks\ndowntime\ndowntimes\ndowntown\ndowntowner\ndowntowners\ndowntowns\ndowntrend\ndowntrends\ndowntrod\ndowntrodden\ndownturn\ndownturns\ndownward\ndownwardly\ndownwardness\ndownwardnesses\ndownwards\ndownwash\ndownwashes\ndownwind\ndowny\ndowries\ndowry\ndows\ndowsabel\ndowsabels\ndowse\ndowsed\ndowser\ndowsers\ndowses\ndowsing\ndoxie\ndoxies\ndoxologies\ndoxology\ndoxorubicin\ndoxorubicins\ndoxy\ndoxycycline\ndoxycyclines\ndoyen\ndoyenne\ndoyennes\ndoyens\ndoyley\ndoyleys\ndoylies\ndoyly\ndoze\ndozed\ndozen\ndozened\ndozening\ndozens\ndozenth\ndozenths\ndozer\ndozers\ndozes\ndozier\ndoziest\ndozily\ndoziness\ndozinesses\ndozing\ndozy\ndrab\ndrabbed\ndrabber\ndrabbest\ndrabbet\ndrabbets\ndrabbing\ndrabble\ndrabbled\ndrabbles\ndrabbling\ndrably\ndrabness\ndrabnesses\ndrabs\ndracaena\ndracaenas\ndrachm\ndrachma\ndrachmae\ndrachmai\ndrachmas\ndrachms\ndraconian\ndraconic\ndraff\ndraffier\ndraffiest\ndraffish\ndraffs\ndraffy\ndraft\ndraftable\ndrafted\ndraftee\ndraftees\ndrafter\ndrafters\ndraftier\ndraftiest\ndraftily\ndraftiness\ndraftinesses\ndrafting\ndraftings\ndrafts\ndraftsman\ndraftsmanship\ndraftsmanships\ndraftsmen\ndraftsperson\ndraftspersons\ndrafty\ndrag\ndragee\ndragees\ndragged\ndragger\ndraggers\ndraggier\ndraggiest\ndragging\ndraggingly\ndraggle\ndraggled\ndraggles\ndraggling\ndraggy\ndragline\ndraglines\ndragnet\ndragnets\ndragoman\ndragomans\ndragomen\ndragon\ndragonet\ndragonets\ndragonflies\ndragonfly\ndragonhead\ndragonheads\ndragonish\ndragons\ndragoon\ndragooned\ndragooning\ndragoons\ndragrope\ndragropes\ndrags\ndragster\ndragsters\ndrail\ndrails\ndrain\ndrainage\ndrainages\ndrained\ndrainer\ndrainers\ndraining\ndrainpipe\ndrainpipes\ndrains\ndrake\ndrakes\ndram\ndrama\ndramas\ndramatic\ndramatically\ndramatics\ndramatisation\ndramatisations\ndramatise\ndramatised\ndramatises\ndramatising\ndramatist\ndramatists\ndramatizable\ndramatization\ndramatizations\ndramatize\ndramatized\ndramatizes\ndramatizing\ndramaturg\ndramaturge\ndramaturges\ndramaturgic\ndramaturgical\ndramaturgically\ndramaturgies\ndramaturgs\ndramaturgy\ndramedies\ndramedy\ndrammed\ndramming\ndrammock\ndrammocks\ndrams\ndramshop\ndramshops\ndrank\ndrapabilities\ndrapability\ndrapable\ndrape\ndrapeabilities\ndrapeability\ndrapeable\ndraped\ndraper\ndraperies\ndrapers\ndrapery\ndrapes\ndrapey\ndraping\ndrastic\ndrastically\ndrat\ndrats\ndratted\ndratting\ndraught\ndraughted\ndraughtier\ndraughtiest\ndraughting\ndraughts\ndraughtsman\ndraughtsmen\ndraughty\ndrave\ndraw\ndrawable\ndrawback\ndrawbacks\ndrawbar\ndrawbars\ndrawbore\ndrawbores\ndrawbridge\ndrawbridges\ndrawdown\ndrawdowns\ndrawee\ndrawees\ndrawer\ndrawerful\ndrawerfuls\ndrawers\ndrawing\ndrawings\ndrawknife\ndrawknives\ndrawl\ndrawled\ndrawler\ndrawlers\ndrawlier\ndrawliest\ndrawling\ndrawlingly\ndrawls\ndrawly\ndrawn\ndrawnwork\ndrawnworks\ndrawplate\ndrawplates\ndraws\ndrawshave\ndrawshaves\ndrawstring\ndrawstrings\ndrawtube\ndrawtubes\ndray\ndrayage\ndrayages\ndrayed\ndraying\ndrayman\ndraymen\ndrays\ndread\ndreaded\ndreadful\ndreadfully\ndreadfulness\ndreadfulnesses\ndreadfuls\ndreading\ndreadlock\ndreadlocks\ndreadnought\ndreadnoughts\ndreads\ndream\ndreamed\ndreamer\ndreamers\ndreamful\ndreamfully\ndreamfulness\ndreamfulnesses\ndreamier\ndreamiest\ndreamily\ndreaminess\ndreaminesses\ndreaming\ndreamland\ndreamlands\ndreamless\ndreamlessly\ndreamlessness\ndreamlessnesses\ndreamlike\ndreams\ndreamt\ndreamtime\ndreamtimes\ndreamworld\ndreamworlds\ndreamy\ndrear\ndrearier\ndrearies\ndreariest\ndrearily\ndreariness\ndrearinesses\ndrears\ndreary\ndreck\ndrecks\ndrecky\ndredge\ndredged\ndredger\ndredgers\ndredges\ndredging\ndredgings\ndree\ndreed\ndreeing\ndrees\ndreg\ndreggier\ndreggiest\ndreggish\ndreggy\ndregs\ndreich\ndreidel\ndreidels\ndreidl\ndreidls\ndreigh\ndrek\ndreks\ndrench\ndrenched\ndrencher\ndrenchers\ndrenches\ndrenching\ndress\ndressage\ndressages\ndressed\ndresser\ndressers\ndresses\ndressier\ndressiest\ndressily\ndressiness\ndressinesses\ndressing\ndressings\ndressmaker\ndressmakers\ndressmaking\ndressmakings\ndressy\ndrest\ndrew\ndrib\ndribbed\ndribbing\ndribble\ndribbled\ndribbler\ndribblers\ndribbles\ndribblet\ndribblets\ndribbling\ndribbly\ndriblet\ndriblets\ndribs\ndried\ndriegh\ndrier\ndriers\ndries\ndriest\ndrift\ndriftage\ndriftages\ndrifted\ndrifter\ndrifters\ndriftier\ndriftiest\ndrifting\ndriftingly\ndriftpin\ndriftpins\ndrifts\ndriftwood\ndriftwoods\ndrifty\ndrill\ndrillabilities\ndrillability\ndrillable\ndrilled\ndriller\ndrillers\ndrilling\ndrillings\ndrillmaster\ndrillmasters\ndrills\ndrily\ndrink\ndrinkabilities\ndrinkability\ndrinkable\ndrinkables\ndrinker\ndrinkers\ndrinking\ndrinks\ndrip\ndripless\ndripped\ndripper\ndrippers\ndrippier\ndrippiest\ndripping\ndrippings\ndrippy\ndrips\ndripstone\ndripstones\ndript\ndrivabilities\ndrivability\ndrivable\ndrive\ndriveabilities\ndriveability\ndriveable\ndrivel\ndriveled\ndriveler\ndrivelers\ndriveline\ndrivelines\ndriveling\ndrivelled\ndrivelling\ndrivels\ndriven\ndrivenness\ndrivennesses\ndriver\ndriverless\ndrivers\ndrives\ndriveshaft\ndriveshafts\ndrivetrain\ndrivetrains\ndriveway\ndriveways\ndriving\ndrivings\ndrizzle\ndrizzled\ndrizzles\ndrizzlier\ndrizzliest\ndrizzling\ndrizzlingly\ndrizzly\ndrogue\ndrogues\ndroid\ndroids\ndroit\ndroits\ndroll\ndrolled\ndroller\ndrolleries\ndrollery\ndrollest\ndrolling\ndrollness\ndrollnesses\ndrolls\ndrolly\ndromedaries\ndromedary\ndromon\ndromond\ndromonds\ndromons\ndrone\ndroned\ndroner\ndroners\ndrones\ndrongo\ndrongos\ndroning\ndroningly\ndronish\ndrool\ndrooled\ndrooling\ndrools\ndroop\ndrooped\ndroopier\ndroopiest\ndroopily\ndrooping\ndroopingly\ndroops\ndroopy\ndrop\ndropcloth\ndropcloths\ndrophead\ndropheads\ndropkick\ndropkicker\ndropkickers\ndropkicks\ndroplet\ndroplets\ndroplight\ndroplights\ndropout\ndropouts\ndroppable\ndropped\ndropper\ndropperful\ndropperfuls\ndroppers\ndroppersful\ndropping\ndroppings\ndrops\ndropshot\ndropshots\ndropsical\ndropsied\ndropsies\ndropsy\ndropt\ndropwort\ndropworts\ndrosera\ndroseras\ndroshkies\ndroshky\ndroshkys\ndroskies\ndrosky\ndroskys\ndrosophila\ndrosophilae\ndrosophilas\ndross\ndrosses\ndrossier\ndrossiest\ndrossy\ndrought\ndroughtier\ndroughtiest\ndroughtiness\ndroughtinesses\ndroughts\ndroughty\ndrouk\ndrouked\ndrouking\ndrouks\ndrouth\ndrouthier\ndrouthiest\ndrouths\ndrouthy\ndrove\ndroved\ndrover\ndrovers\ndroves\ndroving\ndrown\ndrownd\ndrownded\ndrownding\ndrownds\ndrowned\ndrowner\ndrowners\ndrowning\ndrownings\ndrowns\ndrowse\ndrowsed\ndrowses\ndrowsier\ndrowsiest\ndrowsily\ndrowsiness\ndrowsinesses\ndrowsing\ndrowsy\ndrub\ndrubbed\ndrubber\ndrubbers\ndrubbing\ndrubbings\ndrubs\ndrudge\ndrudged\ndrudger\ndrudgeries\ndrudgers\ndrudgery\ndrudges\ndrudging\ndrudgingly\ndrug\ndrugged\ndrugget\ndruggets\ndruggie\ndruggier\ndruggies\ndruggiest\ndrugging\ndruggist\ndruggists\ndruggy\ndrugmaker\ndrugmakers\ndrugs\ndrugstore\ndrugstores\ndruid\ndruidess\ndruidesses\ndruidic\ndruidical\ndruidism\ndruidisms\ndruids\ndrum\ndrumbeat\ndrumbeater\ndrumbeaters\ndrumbeating\ndrumbeatings\ndrumbeats\ndrumble\ndrumbled\ndrumbles\ndrumbling\ndrumfire\ndrumfires\ndrumfish\ndrumfishes\ndrumhead\ndrumheads\ndrumlier\ndrumliest\ndrumlike\ndrumlin\ndrumlins\ndrumly\ndrummed\ndrummer\ndrummers\ndrumming\ndrumroll\ndrumrolls\ndrums\ndrumstick\ndrumsticks\ndrunk\ndrunkard\ndrunkards\ndrunken\ndrunkenly\ndrunkenness\ndrunkennesses\ndrunker\ndrunkest\ndrunks\ndrupaceous\ndrupe\ndrupelet\ndrupelets\ndrupes\ndruse\ndruses\ndruthers\ndry\ndryable\ndryad\ndryades\ndryadic\ndryads\ndryasdust\ndryasdusts\ndryer\ndryers\ndryest\ndrying\ndryish\ndryland\ndrylot\ndrylots\ndryly\ndryness\ndrynesses\ndryopithecine\ndryopithecines\ndrypoint\ndrypoints\ndrys\ndrysalter\ndrysalteries\ndrysalters\ndrysaltery\ndrystone\ndrywall\ndrywalls\nduad\nduads\ndual\ndualism\ndualisms\ndualist\ndualistic\ndualistically\ndualists\ndualities\nduality\ndualize\ndualized\ndualizes\ndualizing\ndually\nduals\ndub\ndubbed\ndubber\ndubbers\ndubbin\ndubbing\ndubbings\ndubbins\ndubieties\ndubiety\ndubious\ndubiously\ndubiousness\ndubiousnesses\ndubitable\ndubitation\ndubitations\ndubnium\ndubniums\ndubonnet\ndubonnets\ndubs\nducal\nducally\nducat\nducats\nduce\nduces\nduchess\nduchesses\nduchies\nduchy\nduci\nduck\nduckbill\nduckbills\nduckboard\nduckboards\nducked\nducker\nduckers\nduckie\nduckier\nduckies\nduckiest\nducking\nduckling\nducklings\nduckpin\nduckpins\nducks\nducktail\nducktails\nduckwalk\nduckwalked\nduckwalking\nduckwalks\nduckweed\nduckweeds\nducky\nduct\nductal\nducted\nductile\nductilities\nductility\nducting\nductings\nductless\nducts\nductule\nductules\nductwork\nductworks\ndud\nduddie\nduddy\ndude\nduded\ndudeen\ndudeens\ndudes\ndudgeon\ndudgeons\nduding\ndudish\ndudishly\nduds\ndue\nduecento\nduecentos\nduel\ndueled\ndueler\nduelers\ndueling\nduelist\nduelists\nduelled\ndueller\nduellers\nduelli\nduelling\nduellist\nduellists\nduello\nduellos\nduels\nduende\nduendes\ndueness\nduenesses\nduenna\nduennas\nduennaship\nduennaships\ndues\nduet\nduets\nduetted\nduetting\nduettist\nduettists\nduff\nduffel\nduffels\nduffer\nduffers\nduffle\nduffles\nduffs\ndug\ndugong\ndugongs\ndugout\ndugouts\ndugs\nduh\ndui\nduiker\nduikers\nduit\nduits\nduke\nduked\ndukedom\ndukedoms\ndukes\nduking\ndulcet\ndulcetly\ndulcets\ndulciana\ndulcianas\ndulcified\ndulcifies\ndulcify\ndulcifying\ndulcimer\ndulcimers\ndulcimore\ndulcimores\ndulcinea\ndulcineas\ndulia\ndulias\ndull\ndullard\ndullards\ndulled\nduller\ndullest\ndulling\ndullish\ndullishly\ndullness\ndullnesses\ndulls\ndullsville\ndullsvilles\ndully\ndulness\ndulnesses\ndulse\ndulses\nduly\nduma\ndumas\ndumb\ndumbbell\ndumbbells\ndumbcane\ndumbcanes\ndumbed\ndumber\ndumbest\ndumbfound\ndumbfounded\ndumbfounder\ndumbfoundered\ndumbfoundering\ndumbfounders\ndumbfounding\ndumbfounds\ndumbhead\ndumbheads\ndumbing\ndumbly\ndumbness\ndumbnesses\ndumbs\ndumbstruck\ndumbwaiter\ndumbwaiters\ndumdum\ndumdums\ndumfound\ndumfounded\ndumfounding\ndumfounds\ndumka\ndumky\ndummied\ndummies\ndummkopf\ndummkopfs\ndummy\ndummying\ndumortierite\ndumortierites\ndump\ndumpcart\ndumpcarts\ndumped\ndumper\ndumpers\ndumpier\ndumpiest\ndumpily\ndumpiness\ndumpinesses\ndumping\ndumpings\ndumpish\ndumpling\ndumplings\ndumps\ndumpster\ndumpsters\ndumpy\ndun\ndunam\ndunams\ndunce\ndunces\ndunch\ndunches\nduncical\nduncish\ndunderhead\ndunderheaded\ndunderheads\ndundrearies\ndune\nduneland\ndunelands\ndunelike\ndunes\ndung\ndungaree\ndungarees\ndunged\ndungeon\ndungeoned\ndungeoning\ndungeons\ndunghill\ndunghills\ndungier\ndungiest\ndunging\ndungs\ndungy\ndunite\ndunites\ndunitic\ndunk\ndunked\ndunker\ndunkers\ndunking\ndunks\ndunlin\ndunlins\ndunnage\ndunnages\ndunned\ndunner\ndunness\ndunnesses\ndunnest\ndunning\ndunnite\ndunnites\nduns\ndunt\ndunted\ndunting\ndunts\nduo\nduodecillion\nduodecillions\nduodecimal\nduodecimals\nduodecimo\nduodecimos\nduodena\nduodenal\nduodenum\nduodenums\nduolog\nduologs\nduologue\nduologues\nduomi\nduomo\nduomos\nduopolies\nduopolistic\nduopoly\nduopsonies\nduopsony\nduos\nduotone\nduotones\ndup\ndupable\ndupe\nduped\nduper\nduperies\ndupers\ndupery\ndupes\nduping\nduple\nduplex\nduplexed\nduplexer\nduplexers\nduplexes\nduplexing\nduplicate\nduplicated\nduplicates\nduplicating\nduplication\nduplications\nduplicative\nduplicator\nduplicators\nduplicities\nduplicitous\nduplicitously\nduplicity\ndupped\ndupping\ndups\ndura\ndurabilities\ndurability\ndurable\ndurableness\ndurablenesses\ndurables\ndurably\ndural\nduralumin\nduralumins\nduramen\nduramens\ndurance\ndurances\nduras\nduration\ndurations\ndurative\nduratives\ndurbar\ndurbars\ndure\ndured\ndures\nduress\nduresses\ndurian\ndurians\nduring\ndurion\ndurions\ndurmast\ndurmasts\ndurn\ndurndest\ndurned\ndurneder\ndurnedest\ndurning\ndurns\nduro\nduroc\ndurocs\ndurometer\ndurometers\nduros\ndurr\ndurra\ndurras\ndurrie\ndurries\ndurrs\ndurst\ndurum\ndurums\ndusk\ndusked\nduskier\nduskiest\nduskily\nduskiness\nduskinesses\ndusking\nduskish\ndusks\ndusky\ndust\ndustbin\ndustbins\ndustcover\ndustcovers\ndusted\nduster\ndusters\ndustheap\ndustheaps\ndustier\ndustiest\ndustily\ndustiness\ndustinesses\ndusting\ndustless\ndustlike\ndustman\ndustmen\ndustoff\ndustoffs\ndustpan\ndustpans\ndustrag\ndustrags\ndusts\ndustup\ndustups\ndusty\ndutch\ndutchman\ndutchmen\nduteous\ndutiable\nduties\ndutiful\ndutifully\ndutifulness\ndutifulnesses\nduty\nduumvir\nduumvirate\nduumvirates\nduumviri\nduumvirs\nduvet\nduvetine\nduvetines\nduvets\nduvetyn\nduvetyne\nduvetynes\nduvetyns\nduxelles\ndwarf\ndwarfed\ndwarfer\ndwarfest\ndwarfing\ndwarfish\ndwarfishly\ndwarfishness\ndwarfishnesses\ndwarfism\ndwarfisms\ndwarflike\ndwarfness\ndwarfnesses\ndwarfs\ndwarves\ndweeb\ndweebs\ndwell\ndwelled\ndweller\ndwellers\ndwelling\ndwellings\ndwells\ndwelt\ndwindle\ndwindled\ndwindles\ndwindling\ndwine\ndwined\ndwines\ndwining\ndyable\ndyad\ndyadic\ndyadically\ndyadics\ndyads\ndyarchic\ndyarchies\ndyarchy\ndybbuk\ndybbukim\ndybbuks\ndye\ndyeabilities\ndyeability\ndyeable\ndyed\ndyeing\ndyeings\ndyer\ndyers\ndyes\ndyestuff\ndyestuffs\ndyeweed\ndyeweeds\ndyewood\ndyewoods\ndying\ndyings\ndyke\ndyked\ndykes\ndykey\ndyking\ndynamic\ndynamical\ndynamically\ndynamics\ndynamism\ndynamisms\ndynamist\ndynamistic\ndynamists\ndynamite\ndynamited\ndynamiter\ndynamiters\ndynamites\ndynamitic\ndynamiting\ndynamo\ndynamometer\ndynamometers\ndynamometric\ndynamometries\ndynamometry\ndynamos\ndynamotor\ndynamotors\ndynast\ndynastic\ndynastically\ndynasties\ndynasts\ndynasty\ndynatron\ndynatrons\ndyne\ndynein\ndyneins\ndynel\ndynels\ndynes\ndynode\ndynodes\ndysarthria\ndysarthrias\ndyscrasia\ndyscrasias\ndysenteric\ndysenteries\ndysentery\ndysfunction\ndysfunctional\ndysfunctions\ndysgeneses\ndysgenesis\ndysgenic\ndyskinesia\ndyskinesias\ndyskinetic\ndyslexia\ndyslexias\ndyslexic\ndyslexics\ndyslogistic\ndyslogistically\ndysmenorrhea\ndysmenorrheas\ndysmenorrheic\ndyspepsia\ndyspepsias\ndyspepsies\ndyspepsy\ndyspeptic\ndyspeptically\ndyspeptics\ndysphagia\ndysphagias\ndysphasia\ndysphasias\ndysphasic\ndysphasics\ndysphemism\ndysphemisms\ndysphemistic\ndysphonia\ndysphonias\ndysphoria\ndysphorias\ndysphoric\ndysplasia\ndysplasias\ndysplastic\ndyspnea\ndyspneal\ndyspneas\ndyspneic\ndyspnoea\ndyspnoeas\ndyspnoic\ndysprosium\ndysprosiums\ndysrhythmia\ndysrhythmias\ndysrhythmic\ndystaxia\ndystaxias\ndystocia\ndystocias\ndystonia\ndystonias\ndystonic\ndystopia\ndystopian\ndystopias\ndystrophic\ndystrophies\ndystrophy\ndysuria\ndysurias\ndysuric\ndyvour\ndyvours\neach\neager\neagerer\neagerest\neagerly\neagerness\neagernesses\neagers\neagle\neagles\neaglet\neaglets\neagre\neagres\nealdorman\nealdormen\neanling\neanlings\near\nearache\nearaches\neardrop\neardrops\neardrum\neardrums\neared\nearflap\nearflaps\nearful\nearfuls\nearing\nearings\nearl\nearlap\nearlaps\nearldom\nearldoms\nearless\nearlier\nearliest\nearliness\nearlinesses\nearlobe\nearlobes\nearlock\nearlocks\nearls\nearlship\nearlships\nearly\nearlywood\nearlywoods\nearmark\nearmarked\nearmarking\nearmarks\nearmuff\nearmuffs\nearn\nearned\nearner\nearners\nearnest\nearnestly\nearnestness\nearnestnesses\nearnests\nearning\nearnings\nearns\nearphone\nearphones\nearpiece\nearpieces\nearplug\nearplugs\nearring\nearrings\nears\nearshot\nearshots\nearsplitting\nearstone\nearstones\nearth\nearthborn\nearthbound\nearthed\nearthen\nearthenware\nearthenwares\nearthier\nearthiest\nearthily\nearthiness\nearthinesses\nearthing\nearthlier\nearthliest\nearthlight\nearthlights\nearthlike\nearthliness\nearthlinesses\nearthling\nearthlings\nearthly\nearthman\nearthmen\nearthmover\nearthmovers\nearthmoving\nearthmovings\nearthnut\nearthnuts\nearthpea\nearthpeas\nearthquake\nearthquakes\nearthrise\nearthrises\nearths\nearthset\nearthsets\nearthshaker\nearthshakers\nearthshaking\nearthshakingly\nearthshine\nearthshines\nearthstar\nearthstars\nearthward\nearthwards\nearthwork\nearthworks\nearthworm\nearthworms\nearthy\nearwax\nearwaxes\nearwig\nearwigged\nearwigging\nearwigs\nearwitness\nearwitnesses\nearworm\nearworms\nease\neased\neaseful\neasefully\neasel\neasels\neasement\neasements\neases\neasier\neasies\neasiest\neasily\neasiness\neasinesses\neasing\neast\neastbound\neaster\neasterlies\neasterly\neastern\neasterner\neasterners\neasternmost\neasters\neasting\neastings\neasts\neastward\neastwards\neasy\neasygoing\neasygoingness\neasygoingnesses\neat\neatable\neatables\neaten\neater\neateries\neaters\neatery\neath\neating\neatings\neats\neau\neaux\neave\neaved\neaves\neavesdrop\neavesdropped\neavesdropper\neavesdroppers\neavesdropping\neavesdrops\nebb\nebbed\nebbet\nebbets\nebbing\nebbs\nebon\nebonies\nebonise\nebonised\nebonises\nebonising\nebonite\nebonites\nebonize\nebonized\nebonizes\nebonizing\nebons\nebony\nebullience\nebulliences\nebulliencies\nebulliency\nebullient\nebulliently\nebullition\nebullitions\necarte\necartes\necaudate\necbolic\necbolics\neccentric\neccentrically\neccentricities\neccentricity\neccentrics\necchymoses\necchymosis\necchymotic\necclesia\necclesiae\necclesial\necclesiastic\necclesiastical\necclesiastically\necclesiasticism\necclesiasticisms\necclesiastics\necclesiological\necclesiologies\necclesiologist\necclesiologists\necclesiology\neccrine\necdyses\necdysial\necdysiast\necdysiasts\necdysis\necdyson\necdysone\necdysones\necdysons\necesis\necesises\nechard\nechards\neche\neched\nechelle\nechelles\nechelon\necheloned\necheloning\nechelons\neches\necheveria\necheverias\nechidna\nechidnae\nechidnas\nechinacea\nechinaceas\nechinate\neching\nechini\nechinococci\nechinococcoses\nechinococcosis\nechinococcus\nechinoderm\nechinodermatous\nechinoderms\nechinoid\nechinoids\nechinus\nechiuroid\nechiuroids\necho\nechocardiogram\nechocardiograms\nechocardiographer\nechocardiographers\nechocardiographic\nechocardiographies\nechocardiography\nechoed\nechoer\nechoers\nechoes\nechoey\nechogram\nechograms\nechoic\nechoing\nechoism\nechoisms\necholalia\necholalias\necholalic\necholess\necholocation\necholocations\nechos\nechovirus\nechoviruses\neclair\neclaircissement\neclaircissements\neclairs\neclampsia\neclampsias\neclamptic\neclat\neclats\neclectic\neclectically\neclecticism\neclecticisms\neclectics\neclipse\neclipsed\neclipses\neclipsing\neclipsis\neclipsises\necliptic\necliptics\neclogite\neclogites\neclogue\neclogues\neclosion\neclosions\necocatastrophe\necocatastrophes\necocidal\necocide\necocides\necofreak\necofreaks\necologic\necological\necologically\necologies\necologist\necologists\necology\neconobox\neconoboxes\neconometric\neconometrically\neconometrician\neconometricians\neconometrics\neconometrist\neconometrists\neconomic\neconomical\neconomically\neconomics\neconomies\neconomise\neconomised\neconomises\neconomising\neconomist\neconomists\neconomize\neconomized\neconomizer\neconomizers\neconomizes\neconomizing\neconomy\necophysiological\necophysiologies\necophysiology\necospecies\necosphere\necospheres\necosystem\necosystems\necoterrorism\necoterrorisms\necoterrorist\necoterrorists\necotonal\necotone\necotones\necotourism\necotourisms\necotourist\necotourists\necotype\necotypes\necotypic\necraseur\necraseurs\necru\necrus\necstasies\necstasy\necstatic\necstatically\necstatics\nectases\nectasis\nectatic\necthyma\necthymata\nectoderm\nectodermal\nectoderms\nectomere\nectomeres\nectomorph\nectomorphic\nectomorphs\nectoparasite\nectoparasites\nectoparasitic\nectopia\nectopias\nectopic\nectopically\nectoplasm\nectoplasmic\nectoplasms\nectosarc\nectosarcs\nectotherm\nectothermic\nectotherms\nectotrophic\nectozoa\nectozoan\nectozoans\nectozoon\nectypal\nectype\nectypes\necu\necumenic\necumenical\necumenicalism\necumenicalisms\necumenically\necumenicism\necumenicisms\necumenicist\necumenicists\necumenicities\necumenicity\necumenics\necumenism\necumenisms\necumenist\necumenists\necus\neczema\neczemas\neczematous\ned\nedacious\nedacities\nedacity\nedaphic\nedaphically\neddied\neddies\neddo\neddoes\neddy\neddying\nedelweiss\nedelweisses\nedema\nedemas\nedemata\nedematous\nedenic\nedentate\nedentates\nedentulous\nedge\nedged\nedgeless\nedger\nedgers\nedges\nedgeways\nedgewise\nedgier\nedgiest\nedgily\nedginess\nedginesses\nedging\nedgings\nedgy\nedh\nedhs\nedibilities\nedibility\nedible\nedibleness\nediblenesses\nedibles\nedict\nedictal\nedicts\nedification\nedifications\nedifice\nedifices\nedified\nedifier\nedifiers\nedifies\nedify\nedifying\nedile\nediles\nedit\neditable\nedited\nediting\nedition\neditions\neditor\neditorial\neditorialist\neditorialists\neditorialization\neditorializations\neditorialize\neditorialized\neditorializer\neditorializers\neditorializes\neditorializing\neditorially\neditorials\neditors\neditorship\neditorships\neditress\neditresses\nedits\neds\neducabilities\neducability\neducable\neducables\neducate\neducated\neducatedness\neducatednesses\neducates\neducating\neducation\neducational\neducationalist\neducationalists\neducationally\neducationese\neducationeses\neducationist\neducationists\neducations\neducative\neducator\neducators\neduce\neduced\neduces\neducible\neducing\neduct\neduction\neductions\neductive\neductor\neductors\neducts\nedulcorate\nedulcorated\nedulcorates\nedulcorating\nedutainment\nedutainments\neel\neelgrass\neelgrasses\neelier\neeliest\neellike\neelpout\neelpouts\neels\neelworm\neelworms\neely\neerie\neerier\neeriest\neerily\neeriness\neerinesses\neery\nef\neff\neffable\nefface\neffaceable\neffaced\neffacement\neffacements\neffacer\neffacers\neffaces\neffacing\neffect\neffected\neffecter\neffecters\neffecting\neffective\neffectively\neffectiveness\neffectivenesses\neffectives\neffectivities\neffectivity\neffector\neffectors\neffects\neffectual\neffectualities\neffectuality\neffectually\neffectualness\neffectualnesses\neffectuate\neffectuated\neffectuates\neffectuating\neffectuation\neffectuations\neffeminacies\neffeminacy\neffeminate\neffeminately\neffeminates\neffendi\neffendis\nefferent\nefferently\nefferents\neffervesce\neffervesced\neffervescence\neffervescences\neffervescent\neffervescently\neffervesces\neffervescing\neffete\neffetely\neffeteness\neffetenesses\nefficacies\nefficacious\nefficaciously\nefficaciousness\nefficaciousnesses\nefficacities\nefficacity\nefficacy\nefficiencies\nefficiency\nefficient\nefficiently\neffigial\neffigies\neffigy\neffloresce\neffloresced\nefflorescence\nefflorescences\nefflorescent\neffloresces\nefflorescing\neffluence\neffluences\neffluent\neffluents\neffluvia\neffluvium\neffluviums\nefflux\neffluxes\neffluxion\neffluxions\neffort\neffortful\neffortfully\neffortfulness\neffortfulnesses\neffortless\neffortlessly\neffortlessness\neffortlessnesses\nefforts\neffronteries\neffrontery\neffs\neffulge\neffulged\neffulgence\neffulgences\neffulgent\neffulges\neffulging\neffuse\neffused\neffuses\neffusing\neffusion\neffusions\neffusive\neffusively\neffusiveness\neffusivenesses\nefs\neft\nefts\neftsoon\neftsoons\negad\negads\negal\negalitarian\negalitarianism\negalitarianisms\negalitarians\negalite\negalites\neger\negers\negest\negesta\negested\negesting\negestion\negestions\negestive\negests\negg\neggar\neggars\neggbeater\neggbeaters\neggcup\neggcups\negged\negger\neggers\negghead\neggheaded\neggheadedness\neggheadednesses\neggheads\negging\neggless\neggnog\neggnogs\neggplant\neggplants\neggs\neggshell\neggshells\neggy\negis\negises\neglantine\neglantines\neglatere\neglateres\neglomise\nego\negocentric\negocentrically\negocentricities\negocentricity\negocentrics\negocentrism\negocentrisms\negoism\negoisms\negoist\negoistic\negoistical\negoistically\negoists\negoless\negomania\negomaniac\negomaniacal\negomaniacally\negomaniacs\negomanias\negos\negotism\negotisms\negotist\negotistic\negotistical\negotistically\negotists\negregious\negregiously\negregiousness\negregiousnesses\negress\negressed\negresses\negressing\negression\negressions\negret\negrets\negyptian\negyptians\neh\neicosanoid\neicosanoids\neide\neider\neiderdown\neiderdowns\neiders\neidetic\neidetically\neidola\neidolic\neidolon\neidolons\neidos\neigenmode\neigenmodes\neigenvalue\neigenvalues\neigenvector\neigenvectors\neight\neightball\neightballs\neighteen\neighteens\neighteenth\neighteenths\neightfold\neighth\neighthly\neighths\neighties\neightieth\neightieths\neights\neightvo\neightvos\neighty\neikon\neikones\neikons\neinkorn\neinkorns\neinstein\neinsteinium\neinsteiniums\neinsteins\neirenic\neisegeses\neisegesis\neisteddfod\neisteddfodau\neisteddfodic\neisteddfods\neiswein\neisweins\neither\nejaculate\nejaculated\nejaculates\nejaculating\nejaculation\nejaculations\nejaculator\nejaculators\nejaculatory\neject\nejecta\nejectable\nejected\nejecting\nejection\nejections\nejective\nejectives\nejectment\nejectments\nejector\nejectors\nejects\neke\neked\nekes\neking\nekistic\nekistics\nekpwele\nekpweles\nektexine\nektexines\nekuele\nel\nelaborate\nelaborated\nelaborately\nelaborateness\nelaboratenesses\nelaborates\nelaborating\nelaboration\nelaborations\nelaborative\nelain\nelains\nelan\neland\nelands\nelans\nelaphine\nelapid\nelapids\nelapine\nelapse\nelapsed\nelapses\nelapsing\nelasmobranch\nelasmobranchs\nelastase\nelastases\nelastic\nelastically\nelasticities\nelasticity\nelasticized\nelastics\nelastin\nelastins\nelastomer\nelastomeric\nelastomers\nelate\nelated\nelatedly\nelatedness\nelatednesses\nelater\nelaterid\nelaterids\nelaterin\nelaterins\nelaterite\nelaterites\nelaters\nelates\nelating\nelation\nelations\nelative\nelatives\nelbow\nelbowed\nelbowing\nelbowroom\nelbowrooms\nelbows\neld\nelder\nelderberries\nelderberry\nelderlies\nelderliness\nelderlinesses\nelderly\nelders\neldership\nelderships\neldest\neldress\neldresses\neldrich\neldritch\nelds\nelecampane\nelecampanes\nelect\nelectabilities\nelectability\nelectable\nelected\nelectee\nelectees\nelecting\nelection\nelectioneer\nelectioneered\nelectioneerer\nelectioneerers\nelectioneering\nelectioneers\nelections\nelective\nelectively\nelectiveness\nelectivenesses\nelectives\nelector\nelectoral\nelectorally\nelectorate\nelectorates\nelectors\nelectress\nelectresses\nelectret\nelectrets\nelectric\nelectrical\nelectrically\nelectrician\nelectricians\nelectricities\nelectricity\nelectrics\nelectrification\nelectrifications\nelectrified\nelectrifies\nelectrify\nelectrifying\nelectro\nelectroacoustic\nelectroacoustics\nelectroanalyses\nelectroanalysis\nelectroanalytical\nelectrocardiogram\nelectrocardiograms\nelectrocardiograph\nelectrocardiographic\nelectrocardiographically\nelectrocardiographies\nelectrocardiographs\nelectrocardiography\nelectrochemical\nelectrochemically\nelectrochemistries\nelectrochemistry\nelectroconvulsive\nelectrocorticogram\nelectrocorticograms\nelectrocute\nelectrocuted\nelectrocutes\nelectrocuting\nelectrocution\nelectrocutions\nelectrode\nelectrodeposit\nelectrodeposited\nelectrodepositing\nelectrodeposition\nelectrodepositions\nelectrodeposits\nelectrodermal\nelectrodes\nelectrodesiccation\nelectrodesiccations\nelectrodialyses\nelectrodialysis\nelectrodialytic\nelectrodynamic\nelectrodynamics\nelectrodynamometer\nelectrodynamometers\nelectroed\nelectroencephalogram\nelectroencephalograms\nelectroencephalograph\nelectroencephalographer\nelectroencephalographers\nelectroencephalographic\nelectroencephalographically\nelectroencephalographies\nelectroencephalographs\nelectroencephalography\nelectrofishing\nelectrofishings\nelectroform\nelectroformed\nelectroforming\nelectroforms\nelectrogeneses\nelectrogenesis\nelectrogenic\nelectrogram\nelectrograms\nelectrohydraulic\nelectroing\nelectrojet\nelectrojets\nelectrokinetic\nelectrokinetics\nelectroless\nelectrologies\nelectrologist\nelectrologists\nelectrology\nelectroluminescence\nelectroluminescences\nelectroluminescent\nelectrolyses\nelectrolysis\nelectrolyte\nelectrolytes\nelectrolytic\nelectrolytically\nelectrolyze\nelectrolyzed\nelectrolyzes\nelectrolyzing\nelectromagnet\nelectromagnetic\nelectromagnetically\nelectromagnetism\nelectromagnetisms\nelectromagnets\nelectromechanical\nelectromechanically\nelectrometallurgies\nelectrometallurgy\nelectrometer\nelectrometers\nelectromyogram\nelectromyograms\nelectromyograph\nelectromyographic\nelectromyographically\nelectromyographies\nelectromyographs\nelectromyography\nelectron\nelectronegative\nelectronegativities\nelectronegativity\nelectronic\nelectronically\nelectronics\nelectrons\nelectrooculogram\nelectrooculograms\nelectrooculographies\nelectrooculography\nelectroosmoses\nelectroosmosis\nelectroosmotic\nelectropherogram\nelectropherograms\nelectrophile\nelectrophiles\nelectrophilic\nelectrophilicities\nelectrophilicity\nelectrophorese\nelectrophoresed\nelectrophoreses\nelectrophoresing\nelectrophoresis\nelectrophoretic\nelectrophoretically\nelectrophoretogram\nelectrophoretograms\nelectrophori\nelectrophorus\nelectrophotographic\nelectrophotographies\nelectrophotography\nelectrophysiologic\nelectrophysiological\nelectrophysiologically\nelectrophysiologies\nelectrophysiologist\nelectrophysiologists\nelectrophysiology\nelectroplate\nelectroplated\nelectroplates\nelectroplating\nelectropositive\nelectroretinogram\nelectroretinograms\nelectroretinograph\nelectroretinographic\nelectroretinographies\nelectroretinographs\nelectroretinography\nelectros\nelectroscope\nelectroscopes\nelectroshock\nelectroshocks\nelectrostatic\nelectrostatically\nelectrostatics\nelectrosurgeries\nelectrosurgery\nelectrosurgical\nelectrotherapies\nelectrotherapy\nelectrothermal\nelectrothermally\nelectrotonic\nelectrotonically\nelectrotonus\nelectrotonuses\nelectrotype\nelectrotyped\nelectrotyper\nelectrotypers\nelectrotypes\nelectrotyping\nelectroweak\nelectrowinning\nelectrowinnings\nelectrum\nelectrums\nelects\nelectuaries\nelectuary\neledoisin\neledoisins\neleemosynary\nelegance\nelegances\nelegancies\nelegancy\nelegant\nelegantly\nelegiac\nelegiacal\nelegiacally\nelegiacs\nelegies\nelegise\nelegised\nelegises\nelegising\nelegist\nelegists\nelegit\nelegits\nelegize\nelegized\nelegizes\nelegizing\nelegy\nelement\nelemental\nelementally\nelementals\nelementarily\nelementariness\nelementarinesses\nelementary\nelements\nelemi\nelemis\nelenchi\nelenchic\nelenchus\nelenctic\nelephant\nelephantiases\nelephantiasis\nelephantine\nelephants\nelevate\nelevated\nelevateds\nelevates\nelevating\nelevation\nelevations\nelevator\nelevators\neleven\nelevens\nelevenses\neleventh\nelevenths\nelevon\nelevons\nelf\nelfin\nelfins\nelfish\nelfishly\nelflike\nelflock\nelflocks\nelhi\nelicit\nelicitation\nelicitations\nelicited\neliciting\nelicitor\nelicitors\nelicits\nelide\nelided\nelides\nelidible\neliding\neligibilities\neligibility\neligible\neligibles\neligibly\neliminate\neliminated\neliminates\neliminating\nelimination\neliminations\neliminative\neliminator\neliminators\nelint\nelints\nelision\nelisions\nelite\nelites\nelitism\nelitisms\nelitist\nelitists\nelixir\nelixirs\nelk\nelkhound\nelkhounds\nelks\nell\nellipse\nellipses\nellipsis\nellipsoid\nellipsoidal\nellipsoids\nelliptic\nelliptical\nelliptically\nellipticals\nellipticities\nellipticity\nells\nelm\nelmier\nelmiest\nelms\nelmy\nelocution\nelocutionary\nelocutionist\nelocutionists\nelocutions\nelodea\nelodeas\neloign\neloigned\neloigner\neloigners\neloigning\neloigns\neloin\neloined\neloiner\neloiners\neloining\neloins\nelongate\nelongated\nelongates\nelongating\nelongation\nelongations\nelope\neloped\nelopement\nelopements\neloper\nelopers\nelopes\neloping\neloquence\neloquences\neloquent\neloquently\nels\nelse\nelsewhere\neluant\neluants\neluate\neluates\nelucidate\nelucidated\nelucidates\nelucidating\nelucidation\nelucidations\nelucidative\nelucidator\nelucidators\nelucubrate\nelucubrated\nelucubrates\nelucubrating\nelucubration\nelucubrations\nelude\neluded\neluder\neluders\neludes\neluding\neluent\neluents\nelusion\nelusions\nelusive\nelusively\nelusiveness\nelusivenesses\nelusory\nelute\neluted\nelutes\neluting\nelution\nelutions\nelutriate\nelutriated\nelutriates\nelutriating\nelutriation\nelutriations\nelutriator\nelutriators\neluvia\neluvial\neluviate\neluviated\neluviates\neluviating\neluviation\neluviations\neluvium\neluviums\nelver\nelvers\nelves\nelvish\nelvishly\nelysian\nelytra\nelytroid\nelytron\nelytrous\nelytrum\nem\nemaciate\nemaciated\nemaciates\nemaciating\nemaciation\nemaciations\nemail\nemailed\nemailing\nemails\nemalangeni\nemanate\nemanated\nemanates\nemanating\nemanation\nemanations\nemanative\nemanator\nemanators\nemancipate\nemancipated\nemancipates\nemancipating\nemancipation\nemancipationist\nemancipationists\nemancipations\nemancipator\nemancipators\nemarginate\nemargination\nemarginations\nemasculate\nemasculated\nemasculates\nemasculating\nemasculation\nemasculations\nemasculator\nemasculators\nembalm\nembalmed\nembalmer\nembalmers\nembalming\nembalmment\nembalmments\nembalms\nembank\nembanked\nembanking\nembankment\nembankments\nembanks\nembar\nembarcadero\nembarcaderos\nembargo\nembargoed\nembargoes\nembargoing\nembark\nembarkation\nembarkations\nembarked\nembarking\nembarkment\nembarkments\nembarks\nembarrass\nembarrassable\nembarrassed\nembarrassedly\nembarrasses\nembarrassing\nembarrassingly\nembarrassment\nembarrassments\nembarred\nembarring\nembars\nembassage\nembassages\nembassies\nembassy\nembattle\nembattled\nembattlement\nembattlements\nembattles\nembattling\nembay\nembayed\nembaying\nembayment\nembayments\nembays\nembed\nembedded\nembedding\nembeddings\nembedment\nembedments\nembeds\nembellish\nembellished\nembellisher\nembellishers\nembellishes\nembellishing\nembellishment\nembellishments\nember\nembers\nembezzle\nembezzled\nembezzlement\nembezzlements\nembezzler\nembezzlers\nembezzles\nembezzling\nembitter\nembittered\nembittering\nembitterment\nembitterments\nembitters\nemblaze\nemblazed\nemblazer\nemblazers\nemblazes\nemblazing\nemblazon\nemblazoned\nemblazoner\nemblazoners\nemblazoning\nemblazonment\nemblazonments\nemblazonries\nemblazonry\nemblazons\nemblem\nemblematic\nemblematical\nemblematically\nemblematize\nemblematized\nemblematizes\nemblematizing\nemblemed\nemblements\nembleming\nemblems\nembodied\nembodier\nembodiers\nembodies\nembodiment\nembodiments\nembody\nembodying\nembolden\nemboldened\nemboldening\nemboldens\nembolectomies\nembolectomy\nemboli\nembolic\nembolies\nembolism\nembolismic\nembolisms\nembolization\nembolizations\nembolus\nemboly\nembonpoint\nembonpoints\nemborder\nembordered\nembordering\nemborders\nembosk\nembosked\nembosking\nembosks\nembosom\nembosomed\nembosoming\nembosoms\nemboss\nembossable\nembossed\nembosser\nembossers\nembosses\nembossing\nembossment\nembossments\nembouchure\nembouchures\nembourgeoisement\nembourgeoisements\nembow\nembowed\nembowel\nemboweled\nemboweling\nembowelled\nembowelling\nembowels\nembower\nembowered\nembowering\nembowers\nembowing\nembows\nembrace\nembraceable\nembraced\nembracement\nembracements\nembraceor\nembraceors\nembracer\nembraceries\nembracers\nembracery\nembraces\nembracing\nembracingly\nembracive\nembrangle\nembrangled\nembranglement\nembranglements\nembrangles\nembrangling\nembrasure\nembrasures\nembrittle\nembrittled\nembrittlement\nembrittlements\nembrittles\nembrittling\nembrocation\nembrocations\nembroider\nembroidered\nembroiderer\nembroiderers\nembroideries\nembroidering\nembroiders\nembroidery\nembroil\nembroiled\nembroiling\nembroilment\nembroilments\nembroils\nembrown\nembrowned\nembrowning\nembrowns\nembrue\nembrued\nembrues\nembruing\nembrute\nembruted\nembrutes\nembruting\nembryo\nembryogeneses\nembryogenesis\nembryogenetic\nembryogenic\nembryogenies\nembryogeny\nembryoid\nembryoids\nembryological\nembryologically\nembryologies\nembryologist\nembryologists\nembryology\nembryon\nembryonal\nembryonated\nembryonic\nembryonically\nembryons\nembryophyte\nembryophytes\nembryos\nemcee\nemceed\nemceeing\nemcees\neme\nemeer\nemeerate\nemeerates\nemeers\nemend\nemendable\nemendate\nemendated\nemendates\nemendating\nemendation\nemendations\nemended\nemender\nemenders\nemending\nemends\nemerald\nemeralds\nemerge\nemerged\nemergence\nemergences\nemergencies\nemergency\nemergent\nemergents\nemerges\nemerging\nemeries\nemerita\nemeritae\nemeritas\nemeriti\nemeritus\nemerod\nemerods\nemeroid\nemeroids\nemersed\nemersion\nemersions\nemery\nemes\nemeses\nemesis\nemetic\nemetically\nemetics\nemetin\nemetine\nemetines\nemetins\nemeu\nemeus\nemeute\nemeutes\nemf\nemfs\nemic\nemigrant\nemigrants\nemigrate\nemigrated\nemigrates\nemigrating\nemigration\nemigrations\nemigre\nemigres\neminence\neminences\neminencies\neminency\neminent\neminently\nemir\nemirate\nemirates\nemirs\nemissaries\nemissary\nemission\nemissions\nemissive\nemissivities\nemissivity\nemit\nemits\nemittance\nemittances\nemitted\nemitter\nemitters\nemitting\nemmenagogue\nemmenagogues\nemmer\nemmers\nemmet\nemmets\nemodin\nemodins\nemollient\nemollients\nemolument\nemoluments\nemote\nemoted\nemoter\nemoters\nemotes\nemoting\nemotion\nemotional\nemotionalism\nemotionalisms\nemotionalist\nemotionalistic\nemotionalists\nemotionalities\nemotionality\nemotionalize\nemotionalized\nemotionalizes\nemotionalizing\nemotionally\nemotionless\nemotionlessly\nemotionlessness\nemotionlessnesses\nemotions\nemotive\nemotively\nemotivities\nemotivity\nempale\nempaled\nempaler\nempalers\nempales\nempaling\nempanada\nempanadas\nempanel\nempaneled\nempaneling\nempanelled\nempanelling\nempanels\nempathetic\nempathetically\nempathic\nempathically\nempathies\nempathise\nempathised\nempathises\nempathising\nempathize\nempathized\nempathizes\nempathizing\nempathy\nempennage\nempennages\nemperies\nemperor\nemperors\nemperorship\nemperorships\nempery\nemphases\nemphasis\nemphasise\nemphasised\nemphasises\nemphasising\nemphasize\nemphasized\nemphasizes\nemphasizing\nemphatic\nemphatically\nemphysema\nemphysemas\nemphysematous\nemphysemic\nempire\nempires\nempiric\nempirical\nempirically\nempiricism\nempiricisms\nempiricist\nempiricists\nempirics\nemplace\nemplaced\nemplacement\nemplacements\nemplaces\nemplacing\nemplane\nemplaned\nemplanes\nemplaning\nemploy\nemployabilities\nemployability\nemployable\nemployables\nemploye\nemployed\nemployee\nemployees\nemployer\nemployers\nemployes\nemploying\nemployment\nemployments\nemploys\nempoison\nempoisoned\nempoisoning\nempoisonment\nempoisonments\nempoisons\nemporia\nemporium\nemporiums\nempower\nempowered\nempowering\nempowerment\nempowerments\nempowers\nempress\nempressement\nempressements\nempresses\nemprise\nemprises\nemprize\nemprizes\nemptied\nemptier\nemptiers\nempties\nemptiest\nemptily\nemptiness\nemptinesses\nemptings\nemptins\nempty\nemptying\nempurple\nempurpled\nempurples\nempurpling\nempyema\nempyemas\nempyemata\nempyemic\nempyreal\nempyrean\nempyreans\nems\nemu\nemulate\nemulated\nemulates\nemulating\nemulation\nemulations\nemulative\nemulatively\nemulator\nemulators\nemulous\nemulously\nemulousness\nemulousnesses\nemulsifiable\nemulsification\nemulsifications\nemulsified\nemulsifier\nemulsifiers\nemulsifies\nemulsify\nemulsifying\nemulsion\nemulsions\nemulsive\nemulsoid\nemulsoidal\nemulsoids\nemus\nemyd\nemyde\nemydes\nemyds\nen\nenable\nenabled\nenabler\nenablers\nenables\nenabling\nenact\nenacted\nenacting\nenactive\nenactment\nenactments\nenactor\nenactors\nenactory\nenacts\nenamel\nenameled\nenameler\nenamelers\nenameling\nenamelist\nenamelists\nenamelled\nenamelling\nenamels\nenamelware\nenamelwares\nenamine\nenamines\nenamor\nenamoration\nenamorations\nenamored\nenamoring\nenamors\nenamour\nenamoured\nenamouring\nenamours\nenantiomer\nenantiomeric\nenantiomers\nenantiomorph\nenantiomorphic\nenantiomorphism\nenantiomorphisms\nenantiomorphous\nenantiomorphs\nenate\nenates\nenatic\nenation\nenations\nencaenia\nencage\nencaged\nencages\nencaging\nencamp\nencamped\nencamping\nencampment\nencampments\nencamps\nencapsulate\nencapsulated\nencapsulates\nencapsulating\nencapsulation\nencapsulations\nencapsule\nencapsuled\nencapsules\nencapsuling\nencase\nencased\nencasement\nencasements\nencases\nencash\nencashable\nencashed\nencashes\nencashing\nencashment\nencashments\nencasing\nencaustic\nencaustics\nenceinte\nenceintes\nencephala\nencephalitic\nencephalitides\nencephalitis\nencephalitogen\nencephalitogenic\nencephalitogens\nencephalogram\nencephalograms\nencephalograph\nencephalographies\nencephalographs\nencephalography\nencephalomyelitides\nencephalomyelitis\nencephalomyocarditis\nencephalomyocarditises\nencephalon\nencephalopathic\nencephalopathies\nencephalopathy\nenchain\nenchained\nenchaining\nenchainment\nenchainments\nenchains\nenchant\nenchanted\nenchanter\nenchanters\nenchanting\nenchantingly\nenchantment\nenchantments\nenchantress\nenchantresses\nenchants\nenchase\nenchased\nenchaser\nenchasers\nenchases\nenchasing\nenchilada\nenchiladas\nenchiridia\nenchiridion\nenchiridions\nenchoric\nencina\nencinal\nencinas\nencipher\nenciphered\nencipherer\nencipherers\nenciphering\nencipherment\nencipherments\nenciphers\nencircle\nencircled\nencirclement\nencirclements\nencircles\nencircling\nenclasp\nenclasped\nenclasping\nenclasps\nenclave\nenclaves\nenclitic\nenclitics\nenclose\nenclosed\nencloser\nenclosers\nencloses\nenclosing\nenclosure\nenclosures\nencode\nencoded\nencoder\nencoders\nencodes\nencoding\nencomia\nencomiast\nencomiastic\nencomiasts\nencomium\nencomiums\nencompass\nencompassed\nencompasses\nencompassing\nencompassment\nencompassments\nencore\nencored\nencores\nencoring\nencounter\nencountered\nencountering\nencounters\nencourage\nencouraged\nencouragement\nencouragements\nencourager\nencouragers\nencourages\nencouraging\nencouragingly\nencrimson\nencrimsoned\nencrimsoning\nencrimsons\nencroach\nencroached\nencroacher\nencroachers\nencroaches\nencroaching\nencroachment\nencroachments\nencrust\nencrustation\nencrustations\nencrusted\nencrusting\nencrusts\nencrypt\nencrypted\nencrypting\nencryption\nencryptions\nencrypts\nencumber\nencumbered\nencumbering\nencumbers\nencumbrance\nencumbrancer\nencumbrancers\nencumbrances\nencyclic\nencyclical\nencyclicals\nencyclics\nencyclopaedia\nencyclopaedias\nencyclopaedic\nencyclopedia\nencyclopedias\nencyclopedic\nencyclopedically\nencyclopedism\nencyclopedisms\nencyclopedist\nencyclopedists\nencyst\nencysted\nencysting\nencystment\nencystments\nencysts\nend\nendamage\nendamaged\nendamages\nendamaging\nendameba\nendamebae\nendamebas\nendamoeba\nendamoebae\nendamoebas\nendanger\nendangered\nendangering\nendangerment\nendangerments\nendangers\nendarch\nendarchies\nendarchy\nendarterectomies\nendarterectomy\nendbrain\nendbrains\nendear\nendeared\nendearing\nendearingly\nendearment\nendearments\nendears\nendeavor\nendeavored\nendeavoring\nendeavors\nendeavour\nendeavoured\nendeavouring\nendeavours\nended\nendemial\nendemic\nendemically\nendemicities\nendemicity\nendemics\nendemism\nendemisms\nender\nendergonic\nendermic\nenders\nendexine\nendexines\nendgame\nendgames\nending\nendings\nendite\nendited\nendites\nenditing\nendive\nendives\nendleaf\nendleaves\nendless\nendlessly\nendlessness\nendlessnesses\nendlong\nendmost\nendnote\nendnotes\nendobiotic\nendocardia\nendocardial\nendocarditis\nendocarditises\nendocardium\nendocarp\nendocarps\nendocast\nendocasts\nendochondral\nendocrine\nendocrines\nendocrinologic\nendocrinological\nendocrinologies\nendocrinologist\nendocrinologists\nendocrinology\nendocytoses\nendocytosis\nendocytotic\nendoderm\nendodermal\nendodermis\nendodermises\nendoderms\nendodontic\nendodontically\nendodontics\nendodontist\nendodontists\nendoenzyme\nendoenzymes\nendoergic\nendogamies\nendogamous\nendogamy\nendogen\nendogenic\nendogenies\nendogenous\nendogenously\nendogens\nendogeny\nendolithic\nendolymph\nendolymphatic\nendolymphs\nendometria\nendometrial\nendometrioses\nendometriosis\nendometritis\nendometritises\nendometrium\nendomitoses\nendomitosis\nendomitotic\nendomixis\nendomixises\nendomorph\nendomorphic\nendomorphies\nendomorphism\nendomorphisms\nendomorphs\nendomorphy\nendonuclease\nendonucleases\nendonucleolytic\nendoparasite\nendoparasites\nendoparasitic\nendoparasitism\nendoparasitisms\nendopeptidase\nendopeptidases\nendoperoxide\nendoperoxides\nendophyte\nendophytes\nendophytic\nendoplasm\nendoplasmic\nendoplasms\nendopod\nendopodite\nendopodites\nendopods\nendopolyploid\nendopolyploidies\nendopolyploidy\nendorphin\nendorphins\nendorsable\nendorse\nendorsed\nendorsee\nendorsees\nendorsement\nendorsements\nendorser\nendorsers\nendorses\nendorsing\nendorsor\nendorsors\nendosarc\nendosarcs\nendoscope\nendoscopes\nendoscopic\nendoscopically\nendoscopies\nendoscopy\nendoskeletal\nendoskeleton\nendoskeletons\nendosmos\nendosmoses\nendosome\nendosomes\nendosperm\nendosperms\nendospore\nendospores\nendostea\nendosteal\nendosteally\nendosteum\nendostyle\nendostyles\nendosulfan\nendosulfans\nendosymbiont\nendosymbionts\nendosymbioses\nendosymbiosis\nendosymbiotic\nendothecia\nendothecium\nendothelia\nendothelial\nendothelioma\nendotheliomas\nendotheliomata\nendothelium\nendotherm\nendothermic\nendothermies\nendotherms\nendothermy\nendotoxic\nendotoxin\nendotoxins\nendotracheal\nendotrophic\nendow\nendowed\nendower\nendowers\nendowing\nendowment\nendowments\nendows\nendozoic\nendpaper\nendpapers\nendplate\nendplates\nendpoint\nendpoints\nendrin\nendrins\nends\nendue\nendued\nendues\nenduing\nendurable\nendurably\nendurance\nendurances\nendure\nendured\nendures\nenduring\nenduringly\nenduringness\nenduringnesses\nenduro\nenduros\nendways\nendwise\nenema\nenemas\nenemata\nenemies\nenemy\nenergetic\nenergetically\nenergetics\nenergid\nenergids\nenergies\nenergise\nenergised\nenergises\nenergising\nenergization\nenergizations\nenergize\nenergized\nenergizer\nenergizers\nenergizes\nenergizing\nenergy\nenervate\nenervated\nenervates\nenervating\nenervation\nenervations\nenface\nenfaced\nenfaces\nenfacing\nenfeeble\nenfeebled\nenfeeblement\nenfeeblements\nenfeebles\nenfeebling\nenfeoff\nenfeoffed\nenfeoffing\nenfeoffment\nenfeoffments\nenfeoffs\nenfetter\nenfettered\nenfettering\nenfetters\nenfever\nenfevered\nenfevering\nenfevers\nenfilade\nenfiladed\nenfilades\nenfilading\nenflame\nenflamed\nenflames\nenflaming\nenfleurage\nenfleurages\nenfold\nenfolded\nenfolder\nenfolders\nenfolding\nenfolds\nenforce\nenforceabilities\nenforceability\nenforceable\nenforced\nenforcement\nenforcements\nenforcer\nenforcers\nenforces\nenforcing\nenframe\nenframed\nenframement\nenframements\nenframes\nenframing\nenfranchise\nenfranchised\nenfranchisement\nenfranchisements\nenfranchises\nenfranchising\neng\nengage\nengaged\nengagement\nengagements\nengager\nengagers\nengages\nengaging\nengagingly\nengarland\nengarlanded\nengarlanding\nengarlands\nengender\nengendered\nengendering\nengenders\nengild\nengilded\nengilding\nengilds\nengine\nengined\nengineer\nengineered\nengineering\nengineerings\nengineers\nengineries\nenginery\nengines\nengining\nenginous\nengird\nengirded\nengirding\nengirdle\nengirdled\nengirdles\nengirdling\nengirds\nengirt\nenglish\nenglished\nenglishes\nenglishing\nenglobe\nenglobed\nenglobes\nenglobing\nenglut\nengluts\nenglutted\nenglutting\nengorge\nengorged\nengorgement\nengorgements\nengorges\nengorging\nengraft\nengrafted\nengrafting\nengraftment\nengraftments\nengrafts\nengrail\nengrailed\nengrailing\nengrails\nengrain\nengrained\nengraining\nengrains\nengram\nengramme\nengrammes\nengrams\nengrave\nengraved\nengraver\nengravers\nengraves\nengraving\nengravings\nengross\nengrossed\nengrosser\nengrossers\nengrosses\nengrossing\nengrossingly\nengrossment\nengrossments\nengs\nengulf\nengulfed\nengulfing\nengulfment\nengulfments\nengulfs\nenhalo\nenhaloed\nenhaloes\nenhaloing\nenhalos\nenhance\nenhanced\nenhancement\nenhancements\nenhancer\nenhancers\nenhances\nenhancing\nenharmonic\nenharmonically\nenigma\nenigmas\nenigmata\nenigmatic\nenigmatical\nenigmatically\nenisle\nenisled\nenisles\nenisling\nenjambed\nenjambement\nenjambements\nenjambment\nenjambments\nenjoin\nenjoined\nenjoiner\nenjoiners\nenjoining\nenjoins\nenjoy\nenjoyable\nenjoyableness\nenjoyablenesses\nenjoyably\nenjoyed\nenjoyer\nenjoyers\nenjoying\nenjoyment\nenjoyments\nenjoys\nenkephalin\nenkephalins\nenkindle\nenkindled\nenkindles\nenkindling\nenlace\nenlaced\nenlacement\nenlacements\nenlaces\nenlacing\nenlarge\nenlargeable\nenlarged\nenlargement\nenlargements\nenlarger\nenlargers\nenlarges\nenlarging\nenlighten\nenlightened\nenlightening\nenlightenment\nenlightenments\nenlightens\nenlist\nenlisted\nenlistee\nenlistees\nenlister\nenlisters\nenlisting\nenlistment\nenlistments\nenlists\nenliven\nenlivened\nenlivening\nenlivens\nenmesh\nenmeshed\nenmeshes\nenmeshing\nenmeshment\nenmeshments\nenmities\nenmity\nennead\nenneadic\nenneads\nenneagon\nenneagons\nennoble\nennobled\nennoblement\nennoblements\nennobler\nennoblers\nennobles\nennobling\nennui\nennuis\nennuye\nennuyee\nenoki\nenokidake\nenokidakes\nenokis\nenol\nenolase\nenolases\nenolic\nenological\nenologies\nenologist\nenologists\nenology\nenols\nenorm\nenormities\nenormity\nenormous\nenormously\nenormousness\nenormousnesses\nenosis\nenosises\nenough\nenoughs\nenounce\nenounced\nenounces\nenouncing\nenow\nenows\nenplane\nenplaned\nenplanes\nenplaning\nenquire\nenquired\nenquires\nenquiries\nenquiring\nenquiry\nenrage\nenraged\nenrages\nenraging\nenrapt\nenrapture\nenraptured\nenraptures\nenrapturing\nenravish\nenravished\nenravishes\nenravishing\nenregister\nenregistered\nenregistering\nenregisters\nenrich\nenriched\nenricher\nenrichers\nenriches\nenriching\nenrichment\nenrichments\nenrobe\nenrobed\nenrober\nenrobers\nenrobes\nenrobing\nenrol\nenroll\nenrolled\nenrollee\nenrollees\nenroller\nenrollers\nenrolling\nenrollment\nenrollments\nenrolls\nenrolment\nenrolments\nenrols\nenroot\nenrooted\nenrooting\nenroots\nens\nensample\nensamples\nensanguine\nensanguined\nensanguines\nensanguining\nensconce\nensconced\nensconces\nensconcing\nenscroll\nenscrolled\nenscrolling\nenscrolls\nensemble\nensembles\nenserf\nenserfed\nenserfing\nenserfment\nenserfments\nenserfs\nensheath\nensheathe\nensheathed\nensheathes\nensheathing\nensheaths\nenshrine\nenshrined\nenshrinee\nenshrinees\nenshrinement\nenshrinements\nenshrines\nenshrining\nenshroud\nenshrouded\nenshrouding\nenshrouds\nensiform\nensign\nensigncies\nensigncy\nensigns\nensilage\nensilaged\nensilages\nensilaging\nensile\nensiled\nensiles\nensiling\nenskied\nenskies\nensky\nenskyed\nenskying\nenslave\nenslaved\nenslavement\nenslavements\nenslaver\nenslavers\nenslaves\nenslaving\nensnare\nensnared\nensnarer\nensnarers\nensnares\nensnaring\nensnarl\nensnarled\nensnarling\nensnarls\nensorcel\nensorceled\nensorceling\nensorcell\nensorcelled\nensorcelling\nensorcellment\nensorcellments\nensorcells\nensorcels\nensoul\nensouled\nensouling\nensouls\nensphere\nensphered\nenspheres\nensphering\nensue\nensued\nensues\nensuing\nensure\nensured\nensurer\nensurers\nensures\nensuring\nenswathe\nenswathed\nenswathes\nenswathing\nentablature\nentablatures\nentail\nentailed\nentailer\nentailers\nentailing\nentailment\nentailments\nentails\nentameba\nentamebae\nentamebas\nentamoeba\nentamoebae\nentamoebas\nentangle\nentangled\nentanglement\nentanglements\nentangler\nentanglers\nentangles\nentangling\nentases\nentasia\nentasias\nentasis\nentastic\nentelechies\nentelechy\nentellus\nentelluses\nentente\nententes\nenter\nentera\nenterable\nenteral\nenterally\nentered\nenterer\nenterers\nenteric\nentering\nenteritides\nenteritis\nenteritises\nenterobacteria\nenterobacterial\nenterobacterium\nenterobiases\nenterobiasis\nenterochromaffin\nenterococcal\nenterococci\nenterococcus\nenterocoel\nenterocoele\nenterocoeles\nenterocoelic\nenterocoelous\nenterocoels\nenterocolitis\nenterocolitises\nenterogastrone\nenterogastrones\nenterokinase\nenterokinases\nenteron\nenterons\nenteropathies\nenteropathogenic\nenteropathy\nenterostomal\nenterostomies\nenterostomy\nenterotoxin\nenterotoxins\nenteroviral\nenterovirus\nenteroviruses\nenterprise\nenterpriser\nenterprisers\nenterprises\nenterprising\nenters\nentertain\nentertained\nentertainer\nentertainers\nentertaining\nentertainingly\nentertainment\nentertainments\nentertains\nenthalpies\nenthalpy\nenthetic\nenthral\nenthrall\nenthralled\nenthralling\nenthrallment\nenthrallments\nenthralls\nenthrals\nenthrone\nenthroned\nenthronement\nenthronements\nenthrones\nenthroning\nenthuse\nenthused\nenthuses\nenthusiasm\nenthusiasms\nenthusiast\nenthusiastic\nenthusiastically\nenthusiasts\nenthusing\nenthymeme\nenthymemes\nentia\nentice\nenticed\nenticement\nenticements\nenticer\nenticers\nentices\nenticing\nenticingly\nentire\nentirely\nentireness\nentirenesses\nentires\nentireties\nentirety\nentities\nentitle\nentitled\nentitlement\nentitlements\nentitles\nentitling\nentity\nentoderm\nentodermal\nentodermic\nentoderms\nentoil\nentoiled\nentoiling\nentoils\nentomb\nentombed\nentombing\nentombment\nentombments\nentombs\nentomofauna\nentomofaunae\nentomofaunas\nentomological\nentomologically\nentomologies\nentomologist\nentomologists\nentomology\nentomophagous\nentomophilies\nentomophilous\nentomophily\nentopic\nentoproct\nentoprocts\nentourage\nentourages\nentozoa\nentozoal\nentozoan\nentozoans\nentozoic\nentozoon\nentrails\nentrain\nentrained\nentrainer\nentrainers\nentraining\nentrainment\nentrainments\nentrains\nentrance\nentranced\nentrancement\nentrancements\nentrances\nentranceway\nentranceways\nentrancing\nentrant\nentrants\nentrap\nentrapment\nentrapments\nentrapped\nentrapping\nentraps\nentreat\nentreated\nentreaties\nentreating\nentreatingly\nentreatment\nentreatments\nentreats\nentreaty\nentrechat\nentrechats\nentrecote\nentrecotes\nentree\nentrees\nentremets\nentrench\nentrenched\nentrenches\nentrenching\nentrenchment\nentrenchments\nentrepot\nentrepots\nentrepreneur\nentrepreneurial\nentrepreneurialism\nentrepreneurialisms\nentrepreneurially\nentrepreneurs\nentrepreneurship\nentrepreneurships\nentresol\nentresols\nentries\nentropic\nentropically\nentropies\nentropion\nentropions\nentropy\nentrust\nentrusted\nentrusting\nentrustment\nentrustments\nentrusts\nentry\nentryway\nentryways\nentwine\nentwined\nentwines\nentwining\nentwist\nentwisted\nentwisting\nentwists\nenucleate\nenucleated\nenucleates\nenucleating\nenucleation\nenucleations\nenumerabilities\nenumerability\nenumerable\nenumerate\nenumerated\nenumerates\nenumerating\nenumeration\nenumerations\nenumerative\nenumerator\nenumerators\nenunciable\nenunciate\nenunciated\nenunciates\nenunciating\nenunciation\nenunciations\nenunciator\nenunciators\nenure\nenured\nenures\nenureses\nenuresis\nenuresises\nenuretic\nenuretics\nenuring\nenvelop\nenvelope\nenveloped\nenvelopes\nenveloping\nenvelopment\nenvelopments\nenvelops\nenvenom\nenvenomed\nenvenoming\nenvenomization\nenvenomizations\nenvenoms\nenviable\nenviableness\nenviablenesses\nenviably\nenvied\nenvier\nenviers\nenvies\nenvious\nenviously\nenviousness\nenviousnesses\nenviron\nenvironed\nenvironing\nenvironment\nenvironmental\nenvironmentalism\nenvironmentalisms\nenvironmentalist\nenvironmentalists\nenvironmentally\nenvironments\nenvirons\nenvisage\nenvisaged\nenvisages\nenvisaging\nenvision\nenvisioned\nenvisioning\nenvisions\nenvoi\nenvois\nenvoy\nenvoys\nenvy\nenvying\nenvyingly\nenwheel\nenwheeled\nenwheeling\nenwheels\nenwind\nenwinding\nenwinds\nenwomb\nenwombed\nenwombing\nenwombs\nenwound\nenwrap\nenwrapped\nenwrapping\nenwraps\nenwreathe\nenwreathed\nenwreathes\nenwreathing\nenzootic\nenzootics\nenzym\nenzymatic\nenzymatically\nenzyme\nenzymes\nenzymic\nenzymically\nenzymologies\nenzymologist\nenzymologists\nenzymology\nenzyms\neobiont\neobionts\neohippus\neohippuses\neolian\neolipile\neolipiles\neolith\neolithic\neoliths\neolopile\neolopiles\neon\neonian\neonism\neonisms\neons\neosin\neosine\neosines\neosinic\neosinophil\neosinophilia\neosinophilias\neosinophilic\neosinophils\neosins\nepact\nepacts\neparch\neparchies\neparchs\neparchy\nepaulet\nepaulets\nepaulette\nepauletted\nepaulettes\nepazote\nepazotes\nepee\nepeeist\nepeeists\nepees\nepeiric\nepeirogenic\nepeirogenically\nepeirogenies\nepeirogeny\nependyma\nependymas\nepentheses\nepenthesis\nepenthetic\nepergne\nepergnes\nepexegeses\nepexegesis\nepexegetic\nepexegetical\nepexegetically\nepha\nephah\nephahs\nephas\nephebe\nephebes\nephebi\nephebic\nepheboi\nephebos\nephebus\nephedra\nephedras\nephedrin\nephedrine\nephedrines\nephedrins\nephemera\nephemerae\nephemeral\nephemeralities\nephemerality\nephemerally\nephemerals\nephemeras\nephemerid\nephemerides\nephemerids\nephemeris\nephemeron\nephod\nephods\nephor\nephoral\nephorate\nephorates\nephori\nephors\nepiblast\nepiblastic\nepiblasts\nepibolic\nepibolies\nepiboly\nepic\nepical\nepically\nepicalyces\nepicalyx\nepicalyxes\nepicardia\nepicardial\nepicardium\nepicarp\nepicarps\nepicedia\nepicedium\nepicene\nepicenes\nepicenism\nepicenisms\nepicenter\nepicenters\nepicentral\nepichlorohydrin\nepichlorohydrins\nepiclike\nepicontinental\nepicotyl\nepicotyls\nepicritic\nepics\nepicure\nepicurean\nepicureanism\nepicureanisms\nepicureans\nepicures\nepicurism\nepicurisms\nepicuticle\nepicuticles\nepicuticular\nepicycle\nepicycles\nepicyclic\nepicycloid\nepicycloidal\nepicycloids\nepidemic\nepidemical\nepidemically\nepidemicities\nepidemicity\nepidemics\nepidemiologic\nepidemiological\nepidemiologically\nepidemiologies\nepidemiologist\nepidemiologists\nepidemiology\nepidendrum\nepidendrums\nepiderm\nepidermal\nepidermic\nepidermis\nepidermises\nepidermoid\nepiderms\nepidiascope\nepidiascopes\nepididymal\nepididymides\nepididymis\nepididymitis\nepididymitises\nepidote\nepidotes\nepidotic\nepidural\nepifauna\nepifaunae\nepifaunal\nepifaunas\nepifocal\nepigastric\nepigeal\nepigean\nepigeic\nepigene\nepigeneses\nepigenesis\nepigenetic\nepigenetically\nepigenic\nepigeous\nepiglottal\nepiglottic\nepiglottides\nepiglottis\nepiglottises\nepigon\nepigone\nepigones\nepigoni\nepigonic\nepigonism\nepigonisms\nepigonous\nepigons\nepigonus\nepigram\nepigrammatic\nepigrammatically\nepigrammatism\nepigrammatisms\nepigrammatist\nepigrammatists\nepigrammatize\nepigrammatized\nepigrammatizer\nepigrammatizers\nepigrammatizes\nepigrammatizing\nepigrams\nepigraph\nepigrapher\nepigraphers\nepigraphic\nepigraphical\nepigraphically\nepigraphies\nepigraphist\nepigraphists\nepigraphs\nepigraphy\nepigynies\nepigynous\nepigyny\nepilation\nepilations\nepilepsies\nepilepsy\nepileptic\nepileptically\nepileptics\nepileptiform\nepileptogenic\nepileptoid\nepilimnion\nepilimnions\nepilog\nepilogs\nepilogue\nepilogued\nepilogues\nepiloguing\nepimer\nepimerase\nepimerases\nepimere\nepimeres\nepimeric\nepimers\nepimysia\nepimysium\nepinaoi\nepinaos\nepinasties\nepinasty\nepinephrin\nepinephrine\nepinephrines\nepinephrins\nepineuria\nepineurium\nepineuriums\nepipelagic\nepiphanic\nepiphanies\nepiphanous\nepiphany\nepiphenomena\nepiphenomenal\nepiphenomenalism\nepiphenomenalisms\nepiphenomenally\nepiphenomenon\nepiphragm\nepiphragms\nepiphyseal\nepiphyses\nepiphysial\nepiphysis\nepiphyte\nepiphytes\nepiphytic\nepiphytically\nepiphytism\nepiphytisms\nepiphytologies\nepiphytology\nepiphytotic\nepiphytotics\nepiscia\nepiscias\nepiscopacies\nepiscopacy\nepiscopal\nepiscopally\nepiscopate\nepiscopates\nepiscope\nepiscopes\nepisiotomies\nepisiotomy\nepisode\nepisodes\nepisodic\nepisodical\nepisodically\nepisomal\nepisomally\nepisome\nepisomes\nepistases\nepistasies\nepistasis\nepistasy\nepistatic\nepistaxes\nepistaxis\nepistemic\nepistemically\nepistemological\nepistemologically\nepistemologies\nepistemologist\nepistemologists\nepistemology\nepistle\nepistler\nepistlers\nepistles\nepistolaries\nepistolary\nepistoler\nepistolers\nepistome\nepistomes\nepistrophe\nepistrophes\nepistyle\nepistyles\nepitaph\nepitaphial\nepitaphic\nepitaphs\nepitases\nepitasis\nepitaxial\nepitaxially\nepitaxic\nepitaxies\nepitaxy\nepithalamia\nepithalamic\nepithalamion\nepithalamium\nepithalamiums\nepithelia\nepithelial\nepithelialization\nepithelializations\nepithelialize\nepithelialized\nepithelializes\nepithelializing\nepithelioid\nepithelioma\nepitheliomas\nepitheliomata\nepitheliomatous\nepithelium\nepitheliums\nepithelization\nepithelizations\nepithelize\nepithelized\nepithelizes\nepithelizing\nepithet\nepithetic\nepithetical\nepithets\nepitome\nepitomes\nepitomic\nepitomical\nepitomise\nepitomised\nepitomises\nepitomising\nepitomize\nepitomized\nepitomizes\nepitomizing\nepitope\nepitopes\nepizoa\nepizoic\nepizoism\nepizoisms\nepizoite\nepizoites\nepizoon\nepizootic\nepizootics\nepizooties\nepizootiologic\nepizootiological\nepizootiologies\nepizootiology\nepizooty\nepoch\nepochal\nepochally\nepochs\nepode\nepodes\neponym\neponymic\neponymies\neponymous\neponyms\neponymy\nepopee\nepopees\nepopoeia\nepopoeias\nepos\neposes\nepoxidation\nepoxidations\nepoxide\nepoxides\nepoxidize\nepoxidized\nepoxidizes\nepoxidizing\nepoxied\nepoxies\nepoxy\nepoxyed\nepoxying\nepsilon\nepsilonic\nepsilons\nequabilities\nequability\nequable\nequableness\nequablenesses\nequably\nequal\nequaled\nequaling\nequalise\nequalised\nequaliser\nequalisers\nequalises\nequalising\nequalitarian\nequalitarianism\nequalitarianisms\nequalitarians\nequalities\nequality\nequalization\nequalizations\nequalize\nequalized\nequalizer\nequalizers\nequalizes\nequalizing\nequalled\nequalling\nequally\nequals\nequanimities\nequanimity\nequate\nequated\nequates\nequating\nequation\nequational\nequationally\nequations\nequator\nequatorial\nequators\nequatorward\nequerries\nequerry\nequestrian\nequestrians\nequestrienne\nequestriennes\nequiangular\nequicaloric\nequid\nequidistant\nequidistantly\nequids\nequilateral\nequilibrant\nequilibrants\nequilibrate\nequilibrated\nequilibrates\nequilibrating\nequilibration\nequilibrations\nequilibrator\nequilibrators\nequilibratory\nequilibria\nequilibrist\nequilibristic\nequilibrists\nequilibrium\nequilibriums\nequimolar\nequine\nequinely\nequines\nequinities\nequinity\nequinoctial\nequinoctials\nequinox\nequinoxes\nequip\nequipage\nequipages\nequipment\nequipments\nequipoise\nequipoised\nequipoises\nequipoising\nequipollence\nequipollences\nequipollent\nequipollently\nequipollents\nequiponderant\nequipotential\nequipped\nequipper\nequippers\nequipping\nequiprobable\nequips\nequiseta\nequisetum\nequisetums\nequitabilities\nequitability\nequitable\nequitableness\nequitablenesses\nequitably\nequitant\nequitation\nequitations\nequites\nequities\nequity\nequivalence\nequivalences\nequivalencies\nequivalency\nequivalent\nequivalently\nequivalents\nequivocal\nequivocalities\nequivocality\nequivocally\nequivocalness\nequivocalnesses\nequivocate\nequivocated\nequivocates\nequivocating\nequivocation\nequivocations\nequivocator\nequivocators\nequivoke\nequivokes\nequivoque\nequivoques\ner\nera\neradiate\neradiated\neradiates\neradiating\neradicable\neradicate\neradicated\neradicates\neradicating\neradication\neradications\neradicator\neradicators\neras\nerasabilities\nerasability\nerasable\nerase\nerased\neraser\nerasers\nerases\nerasing\nerasion\nerasions\nerasure\nerasures\nerbium\nerbiums\nere\nerect\nerectable\nerected\nerecter\nerecters\nerectile\nerectilities\nerectility\nerecting\nerection\nerections\nerective\nerectly\nerectness\nerectnesses\nerector\nerectors\nerects\nerelong\neremite\neremites\neremitic\neremitical\neremitism\neremitisms\neremuri\neremurus\nerenow\nerepsin\nerepsins\nerethic\nerethism\nerethisms\nerewhile\nerewhiles\nerg\nergastic\nergastoplasm\nergastoplasmic\nergastoplasms\nergate\nergates\nergative\nergo\nergodic\nergodicities\nergodicity\nergograph\nergographs\nergometer\nergometers\nergometric\nergonomic\nergonomically\nergonomics\nergonomist\nergonomists\nergonovine\nergonovines\nergosterol\nergosterols\nergot\nergotamine\nergotamines\nergotic\nergotism\nergotisms\nergotized\nergots\nergs\nerica\nericaceous\nericas\nericoid\nerigeron\nerigerons\neringo\neringoes\neringos\neriophyid\neriophyids\neristic\neristical\neristically\neristics\nerlking\nerlkings\nermine\nermined\nermines\nern\nerne\nernes\nerns\nerode\neroded\nerodent\nerodes\nerodibilities\nerodibility\nerodible\neroding\nerogenic\nerogenous\neros\nerose\nerosely\neroses\nerosible\nerosion\nerosional\nerosionally\nerosions\nerosive\nerosiveness\nerosivenesses\nerosivities\nerosivity\nerotic\nerotica\nerotical\nerotically\neroticism\neroticisms\neroticist\neroticists\neroticization\neroticizations\neroticize\neroticized\neroticizes\neroticizing\nerotics\nerotism\nerotisms\nerotization\nerotizations\nerotize\nerotized\nerotizes\nerotizing\nerotogenic\nerr\nerrancies\nerrancy\nerrand\nerrands\nerrant\nerrantly\nerrantries\nerrantry\nerrants\nerrata\nerratas\nerratic\nerratical\nerratically\nerraticism\nerraticisms\nerratics\nerratum\nerred\nerrhine\nerrhines\nerring\nerringly\nerroneous\nerroneously\nerroneousness\nerroneousnesses\nerror\nerrorless\nerrors\nerrs\ners\nersatz\nersatzes\nerses\nerst\nerstwhile\neruct\neructate\neructated\neructates\neructating\neructation\neructations\neructed\neructing\neructs\nerudite\neruditely\nerudition\neruditions\nerugo\nerugos\nerumpent\nerupt\nerupted\neruptible\nerupting\neruption\neruptions\neruptive\neruptively\neruptives\nerupts\nervil\nervils\neryngo\neryngoes\neryngos\nerysipelas\nerysipelases\nerythema\nerythemas\nerythematous\nerythorbate\nerythorbates\nerythremia\nerythremias\nerythrism\nerythrismal\nerythrisms\nerythristic\nerythrite\nerythrites\nerythroblast\nerythroblastic\nerythroblastoses\nerythroblastosis\nerythroblasts\nerythrocyte\nerythrocytes\nerythrocytic\nerythroid\nerythromycin\nerythromycins\nerythron\nerythrons\nerythropoieses\nerythropoiesis\nerythropoietic\nerythropoietin\nerythropoietins\nerythrosin\nerythrosine\nerythrosines\nerythrosins\nes\nescadrille\nescadrilles\nescalade\nescaladed\nescalader\nescaladers\nescalades\nescalading\nescalate\nescalated\nescalates\nescalating\nescalation\nescalations\nescalator\nescalators\nescalatory\nescallop\nescalloped\nescalloping\nescallops\nescalop\nescaloped\nescaloping\nescalops\nescapade\nescapades\nescape\nescaped\nescapee\nescapees\nescapement\nescapements\nescaper\nescapers\nescapes\nescaping\nescapism\nescapisms\nescapist\nescapists\nescapologies\nescapologist\nescapologists\nescapology\nescar\nescargot\nescargots\nescarole\nescaroles\nescarp\nescarped\nescarping\nescarpment\nescarpments\nescarps\nescars\neschalot\neschalots\neschar\nescharotic\nescharotics\neschars\neschatological\neschatologically\neschatologies\neschatology\nescheat\nescheatable\nescheated\nescheating\nescheats\neschew\neschewal\neschewals\neschewed\neschewing\neschews\nescolar\nescolars\nescort\nescorted\nescorting\nescorts\nescot\nescoted\nescoting\nescots\nescritoire\nescritoires\nescrow\nescrowed\nescrowing\nescrows\nescuage\nescuages\nescudo\nescudos\nesculent\nesculents\nescutcheon\nescutcheons\nesemplastic\neserine\neserines\neses\neskar\neskars\nesker\neskers\nesophageal\nesophagi\nesophagus\nesophaguses\nesoteric\nesoterica\nesoterically\nesotericism\nesotericisms\nespadrille\nespadrilles\nespalier\nespaliered\nespaliering\nespaliers\nespanol\nespanoles\nesparto\nespartos\nespecial\nespecially\nesperance\nesperances\nespial\nespials\nespied\nespiegle\nespieglerie\nespiegleries\nespies\nespionage\nespionages\nesplanade\nesplanades\nespousal\nespousals\nespouse\nespoused\nespouser\nespousers\nespouses\nespousing\nespresso\nespressos\nesprit\nesprits\nespy\nespying\nesquire\nesquired\nesquires\nesquiring\ness\nessay\nessayed\nessayer\nessayers\nessaying\nessayist\nessayistic\nessayists\nessays\nessence\nessences\nessential\nessentialism\nessentialisms\nessentialist\nessentialists\nessentialities\nessentiality\nessentialize\nessentialized\nessentializes\nessentializing\nessentially\nessentialness\nessentialnesses\nessentials\nesses\nessoin\nessoins\nessonite\nessonites\nestablish\nestablishable\nestablished\nestablisher\nestablishers\nestablishes\nestablishing\nestablishment\nestablishmentarian\nestablishmentarianism\nestablishmentarianisms\nestablishmentarians\nestablishments\nestaminet\nestaminets\nestancia\nestancias\nestate\nestated\nestates\nestating\nesteem\nesteemed\nesteeming\nesteems\nester\nesterase\nesterases\nesterification\nesterifications\nesterified\nesterifies\nesterify\nesterifying\nesters\nestheses\nesthesia\nesthesias\nesthesis\nesthesises\nesthete\nesthetes\nesthetic\nesthetician\nestheticians\nestheticism\nestheticisms\nesthetics\nestimable\nestimableness\nestimablenesses\nestimably\nestimate\nestimated\nestimates\nestimating\nestimation\nestimations\nestimative\nestimator\nestimators\nestival\nestivate\nestivated\nestivates\nestivating\nestivation\nestivations\nestop\nestopped\nestoppel\nestoppels\nestopping\nestops\nestovers\nestradiol\nestradiols\nestragon\nestragons\nestral\nestrange\nestranged\nestrangement\nestrangements\nestranger\nestrangers\nestranges\nestranging\nestray\nestrayed\nestraying\nestrays\nestreat\nestreated\nestreating\nestreats\nestrin\nestrins\nestriol\nestriols\nestrogen\nestrogenic\nestrogenically\nestrogens\nestrone\nestrones\nestrous\nestrual\nestrum\nestrums\nestrus\nestruses\nestuarial\nestuaries\nestuarine\nestuary\nesurience\nesuriences\nesurient\nesuriently\net\neta\netagere\netageres\netalon\netalons\netamin\netamine\netamines\netamins\netape\netapes\netas\netatism\netatisms\netatist\netcetera\netceteras\netch\netchant\netchants\netched\netcher\netchers\netches\netching\netchings\neternal\neternalize\neternalized\neternalizes\neternalizing\neternally\neternalness\neternalnesses\neternals\neterne\neternise\neternised\neternises\neternising\neternities\neternity\neternization\neternizations\neternize\neternized\neternizes\neternizing\netesian\netesians\neth\nethambutol\nethambutols\nethane\nethanes\nethanol\nethanolamine\nethanolamines\nethanols\nethene\nethenes\nethephon\nethephons\nether\nethereal\netherealities\nethereality\netherealization\netherealizations\netherealize\netherealized\netherealizes\netherealizing\nethereally\netherealness\netherealnesses\netheric\netherified\netherifies\netherify\netherifying\netherish\netherization\netherizations\netherize\netherized\netherizer\netherizers\netherizes\netherizing\nethers\nethic\nethical\nethicalities\nethicality\nethically\nethicalness\nethicalnesses\nethicals\nethician\nethicians\nethicist\nethicists\nethicize\nethicized\nethicizes\nethicizing\nethics\nethinyl\nethinyls\nethion\nethionamide\nethionamides\nethionine\nethionines\nethions\nethmoid\nethmoidal\nethmoids\nethnarch\nethnarchs\nethnic\nethnical\nethnically\nethnicities\nethnicity\nethnics\nethnobotanical\nethnobotanies\nethnobotanist\nethnobotanists\nethnobotany\nethnocentric\nethnocentricities\nethnocentricity\nethnocentrism\nethnocentrisms\nethnographer\nethnographers\nethnographic\nethnographical\nethnographically\nethnographies\nethnography\nethnohistorian\nethnohistorians\nethnohistoric\nethnohistorical\nethnohistories\nethnohistory\nethnologic\nethnological\nethnologies\nethnologist\nethnologists\nethnology\nethnomethodologies\nethnomethodologist\nethnomethodologists\nethnomethodology\nethnomusicological\nethnomusicologies\nethnomusicologist\nethnomusicologists\nethnomusicology\nethnos\nethnoscience\nethnosciences\nethnoses\nethological\nethologies\nethologist\nethologists\nethology\nethos\nethoses\nethoxies\nethoxy\nethoxyl\nethoxyls\neths\nethyl\nethylate\nethylated\nethylates\nethylating\nethylbenzene\nethylbenzenes\nethylene\nethylenediaminetetraacetate\nethylenediaminetetraacetates\nethylenes\nethylenic\nethylic\nethyls\nethyne\nethynes\nethynyl\nethynyls\netic\netiolate\netiolated\netiolates\netiolating\netiolation\netiolations\netiologic\netiological\netiologically\netiologies\netiology\netiquette\netiquettes\netna\netnas\netoile\netoiles\netouffee\netouffees\netude\netudes\netui\netuis\netwee\netwees\netyma\netymological\netymologically\netymologies\netymologise\netymologised\netymologises\netymologising\netymologist\netymologists\netymologize\netymologized\netymologizes\netymologizing\netymology\netymon\netymons\neucaine\neucaines\neucalypt\neucalypti\neucalyptol\neucalyptole\neucalyptoles\neucalyptols\neucalypts\neucalyptus\neucalyptuses\neucaryote\neucaryotes\neucharis\neucharises\neucharistic\neuchre\neuchred\neuchres\neuchring\neuchromatic\neuchromatin\neuchromatins\neuclase\neuclases\neuclidean\neuclidian\neucrite\neucrites\neucritic\neudaemon\neudaemonism\neudaemonisms\neudaemonist\neudaemonistic\neudaemonists\neudaemons\neudaimonism\neudaimonisms\neudemon\neudemons\neudiometer\neudiometers\neudiometric\neudiometrically\neugenia\neugenias\neugenic\neugenically\neugenicist\neugenicists\neugenics\neugenist\neugenists\neugenol\neugenols\neugeosynclinal\neugeosyncline\neugeosynclines\neuglena\neuglenas\neuglenoid\neuglenoids\neuglobulin\neuglobulins\neuhemerism\neuhemerisms\neuhemerist\neuhemeristic\neuhemerists\neukaryote\neukaryotes\neukaryotic\neulachan\neulachans\neulachon\neulachons\neulogia\neulogiae\neulogias\neulogies\neulogise\neulogised\neulogises\neulogising\neulogist\neulogistic\neulogistically\neulogists\neulogium\neulogiums\neulogize\neulogized\neulogizer\neulogizers\neulogizes\neulogizing\neulogy\neunuch\neunuchism\neunuchisms\neunuchoid\neunuchoids\neunuchs\neuonymus\neuonymuses\neupatrid\neupatridae\neupatrids\neupepsia\neupepsias\neupepsies\neupepsy\neupeptic\neuphausiid\neuphausiids\neuphemise\neuphemised\neuphemises\neuphemising\neuphemism\neuphemisms\neuphemist\neuphemistic\neuphemistically\neuphemists\neuphemize\neuphemized\neuphemizer\neuphemizers\neuphemizes\neuphemizing\neuphenic\neuphenics\neuphonic\neuphonically\neuphonies\neuphonious\neuphoniously\neuphoniousness\neuphoniousnesses\neuphonium\neuphoniums\neuphony\neuphorbia\neuphorbias\neuphoria\neuphoriant\neuphoriants\neuphorias\neuphoric\neuphorically\neuphotic\neuphrasies\neuphrasy\neuphroe\neuphroes\neuphuism\neuphuisms\neuphuist\neuphuistic\neuphuistically\neuphuists\neuploid\neuploidies\neuploids\neuploidy\neupnea\neupneas\neupneic\neupnoea\neupnoeas\neupnoeic\neureka\neurhythmic\neurhythmics\neurhythmies\neurhythmy\neuripi\neuripus\neuro\neurokies\neurokous\neuroky\neuropium\neuropiums\neuros\neurybath\neurybathic\neurybaths\neuryhaline\neuryokies\neuryoky\neurypterid\neurypterids\neurythermal\neurythermic\neurythermous\neurythmic\neurythmics\neurythmies\neurythmy\neurytopic\neustacies\neustacy\neustatic\neustele\neusteles\neutaxies\neutaxy\neutectic\neutectics\neutectoid\neutectoids\neuthanasia\neuthanasias\neuthanasic\neuthanatize\neuthanatized\neuthanatizes\neuthanatizing\neuthanize\neuthanized\neuthanizes\neuthanizing\neuthenics\neuthenist\neuthenists\neutherian\neutherians\neuthyroid\neutrophic\neutrophication\neutrophications\neutrophies\neutrophy\neuxenite\neuxenites\nevacuant\nevacuants\nevacuate\nevacuated\nevacuates\nevacuating\nevacuation\nevacuations\nevacuative\nevacuee\nevacuees\nevadable\nevade\nevaded\nevader\nevaders\nevades\nevadible\nevading\nevagination\nevaginations\nevaluate\nevaluated\nevaluates\nevaluating\nevaluation\nevaluations\nevaluative\nevaluator\nevaluators\nevanesce\nevanesced\nevanescence\nevanescences\nevanescent\nevanesces\nevanescing\nevangel\nevangelic\nevangelical\nevangelically\nevangelicals\nevangelism\nevangelisms\nevangelist\nevangelistic\nevangelistically\nevangelists\nevangelization\nevangelizations\nevangelize\nevangelized\nevangelizes\nevangelizing\nevangels\nevanish\nevanished\nevanishes\nevanishing\nevaporate\nevaporated\nevaporates\nevaporating\nevaporation\nevaporations\nevaporative\nevaporator\nevaporators\nevaporite\nevaporites\nevaporitic\nevapotranspiration\nevapotranspirations\nevasion\nevasions\nevasive\nevasively\nevasiveness\nevasivenesses\neve\nevection\nevections\neven\nevened\nevener\neveners\nevenest\nevenfall\nevenfalls\nevenhanded\nevenhandedly\nevenhandedness\nevenhandednesses\nevening\nevenings\nevenly\nevenness\nevennesses\nevens\nevensong\nevensongs\nevent\neventful\neventfully\neventfulness\neventfulnesses\neventide\neventides\neventless\nevents\neventual\neventualities\neventuality\neventually\neventuate\neventuated\neventuates\neventuating\never\neverblooming\neverduring\neverglade\neverglades\nevergreen\nevergreens\neverlasting\neverlastingly\neverlastingness\neverlastingnesses\neverlastings\nevermore\neversible\neversion\neversions\nevert\neverted\neverting\nevertor\nevertors\neverts\nevery\neverybody\neveryday\neverydayness\neverydaynesses\neveryman\neverymen\neveryone\neveryplace\neverything\neveryway\neverywhere\neverywoman\neverywomen\neves\nevict\nevicted\nevictee\nevictees\nevicting\neviction\nevictions\nevictor\nevictors\nevicts\nevidence\nevidenced\nevidences\nevidencing\nevident\nevidential\nevidentially\nevidentiary\nevidently\nevil\nevildoer\nevildoers\nevildoing\nevildoings\neviler\nevilest\neviller\nevillest\nevilly\nevilness\nevilnesses\nevils\nevince\nevinced\nevinces\nevincible\nevincing\nevincive\neviscerate\neviscerated\neviscerates\neviscerating\nevisceration\neviscerations\nevitable\nevite\nevited\nevites\neviting\nevocable\nevocation\nevocations\nevocative\nevocatively\nevocativeness\nevocativenesses\nevocator\nevocators\nevoke\nevoked\nevoker\nevokers\nevokes\nevoking\nevolute\nevolutes\nevolution\nevolutionarily\nevolutionary\nevolutionism\nevolutionisms\nevolutionist\nevolutionists\nevolutions\nevolvable\nevolve\nevolved\nevolvement\nevolvements\nevolver\nevolvers\nevolves\nevolving\nevonymus\nevonymuses\nevulsion\nevulsions\nevzone\nevzones\newe\newer\newers\newes\nex\nexacerbate\nexacerbated\nexacerbates\nexacerbating\nexacerbation\nexacerbations\nexact\nexacta\nexactable\nexactas\nexacted\nexacter\nexacters\nexactest\nexacting\nexactingly\nexactingness\nexactingnesses\nexaction\nexactions\nexactitude\nexactitudes\nexactly\nexactness\nexactnesses\nexactor\nexactors\nexacts\nexaggerate\nexaggerated\nexaggeratedly\nexaggeratedness\nexaggeratednesses\nexaggerates\nexaggerating\nexaggeration\nexaggerations\nexaggerative\nexaggerator\nexaggerators\nexaggeratory\nexalt\nexaltation\nexaltations\nexalted\nexaltedly\nexalter\nexalters\nexalting\nexalts\nexam\nexamen\nexamens\nexaminable\nexaminant\nexaminants\nexamination\nexaminational\nexaminations\nexamine\nexamined\nexaminee\nexaminees\nexaminer\nexaminers\nexamines\nexamining\nexample\nexampled\nexamples\nexampling\nexams\nexanimate\nexanthem\nexanthema\nexanthemas\nexanthemata\nexanthematic\nexanthematous\nexanthems\nexarch\nexarchal\nexarchate\nexarchates\nexarchies\nexarchs\nexarchy\nexasperate\nexasperated\nexasperatedly\nexasperates\nexasperating\nexasperatingly\nexasperation\nexasperations\nexcavate\nexcavated\nexcavates\nexcavating\nexcavation\nexcavational\nexcavations\nexcavator\nexcavators\nexceed\nexceeded\nexceeder\nexceeders\nexceeding\nexceedingly\nexceeds\nexcel\nexcelled\nexcellence\nexcellences\nexcellencies\nexcellency\nexcellent\nexcellently\nexcelling\nexcels\nexcelsior\nexcelsiors\nexcept\nexcepted\nexcepting\nexception\nexceptionabilities\nexceptionability\nexceptionable\nexceptionably\nexceptional\nexceptionalism\nexceptionalisms\nexceptionalities\nexceptionality\nexceptionally\nexceptionalness\nexceptionalnesses\nexceptions\nexceptive\nexcepts\nexcerpt\nexcerpted\nexcerpter\nexcerpters\nexcerpting\nexcerption\nexcerptions\nexcerptor\nexcerptors\nexcerpts\nexcess\nexcessed\nexcesses\nexcessing\nexcessive\nexcessively\nexcessiveness\nexcessivenesses\nexchange\nexchangeabilities\nexchangeability\nexchangeable\nexchanged\nexchanger\nexchangers\nexchanges\nexchanging\nexchequer\nexchequers\nexcide\nexcided\nexcides\nexciding\nexcimer\nexcimers\nexcipient\nexcipients\nexciple\nexciples\nexcisable\nexcise\nexcised\nexciseman\nexcisemen\nexcises\nexcising\nexcision\nexcisional\nexcisions\nexcitabilities\nexcitability\nexcitable\nexcitableness\nexcitablenesses\nexcitant\nexcitants\nexcitation\nexcitations\nexcitative\nexcitatory\nexcite\nexcited\nexcitedly\nexcitement\nexcitements\nexciter\nexciters\nexcites\nexciting\nexcitingly\nexciton\nexcitonic\nexcitons\nexcitor\nexcitors\nexclaim\nexclaimed\nexclaimer\nexclaimers\nexclaiming\nexclaims\nexclamation\nexclamations\nexclamatory\nexclave\nexclaves\nexcludabilities\nexcludability\nexcludable\nexclude\nexcluded\nexcluder\nexcluders\nexcludes\nexcludible\nexcluding\nexclusion\nexclusionary\nexclusionist\nexclusionists\nexclusions\nexclusive\nexclusively\nexclusiveness\nexclusivenesses\nexclusives\nexclusivism\nexclusivisms\nexclusivist\nexclusivists\nexclusivities\nexclusivity\nexcogitate\nexcogitated\nexcogitates\nexcogitating\nexcogitation\nexcogitations\nexcogitative\nexcommunicate\nexcommunicated\nexcommunicates\nexcommunicating\nexcommunication\nexcommunications\nexcommunicative\nexcommunicator\nexcommunicators\nexcoriate\nexcoriated\nexcoriates\nexcoriating\nexcoriation\nexcoriations\nexcrement\nexcremental\nexcrementitious\nexcrements\nexcrescence\nexcrescences\nexcrescencies\nexcrescency\nexcrescent\nexcrescently\nexcreta\nexcretal\nexcrete\nexcreted\nexcreter\nexcreters\nexcretes\nexcreting\nexcretion\nexcretions\nexcretory\nexcruciate\nexcruciated\nexcruciates\nexcruciating\nexcruciatingly\nexcruciation\nexcruciations\nexculpate\nexculpated\nexculpates\nexculpating\nexculpation\nexculpations\nexculpatory\nexcurrent\nexcursion\nexcursionist\nexcursionists\nexcursions\nexcursive\nexcursively\nexcursiveness\nexcursivenesses\nexcursus\nexcursuses\nexcusable\nexcusableness\nexcusablenesses\nexcusably\nexcusatory\nexcuse\nexcused\nexcuser\nexcusers\nexcuses\nexcusing\nexec\nexecrable\nexecrableness\nexecrablenesses\nexecrably\nexecrate\nexecrated\nexecrates\nexecrating\nexecration\nexecrations\nexecrative\nexecrator\nexecrators\nexecs\nexecutable\nexecutables\nexecutant\nexecutants\nexecute\nexecuted\nexecuter\nexecuters\nexecutes\nexecuting\nexecution\nexecutioner\nexecutioners\nexecutions\nexecutive\nexecutives\nexecutor\nexecutorial\nexecutors\nexecutorship\nexecutorships\nexecutory\nexecutrices\nexecutrix\nexecutrixes\nexedra\nexedrae\nexegeses\nexegesis\nexegete\nexegetes\nexegetic\nexegetical\nexegetist\nexegetists\nexempla\nexemplar\nexemplarily\nexemplariness\nexemplarinesses\nexemplarities\nexemplarity\nexemplars\nexemplary\nexemplification\nexemplifications\nexemplified\nexemplifies\nexemplify\nexemplifying\nexemplum\nexempt\nexempted\nexempting\nexemption\nexemptions\nexempts\nexenterate\nexenterated\nexenterates\nexenterating\nexenteration\nexenterations\nexequial\nexequies\nexequy\nexercisable\nexercise\nexercised\nexerciser\nexercisers\nexercises\nexercising\nexercitation\nexercitations\nexergonic\nexergual\nexergue\nexergues\nexert\nexerted\nexerting\nexertion\nexertions\nexertive\nexerts\nexes\nexeunt\nexfoliate\nexfoliated\nexfoliates\nexfoliating\nexfoliation\nexfoliations\nexfoliative\nexhalant\nexhalants\nexhalation\nexhalations\nexhale\nexhaled\nexhalent\nexhalents\nexhales\nexhaling\nexhaust\nexhausted\nexhauster\nexhausters\nexhaustibilities\nexhaustibility\nexhaustible\nexhausting\nexhaustion\nexhaustions\nexhaustive\nexhaustively\nexhaustiveness\nexhaustivenesses\nexhaustivities\nexhaustivity\nexhaustless\nexhaustlessly\nexhaustlessness\nexhaustlessnesses\nexhausts\nexhibit\nexhibited\nexhibiting\nexhibition\nexhibitioner\nexhibitioners\nexhibitionism\nexhibitionisms\nexhibitionist\nexhibitionistic\nexhibitionistically\nexhibitionists\nexhibitions\nexhibitive\nexhibitor\nexhibitors\nexhibitory\nexhibits\nexhilarate\nexhilarated\nexhilarates\nexhilarating\nexhilaratingly\nexhilaration\nexhilarations\nexhilarative\nexhort\nexhortation\nexhortations\nexhortative\nexhortatory\nexhorted\nexhorter\nexhorters\nexhorting\nexhorts\nexhumation\nexhumations\nexhume\nexhumed\nexhumer\nexhumers\nexhumes\nexhuming\nexigence\nexigences\nexigencies\nexigency\nexigent\nexigently\nexigible\nexiguities\nexiguity\nexiguous\nexiguously\nexiguousness\nexiguousnesses\nexile\nexiled\nexiles\nexilian\nexilic\nexiling\neximious\nexine\nexines\nexist\nexisted\nexistence\nexistences\nexistent\nexistential\nexistentialism\nexistentialisms\nexistentialist\nexistentialistic\nexistentialistically\nexistentialists\nexistentially\nexistents\nexisting\nexists\nexit\nexited\nexiting\nexitless\nexits\nexobiological\nexobiologies\nexobiologist\nexobiologists\nexobiology\nexocarp\nexocarps\nexocrine\nexocrines\nexocyclic\nexocytoses\nexocytosis\nexocytotic\nexoderm\nexodermis\nexodermises\nexoderms\nexodoi\nexodontia\nexodontias\nexodontist\nexodontists\nexodos\nexodus\nexoduses\nexoenzyme\nexoenzymes\nexoergic\nexoerythrocytic\nexogamic\nexogamies\nexogamous\nexogamy\nexogen\nexogenous\nexogenously\nexogens\nexon\nexonerate\nexonerated\nexonerates\nexonerating\nexoneration\nexonerations\nexonerative\nexonic\nexons\nexonuclease\nexonucleases\nexonumia\nexopeptidase\nexopeptidases\nexophthalmic\nexophthalmos\nexophthalmoses\nexophthalmus\nexophthalmuses\nexorable\nexorbitance\nexorbitances\nexorbitant\nexorbitantly\nexorcise\nexorcised\nexorciser\nexorcisers\nexorcises\nexorcising\nexorcism\nexorcisms\nexorcist\nexorcistic\nexorcistical\nexorcists\nexorcize\nexorcized\nexorcizes\nexorcizing\nexordia\nexordial\nexordium\nexordiums\nexoskeletal\nexoskeleton\nexoskeletons\nexosmic\nexosmose\nexosmoses\nexosphere\nexospheres\nexospheric\nexospore\nexospores\nexostoses\nexostosis\nexoteric\nexoterically\nexothermal\nexothermally\nexothermic\nexothermically\nexothermicities\nexothermicity\nexotic\nexotica\nexotically\nexoticism\nexoticisms\nexoticness\nexoticnesses\nexotics\nexotism\nexotisms\nexotoxic\nexotoxin\nexotoxins\nexpand\nexpandabilities\nexpandability\nexpandable\nexpanded\nexpander\nexpanders\nexpanding\nexpandor\nexpandors\nexpands\nexpanse\nexpanses\nexpansibilities\nexpansibility\nexpansible\nexpansion\nexpansional\nexpansionary\nexpansionism\nexpansionisms\nexpansionist\nexpansionistic\nexpansionists\nexpansions\nexpansive\nexpansively\nexpansiveness\nexpansivenesses\nexpansivities\nexpansivity\nexpat\nexpatiate\nexpatiated\nexpatiates\nexpatiating\nexpatiation\nexpatiations\nexpatriate\nexpatriated\nexpatriates\nexpatriating\nexpatriation\nexpatriations\nexpatriatism\nexpatriatisms\nexpats\nexpect\nexpectable\nexpectably\nexpectance\nexpectances\nexpectancies\nexpectancy\nexpectant\nexpectantly\nexpectants\nexpectation\nexpectational\nexpectations\nexpectative\nexpected\nexpectedly\nexpectedness\nexpectednesses\nexpecting\nexpectorant\nexpectorants\nexpectorate\nexpectorated\nexpectorates\nexpectorating\nexpectoration\nexpectorations\nexpects\nexpedience\nexpediences\nexpediencies\nexpediency\nexpedient\nexpediential\nexpediently\nexpedients\nexpedite\nexpedited\nexpediter\nexpediters\nexpedites\nexpediting\nexpedition\nexpeditionary\nexpeditions\nexpeditious\nexpeditiously\nexpeditiousness\nexpeditiousnesses\nexpeditor\nexpeditors\nexpel\nexpellable\nexpelled\nexpellee\nexpellees\nexpeller\nexpellers\nexpelling\nexpels\nexpend\nexpendabilities\nexpendability\nexpendable\nexpendables\nexpended\nexpender\nexpenders\nexpending\nexpenditure\nexpenditures\nexpends\nexpense\nexpensed\nexpenses\nexpensing\nexpensive\nexpensively\nexpensiveness\nexpensivenesses\nexperience\nexperienced\nexperiences\nexperiencing\nexperiential\nexperientially\nexperiment\nexperimental\nexperimentalism\nexperimentalisms\nexperimentalist\nexperimentalists\nexperimentally\nexperimentation\nexperimentations\nexperimented\nexperimenter\nexperimenters\nexperimenting\nexperiments\nexpert\nexperted\nexperting\nexpertise\nexpertises\nexpertism\nexpertisms\nexpertize\nexpertized\nexpertizes\nexpertizing\nexpertly\nexpertness\nexpertnesses\nexperts\nexpiable\nexpiate\nexpiated\nexpiates\nexpiating\nexpiation\nexpiations\nexpiator\nexpiators\nexpiatory\nexpiration\nexpirations\nexpiratory\nexpire\nexpired\nexpirer\nexpirers\nexpires\nexpiries\nexpiring\nexpiry\nexplain\nexplainable\nexplained\nexplainer\nexplainers\nexplaining\nexplains\nexplanation\nexplanations\nexplanative\nexplanatively\nexplanatorily\nexplanatory\nexplant\nexplantation\nexplantations\nexplanted\nexplanting\nexplants\nexpletive\nexpletives\nexpletory\nexplicable\nexplicably\nexplicate\nexplicated\nexplicates\nexplicating\nexplication\nexplications\nexplicative\nexplicatively\nexplicator\nexplicators\nexplicatory\nexplicit\nexplicitly\nexplicitness\nexplicitnesses\nexplicits\nexplode\nexploded\nexploder\nexploders\nexplodes\nexploding\nexploit\nexploitable\nexploitation\nexploitations\nexploitative\nexploitatively\nexploited\nexploiter\nexploiters\nexploiting\nexploitive\nexploits\nexploration\nexplorational\nexplorations\nexplorative\nexploratively\nexploratory\nexplore\nexplored\nexplorer\nexplorers\nexplores\nexploring\nexplosion\nexplosions\nexplosive\nexplosively\nexplosiveness\nexplosivenesses\nexplosives\nexpo\nexponent\nexponential\nexponentially\nexponentials\nexponentiation\nexponentiations\nexponents\nexport\nexportabilities\nexportability\nexportable\nexportation\nexportations\nexported\nexporter\nexporters\nexporting\nexports\nexpos\nexposal\nexposals\nexpose\nexposed\nexposer\nexposers\nexposes\nexposing\nexposit\nexposited\nexpositing\nexposition\nexpositional\nexpositions\nexpositive\nexpositor\nexpositors\nexpository\nexposits\nexpostulate\nexpostulated\nexpostulates\nexpostulating\nexpostulation\nexpostulations\nexpostulatory\nexposure\nexposures\nexpound\nexpounded\nexpounder\nexpounders\nexpounding\nexpounds\nexpress\nexpressage\nexpressages\nexpressed\nexpresser\nexpressers\nexpresses\nexpressible\nexpressing\nexpression\nexpressional\nexpressionism\nexpressionisms\nexpressionist\nexpressionistic\nexpressionistically\nexpressionists\nexpressionless\nexpressionlessly\nexpressionlessness\nexpressionlessnesses\nexpressions\nexpressive\nexpressively\nexpressiveness\nexpressivenesses\nexpressivities\nexpressivity\nexpressly\nexpressman\nexpressmen\nexpresso\nexpressos\nexpressway\nexpressways\nexpropriate\nexpropriated\nexpropriates\nexpropriating\nexpropriation\nexpropriations\nexpropriator\nexpropriators\nexpulse\nexpulsed\nexpulses\nexpulsing\nexpulsion\nexpulsions\nexpulsive\nexpunction\nexpunctions\nexpunge\nexpunged\nexpunger\nexpungers\nexpunges\nexpunging\nexpurgate\nexpurgated\nexpurgates\nexpurgating\nexpurgation\nexpurgations\nexpurgator\nexpurgatorial\nexpurgators\nexpurgatory\nexquisite\nexquisitely\nexquisiteness\nexquisitenesses\nexquisites\nexsanguinate\nexsanguinated\nexsanguinates\nexsanguinating\nexsanguination\nexsanguinations\nexscind\nexscinded\nexscinding\nexscinds\nexsecant\nexsecants\nexsect\nexsected\nexsecting\nexsects\nexsert\nexserted\nexsertile\nexserting\nexsertion\nexsertions\nexserts\nexsiccate\nexsiccated\nexsiccates\nexsiccating\nexsiccation\nexsiccations\nexsolution\nexsolutions\nextant\nextemporal\nextemporally\nextemporaneities\nextemporaneity\nextemporaneous\nextemporaneously\nextemporaneousness\nextemporaneousnesses\nextemporarily\nextemporary\nextempore\nextemporisation\nextemporisations\nextemporise\nextemporised\nextemporises\nextemporising\nextemporization\nextemporizations\nextemporize\nextemporized\nextemporizer\nextemporizers\nextemporizes\nextemporizing\nextend\nextendabilities\nextendability\nextendable\nextended\nextendedly\nextendedness\nextendednesses\nextender\nextenders\nextendible\nextending\nextends\nextensibilities\nextensibility\nextensible\nextensile\nextension\nextensional\nextensionalities\nextensionality\nextensionally\nextensions\nextensities\nextensity\nextensive\nextensively\nextensiveness\nextensivenesses\nextensometer\nextensometers\nextensor\nextensors\nextent\nextents\nextenuate\nextenuated\nextenuates\nextenuating\nextenuation\nextenuations\nextenuator\nextenuators\nextenuatory\nexterior\nexteriorise\nexteriorised\nexteriorises\nexteriorising\nexteriorities\nexteriority\nexteriorization\nexteriorizations\nexteriorize\nexteriorized\nexteriorizes\nexteriorizing\nexteriorly\nexteriors\nexterminate\nexterminated\nexterminates\nexterminating\nextermination\nexterminations\nexterminator\nexterminators\nexterminatory\nextermine\nextermined\nextermines\nextermining\nextern\nexternal\nexternalisation\nexternalisations\nexternalise\nexternalised\nexternalises\nexternalising\nexternalism\nexternalisms\nexternalities\nexternality\nexternalization\nexternalizations\nexternalize\nexternalized\nexternalizes\nexternalizing\nexternally\nexternals\nexterne\nexternes\nexterns\nexternship\nexternships\nexteroceptive\nexteroceptor\nexteroceptors\nexterritorial\nexterritorialities\nexterritoriality\nextinct\nextincted\nextincting\nextinction\nextinctions\nextinctive\nextincts\nextinguish\nextinguishable\nextinguished\nextinguisher\nextinguishers\nextinguishes\nextinguishing\nextinguishment\nextinguishments\nextirpate\nextirpated\nextirpates\nextirpating\nextirpation\nextirpations\nextirpator\nextirpators\nextol\nextoll\nextolled\nextoller\nextollers\nextolling\nextolls\nextolment\nextolments\nextols\nextort\nextorted\nextorter\nextorters\nextorting\nextortion\nextortionary\nextortionate\nextortionately\nextortioner\nextortioners\nextortionist\nextortionists\nextortions\nextortive\nextorts\nextra\nextracellular\nextracellularly\nextrachromosomal\nextracorporeal\nextracorporeally\nextracranial\nextract\nextractabilities\nextractability\nextractable\nextracted\nextracting\nextraction\nextractions\nextractive\nextractively\nextractives\nextractor\nextractors\nextracts\nextracurricular\nextracurriculars\nextraditable\nextradite\nextradited\nextradites\nextraditing\nextradition\nextraditions\nextrados\nextradoses\nextraembryonic\nextragalactic\nextrahepatic\nextrajudicial\nextrajudicially\nextralegal\nextralegally\nextralimital\nextralinguistic\nextralinguistically\nextraliterary\nextralities\nextrality\nextralogical\nextramarital\nextramundane\nextramural\nextramurally\nextramusical\nextraneous\nextraneously\nextraneousness\nextraneousnesses\nextranuclear\nextraordinaire\nextraordinarily\nextraordinariness\nextraordinarinesses\nextraordinary\nextrapolate\nextrapolated\nextrapolates\nextrapolating\nextrapolation\nextrapolations\nextrapolative\nextrapolator\nextrapolators\nextrapyramidal\nextras\nextrasensory\nextrasystole\nextrasystoles\nextraterrestrial\nextraterrestrials\nextraterritorial\nextraterritorialities\nextraterritoriality\nextratextual\nextrauterine\nextravagance\nextravagances\nextravagancies\nextravagancy\nextravagant\nextravagantly\nextravaganza\nextravaganzas\nextravagate\nextravagated\nextravagates\nextravagating\nextravasate\nextravasated\nextravasates\nextravasating\nextravasation\nextravasations\nextravascular\nextravehicular\nextraversion\nextraversions\nextravert\nextraverted\nextraverts\nextrema\nextreme\nextremely\nextremeness\nextremenesses\nextremer\nextremes\nextremest\nextremism\nextremisms\nextremist\nextremists\nextremities\nextremity\nextremum\nextricable\nextricate\nextricated\nextricates\nextricating\nextrication\nextrications\nextrinsic\nextrinsically\nextrorse\nextroversion\nextroversions\nextrovert\nextroverted\nextroverts\nextrudabilities\nextrudability\nextrudable\nextrude\nextruded\nextruder\nextruders\nextrudes\nextruding\nextrusion\nextrusions\nextrusive\nextubate\nextubated\nextubates\nextubating\nexuberance\nexuberances\nexuberant\nexuberantly\nexuberate\nexuberated\nexuberates\nexuberating\nexudate\nexudates\nexudation\nexudations\nexudative\nexude\nexuded\nexudes\nexuding\nexult\nexultance\nexultances\nexultancies\nexultancy\nexultant\nexultantly\nexultation\nexultations\nexulted\nexulting\nexultingly\nexults\nexurb\nexurban\nexurbanite\nexurbanites\nexurbia\nexurbias\nexurbs\nexuvia\nexuviae\nexuvial\nexuviate\nexuviated\nexuviates\nexuviating\nexuviation\nexuviations\nexuvium\neyas\neyases\neye\neyeable\neyeball\neyeballed\neyeballing\neyeballs\neyebar\neyebars\neyebeam\neyebeams\neyebolt\neyebolts\neyebright\neyebrights\neyebrow\neyebrows\neyecup\neyecups\neyed\neyedness\neyednesses\neyedropper\neyedroppers\neyedrops\neyeful\neyefuls\neyeglass\neyeglasses\neyehole\neyeholes\neyehook\neyehooks\neyeing\neyelash\neyelashes\neyeless\neyelet\neyelets\neyeletted\neyeletting\neyelid\neyelids\neyelike\neyeliner\neyeliners\neyen\neyeopener\neyeopeners\neyepiece\neyepieces\neyepoint\neyepoints\neyepopper\neyepoppers\neyer\neyers\neyes\neyeshade\neyeshades\neyeshot\neyeshots\neyesight\neyesights\neyesome\neyesore\neyesores\neyespot\neyespots\neyestalk\neyestalks\neyestone\neyestones\neyestrain\neyestrains\neyestrings\neyeteeth\neyetooth\neyewash\neyewashes\neyewater\neyewaters\neyewear\neyewink\neyewinks\neyewitness\neyewitnesses\neying\neyne\neyra\neyras\neyre\neyres\neyrie\neyries\neyrir\neyry\nfa\nfable\nfabled\nfabler\nfablers\nfables\nfabliau\nfabliaux\nfabling\nfabric\nfabricant\nfabricants\nfabricate\nfabricated\nfabricates\nfabricating\nfabrication\nfabrications\nfabricator\nfabricators\nfabrics\nfabular\nfabulist\nfabulistic\nfabulists\nfabulous\nfabulously\nfabulousness\nfabulousnesses\nfacade\nfacades\nface\nfaceable\nfacecloth\nfacecloths\nfaced\nfacedown\nfacedowns\nfaceless\nfacelessness\nfacelessnesses\nfacelift\nfacelifted\nfacelifting\nfacelifts\nfacemask\nfacemasks\nfaceplate\nfaceplates\nfacer\nfacers\nfaces\nfacet\nfacete\nfaceted\nfacetely\nfacetiae\nfaceting\nfacetious\nfacetiously\nfacetiousness\nfacetiousnesses\nfacets\nfacetted\nfacetting\nfaceup\nfacia\nfacial\nfacially\nfacials\nfacias\nfaciend\nfaciends\nfacies\nfacile\nfacilely\nfacileness\nfacilenesses\nfacilitate\nfacilitated\nfacilitates\nfacilitating\nfacilitation\nfacilitations\nfacilitative\nfacilitator\nfacilitators\nfacilitatory\nfacilities\nfacility\nfacing\nfacings\nfacsimile\nfacsimiles\nfact\nfactful\nfacticities\nfacticity\nfaction\nfactional\nfactionalism\nfactionalisms\nfactionally\nfactions\nfactious\nfactiously\nfactiousness\nfactiousnesses\nfactitious\nfactitiously\nfactitiousness\nfactitiousnesses\nfactitive\nfactitively\nfactoid\nfactoids\nfactor\nfactorable\nfactorage\nfactorages\nfactored\nfactorial\nfactorials\nfactories\nfactoring\nfactorization\nfactorizations\nfactorize\nfactorized\nfactorizes\nfactorizing\nfactors\nfactorship\nfactorships\nfactory\nfactorylike\nfactotum\nfactotums\nfacts\nfactual\nfactualism\nfactualisms\nfactualist\nfactualists\nfactualities\nfactuality\nfactually\nfactualness\nfactualnesses\nfacture\nfactures\nfacula\nfaculae\nfacular\nfacultative\nfacultatively\nfaculties\nfaculty\nfad\nfadable\nfaddier\nfaddiest\nfaddish\nfaddishness\nfaddishnesses\nfaddism\nfaddisms\nfaddist\nfaddists\nfaddy\nfade\nfadeaway\nfadeaways\nfaded\nfadedly\nfadein\nfadeins\nfadeless\nfadeout\nfadeouts\nfader\nfaders\nfades\nfadge\nfadged\nfadges\nfadging\nfading\nfadings\nfado\nfados\nfads\nfaecal\nfaeces\nfaena\nfaenas\nfaerie\nfaeries\nfaery\nfag\nfagged\nfagging\nfaggot\nfaggoted\nfaggoting\nfaggotings\nfaggotries\nfaggotry\nfaggots\nfaggoty\nfaggy\nfagin\nfagins\nfagot\nfagoted\nfagoter\nfagoters\nfagoting\nfagotings\nfagots\nfags\nfahlband\nfahlbands\nfaience\nfaiences\nfail\nfailed\nfailing\nfailingly\nfailings\nfaille\nfailles\nfails\nfailure\nfailures\nfain\nfaineant\nfaineants\nfainer\nfainest\nfaint\nfainted\nfainter\nfainters\nfaintest\nfainthearted\nfaintheartedly\nfaintheartedness\nfaintheartednesses\nfainting\nfaintish\nfaintishness\nfaintishnesses\nfaintly\nfaintness\nfaintnesses\nfaints\nfair\nfaired\nfairer\nfairest\nfairground\nfairgrounds\nfairies\nfairing\nfairings\nfairish\nfairishly\nfairlead\nfairleader\nfairleaders\nfairleads\nfairly\nfairness\nfairnesses\nfairs\nfairway\nfairways\nfairy\nfairyism\nfairyisms\nfairyland\nfairylands\nfairylike\nfaith\nfaithed\nfaithful\nfaithfully\nfaithfulness\nfaithfulnesses\nfaithfuls\nfaithing\nfaithless\nfaithlessly\nfaithlessness\nfaithlessnesses\nfaiths\nfaitour\nfaitours\nfajita\nfajitas\nfake\nfaked\nfakeer\nfakeers\nfaker\nfakeries\nfakers\nfakery\nfakes\nfakey\nfaking\nfakir\nfakirs\nfalafel\nfalbala\nfalbalas\nfalcate\nfalcated\nfalces\nfalchion\nfalchions\nfalciform\nfalcon\nfalconer\nfalconers\nfalconet\nfalconets\nfalconine\nfalconries\nfalconry\nfalcons\nfalderal\nfalderals\nfalderol\nfalderols\nfaldstool\nfaldstools\nfall\nfallacies\nfallacious\nfallaciously\nfallaciousness\nfallaciousnesses\nfallacy\nfallal\nfallaleries\nfallalery\nfallals\nfallaway\nfallaways\nfallback\nfallbacks\nfallen\nfaller\nfallers\nfallfish\nfallfishes\nfallibilities\nfallibility\nfallible\nfallibly\nfalling\nfalloff\nfalloffs\nfallout\nfallouts\nfallow\nfallowed\nfallowing\nfallowness\nfallownesses\nfallows\nfalls\nfalse\nfalsehood\nfalsehoods\nfalsely\nfalseness\nfalsenesses\nfalser\nfalsest\nfalsetto\nfalsettos\nfalsework\nfalseworks\nfalsie\nfalsies\nfalsifiabilities\nfalsifiability\nfalsifiable\nfalsification\nfalsifications\nfalsified\nfalsifier\nfalsifiers\nfalsifies\nfalsify\nfalsifying\nfalsities\nfalsity\nfaltboat\nfaltboats\nfalter\nfaltered\nfalterer\nfalterers\nfaltering\nfalteringly\nfalters\nfalx\nfame\nfamed\nfameless\nfames\nfamilial\nfamiliar\nfamiliarise\nfamiliarised\nfamiliarises\nfamiliarising\nfamiliarities\nfamiliarity\nfamiliarization\nfamiliarizations\nfamiliarize\nfamiliarized\nfamiliarizes\nfamiliarizing\nfamiliarly\nfamiliarness\nfamiliarnesses\nfamiliars\nfamilies\nfamilism\nfamilisms\nfamilistic\nfamily\nfamine\nfamines\nfaming\nfamish\nfamished\nfamishes\nfamishing\nfamishment\nfamishments\nfamous\nfamously\nfamousness\nfamousnesses\nfamuli\nfamulus\nfan\nfanatic\nfanatical\nfanatically\nfanaticalness\nfanaticalnesses\nfanaticism\nfanaticisms\nfanaticize\nfanaticized\nfanaticizes\nfanaticizing\nfanatics\nfancied\nfancier\nfanciers\nfancies\nfanciest\nfancified\nfancifies\nfanciful\nfancifully\nfancifulness\nfancifulnesses\nfancify\nfancifying\nfancily\nfanciness\nfancinesses\nfancy\nfancying\nfancywork\nfancyworks\nfandango\nfandangos\nfandom\nfandoms\nfane\nfanega\nfanegada\nfanegadas\nfanegas\nfanes\nfanfare\nfanfares\nfanfaron\nfanfaronade\nfanfaronades\nfanfarons\nfanfold\nfanfolded\nfanfolding\nfanfolds\nfang\nfanga\nfangas\nfanged\nfangless\nfanglike\nfangs\nfanion\nfanions\nfanjet\nfanjets\nfanlight\nfanlights\nfanlike\nfanned\nfanner\nfanners\nfannies\nfanning\nfanny\nfano\nfanon\nfanons\nfanos\nfans\nfantabulous\nfantail\nfantails\nfantasia\nfantasias\nfantasie\nfantasied\nfantasies\nfantasise\nfantasised\nfantasises\nfantasising\nfantasist\nfantasists\nfantasize\nfantasized\nfantasizer\nfantasizers\nfantasizes\nfantasizing\nfantasm\nfantasms\nfantast\nfantastic\nfantastical\nfantasticalities\nfantasticality\nfantastically\nfantasticalness\nfantasticalnesses\nfantasticate\nfantasticated\nfantasticates\nfantasticating\nfantastication\nfantastications\nfantastico\nfantasticoes\nfantastics\nfantasts\nfantasy\nfantasying\nfantasyland\nfantasylands\nfantoccini\nfantod\nfantods\nfantom\nfantoms\nfanum\nfanums\nfanwise\nfanwort\nfanworts\nfanzine\nfanzines\nfaqir\nfaqirs\nfaquir\nfaquirs\nfar\nfarad\nfaradaic\nfaraday\nfaradays\nfaradic\nfaradise\nfaradised\nfaradises\nfaradising\nfaradism\nfaradisms\nfaradize\nfaradized\nfaradizes\nfaradizing\nfarads\nfarandole\nfarandoles\nfaraway\nfarce\nfarced\nfarcer\nfarcers\nfarces\nfarceur\nfarceurs\nfarci\nfarcical\nfarcicalities\nfarcicality\nfarcically\nfarcie\nfarcies\nfarcing\nfarcy\nfard\nfarded\nfardel\nfardels\nfarding\nfards\nfare\nfared\nfarer\nfarers\nfares\nfarewell\nfarewelled\nfarewelling\nfarewells\nfarfal\nfarfalle\nfarfalles\nfarfals\nfarfel\nfarfels\nfarfetched\nfarfetchedness\nfarfetchednesses\nfarina\nfarinaceous\nfarinas\nfaring\nfarinha\nfarinhas\nfarinose\nfarkleberries\nfarkleberry\nfarl\nfarle\nfarles\nfarls\nfarm\nfarmable\nfarmed\nfarmer\nfarmerette\nfarmerettes\nfarmers\nfarmhand\nfarmhands\nfarmhouse\nfarmhouses\nfarming\nfarmings\nfarmland\nfarmlands\nfarms\nfarmstead\nfarmsteads\nfarmwife\nfarmwives\nfarmwork\nfarmworker\nfarmworkers\nfarmworks\nfarmyard\nfarmyards\nfarnesol\nfarnesols\nfarness\nfarnesses\nfaro\nfaros\nfarouche\nfarraginous\nfarrago\nfarragoes\nfarragos\nfarrier\nfarrieries\nfarriers\nfarriery\nfarrow\nfarrowed\nfarrowing\nfarrows\nfarseeing\nfarside\nfarsides\nfarsighted\nfarsightedly\nfarsightedness\nfarsightednesses\nfart\nfarted\nfarther\nfarthermost\nfarthest\nfarthing\nfarthingale\nfarthingales\nfarthings\nfarting\nfarts\nfas\nfasces\nfascia\nfasciae\nfascial\nfascias\nfasciate\nfasciated\nfasciation\nfasciations\nfascicle\nfascicled\nfascicles\nfascicular\nfascicularly\nfasciculate\nfasciculated\nfasciculation\nfasciculations\nfascicule\nfascicules\nfasciculi\nfasciculus\nfascinate\nfascinated\nfascinates\nfascinating\nfascinatingly\nfascination\nfascinations\nfascinator\nfascinators\nfascine\nfascines\nfascioliases\nfascioliasis\nfascism\nfascisms\nfascist\nfascistic\nfascistically\nfascists\nfash\nfashed\nfashes\nfashing\nfashion\nfashionabilities\nfashionability\nfashionable\nfashionableness\nfashionablenesses\nfashionables\nfashionably\nfashioned\nfashioner\nfashioners\nfashioning\nfashionmonger\nfashionmongers\nfashions\nfashious\nfast\nfastback\nfastbacks\nfastball\nfastballer\nfastballers\nfastballs\nfasted\nfasten\nfastened\nfastener\nfasteners\nfastening\nfastenings\nfastens\nfaster\nfasters\nfastest\nfastidious\nfastidiously\nfastidiousness\nfastidiousnesses\nfastigiate\nfasting\nfastings\nfastness\nfastnesses\nfasts\nfastuous\nfat\nfatal\nfatalism\nfatalisms\nfatalist\nfatalistic\nfatalistically\nfatalists\nfatalities\nfatality\nfatally\nfatback\nfatbacks\nfatbird\nfatbirds\nfate\nfated\nfateful\nfatefully\nfatefulness\nfatefulnesses\nfates\nfathead\nfatheaded\nfatheadedly\nfatheadedness\nfatheadednesses\nfatheads\nfather\nfathered\nfatherhood\nfatherhoods\nfathering\nfatherland\nfatherlands\nfatherless\nfatherlike\nfatherliness\nfatherlinesses\nfatherly\nfathers\nfathom\nfathomable\nfathomed\nfathoming\nfathomless\nfathomlessly\nfathomlessness\nfathomlessnesses\nfathoms\nfatidic\nfatidical\nfatigabilities\nfatigability\nfatigable\nfatigue\nfatigued\nfatigues\nfatiguing\nfatiguingly\nfating\nfatless\nfatlike\nfatling\nfatlings\nfatly\nfatness\nfatnesses\nfats\nfatshedera\nfatshederas\nfatso\nfatsoes\nfatsos\nfatstock\nfatstocks\nfatted\nfatten\nfattened\nfattener\nfatteners\nfattening\nfattens\nfatter\nfattest\nfattier\nfatties\nfattiest\nfattily\nfattiness\nfattinesses\nfatting\nfattish\nfatty\nfatuities\nfatuity\nfatuous\nfatuously\nfatuousness\nfatuousnesses\nfatwa\nfatwas\nfatwood\nfatwoods\nfaubourg\nfaubourgs\nfaucal\nfaucals\nfauces\nfaucet\nfaucets\nfaucial\nfaugh\nfauld\nfaulds\nfault\nfaulted\nfaultfinder\nfaultfinders\nfaultfinding\nfaultfindings\nfaultier\nfaultiest\nfaultily\nfaultiness\nfaultinesses\nfaulting\nfaultless\nfaultlessly\nfaultlessness\nfaultlessnesses\nfaults\nfaulty\nfaun\nfauna\nfaunae\nfaunal\nfaunally\nfaunas\nfaunistic\nfaunistically\nfaunlike\nfauns\nfauteuil\nfauteuils\nfauve\nfauves\nfauvism\nfauvisms\nfauvist\nfauvists\nfaux\nfava\nfavas\nfave\nfavela\nfavelas\nfavella\nfavellas\nfaves\nfavism\nfavisms\nfavonian\nfavor\nfavorable\nfavorableness\nfavorablenesses\nfavorably\nfavored\nfavorer\nfavorers\nfavoring\nfavorite\nfavorites\nfavoritism\nfavoritisms\nfavors\nfavour\nfavoured\nfavourer\nfavourers\nfavouring\nfavours\nfavus\nfavuses\nfawn\nfawned\nfawner\nfawners\nfawnier\nfawniest\nfawning\nfawningly\nfawnlike\nfawns\nfawny\nfax\nfaxed\nfaxes\nfaxing\nfay\nfayalite\nfayalites\nfayed\nfaying\nfays\nfaze\nfazed\nfazenda\nfazendas\nfazes\nfazing\nfeal\nfealties\nfealty\nfear\nfeared\nfearer\nfearers\nfearful\nfearfuller\nfearfullest\nfearfully\nfearfulness\nfearfulnesses\nfearing\nfearless\nfearlessly\nfearlessness\nfearlessnesses\nfears\nfearsome\nfearsomely\nfearsomeness\nfearsomenesses\nfeasance\nfeasances\nfease\nfeased\nfeases\nfeasibilities\nfeasibility\nfeasible\nfeasibly\nfeasing\nfeast\nfeasted\nfeaster\nfeasters\nfeastful\nfeasting\nfeasts\nfeat\nfeater\nfeatest\nfeather\nfeatherbed\nfeatherbedded\nfeatherbedding\nfeatherbeddings\nfeatherbeds\nfeatherbrain\nfeatherbrained\nfeatherbrains\nfeathered\nfeatheredge\nfeatheredged\nfeatheredges\nfeatheredging\nfeatherhead\nfeatherheaded\nfeatherheads\nfeatherier\nfeatheriest\nfeathering\nfeatherings\nfeatherless\nfeatherlight\nfeathers\nfeatherstitch\nfeatherstitched\nfeatherstitches\nfeatherstitching\nfeatherweight\nfeatherweights\nfeathery\nfeatlier\nfeatliest\nfeatly\nfeats\nfeature\nfeatured\nfeatureless\nfeatures\nfeaturette\nfeaturettes\nfeaturing\nfeaze\nfeazed\nfeazes\nfeazing\nfebrific\nfebrifuge\nfebrifuges\nfebrile\nfecal\nfeces\nfecial\nfecials\nfeck\nfeckless\nfecklessly\nfecklessness\nfecklessnesses\nfeckly\nfecks\nfecula\nfeculae\nfeculence\nfeculences\nfeculent\nfecund\nfecundate\nfecundated\nfecundates\nfecundating\nfecundation\nfecundations\nfecundities\nfecundity\nfed\nfedayee\nfedayeen\nfederacies\nfederacy\nfederal\nfederalese\nfederaleses\nfederalism\nfederalisms\nfederalist\nfederalists\nfederalization\nfederalizations\nfederalize\nfederalized\nfederalizes\nfederalizing\nfederally\nfederals\nfederate\nfederated\nfederates\nfederating\nfederation\nfederations\nfederative\nfederatively\nfedora\nfedoras\nfeds\nfee\nfeeble\nfeebleminded\nfeeblemindedly\nfeeblemindedness\nfeeblemindednesses\nfeebleness\nfeeblenesses\nfeebler\nfeeblest\nfeeblish\nfeebly\nfeed\nfeedable\nfeedback\nfeedbacks\nfeedbag\nfeedbags\nfeedbox\nfeedboxes\nfeeder\nfeeders\nfeedhole\nfeedholes\nfeeding\nfeedings\nfeedlot\nfeedlots\nfeeds\nfeedstock\nfeedstocks\nfeedstuff\nfeedstuffs\nfeeing\nfeel\nfeeler\nfeelers\nfeeless\nfeeling\nfeelingly\nfeelingness\nfeelingnesses\nfeelings\nfeels\nfees\nfeet\nfeetfirst\nfeetless\nfeeze\nfeezed\nfeezes\nfeezing\nfeh\nfehs\nfeign\nfeigned\nfeigner\nfeigners\nfeigning\nfeigns\nfeijoa\nfeijoas\nfeint\nfeinted\nfeinting\nfeints\nfeirie\nfeist\nfeistier\nfeistiest\nfeistiness\nfeistinesses\nfeists\nfeisty\nfelafel\nfeldsher\nfeldshers\nfeldspar\nfeldspars\nfeldspathic\nfelicific\nfelicitate\nfelicitated\nfelicitates\nfelicitating\nfelicitation\nfelicitations\nfelicitator\nfelicitators\nfelicities\nfelicitous\nfelicitously\nfelicitousness\nfelicitousnesses\nfelicity\nfelid\nfelids\nfeline\nfelinely\nfelines\nfelinities\nfelinity\nfell\nfella\nfellable\nfellah\nfellaheen\nfellahin\nfellahs\nfellas\nfellate\nfellated\nfellates\nfellating\nfellatio\nfellation\nfellations\nfellatios\nfellator\nfellators\nfelled\nfeller\nfellers\nfellest\nfellies\nfelling\nfellmonger\nfellmongered\nfellmongeries\nfellmongering\nfellmongerings\nfellmongers\nfellmongery\nfellness\nfellnesses\nfelloe\nfelloes\nfellow\nfellowed\nfellowing\nfellowly\nfellowman\nfellowmen\nfellows\nfellowship\nfellowshiped\nfellowshiping\nfellowshipped\nfellowshipping\nfellowships\nfells\nfelly\nfelon\nfelonies\nfelonious\nfeloniously\nfeloniousness\nfeloniousnesses\nfelonries\nfelonry\nfelons\nfelony\nfelsite\nfelsites\nfelsitic\nfelspar\nfelspars\nfelstone\nfelstones\nfelt\nfelted\nfelting\nfeltings\nfeltlike\nfelts\nfelucca\nfeluccas\nfelwort\nfelworts\nfem\nfemale\nfemaleness\nfemalenesses\nfemales\nfeme\nfemes\nfeminacies\nfeminacy\nfeminie\nfeminine\nfemininely\nfeminineness\nfemininenesses\nfeminines\nfemininities\nfemininity\nfeminise\nfeminised\nfeminises\nfeminising\nfeminism\nfeminisms\nfeminist\nfeministic\nfeminists\nfeminities\nfeminity\nfeminization\nfeminizations\nfeminize\nfeminized\nfeminizes\nfeminizing\nfemme\nfemmes\nfemora\nfemoral\nfems\nfemtosecond\nfemtoseconds\nfemur\nfemurs\nfen\nfenagle\nfenagled\nfenagles\nfenagling\nfence\nfenced\nfenceless\nfencelessness\nfencelessnesses\nfencer\nfencerow\nfencerows\nfencers\nfences\nfencible\nfencibles\nfencing\nfencings\nfend\nfended\nfender\nfendered\nfenderless\nfenders\nfending\nfends\nfenestra\nfenestrae\nfenestral\nfenestrate\nfenestrated\nfenestration\nfenestrations\nfenland\nfenlands\nfennec\nfennecs\nfennel\nfennels\nfenny\nfens\nfenthion\nfenthions\nfenugreek\nfenugreeks\nfenuron\nfenurons\nfeod\nfeodaries\nfeodary\nfeods\nfeoff\nfeoffed\nfeoffee\nfeoffees\nfeoffer\nfeoffers\nfeoffing\nfeoffment\nfeoffments\nfeoffor\nfeoffors\nfeoffs\nfer\nferacities\nferacity\nferal\nferbam\nferbams\nfere\nferes\nferetories\nferetory\nferia\nferiae\nferial\nferias\nferine\nferities\nferity\nferlie\nferlies\nferly\nfermata\nfermatas\nfermate\nferment\nfermentable\nfermentation\nfermentations\nfermentative\nfermented\nfermenter\nfermenters\nfermenting\nfermentor\nfermentors\nferments\nfermi\nfermion\nfermions\nfermis\nfermium\nfermiums\nfern\nferneries\nfernery\nfernier\nferniest\nfernless\nfernlike\nferns\nferny\nferocious\nferociously\nferociousness\nferociousnesses\nferocities\nferocity\nferrate\nferrates\nferredoxin\nferredoxins\nferrel\nferreled\nferreling\nferrelled\nferrelling\nferrels\nferreous\nferret\nferreted\nferreter\nferreters\nferreting\nferretings\nferrets\nferrety\nferriage\nferriages\nferric\nferricyanide\nferricyanides\nferried\nferries\nferriferous\nferrimagnet\nferrimagnetic\nferrimagnetically\nferrimagnetism\nferrimagnetisms\nferrimagnets\nferrite\nferrites\nferritic\nferritin\nferritins\nferrocene\nferrocenes\nferroconcrete\nferroconcretes\nferrocyanide\nferrocyanides\nferroelectric\nferroelectricities\nferroelectricity\nferroelectrics\nferromagnesian\nferromagnet\nferromagnetic\nferromagnetism\nferromagnetisms\nferromagnets\nferromanganese\nferromanganeses\nferrosilicon\nferrosilicons\nferrotype\nferrotypes\nferrous\nferruginous\nferrule\nferruled\nferrules\nferruling\nferrum\nferrums\nferry\nferryboat\nferryboats\nferrying\nferryman\nferrymen\nfertile\nfertilely\nfertileness\nfertilenesses\nfertilities\nfertility\nfertilizable\nfertilization\nfertilizations\nfertilize\nfertilized\nfertilizer\nfertilizers\nfertilizes\nfertilizing\nferula\nferulae\nferulas\nferule\nferuled\nferules\nferuling\nfervencies\nfervency\nfervent\nfervently\nfervid\nfervidly\nfervidness\nfervidnesses\nfervor\nfervors\nfervour\nfervours\nfescennine\nfescue\nfescues\nfess\nfesse\nfessed\nfesses\nfessing\nfesswise\nfestal\nfestally\nfester\nfestered\nfestering\nfesters\nfestinate\nfestinated\nfestinately\nfestinates\nfestinating\nfestival\nfestivalgoer\nfestivalgoers\nfestivals\nfestive\nfestively\nfestiveness\nfestivenesses\nfestivities\nfestivity\nfestoon\nfestooned\nfestooneries\nfestoonery\nfestooning\nfestoons\nfet\nfeta\nfetal\nfetas\nfetation\nfetations\nfetch\nfetched\nfetcher\nfetchers\nfetches\nfetching\nfetchingly\nfete\nfeted\nfeterita\nfeteritas\nfetes\nfetial\nfetiales\nfetialis\nfetials\nfetich\nfetiches\nfetichism\nfetichisms\nfeticide\nfeticides\nfetid\nfetidly\nfetidness\nfetidnesses\nfeting\nfetish\nfetishes\nfetishism\nfetishisms\nfetishist\nfetishistic\nfetishistically\nfetishists\nfetlock\nfetlocks\nfetologies\nfetologist\nfetologists\nfetology\nfetoprotein\nfetoproteins\nfetor\nfetors\nfetoscope\nfetoscopes\nfetoscopies\nfetoscopy\nfets\nfetted\nfetter\nfettered\nfetterer\nfetterers\nfettering\nfetters\nfetting\nfettle\nfettled\nfettles\nfettling\nfettlings\nfettuccine\nfettuccini\nfettucine\nfettucini\nfetus\nfetuses\nfeu\nfeuar\nfeuars\nfeud\nfeudal\nfeudalism\nfeudalisms\nfeudalist\nfeudalistic\nfeudalists\nfeudalities\nfeudality\nfeudalization\nfeudalizations\nfeudalize\nfeudalized\nfeudalizes\nfeudalizing\nfeudally\nfeudaries\nfeudary\nfeudatories\nfeudatory\nfeuded\nfeuding\nfeudist\nfeudists\nfeuds\nfeued\nfeuilleton\nfeuilletonism\nfeuilletonisms\nfeuilletonist\nfeuilletonists\nfeuilletons\nfeuing\nfeus\nfever\nfevered\nfeverfew\nfeverfews\nfevering\nfeverish\nfeverishly\nfeverishness\nfeverishnesses\nfeverous\nfevers\nfeverwort\nfeverworts\nfew\nfewer\nfewest\nfewness\nfewnesses\nfewtrils\nfey\nfeyer\nfeyest\nfeyly\nfeyness\nfeynesses\nfez\nfezes\nfezzed\nfezzes\nfiacre\nfiacres\nfiance\nfiancee\nfiancees\nfiances\nfianchetti\nfianchetto\nfianchettoed\nfianchettoing\nfianchettos\nfiar\nfiars\nfiaschi\nfiasco\nfiascoes\nfiascos\nfiat\nfiats\nfib\nfibbed\nfibber\nfibbers\nfibbing\nfiber\nfiberboard\nfiberboards\nfibered\nfiberfill\nfiberfills\nfiberglass\nfiberglassed\nfiberglasses\nfiberglassing\nfiberization\nfiberizations\nfiberize\nfiberized\nfiberizes\nfiberizing\nfiberoptic\nfiberoptics\nfibers\nfiberscope\nfiberscopes\nfibranne\nfibrannes\nfibre\nfibreboard\nfibreboards\nfibrefill\nfibrefills\nfibreglass\nfibreglasses\nfibres\nfibril\nfibrilla\nfibrillae\nfibrillar\nfibrillate\nfibrillated\nfibrillates\nfibrillating\nfibrillation\nfibrillations\nfibrils\nfibrin\nfibrinogen\nfibrinogens\nfibrinoid\nfibrinoids\nfibrinolyses\nfibrinolysin\nfibrinolysins\nfibrinolysis\nfibrinolytic\nfibrinopeptide\nfibrinopeptides\nfibrins\nfibroblast\nfibroblastic\nfibroblasts\nfibrocystic\nfibroid\nfibroids\nfibroin\nfibroins\nfibroma\nfibromas\nfibromata\nfibromatous\nfibronectin\nfibronectins\nfibrosarcoma\nfibrosarcomas\nfibrosarcomata\nfibroses\nfibrosis\nfibrositis\nfibrositises\nfibrotic\nfibrous\nfibrovascular\nfibs\nfibula\nfibulae\nfibular\nfibulas\nfice\nfices\nfiche\nfiches\nfichu\nfichus\nficin\nficins\nfickle\nfickleness\nficklenesses\nfickler\nficklest\nfickly\nfico\nficoes\nfictile\nfiction\nfictional\nfictionalise\nfictionalised\nfictionalises\nfictionalising\nfictionalities\nfictionality\nfictionalization\nfictionalizations\nfictionalize\nfictionalized\nfictionalizes\nfictionalizing\nfictionally\nfictioneer\nfictioneering\nfictioneerings\nfictioneers\nfictionist\nfictionists\nfictionization\nfictionizations\nfictionize\nfictionized\nfictionizes\nfictionizing\nfictions\nfictitious\nfictitiously\nfictitiousness\nfictitiousnesses\nfictive\nfictively\nfictiveness\nfictivenesses\nficus\nficuses\nfid\nfiddle\nfiddleback\nfiddlebacks\nfiddled\nfiddlehead\nfiddleheads\nfiddler\nfiddlers\nfiddles\nfiddlestick\nfiddlesticks\nfiddling\nfiddly\nfideism\nfideisms\nfideist\nfideistic\nfideists\nfidelities\nfidelity\nfidge\nfidged\nfidges\nfidget\nfidgeted\nfidgeter\nfidgeters\nfidgetiness\nfidgetinesses\nfidgeting\nfidgets\nfidgety\nfidging\nfido\nfidos\nfids\nfiducial\nfiducially\nfiduciaries\nfiduciary\nfie\nfief\nfiefdom\nfiefdoms\nfiefs\nfield\nfielded\nfielder\nfielders\nfieldfare\nfieldfares\nfielding\nfieldpiece\nfieldpieces\nfields\nfieldstone\nfieldstones\nfieldstrip\nfieldstripped\nfieldstripping\nfieldstrips\nfieldstript\nfieldwork\nfieldworks\nfiend\nfiendish\nfiendishly\nfiendishness\nfiendishnesses\nfiends\nfierce\nfiercely\nfierceness\nfiercenesses\nfiercer\nfiercest\nfierier\nfieriest\nfierily\nfieriness\nfierinesses\nfiery\nfiesta\nfiestas\nfife\nfifed\nfifer\nfifers\nfifes\nfifing\nfifteen\nfifteens\nfifteenth\nfifteenths\nfifth\nfifthly\nfifths\nfifties\nfiftieth\nfiftieths\nfifty\nfiftyish\nfig\nfigeater\nfigeaters\nfigged\nfigging\nfight\nfighter\nfighters\nfighting\nfightings\nfights\nfigment\nfigments\nfigs\nfiguline\nfigulines\nfigural\nfigurant\nfigurants\nfigurate\nfiguration\nfigurations\nfigurative\nfiguratively\nfigurativeness\nfigurativenesses\nfigure\nfigured\nfigurehead\nfigureheads\nfigurer\nfigurers\nfigures\nfigurine\nfigurines\nfiguring\nfigwort\nfigworts\nfil\nfila\nfilagree\nfilagreed\nfilagreeing\nfilagrees\nfilament\nfilamentary\nfilamentous\nfilaments\nfilar\nfilaree\nfilarees\nfilaria\nfilariae\nfilarial\nfilarian\nfilariases\nfilariasis\nfilariid\nfilariids\nfilature\nfilatures\nfilbert\nfilberts\nfilch\nfilched\nfilcher\nfilchers\nfilches\nfilching\nfile\nfileable\nfiled\nfilefish\nfilefishes\nfilemot\nfilename\nfilenames\nfiler\nfilers\nfiles\nfilet\nfileted\nfileting\nfilets\nfilial\nfilially\nfiliate\nfiliated\nfiliates\nfiliating\nfiliation\nfiliations\nfilibeg\nfilibegs\nfilibuster\nfilibustered\nfilibusterer\nfilibusterers\nfilibustering\nfilibusters\nfilicide\nfilicides\nfiliform\nfiligree\nfiligreed\nfiligreeing\nfiligrees\nfiling\nfilings\nfiliopietistic\nfilister\nfilisters\nfill\nfille\nfilled\nfiller\nfillers\nfilles\nfillet\nfilleted\nfilleting\nfillets\nfillies\nfilling\nfillings\nfillip\nfilliped\nfilliping\nfillips\nfillo\nfillos\nfills\nfilly\nfilm\nfilmable\nfilmcard\nfilmcards\nfilmdom\nfilmdoms\nfilmed\nfilmer\nfilmers\nfilmgoer\nfilmgoers\nfilmic\nfilmically\nfilmier\nfilmiest\nfilmily\nfilminess\nfilminesses\nfilming\nfilmland\nfilmlands\nfilmmaker\nfilmmakers\nfilmmaking\nfilmmakings\nfilmographies\nfilmography\nfilms\nfilmset\nfilmsets\nfilmsetter\nfilmsetters\nfilmsetting\nfilmsettings\nfilmstrip\nfilmstrips\nfilmy\nfilo\nfilos\nfilose\nfils\nfilses\nfilter\nfilterabilities\nfilterability\nfilterable\nfiltered\nfilterer\nfilterers\nfiltering\nfilters\nfilth\nfilthier\nfilthiest\nfilthily\nfilthiness\nfilthinesses\nfilths\nfilthy\nfiltrable\nfiltrate\nfiltrated\nfiltrates\nfiltrating\nfiltration\nfiltrations\nfilum\nfimble\nfimbles\nfimbria\nfimbriae\nfimbrial\nfimbriate\nfimbriated\nfimbriation\nfimbriations\nfin\nfinable\nfinagle\nfinagled\nfinagler\nfinaglers\nfinagles\nfinagling\nfinal\nfinale\nfinales\nfinalis\nfinalise\nfinalised\nfinalises\nfinalising\nfinalism\nfinalisms\nfinalist\nfinalists\nfinalities\nfinality\nfinalization\nfinalizations\nfinalize\nfinalized\nfinalizes\nfinalizing\nfinally\nfinals\nfinance\nfinanced\nfinances\nfinancial\nfinancially\nfinancier\nfinanciers\nfinancing\nfinancings\nfinback\nfinbacks\nfinch\nfinches\nfind\nfindable\nfinder\nfinders\nfinding\nfindings\nfinds\nfine\nfineable\nfined\nfinely\nfineness\nfinenesses\nfiner\nfineries\nfinery\nfines\nfinespun\nfinesse\nfinessed\nfinesses\nfinessing\nfinest\nfinfish\nfinfishes\nfinfoot\nfinfoots\nfinger\nfingerboard\nfingerboards\nfingered\nfingerer\nfingerers\nfingerhold\nfingerholds\nfingering\nfingerings\nfingerlike\nfingerling\nfingerlings\nfingernail\nfingernails\nfingerpick\nfingerpicked\nfingerpicking\nfingerpickings\nfingerpicks\nfingerpost\nfingerposts\nfingerprint\nfingerprinted\nfingerprinting\nfingerprintings\nfingerprints\nfingers\nfingertip\nfingertips\nfinial\nfinialed\nfinials\nfinical\nfinically\nfinicalness\nfinicalnesses\nfinickier\nfinickiest\nfinickin\nfinickiness\nfinickinesses\nfinicking\nfinicky\nfinikin\nfiniking\nfining\nfinings\nfinis\nfinises\nfinish\nfinished\nfinisher\nfinishers\nfinishes\nfinishing\nfinite\nfinitely\nfiniteness\nfinitenesses\nfinites\nfinitude\nfinitudes\nfink\nfinked\nfinking\nfinks\nfinless\nfinlike\nfinmark\nfinmarks\nfinned\nfinnickier\nfinnickiest\nfinnicky\nfinnier\nfinniest\nfinning\nfinnmark\nfinnmarks\nfinny\nfino\nfinochio\nfinochios\nfinos\nfins\nfiord\nfiords\nfioritura\nfioriture\nfipple\nfipples\nfique\nfiques\nfir\nfire\nfireable\nfirearm\nfirearms\nfireback\nfirebacks\nfireball\nfireballer\nfireballers\nfireballing\nfireballs\nfirebase\nfirebases\nfirebird\nfirebirds\nfireboat\nfireboats\nfirebomb\nfirebombed\nfirebombing\nfirebombs\nfirebox\nfireboxes\nfirebrand\nfirebrands\nfirebrat\nfirebrats\nfirebreak\nfirebreaks\nfirebrick\nfirebricks\nfirebug\nfirebugs\nfireclay\nfireclays\nfirecracker\nfirecrackers\nfired\nfiredamp\nfiredamps\nfiredog\nfiredogs\nfiredrake\nfiredrakes\nfirefang\nfirefanged\nfirefanging\nfirefangs\nfirefight\nfirefighter\nfirefighters\nfirefighting\nfirefightings\nfirefights\nfireflies\nfirefly\nfireguard\nfireguards\nfirehall\nfirehalls\nfirehose\nfirehoses\nfirehouse\nfirehouses\nfireless\nfirelight\nfirelights\nfirelit\nfirelock\nfirelocks\nfireman\nfiremanic\nfiremen\nfirepan\nfirepans\nfirepink\nfirepinks\nfireplace\nfireplaced\nfireplaces\nfireplug\nfireplugs\nfirepot\nfirepots\nfirepower\nfirepowers\nfireproof\nfireproofed\nfireproofing\nfireproofs\nfirer\nfireroom\nfirerooms\nfirers\nfires\nfireside\nfiresides\nfirestone\nfirestones\nfirestorm\nfirestorms\nfirethorn\nfirethorns\nfiretrap\nfiretraps\nfirewall\nfirewalled\nfirewalling\nfirewalls\nfirewater\nfirewaters\nfireweed\nfireweeds\nfirewood\nfirewoods\nfirework\nfireworks\nfireworm\nfireworms\nfiring\nfirings\nfirkin\nfirkins\nfirm\nfirmament\nfirmamental\nfirmaments\nfirman\nfirmans\nfirmed\nfirmer\nfirmers\nfirmest\nfirming\nfirmly\nfirmness\nfirmnesses\nfirms\nfirmware\nfirmwares\nfirn\nfirns\nfirry\nfirs\nfirst\nfirstborn\nfirstborns\nfirstfruits\nfirsthand\nfirstling\nfirstlings\nfirstly\nfirsts\nfirth\nfirths\nfisc\nfiscal\nfiscally\nfiscals\nfiscs\nfish\nfishabilities\nfishability\nfishable\nfishbolt\nfishbolts\nfishbone\nfishbones\nfishbowl\nfishbowls\nfished\nfisher\nfisherfolk\nfisheries\nfisherman\nfishermen\nfishers\nfisherwoman\nfisherwomen\nfishery\nfishes\nfisheye\nfisheyes\nfishgig\nfishgigs\nfishhook\nfishhooks\nfishier\nfishiest\nfishily\nfishing\nfishings\nfishless\nfishlike\nfishline\nfishlines\nfishmeal\nfishmeals\nfishmonger\nfishmongers\nfishnet\nfishnets\nfishplate\nfishplates\nfishpole\nfishpoles\nfishpond\nfishponds\nfishtail\nfishtailed\nfishtailing\nfishtails\nfishway\nfishways\nfishwife\nfishwives\nfishworm\nfishworms\nfishy\nfissate\nfissile\nfissilities\nfissility\nfission\nfissionabilities\nfissionability\nfissionable\nfissionables\nfissional\nfissioned\nfissioning\nfissions\nfissiparous\nfissiparousness\nfissiparousnesses\nfissiped\nfissipeds\nfissure\nfissured\nfissures\nfissuring\nfist\nfisted\nfistfight\nfistfights\nfistful\nfistfuls\nfistic\nfisticuffs\nfisting\nfistnote\nfistnotes\nfists\nfistula\nfistulae\nfistular\nfistulas\nfistulous\nfit\nfitch\nfitchee\nfitches\nfitchet\nfitchets\nfitchew\nfitchews\nfitchy\nfitful\nfitfully\nfitfulness\nfitfulnesses\nfitly\nfitment\nfitments\nfitness\nfitnesses\nfits\nfittable\nfitted\nfitter\nfitters\nfittest\nfitting\nfittingly\nfittingness\nfittingnesses\nfittings\nfive\nfivefold\nfivepins\nfiver\nfivers\nfives\nfix\nfixable\nfixate\nfixated\nfixates\nfixatif\nfixatifs\nfixating\nfixation\nfixations\nfixative\nfixatives\nfixed\nfixedly\nfixedness\nfixednesses\nfixer\nfixers\nfixes\nfixing\nfixings\nfixit\nfixities\nfixity\nfixt\nfixture\nfixtures\nfixure\nfixures\nfiz\nfizgig\nfizgigs\nfizz\nfizzed\nfizzer\nfizzers\nfizzes\nfizzier\nfizziest\nfizzing\nfizzle\nfizzled\nfizzles\nfizzling\nfizzy\nfjeld\nfjelds\nfjord\nfjords\nflab\nflabbergast\nflabbergasted\nflabbergasting\nflabbergastingly\nflabbergasts\nflabbier\nflabbiest\nflabbily\nflabbiness\nflabbinesses\nflabby\nflabella\nflabellate\nflabelliform\nflabellum\nflabs\nflaccid\nflaccidities\nflaccidity\nflaccidly\nflack\nflacked\nflackeries\nflackery\nflacking\nflacks\nflacon\nflacons\nflag\nflagella\nflagellant\nflagellantism\nflagellantisms\nflagellants\nflagellar\nflagellate\nflagellated\nflagellates\nflagellating\nflagellation\nflagellations\nflagellin\nflagellins\nflagellum\nflagellums\nflageolet\nflageolets\nflagged\nflagger\nflaggers\nflaggier\nflaggiest\nflagging\nflaggingly\nflaggings\nflaggy\nflagitious\nflagitiously\nflagitiousness\nflagitiousnesses\nflagless\nflagman\nflagmen\nflagon\nflagons\nflagpole\nflagpoles\nflagrance\nflagrances\nflagrancies\nflagrancy\nflagrant\nflagrantly\nflags\nflagship\nflagships\nflagstaff\nflagstaffs\nflagstaves\nflagstick\nflagsticks\nflagstone\nflagstones\nflail\nflailed\nflailing\nflails\nflair\nflairs\nflak\nflake\nflaked\nflaker\nflakers\nflakes\nflakey\nflakier\nflakiest\nflakily\nflakiness\nflakinesses\nflaking\nflaky\nflam\nflambe\nflambeau\nflambeaus\nflambeaux\nflambee\nflambeed\nflambeing\nflambes\nflamboyance\nflamboyances\nflamboyancies\nflamboyancy\nflamboyant\nflamboyantly\nflamboyants\nflame\nflamed\nflamen\nflamenco\nflamencos\nflamens\nflameout\nflameouts\nflameproof\nflameproofed\nflameproofer\nflameproofers\nflameproofing\nflameproofs\nflamer\nflamers\nflames\nflamethrower\nflamethrowers\nflamier\nflamiest\nflamines\nflaming\nflamingly\nflamingo\nflamingoes\nflamingos\nflammabilities\nflammability\nflammable\nflammables\nflammed\nflamming\nflams\nflamy\nflan\nflancard\nflancards\nflanerie\nflaneries\nflanes\nflaneur\nflaneurs\nflange\nflanged\nflanger\nflangers\nflanges\nflanging\nflank\nflanked\nflanken\nflankens\nflanker\nflankers\nflanking\nflanks\nflannel\nflanneled\nflannelette\nflannelettes\nflanneling\nflannelled\nflannelling\nflannelly\nflannelmouthed\nflannels\nflans\nflap\nflapdoodle\nflapdoodles\nflapjack\nflapjacks\nflapless\nflappable\nflapped\nflapper\nflappers\nflappier\nflappiest\nflapping\nflappy\nflaps\nflare\nflared\nflares\nflareup\nflareups\nflaring\nflaringly\nflash\nflashback\nflashbacks\nflashboard\nflashboards\nflashbulb\nflashbulbs\nflashcard\nflashcards\nflashcube\nflashcubes\nflashed\nflasher\nflashers\nflashes\nflashgun\nflashguns\nflashier\nflashiest\nflashily\nflashiness\nflashinesses\nflashing\nflashings\nflashlamp\nflashlamps\nflashlight\nflashlights\nflashover\nflashovers\nflashtube\nflashtubes\nflashy\nflask\nflasket\nflaskets\nflasks\nflat\nflatbed\nflatbeds\nflatboat\nflatboats\nflatcap\nflatcaps\nflatcar\nflatcars\nflatfeet\nflatfish\nflatfishes\nflatfoot\nflatfooted\nflatfooting\nflatfoots\nflathead\nflatheads\nflatiron\nflatirons\nflatland\nflatlander\nflatlanders\nflatlands\nflatlet\nflatlets\nflatline\nflatlined\nflatliner\nflatliners\nflatlines\nflatling\nflatlings\nflatlining\nflatlong\nflatly\nflatmate\nflatmates\nflatness\nflatnesses\nflats\nflatted\nflatten\nflattened\nflattener\nflatteners\nflattening\nflattens\nflatter\nflattered\nflatterer\nflatterers\nflatteries\nflattering\nflatteringly\nflatters\nflattery\nflattest\nflatting\nflattish\nflattop\nflattops\nflatulence\nflatulences\nflatulencies\nflatulency\nflatulent\nflatulently\nflatus\nflatuses\nflatware\nflatwares\nflatwash\nflatwashes\nflatways\nflatwise\nflatwork\nflatworks\nflatworm\nflatworms\nflaunt\nflaunted\nflaunter\nflaunters\nflauntier\nflauntiest\nflaunting\nflauntingly\nflaunts\nflaunty\nflautist\nflautists\nflavanol\nflavanols\nflavanone\nflavanones\nflavin\nflavine\nflavines\nflavins\nflavone\nflavones\nflavonoid\nflavonoids\nflavonol\nflavonols\nflavoprotein\nflavoproteins\nflavor\nflavored\nflavorer\nflavorers\nflavorful\nflavorfully\nflavoring\nflavorings\nflavorist\nflavorists\nflavorless\nflavors\nflavorsome\nflavory\nflavour\nflavoured\nflavouring\nflavours\nflavoury\nflaw\nflawed\nflawier\nflawiest\nflawing\nflawless\nflawlessly\nflawlessness\nflawlessnesses\nflaws\nflawy\nflax\nflaxen\nflaxes\nflaxier\nflaxiest\nflaxseed\nflaxseeds\nflaxy\nflay\nflayed\nflayer\nflayers\nflaying\nflays\nflea\nfleabag\nfleabags\nfleabane\nfleabanes\nfleabite\nfleabites\nfleahopper\nfleahoppers\nfleam\nfleams\nfleapit\nfleapits\nfleas\nfleawort\nfleaworts\nfleche\nfleches\nflechette\nflechettes\nfleck\nflecked\nflecking\nflecks\nflecky\nflection\nflections\nfled\nfledge\nfledged\nfledges\nfledgier\nfledgiest\nfledging\nfledgling\nfledglings\nfledgy\nflee\nfleece\nfleeced\nfleecer\nfleecers\nfleeces\nfleech\nfleeched\nfleeches\nfleeching\nfleecier\nfleeciest\nfleecily\nfleecing\nfleecy\nfleeing\nfleer\nfleered\nfleering\nfleeringly\nfleers\nflees\nfleet\nfleeted\nfleeter\nfleetest\nfleeting\nfleetingly\nfleetingness\nfleetingnesses\nfleetly\nfleetness\nfleetnesses\nfleets\nfleishig\nflemish\nflemished\nflemishes\nflemishing\nflench\nflenched\nflenches\nflenching\nflense\nflensed\nflenser\nflensers\nflenses\nflensing\nflesh\nfleshed\nflesher\nfleshers\nfleshes\nfleshier\nfleshiest\nfleshiness\nfleshinesses\nfleshing\nfleshings\nfleshlier\nfleshliest\nfleshly\nfleshment\nfleshments\nfleshpot\nfleshpots\nfleshy\nfletch\nfletched\nfletcher\nfletchers\nfletches\nfletching\nfletchings\nfleury\nflew\nflews\nflex\nflexagon\nflexagons\nflexed\nflexes\nflexibilities\nflexibility\nflexible\nflexibly\nflexile\nflexing\nflexion\nflexions\nflexitime\nflexitimes\nflexographic\nflexographically\nflexographies\nflexography\nflexor\nflexors\nflextime\nflextimes\nflexuose\nflexuous\nflexural\nflexure\nflexures\nfley\nfleyed\nfleying\nfleys\nflibbertigibbet\nflibbertigibbets\nflibbertigibbety\nflic\nflichter\nflichtered\nflichtering\nflichters\nflick\nflicked\nflicker\nflickered\nflickering\nflickeringly\nflickers\nflickery\nflicking\nflicks\nflics\nflied\nflier\nfliers\nflies\nfliest\nflight\nflighted\nflightier\nflightiest\nflightily\nflightiness\nflightinesses\nflighting\nflightless\nflights\nflighty\nflimflam\nflimflammed\nflimflammer\nflimflammeries\nflimflammers\nflimflammery\nflimflamming\nflimflams\nflimsier\nflimsies\nflimsiest\nflimsily\nflimsiness\nflimsinesses\nflimsy\nflinch\nflinched\nflincher\nflinchers\nflinches\nflinching\nflinder\nflinders\nfling\nflinger\nflingers\nflinging\nflings\nflinkite\nflinkites\nflint\nflinted\nflintier\nflintiest\nflintily\nflintiness\nflintinesses\nflinting\nflintlike\nflintlock\nflintlocks\nflints\nflinty\nflip\nflippancies\nflippancy\nflippant\nflippantly\nflipped\nflipper\nflippers\nflippest\nflipping\nflippy\nflips\nflirt\nflirtation\nflirtations\nflirtatious\nflirtatiously\nflirtatiousness\nflirtatiousnesses\nflirted\nflirter\nflirters\nflirtier\nflirtiest\nflirting\nflirts\nflirty\nflit\nflitch\nflitched\nflitches\nflitching\nflite\nflited\nflites\nfliting\nflits\nflitted\nflitter\nflittered\nflittering\nflitters\nflitting\nflivver\nflivvers\nfloat\nfloatage\nfloatages\nfloatation\nfloatations\nfloated\nfloatel\nfloatels\nfloater\nfloaters\nfloatier\nfloatiest\nfloating\nfloatplane\nfloatplanes\nfloats\nfloaty\nfloc\nflocced\nflocci\nfloccing\nfloccose\nflocculant\nflocculants\nflocculate\nflocculated\nflocculates\nflocculating\nflocculation\nflocculations\nflocculator\nflocculators\nfloccule\nflocculent\nfloccules\nflocculi\nflocculus\nfloccus\nflock\nflocked\nflockier\nflockiest\nflocking\nflockings\nflocks\nflocky\nflocs\nfloe\nfloes\nflog\nflogged\nflogger\nfloggers\nflogging\nfloggings\nflogs\nflokati\nflokatis\nflong\nflongs\nflood\nflooded\nflooder\nflooders\nfloodgate\nfloodgates\nflooding\nfloodlight\nfloodlighted\nfloodlighting\nfloodlights\nfloodlit\nfloodplain\nfloodplains\nfloods\nfloodwater\nfloodwaters\nfloodway\nfloodways\nflooey\nflooie\nfloor\nfloorage\nfloorages\nfloorboard\nfloorboards\nfloorcloth\nfloorcloths\nfloored\nfloorer\nfloorers\nflooring\nfloorings\nfloors\nfloorwalker\nfloorwalkers\nfloosie\nfloosies\nfloosy\nfloozie\nfloozies\nfloozy\nflop\nflophouse\nflophouses\nflopover\nflopovers\nflopped\nflopper\nfloppers\nfloppier\nfloppies\nfloppiest\nfloppily\nfloppiness\nfloppinesses\nflopping\nfloppy\nflops\nflora\nflorae\nfloral\nflorally\nflorals\nfloras\nflorence\nflorences\nflorescence\nflorescences\nflorescent\nfloret\nflorets\nfloriated\nfloriation\nfloriations\nfloribunda\nfloribundas\nfloricultural\nfloriculture\nfloricultures\nfloriculturist\nfloriculturists\nflorid\nfloridities\nfloridity\nfloridly\nfloridness\nfloridnesses\nfloriferous\nfloriferousness\nfloriferousnesses\nflorigen\nflorigenic\nflorigens\nflorilegia\nflorilegium\nflorin\nflorins\nflorist\nfloristic\nfloristically\nfloristries\nfloristry\nflorists\nfloruit\nfloruits\nfloss\nflossed\nflosses\nflossie\nflossier\nflossies\nflossiest\nflossily\nflossing\nflossy\nflota\nflotage\nflotages\nflotas\nflotation\nflotations\nflotilla\nflotillas\nflotsam\nflotsams\nflounce\nflounced\nflounces\nflouncier\nflounciest\nflouncing\nflouncings\nflouncy\nflounder\nfloundered\nfloundering\nflounders\nflour\nfloured\nflouring\nflourish\nflourished\nflourisher\nflourishers\nflourishes\nflourishing\nflourishingly\nflourless\nflours\nfloury\nflout\nflouted\nflouter\nflouters\nflouting\nflouts\nflow\nflowage\nflowages\nflowchart\nflowcharting\nflowchartings\nflowcharts\nflowed\nflower\nflowerage\nflowerages\nflowerbed\nflowerbeds\nflowered\nflowerer\nflowerers\nfloweret\nflowerets\nflowerette\nflowerettes\nflowerful\nflowerier\nfloweriest\nflowerily\nfloweriness\nflowerinesses\nflowering\nflowerless\nflowerlike\nflowerpot\nflowerpots\nflowers\nflowery\nflowing\nflowingly\nflowmeter\nflowmeters\nflown\nflows\nflowstone\nflowstones\nflu\nflub\nflubbed\nflubber\nflubbers\nflubbing\nflubdub\nflubdubs\nflubs\nfluctuant\nfluctuate\nfluctuated\nfluctuates\nfluctuating\nfluctuation\nfluctuational\nfluctuations\nflue\nflued\nfluegelhorn\nfluegelhorns\nfluencies\nfluency\nfluent\nfluently\nflueric\nfluerics\nflues\nfluff\nfluffed\nfluffier\nfluffiest\nfluffily\nfluffiness\nfluffinesses\nfluffing\nfluffs\nfluffy\nflugelhorn\nflugelhornist\nflugelhornists\nflugelhorns\nfluid\nfluidal\nfluidally\nfluidextract\nfluidextracts\nfluidic\nfluidics\nfluidise\nfluidised\nfluidises\nfluidising\nfluidities\nfluidity\nfluidization\nfluidizations\nfluidize\nfluidized\nfluidizer\nfluidizers\nfluidizes\nfluidizing\nfluidly\nfluidness\nfluidnesses\nfluidram\nfluidrams\nfluids\nfluke\nfluked\nflukes\nflukey\nflukier\nflukiest\nfluking\nfluky\nflume\nflumed\nflumes\nfluming\nflummeries\nflummery\nflummox\nflummoxed\nflummoxes\nflummoxing\nflump\nflumped\nflumping\nflumps\nflung\nflunk\nflunked\nflunker\nflunkers\nflunkey\nflunkeys\nflunkies\nflunking\nflunks\nflunky\nfluor\nfluorene\nfluorenes\nfluoresce\nfluoresced\nfluorescein\nfluoresceins\nfluorescence\nfluorescences\nfluorescent\nfluorescents\nfluorescer\nfluorescers\nfluoresces\nfluorescing\nfluoric\nfluorid\nfluoridate\nfluoridated\nfluoridates\nfluoridating\nfluoridation\nfluoridations\nfluoride\nfluorides\nfluorids\nfluorimeter\nfluorimeters\nfluorimetric\nfluorimetries\nfluorimetry\nfluorin\nfluorinate\nfluorinated\nfluorinates\nfluorinating\nfluorination\nfluorinations\nfluorine\nfluorines\nfluorins\nfluorite\nfluorites\nfluorocarbon\nfluorocarbons\nfluorochrome\nfluorochromes\nfluorographic\nfluorographies\nfluorography\nfluorometer\nfluorometers\nfluorometric\nfluorometries\nfluorometry\nfluoroscope\nfluoroscoped\nfluoroscopes\nfluoroscopic\nfluoroscopically\nfluoroscopies\nfluoroscoping\nfluoroscopist\nfluoroscopists\nfluoroscopy\nfluoroses\nfluorosis\nfluorotic\nfluorouracil\nfluorouracils\nfluors\nfluorspar\nfluorspars\nfluoxetine\nfluoxetines\nfluphenazine\nfluphenazines\nflurried\nflurries\nflurry\nflurrying\nflus\nflush\nflushable\nflushed\nflusher\nflushers\nflushes\nflushest\nflushing\nflushness\nflushnesses\nfluster\nflustered\nflusteredly\nflustering\nflusters\nflute\nfluted\nflutelike\nfluter\nfluters\nflutes\nflutey\nflutier\nflutiest\nfluting\nflutings\nflutist\nflutists\nflutter\nflutterboard\nflutterboards\nfluttered\nflutterer\nflutterers\nfluttering\nflutters\nfluttery\nfluty\nfluvial\nfluviatile\nflux\nfluxed\nfluxes\nfluxgate\nfluxgates\nfluxing\nfluxion\nfluxional\nfluxions\nfluyt\nfluyts\nfly\nflyable\nflyaway\nflyaways\nflybelt\nflybelts\nflyblew\nflyblow\nflyblowing\nflyblown\nflyblows\nflyboat\nflyboats\nflyboy\nflyboys\nflybridge\nflybridges\nflyby\nflybys\nflycatcher\nflycatchers\nflyer\nflyers\nflying\nflyings\nflyleaf\nflyleaves\nflyless\nflyman\nflymen\nflyoff\nflyoffs\nflyover\nflyovers\nflypaper\nflypapers\nflypast\nflypasts\nflysch\nflysches\nflyspeck\nflyspecked\nflyspecking\nflyspecks\nflyswatter\nflyswatters\nflyte\nflyted\nflytes\nflytier\nflytiers\nflyting\nflytings\nflytrap\nflytraps\nflyway\nflyways\nflyweight\nflyweights\nflywheel\nflywheels\nfoal\nfoaled\nfoaling\nfoals\nfoam\nfoamable\nfoamed\nfoamer\nfoamers\nfoamflower\nfoamflowers\nfoamier\nfoamiest\nfoamily\nfoaminess\nfoaminesses\nfoaming\nfoamless\nfoamlike\nfoams\nfoamy\nfob\nfobbed\nfobbing\nfobs\nfocaccia\nfocaccias\nfocal\nfocalise\nfocalised\nfocalises\nfocalising\nfocalization\nfocalizations\nfocalize\nfocalized\nfocalizes\nfocalizing\nfocally\nfoci\nfocus\nfocusable\nfocused\nfocuser\nfocusers\nfocuses\nfocusing\nfocusless\nfocussed\nfocusses\nfocussing\nfodder\nfoddered\nfoddering\nfodders\nfodgel\nfoe\nfoehn\nfoehns\nfoeman\nfoemen\nfoes\nfoetal\nfoetid\nfoetor\nfoetors\nfoetus\nfoetuses\nfog\nfogbound\nfogbow\nfogbows\nfogdog\nfogdogs\nfogey\nfogeys\nfogfruit\nfogfruits\nfoggage\nfoggages\nfogged\nfogger\nfoggers\nfoggier\nfoggiest\nfoggily\nfogginess\nfogginesses\nfogging\nfoggy\nfoghorn\nfoghorns\nfogie\nfogies\nfogless\nfogs\nfogy\nfogyish\nfogyism\nfogyisms\nfoh\nfohn\nfohns\nfoible\nfoibles\nfoil\nfoilable\nfoiled\nfoiling\nfoils\nfoilsman\nfoilsmen\nfoin\nfoined\nfoining\nfoins\nfoison\nfoisons\nfoist\nfoisted\nfoisting\nfoists\nfolacin\nfolacins\nfolate\nfolates\nfold\nfoldable\nfoldaway\nfoldboat\nfoldboats\nfolded\nfolder\nfolderol\nfolderols\nfolders\nfolding\nfoldout\nfoldouts\nfolds\nfolia\nfoliaceous\nfoliage\nfoliaged\nfoliages\nfoliar\nfoliate\nfoliated\nfoliates\nfoliating\nfoliation\nfoliations\nfolio\nfolioed\nfolioing\nfolios\nfoliose\nfolious\nfolium\nfoliums\nfolk\nfolkie\nfolkies\nfolkish\nfolkishness\nfolkishnesses\nfolklife\nfolklike\nfolklives\nfolklore\nfolklores\nfolkloric\nfolklorish\nfolklorist\nfolkloristic\nfolklorists\nfolkmoot\nfolkmoots\nfolkmot\nfolkmote\nfolkmotes\nfolkmots\nfolks\nfolksier\nfolksiest\nfolksily\nfolksiness\nfolksinesses\nfolksinger\nfolksingers\nfolksinging\nfolksingings\nfolksong\nfolksongs\nfolksy\nfolktale\nfolktales\nfolkway\nfolkways\nfolky\nfolles\nfollicle\nfollicles\nfollicular\nfolliculitis\nfolliculitises\nfollies\nfollis\nfollow\nfollowed\nfollower\nfollowers\nfollowership\nfollowerships\nfollowing\nfollowings\nfollows\nfollowup\nfollowups\nfolly\nfoment\nfomentation\nfomentations\nfomented\nfomenter\nfomenters\nfomenting\nfoments\nfomite\nfomites\nfon\nfond\nfondant\nfondants\nfonded\nfonder\nfondest\nfonding\nfondle\nfondled\nfondler\nfondlers\nfondles\nfondling\nfondlings\nfondly\nfondness\nfondnesses\nfonds\nfondu\nfondue\nfondues\nfondus\nfons\nfont\nfontal\nfontanel\nfontanelle\nfontanelles\nfontanels\nfontina\nfontinas\nfonts\nfood\nfoodie\nfoodies\nfoodless\nfoodlessness\nfoodlessnesses\nfoods\nfoodstuff\nfoodstuffs\nfoodways\nfoofaraw\nfoofaraws\nfool\nfooled\nfooleries\nfoolery\nfoolfish\nfoolfishes\nfoolhardier\nfoolhardiest\nfoolhardily\nfoolhardiness\nfoolhardinesses\nfoolhardy\nfooling\nfoolish\nfoolisher\nfoolishest\nfoolishly\nfoolishness\nfoolishnesses\nfoolproof\nfools\nfoolscap\nfoolscaps\nfoot\nfootage\nfootages\nfootball\nfootballer\nfootballers\nfootballs\nfootbath\nfootbaths\nfootboard\nfootboards\nfootboy\nfootboys\nfootbridge\nfootbridges\nfootcloth\nfootcloths\nfootdragger\nfootdraggers\nfooted\nfooter\nfooters\nfootfall\nfootfalls\nfootfault\nfootfaulted\nfootfaulting\nfootfaults\nfootgear\nfootgears\nfoothill\nfoothills\nfoothold\nfootholds\nfootie\nfootier\nfooties\nfootiest\nfooting\nfootings\nfootlambert\nfootlamberts\nfootle\nfootled\nfootler\nfootlers\nfootles\nfootless\nfootlessly\nfootlessness\nfootlessnesses\nfootlights\nfootlike\nfootling\nfootlocker\nfootlockers\nfootloose\nfootman\nfootmark\nfootmarks\nfootmen\nfootnote\nfootnoted\nfootnotes\nfootnoting\nfootpace\nfootpaces\nfootpad\nfootpads\nfootpath\nfootpaths\nfootprint\nfootprints\nfootrace\nfootraces\nfootrest\nfootrests\nfootrope\nfootropes\nfoots\nfootsie\nfootsies\nfootslog\nfootslogged\nfootslogger\nfootsloggers\nfootslogging\nfootslogs\nfootsore\nfootsoreness\nfootsorenesses\nfootstep\nfootsteps\nfootstone\nfootstones\nfootstool\nfootstools\nfootsy\nfootwall\nfootwalls\nfootway\nfootways\nfootwear\nfootwork\nfootworks\nfootworn\nfooty\nfoozle\nfoozled\nfoozler\nfoozlers\nfoozles\nfoozling\nfop\nfopped\nfopperies\nfoppery\nfopping\nfoppish\nfoppishly\nfoppishness\nfoppishnesses\nfops\nfor\nfora\nforage\nforaged\nforager\nforagers\nforages\nforaging\nforam\nforamen\nforamens\nforamina\nforaminal\nforaminifer\nforaminifera\nforaminiferal\nforaminiferan\nforaminiferans\nforaminifers\nforaminous\nforams\nforay\nforayed\nforayer\nforayers\nforaying\nforays\nforb\nforbad\nforbade\nforbear\nforbearance\nforbearances\nforbearer\nforbearers\nforbearing\nforbears\nforbid\nforbidal\nforbidals\nforbiddance\nforbiddances\nforbidden\nforbidder\nforbidders\nforbidding\nforbiddingly\nforbids\nforbode\nforboded\nforbodes\nforboding\nforbore\nforborne\nforbs\nforby\nforbye\nforce\nforced\nforcedly\nforceful\nforcefully\nforcefulness\nforcefulnesses\nforceless\nforcemeat\nforcemeats\nforceps\nforcepslike\nforcer\nforcers\nforces\nforcible\nforcibleness\nforciblenesses\nforcibly\nforcing\nforcipes\nford\nfordable\nforded\nfordid\nfording\nfordless\nfordo\nfordoes\nfordoing\nfordone\nfords\nfore\nforearm\nforearmed\nforearming\nforearms\nforebay\nforebays\nforebear\nforebears\nforebode\nforeboded\nforeboder\nforeboders\nforebodes\nforebodies\nforeboding\nforebodingly\nforebodingness\nforebodingnesses\nforebodings\nforebody\nforeboom\nforebooms\nforebrain\nforebrains\nforeby\nforebye\nforecaddie\nforecaddies\nforecast\nforecastable\nforecasted\nforecaster\nforecasters\nforecasting\nforecastle\nforecastles\nforecasts\nforecheck\nforechecked\nforechecker\nforecheckers\nforechecking\nforechecks\nforeclose\nforeclosed\nforecloses\nforeclosing\nforeclosure\nforeclosures\nforecourt\nforecourts\nforedate\nforedated\nforedates\nforedating\nforedeck\nforedecks\nforedid\nforedo\nforedoes\nforedoing\nforedone\nforedoom\nforedoomed\nforedooming\nforedooms\nforeface\nforefaces\nforefather\nforefathers\nforefeel\nforefeeling\nforefeels\nforefeet\nforefelt\nforefend\nforefended\nforefending\nforefends\nforefinger\nforefingers\nforefoot\nforefront\nforefronts\nforegather\nforegathered\nforegathering\nforegathers\nforego\nforegoer\nforegoers\nforegoes\nforegoing\nforegone\nforeground\nforegrounded\nforegrounding\nforegrounds\nforegut\nforeguts\nforehand\nforehanded\nforehandedly\nforehandedness\nforehandednesses\nforehands\nforehead\nforeheads\nforehoof\nforehoofs\nforehooves\nforeign\nforeigner\nforeigners\nforeignism\nforeignisms\nforeignness\nforeignnesses\nforejudge\nforejudged\nforejudges\nforejudging\nforeknew\nforeknow\nforeknowing\nforeknowledge\nforeknowledges\nforeknown\nforeknows\nforeladies\nforelady\nforeland\nforelands\nforeleg\nforelegs\nforelimb\nforelimbs\nforelock\nforelocked\nforelocking\nforelocks\nforeman\nforemanship\nforemanships\nforemast\nforemasts\nforemen\nforemilk\nforemilks\nforemost\nforemother\nforemothers\nforename\nforenamed\nforenames\nforenoon\nforenoons\nforensic\nforensically\nforensics\nforeordain\nforeordained\nforeordaining\nforeordains\nforeordination\nforeordinations\nforepart\nforeparts\nforepassed\nforepast\nforepaw\nforepaws\nforepeak\nforepeaks\nforeplay\nforeplays\nforequarter\nforequarters\nforeran\nforerank\nforeranks\nforereach\nforereached\nforereaches\nforereaching\nforerun\nforerunner\nforerunners\nforerunning\nforeruns\nfores\nforesaid\nforesail\nforesails\nforesaw\nforesee\nforeseeabilities\nforeseeability\nforeseeable\nforeseeing\nforeseen\nforeseer\nforeseers\nforesees\nforeshadow\nforeshadowed\nforeshadower\nforeshadowers\nforeshadowing\nforeshadows\nforeshank\nforeshanks\nforesheet\nforesheets\nforeshock\nforeshocks\nforeshore\nforeshores\nforeshorten\nforeshortened\nforeshortening\nforeshortens\nforeshow\nforeshowed\nforeshowing\nforeshown\nforeshows\nforeside\nforesides\nforesight\nforesighted\nforesightedly\nforesightedness\nforesightednesses\nforesightful\nforesights\nforeskin\nforeskins\nforespeak\nforespeaking\nforespeaks\nforespoke\nforespoken\nforest\nforestage\nforestages\nforestal\nforestall\nforestalled\nforestaller\nforestallers\nforestalling\nforestallment\nforestallments\nforestalls\nforestation\nforestations\nforestay\nforestays\nforestaysail\nforestaysails\nforested\nforester\nforesters\nforestial\nforesting\nforestland\nforestlands\nforestries\nforestry\nforests\nforeswear\nforeswearing\nforeswears\nforeswore\nforesworn\nforetaste\nforetasted\nforetastes\nforetasting\nforetell\nforeteller\nforetellers\nforetelling\nforetells\nforethought\nforethoughtful\nforethoughtfully\nforethoughtfulness\nforethoughtfulnesses\nforethoughts\nforetime\nforetimes\nforetoken\nforetokened\nforetokening\nforetokens\nforetold\nforetop\nforetopman\nforetopmen\nforetops\nforever\nforevermore\nforeverness\nforevernesses\nforevers\nforewarn\nforewarned\nforewarning\nforewarns\nforewent\nforewing\nforewings\nforewoman\nforewomen\nforeword\nforewords\nforeworn\nforeyard\nforeyards\nforfeit\nforfeitable\nforfeited\nforfeiter\nforfeiters\nforfeiting\nforfeits\nforfeiture\nforfeitures\nforfend\nforfended\nforfending\nforfends\nforgat\nforgather\nforgathered\nforgathering\nforgathers\nforgave\nforge\nforgeabilities\nforgeability\nforgeable\nforged\nforger\nforgeries\nforgers\nforgery\nforges\nforget\nforgetful\nforgetfully\nforgetfulness\nforgetfulnesses\nforgetive\nforgets\nforgettable\nforgetter\nforgetters\nforgetting\nforging\nforgings\nforgivable\nforgivably\nforgive\nforgiven\nforgiveness\nforgivenesses\nforgiver\nforgivers\nforgives\nforgiving\nforgivingly\nforgivingness\nforgivingnesses\nforgo\nforgoer\nforgoers\nforgoes\nforgoing\nforgone\nforgot\nforgotten\nforint\nforints\nforjudge\nforjudged\nforjudges\nforjudging\nfork\nforkball\nforkballs\nforked\nforkedly\nforker\nforkers\nforkful\nforkfuls\nforkier\nforkiest\nforking\nforkless\nforklift\nforklifted\nforklifting\nforklifts\nforklike\nforks\nforksful\nforky\nforlorn\nforlorner\nforlornest\nforlornly\nforlornness\nforlornnesses\nform\nformabilities\nformability\nformable\nformal\nformaldehyde\nformaldehydes\nformalin\nformalins\nformalise\nformalised\nformalises\nformalising\nformalism\nformalisms\nformalist\nformalistic\nformalists\nformalities\nformality\nformalizable\nformalization\nformalizations\nformalize\nformalized\nformalizer\nformalizers\nformalizes\nformalizing\nformally\nformalness\nformalnesses\nformals\nformalwear\nformamide\nformamides\nformant\nformants\nformat\nformate\nformates\nformation\nformations\nformative\nformatively\nformatives\nformats\nformatted\nformatter\nformatters\nformatting\nforme\nformed\nformee\nformer\nformerly\nformers\nformes\nformfitting\nformful\nformic\nformicaries\nformicary\nformidabilities\nformidability\nformidable\nformidableness\nformidablenesses\nformidably\nforming\nformless\nformlessly\nformlessness\nformlessnesses\nformol\nformols\nforms\nformula\nformulae\nformulaic\nformulaically\nformularies\nformularization\nformularizations\nformularize\nformularized\nformularizer\nformularizers\nformularizes\nformularizing\nformulary\nformulas\nformulate\nformulated\nformulates\nformulating\nformulation\nformulations\nformulator\nformulators\nformulize\nformulized\nformulizes\nformulizing\nformwork\nformworks\nformyl\nformyls\nfornical\nfornicate\nfornicated\nfornicates\nfornicating\nfornication\nfornications\nfornicator\nfornicators\nfornices\nfornix\nforrader\nforrarder\nforrit\nforsake\nforsaken\nforsaker\nforsakers\nforsakes\nforsaking\nforsook\nforsooth\nforspent\nforswear\nforswearing\nforswears\nforswore\nforsworn\nforsythia\nforsythias\nfort\nfortalice\nfortalices\nforte\nfortepiano\nfortepianos\nfortes\nforth\nforthcoming\nforthright\nforthrightly\nforthrightness\nforthrightnesses\nforthrights\nforthwith\nforties\nfortieth\nfortieths\nfortification\nfortifications\nfortified\nfortifier\nfortifiers\nfortifies\nfortify\nfortifying\nfortis\nfortissimi\nfortissimo\nfortissimos\nfortitude\nfortitudes\nfortnight\nfortnightlies\nfortnightly\nfortnights\nfortress\nfortressed\nfortresses\nfortressing\nfortresslike\nforts\nfortuities\nfortuitous\nfortuitously\nfortuitousness\nfortuitousnesses\nfortuity\nfortunate\nfortunately\nfortunateness\nfortunatenesses\nfortune\nfortuned\nfortunes\nfortuneteller\nfortunetellers\nfortunetelling\nfortunetellings\nfortuning\nforty\nfortyish\nforum\nforums\nforward\nforwarded\nforwarder\nforwarders\nforwardest\nforwarding\nforwardly\nforwardness\nforwardnesses\nforwards\nforwent\nforwhy\nforworn\nforzando\nforzandos\nfoss\nfossa\nfossae\nfossas\nfossate\nfosse\nfosses\nfossette\nfossettes\nfossick\nfossicked\nfossicker\nfossickers\nfossicking\nfossicks\nfossil\nfossiliferous\nfossilise\nfossilised\nfossilises\nfossilising\nfossilization\nfossilizations\nfossilize\nfossilized\nfossilizes\nfossilizing\nfossils\nfossorial\nfoster\nfosterage\nfosterages\nfostered\nfosterer\nfosterers\nfostering\nfosterling\nfosterlings\nfosters\nfou\nfouette\nfouettes\nfought\nfoughten\nfoul\nfoulard\nfoulards\nfoulbrood\nfoulbroods\nfouled\nfouler\nfoulest\nfouling\nfoulings\nfoully\nfoulmouthed\nfoulness\nfoulnesses\nfouls\nfound\nfoundation\nfoundational\nfoundationally\nfoundationless\nfoundations\nfounded\nfounder\nfoundered\nfoundering\nfounders\nfounding\nfoundling\nfoundlings\nfoundries\nfoundry\nfounds\nfount\nfountain\nfountained\nfountainhead\nfountainheads\nfountaining\nfountains\nfounts\nfour\nfourchee\nfourdrinier\nfourdriniers\nfourfold\nfourgon\nfourgons\nfourplex\nfourplexes\nfourragere\nfourrageres\nfours\nfourscore\nfoursome\nfoursomes\nfoursquare\nfourteen\nfourteener\nfourteeners\nfourteens\nfourteenth\nfourteenths\nfourth\nfourthly\nfourths\nfovea\nfoveae\nfoveal\nfoveas\nfoveate\nfoveated\nfoveola\nfoveolae\nfoveolar\nfoveolas\nfoveole\nfoveoles\nfoveolet\nfoveolets\nfowl\nfowled\nfowler\nfowlers\nfowling\nfowlings\nfowlpox\nfowlpoxes\nfowls\nfox\nfoxed\nfoxes\nfoxfire\nfoxfires\nfoxfish\nfoxfishes\nfoxglove\nfoxgloves\nfoxhole\nfoxholes\nfoxhound\nfoxhounds\nfoxhunt\nfoxhunted\nfoxhunter\nfoxhunters\nfoxhunting\nfoxhuntings\nfoxhunts\nfoxier\nfoxiest\nfoxily\nfoxiness\nfoxinesses\nfoxing\nfoxings\nfoxlike\nfoxskin\nfoxskins\nfoxtail\nfoxtails\nfoxtrot\nfoxtrots\nfoxtrotted\nfoxtrotting\nfoxy\nfoy\nfoyer\nfoyers\nfoys\nfozier\nfoziest\nfoziness\nfozinesses\nfozy\nfrabjous\nfracas\nfracases\nfractal\nfractals\nfracted\nfracti\nfraction\nfractional\nfractionalization\nfractionalizations\nfractionalize\nfractionalized\nfractionalizes\nfractionalizing\nfractionally\nfractionate\nfractionated\nfractionates\nfractionating\nfractionation\nfractionations\nfractionator\nfractionators\nfractioned\nfractioning\nfractions\nfractious\nfractiously\nfractiousness\nfractiousnesses\nfractur\nfracture\nfractured\nfractures\nfracturing\nfracturs\nfractus\nfrae\nfraena\nfraenum\nfraenums\nfrag\nfragged\nfragging\nfraggings\nfragile\nfragilities\nfragility\nfragment\nfragmental\nfragmentally\nfragmentarily\nfragmentariness\nfragmentarinesses\nfragmentary\nfragmentate\nfragmentated\nfragmentates\nfragmentating\nfragmentation\nfragmentations\nfragmented\nfragmenting\nfragmentize\nfragmentized\nfragmentizes\nfragmentizing\nfragments\nfragrance\nfragrances\nfragrancies\nfragrancy\nfragrant\nfragrantly\nfrags\nfrail\nfrailer\nfrailest\nfrailly\nfrailness\nfrailnesses\nfrails\nfrailties\nfrailty\nfraise\nfraises\nfraktur\nfrakturs\nframable\nframbesia\nframbesias\nframboise\nframboises\nframe\nframeable\nframed\nframer\nframers\nframes\nframeshift\nframeshifts\nframework\nframeworks\nframing\nframings\nfranc\nfranchise\nfranchised\nfranchisee\nfranchisees\nfranchiser\nfranchisers\nfranchises\nfranchising\nfranchisor\nfranchisors\nfrancium\nfranciums\nfrancolin\nfrancolins\nfrancophone\nfrancs\nfrangibilities\nfrangibility\nfrangible\nfrangipane\nfrangipanes\nfrangipani\nfrangipanis\nfrangipanni\nfranglais\nfrank\nfrankable\nfranked\nfranker\nfrankers\nfrankest\nfrankfurt\nfrankfurter\nfrankfurters\nfrankfurts\nfrankincense\nfrankincenses\nfranking\nfranklin\nfranklinite\nfranklinites\nfranklins\nfrankly\nfrankness\nfranknesses\nfrankpledge\nfrankpledges\nfranks\nfrantic\nfrantically\nfranticness\nfranticnesses\nfrap\nfrappe\nfrapped\nfrappes\nfrapping\nfraps\nfrass\nfrasses\nfrat\nfrater\nfraternal\nfraternalism\nfraternalisms\nfraternally\nfraternities\nfraternity\nfraternization\nfraternizations\nfraternize\nfraternized\nfraternizer\nfraternizers\nfraternizes\nfraternizing\nfraters\nfratricidal\nfratricide\nfratricides\nfrats\nfraud\nfrauds\nfraudulence\nfraudulences\nfraudulent\nfraudulently\nfraudulentness\nfraudulentnesses\nfraught\nfraughted\nfraughting\nfraughts\nfraulein\nfrauleins\nfraxinella\nfraxinellas\nfray\nfrayed\nfraying\nfrayings\nfrays\nfrazil\nfrazils\nfrazzle\nfrazzled\nfrazzles\nfrazzling\nfreak\nfreaked\nfreakier\nfreakiest\nfreakily\nfreakiness\nfreakinesses\nfreaking\nfreakish\nfreakishly\nfreakishness\nfreakishnesses\nfreakout\nfreakouts\nfreaks\nfreaky\nfreckle\nfreckled\nfreckles\nfrecklier\nfreckliest\nfreckling\nfreckly\nfree\nfreebase\nfreebased\nfreebaser\nfreebasers\nfreebases\nfreebasing\nfreebee\nfreebees\nfreebie\nfreebies\nfreeboard\nfreeboards\nfreeboot\nfreebooted\nfreebooter\nfreebooters\nfreebooting\nfreeboots\nfreeborn\nfreed\nfreedman\nfreedmen\nfreedom\nfreedoms\nfreedwoman\nfreedwomen\nfreeform\nfreehand\nfreehanded\nfreehandedly\nfreehandedness\nfreehandednesses\nfreehearted\nfreeheartedly\nfreehold\nfreeholder\nfreeholders\nfreeholds\nfreeing\nfreelance\nfreelanced\nfreelancer\nfreelancers\nfreelances\nfreelancing\nfreeload\nfreeloaded\nfreeloader\nfreeloaders\nfreeloading\nfreeloads\nfreely\nfreeman\nfreemartin\nfreemartins\nfreemasonries\nfreemasonry\nfreemen\nfreeness\nfreenesses\nfreer\nfreers\nfrees\nfreesia\nfreesias\nfreest\nfreestanding\nfreestone\nfreestones\nfreestyle\nfreestyler\nfreestylers\nfreestyles\nfreethinker\nfreethinkers\nfreethinking\nfreethinkings\nfreeware\nfreewares\nfreeway\nfreeways\nfreewheel\nfreewheeled\nfreewheeler\nfreewheelers\nfreewheeling\nfreewheelingly\nfreewheels\nfreewill\nfreewriting\nfreewritings\nfreeze\nfreezer\nfreezers\nfreezes\nfreezing\nfreezingly\nfreight\nfreightage\nfreightages\nfreighted\nfreighter\nfreighters\nfreighting\nfreights\nfremd\nfremitus\nfremituses\nfrena\nfrench\nfrenched\nfrenches\nfrenchification\nfrenchifications\nfrenchified\nfrenchifies\nfrenchify\nfrenchifying\nfrenching\nfrenetic\nfrenetically\nfreneticism\nfreneticisms\nfrenetics\nfrenula\nfrenulum\nfrenulums\nfrenum\nfrenums\nfrenzied\nfrenziedly\nfrenzies\nfrenzily\nfrenzy\nfrenzying\nfrequence\nfrequences\nfrequencies\nfrequency\nfrequent\nfrequentation\nfrequentations\nfrequentative\nfrequentatives\nfrequented\nfrequenter\nfrequenters\nfrequentest\nfrequenting\nfrequently\nfrequentness\nfrequentnesses\nfrequents\nfrere\nfreres\nfresco\nfrescoed\nfrescoer\nfrescoers\nfrescoes\nfrescoing\nfrescos\nfresh\nfreshed\nfreshen\nfreshened\nfreshener\nfresheners\nfreshening\nfreshens\nfresher\nfreshes\nfreshest\nfreshet\nfreshets\nfreshing\nfreshly\nfreshman\nfreshmen\nfreshness\nfreshnesses\nfreshwater\nfreshwaters\nfresnel\nfresnels\nfret\nfretful\nfretfully\nfretfulness\nfretfulnesses\nfretless\nfrets\nfretsaw\nfretsaws\nfretsome\nfretted\nfretter\nfretters\nfrettier\nfrettiest\nfretting\nfretty\nfretwork\nfretworks\nfriabilities\nfriability\nfriable\nfriar\nfriaries\nfriarly\nfriars\nfriary\nfribble\nfribbled\nfribbler\nfribblers\nfribbles\nfribbling\nfricandeau\nfricandeaus\nfricandeaux\nfricando\nfricandoes\nfricassee\nfricasseed\nfricasseeing\nfricassees\nfricative\nfricatives\nfriction\nfrictional\nfrictionally\nfrictionless\nfrictionlessly\nfrictions\nfridge\nfridges\nfried\nfriedcake\nfriedcakes\nfriend\nfriended\nfriending\nfriendless\nfriendlessness\nfriendlessnesses\nfriendlier\nfriendlies\nfriendliest\nfriendlily\nfriendliness\nfriendlinesses\nfriendly\nfriends\nfriendship\nfriendships\nfrier\nfriers\nfries\nfrieze\nfriezelike\nfriezes\nfrig\nfrigate\nfrigates\nfrigged\nfrigging\nfright\nfrighted\nfrighten\nfrightened\nfrightening\nfrighteningly\nfrightens\nfrightful\nfrightfully\nfrightfulness\nfrightfulnesses\nfrighting\nfrights\nfrigid\nfrigidities\nfrigidity\nfrigidly\nfrigidness\nfrigidnesses\nfrigorific\nfrigs\nfrijol\nfrijole\nfrijoles\nfrill\nfrilled\nfriller\nfrillers\nfrillier\nfrilliest\nfrilling\nfrillings\nfrills\nfrilly\nfringe\nfringed\nfringes\nfringier\nfringiest\nfringing\nfringy\nfripperies\nfrippery\nfrisbee\nfrisbees\nfrise\nfrisee\nfrisees\nfrises\nfrisette\nfrisettes\nfriseur\nfriseurs\nfrisk\nfrisked\nfrisker\nfriskers\nfrisket\nfriskets\nfriskier\nfriskiest\nfriskily\nfriskiness\nfriskinesses\nfrisking\nfrisks\nfrisky\nfrisson\nfrissons\nfrit\nfrith\nfriths\nfritillaria\nfritillarias\nfritillaries\nfritillary\nfrits\nfritt\nfrittata\nfrittatas\nfritted\nfritter\nfrittered\nfritterer\nfritterers\nfrittering\nfritters\nfritting\nfritts\nfritz\nfritzes\nfrivol\nfrivoled\nfrivoler\nfrivolers\nfrivoling\nfrivolities\nfrivolity\nfrivolled\nfrivoller\nfrivollers\nfrivolling\nfrivolous\nfrivolously\nfrivolousness\nfrivolousnesses\nfrivols\nfriz\nfrized\nfrizer\nfrizers\nfrizes\nfrizette\nfrizettes\nfrizing\nfrizz\nfrizzed\nfrizzer\nfrizzers\nfrizzes\nfrizzier\nfrizziest\nfrizzily\nfrizziness\nfrizzinesses\nfrizzing\nfrizzle\nfrizzled\nfrizzler\nfrizzlers\nfrizzles\nfrizzlier\nfrizzliest\nfrizzling\nfrizzly\nfrizzy\nfro\nfrock\nfrocked\nfrocking\nfrocks\nfroe\nfroes\nfrog\nfrogeye\nfrogeyed\nfrogeyes\nfrogfish\nfrogfishes\nfrogged\nfroggier\nfroggiest\nfrogging\nfroggy\nfroghopper\nfroghoppers\nfroglike\nfrogman\nfrogmen\nfrogs\nfrolic\nfrolicked\nfrolicking\nfrolicky\nfrolics\nfrolicsome\nfrom\nfromage\nfromages\nfromenties\nfromenty\nfrond\nfronded\nfrondeur\nfrondeurs\nfrondose\nfronds\nfrons\nfront\nfrontage\nfrontages\nfrontal\nfrontalities\nfrontality\nfrontally\nfrontals\nfrontcourt\nfrontcourts\nfronted\nfronter\nfrontes\nfrontier\nfrontiers\nfrontiersman\nfrontiersmen\nfronting\nfrontispiece\nfrontispieces\nfrontless\nfrontlet\nfrontlets\nfrontline\nfrontogeneses\nfrontogenesis\nfrontolyses\nfrontolysis\nfronton\nfrontons\nfrontrunner\nfrontrunners\nfronts\nfrontward\nfrontwards\nfrore\nfrosh\nfrost\nfrostbit\nfrostbite\nfrostbites\nfrostbiting\nfrostbitings\nfrostbitten\nfrosted\nfrosteds\nfrostier\nfrostiest\nfrostily\nfrostiness\nfrostinesses\nfrosting\nfrostings\nfrosts\nfrostwork\nfrostworks\nfrosty\nfroth\nfrothed\nfrothier\nfrothiest\nfrothily\nfrothiness\nfrothinesses\nfrothing\nfroths\nfrothy\nfrottage\nfrottages\nfrotteur\nfrotteurs\nfroufrou\nfroufrous\nfrounce\nfrounced\nfrounces\nfrouncing\nfrouzier\nfrouziest\nfrouzy\nfrow\nfroward\nfrowardly\nfrowardness\nfrowardnesses\nfrown\nfrowned\nfrowner\nfrowners\nfrowning\nfrowningly\nfrowns\nfrows\nfrowsier\nfrowsiest\nfrowst\nfrowsted\nfrowstier\nfrowstiest\nfrowsting\nfrowsts\nfrowsty\nfrowsy\nfrowzier\nfrowziest\nfrowzily\nfrowzy\nfroze\nfrozen\nfrozenly\nfrozenness\nfrozennesses\nfructification\nfructifications\nfructified\nfructifies\nfructify\nfructifying\nfructose\nfructoses\nfructuous\nfrug\nfrugal\nfrugalities\nfrugality\nfrugally\nfrugged\nfrugging\nfrugivore\nfrugivores\nfrugivorous\nfrugs\nfruit\nfruitage\nfruitages\nfruitarian\nfruitarians\nfruitcake\nfruitcakes\nfruited\nfruiter\nfruiterer\nfruiterers\nfruiters\nfruitful\nfruitfuller\nfruitfullest\nfruitfully\nfruitfulness\nfruitfulnesses\nfruitier\nfruitiest\nfruitily\nfruitiness\nfruitinesses\nfruiting\nfruition\nfruitions\nfruitless\nfruitlessly\nfruitlessness\nfruitlessnesses\nfruitlet\nfruitlets\nfruits\nfruitwood\nfruitwoods\nfruity\nfrumenties\nfrumenty\nfrump\nfrumpier\nfrumpiest\nfrumpily\nfrumpish\nfrumps\nfrumpy\nfrusta\nfrustrate\nfrustrated\nfrustrates\nfrustrating\nfrustratingly\nfrustration\nfrustrations\nfrustule\nfrustules\nfrustum\nfrustums\nfrutescent\nfruticose\nfry\nfryer\nfryers\nfrying\nfrypan\nfrypans\nfub\nfubbed\nfubbing\nfubs\nfubsier\nfubsiest\nfubsy\nfuchsia\nfuchsias\nfuchsin\nfuchsine\nfuchsines\nfuchsins\nfuci\nfuck\nfucked\nfucker\nfuckers\nfucking\nfucks\nfuckup\nfuckups\nfucoid\nfucoidal\nfucoids\nfucose\nfucoses\nfucous\nfucoxanthin\nfucoxanthins\nfucus\nfucuses\nfud\nfuddle\nfuddled\nfuddles\nfuddling\nfudge\nfudged\nfudges\nfudging\nfuds\nfuehrer\nfuehrers\nfuel\nfueled\nfueler\nfuelers\nfueling\nfuelled\nfueller\nfuellers\nfuelling\nfuels\nfuelwood\nfuelwoods\nfug\nfugacious\nfugacities\nfugacity\nfugal\nfugally\nfugato\nfugatos\nfugged\nfuggier\nfuggiest\nfuggily\nfugging\nfuggy\nfugio\nfugios\nfugitive\nfugitively\nfugitiveness\nfugitivenesses\nfugitives\nfugle\nfugled\nfugleman\nfuglemen\nfugles\nfugling\nfugs\nfugu\nfugue\nfugued\nfugues\nfuguing\nfuguist\nfuguists\nfugus\nfuhrer\nfuhrers\nfuji\nfujis\nfulcra\nfulcrum\nfulcrums\nfulfil\nfulfill\nfulfilled\nfulfiller\nfulfillers\nfulfilling\nfulfillment\nfulfillments\nfulfills\nfulfils\nfulgent\nfulgently\nfulgid\nfulgurant\nfulgurate\nfulgurated\nfulgurates\nfulgurating\nfulguration\nfulgurations\nfulgurite\nfulgurites\nfulgurous\nfulham\nfulhams\nfuliginous\nfuliginously\nfull\nfullam\nfullams\nfullback\nfullbacks\nfulled\nfuller\nfullered\nfullerene\nfullerenes\nfulleries\nfullering\nfullers\nfullery\nfullest\nfullface\nfullfaces\nfulling\nfullmouthed\nfullness\nfullnesses\nfulls\nfully\nfulmar\nfulmars\nfulminant\nfulminate\nfulminated\nfulminates\nfulminating\nfulmination\nfulminations\nfulmine\nfulmined\nfulmines\nfulminic\nfulmining\nfulness\nfulnesses\nfulsome\nfulsomely\nfulsomeness\nfulsomenesses\nfulvous\nfumarase\nfumarases\nfumarate\nfumarates\nfumaric\nfumarole\nfumaroles\nfumarolic\nfumatories\nfumatory\nfumble\nfumbled\nfumbler\nfumblers\nfumbles\nfumbling\nfumblingly\nfume\nfumed\nfumeless\nfumelike\nfumer\nfumers\nfumes\nfumet\nfumets\nfumette\nfumettes\nfumier\nfumiest\nfumigant\nfumigants\nfumigate\nfumigated\nfumigates\nfumigating\nfumigation\nfumigations\nfumigator\nfumigators\nfuming\nfumingly\nfumitories\nfumitory\nfumuli\nfumulus\nfumy\nfun\nfunambulism\nfunambulisms\nfunambulist\nfunambulists\nfunction\nfunctional\nfunctionalism\nfunctionalisms\nfunctionalist\nfunctionalistic\nfunctionalists\nfunctionalities\nfunctionality\nfunctionally\nfunctionaries\nfunctionary\nfunctioned\nfunctioning\nfunctionless\nfunctions\nfunctor\nfunctors\nfund\nfundament\nfundamental\nfundamentalism\nfundamentalisms\nfundamentalist\nfundamentalistic\nfundamentalists\nfundamentally\nfundamentals\nfundaments\nfunded\nfundi\nfundic\nfunding\nfundraiser\nfundraisers\nfundraising\nfundraisings\nfunds\nfundus\nfuneral\nfunerals\nfunerary\nfunereal\nfunereally\nfunest\nfunfair\nfunfairs\nfungal\nfungals\nfungi\nfungibilities\nfungibility\nfungible\nfungibles\nfungic\nfungicidal\nfungicidally\nfungicide\nfungicides\nfungiform\nfungistatic\nfungo\nfungoes\nfungoid\nfungoids\nfungous\nfungus\nfunguses\nfunicle\nfunicles\nfunicular\nfuniculars\nfuniculi\nfuniculus\nfunk\nfunked\nfunker\nfunkers\nfunkia\nfunkias\nfunkier\nfunkiest\nfunkiness\nfunkinesses\nfunking\nfunks\nfunky\nfunned\nfunnel\nfunneled\nfunnelform\nfunneling\nfunnelled\nfunnelling\nfunnels\nfunner\nfunnest\nfunnier\nfunnies\nfunniest\nfunnily\nfunniness\nfunninesses\nfunning\nfunny\nfunnyman\nfunnymen\nfuns\nfur\nfuran\nfurane\nfuranes\nfuranose\nfuranoses\nfuranoside\nfuranosides\nfurans\nfurazolidone\nfurazolidones\nfurbearer\nfurbearers\nfurbelow\nfurbelowed\nfurbelowing\nfurbelows\nfurbish\nfurbished\nfurbisher\nfurbishers\nfurbishes\nfurbishing\nfurcate\nfurcated\nfurcates\nfurcating\nfurcation\nfurcations\nfurcraea\nfurcraeas\nfurcula\nfurculae\nfurcular\nfurculum\nfurfur\nfurfural\nfurfurals\nfurfuran\nfurfurans\nfurfures\nfuribund\nfuries\nfurioso\nfurious\nfuriously\nfurl\nfurlable\nfurled\nfurler\nfurlers\nfurless\nfurling\nfurlong\nfurlongs\nfurlough\nfurloughed\nfurloughing\nfurloughs\nfurls\nfurmenties\nfurmenty\nfurmeties\nfurmety\nfurmities\nfurmity\nfurnace\nfurnaced\nfurnaces\nfurnacing\nfurnish\nfurnished\nfurnisher\nfurnishers\nfurnishes\nfurnishing\nfurnishings\nfurniture\nfurnitures\nfuror\nfurore\nfurores\nfurors\nfurosemide\nfurosemides\nfurred\nfurrier\nfurrieries\nfurriers\nfurriery\nfurriest\nfurrily\nfurriner\nfurriners\nfurring\nfurrings\nfurrow\nfurrowed\nfurrower\nfurrowers\nfurrowing\nfurrows\nfurrowy\nfurry\nfurs\nfurther\nfurtherance\nfurtherances\nfurthered\nfurtherer\nfurtherers\nfurthering\nfurthermore\nfurthermost\nfurthers\nfurthest\nfurtive\nfurtively\nfurtiveness\nfurtivenesses\nfuruncle\nfuruncles\nfurunculoses\nfurunculosis\nfury\nfurze\nfurzes\nfurzier\nfurziest\nfurzy\nfusain\nfusains\nfuscous\nfuse\nfused\nfusee\nfusees\nfusel\nfuselage\nfuselages\nfuseless\nfusels\nfuses\nfusibilities\nfusibility\nfusible\nfusibly\nfusiform\nfusil\nfusile\nfusileer\nfusileers\nfusilier\nfusiliers\nfusillade\nfusillades\nfusilli\nfusillis\nfusils\nfusing\nfusion\nfusionist\nfusionists\nfusions\nfuss\nfussbudget\nfussbudgets\nfussbudgety\nfussed\nfusser\nfussers\nfusses\nfussier\nfussiest\nfussily\nfussiness\nfussinesses\nfussing\nfusspot\nfusspots\nfussy\nfustian\nfustians\nfustic\nfustics\nfustier\nfustiest\nfustigate\nfustigated\nfustigates\nfustigating\nfustigation\nfustigations\nfustily\nfustiness\nfustinesses\nfusty\nfusulinid\nfusulinids\nfutharc\nfutharcs\nfuthark\nfutharks\nfuthorc\nfuthorcs\nfuthork\nfuthorks\nfutile\nfutilely\nfutileness\nfutilenesses\nfutilitarian\nfutilitarianism\nfutilitarianisms\nfutilitarians\nfutilities\nfutility\nfuton\nfutons\nfuttock\nfuttocks\nfutural\nfuture\nfutureless\nfuturelessness\nfuturelessnesses\nfutures\nfuturism\nfuturisms\nfuturist\nfuturistic\nfuturistically\nfuturistics\nfuturists\nfuturities\nfuturity\nfuturological\nfuturologies\nfuturologist\nfuturologists\nfuturology\nfutz\nfutzed\nfutzes\nfutzing\nfuze\nfuzed\nfuzee\nfuzees\nfuzes\nfuzil\nfuzils\nfuzing\nfuzz\nfuzzed\nfuzzes\nfuzzier\nfuzziest\nfuzzily\nfuzziness\nfuzzinesses\nfuzzing\nfuzzy\nfyce\nfyces\nfyke\nfykes\nfylfot\nfylfots\nfytte\nfyttes\ngab\ngabardine\ngabardines\ngabbard\ngabbards\ngabbart\ngabbarts\ngabbed\ngabber\ngabbers\ngabbier\ngabbiest\ngabbing\ngabble\ngabbled\ngabbler\ngabblers\ngabbles\ngabbling\ngabbro\ngabbroic\ngabbroid\ngabbros\ngabby\ngabelle\ngabelled\ngabelles\ngaberdine\ngaberdines\ngabfest\ngabfests\ngabies\ngabion\ngabions\ngable\ngabled\ngables\ngabling\ngaboon\ngaboons\ngabs\ngaby\ngad\ngadabout\ngadabouts\ngadarene\ngadded\ngadder\ngadders\ngaddi\ngadding\ngaddis\ngadflies\ngadfly\ngadget\ngadgeteer\ngadgeteers\ngadgetries\ngadgetry\ngadgets\ngadgety\ngadi\ngadid\ngadids\ngadis\ngadoid\ngadoids\ngadolinite\ngadolinites\ngadolinium\ngadoliniums\ngadroon\ngadrooned\ngadrooning\ngadroonings\ngadroons\ngads\ngadwall\ngadwalls\ngadzookeries\ngadzookery\ngadzooks\ngae\ngaed\ngaeing\ngaen\ngaes\ngaff\ngaffe\ngaffed\ngaffer\ngaffers\ngaffes\ngaffing\ngaffs\ngag\ngaga\ngagaku\ngagakus\ngage\ngaged\ngager\ngagers\ngages\ngagged\ngagger\ngaggers\ngagging\ngaggle\ngaggled\ngaggles\ngaggling\ngaging\ngagman\ngagmen\ngags\ngagster\ngagsters\ngahnite\ngahnites\ngaieties\ngaiety\ngaijin\ngaillardia\ngaillardias\ngaily\ngain\ngainable\ngained\ngainer\ngainers\ngainful\ngainfully\ngainfulness\ngainfulnesses\ngaingiving\ngaingivings\ngaining\ngainless\ngainlier\ngainliest\ngainly\ngains\ngainsaid\ngainsay\ngainsayer\ngainsayers\ngainsaying\ngainsays\ngainst\ngait\ngaited\ngaiter\ngaiters\ngaiting\ngaits\ngal\ngala\ngalabia\ngalabias\ngalabieh\ngalabiehs\ngalabiya\ngalabiyas\ngalactic\ngalactorrhea\ngalactorrheas\ngalactosamine\ngalactosamines\ngalactose\ngalactosemia\ngalactosemias\ngalactosemic\ngalactoses\ngalactosidase\ngalactosidases\ngalactoside\ngalactosides\ngalactosyl\ngalactosyls\ngalago\ngalagos\ngalah\ngalahs\ngalangal\ngalangals\ngalantine\ngalantines\ngalas\ngalatea\ngalateas\ngalavant\ngalavanted\ngalavanting\ngalavants\ngalax\ngalaxes\ngalaxies\ngalaxy\ngalbanum\ngalbanums\ngale\ngalea\ngaleae\ngaleas\ngaleate\ngaleated\ngalena\ngalenas\ngalenic\ngalenical\ngalenicals\ngalenite\ngalenites\ngalere\ngaleres\ngales\ngalilee\ngalilees\ngalingale\ngalingales\ngaliot\ngaliots\ngalipot\ngalipots\ngalivant\ngalivanted\ngalivanting\ngalivants\ngall\ngallamine\ngallamines\ngallant\ngallanted\ngallanting\ngallantly\ngallantries\ngallantry\ngallants\ngallate\ngallates\ngallbladder\ngallbladders\ngalleass\ngalleasses\ngalled\ngallein\ngalleins\ngalleon\ngalleons\ngalleria\ngallerias\ngalleried\ngalleries\ngallery\ngallerygoer\ngallerygoers\ngallerying\ngalleryite\ngalleryites\ngallet\ngalleta\ngalletas\ngalleted\ngalleting\ngallets\ngalley\ngalleys\ngallflies\ngallfly\ngalliard\ngalliards\ngalliass\ngalliasses\ngallic\ngallican\ngallicism\ngallicisms\ngallicization\ngallicizations\ngallicize\ngallicized\ngallicizes\ngallicizing\ngallied\ngallies\ngalligaskins\ngallimaufries\ngallimaufry\ngallinaceous\ngalling\ngallingly\ngallinipper\ngallinippers\ngallinule\ngallinules\ngalliot\ngalliots\ngallipot\ngallipots\ngallium\ngalliums\ngallivant\ngallivanted\ngallivanting\ngallivants\ngallnut\ngallnuts\ngallon\ngallonage\ngallonages\ngallons\ngalloon\ngalloons\ngalloot\ngalloots\ngallop\ngallopade\ngallopades\ngalloped\ngalloper\ngallopers\ngalloping\ngallops\ngallous\ngallowglass\ngallowglasses\ngallows\ngallowses\ngalls\ngallstone\ngallstones\ngallus\ngallused\ngalluses\ngally\ngallying\ngaloot\ngaloots\ngalop\ngalopade\ngalopades\ngaloped\ngaloping\ngalops\ngalore\ngalores\ngalosh\ngaloshe\ngaloshed\ngaloshes\ngals\ngalumph\ngalumphed\ngalumphing\ngalumphs\ngalvanic\ngalvanically\ngalvanise\ngalvanised\ngalvanises\ngalvanising\ngalvanism\ngalvanisms\ngalvanization\ngalvanizations\ngalvanize\ngalvanized\ngalvanizer\ngalvanizers\ngalvanizes\ngalvanizing\ngalvanometer\ngalvanometers\ngalvanometric\ngalvanoscope\ngalvanoscopes\ngalyac\ngalyacs\ngalyak\ngalyaks\ngam\ngama\ngamas\ngamashes\ngamay\ngamays\ngamb\ngamba\ngambade\ngambades\ngambado\ngambadoes\ngambados\ngambas\ngambe\ngambes\ngambeson\ngambesons\ngambia\ngambias\ngambier\ngambiers\ngambir\ngambirs\ngambit\ngambits\ngamble\ngambled\ngambler\ngamblers\ngambles\ngambling\ngamboge\ngamboges\ngambol\ngamboled\ngamboling\ngambolled\ngambolling\ngambols\ngambrel\ngambrels\ngambs\ngambusia\ngambusias\ngame\ngamecock\ngamecocks\ngamed\ngamekeeper\ngamekeepers\ngamelan\ngamelans\ngamelike\ngamely\ngameness\ngamenesses\ngamer\ngamers\ngames\ngamesman\ngamesmanship\ngamesmanships\ngamesmen\ngamesome\ngamesomely\ngamesomeness\ngamesomenesses\ngamest\ngamester\ngamesters\ngametangia\ngametangium\ngamete\ngametes\ngametic\ngametically\ngametocyte\ngametocytes\ngametogeneses\ngametogenesis\ngametogenic\ngametogenous\ngametophore\ngametophores\ngametophyte\ngametophytes\ngametophytic\ngamey\ngamic\ngamier\ngamiest\ngamily\ngamin\ngamine\ngamines\ngaminess\ngaminesses\ngaming\ngamings\ngamins\ngamma\ngammadia\ngammadion\ngammas\ngammed\ngammer\ngammers\ngammier\ngammiest\ngamming\ngammon\ngammoned\ngammoner\ngammoners\ngammoning\ngammons\ngammy\ngamodeme\ngamodemes\ngamopetalous\ngamp\ngamps\ngams\ngamut\ngamuts\ngamy\ngan\nganache\nganaches\ngander\ngandered\ngandering\nganders\ngane\nganef\nganefs\nganev\nganevs\ngang\ngangbang\ngangbanger\ngangbangers\ngangbangs\ngangbuster\ngangbusters\nganged\nganger\ngangers\nganging\ngangland\nganglands\nganglia\nganglial\ngangliar\nganglier\ngangliest\ngangling\nganglion\nganglionated\nganglionic\nganglions\nganglioside\ngangliosides\ngangly\ngangplank\ngangplanks\ngangplow\ngangplows\ngangrel\ngangrels\ngangrene\ngangrened\ngangrenes\ngangrening\ngangrenous\ngangs\ngangster\ngangsterdom\ngangsterdoms\ngangsterish\ngangsterism\ngangsterisms\ngangsters\ngangue\ngangues\ngangway\ngangways\nganister\nganisters\nganja\nganjah\nganjahs\nganjas\ngannet\ngannets\ngannister\ngannisters\nganof\nganofs\nganoid\nganoids\ngantelope\ngantelopes\ngantlet\ngantleted\ngantleting\ngantlets\ngantline\ngantlines\ngantlope\ngantlopes\ngantries\ngantry\nganymede\nganymedes\ngaol\ngaoled\ngaoler\ngaolers\ngaoling\ngaols\ngap\ngape\ngaped\ngaper\ngapers\ngapes\ngapeseed\ngapeseeds\ngapeworm\ngapeworms\ngaping\ngapingly\ngaposis\ngaposises\ngapped\ngappier\ngappiest\ngapping\ngappy\ngaps\ngapy\ngar\ngarage\ngaraged\ngarageman\ngaragemen\ngarages\ngaraging\ngarb\ngarbage\ngarbageman\ngarbagemen\ngarbages\ngarbanzo\ngarbanzos\ngarbed\ngarbing\ngarble\ngarbled\ngarbler\ngarblers\ngarbles\ngarbless\ngarbling\ngarboard\ngarboards\ngarboil\ngarboils\ngarbs\ngarcon\ngarcons\ngardant\ngarden\ngardened\ngardener\ngardeners\ngardenful\ngardenfuls\ngardenia\ngardenias\ngardening\ngardens\ngarderobe\ngarderobes\ngardyloo\ngarfish\ngarfishes\ngarganey\ngarganeys\ngargantuan\ngarget\ngargets\ngargety\ngargle\ngargled\ngargler\ngarglers\ngargles\ngargling\ngargoyle\ngargoyled\ngargoyles\ngaribaldi\ngaribaldis\ngarigue\ngarigues\ngarish\ngarishly\ngarishness\ngarishnesses\ngarland\ngarlanded\ngarlanding\ngarlands\ngarlic\ngarlicked\ngarlicky\ngarlics\ngarment\ngarmented\ngarmenting\ngarments\ngarner\ngarnered\ngarnering\ngarners\ngarnet\ngarnetiferous\ngarnets\ngarni\ngarnierite\ngarnierites\ngarnish\ngarnished\ngarnishee\ngarnisheed\ngarnisheeing\ngarnishees\ngarnishes\ngarnishing\ngarnishment\ngarnishments\ngarniture\ngarnitures\ngarote\ngaroted\ngarotes\ngaroting\ngarotte\ngarotted\ngarotter\ngarotters\ngarottes\ngarotting\ngarpike\ngarpikes\ngarred\ngarret\ngarrets\ngarring\ngarrison\ngarrisoned\ngarrisoning\ngarrisons\ngarron\ngarrons\ngarrote\ngarroted\ngarroter\ngarroters\ngarrotes\ngarroting\ngarrotte\ngarrotted\ngarrottes\ngarrotting\ngarrulities\ngarrulity\ngarrulous\ngarrulously\ngarrulousness\ngarrulousnesses\ngars\ngarter\ngartered\ngartering\ngarters\ngarth\ngarths\ngarvey\ngarveys\ngas\ngasalier\ngasaliers\ngasbag\ngasbags\ngascon\ngasconade\ngasconaded\ngasconader\ngasconaders\ngasconades\ngasconading\ngascons\ngaselier\ngaseliers\ngaseous\ngaseousness\ngaseousnesses\ngases\ngash\ngashed\ngasher\ngashes\ngashest\ngashing\ngasholder\ngasholders\ngashouse\ngashouses\ngasification\ngasifications\ngasified\ngasifier\ngasifiers\ngasifies\ngasiform\ngasify\ngasifying\ngasket\ngaskets\ngaskin\ngasking\ngaskings\ngaskins\ngasless\ngaslight\ngaslights\ngaslit\ngasman\ngasmen\ngasogene\ngasogenes\ngasohol\ngasohols\ngasolene\ngasolenes\ngasolier\ngasoliers\ngasoline\ngasolines\ngasolinic\ngasometer\ngasometers\ngasp\ngasped\ngasper\ngaspers\ngasping\ngasps\ngassed\ngasser\ngassers\ngasses\ngassier\ngassiest\ngassily\ngassiness\ngassinesses\ngassing\ngassings\ngassy\ngast\ngasted\ngaster\ngasters\ngastight\ngastightness\ngastightnesses\ngasting\ngastness\ngastnesses\ngastraea\ngastraeas\ngastral\ngastrea\ngastreas\ngastrectomies\ngastrectomy\ngastric\ngastrin\ngastrins\ngastritides\ngastritis\ngastritises\ngastrocnemii\ngastrocnemius\ngastroduodenal\ngastroenteritides\ngastroenteritis\ngastroenterological\ngastroenterologies\ngastroenterologist\ngastroenterologists\ngastroenterology\ngastroesophageal\ngastrointestinal\ngastrolith\ngastroliths\ngastronome\ngastronomes\ngastronomic\ngastronomical\ngastronomically\ngastronomies\ngastronomist\ngastronomists\ngastronomy\ngastropod\ngastropods\ngastroscope\ngastroscopes\ngastroscopic\ngastroscopies\ngastroscopist\ngastroscopists\ngastroscopy\ngastrotrich\ngastrotrichs\ngastrovascular\ngastrula\ngastrulae\ngastrular\ngastrulas\ngastrulate\ngastrulated\ngastrulates\ngastrulating\ngastrulation\ngastrulations\ngasts\ngasworks\ngat\ngate\ngateau\ngateaus\ngateaux\ngated\ngatefold\ngatefolds\ngatehouse\ngatehouses\ngatekeeper\ngatekeepers\ngatekeeping\ngateless\ngatelike\ngateman\ngatemen\ngatepost\ngateposts\ngates\ngateway\ngateways\ngather\ngathered\ngatherer\ngatherers\ngathering\ngatherings\ngathers\ngating\ngator\ngators\ngats\ngauche\ngauchely\ngaucheness\ngauchenesses\ngaucher\ngaucherie\ngaucheries\ngauchest\ngaucho\ngauchos\ngaud\ngauderies\ngaudery\ngaudier\ngaudies\ngaudiest\ngaudily\ngaudiness\ngaudinesses\ngauds\ngaudy\ngauffer\ngauffered\ngauffering\ngauffers\ngauge\ngauged\ngauger\ngaugers\ngauges\ngauging\ngault\ngaults\ngaum\ngaumed\ngauming\ngaums\ngaun\ngaunt\ngaunter\ngauntest\ngauntlet\ngauntleted\ngauntleting\ngauntlets\ngauntly\ngauntness\ngauntnesses\ngauntries\ngauntry\ngaur\ngaurs\ngauss\ngausses\ngauze\ngauzelike\ngauzes\ngauzier\ngauziest\ngauzily\ngauzy\ngavage\ngavages\ngave\ngavel\ngaveled\ngaveling\ngavelkind\ngavelkinds\ngavelled\ngavelling\ngavelock\ngavelocks\ngavels\ngavial\ngavials\ngavot\ngavots\ngavotte\ngavotted\ngavottes\ngavotting\ngawk\ngawked\ngawker\ngawkers\ngawkier\ngawkies\ngawkiest\ngawkily\ngawkiness\ngawkinesses\ngawking\ngawkish\ngawkishly\ngawkishness\ngawkishnesses\ngawks\ngawky\ngawp\ngawped\ngawper\ngawpers\ngawping\ngawps\ngawsie\ngawsy\ngay\ngayal\ngayals\ngayer\ngayest\ngayeties\ngayety\ngayly\ngayness\ngaynesses\ngays\ngaywings\ngazabo\ngazaboes\ngazabos\ngazania\ngazanias\ngazar\ngazars\ngaze\ngazebo\ngazeboes\ngazebos\ngazed\ngazehound\ngazehounds\ngazelle\ngazelles\ngazer\ngazers\ngazes\ngazette\ngazetted\ngazetteer\ngazetteers\ngazettes\ngazetting\ngazillion\ngazillions\ngazing\ngazogene\ngazogenes\ngazoo\ngazoos\ngazpacho\ngazpachos\ngazump\ngazumped\ngazumper\ngazumpers\ngazumping\ngazumps\ngeanticline\ngeanticlines\ngear\ngearbox\ngearboxes\ngearcase\ngearcases\ngearchange\ngearchanges\ngeared\ngearing\ngearings\ngearless\ngears\ngearshift\ngearshifts\ngearwheel\ngearwheels\ngeck\ngecked\ngecking\ngecko\ngeckoes\ngeckos\ngecks\nged\ngedankenexperiment\ngedankenexperiments\ngeds\ngee\ngeed\ngeegaw\ngeegaws\ngeeing\ngeek\ngeekier\ngeekiest\ngeeks\ngeeky\ngeepound\ngeepounds\ngees\ngeese\ngeest\ngeests\ngeez\ngeezer\ngeezers\ngegenschein\ngegenscheins\ngeisha\ngeishas\ngel\ngelable\ngelada\ngeladas\ngelandesprung\ngelandesprungs\ngelant\ngelants\ngelate\ngelated\ngelates\ngelati\ngelatin\ngelatine\ngelatines\ngelating\ngelatinization\ngelatinizations\ngelatinize\ngelatinized\ngelatinizes\ngelatinizing\ngelatinous\ngelatinously\ngelatinousness\ngelatinousnesses\ngelatins\ngelation\ngelations\ngelato\ngelatos\ngeld\ngelded\ngelder\ngelders\ngelding\ngeldings\ngelds\ngelee\ngelees\ngelid\ngelidities\ngelidity\ngelidly\ngelignite\ngelignites\ngellant\ngellants\ngelled\ngelling\ngels\ngelsemia\ngelsemium\ngelsemiums\ngelt\ngelts\ngem\ngemeinschaft\ngemeinschaften\ngemeinschafts\ngeminal\ngeminally\ngeminate\ngeminated\ngeminates\ngeminating\ngemination\ngeminations\ngemlike\ngemma\ngemmae\ngemmate\ngemmated\ngemmates\ngemmating\ngemmation\ngemmations\ngemmed\ngemmier\ngemmiest\ngemmily\ngemming\ngemmologies\ngemmologist\ngemmologists\ngemmology\ngemmule\ngemmules\ngemmy\ngemological\ngemologies\ngemologist\ngemologists\ngemology\ngemot\ngemote\ngemotes\ngemots\ngems\ngemsbok\ngemsboks\ngemsbuck\ngemsbucks\ngemstone\ngemstones\ngemutlich\ngemutlichkeit\ngemutlichkeits\ngen\ngendarme\ngendarmerie\ngendarmeries\ngendarmery\ngendarmes\ngender\ngendered\ngendering\ngenders\ngene\ngenealogical\ngenealogically\ngenealogies\ngenealogist\ngenealogists\ngenealogy\ngenera\ngenerable\ngeneral\ngeneralisation\ngeneralisations\ngeneralise\ngeneralised\ngeneralises\ngeneralising\ngeneralissimo\ngeneralissimos\ngeneralist\ngeneralists\ngeneralities\ngenerality\ngeneralizabilities\ngeneralizability\ngeneralizable\ngeneralization\ngeneralizations\ngeneralize\ngeneralized\ngeneralizer\ngeneralizers\ngeneralizes\ngeneralizing\ngenerally\ngenerals\ngeneralship\ngeneralships\ngenerate\ngenerated\ngenerates\ngenerating\ngeneration\ngenerational\ngenerationally\ngenerations\ngenerative\ngenerator\ngenerators\ngeneratrices\ngeneratrix\ngeneric\ngenerically\ngenericness\ngenericnesses\ngenerics\ngenerosities\ngenerosity\ngenerous\ngenerously\ngenerousness\ngenerousnesses\ngenes\ngeneses\ngenesis\ngenet\ngenetic\ngenetical\ngenetically\ngeneticist\ngeneticists\ngenetics\ngenets\ngenette\ngenettes\ngeneva\ngenevas\ngenial\ngenialities\ngeniality\ngenially\ngenic\ngenically\ngeniculate\ngeniculated\ngenie\ngenies\ngenii\ngenip\ngenipap\ngenipaps\ngenips\ngenital\ngenitalia\ngenitalic\ngenitally\ngenitals\ngenitival\ngenitivally\ngenitive\ngenitives\ngenitor\ngenitors\ngenitourinary\ngeniture\ngenitures\ngenius\ngeniuses\ngenoa\ngenoas\ngenocidal\ngenocide\ngenocides\ngenoise\ngenoises\ngenom\ngenome\ngenomes\ngenomic\ngenoms\ngenotype\ngenotypes\ngenotypic\ngenotypical\ngenotypically\ngenre\ngenres\ngenro\ngenros\ngens\ngenseng\ngensengs\ngent\ngentamicin\ngentamicins\ngenteel\ngenteeler\ngenteelest\ngenteelism\ngenteelisms\ngenteelly\ngenteelness\ngenteelnesses\ngentes\ngentian\ngentians\ngentil\ngentile\ngentiles\ngentilesse\ngentilesses\ngentilities\ngentility\ngentle\ngentled\ngentlefolk\ngentlefolks\ngentleman\ngentlemanlike\ngentlemanlikeness\ngentlemanlikenesses\ngentlemanliness\ngentlemanlinesses\ngentlemanly\ngentlemen\ngentleness\ngentlenesses\ngentleperson\ngentlepersons\ngentler\ngentles\ngentlest\ngentlewoman\ngentlewomen\ngentling\ngently\ngentoo\ngentoos\ngentrice\ngentrices\ngentries\ngentrification\ngentrifications\ngentrified\ngentrifier\ngentrifiers\ngentrifies\ngentrify\ngentrifying\ngentry\ngents\ngenu\ngenua\ngenuflect\ngenuflected\ngenuflecting\ngenuflection\ngenuflections\ngenuflects\ngenuine\ngenuinely\ngenuineness\ngenuinenesses\ngenus\ngenuses\ngeobotanic\ngeobotanical\ngeobotanies\ngeobotanist\ngeobotanists\ngeobotany\ngeocentric\ngeocentrically\ngeochemical\ngeochemically\ngeochemist\ngeochemistries\ngeochemistry\ngeochemists\ngeochronologic\ngeochronological\ngeochronologically\ngeochronologies\ngeochronologist\ngeochronologists\ngeochronology\ngeode\ngeodes\ngeodesic\ngeodesics\ngeodesies\ngeodesist\ngeodesists\ngeodesy\ngeodetic\ngeodetical\ngeodic\ngeoduck\ngeoducks\ngeognosies\ngeognosy\ngeographer\ngeographers\ngeographic\ngeographical\ngeographically\ngeographies\ngeography\ngeohydrologic\ngeohydrologies\ngeohydrologist\ngeohydrologists\ngeohydrology\ngeoid\ngeoidal\ngeoids\ngeologer\ngeologers\ngeologic\ngeological\ngeologically\ngeologies\ngeologist\ngeologists\ngeologize\ngeologized\ngeologizes\ngeologizing\ngeology\ngeomagnetic\ngeomagnetically\ngeomagnetism\ngeomagnetisms\ngeomancer\ngeomancers\ngeomancies\ngeomancy\ngeomantic\ngeometer\ngeometers\ngeometric\ngeometrical\ngeometrically\ngeometrician\ngeometricians\ngeometrics\ngeometrid\ngeometrids\ngeometries\ngeometrise\ngeometrised\ngeometrises\ngeometrising\ngeometrization\ngeometrizations\ngeometrize\ngeometrized\ngeometrizes\ngeometrizing\ngeometry\ngeomorphic\ngeomorphological\ngeomorphologies\ngeomorphologist\ngeomorphologists\ngeomorphology\ngeophagies\ngeophagy\ngeophone\ngeophones\ngeophysical\ngeophysically\ngeophysicist\ngeophysicists\ngeophysics\ngeophyte\ngeophytes\ngeopolitical\ngeopolitically\ngeopolitician\ngeopoliticians\ngeopolitics\ngeoponic\ngeopressured\ngeoprobe\ngeoprobes\ngeorgette\ngeorgettes\ngeorgic\ngeorgics\ngeoscience\ngeosciences\ngeoscientist\ngeoscientists\ngeostationary\ngeostrategic\ngeostrategies\ngeostrategist\ngeostrategists\ngeostrategy\ngeostrophic\ngeostrophically\ngeosynchronous\ngeosynclinal\ngeosyncline\ngeosynclines\ngeotactic\ngeotaxes\ngeotaxis\ngeotechnical\ngeotectonic\ngeotectonically\ngeothermal\ngeothermally\ngeotropic\ngeotropically\ngeotropism\ngeotropisms\ngerah\ngerahs\ngeranial\ngeranials\ngeraniol\ngeraniols\ngeranium\ngeraniums\ngerardia\ngerardias\ngerbera\ngerberas\ngerbil\ngerbille\ngerbilles\ngerbils\ngerent\ngerents\ngerenuk\ngerenuks\ngerfalcon\ngerfalcons\ngeriatric\ngeriatrician\ngeriatricians\ngeriatrics\ngerm\ngerman\ngermander\ngermanders\ngermane\ngermanely\ngermanic\ngermanium\ngermaniums\ngermanization\ngermanizations\ngermanize\ngermanized\ngermanizes\ngermanizing\ngermans\ngermen\ngermens\ngermfree\ngermicidal\ngermicide\ngermicides\ngermier\ngermiest\ngermina\ngerminabilities\ngerminability\ngerminal\ngerminally\ngerminate\ngerminated\ngerminates\ngerminating\ngermination\ngerminations\ngerminative\ngermproof\ngerms\ngermy\ngerontic\ngerontocracies\ngerontocracy\ngerontocrat\ngerontocratic\ngerontocrats\ngerontologic\ngerontological\ngerontologies\ngerontologist\ngerontologists\ngerontology\ngerontomorphic\ngerrymander\ngerrymandered\ngerrymandering\ngerrymanders\ngerund\ngerundive\ngerundives\ngerunds\ngesellschaft\ngesellschaften\ngesellschafts\ngesneria\ngesneriad\ngesneriads\ngesso\ngessoed\ngessoes\ngest\ngestalt\ngestalten\ngestaltist\ngestaltists\ngestalts\ngestapo\ngestapos\ngestate\ngestated\ngestates\ngestating\ngestation\ngestational\ngestations\ngeste\ngestes\ngestic\ngestical\ngesticulant\ngesticulate\ngesticulated\ngesticulates\ngesticulating\ngesticulation\ngesticulations\ngesticulative\ngesticulator\ngesticulators\ngesticulatory\ngests\ngestural\ngesturally\ngesture\ngestured\ngesturer\ngesturers\ngestures\ngesturing\ngesundheit\nget\ngeta\ngetable\ngetas\ngetatable\ngetaway\ngetaways\ngets\ngettable\ngetter\ngettered\ngettering\ngetters\ngetting\ngetup\ngetups\ngeum\ngeums\ngewgaw\ngewgaws\ngewurztraminer\ngewurztraminers\ngey\ngeyser\ngeyserite\ngeyserites\ngeysers\ngharial\ngharials\ngharri\ngharries\ngharris\ngharry\nghast\nghastful\nghastfully\nghastlier\nghastliest\nghastliness\nghastlinesses\nghastly\nghat\nghats\nghaut\nghauts\nghazi\nghazies\nghazis\nghee\nghees\ngherao\ngheraoed\ngheraoes\ngheraoing\ngherkin\ngherkins\nghetto\nghettoed\nghettoes\nghettoing\nghettoization\nghettoizations\nghettoize\nghettoized\nghettoizes\nghettoizing\nghettos\nghi\nghibli\nghiblis\nghillie\nghillies\nghis\nghost\nghosted\nghostier\nghostiest\nghosting\nghostings\nghostlier\nghostliest\nghostlike\nghostliness\nghostlinesses\nghostly\nghosts\nghostwrite\nghostwriter\nghostwriters\nghostwrites\nghostwriting\nghostwritten\nghostwrote\nghosty\nghoul\nghoulie\nghoulies\nghoulish\nghoulishly\nghoulishness\nghoulishnesses\nghouls\nghyll\nghylls\ngiant\ngiantess\ngiantesses\ngiantism\ngiantisms\ngiantlike\ngiants\ngiaour\ngiaours\ngiardiases\ngiardiasis\ngib\ngibbed\ngibber\ngibbered\ngibberellin\ngibberellins\ngibbering\ngibberish\ngibberishes\ngibbers\ngibbet\ngibbeted\ngibbeting\ngibbets\ngibbetted\ngibbetting\ngibbing\ngibbon\ngibbons\ngibbose\ngibbosities\ngibbosity\ngibbous\ngibbsite\ngibbsites\ngibe\ngibed\ngiber\ngibers\ngibes\ngibing\ngibingly\ngiblet\ngiblets\ngibs\ngibson\ngibsons\ngid\ngiddap\ngiddied\ngiddier\ngiddies\ngiddiest\ngiddily\ngiddiness\ngiddinesses\ngiddy\ngiddyap\ngiddying\ngiddyup\ngids\ngie\ngied\ngieing\ngien\ngies\ngift\ngifted\ngiftedly\ngiftedness\ngiftednesses\ngifting\ngiftless\ngifts\ngiftware\ngiftwares\ngiftwrap\ngiftwrapped\ngiftwrapping\ngiftwraps\ngig\ngiga\ngigabit\ngigabits\ngigabyte\ngigabytes\ngigaflop\ngigaflops\ngigahertz\ngigantesque\ngigantic\ngigantically\ngigantism\ngigantisms\ngigas\ngigaton\ngigatons\ngigawatt\ngigawatts\ngigged\ngigging\ngiggle\ngiggled\ngiggler\ngigglers\ngiggles\ngigglier\ngiggliest\ngiggling\ngigglingly\ngiggly\ngighe\ngiglet\ngiglets\ngiglot\ngiglots\ngigolo\ngigolos\ngigot\ngigots\ngigs\ngigue\ngigues\ngilbert\ngilberts\ngild\ngilded\ngilder\ngilders\ngildhall\ngildhalls\ngilding\ngildings\ngilds\ngill\ngilled\ngiller\ngillers\ngillie\ngillied\ngillies\ngilling\ngillnet\ngillnets\ngillnetted\ngillnetter\ngillnetters\ngillnetting\ngills\ngilly\ngillyflower\ngillyflowers\ngillying\ngilt\ngilthead\ngiltheads\ngilts\ngimbal\ngimbaled\ngimbaling\ngimballed\ngimballing\ngimbals\ngimcrack\ngimcrackeries\ngimcrackery\ngimcracks\ngimel\ngimels\ngimlet\ngimleted\ngimleting\ngimlets\ngimmal\ngimmals\ngimme\ngimmes\ngimmick\ngimmicked\ngimmicking\ngimmickries\ngimmickry\ngimmicks\ngimmicky\ngimmie\ngimmies\ngimp\ngimped\ngimpier\ngimpiest\ngimping\ngimps\ngimpy\ngin\ngingal\ngingall\ngingalls\ngingals\ngingeley\ngingeleys\ngingeli\ngingelies\ngingelis\ngingelli\ngingellies\ngingellis\ngingelly\ngingely\nginger\ngingerbread\ngingerbreaded\ngingerbreads\ngingerbready\ngingered\ngingering\ngingerliness\ngingerlinesses\ngingerly\ngingerroot\ngingerroots\ngingers\ngingersnap\ngingersnaps\ngingery\ngingham\nginghams\ngingili\ngingilis\ngingilli\ngingillis\ngingiva\ngingivae\ngingival\ngingivectomies\ngingivectomy\ngingivitis\ngingivitises\ngingko\ngingkoes\ngink\nginkgo\nginkgoes\nginkgos\nginks\nginned\nginner\nginners\nginnier\nginniest\nginning\nginnings\nginny\ngins\nginseng\nginsengs\ngip\ngipon\ngipons\ngipped\ngipper\ngippers\ngipping\ngips\ngipsied\ngipsies\ngipsy\ngipsying\ngiraffe\ngiraffes\ngiraffish\ngirandole\ngirandoles\ngirasol\ngirasole\ngirasoles\ngirasols\ngird\ngirded\ngirder\ngirders\ngirding\ngirdle\ngirdled\ngirdler\ngirdlers\ngirdles\ngirdling\ngirds\ngirl\ngirlfriend\ngirlfriends\ngirlhood\ngirlhoods\ngirlie\ngirlies\ngirlish\ngirlishly\ngirlishness\ngirlishnesses\ngirls\ngirly\ngirn\ngirned\ngirning\ngirns\ngiro\ngiron\ngirons\ngiros\ngirosol\ngirosols\ngirsh\ngirshes\ngirt\ngirted\ngirth\ngirthed\ngirthing\ngirths\ngirting\ngirts\ngisarme\ngisarmes\ngismo\ngismos\ngist\ngists\ngit\ngitano\ngitanos\ngits\ngittern\ngitterns\ngittin\ngive\ngiveable\ngiveaway\ngiveaways\ngiveback\ngivebacks\ngiven\ngivens\ngiver\ngivers\ngives\ngiving\ngizmo\ngizmos\ngizzard\ngizzards\ngjetost\ngjetosts\nglabella\nglabellae\nglabellar\nglabrate\nglabrescent\nglabrous\nglace\nglaceed\nglaceing\nglaces\nglacial\nglacially\nglaciate\nglaciated\nglaciates\nglaciating\nglaciation\nglaciations\nglacier\nglaciers\nglaciological\nglaciologies\nglaciologist\nglaciologists\nglaciology\nglacis\nglacises\nglad\ngladded\ngladden\ngladdened\ngladdening\ngladdens\ngladder\ngladdest\ngladding\nglade\nglades\ngladiate\ngladiator\ngladiatorial\ngladiators\ngladier\ngladiest\ngladiola\ngladiolas\ngladioli\ngladiolus\ngladioluses\ngladlier\ngladliest\ngladly\ngladness\ngladnesses\nglads\ngladsome\ngladsomely\ngladsomeness\ngladsomenesses\ngladsomer\ngladsomest\ngladstone\ngladstones\nglady\nglaiket\nglaikit\nglair\nglaire\nglaired\nglaires\nglairier\nglairiest\nglairing\nglairs\nglairy\nglaive\nglaived\nglaives\nglamor\nglamorise\nglamorised\nglamorises\nglamorising\nglamorization\nglamorizations\nglamorize\nglamorized\nglamorizer\nglamorizers\nglamorizes\nglamorizing\nglamorous\nglamorously\nglamorousness\nglamorousnesses\nglamors\nglamour\nglamoured\nglamouring\nglamourize\nglamourized\nglamourizes\nglamourizing\nglamourless\nglamourous\nglamours\nglance\nglanced\nglancer\nglancers\nglances\nglancing\nglancingly\ngland\nglandered\nglanders\nglandes\nglandless\nglands\nglandular\nglandularly\nglandule\nglandules\nglans\nglare\nglared\nglares\nglarier\nglariest\nglaring\nglaringly\nglaringness\nglaringnesses\nglary\nglasnost\nglasnosts\nglass\nglassblower\nglassblowers\nglassblowing\nglassblowings\nglassed\nglasses\nglassful\nglassfuls\nglasshouse\nglasshouses\nglassie\nglassier\nglassies\nglassiest\nglassily\nglassine\nglassines\nglassiness\nglassinesses\nglassing\nglassless\nglassmaker\nglassmakers\nglassmaking\nglassmakings\nglassman\nglassmen\nglasspaper\nglasspapered\nglasspapering\nglasspapers\nglassware\nglasswares\nglasswork\nglassworker\nglassworkers\nglassworks\nglasswort\nglassworts\nglassy\nglaucoma\nglaucomas\nglauconite\nglauconites\nglauconitic\nglaucous\nglaucousness\nglaucousnesses\nglaze\nglazed\nglazer\nglazers\nglazes\nglazier\nglazieries\nglaziers\nglaziery\nglaziest\nglazing\nglazings\nglazy\ngleam\ngleamed\ngleamer\ngleamers\ngleamier\ngleamiest\ngleaming\ngleams\ngleamy\nglean\ngleanable\ngleaned\ngleaner\ngleaners\ngleaning\ngleanings\ngleans\ngleba\nglebae\nglebe\nglebes\ngled\nglede\ngledes\ngleds\nglee\ngleed\ngleeds\ngleeful\ngleefully\ngleefulness\ngleefulnesses\ngleek\ngleeked\ngleeking\ngleeks\ngleeman\ngleemen\nglees\ngleesome\ngleet\ngleeted\ngleetier\ngleetiest\ngleeting\ngleets\ngleety\ngleg\nglegly\nglegness\nglegnesses\ngleization\ngleizations\nglen\nglengarries\nglengarry\nglenlike\nglenoid\nglens\ngley\ngleyed\ngleying\ngleyings\ngleys\nglia\ngliadin\ngliadine\ngliadines\ngliadins\nglial\nglias\nglib\nglibber\nglibbest\nglibly\nglibness\nglibnesses\nglide\nglided\nglider\ngliders\nglides\ngliding\ngliff\ngliffs\nglim\nglime\nglimed\nglimes\ngliming\nglimmer\nglimmered\nglimmering\nglimmerings\nglimmers\nglimpse\nglimpsed\nglimpser\nglimpsers\nglimpses\nglimpsing\nglims\nglint\nglinted\nglinting\nglints\nglioblastoma\nglioblastomas\nglioblastomata\nglioma\ngliomas\ngliomata\nglissade\nglissaded\nglissader\nglissaders\nglissades\nglissading\nglissandi\nglissando\nglissandos\nglisten\nglistened\nglistening\nglistens\nglister\nglistered\nglistering\nglisters\nglitch\nglitches\nglitchy\nglitter\nglitterati\nglittered\nglittering\nglitteringly\nglitters\nglittery\nglitz\nglitzes\nglitzier\nglitziest\nglitzy\ngloam\ngloaming\ngloamings\ngloams\ngloat\ngloated\ngloater\ngloaters\ngloating\ngloatingly\ngloats\nglob\nglobal\nglobalise\nglobalised\nglobalises\nglobalising\nglobalism\nglobalisms\nglobalist\nglobalists\nglobalization\nglobalizations\nglobalize\nglobalized\nglobalizes\nglobalizing\nglobally\nglobate\nglobated\nglobbier\nglobbiest\nglobby\nglobe\nglobed\nglobefish\nglobefishes\nglobeflower\nglobeflowers\nglobes\nglobin\nglobing\nglobins\ngloboid\ngloboids\nglobose\nglobous\nglobs\nglobular\nglobule\nglobules\nglobulin\nglobulins\nglochid\nglochidia\nglochidium\nglochids\nglockenspiel\nglockenspiels\nglogg\ngloggs\nglom\nglomera\nglomerular\nglomerule\nglomerules\nglomeruli\nglomerulonephritides\nglomerulonephritis\nglomerulus\nglommed\nglomming\ngloms\nglomus\nglonoin\nglonoins\ngloom\ngloomed\ngloomful\ngloomier\ngloomiest\ngloomily\ngloominess\ngloominesses\nglooming\ngloomings\nglooms\ngloomy\nglop\nglopped\nglopping\ngloppy\nglops\ngloria\nglorias\ngloried\nglories\nglorification\nglorifications\nglorified\nglorifier\nglorifiers\nglorifies\nglorify\nglorifying\ngloriole\nglorioles\nglorious\ngloriously\ngloriousness\ngloriousnesses\nglory\nglorying\ngloss\nglossa\nglossae\nglossal\nglossarial\nglossaries\nglossarist\nglossarists\nglossary\nglossas\nglossator\nglossators\nglossed\nglosseme\nglossemes\nglosser\nglossers\nglosses\nglossier\nglossies\nglossiest\nglossily\nglossina\nglossinas\nglossiness\nglossinesses\nglossing\nglossitis\nglossitises\nglossographer\nglossographers\nglossolalia\nglossolalias\nglossolalist\nglossolalists\nglossopharyngeal\nglossopharyngeals\nglossy\nglost\nglosts\nglottal\nglottic\nglottides\nglottis\nglottises\nglottochronological\nglottochronologies\nglottochronology\nglout\nglouted\nglouting\nglouts\nglove\ngloved\nglover\nglovers\ngloves\ngloving\nglow\nglowed\nglower\nglowered\nglowering\nglowers\nglowflies\nglowfly\nglowing\nglowingly\nglows\nglowworm\nglowworms\ngloxinia\ngloxinias\ngloze\nglozed\nglozes\nglozing\nglucagon\nglucagons\nglucan\nglucans\nglucinic\nglucinum\nglucinums\nglucocorticoid\nglucocorticoids\nglucokinase\nglucokinases\ngluconate\ngluconates\ngluconeogeneses\ngluconeogenesis\nglucosamine\nglucosamines\nglucose\nglucoses\nglucosic\nglucosidase\nglucosidases\nglucoside\nglucosides\nglucosidic\nglucuronidase\nglucuronidases\nglucuronide\nglucuronides\nglue\nglued\nglueing\ngluelike\ngluepot\ngluepots\ngluer\ngluers\nglues\ngluey\nglug\nglugged\nglugging\nglugs\ngluier\ngluiest\ngluily\ngluing\nglum\nglume\nglumes\nglumly\nglummer\nglummest\nglumness\nglumnesses\nglumpier\nglumpiest\nglumpily\nglumpy\nglunch\nglunched\nglunches\nglunching\ngluon\ngluons\nglut\nglutamate\nglutamates\nglutaminase\nglutaminases\nglutamine\nglutamines\nglutaraldehyde\nglutaraldehydes\nglutathione\nglutathiones\ngluteal\nglutei\nglutelin\nglutelins\ngluten\nglutenous\nglutens\nglutethimide\nglutethimides\ngluteus\nglutinous\nglutinously\ngluts\nglutted\nglutting\nglutton\ngluttonies\ngluttonous\ngluttonously\ngluttonousness\ngluttonousnesses\ngluttons\ngluttony\nglycan\nglycans\nglyceraldehyde\nglyceraldehydes\nglyceric\nglyceride\nglycerides\nglyceridic\nglycerin\nglycerinate\nglycerinated\nglycerinates\nglycerinating\nglycerine\nglycerines\nglycerins\nglycerol\nglycerols\nglyceryl\nglyceryls\nglycin\nglycine\nglycines\nglycins\nglycogen\nglycogeneses\nglycogenesis\nglycogenolyses\nglycogenolysis\nglycogenolytic\nglycogens\nglycol\nglycolic\nglycolipid\nglycolipids\nglycols\nglycolyses\nglycolysis\nglycolytic\nglyconic\nglyconics\nglycopeptide\nglycopeptides\nglycoprotein\nglycoproteins\nglycosaminoglycan\nglycosaminoglycans\nglycosidase\nglycosidases\nglycoside\nglycosides\nglycosidic\nglycosidically\nglycosuria\nglycosurias\nglycosyl\nglycosylate\nglycosylated\nglycosylates\nglycosylating\nglycosylation\nglycosylations\nglycosyls\nglycyl\nglycyls\nglyph\nglyphic\nglyphs\nglyptic\nglyptics\ngnar\ngnarl\ngnarled\ngnarlier\ngnarliest\ngnarling\ngnarls\ngnarly\ngnarr\ngnarred\ngnarring\ngnarrs\ngnars\ngnash\ngnashed\ngnashes\ngnashing\ngnat\ngnatcatcher\ngnatcatchers\ngnathal\ngnathic\ngnathion\ngnathions\ngnathite\ngnathites\ngnatlike\ngnats\ngnattier\ngnattiest\ngnatty\ngnaw\ngnawable\ngnawed\ngnawer\ngnawers\ngnawing\ngnawings\ngnawn\ngnaws\ngneiss\ngneisses\ngneissic\ngneissoid\ngneissose\ngnocchi\ngnome\ngnomelike\ngnomes\ngnomic\ngnomical\ngnomish\ngnomist\ngnomists\ngnomon\ngnomonic\ngnomons\ngnoses\ngnosis\ngnostic\ngnosticism\ngnosticisms\ngnostics\ngnotobiotic\ngnotobiotically\ngnu\ngnus\ngo\ngoa\ngoad\ngoaded\ngoading\ngoadlike\ngoads\ngoal\ngoaled\ngoalie\ngoalies\ngoaling\ngoalkeeper\ngoalkeepers\ngoalless\ngoalmouth\ngoalmouths\ngoalpost\ngoalposts\ngoals\ngoaltender\ngoaltenders\ngoaltending\ngoaltendings\ngoalward\ngoanna\ngoannas\ngoas\ngoat\ngoatee\ngoateed\ngoatees\ngoatfish\ngoatfishes\ngoatherd\ngoatherds\ngoatish\ngoatlike\ngoats\ngoatskin\ngoatskins\ngoatsucker\ngoatsuckers\ngob\ngoban\ngobang\ngobangs\ngobans\ngobbed\ngobbet\ngobbets\ngobbing\ngobble\ngobbled\ngobbledegook\ngobbledegooks\ngobbledygook\ngobbledygooks\ngobbler\ngobblers\ngobbles\ngobbling\ngobies\ngobioid\ngobioids\ngoblet\ngoblets\ngoblin\ngoblins\ngobo\ngoboes\ngobonee\ngobony\ngobos\ngobs\ngoby\ngod\ngodchild\ngodchildren\ngoddam\ngoddammed\ngoddamming\ngoddamn\ngoddamned\ngoddamning\ngoddamns\ngoddams\ngoddaughter\ngoddaughters\ngodded\ngoddess\ngoddesses\ngodding\ngodet\ngodets\ngodfather\ngodfathered\ngodfathering\ngodfathers\ngodforsaken\ngodhead\ngodheads\ngodhood\ngodhoods\ngodless\ngodlessness\ngodlessnesses\ngodlier\ngodliest\ngodlike\ngodlikeness\ngodlikenesses\ngodlily\ngodliness\ngodlinesses\ngodling\ngodlings\ngodly\ngodmother\ngodmothers\ngodown\ngodowns\ngodparent\ngodparents\ngodroon\ngodroons\ngods\ngodsend\ngodsends\ngodship\ngodships\ngodson\ngodsons\ngodwit\ngodwits\ngoer\ngoers\ngoes\ngoethite\ngoethites\ngofer\ngofers\ngoffer\ngoffered\ngoffering\ngoffers\ngoggle\ngoggled\ngoggler\ngogglers\ngoggles\ngogglier\ngoggliest\ngoggling\ngoggly\ngoglet\ngoglets\ngogo\ngogos\ngoing\ngoings\ngoiter\ngoiters\ngoitre\ngoitres\ngoitrogen\ngoitrogenic\ngoitrogenicities\ngoitrogenicity\ngoitrogens\ngoitrous\ngolconda\ngolcondas\ngold\ngoldarn\ngoldarns\ngoldbrick\ngoldbricked\ngoldbricking\ngoldbricks\ngoldbug\ngoldbugs\ngolden\ngoldener\ngoldenest\ngoldeneye\ngoldeneyes\ngoldenly\ngoldenness\ngoldennesses\ngoldenrod\ngoldenrods\ngoldenseal\ngoldenseals\ngolder\ngoldest\ngoldeye\ngoldeyes\ngoldfield\ngoldfields\ngoldfinch\ngoldfinches\ngoldfish\ngoldfishes\ngolds\ngoldsmith\ngoldsmiths\ngoldstone\ngoldstones\ngoldurn\ngoldurns\ngolem\ngolems\ngolf\ngolfed\ngolfer\ngolfers\ngolfing\ngolfings\ngolfs\ngolgotha\ngolgothas\ngoliard\ngoliardic\ngoliards\ngolliwog\ngolliwogg\ngolliwoggs\ngolliwogs\ngolly\ngollywog\ngollywogs\ngolosh\ngoloshe\ngoloshes\ngombo\ngombos\ngombroon\ngombroons\ngomeral\ngomerals\ngomerel\ngomerels\ngomeril\ngomerils\ngomuti\ngomutis\ngonad\ngonadal\ngonadectomies\ngonadectomized\ngonadectomy\ngonadial\ngonadic\ngonadotrophic\ngonadotrophin\ngonadotrophins\ngonadotropic\ngonadotropin\ngonadotropins\ngonads\ngondola\ngondolas\ngondolier\ngondoliers\ngone\ngonef\ngonefs\ngoneness\ngonenesses\ngoner\ngoners\ngonfalon\ngonfalons\ngonfanon\ngonfanons\ngong\ngonged\ngonging\ngonglike\ngongoristic\ngongs\ngonia\ngonidia\ngonidial\ngonidic\ngonidium\ngonif\ngoniff\ngoniffs\ngonifs\ngoniometer\ngoniometers\ngoniometric\ngoniometries\ngoniometry\ngonion\ngonium\ngonococcal\ngonococci\ngonococcus\ngonocyte\ngonocytes\ngonof\ngonofs\ngonoph\ngonophore\ngonophores\ngonophs\ngonopore\ngonopores\ngonorrhea\ngonorrheal\ngonorrheas\ngonzo\ngoo\ngoober\ngoobers\ngood\ngoodby\ngoodbye\ngoodbyes\ngoodbys\ngoodie\ngoodies\ngoodish\ngoodlier\ngoodliest\ngoodly\ngoodman\ngoodmen\ngoodness\ngoodnesses\ngoods\ngoodwife\ngoodwill\ngoodwilled\ngoodwills\ngoodwives\ngoody\ngooey\ngooeyness\ngooeynesses\ngoof\ngoofball\ngoofballs\ngoofed\ngoofier\ngoofiest\ngoofily\ngoofiness\ngoofinesses\ngoofing\ngoofs\ngoofy\ngooglies\ngoogly\ngoogol\ngoogolplex\ngoogolplexes\ngoogols\ngooier\ngooiest\ngook\ngooks\ngooky\ngoombah\ngoombahs\ngoombay\ngoombays\ngoon\ngooney\ngooneys\ngoonie\ngoonies\ngoons\ngoony\ngoop\ngoopier\ngoopiest\ngoops\ngoopy\ngooral\ngoorals\ngoos\ngoosander\ngoosanders\ngoose\ngooseberries\ngooseberry\ngoosed\ngoosefish\ngoosefishes\ngooseflesh\ngoosefleshes\ngoosefoot\ngoosefoots\ngoosegrass\ngoosegrasses\ngooseneck\ngoosenecked\ngoosenecks\ngooses\ngoosey\ngoosier\ngoosiest\ngoosing\ngoosy\ngopher\ngophers\ngopik\ngor\ngoral\ngorals\ngorbellies\ngorbelly\ngorblimy\ngorcock\ngorcocks\ngore\ngored\ngores\ngorge\ngorged\ngorgedly\ngorgeous\ngorgeously\ngorgeousness\ngorgeousnesses\ngorger\ngorgerin\ngorgerins\ngorgers\ngorges\ngorget\ngorgeted\ngorgets\ngorging\ngorgon\ngorgonian\ngorgonians\ngorgonize\ngorgonized\ngorgonizes\ngorgonizing\ngorgons\ngorhen\ngorhens\ngorier\ngoriest\ngorilla\ngorillas\ngorily\ngoriness\ngorinesses\ngoring\ngormand\ngormandise\ngormandised\ngormandises\ngormandising\ngormandize\ngormandized\ngormandizer\ngormandizers\ngormandizes\ngormandizing\ngormands\ngormless\ngorp\ngorps\ngorse\ngorses\ngorsier\ngorsiest\ngorsy\ngory\ngos\ngosh\ngoshawk\ngoshawks\ngosling\ngoslings\ngospel\ngospeler\ngospelers\ngospeller\ngospellers\ngospels\ngosport\ngosports\ngossamer\ngossamers\ngossamery\ngossan\ngossans\ngossip\ngossiped\ngossiper\ngossipers\ngossiping\ngossipmonger\ngossipmongers\ngossipped\ngossipping\ngossipries\ngossipry\ngossips\ngossipy\ngossoon\ngossoons\ngossypol\ngossypols\ngot\ngothic\ngothically\ngothicize\ngothicized\ngothicizes\ngothicizing\ngothics\ngothite\ngothites\ngotten\ngouache\ngouaches\ngouge\ngouged\ngouger\ngougers\ngouges\ngouging\ngoulash\ngoulashes\ngourami\ngouramies\ngouramis\ngourd\ngourde\ngourdes\ngourds\ngourmand\ngourmandise\ngourmandises\ngourmandism\ngourmandisms\ngourmandize\ngourmandized\ngourmandizes\ngourmandizing\ngourmands\ngourmet\ngourmets\ngout\ngoutier\ngoutiest\ngoutily\ngouts\ngouty\ngovern\ngovernable\ngovernance\ngovernances\ngoverned\ngoverness\ngovernesses\ngovernessy\ngoverning\ngovernment\ngovernmental\ngovernmentalism\ngovernmentalisms\ngovernmentalist\ngovernmentalists\ngovernmentalize\ngovernmentalized\ngovernmentalizes\ngovernmentalizing\ngovernmentally\ngovernmentese\ngovernmenteses\ngovernments\ngovernor\ngovernorate\ngovernorates\ngovernors\ngovernorship\ngovernorships\ngoverns\ngowan\ngowaned\ngowans\ngowany\ngowd\ngowds\ngowk\ngowks\ngown\ngowned\ngowning\ngowns\ngownsman\ngownsmen\ngox\ngoxes\ngoy\ngoyim\ngoyish\ngoys\ngraal\ngraals\ngrab\ngrabbed\ngrabber\ngrabbers\ngrabbier\ngrabbiest\ngrabbing\ngrabble\ngrabbled\ngrabbler\ngrabblers\ngrabbles\ngrabbling\ngrabby\ngraben\ngrabens\ngrabs\ngrace\ngraced\ngraceful\ngracefuller\ngracefullest\ngracefully\ngracefulness\ngracefulnesses\ngraceless\ngracelessly\ngracelessness\ngracelessnesses\ngraces\ngracile\ngracileness\ngracilenesses\ngraciles\ngracilis\ngracilities\ngracility\ngracing\ngracioso\ngraciosos\ngracious\ngraciously\ngraciousness\ngraciousnesses\ngrackle\ngrackles\ngrad\ngradable\ngradate\ngradated\ngradates\ngradating\ngradation\ngradational\ngradationally\ngradations\ngrade\ngraded\ngradeless\ngrader\ngraders\ngrades\ngradient\ngradients\ngradin\ngradine\ngradines\ngrading\ngradins\ngradiometer\ngradiometers\ngrads\ngradual\ngradualism\ngradualisms\ngradualist\ngradualists\ngradually\ngradualness\ngradualnesses\ngraduals\ngraduand\ngraduands\ngraduate\ngraduated\ngraduates\ngraduating\ngraduation\ngraduations\ngraduator\ngraduators\ngradus\ngraduses\ngraecize\ngraecized\ngraecizes\ngraecizing\ngraffiti\ngraffitist\ngraffitists\ngraffito\ngraft\ngraftage\ngraftages\ngrafted\ngrafter\ngrafters\ngrafting\ngrafts\ngraham\ngrahams\ngrail\ngrails\ngrain\ngrained\ngrainer\ngrainers\ngrainfield\ngrainfields\ngrainier\ngrainiest\ngraininess\ngraininesses\ngraining\ngrains\ngrainy\ngram\ngrama\ngramaries\ngramary\ngramarye\ngramaryes\ngramas\ngramercies\ngramercy\ngramicidin\ngramicidins\ngramineous\ngraminivorous\ngrammar\ngrammarian\ngrammarians\ngrammars\ngrammatical\ngrammaticalities\ngrammaticality\ngrammatically\ngrammaticalness\ngrammaticalnesses\ngramme\ngrammes\ngramophone\ngramophones\ngramp\ngramps\ngrampus\ngrampuses\ngrams\ngran\ngrana\ngranadilla\ngranadillas\ngranaries\ngranary\ngrand\ngrandad\ngrandaddies\ngrandaddy\ngrandads\ngrandam\ngrandame\ngrandames\ngrandams\ngrandaunt\ngrandaunts\ngrandbabies\ngrandbaby\ngrandchild\ngrandchildren\ngranddad\ngranddaddies\ngranddaddy\ngranddads\ngranddam\ngranddams\ngranddaughter\ngranddaughters\ngrandee\ngrandees\ngrander\ngrandest\ngrandeur\ngrandeurs\ngrandfather\ngrandfathered\ngrandfathering\ngrandfatherly\ngrandfathers\ngrandiflora\ngrandiflorae\ngrandifloras\ngrandiloquence\ngrandiloquences\ngrandiloquent\ngrandiloquently\ngrandiose\ngrandiosely\ngrandioseness\ngrandiosenesses\ngrandiosities\ngrandiosity\ngrandioso\ngrandkid\ngrandkids\ngrandly\ngrandma\ngrandmas\ngrandmaster\ngrandmasters\ngrandmother\ngrandmotherly\ngrandmothers\ngrandnephew\ngrandnephews\ngrandness\ngrandnesses\ngrandniece\ngrandnieces\ngrandpa\ngrandparent\ngrandparental\ngrandparenthood\ngrandparenthoods\ngrandparents\ngrandpas\ngrands\ngrandsir\ngrandsire\ngrandsires\ngrandsirs\ngrandson\ngrandsons\ngrandstand\ngrandstanded\ngrandstander\ngrandstanders\ngrandstanding\ngrandstands\ngranduncle\ngranduncles\ngrange\ngranger\ngrangerism\ngrangerisms\ngrangers\ngranges\ngranita\ngranitas\ngranite\ngranitelike\ngranites\ngraniteware\ngranitewares\ngranitic\ngranitoid\ngranivorous\ngrannie\ngrannies\ngranny\ngranodiorite\ngranodiorites\ngranodioritic\ngranola\ngranolas\ngranolithic\ngranophyre\ngranophyres\ngranophyric\ngrans\ngrant\ngrantable\ngranted\ngrantee\ngrantees\ngranter\ngranters\ngranting\ngrantor\ngrantors\ngrants\ngrantsman\ngrantsmanship\ngrantsmanships\ngrantsmen\ngranular\ngranularities\ngranularity\ngranulate\ngranulated\ngranulates\ngranulating\ngranulation\ngranulations\ngranulator\ngranulators\ngranule\ngranules\ngranulite\ngranulites\ngranulitic\ngranulocyte\ngranulocytes\ngranulocytic\ngranulocytopoieses\ngranulocytopoiesis\ngranuloma\ngranulomas\ngranulomata\ngranulomatous\ngranulose\ngranuloses\ngranulosis\ngranum\ngrape\ngrapefruit\ngrapefruits\ngrapelike\ngraperies\ngrapery\ngrapes\ngrapeshot\ngrapevine\ngrapevines\ngrapey\ngraph\ngraphed\ngrapheme\ngraphemes\ngraphemic\ngraphemically\ngraphemics\ngraphic\ngraphical\ngraphically\ngraphicness\ngraphicnesses\ngraphics\ngraphing\ngraphite\ngraphites\ngraphitic\ngraphitizable\ngraphitization\ngraphitizations\ngraphitize\ngraphitized\ngraphitizes\ngraphitizing\ngrapholect\ngrapholects\ngraphological\ngraphologies\ngraphologist\ngraphologists\ngraphology\ngraphs\ngrapier\ngrapiest\ngrapiness\ngrapinesses\ngraplin\ngrapline\ngraplines\ngraplins\ngrapnel\ngrapnels\ngrappa\ngrappas\ngrapple\ngrappled\ngrappler\ngrapplers\ngrapples\ngrappling\ngrapplings\ngraptolite\ngraptolites\ngrapy\ngrasp\ngraspable\ngrasped\ngrasper\ngraspers\ngrasping\ngraspingly\ngraspingness\ngraspingnesses\ngrasps\ngrass\ngrassed\ngrasses\ngrasshopper\ngrasshoppers\ngrassier\ngrassiest\ngrassily\ngrassing\ngrassland\ngrasslands\ngrassless\ngrasslike\ngrassroot\ngrassroots\ngrassy\ngrat\ngrate\ngrated\ngrateful\ngratefuller\ngratefullest\ngratefully\ngratefulness\ngratefulnesses\ngrater\ngraters\ngrates\ngraticule\ngraticules\ngratification\ngratifications\ngratified\ngratifies\ngratify\ngratifying\ngratifyingly\ngratin\ngratine\ngratinee\ngratineed\ngratineeing\ngratinees\ngrating\ngratingly\ngratings\ngratins\ngratis\ngratitude\ngratitudes\ngratuities\ngratuitous\ngratuitously\ngratuitousness\ngratuitousnesses\ngratuity\ngratulate\ngratulated\ngratulates\ngratulating\ngratulation\ngratulations\ngratulatory\ngraupel\ngraupels\ngravamen\ngravamens\ngravamina\ngrave\ngraved\ngravel\ngraveled\ngraveless\ngraveling\ngravelled\ngravelling\ngravelly\ngravels\ngravely\ngraven\ngraveness\ngravenesses\ngraver\ngravers\ngraves\ngraveside\ngravesides\ngravest\ngravestone\ngravestones\ngraveyard\ngraveyards\ngravid\ngravida\ngravidae\ngravidas\ngravidities\ngravidity\ngravidly\ngravies\ngravimeter\ngravimeters\ngravimetric\ngravimetrically\ngravimetries\ngravimetry\ngraving\ngravitas\ngravitases\ngravitate\ngravitated\ngravitates\ngravitating\ngravitation\ngravitational\ngravitationally\ngravitations\ngravitative\ngravities\ngraviton\ngravitons\ngravity\ngravlaks\ngravlax\ngravure\ngravures\ngravy\ngray\ngrayback\ngraybacks\ngraybeard\ngraybeards\ngrayed\ngrayer\ngrayest\ngrayfish\ngrayfishes\ngraying\ngrayish\ngraylag\ngraylags\ngrayling\ngraylings\ngrayly\ngraymail\ngraymails\ngrayness\ngraynesses\ngrayout\ngrayouts\ngrays\ngraywacke\ngraywackes\ngrazable\ngraze\ngrazeable\ngrazed\ngrazer\ngrazers\ngrazes\ngrazier\ngraziers\ngrazing\ngrazings\ngrazioso\ngrease\ngreaseball\ngreaseballs\ngreased\ngreaseless\ngreasepaint\ngreasepaints\ngreaseproof\ngreaseproofs\ngreaser\ngreasers\ngreases\ngreasewood\ngreasewoods\ngreasier\ngreasiest\ngreasily\ngreasiness\ngreasinesses\ngreasing\ngreasy\ngreat\ngreatcoat\ngreatcoats\ngreaten\ngreatened\ngreatening\ngreatens\ngreater\ngreatest\ngreathearted\ngreatheartedly\ngreatheartedness\ngreatheartednesses\ngreatly\ngreatness\ngreatnesses\ngreats\ngreave\ngreaved\ngreaves\ngrebe\ngrebes\ngrecianize\ngrecianized\ngrecianizes\ngrecianizing\ngrecize\ngrecized\ngrecizes\ngrecizing\ngree\ngreed\ngreedier\ngreediest\ngreedily\ngreediness\ngreedinesses\ngreeds\ngreedy\ngreegree\ngreegrees\ngreeing\ngreek\ngreen\ngreenback\ngreenbacker\ngreenbackers\ngreenbackism\ngreenbackisms\ngreenbacks\ngreenbelt\ngreenbelts\ngreenbrier\ngreenbriers\ngreenbug\ngreenbugs\ngreened\ngreener\ngreeneries\ngreenery\ngreenest\ngreenfield\ngreenfinch\ngreenfinches\ngreenflies\ngreenfly\ngreengage\ngreengages\ngreengrocer\ngreengroceries\ngreengrocers\ngreengrocery\ngreenhead\ngreenheads\ngreenheart\ngreenhearts\ngreenhorn\ngreenhorns\ngreenhouse\ngreenhouses\ngreenie\ngreenier\ngreenies\ngreeniest\ngreening\ngreenings\ngreenish\ngreenishness\ngreenishnesses\ngreenkeeper\ngreenkeepers\ngreenlet\ngreenlets\ngreenling\ngreenlings\ngreenly\ngreenmail\ngreenmailed\ngreenmailer\ngreenmailers\ngreenmailing\ngreenmails\ngreenness\ngreennesses\ngreenockite\ngreenockites\ngreenroom\ngreenrooms\ngreens\ngreensand\ngreensands\ngreenshank\ngreenshanks\ngreensick\ngreensickness\ngreensicknesses\ngreenskeeper\ngreenskeepers\ngreenstone\ngreenstones\ngreenstuff\ngreenstuffs\ngreensward\ngreenswards\ngreenth\ngreenths\ngreenway\ngreenways\ngreenwing\ngreenwings\ngreenwood\ngreenwoods\ngreeny\ngrees\ngreet\ngreeted\ngreeter\ngreeters\ngreeting\ngreetings\ngreets\ngregarine\ngregarines\ngregarious\ngregariously\ngregariousness\ngregariousnesses\ngrego\ngregos\ngreige\ngreiges\ngreisen\ngreisens\ngremial\ngremials\ngremlin\ngremlins\ngremmie\ngremmies\ngremmy\ngrenade\ngrenades\ngrenadier\ngrenadiers\ngrenadine\ngrenadines\ngrew\ngrewsome\ngrewsomer\ngrewsomest\ngrey\ngreyed\ngreyer\ngreyest\ngreyhen\ngreyhens\ngreyhound\ngreyhounds\ngreying\ngreyish\ngreylag\ngreylags\ngreyly\ngreyness\ngreynesses\ngreys\ngribble\ngribbles\ngrid\ngridder\ngridders\ngriddle\ngriddlecake\ngriddlecakes\ngriddled\ngriddles\ngriddling\ngride\ngrided\ngrides\ngriding\ngridiron\ngridirons\ngridlock\ngridlocked\ngridlocking\ngridlocks\ngrids\ngrief\ngriefs\ngrievance\ngrievances\ngrievant\ngrievants\ngrieve\ngrieved\ngriever\ngrievers\ngrieves\ngrieving\ngrievous\ngrievously\ngrievousness\ngrievousnesses\ngriff\ngriffe\ngriffes\ngriffin\ngriffins\ngriffon\ngriffons\ngriffs\ngrift\ngrifted\ngrifter\ngrifters\ngrifting\ngrifts\ngrig\ngrigri\ngrigris\ngrigs\ngrill\ngrillade\ngrillades\ngrillage\ngrillages\ngrille\ngrilled\ngriller\ngrillers\ngrilles\ngrilling\ngrillroom\ngrillrooms\ngrills\ngrillwork\ngrillworks\ngrilse\ngrilses\ngrim\ngrimace\ngrimaced\ngrimacer\ngrimacers\ngrimaces\ngrimacing\ngrimalkin\ngrimalkins\ngrime\ngrimed\ngrimes\ngrimier\ngrimiest\ngrimily\ngriminess\ngriminesses\ngriming\ngrimly\ngrimmer\ngrimmest\ngrimness\ngrimnesses\ngrimy\ngrin\ngrinch\ngrinches\ngrind\ngrinded\ngrinder\ngrinderies\ngrinders\ngrindery\ngrinding\ngrindingly\ngrinds\ngrindstone\ngrindstones\ngringo\ngringos\ngrinned\ngrinner\ngrinners\ngrinning\ngrinningly\ngrins\ngriot\ngriots\ngrip\ngripe\ngriped\ngriper\ngripers\ngripes\ngripey\ngripier\ngripiest\ngriping\ngripman\ngripmen\ngrippe\ngripped\ngripper\ngrippers\ngrippes\ngrippier\ngrippiest\ngripping\ngrippingly\ngripple\ngrippy\ngrips\ngripsack\ngripsacks\ngript\ngripy\ngrisaille\ngrisailles\ngriseofulvin\ngriseofulvins\ngriseous\ngrisette\ngrisettes\ngriskin\ngriskins\ngrislier\ngrisliest\ngrisliness\ngrislinesses\ngrisly\ngrison\ngrisons\ngrist\ngristle\ngristles\ngristlier\ngristliest\ngristliness\ngristlinesses\ngristly\ngristmill\ngristmills\ngrists\ngrit\ngrith\ngriths\ngrits\ngritted\ngrittier\ngrittiest\ngrittily\ngrittiness\ngrittinesses\ngritting\ngritty\ngrivet\ngrivets\ngrizzle\ngrizzled\ngrizzler\ngrizzlers\ngrizzles\ngrizzlier\ngrizzlies\ngrizzliest\ngrizzling\ngrizzly\ngroan\ngroaned\ngroaner\ngroaners\ngroaning\ngroans\ngroat\ngroats\ngrocer\ngroceries\ngrocers\ngrocery\ngrodier\ngrodiest\ngrody\ngrog\ngroggeries\ngroggery\ngroggier\ngroggiest\ngroggily\ngrogginess\ngrogginesses\ngroggy\ngrogram\ngrograms\ngrogs\ngrogshop\ngrogshops\ngroin\ngroined\ngroining\ngroins\ngrommet\ngrommets\ngromwell\ngromwells\ngroom\ngroomed\ngroomer\ngroomers\ngrooming\ngrooms\ngroomsman\ngroomsmen\ngroove\ngrooved\ngroover\ngroovers\ngrooves\ngroovier\ngrooviest\ngrooving\ngroovy\ngrope\ngroped\ngroper\ngropers\ngropes\ngroping\ngrosbeak\ngrosbeaks\ngroschen\ngrosgrain\ngrosgrains\ngross\ngrossed\ngrosser\ngrossers\ngrosses\ngrossest\ngrossing\ngrossly\ngrossness\ngrossnesses\ngrossular\ngrossularite\ngrossularites\ngrossulars\ngrosz\ngrosze\ngroszy\ngrot\ngrotesque\ngrotesquely\ngrotesqueness\ngrotesquenesses\ngrotesquerie\ngrotesqueries\ngrotesquery\ngrotesques\ngrots\ngrottier\ngrottiest\ngrotto\ngrottoes\ngrottos\ngrotty\ngrouch\ngrouched\ngrouches\ngrouchier\ngrouchiest\ngrouchily\ngrouchiness\ngrouchinesses\ngrouching\ngrouchy\nground\ngroundbreaker\ngroundbreakers\ngroundbreaking\ngroundburst\ngroundbursts\ngrounded\ngrounder\ngrounders\ngroundfish\ngroundfishes\ngroundhog\ngroundhogs\ngrounding\ngroundings\ngroundless\ngroundlessly\ngroundlessness\ngroundlessnesses\ngroundling\ngroundlings\ngroundmass\ngroundmasses\ngroundnut\ngroundnuts\ngroundout\ngroundouts\ngrounds\ngroundsel\ngroundsels\ngroundsheet\ngroundsheets\ngroundskeeper\ngroundskeepers\ngroundsman\ngroundsmen\ngroundswell\ngroundswells\ngroundwater\ngroundwaters\ngroundwood\ngroundwoods\ngroundwork\ngroundworks\ngroup\ngroupable\ngrouped\ngrouper\ngroupers\ngroupie\ngroupies\ngrouping\ngroupings\ngroupoid\ngroupoids\ngroups\ngroupthink\ngroupthinks\ngroupuscule\ngroupuscules\ngrouse\ngroused\ngrouser\ngrousers\ngrouses\ngrousing\ngrout\ngrouted\ngrouter\ngrouters\ngroutier\ngroutiest\ngrouting\ngrouts\ngrouty\ngrove\ngroved\ngrovel\ngroveled\ngroveler\ngrovelers\ngroveling\ngrovelingly\ngrovelled\ngrovelling\ngrovels\ngroves\ngrow\ngrowable\ngrower\ngrowers\ngrowing\ngrowingly\ngrowl\ngrowled\ngrowler\ngrowlers\ngrowlier\ngrowliest\ngrowliness\ngrowlinesses\ngrowling\ngrowlingly\ngrowls\ngrowly\ngrown\ngrownup\ngrownups\ngrows\ngrowth\ngrowthier\ngrowthiest\ngrowthiness\ngrowthinesses\ngrowths\ngrowthy\ngroyne\ngroynes\ngrub\ngrubbed\ngrubber\ngrubbers\ngrubbier\ngrubbiest\ngrubbily\ngrubbiness\ngrubbinesses\ngrubbing\ngrubby\ngrubs\ngrubstake\ngrubstaked\ngrubstaker\ngrubstakers\ngrubstakes\ngrubstaking\ngrubworm\ngrubworms\ngrudge\ngrudged\ngrudger\ngrudgers\ngrudges\ngrudging\ngrudgingly\ngrue\ngruel\ngrueled\ngrueler\ngruelers\ngrueling\ngruelingly\ngruelings\ngruelled\ngrueller\ngruellers\ngruelling\ngruellings\ngruels\ngrues\ngruesome\ngruesomely\ngruesomeness\ngruesomenesses\ngruesomer\ngruesomest\ngruff\ngruffed\ngruffer\ngruffest\ngruffier\ngruffiest\ngruffily\ngruffing\ngruffish\ngruffly\ngruffness\ngruffnesses\ngruffs\ngruffy\ngrugru\ngrugrus\ngruiform\ngrum\ngrumble\ngrumbled\ngrumbler\ngrumblers\ngrumbles\ngrumbling\ngrumblingly\ngrumbly\ngrume\ngrumes\ngrummer\ngrummest\ngrummet\ngrummets\ngrumose\ngrumous\ngrump\ngrumped\ngrumphie\ngrumphies\ngrumphy\ngrumpier\ngrumpiest\ngrumpily\ngrumpiness\ngrumpinesses\ngrumping\ngrumpish\ngrumps\ngrumpy\ngrunge\ngrunges\ngrungier\ngrungiest\ngrungy\ngrunion\ngrunions\ngrunt\ngrunted\ngrunter\ngrunters\ngrunting\ngruntle\ngruntled\ngruntles\ngruntling\ngrunts\ngrushie\ngrutch\ngrutched\ngrutches\ngrutching\ngrutten\ngruyere\ngruyeres\ngryphon\ngryphons\nguacamole\nguacamoles\nguacharo\nguacharoes\nguacharos\nguaco\nguacos\nguaiac\nguaiacol\nguaiacols\nguaiacs\nguaiacum\nguaiacums\nguaiocum\nguaiocums\nguan\nguanaco\nguanacos\nguanase\nguanases\nguanay\nguanays\nguanethidine\nguanethidines\nguanidin\nguanidine\nguanidines\nguanidins\nguanin\nguanine\nguanines\nguanins\nguano\nguanos\nguanosine\nguanosines\nguans\nguar\nguarani\nguaranies\nguaranis\nguarantee\nguaranteed\nguaranteeing\nguarantees\nguarantied\nguaranties\nguarantor\nguarantors\nguaranty\nguarantying\nguard\nguardant\nguardants\nguarded\nguardedly\nguardedness\nguardednesses\nguarder\nguarders\nguardhouse\nguardhouses\nguardian\nguardians\nguardianship\nguardianships\nguarding\nguardrail\nguardrails\nguardroom\nguardrooms\nguards\nguardsman\nguardsmen\nguars\nguava\nguavas\nguayabera\nguayaberas\nguayule\nguayules\ngubernatorial\nguck\ngucks\ngude\ngudes\ngudgeon\ngudgeoned\ngudgeoning\ngudgeons\nguenon\nguenons\nguerdon\nguerdoned\nguerdoning\nguerdons\ngueridon\ngueridons\nguerilla\nguerillas\nguernsey\nguernseys\nguerrilla\nguerrillas\nguess\nguessable\nguessed\nguesser\nguessers\nguesses\nguessing\nguesstimate\nguesstimated\nguesstimates\nguesstimating\nguesswork\nguessworks\nguest\nguested\nguesthouse\nguesthouses\nguesting\nguestroom\nguestrooms\nguests\nguff\nguffaw\nguffawed\nguffawing\nguffaws\nguffs\nguggle\nguggled\nguggles\nguggling\nguglet\nguglets\nguid\nguidable\nguidance\nguidances\nguide\nguidebook\nguidebooks\nguided\nguideline\nguidelines\nguidepost\nguideposts\nguider\nguiders\nguides\nguideway\nguideways\nguiding\nguidon\nguidons\nguids\nguidwillie\nguild\nguilder\nguilders\nguildhall\nguildhalls\nguilds\nguildship\nguildships\nguildsman\nguildsmen\nguile\nguiled\nguileful\nguilefully\nguilefulness\nguilefulnesses\nguileless\nguilelessly\nguilelessness\nguilelessnesses\nguiles\nguiling\nguillemet\nguillemets\nguillemot\nguillemots\nguilloche\nguilloches\nguillotine\nguillotined\nguillotines\nguillotining\nguilt\nguiltier\nguiltiest\nguiltily\nguiltiness\nguiltinesses\nguiltless\nguiltlessly\nguiltlessness\nguiltlessnesses\nguilts\nguilty\nguimpe\nguimpes\nguinea\nguineas\nguipure\nguipures\nguiro\nguiros\nguisard\nguisards\nguise\nguised\nguises\nguising\nguitar\nguitarfish\nguitarfishes\nguitarist\nguitarists\nguitars\nguitguit\nguitguits\ngul\ngulag\ngulags\ngular\ngulch\ngulches\ngulden\nguldens\ngules\ngulf\ngulfed\ngulfier\ngulfiest\ngulfing\ngulflike\ngulfs\ngulfweed\ngulfweeds\ngulfy\ngull\ngullable\ngullably\ngulled\ngullet\ngullets\ngulley\ngulleys\ngullibilities\ngullibility\ngullible\ngullibly\ngullied\ngullies\ngulling\ngulls\ngully\ngullying\ngulosities\ngulosity\ngulp\ngulped\ngulper\ngulpers\ngulpier\ngulpiest\ngulping\ngulps\ngulpy\nguls\ngum\ngumbo\ngumboil\ngumboils\ngumboot\ngumboots\ngumbos\ngumbotil\ngumbotils\ngumdrop\ngumdrops\ngumless\ngumlike\ngumma\ngummas\ngummata\ngummatous\ngummed\ngummer\ngummers\ngummier\ngummiest\ngumminess\ngumminesses\ngumming\ngummite\ngummites\ngummose\ngummoses\ngummosis\ngummous\ngummy\ngumption\ngumptions\ngums\ngumshoe\ngumshoed\ngumshoeing\ngumshoes\ngumtree\ngumtrees\ngumweed\ngumweeds\ngumwood\ngumwoods\ngun\ngunboat\ngunboats\nguncotton\nguncottons\ngundog\ngundogs\ngunfight\ngunfighter\ngunfighters\ngunfighting\ngunfights\ngunfire\ngunfires\ngunflint\ngunflints\ngunfought\ngunite\ngunites\ngunk\ngunkhole\ngunkholed\ngunkholes\ngunkholing\ngunks\ngunky\ngunless\ngunlock\ngunlocks\ngunman\ngunmen\ngunmetal\ngunmetals\ngunned\ngunnel\ngunnels\ngunnen\ngunner\ngunneries\ngunners\ngunnery\ngunnies\ngunning\ngunnings\ngunny\ngunnybag\ngunnybags\ngunnysack\ngunnysacks\ngunpaper\ngunpapers\ngunplay\ngunplays\ngunpoint\ngunpoints\ngunpowder\ngunpowders\ngunroom\ngunrooms\ngunrunner\ngunrunners\ngunrunning\ngunrunnings\nguns\ngunsel\ngunsels\ngunship\ngunships\ngunshot\ngunshots\ngunslinger\ngunslingers\ngunslinging\ngunslingings\ngunsmith\ngunsmithing\ngunsmithings\ngunsmiths\ngunstock\ngunstocks\ngunwale\ngunwales\nguppies\nguppy\ngurge\ngurged\ngurges\ngurging\ngurgle\ngurgled\ngurgles\ngurglet\ngurglets\ngurgling\ngurnard\ngurnards\ngurnet\ngurnets\ngurney\ngurneys\ngurries\ngurry\ngursh\ngurshes\nguru\ngurus\nguruship\nguruships\ngush\ngushed\ngusher\ngushers\ngushes\ngushier\ngushiest\ngushily\ngushiness\ngushinesses\ngushing\ngushingly\ngushy\ngusset\ngusseted\ngusseting\ngussets\ngussie\ngussied\ngussies\ngussy\ngussying\ngust\ngustable\ngustables\ngustation\ngustations\ngustatorily\ngustatory\ngusted\ngustier\ngustiest\ngustily\ngustiness\ngustinesses\ngusting\ngustless\ngusto\ngustoes\ngusts\ngusty\ngut\ngutbucket\ngutbuckets\ngutless\ngutlessness\ngutlessnesses\ngutlike\nguts\ngutsier\ngutsiest\ngutsily\ngutsiness\ngutsinesses\ngutsy\ngutta\nguttae\nguttate\nguttated\nguttation\nguttations\ngutted\ngutter\nguttered\nguttering\ngutterings\ngutters\nguttersnipe\nguttersnipes\nguttersnipish\nguttery\nguttier\nguttiest\ngutting\nguttle\nguttled\nguttler\nguttlers\nguttles\nguttling\nguttural\ngutturalism\ngutturalisms\ngutturals\ngutty\nguv\nguvs\nguy\nguyed\nguying\nguyline\nguylines\nguyot\nguyots\nguys\nguzzle\nguzzled\nguzzler\nguzzlers\nguzzles\nguzzling\ngweduc\ngweduck\ngweducks\ngweducs\ngybe\ngybed\ngybes\ngybing\ngym\ngymkhana\ngymkhanas\ngymnasia\ngymnasium\ngymnasiums\ngymnast\ngymnastic\ngymnastically\ngymnastics\ngymnasts\ngymnosophist\ngymnosophists\ngymnosperm\ngymnospermies\ngymnospermous\ngymnosperms\ngymnospermy\ngyms\ngynaecea\ngynaeceum\ngynaecia\ngynaecium\ngynaecologies\ngynaecology\ngynandries\ngynandromorph\ngynandromorphic\ngynandromorphies\ngynandromorphism\ngynandromorphisms\ngynandromorphs\ngynandromorphy\ngynandrous\ngynandry\ngynarchies\ngynarchy\ngynecia\ngynecic\ngynecium\ngynecocracies\ngynecocracy\ngynecocratic\ngynecoid\ngynecologic\ngynecological\ngynecologies\ngynecologist\ngynecologists\ngynecology\ngynecomastia\ngynecomastias\ngyniatries\ngyniatry\ngynoecia\ngynoecium\ngynogeneses\ngynogenesis\ngynogenetic\ngynophore\ngynophores\ngyp\ngyplure\ngyplures\ngypped\ngypper\ngyppers\ngypping\ngyps\ngypseian\ngypseous\ngypsied\ngypsies\ngypsiferous\ngypsophila\ngypsophilas\ngypster\ngypsters\ngypsum\ngypsums\ngypsy\ngypsydom\ngypsydoms\ngypsying\ngypsyish\ngypsyism\ngypsyisms\ngyral\ngyrally\ngyrase\ngyrases\ngyrate\ngyrated\ngyrates\ngyrating\ngyration\ngyrational\ngyrations\ngyrator\ngyrators\ngyratory\ngyre\ngyred\ngyrene\ngyrenes\ngyres\ngyrfalcon\ngyrfalcons\ngyri\ngyring\ngyro\ngyrocompass\ngyrocompasses\ngyrofrequencies\ngyrofrequency\ngyroidal\ngyromagnetic\ngyron\ngyrons\ngyroplane\ngyroplanes\ngyros\ngyroscope\ngyroscopes\ngyroscopic\ngyroscopically\ngyrose\ngyrostabilizer\ngyrostabilizers\ngyrostat\ngyrostats\ngyrus\ngyve\ngyved\ngyves\ngyving\nha\nhaaf\nhaafs\nhaar\nhaars\nhabanera\nhabaneras\nhabdalah\nhabdalahs\nhaberdasher\nhaberdasheries\nhaberdashers\nhaberdashery\nhabergeon\nhabergeons\nhabile\nhabiliment\nhabiliments\nhabilitate\nhabilitated\nhabilitates\nhabilitating\nhabilitation\nhabilitations\nhabit\nhabitabilities\nhabitability\nhabitable\nhabitableness\nhabitablenesses\nhabitably\nhabitan\nhabitans\nhabitant\nhabitants\nhabitat\nhabitation\nhabitations\nhabitats\nhabited\nhabiting\nhabits\nhabitual\nhabitually\nhabitualness\nhabitualnesses\nhabituate\nhabituated\nhabituates\nhabituating\nhabituation\nhabituations\nhabitude\nhabitudes\nhabitue\nhabitues\nhabitus\nhaboob\nhaboobs\nhabu\nhabus\nhacek\nhaceks\nhacendado\nhacendados\nhachure\nhachured\nhachures\nhachuring\nhacienda\nhaciendado\nhaciendados\nhaciendas\nhack\nhackamore\nhackamores\nhackberries\nhackberry\nhackbut\nhackbuts\nhacked\nhackee\nhackees\nhacker\nhackers\nhackie\nhackies\nhacking\nhackle\nhackled\nhackler\nhacklers\nhackles\nhacklier\nhackliest\nhackling\nhackly\nhackman\nhackmatack\nhackmatacks\nhackmen\nhackney\nhackneyed\nhackneying\nhackneys\nhacks\nhacksaw\nhacksaws\nhackwork\nhackworks\nhad\nhadal\nhadarim\nhaddest\nhaddock\nhaddocks\nhade\nhaded\nhades\nhading\nhadith\nhadiths\nhadj\nhadjee\nhadjees\nhadjes\nhadji\nhadjis\nhadron\nhadronic\nhadrons\nhadrosaur\nhadrosaurs\nhadst\nhae\nhaecceities\nhaecceity\nhaed\nhaeing\nhaem\nhaemal\nhaematal\nhaematic\nhaematics\nhaematin\nhaematins\nhaematite\nhaematites\nhaemic\nhaemin\nhaemins\nhaemoid\nhaems\nhaen\nhaeredes\nhaeres\nhaes\nhaet\nhaets\nhaffet\nhaffets\nhaffit\nhaffits\nhafis\nhafiz\nhafnium\nhafniums\nhaft\nhaftara\nhaftarah\nhaftarahs\nhaftaras\nhaftarot\nhaftaroth\nhafted\nhafter\nhafters\nhafting\nhaftorah\nhaftorahs\nhaftorot\nhaftoroth\nhafts\nhag\nhagadic\nhagadist\nhagadists\nhagberries\nhagberry\nhagborn\nhagbush\nhagbushes\nhagbut\nhagbuts\nhagdon\nhagdons\nhagfish\nhagfishes\nhaggada\nhaggadah\nhaggadahs\nhaggadas\nhaggadic\nhaggadist\nhaggadistic\nhaggadists\nhaggadot\nhaggadoth\nhaggard\nhaggardly\nhaggardness\nhaggardnesses\nhaggards\nhagged\nhagging\nhaggis\nhaggises\nhaggish\nhaggle\nhaggled\nhaggler\nhagglers\nhaggles\nhaggling\nhagiographer\nhagiographers\nhagiographic\nhagiographical\nhagiographies\nhagiography\nhagiologic\nhagiological\nhagiologies\nhagiology\nhagioscope\nhagioscopes\nhagioscopic\nhagridden\nhagride\nhagrides\nhagriding\nhagrode\nhags\nhah\nhaha\nhahas\nhahnium\nhahniums\nhahs\nhaik\nhaika\nhaiks\nhaiku\nhaikus\nhail\nhailed\nhailer\nhailers\nhailing\nhails\nhailstone\nhailstones\nhailstorm\nhailstorms\nhair\nhairball\nhairballs\nhairband\nhairbands\nhairbreadth\nhairbreadths\nhairbrush\nhairbrushes\nhaircap\nhaircaps\nhaircloth\nhaircloths\nhaircut\nhaircuts\nhaircutter\nhaircutters\nhaircutting\nhaircuttings\nhairdo\nhairdos\nhairdresser\nhairdressers\nhairdressing\nhairdressings\nhaired\nhairier\nhairiest\nhairiness\nhairinesses\nhairless\nhairlessness\nhairlessnesses\nhairlike\nhairline\nhairlines\nhairlock\nhairlocks\nhairnet\nhairnets\nhairpiece\nhairpieces\nhairpin\nhairpins\nhairs\nhairsbreadth\nhairsbreadths\nhairsplitter\nhairsplitters\nhairsplitting\nhairsplittings\nhairspring\nhairsprings\nhairstreak\nhairstreaks\nhairstyle\nhairstyles\nhairstyling\nhairstylings\nhairstylist\nhairstylists\nhairwork\nhairworks\nhairworm\nhairworms\nhairy\nhaj\nhajes\nhaji\nhajis\nhajj\nhajjes\nhajji\nhajjis\nhake\nhakeem\nhakeems\nhakes\nhakim\nhakims\nhalacha\nhalachas\nhalachot\nhalachoth\nhalakah\nhalakahs\nhalakha\nhalakhas\nhalakhot\nhalakic\nhalakist\nhalakists\nhalakoth\nhalala\nhalalah\nhalalahs\nhalalas\nhalation\nhalations\nhalavah\nhalavahs\nhalazone\nhalazones\nhalberd\nhalberds\nhalbert\nhalberts\nhalcyon\nhalcyons\nhale\nhaled\nhaleness\nhalenesses\nhaler\nhalers\nhaleru\nhales\nhalest\nhalf\nhalfback\nhalfbacks\nhalfbeak\nhalfbeaks\nhalfhearted\nhalfheartedly\nhalfheartedness\nhalfheartednesses\nhalflife\nhalflives\nhalfness\nhalfnesses\nhalfpence\nhalfpennies\nhalfpenny\nhalftime\nhalftimes\nhalftone\nhalftones\nhalfway\nhalibut\nhalibuts\nhalid\nhalide\nhalides\nhalidom\nhalidome\nhalidomes\nhalidoms\nhalids\nhaling\nhalite\nhalites\nhalitoses\nhalitosis\nhalitus\nhalituses\nhall\nhallah\nhallahs\nhallel\nhallels\nhallelujah\nhallelujahs\nhalliard\nhalliards\nhallmark\nhallmarked\nhallmarking\nhallmarks\nhallo\nhalloa\nhalloaed\nhalloaing\nhalloas\nhalloed\nhalloes\nhalloing\nhalloo\nhallooed\nhallooing\nhalloos\nhallos\nhallot\nhalloth\nhallow\nhallowed\nhallower\nhallowers\nhallowing\nhallows\nhalls\nhalluces\nhallucinate\nhallucinated\nhallucinates\nhallucinating\nhallucination\nhallucinations\nhallucinator\nhallucinators\nhallucinatory\nhallucinogen\nhallucinogenic\nhallucinogenics\nhallucinogens\nhallucinoses\nhallucinosis\nhallux\nhallway\nhallways\nhalm\nhalma\nhalmas\nhalms\nhalo\nhalocarbon\nhalocarbons\nhalocline\nhaloclines\nhaloed\nhaloes\nhalogen\nhalogenate\nhalogenated\nhalogenates\nhalogenating\nhalogenation\nhalogenations\nhalogenous\nhalogens\nhalogeton\nhalogetons\nhaloid\nhaloids\nhaloing\nhalolike\nhalomorphic\nhaloperidol\nhaloperidols\nhalophile\nhalophiles\nhalophilic\nhalophyte\nhalophytes\nhalophytic\nhalos\nhalothane\nhalothanes\nhalt\nhalted\nhalter\nhalterbreak\nhalterbreaking\nhalterbreaks\nhalterbroke\nhalterbroken\nhaltere\nhaltered\nhalteres\nhaltering\nhalters\nhalting\nhaltingly\nhaltless\nhalts\nhalutz\nhalutzim\nhalva\nhalvah\nhalvahs\nhalvas\nhalve\nhalved\nhalvers\nhalves\nhalving\nhalyard\nhalyards\nham\nhamada\nhamadas\nhamadryad\nhamadryades\nhamadryads\nhamal\nhamals\nhamantasch\nhamantaschen\nhamartia\nhamartias\nhamate\nhamates\nhamaul\nhamauls\nhambone\nhamboned\nhambones\nhamboning\nhamburg\nhamburger\nhamburgers\nhamburgs\nhame\nhames\nhamlet\nhamlets\nhammada\nhammadas\nhammal\nhammals\nhammed\nhammer\nhammered\nhammerer\nhammerers\nhammerhead\nhammerheads\nhammering\nhammerless\nhammerlock\nhammerlocks\nhammers\nhammertoe\nhammertoes\nhammier\nhammiest\nhammily\nhamminess\nhamminesses\nhamming\nhammock\nhammocks\nhammy\nhamper\nhampered\nhamperer\nhamperers\nhampering\nhampers\nhams\nhamster\nhamsters\nhamstring\nhamstringing\nhamstrings\nhamstrung\nhamular\nhamulate\nhamuli\nhamulose\nhamulous\nhamulus\nhamza\nhamzah\nhamzahs\nhamzas\nhanaper\nhanapers\nhance\nhances\nhand\nhandbag\nhandbags\nhandball\nhandballs\nhandbarrow\nhandbarrows\nhandbasket\nhandbaskets\nhandbell\nhandbells\nhandbill\nhandbills\nhandblown\nhandbook\nhandbooks\nhandbreadth\nhandbreadths\nhandcar\nhandcars\nhandcart\nhandcarts\nhandclasp\nhandclasps\nhandcraft\nhandcrafted\nhandcrafting\nhandcrafts\nhandcraftsman\nhandcraftsmanship\nhandcraftsmanships\nhandcraftsmen\nhandcuff\nhandcuffed\nhandcuffing\nhandcuffs\nhanded\nhandedness\nhandednesses\nhandfast\nhandfasted\nhandfasting\nhandfastings\nhandfasts\nhandful\nhandfuls\nhandgrip\nhandgrips\nhandgun\nhandguns\nhandheld\nhandhelds\nhandhold\nhandholding\nhandholdings\nhandholds\nhandicap\nhandicapped\nhandicapper\nhandicappers\nhandicapping\nhandicaps\nhandicraft\nhandicrafter\nhandicrafters\nhandicrafts\nhandicraftsman\nhandicraftsmen\nhandier\nhandiest\nhandily\nhandiness\nhandinesses\nhanding\nhandiwork\nhandiworks\nhandkerchief\nhandkerchiefs\nhandkerchieves\nhandle\nhandleable\nhandlebar\nhandlebars\nhandled\nhandleless\nhandler\nhandlers\nhandles\nhandless\nhandlike\nhandling\nhandlings\nhandlist\nhandlists\nhandloom\nhandlooms\nhandmade\nhandmaid\nhandmaiden\nhandmaidens\nhandmaids\nhandoff\nhandoffs\nhandout\nhandouts\nhandover\nhandovers\nhandpick\nhandpicked\nhandpicking\nhandpicks\nhandpress\nhandpresses\nhandprint\nhandprints\nhandrail\nhandrailing\nhandrailings\nhandrails\nhands\nhandsaw\nhandsaws\nhandsbreadth\nhandsbreadths\nhandsel\nhandseled\nhandseling\nhandselled\nhandselling\nhandsels\nhandset\nhandsets\nhandsewn\nhandsful\nhandshake\nhandshakes\nhandshaking\nhandshakings\nhandsome\nhandsomely\nhandsomeness\nhandsomenesses\nhandsomer\nhandsomest\nhandspike\nhandspikes\nhandspring\nhandsprings\nhandstand\nhandstands\nhandwheel\nhandwheels\nhandwork\nhandworker\nhandworkers\nhandworks\nhandwoven\nhandwringer\nhandwringers\nhandwringing\nhandwringings\nhandwrit\nhandwrite\nhandwrites\nhandwriting\nhandwritings\nhandwritten\nhandwrote\nhandwrought\nhandy\nhandyman\nhandymen\nhandyperson\nhandypersons\nhang\nhangable\nhangar\nhangared\nhangaring\nhangars\nhangbird\nhangbirds\nhangdog\nhangdogs\nhanged\nhanger\nhangers\nhangfire\nhangfires\nhanging\nhangings\nhangman\nhangmen\nhangnail\nhangnails\nhangnest\nhangnests\nhangout\nhangouts\nhangover\nhangovers\nhangs\nhangtag\nhangtags\nhangul\nhangup\nhangups\nhaniwa\nhank\nhanked\nhanker\nhankered\nhankerer\nhankerers\nhankering\nhankers\nhankie\nhankies\nhanking\nhanks\nhanky\nhansa\nhansas\nhanse\nhansel\nhanseled\nhanseling\nhanselled\nhanselling\nhansels\nhanses\nhansom\nhansoms\nhant\nhantavirus\nhantaviruses\nhanted\nhanting\nhantle\nhantles\nhants\nhanuman\nhanumans\nhao\nhaole\nhaoles\nhap\nhapax\nhapaxes\nhaphazard\nhaphazardly\nhaphazardness\nhaphazardnesses\nhaphazardries\nhaphazardry\nhaphazards\nhaphtara\nhaphtaras\nhaphtarot\nhaphtaroth\nhapless\nhaplessly\nhaplessness\nhaplessnesses\nhaplite\nhaplites\nhaploid\nhaploidies\nhaploids\nhaploidy\nhaplologies\nhaplology\nhaplont\nhaplontic\nhaplonts\nhaplopia\nhaplopias\nhaploses\nhaplosis\nhaplotype\nhaplotypes\nhaply\nhapped\nhappen\nhappenchance\nhappenchances\nhappened\nhappening\nhappenings\nhappens\nhappenstance\nhappenstances\nhappier\nhappiest\nhappily\nhappiness\nhappinesses\nhapping\nhappy\nhaps\nhapten\nhaptene\nhaptenes\nhaptenic\nhaptens\nhaptic\nhaptical\nhaptoglobin\nhaptoglobins\nharangue\nharangued\nharanguer\nharanguers\nharangues\nharanguing\nharass\nharassed\nharasser\nharassers\nharasses\nharassing\nharassment\nharassments\nharbinger\nharbingered\nharbingering\nharbingers\nharbor\nharborage\nharborages\nharbored\nharborer\nharborers\nharborful\nharborfuls\nharboring\nharborless\nharbormaster\nharbormasters\nharbors\nharborside\nharbour\nharboured\nharbouring\nharbours\nhard\nhardback\nhardbacks\nhardball\nhardballs\nhardboard\nhardboards\nhardboot\nhardboots\nhardbound\nhardcase\nhardcore\nhardcores\nhardcover\nhardcovers\nhardedge\nhardedges\nharden\nhardened\nhardener\nhardeners\nhardening\nhardenings\nhardens\nharder\nhardest\nhardfisted\nhardhack\nhardhacks\nhardhanded\nhardhandedness\nhardhandednesses\nhardhat\nhardhats\nhardhead\nhardheaded\nhardheadedly\nhardheadedness\nhardheadednesses\nhardheads\nhardhearted\nhardheartedly\nhardheartedness\nhardheartednesses\nhardier\nhardies\nhardiest\nhardihood\nhardihoods\nhardily\nhardiment\nhardiments\nhardiness\nhardinesses\nhardinggrass\nhardinggrasses\nhardline\nhardly\nhardmouthed\nhardness\nhardnesses\nhardnose\nhardnoses\nhardpan\nhardpans\nhards\nhardscrabble\nhardset\nhardship\nhardships\nhardstand\nhardstanding\nhardstandings\nhardstands\nhardtack\nhardtacks\nhardtop\nhardtops\nhardware\nhardwares\nhardwire\nhardwired\nhardwires\nhardwiring\nhardwood\nhardwoods\nhardworking\nhardy\nhare\nharebell\nharebells\nharebrained\nhared\nhareem\nhareems\nharelike\nharelip\nharelips\nharem\nharems\nhares\nhariana\nharianas\nharicot\nharicots\nharijan\nharijans\nharing\nhark\nharked\nharken\nharkened\nharkener\nharkeners\nharkening\nharkens\nharking\nharks\nharl\nharlequin\nharlequinade\nharlequinades\nharlequins\nharlot\nharlotries\nharlotry\nharlots\nharls\nharm\nharmattan\nharmattans\nharmed\nharmer\nharmers\nharmful\nharmfully\nharmfulness\nharmfulnesses\nharmin\nharmine\nharmines\nharming\nharmins\nharmless\nharmlessly\nharmlessness\nharmlessnesses\nharmonic\nharmonica\nharmonically\nharmonicas\nharmonicist\nharmonicists\nharmonics\nharmonies\nharmonious\nharmoniously\nharmoniousness\nharmoniousnesses\nharmonise\nharmonised\nharmonises\nharmonising\nharmonium\nharmoniums\nharmonization\nharmonizations\nharmonize\nharmonized\nharmonizer\nharmonizers\nharmonizes\nharmonizing\nharmony\nharms\nharness\nharnessed\nharnesses\nharnessing\nharp\nharped\nharper\nharpers\nharpies\nharpin\nharping\nharpings\nharpins\nharpist\nharpists\nharpoon\nharpooned\nharpooner\nharpooners\nharpooning\nharpoons\nharps\nharpsichord\nharpsichordist\nharpsichordists\nharpsichords\nharpy\nharquebus\nharquebuses\nharquebusier\nharquebusiers\nharridan\nharridans\nharried\nharrier\nharriers\nharries\nharrow\nharrowed\nharrower\nharrowers\nharrowing\nharrows\nharrumph\nharrumphed\nharrumphing\nharrumphs\nharry\nharrying\nharsh\nharshen\nharshened\nharshening\nharshens\nharsher\nharshest\nharshly\nharshness\nharshnesses\nharslet\nharslets\nhart\nhartal\nhartals\nhartebeest\nhartebeests\nharts\nhartshorn\nhartshorns\nharumph\nharumphed\nharumphing\nharumphs\nharuspex\nharuspication\nharuspications\nharuspices\nharvest\nharvestable\nharvested\nharvester\nharvesters\nharvesting\nharvestman\nharvestmen\nharvests\nharvesttime\nharvesttimes\nhas\nhasenpfeffer\nhasenpfeffers\nhash\nhashed\nhasheesh\nhasheeshes\nhashes\nhashhead\nhashheads\nhashing\nhashish\nhashishes\nhaslet\nhaslets\nhasp\nhasped\nhasping\nhasps\nhassel\nhassels\nhassium\nhassiums\nhassle\nhassled\nhassles\nhassling\nhassock\nhassocks\nhast\nhastate\nhaste\nhasted\nhasteful\nhasten\nhastened\nhastener\nhasteners\nhastening\nhastens\nhastes\nhastier\nhastiest\nhastily\nhastiness\nhastinesses\nhasting\nhasty\nhat\nhatable\nhatband\nhatbands\nhatbox\nhatboxes\nhatch\nhatchabilities\nhatchability\nhatchable\nhatchback\nhatchbacks\nhatcheck\nhatched\nhatchel\nhatcheled\nhatcheling\nhatchelled\nhatchelling\nhatchels\nhatcher\nhatcheries\nhatchers\nhatchery\nhatches\nhatchet\nhatchets\nhatching\nhatchings\nhatchling\nhatchlings\nhatchment\nhatchments\nhatchway\nhatchways\nhate\nhateable\nhated\nhateful\nhatefully\nhatefulness\nhatefulnesses\nhatemonger\nhatemongers\nhater\nhaters\nhates\nhatful\nhatfuls\nhath\nhating\nhatless\nhatlike\nhatmaker\nhatmakers\nhatpin\nhatpins\nhatrack\nhatracks\nhatred\nhatreds\nhats\nhatsful\nhatted\nhatter\nhatteria\nhatterias\nhatters\nhatting\nhauberk\nhauberks\nhaugh\nhaughs\nhaughtier\nhaughtiest\nhaughtily\nhaughtiness\nhaughtinesses\nhaughty\nhaul\nhaulage\nhaulages\nhauled\nhauler\nhaulers\nhaulier\nhauliers\nhauling\nhaulm\nhaulmier\nhaulmiest\nhaulms\nhaulmy\nhauls\nhaulyard\nhaulyards\nhaunch\nhaunched\nhaunches\nhaunt\nhaunted\nhaunter\nhaunters\nhaunting\nhauntingly\nhaunts\nhausen\nhausens\nhausfrau\nhausfrauen\nhausfraus\nhaustella\nhaustellum\nhaustoria\nhaustorial\nhaustorium\nhaut\nhautbois\nhautboy\nhautboys\nhaute\nhauteur\nhauteurs\nhavarti\nhavartis\nhavdalah\nhavdalahs\nhave\nhavelock\nhavelocks\nhaven\nhavened\nhavening\nhavens\nhaver\nhavered\nhaverel\nhaverels\nhavering\nhavers\nhaversack\nhaversacks\nhaves\nhaving\nhavior\nhaviors\nhaviour\nhaviours\nhavoc\nhavocked\nhavocker\nhavockers\nhavocking\nhavocs\nhaw\nhawed\nhawfinch\nhawfinches\nhawing\nhawk\nhawkbill\nhawkbills\nhawked\nhawker\nhawkers\nhawkey\nhawkeyed\nhawkeys\nhawkie\nhawkies\nhawking\nhawkings\nhawkish\nhawkishly\nhawkishness\nhawkishnesses\nhawklike\nhawkmoth\nhawkmoths\nhawknose\nhawknoses\nhawks\nhawksbill\nhawksbills\nhawkshaw\nhawkshaws\nhawkweed\nhawkweeds\nhaws\nhawse\nhawsehole\nhawseholes\nhawser\nhawsers\nhawses\nhawthorn\nhawthorns\nhay\nhaycock\nhaycocks\nhayed\nhayer\nhayers\nhayfield\nhayfields\nhayfork\nhayforks\nhaying\nhayings\nhaylage\nhaylages\nhayloft\nhaylofts\nhaymaker\nhaymakers\nhaymow\nhaymows\nhayrack\nhayracks\nhayrick\nhayricks\nhayride\nhayrides\nhays\nhayseed\nhayseeds\nhaystack\nhaystacks\nhayward\nhaywards\nhaywire\nhaywires\nhazan\nhazanim\nhazans\nhazard\nhazarded\nhazarding\nhazardous\nhazardously\nhazardousness\nhazardousnesses\nhazards\nhaze\nhazed\nhazel\nhazelhen\nhazelhens\nhazelly\nhazelnut\nhazelnuts\nhazels\nhazer\nhazers\nhazes\nhazier\nhaziest\nhazily\nhaziness\nhazinesses\nhazing\nhazings\nhazy\nhazzan\nhazzanim\nhazzans\nhe\nhead\nheadache\nheadaches\nheadachier\nheadachiest\nheadachy\nheadband\nheadbands\nheadboard\nheadboards\nheadcheese\nheadcheeses\nheadcount\nheadcounts\nheaddress\nheaddresses\nheaded\nheader\nheaders\nheadfirst\nheadfish\nheadfishes\nheadforemost\nheadgate\nheadgates\nheadgear\nheadgears\nheadhunt\nheadhunted\nheadhunter\nheadhunters\nheadhunting\nheadhunts\nheadier\nheadiest\nheadily\nheadiness\nheadinesses\nheading\nheadings\nheadlamp\nheadlamps\nheadland\nheadlands\nheadless\nheadlessness\nheadlessnesses\nheadlight\nheadlights\nheadline\nheadlined\nheadliner\nheadliners\nheadlines\nheadlining\nheadlock\nheadlocks\nheadlong\nheadman\nheadmaster\nheadmasters\nheadmastership\nheadmasterships\nheadmen\nheadmistress\nheadmistresses\nheadmost\nheadnote\nheadnotes\nheadphone\nheadphones\nheadpiece\nheadpieces\nheadpin\nheadpins\nheadquarter\nheadquartered\nheadquartering\nheadquarters\nheadrace\nheadraces\nheadrest\nheadrests\nheadroom\nheadrooms\nheads\nheadsail\nheadsails\nheadset\nheadsets\nheadship\nheadships\nheadshrinker\nheadshrinkers\nheadsman\nheadsmen\nheadspace\nheadspaces\nheadspring\nheadsprings\nheadstall\nheadstalls\nheadstand\nheadstands\nheadstay\nheadstays\nheadstock\nheadstocks\nheadstone\nheadstones\nheadstream\nheadstreams\nheadstrong\nheadwaiter\nheadwaiters\nheadwater\nheadwaters\nheadway\nheadways\nheadwind\nheadwinds\nheadword\nheadwords\nheadwork\nheadworks\nheady\nheal\nhealable\nhealed\nhealer\nhealers\nhealing\nhealings\nheals\nhealth\nhealthful\nhealthfully\nhealthfulness\nhealthfulnesses\nhealthier\nhealthiest\nhealthily\nhealthiness\nhealthinesses\nhealths\nhealthy\nheap\nheaped\nheaping\nheaps\nhear\nhearable\nheard\nhearer\nhearers\nhearing\nhearings\nhearken\nhearkened\nhearkening\nhearkens\nhears\nhearsay\nhearsays\nhearse\nhearsed\nhearses\nhearsing\nheart\nheartache\nheartaches\nheartbeat\nheartbeats\nheartbreak\nheartbreaker\nheartbreakers\nheartbreaking\nheartbreakingly\nheartbreaks\nheartbroken\nheartburn\nheartburning\nheartburnings\nheartburns\nhearted\nhearten\nheartened\nheartening\nhearteningly\nheartens\nheartfelt\nhearth\nhearths\nhearthstone\nhearthstones\nheartier\nhearties\nheartiest\nheartily\nheartiness\nheartinesses\nhearting\nheartland\nheartlands\nheartless\nheartlessly\nheartlessness\nheartlessnesses\nheartrending\nheartrendingly\nhearts\nheartsease\nheartseases\nheartsick\nheartsickness\nheartsicknesses\nheartsome\nheartsomely\nheartsore\nheartstring\nheartstrings\nheartthrob\nheartthrobs\nheartwarming\nheartwood\nheartwoods\nheartworm\nheartworms\nhearty\nheat\nheatable\nheated\nheatedly\nheater\nheaters\nheath\nheathen\nheathendom\nheathendoms\nheathenish\nheathenishly\nheathenism\nheathenisms\nheathenize\nheathenized\nheathenizes\nheathenizing\nheathens\nheather\nheathers\nheathery\nheathier\nheathiest\nheathland\nheathlands\nheathless\nheathlike\nheaths\nheathy\nheating\nheatless\nheatproof\nheats\nheatstroke\nheatstrokes\nheaume\nheaumes\nheave\nheaved\nheaven\nheavenlier\nheavenliest\nheavenliness\nheavenlinesses\nheavenly\nheavens\nheavenward\nheavenwards\nheaver\nheavers\nheaves\nheavier\nheavies\nheaviest\nheavily\nheaviness\nheavinesses\nheaving\nheavy\nheavyhearted\nheavyheartedly\nheavyheartedness\nheavyheartednesses\nheavyset\nheavyweight\nheavyweights\nhebdomad\nhebdomadal\nhebdomadally\nhebdomads\nhebe\nhebephrenia\nhebephrenias\nhebephrenic\nhebephrenics\nhebes\nhebetate\nhebetated\nhebetates\nhebetating\nhebetation\nhebetations\nhebetic\nhebetude\nhebetudes\nhebetudinous\nhebraization\nhebraizations\nhebraize\nhebraized\nhebraizes\nhebraizing\nhecatomb\nhecatombs\nheck\nheckle\nheckled\nheckler\nhecklers\nheckles\nheckling\nhecks\nhectare\nhectares\nhectic\nhectical\nhectically\nhecticly\nhectogram\nhectograms\nhectograph\nhectographed\nhectographing\nhectographs\nhectoliter\nhectoliters\nhectometer\nhectometers\nhector\nhectored\nhectoring\nhectoringly\nhectors\nheddle\nheddles\nheder\nheders\nhedge\nhedged\nhedgehog\nhedgehogs\nhedgehop\nhedgehopped\nhedgehopper\nhedgehoppers\nhedgehopping\nhedgehops\nhedgepig\nhedgepigs\nhedger\nhedgerow\nhedgerows\nhedgers\nhedges\nhedgier\nhedgiest\nhedging\nhedgingly\nhedgy\nhedonic\nhedonically\nhedonics\nhedonism\nhedonisms\nhedonist\nhedonistic\nhedonistically\nhedonists\nheed\nheeded\nheeder\nheeders\nheedful\nheedfully\nheedfulness\nheedfulnesses\nheeding\nheedless\nheedlessly\nheedlessness\nheedlessnesses\nheeds\nheehaw\nheehawed\nheehawing\nheehaws\nheel\nheelball\nheelballs\nheeled\nheeler\nheelers\nheeling\nheelings\nheelless\nheelpiece\nheelpieces\nheelpost\nheelposts\nheels\nheeltap\nheeltaps\nheeze\nheezed\nheezes\nheezing\nheft\nhefted\nhefter\nhefters\nheftier\nheftiest\nheftily\nheftiness\nheftinesses\nhefting\nhefts\nhefty\nhegari\nhegaris\nhegemonic\nhegemonies\nhegemony\nhegira\nhegiras\nhegumen\nhegumene\nhegumenes\nhegumenies\nhegumens\nhegumeny\nheh\nhehs\nheifer\nheifers\nheigh\nheight\nheighten\nheightened\nheightening\nheightens\nheighth\nheighths\nheights\nheil\nheiled\nheiling\nheils\nheimish\nheinie\nheinies\nheinous\nheinously\nheinousness\nheinousnesses\nheir\nheirdom\nheirdoms\nheired\nheiress\nheiresses\nheiring\nheirless\nheirloom\nheirlooms\nheirs\nheirship\nheirships\nheishi\nheist\nheisted\nheister\nheisters\nheisting\nheists\nhejira\nhejiras\nhektare\nhektares\nheld\nheldentenor\nheldentenors\nheliac\nheliacal\nheliacally\nheliast\nheliasts\nhelical\nhelically\nhelices\nhelicities\nhelicity\nhelicoid\nhelicoidal\nhelicoids\nhelicon\nhelicons\nhelicopt\nhelicopted\nhelicopter\nhelicoptered\nhelicoptering\nhelicopters\nhelicopting\nhelicopts\nhelilift\nhelilifted\nhelilifting\nhelilifts\nhelio\nheliocentric\nheliograph\nheliographed\nheliographic\nheliographing\nheliographs\nheliolatries\nheliolatrous\nheliolatry\nheliometer\nheliometers\nheliometric\nheliometrically\nhelios\nheliostat\nheliostats\nheliotrope\nheliotropes\nheliotropic\nheliotropism\nheliotropisms\nheliozoan\nheliozoans\nhelipad\nhelipads\nheliport\nheliports\nhelistop\nhelistops\nhelium\nheliums\nhelix\nhelixes\nhell\nhellacious\nhellaciously\nhellbender\nhellbenders\nhellbent\nhellbox\nhellboxes\nhellbroth\nhellbroths\nhellcat\nhellcats\nhellebore\nhellebores\nhelled\nhellenization\nhellenizations\nhellenize\nhellenized\nhellenizes\nhellenizing\nheller\nhelleri\nhelleries\nhelleris\nhellers\nhellery\nhellfire\nhellfires\nhellgrammite\nhellgrammites\nhellhole\nhellholes\nhellhound\nhellhounds\nhelling\nhellion\nhellions\nhellish\nhellishly\nhellishness\nhellishnesses\nhellkite\nhellkites\nhello\nhelloed\nhelloes\nhelloing\nhellos\nhells\nhelluva\nhelm\nhelmed\nhelmet\nhelmeted\nhelmeting\nhelmetlike\nhelmets\nhelming\nhelminth\nhelminthiases\nhelminthiasis\nhelminthic\nhelminthologies\nhelminthology\nhelminths\nhelmless\nhelms\nhelmsman\nhelmsmanship\nhelmsmanships\nhelmsmen\nhelo\nhelos\nhelot\nhelotage\nhelotages\nhelotism\nhelotisms\nhelotries\nhelotry\nhelots\nhelp\nhelpable\nhelped\nhelper\nhelpers\nhelpful\nhelpfully\nhelpfulness\nhelpfulnesses\nhelping\nhelpings\nhelpless\nhelplessly\nhelplessness\nhelplessnesses\nhelpmate\nhelpmates\nhelpmeet\nhelpmeets\nhelps\nhelve\nhelved\nhelves\nhelving\nhem\nhemacytometer\nhemacytometers\nhemagglutinate\nhemagglutinated\nhemagglutinates\nhemagglutinating\nhemagglutination\nhemagglutinations\nhemagglutinin\nhemagglutinins\nhemagog\nhemagogs\nhemal\nhemangioma\nhemangiomas\nhemangiomata\nhematal\nhematein\nhemateins\nhematic\nhematics\nhematin\nhematine\nhematines\nhematinic\nhematinics\nhematins\nhematite\nhematites\nhematitic\nhematocrit\nhematocrits\nhematogenous\nhematoid\nhematologic\nhematological\nhematologies\nhematologist\nhematologists\nhematology\nhematoma\nhematomas\nhematomata\nhematophagous\nhematopoieses\nhematopoiesis\nhematopoietic\nhematoporphyrin\nhematoporphyrins\nhematoxylin\nhematoxylins\nhematuria\nhematurias\nheme\nhemelytra\nhemelytron\nhemerocallis\nhemerocallises\nhemerythrin\nhemerythrins\nhemes\nhemiacetal\nhemiacetals\nhemic\nhemicellulose\nhemicelluloses\nhemichordate\nhemichordates\nhemicycle\nhemicycles\nhemidemisemiquaver\nhemidemisemiquavers\nhemihedral\nhemihydrate\nhemihydrated\nhemihydrates\nhemimetabolous\nhemimorphic\nhemimorphism\nhemimorphisms\nhemin\nhemins\nhemiola\nhemiolas\nhemiolia\nhemiolias\nhemiplegia\nhemiplegias\nhemiplegic\nhemiplegics\nhemipter\nhemipteran\nhemipterans\nhemipterous\nhemipters\nhemisphere\nhemispheres\nhemispheric\nhemispherical\nhemistich\nhemistichs\nhemizygous\nhemline\nhemlines\nhemlock\nhemlocks\nhemmed\nhemmer\nhemmers\nhemming\nhemochromatoses\nhemochromatosis\nhemocoel\nhemocoels\nhemocyanin\nhemocyanins\nhemocyte\nhemocytes\nhemocytometer\nhemocytometers\nhemodialyses\nhemodialysis\nhemodilution\nhemodilutions\nhemodynamic\nhemodynamically\nhemodynamics\nhemoflagellate\nhemoflagellates\nhemoglobin\nhemoglobinopathies\nhemoglobinopathy\nhemoglobins\nhemoglobinuria\nhemoglobinurias\nhemoglobinuric\nhemoid\nhemolymph\nhemolymphs\nhemolyses\nhemolysin\nhemolysins\nhemolysis\nhemolytic\nhemolyze\nhemolyzed\nhemolyzes\nhemolyzing\nhemophilia\nhemophiliac\nhemophiliacs\nhemophilias\nhemophilic\nhemophilics\nhemopoieses\nhemopoiesis\nhemopoietic\nhemoprotein\nhemoproteins\nhemoptyses\nhemoptysis\nhemorrhage\nhemorrhaged\nhemorrhages\nhemorrhagic\nhemorrhaging\nhemorrhoid\nhemorrhoidal\nhemorrhoidals\nhemorrhoids\nhemosiderin\nhemosiderins\nhemostases\nhemostasis\nhemostat\nhemostatic\nhemostatics\nhemostats\nhemp\nhempen\nhempie\nhempier\nhempiest\nhemplike\nhemps\nhempseed\nhempseeds\nhempweed\nhempweeds\nhempy\nhems\nhemstitch\nhemstitched\nhemstitcher\nhemstitchers\nhemstitches\nhemstitching\nhen\nhenbane\nhenbanes\nhenbit\nhenbits\nhence\nhenceforth\nhenceforward\nhenchman\nhenchmen\nhencoop\nhencoops\nhendecasyllabic\nhendecasyllabics\nhendecasyllable\nhendecasyllables\nhendiadys\nhendiadyses\nhenequen\nhenequens\nhenequin\nhenequins\nhenhouse\nhenhouses\nheniquen\nheniquens\nhenlike\nhenna\nhennaed\nhennaing\nhennas\nhenneries\nhennery\nhenotheism\nhenotheisms\nhenotheist\nhenotheistic\nhenotheists\nhenpeck\nhenpecked\nhenpecking\nhenpecks\nhenries\nhenry\nhenrys\nhens\nhent\nhented\nhenting\nhents\nhep\nheparin\nheparinized\nheparins\nhepatectomies\nhepatectomized\nhepatectomy\nhepatic\nhepatica\nhepaticae\nhepaticas\nhepatics\nhepatitides\nhepatitis\nhepatize\nhepatized\nhepatizes\nhepatizing\nhepatocellular\nhepatocyte\nhepatocytes\nhepatoma\nhepatomas\nhepatomata\nhepatomegalies\nhepatomegaly\nhepatopancreas\nhepatopancreases\nhepatotoxic\nhepatotoxicities\nhepatotoxicity\nhepcat\nhepcats\nheptachlor\nheptachlors\nheptad\nheptads\nheptagon\nheptagonal\nheptagons\nheptameter\nheptameters\nheptane\nheptanes\nheptarch\nheptarchies\nheptarchs\nheptarchy\nheptose\nheptoses\nher\nherald\nheralded\nheraldic\nheraldically\nheralding\nheraldries\nheraldry\nheralds\nherb\nherbaceous\nherbage\nherbages\nherbal\nherbalist\nherbalists\nherbals\nherbaria\nherbarium\nherbariums\nherbed\nherbicidal\nherbicidally\nherbicide\nherbicides\nherbier\nherbiest\nherbivore\nherbivores\nherbivories\nherbivorous\nherbivory\nherbless\nherblike\nherbs\nherby\nherculean\nhercules\nherculeses\nherd\nherded\nherder\nherders\nherdic\nherdics\nherding\nherdlike\nherdman\nherdmen\nherds\nherdsman\nherdsmen\nhere\nhereabout\nhereabouts\nhereafter\nhereafters\nhereat\nhereaway\nhereaways\nhereby\nheredes\nhereditament\nhereditaments\nhereditarian\nhereditarians\nhereditarily\nhereditary\nheredities\nheredity\nherein\nhereinabove\nhereinafter\nhereinbefore\nhereinbelow\nhereinto\nhereof\nhereon\nheres\nheresiarch\nheresiarchs\nheresies\nheresy\nheretic\nheretical\nheretically\nheretics\nhereto\nheretofore\nheretrices\nheretrix\nheretrixes\nhereunder\nhereunto\nhereupon\nherewith\nheriot\nheriots\nheritabilities\nheritability\nheritable\nheritage\nheritages\nheritor\nheritors\nheritrices\nheritrix\nheritrixes\nherl\nherls\nherm\nherma\nhermae\nhermaean\nhermai\nhermaphrodite\nhermaphrodites\nhermaphroditic\nhermaphroditism\nhermaphroditisms\nhermatypic\nhermeneutic\nhermeneutical\nhermeneutically\nhermeneutics\nhermetic\nhermetical\nhermetically\nhermeticism\nhermeticisms\nhermetism\nhermetisms\nhermetist\nhermetists\nhermit\nhermitage\nhermitages\nhermitic\nhermitism\nhermitisms\nhermitries\nhermitry\nhermits\nherms\nhern\nhernia\nherniae\nhernial\nhernias\nherniate\nherniated\nherniates\nherniating\nherniation\nherniations\nherns\nhero\nheroes\nheroic\nheroical\nheroically\nheroicomic\nheroicomical\nheroics\nheroin\nheroine\nheroines\nheroinism\nheroinisms\nheroins\nheroism\nheroisms\nheroize\nheroized\nheroizes\nheroizing\nheron\nheronries\nheronry\nherons\nheros\nherpes\nherpesvirus\nherpesviruses\nherpetic\nherpetological\nherpetologies\nherpetologist\nherpetologists\nherpetology\nherrenvolk\nherrenvolks\nherried\nherries\nherring\nherringbone\nherringboned\nherringbones\nherringboning\nherrings\nherry\nherrying\nhers\nherself\nherstories\nherstory\nhertz\nhertzes\nhes\nhesitance\nhesitances\nhesitancies\nhesitancy\nhesitant\nhesitantly\nhesitate\nhesitated\nhesitater\nhesitaters\nhesitates\nhesitating\nhesitatingly\nhesitation\nhesitations\nhesperidia\nhesperidin\nhesperidins\nhesperidium\nhessian\nhessians\nhessite\nhessites\nhessonite\nhessonites\nhest\nhests\nhet\nhetaera\nhetaerae\nhetaeras\nhetaeric\nhetaira\nhetairai\nhetairas\nhetero\nheteroatom\nheteroatoms\nheteroauxin\nheteroauxins\nheterocercal\nheterochromatic\nheterochromatin\nheterochromatins\nheteroclite\nheteroclites\nheterocycle\nheterocycles\nheterocyclic\nheterocyclics\nheterocyst\nheterocystous\nheterocysts\nheterodox\nheterodoxies\nheterodoxy\nheteroduplex\nheteroduplexes\nheterodyne\nheterodyned\nheterodynes\nheterodyning\nheteroecious\nheteroecism\nheteroecisms\nheterogamete\nheterogametes\nheterogametic\nheterogameties\nheterogamety\nheterogamies\nheterogamous\nheterogamy\nheterogeneities\nheterogeneity\nheterogeneous\nheterogeneously\nheterogeneousness\nheterogeneousnesses\nheterogenies\nheterogenous\nheterogeny\nheterogonic\nheterogonies\nheterogony\nheterograft\nheterografts\nheterokarya\nheterokaryon\nheterokaryons\nheterokaryoses\nheterokaryosis\nheterokaryotic\nheterologous\nheterologously\nheterolyses\nheterolysis\nheterolytic\nheteromorphic\nheteromorphism\nheteromorphisms\nheteronomies\nheteronomous\nheteronomy\nheteronym\nheteronyms\nheterophil\nheterophile\nheterophonies\nheterophony\nheterophyllies\nheterophyllous\nheterophylly\nheteroploid\nheteroploidies\nheteroploids\nheteroploidy\nheteropterous\nheteros\nheteroses\nheterosexual\nheterosexualities\nheterosexuality\nheterosexually\nheterosexuals\nheterosis\nheterospories\nheterosporous\nheterospory\nheterothallic\nheterothallism\nheterothallisms\nheterotic\nheterotopic\nheterotroph\nheterotrophic\nheterotrophically\nheterotrophies\nheterotrophs\nheterotrophy\nheterotypic\nheterozygoses\nheterozygosis\nheterozygosities\nheterozygosity\nheterozygote\nheterozygotes\nheterozygous\nheth\nheths\nhetman\nhetmans\nhets\nheuch\nheuchs\nheugh\nheughs\nheulandite\nheulandites\nheuristic\nheuristically\nheuristics\nhew\nhewable\nhewed\nhewer\nhewers\nhewing\nhewn\nhews\nhex\nhexachlorethane\nhexachlorethanes\nhexachloroethane\nhexachloroethanes\nhexachlorophene\nhexachlorophenes\nhexachord\nhexachords\nhexad\nhexade\nhexadecimal\nhexadecimals\nhexades\nhexadic\nhexads\nhexagon\nhexagonal\nhexagonally\nhexagons\nhexagram\nhexagrams\nhexahedra\nhexahedron\nhexahedrons\nhexahydrate\nhexahydrates\nhexameter\nhexameters\nhexamethonium\nhexamethoniums\nhexamethylenetetramine\nhexamethylenetetramines\nhexamine\nhexamines\nhexane\nhexanes\nhexapla\nhexaplar\nhexaplas\nhexaploid\nhexaploidies\nhexaploids\nhexaploidy\nhexapod\nhexapodies\nhexapods\nhexapody\nhexarchies\nhexarchy\nhexed\nhexer\nhexerei\nhexereis\nhexers\nhexes\nhexing\nhexobarbital\nhexobarbitals\nhexokinase\nhexokinases\nhexone\nhexones\nhexosaminidase\nhexosaminidases\nhexosan\nhexosans\nhexose\nhexoses\nhexyl\nhexylresorcinol\nhexylresorcinols\nhexyls\nhey\nheyday\nheydays\nheydey\nheydeys\nhi\nhiatal\nhiatus\nhiatuses\nhibachi\nhibachis\nhibakusha\nhibernacula\nhibernaculum\nhibernal\nhibernate\nhibernated\nhibernates\nhibernating\nhibernation\nhibernations\nhibernator\nhibernators\nhibiscus\nhibiscuses\nhic\nhiccough\nhiccoughed\nhiccoughing\nhiccoughs\nhiccup\nhiccuped\nhiccuping\nhiccupped\nhiccupping\nhiccups\nhick\nhickey\nhickeys\nhickies\nhickish\nhickories\nhickory\nhicks\nhid\nhidable\nhidalgo\nhidalgos\nhidden\nhiddenite\nhiddenites\nhiddenly\nhiddenness\nhiddennesses\nhide\nhideaway\nhideaways\nhidebound\nhided\nhideless\nhideosities\nhideosity\nhideous\nhideously\nhideousness\nhideousnesses\nhideout\nhideouts\nhider\nhiders\nhides\nhiding\nhidings\nhidroses\nhidrosis\nhidrotic\nhidrotics\nhie\nhied\nhieing\nhiemal\nhierarch\nhierarchal\nhierarchic\nhierarchical\nhierarchically\nhierarchies\nhierarchize\nhierarchized\nhierarchizes\nhierarchizing\nhierarchs\nhierarchy\nhieratic\nhieratically\nhierodule\nhierodules\nhieroglyph\nhieroglyphic\nhieroglyphical\nhieroglyphically\nhieroglyphics\nhieroglyphs\nhierophant\nhierophantic\nhierophants\nhies\nhifalutin\nhiggle\nhiggled\nhiggler\nhigglers\nhiggles\nhiggling\nhigh\nhighball\nhighballed\nhighballing\nhighballs\nhighbinder\nhighbinders\nhighborn\nhighboy\nhighboys\nhighbred\nhighbrow\nhighbrowed\nhighbrowism\nhighbrowisms\nhighbrows\nhighbush\nhighchair\nhighchairs\nhigher\nhighest\nhighfalutin\nhighflier\nhighfliers\nhighflyer\nhighflyers\nhighhanded\nhighhandedly\nhighhandedness\nhighhandednesses\nhighjack\nhighjacked\nhighjacking\nhighjacks\nhighland\nhighlander\nhighlanders\nhighlands\nhighlife\nhighlifes\nhighlight\nhighlighted\nhighlighter\nhighlighters\nhighlighting\nhighlights\nhighly\nhighness\nhighnesses\nhighroad\nhighroads\nhighs\nhighspot\nhighspots\nhight\nhightail\nhightailed\nhightailing\nhightails\nhighted\nhighth\nhighths\nhighting\nhights\nhighway\nhighwayman\nhighwaymen\nhighways\nhijack\nhijacked\nhijacker\nhijackers\nhijacking\nhijackings\nhijacks\nhijinks\nhike\nhiked\nhiker\nhikers\nhikes\nhiking\nhila\nhilar\nhilarious\nhilariously\nhilariousness\nhilariousnesses\nhilarities\nhilarity\nhilding\nhildings\nhili\nhill\nhillbillies\nhillbilly\nhillcrest\nhillcrests\nhilled\nhiller\nhillers\nhillier\nhilliest\nhilling\nhillo\nhilloa\nhilloaed\nhilloaing\nhilloas\nhillock\nhillocks\nhillocky\nhilloed\nhilloes\nhilloing\nhillos\nhills\nhillside\nhillsides\nhilltop\nhilltops\nhilly\nhilt\nhilted\nhilting\nhiltless\nhilts\nhilum\nhilus\nhim\nhimatia\nhimation\nhimations\nhimself\nhin\nhind\nhindbrain\nhindbrains\nhinder\nhindered\nhinderer\nhinderers\nhindering\nhinders\nhindgut\nhindguts\nhindmost\nhindquarter\nhindquarters\nhindrance\nhindrances\nhinds\nhindsight\nhindsights\nhinge\nhinged\nhinger\nhingers\nhinges\nhinging\nhinnied\nhinnies\nhinny\nhinnying\nhins\nhint\nhinted\nhinter\nhinterland\nhinterlands\nhinters\nhinting\nhints\nhip\nhipbone\nhipbones\nhipless\nhiplike\nhipline\nhiplines\nhipness\nhipnesses\nhipparch\nhipparchs\nhipped\nhipper\nhippest\nhippie\nhippiedom\nhippiedoms\nhippieness\nhippienesses\nhippier\nhippies\nhippiest\nhippiness\nhippinesses\nhipping\nhippish\nhippo\nhippocampal\nhippocampi\nhippocampus\nhippocras\nhippocrases\nhippodrome\nhippodromes\nhippogriff\nhippogriffs\nhippopotami\nhippopotamus\nhippopotamuses\nhippos\nhippy\nhips\nhipshot\nhipster\nhipsterism\nhipsterisms\nhipsters\nhirable\nhiragana\nhiraganas\nhircine\nhire\nhireable\nhired\nhireling\nhirelings\nhirer\nhirers\nhires\nhiring\nhirple\nhirpled\nhirples\nhirpling\nhirsel\nhirseled\nhirseling\nhirselled\nhirselling\nhirsels\nhirsle\nhirsled\nhirsles\nhirsling\nhirsute\nhirsuteness\nhirsutenesses\nhirsutism\nhirsutisms\nhirudin\nhirudins\nhis\nhisn\nhispanidad\nhispanidads\nhispanism\nhispanisms\nhispid\nhiss\nhissed\nhisself\nhisser\nhissers\nhisses\nhissies\nhissing\nhissings\nhissy\nhist\nhistamin\nhistaminase\nhistaminases\nhistamine\nhistaminergic\nhistamines\nhistamins\nhisted\nhistidin\nhistidine\nhistidines\nhistidins\nhisting\nhistiocyte\nhistiocytes\nhistiocytic\nhistochemical\nhistochemically\nhistochemistries\nhistochemistry\nhistocompatibilities\nhistocompatibility\nhistogen\nhistogeneses\nhistogenesis\nhistogenetic\nhistogens\nhistogram\nhistograms\nhistoid\nhistologic\nhistological\nhistologically\nhistologies\nhistologist\nhistologists\nhistology\nhistolyses\nhistolysis\nhistone\nhistones\nhistopathologic\nhistopathological\nhistopathologically\nhistopathologies\nhistopathologist\nhistopathologists\nhistopathology\nhistophysiologic\nhistophysiological\nhistophysiologies\nhistophysiology\nhistoplasmoses\nhistoplasmosis\nhistorian\nhistorians\nhistoric\nhistorical\nhistorically\nhistoricalness\nhistoricalnesses\nhistoricism\nhistoricisms\nhistoricist\nhistoricists\nhistoricities\nhistoricity\nhistoricize\nhistoricized\nhistoricizes\nhistoricizing\nhistories\nhistoriographer\nhistoriographers\nhistoriographic\nhistoriographical\nhistoriographically\nhistoriographies\nhistoriography\nhistory\nhistrionic\nhistrionically\nhistrionics\nhists\nhit\nhitch\nhitched\nhitcher\nhitchers\nhitches\nhitchhike\nhitchhiked\nhitchhiker\nhitchhikers\nhitchhikes\nhitchhiking\nhitching\nhither\nhithermost\nhitherto\nhitherward\nhitless\nhits\nhitter\nhitters\nhitting\nhive\nhived\nhiveless\nhives\nhiving\nhizzoner\nhizzoners\nhm\nhmm\nho\nhoactzin\nhoactzines\nhoactzins\nhoagie\nhoagies\nhoagy\nhoar\nhoard\nhoarded\nhoarder\nhoarders\nhoarding\nhoardings\nhoards\nhoarfrost\nhoarfrosts\nhoarier\nhoariest\nhoarily\nhoariness\nhoarinesses\nhoars\nhoarse\nhoarsely\nhoarsen\nhoarsened\nhoarseness\nhoarsenesses\nhoarsening\nhoarsens\nhoarser\nhoarsest\nhoary\nhoatzin\nhoatzines\nhoatzins\nhoax\nhoaxed\nhoaxer\nhoaxers\nhoaxes\nhoaxing\nhob\nhobbed\nhobbies\nhobbing\nhobbit\nhobbits\nhobble\nhobblebush\nhobblebushes\nhobbled\nhobbledehoy\nhobbledehoys\nhobbler\nhobblers\nhobbles\nhobbling\nhobby\nhobbyhorse\nhobbyhorses\nhobbyist\nhobbyists\nhobgoblin\nhobgoblins\nhoblike\nhobnail\nhobnailed\nhobnailing\nhobnails\nhobnob\nhobnobbed\nhobnobber\nhobnobbers\nhobnobbing\nhobnobs\nhobo\nhoboed\nhoboes\nhoboing\nhoboism\nhoboisms\nhobos\nhobs\nhock\nhocked\nhocker\nhockers\nhockey\nhockeys\nhocking\nhocks\nhockshop\nhockshops\nhocus\nhocused\nhocuses\nhocusing\nhocussed\nhocusses\nhocussing\nhod\nhodad\nhodaddies\nhodaddy\nhodads\nhodden\nhoddens\nhoddin\nhoddins\nhodgepodge\nhodgepodges\nhodoscope\nhodoscopes\nhods\nhoe\nhoecake\nhoecakes\nhoed\nhoedown\nhoedowns\nhoeing\nhoelike\nhoer\nhoers\nhoes\nhog\nhogan\nhogans\nhogback\nhogbacks\nhogfish\nhogfishes\nhogg\nhogged\nhogger\nhoggers\nhogget\nhoggets\nhogging\nhoggish\nhoggishly\nhoggishness\nhoggishnesses\nhoggs\nhoglike\nhogmanay\nhogmanays\nhogmane\nhogmanes\nhogmenay\nhogmenays\nhognose\nhognoses\nhognut\nhognuts\nhogs\nhogshead\nhogsheads\nhogtie\nhogtied\nhogtieing\nhogties\nhogtying\nhogwash\nhogwashes\nhogweed\nhogweeds\nhoick\nhoicked\nhoicking\nhoicks\nhoiden\nhoidened\nhoidening\nhoidens\nhoise\nhoised\nhoises\nhoising\nhoist\nhoisted\nhoister\nhoisters\nhoisting\nhoists\nhoke\nhoked\nhokes\nhokey\nhokeyness\nhokeynesses\nhokeypokey\nhokeypokeys\nhokier\nhokiest\nhokily\nhokiness\nhokinesses\nhoking\nhokku\nhokum\nhokums\nhokypokies\nhokypoky\nholandric\nholard\nholards\nhold\nholdable\nholdall\nholdalls\nholdback\nholdbacks\nholden\nholder\nholders\nholdfast\nholdfasts\nholding\nholdings\nholdout\nholdouts\nholdover\nholdovers\nholds\nholdup\nholdups\nhole\nholed\nholeless\nholes\nholey\nholibut\nholibuts\nholiday\nholidayed\nholidayer\nholidayers\nholidaying\nholidaymaker\nholidaymakers\nholidays\nholier\nholies\nholiest\nholily\nholiness\nholinesses\nholing\nholism\nholisms\nholist\nholistic\nholistically\nholists\nholk\nholked\nholking\nholks\nholla\nhollaed\nhollaing\nholland\nhollandaise\nhollandaises\nhollands\nhollas\nholler\nhollered\nhollering\nhollers\nhollies\nhollo\nholloa\nholloaed\nholloaing\nholloas\nholloed\nholloes\nholloing\nholloo\nhollooed\nhollooing\nholloos\nhollos\nhollow\nholloware\nhollowares\nhollowed\nhollower\nhollowest\nhollowing\nhollowly\nhollowness\nhollownesses\nhollows\nhollowware\nhollowwares\nholly\nhollyhock\nhollyhocks\nholm\nholmic\nholmium\nholmiums\nholms\nholoblastic\nholocaust\nholocausts\nholocrine\nholoenzyme\nholoenzymes\nhologamies\nhologamy\nhologram\nholograms\nholograph\nholographed\nholographer\nholographers\nholographic\nholographically\nholographies\nholographing\nholographs\nholography\nhologynies\nhologyny\nholohedral\nholometabolism\nholometabolisms\nholometabolous\nholophrastic\nholophytic\nholothurian\nholothurians\nholotype\nholotypes\nholotypic\nholozoic\nholp\nholpen\nhols\nholstein\nholsteins\nholster\nholstered\nholstering\nholsters\nholt\nholts\nholy\nholyday\nholydays\nholystone\nholystoned\nholystones\nholystoning\nholytide\nholytides\nhomage\nhomaged\nhomager\nhomagers\nhomages\nhomaging\nhombre\nhombres\nhomburg\nhomburgs\nhome\nhomebodies\nhomebody\nhomebound\nhomeboy\nhomeboys\nhomebred\nhomebreds\nhomebrew\nhomebrews\nhomebuilt\nhomecoming\nhomecomings\nhomed\nhomegirl\nhomegirls\nhomegrown\nhomeland\nhomelands\nhomeless\nhomelessness\nhomelessnesses\nhomelier\nhomeliest\nhomelike\nhomeliness\nhomelinesses\nhomely\nhomemade\nhomemaker\nhomemakers\nhomemaking\nhomemakings\nhomeobox\nhomeoboxes\nhomeomorphic\nhomeomorphism\nhomeomorphisms\nhomeopath\nhomeopathic\nhomeopathically\nhomeopathies\nhomeopaths\nhomeopathy\nhomeostases\nhomeostasis\nhomeostatic\nhomeotherm\nhomeothermic\nhomeothermies\nhomeotherms\nhomeothermy\nhomeotic\nhomeowner\nhomeowners\nhomeport\nhomeported\nhomeporting\nhomeports\nhomer\nhomered\nhomering\nhomeroom\nhomerooms\nhomers\nhomes\nhomeschool\nhomeschooled\nhomeschooler\nhomeschoolers\nhomeschooling\nhomeschoolings\nhomeschools\nhomesick\nhomesickness\nhomesicknesses\nhomesite\nhomesites\nhomespun\nhomespuns\nhomestay\nhomestays\nhomestead\nhomesteaded\nhomesteader\nhomesteaders\nhomesteading\nhomesteads\nhomestretch\nhomestretches\nhometown\nhometowns\nhomeward\nhomewards\nhomework\nhomeworks\nhomey\nhomeyness\nhomeynesses\nhomicidal\nhomicidally\nhomicide\nhomicides\nhomier\nhomiest\nhomiletic\nhomiletical\nhomiletics\nhomilies\nhomilist\nhomilists\nhomily\nhomines\nhominess\nhominesses\nhoming\nhominian\nhominians\nhominid\nhominids\nhominies\nhominine\nhominization\nhominizations\nhominize\nhominized\nhominizes\nhominizing\nhominoid\nhominoids\nhominy\nhommock\nhommocks\nhommos\nhommoses\nhomo\nhomocercal\nhomoerotic\nhomoeroticism\nhomoeroticisms\nhomogametic\nhomogamies\nhomogamous\nhomogamy\nhomogenate\nhomogenates\nhomogeneities\nhomogeneity\nhomogeneous\nhomogeneously\nhomogeneousness\nhomogeneousnesses\nhomogenies\nhomogenisation\nhomogenisations\nhomogenise\nhomogenised\nhomogenises\nhomogenising\nhomogenization\nhomogenizations\nhomogenize\nhomogenized\nhomogenizer\nhomogenizers\nhomogenizes\nhomogenizing\nhomogenous\nhomogeny\nhomogonies\nhomogony\nhomograft\nhomografts\nhomograph\nhomographic\nhomographs\nhomoiotherm\nhomoiothermic\nhomoiotherms\nhomoiousian\nhomoiousians\nhomolog\nhomologate\nhomologated\nhomologates\nhomologating\nhomologation\nhomologations\nhomological\nhomologically\nhomologies\nhomologize\nhomologized\nhomologizer\nhomologizers\nhomologizes\nhomologizing\nhomologous\nhomologs\nhomologue\nhomologues\nhomology\nhomolyses\nhomolysis\nhomolytic\nhomomorphic\nhomomorphism\nhomomorphisms\nhomonuclear\nhomonym\nhomonymic\nhomonymies\nhomonymous\nhomonymously\nhomonyms\nhomonymy\nhomoousian\nhomoousians\nhomophile\nhomophobe\nhomophobes\nhomophobia\nhomophobias\nhomophobic\nhomophone\nhomophones\nhomophonic\nhomophonies\nhomophonous\nhomophony\nhomoplasies\nhomoplastic\nhomoplasy\nhomopolar\nhomopolymer\nhomopolymeric\nhomopolymers\nhomopteran\nhomopterans\nhomopterous\nhomos\nhomoscedastic\nhomoscedasticities\nhomoscedasticity\nhomosex\nhomosexes\nhomosexual\nhomosexualities\nhomosexuality\nhomosexually\nhomosexuals\nhomosocial\nhomosocialities\nhomosociality\nhomospories\nhomosporous\nhomospory\nhomothallic\nhomothallism\nhomothallisms\nhomotransplant\nhomotransplantation\nhomotransplantations\nhomotransplants\nhomozygoses\nhomozygosis\nhomozygosities\nhomozygosity\nhomozygote\nhomozygotes\nhomozygous\nhomozygously\nhomunculi\nhomunculus\nhomy\nhon\nhonan\nhonans\nhoncho\nhonchoed\nhonchoing\nhonchos\nhonda\nhondas\nhondle\nhondled\nhondles\nhondling\nhone\nhoned\nhoner\nhoners\nhones\nhonest\nhonester\nhonestest\nhonesties\nhonestly\nhonesty\nhonewort\nhoneworts\nhoney\nhoneybee\nhoneybees\nhoneybun\nhoneybunch\nhoneybunches\nhoneybuns\nhoneycomb\nhoneycombed\nhoneycombing\nhoneycombs\nhoneycreeper\nhoneycreepers\nhoneydew\nhoneydews\nhoneyeater\nhoneyeaters\nhoneyed\nhoneyful\nhoneyguide\nhoneyguides\nhoneying\nhoneymoon\nhoneymooned\nhoneymooner\nhoneymooners\nhoneymooning\nhoneymoons\nhoneys\nhoneysuckle\nhoneysuckles\nhong\nhongs\nhonied\nhoning\nhonk\nhonked\nhonker\nhonkers\nhonkey\nhonkeys\nhonkie\nhonkies\nhonking\nhonks\nhonky\nhonor\nhonorabilities\nhonorability\nhonorable\nhonorableness\nhonorablenesses\nhonorably\nhonorand\nhonorands\nhonoraria\nhonoraries\nhonorarily\nhonorarium\nhonorariums\nhonorary\nhonored\nhonoree\nhonorees\nhonorer\nhonorers\nhonorific\nhonorifically\nhonorifics\nhonoring\nhonors\nhonour\nhonourable\nhonoured\nhonourer\nhonourers\nhonouring\nhonours\nhons\nhooch\nhooches\nhood\nhooded\nhoodedness\nhoodednesses\nhoodie\nhoodier\nhoodies\nhoodiest\nhooding\nhoodless\nhoodlike\nhoodlum\nhoodlumish\nhoodlumism\nhoodlumisms\nhoodlums\nhoodoo\nhoodooed\nhoodooing\nhoodooism\nhoodooisms\nhoodoos\nhoods\nhoodwink\nhoodwinked\nhoodwinker\nhoodwinkers\nhoodwinking\nhoodwinks\nhoody\nhooey\nhooeys\nhoof\nhoofbeat\nhoofbeats\nhoofed\nhoofer\nhoofers\nhoofing\nhoofless\nhooflike\nhoofprint\nhoofprints\nhoofs\nhook\nhooka\nhookah\nhookahs\nhookas\nhooked\nhooker\nhookers\nhookey\nhookeys\nhookier\nhookies\nhookiest\nhooking\nhookless\nhooklet\nhooklets\nhooklike\nhooknose\nhooknoses\nhooks\nhookup\nhookups\nhookworm\nhookworms\nhooky\nhoolie\nhooligan\nhooliganism\nhooliganisms\nhooligans\nhooly\nhoop\nhooped\nhooper\nhoopers\nhooping\nhoopla\nhooplas\nhoopless\nhooplike\nhoopoe\nhoopoes\nhoopoo\nhoopoos\nhoops\nhoopskirt\nhoopskirts\nhoopster\nhoopsters\nhoorah\nhoorahed\nhoorahing\nhoorahs\nhooray\nhoorayed\nhooraying\nhoorays\nhoosegow\nhoosegows\nhoosgow\nhoosgows\nhoot\nhootch\nhootches\nhooted\nhootenannies\nhootenanny\nhooter\nhooters\nhootier\nhootiest\nhooting\nhoots\nhooty\nhooved\nhooves\nhop\nhope\nhoped\nhopeful\nhopefully\nhopefulness\nhopefulnesses\nhopefuls\nhopeless\nhopelessly\nhopelessness\nhopelessnesses\nhoper\nhopers\nhopes\nhophead\nhopheads\nhoping\nhoplite\nhoplites\nhoplitic\nhopped\nhopper\nhoppers\nhoppier\nhoppiest\nhopping\nhoppings\nhopple\nhoppled\nhopples\nhoppling\nhoppy\nhops\nhopsack\nhopsacking\nhopsackings\nhopsacks\nhopscotch\nhopscotched\nhopscotches\nhopscotching\nhoptoad\nhoptoads\nhora\nhorah\nhorahs\nhoral\nhorary\nhoras\nhorde\nhorded\nhordein\nhordeins\nhordes\nhording\nhorehound\nhorehounds\nhorizon\nhorizonal\nhorizonless\nhorizons\nhorizontal\nhorizontalities\nhorizontality\nhorizontally\nhorizontals\nhormogonia\nhormogonium\nhormonal\nhormonally\nhormone\nhormonelike\nhormones\nhormonic\nhorn\nhornbeam\nhornbeams\nhornbill\nhornbills\nhornblende\nhornblendes\nhornblendic\nhornbook\nhornbooks\nhorned\nhornedness\nhornednesses\nhornet\nhornets\nhornfels\nhornier\nhorniest\nhornily\nhorniness\nhorninesses\nhorning\nhornist\nhornists\nhornito\nhornitos\nhornless\nhornlessness\nhornlessnesses\nhornlike\nhornpipe\nhornpipes\nhornpout\nhornpouts\nhorns\nhornstone\nhornstones\nhornswoggle\nhornswoggled\nhornswoggles\nhornswoggling\nhorntail\nhorntails\nhornworm\nhornworms\nhornwort\nhornworts\nhorny\nhorologe\nhorologes\nhorological\nhorologies\nhorologist\nhorologists\nhorology\nhoroscope\nhoroscopes\nhorrendous\nhorrendously\nhorrent\nhorrible\nhorribleness\nhorriblenesses\nhorribles\nhorribly\nhorrid\nhorridly\nhorridness\nhorridnesses\nhorrific\nhorrifically\nhorrified\nhorrifies\nhorrify\nhorrifying\nhorrifyingly\nhorror\nhorrors\nhorse\nhorseback\nhorsebacks\nhorsebean\nhorsebeans\nhorsecar\nhorsecars\nhorsed\nhorsefeathers\nhorseflesh\nhorsefleshes\nhorseflies\nhorsefly\nhorsehair\nhorsehairs\nhorsehide\nhorsehides\nhorselaugh\nhorselaughs\nhorseless\nhorselike\nhorseman\nhorsemanship\nhorsemanships\nhorsemen\nhorsemint\nhorsemints\nhorseplay\nhorseplayer\nhorseplayers\nhorseplays\nhorsepower\nhorsepowers\nhorsepox\nhorsepoxes\nhorserace\nhorseraces\nhorseradish\nhorseradishes\nhorses\nhorseshit\nhorseshits\nhorseshod\nhorseshoe\nhorseshoed\nhorseshoeing\nhorseshoer\nhorseshoers\nhorseshoes\nhorsetail\nhorsetails\nhorseweed\nhorseweeds\nhorsewhip\nhorsewhipped\nhorsewhipper\nhorsewhippers\nhorsewhipping\nhorsewhips\nhorsewoman\nhorsewomen\nhorsey\nhorsier\nhorsiest\nhorsily\nhorsiness\nhorsinesses\nhorsing\nhorst\nhorste\nhorstes\nhorsts\nhorsy\nhortative\nhortatively\nhortatory\nhorticultural\nhorticulturally\nhorticulture\nhorticultures\nhorticulturist\nhorticulturists\nhosanna\nhosannaed\nhosannah\nhosannahs\nhosannaing\nhosannas\nhose\nhosed\nhosel\nhosels\nhosen\nhosepipe\nhosepipes\nhoses\nhosier\nhosieries\nhosiers\nhosiery\nhosing\nhospice\nhospices\nhospitable\nhospitably\nhospital\nhospitalise\nhospitalised\nhospitalises\nhospitalising\nhospitalities\nhospitality\nhospitalization\nhospitalizations\nhospitalize\nhospitalized\nhospitalizes\nhospitalizing\nhospitals\nhospitia\nhospitium\nhospodar\nhospodars\nhost\nhosta\nhostage\nhostages\nhostas\nhosted\nhostel\nhosteled\nhosteler\nhostelers\nhosteling\nhostelled\nhosteller\nhostellers\nhostelling\nhostelries\nhostelry\nhostels\nhostess\nhostessed\nhostesses\nhostessing\nhostile\nhostilely\nhostiles\nhostilities\nhostility\nhosting\nhostler\nhostlers\nhostly\nhosts\nhot\nhotbed\nhotbeds\nhotblood\nhotbloods\nhotbox\nhotboxes\nhotcake\nhotcakes\nhotch\nhotched\nhotches\nhotching\nhotchpot\nhotchpotch\nhotchpotches\nhotchpots\nhotdog\nhotdogged\nhotdogger\nhotdoggers\nhotdogging\nhotdogs\nhotel\nhoteldom\nhoteldoms\nhotelier\nhoteliers\nhotelman\nhotelmen\nhotels\nhotfoot\nhotfooted\nhotfooting\nhotfoots\nhothead\nhotheaded\nhotheadedly\nhotheadedness\nhotheadednesses\nhotheads\nhothouse\nhothouses\nhotline\nhotlines\nhotly\nhotness\nhotnesses\nhotpress\nhotpressed\nhotpresses\nhotpressing\nhotrod\nhotrods\nhots\nhotshot\nhotshots\nhotspot\nhotspots\nhotspur\nhotspurs\nhotted\nhotter\nhottest\nhotting\nhottish\nhoudah\nhoudahs\nhound\nhounded\nhounder\nhounders\nhounding\nhounds\nhour\nhourglass\nhourglasses\nhouri\nhouris\nhourly\nhours\nhouse\nhouseboat\nhouseboater\nhouseboaters\nhouseboats\nhousebound\nhouseboy\nhouseboys\nhousebreak\nhousebreaker\nhousebreakers\nhousebreaking\nhousebreakings\nhousebreaks\nhousebroke\nhousebroken\nhousecarl\nhousecarls\nhouseclean\nhousecleaned\nhousecleaning\nhousecleanings\nhousecleans\nhousecoat\nhousecoats\nhoused\nhousedress\nhousedresses\nhousefather\nhousefathers\nhouseflies\nhousefly\nhousefront\nhousefronts\nhouseful\nhousefuls\nhouseguest\nhouseguests\nhousehold\nhouseholder\nhouseholders\nhouseholds\nhousehusband\nhousehusbands\nhousekeep\nhousekeeper\nhousekeepers\nhousekeeping\nhousekeepings\nhousekeeps\nhousekept\nhousel\nhouseled\nhouseleek\nhouseleeks\nhouseless\nhouselessness\nhouselessnesses\nhouselights\nhouseling\nhouselled\nhouselling\nhousels\nhousemaid\nhousemaids\nhouseman\nhousemaster\nhousemasters\nhousemate\nhousemates\nhousemen\nhousemother\nhousemothers\nhousepainter\nhousepainters\nhouseparent\nhouseparents\nhouseperson\nhousepersons\nhouseplant\nhouseplants\nhouser\nhouseroom\nhouserooms\nhousers\nhouses\nhousesat\nhousesit\nhousesits\nhousesitting\nhousetop\nhousetops\nhousetrain\nhousetrained\nhousetraining\nhousetrains\nhousewares\nhousewarming\nhousewarmings\nhousewife\nhousewifeliness\nhousewifelinesses\nhousewifely\nhousewiferies\nhousewifery\nhousewifey\nhousewives\nhousework\nhouseworks\nhousing\nhousings\nhove\nhovel\nhoveled\nhoveling\nhovelled\nhovelling\nhovels\nhover\nhovercraft\nhovercrafts\nhovered\nhoverer\nhoverers\nhovering\nhovers\nhow\nhowbeit\nhowdah\nhowdahs\nhowdie\nhowdied\nhowdies\nhowdy\nhowdying\nhowe\nhowes\nhowever\nhowf\nhowff\nhowffs\nhowfs\nhowitzer\nhowitzers\nhowk\nhowked\nhowking\nhowks\nhowl\nhowled\nhowler\nhowlers\nhowlet\nhowlets\nhowling\nhowlingly\nhowls\nhows\nhowsoever\nhoy\nhoya\nhoyas\nhoyden\nhoydened\nhoydening\nhoydenish\nhoydens\nhoyle\nhoyles\nhoys\nhuarache\nhuaraches\nhuaracho\nhuarachos\nhub\nhubbies\nhubbly\nhubbub\nhubbubs\nhubby\nhubcap\nhubcaps\nhubris\nhubrises\nhubristic\nhubs\nhuck\nhuckaback\nhuckabacks\nhuckle\nhuckleberries\nhuckleberry\nhuckles\nhucks\nhuckster\nhuckstered\nhuckstering\nhucksterism\nhucksterisms\nhucksters\nhuddle\nhuddled\nhuddler\nhuddlers\nhuddles\nhuddling\nhue\nhued\nhueless\nhues\nhuff\nhuffed\nhuffier\nhuffiest\nhuffily\nhuffiness\nhuffinesses\nhuffing\nhuffish\nhuffs\nhuffy\nhug\nhuge\nhugely\nhugeness\nhugenesses\nhugeous\nhugeously\nhuger\nhugest\nhuggable\nhugged\nhugger\nhuggers\nhugging\nhugs\nhuh\nhuic\nhuipil\nhuipiles\nhuipils\nhuisache\nhuisaches\nhula\nhulas\nhulk\nhulked\nhulkier\nhulkiest\nhulking\nhulks\nhulky\nhull\nhullabaloo\nhullabaloos\nhulled\nhuller\nhullers\nhulling\nhullo\nhulloa\nhulloaed\nhulloaing\nhulloas\nhulloed\nhulloes\nhulloing\nhullos\nhulls\nhum\nhuman\nhumane\nhumanely\nhumaneness\nhumanenesses\nhumaner\nhumanest\nhumanise\nhumanised\nhumanises\nhumanising\nhumanism\nhumanisms\nhumanist\nhumanistic\nhumanistically\nhumanists\nhumanitarian\nhumanitarianism\nhumanitarianisms\nhumanitarians\nhumanities\nhumanity\nhumanization\nhumanizations\nhumanize\nhumanized\nhumanizer\nhumanizers\nhumanizes\nhumanizing\nhumankind\nhumanlike\nhumanly\nhumanness\nhumannesses\nhumanoid\nhumanoids\nhumans\nhumate\nhumates\nhumble\nhumbled\nhumbleness\nhumblenesses\nhumbler\nhumblers\nhumbles\nhumblest\nhumbling\nhumblingly\nhumbly\nhumbug\nhumbugged\nhumbuggeries\nhumbuggery\nhumbugging\nhumbugs\nhumdinger\nhumdingers\nhumdrum\nhumdrums\nhumectant\nhumectants\nhumeral\nhumerals\nhumeri\nhumerus\nhumic\nhumid\nhumidification\nhumidifications\nhumidified\nhumidifier\nhumidifiers\nhumidifies\nhumidify\nhumidifying\nhumidistat\nhumidistats\nhumidities\nhumidity\nhumidly\nhumidor\nhumidors\nhumification\nhumifications\nhumified\nhumiliate\nhumiliated\nhumiliates\nhumiliating\nhumiliatingly\nhumiliation\nhumiliations\nhumilities\nhumility\nhummable\nhummed\nhummer\nhummers\nhumming\nhummingbird\nhummingbirds\nhummock\nhummocked\nhummocking\nhummocks\nhummocky\nhummus\nhummuses\nhumongous\nhumor\nhumoral\nhumored\nhumoresque\nhumoresques\nhumorful\nhumoring\nhumorist\nhumoristic\nhumorists\nhumorless\nhumorlessly\nhumorlessness\nhumorlessnesses\nhumorous\nhumorously\nhumorousness\nhumorousnesses\nhumors\nhumour\nhumoured\nhumouring\nhumours\nhump\nhumpback\nhumpbacked\nhumpbacks\nhumped\nhumph\nhumphed\nhumphing\nhumphs\nhumpier\nhumpiest\nhumping\nhumpless\nhumps\nhumpy\nhums\nhumungous\nhumus\nhumuses\nhumvee\nhumvees\nhun\nhunch\nhunchback\nhunchbacked\nhunchbacks\nhunched\nhunches\nhunching\nhundred\nhundredfold\nhundreds\nhundredth\nhundredths\nhundredweight\nhundredweights\nhung\nhunger\nhungered\nhungering\nhungers\nhungover\nhungrier\nhungriest\nhungrily\nhungriness\nhungrinesses\nhungry\nhunh\nhunk\nhunker\nhunkered\nhunkering\nhunkers\nhunkier\nhunkies\nhunkiest\nhunks\nhunky\nhunnish\nhuns\nhunt\nhuntable\nhunted\nhuntedly\nhunter\nhunters\nhunting\nhuntings\nhuntress\nhuntresses\nhunts\nhuntsman\nhuntsmen\nhup\nhurdies\nhurdle\nhurdled\nhurdler\nhurdlers\nhurdles\nhurdling\nhurds\nhurl\nhurled\nhurler\nhurlers\nhurley\nhurleys\nhurlies\nhurling\nhurlings\nhurls\nhurly\nhurrah\nhurrahed\nhurrahing\nhurrahs\nhurray\nhurrayed\nhurraying\nhurrays\nhurricane\nhurricanes\nhurried\nhurriedly\nhurriedness\nhurriednesses\nhurrier\nhurriers\nhurries\nhurry\nhurrying\nhurst\nhursts\nhurt\nhurter\nhurters\nhurtful\nhurtfully\nhurtfulness\nhurtfulnesses\nhurting\nhurtle\nhurtled\nhurtles\nhurtless\nhurtling\nhurts\nhusband\nhusbanded\nhusbander\nhusbanders\nhusbanding\nhusbandly\nhusbandman\nhusbandmen\nhusbandries\nhusbandry\nhusbands\nhush\nhushaby\nhushed\nhushedly\nhushes\nhushful\nhushing\nhusk\nhusked\nhusker\nhuskers\nhuskie\nhuskier\nhuskies\nhuskiest\nhuskily\nhuskiness\nhuskinesses\nhusking\nhuskings\nhusklike\nhusks\nhusky\nhussar\nhussars\nhussies\nhussy\nhustings\nhustle\nhustled\nhustler\nhustlers\nhustles\nhustling\nhuswife\nhuswifes\nhuswives\nhut\nhutch\nhutched\nhutches\nhutching\nhutlike\nhutment\nhutments\nhuts\nhutted\nhutting\nhutzpa\nhutzpah\nhutzpahs\nhutzpas\nhuzza\nhuzzaed\nhuzzah\nhuzzahed\nhuzzahing\nhuzzahs\nhuzzaing\nhuzzas\nhwan\nhyacinth\nhyacinthine\nhyacinths\nhyaena\nhyaenas\nhyaenic\nhyalin\nhyaline\nhyalines\nhyalins\nhyalite\nhyalites\nhyalogen\nhyalogens\nhyaloid\nhyaloids\nhyaloplasm\nhyaloplasms\nhyaluronidase\nhyaluronidases\nhybrid\nhybridism\nhybridisms\nhybridities\nhybridity\nhybridization\nhybridizations\nhybridize\nhybridized\nhybridizer\nhybridizers\nhybridizes\nhybridizing\nhybridoma\nhybridomas\nhybrids\nhybris\nhybrises\nhydathode\nhydathodes\nhydatid\nhydatids\nhydra\nhydracid\nhydracids\nhydrae\nhydragog\nhydragogs\nhydralazine\nhydralazines\nhydrangea\nhydrangeas\nhydrant\nhydranth\nhydranths\nhydrants\nhydras\nhydrase\nhydrases\nhydrate\nhydrated\nhydrates\nhydrating\nhydration\nhydrations\nhydrator\nhydrators\nhydraulic\nhydraulically\nhydraulics\nhydrazide\nhydrazides\nhydrazine\nhydrazines\nhydria\nhydriae\nhydric\nhydrid\nhydride\nhydrides\nhydrids\nhydro\nhydrobiological\nhydrobiologies\nhydrobiologist\nhydrobiologists\nhydrobiology\nhydrocarbon\nhydrocarbons\nhydrocele\nhydroceles\nhydrocephalic\nhydrocephalics\nhydrocephalies\nhydrocephalus\nhydrocephaluses\nhydrocephaly\nhydrochloride\nhydrochlorides\nhydrochlorothiazide\nhydrochlorothiazides\nhydrocolloid\nhydrocolloidal\nhydrocolloids\nhydrocortisone\nhydrocortisones\nhydrocrack\nhydrocracked\nhydrocracker\nhydrocrackers\nhydrocracking\nhydrocrackings\nhydrocracks\nhydrodynamic\nhydrodynamical\nhydrodynamically\nhydrodynamicist\nhydrodynamicists\nhydrodynamics\nhydroelectric\nhydroelectrically\nhydroelectricities\nhydroelectricity\nhydrofoil\nhydrofoils\nhydrogel\nhydrogels\nhydrogen\nhydrogenase\nhydrogenases\nhydrogenate\nhydrogenated\nhydrogenates\nhydrogenating\nhydrogenation\nhydrogenations\nhydrogenous\nhydrogens\nhydrographer\nhydrographers\nhydrographic\nhydrographies\nhydrography\nhydroid\nhydroids\nhydrokinetic\nhydrolase\nhydrolases\nhydrologic\nhydrological\nhydrologically\nhydrologies\nhydrologist\nhydrologists\nhydrology\nhydrolysate\nhydrolysates\nhydrolyses\nhydrolysis\nhydrolytic\nhydrolytically\nhydrolyzable\nhydrolyzate\nhydrolyzates\nhydrolyze\nhydrolyzed\nhydrolyzes\nhydrolyzing\nhydromagnetic\nhydromancies\nhydromancy\nhydromechanical\nhydromechanics\nhydromedusa\nhydromedusae\nhydromel\nhydromels\nhydrometallurgical\nhydrometallurgies\nhydrometallurgist\nhydrometallurgists\nhydrometallurgy\nhydrometeor\nhydrometeorological\nhydrometeorologies\nhydrometeorologist\nhydrometeorologists\nhydrometeorology\nhydrometeors\nhydrometer\nhydrometers\nhydrometric\nhydromorphic\nhydronic\nhydronically\nhydronium\nhydroniums\nhydropathic\nhydropathies\nhydropathy\nhydroperoxide\nhydroperoxides\nhydrophane\nhydrophanes\nhydrophilic\nhydrophilicities\nhydrophilicity\nhydrophobia\nhydrophobias\nhydrophobic\nhydrophobicities\nhydrophobicity\nhydrophone\nhydrophones\nhydrophyte\nhydrophytes\nhydrophytic\nhydropic\nhydroplane\nhydroplaned\nhydroplanes\nhydroplaning\nhydroponic\nhydroponically\nhydroponics\nhydropower\nhydropowers\nhydrops\nhydropses\nhydropsies\nhydropsy\nhydroquinone\nhydroquinones\nhydros\nhydrosere\nhydroseres\nhydroski\nhydroskis\nhydrosol\nhydrosolic\nhydrosols\nhydrospace\nhydrospaces\nhydrosphere\nhydrospheres\nhydrospheric\nhydrostatic\nhydrostatically\nhydrostatics\nhydrotherapies\nhydrotherapy\nhydrothermal\nhydrothermally\nhydrothoraces\nhydrothorax\nhydrothoraxes\nhydrotropic\nhydrotropism\nhydrotropisms\nhydrous\nhydroxide\nhydroxides\nhydroxy\nhydroxyapatite\nhydroxyapatites\nhydroxyl\nhydroxylamine\nhydroxylamines\nhydroxylapatite\nhydroxylapatites\nhydroxylase\nhydroxylases\nhydroxylate\nhydroxylated\nhydroxylates\nhydroxylating\nhydroxylation\nhydroxylations\nhydroxylic\nhydroxyls\nhydroxyproline\nhydroxyprolines\nhydroxytryptamine\nhydroxytryptamines\nhydroxyurea\nhydroxyureas\nhydroxyzine\nhydroxyzines\nhydrozoan\nhydrozoans\nhyena\nhyenas\nhyenic\nhyenine\nhyenoid\nhyetal\nhygeist\nhygeists\nhygieist\nhygieists\nhygiene\nhygienes\nhygienic\nhygienically\nhygienics\nhygienist\nhygienists\nhygrograph\nhygrographs\nhygrometer\nhygrometers\nhygrometric\nhygrophilous\nhygrophyte\nhygrophytes\nhygrophytic\nhygroscopic\nhygroscopicities\nhygroscopicity\nhying\nhyla\nhylas\nhylozoic\nhylozoism\nhylozoisms\nhylozoist\nhylozoistic\nhylozoists\nhymen\nhymenal\nhymeneal\nhymeneally\nhymeneals\nhymenia\nhymenial\nhymenium\nhymeniums\nhymenoptera\nhymenopteran\nhymenopterans\nhymenopteron\nhymenopterons\nhymenopterous\nhymens\nhymn\nhymnal\nhymnals\nhymnaries\nhymnary\nhymnbook\nhymnbooks\nhymned\nhymning\nhymnist\nhymnists\nhymnless\nhymnlike\nhymnodies\nhymnody\nhymnologies\nhymnology\nhymns\nhyoid\nhyoidal\nhyoidean\nhyoids\nhyoscine\nhyoscines\nhyoscyamine\nhyoscyamines\nhyp\nhypabyssal\nhypabyssally\nhypaethral\nhypallage\nhypallages\nhypanthia\nhypanthium\nhype\nhyped\nhyper\nhyperacid\nhyperacidities\nhyperacidity\nhyperactive\nhyperactives\nhyperactivities\nhyperactivity\nhyperacuities\nhyperacuity\nhyperacute\nhyperaesthesia\nhyperaesthesias\nhyperaesthetic\nhyperaggressive\nhyperalert\nhyperalimentation\nhyperalimentations\nhyperarid\nhyperarousal\nhyperarousals\nhyperaware\nhyperawareness\nhyperawarenesses\nhyperbaric\nhyperbarically\nhyperbola\nhyperbolae\nhyperbolas\nhyperbole\nhyperboles\nhyperbolic\nhyperbolical\nhyperbolically\nhyperbolist\nhyperbolists\nhyperbolize\nhyperbolized\nhyperbolizes\nhyperbolizing\nhyperboloid\nhyperboloidal\nhyperboloids\nhyperborean\nhyperboreans\nhypercalcemia\nhypercalcemias\nhypercalcemic\nhypercapnia\nhypercapnias\nhypercapnic\nhypercatabolism\nhypercatabolisms\nhypercatalectic\nhypercatalexes\nhypercatalexis\nhypercautious\nhypercharge\nhypercharged\nhypercharges\nhypercholesterolemia\nhypercholesterolemias\nhypercholesterolemic\nhypercivilized\nhypercoagulabilities\nhypercoagulability\nhypercoagulable\nhypercompetitive\nhypercomplex\nhyperconcentration\nhyperconcentrations\nhyperconscious\nhyperconsciousness\nhyperconsciousnesses\nhypercorrect\nhypercorrection\nhypercorrections\nhypercorrectly\nhypercorrectness\nhypercorrectnesses\nhypercritic\nhypercritical\nhypercritically\nhypercriticism\nhypercriticisms\nhypercritics\nhypercube\nhypercubes\nhyperdevelopment\nhyperdevelopments\nhyperefficient\nhyperemia\nhyperemias\nhyperemic\nhyperemotional\nhyperemotionalities\nhyperemotionality\nhyperendemic\nhyperenergetic\nhyperesthesia\nhyperesthesias\nhyperesthetic\nhypereutectic\nhypereutectoid\nhyperexcitabilities\nhyperexcitability\nhyperexcitable\nhyperexcited\nhyperexcitement\nhyperexcitements\nhyperexcretion\nhyperexcretions\nhyperextend\nhyperextended\nhyperextending\nhyperextends\nhyperextension\nhyperextensions\nhyperfastidious\nhyperfine\nhyperfunction\nhyperfunctional\nhyperfunctioning\nhyperfunctions\nhypergamies\nhypergamy\nhyperglycemia\nhyperglycemias\nhyperglycemic\nhypergol\nhypergolic\nhypergolically\nhypergols\nhyperhidroses\nhyperhidrosis\nhyperimmune\nhyperimmunization\nhyperimmunizations\nhyperimmunize\nhyperimmunized\nhyperimmunizes\nhyperimmunizing\nhyperinflated\nhyperinflation\nhyperinflationary\nhyperinflations\nhyperinnervation\nhyperinnervations\nhyperinsulinism\nhyperinsulinisms\nhyperintellectual\nhyperintelligent\nhyperintense\nhyperinvolution\nhyperinvolutions\nhyperirritabilities\nhyperirritability\nhyperirritable\nhyperkeratoses\nhyperkeratosis\nhyperkeratotic\nhyperkineses\nhyperkinesia\nhyperkinesias\nhyperkinesis\nhyperkinetic\nhyperlink\nhyperlinked\nhyperlinking\nhyperlinks\nhyperlipemia\nhyperlipemias\nhyperlipemic\nhyperlipidemia\nhyperlipidemias\nhypermania\nhypermanias\nhypermanic\nhypermarket\nhypermarkets\nhypermasculine\nhypermedia\nhypermedias\nhypermetabolic\nhypermetabolism\nhypermetabolisms\nhypermeter\nhypermeters\nhypermetric\nhypermetrical\nhypermetropia\nhypermetropias\nhypermetropic\nhypermnesia\nhypermnesias\nhypermnesic\nhypermobilities\nhypermobility\nhypermodern\nhypermodernist\nhypermodernists\nhypermutabilities\nhypermutability\nhypermutable\nhypernationalistic\nhyperon\nhyperons\nhyperope\nhyperopes\nhyperopia\nhyperopias\nhyperopic\nhyperostoses\nhyperostosis\nhyperostotic\nhyperparasite\nhyperparasites\nhyperparasitic\nhyperparasitism\nhyperparasitisms\nhyperparathyroidism\nhyperparathyroidisms\nhyperphagia\nhyperphagias\nhyperphagic\nhyperphysical\nhyperpigmentation\nhyperpigmentations\nhyperpigmented\nhyperpituitarism\nhyperpituitarisms\nhyperpituitary\nhyperplane\nhyperplanes\nhyperplasia\nhyperplasias\nhyperplastic\nhyperploid\nhyperploidies\nhyperploids\nhyperploidy\nhyperpnea\nhyperpneas\nhyperpneic\nhyperpolarization\nhyperpolarizations\nhyperpolarize\nhyperpolarized\nhyperpolarizes\nhyperpolarizing\nhyperproducer\nhyperproducers\nhyperproduction\nhyperproductions\nhyperpure\nhyperpyrexia\nhyperpyrexias\nhyperrational\nhyperrationalities\nhyperrationality\nhyperreactive\nhyperreactivities\nhyperreactivity\nhyperreactor\nhyperreactors\nhyperrealism\nhyperrealisms\nhyperrealist\nhyperrealistic\nhyperresponsive\nhyperromantic\nhypersaline\nhypersalinities\nhypersalinity\nhypersalivation\nhypersalivations\nhypersecretion\nhypersecretions\nhypersensitive\nhypersensitiveness\nhypersensitivenesses\nhypersensitivities\nhypersensitivity\nhypersensitization\nhypersensitizations\nhypersensitize\nhypersensitized\nhypersensitizes\nhypersensitizing\nhypersexual\nhypersexualities\nhypersexuality\nhypersomnolence\nhypersomnolences\nhypersonic\nhypersonically\nhyperspace\nhyperspaces\nhyperstatic\nhypersthene\nhypersthenes\nhypersthenic\nhyperstimulate\nhyperstimulated\nhyperstimulates\nhyperstimulating\nhyperstimulation\nhyperstimulations\nhypersurface\nhypersurfaces\nhypersusceptibilities\nhypersusceptibility\nhypersusceptible\nhypertense\nhypertension\nhypertensions\nhypertensive\nhypertensives\nhypertext\nhypertexts\nhyperthermia\nhyperthermias\nhyperthermic\nhyperthyroid\nhyperthyroidism\nhyperthyroidisms\nhypertonia\nhypertonias\nhypertonic\nhypertonicities\nhypertonicity\nhypertrophic\nhypertrophied\nhypertrophies\nhypertrophy\nhypertrophying\nhypertypical\nhyperurbanism\nhyperurbanisms\nhyperuricemia\nhyperuricemias\nhypervelocities\nhypervelocity\nhyperventilate\nhyperventilated\nhyperventilates\nhyperventilating\nhyperventilation\nhyperventilations\nhypervigilance\nhypervigilances\nhypervigilant\nhypervirulent\nhyperviscosities\nhyperviscosity\nhypervitaminoses\nhypervitaminosis\nhypes\nhypha\nhyphae\nhyphal\nhyphemia\nhyphemias\nhyphen\nhyphenate\nhyphenated\nhyphenates\nhyphenating\nhyphenation\nhyphenations\nhyphened\nhyphening\nhyphenless\nhyphens\nhyping\nhypnagogic\nhypnic\nhypnogogic\nhypnoid\nhypnoidal\nhypnopompic\nhypnoses\nhypnosis\nhypnotherapies\nhypnotherapist\nhypnotherapists\nhypnotherapy\nhypnotic\nhypnotically\nhypnotics\nhypnotism\nhypnotisms\nhypnotist\nhypnotists\nhypnotizabilities\nhypnotizability\nhypnotizable\nhypnotize\nhypnotized\nhypnotizes\nhypnotizing\nhypo\nhypoacid\nhypoallergenic\nhypoblast\nhypoblasts\nhypocalcemia\nhypocalcemias\nhypocalcemic\nhypocaust\nhypocausts\nhypocenter\nhypocenters\nhypocentral\nhypochlorite\nhypochlorites\nhypochondria\nhypochondriac\nhypochondriacal\nhypochondriacally\nhypochondriacs\nhypochondrias\nhypochondriases\nhypochondriasis\nhypocorism\nhypocorisms\nhypocoristic\nhypocoristical\nhypocoristically\nhypocotyl\nhypocotyls\nhypocrisies\nhypocrisy\nhypocrite\nhypocrites\nhypocritical\nhypocritically\nhypocycloid\nhypocycloids\nhypoderm\nhypodermal\nhypodermic\nhypodermically\nhypodermics\nhypodermis\nhypodermises\nhypoderms\nhypodiploid\nhypodiploidies\nhypodiploidy\nhypoed\nhypoeutectoid\nhypogastric\nhypogea\nhypogeal\nhypogean\nhypogene\nhypogeous\nhypogeum\nhypoglossal\nhypoglossals\nhypoglycemia\nhypoglycemias\nhypoglycemic\nhypoglycemics\nhypogynies\nhypogynous\nhypogyny\nhypoing\nhypokalemia\nhypokalemias\nhypokalemic\nhypolimnia\nhypolimnion\nhypolimnions\nhypomagnesemia\nhypomagnesemias\nhypomania\nhypomanias\nhypomanic\nhypomorph\nhypomorphic\nhypomorphs\nhyponea\nhyponeas\nhyponoia\nhyponoias\nhypoparathyroidism\nhypoparathyroidisms\nhypopharynges\nhypopharynx\nhypopharynxes\nhypophyseal\nhypophysectomies\nhypophysectomize\nhypophysectomized\nhypophysectomizes\nhypophysectomizing\nhypophysectomy\nhypophyses\nhypophysial\nhypophysis\nhypopituitarism\nhypopituitarisms\nhypopituitary\nhypoplasia\nhypoplasias\nhypoplastic\nhypoploid\nhypoploids\nhypopnea\nhypopneas\nhypopyon\nhypopyons\nhypos\nhyposensitization\nhyposensitizations\nhyposensitize\nhyposensitized\nhyposensitizes\nhyposensitizing\nhypospadias\nhypospadiases\nhypostases\nhypostasis\nhypostatic\nhypostatically\nhypostatization\nhypostatizations\nhypostatize\nhypostatized\nhypostatizes\nhypostatizing\nhypostome\nhypostomes\nhypostyle\nhypostyles\nhypotactic\nhypotaxes\nhypotaxis\nhypotension\nhypotensions\nhypotensive\nhypotensives\nhypotenuse\nhypotenuses\nhypothalami\nhypothalamic\nhypothalamus\nhypothec\nhypothecate\nhypothecated\nhypothecates\nhypothecating\nhypothecation\nhypothecations\nhypothecator\nhypothecators\nhypothecs\nhypothenuse\nhypothenuses\nhypothermal\nhypothermia\nhypothermias\nhypothermic\nhypotheses\nhypothesis\nhypothesize\nhypothesized\nhypothesizes\nhypothesizing\nhypothetical\nhypothetically\nhypothyroid\nhypothyroidism\nhypothyroidisms\nhypotonia\nhypotonias\nhypotonic\nhypotonicities\nhypotonicity\nhypoxanthine\nhypoxanthines\nhypoxemia\nhypoxemias\nhypoxemic\nhypoxia\nhypoxias\nhypoxic\nhyps\nhypsometer\nhypsometers\nhypsometric\nhyraces\nhyracoid\nhyracoids\nhyrax\nhyraxes\nhyson\nhysons\nhyssop\nhyssops\nhysterectomies\nhysterectomized\nhysterectomy\nhystereses\nhysteresis\nhysteretic\nhysteria\nhysterias\nhysteric\nhysterical\nhysterically\nhysterics\nhysteroid\nhysterotomies\nhysterotomy\nhyte\niamb\niambi\niambic\niambics\niambs\niambus\niambuses\niatric\niatrical\niatrogenic\niatrogenically\nibex\nibexes\nibices\nibidem\nibis\nibises\nibogaine\nibogaines\nibuprofen\nibuprofens\nice\niceberg\nicebergs\niceblink\niceblinks\niceboat\niceboater\niceboaters\niceboating\niceboatings\niceboats\nicebound\nicebox\niceboxes\nicebreaker\nicebreakers\nicecap\nicecaps\niced\nicefall\nicefalls\nicehouse\nicehouses\nicekhana\nicekhanas\niceless\nicelike\nicemaker\nicemakers\niceman\nicemen\nices\nich\nichneumon\nichneumons\nichnite\nichnites\nichor\nichorous\nichors\nichs\nichthyic\nichthyofauna\nichthyofaunae\nichthyofaunal\nichthyofaunas\nichthyological\nichthyologically\nichthyologies\nichthyologist\nichthyologists\nichthyology\nichthyophagous\nichthyosaur\nichthyosaurian\nichthyosaurians\nichthyosaurs\nicicle\nicicled\nicicles\nicier\niciest\nicily\niciness\nicinesses\nicing\nicings\nick\nicker\nickers\nickier\nickiest\nickily\nickiness\nickinesses\nicky\nicon\nicones\niconic\niconical\niconically\niconicities\niconicity\niconoclasm\niconoclasms\niconoclast\niconoclastic\niconoclastically\niconoclasts\niconographer\niconographers\niconographic\niconographical\niconographically\niconographies\niconography\niconolatries\niconolatry\niconological\niconologies\niconology\niconoscope\niconoscopes\niconostases\niconostasis\nicons\nicosahedra\nicosahedral\nicosahedron\nicosahedrons\nicteric\nicterics\nicterus\nicteruses\nictic\nictus\nictuses\nicy\nid\nidea\nideal\nidealess\nidealise\nidealised\nidealises\nidealising\nidealism\nidealisms\nidealist\nidealistic\nidealistically\nidealists\nidealities\nideality\nidealization\nidealizations\nidealize\nidealized\nidealizer\nidealizers\nidealizes\nidealizing\nidealless\nideally\nidealogies\nidealogue\nidealogues\nidealogy\nideals\nideas\nideate\nideated\nideates\nideating\nideation\nideational\nideationally\nideations\nideative\nidem\nidempotent\nidempotents\nidentic\nidentical\nidentically\nidenticalness\nidenticalnesses\nidentifiable\nidentifiably\nidentification\nidentifications\nidentified\nidentifier\nidentifiers\nidentifies\nidentify\nidentifying\nidentities\nidentity\nideogram\nideogramic\nideogrammatic\nideogrammic\nideograms\nideograph\nideographic\nideographically\nideographies\nideographs\nideography\nideologic\nideological\nideologically\nideologies\nideologist\nideologists\nideologize\nideologized\nideologizes\nideologizing\nideologue\nideologues\nideology\nideomotor\nides\nidioblast\nidioblastic\nidioblasts\nidiocies\nidiocy\nidiographic\nidiolect\nidiolectal\nidiolects\nidiom\nidiomatic\nidiomatically\nidiomaticness\nidiomaticnesses\nidiomorphic\nidioms\nidiopathic\nidiopathically\nidiosyncrasies\nidiosyncrasy\nidiosyncratic\nidiosyncratically\nidiot\nidiotic\nidiotical\nidiotically\nidiotism\nidiotisms\nidiots\nidle\nidled\nidleness\nidlenesses\nidler\nidlers\nidles\nidlesse\nidlesses\nidlest\nidling\nidly\nidocrase\nidocrases\nidol\nidolater\nidolaters\nidolator\nidolators\nidolatries\nidolatrous\nidolatrously\nidolatrousness\nidolatrousnesses\nidolatry\nidolise\nidolised\nidoliser\nidolisers\nidolises\nidolising\nidolism\nidolisms\nidolization\nidolizations\nidolize\nidolized\nidolizer\nidolizers\nidolizes\nidolizing\nidols\nidoneities\nidoneity\nidoneous\nids\nidyl\nidylist\nidylists\nidyll\nidyllic\nidyllically\nidyllist\nidyllists\nidylls\nidyls\nif\niff\niffier\niffiest\niffiness\niffinesses\niffy\nifs\nigloo\nigloos\niglu\niglus\nignatia\nignatias\nigneous\nignescent\nignified\nignifies\nignify\nignifying\nignimbrite\nignimbrites\nignitabilities\nignitability\nignitable\nignite\nignited\nigniter\nigniters\nignites\nignitible\nigniting\nignition\nignitions\nignitor\nignitors\nignitron\nignitrons\nignobilities\nignobility\nignoble\nignobleness\nignoblenesses\nignobly\nignominies\nignominious\nignominiously\nignominiousness\nignominiousnesses\nignominy\nignorable\nignorami\nignoramus\nignoramuses\nignorance\nignorances\nignorant\nignorantly\nignorantness\nignorantnesses\nignore\nignored\nignorer\nignorers\nignores\nignoring\niguana\niguanas\niguanian\niguanians\niguanodon\niguanodons\nihram\nihrams\nikat\nikats\nikebana\nikebanas\nikon\nikons\nilea\nileac\nileal\nileitides\nileitis\nileum\nileus\nileuses\nilex\nilexes\nilia\niliac\niliad\niliads\nilial\nilium\nilk\nilka\nilks\nill\nillation\nillations\nillative\nillatively\nillatives\nillaudable\nillaudably\nillegal\nillegalities\nillegality\nillegalization\nillegalizations\nillegalize\nillegalized\nillegalizes\nillegalizing\nillegally\nillegals\nillegibilities\nillegibility\nillegible\nillegibly\nillegitimacies\nillegitimacy\nillegitimate\nillegitimately\niller\nillest\nilliberal\nilliberalism\nilliberalisms\nilliberalities\nilliberality\nilliberally\nilliberalness\nilliberalnesses\nillicit\nillicitly\nillicitness\nillicitnesses\nillimitabilities\nillimitability\nillimitable\nillimitableness\nillimitablenesses\nillimitably\nillinium\nilliniums\nilliquid\nilliquidities\nilliquidity\nillite\nilliteracies\nilliteracy\nilliterate\nilliterately\nilliterateness\nilliteratenesses\nilliterates\nillites\nillitic\nillness\nillnesses\nillocutionary\nillogic\nillogical\nillogicalities\nillogicality\nillogically\nillogicalness\nillogicalnesses\nillogics\nills\nillume\nillumed\nillumes\nilluminable\nilluminance\nilluminances\nilluminant\nilluminants\nilluminate\nilluminated\nilluminates\nilluminati\nilluminating\nilluminatingly\nillumination\nilluminations\nilluminative\nilluminator\nilluminators\nillumine\nillumined\nillumines\nilluming\nillumining\nilluminism\nilluminisms\nilluminist\nilluminists\nillusion\nillusional\nillusionary\nillusionism\nillusionisms\nillusionist\nillusionistic\nillusionistically\nillusionists\nillusions\nillusive\nillusively\nillusiveness\nillusivenesses\nillusorily\nillusoriness\nillusorinesses\nillusory\nillustrate\nillustrated\nillustrates\nillustrating\nillustration\nillustrational\nillustrations\nillustrative\nillustratively\nillustrator\nillustrators\nillustrious\nillustriously\nillustriousness\nillustriousnesses\nilluvia\nilluvial\nilluviated\nilluviation\nilluviations\nilluvium\nilluviums\nilly\nilmenite\nilmenites\nimage\nimaged\nimager\nimageries\nimagers\nimagery\nimages\nimaginable\nimaginableness\nimaginablenesses\nimaginably\nimaginal\nimaginaries\nimaginarily\nimaginariness\nimaginarinesses\nimaginary\nimagination\nimaginations\nimaginative\nimaginatively\nimaginativeness\nimaginativenesses\nimagine\nimagined\nimaginer\nimaginers\nimagines\nimaging\nimagings\nimagining\nimagism\nimagisms\nimagist\nimagistic\nimagistically\nimagists\nimago\nimagoes\nimagos\nimam\nimamate\nimamates\nimams\nimaret\nimarets\nimaum\nimaums\nimbalance\nimbalanced\nimbalances\nimbalm\nimbalmed\nimbalmer\nimbalmers\nimbalming\nimbalms\nimbark\nimbarked\nimbarking\nimbarks\nimbecile\nimbeciles\nimbecilic\nimbecilities\nimbecility\nimbed\nimbedded\nimbedding\nimbeds\nimbibe\nimbibed\nimbiber\nimbibers\nimbibes\nimbibing\nimbibition\nimbibitional\nimbibitions\nimbitter\nimbittered\nimbittering\nimbitters\nimblaze\nimblazed\nimblazes\nimblazing\nimbodied\nimbodies\nimbody\nimbodying\nimbolden\nimboldened\nimboldening\nimboldens\nimbosom\nimbosomed\nimbosoming\nimbosoms\nimbower\nimbowered\nimbowering\nimbowers\nimbricate\nimbricated\nimbricates\nimbricating\nimbrication\nimbrications\nimbroglio\nimbroglios\nimbrown\nimbrowned\nimbrowning\nimbrowns\nimbrue\nimbrued\nimbrues\nimbruing\nimbrute\nimbruted\nimbrutes\nimbruting\nimbue\nimbued\nimbues\nimbuing\nimid\nimidazole\nimidazoles\nimide\nimides\nimidic\nimido\nimids\nimine\nimines\nimino\nimipramine\nimipramines\nimitable\nimitate\nimitated\nimitates\nimitating\nimitation\nimitations\nimitative\nimitatively\nimitativeness\nimitativenesses\nimitator\nimitators\nimmaculacies\nimmaculacy\nimmaculate\nimmaculately\nimmane\nimmanence\nimmanences\nimmanencies\nimmanency\nimmanent\nimmanentism\nimmanentisms\nimmanentist\nimmanentistic\nimmanentists\nimmanently\nimmaterial\nimmaterialism\nimmaterialisms\nimmaterialist\nimmaterialists\nimmaterialities\nimmateriality\nimmaterialize\nimmaterialized\nimmaterializes\nimmaterializing\nimmature\nimmaturely\nimmatures\nimmaturities\nimmaturity\nimmeasurable\nimmeasurableness\nimmeasurablenesses\nimmeasurably\nimmediacies\nimmediacy\nimmediate\nimmediately\nimmediateness\nimmediatenesses\nimmedicable\nimmedicably\nimmemorial\nimmemorially\nimmense\nimmensely\nimmenseness\nimmensenesses\nimmenser\nimmensest\nimmensities\nimmensity\nimmensurable\nimmerge\nimmerged\nimmerges\nimmerging\nimmerse\nimmersed\nimmerses\nimmersible\nimmersing\nimmersion\nimmersions\nimmesh\nimmeshed\nimmeshes\nimmeshing\nimmethodical\nimmethodically\nimmies\nimmigrant\nimmigrants\nimmigrate\nimmigrated\nimmigrates\nimmigrating\nimmigration\nimmigrational\nimmigrations\nimminence\nimminences\nimminencies\nimminency\nimminent\nimminently\nimmingle\nimmingled\nimmingles\nimmingling\nimmiscibilities\nimmiscibility\nimmiscible\nimmitigable\nimmitigably\nimmittance\nimmittances\nimmix\nimmixed\nimmixes\nimmixing\nimmixture\nimmixtures\nimmobile\nimmobilism\nimmobilisms\nimmobilities\nimmobility\nimmobilization\nimmobilizations\nimmobilize\nimmobilized\nimmobilizer\nimmobilizers\nimmobilizes\nimmobilizing\nimmoderacies\nimmoderacy\nimmoderate\nimmoderately\nimmoderateness\nimmoderatenesses\nimmoderation\nimmoderations\nimmodest\nimmodesties\nimmodestly\nimmodesty\nimmolate\nimmolated\nimmolates\nimmolating\nimmolation\nimmolations\nimmolator\nimmolators\nimmoral\nimmoralism\nimmoralisms\nimmoralist\nimmoralists\nimmoralities\nimmorality\nimmorally\nimmortal\nimmortalise\nimmortalised\nimmortalises\nimmortalising\nimmortalities\nimmortality\nimmortalization\nimmortalizations\nimmortalize\nimmortalized\nimmortalizer\nimmortalizers\nimmortalizes\nimmortalizing\nimmortally\nimmortals\nimmortelle\nimmortelles\nimmotile\nimmovabilities\nimmovability\nimmovable\nimmovableness\nimmovablenesses\nimmovables\nimmovably\nimmune\nimmunes\nimmunise\nimmunised\nimmunises\nimmunising\nimmunities\nimmunity\nimmunization\nimmunizations\nimmunize\nimmunized\nimmunizes\nimmunizing\nimmunoassay\nimmunoassayable\nimmunoassays\nimmunoblot\nimmunoblots\nimmunoblotting\nimmunoblottings\nimmunochemical\nimmunochemically\nimmunochemist\nimmunochemistries\nimmunochemistry\nimmunochemists\nimmunocompetence\nimmunocompetences\nimmunocompetent\nimmunocompromised\nimmunocytochemical\nimmunocytochemically\nimmunocytochemistries\nimmunocytochemistry\nimmunodeficiencies\nimmunodeficiency\nimmunodeficient\nimmunodiagnoses\nimmunodiagnosis\nimmunodiagnostic\nimmunodiffusion\nimmunodiffusions\nimmunoelectrophoreses\nimmunoelectrophoresis\nimmunoelectrophoretic\nimmunoelectrophoretically\nimmunofluorescence\nimmunofluorescences\nimmunofluorescent\nimmunogen\nimmunogeneses\nimmunogenesis\nimmunogenetic\nimmunogenetically\nimmunogeneticist\nimmunogeneticists\nimmunogenetics\nimmunogenic\nimmunogenicities\nimmunogenicity\nimmunogens\nimmunoglobulin\nimmunoglobulins\nimmunohematologic\nimmunohematological\nimmunohematologies\nimmunohematologist\nimmunohematologists\nimmunohematology\nimmunohistochemical\nimmunohistochemistries\nimmunohistochemistry\nimmunologic\nimmunological\nimmunologically\nimmunologies\nimmunologist\nimmunologists\nimmunology\nimmunomodulator\nimmunomodulators\nimmunomodulatory\nimmunopathologic\nimmunopathological\nimmunopathologies\nimmunopathologist\nimmunopathologists\nimmunopathology\nimmunoprecipitate\nimmunoprecipitated\nimmunoprecipitates\nimmunoprecipitating\nimmunoprecipitation\nimmunoprecipitations\nimmunoreactive\nimmunoreactivities\nimmunoreactivity\nimmunoregulation\nimmunoregulations\nimmunoregulatory\nimmunosorbent\nimmunosorbents\nimmunosuppress\nimmunosuppressant\nimmunosuppressants\nimmunosuppressed\nimmunosuppresses\nimmunosuppressing\nimmunosuppression\nimmunosuppressions\nimmunosuppressive\nimmunotherapeutic\nimmunotherapies\nimmunotherapy\nimmure\nimmured\nimmurement\nimmurements\nimmures\nimmuring\nimmutabilities\nimmutability\nimmutable\nimmutableness\nimmutablenesses\nimmutably\nimmy\nimp\nimpact\nimpacted\nimpacter\nimpacters\nimpacting\nimpaction\nimpactions\nimpactive\nimpactor\nimpactors\nimpacts\nimpaint\nimpainted\nimpainting\nimpaints\nimpair\nimpaired\nimpairer\nimpairers\nimpairing\nimpairment\nimpairments\nimpairs\nimpala\nimpalas\nimpale\nimpaled\nimpalement\nimpalements\nimpaler\nimpalers\nimpales\nimpaling\nimpalpabilities\nimpalpability\nimpalpable\nimpalpably\nimpanel\nimpaneled\nimpaneling\nimpanelled\nimpanelling\nimpanels\nimparadise\nimparadised\nimparadises\nimparadising\nimparities\nimparity\nimpark\nimparked\nimparking\nimparks\nimpart\nimpartation\nimpartations\nimparted\nimparter\nimparters\nimpartial\nimpartialities\nimpartiality\nimpartially\nimpartible\nimpartibly\nimparting\nimpartment\nimpartments\nimparts\nimpassabilities\nimpassability\nimpassable\nimpassableness\nimpassablenesses\nimpassably\nimpasse\nimpasses\nimpassibilities\nimpassibility\nimpassible\nimpassibly\nimpassion\nimpassioned\nimpassioning\nimpassions\nimpassive\nimpassively\nimpassiveness\nimpassivenesses\nimpassivities\nimpassivity\nimpaste\nimpasted\nimpastes\nimpasting\nimpasto\nimpastoed\nimpastos\nimpatience\nimpatiences\nimpatiens\nimpatienses\nimpatient\nimpatiently\nimpavid\nimpawn\nimpawned\nimpawning\nimpawns\nimpeach\nimpeachable\nimpeached\nimpeaches\nimpeaching\nimpeachment\nimpeachments\nimpearl\nimpearled\nimpearling\nimpearls\nimpeccabilities\nimpeccability\nimpeccable\nimpeccably\nimpecuniosities\nimpecuniosity\nimpecunious\nimpecuniously\nimpecuniousness\nimpecuniousnesses\nimped\nimpedance\nimpedances\nimpede\nimpeded\nimpeder\nimpeders\nimpedes\nimpediment\nimpedimenta\nimpediments\nimpeding\nimpel\nimpelled\nimpeller\nimpellers\nimpelling\nimpellor\nimpellors\nimpels\nimpend\nimpended\nimpendent\nimpending\nimpends\nimpenetrabilities\nimpenetrability\nimpenetrable\nimpenetrably\nimpenitence\nimpenitences\nimpenitent\nimpenitently\nimperative\nimperatively\nimperativeness\nimperativenesses\nimperatives\nimperator\nimperatorial\nimperators\nimperceivable\nimperceptible\nimperceptibly\nimperceptive\nimperceptiveness\nimperceptivenesses\nimpercipience\nimpercipiences\nimpercipient\nimperfect\nimperfection\nimperfections\nimperfective\nimperfectives\nimperfectly\nimperfectness\nimperfectnesses\nimperfects\nimperforate\nimperia\nimperial\nimperialism\nimperialisms\nimperialist\nimperialistic\nimperialistically\nimperialists\nimperially\nimperials\nimperil\nimperiled\nimperiling\nimperilled\nimperilling\nimperilment\nimperilments\nimperils\nimperious\nimperiously\nimperiousness\nimperiousnesses\nimperishabilities\nimperishability\nimperishable\nimperishableness\nimperishablenesses\nimperishables\nimperishably\nimperium\nimperiums\nimpermanence\nimpermanences\nimpermanencies\nimpermanency\nimpermanent\nimpermanently\nimpermeabilities\nimpermeability\nimpermeable\nimpermissibilities\nimpermissibility\nimpermissible\nimpermissibly\nimpersonal\nimpersonalities\nimpersonality\nimpersonalization\nimpersonalizations\nimpersonalize\nimpersonalized\nimpersonalizes\nimpersonalizing\nimpersonally\nimpersonate\nimpersonated\nimpersonates\nimpersonating\nimpersonation\nimpersonations\nimpersonator\nimpersonators\nimpertinence\nimpertinences\nimpertinencies\nimpertinency\nimpertinent\nimpertinently\nimperturbabilities\nimperturbability\nimperturbable\nimperturbably\nimpervious\nimperviously\nimperviousness\nimperviousnesses\nimpetiginous\nimpetigo\nimpetigos\nimpetrate\nimpetrated\nimpetrates\nimpetrating\nimpetration\nimpetrations\nimpetuosities\nimpetuosity\nimpetuous\nimpetuously\nimpetuousness\nimpetuousnesses\nimpetus\nimpetuses\nimphee\nimphees\nimpi\nimpieties\nimpiety\nimping\nimpinge\nimpinged\nimpingement\nimpingements\nimpinger\nimpingers\nimpinges\nimpinging\nimpings\nimpious\nimpiously\nimpis\nimpish\nimpishly\nimpishness\nimpishnesses\nimplacabilities\nimplacability\nimplacable\nimplacably\nimplant\nimplantable\nimplantation\nimplantations\nimplanted\nimplanter\nimplanters\nimplanting\nimplants\nimplausibilities\nimplausibility\nimplausible\nimplausibly\nimplead\nimpleaded\nimpleading\nimpleads\nimpledge\nimpledged\nimpledges\nimpledging\nimplement\nimplementation\nimplementations\nimplemented\nimplementer\nimplementers\nimplementing\nimplementor\nimplementors\nimplements\nimplicate\nimplicated\nimplicates\nimplicating\nimplication\nimplications\nimplicative\nimplicatively\nimplicativeness\nimplicativenesses\nimplicit\nimplicitly\nimplicitness\nimplicitnesses\nimplied\nimplies\nimplode\nimploded\nimplodes\nimploding\nimplore\nimplored\nimplorer\nimplorers\nimplores\nimploring\nimploringly\nimplosion\nimplosions\nimplosive\nimplosives\nimply\nimplying\nimpolicies\nimpolicy\nimpolite\nimpolitely\nimpoliteness\nimpolitenesses\nimpolitic\nimpolitical\nimpolitically\nimpoliticly\nimponderabilities\nimponderability\nimponderable\nimponderables\nimponderably\nimpone\nimponed\nimpones\nimponing\nimporous\nimport\nimportable\nimportance\nimportances\nimportancies\nimportancy\nimportant\nimportantly\nimportation\nimportations\nimported\nimporter\nimporters\nimporting\nimports\nimportunate\nimportunately\nimportunateness\nimportunatenesses\nimportune\nimportuned\nimportunely\nimportuner\nimportuners\nimportunes\nimportuning\nimportunities\nimportunity\nimpose\nimposed\nimposer\nimposers\nimposes\nimposing\nimposingly\nimposition\nimpositions\nimpossibilities\nimpossibility\nimpossible\nimpossibleness\nimpossiblenesses\nimpossibly\nimpost\nimposted\nimposter\nimposters\nimposthume\nimposthumes\nimposting\nimpostor\nimpostors\nimposts\nimpostume\nimpostumes\nimposture\nimpostures\nimpotence\nimpotences\nimpotencies\nimpotency\nimpotent\nimpotently\nimpotents\nimpound\nimpounded\nimpounding\nimpoundment\nimpoundments\nimpounds\nimpoverish\nimpoverished\nimpoverisher\nimpoverishers\nimpoverishes\nimpoverishing\nimpoverishment\nimpoverishments\nimpower\nimpowered\nimpowering\nimpowers\nimpracticabilities\nimpracticability\nimpracticable\nimpracticably\nimpractical\nimpracticalities\nimpracticality\nimpractically\nimprecate\nimprecated\nimprecates\nimprecating\nimprecation\nimprecations\nimprecatory\nimprecise\nimprecisely\nimpreciseness\nimprecisenesses\nimprecision\nimprecisions\nimpregn\nimpregnabilities\nimpregnability\nimpregnable\nimpregnableness\nimpregnablenesses\nimpregnably\nimpregnant\nimpregnants\nimpregnate\nimpregnated\nimpregnates\nimpregnating\nimpregnation\nimpregnations\nimpregnator\nimpregnators\nimpregned\nimpregning\nimpregns\nimpresa\nimpresario\nimpresarios\nimpresas\nimprese\nimpreses\nimpress\nimpressed\nimpresses\nimpressibilities\nimpressibility\nimpressible\nimpressing\nimpression\nimpressionabilities\nimpressionability\nimpressionable\nimpressionism\nimpressionisms\nimpressionist\nimpressionistic\nimpressionistically\nimpressionists\nimpressions\nimpressive\nimpressively\nimpressiveness\nimpressivenesses\nimpressment\nimpressments\nimpressure\nimpressures\nimprest\nimprests\nimprimatur\nimprimaturs\nimprimis\nimprint\nimprinted\nimprinter\nimprinters\nimprinting\nimprintings\nimprints\nimprison\nimprisoned\nimprisoning\nimprisonment\nimprisonments\nimprisons\nimprobabilities\nimprobability\nimprobable\nimprobably\nimpromptu\nimpromptus\nimproper\nimproperly\nimproperness\nimpropernesses\nimproprieties\nimpropriety\nimprov\nimprovabilities\nimprovability\nimprovable\nimprove\nimproved\nimprovement\nimprovements\nimprover\nimprovers\nimproves\nimprovidence\nimprovidences\nimprovident\nimprovidently\nimproving\nimprovisation\nimprovisational\nimprovisationally\nimprovisations\nimprovisator\nimprovisatore\nimprovisatores\nimprovisatori\nimprovisatorial\nimprovisators\nimprovisatory\nimprovise\nimprovised\nimproviser\nimprovisers\nimprovises\nimprovising\nimprovisor\nimprovisors\nimprovs\nimprudence\nimprudences\nimprudent\nimprudently\nimps\nimpudence\nimpudences\nimpudent\nimpudently\nimpudicities\nimpudicity\nimpugn\nimpugnable\nimpugned\nimpugner\nimpugners\nimpugning\nimpugns\nimpuissance\nimpuissances\nimpuissant\nimpulse\nimpulsed\nimpulses\nimpulsing\nimpulsion\nimpulsions\nimpulsive\nimpulsively\nimpulsiveness\nimpulsivenesses\nimpulsivities\nimpulsivity\nimpunities\nimpunity\nimpure\nimpurely\nimpureness\nimpurenesses\nimpurities\nimpurity\nimputabilities\nimputability\nimputable\nimputation\nimputations\nimputative\nimputatively\nimpute\nimputed\nimputer\nimputers\nimputes\nimputing\nin\ninabilities\ninability\ninaccessibilities\ninaccessibility\ninaccessible\ninaccessibly\ninaccuracies\ninaccuracy\ninaccurate\ninaccurately\ninaction\ninactions\ninactivate\ninactivated\ninactivates\ninactivating\ninactivation\ninactivations\ninactive\ninactively\ninactivities\ninactivity\ninadequacies\ninadequacy\ninadequate\ninadequately\ninadequateness\ninadequatenesses\ninadmissibilities\ninadmissibility\ninadmissible\ninadmissibly\ninadvertence\ninadvertences\ninadvertencies\ninadvertency\ninadvertent\ninadvertently\ninadvisabilities\ninadvisability\ninadvisable\ninalienabilities\ninalienability\ninalienable\ninalienably\ninalterabilities\ninalterability\ninalterable\ninalterableness\ninalterablenesses\ninalterably\ninamorata\ninamoratas\ninane\ninanely\ninaneness\ninanenesses\ninaner\ninanes\ninanest\ninanimate\ninanimately\ninanimateness\ninanimatenesses\ninanities\ninanition\ninanitions\ninanity\ninapparent\ninapparently\ninappeasable\ninappetence\ninappetences\ninapplicabilities\ninapplicability\ninapplicable\ninapplicably\ninapposite\ninappositely\ninappositeness\ninappositenesses\ninappreciable\ninappreciably\ninappreciative\ninappreciatively\ninappreciativeness\ninappreciativenesses\ninapproachable\ninappropriate\ninappropriately\ninappropriateness\ninappropriatenesses\ninapt\ninaptitude\ninaptitudes\ninaptly\ninaptness\ninaptnesses\ninarable\ninarch\ninarched\ninarches\ninarching\ninarguable\ninarguably\ninarm\ninarmed\ninarming\ninarms\ninarticulacies\ninarticulacy\ninarticulate\ninarticulately\ninarticulateness\ninarticulatenesses\ninarticulates\ninartistic\ninartistically\ninattention\ninattentions\ninattentive\ninattentively\ninattentiveness\ninattentivenesses\ninaudibilities\ninaudibility\ninaudible\ninaudibly\ninaugural\ninaugurals\ninaugurate\ninaugurated\ninaugurates\ninaugurating\ninauguration\ninaugurations\ninaugurator\ninaugurators\ninauspicious\ninauspiciously\ninauspiciousness\ninauspiciousnesses\ninauthentic\ninauthenticities\ninauthenticity\ninbeing\ninbeings\ninboard\ninboards\ninborn\ninbound\ninbounded\ninbounding\ninbounds\ninbreathe\ninbreathed\ninbreathes\ninbreathing\ninbred\ninbreds\ninbreed\ninbreeding\ninbreedings\ninbreeds\ninbuilt\ninburst\ninbursts\ninby\ninbye\nincage\nincaged\nincages\nincaging\nincalculabilities\nincalculability\nincalculable\nincalculably\nincalescence\nincalescences\nincalescent\nincandesce\nincandesced\nincandescence\nincandescences\nincandescent\nincandescently\nincandescents\nincandesces\nincandescing\nincant\nincantation\nincantational\nincantations\nincantatory\nincanted\nincanting\nincants\nincapabilities\nincapability\nincapable\nincapableness\nincapablenesses\nincapably\nincapacitate\nincapacitated\nincapacitates\nincapacitating\nincapacitation\nincapacitations\nincapacities\nincapacity\nincarcerate\nincarcerated\nincarcerates\nincarcerating\nincarceration\nincarcerations\nincardination\nincardinations\nincarnadine\nincarnadined\nincarnadines\nincarnadining\nincarnate\nincarnated\nincarnates\nincarnating\nincarnation\nincarnations\nincase\nincased\nincases\nincasing\nincaution\nincautions\nincautious\nincautiously\nincautiousness\nincautiousnesses\nincendiaries\nincendiarism\nincendiarisms\nincendiary\nincense\nincensed\nincenses\nincensing\nincenter\nincenters\nincentive\nincentives\nincentivize\nincentivized\nincentivizes\nincentivizing\nincept\nincepted\nincepting\ninception\ninceptions\ninceptive\ninceptively\ninceptives\ninceptor\ninceptors\nincepts\nincertitude\nincertitudes\nincessancies\nincessancy\nincessant\nincessantly\nincest\nincests\nincestuous\nincestuously\nincestuousness\nincestuousnesses\ninch\ninched\ninches\ninching\ninchmeal\ninchoate\ninchoately\ninchoateness\ninchoatenesses\ninchoative\ninchoatively\ninchoatives\ninchworm\ninchworms\nincidence\nincidences\nincident\nincidental\nincidentally\nincidentals\nincidents\nincinerate\nincinerated\nincinerates\nincinerating\nincineration\nincinerations\nincinerator\nincinerators\nincipience\nincipiences\nincipiencies\nincipiency\nincipient\nincipiently\nincipit\nincipits\nincisal\nincise\nincised\nincises\nincising\nincision\nincisions\nincisive\nincisively\nincisiveness\nincisivenesses\nincisor\nincisors\nincisory\nincisure\nincisures\nincitant\nincitants\nincitation\nincitations\nincite\nincited\nincitement\nincitements\ninciter\ninciters\nincites\ninciting\nincivil\nincivilities\nincivility\ninclasp\ninclasped\ninclasping\ninclasps\ninclemencies\ninclemency\ninclement\ninclemently\ninclinable\ninclination\ninclinational\ninclinations\nincline\ninclined\nincliner\nincliners\ninclines\ninclining\ninclinings\ninclinometer\ninclinometers\ninclip\ninclipped\ninclipping\ninclips\ninclose\ninclosed\nincloser\ninclosers\nincloses\ninclosing\ninclosure\ninclosures\nincludable\ninclude\nincluded\nincludes\nincludible\nincluding\ninclusion\ninclusions\ninclusive\ninclusively\ninclusiveness\ninclusivenesses\nincoercible\nincog\nincogitant\nincognita\nincognitas\nincognito\nincognitos\nincognizance\nincognizances\nincognizant\nincogs\nincoherence\nincoherences\nincoherent\nincoherently\nincombustibilities\nincombustibility\nincombustible\nincombustibles\nincome\nincomer\nincomers\nincomes\nincoming\nincomings\nincommensurabilities\nincommensurability\nincommensurable\nincommensurables\nincommensurably\nincommensurate\nincommode\nincommoded\nincommodes\nincommoding\nincommodious\nincommodiously\nincommodiousness\nincommodiousnesses\nincommodities\nincommodity\nincommunicabilities\nincommunicability\nincommunicable\nincommunicably\nincommunicado\nincommunicative\nincommutable\nincommutably\nincomparabilities\nincomparability\nincomparable\nincomparably\nincompatibilities\nincompatibility\nincompatible\nincompatibles\nincompatibly\nincompetence\nincompetences\nincompetencies\nincompetency\nincompetent\nincompetently\nincompetents\nincomplete\nincompletely\nincompleteness\nincompletenesses\nincompliant\nincomprehensibilities\nincomprehensibility\nincomprehensible\nincomprehensibleness\nincomprehensiblenesses\nincomprehensibly\nincomprehension\nincomprehensions\nincompressible\nincomputable\nincomputably\ninconceivabilities\ninconceivability\ninconceivable\ninconceivableness\ninconceivablenesses\ninconceivably\ninconcinnities\ninconcinnity\ninconclusive\ninconclusively\ninconclusiveness\ninconclusivenesses\nincondite\ninconformities\ninconformity\nincongruence\nincongruences\nincongruent\nincongruently\nincongruities\nincongruity\nincongruous\nincongruously\nincongruousness\nincongruousnesses\ninconnu\ninconnus\ninconscient\ninconsecutive\ninconsequence\ninconsequences\ninconsequent\ninconsequential\ninconsequentialities\ninconsequentiality\ninconsequentially\ninconsequently\ninconsiderable\ninconsiderableness\ninconsiderablenesses\ninconsiderably\ninconsiderate\ninconsiderately\ninconsiderateness\ninconsideratenesses\ninconsideration\ninconsiderations\ninconsistence\ninconsistences\ninconsistencies\ninconsistency\ninconsistent\ninconsistently\ninconsolable\ninconsolableness\ninconsolablenesses\ninconsolably\ninconsonance\ninconsonances\ninconsonant\ninconspicuous\ninconspicuously\ninconspicuousness\ninconspicuousnesses\ninconstancies\ninconstancy\ninconstant\ninconstantly\ninconsumable\ninconsumably\nincontestabilities\nincontestability\nincontestable\nincontestably\nincontinence\nincontinences\nincontinencies\nincontinency\nincontinent\nincontinently\nincontrollable\nincontrovertible\nincontrovertibly\ninconvenience\ninconvenienced\ninconveniences\ninconveniencies\ninconveniencing\ninconveniency\ninconvenient\ninconveniently\ninconvertibilities\ninconvertibility\ninconvertible\ninconvertibly\ninconvincible\nincony\nincoordination\nincoordinations\nincorporable\nincorporate\nincorporated\nincorporates\nincorporating\nincorporation\nincorporations\nincorporative\nincorporator\nincorporators\nincorporeal\nincorporeally\nincorporeities\nincorporeity\nincorpse\nincorpsed\nincorpses\nincorpsing\nincorrect\nincorrectly\nincorrectness\nincorrectnesses\nincorrigibilities\nincorrigibility\nincorrigible\nincorrigibleness\nincorrigiblenesses\nincorrigibles\nincorrigibly\nincorrupt\nincorrupted\nincorruptibilities\nincorruptibility\nincorruptible\nincorruptibles\nincorruptibly\nincorruption\nincorruptions\nincorruptly\nincorruptness\nincorruptnesses\nincreasable\nincrease\nincreased\nincreaser\nincreasers\nincreases\nincreasing\nincreasingly\nincreate\nincredibilities\nincredibility\nincredible\nincredibleness\nincrediblenesses\nincredibly\nincredulities\nincredulity\nincredulous\nincredulously\nincrement\nincremental\nincrementalism\nincrementalisms\nincrementalist\nincrementalists\nincrementally\nincremented\nincrementing\nincrements\nincrescent\nincriminate\nincriminated\nincriminates\nincriminating\nincrimination\nincriminations\nincriminatory\nincross\nincrossed\nincrosses\nincrossing\nincrust\nincrustation\nincrustations\nincrusted\nincrusting\nincrusts\nincubate\nincubated\nincubates\nincubating\nincubation\nincubations\nincubative\nincubator\nincubators\nincubatory\nincubi\nincubus\nincubuses\nincudal\nincudate\nincudes\ninculcate\ninculcated\ninculcates\ninculcating\ninculcation\ninculcations\ninculcator\ninculcators\ninculpable\ninculpate\ninculpated\ninculpates\ninculpating\ninculpation\ninculpations\ninculpatory\nincult\nincumbencies\nincumbency\nincumbent\nincumbents\nincumber\nincumbered\nincumbering\nincumbers\nincunable\nincunables\nincunabula\nincunabulum\nincur\nincurable\nincurables\nincurably\nincuriosities\nincuriosity\nincurious\nincuriously\nincuriousness\nincuriousnesses\nincurred\nincurrence\nincurrences\nincurrent\nincurring\nincurs\nincursion\nincursions\nincurvate\nincurvated\nincurvates\nincurvating\nincurvation\nincurvations\nincurvature\nincurvatures\nincurve\nincurved\nincurves\nincurving\nincus\nincuse\nincused\nincuses\nincusing\nindaba\nindabas\nindagate\nindagated\nindagates\nindagating\nindagation\nindagations\nindagator\nindagators\nindamin\nindamine\nindamines\nindamins\nindebted\nindebtedness\nindebtednesses\nindecencies\nindecency\nindecent\nindecenter\nindecentest\nindecently\nindecipherable\nindecision\nindecisions\nindecisive\nindecisively\nindecisiveness\nindecisivenesses\nindeclinable\nindecomposable\nindecorous\nindecorously\nindecorousness\nindecorousnesses\nindecorum\nindecorums\nindeed\nindefatigabilities\nindefatigability\nindefatigable\nindefatigableness\nindefatigablenesses\nindefatigably\nindefeasibilities\nindefeasibility\nindefeasible\nindefeasibly\nindefectibilities\nindefectibility\nindefectible\nindefectibly\nindefensibilities\nindefensibility\nindefensible\nindefensibly\nindefinabilities\nindefinability\nindefinable\nindefinableness\nindefinablenesses\nindefinables\nindefinably\nindefinite\nindefinitely\nindefiniteness\nindefinitenesses\nindefinites\nindehiscence\nindehiscences\nindehiscent\nindelibilities\nindelibility\nindelible\nindelibly\nindelicacies\nindelicacy\nindelicate\nindelicately\nindelicateness\nindelicatenesses\nindemnification\nindemnifications\nindemnified\nindemnifier\nindemnifiers\nindemnifies\nindemnify\nindemnifying\nindemnities\nindemnity\nindemonstrable\nindemonstrably\nindene\nindenes\nindent\nindentation\nindentations\nindented\nindenter\nindenters\nindenting\nindention\nindentions\nindentor\nindentors\nindents\nindenture\nindentured\nindentures\nindenturing\nindependence\nindependences\nindependencies\nindependency\nindependent\nindependently\nindependents\nindescribable\nindescribableness\nindescribablenesses\nindescribably\nindestructibilities\nindestructibility\nindestructible\nindestructibleness\nindestructiblenesses\nindestructibly\nindeterminable\nindeterminably\nindeterminacies\nindeterminacy\nindeterminate\nindeterminately\nindeterminateness\nindeterminatenesses\nindetermination\nindeterminations\nindeterminism\nindeterminisms\nindeterminist\nindeterministic\nindeterminists\nindevout\nindex\nindexation\nindexations\nindexed\nindexer\nindexers\nindexes\nindexical\nindexicals\nindexing\nindexings\nindican\nindicans\nindicant\nindicants\nindicate\nindicated\nindicates\nindicating\nindication\nindicational\nindications\nindicative\nindicatively\nindicatives\nindicator\nindicators\nindicatory\nindices\nindicia\nindicias\nindicium\nindiciums\nindict\nindictable\nindicted\nindictee\nindictees\nindicter\nindicters\nindicting\nindiction\nindictions\nindictment\nindictments\nindictor\nindictors\nindicts\nindie\nindies\nindifference\nindifferences\nindifferencies\nindifferency\nindifferent\nindifferentism\nindifferentisms\nindifferentist\nindifferentists\nindifferently\nindigen\nindigence\nindigences\nindigene\nindigenes\nindigenization\nindigenizations\nindigenize\nindigenized\nindigenizes\nindigenizing\nindigenous\nindigenously\nindigenousness\nindigenousnesses\nindigens\nindigent\nindigents\nindigested\nindigestibilities\nindigestibility\nindigestible\nindigestibles\nindigestion\nindigestions\nindign\nindignant\nindignantly\nindignation\nindignations\nindignities\nindignity\nindignly\nindigo\nindigoes\nindigoid\nindigoids\nindigos\nindigotin\nindigotins\nindirect\nindirection\nindirections\nindirectly\nindirectness\nindirectnesses\nindiscernible\nindisciplinable\nindiscipline\nindisciplined\nindisciplines\nindiscoverable\nindiscreet\nindiscreetly\nindiscreetness\nindiscreetnesses\nindiscretion\nindiscretions\nindiscriminate\nindiscriminately\nindiscriminateness\nindiscriminatenesses\nindiscriminating\nindiscriminatingly\nindiscrimination\nindiscriminations\nindispensabilities\nindispensability\nindispensable\nindispensableness\nindispensablenesses\nindispensables\nindispensably\nindispose\nindisposed\nindisposes\nindisposing\nindisposition\nindispositions\nindisputable\nindisputableness\nindisputablenesses\nindisputably\nindissociable\nindissociably\nindissolubilities\nindissolubility\nindissoluble\nindissolubleness\nindissolublenesses\nindissolubly\nindistinct\nindistinctive\nindistinctly\nindistinctness\nindistinctnesses\nindistinguishabilities\nindistinguishability\nindistinguishable\nindistinguishableness\nindistinguishablenesses\nindistinguishably\nindite\nindited\ninditer\ninditers\nindites\ninditing\nindium\nindiums\nindividual\nindividualise\nindividualised\nindividualises\nindividualising\nindividualism\nindividualisms\nindividualist\nindividualistic\nindividualistically\nindividualists\nindividualities\nindividuality\nindividualization\nindividualizations\nindividualize\nindividualized\nindividualizes\nindividualizing\nindividually\nindividuals\nindividuate\nindividuated\nindividuates\nindividuating\nindividuation\nindividuations\nindivisibilities\nindivisibility\nindivisible\nindivisibles\nindivisibly\nindocile\nindocilities\nindocility\nindoctrinate\nindoctrinated\nindoctrinates\nindoctrinating\nindoctrination\nindoctrinations\nindoctrinator\nindoctrinators\nindol\nindole\nindolence\nindolences\nindolent\nindolently\nindoles\nindols\nindomethacin\nindomethacins\nindomitabilities\nindomitability\nindomitable\nindomitableness\nindomitablenesses\nindomitably\nindoor\nindoors\nindophenol\nindophenols\nindorse\nindorsed\nindorsee\nindorsees\nindorsement\nindorsements\nindorser\nindorsers\nindorses\nindorsing\nindorsor\nindorsors\nindow\nindowed\nindowing\nindows\nindoxyl\nindoxyls\nindraft\nindrafts\nindrawn\nindri\nindris\nindubitabilities\nindubitability\nindubitable\nindubitableness\nindubitablenesses\nindubitably\ninduce\ninduced\ninducement\ninducements\ninducer\ninducers\ninduces\ninducibilities\ninducibility\ninducible\ninducing\ninduct\ninductance\ninductances\ninducted\ninductee\ninductees\ninducting\ninduction\ninductions\ninductive\ninductively\ninductor\ninductors\ninducts\nindue\nindued\nindues\ninduing\nindulge\nindulged\nindulgence\nindulgences\nindulgent\nindulgently\nindulger\nindulgers\nindulges\nindulging\nindulin\ninduline\nindulines\nindulins\nindult\nindults\nindurate\nindurated\nindurates\nindurating\ninduration\nindurations\nindurative\nindusia\nindusial\nindusium\nindustrial\nindustrialise\nindustrialised\nindustrialises\nindustrialising\nindustrialism\nindustrialisms\nindustrialist\nindustrialists\nindustrialization\nindustrializations\nindustrialize\nindustrialized\nindustrializes\nindustrializing\nindustrially\nindustrials\nindustries\nindustrious\nindustriously\nindustriousness\nindustriousnesses\nindustry\nindwell\nindweller\nindwellers\nindwelling\nindwells\nindwelt\ninearth\ninearthed\ninearthing\ninearths\ninebriant\ninebriants\ninebriate\ninebriated\ninebriates\ninebriating\ninebriation\ninebriations\ninebrieties\ninebriety\ninedible\ninedita\ninedited\nineducabilities\nineducability\nineducable\nineffabilities\nineffability\nineffable\nineffableness\nineffablenesses\nineffably\nineffaceabilities\nineffaceability\nineffaceable\nineffaceably\nineffective\nineffectively\nineffectiveness\nineffectivenesses\nineffectual\nineffectualities\nineffectuality\nineffectually\nineffectualness\nineffectualnesses\ninefficacies\ninefficacious\ninefficaciously\ninefficaciousness\ninefficaciousnesses\ninefficacy\ninefficiencies\ninefficiency\ninefficient\ninefficiently\ninefficients\ninegalitarian\ninelastic\ninelasticities\ninelasticity\ninelegance\ninelegances\ninelegant\ninelegantly\nineligibilities\nineligibility\nineligible\nineligibles\nineloquent\nineloquently\nineluctabilities\nineluctability\nineluctable\nineluctably\nineludible\ninenarrable\ninept\nineptitude\nineptitudes\nineptly\nineptness\nineptnesses\ninequalities\ninequality\ninequitable\ninequitably\ninequities\ninequity\ninequivalve\ninequivalved\nineradicabilities\nineradicability\nineradicable\nineradicably\ninerrancies\ninerrancy\ninerrant\ninert\ninertia\ninertiae\ninertial\ninertially\ninertias\ninertly\ninertness\ninertnesses\ninerts\ninescapable\ninescapably\ninessential\ninessentials\ninestimable\ninestimably\ninevitabilities\ninevitability\ninevitable\ninevitableness\ninevitablenesses\ninevitably\ninexact\ninexactitude\ninexactitudes\ninexactly\ninexactness\ninexactnesses\ninexcusable\ninexcusableness\ninexcusablenesses\ninexcusably\ninexhaustibilities\ninexhaustibility\ninexhaustible\ninexhaustibleness\ninexhaustiblenesses\ninexhaustibly\ninexistence\ninexistences\ninexistent\ninexorabilities\ninexorability\ninexorable\ninexorableness\ninexorablenesses\ninexorably\ninexpedience\ninexpediences\ninexpediencies\ninexpediency\ninexpedient\ninexpediently\ninexpensive\ninexpensively\ninexpensiveness\ninexpensivenesses\ninexperience\ninexperienced\ninexperiences\ninexpert\ninexpertly\ninexpertness\ninexpertnesses\ninexperts\ninexpiable\ninexpiably\ninexplainable\ninexplicabilities\ninexplicability\ninexplicable\ninexplicableness\ninexplicablenesses\ninexplicably\ninexplicit\ninexpressibilities\ninexpressibility\ninexpressible\ninexpressibleness\ninexpressiblenesses\ninexpressibly\ninexpressive\ninexpressively\ninexpressiveness\ninexpressivenesses\ninexpugnable\ninexpugnableness\ninexpugnablenesses\ninexpugnably\ninexpungible\ninextinguishable\ninextinguishably\ninextricabilities\ninextricability\ninextricable\ninextricably\ninfall\ninfallibilities\ninfallibility\ninfallible\ninfallibly\ninfalling\ninfalls\ninfamies\ninfamous\ninfamously\ninfamy\ninfancies\ninfancy\ninfant\ninfanta\ninfantas\ninfante\ninfantes\ninfanticidal\ninfanticide\ninfanticides\ninfantile\ninfantilism\ninfantilisms\ninfantilities\ninfantility\ninfantilization\ninfantilizations\ninfantilize\ninfantilized\ninfantilizes\ninfantilizing\ninfantine\ninfantries\ninfantry\ninfantryman\ninfantrymen\ninfants\ninfarct\ninfarcted\ninfarction\ninfarctions\ninfarcts\ninfare\ninfares\ninfatuate\ninfatuated\ninfatuates\ninfatuating\ninfatuation\ninfatuations\ninfauna\ninfaunae\ninfaunal\ninfaunas\ninfeasibilities\ninfeasibility\ninfeasible\ninfect\ninfected\ninfecter\ninfecters\ninfecting\ninfection\ninfections\ninfectious\ninfectiously\ninfectiousness\ninfectiousnesses\ninfective\ninfectivities\ninfectivity\ninfector\ninfectors\ninfects\ninfecund\ninfelicities\ninfelicitous\ninfelicitously\ninfelicity\ninfeoff\ninfeoffed\ninfeoffing\ninfeoffs\ninfer\ninferable\ninference\ninferences\ninferential\ninferentially\ninferior\ninferiorities\ninferiority\ninferiorly\ninferiors\ninfernal\ninfernally\ninferno\ninfernos\ninferred\ninferrer\ninferrers\ninferrible\ninferring\ninfers\ninfertile\ninfertilities\ninfertility\ninfest\ninfestant\ninfestants\ninfestation\ninfestations\ninfested\ninfester\ninfesters\ninfesting\ninfests\ninfibulate\ninfibulated\ninfibulates\ninfibulating\ninfibulation\ninfibulations\ninfidel\ninfidelities\ninfidelity\ninfidels\ninfield\ninfielder\ninfielders\ninfields\ninfight\ninfighter\ninfighters\ninfighting\ninfightings\ninfights\ninfiltrate\ninfiltrated\ninfiltrates\ninfiltrating\ninfiltration\ninfiltrations\ninfiltrative\ninfiltrator\ninfiltrators\ninfinite\ninfinitely\ninfiniteness\ninfinitenesses\ninfinites\ninfinitesimal\ninfinitesimally\ninfinitesimals\ninfinities\ninfinitival\ninfinitive\ninfinitively\ninfinitives\ninfinitude\ninfinitudes\ninfinity\ninfirm\ninfirmaries\ninfirmary\ninfirmed\ninfirming\ninfirmities\ninfirmity\ninfirmly\ninfirms\ninfix\ninfixation\ninfixations\ninfixed\ninfixes\ninfixing\ninfixion\ninfixions\ninflame\ninflamed\ninflamer\ninflamers\ninflames\ninflaming\ninflammabilities\ninflammability\ninflammable\ninflammableness\ninflammablenesses\ninflammables\ninflammably\ninflammation\ninflammations\ninflammatorily\ninflammatory\ninflatable\ninflatables\ninflate\ninflated\ninflater\ninflaters\ninflates\ninflating\ninflation\ninflationary\ninflationism\ninflationisms\ninflationist\ninflationists\ninflations\ninflator\ninflators\ninflect\ninflectable\ninflected\ninflecting\ninflection\ninflectional\ninflectionally\ninflections\ninflective\ninflects\ninflexed\ninflexibilities\ninflexibility\ninflexible\ninflexibleness\ninflexiblenesses\ninflexibly\ninflexion\ninflexions\ninflict\ninflicted\ninflicter\ninflicters\ninflicting\ninfliction\ninflictions\ninflictive\ninflictor\ninflictors\ninflicts\ninflight\ninflorescence\ninflorescences\ninflow\ninflows\ninfluence\ninfluenceable\ninfluenced\ninfluences\ninfluencing\ninfluent\ninfluential\ninfluentially\ninfluentials\ninfluents\ninfluenza\ninfluenzal\ninfluenzas\ninflux\ninfluxes\ninfo\ninfold\ninfolded\ninfolder\ninfolders\ninfolding\ninfolds\ninfomercial\ninfomercials\ninform\ninformal\ninformalities\ninformality\ninformally\ninformant\ninformants\ninformatics\ninformation\ninformational\ninformationally\ninformations\ninformative\ninformatively\ninformativeness\ninformativenesses\ninformatorily\ninformatory\ninformed\ninformedly\ninformer\ninformers\ninforming\ninforms\ninfos\ninfotainment\ninfotainments\ninfought\ninfra\ninfract\ninfracted\ninfracting\ninfraction\ninfractions\ninfracts\ninfrahuman\ninfrahumans\ninfrangibilities\ninfrangibility\ninfrangible\ninfrangibly\ninfrared\ninfrareds\ninfrasonic\ninfraspecific\ninfrastructure\ninfrastructures\ninfrequence\ninfrequences\ninfrequencies\ninfrequency\ninfrequent\ninfrequently\ninfringe\ninfringed\ninfringement\ninfringements\ninfringer\ninfringers\ninfringes\ninfringing\ninfrugal\ninfundibula\ninfundibular\ninfundibuliform\ninfundibulum\ninfuriate\ninfuriated\ninfuriates\ninfuriating\ninfuriatingly\ninfuriation\ninfuriations\ninfuse\ninfused\ninfuser\ninfusers\ninfuses\ninfusibilities\ninfusibility\ninfusible\ninfusibleness\ninfusiblenesses\ninfusing\ninfusion\ninfusions\ninfusive\ninfusorian\ninfusorians\ningate\ningates\ningather\ningathered\ningathering\ningatherings\ningathers\ningenious\ningeniously\ningeniousness\ningeniousnesses\ningenue\ningenues\ningenuities\ningenuity\ningenuous\ningenuously\ningenuousness\ningenuousnesses\ningest\ningesta\ningested\ningestible\ningesting\ningestion\ningestions\ningestive\ningests\ningle\ninglenook\ninglenooks\ningles\ninglorious\ningloriously\ningloriousness\ningloriousnesses\ningoing\ningot\ningoted\ningoting\ningots\ningraft\ningrafted\ningrafting\ningrafts\ningrain\ningrained\ningrainedly\ningraining\ningrains\ningrate\ningrates\ningratiate\ningratiated\ningratiates\ningratiating\ningratiatingly\ningratiation\ningratiations\ningratiatory\ningratitude\ningratitudes\ningredient\ningredients\ningress\ningresses\ningression\ningressions\ningressive\ningressiveness\ningressivenesses\ningressives\ningroup\ningroups\ningrowing\ningrown\ningrownness\ningrownnesses\ningrowth\ningrowths\ninguinal\ningulf\ningulfed\ningulfing\ningulfs\ningurgitate\ningurgitated\ningurgitates\ningurgitating\ningurgitation\ningurgitations\ninhabit\ninhabitable\ninhabitancies\ninhabitancy\ninhabitant\ninhabitants\ninhabitation\ninhabitations\ninhabited\ninhabiter\ninhabiters\ninhabiting\ninhabits\ninhalant\ninhalants\ninhalation\ninhalational\ninhalations\ninhalator\ninhalators\ninhale\ninhaled\ninhaler\ninhalers\ninhales\ninhaling\ninharmonic\ninharmonies\ninharmonious\ninharmoniously\ninharmoniousness\ninharmoniousnesses\ninharmony\ninhaul\ninhauler\ninhaulers\ninhauls\ninhere\ninhered\ninherence\ninherences\ninherent\ninherently\ninheres\ninhering\ninherit\ninheritabilities\ninheritability\ninheritable\ninheritableness\ninheritablenesses\ninheritance\ninheritances\ninherited\ninheriting\ninheritor\ninheritors\ninheritress\ninheritresses\ninheritrices\ninheritrix\ninheritrixes\ninherits\ninhesion\ninhesions\ninhibin\ninhibins\ninhibit\ninhibited\ninhibiting\ninhibition\ninhibitions\ninhibitive\ninhibitor\ninhibitors\ninhibitory\ninhibits\ninholding\ninholdings\ninhomogeneities\ninhomogeneity\ninhomogeneous\ninhospitable\ninhospitableness\ninhospitablenesses\ninhospitably\ninhospitalities\ninhospitality\ninhuman\ninhumane\ninhumanely\ninhumanities\ninhumanity\ninhumanly\ninhumanness\ninhumannesses\ninhumation\ninhumations\ninhume\ninhumed\ninhumer\ninhumers\ninhumes\ninhuming\ninia\ninimical\ninimically\ninimitable\ninimitableness\ninimitablenesses\ninimitably\ninion\ninions\niniquities\niniquitous\niniquitously\niniquitousness\niniquitousnesses\niniquity\ninitial\ninitialed\ninitialing\ninitialism\ninitialisms\ninitialization\ninitializations\ninitialize\ninitialized\ninitializes\ninitializing\ninitialled\ninitialling\ninitially\ninitialness\ninitialnesses\ninitials\ninitiate\ninitiated\ninitiates\ninitiating\ninitiation\ninitiations\ninitiative\ninitiatives\ninitiator\ninitiators\ninitiatory\ninject\ninjectable\ninjectables\ninjectant\ninjectants\ninjected\ninjecting\ninjection\ninjections\ninjective\ninjector\ninjectors\ninjects\ninjudicious\ninjudiciously\ninjudiciousness\ninjudiciousnesses\ninjunction\ninjunctions\ninjunctive\ninjure\ninjured\ninjurer\ninjurers\ninjures\ninjuries\ninjuring\ninjurious\ninjuriously\ninjuriousness\ninjuriousnesses\ninjury\ninjustice\ninjustices\nink\ninkberries\ninkberry\ninkblot\ninkblots\ninked\ninker\ninkers\ninkhorn\ninkhorns\ninkier\ninkiest\ninkiness\ninkinesses\ninking\ninkjet\ninkle\ninkles\ninkless\ninklike\ninkling\ninklings\ninkpot\ninkpots\ninks\ninkstand\ninkstands\ninkstone\ninkstones\ninkwell\ninkwells\ninkwood\ninkwoods\ninky\ninlace\ninlaced\ninlaces\ninlacing\ninlaid\ninland\ninlander\ninlanders\ninlands\ninlay\ninlayer\ninlayers\ninlaying\ninlays\ninlet\ninlets\ninletting\ninlier\ninliers\ninly\ninmate\ninmates\ninmesh\ninmeshed\ninmeshes\ninmeshing\ninmost\ninn\ninnards\ninnate\ninnately\ninnateness\ninnatenesses\ninned\ninner\ninnerly\ninnermost\ninnermosts\ninners\ninnersole\ninnersoles\ninnerspring\ninnervate\ninnervated\ninnervates\ninnervating\ninnervation\ninnervations\ninnerve\ninnerved\ninnerves\ninnerving\ninning\ninnings\ninnkeeper\ninnkeepers\ninnless\ninnocence\ninnocences\ninnocencies\ninnocency\ninnocent\ninnocenter\ninnocentest\ninnocently\ninnocents\ninnocuous\ninnocuously\ninnocuousness\ninnocuousnesses\ninnominate\ninnovate\ninnovated\ninnovates\ninnovating\ninnovation\ninnovational\ninnovations\ninnovative\ninnovatively\ninnovativeness\ninnovativenesses\ninnovator\ninnovators\ninnovatory\ninns\ninnuendo\ninnuendoed\ninnuendoes\ninnuendoing\ninnuendos\ninnumerable\ninnumerably\ninnumeracies\ninnumeracy\ninnumerate\ninnumerates\ninnumerous\ninobservance\ninobservances\ninobservant\ninocula\ninoculant\ninoculants\ninoculate\ninoculated\ninoculates\ninoculating\ninoculation\ninoculations\ninoculative\ninoculator\ninoculators\ninoculum\ninoculums\ninoffensive\ninoffensively\ninoffensiveness\ninoffensivenesses\ninoperable\ninoperative\ninoperativeness\ninoperativenesses\ninoperculate\ninoperculates\ninopportune\ninopportunely\ninopportuneness\ninopportunenesses\ninordinate\ninordinately\ninordinateness\ninordinatenesses\ninorganic\ninorganically\ninosculate\ninosculated\ninosculates\ninosculating\ninosculation\ninosculations\ninosite\ninosites\ninositol\ninositols\ninotropic\ninpatient\ninpatients\ninphase\ninpour\ninpoured\ninpouring\ninpourings\ninpours\ninput\ninputs\ninputted\ninputting\ninquest\ninquests\ninquiet\ninquieted\ninquieting\ninquiets\ninquietude\ninquietudes\ninquiline\ninquilines\ninquire\ninquired\ninquirer\ninquirers\ninquires\ninquiries\ninquiring\ninquiringly\ninquiry\ninquisition\ninquisitional\ninquisitions\ninquisitive\ninquisitively\ninquisitiveness\ninquisitivenesses\ninquisitor\ninquisitorial\ninquisitorially\ninquisitors\ninro\ninroad\ninroads\ninrush\ninrushes\nins\ninsalubrious\ninsalubrities\ninsalubrity\ninsane\ninsanely\ninsaneness\ninsanenesses\ninsaner\ninsanest\ninsanitary\ninsanitation\ninsanitations\ninsanities\ninsanity\ninsatiabilities\ninsatiability\ninsatiable\ninsatiableness\ninsatiablenesses\ninsatiably\ninsatiate\ninsatiately\ninsatiateness\ninsatiatenesses\ninscape\ninscapes\ninscribe\ninscribed\ninscriber\ninscribers\ninscribes\ninscribing\ninscription\ninscriptional\ninscriptions\ninscriptive\ninscriptively\ninscroll\ninscrolled\ninscrolling\ninscrolls\ninscrutabilities\ninscrutability\ninscrutable\ninscrutableness\ninscrutablenesses\ninscrutably\ninsculp\ninsculped\ninsculping\ninsculps\ninseam\ninseams\ninsect\ninsectan\ninsectaries\ninsectary\ninsecticidal\ninsecticidally\ninsecticide\ninsecticides\ninsectile\ninsectivore\ninsectivores\ninsectivorous\ninsects\ninsecure\ninsecurely\ninsecureness\ninsecurenesses\ninsecurities\ninsecurity\ninselberg\ninselberge\ninselbergs\ninseminate\ninseminated\ninseminates\ninseminating\ninsemination\ninseminations\ninseminator\ninseminators\ninsensate\ninsensately\ninsensibilities\ninsensibility\ninsensible\ninsensibleness\ninsensiblenesses\ninsensibly\ninsensitive\ninsensitively\ninsensitiveness\ninsensitivenesses\ninsensitivities\ninsensitivity\ninsentience\ninsentiences\ninsentient\ninseparabilities\ninseparability\ninseparable\ninseparableness\ninseparablenesses\ninseparables\ninseparably\ninsert\ninserted\ninserter\ninserters\ninserting\ninsertion\ninsertional\ninsertions\ninserts\ninset\ninsets\ninsetted\ninsetter\ninsetters\ninsetting\ninsheath\ninsheathed\ninsheathing\ninsheaths\ninshore\ninshrine\ninshrined\ninshrines\ninshrining\ninside\ninsider\ninsiders\ninsides\ninsidious\ninsidiously\ninsidiousness\ninsidiousnesses\ninsight\ninsightful\ninsightfully\ninsights\ninsigne\ninsignia\ninsignias\ninsignificance\ninsignificances\ninsignificancies\ninsignificancy\ninsignificant\ninsignificantly\ninsincere\ninsincerely\ninsincerities\ninsincerity\ninsinuate\ninsinuated\ninsinuates\ninsinuating\ninsinuatingly\ninsinuation\ninsinuations\ninsinuative\ninsinuator\ninsinuators\ninsipid\ninsipidities\ninsipidity\ninsipidly\ninsist\ninsisted\ninsistence\ninsistences\ninsistencies\ninsistency\ninsistent\ninsistently\ninsister\ninsisters\ninsisting\ninsists\ninsnare\ninsnared\ninsnarer\ninsnarers\ninsnares\ninsnaring\ninsobrieties\ninsobriety\ninsociabilities\ninsociability\ninsociable\ninsociably\ninsofar\ninsolate\ninsolated\ninsolates\ninsolating\ninsolation\ninsolations\ninsole\ninsolence\ninsolences\ninsolent\ninsolently\ninsolents\ninsoles\ninsolubilities\ninsolubility\ninsolubilization\ninsolubilizations\ninsolubilize\ninsolubilized\ninsolubilizes\ninsolubilizing\ninsoluble\ninsolubleness\ninsolublenesses\ninsolubles\ninsolubly\ninsolvable\ninsolvably\ninsolvencies\ninsolvency\ninsolvent\ninsolvents\ninsomnia\ninsomniac\ninsomniacs\ninsomnias\ninsomuch\ninsouciance\ninsouciances\ninsouciant\ninsouciantly\ninsoul\ninsouled\ninsouling\ninsouls\ninspan\ninspanned\ninspanning\ninspans\ninspect\ninspected\ninspecting\ninspection\ninspections\ninspective\ninspector\ninspectorate\ninspectorates\ninspectors\ninspectorship\ninspectorships\ninspects\ninsphere\ninsphered\ninspheres\ninsphering\ninspiration\ninspirational\ninspirationally\ninspirations\ninspirator\ninspirators\ninspiratory\ninspire\ninspired\ninspirer\ninspirers\ninspires\ninspiring\ninspiringly\ninspirit\ninspirited\ninspiriting\ninspiritingly\ninspirits\ninspissate\ninspissated\ninspissates\ninspissating\ninspissation\ninspissations\ninspissator\ninspissators\ninstabilities\ninstability\ninstable\ninstal\ninstall\ninstallation\ninstallations\ninstalled\ninstaller\ninstallers\ninstalling\ninstallment\ninstallments\ninstalls\ninstalment\ninstalments\ninstals\ninstance\ninstanced\ninstances\ninstancies\ninstancing\ninstancy\ninstant\ninstantaneities\ninstantaneity\ninstantaneous\ninstantaneously\ninstantaneousness\ninstantaneousnesses\ninstanter\ninstantiate\ninstantiated\ninstantiates\ninstantiating\ninstantiation\ninstantiations\ninstantly\ninstantness\ninstantnesses\ninstants\ninstar\ninstarred\ninstarring\ninstars\ninstate\ninstated\ninstates\ninstating\ninstauration\ninstaurations\ninstead\ninstep\ninsteps\ninstigate\ninstigated\ninstigates\ninstigating\ninstigation\ninstigations\ninstigative\ninstigator\ninstigators\ninstil\ninstill\ninstillation\ninstillations\ninstilled\ninstiller\ninstillers\ninstilling\ninstillment\ninstillments\ninstills\ninstils\ninstinct\ninstinctive\ninstinctively\ninstincts\ninstinctual\ninstinctually\ninstitute\ninstituted\ninstituter\ninstituters\ninstitutes\ninstituting\ninstitution\ninstitutional\ninstitutionalise\ninstitutionalised\ninstitutionalises\ninstitutionalising\ninstitutionalism\ninstitutionalisms\ninstitutionalist\ninstitutionalists\ninstitutionalization\ninstitutionalizations\ninstitutionalize\ninstitutionalized\ninstitutionalizes\ninstitutionalizing\ninstitutionally\ninstitutions\ninstitutor\ninstitutors\ninstroke\ninstrokes\ninstruct\ninstructed\ninstructing\ninstruction\ninstructional\ninstructions\ninstructive\ninstructively\ninstructiveness\ninstructivenesses\ninstructor\ninstructors\ninstructorship\ninstructorships\ninstructress\ninstructresses\ninstructs\ninstrument\ninstrumental\ninstrumentalism\ninstrumentalisms\ninstrumentalist\ninstrumentalists\ninstrumentalities\ninstrumentality\ninstrumentally\ninstrumentals\ninstrumentation\ninstrumentations\ninstrumented\ninstrumenting\ninstruments\ninsubordinate\ninsubordinately\ninsubordinates\ninsubordination\ninsubordinations\ninsubstantial\ninsubstantialities\ninsubstantiality\ninsufferable\ninsufferableness\ninsufferablenesses\ninsufferably\ninsufficiencies\ninsufficiency\ninsufficient\ninsufficiently\ninsufflate\ninsufflated\ninsufflates\ninsufflating\ninsufflation\ninsufflations\ninsufflator\ninsufflators\ninsulant\ninsulants\ninsular\ninsularism\ninsularisms\ninsularities\ninsularity\ninsularly\ninsulars\ninsulate\ninsulated\ninsulates\ninsulating\ninsulation\ninsulations\ninsulator\ninsulators\ninsulin\ninsulins\ninsult\ninsulted\ninsulter\ninsulters\ninsulting\ninsultingly\ninsults\ninsuperable\ninsuperably\ninsupportable\ninsupportably\ninsuppressible\ninsurabilities\ninsurability\ninsurable\ninsurance\ninsurances\ninsurant\ninsurants\ninsure\ninsured\ninsureds\ninsurer\ninsurers\ninsures\ninsurgence\ninsurgences\ninsurgencies\ninsurgency\ninsurgent\ninsurgently\ninsurgents\ninsuring\ninsurmountable\ninsurmountably\ninsurrection\ninsurrectional\ninsurrectionaries\ninsurrectionary\ninsurrectionist\ninsurrectionists\ninsurrections\ninsusceptibilities\ninsusceptibility\ninsusceptible\ninsusceptibly\ninswathe\ninswathed\ninswathes\ninswathing\ninswept\nintact\nintactness\nintactnesses\nintagli\nintaglio\nintaglioed\nintaglioing\nintaglios\nintake\nintakes\nintangibilities\nintangibility\nintangible\nintangibleness\nintangiblenesses\nintangibles\nintangibly\nintarsia\nintarsias\ninteger\nintegers\nintegrabilities\nintegrability\nintegrable\nintegral\nintegralities\nintegrality\nintegrally\nintegrals\nintegrand\nintegrands\nintegrate\nintegrated\nintegrates\nintegrating\nintegration\nintegrationist\nintegrationists\nintegrations\nintegrative\nintegrator\nintegrators\nintegrities\nintegrity\nintegument\nintegumentary\ninteguments\nintellect\nintellection\nintellections\nintellective\nintellectively\nintellects\nintellectual\nintellectualism\nintellectualisms\nintellectualist\nintellectualistic\nintellectualists\nintellectualities\nintellectuality\nintellectualization\nintellectualizations\nintellectualize\nintellectualized\nintellectualizer\nintellectualizers\nintellectualizes\nintellectualizing\nintellectually\nintellectualness\nintellectualnesses\nintellectuals\nintelligence\nintelligencer\nintelligencers\nintelligences\nintelligent\nintelligential\nintelligently\nintelligentsia\nintelligentsias\nintelligibilities\nintelligibility\nintelligible\nintelligibleness\nintelligiblenesses\nintelligibly\nintemperance\nintemperances\nintemperate\nintemperately\nintemperateness\nintemperatenesses\nintend\nintendance\nintendances\nintendant\nintendants\nintended\nintendedly\nintendeds\nintender\nintenders\nintending\nintendment\nintendments\nintends\nintenerate\nintenerated\nintenerates\nintenerating\ninteneration\nintenerations\nintense\nintensely\nintenseness\nintensenesses\nintenser\nintensest\nintensification\nintensifications\nintensified\nintensifier\nintensifiers\nintensifies\nintensify\nintensifying\nintension\nintensional\nintensionalities\nintensionality\nintensionally\nintensions\nintensities\nintensity\nintensive\nintensively\nintensiveness\nintensivenesses\nintensives\nintent\nintention\nintentional\nintentionalities\nintentionality\nintentionally\nintentions\nintently\nintentness\nintentnesses\nintents\ninter\ninterabang\ninterabangs\ninteract\ninteractant\ninteractants\ninteracted\ninteracting\ninteraction\ninteractional\ninteractions\ninteractive\ninteractively\ninteracts\ninterage\ninteragency\ninterallelic\ninterallied\ninteranimation\ninteranimations\ninterannual\ninterassociation\ninterassociations\ninteratomic\ninteravailabilities\ninteravailability\ninterbank\ninterbasin\ninterbed\ninterbedded\ninterbedding\ninterbeds\ninterbehavior\ninterbehavioral\ninterbehaviors\ninterborough\ninterboroughs\ninterbranch\ninterbred\ninterbreed\ninterbreeding\ninterbreeds\nintercalary\nintercalate\nintercalated\nintercalates\nintercalating\nintercalation\nintercalations\nintercalibration\nintercalibrations\nintercampus\nintercaste\nintercede\ninterceded\ninterceder\ninterceders\nintercedes\ninterceding\nintercell\nintercellular\nintercensal\nintercept\nintercepted\nintercepter\nintercepters\nintercepting\ninterception\ninterceptions\ninterceptor\ninterceptors\nintercepts\nintercession\nintercessional\nintercessions\nintercessor\nintercessors\nintercessory\ninterchain\ninterchained\ninterchaining\ninterchains\ninterchange\ninterchangeabilities\ninterchangeability\ninterchangeable\ninterchangeableness\ninterchangeablenesses\ninterchangeably\ninterchanged\ninterchanger\ninterchangers\ninterchanges\ninterchanging\ninterchannel\ninterchromosomal\ninterchurch\nintercity\ninterclan\ninterclass\ninterclub\nintercluster\nintercoastal\nintercollegiate\nintercolonial\nintercolumniation\nintercolumniations\nintercom\nintercommunal\nintercommunicate\nintercommunicated\nintercommunicates\nintercommunicating\nintercommunication\nintercommunications\nintercommunion\nintercommunions\nintercommunities\nintercommunity\nintercompany\nintercompare\nintercompared\nintercompares\nintercomparing\nintercomparison\nintercomparisons\nintercomprehensibilities\nintercomprehensibility\nintercoms\ninterconnect\ninterconnected\ninterconnectedness\ninterconnectednesses\ninterconnecting\ninterconnection\ninterconnections\ninterconnects\nintercontinental\ninterconversion\ninterconversions\ninterconvert\ninterconverted\ninterconvertibilities\ninterconvertibility\ninterconvertible\ninterconverting\ninterconverts\nintercooler\nintercoolers\nintercorporate\nintercorrelate\nintercorrelated\nintercorrelates\nintercorrelating\nintercorrelation\nintercorrelations\nintercortical\nintercostal\nintercostals\nintercountry\nintercounty\nintercouple\nintercourse\nintercourses\nintercrater\nintercrop\nintercropped\nintercropping\nintercrops\nintercross\nintercrossed\nintercrosses\nintercrossing\nintercrystalline\nintercultural\ninterculturally\ninterculture\nintercultures\nintercurrent\nintercut\nintercuts\nintercutting\ninterdealer\ninterdealers\ninterdenominational\ninterdental\ninterdentally\ninterdepartmental\ninterdepartmentally\ninterdepend\ninterdepended\ninterdependence\ninterdependences\ninterdependencies\ninterdependency\ninterdependent\ninterdependently\ninterdepending\ninterdepends\ninterdialectal\ninterdict\ninterdicted\ninterdicting\ninterdiction\ninterdictions\ninterdictive\ninterdictor\ninterdictors\ninterdictory\ninterdicts\ninterdiffuse\ninterdiffused\ninterdiffuses\ninterdiffusing\ninterdiffusion\ninterdiffusions\ninterdigitate\ninterdigitated\ninterdigitates\ninterdigitating\ninterdigitation\ninterdigitations\ninterdisciplinary\ninterdistrict\ninterdivisional\ninterdominion\ninterelectrode\ninterelectrodes\ninterelectron\ninterelectronic\ninterepidemic\ninterest\ninterested\ninterestedly\ninteresting\ninterestingly\ninterestingness\ninterestingnesses\ninterests\ninterethnic\ninterface\ninterfaced\ninterfaces\ninterfacial\ninterfacing\ninterfacings\ninterfaculties\ninterfaculty\ninterfaith\ninterfamilial\ninterfamily\ninterfere\ninterfered\ninterference\ninterferences\ninterferential\ninterferer\ninterferers\ninterferes\ninterfering\ninterferogram\ninterferograms\ninterferometer\ninterferometers\ninterferometric\ninterferometrically\ninterferometries\ninterferometry\ninterferon\ninterferons\ninterfertile\ninterfertilities\ninterfertility\ninterfiber\ninterfile\ninterfiled\ninterfiles\ninterfiling\ninterfirm\ninterflow\ninterfluve\ninterfluves\ninterfluvial\ninterfold\ninterfolded\ninterfolding\ninterfolds\ninterfraternity\ninterfuse\ninterfused\ninterfuses\ninterfusing\ninterfusion\ninterfusions\nintergalactic\nintergang\nintergeneration\nintergenerational\nintergenerations\nintergeneric\ninterglacial\ninterglacials\nintergovernmental\nintergradation\nintergradational\nintergradations\nintergrade\nintergraded\nintergrades\nintergrading\nintergraft\nintergrafted\nintergrafting\nintergrafts\nintergranular\nintergroup\nintergrowth\nintergrowths\ninterhemispheric\ninterim\ninterims\ninterindividual\ninterindustry\ninterinfluence\ninterinfluenced\ninterinfluences\ninterinfluencing\ninterinstitutional\ninterinvolve\ninterinvolved\ninterinvolves\ninterinvolving\ninterionic\ninterior\ninteriorise\ninteriorised\ninteriorises\ninteriorising\ninteriorities\ninteriority\ninteriorization\ninteriorizations\ninteriorize\ninteriorized\ninteriorizes\ninteriorizing\ninteriorly\ninteriors\ninterisland\ninterject\ninterjected\ninterjecting\ninterjection\ninterjectional\ninterjectionally\ninterjections\ninterjector\ninterjectors\ninterjectory\ninterjects\ninterjurisdictional\ninterknit\ninterknits\ninterknitted\ninterknitting\ninterlace\ninterlaced\ninterlacement\ninterlacements\ninterlaces\ninterlacing\ninterlacustrine\ninterlaid\ninterlaminar\ninterlap\ninterlapped\ninterlapping\ninterlaps\ninterlard\ninterlarded\ninterlarding\ninterlards\ninterlay\ninterlayer\ninterlayered\ninterlayering\ninterlayers\ninterlaying\ninterlays\ninterleave\ninterleaved\ninterleaves\ninterleaving\ninterlend\ninterlending\ninterlends\ninterlent\ninterleukin\ninterleukins\ninterlibrary\ninterline\ninterlinear\ninterlinearly\ninterlinears\ninterlineation\ninterlineations\ninterlined\ninterliner\ninterliners\ninterlines\ninterlining\ninterlinings\ninterlink\ninterlinked\ninterlinking\ninterlinks\ninterlobular\ninterlocal\ninterlock\ninterlocked\ninterlocking\ninterlocks\ninterlocutor\ninterlocutors\ninterlocutory\ninterlope\ninterloped\ninterloper\ninterlopers\ninterlopes\ninterloping\ninterlude\ninterludes\ninterlunar\ninterlunary\nintermale\nintermarginal\nintermarriage\nintermarriages\nintermarried\nintermarries\nintermarry\nintermarrying\nintermeddle\nintermeddled\nintermeddler\nintermeddlers\nintermeddles\nintermeddling\nintermediacies\nintermediacy\nintermediaries\nintermediary\nintermediate\nintermediated\nintermediately\nintermediateness\nintermediatenesses\nintermediates\nintermediating\nintermediation\nintermediations\nintermedin\nintermedins\nintermembrane\nintermenstrual\ninterment\ninterments\nintermesh\nintermeshed\nintermeshes\nintermeshing\nintermetallic\nintermetallics\nintermezzi\nintermezzo\nintermezzos\ninterminable\ninterminableness\ninterminablenesses\ninterminably\nintermingle\nintermingled\nintermingles\nintermingling\ninterministerial\nintermission\nintermissionless\nintermissions\nintermit\nintermitotic\nintermits\nintermitted\nintermittence\nintermittences\nintermittencies\nintermittency\nintermittent\nintermittently\nintermitter\nintermitters\nintermitting\nintermix\nintermixed\nintermixes\nintermixing\nintermixture\nintermixtures\nintermodal\nintermodulation\nintermodulations\nintermolecular\nintermolecularly\nintermont\nintermontane\nintermountain\nintermural\nintern\ninternal\ninternalise\ninternalised\ninternalises\ninternalising\ninternalities\ninternality\ninternalization\ninternalizations\ninternalize\ninternalized\ninternalizes\ninternalizing\ninternally\ninternals\ninternational\ninternationalise\ninternationalised\ninternationalises\ninternationalising\ninternationalism\ninternationalisms\ninternationalist\ninternationalists\ninternationalities\ninternationality\ninternationalization\ninternationalizations\ninternationalize\ninternationalized\ninternationalizes\ninternationalizing\ninternationally\ninternationals\ninterne\ninternecine\ninterned\ninternee\ninternees\ninternes\ninterneuron\ninterneuronal\ninterneurons\ninterning\ninternist\ninternists\ninternment\ninternments\ninternodal\ninternode\ninternodes\ninterns\ninternship\ninternships\ninternuclear\ninternucleon\ninternucleonic\ninternucleotide\ninternuncial\ninternuncio\ninternuncios\ninterobserver\ninterobservers\ninterocean\ninteroceanic\ninteroceptive\ninteroceptor\ninteroceptors\ninteroffice\ninteroperabilities\ninteroperability\ninteroperable\ninteroperative\ninteroperatives\ninterorbital\ninterorgan\ninterorganizational\ninterpandemic\ninterparish\ninterparochial\ninterparoxysmal\ninterparticle\ninterparty\ninterpellate\ninterpellated\ninterpellates\ninterpellating\ninterpellation\ninterpellations\ninterpellator\ninterpellators\ninterpenetrate\ninterpenetrated\ninterpenetrates\ninterpenetrating\ninterpenetration\ninterpenetrations\ninterperceptual\ninterpermeate\ninterpermeated\ninterpermeates\ninterpermeating\ninterpersonal\ninterpersonally\ninterphalangeal\ninterphase\ninterphases\ninterplanetary\ninterplant\ninterplanted\ninterplanting\ninterplants\ninterplay\ninterplayed\ninterplaying\ninterplays\ninterplead\ninterpleaded\ninterpleader\ninterpleaders\ninterpleading\ninterpleads\ninterpled\ninterpluvial\ninterpoint\ninterpoints\ninterpolate\ninterpolated\ninterpolates\ninterpolating\ninterpolation\ninterpolations\ninterpolative\ninterpolator\ninterpolators\ninterpopulation\ninterpopulational\ninterpose\ninterposed\ninterposer\ninterposers\ninterposes\ninterposing\ninterposition\ninterpositions\ninterpret\ninterpretabilities\ninterpretability\ninterpretable\ninterpretation\ninterpretational\ninterpretations\ninterpretative\ninterpretatively\ninterpreted\ninterpreter\ninterpreters\ninterpreting\ninterpretive\ninterpretively\ninterprets\ninterprofessional\ninterprovincial\ninterproximal\ninterpsychic\ninterpupillary\ninterracial\ninterracially\ninterred\ninterreges\ninterregional\ninterregna\ninterregnum\ninterregnums\ninterrelate\ninterrelated\ninterrelatedly\ninterrelatedness\ninterrelatednesses\ninterrelates\ninterrelating\ninterrelation\ninterrelations\ninterrelationship\ninterrelationships\ninterreligious\ninterrenal\ninterrex\ninterring\ninterrobang\ninterrobangs\ninterrogate\ninterrogated\ninterrogatee\ninterrogatees\ninterrogates\ninterrogating\ninterrogation\ninterrogational\ninterrogations\ninterrogative\ninterrogatively\ninterrogatives\ninterrogator\ninterrogatories\ninterrogators\ninterrogatory\ninterrogee\ninterrogees\ninterrow\ninterrupt\ninterrupted\ninterrupter\ninterrupters\ninterruptible\ninterrupting\ninterruption\ninterruptions\ninterruptive\ninterruptor\ninterruptors\ninterrupts\ninters\ninterscholastic\ninterschool\ninterschools\nintersect\nintersected\nintersecting\nintersection\nintersectional\nintersections\nintersects\nintersegment\nintersegmental\nintersegments\nintersensory\ninterservice\nintersession\nintersessions\nintersex\nintersexes\nintersexual\nintersexualities\nintersexuality\nintersexually\nintersocietal\nintersociety\ninterspace\ninterspaced\ninterspaces\ninterspacing\ninterspecies\ninterspecific\nintersperse\ninterspersed\nintersperses\ninterspersing\ninterspersion\ninterspersions\ninterstadial\ninterstadials\ninterstage\ninterstate\ninterstates\ninterstation\ninterstellar\nintersterile\nintersterilities\nintersterility\ninterstice\ninterstices\ninterstimulation\ninterstimulations\ninterstimuli\ninterstimulus\ninterstitial\ninterstitially\ninterstrain\ninterstrains\ninterstrand\ninterstrands\ninterstratification\ninterstratifications\ninterstratified\ninterstratifies\ninterstratify\ninterstratifying\nintersubjective\nintersubjectively\nintersubjectivities\nintersubjectivity\nintersubstitutabilities\nintersubstitutability\nintersubstitutable\nintersystem\ninterterm\ninterterminal\ninterterritorial\nintertestamental\nintertextual\nintertextualities\nintertextuality\nintertextually\nintertidal\nintertidally\nintertie\ninterties\nintertill\nintertillage\nintertillages\nintertilled\nintertilling\nintertills\nintertranslatable\nintertrial\nintertribal\nintertroop\nintertropical\nintertwine\nintertwined\nintertwinement\nintertwinements\nintertwines\nintertwining\nintertwist\nintertwisted\nintertwisting\nintertwists\ninterunion\ninterunions\ninterunit\ninteruniversity\ninterurban\ninterurbans\ninterval\nintervale\nintervales\nintervalley\nintervalleys\nintervallic\nintervalometer\nintervalometers\nintervals\nintervene\nintervened\nintervener\ninterveners\nintervenes\nintervening\nintervenor\nintervenors\nintervention\ninterventionism\ninterventionisms\ninterventionist\ninterventionists\ninterventions\ninterventricular\nintervertebral\ninterview\ninterviewed\ninterviewee\ninterviewees\ninterviewer\ninterviewers\ninterviewing\ninterviews\nintervillage\nintervisibilities\nintervisibility\nintervisible\nintervisitation\nintervisitations\nintervocalic\nintervocalically\ninterwar\ninterweave\ninterweaved\ninterweaves\ninterweaving\ninterwork\ninterworked\ninterworking\ninterworkings\ninterworks\ninterwove\ninterwoven\ninterwrought\ninterzonal\ninterzone\nintestacies\nintestacy\nintestate\nintestates\nintestinal\nintestinally\nintestine\nintestines\ninthral\ninthrall\ninthralled\ninthralling\ninthralls\ninthrals\ninthrone\ninthroned\ninthrones\ninthroning\ninti\nintima\nintimacies\nintimacy\nintimae\nintimal\nintimas\nintimate\nintimated\nintimately\nintimateness\nintimatenesses\nintimater\nintimaters\nintimates\nintimating\nintimation\nintimations\nintime\nintimidate\nintimidated\nintimidates\nintimidating\nintimidatingly\nintimidation\nintimidations\nintimidator\nintimidators\nintimidatory\nintimist\nintimists\nintinction\nintinctions\nintine\nintines\nintis\nintitle\nintitled\nintitles\nintitling\nintitule\nintituled\nintitules\nintituling\ninto\nintolerabilities\nintolerability\nintolerable\nintolerableness\nintolerablenesses\nintolerably\nintolerance\nintolerances\nintolerant\nintolerantly\nintolerantness\nintolerantnesses\nintomb\nintombed\nintombing\nintombs\nintonate\nintonated\nintonates\nintonating\nintonation\nintonational\nintonations\nintone\nintoned\nintoner\nintoners\nintones\nintoning\nintort\nintorted\nintorting\nintorts\nintown\nintoxicant\nintoxicants\nintoxicate\nintoxicated\nintoxicatedly\nintoxicates\nintoxicating\nintoxication\nintoxications\nintracardiac\nintracardial\nintracardially\nintracellular\nintracellularly\nintracerebral\nintracerebrally\nintracompany\nintracranial\nintracranially\nintractabilities\nintractability\nintractable\nintractably\nintracutaneous\nintracutaneously\nintraday\nintradermal\nintradermally\nintrados\nintradoses\nintragalactic\nintragenic\nintramolecular\nintramolecularly\nintramural\nintramurally\nintramuscular\nintramuscularly\nintranasal\nintranasally\nintranet\nintranets\nintransigeance\nintransigeances\nintransigeant\nintransigeantly\nintransigeants\nintransigence\nintransigences\nintransigent\nintransigently\nintransigents\nintransitive\nintransitively\nintransitiveness\nintransitivenesses\nintransitivities\nintransitivity\nintrant\nintrants\nintraocular\nintraocularly\nintraperitoneal\nintraperitoneally\nintrapersonal\nintraplate\nintrapopulation\nintrapreneur\nintrapreneurial\nintrapreneurs\nintrapsychic\nintrapsychically\nintraspecies\nintraspecific\nintrastate\nintrathecal\nintrathecally\nintrathoracic\nintrathoracically\nintrauterine\nintravascular\nintravascularly\nintravenous\nintravenouses\nintravenously\nintraventricular\nintraventricularly\nintravital\nintravitally\nintravitam\nintrazonal\nintreat\nintreated\nintreating\nintreats\nintrench\nintrenched\nintrenches\nintrenching\nintrepid\nintrepidities\nintrepidity\nintrepidly\nintrepidness\nintrepidnesses\nintricacies\nintricacy\nintricate\nintricately\nintricateness\nintricatenesses\nintrigant\nintrigants\nintriguant\nintriguants\nintrigue\nintrigued\nintriguer\nintriguers\nintrigues\nintriguing\nintriguingly\nintrinsic\nintrinsical\nintrinsically\nintro\nintroduce\nintroduced\nintroducer\nintroducers\nintroduces\nintroducing\nintroduction\nintroductions\nintroductorily\nintroductory\nintrofied\nintrofies\nintrofy\nintrofying\nintrogressant\nintrogressants\nintrogression\nintrogressions\nintrogressive\nintroit\nintroits\nintroject\nintrojected\nintrojecting\nintrojection\nintrojections\nintrojects\nintromission\nintromissions\nintromit\nintromits\nintromitted\nintromittent\nintromitter\nintromitters\nintromitting\nintron\nintrons\nintrorse\nintros\nintrospect\nintrospected\nintrospecting\nintrospection\nintrospectional\nintrospectionism\nintrospectionisms\nintrospectionist\nintrospectionistic\nintrospectionists\nintrospections\nintrospective\nintrospectively\nintrospectiveness\nintrospectivenesses\nintrospects\nintroversion\nintroversions\nintroversive\nintroversively\nintrovert\nintroverted\nintroverting\nintroverts\nintrude\nintruded\nintruder\nintruders\nintrudes\nintruding\nintrusion\nintrusions\nintrusive\nintrusively\nintrusiveness\nintrusivenesses\nintrusives\nintrust\nintrusted\nintrusting\nintrusts\nintubate\nintubated\nintubates\nintubating\nintubation\nintubations\nintuit\nintuitable\nintuited\nintuiting\nintuition\nintuitional\nintuitionism\nintuitionisms\nintuitionist\nintuitionists\nintuitions\nintuitive\nintuitively\nintuitiveness\nintuitivenesses\nintuits\nintumescence\nintumescences\nintumescent\ninturn\ninturned\ninturns\nintussuscept\nintussuscepted\nintussuscepting\nintussusception\nintussusceptions\nintussusceptive\nintussuscepts\nintwine\nintwined\nintwines\nintwining\nintwist\nintwisted\nintwisting\nintwists\ninulase\ninulases\ninulin\ninulins\ninunction\ninunctions\ninundant\ninundate\ninundated\ninundates\ninundating\ninundation\ninundations\ninundator\ninundators\ninundatory\ninurbane\ninure\ninured\ninurement\ninurements\ninures\ninuring\ninurn\ninurned\ninurning\ninurns\ninutile\ninutilities\ninutility\ninvade\ninvaded\ninvader\ninvaders\ninvades\ninvading\ninvaginate\ninvaginated\ninvaginates\ninvaginating\ninvagination\ninvaginations\ninvalid\ninvalidate\ninvalidated\ninvalidates\ninvalidating\ninvalidation\ninvalidations\ninvalidator\ninvalidators\ninvalided\ninvaliding\ninvalidism\ninvalidisms\ninvalidities\ninvalidity\ninvalidly\ninvalids\ninvaluable\ninvaluableness\ninvaluablenesses\ninvaluably\ninvar\ninvariabilities\ninvariability\ninvariable\ninvariables\ninvariably\ninvariance\ninvariances\ninvariant\ninvariants\ninvars\ninvasion\ninvasions\ninvasive\ninvasively\ninvasiveness\ninvasivenesses\ninvected\ninvective\ninvectively\ninvectiveness\ninvectivenesses\ninvectives\ninveigh\ninveighed\ninveigher\ninveighers\ninveighing\ninveighs\ninveigle\ninveigled\ninveiglement\ninveiglements\ninveigler\ninveiglers\ninveigles\ninveigling\ninvent\ninvented\ninventer\ninventers\ninventing\ninvention\ninventions\ninventive\ninventively\ninventiveness\ninventivenesses\ninventor\ninventorial\ninventorially\ninventoried\ninventories\ninventors\ninventory\ninventorying\ninventress\ninventresses\ninvents\ninverities\ninverity\ninverness\ninvernesses\ninverse\ninversely\ninverses\ninversion\ninversions\ninversive\ninvert\ninvertase\ninvertases\ninvertebrate\ninvertebrates\ninverted\ninverter\ninverters\ninvertible\ninverting\ninvertor\ninvertors\ninverts\ninvest\ninvestable\ninvested\ninvestigate\ninvestigated\ninvestigates\ninvestigating\ninvestigation\ninvestigational\ninvestigations\ninvestigative\ninvestigator\ninvestigators\ninvestigatory\ninvesting\ninvestiture\ninvestitures\ninvestment\ninvestments\ninvestor\ninvestors\ninvests\ninveteracies\ninveteracy\ninveterate\ninveterately\ninviabilities\ninviability\ninviable\ninviably\ninvidious\ninvidiously\ninvidiousness\ninvidiousnesses\ninvigilate\ninvigilated\ninvigilates\ninvigilating\ninvigilation\ninvigilations\ninvigilator\ninvigilators\ninvigorate\ninvigorated\ninvigorates\ninvigorating\ninvigoratingly\ninvigoration\ninvigorations\ninvigorator\ninvigorators\ninvincibilities\ninvincibility\ninvincible\ninvincibleness\ninvinciblenesses\ninvincibly\ninviolabilities\ninviolability\ninviolable\ninviolableness\ninviolablenesses\ninviolably\ninviolacies\ninviolacy\ninviolate\ninviolately\ninviolateness\ninviolatenesses\ninvirile\ninviscid\ninvisibilities\ninvisibility\ninvisible\ninvisibleness\ninvisiblenesses\ninvisibles\ninvisibly\ninvital\ninvitation\ninvitational\ninvitationals\ninvitations\ninvitatories\ninvitatory\ninvite\ninvited\ninvitee\ninvitees\ninviter\ninviters\ninvites\ninviting\ninvitingly\ninvocate\ninvocated\ninvocates\ninvocating\ninvocation\ninvocational\ninvocations\ninvocatory\ninvoice\ninvoiced\ninvoices\ninvoicing\ninvoke\ninvoked\ninvoker\ninvokers\ninvokes\ninvoking\ninvolucra\ninvolucral\ninvolucrate\ninvolucre\ninvolucres\ninvolucrum\ninvoluntarily\ninvoluntariness\ninvoluntarinesses\ninvoluntary\ninvolute\ninvoluted\ninvolutes\ninvoluting\ninvolution\ninvolutional\ninvolutions\ninvolve\ninvolved\ninvolvedly\ninvolvement\ninvolvements\ninvolver\ninvolvers\ninvolves\ninvolving\ninvulnerabilities\ninvulnerability\ninvulnerable\ninvulnerableness\ninvulnerablenesses\ninvulnerably\ninwall\ninwalled\ninwalling\ninwalls\ninward\ninwardly\ninwardness\ninwardnesses\ninwards\ninweave\ninweaved\ninweaves\ninweaving\ninwind\ninwinding\ninwinds\ninwound\ninwove\ninwoven\ninwrap\ninwrapped\ninwrapping\ninwraps\niodate\niodated\niodates\niodating\niodation\niodations\niodic\niodid\niodide\niodides\niodids\niodin\niodinate\niodinated\niodinates\niodinating\niodination\niodinations\niodine\niodines\niodins\niodise\niodised\niodises\niodising\niodism\niodisms\niodize\niodized\niodizer\niodizers\niodizes\niodizing\niodoform\niodoforms\niodophor\niodophors\niodopsin\niodopsins\niodous\niolite\niolites\nion\nionic\nionicities\nionicity\nionics\nionise\nionised\nionises\nionising\nionium\nioniums\nionizable\nionization\nionizations\nionize\nionized\nionizer\nionizers\nionizes\nionizing\nionogen\nionogens\nionomer\nionomers\nionone\nionones\nionophore\nionophores\nionosphere\nionospheres\nionospheric\nionospherically\nions\niontophoreses\niontophoresis\niontophoretic\niontophoretically\niota\niotacism\niotacisms\niotas\nipecac\nipecacs\nipecacuanha\nipecacuanhas\nipomoea\nipomoeas\niproniazid\niproniazids\nipsilateral\nipsilaterally\niracund\nirade\nirades\nirascibilities\nirascibility\nirascible\nirascibleness\nirasciblenesses\nirascibly\nirate\nirately\nirateness\niratenesses\nirater\niratest\nire\nired\nireful\nirefully\nireless\nirenic\nirenical\nirenically\nirenics\nires\nirid\nirides\niridescence\niridescences\niridescent\niridescently\niridic\niridium\niridiums\niridologies\niridologist\niridologists\niridology\niridosmine\niridosmines\nirids\niring\niris\nirised\nirises\nirising\niritic\niritis\niritises\nirk\nirked\nirking\nirks\nirksome\nirksomely\nirksomeness\nirksomenesses\niroko\nirokos\niron\nironbark\nironbarks\nironbound\nironclad\nironclads\nirone\nironed\nironer\nironers\nirones\nironfisted\nironhanded\nironhearted\nironic\nironical\nironically\nironicalness\nironicalnesses\nironies\nironing\nironings\nironist\nironists\nironize\nironized\nironizes\nironizing\nironlike\nironmaster\nironmasters\nironmonger\nironmongeries\nironmongers\nironmongery\nironness\nironnesses\nirons\nironside\nironsides\nironstone\nironstones\nironware\nironwares\nironweed\nironweeds\nironwood\nironwoods\nironwork\nironworker\nironworkers\nironworks\nirony\nirradiance\nirradiances\nirradiate\nirradiated\nirradiates\nirradiating\nirradiation\nirradiations\nirradiative\nirradiator\nirradiators\nirradicable\nirradicably\nirrational\nirrationalism\nirrationalisms\nirrationalist\nirrationalistic\nirrationalists\nirrationalities\nirrationality\nirrationally\nirrationals\nirreal\nirrealities\nirreality\nirreclaimable\nirreclaimably\nirreconcilabilities\nirreconcilability\nirreconcilable\nirreconcilableness\nirreconcilablenesses\nirreconcilables\nirreconcilably\nirrecoverable\nirrecoverableness\nirrecoverablenesses\nirrecoverably\nirrecusable\nirrecusably\nirredeemable\nirredeemably\nirredenta\nirredentas\nirredentism\nirredentisms\nirredentist\nirredentists\nirreducibilities\nirreducibility\nirreducible\nirreducibly\nirreflexive\nirreformabilities\nirreformability\nirreformable\nirrefragabilities\nirrefragability\nirrefragable\nirrefragably\nirrefutabilities\nirrefutability\nirrefutable\nirrefutably\nirregardless\nirregular\nirregularities\nirregularity\nirregularly\nirregulars\nirrelative\nirrelatively\nirrelevance\nirrelevances\nirrelevancies\nirrelevancy\nirrelevant\nirrelevantly\nirreligion\nirreligionist\nirreligionists\nirreligions\nirreligious\nirreligiously\nirremeable\nirremediable\nirremediableness\nirremediablenesses\nirremediably\nirremovabilities\nirremovability\nirremovable\nirremovably\nirreparable\nirreparableness\nirreparablenesses\nirreparably\nirrepealabilities\nirrepealability\nirrepealable\nirreplaceabilities\nirreplaceability\nirreplaceable\nirreplaceableness\nirreplaceablenesses\nirreplaceably\nirrepressibilities\nirrepressibility\nirrepressible\nirrepressibly\nirreproachabilities\nirreproachability\nirreproachable\nirreproachableness\nirreproachablenesses\nirreproachably\nirreproducibilities\nirreproducibility\nirreproducible\nirresistibilities\nirresistibility\nirresistible\nirresistibleness\nirresistiblenesses\nirresistibly\nirresoluble\nirresolute\nirresolutely\nirresoluteness\nirresolutenesses\nirresolution\nirresolutions\nirresolvable\nirrespective\nirresponsibilities\nirresponsibility\nirresponsible\nirresponsibleness\nirresponsiblenesses\nirresponsibles\nirresponsibly\nirresponsive\nirresponsiveness\nirresponsivenesses\nirretrievabilities\nirretrievability\nirretrievable\nirretrievably\nirreverence\nirreverences\nirreverent\nirreverently\nirreversibilities\nirreversibility\nirreversible\nirreversibly\nirrevocabilities\nirrevocability\nirrevocable\nirrevocableness\nirrevocablenesses\nirrevocably\nirridenta\nirridentas\nirrigate\nirrigated\nirrigates\nirrigating\nirrigation\nirrigations\nirrigator\nirrigators\nirritabilities\nirritability\nirritable\nirritableness\nirritablenesses\nirritably\nirritant\nirritants\nirritate\nirritated\nirritates\nirritating\nirritatingly\nirritation\nirritations\nirritative\nirrotational\nirrupt\nirrupted\nirrupting\nirruption\nirruptions\nirruptive\nirruptively\nirrupts\nis\nisagoge\nisagoges\nisagogic\nisagogics\nisallobar\nisallobaric\nisallobars\nisarithm\nisarithms\nisatin\nisatine\nisatines\nisatinic\nisatins\nisba\nisbas\nischaemia\nischaemias\nischemia\nischemias\nischemic\nischia\nischial\nischium\nisentropic\nisentropically\nisinglass\nisinglasses\nisland\nislanded\nislander\nislanders\nislanding\nislands\nisle\nisled\nisleless\nisles\nislet\nislets\nisling\nism\nisms\nisoagglutinin\nisoagglutinins\nisoalloxazine\nisoalloxazines\nisoantibodies\nisoantibody\nisoantigen\nisoantigenic\nisoantigens\nisobar\nisobare\nisobares\nisobaric\nisobars\nisobath\nisobaths\nisobutane\nisobutanes\nisobutylene\nisobutylenes\nisocaloric\nisocarboxazid\nisocarboxazids\nisocheim\nisocheims\nisochime\nisochimes\nisochor\nisochore\nisochores\nisochors\nisochromosome\nisochromosomes\nisochron\nisochronal\nisochronally\nisochrone\nisochrones\nisochronism\nisochronisms\nisochronous\nisochronously\nisochrons\nisocline\nisoclines\nisocracies\nisocracy\nisocyanate\nisocyanates\nisocyclic\nisodiametric\nisodose\nisoelectric\nisoelectronic\nisoelectronically\nisoenzymatic\nisoenzyme\nisoenzymes\nisoenzymic\nisogamete\nisogametes\nisogametic\nisogamies\nisogamous\nisogamy\nisogeneic\nisogenic\nisogenies\nisogeny\nisogloss\nisoglossal\nisoglosses\nisoglossic\nisogon\nisogonal\nisogonals\nisogone\nisogones\nisogonic\nisogonics\nisogonies\nisogons\nisogony\nisograft\nisografted\nisografting\nisografts\nisogram\nisograms\nisograph\nisographs\nisogriv\nisogrivs\nisohel\nisohels\nisohyet\nisohyetal\nisohyets\nisolable\nisolatable\nisolate\nisolated\nisolates\nisolating\nisolation\nisolationism\nisolationisms\nisolationist\nisolationists\nisolations\nisolator\nisolators\nisolead\nisoleads\nisoleucine\nisoleucines\nisoline\nisolines\nisolog\nisologs\nisologue\nisologues\nisomer\nisomerase\nisomerases\nisomeric\nisomerism\nisomerisms\nisomerization\nisomerizations\nisomerize\nisomerized\nisomerizes\nisomerizing\nisomers\nisometric\nisometrically\nisometrics\nisometries\nisometry\nisomorph\nisomorphic\nisomorphically\nisomorphism\nisomorphisms\nisomorphous\nisomorphs\nisoniazid\nisoniazids\nisonomic\nisonomies\nisonomy\nisooctane\nisooctanes\nisopach\nisopachs\nisophotal\nisophote\nisophotes\nisopiestic\nisopleth\nisoplethic\nisopleths\nisopod\nisopodan\nisopodans\nisopods\nisoprenaline\nisoprenalines\nisoprene\nisoprenes\nisoprenoid\nisopropyl\nisopropyls\nisoproterenol\nisoproterenols\nisopycnic\nisosceles\nisosmotic\nisosmotically\nisospin\nisospins\nisospories\nisospory\nisostasies\nisostasy\nisostatic\nisostatically\nisotach\nisotachs\nisotactic\nisothere\nisotheres\nisotherm\nisothermal\nisothermally\nisotherms\nisotone\nisotones\nisotonic\nisotonically\nisotonicities\nisotonicity\nisotope\nisotopes\nisotopic\nisotopically\nisotopies\nisotopy\nisotropic\nisotropies\nisotropy\nisotype\nisotypes\nisotypic\nisozyme\nisozymes\nisozymic\nissei\nisseis\nissuable\nissuably\nissuance\nissuances\nissuant\nissue\nissued\nissueless\nissuer\nissuers\nissues\nissuing\nisthmi\nisthmian\nisthmians\nisthmic\nisthmoid\nisthmus\nisthmuses\nistle\nistles\nit\nitalianate\nitalianated\nitalianates\nitalianating\nitalianise\nitalianised\nitalianises\nitalianising\nitalianize\nitalianized\nitalianizes\nitalianizing\nitalic\nitalicise\nitalicised\nitalicises\nitalicising\nitalicization\nitalicizations\nitalicize\nitalicized\nitalicizes\nitalicizing\nitalics\nitch\nitched\nitches\nitchier\nitchiest\nitchily\nitchiness\nitchinesses\nitching\nitchings\nitchy\nitem\nitemed\niteming\nitemise\nitemised\nitemises\nitemising\nitemization\nitemizations\nitemize\nitemized\nitemizer\nitemizers\nitemizes\nitemizing\nitems\niterance\niterances\niterant\niterate\niterated\niterates\niterating\niteration\niterations\niterative\niteratively\niterum\nither\nithyphallic\nitinerancies\nitinerancy\nitinerant\nitinerantly\nitinerants\nitineraries\nitinerary\nitinerate\nitinerated\nitinerates\nitinerating\nitineration\nitinerations\nits\nitself\nivermectin\nivermectins\nivied\nivies\nivories\nivory\nivorybill\nivorybills\nivy\nivylike\niwis\nixia\nixias\nixodid\nixodids\nixora\nixoras\nixtle\nixtles\nizar\nizars\nizzard\nizzards\njab\njabbed\njabber\njabbered\njabberer\njabberers\njabbering\njabbers\njabberwockies\njabberwocky\njabbing\njabiru\njabirus\njaborandi\njaborandis\njabot\njaboticaba\njaboticabas\njabots\njabs\njacal\njacales\njacals\njacamar\njacamars\njacana\njacanas\njacaranda\njacarandas\njacinth\njacinthe\njacinthes\njacinths\njack\njackal\njackals\njackanapes\njackanapeses\njackaroo\njackaroos\njackass\njackasseries\njackassery\njackasses\njackboot\njackbooted\njackboots\njackdaw\njackdaws\njacked\njacker\njackeroo\njackeroos\njackers\njacket\njacketed\njacketing\njacketless\njackets\njackfish\njackfishes\njackfruit\njackfruits\njackhammer\njackhammered\njackhammering\njackhammers\njackies\njacking\njackknife\njackknifed\njackknifes\njackknifing\njackknives\njackleg\njacklegs\njacklight\njacklights\njackpot\njackpots\njackrabbit\njackrabbits\njackroll\njackrolled\njackrolling\njackrolls\njacks\njackscrew\njackscrews\njacksmelt\njacksmelts\njackstay\njackstays\njackstraw\njackstraws\njacky\njacobin\njacobins\njacobus\njacobuses\njaconet\njaconets\njacquard\njacquards\njacquerie\njacqueries\njactitation\njactitations\njaculate\njaculated\njaculates\njaculating\njade\njaded\njadedly\njadedness\njadednesses\njadeite\njadeites\njades\njading\njadish\njadishly\njaditic\njaeger\njaegers\njag\njager\njagers\njagg\njaggaries\njaggary\njagged\njaggeder\njaggedest\njaggedly\njaggedness\njaggednesses\njagger\njaggeries\njaggers\njaggery\njaggheries\njagghery\njaggier\njaggiest\njagging\njaggs\njaggy\njagless\njagra\njagras\njags\njaguar\njaguarondi\njaguarondis\njaguars\njaguarundi\njaguarundis\njail\njailbait\njailbird\njailbirds\njailbreak\njailbreaks\njailed\njailer\njailers\njailhouse\njailhouses\njailing\njailor\njailors\njails\njake\njakes\njalap\njalapeno\njalapenos\njalapic\njalapin\njalapins\njalaps\njalop\njalopies\njaloppies\njaloppy\njalops\njalopy\njalousie\njalousies\njam\njamb\njambalaya\njambalayas\njambe\njambeau\njambeaux\njambed\njambes\njambing\njamboree\njamborees\njambs\njammed\njammer\njammers\njammier\njammies\njammiest\njamming\njammy\njams\njane\njanes\njangle\njangled\njangler\njanglers\njangles\njanglier\njangliest\njangling\njangly\njaniform\njanisaries\njanisary\njanissaries\njanissary\njanitor\njanitorial\njanitors\njanizaries\njanizary\njanty\njapan\njapanize\njapanized\njapanizes\njapanizing\njapanned\njapanner\njapanners\njapanning\njapans\njape\njaped\njaper\njaperies\njapers\njapery\njapes\njaping\njapingly\njaponaiserie\njaponaiseries\njaponica\njaponicas\njar\njardiniere\njardinieres\njarful\njarfuls\njargon\njargoned\njargonel\njargonels\njargoning\njargonish\njargonistic\njargonize\njargonized\njargonizes\njargonizing\njargons\njargoon\njargoons\njarhead\njarheads\njarina\njarinas\njarl\njarldom\njarldoms\njarls\njarosite\njarosites\njarovize\njarovized\njarovizes\njarovizing\njarrah\njarrahs\njarred\njarring\njarringly\njars\njarsful\njarvey\njarveys\njasmin\njasmine\njasmines\njasmins\njasper\njaspers\njasperware\njasperwares\njaspery\njassid\njassids\njato\njatos\njauk\njauked\njauking\njauks\njaunce\njaunced\njaunces\njauncing\njaundice\njaundiced\njaundices\njaundicing\njaunt\njaunted\njauntier\njauntiest\njauntily\njauntiness\njauntinesses\njaunting\njaunts\njaunty\njaup\njauped\njauping\njaups\njava\njavas\njavelin\njavelina\njavelinas\njavelined\njavelining\njavelins\njaw\njawan\njawans\njawbone\njawboned\njawboner\njawboners\njawbones\njawboning\njawbonings\njawbreaker\njawbreakers\njawed\njawing\njawlike\njawline\njawlines\njaws\njay\njaybird\njaybirds\njaygee\njaygees\njayhawker\njayhawkers\njays\njayvee\njayvees\njaywalk\njaywalked\njaywalker\njaywalkers\njaywalking\njaywalks\njazz\njazzed\njazzer\njazzers\njazzes\njazzier\njazziest\njazzily\njazziness\njazzinesses\njazzing\njazzlike\njazzman\njazzmen\njazzy\njealous\njealousies\njealously\njealousness\njealousnesses\njealousy\njean\njeans\njebel\njebels\njee\njeed\njeeing\njeep\njeeped\njeepers\njeeping\njeepney\njeepneys\njeeps\njeer\njeered\njeerer\njeerers\njeering\njeeringly\njeers\njees\njeez\njefe\njefes\njehad\njehads\njehu\njehus\njejuna\njejunal\njejune\njejunely\njejuneness\njejunenesses\njejunities\njejunity\njejunum\njell\njellaba\njellabas\njelled\njellied\njellies\njellified\njellifies\njellify\njellifying\njelling\njells\njelly\njellybean\njellybeans\njellyfish\njellyfishes\njellying\njellylike\njelutong\njelutongs\njemadar\njemadars\njemidar\njemidars\njemmied\njemmies\njemmy\njemmying\njennet\njennets\njennies\njenny\njeon\njeopard\njeoparded\njeopardies\njeoparding\njeopardise\njeopardised\njeopardises\njeopardising\njeopardize\njeopardized\njeopardizes\njeopardizing\njeopards\njeopardy\njerboa\njerboas\njereed\njereeds\njeremiad\njeremiads\njerid\njerids\njerk\njerked\njerker\njerkers\njerkier\njerkies\njerkiest\njerkily\njerkin\njerkiness\njerkinesses\njerking\njerkins\njerks\njerkwater\njerky\njeroboam\njeroboams\njerreed\njerreeds\njerrican\njerricans\njerrid\njerrids\njerries\njerry\njerrycan\njerrycans\njersey\njerseyed\njerseys\njess\njessamine\njessamines\njessant\njesse\njessed\njesses\njessing\njest\njested\njester\njesters\njestful\njesting\njestings\njests\njesuit\njesuitic\njesuitical\njesuitically\njesuitism\njesuitisms\njesuitries\njesuitry\njesuits\njet\njetbead\njetbeads\njete\njetes\njetlike\njetliner\njetliners\njeton\njetons\njetport\njetports\njets\njetsam\njetsams\njetsom\njetsoms\njetted\njettied\njettier\njetties\njettiest\njetting\njettison\njettisonable\njettisoned\njettisoning\njettisons\njetton\njettons\njetty\njettying\njeu\njeux\njew\njewed\njewel\njeweled\njeweler\njewelers\njeweling\njewelled\njeweller\njewelleries\njewellers\njewellery\njewellike\njewelling\njewelries\njewelry\njewels\njewelweed\njewelweeds\njewfish\njewfishes\njewing\njews\njezail\njezails\njezebel\njezebels\njiao\njib\njibb\njibbed\njibber\njibbers\njibbing\njibboom\njibbooms\njibbs\njibe\njibed\njiber\njibers\njibes\njibing\njibingly\njibs\njicama\njicamas\njiff\njiffies\njiffs\njiffy\njig\njigaboo\njigaboos\njigged\njigger\njiggered\njiggering\njiggers\njigging\njiggle\njiggled\njiggles\njigglier\njiggliest\njiggling\njiggly\njigs\njigsaw\njigsawed\njigsawing\njigsawn\njigsaws\njihad\njihads\njill\njillion\njillions\njills\njilt\njilted\njilter\njilters\njilting\njilts\njiminy\njimjams\njimmied\njimmies\njimminy\njimmy\njimmying\njimp\njimper\njimpest\njimply\njimpy\njimsonweed\njimsonweeds\njin\njingal\njingall\njingalls\njingals\njingko\njingkoes\njingle\njingled\njingler\njinglers\njingles\njinglier\njingliest\njingling\njingly\njingo\njingoes\njingoish\njingoism\njingoisms\njingoist\njingoistic\njingoistically\njingoists\njink\njinked\njinker\njinkers\njinking\njinks\njinn\njinnee\njinni\njinns\njinricksha\njinrickshas\njinrikisha\njinrikishas\njins\njinx\njinxed\njinxes\njinxing\njipijapa\njipijapas\njism\njisms\njitney\njitneys\njitter\njitterbug\njitterbugged\njitterbugging\njitterbugs\njittered\njitterier\njitteriest\njitteriness\njitterinesses\njittering\njitters\njittery\njiujitsu\njiujitsus\njiujutsu\njiujutsus\njive\njiveass\njived\njiver\njivers\njives\njivey\njivier\njiviest\njiving\njnana\njnanas\njo\njoannes\njob\njobbed\njobber\njobberies\njobbers\njobbery\njobbing\njobholder\njobholders\njobless\njoblessness\njoblessnesses\njobname\njobnames\njobs\njock\njockette\njockettes\njockey\njockeyed\njockeying\njockeys\njocko\njockos\njocks\njockstrap\njockstraps\njocose\njocosely\njocoseness\njocosenesses\njocosities\njocosity\njocular\njocularities\njocularity\njocularly\njocund\njocundities\njocundity\njocundly\njodhpur\njodhpurs\njoe\njoes\njoey\njoeys\njog\njogged\njogger\njoggers\njogging\njoggings\njoggle\njoggled\njoggler\njogglers\njoggles\njoggling\njogs\njohannes\njohn\njohnboat\njohnboats\njohnnies\njohnny\njohnnycake\njohnnycakes\njohns\njohnsongrass\njohnsongrasses\njoin\njoinable\njoinder\njoinders\njoined\njoiner\njoineries\njoiners\njoinery\njoining\njoinings\njoins\njoint\njointed\njointedly\njointedness\njointednesses\njointer\njointers\njointing\njointly\njointress\njointresses\njoints\njointure\njointured\njointures\njointuring\njointworm\njointworms\njoist\njoisted\njoisting\njoists\njojoba\njojobas\njoke\njoked\njoker\njokers\njokes\njokester\njokesters\njokey\njokier\njokiest\njokily\njokiness\njokinesses\njoking\njokingly\njoky\njole\njoles\njollied\njollier\njollies\njolliest\njollification\njollifications\njollified\njollifies\njollify\njollifying\njollily\njolliness\njollinesses\njollities\njollity\njolly\njollying\njolt\njolted\njolter\njolters\njoltier\njoltiest\njoltily\njolting\njolts\njolty\njones\njoneses\njongleur\njongleurs\njonquil\njonquils\njoram\njorams\njordan\njordans\njorum\njorums\njoseph\njosephs\njosh\njoshed\njosher\njoshers\njoshes\njoshing\njoss\njosses\njostle\njostled\njostler\njostlers\njostles\njostling\njot\njota\njotas\njots\njotted\njotter\njotters\njotting\njottings\njotty\njoual\njouals\njouk\njouked\njouking\njouks\njoule\njoules\njounce\njounced\njounces\njouncier\njounciest\njouncing\njouncy\njournal\njournalese\njournaleses\njournalism\njournalisms\njournalist\njournalistic\njournalistically\njournalists\njournalize\njournalized\njournalizer\njournalizers\njournalizes\njournalizing\njournals\njourney\njourneyed\njourneyer\njourneyers\njourneying\njourneyman\njourneymen\njourneys\njourneywork\njourneyworks\njoust\njousted\njouster\njousters\njousting\njousts\njovial\njovialities\njoviality\njovially\njovialties\njovialty\njow\njowar\njowars\njowed\njowing\njowl\njowled\njowlier\njowliest\njowls\njowly\njows\njoy\njoyance\njoyances\njoyed\njoyful\njoyfuller\njoyfullest\njoyfully\njoyfulness\njoyfulnesses\njoying\njoyless\njoylessly\njoylessness\njoylessnesses\njoyous\njoyously\njoyousness\njoyousnesses\njoypop\njoypopped\njoypopper\njoypoppers\njoypopping\njoypops\njoyridden\njoyride\njoyrider\njoyriders\njoyrides\njoyriding\njoyridings\njoyrode\njoys\njoystick\njoysticks\njuba\njubas\njubbah\njubbahs\njube\njubes\njubhah\njubhahs\njubilance\njubilances\njubilant\njubilantly\njubilarian\njubilarians\njubilate\njubilated\njubilates\njubilating\njubilation\njubilations\njubile\njubilee\njubilees\njubiles\njudas\njudases\njudder\njuddered\njuddering\njudders\njudge\njudged\njudgement\njudgements\njudger\njudgers\njudges\njudgeship\njudgeships\njudging\njudgmatic\njudgmatical\njudgmatically\njudgment\njudgmental\njudgmentally\njudgments\njudicatories\njudicatory\njudicature\njudicatures\njudicial\njudicially\njudiciaries\njudiciary\njudicious\njudiciously\njudiciousness\njudiciousnesses\njudo\njudoist\njudoists\njudoka\njudokas\njudos\njug\njuga\njugal\njugate\njugful\njugfuls\njugged\njuggernaut\njuggernauts\njugging\njuggle\njuggled\njuggler\njuggleries\njugglers\njugglery\njuggles\njuggling\njugglings\njughead\njugheads\njugs\njugsful\njugula\njugular\njugulars\njugulate\njugulated\njugulates\njugulating\njugulum\njugum\njugums\njuice\njuiced\njuicehead\njuiceheads\njuiceless\njuicer\njuicers\njuices\njuicier\njuiciest\njuicily\njuiciness\njuicinesses\njuicing\njuicy\njujitsu\njujitsus\njuju\njujube\njujubes\njujuism\njujuisms\njujuist\njujuists\njujus\njujutsu\njujutsus\njuke\njukebox\njukeboxes\njuked\njukes\njuking\njulep\njuleps\njulienne\njulienned\njuliennes\njulienning\njumbal\njumbals\njumble\njumbled\njumbler\njumblers\njumbles\njumbling\njumbo\njumbos\njumbuck\njumbucks\njump\njumped\njumper\njumpers\njumpier\njumpiest\njumpily\njumpiness\njumpinesses\njumping\njumpoff\njumpoffs\njumps\njumpsuit\njumpsuits\njumpy\njun\njunco\njuncoes\njuncos\njunction\njunctional\njunctions\njunctural\njuncture\njunctures\njungle\njungled\njunglelike\njungles\njunglier\njungliest\njungly\njunior\njuniorate\njuniorates\njuniors\njuniper\njunipers\njunk\njunked\njunker\njunkers\njunket\njunketed\njunketeer\njunketeers\njunketer\njunketers\njunketing\njunkets\njunkie\njunkier\njunkies\njunkiest\njunking\njunkman\njunkmen\njunks\njunky\njunkyard\njunkyards\njunta\njuntas\njunto\njuntos\njupe\njupes\njupon\njupons\njura\njural\njurally\njurant\njurants\njurat\njuratory\njurats\njurel\njurels\njuridic\njuridical\njuridically\njuried\njuries\njurisconsult\njurisconsults\njurisdiction\njurisdictional\njurisdictionally\njurisdictions\njurisprudence\njurisprudences\njurisprudent\njurisprudential\njurisprudentially\njurisprudents\njurist\njuristic\njuristically\njurists\njuror\njurors\njury\njurying\njuryman\njurymen\njus\njussive\njussives\njust\njusted\njuster\njusters\njustest\njustice\njustices\njusticiabilities\njusticiability\njusticiable\njusticiar\njusticiars\njustifiabilities\njustifiability\njustifiable\njustifiably\njustification\njustifications\njustificative\njustificatory\njustified\njustifier\njustifiers\njustifies\njustify\njustifying\njusting\njustle\njustled\njustles\njustling\njustly\njustness\njustnesses\njusts\njut\njute\njutes\njuts\njutted\njuttied\njutties\njutting\njutty\njuttying\njuvenal\njuvenals\njuvenescence\njuvenescences\njuvenescent\njuvenile\njuveniles\njuvenilia\njuvenilities\njuvenility\njuxtapose\njuxtaposed\njuxtaposes\njuxtaposing\njuxtaposition\njuxtapositional\njuxtapositions\nka\nkaas\nkab\nkabab\nkababs\nkabaka\nkabakas\nkabala\nkabalas\nkabar\nkabars\nkabaya\nkabayas\nkabbala\nkabbalah\nkabbalahs\nkabbalas\nkabeljou\nkabeljous\nkabiki\nkabikis\nkabob\nkabobs\nkabs\nkabuki\nkabukis\nkachina\nkachinas\nkaddish\nkaddishes\nkaddishim\nkadi\nkadis\nkae\nkaes\nkaf\nkaffeeklatsch\nkaffeeklatsches\nkaffir\nkaffirs\nkaffiyeh\nkaffiyehs\nkafir\nkafirs\nkafs\nkaftan\nkaftans\nkagu\nkagus\nkahuna\nkahunas\nkaiak\nkaiaks\nkaif\nkaifs\nkail\nkails\nkailyard\nkailyards\nkain\nkainit\nkainite\nkainites\nkainits\nkains\nkaiser\nkaiserdom\nkaiserdoms\nkaiserin\nkaiserins\nkaiserism\nkaiserisms\nkaisers\nkajeput\nkajeputs\nkaka\nkakapo\nkakapos\nkakas\nkakemono\nkakemonos\nkaki\nkakiemon\nkakiemons\nkakis\nkalam\nkalams\nkalanchoe\nkalanchoes\nkale\nkaleidoscope\nkaleidoscopes\nkaleidoscopic\nkaleidoscopically\nkalends\nkales\nkalewife\nkalewives\nkaleyard\nkaleyards\nkalian\nkalians\nkalif\nkalifate\nkalifates\nkalifs\nkalimba\nkalimbas\nkaliph\nkaliphs\nkalium\nkaliums\nkallidin\nkallidins\nkallikrein\nkallikreins\nkalmia\nkalmias\nkalong\nkalongs\nkalpa\nkalpak\nkalpaks\nkalpas\nkalyptra\nkalyptras\nkamaaina\nkamaainas\nkamacite\nkamacites\nkamala\nkamalas\nkame\nkames\nkami\nkamik\nkamikaze\nkamikazes\nkamiks\nkampong\nkampongs\nkamseen\nkamseens\nkamsin\nkamsins\nkana\nkanamycin\nkanamycins\nkanas\nkanban\nkanbans\nkane\nkanes\nkangaroo\nkangaroos\nkanji\nkanjis\nkantar\nkantars\nkantele\nkanteles\nkaoliang\nkaoliangs\nkaolin\nkaoline\nkaolines\nkaolinic\nkaolinite\nkaolinites\nkaolinitic\nkaolins\nkaon\nkaons\nkapa\nkapas\nkapellmeister\nkapellmeisters\nkaph\nkaphs\nkapok\nkapoks\nkappa\nkappas\nkaput\nkaputt\nkarabiner\nkarabiners\nkarakul\nkarakuls\nkaraoke\nkaraokes\nkarat\nkarate\nkarateist\nkarateists\nkarates\nkarats\nkarma\nkarmas\nkarmic\nkarn\nkarns\nkaroo\nkaroos\nkaross\nkarosses\nkarroo\nkarroos\nkarst\nkarstic\nkarsts\nkart\nkarting\nkartings\nkarts\nkaryogamies\nkaryogamy\nkaryokineses\nkaryokinesis\nkaryokinetic\nkaryologic\nkaryological\nkaryologies\nkaryology\nkaryolymph\nkaryolymphs\nkaryosome\nkaryosomes\nkaryotin\nkaryotins\nkaryotype\nkaryotyped\nkaryotypes\nkaryotypic\nkaryotypically\nkaryotyping\nkas\nkasbah\nkasbahs\nkasha\nkashas\nkasher\nkashered\nkashering\nkashers\nkashmir\nkashmirs\nkashrut\nkashruth\nkashruths\nkashruts\nkat\nkata\nkatabatic\nkatakana\nkatakanas\nkatas\nkatchina\nkatchinas\nkatcina\nkatcinas\nkatharses\nkatharsis\nkathodal\nkathode\nkathodes\nkathodic\nkation\nkations\nkats\nkatydid\nkatydids\nkatzenjammer\nkatzenjammers\nkauri\nkauries\nkauris\nkaury\nkava\nkavakava\nkavakavas\nkavas\nkavass\nkavasses\nkay\nkayak\nkayaked\nkayaker\nkayakers\nkayaking\nkayakings\nkayaks\nkayles\nkayo\nkayoed\nkayoes\nkayoing\nkayos\nkays\nkazachki\nkazachok\nkazatski\nkazatskies\nkazatsky\nkazoo\nkazoos\nkbar\nkbars\nkea\nkeas\nkebab\nkebabs\nkebar\nkebars\nkebbie\nkebbies\nkebbock\nkebbocks\nkebbuck\nkebbucks\nkeblah\nkeblahs\nkebob\nkebobs\nkeck\nkecked\nkecking\nkeckle\nkeckled\nkeckles\nkeckling\nkecks\nkeddah\nkeddahs\nkedge\nkedged\nkedgeree\nkedgerees\nkedges\nkedging\nkeef\nkeefs\nkeek\nkeeked\nkeeking\nkeeks\nkeel\nkeelage\nkeelages\nkeelboat\nkeelboats\nkeeled\nkeelhale\nkeelhaled\nkeelhales\nkeelhaling\nkeelhaul\nkeelhauled\nkeelhauling\nkeelhauls\nkeeling\nkeelless\nkeels\nkeelson\nkeelsons\nkeen\nkeened\nkeener\nkeeners\nkeenest\nkeening\nkeenly\nkeenness\nkeennesses\nkeens\nkeep\nkeepable\nkeeper\nkeepers\nkeeping\nkeepings\nkeeps\nkeepsake\nkeepsakes\nkeeshond\nkeeshonden\nkeeshonds\nkeester\nkeesters\nkeet\nkeets\nkeeve\nkeeves\nkef\nkeffiyeh\nkeffiyehs\nkefir\nkefirs\nkefs\nkeg\nkegeler\nkegelers\nkegler\nkeglers\nkegling\nkeglings\nkegs\nkeir\nkeirs\nkeister\nkeisters\nkeitloa\nkeitloas\nkelep\nkeleps\nkelim\nkelims\nkellies\nkelly\nkeloid\nkeloidal\nkeloids\nkelp\nkelped\nkelpie\nkelpies\nkelping\nkelps\nkelpy\nkelson\nkelsons\nkelter\nkelters\nkelvin\nkelvins\nkemp\nkemps\nkempt\nken\nkenaf\nkenafs\nkench\nkenches\nkendo\nkendos\nkenned\nkennel\nkenneled\nkenneling\nkennelled\nkennelling\nkennels\nkenning\nkennings\nkeno\nkenos\nkenosis\nkenosises\nkenotic\nkenotron\nkenotrons\nkens\nkenspeckle\nkent\nkentledge\nkentledges\nkep\nkephalin\nkephalins\nkepi\nkepis\nkepped\nkeppen\nkepping\nkeps\nkept\nkeramic\nkeramics\nkeratin\nkeratinization\nkeratinizations\nkeratinize\nkeratinized\nkeratinizes\nkeratinizing\nkeratinophilic\nkeratinous\nkeratins\nkeratitides\nkeratitis\nkeratoconjunctivitis\nkeratoconjunctivitises\nkeratoid\nkeratoma\nkeratomas\nkeratomata\nkeratoplasties\nkeratoplasty\nkeratose\nkeratoses\nkeratosis\nkeratotic\nkeratotomies\nkeratotomy\nkerb\nkerbed\nkerbing\nkerbs\nkerchief\nkerchiefed\nkerchiefs\nkerchieves\nkerchoo\nkerf\nkerfed\nkerfing\nkerfs\nkerfuffle\nkerfuffles\nkermes\nkermeses\nkermess\nkermesse\nkermesses\nkermis\nkermises\nkern\nkerne\nkerned\nkernel\nkerneled\nkerneling\nkernelled\nkernelling\nkernels\nkernes\nkerning\nkernite\nkernites\nkerns\nkerogen\nkerogens\nkerosene\nkerosenes\nkerosine\nkerosines\nkerplunk\nkerplunked\nkerplunking\nkerplunks\nkerria\nkerrias\nkerries\nkerry\nkersey\nkerseymere\nkerseymeres\nkerseys\nkerygma\nkerygmas\nkerygmata\nkerygmatic\nkestrel\nkestrels\nketch\nketches\nketchup\nketchups\nketene\nketenes\nketo\nketogeneses\nketogenesis\nketogenic\nketol\nketols\nketone\nketones\nketonic\nketose\nketoses\nketosis\nketosteroid\nketosteroids\nketotic\nkettle\nkettledrum\nkettledrums\nkettles\nkevel\nkevels\nkevil\nkevils\nkex\nkexes\nkey\nkeyboard\nkeyboarded\nkeyboarder\nkeyboarders\nkeyboarding\nkeyboardist\nkeyboardists\nkeyboards\nkeybutton\nkeybuttons\nkeycard\nkeycards\nkeyed\nkeyhole\nkeyholes\nkeying\nkeyless\nkeynote\nkeynoted\nkeynoter\nkeynoters\nkeynotes\nkeynoting\nkeypad\nkeypads\nkeypunch\nkeypunched\nkeypuncher\nkeypunchers\nkeypunches\nkeypunching\nkeys\nkeyset\nkeysets\nkeyster\nkeysters\nkeystone\nkeystones\nkeystroke\nkeystroked\nkeystrokes\nkeystroking\nkeyway\nkeyways\nkeyword\nkeywords\nkhaddar\nkhaddars\nkhadi\nkhadis\nkhaf\nkhafs\nkhaki\nkhakis\nkhalif\nkhalifa\nkhalifas\nkhalifs\nkhamseen\nkhamseens\nkhamsin\nkhamsins\nkhan\nkhanate\nkhanates\nkhans\nkhaph\nkhaphs\nkhat\nkhats\nkhazen\nkhazenim\nkhazens\nkheda\nkhedah\nkhedahs\nkhedas\nkhedival\nkhedive\nkhedives\nkhedivial\nkhet\nkheth\nkheths\nkhets\nkhi\nkhirkah\nkhirkahs\nkhis\nkhoum\nkhoums\nkiang\nkiangs\nkiaugh\nkiaughs\nkibbe\nkibbeh\nkibbehs\nkibbes\nkibbi\nkibbis\nkibbitz\nkibbitzed\nkibbitzer\nkibbitzers\nkibbitzes\nkibbitzing\nkibble\nkibbled\nkibbles\nkibbling\nkibbutz\nkibbutzim\nkibbutznik\nkibbutzniks\nkibe\nkibei\nkibeis\nkibes\nkibitz\nkibitzed\nkibitzer\nkibitzers\nkibitzes\nkibitzing\nkibla\nkiblah\nkiblahs\nkiblas\nkibosh\nkiboshed\nkiboshes\nkiboshing\nkick\nkickable\nkickback\nkickbacks\nkickball\nkickballs\nkickboard\nkickboards\nkickboxer\nkickboxers\nkickboxing\nkickboxings\nkicked\nkicker\nkickers\nkickier\nkickiest\nkicking\nkickoff\nkickoffs\nkicks\nkickshaw\nkickshaws\nkickstand\nkickstands\nkickstart\nkickstarted\nkickstarting\nkickstarts\nkickup\nkickups\nkicky\nkid\nkidded\nkidder\nkidders\nkiddie\nkiddies\nkidding\nkiddingly\nkiddish\nkiddo\nkiddoes\nkiddos\nkiddush\nkiddushes\nkiddushim\nkiddy\nkidlike\nkidnap\nkidnaped\nkidnapee\nkidnapees\nkidnaper\nkidnapers\nkidnaping\nkidnapped\nkidnappee\nkidnappees\nkidnapper\nkidnappers\nkidnapping\nkidnaps\nkidney\nkidneys\nkids\nkidskin\nkidskins\nkidvid\nkidvids\nkief\nkiefs\nkielbasa\nkielbasas\nkielbasi\nkielbasy\nkier\nkiers\nkieselguhr\nkieselguhrs\nkieserite\nkieserites\nkiester\nkiesters\nkif\nkifs\nkike\nkikes\nkilderkin\nkilderkins\nkilim\nkilims\nkill\nkilldee\nkilldeer\nkilldeers\nkilldees\nkilled\nkiller\nkillers\nkillick\nkillicks\nkillie\nkillies\nkillifish\nkillifishes\nkilling\nkillingly\nkillings\nkilljoy\nkilljoys\nkillock\nkillocks\nkills\nkiln\nkilned\nkilning\nkilns\nkilo\nkilobar\nkilobars\nkilobase\nkilobases\nkilobaud\nkilobauds\nkilobit\nkilobits\nkilobyte\nkilobytes\nkilocalorie\nkilocalories\nkilocycle\nkilocycles\nkilogauss\nkilogausses\nkilogram\nkilograms\nkilohertz\nkilojoule\nkilojoules\nkiloliter\nkiloliters\nkilometer\nkilometers\nkilomole\nkilomoles\nkiloparsec\nkiloparsecs\nkilopascal\nkilopascals\nkilorad\nkilorads\nkilos\nkiloton\nkilotons\nkilovolt\nkilovolts\nkilowatt\nkilowatts\nkilt\nkilted\nkilter\nkilters\nkiltie\nkilties\nkilting\nkiltings\nkilts\nkilty\nkimberlite\nkimberlites\nkimchee\nkimchees\nkimchi\nkimchis\nkimono\nkimonoed\nkimonos\nkin\nkina\nkinas\nkinase\nkinases\nkind\nkinder\nkindergarten\nkindergartener\nkindergarteners\nkindergartens\nkindergartner\nkindergartners\nkindest\nkindhearted\nkindheartedly\nkindheartedness\nkindheartednesses\nkindle\nkindled\nkindler\nkindlers\nkindles\nkindless\nkindlessly\nkindlier\nkindliest\nkindliness\nkindlinesses\nkindling\nkindlings\nkindly\nkindness\nkindnesses\nkindred\nkindreds\nkinds\nkine\nkinema\nkinemas\nkinematic\nkinematical\nkinematically\nkinematics\nkines\nkinescope\nkinescoped\nkinescopes\nkinescoping\nkineses\nkinesic\nkinesics\nkinesiologies\nkinesiology\nkinesis\nkinestheses\nkinesthesia\nkinesthesias\nkinesthesis\nkinesthetic\nkinesthetically\nkinetic\nkinetically\nkineticist\nkineticists\nkinetics\nkinetin\nkinetins\nkinetochore\nkinetochores\nkinetoplast\nkinetoplasts\nkinetoscope\nkinetoscopes\nkinetosome\nkinetosomes\nkinfolk\nkinfolks\nking\nkingbird\nkingbirds\nkingbolt\nkingbolts\nkingcraft\nkingcrafts\nkingcup\nkingcups\nkingdom\nkingdoms\nkinged\nkingfish\nkingfisher\nkingfishers\nkingfishes\nkinghood\nkinghoods\nkinging\nkingless\nkinglet\nkinglets\nkinglier\nkingliest\nkinglike\nkingliness\nkinglinesses\nkingly\nkingmaker\nkingmakers\nkingpin\nkingpins\nkingpost\nkingposts\nkings\nkingship\nkingships\nkingside\nkingsides\nkingwood\nkingwoods\nkinin\nkinins\nkink\nkinkajou\nkinkajous\nkinked\nkinkier\nkinkiest\nkinkily\nkinkiness\nkinkinesses\nkinking\nkinks\nkinky\nkinnikinnick\nkinnikinnicks\nkino\nkinos\nkins\nkinsfolk\nkinship\nkinships\nkinsman\nkinsmen\nkinswoman\nkinswomen\nkiosk\nkiosks\nkip\nkipped\nkippen\nkipper\nkippered\nkipperer\nkipperers\nkippering\nkippers\nkipping\nkips\nkipskin\nkipskins\nkir\nkirigami\nkirigamis\nkirk\nkirkman\nkirkmen\nkirks\nkirmess\nkirmesses\nkirn\nkirned\nkirning\nkirns\nkirs\nkirsch\nkirsches\nkirtle\nkirtled\nkirtles\nkishka\nkishkas\nkishke\nkishkes\nkismat\nkismats\nkismet\nkismetic\nkismets\nkiss\nkissable\nkissably\nkissed\nkisser\nkissers\nkisses\nkissing\nkissy\nkist\nkistful\nkistfuls\nkists\nkit\nkitchen\nkitchenette\nkitchenettes\nkitchens\nkitchenware\nkitchenwares\nkite\nkited\nkitelike\nkiter\nkiters\nkites\nkith\nkithara\nkitharas\nkithe\nkithed\nkithes\nkithing\nkiths\nkiting\nkitling\nkitlings\nkits\nkitsch\nkitsches\nkitschy\nkitted\nkittel\nkitten\nkittened\nkittening\nkittenish\nkittenishly\nkittenishness\nkittenishnesses\nkittens\nkitties\nkitting\nkittiwake\nkittiwakes\nkittle\nkittled\nkittler\nkittles\nkittlest\nkittling\nkitty\nkiva\nkivas\nkiwi\nkiwifruit\nkiwifruits\nkiwis\nklatch\nklatches\nklatsch\nklatsches\nklavern\nklaverns\nklaxon\nklaxons\nkleagle\nkleagles\nklebsiella\nklebsiellas\nklepht\nklephtic\nklephts\nkleptomania\nkleptomaniac\nkleptomaniacs\nkleptomanias\nklezmer\nklezmers\nklezmorim\nklister\nklisters\nklong\nklongs\nkloof\nkloofs\nkludge\nkludges\nkludgy\nkluge\nkluges\nklutz\nklutzes\nklutzier\nklutziest\nklutziness\nklutzinesses\nklutzy\nklystron\nklystrons\nknack\nknacked\nknacker\nknackered\nknackeries\nknackers\nknackery\nknacking\nknacks\nknackwurst\nknackwursts\nknap\nknapped\nknapper\nknappers\nknapping\nknaps\nknapsack\nknapsacked\nknapsacks\nknapweed\nknapweeds\nknar\nknarred\nknarry\nknars\nknaur\nknaurs\nknave\nknaveries\nknavery\nknaves\nknavish\nknavishly\nknawel\nknawels\nknead\nkneadable\nkneaded\nkneader\nkneaders\nkneading\nkneads\nknee\nkneecap\nkneecapped\nkneecapping\nkneecappings\nkneecaps\nkneed\nkneehole\nkneeholes\nkneeing\nkneel\nkneeled\nkneeler\nkneelers\nkneeling\nkneels\nkneepad\nkneepads\nkneepan\nkneepans\nknees\nkneesock\nkneesocks\nknell\nknelled\nknelling\nknells\nknelt\nknesset\nknessets\nknew\nknickerbocker\nknickerbockers\nknickers\nknickknack\nknickknacks\nknife\nknifed\nknifelike\nknifepoint\nknifepoints\nknifer\nknifers\nknifes\nknifing\nknight\nknighted\nknighthood\nknighthoods\nknighting\nknightliness\nknightlinesses\nknightly\nknights\nknish\nknishes\nknit\nknits\nknitted\nknitter\nknitters\nknitting\nknittings\nknitwear\nknives\nknob\nknobbed\nknobbier\nknobbiest\nknobblier\nknobbliest\nknobbly\nknobby\nknobkerrie\nknobkerries\nknoblike\nknobs\nknock\nknockabout\nknockabouts\nknockdown\nknockdowns\nknocked\nknocker\nknockers\nknocking\nknockoff\nknockoffs\nknockout\nknockouts\nknocks\nknockwurst\nknockwursts\nknoll\nknolled\nknoller\nknollers\nknolling\nknolls\nknolly\nknop\nknopped\nknops\nknosp\nknosps\nknot\nknotgrass\nknotgrasses\nknothole\nknotholes\nknotless\nknotlike\nknots\nknotted\nknotter\nknotters\nknottier\nknottiest\nknottily\nknottiness\nknottinesses\nknotting\nknottings\nknotty\nknotweed\nknotweeds\nknout\nknouted\nknouting\nknouts\nknow\nknowable\nknower\nknowers\nknowing\nknowinger\nknowingest\nknowingly\nknowingness\nknowingnesses\nknowings\nknowledge\nknowledgeabilities\nknowledgeability\nknowledgeable\nknowledgeableness\nknowledgeablenesses\nknowledgeably\nknowledges\nknown\nknowns\nknows\nknubbier\nknubbiest\nknubby\nknuckle\nknuckleball\nknuckleballer\nknuckleballers\nknuckleballs\nknucklebone\nknucklebones\nknuckled\nknucklehead\nknuckleheaded\nknuckleheads\nknuckler\nknucklers\nknuckles\nknucklier\nknuckliest\nknuckling\nknuckly\nknur\nknurl\nknurled\nknurlier\nknurliest\nknurling\nknurls\nknurly\nknurs\nkoa\nkoala\nkoalas\nkoan\nkoans\nkoas\nkob\nkobo\nkobold\nkobolds\nkobos\nkobs\nkoel\nkoels\nkohl\nkohlrabi\nkohlrabies\nkohls\nkoi\nkoine\nkoines\nkois\nkokanee\nkokanees\nkola\nkolache\nkolacky\nkolas\nkolbasi\nkolbasis\nkolbassi\nkolbassis\nkolhoz\nkolhozes\nkolhozy\nkolinski\nkolinskies\nkolinsky\nkolkhos\nkolkhoses\nkolkhosy\nkolkhoz\nkolkhozes\nkolkhoznik\nkolkhozniki\nkolkhozniks\nkolkhozy\nkolkoz\nkolkozes\nkolkozy\nkolo\nkolos\nkomatik\nkomatiks\nkomondor\nkomondorock\nkomondorok\nkomondors\nkonk\nkonked\nkonking\nkonks\nkoodoo\nkoodoos\nkook\nkookaburra\nkookaburras\nkookie\nkookier\nkookiest\nkookiness\nkookinesses\nkooks\nkooky\nkop\nkopeck\nkopecks\nkopek\nkopeks\nkoph\nkophs\nkopje\nkopjes\nkoppa\nkoppas\nkoppie\nkoppies\nkops\nkor\nkorai\nkorat\nkorats\nkore\nkors\nkorun\nkoruna\nkorunas\nkoruny\nkos\nkosher\nkoshered\nkoshering\nkoshers\nkoss\nkoto\nkotos\nkotow\nkotowed\nkotower\nkotowers\nkotowing\nkotows\nkoumis\nkoumises\nkoumiss\nkoumisses\nkoumys\nkoumyses\nkoumyss\nkoumysses\nkouprey\nkoupreys\nkouroi\nkouros\nkousso\nkoussos\nkowtow\nkowtowed\nkowtower\nkowtowers\nkowtowing\nkowtows\nkraal\nkraaled\nkraaling\nkraals\nkraft\nkrafts\nkrait\nkraits\nkraken\nkrakens\nkrater\nkraters\nkraut\nkrauts\nkreep\nkreeps\nkremlin\nkremlinologies\nkremlinologist\nkremlinologists\nkremlinology\nkremlins\nkreplach\nkreutzer\nkreutzers\nkreuzer\nkreuzers\nkrill\nkrills\nkrimmer\nkrimmers\nkris\nkrises\nkrona\nkrone\nkronen\nkroner\nkronor\nkronur\nkroon\nkrooni\nkroons\nkrubi\nkrubis\nkrubut\nkrubuts\nkrugerrand\nkrugerrands\nkruller\nkrullers\nkrumhorn\nkrumhorns\nkrummholz\nkrummhorn\nkrummhorns\nkryolite\nkryolites\nkryolith\nkryoliths\nkrypton\nkryptons\nkuchen\nkudo\nkudos\nkudu\nkudus\nkudzu\nkudzus\nkue\nkues\nkugel\nkugels\nkukri\nkukris\nkulak\nkulaki\nkulaks\nkultur\nkulturs\nkumiss\nkumisses\nkummel\nkummels\nkumquat\nkumquats\nkumys\nkumyses\nkuna\nkundalini\nkundalinis\nkune\nkunzite\nkunzites\nkurbash\nkurbashed\nkurbashes\nkurbashing\nkurgan\nkurgans\nkurrajong\nkurrajongs\nkurta\nkurtas\nkurtoses\nkurtosis\nkurtosises\nkuru\nkurus\nkusso\nkussos\nkuvasz\nkuvaszok\nkvas\nkvases\nkvass\nkvasses\nkvetch\nkvetched\nkvetches\nkvetchier\nkvetchiest\nkvetching\nkvetchy\nkwacha\nkwachas\nkwanza\nkwanzas\nkwashiorkor\nkwashiorkors\nkyack\nkyacks\nkyak\nkyaks\nkyanise\nkyanised\nkyanises\nkyanising\nkyanite\nkyanites\nkyanize\nkyanized\nkyanizes\nkyanizing\nkyar\nkyars\nkyat\nkyats\nkybosh\nkyboshed\nkyboshes\nkyboshing\nkylices\nkylikes\nkylix\nkymogram\nkymograms\nkymograph\nkymographic\nkymographies\nkymographs\nkymography\nkyphoses\nkyphosis\nkyphotic\nkyrie\nkyries\nkyte\nkytes\nkythe\nkythed\nkythes\nkything\nla\nlaager\nlaagered\nlaagering\nlaagers\nlaari\nlab\nlabanotation\nlabanotations\nlabara\nlabarum\nlabarums\nlabdanum\nlabdanums\nlabel\nlabelable\nlabeled\nlabeler\nlabelers\nlabeling\nlabella\nlabelled\nlabeller\nlabellers\nlabelling\nlabellum\nlabels\nlabia\nlabial\nlabialization\nlabializations\nlabialize\nlabialized\nlabializes\nlabializing\nlabially\nlabials\nlabiate\nlabiated\nlabiates\nlabile\nlabilities\nlability\nlabiodental\nlabiodentals\nlabiovelar\nlabiovelars\nlabium\nlabor\nlaboratories\nlaboratory\nlabored\nlaborer\nlaborers\nlaboring\nlaborious\nlaboriously\nlaboriousness\nlaboriousnesses\nlaborite\nlaborites\nlabors\nlaborsaving\nlabour\nlaboured\nlabourer\nlabourers\nlabouring\nlabours\nlabra\nlabrador\nlabradorite\nlabradorites\nlabradors\nlabret\nlabrets\nlabroid\nlabroids\nlabrum\nlabrums\nlabrusca\nlabs\nlaburnum\nlaburnums\nlabyrinth\nlabyrinthian\nlabyrinthine\nlabyrinthodont\nlabyrinthodonts\nlabyrinths\nlac\nlaccolith\nlaccolithic\nlaccoliths\nlace\nlaced\nlaceless\nlacelike\nlacer\nlacerate\nlacerated\nlacerates\nlacerating\nlaceration\nlacerations\nlacerative\nlacers\nlacertid\nlacertids\nlaces\nlacewing\nlacewings\nlacewood\nlacewoods\nlacework\nlaceworks\nlacey\nlaches\nlachrymal\nlachrymator\nlachrymators\nlachrymose\nlachrymosely\nlachrymosities\nlachrymosity\nlacier\nlaciest\nlacily\nlaciness\nlacinesses\nlacing\nlacings\nlaciniate\nlaciniation\nlaciniations\nlack\nlackadaisical\nlackadaisically\nlackaday\nlacked\nlacker\nlackered\nlackering\nlackers\nlackey\nlackeyed\nlackeying\nlackeys\nlacking\nlackluster\nlacklusters\nlacks\nlaconic\nlaconically\nlaconism\nlaconisms\nlacquer\nlacquered\nlacquerer\nlacquerers\nlacquering\nlacquers\nlacquerware\nlacquerwares\nlacquerwork\nlacquerworks\nlacquey\nlacqueyed\nlacqueying\nlacqueys\nlacrimal\nlacrimals\nlacrimation\nlacrimations\nlacrimator\nlacrimators\nlacrosse\nlacrosses\nlacs\nlactalbumin\nlactalbumins\nlactam\nlactams\nlactary\nlactase\nlactases\nlactate\nlactated\nlactates\nlactating\nlactation\nlactational\nlactations\nlacteal\nlacteals\nlactean\nlacteous\nlactic\nlactiferous\nlactobacilli\nlactobacillus\nlactogenic\nlactoglobulin\nlactoglobulins\nlactone\nlactones\nlactonic\nlactose\nlactoses\nlacuna\nlacunae\nlacunal\nlacunar\nlacunaria\nlacunars\nlacunary\nlacunas\nlacunate\nlacune\nlacunes\nlacunose\nlacustrine\nlacy\nlad\nladanum\nladanums\nladder\nladdered\nladdering\nladderlike\nladders\nladdie\nladdies\nlade\nladed\nladen\nladened\nladening\nladens\nlader\nladers\nlades\nladies\nlading\nladings\nladino\nladinos\nladle\nladled\nladleful\nladlefuls\nladler\nladlers\nladles\nladling\nladron\nladrone\nladrones\nladrons\nlads\nlady\nladybird\nladybirds\nladybug\nladybugs\nladyfinger\nladyfingers\nladyfish\nladyfishes\nladyhood\nladyhoods\nladyish\nladykin\nladykins\nladylike\nladylove\nladyloves\nladypalm\nladypalms\nladyship\nladyships\nlaetrile\nlaetriles\nlaevo\nlag\nlagan\nlagans\nlagend\nlagends\nlager\nlagered\nlagering\nlagers\nlaggard\nlaggardly\nlaggardness\nlaggardnesses\nlaggards\nlagged\nlagger\nlaggers\nlagging\nlaggings\nlagnappe\nlagnappes\nlagniappe\nlagniappes\nlagomorph\nlagomorphs\nlagoon\nlagoonal\nlagoons\nlags\nlaguna\nlagunas\nlagune\nlagunes\nlahar\nlahars\nlaic\nlaical\nlaically\nlaich\nlaichs\nlaicise\nlaicised\nlaicises\nlaicising\nlaicism\nlaicisms\nlaicization\nlaicizations\nlaicize\nlaicized\nlaicizes\nlaicizing\nlaics\nlaid\nlaigh\nlaighs\nlain\nlair\nlaird\nlairdly\nlairds\nlaired\nlairing\nlairs\nlaitance\nlaitances\nlaith\nlaithly\nlaities\nlaity\nlake\nlaked\nlakefront\nlakefronts\nlakelike\nlakeport\nlakeports\nlaker\nlakers\nlakes\nlakeshore\nlakeshores\nlakeside\nlakesides\nlakh\nlakhs\nlakier\nlakiest\nlaking\nlakings\nlaky\nlall\nlallan\nlalland\nlallands\nlallans\nlalled\nlalling\nlalls\nlallygag\nlallygagged\nlallygagging\nlallygags\nlam\nlama\nlamas\nlamaseries\nlamasery\nlamb\nlambast\nlambaste\nlambasted\nlambastes\nlambasting\nlambasts\nlambda\nlambdas\nlambdoid\nlambed\nlambencies\nlambency\nlambent\nlambently\nlamber\nlambers\nlambert\nlamberts\nlambie\nlambier\nlambies\nlambiest\nlambing\nlambkill\nlambkills\nlambkin\nlambkins\nlamblike\nlambrequin\nlambrequins\nlambs\nlambskin\nlambskins\nlamby\nlame\nlamebrain\nlamebrained\nlamebrains\nlamed\nlamedh\nlamedhs\nlameds\nlamella\nlamellae\nlamellar\nlamellas\nlamellate\nlamellately\nlamellibranch\nlamellibranchs\nlamellicorn\nlamellicorns\nlamelliform\nlamely\nlameness\nlamenesses\nlament\nlamentable\nlamentableness\nlamentablenesses\nlamentably\nlamentation\nlamentations\nlamented\nlamentedly\nlamenter\nlamenters\nlamenting\nlaments\nlamer\nlames\nlamest\nlamia\nlamiae\nlamias\nlamina\nlaminae\nlaminal\nlaminar\nlaminaria\nlaminarian\nlaminarians\nlaminarias\nlaminarin\nlaminarins\nlaminary\nlaminas\nlaminate\nlaminated\nlaminates\nlaminating\nlamination\nlaminations\nlaminator\nlaminators\nlaming\nlaminitis\nlaminitises\nlaminose\nlaminous\nlamister\nlamisters\nlammed\nlammergeier\nlammergeiers\nlammergeyer\nlammergeyers\nlamming\nlamp\nlampad\nlampads\nlampas\nlampases\nlampblack\nlampblacks\nlamped\nlampers\nlamperses\nlamping\nlampion\nlampions\nlamplight\nlamplighter\nlamplighters\nlamplights\nlampoon\nlampooned\nlampooner\nlampooneries\nlampooners\nlampoonery\nlampooning\nlampoons\nlamppost\nlampposts\nlamprey\nlampreys\nlamps\nlampshell\nlampshells\nlampyrid\nlampyrids\nlams\nlamster\nlamsters\nlanai\nlanais\nlanate\nlanated\nlance\nlanced\nlancelet\nlancelets\nlanceolate\nlancer\nlancers\nlances\nlancet\nlanceted\nlancets\nlancewood\nlancewoods\nlanciers\nlancinating\nlancing\nland\nlandau\nlandaulet\nlandaulets\nlandaus\nlanded\nlander\nlanders\nlandfall\nlandfalls\nlandfill\nlandfills\nlandform\nlandforms\nlandgrab\nlandgrabs\nlandholder\nlandholders\nlandholding\nlandholdings\nlanding\nlandings\nlandladies\nlandlady\nlandler\nlandlers\nlandless\nlandlessness\nlandlessnesses\nlandline\nlandlines\nlandlocked\nlandlord\nlandlordism\nlandlordisms\nlandlords\nlandlubber\nlandlubberliness\nlandlubberlinesses\nlandlubberly\nlandlubbers\nlandlubbing\nlandman\nlandmark\nlandmarks\nlandmass\nlandmasses\nlandmen\nlandmine\nlandmines\nlandowner\nlandowners\nlandownership\nlandownerships\nlandowning\nlandownings\nlands\nlandscape\nlandscaped\nlandscaper\nlandscapers\nlandscapes\nlandscaping\nlandscapist\nlandscapists\nlandside\nlandsides\nlandskip\nlandskips\nlandsleit\nlandslid\nlandslide\nlandslides\nlandsliding\nlandslip\nlandslips\nlandsman\nlandsmen\nlandward\nlane\nlanely\nlanes\nlaneway\nlaneways\nlang\nlangbeinite\nlangbeinites\nlanglauf\nlanglaufer\nlanglaufers\nlanglaufs\nlangley\nlangleys\nlangostino\nlangostinos\nlangouste\nlangoustes\nlangoustine\nlangoustines\nlangrage\nlangrages\nlangrel\nlangrels\nlangshan\nlangshans\nlangsyne\nlangsynes\nlanguage\nlanguages\nlangue\nlangues\nlanguet\nlanguets\nlanguid\nlanguidly\nlanguidness\nlanguidnesses\nlanguish\nlanguished\nlanguisher\nlanguishers\nlanguishes\nlanguishing\nlanguishingly\nlanguishment\nlanguishments\nlanguor\nlanguorous\nlanguorously\nlanguors\nlangur\nlangurs\nlaniard\nlaniards\nlaniaries\nlaniary\nlanital\nlanitals\nlank\nlanker\nlankest\nlankier\nlankiest\nlankily\nlankiness\nlankinesses\nlankly\nlankness\nlanknesses\nlanky\nlanner\nlanneret\nlannerets\nlanners\nlanolin\nlanoline\nlanolines\nlanolins\nlanose\nlanosities\nlanosity\nlantana\nlantanas\nlantern\nlanterns\nlanthanide\nlanthanides\nlanthanum\nlanthanums\nlanthorn\nlanthorns\nlanuginous\nlanugo\nlanugos\nlanyard\nlanyards\nlap\nlaparoscope\nlaparoscopes\nlaparoscopic\nlaparoscopies\nlaparoscopist\nlaparoscopists\nlaparoscopy\nlaparotomies\nlaparotomy\nlapboard\nlapboards\nlapdog\nlapdogs\nlapel\nlapeled\nlapelled\nlapels\nlapful\nlapfuls\nlapidarian\nlapidaries\nlapidary\nlapidate\nlapidated\nlapidates\nlapidating\nlapides\nlapidified\nlapidifies\nlapidify\nlapidifying\nlapidist\nlapidists\nlapilli\nlapillus\nlapin\nlapins\nlapis\nlapises\nlapped\nlapper\nlappered\nlappering\nlappers\nlappet\nlappeted\nlappets\nlapping\nlaps\nlapsable\nlapse\nlapsed\nlapser\nlapsers\nlapses\nlapsible\nlapsing\nlapstrake\nlapsus\nlaptop\nlaptops\nlapwing\nlapwings\nlar\nlarboard\nlarboards\nlarcener\nlarceners\nlarcenies\nlarcenist\nlarcenists\nlarcenous\nlarcenously\nlarceny\nlarch\nlarches\nlard\nlarded\nlarder\nlarders\nlardier\nlardiest\nlarding\nlardlike\nlardon\nlardons\nlardoon\nlardoons\nlards\nlardy\nlaree\nlarees\nlares\nlargando\nlarge\nlargehearted\nlargeheartedness\nlargeheartednesses\nlargely\nlargemouth\nlargemouths\nlargeness\nlargenesses\nlarger\nlarges\nlargess\nlargesse\nlargesses\nlargest\nlarghetto\nlarghettos\nlargish\nlargo\nlargos\nlari\nlariat\nlariated\nlariating\nlariats\nlarine\nlaris\nlark\nlarked\nlarker\nlarkers\nlarkier\nlarkiest\nlarkiness\nlarkinesses\nlarking\nlarkish\nlarks\nlarksome\nlarkspur\nlarkspurs\nlarky\nlarrigan\nlarrigans\nlarrikin\nlarrikins\nlarrup\nlarruped\nlarruper\nlarrupers\nlarruping\nlarrups\nlars\nlarum\nlarums\nlarva\nlarvae\nlarval\nlarvas\nlarvicidal\nlarvicide\nlarvicides\nlaryngal\nlaryngals\nlaryngeal\nlaryngeals\nlaryngectomee\nlaryngectomees\nlaryngectomies\nlaryngectomized\nlaryngectomy\nlarynges\nlaryngitic\nlaryngitides\nlaryngitis\nlaryngologies\nlaryngology\nlaryngoscope\nlaryngoscopes\nlaryngoscopies\nlaryngoscopy\nlarynx\nlarynxes\nlas\nlasagna\nlasagnas\nlasagne\nlasagnes\nlascar\nlascars\nlascivious\nlasciviously\nlasciviousness\nlasciviousnesses\nlase\nlased\nlaser\nlasers\nlases\nlash\nlashed\nlasher\nlashers\nlashes\nlashing\nlashings\nlashins\nlashkar\nlashkars\nlasing\nlass\nlasses\nlassie\nlassies\nlassitude\nlassitudes\nlasso\nlassoed\nlassoer\nlassoers\nlassoes\nlassoing\nlassos\nlast\nlasted\nlaster\nlasters\nlasting\nlastingly\nlastingness\nlastingnesses\nlastings\nlastly\nlasts\nlat\nlatakia\nlatakias\nlatch\nlatched\nlatches\nlatchet\nlatchets\nlatching\nlatchkey\nlatchkeys\nlatchstring\nlatchstrings\nlate\nlatecomer\nlatecomers\nlated\nlateen\nlateener\nlateeners\nlateens\nlately\nlaten\nlatencies\nlatency\nlatened\nlateness\nlatenesses\nlatening\nlatens\nlatensification\nlatensifications\nlatent\nlatently\nlatents\nlater\nlaterad\nlateral\nlateraled\nlateraling\nlateralization\nlateralizations\nlateralize\nlateralized\nlateralizes\nlateralizing\nlateralled\nlateralling\nlaterally\nlaterals\nlaterite\nlaterites\nlateritic\nlaterization\nlaterizations\nlaterize\nlaterized\nlaterizes\nlaterizing\nlatest\nlatests\nlatewood\nlatewoods\nlatex\nlatexes\nlath\nlathe\nlathed\nlather\nlathered\nlatherer\nlatherers\nlathering\nlathers\nlathery\nlathes\nlathi\nlathier\nlathiest\nlathing\nlathings\nlathis\nlaths\nlathwork\nlathworks\nlathy\nlathyrism\nlathyrisms\nlathyritic\nlati\nlatices\nlaticifer\nlaticifers\nlatifundia\nlatifundio\nlatifundios\nlatifundium\nlatigo\nlatigoes\nlatigos\nlatinities\nlatinity\nlatinization\nlatinizations\nlatinize\nlatinized\nlatinizes\nlatinizing\nlatino\nlatinos\nlatish\nlatitude\nlatitudes\nlatitudinal\nlatitudinally\nlatitudinarian\nlatitudinarianism\nlatitudinarianisms\nlatitudinarians\nlatke\nlatkes\nlatosol\nlatosolic\nlatosols\nlatria\nlatrias\nlatrine\nlatrines\nlats\nlatte\nlatten\nlattens\nlatter\nlatterly\nlattes\nlattice\nlatticed\nlattices\nlatticework\nlatticeworks\nlatticing\nlattin\nlattins\nlauan\nlauans\nlaud\nlaudable\nlaudableness\nlaudablenesses\nlaudably\nlaudanum\nlaudanums\nlaudation\nlaudations\nlaudative\nlaudator\nlaudators\nlaudatory\nlauded\nlauder\nlauders\nlauding\nlauds\nlaugh\nlaughable\nlaughableness\nlaughablenesses\nlaughably\nlaughed\nlaugher\nlaughers\nlaughing\nlaughingly\nlaughings\nlaughingstock\nlaughingstocks\nlaughs\nlaughter\nlaughters\nlaunce\nlaunces\nlaunch\nlaunched\nlauncher\nlaunchers\nlaunches\nlaunching\nlaunchpad\nlaunchpads\nlaunder\nlaundered\nlaunderer\nlaunderers\nlaunderette\nlaunderettes\nlaundering\nlaunders\nlaundress\nlaundresses\nlaundrette\nlaundrettes\nlaundries\nlaundromat\nlaundromats\nlaundry\nlaundryman\nlaundrymen\nlaura\nlaurae\nlauras\nlaureate\nlaureated\nlaureates\nlaureateship\nlaureateships\nlaureating\nlaureation\nlaureations\nlaurel\nlaureled\nlaureling\nlaurelled\nlaurelling\nlaurels\nlauwine\nlauwines\nlav\nlava\nlavabo\nlavaboes\nlavabos\nlavage\nlavages\nlavalava\nlavalavas\nlavalier\nlavaliere\nlavalieres\nlavaliers\nlavalike\nlavalliere\nlavallieres\nlavas\nlavation\nlavations\nlavatories\nlavatory\nlave\nlaved\nlaveer\nlaveered\nlaveering\nlaveers\nlavender\nlavendered\nlavendering\nlavenders\nlaver\nlaverock\nlaverocks\nlavers\nlaves\nlaving\nlavish\nlavished\nlavisher\nlavishers\nlavishes\nlavishest\nlavishing\nlavishly\nlavishness\nlavishnesses\nlavrock\nlavrocks\nlavs\nlaw\nlawbook\nlawbooks\nlawbreaker\nlawbreakers\nlawbreaking\nlawbreakings\nlawed\nlawful\nlawfully\nlawfulness\nlawfulnesses\nlawgiver\nlawgivers\nlawine\nlawines\nlawing\nlawings\nlawless\nlawlessly\nlawlessness\nlawlessnesses\nlawlike\nlawmaker\nlawmakers\nlawmaking\nlawmakings\nlawman\nlawmen\nlawn\nlawnmower\nlawnmowers\nlawns\nlawny\nlawrencium\nlawrenciums\nlaws\nlawsuit\nlawsuits\nlawyer\nlawyered\nlawyering\nlawyerings\nlawyerlike\nlawyerly\nlawyers\nlax\nlaxation\nlaxations\nlaxative\nlaxatives\nlaxer\nlaxest\nlaxities\nlaxity\nlaxly\nlaxness\nlaxnesses\nlay\nlayabout\nlayabouts\nlayaway\nlayaways\nlayed\nlayer\nlayerage\nlayerages\nlayered\nlayering\nlayerings\nlayers\nlayette\nlayettes\nlaying\nlayman\nlaymen\nlayoff\nlayoffs\nlayout\nlayouts\nlayover\nlayovers\nlaypeople\nlayperson\nlaypersons\nlays\nlayup\nlayups\nlaywoman\nlaywomen\nlazar\nlazaret\nlazarets\nlazarette\nlazarettes\nlazaretto\nlazarettos\nlazars\nlaze\nlazed\nlazes\nlazied\nlazier\nlazies\nlaziest\nlazily\nlaziness\nlazinesses\nlazing\nlazuli\nlazulis\nlazulite\nlazulites\nlazurite\nlazurites\nlazy\nlazybones\nlazying\nlazyish\nlea\nleach\nleachabilities\nleachability\nleachable\nleachate\nleachates\nleached\nleacher\nleachers\nleaches\nleachier\nleachiest\nleaching\nleachy\nlead\nleaded\nleaden\nleadenly\nleadenness\nleadennesses\nleader\nleaderboard\nleaderboards\nleaderless\nleaders\nleadership\nleaderships\nleadier\nleadiest\nleading\nleadings\nleadless\nleadman\nleadmen\nleadoff\nleadoffs\nleadplant\nleadplants\nleads\nleadscrew\nleadscrews\nleadsman\nleadsmen\nleadwork\nleadworks\nleadwort\nleadworts\nleady\nleaf\nleafage\nleafages\nleafed\nleafhopper\nleafhoppers\nleafier\nleafiest\nleafing\nleafless\nleaflet\nleafleted\nleafleteer\nleafleteers\nleafleting\nleaflets\nleafletted\nleafletting\nleaflike\nleafs\nleafstalk\nleafstalks\nleafworm\nleafworms\nleafy\nleague\nleagued\nleaguer\nleaguered\nleaguering\nleaguers\nleagues\nleaguing\nleak\nleakage\nleakages\nleaked\nleaker\nleakers\nleakier\nleakiest\nleakily\nleakiness\nleakinesses\nleaking\nleakless\nleakproof\nleaks\nleaky\nleal\nleally\nlealties\nlealty\nlean\nleaned\nleaner\nleaners\nleanest\nleaning\nleanings\nleanly\nleanness\nleannesses\nleans\nleant\nleap\nleaped\nleaper\nleapers\nleapfrog\nleapfrogged\nleapfrogging\nleapfrogs\nleaping\nleaps\nleapt\nlear\nlearier\nleariest\nlearn\nlearnable\nlearned\nlearnedly\nlearnedness\nlearnednesses\nlearner\nlearners\nlearning\nlearnings\nlearns\nlearnt\nlears\nleary\nleas\nleasable\nlease\nleaseback\nleasebacks\nleased\nleasehold\nleaseholder\nleaseholders\nleaseholds\nleaser\nleasers\nleases\nleash\nleashed\nleashes\nleashing\nleasing\nleasings\nleast\nleasts\nleastways\nleastwise\nleather\nleatherback\nleatherbacks\nleathered\nleatherette\nleatherettes\nleathering\nleatherleaf\nleatherleaves\nleatherlike\nleathern\nleatherneck\nleathernecks\nleathers\nleatherwood\nleatherwoods\nleathery\nleave\nleaved\nleaven\nleavened\nleavening\nleavenings\nleavens\nleaver\nleavers\nleaves\nleavier\nleaviest\nleaving\nleavings\nleavy\nleben\nlebens\nlebensraum\nlebensraums\nlech\nlechayim\nlechayims\nleched\nlecher\nlechered\nlecheries\nlechering\nlecherous\nlecherously\nlecherousness\nlecherousnesses\nlechers\nlechery\nleches\nleching\nlechwe\nlechwes\nlecithin\nlecithinase\nlecithinases\nlecithins\nlectern\nlecterns\nlectin\nlectins\nlection\nlectionaries\nlectionary\nlections\nlector\nlectors\nlectotype\nlectotypes\nlecture\nlectured\nlecturer\nlecturers\nlectures\nlectureship\nlectureships\nlecturing\nlecythi\nlecythis\nlecythus\nled\nlederhosen\nledge\nledger\nledgers\nledges\nledgier\nledgiest\nledgy\nlee\nleeboard\nleeboards\nleech\nleeched\nleeches\nleeching\nleechlike\nleek\nleeks\nleer\nleered\nleerier\nleeriest\nleerily\nleering\nleeringly\nleers\nleery\nlees\nleet\nleets\nleeward\nleewards\nleeway\nleeways\nleft\nlefter\nleftest\nlefties\nleftish\nleftism\nleftisms\nleftist\nleftists\nleftmost\nleftover\nleftovers\nlefts\nleftward\nleftwards\nleftwing\nlefty\nleg\nlegacies\nlegacy\nlegal\nlegalese\nlegaleses\nlegalise\nlegalised\nlegalises\nlegalising\nlegalism\nlegalisms\nlegalist\nlegalistic\nlegalistically\nlegalists\nlegalities\nlegality\nlegalization\nlegalizations\nlegalize\nlegalized\nlegalizer\nlegalizers\nlegalizes\nlegalizing\nlegally\nlegals\nlegate\nlegated\nlegatee\nlegatees\nlegates\nlegateship\nlegateships\nlegatine\nlegating\nlegation\nlegations\nlegato\nlegator\nlegators\nlegatos\nlegend\nlegendarily\nlegendary\nlegendries\nlegendry\nlegends\nleger\nlegerdemain\nlegerdemains\nlegerities\nlegerity\nlegers\nleges\nlegged\nleggier\nleggiero\nleggiest\nleggin\nlegginess\nlegginesses\nlegging\nleggings\nleggins\nleggy\nleghorn\nleghorns\nlegibilities\nlegibility\nlegible\nlegibly\nlegion\nlegionaries\nlegionary\nlegionnaire\nlegionnaires\nlegions\nlegislate\nlegislated\nlegislates\nlegislating\nlegislation\nlegislations\nlegislative\nlegislatively\nlegislatives\nlegislator\nlegislatorial\nlegislators\nlegislatorship\nlegislatorships\nlegislature\nlegislatures\nlegist\nlegists\nlegit\nlegitimacies\nlegitimacy\nlegitimate\nlegitimated\nlegitimately\nlegitimates\nlegitimating\nlegitimation\nlegitimations\nlegitimatize\nlegitimatized\nlegitimatizes\nlegitimatizing\nlegitimator\nlegitimators\nlegitimise\nlegitimised\nlegitimises\nlegitimising\nlegitimism\nlegitimisms\nlegitimist\nlegitimists\nlegitimization\nlegitimizations\nlegitimize\nlegitimized\nlegitimizer\nlegitimizers\nlegitimizes\nlegitimizing\nlegits\nlegless\nleglike\nlegman\nlegmen\nlegong\nlegongs\nlegroom\nlegrooms\nlegs\nlegume\nlegumes\nlegumin\nleguminous\nlegumins\nlegwork\nlegworks\nlehayim\nlehayims\nlehr\nlehrs\nlehua\nlehuas\nlei\nleis\nleishmania\nleishmanial\nleishmanias\nleishmaniases\nleishmaniasis\nleister\nleistered\nleistering\nleisters\nleisure\nleisured\nleisureliness\nleisurelinesses\nleisurely\nleisures\nleisurewear\nleitmotif\nleitmotifs\nleitmotiv\nleitmotivs\nlek\nleke\nleks\nleku\nlekvar\nlekvars\nlekythi\nlekythoi\nlekythos\nlekythus\nleman\nlemans\nlemma\nlemmas\nlemmata\nlemming\nlemminglike\nlemmings\nlemniscal\nlemniscate\nlemniscates\nlemnisci\nlemniscus\nlemon\nlemonade\nlemonades\nlemongrass\nlemongrasses\nlemonish\nlemons\nlemony\nlempira\nlempiras\nlemur\nlemures\nlemurine\nlemuroid\nlemuroids\nlemurs\nlend\nlendable\nlender\nlenders\nlending\nlends\nlenes\nlength\nlengthen\nlengthened\nlengthener\nlengtheners\nlengthening\nlengthens\nlengthier\nlengthiest\nlengthily\nlengthiness\nlengthinesses\nlengths\nlengthways\nlengthwise\nlengthy\nlenience\nleniences\nleniencies\nleniency\nlenient\nleniently\nlenis\nlenities\nlenition\nlenitions\nlenitive\nlenitively\nlenitives\nlenity\nleno\nlenos\nlens\nlense\nlensed\nlenses\nlensing\nlensless\nlensman\nlensmen\nlent\nlentamente\nlentando\nlenten\nlentic\nlenticel\nlenticels\nlenticular\nlenticule\nlenticules\nlentigines\nlentigo\nlentil\nlentils\nlentisk\nlentisks\nlentissimo\nlentivirus\nlentiviruses\nlento\nlentoid\nlentos\nleone\nleones\nleonine\nleopard\nleopardess\nleopardesses\nleopards\nleotard\nleotarded\nleotards\nleper\nlepers\nlepidolite\nlepidolites\nlepidoptera\nlepidopteran\nlepidopterans\nlepidopterist\nlepidopterists\nlepidopterological\nlepidopterologies\nlepidopterologist\nlepidopterologists\nlepidopterology\nlepidopterous\nlepidote\nlepidotes\nleporid\nleporidae\nleporids\nleporine\nleprechaun\nleprechaunish\nleprechauns\nlepromatous\nleprosaria\nleprosarium\nleprosariums\nleprose\nleprosies\nleprosy\nleprotic\nleprous\nleprously\nlept\nlepta\nleptocephali\nleptocephalus\nlepton\nleptonic\nleptons\nleptosome\nleptosomes\nleptospiral\nleptospire\nleptospires\nleptospiroses\nleptospirosis\nleptotene\nleptotenes\nlesbian\nlesbianism\nlesbianisms\nlesbians\nlesion\nlesioned\nlesions\nlespedeza\nlespedezas\nless\nlessee\nlessees\nlessen\nlessened\nlessening\nlessens\nlesser\nlesson\nlessoned\nlessoning\nlessons\nlessor\nlessors\nlest\nlet\nletch\nletched\nletches\nletching\nletdown\nletdowns\nlethal\nlethalities\nlethality\nlethally\nlethals\nlethargic\nlethargically\nlethargies\nlethargy\nlethe\nlethean\nlethes\nlets\nletted\nletter\nletterbomb\nletterbombs\nletterboxed\nletterboxing\nletterboxings\nlettered\nletterer\nletterers\nletterform\nletterforms\nletterhead\nletterheads\nlettering\nletterings\nletterman\nlettermen\nletterpress\nletterpresses\nletters\nletterspace\nletterspaces\nletterspacing\nletterspacings\nletting\nlettuce\nlettuces\nletup\nletups\nleu\nleucemia\nleucemias\nleucemic\nleucin\nleucine\nleucines\nleucins\nleucite\nleucites\nleucitic\nleucocidin\nleucocidins\nleucoma\nleucomas\nleucoplast\nleucoplasts\nleud\nleudes\nleuds\nleukaemia\nleukaemias\nleukaemogeneses\nleukaemogenesis\nleukemia\nleukemias\nleukemic\nleukemics\nleukemogeneses\nleukemogenesis\nleukemogenic\nleukemoid\nleukocyte\nleukocytes\nleukocytic\nleukocytoses\nleukocytosis\nleukodystrophies\nleukodystrophy\nleukoma\nleukomas\nleukon\nleukons\nleukopenia\nleukopenias\nleukopenic\nleukoplakia\nleukoplakias\nleukoplakic\nleukopoieses\nleukopoiesis\nleukopoietic\nleukorrhea\nleukorrheal\nleukorrheas\nleukoses\nleukosis\nleukotic\nleukotomies\nleukotomy\nleukotriene\nleukotrienes\nlev\nleva\nlevant\nlevanted\nlevanter\nlevanters\nlevanting\nlevants\nlevator\nlevatores\nlevators\nlevee\nleveed\nleveeing\nlevees\nlevel\nleveled\nleveler\nlevelers\nlevelheaded\nlevelheadedness\nlevelheadednesses\nleveling\nlevelled\nleveller\nlevellers\nlevelling\nlevelly\nlevelness\nlevelnesses\nlevels\nlever\nleverage\nleveraged\nleverages\nleveraging\nlevered\nleveret\nleverets\nlevering\nlevers\nleviable\nleviathan\nleviathans\nlevied\nlevier\nleviers\nlevies\nlevigate\nlevigated\nlevigates\nlevigating\nlevigation\nlevigations\nlevin\nlevins\nlevirate\nlevirates\nleviratic\nlevitate\nlevitated\nlevitates\nlevitating\nlevitation\nlevitational\nlevitations\nlevities\nlevity\nlevo\nlevodopa\nlevodopas\nlevogyre\nlevorotary\nlevorotatory\nlevulin\nlevulins\nlevulose\nlevuloses\nlevy\nlevying\nlewd\nlewder\nlewdest\nlewdly\nlewdness\nlewdnesses\nlewis\nlewises\nlewisite\nlewisites\nlewisson\nlewissons\nlex\nlexeme\nlexemes\nlexemic\nlexes\nlexica\nlexical\nlexicalisation\nlexicalisations\nlexicalities\nlexicality\nlexicalization\nlexicalizations\nlexicalize\nlexicalized\nlexicalizes\nlexicalizing\nlexically\nlexicographer\nlexicographers\nlexicographic\nlexicographical\nlexicographically\nlexicographies\nlexicography\nlexicologies\nlexicologist\nlexicologists\nlexicology\nlexicon\nlexicons\nlexis\nlexises\nley\nleys\nlez\nlezzes\nlezzie\nlezzies\nlezzy\nli\nliabilities\nliability\nliable\nliaise\nliaised\nliaises\nliaising\nliaison\nliaisons\nliana\nlianas\nliane\nlianes\nliang\nliangs\nlianoid\nliar\nliard\nliards\nliars\nlib\nlibation\nlibationary\nlibations\nlibber\nlibbers\nlibecchio\nlibecchios\nlibeccio\nlibeccios\nlibel\nlibelant\nlibelants\nlibeled\nlibelee\nlibelees\nlibeler\nlibelers\nlibeling\nlibelist\nlibelists\nlibellant\nlibellants\nlibelled\nlibellee\nlibellees\nlibeller\nlibellers\nlibelling\nlibellous\nlibelous\nlibels\nliber\nliberal\nliberalise\nliberalised\nliberalises\nliberalising\nliberalism\nliberalisms\nliberalist\nliberalistic\nliberalists\nliberalities\nliberality\nliberalization\nliberalizations\nliberalize\nliberalized\nliberalizer\nliberalizers\nliberalizes\nliberalizing\nliberally\nliberalness\nliberalnesses\nliberals\nliberate\nliberated\nliberates\nliberating\nliberation\nliberationist\nliberationists\nliberations\nliberator\nliberators\nlibers\nlibertarian\nlibertarianism\nlibertarianisms\nlibertarians\nliberties\nlibertinage\nlibertinages\nlibertine\nlibertines\nlibertinism\nlibertinisms\nliberty\nlibidinal\nlibidinally\nlibidinous\nlibidinously\nlibidinousness\nlibidinousnesses\nlibido\nlibidos\nliblab\nliblabs\nlibra\nlibrae\nlibrarian\nlibrarians\nlibrarianship\nlibrarianships\nlibraries\nlibrary\nlibras\nlibrate\nlibrated\nlibrates\nlibrating\nlibration\nlibrational\nlibrations\nlibratory\nlibretti\nlibrettist\nlibrettists\nlibretto\nlibrettos\nlibri\nlibriform\nlibs\nlice\nlicence\nlicenced\nlicencee\nlicencees\nlicencer\nlicencers\nlicences\nlicencing\nlicensable\nlicense\nlicensed\nlicensee\nlicensees\nlicenser\nlicensers\nlicenses\nlicensing\nlicensor\nlicensors\nlicensure\nlicensures\nlicente\nlicentiate\nlicentiates\nlicentious\nlicentiously\nlicentiousness\nlicentiousnesses\nlich\nlichee\nlichees\nlichen\nlichened\nlichenin\nlichening\nlichenins\nlichenological\nlichenologies\nlichenologist\nlichenologists\nlichenology\nlichenous\nlichens\nliches\nlichi\nlichis\nlicht\nlichted\nlichting\nlichtly\nlichts\nlicit\nlicitly\nlick\nlicked\nlicker\nlickerish\nlickerishly\nlickerishness\nlickerishnesses\nlickers\nlicking\nlickings\nlicks\nlickspit\nlickspits\nlickspittle\nlickspittles\nlicorice\nlicorices\nlictor\nlictors\nlid\nlidar\nlidars\nlidded\nlidding\nlidless\nlido\nlidocaine\nlidocaines\nlidos\nlids\nlie\nliebfraumilch\nliebfraumilchs\nlied\nlieder\nlief\nliefer\nliefest\nliefly\nliege\nliegeman\nliegemen\nlieges\nlien\nlienable\nlienal\nliens\nlienteries\nlientery\nlier\nlierne\nliernes\nliers\nlies\nlieu\nlieus\nlieutenancies\nlieutenancy\nlieutenant\nlieutenants\nlieve\nliever\nlievest\nlife\nlifeblood\nlifebloods\nlifeboat\nlifeboats\nlifeful\nlifeguard\nlifeguarded\nlifeguarding\nlifeguards\nlifeless\nlifelessly\nlifelessness\nlifelessnesses\nlifelike\nlifelikeness\nlifelikenesses\nlifeline\nlifelines\nlifelong\nlifemanship\nlifemanships\nlifer\nlifers\nlifesaver\nlifesavers\nlifesaving\nlifesavings\nlifestyle\nlifestyles\nlifetime\nlifetimes\nlifeway\nlifeways\nlifework\nlifeworks\nlift\nliftable\nlifted\nlifter\nlifters\nliftgate\nliftgates\nlifting\nliftman\nliftmen\nliftoff\nliftoffs\nlifts\nligament\nligamentous\nligaments\nligan\nligand\nligands\nligans\nligase\nligases\nligate\nligated\nligates\nligating\nligation\nligations\nligative\nligature\nligatured\nligatures\nligaturing\nliger\nligers\nlight\nlightbulb\nlightbulbs\nlighted\nlighten\nlightened\nlightener\nlighteners\nlightening\nlightens\nlighter\nlighterage\nlighterages\nlightered\nlightering\nlighters\nlightest\nlightface\nlightfaced\nlightfaces\nlightfast\nlightfastness\nlightfastnesses\nlightful\nlightheaded\nlighthearted\nlightheartedly\nlightheartedness\nlightheartednesses\nlighthouse\nlighthouses\nlighting\nlightings\nlightish\nlightless\nlightly\nlightness\nlightnesses\nlightning\nlightninged\nlightnings\nlightplane\nlightplanes\nlightproof\nlights\nlightship\nlightships\nlightsome\nlightsomely\nlightsomeness\nlightsomenesses\nlighttight\nlightweight\nlightweights\nlightwood\nlightwoods\nligneous\nlignification\nlignifications\nlignified\nlignifies\nlignify\nlignifying\nlignin\nlignins\nlignite\nlignites\nlignitic\nlignocellulose\nlignocelluloses\nlignocellulosic\nlignosulfonate\nlignosulfonates\nligroin\nligroine\nligroines\nligroins\nligula\nligulae\nligular\nligulas\nligulate\nligule\nligules\nliguloid\nligure\nligures\nlikabilities\nlikability\nlikable\nlikableness\nlikablenesses\nlike\nlikeable\nliked\nlikelier\nlikeliest\nlikelihood\nlikelihoods\nlikely\nliken\nlikened\nlikeness\nlikenesses\nlikening\nlikens\nliker\nlikers\nlikes\nlikest\nlikewise\nliking\nlikings\nlikuta\nlilac\nlilacs\nlilangeni\nlilied\nlilies\nlilliput\nlilliputian\nlilliputians\nlilliputs\nlilt\nlilted\nlilting\nliltingly\nliltingness\nliltingnesses\nlilts\nlily\nlilylike\nlima\nlimacine\nlimacon\nlimacons\nliman\nlimans\nlimas\nlimb\nlimba\nlimbas\nlimbate\nlimbeck\nlimbecks\nlimbed\nlimber\nlimbered\nlimberer\nlimberest\nlimbering\nlimberly\nlimberness\nlimbernesses\nlimbers\nlimbi\nlimbic\nlimbier\nlimbiest\nlimbing\nlimbless\nlimbo\nlimbos\nlimbs\nlimbus\nlimbuses\nlimby\nlime\nlimeade\nlimeades\nlimed\nlimekiln\nlimekilns\nlimeless\nlimelight\nlimelighted\nlimelighting\nlimelights\nlimen\nlimens\nlimerick\nlimericks\nlimes\nlimestone\nlimestones\nlimewater\nlimewaters\nlimey\nlimeys\nlimier\nlimiest\nlimina\nliminal\nliminess\nliminesses\nliming\nlimit\nlimitable\nlimitary\nlimitation\nlimitational\nlimitations\nlimitative\nlimited\nlimitedly\nlimitedness\nlimitednesses\nlimiteds\nlimiter\nlimiters\nlimites\nlimiting\nlimitingly\nlimitless\nlimitlessly\nlimitlessness\nlimitlessnesses\nlimitrophe\nlimits\nlimmer\nlimmers\nlimn\nlimned\nlimner\nlimners\nlimnetic\nlimnic\nlimning\nlimnologic\nlimnological\nlimnologies\nlimnologist\nlimnologists\nlimnology\nlimns\nlimo\nlimonene\nlimonenes\nlimonite\nlimonites\nlimonitic\nlimos\nlimousine\nlimousines\nlimp\nlimpa\nlimpas\nlimped\nlimper\nlimpers\nlimpest\nlimpet\nlimpets\nlimpid\nlimpidities\nlimpidity\nlimpidly\nlimpidness\nlimpidnesses\nlimping\nlimpkin\nlimpkins\nlimply\nlimpness\nlimpnesses\nlimps\nlimpsey\nlimpsier\nlimpsiest\nlimpsy\nlimuli\nlimuloid\nlimuloids\nlimulus\nlimy\nlin\nlinable\nlinac\nlinacs\nlinage\nlinages\nlinalol\nlinalols\nlinalool\nlinalools\nlinchpin\nlinchpins\nlincomycin\nlincomycins\nlindane\nlindanes\nlinden\nlindens\nlindies\nlindy\nline\nlineable\nlineage\nlineages\nlineal\nlinealities\nlineality\nlineally\nlineament\nlineamental\nlineaments\nlinear\nlinearise\nlinearised\nlinearises\nlinearising\nlinearities\nlinearity\nlinearization\nlinearizations\nlinearize\nlinearized\nlinearizes\nlinearizing\nlinearly\nlineate\nlineated\nlineation\nlineations\nlinebacker\nlinebackers\nlinebacking\nlinebackings\nlinebred\nlinebreeding\nlinebreedings\nlinecaster\nlinecasters\nlinecasting\nlinecastings\nlinecut\nlinecuts\nlined\nlineless\nlinelike\nlineman\nlinemen\nlinen\nlinens\nlineny\nliner\nlinerboard\nlinerboards\nlinerless\nliners\nlines\nlinesman\nlinesmen\nlineup\nlineups\nliney\nling\nlinga\nlingam\nlingams\nlingas\nlingcod\nlingcods\nlinger\nlingered\nlingerer\nlingerers\nlingerie\nlingeries\nlingering\nlingeringly\nlingers\nlingier\nlingiest\nlingo\nlingoes\nlingonberries\nlingonberry\nlings\nlingua\nlinguae\nlingual\nlingually\nlinguals\nlinguine\nlinguines\nlinguini\nlinguinis\nlinguist\nlinguistic\nlinguistical\nlinguistically\nlinguistician\nlinguisticians\nlinguistics\nlinguists\nlingy\nlinier\nliniest\nliniment\nliniments\nlinin\nlining\nlinings\nlinins\nlink\nlinkable\nlinkage\nlinkages\nlinkboy\nlinkboys\nlinked\nlinker\nlinkers\nlinking\nlinkman\nlinkmen\nlinks\nlinksman\nlinksmen\nlinkup\nlinkups\nlinkwork\nlinkworks\nlinky\nlinn\nlinnet\nlinnets\nlinns\nlino\nlinocut\nlinocuts\nlinoleate\nlinoleates\nlinoleum\nlinoleums\nlinos\nlins\nlinsang\nlinsangs\nlinseed\nlinseeds\nlinsey\nlinseys\nlinstock\nlinstocks\nlint\nlintel\nlintels\nlinter\nlinters\nlintier\nlintiest\nlintless\nlintol\nlintols\nlints\nlintwhite\nlintwhites\nlinty\nlinum\nlinums\nlinuron\nlinurons\nliny\nlion\nlioness\nlionesses\nlionfish\nlionfishes\nlionhearted\nlionise\nlionised\nlioniser\nlionisers\nlionises\nlionising\nlionization\nlionizations\nlionize\nlionized\nlionizer\nlionizers\nlionizes\nlionizing\nlionlike\nlions\nlip\nlipa\nlipase\nlipases\nlipe\nlipid\nlipide\nlipides\nlipidic\nlipids\nlipin\nlipins\nlipless\nliplike\nlipocyte\nlipocytes\nlipogeneses\nlipogenesis\nlipoid\nlipoidal\nlipoids\nlipolyses\nlipolysis\nlipolytic\nlipoma\nlipomas\nlipomata\nlipomatous\nlipophilic\nlipopolysaccharide\nlipopolysaccharides\nlipoprotein\nlipoproteins\nliposomal\nliposome\nliposomes\nliposuction\nliposuctions\nlipotropic\nlipotropin\nlipotropins\nlipped\nlippen\nlippened\nlippening\nlippens\nlipper\nlippered\nlippering\nlippers\nlippier\nlippiest\nlipping\nlippings\nlippy\nlipreading\nlipreadings\nlips\nlipstick\nlipsticked\nlipsticks\nliquate\nliquated\nliquates\nliquating\nliquation\nliquations\nliquefaction\nliquefactions\nliquefied\nliquefier\nliquefiers\nliquefies\nliquefy\nliquefying\nliquescent\nliqueur\nliqueurs\nliquid\nliquidambar\nliquidambars\nliquidate\nliquidated\nliquidates\nliquidating\nliquidation\nliquidations\nliquidator\nliquidators\nliquidities\nliquidity\nliquidize\nliquidized\nliquidizes\nliquidizing\nliquidly\nliquidness\nliquidnesses\nliquids\nliquified\nliquifies\nliquify\nliquifying\nliquor\nliquored\nliquorice\nliquorices\nliquoring\nliquors\nlira\nliras\nlire\nliri\nliripipe\nliripipes\nlirot\nliroth\nlis\nlisente\nlisle\nlisles\nlisp\nlisped\nlisper\nlispers\nlisping\nlisps\nlissom\nlissome\nlissomely\nlissomeness\nlissomenesses\nlissomly\nlist\nlistable\nlisted\nlistee\nlistees\nlistel\nlistels\nlisten\nlistenable\nlistened\nlistener\nlisteners\nlistenership\nlistenerships\nlistening\nlistens\nlister\nlisterioses\nlisteriosis\nlisters\nlisting\nlistings\nlistless\nlistlessly\nlistlessness\nlistlessnesses\nlists\nlit\nlitai\nlitanies\nlitany\nlitas\nlitchi\nlitchis\nlite\nliter\nliteracies\nliteracy\nliteral\nliteralism\nliteralisms\nliteralist\nliteralistic\nliteralists\nliteralities\nliterality\nliteralization\nliteralizations\nliteralize\nliteralized\nliteralizes\nliteralizing\nliterally\nliteralness\nliteralnesses\nliterals\nliterarily\nliterariness\nliterarinesses\nliterary\nliterate\nliterately\nliterateness\nliteratenesses\nliterates\nliterati\nliteratim\nliteration\nliterations\nliterator\nliterators\nliterature\nliteratures\nliteratus\nliters\nlitharge\nlitharges\nlithe\nlithely\nlithemia\nlithemias\nlithemic\nlitheness\nlithenesses\nlither\nlithesome\nlithest\nlithia\nlithias\nlithiases\nlithiasis\nlithic\nlithification\nlithifications\nlithified\nlithifies\nlithify\nlithifying\nlithium\nlithiums\nlitho\nlithoed\nlithograph\nlithographed\nlithographer\nlithographers\nlithographic\nlithographically\nlithographies\nlithographing\nlithographs\nlithography\nlithoid\nlithoing\nlithologic\nlithological\nlithologically\nlithologies\nlithology\nlithophane\nlithophanes\nlithophyte\nlithophytes\nlithopone\nlithopones\nlithos\nlithosol\nlithosols\nlithosphere\nlithospheres\nlithospheric\nlithotomies\nlithotomy\nlithotripsies\nlithotripsy\nlithotripter\nlithotripters\nlithotriptor\nlithotriptors\nlitigable\nlitigant\nlitigants\nlitigate\nlitigated\nlitigates\nlitigating\nlitigation\nlitigations\nlitigator\nlitigators\nlitigious\nlitigiously\nlitigiousness\nlitigiousnesses\nlitmus\nlitmuses\nlitoral\nlitotes\nlitotic\nlitre\nlitres\nlits\nlitten\nlitter\nlitterateur\nlitterateurs\nlitterbag\nlitterbags\nlitterbug\nlitterbugs\nlittered\nlitterer\nlitterers\nlittering\nlittermate\nlittermates\nlitters\nlittery\nlittle\nlittleneck\nlittlenecks\nlittleness\nlittlenesses\nlittler\nlittles\nlittlest\nlittlish\nlittoral\nlittorals\nlitu\nliturgic\nliturgical\nliturgically\nliturgics\nliturgies\nliturgiologies\nliturgiologist\nliturgiologists\nliturgiology\nliturgist\nliturgists\nliturgy\nlivabilities\nlivability\nlivable\nlivableness\nlivablenesses\nlive\nliveabilities\nliveability\nliveable\nlived\nlivelier\nliveliest\nlivelihood\nlivelihoods\nlivelily\nliveliness\nlivelinesses\nlivelong\nlively\nliven\nlivened\nlivener\nliveners\nliveness\nlivenesses\nlivening\nlivens\nliver\nliveried\nliveries\nliverish\nliverishness\nliverishnesses\nlivers\nliverwort\nliverworts\nliverwurst\nliverwursts\nlivery\nliveryman\nliverymen\nlives\nlivest\nlivestock\nlivestocks\nlivetrap\nlivetrapped\nlivetrapping\nlivetraps\nlivid\nlividities\nlividity\nlividly\nlividness\nlividnesses\nlivier\nliviers\nliving\nlivingly\nlivingness\nlivingnesses\nlivings\nlivre\nlivres\nlivyer\nlivyers\nlixivia\nlixivial\nlixiviate\nlixiviated\nlixiviates\nlixiviating\nlixiviation\nlixiviations\nlixivium\nlixiviums\nlizard\nlizards\nllama\nllamas\nllano\nllanos\nlo\nloach\nloaches\nload\nloaded\nloader\nloaders\nloading\nloadings\nloadmaster\nloadmasters\nloads\nloadstar\nloadstars\nloadstone\nloadstones\nloaf\nloafed\nloafer\nloafers\nloafing\nloafs\nloam\nloamed\nloamier\nloamiest\nloaming\nloamless\nloams\nloamy\nloan\nloanable\nloaned\nloaner\nloaners\nloaning\nloanings\nloans\nloanword\nloanwords\nloath\nloathe\nloathed\nloather\nloathers\nloathes\nloathful\nloathing\nloathings\nloathly\nloathness\nloathnesses\nloathsome\nloathsomely\nloathsomeness\nloathsomenesses\nloaves\nlob\nlobar\nlobate\nlobated\nlobately\nlobation\nlobations\nlobbed\nlobber\nlobbers\nlobbied\nlobbies\nlobbing\nlobby\nlobbyer\nlobbyers\nlobbygow\nlobbygows\nlobbying\nlobbyism\nlobbyisms\nlobbyist\nlobbyists\nlobe\nlobectomies\nlobectomy\nlobed\nlobefin\nlobefins\nlobelia\nlobelias\nlobeline\nlobelines\nlobes\nloblollies\nloblolly\nlobo\nlobos\nlobotomies\nlobotomise\nlobotomised\nlobotomises\nlobotomising\nlobotomize\nlobotomized\nlobotomizes\nlobotomizing\nlobotomy\nlobs\nlobscouse\nlobscouses\nlobster\nlobstered\nlobstering\nlobsterings\nlobsterlike\nlobsterman\nlobstermen\nlobsters\nlobstick\nlobsticks\nlobular\nlobulate\nlobulated\nlobulation\nlobulations\nlobule\nlobules\nlobulose\nlobworm\nlobworms\nloca\nlocal\nlocale\nlocales\nlocalise\nlocalised\nlocalises\nlocalising\nlocalism\nlocalisms\nlocalist\nlocalists\nlocalite\nlocalites\nlocalities\nlocality\nlocalizabilities\nlocalizability\nlocalizable\nlocalization\nlocalizations\nlocalize\nlocalized\nlocalizes\nlocalizing\nlocally\nlocals\nlocatable\nlocate\nlocated\nlocater\nlocaters\nlocates\nlocating\nlocation\nlocational\nlocationally\nlocations\nlocative\nlocatives\nlocator\nlocators\nloch\nlochan\nlochans\nlochia\nlochial\nlochs\nloci\nlock\nlockable\nlockage\nlockages\nlockbox\nlockboxes\nlockdown\nlockdowns\nlocked\nlocker\nlockers\nlocket\nlockets\nlocking\nlockjaw\nlockjaws\nlockkeeper\nlockkeepers\nlocknut\nlocknuts\nlockout\nlockouts\nlockram\nlockrams\nlocks\nlocksmith\nlocksmithing\nlocksmithings\nlocksmiths\nlockstep\nlocksteps\nlockstitch\nlockstitched\nlockstitches\nlockstitching\nlockup\nlockups\nloco\nlocoed\nlocoes\nlocofoco\nlocofocos\nlocoing\nlocoism\nlocoisms\nlocomote\nlocomoted\nlocomotes\nlocomoting\nlocomotion\nlocomotions\nlocomotive\nlocomotives\nlocomotor\nlocomotory\nlocos\nlocoweed\nlocoweeds\nlocular\nloculate\nlocule\nloculed\nlocules\nloculi\nloculicidal\nloculus\nlocum\nlocums\nlocus\nlocust\nlocusta\nlocustae\nlocustal\nlocusts\nlocution\nlocutions\nlocutories\nlocutory\nlode\nloden\nlodens\nlodes\nlodestar\nlodestars\nlodestone\nlodestones\nlodge\nlodged\nlodgement\nlodgements\nlodger\nlodgers\nlodges\nlodging\nlodgings\nlodgment\nlodgments\nlodicule\nlodicules\nloess\nloessal\nloesses\nloessial\nloft\nlofted\nlofter\nlofters\nloftier\nloftiest\nloftily\nloftiness\nloftinesses\nlofting\nloftless\nloftlike\nlofts\nlofty\nlog\nlogan\nloganberries\nloganberry\nlogania\nlogans\nlogaoedic\nlogaoedics\nlogarithm\nlogarithmic\nlogarithmically\nlogarithms\nlogbook\nlogbooks\nloge\nloges\nloggats\nlogged\nlogger\nloggerhead\nloggerheads\nloggers\nloggets\nloggia\nloggias\nloggie\nloggier\nloggiest\nlogging\nloggings\nloggy\nlogia\nlogic\nlogical\nlogicalities\nlogicality\nlogically\nlogicalness\nlogicalnesses\nlogician\nlogicians\nlogicise\nlogicised\nlogicises\nlogicising\nlogicize\nlogicized\nlogicizes\nlogicizing\nlogics\nlogier\nlogiest\nlogily\nloginess\nloginesses\nlogion\nlogions\nlogistic\nlogistical\nlogistically\nlogistician\nlogisticians\nlogistics\nlogjam\nlogjams\nlognormal\nlognormalities\nlognormality\nlognormally\nlogo\nlogogram\nlogogrammatic\nlogograms\nlogograph\nlogographic\nlogographically\nlogographs\nlogogriph\nlogogriphs\nlogoi\nlogomach\nlogomachies\nlogomachs\nlogomachy\nlogorrhea\nlogorrheas\nlogorrheic\nlogos\nlogotype\nlogotypes\nlogotypies\nlogotypy\nlogroll\nlogrolled\nlogroller\nlogrollers\nlogrolling\nlogrollings\nlogrolls\nlogs\nlogway\nlogways\nlogwood\nlogwoods\nlogy\nloin\nloincloth\nloincloths\nloins\nloiter\nloitered\nloiterer\nloiterers\nloitering\nloiters\nloll\nlollapalooza\nlollapaloozas\nlolled\nloller\nlollers\nlollies\nlolling\nlollipop\nlollipops\nlollop\nlolloped\nlolloping\nlollops\nlolls\nlolly\nlollygag\nlollygagged\nlollygagging\nlollygags\nlollypop\nlollypops\nlomein\nlomeins\nloment\nlomenta\nloments\nlomentum\nlomentums\nlone\nlonelier\nloneliest\nlonelily\nloneliness\nlonelinesses\nlonely\nloneness\nlonenesses\nloner\nloners\nlonesome\nlonesomely\nlonesomeness\nlonesomenesses\nlonesomes\nlong\nlongan\nlonganimities\nlonganimity\nlongans\nlongboat\nlongboats\nlongbow\nlongbowman\nlongbowmen\nlongbows\nlonge\nlonged\nlongeing\nlonger\nlongeron\nlongerons\nlongers\nlonges\nlongest\nlongevities\nlongevity\nlongevous\nlonghair\nlonghaired\nlonghairs\nlonghand\nlonghands\nlonghead\nlongheaded\nlongheadedness\nlongheadednesses\nlongheads\nlonghorn\nlonghorns\nlonghouse\nlonghouses\nlongicorn\nlongicorns\nlongies\nlonging\nlongingly\nlongings\nlongish\nlongitude\nlongitudes\nlongitudinal\nlongitudinally\nlongleaf\nlongleaves\nlongline\nlonglines\nlongly\nlongness\nlongnesses\nlongs\nlongship\nlongships\nlongshoreman\nlongshoremen\nlongshoring\nlongshorings\nlongsighted\nlongsightedness\nlongsightednesses\nlongsome\nlongsomely\nlongsomeness\nlongsomenesses\nlongspur\nlongspurs\nlongstanding\nlongtime\nlongueur\nlongueurs\nlongways\nlongwise\nloo\nloobies\nlooby\nlooed\nlooey\nlooeys\nloof\nloofa\nloofah\nloofahs\nloofas\nloofs\nlooie\nlooies\nlooing\nlook\nlookalike\nlookalikes\nlookdown\nlookdowns\nlooked\nlooker\nlookers\nlooking\nlookout\nlookouts\nlooks\nlookup\nlookups\nloom\nloomed\nlooming\nlooms\nloon\nlooney\nlooneys\nloonier\nloonies\nlooniest\nlooniness\nlooninesses\nloons\nloony\nloop\nlooped\nlooper\nloopers\nloophole\nloopholed\nloopholes\nloopholing\nloopier\nloopiest\nlooping\nloops\nloopy\nloos\nloose\nloosed\nloosely\nloosen\nloosened\nloosener\nlooseners\nlooseness\nloosenesses\nloosening\nloosens\nlooser\nlooses\nloosest\nloosestrife\nloosestrifes\nloosing\nloot\nlooted\nlooter\nlooters\nlooting\nloots\nlop\nlope\nloped\nloper\nlopers\nlopes\nlophophore\nlophophores\nloping\nlopped\nlopper\nloppered\nloppering\nloppers\nloppier\nloppiest\nlopping\nloppy\nlops\nlopsided\nlopsidedly\nlopsidedness\nlopsidednesses\nlopstick\nlopsticks\nloquacious\nloquaciously\nloquaciousness\nloquaciousnesses\nloquacities\nloquacity\nloquat\nloquats\nloral\nloran\nlorans\nlord\nlorded\nlording\nlordings\nlordless\nlordlier\nlordliest\nlordlike\nlordliness\nlordlinesses\nlordling\nlordlings\nlordly\nlordoma\nlordomas\nlordoses\nlordosis\nlordotic\nlords\nlordship\nlordships\nlore\nloreal\nlores\nlorgnette\nlorgnettes\nlorgnon\nlorgnons\nlorica\nloricae\nloricate\nloricates\nlories\nlorikeet\nlorikeets\nlorimer\nlorimers\nloriner\nloriners\nloris\nlorises\nlorn\nlornness\nlornnesses\nlorries\nlorry\nlory\nlosable\nlosableness\nlosablenesses\nlose\nlosel\nlosels\nloser\nlosers\nloses\nlosing\nlosingly\nlosings\nloss\nlosses\nlossy\nlost\nlostness\nlostnesses\nlot\nlota\nlotah\nlotahs\nlotas\nloth\nlothario\nlotharios\nlothsome\nloti\nlotic\nlotion\nlotions\nlotos\nlotoses\nlots\nlotte\nlotted\nlotteries\nlottery\nlottes\nlotting\nlotto\nlottos\nlotus\nlotuses\nlotusland\nlotuslands\nlouche\nloud\nlouden\nloudened\nloudening\nloudens\nlouder\nloudest\nloudish\nloudlier\nloudliest\nloudly\nloudmouth\nloudmouthed\nloudmouths\nloudness\nloudnesses\nloudspeaker\nloudspeakers\nlough\nloughs\nlouie\nlouies\nlouis\nlounge\nlounged\nlounger\nloungers\nlounges\nloungewear\nlounging\nloungy\nloup\nloupe\nlouped\nloupen\nloupes\nlouping\nloups\nlour\nloured\nlouring\nlours\nloury\nlouse\nloused\nlouses\nlousewort\nlouseworts\nlousier\nlousiest\nlousily\nlousiness\nlousinesses\nlousing\nlousy\nlout\nlouted\nlouting\nloutish\nloutishly\nloutishness\nloutishnesses\nlouts\nlouver\nlouvered\nlouvers\nlouvre\nlouvred\nlouvres\nlovabilities\nlovability\nlovable\nlovableness\nlovablenesses\nlovably\nlovage\nlovages\nlovastatin\nlovastatins\nlovat\nlovats\nlove\nloveable\nloveably\nlovebird\nlovebirds\nlovebug\nlovebugs\nloved\nloveless\nlovelessly\nlovelessness\nlovelessnesses\nlovelier\nlovelies\nloveliest\nlovelily\nloveliness\nlovelinesses\nlovelock\nlovelocks\nlovelorn\nlovelornness\nlovelornnesses\nlovely\nlovemaking\nlovemakings\nlover\nloverly\nlovers\nloves\nloveseat\nloveseats\nlovesick\nlovesickness\nlovesicknesses\nlovesome\nlovevine\nlovevines\nloving\nlovingly\nlovingness\nlovingnesses\nlow\nlowball\nlowballed\nlowballing\nlowballs\nlowborn\nlowboy\nlowboys\nlowbred\nlowbrow\nlowbrows\nlowdown\nlowdowns\nlowe\nlowed\nlower\nlowercase\nlowercased\nlowercases\nlowercasing\nlowerclassman\nlowerclassmen\nlowered\nlowering\nlowermost\nlowers\nlowery\nlowes\nlowest\nlowing\nlowings\nlowish\nlowland\nlowlander\nlowlanders\nlowlands\nlowlier\nlowliest\nlowlife\nlowlifer\nlowlifers\nlowlifes\nlowlight\nlowlights\nlowlihead\nlowliheads\nlowliness\nlowlinesses\nlowlives\nlowly\nlown\nlowness\nlownesses\nlowrider\nlowriders\nlows\nlowse\nlox\nloxed\nloxes\nloxing\nloxodrome\nloxodromes\nloyal\nloyaler\nloyalest\nloyalism\nloyalisms\nloyalist\nloyalists\nloyally\nloyalties\nloyalty\nlozenge\nlozenges\nluau\nluaus\nlubber\nlubberliness\nlubberlinesses\nlubberly\nlubbers\nlube\nlubed\nlubes\nlubing\nlubric\nlubrical\nlubricant\nlubricants\nlubricate\nlubricated\nlubricates\nlubricating\nlubrication\nlubrications\nlubricative\nlubricator\nlubricators\nlubricious\nlubriciously\nlubricities\nlubricity\nlubricous\nlucarne\nlucarnes\nluce\nlucence\nlucences\nlucencies\nlucency\nlucent\nlucently\nlucern\nlucerne\nlucernes\nlucerns\nluces\nlucid\nlucidities\nlucidity\nlucidly\nlucidness\nlucidnesses\nlucifer\nluciferase\nluciferases\nluciferin\nluciferins\nluciferous\nlucifers\nluck\nlucked\nluckie\nluckier\nluckies\nluckiest\nluckily\nluckiness\nluckinesses\nlucking\nluckless\nlucks\nlucky\nlucrative\nlucratively\nlucrativeness\nlucrativenesses\nlucre\nlucres\nlucubration\nlucubrations\nluculent\nluculently\nlude\nludes\nludic\nludicrous\nludicrously\nludicrousness\nludicrousnesses\nlues\nluetic\nluetics\nluff\nluffa\nluffas\nluffed\nluffing\nluffs\nluftmensch\nluftmenschen\nlug\nluge\nluged\nlugeing\nluger\nlugers\nluges\nluggage\nluggages\nlugged\nlugger\nluggers\nluggie\nluggies\nlugging\nluging\nlugs\nlugsail\nlugsails\nlugubrious\nlugubriously\nlugubriousness\nlugubriousnesses\nlugworm\nlugworms\nlukewarm\nlukewarmly\nlukewarmness\nlukewarmnesses\nlull\nlullabied\nlullabies\nlullaby\nlullabying\nlulled\nlulling\nlulls\nlulu\nlulus\nlum\nlumbago\nlumbagos\nlumbar\nlumbars\nlumber\nlumbered\nlumberer\nlumberers\nlumbering\nlumberjack\nlumberjacks\nlumberman\nlumbermen\nlumbers\nlumberyard\nlumberyards\nlumbosacral\nlumen\nlumenal\nlumens\nlumina\nluminaire\nluminaires\nluminal\nluminance\nluminances\nluminaria\nluminarias\nluminaries\nluminary\nluminesce\nluminesced\nluminescence\nluminescences\nluminescent\nluminesces\nluminescing\nluminiferous\nluminism\nluminisms\nluminist\nluminists\nluminosities\nluminosity\nluminous\nluminously\nluminousness\nluminousnesses\nlummox\nlummoxes\nlump\nlumpectomies\nlumpectomy\nlumped\nlumpen\nlumpenproletariat\nlumpenproletariats\nlumpens\nlumper\nlumpers\nlumpfish\nlumpfishes\nlumpier\nlumpiest\nlumpily\nlumpiness\nlumpinesses\nlumping\nlumpish\nlumpishly\nlumpishness\nlumpishnesses\nlumps\nlumpy\nlums\nluna\nlunacies\nlunacy\nlunar\nlunarian\nlunarians\nlunars\nlunas\nlunate\nlunated\nlunately\nlunatic\nlunatics\nlunation\nlunations\nlunch\nlunched\nluncheon\nluncheonette\nluncheonettes\nluncheons\nluncher\nlunchers\nlunches\nlunching\nlunchmeat\nlunchmeats\nlunchroom\nlunchrooms\nlunchtime\nlunchtimes\nlune\nlunes\nlunet\nlunets\nlunette\nlunettes\nlung\nlungan\nlungans\nlunge\nlunged\nlungee\nlungees\nlunger\nlungers\nlunges\nlungfish\nlungfishes\nlungful\nlungfuls\nlungi\nlunging\nlungis\nlungs\nlungworm\nlungworms\nlungwort\nlungworts\nlungyi\nlungyis\nlunier\nlunies\nluniest\nlunisolar\nlunk\nlunker\nlunkers\nlunkhead\nlunkheaded\nlunkheads\nlunks\nlunt\nlunted\nlunting\nlunts\nlunula\nlunulae\nlunular\nlunulate\nlunule\nlunules\nluny\nlupanar\nlupanars\nlupin\nlupine\nlupines\nlupins\nlupous\nlupulin\nlupulins\nlupus\nlupuses\nlurch\nlurched\nlurcher\nlurchers\nlurches\nlurching\nlurdan\nlurdane\nlurdanes\nlurdans\nlure\nlured\nlurer\nlurers\nlures\nlurid\nluridly\nluridness\nluridnesses\nluring\nlurk\nlurked\nlurker\nlurkers\nlurking\nlurks\nluscious\nlusciously\nlusciousness\nlusciousnesses\nlush\nlushed\nlusher\nlushes\nlushest\nlushing\nlushly\nlushness\nlushnesses\nlust\nlusted\nluster\nlustered\nlustering\nlusterless\nlusters\nlusterware\nlusterwares\nlustful\nlustfully\nlustfulness\nlustfulnesses\nlustier\nlustiest\nlustihood\nlustihoods\nlustily\nlustiness\nlustinesses\nlusting\nlustra\nlustral\nlustrate\nlustrated\nlustrates\nlustrating\nlustration\nlustrations\nlustre\nlustred\nlustres\nlustring\nlustrings\nlustrous\nlustrously\nlustrousness\nlustrousnesses\nlustrum\nlustrums\nlusts\nlusty\nlusus\nlususes\nlutanist\nlutanists\nlute\nlutea\nluteal\nlutecium\nluteciums\nluted\nlutefisk\nlutefisks\nlutein\nluteinization\nluteinizations\nluteinize\nluteinized\nluteinizes\nluteinizing\nluteins\nlutenist\nlutenists\nluteolin\nluteolins\nluteotrophic\nluteotrophin\nluteotrophins\nluteotropic\nluteotropin\nluteotropins\nluteous\nlutes\nlutestring\nlutestrings\nlutetium\nlutetiums\nluteum\nluthern\nlutherns\nluthier\nluthiers\nluting\nlutings\nlutist\nlutists\nlutz\nlutzes\nluv\nluvs\nlux\nluxate\nluxated\nluxates\nluxating\nluxation\nluxations\nluxe\nluxes\nluxuriance\nluxuriances\nluxuriant\nluxuriantly\nluxuriate\nluxuriated\nluxuriates\nluxuriating\nluxuries\nluxurious\nluxuriously\nluxuriousness\nluxuriousnesses\nluxury\nlwei\nlweis\nlyard\nlyart\nlyase\nlyases\nlycanthrope\nlycanthropes\nlycanthropic\nlycanthropies\nlycanthropy\nlycea\nlycee\nlycees\nlyceum\nlyceums\nlychee\nlychees\nlychnis\nlychnises\nlycopene\nlycopenes\nlycopod\nlycopodium\nlycopodiums\nlycopods\nlyddite\nlyddites\nlye\nlyes\nlying\nlyingly\nlyings\nlymph\nlymphadenitis\nlymphadenitises\nlymphadenopathies\nlymphadenopathy\nlymphangiogram\nlymphangiograms\nlymphangiographic\nlymphangiographies\nlymphangiography\nlymphatic\nlymphatically\nlymphatics\nlymphoblast\nlymphoblastic\nlymphoblasts\nlymphocyte\nlymphocytes\nlymphocytic\nlymphocytoses\nlymphocytosis\nlymphogram\nlymphograms\nlymphogranuloma\nlymphogranulomas\nlymphogranulomata\nlymphogranulomatoses\nlymphogranulomatosis\nlymphographic\nlymphographies\nlymphography\nlymphoid\nlymphokine\nlymphokines\nlymphoma\nlymphomas\nlymphomata\nlymphomatoses\nlymphomatosis\nlymphomatous\nlymphosarcoma\nlymphosarcomas\nlymphosarcomata\nlymphs\nlyncean\nlynch\nlynched\nlyncher\nlynchers\nlynches\nlynching\nlynchings\nlynchpin\nlynchpins\nlynx\nlynxes\nlyonnaise\nlyophile\nlyophiled\nlyophilic\nlyophilise\nlyophilised\nlyophilises\nlyophilising\nlyophilization\nlyophilizations\nlyophilize\nlyophilized\nlyophilizer\nlyophilizers\nlyophilizes\nlyophilizing\nlyophobic\nlyrate\nlyrated\nlyrately\nlyre\nlyrebird\nlyrebirds\nlyres\nlyric\nlyrical\nlyrically\nlyricalness\nlyricalnesses\nlyricise\nlyricised\nlyricises\nlyricising\nlyricism\nlyricisms\nlyricist\nlyricists\nlyricize\nlyricized\nlyricizes\nlyricizing\nlyrics\nlyriform\nlyrism\nlyrisms\nlyrist\nlyrists\nlysate\nlysates\nlyse\nlysed\nlyses\nlysimeter\nlysimeters\nlysimetric\nlysin\nlysine\nlysines\nlysing\nlysins\nlysis\nlysogen\nlysogenic\nlysogenicities\nlysogenicity\nlysogenies\nlysogenise\nlysogenised\nlysogenises\nlysogenising\nlysogenization\nlysogenizations\nlysogenize\nlysogenized\nlysogenizes\nlysogenizing\nlysogens\nlysogeny\nlysolecithin\nlysolecithins\nlysosomal\nlysosome\nlysosomes\nlysozyme\nlysozymes\nlyssa\nlyssas\nlytic\nlytically\nlytta\nlyttae\nlyttas\nma\nmaar\nmaars\nmabe\nmabes\nmac\nmacaber\nmacabre\nmacaco\nmacacos\nmacadam\nmacadamia\nmacadamias\nmacadamize\nmacadamized\nmacadamizes\nmacadamizing\nmacadams\nmacaque\nmacaques\nmacaroni\nmacaronic\nmacaronics\nmacaronies\nmacaronis\nmacaroon\nmacaroons\nmacaw\nmacaws\nmaccabaw\nmaccabaws\nmaccaboy\nmaccaboys\nmacchia\nmacchie\nmaccoboy\nmaccoboys\nmace\nmaced\nmacedoine\nmacedoines\nmacer\nmacerate\nmacerated\nmacerates\nmacerating\nmaceration\nmacerations\nmacerator\nmacerators\nmacers\nmaces\nmach\nmache\nmaches\nmachete\nmachetes\nmachicolated\nmachicolation\nmachicolations\nmachinabilities\nmachinability\nmachinable\nmachinate\nmachinated\nmachinates\nmachinating\nmachination\nmachinations\nmachinator\nmachinators\nmachine\nmachineabilities\nmachineability\nmachineable\nmachined\nmachinelike\nmachineries\nmachinery\nmachines\nmachining\nmachinist\nmachinists\nmachismo\nmachismos\nmacho\nmachos\nmachree\nmachrees\nmachs\nmachzor\nmachzorim\nmachzors\nmacing\nmacintosh\nmacintoshes\nmack\nmackerel\nmackerels\nmackinaw\nmackinaws\nmackintosh\nmackintoshes\nmackle\nmackled\nmackles\nmackling\nmacks\nmacle\nmacled\nmacles\nmacon\nmacons\nmacrame\nmacrames\nmacro\nmacroaggregate\nmacroaggregated\nmacroaggregates\nmacrobiotic\nmacrocosm\nmacrocosmic\nmacrocosmically\nmacrocosms\nmacrocyclic\nmacrocyte\nmacrocytes\nmacrocytic\nmacrocytoses\nmacrocytosis\nmacroeconomic\nmacroeconomics\nmacroevolution\nmacroevolutionary\nmacroevolutions\nmacrofossil\nmacrofossils\nmacrogamete\nmacrogametes\nmacroglobulin\nmacroglobulinemia\nmacroglobulinemias\nmacroglobulinemic\nmacroglobulins\nmacroinstruction\nmacroinstructions\nmacrolepidoptera\nmacromere\nmacromeres\nmacromolecular\nmacromolecule\nmacromolecules\nmacron\nmacrons\nmacronuclear\nmacronuclei\nmacronucleus\nmacronucleuses\nmacronutrient\nmacronutrients\nmacrophage\nmacrophages\nmacrophagic\nmacrophotograph\nmacrophotographies\nmacrophotographs\nmacrophotography\nmacrophyte\nmacrophytes\nmacrophytic\nmacropterous\nmacros\nmacroscale\nmacroscales\nmacroscopic\nmacroscopically\nmacrostructural\nmacrostructure\nmacrostructures\nmacrural\nmacruran\nmacrurans\nmacs\nmacula\nmaculae\nmacular\nmaculas\nmaculate\nmaculated\nmaculates\nmaculating\nmaculation\nmaculations\nmacule\nmaculed\nmacules\nmaculing\nmacumba\nmacumbas\nmad\nmadam\nmadame\nmadames\nmadams\nmadcap\nmadcaps\nmadded\nmadden\nmaddened\nmaddening\nmaddeningly\nmaddens\nmadder\nmadders\nmaddest\nmadding\nmaddish\nmade\nmadeira\nmadeiras\nmadeleine\nmadeleines\nmademoiselle\nmademoiselles\nmadhouse\nmadhouses\nmadly\nmadman\nmadmen\nmadness\nmadnesses\nmadonna\nmadonnas\nmadras\nmadrases\nmadre\nmadrepore\nmadrepores\nmadreporian\nmadreporians\nmadreporic\nmadreporite\nmadreporites\nmadres\nmadrigal\nmadrigalian\nmadrigalist\nmadrigalists\nmadrigals\nmadrilene\nmadrilenes\nmadrona\nmadronas\nmadrone\nmadrones\nmadrono\nmadronos\nmads\nmaduro\nmaduros\nmadwoman\nmadwomen\nmadwort\nmadworts\nmadzoon\nmadzoons\nmae\nmaelstrom\nmaelstroms\nmaenad\nmaenades\nmaenadic\nmaenads\nmaes\nmaestoso\nmaestosos\nmaestri\nmaestro\nmaestros\nmaffia\nmaffias\nmaffick\nmafficked\nmafficking\nmafficks\nmafia\nmafias\nmafic\nmafiosi\nmafioso\nmafiosos\nmaftir\nmaftirs\nmag\nmagazine\nmagazines\nmagazinist\nmagazinists\nmagdalen\nmagdalene\nmagdalenes\nmagdalens\nmage\nmagenta\nmagentas\nmages\nmaggot\nmaggots\nmaggoty\nmagi\nmagian\nmagians\nmagic\nmagical\nmagically\nmagician\nmagicians\nmagicked\nmagicking\nmagics\nmagilp\nmagilps\nmagister\nmagisterial\nmagisterially\nmagisterium\nmagisteriums\nmagisters\nmagistracies\nmagistracy\nmagistral\nmagistrally\nmagistrate\nmagistrates\nmagistratical\nmagistratically\nmagistrature\nmagistratures\nmaglev\nmaglevs\nmagma\nmagmas\nmagmata\nmagmatic\nmagnanimities\nmagnanimity\nmagnanimous\nmagnanimously\nmagnanimousness\nmagnanimousnesses\nmagnate\nmagnates\nmagnesia\nmagnesian\nmagnesias\nmagnesic\nmagnesite\nmagnesites\nmagnesium\nmagnesiums\nmagnet\nmagnetic\nmagnetically\nmagnetics\nmagnetise\nmagnetised\nmagnetises\nmagnetising\nmagnetism\nmagnetisms\nmagnetite\nmagnetites\nmagnetizable\nmagnetization\nmagnetizations\nmagnetize\nmagnetized\nmagnetizer\nmagnetizers\nmagnetizes\nmagnetizing\nmagneto\nmagnetoelectric\nmagnetofluiddynamics\nmagnetograph\nmagnetographs\nmagnetohydrodynamic\nmagnetohydrodynamics\nmagnetometer\nmagnetometers\nmagnetometric\nmagnetometries\nmagnetometry\nmagneton\nmagnetons\nmagnetopause\nmagnetopauses\nmagnetoresistance\nmagnetoresistances\nmagnetos\nmagnetosphere\nmagnetospheres\nmagnetospheric\nmagnetostatic\nmagnetostriction\nmagnetostrictions\nmagnetostrictive\nmagnetostrictively\nmagnetron\nmagnetrons\nmagnets\nmagnific\nmagnifical\nmagnifically\nmagnificat\nmagnification\nmagnifications\nmagnificats\nmagnificence\nmagnificences\nmagnificent\nmagnificently\nmagnifico\nmagnificoes\nmagnificos\nmagnified\nmagnifier\nmagnifiers\nmagnifies\nmagnify\nmagnifying\nmagniloquence\nmagniloquences\nmagniloquent\nmagniloquently\nmagnitude\nmagnitudes\nmagnolia\nmagnolias\nmagnum\nmagnums\nmagot\nmagots\nmagpie\nmagpies\nmags\nmaguey\nmagueys\nmagus\nmaharaja\nmaharajah\nmaharajahs\nmaharajas\nmaharanee\nmaharanees\nmaharani\nmaharanis\nmaharishi\nmaharishis\nmahatma\nmahatmas\nmahimahi\nmahimahis\nmahjong\nmahjongg\nmahjonggs\nmahjongs\nmahlstick\nmahlsticks\nmahoe\nmahoes\nmahoganies\nmahogany\nmahonia\nmahonias\nmahout\nmahouts\nmahuang\nmahuangs\nmahzor\nmahzorim\nmahzors\nmaid\nmaiden\nmaidenhair\nmaidenhairs\nmaidenhead\nmaidenheads\nmaidenhood\nmaidenhoods\nmaidenliness\nmaidenlinesses\nmaidenly\nmaidens\nmaidhood\nmaidhoods\nmaidish\nmaids\nmaidservant\nmaidservants\nmaieutic\nmaigre\nmaihem\nmaihems\nmail\nmailabilities\nmailability\nmailable\nmailbag\nmailbags\nmailbomb\nmailbombed\nmailbombing\nmailbombs\nmailbox\nmailboxes\nmaile\nmailed\nmailer\nmailers\nmailes\nmailing\nmailings\nmaill\nmailless\nmaillot\nmaillots\nmaills\nmailman\nmailmen\nmails\nmaim\nmaimed\nmaimer\nmaimers\nmaiming\nmaims\nmain\nmainframe\nmainframes\nmainland\nmainlander\nmainlanders\nmainlands\nmainline\nmainlined\nmainlines\nmainlining\nmainly\nmainmast\nmainmasts\nmains\nmainsail\nmainsails\nmainsheet\nmainsheets\nmainspring\nmainsprings\nmainstay\nmainstays\nmainstream\nmainstreamed\nmainstreaming\nmainstreams\nmaintain\nmaintainabilities\nmaintainability\nmaintainable\nmaintained\nmaintainer\nmaintainers\nmaintaining\nmaintains\nmaintenance\nmaintenances\nmaintop\nmaintops\nmaiolica\nmaiolicas\nmair\nmairs\nmaisonette\nmaisonettes\nmaist\nmaists\nmaize\nmaizes\nmajagua\nmajaguas\nmajestic\nmajestically\nmajesties\nmajesty\nmajolica\nmajolicas\nmajor\nmajordomo\nmajordomos\nmajored\nmajorette\nmajorettes\nmajoring\nmajoritarian\nmajoritarianism\nmajoritarianisms\nmajoritarians\nmajorities\nmajority\nmajorly\nmajors\nmajuscular\nmajuscule\nmajuscules\nmakable\nmakar\nmakars\nmake\nmakeable\nmakebate\nmakebates\nmakefast\nmakefasts\nmakeover\nmakeovers\nmaker\nmakereadies\nmakeready\nmakers\nmakes\nmakeshift\nmakeshifts\nmakeup\nmakeups\nmakeweight\nmakeweights\nmakimono\nmakimonos\nmaking\nmakings\nmako\nmakos\nmakuta\nmalabsorption\nmalabsorptions\nmalacca\nmalaccas\nmalachite\nmalachites\nmalacological\nmalacologies\nmalacologist\nmalacologists\nmalacology\nmalacostracan\nmalacostracans\nmaladaptation\nmaladaptations\nmaladapted\nmaladaptive\nmaladies\nmaladjusted\nmaladjustive\nmaladjustment\nmaladjustments\nmaladminister\nmaladministered\nmaladministering\nmaladministers\nmaladministration\nmaladministrations\nmaladroit\nmaladroitly\nmaladroitness\nmaladroitnesses\nmalady\nmalaguena\nmalaguenas\nmalaise\nmalaises\nmalamute\nmalamutes\nmalanga\nmalangas\nmalapert\nmalapertly\nmalapertness\nmalapertnesses\nmalaperts\nmalapportioned\nmalapportionment\nmalapportionments\nmalaprop\nmalapropian\nmalapropism\nmalapropisms\nmalapropist\nmalapropists\nmalapropos\nmalaprops\nmalar\nmalaria\nmalarial\nmalarian\nmalarias\nmalariologies\nmalariologist\nmalariologists\nmalariology\nmalarious\nmalarkey\nmalarkeys\nmalarkies\nmalarky\nmalaroma\nmalaromas\nmalars\nmalate\nmalates\nmalathion\nmalathions\nmalcontent\nmalcontented\nmalcontentedly\nmalcontentedness\nmalcontentednesses\nmalcontents\nmaldistribution\nmaldistributions\nmale\nmaleate\nmaleates\nmaledict\nmaledicted\nmaledicting\nmalediction\nmaledictions\nmaledictory\nmaledicts\nmalefaction\nmalefactions\nmalefactor\nmalefactors\nmalefic\nmaleficence\nmaleficences\nmaleficent\nmalemiut\nmalemiuts\nmalemute\nmalemutes\nmaleness\nmalenesses\nmales\nmalevolence\nmalevolences\nmalevolent\nmalevolently\nmalfeasance\nmalfeasances\nmalfed\nmalformation\nmalformations\nmalformed\nmalfunction\nmalfunctioned\nmalfunctioning\nmalfunctions\nmalgre\nmalic\nmalice\nmalices\nmalicious\nmaliciously\nmaliciousness\nmaliciousnesses\nmalign\nmalignance\nmalignances\nmalignancies\nmalignancy\nmalignant\nmalignantly\nmaligned\nmaligner\nmaligners\nmaligning\nmalignities\nmalignity\nmalignly\nmaligns\nmalihini\nmalihinis\nmaline\nmalines\nmalinger\nmalingered\nmalingerer\nmalingerers\nmalingering\nmalingers\nmalison\nmalisons\nmalkin\nmalkins\nmall\nmallard\nmallards\nmalleabilities\nmalleability\nmalleable\nmalled\nmallee\nmallees\nmallei\nmalleoli\nmalleolus\nmallet\nmallets\nmalleus\nmalling\nmallow\nmallows\nmalls\nmalm\nmalmier\nmalmiest\nmalms\nmalmsey\nmalmseys\nmalmy\nmalnourished\nmalnutrition\nmalnutritions\nmalocclusion\nmalocclusions\nmalodor\nmalodorous\nmalodorously\nmalodorousness\nmalodorousnesses\nmalodors\nmalolactic\nmaloti\nmalposed\nmalposition\nmalpositions\nmalpractice\nmalpractices\nmalpractitioner\nmalpractitioners\nmalt\nmaltase\nmaltases\nmalted\nmalteds\nmaltha\nmalthas\nmaltier\nmaltiest\nmalting\nmaltol\nmaltols\nmaltose\nmaltoses\nmaltreat\nmaltreated\nmaltreater\nmaltreaters\nmaltreating\nmaltreatment\nmaltreatments\nmaltreats\nmalts\nmaltster\nmaltsters\nmalty\nmalvasia\nmalvasias\nmalversation\nmalversations\nmama\nmamaliga\nmamaligas\nmamas\nmamba\nmambas\nmambo\nmamboed\nmamboes\nmamboing\nmambos\nmameluke\nmamelukes\nmamey\nmameyes\nmameys\nmamie\nmamies\nmamluk\nmamluks\nmamma\nmammae\nmammal\nmammalian\nmammalians\nmammalogies\nmammalogist\nmammalogists\nmammalogy\nmammals\nmammary\nmammas\nmammate\nmammati\nmammatus\nmammee\nmammees\nmammer\nmammered\nmammering\nmammers\nmammet\nmammets\nmammey\nmammeys\nmammie\nmammies\nmammilla\nmammillae\nmammillary\nmammillated\nmammitides\nmammitis\nmammock\nmammocked\nmammocking\nmammocks\nmammogram\nmammograms\nmammographic\nmammographies\nmammography\nmammon\nmammonism\nmammonisms\nmammonist\nmammonists\nmammons\nmammoth\nmammoths\nmammy\nman\nmana\nmanacle\nmanacled\nmanacles\nmanacling\nmanage\nmanageabilities\nmanageability\nmanageable\nmanageableness\nmanageablenesses\nmanageably\nmanaged\nmanagement\nmanagemental\nmanagements\nmanager\nmanageress\nmanageresses\nmanagerial\nmanagerially\nmanagers\nmanagership\nmanagerships\nmanages\nmanaging\nmanakin\nmanakins\nmanana\nmananas\nmanas\nmanat\nmanatee\nmanatees\nmanatoid\nmanats\nmanche\nmanches\nmanchet\nmanchets\nmanchineel\nmanchineels\nmanciple\nmanciples\nmandala\nmandalas\nmandalic\nmandamus\nmandamused\nmandamuses\nmandamusing\nmandarin\nmandarinate\nmandarinates\nmandarinic\nmandarinism\nmandarinisms\nmandarins\nmandataries\nmandatary\nmandate\nmandated\nmandates\nmandating\nmandator\nmandatories\nmandatorily\nmandators\nmandatory\nmandible\nmandibles\nmandibular\nmandibulate\nmandioca\nmandiocas\nmandola\nmandolas\nmandolin\nmandoline\nmandolines\nmandolinist\nmandolinists\nmandolins\nmandragora\nmandragoras\nmandrake\nmandrakes\nmandrel\nmandrels\nmandril\nmandrill\nmandrills\nmandrils\nmane\nmaned\nmanege\nmaneges\nmaneless\nmanes\nmaneuver\nmaneuverabilities\nmaneuverability\nmaneuverable\nmaneuvered\nmaneuverer\nmaneuverers\nmaneuvering\nmaneuvers\nmanful\nmanfully\nmanfulness\nmanfulnesses\nmangabey\nmangabeys\nmangabies\nmangaby\nmanganate\nmanganates\nmanganese\nmanganeses\nmanganesian\nmanganic\nmanganite\nmanganites\nmanganous\nmange\nmangel\nmangels\nmanger\nmangers\nmanges\nmangey\nmangier\nmangiest\nmangily\nmanginess\nmanginesses\nmangle\nmangled\nmangler\nmanglers\nmangles\nmangling\nmango\nmangoes\nmangold\nmangolds\nmangonel\nmangonels\nmangos\nmangosteen\nmangosteens\nmangrove\nmangroves\nmangy\nmanhandle\nmanhandled\nmanhandles\nmanhandling\nmanhattan\nmanhattans\nmanhole\nmanholes\nmanhood\nmanhoods\nmanhunt\nmanhunts\nmania\nmaniac\nmaniacal\nmaniacally\nmaniacs\nmanias\nmanic\nmanically\nmanicotti\nmanics\nmanicure\nmanicured\nmanicures\nmanicuring\nmanicurist\nmanicurists\nmanifest\nmanifestant\nmanifestants\nmanifestation\nmanifestations\nmanifested\nmanifester\nmanifesters\nmanifesting\nmanifestly\nmanifesto\nmanifestoed\nmanifestoes\nmanifestoing\nmanifestos\nmanifests\nmanifold\nmanifolded\nmanifolding\nmanifoldly\nmanifoldness\nmanifoldnesses\nmanifolds\nmanihot\nmanihots\nmanikin\nmanikins\nmanila\nmanilas\nmanilla\nmanillas\nmanille\nmanilles\nmanioc\nmanioca\nmaniocas\nmaniocs\nmaniple\nmaniples\nmanipulabilities\nmanipulability\nmanipulable\nmanipular\nmanipulatable\nmanipulate\nmanipulated\nmanipulates\nmanipulating\nmanipulation\nmanipulations\nmanipulative\nmanipulatively\nmanipulativeness\nmanipulativenesses\nmanipulator\nmanipulators\nmanipulatory\nmanito\nmanitos\nmanitou\nmanitous\nmanitu\nmanitus\nmankind\nmanless\nmanlier\nmanliest\nmanlike\nmanlily\nmanliness\nmanlinesses\nmanly\nmanmade\nmanna\nmannan\nmannans\nmannas\nmanned\nmannequin\nmannequins\nmanner\nmannered\nmannerism\nmannerisms\nmannerist\nmanneristic\nmannerists\nmannerless\nmannerliness\nmannerlinesses\nmannerly\nmanners\nmannikin\nmannikins\nmanning\nmannish\nmannishly\nmannishness\nmannishnesses\nmannite\nmannites\nmannitic\nmannitol\nmannitols\nmannose\nmannoses\nmano\nmanoeuvre\nmanoeuvred\nmanoeuvres\nmanoeuvring\nmanometer\nmanometers\nmanometric\nmanometrically\nmanometries\nmanometry\nmanor\nmanorial\nmanorialism\nmanorialisms\nmanors\nmanos\nmanpack\nmanpower\nmanpowers\nmanque\nmanrope\nmanropes\nmans\nmansard\nmansarded\nmansards\nmanse\nmanservant\nmanses\nmansion\nmansions\nmanslaughter\nmanslaughters\nmanslayer\nmanslayers\nmansuetude\nmansuetudes\nmanta\nmantas\nmanteau\nmanteaus\nmanteaux\nmantel\nmantelet\nmantelets\nmantelpiece\nmantelpieces\nmantels\nmantelshelf\nmantelshelves\nmantes\nmantic\nmanticore\nmanticores\nmantid\nmantids\nmantilla\nmantillas\nmantis\nmantises\nmantissa\nmantissas\nmantle\nmantled\nmantles\nmantlet\nmantlets\nmantling\nmantlings\nmantra\nmantrap\nmantraps\nmantras\nmantric\nmantua\nmantuas\nmanual\nmanually\nmanuals\nmanuary\nmanubria\nmanubrium\nmanubriums\nmanufactories\nmanufactory\nmanufacture\nmanufactured\nmanufacturer\nmanufacturers\nmanufactures\nmanufacturing\nmanufacturings\nmanumission\nmanumissions\nmanumit\nmanumits\nmanumitted\nmanumitting\nmanure\nmanured\nmanurer\nmanurers\nmanures\nmanurial\nmanuring\nmanus\nmanuscript\nmanuscripts\nmanward\nmanwards\nmanwise\nmany\nmanyfold\nmanzanita\nmanzanitas\nmap\nmaple\nmaples\nmaplike\nmapmaker\nmapmakers\nmapmaking\nmapmakings\nmappable\nmapped\nmapper\nmappers\nmapping\nmappings\nmaps\nmaquette\nmaquettes\nmaqui\nmaquiladora\nmaquiladoras\nmaquillage\nmaquillages\nmaquis\nmar\nmarabou\nmarabous\nmarabout\nmarabouts\nmaraca\nmaracas\nmaranta\nmarantas\nmarasca\nmarascas\nmaraschino\nmaraschinos\nmarasmic\nmarasmus\nmarasmuses\nmarathon\nmarathoner\nmarathoners\nmarathoning\nmarathonings\nmarathons\nmaraud\nmarauded\nmarauder\nmarauders\nmarauding\nmarauds\nmaravedi\nmaravedis\nmarble\nmarbled\nmarbleise\nmarbleised\nmarbleises\nmarbleising\nmarbleize\nmarbleized\nmarbleizes\nmarbleizing\nmarbler\nmarblers\nmarbles\nmarblier\nmarbliest\nmarbling\nmarblings\nmarbly\nmarc\nmarcasite\nmarcasites\nmarcato\nmarcel\nmarcelled\nmarcelling\nmarcels\nmarch\nmarched\nmarchen\nmarcher\nmarchers\nmarches\nmarchesa\nmarchese\nmarchesi\nmarching\nmarchioness\nmarchionesses\nmarchlike\nmarchpane\nmarchpanes\nmarcs\nmare\nmaremma\nmaremme\nmarengo\nmares\nmargaric\nmargarin\nmargarine\nmargarines\nmargarins\nmargarita\nmargaritas\nmargarite\nmargarites\nmargay\nmargays\nmarge\nmargent\nmargented\nmargenting\nmargents\nmarges\nmargin\nmarginal\nmarginalia\nmarginalities\nmarginality\nmarginalization\nmarginalizations\nmarginalize\nmarginalized\nmarginalizes\nmarginalizing\nmarginally\nmarginate\nmarginated\nmarginates\nmarginating\nmargination\nmarginations\nmargined\nmargining\nmargins\nmargravate\nmargravates\nmargrave\nmargraves\nmargravial\nmargraviate\nmargraviates\nmargravine\nmargravines\nmarguerite\nmarguerites\nmaria\nmariachi\nmariachis\nmariculture\nmaricultures\nmariculturist\nmariculturists\nmarigold\nmarigolds\nmarihuana\nmarihuanas\nmarijuana\nmarijuanas\nmarimba\nmarimbas\nmarimbist\nmarimbists\nmarina\nmarinade\nmarinaded\nmarinades\nmarinading\nmarinara\nmarinaras\nmarinas\nmarinate\nmarinated\nmarinates\nmarinating\nmarination\nmarinations\nmarine\nmariner\nmariners\nmarines\nmarionette\nmarionettes\nmariposa\nmariposas\nmarish\nmarishes\nmarital\nmaritally\nmaritime\nmarjoram\nmarjorams\nmark\nmarkdown\nmarkdowns\nmarked\nmarkedly\nmarkedness\nmarkednesses\nmarker\nmarkers\nmarket\nmarketabilities\nmarketability\nmarketable\nmarketed\nmarketeer\nmarketeers\nmarketer\nmarketers\nmarketing\nmarketings\nmarketplace\nmarketplaces\nmarkets\nmarkhoor\nmarkhoors\nmarkhor\nmarkhors\nmarking\nmarkings\nmarkka\nmarkkaa\nmarkkas\nmarks\nmarksman\nmarksmanship\nmarksmanships\nmarksmen\nmarkswoman\nmarkswomen\nmarkup\nmarkups\nmarl\nmarled\nmarlier\nmarliest\nmarlin\nmarline\nmarlines\nmarlinespike\nmarlinespikes\nmarling\nmarlings\nmarlins\nmarlinspike\nmarlinspikes\nmarlite\nmarlites\nmarlitic\nmarls\nmarlstone\nmarlstones\nmarly\nmarmalade\nmarmalades\nmarmite\nmarmites\nmarmoreal\nmarmoreally\nmarmorean\nmarmoset\nmarmosets\nmarmot\nmarmots\nmarocain\nmarocains\nmaroon\nmarooned\nmarooning\nmaroons\nmarplot\nmarplots\nmarque\nmarquee\nmarquees\nmarques\nmarquess\nmarquessate\nmarquessates\nmarquesses\nmarqueterie\nmarqueteries\nmarquetries\nmarquetry\nmarquis\nmarquisate\nmarquisates\nmarquise\nmarquises\nmarquisette\nmarquisettes\nmarram\nmarrams\nmarrano\nmarranos\nmarred\nmarrer\nmarrers\nmarriage\nmarriageabilities\nmarriageability\nmarriageable\nmarriages\nmarried\nmarrieds\nmarrier\nmarriers\nmarries\nmarring\nmarron\nmarrons\nmarrow\nmarrowbone\nmarrowbones\nmarrowed\nmarrowfat\nmarrowfats\nmarrowing\nmarrows\nmarrowy\nmarry\nmarrying\nmars\nmarsala\nmarsalas\nmarse\nmarses\nmarsh\nmarshal\nmarshalcies\nmarshalcy\nmarshaled\nmarshaling\nmarshall\nmarshalled\nmarshalling\nmarshalls\nmarshals\nmarshalship\nmarshalships\nmarshes\nmarshier\nmarshiest\nmarshiness\nmarshinesses\nmarshland\nmarshlands\nmarshmallow\nmarshmallows\nmarshmallowy\nmarshy\nmarsupia\nmarsupial\nmarsupials\nmarsupium\nmart\nmartagon\nmartagons\nmarted\nmartello\nmartellos\nmarten\nmartens\nmartensite\nmartensites\nmartensitic\nmartensitically\nmartial\nmartially\nmartian\nmartians\nmartin\nmartinet\nmartinets\nmarting\nmartingale\nmartingales\nmartini\nmartinis\nmartins\nmartlet\nmartlets\nmarts\nmartyr\nmartyrdom\nmartyrdoms\nmartyred\nmartyries\nmartyring\nmartyrization\nmartyrizations\nmartyrize\nmartyrized\nmartyrizes\nmartyrizing\nmartyrly\nmartyrologies\nmartyrologist\nmartyrologists\nmartyrology\nmartyrs\nmartyry\nmarvel\nmarveled\nmarveling\nmarvelled\nmarvelling\nmarvellous\nmarvelous\nmarvelously\nmarvelousness\nmarvelousnesses\nmarvels\nmarvy\nmaryjane\nmaryjanes\nmarzipan\nmarzipans\nmas\nmascara\nmascaraed\nmascaraing\nmascaras\nmascarpone\nmascarpones\nmascon\nmascons\nmascot\nmascots\nmasculine\nmasculinely\nmasculines\nmasculinise\nmasculinised\nmasculinises\nmasculinising\nmasculinist\nmasculinists\nmasculinities\nmasculinity\nmasculinization\nmasculinizations\nmasculinize\nmasculinized\nmasculinizes\nmasculinizing\nmaser\nmasers\nmash\nmashed\nmasher\nmashers\nmashes\nmashie\nmashies\nmashing\nmashy\nmasjid\nmasjids\nmask\nmaskable\nmasked\nmaskeg\nmaskegs\nmasker\nmaskers\nmasking\nmaskings\nmasklike\nmasks\nmasochism\nmasochisms\nmasochist\nmasochistic\nmasochistically\nmasochists\nmason\nmasoned\nmasonic\nmasoning\nmasonries\nmasonry\nmasons\nmasque\nmasquer\nmasquerade\nmasqueraded\nmasquerader\nmasqueraders\nmasquerades\nmasquerading\nmasquers\nmasques\nmass\nmassa\nmassacre\nmassacred\nmassacrer\nmassacrers\nmassacres\nmassacring\nmassage\nmassaged\nmassager\nmassagers\nmassages\nmassaging\nmassas\nmassasauga\nmassasaugas\nmasscult\nmasscults\nmasse\nmassed\nmassedly\nmasses\nmasseter\nmasseteric\nmasseters\nmasseur\nmasseurs\nmasseuse\nmasseuses\nmassicot\nmassicots\nmassier\nmassiest\nmassif\nmassifs\nmassing\nmassive\nmassively\nmassiveness\nmassivenesses\nmassless\nmassy\nmast\nmastaba\nmastabah\nmastabahs\nmastabas\nmastectomies\nmastectomy\nmasted\nmaster\nmastered\nmasterful\nmasterfully\nmasterfulness\nmasterfulnesses\nmasteries\nmastering\nmasterliness\nmasterlinesses\nmasterly\nmastermind\nmasterminded\nmasterminding\nmasterminds\nmasterpiece\nmasterpieces\nmasters\nmastership\nmasterships\nmastersinger\nmastersingers\nmasterstroke\nmasterstrokes\nmasterwork\nmasterworks\nmastery\nmasthead\nmastheaded\nmastheading\nmastheads\nmastic\nmasticate\nmasticated\nmasticates\nmasticating\nmastication\nmastications\nmasticator\nmasticatories\nmasticators\nmasticatory\nmastiche\nmastiches\nmastics\nmastiff\nmastiffs\nmastigophoran\nmastigophorans\nmasting\nmastitic\nmastitides\nmastitis\nmastix\nmastixes\nmastless\nmastlike\nmastodon\nmastodonic\nmastodons\nmastodont\nmastodonts\nmastoid\nmastoidectomies\nmastoidectomy\nmastoiditides\nmastoiditis\nmastoids\nmasts\nmasturbate\nmasturbated\nmasturbates\nmasturbating\nmasturbation\nmasturbations\nmasturbator\nmasturbators\nmasturbatory\nmasurium\nmasuriums\nmat\nmatador\nmatadors\nmatambala\nmatch\nmatchable\nmatchboard\nmatchboards\nmatchbook\nmatchbooks\nmatchbox\nmatchboxes\nmatched\nmatcher\nmatchers\nmatches\nmatching\nmatchless\nmatchlessly\nmatchlock\nmatchlocks\nmatchmaker\nmatchmakers\nmatchmaking\nmatchmakings\nmatchstick\nmatchsticks\nmatchup\nmatchups\nmatchwood\nmatchwoods\nmate\nmated\nmateless\nmatelot\nmatelote\nmatelotes\nmatelots\nmater\nmaterfamilias\nmaterfamiliases\nmaterial\nmaterialise\nmaterialised\nmaterialises\nmaterialising\nmaterialism\nmaterialisms\nmaterialist\nmaterialistic\nmaterialistically\nmaterialists\nmaterialities\nmateriality\nmaterialization\nmaterializations\nmaterialize\nmaterialized\nmaterializer\nmaterializers\nmaterializes\nmaterializing\nmaterially\nmaterialness\nmaterialnesses\nmaterials\nmateriel\nmateriels\nmaternal\nmaternalism\nmaternalisms\nmaternally\nmaternities\nmaternity\nmaters\nmates\nmateship\nmateships\nmatey\nmateyness\nmateynesses\nmateys\nmath\nmathematic\nmathematical\nmathematically\nmathematician\nmathematicians\nmathematics\nmathematization\nmathematizations\nmathematize\nmathematized\nmathematizes\nmathematizing\nmaths\nmatilda\nmatildas\nmatin\nmatinal\nmatinee\nmatinees\nmatiness\nmatinesses\nmating\nmatings\nmatins\nmatless\nmatrass\nmatrasses\nmatres\nmatriarch\nmatriarchal\nmatriarchate\nmatriarchates\nmatriarchies\nmatriarchs\nmatriarchy\nmatrices\nmatricidal\nmatricide\nmatricides\nmatriculant\nmatriculants\nmatriculate\nmatriculated\nmatriculates\nmatriculating\nmatriculation\nmatriculations\nmatrilineal\nmatrilineally\nmatrimonial\nmatrimonially\nmatrimonies\nmatrimony\nmatrix\nmatrixes\nmatron\nmatronal\nmatronly\nmatrons\nmatronymic\nmatronymics\nmats\nmatsah\nmatsahs\nmatt\nmatte\nmatted\nmattedly\nmatter\nmattered\nmattering\nmatters\nmattery\nmattes\nmattin\nmatting\nmattings\nmattins\nmattock\nmattocks\nmattoid\nmattoids\nmattrass\nmattrasses\nmattress\nmattresses\nmatts\nmaturate\nmaturated\nmaturates\nmaturating\nmaturation\nmaturational\nmaturations\nmature\nmatured\nmaturely\nmaturer\nmatures\nmaturest\nmaturing\nmaturities\nmaturity\nmatutinal\nmatutinally\nmatza\nmatzah\nmatzahs\nmatzas\nmatzo\nmatzoh\nmatzohs\nmatzoon\nmatzoons\nmatzos\nmatzot\nmatzoth\nmaud\nmaudlin\nmauds\nmauger\nmaugre\nmaul\nmauled\nmauler\nmaulers\nmauling\nmauls\nmaulstick\nmaulsticks\nmaumet\nmaumetries\nmaumetry\nmaumets\nmaun\nmaund\nmaunder\nmaundered\nmaunderer\nmaunderers\nmaundering\nmaunders\nmaundies\nmaunds\nmaundy\nmausolea\nmausoleum\nmausoleums\nmaut\nmauts\nmauve\nmauves\nmaven\nmavens\nmaverick\nmavericks\nmavie\nmavies\nmavin\nmavins\nmavis\nmavises\nmavourneen\nmavourneens\nmaw\nmawed\nmawing\nmawkish\nmawkishly\nmawkishness\nmawkishnesses\nmawn\nmaws\nmax\nmaxes\nmaxi\nmaxicoat\nmaxicoats\nmaxilla\nmaxillae\nmaxillaries\nmaxillary\nmaxillas\nmaxilliped\nmaxillipeds\nmaxillofacial\nmaxim\nmaxima\nmaximal\nmaximalist\nmaximalists\nmaximally\nmaximals\nmaximin\nmaximins\nmaximise\nmaximised\nmaximises\nmaximising\nmaximite\nmaximites\nmaximization\nmaximizations\nmaximize\nmaximized\nmaximizer\nmaximizers\nmaximizes\nmaximizing\nmaxims\nmaximum\nmaximums\nmaxis\nmaxixe\nmaxixes\nmaxwell\nmaxwells\nmay\nmaya\nmayan\nmayapple\nmayapples\nmayas\nmaybe\nmaybes\nmaybush\nmaybushes\nmayday\nmaydays\nmayed\nmayest\nmayflies\nmayflower\nmayflowers\nmayfly\nmayhap\nmayhem\nmayhems\nmaying\nmayings\nmayo\nmayonnaise\nmayonnaises\nmayor\nmayoral\nmayoralties\nmayoralty\nmayoress\nmayoresses\nmayors\nmayos\nmaypole\nmaypoles\nmaypop\nmaypops\nmays\nmayst\nmayvin\nmayvins\nmayweed\nmayweeds\nmazaedia\nmazaedium\nmazard\nmazards\nmaze\nmazed\nmazedly\nmazelike\nmazer\nmazers\nmazes\nmazier\nmaziest\nmazily\nmaziness\nmazinesses\nmazing\nmazourka\nmazourkas\nmazuma\nmazumas\nmazurka\nmazurkas\nmazy\nmazzard\nmazzards\nmbira\nmbiras\nme\nmead\nmeadow\nmeadowland\nmeadowlands\nmeadowlark\nmeadowlarks\nmeadows\nmeadowsweet\nmeadowsweets\nmeadowy\nmeads\nmeager\nmeagerly\nmeagerness\nmeagernesses\nmeagre\nmeagrely\nmeal\nmealie\nmealier\nmealies\nmealiest\nmealless\nmeals\nmealtime\nmealtimes\nmealworm\nmealworms\nmealy\nmealybug\nmealybugs\nmealymouthed\nmean\nmeander\nmeandered\nmeandering\nmeanders\nmeandrous\nmeaner\nmeaners\nmeanest\nmeanie\nmeanies\nmeaning\nmeaningful\nmeaningfully\nmeaningfulness\nmeaningfulnesses\nmeaningless\nmeaninglessly\nmeaninglessness\nmeaninglessnesses\nmeaningly\nmeanings\nmeanly\nmeanness\nmeannesses\nmeans\nmeanspirited\nmeant\nmeantime\nmeantimes\nmeanwhile\nmeanwhiles\nmeany\nmeasle\nmeasled\nmeasles\nmeaslier\nmeasliest\nmeasly\nmeasurabilities\nmeasurability\nmeasurable\nmeasurably\nmeasure\nmeasured\nmeasuredly\nmeasureless\nmeasurement\nmeasurements\nmeasurer\nmeasurers\nmeasures\nmeasuring\nmeat\nmeatal\nmeatball\nmeatballs\nmeated\nmeathead\nmeatheads\nmeatier\nmeatiest\nmeatily\nmeatiness\nmeatinesses\nmeatless\nmeatloaf\nmeatloaves\nmeatman\nmeatmen\nmeatpacking\nmeatpackings\nmeats\nmeatus\nmeatuses\nmeaty\nmecamylamine\nmecamylamines\nmecca\nmeccas\nmechanic\nmechanical\nmechanically\nmechanicals\nmechanician\nmechanicians\nmechanics\nmechanism\nmechanisms\nmechanist\nmechanistic\nmechanistically\nmechanists\nmechanizable\nmechanization\nmechanizations\nmechanize\nmechanized\nmechanizer\nmechanizers\nmechanizes\nmechanizing\nmechanochemical\nmechanochemistries\nmechanochemistry\nmechanoreception\nmechanoreceptions\nmechanoreceptive\nmechanoreceptor\nmechanoreceptors\nmeclizine\nmeclizines\nmeconium\nmeconiums\nmed\nmedaillon\nmedaillons\nmedaka\nmedakas\nmedal\nmedaled\nmedaling\nmedalist\nmedalists\nmedalled\nmedallic\nmedalling\nmedallion\nmedallions\nmedallist\nmedallists\nmedals\nmeddle\nmeddled\nmeddler\nmeddlers\nmeddles\nmeddlesome\nmeddlesomeness\nmeddlesomenesses\nmeddling\nmedevac\nmedevacked\nmedevacking\nmedevacs\nmedflies\nmedfly\nmedia\nmediacies\nmediacy\nmediad\nmediae\nmediaeval\nmediaevals\nmediagenic\nmedial\nmedially\nmedials\nmedian\nmedianly\nmedians\nmediant\nmediants\nmedias\nmediastina\nmediastinal\nmediastinum\nmediate\nmediated\nmediately\nmediates\nmediating\nmediation\nmediational\nmediations\nmediative\nmediator\nmediators\nmediatory\nmediatrices\nmediatrix\nmediatrixes\nmedic\nmedicable\nmedicaid\nmedicaids\nmedical\nmedically\nmedicals\nmedicament\nmedicamentous\nmedicaments\nmedicare\nmedicares\nmedicate\nmedicated\nmedicates\nmedicating\nmedication\nmedications\nmedicinable\nmedicinal\nmedicinally\nmedicinals\nmedicine\nmedicined\nmedicines\nmedicining\nmedick\nmedicks\nmedico\nmedicolegal\nmedicos\nmedics\nmedieval\nmedievalism\nmedievalisms\nmedievalist\nmedievalists\nmedievally\nmedievals\nmedigap\nmedigaps\nmedii\nmedina\nmedinas\nmediocre\nmediocrities\nmediocrity\nmeditate\nmeditated\nmeditates\nmeditating\nmeditation\nmeditations\nmeditative\nmeditatively\nmeditativeness\nmeditativenesses\nmeditator\nmeditators\nmediterranean\nmedium\nmediumistic\nmediums\nmediumship\nmediumships\nmedius\nmedlar\nmedlars\nmedley\nmedleys\nmedulla\nmedullae\nmedullar\nmedullary\nmedullas\nmedullated\nmedulloblastoma\nmedulloblastomas\nmedulloblastomata\nmedusa\nmedusae\nmedusal\nmedusan\nmedusans\nmedusas\nmedusoid\nmedusoids\nmeed\nmeeds\nmeek\nmeeker\nmeekest\nmeekly\nmeekness\nmeeknesses\nmeerkat\nmeerkats\nmeerschaum\nmeerschaums\nmeet\nmeeter\nmeeters\nmeeting\nmeetinghouse\nmeetinghouses\nmeetings\nmeetly\nmeetness\nmeetnesses\nmeets\nmeg\nmegabar\nmegabars\nmegabit\nmegabits\nmegabuck\nmegabucks\nmegabyte\nmegabytes\nmegacities\nmegacity\nmegacorporation\nmegacorporations\nmegacycle\nmegacycles\nmegadeal\nmegadeals\nmegadeath\nmegadeaths\nmegadose\nmegadoses\nmegadyne\nmegadynes\nmegafauna\nmegafaunae\nmegafaunal\nmegafaunas\nmegagamete\nmegagametes\nmegagametophyte\nmegagametophytes\nmegahertz\nmegahit\nmegahits\nmegakaryocyte\nmegakaryocytes\nmegakaryocytic\nmegalith\nmegalithic\nmegaliths\nmegaloblast\nmegaloblastic\nmegaloblasts\nmegalomania\nmegalomaniac\nmegalomaniacal\nmegalomaniacally\nmegalomaniacs\nmegalomanias\nmegalomanic\nmegalopolis\nmegalopolises\nmegalopolitan\nmegalopolitans\nmegalops\nmegalopses\nmegaparsec\nmegaparsecs\nmegaphone\nmegaphoned\nmegaphones\nmegaphonic\nmegaphoning\nmegapod\nmegapode\nmegapodes\nmegapods\nmegaproject\nmegaprojects\nmegascopic\nmegascopically\nmegasporangia\nmegasporangium\nmegaspore\nmegaspores\nmegasporic\nmegasporogeneses\nmegasporogenesis\nmegasporophyll\nmegasporophylls\nmegass\nmegasse\nmegasses\nmegastar\nmegastars\nmegaton\nmegatonnage\nmegatonnages\nmegatons\nmegavitamin\nmegavitamins\nmegavolt\nmegavolts\nmegawatt\nmegawatts\nmegillah\nmegillahs\nmegilloth\nmegilp\nmegilph\nmegilphs\nmegilps\nmegohm\nmegohms\nmegrim\nmegrims\nmegs\nmeikle\nmeinie\nmeinies\nmeiny\nmeioses\nmeiosis\nmeiotic\nmeiotically\nmeitnerium\nmeitneriums\nmel\nmelamdim\nmelamed\nmelamine\nmelamines\nmelancholia\nmelancholiac\nmelancholiacs\nmelancholias\nmelancholic\nmelancholics\nmelancholies\nmelancholy\nmelange\nmelanges\nmelanian\nmelanic\nmelanics\nmelanin\nmelanins\nmelanism\nmelanisms\nmelanist\nmelanistic\nmelanists\nmelanite\nmelanites\nmelanitic\nmelanization\nmelanizations\nmelanize\nmelanized\nmelanizes\nmelanizing\nmelanoblast\nmelanoblasts\nmelanocyte\nmelanocytes\nmelanogeneses\nmelanogenesis\nmelanoid\nmelanoids\nmelanoma\nmelanomas\nmelanomata\nmelanophore\nmelanophores\nmelanosome\nmelanosomes\nmelanotic\nmelanous\nmelatonin\nmelatonins\nmeld\nmelded\nmelder\nmelders\nmelding\nmelds\nmelee\nmelees\nmelic\nmelilite\nmelilites\nmelilot\nmelilots\nmelinite\nmelinites\nmeliorate\nmeliorated\nmeliorates\nmeliorating\nmelioration\nmeliorations\nmeliorative\nmeliorator\nmeliorators\nmeliorism\nmeliorisms\nmeliorist\nmelioristic\nmeliorists\nmelisma\nmelismas\nmelismata\nmelismatic\nmell\nmelled\nmellific\nmellifluent\nmellifluently\nmellifluous\nmellifluously\nmellifluousness\nmellifluousnesses\nmelling\nmellophone\nmellophones\nmellotron\nmellotrons\nmellow\nmellowed\nmellower\nmellowest\nmellowing\nmellowly\nmellowness\nmellownesses\nmellows\nmells\nmelodeon\nmelodeons\nmelodia\nmelodias\nmelodic\nmelodica\nmelodically\nmelodicas\nmelodies\nmelodious\nmelodiously\nmelodiousness\nmelodiousnesses\nmelodise\nmelodised\nmelodises\nmelodising\nmelodist\nmelodists\nmelodize\nmelodized\nmelodizer\nmelodizers\nmelodizes\nmelodizing\nmelodrama\nmelodramas\nmelodramatic\nmelodramatically\nmelodramatics\nmelodramatise\nmelodramatised\nmelodramatises\nmelodramatising\nmelodramatist\nmelodramatists\nmelodramatization\nmelodramatizations\nmelodramatize\nmelodramatized\nmelodramatizes\nmelodramatizing\nmelody\nmeloid\nmeloids\nmelon\nmelons\nmelphalan\nmelphalans\nmels\nmelt\nmeltabilities\nmeltability\nmeltable\nmeltage\nmeltages\nmeltdown\nmeltdowns\nmelted\nmelter\nmelters\nmelting\nmeltingly\nmelton\nmeltons\nmelts\nmeltwater\nmeltwaters\nmem\nmember\nmembered\nmembers\nmembership\nmemberships\nmembrane\nmembraned\nmembranes\nmembranous\nmembranously\nmeme\nmemento\nmementoes\nmementos\nmemes\nmemo\nmemoir\nmemoirist\nmemoirists\nmemoirs\nmemorabilia\nmemorabilities\nmemorability\nmemorable\nmemorableness\nmemorablenesses\nmemorably\nmemoranda\nmemorandum\nmemorandums\nmemorial\nmemorialise\nmemorialised\nmemorialises\nmemorialising\nmemorialist\nmemorialists\nmemorialize\nmemorialized\nmemorializes\nmemorializing\nmemorially\nmemorials\nmemories\nmemorise\nmemorised\nmemorises\nmemorising\nmemoriter\nmemorizable\nmemorization\nmemorizations\nmemorize\nmemorized\nmemorizer\nmemorizers\nmemorizes\nmemorizing\nmemory\nmemos\nmems\nmemsahib\nmemsahibs\nmen\nmenace\nmenaced\nmenacer\nmenacers\nmenaces\nmenacing\nmenacingly\nmenad\nmenadione\nmenadiones\nmenads\nmenage\nmenagerie\nmenageries\nmenages\nmenarche\nmenarcheal\nmenarches\nmenazon\nmenazons\nmend\nmendable\nmendacious\nmendaciously\nmendaciousness\nmendaciousnesses\nmendacities\nmendacity\nmended\nmendelevium\nmendeleviums\nmender\nmenders\nmendicancies\nmendicancy\nmendicant\nmendicants\nmendicities\nmendicity\nmendigo\nmendigos\nmending\nmendings\nmends\nmenfolk\nmenfolks\nmenhaden\nmenhadens\nmenhir\nmenhirs\nmenial\nmenially\nmenials\nmeningeal\nmeninges\nmeningioma\nmeningiomas\nmeningiomata\nmeningitic\nmeningitides\nmeningitis\nmeningococcal\nmeningococci\nmeningococcic\nmeningococcus\nmeningoencephalitic\nmeningoencephalitides\nmeningoencephalitis\nmeninx\nmeniscal\nmenisci\nmeniscus\nmeniscuses\nmeno\nmenologies\nmenology\nmenopausal\nmenopause\nmenopauses\nmenorah\nmenorahs\nmenorrhagia\nmenorrhagias\nmensa\nmensae\nmensal\nmensas\nmensch\nmenschen\nmensches\nmense\nmensed\nmenseful\nmenseless\nmenservants\nmenses\nmensing\nmenstrua\nmenstrual\nmenstruate\nmenstruated\nmenstruates\nmenstruating\nmenstruation\nmenstruations\nmenstruum\nmenstruums\nmensurabilities\nmensurability\nmensurable\nmensural\nmensuration\nmensurations\nmenswear\nmenta\nmental\nmentalism\nmentalisms\nmentalist\nmentalistic\nmentalists\nmentalities\nmentality\nmentally\nmentation\nmentations\nmenthene\nmenthenes\nmenthol\nmentholated\nmenthols\nmention\nmentionable\nmentioned\nmentioner\nmentioners\nmentioning\nmentions\nmentor\nmentored\nmentoring\nmentors\nmentorship\nmentorships\nmentum\nmenu\nmenus\nmeou\nmeoued\nmeouing\nmeous\nmeow\nmeowed\nmeowing\nmeows\nmeperidine\nmeperidines\nmephitic\nmephitis\nmephitises\nmeprobamate\nmeprobamates\nmerbromin\nmerbromins\nmercantile\nmercantilism\nmercantilisms\nmercantilist\nmercantilistic\nmercantilists\nmercaptan\nmercaptans\nmercapto\nmercaptopurine\nmercaptopurines\nmercenaries\nmercenarily\nmercenariness\nmercenarinesses\nmercenary\nmercer\nmerceries\nmercerise\nmercerised\nmercerises\nmercerising\nmercerization\nmercerizations\nmercerize\nmercerized\nmercerizes\nmercerizing\nmercers\nmercery\nmerchandise\nmerchandised\nmerchandiser\nmerchandisers\nmerchandises\nmerchandising\nmerchandisings\nmerchandize\nmerchandized\nmerchandizes\nmerchandizing\nmerchandizings\nmerchant\nmerchantabilities\nmerchantability\nmerchantable\nmerchanted\nmerchanting\nmerchantman\nmerchantmen\nmerchants\nmercies\nmerciful\nmercifully\nmercifulness\nmercifulnesses\nmerciless\nmercilessly\nmercilessness\nmercilessnesses\nmercurate\nmercurated\nmercurates\nmercurating\nmercuration\nmercurations\nmercurial\nmercurially\nmercurialness\nmercurialnesses\nmercurials\nmercuric\nmercuries\nmercurous\nmercury\nmercy\nmerde\nmerdes\nmere\nmerely\nmerengue\nmerengues\nmerer\nmeres\nmerest\nmeretricious\nmeretriciously\nmeretriciousness\nmeretriciousnesses\nmerganser\nmergansers\nmerge\nmerged\nmergence\nmergences\nmerger\nmergers\nmerges\nmerging\nmeridian\nmeridians\nmeridional\nmeridionally\nmeridionals\nmeringue\nmeringues\nmerino\nmerinos\nmerises\nmerisis\nmeristem\nmeristematic\nmeristematically\nmeristems\nmeristic\nmeristically\nmerit\nmerited\nmeriting\nmeritocracies\nmeritocracy\nmeritocrat\nmeritocratic\nmeritocrats\nmeritorious\nmeritoriously\nmeritoriousness\nmeritoriousnesses\nmerits\nmerk\nmerks\nmerl\nmerle\nmerles\nmerlin\nmerlins\nmerlon\nmerlons\nmerlot\nmerlots\nmerls\nmermaid\nmermaids\nmerman\nmermen\nmeroblastic\nmeroblastically\nmerocrine\nmeromorphic\nmeromyosin\nmeromyosins\nmeropia\nmeropias\nmeropic\nmerozoite\nmerozoites\nmerrier\nmerriest\nmerrily\nmerriment\nmerriments\nmerriness\nmerrinesses\nmerry\nmerrymaker\nmerrymakers\nmerrymaking\nmerrymakings\nmerrythought\nmerrythoughts\nmesa\nmesalliance\nmesalliances\nmesally\nmesarch\nmesas\nmescal\nmescaline\nmescalines\nmescals\nmesclun\nmescluns\nmesdames\nmesdemoiselles\nmeseemed\nmeseemeth\nmeseems\nmesembryanthemum\nmesembryanthemums\nmesencephala\nmesencephalic\nmesencephalon\nmesenchymal\nmesenchyme\nmesenchymes\nmesentera\nmesenteric\nmesenteries\nmesenteron\nmesentery\nmesh\nmeshed\nmeshes\nmeshier\nmeshiest\nmeshing\nmeshuga\nmeshugah\nmeshugga\nmeshuggah\nmeshugge\nmeshuggener\nmeshuggeners\nmeshwork\nmeshworks\nmeshy\nmesial\nmesially\nmesian\nmesic\nmesmeric\nmesmerically\nmesmerise\nmesmerised\nmesmerises\nmesmerising\nmesmerism\nmesmerisms\nmesmerist\nmesmerists\nmesmerize\nmesmerized\nmesmerizer\nmesmerizers\nmesmerizes\nmesmerizing\nmesnalties\nmesnalty\nmesne\nmesnes\nmesocarp\nmesocarps\nmesocyclone\nmesocyclones\nmesoderm\nmesodermal\nmesoderms\nmesoglea\nmesogleas\nmesogloea\nmesogloeas\nmesomere\nmesomeres\nmesomorph\nmesomorphic\nmesomorphies\nmesomorphs\nmesomorphy\nmeson\nmesonephric\nmesonephroi\nmesonephros\nmesonic\nmesons\nmesopause\nmesopauses\nmesopelagic\nmesophyl\nmesophyll\nmesophyllic\nmesophyllous\nmesophylls\nmesophyls\nmesophyte\nmesophytes\nmesophytic\nmesoscale\nmesosome\nmesosomes\nmesosphere\nmesospheres\nmesospheric\nmesothelia\nmesothelial\nmesothelioma\nmesotheliomas\nmesotheliomata\nmesothelium\nmesothoraces\nmesothoracic\nmesothorax\nmesothoraxes\nmesotron\nmesotrons\nmesotrophic\nmesquit\nmesquite\nmesquites\nmesquits\nmess\nmessage\nmessaged\nmessages\nmessaging\nmessaline\nmessalines\nmessan\nmessans\nmessed\nmesseigneurs\nmessenger\nmessengers\nmesses\nmessiah\nmessiahs\nmessiahship\nmessiahships\nmessianic\nmessianism\nmessianisms\nmessier\nmessiest\nmessieurs\nmessily\nmessiness\nmessinesses\nmessing\nmessman\nmessmate\nmessmates\nmessmen\nmessuage\nmessuages\nmessy\nmestee\nmestees\nmesteso\nmestesoes\nmestesos\nmestino\nmestinoes\nmestinos\nmestiza\nmestizas\nmestizo\nmestizoes\nmestizos\nmestranol\nmestranols\nmet\nmeta\nmetabolic\nmetabolically\nmetabolism\nmetabolisms\nmetabolite\nmetabolites\nmetabolizable\nmetabolize\nmetabolized\nmetabolizes\nmetabolizing\nmetacarpal\nmetacarpals\nmetacarpi\nmetacarpus\nmetacenter\nmetacenters\nmetacentric\nmetacentrics\nmetacercaria\nmetacercariae\nmetacercarial\nmetachromatic\nmetaethical\nmetaethics\nmetafiction\nmetafictional\nmetafictionist\nmetafictionists\nmetafictions\nmetagalactic\nmetagalaxies\nmetagalaxy\nmetage\nmetageneses\nmetagenesis\nmetagenetic\nmetages\nmetal\nmetalanguage\nmetalanguages\nmetaled\nmetaling\nmetalinguistic\nmetalinguistics\nmetalise\nmetalised\nmetalises\nmetalising\nmetalist\nmetalists\nmetalize\nmetalized\nmetalizes\nmetalizing\nmetalled\nmetallic\nmetallically\nmetallics\nmetalliferous\nmetalling\nmetallization\nmetallizations\nmetallize\nmetallized\nmetallizes\nmetallizing\nmetallographer\nmetallographers\nmetallographic\nmetallographically\nmetallographies\nmetallography\nmetalloid\nmetalloidal\nmetalloids\nmetallophone\nmetallophones\nmetallurgical\nmetallurgically\nmetallurgies\nmetallurgist\nmetallurgists\nmetallurgy\nmetalmark\nmetalmarks\nmetals\nmetalsmith\nmetalsmiths\nmetalware\nmetalwares\nmetalwork\nmetalworker\nmetalworkers\nmetalworking\nmetalworkings\nmetalworks\nmetamathematical\nmetamathematics\nmetamer\nmetamere\nmetameres\nmetameric\nmetamerically\nmetamerism\nmetamerisms\nmetamers\nmetamorphic\nmetamorphically\nmetamorphism\nmetamorphisms\nmetamorphose\nmetamorphosed\nmetamorphoses\nmetamorphosing\nmetamorphosis\nmetanalyses\nmetanalysis\nmetanephric\nmetanephroi\nmetanephros\nmetaphase\nmetaphases\nmetaphor\nmetaphoric\nmetaphorical\nmetaphorically\nmetaphors\nmetaphosphate\nmetaphosphates\nmetaphrase\nmetaphrases\nmetaphysic\nmetaphysical\nmetaphysically\nmetaphysician\nmetaphysicians\nmetaphysics\nmetaplasia\nmetaplasias\nmetaplastic\nmetapsychological\nmetapsychologies\nmetapsychology\nmetasequoia\nmetasequoias\nmetasomatic\nmetasomatism\nmetasomatisms\nmetastabilities\nmetastability\nmetastable\nmetastably\nmetastases\nmetastasis\nmetastasize\nmetastasized\nmetastasizes\nmetastasizing\nmetastatic\nmetastatically\nmetatarsal\nmetatarsals\nmetatarsi\nmetatarsus\nmetate\nmetates\nmetatheses\nmetathesis\nmetathetic\nmetathetical\nmetathetically\nmetathoraces\nmetathoracic\nmetathorax\nmetathoraxes\nmetaxylem\nmetaxylems\nmetazoa\nmetazoal\nmetazoan\nmetazoans\nmetazoic\nmetazoon\nmete\nmeted\nmetempsychoses\nmetempsychosis\nmetencephala\nmetencephalic\nmetencephalon\nmetencephalons\nmeteor\nmeteoric\nmeteorically\nmeteorite\nmeteorites\nmeteoritic\nmeteoritical\nmeteoriticist\nmeteoriticists\nmeteoritics\nmeteoroid\nmeteoroidal\nmeteoroids\nmeteorologic\nmeteorological\nmeteorologically\nmeteorologies\nmeteorologist\nmeteorologists\nmeteorology\nmeteors\nmetepa\nmetepas\nmeter\nmeterage\nmeterages\nmetered\nmetering\nmeters\nmeterstick\nmetersticks\nmetes\nmetestrus\nmetestruses\nmeth\nmethacrylate\nmethacrylates\nmethadon\nmethadone\nmethadones\nmethadons\nmethamphetamine\nmethamphetamines\nmethanation\nmethanations\nmethane\nmethanes\nmethanol\nmethanols\nmethaqualone\nmethaqualones\nmethedrine\nmethedrines\nmetheglin\nmetheglins\nmethemoglobin\nmethemoglobinemia\nmethemoglobinemias\nmethemoglobins\nmethenamine\nmethenamines\nmethicillin\nmethicillins\nmethinks\nmethionine\nmethionines\nmethod\nmethodic\nmethodical\nmethodically\nmethodicalness\nmethodicalnesses\nmethodise\nmethodised\nmethodises\nmethodising\nmethodism\nmethodisms\nmethodist\nmethodistic\nmethodists\nmethodize\nmethodized\nmethodizes\nmethodizing\nmethodological\nmethodologically\nmethodologies\nmethodologist\nmethodologists\nmethodology\nmethods\nmethotrexate\nmethotrexates\nmethought\nmethoxy\nmethoxychlor\nmethoxychlors\nmethoxyflurane\nmethoxyfluranes\nmethoxyl\nmeths\nmethyl\nmethylal\nmethylals\nmethylamine\nmethylamines\nmethylase\nmethylases\nmethylate\nmethylated\nmethylates\nmethylating\nmethylation\nmethylations\nmethylator\nmethylators\nmethylcellulose\nmethylcelluloses\nmethylcholanthrene\nmethylcholanthrenes\nmethyldopa\nmethyldopas\nmethylene\nmethylenes\nmethylic\nmethylmercuries\nmethylmercury\nmethylnaphthalene\nmethylnaphthalenes\nmethylphenidate\nmethylphenidates\nmethylprednisolone\nmethylprednisolones\nmethyls\nmethylxanthine\nmethylxanthines\nmethysergide\nmethysergides\nmeticais\nmetical\nmeticals\nmeticulosities\nmeticulosity\nmeticulous\nmeticulously\nmeticulousness\nmeticulousnesses\nmetier\nmetiers\nmeting\nmetis\nmetisse\nmetisses\nmetonym\nmetonymic\nmetonymical\nmetonymies\nmetonyms\nmetonymy\nmetopae\nmetope\nmetopes\nmetopic\nmetopon\nmetopons\nmetre\nmetred\nmetres\nmetric\nmetrical\nmetrically\nmetrication\nmetrications\nmetricize\nmetricized\nmetricizes\nmetricizing\nmetrics\nmetrified\nmetrifies\nmetrify\nmetrifying\nmetring\nmetrist\nmetrists\nmetritis\nmetritises\nmetro\nmetrological\nmetrologies\nmetrologist\nmetrologists\nmetrology\nmetronidazole\nmetronidazoles\nmetronome\nmetronomes\nmetronomic\nmetronomical\nmetronomically\nmetroplex\nmetroplexes\nmetropolis\nmetropolises\nmetropolitan\nmetropolitans\nmetrorrhagia\nmetrorrhagias\nmetros\nmettle\nmettled\nmettles\nmettlesome\nmetump\nmetumps\nmeuniere\nmew\nmewed\nmewing\nmewl\nmewled\nmewler\nmewlers\nmewling\nmewls\nmews\nmezcal\nmezcals\nmeze\nmezereon\nmezereons\nmezereum\nmezereums\nmezes\nmezquit\nmezquite\nmezquites\nmezquits\nmezuza\nmezuzah\nmezuzahs\nmezuzas\nmezuzot\nmezuzoth\nmezzanine\nmezzanines\nmezzo\nmezzos\nmezzotint\nmezzotints\nmho\nmhos\nmi\nmiaou\nmiaoued\nmiaouing\nmiaous\nmiaow\nmiaowed\nmiaowing\nmiaows\nmiasm\nmiasma\nmiasmal\nmiasmas\nmiasmata\nmiasmatic\nmiasmic\nmiasmically\nmiasms\nmiaul\nmiauled\nmiauling\nmiauls\nmib\nmibs\nmica\nmicaceous\nmicas\nmicawber\nmicawbers\nmice\nmicell\nmicella\nmicellae\nmicellar\nmicelle\nmicelles\nmicells\nmiche\nmiched\nmiches\nmiching\nmick\nmickey\nmickeys\nmickle\nmickler\nmickles\nmicklest\nmicks\nmicra\nmicrified\nmicrifies\nmicrify\nmicrifying\nmicro\nmicroampere\nmicroamperes\nmicroanalyses\nmicroanalysis\nmicroanalyst\nmicroanalysts\nmicroanalytic\nmicroanalytical\nmicroanatomical\nmicroanatomies\nmicroanatomy\nmicrobalance\nmicrobalances\nmicrobar\nmicrobarograph\nmicrobarographs\nmicrobars\nmicrobe\nmicrobeam\nmicrobeams\nmicrobes\nmicrobial\nmicrobic\nmicrobiologic\nmicrobiological\nmicrobiologically\nmicrobiologies\nmicrobiologist\nmicrobiologists\nmicrobiology\nmicrobrew\nmicrobrewer\nmicrobreweries\nmicrobrewers\nmicrobrewery\nmicrobrewing\nmicrobrewings\nmicrobrews\nmicroburst\nmicrobursts\nmicrobus\nmicrobuses\nmicrobusses\nmicrocalorimeter\nmicrocalorimeters\nmicrocalorimetric\nmicrocalorimetries\nmicrocalorimetry\nmicrocapsule\nmicrocapsules\nmicrocassette\nmicrocassettes\nmicrocephalic\nmicrocephalics\nmicrocephalies\nmicrocephaly\nmicrochip\nmicrochips\nmicrocircuit\nmicrocircuitries\nmicrocircuitry\nmicrocircuits\nmicrocirculation\nmicrocirculations\nmicrocirculatory\nmicroclimate\nmicroclimates\nmicroclimatic\nmicrocline\nmicroclines\nmicrococcal\nmicrococci\nmicrococcus\nmicrocode\nmicrocodes\nmicrocomputer\nmicrocomputers\nmicrocopies\nmicrocopy\nmicrocosm\nmicrocosmic\nmicrocosmically\nmicrocosmos\nmicrocosmoses\nmicrocosms\nmicrocrystal\nmicrocrystalline\nmicrocrystallinities\nmicrocrystallinity\nmicrocrystals\nmicrocultural\nmicroculture\nmicrocultures\nmicrocurie\nmicrocuries\nmicrocyte\nmicrocytes\nmicrocytic\nmicrodensitometer\nmicrodensitometers\nmicrodensitometric\nmicrodensitometries\nmicrodensitometry\nmicrodissection\nmicrodissections\nmicrodot\nmicrodots\nmicroearthquake\nmicroearthquakes\nmicroeconomic\nmicroeconomics\nmicroelectrode\nmicroelectrodes\nmicroelectronic\nmicroelectronically\nmicroelectronics\nmicroelectrophoreses\nmicroelectrophoresis\nmicroelectrophoretic\nmicroelectrophoretically\nmicroelement\nmicroelements\nmicroencapsulate\nmicroencapsulated\nmicroencapsulates\nmicroencapsulating\nmicroencapsulation\nmicroencapsulations\nmicroenvironment\nmicroenvironmental\nmicroenvironments\nmicroevolution\nmicroevolutionary\nmicroevolutions\nmicrofarad\nmicrofarads\nmicrofauna\nmicrofaunae\nmicrofaunal\nmicrofaunas\nmicrofibril\nmicrofibrillar\nmicrofibrils\nmicrofiche\nmicrofiches\nmicrofilament\nmicrofilaments\nmicrofilaria\nmicrofilariae\nmicrofilarial\nmicrofilm\nmicrofilmable\nmicrofilmed\nmicrofilmer\nmicrofilmers\nmicrofilming\nmicrofilms\nmicroflora\nmicroflorae\nmicrofloral\nmicrofloras\nmicroform\nmicroforms\nmicrofossil\nmicrofossils\nmicrofungi\nmicrofungus\nmicrofunguses\nmicrogamete\nmicrogametes\nmicrogametocyte\nmicrogametocytes\nmicrogram\nmicrograms\nmicrograph\nmicrographed\nmicrographic\nmicrographically\nmicrographics\nmicrographing\nmicrographs\nmicrogravities\nmicrogravity\nmicrogroove\nmicrogrooves\nmicrohabitat\nmicrohabitats\nmicrohm\nmicrohms\nmicroimage\nmicroimages\nmicroinch\nmicroinches\nmicroinject\nmicroinjected\nmicroinjecting\nmicroinjection\nmicroinjections\nmicroinjects\nmicroinstruction\nmicroinstructions\nmicrolepidoptera\nmicrolepidopterous\nmicroliter\nmicroliters\nmicrolith\nmicrolithic\nmicroliths\nmicroluces\nmicrolux\nmicroluxes\nmicromanage\nmicromanaged\nmicromanagement\nmicromanagements\nmicromanager\nmicromanagers\nmicromanages\nmicromanaging\nmicromanipulation\nmicromanipulations\nmicromanipulator\nmicromanipulators\nmicromere\nmicromeres\nmicrometeorite\nmicrometeorites\nmicrometeoritic\nmicrometeoroid\nmicrometeoroids\nmicrometeorological\nmicrometeorologies\nmicrometeorologist\nmicrometeorologists\nmicrometeorology\nmicrometer\nmicrometers\nmicromethod\nmicromethods\nmicromho\nmicromhos\nmicromini\nmicrominiature\nmicrominiaturization\nmicrominiaturizations\nmicrominiaturized\nmicrominis\nmicromolar\nmicromole\nmicromoles\nmicromorphological\nmicromorphologies\nmicromorphology\nmicron\nmicronize\nmicronized\nmicronizes\nmicronizing\nmicrons\nmicronuclei\nmicronucleus\nmicronucleuses\nmicronutrient\nmicronutrients\nmicroorganism\nmicroorganisms\nmicropaleontologic\nmicropaleontological\nmicropaleontologies\nmicropaleontologist\nmicropaleontologists\nmicropaleontology\nmicroparticle\nmicroparticles\nmicrophage\nmicrophages\nmicrophone\nmicrophones\nmicrophonic\nmicrophonics\nmicrophotograph\nmicrophotographer\nmicrophotographers\nmicrophotographic\nmicrophotographies\nmicrophotographs\nmicrophotography\nmicrophotometer\nmicrophotometers\nmicrophotometric\nmicrophotometrically\nmicrophotometries\nmicrophotometry\nmicrophyll\nmicrophyllous\nmicrophylls\nmicrophysical\nmicrophysically\nmicrophysics\nmicropipet\nmicropipets\nmicropipette\nmicropipettes\nmicroplankton\nmicroplanktons\nmicropore\nmicropores\nmicroporosities\nmicroporosity\nmicroporous\nmicroprism\nmicroprisms\nmicroprobe\nmicroprobes\nmicroprocessor\nmicroprocessors\nmicroprogram\nmicroprogramming\nmicroprogrammings\nmicroprograms\nmicroprojection\nmicroprojections\nmicroprojector\nmicroprojectors\nmicropublisher\nmicropublishers\nmicropublishing\nmicropublishings\nmicropulsation\nmicropulsations\nmicropuncture\nmicropunctures\nmicropylar\nmicropyle\nmicropyles\nmicroquake\nmicroquakes\nmicroradiograph\nmicroradiographic\nmicroradiographies\nmicroradiographs\nmicroradiography\nmicroreader\nmicroreaders\nmicroreproduction\nmicroreproductions\nmicros\nmicroscale\nmicroscales\nmicroscope\nmicroscopes\nmicroscopic\nmicroscopical\nmicroscopically\nmicroscopies\nmicroscopist\nmicroscopists\nmicroscopy\nmicrosecond\nmicroseconds\nmicroseism\nmicroseismic\nmicroseismicities\nmicroseismicity\nmicroseisms\nmicrosomal\nmicrosome\nmicrosomes\nmicrospectrophotometer\nmicrospectrophotometers\nmicrospectrophotometric\nmicrospectrophotometries\nmicrospectrophotometry\nmicrosphere\nmicrospheres\nmicrospherical\nmicrosporangia\nmicrosporangiate\nmicrosporangium\nmicrospore\nmicrospores\nmicrosporocyte\nmicrosporocytes\nmicrosporogeneses\nmicrosporogenesis\nmicrosporophyll\nmicrosporophylls\nmicrosporous\nmicrostate\nmicrostates\nmicrostructural\nmicrostructure\nmicrostructures\nmicrosurgeries\nmicrosurgery\nmicrosurgical\nmicroswitch\nmicroswitches\nmicrotechnic\nmicrotechnics\nmicrotechnique\nmicrotechniques\nmicrotome\nmicrotomes\nmicrotonal\nmicrotonalities\nmicrotonality\nmicrotonally\nmicrotone\nmicrotones\nmicrotubular\nmicrotubule\nmicrotubules\nmicrovascular\nmicrovasculature\nmicrovasculatures\nmicrovillar\nmicrovilli\nmicrovillous\nmicrovillus\nmicrovolt\nmicrovolts\nmicrowatt\nmicrowatts\nmicrowavable\nmicrowave\nmicrowaveable\nmicrowaved\nmicrowaves\nmicrowaving\nmicroworld\nmicroworlds\nmicrurgies\nmicrurgy\nmicturate\nmicturated\nmicturates\nmicturating\nmicturition\nmicturitions\nmid\nmidafternoon\nmidafternoons\nmidair\nmidairs\nmidbrain\nmidbrains\nmidcourse\nmidcult\nmidcults\nmidday\nmiddays\nmidden\nmiddens\nmiddies\nmiddle\nmiddlebrow\nmiddlebrows\nmiddled\nmiddleman\nmiddlemen\nmiddler\nmiddlers\nmiddles\nmiddleweight\nmiddleweights\nmiddling\nmiddlingly\nmiddlings\nmiddorsal\nmiddy\nmidfield\nmidfielder\nmidfielders\nmidfields\nmidge\nmidges\nmidget\nmidgets\nmidgut\nmidguts\nmidi\nmidiron\nmidirons\nmidis\nmidland\nmidlands\nmidlatitude\nmidlatitudes\nmidleg\nmidlegs\nmidlife\nmidline\nmidlines\nmidlives\nmidmonth\nmidmonths\nmidmorning\nmidmornings\nmidmost\nmidmosts\nmidnight\nmidnightly\nmidnights\nmidnoon\nmidnoons\nmidpoint\nmidpoints\nmidrange\nmidranges\nmidrash\nmidrashic\nmidrashim\nmidrashot\nmidrashoth\nmidrib\nmidribs\nmidriff\nmidriffs\nmids\nmidsagittal\nmidsection\nmidsections\nmidship\nmidshipman\nmidshipmen\nmidships\nmidsize\nmidsized\nmidsole\nmidsoles\nmidspace\nmidspaces\nmidst\nmidstories\nmidstory\nmidstream\nmidstreams\nmidsts\nmidsummer\nmidsummers\nmidterm\nmidterms\nmidtown\nmidtowns\nmidwatch\nmidwatches\nmidway\nmidways\nmidweek\nmidweekly\nmidweeks\nmidwestern\nmidwife\nmidwifed\nmidwiferies\nmidwifery\nmidwifes\nmidwifing\nmidwinter\nmidwinters\nmidwived\nmidwives\nmidwiving\nmidyear\nmidyears\nmien\nmiens\nmifepristone\nmifepristones\nmiff\nmiffed\nmiffier\nmiffiest\nmiffing\nmiffs\nmiffy\nmig\nmigg\nmiggle\nmiggles\nmiggs\nmight\nmightier\nmightiest\nmightily\nmightiness\nmightinesses\nmights\nmighty\nmignon\nmignonette\nmignonettes\nmignonne\nmignons\nmigraine\nmigraines\nmigrainous\nmigrant\nmigrants\nmigrate\nmigrated\nmigrates\nmigrating\nmigration\nmigrational\nmigrations\nmigrator\nmigrators\nmigratory\nmigs\nmihrab\nmihrabs\nmijnheer\nmijnheers\nmikado\nmikados\nmike\nmiked\nmikes\nmiking\nmikra\nmikron\nmikrons\nmikvah\nmikvahs\nmikveh\nmikvehs\nmikvos\nmikvot\nmikvoth\nmil\nmiladi\nmiladies\nmiladis\nmilady\nmilage\nmilages\nmilch\nmilchig\nmild\nmilden\nmildened\nmildening\nmildens\nmilder\nmildest\nmildew\nmildewed\nmildewing\nmildews\nmildewy\nmildly\nmildness\nmildnesses\nmile\nmileage\nmileages\nmilepost\nmileposts\nmiler\nmilers\nmiles\nmilesimo\nmilesimos\nmilestone\nmilestones\nmilfoil\nmilfoils\nmilia\nmiliaria\nmiliarial\nmiliarias\nmiliary\nmilieu\nmilieus\nmilieux\nmilitance\nmilitances\nmilitancies\nmilitancy\nmilitant\nmilitantly\nmilitantness\nmilitantnesses\nmilitants\nmilitaria\nmilitaries\nmilitarily\nmilitarise\nmilitarised\nmilitarises\nmilitarising\nmilitarism\nmilitarisms\nmilitarist\nmilitaristic\nmilitaristically\nmilitarists\nmilitarization\nmilitarizations\nmilitarize\nmilitarized\nmilitarizes\nmilitarizing\nmilitary\nmilitate\nmilitated\nmilitates\nmilitating\nmilitia\nmilitiaman\nmilitiamen\nmilitias\nmilium\nmilk\nmilked\nmilker\nmilkers\nmilkfish\nmilkfishes\nmilkier\nmilkiest\nmilkily\nmilkiness\nmilkinesses\nmilking\nmilkmaid\nmilkmaids\nmilkman\nmilkmen\nmilks\nmilkshake\nmilkshakes\nmilkshed\nmilksheds\nmilksop\nmilksops\nmilkweed\nmilkweeds\nmilkwood\nmilkwoods\nmilkwort\nmilkworts\nmilky\nmill\nmillable\nmillage\nmillages\nmillcake\nmillcakes\nmilldam\nmilldams\nmille\nmilled\nmillefiori\nmillefioris\nmillefleur\nmillefleurs\nmillenarian\nmillenarianism\nmillenarianisms\nmillenarians\nmillenaries\nmillenary\nmillennia\nmillennial\nmillennialism\nmillennialisms\nmillennialist\nmillennialists\nmillennium\nmillenniums\nmilleped\nmillepeds\nmiller\nmillerite\nmillerites\nmillers\nmilles\nmillesimal\nmillesimally\nmillesimals\nmillet\nmillets\nmilliampere\nmilliamperes\nmilliard\nmilliards\nmilliare\nmilliares\nmilliaries\nmilliary\nmillibar\nmillibars\nmillicurie\nmillicuries\nmillidegree\nmillidegrees\nmillieme\nmilliemes\nmillier\nmilliers\nmilligal\nmilligals\nmilligram\nmilligrams\nmillihenries\nmillihenry\nmillihenrys\nmillilambert\nmillilamberts\nmilliliter\nmilliliters\nmilliluces\nmillilux\nmilliluxes\nmillime\nmillimes\nmillimeter\nmillimeters\nmillimho\nmillimhos\nmillimicron\nmillimicrons\nmillimolar\nmillimole\nmillimoles\nmilline\nmilliner\nmillineries\nmilliners\nmillinery\nmillines\nmilling\nmillings\nmilliohm\nmilliohms\nmillion\nmillionaire\nmillionaires\nmillionairess\nmillionairesses\nmillionfold\nmillions\nmillionth\nmillionths\nmilliosmol\nmilliosmols\nmilliped\nmillipede\nmillipedes\nmillipeds\nmilliradian\nmilliradians\nmillirem\nmillirems\nmilliroentgen\nmilliroentgens\nmillisecond\nmilliseconds\nmillivolt\nmillivolts\nmilliwatt\nmilliwatts\nmillpond\nmillponds\nmillrace\nmillraces\nmillrun\nmillruns\nmills\nmillstone\nmillstones\nmillstream\nmillstreams\nmillwork\nmillworks\nmillwright\nmillwrights\nmilneb\nmilnebs\nmilo\nmilord\nmilords\nmilos\nmilpa\nmilpas\nmilquetoast\nmilquetoasts\nmilreis\nmils\nmilt\nmilted\nmilter\nmilters\nmiltier\nmiltiest\nmilting\nmilts\nmilty\nmim\nmimbar\nmimbars\nmime\nmimed\nmimeo\nmimeoed\nmimeograph\nmimeographed\nmimeographing\nmimeographs\nmimeoing\nmimeos\nmimer\nmimers\nmimes\nmimeses\nmimesis\nmimesises\nmimetic\nmimetically\nmimetite\nmimetites\nmimic\nmimical\nmimicked\nmimicker\nmimickers\nmimicking\nmimicries\nmimicry\nmimics\nmiming\nmimosa\nmimosas\nmina\nminable\nminacities\nminacity\nminae\nminaret\nminarets\nminas\nminatory\nminaudiere\nminaudieres\nmince\nminced\nmincemeat\nmincemeats\nmincer\nmincers\nminces\nmincier\nminciest\nmincing\nmincingly\nmincy\nmind\nmindblower\nmindblowers\nminded\nmindedness\nmindednesses\nminder\nminders\nmindful\nmindfully\nmindfulness\nmindfulnesses\nminding\nmindless\nmindlessly\nmindlessness\nmindlessnesses\nminds\nmindset\nmindsets\nmine\nmineable\nmined\nminefield\nminefields\nminelayer\nminelayers\nminer\nmineral\nmineralise\nmineralised\nmineralises\nmineralising\nmineralizable\nmineralization\nmineralizations\nmineralize\nmineralized\nmineralizer\nmineralizers\nmineralizes\nmineralizing\nmineralocorticoid\nmineralocorticoids\nmineralogic\nmineralogical\nmineralogically\nmineralogies\nmineralogist\nmineralogists\nmineralogy\nminerals\nminers\nmines\nminestrone\nminestrones\nminesweeper\nminesweepers\nminesweeping\nminesweepings\nmingier\nmingiest\nmingle\nmingled\nmingler\nminglers\nmingles\nmingling\nmingy\nmini\nminiature\nminiatures\nminiaturist\nminiaturistic\nminiaturists\nminiaturization\nminiaturizations\nminiaturize\nminiaturized\nminiaturizes\nminiaturizing\nminibar\nminibars\nminibike\nminibiker\nminibikers\nminibikes\nminibus\nminibuses\nminibusses\nminicab\nminicabs\nminicam\nminicamp\nminicamps\nminicams\nminicar\nminicars\nminicomputer\nminicomputers\nminicourse\nminicourses\nminified\nminifies\nminify\nminifying\nminikin\nminikins\nminilab\nminilabs\nminim\nminima\nminimal\nminimalism\nminimalisms\nminimalist\nminimalists\nminimally\nminimals\nminimax\nminimaxes\nminimill\nminimills\nminimise\nminimised\nminimises\nminimising\nminimization\nminimizations\nminimize\nminimized\nminimizer\nminimizers\nminimizes\nminimizing\nminims\nminimum\nminimums\nmining\nminings\nminion\nminions\nminipark\nminiparks\nminis\nminischool\nminischools\nminiscule\nminiscules\nminiseries\nminish\nminished\nminishes\nminishing\nminiski\nminiskirt\nminiskirted\nminiskirts\nminiskis\nministate\nministates\nminister\nministered\nministerial\nministerially\nministering\nministers\nministrant\nministrants\nministration\nministrations\nministries\nministroke\nministrokes\nministry\nminium\nminiums\nminivan\nminivans\nminiver\nminivers\nmink\nminke\nminkes\nminks\nminnesinger\nminnesingers\nminnies\nminnow\nminnows\nminny\nminor\nminorca\nminorcas\nminored\nminoring\nminorities\nminority\nminors\nminoxidil\nminoxidils\nminster\nminsters\nminstrel\nminstrels\nminstrelsies\nminstrelsy\nmint\nmintage\nmintages\nminted\nminter\nminters\nmintier\nmintiest\nminting\nmints\nminty\nminuend\nminuends\nminuet\nminuets\nminus\nminuscule\nminuscules\nminuses\nminute\nminuted\nminutely\nminuteman\nminutemen\nminuteness\nminutenesses\nminuter\nminutes\nminutest\nminutia\nminutiae\nminutial\nminuting\nminx\nminxes\nminxish\nminyan\nminyanim\nminyans\nmioses\nmiosis\nmiotic\nmiotics\nmiquelet\nmiquelets\nmir\nmiracidia\nmiracidial\nmiracidium\nmiracle\nmiracles\nmiraculous\nmiraculously\nmiraculousness\nmiraculousnesses\nmirador\nmiradors\nmirage\nmirages\nmire\nmired\nmires\nmirex\nmirexes\nmiri\nmirier\nmiriest\nmiriness\nmirinesses\nmiring\nmirk\nmirker\nmirkest\nmirkier\nmirkiest\nmirkily\nmirks\nmirky\nmirliton\nmirlitons\nmirror\nmirrored\nmirroring\nmirrorlike\nmirrors\nmirs\nmirth\nmirthful\nmirthfully\nmirthfulness\nmirthfulnesses\nmirthless\nmirthlessly\nmirths\nmiry\nmirza\nmirzas\nmis\nmisact\nmisacted\nmisacting\nmisacts\nmisadapt\nmisadapted\nmisadapting\nmisadapts\nmisadd\nmisadded\nmisadding\nmisaddress\nmisaddressed\nmisaddresses\nmisaddressing\nmisadds\nmisadjust\nmisadjusted\nmisadjusting\nmisadjusts\nmisadministration\nmisadministrations\nmisadventure\nmisadventures\nmisadvise\nmisadvised\nmisadvises\nmisadvising\nmisagent\nmisagents\nmisaim\nmisaimed\nmisaiming\nmisaims\nmisalign\nmisaligned\nmisaligning\nmisalignment\nmisalignments\nmisaligns\nmisalliance\nmisalliances\nmisallied\nmisallies\nmisallocate\nmisallocated\nmisallocates\nmisallocating\nmisallocation\nmisallocations\nmisally\nmisallying\nmisalter\nmisaltered\nmisaltering\nmisalters\nmisanalyses\nmisanalysis\nmisandries\nmisandry\nmisanthrope\nmisanthropes\nmisanthropic\nmisanthropically\nmisanthropies\nmisanthropy\nmisapplication\nmisapplications\nmisapplied\nmisapplies\nmisapply\nmisapplying\nmisappraisal\nmisappraisals\nmisapprehend\nmisapprehended\nmisapprehending\nmisapprehends\nmisapprehension\nmisapprehensions\nmisappropriate\nmisappropriated\nmisappropriates\nmisappropriating\nmisappropriation\nmisappropriations\nmisarticulate\nmisarticulated\nmisarticulates\nmisarticulating\nmisassay\nmisassayed\nmisassaying\nmisassays\nmisassemble\nmisassembled\nmisassembles\nmisassembling\nmisassumption\nmisassumptions\nmisate\nmisatone\nmisatoned\nmisatones\nmisatoning\nmisattribute\nmisattributed\nmisattributes\nmisattributing\nmisattribution\nmisattributions\nmisaver\nmisaverred\nmisaverring\nmisavers\nmisaward\nmisawarded\nmisawarding\nmisawards\nmisbalance\nmisbalanced\nmisbalances\nmisbalancing\nmisbecame\nmisbecome\nmisbecomes\nmisbecoming\nmisbegan\nmisbegin\nmisbeginning\nmisbegins\nmisbegot\nmisbegotten\nmisbegun\nmisbehave\nmisbehaved\nmisbehaver\nmisbehavers\nmisbehaves\nmisbehaving\nmisbehavior\nmisbehaviors\nmisbelief\nmisbeliefs\nmisbelieve\nmisbelieved\nmisbeliever\nmisbelievers\nmisbelieves\nmisbelieving\nmisbias\nmisbiased\nmisbiases\nmisbiasing\nmisbiassed\nmisbiasses\nmisbiassing\nmisbill\nmisbilled\nmisbilling\nmisbills\nmisbind\nmisbinding\nmisbinds\nmisbound\nmisbrand\nmisbranded\nmisbranding\nmisbrands\nmisbuild\nmisbuilding\nmisbuilds\nmisbuilt\nmisbutton\nmisbuttoned\nmisbuttoning\nmisbuttons\nmiscalculate\nmiscalculated\nmiscalculates\nmiscalculating\nmiscalculation\nmiscalculations\nmiscall\nmiscalled\nmiscalling\nmiscalls\nmiscaption\nmiscaptioned\nmiscaptioning\nmiscaptions\nmiscarriage\nmiscarriages\nmiscarried\nmiscarries\nmiscarry\nmiscarrying\nmiscast\nmiscasting\nmiscasts\nmiscatalog\nmiscataloged\nmiscataloging\nmiscatalogs\nmiscegenation\nmiscegenational\nmiscegenations\nmiscellanea\nmiscellaneous\nmiscellaneously\nmiscellaneousness\nmiscellaneousnesses\nmiscellanies\nmiscellanist\nmiscellanists\nmiscellany\nmischance\nmischances\nmischannel\nmischanneled\nmischanneling\nmischannelled\nmischannelling\nmischannels\nmischaracterization\nmischaracterizations\nmischaracterize\nmischaracterized\nmischaracterizes\nmischaracterizing\nmischarge\nmischarged\nmischarges\nmischarging\nmischief\nmischiefs\nmischievous\nmischievously\nmischievousness\nmischievousnesses\nmischoice\nmischoices\nmiscibilities\nmiscibility\nmiscible\nmiscitation\nmiscitations\nmiscite\nmiscited\nmiscites\nmisciting\nmisclaim\nmisclaimed\nmisclaiming\nmisclaims\nmisclass\nmisclassed\nmisclasses\nmisclassification\nmisclassifications\nmisclassified\nmisclassifies\nmisclassify\nmisclassifying\nmisclassing\nmiscode\nmiscoded\nmiscodes\nmiscoding\nmiscoin\nmiscoined\nmiscoining\nmiscoins\nmiscolor\nmiscolored\nmiscoloring\nmiscolors\nmiscommunication\nmiscommunications\nmiscomprehension\nmiscomprehensions\nmiscomputation\nmiscomputations\nmiscompute\nmiscomputed\nmiscomputes\nmiscomputing\nmisconceive\nmisconceived\nmisconceiver\nmisconceivers\nmisconceives\nmisconceiving\nmisconception\nmisconceptions\nmisconduct\nmisconducted\nmisconducting\nmisconducts\nmisconnect\nmisconnected\nmisconnecting\nmisconnection\nmisconnections\nmisconnects\nmisconstruction\nmisconstructions\nmisconstrue\nmisconstrued\nmisconstrues\nmisconstruing\nmiscook\nmiscooked\nmiscooking\nmiscooks\nmiscopied\nmiscopies\nmiscopy\nmiscopying\nmiscorrelation\nmiscorrelations\nmiscount\nmiscounted\nmiscounting\nmiscounts\nmiscreant\nmiscreants\nmiscreate\nmiscreated\nmiscreates\nmiscreating\nmiscreation\nmiscreations\nmiscue\nmiscued\nmiscues\nmiscuing\nmiscut\nmiscuts\nmiscutting\nmisdate\nmisdated\nmisdates\nmisdating\nmisdeal\nmisdealing\nmisdeals\nmisdealt\nmisdeed\nmisdeeds\nmisdeem\nmisdeemed\nmisdeeming\nmisdeems\nmisdefine\nmisdefined\nmisdefines\nmisdefining\nmisdemeanant\nmisdemeanants\nmisdemeanor\nmisdemeanors\nmisdescribe\nmisdescribed\nmisdescribes\nmisdescribing\nmisdescription\nmisdescriptions\nmisdevelop\nmisdeveloped\nmisdeveloping\nmisdevelops\nmisdiagnose\nmisdiagnosed\nmisdiagnoses\nmisdiagnosing\nmisdiagnosis\nmisdial\nmisdialed\nmisdialing\nmisdialled\nmisdialling\nmisdials\nmisdid\nmisdirect\nmisdirected\nmisdirecting\nmisdirection\nmisdirections\nmisdirects\nmisdistribution\nmisdistributions\nmisdivision\nmisdivisions\nmisdo\nmisdoer\nmisdoers\nmisdoes\nmisdoing\nmisdoings\nmisdone\nmisdoubt\nmisdoubted\nmisdoubting\nmisdoubts\nmisdraw\nmisdrawing\nmisdrawn\nmisdraws\nmisdrew\nmisdrive\nmisdriven\nmisdrives\nmisdriving\nmisdrove\nmise\nmisease\nmiseases\nmiseat\nmiseaten\nmiseating\nmiseats\nmisedit\nmisedited\nmisediting\nmisedits\nmiseducate\nmiseducated\nmiseducates\nmiseducating\nmiseducation\nmiseducations\nmisemphases\nmisemphasis\nmisemphasize\nmisemphasized\nmisemphasizes\nmisemphasizing\nmisemploy\nmisemployed\nmisemploying\nmisemployment\nmisemployments\nmisemploys\nmisenrol\nmisenroll\nmisenrolled\nmisenrolling\nmisenrolls\nmisenrols\nmisenter\nmisentered\nmisentering\nmisenters\nmisentries\nmisentry\nmiser\nmiserable\nmiserableness\nmiserablenesses\nmiserables\nmiserably\nmiserere\nmisereres\nmisericord\nmisericorde\nmisericordes\nmisericords\nmiseries\nmiserliness\nmiserlinesses\nmiserly\nmisers\nmisery\nmises\nmisesteem\nmisesteemed\nmisesteeming\nmisesteems\nmisestimate\nmisestimated\nmisestimates\nmisestimating\nmisestimation\nmisestimations\nmisevaluate\nmisevaluated\nmisevaluates\nmisevaluating\nmisevaluation\nmisevaluations\nmisevent\nmisevents\nmisfaith\nmisfaiths\nmisfeasance\nmisfeasances\nmisfeasor\nmisfeasors\nmisfield\nmisfielded\nmisfielding\nmisfields\nmisfile\nmisfiled\nmisfiles\nmisfiling\nmisfire\nmisfired\nmisfires\nmisfiring\nmisfit\nmisfits\nmisfitted\nmisfitting\nmisfocus\nmisfocused\nmisfocuses\nmisfocusing\nmisfocussed\nmisfocusses\nmisfocussing\nmisform\nmisformed\nmisforming\nmisforms\nmisfortune\nmisfortunes\nmisframe\nmisframed\nmisframes\nmisframing\nmisfunction\nmisfunctioned\nmisfunctioning\nmisfunctions\nmisgauge\nmisgauged\nmisgauges\nmisgauging\nmisgave\nmisgive\nmisgiven\nmisgives\nmisgiving\nmisgivings\nmisgovern\nmisgoverned\nmisgoverning\nmisgovernment\nmisgovernments\nmisgoverns\nmisgrade\nmisgraded\nmisgrades\nmisgrading\nmisgraft\nmisgrafted\nmisgrafting\nmisgrafts\nmisgrew\nmisgrow\nmisgrowing\nmisgrown\nmisgrows\nmisguess\nmisguessed\nmisguesses\nmisguessing\nmisguidance\nmisguidances\nmisguide\nmisguided\nmisguidedly\nmisguidedness\nmisguidednesses\nmisguider\nmisguiders\nmisguides\nmisguiding\nmishandle\nmishandled\nmishandles\nmishandling\nmishanter\nmishanters\nmishap\nmishaps\nmishear\nmisheard\nmishearing\nmishears\nmishit\nmishits\nmishitting\nmishmash\nmishmashes\nmishmosh\nmishmoshes\nmisidentification\nmisidentifications\nmisidentified\nmisidentifies\nmisidentify\nmisidentifying\nmisimpression\nmisimpressions\nmisinfer\nmisinferred\nmisinferring\nmisinfers\nmisinform\nmisinformation\nmisinformations\nmisinformed\nmisinforming\nmisinforms\nmisinter\nmisinterpret\nmisinterpretation\nmisinterpretations\nmisinterpreted\nmisinterpreting\nmisinterprets\nmisinterred\nmisinterring\nmisinters\nmisjoin\nmisjoinder\nmisjoinders\nmisjoined\nmisjoining\nmisjoins\nmisjudge\nmisjudged\nmisjudges\nmisjudging\nmisjudgment\nmisjudgments\nmiskal\nmiskals\nmiskeep\nmiskeeping\nmiskeeps\nmiskept\nmiskick\nmiskicked\nmiskicking\nmiskicks\nmisknew\nmisknow\nmisknowing\nmisknowledge\nmisknowledges\nmisknown\nmisknows\nmislabel\nmislabeled\nmislabeling\nmislabelled\nmislabelling\nmislabels\nmislabor\nmislabored\nmislaboring\nmislabors\nmislaid\nmislain\nmislay\nmislayer\nmislayers\nmislaying\nmislays\nmislead\nmisleader\nmisleaders\nmisleading\nmisleadingly\nmisleads\nmisleared\nmislearn\nmislearned\nmislearning\nmislearns\nmislearnt\nmisled\nmislie\nmislies\nmislight\nmislighted\nmislighting\nmislights\nmislike\nmisliked\nmisliker\nmislikers\nmislikes\nmisliking\nmislit\nmislive\nmislived\nmislives\nmisliving\nmislocate\nmislocated\nmislocates\nmislocating\nmislocation\nmislocations\nmislodge\nmislodged\nmislodges\nmislodging\nmislying\nmismade\nmismake\nmismakes\nmismaking\nmismanage\nmismanaged\nmismanagement\nmismanagements\nmismanages\nmismanaging\nmismark\nmismarked\nmismarking\nmismarks\nmismarriage\nmismarriages\nmismatch\nmismatched\nmismatches\nmismatching\nmismate\nmismated\nmismates\nmismating\nmismeasurement\nmismeasurements\nmismeet\nmismeeting\nmismeets\nmismet\nmismove\nmismoved\nmismoves\nmismoving\nmisname\nmisnamed\nmisnames\nmisnaming\nmisnomer\nmisnomered\nmisnomers\nmiso\nmisogamies\nmisogamist\nmisogamists\nmisogamy\nmisogynic\nmisogynies\nmisogynist\nmisogynistic\nmisogynists\nmisogyny\nmisologies\nmisology\nmisoneism\nmisoneisms\nmisorder\nmisordered\nmisordering\nmisorders\nmisorient\nmisorientation\nmisorientations\nmisoriented\nmisorienting\nmisorients\nmisos\nmispackage\nmispackaged\nmispackages\nmispackaging\nmispage\nmispaged\nmispages\nmispaging\nmispaint\nmispainted\nmispainting\nmispaints\nmisparse\nmisparsed\nmisparses\nmisparsing\nmispart\nmisparted\nmisparting\nmisparts\nmispatch\nmispatched\nmispatches\nmispatching\nmispen\nmispenned\nmispenning\nmispens\nmisperceive\nmisperceived\nmisperceives\nmisperceiving\nmisperception\nmisperceptions\nmisphrase\nmisphrased\nmisphrases\nmisphrasing\nmisplace\nmisplaced\nmisplacement\nmisplacements\nmisplaces\nmisplacing\nmisplan\nmisplanned\nmisplanning\nmisplans\nmisplant\nmisplanted\nmisplanting\nmisplants\nmisplay\nmisplayed\nmisplaying\nmisplays\nmisplead\nmispleaded\nmispleading\nmispleads\nmispled\nmispoint\nmispointed\nmispointing\nmispoints\nmispoise\nmispoised\nmispoises\nmispoising\nmisposition\nmispositioned\nmispositioning\nmispositions\nmisprice\nmispriced\nmisprices\nmispricing\nmisprint\nmisprinted\nmisprinting\nmisprints\nmisprision\nmisprisions\nmisprize\nmisprized\nmisprizes\nmisprizing\nmisprogram\nmisprogramed\nmisprograming\nmisprogrammed\nmisprogramming\nmisprograms\nmispronounce\nmispronounced\nmispronounces\nmispronouncing\nmispronunciation\nmispronunciations\nmisquotation\nmisquotations\nmisquote\nmisquoted\nmisquotes\nmisquoting\nmisraise\nmisraised\nmisraises\nmisraising\nmisrate\nmisrated\nmisrates\nmisrating\nmisread\nmisreading\nmisreads\nmisreckon\nmisreckoned\nmisreckoning\nmisreckons\nmisrecollection\nmisrecollections\nmisrecord\nmisrecorded\nmisrecording\nmisrecords\nmisrefer\nmisreference\nmisreferences\nmisreferred\nmisreferring\nmisrefers\nmisregister\nmisregistered\nmisregistering\nmisregisters\nmisregistration\nmisregistrations\nmisrelate\nmisrelated\nmisrelates\nmisrelating\nmisrelied\nmisrelies\nmisrely\nmisrelying\nmisremember\nmisremembered\nmisremembering\nmisremembers\nmisrender\nmisrendered\nmisrendering\nmisrenders\nmisreport\nmisreported\nmisreporting\nmisreports\nmisrepresent\nmisrepresentation\nmisrepresentations\nmisrepresentative\nmisrepresented\nmisrepresenting\nmisrepresents\nmisroute\nmisrouted\nmisroutes\nmisrouting\nmisrule\nmisruled\nmisrules\nmisruling\nmiss\nmissable\nmissaid\nmissal\nmissals\nmissay\nmissaying\nmissays\nmisseat\nmisseated\nmisseating\nmisseats\nmissed\nmissel\nmissels\nmissend\nmissending\nmissends\nmissense\nmissenses\nmissent\nmisses\nmisset\nmissets\nmissetting\nmisshape\nmisshaped\nmisshapen\nmisshapenly\nmisshapes\nmisshaping\nmisshod\nmissies\nmissile\nmissileer\nmissileers\nmissileman\nmissilemen\nmissileries\nmissilery\nmissiles\nmissilries\nmissilry\nmissing\nmissiologies\nmissiology\nmission\nmissionaries\nmissionary\nmissioned\nmissioner\nmissioners\nmissioning\nmissionization\nmissionizations\nmissionize\nmissionized\nmissionizer\nmissionizers\nmissionizes\nmissionizing\nmissions\nmissis\nmissises\nmissive\nmissives\nmissort\nmissorted\nmissorting\nmissorts\nmissound\nmissounded\nmissounding\nmissounds\nmissout\nmissouts\nmisspace\nmisspaced\nmisspaces\nmisspacing\nmisspeak\nmisspeaking\nmisspeaks\nmisspell\nmisspelled\nmisspelling\nmisspellings\nmisspells\nmisspelt\nmisspend\nmisspending\nmisspends\nmisspent\nmisspoke\nmisspoken\nmisstart\nmisstarted\nmisstarting\nmisstarts\nmisstate\nmisstated\nmisstatement\nmisstatements\nmisstates\nmisstating\nmissteer\nmissteered\nmissteering\nmissteers\nmisstep\nmissteps\nmisstop\nmisstopped\nmisstopping\nmisstops\nmisstricken\nmisstrike\nmisstrikes\nmisstriking\nmisstruck\nmisstyle\nmisstyled\nmisstyles\nmisstyling\nmissuit\nmissuited\nmissuiting\nmissuits\nmissus\nmissuses\nmissy\nmist\nmistakable\nmistake\nmistaken\nmistakenly\nmistaker\nmistakers\nmistakes\nmistaking\nmistaught\nmistbow\nmistbows\nmisteach\nmisteaches\nmisteaching\nmisted\nmistend\nmistended\nmistending\nmistends\nmister\nmisterm\nmistermed\nmisterming\nmisterms\nmisters\nmisteuk\nmisthink\nmisthinking\nmisthinks\nmisthought\nmisthrew\nmisthrow\nmisthrowing\nmisthrown\nmisthrows\nmistier\nmistiest\nmistily\nmistime\nmistimed\nmistimes\nmistiming\nmistiness\nmistinesses\nmisting\nmistitle\nmistitled\nmistitles\nmistitling\nmistletoe\nmistletoes\nmistook\nmistouch\nmistouched\nmistouches\nmistouching\nmistrace\nmistraced\nmistraces\nmistracing\nmistrain\nmistrained\nmistraining\nmistrains\nmistral\nmistrals\nmistranscribe\nmistranscribed\nmistranscribes\nmistranscribing\nmistranscription\nmistranscriptions\nmistranslate\nmistranslated\nmistranslates\nmistranslating\nmistranslation\nmistranslations\nmistreat\nmistreated\nmistreating\nmistreatment\nmistreatments\nmistreats\nmistress\nmistresses\nmistrial\nmistrials\nmistrust\nmistrusted\nmistrustful\nmistrustfully\nmistrustfulness\nmistrustfulnesses\nmistrusting\nmistrusts\nmistruth\nmistruths\nmistryst\nmistrysted\nmistrysting\nmistrysts\nmists\nmistune\nmistuned\nmistunes\nmistuning\nmistutor\nmistutored\nmistutoring\nmistutors\nmisty\nmistype\nmistyped\nmistypes\nmistyping\nmisunderstand\nmisunderstanding\nmisunderstandings\nmisunderstands\nmisunderstood\nmisunion\nmisunions\nmisusage\nmisusages\nmisuse\nmisused\nmisuser\nmisusers\nmisuses\nmisusing\nmisutilization\nmisutilizations\nmisvalue\nmisvalued\nmisvalues\nmisvaluing\nmisvocalization\nmisvocalizations\nmisword\nmisworded\nmiswording\nmiswords\nmiswrit\nmiswrite\nmiswrites\nmiswriting\nmiswritten\nmiswrote\nmisyoke\nmisyoked\nmisyokes\nmisyoking\nmite\nmiter\nmitered\nmiterer\nmiterers\nmitering\nmiters\nmiterwort\nmiterworts\nmites\nmither\nmithers\nmithridate\nmithridates\nmiticidal\nmiticide\nmiticides\nmitier\nmitiest\nmitigate\nmitigated\nmitigates\nmitigating\nmitigation\nmitigations\nmitigative\nmitigator\nmitigators\nmitigatory\nmitis\nmitises\nmitochondria\nmitochondrial\nmitochondrion\nmitogen\nmitogenic\nmitogenicities\nmitogenicity\nmitogens\nmitomycin\nmitomycins\nmitoses\nmitosis\nmitotic\nmitotically\nmitral\nmitre\nmitred\nmitres\nmitrewort\nmitreworts\nmitring\nmitsvah\nmitsvahs\nmitsvoth\nmitt\nmitten\nmittens\nmittimus\nmittimuses\nmitts\nmity\nmitzvah\nmitzvahs\nmitzvoth\nmix\nmixable\nmixed\nmixer\nmixers\nmixes\nmixible\nmixing\nmixologies\nmixologist\nmixologists\nmixology\nmixt\nmixture\nmixtures\nmixup\nmixups\nmizen\nmizens\nmizzen\nmizzenmast\nmizzenmasts\nmizzens\nmizzle\nmizzled\nmizzles\nmizzling\nmizzly\nmm\nmnemonic\nmnemonically\nmnemonics\nmo\nmoa\nmoan\nmoaned\nmoaner\nmoaners\nmoanful\nmoaning\nmoans\nmoas\nmoat\nmoated\nmoating\nmoatlike\nmoats\nmob\nmobbed\nmobber\nmobbers\nmobbing\nmobbish\nmobcap\nmobcaps\nmobile\nmobiles\nmobilise\nmobilised\nmobilises\nmobilising\nmobilities\nmobility\nmobilization\nmobilizations\nmobilize\nmobilized\nmobilizes\nmobilizing\nmobled\nmobocracies\nmobocracy\nmobocrat\nmobocratic\nmobocrats\nmobs\nmobster\nmobsters\nmoc\nmoccasin\nmoccasins\nmocha\nmochas\nmochila\nmochilas\nmock\nmockable\nmocked\nmocker\nmockeries\nmockers\nmockery\nmocking\nmockingbird\nmockingbirds\nmockingly\nmocks\nmockup\nmockups\nmocs\nmod\nmodal\nmodalities\nmodality\nmodally\nmode\nmodel\nmodeled\nmodeler\nmodelers\nmodeling\nmodelings\nmodelist\nmodelists\nmodelled\nmodeller\nmodellers\nmodelling\nmodels\nmodem\nmodems\nmoderate\nmoderated\nmoderately\nmoderateness\nmoderatenesses\nmoderates\nmoderating\nmoderation\nmoderations\nmoderato\nmoderator\nmoderators\nmoderatorship\nmoderatorships\nmoderatos\nmodern\nmoderne\nmoderner\nmodernes\nmodernest\nmodernisation\nmodernisations\nmodernise\nmodernised\nmodernises\nmodernising\nmodernism\nmodernisms\nmodernist\nmodernistic\nmodernists\nmodernities\nmodernity\nmodernization\nmodernizations\nmodernize\nmodernized\nmodernizer\nmodernizers\nmodernizes\nmodernizing\nmodernly\nmodernness\nmodernnesses\nmoderns\nmodes\nmodest\nmodester\nmodestest\nmodesties\nmodestly\nmodesty\nmodi\nmodica\nmodicum\nmodicums\nmodifiabilities\nmodifiability\nmodifiable\nmodification\nmodifications\nmodified\nmodifier\nmodifiers\nmodifies\nmodify\nmodifying\nmodillion\nmodillions\nmodioli\nmodiolus\nmodish\nmodishly\nmodishness\nmodishnesses\nmodiste\nmodistes\nmods\nmodulabilities\nmodulability\nmodular\nmodularities\nmodularity\nmodularized\nmodularly\nmodulate\nmodulated\nmodulates\nmodulating\nmodulation\nmodulations\nmodulator\nmodulators\nmodulatory\nmodule\nmodules\nmoduli\nmodulo\nmodulus\nmodus\nmofette\nmofettes\nmoffette\nmoffettes\nmog\nmogged\nmoggie\nmoggies\nmogging\nmoggy\nmogs\nmogul\nmoguls\nmohair\nmohairs\nmohalim\nmohel\nmohelim\nmohels\nmohur\nmohurs\nmoidore\nmoidores\nmoieties\nmoiety\nmoil\nmoiled\nmoiler\nmoilers\nmoiling\nmoilingly\nmoils\nmoira\nmoirai\nmoire\nmoires\nmoist\nmoisten\nmoistened\nmoistener\nmoisteners\nmoistening\nmoistens\nmoister\nmoistest\nmoistful\nmoistly\nmoistness\nmoistnesses\nmoisture\nmoistures\nmoisturise\nmoisturised\nmoisturises\nmoisturising\nmoisturize\nmoisturized\nmoisturizer\nmoisturizers\nmoisturizes\nmoisturizing\nmojarra\nmojarras\nmojo\nmojoes\nmojos\nmoke\nmokes\nmol\nmola\nmolal\nmolalities\nmolality\nmolar\nmolarities\nmolarity\nmolars\nmolas\nmolasses\nmolasseses\nmold\nmoldable\nmoldboard\nmoldboards\nmolded\nmolder\nmoldered\nmoldering\nmolders\nmoldier\nmoldiest\nmoldiness\nmoldinesses\nmolding\nmoldings\nmolds\nmoldwarp\nmoldwarps\nmoldy\nmole\nmolecular\nmolecularly\nmolecule\nmolecules\nmolehill\nmolehills\nmoles\nmoleskin\nmoleskins\nmolest\nmolestation\nmolestations\nmolested\nmolester\nmolesters\nmolesting\nmolests\nmolies\nmoline\nmoll\nmollah\nmollahs\nmollie\nmollies\nmollification\nmollifications\nmollified\nmollifies\nmollify\nmollifying\nmolls\nmollusc\nmolluscan\nmolluscicidal\nmolluscicide\nmolluscicides\nmolluscs\nmollusk\nmolluskan\nmollusks\nmolly\nmollycoddle\nmollycoddled\nmollycoddler\nmollycoddlers\nmollycoddles\nmollycoddling\nmoloch\nmolochs\nmols\nmolt\nmolted\nmolten\nmoltenly\nmolter\nmolters\nmolting\nmolto\nmolts\nmoly\nmolybdate\nmolybdates\nmolybdenite\nmolybdenites\nmolybdenum\nmolybdenums\nmolybdic\nmom\nmome\nmoment\nmomenta\nmomentarily\nmomentariness\nmomentarinesses\nmomentary\nmomently\nmomento\nmomentoes\nmomentos\nmomentous\nmomentously\nmomentousness\nmomentousnesses\nmoments\nmomentum\nmomentums\nmomes\nmomi\nmomism\nmomisms\nmomma\nmommas\nmommies\nmommy\nmoms\nmomser\nmomsers\nmomus\nmomuses\nmomzer\nmomzers\nmon\nmonachal\nmonachism\nmonachisms\nmonacid\nmonacids\nmonad\nmonadal\nmonadelphous\nmonades\nmonadic\nmonadism\nmonadisms\nmonadnock\nmonadnocks\nmonads\nmonandries\nmonandry\nmonarch\nmonarchal\nmonarchial\nmonarchic\nmonarchical\nmonarchically\nmonarchies\nmonarchism\nmonarchisms\nmonarchist\nmonarchists\nmonarchs\nmonarchy\nmonarda\nmonardas\nmonas\nmonasteries\nmonastery\nmonastic\nmonastically\nmonasticism\nmonasticisms\nmonastics\nmonatomic\nmonaural\nmonaurally\nmonaxial\nmonaxon\nmonaxons\nmonazite\nmonazites\nmonde\nmondes\nmondo\nmondos\nmonecian\nmonecious\nmonellin\nmonellins\nmoneran\nmonerans\nmonestrous\nmonetarily\nmonetarism\nmonetarisms\nmonetarist\nmonetarists\nmonetary\nmonetise\nmonetised\nmonetises\nmonetising\nmonetization\nmonetizations\nmonetize\nmonetized\nmonetizes\nmonetizing\nmoney\nmoneybag\nmoneybags\nmoneyed\nmoneyer\nmoneyers\nmoneygrubbing\nmoneygrubbings\nmoneylender\nmoneylenders\nmoneymaker\nmoneymakers\nmoneymaking\nmoneymakings\nmoneyman\nmoneymen\nmoneys\nmoneywort\nmoneyworts\nmongeese\nmonger\nmongered\nmongering\nmongers\nmongo\nmongoe\nmongoes\nmongol\nmongolism\nmongolisms\nmongoloid\nmongoloids\nmongols\nmongoose\nmongooses\nmongos\nmongrel\nmongrelization\nmongrelizations\nmongrelize\nmongrelized\nmongrelizes\nmongrelizing\nmongrels\nmongst\nmonicker\nmonickers\nmonie\nmonied\nmonies\nmoniker\nmonikers\nmoniliases\nmoniliasis\nmoniliform\nmonish\nmonished\nmonishes\nmonishing\nmonism\nmonisms\nmonist\nmonistic\nmonists\nmonition\nmonitions\nmonitive\nmonitor\nmonitored\nmonitorial\nmonitories\nmonitoring\nmonitors\nmonitorship\nmonitorships\nmonitory\nmonk\nmonkeries\nmonkery\nmonkey\nmonkeyed\nmonkeying\nmonkeypod\nmonkeypods\nmonkeys\nmonkeyshine\nmonkeyshines\nmonkfish\nmonkfishes\nmonkhood\nmonkhoods\nmonkish\nmonks\nmonkshood\nmonkshoods\nmono\nmonoacid\nmonoacidic\nmonoacids\nmonoamine\nmonoaminergic\nmonoamines\nmonobasic\nmonocarboxylic\nmonocarp\nmonocarpic\nmonocarps\nmonochasia\nmonochasial\nmonochasium\nmonochord\nmonochords\nmonochromat\nmonochromatic\nmonochromatically\nmonochromaticities\nmonochromaticity\nmonochromatism\nmonochromatisms\nmonochromator\nmonochromators\nmonochromats\nmonochrome\nmonochromes\nmonochromic\nmonochromist\nmonochromists\nmonocle\nmonocled\nmonocles\nmonocline\nmonoclines\nmonoclinic\nmonoclonal\nmonoclonals\nmonocoque\nmonocoques\nmonocot\nmonocots\nmonocotyledon\nmonocotyledonous\nmonocotyledons\nmonocracies\nmonocracy\nmonocrat\nmonocratic\nmonocrats\nmonocrystal\nmonocrystalline\nmonocrystals\nmonocular\nmonocularly\nmonoculars\nmonocultural\nmonoculture\nmonocultures\nmonocyclic\nmonocyte\nmonocytes\nmonocytic\nmonodic\nmonodical\nmonodically\nmonodies\nmonodisperse\nmonodist\nmonodists\nmonodrama\nmonodramas\nmonodramatic\nmonody\nmonoecies\nmonoecious\nmonoecism\nmonoecisms\nmonoecy\nmonoester\nmonoesters\nmonofil\nmonofilament\nmonofilaments\nmonofils\nmonofuel\nmonofuels\nmonogamic\nmonogamies\nmonogamist\nmonogamists\nmonogamous\nmonogamously\nmonogamy\nmonogastric\nmonogenean\nmonogeneans\nmonogeneses\nmonogenesis\nmonogenetic\nmonogenic\nmonogenically\nmonogenies\nmonogeny\nmonogerm\nmonoglot\nmonoglots\nmonoglyceride\nmonoglycerides\nmonogram\nmonogramed\nmonograming\nmonogrammatic\nmonogrammed\nmonogrammer\nmonogrammers\nmonogramming\nmonograms\nmonograph\nmonographed\nmonographic\nmonographing\nmonographs\nmonogynies\nmonogynous\nmonogyny\nmonohull\nmonohulls\nmonohybrid\nmonohybrids\nmonohydric\nmonohydroxy\nmonolayer\nmonolayers\nmonolingual\nmonolinguals\nmonolith\nmonolithic\nmonolithically\nmonoliths\nmonolog\nmonologies\nmonologist\nmonologists\nmonologs\nmonologue\nmonologues\nmonologuist\nmonologuists\nmonology\nmonomania\nmonomaniac\nmonomaniacal\nmonomaniacally\nmonomaniacs\nmonomanias\nmonomer\nmonomeric\nmonomers\nmonometallic\nmonometallism\nmonometallisms\nmonometallist\nmonometallists\nmonometer\nmonometers\nmonomial\nmonomials\nmonomolecular\nmonomolecularly\nmonomorphemic\nmonomorphic\nmonomorphism\nmonomorphisms\nmononuclear\nmononuclears\nmononucleate\nmononucleated\nmononucleoses\nmononucleosis\nmononucleotide\nmononucleotides\nmonophagies\nmonophagous\nmonophagy\nmonophonic\nmonophonically\nmonophonies\nmonophony\nmonophthong\nmonophthongal\nmonophthongs\nmonophyletic\nmonophylies\nmonophyly\nmonoplane\nmonoplanes\nmonoploid\nmonoploids\nmonopode\nmonopodes\nmonopodial\nmonopodially\nmonopodies\nmonopody\nmonopole\nmonopoles\nmonopolies\nmonopolise\nmonopolised\nmonopolises\nmonopolising\nmonopolist\nmonopolistic\nmonopolistically\nmonopolists\nmonopolization\nmonopolizations\nmonopolize\nmonopolized\nmonopolizer\nmonopolizers\nmonopolizes\nmonopolizing\nmonopoly\nmonopropellant\nmonopropellants\nmonopsonies\nmonopsonistic\nmonopsony\nmonorail\nmonorails\nmonorchid\nmonorchidism\nmonorchidisms\nmonorchids\nmonorhyme\nmonorhymed\nmonorhymes\nmonos\nmonosaccharide\nmonosaccharides\nmonosome\nmonosomes\nmonosomic\nmonosomics\nmonosomies\nmonosomy\nmonospecific\nmonospecificities\nmonospecificity\nmonostele\nmonosteles\nmonostelic\nmonostelies\nmonostely\nmonosyllabic\nmonosyllabically\nmonosyllabicities\nmonosyllabicity\nmonosyllable\nmonosyllables\nmonosynaptic\nmonosynaptically\nmonoterpene\nmonoterpenes\nmonotheism\nmonotheisms\nmonotheist\nmonotheistic\nmonotheistical\nmonotheistically\nmonotheists\nmonotint\nmonotints\nmonotone\nmonotones\nmonotonic\nmonotonically\nmonotonicities\nmonotonicity\nmonotonies\nmonotonous\nmonotonously\nmonotonousness\nmonotonousnesses\nmonotony\nmonotreme\nmonotremes\nmonotype\nmonotypes\nmonotypic\nmonounsaturate\nmonounsaturated\nmonounsaturates\nmonovalent\nmonovular\nmonoxide\nmonoxides\nmonozygotic\nmons\nmonseigneur\nmonsieur\nmonsignor\nmonsignori\nmonsignorial\nmonsignors\nmonsoon\nmonsoonal\nmonsoons\nmonster\nmonstera\nmonsteras\nmonsters\nmonstrance\nmonstrances\nmonstrosities\nmonstrosity\nmonstrous\nmonstrously\nmonstrousness\nmonstrousnesses\nmontadale\nmontadales\nmontage\nmontaged\nmontages\nmontaging\nmontagnard\nmontagnards\nmontane\nmontanes\nmonte\nmonteith\nmonteiths\nmontero\nmonteros\nmontes\nmonth\nmonthlies\nmonthlong\nmonthly\nmonths\nmontmorillonite\nmontmorillonites\nmontmorillonitic\nmonument\nmonumental\nmonumentalities\nmonumentality\nmonumentalize\nmonumentalized\nmonumentalizes\nmonumentalizing\nmonumentally\nmonuments\nmonuron\nmonurons\nmony\nmonzonite\nmonzonites\nmoo\nmooch\nmooched\nmoocher\nmoochers\nmooches\nmooching\nmood\nmoodier\nmoodiest\nmoodily\nmoodiness\nmoodinesses\nmoods\nmoody\nmooed\nmooing\nmool\nmoola\nmoolah\nmoolahs\nmoolas\nmooley\nmooleys\nmools\nmoon\nmoonbeam\nmoonbeams\nmoonbow\nmoonbows\nmooncalf\nmooncalves\nmoondust\nmoondusts\nmooned\nmooneye\nmooneyes\nmoonfaced\nmoonfish\nmoonfishes\nmoonflower\nmoonflowers\nmoonier\nmooniest\nmoonily\nmooning\nmoonish\nmoonishly\nmoonless\nmoonlet\nmoonlets\nmoonlight\nmoonlighted\nmoonlighter\nmoonlighters\nmoonlighting\nmoonlights\nmoonlike\nmoonlit\nmoonport\nmoonports\nmoonquake\nmoonquakes\nmoonrise\nmoonrises\nmoons\nmoonsail\nmoonsails\nmoonscape\nmoonscapes\nmoonseed\nmoonseeds\nmoonset\nmoonsets\nmoonshine\nmoonshiner\nmoonshiners\nmoonshines\nmoonshot\nmoonshots\nmoonstone\nmoonstones\nmoonstruck\nmoonwalk\nmoonwalks\nmoonward\nmoonwort\nmoonworts\nmoony\nmoor\nmoorage\nmoorages\nmoorcock\nmoorcocks\nmoored\nmoorfowl\nmoorfowls\nmoorhen\nmoorhens\nmoorier\nmooriest\nmooring\nmoorings\nmoorish\nmoorland\nmoorlands\nmoors\nmoorwort\nmoorworts\nmoory\nmoos\nmoose\nmoot\nmooted\nmooter\nmooters\nmooting\nmoots\nmop\nmopboard\nmopboards\nmope\nmoped\nmopeds\nmoper\nmoperies\nmopers\nmopery\nmopes\nmopey\nmopier\nmopiest\nmoping\nmopingly\nmopish\nmopishly\nmopoke\nmopokes\nmopped\nmopper\nmoppers\nmoppet\nmoppets\nmopping\nmops\nmopy\nmoquette\nmoquettes\nmor\nmora\nmorae\nmorainal\nmoraine\nmoraines\nmorainic\nmoral\nmorale\nmorales\nmoralise\nmoralised\nmoralises\nmoralising\nmoralism\nmoralisms\nmoralist\nmoralistic\nmoralistically\nmoralists\nmoralities\nmorality\nmoralization\nmoralizations\nmoralize\nmoralized\nmoralizer\nmoralizers\nmoralizes\nmoralizing\nmorally\nmorals\nmoras\nmorass\nmorasses\nmorassy\nmoratoria\nmoratorium\nmoratoriums\nmoratory\nmoray\nmorays\nmorbid\nmorbidities\nmorbidity\nmorbidly\nmorbidness\nmorbidnesses\nmorbific\nmorbilli\nmorceau\nmorceaux\nmordancies\nmordancy\nmordant\nmordanted\nmordanting\nmordantly\nmordants\nmordent\nmordents\nmore\nmoreen\nmoreens\nmorel\nmorelle\nmorelles\nmorello\nmorellos\nmorels\nmoreover\nmores\nmoresque\nmoresques\nmorgan\nmorganatic\nmorganatically\nmorganite\nmorganites\nmorgans\nmorgen\nmorgens\nmorgue\nmorgues\nmoribund\nmoribundities\nmoribundity\nmorion\nmorions\nmorn\nmorning\nmornings\nmorns\nmorocco\nmoroccos\nmoron\nmoronic\nmoronically\nmoronism\nmoronisms\nmoronities\nmoronity\nmorons\nmorose\nmorosely\nmoroseness\nmorosenesses\nmorosities\nmorosity\nmorph\nmorphactin\nmorphactins\nmorphallaxes\nmorphallaxis\nmorphed\nmorpheme\nmorphemes\nmorphemic\nmorphemically\nmorphemics\nmorphia\nmorphias\nmorphic\nmorphin\nmorphine\nmorphines\nmorphing\nmorphinism\nmorphinisms\nmorphins\nmorpho\nmorphogen\nmorphogeneses\nmorphogenesis\nmorphogenetic\nmorphogenetically\nmorphogenic\nmorphogens\nmorphologic\nmorphological\nmorphologically\nmorphologies\nmorphologist\nmorphologists\nmorphology\nmorphometric\nmorphometrically\nmorphometries\nmorphometry\nmorphophonemics\nmorphos\nmorphs\nmorrion\nmorrions\nmorris\nmorrises\nmorro\nmorros\nmorrow\nmorrows\nmors\nmorse\nmorsel\nmorseled\nmorseling\nmorselled\nmorselling\nmorsels\nmort\nmortadella\nmortadellas\nmortal\nmortalities\nmortality\nmortally\nmortals\nmortar\nmortarboard\nmortarboards\nmortared\nmortaring\nmortarless\nmortars\nmortary\nmortgage\nmortgaged\nmortgagee\nmortgagees\nmortgager\nmortgagers\nmortgages\nmortgaging\nmortgagor\nmortgagors\nmortice\nmorticed\nmortices\nmortician\nmorticians\nmorticing\nmortification\nmortifications\nmortified\nmortifies\nmortify\nmortifying\nmortise\nmortised\nmortiser\nmortisers\nmortises\nmortising\nmortmain\nmortmains\nmorts\nmortuaries\nmortuary\nmorula\nmorulae\nmorular\nmorulas\nmorulation\nmorulations\nmos\nmosaic\nmosaically\nmosaicism\nmosaicisms\nmosaicist\nmosaicists\nmosaicked\nmosaicking\nmosaiclike\nmosaics\nmosasaur\nmosasaurs\nmoschate\nmosey\nmoseyed\nmoseying\nmoseys\nmosh\nmoshav\nmoshavim\nmoshed\nmosher\nmoshers\nmoshes\nmoshing\nmosk\nmosks\nmosque\nmosques\nmosquito\nmosquitoes\nmosquitoey\nmosquitos\nmoss\nmossback\nmossbacked\nmossbacks\nmossed\nmosser\nmossers\nmosses\nmossier\nmossiest\nmossing\nmosslike\nmosso\nmossy\nmost\nmoste\nmostest\nmostests\nmostly\nmosts\nmot\nmote\nmotel\nmotels\nmotes\nmotet\nmotets\nmotey\nmoth\nmothball\nmothballed\nmothballing\nmothballs\nmother\nmotherboard\nmotherboards\nmothered\nmotherfucker\nmotherfuckers\nmotherfucking\nmotherhood\nmotherhoods\nmotherhouse\nmotherhouses\nmothering\nmotherland\nmotherlands\nmotherless\nmotherlessness\nmotherlessnesses\nmotherliness\nmotherlinesses\nmotherly\nmothers\nmothery\nmothier\nmothiest\nmothlike\nmothproof\nmothproofed\nmothproofer\nmothproofers\nmothproofing\nmothproofs\nmoths\nmothy\nmotif\nmotific\nmotifs\nmotile\nmotiles\nmotilities\nmotility\nmotion\nmotional\nmotioned\nmotioner\nmotioners\nmotioning\nmotionless\nmotionlessly\nmotionlessness\nmotionlessnesses\nmotions\nmotivate\nmotivated\nmotivates\nmotivating\nmotivation\nmotivational\nmotivationally\nmotivations\nmotivative\nmotivator\nmotivators\nmotive\nmotived\nmotiveless\nmotivelessly\nmotives\nmotivic\nmotiving\nmotivities\nmotivity\nmotley\nmotleyer\nmotleyest\nmotleys\nmotlier\nmotliest\nmotmot\nmotmots\nmotocross\nmotocrosses\nmotoneuron\nmotoneuronal\nmotoneurons\nmotor\nmotorbike\nmotorbiked\nmotorbikes\nmotorbiking\nmotorboat\nmotorboater\nmotorboaters\nmotorboating\nmotorboatings\nmotorboats\nmotorbus\nmotorbuses\nmotorbusses\nmotorcade\nmotorcaded\nmotorcades\nmotorcading\nmotorcar\nmotorcars\nmotorcycle\nmotorcycled\nmotorcycles\nmotorcycling\nmotorcyclist\nmotorcyclists\nmotordom\nmotordoms\nmotored\nmotoric\nmotorically\nmotoring\nmotorings\nmotorise\nmotorised\nmotorises\nmotorising\nmotorist\nmotorists\nmotorization\nmotorizations\nmotorize\nmotorized\nmotorizes\nmotorizing\nmotorless\nmotorman\nmotormen\nmotormouth\nmotormouths\nmotors\nmotortruck\nmotortrucks\nmotorway\nmotorways\nmots\nmott\nmotte\nmottes\nmottle\nmottled\nmottler\nmottlers\nmottles\nmottling\nmotto\nmottoes\nmottos\nmotts\nmouch\nmouched\nmouches\nmouching\nmouchoir\nmouchoirs\nmoue\nmoues\nmoufflon\nmoufflons\nmouflon\nmouflons\nmouille\nmoujik\nmoujiks\nmoulage\nmoulages\nmould\nmoulded\nmoulder\nmouldered\nmouldering\nmoulders\nmouldier\nmouldiest\nmoulding\nmouldings\nmoulds\nmouldy\nmoulin\nmoulins\nmoult\nmoulted\nmoulter\nmoulters\nmoulting\nmoults\nmound\nmounded\nmounding\nmounds\nmount\nmountable\nmountain\nmountaineer\nmountaineering\nmountaineerings\nmountaineers\nmountainous\nmountainously\nmountainousness\nmountainousnesses\nmountains\nmountainside\nmountainsides\nmountaintop\nmountaintops\nmountainy\nmountebank\nmountebanked\nmountebankeries\nmountebankery\nmountebanking\nmountebanks\nmounted\nmounter\nmounters\nmounting\nmountings\nmounts\nmourn\nmourned\nmourner\nmourners\nmournful\nmournfuller\nmournfullest\nmournfully\nmournfulness\nmournfulnesses\nmourning\nmourningly\nmournings\nmourns\nmouse\nmoused\nmouser\nmousers\nmouses\nmousetrap\nmousetrapped\nmousetrapping\nmousetraps\nmousey\nmousier\nmousiest\nmousily\nmousiness\nmousinesses\nmousing\nmousings\nmoussaka\nmoussakas\nmousse\nmoussed\nmousseline\nmousselines\nmousses\nmoussing\nmoustache\nmoustaches\nmoustachio\nmoustachios\nmousy\nmouth\nmouthbreeder\nmouthbreeders\nmouthed\nmouther\nmouthers\nmouthful\nmouthfuls\nmouthier\nmouthiest\nmouthily\nmouthing\nmouthlike\nmouthpart\nmouthparts\nmouthpiece\nmouthpieces\nmouths\nmouthwash\nmouthwashes\nmouthwatering\nmouthwateringly\nmouthy\nmouton\nmoutons\nmovabilities\nmovability\nmovable\nmovableness\nmovablenesses\nmovables\nmovably\nmove\nmoveable\nmoveables\nmoveably\nmoved\nmoveless\nmovelessly\nmovelessness\nmovelessnesses\nmovement\nmovements\nmover\nmovers\nmoves\nmovie\nmoviedom\nmoviedoms\nmoviegoer\nmoviegoers\nmoviegoing\nmoviegoings\nmoviemaker\nmoviemakers\nmoviemaking\nmoviemakings\nmovieola\nmovieolas\nmovies\nmoving\nmovingly\nmoviola\nmoviolas\nmow\nmowed\nmower\nmowers\nmowing\nmowings\nmown\nmows\nmoxa\nmoxas\nmoxie\nmoxies\nmozetta\nmozettas\nmozette\nmozo\nmozos\nmozzarella\nmozzarellas\nmozzetta\nmozzettas\nmozzette\nmridanga\nmridangam\nmridangams\nmridangas\nmu\nmuch\nmuchacho\nmuchachos\nmuches\nmuchly\nmuchness\nmuchnesses\nmucid\nmucidities\nmucidity\nmucilage\nmucilages\nmucilaginous\nmucilaginously\nmucin\nmucinoid\nmucinous\nmucins\nmuck\nmuckamuck\nmuckamucks\nmucked\nmucker\nmuckers\nmuckier\nmuckiest\nmuckily\nmucking\nmuckle\nmuckles\nmuckluck\nmucklucks\nmuckrake\nmuckraked\nmuckraker\nmuckrakers\nmuckrakes\nmuckraking\nmucks\nmuckworm\nmuckworms\nmucky\nmucluc\nmuclucs\nmucocutaneous\nmucoid\nmucoidal\nmucoids\nmucolytic\nmucopeptide\nmucopeptides\nmucopolysaccharide\nmucopolysaccharides\nmucoprotein\nmucoproteins\nmucor\nmucors\nmucosa\nmucosae\nmucosal\nmucosas\nmucose\nmucosities\nmucosity\nmucous\nmucro\nmucronate\nmucrones\nmucros\nmucus\nmucuses\nmud\nmudcap\nmudcapped\nmudcapping\nmudcaps\nmudcat\nmudcats\nmudded\nmudder\nmudders\nmuddied\nmuddier\nmuddies\nmuddiest\nmuddily\nmuddiness\nmuddinesses\nmudding\nmuddle\nmuddled\nmuddleheaded\nmuddleheadedly\nmuddleheadedness\nmuddleheadednesses\nmuddler\nmuddlers\nmuddles\nmuddling\nmuddly\nmuddy\nmuddying\nmudfish\nmudfishes\nmudflap\nmudflaps\nmudflat\nmudflats\nmudflow\nmudflows\nmudguard\nmudguards\nmudhole\nmudholes\nmudlark\nmudlarks\nmudpack\nmudpacks\nmudpuppies\nmudpuppy\nmudra\nmudras\nmudrock\nmudrocks\nmudroom\nmudrooms\nmuds\nmudsill\nmudsills\nmudskipper\nmudskippers\nmudslide\nmudslides\nmudslinger\nmudslingers\nmudslinging\nmudslingings\nmudstone\nmudstones\nmueddin\nmueddins\nmuenster\nmuensters\nmuesli\nmueslis\nmuezzin\nmuezzins\nmuff\nmuffed\nmuffin\nmuffing\nmuffins\nmuffle\nmuffled\nmuffler\nmufflered\nmufflers\nmuffles\nmuffling\nmuffs\nmufti\nmuftis\nmug\nmugful\nmugfuls\nmugg\nmuggar\nmuggars\nmugged\nmuggee\nmuggees\nmugger\nmuggers\nmuggier\nmuggiest\nmuggily\nmugginess\nmugginesses\nmugging\nmuggings\nmuggins\nmuggs\nmuggur\nmuggurs\nmuggy\nmugs\nmugshot\nmugshots\nmugwort\nmugworts\nmugwump\nmugwumps\nmuhlies\nmuhly\nmujahedeen\nmujahedin\nmujahideen\nmujik\nmujiks\nmukluk\nmukluks\nmuktuk\nmuktuks\nmulatto\nmulattoes\nmulattos\nmulberries\nmulberry\nmulch\nmulched\nmulches\nmulching\nmulct\nmulcted\nmulcting\nmulcts\nmule\nmuled\nmules\nmuleta\nmuletas\nmuleteer\nmuleteers\nmuley\nmuleys\nmuliebrities\nmuliebrity\nmuling\nmulish\nmulishly\nmulishness\nmulishnesses\nmull\nmulla\nmullah\nmullahism\nmullahisms\nmullahs\nmullas\nmulled\nmullein\nmulleins\nmullen\nmullens\nmuller\nmullers\nmullet\nmullets\nmulley\nmulleys\nmulligan\nmulligans\nmulligatawnies\nmulligatawny\nmulling\nmullion\nmullioned\nmullioning\nmullions\nmullite\nmullites\nmullock\nmullocks\nmullocky\nmulls\nmultiage\nmultiagency\nmultiarmed\nmultiatom\nmultiauthor\nmultiaxial\nmultiband\nmultibank\nmultibarrel\nmultibarreled\nmultibillion\nmultibillionaire\nmultibillionaires\nmultibillions\nmultibladed\nmultibranched\nmultibuilding\nmulticampus\nmulticar\nmulticarbon\nmulticausal\nmulticell\nmulticelled\nmulticellular\nmulticellularities\nmulticellularity\nmulticenter\nmultichain\nmultichambered\nmultichannel\nmultichannels\nmulticharacter\nmulticity\nmulticlient\nmulticoated\nmulticolor\nmulticolored\nmulticolors\nmulticolumn\nmulticomponent\nmulticonductor\nmulticopy\nmulticounty\nmulticourse\nmulticourses\nmulticultural\nmulticulturalism\nmulticulturalisms\nmulticurie\nmulticurrency\nmultidialectal\nmultidimensional\nmultidimensionalities\nmultidimensionality\nmultidirectional\nmultidisciplinary\nmultidiscipline\nmultidisciplines\nmultidivisional\nmultidomain\nmultidrug\nmultielectrode\nmultielement\nmultiemployer\nmultiengine\nmultiengines\nmultienzyme\nmultiethnic\nmultifaceted\nmultifactor\nmultifactorial\nmultifactorially\nmultifamily\nmultifarious\nmultifariousness\nmultifariousnesses\nmultifid\nmultifilament\nmultifilaments\nmultiflash\nmultifocal\nmultifold\nmultiform\nmultiformities\nmultiformity\nmultifrequency\nmultifunction\nmultifunctional\nmultigenerational\nmultigenic\nmultigerm\nmultigrade\nmultigrain\nmultigrains\nmultigrid\nmultigroup\nmultihandicapped\nmultiheaded\nmultihospital\nmultihued\nmultihull\nmultihulls\nmultijet\nmultilane\nmultilateral\nmultilateralism\nmultilateralisms\nmultilateralist\nmultilateralists\nmultilaterally\nmultilayer\nmultilayered\nmultilevel\nmultileveled\nmultiline\nmultilingual\nmultilingualism\nmultilingualisms\nmultilingually\nmultilobed\nmultimanned\nmultimedia\nmultimedias\nmultimegaton\nmultimegatons\nmultimegawatt\nmultimegawatts\nmultimember\nmultimetallic\nmultimillennial\nmultimillion\nmultimillionaire\nmultimillionaires\nmultimillions\nmultimodal\nmultimode\nmultimolecular\nmultination\nmultinational\nmultinationals\nmultinomial\nmultinomials\nmultinuclear\nmultinucleate\nmultinucleated\nmultiorgasmic\nmultipage\nmultipaned\nmultiparameter\nmultiparous\nmultipart\nmultiparticle\nmultipartite\nmultiparty\nmultipath\nmultiped\nmultipeds\nmultiphase\nmultiphasic\nmultiphoton\nmultipicture\nmultipiece\nmultipion\nmultipiston\nmultiplant\nmultiplayer\nmultiple\nmultiples\nmultiplet\nmultiplets\nmultiplex\nmultiplexed\nmultiplexer\nmultiplexers\nmultiplexes\nmultiplexing\nmultiplexor\nmultiplexors\nmultiplicand\nmultiplicands\nmultiplication\nmultiplications\nmultiplicative\nmultiplicatively\nmultiplicities\nmultiplicity\nmultiplied\nmultiplier\nmultipliers\nmultiplies\nmultiply\nmultiplying\nmultipolar\nmultipolarities\nmultipolarity\nmultipole\nmultipotential\nmultipower\nmultiproblem\nmultiprocessing\nmultiprocessings\nmultiprocessor\nmultiprocessors\nmultiproduct\nmultiprogramming\nmultiprogrammings\nmultipronged\nmultipurpose\nmultiracial\nmultiracialism\nmultiracialisms\nmultirange\nmultiregional\nmultireligious\nmultiroom\nmultiscreen\nmultisense\nmultisensory\nmultiservice\nmultisided\nmultisite\nmultisize\nmultiskilled\nmultisource\nmultispecies\nmultispectral\nmultispeed\nmultisport\nmultistage\nmultistate\nmultistemmed\nmultistep\nmultistoried\nmultistory\nmultistranded\nmultisyllabic\nmultisystem\nmultitalented\nmultitask\nmultitasked\nmultitasking\nmultitaskings\nmultitasks\nmultiterminal\nmultitiered\nmultiton\nmultitone\nmultitowered\nmultitrack\nmultitracked\nmultitracking\nmultitracks\nmultitrillion\nmultitrillions\nmultitude\nmultitudes\nmultitudinous\nmultitudinously\nmultitudinousness\nmultitudinousnesses\nmultiunion\nmultiunit\nmultiuse\nmultiuser\nmultivalence\nmultivalences\nmultivalent\nmultivalents\nmultivariable\nmultivariate\nmultiversities\nmultiversity\nmultivitamin\nmultivitamins\nmultivoltine\nmultivolume\nmultiwall\nmultiwarhead\nmultiwavelength\nmultiyear\nmulture\nmultures\nmum\nmumble\nmumbled\nmumbler\nmumblers\nmumbles\nmumbling\nmumbly\nmumm\nmummed\nmummer\nmummeries\nmummers\nmummery\nmummichog\nmummichogs\nmummied\nmummies\nmummification\nmummifications\nmummified\nmummifies\nmummify\nmummifying\nmumming\nmumms\nmummy\nmummying\nmump\nmumped\nmumper\nmumpers\nmumping\nmumps\nmums\nmumu\nmumus\nmun\nmunch\nmunched\nmuncher\nmunchers\nmunches\nmunchies\nmunching\nmunchkin\nmunchkins\nmundane\nmundanely\nmundaneness\nmundanenesses\nmundanes\nmundanities\nmundanity\nmundungo\nmundungos\nmundungus\nmundunguses\nmungo\nmungoose\nmungooses\nmungos\nmuni\nmunicipal\nmunicipalities\nmunicipality\nmunicipalization\nmunicipalizations\nmunicipalize\nmunicipalized\nmunicipalizes\nmunicipalizing\nmunicipally\nmunicipals\nmunificence\nmunificences\nmunificent\nmunificently\nmuniment\nmuniments\nmunis\nmunition\nmunitioned\nmunitioning\nmunitions\nmunnion\nmunnions\nmuns\nmunster\nmunsters\nmuntin\nmunting\nmuntings\nmuntins\nmuntjac\nmuntjacs\nmuntjak\nmuntjaks\nmuon\nmuonic\nmuonium\nmuoniums\nmuons\nmura\nmuraenid\nmuraenids\nmural\nmuralist\nmuralists\nmurals\nmuras\nmurder\nmurdered\nmurderee\nmurderees\nmurderer\nmurderers\nmurderess\nmurderesses\nmurdering\nmurderous\nmurderously\nmurderousness\nmurderousnesses\nmurders\nmure\nmured\nmurein\nmureins\nmures\nmurex\nmurexes\nmuriate\nmuriated\nmuriates\nmuricate\nmurices\nmurid\nmurids\nmurine\nmurines\nmuring\nmurk\nmurker\nmurkest\nmurkier\nmurkiest\nmurkily\nmurkiness\nmurkinesses\nmurkly\nmurks\nmurky\nmurmur\nmurmured\nmurmurer\nmurmurers\nmurmuring\nmurmurous\nmurmurously\nmurmurs\nmurphies\nmurphy\nmurr\nmurra\nmurrain\nmurrains\nmurras\nmurre\nmurrelet\nmurrelets\nmurres\nmurrey\nmurreys\nmurrha\nmurrhas\nmurrhine\nmurries\nmurrine\nmurrs\nmurry\nmurther\nmurthered\nmurthering\nmurthers\nmus\nmusca\nmuscadel\nmuscadels\nmuscadet\nmuscadets\nmuscadine\nmuscadines\nmuscae\nmuscarine\nmuscarines\nmuscarinic\nmuscat\nmuscatel\nmuscatels\nmuscats\nmuscid\nmuscids\nmuscle\nmusclebound\nmuscled\nmuscles\nmuscling\nmuscly\nmuscovite\nmuscovites\nmuscular\nmuscularities\nmuscularity\nmuscularly\nmusculature\nmusculatures\nmusculoskeletal\nmuse\nmused\nmuseful\nmuseological\nmuseologies\nmuseologist\nmuseologists\nmuseology\nmuser\nmusers\nmuses\nmusette\nmusettes\nmuseum\nmuseums\nmush\nmushed\nmusher\nmushers\nmushes\nmushier\nmushiest\nmushily\nmushiness\nmushinesses\nmushing\nmushroom\nmushroomed\nmushrooming\nmushrooms\nmushy\nmusic\nmusical\nmusicale\nmusicales\nmusicalise\nmusicalised\nmusicalises\nmusicalising\nmusicalities\nmusicality\nmusicalization\nmusicalizations\nmusicalize\nmusicalized\nmusicalizes\nmusicalizing\nmusically\nmusicals\nmusician\nmusicianly\nmusicians\nmusicianship\nmusicianships\nmusicological\nmusicologies\nmusicologist\nmusicologists\nmusicology\nmusics\nmusing\nmusingly\nmusings\nmusjid\nmusjids\nmusk\nmuskeg\nmuskegs\nmuskellunge\nmuskellunges\nmusket\nmusketeer\nmusketeers\nmusketries\nmusketry\nmuskets\nmuskie\nmuskier\nmuskies\nmuskiest\nmuskily\nmuskiness\nmuskinesses\nmuskit\nmuskits\nmuskmelon\nmuskmelons\nmuskrat\nmuskrats\nmusks\nmusky\nmuslin\nmuslins\nmuspike\nmuspikes\nmusquash\nmusquashes\nmuss\nmussed\nmussel\nmussels\nmusses\nmussier\nmussiest\nmussily\nmussiness\nmussinesses\nmussing\nmussy\nmust\nmustache\nmustached\nmustaches\nmustachio\nmustachioed\nmustachios\nmustang\nmustangs\nmustard\nmustards\nmustardy\nmusted\nmustee\nmustees\nmuster\nmustered\nmustering\nmusters\nmusth\nmusths\nmustier\nmustiest\nmustily\nmustiness\nmustinesses\nmusting\nmusts\nmusty\nmut\nmutabilities\nmutability\nmutable\nmutably\nmutagen\nmutageneses\nmutagenesis\nmutagenic\nmutagenically\nmutagenicities\nmutagenicity\nmutagens\nmutant\nmutants\nmutase\nmutases\nmutate\nmutated\nmutates\nmutating\nmutation\nmutational\nmutationally\nmutations\nmutative\nmutch\nmutches\nmutchkin\nmutchkins\nmute\nmuted\nmutedly\nmutely\nmuteness\nmutenesses\nmuter\nmutes\nmutest\nmuticous\nmutilate\nmutilated\nmutilates\nmutilating\nmutilation\nmutilations\nmutilator\nmutilators\nmutine\nmutined\nmutineer\nmutineered\nmutineering\nmutineers\nmutines\nmuting\nmutinied\nmutinies\nmutining\nmutinous\nmutinously\nmutinousness\nmutinousnesses\nmutiny\nmutinying\nmutism\nmutisms\nmuton\nmutons\nmuts\nmutt\nmutter\nmuttered\nmutterer\nmutterers\nmuttering\nmutters\nmutton\nmuttonchops\nmuttonfish\nmuttonfishes\nmuttons\nmuttony\nmutts\nmutual\nmutualism\nmutualisms\nmutualist\nmutualistic\nmutualists\nmutualities\nmutuality\nmutualization\nmutualizations\nmutualize\nmutualized\nmutualizes\nmutualizing\nmutually\nmutuals\nmutuel\nmutuels\nmutular\nmutule\nmutules\nmuumuu\nmuumuus\nmuzhik\nmuzhiks\nmuzjik\nmuzjiks\nmuzzier\nmuzziest\nmuzzily\nmuzziness\nmuzzinesses\nmuzzle\nmuzzled\nmuzzler\nmuzzlers\nmuzzles\nmuzzling\nmuzzy\nmy\nmyalgia\nmyalgias\nmyalgic\nmyases\nmyasis\nmyasthenia\nmyasthenias\nmyasthenic\nmyasthenics\nmycele\nmyceles\nmycelia\nmycelial\nmycelian\nmycelium\nmyceloid\nmycetoma\nmycetomas\nmycetomata\nmycetomatous\nmycetophagous\nmycetozoan\nmycetozoans\nmycobacteria\nmycobacterial\nmycobacterium\nmycoflora\nmycoflorae\nmycofloras\nmycological\nmycologically\nmycologies\nmycologist\nmycologists\nmycology\nmycophagies\nmycophagist\nmycophagists\nmycophagous\nmycophagy\nmycophile\nmycophiles\nmycoplasma\nmycoplasmal\nmycoplasmas\nmycoplasmata\nmycorrhiza\nmycorrhizae\nmycorrhizal\nmycorrhizas\nmycoses\nmycosis\nmycotic\nmycotoxin\nmycotoxins\nmydriases\nmydriasis\nmydriatic\nmydriatics\nmyelencephala\nmyelencephalic\nmyelencephalon\nmyelencephalons\nmyelin\nmyelinated\nmyeline\nmyelines\nmyelinic\nmyelins\nmyelitides\nmyelitis\nmyeloblast\nmyeloblastic\nmyeloblasts\nmyelocyte\nmyelocytes\nmyelocytic\nmyelofibroses\nmyelofibrosis\nmyelofibrotic\nmyelogenous\nmyeloid\nmyeloma\nmyelomas\nmyelomata\nmyelomatous\nmyelopathic\nmyelopathies\nmyelopathy\nmyeloproliferative\nmyiases\nmyiasis\nmylonite\nmylonites\nmyna\nmynah\nmynahs\nmynas\nmynheer\nmynheers\nmyoblast\nmyoblasts\nmyocardia\nmyocardial\nmyocarditis\nmyocarditises\nmyocardium\nmyoclonic\nmyoclonus\nmyoclonuses\nmyoelectric\nmyoelectrical\nmyofibril\nmyofibrillar\nmyofibrils\nmyofilament\nmyofilaments\nmyogenic\nmyoglobin\nmyoglobins\nmyograph\nmyographs\nmyoid\nmyoinositol\nmyoinositols\nmyologic\nmyologies\nmyology\nmyoma\nmyomas\nmyomata\nmyomatous\nmyoneural\nmyopathic\nmyopathies\nmyopathy\nmyope\nmyopes\nmyopia\nmyopias\nmyopic\nmyopically\nmyopies\nmyopy\nmyoscope\nmyoscopes\nmyoses\nmyosin\nmyosins\nmyosis\nmyositis\nmyositises\nmyosote\nmyosotes\nmyosotis\nmyosotises\nmyotic\nmyotics\nmyotome\nmyotomes\nmyotonia\nmyotonias\nmyotonic\nmyriad\nmyriads\nmyriapod\nmyriapods\nmyrica\nmyricas\nmyriopod\nmyriopods\nmyrmecological\nmyrmecologies\nmyrmecologist\nmyrmecologists\nmyrmecology\nmyrmecophile\nmyrmecophiles\nmyrmecophilous\nmyrmidon\nmyrmidons\nmyrobalan\nmyrobalans\nmyrrh\nmyrrhic\nmyrrhs\nmyrtle\nmyrtles\nmyself\nmysid\nmysids\nmysost\nmysosts\nmystagog\nmystagogies\nmystagogs\nmystagogue\nmystagogues\nmystagogy\nmysteries\nmysterious\nmysteriously\nmysteriousness\nmysteriousnesses\nmystery\nmystic\nmystical\nmystically\nmysticism\nmysticisms\nmysticly\nmystics\nmystification\nmystifications\nmystified\nmystifier\nmystifiers\nmystifies\nmystify\nmystifying\nmystifyingly\nmystique\nmystiques\nmyth\nmythic\nmythical\nmythically\nmythicize\nmythicized\nmythicizer\nmythicizers\nmythicizes\nmythicizing\nmythier\nmythiest\nmythmaker\nmythmakers\nmythmaking\nmythmakings\nmythographer\nmythographers\nmythographies\nmythography\nmythoi\nmythologer\nmythologers\nmythologic\nmythological\nmythologically\nmythologies\nmythologist\nmythologists\nmythologize\nmythologized\nmythologizer\nmythologizers\nmythologizes\nmythologizing\nmythology\nmythomania\nmythomaniac\nmythomaniacs\nmythomanias\nmythopoeia\nmythopoeias\nmythopoeic\nmythopoetic\nmythopoetical\nmythos\nmyths\nmythy\nmyxedema\nmyxedemas\nmyxedematous\nmyxocyte\nmyxocytes\nmyxoid\nmyxoma\nmyxomas\nmyxomata\nmyxomatoses\nmyxomatosis\nmyxomatous\nmyxomycete\nmyxomycetes\nmyxoviral\nmyxovirus\nmyxoviruses\nna\nnaan\nnaans\nnab\nnabbed\nnabber\nnabbers\nnabbing\nnabe\nnabes\nnabis\nnabob\nnaboberies\nnabobery\nnabobess\nnabobesses\nnabobish\nnabobism\nnabobisms\nnabobs\nnabs\nnacelle\nnacelles\nnachas\nnaches\nnacho\nnachos\nnacre\nnacred\nnacreous\nnacres\nnada\nnadas\nnadir\nnadiral\nnadirs\nnae\nnaething\nnaethings\nnaevi\nnaevoid\nnaevus\nnag\nnagana\nnaganas\nnagged\nnagger\nnaggers\nnaggier\nnaggiest\nnagging\nnaggingly\nnaggy\nnags\nnah\nnaiad\nnaiades\nnaiads\nnaif\nnaifs\nnail\nnailbrush\nnailbrushes\nnailed\nnailer\nnailers\nnailfold\nnailfolds\nnailhead\nnailheads\nnailing\nnails\nnailset\nnailsets\nnainsook\nnainsooks\nnaira\nnairas\nnaive\nnaively\nnaiveness\nnaivenesses\nnaiver\nnaives\nnaivest\nnaivete\nnaivetes\nnaiveties\nnaivety\nnaked\nnakeder\nnakedest\nnakedly\nnakedness\nnakednesses\nnaled\nnaleds\nnalorphine\nnalorphines\nnaloxone\nnaloxones\nnaltrexone\nnaltrexones\nnam\nnamable\nname\nnameable\nnamed\nnameless\nnamelessly\nnamelessness\nnamelessnesses\nnamely\nnameplate\nnameplates\nnamer\nnamers\nnames\nnamesake\nnamesakes\nnametag\nnametags\nnaming\nnan\nnana\nnanas\nnance\nnances\nnancies\nnancy\nnancys\nnandin\nnandina\nnandinas\nnandins\nnanism\nnanisms\nnankeen\nnankeens\nnankin\nnankins\nnannie\nnannies\nnannoplankton\nnannoplanktons\nnanny\nnanogram\nnanograms\nnanometer\nnanometers\nnanosecond\nnanoseconds\nnanotechnologies\nnanotechnology\nnanotesla\nnanoteslas\nnanowatt\nnanowatts\nnans\nnaoi\nnaos\nnap\nnapalm\nnapalmed\nnapalming\nnapalms\nnape\nnaperies\nnapery\nnapes\nnaphtha\nnaphthalene\nnaphthalenes\nnaphthas\nnaphthene\nnaphthenes\nnaphthenic\nnaphthol\nnaphthols\nnaphthyl\nnaphthylamine\nnaphthylamines\nnaphthyls\nnaphtol\nnaphtols\nnapiform\nnapkin\nnapkins\nnapless\nnapoleon\nnapoleons\nnappe\nnapped\nnapper\nnappers\nnappes\nnappie\nnappier\nnappies\nnappiest\nnapping\nnappy\nnaprapathies\nnaprapathy\nnaps\nnarc\nnarcein\nnarceine\nnarceines\nnarceins\nnarcism\nnarcisms\nnarcissi\nnarcissism\nnarcissisms\nnarcissist\nnarcissistic\nnarcissists\nnarcissus\nnarcissuses\nnarcist\nnarcists\nnarco\nnarcolepsies\nnarcolepsy\nnarcoleptic\nnarcoleptics\nnarcos\nnarcose\nnarcoses\nnarcosis\nnarcotic\nnarcotically\nnarcotics\nnarcotize\nnarcotized\nnarcotizes\nnarcotizing\nnarcs\nnard\nnardine\nnards\nnares\nnarghile\nnarghiles\nnargile\nnargileh\nnargilehs\nnargiles\nnarial\nnaric\nnarine\nnaris\nnark\nnarked\nnarking\nnarks\nnarky\nnarrate\nnarrated\nnarrater\nnarraters\nnarrates\nnarrating\nnarration\nnarrational\nnarrations\nnarrative\nnarratively\nnarratives\nnarratological\nnarratologies\nnarratologist\nnarratologists\nnarratology\nnarrator\nnarrators\nnarrow\nnarrowband\nnarrowcasting\nnarrowcastings\nnarrowed\nnarrower\nnarrowest\nnarrowing\nnarrowly\nnarrowness\nnarrownesses\nnarrows\nnarthex\nnarthexes\nnarwal\nnarwals\nnarwhal\nnarwhale\nnarwhales\nnarwhals\nnary\nnasal\nnasalise\nnasalised\nnasalises\nnasalising\nnasalities\nnasality\nnasalization\nnasalizations\nnasalize\nnasalized\nnasalizes\nnasalizing\nnasally\nnasals\nnascence\nnascences\nnascencies\nnascency\nnascent\nnasial\nnasion\nnasions\nnasogastric\nnasopharyngeal\nnasopharynges\nnasopharynx\nnasopharynxes\nnastic\nnastier\nnasties\nnastiest\nnastily\nnastiness\nnastinesses\nnasturtium\nnasturtiums\nnasty\nnatal\nnatalities\nnatality\nnatant\nnatantly\nnatation\nnatations\nnatatoria\nnatatorial\nnatatorium\nnatatoriums\nnatatory\nnatch\nnates\nnatheless\nnathless\nnation\nnational\nnationalise\nnationalised\nnationalises\nnationalising\nnationalism\nnationalisms\nnationalist\nnationalistic\nnationalistically\nnationalists\nnationalities\nnationality\nnationalization\nnationalizations\nnationalize\nnationalized\nnationalizer\nnationalizers\nnationalizes\nnationalizing\nnationally\nnationals\nnationhood\nnationhoods\nnations\nnationwide\nnative\nnatively\nnativeness\nnativenesses\nnatives\nnativism\nnativisms\nnativist\nnativistic\nnativists\nnativities\nnativity\nnatrium\nnatriums\nnatriureses\nnatriuresis\nnatriuretic\nnatriuretics\nnatrolite\nnatrolites\nnatron\nnatrons\nnatter\nnattered\nnattering\nnatters\nnattier\nnattiest\nnattily\nnattiness\nnattinesses\nnatty\nnatural\nnaturalise\nnaturalised\nnaturalises\nnaturalising\nnaturalism\nnaturalisms\nnaturalist\nnaturalistic\nnaturalistically\nnaturalists\nnaturalization\nnaturalizations\nnaturalize\nnaturalized\nnaturalizes\nnaturalizing\nnaturally\nnaturalness\nnaturalnesses\nnaturals\nnature\nnatured\nnatures\nnaturism\nnaturisms\nnaturist\nnaturists\nnaturopath\nnaturopathic\nnaturopathies\nnaturopaths\nnaturopathy\nnaught\nnaughtier\nnaughtiest\nnaughtily\nnaughtiness\nnaughtinesses\nnaughts\nnaughty\nnaumachia\nnaumachiae\nnaumachias\nnaumachies\nnaumachy\nnauplial\nnauplii\nnauplius\nnausea\nnauseant\nnauseants\nnauseas\nnauseate\nnauseated\nnauseates\nnauseating\nnauseatingly\nnauseous\nnauseously\nnauseousness\nnauseousnesses\nnautch\nnautches\nnautical\nnautically\nnautili\nnautiloid\nnautiloids\nnautilus\nnautiluses\nnavaid\nnavaids\nnaval\nnavally\nnavar\nnavars\nnave\nnavel\nnavels\nnaves\nnavette\nnavettes\nnavicert\nnavicerts\nnavicular\nnaviculars\nnavies\nnavigabilities\nnavigability\nnavigable\nnavigably\nnavigate\nnavigated\nnavigates\nnavigating\nnavigation\nnavigational\nnavigationally\nnavigations\nnavigator\nnavigators\nnavvies\nnavvy\nnavy\nnaw\nnawab\nnawabs\nnay\nnays\nnaysayer\nnaysayers\nnazi\nnazification\nnazifications\nnazified\nnazifies\nnazify\nnazifying\nnazis\nne\nneanderthal\nneanderthals\nneap\nneaps\nnear\nnearby\nneared\nnearer\nnearest\nnearing\nnearlier\nnearliest\nnearly\nnearness\nnearnesses\nnears\nnearshore\nnearside\nnearsides\nnearsighted\nnearsightedly\nnearsightedness\nnearsightednesses\nneat\nneaten\nneatened\nneatening\nneatens\nneater\nneatest\nneath\nneatherd\nneatherds\nneatly\nneatness\nneatnesses\nneats\nneb\nnebbish\nnebbishes\nnebbishy\nnebenkern\nnebenkerns\nnebs\nnebula\nnebulae\nnebular\nnebulas\nnebule\nnebulise\nnebulised\nnebulises\nnebulising\nnebulization\nnebulizations\nnebulize\nnebulized\nnebulizer\nnebulizers\nnebulizes\nnebulizing\nnebulose\nnebulosities\nnebulosity\nnebulous\nnebulously\nnebulousness\nnebulousnesses\nnebuly\nnecessaries\nnecessarily\nnecessary\nnecessitarian\nnecessitarianism\nnecessitarianisms\nnecessitarians\nnecessitate\nnecessitated\nnecessitates\nnecessitating\nnecessitation\nnecessitations\nnecessities\nnecessitous\nnecessitously\nnecessitousness\nnecessitousnesses\nnecessity\nneck\nneckband\nneckbands\nnecked\nnecker\nneckerchief\nneckerchiefs\nneckerchieves\nneckers\nnecking\nneckings\nnecklace\nnecklaces\nneckless\nnecklike\nneckline\nnecklines\nnecks\nnecktie\nneckties\nneckwear\nnecrological\nnecrologies\nnecrologist\nnecrologists\nnecrology\nnecromancer\nnecromancers\nnecromancies\nnecromancy\nnecromantic\nnecromantically\nnecrophagous\nnecrophilia\nnecrophiliac\nnecrophiliacs\nnecrophilias\nnecrophilic\nnecrophilism\nnecrophilisms\nnecropoleis\nnecropoles\nnecropoli\nnecropolis\nnecropolises\nnecropsied\nnecropsies\nnecropsy\nnecropsying\nnecrose\nnecrosed\nnecroses\nnecrosing\nnecrosis\nnecrotic\nnecrotizing\nnectar\nnectaries\nnectarine\nnectarines\nnectarous\nnectars\nnectary\nnee\nneed\nneeded\nneeder\nneeders\nneedful\nneedfully\nneedfulness\nneedfulnesses\nneedfuls\nneedier\nneediest\nneedily\nneediness\nneedinesses\nneeding\nneedle\nneedled\nneedlefish\nneedlefishes\nneedlelike\nneedlepoint\nneedlepoints\nneedler\nneedlers\nneedles\nneedless\nneedlessly\nneedlessness\nneedlessnesses\nneedlewoman\nneedlewomen\nneedlework\nneedleworker\nneedleworkers\nneedleworks\nneedling\nneedlings\nneeds\nneedy\nneem\nneems\nneep\nneeps\nnefarious\nnefariously\nnegate\nnegated\nnegater\nnegaters\nnegates\nnegating\nnegation\nnegational\nnegations\nnegative\nnegatived\nnegatively\nnegativeness\nnegativenesses\nnegatives\nnegativing\nnegativism\nnegativisms\nnegativist\nnegativistic\nnegativists\nnegativities\nnegativity\nnegaton\nnegatons\nnegator\nnegators\nnegatron\nnegatrons\nneglect\nneglected\nneglecter\nneglecters\nneglectful\nneglectfully\nneglectfulness\nneglectfulnesses\nneglecting\nneglects\nneglige\nnegligee\nnegligees\nnegligence\nnegligences\nnegligent\nnegligently\nnegliges\nnegligibilities\nnegligibility\nnegligible\nnegligibly\nnegotiabilities\nnegotiability\nnegotiable\nnegotiant\nnegotiants\nnegotiate\nnegotiated\nnegotiates\nnegotiating\nnegotiation\nnegotiations\nnegotiator\nnegotiators\nnegotiatory\nnegritude\nnegritudes\nnegroid\nnegroids\nnegroni\nnegronis\nnegrophobe\nnegrophobes\nnegrophobia\nnegrophobias\nnegus\nneguses\nneif\nneifs\nneigh\nneighbor\nneighbored\nneighborhood\nneighborhoods\nneighboring\nneighborliness\nneighborlinesses\nneighborly\nneighbors\nneighbour\nneighboured\nneighbouring\nneighbours\nneighed\nneighing\nneighs\nneist\nneither\nnekton\nnektonic\nnektons\nnellie\nnellies\nnelly\nnelson\nnelsons\nnelumbo\nnelumbos\nnema\nnemas\nnematic\nnematicidal\nnematicide\nnematicides\nnematocidal\nnematocide\nnematocides\nnematocyst\nnematocysts\nnematode\nnematodes\nnematological\nnematologies\nnematologist\nnematologists\nnematology\nnemertean\nnemerteans\nnemertine\nnemertines\nnemeses\nnemesis\nnemophila\nnemophilas\nnene\nnenes\nneoclassic\nneoclassical\nneoclassicism\nneoclassicisms\nneoclassicist\nneoclassicists\nneocolonial\nneocolonialism\nneocolonialisms\nneocolonialist\nneocolonialists\nneoconservatism\nneoconservatisms\nneoconservative\nneoconservatives\nneocortex\nneocortexes\nneocortical\nneocortices\nneodymium\nneodymiums\nneoliberal\nneoliberalism\nneoliberalisms\nneoliberals\nneolith\nneolithic\nneoliths\nneologic\nneologies\nneologism\nneologisms\nneologistic\nneology\nneomorph\nneomorphs\nneomycin\nneomycins\nneon\nneonatal\nneonatally\nneonate\nneonates\nneonatologies\nneonatologist\nneonatologists\nneonatology\nneoned\nneons\nneoorthodox\nneoorthodoxies\nneoorthodoxy\nneophilia\nneophiliac\nneophiliacs\nneophilias\nneophyte\nneophytes\nneoplasia\nneoplasias\nneoplasm\nneoplasms\nneoplastic\nneoplasticism\nneoplasticisms\nneoplasticist\nneoplasticists\nneoprene\nneoprenes\nneorealism\nneorealisms\nneorealist\nneorealistic\nneorealists\nneostigmine\nneostigmines\nneotenic\nneotenies\nneoteny\nneoteric\nneoterics\nneotropics\nneotype\nneotypes\nnepenthe\nnepenthean\nnepenthes\nnepheline\nnephelines\nnephelinic\nnephelinite\nnephelinites\nnephelinitic\nnephelite\nnephelites\nnephelometer\nnephelometers\nnephelometric\nnephelometrically\nnephelometries\nnephelometry\nnephew\nnephews\nnephoscope\nnephoscopes\nnephrectomies\nnephrectomize\nnephrectomized\nnephrectomizes\nnephrectomizing\nnephrectomy\nnephric\nnephridia\nnephridial\nnephridium\nnephrism\nnephrisms\nnephrite\nnephrites\nnephritic\nnephritides\nnephritis\nnephrologies\nnephrologist\nnephrologists\nnephrology\nnephron\nnephrons\nnephropathic\nnephropathies\nnephropathy\nnephroses\nnephrosis\nnephrostome\nnephrostomes\nnephrotic\nnephrotics\nnephrotoxic\nnephrotoxicities\nnephrotoxicity\nnepotic\nnepotism\nnepotisms\nnepotist\nnepotistic\nnepotists\nneptunium\nneptuniums\nnerd\nnerdier\nnerdiest\nnerdish\nnerds\nnerdy\nnereid\nnereides\nnereids\nnereis\nnereises\nneritic\nnerol\nneroli\nnerolis\nnerols\nnerts\nnertz\nnervate\nnervation\nnervations\nnerve\nnerved\nnerveless\nnervelessly\nnervelessness\nnervelessnesses\nnerves\nnervier\nnerviest\nnervily\nnervine\nnervines\nnerviness\nnervinesses\nnerving\nnervings\nnervosities\nnervosity\nnervous\nnervously\nnervousness\nnervousnesses\nnervule\nnervules\nnervure\nnervures\nnervy\nnescience\nnesciences\nnescient\nnescients\nness\nnesses\nnest\nnestable\nnested\nnester\nnesters\nnesting\nnestle\nnestled\nnestler\nnestlers\nnestles\nnestlike\nnestling\nnestlings\nnestor\nnestors\nnests\nnet\nnether\nnethermost\nnetherworld\nnetherworlds\nnetiquette\nnetiquettes\nnetizen\nnetizens\nnetless\nnetlike\nnetminder\nnetminders\nnetop\nnetops\nnets\nnetsuke\nnetsukes\nnett\nnettable\nnetted\nnetter\nnetters\nnettier\nnettiest\nnetting\nnettings\nnettle\nnettled\nnettler\nnettlers\nnettles\nnettlesome\nnettlier\nnettliest\nnettling\nnettly\nnetts\nnetty\nnetwork\nnetworked\nnetworking\nnetworkings\nnetworks\nneuk\nneuks\nneum\nneumatic\nneume\nneumes\nneumic\nneums\nneural\nneuralgia\nneuralgias\nneuralgic\nneurally\nneuraminidase\nneuraminidases\nneurasthenia\nneurasthenias\nneurasthenic\nneurasthenically\nneurasthenics\nneuraxon\nneuraxons\nneurilemma\nneurilemmal\nneurilemmas\nneurine\nneurines\nneuritic\nneuritics\nneuritides\nneuritis\nneuritises\nneuroactive\nneuroanatomic\nneuroanatomical\nneuroanatomies\nneuroanatomist\nneuroanatomists\nneuroanatomy\nneurobiological\nneurobiologies\nneurobiologist\nneurobiologists\nneurobiology\nneuroblastoma\nneuroblastomas\nneuroblastomata\nneurochemical\nneurochemicals\nneurochemist\nneurochemistries\nneurochemistry\nneurochemists\nneurodegenerative\nneuroendocrine\nneuroendocrinological\nneuroendocrinologies\nneuroendocrinologist\nneuroendocrinologists\nneuroendocrinology\nneurofibril\nneurofibrillary\nneurofibrils\nneurofibroma\nneurofibromas\nneurofibromata\nneurofibromatoses\nneurofibromatosis\nneurogenic\nneurogenically\nneuroglia\nneuroglial\nneuroglias\nneurohormonal\nneurohormone\nneurohormones\nneurohumor\nneurohumoral\nneurohumors\nneurohypophyseal\nneurohypophyses\nneurohypophysial\nneurohypophysis\nneuroid\nneuroleptic\nneuroleptics\nneurologic\nneurological\nneurologically\nneurologies\nneurologist\nneurologists\nneurology\nneuroma\nneuromas\nneuromata\nneuromuscular\nneuron\nneuronal\nneurone\nneurones\nneuronic\nneurons\nneuropathic\nneuropathically\nneuropathies\nneuropathologic\nneuropathological\nneuropathologies\nneuropathologist\nneuropathologists\nneuropathology\nneuropathy\nneuropeptide\nneuropeptides\nneuropharmacologic\nneuropharmacological\nneuropharmacologies\nneuropharmacologist\nneuropharmacologists\nneuropharmacology\nneurophysiologic\nneurophysiological\nneurophysiologically\nneurophysiologies\nneurophysiologist\nneurophysiologists\nneurophysiology\nneuropsychiatric\nneuropsychiatrically\nneuropsychiatries\nneuropsychiatrist\nneuropsychiatrists\nneuropsychiatry\nneuropsychological\nneuropsychologies\nneuropsychologist\nneuropsychologists\nneuropsychology\nneuropteran\nneuropterans\nneuropterous\nneuroradiological\nneuroradiologies\nneuroradiologist\nneuroradiologists\nneuroradiology\nneurosal\nneuroscience\nneurosciences\nneuroscientific\nneuroscientist\nneuroscientists\nneurosecretion\nneurosecretions\nneurosecretory\nneurosensory\nneuroses\nneurosis\nneurospora\nneurosporas\nneurosurgeon\nneurosurgeons\nneurosurgeries\nneurosurgery\nneurosurgical\nneurotic\nneurotically\nneuroticism\nneuroticisms\nneurotics\nneurotoxic\nneurotoxicities\nneurotoxicity\nneurotoxin\nneurotoxins\nneurotransmission\nneurotransmissions\nneurotransmitter\nneurotransmitters\nneurotropic\nneurula\nneurulae\nneurulas\nneurulation\nneurulations\nneuston\nneustons\nneuter\nneutered\nneutering\nneuters\nneutral\nneutralise\nneutralised\nneutralises\nneutralising\nneutralism\nneutralisms\nneutralist\nneutralistic\nneutralists\nneutralities\nneutrality\nneutralization\nneutralizations\nneutralize\nneutralized\nneutralizer\nneutralizers\nneutralizes\nneutralizing\nneutrally\nneutralness\nneutralnesses\nneutrals\nneutrino\nneutrinoless\nneutrinos\nneutron\nneutronic\nneutrons\nneutrophil\nneutrophilic\nneutrophils\nneve\nnever\nnevermore\nnevertheless\nneves\nnevi\nnevoid\nnevus\nnew\nnewbie\nnewbies\nnewborn\nnewborns\nnewcomer\nnewcomers\nnewel\nnewels\nnewer\nnewest\nnewfangled\nnewfangledness\nnewfanglednesses\nnewfound\nnewie\nnewies\nnewish\nnewly\nnewlywed\nnewlyweds\nnewmarket\nnewmarkets\nnewmown\nnewness\nnewnesses\nnews\nnewsagent\nnewsagents\nnewsboy\nnewsboys\nnewsbreak\nnewsbreaks\nnewscast\nnewscaster\nnewscasters\nnewscasts\nnewsdealer\nnewsdealers\nnewsgroup\nnewsgroups\nnewshawk\nnewshawks\nnewshound\nnewshounds\nnewsie\nnewsier\nnewsies\nnewsiest\nnewsiness\nnewsinesses\nnewsless\nnewsletter\nnewsletters\nnewsmagazine\nnewsmagazines\nnewsmaker\nnewsmakers\nnewsman\nnewsmen\nnewsmonger\nnewsmongers\nnewspaper\nnewspapered\nnewspapering\nnewspaperman\nnewspapermen\nnewspapers\nnewspaperwoman\nnewspaperwomen\nnewspeak\nnewspeaks\nnewspeople\nnewsperson\nnewspersons\nnewsprint\nnewsprints\nnewsreader\nnewsreaders\nnewsreel\nnewsreels\nnewsroom\nnewsrooms\nnewsstand\nnewsstands\nnewsweeklies\nnewsweekly\nnewswoman\nnewswomen\nnewsworthiness\nnewsworthinesses\nnewsworthy\nnewswriting\nnewswritings\nnewsy\nnewt\nnewton\nnewtons\nnewts\nnext\nnextdoor\nnexus\nnexuses\nngultrum\nngultrums\nngwee\nniacin\nniacinamide\nniacinamides\nniacins\nnialamide\nnialamides\nnib\nnibbed\nnibbing\nnibble\nnibbled\nnibbler\nnibblers\nnibbles\nnibbling\nniblick\nniblicks\nniblike\nnibs\nnicad\nnicads\nniccolite\nniccolites\nnice\nnicely\nniceness\nnicenesses\nnicer\nnicest\nniceties\nnicety\nniche\nniched\nniches\nniching\nnick\nnicked\nnickel\nnickeled\nnickelic\nnickeliferous\nnickeling\nnickelled\nnickelling\nnickelodeon\nnickelodeons\nnickels\nnicker\nnickered\nnickering\nnickers\nnicking\nnickle\nnickled\nnickles\nnickling\nnicknack\nnicknacks\nnickname\nnicknamed\nnicknamer\nnicknamers\nnicknames\nnicknaming\nnicks\nnicol\nnicols\nnicotiana\nnicotianas\nnicotin\nnicotinamide\nnicotinamides\nnicotine\nnicotines\nnicotinic\nnicotins\nnictate\nnictated\nnictates\nnictating\nnictitate\nnictitated\nnictitates\nnictitating\nnidal\nnide\nnided\nnidering\nniderings\nnides\nnidget\nnidgets\nnidi\nnidicolous\nnidification\nnidifications\nnidified\nnidifies\nnidifugous\nnidify\nnidifying\nniding\nnidus\nniduses\nniece\nnieces\nnielli\nniellist\nniellists\nniello\nnielloed\nnielloing\nniellos\nnieve\nnieves\nnifedipine\nnifedipines\nniffer\nniffered\nniffering\nniffers\nniftier\nnifties\nniftiest\nniftily\nnifty\nniggard\nniggarded\nniggarding\nniggardliness\nniggardlinesses\nniggardly\nniggards\nnigger\nniggers\nniggle\nniggled\nniggler\nnigglers\nniggles\nniggling\nnigglingly\nnigglings\nnigh\nnighed\nnigher\nnighest\nnighing\nnighness\nnighnesses\nnighs\nnight\nnightcap\nnightcaps\nnightclothes\nnightclub\nnightclubbed\nnightclubber\nnightclubbers\nnightclubbing\nnightclubs\nnightdress\nnightdresses\nnightfall\nnightfalls\nnightglow\nnightglows\nnightgown\nnightgowns\nnighthawk\nnighthawks\nnightie\nnighties\nnightingale\nnightingales\nnightjar\nnightjars\nnightless\nnightlife\nnightlifes\nnightlong\nnightly\nnightmare\nnightmares\nnightmarish\nnightmarishly\nnights\nnightscope\nnightscopes\nnightshade\nnightshades\nnightshirt\nnightshirts\nnightside\nnightsides\nnightspot\nnightspots\nnightstand\nnightstands\nnightstick\nnightsticks\nnighttime\nnighttimes\nnightwalker\nnightwalkers\nnightwear\nnighty\nnigrified\nnigrifies\nnigrify\nnigrifying\nnigrosin\nnigrosins\nnihil\nnihilism\nnihilisms\nnihilist\nnihilistic\nnihilists\nnihilities\nnihility\nnihils\nnil\nnilgai\nnilgais\nnilgau\nnilgaus\nnilghai\nnilghais\nnilghau\nnilghaus\nnill\nnilled\nnilling\nnills\nnilpotent\nnils\nnim\nnimbi\nnimble\nnimbleness\nnimblenesses\nnimbler\nnimblest\nnimbly\nnimbostrati\nnimbostratus\nnimbus\nnimbused\nnimbuses\nnimieties\nnimiety\nnimious\nnimmed\nnimming\nnimrod\nnimrods\nnims\nnincompoop\nnincompooperies\nnincompoopery\nnincompoops\nnine\nninebark\nninebarks\nninefold\nninepin\nninepins\nnines\nnineteen\nnineteens\nnineteenth\nnineteenths\nnineties\nninetieth\nninetieths\nninety\nninhydrin\nninhydrins\nninja\nninjas\nninnies\nninny\nninnyhammer\nninnyhammers\nninnyish\nninon\nninons\nninth\nninthly\nninths\nniobate\nniobates\nniobic\nniobium\nniobiums\nniobous\nnip\nnipa\nnipas\nnipped\nnipper\nnippers\nnippier\nnippiest\nnippily\nnippiness\nnippinesses\nnipping\nnippingly\nnipple\nnippled\nnipples\nnippy\nnips\nnirvana\nnirvanas\nnirvanic\nnisei\nniseis\nnisi\nnisus\nnit\nnitchie\nnitchies\nnite\nniter\nniterie\nniteries\nniters\nnitery\nnites\nnitid\nnitinol\nnitinols\nniton\nnitons\nnitpick\nnitpicked\nnitpicker\nnitpickers\nnitpickier\nnitpickiest\nnitpicking\nnitpicks\nnitpicky\nnitrate\nnitrated\nnitrates\nnitrating\nnitration\nnitrations\nnitrator\nnitrators\nnitre\nnitres\nnitric\nnitrid\nnitride\nnitrided\nnitrides\nnitriding\nnitrids\nnitrification\nnitrifications\nnitrified\nnitrifier\nnitrifiers\nnitrifies\nnitrify\nnitrifying\nnitril\nnitrile\nnitriles\nnitrils\nnitrite\nnitrites\nnitro\nnitrobenzene\nnitrobenzenes\nnitrocellulose\nnitrocelluloses\nnitrofuran\nnitrofurans\nnitrogen\nnitrogenase\nnitrogenases\nnitrogenous\nnitrogens\nnitroglycerin\nnitroglycerine\nnitroglycerines\nnitroglycerins\nnitrolic\nnitromethane\nnitromethanes\nnitroparaffin\nnitroparaffins\nnitros\nnitrosamine\nnitrosamines\nnitroso\nnitrosyl\nnitrosyls\nnitrous\nnits\nnittier\nnittiest\nnitty\nnitwit\nnitwits\nnival\nniveous\nnix\nnixe\nnixed\nnixes\nnixie\nnixies\nnixing\nnixy\nnizam\nnizamate\nnizamates\nnizams\nno\nnob\nnobbier\nnobbiest\nnobbily\nnobble\nnobbled\nnobbler\nnobblers\nnobbles\nnobbling\nnobby\nnobelium\nnobeliums\nnobilities\nnobility\nnoble\nnobleman\nnoblemen\nnobleness\nnoblenesses\nnobler\nnobles\nnoblesse\nnoblesses\nnoblest\nnoblewoman\nnoblewomen\nnobly\nnobodies\nnobody\nnobs\nnocent\nnociceptive\nnock\nnocked\nnocking\nnocks\nnoctambulist\nnoctambulists\nnoctuid\nnoctuids\nnoctule\nnoctules\nnoctuoid\nnocturn\nnocturnal\nnocturnally\nnocturne\nnocturnes\nnocturns\nnocuous\nnocuously\nnod\nnodal\nnodalities\nnodality\nnodally\nnodded\nnodder\nnodders\nnoddies\nnodding\nnoddle\nnoddled\nnoddles\nnoddling\nnoddy\nnode\nnodes\nnodi\nnodical\nnodose\nnodosities\nnodosity\nnodous\nnods\nnodular\nnodulation\nnodulations\nnodule\nnodules\nnodulose\nnodulous\nnodus\nnoel\nnoels\nnoes\nnoesis\nnoesises\nnoetic\nnog\nnogg\nnogged\nnoggin\nnogging\nnoggings\nnoggins\nnoggs\nnogs\nnoh\nnohow\nnoil\nnoils\nnoily\nnoir\nnoirish\nnoirs\nnoise\nnoised\nnoiseless\nnoiselessly\nnoisemaker\nnoisemakers\nnoisemaking\nnoisemakings\nnoises\nnoisette\nnoisettes\nnoisier\nnoisiest\nnoisily\nnoisiness\nnoisinesses\nnoising\nnoisome\nnoisomely\nnoisomeness\nnoisomenesses\nnoisy\nnolo\nnolos\nnom\nnoma\nnomad\nnomadic\nnomadism\nnomadisms\nnomads\nnomarch\nnomarchies\nnomarchs\nnomarchy\nnomas\nnombles\nnombril\nnombrils\nnome\nnomen\nnomenclator\nnomenclatorial\nnomenclators\nnomenclatural\nnomenclature\nnomenclatures\nnomes\nnomina\nnominal\nnominalism\nnominalisms\nnominalist\nnominalistic\nnominalists\nnominally\nnominals\nnominate\nnominated\nnominates\nnominating\nnomination\nnominations\nnominative\nnominatives\nnominator\nnominators\nnominee\nnominees\nnomism\nnomisms\nnomistic\nnomogram\nnomograms\nnomograph\nnomographic\nnomographies\nnomographs\nnomography\nnomoi\nnomological\nnomologies\nnomology\nnomos\nnomothetic\nnoms\nnona\nnonabrasive\nnonabsorbable\nnonabsorbent\nnonabsorbents\nnonabsorptive\nnonabstract\nnonabstracts\nnonacademic\nnonacademics\nnonacceptance\nnonacceptances\nnonaccountable\nnonaccredited\nnonaccrual\nnonachievement\nnonachievements\nnonacid\nnonacidic\nnonacids\nnonacquisitive\nnonacting\nnonaction\nnonactions\nnonactivated\nnonactor\nnonactors\nnonadaptive\nnonaddict\nnonaddictive\nnonaddicts\nnonadditive\nnonadditivities\nnonadditivity\nnonadhesive\nnonadiabatic\nnonadjacent\nnonadmirer\nnonadmirers\nnonadmission\nnonadmissions\nnonadult\nnonadults\nnonaesthetic\nnonaffiliated\nnonaffluent\nnonage\nnonagenarian\nnonagenarians\nnonages\nnonaggression\nnonaggressions\nnonaggressive\nnonagon\nnonagons\nnonagricultural\nnonalcoholic\nnonalcoholics\nnonaligned\nnonalignment\nnonalignments\nnonallelic\nnonallergenic\nnonallergic\nnonalphabetic\nnonaluminum\nnonambiguous\nnonanalytic\nnonanatomic\nnonanimal\nnonanswer\nnonanswers\nnonantagonistic\nnonanthropological\nnonanthropologist\nnonanthropologists\nnonantibiotic\nnonantibiotics\nnonantigenic\nnonappearance\nnonappearances\nnonaquatic\nnonaqueous\nnonarable\nnonarbitrariness\nnonarbitrarinesses\nnonarbitrary\nnonarchitect\nnonarchitects\nnonarchitecture\nnonarchitectures\nnonargument\nnonarguments\nnonaristocratic\nnonaromatic\nnonart\nnonartist\nnonartistic\nnonartists\nnonarts\nnonas\nnonascetic\nnonascetics\nnonaspirin\nnonaspirins\nnonassertive\nnonassociated\nnonastronomical\nnonathlete\nnonathletes\nnonathletic\nnonatomic\nnonattached\nnonattachment\nnonattachments\nnonattendance\nnonattendances\nnonattender\nnonattenders\nnonauditory\nnonauthor\nnonauthoritarian\nnonauthors\nnonautomated\nnonautomatic\nnonautomotive\nnonautonomous\nnonavailabilities\nnonavailability\nnonbacterial\nnonbank\nnonbanking\nnonbanks\nnonbarbiturate\nnonbarbiturates\nnonbasic\nnonbearing\nnonbehavioral\nnonbeing\nnonbeings\nnonbelief\nnonbeliefs\nnonbeliever\nnonbelievers\nnonbelligerencies\nnonbelligerency\nnonbelligerent\nnonbelligerents\nnonbetting\nnonbibliographic\nnonbinary\nnonbinding\nnonbiodegradable\nnonbiodegradables\nnonbiographical\nnonbiological\nnonbiologically\nnonbiologist\nnonbiologists\nnonbiting\nnonblack\nnonblacks\nnonbodies\nnonbody\nnonbonded\nnonbonding\nnonbook\nnonbooks\nnonbotanist\nnonbotanists\nnonbrand\nnonbreakable\nnonbreathing\nnonbreeder\nnonbreeders\nnonbreeding\nnonbreedings\nnonbroadcast\nnonbroadcasts\nnonbuilding\nnonbuildings\nnonburnable\nnonbusiness\nnonbuying\nnoncabinet\nnoncabinets\nnoncaking\nnoncallable\nnoncaloric\nnoncampus\nnoncancelable\nnoncancerous\nnoncandidacies\nnoncandidacy\nnoncandidate\nnoncandidates\nnoncannibalistic\nnoncapital\nnoncapitalist\nnoncapitalists\nnoncapitals\nnoncarcinogen\nnoncarcinogenic\nnoncarcinogens\nnoncardiac\nnoncareer\nnoncarrier\nnoncarriers\nnoncash\nnoncasual\nnoncausal\nnonce\nnoncelebration\nnoncelebrations\nnoncelebrities\nnoncelebrity\nnoncellular\nnoncellulosic\nnoncentral\nnoncertificated\nnoncertified\nnonces\nnonchalance\nnonchalances\nnonchalant\nnonchalantly\nnoncharacter\nnoncharacters\nnoncharismatic\nnonchauvinist\nnonchauvinists\nnonchemical\nnonchemicals\nnonchromosomal\nnonchronological\nnonchurch\nnonchurchgoer\nnonchurchgoers\nnoncircular\nnoncirculating\nnoncitizen\nnoncitizens\nnonclandestine\nnonclass\nnonclasses\nnonclassical\nnonclassified\nnonclassroom\nnonclassrooms\nnonclerical\nnonclericals\nnoncling\nnonclinical\nnonclogging\nnoncoercive\nnoncognitive\nnoncoherent\nnoncoincidence\nnoncoincidences\nnoncoital\nnoncoking\nnoncola\nnoncollector\nnoncollectors\nnoncollege\nnoncolleges\nnoncollegiate\nnoncollinear\nnoncolor\nnoncolored\nnoncolorfast\nnoncolors\nnoncom\nnoncombat\nnoncombatant\nnoncombatants\nnoncombative\nnoncombustible\nnoncombustibles\nnoncommercial\nnoncommercials\nnoncommitment\nnoncommitments\nnoncommittal\nnoncommittally\nnoncommitted\nnoncommunicating\nnoncommunication\nnoncommunications\nnoncommunicative\nnoncommunist\nnoncommunists\nnoncommunities\nnoncommunity\nnoncommutative\nnoncommutativities\nnoncommutativity\nnoncomparabilities\nnoncomparability\nnoncomparable\nnoncompatible\nnoncompetition\nnoncompetitive\nnoncompetitor\nnoncompetitors\nnoncomplementary\nnoncomplex\nnoncompliance\nnoncompliances\nnoncompliant\nnoncomplicated\nnoncomplying\nnoncomplyings\nnoncomposer\nnoncomposers\nnoncompound\nnoncompounds\nnoncomprehension\nnoncomprehensions\nnoncompressible\nnoncomputer\nnoncomputerized\nnoncoms\nnonconceptual\nnonconcern\nnonconcerns\nnonconclusion\nnonconclusions\nnonconcur\nnonconcurred\nnonconcurrence\nnonconcurrences\nnonconcurrent\nnonconcurring\nnonconcurs\nnoncondensable\nnonconditioned\nnonconducting\nnonconduction\nnonconductions\nnonconductive\nnonconductor\nnonconductors\nnonconference\nnonconferences\nnonconfidence\nnonconfidences\nnonconfidential\nnonconflicting\nnonconform\nnonconformance\nnonconformances\nnonconformed\nnonconformer\nnonconformers\nnonconforming\nnonconformism\nnonconformisms\nnonconformist\nnonconformists\nnonconformities\nnonconformity\nnonconforms\nnonconfrontation\nnonconfrontational\nnonconfrontations\nnoncongruent\nnonconjugated\nnonconnection\nnonconnections\nnonconscious\nnonconsecutive\nnonconsensual\nnonconservation\nnonconservations\nnonconservative\nnonconservatives\nnonconsolidated\nnonconstant\nnonconstants\nnonconstitutional\nnonconstruction\nnonconstructions\nnonconstructive\nnonconsumer\nnonconsumers\nnonconsuming\nnonconsumption\nnonconsumptions\nnonconsumptive\nnoncontact\nnoncontacts\nnoncontagious\nnoncontemporaries\nnoncontemporary\nnoncontiguous\nnoncontingent\nnoncontinuous\nnoncontract\nnoncontractual\nnoncontradiction\nnoncontradictions\nnoncontradictory\nnoncontributory\nnoncontrollable\nnoncontrolled\nnoncontrolling\nnoncontroversial\nnonconventional\nnonconvertible\nnoncooperation\nnoncooperationist\nnoncooperationists\nnoncooperations\nnoncooperative\nnoncooperator\nnoncooperators\nnoncoplanar\nnoncorporate\nnoncorrelation\nnoncorrelations\nnoncorrodible\nnoncorroding\nnoncorrodings\nnoncorrosive\nnoncountries\nnoncountry\nnoncounty\nnoncoverage\nnoncoverages\nnoncreative\nnoncreativities\nnoncreativity\nnoncredentialed\nnoncredit\nnoncrime\nnoncrimes\nnoncriminal\nnoncriminals\nnoncrises\nnoncrisis\nnoncritical\nnoncrossover\nnoncrushable\nnoncrystalline\nnonculinary\nnoncultivated\nnoncultivation\nnoncultivations\nnoncultural\nnoncumulative\nnoncurrent\nnoncustodial\nnoncustomer\nnoncustomers\nnoncyclic\nnoncyclical\nnondairy\nnondance\nnondancer\nnondancers\nnondances\nnondeceptive\nnondecision\nnondecisions\nnondecreasing\nnondeductibilities\nnondeductibility\nnondeductible\nnondeductive\nnondefense\nnondeferrable\nnondeforming\nnondegenerate\nnondegenerates\nnondegradable\nnondegradables\nnondegree\nnondelegate\nnondelegates\nnondeliberate\nnondelinquent\nnondeliveries\nnondelivery\nnondemanding\nnondemocratic\nnondenominational\nnondenominationalism\nnondenominationalisms\nnondepartmental\nnondependent\nnondependents\nnondepletable\nnondepleting\nnondeposition\nnondepositions\nnondepressed\nnonderivative\nnonderivatives\nnondescript\nnondescriptive\nnondescripts\nnondesert\nnondestructive\nnondestructively\nnondestructiveness\nnondestructivenesses\nnondetachable\nnondeterministic\nnondevelopment\nnondevelopments\nnondeviant\nnondeviants\nnondiabetic\nnondiabetics\nnondialyzable\nnondiapausing\nnondidactic\nnondiffusible\nnondimensional\nnondiplomatic\nnondirected\nnondirectional\nnondirective\nnondisabled\nnondisableds\nnondisclosure\nnondisclosures\nnondiscount\nnondiscretionary\nnondiscrimination\nnondiscriminations\nnondiscriminatory\nnondiscursive\nnondisjunction\nnondisjunctional\nnondisjunctions\nnondispersive\nnondisruptive\nnondistinctive\nnondiversified\nnondividing\nnondoctor\nnondoctors\nnondoctrinaire\nnondocumentaries\nnondocumentary\nnondogmatic\nnondollar\nnondomestic\nnondomestics\nnondominant\nnondominants\nnondormant\nnondramatic\nnondrinker\nnondrinkers\nnondrinking\nnondriver\nnondrivers\nnondrug\nnondurable\nnondurables\nnone\nnonearning\nnonearnings\nnonecclesiastical\nnoneconomic\nnoneconomist\nnoneconomists\nnonedible\nnoneditorial\nnoneducation\nnoneducational\nnoneducations\nnoneffective\nnoneffectives\nnonego\nnonegos\nnonelastic\nnonelect\nnonelected\nnonelection\nnonelections\nnonelective\nnonelectives\nnonelectric\nnonelectrical\nnonelectrics\nnonelectrolyte\nnonelectrolytes\nnonelectronic\nnonelectronics\nnonelementary\nnonelite\nnonemergencies\nnonemergency\nnonemotional\nnonemphatic\nnonempirical\nnonemployee\nnonemployees\nnonemployment\nnonemployments\nnonempty\nnonencapsulated\nnonending\nnonenergy\nnonenforceabilities\nnonenforceability\nnonenforcement\nnonenforcements\nnonengagement\nnonengagements\nnonengineering\nnonengineerings\nnonentertainment\nnonentertainments\nnonentities\nnonentity\nnonentries\nnonentry\nnonenzymatic\nnonenzymic\nnonequal\nnonequals\nnonequilibria\nnonequilibrium\nnonequilibriums\nnonequivalence\nnonequivalences\nnonequivalent\nnonequivalents\nnonerotic\nnones\nnonessential\nnonessentials\nnonestablished\nnonestablishment\nnonestablishments\nnonesterified\nnonesuch\nnonesuches\nnonet\nnonetheless\nnonethical\nnonethnic\nnonets\nnonevaluative\nnonevent\nnonevents\nnonevidence\nnonevidences\nnonexclusive\nnonexecutive\nnonexecutives\nnonexempt\nnonexistence\nnonexistences\nnonexistent\nnonexistential\nnonexotic\nnonexpendable\nnonexperimental\nnonexpert\nnonexperts\nnonexplanatory\nnonexploitation\nnonexploitations\nnonexploitative\nnonexploitive\nnonexplosive\nnonexplosives\nnonexposed\nnonextant\nnonfact\nnonfactor\nnonfactors\nnonfacts\nnonfactual\nnonfaculty\nnonfading\nnonfamilial\nnonfamilies\nnonfamily\nnonfan\nnonfans\nnonfarm\nnonfarmer\nnonfarmers\nnonfat\nnonfatal\nnonfattening\nnonfatty\nnonfeasance\nnonfeasances\nnonfederal\nnonfederated\nnonfeminist\nnonfeminists\nnonferrous\nnonfiction\nnonfictional\nnonfictions\nnonfigurative\nnonfilamentous\nnonfilterable\nnonfinal\nnonfinancial\nnonfinite\nnonfissionable\nnonflammabilities\nnonflammability\nnonflammable\nnonflowering\nnonfluencies\nnonfluency\nnonfluid\nnonfluids\nnonfluorescent\nnonflying\nnonfocal\nnonfood\nnonforfeitable\nnonforfeiture\nnonforfeitures\nnonformal\nnonfossil\nnonfraternization\nnonfraternizations\nnonfreezing\nnonfrivolous\nnonfrozen\nnonfuel\nnonfulfillment\nnonfulfillments\nnonfunctional\nnonfunctioning\nnongame\nnongaseous\nnongay\nnongays\nnongenetic\nnongenital\nnongeometrical\nnonghetto\nnonglamorous\nnonglare\nnongolfer\nnongolfers\nnongonococcal\nnongovernment\nnongovernmental\nnongovernments\nnongraded\nnongraduate\nnongraduates\nnongrammatical\nnongranular\nnongravitational\nnongreasy\nnongreen\nnongregarious\nnongrowing\nnongrowth\nnonguest\nnonguests\nnonguilt\nnonguilts\nnonhalogenated\nnonhandicapped\nnonhappening\nnonhappenings\nnonhardy\nnonharmonic\nnonhazardous\nnonheme\nnonhemolytic\nnonhereditary\nnonhero\nnonheroes\nnonhierarchical\nnonhistone\nnonhistorical\nnonhome\nnonhomogeneous\nnonhomologous\nnonhomosexual\nnonhomosexuals\nnonhormonal\nnonhospital\nnonhospitalized\nnonhospitals\nnonhostile\nnonhousing\nnonhousings\nnonhuman\nnonhunter\nnonhunters\nnonhunting\nnonhygroscopic\nnonhysterical\nnonideal\nnonidentical\nnonidentities\nnonidentity\nnonideological\nnonillion\nnonillions\nnonimage\nnonimitative\nnonimmigrant\nnonimmigrants\nnonimmune\nnonimpact\nnonimplication\nnonimplications\nnonimportation\nnonimportations\nnoninclusion\nnoninclusions\nnonincreasing\nnonincumbent\nnonincumbents\nnonindependence\nnonindependences\nnonindigenous\nnonindividual\nnoninductive\nnonindustrial\nnonindustrialized\nnonindustry\nnoninfected\nnoninfectious\nnoninfective\nnoninfested\nnoninflammable\nnoninflammatory\nnoninflationary\nnoninflectional\nnoninfluence\nnoninfluences\nnoninformation\nnoninformations\nnoninitial\nnoninitiate\nnoninitiates\nnoninjury\nnoninsect\nnoninsecticidal\nnoninsects\nnoninstallment\nnoninstitutional\nnoninstitutionalized\nnoninstructional\nnoninstrumental\nnoninsurance\nnoninsurances\nnoninsured\nnonintegral\nnonintegrated\nnonintellectual\nnonintellectuals\nnoninteracting\nnoninteractive\nnoninterchangeable\nnonintercourse\nnonintercourses\nnoninterest\nnoninterests\nnoninterference\nnoninterferences\nnonintersecting\nnonintervention\nnoninterventionist\nnoninterventionists\nnoninterventions\nnonintimidating\nnonintoxicant\nnonintoxicating\nnonintrusive\nnonintuitive\nnoninvasive\nnoninvolved\nnoninvolvement\nnoninvolvements\nnonionic\nnonionizing\nnoniron\nnonirradiated\nnonirrigated\nnonirritant\nnonirritating\nnonissue\nnonissues\nnonjoinder\nnonjoinders\nnonjoiner\nnonjoiners\nnonjudgmental\nnonjudicial\nnonjuring\nnonjuror\nnonjurors\nnonjury\nnonjusticiable\nnonkosher\nnonlabor\nnonlandowner\nnonlandowners\nnonlanguage\nnonlanguages\nnonlawyer\nnonlawyers\nnonleaded\nnonleafy\nnonleague\nnonlegal\nnonlegume\nnonlegumes\nnonleguminous\nnonlethal\nnonlexical\nnonlibrarian\nnonlibrarians\nnonlibraries\nnonlibrary\nnonlife\nnonlineal\nnonlinear\nnonlinearities\nnonlinearity\nnonlinguistic\nnonliquid\nnonliquids\nnonliteral\nnonliterary\nnonliterate\nnonliterates\nnonlives\nnonliving\nnonlocal\nnonlocals\nnonlogical\nnonluminous\nnonmagnetic\nnonmainstream\nnonmajor\nnonmajors\nnonmalignant\nnonmalleable\nnonman\nnonmanagement\nnonmanagements\nnonmanagerial\nnonmanual\nnonmanufacturing\nnonmanufacturings\nnonmarital\nnonmarket\nnonmaterial\nnonmaterialistic\nnonmathematical\nnonmathematician\nnonmathematicians\nnonmatriculated\nnonmeaningful\nnonmeasurable\nnonmeat\nnonmechanical\nnonmechanistic\nnonmedical\nnonmeeting\nnonmeetings\nnonmember\nnonmembers\nnonmembership\nnonmemberships\nnonmen\nnonmental\nnonmercurial\nnonmetal\nnonmetallic\nnonmetals\nnonmetameric\nnonmetaphorical\nnonmetric\nnonmetrical\nnonmetro\nnonmetropolitan\nnonmetropolitans\nnonmicrobial\nnonmigrant\nnonmigrants\nnonmigratory\nnonmilitant\nnonmilitants\nnonmilitary\nnonmimetic\nnonminority\nnonmobile\nnonmodal\nnonmolecular\nnonmonetarist\nnonmonetarists\nnonmonetary\nnonmoney\nnonmonogamous\nnonmoral\nnonmotile\nnonmotilities\nnonmotility\nnonmotorized\nnonmoving\nnonmunicipal\nnonmusic\nnonmusical\nnonmusician\nnonmusicians\nnonmusics\nnonmutant\nnonmutants\nnonmyelinated\nnonmystical\nnonnarrative\nnonnarratives\nnonnational\nnonnationals\nnonnative\nnonnatives\nnonnatural\nnonnaval\nnonnecessities\nnonnecessity\nnonnegative\nnonnegligent\nnonnegotiable\nnonnetwork\nnonnews\nnonnitrogenous\nnonnormative\nnonnovel\nnonnovels\nnonnuclear\nnonnucleated\nnonnumerical\nnonnumericals\nnonnutritious\nnonnutritive\nnonobese\nnonobjective\nnonobjectivism\nnonobjectivisms\nnonobjectivist\nnonobjectivists\nnonobjectivities\nnonobjectivity\nnonobligatory\nnonobscene\nnonobservance\nnonobservances\nnonobservant\nnonobvious\nnonoccupational\nnonoccurrence\nnonoccurrences\nnonofficial\nnonohmic\nnonoily\nnonoperatic\nnonoperating\nnonoperational\nnonoperative\nnonoptimal\nnonorganic\nnonorgasmic\nnonorthodox\nnonoverlapping\nnonoverlappings\nnonowner\nnonowners\nnonoxidizing\nnonpagan\nnonpagans\nnonpaid\nnonpapal\nnonpar\nnonparallel\nnonparallels\nnonparametric\nnonparasitic\nnonpareil\nnonpareils\nnonparticipant\nnonparticipants\nnonparticipating\nnonparticipation\nnonparticipations\nnonparticipatory\nnonpartisan\nnonpartisans\nnonpartisanship\nnonpartisanships\nnonparty\nnonpasserine\nnonpassive\nnonpast\nnonpasts\nnonpathogenic\nnonpaying\nnonpayment\nnonpayments\nnonpeak\nnonperformance\nnonperformances\nnonperformer\nnonperformers\nnonperforming\nnonperishable\nnonperishables\nnonpermissive\nnonpersistent\nnonperson\nnonpersonal\nnonpersons\nnonpetroleum\nnonpetroleums\nnonphilosopher\nnonphilosophers\nnonphilosophical\nnonphonemic\nnonphonetic\nnonphosphate\nnonphosphates\nnonphotographic\nnonphysical\nnonphysician\nnonphysicians\nnonplanar\nnonplastic\nnonplastics\nnonplay\nnonplaying\nnonplays\nnonplus\nnonplused\nnonpluses\nnonplusing\nnonplussed\nnonplusses\nnonplussing\nnonpoetic\nnonpoint\nnonpoisonous\nnonpolar\nnonpolarizable\nnonpolice\nnonpolitical\nnonpolitically\nnonpolitician\nnonpoliticians\nnonpolluting\nnonpoor\nnonporous\nnonpossession\nnonpossessions\nnonpractical\nnonpracticing\nnonpreferential\nnonpregnant\nnonprescription\nnonprint\nnonproblem\nnonproblems\nnonproducing\nnonproductive\nnonproductiveness\nnonproductivenesses\nnonprofessional\nnonprofessionally\nnonprofessionals\nnonprofessorial\nnonprofit\nnonprofits\nnonprogram\nnonprogrammer\nnonprogrammers\nnonprograms\nnonprogressive\nnonprogressives\nnonproliferation\nnonproliferations\nnonproprietaries\nnonproprietary\nnonpros\nnonprossed\nnonprosses\nnonprossing\nnonprotein\nnonpsychiatric\nnonpsychiatrist\nnonpsychiatrists\nnonpsychological\nnonpsychotic\nnonpublic\nnonpunitive\nnonpurposive\nnonquantifiable\nnonquantitative\nnonquota\nnonracial\nnonracially\nnonradioactive\nnonrailroad\nnonrandom\nnonrandomness\nnonrandomnesses\nnonrated\nnonrational\nnonreactive\nnonreactor\nnonreactors\nnonreader\nnonreaders\nnonreading\nnonrealistic\nnonreappointment\nnonreappointments\nnonreceipt\nnonreceipts\nnonreciprocal\nnonreciprocals\nnonrecognition\nnonrecognitions\nnonrecombinant\nnonrecombinants\nnonrecourse\nnonrecurrent\nnonrecurring\nnonrecyclable\nnonrecyclables\nnonreducing\nnonredundant\nnonrefillable\nnonreflecting\nnonrefundable\nnonregulated\nnonregulation\nnonregulations\nnonrelative\nnonrelatives\nnonrelativistic\nnonrelativistically\nnonrelevant\nnonreligious\nnonrenewable\nnonrenewal\nnonrenewals\nnonrepayable\nnonrepresentational\nnonrepresentationalism\nnonrepresentationalisms\nnonrepresentative\nnonrepresentatives\nnonreproducible\nnonreproductive\nnonresidence\nnonresidences\nnonresidencies\nnonresidency\nnonresident\nnonresidential\nnonresidents\nnonresistance\nnonresistances\nnonresistant\nnonresistants\nnonresonant\nnonrespondent\nnonrespondents\nnonresponder\nnonresponders\nnonresponse\nnonresponses\nnonresponsive\nnonrestricted\nnonrestrictive\nnonretractile\nnonretroactive\nnonreturnable\nnonreturnables\nnonreusable\nnonreusables\nnonreversible\nnonrevolutionaries\nnonrevolutionary\nnonrigid\nnonrioter\nnonrioters\nnonrioting\nnonrival\nnonrivals\nnonrotating\nnonroutine\nnonroutines\nnonroyal\nnonrubber\nnonruling\nnonruminant\nnonruminants\nnonrural\nnonsalable\nnonsaline\nnonsaponifiable\nnonscheduled\nnonschizophrenic\nnonschool\nnonscience\nnonsciences\nnonscientific\nnonscientist\nnonscientists\nnonseasonal\nnonsecretor\nnonsecretories\nnonsecretors\nnonsecretory\nnonsectarian\nnonsecure\nnonsedimentable\nnonsegregated\nnonsegregation\nnonsegregations\nnonselected\nnonselective\nnonself\nnonselves\nnonsensational\nnonsense\nnonsenses\nnonsensical\nnonsensically\nnonsensicalness\nnonsensicalnesses\nnonsensitive\nnonsensuous\nnonsentence\nnonsentences\nnonseptate\nnonsequential\nnonserious\nnonsexist\nnonsexual\nnonshrink\nnonshrinkable\nnonsigner\nnonsigners\nnonsignificant\nnonsignificantly\nnonsimultaneous\nnonsinkable\nnonskater\nnonskaters\nnonsked\nnonskeds\nnonskeletal\nnonskid\nnonskier\nnonskiers\nnonslip\nnonsmoker\nnonsmokers\nnonsmoking\nnonsocial\nnonsocialist\nnonsocialists\nnonsolar\nnonsolid\nnonsolids\nnonsolution\nnonsolutions\nnonspatial\nnonspeaker\nnonspeakers\nnonspeaking\nnonspecialist\nnonspecialists\nnonspecific\nnonspecifically\nnonspectacular\nnonspeculative\nnonspeech\nnonspherical\nnonsporting\nnonstandard\nnonstarter\nnonstarters\nnonstationaries\nnonstationary\nnonstatistical\nnonsteady\nnonsteroid\nnonsteroidal\nnonsteroids\nnonstick\nnonstop\nnonstories\nnonstory\nnonstrategic\nnonstructural\nnonstructured\nnonstudent\nnonstudents\nnonstyle\nnonstyles\nnonsubject\nnonsubjective\nnonsubjects\nnonsubsidized\nnonsuccess\nnonsuccesses\nnonsuch\nnonsuches\nnonsugar\nnonsugars\nnonsuit\nnonsuited\nnonsuiting\nnonsuits\nnonsuperimposable\nnonsupervisory\nnonsupport\nnonsupports\nnonsurgical\nnonswimmer\nnonswimmers\nnonsyllabic\nnonsymbolic\nnonsymmetric\nnonsymmetrical\nnonsynchronous\nnonsystem\nnonsystematic\nnonsystemic\nnonsystems\nnontarget\nnontariff\nnontax\nnontaxable\nnontaxables\nnontaxes\nnonteaching\nnontechnical\nnontemporal\nnontemporals\nnontenured\nnonterminal\nnonterminating\nnontheatrical\nnontheist\nnontheistic\nnontheists\nnontheological\nnontheoretical\nnontherapeutic\nnonthermal\nnonthinking\nnonthinkings\nnonthreatening\nnontidal\nnontitle\nnontobacco\nnontobaccos\nnontonal\nnontotalitarian\nnontoxic\nnontraditional\nnontransferable\nnontreatment\nnontreatments\nnontrivial\nnontropical\nnontrump\nnontruth\nnontruths\nnonturbulent\nnontypical\nnonunanimous\nnonuniform\nnonuniformities\nnonuniformity\nnonunion\nnonunionized\nnonunions\nnonunique\nnonuniqueness\nnonuniquenesses\nnonuniversal\nnonuniversals\nnonuniversities\nnonuniversity\nnonuple\nnonuples\nnonurban\nnonurgent\nnonuse\nnonuser\nnonusers\nnonuses\nnonusing\nnonutilitarian\nnonutilitarians\nnonutilities\nnonutility\nnonutopian\nnonvalid\nnonvalidities\nnonvalidity\nnonvanishing\nnonvascular\nnonvector\nnonvectors\nnonvegetarian\nnonvegetarians\nnonvenomous\nnonverbal\nnonverbally\nnonveteran\nnonveterans\nnonviable\nnonviewer\nnonviewers\nnonvintage\nnonviolence\nnonviolences\nnonviolent\nnonviolently\nnonviral\nnonvirgin\nnonvirgins\nnonviscous\nnonvisual\nnonvocal\nnonvocational\nnonvolatile\nnonvolcanic\nnonvoluntary\nnonvoter\nnonvoters\nnonvoting\nnonwar\nnonwars\nnonwhite\nnonwhites\nnonwinning\nnonwoody\nnonword\nnonwords\nnonwork\nnonworker\nnonworkers\nnonworking\nnonwoven\nnonwovens\nnonwriter\nnonwriters\nnonyellowing\nnonyl\nnonyls\nnonzero\nnoo\nnoodge\nnoodged\nnoodges\nnoodging\nnoodle\nnoodled\nnoodles\nnoodling\nnook\nnookies\nnooklike\nnooks\nnooky\nnoon\nnoonday\nnoondays\nnooning\nnoonings\nnoons\nnoontide\nnoontides\nnoontime\nnoontimes\nnoose\nnoosed\nnooser\nnoosers\nnooses\nnoosing\nnoosphere\nnoospheres\nnopal\nnopals\nnope\nnor\nnoradrenalin\nnoradrenaline\nnoradrenalines\nnoradrenalins\nnoradrenergic\nnordic\nnorepinephrine\nnorepinephrines\nnorethindrone\nnorethindrones\nnori\nnoria\nnorias\nnoris\nnorite\nnorites\nnoritic\nnorland\nnorlands\nnorm\nnormal\nnormalcies\nnormalcy\nnormalise\nnormalised\nnormalises\nnormalising\nnormalities\nnormality\nnormalizable\nnormalization\nnormalizations\nnormalize\nnormalized\nnormalizer\nnormalizers\nnormalizes\nnormalizing\nnormally\nnormals\nnormande\nnormative\nnormatively\nnormativeness\nnormativenesses\nnormed\nnormless\nnormotensive\nnormotensives\nnormothermia\nnormothermias\nnormothermic\nnorms\nnorth\nnorthbound\nnortheast\nnortheaster\nnortheasterly\nnortheastern\nnortheasternmost\nnortheasters\nnortheasts\nnortheastward\nnortheastwards\nnorther\nnortherlies\nnortherly\nnorthern\nnortherner\nnortherners\nnorthernmost\nnortherns\nnorthers\nnorthing\nnorthings\nnorthland\nnorthlands\nnorths\nnorthward\nnorthwards\nnorthwest\nnorthwester\nnorthwesterly\nnorthwestern\nnorthwesternmost\nnorthwesters\nnorthwests\nnorthwestward\nnorthwestwards\nnortriptyline\nnortriptylines\nnos\nnose\nnosebag\nnosebags\nnoseband\nnosebands\nnosebleed\nnosebleeds\nnosed\nnosedive\nnosedives\nnosegay\nnosegays\nnoseguard\nnoseguards\nnoseless\nnoselike\nnosepiece\nnosepieces\nnoses\nnosewheel\nnosewheels\nnosey\nnosh\nnoshed\nnosher\nnoshers\nnoshes\nnoshing\nnosier\nnosiest\nnosily\nnosiness\nnosinesses\nnosing\nnosings\nnosocomial\nnosologic\nnosological\nnosologically\nnosologies\nnosology\nnostalgia\nnostalgias\nnostalgic\nnostalgically\nnostalgics\nnostalgist\nnostalgists\nnostoc\nnostocs\nnostril\nnostrils\nnostrum\nnostrums\nnosy\nnot\nnota\nnotabilities\nnotability\nnotable\nnotableness\nnotablenesses\nnotables\nnotably\nnotal\nnotarial\nnotarially\nnotaries\nnotarization\nnotarizations\nnotarize\nnotarized\nnotarizes\nnotarizing\nnotary\nnotate\nnotated\nnotates\nnotating\nnotation\nnotational\nnotations\nnotch\nnotchback\nnotchbacks\nnotched\nnotcher\nnotchers\nnotches\nnotching\nnote\nnotebook\nnotebooks\nnotecase\nnotecases\nnoted\nnotedly\nnotedness\nnotednesses\nnoteless\nnotepad\nnotepads\nnotepaper\nnotepapers\nnoter\nnoters\nnotes\nnoteworthily\nnoteworthiness\nnoteworthinesses\nnoteworthy\nnother\nnothing\nnothingness\nnothingnesses\nnothings\nnotice\nnoticeable\nnoticeably\nnoticed\nnoticer\nnoticers\nnotices\nnoticing\nnotifiable\nnotification\nnotifications\nnotified\nnotifier\nnotifiers\nnotifies\nnotify\nnotifying\nnoting\nnotion\nnotional\nnotionalities\nnotionality\nnotionally\nnotions\nnotochord\nnotochordal\nnotochords\nnotorieties\nnotoriety\nnotorious\nnotoriously\nnotornes\nnotornis\nnotturni\nnotturno\nnotum\nnotwithstanding\nnougat\nnougats\nnought\nnoughts\nnoumena\nnoumenal\nnoumenon\nnoun\nnounal\nnounally\nnounless\nnouns\nnourish\nnourished\nnourisher\nnourishers\nnourishes\nnourishing\nnourishment\nnourishments\nnous\nnouses\nnouveau\nnouvelle\nnova\nnovaculite\nnovaculites\nnovae\nnovalike\nnovas\nnovation\nnovations\nnovel\nnovelette\nnovelettes\nnovelettish\nnovelise\nnovelised\nnovelises\nnovelising\nnovelist\nnovelistic\nnovelistically\nnovelists\nnovelization\nnovelizations\nnovelize\nnovelized\nnovelizes\nnovelizing\nnovella\nnovellas\nnovelle\nnovelly\nnovels\nnovelties\nnovelty\nnovemdecillion\nnovemdecillions\nnovena\nnovenae\nnovenas\nnovercal\nnovice\nnovices\nnovitiate\nnovitiates\nnovobiocin\nnovobiocins\nnovocaine\nnovocaines\nnow\nnowadays\nnoway\nnoways\nnowhere\nnowheres\nnowhither\nnowise\nnowness\nnownesses\nnows\nnowt\nnowts\nnoxious\nnoxiously\nnoxiousness\nnoxiousnesses\nnoyade\nnoyades\nnozzle\nnozzles\nnth\nnu\nnuance\nnuanced\nnuances\nnub\nnubbier\nnubbiest\nnubbin\nnubbins\nnubble\nnubbles\nnubblier\nnubbliest\nnubbly\nnubby\nnubia\nnubias\nnubile\nnubilities\nnubility\nnubilose\nnubilous\nnubs\nnucellar\nnucelli\nnucellus\nnucha\nnuchae\nnuchal\nnuchals\nnucleal\nnuclear\nnuclease\nnucleases\nnucleate\nnucleated\nnucleates\nnucleating\nnucleation\nnucleations\nnucleator\nnucleators\nnuclei\nnuclein\nnucleins\nnucleocapsid\nnucleocapsids\nnucleoid\nnucleoids\nnucleolar\nnucleole\nnucleoles\nnucleoli\nnucleolus\nnucleon\nnucleonic\nnucleonics\nnucleons\nnucleophile\nnucleophiles\nnucleophilic\nnucleophilically\nnucleophilicities\nnucleophilicity\nnucleoplasm\nnucleoplasmic\nnucleoplasms\nnucleoprotein\nnucleoproteins\nnucleoside\nnucleosides\nnucleosomal\nnucleosome\nnucleosomes\nnucleosyntheses\nnucleosynthesis\nnucleosynthetic\nnucleotidase\nnucleotidases\nnucleotide\nnucleotides\nnucleus\nnucleuses\nnuclide\nnuclides\nnuclidic\nnude\nnudely\nnudeness\nnudenesses\nnuder\nnudes\nnudest\nnudge\nnudged\nnudger\nnudgers\nnudges\nnudging\nnudibranch\nnudibranchs\nnudicaul\nnudie\nnudies\nnudism\nnudisms\nnudist\nnudists\nnudities\nnudity\nnudnick\nnudnicks\nnudnik\nnudniks\nnudzh\nnudzhed\nnudzhes\nnudzhing\nnugatory\nnugget\nnuggets\nnuggety\nnuisance\nnuisances\nnuke\nnuked\nnukes\nnuking\nnull\nnullah\nnullahs\nnulled\nnullification\nnullificationist\nnullificationists\nnullifications\nnullified\nnullifier\nnullifiers\nnullifies\nnullify\nnullifying\nnulling\nnulliparous\nnullities\nnullity\nnulls\nnumb\nnumbat\nnumbats\nnumbed\nnumber\nnumberable\nnumbered\nnumberer\nnumberers\nnumbering\nnumberless\nnumbers\nnumbest\nnumbfish\nnumbfishes\nnumbing\nnumbingly\nnumbles\nnumbly\nnumbness\nnumbnesses\nnumbs\nnumbskull\nnumbskulls\nnumen\nnumerable\nnumeracies\nnumeracy\nnumeral\nnumerally\nnumerals\nnumerary\nnumerate\nnumerated\nnumerates\nnumerating\nnumeration\nnumerations\nnumerator\nnumerators\nnumeric\nnumerical\nnumerically\nnumerics\nnumerological\nnumerologies\nnumerologist\nnumerologists\nnumerology\nnumerous\nnumerously\nnumerousness\nnumerousnesses\nnumina\nnuminous\nnuminouses\nnuminousness\nnuminousnesses\nnumismatic\nnumismatically\nnumismatics\nnumismatist\nnumismatists\nnummary\nnummular\nnumskull\nnumskulls\nnun\nnunatak\nnunataks\nnunchaku\nnunchakus\nnunciature\nnunciatures\nnuncio\nnuncios\nnuncle\nnuncles\nnuncupative\nnunlike\nnunneries\nnunnery\nnunnish\nnuns\nnuptial\nnuptialities\nnuptiality\nnuptials\nnurd\nnurds\nnurl\nnurled\nnurling\nnurls\nnurse\nnursed\nnursemaid\nnursemaids\nnurser\nnurseries\nnursers\nnursery\nnurseryman\nnurserymen\nnurses\nnursing\nnursings\nnursling\nnurslings\nnurtural\nnurturance\nnurturances\nnurturant\nnurture\nnurtured\nnurturer\nnurturers\nnurtures\nnurturing\nnus\nnut\nnutant\nnutate\nnutated\nnutates\nnutating\nnutation\nnutational\nnutations\nnutbrown\nnutcase\nnutcases\nnutcracker\nnutcrackers\nnutgall\nnutgalls\nnutgrass\nnutgrasses\nnuthatch\nnuthatches\nnuthouse\nnuthouses\nnutlet\nnutlets\nnutlike\nnutmeat\nnutmeats\nnutmeg\nnutmegs\nnutpick\nnutpicks\nnutria\nnutrias\nnutrient\nnutrients\nnutriment\nnutriments\nnutrition\nnutritional\nnutritionally\nnutritionist\nnutritionists\nnutritions\nnutritious\nnutritiously\nnutritiousness\nnutritiousnesses\nnutritive\nnutritively\nnuts\nnutsedge\nnutsedges\nnutshell\nnutshells\nnutsier\nnutsiest\nnutsy\nnutted\nnutter\nnutters\nnuttier\nnuttiest\nnuttily\nnuttiness\nnuttinesses\nnutting\nnuttings\nnutty\nnutwood\nnutwoods\nnuzzle\nnuzzled\nnuzzler\nnuzzlers\nnuzzles\nnuzzling\nnyala\nnyalas\nnyctalopia\nnyctalopias\nnylghai\nnylghais\nnylghau\nnylghaus\nnylon\nnylons\nnymph\nnympha\nnymphae\nnymphal\nnymphalid\nnymphalids\nnymphean\nnymphet\nnymphets\nnymphette\nnymphettes\nnympho\nnympholepsies\nnympholepsy\nnympholept\nnympholeptic\nnympholepts\nnymphomania\nnymphomaniac\nnymphomaniacal\nnymphomaniacs\nnymphomanias\nnymphos\nnymphs\nnystagmic\nnystagmus\nnystagmuses\nnystatin\nnystatins\noaf\noafish\noafishly\noafishness\noafishnesses\noafs\noak\noaken\noaklike\noakmoss\noakmosses\noaks\noakum\noakums\noar\noared\noarfish\noarfishes\noaring\noarless\noarlike\noarlock\noarlocks\noars\noarsman\noarsmanship\noarsmanships\noarsmen\noarswoman\noarswomen\noases\noasis\noast\noasthouse\noasthouses\noasts\noat\noatcake\noatcakes\noaten\noater\noaters\noath\noaths\noatlike\noatmeal\noatmeals\noats\noaves\nobbligati\nobbligato\nobbligatos\nobconic\nobcordate\nobduracies\nobduracy\nobdurate\nobdurately\nobdurateness\nobduratenesses\nobe\nobeah\nobeahism\nobeahisms\nobeahs\nobedience\nobediences\nobedient\nobediently\nobeisance\nobeisances\nobeisant\nobeisantly\nobeli\nobelia\nobelias\nobelise\nobelised\nobelises\nobelising\nobelisk\nobelisks\nobelism\nobelisms\nobelize\nobelized\nobelizes\nobelizing\nobelus\nobes\nobese\nobesely\nobesities\nobesity\nobey\nobeyable\nobeyed\nobeyer\nobeyers\nobeying\nobeys\nobfuscate\nobfuscated\nobfuscates\nobfuscating\nobfuscation\nobfuscations\nobfuscatory\nobi\nobia\nobias\nobiism\nobiisms\nobis\nobit\nobits\nobituaries\nobituarist\nobituarists\nobituary\nobject\nobjected\nobjectification\nobjectifications\nobjectified\nobjectifies\nobjectify\nobjectifying\nobjecting\nobjection\nobjectionable\nobjectionableness\nobjectionablenesses\nobjectionably\nobjections\nobjective\nobjectively\nobjectiveness\nobjectivenesses\nobjectives\nobjectivism\nobjectivisms\nobjectivist\nobjectivistic\nobjectivists\nobjectivities\nobjectivity\nobjectless\nobjectlessness\nobjectlessnesses\nobjector\nobjectors\nobjects\nobjet\nobjets\nobjurgate\nobjurgated\nobjurgates\nobjurgating\nobjurgation\nobjurgations\nobjurgatory\noblanceolate\noblast\noblasti\noblasts\noblate\noblately\noblateness\noblatenesses\noblates\noblation\noblations\noblatory\nobligate\nobligated\nobligately\nobligates\nobligati\nobligating\nobligation\nobligations\nobligato\nobligatorily\nobligatory\nobligatos\noblige\nobliged\nobligee\nobligees\nobliger\nobligers\nobliges\nobliging\nobligingly\nobligingness\nobligingnesses\nobligor\nobligors\noblique\nobliqued\nobliquely\nobliqueness\nobliquenesses\nobliques\nobliquing\nobliquities\nobliquity\nobliterate\nobliterated\nobliterates\nobliterating\nobliteration\nobliterations\nobliterative\nobliterator\nobliterators\noblivion\noblivions\noblivious\nobliviously\nobliviousness\nobliviousnesses\noblong\noblongly\noblongs\nobloquies\nobloquy\nobnoxious\nobnoxiously\nobnoxiousness\nobnoxiousnesses\nobnubilate\nobnubilated\nobnubilates\nobnubilating\nobnubilation\nobnubilations\noboe\noboes\noboist\noboists\nobol\nobole\noboles\noboli\nobols\nobolus\nobovate\nobovoid\nobscene\nobscenely\nobscener\nobscenest\nobscenities\nobscenity\nobscurant\nobscurantic\nobscurantism\nobscurantisms\nobscurantist\nobscurantists\nobscurants\nobscuration\nobscurations\nobscure\nobscured\nobscurely\nobscureness\nobscurenesses\nobscurer\nobscures\nobscurest\nobscuring\nobscurities\nobscurity\nobsequies\nobsequious\nobsequiously\nobsequiousness\nobsequiousnesses\nobsequy\nobservabilities\nobservability\nobservable\nobservables\nobservably\nobservance\nobservances\nobservant\nobservantly\nobservants\nobservation\nobservational\nobservationally\nobservations\nobservatories\nobservatory\nobserve\nobserved\nobserver\nobservers\nobserves\nobserving\nobservingly\nobsess\nobsessed\nobsesses\nobsessing\nobsession\nobsessional\nobsessionally\nobsessions\nobsessive\nobsessively\nobsessiveness\nobsessivenesses\nobsessives\nobsessor\nobsessors\nobsidian\nobsidians\nobsolesce\nobsolesced\nobsolescence\nobsolescences\nobsolescent\nobsolescently\nobsolesces\nobsolescing\nobsolete\nobsoleted\nobsoletely\nobsoleteness\nobsoletenesses\nobsoletes\nobsoleting\nobstacle\nobstacles\nobstetric\nobstetrical\nobstetrically\nobstetrician\nobstetricians\nobstetrics\nobstinacies\nobstinacy\nobstinate\nobstinately\nobstinateness\nobstinatenesses\nobstreperous\nobstreperously\nobstreperousness\nobstreperousnesses\nobstruct\nobstructed\nobstructing\nobstruction\nobstructionism\nobstructionisms\nobstructionist\nobstructionistic\nobstructionists\nobstructions\nobstructive\nobstructively\nobstructiveness\nobstructivenesses\nobstructives\nobstructor\nobstructors\nobstructs\nobtain\nobtainabilities\nobtainability\nobtainable\nobtained\nobtainer\nobtainers\nobtaining\nobtainment\nobtainments\nobtains\nobtect\nobtected\nobtest\nobtested\nobtesting\nobtests\nobtrude\nobtruded\nobtruder\nobtruders\nobtrudes\nobtruding\nobtrusion\nobtrusions\nobtrusive\nobtrusively\nobtrusiveness\nobtrusivenesses\nobtund\nobtunded\nobtunding\nobtunds\nobturate\nobturated\nobturates\nobturating\nobturation\nobturations\nobturator\nobturators\nobtuse\nobtusely\nobtuseness\nobtusenesses\nobtuser\nobtusest\nobtusities\nobtusity\nobverse\nobversely\nobverses\nobvert\nobverted\nobverting\nobverts\nobviable\nobviate\nobviated\nobviates\nobviating\nobviation\nobviations\nobviator\nobviators\nobvious\nobviously\nobviousness\nobviousnesses\nobvolute\noca\nocarina\nocarinas\nocas\noccasion\noccasional\noccasionally\noccasioned\noccasioning\noccasions\noccident\noccidental\noccidentalize\noccidentalized\noccidentalizes\noccidentalizing\noccidentally\noccidents\noccipita\noccipital\noccipitally\noccipitals\nocciput\nocciputs\nocclude\noccluded\noccludes\noccluding\nocclusal\nocclusion\nocclusions\nocclusive\noccult\noccultation\noccultations\nocculted\nocculter\nocculters\nocculting\noccultism\noccultisms\noccultist\noccultists\noccultly\noccults\noccupancies\noccupancy\noccupant\noccupants\noccupation\noccupational\noccupationally\noccupations\noccupied\noccupier\noccupiers\noccupies\noccupy\noccupying\noccur\noccurred\noccurrence\noccurrences\noccurrent\noccurrents\noccurring\noccurs\nocean\noceanaria\noceanarium\noceanariums\noceanaut\noceanauts\noceanfront\noceanfronts\noceangoing\noceanic\noceanographer\noceanographers\noceanographic\noceanographical\noceanographically\noceanographies\noceanography\noceanologies\noceanologist\noceanologists\noceanology\noceans\nocellar\nocellate\nocelli\nocellus\noceloid\nocelot\nocelots\nocher\nochered\nochering\nocherous\nochers\nochery\nochlocracies\nochlocracy\nochlocrat\nochlocratic\nochlocratical\nochlocrats\nochone\nochre\nochrea\nochreae\nochred\nochreous\nochres\nochring\nochroid\nochrous\nochry\nocker\nockers\nocotillo\nocotillos\nocrea\nocreae\nocreate\noctad\noctadic\noctads\noctagon\noctagonal\noctagonally\noctagons\noctahedra\noctahedral\noctahedrally\noctahedron\noctahedrons\noctal\noctameter\noctameters\noctan\noctane\noctanes\noctangle\noctangles\noctanol\noctanols\noctans\noctant\noctantal\noctants\noctapeptide\noctapeptides\noctarchies\noctarchy\noctaval\noctave\noctaves\noctavo\noctavos\noctet\noctets\noctette\noctettes\noctillion\noctillions\noctodecillion\noctodecillions\noctogenarian\noctogenarians\noctonaries\noctonary\noctopi\noctoploid\noctoploids\noctopod\noctopodes\noctopods\noctopus\noctopuses\noctoroon\noctoroons\noctosyllabic\noctosyllabics\noctosyllable\noctosyllables\noctothorp\noctothorps\noctroi\noctrois\noctuple\noctupled\noctuples\noctuplet\noctuplets\noctuplex\noctupling\noctuply\noctyl\noctyls\nocular\nocularist\nocularists\nocularly\noculars\noculi\noculist\noculists\noculomotor\noculus\nod\nodalisk\nodalisks\nodalisque\nodalisques\nodd\noddball\noddballs\nodder\noddest\noddish\noddities\noddity\noddly\noddment\noddments\noddness\noddnesses\nodds\noddsmaker\noddsmakers\node\nodea\nodeon\nodeons\nodes\nodeum\nodeums\nodic\nodious\nodiously\nodiousness\nodiousnesses\nodist\nodists\nodium\nodiums\nodograph\nodographs\nodometer\nodometers\nodometries\nodometry\nodonate\nodonates\nodontoblast\nodontoblastic\nodontoblasts\nodontoglossum\nodontoglossums\nodontoid\nodontoids\nodor\nodorant\nodorants\nodored\nodorful\nodoriferous\nodoriferously\nodoriferousness\nodoriferousnesses\nodorize\nodorized\nodorizes\nodorizing\nodorless\nodorous\nodorously\nodorousness\nodorousnesses\nodors\nodour\nodourful\nodours\nods\nodyl\nodyle\nodyles\nodyls\nodyssey\nodysseys\noe\noecologies\noecology\noecumenical\noedema\noedemas\noedemata\noedipal\noedipally\noedipean\noeillade\noeillades\noenologies\noenology\noenomel\noenomels\noenophile\noenophiles\noersted\noersteds\noes\noesophagi\noesophagus\noestrin\noestrins\noestriol\noestriols\noestrone\noestrones\noestrous\noestrum\noestrums\noestrus\noestruses\noeuvre\noeuvres\nof\nofay\nofays\noff\noffal\noffals\noffbeat\noffbeats\noffcast\noffcasts\noffcut\noffcuts\noffed\noffence\noffences\noffend\noffended\noffender\noffenders\noffending\noffends\noffense\noffenseless\noffenses\noffensive\noffensively\noffensiveness\noffensivenesses\noffensives\noffer\noffered\nofferer\nofferers\noffering\nofferings\nofferor\nofferors\noffers\noffertories\noffertory\noffguard\noffhand\noffhanded\noffhandedly\noffhandedness\noffhandednesses\noffice\nofficeholder\nofficeholders\nofficer\nofficered\nofficering\nofficers\noffices\nofficial\nofficialdom\nofficialdoms\nofficialese\nofficialeses\nofficialism\nofficialisms\nofficially\nofficials\nofficiant\nofficiants\nofficiaries\nofficiary\nofficiate\nofficiated\nofficiates\nofficiating\nofficiation\nofficiations\nofficinal\nofficious\nofficiously\nofficiousness\nofficiousnesses\noffing\noffings\noffish\noffishly\noffishness\noffishnesses\noffkey\noffline\noffload\noffloaded\noffloading\noffloads\noffprint\noffprinted\noffprinting\noffprints\nofframp\nofframps\noffs\noffscouring\noffscourings\noffscreen\noffset\noffsets\noffsetting\noffshoot\noffshoots\noffshore\noffside\noffsides\noffspring\noffsprings\noffstage\noffstages\nofftrack\noft\noften\noftener\noftenest\noftentimes\nofter\noftest\nofttimes\nogam\nogams\nogdoad\nogdoads\nogee\nogees\nogham\noghamic\noghamist\noghamists\noghams\nogival\nogive\nogives\nogle\nogled\nogler\noglers\nogles\nogling\nogre\nogreish\nogreism\nogreisms\nogres\nogress\nogresses\nogrish\nogrishly\nogrism\nogrisms\noh\nohed\nohia\nohias\nohing\nohm\nohmage\nohmages\nohmic\nohmically\nohmmeter\nohmmeters\nohms\noho\nohs\noidia\noidium\noil\noilbird\noilbirds\noilcamp\noilcamps\noilcan\noilcans\noilcloth\noilcloths\noilcup\noilcups\noiled\noiler\noilers\noilhole\noilholes\noilier\noiliest\noilily\noiliness\noilinesses\noiling\noilman\noilmen\noilpaper\noilpapers\noilproof\noils\noilseed\noilseeds\noilskin\noilskins\noilstone\noilstones\noiltight\noilway\noilways\noily\noink\noinked\noinking\noinks\noinologies\noinology\noinomel\noinomels\nointment\nointments\noiticica\noiticicas\noka\nokapi\nokapis\nokas\nokay\nokayed\nokaying\nokays\noke\nokeh\nokehs\nokes\nokeydoke\nokeydokey\nokra\nokras\nold\nolden\nolder\noldest\noldfangled\noldie\noldies\noldish\noldness\noldnesses\nolds\noldsquaw\noldsquaws\noldster\noldsters\noldstyle\noldstyles\noldwife\noldwives\noldy\nole\nolea\noleaginous\noleaginously\noleaginousness\noleaginousnesses\noleander\noleanders\noleandomycin\noleandomycins\noleaster\noleasters\noleate\noleates\nolecranon\nolecranons\nolefin\nolefine\nolefines\nolefinic\nolefins\noleic\nolein\noleine\noleines\noleins\noleo\noleograph\noleographs\noleomargarine\noleomargarines\noleoresin\noleoresinous\noleoresins\noleos\noles\noleum\noleums\nolfaction\nolfactions\nolfactometer\nolfactometers\nolfactory\nolibanum\nolibanums\noligarch\noligarchic\noligarchical\noligarchies\noligarchs\noligarchy\noligochaete\noligochaetes\noligoclase\noligoclases\noligodendrocyte\noligodendrocytes\noligodendroglia\noligodendroglial\noligodendroglias\noligomer\noligomeric\noligomerization\noligomerizations\noligomers\noligonucleotide\noligonucleotides\noligophagies\noligophagous\noligophagy\noligopolies\noligopolistic\noligopoly\noligopsonies\noligopsonistic\noligopsony\noligosaccharide\noligosaccharides\noligotrophic\noliguria\noligurias\nolio\nolios\nolivaceous\nolivary\nolive\nolivenite\nolivenites\nolives\nolivine\nolivines\nolivinic\nolivinitic\nolla\nollas\nologies\nologist\nologists\nology\nololiuqui\nololiuquis\noloroso\nolorosos\nolympiad\nolympiads\nom\nomasa\nomasum\nomber\nombers\nombre\nombres\nombudsman\nombudsmanship\nombudsmanships\nombudsmen\nomega\nomegas\nomelet\nomelets\nomelette\nomelettes\nomen\nomened\nomening\nomens\nomenta\nomental\nomentum\nomentums\nomer\nomers\nomicron\nomicrons\nomikron\nomikrons\nominous\nominously\nominousness\nominousnesses\nomissible\nomission\nomissions\nomissive\nomit\nomits\nomitted\nomitter\nomitters\nomitting\nommatidia\nommatidial\nommatidium\nomniarch\nomniarchs\nomnibus\nomnibuses\nomnibusses\nomnicompetence\nomnicompetences\nomnicompetent\nomnidirectional\nomnifarious\nomnific\nomnificent\nomniform\nomnimode\nomnipotence\nomnipotences\nomnipotent\nomnipotently\nomnipotents\nomnipresence\nomnipresences\nomnipresent\nomnirange\nomniranges\nomniscience\nomnisciences\nomniscient\nomnisciently\nomnivora\nomnivore\nomnivores\nomnivorous\nomnivorously\nomophagies\nomophagy\nomphali\nomphalos\nomphaloses\nomphaloskepses\nomphaloskepsis\noms\non\nonager\nonagers\nonagri\nonanism\nonanisms\nonanist\nonanistic\nonanists\nonboard\nonce\nonces\nonchocerciases\nonchocerciasis\noncidium\noncidiums\noncogene\noncogenes\noncogeneses\noncogenesis\noncogenic\noncogenicities\noncogenicity\noncologic\noncological\noncologies\noncologist\noncologists\noncology\noncoming\noncomings\noncornavirus\noncornaviruses\nondogram\nondograms\none\nonefold\noneiric\noneirically\noneiromancies\noneiromancy\noneness\nonenesses\nonerier\noneriest\nonerous\nonerously\nonerousness\nonerousnesses\nonery\nones\noneself\nonetime\nongoing\nongoingness\nongoingnesses\nonion\nonions\nonionskin\nonionskins\noniony\nonium\nonline\nonlooker\nonlookers\nonlooking\nonly\nonomastic\nonomastically\nonomastician\nonomasticians\nonomastics\nonomatologies\nonomatologist\nonomatologists\nonomatology\nonomatopoeia\nonomatopoeias\nonomatopoeic\nonomatopoeically\nonomatopoetic\nonomatopoetically\nonrush\nonrushes\nonrushing\nons\nonscreen\nonset\nonsets\nonshore\nonside\nonslaught\nonslaughts\nonstage\nonstream\nontic\nontically\nonto\nontogeneses\nontogenesis\nontogenetic\nontogenetically\nontogenies\nontogeny\nontological\nontologically\nontologies\nontologist\nontologists\nontology\nonus\nonuses\nonward\nonwards\nonychophoran\nonychophorans\nonyx\nonyxes\noocyst\noocysts\noocyte\noocytes\noodles\noodlins\noogamete\noogametes\noogamies\noogamous\noogamy\noogeneses\noogenesis\noogenetic\noogenies\noogeny\noogonia\noogonial\noogonium\noogoniums\nooh\noohed\noohing\noohs\noolachan\noolachans\noolite\noolites\noolith\nooliths\noolitic\noologic\noologies\noologist\noologists\noology\noolong\noolongs\noomiac\noomiack\noomiacks\noomiacs\noomiak\noomiaks\noompah\noompahed\noompahing\noompahs\noomph\noomphs\noophorectomies\noophorectomy\noophyte\noophytes\noophytic\noops\noorali\nooralis\noorie\noosperm\noosperms\noosphere\noospheres\noospore\noospores\noosporic\noot\nootheca\noothecae\noothecal\nootid\nootids\noots\nooze\noozed\noozes\noozier\nooziest\noozily\nooziness\noozinesses\noozing\noozy\nop\nopacified\nopacifies\nopacify\nopacifying\nopacities\nopacity\nopah\nopahs\nopal\nopalesce\nopalesced\nopalescence\nopalescences\nopalescent\nopalescently\nopalesces\nopalescing\nopaline\nopalines\nopals\nopaque\nopaqued\nopaquely\nopaqueness\nopaquenesses\nopaquer\nopaques\nopaquest\nopaquing\nope\noped\nopen\nopenabilities\nopenability\nopenable\nopencast\nopened\nopener\nopeners\nopenest\nopenhanded\nopenhandedly\nopenhandedness\nopenhandednesses\nopenhearted\nopenheartedly\nopenheartedness\nopenheartednesses\nopening\nopenings\nopenly\nopenmouthed\nopenmouthedly\nopenmouthedness\nopenmouthednesses\nopenness\nopennesses\nopens\nopenwork\nopenworks\nopera\noperabilities\noperability\noperable\noperably\noperagoer\noperagoers\noperagoing\noperagoings\noperand\noperands\noperant\noperantly\noperants\noperas\noperate\noperated\noperates\noperatic\noperatically\noperatics\noperating\noperation\noperational\noperationalism\noperationalisms\noperationalist\noperationalistic\noperationalists\noperationally\noperationism\noperationisms\noperationist\noperationists\noperations\noperative\noperatively\noperativeness\noperativenesses\noperatives\noperator\noperatorless\noperators\nopercele\noperceles\nopercula\nopercular\noperculars\noperculate\noperculated\nopercule\nopercules\noperculum\noperculums\noperetta\noperettas\noperettist\noperettists\noperon\noperons\noperose\noperosely\noperoseness\noperosenesses\nopes\nophidian\nophidians\nophite\nophites\nophitic\nophiuroid\nophiuroids\nophthalmia\nophthalmias\nophthalmic\nophthalmologic\nophthalmological\nophthalmologically\nophthalmologies\nophthalmologist\nophthalmologists\nophthalmology\nophthalmoscope\nophthalmoscopes\nophthalmoscopic\nophthalmoscopies\nophthalmoscopy\nopiate\nopiated\nopiates\nopiating\nopine\nopined\nopines\noping\nopining\nopinion\nopinionated\nopinionatedly\nopinionatedness\nopinionatednesses\nopinionative\nopinionatively\nopinionativeness\nopinionativenesses\nopinioned\nopinions\nopioid\nopioids\nopisthobranch\nopisthobranchs\nopium\nopiumism\nopiumisms\nopiums\nopossum\nopossums\noppidan\noppidans\noppilant\noppilate\noppilated\noppilates\noppilating\nopponent\nopponents\nopportune\nopportunely\nopportuneness\nopportunenesses\nopportunism\nopportunisms\nopportunist\nopportunistic\nopportunistically\nopportunists\nopportunities\nopportunity\nopposabilities\nopposability\nopposable\noppose\nopposed\nopposeless\nopposer\nopposers\nopposes\nopposing\nopposite\noppositely\noppositeness\noppositenesses\nopposites\nopposition\noppositional\noppositionist\noppositionists\noppositions\noppress\noppressed\noppresses\noppressing\noppression\noppressions\noppressive\noppressively\noppressiveness\noppressivenesses\noppressor\noppressors\nopprobrious\nopprobriously\nopprobriousness\nopprobriousnesses\nopprobrium\nopprobriums\noppugn\noppugned\noppugner\noppugners\noppugning\noppugns\nops\nopsin\nopsins\nopsonic\nopsonified\nopsonifies\nopsonify\nopsonifying\nopsonin\nopsonins\nopsonize\nopsonized\nopsonizes\nopsonizing\nopt\noptative\noptatively\noptatives\nopted\noptic\noptical\noptically\noptician\nopticians\nopticist\nopticists\noptics\noptima\noptimal\noptimalities\noptimality\noptimally\noptime\noptimes\noptimisation\noptimisations\noptimise\noptimised\noptimises\noptimising\noptimism\noptimisms\noptimist\noptimistic\noptimistically\noptimists\noptimization\noptimizations\noptimize\noptimized\noptimizer\noptimizers\noptimizes\noptimizing\noptimum\noptimums\nopting\noption\noptional\noptionalities\noptionality\noptionally\noptionals\noptioned\noptionee\noptionees\noptioning\noptions\noptoelectronic\noptoelectronics\noptokinetic\noptometric\noptometries\noptometrist\noptometrists\noptometry\nopts\nopulence\nopulences\nopulencies\nopulency\nopulent\nopulently\nopuntia\nopuntias\nopus\nopuscula\nopuscule\nopuscules\nopusculum\nopuses\noquassa\noquassas\nor\nora\norach\norache\noraches\noracle\noracles\noracular\noracularities\noracularity\noracularly\norad\noral\noralism\noralisms\noralist\noralists\noralities\norality\norally\norals\norang\norange\norangeade\norangeades\norangerie\norangeries\norangery\noranges\norangewood\norangewoods\norangey\norangier\norangiest\norangish\norangs\norangutan\norangutans\norangy\norate\norated\norates\norating\noration\norations\norator\noratorical\noratorically\noratories\noratorio\noratorios\norators\noratory\noratress\noratresses\noratrices\noratrix\norb\norbed\norbicular\norbicularly\norbiculate\norbier\norbiest\norbing\norbit\norbital\norbitals\norbited\norbiter\norbiters\norbiting\norbits\norbs\norby\norc\norca\norcas\norcein\norceins\norchard\norchardist\norchardists\norchards\norchestra\norchestral\norchestrally\norchestras\norchestrate\norchestrated\norchestrater\norchestraters\norchestrates\norchestrating\norchestration\norchestrational\norchestrations\norchestrator\norchestrators\norchid\norchidaceous\norchidlike\norchids\norchil\norchils\norchis\norchises\norchitic\norchitis\norchitises\norcin\norcinol\norcinols\norcins\norcs\nordain\nordained\nordainer\nordainers\nordaining\nordainment\nordainments\nordains\nordeal\nordeals\norder\norderable\nordered\norderer\norderers\nordering\norderless\norderlies\norderliness\norderlinesses\norderly\norders\nordinal\nordinals\nordinance\nordinances\nordinand\nordinands\nordinarier\nordinaries\nordinariest\nordinarily\nordinariness\nordinarinesses\nordinary\nordinate\nordinates\nordination\nordinations\nordines\nordnance\nordnances\nordo\nordonnance\nordonnances\nordos\nordure\nordures\nore\noread\noreads\norectic\norective\noregano\noreganos\noreide\noreides\nores\norfray\norfrays\norgan\norgana\norgandie\norgandies\norgandy\norganelle\norganelles\norganic\norganically\norganicism\norganicisms\norganicist\norganicists\norganicities\norganicity\norganics\norganisation\norganisations\norganise\norganised\norganiser\norganisers\norganises\norganising\norganism\norganismal\norganismic\norganismically\norganisms\norganist\norganists\norganizable\norganization\norganizational\norganizationally\norganizations\norganize\norganized\norganizer\norganizers\norganizes\norganizing\norganochlorine\norganochlorines\norganogeneses\norganogenesis\norganogenetic\norganoleptic\norganoleptically\norganologies\norganology\norganomercurial\norganomercurials\norganometallic\norganometallics\norganon\norganons\norganophosphate\norganophosphates\norganophosphorous\norganophosphorus\norganophosphoruses\norgans\norganum\norganums\norganza\norganzas\norganzine\norganzines\norgasm\norgasmic\norgasms\norgastic\norgeat\norgeats\norgiac\norgiastic\norgiastically\norgic\norgies\norgone\norgones\norgulous\norgy\noribatid\noribatids\noribi\noribis\noriel\noriels\norient\noriental\norientalism\norientalisms\norientalist\norientalists\norientalize\norientalized\norientalizes\norientalizing\norientally\norientals\norientate\norientated\norientates\norientating\norientation\norientational\norientationally\norientations\noriented\norienteer\norienteering\norienteerings\norienteers\norienting\norients\norifice\norifices\norificial\noriflamme\noriflammes\norigami\norigamis\norigan\norigans\noriganum\noriganums\norigin\noriginal\noriginalities\noriginality\noriginally\noriginals\noriginate\noriginated\noriginates\noriginating\norigination\noriginations\noriginative\noriginatively\noriginator\noriginators\norigins\norinasal\norinasals\noriole\norioles\norismological\norismologies\norismology\norison\norisons\norle\norles\norlop\norlops\normer\normers\normolu\normolus\nornament\nornamental\nornamentally\nornamentals\nornamentation\nornamentations\nornamented\nornamenting\nornaments\nornate\nornately\nornateness\nornatenesses\nornerier\norneriest\norneriness\nornerinesses\nornery\nornis\nornithes\nornithic\nornithine\nornithines\nornithischian\nornithischians\nornithologic\nornithological\nornithologically\nornithologies\nornithologist\nornithologists\nornithology\nornithopod\nornithopods\nornithopter\nornithopters\nornithoses\nornithosis\norogeneses\norogenesis\norogenetic\norogenic\norogenies\norogeny\norographic\norographical\norographies\norography\noroide\noroides\norologies\norology\norometer\norometers\noropharyngeal\noropharynges\noropharynx\noropharynxes\norotund\norotundities\norotundity\norphan\norphanage\norphanages\norphaned\norphanhood\norphanhoods\norphaning\norphans\norphic\norphical\norphically\norphrey\norphreys\norpiment\norpiments\norpin\norpine\norpines\norpins\norra\norreries\norrery\norrice\norrices\norris\norrises\norrisroot\norrisroots\nors\nort\northicon\northicons\northo\northocenter\northocenters\northochromatic\northoclase\northoclases\northodontia\northodontias\northodontic\northodontically\northodontics\northodontist\northodontists\northodox\northodoxes\northodoxies\northodoxly\northodoxy\northoepic\northoepically\northoepies\northoepist\northoepists\northoepy\northogeneses\northogenesis\northogenetic\northogenetically\northogonal\northogonalities\northogonality\northogonalization\northogonalizations\northogonalize\northogonalized\northogonalizes\northogonalizing\northogonally\northograde\northographic\northographical\northographically\northographies\northography\northomolecular\northonormal\northopaedic\northopaedics\northopedic\northopedically\northopedics\northopedist\northopedists\northophosphate\northophosphates\northopsychiatric\northopsychiatries\northopsychiatrist\northopsychiatrists\northopsychiatry\northoptera\northopteran\northopterans\northopterist\northopterists\northopteroid\northopteroids\northorhombic\northoscopic\northoses\northosis\northostatic\northotic\northotics\northotist\northotists\northotropous\nortolan\nortolans\norts\noryx\noryxes\norzo\norzos\nos\nosar\noscillate\noscillated\noscillates\noscillating\noscillation\noscillational\noscillations\noscillator\noscillators\noscillatory\noscillogram\noscillograms\noscillograph\noscillographic\noscillographically\noscillographies\noscillographs\noscillography\noscilloscope\noscilloscopes\noscilloscopic\noscine\noscines\noscinine\noscitant\noscula\nosculant\noscular\nosculate\nosculated\nosculates\nosculating\nosculation\nosculations\nosculatory\noscule\noscules\nosculum\nose\noses\nosier\nosiers\nosmatic\nosmeteria\nosmeterium\nosmic\nosmics\nosmious\nosmiridium\nosmiridiums\nosmium\nosmiums\nosmol\nosmolal\nosmolalities\nosmolality\nosmolar\nosmolarities\nosmolarity\nosmole\nosmoles\nosmols\nosmometer\nosmometers\nosmometric\nosmometries\nosmometry\nosmoregulation\nosmoregulations\nosmoregulatory\nosmose\nosmosed\nosmoses\nosmosing\nosmosis\nosmotic\nosmotically\nosmous\nosmund\nosmunda\nosmundas\nosmunds\nosnaburg\nosnaburgs\nosprey\nospreys\nossa\nossein\nosseins\nosseous\nossia\nossicle\nossicles\nossicular\nossific\nossification\nossifications\nossified\nossifier\nossifiers\nossifies\nossifrage\nossifrages\nossify\nossifying\nossuaries\nossuary\nosteal\nosteites\nosteitic\nosteitides\nosteitis\nostensible\nostensibly\nostensive\nostensively\nostensoria\nostensorium\nostentation\nostentations\nostentatious\nostentatiously\nostentatiousness\nostentatiousnesses\nosteoarthritic\nosteoarthritides\nosteoarthritis\nosteoblast\nosteoblastic\nosteoblasts\nosteoclast\nosteoclastic\nosteoclasts\nosteocyte\nosteocytes\nosteogeneses\nosteogenesis\nosteogenic\nosteoid\nosteoids\nosteological\nosteologies\nosteologist\nosteologists\nosteology\nosteoma\nosteomalacia\nosteomalacias\nosteomas\nosteomata\nosteomyelitides\nosteomyelitis\nosteopath\nosteopathic\nosteopathically\nosteopathies\nosteopaths\nosteopathy\nosteoplastic\nosteoplasties\nosteoplasty\nosteoporoses\nosteoporosis\nosteoporotic\nosteosarcoma\nosteosarcomas\nosteosarcomata\nosteoses\nosteosis\nosteosises\nostia\nostiaries\nostiary\nostinati\nostinato\nostinatos\nostiolar\nostiole\nostioles\nostium\nostler\nostlers\nostmark\nostmarks\nostomies\nostomy\nostoses\nostosis\nostosises\nostraca\nostracise\nostracised\nostracises\nostracising\nostracism\nostracisms\nostracize\nostracized\nostracizes\nostracizing\nostracod\nostracode\nostracoderm\nostracoderms\nostracodes\nostracods\nostracon\nostrich\nostriches\nostrichlike\notalgia\notalgias\notalgic\notalgies\notalgy\nother\notherguess\notherness\nothernesses\nothers\notherwhere\notherwhile\notherwhiles\notherwise\notherworld\notherworldliness\notherworldlinesses\notherworldly\notherworlds\notic\notiose\notiosely\notioseness\notiosenesses\notiosities\notiosity\notitic\notitides\notitis\notocyst\notocystic\notocysts\notolaryngological\notolaryngologies\notolaryngologist\notolaryngologists\notolaryngology\notolith\notolithic\notoliths\notologies\notology\notorhinolaryngological\notorhinolaryngologies\notorhinolaryngologist\notorhinolaryngologists\notorhinolaryngology\notoscleroses\notosclerosis\notoscope\notoscopes\notoscopies\notoscopy\nototoxic\nototoxicities\nototoxicity\nottar\nottars\nottava\nottavas\notter\notters\notto\nottoman\nottomans\nottos\nouabain\nouabains\noubliette\noubliettes\nouch\nouched\nouches\nouching\noud\nouds\nought\noughted\noughting\noughts\nouguiya\nouguiyas\nouistiti\nouistitis\nounce\nounces\nouph\nouphe\nouphes\nouphs\nour\nourang\nourangs\nourari\nouraris\nourebi\nourebis\nourie\nours\nourself\nourselves\nousel\nousels\noust\nousted\nouster\nousters\nousting\nousts\nout\noutachieve\noutachieved\noutachieves\noutachieving\noutact\noutacted\noutacting\noutacts\noutadd\noutadded\noutadding\noutadds\noutage\noutages\noutargue\noutargued\noutargues\noutarguing\noutask\noutasked\noutasking\noutasks\noutate\noutback\noutbacks\noutbake\noutbaked\noutbakes\noutbaking\noutbalance\noutbalanced\noutbalances\noutbalancing\noutbargain\noutbargained\noutbargaining\noutbargains\noutbark\noutbarked\noutbarking\noutbarks\noutbawl\noutbawled\noutbawling\noutbawls\noutbeam\noutbeamed\noutbeaming\noutbeams\noutbeg\noutbegged\noutbegging\noutbegs\noutbid\noutbidden\noutbidding\noutbids\noutbitch\noutbitched\noutbitches\noutbitching\noutblaze\noutblazed\noutblazes\noutblazing\noutbleat\noutbleated\noutbleating\noutbleats\noutbless\noutblessed\noutblesses\noutblessing\noutbloom\noutbloomed\noutblooming\noutblooms\noutbluff\noutbluffed\noutbluffing\noutbluffs\noutblush\noutblushed\noutblushes\noutblushing\noutboard\noutboards\noutboast\noutboasted\noutboasting\noutboasts\noutbought\noutbound\noutbox\noutboxed\noutboxes\noutboxing\noutbrag\noutbragged\noutbragging\noutbrags\noutbrave\noutbraved\noutbraves\noutbraving\noutbrawl\noutbrawled\noutbrawling\noutbrawls\noutbreak\noutbreaks\noutbred\noutbreed\noutbreeding\noutbreedings\noutbreeds\noutbribe\noutbribed\noutbribes\noutbribing\noutbuild\noutbuilding\noutbuildings\noutbuilds\noutbuilt\noutbulk\noutbulked\noutbulking\noutbulks\noutbullied\noutbullies\noutbully\noutbullying\noutburn\noutburned\noutburning\noutburns\noutburnt\noutburst\noutbursts\noutbuy\noutbuying\noutbuys\noutby\noutbye\noutcaper\noutcapered\noutcapering\noutcapers\noutcast\noutcaste\noutcastes\noutcasts\noutcatch\noutcatches\noutcatching\noutcaught\noutcavil\noutcaviled\noutcaviling\noutcavilled\noutcavilling\noutcavils\noutcharge\noutcharged\noutcharges\noutcharging\noutcharm\noutcharmed\noutcharming\noutcharms\noutcheat\noutcheated\noutcheating\noutcheats\noutchid\noutchidden\noutchide\noutchided\noutchides\noutchiding\noutclass\noutclassed\noutclasses\noutclassing\noutclimb\noutclimbed\noutclimbing\noutclimbs\noutclomb\noutcoach\noutcoached\noutcoaches\noutcoaching\noutcome\noutcomes\noutcompete\noutcompeted\noutcompetes\noutcompeting\noutcook\noutcooked\noutcooking\noutcooks\noutcount\noutcounted\noutcounting\noutcounts\noutcrawl\noutcrawled\noutcrawling\noutcrawls\noutcried\noutcries\noutcrop\noutcropped\noutcropping\noutcroppings\noutcrops\noutcross\noutcrossed\noutcrosses\noutcrossing\noutcrow\noutcrowed\noutcrowing\noutcrows\noutcry\noutcrying\noutcurse\noutcursed\noutcurses\noutcursing\noutcurve\noutcurves\noutdance\noutdanced\noutdances\noutdancing\noutdare\noutdared\noutdares\noutdaring\noutdate\noutdated\noutdatedly\noutdatedness\noutdatednesses\noutdates\noutdating\noutdazzle\noutdazzled\noutdazzles\noutdazzling\noutdebate\noutdebated\noutdebates\noutdebating\noutdeliver\noutdelivered\noutdelivering\noutdelivers\noutdesign\noutdesigned\noutdesigning\noutdesigns\noutdid\noutdistance\noutdistanced\noutdistances\noutdistancing\noutdo\noutdodge\noutdodged\noutdodges\noutdodging\noutdoer\noutdoers\noutdoes\noutdoing\noutdone\noutdoor\noutdoors\noutdoorsman\noutdoorsmanship\noutdoorsmanships\noutdoorsmen\noutdoorsy\noutdrag\noutdragged\noutdragging\noutdrags\noutdrank\noutdraw\noutdrawing\noutdrawn\noutdraws\noutdream\noutdreamed\noutdreaming\noutdreams\noutdreamt\noutdress\noutdressed\noutdresses\noutdressing\noutdrew\noutdrink\noutdrinking\noutdrinks\noutdrive\noutdriven\noutdrives\noutdriving\noutdrop\noutdropped\noutdropping\noutdrops\noutdrove\noutdrunk\noutduel\noutdueled\noutdueling\noutduelled\noutduelling\noutduels\noutearn\noutearned\noutearning\noutearns\nouteat\nouteaten\nouteating\nouteats\noutecho\noutechoed\noutechoes\noutechoing\nouted\nouter\noutercoat\noutercoats\noutermost\nouters\nouterwear\noutfable\noutfabled\noutfables\noutfabling\noutface\noutfaced\noutfaces\noutfacing\noutfall\noutfalls\noutfast\noutfasted\noutfasting\noutfasts\noutfawn\noutfawned\noutfawning\noutfawns\noutfeast\noutfeasted\noutfeasting\noutfeasts\noutfeel\noutfeeling\noutfeels\noutfelt\noutfield\noutfielder\noutfielders\noutfields\noutfight\noutfighting\noutfights\noutfigure\noutfigured\noutfigures\noutfiguring\noutfind\noutfinding\noutfinds\noutfire\noutfired\noutfires\noutfiring\noutfish\noutfished\noutfishes\noutfishing\noutfit\noutfits\noutfitted\noutfitter\noutfitters\noutfitting\noutflank\noutflanked\noutflanking\noutflanks\noutflew\noutflies\noutflow\noutflowed\noutflowing\noutflown\noutflows\noutfly\noutflying\noutfool\noutfooled\noutfooling\noutfools\noutfoot\noutfooted\noutfooting\noutfoots\noutfought\noutfound\noutfox\noutfoxed\noutfoxes\noutfoxing\noutfrown\noutfrowned\noutfrowning\noutfrowns\noutfumble\noutfumbled\noutfumbles\noutfumbling\noutgain\noutgained\noutgaining\noutgains\noutgas\noutgassed\noutgasses\noutgassing\noutgave\noutgeneral\noutgeneraled\noutgeneraling\noutgenerals\noutgive\noutgiven\noutgives\noutgiving\noutgivings\noutglare\noutglared\noutglares\noutglaring\noutglitter\noutglittered\noutglittering\noutglitters\noutglow\noutglowed\noutglowing\noutglows\noutgnaw\noutgnawed\noutgnawing\noutgnawn\noutgnaws\noutgo\noutgoes\noutgoing\noutgoingness\noutgoingnesses\noutgoings\noutgone\noutgrew\noutgrin\noutgrinned\noutgrinning\noutgrins\noutgross\noutgrossed\noutgrosses\noutgrossing\noutgroup\noutgroups\noutgrow\noutgrowing\noutgrown\noutgrows\noutgrowth\noutgrowths\noutguess\noutguessed\noutguesses\noutguessing\noutguide\noutguided\noutguides\noutguiding\noutgun\noutgunned\noutgunning\noutguns\noutgush\noutgushes\nouthaul\nouthauls\nouthear\noutheard\nouthearing\nouthears\nouthit\nouthits\nouthitting\nouthomer\nouthomered\nouthomering\nouthomers\nouthouse\nouthouses\nouthowl\nouthowled\nouthowling\nouthowls\nouthumor\nouthumored\nouthumoring\nouthumors\nouthunt\nouthunted\nouthunting\nouthunts\nouthustle\nouthustled\nouthustles\nouthustling\nouting\noutings\noutintrigue\noutintrigued\noutintrigues\noutintriguing\noutjinx\noutjinxed\noutjinxes\noutjinxing\noutjump\noutjumped\noutjumping\noutjumps\noutjut\noutjuts\noutjutted\noutjutting\noutkeep\noutkeeping\noutkeeps\noutkept\noutkick\noutkicked\noutkicking\noutkicks\noutkill\noutkilled\noutkilling\noutkills\noutkiss\noutkissed\noutkisses\noutkissing\noutlaid\noutlain\noutland\noutlander\noutlanders\noutlandish\noutlandishly\noutlandishness\noutlandishnesses\noutlands\noutlast\noutlasted\noutlasting\noutlasts\noutlaugh\noutlaughed\noutlaughing\noutlaughs\noutlaw\noutlawed\noutlawing\noutlawries\noutlawry\noutlaws\noutlay\noutlaying\noutlays\noutleap\noutleaped\noutleaping\noutleaps\noutleapt\noutlearn\noutlearned\noutlearning\noutlearns\noutlearnt\noutlet\noutlets\noutlie\noutlier\noutliers\noutlies\noutline\noutlined\noutliner\noutliners\noutlines\noutlining\noutlive\noutlived\noutliver\noutlivers\noutlives\noutliving\noutlook\noutlooks\noutlove\noutloved\noutloves\noutloving\noutlying\noutman\noutmaneuver\noutmaneuvered\noutmaneuvering\noutmaneuvers\noutmanipulate\noutmanipulated\noutmanipulates\noutmanipulating\noutmanned\noutmanning\noutmans\noutmarch\noutmarched\noutmarches\noutmarching\noutmatch\noutmatched\noutmatches\noutmatching\noutmode\noutmoded\noutmodes\noutmoding\noutmost\noutmove\noutmoved\noutmoves\noutmoving\noutmuscle\noutmuscled\noutmuscles\noutmuscling\noutnumber\noutnumbered\noutnumbering\noutnumbers\noutorganize\noutorganized\noutorganizes\noutorganizing\noutpace\noutpaced\noutpaces\noutpacing\noutpaint\noutpainted\noutpainting\noutpaints\noutpass\noutpassed\noutpasses\noutpassing\noutpatient\noutpatients\noutperform\noutperformed\noutperforming\noutperforms\noutpitch\noutpitched\noutpitches\noutpitching\noutpitied\noutpities\noutpity\noutpitying\noutplacement\noutplacements\noutplan\noutplanned\noutplanning\noutplans\noutplay\noutplayed\noutplaying\noutplays\noutplod\noutplodded\noutplodding\noutplods\noutplot\noutplots\noutplotted\noutplotting\noutpoint\noutpointed\noutpointing\noutpoints\noutpolitick\noutpoliticked\noutpoliticking\noutpoliticks\noutpoll\noutpolled\noutpolling\noutpolls\noutpopulate\noutpopulated\noutpopulates\noutpopulating\noutport\noutports\noutpost\noutposts\noutpour\noutpoured\noutpouring\noutpourings\noutpours\noutpower\noutpowered\noutpowering\noutpowers\noutpray\noutprayed\noutpraying\noutprays\noutpreach\noutpreached\noutpreaches\noutpreaching\noutpreen\noutpreened\noutpreening\noutpreens\noutpress\noutpressed\noutpresses\noutpressing\noutprice\noutpriced\noutprices\noutpricing\noutproduce\noutproduced\noutproduces\noutproducing\noutpromise\noutpromised\noutpromises\noutpromising\noutpull\noutpulled\noutpulling\noutpulls\noutpunch\noutpunched\noutpunches\noutpunching\noutpush\noutpushed\noutpushes\noutpushing\noutput\noutputs\noutputted\noutputting\noutquote\noutquoted\noutquotes\noutquoting\noutrace\noutraced\noutraces\noutracing\noutrage\noutraged\noutrageous\noutrageously\noutrageousness\noutrageousnesses\noutrages\noutraging\noutraise\noutraised\noutraises\noutraising\noutran\noutrance\noutrances\noutrang\noutrange\noutranged\noutranges\noutranging\noutrank\noutranked\noutranking\noutranks\noutrate\noutrated\noutrates\noutrating\noutrave\noutraved\noutraves\noutraving\noutre\noutreach\noutreached\noutreaches\noutreaching\noutread\noutreading\noutreads\noutrebound\noutrebounded\noutrebounding\noutrebounds\noutreproduce\noutreproduced\noutreproduces\noutreproducing\noutridden\noutride\noutrider\noutriders\noutrides\noutriding\noutrigger\noutriggers\noutright\noutrightly\noutring\noutringing\noutrings\noutrival\noutrivaled\noutrivaling\noutrivalled\noutrivalling\noutrivals\noutroar\noutroared\noutroaring\noutroars\noutrock\noutrocked\noutrocking\noutrocks\noutrode\noutroll\noutrolled\noutrolling\noutrolls\noutroot\noutrooted\noutrooting\noutroots\noutrow\noutrowed\noutrowing\noutrows\noutrun\noutrung\noutrunning\noutruns\noutrush\noutrushed\noutrushes\noutrushing\nouts\noutsail\noutsailed\noutsailing\noutsails\noutsang\noutsat\noutsavor\noutsavored\noutsavoring\noutsavors\noutsaw\noutscheme\noutschemed\noutschemes\noutscheming\noutscold\noutscolded\noutscolding\noutscolds\noutscoop\noutscooped\noutscooping\noutscoops\noutscore\noutscored\noutscores\noutscoring\noutscorn\noutscorned\noutscorning\noutscorns\noutsee\noutseeing\noutseen\noutsees\noutsell\noutselling\noutsells\noutsert\noutserts\noutserve\noutserved\noutserves\noutserving\noutset\noutsets\noutshame\noutshamed\noutshames\noutshaming\noutshine\noutshined\noutshines\noutshining\noutshone\noutshoot\noutshooting\noutshoots\noutshot\noutshout\noutshouted\noutshouting\noutshouts\noutside\noutsider\noutsiderness\noutsidernesses\noutsiders\noutsides\noutsight\noutsights\noutsin\noutsing\noutsinging\noutsings\noutsinned\noutsinning\noutsins\noutsit\noutsits\noutsitting\noutsize\noutsized\noutsizes\noutskate\noutskated\noutskates\noutskating\noutskirt\noutskirts\noutsleep\noutsleeping\noutsleeps\noutslept\noutslick\noutslicked\noutslicking\noutslicks\noutsmart\noutsmarted\noutsmarting\noutsmarts\noutsmile\noutsmiled\noutsmiles\noutsmiling\noutsmoke\noutsmoked\noutsmokes\noutsmoking\noutsnore\noutsnored\noutsnores\noutsnoring\noutsoar\noutsoared\noutsoaring\noutsoars\noutsold\noutsole\noutsoles\noutsourcing\noutsourcings\noutspan\noutspanned\noutspanning\noutspans\noutsparkle\noutsparkled\noutsparkles\noutsparkling\noutspeak\noutspeaking\noutspeaks\noutsped\noutspeed\noutspeeded\noutspeeding\noutspeeds\noutspell\noutspelled\noutspelling\noutspells\noutspelt\noutspend\noutspending\noutspends\noutspent\noutspoke\noutspoken\noutspokenly\noutspokenness\noutspokennesses\noutspread\noutspreading\noutspreads\noutsprint\noutsprinted\noutsprinting\noutsprints\noutstand\noutstanding\noutstandingly\noutstands\noutstare\noutstared\noutstares\noutstaring\noutstart\noutstarted\noutstarting\noutstarts\noutstate\noutstated\noutstates\noutstating\noutstation\noutstations\noutstay\noutstayed\noutstaying\noutstays\noutsteer\noutsteered\noutsteering\noutsteers\noutstood\noutstretch\noutstretched\noutstretches\noutstretching\noutstridden\noutstride\noutstrides\noutstriding\noutstrip\noutstripped\noutstripping\noutstrips\noutstrode\noutstudied\noutstudies\noutstudy\noutstudying\noutstunt\noutstunted\noutstunting\noutstunts\noutsulk\noutsulked\noutsulking\noutsulks\noutsung\noutswam\noutsware\noutswear\noutswearing\noutswears\noutswim\noutswimming\noutswims\noutswore\noutsworn\noutswum\nouttake\nouttakes\nouttalk\nouttalked\nouttalking\nouttalks\nouttask\nouttasked\nouttasking\nouttasks\nouttell\nouttelling\nouttells\noutthank\noutthanked\noutthanking\noutthanks\noutthink\noutthinking\noutthinks\noutthought\noutthrew\noutthrob\noutthrobbed\noutthrobbing\noutthrobs\noutthrow\noutthrowing\noutthrown\noutthrows\noutthrust\noutthrusting\noutthrusts\nouttold\nouttower\nouttowered\nouttowering\nouttowers\nouttrade\nouttraded\nouttrades\nouttrading\nouttrick\nouttricked\nouttricking\nouttricks\nouttrot\nouttrots\nouttrotted\nouttrotting\nouttrump\nouttrumped\nouttrumping\nouttrumps\noutturn\noutturns\noutvalue\noutvalued\noutvalues\noutvaluing\noutvaunt\noutvaunted\noutvaunting\noutvaunts\noutvie\noutvied\noutvies\noutvoice\noutvoiced\noutvoices\noutvoicing\noutvote\noutvoted\noutvotes\noutvoting\noutvying\noutwait\noutwaited\noutwaiting\noutwaits\noutwalk\noutwalked\noutwalking\noutwalks\noutwar\noutward\noutwardly\noutwardness\noutwardnesses\noutwards\noutwarred\noutwarring\noutwars\noutwash\noutwashes\noutwaste\noutwasted\noutwastes\noutwasting\noutwatch\noutwatched\noutwatches\noutwatching\noutwear\noutwearied\noutwearies\noutwearing\noutwears\noutweary\noutwearying\noutweep\noutweeping\noutweeps\noutweigh\noutweighed\noutweighing\noutweighs\noutwent\noutwept\noutwhirl\noutwhirled\noutwhirling\noutwhirls\noutwile\noutwiled\noutwiles\noutwiling\noutwill\noutwilled\noutwilling\noutwills\noutwind\noutwinded\noutwinding\noutwinds\noutwish\noutwished\noutwishes\noutwishing\noutwit\noutwits\noutwitted\noutwitting\noutwore\noutwork\noutworked\noutworker\noutworkers\noutworking\noutworks\noutworn\noutwrestle\noutwrestled\noutwrestles\noutwrestling\noutwrit\noutwrite\noutwrites\noutwriting\noutwritten\noutwrote\noutwrought\noutyell\noutyelled\noutyelling\noutyells\noutyelp\noutyelped\noutyelping\noutyelps\noutyield\noutyielded\noutyielding\noutyields\nouzel\nouzels\nouzo\nouzos\nova\noval\novalbumin\novalbumins\novalities\novality\novally\novalness\novalnesses\novals\novarial\novarian\novariectomies\novariectomized\novariectomy\novaries\novariole\novarioles\novariotomies\novariotomy\novaritides\novaritis\novary\novate\novately\novation\novations\noven\novenbird\novenbirds\novenlike\novenproof\novens\novenware\novenwares\nover\noverable\noverabstract\noverabstracted\noverabstracting\noverabstracts\noverabundance\noverabundances\noverabundant\noveraccentuate\noveraccentuated\noveraccentuates\noveraccentuating\noverachieve\noverachieved\noverachievement\noverachievements\noverachiever\noverachievers\noverachieves\noverachieving\noveract\noveracted\noveracting\noveraction\noveractions\noveractive\noveractivities\noveractivity\noveracts\noveradjustment\noveradjustments\noveradvertise\noveradvertised\noveradvertises\noveradvertising\noverage\noveraged\noverages\noveraggressive\noveralert\noverall\noveralled\noveralls\noverambitious\noverambitiousness\noverambitiousnesses\noveramplified\noveranalyses\noveranalysis\noveranalytical\noveranalyze\noveranalyzed\noveranalyzes\noveranalyzing\noveranxieties\noveranxiety\noveranxious\noverapplication\noverapplications\noverapt\noverarch\noverarched\noverarches\noverarching\noverarm\noverarousal\noverarousals\noverarrange\noverarranged\noverarranges\noverarranging\noverarticulate\noverarticulated\noverarticulates\noverarticulating\noverassert\noverasserted\noverasserting\noverassertion\noverassertions\noverassertive\noverasserts\noverassessment\noverassessments\noverate\noverattention\noverattentions\noverawe\noverawed\noverawes\noverawing\noverbake\noverbaked\noverbakes\noverbaking\noverbalance\noverbalanced\noverbalances\noverbalancing\noverbear\noverbearing\noverbearingly\noverbears\noverbeat\noverbeaten\noverbeating\noverbeats\noverbed\noverbejeweled\noverbet\noverbets\noverbetted\noverbetting\noverbid\noverbidden\noverbidder\noverbidders\noverbidding\noverbids\noverbig\noverbill\noverbilled\noverbilling\noverbills\noverbite\noverbites\noverbleach\noverbleached\noverbleaches\noverbleaching\noverblew\noverblouse\noverblouses\noverblow\noverblowing\noverblown\noverblows\noverboard\noverboil\noverboiled\noverboiling\noverboils\noverbold\noverbook\noverbooked\noverbooking\noverbooks\noverbore\noverborn\noverborne\noverborrow\noverborrowed\noverborrowing\noverborrows\noverbought\noverbreathing\noverbreathings\noverbred\noverbrief\noverbright\noverbroad\noverbrowse\noverbrowsed\noverbrowses\noverbrowsing\noverbrutal\noverbuild\noverbuilding\noverbuilds\noverbuilt\noverburden\noverburdened\noverburdening\noverburdens\noverburn\noverburned\noverburning\noverburns\noverburnt\noverbusy\noverbuy\noverbuying\noverbuys\novercall\novercalled\novercalling\novercalls\novercame\novercapacities\novercapacity\novercapitalization\novercapitalizations\novercapitalize\novercapitalized\novercapitalizes\novercapitalizing\novercareful\novercast\novercasted\novercasting\novercastings\novercasts\novercaution\novercautioned\novercautioning\novercautions\novercautious\novercentralization\novercentralizations\novercentralize\novercentralized\novercentralizes\novercentralizing\novercharge\novercharged\novercharges\novercharging\noverchill\noverchilled\noverchilling\noverchills\novercivilized\noverclaim\noverclaimed\noverclaiming\noverclaims\noverclassification\noverclassifications\noverclassified\noverclassifies\noverclassify\noverclassifying\noverclean\novercleaned\novercleaning\novercleans\noverclear\novercleared\noverclearing\noverclears\novercloud\noverclouded\noverclouding\noverclouds\novercoach\novercoached\novercoaches\novercoaching\novercoat\novercoats\novercold\novercome\novercomer\novercomers\novercomes\novercoming\novercommercialization\novercommercializations\novercommercialize\novercommercialized\novercommercializes\novercommercializing\novercommit\novercommitment\novercommitments\novercommits\novercommitted\novercommitting\novercommunicate\novercommunicated\novercommunicates\novercommunicating\novercommunication\novercommunications\novercompensate\novercompensated\novercompensates\novercompensating\novercompensation\novercompensations\novercompensatory\novercomplex\novercompliance\novercompliances\novercomplicate\novercomplicated\novercomplicates\novercomplicating\novercompress\novercompressed\novercompresses\novercompressing\noverconcentration\noverconcentrations\noverconcern\noverconcerned\noverconcerning\noverconcerns\noverconfidence\noverconfidences\noverconfident\noverconfidently\noverconscientious\noverconscious\noverconservative\noverconstruct\noverconstructed\noverconstructing\noverconstructs\noverconsume\noverconsumed\noverconsumes\noverconsuming\noverconsumption\noverconsumptions\novercontrol\novercontrolled\novercontrolling\novercontrols\novercook\novercooked\novercooking\novercooks\novercool\novercooled\novercooling\novercools\novercorrect\novercorrected\novercorrecting\novercorrection\novercorrections\novercorrects\novercount\novercounted\novercounting\novercounts\novercoy\novercram\novercrammed\novercramming\novercrams\novercredulous\novercritical\novercrop\novercropped\novercropping\novercrops\novercrowd\novercrowded\novercrowding\novercrowds\novercultivation\novercultivations\novercure\novercured\novercures\novercuring\novercut\novercuts\novercutting\noverdare\noverdared\noverdares\noverdaring\noverdear\noverdeck\noverdecked\noverdecking\noverdecks\noverdecorate\noverdecorated\noverdecorates\noverdecorating\noverdecoration\noverdecorations\noverdemanding\noverdependence\noverdependences\noverdependent\noverdesign\noverdesigned\noverdesigning\noverdesigns\noverdetermined\noverdevelop\noverdeveloped\noverdeveloping\noverdevelopment\noverdevelopments\noverdevelops\noverdid\noverdifferentiation\noverdifferentiations\noverdirect\noverdirected\noverdirecting\noverdirects\noverdiscount\noverdiscounted\noverdiscounting\noverdiscounts\noverdiversified\noverdiversities\noverdiversity\noverdo\noverdocument\noverdocumented\noverdocumenting\noverdocuments\noverdoer\noverdoers\noverdoes\noverdog\noverdogs\noverdoing\noverdominance\noverdominances\noverdominant\noverdone\noverdosage\noverdosages\noverdose\noverdosed\noverdoses\noverdosing\noverdraft\noverdrafts\noverdramatic\noverdramatize\noverdramatized\noverdramatizes\noverdramatizing\noverdrank\noverdraw\noverdrawing\noverdrawn\noverdraws\noverdress\noverdressed\noverdresses\noverdressing\noverdrew\noverdried\noverdries\noverdrink\noverdrinking\noverdrinks\noverdrive\noverdriven\noverdrives\noverdriving\noverdrove\noverdrunk\noverdry\noverdrying\noverdub\noverdubbed\noverdubbing\noverdubs\noverdue\noverdye\noverdyed\noverdyeing\noverdyes\novereager\novereagerness\novereagernesses\noverearnest\novereasy\novereat\novereaten\novereater\novereaters\novereating\novereats\novered\noveredit\noveredited\noverediting\noveredits\novereducate\novereducated\novereducates\novereducating\novereducation\novereducations\noverelaborate\noverelaborated\noverelaborates\noverelaborating\noverelaboration\noverelaborations\noverembellish\noverembellished\noverembellishes\noverembellishing\noverembellishment\noverembellishments\noveremote\noveremoted\noveremotes\noveremoting\noveremotional\noveremphases\noveremphasis\noveremphasize\noveremphasized\noveremphasizes\noveremphasizing\noveremphatic\noverenamored\noverencourage\noverencouraged\noverencourages\noverencouraging\noverenergetic\noverengineer\noverengineered\noverengineering\noverengineers\noverenrolled\noverentertained\noverenthusiasm\noverenthusiasms\noverenthusiastic\noverenthusiastically\noverequipped\noverestimate\noverestimated\noverestimates\noverestimating\noverestimation\noverestimations\noverevaluation\noverevaluations\noverexaggerate\noverexaggerated\noverexaggerates\noverexaggerating\noverexaggeration\noverexaggerations\noverexcite\noverexcited\noverexcites\noverexciting\noverexercise\noverexercised\noverexercises\noverexercising\noverexert\noverexerted\noverexerting\noverexertion\noverexertions\noverexerts\noverexpand\noverexpanded\noverexpanding\noverexpands\noverexpansion\noverexpansions\noverexpectation\noverexpectations\noverexplain\noverexplained\noverexplaining\noverexplains\noverexplicit\noverexploit\noverexploitation\noverexploitations\noverexploited\noverexploiting\noverexploits\noverexpose\noverexposed\noverexposes\noverexposing\noverexposure\noverexposures\noverextend\noverextended\noverextending\noverextends\noverextension\noverextensions\noverextraction\noverextractions\noverextrapolation\noverextrapolations\noverextravagant\noverexuberant\noverfacile\noverfamiliar\noverfamiliarities\noverfamiliarity\noverfar\noverfast\noverfastidious\noverfat\noverfatigue\noverfatigued\noverfatigues\noverfavor\noverfavored\noverfavoring\noverfavors\noverfear\noverfeared\noverfearing\noverfears\noverfed\noverfeed\noverfeeding\noverfeeds\noverfertilization\noverfertilizations\noverfertilize\noverfertilized\noverfertilizes\noverfertilizing\noverfill\noverfilled\noverfilling\noverfills\noverfish\noverfished\noverfishes\noverfishing\noverflew\noverflies\noverflight\noverflights\noverflow\noverflowed\noverflowing\noverflown\noverflows\noverfly\noverflying\noverfocus\noverfocused\noverfocuses\noverfocusing\noverfocussed\noverfocusses\noverfocussing\noverfond\noverfoul\noverfree\noverfulfill\noverfulfilled\noverfulfilling\noverfulfills\noverfull\noverfund\noverfunded\noverfunding\noverfunds\noverfussy\novergarment\novergarments\novergeneralization\novergeneralizations\novergeneralize\novergeneralized\novergeneralizes\novergeneralizing\novergenerosities\novergenerosity\novergenerous\novergenerously\novergild\novergilded\novergilding\novergilds\novergilt\novergird\novergirded\novergirding\novergirds\novergirt\noverglad\noverglamorize\noverglamorized\noverglamorizes\noverglamorizing\noverglaze\noverglazes\novergoad\novergoaded\novergoading\novergoads\novergovern\novergoverned\novergoverning\novergoverns\novergraze\novergrazed\novergrazes\novergrazing\novergrew\novergrow\novergrowing\novergrown\novergrows\novergrowth\novergrowths\noverhand\noverhanded\noverhanding\noverhandle\noverhandled\noverhandles\noverhandling\noverhands\noverhang\noverhanging\noverhangs\noverhard\noverharvest\noverharvested\noverharvesting\noverharvests\noverhasty\noverhate\noverhated\noverhates\noverhating\noverhaul\noverhauled\noverhauling\noverhauls\noverhead\noverheads\noverheap\noverheaped\noverheaping\noverheaps\noverhear\noverheard\noverhearing\noverhears\noverheat\noverheated\noverheating\noverheats\noverheld\noverhigh\noverhold\noverholding\noverholds\noverholy\noverhomogenize\noverhomogenized\noverhomogenizes\noverhomogenizing\noverhope\noverhoped\noverhopes\noverhoping\noverhot\noverhung\noverhunt\noverhunted\noverhunting\noverhuntings\noverhunts\noverhype\noverhyped\noverhypes\noverhyping\noveridealistic\noveridealize\noveridealized\noveridealizes\noveridealizing\noveridentification\noveridentifications\noveridentified\noveridentifies\noveridentify\noveridentifying\noveridle\noverimaginative\noverimpress\noverimpressed\noverimpresses\noverimpressing\noverindebtedness\noverindebtednesses\noverindulge\noverindulged\noverindulgence\noverindulgences\noverindulgent\noverindulges\noverindulging\noverindustrialize\noverindustrialized\noverindustrializes\noverindustrializing\noverinflate\noverinflated\noverinflates\noverinflating\noverinflation\noverinflations\noverinform\noverinformed\noverinforming\noverinforms\novering\noveringenious\noveringenuities\noveringenuity\noverinsistent\noverinsure\noverinsured\noverinsures\noverinsuring\noverintellectualization\noverintellectualizations\noverintellectualize\noverintellectualized\noverintellectualizes\noverintellectualizing\noverintense\noverintensities\noverintensity\noverinterpretation\noverinterpretations\noverinvestment\noverinvestments\noverissuance\noverissuances\noverissue\noverissued\noverissues\noverissuing\noverjoy\noverjoyed\noverjoying\noverjoys\noverjust\noverkeen\noverkill\noverkilled\noverkilling\noverkills\noverkind\noverlabor\noverlabored\noverlaboring\noverlabors\noverlade\noverladed\noverladen\noverlades\noverlading\noverlaid\noverlain\noverland\noverlands\noverlap\noverlapped\noverlapping\noverlaps\noverlarge\noverlate\noverlavish\noverlax\noverlay\noverlaying\noverlays\noverleaf\noverleap\noverleaped\noverleaping\noverleaps\noverleapt\noverlearn\noverlearned\noverlearning\noverlearns\noverlend\noverlending\noverlends\noverlength\noverlengthen\noverlengthened\noverlengthening\noverlengthens\noverlent\noverlet\noverlets\noverletting\noverlewd\noverlie\noverlies\noverlight\noverlighted\noverlighting\noverlights\noverlit\noverliteral\noverliterary\noverlive\noverlived\noverlives\noverliving\noverload\noverloaded\noverloading\noverloads\noverlong\noverlook\noverlooked\noverlooking\noverlooks\noverlord\noverlorded\noverlording\noverlords\noverlordship\noverlordships\noverloud\noverlove\noverloved\noverloves\noverloving\noverlush\noverly\noverlying\noverman\novermanage\novermanaged\novermanages\novermanaging\novermanned\novermannered\novermanning\novermans\novermantel\novermantels\novermany\novermaster\novermastered\novermastering\novermasters\novermatch\novermatched\novermatches\novermatching\novermature\novermaturities\novermaturity\novermedicate\novermedicated\novermedicates\novermedicating\novermedication\novermedications\novermeek\novermelt\novermelted\novermelting\novermelts\novermen\novermighty\novermild\novermilk\novermilked\novermilking\novermilks\novermine\novermined\novermines\novermining\novermix\novermixed\novermixes\novermixing\novermodest\novermodestly\novermodulated\novermuch\novermuches\novermuscled\novernear\noverneat\novernew\novernice\novernight\novernighted\novernighter\novernighters\novernighting\novernights\novernourish\novernourished\novernourishes\novernourishing\novernutrition\novernutritions\noverobvious\noveroperate\noveroperated\noveroperates\noveroperating\noveropinionated\noveroptimism\noveroptimisms\noveroptimist\noveroptimistic\noveroptimistically\noveroptimists\noverorchestrate\noverorchestrated\noverorchestrates\noverorchestrating\noverorganize\noverorganized\noverorganizes\noverorganizing\noverornament\noverornamented\noverornamenting\noverornaments\noverpackage\noverpackaged\noverpackages\noverpackaging\noverpaid\noverparticular\noverpass\noverpassed\noverpasses\noverpassing\noverpast\noverpay\noverpaying\noverpayment\noverpayments\noverpays\noverpedal\noverpedaled\noverpedaling\noverpedalled\noverpedalling\noverpedals\noverpeople\noverpeopled\noverpeoples\noverpeopling\noverpersuade\noverpersuaded\noverpersuades\noverpersuading\noverpersuasion\noverpersuasions\noverpert\noverplaid\noverplaided\noverplaids\noverplan\noverplanned\noverplanning\noverplans\noverplant\noverplanted\noverplanting\noverplants\noverplay\noverplayed\noverplaying\noverplays\noverplied\noverplies\noverplot\noverplots\noverplotted\noverplotting\noverplus\noverpluses\noverply\noverplying\noverpopulate\noverpopulated\noverpopulates\noverpopulating\noverpopulation\noverpopulations\noverpotent\noverpower\noverpowered\noverpowering\noverpoweringly\noverpowers\noverpraise\noverpraised\noverpraises\noverpraising\noverprecise\noverprescribe\noverprescribed\noverprescribes\noverprescribing\noverprescription\noverprescriptions\noverpressure\noverpressures\noverprice\noverpriced\noverprices\noverpricing\noverprint\noverprinted\noverprinting\noverprints\noverprivileged\noverprize\noverprized\noverprizes\noverprizing\noverprocess\noverprocessed\noverprocesses\noverprocessing\noverproduce\noverproduced\noverproduces\noverproducing\noverproduction\noverproductions\noverprogram\noverprogramed\noverprograming\noverprogrammed\noverprogramming\noverprograms\noverpromise\noverpromised\noverpromises\noverpromising\noverpromote\noverpromoted\noverpromotes\noverpromoting\noverproof\noverproportion\noverproportionate\noverproportionately\noverproportioned\noverproportioning\noverproportions\noverprotect\noverprotected\noverprotecting\noverprotection\noverprotections\noverprotective\noverprotectiveness\noverprotectivenesses\noverprotects\noverpump\noverpumped\noverpumping\noverpumps\noverqualified\noverran\noverrank\noverrash\noverrate\noverrated\noverrates\noverrating\noverreach\noverreached\noverreacher\noverreachers\noverreaches\noverreaching\noverreact\noverreacted\noverreacting\noverreaction\noverreactions\noverreacts\noverrefined\noverrefinement\noverrefinements\noverregulate\noverregulated\noverregulates\noverregulating\noverregulation\noverregulations\noverreliance\noverreliances\noverreport\noverreported\noverreporting\noverreports\noverrepresentation\noverrepresentations\noverrepresented\noverrespond\noverresponded\noverresponding\noverresponds\noverrich\noverridden\noverride\noverrides\noverriding\noverrife\noverrigid\noverripe\noverrode\noverrude\noverruff\noverruffed\noverruffing\noverruffs\noverrule\noverruled\noverrules\noverruling\noverrun\noverrunning\noverruns\novers\noversad\noversale\noversales\noversalt\noversalted\noversalting\noversalts\noversanguine\noversaturate\noversaturated\noversaturates\noversaturating\noversaturation\noversaturations\noversauce\noversauced\noversauces\noversaucing\noversave\noversaved\noversaves\noversaving\noversaw\noverscale\noverscaled\noverscrupulous\noversea\noverseas\noversecretion\noversecretions\noversee\noverseed\noverseeded\noverseeding\noverseeds\noverseeing\noverseen\noverseer\noverseers\noversees\noversell\noverselling\noversells\noversensitive\noversensitiveness\noversensitivenesses\noversensitivities\noversensitivity\noverserious\noverseriously\noverservice\noverserviced\noverservices\noverservicing\noverset\noversets\noversetting\noversew\noversewed\noversewing\noversewn\noversews\noversexed\novershadow\novershadowed\novershadowing\novershadows\novershirt\novershirts\novershoe\novershoes\novershoot\novershooting\novershoots\novershot\novershots\noversick\noverside\noversides\noversight\noversights\noversimple\noversimplification\noversimplifications\noversimplified\noversimplifies\noversimplify\noversimplifying\noversimplistic\noversimply\noversize\noversized\noversizes\noverskirt\noverskirts\noverslaugh\noverslaughed\noverslaughing\noverslaughs\noversleep\noversleeping\noversleeps\noverslept\noverslip\noverslipped\noverslipping\noverslips\noverslipt\noverslow\noversmoke\noversmoked\noversmokes\noversmoking\noversoak\noversoaked\noversoaking\noversoaks\noversoft\noversold\noversolicitous\noversoon\noversophisticated\noversoul\noversouls\noverspecialization\noverspecializations\noverspecialize\noverspecialized\noverspecializes\noverspecializing\noverspeculate\noverspeculated\noverspeculates\noverspeculating\noverspeculation\noverspeculations\noverspend\noverspender\noverspenders\noverspending\noverspends\noverspent\noverspill\noverspills\noverspin\noverspins\noverspread\noverspreading\noverspreads\noverstabilities\noverstability\noverstaff\noverstaffed\noverstaffing\noverstaffs\noverstate\noverstated\noverstatement\noverstatements\noverstates\noverstating\noverstay\noverstayed\noverstaying\noverstays\noversteer\noversteers\noverstep\noverstepped\noverstepping\noversteps\noverstimulate\noverstimulated\noverstimulates\noverstimulating\noverstimulation\noverstimulations\noverstir\noverstirred\noverstirring\noverstirs\noverstock\noverstocked\noverstocking\noverstocks\noverstories\noverstory\noverstrain\noverstrained\noverstraining\noverstrains\noverstress\noverstressed\noverstresses\noverstressing\noverstretch\noverstretched\noverstretches\noverstretching\noverstrew\noverstrewed\noverstrewing\noverstrewn\noverstrews\noverstridden\noverstride\noverstrides\noverstriding\noverstrike\noverstrikes\noverstriking\noverstrode\noverstruck\noverstructured\noverstrung\noverstuff\noverstuffed\noverstuffing\noverstuffs\noversubscribe\noversubscribed\noversubscribes\noversubscribing\noversubscription\noversubscriptions\noversubtle\noversuds\noversudsed\noversudses\noversudsing\noversup\noversupped\noversupping\noversupplied\noversupplies\noversupply\noversupplying\noversups\noversure\noversuspicious\noversweet\noversweeten\noversweetened\noversweetening\noversweetens\noversweetness\noversweetnesses\noverswing\noverswinging\noverswings\noverswung\novert\novertake\novertaken\novertakes\novertaking\novertalk\novertalkative\novertalked\novertalking\novertalks\novertame\novertart\novertask\novertasked\novertasking\novertasks\novertax\novertaxation\novertaxations\novertaxed\novertaxes\novertaxing\noverthin\noverthink\noverthinking\noverthinks\noverthought\noverthrew\noverthrow\noverthrowing\noverthrown\noverthrows\novertighten\novertightened\novertightening\novertightens\novertime\novertimed\novertimes\novertiming\novertip\novertipped\novertipping\novertips\novertire\novertired\novertires\novertiring\novertly\novertness\novertnesses\novertoil\novertoiled\novertoiling\novertoils\novertone\novertones\novertook\novertop\novertopped\novertopping\novertops\novertrade\novertraded\novertrades\novertrading\novertrain\novertrained\novertraining\novertrains\novertreat\novertreated\novertreating\novertreatment\novertreatments\novertreats\novertrick\novertricks\novertrim\novertrimmed\novertrimming\novertrims\novertrump\novertrumped\novertrumping\novertrumps\noverture\novertured\novertures\noverturing\noverturn\noverturned\noverturning\noverturns\noverurge\noverurged\noverurges\noverurging\noveruse\noverused\noveruses\noverusing\noverutilization\noverutilizations\noverutilize\noverutilized\noverutilizes\noverutilizing\novervaluation\novervaluations\novervalue\novervalued\novervalues\novervaluing\noverview\noverviews\noverviolent\novervivid\novervoltage\novervoltages\novervote\novervoted\novervotes\novervoting\noverwarm\noverwarmed\noverwarming\noverwarms\noverwary\noverwater\noverwatered\noverwatering\noverwaters\noverweak\noverwear\noverwearing\noverwears\noverweary\noverween\noverweened\noverweening\noverweeningly\noverweens\noverweigh\noverweighed\noverweighing\noverweighs\noverweight\noverweighted\noverweighting\noverweights\noverwet\noverwets\noverwetted\noverwetting\noverwhelm\noverwhelmed\noverwhelming\noverwhelmingly\noverwhelms\noverwide\noverwily\noverwind\noverwinding\noverwinds\noverwinter\noverwintered\noverwintering\noverwinters\noverwise\noverwithheld\noverwithhold\noverwithholding\noverwithholds\noverword\noverwords\noverwore\noverwork\noverworked\noverworking\noverworks\noverworn\noverwound\noverwrite\noverwrites\noverwriting\noverwritten\noverwrote\noverwrought\noverzeal\noverzealous\noverzealously\noverzealousness\noverzealousnesses\noverzeals\novibos\novicidal\novicide\novicides\noviducal\noviduct\noviductal\noviducts\noviform\novine\novines\novipara\noviparous\noviposit\noviposited\novipositing\noviposition\novipositional\novipositions\novipositor\novipositors\noviposits\novisac\novisacs\novoid\novoidal\novoids\novolactovegetarian\novolactovegetarians\novoli\novolo\novolos\novonic\novonics\novotestes\novotestis\novoviviparous\novoviviparously\novoviviparousness\novoviviparousnesses\novular\novulary\novulate\novulated\novulates\novulating\novulation\novulations\novulatory\novule\novules\novum\now\nowe\nowed\nowes\nowing\nowl\nowlet\nowlets\nowlish\nowlishly\nowlishness\nowlishnesses\nowllike\nowls\nown\nownable\nowned\nowner\nowners\nownership\nownerships\nowning\nowns\nowse\nowsen\nox\noxacillin\noxacillins\noxalacetate\noxalacetates\noxalate\noxalated\noxalates\noxalating\noxalic\noxalis\noxalises\noxaloacetate\noxaloacetates\noxazepam\noxazepams\noxazine\noxazines\noxblood\noxbloods\noxbow\noxbows\noxcart\noxcarts\noxen\noxes\noxeye\noxeyes\noxford\noxfords\noxheart\noxhearts\noxid\noxidable\noxidant\noxidants\noxidase\noxidases\noxidasic\noxidate\noxidated\noxidates\noxidating\noxidation\noxidations\noxidative\noxidatively\noxide\noxides\noxidic\noxidise\noxidised\noxidiser\noxidisers\noxidises\noxidising\noxidizable\noxidize\noxidized\noxidizer\noxidizers\noxidizes\noxidizing\noxidoreductase\noxidoreductases\noxids\noxim\noxime\noximes\noxims\noxlip\noxlips\noxo\noxpecker\noxpeckers\noxtail\noxtails\noxter\noxters\noxtongue\noxtongues\noxy\noxyacetylene\noxyacid\noxyacids\noxygen\noxygenate\noxygenated\noxygenates\noxygenating\noxygenation\noxygenations\noxygenator\noxygenators\noxygenic\noxygenless\noxygens\noxyhemoglobin\noxyhemoglobins\noxyhydrogen\noxymora\noxymoron\noxymoronic\noxymoronically\noxymorons\noxyphenbutazone\noxyphenbutazones\noxyphil\noxyphile\noxyphiles\noxyphilic\noxyphils\noxysalt\noxysalts\noxysome\noxysomes\noxytetracycline\noxytetracyclines\noxytocic\noxytocics\noxytocin\noxytocins\noxytone\noxytones\noxyuriases\noxyuriasis\noy\noyer\noyers\noyes\noyesses\noyez\noyster\noystercatcher\noystercatchers\noystered\noysterer\noysterers\noystering\noysterings\noysterman\noystermen\noysters\nozocerite\nozocerites\nozokerite\nozokerites\nozonate\nozonated\nozonates\nozonating\nozonation\nozonations\nozone\nozones\nozonic\nozonide\nozonides\nozonise\nozonised\nozonises\nozonising\nozonization\nozonizations\nozonize\nozonized\nozonizer\nozonizers\nozonizes\nozonizing\nozonosphere\nozonospheres\nozonous\npa\npablum\npablums\npabular\npabulum\npabulums\npac\npaca\npacas\npace\npaced\npacemaker\npacemakers\npacemaking\npacemakings\npacer\npacers\npaces\npacesetter\npacesetters\npacesetting\npacha\npachadom\npachadoms\npachalic\npachalics\npachas\npachinko\npachinkos\npachisi\npachisis\npachouli\npachoulis\npachuco\npachucos\npachyderm\npachydermatous\npachyderms\npachysandra\npachysandras\npachytene\npachytenes\npacifiable\npacific\npacifically\npacification\npacifications\npacificator\npacificators\npacificism\npacificisms\npacificist\npacificists\npacified\npacifier\npacifiers\npacifies\npacifism\npacifisms\npacifist\npacifistic\npacifistically\npacifists\npacify\npacifying\npacing\npack\npackabilities\npackability\npackable\npackage\npackaged\npackager\npackagers\npackages\npackaging\npackboard\npackboards\npacked\npacker\npackers\npacket\npacketed\npacketing\npackets\npackhorse\npackhorses\npacking\npackinghouse\npackinghouses\npackings\npackly\npackman\npackmen\npackness\npacknesses\npacks\npacksack\npacksacks\npacksaddle\npacksaddles\npackthread\npackthreads\npackwax\npackwaxes\npaclitaxel\npaclitaxels\npacs\npact\npaction\npactions\npacts\npad\npadauk\npadauks\npadded\npadder\npadders\npaddies\npadding\npaddings\npaddle\npaddleball\npaddleballs\npaddleboard\npaddleboards\npaddleboat\npaddleboats\npaddled\npaddlefish\npaddlefishes\npaddler\npaddlers\npaddles\npaddling\npaddlings\npaddock\npaddocked\npaddocking\npaddocks\npaddy\npadi\npadis\npadishah\npadishahs\npadle\npadles\npadlock\npadlocked\npadlocking\npadlocks\npadnag\npadnags\npadouk\npadouks\npadre\npadres\npadri\npadrone\npadrones\npadroni\npads\npadshah\npadshahs\npaduasoy\npaduasoys\npaean\npaeanism\npaeanisms\npaeans\npaediatric\npaediatrician\npaediatricians\npaediatrics\npaedogeneses\npaedogenesis\npaedogenetic\npaedogenetically\npaedogenic\npaedomorphic\npaedomorphism\npaedomorphisms\npaedomorphoses\npaedomorphosis\npaella\npaellas\npaeon\npaeons\npaesan\npaesani\npaesano\npaesanos\npaesans\npagan\npagandom\npagandoms\npaganise\npaganised\npaganises\npaganish\npaganising\npaganism\npaganisms\npaganist\npaganists\npaganize\npaganized\npaganizer\npaganizers\npaganizes\npaganizing\npagans\npage\npageant\npageantries\npageantry\npageants\npageboy\npageboys\npaged\npager\npagers\npages\npaginal\npaginate\npaginated\npaginates\npaginating\npagination\npaginations\npaging\npagings\npagod\npagoda\npagodas\npagods\npagurian\npagurians\npagurid\npagurids\npah\npahlavi\npahlavis\npahoehoe\npahoehoes\npaid\npaik\npaiked\npaiking\npaiks\npail\npailful\npailfuls\npaillard\npaillards\npaillette\npaillettes\npails\npailsful\npain\npainch\npainches\npained\npainful\npainfuller\npainfullest\npainfully\npainfulness\npainfulnesses\npaining\npainkiller\npainkillers\npainkilling\npainless\npainlessly\npainlessness\npainlessnesses\npains\npainstaking\npainstakingly\npainstakings\npaint\npaintbrush\npaintbrushes\npainted\npainter\npainterliness\npainterlinesses\npainterly\npainters\npaintier\npaintiest\npainting\npaintings\npaints\npaintwork\npaintworks\npainty\npair\npaired\npairing\npairings\npairs\npaisa\npaisan\npaisana\npaisanas\npaisano\npaisanos\npaisans\npaisas\npaise\npaisley\npaisleys\npajama\npajamaed\npajamas\npakeha\npakehas\npal\npalabra\npalabras\npalace\npalaced\npalaces\npaladin\npaladins\npalaestra\npalaestrae\npalaestras\npalais\npalanquin\npalanquins\npalatabilities\npalatability\npalatable\npalatableness\npalatablenesses\npalatably\npalatal\npalatalization\npalatalizations\npalatalize\npalatalized\npalatalizes\npalatalizing\npalatally\npalatals\npalate\npalates\npalatial\npalatially\npalatialness\npalatialnesses\npalatinate\npalatinates\npalatine\npalatines\npalaver\npalavered\npalavering\npalavers\npalazzi\npalazzo\npalazzos\npale\npalea\npaleae\npaleal\npaled\npaleface\npalefaces\npalely\npaleness\npalenesses\npaleoanthropological\npaleoanthropologies\npaleoanthropologist\npaleoanthropologists\npaleoanthropology\npaleobiologic\npaleobiological\npaleobiologies\npaleobiologist\npaleobiologists\npaleobiology\npaleobotanic\npaleobotanical\npaleobotanically\npaleobotanies\npaleobotanist\npaleobotanists\npaleobotany\npaleoclimatologies\npaleoclimatologist\npaleoclimatologists\npaleoclimatology\npaleoecologic\npaleoecological\npaleoecologies\npaleoecologist\npaleoecologists\npaleoecology\npaleogeographic\npaleogeographical\npaleogeographically\npaleogeographies\npaleogeography\npaleographer\npaleographers\npaleographic\npaleographical\npaleographically\npaleographies\npaleography\npaleomagnetic\npaleomagnetically\npaleomagnetism\npaleomagnetisms\npaleomagnetist\npaleomagnetists\npaleontologic\npaleontological\npaleontologies\npaleontologist\npaleontologists\npaleontology\npaleopathological\npaleopathologies\npaleopathologist\npaleopathologists\npaleopathology\npaleosol\npaleosols\npaleozoological\npaleozoologies\npaleozoologist\npaleozoologists\npaleozoology\npaler\npales\npalest\npalestra\npalestrae\npalestras\npalet\npaletot\npaletots\npalets\npalette\npalettes\npaleways\npalewise\npalfrey\npalfreys\npalier\npaliest\npalikar\npalikars\npalimonies\npalimony\npalimpsest\npalimpsests\npalindrome\npalindromes\npalindromic\npalindromist\npalindromists\npaling\npalingeneses\npalingenesis\npalingenetic\npalings\npalinode\npalinodes\npalisade\npalisaded\npalisades\npalisading\npalish\npall\npalladia\npalladic\npalladium\npalladiums\npalladous\npallbearer\npallbearers\npalled\npallet\npalletise\npalletised\npalletises\npalletising\npalletization\npalletizations\npalletize\npalletized\npalletizer\npalletizers\npalletizes\npalletizing\npallets\npallette\npallettes\npallia\npallial\npalliasse\npalliasses\npalliate\npalliated\npalliates\npalliating\npalliation\npalliations\npalliative\npalliatively\npalliatives\npalliator\npalliators\npallid\npallidly\npallidness\npallidnesses\npallier\npalliest\npalling\npallium\npalliums\npallor\npallors\npalls\npally\npalm\npalmar\npalmary\npalmate\npalmated\npalmately\npalmation\npalmations\npalmed\npalmer\npalmers\npalmerworm\npalmerworms\npalmette\npalmettes\npalmetto\npalmettoes\npalmettos\npalmier\npalmiest\npalming\npalmist\npalmistries\npalmistry\npalmists\npalmitate\npalmitates\npalmitin\npalmitins\npalmlike\npalms\npalmy\npalmyra\npalmyras\npalomino\npalominos\npalooka\npalookas\npaloverde\npaloverdes\npalp\npalpabilities\npalpability\npalpable\npalpably\npalpal\npalpate\npalpated\npalpates\npalpating\npalpation\npalpations\npalpator\npalpators\npalpebra\npalpebrae\npalpebral\npalpebras\npalpi\npalpitant\npalpitate\npalpitated\npalpitates\npalpitating\npalpitation\npalpitations\npalps\npalpus\npals\npalsgrave\npalsgraves\npalship\npalships\npalsied\npalsies\npalsy\npalsying\npalter\npaltered\npalterer\npalterers\npaltering\npalters\npaltrier\npaltriest\npaltrily\npaltriness\npaltrinesses\npaltry\npaludal\npaludism\npaludisms\npaly\npalynologic\npalynological\npalynologically\npalynologies\npalynologist\npalynologists\npalynology\npam\npampa\npampas\npampean\npampeans\npamper\npampered\npamperer\npamperers\npampering\npampero\npamperos\npampers\npamphlet\npamphleteer\npamphleteered\npamphleteering\npamphleteers\npamphlets\npams\npan\npanacea\npanacean\npanaceas\npanache\npanaches\npanada\npanadas\npanama\npanamas\npanatela\npanatelas\npanbroil\npanbroiled\npanbroiling\npanbroils\npancake\npancaked\npancakes\npancaking\npancetta\npancettas\npanchax\npanchaxes\npanchromatic\npancratia\npancratium\npancratiums\npancreas\npancreases\npancreatectomies\npancreatectomized\npancreatectomy\npancreatic\npancreatin\npancreatins\npancreatitides\npancreatitis\npancreozymin\npancreozymins\npancytopenia\npancytopenias\npanda\npandani\npandanus\npandanuses\npandas\npandect\npandects\npandemic\npandemics\npandemonium\npandemoniums\npander\npandered\npanderer\npanderers\npandering\npanders\npandied\npandies\npandit\npandits\npandoor\npandoors\npandora\npandoras\npandore\npandores\npandour\npandours\npandowdies\npandowdy\npandura\npanduras\npandy\npandying\npane\npaned\npanegyric\npanegyrical\npanegyrically\npanegyrics\npanegyrist\npanegyrists\npanel\npaneled\npaneling\npanelings\npanelist\npanelists\npanelled\npanelling\npanellings\npanels\npanes\npanetela\npanetelas\npanettone\npanettones\npanettoni\npanfish\npanfishes\npanfried\npanfries\npanfry\npanfrying\npanful\npanfuls\npang\npanga\npangas\npanged\npangen\npangene\npangenes\npangeneses\npangenesis\npangenetic\npangens\npanging\npangolin\npangolins\npangram\npangrams\npangs\npanhandle\npanhandled\npanhandler\npanhandlers\npanhandles\npanhandling\npanhuman\npanic\npanicked\npanickier\npanickiest\npanicking\npanicky\npanicle\npanicled\npanicles\npanics\npaniculate\npanicum\npanicums\npanier\npaniers\npanjandra\npanjandrum\npanjandrums\npanleukopenia\npanleukopenias\npanmictic\npanmixes\npanmixia\npanmixias\npanmixis\npanne\npanned\npannes\npannier\npanniers\npannikin\npannikins\npanning\npanocha\npanochas\npanoche\npanoches\npanoplied\npanoplies\npanoply\npanoptic\npanorama\npanoramas\npanoramic\npanoramically\npanpipe\npanpipes\npans\npansexual\npansexualities\npansexuality\npansies\npansophies\npansophy\npansy\npant\npantalets\npantalettes\npantalone\npantalones\npantaloon\npantaloons\npantdress\npantdresses\npantechnicon\npantechnicons\npanted\npantheism\npantheisms\npantheist\npantheistic\npantheistical\npantheistically\npantheists\npantheon\npantheons\npanther\npanthers\npantie\npanties\npantile\npantiled\npantiles\npanting\npantisocracies\npantisocracy\npantisocratic\npantisocratical\npantisocratist\npantisocratists\npanto\npantofle\npantofles\npantograph\npantographic\npantographs\npantomime\npantomimed\npantomimes\npantomimic\npantomiming\npantomimist\npantomimists\npantos\npantothenate\npantothenates\npantoum\npantoums\npantries\npantropic\npantropical\npantry\npantryman\npantrymen\npants\npantsuit\npantsuited\npantsuits\npanty\npantyhose\npantywaist\npantywaists\npanzer\npanzers\npap\npapa\npapacies\npapacy\npapain\npapains\npapal\npapally\npaparazzi\npaparazzo\npapas\npapaverine\npapaverines\npapaw\npapaws\npapaya\npapayan\npapayas\npaper\npaperback\npaperbacked\npaperbacks\npaperboard\npaperboards\npaperbound\npaperbounds\npaperboy\npaperboys\npapered\npaperer\npaperers\npapergirl\npapergirls\npaperhanger\npaperhangers\npaperhanging\npaperhangings\npaperiness\npaperinesses\npapering\npaperless\npapermaker\npapermakers\npapermaking\npapermakings\npapers\npaperweight\npaperweights\npaperwork\npaperworks\npapery\npapeterie\npapeteries\npaphian\npaphians\npapilionaceous\npapilla\npapillae\npapillar\npapillary\npapillate\npapilloma\npapillomas\npapillomata\npapillomatous\npapillomavirus\npapillomaviruses\npapillon\npapillons\npapillose\npapillote\npapillotes\npapist\npapistic\npapistries\npapistry\npapists\npapoose\npapooses\npapovavirus\npapovaviruses\npappi\npappier\npappies\npappiest\npappoose\npappooses\npappose\npappous\npappus\npappy\npaprica\npapricas\npaprika\npaprikas\npaps\npapula\npapulae\npapular\npapule\npapules\npapulose\npapyral\npapyri\npapyrian\npapyrine\npapyrologies\npapyrologist\npapyrologists\npapyrology\npapyrus\npapyruses\npar\npara\nparabioses\nparabiosis\nparabiotic\nparabiotically\nparable\nparables\nparabola\nparabolas\nparabolic\nparabolically\nparaboloid\nparaboloidal\nparaboloids\nparachor\nparachors\nparachute\nparachuted\nparachutes\nparachutic\nparachuting\nparachutist\nparachutists\nparade\nparaded\nparader\nparaders\nparades\nparadichlorobenzene\nparadichlorobenzenes\nparadiddle\nparadiddles\nparadigm\nparadigmatic\nparadigmatically\nparadigms\nparading\nparadisaic\nparadisaical\nparadisaically\nparadisal\nparadise\nparadises\nparadisiac\nparadisiacal\nparadisiacally\nparadisial\nparadisical\nparador\nparadores\nparadors\nparados\nparadoses\nparadox\nparadoxes\nparadoxical\nparadoxicalities\nparadoxicality\nparadoxically\nparadoxicalness\nparadoxicalnesses\nparadrop\nparadropped\nparadropping\nparadrops\nparae\nparaesthesia\nparaesthesias\nparaffin\nparaffined\nparaffinic\nparaffining\nparaffins\nparaform\nparaformaldehyde\nparaformaldehydes\nparaforms\nparageneses\nparagenesis\nparagenetic\nparagenetically\nparagoge\nparagoges\nparagon\nparagoned\nparagoning\nparagons\nparagraph\nparagraphed\nparagrapher\nparagraphers\nparagraphic\nparagraphing\nparagraphs\nparainfluenza\nparainfluenzas\nparajournalism\nparajournalisms\nparakeet\nparakeets\nparakite\nparakites\nparalanguage\nparalanguages\nparaldehyde\nparaldehydes\nparalegal\nparalegals\nparalinguistic\nparalinguistics\nparallactic\nparallax\nparallaxes\nparallel\nparalleled\nparallelepiped\nparallelepipeds\nparalleling\nparallelism\nparallelisms\nparallelled\nparallelling\nparallelogram\nparallelograms\nparallels\nparalogism\nparalogisms\nparalyse\nparalysed\nparalyses\nparalysing\nparalysis\nparalytic\nparalytically\nparalytics\nparalyzation\nparalyzations\nparalyze\nparalyzed\nparalyzer\nparalyzers\nparalyzes\nparalyzing\nparalyzingly\nparamagnet\nparamagnetic\nparamagnetically\nparamagnetism\nparamagnetisms\nparamagnets\nparamecia\nparamecium\nparameciums\nparamedic\nparamedical\nparamedicals\nparamedics\nparament\nparamenta\nparaments\nparameter\nparameterization\nparameterizations\nparameterize\nparameterized\nparameterizes\nparameterizing\nparameters\nparametric\nparametrically\nparametrization\nparametrizations\nparametrize\nparametrized\nparametrizes\nparametrizing\nparamilitary\nparamnesia\nparamnesias\nparamo\nparamos\nparamount\nparamountcies\nparamountcy\nparamountly\nparamounts\nparamour\nparamours\nparamylum\nparamylums\nparamyxovirus\nparamyxoviruses\nparang\nparangs\nparanoea\nparanoeas\nparanoia\nparanoiac\nparanoiacs\nparanoias\nparanoic\nparanoically\nparanoics\nparanoid\nparanoidal\nparanoids\nparanormal\nparanormalities\nparanormality\nparanormally\nparanormals\nparanymph\nparanymphs\nparapet\nparapeted\nparapets\nparaph\nparaphernalia\nparaphrasable\nparaphrase\nparaphrased\nparaphraser\nparaphrasers\nparaphrases\nparaphrasing\nparaphrastic\nparaphrastically\nparaphs\nparaphyses\nparaphysis\nparaplegia\nparaplegias\nparaplegic\nparaplegics\nparapodia\nparapodial\nparapodium\nparaprofessional\nparaprofessionals\nparapsychological\nparapsychologies\nparapsychologist\nparapsychologists\nparapsychology\nparaquat\nparaquats\nparaquet\nparaquets\npararosaniline\npararosanilines\nparas\nparasailing\nparasailings\nparasang\nparasangs\nparasexual\nparasexualities\nparasexuality\nparashah\nparashahs\nparashioth\nparashot\nparashoth\nparasite\nparasites\nparasitic\nparasitical\nparasitically\nparasiticidal\nparasiticide\nparasiticides\nparasitise\nparasitised\nparasitises\nparasitising\nparasitism\nparasitisms\nparasitization\nparasitizations\nparasitize\nparasitized\nparasitizes\nparasitizing\nparasitoid\nparasitoids\nparasitologic\nparasitological\nparasitologically\nparasitologies\nparasitologist\nparasitologists\nparasitology\nparasitoses\nparasitosis\nparasol\nparasols\nparasympathetic\nparasympathetics\nparasympathomimetic\nparasyntheses\nparasynthesis\nparasynthetic\nparatactic\nparatactical\nparatactically\nparataxes\nparataxis\nparathion\nparathions\nparathormone\nparathormones\nparathyroid\nparathyroidectomies\nparathyroidectomized\nparathyroidectomy\nparathyroids\nparatroop\nparatrooper\nparatroopers\nparatroops\nparatyphoid\nparatyphoids\nparavane\nparavanes\nparawing\nparawings\nparazoan\nparazoans\nparboil\nparboiled\nparboiling\nparboils\nparbuckle\nparbuckled\nparbuckles\nparbuckling\nparcel\nparceled\nparceling\nparcelled\nparcelling\nparcels\nparcenaries\nparcenary\nparcener\nparceners\nparch\nparched\nparches\nparchesi\nparchesis\nparching\nparchisi\nparchisis\nparchment\nparchments\npard\npardah\npardahs\npardee\npardi\npardie\npardine\npardner\npardners\npardon\npardonable\npardonableness\npardonablenesses\npardonably\npardoned\npardoner\npardoners\npardoning\npardons\npards\npardy\npare\nparecism\nparecisms\npared\nparegoric\nparegorics\npareira\npareiras\nparenchyma\nparenchymal\nparenchymas\nparenchymata\nparenchymatous\nparent\nparentage\nparentages\nparental\nparentally\nparented\nparenteral\nparenterally\nparentheses\nparenthesis\nparenthesize\nparenthesized\nparenthesizes\nparenthesizing\nparenthetic\nparenthetical\nparenthetically\nparenthood\nparenthoods\nparenting\nparentings\nparentless\nparents\npareo\npareos\nparer\nparerga\nparergon\nparers\npares\npareses\nparesis\nparesthesia\nparesthesias\nparesthetic\nparetic\nparetics\npareu\npareus\npareve\nparfait\nparfaits\nparfleche\nparfleches\nparflesh\nparfleshes\nparfocal\nparfocalities\nparfocality\nparfocalize\nparfocalized\nparfocalizes\nparfocalizing\nparge\nparged\nparges\nparget\npargeted\npargeting\npargets\npargetted\npargetting\nparging\npargings\npargo\npargos\npargyline\npargylines\nparhelia\nparhelic\nparhelion\npariah\npariahs\nparian\nparians\nparies\nparietal\nparietals\nparietes\nparimutuel\nparing\nparings\nparis\nparises\nparish\nparishes\nparishioner\nparishioners\nparities\nparity\npark\nparka\nparkas\nparked\nparker\nparkers\nparking\nparkings\nparkinsonian\nparkinsonism\nparkinsonisms\nparkland\nparklands\nparklike\nparks\nparkway\nparkways\nparlance\nparlances\nparlando\nparlante\nparlay\nparlayed\nparlaying\nparlays\nparle\nparled\nparles\nparley\nparleyed\nparleyer\nparleyers\nparleying\nparleys\nparliament\nparliamentarian\nparliamentarians\nparliamentary\nparliaments\nparling\nparlor\nparlors\nparlour\nparlours\nparlous\nparlously\nparmigiana\nparmigiano\nparochial\nparochialism\nparochialisms\nparochially\nparodic\nparodied\nparodies\nparodist\nparodistic\nparodists\nparodoi\nparodos\nparody\nparodying\nparol\nparole\nparoled\nparolee\nparolees\nparoles\nparoling\nparols\nparonomasia\nparonomasias\nparonomastic\nparonym\nparonymous\nparonyms\nparoquet\nparoquets\nparotic\nparotid\nparotids\nparotitis\nparotitises\nparotoid\nparotoids\nparous\nparoxysm\nparoxysmal\nparoxysms\nparquet\nparqueted\nparqueting\nparquetries\nparquetry\nparquets\nparr\nparrakeet\nparrakeets\nparral\nparrals\nparred\nparrel\nparrels\nparricidal\nparricide\nparricides\nparridge\nparridges\nparried\nparries\nparring\nparritch\nparritches\nparroket\nparrokets\nparrot\nparroted\nparroter\nparroters\nparroting\nparrots\nparroty\nparrs\nparry\nparrying\npars\nparsable\nparse\nparsec\nparsecs\nparsed\nparser\nparsers\nparses\nparsimonies\nparsimonious\nparsimoniously\nparsimony\nparsing\nparsley\nparsleyed\nparsleys\nparslied\nparsnip\nparsnips\nparson\nparsonage\nparsonages\nparsonic\nparsons\npart\npartake\npartaken\npartaker\npartakers\npartakes\npartaking\npartan\npartans\nparted\nparterre\nparterres\nparthenocarpic\nparthenocarpies\nparthenocarpy\nparthenogeneses\nparthenogenesis\nparthenogenetic\nparthenogenetically\npartial\npartialities\npartiality\npartially\npartials\npartibilities\npartibility\npartible\nparticipant\nparticipants\nparticipate\nparticipated\nparticipates\nparticipating\nparticipation\nparticipational\nparticipations\nparticipative\nparticipator\nparticipators\nparticipatory\nparticipial\nparticipially\nparticiple\nparticiples\nparticle\nparticleboard\nparticleboards\nparticles\nparticular\nparticularise\nparticularised\nparticularises\nparticularising\nparticularism\nparticularisms\nparticularist\nparticularistic\nparticularists\nparticularities\nparticularity\nparticularization\nparticularizations\nparticularize\nparticularized\nparticularizes\nparticularizing\nparticularly\nparticulars\nparticulate\nparticulates\npartied\npartier\npartiers\nparties\nparting\npartings\npartisan\npartisanly\npartisans\npartisanship\npartisanships\npartita\npartitas\npartite\npartition\npartitioned\npartitioner\npartitioners\npartitioning\npartitionist\npartitionists\npartitions\npartitive\npartitively\npartizan\npartizans\npartlet\npartlets\npartly\npartner\npartnered\npartnering\npartnerless\npartners\npartnership\npartnerships\nparton\npartons\npartook\npartridge\npartridgeberries\npartridgeberry\npartridges\nparts\nparturient\nparturients\nparturition\nparturitions\npartway\nparty\npartyer\npartyers\npartying\nparura\nparuras\nparure\nparures\nparve\nparvenu\nparvenue\nparvenues\nparvenus\nparvis\nparvise\nparvises\nparvo\nparvolin\nparvolins\nparvos\nparvovirus\nparvoviruses\npas\npascal\npascals\npaschal\npaschals\npase\npaseo\npaseos\npases\npash\npasha\npashadom\npashadoms\npashalic\npashalics\npashalik\npashaliks\npashas\npashed\npashes\npashing\npasqueflower\npasqueflowers\npasquil\npasquils\npasquinade\npasquinaded\npasquinades\npasquinading\npass\npassable\npassably\npassacaglia\npassacaglias\npassade\npassades\npassado\npassadoes\npassados\npassage\npassaged\npassages\npassageway\npassageways\npassagework\npassageworks\npassaging\npassant\npassband\npassbands\npassbook\npassbooks\npasse\npassed\npassee\npassel\npassels\npassementerie\npassementeries\npassenger\npassengers\npasser\npasserby\npasserine\npasserines\npassers\npassersby\npasses\npassible\npassim\npassing\npassings\npassion\npassional\npassionate\npassionately\npassionateness\npassionatenesses\npassionflower\npassionflowers\npassionless\npassions\npassivate\npassivated\npassivates\npassivating\npassivation\npassivations\npassive\npassively\npassiveness\npassivenesses\npassives\npassivism\npassivisms\npassivist\npassivists\npassivities\npassivity\npasskey\npasskeys\npassless\npassover\npassovers\npassport\npassports\npassus\npassuses\npassword\npasswords\npast\npasta\npastas\npaste\npasteboard\npasteboards\npasted\npastedown\npastedowns\npastel\npastelist\npastelists\npastellist\npastellists\npastels\npaster\npastern\npasterns\npasters\npastes\npasteup\npasteups\npasteurise\npasteurised\npasteurises\npasteurising\npasteurization\npasteurizations\npasteurize\npasteurized\npasteurizer\npasteurizers\npasteurizes\npasteurizing\npasticci\npasticcio\npasticcios\npastiche\npastiches\npasticheur\npasticheurs\npastie\npastier\npasties\npastiest\npastil\npastille\npastilles\npastils\npastime\npastimes\npastina\npastinas\npastiness\npastinesses\npasting\npastis\npastises\npastless\npastness\npastnesses\npastor\npastoral\npastorale\npastorales\npastorali\npastoralism\npastoralisms\npastoralist\npastoralists\npastorally\npastoralness\npastoralnesses\npastorals\npastorate\npastorates\npastored\npastoring\npastors\npastorship\npastorships\npastrami\npastramis\npastries\npastromi\npastromis\npastry\npasts\npasturage\npasturages\npastural\npasture\npastured\npastureland\npasturelands\npasturer\npasturers\npastures\npasturing\npasty\npat\npataca\npatacas\npatagia\npatagial\npatagium\npatamar\npatamars\npatch\npatchboard\npatchboards\npatched\npatcher\npatchers\npatches\npatchier\npatchiest\npatchily\npatchiness\npatchinesses\npatching\npatchouli\npatchoulies\npatchoulis\npatchouly\npatchwork\npatchworks\npatchy\npate\npated\npatella\npatellae\npatellar\npatellas\npatelliform\npaten\npatencies\npatency\npatens\npatent\npatentabilities\npatentability\npatentable\npatented\npatentee\npatentees\npatenting\npatently\npatentor\npatentors\npatents\npater\npaterfamilias\npaternal\npaternalism\npaternalisms\npaternalist\npaternalistic\npaternalistically\npaternalists\npaternally\npaternities\npaternity\npaternoster\npaternosters\npaters\npates\npath\npathbreaking\npathetic\npathetical\npathetically\npathfinder\npathfinders\npathfinding\npathfindings\npathless\npathlessness\npathlessnesses\npathobiologies\npathobiology\npathogen\npathogeneses\npathogenesis\npathogenetic\npathogenic\npathogenicities\npathogenicity\npathogens\npathognomonic\npathologic\npathological\npathologically\npathologies\npathologist\npathologists\npathology\npathophysiologic\npathophysiological\npathophysiologies\npathophysiology\npathos\npathoses\npaths\npathway\npathways\npatience\npatiences\npatient\npatienter\npatientest\npatiently\npatients\npatin\npatina\npatinae\npatinas\npatinate\npatinated\npatinates\npatinating\npatination\npatinations\npatine\npatined\npatines\npatining\npatinize\npatinized\npatinizes\npatinizing\npatins\npatio\npatios\npatisserie\npatisseries\npatissier\npatissiers\npatly\npatness\npatnesses\npatois\npatootie\npatooties\npatresfamilias\npatriarch\npatriarchal\npatriarchate\npatriarchates\npatriarchies\npatriarchs\npatriarchy\npatrician\npatricians\npatriciate\npatriciates\npatricidal\npatricide\npatricides\npatrilineal\npatrimonial\npatrimonies\npatrimony\npatriot\npatriotic\npatriotically\npatriotism\npatriotisms\npatriots\npatristic\npatristical\npatristics\npatrol\npatrolled\npatroller\npatrollers\npatrolling\npatrolman\npatrolmen\npatrols\npatron\npatronage\npatronages\npatronal\npatroness\npatronesses\npatronise\npatronised\npatronises\npatronising\npatronization\npatronizations\npatronize\npatronized\npatronizes\npatronizing\npatronizingly\npatronly\npatrons\npatronymic\npatronymics\npatroon\npatroons\npats\npatsies\npatsy\npattamar\npattamars\npatted\npattee\npatten\npattens\npatter\npattered\npatterer\npatterers\npattering\npattern\npatterned\npatterning\npatternings\npatternless\npatterns\npatters\npattie\npatties\npatting\npatty\npattypan\npattypans\npatulent\npatulous\npaty\npatzer\npatzers\npaucities\npaucity\npaughty\npauldron\npauldrons\npaulin\npaulins\npaulownia\npaulownias\npaunch\npaunched\npaunches\npaunchier\npaunchiest\npaunchiness\npaunchinesses\npaunchy\npauper\npaupered\npaupering\npauperism\npauperisms\npauperize\npauperized\npauperizes\npauperizing\npaupers\npaupiette\npaupiettes\npausal\npause\npaused\npauser\npausers\npauses\npausing\npavan\npavane\npavanes\npavans\npave\npaved\npaveed\npavement\npavements\npaver\npavers\npaves\npavid\npavilion\npavilioned\npavilioning\npavilions\npavillon\npavillons\npavin\npaving\npavings\npavins\npavior\npaviors\npaviour\npaviours\npavis\npavise\npaviser\npavisers\npavises\npavlova\npavlovas\npavonine\npaw\npawed\npawer\npawers\npawing\npawkier\npawkiest\npawkily\npawky\npawl\npawls\npawn\npawnable\npawnage\npawnages\npawnbroker\npawnbrokers\npawnbroking\npawnbrokings\npawned\npawnee\npawnees\npawner\npawners\npawning\npawnor\npawnors\npawns\npawnshop\npawnshops\npawpaw\npawpaws\npaws\npax\npaxes\npaxwax\npaxwaxes\npay\npayable\npayables\npayably\npayback\npaybacks\npaycheck\npaychecks\npayday\npaydays\npayed\npayee\npayees\npayer\npayers\npaygrade\npaygrades\npaying\npayload\npayloads\npaymaster\npaymasters\npayment\npayments\npaynim\npaynims\npayoff\npayoffs\npayola\npayolas\npayor\npayors\npayout\npayouts\npayroll\npayrolls\npays\npaystub\npaystubs\npazazz\npazazzes\npe\npea\npeace\npeaceable\npeaceableness\npeaceablenesses\npeaceably\npeaced\npeaceful\npeacefuller\npeacefullest\npeacefully\npeacefulness\npeacefulnesses\npeacekeeper\npeacekeepers\npeacekeeping\npeacekeepings\npeacemaker\npeacemakers\npeacemaking\npeacemakings\npeacenik\npeaceniks\npeaces\npeacetime\npeacetimes\npeach\npeached\npeacher\npeachers\npeaches\npeachier\npeachiest\npeaching\npeachy\npeacing\npeacoat\npeacoats\npeacock\npeacocked\npeacockier\npeacockiest\npeacocking\npeacockish\npeacocks\npeacocky\npeafowl\npeafowls\npeag\npeage\npeages\npeags\npeahen\npeahens\npeak\npeaked\npeakedness\npeakednesses\npeakier\npeakiest\npeaking\npeakish\npeakless\npeaklike\npeaks\npeaky\npeal\npealed\npealike\npealing\npeals\npean\npeans\npeanut\npeanuts\npear\npearl\npearlash\npearlashes\npearled\npearler\npearlers\npearlescence\npearlescences\npearlescent\npearlier\npearliest\npearling\npearlite\npearlites\npearlitic\npearlized\npearls\npearly\npearmain\npearmains\npears\npeart\npearter\npeartest\npeartly\npeas\npeasant\npeasantries\npeasantry\npeasants\npeascod\npeascods\npease\npeasecod\npeasecods\npeasen\npeases\npeashooter\npeashooters\npeat\npeatier\npeatiest\npeats\npeaty\npeavey\npeaveys\npeavies\npeavy\npebble\npebbled\npebbles\npebblier\npebbliest\npebbling\npebbly\npec\npecan\npecans\npeccable\npeccadillo\npeccadilloes\npeccadillos\npeccancies\npeccancy\npeccant\npeccantly\npeccaries\npeccary\npeccavi\npeccavis\npech\npechan\npechans\npeched\npeching\npechs\npeck\npecked\npecker\npeckers\npeckerwood\npeckerwoods\npeckier\npeckiest\npecking\npeckish\npecks\npecky\npecorini\npecorino\npecorinos\npecs\npectase\npectases\npectate\npectates\npecten\npectens\npectic\npectin\npectinaceous\npectinate\npectination\npectinations\npectines\npectinesterase\npectinesterases\npectins\npectize\npectized\npectizes\npectizing\npectoral\npectorals\npeculate\npeculated\npeculates\npeculating\npeculation\npeculations\npeculator\npeculators\npeculia\npeculiar\npeculiarities\npeculiarity\npeculiarly\npeculiars\npeculium\npecuniarily\npecuniary\nped\npedagog\npedagogic\npedagogical\npedagogically\npedagogics\npedagogies\npedagogs\npedagogue\npedagogues\npedagogy\npedal\npedaled\npedalfer\npedalfers\npedalier\npedaliers\npedaling\npedalled\npedalling\npedalo\npedalos\npedals\npedant\npedantic\npedantically\npedantries\npedantry\npedants\npedate\npedately\npeddle\npeddled\npeddler\npeddleries\npeddlers\npeddlery\npeddles\npeddling\npederast\npederastic\npederasties\npederasts\npederasty\npedes\npedestal\npedestaled\npedestaling\npedestalled\npedestalling\npedestals\npedestrian\npedestrianism\npedestrianisms\npedestrians\npediatric\npediatrician\npediatricians\npediatrics\npediatrist\npediatrists\npedicab\npedicabs\npedicel\npedicellate\npedicels\npedicle\npedicled\npedicles\npediculate\npediculates\npediculoses\npediculosis\npediculous\npedicure\npedicured\npedicures\npedicuring\npedicurist\npedicurists\npediform\npedigree\npedigreed\npedigrees\npediment\npedimental\npedimented\npediments\npedipalp\npedipalps\npedlar\npedlaries\npedlars\npedlary\npedler\npedleries\npedlers\npedlery\npedocal\npedocalic\npedocals\npedogeneses\npedogenesis\npedogenetic\npedogenic\npedologic\npedological\npedologies\npedologist\npedologists\npedology\npedometer\npedometers\npedophile\npedophiles\npedophilia\npedophiliac\npedophilias\npedophilic\npedro\npedros\npeds\npeduncle\npeduncled\npeduncles\npeduncular\npedunculate\npedunculated\npee\npeebeen\npeebeens\npeed\npeeing\npeek\npeekaboo\npeekaboos\npeeked\npeeking\npeeks\npeel\npeelable\npeeled\npeeler\npeelers\npeeling\npeelings\npeels\npeen\npeened\npeening\npeens\npeep\npeeped\npeeper\npeepers\npeephole\npeepholes\npeeping\npeeps\npeepshow\npeepshows\npeepul\npeepuls\npeer\npeerage\npeerages\npeered\npeeress\npeeresses\npeerie\npeeries\npeering\npeerless\npeerlessly\npeers\npeery\npees\npeesweep\npeesweeps\npeetweet\npeetweets\npeeve\npeeved\npeeves\npeeving\npeevish\npeevishly\npeevishness\npeevishnesses\npeewee\npeewees\npeewit\npeewits\npeg\npegboard\npegboards\npegbox\npegboxes\npegged\npegging\npegless\npeglike\npegmatite\npegmatites\npegmatitic\npegs\npeh\npehs\npeignoir\npeignoirs\npein\npeined\npeining\npeins\npeise\npeised\npeises\npeising\npejorative\npejoratively\npejoratives\npekan\npekans\npeke\npekes\npekin\npekins\npekoe\npekoes\npelage\npelages\npelagial\npelagic\npelargonium\npelargoniums\npele\npelecypod\npelecypods\npelerine\npelerines\npeles\npelf\npelfs\npelican\npelicans\npelisse\npelisses\npelite\npelites\npelitic\npellagra\npellagras\npellagrin\npellagrins\npellagrous\npellet\npelletal\npelleted\npelleting\npelletise\npelletised\npelletises\npelletising\npelletization\npelletizations\npelletize\npelletized\npelletizer\npelletizers\npelletizes\npelletizing\npellets\npellicle\npellicles\npellitories\npellitory\npellmell\npellmells\npellucid\npellucidly\npelmet\npelmets\npelon\npeloria\npelorian\npelorias\npeloric\npelorus\npeloruses\npelota\npelotas\npelt\npeltast\npeltasts\npeltate\npelted\npelter\npeltered\npeltering\npelters\npelting\npeltries\npeltry\npelts\npelves\npelvic\npelvics\npelvis\npelvises\npelycosaur\npelycosaurs\npembina\npembinas\npemican\npemicans\npemmican\npemmicans\npemoline\npemolines\npemphigus\npemphiguses\npemphix\npemphixes\npen\npenal\npenalise\npenalised\npenalises\npenalising\npenalities\npenality\npenalization\npenalizations\npenalize\npenalized\npenalizes\npenalizing\npenally\npenalties\npenalty\npenance\npenanced\npenances\npenancing\npenang\npenangs\npenates\npence\npencel\npencels\npenchant\npenchants\npencil\npenciled\npenciler\npencilers\npenciling\npencilings\npencilled\npencilling\npencillings\npencils\npend\npendant\npendants\npended\npendencies\npendency\npendent\npendentive\npendentives\npendents\npending\npends\npendular\npendulous\npendulousness\npendulousnesses\npendulum\npendulums\npeneplain\npeneplains\npeneplane\npeneplanes\npenes\npenetrabilities\npenetrability\npenetrable\npenetralia\npenetrance\npenetrances\npenetrant\npenetrants\npenetrate\npenetrated\npenetrates\npenetrating\npenetratingly\npenetration\npenetrations\npenetrative\npenetrometer\npenetrometers\npengo\npengos\npenguin\npenguins\npenholder\npenholders\npenial\npenicil\npenicillamine\npenicillamines\npenicillate\npenicillia\npenicillin\npenicillinase\npenicillinases\npenicillins\npenicillium\npenicilliums\npenicils\npenile\npeninsula\npeninsular\npeninsulas\npenis\npenises\npenitence\npenitences\npenitent\npenitential\npenitentially\npenitentiaries\npenitentiary\npenitently\npenitents\npenknife\npenknives\npenlight\npenlights\npenlite\npenlites\npenman\npenmanship\npenmanships\npenmen\npenna\npennae\npenname\npennames\npennant\npennants\npennate\npennated\npenne\npenned\npenner\npenners\npenni\npennia\npennies\npenniless\npennine\npennines\npenning\npennis\npennon\npennoncel\npennoncels\npennoned\npennons\npenny\npennycress\npennycresses\npennyroyal\npennyroyals\npennyweight\npennyweights\npennywhistle\npennywhistles\npennywort\npennyworth\npennyworths\npennyworts\npenoche\npenoches\npenological\npenologies\npenologist\npenologists\npenology\npenoncel\npenoncels\npenpoint\npenpoints\npens\npensee\npensees\npensil\npensile\npensils\npension\npensionable\npensionaries\npensionary\npensione\npensioned\npensioner\npensioners\npensiones\npensioning\npensionless\npensions\npensive\npensively\npensiveness\npensivenesses\npenstemon\npenstemons\npenster\npensters\npenstock\npenstocks\npent\npentachlorophenol\npentachlorophenols\npentacle\npentacles\npentad\npentads\npentagon\npentagonal\npentagonally\npentagonals\npentagons\npentagram\npentagrams\npentahedra\npentahedral\npentahedron\npentahedrons\npentamerous\npentameter\npentameters\npentamidine\npentamidines\npentane\npentanes\npentangle\npentangles\npentanol\npentanols\npentapeptide\npentapeptides\npentaploid\npentaploidies\npentaploids\npentaploidy\npentarch\npentarchies\npentarchs\npentarchy\npentathlete\npentathletes\npentathlon\npentathlons\npentatonic\npentavalent\npentazocine\npentazocines\npentene\npentenes\npenthouse\npenthouses\npentlandite\npentlandites\npentobarbital\npentobarbitals\npentobarbitone\npentobarbitones\npentode\npentodes\npentomic\npentosan\npentosans\npentose\npentoses\npentoxide\npentoxides\npentstemon\npentstemons\npentyl\npentylenetetrazol\npentylenetetrazols\npentyls\npenuche\npenuches\npenuchi\npenuchis\npenuchle\npenuchles\npenuckle\npenuckles\npenult\npenultima\npenultimas\npenultimate\npenultimately\npenults\npenumbra\npenumbrae\npenumbral\npenumbras\npenuries\npenurious\npenuriously\npenuriousness\npenuriousnesses\npenury\npeon\npeonage\npeonages\npeones\npeonies\npeonism\npeonisms\npeons\npeony\npeople\npeopled\npeoplehood\npeoplehoods\npeopleless\npeopler\npeoplers\npeoples\npeopling\npep\npeperomia\npeperomias\npeperoni\npeperonis\npepla\npeplos\npeploses\npeplum\npeplumed\npeplums\npeplus\npepluses\npepo\npeponida\npeponidas\npeponium\npeponiums\npepos\npepped\npepper\npepperbox\npepperboxes\npeppercorn\npeppercorns\npeppered\npepperer\npepperers\npeppergrass\npeppergrasses\npepperiness\npepperinesses\npeppering\npeppermint\npeppermints\npepperminty\npepperoni\npepperonis\npeppers\npeppertree\npeppertrees\npeppery\npeppier\npeppiest\npeppily\npeppiness\npeppinesses\npepping\npeppy\npeps\npepsin\npepsine\npepsines\npepsinogen\npepsinogens\npepsins\npeptic\npeptics\npeptid\npeptidase\npeptidases\npeptide\npeptides\npeptidic\npeptidoglycan\npeptidoglycans\npeptids\npeptize\npeptized\npeptizer\npeptizers\npeptizes\npeptizing\npeptone\npeptones\npeptonic\nper\nperacid\nperacids\nperadventure\nperadventures\nperambulate\nperambulated\nperambulates\nperambulating\nperambulation\nperambulations\nperambulator\nperambulators\nperambulatory\nperborate\nperborates\npercale\npercales\npercaline\npercalines\nperceivable\nperceivably\nperceive\nperceived\nperceiver\nperceivers\nperceives\nperceiving\npercent\npercentage\npercentages\npercentile\npercentiles\npercents\npercept\nperceptibilities\nperceptibility\nperceptible\nperceptibly\nperception\nperceptional\nperceptions\nperceptive\nperceptively\nperceptiveness\nperceptivenesses\nperceptivities\nperceptivity\npercepts\nperceptual\nperceptually\nperch\nperchance\nperched\npercher\nperchers\nperches\nperching\nperchlorate\nperchlorates\nperchloroethylene\nperchloroethylenes\npercipience\npercipiences\npercipient\npercipiently\npercipients\npercoid\npercoids\npercolate\npercolated\npercolates\npercolating\npercolation\npercolations\npercolator\npercolators\npercuss\npercussed\npercusses\npercussing\npercussion\npercussionist\npercussionists\npercussions\npercussive\npercussively\npercussiveness\npercussivenesses\npercutaneous\npercutaneously\nperdie\nperdition\nperditions\nperdu\nperdue\nperdues\nperdurabilities\nperdurability\nperdurable\nperdurably\nperdure\nperdured\nperdures\nperduring\nperdus\nperdy\nperea\nperegrin\nperegrinate\nperegrinated\nperegrinates\nperegrinating\nperegrination\nperegrinations\nperegrine\nperegrines\nperegrins\npereia\npereion\npereiopod\npereiopods\nperemptorily\nperemptoriness\nperemptorinesses\nperemptory\nperennate\nperennated\nperennates\nperennating\nperennation\nperennations\nperennial\nperennially\nperennials\npereon\npereopod\npereopods\nperestroika\nperestroikas\nperfect\nperfecta\nperfectas\nperfected\nperfecter\nperfecters\nperfectest\nperfectibilities\nperfectibility\nperfectible\nperfecting\nperfection\nperfectionism\nperfectionisms\nperfectionist\nperfectionistic\nperfectionists\nperfections\nperfective\nperfectively\nperfectiveness\nperfectivenesses\nperfectives\nperfectivities\nperfectivity\nperfectly\nperfectness\nperfectnesses\nperfecto\nperfectos\nperfects\nperfervid\nperfidies\nperfidious\nperfidiously\nperfidiousness\nperfidiousnesses\nperfidy\nperfoliate\nperforate\nperforated\nperforates\nperforating\nperforation\nperforations\nperforator\nperforators\nperforce\nperform\nperformabilities\nperformability\nperformable\nperformance\nperformances\nperformative\nperformatives\nperformatory\nperformed\nperformer\nperformers\nperforming\nperforms\nperfume\nperfumed\nperfumer\nperfumeries\nperfumers\nperfumery\nperfumes\nperfuming\nperfunctorily\nperfunctoriness\nperfunctorinesses\nperfunctory\nperfusate\nperfusates\nperfuse\nperfused\nperfuses\nperfusing\nperfusion\nperfusionist\nperfusionists\nperfusions\npergola\npergolas\nperhaps\nperhapses\nperi\nperianth\nperianths\nperiapt\nperiapts\nperiblem\nperiblems\npericardia\npericardial\npericarditides\npericarditis\npericardium\npericarp\npericarps\nperichondral\nperichondria\nperichondrium\npericopae\npericope\npericopes\npericrania\npericranial\npericranium\npericycle\npericycles\npericyclic\nperiderm\nperiderms\nperidia\nperidial\nperidium\nperidot\nperidotic\nperidotite\nperidotites\nperidotitic\nperidots\nperigeal\nperigean\nperigee\nperigees\nperigon\nperigons\nperigynies\nperigynous\nperigyny\nperihelia\nperihelial\nperihelion\nperikarya\nperikaryal\nperikaryon\nperil\nperiled\nperiling\nperilla\nperillas\nperilled\nperilling\nperilous\nperilously\nperilousness\nperilousnesses\nperils\nperilune\nperilunes\nperilymph\nperilymphs\nperimeter\nperimeters\nperimysia\nperimysium\nperinatal\nperinatally\nperinea\nperineal\nperineum\nperineuria\nperineurium\nperiod\nperiodic\nperiodical\nperiodically\nperiodicals\nperiodicities\nperiodicity\nperiodid\nperiodids\nperiodization\nperiodizations\nperiodontal\nperiodontally\nperiodontics\nperiodontist\nperiodontists\nperiodontologies\nperiodontology\nperiods\nperionychia\nperionychium\nperiostea\nperiosteal\nperiosteum\nperiostitis\nperiostitises\nperiotic\nperipatetic\nperipatetically\nperipatetics\nperipatus\nperipatuses\nperipeteia\nperipeteias\nperipeties\nperipety\nperipheral\nperipherally\nperipherals\nperipheries\nperiphery\nperiphrases\nperiphrasis\nperiphrastic\nperiphrastically\nperiphytic\nperiphyton\nperiphytons\nperiplast\nperiplasts\nperipter\nperipters\nperique\nperiques\nperis\nperisarc\nperisarcs\nperiscope\nperiscopes\nperiscopic\nperish\nperishabilities\nperishability\nperishable\nperishables\nperished\nperishes\nperishing\nperissodactyl\nperissodactyls\nperistalses\nperistalsis\nperistaltic\nperistome\nperistomes\nperistomial\nperistyle\nperistyles\nperithecia\nperithecial\nperithecium\nperitonea\nperitoneal\nperitoneally\nperitoneum\nperitoneums\nperitonitis\nperitonitises\nperitrichous\nperitrichously\nperiwig\nperiwigged\nperiwigs\nperiwinkle\nperiwinkles\nperjure\nperjured\nperjurer\nperjurers\nperjures\nperjuries\nperjuring\nperjurious\nperjuriously\nperjury\nperk\nperked\nperkier\nperkiest\nperkily\nperkiness\nperkinesses\nperking\nperkish\nperks\nperky\nperlite\nperlites\nperlitic\nperm\npermafrost\npermafrosts\npermanence\npermanences\npermanencies\npermanency\npermanent\npermanently\npermanentness\npermanentnesses\npermanents\npermanganate\npermanganates\npermeabilities\npermeability\npermeable\npermeant\npermease\npermeases\npermeate\npermeated\npermeates\npermeating\npermeation\npermeations\npermeative\npermed\npermethrin\npermethrins\npermillage\npermillages\nperming\npermissibilities\npermissibility\npermissible\npermissibleness\npermissiblenesses\npermissibly\npermission\npermissions\npermissive\npermissively\npermissiveness\npermissivenesses\npermit\npermits\npermitted\npermittee\npermittees\npermitter\npermitters\npermitting\npermittivities\npermittivity\nperms\npermutable\npermutation\npermutational\npermutations\npermute\npermuted\npermutes\npermuting\npernicious\nperniciously\nperniciousness\nperniciousnesses\npernickety\nperoneal\nperoral\nperorally\nperorate\nperorated\nperorates\nperorating\nperoration\nperorational\nperorations\nperovskite\nperovskites\nperoxid\nperoxidase\nperoxidases\nperoxide\nperoxided\nperoxides\nperoxidic\nperoxiding\nperoxids\nperoxisomal\nperoxisome\nperoxisomes\nperoxy\nperp\nperpend\nperpended\nperpendicular\nperpendicularities\nperpendicularity\nperpendicularly\nperpendiculars\nperpending\nperpends\nperpent\nperpents\nperpetrate\nperpetrated\nperpetrates\nperpetrating\nperpetration\nperpetrations\nperpetrator\nperpetrators\nperpetual\nperpetually\nperpetuate\nperpetuated\nperpetuates\nperpetuating\nperpetuation\nperpetuations\nperpetuator\nperpetuators\nperpetuities\nperpetuity\nperphenazine\nperphenazines\nperplex\nperplexed\nperplexedly\nperplexes\nperplexing\nperplexities\nperplexity\nperps\nperquisite\nperquisites\nperries\nperron\nperrons\nperry\npersalt\npersalts\nperse\npersecute\npersecuted\npersecutee\npersecutees\npersecutes\npersecuting\npersecution\npersecutions\npersecutive\npersecutor\npersecutors\npersecutory\nperses\nperseverance\nperseverances\nperseverate\nperseverated\nperseverates\nperseverating\nperseveration\nperseverations\npersevere\npersevered\nperseveres\npersevering\nperseveringly\npersiflage\npersiflages\npersimmon\npersimmons\npersist\npersisted\npersistence\npersistences\npersistencies\npersistency\npersistent\npersistently\npersister\npersisters\npersisting\npersists\npersnicketiness\npersnicketinesses\npersnickety\nperson\npersona\npersonable\npersonableness\npersonablenesses\npersonae\npersonage\npersonages\npersonal\npersonalise\npersonalised\npersonalises\npersonalising\npersonalism\npersonalisms\npersonalist\npersonalistic\npersonalists\npersonalities\npersonality\npersonalization\npersonalizations\npersonalize\npersonalized\npersonalizes\npersonalizing\npersonally\npersonals\npersonalties\npersonalty\npersonas\npersonate\npersonated\npersonates\npersonating\npersonation\npersonations\npersonative\npersonator\npersonators\npersonhood\npersonhoods\npersonification\npersonifications\npersonified\npersonifier\npersonifiers\npersonifies\npersonify\npersonifying\npersonnel\npersonnels\npersons\nperspectival\nperspective\nperspectively\nperspectives\nperspicacious\nperspicaciously\nperspicaciousness\nperspicaciousnesses\nperspicacities\nperspicacity\nperspicuities\nperspicuity\nperspicuous\nperspicuously\nperspicuousness\nperspicuousnesses\nperspiration\nperspirations\nperspiratory\nperspire\nperspired\nperspires\nperspiring\nperspiry\npersuadable\npersuade\npersuaded\npersuader\npersuaders\npersuades\npersuading\npersuasible\npersuasion\npersuasions\npersuasive\npersuasively\npersuasiveness\npersuasivenesses\npert\npertain\npertained\npertaining\npertains\nperter\npertest\npertinacious\npertinaciously\npertinaciousness\npertinaciousnesses\npertinacities\npertinacity\npertinence\npertinences\npertinencies\npertinency\npertinent\npertinently\npertly\npertness\npertnesses\nperturb\nperturbable\nperturbation\nperturbational\nperturbations\nperturbed\nperturbing\nperturbs\npertussis\npertussises\nperuke\nperuked\nperukes\nperusal\nperusals\nperuse\nperused\nperuser\nperusers\nperuses\nperusing\npervade\npervaded\npervader\npervaders\npervades\npervading\npervasion\npervasions\npervasive\npervasively\npervasiveness\npervasivenesses\nperverse\nperversely\nperverseness\nperversenesses\nperversion\nperversions\nperversities\nperversity\nperversive\npervert\nperverted\npervertedly\npervertedness\npervertednesses\nperverter\nperverters\nperverting\nperverts\npervious\nperviousness\nperviousnesses\npes\npesade\npesades\npeseta\npesetas\npesewa\npesewas\npeskier\npeskiest\npeskily\npesky\npeso\npesos\npessaries\npessary\npessimism\npessimisms\npessimist\npessimistic\npessimistically\npessimists\npest\npester\npestered\npesterer\npesterers\npestering\npesters\npesthole\npestholes\npesthouse\npesthouses\npesticide\npesticides\npestier\npestiest\npestiferous\npestiferously\npestiferousness\npestiferousnesses\npestilence\npestilences\npestilent\npestilential\npestilentially\npestilently\npestle\npestled\npestles\npestling\npesto\npestos\npests\npesty\npet\npetal\npetaled\npetaline\npetalled\npetallike\npetalodies\npetalody\npetaloid\npetalous\npetals\npetard\npetards\npetasos\npetasoses\npetasus\npetasuses\npetcock\npetcocks\npetechia\npetechiae\npetechial\npeter\npetered\npetering\npeters\npetiolar\npetiolate\npetiole\npetioled\npetioles\npetiolule\npetiolules\npetit\npetite\npetiteness\npetitenesses\npetites\npetition\npetitionary\npetitioned\npetitioner\npetitioners\npetitioning\npetitions\npetnap\npetnapped\npetnapping\npetnaps\npetrale\npetrales\npetrel\npetrels\npetrifaction\npetrifactions\npetrification\npetrifications\npetrified\npetrifies\npetrify\npetrifying\npetrochemical\npetrochemicals\npetrochemistries\npetrochemistry\npetrodollar\npetrodollars\npetrogeneses\npetrogenesis\npetrogenetic\npetroglyph\npetroglyphs\npetrographer\npetrographers\npetrographic\npetrographical\npetrographically\npetrographies\npetrography\npetrol\npetrolatum\npetrolatums\npetroleum\npetroleums\npetrolic\npetrologic\npetrological\npetrologically\npetrologies\npetrologist\npetrologists\npetrology\npetrols\npetronel\npetronels\npetrosal\npetrous\npets\npetsai\npetsais\npetted\npettedly\npetter\npetters\npetti\npetticoat\npetticoated\npetticoats\npettier\npettiest\npettifog\npettifogged\npettifogger\npettifoggeries\npettifoggers\npettifoggery\npettifogging\npettifoggings\npettifogs\npettily\npettiness\npettinesses\npetting\npettings\npettish\npettishly\npettishness\npettishnesses\npettitoes\npettle\npettled\npettles\npettling\npetto\npetty\npetulance\npetulances\npetulancies\npetulancy\npetulant\npetulantly\npetunia\npetunias\npetuntse\npetuntses\npetuntze\npetuntzes\npew\npewee\npewees\npewholder\npewholders\npewit\npewits\npews\npewter\npewterer\npewterers\npewters\npeyote\npeyotes\npeyotl\npeyotls\npeytral\npeytrals\npeytrel\npeytrels\npfennig\npfennige\npfennigs\npfft\npfui\nphaeton\nphaetons\nphage\nphages\nphagocyte\nphagocytes\nphagocytic\nphagocytize\nphagocytized\nphagocytizes\nphagocytizing\nphagocytose\nphagocytosed\nphagocytoses\nphagocytosing\nphagocytosis\nphagocytotic\nphalange\nphalangeal\nphalanger\nphalangers\nphalanges\nphalansteries\nphalanstery\nphalanx\nphalanxes\nphalarope\nphalaropes\nphalli\nphallic\nphallically\nphallicism\nphallicisms\nphallism\nphallisms\nphallist\nphallists\nphallocentric\nphallus\nphalluses\nphanerogam\nphanerogams\nphanerophyte\nphanerophytes\nphantasied\nphantasies\nphantasm\nphantasma\nphantasmagoria\nphantasmagorias\nphantasmagoric\nphantasmagorical\nphantasmal\nphantasmata\nphantasmic\nphantasms\nphantast\nphantasts\nphantasy\nphantasying\nphantom\nphantomlike\nphantoms\npharaoh\npharaohs\npharaonic\npharisaic\npharisaical\npharisaically\npharisaicalness\npharisaicalnesses\npharisaism\npharisaisms\npharisee\npharisees\npharmaceutical\npharmaceutically\npharmaceuticals\npharmacies\npharmacist\npharmacists\npharmacodynamic\npharmacodynamically\npharmacodynamics\npharmacognosies\npharmacognostic\npharmacognostical\npharmacognosy\npharmacokinetic\npharmacokinetics\npharmacologic\npharmacological\npharmacologically\npharmacologies\npharmacologist\npharmacologists\npharmacology\npharmacopeia\npharmacopeial\npharmacopeias\npharmacopoeia\npharmacopoeial\npharmacopoeias\npharmacotherapies\npharmacotherapy\npharmacy\npharos\npharoses\npharyngeal\npharynges\npharyngitides\npharyngitis\npharynx\npharynxes\nphase\nphaseal\nphased\nphasedown\nphasedowns\nphaseout\nphaseouts\nphases\nphasic\nphasing\nphasis\nphasmid\nphasmids\nphat\nphatic\nphatically\npheasant\npheasants\nphellem\nphellems\nphelloderm\nphelloderms\nphellogen\nphellogens\nphelonia\nphelonion\nphelonions\nphenacaine\nphenacaines\nphenacetin\nphenacetins\nphenacite\nphenacites\nphenakite\nphenakites\nphenanthrene\nphenanthrenes\nphenate\nphenates\nphenazin\nphenazine\nphenazines\nphenazins\nphencyclidine\nphencyclidines\nphenetic\npheneticist\npheneticists\nphenetics\nphenetol\nphenetols\nphenix\nphenixes\nphenmetrazine\nphenmetrazines\nphenobarbital\nphenobarbitals\nphenobarbitone\nphenobarbitones\nphenocopies\nphenocopy\nphenocryst\nphenocrystic\nphenocrysts\nphenol\nphenolate\nphenolated\nphenolates\nphenolic\nphenolics\nphenological\nphenologically\nphenologies\nphenology\nphenolphthalein\nphenolphthaleins\nphenols\nphenom\nphenomena\nphenomenal\nphenomenalism\nphenomenalisms\nphenomenalist\nphenomenalistic\nphenomenalistically\nphenomenalists\nphenomenally\nphenomenas\nphenomenological\nphenomenologically\nphenomenologies\nphenomenologist\nphenomenologists\nphenomenology\nphenomenon\nphenomenons\nphenoms\nphenothiazine\nphenothiazines\nphenotype\nphenotypes\nphenotypic\nphenotypical\nphenotypically\nphenoxide\nphenoxides\nphenoxy\nphentolamine\nphentolamines\nphenyl\nphenylalanine\nphenylalanines\nphenylbutazone\nphenylbutazones\nphenylephrine\nphenylephrines\nphenylethylamine\nphenylethylamines\nphenylic\nphenylketonuria\nphenylketonurias\nphenylketonuric\nphenylketonurics\nphenylpropanolamine\nphenylpropanolamines\nphenyls\nphenylthiocarbamide\nphenylthiocarbamides\nphenylthiourea\nphenylthioureas\nphenytoin\nphenytoins\npheochromocytoma\npheochromocytomas\npheochromocytomata\npheromonal\npheromone\npheromones\nphew\nphi\nphial\nphials\nphilabeg\nphilabegs\nphiladelphus\nphiladelphuses\nphilander\nphilandered\nphilanderer\nphilanderers\nphilandering\nphilanders\nphilanthropic\nphilanthropical\nphilanthropically\nphilanthropies\nphilanthropist\nphilanthropists\nphilanthropoid\nphilanthropoids\nphilanthropy\nphilatelic\nphilatelically\nphilatelies\nphilatelist\nphilatelists\nphilately\nphilharmonic\nphilharmonics\nphilhellene\nphilhellenes\nphilhellenic\nphilhellenism\nphilhellenisms\nphilhellenist\nphilhellenists\nphilibeg\nphilibegs\nphilippic\nphilippics\nphilistia\nphilistine\nphilistines\nphilistinism\nphilistinisms\nphillumenist\nphillumenists\nphilodendra\nphilodendron\nphilodendrons\nphilological\nphilologically\nphilologies\nphilologist\nphilologists\nphilology\nphilomel\nphilomels\nphiloprogenitive\nphiloprogenitiveness\nphiloprogenitivenesses\nphilosophe\nphilosopher\nphilosophers\nphilosophes\nphilosophic\nphilosophical\nphilosophically\nphilosophies\nphilosophise\nphilosophised\nphilosophises\nphilosophising\nphilosophize\nphilosophized\nphilosophizer\nphilosophizers\nphilosophizes\nphilosophizing\nphilosophy\nphilter\nphiltered\nphiltering\nphilters\nphiltra\nphiltre\nphiltred\nphiltres\nphiltring\nphiltrum\nphimoses\nphimosis\nphimotic\nphis\nphiz\nphizes\nphlebitides\nphlebitis\nphlebogram\nphlebograms\nphlebographic\nphlebographies\nphlebography\nphlebologies\nphlebology\nphlebotomies\nphlebotomist\nphlebotomists\nphlebotomy\nphlegm\nphlegmatic\nphlegmatically\nphlegmier\nphlegmiest\nphlegms\nphlegmy\nphloem\nphloems\nphlogistic\nphlogiston\nphlogistons\nphlogopite\nphlogopites\nphlox\nphloxes\nphobia\nphobias\nphobic\nphobics\nphocine\nphoebe\nphoebes\nphoebus\nphoebuses\nphoenix\nphoenixes\nphoenixlike\nphon\nphonal\nphonate\nphonated\nphonates\nphonating\nphonation\nphonations\nphone\nphoned\nphonematic\nphoneme\nphonemes\nphonemic\nphonemically\nphonemicist\nphonemicists\nphonemics\nphones\nphonetic\nphonetically\nphonetician\nphoneticians\nphonetics\nphoney\nphoneyed\nphoneying\nphoneys\nphonic\nphonically\nphonics\nphonied\nphonier\nphonies\nphoniest\nphonily\nphoniness\nphoninesses\nphoning\nphono\nphonocardiogram\nphonocardiograms\nphonocardiograph\nphonocardiographic\nphonocardiographies\nphonocardiographs\nphonocardiography\nphonogram\nphonogramic\nphonogramically\nphonogrammic\nphonogrammically\nphonograms\nphonograph\nphonographer\nphonographers\nphonographic\nphonographically\nphonographies\nphonographs\nphonography\nphonolite\nphonolites\nphonologic\nphonological\nphonologically\nphonologies\nphonologist\nphonologists\nphonology\nphonon\nphonons\nphonos\nphonotactic\nphonotactics\nphons\nphony\nphonying\nphooey\nphorate\nphorates\nphoronid\nphoronids\nphosgene\nphosgenes\nphosphatase\nphosphatases\nphosphate\nphosphates\nphosphatic\nphosphatide\nphosphatides\nphosphatidic\nphosphatidyl\nphosphatidylcholine\nphosphatidylcholines\nphosphatidylethanolamine\nphosphatidylethanolamines\nphosphatidyls\nphosphatization\nphosphatizations\nphosphatize\nphosphatized\nphosphatizes\nphosphatizing\nphosphaturia\nphosphaturias\nphosphene\nphosphenes\nphosphid\nphosphide\nphosphides\nphosphids\nphosphin\nphosphine\nphosphines\nphosphins\nphosphite\nphosphites\nphosphocreatine\nphosphocreatines\nphosphodiesterase\nphosphodiesterases\nphosphoenolpyruvate\nphosphoenolpyruvates\nphosphofructokinase\nphosphofructokinases\nphosphoglucomutase\nphosphoglucomutases\nphosphoglyceraldehyde\nphosphoglyceraldehydes\nphosphoglycerate\nphosphoglycerates\nphosphokinase\nphosphokinases\nphospholipase\nphospholipases\nphospholipid\nphospholipids\nphosphomonoesterase\nphosphomonoesterases\nphosphonium\nphosphoniums\nphosphoprotein\nphosphoproteins\nphosphor\nphosphore\nphosphores\nphosphoresce\nphosphoresced\nphosphorescence\nphosphorescences\nphosphorescent\nphosphorescently\nphosphoresces\nphosphorescing\nphosphoric\nphosphorite\nphosphorites\nphosphoritic\nphosphorolyses\nphosphorolysis\nphosphorolytic\nphosphorous\nphosphors\nphosphorus\nphosphoruses\nphosphoryl\nphosphorylase\nphosphorylases\nphosphorylate\nphosphorylated\nphosphorylates\nphosphorylating\nphosphorylation\nphosphorylations\nphosphorylative\nphosphoryls\nphot\nphotic\nphotically\nphotics\nphoto\nphotoautotroph\nphotoautotrophic\nphotoautotrophically\nphotoautotrophs\nphotobiologic\nphotobiological\nphotobiologies\nphotobiologist\nphotobiologists\nphotobiology\nphotocathode\nphotocathodes\nphotocell\nphotocells\nphotochemical\nphotochemically\nphotochemist\nphotochemistries\nphotochemistry\nphotochemists\nphotochromic\nphotochromism\nphotochromisms\nphotocoagulation\nphotocoagulations\nphotocompose\nphotocomposed\nphotocomposer\nphotocomposers\nphotocomposes\nphotocomposing\nphotocomposition\nphotocompositions\nphotoconductive\nphotoconductivities\nphotoconductivity\nphotocopied\nphotocopier\nphotocopiers\nphotocopies\nphotocopy\nphotocopying\nphotocurrent\nphotocurrents\nphotodecomposition\nphotodecompositions\nphotodegradable\nphotodetector\nphotodetectors\nphotodiode\nphotodiodes\nphotodisintegrate\nphotodisintegrated\nphotodisintegrates\nphotodisintegrating\nphotodisintegration\nphotodisintegrations\nphotodissociate\nphotodissociated\nphotodissociates\nphotodissociating\nphotodissociation\nphotodissociations\nphotoduplicate\nphotoduplicated\nphotoduplicates\nphotoduplicating\nphotoduplication\nphotoduplications\nphotodynamic\nphotodynamically\nphotoed\nphotoelectric\nphotoelectrically\nphotoelectron\nphotoelectronic\nphotoelectrons\nphotoemission\nphotoemissions\nphotoemissive\nphotoengrave\nphotoengraved\nphotoengraver\nphotoengravers\nphotoengraves\nphotoengraving\nphotoengravings\nphotoexcitation\nphotoexcitations\nphotoexcited\nphotofinisher\nphotofinishers\nphotofinishing\nphotofinishings\nphotoflash\nphotoflashes\nphotoflood\nphotofloods\nphotofluorographies\nphotofluorography\nphotog\nphotogenic\nphotogenically\nphotogeologic\nphotogeological\nphotogeologies\nphotogeologist\nphotogeologists\nphotogeology\nphotogram\nphotogrammetric\nphotogrammetries\nphotogrammetrist\nphotogrammetrists\nphotogrammetry\nphotograms\nphotograph\nphotographed\nphotographer\nphotographers\nphotographic\nphotographically\nphotographies\nphotographing\nphotographs\nphotography\nphotogravure\nphotogravures\nphotogs\nphotoinduced\nphotoinduction\nphotoinductions\nphotoinductive\nphotoing\nphotointerpretation\nphotointerpretations\nphotointerpreter\nphotointerpreters\nphotoionization\nphotoionizations\nphotoionize\nphotoionized\nphotoionizes\nphotoionizing\nphotojournalism\nphotojournalisms\nphotojournalist\nphotojournalistic\nphotojournalists\nphotokineses\nphotokinesis\nphotokinetic\nphotolithograph\nphotolithographed\nphotolithographic\nphotolithographically\nphotolithographies\nphotolithographing\nphotolithographs\nphotolithography\nphotolyses\nphotolysis\nphotolytic\nphotolytically\nphotolyzable\nphotolyze\nphotolyzed\nphotolyzes\nphotolyzing\nphotomap\nphotomapped\nphotomapping\nphotomaps\nphotomask\nphotomasks\nphotomechanical\nphotomechanically\nphotometer\nphotometers\nphotometric\nphotometrically\nphotometries\nphotometry\nphotomicrograph\nphotomicrographic\nphotomicrographies\nphotomicrographs\nphotomicrography\nphotomontage\nphotomontages\nphotomorphogeneses\nphotomorphogenesis\nphotomorphogenic\nphotomosaic\nphotomosaics\nphotomultiplier\nphotomultipliers\nphotomural\nphotomurals\nphoton\nphotonegative\nphotonic\nphotonics\nphotons\nphotonuclear\nphotooxidation\nphotooxidations\nphotooxidative\nphotooxidize\nphotooxidized\nphotooxidizes\nphotooxidizing\nphotoperiod\nphotoperiodic\nphotoperiodically\nphotoperiodism\nphotoperiodisms\nphotoperiods\nphotophase\nphotophases\nphotophobia\nphotophobias\nphotophobic\nphotophore\nphotophores\nphotophosphorylation\nphotophosphorylations\nphotopia\nphotopias\nphotopic\nphotoplay\nphotoplays\nphotopolarimeter\nphotopolarimeters\nphotopolymer\nphotopolymers\nphotopositive\nphotoproduct\nphotoproduction\nphotoproductions\nphotoproducts\nphotoreaction\nphotoreactions\nphotoreactivating\nphotoreactivation\nphotoreactivations\nphotoreception\nphotoreceptions\nphotoreceptive\nphotoreceptor\nphotoreceptors\nphotoreconnaissance\nphotoreconnaissances\nphotoreduce\nphotoreduced\nphotoreduces\nphotoreducing\nphotoreduction\nphotoreductions\nphotoreproduction\nphotoreproductions\nphotoresist\nphotoresists\nphotorespiration\nphotorespirations\nphotos\nphotosensitive\nphotosensitivities\nphotosensitivity\nphotosensitization\nphotosensitizations\nphotosensitize\nphotosensitized\nphotosensitizer\nphotosensitizers\nphotosensitizes\nphotosensitizing\nphotoset\nphotosets\nphotosetter\nphotosetters\nphotosetting\nphotosphere\nphotospheres\nphotospheric\nphotostat\nphotostated\nphotostatic\nphotostating\nphotostats\nphotostatted\nphotostatting\nphotosynthate\nphotosynthates\nphotosyntheses\nphotosynthesis\nphotosynthesize\nphotosynthesized\nphotosynthesizes\nphotosynthesizing\nphotosynthetic\nphotosynthetically\nphotosystem\nphotosystems\nphototactic\nphototactically\nphototaxes\nphototaxis\nphototelegraphies\nphototelegraphy\nphototoxic\nphototoxicities\nphototoxicity\nphototropic\nphototropically\nphototropism\nphototropisms\nphototube\nphototubes\nphototypesetter\nphototypesetters\nphototypesetting\nphototypesettings\nphotovoltaic\nphotovoltaics\nphots\nphpht\nphragmoplast\nphragmoplasts\nphrasal\nphrasally\nphrase\nphrased\nphrasemaker\nphrasemakers\nphrasemaking\nphrasemakings\nphrasemonger\nphrasemongering\nphrasemongerings\nphrasemongers\nphraseological\nphraseologies\nphraseologist\nphraseologists\nphraseology\nphrases\nphrasing\nphrasings\nphratral\nphratric\nphratries\nphratry\nphreatic\nphreatophyte\nphreatophytes\nphreatophytic\nphrenetic\nphrenic\nphrenological\nphrenologies\nphrenologist\nphrenologists\nphrenology\nphrensied\nphrensies\nphrensy\nphrensying\npht\nphthalic\nphthalin\nphthalins\nphthalocyanine\nphthalocyanines\nphthises\nphthisic\nphthisical\nphthisics\nphthisis\nphut\nphuts\nphycocyanin\nphycocyanins\nphycoerythrin\nphycoerythrins\nphycological\nphycologies\nphycologist\nphycologists\nphycology\nphycomycete\nphycomycetes\nphycomycetous\nphyla\nphylacteries\nphylactery\nphylae\nphylar\nphylaxis\nphylaxises\nphyle\nphyleses\nphylesis\nphylesises\nphyletic\nphyletically\nphylic\nphyllaries\nphyllary\nphyllite\nphyllites\nphyllo\nphylloclade\nphylloclades\nphyllode\nphyllodes\nphyllodia\nphyllodium\nphylloid\nphylloids\nphyllome\nphyllomes\nphyllos\nphyllotactic\nphyllotaxes\nphyllotaxies\nphyllotaxis\nphyllotaxy\nphylloxera\nphylloxerae\nphylloxeras\nphylogenetic\nphylogenetically\nphylogenies\nphylogeny\nphylon\nphylum\nphysed\nphyseds\nphyses\nphysiatrist\nphysiatrists\nphysic\nphysical\nphysicalism\nphysicalisms\nphysicalist\nphysicalistic\nphysicalists\nphysicalities\nphysicality\nphysically\nphysicalness\nphysicalnesses\nphysicals\nphysician\nphysicians\nphysicist\nphysicists\nphysicked\nphysicking\nphysicochemical\nphysicochemically\nphysics\nphysiocratic\nphysiognomic\nphysiognomical\nphysiognomically\nphysiognomies\nphysiognomy\nphysiographer\nphysiographers\nphysiographic\nphysiographical\nphysiographies\nphysiography\nphysiologic\nphysiological\nphysiologically\nphysiologies\nphysiologist\nphysiologists\nphysiology\nphysiopathologic\nphysiopathological\nphysiopathologies\nphysiopathology\nphysiotherapies\nphysiotherapist\nphysiotherapists\nphysiotherapy\nphysique\nphysiques\nphysis\nphysostigmine\nphysostigmines\nphytane\nphytanes\nphytoalexin\nphytoalexins\nphytochemical\nphytochemically\nphytochemist\nphytochemistries\nphytochemistry\nphytochemists\nphytochrome\nphytochromes\nphytoflagellate\nphytoflagellates\nphytogeographer\nphytogeographers\nphytogeographic\nphytogeographical\nphytogeographically\nphytogeographies\nphytogeography\nphytohemagglutinin\nphytohemagglutinins\nphytohormone\nphytohormones\nphytoid\nphytol\nphytols\nphyton\nphytonic\nphytons\nphytopathogen\nphytopathogenic\nphytopathogens\nphytopathological\nphytopathologies\nphytopathology\nphytophagous\nphytoplankter\nphytoplankters\nphytoplankton\nphytoplanktonic\nphytoplanktons\nphytosociological\nphytosociologies\nphytosociology\nphytosterol\nphytosterols\nphytotoxic\nphytotoxicities\nphytotoxicity\npi\npia\npiacular\npiaffe\npiaffed\npiaffer\npiaffers\npiaffes\npiaffing\npial\npian\npianic\npianism\npianisms\npianissimi\npianissimo\npianissimos\npianist\npianistic\npianistically\npianists\npiano\npianoforte\npianofortes\npianos\npians\npias\npiasaba\npiasabas\npiasava\npiasavas\npiassaba\npiassabas\npiassava\npiassavas\npiaster\npiasters\npiastre\npiastres\npiazza\npiazzas\npiazze\npibal\npibals\npibroch\npibrochs\npic\npica\npicacho\npicachos\npicador\npicadores\npicadors\npical\npicaninnies\npicaninny\npicante\npicara\npicaras\npicaresque\npicaresques\npicaro\npicaroon\npicarooned\npicarooning\npicaroons\npicaros\npicas\npicayune\npicayunes\npicayunish\npiccalilli\npiccalillis\npiccolo\npiccoloist\npiccoloists\npiccolos\npice\npiceous\npiciform\npick\npickaback\npickabacked\npickabacking\npickabacks\npickadil\npickadils\npickaninnies\npickaninny\npickaroon\npickaroons\npickax\npickaxe\npickaxed\npickaxes\npickaxing\npicked\npickeer\npickeered\npickeering\npickeers\npicker\npickerel\npickerels\npickerelweed\npickerelweeds\npickers\npicket\npicketboat\npicketboats\npicketed\npicketer\npicketers\npicketing\npickets\npickier\npickiest\npicking\npickings\npickle\npickled\npickles\npickling\npicklock\npicklocks\npickoff\npickoffs\npickpocket\npickpockets\npickproof\npicks\npickthank\npickthanks\npickup\npickups\npickwick\npickwicks\npicky\npicloram\npiclorams\npicnic\npicnicked\npicnicker\npicnickers\npicnicking\npicnicky\npicnics\npicofarad\npicofarads\npicogram\npicograms\npicolin\npicoline\npicolines\npicolins\npicomole\npicomoles\npicornavirus\npicornaviruses\npicosecond\npicoseconds\npicot\npicoted\npicotee\npicotees\npicoting\npicots\npicquet\npicquets\npicrate\npicrated\npicrates\npicric\npicrite\npicrites\npicritic\npicrotoxin\npicrotoxins\npics\npictogram\npictograms\npictograph\npictographic\npictographies\npictographs\npictography\npictorial\npictorialism\npictorialisms\npictorialist\npictorialists\npictorialization\npictorializations\npictorialize\npictorialized\npictorializes\npictorializing\npictorially\npictorialness\npictorialnesses\npictorials\npicture\npictured\npicturephone\npicturephones\npictures\npicturesque\npicturesquely\npicturesqueness\npicturesquenesses\npicturing\npicturization\npicturizations\npicturize\npicturized\npicturizes\npicturizing\npicul\npiculs\npiddle\npiddled\npiddler\npiddlers\npiddles\npiddling\npiddly\npiddock\npiddocks\npidgin\npidginization\npidginizations\npidginize\npidginized\npidginizes\npidginizing\npidgins\npie\npiebald\npiebalds\npiece\npieced\npiecemeal\npiecer\npiecers\npieces\npiecewise\npiecework\npieceworker\npieceworkers\npieceworks\npiecing\npiecings\npiecrust\npiecrusts\npied\npiedfort\npiedforts\npiedmont\npiedmonts\npiefort\npieforts\npieing\npieplant\npieplants\npier\npierce\npierced\npiercer\npiercers\npierces\npiercing\npiercingly\npiercings\npierogi\npierogies\npierrot\npierrots\npiers\npies\npieta\npietas\npieties\npietism\npietisms\npietist\npietistic\npietistically\npietists\npiety\npiezoelectric\npiezoelectrically\npiezoelectricities\npiezoelectricity\npiezometer\npiezometers\npiezometric\npiffle\npiffled\npiffles\npiffling\npig\npigboat\npigboats\npigeon\npigeonhole\npigeonholed\npigeonholer\npigeonholers\npigeonholes\npigeonholing\npigeonite\npigeonites\npigeons\npigeonwing\npigeonwings\npigfish\npigfishes\npigged\npiggeries\npiggery\npiggie\npiggier\npiggies\npiggiest\npiggin\npigging\npiggins\npiggish\npiggishly\npiggishness\npiggishnesses\npiggy\npiggyback\npiggybacked\npiggybacking\npiggybacks\npigheaded\npigheadedly\npigheadedness\npigheadednesses\npiglet\npiglets\npiglike\npigment\npigmentary\npigmentation\npigmentations\npigmented\npigmenting\npigments\npigmies\npigmy\npignoli\npignolia\npignolias\npignolis\npignora\npignus\npignut\npignuts\npigout\npigouts\npigpen\npigpens\npigs\npigskin\npigskins\npigsney\npigsneys\npigstick\npigsticked\npigsticker\npigstickers\npigsticking\npigsticks\npigsties\npigsty\npigtail\npigtailed\npigtails\npigweed\npigweeds\npiing\npika\npikake\npikakes\npikas\npike\npiked\npikeman\npikemen\npiker\npikers\npikes\npikestaff\npikestaffs\npikestaves\npiki\npiking\npikis\npilaf\npilaff\npilaffs\npilafs\npilar\npilaster\npilasters\npilau\npilaus\npilaw\npilaws\npilchard\npilchards\npile\npilea\npileate\npileated\npiled\npilei\npileless\npileous\npiles\npileum\npileup\npileups\npileus\npilewort\npileworts\npilfer\npilferable\npilferage\npilferages\npilfered\npilferer\npilferers\npilfering\npilferproof\npilfers\npilgarlic\npilgarlics\npilgrim\npilgrimage\npilgrimaged\npilgrimages\npilgrimaging\npilgrims\npili\npiliform\npiling\npilings\npilis\npill\npillage\npillaged\npillager\npillagers\npillages\npillaging\npillar\npillared\npillaring\npillarless\npillars\npillbox\npillboxes\npilled\npilling\npillion\npillions\npilloried\npillories\npillory\npillorying\npillow\npillowcase\npillowcases\npillowed\npillowing\npillows\npillowy\npills\npilocarpine\npilocarpines\npilose\npilosities\npilosity\npilot\npilotage\npilotages\npiloted\npilothouse\npilothouses\npiloting\npilotings\npilotless\npilots\npilous\npilsener\npilseners\npilsner\npilsners\npilular\npilule\npilules\npilus\npily\npima\npimas\npimento\npimentos\npimiento\npimientos\npimp\npimped\npimpernel\npimpernels\npimping\npimple\npimpled\npimples\npimplier\npimpliest\npimply\npimpmobile\npimpmobiles\npimps\npin\npina\npinafore\npinafored\npinafores\npinang\npinangs\npinas\npinaster\npinasters\npinata\npinatas\npinball\npinballs\npinbone\npinbones\npincer\npincerlike\npincers\npinch\npinchbeck\npinchbecks\npinchbug\npinchbugs\npincheck\npinchecks\npinched\npincher\npinchers\npinches\npinching\npinchpenny\npincushion\npincushions\npinder\npinders\npindling\npine\npineal\npinealectomies\npinealectomize\npinealectomized\npinealectomizes\npinealectomizing\npinealectomy\npineals\npineapple\npineapples\npinecone\npinecones\npined\npinedrops\npineland\npinelands\npinelike\npinene\npinenes\npineries\npinery\npines\npinesap\npinesaps\npineta\npinetum\npinewood\npinewoods\npiney\npinfeather\npinfeathers\npinfish\npinfishes\npinfold\npinfolded\npinfolding\npinfolds\nping\npinged\npinger\npingers\npinging\npingo\npingoes\npingos\npingrass\npingrasses\npings\npinguid\npinhead\npinheaded\npinheadedness\npinheadednesses\npinheads\npinhole\npinholes\npinier\npiniest\npining\npinion\npinioned\npinioning\npinions\npinite\npinites\npinitol\npinitols\npink\npinked\npinken\npinkened\npinkening\npinkens\npinker\npinkers\npinkest\npinkey\npinkeye\npinkeyes\npinkeys\npinkie\npinkies\npinking\npinkings\npinkish\npinkishness\npinkishnesses\npinkly\npinkness\npinknesses\npinko\npinkoes\npinkos\npinkroot\npinkroots\npinks\npinky\npinna\npinnace\npinnaces\npinnacle\npinnacled\npinnacles\npinnacling\npinnae\npinnal\npinnas\npinnate\npinnated\npinnately\npinnatifid\npinned\npinner\npinners\npinnies\npinning\npinniped\npinnipeds\npinnula\npinnulae\npinnular\npinnule\npinnules\npinny\npinochle\npinochles\npinocle\npinocles\npinocytic\npinocytoses\npinocytosis\npinocytotic\npinocytotically\npinole\npinoles\npinon\npinones\npinons\npinot\npinots\npinpoint\npinpointed\npinpointing\npinpoints\npinprick\npinpricked\npinpricking\npinpricks\npins\npinscher\npinschers\npinsetter\npinsetters\npinspotter\npinspotters\npinstripe\npinstriped\npinstripes\npint\npinta\npintada\npintadas\npintado\npintadoes\npintados\npintail\npintails\npintano\npintanos\npintas\npintle\npintles\npinto\npintoes\npintos\npints\npintsize\npinup\npinups\npinwale\npinwales\npinweed\npinweeds\npinwheel\npinwheeled\npinwheeling\npinwheels\npinwork\npinworks\npinworm\npinworms\npiny\npinyin\npinyon\npinyons\npiolet\npiolets\npion\npioneer\npioneered\npioneering\npioneers\npionic\npions\npiosities\npiosity\npious\npiously\npiousness\npiousnesses\npip\npipage\npipages\npipal\npipals\npipe\npipeage\npipeages\npiped\npipefish\npipefishes\npipeful\npipefuls\npipeless\npipelike\npipeline\npipelined\npipelines\npipelining\npiper\npiperazine\npiperazines\npiperidine\npiperidines\npiperine\npiperines\npiperonal\npiperonals\npipers\npipes\npipestem\npipestems\npipestone\npipestones\npipet\npipets\npipette\npipetted\npipettes\npipetting\npipier\npipiest\npipiness\npipinesses\npiping\npipingly\npipings\npipit\npipits\npipkin\npipkins\npipped\npippin\npipping\npippins\npips\npipsissewa\npipsissewas\npipsqueak\npipsqueaks\npipy\npiquance\npiquances\npiquancies\npiquancy\npiquant\npiquantly\npiquantness\npiquantnesses\npique\npiqued\npiques\npiquet\npiquets\npiquing\npiracies\npiracy\npiragua\npiraguas\npirana\npiranas\npiranha\npiranhas\npirarucu\npirarucus\npirate\npirated\npirates\npiratic\npiratical\npiratically\npirating\npiraya\npirayas\npiriform\npirn\npirns\npirog\npirogen\npiroghi\npirogi\npirogies\npirogue\npirogues\npirojki\npiroplasm\npiroplasma\npiroplasmata\npiroplasms\npiroque\npiroques\npiroshki\npirouette\npirouetted\npirouettes\npirouetting\npirozhki\npirozhok\npis\npiscaries\npiscary\npiscator\npiscatorial\npiscators\npiscatory\npisciculture\npiscicultures\npiscina\npiscinae\npiscinal\npiscinas\npiscine\npiscivorous\npisco\npiscos\npish\npished\npishes\npishing\npishoge\npishoges\npishogue\npishogues\npisiform\npisiforms\npismire\npismires\npiso\npisolite\npisolites\npisolitic\npisos\npiss\npissant\npissants\npissed\npisser\npissers\npisses\npissing\npissoir\npissoirs\npistache\npistaches\npistachio\npistachios\npistareen\npistareens\npiste\npistes\npistil\npistillate\npistils\npistol\npistole\npistoled\npistoleer\npistoleers\npistoles\npistoling\npistolled\npistolling\npistols\npiston\npistons\npit\npita\npitapat\npitapats\npitapatted\npitapatting\npitas\npitch\npitchblende\npitchblendes\npitched\npitcher\npitcherful\npitcherfuls\npitchers\npitchersful\npitches\npitchfork\npitchforked\npitchforking\npitchforks\npitchier\npitchiest\npitchily\npitching\npitchman\npitchmen\npitchout\npitchouts\npitchpole\npitchpoled\npitchpoles\npitchpoling\npitchwoman\npitchwomen\npitchy\npiteous\npiteously\npiteousness\npiteousnesses\npitfall\npitfalls\npith\npithead\npitheads\npithecanthropi\npithecanthropine\npithecanthropines\npithecanthropus\npithed\npithier\npithiest\npithily\npithiness\npithinesses\npithing\npithless\npiths\npithy\npitiable\npitiableness\npitiablenesses\npitiably\npitied\npitier\npitiers\npities\npitiful\npitifuller\npitifullest\npitifully\npitifulness\npitifulnesses\npitiless\npitilessly\npitilessness\npitilessnesses\npitman\npitmans\npitmen\npiton\npitons\npits\npitsaw\npitsaws\npittance\npittances\npitted\npitting\npittings\npittosporum\npittosporums\npituitaries\npituitary\npity\npitying\npityingly\npityriases\npityriasis\npiu\npivot\npivotable\npivotal\npivotally\npivoted\npivoting\npivotman\npivotmen\npivots\npix\npixel\npixels\npixes\npixie\npixieish\npixies\npixilated\npixilation\npixilations\npixillated\npixiness\npixinesses\npixy\npixyish\npizazz\npizazzes\npizazzy\npizza\npizzalike\npizzas\npizzazz\npizzazzes\npizzazzy\npizzeria\npizzerias\npizzicati\npizzicato\npizzle\npizzles\nplacabilities\nplacability\nplacable\nplacably\nplacard\nplacarded\nplacarding\nplacards\nplacate\nplacated\nplacater\nplacaters\nplacates\nplacating\nplacatingly\nplacation\nplacations\nplacative\nplacatory\nplace\nplaceable\nplacebo\nplaceboes\nplacebos\nplaced\nplaceholder\nplaceholders\nplacekick\nplacekicked\nplacekicker\nplacekickers\nplacekicking\nplacekicks\nplaceless\nplacelessly\nplaceman\nplacemen\nplacement\nplacements\nplacenta\nplacentae\nplacental\nplacentals\nplacentas\nplacentation\nplacentations\nplacer\nplacers\nplaces\nplacet\nplacets\nplacid\nplacidities\nplacidity\nplacidly\nplacidness\nplacidnesses\nplacing\nplack\nplacket\nplackets\nplacks\nplacoid\nplacoids\nplafond\nplafonds\nplagal\nplage\nplages\nplagiaries\nplagiarise\nplagiarised\nplagiarises\nplagiarising\nplagiarism\nplagiarisms\nplagiarist\nplagiaristic\nplagiarists\nplagiarize\nplagiarized\nplagiarizer\nplagiarizers\nplagiarizes\nplagiarizing\nplagiary\nplagioclase\nplagioclases\nplagiotropic\nplague\nplagued\nplaguer\nplaguers\nplagues\nplaguey\nplaguily\nplaguing\nplaguy\nplaice\nplaices\nplaid\nplaided\nplaids\nplain\nplainchant\nplainchants\nplainclothes\nplainclothesman\nplainclothesmen\nplained\nplainer\nplainest\nplaining\nplainly\nplainness\nplainnesses\nplains\nplainsman\nplainsmen\nplainsong\nplainsongs\nplainspoken\nplainspokenness\nplainspokennesses\nplaint\nplaintext\nplaintexts\nplaintful\nplaintiff\nplaintiffs\nplaintive\nplaintively\nplaintiveness\nplaintivenesses\nplaints\nplaister\nplaistered\nplaistering\nplaisters\nplait\nplaited\nplaiter\nplaiters\nplaiting\nplaitings\nplaits\nplan\nplanar\nplanaria\nplanarian\nplanarians\nplanarias\nplanarities\nplanarity\nplanate\nplanation\nplanations\nplanch\nplanche\nplanches\nplanchet\nplanchets\nplanchette\nplanchettes\nplane\nplaned\nplaneload\nplaneloads\nplaner\nplaners\nplanes\nplanet\nplanetaria\nplanetarium\nplanetariums\nplanetary\nplanetesimal\nplanetesimals\nplanetlike\nplanetoid\nplanetoidal\nplanetoids\nplanetological\nplanetologies\nplanetologist\nplanetologists\nplanetology\nplanets\nplanetwide\nplanform\nplanforms\nplangencies\nplangency\nplangent\nplangently\nplanimeter\nplanimeters\nplanimetric\nplanimetrically\nplaning\nplanish\nplanished\nplanisher\nplanishers\nplanishes\nplanishing\nplanisphere\nplanispheres\nplanispheric\nplank\nplanked\nplanking\nplankings\nplanks\nplankter\nplankters\nplankton\nplanktonic\nplanktons\nplanless\nplanlessly\nplanlessness\nplanlessnesses\nplanned\nplanner\nplanners\nplanning\nplannings\nplanographic\nplanographies\nplanography\nplanosol\nplanosols\nplans\nplant\nplantable\nplantain\nplantains\nplantar\nplantation\nplantations\nplanted\nplanter\nplanters\nplantigrade\nplantigrades\nplanting\nplantings\nplantlet\nplantlets\nplantlike\nplantocracies\nplantocracy\nplants\nplantsman\nplantsmen\nplanula\nplanulae\nplanular\nplaque\nplaques\nplash\nplashed\nplasher\nplashers\nplashes\nplashier\nplashiest\nplashing\nplashy\nplasm\nplasma\nplasmagel\nplasmagels\nplasmagene\nplasmagenes\nplasmalemma\nplasmalemmas\nplasmaphereses\nplasmapheresis\nplasmas\nplasmasol\nplasmasols\nplasmatic\nplasmic\nplasmid\nplasmids\nplasmin\nplasminogen\nplasminogens\nplasmins\nplasmodesm\nplasmodesma\nplasmodesmas\nplasmodesmata\nplasmodesms\nplasmodia\nplasmodium\nplasmogamies\nplasmogamy\nplasmoid\nplasmoids\nplasmolyses\nplasmolysis\nplasmolytic\nplasmolyze\nplasmolyzed\nplasmolyzes\nplasmolyzing\nplasmon\nplasmons\nplasms\nplaster\nplasterboard\nplasterboards\nplastered\nplasterer\nplasterers\nplastering\nplasterings\nplasters\nplasterwork\nplasterworks\nplastery\nplastic\nplastically\nplasticene\nplasticenes\nplasticine\nplasticines\nplasticities\nplasticity\nplasticization\nplasticizations\nplasticize\nplasticized\nplasticizer\nplasticizers\nplasticizes\nplasticizing\nplasticky\nplastics\nplastid\nplastidial\nplastids\nplastisol\nplastisols\nplastocyanin\nplastocyanins\nplastoquinone\nplastoquinones\nplastral\nplastron\nplastrons\nplastrum\nplastrums\nplat\nplatan\nplatane\nplatanes\nplatans\nplate\nplateau\nplateaued\nplateauing\nplateaus\nplateaux\nplated\nplateful\nplatefuls\nplateglass\nplatelet\nplatelets\nplatelike\nplatemaker\nplatemakers\nplatemaking\nplatemakings\nplaten\nplatens\nplater\nplateresque\nplaters\nplates\nplatesful\nplatform\nplatforms\nplatier\nplaties\nplatiest\nplatina\nplatinas\nplating\nplatings\nplatinic\nplatinize\nplatinized\nplatinizes\nplatinizing\nplatinocyanide\nplatinocyanides\nplatinum\nplatinums\nplatitude\nplatitudes\nplatitudinal\nplatitudinarian\nplatitudinarians\nplatitudinize\nplatitudinized\nplatitudinizes\nplatitudinizing\nplatitudinous\nplatitudinously\nplatonic\nplatonically\nplatoon\nplatooned\nplatooning\nplatoons\nplats\nplatted\nplatter\nplatterful\nplatterfuls\nplatters\nplattersful\nplatting\nplaty\nplatyfish\nplatyfishes\nplatyhelminth\nplatyhelminthic\nplatyhelminths\nplatypi\nplatypus\nplatypuses\nplatyrrhine\nplatyrrhines\nplatys\nplaudit\nplaudits\nplausibilities\nplausibility\nplausible\nplausibleness\nplausiblenesses\nplausibly\nplausive\nplay\nplaya\nplayabilities\nplayability\nplayable\nplayact\nplayacted\nplayacting\nplayactings\nplayacts\nplayas\nplayback\nplaybacks\nplaybill\nplaybills\nplaybook\nplaybooks\nplayboy\nplayboys\nplaydate\nplaydates\nplayday\nplaydays\nplaydown\nplaydowns\nplayed\nplayer\nplayers\nplayfellow\nplayfellows\nplayfield\nplayfields\nplayful\nplayfully\nplayfulness\nplayfulnesses\nplaygirl\nplaygirls\nplaygoer\nplaygoers\nplayground\nplaygrounds\nplayhouse\nplayhouses\nplaying\nplayland\nplaylands\nplayless\nplaylet\nplaylets\nplaylike\nplaylist\nplaylists\nplaymaker\nplaymakers\nplaymaking\nplaymakings\nplaymate\nplaymates\nplayoff\nplayoffs\nplaypen\nplaypens\nplayroom\nplayrooms\nplays\nplaysuit\nplaysuits\nplaything\nplaythings\nplaytime\nplaytimes\nplaywear\nplaywright\nplaywrighting\nplaywrightings\nplaywrights\nplaywriting\nplaywritings\nplaza\nplazas\nplea\npleach\npleached\npleaches\npleaching\nplead\npleadable\npleaded\npleader\npleaders\npleading\npleadingly\npleadings\npleads\npleas\npleasance\npleasances\npleasant\npleasanter\npleasantest\npleasantly\npleasantness\npleasantnesses\npleasantries\npleasantry\nplease\npleased\npleaser\npleasers\npleases\npleasing\npleasingly\npleasingness\npleasingnesses\npleasurabilities\npleasurability\npleasurable\npleasurableness\npleasurablenesses\npleasurably\npleasure\npleasured\npleasureless\npleasures\npleasuring\npleat\npleated\npleater\npleaters\npleating\npleatless\npleats\npleb\nplebe\nplebeian\nplebeianism\nplebeianisms\nplebeianly\nplebeians\nplebes\nplebiscitary\nplebiscite\nplebiscites\nplebs\nplecopteran\nplecopterans\nplectra\nplectron\nplectrons\nplectrum\nplectrums\npled\npledge\npledged\npledgee\npledgees\npledgeor\npledgeors\npledger\npledgers\npledges\npledget\npledgets\npledging\npledgor\npledgors\npleiad\npleiades\npleiads\npleinairism\npleinairisms\npleinairist\npleinairists\npleiotropic\npleiotropies\npleiotropy\nplena\nplenary\nplench\nplenches\nplenipotent\nplenipotentiaries\nplenipotentiary\nplenish\nplenished\nplenishes\nplenishing\nplenism\nplenisms\nplenist\nplenists\nplenitude\nplenitudes\nplenitudinous\nplenteous\nplenteously\nplenteousness\nplenteousnesses\nplenties\nplentiful\nplentifully\nplentifulness\nplentifulnesses\nplentitude\nplentitudes\nplenty\nplenum\nplenums\npleochroic\npleochroism\npleochroisms\npleomorphic\npleomorphism\npleomorphisms\npleonasm\npleonasms\npleonastic\npleonastically\npleopod\npleopods\nplerocercoid\nplerocercoids\nplesiosaur\nplesiosaurs\nplessor\nplessors\nplethora\nplethoras\nplethoric\nplethysmogram\nplethysmograms\nplethysmograph\nplethysmographic\nplethysmographically\nplethysmographies\nplethysmographs\nplethysmography\npleura\npleurae\npleural\npleuras\npleurisies\npleurisy\npleuritic\npleuron\npleuropneumonia\npleuropneumonias\npleuston\npleustonic\npleustons\nplew\nplews\nplexal\nplexiform\nplexor\nplexors\nplexus\nplexuses\npliabilities\npliability\npliable\npliableness\npliablenesses\npliably\npliancies\npliancy\npliant\npliantly\npliantness\npliantnesses\nplica\nplicae\nplical\nplicate\nplicated\nplication\nplications\nplie\nplied\nplier\npliers\nplies\nplight\nplighted\nplighter\nplighters\nplighting\nplights\nplimsol\nplimsole\nplimsoles\nplimsoll\nplimsolls\nplimsols\nplink\nplinked\nplinker\nplinkers\nplinking\nplinks\nplinth\nplinths\npliotron\npliotrons\npliskie\npliskies\nplisky\nplisse\nplisses\nplod\nplodded\nplodder\nplodders\nplodding\nploddingly\nplods\nploidies\nploidy\nplonk\nplonked\nplonking\nplonks\nplop\nplopped\nplopping\nplops\nplosion\nplosions\nplosive\nplosives\nplot\nplotless\nplotlessness\nplotlessnesses\nplotline\nplotlines\nplots\nplottage\nplottages\nplotted\nplotter\nplotters\nplottier\nplotties\nplottiest\nplotting\nplotty\nplotz\nplotzed\nplotzes\nplotzing\nplough\nploughed\nplougher\nploughers\nploughing\nploughs\nplover\nplovers\nplow\nplowable\nplowback\nplowbacks\nplowboy\nplowboys\nplowed\nplower\nplowers\nplowhead\nplowheads\nplowing\nplowland\nplowlands\nplowman\nplowmen\nplows\nplowshare\nplowshares\nploy\nployed\nploying\nploys\npluck\nplucked\nplucker\npluckers\npluckier\npluckiest\npluckily\npluckiness\npluckinesses\nplucking\nplucks\nplucky\nplug\nplugged\nplugger\npluggers\nplugging\nplugless\nplugola\nplugolas\nplugs\npluguglies\nplugugly\nplum\nplumage\nplumaged\nplumages\nplumate\nplumb\nplumbago\nplumbagos\nplumbed\nplumber\nplumberies\nplumbers\nplumbery\nplumbic\nplumbing\nplumbings\nplumbism\nplumbisms\nplumbous\nplumbs\nplumbum\nplumbums\nplume\nplumed\nplumelet\nplumelets\nplumeria\nplumerias\nplumes\nplumier\nplumiest\npluming\nplumiped\nplumipeds\nplumlike\nplummet\nplummeted\nplummeting\nplummets\nplummier\nplummiest\nplummy\nplumose\nplump\nplumped\nplumpen\nplumpened\nplumpening\nplumpens\nplumper\nplumpers\nplumpest\nplumping\nplumpish\nplumply\nplumpness\nplumpnesses\nplumps\nplums\nplumular\nplumule\nplumules\nplumy\nplunder\nplundered\nplunderer\nplunderers\nplundering\nplunderous\nplunders\nplunge\nplunged\nplunger\nplungers\nplunges\nplunging\nplunk\nplunked\nplunker\nplunkers\nplunking\nplunks\npluperfect\npluperfects\nplural\npluralism\npluralisms\npluralist\npluralistic\npluralistically\npluralists\npluralities\nplurality\npluralization\npluralizations\npluralize\npluralized\npluralizes\npluralizing\nplurally\nplurals\npluripotent\nplus\npluses\nplush\nplusher\nplushes\nplushest\nplushier\nplushiest\nplushily\nplushiness\nplushinesses\nplushly\nplushness\nplushnesses\nplushy\nplussage\nplussages\nplusses\nplutei\npluteus\nplutocracies\nplutocracy\nplutocrat\nplutocratic\nplutocratically\nplutocrats\npluton\nplutonian\nplutonic\nplutonium\nplutoniums\nplutons\npluvial\npluvials\npluvian\npluviose\npluvious\nply\nplyer\nplyers\nplying\nplyingly\nplyometric\nplyometrics\nplywood\nplywoods\npneuma\npneumas\npneumatic\npneumatically\npneumaticities\npneumaticity\npneumatologies\npneumatology\npneumatolytic\npneumatophore\npneumatophores\npneumococcal\npneumococci\npneumococcus\npneumoconioses\npneumoconiosis\npneumograph\npneumographs\npneumonectomies\npneumonectomy\npneumonia\npneumonias\npneumonic\npneumonitides\npneumonitis\npneumothoraces\npneumothorax\npneumothoraxes\npoaceous\npoach\npoached\npoacher\npoachers\npoaches\npoachier\npoachiest\npoaching\npoachy\npochard\npochards\npock\npocked\npocket\npocketable\npocketbook\npocketbooks\npocketed\npocketer\npocketers\npocketful\npocketfuls\npocketing\npocketknife\npocketknives\npockets\npocketsful\npockier\npockiest\npockily\npocking\npockmark\npockmarked\npockmarking\npockmarks\npocks\npocky\npoco\npococurante\npococurantism\npococurantisms\npocosin\npocosins\npod\npodagra\npodagral\npodagras\npodagric\npodded\npodding\npodesta\npodestas\npodgier\npodgiest\npodgily\npodgy\npodia\npodiatric\npodiatries\npodiatrist\npodiatrists\npodiatry\npodite\npodites\npoditic\npodium\npodiums\npodlike\npodocarp\npodomere\npodomeres\npodophylli\npodophyllin\npodophyllins\npodophyllum\npodophyllums\npods\npodsol\npodsolic\npodsolization\npodsolizations\npodsols\npodzol\npodzolic\npodzolization\npodzolizations\npodzolize\npodzolized\npodzolizes\npodzolizing\npodzols\npoechore\npoechores\npoem\npoems\npoesies\npoesy\npoet\npoetaster\npoetasters\npoetess\npoetesses\npoetic\npoetical\npoetically\npoeticalness\npoeticalnesses\npoeticism\npoeticisms\npoeticize\npoeticized\npoeticizes\npoeticizing\npoetics\npoetise\npoetised\npoetiser\npoetisers\npoetises\npoetising\npoetize\npoetized\npoetizer\npoetizers\npoetizes\npoetizing\npoetless\npoetlike\npoetries\npoetry\npoets\npogey\npogeys\npogies\npogonia\npogonias\npogonip\npogonips\npogonophoran\npogonophorans\npogrom\npogromed\npogroming\npogromist\npogromists\npogroms\npogy\npoh\npoi\npoignance\npoignances\npoignancies\npoignancy\npoignant\npoignantly\npoikilotherm\npoikilothermic\npoikilotherms\npoilu\npoilus\npoinciana\npoincianas\npoind\npoinded\npoinding\npoinds\npoinsettia\npoinsettias\npoint\npointe\npointed\npointedly\npointedness\npointednesses\npointelle\npointelles\npointer\npointers\npointes\npointier\npointiest\npointillism\npointillisms\npointillist\npointillistic\npointillists\npointing\npointless\npointlessly\npointlessness\npointlessnesses\npointman\npointmen\npoints\npointtillist\npointy\npois\npoise\npoised\npoiser\npoisers\npoises\npoisha\npoising\npoison\npoisoned\npoisoner\npoisoners\npoisoning\npoisonings\npoisonous\npoisonously\npoisons\npoisonwood\npoisonwoods\npoitrel\npoitrels\npoke\npokeberries\npokeberry\npoked\npoker\npokeroot\npokeroots\npokers\npokes\npokeweed\npokeweeds\npokey\npokeys\npokier\npokies\npokiest\npokily\npokiness\npokinesses\npoking\npoky\npol\npolar\npolarimeter\npolarimeters\npolarimetric\npolarimetries\npolarimetry\npolariscope\npolariscopes\npolariscopic\npolarise\npolarised\npolarises\npolarising\npolarities\npolarity\npolarizabilities\npolarizability\npolarizable\npolarization\npolarizations\npolarize\npolarized\npolarizer\npolarizers\npolarizes\npolarizing\npolarographic\npolarographically\npolarographies\npolarography\npolaron\npolarons\npolars\npolder\npolders\npole\npoleax\npoleaxe\npoleaxed\npoleaxes\npoleaxing\npolecat\npolecats\npoled\npoleis\npoleless\npolemic\npolemical\npolemically\npolemicist\npolemicists\npolemicize\npolemicized\npolemicizes\npolemicizing\npolemics\npolemist\npolemists\npolemize\npolemized\npolemizes\npolemizing\npolemonium\npolemoniums\npolenta\npolentas\npoler\npolers\npoles\npolestar\npolestars\npoleward\npoleyn\npoleyns\npolice\npoliced\npoliceman\npolicemen\npolices\npolicewoman\npolicewomen\npolicies\npolicing\npolicy\npolicyholder\npolicyholders\npolies\npoling\npolio\npoliomyelitides\npoliomyelitis\npolios\npoliovirus\npolioviruses\npolis\npolish\npolished\npolisher\npolishers\npolishes\npolishing\npolitburo\npolitburos\npolite\npolitely\npoliteness\npolitenesses\npoliter\npolitesse\npolitesses\npolitest\npolitic\npolitical\npoliticalization\npoliticalizations\npoliticalize\npoliticalized\npoliticalizes\npoliticalizing\npolitically\npolitician\npoliticians\npoliticise\npoliticised\npoliticises\npoliticising\npoliticization\npoliticizations\npoliticize\npoliticized\npoliticizes\npoliticizing\npolitick\npoliticked\npoliticker\npolitickers\npoliticking\npoliticks\npolitico\npoliticoes\npoliticos\npolitics\npolities\npolity\npolka\npolkaed\npolkaing\npolkas\npoll\npollack\npollacks\npollard\npollarded\npollarding\npollards\npolled\npollee\npollees\npollen\npollened\npollening\npollenizer\npollenizers\npollenoses\npollenosis\npollens\npoller\npollers\npollex\npollical\npollices\npollinate\npollinated\npollinates\npollinating\npollination\npollinations\npollinator\npollinators\npolling\npollinia\npollinic\npollinium\npollinizer\npollinizers\npollinoses\npollinosis\npollist\npollists\npolliwog\npolliwogs\npollock\npollocks\npolls\npollster\npollsters\npollutant\npollutants\npollute\npolluted\npolluter\npolluters\npollutes\npolluting\npollution\npollutions\npollutive\npollywog\npollywogs\npolo\npoloist\npoloists\npolonaise\npolonaises\npolonium\npoloniums\npolos\npols\npoltergeist\npoltergeists\npoltroon\npoltrooneries\npoltroonery\npoltroons\npoly\npolyacrylamide\npolyacrylamides\npolyacrylonitrile\npolyacrylonitriles\npolyalcohol\npolyalcohols\npolyamide\npolyamides\npolyamine\npolyamines\npolyandries\npolyandrous\npolyandry\npolyantha\npolyanthas\npolyanthi\npolyanthus\npolyanthuses\npolyatomic\npolybrid\npolybrids\npolybutadiene\npolybutadienes\npolycarbonate\npolycarbonates\npolycentric\npolycentrism\npolycentrisms\npolychaete\npolychaetes\npolychotomies\npolychotomous\npolychotomy\npolychromatic\npolychromatophilia\npolychromatophilias\npolychromatophilic\npolychrome\npolychromed\npolychromes\npolychromies\npolychroming\npolychromy\npolycistronic\npolyclinic\npolyclinics\npolyclonal\npolycondensation\npolycondensations\npolycot\npolycots\npolycrystal\npolycrystalline\npolycrystals\npolycyclic\npolycystic\npolycythemia\npolycythemias\npolycythemic\npolydactyl\npolydactylies\npolydactyly\npolydipsia\npolydipsias\npolydipsic\npolydisperse\npolydispersities\npolydispersity\npolyelectrolyte\npolyelectrolytes\npolyembryonic\npolyembryonies\npolyembryony\npolyene\npolyenes\npolyenic\npolyester\npolyesterification\npolyesterifications\npolyesters\npolyestrous\npolyethylene\npolyethylenes\npolygala\npolygalas\npolygamic\npolygamies\npolygamist\npolygamists\npolygamize\npolygamized\npolygamizes\npolygamizing\npolygamous\npolygamy\npolygene\npolygenes\npolygeneses\npolygenesis\npolygenetic\npolygenic\npolyglot\npolyglotism\npolyglotisms\npolyglots\npolyglottism\npolyglottisms\npolygon\npolygonal\npolygonally\npolygonies\npolygons\npolygonum\npolygonums\npolygony\npolygraph\npolygrapher\npolygraphers\npolygraphic\npolygraphist\npolygraphists\npolygraphs\npolygynies\npolygynous\npolygyny\npolyhedra\npolyhedral\npolyhedron\npolyhedrons\npolyhedroses\npolyhedrosis\npolyhistor\npolyhistoric\npolyhistors\npolyhydroxy\npolylysine\npolylysines\npolymath\npolymathic\npolymathies\npolymaths\npolymathy\npolymer\npolymerase\npolymerases\npolymeric\npolymerisation\npolymerisations\npolymerise\npolymerised\npolymerises\npolymerising\npolymerism\npolymerisms\npolymerization\npolymerizations\npolymerize\npolymerized\npolymerizes\npolymerizing\npolymers\npolymorph\npolymorphic\npolymorphically\npolymorphism\npolymorphisms\npolymorphonuclear\npolymorphonuclears\npolymorphous\npolymorphously\npolymorphs\npolymyxin\npolymyxins\npolyneuritides\npolyneuritis\npolyneuritises\npolynomial\npolynomials\npolynuclear\npolynucleotide\npolynucleotides\npolynya\npolynyas\npolynyi\npolyolefin\npolyolefins\npolyoma\npolyomas\npolyonymous\npolyp\npolyparies\npolypary\npolypeptide\npolypeptides\npolypeptidic\npolypetalous\npolyphagia\npolyphagias\npolyphagies\npolyphagous\npolyphagy\npolyphase\npolyphasic\npolyphenol\npolyphenolic\npolyphenols\npolyphiloprogenitive\npolyphone\npolyphones\npolyphonic\npolyphonically\npolyphonies\npolyphonous\npolyphonously\npolyphony\npolyphyletic\npolyphyletically\npolypi\npolypide\npolypides\npolyploid\npolyploidies\npolyploids\npolyploidy\npolypnea\npolypneas\npolypod\npolypodies\npolypods\npolypody\npolypoid\npolypore\npolypores\npolypous\npolypropylene\npolypropylenes\npolyps\npolyptych\npolyptychs\npolypus\npolypuses\npolyrhythm\npolyrhythmic\npolyrhythmically\npolyrhythms\npolyribonucleotide\npolyribonucleotides\npolyribosomal\npolyribosome\npolyribosomes\npolys\npolysaccharide\npolysaccharides\npolysemies\npolysemous\npolysemy\npolysome\npolysomes\npolysorbate\npolysorbates\npolystichous\npolystyrene\npolystyrenes\npolysulfide\npolysulfides\npolysyllabic\npolysyllabically\npolysyllable\npolysyllables\npolysynaptic\npolysynaptically\npolysyndeton\npolysyndetons\npolytechnic\npolytechnics\npolytene\npolytenies\npolyteny\npolytheism\npolytheisms\npolytheist\npolytheistic\npolytheistical\npolytheists\npolythene\npolythenes\npolytonal\npolytonalities\npolytonality\npolytonally\npolytype\npolytypes\npolytypic\npolyunsaturated\npolyurethane\npolyurethanes\npolyuria\npolyurias\npolyuric\npolyvalence\npolyvalences\npolyvalent\npolyvinyl\npolywater\npolywaters\npolyzoan\npolyzoans\npolyzoic\npom\npomace\npomaceous\npomaces\npomade\npomaded\npomades\npomading\npomander\npomanders\npomatum\npomatums\npome\npomegranate\npomegranates\npomelo\npomelos\npomes\npomfret\npomfrets\npommee\npommel\npommeled\npommeling\npommelled\npommelling\npommels\npommie\npommies\npommy\npomological\npomologies\npomologist\npomologists\npomology\npomp\npompadour\npompadoured\npompadours\npompano\npompanos\npompom\npompoms\npompon\npompons\npomposities\npomposity\npompous\npompously\npompousness\npompousnesses\npomps\npoms\nponce\nponced\nponces\nponcho\nponchos\nponcing\npond\nponded\nponder\nponderable\npondered\nponderer\nponderers\npondering\nponderosa\nponderosas\nponderous\nponderously\nponderousness\nponderousnesses\nponders\nponding\nponds\npondweed\npondweeds\npone\nponent\npones\npong\nponged\npongee\npongees\npongid\npongids\nponging\npongs\nponiard\nponiarded\nponiarding\nponiards\nponied\nponies\npons\npontes\npontifex\npontiff\npontiffs\npontific\npontifical\npontifically\npontificals\npontificate\npontificated\npontificates\npontificating\npontification\npontifications\npontificator\npontificators\npontifices\npontil\npontils\npontine\nponton\npontons\npontoon\npontoons\npony\nponying\nponytail\nponytailed\nponytails\npooch\npooched\npooches\npooching\npood\npoodle\npoodles\npoods\npoof\npoofs\npooftah\npooftahs\npoofter\npoofters\npoofy\npooh\npoohed\npoohing\npoohs\npooka\npookas\npool\npooled\npoolhall\npoolhalls\npooling\npoolroom\npoolrooms\npools\npoolside\npoolsides\npoon\npoons\npoop\npooped\npooping\npoops\npoor\npoorer\npoorest\npoorhouse\npoorhouses\npoori\npooris\npoorish\npoorly\npoorness\npoornesses\npoortith\npoortiths\npoove\npooves\npop\npopcorn\npopcorns\npope\npopedom\npopedoms\npopeless\npopelike\npoperies\npopery\npopes\npopeyed\npopgun\npopguns\npopinjay\npopinjays\npopish\npopishly\npoplar\npoplars\npoplin\npoplins\npopliteal\npoplitic\npopover\npopovers\npoppa\npoppas\npopped\npopper\npoppers\npoppet\npoppets\npoppied\npoppies\npopping\npopple\npoppled\npopples\npoppling\npoppy\npoppycock\npoppycocks\npoppyhead\npoppyheads\npops\npopsicle\npopsicles\npopsie\npopsies\npopsy\npopulace\npopulaces\npopular\npopularise\npopularised\npopularises\npopularising\npopularities\npopularity\npopularization\npopularizations\npopularize\npopularized\npopularizer\npopularizers\npopularizes\npopularizing\npopularly\npopulate\npopulated\npopulates\npopulating\npopulation\npopulational\npopulations\npopulism\npopulisms\npopulist\npopulistic\npopulists\npopulous\npopulously\npopulousness\npopulousnesses\nporbeagle\nporbeagles\nporcelain\nporcelainize\nporcelainized\nporcelainizes\nporcelainizing\nporcelainlike\nporcelains\nporcelaneous\nporcellaneous\nporch\nporches\nporcine\nporcini\nporcino\nporcupine\nporcupines\npore\npored\npores\nporgies\nporgy\nporing\nporism\nporisms\npork\nporker\nporkers\nporkier\nporkies\nporkiest\nporkpie\nporkpies\nporks\nporkwood\nporkwoods\nporky\nporn\npornier\nporniest\nporno\npornographer\npornographers\npornographic\npornographically\npornographies\npornography\npornos\nporns\nporny\nporose\nporosities\nporosity\nporous\nporously\nporousness\nporousnesses\nporphyria\nporphyrias\nporphyries\nporphyrin\nporphyrins\nporphyritic\nporphyropsin\nporphyropsins\nporphyry\nporpoise\nporpoises\nporrect\nporridge\nporridges\nporridgy\nporringer\nporringers\nport\nportabella\nportabellas\nportabello\nportabellos\nportabilities\nportability\nportable\nportables\nportably\nportage\nportaged\nportages\nportaging\nportal\nportaled\nportals\nportamenti\nportamento\nportamentos\nportance\nportances\nportapack\nportapacks\nportapak\nportapaks\nportative\nportcullis\nportcullises\nported\nportend\nportended\nportending\nportends\nportent\nportentous\nportentously\nportentousness\nportentousnesses\nportents\nporter\nporterage\nporterages\nportered\nporterhouse\nporterhouses\nportering\nporters\nportfolio\nportfolios\nporthole\nportholes\nportico\nporticoes\nporticos\nportiere\nportieres\nporting\nportion\nportioned\nportioning\nportionless\nportions\nportless\nportlier\nportliest\nportliness\nportlinesses\nportly\nportmanteau\nportmanteaus\nportmanteaux\nportobello\nportobellos\nportrait\nportraitist\nportraitists\nportraits\nportraiture\nportraitures\nportray\nportrayal\nportrayals\nportrayed\nportrayer\nportrayers\nportraying\nportrays\nportress\nportresses\nports\nportulaca\nportulacas\nposada\nposadas\npose\nposed\nposer\nposers\nposes\nposeur\nposeurs\nposh\nposher\nposhest\nposhly\nposhness\nposhnesses\nposies\nposing\nposingly\nposit\nposited\npositing\nposition\npositional\npositionally\npositioned\npositioning\npositions\npositive\npositively\npositiveness\npositivenesses\npositiver\npositives\npositivest\npositivism\npositivisms\npositivist\npositivistic\npositivistically\npositivists\npositivities\npositivity\npositron\npositronium\npositroniums\npositrons\nposits\nposologies\nposology\nposse\nposses\npossess\npossessed\npossessedly\npossessedness\npossessednesses\npossesses\npossessing\npossession\npossessional\npossessionless\npossessions\npossessive\npossessively\npossessiveness\npossessivenesses\npossessives\npossessor\npossessors\npossessory\nposset\npossets\npossibilities\npossibility\npossible\npossibler\npossiblest\npossibly\npossum\npossums\npost\npostabortion\npostaccident\npostadolescent\npostadolescents\npostage\npostages\npostal\npostally\npostals\npostamputation\npostanal\npostapocalyptic\npostarrest\npostatomic\npostattack\npostaxial\npostbaccalaureate\npostbag\npostbags\npostbase\npostbellum\npostbiblical\npostbourgeois\npostbox\npostboxes\npostboy\npostboys\npostburn\npostcapitalist\npostcard\npostcardlike\npostcards\npostcava\npostcavae\npostcaval\npostclassic\npostclassical\npostcode\npostcodes\npostcoital\npostcollege\npostcolleges\npostcollegiate\npostcolonial\npostconception\npostconcert\npostconquest\npostconsonantal\npostconvention\npostcopulatory\npostcoronary\npostcoup\npostcranial\npostcranially\npostcrash\npostcrises\npostcrisis\npostdate\npostdated\npostdates\npostdating\npostdeadline\npostdebate\npostdebutante\npostdebutantes\npostdelivery\npostdepositional\npostdepression\npostdevaluation\npostdiluvian\npostdiluvians\npostdive\npostdivestiture\npostdivorce\npostdoc\npostdocs\npostdoctoral\npostdoctorate\npostdrug\nposted\npostediting\nposteditings\nposteen\nposteens\npostelection\npostembryonal\npostembryonic\npostemergence\npostemergency\npostencephalitic\npostepileptic\nposter\nposterior\nposteriorities\nposteriority\nposteriorly\nposteriors\nposterities\nposterity\npostern\nposterns\nposterolateral\nposters\nposteruptive\npostexercise\npostexilic\npostexperience\npostexperimental\npostexposure\npostface\npostfaces\npostfault\npostfeminist\npostfire\npostfix\npostfixed\npostfixes\npostfixing\npostflight\npostform\npostformed\npostforming\npostforms\npostfracture\npostfractures\npostfreeze\npostgame\npostganglionic\npostglacial\npostgrad\npostgrads\npostgraduate\npostgraduates\npostgraduation\npostharvest\nposthaste\nposthastes\npostheat\npostheats\nposthemorrhagic\nposthole\npostholes\npostholiday\npostholocaust\nposthospital\nposthumous\nposthumously\nposthumousness\nposthumousnesses\nposthypnotic\npostiche\npostiches\npostilion\npostilions\npostillion\npostillions\npostimpact\npostimperial\npostin\npostinaugural\npostindependence\npostindustrial\npostinfection\nposting\npostings\npostinjection\npostinoculation\npostins\npostique\npostiques\npostirradiation\npostischemic\npostisolation\npostlanding\npostlapsarian\npostlaunch\npostliberation\npostliterate\npostlude\npostludes\npostman\npostmarital\npostmark\npostmarked\npostmarking\npostmarks\npostmastectomy\npostmaster\npostmasters\npostmastership\npostmasterships\npostmating\npostmedieval\npostmen\npostmenopausal\npostmidnight\npostmillenarian\npostmillenarianism\npostmillenarianisms\npostmillenarians\npostmillennial\npostmillennialism\npostmillennialisms\npostmillennialist\npostmillennialists\npostmistress\npostmistresses\npostmodern\npostmodernism\npostmodernisms\npostmodernist\npostmodernists\npostmortem\npostmortems\npostnatal\npostnatally\npostneonatal\npostnuptial\npostoperative\npostoperatively\npostoral\npostorbital\npostorgasmic\npostpaid\npostpartum\npostpollination\npostponable\npostpone\npostponed\npostponement\npostponements\npostponer\npostponers\npostpones\npostponing\npostposition\npostpositional\npostpositionally\npostpositions\npostpositive\npostpositively\npostprandial\npostpresidential\npostprimary\npostprison\npostproduction\npostproductions\npostpsychoanalytic\npostpuberty\npostpubescent\npostpubescents\npostrace\npostrecession\npostresurrection\npostresurrections\npostretirement\npostrevolutionary\npostriot\npostromantic\nposts\npostscript\npostscripts\npostseason\npostseasons\npostsecondary\npostshow\npoststimulation\npoststimulatory\npoststimulus\npoststrike\npostsurgical\npostsynaptic\npostsynaptically\npostsync\npostsynced\npostsyncing\npostsyncs\nposttax\npostteen\nposttension\nposttensioned\nposttensioning\nposttensions\nposttest\nposttests\nposttranscriptional\nposttransfusion\nposttranslational\nposttraumatic\nposttreatment\nposttrial\npostulancies\npostulancy\npostulant\npostulants\npostulate\npostulated\npostulates\npostulating\npostulation\npostulational\npostulations\npostulator\npostulators\npostural\nposture\npostured\nposturer\nposturers\npostures\nposturing\nposturings\npostvaccinal\npostvaccination\npostvagotomy\npostvasectomy\npostvocalic\npostwar\npostweaning\npostworkshop\nposy\npot\npotabilities\npotability\npotable\npotableness\npotablenesses\npotables\npotage\npotages\npotamic\npotash\npotashes\npotassic\npotassium\npotassiums\npotation\npotations\npotato\npotatoes\npotatory\npotbellied\npotbellies\npotbelly\npotboil\npotboiled\npotboiler\npotboilers\npotboiling\npotboils\npotboy\npotboys\npoteen\npoteens\npotence\npotences\npotencies\npotency\npotent\npotentate\npotentates\npotential\npotentialities\npotentiality\npotentially\npotentials\npotentiate\npotentiated\npotentiates\npotentiating\npotentiation\npotentiations\npotentiator\npotentiators\npotentilla\npotentillas\npotentiometer\npotentiometers\npotentiometric\npotently\npotful\npotfuls\npothead\npotheads\npotheen\npotheens\npother\npotherb\npotherbs\npothered\npothering\npothers\npotholder\npotholders\npothole\npotholed\npotholes\npothook\npothooks\npothouse\npothouses\npothunter\npothunters\npothunting\npothuntings\npotiche\npotiches\npotion\npotions\npotlach\npotlache\npotlaches\npotlatch\npotlatched\npotlatches\npotlatching\npotlike\npotline\npotlines\npotluck\npotlucks\npotman\npotmen\npotometer\npotometers\npotpie\npotpies\npotpourri\npotpourris\npots\npotshard\npotshards\npotsherd\npotsherds\npotshot\npotshots\npotshotting\npotsie\npotsies\npotstone\npotstones\npotsy\npottage\npottages\npotted\npotteen\npotteens\npotter\npottered\npotterer\npotterers\npotteries\npottering\npotteringly\npotters\npottery\npottier\npotties\npottiest\npotting\npottle\npottles\npotto\npottos\npotty\npotzer\npotzers\npouch\npouched\npouches\npouchier\npouchiest\npouching\npouchy\npouf\npoufed\npouff\npouffe\npouffed\npouffes\npouffs\npoufs\npoulard\npoularde\npoulardes\npoulards\npoult\npoulter\npoulterer\npoulterers\npoulters\npoultice\npoulticed\npoultices\npoulticing\npoultries\npoultry\npoultryman\npoultrymen\npoults\npounce\npounced\npouncer\npouncers\npounces\npouncing\npound\npoundage\npoundages\npoundal\npoundals\npounded\npounder\npounders\npounding\npounds\npour\npourable\npourboire\npourboires\npoured\npourer\npourers\npouring\npouringly\npourparler\npourparlers\npourpoint\npourpoints\npours\npoussette\npoussetted\npoussettes\npoussetting\npoussie\npoussies\npout\npouted\npouter\npouters\npoutful\npoutier\npoutiest\npouting\npouts\npouty\npoverties\npoverty\npow\npowder\npowdered\npowderer\npowderers\npowdering\npowderless\npowderlike\npowders\npowdery\npower\npowerboat\npowerboats\npowerbroker\npowerbrokers\npowered\npowerful\npowerfully\npowerhouse\npowerhouses\npowering\npowerless\npowerlessly\npowerlessness\npowerlessnesses\npowers\npows\npowter\npowters\npowwow\npowwowed\npowwowing\npowwows\npox\npoxed\npoxes\npoxing\npoxvirus\npoxviruses\npoyou\npoyous\npozzolan\npozzolana\npozzolanas\npozzolanic\npozzolans\npraam\npraams\npractic\npracticabilities\npracticability\npracticable\npracticableness\npracticablenesses\npracticably\npractical\npracticalities\npracticality\npractically\npracticalness\npracticalnesses\npracticals\npractice\npracticed\npracticer\npracticers\npractices\npracticing\npracticum\npracticums\npractise\npractised\npractises\npractising\npractitioner\npractitioners\npraecipe\npraecipes\npraedial\npraefect\npraefects\npraelect\npraelected\npraelecting\npraelects\npraemunire\npraemunires\npraenomen\npraenomens\npraenomina\npraesidia\npraesidium\npraesidiums\npraetor\npraetorial\npraetorian\npraetorians\npraetors\npraetorship\npraetorships\npragmatic\npragmatical\npragmatically\npragmaticism\npragmaticisms\npragmaticist\npragmaticists\npragmatics\npragmatism\npragmatisms\npragmatist\npragmatistic\npragmatists\nprahu\nprahus\nprairie\nprairies\npraise\npraised\npraiser\npraisers\npraises\npraiseworthily\npraiseworthiness\npraiseworthinesses\npraiseworthy\npraising\npraline\npralines\npralltriller\npralltrillers\npram\nprams\nprance\npranced\nprancer\nprancers\nprances\nprancing\nprandial\nprang\npranged\npranging\nprangs\nprank\npranked\npranking\nprankish\nprankishly\nprankishness\nprankishnesses\npranks\nprankster\npranksters\nprao\npraos\nprase\npraseodymium\npraseodymiums\nprases\nprat\nprate\nprated\nprater\npraters\nprates\npratfall\npratfalls\npratincole\npratincoles\nprating\npratingly\npratique\npratiques\nprats\nprattle\nprattled\nprattler\nprattlers\nprattles\nprattling\nprattlingly\nprau\npraus\nprawn\nprawned\nprawner\nprawners\nprawning\nprawns\npraxeological\npraxeologies\npraxeology\npraxes\npraxis\npraxises\npray\nprayed\nprayer\nprayerful\nprayerfully\nprayerfulness\nprayerfulnesses\nprayers\npraying\nprays\npreach\npreached\npreacher\npreachers\npreaches\npreachier\npreachiest\npreachified\npreachifies\npreachify\npreachifying\npreachily\npreachiness\npreachinesses\npreaching\npreachingly\npreachment\npreachments\npreachy\npreact\npreacted\npreacting\npreacts\npreadapt\npreadaptation\npreadaptations\npreadapted\npreadapting\npreadaptive\npreadapts\npreadmission\npreadmissions\npreadmit\npreadmits\npreadmitted\npreadmitting\npreadolescence\npreadolescences\npreadolescent\npreadolescents\npreadopt\npreadopted\npreadopting\npreadopts\npreadult\npreaged\npreagricultural\npreallot\npreallots\npreallotted\npreallotting\npreamble\npreambles\npreamp\npreamplifier\npreamplifiers\npreamps\npreanal\npreanesthetic\npreanesthetics\npreannounce\npreannounced\npreannounces\npreannouncing\npreapprove\npreapproved\npreapproves\npreapproving\nprearm\nprearmed\nprearming\nprearms\nprearrange\nprearranged\nprearrangement\nprearrangements\nprearranges\nprearranging\npreassembled\npreassign\npreassigned\npreassigning\npreassigns\npreatomic\npreaudit\npreaudits\npreaver\npreaverred\npreaverring\npreavers\npreaxial\nprebake\nprebaked\nprebakes\nprebaking\nprebasal\nprebattle\nprebend\nprebendal\nprebendaries\nprebendary\nprebends\nprebiblical\nprebill\nprebilled\nprebilling\nprebills\nprebind\nprebinding\nprebinds\nprebiologic\nprebiological\nprebiotic\nprebless\npreblessed\npreblesses\npreblessing\npreboil\npreboiled\npreboiling\npreboils\nprebook\nprebooked\nprebooking\nprebooks\npreboom\nprebound\nprebreakfast\nprecalculi\nprecalculus\nprecalculuses\nprecancel\nprecanceled\nprecanceling\nprecancellation\nprecancellations\nprecancelled\nprecancelling\nprecancels\nprecancerous\nprecapitalist\nprecapitalists\nprecarious\nprecariously\nprecariousness\nprecariousnesses\nprecast\nprecasting\nprecasts\nprecatory\nprecaution\nprecautionary\nprecautioned\nprecautioning\nprecautions\nprecava\nprecavae\nprecaval\nprecede\npreceded\nprecedence\nprecedences\nprecedencies\nprecedency\nprecedent\nprecedents\nprecedes\npreceding\nprecensor\nprecensored\nprecensoring\nprecensors\nprecent\nprecented\nprecenting\nprecentor\nprecentorial\nprecentors\nprecentorship\nprecentorships\nprecents\nprecept\npreceptive\npreceptor\npreceptorial\npreceptorials\npreceptories\npreceptors\npreceptorship\npreceptorships\npreceptory\nprecepts\nprecertification\nprecertifications\nprecertified\nprecertifies\nprecertify\nprecertifying\nprecess\nprecessed\nprecesses\nprecessing\nprecession\nprecessional\nprecessions\nprecheck\nprechecked\nprechecking\nprechecks\nprechill\nprechilled\nprechilling\nprechills\nprecieuse\nprecieux\nprecinct\nprecincts\npreciosities\npreciosity\nprecious\npreciouses\npreciously\npreciousness\npreciousnesses\nprecipe\nprecipes\nprecipice\nprecipices\nprecipitable\nprecipitance\nprecipitances\nprecipitancies\nprecipitancy\nprecipitant\nprecipitantly\nprecipitantness\nprecipitantnesses\nprecipitants\nprecipitate\nprecipitated\nprecipitately\nprecipitateness\nprecipitatenesses\nprecipitates\nprecipitating\nprecipitation\nprecipitations\nprecipitative\nprecipitator\nprecipitators\nprecipitin\nprecipitinogen\nprecipitinogens\nprecipitins\nprecipitous\nprecipitously\nprecipitousness\nprecipitousnesses\nprecis\nprecise\nprecised\nprecisely\npreciseness\nprecisenesses\npreciser\nprecises\nprecisest\nprecisian\nprecisians\nprecising\nprecision\nprecisionist\nprecisionists\nprecisions\nprecited\npreclean\nprecleaned\nprecleaning\nprecleans\npreclear\npreclearance\npreclearances\nprecleared\npreclearing\npreclears\npreclinical\npreclude\nprecluded\nprecludes\nprecluding\npreclusion\npreclusions\npreclusive\npreclusively\nprecocial\nprecocious\nprecociously\nprecociousness\nprecociousnesses\nprecocities\nprecocity\nprecode\nprecoded\nprecodes\nprecoding\nprecognition\nprecognitions\nprecognitive\nprecoital\nprecollege\nprecolleges\nprecollegiate\nprecolonial\nprecombustion\nprecombustions\nprecommitment\nprecompute\nprecomputed\nprecomputer\nprecomputers\nprecomputes\nprecomputing\npreconceive\npreconceived\npreconceives\npreconceiving\npreconception\npreconceptions\npreconcert\npreconcerted\npreconcerting\npreconcerts\nprecondition\npreconditioned\npreconditioning\npreconditions\npreconquest\npreconscious\npreconsciouses\npreconsciously\npreconsonantal\npreconstructed\nprecontact\npreconvention\npreconventions\npreconviction\npreconvictions\nprecook\nprecooked\nprecooking\nprecooks\nprecool\nprecooled\nprecooling\nprecools\nprecopulatory\nprecoup\nprecrash\nprecrease\nprecreased\nprecreases\nprecreasing\nprecrisis\nprecritical\nprecure\nprecured\nprecures\nprecuring\nprecursor\nprecursors\nprecursory\nprecut\nprecuts\nprecutting\npredaceous\npredaceousness\npredaceousnesses\npredacious\npredacities\npredacity\npredate\npredated\npredates\npredating\npredation\npredations\npredator\npredators\npredatory\npredawn\npredawns\npredecease\npredeceased\npredeceases\npredeceasing\npredecessor\npredecessors\npredefine\npredefined\npredefines\npredefining\npredeliveries\npredelivery\npredeparture\npredepartures\npredesignate\npredesignated\npredesignates\npredesignating\npredestinarian\npredestinarianism\npredestinarianisms\npredestinarians\npredestinate\npredestinated\npredestinates\npredestinating\npredestination\npredestinations\npredestinator\npredestinators\npredestine\npredestined\npredestines\npredestining\npredetermination\npredeterminations\npredetermine\npredetermined\npredeterminer\npredeterminers\npredetermines\npredetermining\npredevaluation\npredevaluations\npredevelopment\npredevelopments\nprediabetes\nprediabetic\nprediabetics\npredial\npredicable\npredicables\npredicament\npredicaments\npredicate\npredicated\npredicates\npredicating\npredication\npredications\npredicative\npredicatively\npredicatory\npredict\npredictabilities\npredictability\npredictable\npredictably\npredicted\npredicting\nprediction\npredictions\npredictive\npredictively\npredictor\npredictors\npredicts\npredigest\npredigested\npredigesting\npredigestion\npredigestions\npredigests\npredilection\npredilections\npredinner\npredischarge\npredischarged\npredischarges\npredischarging\nprediscoveries\nprediscovery\npredispose\npredisposed\npredisposes\npredisposing\npredisposition\npredispositions\npredive\nprednisolone\nprednisolones\nprednisone\nprednisones\npredoctoral\npredominance\npredominances\npredominancies\npredominancy\npredominant\npredominantly\npredominate\npredominated\npredominately\npredominates\npredominating\npredomination\npredominations\npredrill\npredrilled\npredrilling\npredrills\npredusk\npredusks\npredynastic\npree\npreeclampsia\npreeclampsias\npreeclamptic\npreed\npreedit\npreedited\npreediting\npreedits\npreeing\npreelect\npreelected\npreelecting\npreelection\npreelections\npreelectric\npreelects\npreembargo\npreemergence\npreemergent\npreemie\npreemies\npreeminence\npreeminences\npreeminent\npreeminently\npreemployment\npreemployments\npreempt\npreempted\npreempting\npreemption\npreemptions\npreemptive\npreemptively\npreemptor\npreemptors\npreemptory\npreempts\npreen\npreenact\npreenacted\npreenacting\npreenacts\npreened\npreener\npreeners\npreening\npreenrollment\npreenrollments\npreens\npreerect\npreerected\npreerecting\npreerects\nprees\npreestablish\npreestablished\npreestablishes\npreestablishing\npreethical\npreexilic\npreexist\npreexisted\npreexistence\npreexistences\npreexistent\npreexisting\npreexists\npreexperiment\npreexperiments\nprefab\nprefabbed\nprefabbing\nprefabricate\nprefabricated\nprefabricates\nprefabricating\nprefabrication\nprefabrications\nprefabs\npreface\nprefaced\nprefacer\nprefacers\nprefaces\nprefacing\nprefade\nprefaded\nprefades\nprefading\nprefascist\nprefascists\nprefatory\nprefect\nprefects\nprefectural\nprefecture\nprefectures\nprefer\npreferabilities\npreferability\npreferable\npreferably\npreference\npreferences\npreferential\npreferentially\npreferment\npreferments\npreferred\npreferrer\npreferrers\npreferring\nprefers\nprefeudal\nprefight\nprefiguration\nprefigurations\nprefigurative\nprefiguratively\nprefigurativeness\nprefigurativenesses\nprefigure\nprefigured\nprefigurement\nprefigurements\nprefigures\nprefiguring\nprefile\nprefiled\nprefiles\nprefiling\nprefilled\nprefinance\nprefinanced\nprefinances\nprefinancing\nprefire\nprefired\nprefires\nprefiring\nprefix\nprefixal\nprefixed\nprefixes\nprefixing\npreflame\npreflight\nprefocus\nprefocused\nprefocuses\nprefocusing\nprefocussed\nprefocusses\nprefocussing\npreform\npreformat\npreformation\npreformationist\npreformationists\npreformations\npreformats\npreformatted\npreformatting\npreformed\npreforming\npreforms\npreformulate\npreformulated\npreformulates\npreformulating\nprefrank\nprefranked\nprefranking\nprefranks\nprefreeze\nprefreezes\nprefreezing\nprefreshman\nprefreshmen\nprefrontal\nprefrontals\nprefroze\nprefrozen\npregame\npreganglionic\npregenital\npreggers\npregnabilities\npregnability\npregnable\npregnancies\npregnancy\npregnant\npregnantly\npregnenolone\npregnenolones\npreharvest\npreharvests\npreheadache\nprehearing\nprehearings\npreheat\npreheated\npreheater\npreheaters\npreheating\npreheats\nprehensile\nprehensilities\nprehensility\nprehension\nprehensions\nprehiring\nprehistorian\nprehistorians\nprehistoric\nprehistorical\nprehistorically\nprehistories\nprehistory\npreholiday\nprehominid\nprehominids\nprehuman\nprehumans\npreignition\npreignitions\npreimplantation\npreinaugural\npreincorporation\npreincorporations\npreinduction\npreinductions\npreindustrial\npreinterview\npreinterviewed\npreinterviewing\npreinterviews\npreinvasion\nprejudge\nprejudged\nprejudger\nprejudgers\nprejudges\nprejudging\nprejudgment\nprejudgments\nprejudice\nprejudiced\nprejudices\nprejudicial\nprejudicially\nprejudicialness\nprejudicialnesses\nprejudicing\nprekindergarten\nprekindergartens\nprelacies\nprelacy\nprelapsarian\nprelate\nprelates\nprelatic\nprelature\nprelatures\nprelaunch\nprelaw\nprelect\nprelected\nprelecting\nprelection\nprelections\nprelects\nprelegal\nprelibation\nprelibations\nprelife\nprelim\npreliminaries\npreliminarily\npreliminary\nprelimit\nprelimited\nprelimiting\nprelimits\nprelims\npreliterary\npreliterate\npreliterates\nprelives\nprelogical\nprelude\npreluded\npreluder\npreluders\npreludes\npreluding\nprelunch\npreluncheon\nprelusion\nprelusions\nprelusive\nprelusively\npremade\npremalignant\npreman\npremanufacture\npremanufactured\npremanufactures\npremanufacturing\npremarital\npremaritally\npremarket\npremarketing\npremarketings\npremarriage\npremarriages\npremature\nprematurely\nprematureness\nprematurenesses\nprematures\nprematurities\nprematurity\npremaxilla\npremaxillae\npremaxillaries\npremaxillary\npremeal\npremeasure\npremeasured\npremeasures\npremeasuring\npremed\npremedic\npremedical\npremedics\npremedieval\npremeditate\npremeditated\npremeditatedly\npremeditates\npremeditating\npremeditation\npremeditations\npremeditative\npremeditator\npremeditators\npremeds\npremeet\npremeiotic\npremen\npremenopausal\npremenstrual\npremenstrually\npremerger\npremie\npremier\npremiere\npremiered\npremieres\npremiering\npremiers\npremiership\npremierships\npremies\npremigration\npremillenarian\npremillenarianism\npremillenarianisms\npremillenarians\npremillennial\npremillennialism\npremillennialisms\npremillennialist\npremillennialists\npremillennially\npremise\npremised\npremises\npremising\npremiss\npremisses\npremium\npremiums\npremix\npremixed\npremixes\npremixing\npremixt\npremodern\npremodification\npremodifications\npremodified\npremodifies\npremodify\npremodifying\npremoisten\npremoistened\npremoistening\npremoistens\npremolar\npremolars\npremold\npremolded\npremolding\npremolds\npremolt\npremonish\npremonished\npremonishes\npremonishing\npremonition\npremonitions\npremonitorily\npremonitory\npremoral\npremorse\npremune\npremunition\npremunitions\npremycotic\nprename\nprenames\nprenatal\nprenatally\nprenomen\nprenomens\nprenomina\nprenominate\nprenominated\nprenominates\nprenominating\nprenomination\nprenominations\nprenoon\nprenotification\nprenotifications\nprenotified\nprenotifies\nprenotify\nprenotifying\nprenotion\nprenotions\nprentice\nprenticed\nprentices\nprenticing\nprenumber\nprenumbered\nprenumbering\nprenumbers\nprenuptial\npreoccupancies\npreoccupancy\npreoccupation\npreoccupations\npreoccupied\npreoccupies\npreoccupy\npreoccupying\npreopening\npreoperational\npreoperative\npreoperatively\npreordain\npreordained\npreordaining\npreordainment\npreordainments\npreordains\npreorder\npreordered\npreordering\npreorders\npreordination\npreordinations\npreovulatory\nprep\nprepack\nprepackage\nprepackaged\nprepackages\nprepackaging\nprepacked\nprepacking\nprepacks\nprepaid\npreparation\npreparations\npreparative\npreparatively\npreparatives\npreparator\npreparatorily\npreparators\npreparatory\nprepare\nprepared\npreparedly\npreparedness\npreparednesses\npreparer\npreparers\nprepares\npreparing\nprepaste\nprepasted\nprepastes\nprepasting\nprepay\nprepaying\nprepayment\nprepayments\nprepays\nprepense\nprepensely\npreperformance\npreperformances\nprepill\npreplace\npreplaced\npreplaces\npreplacing\npreplan\npreplanned\npreplanning\npreplans\npreplant\npreplanting\npreponderance\npreponderances\npreponderancies\npreponderancy\npreponderant\npreponderantly\npreponderate\npreponderated\npreponderately\npreponderates\npreponderating\npreponderation\npreponderations\npreportion\npreportioned\npreportioning\npreportions\npreposition\nprepositional\nprepositionally\nprepositions\nprepositive\nprepositively\nprepossess\nprepossessed\nprepossesses\nprepossessing\nprepossession\nprepossessions\npreposterous\npreposterously\npreposterousness\npreposterousnesses\nprepotencies\nprepotency\nprepotent\nprepotently\nprepped\npreppie\npreppier\npreppies\npreppiest\npreppily\npreppiness\npreppinesses\nprepping\npreppy\npreprandial\nprepreg\nprepregs\npreprepared\nprepresidential\npreprice\nprepriced\npreprices\nprepricing\npreprimary\npreprint\npreprinted\npreprinting\npreprints\npreprocess\npreprocessed\npreprocesses\npreprocessing\npreprocessor\npreprocessors\npreproduction\npreproductions\npreprofessional\npreprogram\npreprogramed\npreprograming\npreprogrammed\npreprogramming\npreprograms\npreps\nprepsychedelic\nprepuberal\nprepubertal\nprepuberties\nprepuberty\nprepubescence\nprepubescences\nprepubescent\nprepubescents\nprepublication\nprepublications\nprepuce\nprepuces\nprepunch\nprepunched\nprepunches\nprepunching\nprepupal\nprepurchase\nprepurchased\nprepurchases\nprepurchasing\npreputial\nprequalification\nprequalifications\nprequalified\nprequalifies\nprequalify\nprequalifying\nprequel\nprequels\nprerace\nprerecession\nprerecord\nprerecorded\nprerecording\nprerecords\npreregister\npreregistered\npreregistering\npreregisters\npreregistration\npreregistrations\nprerehearsal\nprerelease\nprereleases\nprerenal\nprerequire\nprerequired\nprerequires\nprerequiring\nprerequisite\nprerequisites\npreretirement\npreretirements\nprereturn\nprereview\nprerevisionist\nprerevisionists\nprerevolution\nprerevolutionary\nprerinse\nprerinses\npreriot\nprerock\nprerogative\nprerogatived\nprerogatives\npreromantic\npresa\npresage\npresaged\npresageful\npresager\npresagers\npresages\npresaging\npresale\npresanctified\npresbyope\npresbyopes\npresbyopia\npresbyopias\npresbyopic\npresbyopics\npresbyter\npresbyterate\npresbyterates\npresbyterial\npresbyterially\npresbyterials\npresbyterian\npresbyteries\npresbyters\npresbytery\npreschedule\nprescheduled\npreschedules\nprescheduling\npreschool\npreschooler\npreschoolers\npreschools\nprescience\npresciences\nprescient\nprescientific\npresciently\nprescind\nprescinded\nprescinding\nprescinds\nprescore\nprescored\nprescores\nprescoring\nprescreen\nprescreened\nprescreening\nprescreenings\nprescreens\nprescribe\nprescribed\nprescriber\nprescribers\nprescribes\nprescribing\nprescript\nprescription\nprescriptions\nprescriptive\nprescriptively\nprescripts\nprese\npreseason\npreseasons\npreselect\npreselected\npreselecting\npreselection\npreselections\npreselects\npresell\npreselling\npresells\npresence\npresences\npresent\npresentabilities\npresentability\npresentable\npresentableness\npresentablenesses\npresentably\npresentation\npresentational\npresentations\npresentative\npresented\npresentee\npresentees\npresentence\npresentenced\npresentences\npresentencing\npresentencings\npresenter\npresenters\npresentient\npresentiment\npresentimental\npresentiments\npresenting\npresentism\npresentisms\npresentist\npresently\npresentment\npresentments\npresentness\npresentnesses\npresents\npreservabilities\npreservability\npreservable\npreservation\npreservationist\npreservationists\npreservations\npreservative\npreservatives\npreserve\npreserved\npreserver\npreservers\npreserves\npreservice\npreserving\npreset\npresets\npresetting\npresettlement\npresettlements\npreshape\npreshaped\npreshapes\npreshaping\npreshow\npreshowed\npreshowing\npreshown\npreshows\npreshrank\npreshrink\npreshrinking\npreshrinks\npreshrunk\npreshrunken\npreside\npresided\npresidencies\npresidency\npresident\npresidential\npresidentially\npresidents\npresidentship\npresidentships\npresider\npresiders\npresides\npresidia\npresidial\npresidiary\npresiding\npresidio\npresidios\npresidium\npresidiums\npresift\npresifted\npresifting\npresifts\npresignified\npresignifies\npresignify\npresignifying\npreslaughter\npresleep\npreslice\npresliced\npreslices\npreslicing\npresoak\npresoaked\npresoaking\npresoaks\npresold\npresong\npresort\npresorted\npresorting\npresorts\nprespecified\nprespecifies\nprespecify\nprespecifying\npresplit\npress\npressboard\npressboards\npressed\npresser\npressers\npresses\npressing\npressingly\npressings\npressman\npressmark\npressmarks\npressmen\npressor\npressors\npressroom\npressrooms\npressrun\npressruns\npressure\npressured\npressureless\npressures\npressuring\npressurise\npressurised\npressurises\npressurising\npressurization\npressurizations\npressurize\npressurized\npressurizer\npressurizers\npressurizes\npressurizing\npresswork\npressworks\nprest\nprestamp\nprestamped\nprestamping\nprestamps\nprester\npresterilize\npresterilized\npresterilizes\npresterilizing\npresters\nprestidigitation\nprestidigitations\nprestidigitator\nprestidigitators\nprestige\nprestigeful\nprestiges\nprestigious\nprestigiously\nprestigiousness\nprestigiousnesses\nprestissimo\npresto\nprestorage\nprestorages\nprestos\nprestress\nprestressed\nprestresses\nprestressing\nprestrike\nprestructure\nprestructured\nprestructures\nprestructuring\nprests\npresumable\npresumably\npresume\npresumed\npresumedly\npresumer\npresumers\npresumes\npresuming\npresumingly\npresummit\npresumption\npresumptions\npresumptive\npresumptively\npresumptuous\npresumptuously\npresumptuousness\npresumptuousnesses\npresuppose\npresupposed\npresupposes\npresupposing\npresupposition\npresuppositional\npresuppositions\npresurgery\npresweeten\npresweetened\npresweetening\npresweetens\npresymptomatic\npresynaptic\npresynaptically\npretape\npretaped\npretapes\npretaping\npretaste\npretasted\npretastes\npretasting\npretax\npretechnological\npreteen\npreteens\npretelevision\npretence\npretences\npretend\npretended\npretendedly\npretender\npretenders\npretending\npretends\npretense\npretenses\npretension\npretensioned\npretensioning\npretensionless\npretensions\npretentious\npretentiously\npretentiousness\npretentiousnesses\npreterit\npreterite\npreterites\npreterits\npreterm\npreterminal\npretermination\npreterminations\npretermission\npretermissions\npretermit\npretermits\npretermitted\npretermitting\npreternatural\npreternaturally\npreternaturalness\npreternaturalnesses\npretest\npretested\npretesting\npretests\npretext\npretexted\npretexting\npretexts\npretheater\npretor\npretorian\npretorians\npretors\npretournament\npretournaments\npretrain\npretrained\npretraining\npretrains\npretravel\npretreat\npretreated\npretreating\npretreatment\npretreatments\npretreats\npretrial\npretrials\npretrim\npretrimmed\npretrimming\npretrims\nprettied\nprettier\npretties\nprettiest\nprettification\nprettifications\nprettified\nprettifier\nprettifiers\nprettifies\nprettify\nprettifying\nprettily\nprettiness\nprettinesses\npretty\nprettying\nprettyish\npretype\npretyped\npretypes\npretyping\npretzel\npretzels\npreunification\npreunion\npreunions\npreunite\npreunited\npreunites\npreuniting\npreuniversity\nprevail\nprevailed\nprevailing\nprevails\nprevalence\nprevalences\nprevalent\nprevalently\nprevalents\nprevaricate\nprevaricated\nprevaricates\nprevaricating\nprevarication\nprevarications\nprevaricator\nprevaricators\nprevenient\npreveniently\nprevent\npreventabilities\npreventability\npreventable\npreventative\npreventatives\nprevented\npreventer\npreventers\npreventible\npreventing\nprevention\npreventions\npreventive\npreventively\npreventiveness\npreventivenesses\npreventives\nprevents\npreverbal\npreviable\npreview\npreviewed\npreviewer\npreviewers\npreviewing\npreviews\nprevious\npreviously\npreviousness\npreviousnesses\nprevise\nprevised\nprevises\nprevising\nprevision\nprevisional\nprevisionary\nprevisioned\nprevisioning\nprevisions\nprevisor\nprevisors\nprevocalic\nprevocational\nprevue\nprevued\nprevues\nprevuing\nprewar\nprewarm\nprewarmed\nprewarming\nprewarms\nprewarn\nprewarned\nprewarning\nprewarns\nprewash\nprewashed\nprewashes\nprewashing\npreweaning\nprework\nprewrap\nprewrapped\nprewrapping\nprewraps\nprewriting\nprewritings\nprex\nprexes\nprexies\nprexy\nprey\npreyed\npreyer\npreyers\npreying\npreys\nprez\nprezes\npriapean\npriapi\npriapic\npriapism\npriapisms\npriapus\npriapuses\nprice\npriced\npriceless\npricelessly\npricer\npricers\nprices\npricey\npricier\npriciest\npricing\nprick\npricked\npricker\nprickers\npricket\nprickets\nprickier\nprickiest\npricking\nprickings\nprickle\nprickled\nprickles\npricklier\nprickliest\nprickliness\npricklinesses\nprickling\nprickly\npricks\npricky\npricy\npride\nprided\nprideful\npridefully\npridefulness\npridefulnesses\nprides\npriding\npried\npriedieu\npriedieus\npriedieux\nprier\npriers\npries\npriest\npriested\npriestess\npriestesses\npriesthood\npriesthoods\npriesting\npriestlier\npriestliest\npriestliness\npriestlinesses\npriestly\npriests\nprig\nprigged\npriggeries\npriggery\nprigging\npriggish\npriggishly\npriggishness\npriggishnesses\npriggism\npriggisms\nprigs\nprill\nprilled\nprilling\nprills\nprim\nprima\nprimacies\nprimacy\nprimage\nprimages\nprimal\nprimalities\nprimality\nprimaries\nprimarily\nprimary\nprimas\nprimatal\nprimatals\nprimate\nprimates\nprimateship\nprimateships\nprimatial\nprimatological\nprimatologies\nprimatologist\nprimatologists\nprimatology\nprimavera\nprime\nprimed\nprimely\nprimeness\nprimenesses\nprimer\nprimero\nprimeros\nprimers\nprimes\nprimeval\nprimevally\nprimi\nprimine\nprimines\npriming\nprimings\nprimipara\nprimiparae\nprimiparas\nprimiparous\nprimitive\nprimitively\nprimitiveness\nprimitivenesses\nprimitives\nprimitivism\nprimitivisms\nprimitivist\nprimitivistic\nprimitivists\nprimitivities\nprimitivity\nprimly\nprimmed\nprimmer\nprimmest\nprimming\nprimness\nprimnesses\nprimo\nprimogenitor\nprimogenitors\nprimogeniture\nprimogenitures\nprimordia\nprimordial\nprimordially\nprimordium\nprimos\nprimp\nprimped\nprimping\nprimps\nprimrose\nprimroses\nprims\nprimsie\nprimula\nprimulas\nprimus\nprimuses\nprince\nprincedom\nprincedoms\nprincelet\nprincelets\nprincelier\nprinceliest\nprinceliness\nprincelinesses\nprinceling\nprincelings\nprincely\nprinces\nprinceship\nprinceships\nprincess\nprincesse\nprincesses\nprincipal\nprincipalities\nprincipality\nprincipally\nprincipals\nprincipalship\nprincipalships\nprincipe\nprincipi\nprincipia\nprincipium\nprinciple\nprincipled\nprinciples\nprincock\nprincocks\nprincox\nprincoxes\nprink\nprinked\nprinker\nprinkers\nprinking\nprinks\nprint\nprintabilities\nprintability\nprintable\nprinted\nprinter\nprinteries\nprinters\nprintery\nprinthead\nprintheads\nprinting\nprintings\nprintless\nprintmaker\nprintmakers\nprintmaking\nprintmakings\nprintout\nprintouts\nprints\nprion\nprions\nprior\npriorate\npriorates\nprioress\nprioresses\npriories\npriorities\nprioritization\nprioritizations\nprioritize\nprioritized\nprioritizes\nprioritizing\npriority\npriorly\npriors\npriorship\npriorships\npriory\nprise\nprised\nprisere\npriseres\nprises\nprising\nprism\nprismatic\nprismatically\nprismatoid\nprismatoids\nprismoid\nprismoidal\nprismoids\nprisms\nprison\nprisoned\nprisoner\nprisoners\nprisoning\nprisons\npriss\nprissed\nprisses\nprissier\nprissies\nprissiest\nprissily\nprissiness\nprissinesses\nprissing\nprissy\npristane\npristanes\npristine\npristinely\nprithee\nprivacies\nprivacy\nprivatdocent\nprivatdocents\nprivatdozent\nprivatdozents\nprivate\nprivateer\nprivateered\nprivateering\nprivateers\nprivately\nprivateness\nprivatenesses\nprivater\nprivates\nprivatest\nprivation\nprivations\nprivatise\nprivatised\nprivatises\nprivatising\nprivatism\nprivatisms\nprivative\nprivatively\nprivatives\nprivatization\nprivatizations\nprivatize\nprivatized\nprivatizes\nprivatizing\nprivet\nprivets\nprivier\nprivies\npriviest\nprivilege\nprivileged\nprivileges\nprivileging\nprivily\nprivities\nprivity\nprivy\nprize\nprized\nprizefight\nprizefighter\nprizefighters\nprizefighting\nprizefightings\nprizefights\nprizer\nprizers\nprizes\nprizewinner\nprizewinners\nprizewinning\nprizing\npro\nproa\nproabortion\nproactive\nproas\nprobabilism\nprobabilisms\nprobabilist\nprobabilistic\nprobabilistically\nprobabilists\nprobabilities\nprobability\nprobable\nprobables\nprobably\nproband\nprobands\nprobang\nprobangs\nprobate\nprobated\nprobates\nprobating\nprobation\nprobational\nprobationally\nprobationary\nprobationer\nprobationers\nprobations\nprobative\nprobatory\nprobe\nprobed\nprobenecid\nprobenecids\nprober\nprobers\nprobes\nprobing\nprobit\nprobities\nprobits\nprobity\nproblem\nproblematic\nproblematical\nproblematically\nproblematics\nproblems\nproboscidean\nproboscideans\nproboscides\nproboscidian\nproboscidians\nproboscis\nproboscises\nprocaine\nprocaines\nprocambia\nprocambial\nprocambium\nprocambiums\nprocarbazine\nprocarbazines\nprocarp\nprocarps\nprocaryote\nprocaryotes\nprocathedral\nprocathedrals\nprocedural\nprocedurally\nprocedurals\nprocedure\nprocedures\nproceed\nproceeded\nproceeding\nproceedings\nproceeds\nprocephalic\nprocercoid\nprocercoids\nprocess\nprocessabilities\nprocessability\nprocessable\nprocessed\nprocesses\nprocessibilities\nprocessibility\nprocessible\nprocessing\nprocession\nprocessional\nprocessionally\nprocessionals\nprocessioned\nprocessioning\nprocessions\nprocessor\nprocessors\nprochain\nprochein\nproclaim\nproclaimed\nproclaimer\nproclaimers\nproclaiming\nproclaims\nproclamation\nproclamations\nproclitic\nproclitics\nproclivities\nproclivity\nproconsul\nproconsular\nproconsulate\nproconsulates\nproconsuls\nproconsulship\nproconsulships\nprocrastinate\nprocrastinated\nprocrastinates\nprocrastinating\nprocrastination\nprocrastinations\nprocrastinator\nprocrastinators\nprocreant\nprocreate\nprocreated\nprocreates\nprocreating\nprocreation\nprocreations\nprocreative\nprocreator\nprocreators\nprocrustean\nprocryptic\nproctodaea\nproctodaeum\nproctodaeums\nproctologic\nproctological\nproctologies\nproctologist\nproctologists\nproctology\nproctor\nproctored\nproctorial\nproctoring\nproctors\nproctorship\nproctorships\nprocumbent\nprocurable\nprocural\nprocurals\nprocuration\nprocurations\nprocurator\nprocuratorial\nprocurators\nprocure\nprocured\nprocurement\nprocurements\nprocurer\nprocurers\nprocures\nprocuring\nprod\nprodded\nprodder\nprodders\nprodding\nprodigal\nprodigalities\nprodigality\nprodigally\nprodigals\nprodigies\nprodigious\nprodigiously\nprodigiousness\nprodigiousnesses\nprodigy\nprodromal\nprodromata\nprodrome\nprodromes\nprods\nproduce\nproduced\nproducer\nproducers\nproduces\nproducible\nproducing\nproduct\nproduction\nproductional\nproductions\nproductive\nproductively\nproductiveness\nproductivenesses\nproductivities\nproductivity\nproducts\nproem\nproemial\nproems\nproenzyme\nproenzymes\nproestrus\nproestruses\nproette\nproettes\nprof\nprofanation\nprofanations\nprofanatory\nprofane\nprofaned\nprofanely\nprofaneness\nprofanenesses\nprofaner\nprofaners\nprofanes\nprofaning\nprofanities\nprofanity\nprofess\nprofessed\nprofessedly\nprofesses\nprofessing\nprofession\nprofessional\nprofessionalism\nprofessionalisms\nprofessionalization\nprofessionalizations\nprofessionalize\nprofessionalized\nprofessionalizes\nprofessionalizing\nprofessionally\nprofessionals\nprofessions\nprofessor\nprofessorate\nprofessorates\nprofessorial\nprofessorially\nprofessoriat\nprofessoriate\nprofessoriates\nprofessoriats\nprofessors\nprofessorship\nprofessorships\nproffer\nproffered\nproffering\nproffers\nproficiencies\nproficiency\nproficient\nproficiently\nproficients\nprofile\nprofiled\nprofiler\nprofilers\nprofiles\nprofiling\nprofit\nprofitabilities\nprofitability\nprofitable\nprofitableness\nprofitablenesses\nprofitably\nprofited\nprofiteer\nprofiteered\nprofiteering\nprofiteers\nprofiter\nprofiterole\nprofiteroles\nprofiters\nprofiting\nprofitless\nprofits\nprofitwise\nprofligacies\nprofligacy\nprofligate\nprofligately\nprofligates\nprofluent\nprofound\nprofounder\nprofoundest\nprofoundly\nprofoundness\nprofoundnesses\nprofounds\nprofs\nprofundities\nprofundity\nprofuse\nprofusely\nprofuseness\nprofusenesses\nprofusion\nprofusions\nprog\nprogenies\nprogenitor\nprogenitors\nprogeny\nprogeria\nprogerias\nprogestational\nprogesterone\nprogesterones\nprogestin\nprogestins\nprogestogen\nprogestogenic\nprogestogens\nprogged\nprogger\nproggers\nprogging\nproglottid\nproglottides\nproglottids\nproglottis\nprognathism\nprognathisms\nprognathous\nprognose\nprognosed\nprognoses\nprognosing\nprognosis\nprognostic\nprognosticate\nprognosticated\nprognosticates\nprognosticating\nprognostication\nprognostications\nprognosticative\nprognosticator\nprognosticators\nprognostics\nprograde\nprogram\nprogramed\nprogramer\nprogramers\nprograming\nprogramings\nprogrammabilities\nprogrammability\nprogrammable\nprogrammables\nprogrammatic\nprogrammatically\nprogramme\nprogrammed\nprogrammer\nprogrammers\nprogrammes\nprogramming\nprogrammings\nprograms\nprogress\nprogressed\nprogresses\nprogressing\nprogression\nprogressional\nprogressions\nprogressive\nprogressively\nprogressiveness\nprogressivenesses\nprogressives\nprogressivism\nprogressivisms\nprogressivist\nprogressivistic\nprogressivists\nprogressivities\nprogressivity\nprogs\nprohibit\nprohibited\nprohibiting\nprohibition\nprohibitionist\nprohibitionists\nprohibitions\nprohibitive\nprohibitively\nprohibitiveness\nprohibitivenesses\nprohibitory\nprohibits\nproinsulin\nproinsulins\nproject\nprojectable\nprojected\nprojectile\nprojectiles\nprojecting\nprojection\nprojectional\nprojectionist\nprojectionists\nprojections\nprojective\nprojectively\nprojector\nprojectors\nprojects\nprojet\nprojets\nprokaryote\nprokaryotes\nprokaryotic\nprolabor\nprolactin\nprolactins\nprolamin\nprolamine\nprolamines\nprolamins\nprolan\nprolans\nprolapse\nprolapsed\nprolapses\nprolapsing\nprolate\nprole\nproleg\nprolegomena\nprolegomenon\nprolegomenous\nprolegs\nprolepses\nprolepsis\nproleptic\nproleptically\nproles\nproletarian\nproletarianise\nproletarianised\nproletarianises\nproletarianising\nproletarianization\nproletarianizations\nproletarianize\nproletarianized\nproletarianizes\nproletarianizing\nproletarians\nproletariat\nproletariats\nproliferate\nproliferated\nproliferates\nproliferating\nproliferation\nproliferations\nproliferative\nprolific\nprolificacies\nprolificacy\nprolifically\nprolificities\nprolificity\nprolificness\nprolificnesses\nproline\nprolines\nprolix\nprolixities\nprolixity\nprolixly\nprolocutor\nprolocutors\nprolog\nprologed\nprologing\nprologize\nprologized\nprologizes\nprologizing\nprologs\nprologue\nprologued\nprologues\nprologuing\nprologuize\nprologuized\nprologuizes\nprologuizing\nprolong\nprolongation\nprolongations\nprolonge\nprolonged\nprolonger\nprolongers\nprolonges\nprolonging\nprolongs\nprolusion\nprolusions\nprolusory\nprom\npromenade\npromenaded\npromenader\npromenaders\npromenades\npromenading\npromethium\npromethiums\npromine\nprominence\nprominences\nprominent\nprominently\npromines\npromiscuities\npromiscuity\npromiscuous\npromiscuously\npromiscuousness\npromiscuousnesses\npromise\npromised\npromisee\npromisees\npromiser\npromisers\npromises\npromising\npromisingly\npromisor\npromisors\npromissory\npromo\npromontories\npromontory\npromos\npromotabilities\npromotability\npromotable\npromote\npromoted\npromoter\npromoters\npromotes\npromoting\npromotion\npromotional\npromotions\npromotive\npromotiveness\npromotivenesses\nprompt\npromptbook\npromptbooks\nprompted\nprompter\nprompters\npromptest\nprompting\npromptitude\npromptitudes\npromptly\npromptness\npromptnesses\nprompts\nproms\npromulgate\npromulgated\npromulgates\npromulgating\npromulgation\npromulgations\npromulgator\npromulgators\npromulge\npromulged\npromulges\npromulging\npronate\npronated\npronates\npronating\npronation\npronations\npronator\npronatores\npronators\nprone\npronely\nproneness\npronenesses\npronephra\npronephric\npronephroi\npronephros\nprong\npronged\npronghorn\npronghorns\npronging\nprongs\npronominal\npronominally\npronota\npronotum\npronoun\npronounce\npronounceabilities\npronounceability\npronounceable\npronounced\npronouncedly\npronouncement\npronouncements\npronouncer\npronouncers\npronounces\npronouncing\npronouns\npronto\npronuclear\npronuclei\npronucleus\npronucleuses\npronunciamento\npronunciamentoes\npronunciamentos\npronunciation\npronunciational\npronunciations\nproof\nproofed\nproofer\nproofers\nproofing\nproofread\nproofreader\nproofreaders\nproofreading\nproofreads\nproofroom\nproofrooms\nproofs\nprop\npropaedeutic\npropaedeutics\npropagable\npropaganda\npropagandas\npropagandist\npropagandistic\npropagandistically\npropagandists\npropagandize\npropagandized\npropagandizer\npropagandizers\npropagandizes\npropagandizing\npropagate\npropagated\npropagates\npropagating\npropagation\npropagations\npropagative\npropagator\npropagators\npropagule\npropagules\npropane\npropanes\npropel\npropellant\npropellants\npropelled\npropellent\npropellents\npropeller\npropellers\npropelling\npropellor\npropellors\npropels\npropend\npropended\npropending\npropends\npropene\npropenes\npropenol\npropenols\npropense\npropensities\npropensity\npropenyl\nproper\nproperdin\nproperdins\nproperer\nproperest\nproperly\nproperness\npropernesses\npropers\npropertied\nproperties\nproperty\npropertyless\npropertylessness\npropertylessnesses\nprophage\nprophages\nprophase\nprophases\nprophasic\nprophecies\nprophecy\nprophesied\nprophesier\nprophesiers\nprophesies\nprophesy\nprophesying\nprophet\nprophetess\nprophetesses\nprophethood\nprophethoods\nprophetic\nprophetical\nprophetically\nprophets\nprophylactic\nprophylactically\nprophylactics\nprophylaxes\nprophylaxis\npropine\npropined\npropines\npropining\npropinquities\npropinquity\npropionate\npropionates\npropitiate\npropitiated\npropitiates\npropitiating\npropitiation\npropitiations\npropitiator\npropitiators\npropitiatory\npropitious\npropitiously\npropitiousness\npropitiousnesses\npropjet\npropjets\nproplastid\nproplastids\npropman\npropmen\npropolis\npropolises\npropone\nproponed\nproponent\nproponents\npropones\nproponing\nproportion\nproportionable\nproportionably\nproportional\nproportionalities\nproportionality\nproportionally\nproportionals\nproportionate\nproportionated\nproportionately\nproportionates\nproportionating\nproportioned\nproportioning\nproportions\nproposal\nproposals\npropose\nproposed\nproposer\nproposers\nproposes\nproposing\npropositi\nproposition\npropositional\npropositioned\npropositioning\npropositions\npropositus\npropound\npropounded\npropounder\npropounders\npropounding\npropounds\npropoxyphene\npropoxyphenes\npropped\npropping\npropraetor\npropraetors\npropranolol\npropranolols\npropretor\npropretors\nproprietaries\nproprietary\nproprieties\nproprietor\nproprietorial\nproprietors\nproprietorship\nproprietorships\nproprietress\nproprietresses\npropriety\nproprioception\nproprioceptions\nproprioceptive\nproprioceptor\nproprioceptors\nprops\nproptoses\nproptosis\npropulsion\npropulsions\npropulsive\npropyl\npropyla\npropylaea\npropylaeum\npropylene\npropylenes\npropylic\npropylon\npropyls\nprorate\nprorated\nprorates\nprorating\nproration\nprorations\nprorogate\nprorogated\nprorogates\nprorogating\nprorogation\nprorogations\nprorogue\nprorogued\nprorogues\nproroguing\npros\nprosaic\nprosaically\nprosaism\nprosaisms\nprosaist\nprosaists\nprosateur\nprosateurs\nprosauropod\nprosauropods\nproscenia\nproscenium\nprosceniums\nprosciutti\nprosciutto\nprosciuttos\nproscribe\nproscribed\nproscriber\nproscribers\nproscribes\nproscribing\nproscription\nproscriptions\nproscriptive\nproscriptively\nprose\nprosect\nprosected\nprosecting\nprosector\nprosectors\nprosects\nprosecutable\nprosecute\nprosecuted\nprosecutes\nprosecuting\nprosecution\nprosecutions\nprosecutor\nprosecutorial\nprosecutors\nprosed\nproselyte\nproselyted\nproselytes\nproselyting\nproselytise\nproselytised\nproselytises\nproselytising\nproselytism\nproselytisms\nproselytization\nproselytizations\nproselytize\nproselytized\nproselytizer\nproselytizers\nproselytizes\nproselytizing\nproseminar\nproseminars\nprosencephala\nprosencephalic\nprosencephalon\nproser\nprosers\nproses\nprosier\nprosiest\nprosily\nprosimian\nprosimians\nprosiness\nprosinesses\nprosing\nprosit\nproso\nprosobranch\nprosobranchs\nprosodic\nprosodical\nprosodically\nprosodies\nprosodist\nprosodists\nprosody\nprosoma\nprosomal\nprosomas\nprosomata\nprosopographical\nprosopographies\nprosopography\nprosopopoeia\nprosopopoeias\nprosos\nprospect\nprospected\nprospecting\nprospective\nprospectively\nprospector\nprospectors\nprospects\nprospectus\nprospectuses\nprosper\nprospered\nprospering\nprosperities\nprosperity\nprosperous\nprosperously\nprosperousness\nprosperousnesses\nprospers\npross\nprosses\nprossie\nprossies\nprost\nprostacyclin\nprostacyclins\nprostaglandin\nprostaglandins\nprostate\nprostatectomies\nprostatectomy\nprostates\nprostatic\nprostatism\nprostatisms\nprostatitis\nprostatitises\nprostheses\nprosthesis\nprosthetic\nprosthetically\nprosthetics\nprosthetist\nprosthetists\nprosthodontics\nprosthodontist\nprosthodontists\nprostie\nprosties\nprostitute\nprostituted\nprostitutes\nprostituting\nprostitution\nprostitutions\nprostitutor\nprostitutors\nprostomia\nprostomial\nprostomium\nprostrate\nprostrated\nprostrates\nprostrating\nprostration\nprostrations\nprostyle\nprostyles\nprosy\nprotactinium\nprotactiniums\nprotagonist\nprotagonists\nprotamin\nprotamine\nprotamines\nprotamins\nprotases\nprotasis\nprotatic\nprotea\nprotean\nproteans\nproteas\nprotease\nproteases\nprotect\nprotectant\nprotectants\nprotected\nprotecting\nprotection\nprotectionism\nprotectionisms\nprotectionist\nprotectionists\nprotections\nprotective\nprotectively\nprotectiveness\nprotectivenesses\nprotector\nprotectoral\nprotectorate\nprotectorates\nprotectories\nprotectors\nprotectorship\nprotectorships\nprotectory\nprotectress\nprotectresses\nprotects\nprotege\nprotegee\nprotegees\nproteges\nprotei\nproteid\nproteide\nproteides\nproteids\nprotein\nproteinaceous\nproteinase\nproteinases\nproteins\nproteinuria\nproteinurias\nprotend\nprotended\nprotending\nprotends\nprotensive\nprotensively\nproteoglycan\nproteoglycans\nproteolyses\nproteolysis\nproteolytic\nproteolytically\nproteose\nproteoses\nprotest\nprotestant\nprotestants\nprotestation\nprotestations\nprotested\nprotester\nprotesters\nprotesting\nprotestor\nprotestors\nprotests\nproteus\nproteuses\nprothalamia\nprothalamion\nprothalamium\nprothalli\nprothallia\nprothallium\nprothallus\nprothalluses\nprotheses\nprothesis\nprothetic\nprothonotarial\nprothonotaries\nprothonotary\nprothoraces\nprothoracic\nprothorax\nprothoraxes\nprothrombin\nprothrombins\nprotist\nprotistan\nprotistans\nprotists\nprotium\nprotiums\nprotocol\nprotocoled\nprotocoling\nprotocolled\nprotocolling\nprotocols\nprotoderm\nprotoderms\nprotogalaxies\nprotogalaxy\nprotohistorian\nprotohistorians\nprotohistoric\nprotohistories\nprotohistory\nprotohuman\nprotohumans\nprotolanguage\nprotolanguages\nprotomartyr\nprotomartyrs\nproton\nprotonate\nprotonated\nprotonates\nprotonating\nprotonation\nprotonations\nprotonema\nprotonemal\nprotonemata\nprotonematal\nprotonic\nprotonotaries\nprotonotary\nprotons\nprotopathic\nprotophloem\nprotophloems\nprotoplanet\nprotoplanetary\nprotoplanets\nprotoplasm\nprotoplasmic\nprotoplasms\nprotoplast\nprotoplasts\nprotopod\nprotopods\nprotoporphyrin\nprotoporphyrins\nprotostar\nprotostars\nprotostele\nprotosteles\nprotostelic\nprotostome\nprotostomes\nprototroph\nprototrophic\nprototrophies\nprototrophs\nprototrophy\nprototypal\nprototype\nprototyped\nprototypes\nprototypic\nprototypical\nprototypically\nprototyping\nprotoxid\nprotoxids\nprotoxylem\nprotoxylems\nprotozoa\nprotozoal\nprotozoan\nprotozoans\nprotozoologies\nprotozoologist\nprotozoologists\nprotozoology\nprotozoon\nprotozoons\nprotract\nprotracted\nprotractile\nprotracting\nprotraction\nprotractions\nprotractive\nprotractor\nprotractors\nprotracts\nprotreptic\nprotreptics\nprotrude\nprotruded\nprotrudes\nprotruding\nprotrusible\nprotrusion\nprotrusions\nprotrusive\nprotrusively\nprotrusiveness\nprotrusivenesses\nprotuberance\nprotuberances\nprotuberant\nprotuberantly\nprotyl\nprotyle\nprotyles\nprotyls\nproud\nprouder\nproudest\nproudful\nproudhearted\nproudly\nprounion\nproustite\nproustites\nprovable\nprovableness\nprovablenesses\nprovably\nprovascular\nprove\nproved\nproven\nprovenance\nprovenances\nprovender\nprovenders\nprovenience\nproveniences\nprovenly\nproventriculi\nproventriculus\nprover\nproverb\nproverbed\nproverbial\nproverbially\nproverbing\nproverbs\nprovers\nproves\nprovide\nprovided\nprovidence\nprovidences\nprovident\nprovidential\nprovidentially\nprovidently\nprovider\nproviders\nprovides\nproviding\nprovince\nprovinces\nprovincial\nprovincialism\nprovincialisms\nprovincialist\nprovincialists\nprovincialities\nprovinciality\nprovincialization\nprovincializations\nprovincialize\nprovincialized\nprovincializes\nprovincializing\nprovincially\nprovincials\nproving\nproviral\nprovirus\nproviruses\nprovision\nprovisional\nprovisionally\nprovisionals\nprovisionary\nprovisioned\nprovisioner\nprovisioners\nprovisioning\nprovisions\nproviso\nprovisoes\nprovisory\nprovisos\nprovitamin\nprovitamins\nprovocateur\nprovocateurs\nprovocation\nprovocations\nprovocative\nprovocatively\nprovocativeness\nprovocativenesses\nprovocatives\nprovoke\nprovoked\nprovoker\nprovokers\nprovokes\nprovoking\nprovokingly\nprovolone\nprovolones\nprovost\nprovosts\nprow\nprowar\nprower\nprowess\nprowesses\nprowest\nprowl\nprowled\nprowler\nprowlers\nprowling\nprowls\nprows\nproxemic\nproxemics\nproxies\nproximal\nproximally\nproximate\nproximately\nproximateness\nproximatenesses\nproximities\nproximity\nproximo\nproxy\nprude\nprudence\nprudences\nprudent\nprudential\nprudentially\nprudently\npruderies\nprudery\nprudes\nprudish\nprudishly\nprudishness\nprudishnesses\npruinose\nprunable\nprune\npruned\nprunella\nprunellas\nprunelle\nprunelles\nprunello\nprunellos\npruner\npruners\nprunes\npruning\nprunus\nprunuses\nprurience\npruriences\npruriencies\npruriency\nprurient\npruriently\nprurigo\nprurigos\npruritic\npruritus\nprurituses\nprussianise\nprussianised\nprussianises\nprussianising\nprussianization\nprussianizations\nprussianize\nprussianized\nprussianizes\nprussianizing\nprussic\npruta\nprutah\nprutot\nprutoth\npry\npryer\npryers\nprying\npryingly\nprythee\npsalm\npsalmbook\npsalmbooks\npsalmed\npsalmic\npsalming\npsalmist\npsalmists\npsalmodies\npsalmody\npsalms\npsalter\npsalteria\npsalteries\npsalterium\npsalters\npsaltery\npsaltries\npsaltry\npsammite\npsammites\npsammon\npsammons\npschent\npschents\npsephite\npsephites\npsephological\npsephologies\npsephologist\npsephologists\npsephology\npseud\npseudepigraph\npseudepigrapha\npseudepigraphies\npseudepigraphon\npseudepigraphs\npseudepigraphy\npseudo\npseudoallele\npseudoalleles\npseudocholinesterase\npseudocholinesterases\npseudoclassic\npseudoclassicism\npseudoclassicisms\npseudoclassics\npseudocoel\npseudocoelomate\npseudocoelomates\npseudocoels\npseudocyeses\npseudocyesis\npseudomonad\npseudomonades\npseudomonads\npseudomonas\npseudomorph\npseudomorphic\npseudomorphism\npseudomorphisms\npseudomorphous\npseudomorphs\npseudonym\npseudonymities\npseudonymity\npseudonymous\npseudonymously\npseudonymousness\npseudonymousnesses\npseudonyms\npseudoparenchyma\npseudoparenchymas\npseudoparenchymata\npseudoparenchymatous\npseudopod\npseudopodal\npseudopodia\npseudopodial\npseudopodium\npseudopods\npseudopregnancies\npseudopregnancy\npseudopregnant\npseudorandom\npseudos\npseudoscience\npseudosciences\npseudoscientific\npseudoscientist\npseudoscientists\npseudoscorpion\npseudoscorpions\npseudosophisticated\npseudosophistication\npseudosophistications\npseudotuberculoses\npseudotuberculosis\npseuds\npshaw\npshawed\npshawing\npshaws\npsi\npsilocin\npsilocins\npsilocybin\npsilocybins\npsilophyte\npsilophytes\npsilophytic\npsiloses\npsilosis\npsilotic\npsis\npsittacine\npsittacines\npsittacoses\npsittacosis\npsittacotic\npsoae\npsoai\npsoas\npsoatic\npsocid\npsocids\npsoralea\npsoraleas\npsoralen\npsoralens\npsoriases\npsoriasis\npsoriatic\npsoriatics\npsst\npsych\npsychasthenia\npsychasthenias\npsychasthenic\npsychasthenics\npsyche\npsyched\npsychedelia\npsychedelias\npsychedelic\npsychedelically\npsychedelics\npsyches\npsychiatric\npsychiatrically\npsychiatries\npsychiatrist\npsychiatrists\npsychiatry\npsychic\npsychical\npsychically\npsychics\npsyching\npsycho\npsychoacoustic\npsychoacoustics\npsychoactive\npsychoanalyses\npsychoanalysis\npsychoanalyst\npsychoanalysts\npsychoanalytic\npsychoanalytical\npsychoanalytically\npsychoanalyze\npsychoanalyzed\npsychoanalyzes\npsychoanalyzing\npsychobabble\npsychobabbler\npsychobabblers\npsychobabbles\npsychobiographer\npsychobiographers\npsychobiographical\npsychobiographies\npsychobiography\npsychobiologic\npsychobiological\npsychobiologies\npsychobiologist\npsychobiologists\npsychobiology\npsychochemical\npsychochemicals\npsychodrama\npsychodramas\npsychodramatic\npsychodynamic\npsychodynamically\npsychodynamics\npsychogeneses\npsychogenesis\npsychogenetic\npsychogenic\npsychogenically\npsychograph\npsychographs\npsychohistorian\npsychohistorians\npsychohistorical\npsychohistories\npsychohistory\npsychokineses\npsychokinesis\npsychokinetic\npsycholinguist\npsycholinguistic\npsycholinguistics\npsycholinguists\npsychologic\npsychological\npsychologically\npsychologies\npsychologise\npsychologised\npsychologises\npsychologising\npsychologism\npsychologisms\npsychologist\npsychologists\npsychologize\npsychologized\npsychologizes\npsychologizing\npsychology\npsychometric\npsychometrically\npsychometrician\npsychometricians\npsychometrics\npsychometries\npsychometry\npsychomotor\npsychoneuroses\npsychoneurosis\npsychoneurotic\npsychoneurotics\npsychopath\npsychopathic\npsychopathically\npsychopathics\npsychopathies\npsychopathologic\npsychopathological\npsychopathologically\npsychopathologies\npsychopathologist\npsychopathologists\npsychopathology\npsychopaths\npsychopathy\npsychopharmacologic\npsychopharmacological\npsychopharmacologies\npsychopharmacologist\npsychopharmacologists\npsychopharmacology\npsychophysical\npsychophysically\npsychophysicist\npsychophysicists\npsychophysics\npsychophysiologic\npsychophysiological\npsychophysiologically\npsychophysiologies\npsychophysiologist\npsychophysiologists\npsychophysiology\npsychos\npsychoses\npsychosexual\npsychosexualities\npsychosexuality\npsychosexually\npsychosis\npsychosocial\npsychosocially\npsychosomatic\npsychosomatically\npsychosomatics\npsychosurgeon\npsychosurgeons\npsychosurgeries\npsychosurgery\npsychosurgical\npsychosyntheses\npsychosynthesis\npsychotherapeutic\npsychotherapeutically\npsychotherapies\npsychotherapist\npsychotherapists\npsychotherapy\npsychotic\npsychotically\npsychotics\npsychotomimetic\npsychotomimetically\npsychotomimetics\npsychotropic\npsychotropics\npsychrometer\npsychrometers\npsychrometric\npsychrometries\npsychrometry\npsychrophilic\npsychs\npsylla\npsyllas\npsyllid\npsyllids\npsyllium\npsylliums\npsywar\npsywars\nptarmigan\nptarmigans\npteranodon\npteranodons\npteridine\npteridines\npteridological\npteridologies\npteridologist\npteridologists\npteridology\npteridophyte\npteridophytes\npteridosperm\npteridosperms\npterin\npterins\npterodactyl\npterodactyls\npteropod\npteropods\npterosaur\npterosaurs\npterygia\npterygium\npterygiums\npterygoid\npterygoids\npteryla\npterylae\nptisan\nptisans\nptomain\nptomaine\nptomaines\nptomains\nptoses\nptosis\nptotic\nptyalin\nptyalins\nptyalism\nptyalisms\npub\npuberal\npubertal\npuberties\npuberty\npuberulent\npubes\npubescence\npubescences\npubescent\npubic\npubis\npublic\npublically\npublican\npublicans\npublication\npublications\npublicise\npublicised\npublicises\npublicising\npublicist\npublicists\npublicities\npublicity\npublicize\npublicized\npublicizes\npublicizing\npublicly\npublicness\npublicnesses\npublics\npublish\npublishable\npublished\npublisher\npublishers\npublishes\npublishing\npublishings\npubs\npuccoon\npuccoons\npuce\npuces\npuck\npucka\npucker\npuckered\npuckerer\npuckerers\npuckerier\npuckeriest\npuckering\npuckers\npuckery\npuckish\npuckishly\npuckishness\npuckishnesses\npucks\npud\npudding\npuddings\npuddle\npuddled\npuddler\npuddlers\npuddles\npuddlier\npuddliest\npuddling\npuddlings\npuddly\npudencies\npudency\npudenda\npudendal\npudendum\npudgier\npudgiest\npudgily\npudginess\npudginesses\npudgy\npudibund\npudic\npuds\npueblo\npueblos\npuerile\npuerilely\npuerilism\npuerilisms\npuerilities\npuerility\npuerperal\npuerperia\npuerperium\npuff\npuffball\npuffballs\npuffed\npuffer\npufferies\npuffers\npuffery\npuffier\npuffiest\npuffily\npuffin\npuffiness\npuffinesses\npuffing\npuffins\npuffs\npuffy\npug\npugaree\npugarees\npuggaree\npuggarees\npugged\npuggier\npuggiest\npugging\npuggish\npuggree\npuggrees\npuggries\npuggry\npuggy\npugh\npugilism\npugilisms\npugilist\npugilistic\npugilists\npugmark\npugmarks\npugnacious\npugnaciously\npugnaciousness\npugnaciousnesses\npugnacities\npugnacity\npugree\npugrees\npugs\npuisne\npuisnes\npuissance\npuissances\npuissant\npuja\npujah\npujahs\npujas\npuke\npuked\npukes\npuking\npukka\npul\npula\npulchritude\npulchritudes\npulchritudinous\npule\npuled\npuler\npulers\npules\npuli\npulicene\npulicide\npulicides\npulik\npuling\npulingly\npulings\npulis\npull\npullback\npullbacks\npulled\npuller\npullers\npullet\npullets\npulley\npulleys\npulling\npullman\npullmans\npullout\npullouts\npullover\npullovers\npulls\npullulate\npullulated\npullulates\npullulating\npullulation\npullulations\npullup\npullups\npulmonary\npulmonate\npulmonates\npulmonic\npulmotor\npulmotors\npulp\npulpal\npulpally\npulped\npulper\npulpers\npulpier\npulpiest\npulpily\npulpiness\npulpinesses\npulping\npulpit\npulpital\npulpits\npulpless\npulpous\npulps\npulpwood\npulpwoods\npulpy\npulque\npulques\npuls\npulsant\npulsar\npulsars\npulsate\npulsated\npulsates\npulsatile\npulsating\npulsation\npulsations\npulsator\npulsators\npulse\npulsed\npulsejet\npulsejets\npulser\npulsers\npulses\npulsing\npulsion\npulsions\npulsojet\npulsojets\npulverable\npulverise\npulverised\npulverises\npulverising\npulverizable\npulverization\npulverizations\npulverize\npulverized\npulverizer\npulverizers\npulverizes\npulverizing\npulverulent\npulvilli\npulvillus\npulvinar\npulvini\npulvinus\npuma\npumas\npumelo\npumelos\npumice\npumiced\npumiceous\npumicer\npumicers\npumices\npumicing\npumicite\npumicites\npummel\npummeled\npummeling\npummelled\npummelling\npummelo\npummelos\npummels\npump\npumped\npumper\npumpernickel\npumpernickels\npumpers\npumping\npumpkin\npumpkins\npumpkinseed\npumpkinseeds\npumpless\npumplike\npumps\npun\npuna\npunas\npunch\npunchball\npunchballs\npunchboard\npunchboards\npunched\npuncheon\npuncheons\npuncher\npunchers\npunches\npunchier\npunchiest\npunchily\npunchinello\npunchinellos\npunching\npunchless\npunchy\npunctate\npunctation\npunctations\npunctilio\npunctilios\npunctilious\npunctiliously\npunctiliousness\npunctiliousnesses\npunctual\npunctualities\npunctuality\npunctually\npunctuate\npunctuated\npunctuates\npunctuating\npunctuation\npunctuations\npunctuator\npunctuators\npuncture\npunctured\npunctures\npuncturing\npundit\npunditic\npunditries\npunditry\npundits\npung\npungencies\npungency\npungent\npungently\npungle\npungled\npungles\npungling\npungs\npunier\npuniest\npunily\npuniness\npuninesses\npunish\npunishabilities\npunishability\npunishable\npunished\npunisher\npunishers\npunishes\npunishing\npunishment\npunishments\npunition\npunitions\npunitive\npunitively\npunitiveness\npunitivenesses\npunitory\npunk\npunka\npunkah\npunkahs\npunkas\npunker\npunkers\npunkest\npunkey\npunkeys\npunkie\npunkier\npunkies\npunkiest\npunkin\npunkiness\npunkinesses\npunkins\npunkish\npunks\npunky\npunned\npunner\npunners\npunnet\npunnets\npunnier\npunniest\npunning\npunny\npuns\npunster\npunsters\npunt\npunted\npunter\npunters\npunties\npunting\npunto\npuntos\npunts\npunty\npuny\npup\npupa\npupae\npupal\npuparia\npuparial\npuparium\npupas\npupate\npupated\npupates\npupating\npupation\npupations\npupfish\npupfishes\npupil\npupilage\npupilages\npupilar\npupilary\npupillage\npupillages\npupillary\npupils\npupped\npuppet\npuppeteer\npuppeteers\npuppetlike\npuppetries\npuppetry\npuppets\npuppies\npupping\npuppy\npuppydom\npuppydoms\npuppyhood\npuppyhoods\npuppyish\npuppylike\npups\npur\npurana\npuranas\npuranic\npurblind\npurblindly\npurblindness\npurblindnesses\npurchasable\npurchase\npurchased\npurchaser\npurchasers\npurchases\npurchasing\npurda\npurdah\npurdahs\npurdas\npure\npureblood\npurebloods\npurebred\npurebreds\npuree\npureed\npureeing\npurees\npurely\npureness\npurenesses\npurer\npurest\npurfle\npurfled\npurfles\npurfling\npurflings\npurgation\npurgations\npurgative\npurgatives\npurgatorial\npurgatories\npurgatory\npurge\npurged\npurger\npurgers\npurges\npurging\npurgings\npuri\npurification\npurifications\npurificator\npurificators\npurificatory\npurified\npurifier\npurifiers\npurifies\npurify\npurifying\npurin\npurine\npurines\npurins\npuris\npurism\npurisms\npurist\npuristic\npuristically\npurists\npuritan\npuritanical\npuritanically\npuritanism\npuritanisms\npuritans\npurities\npurity\npurl\npurled\npurlieu\npurlieus\npurlin\npurline\npurlines\npurling\npurlins\npurloin\npurloined\npurloiner\npurloiners\npurloining\npurloins\npurls\npuromycin\npuromycins\npurple\npurpled\npurpleheart\npurplehearts\npurpler\npurples\npurplest\npurpling\npurplish\npurply\npurport\npurported\npurportedly\npurporting\npurports\npurpose\npurposed\npurposeful\npurposefully\npurposefulness\npurposefulnesses\npurposeless\npurposelessly\npurposelessness\npurposelessnesses\npurposely\npurposes\npurposing\npurposive\npurposively\npurposiveness\npurposivenesses\npurpura\npurpuras\npurpure\npurpures\npurpuric\npurpurin\npurpurins\npurr\npurred\npurring\npurringly\npurrs\npurs\npurse\npursed\npurselike\npurser\npursers\npurses\npursier\npursiest\npursily\npursiness\npursinesses\npursing\npurslane\npurslanes\npursuance\npursuances\npursuant\npursue\npursued\npursuer\npursuers\npursues\npursuing\npursuit\npursuits\npursuivant\npursuivants\npursy\npurtenance\npurtenances\npurulence\npurulences\npurulent\npurvey\npurveyance\npurveyances\npurveyed\npurveying\npurveyor\npurveyors\npurveys\npurview\npurviews\npus\npuses\npush\npushball\npushballs\npushcart\npushcarts\npushchair\npushchairs\npushdown\npushdowns\npushed\npusher\npushers\npushes\npushful\npushfulness\npushfulnesses\npushier\npushiest\npushily\npushiness\npushinesses\npushing\npushover\npushovers\npushpin\npushpins\npushrod\npushrods\npushup\npushups\npushy\npusillanimities\npusillanimity\npusillanimous\npusillanimously\npusley\npusleys\npuslike\npuss\npusses\npussier\npussies\npussiest\npussley\npussleys\npusslies\npusslike\npussly\npussy\npussycat\npussycats\npussyfoot\npussyfooted\npussyfooter\npussyfooters\npussyfooting\npussyfoots\npussytoes\npustulant\npustulants\npustular\npustulated\npustulation\npustulations\npustule\npustuled\npustules\nput\nputamen\nputamina\nputative\nputatively\nputdown\nputdowns\nputlog\nputlogs\nputoff\nputoffs\nputon\nputons\nputout\nputouts\nputrefaction\nputrefactions\nputrefactive\nputrefied\nputrefies\nputrefy\nputrefying\nputrescence\nputrescences\nputrescent\nputrescible\nputrescine\nputrescines\nputrid\nputridities\nputridity\nputridly\nputs\nputsch\nputsches\nputschist\nputschists\nputt\nputted\nputtee\nputtees\nputter\nputtered\nputterer\nputterers\nputtering\nputters\nputti\nputtied\nputtier\nputtiers\nputties\nputting\nputto\nputts\nputty\nputtying\nputtyless\nputtylike\nputtyroot\nputtyroots\nputz\nputzed\nputzes\nputzing\npuzzle\npuzzled\npuzzleheaded\npuzzleheadedness\npuzzleheadednesses\npuzzlement\npuzzlements\npuzzler\npuzzlers\npuzzles\npuzzling\npuzzlingly\npya\npyaemia\npyaemias\npyaemic\npyas\npycnidia\npycnidial\npycnidium\npycnogonid\npycnogonids\npycnometer\npycnometers\npycnoses\npycnosis\npycnotic\npye\npyelitic\npyelitis\npyelitises\npyelonephritic\npyelonephritides\npyelonephritis\npyemia\npyemias\npyemic\npyes\npygidia\npygidial\npygidium\npygmaean\npygmean\npygmies\npygmoid\npygmy\npygmyish\npygmyism\npygmyisms\npyic\npyin\npyins\npyjamas\npyknic\npyknics\npyknoses\npyknosis\npyknotic\npylon\npylons\npylori\npyloric\npylorus\npyloruses\npyoderma\npyodermas\npyogenic\npyoid\npyorrhea\npyorrheas\npyoses\npyosis\npyracantha\npyracanthas\npyralid\npyralids\npyramid\npyramidal\npyramidally\npyramided\npyramidical\npyramiding\npyramids\npyran\npyranoid\npyranose\npyranoses\npyranoside\npyranosides\npyrans\npyrargyrite\npyrargyrites\npyre\npyrene\npyrenes\npyrenoid\npyrenoids\npyres\npyrethrin\npyrethrins\npyrethroid\npyrethroids\npyrethrum\npyrethrums\npyretic\npyrexia\npyrexial\npyrexias\npyrexic\npyrheliometer\npyrheliometers\npyrheliometric\npyric\npyridic\npyridine\npyridines\npyridoxal\npyridoxals\npyridoxamine\npyridoxamines\npyridoxine\npyridoxines\npyriform\npyrimethamine\npyrimethamines\npyrimidine\npyrimidines\npyrite\npyrites\npyritic\npyritous\npyrocatechol\npyrocatechols\npyroclastic\npyroelectric\npyroelectricities\npyroelectricity\npyrogallol\npyrogallols\npyrogen\npyrogenic\npyrogenicities\npyrogenicity\npyrogens\npyrola\npyrolas\npyrolize\npyrolized\npyrolizes\npyrolizing\npyrologies\npyrology\npyrolusite\npyrolusites\npyrolysate\npyrolysates\npyrolyses\npyrolysis\npyrolytic\npyrolytically\npyrolyzable\npyrolyzate\npyrolyzates\npyrolyze\npyrolyzed\npyrolyzer\npyrolyzers\npyrolyzes\npyrolyzing\npyromancies\npyromancy\npyromania\npyromaniac\npyromaniacal\npyromaniacs\npyromanias\npyrometallurgical\npyrometallurgies\npyrometallurgy\npyrometer\npyrometers\npyrometric\npyrometrically\npyrometries\npyrometry\npyromorphite\npyromorphites\npyrone\npyrones\npyronine\npyronines\npyroninophilic\npyrope\npyropes\npyrophoric\npyrophosphate\npyrophosphates\npyrophyllite\npyrophyllites\npyrosis\npyrosises\npyrostat\npyrostats\npyrotechnic\npyrotechnical\npyrotechnically\npyrotechnics\npyrotechnist\npyrotechnists\npyroxene\npyroxenes\npyroxenic\npyroxenite\npyroxenites\npyroxenitic\npyroxenoid\npyroxenoids\npyroxylin\npyroxylins\npyrrhic\npyrrhics\npyrrhotite\npyrrhotites\npyrrol\npyrrole\npyrroles\npyrrolic\npyrrols\npyruvate\npyruvates\npython\npythoness\npythonesses\npythonic\npythons\npyuria\npyurias\npyx\npyxes\npyxides\npyxidia\npyxidium\npyxie\npyxies\npyxis\nqaid\nqaids\nqanat\nqanats\nqat\nqats\nqindar\nqindarka\nqindarkas\nqindars\nqintar\nqintars\nqiviut\nqiviuts\nqoph\nqophs\nqua\nquaalude\nquaaludes\nquack\nquacked\nquackeries\nquackery\nquacking\nquackish\nquackism\nquackisms\nquacks\nquacksalver\nquacksalvers\nquad\nquadded\nquadding\nquadplex\nquadplexes\nquadrangle\nquadrangles\nquadrangular\nquadrans\nquadrant\nquadrantal\nquadrantes\nquadrants\nquadraphonic\nquadraphonics\nquadrat\nquadrate\nquadrated\nquadrates\nquadratic\nquadratically\nquadratics\nquadrating\nquadrats\nquadrature\nquadratures\nquadrennia\nquadrennial\nquadrennially\nquadrennials\nquadrennium\nquadrenniums\nquadric\nquadricentennial\nquadricentennials\nquadriceps\nquadricepses\nquadrics\nquadriga\nquadrigae\nquadrilateral\nquadrilaterals\nquadrille\nquadrilles\nquadrillion\nquadrillions\nquadrillionth\nquadrillionths\nquadripartite\nquadriphonic\nquadriphonics\nquadriplegia\nquadriplegias\nquadriplegic\nquadriplegics\nquadrivalent\nquadrivalents\nquadrivia\nquadrivial\nquadrivium\nquadriviums\nquadroon\nquadroons\nquadrumanous\nquadrumvir\nquadrumvirate\nquadrumvirates\nquadrumvirs\nquadruped\nquadrupedal\nquadrupeds\nquadruple\nquadrupled\nquadruples\nquadruplet\nquadruplets\nquadruplicate\nquadruplicated\nquadruplicates\nquadruplicating\nquadruplication\nquadruplications\nquadruplicities\nquadruplicity\nquadrupling\nquadruply\nquadrupole\nquadrupoles\nquads\nquaere\nquaeres\nquaestor\nquaestors\nquaff\nquaffed\nquaffer\nquaffers\nquaffing\nquaffs\nquag\nquagga\nquaggas\nquaggier\nquaggiest\nquaggy\nquagmire\nquagmires\nquagmirier\nquagmiriest\nquagmiry\nquags\nquahaug\nquahaugs\nquahog\nquahogs\nquai\nquaich\nquaiches\nquaichs\nquaigh\nquaighs\nquail\nquailed\nquailing\nquails\nquaint\nquainter\nquaintest\nquaintly\nquaintness\nquaintnesses\nquais\nquake\nquaked\nquaker\nquakers\nquakes\nquakier\nquakiest\nquakily\nquaking\nquaky\nquale\nqualia\nqualifiable\nqualification\nqualifications\nqualified\nqualifiedly\nqualifier\nqualifiers\nqualifies\nqualify\nqualifying\nqualitative\nqualitatively\nqualities\nquality\nqualm\nqualmier\nqualmiest\nqualmish\nqualmishly\nqualmishness\nqualmishnesses\nqualms\nqualmy\nquamash\nquamashes\nquandang\nquandangs\nquandaries\nquandary\nquandong\nquandongs\nquango\nquangos\nquant\nquanta\nquantal\nquanted\nquantic\nquantics\nquantifiable\nquantification\nquantificational\nquantificationally\nquantifications\nquantified\nquantifier\nquantifiers\nquantifies\nquantify\nquantifying\nquantile\nquantiles\nquanting\nquantitate\nquantitated\nquantitates\nquantitating\nquantitation\nquantitations\nquantitative\nquantitatively\nquantitativeness\nquantitativenesses\nquantities\nquantity\nquantization\nquantizations\nquantize\nquantized\nquantizer\nquantizers\nquantizes\nquantizing\nquantong\nquantongs\nquants\nquantum\nquarantine\nquarantined\nquarantines\nquarantining\nquare\nquark\nquarks\nquarrel\nquarreled\nquarreler\nquarrelers\nquarreling\nquarrelled\nquarreller\nquarrellers\nquarrelling\nquarrels\nquarrelsome\nquarrelsomely\nquarrelsomeness\nquarrelsomenesses\nquarried\nquarrier\nquarriers\nquarries\nquarry\nquarrying\nquarryings\nquarryman\nquarrymen\nquart\nquartan\nquartans\nquarte\nquarter\nquarterage\nquarterages\nquarterback\nquarterbacked\nquarterbacking\nquarterbacks\nquarterdeck\nquarterdecks\nquartered\nquarterfinal\nquarterfinalist\nquarterfinalists\nquarterfinals\nquartering\nquarterings\nquarterlies\nquarterly\nquartermaster\nquartermasters\nquartern\nquarterns\nquarters\nquartersawed\nquartersawn\nquarterstaff\nquarterstaffs\nquarterstaves\nquartes\nquartet\nquartets\nquartette\nquartettes\nquartic\nquartics\nquartile\nquartiles\nquarto\nquartos\nquarts\nquartz\nquartzes\nquartzite\nquartzites\nquartzitic\nquartzose\nquasar\nquasars\nquash\nquashed\nquasher\nquashers\nquashes\nquashing\nquasi\nquasicrystal\nquasicrystalline\nquasicrystals\nquasiparticle\nquasiparticles\nquasiperiodic\nquasiperiodicities\nquasiperiodicity\nquass\nquasses\nquassia\nquassias\nquassin\nquassins\nquate\nquatercentenaries\nquatercentenary\nquaternaries\nquaternary\nquaternion\nquaternions\nquaternities\nquaternity\nquatorze\nquatorzes\nquatrain\nquatrains\nquatre\nquatrefoil\nquatrefoils\nquatres\nquattrocento\nquattrocentos\nquattuordecillion\nquattuordecillions\nquaver\nquavered\nquaverer\nquaverers\nquavering\nquaveringly\nquavers\nquavery\nquay\nquayage\nquayages\nquaylike\nquays\nquayside\nquaysides\nquean\nqueans\nqueasier\nqueasiest\nqueasily\nqueasiness\nqueasinesses\nqueasy\nqueazier\nqueaziest\nqueazy\nquebracho\nquebrachos\nqueen\nqueendom\nqueendoms\nqueened\nqueening\nqueenlier\nqueenliest\nqueenliness\nqueenlinesses\nqueenly\nqueens\nqueenship\nqueenships\nqueenside\nqueensides\nqueer\nqueered\nqueerer\nqueerest\nqueering\nqueerish\nqueerly\nqueerness\nqueernesses\nqueers\nquell\nquelled\nqueller\nquellers\nquelling\nquells\nquench\nquenchable\nquenched\nquencher\nquenchers\nquenches\nquenching\nquenchless\nquenelle\nquenelles\nquercetin\nquercetins\nquercine\nquercitron\nquercitrons\nquerida\nqueridas\nqueried\nquerier\nqueriers\nqueries\nquerist\nquerists\nquern\nquerns\nquerulous\nquerulously\nquerulousness\nquerulousnesses\nquery\nquerying\nquesadilla\nquesadillas\nquest\nquested\nquester\nquesters\nquesting\nquestion\nquestionable\nquestionableness\nquestionablenesses\nquestionably\nquestionaries\nquestionary\nquestioned\nquestioner\nquestioners\nquestioning\nquestionless\nquestionnaire\nquestionnaires\nquestions\nquestor\nquestors\nquests\nquetzal\nquetzales\nquetzals\nqueue\nqueued\nqueueing\nqueuer\nqueuers\nqueues\nqueuing\nquey\nqueys\nquezal\nquezales\nquezals\nquibble\nquibbled\nquibbler\nquibblers\nquibbles\nquibbling\nquiche\nquiches\nquick\nquicken\nquickened\nquickener\nquickeners\nquickening\nquickens\nquicker\nquickest\nquickie\nquickies\nquicklime\nquicklimes\nquickly\nquickness\nquicknesses\nquicks\nquicksand\nquicksands\nquickset\nquicksets\nquicksilver\nquicksilvers\nquickstep\nquicksteps\nquid\nquiddities\nquiddity\nquidnunc\nquidnuncs\nquids\nquiescence\nquiescences\nquiescent\nquiescently\nquiet\nquieted\nquieten\nquietened\nquietening\nquietens\nquieter\nquieters\nquietest\nquieting\nquietism\nquietisms\nquietist\nquietistic\nquietists\nquietly\nquietness\nquietnesses\nquiets\nquietude\nquietudes\nquietus\nquietuses\nquiff\nquiffs\nquill\nquillai\nquillaia\nquillaias\nquillais\nquillaja\nquillajas\nquillback\nquillbacks\nquilled\nquillet\nquillets\nquilling\nquillings\nquills\nquillwork\nquillworks\nquilt\nquilted\nquilter\nquilters\nquilting\nquiltings\nquilts\nquin\nquinacrine\nquinacrines\nquinaries\nquinary\nquinate\nquince\nquincentenaries\nquincentenary\nquincentennial\nquincentennials\nquinces\nquincuncial\nquincunx\nquincunxes\nquincunxial\nquindecillion\nquindecillions\nquinela\nquinelas\nquinella\nquinellas\nquinic\nquinidine\nquinidines\nquiniela\nquinielas\nquinin\nquinina\nquininas\nquinine\nquinines\nquinins\nquinnat\nquinnats\nquinoa\nquinoas\nquinoid\nquinoids\nquinol\nquinolin\nquinoline\nquinolines\nquinolins\nquinols\nquinone\nquinones\nquinonoid\nquinquennia\nquinquennial\nquinquennially\nquinquennials\nquinquennium\nquinquenniums\nquins\nquinsies\nquinsy\nquint\nquinta\nquintain\nquintains\nquintal\nquintals\nquintan\nquintans\nquintar\nquintars\nquintas\nquinte\nquintes\nquintessence\nquintessences\nquintessential\nquintessentially\nquintet\nquintets\nquintette\nquintettes\nquintic\nquintics\nquintile\nquintiles\nquintillion\nquintillions\nquintillionth\nquintillionths\nquintin\nquintins\nquints\nquintuple\nquintupled\nquintuples\nquintuplet\nquintuplets\nquintuplicate\nquintuplicated\nquintuplicates\nquintuplicating\nquintupling\nquip\nquipped\nquipper\nquippers\nquipping\nquippish\nquippu\nquippus\nquips\nquipster\nquipsters\nquipu\nquipus\nquire\nquired\nquires\nquiring\nquirk\nquirked\nquirkier\nquirkiest\nquirkily\nquirkiness\nquirkinesses\nquirking\nquirkish\nquirks\nquirky\nquirt\nquirted\nquirting\nquirts\nquisling\nquislingism\nquislingisms\nquislings\nquit\nquitch\nquitches\nquitclaim\nquitclaimed\nquitclaiming\nquitclaims\nquite\nquitrent\nquitrents\nquits\nquittance\nquittances\nquitted\nquitter\nquitters\nquitting\nquittor\nquittors\nquiver\nquivered\nquiverer\nquiverers\nquivering\nquiveringly\nquivers\nquivery\nquixote\nquixotes\nquixotic\nquixotical\nquixotically\nquixotism\nquixotisms\nquixotries\nquixotry\nquiz\nquizmaster\nquizmasters\nquizzed\nquizzer\nquizzers\nquizzes\nquizzical\nquizzicalities\nquizzicality\nquizzically\nquizzing\nquod\nquodlibet\nquodlibets\nquods\nquohog\nquohogs\nquoin\nquoined\nquoining\nquoins\nquoit\nquoited\nquoiting\nquoits\nquokka\nquokkas\nquomodo\nquomodos\nquondam\nquorum\nquorums\nquota\nquotabilities\nquotability\nquotable\nquotably\nquotas\nquotation\nquotations\nquote\nquoted\nquoter\nquoters\nquotes\nquoth\nquotha\nquotidian\nquotidians\nquotient\nquotients\nquoting\nqursh\nqurshes\nqurush\nqurushes\nqwerty\nqwertys\nrabat\nrabato\nrabatos\nrabats\nrabbet\nrabbeted\nrabbeting\nrabbets\nrabbi\nrabbies\nrabbin\nrabbinate\nrabbinates\nrabbinic\nrabbinical\nrabbinically\nrabbinism\nrabbinisms\nrabbins\nrabbis\nrabbit\nrabbitbrush\nrabbitbrushes\nrabbited\nrabbiter\nrabbiters\nrabbiting\nrabbitries\nrabbitry\nrabbits\nrabbity\nrabble\nrabbled\nrabblement\nrabblements\nrabbler\nrabblers\nrabbles\nrabbling\nrabboni\nrabbonis\nrabic\nrabid\nrabidities\nrabidity\nrabidly\nrabidness\nrabidnesses\nrabies\nrabietic\nraccoon\nraccoons\nrace\nracecourse\nracecourses\nraced\nracehorse\nracehorses\nracemate\nracemates\nraceme\nracemed\nracemes\nracemic\nracemism\nracemisms\nracemization\nracemizations\nracemize\nracemized\nracemizes\nracemizing\nracemoid\nracemose\nracemous\nracer\nracers\nraces\nracetrack\nracetracker\nracetrackers\nracetracks\nracewalker\nracewalkers\nracewalking\nracewalkings\nraceway\nraceways\nrachet\nrachets\nrachial\nrachides\nrachilla\nrachillae\nrachis\nrachises\nrachitic\nrachitides\nrachitis\nracial\nracialism\nracialisms\nracialist\nracialistic\nracialists\nracially\nracier\nraciest\nracily\nraciness\nracinesses\nracing\nracings\nracism\nracisms\nracist\nracists\nrack\nracked\nracker\nrackers\nracket\nracketed\nracketeer\nracketeered\nracketeering\nracketeers\nracketier\nracketiest\nracketing\nrackets\nrackety\nrackful\nrackfuls\nracking\nrackingly\nrackle\nracks\nrackwork\nrackworks\nraclette\nraclettes\nracon\nracons\nraconteur\nraconteurs\nracoon\nracoons\nracquet\nracquetball\nracquetballs\nracquets\nracy\nrad\nradar\nradars\nradarscope\nradarscopes\nradded\nradding\nraddle\nraddled\nraddles\nraddling\nradiable\nradial\nradiale\nradialia\nradially\nradials\nradian\nradiance\nradiances\nradiancies\nradiancy\nradians\nradiant\nradiantly\nradiants\nradiate\nradiated\nradiately\nradiates\nradiating\nradiation\nradiational\nradiationless\nradiations\nradiative\nradiator\nradiators\nradical\nradicalise\nradicalised\nradicalises\nradicalising\nradicalism\nradicalisms\nradicalization\nradicalizations\nradicalize\nradicalized\nradicalizes\nradicalizing\nradically\nradicalness\nradicalnesses\nradicals\nradicand\nradicands\nradicate\nradicated\nradicates\nradicating\nradicchio\nradicchios\nradicel\nradicels\nradices\nradicle\nradicles\nradicular\nradii\nradio\nradioactive\nradioactively\nradioactivities\nradioactivity\nradioallergosorbent\nradioautograph\nradioautographic\nradioautographies\nradioautographs\nradioautography\nradiobiologic\nradiobiological\nradiobiologically\nradiobiologies\nradiobiologist\nradiobiologists\nradiobiology\nradiocarbon\nradiocarbons\nradiochemical\nradiochemically\nradiochemist\nradiochemistries\nradiochemistry\nradiochemists\nradiochromatogram\nradiochromatograms\nradioecologies\nradioecology\nradioed\nradioelement\nradioelements\nradiogenic\nradiogram\nradiograms\nradiograph\nradiographed\nradiographic\nradiographically\nradiographies\nradiographing\nradiographs\nradiography\nradioimmunoassay\nradioimmunoassayable\nradioimmunoassays\nradioing\nradioisotope\nradioisotopes\nradioisotopic\nradioisotopically\nradiolabel\nradiolabeled\nradiolabeling\nradiolabelled\nradiolabelling\nradiolabels\nradiolarian\nradiolarians\nradiologic\nradiological\nradiologically\nradiologies\nradiologist\nradiologists\nradiology\nradiolucencies\nradiolucency\nradiolucent\nradiolyses\nradiolysis\nradiolytic\nradioman\nradiomen\nradiometer\nradiometers\nradiometric\nradiometrically\nradiometries\nradiometry\nradiomimetic\nradionuclide\nradionuclides\nradiopaque\nradiopharmaceutical\nradiopharmaceuticals\nradiophone\nradiophones\nradiophoto\nradiophotos\nradioprotection\nradioprotections\nradioprotective\nradios\nradiosensitive\nradiosensitivities\nradiosensitivity\nradiosonde\nradiosondes\nradiostrontium\nradiostrontiums\nradiotelegraph\nradiotelegraphies\nradiotelegraphs\nradiotelegraphy\nradiotelemetric\nradiotelemetries\nradiotelemetry\nradiotelephone\nradiotelephones\nradiotelephonies\nradiotelephony\nradiotherapies\nradiotherapist\nradiotherapists\nradiotherapy\nradiothorium\nradiothoriums\nradiotracer\nradiotracers\nradish\nradishes\nradium\nradiums\nradius\nradiuses\nradix\nradixes\nradome\nradomes\nradon\nradons\nrads\nradula\nradulae\nradular\nradulas\nradwaste\nradwastes\nraff\nraffia\nraffias\nraffinose\nraffinoses\nraffish\nraffishly\nraffishness\nraffishnesses\nraffle\nraffled\nraffler\nrafflers\nraffles\nrafflesia\nrafflesias\nraffling\nraffs\nraft\nrafted\nrafter\nraftered\nrafters\nrafting\nrafts\nraftsman\nraftsmen\nrag\nraga\nragamuffin\nragamuffins\nragas\nragbag\nragbags\nrage\nraged\nragee\nragees\nrages\nragged\nraggeder\nraggedest\nraggedly\nraggedness\nraggednesses\nraggedy\nraggee\nraggees\nraggies\nragging\nraggle\nraggles\nraggy\nragi\nraging\nragingly\nragis\nraglan\nraglans\nragman\nragmen\nragout\nragouted\nragouting\nragouts\nragpicker\nragpickers\nrags\nragtag\nragtags\nragtime\nragtimes\nragtop\nragtops\nragweed\nragweeds\nragwort\nragworts\nrah\nraia\nraias\nraid\nraided\nraider\nraiders\nraiding\nraids\nrail\nrailbird\nrailbirds\nrailbus\nrailbuses\nrailbusses\nrailcar\nrailcars\nrailed\nrailer\nrailers\nrailhead\nrailheads\nrailing\nrailings\nrailleries\nraillery\nrailroad\nrailroaded\nrailroader\nrailroaders\nrailroading\nrailroadings\nrailroads\nrails\nrailway\nrailways\nraiment\nraiments\nrain\nrainband\nrainbands\nrainbird\nrainbirds\nrainbow\nrainbowlike\nrainbows\nraincheck\nrainchecks\nraincoat\nraincoats\nraindrop\nraindrops\nrained\nrainfall\nrainfalls\nrainforest\nrainforests\nrainier\nrainiest\nrainily\nraining\nrainless\nrainmaker\nrainmakers\nrainmaking\nrainmakings\nrainout\nrainouts\nrainproof\nrains\nrainspout\nrainspouts\nrainsquall\nrainsqualls\nrainstorm\nrainstorms\nrainwash\nrainwashed\nrainwashes\nrainwashing\nrainwater\nrainwaters\nrainwear\nrainy\nraisable\nraise\nraised\nraiser\nraisers\nraises\nraisin\nraising\nraisings\nraisins\nraisiny\nraisonne\nraj\nraja\nrajah\nrajahs\nrajas\nrajes\nrake\nraked\nrakee\nrakees\nrakehell\nrakehells\nrakehelly\nrakeoff\nrakeoffs\nraker\nrakers\nrakes\nraki\nraking\nrakis\nrakish\nrakishly\nrakishness\nrakishnesses\nrale\nrales\nrallentando\nrallied\nrallier\nralliers\nrallies\nralline\nrally\nrallye\nrallyes\nrallying\nrallyings\nrallyist\nrallyists\nralph\nralphed\nralphing\nralphs\nram\nramate\nramble\nrambled\nrambler\nramblers\nrambles\nrambling\nramblingly\nramblings\nrambouillet\nrambouillets\nrambunctious\nrambunctiously\nrambunctiousness\nrambunctiousnesses\nrambutan\nrambutans\nramee\nramees\nramekin\nramekins\nramen\nramens\nramenta\nramentum\nramequin\nramequins\nramet\nramets\nrami\nramie\nramies\nramification\nramifications\nramified\nramifies\nramiform\nramify\nramifying\nramilie\nramilies\nramillie\nramillies\nramjet\nramjets\nrammed\nrammer\nrammers\nrammier\nrammiest\nramming\nrammish\nrammy\nramose\nramosely\nramosities\nramosity\nramous\nramp\nrampage\nrampaged\nrampageous\nrampageously\nrampageousness\nrampageousnesses\nrampager\nrampagers\nrampages\nrampaging\nrampancies\nrampancy\nrampant\nrampantly\nrampart\nramparted\nramparting\nramparts\nramped\nrampike\nrampikes\nramping\nrampion\nrampions\nrampole\nrampoles\nramps\nramrod\nramrodded\nramrodding\nramrods\nrams\nramshackle\nramshorn\nramshorns\nramson\nramsons\nramtil\nramtils\nramulose\nramulous\nramus\nran\nrance\nrances\nranch\nranched\nrancher\nranchero\nrancheros\nranchers\nranches\nranching\nranchman\nranchmen\nrancho\nranchos\nrancid\nrancidities\nrancidity\nrancidly\nrancidness\nrancidnesses\nrancor\nrancored\nrancorous\nrancorously\nrancors\nrancour\nrancours\nrand\nrandan\nrandans\nrandier\nrandies\nrandiest\nrandom\nrandomization\nrandomizations\nrandomize\nrandomized\nrandomizer\nrandomizers\nrandomizes\nrandomizing\nrandomly\nrandomness\nrandomnesses\nrandoms\nrands\nrandy\nranee\nranees\nrang\nrange\nranged\nrangeland\nrangelands\nranger\nrangers\nranges\nrangier\nrangiest\nranginess\nranginesses\nranging\nrangy\nrani\nranid\nranids\nranis\nrank\nranked\nranker\nrankers\nrankest\nranking\nrankings\nrankish\nrankle\nrankled\nrankles\nrankling\nrankly\nrankness\nranknesses\nranks\nranpike\nranpikes\nransack\nransacked\nransacker\nransackers\nransacking\nransacks\nransom\nransomed\nransomer\nransomers\nransoming\nransoms\nrant\nranted\nranter\nranters\nranting\nrantingly\nrants\nranula\nranulae\nranulas\nranunculi\nranunculus\nranunculuses\nrap\nrapacious\nrapaciously\nrapaciousness\nrapaciousnesses\nrapacities\nrapacity\nrape\nraped\nraper\nrapers\nrapes\nrapeseed\nrapeseeds\nraphae\nraphe\nraphes\nraphia\nraphias\nraphide\nraphides\nraphis\nrapid\nrapider\nrapidest\nrapidities\nrapidity\nrapidly\nrapidness\nrapidnesses\nrapids\nrapier\nrapiered\nrapiers\nrapine\nrapines\nraping\nrapini\nrapinis\nrapist\nrapists\nrapparee\nrapparees\nrapped\nrappee\nrappees\nrappel\nrappeled\nrappeling\nrappelled\nrappelling\nrappels\nrappen\nrapper\nrappers\nrapping\nrappini\nrappinis\nrapport\nrapporteur\nrapporteurs\nrapports\nrapprochement\nrapprochements\nraps\nrapscallion\nrapscallions\nrapt\nraptly\nraptness\nraptnesses\nraptor\nraptorial\nraptors\nrapture\nraptured\nraptures\nrapturing\nrapturous\nrapturously\nrapturousness\nrapturousnesses\nrare\nrarebit\nrarebits\nrared\nrarefaction\nrarefactional\nrarefactions\nrarefied\nrarefier\nrarefiers\nrarefies\nrarefy\nrarefying\nrarely\nrareness\nrarenesses\nrarer\nrareripe\nrareripes\nrares\nrarest\nrarified\nrarifies\nrarify\nrarifying\nraring\nrarities\nrarity\nras\nrasbora\nrasboras\nrascal\nrascalities\nrascality\nrascally\nrascals\nrase\nrased\nraser\nrasers\nrases\nrash\nrasher\nrashers\nrashes\nrashest\nrashlike\nrashly\nrashness\nrashnesses\nrasing\nrasorial\nrasp\nraspberries\nraspberry\nrasped\nrasper\nraspers\nraspier\nraspiest\nrasping\nraspingly\nraspish\nrasps\nraspy\nrassle\nrassled\nrassles\nrassling\nraster\nrasters\nrasure\nrasures\nrat\nratable\nratably\nratafee\nratafees\nratafia\nratafias\nratal\nratals\nratan\nratanies\nratans\nratany\nrataplan\nrataplanned\nrataplanning\nrataplans\nratatat\nratatats\nratatouille\nratatouilles\nratbag\nratbags\nratch\nratches\nratchet\nratcheted\nratcheting\nratchets\nrate\nrateable\nrateably\nrated\nratel\nratels\nratemeter\nratemeters\nratepayer\nratepayers\nrater\nraters\nrates\nratfink\nratfinks\nratfish\nratfishes\nrath\nrathe\nrather\nrathole\nratholes\nrathskeller\nrathskellers\nraticide\nraticides\nratification\nratifications\nratified\nratifier\nratifiers\nratifies\nratify\nratifying\nratine\nratines\nrating\nratings\nratio\nratiocinate\nratiocinated\nratiocinates\nratiocinating\nratiocination\nratiocinations\nratiocinative\nratiocinator\nratiocinators\nration\nrational\nrationale\nrationales\nrationalise\nrationalised\nrationalises\nrationalising\nrationalism\nrationalisms\nrationalist\nrationalistic\nrationalistically\nrationalists\nrationalities\nrationality\nrationalizable\nrationalization\nrationalizations\nrationalize\nrationalized\nrationalizer\nrationalizers\nrationalizes\nrationalizing\nrationally\nrationalness\nrationalnesses\nrationals\nrationed\nrationing\nrations\nratios\nratite\nratites\nratlike\nratlin\nratline\nratlines\nratlins\nrato\nratoon\nratooned\nratooner\nratooners\nratooning\nratoons\nratos\nrats\nratsbane\nratsbanes\nrattail\nrattails\nrattan\nrattans\nratted\nratteen\nratteens\nratten\nrattened\nrattener\nratteners\nrattening\nrattens\nratter\nratters\nrattier\nrattiest\nratting\nrattish\nrattle\nrattlebrain\nrattlebrained\nrattlebrains\nrattled\nrattler\nrattlers\nrattles\nrattlesnake\nrattlesnakes\nrattletrap\nrattletraps\nrattling\nrattlingly\nrattlings\nrattly\nratton\nrattons\nrattoon\nrattooned\nrattooning\nrattoons\nrattrap\nrattraps\nratty\nraucities\nraucity\nraucous\nraucously\nraucousness\nraucousnesses\nraunch\nraunches\nraunchier\nraunchiest\nraunchily\nraunchiness\nraunchinesses\nraunchy\nrauwolfia\nrauwolfias\nravage\nravaged\nravagement\nravagements\nravager\nravagers\nravages\nravaging\nrave\nraved\nravel\nraveled\nraveler\nravelers\nravelin\nraveling\nravelings\nravelins\nravelled\nraveller\nravellers\nravelling\nravellings\nravelly\nravelment\nravelments\nravels\nraven\nravened\nravener\nraveners\nravening\nravenings\nravenous\nravenously\nravenousness\nravenousnesses\nravens\nraver\nravers\nraves\nravigote\nravigotes\nravin\nravine\nravined\nravines\nraving\nravingly\nravings\nravining\nravins\nravioli\nraviolis\nravish\nravished\nravisher\nravishers\nravishes\nravishing\nravishingly\nravishment\nravishments\nraw\nrawboned\nrawer\nrawest\nrawhide\nrawhided\nrawhides\nrawhiding\nrawin\nrawins\nrawinsonde\nrawinsondes\nrawish\nrawly\nrawness\nrawnesses\nraws\nrax\nraxed\nraxes\nraxing\nray\nraya\nrayah\nrayahs\nrayas\nrayed\nraygrass\nraygrasses\nraying\nrayless\nraylessness\nraylessnesses\nraylike\nrayon\nrayons\nrays\nraze\nrazed\nrazee\nrazeed\nrazeeing\nrazees\nrazer\nrazers\nrazes\nrazing\nrazor\nrazorback\nrazorbacks\nrazorbill\nrazorbills\nrazored\nrazoring\nrazors\nrazz\nrazzamatazz\nrazzamatazzes\nrazzed\nrazzes\nrazzing\nrazzmatazz\nrazzmatazzes\nre\nreabsorb\nreabsorbed\nreabsorbing\nreabsorbs\nreaccede\nreacceded\nreaccedes\nreacceding\nreaccelerate\nreaccelerated\nreaccelerates\nreaccelerating\nreaccent\nreaccented\nreaccenting\nreaccents\nreaccept\nreaccepted\nreaccepting\nreaccepts\nreaccession\nreaccessions\nreacclimatize\nreacclimatized\nreacclimatizes\nreacclimatizing\nreaccredit\nreaccreditation\nreaccreditations\nreaccredited\nreaccrediting\nreaccredits\nreaccuse\nreaccused\nreaccuses\nreaccusing\nreach\nreachable\nreached\nreacher\nreachers\nreaches\nreaching\nreacquaint\nreacquainted\nreacquainting\nreacquaints\nreacquire\nreacquired\nreacquires\nreacquiring\nreacquisition\nreacquisitions\nreact\nreactance\nreactances\nreactant\nreactants\nreacted\nreacting\nreaction\nreactionaries\nreactionary\nreactionaryism\nreactionaryisms\nreactions\nreactivate\nreactivated\nreactivates\nreactivating\nreactivation\nreactivations\nreactive\nreactively\nreactiveness\nreactivenesses\nreactivities\nreactivity\nreactor\nreactors\nreacts\nread\nreadabilities\nreadability\nreadable\nreadableness\nreadablenesses\nreadably\nreadapt\nreadapted\nreadapting\nreadapts\nreadd\nreadded\nreaddict\nreaddicted\nreaddicting\nreaddicts\nreadding\nreaddress\nreaddressed\nreaddresses\nreaddressing\nreadds\nreader\nreaderly\nreaders\nreadership\nreaderships\nreadied\nreadier\nreadies\nreadiest\nreadily\nreadiness\nreadinesses\nreading\nreadings\nreadjust\nreadjustable\nreadjusted\nreadjusting\nreadjustment\nreadjustments\nreadjusts\nreadmission\nreadmissions\nreadmit\nreadmits\nreadmitted\nreadmitting\nreadopt\nreadopted\nreadopting\nreadopts\nreadorn\nreadorned\nreadorning\nreadorns\nreadout\nreadouts\nreads\nready\nreadying\nreadymade\nreadymades\nreaffirm\nreaffirmation\nreaffirmations\nreaffirmed\nreaffirming\nreaffirms\nreaffix\nreaffixed\nreaffixes\nreaffixing\nreafforest\nreafforestation\nreafforestations\nreafforested\nreafforesting\nreafforests\nreagent\nreagents\nreaggregate\nreaggregated\nreaggregates\nreaggregating\nreaggregation\nreaggregations\nreagin\nreaginic\nreagins\nreal\nrealer\nreales\nrealest\nrealgar\nrealgars\nrealia\nrealign\nrealigned\nrealigning\nrealignment\nrealignments\nrealigns\nrealise\nrealised\nrealiser\nrealisers\nrealises\nrealising\nrealism\nrealisms\nrealist\nrealistic\nrealistically\nrealists\nrealities\nreality\nrealizable\nrealization\nrealizations\nrealize\nrealized\nrealizer\nrealizers\nrealizes\nrealizing\nreallocate\nreallocated\nreallocates\nreallocating\nreallocation\nreallocations\nreallot\nreallots\nreallotted\nreallotting\nreally\nrealm\nrealms\nrealness\nrealnesses\nrealpolitik\nrealpolitiks\nreals\nrealter\nrealtered\nrealtering\nrealters\nrealties\nrealtime\nrealtor\nrealtors\nrealty\nream\nreamed\nreamer\nreamers\nreaming\nreams\nreanalyses\nreanalysis\nreanalyze\nreanalyzed\nreanalyzes\nreanalyzing\nreanimate\nreanimated\nreanimates\nreanimating\nreanimation\nreanimations\nreannex\nreannexation\nreannexations\nreannexed\nreannexes\nreannexing\nreanoint\nreanointed\nreanointing\nreanoints\nreap\nreapable\nreaped\nreaper\nreapers\nreaphook\nreaphooks\nreaping\nreappear\nreappearance\nreappearances\nreappeared\nreappearing\nreappears\nreapplication\nreapplications\nreapplied\nreapplies\nreapply\nreapplying\nreappoint\nreappointed\nreappointing\nreappointment\nreappointments\nreappoints\nreapportion\nreapportioned\nreapportioning\nreapportionment\nreapportionments\nreapportions\nreappraisal\nreappraisals\nreappraise\nreappraised\nreappraises\nreappraising\nreappropriate\nreappropriated\nreappropriates\nreappropriating\nreapprove\nreapproved\nreapproves\nreapproving\nreaps\nrear\nreared\nrearer\nrearers\nrearguard\nreargue\nreargued\nreargues\nrearguing\nreargument\nrearguments\nrearing\nrearm\nrearmament\nrearmaments\nrearmed\nrearmice\nrearming\nrearmost\nrearmouse\nrearms\nrearousal\nrearousals\nrearouse\nrearoused\nrearouses\nrearousing\nrearrange\nrearranged\nrearrangement\nrearrangements\nrearranges\nrearranging\nrearrest\nrearrested\nrearresting\nrearrests\nrears\nrearticulate\nrearticulated\nrearticulates\nrearticulating\nrearward\nrearwards\nreascend\nreascended\nreascending\nreascends\nreascent\nreascents\nreason\nreasonabilities\nreasonability\nreasonable\nreasonableness\nreasonablenesses\nreasonably\nreasoned\nreasoner\nreasoners\nreasoning\nreasonings\nreasonless\nreasonlessly\nreasons\nreassail\nreassailed\nreassailing\nreassails\nreassemblage\nreassemblages\nreassemble\nreassembled\nreassembles\nreassemblies\nreassembling\nreassembly\nreassert\nreasserted\nreasserting\nreassertion\nreassertions\nreasserts\nreassess\nreassessed\nreassesses\nreassessing\nreassessment\nreassessments\nreassign\nreassigned\nreassigning\nreassignment\nreassignments\nreassigns\nreassort\nreassorted\nreassorting\nreassorts\nreassume\nreassumed\nreassumes\nreassuming\nreassumption\nreassumptions\nreassurance\nreassurances\nreassure\nreassured\nreassures\nreassuring\nreassuringly\nreata\nreatas\nreattach\nreattached\nreattaches\nreattaching\nreattachment\nreattachments\nreattack\nreattacked\nreattacking\nreattacks\nreattain\nreattained\nreattaining\nreattains\nreattempt\nreattempted\nreattempting\nreattempts\nreattribute\nreattributed\nreattributes\nreattributing\nreattribution\nreattributions\nreauthorization\nreauthorizations\nreauthorize\nreauthorized\nreauthorizes\nreauthorizing\nreavail\nreavailed\nreavailing\nreavails\nreave\nreaved\nreaver\nreavers\nreaves\nreaving\nreavow\nreavowed\nreavowing\nreavows\nreawake\nreawaked\nreawaken\nreawakened\nreawakening\nreawakens\nreawakes\nreawaking\nreawoke\nreawoken\nreb\nrebait\nrebaited\nrebaiting\nrebaits\nrebalance\nrebalanced\nrebalances\nrebalancing\nrebaptism\nrebaptisms\nrebaptize\nrebaptized\nrebaptizes\nrebaptizing\nrebar\nrebarbative\nrebarbatively\nrebars\nrebate\nrebated\nrebater\nrebaters\nrebates\nrebating\nrebato\nrebatos\nrebbe\nrebbes\nrebec\nrebeck\nrebecks\nrebecs\nrebegan\nrebegin\nrebeginning\nrebegins\nrebegun\nrebel\nrebeldom\nrebeldoms\nrebelled\nrebelling\nrebellion\nrebellions\nrebellious\nrebelliously\nrebelliousness\nrebelliousnesses\nrebels\nrebid\nrebidden\nrebidding\nrebids\nrebill\nrebilled\nrebilling\nrebills\nrebind\nrebinding\nrebinds\nrebirth\nrebirths\nreblend\nreblended\nreblending\nreblends\nrebloom\nrebloomed\nreblooming\nreblooms\nreboant\nreboard\nreboarded\nreboarding\nreboards\nrebodied\nrebodies\nrebody\nrebodying\nreboil\nreboiled\nreboiling\nreboils\nrebook\nrebooked\nrebooking\nrebooks\nreboot\nrebooted\nrebooting\nreboots\nrebop\nrebops\nrebore\nrebored\nrebores\nreboring\nreborn\nrebottle\nrebottled\nrebottles\nrebottling\nrebought\nrebound\nrebounded\nrebounder\nrebounders\nrebounding\nrebounds\nrebozo\nrebozos\nrebranch\nrebranched\nrebranches\nrebranching\nrebred\nrebreed\nrebreeding\nrebreeds\nrebroadcast\nrebroadcasting\nrebroadcasts\nrebs\nrebuff\nrebuffed\nrebuffing\nrebuffs\nrebuild\nrebuilded\nrebuilding\nrebuilds\nrebuilt\nrebuke\nrebuked\nrebuker\nrebukers\nrebukes\nrebuking\nreburial\nreburials\nreburied\nreburies\nrebury\nreburying\nrebus\nrebuses\nrebut\nrebuts\nrebuttable\nrebuttal\nrebuttals\nrebutted\nrebutter\nrebutters\nrebutting\nrebutton\nrebuttoned\nrebuttoning\nrebuttons\nrebuy\nrebuying\nrebuys\nrec\nrecalcitrance\nrecalcitrances\nrecalcitrancies\nrecalcitrancy\nrecalcitrant\nrecalcitrants\nrecalculate\nrecalculated\nrecalculates\nrecalculating\nrecalculation\nrecalculations\nrecalibrate\nrecalibrated\nrecalibrates\nrecalibrating\nrecalibration\nrecalibrations\nrecall\nrecallabilities\nrecallability\nrecallable\nrecalled\nrecaller\nrecallers\nrecalling\nrecalls\nrecamier\nrecamiers\nrecanalization\nrecanalizations\nrecanalize\nrecanalized\nrecanalizes\nrecanalizing\nrecane\nrecaned\nrecanes\nrecaning\nrecant\nrecantation\nrecantations\nrecanted\nrecanter\nrecanters\nrecanting\nrecants\nrecap\nrecapitalization\nrecapitalizations\nrecapitalize\nrecapitalized\nrecapitalizes\nrecapitalizing\nrecapitulate\nrecapitulated\nrecapitulates\nrecapitulating\nrecapitulation\nrecapitulations\nrecappable\nrecapped\nrecapping\nrecaps\nrecapture\nrecaptured\nrecaptures\nrecapturing\nrecarpet\nrecarpeted\nrecarpeting\nrecarpets\nrecarried\nrecarries\nrecarry\nrecarrying\nrecast\nrecasting\nrecasts\nrecce\nrecces\nrecede\nreceded\nrecedes\nreceding\nreceipt\nreceipted\nreceipting\nreceipts\nreceivable\nreceivables\nreceive\nreceived\nreceiver\nreceivers\nreceivership\nreceiverships\nreceives\nreceiving\nrecencies\nrecency\nrecension\nrecensions\nrecent\nrecenter\nrecentest\nrecently\nrecentness\nrecentnesses\nrecentralization\nrecentralizations\nrecentrifuge\nrecentrifuged\nrecentrifuges\nrecentrifuging\nrecept\nreceptacle\nreceptacles\nreception\nreceptionist\nreceptionists\nreceptions\nreceptive\nreceptively\nreceptiveness\nreceptivenesses\nreceptivities\nreceptivity\nreceptor\nreceptors\nrecepts\nrecertification\nrecertifications\nrecertified\nrecertifies\nrecertify\nrecertifying\nrecess\nrecessed\nrecesses\nrecessing\nrecession\nrecessional\nrecessionals\nrecessionary\nrecessions\nrecessive\nrecessively\nrecessiveness\nrecessivenesses\nrecessives\nrechallenge\nrechallenged\nrechallenges\nrechallenging\nrechange\nrechanged\nrechanges\nrechanging\nrechannel\nrechanneled\nrechanneling\nrechannelled\nrechannelling\nrechannels\nrecharge\nrechargeable\nrecharged\nrecharger\nrechargers\nrecharges\nrecharging\nrechart\nrecharted\nrecharter\nrechartered\nrechartering\nrecharters\nrecharting\nrecharts\nrechauffe\nrechauffes\nrecheat\nrecheats\nrecheck\nrechecked\nrechecking\nrechecks\nrecherche\nrechew\nrechewed\nrechewing\nrechews\nrechoose\nrechooses\nrechoosing\nrechoreograph\nrechoreographed\nrechoreographing\nrechoreographs\nrechose\nrechosen\nrechristen\nrechristened\nrechristening\nrechristens\nrechromatograph\nrechromatographed\nrechromatographies\nrechromatographing\nrechromatographs\nrechromatography\nrecidivism\nrecidivisms\nrecidivist\nrecidivistic\nrecidivists\nrecipe\nrecipes\nrecipient\nrecipients\nreciprocal\nreciprocally\nreciprocals\nreciprocate\nreciprocated\nreciprocates\nreciprocating\nreciprocation\nreciprocations\nreciprocative\nreciprocator\nreciprocators\nreciprocities\nreciprocity\nrecircle\nrecircled\nrecircles\nrecircling\nrecirculate\nrecirculated\nrecirculates\nrecirculating\nrecirculation\nrecirculations\nrecision\nrecisions\nrecital\nrecitalist\nrecitalists\nrecitals\nrecitation\nrecitations\nrecitative\nrecitatives\nrecitativi\nrecitativo\nrecitativos\nrecite\nrecited\nreciter\nreciters\nrecites\nreciting\nreck\nrecked\nrecking\nreckless\nrecklessly\nrecklessness\nrecklessnesses\nreckon\nreckoned\nreckoner\nreckoners\nreckoning\nreckonings\nreckons\nrecks\nreclad\nreclaim\nreclaimable\nreclaimed\nreclaiming\nreclaims\nreclamation\nreclamations\nreclame\nreclames\nreclasp\nreclasped\nreclasping\nreclasps\nreclassification\nreclassifications\nreclassified\nreclassifies\nreclassify\nreclassifying\nreclean\nrecleaned\nrecleaning\nrecleans\nrecline\nreclined\nrecliner\nrecliners\nreclines\nreclining\nreclosable\nreclothe\nreclothed\nreclothes\nreclothing\nrecluse\nrecluses\nreclusion\nreclusions\nreclusive\nreclusively\nreclusiveness\nreclusivenesses\nrecoal\nrecoaled\nrecoaling\nrecoals\nrecock\nrecocked\nrecocking\nrecocks\nrecode\nrecoded\nrecodes\nrecodification\nrecodifications\nrecodified\nrecodifies\nrecodify\nrecodifying\nrecoding\nrecognise\nrecognised\nrecognises\nrecognising\nrecognition\nrecognitions\nrecognizabilities\nrecognizability\nrecognizable\nrecognizably\nrecognizance\nrecognizances\nrecognize\nrecognized\nrecognizer\nrecognizers\nrecognizes\nrecognizing\nrecoil\nrecoiled\nrecoiler\nrecoilers\nrecoiling\nrecoilless\nrecoils\nrecoin\nrecoinage\nrecoinages\nrecoined\nrecoining\nrecoins\nrecollect\nrecollected\nrecollecting\nrecollection\nrecollections\nrecollects\nrecolonization\nrecolonizations\nrecolonize\nrecolonized\nrecolonizes\nrecolonizing\nrecolor\nrecolored\nrecoloring\nrecolors\nrecomb\nrecombed\nrecombinant\nrecombinants\nrecombination\nrecombinational\nrecombinations\nrecombine\nrecombined\nrecombines\nrecombing\nrecombining\nrecombs\nrecommence\nrecommenced\nrecommencement\nrecommencements\nrecommences\nrecommencing\nrecommend\nrecommendable\nrecommendation\nrecommendations\nrecommendatory\nrecommended\nrecommending\nrecommends\nrecommission\nrecommissioned\nrecommissioning\nrecommissions\nrecommit\nrecommitment\nrecommitments\nrecommits\nrecommittal\nrecommittals\nrecommitted\nrecommitting\nrecompense\nrecompensed\nrecompenses\nrecompensing\nrecompilation\nrecompilations\nrecompile\nrecompiled\nrecompiles\nrecompiling\nrecompose\nrecomposed\nrecomposes\nrecomposing\nrecomposition\nrecompositions\nrecomputation\nrecomputations\nrecompute\nrecomputed\nrecomputes\nrecomputing\nrecon\nreconceive\nreconceived\nreconceives\nreconceiving\nreconcentrate\nreconcentrated\nreconcentrates\nreconcentrating\nreconcentration\nreconcentrations\nreconception\nreconceptions\nreconceptualization\nreconceptualizations\nreconceptualize\nreconceptualized\nreconceptualizes\nreconceptualizing\nreconcilabilities\nreconcilability\nreconcilable\nreconcile\nreconciled\nreconcilement\nreconcilements\nreconciler\nreconcilers\nreconciles\nreconciliation\nreconciliations\nreconciliatory\nreconciling\nrecondense\nrecondensed\nrecondenses\nrecondensing\nrecondite\nreconditely\nreconditeness\nreconditenesses\nrecondition\nreconditioned\nreconditioning\nreconditions\nreconfigurable\nreconfiguration\nreconfigurations\nreconfigure\nreconfigured\nreconfigures\nreconfiguring\nreconfirm\nreconfirmation\nreconfirmations\nreconfirmed\nreconfirming\nreconfirms\nreconnaissance\nreconnaissances\nreconnect\nreconnected\nreconnecting\nreconnection\nreconnections\nreconnects\nreconnoiter\nreconnoitered\nreconnoitering\nreconnoiters\nreconnoitre\nreconnoitred\nreconnoitres\nreconnoitring\nreconquer\nreconquered\nreconquering\nreconquers\nreconquest\nreconquests\nrecons\nreconsecrate\nreconsecrated\nreconsecrates\nreconsecrating\nreconsecration\nreconsecrations\nreconsider\nreconsideration\nreconsiderations\nreconsidered\nreconsidering\nreconsiders\nreconsolidate\nreconsolidated\nreconsolidates\nreconsolidating\nreconstitute\nreconstituted\nreconstitutes\nreconstituting\nreconstitution\nreconstitutions\nreconstruct\nreconstructed\nreconstructible\nreconstructing\nreconstruction\nreconstructionism\nreconstructionisms\nreconstructionist\nreconstructionists\nreconstructions\nreconstructive\nreconstructor\nreconstructors\nreconstructs\nrecontact\nrecontacted\nrecontacting\nrecontacts\nrecontaminate\nrecontaminated\nrecontaminates\nrecontaminating\nrecontamination\nrecontaminations\nrecontextualize\nrecontextualized\nrecontextualizes\nrecontextualizing\nrecontour\nrecontoured\nrecontouring\nrecontours\nreconvene\nreconvened\nreconvenes\nreconvening\nreconversion\nreconversions\nreconvert\nreconverted\nreconverting\nreconverts\nreconvey\nreconveyance\nreconveyances\nreconveyed\nreconveying\nreconveys\nreconvict\nreconvicted\nreconvicting\nreconviction\nreconvictions\nreconvicts\nreconvince\nreconvinced\nreconvinces\nreconvincing\nrecook\nrecooked\nrecooking\nrecooks\nrecopied\nrecopies\nrecopy\nrecopying\nrecord\nrecordable\nrecordation\nrecordations\nrecorded\nrecorder\nrecorders\nrecording\nrecordings\nrecordist\nrecordists\nrecords\nrecork\nrecorked\nrecorking\nrecorks\nrecount\nrecounted\nrecounter\nrecounters\nrecounting\nrecounts\nrecoup\nrecoupable\nrecoupe\nrecouped\nrecouping\nrecouple\nrecoupled\nrecouples\nrecoupling\nrecoupment\nrecoupments\nrecoups\nrecourse\nrecourses\nrecover\nrecoverabilities\nrecoverability\nrecoverable\nrecovered\nrecoverer\nrecoverers\nrecoveries\nrecovering\nrecovers\nrecovery\nrecrate\nrecrated\nrecrates\nrecrating\nrecreant\nrecreants\nrecreate\nrecreated\nrecreates\nrecreating\nrecreation\nrecreational\nrecreationist\nrecreationists\nrecreations\nrecreative\nrecriminate\nrecriminated\nrecriminates\nrecriminating\nrecrimination\nrecriminations\nrecriminative\nrecriminatory\nrecross\nrecrossed\nrecrosses\nrecrossing\nrecrown\nrecrowned\nrecrowning\nrecrowns\nrecrudesce\nrecrudesced\nrecrudescence\nrecrudescences\nrecrudescent\nrecrudesces\nrecrudescing\nrecruit\nrecruited\nrecruiter\nrecruiters\nrecruiting\nrecruitment\nrecruitments\nrecruits\nrecrystallization\nrecrystallizations\nrecrystallize\nrecrystallized\nrecrystallizes\nrecrystallizing\nrecs\nrecta\nrectal\nrectally\nrectangle\nrectangles\nrectangular\nrectangularities\nrectangularity\nrectangularly\nrecti\nrectifiabilities\nrectifiability\nrectifiable\nrectification\nrectifications\nrectified\nrectifier\nrectifiers\nrectifies\nrectify\nrectifying\nrectilinear\nrectilinearly\nrectitude\nrectitudes\nrectitudinous\nrecto\nrector\nrectorate\nrectorates\nrectorial\nrectories\nrectors\nrectorship\nrectorships\nrectory\nrectos\nrectrices\nrectrix\nrectum\nrectums\nrectus\nrecultivate\nrecultivated\nrecultivates\nrecultivating\nrecumbencies\nrecumbency\nrecumbent\nrecuperate\nrecuperated\nrecuperates\nrecuperating\nrecuperation\nrecuperations\nrecuperative\nrecur\nrecurred\nrecurrence\nrecurrences\nrecurrent\nrecurrently\nrecurring\nrecurs\nrecursion\nrecursions\nrecursive\nrecursively\nrecursiveness\nrecursivenesses\nrecurve\nrecurved\nrecurves\nrecurving\nrecusal\nrecusals\nrecusancies\nrecusancy\nrecusant\nrecusants\nrecuse\nrecused\nrecuses\nrecusing\nrecut\nrecuts\nrecutting\nrecyclable\nrecyclables\nrecycle\nrecycled\nrecycler\nrecyclers\nrecycles\nrecycling\nred\nredact\nredacted\nredacting\nredaction\nredactional\nredactions\nredactor\nredactors\nredacts\nredamage\nredamaged\nredamages\nredamaging\nredan\nredans\nredargue\nredargued\nredargues\nredarguing\nredate\nredated\nredates\nredating\nredbait\nredbaited\nredbaiting\nredbaits\nredbay\nredbays\nredbird\nredbirds\nredbone\nredbones\nredbreast\nredbreasts\nredbrick\nredbricks\nredbud\nredbuds\nredbug\nredbugs\nredcap\nredcaps\nredcoat\nredcoats\nredd\nredded\nredden\nreddened\nreddening\nreddens\nredder\nredders\nreddest\nredding\nreddish\nreddishness\nreddishnesses\nreddle\nreddled\nreddles\nreddling\nredds\nrede\nredear\nredears\nredecide\nredecided\nredecides\nredeciding\nredecorate\nredecorated\nredecorates\nredecorating\nredecoration\nredecorations\nredecorator\nredecorators\nreded\nrededicate\nrededicated\nrededicates\nrededicating\nrededication\nrededications\nredeem\nredeemable\nredeemed\nredeemer\nredeemers\nredeeming\nredeems\nredefeat\nredefeated\nredefeating\nredefeats\nredefect\nredefected\nredefecting\nredefects\nredefied\nredefies\nredefine\nredefined\nredefines\nredefining\nredefinition\nredefinitions\nredefy\nredefying\nredeliver\nredelivered\nredeliveries\nredelivering\nredelivers\nredelivery\nredemand\nredemanded\nredemanding\nredemands\nredemption\nredemptioner\nredemptioners\nredemptions\nredemptive\nredemptory\nredenied\nredenies\nredeny\nredenying\nredeploy\nredeployed\nredeploying\nredeployment\nredeployments\nredeploys\nredeposit\nredeposited\nredepositing\nredeposits\nredes\nredescribe\nredescribed\nredescribes\nredescribing\nredescription\nredescriptions\nredesign\nredesigned\nredesigning\nredesigns\nredetermination\nredeterminations\nredetermine\nredetermined\nredetermines\nredetermining\nredevelop\nredeveloped\nredeveloper\nredevelopers\nredeveloping\nredevelopment\nredevelopments\nredevelops\nredeye\nredeyes\nredfin\nredfins\nredfish\nredfishes\nredhead\nredheaded\nredheads\nredhorse\nredhorses\nredia\nrediae\nredial\nredialed\nredialing\nredialled\nredialling\nredials\nredias\nredid\nredigest\nredigested\nredigesting\nredigestion\nredigestions\nredigests\nreding\nredingote\nredingotes\nredintegrate\nredintegrated\nredintegrates\nredintegrating\nredintegration\nredintegrations\nredintegrative\nredip\nredipped\nredipping\nredips\nredipt\nredirect\nredirected\nredirecting\nredirection\nredirections\nredirects\nrediscount\nrediscountable\nrediscounted\nrediscounting\nrediscounts\nrediscover\nrediscovered\nrediscoveries\nrediscovering\nrediscovers\nrediscovery\nrediscuss\nrediscussed\nrediscusses\nrediscussing\nredisplay\nredisplayed\nredisplaying\nredisplays\nredispose\nredisposed\nredisposes\nredisposing\nredisposition\nredispositions\nredissolve\nredissolved\nredissolves\nredissolving\nredistill\nredistillation\nredistillations\nredistilled\nredistilling\nredistills\nredistribute\nredistributed\nredistributes\nredistributing\nredistribution\nredistributional\nredistributionist\nredistributionists\nredistributions\nredistributive\nredistrict\nredistricted\nredistricting\nredistricts\nredivide\nredivided\nredivides\nredividing\nredivision\nredivisions\nredivivus\nredleg\nredlegs\nredline\nredlined\nredlines\nredlining\nredly\nredneck\nrednecked\nrednecks\nredness\nrednesses\nredo\nredock\nredocked\nredocking\nredocks\nredoes\nredoing\nredolence\nredolences\nredolent\nredolently\nredon\nredone\nredonned\nredonning\nredons\nredos\nredouble\nredoubled\nredoubles\nredoubling\nredoubt\nredoubtable\nredoubtably\nredoubts\nredound\nredounded\nredounding\nredounds\nredout\nredouts\nredowa\nredowas\nredox\nredoxes\nredpoll\nredpolls\nredraft\nredrafted\nredrafting\nredrafts\nredraw\nredrawer\nredrawers\nredrawing\nredrawn\nredraws\nredream\nredreamed\nredreaming\nredreams\nredreamt\nredress\nredressed\nredresser\nredressers\nredresses\nredressing\nredrew\nredried\nredries\nredrill\nredrilled\nredrilling\nredrills\nredrive\nredriven\nredrives\nredriving\nredroot\nredroots\nredrove\nredry\nredrying\nreds\nredshank\nredshanks\nredshift\nredshifted\nredshifts\nredshirt\nredshirted\nredshirting\nredshirts\nredskin\nredskins\nredstart\nredstarts\nredtail\nredtails\nredtop\nredtops\nredub\nredubbed\nredubbing\nredubs\nreduce\nreduced\nreducer\nreducers\nreduces\nreducibilities\nreducibility\nreducible\nreducibly\nreducing\nreductant\nreductants\nreductase\nreductases\nreduction\nreductional\nreductionism\nreductionisms\nreductionist\nreductionistic\nreductionists\nreductions\nreductive\nreductively\nreductiveness\nreductivenesses\nreductor\nreductors\nredundancies\nredundancy\nredundant\nredundantly\nreduplicate\nreduplicated\nreduplicates\nreduplicating\nreduplication\nreduplications\nreduplicative\nreduplicatively\nreduviid\nreduviids\nredux\nredware\nredwares\nredwing\nredwings\nredwood\nredwoods\nredye\nredyed\nredyeing\nredyes\nree\nreearn\nreearned\nreearning\nreearns\nreechier\nreechiest\nreecho\nreechoed\nreechoes\nreechoing\nreechy\nreed\nreedbird\nreedbirds\nreedbuck\nreedbucks\nreeded\nreedier\nreediest\nreedified\nreedifies\nreedify\nreedifying\nreedily\nreediness\nreedinesses\nreeding\nreedings\nreedit\nreedited\nreediting\nreedition\nreeditions\nreedits\nreedlike\nreedling\nreedlings\nreedman\nreedmen\nreeds\nreeducate\nreeducated\nreeducates\nreeducating\nreeducation\nreeducations\nreeducative\nreedy\nreef\nreefable\nreefed\nreefer\nreefers\nreefier\nreefiest\nreefing\nreefs\nreefy\nreeject\nreejected\nreejecting\nreejects\nreek\nreeked\nreeker\nreekers\nreekier\nreekiest\nreeking\nreeks\nreeky\nreel\nreelable\nreelect\nreelected\nreelecting\nreelection\nreelections\nreelects\nreeled\nreeler\nreelers\nreeligibilities\nreeligibility\nreeligible\nreeling\nreels\nreembark\nreembarked\nreembarking\nreembarks\nreembodied\nreembodies\nreembody\nreembodying\nreembroider\nreembroidered\nreembroidering\nreembroiders\nreemerge\nreemerged\nreemergence\nreemergences\nreemerges\nreemerging\nreemission\nreemissions\nreemit\nreemits\nreemitted\nreemitting\nreemphases\nreemphasis\nreemphasize\nreemphasized\nreemphasizes\nreemphasizing\nreemploy\nreemployed\nreemploying\nreemployment\nreemployments\nreemploys\nreenact\nreenacted\nreenacting\nreenactment\nreenactments\nreenacts\nreencounter\nreencountered\nreencountering\nreencounters\nreendow\nreendowed\nreendowing\nreendows\nreenergize\nreenergized\nreenergizes\nreenergizing\nreenforce\nreenforced\nreenforces\nreenforcing\nreengage\nreengaged\nreengagement\nreengagements\nreengages\nreengaging\nreengineer\nreengineered\nreengineering\nreengineers\nreengrave\nreengraved\nreengraves\nreengraving\nreenjoy\nreenjoyed\nreenjoying\nreenjoys\nreenlist\nreenlisted\nreenlisting\nreenlistment\nreenlistments\nreenlists\nreenroll\nreenrolled\nreenrolling\nreenrolls\nreenter\nreentered\nreentering\nreenters\nreenthrone\nreenthroned\nreenthrones\nreenthroning\nreentrance\nreentrances\nreentrant\nreentrants\nreentries\nreentry\nreequip\nreequipment\nreequipments\nreequipped\nreequipping\nreequips\nreerect\nreerected\nreerecting\nreerects\nrees\nreescalate\nreescalated\nreescalates\nreescalating\nreescalation\nreescalations\nreest\nreestablish\nreestablished\nreestablishes\nreestablishing\nreestablishment\nreestablishments\nreested\nreestimate\nreestimated\nreestimates\nreestimating\nreesting\nreests\nreevaluate\nreevaluated\nreevaluates\nreevaluating\nreevaluation\nreevaluations\nreeve\nreeved\nreeves\nreeving\nreevoke\nreevoked\nreevokes\nreevoking\nreexamination\nreexaminations\nreexamine\nreexamined\nreexamines\nreexamining\nreexpel\nreexpelled\nreexpelling\nreexpels\nreexperience\nreexperienced\nreexperiences\nreexperiencing\nreexplore\nreexplored\nreexplores\nreexploring\nreexport\nreexportation\nreexportations\nreexported\nreexporting\nreexports\nreexpose\nreexposed\nreexposes\nreexposing\nreexposure\nreexposures\nreexpress\nreexpressed\nreexpresses\nreexpressing\nref\nreface\nrefaced\nrefaces\nrefacing\nrefall\nrefallen\nrefalling\nrefalls\nrefashion\nrefashioned\nrefashioning\nrefashions\nrefasten\nrefastened\nrefastening\nrefastens\nrefect\nrefected\nrefecting\nrefection\nrefections\nrefectories\nrefectory\nrefects\nrefed\nrefeed\nrefeeding\nrefeeds\nrefeel\nrefeeling\nrefeels\nrefel\nrefell\nrefelled\nrefelling\nrefels\nrefelt\nrefence\nrefenced\nrefences\nrefencing\nrefer\nreferable\nreferee\nrefereed\nrefereeing\nreferees\nreference\nreferenced\nreferences\nreferencing\nreferenda\nreferendum\nreferendums\nreferent\nreferential\nreferentialities\nreferentiality\nreferentially\nreferents\nreferral\nreferrals\nreferred\nreferrer\nreferrers\nreferring\nrefers\nreffed\nreffing\nrefight\nrefighting\nrefights\nrefigure\nrefigured\nrefigures\nrefiguring\nrefile\nrefiled\nrefiles\nrefiling\nrefill\nrefillable\nrefilled\nrefilling\nrefills\nrefilm\nrefilmed\nrefilming\nrefilms\nrefilter\nrefiltered\nrefiltering\nrefilters\nrefinance\nrefinanced\nrefinances\nrefinancing\nrefind\nrefinding\nrefinds\nrefine\nrefined\nrefinement\nrefinements\nrefiner\nrefineries\nrefiners\nrefinery\nrefines\nrefining\nrefinish\nrefinished\nrefinisher\nrefinishers\nrefinishes\nrefinishing\nrefire\nrefired\nrefires\nrefiring\nrefit\nrefits\nrefitted\nrefitting\nrefix\nrefixed\nrefixes\nrefixing\nreflate\nreflated\nreflates\nreflating\nreflation\nreflationary\nreflations\nreflect\nreflectance\nreflectances\nreflected\nreflecting\nreflection\nreflectional\nreflections\nreflective\nreflectively\nreflectiveness\nreflectivenesses\nreflectivities\nreflectivity\nreflectometer\nreflectometers\nreflectometries\nreflectometry\nreflector\nreflectorize\nreflectorized\nreflectorizes\nreflectorizing\nreflectors\nreflects\nreflet\nreflets\nreflew\nreflex\nreflexed\nreflexes\nreflexing\nreflexion\nreflexions\nreflexive\nreflexively\nreflexiveness\nreflexivenesses\nreflexives\nreflexivities\nreflexivity\nreflexly\nreflexologies\nreflexology\nreflies\nrefloat\nrefloated\nrefloating\nrefloats\nreflood\nreflooded\nreflooding\nrefloods\nreflow\nreflowed\nreflower\nreflowered\nreflowering\nreflowers\nreflowing\nreflown\nreflows\nrefluence\nrefluences\nrefluent\nreflux\nrefluxed\nrefluxes\nrefluxing\nrefly\nreflying\nrefocus\nrefocused\nrefocuses\nrefocusing\nrefocussed\nrefocusses\nrefocussing\nrefold\nrefolded\nrefolding\nrefolds\nreforest\nreforestation\nreforestations\nreforested\nreforesting\nreforests\nreforge\nreforged\nreforges\nreforging\nreform\nreformabilities\nreformability\nreformable\nreformat\nreformate\nreformates\nreformation\nreformational\nreformations\nreformative\nreformatories\nreformatory\nreformats\nreformatted\nreformatting\nreformed\nreformer\nreformers\nreforming\nreformism\nreformisms\nreformist\nreformists\nreforms\nreformulate\nreformulated\nreformulates\nreformulating\nreformulation\nreformulations\nrefortification\nrefortifications\nrefortified\nrefortifies\nrefortify\nrefortifying\nrefought\nrefound\nrefoundation\nrefoundations\nrefounded\nrefounding\nrefounds\nrefract\nrefracted\nrefractile\nrefracting\nrefraction\nrefractions\nrefractive\nrefractively\nrefractiveness\nrefractivenesses\nrefractivities\nrefractivity\nrefractometer\nrefractometers\nrefractometric\nrefractometries\nrefractometry\nrefractor\nrefractories\nrefractorily\nrefractoriness\nrefractorinesses\nrefractors\nrefractory\nrefracts\nrefrain\nrefrained\nrefraining\nrefrainment\nrefrainments\nrefrains\nreframe\nreframed\nreframes\nreframing\nrefrangibilities\nrefrangibility\nrefrangible\nrefrangibleness\nrefrangiblenesses\nrefreeze\nrefreezes\nrefreezing\nrefresh\nrefreshed\nrefreshen\nrefreshened\nrefreshening\nrefreshens\nrefresher\nrefreshers\nrefreshes\nrefreshing\nrefreshingly\nrefreshment\nrefreshments\nrefried\nrefries\nrefrigerant\nrefrigerants\nrefrigerate\nrefrigerated\nrefrigerates\nrefrigerating\nrefrigeration\nrefrigerations\nrefrigerator\nrefrigerators\nrefront\nrefronted\nrefronting\nrefronts\nrefroze\nrefrozen\nrefry\nrefrying\nrefs\nreft\nrefuel\nrefueled\nrefueling\nrefuelled\nrefuelling\nrefuels\nrefuge\nrefuged\nrefugee\nrefugeeism\nrefugeeisms\nrefugees\nrefuges\nrefugia\nrefuging\nrefugium\nrefulgence\nrefulgences\nrefulgent\nrefund\nrefundabilities\nrefundability\nrefundable\nrefunded\nrefunder\nrefunders\nrefunding\nrefunds\nrefurbish\nrefurbished\nrefurbisher\nrefurbishers\nrefurbishes\nrefurbishing\nrefurbishment\nrefurbishments\nrefurnish\nrefurnished\nrefurnishes\nrefurnishing\nrefusal\nrefusals\nrefuse\nrefused\nrefusenik\nrefuseniks\nrefuser\nrefusers\nrefuses\nrefusing\nrefusnik\nrefusniks\nrefutable\nrefutably\nrefutal\nrefutals\nrefutation\nrefutations\nrefute\nrefuted\nrefuter\nrefuters\nrefutes\nrefuting\nreg\nregain\nregained\nregainer\nregainers\nregaining\nregains\nregal\nregale\nregaled\nregaler\nregalers\nregales\nregalia\nregaling\nregalities\nregality\nregally\nregard\nregardant\nregarded\nregardful\nregardfully\nregardfulness\nregardfulnesses\nregarding\nregardless\nregardlessly\nregardlessness\nregardlessnesses\nregards\nregather\nregathered\nregathering\nregathers\nregatta\nregattas\nregauge\nregauged\nregauges\nregauging\nregave\nregear\nregeared\nregearing\nregears\nregelate\nregelated\nregelates\nregelating\nregencies\nregency\nregenerable\nregeneracies\nregeneracy\nregenerate\nregenerated\nregenerately\nregenerateness\nregeneratenesses\nregenerates\nregenerating\nregeneration\nregenerations\nregenerative\nregenerator\nregenerators\nregent\nregental\nregents\nreges\nreggae\nreggaes\nregicidal\nregicide\nregicides\nregild\nregilded\nregilding\nregilds\nregilt\nregime\nregimen\nregimens\nregiment\nregimental\nregimentals\nregimentation\nregimentations\nregimented\nregimenting\nregiments\nregimes\nregina\nreginae\nreginal\nreginas\nregion\nregional\nregionalism\nregionalisms\nregionalist\nregionalistic\nregionalists\nregionalization\nregionalizations\nregionalize\nregionalized\nregionalizes\nregionalizing\nregionally\nregionals\nregions\nregisseur\nregisseurs\nregister\nregisterable\nregistered\nregistering\nregisters\nregistrable\nregistrant\nregistrants\nregistrar\nregistrars\nregistration\nregistrations\nregistries\nregistry\nregius\nregive\nregiven\nregives\nregiving\nreglaze\nreglazed\nreglazes\nreglazing\nreglet\nreglets\nregloss\nreglossed\nreglosses\nreglossing\nreglow\nreglowed\nreglowing\nreglows\nreglue\nreglued\nreglues\nregluing\nregma\nregmata\nregna\nregnal\nregnancies\nregnancy\nregnant\nregnum\nregolith\nregoliths\nregorge\nregorged\nregorges\nregorging\nregosol\nregosols\nregrade\nregraded\nregrades\nregrading\nregraft\nregrafted\nregrafting\nregrafts\nregrant\nregranted\nregranting\nregrants\nregrate\nregrated\nregrates\nregrating\nregreen\nregreened\nregreening\nregreens\nregreet\nregreeted\nregreeting\nregreets\nregress\nregressed\nregresses\nregressing\nregression\nregressions\nregressive\nregressively\nregressiveness\nregressivenesses\nregressivities\nregressivity\nregressor\nregressors\nregret\nregretful\nregretfully\nregretfulness\nregretfulnesses\nregrets\nregrettable\nregrettably\nregretted\nregretter\nregretters\nregretting\nregrew\nregrind\nregrinding\nregrinds\nregroom\nregroomed\nregrooming\nregrooms\nregroove\nregrooved\nregrooves\nregrooving\nreground\nregroup\nregrouped\nregrouping\nregroups\nregrow\nregrowing\nregrown\nregrows\nregrowth\nregrowths\nregs\nregular\nregularities\nregularity\nregularization\nregularizations\nregularize\nregularized\nregularizes\nregularizing\nregularly\nregulars\nregulate\nregulated\nregulates\nregulating\nregulation\nregulations\nregulative\nregulator\nregulators\nregulatory\nreguli\nreguline\nregulus\nreguluses\nregurgitate\nregurgitated\nregurgitates\nregurgitating\nregurgitation\nregurgitations\nrehab\nrehabbed\nrehabber\nrehabbers\nrehabbing\nrehabilitant\nrehabilitants\nrehabilitate\nrehabilitated\nrehabilitates\nrehabilitating\nrehabilitation\nrehabilitations\nrehabilitative\nrehabilitator\nrehabilitators\nrehabs\nrehammer\nrehammered\nrehammering\nrehammers\nrehandle\nrehandled\nrehandles\nrehandling\nrehang\nrehanged\nrehanging\nrehangs\nreharden\nrehardened\nrehardening\nrehardens\nrehash\nrehashed\nrehashes\nrehashing\nrehear\nreheard\nrehearing\nrehearings\nrehears\nrehearsal\nrehearsals\nrehearse\nrehearsed\nrehearser\nrehearsers\nrehearses\nrehearsing\nreheat\nreheated\nreheater\nreheaters\nreheating\nreheats\nreheel\nreheeled\nreheeling\nreheels\nrehem\nrehemmed\nrehemming\nrehems\nrehinge\nrehinged\nrehinges\nrehinging\nrehire\nrehired\nrehires\nrehiring\nrehoboam\nrehoboams\nrehospitalization\nrehospitalizations\nrehospitalize\nrehospitalized\nrehospitalizes\nrehospitalizing\nrehouse\nrehoused\nrehouses\nrehousing\nrehumanize\nrehumanized\nrehumanizes\nrehumanizing\nrehung\nrehydratable\nrehydrate\nrehydrated\nrehydrates\nrehydrating\nrehydration\nrehydrations\nrehypnotize\nrehypnotized\nrehypnotizes\nrehypnotizing\nrei\nreichsmark\nreichsmarks\nreidentified\nreidentifies\nreidentify\nreidentifying\nreif\nreification\nreifications\nreified\nreifier\nreifiers\nreifies\nreifs\nreify\nreifying\nreign\nreigned\nreigning\nreignite\nreignited\nreignites\nreigniting\nreignition\nreignitions\nreigns\nreimage\nreimaged\nreimages\nreimagine\nreimagined\nreimagines\nreimaging\nreimagining\nreimbursable\nreimburse\nreimbursed\nreimbursement\nreimbursements\nreimburses\nreimbursing\nreimmerse\nreimmersed\nreimmerses\nreimmersing\nreimplant\nreimplantation\nreimplantations\nreimplanted\nreimplanting\nreimplants\nreimport\nreimportation\nreimportations\nreimported\nreimporting\nreimports\nreimpose\nreimposed\nreimposes\nreimposing\nreimposition\nreimpositions\nreimpression\nreimpressions\nrein\nreincarnate\nreincarnated\nreincarnates\nreincarnating\nreincarnation\nreincarnations\nreincite\nreincited\nreincites\nreinciting\nreincorporate\nreincorporated\nreincorporates\nreincorporating\nreincorporation\nreincorporations\nreincur\nreincurred\nreincurring\nreincurs\nreindeer\nreindeers\nreindex\nreindexed\nreindexes\nreindexing\nreindict\nreindicted\nreindicting\nreindictment\nreindictments\nreindicts\nreinduce\nreinduced\nreinduces\nreinducing\nreinduct\nreinducted\nreinducting\nreinducts\nreindustrialization\nreindustrializations\nreindustrialize\nreindustrialized\nreindustrializes\nreindustrializing\nreined\nreinfect\nreinfected\nreinfecting\nreinfection\nreinfections\nreinfects\nreinfestation\nreinfestations\nreinflate\nreinflated\nreinflates\nreinflating\nreinflation\nreinflations\nreinforce\nreinforceable\nreinforced\nreinforcement\nreinforcements\nreinforcer\nreinforcers\nreinforces\nreinforcing\nreinform\nreinformed\nreinforming\nreinforms\nreinfuse\nreinfused\nreinfuses\nreinfusing\nreinhabit\nreinhabited\nreinhabiting\nreinhabits\nreining\nreinitiate\nreinitiated\nreinitiates\nreinitiating\nreinject\nreinjected\nreinjecting\nreinjection\nreinjections\nreinjects\nreinjure\nreinjured\nreinjures\nreinjuries\nreinjuring\nreinjury\nreink\nreinked\nreinking\nreinks\nreinless\nreinnervate\nreinnervated\nreinnervates\nreinnervating\nreinnervation\nreinnervations\nreinoculate\nreinoculated\nreinoculates\nreinoculating\nreinoculation\nreinoculations\nreins\nreinsert\nreinserted\nreinserting\nreinsertion\nreinsertions\nreinserts\nreinsman\nreinsmen\nreinspect\nreinspected\nreinspecting\nreinspection\nreinspections\nreinspects\nreinspire\nreinspired\nreinspires\nreinspiring\nreinstall\nreinstallation\nreinstallations\nreinstalled\nreinstalling\nreinstalls\nreinstate\nreinstated\nreinstatement\nreinstatements\nreinstates\nreinstating\nreinstitute\nreinstituted\nreinstitutes\nreinstituting\nreinstitutionalization\nreinstitutionalizations\nreinstitutionalize\nreinstitutionalized\nreinstitutionalizes\nreinstitutionalizing\nreinsurance\nreinsurances\nreinsure\nreinsured\nreinsurer\nreinsurers\nreinsures\nreinsuring\nreintegrate\nreintegrated\nreintegrates\nreintegrating\nreintegration\nreintegrations\nreintegrative\nreinter\nreinterpret\nreinterpretation\nreinterpretations\nreinterpreted\nreinterpreting\nreinterprets\nreinterred\nreinterring\nreinters\nreinterview\nreinterviewed\nreinterviewing\nreinterviews\nreintroduce\nreintroduced\nreintroduces\nreintroducing\nreintroduction\nreintroductions\nreinvade\nreinvaded\nreinvades\nreinvading\nreinvasion\nreinvasions\nreinvent\nreinvented\nreinventing\nreinvention\nreinventions\nreinvents\nreinvest\nreinvested\nreinvestigate\nreinvestigated\nreinvestigates\nreinvestigating\nreinvestigation\nreinvestigations\nreinvesting\nreinvestment\nreinvestments\nreinvests\nreinvigorate\nreinvigorated\nreinvigorates\nreinvigorating\nreinvigoration\nreinvigorations\nreinvigorator\nreinvigorators\nreinvite\nreinvited\nreinvites\nreinviting\nreinvoke\nreinvoked\nreinvokes\nreinvoking\nreis\nreissue\nreissued\nreissuer\nreissuers\nreissues\nreissuing\nreitbok\nreitboks\nreiterate\nreiterated\nreiterates\nreiterating\nreiteration\nreiterations\nreiterative\nreiteratively\nreive\nreived\nreiver\nreivers\nreives\nreiving\nrejacket\nrejacketed\nrejacketing\nrejackets\nreject\nrejected\nrejectee\nrejectees\nrejecter\nrejecters\nrejecting\nrejectingly\nrejection\nrejections\nrejective\nrejector\nrejectors\nrejects\nrejigger\nrejiggered\nrejiggering\nrejiggers\nrejoice\nrejoiced\nrejoicer\nrejoicers\nrejoices\nrejoicing\nrejoicingly\nrejoicings\nrejoin\nrejoinder\nrejoinders\nrejoined\nrejoining\nrejoins\nrejudge\nrejudged\nrejudges\nrejudging\nrejuggle\nrejuggled\nrejuggles\nrejuggling\nrejuvenate\nrejuvenated\nrejuvenates\nrejuvenating\nrejuvenation\nrejuvenations\nrejuvenator\nrejuvenators\nrejuvenescence\nrejuvenescences\nrejuvenescent\nrekey\nrekeyboard\nrekeyboarded\nrekeyboarding\nrekeyboards\nrekeyed\nrekeying\nrekeys\nrekindle\nrekindled\nrekindles\nrekindling\nreknit\nreknits\nreknitted\nreknitting\nrelabel\nrelabeled\nrelabeling\nrelabelled\nrelabelling\nrelabels\nrelace\nrelaced\nrelaces\nrelacing\nrelacquer\nrelacquered\nrelacquering\nrelacquers\nrelaid\nrelandscape\nrelandscaped\nrelandscapes\nrelandscaping\nrelapse\nrelapsed\nrelapser\nrelapsers\nrelapses\nrelapsing\nrelatable\nrelate\nrelated\nrelatedly\nrelatedness\nrelatednesses\nrelater\nrelaters\nrelates\nrelating\nrelation\nrelational\nrelationally\nrelations\nrelationship\nrelationships\nrelative\nrelatively\nrelatives\nrelativism\nrelativisms\nrelativist\nrelativistic\nrelativistically\nrelativists\nrelativities\nrelativity\nrelativize\nrelativized\nrelativizes\nrelativizing\nrelator\nrelators\nrelaunch\nrelaunched\nrelaunches\nrelaunching\nrelax\nrelaxant\nrelaxants\nrelaxation\nrelaxations\nrelaxed\nrelaxedly\nrelaxedness\nrelaxednesses\nrelaxer\nrelaxers\nrelaxes\nrelaxin\nrelaxing\nrelaxins\nrelay\nrelayed\nrelaying\nrelays\nrelearn\nrelearned\nrelearning\nrelearns\nrelearnt\nreleasable\nrelease\nreleased\nreleaser\nreleasers\nreleases\nreleasing\nrelegate\nrelegated\nrelegates\nrelegating\nrelegation\nrelegations\nrelend\nrelending\nrelends\nrelent\nrelented\nrelenting\nrelentless\nrelentlessly\nrelentlessness\nrelentlessnesses\nrelents\nrelet\nrelets\nreletter\nrelettered\nrelettering\nreletters\nreletting\nrelevance\nrelevances\nrelevancies\nrelevancy\nrelevant\nrelevantly\nreleve\nreleves\nreliabilities\nreliability\nreliable\nreliableness\nreliablenesses\nreliables\nreliably\nreliance\nreliances\nreliant\nreliantly\nrelic\nrelicense\nrelicensed\nrelicenses\nrelicensing\nrelicensure\nrelicensures\nrelics\nrelict\nreliction\nrelictions\nrelicts\nrelied\nrelief\nreliefs\nrelier\nreliers\nrelies\nrelievable\nrelieve\nrelieved\nrelievedly\nreliever\nrelievers\nrelieves\nrelieving\nrelievo\nrelievos\nrelight\nrelighted\nrelighting\nrelights\nreligion\nreligionist\nreligionists\nreligionless\nreligions\nreligiose\nreligiosities\nreligiosity\nreligious\nreligiously\nreligiousness\nreligiousnesses\nreline\nrelined\nrelines\nrelining\nrelink\nrelinked\nrelinking\nrelinks\nrelinquish\nrelinquished\nrelinquishes\nrelinquishing\nrelinquishment\nrelinquishments\nreliquaries\nreliquary\nrelique\nreliquefied\nreliquefies\nreliquefy\nreliquefying\nreliques\nreliquiae\nrelish\nrelishable\nrelished\nrelishes\nrelishing\nrelist\nrelisted\nrelisting\nrelists\nrelit\nrelive\nrelived\nrelives\nreliving\nreload\nreloaded\nreloader\nreloaders\nreloading\nreloads\nreloan\nreloaned\nreloaning\nreloans\nrelocatable\nrelocate\nrelocated\nrelocatee\nrelocatees\nrelocates\nrelocating\nrelocation\nrelocations\nrelock\nrelocked\nrelocking\nrelocks\nrelook\nrelooked\nrelooking\nrelooks\nrelubricate\nrelubricated\nrelubricates\nrelubricating\nrelubrication\nrelubrications\nrelucent\nreluct\nreluctance\nreluctances\nreluctancies\nreluctancy\nreluctant\nreluctantly\nreluctate\nreluctated\nreluctates\nreluctating\nreluctation\nreluctations\nrelucted\nrelucting\nrelucts\nrelume\nrelumed\nrelumes\nrelumine\nrelumined\nrelumines\nreluming\nrelumining\nrely\nrelying\nrem\nremade\nremail\nremailed\nremailing\nremails\nremain\nremainder\nremaindered\nremaindering\nremainders\nremained\nremaining\nremains\nremake\nremaker\nremakers\nremakes\nremaking\nreman\nremand\nremanded\nremanding\nremands\nremanence\nremanences\nremanent\nremanned\nremanning\nremans\nremanufacture\nremanufactured\nremanufacturer\nremanufacturers\nremanufactures\nremanufacturing\nremap\nremapped\nremapping\nremaps\nremark\nremarkable\nremarkableness\nremarkablenesses\nremarkably\nremarked\nremarker\nremarkers\nremarket\nremarketed\nremarketing\nremarkets\nremarking\nremarks\nremarque\nremarques\nremarriage\nremarriages\nremarried\nremarries\nremarry\nremarrying\nremaster\nremastered\nremastering\nremasters\nrematch\nrematched\nrematches\nrematching\nremate\nremated\nrematerialize\nrematerialized\nrematerializes\nrematerializing\nremates\nremating\nremeasure\nremeasured\nremeasurement\nremeasurements\nremeasures\nremeasuring\nremediabilities\nremediability\nremediable\nremedial\nremedially\nremediate\nremediated\nremediates\nremediating\nremediation\nremediations\nremedied\nremedies\nremediless\nremedy\nremedying\nremeet\nremeeting\nremeets\nremelt\nremelted\nremelting\nremelts\nremember\nrememberabilities\nrememberability\nrememberable\nremembered\nrememberer\nrememberers\nremembering\nremembers\nremembrance\nremembrancer\nremembrancers\nremembrances\nremend\nremended\nremending\nremends\nremerge\nremerged\nremerges\nremerging\nremet\nremex\nremiges\nremigial\nremigration\nremigrations\nremilitarization\nremilitarizations\nremilitarize\nremilitarized\nremilitarizes\nremilitarizing\nremind\nreminded\nreminder\nreminders\nremindful\nreminding\nreminds\nreminisce\nreminisced\nreminiscence\nreminiscences\nreminiscent\nreminiscential\nreminiscently\nreminiscer\nreminiscers\nreminisces\nreminiscing\nremint\nreminted\nreminting\nremints\nremise\nremised\nremises\nremising\nremiss\nremissible\nremissibly\nremission\nremissions\nremissly\nremissness\nremissnesses\nremit\nremitment\nremitments\nremits\nremittable\nremittal\nremittals\nremittance\nremittances\nremitted\nremittent\nremitter\nremitters\nremitting\nremittor\nremittors\nremix\nremixed\nremixes\nremixing\nremixt\nremnant\nremnants\nremobilization\nremobilizations\nremobilize\nremobilized\nremobilizes\nremobilizing\nremodel\nremodeled\nremodeling\nremodelled\nremodelling\nremodels\nremodified\nremodifies\nremodify\nremodifying\nremoisten\nremoistened\nremoistening\nremoistens\nremolade\nremolades\nremold\nremolded\nremolding\nremolds\nremonetization\nremonetizations\nremonetize\nremonetized\nremonetizes\nremonetizing\nremonstrance\nremonstrances\nremonstrant\nremonstrantly\nremonstrants\nremonstrate\nremonstrated\nremonstrates\nremonstrating\nremonstration\nremonstrations\nremonstrative\nremonstratively\nremonstrator\nremonstrators\nremora\nremoras\nremorid\nremorse\nremorseful\nremorsefully\nremorsefulness\nremorsefulnesses\nremorseless\nremorselessly\nremorselessness\nremorselessnesses\nremorses\nremortgage\nremortgaged\nremortgages\nremortgaging\nremote\nremotely\nremoteness\nremotenesses\nremoter\nremotes\nremotest\nremotion\nremotions\nremotivate\nremotivated\nremotivates\nremotivating\nremotivation\nremotivations\nremount\nremounted\nremounting\nremounts\nremovabilities\nremovability\nremovable\nremovableness\nremovablenesses\nremovably\nremoval\nremovals\nremove\nremoveable\nremoved\nremover\nremovers\nremoves\nremoving\nrems\nremuda\nremudas\nremunerate\nremunerated\nremunerates\nremunerating\nremuneration\nremunerations\nremunerative\nremuneratively\nremunerativeness\nremunerativenesses\nremunerator\nremunerators\nremuneratory\nremythologize\nremythologized\nremythologizes\nremythologizing\nrenail\nrenailed\nrenailing\nrenails\nrenaissance\nrenaissances\nrenal\nrename\nrenamed\nrenames\nrenaming\nrenascence\nrenascences\nrenascent\nrenationalization\nrenationalizations\nrenationalize\nrenationalized\nrenationalizes\nrenationalizing\nrenaturation\nrenaturations\nrenature\nrenatured\nrenatures\nrenaturing\nrencontre\nrencontres\nrencounter\nrencountered\nrencountering\nrencounters\nrend\nrended\nrender\nrenderable\nrendered\nrenderer\nrenderers\nrendering\nrenders\nrendezvous\nrendezvoused\nrendezvouses\nrendezvousing\nrendible\nrending\nrendition\nrenditions\nrends\nrendzina\nrendzinas\nrenegade\nrenegaded\nrenegades\nrenegading\nrenegado\nrenegadoes\nrenegados\nrenege\nreneged\nreneger\nrenegers\nreneges\nreneging\nrenegotiable\nrenegotiate\nrenegotiated\nrenegotiates\nrenegotiating\nrenegotiation\nrenegotiations\nrenest\nrenested\nrenesting\nrenests\nrenew\nrenewabilities\nrenewability\nrenewable\nrenewably\nrenewal\nrenewals\nrenewed\nrenewer\nrenewers\nrenewing\nrenews\nreniform\nrenig\nrenigged\nrenigging\nrenigs\nrenin\nrenins\nrenitencies\nrenitency\nrenitent\nrenminbi\nrennase\nrennases\nrennet\nrennets\nrennin\nrennins\nrenogram\nrenograms\nrenographic\nrenographies\nrenography\nrenominate\nrenominated\nrenominates\nrenominating\nrenomination\nrenominations\nrenormalization\nrenormalizations\nrenormalize\nrenormalized\nrenormalizes\nrenormalizing\nrenotified\nrenotifies\nrenotify\nrenotifying\nrenounce\nrenounced\nrenouncement\nrenouncements\nrenouncer\nrenouncers\nrenounces\nrenouncing\nrenovascular\nrenovate\nrenovated\nrenovates\nrenovating\nrenovation\nrenovations\nrenovative\nrenovator\nrenovators\nrenown\nrenowned\nrenowning\nrenowns\nrent\nrentabilities\nrentability\nrentable\nrental\nrentals\nrente\nrented\nrenter\nrenters\nrentes\nrentier\nrentiers\nrenting\nrents\nrenumber\nrenumbered\nrenumbering\nrenumbers\nrenunciate\nrenunciates\nrenunciation\nrenunciations\nrenunciative\nrenunciatory\nrenvoi\nrenvois\nreobject\nreobjected\nreobjecting\nreobjects\nreobserve\nreobserved\nreobserves\nreobserving\nreobtain\nreobtained\nreobtaining\nreobtains\nreoccupation\nreoccupations\nreoccupied\nreoccupies\nreoccupy\nreoccupying\nreoccur\nreoccurred\nreoccurrence\nreoccurrences\nreoccurring\nreoccurs\nreoffer\nreoffered\nreoffering\nreoffers\nreoil\nreoiled\nreoiling\nreoils\nreopen\nreopened\nreopening\nreopenings\nreopens\nreoperate\nreoperated\nreoperates\nreoperating\nreoperation\nreoperations\nreoppose\nreopposed\nreopposes\nreopposing\nreorchestrate\nreorchestrated\nreorchestrates\nreorchestrating\nreorchestration\nreorchestrations\nreordain\nreordained\nreordaining\nreordains\nreorder\nreordered\nreordering\nreorders\nreorganization\nreorganizational\nreorganizations\nreorganize\nreorganized\nreorganizer\nreorganizers\nreorganizes\nreorganizing\nreorient\nreorientate\nreorientated\nreorientates\nreorientating\nreorientation\nreorientations\nreoriented\nreorienting\nreorients\nreoutfit\nreoutfits\nreoutfitted\nreoutfitting\nreovirus\nreoviruses\nreoxidation\nreoxidations\nreoxidize\nreoxidized\nreoxidizes\nreoxidizing\nrep\nrepacified\nrepacifies\nrepacify\nrepacifying\nrepack\nrepackage\nrepackaged\nrepackager\nrepackagers\nrepackages\nrepackaging\nrepacked\nrepacking\nrepacks\nrepaid\nrepaint\nrepainted\nrepainting\nrepaints\nrepair\nrepairabilities\nrepairability\nrepairable\nrepaired\nrepairer\nrepairers\nrepairing\nrepairman\nrepairmen\nrepairs\nrepand\nrepandly\nrepanel\nrepaneled\nrepaneling\nrepanelled\nrepanelling\nrepanels\nrepaper\nrepapered\nrepapering\nrepapers\nreparable\nreparation\nreparations\nreparative\nrepark\nreparked\nreparking\nreparks\nrepartee\nrepartees\nrepartition\nrepartitioned\nrepartitioning\nrepartitions\nrepass\nrepassage\nrepassages\nrepassed\nrepasses\nrepassing\nrepast\nrepasted\nrepasting\nrepasts\nrepatch\nrepatched\nrepatches\nrepatching\nrepatriate\nrepatriated\nrepatriates\nrepatriating\nrepatriation\nrepatriations\nrepattern\nrepatterned\nrepatterning\nrepatterns\nrepave\nrepaved\nrepaves\nrepaving\nrepay\nrepayable\nrepaying\nrepayment\nrepayments\nrepays\nrepeal\nrepealable\nrepealed\nrepealer\nrepealers\nrepealing\nrepeals\nrepeat\nrepeatabilities\nrepeatability\nrepeatable\nrepeated\nrepeatedly\nrepeater\nrepeaters\nrepeating\nrepeats\nrepechage\nrepechages\nrepeg\nrepegged\nrepegging\nrepegs\nrepel\nrepellant\nrepellants\nrepelled\nrepellencies\nrepellency\nrepellent\nrepellently\nrepellents\nrepeller\nrepellers\nrepelling\nrepels\nrepent\nrepentance\nrepentances\nrepentant\nrepentantly\nrepented\nrepenter\nrepenters\nrepenting\nrepents\nrepeople\nrepeopled\nrepeoples\nrepeopling\nrepercussion\nrepercussions\nrepercussive\nreperk\nreperked\nreperking\nreperks\nrepertoire\nrepertoires\nrepertories\nrepertory\nrepetend\nrepetends\nrepetition\nrepetitional\nrepetitions\nrepetitious\nrepetitiously\nrepetitiousness\nrepetitiousnesses\nrepetitive\nrepetitively\nrepetitiveness\nrepetitivenesses\nrephotograph\nrephotographed\nrephotographing\nrephotographs\nrephrase\nrephrased\nrephrases\nrephrasing\nrepin\nrepine\nrepined\nrepiner\nrepiners\nrepines\nrepining\nrepinned\nrepinning\nrepins\nreplace\nreplaceable\nreplaced\nreplacement\nreplacements\nreplacer\nreplacers\nreplaces\nreplacing\nreplan\nreplanned\nreplanning\nreplans\nreplant\nreplantation\nreplantations\nreplanted\nreplanting\nreplants\nreplaster\nreplastered\nreplastering\nreplasters\nreplate\nreplated\nreplates\nreplating\nreplay\nreplayed\nreplaying\nreplays\nreplead\nrepleaded\nrepleader\nrepleaders\nrepleading\nrepleads\nrepled\nrepledge\nrepledged\nrepledges\nrepledging\nreplenish\nreplenishable\nreplenished\nreplenisher\nreplenishers\nreplenishes\nreplenishing\nreplenishment\nreplenishments\nreplete\nrepleteness\nrepletenesses\nrepletion\nrepletions\nrepleviable\nreplevied\nreplevies\nreplevin\nreplevined\nreplevining\nreplevins\nreplevy\nreplevying\nreplica\nreplicabilities\nreplicability\nreplicable\nreplicas\nreplicase\nreplicases\nreplicate\nreplicated\nreplicates\nreplicating\nreplication\nreplications\nreplicative\nreplicator\nreplicators\nreplicon\nreplicons\nreplied\nreplier\nrepliers\nreplies\nreplot\nreplots\nreplotted\nreplotting\nreplumb\nreplumbed\nreplumbing\nreplumbs\nreplunge\nreplunged\nreplunges\nreplunging\nreply\nreplying\nrepo\nrepolarization\nrepolarizations\nrepolarize\nrepolarized\nrepolarizes\nrepolarizing\nrepolish\nrepolished\nrepolishes\nrepolishing\nrepoll\nrepolled\nrepolling\nrepolls\nrepopularize\nrepopularized\nrepopularizes\nrepopularizing\nrepopulate\nrepopulated\nrepopulates\nrepopulating\nrepopulation\nrepopulations\nreport\nreportable\nreportage\nreportages\nreported\nreportedly\nreporter\nreporters\nreporting\nreportorial\nreportorially\nreports\nrepos\nreposal\nreposals\nrepose\nreposed\nreposeful\nreposefully\nreposefulness\nreposefulnesses\nreposer\nreposers\nreposes\nreposing\nreposit\nreposited\nrepositing\nreposition\nrepositioned\nrepositioning\nrepositions\nrepositories\nrepository\nreposits\nrepossess\nrepossessed\nrepossesses\nrepossessing\nrepossession\nrepossessions\nrepossessor\nrepossessors\nrepot\nrepots\nrepotted\nrepotting\nrepour\nrepoured\nrepouring\nrepours\nrepousse\nrepousses\nrepower\nrepowered\nrepowering\nrepowers\nrepp\nrepped\nrepps\nreprehend\nreprehended\nreprehending\nreprehends\nreprehensibilities\nreprehensibility\nreprehensible\nreprehensibleness\nreprehensiblenesses\nreprehensibly\nreprehension\nreprehensions\nreprehensive\nrepresent\nrepresentable\nrepresentation\nrepresentational\nrepresentationalism\nrepresentationalisms\nrepresentationalist\nrepresentationalists\nrepresentationally\nrepresentations\nrepresentative\nrepresentatively\nrepresentativeness\nrepresentativenesses\nrepresentatives\nrepresentativities\nrepresentativity\nrepresented\nrepresenter\nrepresenters\nrepresenting\nrepresents\nrepress\nrepressed\nrepresses\nrepressibilities\nrepressibility\nrepressible\nrepressing\nrepression\nrepressionist\nrepressions\nrepressive\nrepressively\nrepressiveness\nrepressivenesses\nrepressor\nrepressors\nrepressurize\nrepressurized\nrepressurizes\nrepressurizing\nreprice\nrepriced\nreprices\nrepricing\nreprieval\nreprievals\nreprieve\nreprieved\nreprieves\nreprieving\nreprimand\nreprimanded\nreprimanding\nreprimands\nreprint\nreprinted\nreprinter\nreprinters\nreprinting\nreprints\nreprisal\nreprisals\nreprise\nreprised\nreprises\nreprising\nrepristinate\nrepristinated\nrepristinates\nrepristinating\nrepristination\nrepristinations\nreprivatization\nreprivatizations\nreprivatize\nreprivatized\nreprivatizes\nreprivatizing\nrepro\nreproach\nreproachable\nreproached\nreproacher\nreproachers\nreproaches\nreproachful\nreproachfully\nreproachfulness\nreproachfulnesses\nreproaching\nreproachingly\nreprobance\nreprobances\nreprobate\nreprobated\nreprobates\nreprobating\nreprobation\nreprobations\nreprobative\nreprobatory\nreprobe\nreprobed\nreprobes\nreprobing\nreprocess\nreprocessed\nreprocesses\nreprocessing\nreproduce\nreproduced\nreproducer\nreproducers\nreproduces\nreproducibilities\nreproducibility\nreproducible\nreproducibles\nreproducibly\nreproducing\nreproduction\nreproductions\nreproductive\nreproductively\nreproductives\nreprogram\nreprogramed\nreprograming\nreprogrammable\nreprogrammed\nreprogramming\nreprograms\nreprographer\nreprographers\nreprographic\nreprographics\nreprographies\nreprography\nreproof\nreproofs\nrepros\nreproval\nreprovals\nreprove\nreproved\nreprover\nreprovers\nreproves\nreproving\nreprovingly\nreprovision\nreprovisioned\nreprovisioning\nreprovisions\nreps\nreptant\nreptile\nreptiles\nreptilia\nreptilian\nreptilians\nreptilium\nrepublic\nrepublican\nrepublicanism\nrepublicanisms\nrepublicanize\nrepublicanized\nrepublicanizes\nrepublicanizing\nrepublicans\nrepublication\nrepublications\nrepublics\nrepublish\nrepublished\nrepublisher\nrepublishers\nrepublishes\nrepublishing\nrepudiate\nrepudiated\nrepudiates\nrepudiating\nrepudiation\nrepudiationist\nrepudiationists\nrepudiations\nrepudiator\nrepudiators\nrepugn\nrepugnance\nrepugnances\nrepugnancies\nrepugnancy\nrepugnant\nrepugnantly\nrepugned\nrepugning\nrepugns\nrepulse\nrepulsed\nrepulser\nrepulsers\nrepulses\nrepulsing\nrepulsion\nrepulsions\nrepulsive\nrepulsively\nrepulsiveness\nrepulsivenesses\nrepump\nrepumped\nrepumping\nrepumps\nrepunctuation\nrepunctuations\nrepurchase\nrepurchased\nrepurchases\nrepurchasing\nrepurified\nrepurifies\nrepurify\nrepurifying\nrepursue\nrepursued\nrepursues\nrepursuing\nreputabilities\nreputability\nreputable\nreputably\nreputation\nreputational\nreputations\nrepute\nreputed\nreputedly\nreputes\nreputing\nrequalification\nrequalifications\nrequalified\nrequalifies\nrequalify\nrequalifying\nrequest\nrequested\nrequester\nrequesters\nrequesting\nrequestor\nrequestors\nrequests\nrequiem\nrequiems\nrequiescat\nrequiescats\nrequin\nrequins\nrequire\nrequired\nrequirement\nrequirements\nrequirer\nrequirers\nrequires\nrequiring\nrequisite\nrequisiteness\nrequisitenesses\nrequisites\nrequisition\nrequisitioned\nrequisitioning\nrequisitions\nrequital\nrequitals\nrequite\nrequited\nrequiter\nrequiters\nrequites\nrequiting\nrerack\nreracked\nreracking\nreracks\nreradiate\nreradiated\nreradiates\nreradiating\nreradiation\nreradiations\nreraise\nreraised\nreraises\nreraising\nreran\nreread\nrereading\nrereadings\nrereads\nrerecord\nrerecorded\nrerecording\nrerecords\nreredos\nreredoses\nreregister\nreregistered\nreregistering\nreregisters\nreregistration\nreregistrations\nreregulate\nreregulated\nreregulates\nreregulating\nreregulation\nreregulations\nrerelease\nrereleased\nrereleases\nrereleasing\nreremice\nreremind\nrereminded\nrereminding\nrereminds\nreremouse\nrerepeat\nrerepeated\nrerepeating\nrerepeats\nrereview\nrereviewed\nrereviewing\nrereviews\nrereward\nrerewards\nrerig\nrerigged\nrerigging\nrerigs\nrerise\nrerisen\nrerises\nrerising\nreroll\nrerolled\nreroller\nrerollers\nrerolling\nrerolls\nreroof\nreroofed\nreroofing\nreroofs\nrerose\nreroute\nrerouted\nreroutes\nrerouting\nrerun\nrerunning\nreruns\nres\nresaddle\nresaddled\nresaddles\nresaddling\nresaid\nresail\nresailed\nresailing\nresails\nresalable\nresale\nresales\nresalute\nresaluted\nresalutes\nresaluting\nresample\nresampled\nresamples\nresampling\nresaw\nresawed\nresawing\nresawn\nresaws\nresay\nresaying\nresays\nrescale\nrescaled\nrescales\nrescaling\nreschedule\nrescheduled\nreschedules\nrescheduling\nreschool\nreschooled\nreschooling\nreschools\nrescind\nrescinded\nrescinder\nrescinders\nrescinding\nrescindment\nrescindments\nrescinds\nrescission\nrescissions\nrescissory\nrescore\nrescored\nrescores\nrescoring\nrescreen\nrescreened\nrescreening\nrescreens\nrescript\nrescripts\nrescuable\nrescue\nrescued\nrescuer\nrescuers\nrescues\nrescuing\nresculpt\nresculpted\nresculpting\nresculpts\nreseal\nresealable\nresealed\nresealing\nreseals\nresearch\nresearchable\nresearched\nresearcher\nresearchers\nresearches\nresearching\nresearchist\nresearchists\nreseason\nreseasoned\nreseasoning\nreseasons\nreseat\nreseated\nreseating\nreseats\nreseau\nreseaus\nreseaux\nresect\nresectabilities\nresectability\nresectable\nresected\nresecting\nresection\nresections\nresects\nresecure\nresecured\nresecures\nresecuring\nreseda\nresedas\nresee\nreseed\nreseeded\nreseeding\nreseeds\nreseeing\nreseek\nreseeking\nreseeks\nreseen\nresees\nresegregate\nresegregated\nresegregates\nresegregating\nresegregation\nresegregations\nreseize\nreseized\nreseizes\nreseizing\nresell\nreseller\nresellers\nreselling\nresells\nresemblance\nresemblances\nresemblant\nresemble\nresembled\nresembles\nresembling\nresend\nresending\nresends\nresensitize\nresensitized\nresensitizes\nresensitizing\nresent\nresented\nresentence\nresentenced\nresentences\nresentencing\nresentful\nresentfully\nresentfulness\nresentfulnesses\nresenting\nresentment\nresentments\nresents\nreserpine\nreserpines\nreservable\nreservation\nreservationist\nreservationists\nreservations\nreserve\nreserved\nreservedly\nreservedness\nreservednesses\nreserver\nreservers\nreserves\nreservice\nreserviced\nreservices\nreservicing\nreserving\nreservist\nreservists\nreservoir\nreservoirs\nreset\nresets\nresettable\nresetter\nresetters\nresetting\nresettle\nresettled\nresettlement\nresettlements\nresettles\nresettling\nresew\nresewed\nresewing\nresewn\nresews\nresh\nreshape\nreshaped\nreshaper\nreshapers\nreshapes\nreshaping\nreshave\nreshaved\nreshaven\nreshaves\nreshaving\nreshes\nreshine\nreshined\nreshines\nreshingle\nreshingled\nreshingles\nreshingling\nreshining\nreship\nreshipped\nreshipping\nreships\nreshod\nreshoe\nreshoeing\nreshoes\nreshone\nreshoot\nreshooting\nreshoots\nreshot\nreshow\nreshowed\nreshowing\nreshown\nreshows\nreshuffle\nreshuffled\nreshuffles\nreshuffling\nresid\nreside\nresided\nresidence\nresidences\nresidencies\nresidency\nresident\nresidential\nresidentially\nresidents\nresider\nresiders\nresides\nresiding\nresids\nresidua\nresidual\nresidually\nresiduals\nresiduary\nresidue\nresidues\nresiduum\nresiduums\nresift\nresifted\nresifting\nresifts\nresight\nresighted\nresighting\nresights\nresign\nresignation\nresignations\nresigned\nresignedly\nresignedness\nresignednesses\nresigner\nresigners\nresigning\nresigns\nresile\nresiled\nresiles\nresilience\nresiliences\nresiliencies\nresiliency\nresilient\nresiliently\nresiling\nresilver\nresilvered\nresilvering\nresilvers\nresin\nresinate\nresinated\nresinates\nresinating\nresined\nresinified\nresinifies\nresinify\nresinifying\nresining\nresinoid\nresinoids\nresinous\nresins\nresiny\nresist\nresistance\nresistances\nresistant\nresistants\nresisted\nresister\nresisters\nresistibilities\nresistibility\nresistible\nresisting\nresistive\nresistively\nresistiveness\nresistivenesses\nresistivities\nresistivity\nresistless\nresistlessly\nresistlessness\nresistlessnesses\nresistor\nresistors\nresists\nresite\nresited\nresites\nresiting\nresitting\nresittings\nresize\nresized\nresizes\nresizing\nresketch\nresketched\nresketches\nresketching\nreslate\nreslated\nreslates\nreslating\nresmelt\nresmelted\nresmelting\nresmelts\nresmooth\nresmoothed\nresmoothing\nresmooths\nresoak\nresoaked\nresoaking\nresoaks\nresocialization\nresocializations\nresocialize\nresocialized\nresocializes\nresocializing\nresod\nresodded\nresodding\nresods\nresojet\nresojets\nresold\nresolder\nresoldered\nresoldering\nresolders\nresole\nresoled\nresoles\nresolidification\nresolidifications\nresolidified\nresolidifies\nresolidify\nresolidifying\nresoling\nresoluble\nresolute\nresolutely\nresoluteness\nresolutenesses\nresoluter\nresolutes\nresolutest\nresolution\nresolutions\nresolvable\nresolve\nresolved\nresolvent\nresolvents\nresolver\nresolvers\nresolves\nresolving\nresonance\nresonances\nresonant\nresonantly\nresonants\nresonate\nresonated\nresonates\nresonating\nresonator\nresonators\nresorb\nresorbed\nresorbing\nresorbs\nresorcin\nresorcinol\nresorcinols\nresorcins\nresorption\nresorptions\nresorptive\nresort\nresorted\nresorter\nresorters\nresorting\nresorts\nresought\nresound\nresounded\nresounding\nresoundingly\nresounds\nresource\nresourceful\nresourcefully\nresourcefulness\nresourcefulnesses\nresources\nresow\nresowed\nresowing\nresown\nresows\nrespace\nrespaced\nrespaces\nrespacing\nrespade\nrespaded\nrespades\nrespading\nrespeak\nrespeaking\nrespeaks\nrespect\nrespectabilities\nrespectability\nrespectable\nrespectableness\nrespectablenesses\nrespectables\nrespectably\nrespected\nrespecter\nrespecters\nrespectful\nrespectfully\nrespectfulness\nrespectfulnesses\nrespecting\nrespective\nrespectively\nrespectiveness\nrespectivenesses\nrespects\nrespell\nrespelled\nrespelling\nrespellings\nrespells\nrespelt\nrespirable\nrespiration\nrespirations\nrespirator\nrespirators\nrespiratory\nrespire\nrespired\nrespires\nrespiring\nrespiritualize\nrespiritualized\nrespiritualizes\nrespiritualizing\nrespirometer\nrespirometers\nrespirometric\nrespirometries\nrespirometry\nrespite\nrespited\nrespites\nrespiting\nresplendence\nresplendences\nresplendencies\nresplendency\nresplendent\nresplendently\nresplice\nrespliced\nresplices\nresplicing\nresplit\nresplits\nresplitting\nrespoke\nrespoken\nrespond\nresponded\nrespondent\nrespondents\nresponder\nresponders\nresponding\nresponds\nresponsa\nresponse\nresponses\nresponsibilities\nresponsibility\nresponsible\nresponsibleness\nresponsiblenesses\nresponsibly\nresponsions\nresponsive\nresponsively\nresponsiveness\nresponsivenesses\nresponsories\nresponsory\nresponsum\nrespot\nrespots\nrespotted\nrespotting\nresprang\nrespray\nresprayed\nrespraying\nresprays\nrespread\nrespreading\nrespreads\nrespring\nrespringing\nresprings\nresprout\nresprouted\nresprouting\nresprouts\nresprung\nressentiment\nressentiments\nrest\nrestabilize\nrestabilized\nrestabilizes\nrestabilizing\nrestack\nrestacked\nrestacking\nrestacks\nrestaff\nrestaffed\nrestaffing\nrestaffs\nrestage\nrestaged\nrestages\nrestaging\nrestamp\nrestamped\nrestamping\nrestamps\nrestart\nrestartable\nrestarted\nrestarting\nrestarts\nrestate\nrestated\nrestatement\nrestatements\nrestates\nrestating\nrestaurant\nrestauranteur\nrestauranteurs\nrestaurants\nrestaurateur\nrestaurateurs\nrested\nrester\nresters\nrestful\nrestfuller\nrestfullest\nrestfully\nrestfulness\nrestfulnesses\nrestimulate\nrestimulated\nrestimulates\nrestimulating\nrestimulation\nrestimulations\nresting\nrestitch\nrestitched\nrestitches\nrestitching\nrestitute\nrestituted\nrestitutes\nrestituting\nrestitution\nrestitutions\nrestive\nrestively\nrestiveness\nrestivenesses\nrestless\nrestlessly\nrestlessness\nrestlessnesses\nrestock\nrestocked\nrestocking\nrestocks\nrestoke\nrestoked\nrestokes\nrestoking\nrestorable\nrestoral\nrestorals\nrestoration\nrestorations\nrestorative\nrestoratives\nrestore\nrestored\nrestorer\nrestorers\nrestores\nrestoring\nrestrain\nrestrainable\nrestrained\nrestrainedly\nrestrainer\nrestrainers\nrestraining\nrestrains\nrestraint\nrestraints\nrestrengthen\nrestrengthened\nrestrengthening\nrestrengthens\nrestress\nrestressed\nrestresses\nrestressing\nrestricken\nrestrict\nrestricted\nrestrictedly\nrestricting\nrestriction\nrestrictionism\nrestrictionisms\nrestrictionist\nrestrictionists\nrestrictions\nrestrictive\nrestrictively\nrestrictiveness\nrestrictivenesses\nrestrictives\nrestricts\nrestrike\nrestrikes\nrestriking\nrestring\nrestringing\nrestrings\nrestrive\nrestriven\nrestrives\nrestriving\nrestroom\nrestrooms\nrestrove\nrestruck\nrestructure\nrestructured\nrestructures\nrestructuring\nrestrung\nrests\nrestudied\nrestudies\nrestudy\nrestudying\nrestuff\nrestuffed\nrestuffing\nrestuffs\nrestyle\nrestyled\nrestyles\nrestyling\nresubmission\nresubmissions\nresubmit\nresubmits\nresubmitted\nresubmitting\nresult\nresultant\nresultantly\nresultants\nresulted\nresultful\nresulting\nresultless\nresults\nresume\nresumed\nresumer\nresumers\nresumes\nresuming\nresummon\nresummoned\nresummoning\nresummons\nresumption\nresumptions\nresupinate\nresupine\nresupplied\nresupplies\nresupply\nresupplying\nresurface\nresurfaced\nresurfacer\nresurfacers\nresurfaces\nresurfacing\nresurge\nresurged\nresurgence\nresurgences\nresurgent\nresurges\nresurging\nresurrect\nresurrected\nresurrecting\nresurrection\nresurrectional\nresurrectionist\nresurrectionists\nresurrections\nresurrects\nresurvey\nresurveyed\nresurveying\nresurveys\nresuscitate\nresuscitated\nresuscitates\nresuscitating\nresuscitation\nresuscitations\nresuscitative\nresuscitator\nresuscitators\nresyntheses\nresynthesis\nresynthesize\nresynthesized\nresynthesizes\nresynthesizing\nresystematize\nresystematized\nresystematizes\nresystematizing\nret\nretable\nretables\nretack\nretacked\nretacking\nretackle\nretackled\nretackles\nretackling\nretacks\nretag\nretagged\nretagging\nretags\nretail\nretailed\nretailer\nretailers\nretailing\nretailings\nretailor\nretailored\nretailoring\nretailors\nretails\nretain\nretained\nretainer\nretainers\nretaining\nretains\nretake\nretaken\nretaker\nretakers\nretakes\nretaking\nretaliate\nretaliated\nretaliates\nretaliating\nretaliation\nretaliations\nretaliative\nretaliatory\nretape\nretaped\nretapes\nretaping\nretard\nretardant\nretardants\nretardate\nretardates\nretardation\nretardations\nretarded\nretarder\nretarders\nretarding\nretards\nretarget\nretargeted\nretargeting\nretargets\nretaste\nretasted\nretastes\nretasting\nretaught\nretax\nretaxed\nretaxes\nretaxing\nretch\nretched\nretches\nretching\nrete\nreteach\nreteaches\nreteaching\nreteam\nreteamed\nreteaming\nreteams\nretear\nretearing\nretears\nretell\nretelling\nretellings\nretells\nretem\nretemper\nretempered\nretempering\nretempers\nretems\nretene\nretenes\nretention\nretentions\nretentive\nretentively\nretentiveness\nretentivenesses\nretentivities\nretentivity\nretest\nretested\nretesting\nretests\nretexture\nretextured\nretextures\nretexturing\nrethink\nrethinker\nrethinkers\nrethinking\nrethinks\nrethought\nrethread\nrethreaded\nrethreading\nrethreads\nretia\nretial\nretiarii\nretiarius\nretiary\nreticence\nreticences\nreticencies\nreticency\nreticent\nreticently\nreticle\nreticles\nreticula\nreticular\nreticulate\nreticulated\nreticulately\nreticulates\nreticulating\nreticulation\nreticulations\nreticule\nreticules\nreticulocyte\nreticulocytes\nreticuloendothelial\nreticulum\nretie\nretied\nreties\nretiform\nretighten\nretightened\nretightening\nretightens\nretile\nretiled\nretiles\nretiling\nretime\nretimed\nretimes\nretiming\nretina\nretinacula\nretinaculum\nretinae\nretinal\nretinals\nretinas\nretine\nretinene\nretinenes\nretines\nretinite\nretinites\nretinitides\nretinitis\nretinoblastoma\nretinoblastomas\nretinoblastomata\nretinoid\nretinoids\nretinol\nretinols\nretinopathies\nretinopathy\nretinoscopies\nretinoscopy\nretinotectal\nretint\nretinted\nretinting\nretints\nretinue\nretinued\nretinues\nretinula\nretinulae\nretinular\nretinulas\nretirant\nretirants\nretire\nretired\nretiredly\nretiredness\nretirednesses\nretiree\nretirees\nretirement\nretirements\nretirer\nretirers\nretires\nretiring\nretiringly\nretiringness\nretiringnesses\nretitle\nretitled\nretitles\nretitling\nretold\nretook\nretool\nretooled\nretooling\nretools\nretore\nretorn\nretort\nretorted\nretorter\nretorters\nretorting\nretorts\nretouch\nretouched\nretoucher\nretouchers\nretouches\nretouching\nretrace\nretraced\nretraces\nretracing\nretrack\nretracked\nretracking\nretracks\nretract\nretractable\nretracted\nretractile\nretractilities\nretractility\nretracting\nretraction\nretractions\nretractor\nretractors\nretracts\nretrain\nretrainable\nretrained\nretraining\nretrains\nretral\nretrally\nretransfer\nretransferred\nretransferring\nretransfers\nretransform\nretransformation\nretransformations\nretransformed\nretransforming\nretransforms\nretranslate\nretranslated\nretranslates\nretranslating\nretranslation\nretranslations\nretransmission\nretransmissions\nretransmit\nretransmits\nretransmitted\nretransmitting\nretread\nretreaded\nretreading\nretreads\nretreat\nretreatant\nretreatants\nretreated\nretreater\nretreaters\nretreating\nretreats\nretrench\nretrenched\nretrenches\nretrenching\nretrenchment\nretrenchments\nretrial\nretrials\nretribution\nretributions\nretributive\nretributively\nretributory\nretried\nretries\nretrievabilities\nretrievability\nretrievable\nretrieval\nretrievals\nretrieve\nretrieved\nretriever\nretrievers\nretrieves\nretrieving\nretrim\nretrimmed\nretrimming\nretrims\nretro\nretroact\nretroacted\nretroacting\nretroaction\nretroactions\nretroactive\nretroactively\nretroactivities\nretroactivity\nretroacts\nretrocede\nretroceded\nretrocedes\nretroceding\nretrocession\nretrocessions\nretrodict\nretrodicted\nretrodicting\nretrodiction\nretrodictions\nretrodictive\nretrodicts\nretrofire\nretrofired\nretrofires\nretrofiring\nretrofit\nretrofits\nretrofitted\nretrofitting\nretroflection\nretroflections\nretroflex\nretroflexion\nretroflexions\nretrogradation\nretrogradations\nretrograde\nretrograded\nretrogradely\nretrogrades\nretrograding\nretrogress\nretrogressed\nretrogresses\nretrogressing\nretrogression\nretrogressions\nretrogressive\nretrogressively\nretropack\nretropacks\nretroperitoneal\nretroperitoneally\nretroreflection\nretroreflections\nretroreflective\nretroreflector\nretroreflectors\nretrorocket\nretrorockets\nretrorse\nretros\nretrospect\nretrospected\nretrospecting\nretrospection\nretrospections\nretrospective\nretrospectively\nretrospectives\nretrospects\nretrousse\nretroversion\nretroversions\nretroviral\nretrovirus\nretroviruses\nretry\nretrying\nrets\nretsina\nretsinas\nretted\nretting\nretune\nretuned\nretunes\nretuning\nreturn\nreturnable\nreturnables\nreturned\nreturnee\nreturnees\nreturner\nreturners\nreturning\nreturns\nretuse\nretwist\nretwisted\nretwisting\nretwists\nretying\nretype\nretyped\nretypes\nretyping\nreunification\nreunifications\nreunified\nreunifies\nreunify\nreunifying\nreunion\nreunionist\nreunionistic\nreunionists\nreunions\nreunite\nreunited\nreuniter\nreuniters\nreunites\nreuniting\nreupholster\nreupholstered\nreupholstering\nreupholsters\nreusabilities\nreusability\nreusable\nreuse\nreused\nreuses\nreusing\nreutilization\nreutilizations\nreutilize\nreutilized\nreutilizes\nreutilizing\nreutter\nreuttered\nreuttering\nreutters\nrev\nrevaccinate\nrevaccinated\nrevaccinates\nrevaccinating\nrevaccination\nrevaccinations\nrevalidate\nrevalidated\nrevalidates\nrevalidating\nrevalidation\nrevalidations\nrevalorization\nrevalorizations\nrevalorize\nrevalorized\nrevalorizes\nrevalorizing\nrevaluate\nrevaluated\nrevaluates\nrevaluating\nrevaluation\nrevaluations\nrevalue\nrevalued\nrevalues\nrevaluing\nrevamp\nrevamped\nrevamper\nrevampers\nrevamping\nrevamps\nrevanche\nrevanches\nrevanchism\nrevanchisms\nrevanchist\nrevanchists\nrevascularization\nrevascularizations\nreveal\nrevealable\nrevealed\nrevealer\nrevealers\nrevealing\nrevealingly\nrevealment\nrevealments\nreveals\nrevegetate\nrevegetated\nrevegetates\nrevegetating\nrevegetation\nrevegetations\nrevehent\nreveille\nreveilles\nrevel\nrevelation\nrevelations\nrevelator\nrevelators\nrevelatory\nreveled\nreveler\nrevelers\nreveling\nrevelled\nreveller\nrevellers\nrevelling\nrevelries\nrevelry\nrevels\nrevenant\nrevenants\nrevenge\nrevenged\nrevengeful\nrevengefully\nrevengefulness\nrevengefulnesses\nrevenger\nrevengers\nrevenges\nrevenging\nrevenual\nrevenue\nrevenued\nrevenuer\nrevenuers\nrevenues\nreverb\nreverbed\nreverberant\nreverberantly\nreverberate\nreverberated\nreverberates\nreverberating\nreverberation\nreverberations\nreverberative\nreverberatory\nreverbing\nreverbs\nrevere\nrevered\nreverence\nreverenced\nreverencer\nreverencers\nreverences\nreverencing\nreverend\nreverends\nreverent\nreverential\nreverentially\nreverently\nreverer\nreverers\nreveres\nreverie\nreveries\nreverified\nreverifies\nreverify\nreverifying\nrevering\nrevers\nreversal\nreversals\nreverse\nreversed\nreversely\nreverser\nreversers\nreverses\nreversibilities\nreversibility\nreversible\nreversibles\nreversibly\nreversing\nreversion\nreversional\nreversionary\nreversioner\nreversioners\nreversions\nreverso\nreversos\nrevert\nrevertant\nrevertants\nreverted\nreverter\nreverters\nrevertible\nreverting\nreverts\nrevery\nrevest\nrevested\nrevesting\nrevests\nrevet\nrevetment\nrevetments\nrevets\nrevetted\nrevetting\nrevictual\nrevictualed\nrevictualing\nrevictualled\nrevictualling\nrevictuals\nreview\nreviewable\nreviewal\nreviewals\nreviewed\nreviewer\nreviewers\nreviewing\nreviews\nrevile\nreviled\nrevilement\nrevilements\nreviler\nrevilers\nreviles\nreviling\nrevisable\nrevisal\nrevisals\nrevise\nrevised\nreviser\nrevisers\nrevises\nrevising\nrevision\nrevisionary\nrevisionism\nrevisionisms\nrevisionist\nrevisionists\nrevisions\nrevisit\nrevisited\nrevisiting\nrevisits\nrevisor\nrevisors\nrevisory\nrevisualization\nrevisualizations\nrevitalise\nrevitalised\nrevitalises\nrevitalising\nrevitalization\nrevitalizations\nrevitalize\nrevitalized\nrevitalizes\nrevitalizing\nrevivable\nrevival\nrevivalism\nrevivalisms\nrevivalist\nrevivalistic\nrevivalists\nrevivals\nrevive\nrevived\nreviver\nrevivers\nrevives\nrevivification\nrevivifications\nrevivified\nrevivifies\nrevivify\nrevivifying\nreviving\nreviviscence\nreviviscences\nreviviscent\nrevocable\nrevocation\nrevocations\nrevoice\nrevoiced\nrevoices\nrevoicing\nrevokable\nrevoke\nrevoked\nrevoker\nrevokers\nrevokes\nrevoking\nrevolt\nrevolted\nrevolter\nrevolters\nrevolting\nrevoltingly\nrevolts\nrevolute\nrevolution\nrevolutionaries\nrevolutionarily\nrevolutionariness\nrevolutionarinesses\nrevolutionary\nrevolutionise\nrevolutionised\nrevolutionises\nrevolutionising\nrevolutionist\nrevolutionists\nrevolutionize\nrevolutionized\nrevolutionizer\nrevolutionizers\nrevolutionizes\nrevolutionizing\nrevolutions\nrevolvable\nrevolve\nrevolved\nrevolver\nrevolvers\nrevolves\nrevolving\nrevote\nrevoted\nrevotes\nrevoting\nrevs\nrevue\nrevues\nrevuist\nrevuists\nrevulsed\nrevulsion\nrevulsions\nrevulsive\nrevved\nrevving\nrewake\nrewaked\nrewaken\nrewakened\nrewakening\nrewakens\nrewakes\nrewaking\nrewan\nreward\nrewardable\nrewarded\nrewarder\nrewarders\nrewarding\nrewardingly\nrewards\nrewarm\nrewarmed\nrewarming\nrewarms\nrewash\nrewashed\nrewashes\nrewashing\nrewax\nrewaxed\nrewaxes\nrewaxing\nreweave\nreweaved\nreweaves\nreweaving\nrewed\nrewedded\nrewedding\nreweds\nreweigh\nreweighed\nreweighing\nreweighs\nreweld\nrewelded\nrewelding\nrewelds\nrewet\nrewets\nrewetted\nrewetting\nrewiden\nrewidened\nrewidening\nrewidens\nrewin\nrewind\nrewinded\nrewinder\nrewinders\nrewinding\nrewinds\nrewinning\nrewins\nrewire\nrewired\nrewires\nrewiring\nrewoke\nrewoken\nrewon\nreword\nreworded\nrewording\nrewords\nrework\nreworked\nreworking\nreworks\nrewound\nrewove\nrewoven\nrewrap\nrewrapped\nrewrapping\nrewraps\nrewrapt\nrewrite\nrewriter\nrewriters\nrewrites\nrewriting\nrewritten\nrewrote\nrewrought\nrex\nrexes\nreynard\nreynards\nrezone\nrezoned\nrezones\nrezoning\nrhabdocoele\nrhabdocoeles\nrhabdom\nrhabdomancer\nrhabdomancers\nrhabdomancies\nrhabdomancy\nrhabdome\nrhabdomere\nrhabdomeres\nrhabdomes\nrhabdoms\nrhabdomyosarcoma\nrhabdomyosarcomas\nrhabdomyosarcomata\nrhabdovirus\nrhabdoviruses\nrhachides\nrhachis\nrhachises\nrhadamanthine\nrhamnose\nrhamnoses\nrhamnus\nrhamnuses\nrhaphae\nrhaphe\nrhaphes\nrhapsode\nrhapsodes\nrhapsodic\nrhapsodical\nrhapsodically\nrhapsodies\nrhapsodist\nrhapsodists\nrhapsodize\nrhapsodized\nrhapsodizes\nrhapsodizing\nrhapsody\nrhatanies\nrhatany\nrhea\nrheas\nrhebok\nrheboks\nrhematic\nrhenium\nrheniums\nrheobase\nrheobases\nrheological\nrheologically\nrheologies\nrheologist\nrheologists\nrheology\nrheometer\nrheometers\nrheophil\nrheostat\nrheostatic\nrheostats\nrhesus\nrhesuses\nrhetor\nrhetoric\nrhetorical\nrhetorically\nrhetorician\nrhetoricians\nrhetorics\nrhetors\nrheum\nrheumatic\nrheumatically\nrheumatics\nrheumatism\nrheumatisms\nrheumatiz\nrheumatizes\nrheumatoid\nrheumatologies\nrheumatologist\nrheumatologists\nrheumatology\nrheumic\nrheumier\nrheumiest\nrheums\nrheumy\nrhinal\nrhinencephala\nrhinencephalic\nrhinencephalon\nrhinencephalons\nrhinestone\nrhinestoned\nrhinestones\nrhinitides\nrhinitis\nrhino\nrhinoceri\nrhinoceros\nrhinoceroses\nrhinoplasties\nrhinoplasty\nrhinos\nrhinoscopies\nrhinoscopy\nrhinovirus\nrhinoviruses\nrhizobia\nrhizobial\nrhizobium\nrhizoctonia\nrhizoctonias\nrhizoid\nrhizoidal\nrhizoids\nrhizoma\nrhizomata\nrhizomatous\nrhizome\nrhizomes\nrhizomic\nrhizopi\nrhizoplane\nrhizoplanes\nrhizopod\nrhizopods\nrhizopus\nrhizopuses\nrhizosphere\nrhizospheres\nrhizotomies\nrhizotomy\nrho\nrhodamin\nrhodamine\nrhodamines\nrhodamins\nrhodic\nrhodium\nrhodiums\nrhodochrosite\nrhodochrosites\nrhododendron\nrhododendrons\nrhodolite\nrhodolites\nrhodomontade\nrhodomontades\nrhodonite\nrhodonites\nrhodopsin\nrhodopsins\nrhodora\nrhodoras\nrhomb\nrhombencephala\nrhombencephalon\nrhombi\nrhombic\nrhombohedra\nrhombohedral\nrhombohedron\nrhombohedrons\nrhomboid\nrhomboidal\nrhomboidei\nrhomboideus\nrhomboids\nrhombs\nrhombus\nrhombuses\nrhonchal\nrhonchi\nrhonchus\nrhos\nrhubarb\nrhubarbs\nrhumb\nrhumba\nrhumbaed\nrhumbaing\nrhumbas\nrhumbs\nrhus\nrhuses\nrhyme\nrhymed\nrhymeless\nrhymer\nrhymers\nrhymes\nrhymester\nrhymesters\nrhyming\nrhynchocephalian\nrhynchocephalians\nrhyolite\nrhyolites\nrhyolitic\nrhyta\nrhythm\nrhythmic\nrhythmical\nrhythmically\nrhythmicities\nrhythmicity\nrhythmics\nrhythmist\nrhythmists\nrhythmization\nrhythmizations\nrhythmize\nrhythmized\nrhythmizes\nrhythmizing\nrhythms\nrhytidome\nrhytidomes\nrhyton\nrhytons\nria\nrial\nrials\nrialto\nrialtos\nriant\nriantly\nrias\nriata\nriatas\nrib\nribald\nribaldly\nribaldries\nribaldry\nribalds\nriband\nribands\nribavirin\nribavirins\nribband\nribbands\nribbed\nribber\nribbers\nribbier\nribbiest\nribbing\nribbings\nribbon\nribboned\nribbonfish\nribbonfishes\nribboning\nribbonlike\nribbons\nribbony\nribby\nribes\nribeye\nribeyes\nribgrass\nribgrasses\nribier\nribiers\nribless\nriblet\nriblets\nriblike\nriboflavin\nriboflavins\nribonuclease\nribonucleases\nribonucleoprotein\nribonucleoproteins\nribonucleoside\nribonucleosides\nribonucleotide\nribonucleotides\nribose\nriboses\nribosomal\nribosome\nribosomes\nribs\nribwort\nribworts\nrice\nricebird\nricebirds\nriced\nricer\nricercar\nricercare\nricercari\nricercars\nricers\nrices\nrich\nrichen\nrichened\nrichening\nrichens\nricher\nriches\nrichest\nrichly\nrichness\nrichnesses\nrichweed\nrichweeds\nricin\nricing\nricins\nricinus\nricinuses\nrick\nricked\nricketier\nricketiest\nrickets\nrickettsia\nrickettsiae\nrickettsial\nrickettsias\nrickety\nrickey\nrickeys\nricking\nrickrack\nrickracks\nricks\nricksha\nrickshas\nrickshaw\nrickshaws\nricochet\nricocheted\nricocheting\nricochets\nricochetted\nricochetting\nricotta\nricottas\nricrac\nricracs\nrictal\nrictus\nrictuses\nrid\nridable\nriddance\nriddances\nridded\nridden\nridder\nridders\nridding\nriddle\nriddled\nriddler\nriddlers\nriddles\nriddling\nride\nrideable\nrident\nrider\nriderless\nriders\nridership\nriderships\nrides\nridge\nridged\nridgel\nridgeline\nridgelines\nridgeling\nridgelings\nridgels\nridgepole\nridgepoles\nridges\nridgier\nridgiest\nridgil\nridgils\nridging\nridgling\nridglings\nridgy\nridicule\nridiculed\nridiculer\nridiculers\nridicules\nridiculing\nridiculous\nridiculously\nridiculousness\nridiculousnesses\nriding\nridings\nridley\nridleys\nridotto\nridottos\nrids\nriel\nriels\nriesling\nrieslings\nriever\nrievers\nrif\nrifampicin\nrifampicins\nrifampin\nrifampins\nrife\nrifely\nrifeness\nrifenesses\nrifer\nrifest\nriff\nriffed\nriffing\nriffle\nriffled\nriffler\nrifflers\nriffles\nriffling\nriffraff\nriffraffs\nriffs\nrifle\nriflebird\nriflebirds\nrifled\nrifleman\nriflemen\nrifler\nrifleries\nriflers\nriflery\nrifles\nrifling\nriflings\nrifs\nrift\nrifted\nrifting\nriftless\nrifts\nrig\nrigadoon\nrigadoons\nrigamarole\nrigamaroles\nrigatoni\nrigatonis\nrigaudon\nrigaudons\nrigged\nrigger\nriggers\nrigging\nriggings\nright\nrighted\nrighteous\nrighteously\nrighteousness\nrighteousnesses\nrighter\nrighters\nrightest\nrightful\nrightfully\nrightfulness\nrightfulnesses\nrighties\nrighting\nrightism\nrightisms\nrightist\nrightists\nrightly\nrightmost\nrightness\nrightnesses\nrighto\nrights\nrightsize\nrightsized\nrightsizes\nrightsizing\nrightward\nrightwards\nrighty\nrigid\nrigidification\nrigidifications\nrigidified\nrigidifies\nrigidify\nrigidifying\nrigidities\nrigidity\nrigidly\nrigidness\nrigidnesses\nrigmarole\nrigmaroles\nrigor\nrigorism\nrigorisms\nrigorist\nrigoristic\nrigorists\nrigorous\nrigorously\nrigorousness\nrigorousnesses\nrigors\nrigour\nrigours\nrigs\nrijsttafel\nrijsttafels\nrikisha\nrikishas\nrikshaw\nrikshaws\nrile\nriled\nriles\nriley\nrilievi\nrilievo\nrilievos\nriling\nrill\nrille\nrilled\nrilles\nrillet\nrillets\nrillettes\nrilling\nrills\nrim\nrime\nrimed\nrimer\nrimers\nrimes\nrimester\nrimesters\nrimfire\nrimfires\nrimier\nrimiest\nriminess\nriminesses\nriming\nrimland\nrimlands\nrimless\nrimmed\nrimmer\nrimmers\nrimming\nrimose\nrimosely\nrimosities\nrimosity\nrimous\nrimple\nrimpled\nrimples\nrimpling\nrimrock\nrimrocks\nrims\nrimy\nrin\nrind\nrinded\nrinderpest\nrinderpests\nrinds\nring\nringbark\nringbarked\nringbarking\nringbarks\nringbolt\nringbolts\nringbone\nringbones\nringdove\nringdoves\nringed\nringent\nringer\nringers\nringgit\nringgits\nringhals\nringhalses\nringing\nringingly\nringleader\nringleaders\nringlet\nringlets\nringlike\nringmaster\nringmasters\nringneck\nringnecks\nrings\nringside\nringsides\nringstraked\nringtail\nringtails\nringtaw\nringtaws\nringtoss\nringtosses\nringworm\nringworms\nrink\nrinks\nrinning\nrins\nrinsable\nrinse\nrinsed\nrinser\nrinsers\nrinses\nrinsible\nrinsing\nrinsings\nrioja\nriojas\nriot\nrioted\nrioter\nrioters\nrioting\nriotous\nriotously\nriotousness\nriotousnesses\nriots\nrip\nriparian\nripcord\nripcords\nripe\nriped\nripely\nripen\nripened\nripener\nripeners\nripeness\nripenesses\nripening\nripens\nriper\nripes\nripest\nripieni\nripieno\nripienos\nriping\nripoff\nripoffs\nripost\nriposte\nriposted\nripostes\nriposting\nriposts\nrippable\nripped\nripper\nrippers\nripping\nripple\nrippled\nrippler\nripplers\nripples\nripplet\nripplets\nripplier\nrippliest\nrippling\nripply\nriprap\nriprapped\nriprapping\nripraps\nrips\nripsaw\nripsaws\nripsnorter\nripsnorters\nripsnorting\nripstop\nripstops\nriptide\nriptides\nrise\nrisen\nriser\nrisers\nrises\nrishi\nrishis\nrisibilities\nrisibility\nrisible\nrisibles\nrisibly\nrising\nrisings\nrisk\nrisked\nrisker\nriskers\nriskier\nriskiest\nriskily\nriskiness\nriskinesses\nrisking\nriskless\nrisks\nrisky\nrisorgimento\nrisorgimentos\nrisotto\nrisottos\nrisque\nrissole\nrissoles\nrisus\nrisuses\nritard\nritardando\nritardandos\nritards\nrite\nrites\nritornelli\nritornello\nritornellos\nritter\nritters\nritual\nritualism\nritualisms\nritualist\nritualistic\nritualistically\nritualists\nritualization\nritualizations\nritualize\nritualized\nritualizes\nritualizing\nritually\nrituals\nritz\nritzes\nritzier\nritziest\nritzily\nritziness\nritzinesses\nritzy\nrivage\nrivages\nrival\nrivaled\nrivaling\nrivalled\nrivalling\nrivalries\nrivalrous\nrivalry\nrivals\nrive\nrived\nriven\nriver\nriverbank\nriverbanks\nriverbed\nriverbeds\nriverboat\nriverboats\nriverfront\nriverfronts\nriverine\nrivers\nriverside\nriversides\nriverward\nriverwards\nrives\nrivet\nriveted\nriveter\nriveters\nriveting\nrivetingly\nrivets\nrivetted\nrivetting\nriviera\nrivieras\nriviere\nrivieres\nriving\nrivulet\nrivulets\nrivulose\nriyal\nriyals\nroach\nroached\nroaches\nroaching\nroad\nroadabilities\nroadability\nroadbed\nroadbeds\nroadblock\nroadblocked\nroadblocking\nroadblocks\nroadeo\nroadeos\nroadholding\nroadholdings\nroadhouse\nroadhouses\nroadie\nroadies\nroadkill\nroadkills\nroadless\nroadmap\nroadmaps\nroadrunner\nroadrunners\nroads\nroadshow\nroadshows\nroadside\nroadsides\nroadstead\nroadsteads\nroadster\nroadsters\nroadway\nroadways\nroadwork\nroadworks\nroadworthiness\nroadworthinesses\nroadworthy\nroam\nroamed\nroamer\nroamers\nroaming\nroams\nroan\nroans\nroar\nroared\nroarer\nroarers\nroaring\nroaringly\nroarings\nroars\nroast\nroasted\nroaster\nroasters\nroasting\nroasts\nrob\nrobalo\nrobalos\nroband\nrobands\nrobbed\nrobber\nrobberies\nrobbers\nrobbery\nrobbin\nrobbing\nrobbins\nrobe\nrobed\nrobes\nrobin\nrobing\nrobins\nroble\nrobles\nroborant\nroborants\nrobot\nrobotic\nrobotically\nrobotics\nrobotism\nrobotisms\nrobotization\nrobotizations\nrobotize\nrobotized\nrobotizes\nrobotizing\nrobotries\nrobotry\nrobots\nrobs\nrobust\nrobusta\nrobustas\nrobuster\nrobustest\nrobustious\nrobustiously\nrobustiousness\nrobustiousnesses\nrobustly\nrobustness\nrobustnesses\nroc\nrocaille\nrocailles\nrochet\nrochets\nrock\nrockabies\nrockabillies\nrockabilly\nrockaby\nrockabye\nrockabyes\nrockaway\nrockaways\nrockbound\nrocked\nrocker\nrockeries\nrockers\nrockery\nrocket\nrocketed\nrocketeer\nrocketeers\nrocketer\nrocketers\nrocketing\nrocketries\nrocketry\nrockets\nrockfall\nrockfalls\nrockfish\nrockfishes\nrockhopper\nrockhoppers\nrockhound\nrockhounding\nrockhoundings\nrockhounds\nrockier\nrockiest\nrockiness\nrockinesses\nrocking\nrockless\nrocklike\nrockling\nrocklings\nrockoon\nrockoons\nrockrose\nrockroses\nrocks\nrockshaft\nrockshafts\nrockslide\nrockslides\nrockweed\nrockweeds\nrockwork\nrockworks\nrocky\nrococo\nrococos\nrocs\nrod\nrodded\nrodding\nrode\nrodent\nrodenticide\nrodenticides\nrodents\nrodeo\nrodeoed\nrodeoing\nrodeos\nrodless\nrodlike\nrodman\nrodmen\nrodomontade\nrodomontades\nrods\nrodsman\nrodsmen\nroe\nroebuck\nroebucks\nroentgen\nroentgenogram\nroentgenograms\nroentgenographic\nroentgenographically\nroentgenographies\nroentgenography\nroentgenologic\nroentgenological\nroentgenologically\nroentgenologies\nroentgenologist\nroentgenologists\nroentgenology\nroentgens\nroes\nrogation\nrogations\nrogatory\nroger\nrogers\nrogue\nrogued\nrogueing\nrogueries\nroguery\nrogues\nroguing\nroguish\nroguishly\nroguishness\nroguishnesses\nroil\nroiled\nroilier\nroiliest\nroiling\nroils\nroily\nroister\nroistered\nroisterer\nroisterers\nroistering\nroisterous\nroisterously\nroisters\nrolamite\nrolamites\nrole\nroles\nrolf\nrolfed\nrolfer\nrolfers\nrolfing\nrolfs\nroll\nrollaway\nrollback\nrollbacks\nrolled\nroller\nrollers\nrollick\nrollicked\nrollicking\nrollicks\nrollicky\nrolling\nrollings\nrollmop\nrollmops\nrollout\nrollouts\nrollover\nrollovers\nrolls\nrolltop\nrollway\nrollways\nrom\nromaine\nromaines\nroman\nromance\nromanced\nromancer\nromancers\nromances\nromancing\nromanise\nromanised\nromanises\nromanising\nromanization\nromanizations\nromanize\nromanized\nromanizes\nromanizing\nromano\nromanos\nromans\nromantic\nromantically\nromanticise\nromanticised\nromanticises\nromanticising\nromanticism\nromanticisms\nromanticist\nromanticists\nromanticization\nromanticizations\nromanticize\nromanticized\nromanticizes\nromanticizing\nromantics\nromaunt\nromaunts\nromeldale\nromeldales\nromeo\nromeos\nromp\nromped\nromper\nrompers\nromping\nrompish\nromps\nroms\nrondeau\nrondeaux\nrondel\nrondelet\nrondelets\nrondelle\nrondelles\nrondels\nrondo\nrondos\nrondure\nrondures\nronion\nronions\nronnel\nronnels\nrontgen\nrontgens\nronyon\nronyons\nrood\nroods\nroof\nroofed\nroofer\nroofers\nroofing\nroofings\nroofless\nrooflike\nroofline\nrooflines\nroofs\nrooftop\nrooftops\nrooftree\nrooftrees\nrook\nrooked\nrookeries\nrookery\nrookie\nrookier\nrookies\nrookiest\nrooking\nrooks\nrooky\nroom\nroomed\nroomer\nroomers\nroomette\nroomettes\nroomful\nroomfuls\nroomie\nroomier\nroomies\nroomiest\nroomily\nroominess\nroominesses\nrooming\nroommate\nroommates\nrooms\nroomy\nroorbach\nroorbachs\nroorback\nroorbacks\nroose\nroosed\nrooser\nroosers\nrooses\nroosing\nroost\nroosted\nrooster\nroosters\nroosting\nroosts\nroot\nrootage\nrootages\nrooted\nrootedness\nrootednesses\nrooter\nrooters\nroothold\nrootholds\nrootier\nrootiest\nrooting\nrootless\nrootlessness\nrootlessnesses\nrootlet\nrootlets\nrootlike\nroots\nrootstock\nrootstocks\nrooty\nropable\nrope\nroped\nropedancer\nropedancers\nropedancing\nropedancings\nropelike\nroper\nroperies\nropers\nropery\nropes\nropewalk\nropewalker\nropewalkers\nropewalks\nropeway\nropeways\nropey\nropier\nropiest\nropily\nropiness\nropinesses\nroping\nropy\nroque\nroquelaure\nroquelaures\nroques\nroquet\nroqueted\nroqueting\nroquets\nrorqual\nrorquals\nrosaceous\nrosaria\nrosarian\nrosarians\nrosaries\nrosarium\nrosariums\nrosary\nroscoe\nroscoes\nrose\nroseate\nroseately\nrosebay\nrosebays\nrosebud\nrosebuds\nrosebush\nrosebushes\nrosed\nrosefish\nrosefishes\nroselike\nroselle\nroselles\nrosemaling\nrosemalings\nrosemaries\nrosemary\nroseola\nroseolar\nroseolas\nroseries\nroseroot\nroseroots\nrosery\nroses\nroseslug\nroseslugs\nroset\nrosets\nrosette\nrosettes\nrosewater\nrosewood\nrosewoods\nrosier\nrosiest\nrosily\nrosin\nrosined\nrosiness\nrosinesses\nrosing\nrosining\nrosinol\nrosinols\nrosinous\nrosins\nrosinweed\nrosinweeds\nrosiny\nrosolio\nrosolios\nrostella\nrostellar\nrostellum\nrostellums\nroster\nrosters\nrostra\nrostral\nrostrally\nrostrate\nrostrum\nrostrums\nrosulate\nrosy\nrot\nrota\nrotameter\nrotameters\nrotaries\nrotary\nrotas\nrotatable\nrotate\nrotated\nrotates\nrotating\nrotation\nrotational\nrotations\nrotative\nrotatively\nrotator\nrotatores\nrotators\nrotatory\nrotavirus\nrotaviruses\nrotch\nrotche\nrotches\nrote\nrotenone\nrotenones\nrotes\nrotgut\nrotguts\nroti\nrotifer\nrotifers\nrotiform\nrotis\nrotisserie\nrotisseries\nrotl\nrotls\nroto\nrotogravure\nrotogravures\nrotor\nrotorcraft\nrotors\nrotos\nrototill\nrototilled\nrototiller\nrototillers\nrototilling\nrototills\nrots\nrotte\nrotted\nrotten\nrottener\nrottenest\nrottenly\nrottenness\nrottennesses\nrottenstone\nrottenstones\nrotter\nrotters\nrottes\nrotting\nrottweiler\nrottweilers\nrotund\nrotunda\nrotundas\nrotundities\nrotundity\nrotundly\nrotundness\nrotundnesses\nroturier\nroturiers\nrouble\nroubles\nrouche\nrouches\nroue\nrouen\nrouens\nroues\nrouge\nrouged\nrouges\nrough\nroughage\nroughages\nroughcast\nroughcasting\nroughcasts\nroughdried\nroughdries\nroughdry\nroughdrying\nroughed\nroughen\nroughened\nroughening\nroughens\nrougher\nroughers\nroughest\nroughhew\nroughhewed\nroughhewing\nroughhewn\nroughhews\nroughhouse\nroughhoused\nroughhouses\nroughhousing\nroughing\nroughish\nroughleg\nroughlegs\nroughly\nroughneck\nroughnecks\nroughness\nroughnesses\nroughrider\nroughriders\nroughs\nroughshod\nrouging\nrouille\nrouilles\nroulade\nroulades\nrouleau\nrouleaus\nrouleaux\nroulette\nrouletted\nroulettes\nrouletting\nround\nroundabout\nroundaboutness\nroundaboutnesses\nroundabouts\nrounded\nroundedness\nroundednesses\nroundel\nroundelay\nroundelays\nroundels\nrounder\nrounders\nroundest\nroundheaded\nroundheadedness\nroundheadednesses\nroundhouse\nroundhouses\nrounding\nroundish\nroundlet\nroundlets\nroundly\nroundness\nroundnesses\nrounds\nroundsman\nroundsmen\nroundtable\nroundtables\nroundup\nroundups\nroundwood\nroundwoods\nroundworm\nroundworms\nroup\nrouped\nroupet\nroupier\nroupiest\nroupily\nrouping\nroups\nroupy\nrouse\nrouseabout\nrouseabouts\nroused\nrousement\nrousements\nrouser\nrousers\nrouses\nrousing\nrousingly\nrousseau\nrousseaus\nroust\nroustabout\nroustabouts\nrousted\nrouster\nrousters\nrousting\nrousts\nrout\nroute\nrouted\nrouteman\nroutemen\nrouter\nrouters\nroutes\nrouteway\nrouteways\nrouth\nrouths\nroutine\nroutinely\nroutines\nrouting\nroutinization\nroutinizations\nroutinize\nroutinized\nroutinizes\nroutinizing\nrouts\nroux\nrove\nroved\nroven\nrover\nrovers\nroves\nroving\nrovingly\nrovings\nrow\nrowable\nrowan\nrowanberries\nrowanberry\nrowans\nrowboat\nrowboats\nrowdier\nrowdies\nrowdiest\nrowdily\nrowdiness\nrowdinesses\nrowdy\nrowdyish\nrowdyism\nrowdyisms\nrowed\nrowel\nroweled\nroweling\nrowelled\nrowelling\nrowels\nrowen\nrowens\nrower\nrowers\nrowing\nrowings\nrowlock\nrowlocks\nrows\nrowth\nrowths\nroyal\nroyalism\nroyalisms\nroyalist\nroyalists\nroyally\nroyals\nroyalties\nroyalty\nroyster\nroystered\nroystering\nroysters\nrozzer\nrozzers\nruana\nruanas\nrub\nrubaboo\nrubaboos\nrubace\nrubaces\nrubaiyat\nrubasse\nrubasses\nrubati\nrubato\nrubatos\nrubbaboo\nrubbaboos\nrubbed\nrubber\nrubbered\nrubbering\nrubberize\nrubberized\nrubberizes\nrubberizing\nrubberlike\nrubberneck\nrubbernecked\nrubbernecker\nrubberneckers\nrubbernecking\nrubbernecks\nrubbers\nrubbery\nrubbing\nrubbings\nrubbish\nrubbishes\nrubbishy\nrubble\nrubbled\nrubbles\nrubblier\nrubbliest\nrubbling\nrubbly\nrubdown\nrubdowns\nrube\nrubefacient\nrubefacients\nrubella\nrubellas\nrubellite\nrubellites\nrubeola\nrubeolar\nrubeolas\nrubes\nrubicund\nrubicundities\nrubicundity\nrubidic\nrubidium\nrubidiums\nrubied\nrubier\nrubies\nrubiest\nrubigo\nrubigos\nrubious\nruble\nrubles\nruboff\nruboffs\nrubout\nrubouts\nrubric\nrubrical\nrubrically\nrubricate\nrubricated\nrubricates\nrubricating\nrubrication\nrubrications\nrubricator\nrubricators\nrubrics\nrubs\nrubus\nruby\nrubying\nrubylike\nrubythroat\nrubythroats\nruche\nruched\nruches\nruching\nruchings\nruck\nrucked\nrucking\nruckle\nruckled\nruckles\nruckling\nrucks\nrucksack\nrucksacks\nruckus\nruckuses\nruction\nructions\nructious\nrudbeckia\nrudbeckias\nrudd\nrudder\nrudderless\nrudderpost\nrudderposts\nrudders\nruddier\nruddiest\nruddily\nruddiness\nruddinesses\nruddle\nruddled\nruddles\nruddling\nruddock\nruddocks\nrudds\nruddy\nrude\nrudely\nrudeness\nrudenesses\nruder\nruderal\nruderals\nrudesbies\nrudesby\nrudest\nrudiment\nrudimental\nrudimentarily\nrudimentariness\nrudimentarinesses\nrudimentary\nrudiments\nrue\nrued\nrueful\nruefully\nruefulness\nruefulnesses\nruer\nruers\nrues\nrufescent\nruff\nruffe\nruffed\nruffes\nruffian\nruffianism\nruffianisms\nruffianly\nruffians\nruffing\nruffle\nruffled\nruffler\nrufflers\nruffles\nrufflier\nruffliest\nrufflike\nruffling\nruffly\nruffs\nrufiyaa\nrufous\nrug\nruga\nrugae\nrugal\nrugate\nrugbies\nrugby\nrugged\nruggeder\nruggedest\nruggedization\nruggedizations\nruggedize\nruggedized\nruggedizes\nruggedizing\nruggedly\nruggedness\nruggednesses\nrugger\nruggers\nrugging\nruglike\nrugola\nrugolas\nrugosa\nrugosas\nrugose\nrugosely\nrugosities\nrugosity\nrugous\nrugs\nrugulose\nruin\nruinable\nruinate\nruinated\nruinates\nruinating\nruination\nruinations\nruined\nruiner\nruiners\nruing\nruining\nruinous\nruinously\nruinousness\nruinousnesses\nruins\nrulable\nrule\nruled\nruleless\nruler\nrulers\nrulership\nrulerships\nrules\nrulier\nruliest\nruling\nrulings\nruly\nrum\nrumaki\nrumakis\nrumba\nrumbaed\nrumbaing\nrumbas\nrumble\nrumbled\nrumbler\nrumblers\nrumbles\nrumbling\nrumblings\nrumbly\nrumbustious\nrumbustiously\nrumbustiousness\nrumbustiousnesses\nrumen\nrumens\nrumina\nruminal\nruminant\nruminantly\nruminants\nruminate\nruminated\nruminates\nruminating\nrumination\nruminations\nruminative\nruminatively\nruminator\nruminators\nrummage\nrummaged\nrummager\nrummagers\nrummages\nrummaging\nrummer\nrummers\nrummest\nrummier\nrummies\nrummiest\nrummy\nrumor\nrumored\nrumoring\nrumormonger\nrumormongering\nrumormongerings\nrumormongers\nrumors\nrumour\nrumoured\nrumouring\nrumours\nrump\nrumple\nrumpled\nrumples\nrumpless\nrumplier\nrumpliest\nrumpling\nrumply\nrumps\nrumpus\nrumpuses\nrumrunner\nrumrunners\nrums\nrun\nrunabout\nrunabouts\nrunagate\nrunagates\nrunaround\nrunarounds\nrunaway\nrunaways\nrunback\nrunbacks\nruncinate\nrundle\nrundles\nrundlet\nrundlets\nrundown\nrundowns\nrune\nrunelike\nrunes\nrung\nrungless\nrungs\nrunic\nrunkle\nrunkled\nrunkles\nrunkling\nrunless\nrunlet\nrunlets\nrunnel\nrunnels\nrunner\nrunners\nrunnier\nrunniest\nrunning\nrunnings\nrunny\nrunoff\nrunoffs\nrunout\nrunouts\nrunover\nrunovers\nrunround\nrunrounds\nruns\nrunt\nruntier\nruntiest\nruntiness\nruntinesses\nruntish\nrunts\nrunty\nrunway\nrunways\nrupee\nrupees\nrupiah\nrupiahs\nrupture\nruptured\nruptures\nrupturing\nrural\nruralise\nruralised\nruralises\nruralising\nruralism\nruralisms\nruralist\nruralists\nruralite\nruralites\nruralities\nrurality\nruralize\nruralized\nruralizes\nruralizing\nrurally\nrurban\nruse\nruses\nrush\nrushed\nrushee\nrushees\nrusher\nrushers\nrushes\nrushier\nrushiest\nrushing\nrushings\nrushlight\nrushlights\nrushlike\nrushy\nrusine\nrusk\nrusks\nrusset\nrusseting\nrussetings\nrussets\nrussetting\nrussettings\nrussety\nrussified\nrussifies\nrussify\nrussifying\nrust\nrustable\nrusted\nrustic\nrustical\nrustically\nrusticals\nrusticate\nrusticated\nrusticates\nrusticating\nrustication\nrustications\nrusticator\nrusticators\nrusticities\nrusticity\nrusticly\nrustics\nrustier\nrustiest\nrustily\nrustiness\nrustinesses\nrusting\nrustle\nrustled\nrustler\nrustlers\nrustles\nrustless\nrustling\nrustproof\nrustproofed\nrustproofing\nrustproofs\nrusts\nrusty\nrut\nrutabaga\nrutabagas\nruth\nruthenic\nruthenium\nrutheniums\nrutherfordium\nrutherfordiums\nruthful\nruthfully\nruthfulness\nruthfulnesses\nruthless\nruthlessly\nruthlessness\nruthlessnesses\nruths\nrutilant\nrutile\nrutiles\nrutin\nrutins\nruts\nrutted\nruttier\nruttiest\nruttily\nrutting\nruttish\nruttishly\nruttishness\nruttishnesses\nrutty\nrya\nryas\nrye\nryegrass\nryegrasses\nryes\nryke\nryked\nrykes\nryking\nrynd\nrynds\nryokan\nryokans\nryot\nryots\nsab\nsabadilla\nsabadillas\nsabaton\nsabatons\nsabayon\nsabayons\nsabbat\nsabbath\nsabbaths\nsabbatic\nsabbatical\nsabbaticals\nsabbatics\nsabbats\nsabbed\nsabbing\nsabe\nsabed\nsabeing\nsaber\nsabered\nsabering\nsabermetrician\nsabermetricians\nsabermetrics\nsabers\nsabes\nsabin\nsabine\nsabines\nsabins\nsabir\nsabirs\nsable\nsablefish\nsablefishes\nsables\nsabot\nsabotage\nsabotaged\nsabotages\nsabotaging\nsaboteur\nsaboteurs\nsabots\nsabra\nsabras\nsabre\nsabred\nsabres\nsabring\nsabs\nsabulose\nsabulous\nsac\nsacahuista\nsacahuistas\nsacahuiste\nsacahuistes\nsacaton\nsacatons\nsacbut\nsacbuts\nsaccade\nsaccades\nsaccadic\nsaccate\nsaccharase\nsaccharases\nsaccharide\nsaccharides\nsaccharification\nsaccharifications\nsaccharified\nsaccharifies\nsaccharify\nsaccharifying\nsaccharimeter\nsaccharimeters\nsaccharin\nsaccharine\nsaccharinities\nsaccharinity\nsaccharins\nsaccharoidal\nsaccharometer\nsaccharometers\nsaccharomyces\nsaccular\nsacculate\nsacculated\nsacculation\nsacculations\nsaccule\nsaccules\nsacculi\nsacculus\nsacerdotal\nsacerdotalism\nsacerdotalisms\nsacerdotalist\nsacerdotalists\nsacerdotally\nsachem\nsachemic\nsachems\nsachet\nsacheted\nsachets\nsack\nsackbut\nsackbuts\nsackcloth\nsackcloths\nsacked\nsacker\nsackers\nsackful\nsackfuls\nsacking\nsackings\nsacklike\nsacks\nsacksful\nsaclike\nsacque\nsacques\nsacra\nsacral\nsacrals\nsacrament\nsacramental\nsacramentalism\nsacramentalisms\nsacramentalist\nsacramentalists\nsacramentally\nsacramentals\nsacraments\nsacraria\nsacrarium\nsacred\nsacredly\nsacredness\nsacrednesses\nsacrifice\nsacrificed\nsacrificer\nsacrificers\nsacrifices\nsacrificial\nsacrificially\nsacrificing\nsacrilege\nsacrileges\nsacrilegious\nsacrilegiously\nsacrilegiousness\nsacrilegiousnesses\nsacring\nsacrings\nsacrist\nsacristan\nsacristans\nsacristies\nsacrists\nsacristy\nsacroiliac\nsacroiliacs\nsacrosanct\nsacrosanctities\nsacrosanctity\nsacrum\nsacrums\nsacs\nsad\nsadden\nsaddened\nsaddening\nsaddens\nsadder\nsaddest\nsaddhu\nsaddhus\nsaddle\nsaddlebag\nsaddlebags\nsaddlebow\nsaddlebows\nsaddlebred\nsaddlebreds\nsaddlecloth\nsaddlecloths\nsaddled\nsaddleless\nsaddler\nsaddleries\nsaddlers\nsaddlery\nsaddles\nsaddlesore\nsaddletree\nsaddletrees\nsaddling\nsade\nsades\nsadhe\nsadhes\nsadhu\nsadhus\nsadi\nsadiron\nsadirons\nsadis\nsadism\nsadisms\nsadist\nsadistic\nsadistically\nsadists\nsadly\nsadness\nsadnesses\nsadomasochism\nsadomasochisms\nsadomasochist\nsadomasochistic\nsadomasochists\nsae\nsafari\nsafaried\nsafariing\nsafaris\nsafe\nsafecracker\nsafecrackers\nsafecracking\nsafecrackings\nsafeguard\nsafeguarded\nsafeguarding\nsafeguards\nsafekeeping\nsafekeepings\nsafelight\nsafelights\nsafely\nsafeness\nsafenesses\nsafer\nsafes\nsafest\nsafetied\nsafeties\nsafety\nsafetying\nsafetyman\nsafetymen\nsafflower\nsafflowers\nsaffron\nsaffrons\nsafranin\nsafranine\nsafranines\nsafranins\nsafrol\nsafrole\nsafroles\nsafrols\nsag\nsaga\nsagacious\nsagaciously\nsagaciousness\nsagaciousnesses\nsagacities\nsagacity\nsagaman\nsagamen\nsagamore\nsagamores\nsaganash\nsaganashes\nsagas\nsagbut\nsagbuts\nsage\nsagebrush\nsagebrushes\nsagely\nsageness\nsagenesses\nsager\nsages\nsagest\nsaggar\nsaggard\nsaggards\nsaggared\nsaggaring\nsaggars\nsagged\nsagger\nsaggered\nsaggering\nsaggers\nsaggier\nsaggiest\nsagging\nsaggy\nsagier\nsagiest\nsagittal\nsagittally\nsagittate\nsago\nsagos\nsags\nsaguaro\nsaguaros\nsagum\nsagy\nsahib\nsahibs\nsahiwal\nsahiwals\nsahuaro\nsahuaros\nsaice\nsaices\nsaid\nsaids\nsaiga\nsaigas\nsail\nsailable\nsailboard\nsailboarding\nsailboardings\nsailboards\nsailboat\nsailboater\nsailboaters\nsailboating\nsailboatings\nsailboats\nsailcloth\nsailcloths\nsailed\nsailer\nsailers\nsailfish\nsailfishes\nsailing\nsailings\nsailor\nsailorly\nsailors\nsailplane\nsailplaned\nsailplaner\nsailplaners\nsailplanes\nsailplaning\nsails\nsaimin\nsaimins\nsain\nsained\nsainfoin\nsainfoins\nsaining\nsains\nsaint\nsaintdom\nsaintdoms\nsainted\nsainthood\nsainthoods\nsainting\nsaintlier\nsaintliest\nsaintlike\nsaintliness\nsaintlinesses\nsaintly\nsaints\nsaintship\nsaintships\nsaith\nsaithe\nsaiyid\nsaiyids\nsajou\nsajous\nsake\nsaker\nsakers\nsakes\nsaki\nsakis\nsal\nsalaam\nsalaamed\nsalaaming\nsalaams\nsalabilities\nsalability\nsalable\nsalably\nsalacious\nsalaciously\nsalaciousness\nsalaciousnesses\nsalacities\nsalacity\nsalad\nsaladang\nsaladangs\nsalads\nsalal\nsalals\nsalamander\nsalamanders\nsalamandrine\nsalami\nsalamis\nsalariat\nsalariats\nsalaried\nsalaries\nsalary\nsalarying\nsalaryman\nsalarymen\nsalchow\nsalchows\nsale\nsaleable\nsaleably\nsalep\nsaleps\nsaleratus\nsaleratuses\nsaleroom\nsalerooms\nsales\nsalesclerk\nsalesclerks\nsalesgirl\nsalesgirls\nsalesladies\nsaleslady\nsalesman\nsalesmanship\nsalesmanships\nsalesmen\nsalespeople\nsalesperson\nsalespersons\nsalesroom\nsalesrooms\nsaleswoman\nsaleswomen\nsalic\nsalicin\nsalicine\nsalicines\nsalicins\nsalicylate\nsalicylates\nsalience\nsaliences\nsaliencies\nsaliency\nsalient\nsaliently\nsalients\nsalified\nsalifies\nsalify\nsalifying\nsalina\nsalinas\nsaline\nsalines\nsalinities\nsalinity\nsalinization\nsalinizations\nsalinize\nsalinized\nsalinizes\nsalinizing\nsalinometer\nsalinometers\nsaliva\nsalivary\nsalivas\nsalivate\nsalivated\nsalivates\nsalivating\nsalivation\nsalivations\nsalivator\nsalivators\nsall\nsallet\nsallets\nsallied\nsallier\nsalliers\nsallies\nsallow\nsallowed\nsallower\nsallowest\nsallowing\nsallowish\nsallowly\nsallowness\nsallownesses\nsallows\nsallowy\nsally\nsallying\nsalmagundi\nsalmagundis\nsalmi\nsalmis\nsalmon\nsalmonberries\nsalmonberry\nsalmonella\nsalmonellae\nsalmonellas\nsalmonelloses\nsalmonellosis\nsalmonid\nsalmonids\nsalmonoid\nsalmonoids\nsalmons\nsalol\nsalols\nsalometer\nsalometers\nsalon\nsalons\nsaloon\nsaloons\nsaloop\nsaloops\nsalp\nsalpa\nsalpae\nsalpas\nsalpian\nsalpians\nsalpid\nsalpids\nsalpiglossis\nsalpiglossises\nsalpinges\nsalpingitis\nsalpingitises\nsalpinx\nsalps\nsals\nsalsa\nsalsas\nsalsifies\nsalsify\nsalsilla\nsalsillas\nsalt\nsaltant\nsaltarelli\nsaltarello\nsaltarellos\nsaltation\nsaltations\nsaltatorial\nsaltatory\nsaltbox\nsaltboxes\nsaltbush\nsaltbushes\nsaltcellar\nsaltcellars\nsalted\nsalter\nsaltern\nsalterns\nsalters\nsaltest\nsaltie\nsaltier\nsaltiers\nsalties\nsaltiest\nsaltily\nsaltimbocca\nsaltimboccas\nsaltine\nsaltines\nsaltiness\nsaltinesses\nsalting\nsaltings\nsaltire\nsaltires\nsaltish\nsaltless\nsaltlike\nsaltness\nsaltnesses\nsaltpan\nsaltpans\nsaltpeter\nsaltpeters\nsalts\nsaltshaker\nsaltshakers\nsaltwater\nsaltwork\nsaltworks\nsaltwort\nsaltworts\nsalty\nsalubrious\nsalubriously\nsalubriousness\nsalubriousnesses\nsalubrities\nsalubrity\nsaluki\nsalukis\nsalutarily\nsalutariness\nsalutarinesses\nsalutary\nsalutation\nsalutational\nsalutations\nsalutatorian\nsalutatorians\nsalutatories\nsalutatory\nsalute\nsaluted\nsaluter\nsaluters\nsalutes\nsalutiferous\nsaluting\nsalvable\nsalvably\nsalvage\nsalvageabilities\nsalvageability\nsalvageable\nsalvaged\nsalvagee\nsalvagees\nsalvager\nsalvagers\nsalvages\nsalvaging\nsalvarsan\nsalvarsans\nsalvation\nsalvational\nsalvationism\nsalvationisms\nsalvationist\nsalvations\nsalve\nsalved\nsalver\nsalverform\nsalvers\nsalves\nsalvia\nsalvias\nsalvific\nsalving\nsalvo\nsalvoed\nsalvoes\nsalvoing\nsalvor\nsalvors\nsalvos\nsamara\nsamaras\nsamaritan\nsamaritans\nsamarium\nsamariums\nsamarskite\nsamarskites\nsamba\nsambaed\nsambaing\nsambar\nsambars\nsambas\nsambhar\nsambhars\nsambhur\nsambhurs\nsambo\nsambos\nsambuca\nsambucas\nsambuke\nsambukes\nsambur\nsamburs\nsame\nsamech\nsamechs\nsamek\nsamekh\nsamekhs\nsameks\nsameness\nsamenesses\nsamiel\nsamiels\nsamisen\nsamisens\nsamite\nsamites\nsamizdat\nsamizdats\nsamlet\nsamlets\nsamosa\nsamosas\nsamovar\nsamovars\nsamoyed\nsamoyeds\nsamp\nsampan\nsampans\nsamphire\nsamphires\nsample\nsampled\nsampler\nsamplers\nsamples\nsampling\nsamplings\nsamps\nsamsara\nsamsaras\nsamshu\nsamshus\nsamurai\nsamurais\nsanative\nsanatoria\nsanatorium\nsanatoriums\nsanbenito\nsanbenitos\nsancta\nsanctification\nsanctifications\nsanctified\nsanctifier\nsanctifiers\nsanctifies\nsanctify\nsanctifying\nsanctimonies\nsanctimonious\nsanctimoniously\nsanctimoniousness\nsanctimoniousnesses\nsanctimony\nsanction\nsanctionable\nsanctioned\nsanctioning\nsanctions\nsanctities\nsanctity\nsanctuaries\nsanctuary\nsanctum\nsanctums\nsand\nsandal\nsandaled\nsandaling\nsandalled\nsandalling\nsandals\nsandalwood\nsandalwoods\nsandarac\nsandaracs\nsandbag\nsandbagged\nsandbagger\nsandbaggers\nsandbagging\nsandbags\nsandbank\nsandbanks\nsandbar\nsandbars\nsandblast\nsandblasted\nsandblaster\nsandblasters\nsandblasting\nsandblasts\nsandbox\nsandboxes\nsandbur\nsandburr\nsandburrs\nsandburs\nsanddab\nsanddabs\nsanded\nsander\nsanderling\nsanderlings\nsanders\nsandfish\nsandfishes\nsandflies\nsandfly\nsandglass\nsandglasses\nsandgrouse\nsandgrouses\nsandhi\nsandhis\nsandhog\nsandhogs\nsandier\nsandiest\nsandiness\nsandinesses\nsanding\nsandlike\nsandling\nsandlings\nsandlot\nsandlots\nsandlotter\nsandlotters\nsandman\nsandmen\nsandpainting\nsandpaintings\nsandpaper\nsandpapered\nsandpapering\nsandpapers\nsandpapery\nsandpeep\nsandpeeps\nsandpile\nsandpiles\nsandpiper\nsandpipers\nsandpit\nsandpits\nsands\nsandshoe\nsandshoes\nsandsoap\nsandsoaps\nsandspur\nsandspurs\nsandstone\nsandstones\nsandstorm\nsandstorms\nsandwich\nsandwiched\nsandwiches\nsandwiching\nsandworm\nsandworms\nsandwort\nsandworts\nsandy\nsane\nsaned\nsanely\nsaneness\nsanenesses\nsaner\nsanes\nsanest\nsang\nsanga\nsangar\nsangaree\nsangarees\nsangars\nsangas\nsanger\nsangers\nsangfroid\nsangfroids\nsangh\nsanghs\nsangria\nsangrias\nsanguinaria\nsanguinarias\nsanguinarily\nsanguinary\nsanguine\nsanguinely\nsanguineness\nsanguinenesses\nsanguineous\nsanguines\nsanguinities\nsanguinity\nsanicle\nsanicles\nsanies\nsaning\nsanious\nsanitaria\nsanitarian\nsanitarians\nsanitaries\nsanitarily\nsanitarium\nsanitariums\nsanitary\nsanitate\nsanitated\nsanitates\nsanitating\nsanitation\nsanitations\nsanities\nsanitise\nsanitised\nsanitises\nsanitising\nsanitization\nsanitizations\nsanitize\nsanitized\nsanitizes\nsanitizing\nsanitoria\nsanitorium\nsanitoriums\nsanity\nsanjak\nsanjaks\nsank\nsannop\nsannops\nsannup\nsannups\nsannyasi\nsannyasin\nsannyasins\nsannyasis\nsans\nsansar\nsansars\nsansculotte\nsansculottes\nsansculottic\nsansculottish\nsansculottism\nsansculottisms\nsansei\nsanseis\nsanserif\nsanserifs\nsansevieria\nsansevierias\nsantalic\nsantalol\nsantalols\nsantimi\nsantims\nsantir\nsantirs\nsanto\nsantol\nsantolina\nsantolinas\nsantols\nsantonin\nsantonins\nsantos\nsantour\nsantours\nsantur\nsanturs\nsap\nsapajou\nsapajous\nsaphead\nsapheaded\nsapheads\nsaphena\nsaphenae\nsaphenous\nsapid\nsapidities\nsapidity\nsapience\nsapiences\nsapiencies\nsapiency\nsapiens\nsapient\nsapiently\nsapless\nsaplessness\nsaplessnesses\nsapling\nsaplings\nsapodilla\nsapodillas\nsapogenin\nsapogenins\nsaponaceous\nsaponaceousness\nsaponaceousnesses\nsaponifiable\nsaponification\nsaponifications\nsaponified\nsaponifier\nsaponifiers\nsaponifies\nsaponify\nsaponifying\nsaponin\nsaponine\nsaponines\nsaponins\nsaponite\nsaponites\nsapor\nsaporous\nsapors\nsapota\nsapotas\nsapote\nsapotes\nsapour\nsapours\nsapped\nsapper\nsappers\nsapphic\nsapphics\nsapphire\nsapphires\nsapphirine\nsapphism\nsapphisms\nsapphist\nsapphists\nsappier\nsappiest\nsappily\nsappiness\nsappinesses\nsapping\nsappy\nsapremia\nsapremias\nsapremic\nsaprobe\nsaprobes\nsaprobic\nsaprogenic\nsaprogenicities\nsaprogenicity\nsaprolite\nsaprolites\nsapropel\nsapropels\nsaprophagous\nsaprophyte\nsaprophytes\nsaprophytic\nsaprophytically\nsaprozoic\nsaps\nsapsago\nsapsagos\nsapsucker\nsapsuckers\nsapwood\nsapwoods\nsaraband\nsarabande\nsarabandes\nsarabands\nsaran\nsarans\nsarape\nsarapes\nsarcasm\nsarcasms\nsarcastic\nsarcastically\nsarcenet\nsarcenets\nsarcoid\nsarcoidoses\nsarcoidosis\nsarcoids\nsarcolemma\nsarcolemmal\nsarcolemmas\nsarcoma\nsarcomas\nsarcomata\nsarcomatoses\nsarcomatosis\nsarcomatous\nsarcomere\nsarcomeres\nsarcophagi\nsarcophagus\nsarcophaguses\nsarcoplasm\nsarcoplasmic\nsarcoplasms\nsarcosomal\nsarcosome\nsarcosomes\nsarcous\nsard\nsardana\nsardanas\nsardar\nsardars\nsardine\nsardines\nsardius\nsardiuses\nsardonic\nsardonically\nsardonicism\nsardonicisms\nsardonyx\nsardonyxes\nsards\nsaree\nsarees\nsargasso\nsargassos\nsargassum\nsargassums\nsarge\nsarges\nsari\nsarin\nsarins\nsaris\nsark\nsarkier\nsarkiest\nsarks\nsarky\nsarment\nsarmenta\nsarments\nsarmentum\nsarod\nsarode\nsarodes\nsarodist\nsarodists\nsarods\nsarong\nsarongs\nsaros\nsaroses\nsarracenia\nsarracenias\nsarsaparilla\nsarsaparillas\nsarsar\nsarsars\nsarsen\nsarsenet\nsarsenets\nsarsens\nsartor\nsartorial\nsartorially\nsartorii\nsartorius\nsartors\nsash\nsashay\nsashayed\nsashaying\nsashays\nsashed\nsashes\nsashimi\nsashimis\nsashing\nsasin\nsasins\nsaskatoon\nsaskatoons\nsasquatch\nsasquatches\nsass\nsassabies\nsassaby\nsassafras\nsassafrases\nsassed\nsasses\nsassier\nsassies\nsassiest\nsassily\nsassing\nsasswood\nsasswoods\nsassy\nsastruga\nsastrugi\nsat\nsatang\nsatangs\nsatanic\nsatanically\nsatanism\nsatanisms\nsatanist\nsatanists\nsatara\nsataras\nsatay\nsatays\nsatchel\nsatchelful\nsatchelfuls\nsatchels\nsatchelsful\nsate\nsated\nsateen\nsateens\nsatellite\nsatellites\nsatem\nsates\nsati\nsatiable\nsatiably\nsatiate\nsatiated\nsatiates\nsatiating\nsatiation\nsatiations\nsatieties\nsatiety\nsatin\nsatinet\nsatinets\nsating\nsatinpod\nsatinpods\nsatins\nsatinwood\nsatinwoods\nsatiny\nsatire\nsatires\nsatiric\nsatirical\nsatirically\nsatirise\nsatirised\nsatirises\nsatirising\nsatirist\nsatirists\nsatirizable\nsatirize\nsatirized\nsatirizes\nsatirizing\nsatis\nsatisfaction\nsatisfactions\nsatisfactorily\nsatisfactoriness\nsatisfactorinesses\nsatisfactory\nsatisfiable\nsatisfied\nsatisfies\nsatisfy\nsatisfying\nsatisfyingly\nsatori\nsatoris\nsatrap\nsatrapies\nsatraps\nsatrapy\nsatsuma\nsatsumas\nsaturable\nsaturant\nsaturants\nsaturate\nsaturated\nsaturates\nsaturating\nsaturation\nsaturations\nsaturator\nsaturators\nsaturnalia\nsaturnalian\nsaturnalianly\nsaturnalias\nsaturniid\nsaturniids\nsaturnine\nsaturnism\nsaturnisms\nsatyagraha\nsatyagrahas\nsatyr\nsatyriases\nsatyriasis\nsatyric\nsatyrid\nsatyrids\nsatyrs\nsau\nsauce\nsauceboat\nsauceboats\nsaucebox\nsauceboxes\nsauced\nsaucepan\nsaucepans\nsaucer\nsaucerlike\nsaucers\nsauces\nsauch\nsauchs\nsaucier\nsauciest\nsaucily\nsauciness\nsaucinesses\nsaucing\nsaucy\nsauerbraten\nsauerbratens\nsauerkraut\nsauerkrauts\nsauger\nsaugers\nsaugh\nsaughs\nsaughy\nsaul\nsauls\nsault\nsaults\nsauna\nsaunas\nsaunter\nsauntered\nsaunterer\nsaunterers\nsauntering\nsaunters\nsaurel\nsaurels\nsaurian\nsaurians\nsauries\nsaurischian\nsaurischians\nsauropod\nsauropods\nsaury\nsausage\nsausages\nsaute\nsauted\nsauteed\nsauteing\nsauterne\nsauternes\nsautes\nsautoir\nsautoire\nsautoires\nsautoirs\nsavable\nsavage\nsavaged\nsavagely\nsavageness\nsavagenesses\nsavager\nsavageries\nsavagery\nsavages\nsavagest\nsavaging\nsavagism\nsavagisms\nsavanna\nsavannah\nsavannahs\nsavannas\nsavant\nsavants\nsavarin\nsavarins\nsavate\nsavates\nsave\nsaveable\nsaved\nsaveloy\nsaveloys\nsaver\nsavers\nsaves\nsavin\nsavine\nsavines\nsaving\nsavingly\nsavings\nsavins\nsavior\nsaviors\nsaviour\nsaviours\nsavor\nsavored\nsavorer\nsavorers\nsavorier\nsavories\nsavoriest\nsavorily\nsavoriness\nsavorinesses\nsavoring\nsavorless\nsavorous\nsavors\nsavory\nsavour\nsavoured\nsavourer\nsavourers\nsavourier\nsavouries\nsavouriest\nsavouring\nsavours\nsavoury\nsavoy\nsavoys\nsavvied\nsavvier\nsavvies\nsavviest\nsavvy\nsavvying\nsaw\nsawbill\nsawbills\nsawbones\nsawboneses\nsawbuck\nsawbucks\nsawdust\nsawdusts\nsawed\nsawer\nsawers\nsawfish\nsawfishes\nsawflies\nsawfly\nsawhorse\nsawhorses\nsawing\nsawlike\nsawlog\nsawlogs\nsawmill\nsawmills\nsawn\nsawney\nsawneys\nsaws\nsawteeth\nsawtimber\nsawtimbers\nsawtooth\nsawyer\nsawyers\nsax\nsaxatile\nsaxes\nsaxhorn\nsaxhorns\nsaxicolous\nsaxifrage\nsaxifrages\nsaxitoxin\nsaxitoxins\nsaxonies\nsaxony\nsaxophone\nsaxophones\nsaxophonic\nsaxophonist\nsaxophonists\nsaxtuba\nsaxtubas\nsay\nsayable\nsayer\nsayers\nsayest\nsayid\nsayids\nsaying\nsayings\nsayonara\nsayonaras\nsays\nsayst\nsayyid\nsayyids\nscab\nscabbard\nscabbarded\nscabbarding\nscabbards\nscabbed\nscabbier\nscabbiest\nscabbily\nscabbing\nscabble\nscabbled\nscabbles\nscabbling\nscabby\nscabies\nscabietic\nscabiosa\nscabiosas\nscabious\nscabiouses\nscabland\nscablands\nscablike\nscabrous\nscabrously\nscabrousness\nscabrousnesses\nscabs\nscad\nscads\nscaffold\nscaffolded\nscaffolding\nscaffoldings\nscaffolds\nscag\nscagliola\nscagliolas\nscags\nscalable\nscalably\nscalade\nscalades\nscalado\nscalados\nscalage\nscalages\nscalar\nscalare\nscalares\nscalariform\nscalariformly\nscalars\nscalawag\nscalawags\nscald\nscalded\nscaldic\nscalding\nscalds\nscale\nscaled\nscaleless\nscalelike\nscalene\nscaleni\nscalenus\nscalepan\nscalepans\nscaler\nscalers\nscales\nscaleup\nscaleups\nscalier\nscaliest\nscaliness\nscalinesses\nscaling\nscall\nscallion\nscallions\nscallop\nscalloped\nscalloper\nscallopers\nscalloping\nscallopini\nscallopinis\nscallops\nscalls\nscallywag\nscallywags\nscalogram\nscalograms\nscaloppine\nscaloppines\nscalp\nscalped\nscalpel\nscalpels\nscalper\nscalpers\nscalping\nscalps\nscaly\nscam\nscammed\nscamming\nscammonies\nscammony\nscamp\nscamped\nscamper\nscampered\nscampering\nscampers\nscampi\nscampies\nscamping\nscampish\nscamps\nscams\nscan\nscandal\nscandaled\nscandaling\nscandalise\nscandalised\nscandalises\nscandalising\nscandalize\nscandalized\nscandalizes\nscandalizing\nscandalled\nscandalling\nscandalmonger\nscandalmongering\nscandalmongerings\nscandalmongers\nscandalous\nscandalously\nscandalousness\nscandalousnesses\nscandals\nscandent\nscandia\nscandias\nscandic\nscandium\nscandiums\nscannable\nscanned\nscanner\nscanners\nscanning\nscannings\nscans\nscansion\nscansions\nscant\nscanted\nscanter\nscantest\nscantier\nscanties\nscantiest\nscantily\nscantiness\nscantinesses\nscanting\nscantling\nscantlings\nscantly\nscantness\nscantnesses\nscants\nscanty\nscape\nscaped\nscapegoat\nscapegoated\nscapegoating\nscapegoatings\nscapegoatism\nscapegoatisms\nscapegoats\nscapegrace\nscapegraces\nscapes\nscaphoid\nscaphoids\nscaping\nscapolite\nscapolites\nscapose\nscapula\nscapulae\nscapular\nscapulars\nscapulas\nscar\nscarab\nscarabaei\nscarabaeus\nscarabaeuses\nscarabs\nscaramouch\nscaramouche\nscaramouches\nscarce\nscarcely\nscarceness\nscarcenesses\nscarcer\nscarcest\nscarcities\nscarcity\nscare\nscarecrow\nscarecrows\nscared\nscarehead\nscareheads\nscaremonger\nscaremongers\nscarer\nscarers\nscares\nscarey\nscarf\nscarfed\nscarfing\nscarfpin\nscarfpins\nscarfs\nscarfskin\nscarfskins\nscarier\nscariest\nscarification\nscarifications\nscarified\nscarifier\nscarifiers\nscarifies\nscarify\nscarifying\nscarifyingly\nscarily\nscaring\nscariose\nscarious\nscarlatina\nscarlatinal\nscarlatinas\nscarless\nscarlet\nscarlets\nscarp\nscarped\nscarper\nscarpered\nscarpering\nscarpers\nscarph\nscarphed\nscarphing\nscarphs\nscarping\nscarps\nscarred\nscarrier\nscarriest\nscarring\nscarry\nscars\nscart\nscarted\nscarting\nscarts\nscarves\nscary\nscat\nscatback\nscatbacks\nscathe\nscathed\nscatheless\nscathes\nscathing\nscathingly\nscatological\nscatologies\nscatology\nscats\nscatt\nscatted\nscatter\nscatteration\nscatterations\nscatterbrain\nscatterbrained\nscatterbrains\nscattered\nscatterer\nscatterers\nscattergood\nscattergoods\nscattergram\nscattergrams\nscattergun\nscatterguns\nscattering\nscatteringly\nscatterings\nscatters\nscattershot\nscattier\nscattiest\nscatting\nscatts\nscatty\nscaup\nscauper\nscaupers\nscaups\nscaur\nscaurs\nscavenge\nscavenged\nscavenger\nscavengers\nscavenges\nscavenging\nscena\nscenario\nscenarios\nscenarist\nscenarists\nscenas\nscend\nscended\nscending\nscends\nscene\nsceneries\nscenery\nscenes\nsceneshifter\nsceneshifters\nscenic\nscenical\nscenically\nscenographer\nscenographers\nscenographic\nscenographies\nscenography\nscent\nscented\nscenting\nscentless\nscents\nscepter\nsceptered\nsceptering\nscepters\nsceptic\nsceptical\nscepticism\nscepticisms\nsceptics\nsceptral\nsceptre\nsceptred\nsceptres\nsceptring\nschadenfreude\nschadenfreudes\nschappe\nschappes\nschav\nschavs\nschedule\nscheduled\nscheduler\nschedulers\nschedules\nscheduling\nscheelite\nscheelites\nschema\nschemas\nschemata\nschematic\nschematically\nschematics\nschematism\nschematisms\nschematization\nschematizations\nschematize\nschematized\nschematizes\nschematizing\nscheme\nschemed\nschemer\nschemers\nschemes\nscheming\nscherzando\nscherzandos\nscherzi\nscherzo\nscherzos\nschiller\nschillers\nschilling\nschillings\nschipperke\nschipperkes\nschism\nschismatic\nschismatical\nschismatically\nschismatics\nschismatize\nschismatized\nschismatizes\nschismatizing\nschisms\nschist\nschistose\nschistosities\nschistosity\nschistosomal\nschistosome\nschistosomes\nschistosomiases\nschistosomiasis\nschists\nschizier\nschiziest\nschizo\nschizocarp\nschizocarps\nschizogonic\nschizogonies\nschizogonous\nschizogony\nschizoid\nschizoids\nschizont\nschizonts\nschizophrene\nschizophrenes\nschizophrenia\nschizophrenias\nschizophrenic\nschizophrenically\nschizophrenics\nschizos\nschizy\nschizzier\nschizziest\nschizzy\nschlemiel\nschlemiels\nschlep\nschlepp\nschlepped\nschlepping\nschlepps\nschleps\nschliere\nschlieren\nschlieric\nschlock\nschlockmeister\nschlockmeisters\nschlocks\nschlocky\nschlump\nschlumped\nschlumping\nschlumps\nschmaltz\nschmaltzes\nschmaltzier\nschmaltziest\nschmaltzy\nschmalz\nschmalzes\nschmalzier\nschmalziest\nschmalzy\nschmear\nschmears\nschmeer\nschmeered\nschmeering\nschmeers\nschmelze\nschmelzes\nschmo\nschmoe\nschmoes\nschmoos\nschmoose\nschmoosed\nschmooses\nschmoosing\nschmooze\nschmoozed\nschmoozes\nschmoozing\nschmos\nschmuck\nschmucks\nschnapps\nschnaps\nschnauzer\nschnauzers\nschnecke\nschnecken\nschnitzel\nschnitzels\nschnook\nschnooks\nschnorkel\nschnorkeled\nschnorkeling\nschnorkels\nschnorrer\nschnorrers\nschnoz\nschnozes\nschnozz\nschnozzes\nschnozzle\nschnozzles\nscholar\nscholarly\nscholars\nscholarship\nscholarships\nscholastic\nscholastically\nscholasticate\nscholasticates\nscholasticism\nscholasticisms\nscholastics\nscholia\nscholiast\nscholiastic\nscholiasts\nscholium\nscholiums\nschool\nschoolbag\nschoolbags\nschoolbook\nschoolbooks\nschoolboy\nschoolboyish\nschoolboys\nschoolchild\nschoolchildren\nschooled\nschoolfellow\nschoolfellows\nschoolgirl\nschoolgirls\nschoolhouse\nschoolhouses\nschooling\nschoolings\nschoolkid\nschoolkids\nschoolman\nschoolmarm\nschoolmarmish\nschoolmarms\nschoolmaster\nschoolmasterish\nschoolmasterly\nschoolmasters\nschoolmate\nschoolmates\nschoolmen\nschoolmistress\nschoolmistresses\nschoolroom\nschoolrooms\nschools\nschoolteacher\nschoolteachers\nschooltime\nschooltimes\nschoolwork\nschoolworks\nschoolyard\nschoolyards\nschooner\nschooners\nschorl\nschorls\nschottische\nschottisches\nschrik\nschriks\nschrod\nschrods\nschtick\nschticks\nschtik\nschtiks\nschuit\nschuits\nschul\nschuln\nschuss\nschussboomer\nschussboomers\nschussed\nschusser\nschussers\nschusses\nschussing\nschwa\nschwarmerei\nschwarmereis\nschwas\nsciaenid\nsciaenids\nsciatic\nsciatica\nsciaticas\nsciatics\nscience\nsciences\nsciential\nscientific\nscientifically\nscientism\nscientisms\nscientist\nscientists\nscientize\nscientized\nscientizes\nscientizing\nscilicet\nscilla\nscillas\nscimetar\nscimetars\nscimitar\nscimitars\nscimiter\nscimiters\nscincoid\nscincoids\nscintigraphic\nscintigraphies\nscintigraphy\nscintilla\nscintillant\nscintillantly\nscintillas\nscintillate\nscintillated\nscintillates\nscintillating\nscintillation\nscintillations\nscintillator\nscintillators\nscintillometer\nscintillometers\nsciolism\nsciolisms\nsciolist\nsciolistic\nsciolists\nscion\nscions\nscirocco\nsciroccos\nscirrhi\nscirrhous\nscirrhus\nscirrhuses\nscissile\nscission\nscissions\nscissor\nscissored\nscissoring\nscissors\nscissortail\nscissortails\nscissure\nscissures\nsciurid\nsciurids\nsciurine\nsciurines\nsciuroid\nsclaff\nsclaffed\nsclaffer\nsclaffers\nsclaffing\nsclaffs\nsclera\nsclerae\nscleral\nscleras\nsclereid\nsclereids\nsclerenchyma\nsclerenchymas\nsclerenchymata\nsclerenchymatous\nsclerite\nsclerites\nscleroderma\nsclerodermas\nsclerodermata\nscleroid\nscleroma\nscleromas\nscleromata\nsclerometer\nsclerometers\nscleroprotein\nscleroproteins\nsclerose\nsclerosed\nscleroses\nsclerosing\nsclerosis\nsclerotia\nsclerotial\nsclerotic\nsclerotics\nsclerotin\nsclerotins\nsclerotium\nsclerotization\nsclerotizations\nsclerotized\nsclerous\nscoff\nscoffed\nscoffer\nscoffers\nscoffing\nscofflaw\nscofflaws\nscoffs\nscold\nscolded\nscolder\nscolders\nscolding\nscoldings\nscolds\nscoleces\nscolecite\nscolecites\nscolex\nscolices\nscolioma\nscoliomas\nscolioses\nscoliosis\nscoliotic\nscollop\nscolloped\nscolloping\nscollops\nscolopendra\nscolopendras\nscombroid\nscombroids\nsconce\nsconced\nsconces\nsconcing\nscone\nscones\nscoop\nscooped\nscooper\nscoopers\nscoopful\nscoopfuls\nscooping\nscoops\nscoopsful\nscoot\nscooted\nscooter\nscooters\nscooting\nscoots\nscop\nscope\nscoped\nscopes\nscoping\nscopolamine\nscopolamines\nscops\nscopula\nscopulae\nscopulas\nscorbutic\nscorch\nscorched\nscorcher\nscorchers\nscorches\nscorching\nscorchingly\nscore\nscoreboard\nscoreboards\nscorecard\nscorecards\nscored\nscorekeeper\nscorekeepers\nscoreless\nscorepad\nscorepads\nscorer\nscorers\nscores\nscoria\nscoriaceous\nscoriae\nscorified\nscorifies\nscorify\nscorifying\nscoring\nscorn\nscorned\nscorner\nscorners\nscornful\nscornfully\nscornfulness\nscornfulnesses\nscorning\nscorns\nscorpaenid\nscorpaenids\nscorpion\nscorpions\nscot\nscotch\nscotched\nscotches\nscotching\nscoter\nscoters\nscotia\nscotias\nscotoma\nscotomas\nscotomata\nscotopia\nscotopias\nscotopic\nscots\nscottie\nscotties\nscoundrel\nscoundrelly\nscoundrels\nscour\nscoured\nscourer\nscourers\nscourge\nscourged\nscourger\nscourgers\nscourges\nscourging\nscouring\nscourings\nscours\nscouse\nscouses\nscout\nscoutcraft\nscoutcrafts\nscouted\nscouter\nscouters\nscouth\nscouther\nscouthered\nscouthering\nscouthers\nscouths\nscouting\nscoutings\nscoutmaster\nscoutmasters\nscouts\nscow\nscowder\nscowdered\nscowdering\nscowders\nscowed\nscowing\nscowl\nscowled\nscowler\nscowlers\nscowling\nscowlingly\nscowls\nscows\nscrabble\nscrabbled\nscrabbler\nscrabblers\nscrabbles\nscrabblier\nscrabbliest\nscrabbling\nscrabbly\nscrag\nscragged\nscraggier\nscraggiest\nscragging\nscragglier\nscraggliest\nscraggly\nscraggy\nscrags\nscraich\nscraiched\nscraiching\nscraichs\nscraigh\nscraighed\nscraighing\nscraighs\nscram\nscramble\nscrambled\nscrambler\nscramblers\nscrambles\nscrambling\nscramjet\nscramjets\nscrammed\nscramming\nscrams\nscrannel\nscrannels\nscrap\nscrapbook\nscrapbooks\nscrape\nscraped\nscraper\nscrapers\nscrapes\nscrapheap\nscrapheaps\nscrapie\nscrapies\nscraping\nscrapings\nscrappage\nscrappages\nscrapped\nscrapper\nscrappers\nscrappier\nscrappiest\nscrappily\nscrappiness\nscrappinesses\nscrapping\nscrapple\nscrapples\nscrappy\nscraps\nscratch\nscratchboard\nscratchboards\nscratched\nscratcher\nscratchers\nscratches\nscratchier\nscratchiest\nscratchily\nscratchiness\nscratchinesses\nscratching\nscratchy\nscrawl\nscrawled\nscrawler\nscrawlers\nscrawlier\nscrawliest\nscrawling\nscrawls\nscrawly\nscrawnier\nscrawniest\nscrawniness\nscrawninesses\nscrawny\nscreak\nscreaked\nscreaking\nscreaks\nscreaky\nscream\nscreamed\nscreamer\nscreamers\nscreaming\nscreamingly\nscreams\nscree\nscreech\nscreeched\nscreecher\nscreechers\nscreeches\nscreechier\nscreechiest\nscreeching\nscreechy\nscreed\nscreeded\nscreeding\nscreeds\nscreen\nscreenable\nscreened\nscreener\nscreeners\nscreening\nscreenings\nscreenland\nscreenlands\nscreenplay\nscreenplays\nscreens\nscreenwriter\nscreenwriters\nscrees\nscrew\nscrewball\nscrewballs\nscrewbean\nscrewbeans\nscrewdriver\nscrewdrivers\nscrewed\nscrewer\nscrewers\nscrewier\nscrewiest\nscrewiness\nscrewinesses\nscrewing\nscrewlike\nscrews\nscrewup\nscrewups\nscrewworm\nscrewworms\nscrewy\nscribal\nscribble\nscribbled\nscribbler\nscribblers\nscribbles\nscribbling\nscribblings\nscribe\nscribed\nscriber\nscribers\nscribes\nscribing\nscried\nscries\nscrieve\nscrieved\nscrieves\nscrieving\nscrim\nscrimmage\nscrimmaged\nscrimmager\nscrimmagers\nscrimmages\nscrimmaging\nscrimp\nscrimped\nscrimper\nscrimpers\nscrimpier\nscrimpiest\nscrimping\nscrimpit\nscrimps\nscrimpy\nscrims\nscrimshander\nscrimshanders\nscrimshaw\nscrimshawed\nscrimshawing\nscrimshaws\nscrip\nscrips\nscript\nscripted\nscripter\nscripters\nscripting\nscriptoria\nscriptorium\nscriptoriums\nscripts\nscriptural\nscripturally\nscripture\nscriptures\nscriptwriter\nscriptwriters\nscrive\nscrived\nscrivener\nscriveners\nscrives\nscriving\nscrod\nscrods\nscrofula\nscrofulas\nscrofulous\nscroggier\nscroggiest\nscroggy\nscroll\nscrolled\nscrolling\nscrolls\nscrollwork\nscrollworks\nscrooch\nscrooched\nscrooches\nscrooching\nscrooge\nscrooges\nscroop\nscrooped\nscrooping\nscroops\nscrootch\nscrootched\nscrootches\nscrootching\nscrota\nscrotal\nscrotum\nscrotums\nscrouge\nscrouged\nscrouges\nscrouging\nscrounge\nscrounged\nscrounger\nscroungers\nscrounges\nscroungier\nscroungiest\nscrounging\nscroungy\nscrub\nscrubbable\nscrubbed\nscrubber\nscrubbers\nscrubbier\nscrubbiest\nscrubbing\nscrubby\nscrubland\nscrublands\nscrubs\nscrubwoman\nscrubwomen\nscruff\nscruffier\nscruffiest\nscruffily\nscruffiness\nscruffinesses\nscruffs\nscruffy\nscrum\nscrummage\nscrummaged\nscrummages\nscrummaging\nscrummed\nscrumming\nscrumptious\nscrumptiously\nscrums\nscrunch\nscrunched\nscrunches\nscrunching\nscruple\nscrupled\nscruples\nscrupling\nscrupulosities\nscrupulosity\nscrupulous\nscrupulously\nscrupulousness\nscrupulousnesses\nscrutable\nscrutineer\nscrutineers\nscrutinies\nscrutinise\nscrutinised\nscrutinises\nscrutinising\nscrutinize\nscrutinized\nscrutinizer\nscrutinizers\nscrutinizes\nscrutinizing\nscrutiny\nscry\nscrying\nscuba\nscubas\nscud\nscudded\nscudding\nscudi\nscudo\nscuds\nscuff\nscuffed\nscuffing\nscuffle\nscuffled\nscuffler\nscufflers\nscuffles\nscuffling\nscuffs\nsculk\nsculked\nsculker\nsculkers\nsculking\nsculks\nscull\nsculled\nsculler\nsculleries\nscullers\nscullery\nsculling\nscullion\nscullions\nsculls\nsculp\nsculped\nsculpin\nsculping\nsculpins\nsculps\nsculpt\nsculpted\nsculpting\nsculptor\nsculptors\nsculptress\nsculptresses\nsculpts\nsculptural\nsculpturally\nsculpture\nsculptured\nsculptures\nsculpturesque\nsculpturesquely\nsculpturing\nscum\nscumbag\nscumbags\nscumble\nscumbled\nscumbles\nscumbling\nscumlike\nscummed\nscummer\nscummers\nscummier\nscummiest\nscumming\nscummy\nscums\nscungilli\nscungillis\nscunner\nscunnered\nscunnering\nscunners\nscup\nscuppaug\nscuppaugs\nscupper\nscuppered\nscuppering\nscuppernong\nscuppernongs\nscuppers\nscups\nscurf\nscurfier\nscurfiest\nscurfs\nscurfy\nscurried\nscurries\nscurril\nscurrile\nscurrilities\nscurrility\nscurrilous\nscurrilously\nscurrilousness\nscurrilousnesses\nscurry\nscurrying\nscurvier\nscurvies\nscurviest\nscurvily\nscurviness\nscurvinesses\nscurvy\nscut\nscuta\nscutage\nscutages\nscutate\nscutch\nscutched\nscutcheon\nscutcheons\nscutcher\nscutchers\nscutches\nscutching\nscute\nscutella\nscutellar\nscutellate\nscutellated\nscutellum\nscutes\nscuts\nscutter\nscuttered\nscuttering\nscutters\nscuttle\nscuttlebutt\nscuttlebutts\nscuttled\nscuttles\nscuttling\nscutum\nscuzzier\nscuzziest\nscuzzy\nscyphate\nscyphi\nscyphistoma\nscyphistomae\nscyphistomas\nscyphozoan\nscyphozoans\nscyphus\nscythe\nscythed\nscythes\nscything\nsea\nseabag\nseabags\nseabeach\nseabeaches\nseabed\nseabeds\nseabird\nseabirds\nseaboard\nseaboards\nseaboot\nseaboots\nseaborgium\nseaborgiums\nseaborne\nseacoast\nseacoasts\nseacock\nseacocks\nseacraft\nseacrafts\nseadog\nseadogs\nseadrome\nseadromes\nseafarer\nseafarers\nseafaring\nseafarings\nseafloor\nseafloors\nseafood\nseafoods\nseafowl\nseafowls\nseafront\nseafronts\nseagirt\nseagoing\nseagull\nseagulls\nseal\nsealable\nsealant\nsealants\nsealed\nsealer\nsealeries\nsealers\nsealery\nsealing\nseallike\nseals\nsealskin\nsealskins\nseam\nseaman\nseamanlike\nseamanly\nseamanship\nseamanships\nseamark\nseamarks\nseamed\nseamen\nseamer\nseamers\nseamier\nseamiest\nseaminess\nseaminesses\nseaming\nseamless\nseamlessly\nseamlessness\nseamlessnesses\nseamlike\nseamount\nseamounts\nseams\nseamster\nseamsters\nseamstress\nseamstresses\nseamy\nseance\nseances\nseapiece\nseapieces\nseaplane\nseaplanes\nseaport\nseaports\nseaquake\nseaquakes\nsear\nsearch\nsearchable\nsearched\nsearcher\nsearchers\nsearches\nsearching\nsearchingly\nsearchless\nsearchlight\nsearchlights\nseared\nsearer\nsearest\nsearing\nsearingly\nsearobin\nsearobins\nsears\nseas\nseascape\nseascapes\nseascout\nseascouts\nseashell\nseashells\nseashore\nseashores\nseasick\nseasickness\nseasicknesses\nseaside\nseasides\nseason\nseasonable\nseasonableness\nseasonablenesses\nseasonably\nseasonal\nseasonalities\nseasonality\nseasonally\nseasoned\nseasoner\nseasoners\nseasoning\nseasonings\nseasonless\nseasons\nseastrand\nseastrands\nseat\nseatbelt\nseatbelts\nseated\nseater\nseaters\nseating\nseatings\nseatless\nseatmate\nseatmates\nseatrain\nseatrains\nseats\nseatwork\nseatworks\nseawall\nseawalls\nseawan\nseawans\nseawant\nseawants\nseaward\nseawards\nseaware\nseawares\nseawater\nseawaters\nseaway\nseaways\nseaweed\nseaweeds\nseaworthiness\nseaworthinesses\nseaworthy\nsebaceous\nsebacic\nsebasic\nseborrhea\nseborrheas\nseborrheic\nsebum\nsebums\nsec\nsecalose\nsecaloses\nsecant\nsecantly\nsecants\nsecateur\nsecateurs\nsecco\nseccos\nsecede\nseceded\nseceder\nseceders\nsecedes\nseceding\nsecern\nsecerned\nsecerning\nsecerns\nsecession\nsecessionism\nsecessionisms\nsecessionist\nsecessionists\nsecessions\nseclude\nsecluded\nsecludedly\nsecludedness\nsecludednesses\nsecludes\nsecluding\nseclusion\nseclusions\nseclusive\nseclusively\nseclusiveness\nseclusivenesses\nsecobarbital\nsecobarbitals\nsecond\nsecondaries\nsecondarily\nsecondariness\nsecondarinesses\nsecondary\nseconde\nseconded\nseconder\nseconders\nsecondes\nsecondhand\nsecondi\nseconding\nsecondly\nsecondo\nseconds\nsecpar\nsecpars\nsecrecies\nsecrecy\nsecret\nsecretagogue\nsecretagogues\nsecretarial\nsecretariat\nsecretariats\nsecretaries\nsecretary\nsecretaryship\nsecretaryships\nsecrete\nsecreted\nsecreter\nsecretes\nsecretest\nsecretin\nsecreting\nsecretins\nsecretion\nsecretionary\nsecretions\nsecretive\nsecretively\nsecretiveness\nsecretivenesses\nsecretly\nsecretor\nsecretors\nsecretory\nsecrets\nsecs\nsect\nsectarian\nsectarianism\nsectarianisms\nsectarianize\nsectarianized\nsectarianizes\nsectarianizing\nsectarians\nsectaries\nsectary\nsectile\nsectilities\nsectility\nsection\nsectional\nsectionalism\nsectionalisms\nsectionally\nsectionals\nsectioned\nsectioning\nsections\nsector\nsectoral\nsectored\nsectorial\nsectoring\nsectors\nsects\nsecular\nsecularise\nsecularised\nsecularises\nsecularising\nsecularism\nsecularisms\nsecularist\nsecularistic\nsecularists\nsecularities\nsecularity\nsecularization\nsecularizations\nsecularize\nsecularized\nsecularizer\nsecularizers\nsecularizes\nsecularizing\nsecularly\nseculars\nsecund\nsecundly\nsecundum\nsecure\nsecured\nsecurely\nsecurement\nsecurements\nsecureness\nsecurenesses\nsecurer\nsecurers\nsecures\nsecurest\nsecuring\nsecurities\nsecuritization\nsecuritizations\nsecuritize\nsecuritized\nsecuritizes\nsecuritizing\nsecurity\nsedan\nsedans\nsedarim\nsedate\nsedated\nsedately\nsedateness\nsedatenesses\nsedater\nsedates\nsedatest\nsedating\nsedation\nsedations\nsedative\nsedatives\nsedentary\nseder\nseders\nsederunt\nsederunts\nsedge\nsedges\nsedgier\nsedgiest\nsedgy\nsedile\nsedilia\nsedilium\nsediment\nsedimentable\nsedimentary\nsedimentation\nsedimentations\nsedimented\nsedimenting\nsedimentologic\nsedimentological\nsedimentologically\nsedimentologies\nsedimentologist\nsedimentologists\nsedimentology\nsediments\nsedition\nseditions\nseditious\nseditiously\nseditiousness\nseditiousnesses\nseduce\nseduced\nseducement\nseducements\nseducer\nseducers\nseduces\nseducing\nseducive\nseduction\nseductions\nseductive\nseductively\nseductiveness\nseductivenesses\nseductress\nseductresses\nsedulities\nsedulity\nsedulous\nsedulously\nsedulousness\nsedulousnesses\nsedum\nsedums\nsee\nseeable\nseecatch\nseecatchie\nseed\nseedbed\nseedbeds\nseedcake\nseedcakes\nseedcase\nseedcases\nseedeater\nseedeaters\nseeded\nseeder\nseeders\nseedier\nseediest\nseedily\nseediness\nseedinesses\nseeding\nseedless\nseedlike\nseedling\nseedlings\nseedman\nseedmen\nseedpod\nseedpods\nseeds\nseedsman\nseedsmen\nseedtime\nseedtimes\nseedy\nseeing\nseeings\nseek\nseeker\nseekers\nseeking\nseeks\nseel\nseeled\nseeling\nseels\nseely\nseem\nseemed\nseemer\nseemers\nseeming\nseemingly\nseemings\nseemlier\nseemliest\nseemliness\nseemlinesses\nseemly\nseems\nseen\nseep\nseepage\nseepages\nseeped\nseepier\nseepiest\nseeping\nseeps\nseepy\nseer\nseeress\nseeresses\nseers\nseersucker\nseersuckers\nsees\nseesaw\nseesawed\nseesawing\nseesaws\nseethe\nseethed\nseethes\nseething\nseg\nsegetal\nseggar\nseggars\nsegment\nsegmental\nsegmentally\nsegmentary\nsegmentation\nsegmentations\nsegmented\nsegmenting\nsegments\nsegni\nsegno\nsegnos\nsego\nsegos\nsegregant\nsegregants\nsegregate\nsegregated\nsegregates\nsegregating\nsegregation\nsegregationist\nsegregationists\nsegregations\nsegregative\nsegs\nsegue\nsegued\nsegueing\nsegues\nseguidilla\nseguidillas\nsei\nseicento\nseicentos\nseiche\nseiches\nseidel\nseidels\nseif\nseifs\nseigneur\nseigneurial\nseigneuries\nseigneurs\nseigneury\nseignior\nseigniorage\nseigniorages\nseigniories\nseigniors\nseigniory\nseignorage\nseignorages\nseignorial\nseignories\nseignory\nseine\nseined\nseiner\nseiners\nseines\nseining\nseis\nseisable\nseise\nseised\nseiser\nseisers\nseises\nseisin\nseising\nseisings\nseisins\nseism\nseismal\nseismic\nseismically\nseismicities\nseismicity\nseismism\nseismisms\nseismogram\nseismograms\nseismograph\nseismographer\nseismographers\nseismographic\nseismographies\nseismographs\nseismography\nseismological\nseismologies\nseismologist\nseismologists\nseismology\nseismometer\nseismometers\nseismometric\nseismometries\nseismometry\nseisms\nseisor\nseisors\nseisure\nseisures\nseizable\nseize\nseized\nseizer\nseizers\nseizes\nseizin\nseizing\nseizings\nseizins\nseizor\nseizors\nseizure\nseizures\nsejant\nsejeant\nsel\nselachian\nselachians\nseladang\nseladangs\nselaginella\nselaginellas\nselah\nselahs\nselamlik\nselamliks\nselcouth\nseldom\nseldomly\nselect\nselectable\nselected\nselectee\nselectees\nselecting\nselection\nselectionist\nselectionists\nselections\nselective\nselectively\nselectiveness\nselectivenesses\nselectivities\nselectivity\nselectly\nselectman\nselectmen\nselectness\nselectnesses\nselector\nselectors\nselects\nselenate\nselenates\nselenic\nselenide\nselenides\nseleniferous\nselenite\nselenites\nselenium\nseleniums\nselenocentric\nselenological\nselenologies\nselenologist\nselenologists\nselenology\nselenous\nself\nselfdom\nselfdoms\nselfed\nselfheal\nselfheals\nselfhood\nselfhoods\nselfing\nselfish\nselfishly\nselfishness\nselfishnesses\nselfless\nselflessly\nselflessness\nselflessnesses\nselfness\nselfnesses\nselfs\nselfsame\nselfsameness\nselfsamenesses\nselfward\nsell\nsellable\nselle\nseller\nsellers\nselles\nselling\nsellout\nsellouts\nsells\nsels\nselsyn\nselsyns\nseltzer\nseltzers\nselva\nselvage\nselvaged\nselvages\nselvas\nselvedge\nselvedged\nselvedges\nselves\nsemantic\nsemantical\nsemantically\nsemanticist\nsemanticists\nsemantics\nsemaphore\nsemaphored\nsemaphores\nsemaphoring\nsemasiological\nsemasiologies\nsemasiology\nsematic\nsemblable\nsemblables\nsemblably\nsemblance\nsemblances\nseme\nsemeiologies\nsemeiology\nsemeiotic\nsemeiotics\nsememe\nsememes\nsememic\nsemen\nsemens\nsemes\nsemester\nsemesters\nsemestral\nsemestrial\nsemi\nsemiabstract\nsemiabstraction\nsemiabstractions\nsemiannual\nsemiannually\nsemiaquatic\nsemiarboreal\nsemiarid\nsemiaridities\nsemiaridity\nsemiautobiographical\nsemiautomatic\nsemiautomatically\nsemiautomatics\nsemiautonomous\nsemibald\nsemibreve\nsemibreves\nsemicentennial\nsemicentennials\nsemicircle\nsemicircles\nsemicircular\nsemicivilized\nsemiclassic\nsemiclassical\nsemiclassics\nsemicolon\nsemicolonial\nsemicolonialism\nsemicolonialisms\nsemicolonies\nsemicolons\nsemicolony\nsemicoma\nsemicomas\nsemicommercial\nsemiconducting\nsemiconductor\nsemiconductors\nsemiconscious\nsemiconsciousness\nsemiconsciousnesses\nsemiconservative\nsemiconservatively\nsemicrystalline\nsemicylindrical\nsemidarkness\nsemidarknesses\nsemideaf\nsemideified\nsemideifies\nsemideify\nsemideifying\nsemidesert\nsemideserts\nsemidetached\nsemidiameter\nsemidiameters\nsemidiurnal\nsemidivine\nsemidocumentaries\nsemidocumentary\nsemidome\nsemidomed\nsemidomes\nsemidomesticated\nsemidomestication\nsemidomestications\nsemidominant\nsemidry\nsemidrying\nsemidwarf\nsemidwarfs\nsemidwarves\nsemiempirical\nsemierect\nsemievergreen\nsemifeudal\nsemifinal\nsemifinalist\nsemifinalists\nsemifinals\nsemifinished\nsemifit\nsemifitted\nsemiflexible\nsemifluid\nsemifluids\nsemiformal\nsemifunctional\nsemigala\nsemigloss\nsemigovernmental\nsemigroup\nsemigroups\nsemihard\nsemihigh\nsemihobo\nsemihoboes\nsemihobos\nsemilegendary\nsemilethal\nsemilethals\nsemiliquid\nsemiliquids\nsemiliterate\nsemiliterates\nsemilog\nsemilogarithmic\nsemilunar\nsemilustrous\nsemimat\nsemimatt\nsemimatte\nsemimetal\nsemimetallic\nsemimetals\nsemimicro\nsemimoist\nsemimonastic\nsemimonthlies\nsemimonthly\nsemimute\nsemimystical\nsemina\nseminal\nseminally\nseminar\nseminarian\nseminarians\nseminaries\nseminarist\nseminarists\nseminars\nseminary\nseminatural\nseminiferous\nseminomad\nseminomadic\nseminomads\nseminude\nseminudities\nseminudity\nsemiofficial\nsemiofficially\nsemiological\nsemiologically\nsemiologies\nsemiologist\nsemiologists\nsemiology\nsemiopaque\nsemioses\nsemiosis\nsemiotic\nsemiotician\nsemioticians\nsemioticist\nsemioticists\nsemiotics\nsemipalmated\nsemiparasite\nsemiparasites\nsemiparasitic\nsemipermanent\nsemipermeabilities\nsemipermeability\nsemipermeable\nsemipolitical\nsemipopular\nsemiporcelain\nsemiporcelains\nsemipornographic\nsemipornographies\nsemipornography\nsemipostal\nsemipostals\nsemiprecious\nsemiprivate\nsemipro\nsemiprofessional\nsemiprofessionally\nsemiprofessionals\nsemipros\nsemipublic\nsemiquantitative\nsemiquantitatively\nsemiquaver\nsemiquavers\nsemiraw\nsemireligious\nsemiretired\nsemiretirement\nsemiretirements\nsemirigid\nsemirural\nsemis\nsemisacred\nsemisecret\nsemisedentary\nsemises\nsemishrubby\nsemiskilled\nsemisoft\nsemisolid\nsemisolids\nsemisubmersible\nsemisubmersibles\nsemisweet\nsemisynthetic\nsemiterrestrial\nsemitist\nsemitists\nsemitonal\nsemitonally\nsemitone\nsemitones\nsemitonic\nsemitonically\nsemitrailer\nsemitrailers\nsemitranslucent\nsemitransparent\nsemitropic\nsemitropical\nsemitropics\nsemivowel\nsemivowels\nsemiweeklies\nsemiweekly\nsemiwild\nsemiworks\nsemiyearly\nsemolina\nsemolinas\nsempervivum\nsempervivums\nsempiternal\nsempiternally\nsempiternities\nsempiternity\nsemple\nsemplice\nsempre\nsempstress\nsempstresses\nsen\nsenarii\nsenarius\nsenary\nsenate\nsenates\nsenator\nsenatorial\nsenatorian\nsenators\nsenatorship\nsenatorships\nsend\nsendable\nsendal\nsendals\nsended\nsender\nsenders\nsending\nsendoff\nsendoffs\nsends\nsendup\nsendups\nsene\nseneca\nsenecas\nsenecio\nsenecios\nsenectitude\nsenectitudes\nsenega\nsenegas\nsenescence\nsenescences\nsenescent\nseneschal\nseneschals\nsengi\nsenhor\nsenhora\nsenhoras\nsenhores\nsenhorita\nsenhoritas\nsenhors\nsenile\nsenilely\nseniles\nsenilities\nsenility\nsenior\nseniorities\nseniority\nseniors\nseniti\nsenna\nsennas\nsennet\nsennets\nsennight\nsennights\nsennit\nsennits\nsenopia\nsenopias\nsenor\nsenora\nsenoras\nsenores\nsenorita\nsenoritas\nsenors\nsenryu\nsensa\nsensate\nsensated\nsensately\nsensates\nsensating\nsensation\nsensational\nsensationalise\nsensationalised\nsensationalises\nsensationalising\nsensationalism\nsensationalisms\nsensationalist\nsensationalistic\nsensationalists\nsensationalize\nsensationalized\nsensationalizes\nsensationalizing\nsensationally\nsensations\nsense\nsensed\nsenseful\nsenseless\nsenselessly\nsenselessness\nsenselessnesses\nsenses\nsensibilia\nsensibilities\nsensibility\nsensible\nsensibleness\nsensiblenesses\nsensibler\nsensibles\nsensiblest\nsensibly\nsensilla\nsensillae\nsensillum\nsensing\nsensitisation\nsensitisations\nsensitise\nsensitised\nsensitises\nsensitising\nsensitive\nsensitively\nsensitiveness\nsensitivenesses\nsensitives\nsensitivities\nsensitivity\nsensitization\nsensitizations\nsensitize\nsensitized\nsensitizer\nsensitizers\nsensitizes\nsensitizing\nsensitometer\nsensitometers\nsensitometric\nsensitometries\nsensitometry\nsensor\nsensoria\nsensorial\nsensorially\nsensorimotor\nsensorineural\nsensorium\nsensoriums\nsensors\nsensory\nsensual\nsensualism\nsensualisms\nsensualist\nsensualistic\nsensualists\nsensualities\nsensuality\nsensualization\nsensualizations\nsensualize\nsensualized\nsensualizes\nsensualizing\nsensually\nsensum\nsensuosities\nsensuosity\nsensuous\nsensuously\nsensuousness\nsensuousnesses\nsent\nsente\nsentence\nsentenced\nsentences\nsentencing\nsententia\nsententiae\nsentential\nsententious\nsententiously\nsententiousness\nsententiousnesses\nsenti\nsentience\nsentiences\nsentient\nsentiently\nsentients\nsentiment\nsentimental\nsentimentalise\nsentimentalised\nsentimentalises\nsentimentalising\nsentimentalism\nsentimentalisms\nsentimentalist\nsentimentalists\nsentimentalities\nsentimentality\nsentimentalization\nsentimentalizations\nsentimentalize\nsentimentalized\nsentimentalizes\nsentimentalizing\nsentimentally\nsentiments\nsentimo\nsentimos\nsentinel\nsentineled\nsentineling\nsentinelled\nsentinelling\nsentinels\nsentries\nsentry\nsepal\nsepaled\nsepaline\nsepalled\nsepaloid\nsepalous\nsepals\nseparabilities\nseparability\nseparable\nseparableness\nseparablenesses\nseparate\nseparated\nseparately\nseparateness\nseparatenesses\nseparates\nseparating\nseparation\nseparationist\nseparationists\nseparations\nseparatism\nseparatisms\nseparatist\nseparatistic\nseparatists\nseparative\nseparator\nseparators\nsepia\nsepias\nsepic\nsepiolite\nsepiolites\nsepoy\nsepoys\nseppuku\nseppukus\nsepses\nsepsis\nsept\nsepta\nseptal\nseptaria\nseptarium\nseptate\nseptenarii\nseptenarius\nseptendecillion\nseptendecillions\nseptennial\nseptennially\nseptentrion\nseptentrional\nseptentrions\nseptet\nseptets\nseptette\nseptettes\nseptic\nseptical\nsepticemia\nsepticemias\nsepticemic\nsepticidal\nseptics\nseptillion\nseptillions\nseptime\nseptimes\nsepts\nseptuagenarian\nseptuagenarians\nseptum\nseptums\nseptuple\nseptupled\nseptuples\nseptupling\nsepulcher\nsepulchered\nsepulchering\nsepulchers\nsepulchral\nsepulchrally\nsepulchre\nsepulchred\nsepulchres\nsepulchring\nsepulture\nsepultures\nsequacious\nsequaciously\nsequacities\nsequacity\nsequel\nsequela\nsequelae\nsequels\nsequence\nsequenced\nsequencer\nsequencers\nsequences\nsequencies\nsequencing\nsequency\nsequent\nsequential\nsequentially\nsequents\nsequester\nsequestered\nsequestering\nsequesters\nsequestra\nsequestrate\nsequestrated\nsequestrates\nsequestrating\nsequestration\nsequestrations\nsequestrum\nsequestrums\nsequin\nsequined\nsequinned\nsequins\nsequitur\nsequiturs\nsequoia\nsequoias\nser\nsera\nserac\nseracs\nseraglio\nseraglios\nserai\nserail\nserails\nserais\nseral\nserape\nserapes\nseraph\nseraphic\nseraphically\nseraphim\nseraphims\nseraphin\nseraphs\nserdab\nserdabs\nsere\nsered\nserein\nsereins\nserenade\nserenaded\nserenader\nserenaders\nserenades\nserenading\nserenata\nserenatas\nserenate\nserendipities\nserendipitous\nserendipitously\nserendipity\nserene\nserenely\nsereneness\nserenenesses\nserener\nserenes\nserenest\nserenities\nserenity\nserer\nseres\nserest\nserf\nserfage\nserfages\nserfdom\nserfdoms\nserfhood\nserfhoods\nserfish\nserflike\nserfs\nserge\nsergeancies\nsergeancy\nsergeant\nsergeanties\nsergeants\nsergeanty\nserges\nserging\nsergings\nserial\nserialise\nserialised\nserialises\nserialising\nserialism\nserialisms\nserialist\nserialists\nserialization\nserializations\nserialize\nserialized\nserializes\nserializing\nserially\nserials\nseriate\nseriated\nseriately\nseriates\nseriatim\nseriating\nsericeous\nsericin\nsericins\nsericultural\nsericulture\nsericultures\nsericulturist\nsericulturists\nseriema\nseriemas\nseries\nserif\nserifed\nseriffed\nserifs\nserigraph\nserigrapher\nserigraphers\nserigraphies\nserigraphs\nserigraphy\nserin\nserine\nserines\nsering\nseringa\nseringas\nserins\nseriocomic\nseriocomically\nserious\nseriously\nseriousness\nseriousnesses\nserjeant\nserjeanties\nserjeants\nserjeanty\nsermon\nsermonette\nsermonettes\nsermonic\nsermonize\nsermonized\nsermonizer\nsermonizers\nsermonizes\nsermonizing\nsermons\nseroconversion\nseroconversions\nserodiagnoses\nserodiagnosis\nserodiagnostic\nserologic\nserological\nserologically\nserologies\nserologist\nserologists\nserology\nseronegative\nseronegativities\nseronegativity\nseropositive\nseropositivities\nseropositivity\nseropurulent\nserosa\nserosae\nserosal\nserosas\nserosities\nserosity\nserotinal\nserotine\nserotines\nserotinous\nserotonergic\nserotonin\nserotoninergic\nserotonins\nserotype\nserotypes\nserous\nserow\nserows\nserpent\nserpentine\nserpentinely\nserpentines\nserpents\nserpigines\nserpiginous\nserpiginously\nserpigo\nserpigoes\nserranid\nserranids\nserrano\nserranos\nserrate\nserrated\nserrates\nserrating\nserration\nserrations\nserried\nserriedly\nserriedness\nserriednesses\nserries\nserry\nserrying\nsers\nserum\nserumal\nserums\nservable\nserval\nservals\nservant\nservanthood\nservanthoods\nservantless\nservants\nserve\nserved\nserver\nservers\nserves\nservice\nserviceabilities\nserviceability\nserviceable\nserviceableness\nserviceablenesses\nserviceably\nserviceberries\nserviceberry\nserviced\nserviceman\nservicemen\nservicer\nservicers\nservices\nservicewoman\nservicewomen\nservicing\nserviette\nserviettes\nservile\nservilely\nservileness\nservilenesses\nservilities\nservility\nserving\nservings\nservitor\nservitors\nservitude\nservitudes\nservo\nservomechanism\nservomechanisms\nservomotor\nservomotors\nservos\nsesame\nsesames\nsesamoid\nsesamoids\nsesquicarbonate\nsesquicarbonates\nsesquicentenaries\nsesquicentenary\nsesquicentennial\nsesquicentennials\nsesquipedalian\nsesquiterpene\nsesquiterpenes\nsessile\nsession\nsessional\nsessions\nsesspool\nsesspools\nsesterce\nsesterces\nsestertia\nsestertium\nsestet\nsestets\nsestina\nsestinas\nsestine\nsestines\nset\nseta\nsetaceous\nsetae\nsetal\nsetback\nsetbacks\nsetenant\nsetenants\nsetiform\nsetline\nsetlines\nsetoff\nsetoffs\nseton\nsetons\nsetose\nsetous\nsetout\nsetouts\nsets\nsetscrew\nsetscrews\nsett\nsettee\nsettees\nsetter\nsetters\nsetting\nsettings\nsettle\nsettleable\nsettled\nsettlement\nsettlements\nsettler\nsettlers\nsettles\nsettling\nsettlings\nsettlor\nsettlors\nsetts\nsetulose\nsetulous\nsetup\nsetups\nseven\nsevenfold\nsevens\nseventeen\nseventeens\nseventeenth\nseventeenths\nseventh\nsevenths\nseventies\nseventieth\nseventieths\nseventy\nsever\nseverabilities\nseverability\nseverable\nseveral\nseveralfold\nseverally\nseverals\nseveralties\nseveralty\nseverance\nseverances\nsevere\nsevered\nseverely\nsevereness\nseverenesses\nseverer\nseverest\nsevering\nseverities\nseverity\nsevers\nseviche\nseviches\nsevruga\nsevrugas\nsew\nsewabilities\nsewability\nsewable\nsewage\nsewages\nsewan\nsewans\nsewar\nsewars\nsewed\nsewer\nsewerage\nsewerages\nsewered\nsewering\nsewers\nsewing\nsewings\nsewn\nsews\nsex\nsexagenarian\nsexagenarians\nsexagesimal\nsexagesimals\nsexdecillion\nsexdecillions\nsexed\nsexes\nsexier\nsexiest\nsexily\nsexiness\nsexinesses\nsexing\nsexism\nsexisms\nsexist\nsexists\nsexless\nsexlessly\nsexlessness\nsexlessnesses\nsexologies\nsexologist\nsexologists\nsexology\nsexploitation\nsexploitations\nsexpot\nsexpots\nsext\nsextain\nsextains\nsextan\nsextans\nsextant\nsextants\nsextarii\nsextarius\nsextet\nsextets\nsextette\nsextettes\nsextile\nsextiles\nsextillion\nsextillions\nsexto\nsextodecimo\nsextodecimos\nsexton\nsextons\nsextos\nsexts\nsextuple\nsextupled\nsextuples\nsextuplet\nsextuplets\nsextuplicate\nsextuplicated\nsextuplicates\nsextuplicating\nsextupling\nsextuply\nsexual\nsexualities\nsexuality\nsexualization\nsexualizations\nsexualize\nsexualized\nsexualizes\nsexualizing\nsexually\nsexy\nsferics\nsforzandi\nsforzando\nsforzandos\nsforzato\nsforzatos\nsfumato\nsfumatos\nsgraffiti\nsgraffito\nsh\nsha\nshabbier\nshabbiest\nshabbily\nshabbiness\nshabbinesses\nshabby\nshack\nshackle\nshacklebone\nshacklebones\nshackled\nshackler\nshacklers\nshackles\nshackling\nshacko\nshackoes\nshackos\nshacks\nshad\nshadberries\nshadberry\nshadblow\nshadblows\nshadbush\nshadbushes\nshadchan\nshadchanim\nshadchans\nshaddock\nshaddocks\nshade\nshaded\nshadeless\nshader\nshaders\nshades\nshadflies\nshadfly\nshadier\nshadiest\nshadily\nshadiness\nshadinesses\nshading\nshadings\nshadoof\nshadoofs\nshadow\nshadowbox\nshadowboxed\nshadowboxes\nshadowboxing\nshadowed\nshadower\nshadowers\nshadowgraph\nshadowgraphies\nshadowgraphs\nshadowgraphy\nshadowier\nshadowiest\nshadowily\nshadowiness\nshadowinesses\nshadowing\nshadowless\nshadowlike\nshadows\nshadowy\nshadrach\nshadrachs\nshads\nshaduf\nshadufs\nshady\nshaft\nshafted\nshafting\nshaftings\nshafts\nshag\nshagbark\nshagbarks\nshagged\nshaggier\nshaggiest\nshaggily\nshagginess\nshagginesses\nshagging\nshaggy\nshaggymane\nshaggymanes\nshagreen\nshagreens\nshags\nshah\nshahdom\nshahdoms\nshahs\nshaird\nshairds\nshairn\nshairns\nshaitan\nshaitans\nshakable\nshake\nshakeable\nshakedown\nshakedowns\nshaken\nshakeout\nshakeouts\nshaker\nshakers\nshakes\nshakeup\nshakeups\nshakier\nshakiest\nshakily\nshakiness\nshakinesses\nshaking\nshako\nshakoes\nshakos\nshaky\nshale\nshaled\nshales\nshaley\nshalier\nshaliest\nshall\nshalloon\nshalloons\nshallop\nshallops\nshallot\nshallots\nshallow\nshallowed\nshallower\nshallowest\nshallowing\nshallowly\nshallowness\nshallownesses\nshallows\nshalom\nshaloms\nshalt\nshaly\nsham\nshamable\nshaman\nshamanic\nshamanism\nshamanisms\nshamanist\nshamanistic\nshamanists\nshamans\nshamas\nshamble\nshambled\nshambles\nshambling\nshambolic\nshame\nshamed\nshamefaced\nshamefacedly\nshamefacedness\nshamefacednesses\nshamefast\nshameful\nshamefully\nshamefulness\nshamefulnesses\nshameless\nshamelessly\nshamelessness\nshamelessnesses\nshames\nshaming\nshammas\nshammash\nshammashim\nshammasim\nshammed\nshammer\nshammers\nshammes\nshammied\nshammies\nshamming\nshammos\nshammosim\nshammy\nshammying\nshamois\nshamos\nshamosim\nshamoy\nshamoyed\nshamoying\nshamoys\nshampoo\nshampooed\nshampooer\nshampooers\nshampooing\nshampoos\nshamrock\nshamrocks\nshams\nshamus\nshamuses\nshandies\nshandy\nshandygaff\nshandygaffs\nshanghai\nshanghaied\nshanghaier\nshanghaiers\nshanghaiing\nshanghais\nshank\nshanked\nshanking\nshankpiece\nshankpieces\nshanks\nshannies\nshanny\nshantey\nshanteys\nshanti\nshanties\nshantih\nshantihs\nshantis\nshantung\nshantungs\nshanty\nshantyman\nshantymen\nshantytown\nshantytowns\nshapable\nshape\nshapeable\nshaped\nshapeless\nshapelessly\nshapelessness\nshapelessnesses\nshapelier\nshapeliest\nshapeliness\nshapelinesses\nshapely\nshapen\nshaper\nshapers\nshapes\nshapeup\nshapeups\nshaping\nsharable\nshard\nshards\nshare\nshareabilities\nshareability\nshareable\nsharecrop\nsharecropped\nsharecropper\nsharecroppers\nsharecropping\nsharecrops\nshared\nshareholder\nshareholders\nsharer\nsharers\nshares\nshareware\nsharewares\nsharif\nsharifian\nsharifs\nsharing\nshark\nsharked\nsharker\nsharkers\nsharking\nsharklike\nsharks\nsharkskin\nsharkskins\nsharn\nsharns\nsharny\nsharp\nsharped\nsharpen\nsharpened\nsharpener\nsharpeners\nsharpening\nsharpens\nsharper\nsharpers\nsharpest\nsharpie\nsharpies\nsharping\nsharply\nsharpness\nsharpnesses\nsharps\nsharpshooter\nsharpshooters\nsharpshooting\nsharpshootings\nsharpy\nshashlick\nshashlicks\nshashlik\nshashliks\nshaslik\nshasliks\nshat\nshatter\nshattered\nshattering\nshatteringly\nshatterproof\nshatters\nshaugh\nshaughs\nshaul\nshauled\nshauling\nshauls\nshavable\nshave\nshaved\nshaveling\nshavelings\nshaven\nshaver\nshavers\nshaves\nshavetail\nshavetails\nshavie\nshavies\nshaving\nshavings\nshaw\nshawed\nshawing\nshawl\nshawled\nshawling\nshawls\nshawm\nshawms\nshawn\nshaws\nshay\nshays\nshazam\nshe\nshea\nsheaf\nsheafed\nsheafing\nsheaflike\nsheafs\nsheal\nshealing\nshealings\nsheals\nshear\nsheared\nshearer\nshearers\nshearing\nshearings\nshearling\nshearlings\nshears\nshearwater\nshearwaters\nsheas\nsheath\nsheathbill\nsheathbills\nsheathe\nsheathed\nsheather\nsheathers\nsheathes\nsheathing\nsheathings\nsheaths\nsheave\nsheaved\nsheaves\nsheaving\nshebang\nshebangs\nshebean\nshebeans\nshebeen\nshebeens\nshed\nshedable\nshedded\nshedder\nshedders\nshedding\nshedlike\nsheds\nsheen\nsheened\nsheeney\nsheeneys\nsheenful\nsheenie\nsheenier\nsheenies\nsheeniest\nsheening\nsheens\nsheeny\nsheep\nsheepberries\nsheepberry\nsheepcot\nsheepcote\nsheepcotes\nsheepcots\nsheepdog\nsheepdogs\nsheepfold\nsheepfolds\nsheepherder\nsheepherders\nsheepherding\nsheepherdings\nsheepish\nsheepishly\nsheepishness\nsheepishnesses\nsheeplike\nsheepman\nsheepmen\nsheepshank\nsheepshanks\nsheepshead\nsheepsheads\nsheepshearer\nsheepshearers\nsheepshearing\nsheepshearings\nsheepskin\nsheepskins\nsheer\nsheered\nsheerer\nsheerest\nsheering\nsheerlegs\nsheerly\nsheerness\nsheernesses\nsheers\nsheesh\nsheet\nsheeted\nsheeter\nsheeters\nsheetfed\nsheeting\nsheetings\nsheetlike\nsheets\nsheeve\nsheeves\nshegetz\nsheik\nsheikdom\nsheikdoms\nsheikh\nsheikhdom\nsheikhdoms\nsheikhs\nsheiks\nsheila\nsheilas\nsheitan\nsheitans\nshekel\nshekels\nsheldrake\nsheldrakes\nshelduck\nshelducks\nshelf\nshelfful\nshelffuls\nshelflike\nshell\nshellac\nshellack\nshellacked\nshellacking\nshellackings\nshellacks\nshellacs\nshellback\nshellbacks\nshellcracker\nshellcrackers\nshelled\nsheller\nshellers\nshellfire\nshellfires\nshellfish\nshellfisheries\nshellfishery\nshellfishes\nshellier\nshelliest\nshelling\nshellproof\nshells\nshellshocked\nshellwork\nshellworks\nshelly\nshelta\nsheltas\nshelter\nshelterbelt\nshelterbelts\nsheltered\nshelterer\nshelterers\nsheltering\nshelterless\nshelters\nsheltie\nshelties\nshelty\nshelve\nshelved\nshelver\nshelvers\nshelves\nshelvier\nshelviest\nshelving\nshelvings\nshelvy\nshenanigan\nshenanigans\nshend\nshending\nshends\nshent\nsheol\nsheols\nshepherd\nshepherded\nshepherdess\nshepherdesses\nshepherding\nshepherds\nsheqalim\nsheqel\nsherbert\nsherberts\nsherbet\nsherbets\nsherd\nsherds\nshereef\nshereefs\nshergottite\nshergottites\nsherif\nsheriff\nsheriffdom\nsheriffdoms\nsheriffs\nsherifs\nsherlock\nsherlocks\nsheroot\nsheroots\nsherpa\nsherpas\nsherries\nsherris\nsherrises\nsherry\nshes\nshetland\nshetlands\nsheuch\nsheuchs\nsheugh\nsheughs\nshew\nshewbread\nshewbreads\nshewed\nshewer\nshewers\nshewing\nshewn\nshews\nshh\nshiatsu\nshiatsus\nshiatzu\nshiatzus\nshibah\nshibahs\nshibboleth\nshibboleths\nshicker\nshickers\nshicksa\nshicksas\nshied\nshiel\nshield\nshielded\nshielder\nshielders\nshielding\nshields\nshieling\nshielings\nshiels\nshier\nshiers\nshies\nshiest\nshift\nshiftable\nshifted\nshifter\nshifters\nshiftier\nshiftiest\nshiftily\nshiftiness\nshiftinesses\nshifting\nshiftless\nshiftlessly\nshiftlessness\nshiftlessnesses\nshifts\nshifty\nshigella\nshigellae\nshigellas\nshigelloses\nshigellosis\nshiitake\nshiitakes\nshikar\nshikaree\nshikarees\nshikari\nshikaris\nshikarred\nshikarring\nshikars\nshikker\nshikkers\nshiksa\nshiksas\nshikse\nshikses\nshilingi\nshill\nshillala\nshillalah\nshillalahs\nshillalas\nshilled\nshillelagh\nshillelaghs\nshilling\nshillings\nshills\nshilpit\nshily\nshim\nshimmed\nshimmer\nshimmered\nshimmering\nshimmers\nshimmery\nshimmied\nshimmies\nshimming\nshimmy\nshimmying\nshims\nshin\nshinbone\nshinbones\nshindies\nshindig\nshindigs\nshindy\nshindys\nshine\nshined\nshiner\nshiners\nshines\nshingle\nshingled\nshingler\nshinglers\nshingles\nshingling\nshingly\nshinier\nshiniest\nshinily\nshininess\nshininesses\nshining\nshinleaf\nshinleafs\nshinleaves\nshinned\nshinneries\nshinnery\nshinney\nshinneyed\nshinneying\nshinneys\nshinnied\nshinnies\nshinning\nshinny\nshinnying\nshinplaster\nshinplasters\nshins\nshinsplints\nshiny\nship\nshipboard\nshipboards\nshipborne\nshipbuilder\nshipbuilders\nshipbuilding\nshipbuildings\nshipfitter\nshipfitters\nshiplap\nshiplaps\nshipload\nshiploads\nshipman\nshipmaster\nshipmasters\nshipmate\nshipmates\nshipmen\nshipment\nshipments\nshipowner\nshipowners\nshippable\nshipped\nshippen\nshippens\nshipper\nshippers\nshipping\nshippings\nshippon\nshippons\nships\nshipshape\nshipside\nshipsides\nshipway\nshipways\nshipworm\nshipworms\nshipwreck\nshipwrecked\nshipwrecking\nshipwrecks\nshipwright\nshipwrights\nshipyard\nshipyards\nshire\nshires\nshirk\nshirked\nshirker\nshirkers\nshirking\nshirks\nshirr\nshirred\nshirring\nshirrings\nshirrs\nshirt\nshirtdress\nshirtdresses\nshirtfront\nshirtfronts\nshirtier\nshirtiest\nshirting\nshirtings\nshirtless\nshirtmaker\nshirtmakers\nshirts\nshirtsleeve\nshirtsleeved\nshirtsleeves\nshirttail\nshirttails\nshirtwaist\nshirtwaists\nshirty\nshist\nshists\nshit\nshitake\nshitakes\nshithead\nshitheads\nshits\nshittah\nshittahs\nshitted\nshittier\nshittiest\nshittim\nshittims\nshittimwood\nshittimwoods\nshitting\nshitty\nshiv\nshiva\nshivah\nshivahs\nshivaree\nshivareed\nshivareeing\nshivarees\nshivas\nshive\nshiver\nshivered\nshiverer\nshiverers\nshivering\nshivers\nshivery\nshives\nshivs\nshkotzim\nshlemiehl\nshlemiehls\nshlemiel\nshlemiels\nshlep\nshlepp\nshlepped\nshlepping\nshlepps\nshleps\nshlock\nshlocks\nshlump\nshlumped\nshlumping\nshlumps\nshlumpy\nshmaltz\nshmaltzes\nshmaltzier\nshmaltziest\nshmaltzy\nshmear\nshmears\nshmo\nshmoes\nshmooze\nshmoozed\nshmoozes\nshmoozing\nshmuck\nshmucks\nshnaps\nshnook\nshnooks\nshoal\nshoaled\nshoaler\nshoalest\nshoalier\nshoaliest\nshoaling\nshoals\nshoaly\nshoat\nshoats\nshock\nshockable\nshocked\nshocker\nshockers\nshocking\nshockingly\nshockproof\nshocks\nshod\nshodden\nshoddier\nshoddies\nshoddiest\nshoddily\nshoddiness\nshoddinesses\nshoddy\nshoe\nshoebill\nshoebills\nshoeblack\nshoeblacks\nshoed\nshoehorn\nshoehorned\nshoehorning\nshoehorns\nshoeing\nshoelace\nshoelaces\nshoeless\nshoemaker\nshoemakers\nshoepac\nshoepack\nshoepacks\nshoepacs\nshoer\nshoers\nshoes\nshoeshine\nshoeshines\nshoestring\nshoestrings\nshoetree\nshoetrees\nshofar\nshofars\nshofroth\nshog\nshogged\nshogging\nshogs\nshogun\nshogunal\nshogunate\nshogunates\nshoguns\nshoji\nshojis\nsholom\nsholoms\nshone\nshoo\nshooed\nshooflies\nshoofly\nshooing\nshook\nshooks\nshool\nshooled\nshooling\nshools\nshoon\nshoos\nshoot\nshooter\nshooters\nshooting\nshootings\nshootout\nshootouts\nshoots\nshop\nshopboy\nshopboys\nshopgirl\nshopgirls\nshophar\nshophars\nshophroth\nshopkeeper\nshopkeepers\nshoplift\nshoplifted\nshoplifter\nshoplifters\nshoplifting\nshoplifts\nshopman\nshopmen\nshoppe\nshopped\nshopper\nshoppers\nshoppes\nshopping\nshoppings\nshops\nshoptalk\nshoptalks\nshopwindow\nshopwindows\nshopworn\nshoran\nshorans\nshore\nshorebird\nshorebirds\nshored\nshorefront\nshorefronts\nshoreline\nshorelines\nshores\nshoreside\nshoreward\nshorewards\nshoring\nshorings\nshorl\nshorls\nshorn\nshort\nshortage\nshortages\nshortbread\nshortbreads\nshortcake\nshortcakes\nshortchange\nshortchanged\nshortchanger\nshortchangers\nshortchanges\nshortchanging\nshortcoming\nshortcomings\nshortcut\nshortcuts\nshortcutting\nshorted\nshorten\nshortened\nshortener\nshorteners\nshortening\nshortenings\nshortens\nshorter\nshortest\nshortfall\nshortfalls\nshorthair\nshorthaired\nshorthairs\nshorthand\nshorthanded\nshorthands\nshorthorn\nshorthorns\nshortia\nshortias\nshortie\nshorties\nshorting\nshortish\nshortlist\nshortlists\nshortly\nshortness\nshortnesses\nshorts\nshortsighted\nshortsightedly\nshortsightedness\nshortsightednesses\nshortstop\nshortstops\nshortwave\nshortwaves\nshorty\nshot\nshote\nshotes\nshotgun\nshotgunned\nshotgunner\nshotgunners\nshotgunning\nshotguns\nshots\nshott\nshotted\nshotten\nshotting\nshotts\nshould\nshoulder\nshouldered\nshouldering\nshoulders\nshouldest\nshouldst\nshout\nshouted\nshouter\nshouters\nshouting\nshouts\nshove\nshoved\nshovel\nshoveled\nshoveler\nshovelers\nshovelful\nshovelfuls\nshoveling\nshovelled\nshoveller\nshovellers\nshovelling\nshovelnose\nshovelnoses\nshovels\nshovelsful\nshover\nshovers\nshoves\nshoving\nshow\nshowable\nshowbiz\nshowbizzes\nshowbizzy\nshowboat\nshowboated\nshowboating\nshowboats\nshowbread\nshowbreads\nshowcase\nshowcased\nshowcases\nshowcasing\nshowdown\nshowdowns\nshowed\nshower\nshowered\nshowerer\nshowerers\nshowerhead\nshowerheads\nshowering\nshowerless\nshowers\nshowery\nshowgirl\nshowgirls\nshowier\nshowiest\nshowily\nshowiness\nshowinesses\nshowing\nshowings\nshowman\nshowmanship\nshowmanships\nshowmen\nshown\nshowoff\nshowoffs\nshowpiece\nshowpieces\nshowplace\nshowplaces\nshowring\nshowrings\nshowroom\nshowrooms\nshows\nshowstopper\nshowstoppers\nshowstopping\nshowtime\nshowtimes\nshowy\nshoyu\nshoyus\nshrank\nshrapnel\nshred\nshredded\nshredder\nshredders\nshredding\nshreds\nshrew\nshrewd\nshrewder\nshrewdest\nshrewdie\nshrewdies\nshrewdly\nshrewdness\nshrewdnesses\nshrewed\nshrewing\nshrewish\nshrewishly\nshrewishness\nshrewishnesses\nshrewlike\nshrews\nshri\nshriek\nshrieked\nshrieker\nshriekers\nshriekier\nshriekiest\nshrieking\nshrieks\nshrieky\nshrieval\nshrievalties\nshrievalty\nshrieve\nshrieved\nshrieves\nshrieving\nshrift\nshrifts\nshrike\nshrikes\nshrill\nshrilled\nshriller\nshrillest\nshrilling\nshrillness\nshrillnesses\nshrills\nshrilly\nshrimp\nshrimped\nshrimper\nshrimpers\nshrimpier\nshrimpiest\nshrimping\nshrimplike\nshrimps\nshrimpy\nshrine\nshrined\nshrines\nshrining\nshrink\nshrinkable\nshrinkage\nshrinkages\nshrinker\nshrinkers\nshrinking\nshrinks\nshris\nshrive\nshrived\nshrivel\nshriveled\nshriveling\nshrivelled\nshrivelling\nshrivels\nshriven\nshriver\nshrivers\nshrives\nshriving\nshroff\nshroffed\nshroffing\nshroffs\nshroud\nshrouded\nshrouding\nshrouds\nshrove\nshrub\nshrubberies\nshrubbery\nshrubbier\nshrubbiest\nshrubby\nshrubs\nshrug\nshrugged\nshrugging\nshrugs\nshrunk\nshrunken\nshtetel\nshtetels\nshtetl\nshtetlach\nshtetls\nshtick\nshticks\nshtik\nshtiks\nshuck\nshucked\nshucker\nshuckers\nshucking\nshuckings\nshucks\nshudder\nshuddered\nshuddering\nshudders\nshuddery\nshuffle\nshuffleboard\nshuffleboards\nshuffled\nshuffler\nshufflers\nshuffles\nshuffling\nshul\nshuln\nshuls\nshun\nshunned\nshunner\nshunners\nshunning\nshunpike\nshunpiked\nshunpiker\nshunpikers\nshunpikes\nshunpiking\nshunpikings\nshuns\nshunt\nshunted\nshunter\nshunters\nshunting\nshunts\nshush\nshushed\nshushes\nshushing\nshut\nshutdown\nshutdowns\nshute\nshuted\nshutes\nshuteye\nshuteyes\nshuting\nshutoff\nshutoffs\nshutout\nshutouts\nshuts\nshutter\nshutterbug\nshutterbugs\nshuttered\nshuttering\nshutterless\nshutters\nshutting\nshuttle\nshuttlecock\nshuttlecocked\nshuttlecocking\nshuttlecocks\nshuttled\nshuttleless\nshuttles\nshuttling\nshwanpan\nshwanpans\nshy\nshyer\nshyers\nshyest\nshying\nshylock\nshylocked\nshylocking\nshylocks\nshyly\nshyness\nshynesses\nshyster\nshysters\nsi\nsial\nsialagogue\nsialagogues\nsialic\nsialid\nsialidan\nsialidans\nsialids\nsialoid\nsials\nsiamang\nsiamangs\nsiamese\nsiameses\nsib\nsibb\nsibbs\nsibilance\nsibilances\nsibilant\nsibilantly\nsibilants\nsibilate\nsibilated\nsibilates\nsibilating\nsibilation\nsibilations\nsibling\nsiblings\nsibs\nsibyl\nsibylic\nsibyllic\nsibylline\nsibyls\nsic\nsiccan\nsicced\nsiccing\nsice\nsices\nsick\nsickbay\nsickbays\nsickbed\nsickbeds\nsicked\nsickee\nsickees\nsicken\nsickened\nsickener\nsickeners\nsickening\nsickeningly\nsickens\nsicker\nsickerly\nsickest\nsickie\nsickies\nsicking\nsickish\nsickishly\nsickishness\nsickishnesses\nsickle\nsickled\nsicklemia\nsicklemias\nsickles\nsicklied\nsicklier\nsicklies\nsickliest\nsicklily\nsickliness\nsicklinesses\nsickling\nsickly\nsicklying\nsickness\nsicknesses\nsicko\nsickos\nsickout\nsickouts\nsickroom\nsickrooms\nsicks\nsics\nsiddur\nsiddurim\nsiddurs\nside\nsidearm\nsideband\nsidebands\nsidebar\nsidebars\nsideboard\nsideboards\nsideburned\nsideburns\nsidecar\nsidecars\nsided\nsidedness\nsidednesses\nsidedress\nsidedresses\nsidehill\nsidehills\nsidekick\nsidekicks\nsidelight\nsidelights\nsideline\nsidelined\nsideliner\nsideliners\nsidelines\nsideling\nsidelining\nsidelong\nsideman\nsidemen\nsidepiece\nsidepieces\nsidereal\nsiderite\nsiderites\nsiderolite\nsiderolites\nsides\nsidesaddle\nsidesaddles\nsideshow\nsideshows\nsideslip\nsideslipped\nsideslipping\nsideslips\nsidespin\nsidespins\nsidesplitting\nsidesplittingly\nsidestep\nsidestepped\nsidestepper\nsidesteppers\nsidestepping\nsidesteps\nsidestream\nsidestroke\nsidestrokes\nsideswipe\nsideswiped\nsideswipes\nsideswiping\nsidetrack\nsidetracked\nsidetracking\nsidetracks\nsidewalk\nsidewalks\nsidewall\nsidewalls\nsideward\nsidewards\nsideway\nsideways\nsidewinder\nsidewinders\nsidewise\nsiding\nsidings\nsidle\nsidled\nsidler\nsidlers\nsidles\nsidling\nsiege\nsieged\nsieges\nsieging\nsiemens\nsienite\nsienites\nsienna\nsiennas\nsierozem\nsierozems\nsierra\nsierran\nsierras\nsiesta\nsiestas\nsieur\nsieurs\nsieve\nsieved\nsieves\nsieving\nsifaka\nsifakas\nsiffleur\nsiffleurs\nsift\nsifted\nsifter\nsifters\nsifting\nsiftings\nsifts\nsiganid\nsiganids\nsigh\nsighed\nsigher\nsighers\nsighing\nsighless\nsighlike\nsighs\nsight\nsighted\nsighter\nsighters\nsighting\nsightings\nsightless\nsightlessly\nsightlessness\nsightlessnesses\nsightlier\nsightliest\nsightliness\nsightlinesses\nsightly\nsights\nsightsaw\nsightsee\nsightseeing\nsightseen\nsightseer\nsightseers\nsightsees\nsigil\nsigils\nsigloi\nsiglos\nsigma\nsigmas\nsigmate\nsigmoid\nsigmoidal\nsigmoidally\nsigmoidoscopies\nsigmoidoscopy\nsigmoids\nsign\nsignage\nsignages\nsignal\nsignaled\nsignaler\nsignalers\nsignaling\nsignalise\nsignalised\nsignalises\nsignalising\nsignalization\nsignalizations\nsignalize\nsignalized\nsignalizes\nsignalizing\nsignalled\nsignaller\nsignallers\nsignalling\nsignally\nsignalman\nsignalmen\nsignalment\nsignalments\nsignals\nsignatories\nsignatory\nsignature\nsignatures\nsignboard\nsignboards\nsigned\nsignee\nsignees\nsigner\nsigners\nsignet\nsigneted\nsigneting\nsignets\nsignificance\nsignificances\nsignificancies\nsignificancy\nsignificant\nsignificantly\nsignification\nsignifications\nsignificative\nsignifics\nsignified\nsignifieds\nsignifier\nsignifiers\nsignifies\nsignify\nsignifying\nsignifyings\nsigning\nsignior\nsigniori\nsigniories\nsigniors\nsigniory\nsignor\nsignora\nsignoras\nsignore\nsignori\nsignories\nsignorina\nsignorinas\nsignorine\nsignors\nsignory\nsignpost\nsignposted\nsignposting\nsignposts\nsigns\nsike\nsiker\nsikes\nsilage\nsilages\nsilane\nsilanes\nsild\nsilds\nsilence\nsilenced\nsilencer\nsilencers\nsilences\nsilencing\nsileni\nsilent\nsilenter\nsilentest\nsilently\nsilentness\nsilentnesses\nsilents\nsilenus\nsilesia\nsilesias\nsilex\nsilexes\nsilhouette\nsilhouetted\nsilhouettes\nsilhouetting\nsilhouettist\nsilhouettists\nsilica\nsilicas\nsilicate\nsilicates\nsiliceous\nsilicic\nsilicide\nsilicides\nsilicification\nsilicifications\nsilicified\nsilicifies\nsilicify\nsilicifying\nsilicious\nsilicium\nsiliciums\nsilicle\nsilicles\nsilicon\nsilicone\nsilicones\nsiliconized\nsilicons\nsilicoses\nsilicosis\nsilicotic\nsilicotics\nsilicula\nsiliculae\nsiliculas\nsiliqua\nsiliquae\nsiliquas\nsilique\nsiliques\nsilk\nsilkaline\nsilkalines\nsilked\nsilken\nsilkier\nsilkies\nsilkiest\nsilkily\nsilkiness\nsilkinesses\nsilking\nsilklike\nsilkoline\nsilkolines\nsilks\nsilkscreen\nsilkscreens\nsilkweed\nsilkweeds\nsilkworm\nsilkworms\nsilky\nsill\nsillabub\nsillabubs\nsiller\nsillers\nsillibub\nsillibubs\nsillier\nsillies\nsilliest\nsillily\nsillimanite\nsillimanites\nsilliness\nsillinesses\nsills\nsilly\nsilo\nsiloed\nsiloing\nsilos\nsiloxane\nsiloxanes\nsilt\nsiltation\nsiltations\nsilted\nsiltier\nsiltiest\nsilting\nsilts\nsiltstone\nsiltstones\nsilty\nsilurid\nsilurids\nsiluroid\nsiluroids\nsilva\nsilvae\nsilvan\nsilvans\nsilvas\nsilver\nsilverback\nsilverbacks\nsilverberries\nsilverberry\nsilvered\nsilverer\nsilverers\nsilverfish\nsilverfishes\nsilveriness\nsilverinesses\nsilvering\nsilverly\nsilvern\nsilverpoint\nsilverpoints\nsilvers\nsilverside\nsilversides\nsilversmith\nsilversmithing\nsilversmithings\nsilversmiths\nsilverware\nsilverwares\nsilverweed\nsilverweeds\nsilvery\nsilvex\nsilvexes\nsilvical\nsilvics\nsilvicultural\nsilviculturally\nsilviculture\nsilvicultures\nsilviculturist\nsilviculturists\nsim\nsima\nsimar\nsimars\nsimaruba\nsimarubas\nsimas\nsimazine\nsimazines\nsimian\nsimians\nsimilar\nsimilarities\nsimilarity\nsimilarly\nsimile\nsimiles\nsimilitude\nsimilitudes\nsimioid\nsimious\nsimitar\nsimitars\nsimlin\nsimlins\nsimmer\nsimmered\nsimmering\nsimmers\nsimnel\nsimnels\nsimoleon\nsimoleons\nsimoniac\nsimoniacal\nsimoniacally\nsimoniacs\nsimonies\nsimonist\nsimonists\nsimonize\nsimonized\nsimonizes\nsimonizing\nsimony\nsimoom\nsimooms\nsimoon\nsimoons\nsimp\nsimpatico\nsimper\nsimpered\nsimperer\nsimperers\nsimpering\nsimpers\nsimple\nsimpleminded\nsimplemindedly\nsimplemindedness\nsimplemindednesses\nsimpleness\nsimplenesses\nsimpler\nsimples\nsimplest\nsimpleton\nsimpletons\nsimplex\nsimplexes\nsimplices\nsimplicia\nsimplicial\nsimplicially\nsimplicities\nsimplicity\nsimplification\nsimplifications\nsimplified\nsimplifier\nsimplifiers\nsimplifies\nsimplify\nsimplifying\nsimplism\nsimplisms\nsimplist\nsimplistic\nsimplistically\nsimplists\nsimply\nsimps\nsims\nsimulacra\nsimulacre\nsimulacres\nsimulacrum\nsimulacrums\nsimulant\nsimulants\nsimular\nsimulars\nsimulate\nsimulated\nsimulates\nsimulating\nsimulation\nsimulations\nsimulative\nsimulator\nsimulators\nsimulcast\nsimulcasted\nsimulcasting\nsimulcasts\nsimultaneities\nsimultaneity\nsimultaneous\nsimultaneously\nsimultaneousness\nsimultaneousnesses\nsin\nsinapism\nsinapisms\nsince\nsincere\nsincerely\nsincereness\nsincerenesses\nsincerer\nsincerest\nsincerities\nsincerity\nsincipita\nsincipital\nsinciput\nsinciputs\nsine\nsinecure\nsinecures\nsines\nsinew\nsinewed\nsinewing\nsinews\nsinewy\nsinfonia\nsinfonias\nsinfonie\nsinfonietta\nsinfoniettas\nsinful\nsinfully\nsinfulness\nsinfulnesses\nsing\nsingable\nsinge\nsinged\nsingeing\nsinger\nsingers\nsinges\nsinging\nsingle\nsingled\nsingleness\nsinglenesses\nsingles\nsinglestick\nsinglesticks\nsinglet\nsingleton\nsingletons\nsingletree\nsingletrees\nsinglets\nsingling\nsingly\nsings\nsingsong\nsingsongs\nsingsongy\nsingspiel\nsingspiels\nsingular\nsingularities\nsingularity\nsingularize\nsingularized\nsingularizes\nsingularizing\nsingularly\nsingulars\nsinh\nsinhs\nsinicize\nsinicized\nsinicizes\nsinicizing\nsinister\nsinisterly\nsinisterness\nsinisternesses\nsinistral\nsinistrous\nsink\nsinkable\nsinkage\nsinkages\nsinker\nsinkers\nsinkhole\nsinkholes\nsinking\nsinks\nsinless\nsinlessly\nsinlessness\nsinlessnesses\nsinned\nsinner\nsinners\nsinning\nsinoatrial\nsinological\nsinologies\nsinologist\nsinologists\nsinologue\nsinologues\nsinology\nsinopia\nsinopias\nsinopie\nsins\nsinsemilla\nsinsemillas\nsinsyne\nsinter\nsinterabilities\nsinterability\nsintered\nsintering\nsinters\nsinuate\nsinuated\nsinuates\nsinuating\nsinuosities\nsinuosity\nsinuous\nsinuously\nsinuousness\nsinuousnesses\nsinus\nsinuses\nsinusitis\nsinusitises\nsinusoid\nsinusoidal\nsinusoidally\nsinusoids\nsip\nsipe\nsiped\nsipes\nsiphon\nsiphonal\nsiphoned\nsiphonic\nsiphoning\nsiphonophore\nsiphonophores\nsiphonostele\nsiphonosteles\nsiphons\nsiping\nsipped\nsipper\nsippers\nsippet\nsippets\nsipping\nsips\nsir\nsirdar\nsirdars\nsire\nsired\nsiree\nsirees\nsiren\nsirenian\nsirenians\nsirens\nsires\nsiring\nsirloin\nsirloins\nsirocco\nsiroccos\nsirra\nsirrah\nsirrahs\nsirras\nsirree\nsirrees\nsirs\nsirup\nsirups\nsirupy\nsirvente\nsirventes\nsis\nsisal\nsisals\nsises\nsiskin\nsiskins\nsissier\nsissies\nsissiest\nsissified\nsissy\nsissyish\nsister\nsistered\nsisterhood\nsisterhoods\nsistering\nsisterly\nsisters\nsistra\nsistroid\nsistrum\nsistrums\nsit\nsitar\nsitarist\nsitarists\nsitars\nsitcom\nsitcoms\nsite\nsited\nsites\nsith\nsithence\nsithens\nsiting\nsitologies\nsitology\nsitosterol\nsitosterols\nsits\nsitten\nsitter\nsitters\nsitting\nsittings\nsituate\nsituated\nsituates\nsituating\nsituation\nsituational\nsituationally\nsituations\nsitup\nsitups\nsitus\nsituses\nsitzmark\nsitzmarks\nsiver\nsivers\nsix\nsixes\nsixfold\nsixmo\nsixmos\nsixpence\nsixpences\nsixpenny\nsixte\nsixteen\nsixteenmo\nsixteenmos\nsixteens\nsixteenth\nsixteenths\nsixtes\nsixth\nsixthly\nsixths\nsixties\nsixtieth\nsixtieths\nsixty\nsixtyish\nsizable\nsizableness\nsizablenesses\nsizably\nsizar\nsizars\nsize\nsizeable\nsizeably\nsized\nsizer\nsizers\nsizes\nsizier\nsiziest\nsiziness\nsizinesses\nsizing\nsizings\nsizy\nsizzle\nsizzled\nsizzler\nsizzlers\nsizzles\nsizzling\nsjambok\nsjamboked\nsjamboking\nsjamboks\nska\nskag\nskags\nskald\nskaldic\nskalds\nskas\nskat\nskate\nskateboard\nskateboarder\nskateboarders\nskateboarding\nskateboardings\nskateboards\nskated\nskater\nskaters\nskates\nskating\nskatings\nskatol\nskatole\nskatoles\nskatols\nskats\nskean\nskeane\nskeanes\nskeans\nskedaddle\nskedaddled\nskedaddler\nskedaddlers\nskedaddles\nskedaddling\nskee\nskeed\nskeeing\nskeen\nskeens\nskees\nskeet\nskeeter\nskeeters\nskeets\nskeg\nskegs\nskeigh\nskein\nskeined\nskeining\nskeins\nskeletal\nskeletally\nskeleton\nskeletonic\nskeletonise\nskeletonised\nskeletonises\nskeletonising\nskeletonize\nskeletonized\nskeletonizer\nskeletonizers\nskeletonizes\nskeletonizing\nskeletons\nskellum\nskellums\nskelm\nskelms\nskelp\nskelped\nskelping\nskelpit\nskelps\nskelter\nskeltered\nskeltering\nskelters\nskene\nskenes\nskep\nskeps\nskepsis\nskepsises\nskeptic\nskeptical\nskeptically\nskepticism\nskepticisms\nskeptics\nskerries\nskerry\nsketch\nsketchbook\nsketchbooks\nsketched\nsketcher\nsketchers\nsketches\nsketchier\nsketchiest\nsketchily\nsketchiness\nsketchinesses\nsketching\nsketchy\nskew\nskewback\nskewbacks\nskewbald\nskewbalds\nskewed\nskewer\nskewered\nskewering\nskewers\nskewing\nskewness\nskewnesses\nskews\nski\nskiable\nskiagram\nskiagrams\nskibob\nskibobber\nskibobbers\nskibobbing\nskibobbings\nskibobs\nskid\nskidded\nskidder\nskidders\nskiddier\nskiddiest\nskidding\nskiddoo\nskiddooed\nskiddooing\nskiddoos\nskiddy\nskidoo\nskidooed\nskidooing\nskidoos\nskidproof\nskids\nskidway\nskidways\nskied\nskier\nskiers\nskies\nskiey\nskiff\nskiffle\nskiffled\nskiffles\nskiffling\nskiffs\nskiing\nskiings\nskijorer\nskijorers\nskijoring\nskijorings\nskilful\nskill\nskilled\nskilless\nskillessness\nskillessnesses\nskillet\nskillets\nskillful\nskillfully\nskillfulness\nskillfulnesses\nskilling\nskillings\nskills\nskim\nskimmed\nskimmer\nskimmers\nskimming\nskimmings\nskimo\nskimobile\nskimobiles\nskimos\nskimp\nskimped\nskimpier\nskimpiest\nskimpily\nskimpiness\nskimpinesses\nskimping\nskimps\nskimpy\nskims\nskin\nskinflint\nskinflints\nskinful\nskinfuls\nskinhead\nskinheads\nskink\nskinked\nskinker\nskinkers\nskinking\nskinks\nskinless\nskinlike\nskinned\nskinner\nskinners\nskinnier\nskinniest\nskinniness\nskinninesses\nskinning\nskinny\nskins\nskint\nskintight\nskioring\nskiorings\nskip\nskipjack\nskipjacks\nskiplane\nskiplanes\nskippable\nskipped\nskipper\nskippered\nskippering\nskippers\nskippet\nskippets\nskipping\nskips\nskirl\nskirled\nskirling\nskirls\nskirmish\nskirmished\nskirmisher\nskirmishers\nskirmishes\nskirmishing\nskirr\nskirred\nskirret\nskirrets\nskirring\nskirrs\nskirt\nskirted\nskirter\nskirters\nskirting\nskirtings\nskirts\nskis\nskit\nskite\nskited\nskites\nskiting\nskits\nskitter\nskittered\nskitterier\nskitteriest\nskittering\nskitters\nskittery\nskittish\nskittishly\nskittishness\nskittishnesses\nskittle\nskittles\nskive\nskived\nskiver\nskivers\nskives\nskiving\nskivvied\nskivvies\nskivvy\nskivvying\nskiwear\nsklent\nsklented\nsklenting\nsklents\nskoal\nskoaled\nskoaling\nskoals\nskookum\nskosh\nskoshes\nskreegh\nskreeghed\nskreeghing\nskreeghs\nskreigh\nskreighed\nskreighing\nskreighs\nskua\nskuas\nskulduggeries\nskulduggery\nskulk\nskulked\nskulker\nskulkers\nskulking\nskulks\nskull\nskullcap\nskullcaps\nskullduggeries\nskullduggery\nskulled\nskulls\nskunk\nskunked\nskunking\nskunks\nsky\nskyborne\nskybox\nskyboxes\nskycap\nskycaps\nskydive\nskydived\nskydiver\nskydivers\nskydives\nskydiving\nskydivings\nskydove\nskyed\nskyey\nskyhook\nskyhooks\nskying\nskyjack\nskyjacked\nskyjacker\nskyjackers\nskyjacking\nskyjackings\nskyjacks\nskylark\nskylarked\nskylarker\nskylarkers\nskylarking\nskylarks\nskylight\nskylighted\nskylights\nskyline\nskylines\nskylit\nskyman\nskymen\nskyphoi\nskyphos\nskyrocket\nskyrocketed\nskyrocketing\nskyrockets\nskysail\nskysails\nskyscraper\nskyscrapers\nskywalk\nskywalks\nskyward\nskywards\nskyway\nskyways\nskywrite\nskywriter\nskywriters\nskywrites\nskywriting\nskywritings\nskywritten\nskywrote\nslab\nslabbed\nslabber\nslabbered\nslabbering\nslabbers\nslabbery\nslabbing\nslablike\nslabs\nslack\nslacked\nslacken\nslackened\nslackening\nslackens\nslacker\nslackers\nslackest\nslacking\nslackly\nslackness\nslacknesses\nslacks\nslag\nslagged\nslaggier\nslaggiest\nslagging\nslaggy\nslags\nslain\nslainte\nslakable\nslake\nslaked\nslaker\nslakers\nslakes\nslaking\nslalom\nslalomed\nslaloming\nslaloms\nslam\nslammed\nslammer\nslammers\nslamming\nslams\nslander\nslandered\nslanderer\nslanderers\nslandering\nslanderous\nslanderously\nslanderousness\nslanderousnesses\nslanders\nslang\nslanged\nslangier\nslangiest\nslangily\nslanginess\nslanginesses\nslanging\nslangs\nslanguage\nslanguages\nslangy\nslank\nslant\nslanted\nslanting\nslantingly\nslants\nslantways\nslantwise\nslanty\nslap\nslapdash\nslapdashes\nslaphappier\nslaphappiest\nslaphappy\nslapjack\nslapjacks\nslapped\nslapper\nslappers\nslapping\nslaps\nslapstick\nslapsticks\nslash\nslashed\nslasher\nslashers\nslashes\nslashing\nslashingly\nslashings\nslat\nslatch\nslatches\nslate\nslated\nslatelike\nslater\nslaters\nslates\nslatey\nslather\nslathered\nslathering\nslathers\nslatier\nslatiest\nslating\nslatings\nslats\nslatted\nslattern\nslatternliness\nslatternlinesses\nslatternly\nslatterns\nslatting\nslattings\nslaty\nslaughter\nslaughtered\nslaughterer\nslaughterers\nslaughterhouse\nslaughterhouses\nslaughtering\nslaughterous\nslaughterously\nslaughters\nslave\nslaved\nslaveholder\nslaveholders\nslaveholding\nslaveholdings\nslaver\nslavered\nslaverer\nslaverers\nslaveries\nslavering\nslavers\nslavery\nslaves\nslavey\nslaveys\nslaving\nslavish\nslavishly\nslavishness\nslavishnesses\nslavocracies\nslavocracy\nslaw\nslaws\nslay\nslayed\nslayer\nslayers\nslaying\nslayings\nslays\nsleave\nsleaved\nsleaves\nsleaving\nsleaze\nsleazebag\nsleazebags\nsleazeball\nsleazeballs\nsleazes\nsleazier\nsleaziest\nsleazily\nsleaziness\nsleazinesses\nsleazo\nsleazy\nsled\nsledded\nsledder\nsledders\nsledding\nsleddings\nsledge\nsledged\nsledgehammer\nsledgehammered\nsledgehammering\nsledgehammers\nsledges\nsledging\nsleds\nsleek\nsleeked\nsleeken\nsleekened\nsleekening\nsleekens\nsleeker\nsleekest\nsleekier\nsleekiest\nsleeking\nsleekit\nsleekly\nsleekness\nsleeknesses\nsleeks\nsleeky\nsleep\nsleeper\nsleepers\nsleepier\nsleepiest\nsleepily\nsleepiness\nsleepinesses\nsleeping\nsleepings\nsleepless\nsleeplessly\nsleeplessness\nsleeplessnesses\nsleeplike\nsleepover\nsleepovers\nsleeps\nsleepwalk\nsleepwalked\nsleepwalker\nsleepwalkers\nsleepwalking\nsleepwalks\nsleepwear\nsleepy\nsleepyhead\nsleepyheads\nsleet\nsleeted\nsleetier\nsleetiest\nsleeting\nsleets\nsleety\nsleeve\nsleeved\nsleeveless\nsleevelet\nsleevelets\nsleeves\nsleeving\nsleigh\nsleighed\nsleigher\nsleighers\nsleighing\nsleighs\nsleight\nsleights\nslender\nslenderer\nslenderest\nslenderize\nslenderized\nslenderizes\nslenderizing\nslenderly\nslenderness\nslendernesses\nslept\nsleuth\nsleuthed\nsleuthhound\nsleuthhounds\nsleuthing\nsleuths\nslew\nslewed\nslewing\nslews\nslice\nsliceable\nsliced\nslicer\nslicers\nslices\nslicing\nslick\nslicked\nslickenside\nslickensides\nslicker\nslickers\nslickest\nslicking\nslickly\nslickness\nslicknesses\nslickrock\nslickrocks\nslicks\nslid\nslidable\nslidden\nslide\nslider\nsliders\nslides\nslideway\nslideways\nsliding\nslier\nsliest\nslight\nslighted\nslighter\nslightest\nslighting\nslightingly\nslightly\nslightness\nslightnesses\nslights\nslily\nslim\nslime\nslimeball\nslimeballs\nslimed\nslimes\nslimier\nslimiest\nslimily\nsliminess\nsliminesses\nsliming\nslimly\nslimmed\nslimmer\nslimmers\nslimmest\nslimming\nslimnastics\nslimness\nslimnesses\nslimpsier\nslimpsiest\nslimpsy\nslims\nslimsier\nslimsiest\nslimsy\nslimy\nsling\nslinger\nslingers\nslinging\nslings\nslingshot\nslingshots\nslink\nslinked\nslinkier\nslinkiest\nslinkily\nslinkiness\nslinkinesses\nslinking\nslinks\nslinky\nslip\nslipcase\nslipcased\nslipcases\nslipcover\nslipcovers\nslipe\nsliped\nslipes\nslipform\nslipformed\nslipforming\nslipforms\nsliping\nslipknot\nslipknots\nslipless\nslipout\nslipouts\nslipover\nslipovers\nslippage\nslippages\nslipped\nslipper\nslippered\nslipperier\nslipperiest\nslipperiness\nslipperinesses\nslippers\nslippery\nslippier\nslippiest\nslipping\nslippy\nslips\nslipshod\nslipslop\nslipslops\nslipsole\nslipsoles\nslipstream\nslipstreamed\nslipstreaming\nslipstreams\nslipt\nslipup\nslipups\nslipware\nslipwares\nslipway\nslipways\nslit\nslither\nslithered\nslithering\nslithers\nslithery\nslitless\nslits\nslitted\nslitter\nslitters\nslitting\nsliver\nslivered\nsliverer\nsliverers\nslivering\nslivers\nslivovic\nslivovices\nslivovitz\nslivovitzes\nslob\nslobber\nslobbered\nslobberer\nslobberers\nslobbering\nslobbers\nslobbery\nslobbier\nslobbiest\nslobbish\nslobby\nslobs\nsloe\nsloes\nslog\nslogan\nsloganeer\nsloganeered\nsloganeering\nsloganeers\nsloganize\nsloganized\nsloganizes\nsloganizing\nslogans\nslogged\nslogger\nsloggers\nslogging\nslogs\nsloid\nsloids\nslojd\nslojds\nsloop\nsloops\nslop\nslope\nsloped\nsloper\nslopers\nslopes\nsloping\nslopped\nsloppier\nsloppiest\nsloppily\nsloppiness\nsloppinesses\nslopping\nsloppy\nslops\nslopwork\nslopworks\nslosh\nsloshed\nsloshes\nsloshier\nsloshiest\nsloshing\nsloshy\nslot\nslotback\nslotbacks\nsloth\nslothful\nslothfully\nslothfulness\nslothfulnesses\nsloths\nslots\nslotted\nslotting\nslouch\nslouched\nsloucher\nslouchers\nslouches\nslouchier\nslouchiest\nslouchily\nslouchiness\nslouchinesses\nslouching\nslouchy\nslough\nsloughed\nsloughier\nsloughiest\nsloughing\nsloughs\nsloughy\nsloven\nslovenlier\nslovenliest\nslovenliness\nslovenlinesses\nslovenly\nslovens\nslow\nslowdown\nslowdowns\nslowed\nslower\nslowest\nslowing\nslowish\nslowly\nslowness\nslownesses\nslowpoke\nslowpokes\nslows\nslowworm\nslowworms\nsloyd\nsloyds\nslub\nslubbed\nslubber\nslubbered\nslubbering\nslubbers\nslubbing\nslubbings\nslubs\nsludge\nsludges\nsludgier\nsludgiest\nsludgy\nslue\nslued\nslues\nsluff\nsluffed\nsluffing\nsluffs\nslug\nslugabed\nslugabeds\nslugfest\nslugfests\nsluggard\nsluggardly\nsluggardness\nsluggardnesses\nsluggards\nslugged\nslugger\nsluggers\nslugging\nsluggish\nsluggishly\nsluggishness\nsluggishnesses\nslugs\nsluice\nsluiced\nsluices\nsluiceway\nsluiceways\nsluicing\nsluicy\nsluing\nslum\nslumber\nslumbered\nslumberer\nslumberers\nslumbering\nslumberous\nslumbers\nslumbery\nslumbrous\nslumgullion\nslumgullions\nslumgum\nslumgums\nslumism\nslumisms\nslumlord\nslumlords\nslummed\nslummer\nslummers\nslummier\nslummiest\nslumming\nslummy\nslump\nslumped\nslumpflation\nslumpflations\nslumping\nslumps\nslums\nslung\nslungshot\nslungshots\nslunk\nslur\nslurb\nslurban\nslurbs\nslurp\nslurped\nslurping\nslurps\nslurred\nslurried\nslurries\nslurring\nslurry\nslurrying\nslurs\nslush\nslushed\nslushes\nslushier\nslushiest\nslushily\nslushiness\nslushinesses\nslushing\nslushy\nslut\nsluts\nsluttier\nsluttiest\nsluttish\nsluttishly\nsluttishness\nsluttishnesses\nslutty\nsly\nslyboots\nslyer\nslyest\nslyly\nslyness\nslynesses\nslype\nslypes\nsmack\nsmacked\nsmacker\nsmackers\nsmacking\nsmacks\nsmall\nsmallage\nsmallages\nsmallclothes\nsmaller\nsmallest\nsmallholder\nsmallholders\nsmallholding\nsmallholdings\nsmallish\nsmallmouth\nsmallmouths\nsmallness\nsmallnesses\nsmallpox\nsmallpoxes\nsmalls\nsmallsword\nsmallswords\nsmalt\nsmalti\nsmaltine\nsmaltines\nsmaltite\nsmaltites\nsmalto\nsmaltos\nsmalts\nsmaragd\nsmaragde\nsmaragdes\nsmaragdine\nsmaragdite\nsmaragdites\nsmaragds\nsmarm\nsmarmier\nsmarmiest\nsmarmily\nsmarminess\nsmarminesses\nsmarms\nsmarmy\nsmart\nsmartass\nsmartasses\nsmarted\nsmarten\nsmartened\nsmartening\nsmartens\nsmarter\nsmartest\nsmartie\nsmarties\nsmarting\nsmartly\nsmartness\nsmartnesses\nsmarts\nsmartweed\nsmartweeds\nsmarty\nsmash\nsmashed\nsmasher\nsmashers\nsmashes\nsmashing\nsmashingly\nsmashup\nsmashups\nsmatter\nsmattered\nsmatterer\nsmatterers\nsmattering\nsmatterings\nsmatters\nsmaze\nsmazes\nsmear\nsmearcase\nsmearcases\nsmeared\nsmearer\nsmearers\nsmearier\nsmeariest\nsmearing\nsmears\nsmeary\nsmectic\nsmectite\nsmectites\nsmectitic\nsmeddum\nsmeddums\nsmeek\nsmeeked\nsmeeking\nsmeeks\nsmegma\nsmegmas\nsmell\nsmelled\nsmeller\nsmellers\nsmellier\nsmelliest\nsmelling\nsmells\nsmelly\nsmelt\nsmelted\nsmelter\nsmelteries\nsmelters\nsmeltery\nsmelting\nsmelts\nsmerk\nsmerked\nsmerking\nsmerks\nsmew\nsmews\nsmidge\nsmidgen\nsmidgens\nsmidgeon\nsmidgeons\nsmidges\nsmidgin\nsmidgins\nsmiercase\nsmiercases\nsmilax\nsmilaxes\nsmile\nsmiled\nsmileless\nsmiler\nsmilers\nsmiles\nsmiley\nsmileys\nsmiling\nsmilingly\nsmirch\nsmirched\nsmirches\nsmirching\nsmirk\nsmirked\nsmirker\nsmirkers\nsmirkier\nsmirkiest\nsmirking\nsmirks\nsmirky\nsmit\nsmite\nsmiter\nsmiters\nsmites\nsmith\nsmithereens\nsmitheries\nsmithers\nsmithery\nsmithies\nsmiths\nsmithsonite\nsmithsonites\nsmithy\nsmiting\nsmitten\nsmock\nsmocked\nsmocking\nsmockings\nsmocks\nsmog\nsmoggier\nsmoggiest\nsmoggy\nsmogless\nsmogs\nsmokable\nsmoke\nsmokeable\nsmoked\nsmokehouse\nsmokehouses\nsmokejack\nsmokejacks\nsmokeless\nsmokelike\nsmokepot\nsmokepots\nsmoker\nsmokers\nsmokes\nsmokescreen\nsmokescreens\nsmokestack\nsmokestacks\nsmokey\nsmokier\nsmokiest\nsmokily\nsmokiness\nsmokinesses\nsmoking\nsmoky\nsmolder\nsmoldered\nsmoldering\nsmolders\nsmolt\nsmolts\nsmooch\nsmooched\nsmooches\nsmooching\nsmoochy\nsmooth\nsmoothbore\nsmoothbores\nsmoothed\nsmoothen\nsmoothened\nsmoothening\nsmoothens\nsmoother\nsmoothers\nsmoothes\nsmoothest\nsmoothie\nsmoothies\nsmoothing\nsmoothly\nsmoothness\nsmoothnesses\nsmooths\nsmoothy\nsmorgasbord\nsmorgasbords\nsmote\nsmother\nsmothered\nsmothering\nsmothers\nsmothery\nsmoulder\nsmouldered\nsmouldering\nsmoulders\nsmudge\nsmudged\nsmudges\nsmudgier\nsmudgiest\nsmudgily\nsmudginess\nsmudginesses\nsmudging\nsmudgy\nsmug\nsmugger\nsmuggest\nsmuggle\nsmuggled\nsmuggler\nsmugglers\nsmuggles\nsmuggling\nsmugly\nsmugness\nsmugnesses\nsmut\nsmutch\nsmutched\nsmutches\nsmutchier\nsmutchiest\nsmutching\nsmutchy\nsmuts\nsmutted\nsmuttier\nsmuttiest\nsmuttily\nsmuttiness\nsmuttinesses\nsmutting\nsmutty\nsnack\nsnacked\nsnacking\nsnacks\nsnaffle\nsnaffled\nsnaffles\nsnaffling\nsnafu\nsnafued\nsnafuing\nsnafus\nsnag\nsnagged\nsnaggier\nsnaggiest\nsnagging\nsnaggleteeth\nsnaggletooth\nsnaggletoothed\nsnaggy\nsnaglike\nsnags\nsnail\nsnailed\nsnailing\nsnaillike\nsnails\nsnake\nsnakebird\nsnakebirds\nsnakebit\nsnakebite\nsnakebites\nsnakebitten\nsnaked\nsnakelike\nsnakeroot\nsnakeroots\nsnakes\nsnakeskin\nsnakeskins\nsnakeweed\nsnakeweeds\nsnakey\nsnakier\nsnakiest\nsnakily\nsnaking\nsnaky\nsnap\nsnapback\nsnapbacks\nsnapdragon\nsnapdragons\nsnapless\nsnapped\nsnapper\nsnappers\nsnappier\nsnappiest\nsnappily\nsnappiness\nsnappinesses\nsnapping\nsnappish\nsnappishly\nsnappishness\nsnappishnesses\nsnappy\nsnaps\nsnapshooter\nsnapshooters\nsnapshot\nsnapshots\nsnapshotted\nsnapshotting\nsnapweed\nsnapweeds\nsnare\nsnared\nsnarer\nsnarers\nsnares\nsnaring\nsnark\nsnarkier\nsnarkiest\nsnarks\nsnarky\nsnarl\nsnarled\nsnarler\nsnarlers\nsnarlier\nsnarliest\nsnarling\nsnarls\nsnarly\nsnash\nsnashes\nsnatch\nsnatched\nsnatcher\nsnatchers\nsnatches\nsnatchier\nsnatchiest\nsnatching\nsnatchy\nsnath\nsnathe\nsnathes\nsnaths\nsnaw\nsnawed\nsnawing\nsnaws\nsnazzier\nsnazziest\nsnazzy\nsneak\nsneaked\nsneaker\nsneakered\nsneakers\nsneakier\nsneakiest\nsneakily\nsneakiness\nsneakinesses\nsneaking\nsneakingly\nsneaks\nsneaky\nsneap\nsneaped\nsneaping\nsneaps\nsneck\nsnecks\nsned\nsnedded\nsnedding\nsneds\nsneer\nsneered\nsneerer\nsneerers\nsneerful\nsneering\nsneers\nsneesh\nsneeshes\nsneeze\nsneezed\nsneezer\nsneezers\nsneezes\nsneezeweed\nsneezeweeds\nsneezier\nsneeziest\nsneezing\nsneezy\nsnell\nsnelled\nsneller\nsnellest\nsnelling\nsnells\nsnib\nsnibbed\nsnibbing\nsnibs\nsnick\nsnicked\nsnicker\nsnickered\nsnickerer\nsnickerers\nsnickering\nsnickers\nsnickersnee\nsnickersnees\nsnickery\nsnicking\nsnicks\nsnide\nsnidely\nsnideness\nsnidenesses\nsnider\nsnidest\nsniff\nsniffed\nsniffer\nsniffers\nsniffier\nsniffiest\nsniffily\nsniffiness\nsniffinesses\nsniffing\nsniffish\nsniffishly\nsniffishness\nsniffishnesses\nsniffle\nsniffled\nsniffler\nsnifflers\nsniffles\nsniffling\nsniffs\nsniffy\nsnifter\nsnifters\nsnigger\nsniggered\nsniggerer\nsniggerers\nsniggering\nsniggers\nsniggle\nsniggled\nsniggler\nsnigglers\nsniggles\nsniggling\nsnip\nsnipe\nsniped\nsniper\nsnipers\nsniperscope\nsniperscopes\nsnipes\nsniping\nsnipped\nsnipper\nsnippers\nsnippersnapper\nsnippersnappers\nsnippet\nsnippetier\nsnippetiest\nsnippets\nsnippety\nsnippier\nsnippiest\nsnippily\nsnipping\nsnippy\nsnips\nsnit\nsnitch\nsnitched\nsnitcher\nsnitchers\nsnitches\nsnitching\nsnits\nsnivel\nsniveled\nsniveler\nsnivelers\nsniveling\nsnivelled\nsnivelling\nsnivels\nsnob\nsnobberies\nsnobbery\nsnobbier\nsnobbiest\nsnobbily\nsnobbish\nsnobbishly\nsnobbishness\nsnobbishnesses\nsnobbism\nsnobbisms\nsnobby\nsnobs\nsnog\nsnogged\nsnogging\nsnogs\nsnollygoster\nsnollygosters\nsnood\nsnooded\nsnooding\nsnoods\nsnook\nsnooked\nsnooker\nsnookered\nsnookering\nsnookers\nsnooking\nsnooks\nsnool\nsnooled\nsnooling\nsnools\nsnoop\nsnooped\nsnooper\nsnoopers\nsnoopier\nsnoopiest\nsnoopily\nsnooping\nsnoops\nsnoopy\nsnoot\nsnooted\nsnootier\nsnootiest\nsnootily\nsnootiness\nsnootinesses\nsnooting\nsnoots\nsnooty\nsnooze\nsnoozed\nsnoozer\nsnoozers\nsnoozes\nsnoozier\nsnooziest\nsnoozing\nsnoozle\nsnoozled\nsnoozles\nsnoozling\nsnoozy\nsnore\nsnored\nsnorer\nsnorers\nsnores\nsnoring\nsnorkel\nsnorkeled\nsnorkeler\nsnorkelers\nsnorkeling\nsnorkels\nsnort\nsnorted\nsnorter\nsnorters\nsnorting\nsnorts\nsnot\nsnots\nsnottier\nsnottiest\nsnottily\nsnottiness\nsnottinesses\nsnotty\nsnout\nsnouted\nsnoutier\nsnoutiest\nsnouting\nsnoutish\nsnouts\nsnouty\nsnow\nsnowball\nsnowballed\nsnowballing\nsnowballs\nsnowbank\nsnowbanks\nsnowbell\nsnowbells\nsnowbelt\nsnowbelts\nsnowberries\nsnowberry\nsnowbird\nsnowbirds\nsnowblower\nsnowblowers\nsnowboard\nsnowboarder\nsnowboarders\nsnowboarding\nsnowboardings\nsnowboards\nsnowbound\nsnowbrush\nsnowbrushes\nsnowbush\nsnowbushes\nsnowcap\nsnowcapped\nsnowcaps\nsnowdrift\nsnowdrifts\nsnowdrop\nsnowdrops\nsnowed\nsnowfall\nsnowfalls\nsnowfield\nsnowfields\nsnowflake\nsnowflakes\nsnowier\nsnowiest\nsnowily\nsnowiness\nsnowinesses\nsnowing\nsnowland\nsnowlands\nsnowless\nsnowlike\nsnowmaker\nsnowmakers\nsnowmaking\nsnowman\nsnowmelt\nsnowmelts\nsnowmen\nsnowmobile\nsnowmobiler\nsnowmobilers\nsnowmobiles\nsnowmobiling\nsnowmobilings\nsnowmobilist\nsnowmobilists\nsnowmold\nsnowmolds\nsnowpack\nsnowpacks\nsnowplow\nsnowplowed\nsnowplowing\nsnowplows\nsnows\nsnowscape\nsnowscapes\nsnowshed\nsnowsheds\nsnowshoe\nsnowshoed\nsnowshoeing\nsnowshoer\nsnowshoers\nsnowshoes\nsnowslide\nsnowslides\nsnowstorm\nsnowstorms\nsnowsuit\nsnowsuits\nsnowy\nsnub\nsnubbed\nsnubber\nsnubbers\nsnubbier\nsnubbiest\nsnubbiness\nsnubbinesses\nsnubbing\nsnubby\nsnubness\nsnubnesses\nsnubs\nsnuck\nsnuff\nsnuffbox\nsnuffboxes\nsnuffed\nsnuffer\nsnuffers\nsnuffier\nsnuffiest\nsnuffily\nsnuffing\nsnuffle\nsnuffled\nsnuffler\nsnufflers\nsnuffles\nsnufflier\nsnuffliest\nsnuffling\nsnuffly\nsnuffs\nsnuffy\nsnug\nsnugged\nsnugger\nsnuggeries\nsnuggery\nsnuggest\nsnuggies\nsnugging\nsnuggle\nsnuggled\nsnuggles\nsnuggling\nsnugly\nsnugness\nsnugnesses\nsnugs\nsnye\nsnyes\nso\nsoak\nsoakage\nsoakages\nsoaked\nsoaker\nsoakers\nsoaking\nsoaks\nsoap\nsoapbark\nsoapbarks\nsoapberries\nsoapberry\nsoapbox\nsoapboxes\nsoaped\nsoaper\nsoapers\nsoapier\nsoapiest\nsoapily\nsoapiness\nsoapinesses\nsoaping\nsoapless\nsoaplike\nsoaps\nsoapstone\nsoapstones\nsoapsuds\nsoapwort\nsoapworts\nsoapy\nsoar\nsoared\nsoarer\nsoarers\nsoaring\nsoarings\nsoars\nsoave\nsoaves\nsob\nsobbed\nsobber\nsobbers\nsobbing\nsobeit\nsober\nsobered\nsoberer\nsoberest\nsobering\nsoberize\nsoberized\nsoberizes\nsoberizing\nsoberly\nsoberness\nsobernesses\nsobers\nsobersided\nsobersidedness\nsobersidednesses\nsobersides\nsobful\nsobrieties\nsobriety\nsobriquet\nsobriquets\nsobs\nsocage\nsocager\nsocagers\nsocages\nsoccage\nsoccages\nsoccer\nsoccers\nsociabilities\nsociability\nsociable\nsociableness\nsociablenesses\nsociables\nsociably\nsocial\nsocialise\nsocialised\nsocialises\nsocialising\nsocialism\nsocialisms\nsocialist\nsocialistic\nsocialistically\nsocialists\nsocialite\nsocialites\nsocialities\nsociality\nsocialization\nsocializations\nsocialize\nsocialized\nsocializer\nsocializers\nsocializes\nsocializing\nsocially\nsocials\nsocietal\nsocietally\nsocieties\nsociety\nsociobiological\nsociobiologies\nsociobiologist\nsociobiologists\nsociobiology\nsociocultural\nsocioculturally\nsocioeconomic\nsocioeconomically\nsociogram\nsociograms\nsociohistorical\nsociolinguist\nsociolinguistic\nsociolinguistics\nsociolinguists\nsociologese\nsociologeses\nsociologic\nsociological\nsociologically\nsociologies\nsociologist\nsociologists\nsociology\nsociometric\nsociometries\nsociometry\nsociopath\nsociopathic\nsociopathies\nsociopaths\nsociopathy\nsociopolitical\nsociopsychological\nsocioreligious\nsociosexual\nsock\nsockdolager\nsockdolagers\nsockdologer\nsockdologers\nsocked\nsocket\nsocketed\nsocketing\nsockets\nsockeye\nsockeyes\nsocking\nsockless\nsockman\nsockmen\nsocko\nsocks\nsocle\nsocles\nsocman\nsocmen\nsod\nsoda\nsodaless\nsodalist\nsodalists\nsodalite\nsodalites\nsodalities\nsodality\nsodamide\nsodamides\nsodas\nsodbuster\nsodbusters\nsodded\nsodden\nsoddened\nsoddening\nsoddenly\nsoddenness\nsoddennesses\nsoddens\nsoddies\nsodding\nsoddy\nsodic\nsodium\nsodiums\nsodom\nsodomies\nsodomist\nsodomists\nsodomite\nsodomites\nsodomitic\nsodomitical\nsodomize\nsodomized\nsodomizes\nsodomizing\nsodoms\nsodomy\nsods\nsoever\nsofa\nsofar\nsofars\nsofas\nsoffit\nsoffits\nsoft\nsofta\nsoftas\nsoftback\nsoftbacks\nsoftball\nsoftballer\nsoftballers\nsoftballs\nsoftbound\nsoftcover\nsoftcovers\nsoften\nsoftened\nsoftener\nsofteners\nsoftening\nsoftens\nsofter\nsoftest\nsofthead\nsoftheaded\nsoftheadedly\nsoftheadedness\nsoftheadednesses\nsoftheads\nsofthearted\nsoftheartedly\nsoftheartedness\nsoftheartednesses\nsoftie\nsofties\nsoftish\nsoftly\nsoftness\nsoftnesses\nsofts\nsoftshell\nsoftshells\nsoftware\nsoftwares\nsoftwood\nsoftwoods\nsofty\nsogged\nsoggier\nsoggiest\nsoggily\nsogginess\nsogginesses\nsoggy\nsoigne\nsoignee\nsoil\nsoilage\nsoilages\nsoilborne\nsoiled\nsoiling\nsoilless\nsoils\nsoilure\nsoilures\nsoiree\nsoirees\nsoja\nsojas\nsojourn\nsojourned\nsojourner\nsojourners\nsojourning\nsojourns\nsoke\nsokeman\nsokemen\nsokes\nsokol\nsokols\nsol\nsola\nsolace\nsolaced\nsolacement\nsolacements\nsolacer\nsolacers\nsolaces\nsolacing\nsolan\nsolanaceous\nsoland\nsolander\nsolanders\nsolands\nsolanin\nsolanine\nsolanines\nsolanins\nsolano\nsolanos\nsolans\nsolanum\nsolanums\nsolar\nsolaria\nsolarise\nsolarised\nsolarises\nsolarising\nsolarism\nsolarisms\nsolarium\nsolariums\nsolarization\nsolarizations\nsolarize\nsolarized\nsolarizes\nsolarizing\nsolate\nsolated\nsolates\nsolatia\nsolating\nsolation\nsolations\nsolatium\nsold\nsoldan\nsoldans\nsolder\nsolderabilities\nsolderability\nsoldered\nsolderer\nsolderers\nsoldering\nsolders\nsoldi\nsoldier\nsoldiered\nsoldieries\nsoldiering\nsoldierings\nsoldierly\nsoldiers\nsoldiership\nsoldierships\nsoldiery\nsoldo\nsole\nsolecise\nsolecised\nsolecises\nsolecising\nsolecism\nsolecisms\nsolecist\nsolecistic\nsolecists\nsolecize\nsolecized\nsolecizes\nsolecizing\nsoled\nsolei\nsoleless\nsolely\nsolemn\nsolemner\nsolemnest\nsolemnified\nsolemnifies\nsolemnify\nsolemnifying\nsolemnities\nsolemnity\nsolemnization\nsolemnizations\nsolemnize\nsolemnized\nsolemnizes\nsolemnizing\nsolemnly\nsolemnness\nsolemnnesses\nsoleness\nsolenesses\nsolenoid\nsolenoidal\nsolenoids\nsoleplate\nsoleplates\nsoleret\nsolerets\nsoles\nsoleus\nsoleuses\nsolfatara\nsolfataras\nsolfege\nsolfeges\nsolfeggi\nsolfeggio\nsolfeggios\nsolgel\nsoli\nsolicit\nsolicitant\nsolicitants\nsolicitation\nsolicitations\nsolicited\nsoliciting\nsolicitor\nsolicitors\nsolicitorship\nsolicitorships\nsolicitous\nsolicitously\nsolicitousness\nsolicitousnesses\nsolicits\nsolicitude\nsolicitudes\nsolid\nsolidago\nsolidagos\nsolidarism\nsolidarisms\nsolidarist\nsolidaristic\nsolidarists\nsolidarities\nsolidarity\nsolidary\nsolider\nsolidest\nsolidi\nsolidification\nsolidifications\nsolidified\nsolidifies\nsolidify\nsolidifying\nsolidities\nsolidity\nsolidly\nsolidness\nsolidnesses\nsolids\nsolidus\nsolifluction\nsolifluctions\nsoliloquies\nsoliloquise\nsoliloquised\nsoliloquises\nsoliloquising\nsoliloquist\nsoliloquists\nsoliloquize\nsoliloquized\nsoliloquizer\nsoliloquizers\nsoliloquizes\nsoliloquizing\nsoliloquy\nsoling\nsolion\nsolions\nsolipsism\nsolipsisms\nsolipsist\nsolipsistic\nsolipsistically\nsolipsists\nsoliquid\nsoliquids\nsolitaire\nsolitaires\nsolitaries\nsolitarily\nsolitariness\nsolitarinesses\nsolitary\nsoliton\nsolitons\nsolitude\nsolitudes\nsolitudinarian\nsolitudinarians\nsolleret\nsollerets\nsolmization\nsolmizations\nsolo\nsoloed\nsoloing\nsoloist\nsoloists\nsolon\nsolonchak\nsolonchaks\nsolonets\nsolonetses\nsolonetz\nsolonetzes\nsolonetzic\nsolons\nsolos\nsols\nsolstice\nsolstices\nsolstitial\nsolubilise\nsolubilised\nsolubilises\nsolubilising\nsolubilities\nsolubility\nsolubilization\nsolubilizations\nsolubilize\nsolubilized\nsolubilizes\nsolubilizing\nsoluble\nsolubles\nsolubly\nsolum\nsolums\nsolus\nsolute\nsolutes\nsolution\nsolutions\nsolvabilities\nsolvability\nsolvable\nsolvate\nsolvated\nsolvates\nsolvating\nsolvation\nsolvations\nsolve\nsolved\nsolvencies\nsolvency\nsolvent\nsolventless\nsolvently\nsolvents\nsolver\nsolvers\nsolves\nsolving\nsolvolyses\nsolvolysis\nsolvolytic\nsom\nsoma\nsomas\nsomata\nsomatic\nsomatically\nsomatological\nsomatologies\nsomatology\nsomatomedin\nsomatomedins\nsomatopleure\nsomatopleures\nsomatosensory\nsomatostatin\nsomatostatins\nsomatotrophin\nsomatotrophins\nsomatotropin\nsomatotropins\nsomatotype\nsomatotypes\nsomber\nsomberly\nsomberness\nsombernesses\nsombre\nsombrely\nsombrero\nsombreros\nsombrous\nsome\nsomebodies\nsomebody\nsomeday\nsomedeal\nsomehow\nsomeone\nsomeones\nsomeplace\nsomersault\nsomersaulted\nsomersaulting\nsomersaults\nsomerset\nsomerseted\nsomerseting\nsomersets\nsomersetted\nsomersetting\nsomething\nsometime\nsometimes\nsomeway\nsomeways\nsomewhat\nsomewhats\nsomewhen\nsomewhere\nsomewheres\nsomewhither\nsomewise\nsomital\nsomite\nsomites\nsomitic\nsommelier\nsommeliers\nsomnambulant\nsomnambulate\nsomnambulated\nsomnambulates\nsomnambulating\nsomnambulation\nsomnambulations\nsomnambulism\nsomnambulisms\nsomnambulist\nsomnambulistic\nsomnambulistically\nsomnambulists\nsomnifacient\nsomnifacients\nsomniferous\nsomnolence\nsomnolences\nsomnolent\nsomnolently\nson\nsonance\nsonances\nsonant\nsonantal\nsonantic\nsonants\nsonar\nsonarman\nsonarmen\nsonars\nsonata\nsonatas\nsonatina\nsonatinas\nsonatine\nsonde\nsonder\nsonders\nsondes\nsone\nsones\nsong\nsongbird\nsongbirds\nsongbook\nsongbooks\nsongfest\nsongfests\nsongful\nsongfully\nsongfulness\nsongfulnesses\nsongless\nsonglessly\nsonglike\nsongs\nsongsmith\nsongsmiths\nsongster\nsongsters\nsongstress\nsongstresses\nsongwriter\nsongwriters\nsongwriting\nsongwritings\nsonhood\nsonhoods\nsonic\nsonically\nsonicate\nsonicated\nsonicates\nsonicating\nsonication\nsonications\nsonics\nsonless\nsonlike\nsonly\nsonnet\nsonneted\nsonneteer\nsonneteering\nsonneteerings\nsonneteers\nsonneting\nsonnets\nsonnetted\nsonnetting\nsonnies\nsonny\nsonobuoy\nsonobuoys\nsonogram\nsonograms\nsonographer\nsonographers\nsonographies\nsonography\nsonorant\nsonorants\nsonorities\nsonority\nsonorous\nsonorously\nsonorousness\nsonorousnesses\nsonovox\nsonovoxes\nsons\nsonship\nsonships\nsonsie\nsonsier\nsonsiest\nsonsy\nsoochong\nsoochongs\nsooey\nsook\nsooks\nsoon\nsooner\nsooners\nsoonest\nsoot\nsooted\nsooth\nsoothe\nsoothed\nsoother\nsoothers\nsoothes\nsoothest\nsoothfast\nsoothing\nsoothingly\nsoothingness\nsoothingnesses\nsoothly\nsooths\nsoothsaid\nsoothsay\nsoothsayer\nsoothsayers\nsoothsaying\nsoothsayings\nsoothsays\nsootier\nsootiest\nsootily\nsootiness\nsootinesses\nsooting\nsoots\nsooty\nsop\nsopaipilla\nsopaipillas\nsopapilla\nsopapillas\nsoph\nsophies\nsophism\nsophisms\nsophist\nsophistic\nsophistical\nsophistically\nsophisticate\nsophisticated\nsophisticatedly\nsophisticates\nsophisticating\nsophistication\nsophistications\nsophistries\nsophistry\nsophists\nsophomore\nsophomores\nsophomoric\nsophs\nsophy\nsopite\nsopited\nsopites\nsopiting\nsopor\nsoporiferous\nsoporiferousness\nsoporiferousnesses\nsoporific\nsoporifics\nsopors\nsopped\nsoppier\nsoppiest\nsoppiness\nsoppinesses\nsopping\nsoppy\nsoprani\nsopranino\nsopraninos\nsoprano\nsopranos\nsops\nsora\nsoras\nsorb\nsorbabilities\nsorbability\nsorbable\nsorbate\nsorbates\nsorbed\nsorbent\nsorbents\nsorbet\nsorbets\nsorbic\nsorbing\nsorbitol\nsorbitols\nsorbose\nsorboses\nsorbs\nsorcerer\nsorcerers\nsorceress\nsorceresses\nsorceries\nsorcerous\nsorcery\nsord\nsordid\nsordidly\nsordidness\nsordidnesses\nsordine\nsordines\nsordini\nsordino\nsordor\nsordors\nsords\nsore\nsorehead\nsoreheaded\nsoreheads\nsorel\nsorels\nsorely\nsoreness\nsorenesses\nsorer\nsores\nsorest\nsorgho\nsorghos\nsorghum\nsorghums\nsorgo\nsorgos\nsori\nsoricine\nsoring\nsorings\nsorites\nsoritic\nsorn\nsorned\nsorner\nsorners\nsorning\nsorns\nsoroche\nsoroches\nsororal\nsororate\nsororates\nsororities\nsorority\nsoroses\nsorosis\nsorosises\nsorption\nsorptions\nsorptive\nsorrel\nsorrels\nsorrier\nsorriest\nsorrily\nsorriness\nsorrinesses\nsorrow\nsorrowed\nsorrower\nsorrowers\nsorrowful\nsorrowfully\nsorrowfulness\nsorrowfulnesses\nsorrowing\nsorrows\nsorry\nsort\nsortable\nsortably\nsorted\nsorter\nsorters\nsortie\nsortied\nsortieing\nsorties\nsortilege\nsortileges\nsorting\nsortition\nsortitions\nsorts\nsorus\nsos\nsostenuti\nsostenuto\nsostenutos\nsot\nsoteriological\nsoteriologies\nsoteriology\nsoth\nsoths\nsotol\nsotols\nsots\nsotted\nsottish\nsottishly\nsottishness\nsottishnesses\nsou\nsouari\nsouaris\nsoubise\nsoubises\nsoubrette\nsoubrettes\nsoubriquet\nsoubriquets\nsoucar\nsoucars\nsouchong\nsouchongs\nsoudan\nsoudans\nsouffle\nsouffled\nsouffleed\nsouffles\nsough\nsoughed\nsoughing\nsoughs\nsought\nsouk\nsouks\nsoul\nsouled\nsoulful\nsoulfully\nsoulfulness\nsoulfulnesses\nsoulless\nsoullessly\nsoullessness\nsoullessnesses\nsoullike\nsouls\nsound\nsoundable\nsoundalike\nsoundalikes\nsoundboard\nsoundboards\nsoundbox\nsoundboxes\nsounded\nsounder\nsounders\nsoundest\nsounding\nsoundingly\nsoundings\nsoundless\nsoundlessly\nsoundly\nsoundman\nsoundmen\nsoundness\nsoundnesses\nsoundproof\nsoundproofed\nsoundproofing\nsoundproofs\nsounds\nsoundstage\nsoundstages\nsoundtrack\nsoundtracks\nsoup\nsoupcon\nsoupcons\nsouped\nsoupier\nsoupiest\nsouping\nsoups\nsoupspoon\nsoupspoons\nsoupy\nsour\nsourball\nsourballs\nsource\nsourcebook\nsourcebooks\nsourced\nsourceless\nsources\nsourcing\nsourdine\nsourdines\nsourdough\nsourdoughs\nsoured\nsourer\nsourest\nsouring\nsourish\nsourly\nsourness\nsournesses\nsourpuss\nsourpusses\nsours\nsoursop\nsoursops\nsourwood\nsourwoods\nsous\nsousaphone\nsousaphones\nsouse\nsoused\nsouses\nsousing\nsoutache\nsoutaches\nsoutane\nsoutanes\nsouter\nsouters\nsouth\nsouthbound\nsoutheast\nsoutheaster\nsoutheasterly\nsoutheastern\nsoutheasternmost\nsoutheasters\nsoutheasts\nsoutheastward\nsoutheastwards\nsouthed\nsouther\nsoutherlies\nsoutherly\nsouthern\nsoutherner\nsoutherners\nsouthernmost\nsouthernness\nsouthernnesses\nsoutherns\nsouthernwood\nsouthernwoods\nsouthers\nsouthing\nsouthings\nsouthland\nsouthlands\nsouthpaw\nsouthpaws\nsouthron\nsouthrons\nsouths\nsouthward\nsouthwards\nsouthwest\nsouthwester\nsouthwesterly\nsouthwestern\nsouthwesternmost\nsouthwesters\nsouthwests\nsouthwestward\nsouthwestwards\nsouvenir\nsouvenirs\nsouvlaki\nsouvlakia\nsouvlakias\nsouvlakis\nsovereign\nsovereignly\nsovereigns\nsovereignties\nsovereignty\nsoviet\nsovietism\nsovietisms\nsovietization\nsovietizations\nsovietize\nsovietized\nsovietizes\nsovietizing\nsoviets\nsovkhoz\nsovkhozes\nsovkhozy\nsovran\nsovranly\nsovrans\nsovranties\nsovranty\nsow\nsowable\nsowans\nsowar\nsowars\nsowbellies\nsowbelly\nsowbread\nsowbreads\nsowcar\nsowcars\nsowed\nsowens\nsower\nsowers\nsowing\nsown\nsows\nsox\nsoy\nsoya\nsoyas\nsoybean\nsoybeans\nsoymilk\nsoymilks\nsoys\nsoyuz\nsoyuzes\nsozin\nsozine\nsozines\nsozins\nsozzled\nspa\nspace\nspaceband\nspacebands\nspacecraft\nspacecrafts\nspaced\nspaceflight\nspaceflights\nspaceless\nspaceman\nspacemen\nspaceport\nspaceports\nspacer\nspacers\nspaces\nspaceship\nspaceships\nspacesuit\nspacesuits\nspacewalk\nspacewalked\nspacewalker\nspacewalkers\nspacewalking\nspacewalks\nspaceward\nspacey\nspacial\nspacier\nspaciest\nspacing\nspacings\nspacious\nspaciously\nspaciousness\nspaciousnesses\nspackle\nspackled\nspackles\nspackling\nspacy\nspade\nspaded\nspadefish\nspadefishes\nspadeful\nspadefuls\nspader\nspaders\nspades\nspadework\nspadeworks\nspadices\nspadille\nspadilles\nspading\nspadix\nspadixes\nspado\nspadones\nspae\nspaed\nspaeing\nspaeings\nspaes\nspaetzle\nspaetzles\nspaghetti\nspaghettilike\nspaghettini\nspaghettinis\nspaghettis\nspagyric\nspagyrics\nspahee\nspahees\nspahi\nspahis\nspail\nspails\nspait\nspaits\nspake\nspale\nspales\nspall\nspallable\nspallation\nspallations\nspalled\nspaller\nspallers\nspalling\nspalls\nspalpeen\nspalpeens\nspam\nspammed\nspammer\nspammers\nspamming\nspams\nspan\nspanakopita\nspanakopitas\nspancel\nspanceled\nspanceling\nspancelled\nspancelling\nspancels\nspandex\nspandexes\nspandrel\nspandrels\nspandril\nspandrils\nspang\nspangle\nspangled\nspangles\nspanglier\nspangliest\nspangling\nspangly\nspaniel\nspaniels\nspank\nspanked\nspanker\nspankers\nspanking\nspankings\nspanks\nspanless\nspanned\nspanner\nspanners\nspanning\nspanokopita\nspanokopitas\nspans\nspanworm\nspanworms\nspar\nsparable\nsparables\nspare\nspareable\nspared\nsparely\nspareness\nsparenesses\nsparer\nsparerib\nspareribs\nsparers\nspares\nsparest\nsparge\nsparged\nsparger\nspargers\nsparges\nsparging\nsparid\nsparids\nsparing\nsparingly\nspark\nsparked\nsparker\nsparkers\nsparkier\nsparkiest\nsparkily\nsparking\nsparkish\nsparkle\nsparkled\nsparkler\nsparklers\nsparkles\nsparklier\nsparkliest\nsparkling\nsparkly\nsparkplug\nsparkplugged\nsparkplugging\nsparkplugs\nsparks\nsparky\nsparlike\nsparling\nsparlings\nsparoid\nsparoids\nsparred\nsparrier\nsparriest\nsparring\nsparrow\nsparrowlike\nsparrows\nsparry\nspars\nsparse\nsparsely\nsparseness\nsparsenesses\nsparser\nsparsest\nsparsities\nsparsity\nspartan\nsparteine\nsparteines\nspas\nspasm\nspasmodic\nspasmodically\nspasmolytic\nspasmolytics\nspasms\nspastic\nspastically\nspasticities\nspasticity\nspastics\nspat\nspate\nspates\nspathal\nspathe\nspathed\nspathes\nspathic\nspathose\nspathulate\nspatial\nspatialities\nspatiality\nspatially\nspatiotemporal\nspatiotemporally\nspats\nspatted\nspatter\nspatterdock\nspatterdocks\nspattered\nspattering\nspatters\nspatting\nspatula\nspatular\nspatulas\nspatulate\nspatzle\nspatzles\nspavie\nspavies\nspaviet\nspavin\nspavined\nspavins\nspawn\nspawned\nspawner\nspawners\nspawning\nspawns\nspay\nspayed\nspaying\nspays\nspaz\nspazzes\nspeak\nspeakable\nspeakeasies\nspeakeasy\nspeaker\nspeakerphone\nspeakerphones\nspeakers\nspeakership\nspeakerships\nspeaking\nspeakings\nspeaks\nspean\nspeaned\nspeaning\nspeans\nspear\nspeared\nspearer\nspearers\nspearfish\nspearfished\nspearfishes\nspearfishing\nspeargun\nspearguns\nspearhead\nspearheaded\nspearheading\nspearheads\nspearing\nspearman\nspearmen\nspearmint\nspearmints\nspears\nspearwort\nspearworts\nspec\nspecced\nspeccing\nspecial\nspecialer\nspecialest\nspecialisation\nspecialisations\nspecialise\nspecialised\nspecialises\nspecialising\nspecialism\nspecialisms\nspecialist\nspecialistic\nspecialists\nspecialities\nspeciality\nspecialization\nspecializations\nspecialize\nspecialized\nspecializes\nspecializing\nspecially\nspecialness\nspecialnesses\nspecials\nspecialties\nspecialty\nspeciate\nspeciated\nspeciates\nspeciating\nspeciation\nspeciational\nspeciations\nspecie\nspecies\nspeciesism\nspeciesisms\nspecifiable\nspecific\nspecifically\nspecification\nspecifications\nspecificities\nspecificity\nspecifics\nspecified\nspecifier\nspecifiers\nspecifies\nspecify\nspecifying\nspecimen\nspecimens\nspeciosities\nspeciosity\nspecious\nspeciously\nspeciousness\nspeciousnesses\nspeck\nspecked\nspecking\nspeckle\nspeckled\nspeckles\nspeckling\nspecks\nspecs\nspectacle\nspectacled\nspectacles\nspectacular\nspectacularly\nspectaculars\nspectate\nspectated\nspectates\nspectating\nspectator\nspectatorial\nspectators\nspectatorship\nspectatorships\nspecter\nspecters\nspectinomycin\nspectinomycins\nspectra\nspectral\nspectrally\nspectre\nspectres\nspectrofluorimeter\nspectrofluorimeters\nspectrofluorometer\nspectrofluorometers\nspectrofluorometric\nspectrofluorometries\nspectrofluorometry\nspectrogram\nspectrograms\nspectrograph\nspectrographic\nspectrographically\nspectrographies\nspectrographs\nspectrography\nspectroheliogram\nspectroheliograms\nspectroheliograph\nspectroheliographies\nspectroheliographs\nspectroheliography\nspectrohelioscope\nspectrohelioscopes\nspectrometer\nspectrometers\nspectrometric\nspectrometries\nspectrometry\nspectrophotometer\nspectrophotometers\nspectrophotometric\nspectrophotometrical\nspectrophotometrically\nspectrophotometries\nspectrophotometry\nspectroscope\nspectroscopes\nspectroscopic\nspectroscopically\nspectroscopies\nspectroscopist\nspectroscopists\nspectroscopy\nspectrum\nspectrums\nspecula\nspecular\nspecularities\nspecularity\nspecularly\nspeculate\nspeculated\nspeculates\nspeculating\nspeculation\nspeculations\nspeculative\nspeculatively\nspeculator\nspeculators\nspeculum\nspeculums\nsped\nspeech\nspeeches\nspeechified\nspeechifies\nspeechify\nspeechifying\nspeechless\nspeechlessly\nspeechlessness\nspeechlessnesses\nspeechwriter\nspeechwriters\nspeed\nspeedball\nspeedballed\nspeedballing\nspeedballs\nspeedboat\nspeedboating\nspeedboatings\nspeedboats\nspeeded\nspeeder\nspeeders\nspeedier\nspeediest\nspeedily\nspeediness\nspeedinesses\nspeeding\nspeedings\nspeedo\nspeedometer\nspeedometers\nspeedos\nspeeds\nspeedster\nspeedsters\nspeedup\nspeedups\nspeedway\nspeedways\nspeedwell\nspeedwells\nspeedy\nspeel\nspeeled\nspeeling\nspeels\nspeer\nspeered\nspeering\nspeerings\nspeers\nspeil\nspeiled\nspeiling\nspeils\nspeir\nspeired\nspeiring\nspeirs\nspeise\nspeises\nspeiss\nspeisses\nspelaean\nspelean\nspeleological\nspeleologies\nspeleologist\nspeleologists\nspeleology\nspell\nspellbind\nspellbinder\nspellbinders\nspellbinding\nspellbindingly\nspellbinds\nspellbound\nspelled\nspeller\nspellers\nspelling\nspellings\nspells\nspelt\nspelter\nspelters\nspelts\nspeltz\nspeltzes\nspelunk\nspelunked\nspelunker\nspelunkers\nspelunking\nspelunkings\nspelunks\nspence\nspencer\nspencers\nspences\nspend\nspendable\nspender\nspenders\nspending\nspends\nspendthrift\nspendthrifts\nspense\nspenses\nspent\nsperm\nspermaceti\nspermacetis\nspermagonia\nspermagonium\nspermaries\nspermary\nspermatheca\nspermathecae\nspermatia\nspermatial\nspermatic\nspermatid\nspermatids\nspermatium\nspermatocyte\nspermatocytes\nspermatogeneses\nspermatogenesis\nspermatogenic\nspermatogonia\nspermatogonial\nspermatogonium\nspermatophore\nspermatophores\nspermatophyte\nspermatophytes\nspermatophytic\nspermatozoa\nspermatozoal\nspermatozoan\nspermatozoans\nspermatozoid\nspermatozoids\nspermatozoon\nspermic\nspermicidal\nspermicide\nspermicides\nspermine\nspermines\nspermiogeneses\nspermiogenesis\nspermophile\nspermophiles\nspermous\nsperms\nsperrylite\nsperrylites\nspessartine\nspessartines\nspessartite\nspessartites\nspew\nspewed\nspewer\nspewers\nspewing\nspews\nsphagnous\nsphagnum\nsphagnums\nsphalerite\nsphalerites\nsphene\nsphenes\nsphenic\nsphenodon\nsphenodons\nsphenodont\nsphenoid\nsphenoidal\nsphenoids\nsphenopsid\nsphenopsids\nspheral\nsphere\nsphered\nspheres\nspheric\nspherical\nspherically\nsphericities\nsphericity\nspherics\nspherier\nspheriest\nsphering\nspheroid\nspheroidal\nspheroidally\nspheroids\nspherometer\nspherometers\nspheroplast\nspheroplasts\nspherule\nspherules\nspherulite\nspherulites\nspherulitic\nsphery\nsphincter\nsphincteric\nsphincters\nsphinges\nsphingid\nsphingids\nsphingosine\nsphingosines\nsphinx\nsphinxes\nsphinxlike\nsphygmic\nsphygmograph\nsphygmographs\nsphygmomanometer\nsphygmomanometers\nsphygmomanometries\nsphygmomanometry\nsphygmus\nsphygmuses\nspic\nspica\nspicae\nspicas\nspicate\nspicated\nspiccato\nspiccatos\nspice\nspicebush\nspicebushes\nspiced\nspiceless\nspicer\nspiceries\nspicers\nspicery\nspices\nspicey\nspicier\nspiciest\nspicily\nspiciness\nspicinesses\nspicing\nspick\nspicks\nspics\nspicula\nspiculae\nspicular\nspiculation\nspiculations\nspicule\nspicules\nspiculum\nspicy\nspider\nspiderier\nspideriest\nspiderish\nspiderlike\nspiders\nspiderweb\nspiderwebs\nspiderwort\nspiderworts\nspidery\nspied\nspiegel\nspiegeleisen\nspiegeleisens\nspiegels\nspiel\nspieled\nspieler\nspielers\nspieling\nspiels\nspier\nspiered\nspiering\nspiers\nspies\nspiff\nspiffed\nspiffier\nspiffiest\nspiffily\nspiffiness\nspiffinesses\nspiffing\nspiffs\nspiffy\nspigot\nspigots\nspik\nspike\nspiked\nspikelet\nspikelets\nspikelike\nspikenard\nspikenards\nspiker\nspikers\nspikes\nspikey\nspikier\nspikiest\nspikily\nspikiness\nspikinesses\nspiking\nspiks\nspiky\nspile\nspiled\nspiles\nspilikin\nspilikins\nspiling\nspilings\nspill\nspillable\nspillage\nspillages\nspilled\nspiller\nspillers\nspillikin\nspillikins\nspilling\nspillover\nspillovers\nspills\nspillway\nspillways\nspilt\nspilth\nspilths\nspin\nspinach\nspinaches\nspinachlike\nspinachy\nspinage\nspinages\nspinal\nspinally\nspinals\nspinate\nspindle\nspindled\nspindler\nspindlers\nspindles\nspindlier\nspindliest\nspindling\nspindly\nspindrift\nspindrifts\nspine\nspined\nspinel\nspineless\nspinelessly\nspinelessness\nspinelessnesses\nspinelike\nspinelle\nspinelles\nspinels\nspines\nspinet\nspinets\nspinier\nspiniest\nspinifex\nspinifexes\nspininess\nspininesses\nspinless\nspinnaker\nspinnakers\nspinner\nspinneret\nspinnerets\nspinnerette\nspinnerettes\nspinneries\nspinners\nspinnery\nspinney\nspinneys\nspinnies\nspinning\nspinnings\nspinny\nspinoff\nspinoffs\nspinor\nspinors\nspinose\nspinosities\nspinosity\nspinous\nspinout\nspinouts\nspins\nspinster\nspinsterhood\nspinsterhoods\nspinsterish\nspinsterly\nspinsters\nspinthariscope\nspinthariscopes\nspinto\nspintos\nspinula\nspinulae\nspinule\nspinules\nspinulose\nspiny\nspiracle\nspiracles\nspiracular\nspiraea\nspiraeas\nspiral\nspiraled\nspiraling\nspiralled\nspiralling\nspirally\nspirals\nspirant\nspirants\nspire\nspirea\nspireas\nspired\nspirem\nspireme\nspiremes\nspirems\nspires\nspirier\nspiriest\nspirilla\nspirillum\nspiring\nspirit\nspirited\nspiritedly\nspiritedness\nspiritednesses\nspiriting\nspiritism\nspiritisms\nspiritist\nspiritistic\nspiritists\nspiritless\nspiritlessly\nspiritlessness\nspiritlessnesses\nspiritoso\nspiritous\nspirits\nspiritual\nspiritualism\nspiritualisms\nspiritualist\nspiritualistic\nspiritualists\nspiritualities\nspirituality\nspiritualization\nspiritualizations\nspiritualize\nspiritualized\nspiritualizes\nspiritualizing\nspiritually\nspiritualness\nspiritualnesses\nspirituals\nspiritualties\nspiritualty\nspirituel\nspirituelle\nspirituous\nspirochaete\nspirochaetes\nspirochetal\nspirochete\nspirochetes\nspirochetoses\nspirochetosis\nspirogyra\nspirogyras\nspiroid\nspirometer\nspirometers\nspirometric\nspirometries\nspirometry\nspirt\nspirted\nspirting\nspirts\nspirula\nspirulae\nspirulas\nspiry\nspit\nspital\nspitals\nspitball\nspitballs\nspite\nspited\nspiteful\nspitefuller\nspitefullest\nspitefully\nspitefulness\nspitefulnesses\nspites\nspitfire\nspitfires\nspiting\nspits\nspitted\nspitter\nspitters\nspitting\nspittle\nspittlebug\nspittlebugs\nspittles\nspittoon\nspittoons\nspitz\nspitzes\nspiv\nspivs\nsplake\nsplakes\nsplanchnic\nsplash\nsplashboard\nsplashboards\nsplashdown\nsplashdowns\nsplashed\nsplasher\nsplashers\nsplashes\nsplashier\nsplashiest\nsplashily\nsplashiness\nsplashinesses\nsplashing\nsplashy\nsplat\nsplats\nsplatted\nsplatter\nsplattered\nsplattering\nsplatters\nsplatting\nsplay\nsplayed\nsplayfeet\nsplayfoot\nsplayfooted\nsplaying\nsplays\nspleen\nspleenful\nspleenier\nspleeniest\nspleens\nspleenwort\nspleenworts\nspleeny\nsplendent\nsplendid\nsplendider\nsplendidest\nsplendidly\nsplendidness\nsplendidnesses\nsplendiferous\nsplendiferously\nsplendiferousness\nsplendiferousnesses\nsplendor\nsplendorous\nsplendors\nsplendour\nsplendours\nsplendrous\nsplenectomies\nsplenectomize\nsplenectomized\nsplenectomizes\nsplenectomizing\nsplenectomy\nsplenetic\nsplenetically\nsplenetics\nsplenia\nsplenial\nsplenic\nsplenii\nsplenium\nsplenius\nsplenomegalies\nsplenomegaly\nsplent\nsplents\nspleuchan\nspleuchans\nsplice\nspliced\nsplicer\nsplicers\nsplices\nsplicing\nspliff\nspliffs\nspline\nsplined\nsplines\nsplining\nsplint\nsplinted\nsplinter\nsplintered\nsplintering\nsplinters\nsplintery\nsplinting\nsplints\nsplit\nsplits\nsplitter\nsplitters\nsplitting\nsplodge\nsplodged\nsplodges\nsplodging\nsplore\nsplores\nsplosh\nsploshed\nsploshes\nsploshing\nsplotch\nsplotched\nsplotches\nsplotchier\nsplotchiest\nsplotching\nsplotchy\nsplurge\nsplurged\nsplurger\nsplurgers\nsplurges\nsplurgier\nsplurgiest\nsplurging\nsplurgy\nsplutter\nspluttered\nsplutterer\nsplutterers\nspluttering\nsplutters\nspluttery\nspode\nspodes\nspodumene\nspodumenes\nspoil\nspoilable\nspoilage\nspoilages\nspoiled\nspoiler\nspoilers\nspoiling\nspoils\nspoilsman\nspoilsmen\nspoilsport\nspoilsports\nspoilt\nspoke\nspoked\nspoken\nspokes\nspokeshave\nspokeshaves\nspokesman\nspokesmanship\nspokesmanships\nspokesmen\nspokespeople\nspokesperson\nspokespersons\nspokeswoman\nspokeswomen\nspoking\nspoliate\nspoliated\nspoliates\nspoliating\nspoliation\nspoliations\nspoliator\nspoliators\nspondaic\nspondaics\nspondee\nspondees\nspondylitis\nspondylitises\nsponge\nsponged\nsponger\nspongers\nsponges\nspongeware\nspongewares\nspongier\nspongiest\nspongily\nspongin\nsponginess\nsponginesses\nsponging\nspongins\nspongy\nsponsal\nsponsion\nsponsions\nsponson\nsponsons\nsponsor\nsponsored\nsponsorial\nsponsoring\nsponsors\nsponsorship\nsponsorships\nspontaneities\nspontaneity\nspontaneous\nspontaneously\nspontaneousness\nspontaneousnesses\nspontoon\nspontoons\nspoof\nspoofed\nspoofer\nspooferies\nspoofers\nspoofery\nspoofing\nspoofs\nspoofy\nspook\nspooked\nspookeries\nspookery\nspookier\nspookiest\nspookily\nspookiness\nspookinesses\nspooking\nspookish\nspooks\nspooky\nspool\nspooled\nspooling\nspoolings\nspools\nspoon\nspoonbill\nspoonbills\nspooned\nspoonerism\nspoonerisms\nspooney\nspooneys\nspoonful\nspoonfuls\nspoonier\nspoonies\nspooniest\nspoonily\nspooning\nspoons\nspoonsful\nspoony\nspoor\nspoored\nspooring\nspoors\nsporadic\nsporadically\nsporal\nsporangia\nsporangial\nsporangiophore\nsporangiophores\nsporangium\nspore\nspored\nspores\nsporicidal\nsporicide\nsporicides\nsporing\nsporocarp\nsporocarps\nsporocyst\nsporocysts\nsporogeneses\nsporogenesis\nsporogenic\nsporogenous\nsporogonia\nsporogonic\nsporogonies\nsporogonium\nsporogony\nsporoid\nsporophore\nsporophores\nsporophyll\nsporophylls\nsporophyte\nsporophytes\nsporophytic\nsporopollenin\nsporopollenins\nsporotrichoses\nsporotrichosis\nsporozoa\nsporozoan\nsporozoans\nsporozoite\nsporozoites\nsporozoon\nsporran\nsporrans\nsport\nsported\nsporter\nsporters\nsportfisherman\nsportfishermen\nsportfishing\nsportfishings\nsportful\nsportfully\nsportfulness\nsportfulnesses\nsportier\nsportiest\nsportif\nsportily\nsportiness\nsportinesses\nsporting\nsportingly\nsportive\nsportively\nsportiveness\nsportivenesses\nsports\nsportscast\nsportscaster\nsportscasters\nsportscasting\nsportscastings\nsportscasts\nsportsman\nsportsmanlike\nsportsmanly\nsportsmanship\nsportsmanships\nsportsmen\nsportswear\nsportswoman\nsportswomen\nsportswriter\nsportswriters\nsportswriting\nsportswritings\nsporty\nsporular\nsporulate\nsporulated\nsporulates\nsporulating\nsporulation\nsporulations\nsporulative\nsporule\nsporules\nspot\nspotless\nspotlessly\nspotlessness\nspotlessnesses\nspotlight\nspotlighted\nspotlighting\nspotlights\nspotlit\nspots\nspottable\nspotted\nspotter\nspotters\nspottier\nspottiest\nspottily\nspottiness\nspottinesses\nspotting\nspotty\nspousal\nspousals\nspouse\nspoused\nspouses\nspousing\nspout\nspouted\nspouter\nspouters\nspouting\nspouts\nsprachgefuhl\nsprachgefuhls\nspraddle\nspraddled\nspraddles\nspraddling\nsprag\nsprags\nsprain\nsprained\nspraining\nsprains\nsprang\nsprangs\nsprat\nsprats\nsprattle\nsprattled\nsprattles\nsprattling\nsprawl\nsprawled\nsprawler\nsprawlers\nsprawlier\nsprawliest\nsprawling\nsprawls\nsprawly\nspray\nsprayed\nsprayer\nsprayers\nspraying\nsprays\nspread\nspreadabilities\nspreadability\nspreadable\nspreader\nspreaders\nspreading\nspreads\nspreadsheet\nspreadsheets\nspree\nsprees\nsprent\nsprier\nspriest\nsprig\nsprigged\nsprigger\nspriggers\nspriggier\nspriggiest\nsprigging\nspriggy\nspright\nsprightful\nsprightfully\nsprightfulness\nsprightfulnesses\nsprightlier\nsprightliest\nsprightliness\nsprightlinesses\nsprightly\nsprights\nsprigs\nspring\nspringal\nspringald\nspringalds\nspringals\nspringboard\nspringboards\nspringbok\nspringboks\nspringe\nspringed\nspringeing\nspringer\nspringers\nspringes\nspringhead\nspringheads\nspringhouse\nspringhouses\nspringier\nspringiest\nspringily\nspringiness\nspringinesses\nspringing\nspringings\nspringlike\nsprings\nspringtail\nspringtails\nspringtide\nspringtides\nspringtime\nspringtimes\nspringwater\nspringwaters\nspringwood\nspringwoods\nspringy\nsprinkle\nsprinkled\nsprinkler\nsprinklered\nsprinklers\nsprinkles\nsprinkling\nsprinklings\nsprint\nsprinted\nsprinter\nsprinters\nsprinting\nsprints\nsprit\nsprite\nsprites\nsprits\nspritsail\nspritsails\nspritz\nspritzed\nspritzer\nspritzers\nspritzes\nspritzing\nsprocket\nsprockets\nsprout\nsprouted\nsprouting\nsprouts\nspruce\nspruced\nsprucely\nspruceness\nsprucenesses\nsprucer\nspruces\nsprucest\nsprucier\nspruciest\nsprucing\nsprucy\nsprue\nsprues\nsprug\nsprugs\nsprung\nspry\nspryer\nspryest\nspryly\nspryness\nsprynesses\nspud\nspudded\nspudder\nspudders\nspudding\nspuds\nspue\nspued\nspues\nspuing\nspume\nspumed\nspumes\nspumier\nspumiest\nspuming\nspumone\nspumones\nspumoni\nspumonis\nspumous\nspumy\nspun\nspunbonded\nspunk\nspunked\nspunkie\nspunkier\nspunkies\nspunkiest\nspunkily\nspunkiness\nspunkinesses\nspunking\nspunks\nspunky\nspur\nspurgall\nspurgalled\nspurgalling\nspurgalls\nspurge\nspurges\nspurious\nspuriously\nspuriousness\nspuriousnesses\nspurn\nspurned\nspurner\nspurners\nspurning\nspurns\nspurred\nspurrer\nspurrers\nspurrey\nspurreys\nspurrier\nspurriers\nspurries\nspurring\nspurry\nspurs\nspurt\nspurted\nspurting\nspurtle\nspurtles\nspurts\nsputa\nsputnik\nsputniks\nsputter\nsputtered\nsputterer\nsputterers\nsputtering\nsputters\nsputum\nspy\nspyglass\nspyglasses\nspying\nspymaster\nspymasters\nsquab\nsquabbier\nsquabbiest\nsquabble\nsquabbled\nsquabbler\nsquabblers\nsquabbles\nsquabbling\nsquabby\nsquabs\nsquad\nsquadded\nsquadding\nsquadron\nsquadroned\nsquadroning\nsquadrons\nsquads\nsqualene\nsqualenes\nsqualid\nsqualider\nsqualidest\nsqualidly\nsqualidness\nsqualidnesses\nsquall\nsqualled\nsqualler\nsquallers\nsquallier\nsqualliest\nsqualling\nsqualls\nsqually\nsqualor\nsqualors\nsquama\nsquamae\nsquamate\nsquamation\nsquamations\nsquamosal\nsquamosals\nsquamose\nsquamous\nsquamulose\nsquander\nsquandered\nsquanderer\nsquanderers\nsquandering\nsquanders\nsquare\nsquared\nsquarely\nsquareness\nsquarenesses\nsquarer\nsquarers\nsquares\nsquarest\nsquaring\nsquarish\nsquarishly\nsquarishness\nsquarishnesses\nsquash\nsquashed\nsquasher\nsquashers\nsquashes\nsquashier\nsquashiest\nsquashily\nsquashiness\nsquashinesses\nsquashing\nsquashy\nsquat\nsquatly\nsquatness\nsquatnesses\nsquats\nsquatted\nsquatter\nsquattered\nsquattering\nsquatters\nsquattest\nsquattier\nsquattiest\nsquatting\nsquatty\nsquaw\nsquawfish\nsquawfishes\nsquawk\nsquawked\nsquawker\nsquawkers\nsquawking\nsquawks\nsquawroot\nsquawroots\nsquaws\nsqueak\nsqueaked\nsqueaker\nsqueakers\nsqueakier\nsqueakiest\nsqueaking\nsqueaks\nsqueaky\nsqueal\nsquealed\nsquealer\nsquealers\nsquealing\nsqueals\nsqueamish\nsqueamishly\nsqueamishness\nsqueamishnesses\nsqueegee\nsqueegeed\nsqueegeeing\nsqueegees\nsqueezabilities\nsqueezability\nsqueezable\nsqueeze\nsqueezed\nsqueezer\nsqueezers\nsqueezes\nsqueezing\nsqueg\nsquegged\nsquegging\nsquegs\nsquelch\nsquelched\nsquelcher\nsquelchers\nsquelches\nsquelchier\nsquelchiest\nsquelching\nsquelchy\nsqueteague\nsqueteagues\nsquib\nsquibbed\nsquibbing\nsquibs\nsquid\nsquidded\nsquidding\nsquids\nsquiffed\nsquiffier\nsquiffiest\nsquiffy\nsquiggle\nsquiggled\nsquiggles\nsquigglier\nsquiggliest\nsquiggling\nsquiggly\nsquilgee\nsquilgeed\nsquilgeeing\nsquilgees\nsquill\nsquilla\nsquillae\nsquillas\nsquills\nsquinch\nsquinched\nsquinches\nsquinching\nsquinnied\nsquinnier\nsquinnies\nsquinniest\nsquinny\nsquinnying\nsquint\nsquinted\nsquinter\nsquinters\nsquintest\nsquintier\nsquintiest\nsquinting\nsquintingly\nsquints\nsquinty\nsquirarchies\nsquirarchy\nsquire\nsquirearchies\nsquirearchy\nsquired\nsquireen\nsquireens\nsquires\nsquiring\nsquirish\nsquirm\nsquirmed\nsquirmer\nsquirmers\nsquirmier\nsquirmiest\nsquirming\nsquirms\nsquirmy\nsquirrel\nsquirreled\nsquirreling\nsquirrelled\nsquirrelling\nsquirrelly\nsquirrels\nsquirt\nsquirted\nsquirter\nsquirters\nsquirting\nsquirts\nsquish\nsquished\nsquishes\nsquishier\nsquishiest\nsquishiness\nsquishinesses\nsquishing\nsquishy\nsquoosh\nsquooshed\nsquooshes\nsquooshier\nsquooshiest\nsquooshing\nsquooshy\nsquush\nsquushed\nsquushes\nsquushier\nsquushiest\nsquushing\nsquushy\nsraddha\nsraddhas\nsradha\nsradhas\nsri\nsris\nstab\nstabbed\nstabber\nstabbers\nstabbing\nstabbings\nstabile\nstabiles\nstabilities\nstability\nstabilization\nstabilizations\nstabilize\nstabilized\nstabilizer\nstabilizers\nstabilizes\nstabilizing\nstable\nstabled\nstableman\nstablemate\nstablemates\nstablemen\nstableness\nstablenesses\nstabler\nstablers\nstables\nstablest\nstabling\nstablings\nstablish\nstablished\nstablishes\nstablishing\nstablishment\nstablishments\nstably\nstabs\nstaccati\nstaccato\nstaccatos\nstack\nstackable\nstacked\nstacker\nstackers\nstacking\nstacks\nstackup\nstackups\nstacte\nstactes\nstaddle\nstaddles\nstade\nstades\nstadia\nstadias\nstadium\nstadiums\nstadtholder\nstadtholderate\nstadtholderates\nstadtholders\nstadtholdership\nstadtholderships\nstaff\nstaffed\nstaffer\nstaffers\nstaffing\nstaffs\nstag\nstage\nstageable\nstagecoach\nstagecoaches\nstagecraft\nstagecrafts\nstaged\nstageful\nstagefuls\nstagehand\nstagehands\nstagelike\nstager\nstagers\nstages\nstagestruck\nstagey\nstagflation\nstagflationary\nstagflations\nstaggard\nstaggards\nstaggart\nstaggarts\nstagged\nstagger\nstaggerbush\nstaggerbushes\nstaggered\nstaggerer\nstaggerers\nstaggering\nstaggeringly\nstaggers\nstaggery\nstaggie\nstaggier\nstaggies\nstaggiest\nstagging\nstaggy\nstaghound\nstaghounds\nstagier\nstagiest\nstagily\nstaginess\nstaginesses\nstaging\nstagings\nstagnancies\nstagnancy\nstagnant\nstagnantly\nstagnate\nstagnated\nstagnates\nstagnating\nstagnation\nstagnations\nstags\nstagy\nstaid\nstaider\nstaidest\nstaidly\nstaidness\nstaidnesses\nstaig\nstaigs\nstain\nstainabilities\nstainability\nstainable\nstained\nstainer\nstainers\nstaining\nstainless\nstainlesses\nstainlessly\nstainproof\nstains\nstair\nstaircase\nstaircases\nstairs\nstairway\nstairways\nstairwell\nstairwells\nstaithe\nstaithes\nstake\nstaked\nstakeholder\nstakeholders\nstakeout\nstakeouts\nstakes\nstaking\nstalactite\nstalactites\nstalactitic\nstalag\nstalagmite\nstalagmites\nstalagmitic\nstalags\nstale\nstaled\nstalely\nstalemate\nstalemated\nstalemates\nstalemating\nstaleness\nstalenesses\nstaler\nstales\nstalest\nstaling\nstalk\nstalked\nstalker\nstalkers\nstalkier\nstalkiest\nstalkily\nstalking\nstalkless\nstalks\nstalky\nstall\nstalled\nstallholder\nstallholders\nstalling\nstallion\nstallions\nstalls\nstalwart\nstalwartly\nstalwartness\nstalwartnesses\nstalwarts\nstalworth\nstalworths\nstamen\nstamens\nstamina\nstaminal\nstaminas\nstaminate\nstaminodia\nstaminodium\nstammel\nstammels\nstammer\nstammered\nstammerer\nstammerers\nstammering\nstammers\nstamp\nstamped\nstampede\nstampeded\nstampeder\nstampeders\nstampedes\nstampeding\nstamper\nstampers\nstamping\nstampless\nstamps\nstance\nstances\nstanch\nstanched\nstancher\nstanchers\nstanches\nstanchest\nstanching\nstanchion\nstanchioned\nstanchions\nstanchly\nstand\nstandard\nstandardbred\nstandardbreds\nstandardise\nstandardised\nstandardises\nstandardising\nstandardization\nstandardizations\nstandardize\nstandardized\nstandardizes\nstandardizing\nstandardless\nstandardly\nstandards\nstandaway\nstandby\nstandbys\nstandee\nstandees\nstander\nstanders\nstanding\nstandings\nstandish\nstandishes\nstandoff\nstandoffish\nstandoffishly\nstandoffishness\nstandoffishnesses\nstandoffs\nstandout\nstandouts\nstandpat\nstandpatter\nstandpatters\nstandpattism\nstandpattisms\nstandpipe\nstandpipes\nstandpoint\nstandpoints\nstands\nstandstill\nstandstills\nstandup\nstane\nstaned\nstanes\nstang\nstanged\nstanging\nstangs\nstanhope\nstanhopes\nstanine\nstanines\nstaning\nstank\nstanks\nstannaries\nstannary\nstannic\nstannite\nstannites\nstannous\nstannum\nstannums\nstanza\nstanzaed\nstanzaic\nstanzas\nstapedectomies\nstapedectomy\nstapedes\nstapedial\nstapelia\nstapelias\nstapes\nstaph\nstaphs\nstaphylinid\nstaphylinids\nstaphylococcal\nstaphylococci\nstaphylococcic\nstaphylococcus\nstaple\nstapled\nstapler\nstaplers\nstaples\nstapling\nstar\nstarboard\nstarboarded\nstarboarding\nstarboards\nstarburst\nstarbursts\nstarch\nstarched\nstarches\nstarchier\nstarchiest\nstarchily\nstarchiness\nstarchinesses\nstarching\nstarchy\nstardom\nstardoms\nstardust\nstardusts\nstare\nstared\nstarer\nstarers\nstares\nstarets\nstarfish\nstarfishes\nstarflower\nstarflowers\nstarfruit\nstarfruits\nstargaze\nstargazed\nstargazer\nstargazers\nstargazes\nstargazing\nstargazings\nstaring\nstark\nstarker\nstarkers\nstarkest\nstarkly\nstarkness\nstarknesses\nstarless\nstarlet\nstarlets\nstarlight\nstarlights\nstarlike\nstarling\nstarlings\nstarlit\nstarnose\nstarnoses\nstarred\nstarrier\nstarriest\nstarring\nstarry\nstars\nstarship\nstarships\nstarstruck\nstart\nstarted\nstarter\nstarters\nstarting\nstartle\nstartled\nstartlement\nstartlements\nstartler\nstartlers\nstartles\nstartling\nstartlingly\nstarts\nstartsy\nstartup\nstartups\nstarvation\nstarvations\nstarve\nstarved\nstarveling\nstarvelings\nstarver\nstarvers\nstarves\nstarving\nstarwort\nstarworts\nstases\nstash\nstashed\nstashes\nstashing\nstasima\nstasimon\nstasis\nstat\nstatable\nstatal\nstatant\nstate\nstateable\nstatecraft\nstatecrafts\nstated\nstatedly\nstatehood\nstatehoods\nstatehouse\nstatehouses\nstateless\nstatelessness\nstatelessnesses\nstatelier\nstateliest\nstateliness\nstatelinesses\nstately\nstatement\nstatements\nstater\nstateroom\nstaterooms\nstaters\nstates\nstateside\nstatesman\nstatesmanlike\nstatesmanly\nstatesmanship\nstatesmanships\nstatesmen\nstatewide\nstatic\nstatical\nstatically\nstatice\nstatices\nstaticky\nstatics\nstating\nstation\nstational\nstationary\nstationed\nstationer\nstationeries\nstationers\nstationery\nstationing\nstationmaster\nstationmasters\nstations\nstatism\nstatisms\nstatist\nstatistic\nstatistical\nstatistically\nstatistician\nstatisticians\nstatistics\nstatists\nstative\nstatives\nstatoblast\nstatoblasts\nstatocyst\nstatocysts\nstatolith\nstatoliths\nstator\nstators\nstatoscope\nstatoscopes\nstats\nstatuaries\nstatuary\nstatue\nstatued\nstatues\nstatuesque\nstatuesquely\nstatuette\nstatuettes\nstature\nstatures\nstatus\nstatuses\nstatusy\nstatutable\nstatute\nstatutes\nstatutorily\nstatutory\nstaumrel\nstaumrels\nstaunch\nstaunched\nstauncher\nstaunches\nstaunchest\nstaunching\nstaunchly\nstaunchness\nstaunchnesses\nstaurolite\nstaurolites\nstaurolitic\nstave\nstaved\nstaves\nstavesacre\nstavesacres\nstaving\nstaw\nstay\nstayed\nstayer\nstayers\nstaying\nstays\nstaysail\nstaysails\nstead\nsteaded\nsteadfast\nsteadfastly\nsteadfastness\nsteadfastnesses\nsteadied\nsteadier\nsteadiers\nsteadies\nsteadiest\nsteadily\nsteadiness\nsteadinesses\nsteading\nsteadings\nsteads\nsteady\nsteadying\nsteak\nsteakhouse\nsteakhouses\nsteaks\nsteal\nstealable\nstealage\nstealages\nstealer\nstealers\nstealing\nstealings\nsteals\nstealth\nstealthier\nstealthiest\nstealthily\nstealthiness\nstealthinesses\nstealths\nstealthy\nsteam\nsteamboat\nsteamboats\nsteamed\nsteamer\nsteamered\nsteamering\nsteamers\nsteamfitter\nsteamfitters\nsteamier\nsteamiest\nsteamily\nsteaminess\nsteaminesses\nsteaming\nsteamroll\nsteamrolled\nsteamroller\nsteamrollered\nsteamrollering\nsteamrollers\nsteamrolling\nsteamrolls\nsteams\nsteamship\nsteamships\nsteamy\nsteapsin\nsteapsins\nstearate\nstearates\nstearic\nstearin\nstearine\nstearines\nstearins\nsteatite\nsteatites\nsteatitic\nsteatopygia\nsteatopygias\nsteatopygic\nsteatopygous\nsteatorrhea\nsteatorrheas\nstedfast\nsteed\nsteeds\nsteek\nsteeked\nsteeking\nsteeks\nsteel\nsteeled\nsteelhead\nsteelheads\nsteelie\nsteelier\nsteelies\nsteeliest\nsteeliness\nsteelinesses\nsteeling\nsteelmaker\nsteelmakers\nsteelmaking\nsteelmakings\nsteels\nsteelwork\nsteelworker\nsteelworkers\nsteelworks\nsteely\nsteelyard\nsteelyards\nsteenbok\nsteenboks\nsteep\nsteeped\nsteepen\nsteepened\nsteepening\nsteepens\nsteeper\nsteepers\nsteepest\nsteeping\nsteepish\nsteeple\nsteeplebush\nsteeplebushes\nsteeplechase\nsteeplechaser\nsteeplechasers\nsteeplechases\nsteeplechasing\nsteeplechasings\nsteepled\nsteeplejack\nsteeplejacks\nsteeples\nsteeply\nsteepness\nsteepnesses\nsteeps\nsteer\nsteerable\nsteerage\nsteerages\nsteerageway\nsteerageways\nsteered\nsteerer\nsteerers\nsteering\nsteers\nsteersman\nsteersmen\nsteeve\nsteeved\nsteeves\nsteeving\nsteevings\nstegodon\nstegodons\nstegosaur\nstegosaurs\nstegosaurus\nstegosauruses\nstein\nsteinbok\nsteinboks\nsteins\nstela\nstelae\nstelai\nstelar\nstele\nstelene\nsteles\nstelic\nstella\nstellar\nstellas\nstellate\nstellified\nstellifies\nstellify\nstellifying\nstem\nstemless\nstemlike\nstemma\nstemmas\nstemmata\nstemmatic\nstemmed\nstemmer\nstemmeries\nstemmers\nstemmery\nstemmier\nstemmiest\nstemming\nstemmy\nstems\nstemson\nstemsons\nstemware\nstemwares\nstench\nstenches\nstenchful\nstenchier\nstenchiest\nstenchy\nstencil\nstenciled\nstenciler\nstencilers\nstenciling\nstencilled\nstenciller\nstencillers\nstencilling\nstencils\nstengah\nstengahs\nsteno\nstenobathic\nstenographer\nstenographers\nstenographic\nstenographically\nstenographies\nstenography\nstenohaline\nstenokies\nstenoky\nstenos\nstenosed\nstenoses\nstenosis\nstenotherm\nstenothermal\nstenotherms\nstenotic\nstenotopic\nstenotype\nstenotyped\nstenotypes\nstenotypies\nstenotyping\nstenotypist\nstenotypists\nstenotypy\nstentor\nstentorian\nstentors\nstep\nstepbrother\nstepbrothers\nstepchild\nstepchildren\nstepdame\nstepdames\nstepdaughter\nstepdaughters\nstepfamilies\nstepfamily\nstepfather\nstepfathers\nstephanotis\nstephanotises\nstepladder\nstepladders\nsteplike\nstepmother\nstepmothers\nstepparent\nstepparenting\nstepparentings\nstepparents\nsteppe\nstepped\nstepper\nsteppers\nsteppes\nstepping\nsteppingstone\nsteppingstones\nsteps\nstepsister\nstepsisters\nstepson\nstepsons\nstepwise\nstercoraceous\nstere\nstereo\nstereochemical\nstereochemistries\nstereochemistry\nstereoed\nstereogram\nstereograms\nstereograph\nstereographed\nstereographic\nstereographies\nstereographing\nstereographs\nstereography\nstereoing\nstereoisomer\nstereoisomeric\nstereoisomerism\nstereoisomerisms\nstereoisomers\nstereological\nstereologically\nstereologies\nstereology\nstereomicroscope\nstereomicroscopes\nstereomicroscopic\nstereomicroscopically\nstereophonic\nstereophonically\nstereophonies\nstereophony\nstereophotographic\nstereophotographies\nstereophotography\nstereopses\nstereopsides\nstereopsis\nstereopticon\nstereopticons\nstereoregular\nstereoregularities\nstereoregularity\nstereos\nstereoscope\nstereoscopes\nstereoscopic\nstereoscopically\nstereoscopies\nstereoscopy\nstereospecific\nstereospecifically\nstereospecificities\nstereospecificity\nstereotactic\nstereotaxic\nstereotaxically\nstereotype\nstereotyped\nstereotyper\nstereotypers\nstereotypes\nstereotypic\nstereotypical\nstereotypically\nstereotypies\nstereotyping\nstereotypy\nsteres\nsteric\nsterical\nsterically\nsterigma\nsterigmas\nsterigmata\nsterilant\nsterilants\nsterile\nsterilely\nsterilities\nsterility\nsterilization\nsterilizations\nsterilize\nsterilized\nsterilizer\nsterilizers\nsterilizes\nsterilizing\nsterlet\nsterlets\nsterling\nsterlingly\nsterlingness\nsterlingnesses\nsterlings\nstern\nsterna\nsternal\nsterner\nsternest\nsternforemost\nsternite\nsternites\nsternly\nsternmost\nsternness\nsternnesses\nsternocostal\nsternpost\nsternposts\nsterns\nsternson\nsternsons\nsternum\nsternums\nsternutation\nsternutations\nsternutator\nsternutators\nsternward\nsternwards\nsternway\nsternways\nsteroid\nsteroidal\nsteroidogeneses\nsteroidogenesis\nsteroidogenic\nsteroids\nsterol\nsterols\nstertor\nstertorous\nstertorously\nstertors\nstet\nstethoscope\nstethoscopes\nstethoscopic\nstets\nstetted\nstetting\nstevedore\nstevedored\nstevedores\nstevedoring\nstew\nsteward\nstewarded\nstewardess\nstewardesses\nstewarding\nstewards\nstewardship\nstewardships\nstewbum\nstewbums\nstewed\nstewing\nstewpan\nstewpans\nstews\nstey\nsthenia\nsthenias\nsthenic\nstibial\nstibine\nstibines\nstibium\nstibiums\nstibnite\nstibnites\nstich\nstichic\nstichomythia\nstichomythias\nstichomythic\nstichomythies\nstichomythy\nstichs\nstick\nstickball\nstickballs\nsticked\nsticker\nstickers\nstickful\nstickfuls\nstickhandle\nstickhandled\nstickhandler\nstickhandlers\nstickhandles\nstickhandling\nstickier\nstickiest\nstickily\nstickiness\nstickinesses\nsticking\nstickit\nstickle\nstickleback\nsticklebacks\nstickled\nstickler\nsticklers\nstickles\nsticklike\nstickling\nstickman\nstickmen\nstickout\nstickouts\nstickpin\nstickpins\nsticks\nstickseed\nstickseeds\nsticktight\nsticktights\nstickum\nstickums\nstickup\nstickups\nstickweed\nstickweeds\nstickwork\nstickworks\nsticky\nstiction\nstictions\nstied\nsties\nstiff\nstiffed\nstiffen\nstiffened\nstiffener\nstiffeners\nstiffening\nstiffens\nstiffer\nstiffest\nstiffing\nstiffish\nstiffly\nstiffness\nstiffnesses\nstiffs\nstifle\nstifled\nstifler\nstiflers\nstifles\nstifling\nstiflingly\nstigma\nstigmal\nstigmas\nstigmasterol\nstigmasterols\nstigmata\nstigmatic\nstigmatically\nstigmatics\nstigmatist\nstigmatists\nstigmatization\nstigmatizations\nstigmatize\nstigmatized\nstigmatizes\nstigmatizing\nstilbene\nstilbenes\nstilbestrol\nstilbestrols\nstilbite\nstilbites\nstile\nstiles\nstiletto\nstilettoed\nstilettoes\nstilettoing\nstilettos\nstill\nstillbirth\nstillbirths\nstillborn\nstillborns\nstilled\nstiller\nstillest\nstillier\nstilliest\nstilling\nstillman\nstillmen\nstillness\nstillnesses\nstillroom\nstillrooms\nstills\nstilly\nstilt\nstilted\nstiltedly\nstiltedness\nstiltednesses\nstilting\nstilts\nstime\nstimes\nstimied\nstimies\nstimulant\nstimulants\nstimulate\nstimulated\nstimulates\nstimulating\nstimulation\nstimulations\nstimulative\nstimulator\nstimulators\nstimulatory\nstimuli\nstimulus\nstimy\nstimying\nsting\nstingaree\nstingarees\nstinger\nstingers\nstingier\nstingiest\nstingily\nstinginess\nstinginesses\nstinging\nstingingly\nstingless\nstingo\nstingos\nstingray\nstingrays\nstings\nstingy\nstink\nstinkard\nstinkards\nstinkbug\nstinkbugs\nstinker\nstinkers\nstinkhorn\nstinkhorns\nstinkier\nstinkiest\nstinking\nstinkingly\nstinko\nstinkpot\nstinkpots\nstinks\nstinkweed\nstinkweeds\nstinkwood\nstinkwoods\nstinky\nstint\nstinted\nstinter\nstinters\nstinting\nstints\nstipe\nstiped\nstipel\nstipels\nstipend\nstipendiaries\nstipendiary\nstipends\nstipes\nstipites\nstipple\nstippled\nstippler\nstipplers\nstipples\nstippling\nstipular\nstipulate\nstipulated\nstipulates\nstipulating\nstipulation\nstipulations\nstipulator\nstipulators\nstipulatory\nstipule\nstipuled\nstipules\nstir\nstirabout\nstirabouts\nstirk\nstirks\nstirp\nstirpes\nstirps\nstirred\nstirrer\nstirrers\nstirring\nstirringly\nstirrup\nstirrups\nstirs\nstitch\nstitched\nstitcher\nstitcheries\nstitchers\nstitchery\nstitches\nstitching\nstitchwort\nstitchworts\nstithied\nstithies\nstithy\nstithying\nstiver\nstivers\nstoa\nstoae\nstoai\nstoas\nstoat\nstoats\nstob\nstobbed\nstobbing\nstobs\nstoccado\nstoccados\nstoccata\nstoccatas\nstochastic\nstochastically\nstock\nstockade\nstockaded\nstockades\nstockading\nstockbreeder\nstockbreeders\nstockbroker\nstockbrokerage\nstockbrokerages\nstockbrokers\nstockbroking\nstockbrokings\nstockcar\nstockcars\nstocked\nstocker\nstockers\nstockfish\nstockfishes\nstockholder\nstockholders\nstockier\nstockiest\nstockily\nstockiness\nstockinesses\nstockinet\nstockinets\nstockinette\nstockinettes\nstocking\nstockinged\nstockings\nstockish\nstockist\nstockists\nstockjobber\nstockjobbers\nstockjobbing\nstockjobbings\nstockkeeper\nstockkeepers\nstockman\nstockmen\nstockpile\nstockpiled\nstockpiler\nstockpilers\nstockpiles\nstockpiling\nstockpot\nstockpots\nstockroom\nstockrooms\nstocks\nstocktaking\nstocktakings\nstocky\nstockyard\nstockyards\nstodge\nstodged\nstodges\nstodgier\nstodgiest\nstodgily\nstodginess\nstodginesses\nstodging\nstodgy\nstogey\nstogeys\nstogie\nstogies\nstogy\nstoic\nstoical\nstoically\nstoichiometric\nstoichiometrically\nstoichiometries\nstoichiometry\nstoicism\nstoicisms\nstoics\nstoke\nstoked\nstokehold\nstokeholds\nstoker\nstokers\nstokes\nstokesia\nstokesias\nstoking\nstole\nstoled\nstolen\nstoles\nstolid\nstolider\nstolidest\nstolidities\nstolidity\nstolidly\nstollen\nstollens\nstolon\nstolonic\nstoloniferous\nstolons\nstolport\nstolports\nstoma\nstomach\nstomachache\nstomachaches\nstomached\nstomacher\nstomachers\nstomachic\nstomachics\nstomaching\nstomachs\nstomachy\nstomal\nstomas\nstomata\nstomatal\nstomate\nstomates\nstomatic\nstomatitides\nstomatitis\nstomatitises\nstomatopod\nstomatopods\nstomodaea\nstomodaeal\nstomodaeum\nstomodaeums\nstomodea\nstomodeal\nstomodeum\nstomodeums\nstomp\nstomped\nstomper\nstompers\nstomping\nstomps\nstonable\nstone\nstoneboat\nstoneboats\nstonechat\nstonechats\nstonecrop\nstonecrops\nstonecutter\nstonecutters\nstonecutting\nstonecuttings\nstoned\nstonefish\nstonefishes\nstoneflies\nstonefly\nstonemason\nstonemasonries\nstonemasonry\nstonemasons\nstoner\nstoners\nstones\nstonewall\nstonewalled\nstonewaller\nstonewallers\nstonewalling\nstonewalls\nstoneware\nstonewares\nstonewashed\nstonework\nstoneworks\nstonewort\nstoneworts\nstoney\nstonier\nstoniest\nstonily\nstoniness\nstoninesses\nstoning\nstonish\nstonished\nstonishes\nstonishing\nstony\nstonyhearted\nstood\nstooge\nstooged\nstooges\nstooging\nstook\nstooked\nstooker\nstookers\nstooking\nstooks\nstool\nstooled\nstoolie\nstoolies\nstooling\nstools\nstoop\nstoopball\nstoopballs\nstooped\nstooper\nstoopers\nstooping\nstoops\nstop\nstopbank\nstopbanks\nstopcock\nstopcocks\nstope\nstoped\nstoper\nstopers\nstopes\nstopgap\nstopgaps\nstoping\nstoplight\nstoplights\nstopover\nstopovers\nstoppable\nstoppage\nstoppages\nstopped\nstopper\nstoppered\nstoppering\nstoppers\nstopping\nstopple\nstoppled\nstopples\nstoppling\nstops\nstopt\nstopwatch\nstopwatches\nstorable\nstorables\nstorage\nstorages\nstorax\nstoraxes\nstore\nstored\nstorefront\nstorefronts\nstorehouse\nstorehouses\nstorekeeper\nstorekeepers\nstoreroom\nstorerooms\nstores\nstoreship\nstoreships\nstorewide\nstorey\nstoreyed\nstoreys\nstoried\nstories\nstoring\nstork\nstorks\nstorksbill\nstorksbills\nstorm\nstormbound\nstormed\nstormier\nstormiest\nstormily\nstorminess\nstorminesses\nstorming\nstorms\nstormy\nstory\nstoryboard\nstoryboarded\nstoryboarding\nstoryboards\nstorybook\nstorybooks\nstorying\nstoryteller\nstorytellers\nstorytelling\nstorytellings\nstoss\nstotin\nstotinka\nstotinki\nstotinov\nstound\nstounded\nstounding\nstounds\nstoup\nstoups\nstour\nstoure\nstoures\nstourie\nstours\nstoury\nstout\nstouten\nstoutened\nstoutening\nstoutens\nstouter\nstoutest\nstouthearted\nstoutheartedly\nstoutheartedness\nstoutheartednesses\nstoutish\nstoutly\nstoutness\nstoutnesses\nstouts\nstove\nstovepipe\nstovepipes\nstover\nstovers\nstoves\nstow\nstowable\nstowage\nstowages\nstowaway\nstowaways\nstowed\nstowing\nstowp\nstowps\nstows\nstrabismic\nstrabismus\nstrabismuses\nstraddle\nstraddled\nstraddler\nstraddlers\nstraddles\nstraddling\nstrafe\nstrafed\nstrafer\nstrafers\nstrafes\nstrafing\nstraggle\nstraggled\nstraggler\nstragglers\nstraggles\nstragglier\nstraggliest\nstraggling\nstraggly\nstraight\nstraightaway\nstraightaways\nstraightbred\nstraightbreds\nstraighted\nstraightedge\nstraightedges\nstraighten\nstraightened\nstraightener\nstraighteners\nstraightening\nstraightens\nstraighter\nstraightest\nstraightforward\nstraightforwardly\nstraightforwardness\nstraightforwardnesses\nstraightforwards\nstraighting\nstraightish\nstraightjacket\nstraightjacketed\nstraightjacketing\nstraightjackets\nstraightlaced\nstraightly\nstraightness\nstraightnesses\nstraights\nstraightway\nstrain\nstrained\nstrainer\nstrainers\nstraining\nstrains\nstrait\nstraiten\nstraitened\nstraitening\nstraitens\nstraiter\nstraitest\nstraitjacket\nstraitjacketed\nstraitjacketing\nstraitjackets\nstraitlaced\nstraitlacedly\nstraitlacedness\nstraitlacednesses\nstraitly\nstraitness\nstraitnesses\nstraits\nstrake\nstraked\nstrakes\nstramash\nstramashes\nstramonies\nstramonium\nstramoniums\nstramony\nstrand\nstranded\nstrandedness\nstrandednesses\nstrander\nstranders\nstranding\nstrandline\nstrandlines\nstrands\nstrang\nstrange\nstrangely\nstrangeness\nstrangenesses\nstranger\nstrangered\nstrangering\nstrangers\nstrangest\nstrangle\nstrangled\nstranglehold\nstrangleholds\nstrangler\nstranglers\nstrangles\nstrangling\nstrangulate\nstrangulated\nstrangulates\nstrangulating\nstrangulation\nstrangulations\nstranguries\nstrangury\nstrap\nstraphang\nstraphanger\nstraphangers\nstraphanging\nstraphangs\nstraphung\nstrapless\nstraplesses\nstrappado\nstrappadoes\nstrappados\nstrapped\nstrapper\nstrappers\nstrapping\nstrappings\nstraps\nstrass\nstrasses\nstrata\nstratagem\nstratagems\nstratal\nstratas\nstrategic\nstrategical\nstrategically\nstrategies\nstrategist\nstrategists\nstrategize\nstrategized\nstrategizes\nstrategizing\nstrategy\nstrath\nstraths\nstrathspey\nstrathspeys\nstrati\nstratification\nstratifications\nstratified\nstratifies\nstratiform\nstratify\nstratifying\nstratigraphic\nstratigraphies\nstratigraphy\nstratocracies\nstratocracy\nstratocumuli\nstratocumulus\nstratosphere\nstratospheres\nstratospheric\nstratous\nstratovolcano\nstratovolcanoes\nstratovolcanos\nstratum\nstratums\nstratus\nstravage\nstravaged\nstravages\nstravaging\nstravaig\nstravaiged\nstravaiging\nstravaigs\nstraw\nstrawberries\nstrawberry\nstrawed\nstrawflower\nstrawflowers\nstrawhat\nstrawier\nstrawiest\nstrawing\nstraws\nstrawy\nstray\nstrayed\nstrayer\nstrayers\nstraying\nstrays\nstreak\nstreaked\nstreaker\nstreakers\nstreakier\nstreakiest\nstreakiness\nstreakinesses\nstreaking\nstreakings\nstreaks\nstreaky\nstream\nstreambed\nstreambeds\nstreamed\nstreamer\nstreamers\nstreamier\nstreamiest\nstreaming\nstreamings\nstreamlet\nstreamlets\nstreamline\nstreamlined\nstreamliner\nstreamliners\nstreamlines\nstreamlining\nstreams\nstreamside\nstreamsides\nstreamy\nstreek\nstreeked\nstreeker\nstreekers\nstreeking\nstreeks\nstreel\nstreeled\nstreeling\nstreels\nstreet\nstreetcar\nstreetcars\nstreetlamp\nstreetlamps\nstreetlight\nstreetlights\nstreets\nstreetscape\nstreetscapes\nstreetwalker\nstreetwalkers\nstreetwalking\nstreetwalkings\nstreetwise\nstrength\nstrengthen\nstrengthened\nstrengthener\nstrengtheners\nstrengthening\nstrengthens\nstrengths\nstrenuosities\nstrenuosity\nstrenuous\nstrenuously\nstrenuousness\nstrenuousnesses\nstrep\nstreps\nstreptobacilli\nstreptobacillus\nstreptococcal\nstreptococci\nstreptococcic\nstreptococcus\nstreptokinase\nstreptokinases\nstreptolysin\nstreptolysins\nstreptomyces\nstreptomycete\nstreptomycetes\nstreptomycin\nstreptomycins\nstreptothricin\nstreptothricins\nstress\nstressed\nstresses\nstressful\nstressfully\nstressing\nstressless\nstresslessness\nstresslessnesses\nstressor\nstressors\nstretch\nstretchabilities\nstretchability\nstretchable\nstretched\nstretcher\nstretchers\nstretches\nstretchier\nstretchiest\nstretching\nstretchy\nstretta\nstrettas\nstrette\nstretti\nstretto\nstrettos\nstreusel\nstreusels\nstrew\nstrewed\nstrewer\nstrewers\nstrewing\nstrewment\nstrewments\nstrewn\nstrews\nstria\nstriae\nstriate\nstriated\nstriates\nstriating\nstriation\nstriations\nstrick\nstricken\nstrickle\nstrickled\nstrickles\nstrickling\nstricks\nstrict\nstricter\nstrictest\nstrictly\nstrictness\nstrictnesses\nstricture\nstrictures\nstridden\nstride\nstridence\nstridences\nstridencies\nstridency\nstrident\nstridently\nstrider\nstriders\nstrides\nstriding\nstridor\nstridors\nstridulate\nstridulated\nstridulates\nstridulating\nstridulation\nstridulations\nstridulatory\nstridulous\nstridulously\nstrife\nstrifeless\nstrifes\nstrigil\nstrigils\nstrigose\nstrike\nstrikebound\nstrikebreaker\nstrikebreakers\nstrikebreaking\nstrikebreakings\nstrikeout\nstrikeouts\nstrikeover\nstrikeovers\nstriker\nstrikers\nstrikes\nstriking\nstrikingly\nstring\nstringcourse\nstringcourses\nstringed\nstringencies\nstringency\nstringendo\nstringent\nstringently\nstringer\nstringers\nstringhalt\nstringhalted\nstringhalts\nstringier\nstringiest\nstringiness\nstringinesses\nstringing\nstringings\nstringless\nstringpiece\nstringpieces\nstrings\nstringy\nstringybark\nstringybarks\nstrip\nstripe\nstriped\nstripeless\nstriper\nstripers\nstripes\nstripier\nstripiest\nstriping\nstripings\nstripling\nstriplings\nstrippable\nstripped\nstripper\nstrippers\nstripping\nstrips\nstript\nstriptease\nstripteaser\nstripteasers\nstripteases\nstripy\nstrive\nstrived\nstriven\nstriver\nstrivers\nstrives\nstriving\nstrobe\nstrobes\nstrobic\nstrobil\nstrobila\nstrobilae\nstrobilation\nstrobilations\nstrobile\nstrobiles\nstrobili\nstrobils\nstrobilus\nstroboscope\nstroboscopes\nstroboscopic\nstroboscopically\nstrobotron\nstrobotrons\nstrode\nstroganoff\nstroke\nstroked\nstroker\nstrokers\nstrokes\nstroking\nstroll\nstrolled\nstroller\nstrollers\nstrolling\nstrolls\nstroma\nstromal\nstromata\nstromatolite\nstromatolites\nstromatolitic\nstrong\nstrongbox\nstrongboxes\nstronger\nstrongest\nstronghold\nstrongholds\nstrongish\nstrongly\nstrongman\nstrongmen\nstrongyl\nstrongyle\nstrongyles\nstrongyloidiases\nstrongyloidiasis\nstrongyloidoses\nstrongyloidosis\nstrongyls\nstrontia\nstrontianite\nstrontianites\nstrontias\nstrontic\nstrontium\nstrontiums\nstrook\nstrop\nstrophanthin\nstrophanthins\nstrophe\nstrophes\nstrophic\nstropped\nstropper\nstroppers\nstroppier\nstroppiest\nstropping\nstroppy\nstrops\nstroud\nstrouding\nstroudings\nstrouds\nstrove\nstrow\nstrowed\nstrowing\nstrown\nstrows\nstroy\nstroyed\nstroyer\nstroyers\nstroying\nstroys\nstruck\nstrucken\nstructural\nstructuralism\nstructuralisms\nstructuralist\nstructuralists\nstructuralization\nstructuralizations\nstructuralize\nstructuralized\nstructuralizes\nstructuralizing\nstructurally\nstructuration\nstructurations\nstructure\nstructured\nstructureless\nstructurelessness\nstructurelessnesses\nstructures\nstructuring\nstrudel\nstrudels\nstruggle\nstruggled\nstruggler\nstrugglers\nstruggles\nstruggling\nstrum\nstruma\nstrumae\nstrumas\nstrummed\nstrummer\nstrummers\nstrumming\nstrumose\nstrumous\nstrumpet\nstrumpets\nstrums\nstrung\nstrunt\nstrunted\nstrunting\nstrunts\nstrut\nstruthious\nstruts\nstrutted\nstrutter\nstrutters\nstrutting\nstrychnine\nstrychnines\nstub\nstubbed\nstubbier\nstubbiest\nstubbily\nstubbing\nstubble\nstubbled\nstubbles\nstubblier\nstubbliest\nstubbly\nstubborn\nstubborner\nstubbornest\nstubbornly\nstubbornness\nstubbornnesses\nstubby\nstubs\nstucco\nstuccoed\nstuccoer\nstuccoers\nstuccoes\nstuccoing\nstuccos\nstuccowork\nstuccoworks\nstuck\nstud\nstudbook\nstudbooks\nstudded\nstuddie\nstuddies\nstudding\nstuddings\nstudent\nstudents\nstudentship\nstudentships\nstudfish\nstudfishes\nstudhorse\nstudhorses\nstudied\nstudiedly\nstudiedness\nstudiednesses\nstudier\nstudiers\nstudies\nstudio\nstudios\nstudious\nstudiously\nstudiousness\nstudiousnesses\nstudlier\nstudliest\nstudly\nstuds\nstudwork\nstudworks\nstudy\nstudying\nstuff\nstuffed\nstuffer\nstuffers\nstuffier\nstuffiest\nstuffily\nstuffiness\nstuffinesses\nstuffing\nstuffings\nstuffless\nstuffs\nstuffy\nstuiver\nstuivers\nstull\nstulls\nstultification\nstultifications\nstultified\nstultifies\nstultify\nstultifying\nstum\nstumble\nstumblebum\nstumblebums\nstumbled\nstumbler\nstumblers\nstumbles\nstumbling\nstumblingly\nstummed\nstumming\nstump\nstumpage\nstumpages\nstumped\nstumper\nstumpers\nstumpier\nstumpiest\nstumping\nstumps\nstumpy\nstums\nstun\nstung\nstunk\nstunned\nstunner\nstunners\nstunning\nstunningly\nstuns\nstunsail\nstunsails\nstunt\nstunted\nstuntedness\nstuntednesses\nstunting\nstuntman\nstuntmen\nstunts\nstuntwoman\nstuntwomen\nstupa\nstupas\nstupe\nstupefaction\nstupefactions\nstupefied\nstupefies\nstupefy\nstupefying\nstupefyingly\nstupendous\nstupendously\nstupendousness\nstupendousnesses\nstupes\nstupid\nstupider\nstupidest\nstupidities\nstupidity\nstupidly\nstupidness\nstupidnesses\nstupids\nstupor\nstuporous\nstupors\nsturdied\nsturdier\nsturdies\nsturdiest\nsturdily\nsturdiness\nsturdinesses\nsturdy\nsturgeon\nsturgeons\nsturt\nsturts\nstutter\nstuttered\nstutterer\nstutterers\nstuttering\nstutters\nsty\nstye\nstyed\nstyes\nstygian\nstying\nstylar\nstylate\nstyle\nstylebook\nstylebooks\nstyled\nstyleless\nstylelessness\nstylelessnesses\nstyler\nstylers\nstyles\nstylet\nstylets\nstyli\nstyliform\nstyling\nstylings\nstylise\nstylised\nstyliser\nstylisers\nstylises\nstylish\nstylishly\nstylishness\nstylishnesses\nstylising\nstylist\nstylistic\nstylistically\nstylistics\nstylists\nstylite\nstylites\nstylitic\nstylization\nstylizations\nstylize\nstylized\nstylizer\nstylizers\nstylizes\nstylizing\nstylobate\nstylobates\nstylographies\nstylography\nstyloid\nstylopodia\nstylopodium\nstylus\nstyluses\nstymie\nstymied\nstymieing\nstymies\nstymy\nstymying\nstypsis\nstypsises\nstyptic\nstyptics\nstyrax\nstyraxes\nstyrene\nstyrenes\nsuabilities\nsuability\nsuable\nsuably\nsuasion\nsuasions\nsuasive\nsuasively\nsuasiveness\nsuasivenesses\nsuasory\nsuave\nsuavely\nsuaveness\nsuavenesses\nsuaver\nsuavest\nsuavities\nsuavity\nsub\nsuba\nsubabbot\nsubabbots\nsubacid\nsubacidly\nsubacidness\nsubacidnesses\nsubacrid\nsubacute\nsubacutely\nsubadar\nsubadars\nsubadolescent\nsubadolescents\nsubadult\nsubadults\nsubaerial\nsubaerially\nsubagencies\nsubagency\nsubagent\nsubagents\nsubah\nsubahdar\nsubahdars\nsubahs\nsubalar\nsuballocation\nsuballocations\nsubalpine\nsubaltern\nsubalterns\nsubantarctic\nsubapical\nsubaquatic\nsubaqueous\nsubarachnoid\nsubarachnoidal\nsubarctic\nsubarctics\nsubarea\nsubareas\nsubarid\nsubas\nsubassemblies\nsubassembly\nsubatmospheric\nsubatom\nsubatomic\nsubatoms\nsubaudible\nsubaudibly\nsubaudition\nsubauditions\nsubaverage\nsubaxial\nsubbase\nsubbasement\nsubbasements\nsubbases\nsubbasin\nsubbasins\nsubbass\nsubbasses\nsubbed\nsubbing\nsubbings\nsubbituminous\nsubblock\nsubblocks\nsubbranch\nsubbranches\nsubbreed\nsubbreeds\nsubcabinet\nsubcapsular\nsubcaste\nsubcastes\nsubcategories\nsubcategorization\nsubcategorizations\nsubcategorize\nsubcategorized\nsubcategorizes\nsubcategorizing\nsubcategory\nsubcause\nsubcauses\nsubceiling\nsubceilings\nsubcell\nsubcellar\nsubcellars\nsubcells\nsubcellular\nsubcenter\nsubcenters\nsubcentral\nsubcentrally\nsubchapter\nsubchapters\nsubchaser\nsubchasers\nsubchief\nsubchiefs\nsubclan\nsubclans\nsubclass\nsubclassed\nsubclasses\nsubclassification\nsubclassifications\nsubclassified\nsubclassifies\nsubclassify\nsubclassifying\nsubclassing\nsubclavian\nsubclavians\nsubclerk\nsubclerks\nsubclimax\nsubclimaxes\nsubclinical\nsubclinically\nsubcluster\nsubclusters\nsubcode\nsubcodes\nsubcollection\nsubcollections\nsubcollege\nsubcolleges\nsubcollegiate\nsubcolonies\nsubcolony\nsubcommission\nsubcommissions\nsubcommittee\nsubcommittees\nsubcommunities\nsubcommunity\nsubcompact\nsubcompacts\nsubcomponent\nsubcomponents\nsubconscious\nsubconsciouses\nsubconsciously\nsubconsciousness\nsubconsciousnesses\nsubcontinent\nsubcontinental\nsubcontinents\nsubcontract\nsubcontracted\nsubcontracting\nsubcontractor\nsubcontractors\nsubcontracts\nsubcontraoctave\nsubcontraoctaves\nsubcontraries\nsubcontrary\nsubcool\nsubcooled\nsubcooling\nsubcools\nsubcordate\nsubcoriaceous\nsubcortical\nsubcounties\nsubcounty\nsubcritical\nsubcrustal\nsubcult\nsubcults\nsubcultural\nsubculturally\nsubculture\nsubcultured\nsubcultures\nsubculturing\nsubcurative\nsubcuratives\nsubcutaneous\nsubcutaneously\nsubcutes\nsubcutis\nsubcutises\nsubdeacon\nsubdeacons\nsubdean\nsubdeans\nsubdeb\nsubdebs\nsubdebutante\nsubdebutantes\nsubdecision\nsubdecisions\nsubdepartment\nsubdepartments\nsubdepot\nsubdepots\nsubdermal\nsubdermally\nsubdevelopment\nsubdevelopments\nsubdialect\nsubdialects\nsubdirector\nsubdirectors\nsubdiscipline\nsubdisciplines\nsubdistrict\nsubdistricted\nsubdistricting\nsubdistricts\nsubdividable\nsubdivide\nsubdivided\nsubdivider\nsubdividers\nsubdivides\nsubdividing\nsubdivision\nsubdivisions\nsubdominant\nsubdominants\nsubdual\nsubduals\nsubduce\nsubduced\nsubduces\nsubducing\nsubduct\nsubducted\nsubducting\nsubduction\nsubductions\nsubducts\nsubdue\nsubdued\nsubduedly\nsubduer\nsubduers\nsubdues\nsubduing\nsubdural\nsubecho\nsubechoes\nsubeconomies\nsubeconomy\nsubedit\nsubedited\nsubediting\nsubeditor\nsubeditorial\nsubeditors\nsubedits\nsubemployed\nsubemployment\nsubemployments\nsubentries\nsubentry\nsubepidermal\nsubepoch\nsubepochs\nsuber\nsuberect\nsuberic\nsuberin\nsuberins\nsuberise\nsuberised\nsuberises\nsuberising\nsuberization\nsuberizations\nsuberize\nsuberized\nsuberizes\nsuberizing\nsuberose\nsuberous\nsubers\nsubfamilies\nsubfamily\nsubfield\nsubfields\nsubfile\nsubfiles\nsubfix\nsubfixes\nsubfloor\nsubfloors\nsubfluid\nsubfossil\nsubfossils\nsubframe\nsubframes\nsubfreezing\nsubfusc\nsubgenera\nsubgeneration\nsubgenerations\nsubgenre\nsubgenres\nsubgenus\nsubgenuses\nsubglacial\nsubglacially\nsubgoal\nsubgoals\nsubgovernment\nsubgovernments\nsubgrade\nsubgrades\nsubgraph\nsubgraphs\nsubgroup\nsubgroups\nsubgum\nsubgums\nsubhead\nsubheading\nsubheadings\nsubheads\nsubhuman\nsubhumans\nsubhumid\nsubidea\nsubideas\nsubindex\nsubindexes\nsubindices\nsubindustries\nsubindustry\nsubinfeudate\nsubinfeudated\nsubinfeudates\nsubinfeudating\nsubinfeudation\nsubinfeudations\nsubinhibitory\nsubinterval\nsubintervals\nsubirrigate\nsubirrigated\nsubirrigates\nsubirrigating\nsubirrigation\nsubirrigations\nsubitem\nsubitems\nsubito\nsubjacencies\nsubjacency\nsubjacent\nsubjacently\nsubject\nsubjected\nsubjecting\nsubjection\nsubjections\nsubjective\nsubjectively\nsubjectiveness\nsubjectivenesses\nsubjectives\nsubjectivise\nsubjectivised\nsubjectivises\nsubjectivising\nsubjectivism\nsubjectivisms\nsubjectivist\nsubjectivistic\nsubjectivists\nsubjectivities\nsubjectivity\nsubjectivization\nsubjectivizations\nsubjectivize\nsubjectivized\nsubjectivizes\nsubjectivizing\nsubjectless\nsubjects\nsubjoin\nsubjoined\nsubjoining\nsubjoins\nsubjugate\nsubjugated\nsubjugates\nsubjugating\nsubjugation\nsubjugations\nsubjugator\nsubjugators\nsubjunction\nsubjunctions\nsubjunctive\nsubjunctives\nsubkingdom\nsubkingdoms\nsublanguage\nsublanguages\nsublate\nsublated\nsublates\nsublating\nsublation\nsublations\nsublease\nsubleased\nsubleases\nsubleasing\nsublet\nsublethal\nsublethally\nsublets\nsubletting\nsublevel\nsublevels\nsublibrarian\nsublibrarians\nsublicense\nsublicensed\nsublicenses\nsublicensing\nsublieutenant\nsublieutenants\nsublimable\nsublimate\nsublimated\nsublimates\nsublimating\nsublimation\nsublimations\nsublime\nsublimed\nsublimely\nsublimeness\nsublimenesses\nsublimer\nsublimers\nsublimes\nsublimest\nsubliminal\nsubliminally\nsubliming\nsublimities\nsublimity\nsubline\nsublines\nsublingual\nsubliteracies\nsubliteracy\nsubliterary\nsubliterate\nsubliterature\nsubliteratures\nsublittoral\nsublittorals\nsublot\nsublots\nsublunar\nsublunary\nsubluxation\nsubluxations\nsubmanager\nsubmanagers\nsubmandibular\nsubmandibulars\nsubmarginal\nsubmarine\nsubmarined\nsubmariner\nsubmariners\nsubmarines\nsubmarining\nsubmarket\nsubmarkets\nsubmaxillaries\nsubmaxillary\nsubmaximal\nsubmediant\nsubmediants\nsubmenu\nsubmenus\nsubmerge\nsubmerged\nsubmergence\nsubmergences\nsubmerges\nsubmergible\nsubmerging\nsubmerse\nsubmersed\nsubmerses\nsubmersible\nsubmersibles\nsubmersing\nsubmersion\nsubmersions\nsubmetacentric\nsubmetacentrics\nsubmicrogram\nsubmicron\nsubmicroscopic\nsubmicroscopically\nsubmillimeter\nsubminiature\nsubminimal\nsubminister\nsubministers\nsubmiss\nsubmission\nsubmissions\nsubmissive\nsubmissively\nsubmissiveness\nsubmissivenesses\nsubmit\nsubmitochondrial\nsubmits\nsubmittal\nsubmittals\nsubmitted\nsubmitting\nsubmucosa\nsubmucosae\nsubmucosal\nsubmucosas\nsubmultiple\nsubmultiples\nsubmunition\nsubmunitions\nsubnasal\nsubnational\nsubnet\nsubnets\nsubnetwork\nsubnetworks\nsubniche\nsubniches\nsubnodal\nsubnormal\nsubnormalities\nsubnormality\nsubnormally\nsubnuclear\nsuboceanic\nsuboptic\nsuboptimal\nsuboptimization\nsuboptimizations\nsuboptimize\nsuboptimized\nsuboptimizes\nsuboptimizing\nsuboptimum\nsuboral\nsuborbicular\nsuborbital\nsuborder\nsuborders\nsubordinate\nsubordinated\nsubordinately\nsubordinateness\nsubordinatenesses\nsubordinates\nsubordinating\nsubordination\nsubordinations\nsubordinative\nsubordinator\nsubordinators\nsuborganization\nsuborganizations\nsuborn\nsubornation\nsubornations\nsuborned\nsuborner\nsuborners\nsuborning\nsuborns\nsuboval\nsubovate\nsuboxide\nsuboxides\nsubpanel\nsubpanels\nsubpar\nsubparagraph\nsubparagraphs\nsubparallel\nsubpart\nsubparts\nsubpena\nsubpenaed\nsubpenaing\nsubpenas\nsubperiod\nsubperiods\nsubphase\nsubphases\nsubphyla\nsubphylum\nsubplot\nsubplots\nsubpoena\nsubpoenaed\nsubpoenaing\nsubpoenas\nsubpolar\nsubpopulation\nsubpopulations\nsubpotencies\nsubpotency\nsubpotent\nsubprimate\nsubprimates\nsubprincipal\nsubprincipals\nsubproblem\nsubproblems\nsubprocess\nsubprocesses\nsubproduct\nsubproducts\nsubprofessional\nsubprofessionals\nsubprogram\nsubprograms\nsubproject\nsubprojects\nsubproletariat\nsubproletariats\nsubpubic\nsubrace\nsubraces\nsubrational\nsubregion\nsubregional\nsubregions\nsubrent\nsubrents\nsubreption\nsubreptions\nsubreptitious\nsubreptitiously\nsubring\nsubrings\nsubrogate\nsubrogated\nsubrogates\nsubrogating\nsubrogation\nsubrogations\nsubroutine\nsubroutines\nsubrule\nsubrules\nsubs\nsubsale\nsubsales\nsubsample\nsubsampled\nsubsamples\nsubsampling\nsubsatellite\nsubsatellites\nsubsaturated\nsubsaturation\nsubsaturations\nsubscale\nsubscales\nsubscience\nsubsciences\nsubscribe\nsubscribed\nsubscriber\nsubscribers\nsubscribes\nsubscribing\nsubscript\nsubscription\nsubscriptions\nsubscripts\nsubsea\nsubsecretaries\nsubsecretary\nsubsect\nsubsection\nsubsections\nsubsector\nsubsectors\nsubsects\nsubsegment\nsubsegments\nsubseizure\nsubseizures\nsubsense\nsubsenses\nsubsentence\nsubsentences\nsubsequence\nsubsequences\nsubsequent\nsubsequently\nsubsequents\nsubsere\nsubseres\nsubseries\nsubserve\nsubserved\nsubserves\nsubservience\nsubserviences\nsubserviencies\nsubserviency\nsubservient\nsubserviently\nsubserving\nsubset\nsubsets\nsubshaft\nsubshafts\nsubshell\nsubshells\nsubshrub\nsubshrubs\nsubside\nsubsided\nsubsidence\nsubsidences\nsubsider\nsubsiders\nsubsides\nsubsidiaries\nsubsidiarily\nsubsidiarities\nsubsidiarity\nsubsidiary\nsubsidies\nsubsiding\nsubsidise\nsubsidised\nsubsidises\nsubsidising\nsubsidization\nsubsidizations\nsubsidize\nsubsidized\nsubsidizer\nsubsidizers\nsubsidizes\nsubsidizing\nsubsidy\nsubsist\nsubsisted\nsubsistence\nsubsistences\nsubsistent\nsubsisting\nsubsists\nsubsite\nsubsites\nsubskill\nsubskills\nsubsocial\nsubsocieties\nsubsociety\nsubsoil\nsubsoiled\nsubsoiler\nsubsoilers\nsubsoiling\nsubsoils\nsubsolar\nsubsonic\nsubsonically\nsubspace\nsubspaces\nsubspecialist\nsubspecialists\nsubspecialize\nsubspecialized\nsubspecializes\nsubspecializing\nsubspecialties\nsubspecialty\nsubspecies\nsubspecific\nsubstage\nsubstages\nsubstance\nsubstanceless\nsubstances\nsubstandard\nsubstantial\nsubstantialities\nsubstantiality\nsubstantially\nsubstantialness\nsubstantialnesses\nsubstantials\nsubstantiate\nsubstantiated\nsubstantiates\nsubstantiating\nsubstantiation\nsubstantiations\nsubstantiative\nsubstantival\nsubstantivally\nsubstantive\nsubstantively\nsubstantiveness\nsubstantivenesses\nsubstantives\nsubstantivize\nsubstantivized\nsubstantivizes\nsubstantivizing\nsubstate\nsubstates\nsubstation\nsubstations\nsubstituent\nsubstituents\nsubstitutabilities\nsubstitutability\nsubstitutable\nsubstitute\nsubstituted\nsubstitutes\nsubstituting\nsubstitution\nsubstitutional\nsubstitutionally\nsubstitutionary\nsubstitutions\nsubstitutive\nsubstitutively\nsubstrata\nsubstrate\nsubstrates\nsubstratum\nsubstratums\nsubstructural\nsubstructure\nsubstructures\nsubsumable\nsubsume\nsubsumed\nsubsumes\nsubsuming\nsubsumption\nsubsumptions\nsubsurface\nsubsurfaces\nsubsystem\nsubsystems\nsubtask\nsubtasks\nsubtaxa\nsubtaxon\nsubtaxons\nsubteen\nsubteens\nsubtemperate\nsubtenancies\nsubtenancy\nsubtenant\nsubtenants\nsubtend\nsubtended\nsubtending\nsubtends\nsubterfuge\nsubterfuges\nsubterminal\nsubterranean\nsubterraneanly\nsubterraneous\nsubterraneously\nsubtest\nsubtests\nsubtext\nsubtexts\nsubtextual\nsubtheme\nsubthemes\nsubtherapeutic\nsubthreshold\nsubtile\nsubtilely\nsubtileness\nsubtilenesses\nsubtiler\nsubtilest\nsubtilin\nsubtilins\nsubtilisin\nsubtilisins\nsubtilization\nsubtilizations\nsubtilize\nsubtilized\nsubtilizes\nsubtilizing\nsubtilties\nsubtilty\nsubtitle\nsubtitled\nsubtitles\nsubtitling\nsubtle\nsubtleness\nsubtlenesses\nsubtler\nsubtlest\nsubtleties\nsubtlety\nsubtly\nsubtone\nsubtones\nsubtonic\nsubtonics\nsubtopia\nsubtopias\nsubtopic\nsubtopics\nsubtotal\nsubtotaled\nsubtotaling\nsubtotalled\nsubtotalling\nsubtotally\nsubtotals\nsubtract\nsubtracted\nsubtracter\nsubtracters\nsubtracting\nsubtraction\nsubtractions\nsubtractive\nsubtracts\nsubtrahend\nsubtrahends\nsubtreasuries\nsubtreasury\nsubtrend\nsubtrends\nsubtribe\nsubtribes\nsubtropic\nsubtropical\nsubtropics\nsubtunic\nsubtunics\nsubtype\nsubtypes\nsubulate\nsubumbrella\nsubumbrellas\nsubunit\nsubunits\nsuburb\nsuburban\nsuburbanise\nsuburbanised\nsuburbanises\nsuburbanising\nsuburbanite\nsuburbanites\nsuburbanization\nsuburbanizations\nsuburbanize\nsuburbanized\nsuburbanizes\nsuburbanizing\nsuburbans\nsuburbed\nsuburbia\nsuburbias\nsuburbs\nsubvarieties\nsubvariety\nsubvassal\nsubvassals\nsubvene\nsubvened\nsubvenes\nsubvening\nsubvention\nsubventionary\nsubventions\nsubversion\nsubversionary\nsubversions\nsubversive\nsubversively\nsubversiveness\nsubversivenesses\nsubversives\nsubvert\nsubverted\nsubverter\nsubverters\nsubverting\nsubverts\nsubvicar\nsubvicars\nsubviral\nsubvisible\nsubvisual\nsubvocal\nsubvocalization\nsubvocalizations\nsubvocalize\nsubvocalized\nsubvocalizes\nsubvocalizing\nsubvocally\nsubway\nsubwayed\nsubwaying\nsubways\nsubworld\nsubworlds\nsubwriter\nsubwriters\nsubzero\nsubzone\nsubzones\nsuccah\nsuccahs\nsuccedanea\nsuccedaneous\nsuccedaneum\nsuccedaneums\nsuccedent\nsucceed\nsucceeded\nsucceeder\nsucceeders\nsucceeding\nsucceeds\nsuccess\nsuccesses\nsuccessful\nsuccessfully\nsuccessfulness\nsuccessfulnesses\nsuccession\nsuccessional\nsuccessionally\nsuccessions\nsuccessive\nsuccessively\nsuccessiveness\nsuccessivenesses\nsuccessor\nsuccessors\nsuccinate\nsuccinates\nsuccinct\nsuccincter\nsuccinctest\nsuccinctly\nsuccinctness\nsuccinctnesses\nsuccinic\nsuccinyl\nsuccinylcholine\nsuccinylcholines\nsuccinyls\nsuccor\nsuccored\nsuccorer\nsuccorers\nsuccories\nsuccoring\nsuccors\nsuccory\nsuccotash\nsuccotashes\nsuccoth\nsuccour\nsuccoured\nsuccouring\nsuccours\nsuccuba\nsuccubae\nsuccubas\nsuccubi\nsuccubus\nsuccubuses\nsucculence\nsucculences\nsucculent\nsucculently\nsucculents\nsuccumb\nsuccumbed\nsuccumbing\nsuccumbs\nsuccuss\nsuccussed\nsuccusses\nsuccussing\nsuch\nsuchlike\nsuchness\nsuchnesses\nsuck\nsucked\nsucker\nsuckered\nsuckering\nsuckers\nsuckfish\nsuckfishes\nsucking\nsuckle\nsuckled\nsuckler\nsucklers\nsuckles\nsuckless\nsuckling\nsucklings\nsucks\nsucrase\nsucrases\nsucre\nsucres\nsucrose\nsucroses\nsuction\nsuctional\nsuctioned\nsuctioning\nsuctions\nsuctorial\nsuctorian\nsuctorians\nsudaria\nsudaries\nsudarium\nsudary\nsudation\nsudations\nsudatoria\nsudatories\nsudatorium\nsudatoriums\nsudatory\nsudd\nsudden\nsuddenly\nsuddenness\nsuddennesses\nsuddens\nsudds\nsudor\nsudoral\nsudoriferous\nsudorific\nsudorifics\nsudors\nsuds\nsudsed\nsudser\nsudsers\nsudses\nsudsier\nsudsiest\nsudsing\nsudsless\nsudsy\nsue\nsued\nsuede\nsueded\nsuedes\nsueding\nsuer\nsuers\nsues\nsuet\nsuets\nsuety\nsuffari\nsuffaris\nsuffer\nsufferable\nsufferableness\nsufferablenesses\nsufferably\nsufferance\nsufferances\nsuffered\nsufferer\nsufferers\nsuffering\nsufferings\nsuffers\nsuffice\nsufficed\nsufficer\nsufficers\nsuffices\nsufficiencies\nsufficiency\nsufficient\nsufficiently\nsufficing\nsuffix\nsuffixal\nsuffixation\nsuffixations\nsuffixed\nsuffixes\nsuffixing\nsufflate\nsufflated\nsufflates\nsufflating\nsuffocate\nsuffocated\nsuffocates\nsuffocating\nsuffocatingly\nsuffocation\nsuffocations\nsuffocative\nsuffragan\nsuffragans\nsuffrage\nsuffrages\nsuffragette\nsuffragettes\nsuffragist\nsuffragists\nsuffuse\nsuffused\nsuffuses\nsuffusing\nsuffusion\nsuffusions\nsuffusive\nsugar\nsugarberries\nsugarberry\nsugarcane\nsugarcanes\nsugarcoat\nsugarcoated\nsugarcoating\nsugarcoats\nsugared\nsugarhouse\nsugarhouses\nsugarier\nsugariest\nsugaring\nsugarless\nsugarloaf\nsugarloaves\nsugarplum\nsugarplums\nsugars\nsugary\nsuggest\nsuggested\nsuggester\nsuggesters\nsuggestibilities\nsuggestibility\nsuggestible\nsuggesting\nsuggestion\nsuggestions\nsuggestive\nsuggestively\nsuggestiveness\nsuggestivenesses\nsuggests\nsugh\nsughed\nsughing\nsughs\nsuicidal\nsuicidally\nsuicide\nsuicided\nsuicides\nsuiciding\nsuing\nsuint\nsuints\nsuit\nsuitabilities\nsuitability\nsuitable\nsuitableness\nsuitablenesses\nsuitably\nsuitcase\nsuitcases\nsuite\nsuited\nsuiter\nsuiters\nsuites\nsuiting\nsuitings\nsuitlike\nsuitor\nsuitors\nsuits\nsukiyaki\nsukiyakis\nsukkah\nsukkahs\nsukkot\nsukkoth\nsulcal\nsulcate\nsulcated\nsulci\nsulcus\nsuldan\nsuldans\nsulfa\nsulfadiazine\nsulfadiazines\nsulfanilamide\nsulfanilamides\nsulfas\nsulfatase\nsulfatases\nsulfate\nsulfated\nsulfates\nsulfating\nsulfhydryl\nsulfhydryls\nsulfid\nsulfide\nsulfides\nsulfids\nsulfinpyrazone\nsulfinpyrazones\nsulfinyl\nsulfinyls\nsulfite\nsulfites\nsulfitic\nsulfo\nsulfonamide\nsulfonamides\nsulfonate\nsulfonated\nsulfonates\nsulfonating\nsulfonation\nsulfonations\nsulfone\nsulfones\nsulfonic\nsulfonium\nsulfoniums\nsulfonyl\nsulfonyls\nsulfonylurea\nsulfonylureas\nsulfoxide\nsulfoxides\nsulfur\nsulfured\nsulfuret\nsulfureted\nsulfureting\nsulfurets\nsulfuretted\nsulfuretting\nsulfuric\nsulfuring\nsulfurize\nsulfurized\nsulfurizes\nsulfurizing\nsulfurous\nsulfurously\nsulfurousness\nsulfurousnesses\nsulfurs\nsulfury\nsulfuryl\nsulfuryls\nsulk\nsulked\nsulker\nsulkers\nsulkier\nsulkies\nsulkiest\nsulkily\nsulkiness\nsulkinesses\nsulking\nsulks\nsulky\nsullage\nsullages\nsullen\nsullener\nsullenest\nsullenly\nsullenness\nsullennesses\nsullied\nsullies\nsully\nsullying\nsulpha\nsulphas\nsulphate\nsulphated\nsulphates\nsulphating\nsulphid\nsulphide\nsulphides\nsulphids\nsulphite\nsulphites\nsulphone\nsulphones\nsulphur\nsulphured\nsulphureous\nsulphuring\nsulphurise\nsulphurised\nsulphurises\nsulphurising\nsulphurous\nsulphurs\nsulphury\nsultan\nsultana\nsultanas\nsultanate\nsultanates\nsultaness\nsultanesses\nsultanic\nsultans\nsultrier\nsultriest\nsultrily\nsultriness\nsultrinesses\nsultry\nsulu\nsulus\nsum\nsumac\nsumach\nsumachs\nsumacs\nsumless\nsumma\nsummabilities\nsummability\nsummable\nsummae\nsummand\nsummands\nsummaries\nsummarily\nsummarise\nsummarised\nsummarises\nsummarising\nsummarizable\nsummarization\nsummarizations\nsummarize\nsummarized\nsummarizer\nsummarizers\nsummarizes\nsummarizing\nsummary\nsummas\nsummate\nsummated\nsummates\nsummating\nsummation\nsummational\nsummations\nsummative\nsummed\nsummer\nsummered\nsummerhouse\nsummerhouses\nsummerier\nsummeriest\nsummering\nsummerlike\nsummerlong\nsummerly\nsummers\nsummersault\nsummersaulted\nsummersaulting\nsummersaults\nsummertime\nsummertimes\nsummerwood\nsummerwoods\nsummery\nsumming\nsummit\nsummital\nsummited\nsummiteer\nsummiteers\nsummiting\nsummitries\nsummitry\nsummits\nsummon\nsummonable\nsummoned\nsummoner\nsummoners\nsummoning\nsummons\nsummonsed\nsummonses\nsummonsing\nsumo\nsumos\nsump\nsumps\nsumpter\nsumpters\nsumptuary\nsumptuous\nsumptuously\nsumptuousness\nsumptuousnesses\nsumpweed\nsumpweeds\nsums\nsun\nsunback\nsunbaked\nsunbath\nsunbathe\nsunbathed\nsunbather\nsunbathers\nsunbathes\nsunbathing\nsunbaths\nsunbeam\nsunbeams\nsunbeamy\nsunbelt\nsunbelts\nsunbird\nsunbirds\nsunblock\nsunblocks\nsunbonnet\nsunbonnets\nsunbow\nsunbows\nsunburn\nsunburned\nsunburning\nsunburns\nsunburnt\nsunburst\nsunbursts\nsunchoke\nsunchokes\nsundae\nsundaes\nsundeck\nsundecks\nsunder\nsundered\nsunderer\nsunderers\nsundering\nsunders\nsundew\nsundews\nsundial\nsundials\nsundog\nsundogs\nsundown\nsundowner\nsundowners\nsundowns\nsundress\nsundresses\nsundries\nsundrops\nsundry\nsunfast\nsunfish\nsunfishes\nsunflower\nsunflowers\nsung\nsunglass\nsunglasses\nsunglow\nsunglows\nsunk\nsunken\nsunket\nsunkets\nsunlamp\nsunlamps\nsunland\nsunlands\nsunless\nsunlight\nsunlights\nsunlike\nsunlit\nsunn\nsunna\nsunnah\nsunnahs\nsunnas\nsunned\nsunnier\nsunniest\nsunnily\nsunniness\nsunninesses\nsunning\nsunns\nsunny\nsunporch\nsunporches\nsunproof\nsunrise\nsunrises\nsunroof\nsunroofs\nsunroom\nsunrooms\nsuns\nsunscald\nsunscalds\nsunscreen\nsunscreening\nsunscreens\nsunseeker\nsunseekers\nsunset\nsunsets\nsunshade\nsunshades\nsunshine\nsunshines\nsunshiny\nsunspot\nsunspots\nsunstone\nsunstones\nsunstroke\nsunstrokes\nsunstruck\nsunsuit\nsunsuits\nsuntan\nsuntanned\nsuntans\nsunup\nsunups\nsunward\nsunwards\nsunwise\nsup\nsupe\nsuper\nsuperable\nsuperableness\nsuperablenesses\nsuperably\nsuperabound\nsuperabounded\nsuperabounding\nsuperabounds\nsuperabsorbent\nsuperabsorbents\nsuperabundance\nsuperabundances\nsuperabundant\nsuperabundantly\nsuperachiever\nsuperachievers\nsuperactivities\nsuperactivity\nsuperadd\nsuperadded\nsuperadding\nsuperaddition\nsuperadditions\nsuperadds\nsuperadministrator\nsuperadministrators\nsuperagencies\nsuperagency\nsuperagent\nsuperagents\nsuperalloy\nsuperalloys\nsuperaltern\nsuperalterns\nsuperambitious\nsuperannuate\nsuperannuated\nsuperannuates\nsuperannuating\nsuperannuation\nsuperannuations\nsuperathlete\nsuperathletes\nsuperb\nsuperbad\nsuperbank\nsuperbanks\nsuperber\nsuperbest\nsuperbillionaire\nsuperbillionaires\nsuperbitch\nsuperbitches\nsuperblock\nsuperblocks\nsuperbly\nsuperbness\nsuperbnesses\nsuperboard\nsuperboards\nsuperbomb\nsuperbomber\nsuperbombers\nsuperbombs\nsuperbright\nsuperbureaucrat\nsuperbureaucrats\nsupercabinet\nsupercabinets\nsupercalender\nsupercalendered\nsupercalendering\nsupercalenders\nsupercar\nsupercargo\nsupercargoes\nsupercargos\nsupercarrier\nsupercarriers\nsupercars\nsupercautious\nsupercede\nsuperceded\nsupercedes\nsuperceding\nsupercenter\nsupercenters\nsupercharge\nsupercharged\nsupercharger\nsuperchargers\nsupercharges\nsupercharging\nsuperchic\nsuperchurch\nsuperchurches\nsuperciliary\nsupercilious\nsuperciliously\nsuperciliousness\nsuperciliousnesses\nsupercities\nsupercity\nsupercivilization\nsupercivilizations\nsupercivilized\nsuperclass\nsuperclasses\nsuperclean\nsuperclub\nsuperclubs\nsupercluster\nsuperclusters\nsupercoil\nsupercoiled\nsupercoiling\nsupercoils\nsupercollider\nsupercolliders\nsupercolossal\nsupercomfortable\nsupercompetitive\nsupercomputer\nsupercomputers\nsuperconduct\nsuperconducted\nsuperconducting\nsuperconductive\nsuperconductivities\nsuperconductivity\nsuperconductor\nsuperconductors\nsuperconducts\nsuperconfident\nsuperconglomerate\nsuperconglomerates\nsuperconservative\nsupercontinent\nsupercontinents\nsuperconvenient\nsupercool\nsupercooled\nsupercooling\nsupercools\nsupercop\nsupercops\nsupercorporation\nsupercorporations\nsupercriminal\nsupercriminals\nsupercritical\nsupercurrent\nsupercurrents\nsupercute\nsuperdeluxe\nsuperdiplomat\nsuperdiplomats\nsupered\nsupereffective\nsuperefficiencies\nsuperefficiency\nsuperefficient\nsuperego\nsuperegoist\nsuperegoists\nsuperegos\nsuperelevate\nsuperelevated\nsuperelevates\nsuperelevating\nsuperelevation\nsuperelevations\nsuperelite\nsuperelites\nsupereminence\nsupereminences\nsupereminent\nsupereminently\nsuperencipher\nsuperenciphered\nsuperenciphering\nsuperenciphers\nsupererogation\nsupererogations\nsupererogatory\nsuperette\nsuperettes\nsuperexpensive\nsuperexpress\nsuperexpresses\nsuperfamilies\nsuperfamily\nsuperfan\nsuperfans\nsuperfarm\nsuperfarms\nsuperfast\nsuperfatted\nsuperfecundation\nsuperfecundations\nsuperfetation\nsuperfetations\nsuperficial\nsuperficialities\nsuperficiality\nsuperficially\nsuperficies\nsuperfine\nsuperfirm\nsuperfirms\nsuperfix\nsuperfixes\nsuperflack\nsuperflacks\nsuperfluid\nsuperfluidities\nsuperfluidity\nsuperfluids\nsuperfluities\nsuperfluity\nsuperfluous\nsuperfluously\nsuperfluousness\nsuperfluousnesses\nsuperfund\nsuperfunds\nsupergene\nsupergenes\nsupergiant\nsupergiants\nsuperglue\nsuperglues\nsupergood\nsupergovernment\nsupergovernments\nsupergraphics\nsupergravities\nsupergravity\nsupergroup\nsupergroups\nsupergrowth\nsupergrowths\nsuperharden\nsuperhardened\nsuperhardening\nsuperhardens\nsuperheat\nsuperheated\nsuperheater\nsuperheaters\nsuperheating\nsuperheats\nsuperheavy\nsuperheavyweight\nsuperheavyweights\nsuperhelical\nsuperhelices\nsuperhelix\nsuperhelixes\nsuperhero\nsuperheroes\nsuperheroine\nsuperheroines\nsuperheterodyne\nsuperheterodynes\nsuperhighway\nsuperhighways\nsuperhit\nsuperhits\nsuperhot\nsuperhuman\nsuperhumanities\nsuperhumanity\nsuperhumanly\nsuperhumanness\nsuperhumannesses\nsuperhype\nsuperhyped\nsuperhypes\nsuperhyping\nsuperimposable\nsuperimpose\nsuperimposed\nsuperimposes\nsuperimposing\nsuperimposition\nsuperimpositions\nsuperincumbent\nsuperincumbently\nsuperindividual\nsuperinduce\nsuperinduced\nsuperinduces\nsuperinducing\nsuperinduction\nsuperinductions\nsuperinfect\nsuperinfected\nsuperinfecting\nsuperinfection\nsuperinfections\nsuperinfects\nsupering\nsuperinsulated\nsuperintellectual\nsuperintellectuals\nsuperintelligence\nsuperintelligences\nsuperintelligent\nsuperintend\nsuperintended\nsuperintendence\nsuperintendences\nsuperintendencies\nsuperintendency\nsuperintendent\nsuperintendents\nsuperintending\nsuperintends\nsuperintensities\nsuperintensity\nsuperior\nsuperiorities\nsuperiority\nsuperiorly\nsuperiors\nsuperjacent\nsuperjet\nsuperjets\nsuperjock\nsuperjocks\nsuperjumbo\nsuperlain\nsuperlarge\nsuperlative\nsuperlatively\nsuperlativeness\nsuperlativenesses\nsuperlatives\nsuperlawyer\nsuperlawyers\nsuperlay\nsuperlie\nsuperlies\nsuperlight\nsuperliner\nsuperliners\nsuperlobbyist\nsuperlobbyists\nsuperloyalist\nsuperloyalists\nsuperlunar\nsuperlunary\nsuperluxuries\nsuperluxurious\nsuperluxury\nsuperlying\nsupermacho\nsupermachos\nsupermajorities\nsupermajority\nsupermale\nsupermales\nsuperman\nsupermarket\nsupermarkets\nsupermasculine\nsupermassive\nsupermen\nsupermicro\nsupermicros\nsupermilitant\nsupermillionaire\nsupermillionaires\nsupermind\nsuperminds\nsupermini\nsuperminicomputer\nsuperminicomputers\nsuperminis\nsuperminister\nsuperministers\nsupermodel\nsupermodels\nsupermodern\nsupermom\nsupermoms\nsupernal\nsupernally\nsupernatant\nsupernatants\nsupernation\nsupernational\nsupernations\nsupernatural\nsupernaturalism\nsupernaturalisms\nsupernaturalist\nsupernaturalistic\nsupernaturalists\nsupernaturally\nsupernaturalness\nsupernaturalnesses\nsupernaturals\nsupernature\nsupernatures\nsupernormal\nsupernormalities\nsupernormality\nsupernormally\nsupernova\nsupernovae\nsupernovas\nsupernumeraries\nsupernumerary\nsupernutrition\nsupernutritions\nsuperorder\nsuperorders\nsuperordinate\nsuperorganic\nsuperorganism\nsuperorganisms\nsuperorgasm\nsuperorgasms\nsuperovulate\nsuperovulated\nsuperovulates\nsuperovulating\nsuperovulation\nsuperovulations\nsuperoxide\nsuperoxides\nsuperparasitism\nsuperparasitisms\nsuperpatriot\nsuperpatriotic\nsuperpatriotism\nsuperpatriotisms\nsuperpatriots\nsuperperson\nsuperpersonal\nsuperpersons\nsuperphenomena\nsuperphenomenon\nsuperphenomenons\nsuperphosphate\nsuperphosphates\nsuperphysical\nsuperpimp\nsuperpimps\nsuperplane\nsuperplanes\nsuperplastic\nsuperplasticities\nsuperplasticity\nsuperplayer\nsuperplayers\nsuperpolite\nsuperport\nsuperports\nsuperposable\nsuperpose\nsuperposed\nsuperposes\nsuperposing\nsuperposition\nsuperpositions\nsuperpower\nsuperpowered\nsuperpowerful\nsuperpowers\nsuperpremium\nsuperpremiums\nsuperpro\nsuperprofit\nsuperprofits\nsuperpros\nsuperqualities\nsuperquality\nsuperrace\nsuperraces\nsuperreal\nsuperrealism\nsuperrealisms\nsuperregenerative\nsuperregional\nsuperrich\nsuperroad\nsuperroads\nsuperromantic\nsuperromanticism\nsuperromanticisms\nsupers\nsupersafe\nsupersale\nsupersales\nsupersalesman\nsupersalesmen\nsupersaturate\nsupersaturated\nsupersaturates\nsupersaturating\nsupersaturation\nsupersaturations\nsuperscale\nsuperscales\nsuperschool\nsuperschools\nsuperscout\nsuperscouts\nsuperscribe\nsuperscribed\nsuperscribes\nsuperscribing\nsuperscript\nsuperscription\nsuperscriptions\nsuperscripts\nsupersecrecies\nsupersecrecy\nsupersecret\nsupersecrets\nsupersede\nsupersedeas\nsuperseded\nsuperseder\nsuperseders\nsupersedes\nsuperseding\nsupersedure\nsupersedures\nsupersell\nsuperseller\nsupersellers\nsupersells\nsupersensible\nsupersensitive\nsupersensitively\nsupersensitivities\nsupersensitivity\nsupersensory\nsuperserviceable\nsupersession\nsupersessions\nsuperset\nsupersets\nsupersex\nsupersexes\nsupersexualities\nsupersexuality\nsupersharp\nsupershow\nsupershows\nsupersinger\nsupersingers\nsupersize\nsupersized\nsupersleuth\nsupersleuths\nsuperslick\nsupersmart\nsupersmooth\nsupersoft\nsupersonic\nsupersonically\nsupersonics\nsupersophisticated\nsuperspecial\nsuperspecialist\nsuperspecialists\nsuperspecialization\nsuperspecializations\nsuperspecialized\nsuperspecials\nsuperspectacle\nsuperspectacles\nsuperspectacular\nsuperspectaculars\nsuperspeculation\nsuperspeculations\nsuperspies\nsuperspy\nsuperstar\nsuperstardom\nsuperstardoms\nsuperstars\nsuperstate\nsuperstates\nsuperstation\nsuperstations\nsuperstimulate\nsuperstimulated\nsuperstimulates\nsuperstimulating\nsuperstition\nsuperstitions\nsuperstitious\nsuperstitiously\nsuperstock\nsuperstocks\nsuperstore\nsuperstores\nsuperstrata\nsuperstratum\nsuperstratums\nsuperstrength\nsuperstrengths\nsuperstrike\nsuperstrikes\nsuperstring\nsuperstrings\nsuperstrong\nsuperstructural\nsuperstructure\nsuperstructures\nsuperstud\nsuperstuds\nsupersubstantial\nsupersubtle\nsupersubtleties\nsupersubtlety\nsupersurgeon\nsupersurgeons\nsupersweet\nsupersymmetric\nsupersymmetries\nsupersymmetry\nsupersystem\nsupersystems\nsupertanker\nsupertankers\nsupertax\nsupertaxes\nsuperterrific\nsuperthick\nsuperthin\nsuperthriller\nsuperthrillers\nsupertight\nsupertonic\nsupertonics\nsupervene\nsupervened\nsupervenes\nsupervenient\nsupervening\nsupervention\nsuperventions\nsupervirile\nsupervirtuosi\nsupervirtuoso\nsupervirtuosos\nsupervise\nsupervised\nsupervises\nsupervising\nsupervision\nsupervisions\nsupervisor\nsupervisors\nsupervisory\nsuperwave\nsuperwaves\nsuperweapon\nsuperweapons\nsuperwide\nsuperwife\nsuperwives\nsuperwoman\nsuperwomen\nsupes\nsupinate\nsupinated\nsupinates\nsupinating\nsupination\nsupinations\nsupinator\nsupinators\nsupine\nsupinely\nsupineness\nsupinenesses\nsupines\nsupped\nsupper\nsuppers\nsuppertime\nsuppertimes\nsupping\nsupplant\nsupplantation\nsupplantations\nsupplanted\nsupplanter\nsupplanters\nsupplanting\nsupplants\nsupple\nsuppled\nsupplejack\nsupplejacks\nsupplely\nsupplement\nsupplemental\nsupplementals\nsupplementary\nsupplementation\nsupplementations\nsupplemented\nsupplementer\nsupplementers\nsupplementing\nsupplements\nsuppleness\nsupplenesses\nsuppler\nsupples\nsupplest\nsuppletion\nsuppletions\nsuppletive\nsuppletory\nsuppliance\nsuppliances\nsuppliant\nsuppliantly\nsuppliants\nsupplicant\nsupplicants\nsupplicate\nsupplicated\nsupplicates\nsupplicating\nsupplication\nsupplications\nsupplicatory\nsupplied\nsupplier\nsuppliers\nsupplies\nsuppling\nsupply\nsupplying\nsupport\nsupportabilities\nsupportability\nsupportable\nsupported\nsupporter\nsupporters\nsupporting\nsupportive\nsupportiveness\nsupportivenesses\nsupports\nsupposable\nsupposably\nsupposal\nsupposals\nsuppose\nsupposed\nsupposedly\nsupposer\nsupposers\nsupposes\nsupposing\nsupposition\nsuppositional\nsuppositions\nsuppositious\nsupposititious\nsupposititiously\nsuppositories\nsuppository\nsuppress\nsuppressant\nsuppressants\nsuppressed\nsuppresses\nsuppressibilities\nsuppressibility\nsuppressible\nsuppressing\nsuppression\nsuppressions\nsuppressive\nsuppressiveness\nsuppressivenesses\nsuppressor\nsuppressors\nsuppurate\nsuppurated\nsuppurates\nsuppurating\nsuppuration\nsuppurations\nsuppurative\nsupra\nsupraliminal\nsupramolecular\nsupranational\nsupranationalism\nsupranationalisms\nsupranationalist\nsupranationalists\nsupranationalities\nsupranationality\nsupraoptic\nsupraorbital\nsuprarational\nsuprarenal\nsuprarenals\nsuprasegmental\nsupraventricular\nsupravital\nsupravitally\nsupremacies\nsupremacist\nsupremacists\nsupremacy\nsuprematism\nsuprematisms\nsuprematist\nsuprematists\nsupreme\nsupremely\nsupremeness\nsupremenesses\nsupremer\nsupremest\nsupremo\nsupremos\nsups\nsuq\nsuqs\nsura\nsurah\nsurahs\nsural\nsuras\nsurbase\nsurbased\nsurbases\nsurcease\nsurceased\nsurceases\nsurceasing\nsurcharge\nsurcharged\nsurcharges\nsurcharging\nsurcingle\nsurcingles\nsurcoat\nsurcoats\nsurd\nsurds\nsure\nsurefire\nsurefooted\nsurefootedly\nsurefootedness\nsurefootednesses\nsurely\nsureness\nsurenesses\nsurer\nsurest\nsureties\nsurety\nsuretyship\nsuretyships\nsurf\nsurfable\nsurface\nsurfaced\nsurfacer\nsurfacers\nsurfaces\nsurfacing\nsurfacings\nsurfactant\nsurfactants\nsurfbird\nsurfbirds\nsurfboard\nsurfboarded\nsurfboarder\nsurfboarders\nsurfboarding\nsurfboards\nsurfboat\nsurfboats\nsurfed\nsurfeit\nsurfeited\nsurfeiter\nsurfeiters\nsurfeiting\nsurfeits\nsurfer\nsurfers\nsurffish\nsurffishes\nsurficial\nsurfier\nsurfiest\nsurfing\nsurfings\nsurflike\nsurfperch\nsurfperches\nsurfs\nsurfy\nsurge\nsurged\nsurgeon\nsurgeonfish\nsurgeonfishes\nsurgeons\nsurger\nsurgeries\nsurgers\nsurgery\nsurges\nsurgical\nsurgically\nsurging\nsurgy\nsuricate\nsuricates\nsurimi\nsurjection\nsurjections\nsurjective\nsurlier\nsurliest\nsurlily\nsurliness\nsurlinesses\nsurly\nsurmise\nsurmised\nsurmiser\nsurmisers\nsurmises\nsurmising\nsurmount\nsurmountable\nsurmounted\nsurmounting\nsurmounts\nsurname\nsurnamed\nsurnamer\nsurnamers\nsurnames\nsurnaming\nsurpass\nsurpassable\nsurpassed\nsurpasses\nsurpassing\nsurpassingly\nsurplice\nsurplices\nsurplus\nsurplusage\nsurplusages\nsurpluses\nsurprint\nsurprinted\nsurprinting\nsurprints\nsurprisal\nsurprisals\nsurprise\nsurprised\nsurpriser\nsurprisers\nsurprises\nsurprising\nsurprisingly\nsurprize\nsurprized\nsurprizes\nsurprizing\nsurra\nsurras\nsurreal\nsurrealism\nsurrealisms\nsurrealist\nsurrealistic\nsurrealistically\nsurrealists\nsurreally\nsurrebutter\nsurrebutters\nsurrejoinder\nsurrejoinders\nsurrender\nsurrendered\nsurrendering\nsurrenders\nsurreptitious\nsurreptitiously\nsurrey\nsurreys\nsurrogacies\nsurrogacy\nsurrogate\nsurrogated\nsurrogates\nsurrogating\nsurround\nsurrounded\nsurrounding\nsurroundings\nsurrounds\nsurroyal\nsurroyals\nsurtax\nsurtaxed\nsurtaxes\nsurtaxing\nsurtout\nsurtouts\nsurveil\nsurveillance\nsurveillances\nsurveillant\nsurveillants\nsurveilled\nsurveilling\nsurveils\nsurvey\nsurveyed\nsurveying\nsurveyings\nsurveyor\nsurveyors\nsurveys\nsurvivabilities\nsurvivability\nsurvivable\nsurvival\nsurvivalism\nsurvivalisms\nsurvivalist\nsurvivalists\nsurvivals\nsurvivance\nsurvivances\nsurvive\nsurvived\nsurviver\nsurvivers\nsurvives\nsurviving\nsurvivor\nsurvivors\nsurvivorship\nsurvivorships\nsusceptibilities\nsusceptibility\nsusceptible\nsusceptibleness\nsusceptiblenesses\nsusceptibly\nsusceptive\nsusceptiveness\nsusceptivenesses\nsusceptivities\nsusceptivity\nsushi\nsushis\nsuslik\nsusliks\nsuspect\nsuspected\nsuspecting\nsuspects\nsuspend\nsuspended\nsuspender\nsuspendered\nsuspenders\nsuspending\nsuspends\nsuspense\nsuspenseful\nsuspensefully\nsuspensefulness\nsuspensefulnesses\nsuspenseless\nsuspenser\nsuspensers\nsuspenses\nsuspension\nsuspensions\nsuspensive\nsuspensively\nsuspensor\nsuspensories\nsuspensors\nsuspensory\nsuspicion\nsuspicioned\nsuspicioning\nsuspicions\nsuspicious\nsuspiciously\nsuspiciousness\nsuspiciousnesses\nsuspiration\nsuspirations\nsuspire\nsuspired\nsuspires\nsuspiring\nsuss\nsussed\nsusses\nsussing\nsustain\nsustainabilities\nsustainability\nsustainable\nsustained\nsustainedly\nsustainer\nsustainers\nsustaining\nsustains\nsustenance\nsustenances\nsustentation\nsustentations\nsustentative\nsusurrant\nsusurration\nsusurrations\nsusurrous\nsusurrus\nsusurruses\nsutler\nsutlers\nsutra\nsutras\nsutta\nsuttas\nsuttee\nsuttees\nsutural\nsuturally\nsuture\nsutured\nsutures\nsuturing\nsuzerain\nsuzerains\nsuzerainties\nsuzerainty\nsvaraj\nsvarajes\nsvedberg\nsvedbergs\nsvelte\nsveltely\nsvelteness\nsveltenesses\nsvelter\nsveltest\nswab\nswabbed\nswabber\nswabbers\nswabbie\nswabbies\nswabbing\nswabby\nswabs\nswacked\nswaddle\nswaddled\nswaddles\nswaddling\nswag\nswage\nswaged\nswager\nswagers\nswages\nswagged\nswagger\nswaggered\nswaggerer\nswaggerers\nswaggering\nswaggeringly\nswaggers\nswaggie\nswaggies\nswagging\nswaging\nswagman\nswagmen\nswags\nswail\nswails\nswain\nswainish\nswainishness\nswainishnesses\nswains\nswale\nswales\nswallow\nswallowable\nswallowed\nswallower\nswallowers\nswallowing\nswallows\nswallowtail\nswallowtails\nswam\nswami\nswamies\nswamis\nswamp\nswamped\nswamper\nswampers\nswampier\nswampiest\nswampiness\nswampinesses\nswamping\nswampish\nswampland\nswamplands\nswamps\nswampy\nswamy\nswan\nswang\nswanherd\nswanherds\nswank\nswanked\nswanker\nswankest\nswankier\nswankiest\nswankily\nswankiness\nswankinesses\nswanking\nswanks\nswanky\nswanlike\nswanned\nswanneries\nswannery\nswanning\nswanpan\nswanpans\nswans\nswansdown\nswansdowns\nswanskin\nswanskins\nswap\nswapped\nswapper\nswappers\nswapping\nswaps\nswaraj\nswarajes\nswarajist\nswarajists\nsward\nswarded\nswarding\nswards\nsware\nswarf\nswarfs\nswarm\nswarmed\nswarmer\nswarmers\nswarming\nswarms\nswart\nswarth\nswarthier\nswarthiest\nswarthiness\nswarthinesses\nswarths\nswarthy\nswartness\nswartnesses\nswarty\nswash\nswashbuckle\nswashbuckled\nswashbuckler\nswashbucklers\nswashbuckles\nswashbuckling\nswashed\nswasher\nswashers\nswashes\nswashing\nswastica\nswasticas\nswastika\nswastikas\nswat\nswatch\nswatches\nswath\nswathe\nswathed\nswather\nswathers\nswathes\nswathing\nswaths\nswats\nswatted\nswatter\nswatters\nswatting\nsway\nswayable\nswayback\nswaybacked\nswaybacks\nswayed\nswayer\nswayers\nswayful\nswaying\nsways\nswear\nswearer\nswearers\nswearing\nswears\nswearword\nswearwords\nsweat\nsweatband\nsweatbands\nsweatbox\nsweatboxes\nsweated\nsweater\nsweaterdress\nsweaterdresses\nsweaters\nsweatier\nsweatiest\nsweatily\nsweatiness\nsweatinesses\nsweating\nsweatpants\nsweats\nsweatshirt\nsweatshirts\nsweatshop\nsweatshops\nsweaty\nswede\nswedes\nsweenies\nsweeny\nsweep\nsweepback\nsweepbacks\nsweeper\nsweepers\nsweepier\nsweepiest\nsweeping\nsweepingly\nsweepingness\nsweepingnesses\nsweepings\nsweeps\nsweepstake\nsweepstakes\nsweepy\nsweer\nsweet\nsweetbread\nsweetbreads\nsweetbriar\nsweetbriars\nsweetbrier\nsweetbriers\nsweeten\nsweetened\nsweetener\nsweeteners\nsweetening\nsweetenings\nsweetens\nsweeter\nsweetest\nsweetheart\nsweethearts\nsweetie\nsweeties\nsweeting\nsweetings\nsweetish\nsweetishly\nsweetly\nsweetmeat\nsweetmeats\nsweetness\nsweetnesses\nsweets\nsweetshop\nsweetshops\nsweetsop\nsweetsops\nswell\nswelled\nsweller\nswellest\nswellfish\nswellfishes\nswellhead\nswellheaded\nswellheadedness\nswellheadednesses\nswellheads\nswelling\nswellings\nswells\nswelter\nsweltered\nsweltering\nswelteringly\nswelters\nsweltrier\nsweltriest\nsweltry\nswept\nswerve\nswerved\nswerver\nswervers\nswerves\nswerving\nsweven\nswevens\nswidden\nswiddens\nswift\nswifter\nswifters\nswiftest\nswiftlet\nswiftlets\nswiftly\nswiftness\nswiftnesses\nswifts\nswig\nswigged\nswigger\nswiggers\nswigging\nswigs\nswill\nswilled\nswiller\nswillers\nswilling\nswills\nswim\nswimmable\nswimmer\nswimmeret\nswimmerets\nswimmers\nswimmier\nswimmiest\nswimmily\nswimming\nswimmingly\nswimmings\nswimmy\nswims\nswimsuit\nswimsuits\nswimwear\nswindle\nswindled\nswindler\nswindlers\nswindles\nswindling\nswine\nswineherd\nswineherds\nswinepox\nswinepoxes\nswing\nswingby\nswingbys\nswinge\nswinged\nswingeing\nswinger\nswingers\nswinges\nswingier\nswingiest\nswinging\nswingingest\nswingingly\nswingings\nswingle\nswingled\nswingles\nswingletree\nswingletrees\nswingling\nswingman\nswingmen\nswings\nswingy\nswinish\nswinishly\nswinishness\nswinishnesses\nswink\nswinked\nswinking\nswinks\nswinney\nswinneys\nswipe\nswiped\nswipes\nswiping\nswiple\nswiples\nswipple\nswipples\nswirl\nswirled\nswirlier\nswirliest\nswirling\nswirlingly\nswirls\nswirly\nswish\nswished\nswisher\nswishers\nswishes\nswishier\nswishiest\nswishing\nswishingly\nswishy\nswiss\nswisses\nswitch\nswitchable\nswitchback\nswitchbacked\nswitchbacking\nswitchbacks\nswitchblade\nswitchblades\nswitchboard\nswitchboards\nswitched\nswitcher\nswitcheroo\nswitcheroos\nswitchers\nswitches\nswitchgrass\nswitchgrasses\nswitching\nswitchman\nswitchmen\nswitchyard\nswitchyards\nswith\nswithe\nswither\nswithered\nswithering\nswithers\nswithly\nswive\nswived\nswivel\nswiveled\nswiveling\nswivelled\nswivelling\nswivels\nswives\nswivet\nswivets\nswiving\nswizzle\nswizzled\nswizzler\nswizzlers\nswizzles\nswizzling\nswob\nswobbed\nswobber\nswobbers\nswobbing\nswobs\nswollen\nswoon\nswooned\nswooner\nswooners\nswooning\nswooningly\nswoons\nswoop\nswooped\nswooper\nswoopers\nswooping\nswoops\nswoopstake\nswoosh\nswooshed\nswooshes\nswooshing\nswop\nswopped\nswopping\nswops\nsword\nswordfish\nswordfishes\nswordlike\nswordman\nswordmen\nswordplay\nswordplayer\nswordplayers\nswordplays\nswords\nswordsman\nswordsmanship\nswordsmanships\nswordsmen\nswordtail\nswordtails\nswore\nsworn\nswot\nswots\nswotted\nswotter\nswotters\nswotting\nswoun\nswound\nswounded\nswounding\nswounds\nswouned\nswouning\nswouns\nswum\nswung\nsybarite\nsybarites\nsybaritic\nsybaritically\nsybaritism\nsybaritisms\nsybo\nsyboes\nsycamine\nsycamines\nsycamore\nsycamores\nsyce\nsycee\nsycees\nsyces\nsycomore\nsycomores\nsyconia\nsyconium\nsycophancies\nsycophancy\nsycophant\nsycophantic\nsycophantically\nsycophantish\nsycophantishly\nsycophantism\nsycophantisms\nsycophantly\nsycophants\nsycoses\nsycosis\nsyenite\nsyenites\nsyenitic\nsyke\nsykes\nsyli\nsylis\nsyllabaries\nsyllabary\nsyllabi\nsyllabic\nsyllabically\nsyllabicate\nsyllabicated\nsyllabicates\nsyllabicating\nsyllabication\nsyllabications\nsyllabicities\nsyllabicity\nsyllabics\nsyllabification\nsyllabifications\nsyllabified\nsyllabifies\nsyllabify\nsyllabifying\nsyllable\nsyllabled\nsyllables\nsyllabling\nsyllabub\nsyllabubs\nsyllabus\nsyllabuses\nsyllepses\nsyllepsis\nsylleptic\nsyllogism\nsyllogisms\nsyllogist\nsyllogistic\nsyllogistically\nsyllogists\nsyllogize\nsyllogized\nsyllogizes\nsyllogizing\nsylph\nsylphic\nsylphid\nsylphids\nsylphish\nsylphlike\nsylphs\nsylphy\nsylva\nsylvae\nsylvan\nsylvanite\nsylvanites\nsylvans\nsylvas\nsylvatic\nsylviculture\nsylvicultures\nsylvin\nsylvine\nsylvines\nsylvins\nsylvite\nsylvites\nsymbion\nsymbions\nsymbiont\nsymbionts\nsymbioses\nsymbiosis\nsymbiot\nsymbiote\nsymbiotes\nsymbiotic\nsymbiotically\nsymbiots\nsymbol\nsymboled\nsymbolic\nsymbolical\nsymbolically\nsymboling\nsymbolise\nsymbolised\nsymbolises\nsymbolising\nsymbolism\nsymbolisms\nsymbolist\nsymbolistic\nsymbolists\nsymbolization\nsymbolizations\nsymbolize\nsymbolized\nsymbolizer\nsymbolizers\nsymbolizes\nsymbolizing\nsymbolled\nsymbolling\nsymbologies\nsymbology\nsymbols\nsymmetallism\nsymmetallisms\nsymmetric\nsymmetrical\nsymmetrically\nsymmetricalness\nsymmetricalnesses\nsymmetries\nsymmetrization\nsymmetrizations\nsymmetrize\nsymmetrized\nsymmetrizes\nsymmetrizing\nsymmetry\nsympathectomies\nsympathectomized\nsympathectomy\nsympathetic\nsympathetically\nsympathetics\nsympathies\nsympathin\nsympathins\nsympathise\nsympathised\nsympathises\nsympathising\nsympathize\nsympathized\nsympathizer\nsympathizers\nsympathizes\nsympathizing\nsympatholytic\nsympatholytics\nsympathomimetic\nsympathomimetics\nsympathy\nsympatric\nsympatrically\nsympatries\nsympatry\nsympetalies\nsympetalous\nsympetaly\nsymphonic\nsymphonically\nsymphonies\nsymphonious\nsymphoniously\nsymphonist\nsymphonists\nsymphony\nsymphyseal\nsymphyses\nsymphysial\nsymphysis\nsympodia\nsympodial\nsympodium\nsymposia\nsymposiarch\nsymposiarchs\nsymposiast\nsymposiasts\nsymposium\nsymposiums\nsymptom\nsymptomatic\nsymptomatically\nsymptomatologic\nsymptomatological\nsymptomatologically\nsymptomatologies\nsymptomatology\nsymptomless\nsymptoms\nsyn\nsynaereses\nsynaeresis\nsynaestheses\nsynaesthesia\nsynaesthesias\nsynaesthesis\nsynagog\nsynagogal\nsynagogs\nsynagogue\nsynagogues\nsynalepha\nsynalephas\nsynaloepha\nsynaloephas\nsynanon\nsynanons\nsynapse\nsynapsed\nsynapses\nsynapsid\nsynapsids\nsynapsing\nsynapsis\nsynaptic\nsynaptically\nsynaptosomal\nsynaptosome\nsynaptosomes\nsynarthrodial\nsynarthroses\nsynarthrosis\nsync\nsyncarp\nsyncarpies\nsyncarpous\nsyncarps\nsyncarpy\nsyncategorematic\nsyncategorematically\nsynced\nsynch\nsynched\nsynching\nsynchro\nsynchrocyclotron\nsynchrocyclotrons\nsynchromesh\nsynchromeshes\nsynchronal\nsynchroneities\nsynchroneity\nsynchronic\nsynchronical\nsynchronically\nsynchronicities\nsynchronicity\nsynchronies\nsynchronisation\nsynchronisations\nsynchronise\nsynchronised\nsynchronises\nsynchronising\nsynchronism\nsynchronisms\nsynchronistic\nsynchronization\nsynchronizations\nsynchronize\nsynchronized\nsynchronizer\nsynchronizers\nsynchronizes\nsynchronizing\nsynchronous\nsynchronously\nsynchronousness\nsynchronousnesses\nsynchrony\nsynchros\nsynchroscope\nsynchroscopes\nsynchrotron\nsynchrotrons\nsynchs\nsyncing\nsynclinal\nsyncline\nsynclines\nsyncom\nsyncoms\nsyncopal\nsyncopate\nsyncopated\nsyncopates\nsyncopating\nsyncopation\nsyncopations\nsyncopative\nsyncopator\nsyncopators\nsyncope\nsyncopes\nsyncopic\nsyncretic\nsyncretise\nsyncretised\nsyncretises\nsyncretising\nsyncretism\nsyncretisms\nsyncretist\nsyncretistic\nsyncretists\nsyncretize\nsyncretized\nsyncretizes\nsyncretizing\nsyncs\nsyncytia\nsyncytial\nsyncytium\nsyndactylies\nsyndactylism\nsyndactylisms\nsyndactyly\nsyndeses\nsyndesis\nsyndesises\nsyndesmoses\nsyndesmosis\nsyndet\nsyndetic\nsyndetically\nsyndets\nsyndic\nsyndical\nsyndicalism\nsyndicalisms\nsyndicalist\nsyndicalists\nsyndicate\nsyndicated\nsyndicates\nsyndicating\nsyndication\nsyndications\nsyndicator\nsyndicators\nsyndics\nsyndrome\nsyndromes\nsyne\nsynecdoche\nsynecdoches\nsynecdochic\nsynecdochical\nsynecdochically\nsynecological\nsynecologies\nsynecology\nsynectic\nsynereses\nsyneresis\nsynergetic\nsynergia\nsynergias\nsynergic\nsynergically\nsynergid\nsynergids\nsynergies\nsynergism\nsynergisms\nsynergist\nsynergistic\nsynergistically\nsynergists\nsynergy\nsynesis\nsynesises\nsynesthesia\nsynesthesias\nsynesthetic\nsynfuel\nsynfuels\nsyngamic\nsyngamies\nsyngamy\nsyngas\nsyngases\nsyngasses\nsyngeneic\nsynizeses\nsynizesis\nsynkarya\nsynkaryon\nsynkaryons\nsynod\nsynodal\nsynodic\nsynodical\nsynods\nsynonym\nsynonyme\nsynonymes\nsynonymic\nsynonymical\nsynonymies\nsynonymist\nsynonymists\nsynonymities\nsynonymity\nsynonymize\nsynonymized\nsynonymizes\nsynonymizing\nsynonymous\nsynonymously\nsynonyms\nsynonymy\nsynopses\nsynopsis\nsynopsize\nsynopsized\nsynopsizes\nsynopsizing\nsynoptic\nsynoptical\nsynoptically\nsynostoses\nsynostosis\nsynovia\nsynovial\nsynovias\nsynovitis\nsynovitises\nsyntactic\nsyntactical\nsyntactically\nsyntactics\nsyntagma\nsyntagmas\nsyntagmata\nsyntagmatic\nsyntax\nsyntaxes\nsynth\nsyntheses\nsynthesis\nsynthesist\nsynthesists\nsynthesize\nsynthesized\nsynthesizer\nsynthesizers\nsynthesizes\nsynthesizing\nsynthetase\nsynthetases\nsynthetic\nsynthetically\nsynthetics\nsynths\nsyntonic\nsyntonies\nsyntony\nsynura\nsynurae\nsyph\nsypher\nsyphered\nsyphering\nsyphers\nsyphilis\nsyphilises\nsyphilitic\nsyphilitics\nsyphon\nsyphoned\nsyphoning\nsyphons\nsyphs\nsyren\nsyrens\nsyringa\nsyringas\nsyringe\nsyringed\nsyringes\nsyringing\nsyringomyelia\nsyringomyelias\nsyringomyelic\nsyrinx\nsyrinxes\nsyrphian\nsyrphians\nsyrphid\nsyrphids\nsyrup\nsyrups\nsyrupy\nsysop\nsysops\nsystaltic\nsystem\nsystematic\nsystematically\nsystematicness\nsystematicnesses\nsystematics\nsystematise\nsystematised\nsystematises\nsystematising\nsystematism\nsystematisms\nsystematist\nsystematists\nsystematization\nsystematizations\nsystematize\nsystematized\nsystematizer\nsystematizers\nsystematizes\nsystematizing\nsystemic\nsystemically\nsystemics\nsystemization\nsystemizations\nsystemize\nsystemized\nsystemizes\nsystemizing\nsystemless\nsystems\nsystole\nsystoles\nsystolic\nsyzygal\nsyzygial\nsyzygies\nsyzygy\nta\ntab\ntabanid\ntabanids\ntabard\ntabarded\ntabards\ntabaret\ntabarets\ntabbed\ntabbied\ntabbies\ntabbing\ntabbis\ntabbises\ntabbouleh\ntabboulehs\ntabby\ntabbying\ntaber\ntabered\ntabering\ntabernacle\ntabernacled\ntabernacles\ntabernacling\ntabernacular\ntabers\ntabes\ntabetic\ntabetics\ntabid\ntabla\ntablas\ntablature\ntablatures\ntable\ntableau\ntableaus\ntableaux\ntablecloth\ntablecloths\ntabled\ntableful\ntablefuls\ntableland\ntablelands\ntablemate\ntablemates\ntables\ntablesful\ntablespoon\ntablespoonful\ntablespoonfuls\ntablespoons\ntablespoonsful\ntablet\ntableted\ntableting\ntabletop\ntabletops\ntablets\ntabletted\ntabletting\ntableware\ntablewares\ntabling\ntabloid\ntabloids\ntaboo\ntabooed\ntabooing\ntabooley\ntabooleys\ntaboos\ntabor\ntabored\ntaborer\ntaborers\ntaboret\ntaborets\ntaborin\ntaborine\ntaborines\ntaboring\ntaborins\ntabors\ntabouli\ntaboulis\ntabour\ntaboured\ntabourer\ntabourers\ntabouret\ntabourets\ntabouring\ntabours\ntabs\ntabu\ntabued\ntabuing\ntabular\ntabulate\ntabulated\ntabulates\ntabulating\ntabulation\ntabulations\ntabulator\ntabulators\ntabuli\ntabulis\ntabun\ntabuns\ntabus\ntacamahac\ntacamahacs\ntace\ntaces\ntacet\ntach\ntache\ntaches\ntachinid\ntachinids\ntachism\ntachisme\ntachismes\ntachisms\ntachist\ntachiste\ntachistes\ntachistoscope\ntachistoscopes\ntachistoscopic\ntachistoscopically\ntachists\ntachometer\ntachometers\ntachs\ntachyarrhythmia\ntachyarrhythmias\ntachycardia\ntachycardias\ntachyon\ntachyons\ntacit\ntacitly\ntacitness\ntacitnesses\ntaciturn\ntaciturnities\ntaciturnity\ntack\ntackboard\ntackboards\ntacked\ntacker\ntackers\ntacket\ntackets\ntackey\ntackier\ntackiest\ntackified\ntackifier\ntackifiers\ntackifies\ntackify\ntackifying\ntackily\ntackiness\ntackinesses\ntacking\ntackle\ntackled\ntackler\ntacklers\ntackles\ntackless\ntackling\ntacklings\ntacks\ntacky\ntacnode\ntacnodes\ntaco\ntaconite\ntaconites\ntacos\ntacrine\ntacrines\ntact\ntactful\ntactfully\ntactfulness\ntactfulnesses\ntactic\ntactical\ntactically\ntactician\ntacticians\ntactics\ntactile\ntactilely\ntactilities\ntactility\ntaction\ntactions\ntactless\ntactlessly\ntactlessness\ntactlessnesses\ntacts\ntactual\ntactually\ntad\ntadpole\ntadpoles\ntads\ntae\ntael\ntaels\ntaenia\ntaeniae\ntaenias\ntaeniases\ntaeniasis\ntaffarel\ntaffarels\ntafferel\ntafferels\ntaffeta\ntaffetas\ntaffetized\ntaffia\ntaffias\ntaffies\ntaffrail\ntaffrails\ntaffy\ntafia\ntafias\ntag\ntagalong\ntagalongs\ntagboard\ntagboards\ntagged\ntagger\ntaggers\ntagging\ntagliatelle\ntagliatelles\ntaglike\ntagmeme\ntagmemes\ntagmemic\ntagrag\ntagrags\ntags\ntahini\ntahinis\ntahr\ntahrs\ntahsil\ntahsils\ntaiga\ntaigas\ntaiglach\ntail\ntailback\ntailbacks\ntailboard\ntailboards\ntailbone\ntailbones\ntailcoat\ntailcoated\ntailcoats\ntailed\ntailender\ntailenders\ntailer\ntailers\ntailfan\ntailfans\ntailgate\ntailgated\ntailgater\ntailgaters\ntailgates\ntailgating\ntailing\ntailings\ntaillamp\ntaillamps\ntaille\ntailles\ntailless\ntailleur\ntailleurs\ntaillight\ntaillights\ntaillike\ntailor\ntailorbird\ntailorbirds\ntailored\ntailoring\ntailorings\ntailors\ntailpiece\ntailpieces\ntailpipe\ntailpipes\ntailplane\ntailplanes\ntailrace\ntailraces\ntails\ntailskid\ntailskids\ntailslide\ntailslides\ntailspin\ntailspins\ntailwater\ntailwaters\ntailwind\ntailwinds\ntain\ntains\ntaint\ntainted\ntainting\ntaintless\ntaints\ntaipan\ntaipans\ntaj\ntajes\ntaka\ntakable\ntakahe\ntakahes\ntakas\ntake\ntakeable\ntakeaway\ntakedown\ntakedowns\ntaken\ntakeoff\ntakeoffs\ntakeout\ntakeouts\ntakeover\ntakeovers\ntaker\ntakers\ntakes\ntakeup\ntakeups\ntakin\ntaking\ntakingly\ntakings\ntakins\ntala\ntalapoin\ntalapoins\ntalar\ntalaria\ntalars\ntalas\ntalc\ntalced\ntalcing\ntalcked\ntalcking\ntalcky\ntalcose\ntalcous\ntalcs\ntalcum\ntalcums\ntale\ntalebearer\ntalebearers\ntalebearing\ntalebearings\ntalent\ntalented\ntalentless\ntalents\ntaler\ntalers\ntales\ntalesman\ntalesmen\ntaleysim\ntali\ntalion\ntalions\ntaliped\ntalipeds\ntalipes\ntalipot\ntalipots\ntalisman\ntalismanic\ntalismanically\ntalismans\ntalk\ntalkable\ntalkathon\ntalkathons\ntalkative\ntalkatively\ntalkativeness\ntalkativenesses\ntalked\ntalker\ntalkers\ntalkfest\ntalkfests\ntalkie\ntalkier\ntalkies\ntalkiest\ntalkiness\ntalkinesses\ntalking\ntalkings\ntalks\ntalky\ntall\ntallage\ntallaged\ntallages\ntallaging\ntallaisim\ntallboy\ntallboys\ntaller\ntallest\ntallied\ntallier\ntalliers\ntallies\ntallis\ntallises\ntallish\ntallisim\ntallit\ntallith\ntallithes\ntallithim\ntalliths\ntallitim\ntallitoth\ntallness\ntallnesses\ntallol\ntallols\ntallow\ntallowed\ntallowing\ntallows\ntallowy\ntally\ntallyho\ntallyhoed\ntallyhoing\ntallyhos\ntallying\ntallyman\ntallymen\ntalmudic\ntalmudism\ntalmudisms\ntalon\ntaloned\ntalons\ntalooka\ntalookas\ntaluk\ntaluka\ntalukas\ntaluks\ntalus\ntaluses\ntam\ntamable\ntamal\ntamale\ntamales\ntamals\ntamandu\ntamandua\ntamanduas\ntamandus\ntamarack\ntamaracks\ntamarao\ntamaraos\ntamarau\ntamaraus\ntamari\ntamarillo\ntamarillos\ntamarin\ntamarind\ntamarinds\ntamarins\ntamaris\ntamarisk\ntamarisks\ntamasha\ntamashas\ntambac\ntambacs\ntambak\ntambaks\ntambala\ntambalas\ntambour\ntamboura\ntambouras\ntamboured\ntambourer\ntambourers\ntambourine\ntambourines\ntambouring\ntambours\ntambur\ntambura\ntamburas\ntamburs\ntame\ntameable\ntamed\ntamein\ntameins\ntameless\ntamely\ntameness\ntamenesses\ntamer\ntamers\ntames\ntamest\ntaming\ntamis\ntamises\ntammie\ntammies\ntammy\ntamoxifen\ntamoxifens\ntamp\ntampala\ntampalas\ntampan\ntampans\ntamped\ntamper\ntampered\ntamperer\ntamperers\ntampering\ntamperproof\ntampers\ntamping\ntampion\ntampions\ntampon\ntamponed\ntamponing\ntampons\ntamps\ntams\ntan\ntanager\ntanagers\ntanbark\ntanbarks\ntandem\ntandems\ntandoor\ntandoori\ntandooris\ntandoors\ntang\ntanged\ntangelo\ntangelos\ntangence\ntangences\ntangencies\ntangency\ntangent\ntangential\ntangentially\ntangents\ntangerine\ntangerines\ntangibilities\ntangibility\ntangible\ntangibleness\ntangiblenesses\ntangibles\ntangibly\ntangier\ntangiest\ntanging\ntangle\ntangled\ntanglement\ntanglements\ntangler\ntanglers\ntangles\ntanglier\ntangliest\ntangling\ntangly\ntango\ntangoed\ntangoing\ntangos\ntangram\ntangrams\ntangs\ntangy\ntanist\ntanistries\ntanistry\ntanists\ntank\ntanka\ntankage\ntankages\ntankard\ntankards\ntankas\ntanked\ntanker\ntankers\ntankful\ntankfuls\ntanking\ntanklike\ntanks\ntankship\ntankships\ntannable\ntannage\ntannages\ntannate\ntannates\ntanned\ntanner\ntanneries\ntanners\ntannery\ntannest\ntannic\ntannin\ntanning\ntannings\ntannins\ntannish\ntanrec\ntanrecs\ntans\ntansies\ntansy\ntantalate\ntantalates\ntantalic\ntantalise\ntantalised\ntantalises\ntantalising\ntantalite\ntantalites\ntantalize\ntantalized\ntantalizer\ntantalizers\ntantalizes\ntantalizing\ntantalizingly\ntantalum\ntantalums\ntantalus\ntantaluses\ntantamount\ntantara\ntantaras\ntantivies\ntantivy\ntanto\ntantra\ntantras\ntantric\ntantrum\ntantrums\ntanuki\ntanukis\ntanyard\ntanyards\ntanzanite\ntanzanites\ntao\ntaos\ntap\ntapa\ntapadera\ntapaderas\ntapadero\ntapaderos\ntapalo\ntapalos\ntapas\ntape\ntaped\ntapeless\ntapelike\ntapeline\ntapelines\ntapenade\ntapenades\ntaper\ntapered\ntaperer\ntaperers\ntapering\ntapers\ntaperstick\ntapersticks\ntapes\ntapestried\ntapestries\ntapestry\ntapestrying\ntapeta\ntapetal\ntapetum\ntapeworm\ntapeworms\ntaphole\ntapholes\ntaphonomic\ntaphonomies\ntaphonomist\ntaphonomists\ntaphonomy\ntaphouse\ntaphouses\ntaping\ntapioca\ntapiocas\ntapir\ntapirs\ntapis\ntapises\ntapped\ntapper\ntappers\ntappet\ntappets\ntapping\ntappings\ntaproom\ntaprooms\ntaproot\ntaproots\ntaps\ntapster\ntapsters\ntar\ntaradiddle\ntaradiddles\ntarama\ntaramas\ntarantas\ntarantases\ntarantella\ntarantellas\ntarantism\ntarantisms\ntarantula\ntarantulae\ntarantulas\ntarboosh\ntarbooshes\ntarbush\ntarbushes\ntardier\ntardies\ntardiest\ntardigrade\ntardigrades\ntardily\ntardiness\ntardinesses\ntardo\ntardy\ntardyon\ntardyons\ntare\ntared\ntares\ntarge\ntarges\ntarget\ntargetable\ntargeted\ntargeting\ntargets\ntariff\ntariffed\ntariffing\ntariffs\ntaring\ntarlatan\ntarlatans\ntarletan\ntarletans\ntarmac\ntarmacadam\ntarmacadams\ntarmacs\ntarn\ntarnal\ntarnally\ntarnation\ntarnations\ntarnish\ntarnishable\ntarnished\ntarnishes\ntarnishing\ntarns\ntaro\ntaroc\ntarocs\ntarok\ntaroks\ntaros\ntarot\ntarots\ntarp\ntarpan\ntarpans\ntarpaper\ntarpapers\ntarpaulin\ntarpaulins\ntarpon\ntarpons\ntarps\ntarradiddle\ntarradiddles\ntarragon\ntarragons\ntarre\ntarred\ntarres\ntarriance\ntarriances\ntarried\ntarrier\ntarriers\ntarries\ntarriest\ntarring\ntarry\ntarrying\ntars\ntarsal\ntarsals\ntarsi\ntarsia\ntarsias\ntarsier\ntarsiers\ntarsometatarsi\ntarsometatarsus\ntarsus\ntart\ntartan\ntartana\ntartanas\ntartans\ntartar\ntartaric\ntartars\ntarted\ntarter\ntartest\ntarting\ntartish\ntartlet\ntartlets\ntartly\ntartness\ntartnesses\ntartrate\ntartrates\ntarts\ntartufe\ntartufes\ntartuffe\ntartuffes\ntarty\ntarweed\ntarweeds\ntarzan\ntarzans\ntas\ntask\ntasked\ntasking\ntaskmaster\ntaskmasters\ntaskmistress\ntaskmistresses\ntasks\ntaskwork\ntaskworks\ntass\ntasse\ntassel\ntasseled\ntasseling\ntasselled\ntasselling\ntassels\ntasses\ntasset\ntassets\ntassie\ntassies\ntastable\ntaste\ntasted\ntasteful\ntastefully\ntastefulness\ntastefulnesses\ntasteless\ntastelessly\ntastelessness\ntastelessnesses\ntastemaker\ntastemakers\ntaster\ntasters\ntastes\ntastier\ntastiest\ntastily\ntastiness\ntastinesses\ntasting\ntasty\ntat\ntatami\ntatamis\ntatar\ntatars\ntate\ntater\ntaters\ntates\ntatouay\ntatouays\ntats\ntatted\ntatter\ntatterdemalion\ntatterdemalions\ntattered\ntattering\ntatters\ntattersall\ntattersalls\ntattie\ntattier\ntatties\ntattiest\ntattily\ntattiness\ntattinesses\ntatting\ntattings\ntattle\ntattled\ntattler\ntattlers\ntattles\ntattletale\ntattletales\ntattling\ntattoo\ntattooed\ntattooer\ntattooers\ntattooing\ntattooist\ntattooists\ntattoos\ntatty\ntau\ntaught\ntaunt\ntaunted\ntaunter\ntaunters\ntaunting\ntauntingly\ntaunts\ntaupe\ntaupes\ntaurine\ntaurines\ntaus\ntaut\ntautaug\ntautaugs\ntauted\ntauten\ntautened\ntautening\ntautens\ntauter\ntautest\ntauting\ntautly\ntautness\ntautnesses\ntautog\ntautogs\ntautological\ntautologically\ntautologies\ntautologous\ntautologously\ntautology\ntautomer\ntautomeric\ntautomerism\ntautomerisms\ntautomers\ntautonym\ntautonymies\ntautonyms\ntautonymy\ntauts\ntav\ntavern\ntaverna\ntavernas\ntaverner\ntaverners\ntaverns\ntavs\ntaw\ntawdrier\ntawdries\ntawdriest\ntawdrily\ntawdriness\ntawdrinesses\ntawdry\ntawed\ntawer\ntawers\ntawie\ntawing\ntawney\ntawneys\ntawnier\ntawnies\ntawniest\ntawnily\ntawniness\ntawninesses\ntawny\ntawpie\ntawpies\ntaws\ntawse\ntawsed\ntawses\ntawsing\ntax\ntaxa\ntaxable\ntaxables\ntaxably\ntaxation\ntaxations\ntaxed\ntaxeme\ntaxemes\ntaxemic\ntaxer\ntaxers\ntaxes\ntaxi\ntaxicab\ntaxicabs\ntaxidermic\ntaxidermies\ntaxidermist\ntaxidermists\ntaxidermy\ntaxied\ntaxies\ntaxiing\ntaximan\ntaximen\ntaximeter\ntaximeters\ntaxing\ntaxingly\ntaxis\ntaxite\ntaxites\ntaxitic\ntaxiway\ntaxiways\ntaxless\ntaxman\ntaxmen\ntaxon\ntaxonomic\ntaxonomically\ntaxonomies\ntaxonomist\ntaxonomists\ntaxonomy\ntaxons\ntaxpaid\ntaxpayer\ntaxpayers\ntaxpaying\ntaxus\ntaxwise\ntaxying\ntazza\ntazzas\ntazze\ntchotchke\ntchotchkes\ntea\nteaberries\nteaberry\nteaboard\nteaboards\nteabowl\nteabowls\nteabox\nteaboxes\nteacake\nteacakes\nteacart\nteacarts\nteach\nteachable\nteachableness\nteachablenesses\nteachably\nteacher\nteacherly\nteachers\nteaches\nteaching\nteachings\nteacup\nteacupful\nteacupfuls\nteacups\nteacupsful\nteahouse\nteahouses\nteak\nteakettle\nteakettles\nteaks\nteakwood\nteakwoods\nteal\ntealike\nteals\nteam\nteamaker\nteamakers\nteamed\nteaming\nteammate\nteammates\nteams\nteamster\nteamsters\nteamwork\nteamworks\nteapot\nteapots\nteapoy\nteapoys\ntear\ntearable\ntearaway\ntearaways\nteardown\nteardowns\nteardrop\nteardrops\nteared\ntearer\ntearers\ntearful\ntearfully\ntearfulness\ntearfulnesses\nteargas\nteargases\nteargassed\nteargasses\nteargassing\ntearier\nteariest\ntearily\ntearing\ntearjerker\ntearjerkers\ntearless\ntearoom\ntearooms\ntears\ntearstain\ntearstained\ntearstains\nteary\nteas\ntease\nteased\nteasel\nteaseled\nteaseler\nteaselers\nteaseling\nteaselled\nteaselling\nteasels\nteaser\nteasers\nteases\nteashop\nteashops\nteasing\nteasingly\nteaspoon\nteaspoonful\nteaspoonfuls\nteaspoons\nteaspoonsful\nteat\nteated\nteatime\nteatimes\nteats\nteaware\nteawares\nteazel\nteazeled\nteazeling\nteazelled\nteazelling\nteazels\nteazle\nteazled\nteazles\nteazling\nteched\ntechie\ntechier\ntechies\ntechiest\ntechily\ntechnetium\ntechnetiums\ntechnetronic\ntechnic\ntechnical\ntechnicalities\ntechnicality\ntechnicalization\ntechnicalizations\ntechnicalize\ntechnicalized\ntechnicalizes\ntechnicalizing\ntechnically\ntechnicals\ntechnician\ntechnicians\ntechnics\ntechnique\ntechniques\ntechnobabble\ntechnobabbles\ntechnocracies\ntechnocracy\ntechnocrat\ntechnocratic\ntechnocrats\ntechnologic\ntechnological\ntechnologically\ntechnologies\ntechnologist\ntechnologists\ntechnologize\ntechnologized\ntechnologizes\ntechnologizing\ntechnology\ntechnophile\ntechnophiles\ntechnophobe\ntechnophobes\ntechnophobia\ntechnophobias\ntechnophobic\ntechnostructure\ntechnostructures\ntechy\ntecta\ntectal\ntectite\ntectites\ntectonic\ntectonically\ntectonics\ntectonism\ntectonisms\ntectrices\ntectrix\ntectum\ntectums\nted\ntedded\ntedder\ntedders\nteddies\ntedding\nteddy\ntedious\ntediously\ntediousness\ntediousnesses\ntedium\ntediums\nteds\ntee\nteed\nteeing\nteel\nteels\nteem\nteemed\nteemer\nteemers\nteeming\nteemingly\nteemingness\nteemingnesses\nteems\nteen\nteenage\nteenaged\nteenager\nteenagers\nteener\nteeners\nteenful\nteenier\nteeniest\nteens\nteensier\nteensiest\nteensy\nteentsier\nteentsiest\nteentsy\nteeny\nteenybop\nteenybopper\nteenyboppers\nteepee\nteepees\ntees\nteeter\nteeterboard\nteeterboards\nteetered\nteetering\nteeters\nteeth\nteethe\nteethed\nteether\nteethers\nteethes\nteething\nteethings\nteethridge\nteethridges\nteetotal\nteetotaled\nteetotaler\nteetotalers\nteetotaling\nteetotalism\nteetotalisms\nteetotalist\nteetotalists\nteetotalled\nteetotaller\nteetotallers\nteetotalling\nteetotally\nteetotals\nteetotum\nteetotums\nteff\nteffs\ntefillin\nteg\ntegmen\ntegmenta\ntegmental\ntegmentum\ntegmina\ntegminal\ntegs\ntegua\nteguas\ntegular\ntegumen\ntegument\nteguments\ntegumina\nteiglach\nteiid\nteiids\nteind\nteinds\ntektite\ntektites\ntektitic\ntel\ntela\ntelae\ntelamon\ntelamones\ntelangiectases\ntelangiectasia\ntelangiectasias\ntelangiectasis\ntelangiectatic\ntele\ntelecast\ntelecasted\ntelecaster\ntelecasters\ntelecasting\ntelecasts\ntelecommunication\ntelecommunications\ntelecommute\ntelecommuted\ntelecommuter\ntelecommuters\ntelecommutes\ntelecommuting\nteleconference\nteleconferenced\nteleconferences\nteleconferencing\nteleconferencings\ntelecourse\ntelecourses\nteledu\nteledus\ntelefacsimile\ntelefacsimiles\ntelefilm\ntelefilms\ntelega\ntelegas\ntelegenic\ntelegonies\ntelegony\ntelegram\ntelegrammed\ntelegramming\ntelegrams\ntelegraph\ntelegraphed\ntelegrapher\ntelegraphers\ntelegraphese\ntelegrapheses\ntelegraphic\ntelegraphically\ntelegraphies\ntelegraphing\ntelegraphist\ntelegraphists\ntelegraphs\ntelegraphy\ntelekineses\ntelekinesis\ntelekinetic\ntelekinetically\nteleman\ntelemark\ntelemarketer\ntelemarketers\ntelemarketing\ntelemarketings\ntelemarks\ntelemen\ntelemeter\ntelemetered\ntelemetering\ntelemeters\ntelemetric\ntelemetrically\ntelemetries\ntelemetry\ntelencephala\ntelencephalic\ntelencephalon\ntelencephalons\nteleologic\nteleological\nteleologically\nteleologies\nteleologist\nteleologists\nteleology\nteleonomic\nteleonomies\nteleonomy\nteleost\nteleostean\nteleosts\ntelepath\ntelepathic\ntelepathically\ntelepathies\ntelepaths\ntelepathy\ntelephone\ntelephoned\ntelephoner\ntelephoners\ntelephones\ntelephonic\ntelephonically\ntelephonies\ntelephoning\ntelephonist\ntelephonists\ntelephony\ntelephoto\ntelephotographies\ntelephotography\ntelephotos\nteleplay\nteleplays\nteleport\nteleportation\nteleportations\nteleported\nteleporting\nteleports\nteleprinter\nteleprinters\nteleprocessing\nteleprocessings\nteleran\ntelerans\nteles\ntelescope\ntelescoped\ntelescopes\ntelescopic\ntelescopically\ntelescoping\nteleses\ntelesis\ntelestic\ntelestics\nteletext\nteletexts\ntelethon\ntelethons\nteletypewriter\nteletypewriters\nteleutospore\nteleutospores\ntelevangelism\ntelevangelisms\ntelevangelist\ntelevangelists\nteleview\nteleviewed\nteleviewer\nteleviewers\nteleviewing\nteleviews\ntelevise\ntelevised\ntelevises\ntelevising\ntelevision\ntelevisions\ntelevisual\ntelex\ntelexed\ntelexes\ntelexing\ntelfer\ntelfered\ntelfering\ntelfers\ntelford\ntelfords\ntelia\ntelial\ntelic\ntelically\nteliospore\nteliospores\ntelium\ntell\ntellable\nteller\ntellers\ntellies\ntelling\ntellingly\ntells\ntelltale\ntelltales\ntellurian\ntelluric\ntelluride\ntellurides\ntellurium\ntelluriums\ntellurometer\ntellurometers\ntelly\ntellys\ntelnet\ntelneted\ntelneting\ntelnets\ntelnetted\ntelnetting\ntelocentric\ntelocentrics\nteloi\ntelome\ntelomere\ntelomeres\ntelomes\ntelomic\ntelophase\ntelophases\ntelos\nteloses\ntelotaxes\ntelotaxis\ntelpher\ntelphered\ntelphering\ntelphers\ntels\ntelson\ntelsonic\ntelsons\ntemblor\ntemblores\ntemblors\ntemerarious\ntemerariously\ntemerariousness\ntemerariousnesses\ntemerities\ntemerity\ntemp\ntemped\ntempeh\ntempehs\ntemper\ntempera\ntemperable\ntemperament\ntemperamental\ntemperamentally\ntemperaments\ntemperance\ntemperances\ntemperas\ntemperate\ntemperately\ntemperateness\ntemperatenesses\ntemperature\ntemperatures\ntempered\ntemperer\ntemperers\ntempering\ntempers\ntempest\ntempested\ntempesting\ntempests\ntempestuous\ntempestuously\ntempestuousness\ntempestuousnesses\ntempi\ntemping\ntemplar\ntemplars\ntemplate\ntemplates\ntemple\ntempled\ntemples\ntemplet\ntemplets\ntempo\ntemporal\ntemporalities\ntemporality\ntemporalize\ntemporalized\ntemporalizes\ntemporalizing\ntemporally\ntemporals\ntemporaries\ntemporarily\ntemporariness\ntemporarinesses\ntemporary\ntemporise\ntemporised\ntemporises\ntemporising\ntemporization\ntemporizations\ntemporize\ntemporized\ntemporizer\ntemporizers\ntemporizes\ntemporizing\ntemporomandibular\ntempos\ntemps\ntempt\ntemptable\ntemptation\ntemptations\ntempted\ntempter\ntempters\ntempting\ntemptingly\ntemptress\ntemptresses\ntempts\ntempura\ntempuras\nten\ntenabilities\ntenability\ntenable\ntenableness\ntenablenesses\ntenably\ntenace\ntenaces\ntenacious\ntenaciously\ntenaciousness\ntenaciousnesses\ntenacities\ntenacity\ntenacula\ntenaculum\ntenaculums\ntenail\ntenaille\ntenailles\ntenails\ntenancies\ntenancy\ntenant\ntenantable\ntenanted\ntenanting\ntenantless\ntenantries\ntenantry\ntenants\ntench\ntenches\ntend\ntendance\ntendances\ntended\ntendence\ntendences\ntendencies\ntendencious\ntendency\ntendentious\ntendentiously\ntendentiousness\ntendentiousnesses\ntender\ntendered\ntenderer\ntenderers\ntenderest\ntenderfeet\ntenderfoot\ntenderfoots\ntenderhearted\ntenderheartedly\ntenderheartedness\ntenderheartednesses\ntendering\ntenderization\ntenderizations\ntenderize\ntenderized\ntenderizer\ntenderizers\ntenderizes\ntenderizing\ntenderloin\ntenderloins\ntenderly\ntenderness\ntendernesses\ntenderometer\ntenderometers\ntenders\ntending\ntendinitis\ntendinitises\ntendinous\ntendon\ntendonitis\ntendonitises\ntendons\ntendresse\ntendresses\ntendril\ntendriled\ntendrilled\ntendrilous\ntendrils\ntends\ntenebrae\ntenebrific\ntenebrionid\ntenebrionids\ntenebrious\ntenebrism\ntenebrisms\ntenebrist\ntenebrists\ntenebrous\ntenement\ntenements\ntenesmic\ntenesmus\ntenesmuses\ntenet\ntenets\ntenfold\ntenfolds\ntenge\ntenia\nteniae\ntenias\nteniases\nteniasis\ntenner\ntenners\ntennies\ntennis\ntennises\ntennist\ntennists\ntenon\ntenoned\ntenoner\ntenoners\ntenoning\ntenons\ntenor\ntenorist\ntenorists\ntenorite\ntenorites\ntenors\ntenosynovitis\ntenosynovitises\ntenotomies\ntenotomy\ntenour\ntenours\ntenpence\ntenpences\ntenpenny\ntenpin\ntenpins\ntenpounder\ntenpounders\ntenrec\ntenrecs\ntens\ntense\ntensed\ntensely\ntenseness\ntensenesses\ntenser\ntenses\ntensest\ntensible\ntensibly\ntensile\ntensilities\ntensility\ntensing\ntensiometer\ntensiometers\ntensiometric\ntensiometries\ntensiometry\ntension\ntensional\ntensioned\ntensioner\ntensioners\ntensioning\ntensionless\ntensions\ntensities\ntensity\ntensive\ntensor\ntensors\ntent\ntentacle\ntentacled\ntentacles\ntentacular\ntentage\ntentages\ntentative\ntentatively\ntentativeness\ntentativenesses\ntentatives\ntented\ntenter\ntentered\ntenterhook\ntenterhooks\ntentering\ntenters\ntenth\ntenthly\ntenths\ntentie\ntentier\ntentiest\ntenting\ntentless\ntentlike\ntents\ntenty\ntenues\ntenuis\ntenuities\ntenuity\ntenuous\ntenuously\ntenuousness\ntenuousnesses\ntenurable\ntenure\ntenured\ntenures\ntenurial\ntenurially\ntenuti\ntenuto\ntenutos\nteocalli\nteocallis\nteopan\nteopans\nteosinte\nteosintes\ntepa\ntepal\ntepals\ntepas\ntepee\ntepees\ntepefied\ntepefies\ntepefy\ntepefying\ntephra\ntephras\ntephrite\ntephrites\ntepid\ntepidities\ntepidity\ntepidly\ntepidness\ntepidnesses\ntepoy\ntepoys\ntequila\ntequilas\nterabyte\nterabytes\nterai\nterais\nteraohm\nteraohms\nteraph\nteraphim\nteratism\nteratisms\nteratocarcinoma\nteratocarcinomas\nteratocarcinomata\nteratogen\nteratogeneses\nteratogenesis\nteratogenic\nteratogenicities\nteratogenicity\nteratogens\nteratoid\nteratologic\nteratological\nteratologies\nteratologist\nteratologists\nteratology\nteratoma\nteratomas\nteratomata\nterawatt\nterawatts\nterbia\nterbias\nterbic\nterbium\nterbiums\nterce\ntercel\ntercelet\ntercelets\ntercels\ntercentenaries\ntercentenary\ntercentennial\ntercentennials\nterces\ntercet\ntercets\nterebene\nterebenes\nterebic\nterebinth\nterebinths\nteredines\nteredo\nteredos\nterefah\nterephthalate\nterephthalates\nterete\nterga\ntergal\ntergite\ntergites\ntergiversate\ntergiversated\ntergiversates\ntergiversating\ntergiversation\ntergiversations\ntergiversator\ntergiversators\ntergum\nteriyaki\nteriyakis\nterm\ntermagant\ntermagants\ntermed\ntermer\ntermers\nterminable\nterminableness\nterminablenesses\nterminably\nterminal\nterminally\nterminals\nterminate\nterminated\nterminates\nterminating\ntermination\nterminational\nterminations\nterminative\nterminatively\nterminator\nterminators\nterming\ntermini\nterminological\nterminologically\nterminologies\nterminology\nterminus\nterminuses\ntermitaria\ntermitaries\ntermitarium\ntermitary\ntermite\ntermites\ntermitic\ntermless\ntermly\ntermor\ntermors\nterms\ntermtime\ntermtimes\ntern\nternaries\nternary\nternate\nternately\nterne\nterneplate\nterneplates\nternes\nternion\nternions\nterns\nterpene\nterpeneless\nterpenes\nterpenic\nterpenoid\nterpenoids\nterpineol\nterpineols\nterpinol\nterpinols\nterpolymer\nterpolymers\nterpsichorean\nterra\nterrace\nterraced\nterraces\nterracing\nterrae\nterraform\nterraformed\nterraforming\nterraforms\nterrain\nterrains\nterrane\nterranes\nterrapin\nterrapins\nterraqueous\nterraria\nterrarium\nterrariums\nterras\nterrases\nterrazzo\nterrazzos\nterreen\nterreens\nterrella\nterrellas\nterrene\nterrenes\nterreplein\nterrepleins\nterrestrial\nterrestrially\nterrestrials\nterret\nterrets\nterrible\nterribleness\nterriblenesses\nterribly\nterricolous\nterrier\nterriers\nterries\nterrific\nterrifically\nterrified\nterrifies\nterrify\nterrifying\nterrifyingly\nterrigenous\nterrine\nterrines\nterrit\nterritorial\nterritorialism\nterritorialisms\nterritorialist\nterritorialists\nterritorialities\nterritoriality\nterritorialization\nterritorializations\nterritorialize\nterritorialized\nterritorializes\nterritorializing\nterritorially\nterritorials\nterritories\nterritory\nterrits\nterror\nterrorise\nterrorised\nterrorises\nterrorising\nterrorism\nterrorisms\nterrorist\nterroristic\nterrorists\nterrorization\nterrorizations\nterrorize\nterrorized\nterrorizes\nterrorizing\nterrorless\nterrors\nterry\nterse\ntersely\nterseness\ntersenesses\nterser\ntersest\ntertial\ntertials\ntertian\ntertians\ntertiaries\ntertiary\ntervalent\ntesla\nteslas\ntessellate\ntessellated\ntessellates\ntessellating\ntessellation\ntessellations\ntessera\ntesseract\ntesseracts\ntesserae\ntessitura\ntessituras\ntessiture\ntest\ntesta\ntestabilities\ntestability\ntestable\ntestaceous\ntestacies\ntestacy\ntestae\ntestament\ntestamentary\ntestaments\ntestate\ntestates\ntestator\ntestators\ntestatrices\ntestatrix\ntestatrixes\ntestcross\ntestcrossed\ntestcrosses\ntestcrossing\ntested\ntestee\ntestees\ntester\ntesters\ntestes\ntesticle\ntesticles\ntesticular\ntestier\ntestiest\ntestified\ntestifier\ntestifiers\ntestifies\ntestify\ntestifying\ntestily\ntestimonial\ntestimonials\ntestimonies\ntestimony\ntestiness\ntestinesses\ntesting\ntestis\nteston\ntestons\ntestoon\ntestoons\ntestosterone\ntestosterones\ntests\ntestudines\ntestudo\ntestudos\ntesty\ntet\ntetanal\ntetanic\ntetanically\ntetanics\ntetanies\ntetanise\ntetanised\ntetanises\ntetanising\ntetanization\ntetanizations\ntetanize\ntetanized\ntetanizes\ntetanizing\ntetanoid\ntetanus\ntetanuses\ntetany\ntetartohedral\ntetched\ntetchier\ntetchiest\ntetchily\ntetchiness\ntetchinesses\ntetchy\nteth\ntether\ntetherball\ntetherballs\ntethered\ntethering\ntethers\nteths\ntetotum\ntetotums\ntetra\ntetracaine\ntetracaines\ntetrachloride\ntetrachlorides\ntetrachord\ntetrachords\ntetracid\ntetracids\ntetracycline\ntetracyclines\ntetrad\ntetradic\ntetradrachm\ntetradrachms\ntetrads\ntetradynamous\ntetrafluoride\ntetrafluorides\ntetragon\ntetragonal\ntetragonally\ntetragons\ntetragrammaton\ntetragrammatons\ntetrahedra\ntetrahedral\ntetrahedrally\ntetrahedrite\ntetrahedrites\ntetrahedron\ntetrahedrons\ntetrahydrocannabinol\ntetrahydrocannabinols\ntetrahydrofuran\ntetrahydrofurans\ntetrahymena\ntetrahymenas\ntetralogies\ntetralogy\ntetramer\ntetrameric\ntetramerous\ntetramers\ntetrameter\ntetrameters\ntetramethyllead\ntetramethylleads\ntetraploid\ntetraploidies\ntetraploids\ntetraploidy\ntetrapod\ntetrapods\ntetrapyrrole\ntetrapyrroles\ntetrarch\ntetrarchic\ntetrarchies\ntetrarchs\ntetrarchy\ntetras\ntetraspore\ntetraspores\ntetrasporic\ntetravalent\ntetrazolium\ntetrazoliums\ntetrazzini\ntetrode\ntetrodes\ntetrodotoxin\ntetrodotoxins\ntetroxid\ntetroxide\ntetroxides\ntetroxids\ntetryl\ntetryls\ntets\ntetter\ntetters\nteuch\nteugh\nteughly\nteutonize\nteutonized\nteutonizes\nteutonizing\ntew\ntewed\ntewing\ntews\ntexas\ntexases\ntext\ntextbook\ntextbookish\ntextbooks\ntextile\ntextiles\ntextless\ntexts\ntextual\ntextually\ntextuaries\ntextuary\ntextural\ntexturally\ntexture\ntextured\ntextureless\ntextures\ntexturing\ntexturize\ntexturized\ntexturizes\ntexturizing\nthack\nthacked\nthacking\nthacks\nthae\nthairm\nthairms\nthalami\nthalamic\nthalamus\nthalassaemia\nthalassaemias\nthalassemia\nthalassemias\nthalassemic\nthalassemics\nthalassic\nthalassocracies\nthalassocracy\nthalassocrat\nthalassocrats\nthaler\nthalers\nthalidomide\nthalidomides\nthalli\nthallic\nthallium\nthalliums\nthalloid\nthallophyte\nthallophytes\nthallophytic\nthallous\nthallus\nthalluses\nthan\nthanage\nthanages\nthanatological\nthanatologies\nthanatologist\nthanatologists\nthanatology\nthanatos\nthanatoses\nthane\nthanes\nthaneship\nthaneships\nthank\nthanked\nthanker\nthankers\nthankful\nthankfuller\nthankfullest\nthankfully\nthankfulness\nthankfulnesses\nthanking\nthankless\nthanklessly\nthanklessness\nthanklessnesses\nthanks\nthanksgiving\nthanksgivings\nthankworthy\ntharm\ntharms\nthat\nthataway\nthatch\nthatched\nthatcher\nthatchers\nthatches\nthatchier\nthatchiest\nthatching\nthatchy\nthaumaturge\nthaumaturges\nthaumaturgic\nthaumaturgies\nthaumaturgist\nthaumaturgists\nthaumaturgy\nthaw\nthawed\nthawer\nthawers\nthawing\nthawless\nthaws\nthe\nthearchies\nthearchy\ntheater\ntheatergoer\ntheatergoers\ntheatergoing\ntheatergoings\ntheaters\ntheatre\ntheatres\ntheatric\ntheatrical\ntheatricalism\ntheatricalisms\ntheatricalities\ntheatricality\ntheatricalization\ntheatricalizations\ntheatricalize\ntheatricalized\ntheatricalizes\ntheatricalizing\ntheatrically\ntheatricals\ntheatrics\nthebaine\nthebaines\nthebe\nthebes\ntheca\nthecae\nthecal\nthecate\nthecodont\nthecodonts\nthee\ntheelin\ntheelins\ntheelol\ntheelols\ntheft\nthefts\nthegn\nthegnly\nthegns\nthein\ntheine\ntheines\ntheins\ntheir\ntheirs\ntheirselves\ntheism\ntheisms\ntheist\ntheistic\ntheistical\ntheistically\ntheists\nthelitis\nthelitises\nthem\nthematic\nthematically\nthematics\ntheme\nthemed\nthemes\ntheming\nthemselves\nthen\nthenage\nthenages\nthenal\nthenar\nthenars\nthence\nthenceforth\nthenceforward\nthenceforwards\nthens\ntheobromine\ntheobromines\ntheocentric\ntheocentricities\ntheocentricity\ntheocentrism\ntheocentrisms\ntheocracies\ntheocracy\ntheocrat\ntheocratic\ntheocratical\ntheocratically\ntheocrats\ntheodicies\ntheodicy\ntheodolite\ntheodolites\ntheogonic\ntheogonies\ntheogony\ntheolog\ntheologian\ntheologians\ntheologic\ntheological\ntheologically\ntheologies\ntheologise\ntheologised\ntheologises\ntheologising\ntheologize\ntheologized\ntheologizer\ntheologizers\ntheologizes\ntheologizing\ntheologs\ntheologue\ntheologues\ntheology\ntheonomies\ntheonomous\ntheonomy\ntheophanic\ntheophanies\ntheophany\ntheophylline\ntheophyllines\ntheorbo\ntheorbos\ntheorem\ntheorematic\ntheorems\ntheoretic\ntheoretical\ntheoretically\ntheoretician\ntheoreticians\ntheories\ntheorise\ntheorised\ntheorises\ntheorising\ntheorist\ntheorists\ntheorization\ntheorizations\ntheorize\ntheorized\ntheorizer\ntheorizers\ntheorizes\ntheorizing\ntheory\ntheosophical\ntheosophically\ntheosophies\ntheosophist\ntheosophists\ntheosophy\ntherapeuses\ntherapeusis\ntherapeutic\ntherapeutically\ntherapeutics\ntherapies\ntherapist\ntherapists\ntherapsid\ntherapsids\ntherapy\nthere\nthereabout\nthereabouts\nthereafter\nthereat\nthereby\ntherefor\ntherefore\ntherefrom\ntherein\nthereinafter\nthereinto\ntheremin\ntheremins\nthereof\nthereon\ntheres\nthereto\ntheretofore\nthereunder\nthereunto\nthereupon\ntherewith\ntherewithal\ntheriac\ntheriaca\ntheriacal\ntheriacas\ntheriacs\ntheriomorphic\ntherm\nthermae\nthermal\nthermalization\nthermalizations\nthermalize\nthermalized\nthermalizes\nthermalizing\nthermally\nthermals\ntherme\nthermel\nthermels\nthermes\nthermic\nthermically\nthermion\nthermionic\nthermionics\nthermions\nthermistor\nthermistors\nthermite\nthermites\nthermochemical\nthermochemist\nthermochemistries\nthermochemistry\nthermochemists\nthermocline\nthermoclines\nthermocouple\nthermocouples\nthermoduric\nthermodynamic\nthermodynamical\nthermodynamically\nthermodynamicist\nthermodynamicists\nthermodynamics\nthermoelectric\nthermoelectricities\nthermoelectricity\nthermoelement\nthermoelements\nthermoform\nthermoformable\nthermoformed\nthermoforming\nthermoforms\nthermogram\nthermograms\nthermograph\nthermographic\nthermographically\nthermographies\nthermographs\nthermography\nthermohaline\nthermojunction\nthermojunctions\nthermolabile\nthermolabilities\nthermolability\nthermoluminescence\nthermoluminescences\nthermoluminescent\nthermomagnetic\nthermometer\nthermometers\nthermometric\nthermometrically\nthermometries\nthermometry\nthermonuclear\nthermoperiodicities\nthermoperiodicity\nthermoperiodism\nthermoperiodisms\nthermophile\nthermophiles\nthermophilic\nthermophilous\nthermopile\nthermopiles\nthermoplastic\nthermoplasticities\nthermoplasticity\nthermoplastics\nthermoreceptor\nthermoreceptors\nthermoregulate\nthermoregulated\nthermoregulates\nthermoregulating\nthermoregulation\nthermoregulations\nthermoregulator\nthermoregulators\nthermoregulatory\nthermoremanence\nthermoremanences\nthermoremanent\nthermos\nthermoscope\nthermoscopes\nthermoses\nthermoset\nthermosets\nthermosetting\nthermosphere\nthermospheres\nthermospheric\nthermostabilities\nthermostability\nthermostable\nthermostat\nthermostated\nthermostatic\nthermostatically\nthermostating\nthermostats\nthermostatted\nthermostatting\nthermotactic\nthermotaxes\nthermotaxis\nthermotropic\nthermotropism\nthermotropisms\ntherms\ntheroid\ntheropod\ntheropods\nthesaural\nthesauri\nthesaurus\nthesauruses\nthese\ntheses\nthesis\nthespian\nthespians\ntheta\nthetas\nthetic\nthetical\nthetically\ntheurgic\ntheurgical\ntheurgies\ntheurgist\ntheurgists\ntheurgy\nthew\nthewier\nthewiest\nthewless\nthews\nthewy\nthey\nthiabendazole\nthiabendazoles\nthiamin\nthiaminase\nthiaminases\nthiamine\nthiamines\nthiamins\nthiazide\nthiazides\nthiazin\nthiazine\nthiazines\nthiazins\nthiazol\nthiazole\nthiazoles\nthiazols\nthick\nthicken\nthickened\nthickener\nthickeners\nthickening\nthickenings\nthickens\nthicker\nthickest\nthicket\nthicketed\nthickets\nthickety\nthickhead\nthickheaded\nthickheads\nthickish\nthickly\nthickness\nthicknesses\nthicks\nthickset\nthicksets\nthief\nthieve\nthieved\nthieveries\nthievery\nthieves\nthieving\nthievish\nthievishly\nthievishness\nthievishnesses\nthigh\nthighbone\nthighbones\nthighed\nthighs\nthigmotaxes\nthigmotaxis\nthigmotropism\nthigmotropisms\nthill\nthills\nthimble\nthimbleberries\nthimbleberry\nthimbleful\nthimblefuls\nthimblerig\nthimblerigged\nthimblerigger\nthimbleriggers\nthimblerigging\nthimblerigs\nthimbles\nthimbleweed\nthimbleweeds\nthimerosal\nthimerosals\nthin\nthinclad\nthinclads\nthindown\nthindowns\nthine\nthing\nthingamabob\nthingamabobs\nthingamajig\nthingamajigs\nthingness\nthingnesses\nthings\nthingumajig\nthingumajigs\nthingummies\nthingummy\nthink\nthinkable\nthinkableness\nthinkablenesses\nthinkably\nthinker\nthinkers\nthinking\nthinkingly\nthinkingness\nthinkingnesses\nthinkings\nthinks\nthinly\nthinned\nthinner\nthinners\nthinness\nthinnesses\nthinnest\nthinning\nthinnish\nthins\nthio\nthiocyanate\nthiocyanates\nthiol\nthiolic\nthiols\nthionate\nthionates\nthionic\nthionin\nthionine\nthionines\nthionins\nthionyl\nthionyls\nthiopental\nthiopentals\nthiophen\nthiophene\nthiophenes\nthiophens\nthioridazine\nthioridazines\nthiosulfate\nthiosulfates\nthiotepa\nthiotepas\nthiouracil\nthiouracils\nthiourea\nthioureas\nthir\nthiram\nthirams\nthird\nthirdhand\nthirdly\nthirds\nthirl\nthirlage\nthirlages\nthirled\nthirling\nthirls\nthirst\nthirsted\nthirster\nthirsters\nthirstier\nthirstiest\nthirstily\nthirstiness\nthirstinesses\nthirsting\nthirsts\nthirsty\nthirteen\nthirteens\nthirteenth\nthirteenths\nthirties\nthirtieth\nthirtieths\nthirty\nthirtyish\nthis\nthistle\nthistledown\nthistledowns\nthistles\nthistlier\nthistliest\nthistly\nthither\nthitherto\nthitherward\nthitherwards\nthixotropic\nthixotropies\nthixotropy\ntho\nthole\ntholed\ntholeiite\ntholeiites\ntholeiitic\ntholepin\ntholepins\ntholes\ntholing\ntholoi\ntholos\nthong\nthonged\nthongs\nthoracal\nthoraces\nthoracic\nthoracically\nthoracotomies\nthoracotomy\nthorax\nthoraxes\nthoria\nthorianite\nthorianites\nthorias\nthoric\nthorite\nthorites\nthorium\nthoriums\nthorn\nthornback\nthornbacks\nthornbush\nthornbushes\nthorned\nthornier\nthorniest\nthornily\nthorniness\nthorninesses\nthorning\nthornless\nthornlike\nthorns\nthorny\nthoro\nthoron\nthorons\nthorough\nthoroughbass\nthoroughbasses\nthoroughbrace\nthoroughbraces\nthoroughbred\nthoroughbreds\nthorougher\nthoroughest\nthoroughfare\nthoroughfares\nthoroughgoing\nthoroughly\nthoroughness\nthoroughnesses\nthoroughpin\nthoroughpins\nthoroughwort\nthoroughworts\nthorp\nthorpe\nthorpes\nthorps\nthose\nthou\nthoued\nthough\nthought\nthoughtful\nthoughtfully\nthoughtfulness\nthoughtfulnesses\nthoughtless\nthoughtlessly\nthoughtlessness\nthoughtlessnesses\nthoughts\nthoughtway\nthoughtways\nthouing\nthous\nthousand\nthousandfold\nthousands\nthousandth\nthousandths\nthowless\nthraldom\nthraldoms\nthrall\nthralldom\nthralldoms\nthralled\nthralling\nthralls\nthrash\nthrashed\nthrasher\nthrashers\nthrashes\nthrashing\nthrashings\nthrasonical\nthrasonically\nthrave\nthraves\nthraw\nthrawart\nthrawed\nthrawing\nthrawn\nthrawnly\nthraws\nthread\nthreadbare\nthreadbareness\nthreadbarenesses\nthreaded\nthreader\nthreaders\nthreadfin\nthreadfins\nthreadier\nthreadiest\nthreadiness\nthreadinesses\nthreading\nthreadless\nthreadlike\nthreads\nthreadworm\nthreadworms\nthready\nthreap\nthreaped\nthreaper\nthreapers\nthreaping\nthreaps\nthreat\nthreated\nthreaten\nthreatened\nthreatener\nthreateners\nthreatening\nthreateningly\nthreatens\nthreating\nthreats\nthree\nthreefold\nthreep\nthreeped\nthreepence\nthreepences\nthreepenny\nthreeping\nthreeps\nthrees\nthreescore\nthreesome\nthreesomes\nthrenode\nthrenodes\nthrenodic\nthrenodies\nthrenodist\nthrenodists\nthrenody\nthreonine\nthreonines\nthresh\nthreshed\nthresher\nthreshers\nthreshes\nthreshing\nthreshold\nthresholds\nthrew\nthrice\nthrift\nthriftier\nthriftiest\nthriftily\nthriftiness\nthriftinesses\nthriftless\nthriftlessly\nthriftlessness\nthriftlessnesses\nthrifts\nthrifty\nthrill\nthrilled\nthriller\nthrillers\nthrilling\nthrillingly\nthrills\nthrip\nthrips\nthrive\nthrived\nthriven\nthriver\nthrivers\nthrives\nthriving\nthrivingly\nthro\nthroat\nthroated\nthroatier\nthroatiest\nthroatily\nthroatiness\nthroatinesses\nthroating\nthroatlatch\nthroatlatches\nthroats\nthroaty\nthrob\nthrobbed\nthrobber\nthrobbers\nthrobbing\nthrobs\nthroe\nthroes\nthrombi\nthrombin\nthrombins\nthrombocyte\nthrombocytes\nthrombocytic\nthrombocytopenia\nthrombocytopenias\nthrombocytopenic\nthromboembolic\nthromboembolism\nthromboembolisms\nthrombokinase\nthrombokinases\nthrombolytic\nthrombophlebitides\nthrombophlebitis\nthromboplastic\nthromboplastin\nthromboplastins\nthromboses\nthrombosis\nthrombotic\nthromboxane\nthromboxanes\nthrombus\nthrone\nthroned\nthrones\nthrong\nthronged\nthronging\nthrongs\nthroning\nthrostle\nthrostles\nthrottle\nthrottleable\nthrottled\nthrottlehold\nthrottleholds\nthrottler\nthrottlers\nthrottles\nthrottling\nthrough\nthroughither\nthroughly\nthroughother\nthroughout\nthroughput\nthroughputs\nthroughway\nthroughways\nthrove\nthrow\nthrowaway\nthrowaways\nthrowback\nthrowbacks\nthrower\nthrowers\nthrowing\nthrown\nthrows\nthrowster\nthrowsters\nthru\nthrum\nthrummed\nthrummer\nthrummers\nthrummier\nthrummiest\nthrumming\nthrummy\nthrums\nthruput\nthruputs\nthrush\nthrushes\nthrust\nthrusted\nthruster\nthrusters\nthrustful\nthrusting\nthrustor\nthrustors\nthrusts\nthruway\nthruways\nthud\nthudded\nthudding\nthuds\nthug\nthuggee\nthuggees\nthuggeries\nthuggery\nthuggish\nthugs\nthuja\nthujas\nthulia\nthulias\nthulium\nthuliums\nthumb\nthumbed\nthumbhole\nthumbholes\nthumbing\nthumbkin\nthumbkins\nthumbnail\nthumbnails\nthumbnut\nthumbnuts\nthumbprint\nthumbprints\nthumbs\nthumbscrew\nthumbscrews\nthumbsucker\nthumbsuckers\nthumbtack\nthumbtacked\nthumbtacking\nthumbtacks\nthumbwheel\nthumbwheels\nthump\nthumped\nthumper\nthumpers\nthumping\nthumps\nthunder\nthunderbird\nthunderbirds\nthunderbolt\nthunderbolts\nthunderclap\nthunderclaps\nthundercloud\nthunderclouds\nthundered\nthunderer\nthunderers\nthunderhead\nthunderheads\nthundering\nthunderingly\nthunderous\nthunderously\nthunders\nthundershower\nthundershowers\nthunderstone\nthunderstones\nthunderstorm\nthunderstorms\nthunderstricken\nthunderstrike\nthunderstrikes\nthunderstriking\nthunderstroke\nthunderstrokes\nthunderstruck\nthundery\nthunk\nthunked\nthunking\nthunks\nthurible\nthuribles\nthurifer\nthurifers\nthurl\nthurls\nthus\nthusly\nthuya\nthuyas\nthwack\nthwacked\nthwacker\nthwackers\nthwacking\nthwacks\nthwart\nthwarted\nthwarter\nthwarters\nthwarting\nthwartly\nthwarts\nthwartwise\nthy\nthylacine\nthylacines\nthylakoid\nthylakoids\nthyme\nthymectomies\nthymectomize\nthymectomized\nthymectomizes\nthymectomizing\nthymectomy\nthymes\nthymey\nthymi\nthymic\nthymidine\nthymidines\nthymier\nthymiest\nthymine\nthymines\nthymocyte\nthymocytes\nthymol\nthymols\nthymosin\nthymosins\nthymus\nthymuses\nthymy\nthyratron\nthyratrons\nthyreoid\nthyristor\nthyristors\nthyrocalcitonin\nthyrocalcitonins\nthyroglobulin\nthyroglobulins\nthyroid\nthyroidal\nthyroidectomies\nthyroidectomized\nthyroidectomy\nthyroiditis\nthyroiditises\nthyroids\nthyrotoxicoses\nthyrotoxicosis\nthyrotrophic\nthyrotrophin\nthyrotrophins\nthyrotropic\nthyrotropin\nthyrotropins\nthyroxin\nthyroxine\nthyroxines\nthyroxins\nthyrse\nthyrses\nthyrsi\nthyrsoid\nthyrsus\nthysanuran\nthysanurans\nthyself\nti\ntiara\ntiaraed\ntiaras\ntibia\ntibiae\ntibial\ntibias\ntibiofibula\ntibiofibulae\ntibiofibulas\ntic\ntical\nticals\ntick\nticked\nticker\ntickers\nticket\nticketed\nticketing\nticketless\ntickets\nticking\ntickings\ntickle\ntickled\ntickler\nticklers\ntickles\ntickling\nticklish\nticklishly\nticklishness\nticklishnesses\nticks\ntickseed\ntickseeds\nticktack\nticktacked\nticktacking\nticktacks\nticktacktoe\nticktacktoes\nticktock\nticktocked\nticktocking\nticktocks\ntics\ntictac\ntictacked\ntictacking\ntictacs\ntictoc\ntictocked\ntictocking\ntictocs\ntidal\ntidally\ntidbit\ntidbits\ntiddledywinks\ntiddler\ntiddlers\ntiddly\ntiddlywinks\ntide\ntided\ntideland\ntidelands\ntideless\ntidelike\ntidemark\ntidemarks\ntiderip\ntiderips\ntides\ntidewater\ntidewaters\ntideway\ntideways\ntidied\ntidier\ntidiers\ntidies\ntidiest\ntidily\ntidiness\ntidinesses\ntiding\ntidings\ntidy\ntidying\ntidytips\ntie\ntieback\ntiebacks\ntiebreaker\ntiebreakers\ntiebreaking\ntieclasp\ntieclasps\ntied\ntieing\ntieless\ntiemannite\ntiemannites\ntiepin\ntiepins\ntier\ntierce\ntierced\ntiercel\ntiercels\ntierces\ntiered\ntiering\ntiers\nties\ntiff\ntiffanies\ntiffany\ntiffed\ntiffin\ntiffined\ntiffing\ntiffining\ntiffins\ntiffs\ntiger\ntigereye\ntigereyes\ntigerish\ntigerishly\ntigerishness\ntigerishnesses\ntigerlike\ntigers\ntight\ntighten\ntightened\ntightener\ntighteners\ntightening\ntightens\ntighter\ntightest\ntightfisted\ntightfistedness\ntightfistednesses\ntightly\ntightness\ntightnesses\ntightrope\ntightropes\ntights\ntightwad\ntightwads\ntightwire\ntightwires\ntiglon\ntiglons\ntigon\ntigons\ntigress\ntigresses\ntigrish\ntike\ntikes\ntiki\ntikis\ntil\ntilak\ntilaks\ntilapia\ntilapias\ntilburies\ntilbury\ntilde\ntildes\ntile\ntiled\ntilefish\ntilefishes\ntilelike\ntiler\ntilers\ntiles\ntiling\ntilings\ntill\ntillable\ntillage\ntillages\ntillandsia\ntillandsias\ntilled\ntiller\ntillered\ntillering\ntillerman\ntillermen\ntillers\ntilling\ntillite\ntillites\ntills\ntils\ntilt\ntiltable\ntilted\ntilter\ntilters\ntilth\ntilths\ntilting\ntiltmeter\ntiltmeters\ntilts\ntiltyard\ntiltyards\ntimarau\ntimaraus\ntimbal\ntimbale\ntimbales\ntimbals\ntimber\ntimberdoodle\ntimberdoodles\ntimbered\ntimberhead\ntimberheads\ntimbering\ntimberings\ntimberland\ntimberlands\ntimberline\ntimberlines\ntimberman\ntimbermen\ntimbers\ntimberwork\ntimberworks\ntimbral\ntimbre\ntimbrel\ntimbrelled\ntimbrels\ntimbres\ntime\ntimecard\ntimecards\ntimed\ntimekeeper\ntimekeepers\ntimekeeping\ntimekeepings\ntimeless\ntimelessly\ntimelessness\ntimelessnesses\ntimelier\ntimeliest\ntimeline\ntimelines\ntimeliness\ntimelinesses\ntimely\ntimeous\ntimeously\ntimeout\ntimeouts\ntimepiece\ntimepieces\ntimepleaser\ntimepleasers\ntimer\ntimers\ntimes\ntimesaver\ntimesavers\ntimesaving\ntimescale\ntimescales\ntimeserver\ntimeservers\ntimeserving\ntimeservings\ntimetable\ntimetables\ntimework\ntimeworker\ntimeworkers\ntimeworks\ntimeworn\ntimid\ntimider\ntimidest\ntimidities\ntimidity\ntimidly\ntimidness\ntimidnesses\ntiming\ntimings\ntimocracies\ntimocracy\ntimocratic\ntimocratical\ntimolol\ntimolols\ntimorous\ntimorously\ntimorousness\ntimorousnesses\ntimothies\ntimothy\ntimpana\ntimpani\ntimpanist\ntimpanists\ntimpano\ntimpanum\ntimpanums\ntin\ntinamou\ntinamous\ntincal\ntincals\ntinct\ntincted\ntincting\ntinctorial\ntinctorially\ntincts\ntincture\ntinctured\ntinctures\ntincturing\ntinder\ntinderbox\ntinderboxes\ntinders\ntindery\ntine\ntinea\ntineal\ntineas\ntined\ntineid\ntineids\ntines\ntinfoil\ntinfoils\ntinful\ntinfuls\nting\ntinge\ntinged\ntingeing\ntinges\ntinging\ntingle\ntingled\ntingler\ntinglers\ntingles\ntinglier\ntingliest\ntingling\ntinglingly\ntingly\ntings\ntinhorn\ntinhorns\ntinier\ntiniest\ntinily\ntininess\ntininesses\ntining\ntinker\ntinkered\ntinkerer\ntinkerers\ntinkering\ntinkers\ntinkle\ntinkled\ntinkler\ntinklers\ntinkles\ntinklier\ntinkliest\ntinkling\ntinklings\ntinkly\ntinlike\ntinman\ntinmen\ntinned\ntinner\ntinners\ntinnier\ntinniest\ntinnily\ntinniness\ntinninesses\ntinning\ntinnitus\ntinnituses\ntinny\ntinplate\ntinplates\ntins\ntinsel\ntinseled\ntinseling\ntinselled\ntinselling\ntinselly\ntinsels\ntinsmith\ntinsmithing\ntinsmithings\ntinsmiths\ntinstone\ntinstones\ntint\ntinted\ntinter\ntinters\ntinting\ntintings\ntintinnabulary\ntintinnabulation\ntintinnabulations\ntintless\ntints\ntintype\ntintypes\ntinware\ntinwares\ntinwork\ntinworks\ntiny\ntip\ntipcart\ntipcarts\ntipcat\ntipcats\ntipi\ntipis\ntipless\ntipoff\ntipoffs\ntippable\ntipped\ntipper\ntippers\ntippet\ntippets\ntippier\ntippiest\ntipping\ntipple\ntippled\ntippler\ntipplers\ntipples\ntippling\ntippy\ntippytoe\ntippytoed\ntippytoeing\ntippytoes\ntips\ntipsier\ntipsiest\ntipsily\ntipsiness\ntipsinesses\ntipstaff\ntipstaffs\ntipstaves\ntipster\ntipsters\ntipstock\ntipstocks\ntipsy\ntiptoe\ntiptoed\ntiptoeing\ntiptoes\ntiptop\ntiptops\ntirade\ntirades\ntiramisu\ntiramisus\ntire\ntired\ntireder\ntiredest\ntiredly\ntiredness\ntirednesses\ntireless\ntirelessly\ntirelessness\ntirelessnesses\ntires\ntiresome\ntiresomely\ntiresomeness\ntiresomenesses\ntiring\ntirl\ntirled\ntirling\ntirls\ntiro\ntiros\ntirrivee\ntirrivees\ntis\ntisane\ntisanes\ntissual\ntissue\ntissued\ntissues\ntissuey\ntissuing\ntissular\ntit\ntitan\ntitanate\ntitanates\ntitaness\ntitanesses\ntitania\ntitanias\ntitanic\ntitanically\ntitaniferous\ntitanism\ntitanisms\ntitanite\ntitanites\ntitanium\ntitaniums\ntitanous\ntitans\ntitbit\ntitbits\ntiter\ntiters\ntitfer\ntitfers\ntithable\ntithe\ntithed\ntither\ntithers\ntithes\ntithing\ntithings\ntithonia\ntithonias\ntiti\ntitian\ntitians\ntitillate\ntitillated\ntitillates\ntitillating\ntitillatingly\ntitillation\ntitillations\ntitillative\ntitis\ntitivate\ntitivated\ntitivates\ntitivating\ntitivation\ntitivations\ntitlark\ntitlarks\ntitle\ntitled\ntitleholder\ntitleholders\ntitles\ntitling\ntitlist\ntitlists\ntitman\ntitmen\ntitmice\ntitmouse\ntitrable\ntitrant\ntitrants\ntitratable\ntitrate\ntitrated\ntitrates\ntitrating\ntitration\ntitrations\ntitrator\ntitrators\ntitre\ntitres\ntitrimetric\ntits\ntitter\ntittered\ntitterer\ntitterers\ntittering\ntitters\ntittie\ntitties\ntittivate\ntittivated\ntittivates\ntittivating\ntittle\ntittles\ntittup\ntittuped\ntittuping\ntittupped\ntittupping\ntittuppy\ntittups\ntitty\ntitular\ntitularies\ntitularly\ntitulars\ntitulary\ntivy\ntizzies\ntizzy\ntmeses\ntmesis\nto\ntoad\ntoadeater\ntoadeaters\ntoadfish\ntoadfishes\ntoadflax\ntoadflaxes\ntoadied\ntoadies\ntoadish\ntoadless\ntoadlike\ntoads\ntoadstone\ntoadstones\ntoadstool\ntoadstools\ntoady\ntoadying\ntoadyish\ntoadyism\ntoadyisms\ntoast\ntoasted\ntoaster\ntoasters\ntoastier\ntoastiest\ntoasting\ntoastmaster\ntoastmasters\ntoastmistress\ntoastmistresses\ntoasts\ntoasty\ntobacco\ntobaccoes\ntobacconist\ntobacconists\ntobaccos\ntobies\ntoboggan\ntobogganed\ntobogganer\ntobogganers\ntobogganing\ntobogganings\ntobogganist\ntobogganists\ntoboggans\ntoby\ntoccata\ntoccatas\ntoccate\ntocher\ntochered\ntochering\ntochers\ntocologies\ntocology\ntocopherol\ntocopherols\ntocsin\ntocsins\ntod\ntoday\ntodays\ntoddies\ntoddle\ntoddled\ntoddler\ntoddlerhood\ntoddlerhoods\ntoddlers\ntoddles\ntoddling\ntoddy\ntodies\ntods\ntody\ntoe\ntoea\ntoeas\ntoecap\ntoecaps\ntoed\ntoehold\ntoeholds\ntoeing\ntoeless\ntoelike\ntoenail\ntoenailed\ntoenailing\ntoenails\ntoepiece\ntoepieces\ntoeplate\ntoeplates\ntoes\ntoeshoe\ntoeshoes\ntoff\ntoffee\ntoffees\ntoffies\ntoffs\ntoffy\ntoft\ntofts\ntofu\ntofus\ntog\ntoga\ntogae\ntogaed\ntogas\ntogate\ntogated\ntogether\ntogetherness\ntogethernesses\ntogged\ntoggeries\ntoggery\ntogging\ntoggle\ntoggled\ntoggler\ntogglers\ntoggles\ntoggling\ntogs\ntogue\ntogues\ntoil\ntoile\ntoiled\ntoiler\ntoilers\ntoiles\ntoilet\ntoileted\ntoileting\ntoiletries\ntoiletry\ntoilets\ntoilette\ntoilettes\ntoilful\ntoilfully\ntoiling\ntoils\ntoilsome\ntoilsomely\ntoilsomeness\ntoilsomenesses\ntoilworn\ntoit\ntoited\ntoiting\ntoits\ntokamak\ntokamaks\ntokay\ntokays\ntoke\ntoked\ntoken\ntokened\ntokening\ntokenism\ntokenisms\ntokens\ntoker\ntokers\ntokes\ntoking\ntokologies\ntokology\ntokomak\ntokomaks\ntokonoma\ntokonomas\ntola\ntolan\ntolane\ntolanes\ntolans\ntolar\ntolarjev\ntolars\ntolas\ntolbooth\ntolbooths\ntolbutamide\ntolbutamides\ntold\ntole\ntoled\ntoledo\ntoledos\ntolerabilities\ntolerability\ntolerable\ntolerably\ntolerance\ntolerances\ntolerant\ntolerantly\ntolerate\ntolerated\ntolerates\ntolerating\ntoleration\ntolerations\ntolerative\ntolerator\ntolerators\ntoles\ntolidin\ntolidine\ntolidines\ntolidins\ntoling\ntoll\ntollage\ntollages\ntollbar\ntollbars\ntollbooth\ntollbooths\ntolled\ntoller\ntollers\ntollgate\ntollgates\ntollhouse\ntollhouses\ntolling\ntollman\ntollmen\ntolls\ntollway\ntollways\ntolu\ntoluate\ntoluates\ntoluene\ntoluenes\ntoluic\ntoluid\ntoluide\ntoluides\ntoluidin\ntoluidine\ntoluidines\ntoluidins\ntoluids\ntoluol\ntoluole\ntoluoles\ntoluols\ntolus\ntoluyl\ntoluyls\ntolyl\ntolyls\ntom\ntomahawk\ntomahawked\ntomahawking\ntomahawks\ntomalley\ntomalleys\ntoman\ntomans\ntomatillo\ntomatillos\ntomato\ntomatoes\ntomatoey\ntomb\ntombac\ntomback\ntombacks\ntombacs\ntombak\ntombaks\ntombal\ntombed\ntombing\ntombless\ntomblike\ntombola\ntombolas\ntombolo\ntombolos\ntomboy\ntomboyish\ntomboyishness\ntomboyishnesses\ntomboys\ntombs\ntombstone\ntombstones\ntomcat\ntomcats\ntomcatted\ntomcatting\ntomcod\ntomcods\ntome\ntomenta\ntomentose\ntomentum\ntomes\ntomfool\ntomfooleries\ntomfoolery\ntomfools\ntommed\ntommies\ntomming\ntommy\ntommyrot\ntommyrots\ntomogram\ntomograms\ntomographic\ntomographies\ntomography\ntomorrow\ntomorrows\ntompion\ntompions\ntoms\ntomtit\ntomtits\nton\ntonal\ntonalities\ntonality\ntonally\ntondi\ntondo\ntondos\ntone\ntonearm\ntonearms\ntoned\ntoneless\ntonelessly\ntonelessness\ntonelessnesses\ntoneme\ntonemes\ntonemic\ntoner\ntoners\ntones\ntonetic\ntonetically\ntonetics\ntonette\ntonettes\ntoney\ntong\ntonga\ntongas\ntonged\ntonger\ntongers\ntonging\ntongman\ntongmen\ntongs\ntongue\ntongued\ntongueless\ntonguelike\ntongues\ntonguing\ntonguings\ntonic\ntonically\ntonicities\ntonicity\ntonics\ntonier\ntoniest\ntonight\ntonights\ntoning\ntonish\ntonishly\ntonlet\ntonlets\ntonnage\ntonnages\ntonne\ntonneau\ntonneaus\ntonneaux\ntonner\ntonners\ntonnes\ntonnish\ntonometer\ntonometers\ntonometries\ntonometry\ntonoplast\ntonoplasts\ntons\ntonsil\ntonsilar\ntonsillar\ntonsillectomies\ntonsillectomy\ntonsillitis\ntonsillitises\ntonsils\ntonsorial\ntonsure\ntonsured\ntonsures\ntonsuring\ntontine\ntontines\ntonus\ntonuses\ntony\ntoo\ntook\ntool\ntoolbox\ntoolboxes\ntooled\ntooler\ntoolers\ntoolhead\ntoolheads\ntoolholder\ntoolholders\ntoolhouse\ntoolhouses\ntooling\ntoolings\ntoolless\ntoolmaker\ntoolmakers\ntoolmaking\ntoolmakings\ntoolroom\ntoolrooms\ntools\ntoolshed\ntoolsheds\ntoom\ntoon\ntoons\ntoot\ntooted\ntooter\ntooters\ntooth\ntoothache\ntoothaches\ntoothbrush\ntoothbrushes\ntoothbrushing\ntoothbrushings\ntoothed\ntoothier\ntoothiest\ntoothily\ntoothing\ntoothless\ntoothlike\ntoothpaste\ntoothpastes\ntoothpick\ntoothpicks\ntooths\ntoothsome\ntoothsomely\ntoothsomeness\ntoothsomenesses\ntoothwort\ntoothworts\ntoothy\ntooting\ntootle\ntootled\ntootler\ntootlers\ntootles\ntootling\ntoots\ntootses\ntootsie\ntootsies\ntootsy\ntop\ntopaz\ntopazes\ntopazine\ntopcoat\ntopcoats\ntopcross\ntopcrosses\ntopdressing\ntopdressings\ntope\ntoped\ntopee\ntopees\ntoper\ntopers\ntopes\ntopflight\ntopful\ntopfull\ntopgallant\ntopgallants\ntoph\ntophe\ntophes\ntophi\ntophs\ntophus\ntopi\ntopiaries\ntopiary\ntopic\ntopical\ntopicalities\ntopicality\ntopically\ntopics\ntoping\ntopis\ntopkick\ntopkicks\ntopknot\ntopknots\ntopless\ntoplessness\ntoplessnesses\ntopline\ntoplines\ntoploftical\ntoploftier\ntoploftiest\ntoploftily\ntoploftiness\ntoploftinesses\ntoplofty\ntopmast\ntopmasts\ntopminnow\ntopminnows\ntopmost\ntopnotch\ntopnotcher\ntopnotchers\ntopocentric\ntopographer\ntopographers\ntopographic\ntopographical\ntopographically\ntopographies\ntopography\ntopoi\ntopological\ntopologically\ntopologies\ntopologist\ntopologists\ntopology\ntoponym\ntoponymic\ntoponymical\ntoponymies\ntoponymist\ntoponymists\ntoponyms\ntoponymy\ntopos\ntopotype\ntopotypes\ntopped\ntopper\ntoppers\ntopping\ntoppings\ntopple\ntoppled\ntopples\ntoppling\ntops\ntopsail\ntopsails\ntopside\ntopsider\ntopsiders\ntopsides\ntopsoil\ntopsoiled\ntopsoiling\ntopsoils\ntopspin\ntopspins\ntopstitch\ntopstitched\ntopstitches\ntopstitching\ntopstone\ntopstones\ntopwork\ntopworked\ntopworking\ntopworks\ntoque\ntoques\ntoquet\ntoquets\ntor\ntora\ntorah\ntorahs\ntoras\ntorc\ntorch\ntorchbearer\ntorchbearers\ntorched\ntorchere\ntorcheres\ntorches\ntorchier\ntorchiers\ntorchiest\ntorching\ntorchlight\ntorchlights\ntorchon\ntorchons\ntorchwood\ntorchwoods\ntorchy\ntorcs\ntore\ntoreador\ntoreadors\ntorero\ntoreros\ntores\ntoreutic\ntoreutics\ntori\ntoric\ntories\ntorii\ntorment\ntormented\ntormenter\ntormenters\ntormentil\ntormentils\ntormenting\ntormentor\ntormentors\ntorments\ntorn\ntornadic\ntornado\ntornadoes\ntornados\ntornillo\ntornillos\ntoro\ntoroid\ntoroidal\ntoroidally\ntoroids\ntoros\ntorose\ntorosities\ntorosity\ntorot\ntoroth\ntorous\ntorpedo\ntorpedoed\ntorpedoes\ntorpedoing\ntorpedos\ntorpid\ntorpidities\ntorpidity\ntorpidly\ntorpids\ntorpor\ntorpors\ntorquate\ntorque\ntorqued\ntorquer\ntorquers\ntorques\ntorqueses\ntorquing\ntorr\ntorrefied\ntorrefies\ntorrefy\ntorrefying\ntorrent\ntorrential\ntorrentially\ntorrents\ntorrid\ntorrider\ntorridest\ntorridities\ntorridity\ntorridly\ntorridness\ntorridnesses\ntorrified\ntorrifies\ntorrify\ntorrifying\ntors\ntorsade\ntorsades\ntorse\ntorses\ntorsi\ntorsion\ntorsional\ntorsionally\ntorsions\ntorsk\ntorsks\ntorso\ntorsos\ntort\ntorte\ntortellini\ntortellinis\ntorten\ntortes\ntorticollis\ntorticollises\ntortile\ntortilla\ntortillas\ntortious\ntortiously\ntortoise\ntortoises\ntortoiseshell\ntortoiseshells\ntortoni\ntortonis\ntortricid\ntortricids\ntortrix\ntortrixes\ntorts\ntortuosities\ntortuosity\ntortuous\ntortuously\ntortuousness\ntortuousnesses\ntorture\ntortured\ntorturer\ntorturers\ntortures\ntorturing\ntorturous\ntorturously\ntorula\ntorulae\ntorulas\ntorus\ntory\ntosh\ntoshes\ntoss\ntossed\ntosser\ntossers\ntosses\ntossing\ntosspot\ntosspots\ntossup\ntossups\ntost\ntostada\ntostadas\ntostado\ntostados\ntot\ntotable\ntotal\ntotaled\ntotaling\ntotalisator\ntotalisators\ntotalise\ntotalised\ntotalises\ntotalising\ntotalism\ntotalisms\ntotalist\ntotalistic\ntotalists\ntotalitarian\ntotalitarianism\ntotalitarianisms\ntotalitarianize\ntotalitarianized\ntotalitarianizes\ntotalitarianizing\ntotalitarians\ntotalities\ntotality\ntotalizator\ntotalizators\ntotalize\ntotalized\ntotalizer\ntotalizers\ntotalizes\ntotalizing\ntotalled\ntotalling\ntotally\ntotals\ntote\ntoted\ntotem\ntotemic\ntotemism\ntotemisms\ntotemist\ntotemistic\ntotemists\ntotemite\ntotemites\ntotems\ntoter\ntoters\ntotes\ntother\ntoting\ntotipotencies\ntotipotency\ntotipotent\ntots\ntotted\ntotter\ntottered\ntotterer\ntotterers\ntottering\ntotteringly\ntotters\ntottery\ntotting\ntoucan\ntoucans\ntouch\ntouchable\ntouchback\ntouchbacks\ntouchdown\ntouchdowns\ntouche\ntouched\ntoucher\ntouchers\ntouches\ntouchhole\ntouchholes\ntouchier\ntouchiest\ntouchily\ntouchiness\ntouchinesses\ntouching\ntouchingly\ntouchline\ntouchlines\ntouchmark\ntouchmarks\ntouchstone\ntouchstones\ntouchup\ntouchups\ntouchwood\ntouchwoods\ntouchy\ntough\ntoughed\ntoughen\ntoughened\ntoughening\ntoughens\ntougher\ntoughest\ntoughie\ntoughies\ntoughing\ntoughish\ntoughly\ntoughness\ntoughnesses\ntoughs\ntoughy\ntoupee\ntoupees\ntour\ntouraco\ntouracos\ntourbillion\ntourbillions\ntourbillon\ntourbillons\ntoured\ntourer\ntourers\ntouring\ntourings\ntourism\ntourisms\ntourist\ntouristic\ntouristically\ntourists\ntouristy\ntourmaline\ntourmalines\ntournament\ntournaments\ntournedos\ntourney\ntourneyed\ntourneying\ntourneys\ntourniquet\ntourniquets\ntours\ntouse\ntoused\ntouses\ntousing\ntousle\ntousled\ntousles\ntousling\ntout\ntouted\ntouter\ntouters\ntouting\ntouts\ntouzle\ntouzled\ntouzles\ntouzling\ntovarich\ntovariches\ntovarish\ntovarishes\ntow\ntowage\ntowages\ntoward\ntowardliness\ntowardlinesses\ntowardly\ntowards\ntowaway\ntowaways\ntowboat\ntowboats\ntowed\ntowel\ntoweled\ntowelette\ntowelettes\ntoweling\ntowelings\ntowelled\ntowelling\ntowellings\ntowels\ntower\ntowered\ntowerier\ntoweriest\ntowering\ntoweringly\ntowerlike\ntowers\ntowery\ntowhead\ntowheaded\ntowheads\ntowhee\ntowhees\ntowie\ntowies\ntowing\ntowline\ntowlines\ntowmond\ntowmonds\ntowmont\ntowmonts\ntown\ntownee\ntownees\ntownfolk\ntownhome\ntownhomes\ntownhouse\ntownhouses\ntownie\ntownies\ntownish\ntownless\ntownlet\ntownlets\ntowns\ntownscape\ntownscapes\ntownsfolk\ntownship\ntownships\ntownsman\ntownsmen\ntownspeople\ntownswoman\ntownswomen\ntownwear\ntowny\ntowpath\ntowpaths\ntowrope\ntowropes\ntows\ntowy\ntoxaemia\ntoxaemias\ntoxaemic\ntoxaphene\ntoxaphenes\ntoxemia\ntoxemias\ntoxemic\ntoxic\ntoxical\ntoxicant\ntoxicants\ntoxicities\ntoxicity\ntoxicologic\ntoxicological\ntoxicologically\ntoxicologies\ntoxicologist\ntoxicologists\ntoxicology\ntoxicoses\ntoxicosis\ntoxics\ntoxigenic\ntoxigenicities\ntoxigenicity\ntoxin\ntoxine\ntoxines\ntoxins\ntoxoid\ntoxoids\ntoxophilies\ntoxophilite\ntoxophilites\ntoxophily\ntoxoplasma\ntoxoplasmas\ntoxoplasmic\ntoxoplasmoses\ntoxoplasmosis\ntoy\ntoyed\ntoyer\ntoyers\ntoying\ntoyish\ntoyless\ntoylike\ntoyo\ntoyon\ntoyons\ntoyos\ntoys\ntoyshop\ntoyshops\ntrabeate\ntrabeated\ntrabeation\ntrabeations\ntrabecula\ntrabeculae\ntrabecular\ntrabeculas\ntrabeculate\ntrace\ntraceabilities\ntraceability\ntraceable\ntraced\ntraceless\ntracer\ntraceried\ntraceries\ntracers\ntracery\ntraces\ntrachea\ntracheae\ntracheal\ntracheary\ntracheas\ntracheate\ntracheated\ntracheid\ntracheids\ntracheitis\ntracheitises\ntracheobronchial\ntracheolar\ntracheole\ntracheoles\ntracheophyte\ntracheophytes\ntracheostomies\ntracheostomy\ntracheotomies\ntracheotomy\ntrachle\ntrachled\ntrachles\ntrachling\ntrachoma\ntrachomas\ntrachyte\ntrachytes\ntrachytic\ntracing\ntracings\ntrack\ntrackage\ntrackages\ntrackball\ntrackballs\ntracked\ntracker\ntrackers\ntracking\ntrackings\ntracklayer\ntracklayers\ntracklaying\ntracklayings\ntrackless\ntrackman\ntrackmen\ntracks\ntrackside\ntracksides\ntracksuit\ntracksuits\ntrackwalker\ntrackwalkers\ntrackway\ntrackways\ntract\ntractabilities\ntractability\ntractable\ntractableness\ntractablenesses\ntractably\ntractate\ntractates\ntractile\ntraction\ntractional\ntractions\ntractive\ntractor\ntractors\ntracts\ntrad\ntradable\ntrade\ntradeable\ntradecraft\ntradecrafts\ntraded\ntrademark\ntrademarked\ntrademarking\ntrademarks\ntradeoff\ntradeoffs\ntrader\ntraders\ntrades\ntradescantia\ntradescantias\ntradesman\ntradesmen\ntradespeople\ntrading\ntradition\ntraditional\ntraditionalism\ntraditionalisms\ntraditionalist\ntraditionalistic\ntraditionalists\ntraditionalize\ntraditionalized\ntraditionalizes\ntraditionalizing\ntraditionally\ntraditionary\ntraditionless\ntraditions\ntraditor\ntraditores\ntraduce\ntraduced\ntraducement\ntraducements\ntraducer\ntraducers\ntraduces\ntraducing\ntraffic\ntrafficabilities\ntrafficability\ntrafficable\ntrafficked\ntrafficker\ntraffickers\ntrafficking\ntraffics\ntragacanth\ntragacanths\ntragedian\ntragedians\ntragedienne\ntragediennes\ntragedies\ntragedy\ntragi\ntragic\ntragical\ntragically\ntragicomedies\ntragicomedy\ntragicomic\ntragicomical\ntragics\ntragopan\ntragopans\ntragus\ntraik\ntraiked\ntraiking\ntraiks\ntrail\ntrailblazer\ntrailblazers\ntrailblazing\ntrailbreaker\ntrailbreakers\ntrailed\ntrailer\ntrailerable\ntrailered\ntrailering\ntrailerings\ntrailerist\ntrailerists\ntrailerite\ntrailerites\ntrailers\ntrailhead\ntrailheads\ntrailing\ntrailless\ntrails\ntrailside\ntrain\ntrainabilities\ntrainability\ntrainable\ntrainband\ntrainbands\ntrainbearer\ntrainbearers\ntrained\ntrainee\ntrainees\ntraineeship\ntraineeships\ntrainer\ntrainers\ntrainful\ntrainfuls\ntraining\ntrainings\ntrainload\ntrainloads\ntrainman\ntrainmen\ntrains\ntrainway\ntrainways\ntraipse\ntraipsed\ntraipses\ntraipsing\ntrait\ntraitor\ntraitoress\ntraitoresses\ntraitorous\ntraitorously\ntraitors\ntraitress\ntraitresses\ntraits\ntraject\ntrajected\ntrajecting\ntrajection\ntrajections\ntrajectories\ntrajectory\ntrajects\ntram\ntramcar\ntramcars\ntramel\ntrameled\ntrameling\ntramell\ntramelled\ntramelling\ntramells\ntramels\ntramless\ntramline\ntramlines\ntrammed\ntrammel\ntrammeled\ntrammeling\ntrammelled\ntrammelling\ntrammels\ntramming\ntramontane\ntramontanes\ntramp\ntramped\ntramper\ntrampers\ntramping\ntrampish\ntrample\ntrampled\ntrampler\ntramplers\ntramples\ntrampling\ntrampoline\ntrampoliner\ntrampoliners\ntrampolines\ntrampolining\ntrampolinings\ntrampolinist\ntrampolinists\ntramps\ntramroad\ntramroads\ntrams\ntramway\ntramways\ntrance\ntranced\ntrancelike\ntrances\ntranche\ntranches\ntrancing\ntrangam\ntrangams\ntrank\ntranks\ntranq\ntranqs\ntranquil\ntranquiler\ntranquilest\ntranquilities\ntranquility\ntranquilize\ntranquilized\ntranquilizer\ntranquilizers\ntranquilizes\ntranquilizing\ntranquiller\ntranquillest\ntranquillities\ntranquillity\ntranquillize\ntranquillized\ntranquillizer\ntranquillizers\ntranquillizes\ntranquillizing\ntranquilly\ntranquilness\ntranquilnesses\ntrans\ntransact\ntransacted\ntransacting\ntransactinide\ntransaction\ntransactional\ntransactions\ntransactor\ntransactors\ntransacts\ntransalpine\ntransaminase\ntransaminases\ntransamination\ntransaminations\ntransatlantic\ntransaxle\ntransaxles\ntransceiver\ntransceivers\ntranscend\ntranscended\ntranscendence\ntranscendences\ntranscendencies\ntranscendency\ntranscendent\ntranscendental\ntranscendentalism\ntranscendentalisms\ntranscendentalist\ntranscendentalists\ntranscendentally\ntranscendently\ntranscending\ntranscends\ntranscontinental\ntranscribe\ntranscribed\ntranscriber\ntranscribers\ntranscribes\ntranscribing\ntranscript\ntranscriptase\ntranscriptases\ntranscription\ntranscriptional\ntranscriptionally\ntranscriptionist\ntranscriptionists\ntranscriptions\ntranscripts\ntranscultural\ntranscutaneous\ntransdermal\ntransdisciplinary\ntransduce\ntransduced\ntransducer\ntransducers\ntransduces\ntransducing\ntransductant\ntransductants\ntransduction\ntransductional\ntransductions\ntransect\ntransected\ntransecting\ntransection\ntransections\ntransects\ntransept\ntranseptal\ntransepts\ntransfect\ntransfected\ntransfecting\ntransfection\ntransfections\ntransfects\ntransfer\ntransferabilities\ntransferability\ntransferable\ntransferal\ntransferals\ntransferase\ntransferases\ntransferee\ntransferees\ntransference\ntransferences\ntransferential\ntransferor\ntransferors\ntransferrable\ntransferred\ntransferrer\ntransferrers\ntransferrin\ntransferring\ntransferrins\ntransfers\ntransfiguration\ntransfigurations\ntransfigure\ntransfigured\ntransfigures\ntransfiguring\ntransfinite\ntransfix\ntransfixed\ntransfixes\ntransfixing\ntransfixion\ntransfixions\ntransfixt\ntransform\ntransformable\ntransformation\ntransformational\ntransformationalist\ntransformationalists\ntransformationally\ntransformations\ntransformative\ntransformed\ntransformer\ntransformers\ntransforming\ntransforms\ntransfusable\ntransfuse\ntransfused\ntransfuses\ntransfusible\ntransfusing\ntransfusion\ntransfusional\ntransfusions\ntransgender\ntransgendered\ntransgenerational\ntransgenic\ntransgress\ntransgressed\ntransgresses\ntransgressing\ntransgression\ntransgressions\ntransgressive\ntransgressor\ntransgressors\ntranship\ntranshipped\ntranshipping\ntranships\ntranshistorical\ntranshumance\ntranshumances\ntranshumant\ntranshumants\ntransience\ntransiences\ntransiencies\ntransiency\ntransient\ntransiently\ntransients\ntransilluminate\ntransilluminated\ntransilluminates\ntransilluminating\ntransillumination\ntransilluminations\ntransilluminator\ntransilluminators\ntransistor\ntransistorise\ntransistorised\ntransistorises\ntransistorising\ntransistorization\ntransistorizations\ntransistorize\ntransistorized\ntransistorizes\ntransistorizing\ntransistors\ntransit\ntransited\ntransiting\ntransition\ntransitional\ntransitionally\ntransitions\ntransitive\ntransitively\ntransitiveness\ntransitivenesses\ntransitivities\ntransitivity\ntransitorily\ntransitoriness\ntransitorinesses\ntransitory\ntransits\ntranslatabilities\ntranslatability\ntranslatable\ntranslate\ntranslated\ntranslates\ntranslating\ntranslation\ntranslational\ntranslations\ntranslative\ntranslator\ntranslators\ntranslatory\ntransliterate\ntransliterated\ntransliterates\ntransliterating\ntransliteration\ntransliterations\ntranslocate\ntranslocated\ntranslocates\ntranslocating\ntranslocation\ntranslocations\ntranslucence\ntranslucences\ntranslucencies\ntranslucency\ntranslucent\ntranslucently\ntransmarine\ntransmembrane\ntransmigrate\ntransmigrated\ntransmigrates\ntransmigrating\ntransmigration\ntransmigrations\ntransmigrator\ntransmigrators\ntransmigratory\ntransmissibilities\ntransmissibility\ntransmissible\ntransmission\ntransmissions\ntransmissive\ntransmissivities\ntransmissivity\ntransmissometer\ntransmissometers\ntransmit\ntransmits\ntransmittable\ntransmittal\ntransmittals\ntransmittance\ntransmittances\ntransmitted\ntransmitter\ntransmitters\ntransmitting\ntransmogrification\ntransmogrifications\ntransmogrified\ntransmogrifies\ntransmogrify\ntransmogrifying\ntransmontane\ntransmountain\ntransmutable\ntransmutation\ntransmutations\ntransmutative\ntransmute\ntransmuted\ntransmutes\ntransmuting\ntransnational\ntransnationalism\ntransnationalisms\ntransnatural\ntransoceanic\ntransom\ntransoms\ntransonic\ntranspacific\ntransparence\ntransparences\ntransparencies\ntransparency\ntransparent\ntransparentize\ntransparentized\ntransparentizes\ntransparentizing\ntransparently\ntransparentness\ntransparentnesses\ntranspersonal\ntranspicuous\ntranspierce\ntranspierced\ntranspierces\ntranspiercing\ntranspiration\ntranspirational\ntranspirations\ntranspire\ntranspired\ntranspires\ntranspiring\ntransplacental\ntransplacentally\ntransplant\ntransplantabilities\ntransplantability\ntransplantable\ntransplantation\ntransplantations\ntransplanted\ntransplanter\ntransplanters\ntransplanting\ntransplants\ntranspolar\ntransponder\ntransponders\ntranspontine\ntransport\ntransportabilities\ntransportability\ntransportable\ntransportation\ntransportational\ntransportations\ntransported\ntransportee\ntransportees\ntransporter\ntransporters\ntransporting\ntransports\ntransposable\ntranspose\ntransposed\ntransposes\ntransposing\ntransposition\ntranspositional\ntranspositions\ntransposon\ntransposons\ntranssexual\ntranssexualism\ntranssexualisms\ntranssexualities\ntranssexuality\ntranssexuals\ntransshape\ntransshaped\ntransshapes\ntransshaping\ntransship\ntransshipment\ntransshipments\ntransshipped\ntransshipping\ntransships\ntranssonic\ntransthoracic\ntransthoracically\ntransubstantial\ntransubstantiate\ntransubstantiated\ntransubstantiates\ntransubstantiating\ntransubstantiation\ntransubstantiations\ntransudate\ntransudates\ntransudation\ntransudations\ntransude\ntransuded\ntransudes\ntransuding\ntransuranic\ntransuranics\ntransuranium\ntransvaluate\ntransvaluated\ntransvaluates\ntransvaluating\ntransvaluation\ntransvaluations\ntransvalue\ntransvalued\ntransvalues\ntransvaluing\ntransversal\ntransversals\ntransverse\ntransversely\ntransverses\ntransvestism\ntransvestisms\ntransvestite\ntransvestites\ntrap\ntrapan\ntrapanned\ntrapanning\ntrapans\ntrapball\ntrapballs\ntrapdoor\ntrapdoors\ntrapes\ntrapesed\ntrapeses\ntrapesing\ntrapeze\ntrapezes\ntrapezia\ntrapezii\ntrapezist\ntrapezists\ntrapezium\ntrapeziums\ntrapezius\ntrapeziuses\ntrapezohedra\ntrapezohedron\ntrapezohedrons\ntrapezoid\ntrapezoidal\ntrapezoids\ntraplike\ntrapline\ntraplines\ntrapnest\ntrapnested\ntrapnesting\ntrapnests\ntrappean\ntrapped\ntrapper\ntrappers\ntrapping\ntrappings\ntrappose\ntrappous\ntraprock\ntraprocks\ntraps\ntrapshooter\ntrapshooters\ntrapshooting\ntrapshootings\ntrapt\ntrapunto\ntrapuntos\ntrash\ntrashed\ntrashes\ntrashier\ntrashiest\ntrashily\ntrashiness\ntrashinesses\ntrashing\ntrashman\ntrashmen\ntrashy\ntrass\ntrasses\ntrattoria\ntrattorias\ntrattorie\ntrauchle\ntrauchled\ntrauchles\ntrauchling\ntrauma\ntraumas\ntraumata\ntraumatic\ntraumatically\ntraumatise\ntraumatised\ntraumatises\ntraumatising\ntraumatism\ntraumatisms\ntraumatization\ntraumatizations\ntraumatize\ntraumatized\ntraumatizes\ntraumatizing\ntravail\ntravailed\ntravailing\ntravails\ntrave\ntravel\ntraveled\ntraveler\ntravelers\ntraveling\ntravelled\ntraveller\ntravellers\ntravelling\ntravelog\ntravelogs\ntravelogue\ntravelogues\ntravels\ntraversable\ntraversal\ntraversals\ntraverse\ntraversed\ntraverser\ntraversers\ntraverses\ntraversing\ntravertine\ntravertines\ntraves\ntravestied\ntravesties\ntravesty\ntravestying\ntravois\ntravoise\ntravoises\ntrawl\ntrawled\ntrawler\ntrawlerman\ntrawlermen\ntrawlers\ntrawley\ntrawleys\ntrawling\ntrawlnet\ntrawlnets\ntrawls\ntray\ntrayful\ntrayfuls\ntrays\ntreacheries\ntreacherous\ntreacherously\ntreacherousness\ntreacherousnesses\ntreachery\ntreacle\ntreacles\ntreacly\ntread\ntreaded\ntreader\ntreaders\ntreading\ntreadle\ntreadled\ntreadler\ntreadlers\ntreadles\ntreadless\ntreadling\ntreadmill\ntreadmills\ntreads\ntreason\ntreasonable\ntreasonably\ntreasonous\ntreasons\ntreasurable\ntreasure\ntreasured\ntreasurer\ntreasurers\ntreasurership\ntreasurerships\ntreasures\ntreasuries\ntreasuring\ntreasury\ntreat\ntreatabilities\ntreatability\ntreatable\ntreated\ntreater\ntreaters\ntreaties\ntreating\ntreatise\ntreatises\ntreatment\ntreatments\ntreats\ntreaty\ntreble\ntrebled\ntrebles\ntrebling\ntrebly\ntrebuchet\ntrebuchets\ntrebucket\ntrebuckets\ntrecento\ntrecentos\ntreddle\ntreddled\ntreddles\ntreddling\ntredecillion\ntredecillions\ntree\ntreed\ntreehopper\ntreehoppers\ntreeing\ntreelawn\ntreelawns\ntreeless\ntreelike\ntreen\ntreenail\ntreenails\ntreens\ntreenware\ntreenwares\ntrees\ntreetop\ntreetops\ntref\ntrefah\ntrefoil\ntrefoils\ntrehala\ntrehalas\ntrehalose\ntrehaloses\ntreillage\ntreillages\ntrek\ntrekked\ntrekker\ntrekkers\ntrekking\ntreks\ntrellis\ntrellised\ntrellises\ntrellising\ntrelliswork\ntrellisworks\ntrematode\ntrematodes\ntremble\ntrembled\ntrembler\ntremblers\ntrembles\ntremblier\ntrembliest\ntrembling\ntrembly\ntremendous\ntremendously\ntremendousness\ntremendousnesses\ntremolite\ntremolites\ntremolitic\ntremolo\ntremolos\ntremor\ntremors\ntremulant\ntremulous\ntremulously\ntremulousness\ntremulousnesses\ntrenail\ntrenails\ntrench\ntrenchancies\ntrenchancy\ntrenchant\ntrenchantly\ntrenched\ntrencher\ntrencherman\ntrenchermen\ntrenchers\ntrenches\ntrenching\ntrend\ntrended\ntrendier\ntrendies\ntrendiest\ntrendily\ntrendiness\ntrendinesses\ntrending\ntrends\ntrendsetter\ntrendsetters\ntrendsetting\ntrendy\ntrepan\ntrepanation\ntrepanations\ntrepang\ntrepangs\ntrepanned\ntrepanning\ntrepans\ntrephination\ntrephinations\ntrephine\ntrephined\ntrephines\ntrephining\ntrepid\ntrepidant\ntrepidation\ntrepidations\ntreponema\ntreponemal\ntreponemas\ntreponemata\ntreponematoses\ntreponematosis\ntreponeme\ntreponemes\ntrespass\ntrespassed\ntrespasser\ntrespassers\ntrespasses\ntrespassing\ntress\ntressed\ntressel\ntressels\ntresses\ntressier\ntressiest\ntressour\ntressours\ntressure\ntressures\ntressy\ntrestle\ntrestles\ntrestlework\ntrestleworks\ntret\ntretinoin\ntretinoins\ntrets\ntrevet\ntrevets\ntrews\ntrey\ntreys\ntriable\ntriac\ntriacetate\ntriacetates\ntriacid\ntriacids\ntriacs\ntriad\ntriadic\ntriadically\ntriadics\ntriadism\ntriadisms\ntriads\ntriage\ntriaged\ntriages\ntriaging\ntrial\ntrialogue\ntrialogues\ntrials\ntriamcinolone\ntriamcinolones\ntriangle\ntriangles\ntriangular\ntriangularities\ntriangularity\ntriangularly\ntriangulate\ntriangulated\ntriangulates\ntriangulating\ntriangulation\ntriangulations\ntriarchies\ntriarchy\ntriathlete\ntriathletes\ntriathlon\ntriathlons\ntriatomic\ntriaxial\ntriaxialities\ntriaxiality\ntriazin\ntriazine\ntriazines\ntriazins\ntriazole\ntriazoles\ntribade\ntribades\ntribadic\ntribal\ntribalism\ntribalisms\ntribally\ntribasic\ntribe\ntribes\ntribesman\ntribesmen\ntribespeople\ntriboelectric\ntriboelectricities\ntriboelectricity\ntribological\ntribologies\ntribologist\ntribologists\ntribology\ntriboluminescence\ntriboluminescences\ntriboluminescent\ntribrach\ntribrachic\ntribrachs\ntribulate\ntribulated\ntribulates\ntribulating\ntribulation\ntribulations\ntribunal\ntribunals\ntribunate\ntribunates\ntribune\ntribunes\ntribuneship\ntribuneships\ntributaries\ntributary\ntribute\ntributes\ntricarboxylic\ntrice\ntriced\ntriceps\ntricepses\ntriceratops\ntriceratopses\ntrices\ntrichiases\ntrichiasis\ntrichina\ntrichinae\ntrichinal\ntrichinas\ntrichinize\ntrichinized\ntrichinizes\ntrichinizing\ntrichinoses\ntrichinosis\ntrichinous\ntrichite\ntrichites\ntrichlorfon\ntrichlorfons\ntrichloroethylene\ntrichloroethylenes\ntrichlorphon\ntrichlorphons\ntrichocyst\ntrichocysts\ntrichogyne\ntrichogynes\ntrichoid\ntrichologies\ntrichologist\ntrichologists\ntrichology\ntrichome\ntrichomes\ntrichomonacidal\ntrichomonacide\ntrichomonacides\ntrichomonad\ntrichomonads\ntrichomonal\ntrichomoniases\ntrichomoniasis\ntrichopteran\ntrichopterans\ntrichothecene\ntrichothecenes\ntrichotomies\ntrichotomous\ntrichotomously\ntrichotomy\ntrichromat\ntrichromatic\ntrichromatism\ntrichromatisms\ntrichromats\ntricing\ntrick\ntricked\ntricker\ntrickeries\ntrickers\ntrickery\ntrickie\ntrickier\ntrickiest\ntrickily\ntrickiness\ntrickinesses\ntricking\ntrickish\ntrickishly\ntrickishness\ntrickishnesses\ntrickle\ntrickled\ntrickledown\ntrickles\ntricklier\ntrickliest\ntrickling\ntrickly\ntricks\ntricksier\ntricksiest\ntricksiness\ntricksinesses\ntrickster\ntricksters\ntricksy\ntricky\ntriclad\ntriclads\ntriclinia\ntriclinic\ntriclinium\ntricolette\ntricolettes\ntricolor\ntricolored\ntricolors\ntricorn\ntricorne\ntricornered\ntricornes\ntricorns\ntricot\ntricotine\ntricotines\ntricots\ntrictrac\ntrictracs\ntricuspid\ntricuspids\ntricycle\ntricycles\ntricyclic\ntricyclics\ntrident\ntridents\ntridimensional\ntridimensionalities\ntridimensionality\ntriduum\ntriduums\ntried\ntriene\ntrienes\ntriennia\ntriennial\ntriennially\ntriennials\ntriennium\ntrienniums\ntriens\ntrientes\ntrier\ntrierarch\ntrierarchies\ntrierarchs\ntrierarchy\ntriers\ntries\ntriethyl\ntrifecta\ntrifectas\ntrifid\ntrifle\ntrifled\ntrifler\ntriflers\ntrifles\ntrifling\ntriflings\ntrifluoperazine\ntrifluoperazines\ntrifluralin\ntrifluralins\ntrifocal\ntrifocals\ntrifold\ntrifoliate\ntrifoliolate\ntrifolium\ntrifoliums\ntriforia\ntriforium\ntriform\ntrifurcate\ntrifurcated\ntrifurcates\ntrifurcating\ntrifurcation\ntrifurcations\ntrig\ntrigeminal\ntrigeminals\ntrigged\ntrigger\ntriggered\ntriggerfish\ntriggerfishes\ntriggering\ntriggerman\ntriggermen\ntriggers\ntriggest\ntrigging\ntrigly\ntriglyceride\ntriglycerides\ntriglyph\ntriglyphic\ntriglyphical\ntriglyphs\ntrigness\ntrignesses\ntrigo\ntrigon\ntrigonal\ntrigonally\ntrigonometric\ntrigonometrical\ntrigonometrically\ntrigonometries\ntrigonometry\ntrigons\ntrigos\ntrigram\ntrigrams\ntrigraph\ntrigraphic\ntrigraphs\ntrigs\ntrihalomethane\ntrihalomethanes\ntrihedra\ntrihedral\ntrihedrals\ntrihedron\ntrihedrons\ntrihybrid\ntrihybrids\ntrihydroxy\ntriiodothyronine\ntriiodothyronines\ntrijet\ntrijets\ntrike\ntrikes\ntrilateral\ntrilbies\ntrilby\ntrilinear\ntrilingual\ntrilingually\ntriliteral\ntriliteralism\ntriliteralisms\ntriliterals\ntrill\ntrilled\ntriller\ntrillers\ntrilling\ntrillion\ntrillions\ntrillionth\ntrillionths\ntrillium\ntrilliums\ntrills\ntrilobal\ntrilobate\ntrilobed\ntrilobite\ntrilobites\ntrilogies\ntrilogy\ntrim\ntrimaran\ntrimarans\ntrimer\ntrimeric\ntrimerous\ntrimers\ntrimester\ntrimesters\ntrimeter\ntrimeters\ntrimethoprim\ntrimethoprims\ntrimetrogon\ntrimetrogons\ntrimly\ntrimmed\ntrimmer\ntrimmers\ntrimmest\ntrimming\ntrimmings\ntrimness\ntrimnesses\ntrimonthly\ntrimorph\ntrimorphic\ntrimorphs\ntrimotor\ntrimotors\ntrims\ntrinal\ntrinary\ntrindle\ntrindled\ntrindles\ntrindling\ntrine\ntrined\ntrines\ntrining\ntrinitarian\ntrinities\ntrinitrotoluene\ntrinitrotoluenes\ntrinity\ntrinket\ntrinketed\ntrinketer\ntrinketers\ntrinketing\ntrinketries\ntrinketry\ntrinkets\ntrinkums\ntrinocular\ntrinodal\ntrinomial\ntrinomials\ntrinucleotide\ntrinucleotides\ntrio\ntriode\ntriodes\ntriol\ntriolet\ntriolets\ntriols\ntrios\ntriose\ntrioses\ntrioxid\ntrioxide\ntrioxides\ntrioxids\ntrip\ntripack\ntripacks\ntripart\ntripartite\ntripe\ntripedal\ntripes\ntriphase\ntriphenylmethane\ntriphenylmethanes\ntriphosphate\ntriphosphates\ntriphthong\ntriphthongal\ntriphthongs\ntripinnate\ntripinnately\ntriplane\ntriplanes\ntriple\ntripled\ntriples\ntriplet\ntripletail\ntripletails\ntriplets\ntriplex\ntriplexes\ntriplicate\ntriplicated\ntriplicates\ntriplicating\ntriplication\ntriplications\ntriplicities\ntriplicity\ntripling\ntriplite\ntriplites\ntriploblastic\ntriploid\ntriploidies\ntriploids\ntriploidy\ntriply\ntripod\ntripodal\ntripodic\ntripodies\ntripods\ntripody\ntripoli\ntripolis\ntripos\ntriposes\ntripped\ntripper\ntrippers\ntrippet\ntrippets\ntrippier\ntrippiest\ntripping\ntrippingly\ntrippings\ntrippy\ntrips\ntriptane\ntriptanes\ntriptyca\ntriptycas\ntriptych\ntriptychs\ntripwire\ntripwires\ntriquetrous\ntriradiate\ntrireme\ntriremes\ntrisaccharide\ntrisaccharides\ntriscele\ntrisceles\ntrisect\ntrisected\ntrisecting\ntrisection\ntrisections\ntrisector\ntrisectors\ntrisects\ntriseme\ntrisemes\ntrisemic\ntrishaw\ntrishaws\ntriskaidekaphobia\ntriskaidekaphobias\ntriskele\ntriskeles\ntriskelia\ntriskelion\ntriskelions\ntrismic\ntrismus\ntrismuses\ntrisoctahedra\ntrisoctahedron\ntrisoctahedrons\ntrisome\ntrisomes\ntrisomic\ntrisomics\ntrisomies\ntrisomy\ntristate\ntriste\ntristearin\ntristearins\ntristeza\ntristezas\ntristful\ntristfully\ntristfulness\ntristfulnesses\ntristich\ntristichs\ntristimulus\ntrisubstituted\ntrisulfide\ntrisulfides\ntrisyllabic\ntrisyllable\ntrisyllables\ntrite\ntritely\ntriteness\ntritenesses\ntriter\ntritest\ntritheism\ntritheisms\ntritheist\ntritheistic\ntritheistical\ntritheists\ntrithing\ntrithings\ntritiated\ntriticale\ntriticales\ntriticum\ntriticums\ntritium\ntritiums\ntritoma\ntritomas\ntriton\ntritone\ntritones\ntritons\ntriturable\ntriturate\ntriturated\ntriturates\ntriturating\ntrituration\ntriturations\ntriturator\ntriturators\ntriumph\ntriumphal\ntriumphalism\ntriumphalisms\ntriumphalist\ntriumphalists\ntriumphant\ntriumphantly\ntriumphed\ntriumphing\ntriumphs\ntriumvir\ntriumvirate\ntriumvirates\ntriumviri\ntriumvirs\ntriune\ntriunes\ntriunities\ntriunity\ntrivalent\ntrivalve\ntrivalves\ntrivet\ntrivets\ntrivia\ntrivial\ntrivialise\ntrivialised\ntrivialises\ntrivialising\ntrivialist\ntrivialists\ntrivialities\ntriviality\ntrivialization\ntrivializations\ntrivialize\ntrivialized\ntrivializes\ntrivializing\ntrivially\ntrivium\ntriweeklies\ntriweekly\ntroak\ntroaked\ntroaking\ntroaks\ntrocar\ntrocars\ntrochaic\ntrochaics\ntrochal\ntrochanter\ntrochanteral\ntrochanteric\ntrochanters\ntrochar\ntrochars\ntroche\ntrochee\ntrochees\ntroches\ntrochil\ntrochili\ntrochils\ntrochilus\ntrochlea\ntrochleae\ntrochlear\ntrochlears\ntrochleas\ntrochoid\ntrochoidal\ntrochoids\ntrochophore\ntrochophores\ntrock\ntrocked\ntrocking\ntrocks\ntrod\ntrodden\ntrode\ntroffer\ntroffers\ntroglodyte\ntroglodytes\ntroglodytic\ntrogon\ntrogons\ntroika\ntroikas\ntroilism\ntroilisms\ntroilite\ntroilites\ntroilus\ntroiluses\ntrois\ntroke\ntroked\ntrokes\ntroking\ntroland\ntrolands\ntroll\ntrolled\ntroller\ntrollers\ntrolley\ntrolleybus\ntrolleybuses\ntrolleybusses\ntrolleyed\ntrolleying\ntrolleys\ntrollied\ntrollies\ntrolling\ntrollings\ntrollop\ntrollops\ntrollopy\ntrolls\ntrolly\ntrollying\ntrombone\ntrombones\ntrombonist\ntrombonists\ntrommel\ntrommels\ntromp\ntrompe\ntromped\ntrompes\ntromping\ntromps\ntrona\ntronas\ntrone\ntrones\ntroop\ntrooped\ntrooper\ntroopers\ntroopial\ntroopials\ntrooping\ntroops\ntroopship\ntroopships\ntrooz\ntrop\ntrope\ntropes\ntrophallaxes\ntrophallaxis\ntrophic\ntrophically\ntrophied\ntrophies\ntrophoblast\ntrophoblastic\ntrophoblasts\ntrophozoite\ntrophozoites\ntrophy\ntrophying\ntropic\ntropical\ntropicalize\ntropicalized\ntropicalizes\ntropicalizing\ntropically\ntropics\ntropin\ntropine\ntropines\ntropins\ntropism\ntropisms\ntropistic\ntropocollagen\ntropocollagens\ntropologic\ntropological\ntropologically\ntropomyosin\ntropomyosins\ntroponin\ntroponins\ntropopause\ntropopauses\ntroposphere\ntropospheres\ntropospheric\ntropotaxes\ntropotaxis\ntrot\ntroth\ntrothed\ntrothing\ntrothplight\ntrothplighted\ntrothplighting\ntrothplights\ntroths\ntrotline\ntrotlines\ntrots\ntrotted\ntrotter\ntrotters\ntrotting\ntrotyl\ntrotyls\ntroubadour\ntroubadours\ntrouble\ntroubled\ntroublemaker\ntroublemakers\ntroublemaking\ntroublemakings\ntroubler\ntroublers\ntroubles\ntroubleshoot\ntroubleshooter\ntroubleshooters\ntroubleshooting\ntroubleshoots\ntroubleshot\ntroublesome\ntroublesomely\ntroublesomeness\ntroublesomenesses\ntroubling\ntroublous\ntroublously\ntroublousness\ntroublousnesses\ntrough\ntroughs\ntrounce\ntrounced\ntrouncer\ntrouncers\ntrounces\ntrouncing\ntroupe\ntrouped\ntrouper\ntroupers\ntroupes\ntroupial\ntroupials\ntrouping\ntrouser\ntrousers\ntrousseau\ntrousseaus\ntrousseaux\ntrout\ntroutier\ntroutiest\ntrouts\ntrouty\ntrouvere\ntrouveres\ntrouveur\ntrouveurs\ntrove\ntrover\ntrovers\ntroves\ntrow\ntrowed\ntrowel\ntroweled\ntroweler\ntrowelers\ntroweling\ntrowelled\ntrowelling\ntrowels\ntrowing\ntrows\ntrowsers\ntrowth\ntrowths\ntroy\ntroys\ntruancies\ntruancy\ntruant\ntruanted\ntruanting\ntruantries\ntruantry\ntruants\ntruce\ntruced\ntruces\ntrucing\ntruck\ntruckage\ntruckages\ntrucked\ntrucker\ntruckers\ntruckful\ntruckfuls\ntrucking\ntruckings\ntruckle\ntruckled\ntruckler\ntrucklers\ntruckles\ntruckline\ntrucklines\ntruckling\ntruckload\ntruckloads\ntruckman\ntruckmaster\ntruckmasters\ntruckmen\ntrucks\ntruculence\ntruculences\ntruculencies\ntruculency\ntruculent\ntruculently\ntrudge\ntrudged\ntrudgen\ntrudgens\ntrudgeon\ntrudgeons\ntrudger\ntrudgers\ntrudges\ntrudging\ntrue\ntrueblue\ntrueblues\ntrueborn\ntruebred\ntrued\ntruehearted\ntrueheartedness\ntrueheartednesses\ntrueing\ntruelove\ntrueloves\ntrueness\ntruenesses\ntruepennies\ntruepenny\ntruer\ntrues\ntruest\ntruffe\ntruffes\ntruffle\ntruffled\ntruffles\ntrug\ntrugs\ntruing\ntruism\ntruisms\ntruistic\ntrull\ntrulls\ntruly\ntrumeau\ntrumeaux\ntrump\ntrumped\ntrumperies\ntrumpery\ntrumpet\ntrumpeted\ntrumpeter\ntrumpeters\ntrumpeting\ntrumpetlike\ntrumpets\ntrumping\ntrumps\ntruncate\ntruncated\ntruncates\ntruncating\ntruncation\ntruncations\ntruncheon\ntruncheoned\ntruncheoning\ntruncheons\ntrundle\ntrundled\ntrundler\ntrundlers\ntrundles\ntrundling\ntrunk\ntrunked\ntrunkfish\ntrunkfishes\ntrunkful\ntrunkfuls\ntrunks\ntrunksful\ntrunnel\ntrunnels\ntrunnion\ntrunnions\ntruss\ntrussed\ntrusser\ntrussers\ntrusses\ntrussing\ntrussings\ntrust\ntrustabilities\ntrustability\ntrustable\ntrustbuster\ntrustbusters\ntrusted\ntrustee\ntrusteed\ntrusteeing\ntrustees\ntrusteeship\ntrusteeships\ntruster\ntrusters\ntrustful\ntrustfully\ntrustfulness\ntrustfulnesses\ntrustier\ntrusties\ntrustiest\ntrustily\ntrustiness\ntrustinesses\ntrusting\ntrustingly\ntrustingness\ntrustingnesses\ntrustless\ntrustor\ntrustors\ntrusts\ntrustworthily\ntrustworthiness\ntrustworthinesses\ntrustworthy\ntrusty\ntruth\ntruthful\ntruthfully\ntruthfulness\ntruthfulnesses\ntruths\ntry\ntrying\ntryingly\ntryma\ntrymata\ntryout\ntryouts\ntrypanosome\ntrypanosomes\ntrypanosomiases\ntrypanosomiasis\ntrypsin\ntrypsinogen\ntrypsinogens\ntrypsins\ntryptamine\ntryptamines\ntryptic\ntryptophan\ntryptophane\ntryptophanes\ntryptophans\ntrysail\ntrysails\ntryst\ntryste\ntrysted\ntryster\ntrysters\ntrystes\ntrysting\ntrysts\ntryworks\ntsade\ntsades\ntsadi\ntsadis\ntsar\ntsardom\ntsardoms\ntsarevna\ntsarevnas\ntsarina\ntsarinas\ntsarism\ntsarisms\ntsarist\ntsarists\ntsaritza\ntsaritzas\ntsars\ntsatske\ntsatskes\ntsetse\ntsetses\ntsimmes\ntsimmeses\ntsk\ntsked\ntsking\ntsks\ntsktsk\ntsktsked\ntsktsking\ntsktsks\ntsooris\ntsores\ntsoris\ntsorriss\ntsouris\ntsuba\ntsunami\ntsunamic\ntsunamis\ntsuris\ntsutsugamushi\ntsutsugamushis\ntuatara\ntuataras\ntuatera\ntuateras\ntub\ntuba\ntubae\ntubaist\ntubaists\ntubal\ntubas\ntubate\ntubbable\ntubbed\ntubber\ntubbers\ntubbier\ntubbiest\ntubbing\ntubby\ntube\ntubed\ntubeless\ntubelike\ntubenose\ntubenoses\ntuber\ntubercle\ntubercles\ntubercular\ntuberculars\ntuberculate\ntuberculated\ntuberculin\ntuberculins\ntuberculoid\ntuberculoses\ntuberculosis\ntuberculous\ntuberoid\ntuberose\ntuberoses\ntuberosities\ntuberosity\ntuberous\ntubers\ntubes\ntubework\ntubeworks\ntubful\ntubfuls\ntubifex\ntubifexes\ntubificid\ntubificids\ntubiform\ntubing\ntubings\ntubist\ntubists\ntublike\ntubocurarine\ntubocurarines\ntubs\ntubular\ntubulate\ntubulated\ntubulates\ntubulating\ntubule\ntubules\ntubulin\ntubulins\ntubulose\ntubulous\ntubulure\ntubulures\ntuchun\ntuchuns\ntuck\ntuckahoe\ntuckahoes\ntucked\ntucker\ntuckered\ntuckering\ntuckers\ntucket\ntuckets\ntucking\ntucks\ntuckshop\ntuckshops\ntufa\ntufaceous\ntufas\ntuff\ntuffaceous\ntuffet\ntuffets\ntuffs\ntufoli\ntuft\ntufted\ntufter\ntufters\ntuftier\ntuftiest\ntuftily\ntufting\ntufts\ntufty\ntug\ntugboat\ntugboats\ntugged\ntugger\ntuggers\ntugging\ntughrik\ntughriks\ntugless\ntugrik\ntugriks\ntugs\ntui\ntuille\ntuilles\ntuis\ntuition\ntuitional\ntuitions\ntuladi\ntuladis\ntularemia\ntularemias\ntularemic\ntule\ntules\ntulip\ntulips\ntulipwood\ntulipwoods\ntulle\ntulles\ntullibee\ntullibees\ntumble\ntumblebug\ntumblebugs\ntumbled\ntumbledown\ntumbler\ntumblerful\ntumblerfuls\ntumblers\ntumbles\ntumbleweed\ntumbleweeds\ntumbling\ntumblings\ntumbrel\ntumbrels\ntumbril\ntumbrils\ntumefaction\ntumefactions\ntumefied\ntumefies\ntumefy\ntumefying\ntumescence\ntumescences\ntumescent\ntumid\ntumidities\ntumidity\ntumidly\ntummies\ntummler\ntummlers\ntummy\ntumor\ntumoral\ntumorigeneses\ntumorigenesis\ntumorigenic\ntumorigenicities\ntumorigenicity\ntumorlike\ntumorous\ntumors\ntumour\ntumours\ntump\ntumped\ntumping\ntumpline\ntumplines\ntumps\ntumular\ntumuli\ntumulose\ntumulous\ntumult\ntumults\ntumultuary\ntumultuous\ntumultuously\ntumultuousness\ntumultuousnesses\ntumulus\ntumuluses\ntun\ntuna\ntunabilities\ntunability\ntunable\ntunableness\ntunablenesses\ntunably\ntunas\ntundish\ntundishes\ntundra\ntundras\ntune\ntuneable\ntuneably\ntuned\ntuneful\ntunefully\ntunefulness\ntunefulnesses\ntuneless\ntunelessly\ntuner\ntuners\ntunes\ntunesmith\ntunesmiths\ntuneup\ntuneups\ntung\ntungs\ntungstate\ntungstates\ntungsten\ntungstens\ntungstic\ntunic\ntunica\ntunicae\ntunicate\ntunicated\ntunicates\ntunicle\ntunicles\ntunics\ntuning\ntunings\ntunnage\ntunnages\ntunned\ntunnel\ntunneled\ntunneler\ntunnelers\ntunneling\ntunnelled\ntunnellike\ntunnelling\ntunnels\ntunnies\ntunning\ntunny\ntuns\ntup\ntupelo\ntupelos\ntupik\ntupiks\ntupped\ntuppence\ntuppences\ntuppenny\ntupping\ntups\ntuque\ntuques\nturaco\nturacos\nturacou\nturacous\nturban\nturbaned\nturbanned\nturbans\nturbaries\nturbary\nturbellarian\nturbellarians\nturbeth\nturbeths\nturbid\nturbidimeter\nturbidimeters\nturbidimetric\nturbidimetrically\nturbidimetries\nturbidimetry\nturbidite\nturbidites\nturbidities\nturbidity\nturbidly\nturbidness\nturbidnesses\nturbinal\nturbinals\nturbinate\nturbinated\nturbinates\nturbine\nturbines\nturbit\nturbith\nturbiths\nturbits\nturbo\nturbocar\nturbocars\nturbocharged\nturbocharger\nturbochargers\nturboelectric\nturbofan\nturbofans\nturbogenerator\nturbogenerators\nturbojet\nturbojets\nturbomachineries\nturbomachinery\nturboprop\nturboprops\nturbos\nturboshaft\nturboshafts\nturbot\nturbots\nturbulence\nturbulences\nturbulencies\nturbulency\nturbulent\nturbulently\nturd\nturdine\nturds\ntureen\ntureens\nturf\nturfed\nturfier\nturfiest\nturfing\nturfless\nturflike\nturfman\nturfmen\nturfs\nturfski\nturfskiing\nturfskiings\nturfskis\nturfy\nturgencies\nturgency\nturgent\nturgescence\nturgescences\nturgescent\nturgid\nturgidities\nturgidity\nturgidly\nturgidness\nturgidnesses\nturgite\nturgites\nturgor\nturgors\nturista\nturistas\nturk\nturkey\nturkeys\nturkois\nturkoises\nturks\nturmeric\nturmerics\nturmoil\nturmoiled\nturmoiling\nturmoils\nturn\nturnable\nturnabout\nturnabouts\nturnaround\nturnarounds\nturnbuckle\nturnbuckles\nturncoat\nturncoats\nturndown\nturndowns\nturned\nturner\nturneries\nturners\nturnery\nturnhall\nturnhalls\nturning\nturnings\nturnip\nturnips\nturnkey\nturnkeys\nturnoff\nturnoffs\nturnon\nturnons\nturnout\nturnouts\nturnover\nturnovers\nturnpike\nturnpikes\nturns\nturnsole\nturnsoles\nturnspit\nturnspits\nturnstile\nturnstiles\nturnstone\nturnstones\nturntable\nturntables\nturnup\nturnups\nturnverein\nturnvereins\nturophile\nturophiles\nturpentine\nturpentined\nturpentines\nturpentining\nturpeth\nturpeths\nturpitude\nturpitudes\nturps\nturquois\nturquoise\nturquoises\nturret\nturreted\nturrets\nturrical\nturtle\nturtleback\nturtlebacks\nturtled\nturtledove\nturtledoves\nturtlehead\nturtleheads\nturtleneck\nturtlenecked\nturtlenecks\nturtler\nturtlers\nturtles\nturtling\nturtlings\nturves\ntusche\ntusches\ntush\ntushed\ntushes\ntushie\ntushies\ntushing\ntushy\ntusk\ntusked\ntusker\ntuskers\ntusking\ntuskless\ntusklike\ntusks\ntussah\ntussahs\ntussal\ntussar\ntussars\ntusseh\ntussehs\ntusser\ntussers\ntusses\ntussis\ntussises\ntussive\ntussle\ntussled\ntussles\ntussling\ntussock\ntussocks\ntussocky\ntussor\ntussore\ntussores\ntussors\ntussuck\ntussucks\ntussur\ntussurs\ntut\ntutee\ntutees\ntutelage\ntutelages\ntutelar\ntutelaries\ntutelars\ntutelary\ntutor\ntutorage\ntutorages\ntutored\ntutoress\ntutoresses\ntutorial\ntutorials\ntutoring\ntutors\ntutorship\ntutorships\ntutoyed\ntutoyer\ntutoyered\ntutoyering\ntutoyers\ntuts\ntutted\ntutti\ntutties\ntutting\ntuttis\ntutty\ntutu\ntutus\ntux\ntuxedo\ntuxedoed\ntuxedoes\ntuxedos\ntuxes\ntuyer\ntuyere\ntuyeres\ntuyers\ntwa\ntwaddle\ntwaddled\ntwaddler\ntwaddlers\ntwaddles\ntwaddling\ntwae\ntwaes\ntwain\ntwains\ntwang\ntwanged\ntwanger\ntwangers\ntwangier\ntwangiest\ntwanging\ntwangle\ntwangled\ntwangler\ntwanglers\ntwangles\ntwangling\ntwangs\ntwangy\ntwankies\ntwanky\ntwas\ntwasome\ntwasomes\ntwat\ntwats\ntwattle\ntwattled\ntwattles\ntwattling\ntwayblade\ntwayblades\ntweak\ntweaked\ntweakier\ntweakiest\ntweaking\ntweaks\ntweaky\ntwee\ntweed\ntweedier\ntweediest\ntweediness\ntweedinesses\ntweedle\ntweedled\ntweedles\ntweedling\ntweeds\ntweedy\ntween\ntweenies\ntweeny\ntweet\ntweeted\ntweeter\ntweeters\ntweeting\ntweets\ntweeze\ntweezed\ntweezer\ntweezers\ntweezes\ntweezing\ntwelfth\ntwelfths\ntwelve\ntwelvemo\ntwelvemonth\ntwelvemonths\ntwelvemos\ntwelves\ntwenties\ntwentieth\ntwentieths\ntwenty\ntwerp\ntwerps\ntwibil\ntwibill\ntwibills\ntwibils\ntwice\ntwiddle\ntwiddled\ntwiddler\ntwiddlers\ntwiddles\ntwiddlier\ntwiddliest\ntwiddling\ntwiddly\ntwier\ntwiers\ntwig\ntwigged\ntwiggen\ntwiggier\ntwiggiest\ntwigging\ntwiggy\ntwigless\ntwiglike\ntwigs\ntwilight\ntwilights\ntwilit\ntwill\ntwilled\ntwilling\ntwillings\ntwills\ntwin\ntwinberries\ntwinberry\ntwinborn\ntwine\ntwined\ntwiner\ntwiners\ntwines\ntwinflower\ntwinflowers\ntwinge\ntwinged\ntwingeing\ntwinges\ntwinging\ntwinier\ntwiniest\ntwinight\ntwining\ntwinjet\ntwinjets\ntwinkle\ntwinkled\ntwinkler\ntwinklers\ntwinkles\ntwinkling\ntwinklings\ntwinkly\ntwinned\ntwinning\ntwinnings\ntwins\ntwinset\ntwinsets\ntwinship\ntwinships\ntwiny\ntwirl\ntwirled\ntwirler\ntwirlers\ntwirlier\ntwirliest\ntwirling\ntwirls\ntwirly\ntwirp\ntwirps\ntwist\ntwisted\ntwister\ntwisters\ntwistier\ntwistiest\ntwisting\ntwistings\ntwists\ntwisty\ntwit\ntwitch\ntwitched\ntwitcher\ntwitchers\ntwitches\ntwitchier\ntwitchiest\ntwitchily\ntwitching\ntwitchy\ntwits\ntwitted\ntwitter\ntwittered\ntwittering\ntwitters\ntwittery\ntwitting\ntwixt\ntwo\ntwofer\ntwofers\ntwofold\ntwofolds\ntwopence\ntwopences\ntwopenny\ntwos\ntwosome\ntwosomes\ntwyer\ntwyers\ntycoon\ntycoons\ntye\ntyee\ntyees\ntyer\ntyers\ntyes\ntyin\ntying\ntyiyn\ntyke\ntykes\ntylosin\ntylosins\ntymbal\ntymbals\ntympan\ntympana\ntympanal\ntympani\ntympanic\ntympanies\ntympanist\ntympanists\ntympanites\ntympanitic\ntympano\ntympans\ntympanum\ntympanums\ntympany\ntyne\ntyned\ntynes\ntyning\ntypable\ntypal\ntype\ntypeable\ntypebar\ntypebars\ntypecase\ntypecases\ntypecast\ntypecasting\ntypecasts\ntyped\ntypeface\ntypefaces\ntypefounder\ntypefounders\ntypefounding\ntypefoundings\ntypes\ntypescript\ntypescripts\ntypeset\ntypesets\ntypesetter\ntypesetters\ntypesetting\ntypesettings\ntypestyle\ntypestyles\ntypewrite\ntypewriter\ntypewriters\ntypewrites\ntypewriting\ntypewritings\ntypewritten\ntypewrote\ntypey\ntyphlosole\ntyphlosoles\ntyphoid\ntyphoids\ntyphon\ntyphonic\ntyphons\ntyphoon\ntyphoons\ntyphose\ntyphous\ntyphus\ntyphuses\ntypic\ntypical\ntypicalities\ntypicality\ntypically\ntypicalness\ntypicalnesses\ntypier\ntypiest\ntypification\ntypifications\ntypified\ntypifier\ntypifiers\ntypifies\ntypify\ntypifying\ntyping\ntypist\ntypists\ntypo\ntypograph\ntypographed\ntypographer\ntypographers\ntypographic\ntypographical\ntypographically\ntypographies\ntypographing\ntypographs\ntypography\ntypological\ntypologically\ntypologies\ntypologist\ntypologists\ntypology\ntypos\ntypp\ntypps\ntypy\ntyramine\ntyramines\ntyrannic\ntyrannical\ntyrannically\ntyrannicalness\ntyrannicalnesses\ntyrannicide\ntyrannicides\ntyrannies\ntyrannise\ntyrannised\ntyrannises\ntyrannising\ntyrannize\ntyrannized\ntyrannizer\ntyrannizers\ntyrannizes\ntyrannizing\ntyrannosaur\ntyrannosaurs\ntyrannosaurus\ntyrannosauruses\ntyrannous\ntyrannously\ntyranny\ntyrant\ntyrants\ntyre\ntyred\ntyres\ntyring\ntyro\ntyrocidin\ntyrocidine\ntyrocidines\ntyrocidins\ntyronic\ntyros\ntyrosinase\ntyrosinases\ntyrosine\ntyrosines\ntyrothricin\ntyrothricins\ntythe\ntythed\ntythes\ntything\ntzaddik\ntzaddikim\ntzar\ntzardom\ntzardoms\ntzarevna\ntzarevnas\ntzarina\ntzarinas\ntzarism\ntzarisms\ntzarist\ntzarists\ntzaritza\ntzaritzas\ntzars\ntzetze\ntzetzes\ntzigane\ntziganes\ntzimmes\ntzimmeses\ntzitzis\ntzitzit\ntzitzith\ntzuris\nubieties\nubiety\nubique\nubiquinone\nubiquinones\nubiquities\nubiquitous\nubiquitously\nubiquitousness\nubiquitousnesses\nubiquity\nudder\nudders\nudo\nudometer\nudometers\nudometries\nudometry\nudos\nufological\nufologies\nufologist\nufologists\nufology\nugh\nughs\nuglier\nuglies\nugliest\nuglification\nuglifications\nuglified\nuglifier\nuglifiers\nuglifies\nuglify\nuglifying\nuglily\nugliness\nuglinesses\nugly\nugsome\nuh\nuhlan\nuhlans\nuintahite\nuintahites\nuintaite\nuintaites\nukase\nukases\nuke\nukelele\nukeleles\nukes\nukulele\nukuleles\nulama\nulamas\nulan\nulans\nulcer\nulcerate\nulcerated\nulcerates\nulcerating\nulceration\nulcerations\nulcerative\nulcered\nulcering\nulcerogenic\nulcerous\nulcers\nulema\nulemas\nulexite\nulexites\nullage\nullaged\nullages\nulna\nulnad\nulnae\nulnar\nulnas\nulpan\nulpanim\nulpans\nulster\nulsters\nulterior\nulteriorly\nultima\nultimacies\nultimacy\nultimas\nultimata\nultimate\nultimated\nultimately\nultimateness\nultimatenesses\nultimates\nultimating\nultimatum\nultimatums\nultimo\nultimogeniture\nultimogenitures\nultra\nultrabasic\nultrabasics\nultracareful\nultracasual\nultracautious\nultracentrifugal\nultracentrifugally\nultracentrifugation\nultracentrifugations\nultracentrifuge\nultracentrifuged\nultracentrifuges\nultracentrifuging\nultrachic\nultracivilized\nultraclean\nultracold\nultracommercial\nultracompact\nultracompetent\nultraconservatism\nultraconservatisms\nultraconservative\nultraconservatives\nultracontemporaries\nultracontemporary\nultraconvenient\nultracool\nultracritical\nultrademocratic\nultradense\nultradistance\nultradistances\nultradistant\nultradry\nultraefficient\nultraenergetic\nultraexclusive\nultrafamiliar\nultrafast\nultrafastidious\nultrafeminine\nultrafiche\nultrafiches\nultrafiltrate\nultrafiltrates\nultrafiltration\nultrafiltrations\nultrafine\nultraglamorous\nultrahazardous\nultraheat\nultraheated\nultraheating\nultraheats\nultraheavy\nultrahigh\nultrahip\nultrahot\nultrahuman\nultraism\nultraisms\nultraist\nultraistic\nultraists\nultraleft\nultraleftism\nultraleftisms\nultraleftist\nultraleftists\nultraliberal\nultraliberalism\nultraliberalisms\nultraliberals\nultralight\nultralights\nultralightweight\nultralow\nultramafic\nultramarathon\nultramarathoner\nultramarathoners\nultramarathons\nultramarine\nultramarines\nultramasculine\nultramicro\nultramicroscope\nultramicroscopes\nultramicroscopic\nultramicroscopical\nultramicroscopically\nultramicrotome\nultramicrotomes\nultramicrotomies\nultramicrotomy\nultramilitant\nultraminiature\nultraminiaturized\nultramodern\nultramodernist\nultramodernists\nultramontane\nultramontanes\nultramontanism\nultramontanisms\nultranationalism\nultranationalisms\nultranationalist\nultranationalistic\nultranationalists\nultraorthodox\nultraparadoxical\nultrapatriotic\nultraphysical\nultrapowerful\nultrapractical\nultraprecise\nultraprecision\nultraprecisions\nultraprofessional\nultraprogressive\nultraprogressives\nultrapure\nultraquiet\nultraradical\nultraradicals\nultrarapid\nultrarare\nultrararefied\nultrarational\nultrarealism\nultrarealisms\nultrarealist\nultrarealistic\nultrarealists\nultrared\nultrareds\nultrarefined\nultrareliable\nultrarespectable\nultrarevolutionaries\nultrarevolutionary\nultrarich\nultraright\nultrarightist\nultrarightists\nultraromantic\nultraroyalist\nultraroyalists\nultras\nultrasafe\nultrasecret\nultrasegregationist\nultrasegregationists\nultrasensitive\nultraserious\nultrasharp\nultrashort\nultrasimple\nultraslick\nultraslow\nultrasmall\nultrasmart\nultrasmooth\nultrasoft\nultrasonic\nultrasonically\nultrasonics\nultrasonographer\nultrasonographers\nultrasonographic\nultrasonographies\nultrasonography\nultrasophisticated\nultrasound\nultrasounds\nultrastructural\nultrastructurally\nultrastructure\nultrastructures\nultrathin\nultravacua\nultravacuum\nultravacuums\nultraviolence\nultraviolences\nultraviolent\nultraviolet\nultraviolets\nultravirile\nultravirilities\nultravirility\nultrawide\nulu\nululant\nululate\nululated\nululates\nululating\nululation\nululations\nulus\nulva\nulvas\num\numangite\numangites\numbel\numbeled\numbellar\numbellate\numbelled\numbellet\numbellets\numbellifer\numbelliferous\numbellifers\numbels\number\numbered\numbering\numbers\numbilical\numbilicals\numbilicate\numbilicated\numbilication\numbilications\numbilici\numbilicus\numbilicuses\numbles\numbo\numbonal\numbonate\numbones\numbonic\numbos\numbra\numbrae\numbrage\numbrageous\numbrageously\numbrageousness\numbrageousnesses\numbrages\numbral\numbras\numbrella\numbrellaed\numbrellaing\numbrellas\numbrette\numbrettes\numiac\numiack\numiacks\numiacs\numiak\numiaks\numiaq\numiaqs\numlaut\numlauted\numlauting\numlauts\numm\nump\numped\numping\numpirage\numpirages\numpire\numpired\numpires\numpiring\numps\numpteen\numpteenth\numteenth\nun\nunabashed\nunabashedly\nunabated\nunabatedly\nunabbreviated\nunable\nunabraded\nunabridged\nunabsorbed\nunabsorbent\nunabused\nunacademic\nunacademically\nunaccented\nunacceptabilities\nunacceptability\nunacceptable\nunacceptably\nunaccepted\nunacclimated\nunacclimatized\nunaccommodated\nunaccommodating\nunaccompanied\nunaccountabilities\nunaccountability\nunaccountable\nunaccountably\nunaccounted\nunaccredited\nunacculturated\nunaccustomed\nunaccustomedly\nunachieved\nunacknowledged\nunacquainted\nunactable\nunacted\nunactorish\nunadaptable\nunadapted\nunaddressed\nunadjudicated\nunadjusted\nunadmired\nunadmitted\nunadoptable\nunadorned\nunadult\nunadulterated\nunadulteratedly\nunadventurous\nunadvertised\nunadvised\nunadvisedly\nunaesthetic\nunaffected\nunaffectedly\nunaffectedness\nunaffectednesses\nunaffecting\nunaffectionate\nunaffectionately\nunaffiliated\nunaffluent\nunaffordable\nunafraid\nunaged\nunageing\nunaggressive\nunagile\nunaging\nunai\nunaided\nunaimed\nunaired\nunais\nunakin\nunakite\nunakites\nunalienable\nunalienated\nunaligned\nunalike\nunalleviated\nunallied\nunallocated\nunalloyed\nunalluring\nunalterabilities\nunalterability\nunalterable\nunalterableness\nunalterablenesses\nunalterably\nunaltered\nunambiguous\nunambiguously\nunambitious\nunambivalent\nunambivalently\nunamenable\nunamended\nunamiable\nunamortized\nunamplified\nunamused\nunamusing\nunanalyzable\nunanalyzed\nunanchor\nunanchored\nunanchoring\nunanchors\nunaneled\nunanesthetized\nunanimities\nunanimity\nunanimous\nunanimously\nunannotated\nunannounced\nunanswerabilities\nunanswerability\nunanswerable\nunanswerably\nunanswered\nunanticipated\nunanticipatedly\nunapologetic\nunapologetically\nunapologizing\nunapparent\nunappealable\nunappealing\nunappealingly\nunappeasable\nunappeasably\nunappeased\nunappetizing\nunappetizingly\nunappreciated\nunappreciation\nunappreciations\nunappreciative\nunapproachabilities\nunapproachability\nunapproachable\nunapproachably\nunappropriated\nunapproved\nunapt\nunaptly\nunaptness\nunaptnesses\nunarguable\nunarguably\nunargued\nunarm\nunarmed\nunarming\nunarmored\nunarms\nunarrogant\nunartful\nunarticulated\nunartistic\nunary\nunashamed\nunashamedly\nunasked\nunaspirated\nunassailabilities\nunassailability\nunassailable\nunassailableness\nunassailablenesses\nunassailably\nunassailed\nunassembled\nunassertive\nunassertively\nunassigned\nunassimilable\nunassimilated\nunassisted\nunassociated\nunassuageable\nunassuaged\nunassuming\nunassumingness\nunassumingnesses\nunathletic\nunatoned\nunattached\nunattainable\nunattended\nunattenuated\nunattested\nunattractive\nunattractively\nunattractiveness\nunattractivenesses\nunattributable\nunattributed\nunattuned\nunau\nunaudited\nunaus\nunauthentic\nunauthorized\nunautomated\nunavailabilities\nunavailability\nunavailable\nunavailing\nunavailingly\nunavailingness\nunavailingnesses\nunavenged\nunaverage\nunavoidable\nunavoidably\nunavowed\nunawaked\nunawakened\nunawarded\nunaware\nunawarely\nunawareness\nunawarenesses\nunawares\nunawed\nunawesome\nunbacked\nunbaked\nunbalance\nunbalanced\nunbalances\nunbalancing\nunballasted\nunban\nunbandage\nunbandaged\nunbandages\nunbandaging\nunbanned\nunbanning\nunbans\nunbaptized\nunbar\nunbarbed\nunbarbered\nunbarred\nunbarricaded\nunbarring\nunbars\nunbased\nunbated\nunbathed\nunbe\nunbear\nunbearable\nunbearably\nunbeared\nunbearing\nunbears\nunbeatable\nunbeatably\nunbeaten\nunbeautiful\nunbeautifully\nunbecoming\nunbecomingly\nunbecomingness\nunbecomingnesses\nunbefitting\nunbeholden\nunbeknown\nunbeknownst\nunbelief\nunbeliefs\nunbelievable\nunbelievably\nunbeliever\nunbelievers\nunbelieving\nunbelievingly\nunbelligerent\nunbeloved\nunbelt\nunbelted\nunbelting\nunbelts\nunbemused\nunbend\nunbendable\nunbended\nunbending\nunbends\nunbenign\nunbent\nunbeseeming\nunbiased\nunbiasedness\nunbiasednesses\nunbiblical\nunbid\nunbidden\nunbilled\nunbind\nunbinding\nunbinds\nunbitted\nunbitten\nunbitter\nunblamed\nunbleached\nunblemished\nunblenched\nunblended\nunblessed\nunblest\nunblinded\nunblinking\nunblinkingly\nunblock\nunblocked\nunblocking\nunblocks\nunblooded\nunbloodied\nunbloody\nunblushing\nunblushingly\nunbodied\nunbolt\nunbolted\nunbolting\nunbolts\nunboned\nunbonnet\nunbonneted\nunbonneting\nunbonnets\nunbookish\nunborn\nunbosom\nunbosomed\nunbosoming\nunbosoms\nunbought\nunbouncy\nunbound\nunbounded\nunboundedness\nunboundednesses\nunbowdlerized\nunbowed\nunbox\nunboxed\nunboxes\nunboxing\nunbrace\nunbraced\nunbraces\nunbracing\nunbracketed\nunbraid\nunbraided\nunbraiding\nunbraids\nunbrake\nunbraked\nunbrakes\nunbraking\nunbranched\nunbranded\nunbreachable\nunbreakable\nunbreathable\nunbred\nunbreech\nunbreeched\nunbreeches\nunbreeching\nunbridgeable\nunbridged\nunbridle\nunbridled\nunbridles\nunbridling\nunbriefed\nunbright\nunbrilliant\nunbroke\nunbroken\nunbruised\nunbrushed\nunbuckle\nunbuckled\nunbuckles\nunbuckling\nunbudgeable\nunbudgeably\nunbudgeted\nunbudging\nunbudgingly\nunbuffered\nunbuild\nunbuildable\nunbuilding\nunbuilds\nunbuilt\nunbulky\nunbundle\nunbundled\nunbundles\nunbundling\nunburden\nunburdened\nunburdening\nunburdens\nunbureaucratic\nunburied\nunburnable\nunburned\nunburnt\nunbusinesslike\nunbusted\nunbusy\nunbuttered\nunbutton\nunbuttoned\nunbuttoning\nunbuttons\nuncage\nuncaged\nuncages\nuncaging\nuncake\nuncaked\nuncakes\nuncaking\nuncalcified\nuncalcined\nuncalculated\nuncalculating\nuncalibrated\nuncalled\nuncalloused\nuncanceled\nuncandid\nuncandidly\nuncannier\nuncanniest\nuncannily\nuncanniness\nuncanninesses\nuncanny\nuncanonical\nuncap\nuncapitalized\nuncapped\nuncapping\nuncaps\nuncaptioned\nuncapturable\nuncaring\nuncarpeted\nuncase\nuncased\nuncases\nuncashed\nuncasing\nuncasked\nuncastrated\nuncataloged\nuncatchable\nuncatchy\nuncategorizable\nuncaught\nuncaused\nunceasing\nunceasingly\nuncelebrated\nuncensored\nuncensorious\nuncensured\nunceremonious\nunceremoniously\nunceremoniousness\nunceremoniousnesses\nuncertain\nuncertainly\nuncertainness\nuncertainnesses\nuncertainties\nuncertainty\nuncertified\nunchain\nunchained\nunchaining\nunchains\nunchallengeable\nunchallenged\nunchallenging\nunchancy\nunchangeabilities\nunchangeability\nunchangeable\nunchangeableness\nunchangeablenesses\nunchangeably\nunchanged\nunchanging\nunchangingly\nunchangingness\nunchangingnesses\nunchanneled\nunchaperoned\nuncharacteristic\nuncharacteristically\nuncharge\nuncharged\nuncharges\nuncharging\nuncharismatic\nuncharitable\nuncharitableness\nuncharitablenesses\nuncharitably\nuncharming\nuncharted\nunchartered\nunchary\nunchaste\nunchastely\nunchasteness\nunchastenesses\nunchastities\nunchastity\nunchauvinistic\nuncheckable\nunchecked\nunchewable\nunchewed\nunchic\nunchicly\nunchildlike\nunchivalrous\nunchivalrously\nunchlorinated\nunchoke\nunchoked\nunchokes\nunchoking\nunchoreographed\nunchosen\nunchristened\nunchristian\nunchronicled\nunchronological\nunchurch\nunchurched\nunchurches\nunchurching\nunchurchly\nunci\nuncia\nunciae\nuncial\nuncially\nuncials\nunciform\nunciforms\nunciliated\nuncinal\nuncinariases\nuncinariasis\nuncinate\nuncinematic\nuncini\nuncinus\nuncirculated\nuncircumcised\nuncircumcision\nuncircumcisions\nuncivil\nuncivilized\nuncivilly\nunclad\nunclaimed\nunclamp\nunclamped\nunclamping\nunclamps\nunclarified\nunclarities\nunclarity\nunclasp\nunclasped\nunclasping\nunclasps\nunclassical\nunclassifiable\nunclassified\nuncle\nunclean\nuncleaned\nuncleaner\nuncleanest\nuncleanliness\nuncleanlinesses\nuncleanly\nuncleanness\nuncleannesses\nunclear\nunclearer\nunclearest\nunclench\nunclenched\nunclenches\nunclenching\nuncles\nuncliched\nunclimbable\nunclimbableness\nunclimbablenesses\nunclinch\nunclinched\nunclinches\nunclinching\nunclip\nunclipped\nunclipping\nunclips\nuncloak\nuncloaked\nuncloaking\nuncloaks\nunclog\nunclogged\nunclogging\nunclogs\nunclose\nunclosed\nuncloses\nunclosing\nunclothe\nunclothed\nunclothes\nunclothing\nuncloud\nunclouded\nuncloudedly\nunclouding\nunclouds\nuncloyed\nuncloying\nunclubbable\nunclutter\nuncluttered\nuncluttering\nunclutters\nunco\nuncoalesce\nuncoalesced\nuncoalesces\nuncoalescing\nuncoated\nuncoating\nuncock\nuncocked\nuncocking\nuncocks\nuncoded\nuncodified\nuncoerced\nuncoercive\nuncoercively\nuncoffin\nuncoffined\nuncoffining\nuncoffins\nuncoil\nuncoiled\nuncoiling\nuncoils\nuncoined\nuncollected\nuncollectible\nuncollectibles\nuncolored\nuncombative\nuncombed\nuncombined\nuncomely\nuncomfortable\nuncomfortably\nuncomic\nuncommercial\nuncommercialized\nuncommitted\nuncommon\nuncommoner\nuncommonest\nuncommonly\nuncommonness\nuncommonnesses\nuncommunicable\nuncommunicative\nuncompassionate\nuncompelling\nuncompensated\nuncompetitive\nuncompetitiveness\nuncompetitivenesses\nuncomplacent\nuncomplaining\nuncomplainingly\nuncompleted\nuncomplicated\nuncomplimentary\nuncompounded\nuncomprehended\nuncomprehending\nuncomprehendingly\nuncompromisable\nuncompromising\nuncompromisingly\nuncompromisingness\nuncompromisingnesses\nuncomputerized\nunconcealed\nunconceivable\nunconcern\nunconcerned\nunconcernedly\nunconcernedness\nunconcernednesses\nunconcerns\nunconditional\nunconditionally\nunconditioned\nunconfessed\nunconfined\nunconfirmed\nunconformable\nunconformably\nunconformities\nunconformity\nunconfounded\nunconfuse\nunconfused\nunconfuses\nunconfusing\nuncongenial\nuncongenialities\nuncongeniality\nunconjugated\nunconnected\nunconquerable\nunconquerably\nunconquered\nunconscionabilities\nunconscionability\nunconscionable\nunconscionableness\nunconscionablenesses\nunconscionably\nunconscious\nunconsciouses\nunconsciously\nunconsciousness\nunconsciousnesses\nunconsecrated\nunconsidered\nunconsolidated\nunconstitutional\nunconstitutionalities\nunconstitutionality\nunconstitutionally\nunconstrained\nunconstraint\nunconstraints\nunconstricted\nunconstructed\nunconstructive\nunconsumed\nunconsummated\nuncontainable\nuncontaminated\nuncontemplated\nuncontemporary\nuncontentious\nuncontested\nuncontracted\nuncontradicted\nuncontrived\nuncontrollabilities\nuncontrollability\nuncontrollable\nuncontrollably\nuncontrolled\nuncontroversial\nuncontroversially\nunconventional\nunconventionalities\nunconventionality\nunconventionally\nunconverted\nunconvinced\nunconvincing\nunconvincingly\nunconvincingness\nunconvincingnesses\nunconvoyed\nuncooked\nuncool\nuncooled\nuncooperative\nuncoordinated\nuncopyrightable\nuncork\nuncorked\nuncorking\nuncorks\nuncorrectable\nuncorrected\nuncorrelated\nuncorroborated\nuncorrupt\nuncorseted\nuncos\nuncountable\nuncounted\nuncouple\nuncoupled\nuncoupler\nuncouplers\nuncouples\nuncoupling\nuncourageous\nuncouth\nuncouthly\nuncouthness\nuncouthnesses\nuncovenanted\nuncover\nuncovered\nuncovering\nuncovers\nuncoy\nuncracked\nuncrate\nuncrated\nuncrates\nuncrating\nuncrazy\nuncreate\nuncreated\nuncreates\nuncreating\nuncreative\nuncredentialed\nuncredited\nuncrippled\nuncritical\nuncritically\nuncropped\nuncross\nuncrossable\nuncrossed\nuncrosses\nuncrossing\nuncrowded\nuncrown\nuncrowned\nuncrowning\nuncrowns\nuncrumple\nuncrumpled\nuncrumples\nuncrumpling\nuncrushable\nuncrystallized\nunction\nunctions\nunctuous\nunctuously\nunctuousness\nunctuousnesses\nuncuff\nuncuffed\nuncuffing\nuncuffs\nuncultivable\nuncultivated\nuncultured\nuncurb\nuncurbed\nuncurbing\nuncurbs\nuncured\nuncurious\nuncurl\nuncurled\nuncurling\nuncurls\nuncurrent\nuncursed\nuncurtained\nuncus\nuncustomarily\nuncustomary\nuncut\nuncute\nuncynical\nuncynically\nundamaged\nundamped\nundanceable\nundaring\nundated\nundauntable\nundaunted\nundauntedly\nunde\nundead\nundebatable\nundebatably\nundecadent\nundeceive\nundeceived\nundeceives\nundeceiving\nundecidabilities\nundecidability\nundecidable\nundecided\nundecideds\nundecillion\nundecillions\nundecipherable\nundeciphered\nundecked\nundeclared\nundecomposed\nundecorated\nundedicated\nundee\nundefeated\nundefended\nundefiled\nundefinable\nundefined\nundefoliated\nundeformed\nundelegated\nundeliverable\nundelivered\nundeluded\nundemanding\nundemocratic\nundemocratically\nundemonstrative\nundemonstratively\nundemonstrativeness\nundemonstrativenesses\nundeniable\nundeniableness\nundeniablenesses\nundeniably\nundenied\nundenominational\nundependable\nunder\nunderachieve\nunderachieved\nunderachievement\nunderachievements\nunderachiever\nunderachievers\nunderachieves\nunderachieving\nunderact\nunderacted\nunderacting\nunderactive\nunderactivities\nunderactivity\nunderacts\nunderage\nunderages\nunderappreciated\nunderarm\nunderarms\nunderate\nunderbellies\nunderbelly\nunderbid\nunderbidder\nunderbidders\nunderbidding\nunderbids\nunderbodies\nunderbody\nunderboss\nunderbosses\nunderbought\nunderbred\nunderbrim\nunderbrims\nunderbrush\nunderbrushes\nunderbud\nunderbudded\nunderbudding\nunderbudgeted\nunderbuds\nunderbuy\nunderbuying\nunderbuys\nundercapitalized\nundercard\nundercards\nundercarriage\nundercarriages\nundercharge\nundercharged\nundercharges\nundercharging\nunderclass\nunderclasses\nunderclassman\nunderclassmen\nunderclothes\nunderclothing\nunderclothings\nundercoat\nundercoating\nundercoatings\nundercoats\nundercool\nundercooled\nundercooling\nundercools\nundercount\nundercounted\nundercounting\nundercounts\nundercover\nundercroft\nundercrofts\nundercurrent\nundercurrents\nundercut\nundercuts\nundercutting\nunderdeveloped\nunderdevelopment\nunderdevelopments\nunderdid\nunderdo\nunderdoes\nunderdog\nunderdogs\nunderdoing\nunderdone\nunderdrawers\nundereat\nundereaten\nundereating\nundereats\nundereducated\nunderemphases\nunderemphasis\nunderemphasize\nunderemphasized\nunderemphasizes\nunderemphasizing\nunderemployed\nunderemployment\nunderemployments\nunderestimate\nunderestimated\nunderestimates\nunderestimating\nunderestimation\nunderestimations\nunderexpose\nunderexposed\nunderexposes\nunderexposing\nunderexposure\nunderexposures\nunderfed\nunderfeed\nunderfeeding\nunderfeeds\nunderfinanced\nunderflow\nunderflows\nunderfoot\nunderfund\nunderfunded\nunderfunding\nunderfunds\nunderfur\nunderfurs\nundergarment\nundergarments\nundergird\nundergirded\nundergirding\nundergirds\nundergirt\nunderglaze\nunderglazes\nundergo\nundergod\nundergods\nundergoes\nundergoing\nundergone\nundergrad\nundergrads\nundergraduate\nundergraduates\nunderground\nundergrounder\nundergrounders\nundergrounds\nundergrowth\nundergrowths\nunderhand\nunderhanded\nunderhandedly\nunderhandedness\nunderhandednesses\nunderinflated\nunderinflation\nunderinflations\nunderinsured\nunderinvestment\nunderinvestments\nunderjaw\nunderjaws\nunderlaid\nunderlain\nunderlap\nunderlapped\nunderlapping\nunderlaps\nunderlay\nunderlaying\nunderlayment\nunderlayments\nunderlays\nunderlet\nunderlets\nunderletting\nunderlie\nunderlies\nunderline\nunderlined\nunderlines\nunderling\nunderlings\nunderlining\nunderlip\nunderlips\nunderlit\nunderlying\nunderlyingly\nundermanned\nundermine\nundermined\nundermines\nundermining\nundermost\nunderneath\nundernourished\nundernourishment\nundernourishments\nundernutrition\nundernutritions\nunderpaid\nunderpainting\nunderpaintings\nunderpants\nunderpart\nunderparts\nunderpass\nunderpasses\nunderpay\nunderpaying\nunderpayment\nunderpayments\nunderpays\nunderpin\nunderpinned\nunderpinning\nunderpinnings\nunderpins\nunderplay\nunderplayed\nunderplaying\nunderplays\nunderplot\nunderplots\nunderpopulated\nunderpowered\nunderprepared\nunderprice\nunderpriced\nunderprices\nunderpricing\nunderprivileged\nunderproduction\nunderproductions\nunderproof\nunderpublicized\nunderqualified\nunderran\nunderrate\nunderrated\nunderrates\nunderrating\nunderreact\nunderreacted\nunderreacting\nunderreacts\nunderreport\nunderreported\nunderreporting\nunderreports\nunderrepresentation\nunderrepresentations\nunderrepresented\nunderrun\nunderrunning\nunderruns\nundersaturated\nunderscore\nunderscored\nunderscores\nunderscoring\nundersea\nunderseas\nundersecretaries\nundersecretary\nundersell\nunderselling\nundersells\nunderserved\nunderset\nundersets\nundersexed\nundersheriff\nundersheriffs\nundershirt\nundershirted\nundershirts\nundershoot\nundershooting\nundershoots\nundershorts\nundershot\nundershrub\nundershrubs\nunderside\nundersides\nundersigned\nundersize\nundersized\nunderskirt\nunderskirts\nunderslung\nundersold\nunderspin\nunderspins\nunderstaffed\nunderstaffing\nunderstaffings\nunderstand\nunderstandabilities\nunderstandability\nunderstandable\nunderstandably\nunderstanding\nunderstandingly\nunderstandings\nunderstands\nunderstate\nunderstated\nunderstatedly\nunderstatement\nunderstatements\nunderstates\nunderstating\nundersteer\nundersteered\nundersteering\nundersteers\nunderstood\nunderstories\nunderstory\nunderstrapper\nunderstrappers\nunderstrength\nunderstudied\nunderstudies\nunderstudy\nunderstudying\nundersupplies\nundersupply\nundersurface\nundersurfaces\nundertake\nundertaken\nundertaker\nundertakers\nundertakes\nundertaking\nundertakings\nundertax\nundertaxed\nundertaxes\nundertaxing\nundertenant\nundertenants\nunderthrust\nunderthrusting\nunderthrusts\nundertone\nundertones\nundertook\nundertow\nundertows\nundertrick\nundertricks\nunderused\nunderutilization\nunderutilizations\nunderutilize\nunderutilized\nunderutilizes\nunderutilizing\nundervaluation\nundervaluations\nundervalue\nundervalued\nundervalues\nundervaluing\nunderwater\nunderway\nunderwear\nunderweight\nunderweights\nunderwent\nunderwhelm\nunderwhelmed\nunderwhelming\nunderwhelms\nunderwing\nunderwings\nunderwire\nunderwires\nunderwood\nunderwoods\nunderwool\nunderwools\nunderworld\nunderworlds\nunderwrite\nunderwriter\nunderwriters\nunderwrites\nunderwriting\nunderwritten\nunderwrote\nundescended\nundescribable\nundeserved\nundeserving\nundesignated\nundesigning\nundesirabilities\nundesirability\nundesirable\nundesirableness\nundesirablenesses\nundesirables\nundesirably\nundesired\nundetectable\nundetected\nundeterminable\nundetermined\nundeterred\nundeveloped\nundeviating\nundeviatingly\nundevout\nundiagnosable\nundiagnosed\nundialectical\nundid\nundidactic\nundies\nundifferentiated\nundigested\nundigestible\nundignified\nundiluted\nundiminished\nundimmed\nundine\nundines\nundiplomatic\nundiplomatically\nundirected\nundischarged\nundisciplined\nundisclosed\nundiscouraged\nundiscoverable\nundiscovered\nundiscriminating\nundiscussed\nundisguised\nundisguisedly\nundismayed\nundisputable\nundisputed\nundissociated\nundissolved\nundistinguished\nundistorted\nundistracted\nundistributed\nundisturbed\nundivided\nundo\nundoable\nundocile\nundock\nundocked\nundocking\nundocks\nundoctored\nundoctrinaire\nundocumented\nundoer\nundoers\nundoes\nundogmatic\nundogmatically\nundoing\nundoings\nundomestic\nundomesticated\nundone\nundotted\nundouble\nundoubled\nundoubles\nundoubling\nundoubtable\nundoubted\nundoubtedly\nundoubting\nundrained\nundramatic\nundramatically\nundramatized\nundrape\nundraped\nundrapes\nundraping\nundraw\nundrawing\nundrawn\nundraws\nundreamed\nundreamt\nundress\nundressed\nundresses\nundressing\nundrest\nundrew\nundried\nundrilled\nundrinkable\nundrunk\nundubbed\nundue\nundulant\nundular\nundulate\nundulated\nundulates\nundulating\nundulation\nundulations\nundulatory\nundulled\nunduly\nunduplicated\nundutiful\nundutifully\nundutifulness\nundutifulnesses\nundy\nundyed\nundying\nundynamic\nuneager\nunearmarked\nunearned\nunearth\nunearthed\nunearthing\nunearthliness\nunearthlinesses\nunearthly\nunearths\nunease\nuneases\nuneasier\nuneasiest\nuneasily\nuneasiness\nuneasinesses\nuneasy\nuneatable\nuneaten\nuneccentric\nunecological\nuneconomic\nuneconomical\nunedible\nunedifying\nunedited\nuneducable\nuneducated\nunelaborate\nunelectable\nunelected\nunelectrified\nunembarrassed\nunembellished\nunembittered\nunemotional\nunemotionally\nunemphatic\nunemphatically\nunempirical\nunemployabilities\nunemployability\nunemployable\nunemployables\nunemployed\nunemployeds\nunemployment\nunemployments\nunenchanted\nunenclosed\nunencouraging\nunencumbered\nunendearing\nunended\nunending\nunendingly\nunendurable\nunendurableness\nunendurablenesses\nunendurably\nunenforceable\nunenforced\nunenlarged\nunenlightened\nunenlightening\nunenriched\nunenterprising\nunenthusiastic\nunenthusiastically\nunenviable\nunenvied\nunenvious\nunequal\nunequaled\nunequalled\nunequally\nunequals\nunequipped\nunequivocably\nunequivocal\nunequivocally\nunerased\nunerotic\nunerring\nunerringly\nunescapable\nunescorted\nunessential\nunestablished\nunesthetic\nunethical\nunevaded\nunevaluated\nuneven\nunevener\nunevenest\nunevenly\nunevenness\nunevennesses\nuneventful\nuneventfully\nuneventfulness\nuneventfulnesses\nunevolved\nunexamined\nunexampled\nunexcelled\nunexceptionable\nunexceptionableness\nunexceptionablenesses\nunexceptionably\nunexceptional\nunexcitable\nunexcited\nunexciting\nunexcused\nunexercised\nunexotic\nunexpected\nunexpectedly\nunexpectedness\nunexpectednesses\nunexpended\nunexpert\nunexpired\nunexplainable\nunexplained\nunexploded\nunexploited\nunexplored\nunexposed\nunexpressed\nunexpressive\nunexpurgated\nunextraordinary\nunfaded\nunfading\nunfadingly\nunfailing\nunfailingly\nunfair\nunfairer\nunfairest\nunfairly\nunfairness\nunfairnesses\nunfaith\nunfaithful\nunfaithfully\nunfaithfulness\nunfaithfulnesses\nunfaiths\nunfaked\nunfallen\nunfalsifiable\nunfaltering\nunfalteringly\nunfamiliar\nunfamiliarities\nunfamiliarity\nunfamiliarly\nunfamous\nunfancy\nunfashionable\nunfashionableness\nunfashionablenesses\nunfashionably\nunfasten\nunfastened\nunfastening\nunfastens\nunfastidious\nunfathered\nunfathomable\nunfavorable\nunfavorableness\nunfavorablenesses\nunfavorably\nunfavorite\nunfazed\nunfeared\nunfeasible\nunfed\nunfeeling\nunfeelingly\nunfeelingness\nunfeelingnesses\nunfeigned\nunfeignedly\nunfelt\nunfeminine\nunfence\nunfenced\nunfences\nunfencing\nunfermented\nunfertile\nunfertilized\nunfetter\nunfettered\nunfettering\nunfetters\nunfilial\nunfilially\nunfilled\nunfilmed\nunfiltered\nunfindable\nunfinished\nunfired\nunfished\nunfit\nunfitly\nunfitness\nunfitnesses\nunfits\nunfitted\nunfitting\nunfix\nunfixed\nunfixes\nunfixing\nunfixt\nunflagging\nunflaggingly\nunflamboyant\nunflappabilities\nunflappability\nunflappable\nunflappably\nunflashy\nunflattering\nunflatteringly\nunfledged\nunflexed\nunflinching\nunflinchingly\nunflyable\nunfocused\nunfocussed\nunfoiled\nunfold\nunfolded\nunfolder\nunfolders\nunfolding\nunfoldment\nunfoldments\nunfolds\nunfond\nunforced\nunforeseeable\nunforeseen\nunforested\nunforged\nunforgettable\nunforgettably\nunforgivable\nunforgiven\nunforgiving\nunforgivingness\nunforgivingnesses\nunforgot\nunforked\nunformed\nunformulated\nunforthcoming\nunfortified\nunfortunate\nunfortunately\nunfortunates\nunfossiliferous\nunfought\nunfound\nunfounded\nunframed\nunfree\nunfreed\nunfreedom\nunfreedoms\nunfreeing\nunfrees\nunfreeze\nunfreezes\nunfreezing\nunfrequented\nunfriended\nunfriendlier\nunfriendliest\nunfriendliness\nunfriendlinesses\nunfriendly\nunfrivolous\nunfrock\nunfrocked\nunfrocking\nunfrocks\nunfroze\nunfrozen\nunfruitful\nunfruitfully\nunfruitfulness\nunfruitfulnesses\nunfulfillable\nunfulfilled\nunfunded\nunfunny\nunfurl\nunfurled\nunfurling\nunfurls\nunfurnished\nunfused\nunfussily\nunfussy\nungainlier\nungainliest\nungainliness\nungainlinesses\nungainly\nungallant\nungallantly\nungalled\nungarnished\nungenerosities\nungenerosity\nungenerous\nungenerously\nungenial\nungenteel\nungentle\nungentlemanly\nungently\nungentrified\nungerminated\nungifted\nungimmicky\nungird\nungirded\nungirding\nungirds\nungirt\nunglamorized\nunglamorous\nunglazed\nunglove\nungloved\nungloves\nungloving\nunglue\nunglued\nunglues\nungluing\nungodlier\nungodliest\nungodliness\nungodlinesses\nungodly\nungot\nungotten\nungovernable\nungowned\nungraced\nungraceful\nungracefully\nungracious\nungraciously\nungraciousness\nungraciousnesses\nungraded\nungrammatical\nungrammaticalities\nungrammaticality\nungraspable\nungrateful\nungratefully\nungratefulness\nungratefulnesses\nungreedy\nunground\nungrounded\nungrouped\nungrudging\nungual\nunguard\nunguarded\nunguardedly\nunguardedness\nunguardednesses\nunguarding\nunguards\nunguent\nunguenta\nunguents\nunguentum\nungues\nunguessable\nunguided\nunguis\nungula\nungulae\nungular\nungulate\nungulates\nunhackneyed\nunhailed\nunhair\nunhaired\nunhairing\nunhairs\nunhallow\nunhallowed\nunhallowing\nunhallows\nunhalved\nunhampered\nunhand\nunhanded\nunhandicapped\nunhandier\nunhandiest\nunhandily\nunhandiness\nunhandinesses\nunhanding\nunhands\nunhandsome\nunhandsomely\nunhandy\nunhang\nunhanged\nunhanging\nunhangs\nunhappier\nunhappiest\nunhappily\nunhappiness\nunhappinesses\nunhappy\nunharmed\nunharness\nunharnessed\nunharnesses\nunharnessing\nunharvested\nunhasty\nunhat\nunhatched\nunhats\nunhatted\nunhatting\nunhealed\nunhealthful\nunhealthier\nunhealthiest\nunhealthily\nunhealthiness\nunhealthinesses\nunhealthy\nunheard\nunheated\nunhedged\nunheeded\nunheeding\nunhelm\nunhelmed\nunhelming\nunhelms\nunhelped\nunhelpful\nunhelpfully\nunheralded\nunheroic\nunhesitating\nunhesitatingly\nunhewn\nunhindered\nunhinge\nunhinged\nunhinges\nunhinging\nunhip\nunhired\nunhistorical\nunhitch\nunhitched\nunhitches\nunhitching\nunholier\nunholiest\nunholily\nunholiness\nunholinesses\nunholy\nunhomogenized\nunhonored\nunhood\nunhooded\nunhooding\nunhoods\nunhook\nunhooked\nunhooking\nunhooks\nunhoped\nunhopeful\nunhorse\nunhorsed\nunhorses\nunhorsing\nunhouse\nunhoused\nunhouseled\nunhouses\nunhousing\nunhuman\nunhumorous\nunhung\nunhurried\nunhurriedly\nunhurt\nunhusk\nunhusked\nunhusking\nunhusks\nunhydrolyzed\nunhygienic\nunhyphenated\nunhysterical\nunhysterically\nunialgal\nuniaxial\nunicameral\nunicamerally\nunicellular\nunicolor\nunicorn\nunicorns\nunicycle\nunicycles\nunicyclist\nunicyclists\nunideaed\nunideal\nunidentifiable\nunidentified\nunideological\nunidimensional\nunidimensionalities\nunidimensionality\nunidiomatic\nunidirectional\nunidirectionally\nuniface\nunifaces\nunifiable\nunific\nunification\nunifications\nunified\nunifier\nunifiers\nunifies\nunifilar\nunifoliate\nunifoliolate\nuniform\nuniformed\nuniformer\nuniformest\nuniforming\nuniformitarian\nuniformitarianism\nuniformitarianisms\nuniformitarians\nuniformities\nuniformity\nuniformly\nuniformness\nuniformnesses\nuniforms\nunify\nunifying\nunignorable\nunilateral\nunilaterally\nunilineal\nunilinear\nunilingual\nunilluminating\nunillusioned\nunilobed\nunilocular\nunimaginable\nunimaginably\nunimaginative\nunimaginatively\nunimbued\nunimmunized\nunimpaired\nunimpassioned\nunimpeachable\nunimpeachably\nunimpeded\nunimplemented\nunimportance\nunimportances\nunimportant\nunimposing\nunimpressed\nunimpressive\nunimproved\nunincorporated\nunindexed\nunindicted\nunindustrialized\nuninfected\nuninflated\nuninflected\nuninfluenced\nuninformative\nuninformatively\nuninformed\nuningratiating\nuninhabitable\nuninhabited\nuninhibited\nuninhibitedly\nuninhibitedness\nuninhibitednesses\nuninitiate\nuninitiated\nuninitiates\nuninjured\nuninoculated\nuninspected\nuninspired\nuninspiring\nuninstructed\nuninstructive\nuninsulated\nuninsurable\nuninsured\nunintegrated\nunintellectual\nunintelligent\nunintelligently\nunintelligibilities\nunintelligibility\nunintelligible\nunintelligibleness\nunintelligiblenesses\nunintelligibly\nunintended\nunintentional\nunintentionally\nuninterest\nuninterested\nuninteresting\nuninterests\nuninterrupted\nuninterruptedly\nunintimidated\nuninucleate\nuninventive\nuninvited\nuninviting\nuninvolved\nunion\nunionisation\nunionisations\nunionise\nunionised\nunionises\nunionising\nunionism\nunionisms\nunionist\nunionists\nunionization\nunionizations\nunionize\nunionized\nunionizes\nunionizing\nunions\nuniparental\nuniparentally\nunipod\nunipods\nunipolar\nunique\nuniquely\nuniqueness\nuniquenesses\nuniquer\nuniques\nuniquest\nunironed\nunironically\nunirradiated\nunirrigated\nunisex\nunisexes\nunisexual\nunisexualities\nunisexuality\nunison\nunisonal\nunisons\nunissued\nunit\nunitage\nunitages\nunitard\nunitards\nunitarian\nunitarianism\nunitarianisms\nunitarians\nunitarily\nunitary\nunite\nunited\nunitedly\nuniter\nuniters\nunites\nunities\nuniting\nunitive\nunitization\nunitizations\nunitize\nunitized\nunitizer\nunitizers\nunitizes\nunitizing\nunitrust\nunitrusts\nunits\nunity\nunivalent\nunivalents\nunivalve\nunivalves\nunivariate\nuniversal\nuniversalism\nuniversalisms\nuniversalist\nuniversalistic\nuniversalists\nuniversalities\nuniversality\nuniversalization\nuniversalizations\nuniversalize\nuniversalized\nuniversalizes\nuniversalizing\nuniversally\nuniversalness\nuniversalnesses\nuniversals\nuniverse\nuniverses\nuniversities\nuniversity\nunivocal\nunivocally\nunivocals\nunjaded\nunjam\nunjammed\nunjamming\nunjams\nunjoined\nunjoint\nunjointed\nunjointing\nunjoints\nunjoyful\nunjudged\nunjust\nunjustifiable\nunjustifiably\nunjustified\nunjustly\nunjustness\nunjustnesses\nunkempt\nunkend\nunkenned\nunkennel\nunkenneled\nunkenneling\nunkennelled\nunkennelling\nunkennels\nunkent\nunkept\nunkind\nunkinder\nunkindest\nunkindlier\nunkindliest\nunkindliness\nunkindlinesses\nunkindly\nunkindness\nunkindnesses\nunkingly\nunkink\nunkinked\nunkinking\nunkinks\nunkissed\nunknit\nunknits\nunknitted\nunknitting\nunknot\nunknots\nunknotted\nunknotting\nunknowabilities\nunknowability\nunknowable\nunknowing\nunknowingly\nunknowings\nunknowledgeable\nunknown\nunknowns\nunkosher\nunlabeled\nunlace\nunlaced\nunlaces\nunlacing\nunlade\nunladed\nunladen\nunlades\nunlading\nunladylike\nunlaid\nunlamented\nunlash\nunlashed\nunlashes\nunlashing\nunlatch\nunlatched\nunlatches\nunlatching\nunlaundered\nunlawful\nunlawfully\nunlawfulness\nunlawfulnesses\nunlay\nunlaying\nunlays\nunlead\nunleaded\nunleading\nunleads\nunlearn\nunlearnable\nunlearned\nunlearning\nunlearns\nunlearnt\nunleased\nunleash\nunleashed\nunleashes\nunleashing\nunleavened\nunled\nunless\nunlet\nunlethal\nunletted\nunlettered\nunlevel\nunleveled\nunleveling\nunlevelled\nunlevelling\nunlevels\nunlevied\nunliberated\nunlicensed\nunlicked\nunlikable\nunlike\nunlikelier\nunlikeliest\nunlikelihood\nunlikelihoods\nunlikeliness\nunlikelinesses\nunlikely\nunlikeness\nunlikenesses\nunlimber\nunlimbered\nunlimbering\nunlimbers\nunlimited\nunlimitedly\nunlined\nunlink\nunlinked\nunlinking\nunlinks\nunlisted\nunlistenable\nunlit\nunliterary\nunlivable\nunlive\nunlived\nunlively\nunlives\nunliving\nunload\nunloaded\nunloader\nunloaders\nunloading\nunloads\nunlobed\nunlocalized\nunlock\nunlocked\nunlocking\nunlocks\nunloose\nunloosed\nunloosen\nunloosened\nunloosening\nunloosens\nunlooses\nunloosing\nunlovable\nunloved\nunlovelier\nunloveliest\nunloveliness\nunlovelinesses\nunlovely\nunloving\nunluckier\nunluckiest\nunluckily\nunluckiness\nunluckinesses\nunlucky\nunlyrical\nunmacho\nunmade\nunmagnified\nunmake\nunmaker\nunmakers\nunmakes\nunmaking\nunmalicious\nunmaliciously\nunman\nunmanageable\nunmanageably\nunmanaged\nunmanful\nunmanipulated\nunmanlier\nunmanliest\nunmanliness\nunmanlinesses\nunmanly\nunmanned\nunmannered\nunmanneredly\nunmannerliness\nunmannerlinesses\nunmannerly\nunmanning\nunmans\nunmapped\nunmarked\nunmarketable\nunmarred\nunmarried\nunmarrieds\nunmasculine\nunmask\nunmasked\nunmasker\nunmaskers\nunmasking\nunmasks\nunmatchable\nunmatched\nunmated\nunmatted\nunmeaning\nunmeant\nunmeasurable\nunmeasured\nunmechanized\nunmediated\nunmedicated\nunmeet\nunmeetly\nunmellow\nunmelodious\nunmelodiousness\nunmelodiousnesses\nunmelted\nunmemorable\nunmemorably\nunmended\nunmentionable\nunmentionables\nunmentioned\nunmerciful\nunmercifully\nunmerited\nunmerry\nunmesh\nunmeshed\nunmeshes\nunmeshing\nunmet\nunmetabolized\nunmew\nunmewed\nunmewing\nunmews\nunmilitary\nunmilled\nunmindful\nunmined\nunmingle\nunmingled\nunmingles\nunmingling\nunmistakable\nunmistakably\nunmiter\nunmitered\nunmitering\nunmiters\nunmitigated\nunmitigatedly\nunmitigatedness\nunmitigatednesses\nunmitre\nunmitred\nunmitres\nunmitring\nunmix\nunmixable\nunmixed\nunmixes\nunmixing\nunmixt\nunmodernized\nunmodifiable\nunmodified\nunmodish\nunmold\nunmolded\nunmolding\nunmolds\nunmolested\nunmolten\nunmonitored\nunmoor\nunmoored\nunmooring\nunmoors\nunmoral\nunmoralities\nunmorality\nunmotivated\nunmounted\nunmourned\nunmovable\nunmoved\nunmoving\nunmown\nunmuffle\nunmuffled\nunmuffles\nunmuffling\nunmusical\nunmuzzle\nunmuzzled\nunmuzzles\nunmuzzling\nunmyelinated\nunnail\nunnailed\nunnailing\nunnails\nunnameable\nunnamed\nunnatural\nunnaturally\nunnaturalness\nunnaturalnesses\nunnecessarily\nunnecessary\nunneeded\nunnegotiable\nunnerve\nunnerved\nunnerves\nunnerving\nunnervingly\nunneurotic\nunnewsworthy\nunnilhexium\nunnilhexiums\nunnilpentium\nunnilpentiums\nunnilquadium\nunnilquadiums\nunnoisy\nunnoted\nunnoticeable\nunnoticed\nunnourishing\nunnumbered\nunobjectionable\nunobservable\nunobservant\nunobserved\nunobstructed\nunobtainable\nunobtrusive\nunobtrusively\nunobtrusiveness\nunobtrusivenesses\nunoccupied\nunofficial\nunofficially\nunoiled\nunopen\nunopenable\nunopened\nunopposed\nunordered\nunorganized\nunoriginal\nunornamented\nunornate\nunorthodox\nunorthodoxies\nunorthodoxly\nunorthodoxy\nunostentatious\nunostentatiously\nunowned\nunoxygenated\nunpack\nunpacked\nunpacker\nunpackers\nunpacking\nunpacks\nunpaged\nunpaid\nunpainted\nunpaired\nunpalatabilities\nunpalatability\nunpalatable\nunparalleled\nunparasitized\nunpardonable\nunparented\nunparliamentary\nunparted\nunpassable\nunpasteurized\nunpastoral\nunpatentable\nunpatriotic\nunpaved\nunpaying\nunpedantic\nunpeeled\nunpeg\nunpegged\nunpegging\nunpegs\nunpen\nunpenned\nunpenning\nunpens\nunpent\nunpeople\nunpeopled\nunpeoples\nunpeopling\nunperceived\nunperceptive\nunperfect\nunperformable\nunperformed\nunperson\nunpersons\nunpersuaded\nunpersuasive\nunperturbed\nunpick\nunpicked\nunpicking\nunpicks\nunpicturesque\nunpile\nunpiled\nunpiles\nunpiling\nunpin\nunpinned\nunpinning\nunpins\nunpitied\nunplaced\nunplait\nunplaited\nunplaiting\nunplaits\nunplanned\nunplausible\nunplayable\nunplayed\nunpleasant\nunpleasantly\nunpleasantness\nunpleasantnesses\nunpleased\nunpleasing\nunpliant\nunplowed\nunplug\nunplugged\nunplugging\nunplugs\nunplumbed\nunpoetic\nunpoised\nunpolarized\nunpoliced\nunpolished\nunpolite\nunpolitical\nunpolled\nunpolluted\nunpopular\nunpopularities\nunpopularity\nunposed\nunposted\nunpotted\nunpractical\nunprecedented\nunprecedentedly\nunpredictabilities\nunpredictability\nunpredictable\nunpredictables\nunpredictably\nunpregnant\nunprejudiced\nunpremeditated\nunprepared\nunpreparedness\nunpreparednesses\nunprepossessing\nunpressed\nunpressured\nunpressurized\nunpretending\nunpretentious\nunpretentiously\nunpretentiousness\nunpretentiousnesses\nunpretty\nunpriced\nunprimed\nunprincipled\nunprincipledness\nunprinciplednesses\nunprintable\nunprivileged\nunprized\nunprobed\nunproblematic\nunprocessed\nunproduced\nunproductive\nunprofessed\nunprofessional\nunprofessionally\nunprofessionals\nunprofitable\nunprofitableness\nunprofitablenesses\nunprofitably\nunprogrammable\nunprogrammed\nunprogressive\nunpromising\nunpromisingly\nunprompted\nunpronounceable\nunpronounced\nunpropitious\nunprosperous\nunprotected\nunprovable\nunproved\nunproven\nunprovoked\nunpruned\nunpublicized\nunpublishable\nunpublished\nunpucker\nunpuckered\nunpuckering\nunpuckers\nunpunctual\nunpunctualities\nunpunctuality\nunpunctuated\nunpunished\nunpure\nunpurged\nunpuzzle\nunpuzzled\nunpuzzles\nunpuzzling\nunqualified\nunqualifiedly\nunquantifiable\nunquenchable\nunquestionable\nunquestionably\nunquestioned\nunquestioning\nunquestioningly\nunquiet\nunquieter\nunquietest\nunquietly\nunquietness\nunquietnesses\nunquiets\nunquote\nunquoted\nunquotes\nunquoting\nunraised\nunraked\nunranked\nunrated\nunravel\nunraveled\nunraveling\nunravelled\nunravelling\nunravels\nunravished\nunrazed\nunreachable\nunreached\nunread\nunreadable\nunreadier\nunreadiest\nunreadiness\nunreadinesses\nunready\nunreal\nunrealistic\nunrealistically\nunrealities\nunreality\nunrealizable\nunrealized\nunreally\nunreason\nunreasonable\nunreasonableness\nunreasonablenesses\nunreasonably\nunreasoned\nunreasoning\nunreasoningly\nunreasons\nunreceptive\nunreclaimable\nunreclaimed\nunrecognizable\nunrecognizably\nunrecognized\nunreconcilable\nunreconciled\nunreconstructed\nunrecorded\nunrecoverable\nunrecovered\nunrecyclable\nunredeemable\nunredeemed\nunredressed\nunreel\nunreeled\nunreeler\nunreelers\nunreeling\nunreels\nunreeve\nunreeved\nunreeves\nunreeving\nunrefined\nunreflective\nunreformed\nunrefrigerated\nunregenerate\nunregenerately\nunregistered\nunregulated\nunrehearsed\nunreinforced\nunrelated\nunrelaxed\nunrelenting\nunrelentingly\nunreliabilities\nunreliability\nunreliable\nunrelieved\nunrelievedly\nunreligious\nunreluctant\nunremarkable\nunremarkably\nunremarked\nunremembered\nunreminiscent\nunremitting\nunremittingly\nunremorseful\nunremovable\nunrent\nunrented\nunrepaid\nunrepair\nunrepairs\nunrepeatable\nunrepentant\nunrepentantly\nunreported\nunrepresentative\nunrepresentativeness\nunrepresentativenesses\nunrepresented\nunrepressed\nunrequited\nunreserve\nunreserved\nunreservedly\nunreservedness\nunreservednesses\nunreserves\nunresistant\nunresisting\nunresolvable\nunresolved\nunrespectable\nunresponsive\nunresponsively\nunresponsiveness\nunresponsivenesses\nunrest\nunrested\nunrestful\nunrestored\nunrestrained\nunrestrainedly\nunrestrainedness\nunrestrainednesses\nunrestraint\nunrestraints\nunrestricted\nunrests\nunretouched\nunreturnable\nunrevealed\nunreviewable\nunreviewed\nunrevised\nunrevolutionary\nunrewarded\nunrewarding\nunrhetorical\nunrhymed\nunrhythmic\nunridable\nunriddle\nunriddled\nunriddles\nunriddling\nunrifled\nunrig\nunrigged\nunrigging\nunrighteous\nunrighteously\nunrighteousness\nunrighteousnesses\nunrigs\nunrimed\nunrinsed\nunrip\nunripe\nunripely\nunripened\nunripeness\nunripenesses\nunriper\nunripest\nunripped\nunripping\nunrips\nunrisen\nunrivaled\nunrivalled\nunrobe\nunrobed\nunrobes\nunrobing\nunroll\nunrolled\nunrolling\nunrolls\nunromantic\nunromantically\nunromanticized\nunroof\nunroofed\nunroofing\nunroofs\nunroot\nunrooted\nunrooting\nunroots\nunroped\nunrough\nunround\nunrounded\nunrounding\nunrounds\nunrove\nunroven\nunruffled\nunruled\nunrulier\nunruliest\nunruliness\nunrulinesses\nunruly\nunrushed\nunrusted\nuns\nunsaddle\nunsaddled\nunsaddles\nunsaddling\nunsafe\nunsafely\nunsafeties\nunsafety\nunsaid\nunsalable\nunsalaried\nunsalted\nunsalvageable\nunsanctioned\nunsanitary\nunsated\nunsatisfactorily\nunsatisfactoriness\nunsatisfactorinesses\nunsatisfactory\nunsatisfied\nunsatisfying\nunsaturate\nunsaturated\nunsaturates\nunsaved\nunsavory\nunsawed\nunsawn\nunsay\nunsayable\nunsaying\nunsays\nunscalable\nunscaled\nunscarred\nunscathed\nunscented\nunscheduled\nunscholarly\nunschooled\nunscientific\nunscientifically\nunscramble\nunscrambled\nunscrambler\nunscramblers\nunscrambles\nunscrambling\nunscreened\nunscrew\nunscrewed\nunscrewing\nunscrews\nunscripted\nunscriptural\nunscrupulous\nunscrupulously\nunscrupulousness\nunscrupulousnesses\nunseal\nunsealed\nunsealing\nunseals\nunseam\nunseamed\nunseaming\nunseams\nunsearchable\nunsearchably\nunseared\nunseasonable\nunseasonableness\nunseasonablenesses\nunseasonably\nunseasoned\nunseat\nunseated\nunseating\nunseats\nunseaworthy\nunsecured\nunseeded\nunseeing\nunseemlier\nunseemliest\nunseemliness\nunseemlinesses\nunseemly\nunseen\nunsegmented\nunsegregated\nunseized\nunselected\nunselective\nunselectively\nunselfish\nunselfishly\nunselfishness\nunselfishnesses\nunsell\nunsellable\nunselling\nunsells\nunsensational\nunsensitized\nunsent\nunsentimental\nunseparated\nunserious\nunseriousness\nunseriousnesses\nunserved\nunserviceable\nunset\nunsets\nunsetting\nunsettle\nunsettled\nunsettledness\nunsettlednesses\nunsettlement\nunsettlements\nunsettles\nunsettling\nunsettlingly\nunsew\nunsewed\nunsewing\nunsewn\nunsews\nunsex\nunsexed\nunsexes\nunsexing\nunsexual\nunsexy\nunshackle\nunshackled\nunshackles\nunshackling\nunshaded\nunshakable\nunshakably\nunshaken\nunshamed\nunshaped\nunshapely\nunshapen\nunshared\nunsharp\nunshaved\nunshaven\nunsheathe\nunsheathed\nunsheathes\nunsheathing\nunshed\nunshell\nunshelled\nunshelling\nunshells\nunshielded\nunshift\nunshifted\nunshifting\nunshifts\nunship\nunshipped\nunshipping\nunships\nunshockable\nunshod\nunshorn\nunshowy\nunshrunk\nunshut\nunsicker\nunsifted\nunsight\nunsighted\nunsighting\nunsightlier\nunsightliest\nunsightliness\nunsightlinesses\nunsightly\nunsights\nunsigned\nunsilent\nunsinful\nunsinkable\nunsized\nunskilled\nunskillful\nunskillfully\nunskillfulness\nunskillfulnesses\nunslakable\nunslaked\nunsliced\nunsling\nunslinging\nunslings\nunslung\nunsmart\nunsmiling\nunsmoked\nunsmoothed\nunsnap\nunsnapped\nunsnapping\nunsnaps\nunsnarl\nunsnarled\nunsnarling\nunsnarls\nunsoaked\nunsober\nunsociabilities\nunsociability\nunsociable\nunsociableness\nunsociablenesses\nunsociably\nunsocial\nunsocialized\nunsocially\nunsoiled\nunsold\nunsolder\nunsoldered\nunsoldering\nunsolders\nunsoldierly\nunsolicited\nunsolid\nunsolvable\nunsolved\nunsoncy\nunsonsie\nunsonsy\nunsophisticated\nunsophistication\nunsophistications\nunsorted\nunsought\nunsound\nunsounded\nunsounder\nunsoundest\nunsoundly\nunsoundness\nunsoundnesses\nunsoured\nunsowed\nunsown\nunsparing\nunsparingly\nunspeak\nunspeakable\nunspeakably\nunspeaking\nunspeaks\nunspecialized\nunspecifiable\nunspecific\nunspecified\nunspectacular\nunspent\nunsphere\nunsphered\nunspheres\nunsphering\nunspilt\nunspiritual\nunsplit\nunspoiled\nunspoilt\nunspoke\nunspoken\nunsportsmanlike\nunspotted\nunsprayed\nunsprung\nunspun\nunstable\nunstableness\nunstablenesses\nunstabler\nunstablest\nunstably\nunstack\nunstacked\nunstacking\nunstacks\nunstained\nunstandardized\nunstartling\nunstate\nunstated\nunstates\nunstating\nunstayed\nunsteadied\nunsteadier\nunsteadies\nunsteadiest\nunsteadily\nunsteadiness\nunsteadinesses\nunsteady\nunsteadying\nunsteel\nunsteeled\nunsteeling\nunsteels\nunstep\nunstepped\nunstepping\nunsteps\nunsterile\nunsterilized\nunstick\nunsticking\nunsticks\nunstinted\nunstinting\nunstintingly\nunstitch\nunstitched\nunstitches\nunstitching\nunstoned\nunstop\nunstoppable\nunstoppably\nunstopped\nunstopper\nunstoppered\nunstoppering\nunstoppers\nunstopping\nunstops\nunstrained\nunstrap\nunstrapped\nunstrapping\nunstraps\nunstratified\nunstress\nunstressed\nunstresses\nunstring\nunstringing\nunstrings\nunstructured\nunstrung\nunstuck\nunstudied\nunstuffy\nunstung\nunstylish\nunsubdued\nunsubsidized\nunsubstantial\nunsubstantialities\nunsubstantiality\nunsubstantially\nunsubstantiated\nunsubtle\nunsubtly\nunsuccess\nunsuccesses\nunsuccessful\nunsuccessfully\nunsuitabilities\nunsuitability\nunsuitable\nunsuitably\nunsuited\nunsullied\nunsung\nunsunk\nunsupervised\nunsupportable\nunsupported\nunsure\nunsurely\nunsurpassable\nunsurpassed\nunsurprised\nunsurprising\nunsurprisingly\nunsusceptible\nunsuspected\nunsuspecting\nunsuspectingly\nunsuspicious\nunsustainable\nunswathe\nunswathed\nunswathes\nunswathing\nunswayed\nunswear\nunswearing\nunswears\nunsweetened\nunswept\nunswerving\nunswore\nunsworn\nunsymmetrical\nunsymmetrically\nunsympathetic\nunsympathetically\nunsymptomatic\nunsynchronized\nunsystematic\nunsystematically\nunsystematized\nuntack\nuntacked\nuntacking\nuntacks\nuntactful\nuntagged\nuntainted\nuntaken\nuntalented\nuntamable\nuntame\nuntamed\nuntangle\nuntangled\nuntangles\nuntangling\nuntanned\nuntapped\nuntarnished\nuntasted\nuntaught\nuntaxed\nunteach\nunteachable\nunteaches\nunteaching\nuntechnical\nuntempered\nuntenabilities\nuntenability\nuntenable\nuntenanted\nuntended\nuntented\nuntenured\nuntestable\nuntested\nuntether\nuntethered\nuntethering\nuntethers\nunthawed\nuntheoretical\nunthink\nunthinkabilities\nunthinkability\nunthinkable\nunthinkably\nunthinking\nunthinkingly\nunthinks\nunthought\nunthread\nunthreaded\nunthreading\nunthreads\nunthreatening\nunthrifty\nunthrone\nunthroned\nunthrones\nunthroning\nuntidied\nuntidier\nuntidies\nuntidiest\nuntidily\nuntidiness\nuntidinesses\nuntidy\nuntidying\nuntie\nuntied\nunties\nuntil\nuntillable\nuntilled\nuntilted\nuntimelier\nuntimeliest\nuntimeliness\nuntimelinesses\nuntimely\nuntimeous\nuntinged\nuntipped\nuntired\nuntiring\nuntiringly\nuntitled\nunto\nuntogether\nuntold\nuntorn\nuntouchabilities\nuntouchability\nuntouchable\nuntouchables\nuntouched\nuntoward\nuntowardly\nuntowardness\nuntowardnesses\nuntraceable\nuntraced\nuntraditional\nuntraditionally\nuntrained\nuntrammeled\nuntransformed\nuntranslatabilities\nuntranslatability\nuntranslatable\nuntranslated\nuntraveled\nuntraversed\nuntread\nuntreading\nuntreads\nuntreated\nuntrendy\nuntried\nuntrim\nuntrimmed\nuntrimming\nuntrims\nuntrod\nuntrodden\nuntroubled\nuntrue\nuntruer\nuntruest\nuntruly\nuntruss\nuntrussed\nuntrusses\nuntrussing\nuntrusting\nuntrustworthy\nuntrusty\nuntruth\nuntruthful\nuntruthfully\nuntruthfulness\nuntruthfulnesses\nuntruths\nuntuck\nuntucked\nuntucking\nuntucks\nuntufted\nuntune\nuntuned\nuntunes\nuntuning\nunturned\nuntutored\nuntwine\nuntwined\nuntwines\nuntwining\nuntwist\nuntwisted\nuntwisting\nuntwists\nuntying\nuntypical\nuntypically\nununderstandable\nununited\nunurged\nunusable\nunused\nunusual\nunusually\nunusualness\nunusualnesses\nunutilized\nunutterable\nunutterably\nunvaccinated\nunvalued\nunvanquished\nunvaried\nunvarnished\nunvarying\nunveil\nunveiled\nunveiling\nunveilings\nunveils\nunveined\nunventilated\nunverbalized\nunverifiable\nunverified\nunversed\nunvexed\nunvext\nunviable\nunvisited\nunvocal\nunvoice\nunvoiced\nunvoices\nunvoicing\nunwalled\nunwaning\nunwanted\nunwarier\nunwariest\nunwarily\nunwariness\nunwarinesses\nunwarlike\nunwarmed\nunwarned\nunwarped\nunwarrantable\nunwarrantably\nunwarranted\nunwary\nunwashed\nunwashedness\nunwashednesses\nunwasheds\nunwasted\nunwatchable\nunwavering\nunwaveringly\nunwaxed\nunweaned\nunwearable\nunwearied\nunweariedly\nunweary\nunweathered\nunweave\nunweaves\nunweaving\nunwed\nunwedded\nunweeded\nunweeting\nunweetingly\nunweight\nunweighted\nunweighting\nunweights\nunwelcome\nunwelded\nunwell\nunwept\nunwetted\nunwhite\nunwholesome\nunwholesomely\nunwieldier\nunwieldiest\nunwieldily\nunwieldiness\nunwieldinesses\nunwieldy\nunwifely\nunwilled\nunwilling\nunwillingly\nunwillingness\nunwillingnesses\nunwind\nunwinder\nunwinders\nunwinding\nunwinds\nunwinnable\nunwisdom\nunwisdoms\nunwise\nunwisely\nunwiser\nunwisest\nunwish\nunwished\nunwishes\nunwishing\nunwit\nunwitnessed\nunwits\nunwitted\nunwitting\nunwittingly\nunwomanly\nunwon\nunwonted\nunwontedly\nunwontedness\nunwontednesses\nunwooded\nunwooed\nunworkabilities\nunworkability\nunworkable\nunworkables\nunworked\nunworking\nunworldliness\nunworldlinesses\nunworldly\nunworn\nunworried\nunworthier\nunworthies\nunworthiest\nunworthily\nunworthiness\nunworthinesses\nunworthy\nunwound\nunwounded\nunwove\nunwoven\nunwrap\nunwrapped\nunwrapping\nunwraps\nunwreathe\nunwreathed\nunwreathes\nunwreathing\nunwritten\nunwrung\nunyeaned\nunyielding\nunyieldingly\nunyoke\nunyoked\nunyokes\nunyoking\nunyoung\nunzip\nunzipped\nunzipping\nunzips\nunzoned\nup\nupas\nupases\nupbear\nupbearer\nupbearers\nupbearing\nupbears\nupbeat\nupbeats\nupbind\nupbinding\nupbinds\nupboil\nupboiled\nupboiling\nupboils\nupbore\nupborne\nupbound\nupbow\nupbows\nupbraid\nupbraided\nupbraider\nupbraiders\nupbraiding\nupbraids\nupbringing\nupbringings\nupbuild\nupbuilding\nupbuilds\nupbuilt\nupby\nupbye\nupcast\nupcasting\nupcasts\nupchuck\nupchucked\nupchucking\nupchucks\nupclimb\nupclimbed\nupclimbing\nupclimbs\nupcoast\nupcoil\nupcoiled\nupcoiling\nupcoils\nupcoming\nupcountry\nupcurl\nupcurled\nupcurling\nupcurls\nupcurve\nupcurved\nupcurves\nupcurving\nupdart\nupdarted\nupdarting\nupdarts\nupdate\nupdated\nupdater\nupdaters\nupdates\nupdating\nupdive\nupdived\nupdives\nupdiving\nupdo\nupdos\nupdove\nupdraft\nupdrafts\nupdried\nupdries\nupdry\nupdrying\nupend\nupended\nupending\nupends\nupfield\nupfling\nupflinging\nupflings\nupflow\nupflowed\nupflowing\nupflows\nupflung\nupfold\nupfolded\nupfolding\nupfolds\nupfront\nupgather\nupgathered\nupgathering\nupgathers\nupgaze\nupgazed\nupgazes\nupgazing\nupgird\nupgirded\nupgirding\nupgirds\nupgirt\nupgoing\nupgradabilities\nupgradability\nupgradable\nupgrade\nupgradeabilities\nupgradeability\nupgradeable\nupgraded\nupgrades\nupgrading\nupgrew\nupgrow\nupgrowing\nupgrown\nupgrows\nupgrowth\nupgrowths\nupheap\nupheaped\nupheaping\nupheaps\nupheaval\nupheavals\nupheave\nupheaved\nupheaver\nupheavers\nupheaves\nupheaving\nupheld\nuphill\nuphills\nuphoard\nuphoarded\nuphoarding\nuphoards\nuphold\nupholder\nupholders\nupholding\nupholds\nupholster\nupholstered\nupholsterer\nupholsterers\nupholsteries\nupholstering\nupholsters\nupholstery\nuphove\nuphroe\nuphroes\nupkeep\nupkeeps\nupland\nuplander\nuplanders\nuplands\nupleap\nupleaped\nupleaping\nupleaps\nupleapt\nuplift\nuplifted\nuplifter\nuplifters\nuplifting\nuplifts\nuplight\nuplighted\nuplighting\nuplights\nuplink\nuplinks\nuplit\nupload\nuploaded\nuploading\nuploads\nupmanship\nupmanships\nupmarket\nupmost\nupo\nupon\nupped\nupper\nuppercase\nuppercased\nuppercases\nuppercasing\nupperclassman\nupperclassmen\nuppercut\nuppercuts\nuppercutting\nuppermost\nupperpart\nupperparts\nuppers\nuppile\nuppiled\nuppiles\nuppiling\nupping\nuppings\nuppish\nuppishly\nuppishness\nuppishnesses\nuppitiness\nuppitinesses\nuppity\nuppityness\nuppitynesses\nupprop\nuppropped\nuppropping\nupprops\nupraise\nupraised\nupraiser\nupraisers\nupraises\nupraising\nuprate\nuprated\nuprates\nuprating\nupreach\nupreached\nupreaches\nupreaching\nuprear\nupreared\nuprearing\nuprears\nupright\nuprighted\nuprighting\nuprightly\nuprightness\nuprightnesses\nuprights\nuprise\nuprisen\nupriser\nuprisers\nuprises\nuprising\nuprisings\nupriver\nuprivers\nuproar\nuproarious\nuproariously\nuproariousness\nuproariousnesses\nuproars\nuproot\nuprootal\nuprootals\nuprooted\nuprootedness\nuprootednesses\nuprooter\nuprooters\nuprooting\nuproots\nuprose\nuprouse\nuproused\nuprouses\nuprousing\nuprush\nuprushed\nuprushes\nuprushing\nups\nupsadaisy\nupscale\nupscaled\nupscales\nupscaling\nupsend\nupsending\nupsends\nupsent\nupset\nupsets\nupsetter\nupsetters\nupsetting\nupshift\nupshifted\nupshifting\nupshifts\nupshoot\nupshooting\nupshoots\nupshot\nupshots\nupside\nupsides\nupsilon\nupsilons\nupsoar\nupsoared\nupsoaring\nupsoars\nupsprang\nupspring\nupspringing\nupsprings\nupsprung\nupstage\nupstaged\nupstages\nupstaging\nupstair\nupstairs\nupstand\nupstanding\nupstandingness\nupstandingnesses\nupstands\nupstare\nupstared\nupstares\nupstaring\nupstart\nupstarted\nupstarting\nupstarts\nupstate\nupstater\nupstaters\nupstates\nupstep\nupstepped\nupstepping\nupsteps\nupstir\nupstirred\nupstirring\nupstirs\nupstood\nupstream\nupstroke\nupstrokes\nupsurge\nupsurged\nupsurges\nupsurging\nupsweep\nupsweeping\nupsweeps\nupswell\nupswelled\nupswelling\nupswells\nupswept\nupswing\nupswinging\nupswings\nupswollen\nupswung\nuptake\nuptakes\nuptear\nuptearing\nuptears\nuptempo\nuptempos\nupthrew\nupthrow\nupthrowing\nupthrown\nupthrows\nupthrust\nupthrusting\nupthrusts\nuptick\nupticks\nuptight\nuptightness\nuptightnesses\nuptilt\nuptilted\nuptilting\nuptilts\nuptime\nuptimes\nuptore\nuptorn\nuptoss\nuptossed\nuptosses\nuptossing\nuptown\nuptowner\nuptowners\nuptowns\nuptrend\nuptrends\nupturn\nupturned\nupturning\nupturns\nupwaft\nupwafted\nupwafting\nupwafts\nupward\nupwardly\nupwardness\nupwardnesses\nupwards\nupwell\nupwelled\nupwelling\nupwellings\nupwells\nupwind\nupwinds\nuracil\nuracils\nuraei\nuraemia\nuraemias\nuraemic\nuraeus\nuraeuses\nuralite\nuralites\nuralitic\nurania\nuranias\nuranic\nuranide\nuranides\nuraninite\nuraninites\nuranism\nuranisms\nuranite\nuranites\nuranitic\nuranium\nuraniums\nuranographies\nuranography\nuranous\nuranyl\nuranylic\nuranyls\nurare\nurares\nurari\nuraris\nurase\nurases\nurate\nurates\nuratic\nurb\nurban\nurbane\nurbanely\nurbaner\nurbanest\nurbanisation\nurbanisations\nurbanise\nurbanised\nurbanises\nurbanising\nurbanism\nurbanisms\nurbanist\nurbanistic\nurbanistically\nurbanists\nurbanite\nurbanites\nurbanities\nurbanity\nurbanization\nurbanizations\nurbanize\nurbanized\nurbanizes\nurbanizing\nurbanologies\nurbanologist\nurbanologists\nurbanology\nurbia\nurbias\nurbs\nurceolate\nurchin\nurchins\nurd\nurds\nurea\nureal\nureas\nurease\nureases\nuredia\nuredial\nuredines\nuredinia\nuredinial\nurediniospore\nurediniospores\nuredinium\nurediospore\nurediospores\nuredium\nuredo\nuredos\nuredospore\nuredospores\nureic\nureide\nureides\nuremia\nuremias\nuremic\nureotelic\nureotelism\nureotelisms\nureter\nureteral\nureteric\nureters\nurethan\nurethane\nurethanes\nurethans\nurethra\nurethrae\nurethral\nurethras\nurethritis\nurethritises\nurethroscope\nurethroscopes\nuretic\nurge\nurged\nurgencies\nurgency\nurgent\nurgently\nurger\nurgers\nurges\nurging\nurgingly\nurial\nurials\nuric\nuricosuric\nuricotelic\nuricotelism\nuricotelisms\nuridine\nuridines\nurinal\nurinals\nurinalyses\nurinalysis\nurinaries\nurinary\nurinate\nurinated\nurinates\nurinating\nurination\nurinations\nurine\nurinemia\nurinemias\nurinemic\nurines\nurinogenital\nurinometer\nurinometers\nurinose\nurinous\nurn\nurnlike\nurns\nurochord\nurochordate\nurochordates\nurochords\nurochrome\nurochromes\nurodele\nurodeles\nurogenital\nurokinase\nurokinases\nurolith\nurolithiases\nurolithiasis\nuroliths\nurologic\nurological\nurologies\nurologist\nurologists\nurology\nuropod\nuropodal\nuropods\nuropygia\nuropygium\nuropygiums\nuroscopies\nuroscopy\nurostyle\nurostyles\nursa\nursae\nursiform\nursine\nurtext\nurtexts\nurticant\nurticants\nurticaria\nurticarial\nurticarias\nurticate\nurticated\nurticates\nurticating\nurtication\nurtications\nurus\nuruses\nurushiol\nurushiols\nus\nusabilities\nusability\nusable\nusableness\nusablenesses\nusably\nusage\nusages\nusance\nusances\nusaunce\nusaunces\nuse\nuseable\nuseably\nused\nuseful\nusefully\nusefulness\nusefulnesses\nuseless\nuselessly\nuselessness\nuselessnesses\nuser\nusers\nuses\nusher\nushered\nusherette\nusherettes\nushering\nushers\nusing\nusnea\nusneae\nusneas\nusquabae\nusquabaes\nusque\nusquebae\nusquebaes\nusquebaugh\nusquebaughs\nusques\nustulate\nusual\nusually\nusualness\nusualnesses\nusuals\nusufruct\nusufructs\nusufructuaries\nusufructuary\nusurer\nusurers\nusuries\nusurious\nusuriously\nusuriousness\nusuriousnesses\nusurp\nusurpation\nusurpations\nusurped\nusurper\nusurpers\nusurping\nusurps\nusury\nut\nuta\nutas\nutensil\nutensils\nuteri\nuterine\nuterus\nuteruses\nutile\nutilidor\nutilidors\nutilise\nutilised\nutiliser\nutilisers\nutilises\nutilising\nutilitarian\nutilitarianism\nutilitarianisms\nutilitarians\nutilities\nutility\nutilizable\nutilization\nutilizations\nutilize\nutilized\nutilizer\nutilizers\nutilizes\nutilizing\nutmost\nutmosts\nutopia\nutopian\nutopianism\nutopianisms\nutopians\nutopias\nutopism\nutopisms\nutopist\nutopistic\nutopists\nutricle\nutricles\nutricular\nutriculi\nutriculus\nuts\nutter\nutterable\nutterance\nutterances\nuttered\nutterer\nutterers\nuttering\nutterly\nuttermost\nuttermosts\nutters\nuvarovite\nuvarovites\nuvea\nuveal\nuveas\nuveitic\nuveitides\nuveitis\nuveitises\nuveous\nuvula\nuvulae\nuvular\nuvularly\nuvulars\nuvulas\nuvulitis\nuvulitises\nuxorial\nuxoricide\nuxoricides\nuxorious\nuxoriously\nuxoriousness\nuxoriousnesses\nvac\nvacancies\nvacancy\nvacant\nvacantly\nvacantness\nvacantnesses\nvacate\nvacated\nvacates\nvacating\nvacation\nvacationed\nvacationer\nvacationers\nvacationing\nvacationist\nvacationists\nvacationland\nvacationlands\nvacations\nvaccina\nvaccinal\nvaccinas\nvaccinate\nvaccinated\nvaccinates\nvaccinating\nvaccination\nvaccinations\nvaccinator\nvaccinators\nvaccine\nvaccinee\nvaccinees\nvaccines\nvaccinia\nvaccinial\nvaccinias\nvacillate\nvacillated\nvacillates\nvacillating\nvacillatingly\nvacillation\nvacillations\nvacillator\nvacillators\nvacs\nvacua\nvacuities\nvacuity\nvacuolar\nvacuolate\nvacuolated\nvacuolation\nvacuolations\nvacuole\nvacuoles\nvacuous\nvacuously\nvacuousness\nvacuousnesses\nvacuum\nvacuumed\nvacuuming\nvacuums\nvadose\nvagabond\nvagabondage\nvagabondages\nvagabonded\nvagabonding\nvagabondish\nvagabondism\nvagabondisms\nvagabonds\nvagal\nvagally\nvagaries\nvagarious\nvagariously\nvagary\nvagi\nvagile\nvagilities\nvagility\nvagina\nvaginae\nvaginal\nvaginally\nvaginas\nvaginate\nvaginismus\nvaginismuses\nvaginitides\nvaginitis\nvagotomies\nvagotomy\nvagotonia\nvagotonias\nvagotonic\nvagrancies\nvagrancy\nvagrant\nvagrantly\nvagrants\nvagrom\nvague\nvaguely\nvagueness\nvaguenesses\nvaguer\nvaguest\nvagus\nvahine\nvahines\nvail\nvailed\nvailing\nvails\nvain\nvainer\nvainest\nvainglories\nvainglorious\nvaingloriously\nvaingloriousness\nvaingloriousnesses\nvainglory\nvainly\nvainness\nvainnesses\nvair\nvairs\nvakeel\nvakeels\nvakil\nvakils\nvalance\nvalanced\nvalances\nvalancing\nvale\nvalediction\nvaledictions\nvaledictorian\nvaledictorians\nvaledictories\nvaledictory\nvalence\nvalences\nvalencia\nvalencias\nvalencies\nvalency\nvalentine\nvalentines\nvalerate\nvalerates\nvalerian\nvalerians\nvaleric\nvales\nvalet\nvaleted\nvaleting\nvalets\nvaletudinarian\nvaletudinarianism\nvaletudinarianisms\nvaletudinarians\nvaletudinaries\nvaletudinary\nvalgoid\nvalgus\nvalguses\nvaliance\nvaliances\nvaliancies\nvaliancy\nvaliant\nvaliantly\nvaliantness\nvaliantnesses\nvaliants\nvalid\nvalidate\nvalidated\nvalidates\nvalidating\nvalidation\nvalidations\nvalidities\nvalidity\nvalidly\nvaline\nvalines\nvalise\nvalises\nvalkyr\nvalkyrie\nvalkyries\nvalkyrs\nvallate\nvallecula\nvalleculae\nvallecular\nvalley\nvalleys\nvalonia\nvalonias\nvalor\nvalorise\nvalorised\nvalorises\nvalorising\nvalorization\nvalorizations\nvalorize\nvalorized\nvalorizes\nvalorizing\nvalorous\nvalorously\nvalors\nvalour\nvalours\nvalpolicella\nvalpolicellas\nvalse\nvalses\nvaluable\nvaluableness\nvaluablenesses\nvaluables\nvaluably\nvaluate\nvaluated\nvaluates\nvaluating\nvaluation\nvaluational\nvaluationally\nvaluations\nvaluator\nvaluators\nvalue\nvalued\nvalueless\nvaluelessness\nvaluelessnesses\nvaluer\nvaluers\nvalues\nvaluing\nvaluta\nvalutas\nvalval\nvalvar\nvalvate\nvalve\nvalved\nvalveless\nvalvelet\nvalvelets\nvalves\nvalving\nvalvula\nvalvulae\nvalvular\nvalvule\nvalvules\nvalvulitis\nvalvulitises\nvambrace\nvambraces\nvamoose\nvamoosed\nvamooses\nvamoosing\nvamose\nvamosed\nvamoses\nvamosing\nvamp\nvamped\nvamper\nvampers\nvamping\nvampire\nvampires\nvampiric\nvampirish\nvampirism\nvampirisms\nvampish\nvamps\nvan\nvanadate\nvanadates\nvanadic\nvanadium\nvanadiums\nvanadous\nvanaspati\nvanaspatis\nvanda\nvandal\nvandalic\nvandalise\nvandalised\nvandalises\nvandalising\nvandalism\nvandalisms\nvandalistic\nvandalization\nvandalizations\nvandalize\nvandalized\nvandalizes\nvandalizing\nvandals\nvandas\nvandyke\nvandyked\nvandykes\nvane\nvaned\nvanes\nvang\nvangs\nvanguard\nvanguardism\nvanguardisms\nvanguardist\nvanguardists\nvanguards\nvanilla\nvanillas\nvanillic\nvanillin\nvanillins\nvanish\nvanished\nvanisher\nvanishers\nvanishes\nvanishing\nvanishingly\nvanitied\nvanities\nvanitories\nvanitory\nvanity\nvanman\nvanmen\nvanned\nvanner\nvanners\nvanning\nvanpool\nvanpooling\nvanpoolings\nvanpools\nvanquish\nvanquishable\nvanquished\nvanquisher\nvanquishers\nvanquishes\nvanquishing\nvans\nvantage\nvantages\nvanward\nvapid\nvapidities\nvapidity\nvapidly\nvapidness\nvapidnesses\nvapor\nvapored\nvaporer\nvaporers\nvaporetti\nvaporetto\nvaporettos\nvaporing\nvaporings\nvaporise\nvaporised\nvaporises\nvaporish\nvaporishness\nvaporishnesses\nvaporising\nvaporizable\nvaporization\nvaporizations\nvaporize\nvaporized\nvaporizer\nvaporizers\nvaporizes\nvaporizing\nvaporous\nvaporously\nvaporousness\nvaporousnesses\nvapors\nvaporware\nvaporwares\nvapory\nvapour\nvapoured\nvapourer\nvapourers\nvapouring\nvapours\nvapoury\nvaquero\nvaqueros\nvar\nvara\nvaractor\nvaractors\nvaras\nvaria\nvariabilities\nvariability\nvariable\nvariableness\nvariablenesses\nvariables\nvariably\nvariance\nvariances\nvariant\nvariants\nvariate\nvariated\nvariates\nvariating\nvariation\nvariational\nvariationally\nvariations\nvaricella\nvaricellas\nvarices\nvaricocele\nvaricoceles\nvaricolored\nvaricose\nvaricosed\nvaricosities\nvaricosity\nvaried\nvariedly\nvariegate\nvariegated\nvariegates\nvariegating\nvariegation\nvariegations\nvariegator\nvariegators\nvarier\nvariers\nvaries\nvarietal\nvarietals\nvarieties\nvariety\nvariform\nvariola\nvariolar\nvariolas\nvariole\nvarioles\nvariometer\nvariometers\nvariorum\nvariorums\nvarious\nvariously\nvariousness\nvariousnesses\nvarisized\nvaristor\nvaristors\nvarix\nvarlet\nvarletries\nvarletry\nvarlets\nvarment\nvarments\nvarmint\nvarmints\nvarna\nvarnas\nvarnish\nvarnished\nvarnisher\nvarnishers\nvarnishes\nvarnishing\nvarnishy\nvaroom\nvaroomed\nvarooming\nvarooms\nvars\nvarsities\nvarsity\nvarus\nvaruses\nvarve\nvarved\nvarves\nvary\nvarying\nvaryingly\nvas\nvasa\nvasal\nvascula\nvascular\nvascularities\nvascularity\nvascularization\nvascularizations\nvasculature\nvasculatures\nvasculitides\nvasculitis\nvasculum\nvasculums\nvase\nvasectomies\nvasectomize\nvasectomized\nvasectomizes\nvasectomizing\nvasectomy\nvaselike\nvases\nvasiform\nvasoactive\nvasoactivities\nvasoactivity\nvasoconstriction\nvasoconstrictions\nvasoconstrictive\nvasoconstrictor\nvasoconstrictors\nvasodilatation\nvasodilatations\nvasodilation\nvasodilations\nvasodilator\nvasodilators\nvasomotor\nvasopressin\nvasopressins\nvasopressor\nvasopressors\nvasospasm\nvasospasms\nvasospastic\nvasotocin\nvasotocins\nvasotomies\nvasotomy\nvasovagal\nvassal\nvassalage\nvassalages\nvassals\nvast\nvaster\nvastest\nvastier\nvastiest\nvastities\nvastitude\nvastitudes\nvastity\nvastly\nvastness\nvastnesses\nvasts\nvasty\nvat\nvatful\nvatfuls\nvatic\nvatical\nvaticide\nvaticides\nvaticinal\nvaticinate\nvaticinated\nvaticinates\nvaticinating\nvaticination\nvaticinations\nvaticinator\nvaticinators\nvats\nvatted\nvatting\nvatu\nvatus\nvau\nvaudeville\nvaudevilles\nvaudevillian\nvaudevillians\nvault\nvaulted\nvaulter\nvaulters\nvaultier\nvaultiest\nvaulting\nvaultingly\nvaultings\nvaults\nvaulty\nvaunt\nvaunted\nvaunter\nvaunters\nvauntful\nvauntie\nvaunting\nvauntingly\nvaunts\nvaunty\nvaus\nvav\nvavasor\nvavasors\nvavasour\nvavasours\nvavassor\nvavassors\nvavs\nvaw\nvaward\nvawards\nvawntie\nvaws\nveal\nvealed\nvealer\nvealers\nvealier\nvealiest\nvealing\nveals\nvealy\nvector\nvectored\nvectorial\nvectorially\nvectoring\nvectors\nvedalia\nvedalias\nvedette\nvedettes\nvee\nveejay\nveejays\nveena\nveenas\nveep\nveepee\nveepees\nveeps\nveer\nveered\nveeries\nveering\nveeringly\nveers\nveery\nvees\nveg\nvegan\nveganism\nveganisms\nvegans\nvegetable\nvegetables\nvegetably\nvegetal\nvegetant\nvegetarian\nvegetarianism\nvegetarianisms\nvegetarians\nvegetate\nvegetated\nvegetates\nvegetating\nvegetation\nvegetational\nvegetations\nvegetative\nvegetatively\nvegetativeness\nvegetativenesses\nvegete\nvegetist\nvegetists\nvegetive\nveggie\nveggies\nvegie\nvegies\nvehemence\nvehemences\nvehement\nvehemently\nvehicle\nvehicles\nvehicular\nveil\nveiled\nveiledly\nveiler\nveilers\nveiling\nveilings\nveillike\nveils\nvein\nveinal\nveined\nveiner\nveiners\nveinier\nveiniest\nveining\nveinings\nveinless\nveinlet\nveinlets\nveinlike\nveins\nveinule\nveinules\nveinulet\nveinulets\nveiny\nvela\nvelamen\nvelamina\nvelar\nvelaria\nvelarium\nvelarization\nvelarizations\nvelarize\nvelarized\nvelarizes\nvelarizing\nvelars\nvelate\nveld\nvelds\nveldt\nveldts\nveliger\nveligers\nvelites\nvelleities\nvelleity\nvellum\nvellums\nveloce\nvelocimeter\nvelocimeters\nvelocipede\nvelocipedes\nvelociraptor\nvelociraptors\nvelocities\nvelocity\nvelodrome\nvelodromes\nvelour\nvelours\nveloute\nveloutes\nvelum\nvelure\nvelured\nvelures\nveluring\nvelveret\nvelverets\nvelvet\nvelveted\nvelveteen\nvelveteens\nvelvetlike\nvelvets\nvelvety\nvena\nvenae\nvenal\nvenalities\nvenality\nvenally\nvenatic\nvenation\nvenations\nvend\nvendable\nvendables\nvendace\nvendaces\nvended\nvendee\nvendees\nvender\nvenders\nvendetta\nvendettas\nvendeuse\nvendeuses\nvendibilities\nvendibility\nvendible\nvendibles\nvendibly\nvending\nvendor\nvendors\nvends\nvendue\nvendues\nveneer\nveneered\nveneerer\nveneerers\nveneering\nveneerings\nveneers\nvenenate\nvenenated\nvenenates\nvenenating\nvenenose\nvenerabilities\nvenerability\nvenerable\nvenerableness\nvenerablenesses\nvenerably\nvenerate\nvenerated\nvenerates\nvenerating\nveneration\nvenerations\nvenerator\nvenerators\nvenereal\nveneries\nvenery\nvenesection\nvenesections\nvenetian\nvenetians\nvenge\nvengeance\nvengeances\nvenged\nvengeful\nvengefully\nvengefulness\nvengefulnesses\nvenges\nvenging\nvenial\nvenially\nvenialness\nvenialnesses\nvenin\nvenine\nvenines\nvenins\nvenipuncture\nvenipunctures\nvenire\nvenireman\nveniremen\nvenires\nvenison\nvenisons\nvenogram\nvenograms\nvenographies\nvenography\nvenom\nvenomed\nvenomer\nvenomers\nvenoming\nvenomous\nvenomously\nvenomousness\nvenomousnesses\nvenoms\nvenose\nvenosities\nvenosity\nvenous\nvenously\nvent\nventage\nventages\nventail\nventails\nvented\nventer\nventers\nventifact\nventifacts\nventilate\nventilated\nventilates\nventilating\nventilation\nventilations\nventilator\nventilators\nventilatory\nventing\nventless\nventral\nventrally\nventrals\nventricle\nventricles\nventricose\nventricular\nventriculi\nventriculus\nventriloquial\nventriloquially\nventriloquies\nventriloquism\nventriloquisms\nventriloquist\nventriloquistic\nventriloquists\nventriloquize\nventriloquized\nventriloquizes\nventriloquizing\nventriloquy\nventrolateral\nventromedial\nvents\nventure\nventured\nventurer\nventurers\nventures\nventuresome\nventuresomely\nventuresomeness\nventuresomenesses\nventuri\nventuring\nventuris\nventurous\nventurously\nventurousness\nventurousnesses\nvenue\nvenues\nvenular\nvenule\nvenules\nvenulose\nvenulous\nvera\nveracious\nveraciously\nveraciousness\nveraciousnesses\nveracities\nveracity\nveranda\nverandaed\nverandah\nverandahed\nverandahs\nverandas\nverapamil\nverapamils\nveratria\nveratrias\nveratridine\nveratridines\nveratrin\nveratrine\nveratrines\nveratrins\nveratrum\nveratrums\nverb\nverbal\nverbalism\nverbalisms\nverbalist\nverbalistic\nverbalists\nverbalization\nverbalizations\nverbalize\nverbalized\nverbalizer\nverbalizers\nverbalizes\nverbalizing\nverbally\nverbals\nverbatim\nverbena\nverbenas\nverbiage\nverbiages\nverbicide\nverbicides\nverbid\nverbids\nverbified\nverbifies\nverbify\nverbifying\nverbigeration\nverbigerations\nverbile\nverbiles\nverbless\nverbose\nverbosely\nverboseness\nverbosenesses\nverbosities\nverbosity\nverboten\nverbs\nverdancies\nverdancy\nverdant\nverdantly\nverderer\nverderers\nverderor\nverderors\nverdict\nverdicts\nverdigris\nverdigrises\nverdin\nverdins\nverditer\nverditers\nverdure\nverdured\nverdures\nverdurous\nverecund\nverge\nverged\nvergence\nvergences\nverger\nvergers\nverges\nverging\nverglas\nverglases\nveridic\nveridical\nveridicalities\nveridicality\nveridically\nverier\nveriest\nverifiabilities\nverifiability\nverifiable\nverifiableness\nverifiablenesses\nverification\nverifications\nverified\nverifier\nverifiers\nverifies\nverify\nverifying\nverily\nverisimilar\nverisimilarly\nverisimilitude\nverisimilitudes\nverisimilitudinous\nverism\nverismo\nverismos\nverisms\nverist\nveristic\nverists\nveritable\nveritableness\nveritablenesses\nveritably\nveritas\nveritates\nverite\nverites\nverities\nverity\nverjuice\nverjuices\nvermeil\nvermeils\nvermes\nvermian\nvermicelli\nvermicellis\nvermicide\nvermicides\nvermicular\nvermiculate\nvermiculated\nvermiculation\nvermiculations\nvermiculite\nvermiculites\nvermiform\nvermifuge\nvermifuges\nvermilion\nvermilions\nvermillion\nvermillions\nvermin\nverminous\nvermis\nvermoulu\nvermouth\nvermouths\nvermuth\nvermuths\nvernacle\nvernacles\nvernacular\nvernacularism\nvernacularisms\nvernacularly\nvernaculars\nvernal\nvernalization\nvernalizations\nvernalize\nvernalized\nvernalizes\nvernalizing\nvernally\nvernation\nvernations\nvernicle\nvernicles\nvernier\nverniers\nvernissage\nvernissages\nvernix\nvernixes\nveronica\nveronicas\nverruca\nverrucae\nverrucose\nversal\nversant\nversants\nversatile\nversatilely\nversatileness\nversatilenesses\nversatilities\nversatility\nverse\nversed\nverseman\nversemen\nverser\nversers\nverses\nverset\nversets\nversicle\nversicles\nversicular\nversification\nversifications\nversified\nversifier\nversifiers\nversifies\nversify\nversifying\nversine\nversines\nversing\nversion\nversional\nversions\nverso\nversos\nverst\nverste\nverstes\nversts\nversus\nvert\nvertebra\nvertebrae\nvertebral\nvertebras\nvertebrate\nvertebrates\nvertex\nvertexes\nvertical\nverticalities\nverticality\nvertically\nverticalness\nverticalnesses\nverticals\nvertices\nverticil\nverticillate\nverticils\nvertigines\nvertiginous\nvertiginously\nvertigo\nvertigoes\nvertigos\nverts\nvertu\nvertus\nvervain\nvervains\nverve\nverves\nvervet\nvervets\nvery\nvesica\nvesicae\nvesical\nvesicant\nvesicants\nvesicate\nvesicated\nvesicates\nvesicating\nvesicle\nvesicles\nvesicula\nvesiculae\nvesicular\nvesicularities\nvesicularity\nvesiculate\nvesiculated\nvesiculates\nvesiculating\nvesiculation\nvesiculations\nvesper\nvesperal\nvesperals\nvespers\nvespertilian\nvespertine\nvespiaries\nvespiary\nvespid\nvespids\nvespine\nvessel\nvesseled\nvessels\nvest\nvesta\nvestal\nvestally\nvestals\nvestas\nvested\nvestee\nvestees\nvestiaries\nvestiary\nvestibular\nvestibule\nvestibuled\nvestibules\nvestige\nvestiges\nvestigia\nvestigial\nvestigially\nvestigium\nvesting\nvestings\nvestless\nvestlike\nvestment\nvestmental\nvestments\nvestral\nvestries\nvestry\nvestryman\nvestrymen\nvests\nvestural\nvesture\nvestured\nvestures\nvesturing\nvesuvian\nvesuvianite\nvesuvianites\nvesuvians\nvet\nvetch\nvetches\nvetchling\nvetchlings\nveteran\nveterans\nveterinarian\nveterinarians\nveterinaries\nveterinary\nvetiver\nvetivers\nvetivert\nvetiverts\nveto\nvetoed\nvetoer\nvetoers\nvetoes\nvetoing\nvets\nvetted\nvetting\nvex\nvexation\nvexations\nvexatious\nvexatiously\nvexatiousness\nvexatiousnesses\nvexed\nvexedly\nvexer\nvexers\nvexes\nvexil\nvexilla\nvexillar\nvexillologic\nvexillological\nvexillologies\nvexillologist\nvexillologists\nvexillology\nvexillum\nvexils\nvexing\nvexingly\nvext\nvia\nviabilities\nviability\nviable\nviably\nviaduct\nviaducts\nvial\nvialed\nvialing\nvialled\nvialling\nvials\nviand\nviands\nviatic\nviatica\nviatical\nviaticum\nviaticums\nviator\nviatores\nviators\nvibe\nvibes\nvibist\nvibists\nvibraharp\nvibraharpist\nvibraharpists\nvibraharps\nvibrance\nvibrances\nvibrancies\nvibrancy\nvibrant\nvibrantly\nvibrants\nvibraphone\nvibraphones\nvibraphonist\nvibraphonists\nvibrate\nvibrated\nvibrates\nvibratile\nvibrating\nvibration\nvibrational\nvibrationless\nvibrations\nvibrato\nvibratoless\nvibrator\nvibrators\nvibratory\nvibratos\nvibrio\nvibrioid\nvibrion\nvibriones\nvibrionic\nvibrions\nvibrios\nvibrioses\nvibriosis\nvibrissa\nvibrissae\nvibronic\nviburnum\nviburnums\nvicar\nvicarage\nvicarages\nvicarate\nvicarates\nvicarial\nvicariance\nvicariances\nvicariant\nvicariants\nvicariate\nvicariates\nvicarious\nvicariously\nvicariousness\nvicariousnesses\nvicarly\nvicars\nvicarship\nvicarships\nvice\nviced\nvicegerencies\nvicegerency\nvicegerent\nvicegerents\nviceless\nvicenary\nvicennial\nviceregal\nviceregally\nvicereine\nvicereines\nviceroy\nviceroyalties\nviceroyalty\nviceroys\nviceroyship\nviceroyships\nvices\nvichies\nvichy\nvichyssoise\nvichyssoises\nvicinage\nvicinages\nvicinal\nvicing\nvicinities\nvicinity\nvicious\nviciously\nviciousness\nviciousnesses\nvicissitude\nvicissitudes\nvicissitudinous\nvicomte\nvicomtes\nvictim\nvictimhood\nvictimhoods\nvictimise\nvictimised\nvictimises\nvictimising\nvictimization\nvictimizations\nvictimize\nvictimized\nvictimizer\nvictimizers\nvictimizes\nvictimizing\nvictimless\nvictimologies\nvictimologist\nvictimologists\nvictimology\nvictims\nvictor\nvictoria\nvictorias\nvictories\nvictorious\nvictoriously\nvictoriousness\nvictoriousnesses\nvictors\nvictory\nvictress\nvictresses\nvictual\nvictualed\nvictualer\nvictualers\nvictualing\nvictualled\nvictualler\nvictuallers\nvictualling\nvictuals\nvicugna\nvicugnas\nvicuna\nvicunas\nvide\nvidelicet\nvideo\nvideocassette\nvideocassettes\nvideoconference\nvideoconferences\nvideoconferencing\nvideoconferencings\nvideodisc\nvideodiscs\nvideodisk\nvideodisks\nvideographer\nvideographers\nvideographies\nvideography\nvideoland\nvideolands\nvideophile\nvideophiles\nvideophone\nvideophones\nvideorecorder\nvideorecorders\nvideos\nvideotape\nvideotaped\nvideotapes\nvideotaping\nvideotex\nvideotexes\nvideotext\nvideotexts\nvidette\nvidettes\nvidicon\nvidicons\nviduities\nviduity\nvie\nvied\nvier\nviers\nvies\nview\nviewable\nviewdata\nviewdatas\nviewed\nviewer\nviewers\nviewership\nviewerships\nviewfinder\nviewfinders\nviewier\nviewiest\nviewing\nviewings\nviewless\nviewlessly\nviewpoint\nviewpoints\nviews\nviewy\nvig\nviga\nvigas\nvigesimal\nvigil\nvigilance\nvigilances\nvigilant\nvigilante\nvigilantes\nvigilantism\nvigilantisms\nvigilantly\nvigils\nvigintillion\nvigintillions\nvigneron\nvignerons\nvignette\nvignetted\nvignetter\nvignetters\nvignettes\nvignetting\nvignettist\nvignettists\nvigor\nvigorish\nvigorishes\nvigoroso\nvigorous\nvigorously\nvigorousness\nvigorousnesses\nvigors\nvigour\nvigours\nvigs\nviking\nvikings\nvilayet\nvilayets\nvile\nvilely\nvileness\nvilenesses\nviler\nvilest\nvilification\nvilifications\nvilified\nvilifier\nvilifiers\nvilifies\nvilify\nvilifying\nvilipend\nvilipended\nvilipending\nvilipends\nvill\nvilla\nvilladom\nvilladoms\nvillae\nvillage\nvillager\nvillageries\nvillagers\nvillagery\nvillages\nvillain\nvillainess\nvillainesses\nvillainies\nvillainous\nvillainously\nvillainousness\nvillainousnesses\nvillains\nvillainy\nvillanella\nvillanelle\nvillanelles\nvillas\nvillatic\nvillein\nvilleins\nvillenage\nvillenages\nvilli\nvilliform\nvillose\nvillosities\nvillosity\nvillous\nvills\nvillus\nvim\nvimen\nvimina\nviminal\nvims\nvina\nvinaceous\nvinaigrette\nvinaigrettes\nvinal\nvinals\nvinas\nvinasse\nvinasses\nvinblastine\nvinblastines\nvinca\nvincas\nvincible\nvincibly\nvincristine\nvincristines\nvincula\nvinculum\nvinculums\nvindaloo\nvindaloos\nvindicable\nvindicate\nvindicated\nvindicates\nvindicating\nvindication\nvindications\nvindicative\nvindicator\nvindicators\nvindicatory\nvindictive\nvindictively\nvindictiveness\nvindictivenesses\nvine\nvineal\nvined\nvinedresser\nvinedressers\nvinegar\nvinegared\nvinegarish\nvinegars\nvinegary\nvineries\nvinery\nvines\nvineyard\nvineyardist\nvineyardists\nvineyards\nvinic\nviniculture\nvinicultures\nvinier\nviniest\nvinifera\nviniferas\nvinification\nvinifications\nvinified\nvinifies\nvinify\nvinifying\nvining\nvino\nvinos\nvinosities\nvinosity\nvinous\nvinously\nvintage\nvintager\nvintagers\nvintages\nvintner\nvintners\nviny\nvinyl\nvinylic\nvinylidene\nvinylidenes\nvinyls\nviol\nviola\nviolabilities\nviolability\nviolable\nviolableness\nviolablenesses\nviolably\nviolaceous\nviolas\nviolate\nviolated\nviolater\nviolaters\nviolates\nviolating\nviolation\nviolations\nviolative\nviolator\nviolators\nviolence\nviolences\nviolent\nviolently\nviolet\nviolets\nviolin\nviolinist\nviolinistic\nviolinists\nviolins\nviolist\nviolists\nvioloncelli\nvioloncellist\nvioloncellists\nvioloncello\nvioloncellos\nviolone\nviolones\nviols\nviomycin\nviomycins\nviper\nviperine\nviperish\nviperous\nviperously\nvipers\nviraginous\nvirago\nviragoes\nviragos\nviral\nvirally\nvirelai\nvirelais\nvirelay\nvirelays\nviremia\nviremias\nviremic\nvireo\nvireos\nvires\nvirescence\nvirescences\nvirescent\nvirga\nvirgas\nvirgate\nvirgates\nvirgin\nvirginal\nvirginalist\nvirginalists\nvirginally\nvirginals\nvirginities\nvirginity\nvirgins\nvirgule\nvirgules\nviricidal\nviricide\nviricides\nvirid\nviridescent\nviridian\nviridians\nviridities\nviridity\nvirile\nvirilely\nvirilism\nvirilisms\nvirilities\nvirility\nvirion\nvirions\nvirl\nvirls\nviroid\nviroids\nvirologic\nvirological\nvirologically\nvirologies\nvirologist\nvirologists\nvirology\nviroses\nvirosis\nvirtu\nvirtual\nvirtualities\nvirtuality\nvirtually\nvirtue\nvirtueless\nvirtues\nvirtuosa\nvirtuosas\nvirtuose\nvirtuosi\nvirtuosic\nvirtuosities\nvirtuosity\nvirtuoso\nvirtuosos\nvirtuous\nvirtuously\nvirtuousness\nvirtuousnesses\nvirtus\nvirucidal\nvirucide\nvirucides\nvirulence\nvirulences\nvirulencies\nvirulency\nvirulent\nvirulently\nviruliferous\nvirus\nviruses\nvis\nvisa\nvisaed\nvisage\nvisaged\nvisages\nvisaing\nvisard\nvisards\nvisas\nviscacha\nviscachas\nviscera\nvisceral\nviscerally\nviscid\nviscidities\nviscidity\nviscidly\nviscoelastic\nviscoelasticities\nviscoelasticity\nviscoid\nviscometer\nviscometers\nviscometric\nviscometries\nviscometry\nviscose\nviscoses\nviscosimeter\nviscosimeters\nviscosimetric\nviscosities\nviscosity\nviscount\nviscountcies\nviscountcy\nviscountess\nviscountesses\nviscounties\nviscounts\nviscounty\nviscous\nviscously\nviscousness\nviscousnesses\nviscus\nvise\nvised\nviseed\nviseing\nviselike\nvises\nvisibilities\nvisibility\nvisible\nvisibleness\nvisiblenesses\nvisibly\nvising\nvision\nvisional\nvisionally\nvisionaries\nvisionariness\nvisionarinesses\nvisionary\nvisioned\nvisioning\nvisionless\nvisions\nvisit\nvisitable\nvisitant\nvisitants\nvisitation\nvisitations\nvisitatorial\nvisited\nvisiter\nvisiters\nvisiting\nvisitor\nvisitors\nvisits\nvisive\nvisor\nvisored\nvisoring\nvisorless\nvisors\nvista\nvistaed\nvistas\nvisual\nvisualise\nvisualised\nvisualises\nvisualising\nvisualization\nvisualizations\nvisualize\nvisualized\nvisualizer\nvisualizers\nvisualizes\nvisualizing\nvisually\nvisuals\nvita\nvitae\nvital\nvitalise\nvitalised\nvitalises\nvitalising\nvitalism\nvitalisms\nvitalist\nvitalistic\nvitalists\nvitalities\nvitality\nvitalization\nvitalizations\nvitalize\nvitalized\nvitalizes\nvitalizing\nvitally\nvitals\nvitamer\nvitamers\nvitamin\nvitamine\nvitamines\nvitamins\nvitelli\nvitellin\nvitelline\nvitellins\nvitellogeneses\nvitellogenesis\nvitellus\nvitelluses\nvitesse\nvitesses\nvitiable\nvitiate\nvitiated\nvitiates\nvitiating\nvitiation\nvitiations\nvitiator\nvitiators\nviticultural\nviticulturally\nviticulture\nviticultures\nviticulturist\nviticulturists\nvitiligo\nvitiligos\nvitrain\nvitrains\nvitrectomies\nvitrectomy\nvitreous\nvitreouses\nvitric\nvitrics\nvitrifiable\nvitrification\nvitrifications\nvitrified\nvitrifies\nvitrify\nvitrifying\nvitrine\nvitrines\nvitriol\nvitrioled\nvitriolic\nvitrioling\nvitriolled\nvitriolling\nvitriols\nvitta\nvittae\nvittate\nvittle\nvittled\nvittles\nvittling\nvituline\nvituperate\nvituperated\nvituperates\nvituperating\nvituperation\nvituperations\nvituperative\nvituperatively\nvituperator\nvituperators\nvituperatory\nviva\nvivace\nvivaces\nvivacious\nvivaciously\nvivaciousness\nvivaciousnesses\nvivacities\nvivacity\nvivandiere\nvivandieres\nvivaria\nvivaries\nvivarium\nvivariums\nvivary\nvivas\nvive\nviverrid\nviverrids\nvivers\nvivid\nvivider\nvividest\nvividly\nvividness\nvividnesses\nvivific\nvivification\nvivifications\nvivified\nvivifier\nvivifiers\nvivifies\nvivify\nvivifying\nvivipara\nviviparities\nviviparity\nviviparous\nviviparously\nvivisect\nvivisected\nvivisecting\nvivisection\nvivisectional\nvivisectionist\nvivisectionists\nvivisections\nvivisector\nvivisectors\nvivisects\nvixen\nvixenish\nvixenly\nvixens\nvizard\nvizarded\nvizards\nvizcacha\nvizcachas\nvizier\nvizierate\nvizierates\nvizierial\nviziers\nviziership\nvizierships\nvizir\nvizirate\nvizirates\nvizirial\nvizirs\nvizor\nvizored\nvizoring\nvizors\nvizsla\nvizslas\nvocable\nvocables\nvocably\nvocabular\nvocabularies\nvocabulary\nvocal\nvocalic\nvocalically\nvocalics\nvocalise\nvocalised\nvocalises\nvocalising\nvocalism\nvocalisms\nvocalist\nvocalists\nvocalities\nvocality\nvocalization\nvocalizations\nvocalize\nvocalized\nvocalizer\nvocalizers\nvocalizes\nvocalizing\nvocally\nvocals\nvocation\nvocational\nvocationalism\nvocationalisms\nvocationalist\nvocationalists\nvocationally\nvocations\nvocative\nvocatively\nvocatives\nvoces\nvociferant\nvociferate\nvociferated\nvociferates\nvociferating\nvociferation\nvociferations\nvociferator\nvociferators\nvociferous\nvociferously\nvociferousness\nvociferousnesses\nvocoder\nvocoders\nvodka\nvodkas\nvodoun\nvodouns\nvodun\nvoduns\nvoe\nvoes\nvogie\nvogue\nvogued\nvogueing\nvoguer\nvoguers\nvogues\nvoguing\nvoguish\nvoguishness\nvoguishnesses\nvoice\nvoiced\nvoiceful\nvoicefulness\nvoicefulnesses\nvoiceless\nvoicelessly\nvoicelessness\nvoicelessnesses\nvoiceover\nvoiceovers\nvoiceprint\nvoiceprints\nvoicer\nvoicers\nvoices\nvoicing\nvoid\nvoidable\nvoidableness\nvoidablenesses\nvoidance\nvoidances\nvoided\nvoider\nvoiders\nvoiding\nvoidness\nvoidnesses\nvoids\nvoila\nvoile\nvoiles\nvolant\nvolante\nvolar\nvolatile\nvolatileness\nvolatilenesses\nvolatiles\nvolatilise\nvolatilised\nvolatilises\nvolatilising\nvolatilities\nvolatility\nvolatilizable\nvolatilization\nvolatilizations\nvolatilize\nvolatilized\nvolatilizes\nvolatilizing\nvolcanic\nvolcanically\nvolcanicities\nvolcanicity\nvolcanics\nvolcanism\nvolcanisms\nvolcano\nvolcanoes\nvolcanologic\nvolcanological\nvolcanologies\nvolcanologist\nvolcanologists\nvolcanology\nvolcanos\nvole\nvoled\nvoleries\nvolery\nvoles\nvoling\nvolitant\nvolition\nvolitional\nvolitions\nvolitive\nvolkslied\nvolkslieder\nvolley\nvolleyball\nvolleyballs\nvolleyed\nvolleyer\nvolleyers\nvolleying\nvolleys\nvolost\nvolosts\nvolplane\nvolplaned\nvolplanes\nvolplaning\nvolt\nvolta\nvoltage\nvoltages\nvoltaic\nvoltaism\nvoltaisms\nvolte\nvoltes\nvolti\nvoltmeter\nvoltmeters\nvolts\nvolubilities\nvolubility\nvoluble\nvolubleness\nvolublenesses\nvolubly\nvolume\nvolumed\nvolumes\nvolumeter\nvolumeters\nvolumetric\nvolumetrically\nvoluming\nvoluminosities\nvoluminosity\nvoluminous\nvoluminously\nvoluminousness\nvoluminousnesses\nvoluntaries\nvoluntarily\nvoluntariness\nvoluntarinesses\nvoluntarism\nvoluntarisms\nvoluntarist\nvoluntaristic\nvoluntarists\nvoluntary\nvoluntaryism\nvoluntaryisms\nvoluntaryist\nvoluntaryists\nvolunteer\nvolunteered\nvolunteering\nvolunteerism\nvolunteerisms\nvolunteers\nvoluptuaries\nvoluptuary\nvoluptuous\nvoluptuously\nvoluptuousness\nvoluptuousnesses\nvolute\nvoluted\nvolutes\nvolutin\nvolutins\nvolution\nvolutions\nvolva\nvolvas\nvolvate\nvolvox\nvolvoxes\nvolvuli\nvolvulus\nvolvuluses\nvomer\nvomerine\nvomers\nvomica\nvomicae\nvomit\nvomited\nvomiter\nvomiters\nvomiting\nvomitive\nvomitives\nvomito\nvomitories\nvomitory\nvomitos\nvomitous\nvomits\nvomitus\nvomituses\nvoodoo\nvoodooed\nvoodooing\nvoodooism\nvoodooisms\nvoodooist\nvoodooistic\nvoodooists\nvoodoos\nvoracious\nvoraciously\nvoraciousness\nvoraciousnesses\nvoracities\nvoracity\nvorlage\nvorlages\nvortex\nvortexes\nvortical\nvortically\nvorticella\nvorticellae\nvorticellas\nvortices\nvorticism\nvorticisms\nvorticist\nvorticists\nvorticities\nvorticity\nvorticose\nvotable\nvotaress\nvotaresses\nvotaries\nvotarist\nvotarists\nvotary\nvote\nvoteable\nvoted\nvoteless\nvoter\nvoters\nvotes\nvoting\nvotive\nvotively\nvotiveness\nvotivenesses\nvotress\nvotresses\nvouch\nvouched\nvouchee\nvouchees\nvoucher\nvouchered\nvouchering\nvouchers\nvouches\nvouching\nvouchsafe\nvouchsafed\nvouchsafement\nvouchsafements\nvouchsafes\nvouchsafing\nvoussoir\nvoussoirs\nvouvray\nvouvrays\nvow\nvowed\nvowel\nvowelize\nvowelized\nvowelizes\nvowelizing\nvowels\nvower\nvowers\nvowing\nvowless\nvows\nvox\nvoyage\nvoyaged\nvoyager\nvoyagers\nvoyages\nvoyageur\nvoyageurs\nvoyaging\nvoyeur\nvoyeurism\nvoyeurisms\nvoyeuristic\nvoyeuristically\nvoyeurs\nvroom\nvroomed\nvrooming\nvrooms\nvrouw\nvrouws\nvrow\nvrows\nvug\nvugg\nvuggier\nvuggiest\nvuggs\nvuggy\nvugh\nvughs\nvugs\nvulcanian\nvulcanic\nvulcanicities\nvulcanicity\nvulcanisate\nvulcanisates\nvulcanisation\nvulcanisations\nvulcanise\nvulcanised\nvulcanises\nvulcanising\nvulcanism\nvulcanisms\nvulcanizate\nvulcanizates\nvulcanization\nvulcanizations\nvulcanize\nvulcanized\nvulcanizer\nvulcanizers\nvulcanizes\nvulcanizing\nvulcanologies\nvulcanologist\nvulcanologists\nvulcanology\nvulgar\nvulgarer\nvulgarest\nvulgarian\nvulgarians\nvulgarise\nvulgarised\nvulgarises\nvulgarising\nvulgarism\nvulgarisms\nvulgarities\nvulgarity\nvulgarization\nvulgarizations\nvulgarize\nvulgarized\nvulgarizer\nvulgarizers\nvulgarizes\nvulgarizing\nvulgarly\nvulgars\nvulgate\nvulgates\nvulgo\nvulgus\nvulguses\nvulnerabilities\nvulnerability\nvulnerable\nvulnerableness\nvulnerablenesses\nvulnerably\nvulneraries\nvulnerary\nvulpine\nvulture\nvultures\nvulturine\nvulturish\nvulturous\nvulva\nvulvae\nvulval\nvulvar\nvulvas\nvulvate\nvulvitis\nvulvitises\nvulvovaginitides\nvulvovaginitis\nvying\nvyingly\nwab\nwabble\nwabbled\nwabbler\nwabblers\nwabbles\nwabblier\nwabbliest\nwabbling\nwabbly\nwabs\nwack\nwacke\nwackes\nwackier\nwackiest\nwackily\nwackiness\nwackinesses\nwacko\nwackoes\nwackos\nwacks\nwacky\nwad\nwadable\nwadded\nwadder\nwadders\nwaddie\nwaddied\nwaddies\nwadding\nwaddings\nwaddle\nwaddled\nwaddler\nwaddlers\nwaddles\nwaddling\nwaddly\nwaddy\nwaddying\nwade\nwadeable\nwaded\nwader\nwaders\nwades\nwadi\nwadies\nwading\nwadis\nwadmaal\nwadmaals\nwadmal\nwadmals\nwadmel\nwadmels\nwadmol\nwadmoll\nwadmolls\nwadmols\nwads\nwadset\nwadsets\nwadsetted\nwadsetting\nwady\nwae\nwaeful\nwaeness\nwaenesses\nwaes\nwaesuck\nwaesucks\nwafer\nwafered\nwafering\nwafers\nwafery\nwaff\nwaffed\nwaffie\nwaffies\nwaffing\nwaffle\nwaffled\nwaffler\nwafflers\nwaffles\nwafflestomper\nwafflestompers\nwaffling\nwafflings\nwaffs\nwaft\nwaftage\nwaftages\nwafted\nwafter\nwafters\nwafting\nwafts\nwafture\nwaftures\nwag\nwage\nwaged\nwageless\nwager\nwagered\nwagerer\nwagerers\nwagering\nwagers\nwages\nwageworker\nwageworkers\nwagged\nwagger\nwaggeries\nwaggers\nwaggery\nwagging\nwaggish\nwaggishly\nwaggishness\nwaggishnesses\nwaggle\nwaggled\nwaggles\nwaggling\nwaggly\nwaggon\nwaggoned\nwaggoner\nwaggoners\nwaggoning\nwaggons\nwaging\nwagon\nwagonage\nwagonages\nwagoned\nwagoner\nwagoners\nwagonette\nwagonettes\nwagoning\nwagons\nwags\nwagsome\nwagtail\nwagtails\nwahconda\nwahcondas\nwahine\nwahines\nwahoo\nwahoos\nwaif\nwaifed\nwaifing\nwaiflike\nwaifs\nwail\nwailed\nwailer\nwailers\nwailful\nwailfully\nwailing\nwails\nwailsome\nwain\nwains\nwainscot\nwainscoted\nwainscoting\nwainscotings\nwainscots\nwainscotted\nwainscotting\nwainscottings\nwainwright\nwainwrights\nwair\nwaired\nwairing\nwairs\nwaist\nwaistband\nwaistbands\nwaistcoat\nwaistcoated\nwaistcoats\nwaisted\nwaister\nwaisters\nwaisting\nwaistings\nwaistline\nwaistlines\nwaists\nwait\nwaited\nwaiter\nwaiters\nwaiting\nwaitings\nwaitperson\nwaitpersons\nwaitress\nwaitressed\nwaitresses\nwaitressing\nwaits\nwaitstaff\nwaitstaffs\nwaive\nwaived\nwaiver\nwaivers\nwaives\nwaiving\nwakanda\nwakandas\nwake\nwaked\nwakeful\nwakefully\nwakefulness\nwakefulnesses\nwakeless\nwaken\nwakened\nwakener\nwakeners\nwakening\nwakenings\nwakens\nwaker\nwakerife\nwakers\nwakes\nwakiki\nwakikis\nwaking\nwaldo\nwaldoes\nwale\nwaled\nwaler\nwalers\nwales\nwalies\nwaling\nwalk\nwalkable\nwalkabout\nwalkabouts\nwalkathon\nwalkathons\nwalkaway\nwalkaways\nwalked\nwalker\nwalkers\nwalking\nwalkings\nwalkingstick\nwalkingsticks\nwalkout\nwalkouts\nwalkover\nwalkovers\nwalks\nwalkup\nwalkups\nwalkway\nwalkways\nwalkyrie\nwalkyries\nwall\nwalla\nwallabies\nwallaby\nwallah\nwallahs\nwallaroo\nwallaroos\nwallas\nwallboard\nwallboards\nwalled\nwallet\nwallets\nwalleye\nwalleyed\nwalleyes\nwallflower\nwallflowers\nwallie\nwallies\nwalling\nwallop\nwalloped\nwalloper\nwallopers\nwalloping\nwallops\nwallow\nwallowed\nwallower\nwallowers\nwallowing\nwallows\nwallpaper\nwallpapered\nwallpapering\nwallpapers\nwalls\nwally\nwallydraigle\nwallydraigles\nwalnut\nwalnuts\nwalrus\nwalruses\nwaltz\nwaltzed\nwaltzer\nwaltzers\nwaltzes\nwaltzing\nwaly\nwamble\nwambled\nwambles\nwamblier\nwambliest\nwambling\nwambly\nwame\nwamefou\nwamefous\nwameful\nwamefuls\nwames\nwammus\nwammuses\nwampish\nwampished\nwampishes\nwampishing\nwampum\nwampumpeag\nwampumpeags\nwampums\nwampus\nwampuses\nwamus\nwamuses\nwan\nwand\nwander\nwandered\nwanderer\nwanderers\nwandering\nwanderings\nwanderlust\nwanderlusts\nwanderoo\nwanderoos\nwanders\nwandle\nwands\nwane\nwaned\nwanes\nwaney\nwangan\nwangans\nwangle\nwangled\nwangler\nwanglers\nwangles\nwangling\nwangun\nwanguns\nwanier\nwaniest\nwanigan\nwanigans\nwaning\nwanion\nwanions\nwanly\nwannabe\nwannabes\nwanned\nwanner\nwanness\nwannesses\nwannest\nwannigan\nwannigans\nwanning\nwans\nwant\nwantage\nwantages\nwanted\nwanter\nwanters\nwanting\nwanton\nwantoned\nwantoner\nwantoners\nwantoning\nwantonly\nwantonness\nwantonnesses\nwantons\nwants\nwany\nwap\nwapentake\nwapentakes\nwapiti\nwapitis\nwapped\nwappenschawing\nwappenschawings\nwapping\nwaps\nwar\nwarble\nwarbled\nwarbler\nwarblers\nwarbles\nwarbling\nwarbonnet\nwarbonnets\nwarcraft\nwarcrafts\nward\nwarded\nwarden\nwardenries\nwardenry\nwardens\nwardenship\nwardenships\nwarder\nwarders\nwarding\nwardress\nwardresses\nwardrobe\nwardrobes\nwardroom\nwardrooms\nwards\nwardship\nwardships\nware\nwared\nwarehouse\nwarehoused\nwarehouseman\nwarehousemen\nwarehouser\nwarehousers\nwarehouses\nwarehousing\nwareroom\nwarerooms\nwares\nwarez\nwarfare\nwarfares\nwarfarin\nwarfarins\nwarhead\nwarheads\nwarhorse\nwarhorses\nwarier\nwariest\nwarily\nwariness\nwarinesses\nwaring\nwarison\nwarisons\nwark\nwarked\nwarking\nwarks\nwarless\nwarlike\nwarlock\nwarlocks\nwarlord\nwarlordism\nwarlordisms\nwarlords\nwarm\nwarmaker\nwarmakers\nwarmblooded\nwarmed\nwarmer\nwarmers\nwarmest\nwarmhearted\nwarmheartedness\nwarmheartednesses\nwarming\nwarmish\nwarmly\nwarmness\nwarmnesses\nwarmonger\nwarmongering\nwarmongerings\nwarmongers\nwarmouth\nwarmouths\nwarms\nwarmth\nwarmths\nwarmup\nwarmups\nwarn\nwarned\nwarner\nwarners\nwarning\nwarningly\nwarnings\nwarns\nwarp\nwarpage\nwarpages\nwarpath\nwarpaths\nwarped\nwarper\nwarpers\nwarping\nwarplane\nwarplanes\nwarpower\nwarpowers\nwarps\nwarpwise\nwarragal\nwarragals\nwarrant\nwarrantable\nwarrantableness\nwarrantablenesses\nwarrantably\nwarranted\nwarrantee\nwarrantees\nwarranter\nwarranters\nwarranties\nwarranting\nwarrantless\nwarrantor\nwarrantors\nwarrants\nwarranty\nwarred\nwarren\nwarrener\nwarreners\nwarrens\nwarrigal\nwarrigals\nwarring\nwarrior\nwarriors\nwars\nwarsaw\nwarsaws\nwarship\nwarships\nwarsle\nwarsled\nwarsler\nwarslers\nwarsles\nwarsling\nwarstle\nwarstled\nwarstler\nwarstlers\nwarstles\nwarstling\nwart\nwarted\nwarthog\nwarthogs\nwartier\nwartiest\nwartime\nwartimes\nwartless\nwartlike\nwarts\nwarty\nwarwork\nwarworks\nwarworn\nwary\nwas\nwasabi\nwasabis\nwash\nwashabilities\nwashability\nwashable\nwashables\nwashateria\nwashaterias\nwashbasin\nwashbasins\nwashboard\nwashboards\nwashbowl\nwashbowls\nwashcloth\nwashcloths\nwashday\nwashdays\nwashed\nwasher\nwasherman\nwashermen\nwashers\nwasherwoman\nwasherwomen\nwashes\nwasheteria\nwasheterias\nwashhouse\nwashhouses\nwashier\nwashiest\nwashing\nwashings\nwashout\nwashouts\nwashrag\nwashrags\nwashroom\nwashrooms\nwashstand\nwashstands\nwashtub\nwashtubs\nwashup\nwashups\nwashwoman\nwashwomen\nwashy\nwasp\nwaspier\nwaspiest\nwaspily\nwaspish\nwaspishly\nwaspishness\nwaspishnesses\nwasplike\nwasps\nwaspy\nwassail\nwassailed\nwassailer\nwassailers\nwassailing\nwassails\nwast\nwastable\nwastage\nwastages\nwaste\nwastebasket\nwastebaskets\nwasted\nwasteful\nwastefully\nwastefulness\nwastefulnesses\nwasteland\nwastelands\nwastelot\nwastelots\nwastepaper\nwastepapers\nwaster\nwasterie\nwasteries\nwasters\nwastery\nwastes\nwastewater\nwastewaters\nwasteway\nwasteways\nwasting\nwastrel\nwastrels\nwastrie\nwastries\nwastry\nwasts\nwat\nwatap\nwatape\nwatapes\nwataps\nwatch\nwatchable\nwatchables\nwatchband\nwatchbands\nwatchcase\nwatchcases\nwatchcries\nwatchcry\nwatchdog\nwatchdogged\nwatchdogging\nwatchdogs\nwatched\nwatcher\nwatchers\nwatches\nwatcheye\nwatcheyes\nwatchful\nwatchfully\nwatchfulness\nwatchfulnesses\nwatching\nwatchmaker\nwatchmakers\nwatchmaking\nwatchmakings\nwatchman\nwatchmen\nwatchout\nwatchouts\nwatchtower\nwatchtowers\nwatchword\nwatchwords\nwater\nwaterage\nwaterages\nwaterbed\nwaterbeds\nwaterbird\nwaterbirds\nwaterborne\nwaterbuck\nwaterbucks\nwatercolor\nwatercolorist\nwatercolorists\nwatercolors\nwatercooler\nwatercoolers\nwatercourse\nwatercourses\nwatercraft\nwatercrafts\nwatercress\nwatercresses\nwaterdog\nwaterdogs\nwatered\nwaterer\nwaterers\nwaterfall\nwaterfalls\nwaterflood\nwaterflooded\nwaterflooding\nwaterfloods\nwaterfowl\nwaterfowler\nwaterfowlers\nwaterfowling\nwaterfowlings\nwaterfowls\nwaterfront\nwaterfronts\nwaterier\nwateriest\nwaterily\nwateriness\nwaterinesses\nwatering\nwaterings\nwaterish\nwaterishness\nwaterishnesses\nwaterleaf\nwaterleafs\nwaterless\nwaterlessness\nwaterlessnesses\nwaterline\nwaterlines\nwaterlog\nwaterlogged\nwaterlogging\nwaterlogs\nwaterloo\nwaterloos\nwaterman\nwatermanship\nwatermanships\nwatermark\nwatermarked\nwatermarking\nwatermarks\nwatermelon\nwatermelons\nwatermen\nwaterpower\nwaterpowers\nwaterproof\nwaterproofed\nwaterproofer\nwaterproofers\nwaterproofing\nwaterproofings\nwaterproofness\nwaterproofnesses\nwaterproofs\nwaters\nwaterscape\nwaterscapes\nwatershed\nwatersheds\nwaterside\nwatersides\nwaterskiing\nwaterskiings\nwaterspout\nwaterspouts\nwaterthrush\nwaterthrushes\nwatertight\nwatertightness\nwatertightnesses\nwaterway\nwaterways\nwaterweed\nwaterweeds\nwaterwheel\nwaterwheels\nwaterworks\nwaterworn\nwatery\nwaterzooi\nwaterzoois\nwats\nwatt\nwattage\nwattages\nwattape\nwattapes\nwatter\nwattest\nwatthour\nwatthours\nwattle\nwattlebird\nwattlebirds\nwattled\nwattles\nwattless\nwattling\nwattmeter\nwattmeters\nwatts\nwaucht\nwauchted\nwauchting\nwauchts\nwaugh\nwaught\nwaughted\nwaughting\nwaughts\nwauk\nwauked\nwauking\nwauks\nwaul\nwauled\nwauling\nwauls\nwaur\nwave\nwaveband\nwavebands\nwaved\nwaveform\nwaveforms\nwaveguide\nwaveguides\nwavelength\nwavelengths\nwaveless\nwavelessly\nwavelet\nwavelets\nwavelike\nwaveoff\nwaveoffs\nwaver\nwavered\nwaverer\nwaverers\nwavering\nwaveringly\nwavers\nwavery\nwaves\nwaveshape\nwaveshapes\nwavey\nwaveys\nwavier\nwavies\nwaviest\nwavily\nwaviness\nwavinesses\nwaving\nwavy\nwaw\nwawl\nwawled\nwawling\nwawls\nwaws\nwax\nwaxberries\nwaxberry\nwaxbill\nwaxbills\nwaxed\nwaxen\nwaxer\nwaxers\nwaxes\nwaxier\nwaxiest\nwaxily\nwaxiness\nwaxinesses\nwaxing\nwaxings\nwaxlike\nwaxplant\nwaxplants\nwaxweed\nwaxweeds\nwaxwing\nwaxwings\nwaxwork\nwaxworks\nwaxworm\nwaxworms\nwaxy\nway\nwaybill\nwaybills\nwayfarer\nwayfarers\nwayfaring\nwaygoing\nwaygoings\nwaylaid\nwaylay\nwaylayer\nwaylayers\nwaylaying\nwaylays\nwayless\nways\nwayside\nwaysides\nwayward\nwaywardly\nwaywardness\nwaywardnesses\nwayworn\nwazoo\nwazoos\nwe\nweak\nweaken\nweakened\nweakener\nweakeners\nweakening\nweakens\nweaker\nweakest\nweakfish\nweakfishes\nweakhearted\nweakish\nweaklier\nweakliest\nweakliness\nweaklinesses\nweakling\nweaklings\nweakly\nweakness\nweaknesses\nweakside\nweaksides\nweal\nweald\nwealds\nweals\nwealth\nwealthier\nwealthiest\nwealthily\nwealthiness\nwealthinesses\nwealths\nwealthy\nwean\nweaned\nweaner\nweaners\nweaning\nweanling\nweanlings\nweans\nweapon\nweaponed\nweaponing\nweaponless\nweaponries\nweaponry\nweapons\nwear\nwearabilities\nwearability\nwearable\nwearables\nwearer\nwearers\nwearied\nwearier\nwearies\nweariest\nweariful\nwearifully\nwearifulness\nwearifulnesses\nweariless\nwearilessly\nwearily\nweariness\nwearinesses\nwearing\nwearingly\nwearish\nwearisome\nwearisomely\nwearisomeness\nwearisomenesses\nwears\nweary\nwearying\nweasand\nweasands\nweasel\nweaseled\nweaseling\nweaselled\nweaselling\nweaselly\nweasels\nweasely\nweason\nweasons\nweather\nweatherabilities\nweatherability\nweatherboard\nweatherboarded\nweatherboarding\nweatherboardings\nweatherboards\nweathercast\nweathercaster\nweathercasters\nweathercasts\nweathercock\nweathercocks\nweathered\nweatherglass\nweatherglasses\nweathering\nweatherings\nweatherization\nweatherizations\nweatherize\nweatherized\nweatherizes\nweatherizing\nweatherly\nweatherman\nweathermen\nweatherperson\nweatherpersons\nweatherproof\nweatherproofed\nweatherproofing\nweatherproofness\nweatherproofnesses\nweatherproofs\nweathers\nweatherworn\nweave\nweaved\nweaver\nweaverbird\nweaverbirds\nweavers\nweaves\nweaving\nweazand\nweazands\nweb\nwebbed\nwebbier\nwebbiest\nwebbing\nwebbings\nwebby\nweber\nwebers\nwebfed\nwebfeet\nwebfoot\nwebless\nweblike\nwebs\nwebsite\nwebsites\nwebster\nwebsters\nwebwork\nwebworks\nwebworm\nwebworms\nwecht\nwechts\nwed\nwedded\nwedder\nwedders\nwedding\nweddings\nwedel\nwedeled\nwedeling\nwedeln\nwedelns\nwedels\nwedge\nwedged\nwedges\nwedgie\nwedgier\nwedgies\nwedgiest\nwedging\nwedgy\nwedlock\nwedlocks\nweds\nwee\nweed\nweeded\nweeder\nweeders\nweedier\nweediest\nweedily\nweediness\nweedinesses\nweeding\nweedless\nweedlike\nweeds\nweedy\nweek\nweekday\nweekdays\nweekend\nweekended\nweekender\nweekenders\nweekending\nweekends\nweeklies\nweeklong\nweekly\nweeknight\nweeknights\nweeks\nweel\nween\nweened\nweenie\nweenier\nweenies\nweeniest\nweening\nweens\nweensier\nweensiest\nweensy\nweeny\nweep\nweeper\nweepers\nweepie\nweepier\nweepies\nweepiest\nweeping\nweepings\nweeps\nweepy\nweer\nwees\nweest\nweet\nweeted\nweeting\nweets\nweever\nweevers\nweevil\nweeviled\nweevilly\nweevils\nweevily\nweewee\nweeweed\nweeweeing\nweewees\nweft\nwefts\nweftwise\nweigela\nweigelas\nweigelia\nweigelias\nweigh\nweighable\nweighed\nweigher\nweighers\nweighing\nweighman\nweighmen\nweighs\nweight\nweighted\nweighter\nweighters\nweightier\nweightiest\nweightily\nweightiness\nweightinesses\nweighting\nweightless\nweightlessly\nweightlessness\nweightlessnesses\nweightlifter\nweightlifters\nweightlifting\nweightliftings\nweights\nweighty\nweimaraner\nweimaraners\nweiner\nweiners\nweir\nweird\nweirder\nweirdest\nweirdie\nweirdies\nweirdly\nweirdness\nweirdnesses\nweirdo\nweirdoes\nweirdos\nweirds\nweirdy\nweirs\nweisenheimer\nweisenheimers\nweka\nwekas\nwelch\nwelched\nwelcher\nwelchers\nwelches\nwelching\nwelcome\nwelcomed\nwelcomely\nwelcomeness\nwelcomenesses\nwelcomer\nwelcomers\nwelcomes\nwelcoming\nweld\nweldable\nwelded\nwelder\nwelders\nwelding\nweldless\nweldment\nweldments\nweldor\nweldors\nwelds\nwelfare\nwelfares\nwelfarism\nwelfarisms\nwelfarist\nwelfarists\nwelkin\nwelkins\nwell\nwelladay\nwelladays\nwellaway\nwellaways\nwellborn\nwellcurb\nwellcurbs\nwelldoer\nwelldoers\nwelled\nwellhead\nwellheads\nwellhole\nwellholes\nwellie\nwellies\nwelling\nwellness\nwellnesses\nwells\nwellsite\nwellsites\nwellspring\nwellsprings\nwelly\nwelsh\nwelshed\nwelsher\nwelshers\nwelshes\nwelshing\nwelt\nweltanschauung\nweltanschauungen\nweltanschauungs\nwelted\nwelter\nweltered\nweltering\nwelters\nwelterweight\nwelterweights\nwelting\nweltings\nwelts\nweltschmerz\nweltschmerzes\nwen\nwench\nwenched\nwencher\nwenchers\nwenches\nwenching\nwend\nwended\nwendigo\nwendigoes\nwendigos\nwending\nwends\nwennier\nwenniest\nwennish\nwenny\nwens\nwent\nwentletrap\nwentletraps\nwept\nwere\nweregild\nweregilds\nwerewolf\nwerewolves\nwergeld\nwergelds\nwergelt\nwergelts\nwergild\nwergilds\nwert\nwerwolf\nwerwolves\nweskit\nweskits\nwessand\nwessands\nwest\nwestbound\nwester\nwestered\nwestering\nwesterlies\nwesterly\nwestern\nwesterner\nwesterners\nwesternisation\nwesternisations\nwesternise\nwesternised\nwesternises\nwesternising\nwesternization\nwesternizations\nwesternize\nwesternized\nwesternizes\nwesternizing\nwesternmost\nwesterns\nwesters\nwesting\nwestings\nwestmost\nwests\nwestward\nwestwards\nwet\nwetback\nwetbacks\nwether\nwethers\nwetland\nwetlands\nwetly\nwetness\nwetnesses\nwetproof\nwets\nwetsuit\nwetsuits\nwettabilities\nwettability\nwettable\nwetted\nwetter\nwetters\nwettest\nwetting\nwettings\nwettish\nwetware\nwetwares\nwha\nwhack\nwhacked\nwhacker\nwhackers\nwhackier\nwhackiest\nwhacking\nwhacko\nwhackos\nwhacks\nwhacky\nwhale\nwhaleback\nwhalebacks\nwhaleboat\nwhaleboats\nwhalebone\nwhalebones\nwhaled\nwhalelike\nwhaleman\nwhalemen\nwhaler\nwhalers\nwhales\nwhaling\nwhalings\nwham\nwhammed\nwhammies\nwhamming\nwhammo\nwhammy\nwhamo\nwhams\nwhang\nwhanged\nwhangee\nwhangees\nwhanging\nwhangs\nwhap\nwhapped\nwhapper\nwhappers\nwhapping\nwhaps\nwharf\nwharfage\nwharfages\nwharfed\nwharfing\nwharfinger\nwharfingers\nwharfmaster\nwharfmasters\nwharfs\nwharve\nwharves\nwhat\nwhatchamacallit\nwhatchamacallits\nwhatever\nwhatness\nwhatnesses\nwhatnot\nwhatnots\nwhats\nwhatshisname\nwhatsis\nwhatsises\nwhatsit\nwhatsits\nwhatsoever\nwhaup\nwhaups\nwheal\nwheals\nwheat\nwheatear\nwheatears\nwheaten\nwheatens\nwheats\nwhee\nwheedle\nwheedled\nwheedler\nwheedlers\nwheedles\nwheedling\nwheel\nwheelbarrow\nwheelbarrowed\nwheelbarrowing\nwheelbarrows\nwheelbase\nwheelbases\nwheelchair\nwheelchairs\nwheeled\nwheeler\nwheelers\nwheelhorse\nwheelhorses\nwheelhouse\nwheelhouses\nwheelie\nwheelies\nwheeling\nwheelings\nwheelless\nwheelman\nwheelmen\nwheels\nwheelsman\nwheelsmen\nwheelwork\nwheelworks\nwheelwright\nwheelwrights\nwheen\nwheens\nwheep\nwheeped\nwheeping\nwheeple\nwheepled\nwheeples\nwheepling\nwheeps\nwheeze\nwheezed\nwheezer\nwheezers\nwheezes\nwheezier\nwheeziest\nwheezily\nwheeziness\nwheezinesses\nwheezing\nwheezy\nwhelk\nwhelkier\nwhelkiest\nwhelks\nwhelky\nwhelm\nwhelmed\nwhelming\nwhelms\nwhelp\nwhelped\nwhelping\nwhelps\nwhen\nwhenas\nwhence\nwhencesoever\nwhenever\nwhens\nwhensoever\nwhere\nwhereabout\nwhereabouts\nwhereas\nwhereases\nwhereat\nwhereby\nwherefore\nwherefores\nwherefrom\nwherein\nwhereinto\nwhereof\nwhereon\nwheres\nwheresoever\nwherethrough\nwhereto\nwhereunto\nwhereupon\nwherever\nwherewith\nwherewithal\nwherewithals\nwherried\nwherries\nwherry\nwherrying\nwherve\nwherves\nwhet\nwhether\nwhets\nwhetstone\nwhetstones\nwhetted\nwhetter\nwhetters\nwhetting\nwhew\nwhews\nwhey\nwheyey\nwheyface\nwheyfaces\nwheyish\nwheylike\nwheys\nwhich\nwhichever\nwhichsoever\nwhicker\nwhickered\nwhickering\nwhickers\nwhid\nwhidah\nwhidahs\nwhidded\nwhidding\nwhids\nwhiff\nwhiffed\nwhiffer\nwhiffers\nwhiffet\nwhiffets\nwhiffing\nwhiffle\nwhiffled\nwhiffler\nwhifflers\nwhiffles\nwhiffletree\nwhiffletrees\nwhiffling\nwhiffs\nwhig\nwhigmaleerie\nwhigmaleeries\nwhigs\nwhile\nwhiled\nwhiles\nwhiling\nwhilom\nwhilst\nwhim\nwhimbrel\nwhimbrels\nwhimper\nwhimpered\nwhimpering\nwhimpers\nwhims\nwhimsey\nwhimseys\nwhimsical\nwhimsicalities\nwhimsicality\nwhimsically\nwhimsicalness\nwhimsicalnesses\nwhimsied\nwhimsies\nwhimsy\nwhin\nwhinchat\nwhinchats\nwhine\nwhined\nwhiner\nwhiners\nwhines\nwhiney\nwhinge\nwhinged\nwhingeing\nwhinges\nwhinging\nwhinier\nwhiniest\nwhining\nwhiningly\nwhinnied\nwhinnier\nwhinnies\nwhinniest\nwhinny\nwhinnying\nwhins\nwhinstone\nwhinstones\nwhiny\nwhip\nwhipcord\nwhipcords\nwhiplash\nwhiplashes\nwhiplike\nwhipped\nwhipper\nwhippers\nwhippersnapper\nwhippersnappers\nwhippet\nwhippets\nwhippier\nwhippiest\nwhipping\nwhippings\nwhippletree\nwhippletrees\nwhippoorwill\nwhippoorwills\nwhippy\nwhipray\nwhiprays\nwhips\nwhipsaw\nwhipsawed\nwhipsawing\nwhipsawn\nwhipsaws\nwhipstitch\nwhipstitched\nwhipstitches\nwhipstitching\nwhipstock\nwhipstocks\nwhipt\nwhiptail\nwhiptails\nwhipworm\nwhipworms\nwhir\nwhirl\nwhirled\nwhirler\nwhirlers\nwhirlier\nwhirlies\nwhirliest\nwhirligig\nwhirligigs\nwhirling\nwhirlpool\nwhirlpools\nwhirls\nwhirlwind\nwhirlwinds\nwhirly\nwhirlybird\nwhirlybirds\nwhirr\nwhirred\nwhirried\nwhirries\nwhirring\nwhirrs\nwhirry\nwhirrying\nwhirs\nwhish\nwhished\nwhishes\nwhishing\nwhisht\nwhishted\nwhishting\nwhishts\nwhisk\nwhisked\nwhisker\nwhiskered\nwhiskers\nwhiskery\nwhiskey\nwhiskeys\nwhiskies\nwhisking\nwhisks\nwhisky\nwhisper\nwhispered\nwhisperer\nwhisperers\nwhispering\nwhisperingly\nwhisperings\nwhispers\nwhispery\nwhist\nwhisted\nwhisting\nwhistle\nwhistleable\nwhistleblower\nwhistleblowers\nwhistleblowing\nwhistleblowings\nwhistled\nwhistler\nwhistlers\nwhistles\nwhistling\nwhistlings\nwhists\nwhit\nwhite\nwhitebait\nwhitebaits\nwhitebeard\nwhitebeards\nwhiteboard\nwhiteboards\nwhitecap\nwhitecaps\nwhited\nwhiteface\nwhitefaces\nwhitefish\nwhitefishes\nwhiteflies\nwhitefly\nwhitehead\nwhiteheads\nwhitely\nwhiten\nwhitened\nwhitener\nwhiteners\nwhiteness\nwhitenesses\nwhitening\nwhitenings\nwhitens\nwhiteout\nwhiteouts\nwhiter\nwhites\nwhitesmith\nwhitesmiths\nwhitest\nwhitetail\nwhitetails\nwhitethroat\nwhitethroats\nwhitewall\nwhitewalls\nwhitewash\nwhitewashed\nwhitewasher\nwhitewashers\nwhitewashes\nwhitewashing\nwhitewashings\nwhitewing\nwhitewings\nwhitewood\nwhitewoods\nwhitey\nwhiteys\nwhither\nwhithersoever\nwhitherward\nwhitier\nwhities\nwhitiest\nwhiting\nwhitings\nwhitish\nwhitlow\nwhitlows\nwhitrack\nwhitracks\nwhits\nwhitter\nwhitters\nwhittle\nwhittled\nwhittler\nwhittlers\nwhittles\nwhittling\nwhittlings\nwhittret\nwhittrets\nwhity\nwhiz\nwhizbang\nwhizbangs\nwhizz\nwhizzbang\nwhizzbangs\nwhizzed\nwhizzer\nwhizzers\nwhizzes\nwhizzing\nwho\nwhoa\nwhodunit\nwhodunits\nwhodunnit\nwhodunnits\nwhoever\nwhole\nwholehearted\nwholeheartedly\nwholeness\nwholenesses\nwholes\nwholesale\nwholesaled\nwholesaler\nwholesalers\nwholesales\nwholesaling\nwholesome\nwholesomely\nwholesomeness\nwholesomenesses\nwholism\nwholisms\nwholistic\nwholly\nwhom\nwhomever\nwhomp\nwhomped\nwhomping\nwhomps\nwhomso\nwhomsoever\nwhoof\nwhoofed\nwhoofing\nwhoofs\nwhoop\nwhooped\nwhoopee\nwhoopees\nwhooper\nwhoopers\nwhoopie\nwhooping\nwhoopla\nwhooplas\nwhoops\nwhoosh\nwhooshed\nwhooshes\nwhooshing\nwhoosis\nwhoosises\nwhop\nwhopped\nwhopper\nwhoppers\nwhopping\nwhops\nwhore\nwhored\nwhoredom\nwhoredoms\nwhorehouse\nwhorehouses\nwhoremaster\nwhoremasters\nwhoremonger\nwhoremongers\nwhores\nwhoreson\nwhoresons\nwhoring\nwhorish\nwhorl\nwhorled\nwhorls\nwhort\nwhortle\nwhortleberries\nwhortleberry\nwhortles\nwhorts\nwhose\nwhosesoever\nwhosever\nwhosis\nwhosises\nwhoso\nwhosoever\nwhump\nwhumped\nwhumping\nwhumps\nwhy\nwhydah\nwhydahs\nwhys\nwich\nwiches\nwick\nwickape\nwickapes\nwicked\nwickeder\nwickedest\nwickedly\nwickedness\nwickednesses\nwicker\nwickers\nwickerwork\nwickerworks\nwicket\nwickets\nwicking\nwickings\nwickiup\nwickiups\nwicks\nwickyup\nwickyups\nwicopies\nwicopy\nwidder\nwidders\nwiddershins\nwiddie\nwiddies\nwiddle\nwiddled\nwiddles\nwiddling\nwiddy\nwide\nwideawake\nwideawakes\nwideband\nwidely\nwidemouthed\nwiden\nwidened\nwidener\nwideners\nwideness\nwidenesses\nwidening\nwidens\nwideout\nwideouts\nwider\nwides\nwidespread\nwidest\nwidgeon\nwidgeons\nwidget\nwidgets\nwidish\nwidow\nwidowed\nwidower\nwidowerhood\nwidowerhoods\nwidowers\nwidowhood\nwidowhoods\nwidowing\nwidows\nwidth\nwidths\nwidthway\nwield\nwielded\nwielder\nwielders\nwieldier\nwieldiest\nwielding\nwields\nwieldy\nwiener\nwieners\nwienerwurst\nwienerwursts\nwienie\nwienies\nwife\nwifed\nwifedom\nwifedoms\nwifehood\nwifehoods\nwifeless\nwifelier\nwifeliest\nwifelike\nwifeliness\nwifelinesses\nwifely\nwifes\nwifing\nwiftier\nwiftiest\nwifty\nwig\nwigan\nwigans\nwigeon\nwigeons\nwigged\nwiggeries\nwiggery\nwiggier\nwiggiest\nwigging\nwiggings\nwiggle\nwiggled\nwiggler\nwigglers\nwiggles\nwigglier\nwiggliest\nwiggling\nwiggly\nwiggy\nwight\nwights\nwigless\nwiglet\nwiglets\nwiglike\nwigmaker\nwigmakers\nwigs\nwigwag\nwigwagged\nwigwagging\nwigwags\nwigwam\nwigwams\nwikiup\nwikiups\nwilco\nwild\nwildcat\nwildcats\nwildcatted\nwildcatter\nwildcatters\nwildcatting\nwildebeest\nwildebeests\nwilder\nwildered\nwildering\nwilderment\nwilderments\nwilderness\nwildernesses\nwilders\nwildest\nwildfire\nwildfires\nwildflower\nwildflowers\nwildfowl\nwildfowler\nwildfowlers\nwildfowling\nwildfowlings\nwildfowls\nwilding\nwildings\nwildish\nwildland\nwildlands\nwildlife\nwildling\nwildlings\nwildly\nwildness\nwildnesses\nwilds\nwildwood\nwildwoods\nwile\nwiled\nwiles\nwilful\nwilfully\nwilier\nwiliest\nwilily\nwiliness\nwilinesses\nwiling\nwill\nwillable\nwilled\nwillemite\nwillemites\nwiller\nwillers\nwillet\nwillets\nwillful\nwillfully\nwillfulness\nwillfulnesses\nwillied\nwillies\nwilling\nwillinger\nwillingest\nwillingly\nwillingness\nwillingnesses\nwilliwau\nwilliwaus\nwilliwaw\nwilliwaws\nwillow\nwillowed\nwillower\nwillowers\nwillowier\nwillowiest\nwillowing\nwillowlike\nwillows\nwillowware\nwillowwares\nwillowy\nwillpower\nwillpowers\nwills\nwilly\nwillyard\nwillyart\nwillying\nwillywaw\nwillywaws\nwilt\nwilted\nwilting\nwilts\nwily\nwimble\nwimbled\nwimbles\nwimbling\nwimp\nwimpier\nwimpiest\nwimpiness\nwimpinesses\nwimpish\nwimpishness\nwimpishnesses\nwimple\nwimpled\nwimples\nwimpling\nwimps\nwimpy\nwin\nwince\nwinced\nwincer\nwincers\nwinces\nwincey\nwinceys\nwinch\nwinched\nwincher\nwinchers\nwinches\nwinching\nwincing\nwind\nwindable\nwindage\nwindages\nwindbag\nwindbags\nwindblast\nwindblasts\nwindblown\nwindbreak\nwindbreaker\nwindbreakers\nwindbreaks\nwindburn\nwindburned\nwindburning\nwindburns\nwindburnt\nwindchill\nwindchills\nwinded\nwinder\nwinders\nwindfall\nwindfalls\nwindflaw\nwindflaws\nwindflower\nwindflowers\nwindgall\nwindgalls\nwindhover\nwindhovers\nwindier\nwindiest\nwindigo\nwindigoes\nwindigos\nwindily\nwindiness\nwindinesses\nwinding\nwindings\nwindjammer\nwindjammers\nwindjamming\nwindjammings\nwindlass\nwindlassed\nwindlasses\nwindlassing\nwindle\nwindled\nwindles\nwindless\nwindlessly\nwindlestraw\nwindlestraws\nwindling\nwindlings\nwindmill\nwindmilled\nwindmilling\nwindmills\nwindow\nwindowed\nwindowing\nwindowless\nwindowpane\nwindowpanes\nwindows\nwindowsill\nwindowsills\nwindpipe\nwindpipes\nwindproof\nwindrow\nwindrowed\nwindrowing\nwindrows\nwinds\nwindscreen\nwindscreens\nwindshield\nwindshields\nwindsock\nwindsocks\nwindstorm\nwindstorms\nwindsurf\nwindsurfed\nwindsurfing\nwindsurfings\nwindsurfs\nwindswept\nwindthrow\nwindthrows\nwindup\nwindups\nwindward\nwindwards\nwindway\nwindways\nwindy\nwine\nwined\nwineglass\nwineglasses\nwinegrower\nwinegrowers\nwineless\nwinemaker\nwinemakers\nwinemaking\nwinemakings\nwinepress\nwinepresses\nwineries\nwinery\nwines\nwineshop\nwineshops\nwineskin\nwineskins\nwinesop\nwinesops\nwiney\nwing\nwingback\nwingbacks\nwingbow\nwingbows\nwingding\nwingdings\nwinged\nwingedly\nwinger\nwingers\nwingier\nwingiest\nwinging\nwingless\nwinglessness\nwinglessnesses\nwinglet\nwinglets\nwinglike\nwingman\nwingmen\nwingover\nwingovers\nwings\nwingspan\nwingspans\nwingspread\nwingspreads\nwingtip\nwingtips\nwingy\nwinier\nwiniest\nwining\nwinish\nwink\nwinked\nwinker\nwinkers\nwinking\nwinkle\nwinkled\nwinkles\nwinkling\nwinks\nwinless\nwinnable\nwinned\nwinner\nwinners\nwinning\nwinningly\nwinnings\nwinnock\nwinnocks\nwinnow\nwinnowed\nwinnower\nwinnowers\nwinnowing\nwinnows\nwino\nwinoes\nwinos\nwins\nwinsome\nwinsomely\nwinsomeness\nwinsomenesses\nwinsomer\nwinsomest\nwinter\nwinterberries\nwinterberry\nwintered\nwinterer\nwinterers\nwintergreen\nwintergreens\nwinterier\nwinteriest\nwintering\nwinterization\nwinterizations\nwinterize\nwinterized\nwinterizes\nwinterizing\nwinterkill\nwinterkills\nwinterly\nwinters\nwintertide\nwintertides\nwintertime\nwintertimes\nwintery\nwintle\nwintled\nwintles\nwintling\nwintrier\nwintriest\nwintrily\nwintriness\nwintrinesses\nwintry\nwiny\nwinze\nwinzes\nwipe\nwiped\nwipeout\nwipeouts\nwiper\nwipers\nwipes\nwiping\nwirable\nwire\nwired\nwiredraw\nwiredrawer\nwiredrawers\nwiredrawing\nwiredrawn\nwiredraws\nwiredrew\nwirehair\nwirehaired\nwirehairs\nwireless\nwirelessed\nwirelesses\nwirelessing\nwirelike\nwireman\nwiremen\nwirephoto\nwirephotos\nwirer\nwirers\nwires\nwiretap\nwiretapped\nwiretapper\nwiretappers\nwiretapping\nwiretaps\nwireway\nwireways\nwirework\nwireworks\nwireworm\nwireworms\nwirier\nwiriest\nwirily\nwiriness\nwirinesses\nwiring\nwirings\nwirra\nwiry\nwis\nwisdom\nwisdoms\nwise\nwiseacre\nwiseacres\nwiseass\nwiseasses\nwisecrack\nwisecracked\nwisecracker\nwisecrackers\nwisecracking\nwisecracks\nwised\nwiseguy\nwiseguys\nwiselier\nwiseliest\nwisely\nwiseness\nwisenesses\nwisenheimer\nwisenheimers\nwisent\nwisents\nwiser\nwises\nwisest\nwisewoman\nwisewomen\nwish\nwisha\nwishbone\nwishbones\nwished\nwisher\nwishers\nwishes\nwishful\nwishfully\nwishfulness\nwishfulnesses\nwishing\nwishless\nwising\nwisp\nwisped\nwispier\nwispiest\nwispily\nwispiness\nwispinesses\nwisping\nwispish\nwisplike\nwisps\nwispy\nwiss\nwissed\nwisses\nwissing\nwist\nwistaria\nwistarias\nwisted\nwisteria\nwisterias\nwistful\nwistfully\nwistfulness\nwistfulnesses\nwisting\nwists\nwit\nwitan\nwitch\nwitchcraft\nwitchcrafts\nwitched\nwitcheries\nwitchery\nwitches\nwitchgrass\nwitchgrasses\nwitchier\nwitchiest\nwitching\nwitchings\nwitchlike\nwitchweed\nwitchweeds\nwitchy\nwite\nwited\nwitenagemot\nwitenagemote\nwitenagemotes\nwitenagemots\nwites\nwith\nwithal\nwithdraw\nwithdrawable\nwithdrawal\nwithdrawals\nwithdrawing\nwithdrawn\nwithdrawnness\nwithdrawnnesses\nwithdraws\nwithdrew\nwithe\nwithed\nwither\nwithered\nwitherer\nwitherers\nwithering\nwitheringly\nwitherite\nwitherites\nwithers\nwithershins\nwithes\nwithheld\nwithhold\nwithholder\nwithholders\nwithholding\nwithholds\nwithier\nwithies\nwithiest\nwithin\nwithindoors\nwithing\nwithins\nwithout\nwithoutdoors\nwithouts\nwithstand\nwithstanding\nwithstands\nwithstood\nwithy\nwiting\nwitless\nwitlessly\nwitlessness\nwitlessnesses\nwitling\nwitlings\nwitloof\nwitloofs\nwitness\nwitnessed\nwitnesses\nwitnessing\nwitney\nwitneys\nwits\nwitted\nwitticism\nwitticisms\nwittier\nwittiest\nwittily\nwittiness\nwittinesses\nwitting\nwittingly\nwittings\nwittol\nwittols\nwitty\nwive\nwived\nwiver\nwivern\nwiverns\nwivers\nwives\nwiving\nwiz\nwizard\nwizardly\nwizardries\nwizardry\nwizards\nwizen\nwizened\nwizening\nwizens\nwizes\nwizzen\nwizzens\nwizzes\nwo\nwoad\nwoaded\nwoads\nwoadwax\nwoadwaxes\nwoald\nwoalds\nwobble\nwobbled\nwobbler\nwobblers\nwobbles\nwobblier\nwobblies\nwobbliest\nwobbliness\nwobblinesses\nwobbling\nwobbly\nwobegone\nwodge\nwodges\nwoe\nwoebegone\nwoebegoneness\nwoebegonenesses\nwoeful\nwoefuller\nwoefullest\nwoefully\nwoefulness\nwoefulnesses\nwoeness\nwoenesses\nwoes\nwoesome\nwoful\nwofully\nwog\nwogs\nwok\nwoke\nwoken\nwoks\nwold\nwolds\nwolf\nwolfberries\nwolfberry\nwolfed\nwolfer\nwolfers\nwolffish\nwolffishes\nwolfhound\nwolfhounds\nwolfing\nwolfish\nwolfishly\nwolfishness\nwolfishnesses\nwolflike\nwolfram\nwolframite\nwolframites\nwolframs\nwolfs\nwolfsbane\nwolfsbanes\nwollastonite\nwollastonites\nwolver\nwolverine\nwolverines\nwolvers\nwolves\nwoman\nwomaned\nwomanhood\nwomanhoods\nwomaning\nwomanise\nwomanised\nwomanises\nwomanish\nwomanishly\nwomanishness\nwomanishnesses\nwomanising\nwomanize\nwomanized\nwomanizer\nwomanizers\nwomanizes\nwomanizing\nwomankind\nwomanless\nwomanlier\nwomanliest\nwomanlike\nwomanliness\nwomanlinesses\nwomanly\nwomanpower\nwomanpowers\nwomans\nwomb\nwombat\nwombats\nwombed\nwombier\nwombiest\nwomblike\nwombs\nwomby\nwomen\nwomenfolk\nwomenfolks\nwomenkind\nwomera\nwomeras\nwommera\nwommeras\nwon\nwonder\nwondered\nwonderer\nwonderers\nwonderful\nwonderfully\nwonderfulness\nwonderfulnesses\nwondering\nwonderland\nwonderlands\nwonderment\nwonderments\nwonders\nwonderwork\nwonderworks\nwondrous\nwondrously\nwondrousness\nwondrousnesses\nwonk\nwonkier\nwonkiest\nwonks\nwonky\nwonned\nwonner\nwonners\nwonning\nwons\nwont\nwonted\nwontedly\nwontedness\nwontednesses\nwonting\nwonton\nwontons\nwonts\nwoo\nwood\nwoodbin\nwoodbind\nwoodbinds\nwoodbine\nwoodbines\nwoodbins\nwoodblock\nwoodblocks\nwoodbox\nwoodboxes\nwoodcarver\nwoodcarvers\nwoodcarving\nwoodcarvings\nwoodchat\nwoodchats\nwoodchopper\nwoodchoppers\nwoodchuck\nwoodchucks\nwoodcock\nwoodcocks\nwoodcraft\nwoodcrafts\nwoodcut\nwoodcuts\nwoodcutter\nwoodcutters\nwoodcutting\nwoodcuttings\nwooded\nwooden\nwoodener\nwoodenest\nwoodenhead\nwoodenheaded\nwoodenheads\nwoodenly\nwoodenness\nwoodennesses\nwoodenware\nwoodenwares\nwoodhen\nwoodhens\nwoodie\nwoodier\nwoodies\nwoodiest\nwoodiness\nwoodinesses\nwooding\nwoodland\nwoodlander\nwoodlanders\nwoodlands\nwoodlark\nwoodlarks\nwoodless\nwoodlore\nwoodlores\nwoodlot\nwoodlots\nwoodman\nwoodmen\nwoodnote\nwoodnotes\nwoodpecker\nwoodpeckers\nwoodpile\nwoodpiles\nwoodruff\nwoodruffs\nwoods\nwoodshed\nwoodshedded\nwoodshedding\nwoodsheds\nwoodsia\nwoodsias\nwoodsier\nwoodsiest\nwoodsman\nwoodsmen\nwoodstove\nwoodstoves\nwoodsy\nwoodwax\nwoodwaxes\nwoodwind\nwoodwinds\nwoodwork\nwoodworker\nwoodworkers\nwoodworking\nwoodworkings\nwoodworks\nwoodworm\nwoodworms\nwoody\nwooed\nwooer\nwooers\nwoof\nwoofed\nwoofer\nwoofers\nwoofing\nwoofs\nwooing\nwooingly\nwool\nwooled\nwoolen\nwoolens\nwooler\nwoolers\nwoolfell\nwoolfells\nwoolgatherer\nwoolgatherers\nwoolgathering\nwoolgatherings\nwoolhat\nwoolhats\nwoolie\nwoolier\nwoolies\nwooliest\nwoolled\nwoollen\nwoollens\nwoollier\nwoollies\nwoolliest\nwoollike\nwoollily\nwoolliness\nwoollinesses\nwoolly\nwoolman\nwoolmen\nwoolpack\nwoolpacks\nwools\nwoolsack\nwoolsacks\nwoolshed\nwoolsheds\nwoolskin\nwoolskins\nwoolwork\nwoolworks\nwooly\nwoomera\nwoomeras\nwoops\nwoopsed\nwoopses\nwoopsing\nwoorali\nwooralis\nwoorari\nwooraris\nwoos\nwoosh\nwooshed\nwooshes\nwooshing\nwoozier\nwooziest\nwoozily\nwooziness\nwoozinesses\nwoozy\nwop\nwops\nword\nwordage\nwordages\nwordbook\nwordbooks\nworded\nwordier\nwordiest\nwordily\nwordiness\nwordinesses\nwording\nwordings\nwordless\nwordlessly\nwordlessness\nwordlessnesses\nwordmonger\nwordmongers\nwordplay\nwordplays\nwords\nwordsmith\nwordsmitheries\nwordsmithery\nwordsmiths\nwordy\nwore\nwork\nworkabilities\nworkability\nworkable\nworkableness\nworkablenesses\nworkaday\nworkaholic\nworkaholics\nworkaholism\nworkaholisms\nworkaround\nworkarounds\nworkbag\nworkbags\nworkbasket\nworkbaskets\nworkbench\nworkbenches\nworkboat\nworkboats\nworkbook\nworkbooks\nworkbox\nworkboxes\nworkday\nworkdays\nworked\nworker\nworkers\nworkfare\nworkfares\nworkfolk\nworkfolks\nworkforce\nworkforces\nworkhorse\nworkhorses\nworkhouse\nworkhouses\nworking\nworkingman\nworkingmen\nworkings\nworkingwoman\nworkingwomen\nworkless\nworklessness\nworklessnesses\nworkload\nworkloads\nworkman\nworkmanlike\nworkmanly\nworkmanship\nworkmanships\nworkmate\nworkmates\nworkmen\nworkout\nworkouts\nworkpeople\nworkpiece\nworkpieces\nworkplace\nworkplaces\nworkroom\nworkrooms\nworks\nworksheet\nworksheets\nworkshop\nworkshops\nworkstation\nworkstations\nworktable\nworktables\nworkup\nworkups\nworkweek\nworkweeks\nworkwoman\nworkwomen\nworld\nworldlier\nworldliest\nworldliness\nworldlinesses\nworldling\nworldlings\nworldly\nworlds\nworldview\nworldviews\nworldwide\nworm\nwormed\nwormer\nwormers\nwormhole\nwormholes\nwormier\nwormiest\nwormil\nwormils\nworming\nwormish\nwormlike\nwormroot\nwormroots\nworms\nwormseed\nwormseeds\nwormwood\nwormwoods\nwormy\nworn\nwornness\nwornnesses\nworried\nworriedly\nworrier\nworriers\nworries\nworriment\nworriments\nworrisome\nworrisomely\nworrisomeness\nworrisomenesses\nworrit\nworrited\nworriting\nworrits\nworry\nworrying\nworrywart\nworrywarts\nworse\nworsen\nworsened\nworsening\nworsens\nworser\nworses\nworset\nworsets\nworship\nworshiped\nworshiper\nworshipers\nworshipful\nworshipfully\nworshipfulness\nworshipfulnesses\nworshiping\nworshipless\nworshipped\nworshipper\nworshippers\nworshipping\nworships\nworst\nworsted\nworsteds\nworsting\nworsts\nwort\nworth\nworthed\nworthful\nworthier\nworthies\nworthiest\nworthily\nworthiness\nworthinesses\nworthing\nworthless\nworthlessly\nworthlessness\nworthlessnesses\nworths\nworthwhile\nworthwhileness\nworthwhilenesses\nworthy\nworts\nwos\nwost\nwot\nwots\nwotted\nwotting\nwould\nwouldest\nwouldst\nwound\nwounded\nwounding\nwoundless\nwounds\nwove\nwoven\nwovens\nwow\nwowed\nwowing\nwows\nwowser\nwowsers\nwrack\nwracked\nwrackful\nwracking\nwracks\nwraith\nwraithlike\nwraiths\nwrang\nwrangle\nwrangled\nwrangler\nwranglers\nwrangles\nwrangling\nwrangs\nwrap\nwraparound\nwraparounds\nwrapped\nwrapper\nwrappers\nwrapping\nwrappings\nwraps\nwrapt\nwrasse\nwrasses\nwrassle\nwrassled\nwrassles\nwrassling\nwrastle\nwrastled\nwrastles\nwrastling\nwrath\nwrathed\nwrathful\nwrathfully\nwrathfulness\nwrathfulnesses\nwrathier\nwrathiest\nwrathily\nwrathing\nwraths\nwrathy\nwreak\nwreaked\nwreaker\nwreakers\nwreaking\nwreaks\nwreath\nwreathe\nwreathed\nwreathen\nwreathes\nwreathing\nwreaths\nwreathy\nwreck\nwreckage\nwreckages\nwrecked\nwrecker\nwreckers\nwreckful\nwrecking\nwreckings\nwrecks\nwren\nwrench\nwrenched\nwrenches\nwrenching\nwrenchingly\nwrens\nwrest\nwrested\nwrester\nwresters\nwresting\nwrestle\nwrestled\nwrestler\nwrestlers\nwrestles\nwrestling\nwrestlings\nwrests\nwretch\nwretched\nwretcheder\nwretchedest\nwretchedly\nwretchedness\nwretchednesses\nwretches\nwrick\nwricked\nwricking\nwricks\nwried\nwrier\nwries\nwriest\nwriggle\nwriggled\nwriggler\nwrigglers\nwriggles\nwrigglier\nwriggliest\nwriggling\nwriggly\nwright\nwrights\nwring\nwringed\nwringer\nwringers\nwringing\nwrings\nwrinkle\nwrinkled\nwrinkles\nwrinklier\nwrinkliest\nwrinkling\nwrinkly\nwrist\nwristband\nwristbands\nwristier\nwristiest\nwristlet\nwristlets\nwristlock\nwristlocks\nwrists\nwristwatch\nwristwatches\nwristy\nwrit\nwritable\nwrite\nwriteoff\nwriteoffs\nwriter\nwriterly\nwriters\nwrites\nwriteup\nwriteups\nwrithe\nwrithed\nwrithen\nwrither\nwrithers\nwrithes\nwrithing\nwriting\nwritings\nwrits\nwritten\nwrong\nwrongdoer\nwrongdoers\nwrongdoing\nwrongdoings\nwronged\nwronger\nwrongers\nwrongest\nwrongful\nwrongfully\nwrongfulness\nwrongfulnesses\nwrongheaded\nwrongheadedly\nwrongheadedness\nwrongheadednesses\nwronging\nwrongly\nwrongness\nwrongnesses\nwrongs\nwrote\nwroth\nwrothful\nwrought\nwrung\nwry\nwryer\nwryest\nwrying\nwryly\nwryneck\nwrynecks\nwryness\nwrynesses\nwud\nwulfenite\nwulfenites\nwunderkind\nwunderkinder\nwunderkinds\nwurst\nwursts\nwurzel\nwurzels\nwuss\nwusses\nwussier\nwussies\nwussiest\nwussy\nwuther\nwuthered\nwuthering\nwuthers\nwyandotte\nwyandottes\nwych\nwyches\nwye\nwyes\nwyle\nwyled\nwyles\nwyliecoat\nwyliecoats\nwyling\nwyn\nwynd\nwynds\nwynn\nwynns\nwyns\nwyte\nwyted\nwytes\nwyting\nwyvern\nwyverns\nxanthan\nxanthans\nxanthate\nxanthates\nxanthein\nxantheins\nxanthene\nxanthenes\nxanthic\nxanthin\nxanthine\nxanthines\nxanthins\nxanthoma\nxanthomas\nxanthomata\nxanthone\nxanthones\nxanthophyll\nxanthophylls\nxanthous\nxebec\nxebecs\nxenia\nxenial\nxenias\nxenic\nxenobiotic\nxenobiotics\nxenodiagnoses\nxenodiagnosis\nxenodiagnostic\nxenogamies\nxenogamy\nxenogeneic\nxenogenies\nxenogeny\nxenograft\nxenografts\nxenolith\nxenolithic\nxenoliths\nxenon\nxenons\nxenophile\nxenophiles\nxenophobe\nxenophobes\nxenophobia\nxenophobias\nxenophobic\nxenophobically\nxenotropic\nxerarch\nxeric\nxerographic\nxerographically\nxerographies\nxerography\nxerophile\nxerophilies\nxerophilous\nxerophily\nxerophthalmia\nxerophthalmias\nxerophthalmic\nxerophyte\nxerophytes\nxerophytic\nxerophytism\nxerophytisms\nxeroradiographies\nxeroradiography\nxerosere\nxeroseres\nxeroses\nxerosis\nxerothermic\nxerotic\nxerox\nxeroxed\nxeroxes\nxeroxing\nxerus\nxeruses\nxi\nxiphisterna\nxiphisternum\nxiphoid\nxiphoids\nxis\nxu\nxylan\nxylans\nxylem\nxylems\nxylene\nxylenes\nxylidin\nxylidine\nxylidines\nxylidins\nxylitol\nxylitols\nxylocarp\nxylocarps\nxylograph\nxylographer\nxylographers\nxylographic\nxylographical\nxylographies\nxylographs\nxylography\nxyloid\nxylol\nxylols\nxylophagous\nxylophone\nxylophones\nxylophonist\nxylophonists\nxylose\nxyloses\nxylotomies\nxylotomy\nxylyl\nxylyls\nxyst\nxyster\nxysters\nxysti\nxystoi\nxystos\nxysts\nxystus\nxystuses\nya\nyabber\nyabbered\nyabbering\nyabbers\nyacht\nyachted\nyachter\nyachters\nyachting\nyachtings\nyachtman\nyachtmen\nyachts\nyachtsman\nyachtsmen\nyack\nyacked\nyacking\nyacks\nyaff\nyaffed\nyaffing\nyaffs\nyager\nyagers\nyagi\nyagis\nyah\nyahoo\nyahooism\nyahooisms\nyahoos\nyahrzeit\nyahrzeits\nyaird\nyairds\nyak\nyakitori\nyakitoris\nyakked\nyakker\nyakkers\nyakking\nyaks\nyald\nyam\nyamalka\nyamalkas\nyamen\nyamens\nyammer\nyammered\nyammerer\nyammerers\nyammering\nyammers\nyams\nyamulka\nyamulkas\nyamun\nyamuns\nyang\nyangs\nyank\nyanked\nyanking\nyanks\nyanqui\nyanquis\nyantra\nyantras\nyap\nyapock\nyapocks\nyapok\nyapoks\nyapon\nyapons\nyapped\nyapper\nyappers\nyapping\nyappy\nyaps\nyar\nyarborough\nyarboroughs\nyard\nyardage\nyardages\nyardarm\nyardarms\nyardbird\nyardbirds\nyarded\nyarding\nyardland\nyardlands\nyardman\nyardmaster\nyardmasters\nyardmen\nyards\nyardstick\nyardsticks\nyardwand\nyardwands\nyardwork\nyardworks\nyare\nyarely\nyarer\nyarest\nyarmelke\nyarmelkes\nyarmulke\nyarmulkes\nyarn\nyarned\nyarner\nyarners\nyarning\nyarns\nyarrow\nyarrows\nyashmac\nyashmacs\nyashmak\nyashmaks\nyasmak\nyasmaks\nyatagan\nyatagans\nyataghan\nyataghans\nyatter\nyattered\nyattering\nyatters\nyaud\nyauds\nyauld\nyaup\nyauped\nyauper\nyaupers\nyauping\nyaupon\nyaupons\nyaups\nyautia\nyautias\nyaw\nyawed\nyawing\nyawl\nyawled\nyawling\nyawls\nyawmeter\nyawmeters\nyawn\nyawned\nyawner\nyawners\nyawning\nyawningly\nyawns\nyawp\nyawped\nyawper\nyawpers\nyawping\nyawpings\nyawps\nyaws\nyay\nyays\nycleped\nyclept\nye\nyea\nyeah\nyealing\nyealings\nyean\nyeaned\nyeaning\nyeanling\nyeanlings\nyeans\nyear\nyearbook\nyearbooks\nyearend\nyearends\nyearlies\nyearling\nyearlings\nyearlong\nyearly\nyearn\nyearned\nyearner\nyearners\nyearning\nyearningly\nyearnings\nyearns\nyears\nyeas\nyeasayer\nyeasayers\nyeast\nyeasted\nyeastier\nyeastiest\nyeastily\nyeastiness\nyeastinesses\nyeasting\nyeasts\nyeasty\nyecch\nyecchs\nyech\nyechs\nyechy\nyeelin\nyeelins\nyegg\nyeggman\nyeggmen\nyeggs\nyeh\nyeld\nyelk\nyelks\nyell\nyelled\nyeller\nyellers\nyelling\nyellow\nyellowed\nyellower\nyellowest\nyellowfin\nyellowfins\nyellowhammer\nyellowhammers\nyellowing\nyellowish\nyellowlegs\nyellowly\nyellows\nyellowtail\nyellowtails\nyellowthroat\nyellowthroats\nyellowware\nyellowwares\nyellowwood\nyellowwoods\nyellowy\nyells\nyelp\nyelped\nyelper\nyelpers\nyelping\nyelps\nyen\nyenned\nyenning\nyens\nyenta\nyentas\nyente\nyentes\nyeoman\nyeomanly\nyeomanries\nyeomanry\nyeomen\nyep\nyerba\nyerbas\nyerk\nyerked\nyerking\nyerks\nyes\nyeses\nyeshiva\nyeshivah\nyeshivahs\nyeshivas\nyeshivot\nyeshivoth\nyessed\nyesses\nyessing\nyester\nyesterday\nyesterdays\nyestern\nyesternight\nyesternights\nyesteryear\nyesteryears\nyestreen\nyestreens\nyet\nyeti\nyetis\nyett\nyetts\nyeuk\nyeuked\nyeuking\nyeuks\nyeuky\nyew\nyews\nyid\nyids\nyield\nyielded\nyielder\nyielders\nyielding\nyields\nyikes\nyill\nyills\nyin\nyince\nyins\nyip\nyipe\nyipes\nyipped\nyippee\nyippie\nyippies\nyipping\nyips\nyird\nyirds\nyirr\nyirred\nyirring\nyirrs\nyirth\nyirths\nylem\nylems\nyo\nyob\nyobbo\nyobboes\nyobbos\nyobs\nyock\nyocked\nyocking\nyocks\nyod\nyodel\nyodeled\nyodeler\nyodelers\nyodeling\nyodelled\nyodeller\nyodellers\nyodelling\nyodels\nyodh\nyodhs\nyodle\nyodled\nyodler\nyodlers\nyodles\nyodling\nyods\nyoga\nyogas\nyogee\nyogees\nyogh\nyoghourt\nyoghourts\nyoghs\nyoghurt\nyoghurts\nyogi\nyogic\nyogin\nyogini\nyoginis\nyogins\nyogis\nyogurt\nyogurts\nyohimbine\nyohimbines\nyoicks\nyok\nyoke\nyoked\nyokefellow\nyokefellows\nyokel\nyokeless\nyokelish\nyokels\nyokemate\nyokemates\nyokes\nyoking\nyokozuna\nyokozunas\nyoks\nyolk\nyolked\nyolkier\nyolkiest\nyolks\nyolky\nyom\nyomim\nyon\nyond\nyonder\nyoni\nyonic\nyonis\nyonker\nyonkers\nyore\nyores\nyottabyte\nyottabytes\nyou\nyoung\nyoungberries\nyoungberry\nyounger\nyoungers\nyoungest\nyoungish\nyoungling\nyounglings\nyoungness\nyoungnesses\nyoungs\nyoungster\nyoungsters\nyounker\nyounkers\nyoupon\nyoupons\nyour\nyourn\nyours\nyourself\nyourselves\nyouse\nyouth\nyouthen\nyouthened\nyouthening\nyouthens\nyouthful\nyouthfully\nyouthfulness\nyouthfulnesses\nyouthquake\nyouthquakes\nyouths\nyow\nyowe\nyowed\nyowes\nyowie\nyowies\nyowing\nyowl\nyowled\nyowler\nyowlers\nyowling\nyowls\nyows\nyperite\nyperites\nytterbia\nytterbias\nytterbic\nytterbium\nytterbiums\nyttria\nyttrias\nyttric\nyttrium\nyttriums\nyuan\nyuans\nyuca\nyucas\nyucca\nyuccas\nyucch\nyuch\nyuck\nyucked\nyuckier\nyuckiest\nyucking\nyucks\nyucky\nyuga\nyugas\nyuk\nyukked\nyukking\nyuks\nyulan\nyulans\nyule\nyules\nyuletide\nyuletides\nyum\nyummier\nyummies\nyummiest\nyummy\nyup\nyupon\nyupons\nyuppie\nyuppies\nyups\nyurt\nyurta\nyurts\nywis\nzabaglione\nzabagliones\nzabaione\nzabaiones\nzabajone\nzabajones\nzacaton\nzacatons\nzaddick\nzaddik\nzaddikim\nzaffar\nzaffars\nzaffer\nzaffers\nzaffir\nzaffirs\nzaffre\nzaffres\nzaftig\nzag\nzagged\nzagging\nzags\nzaibatsu\nzaikai\nzaikais\nzaire\nzaires\nzamarra\nzamarras\nzamarro\nzamarros\nzamia\nzamias\nzamindar\nzamindari\nzamindaris\nzamindars\nzanana\nzananas\nzander\nzanders\nzanier\nzanies\nzaniest\nzanily\nzaniness\nzaninesses\nzany\nzanyish\nzanza\nzanzas\nzap\nzapateado\nzapateados\nzapateo\nzapateos\nzapped\nzapper\nzappers\nzappier\nzappiest\nzapping\nzappy\nzaps\nzaptiah\nzaptiahs\nzaptieh\nzaptiehs\nzaratite\nzaratites\nzareba\nzarebas\nzareeba\nzareebas\nzarf\nzarfs\nzariba\nzaribas\nzarzuela\nzarzuelas\nzastruga\nzastrugi\nzax\nzaxes\nzayin\nzayins\nzazen\nzazens\nzeal\nzealot\nzealotries\nzealotry\nzealots\nzealous\nzealously\nzealousness\nzealousnesses\nzeals\nzeatin\nzeatins\nzebec\nzebeck\nzebecks\nzebecs\nzebra\nzebraic\nzebras\nzebrass\nzebrasses\nzebrawood\nzebrawoods\nzebrine\nzebroid\nzebu\nzebus\nzecchin\nzecchini\nzecchino\nzecchinos\nzecchins\nzechin\nzechins\nzed\nzedoaries\nzedoary\nzeds\nzee\nzees\nzein\nzeins\nzeitgeber\nzeitgebers\nzeitgeist\nzeitgeists\nzek\nzeks\nzelkova\nzelkovas\nzemindar\nzemindaries\nzemindars\nzemindary\nzemstva\nzemstvo\nzemstvos\nzenaida\nzenaidas\nzenana\nzenanas\nzenith\nzenithal\nzeniths\nzeolite\nzeolites\nzeolitic\nzephyr\nzephyrs\nzeppelin\nzeppelins\nzeptosecond\nzeptoseconds\nzerk\nzerks\nzero\nzeroed\nzeroes\nzeroing\nzeros\nzeroth\nzest\nzested\nzester\nzesters\nzestful\nzestfully\nzestfulness\nzestfulnesses\nzestier\nzestiest\nzesting\nzestless\nzests\nzesty\nzeta\nzetas\nzettabyte\nzettabytes\nzeugma\nzeugmas\nzibeline\nzibelines\nzibelline\nzibellines\nzibet\nzibeth\nzibeths\nzibets\nzidovudine\nzidovudines\nzig\nzigamorph\nzigamorphs\nzigged\nzigging\nziggurat\nziggurats\nzigs\nzigzag\nzigzagged\nzigzagging\nzigzags\nzikkurat\nzikkurats\nzikurat\nzikurats\nzilch\nzilches\nzill\nzillah\nzillahs\nzillion\nzillionaire\nzillionaires\nzillions\nzillionth\nzills\nzin\nzinc\nzincate\nzincates\nzinced\nzincic\nzincified\nzincifies\nzincify\nzincifying\nzincing\nzincite\nzincites\nzincked\nzincking\nzincky\nzincoid\nzincous\nzincs\nzincy\nzineb\nzinebs\nzinfandel\nzinfandels\nzing\nzingani\nzingano\nzingara\nzingare\nzingari\nzingaro\nzinged\nzinger\nzingers\nzingier\nzingiest\nzinging\nzings\nzingy\nzinkified\nzinkifies\nzinkify\nzinkifying\nzinky\nzinnia\nzinnias\nzins\nzip\nzipless\nzipped\nzipper\nzippered\nzippering\nzippers\nzippier\nzippiest\nzipping\nzippy\nzips\nziram\nzirams\nzircon\nzirconia\nzirconias\nzirconic\nzirconium\nzirconiums\nzircons\nzit\nzither\nzitherist\nzitherists\nzithern\nzitherns\nzithers\nziti\nzitis\nzits\nzizit\nzizith\nzizzle\nzizzled\nzizzles\nzizzling\nzlote\nzloties\nzloty\nzlotych\nzlotys\nzoa\nzoantharian\nzoantharians\nzoaria\nzoarial\nzoarium\nzoariums\nzodiac\nzodiacal\nzodiacs\nzoea\nzoeae\nzoeal\nzoeas\nzoecia\nzoecium\nzoftig\nzoic\nzoisite\nzoisites\nzombi\nzombie\nzombielike\nzombies\nzombification\nzombifications\nzombified\nzombifies\nzombify\nzombifying\nzombiism\nzombiisms\nzombis\nzonal\nzonally\nzonary\nzonate\nzonated\nzonation\nzonations\nzone\nzoned\nzoneless\nzoner\nzoners\nzones\nzonetime\nzonetimes\nzoning\nzonk\nzonked\nzonking\nzonks\nzonula\nzonulae\nzonular\nzonulas\nzonule\nzonules\nzoo\nzoochore\nzoochores\nzooecia\nzooecium\nzoogenic\nzoogeographer\nzoogeographers\nzoogeographic\nzoogeographical\nzoogeographically\nzoogeographies\nzoogeography\nzooglea\nzoogleae\nzoogleal\nzoogleas\nzoogloea\nzoogloeae\nzoogloeas\nzooid\nzooidal\nzooids\nzookeeper\nzookeepers\nzooks\nzoolater\nzoolaters\nzoolatries\nzoolatry\nzoologic\nzoological\nzoologically\nzoologies\nzoologist\nzoologists\nzoology\nzoom\nzoomania\nzoomanias\nzoomed\nzoometries\nzoometry\nzooming\nzoomorph\nzoomorphic\nzoomorphs\nzooms\nzoon\nzoonal\nzoonoses\nzoonosis\nzoonotic\nzoons\nzoophile\nzoophiles\nzoophilic\nzoophilies\nzoophilous\nzoophily\nzoophobe\nzoophobes\nzoophyte\nzoophytes\nzooplankter\nzooplankters\nzooplankton\nzooplanktonic\nzooplanktons\nzoos\nzoosperm\nzoosperms\nzoosporangia\nzoosporangium\nzoospore\nzoospores\nzoosporic\nzoosterol\nzoosterols\nzootechnical\nzootechnics\nzootier\nzootiest\nzootomic\nzootomies\nzootomy\nzooty\nzooxanthella\nzooxanthellae\nzorch\nzorched\nzorches\nzorching\nzori\nzoril\nzorilla\nzorillas\nzorille\nzorilles\nzorillo\nzorillos\nzorils\nzoris\nzoster\nzosters\nzouave\nzouaves\nzounds\nzowie\nzoysia\nzoysias\nzucchetto\nzucchettos\nzucchini\nzucchinis\nzwieback\nzwiebacks\nzwitterion\nzwitterionic\nzwitterions\nzydeco\nzydecos\nzygapophyses\nzygapophysis\nzygodactyl\nzygodactylous\nzygoid\nzygoma\nzygomas\nzygomata\nzygomatic\nzygomorphic\nzygomorphies\nzygomorphy\nzygose\nzygoses\nzygosis\nzygosities\nzygosity\nzygospore\nzygospores\nzygote\nzygotene\nzygotenes\nzygotes\nzygotic\nzymase\nzymases\nzyme\nzymes\nzymogen\nzymogene\nzymogenes\nzymogens\nzymogram\nzymograms\nzymologies\nzymology\nzymosan\nzymosans\nzymoses\nzymosis\nzymotic\nzymurgies\nzymurgy\nzyzzyva\nzyzzyvas\n"
  },
  {
    "path": "examples/other/wordplay/server/game.js",
    "content": "////////// Server only logic //////////\n\nMeteor.methods({\n  start_new_game: function () {\n    // create a new game w/ fresh board\n    var game_id = Games.insert({board: new_board(),\n                                clock: 120});\n\n    // move everyone who is ready in the lobby to the game\n    Players.update({game_id: null, idle: false, name: {$ne: ''}},\n                   {$set: {game_id: game_id}},\n                   {multi: true});\n    // Save a record of who is in the game, so when they leave we can\n    // still show them.\n    var p = Players.find({game_id: game_id},\n                         {fields: {_id: true, name: true}}).fetch();\n    Games.update({_id: game_id}, {$set: {players: p}});\n\n\n    // wind down the game clock\n    var clock = 120;\n    var interval = Meteor.setInterval(function () {\n      clock -= 1;\n      Games.update(game_id, {$set: {clock: clock}});\n\n      // end of game\n      if (clock === 0) {\n        // stop the clock\n        Meteor.clearInterval(interval);\n        // declare zero or more winners\n        var scores = {};\n        Words.find({game_id: game_id}).forEach(function (word) {\n          if (!scores[word.player_id])\n            scores[word.player_id] = 0;\n          scores[word.player_id] += word.score;\n        });\n        var high_score = _.max(scores);\n        var winners = [];\n        _.each(scores, function (score, player_id) {\n          if (score === high_score)\n            winners.push(player_id);\n        });\n        Games.update(game_id, {$set: {winners: winners}});\n      }\n    }, 1000);\n\n    return game_id;\n  },\n\n\n  keepalive: function (player_id) {\n    check(player_id, String);\n    Players.update({_id: player_id},\n                  {$set: {last_keepalive: (new Date()).getTime(),\n                          idle: false}});\n  }\n});\n\nMeteor.setInterval(function () {\n  var now = (new Date()).getTime();\n  var idle_threshold = now - 70*1000; // 70 sec\n  var remove_threshold = now - 60*60*1000; // 1hr\n\n  Players.update({last_keepalive: {$lt: idle_threshold}},\n                 {$set: {idle: true}});\n\n  // XXX need to deal with people coming back!\n  // Players.remove({$lt: {last_keepalive: remove_threshold}});\n\n}, 30*1000);\n"
  },
  {
    "path": "examples/other/wordplay/server/make-boggle-dict.js.noload",
    "content": "require(\"./words.js\");\n\nvar BOGGLE_DICE = ['pchoas', 'oattow', 'lrytte', 'vthrwe',\n                   'eghwne', 'seotis', 'anaeeg', 'idsytt',\n                   'mtoicu', 'afpkfs', 'xlderi', 'ensieu',\n                   'yldevr', 'znrnhl', 'nmiqhu', 'obbaoj'];\n\nvar FLAGS = [0x1, 0x2, 0x4, 0x8,\n             0x10, 0x20, 0x40, 0x80,\n             0x100, 0x200, 0x400, 0x800,\n             0x1000, 0x2000, 0x4000, 0x8000];\n\nvar MASKS = {};\n\n// generate masks for all one, two, three, and four-letter combinations\nvar make_masks = function () {\n  var mask_count = 0;\n\n  // recursive helper\n  var check_mask = function (word, index, used) {\n    for (var i = 0; i < 16; i += 1) {\n      for (var j = 0; j < 6; j += 1) {\n        // if die i is still available, and it has a letter that\n        // matches what we need, we can make use of this.\n        if (!(used & FLAGS[i]) && (BOGGLE_DICE[i][j] === word[index])) {\n          if (word.length === index + 1) {\n            // this is the end of the word, we have a valid mask!\n            if (!MASKS[word])\n              MASKS[word] = [];\n            if (MASKS[word].indexOf(used | FLAGS[i]) === -1) {\n              MASKS[word].push(used | FLAGS[i]);\n              mask_count += 1;\n            }\n            // console.log(\"MASK\", word, used | FLAGS[i]);\n          } else {\n            // descend into searching rest of word w/ remaining dice.\n            check_mask(word,\n                       index + 1,\n                       used | FLAGS[i]);\n          }\n        }\n      }\n    }\n  }\n\n  process.stderr.write(\"CALCULATING MASKS FOR \");\n  for (var a = 97; a <= 97; a += 1) {\n    process.stderr.write(String.fromCharCode(a));\n    check_mask(String.fromCharCode(a), 0, 0x0);\n    for (var b = 97; b <= 122; b += 1) {\n      check_mask(String.fromCharCode(a,b), 0, 0x0);\n      for (var c = 97; c <= 122; c += 1) {\n        check_mask(String.fromCharCode(a,b,c), 0, 0x0);\n        for (var d = 97; d <= 122; d += 1) {\n          check_mask(String.fromCharCode(a,b,c,d), 0, 0x0);\n        }\n      }\n    }\n  }\n  process.stderr.write(\" DONE [\" + mask_count + \" MASKS]\\n\");\n};\n\nmake_masks();\n\nfunction check (word, index, used) {\n  //console.log('CHECK', word, index, used);\n\n  var length;\n  var masks;\n\n  // check up to 4 chars at a time\n  length = (word.length - index > 4) ? 4 : word.length - index;\n  masks = MASKS[word.slice(index, length + index)] || [];\n\n  for (var i = 0; i < masks.length; i += 1) {\n    if (!(used & masks[i])) {\n      // masks[i] has no overlap w/ tiles we already consumed.\n      if (word.length === index + length)\n        // we consumed the whole word.\n        return true;\n      else if (check(word, index + length, used | masks[i]))\n        // some descendant consumed the whole word\n        return true;\n    }\n  }\n\n  // none of the available masks returned true.  there's no match.\n  return false;\n};\n\nvar dict_len = DICTIONARY.length\nfor (var i = 0; i < dict_len; i+=1) {\n  var word = DICTIONARY[i];\n\n  // reject words that have q followed by non-u.  those can't be made\n  // in boggle.  otherwise, strip the q -- our dictionary won't\n  // include the u.\n\n  if (word.match(/q/)) {\n    if (word.match(/q[^u]/)) {\n      process.stderr.write('Q REJECT ' + word + '\\n');\n      continue;\n    } else {\n      word = word.replace('qu', 'q');\n      process.stderr.write('Q REPLACED ' + word + '\\n');\n    }\n  }\n\n  if (check(word, 0, 0x0))\n    console.log(word);\n  else\n    process.stderr.write('REJECT ' + DICTIONARY[i] + '\\n');\n};\n"
  },
  {
    "path": "examples/unfinished/accounts-ui-viewer/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/accounts-ui-viewer/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nautopublish\ninsecure\npreserve-inputs\naccounts-ui\nless\naccounts-google\naccounts-github\naccounts-password\nunderscore\naccounts-facebook\nstandard-app-packages\n"
  },
  {
    "path": "examples/unfinished/accounts-ui-viewer/.meteor/release",
    "content": "0.6.1\n"
  },
  {
    "path": "examples/unfinished/accounts-ui-viewer/accounts-ui-viewer.html",
    "content": "<head>\n  <title>accounts-ui-viewer</title>\n</head>\n\n<body>\n  {{> page}}\n</body>\n\n<template name=\"radio\">\n  <span class=\"radio\">\n    <input id=\"{{key}}:{{value}}\" {{maybeChecked}} type=\"radio\" name=\"{{key}}\" value=\"{{value}}\" />\n    <label for=\"{{key}}:{{value}}\">{{label}}</label>\n  </span>\n</template>\n\n<template name=\"button\">\n  <button>{{label}}</button>\n</template>\n\n<template name=\"page\">\n  <div id=\"controlpane\">\n    <div class=\"group\">\n      <h3>Dropdown align edge:</h3>\n      {{> radio key=\"alignRight\" value=\"false\" label=\"Left\"}}\n      {{> radio key=\"alignRight\" value=\"true\" label=\"Right\"}}\n    </div>\n    <div class=\"group\">\n      <h3>Positioning:</h3>\n      {{> radio key=\"positioning\" value=\"relative\" label=\"Relative\"}}\n      {{> radio key=\"positioning\" value=\"absolute\" label=\"Absolute\"}}\n      {{> radio key=\"positioning\" value=\"floatRight\" label=\"Float:right\"}}\n      {{> radio key=\"positioning\" value=\"inline\" label=\"Inline\"}}\n    </div>\n    <div class=\"group\">\n      <h3>How many third-party services?</h3>\n      {{> radio key=\"numServices\" value=\"0\" label=\"0\"}}\n      {{> radio key=\"numServices\" value=\"1\" label=\"1\"}}\n      {{> radio key=\"numServices\" value=\"2\" label=\"2\"}}\n      {{> radio key=\"numServices\" value=\"3\" label=\"3\"}}\n    </div>\n    <div class=\"group\">\n      <h3>Has password accounts?</h3>\n      {{> radio key=\"hasPasswords\" value=\"false\" label=\"No\"}}\n      {{> radio key=\"hasPasswords\" value=\"true\" label=\"Yes\"}}\n    </div>\n    <div class=\"group\">\n      <h3>Password sign-up fields:</h3>\n      {{> radio key=\"signupFields\" value=\"EMAIL_ONLY\" label=\"Email\"}}\n      {{> radio key=\"signupFields\" value=\"USERNAME_ONLY\" label=\"Username\"}}\n      {{> radio key=\"signupFields\" value=\"USERNAME_AND_EMAIL\" label=\"Username & Email\"}}\n      {{> radio key=\"signupFields\" value=\"USERNAME_AND_OPTIONAL_EMAIL\" label=\"Username & Optional Email\"}}\n    </div>\n    <div class=\"group\">\n      <h3>Fake-Configure:</h3>\n      {{> button key=\"fakeConfig\" value=\"facebook\" label=\"Facebook\"}}\n      {{> button key=\"fakeConfig\" value=\"github\" label=\"GitHub\"}}\n      {{> button key=\"fakeConfig\" value=\"google\" label=\"Google\"}}\n    </div>\n    <div class=\"group\">\n      <h3>Show Configure Dialog:</h3>\n      {{> button key=\"showConfig\" value=\"facebook\" label=\"Facebook\"}}\n      {{> button key=\"showConfig\" value=\"github\" label=\"GitHub\"}}\n      {{> button key=\"showConfig\" value=\"google\" label=\"Google\"}}\n    </div>\n    <div class=\"group\">\n      <h3>Unconfigure:</h3>\n      {{> button key=\"unconfig\" value=\"facebook\" label=\"Facebook\"}}\n      {{> button key=\"unconfig\" value=\"github\" label=\"GitHub\"}}\n      {{> button key=\"unconfig\" value=\"google\" label=\"Google\"}}\n    </div>\n    <div class=\"group\">\n      <h3>Messages:</h3>\n      {{> button key=\"messages\" value=\"error\" label=\"Error\"}}\n      {{> button key=\"messages\" value=\"info\" label=\"Info\"}}\n      {{> button key=\"messages\" value=\"clear\" label=\"Clear\"}}\n    </div>\n    <div class=\"group\">\n      <h3>Signing in/out</h3>\n      {{> button key=\"sign\" value=\"in\" label=\"Fake sign-in\"}}\n      {{> button key=\"sign\" value=\"out\" label=\"Sign out\"}}\n    </div>\n    <div class=\"group\">\n      <h3>Logged-out Views</h3>\n      {{> button key=\"lov\" value=\"signIn\" label=\"Sign In\"}}\n      {{> button key=\"lov\" value=\"createAccount\" label=\"Create Account\"}}\n      {{> button key=\"lov\" value=\"forgotPassword\" label=\"Forgot Password\"}}\n    </div>\n    <div class=\"group\">\n      <h3>Logged-in Views</h3>\n      {{> button key=\"liv\" value=\"accountButtons\" label=\"Account Buttons\"}}\n      {{> button key=\"liv\" value=\"changePassword\" label=\"Change Password\"}}\n      {{> button key=\"liv\" value=\"messageOnly\" label=\"Message Only\"}}\n    </div>\n    <div class=\"group\">\n      <h3>Other Modals</h3>\n      {{> button key=\"modals\" value=\"resetPassword\" label=\"Reset Password\"}}\n      {{> button key=\"modals\" value=\"enrollAccount\" label=\"Enroll Account\"}}\n      {{> button key=\"modals\" value=\"justVerifiedEmail\" label=\"Verified Email\"}}\n    </div>\n    <div class=\"group\">\n      <h3>Logging-in Spinner</h3>\n      {{> radio key=\"fakeLoggingIn\" value=\"false\" label=\"Off\"}}\n      {{> radio key=\"fakeLoggingIn\" value=\"true\" label=\"Pretend loggingIn=true\"}}\n    </div>\n    <div class=\"group\">\n      <h3>Background Color</h3>\n      {{> radio key=\"bgcolor\" value=\"white\" label=\"White\"}}\n      {{> radio key=\"bgcolor\" value=\"black\" label=\"Black\"}}\n      {{> radio key=\"bgcolor\" value=\"red\" label=\"Red\"}}\n    </div>\n  </div>\n  {{#with settings}}\n  <div id=\"previewpane\" class=\"{{settingsClass}}\" style=\"background:{{bgcolor}}\">\n    <div id=\"preview-wrapper\">\n      {{#if match \"positioning:inline\"}}\n        Here is a place to sign in, yay!\n      {{/if}}\n      {{> loginButtons align=dropdownAlign}}\n      {{#if match \"positioning:inline\"}}\n        Isn't that great?\n      {{/if}}\n    </div>\n    <div id=\"pos-indicator\"></div>\n    {{#unless match \"positioning:absolute\"}}\n      <div style=\"clear:both\">\n        A line that shouldn't move when logging in and logging out\n      </div>\n    {{/unless}}\n  </div>\n  {{/with}}\n</template>\n"
  },
  {
    "path": "examples/unfinished/accounts-ui-viewer/accounts-ui-viewer.js",
    "content": "\nMeteor.users.allow({update: function () { return true; }});\n\nif (Meteor.isClient) {\n\n  Accounts.STASH = _.extend({}, Accounts);\n  Accounts.STASH.loggingIn = Meteor.loggingIn;\n\n  var handleSetting = function (key, value) {\n    if (key === \"numServices\") {\n      _.each(['facebook', 'github', 'google'],\n             function (serv, i) {\n               if (i < value)\n                 Accounts[serv] = Accounts.STASH[serv];\n               else\n                 Accounts[serv] = null;\n             });\n    } else if (key === \"hasPasswords\") {\n      Accounts.password = value && Accounts.STASH.password || null;\n      var user = Meteor.user();\n      if (user) {\n        if (! value) {\n          // make sure we have no username if \"app\" has no passwords\n          Meteor.users.update(Meteor.userId(),\n                              { $unset: { username: 1 }});\n        } else {\n          // make sure we have a username\n          Meteor.users.update(Meteor.userId(),\n                              { $set: { username: Random.id() }});\n        }\n      }\n    } else if (key === \"signupFields\") {\n      Accounts.ui._options.passwordSignupFields = value;\n    } else if (key === \"fakeLoggingIn\") {\n      Meteor.loggingIn = (value ? function () { return true; } :\n                          Accounts.STASH.loggingIn);\n    }\n  };\n\n  if (! Session.get('settings'))\n    Session.set('settings', {\n      alignRight: false,\n      positioning: \"relative\",\n      numServices: 3,\n      hasPasswords: true,\n      signupFields: 'EMAIL_ONLY',\n      fakeLoggingIn: false,\n      bgcolor: 'white'\n    });\n  else\n    _.each(Session.get('settings'), function (v,k) {\n      handleSetting(k, v);\n    });\n\n  Template.page.settings = function () {\n    return Session.get('settings');\n  };\n\n  Template.page.settingsClass = function () {\n    var settings = Session.get('settings');\n    var classes = [];\n    if (settings.positioning)\n      classes.push('positioning-' + settings.positioning.toLowerCase());\n    return classes.join(' ');\n  };\n\n  var keyValueFromId = function (id) {\n    var match;\n    if (id && (match = /^(.*?):(.*)$/.exec(id))) {\n      var key = match[1];\n      var value = castValue(match[2]);\n      return [key, value];\n    }\n    return null;\n  };\n\n  var castValue = function (value) {\n    if (value === \"false\")\n      value = false;\n    else if (value === \"true\")\n      value = true;\n    else if (/^[0-9]+$/.test(value))\n      value = Number(value);\n    return value;\n  };\n\n  Template.radio.maybeChecked = function () {\n    var curValue = Session.get('settings')[this.key];\n    if (castValue(this.value) === curValue)\n      return 'checked';\n    return '';\n  };\n\n  Template.page.match = function (kv) {\n    kv = keyValueFromId(kv);\n    if (! kv)\n      return false;\n\n    return Session.get('settings')[kv[0]] === kv[1];\n  };\n\n  Template.page.dropdownAlign = function () {\n    var settings = this;\n    return settings.alignRight ? 'right' : 'left';\n  };\n\n  var fakeLogin = function (callback) {\n    Accounts.createUser(\n      {username: Random.id(),\n       password: \"password\",\n       profile: { name: \"Joe Schmoe\" }},\n      function () {\n        var user = Meteor.user();\n        if (! user)\n          return;\n        // delete our username if we are in a mode\n        // where there aren't usernames/emails/passwords\n        // (only third-party auth) so that there is no\n        // \"Change Password\" button when signed in\n        if (! Session.get('settings').hasPasswords)\n          Meteor.users.update(Meteor.userId(),\n                              { $unset: { username: 1 }});\n        callback();\n      });\n  };\n\n  var exitFlows = function () {\n    Accounts._loginButtonsSession.set('inSignupFlow', false);\n    Accounts._loginButtonsSession.set('inForgotPasswordFlow', false);\n    Accounts._loginButtonsSession.set('inChangePasswordFlow', false);\n    Accounts._loginButtonsSession.set('inMessageOnlyFlow', false);\n  };\n\n  Template.page.events({\n    'change #controlpane input[type=radio]': function (event) {\n      var input = event.currentTarget;\n      var keyValue;\n      if (input && input.id && (keyValue = keyValueFromId(input.id))) {\n        var key = keyValue[0];\n        var value = keyValue[1];\n        if (value === \"false\")\n          value = false;\n        else if (value === \"true\")\n          value = true;\n        var settings = Session.get('settings');\n        settings[key] = value;\n        Session.set('settings', settings);\n\n        handleSetting(key, value);\n      }\n    },\n    'click #controlpane button': function (event) {\n      if (this.key === \"fakeConfig\") {\n        var service = this.value;\n        if (! ServiceConfiguration.configurations.findOne({service: service}))\n          ServiceConfiguration.configurations.insert(\n            {service: service, fake: true});\n      } else if (this.key === \"unconfig\") {\n        var service = this.value;\n        ServiceConfiguration.configurations.remove({service: service});\n      } else if (this.key === \"messages\") {\n        if (this.value === \"error\") {\n          Accounts._loginButtonsSession.errorMessage('An error occurred!  Gee golly gosh.');\n        } else if (this.value === \"info\") {\n          Accounts._loginButtonsSession.infoMessage('Here is some information that is crucial.');\n        } else if (this.value === \"clear\") {\n          Accounts._loginButtonsSession.resetMessages();\n        }\n      } else if (this.key === \"sign\") {\n        if (this.value === 'in') {\n          // create a random new user\n          fakeLogin(function () {\n            Accounts._loginButtonsSession.closeDropdown();\n          });\n        } else if (this.value === 'out') {\n          Meteor.logout();\n        }\n      } else if (this.key === \"showConfig\") {\n        Accounts._loginButtonsSession.configureService(this.value);\n      } else if (this.key === \"lov\") {\n        exitFlows();\n        Accounts._loginButtonsSession.set(\"dropdownVisible\", true);\n        if (Meteor.userId())\n          Meteor.logout();\n        if (this.value === \"createAccount\")\n          Accounts._loginButtonsSession.set(\"inSignupFlow\", true);\n        else if (this.value === \"forgotPassword\")\n          Accounts._loginButtonsSession.set(\"inForgotPasswordFlow\", true);\n      } else if (this.key === \"liv\") {\n        exitFlows();\n        Accounts._loginButtonsSession.set(\"dropdownVisible\", true);\n        if (! Meteor.userId())\n          fakeLogin();\n        if (this.value === \"changePassword\")\n          Accounts._loginButtonsSession.set(\"inChangePasswordFlow\", true);\n        else if (this.value === \"messageOnly\")\n          Accounts._loginButtonsSession.set(\"inMessageOnlyFlow\", true);\n      } else if (this.key === \"modals\") {\n        var value = this.value;\n        _.each([\n          'resetPasswordToken',\n          'enrollAccountToken',\n          'justVerifiedEmail'], function (k) {\n            Accounts._loginButtonsSession.set(\n              k, k.indexOf(value) >= 0 ? 'foo' : null);\n          });\n      }\n    }\n  });\n\n}\n"
  },
  {
    "path": "examples/unfinished/accounts-ui-viewer/accounts-ui-viewer.less",
    "content": "html, body { height: 100%; }\n\n#controlpane {\n  position: absolute;\n  left: 0;\n  width: 299px;\n  top: 0;\n  bottom: 0;\n\n  background: #eee;\n  border-right: 1px solid #999;\n\n  overflow: auto;\n\n  h3 {\n    border-top: 1px solid #999;\n    font-size: 85%;\n    margin-bottom: 5px;\n  }\n\n  .group {\n    margin: 10px;\n  }\n\n  input[type=radio] {\n    margin-left: 5px;\n    vertical-align: middle;\n  }\n\n  label {\n    padding-left: 3px;\n  }\n}\n\n#previewpane {\n  position: absolute;\n  left: 300px;\n  right: 0;\n  top: 0;\n  bottom: 0;\n\n  #preview-wrapper {\n    margin: 20px;\n  }\n}\n\n.radio {\n  white-space: nowrap;\n}\n\n.positioning-floatright {\n  #login-buttons {\n    float: right;\n    margin-right: 180px;\n  }\n\n  #pos-indicator {\n    display: block;\n    top: 0;\n    right: 0;\n    width: 200px;\n    height: 20px;\n  }\n}\n\n.positioning-relative {\n  #login-buttons {\n    position: relative;\n    left: 150px;\n    top: 20px;\n  }\n\n  #pos-indicator {\n    display: block;\n    top: 0;\n    left: 0;\n    width: 170px;\n    height: 40px;\n  }\n}\n\n.positioning-absolute {\n  #login-buttons {\n    position: absolute;\n    left: 170px;\n    top: 40px;\n  }\n\n  #pos-indicator {\n    display: block;\n    top: 0;\n    left: 0;\n    width: 170px;\n    height: 40px;\n  }\n}\n\n#pos-indicator {\n  position: absolute;\n  background: #eec;\n  display: none;\n}\n\na { color: blue; }\n\nbutton { padding: 4px;\n         margin-bottom: 4px; // for when buttons wrap\n       }"
  },
  {
    "path": "examples/unfinished/atoms/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/atoms/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nstandard-app-packages\nautopublish\ninsecure\nunderscore\n"
  },
  {
    "path": "examples/unfinished/atoms/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "examples/unfinished/atoms/atoms.css",
    "content": "g[class=atom] circle {\n  stroke: black;\n  stroke-width: 3px;\n}\n\ng[class=atom] text {\n  font-family: Arial, sans-serif;\n  font-size: 24px;\n  fill: black;\n  font-weight: bold;\n  text-anchor: middle;\n}"
  },
  {
    "path": "examples/unfinished/atoms/atoms.html",
    "content": "<head>\n  <title>Atoms</title>\n</head>\n\n<body>\n  <div id=\"atoms\">\n    <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"500\" height=\"500\" viewBox=\"0 0 500 500\">\n      {{#atom x=100 y=100 color=\"#ffff00\"}}O{{/atom}}\n      {{> hydrogen x=150 y=100}}\n      {{#giantatom x=250 y=100 color=\"#ff9999\"}}My{{/giantatom}}\n    </svg>\n  </div>\n</body>\n\n<template name=\"atom\">\n  <g class=\"atom\">\n    <circle style=\"fill: {{#if color}}{{color}}{{else}}white{{/if}}\" cx={{x}} cy={{y}} r={{#if r}}{{r}}{{else}}20{{/if}} />\n    <text x={{x}} y={{textY}}>{{> UI.contentBlock}}</text>\n  </g>\n</template>\n\n<template name=\"hydrogen\">\n  {{#atom x=x y=y r=r color=\"#00ffff\"}}H{{/atom}}\n</template>\n\n<template name=\"giantatom\">\n  {{#atom x=x y=y r=50 color=color}}{{> UI.contentBlock}}{{/atom}}\n</template>\n"
  },
  {
    "path": "examples/unfinished/atoms/atoms.js",
    "content": "if (Meteor.isClient) {\n  Template.atom.textY = function () {\n    return this.y + 8;\n  };\n}\n"
  },
  {
    "path": "examples/unfinished/azrael/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/azrael/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nunderscore\njquery\njquery-layout\nstandard-app-packages\n"
  },
  {
    "path": "examples/unfinished/azrael/.meteor/release",
    "content": "0.6.0\n"
  },
  {
    "path": "examples/unfinished/azrael/client/azrael.css",
    "content": "#room-list .room.selected {\n    color: white;\n    background-color: black;\n}\n\n.room .name {\n    display: inline;\n}\n\n.room .delete {\n    float: right;\n    display: none;\n}\n\n.room:hover .delete {\n    display: block;\n}\n\n.add-room {\n    margin-top: 20px;\n    font-style: italic;\n}\n\n.add-room:hover {\n    text-decoration: underline;\n}"
  },
  {
    "path": "examples/unfinished/azrael/client/azrael.html",
    "content": "<body>\n\n<div class=\"ui-layout-center\" id=\"chat-view\">\n  {{> center_pane }}\n</div>\n<div class=\"ui-layout-east\">East</div>\n<div class=\"ui-layout-west\">\n  {{> room_list}}\n  {{> add_room}}\n</div>\n<div class=\"ui-layout-north\">Azrael</div>\n\n</body>\n\n<template name=\"room_list\">\n  <div id=\"room-list\">\n    {{#each rooms}}\n      {{> room}}\n    {{/each}}\n  </div>\n</template>\n\n<template name=\"add_room\">\n  <div class=\"add-room\">\n    Create new room\n  </div>\n</template>\n\n<template name=\"room\">\n  <div class=\"room {{maybe_selected}}\">\n  {{#if editing}}\n    <input id=\"room_name_input\" value=\"{{name}}\">\n  {{else}}\n    <div class=\"name\">{{name}}</div>\n    <div class=\"delete\">(x)</div>\n  {{/if}}\n  </div>\n</template>\n\n<template name=\"center_pane\">\n  <div id=\"center-pane\">\n    {{#if any_room_selected}}\n      <div id=\"chat\">\n        {{#each messages}}\n          {{> chat_message}}\n        {{else}}\n           No chat yet!\n        {{/each}}\n      </div>\n      <input id=\"chat-entry\">\n    {{else}}\n      No room selected\n    {{/if}}\n  </div>\n</template>\n\n<template name=\"chat_message\">\n  <div>\n    {{username}}: {{message}}\n  </div>\n</template>\n"
  },
  {
    "path": "examples/unfinished/azrael/client/azrael.js",
    "content": "Meteor.subscribe('rooms');\n\nSession.set('current_room', null);\nSession.set('editing_room_name', false);\n\nDeps.autorun(function () {\n  var room_id = Session.get('current_room');\n  if (room_id) Meteor.subscribe('room-detail', room_id);\n});\n\n// XXX would be nice to eliminate this function and have people just\n// call Session.set(\"current_room\", foo) directly instead\nvar selectRoom = function (room_id) {\n  // XXX pushstate\n  var room = Rooms.find(room_id);\n  Session.set('current_room', room_id);\n};\n\nMeteor.startup(function () {\n  $('body').layout({applyDefaultStyles: true})\n});\n\nTemplate.room_list.rooms = function () {\n  // XXX it would be nice if this were find instead of findLive (ie,\n  // if they were unified in some sane way)\n  return Rooms.findLive({}, {sort: {name: 1}});\n};\n\nTemplate.add_room.events = {\n  'click': function () {\n    // XXX should put up dialog to get name\n    // XXX should support automatically set created/updated timestamps\n    var room_id = Rooms.insert({name: \"New room\",\n                                // XXX horrid syntax\n                                created: (new Date()).getTime()});\n    selectRoom(room_id);\n    // XXX XXX XXX this fails to work -- it leaves edit mode after\n    // 1RTT. what happens is, the server echos the insert back to us,\n    // and that is currently wired up to trigger a changed event on\n    // the findlive, which redraws the element, which triggers blur,\n    // which causes us to set editing_room_name to false.\n    //\n    // one option is to have the rendering function (maybe in a\n    // post-render routine?) decide if it currently wants\n    // focus. (should that be within the recomputation envelope, I\n    // wonder?)\n    //\n    // another is to suppress blur on rerender. probably the only\n    // principled way to do this is to narrow the scope of the\n    // rerender to not include the <input>.\n    //\n    // [No idea if the comment above is still current]\n    Session.set('editing_room_name', true);\n    Deps.flush();\n    $('#room_name_input').focus();\n  }\n};\n\nTemplate.room.events = {\n  'mousedown': function (evt) {\n    selectRoom(this._id);\n  },\n  'dblclick': function (evt) {\n    Session.set('editing_room_name', true);\n    // XXX XXX doesn't generalize.. the element might very reasonably\n    // not have a unique id. may need a different strategy..\n    Deps.flush();\n    $('#room_name_input').focus();\n  },\n  'blur input': function (evt) {\n    Session.set('editing_room_name', false);\n  },\n  'keypress input': function (evt) {\n    // XXX should really have a binding/validator-based pattern\n    // XXX check to see this pattern works if you are saving\n    // continuously (on every keystroke)\n    var value = $(evt.target).val();\n    if (evt.which === 13 && value.length)\n      Rooms.update(this._id, {$set: {name: value}});\n    if (evt.which === 13 || evt.which === 27)\n      Session.set('editing_room_name', false);\n  },\n  // If you make this event be click (rather than mousedown), then\n  // delete doesn't work if the room isn't already selected. what\n  // happens is, the mousedown triggers the selection, which redraws\n  // the room, meaning that the elements are replaced out from under\n  // the event, and the click event is lost.. bleh. needs\n  // reconsideration.\n  'mousedown .delete': function (evt) {\n    Rooms.remove('rooms', this._id);\n    Session.set('current_room', null);\n  },\n};\n\nTemplate.room.editing = function (options) {\n  // Check current_room first, before editing_room_name, to minimize\n  // number of redraws\n  return (Session.equals('current_room', this._id) &&\n          Session.equals('editing_room_name', true));\n};\n\nTemplate.room.maybe_selected = function () {\n  return Session.equals('current_room', this._id) ? \"selected\" : \"\";\n};\n\nTemplate.center_pane.messages = function () {\n  return Chat.findLive({room: Session.get(\"current_room\")},\n                       {sort: {created: 1}});\n};\n\nTemplate.center_pane.any_room_selected = function () {\n  return !Session.equals('current_room', null);\n};\n\nTemplate.center_pane.events = {\n  'keydown #chat-entry': function (evt) {\n    if (evt.which === 13) {\n      var room_id = Session.get('current_room');\n      if (!room_id)\n        return;\n\n      Chat.insert({room: room_id, message: $(evt.target).val(),\n                   username: \"someone\",\n                   created: (new Date()).getTime()});\n      $(evt.target).val('');\n    }\n  }\n};\n"
  },
  {
    "path": "examples/unfinished/azrael/model.js",
    "content": "// XXX it is actually very dangerous to store times as Number. use\n// Date type once it's implemented in minimongo\nRooms = new Mongo.Collection(\"rooms\");\n//Rooms.schema({name: String, created: Number});\n\nChat = new Mongo.Collection(\"chat\");\n/*\nChat.schema({room: String, message: String,\n             username: String, created: Number});\n*/\n\nif (Meteor.isServer) {\n  Meteor.publish('rooms', function () {\n    return Rooms.find();\n  });\n\n  // XXX should limit to just a certain amount of recent chat ..\n  Meteor.publish('room-detail', function (room) {\n    return Chat.find({room: room});\n  });\n}\n"
  },
  {
    "path": "examples/unfinished/benchmark/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/benchmark/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\ninsecure\npreserve-inputs\nbootstrap\nrandom\nstandard-app-packages\n"
  },
  {
    "path": "examples/unfinished/benchmark/.meteor/release",
    "content": "0.6.5.1\n"
  },
  {
    "path": "examples/unfinished/benchmark/benchmark.css",
    "content": "/* CSS declarations go here */\n"
  },
  {
    "path": "examples/unfinished/benchmark/benchmark.html",
    "content": "<head>\n  <title>benchmark</title>\n</head>\n\n<body>\n  {{> status}}\n\n  {{> params}}\n</body>\n\n<template name=\"status\">\n  <p>Status: {{status}}</p>\n  <p>Update Rate: {{updateRate}}</p>\n</template>\n\n<template name=\"params\">\n  <dl>\n  {{#each params}}\n  <dt>{{key}}</dt><dd>{{value}}</dd>\n  {{/each}}\n  </dl>\n</template>\n\n"
  },
  {
    "path": "examples/unfinished/benchmark/benchmark.js",
    "content": "\n// Pick scenario from settings.\n// XXX settings now has public. could move stuff there and avoid this.\nvar PARAMS = {};\nif (Meteor.isServer) {\n  if (!Meteor.settings.params)\n    throw new Error(\"Must set scenario with Meteor.settings\");\n  __meteor_runtime_config__.PARAMS = PARAMS = Meteor.settings.params;\n} else {\n  PARAMS = __meteor_runtime_config__.PARAMS;\n}\n\n\n// id for this client or server.\nvar processId = Random.id();\nconsole.log(\"processId\", processId);\n\n\n//////////////////////////////\n// Helper Functions\n//////////////////////////////\n\nvar random = function (n) {\n  return Math.floor(Random.fraction() * n);\n};\n\nvar randomChars =\n      'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split('');\nvar randomString = function (length) {\n  // XXX make more efficient\n  var ret = '';\n  _.times(length, function () {\n    ret += Random.choice(randomChars);\n  });\n  return ret;\n};\n\nvar preCall = function (name) {\n  console.log('> ' + name);\n};\n\nvar postCall = function (name) {\n  return function (err, callback) {\n    console.log('< ' + name + ' ' + (err ? 'ERR' : 'OK'));\n  };\n};\n\nvar pickCollection = function () {\n  return Random.choice(Collections);\n};\n\nvar generateDoc = function () {\n  var ret = {};\n  ret.fromProcess = processId;\n  _.times(PARAMS.documentNumFields, function (n) {\n    ret['Field' + n] = randomString(PARAMS.documentSize/PARAMS.documentNumFields);\n  });\n\n  return ret;\n};\n\n\n//////////////////////////////\n// Data\n//////////////////////////////\n\n\nvar Collections = [];\n_.times(PARAMS.numCollections, function (n) {\n  Collections.push(new Mongo.Collection(\"Collection\" + n));\n});\n\n\nif (Meteor.isServer) {\n\n  // Make sure we have indexes. Helps mongo CPU usage.\n  Meteor.startup(function () {\n    _.each(Collections, function (C) {\n      C._ensureIndex({toProcess: 1});\n      C._ensureIndex({fromProcess: 1});\n      C._ensureIndex({when: 1});\n    });\n  });\n\n  // periodic db check. generate a client list.\n  var currentClients = [];\n  var totalDocs = 0;\n  Meteor.setInterval(function () {\n    var newClients = {};\n    var newTotal = 0;\n    // XXX hardcoded time\n    var since = +(new Date) - 1000*PARAMS.insertsPerSecond * 5;\n    _.each(Collections, function (C) {\n      _.each(C.find({when: {$gt: since}}, {fields: {fromProcess: 1, when: 1}}).fetch(), function (d) {\n        newTotal += 1;\n        if (d.fromProcess && d.when > since)\n          newClients[d.fromProcess] = true;\n      });\n    });\n    currentClients = _.keys(newClients);\n    totalDocs = newTotal;\n  }, 3*1000); // XXX hardcoded time\n\n  // periodic document cleanup.\n  if (PARAMS.maxAgeSeconds) {\n    Meteor.setInterval(function () {\n      var when = +(new Date) - PARAMS.maxAgeSeconds*1000;\n      _.each(Collections, function (C) {\n        preCall('removeMaxAge');\n        C.remove({when: {$lt: when}}, postCall('removeMaxAge'));\n      });\n      // Clear out 5% of the DB each time, steady state. XXX parameterize?\n    }, 1000*PARAMS.maxAgeSeconds / 20);\n  }\n\n  Meteor.publish(\"data\", function (collection, process) {\n    check(collection, Number);\n    check(process, String);\n    var C = Collections[collection];\n    return C.find({toProcess: process});\n  });\n\n  Meteor.methods({\n    'insert': function (doc) {\n      check(doc, Object);\n      check(doc.fromProcess, String);\n      // pick a random destination. send to ourselves if there is no one\n      // else. by having an entry in the db, we'll end up in the target\n      // list.\n      doc.toProcess = Random.choice(currentClients) || doc.fromProcess;\n\n      doc.when = +(new Date);\n\n      var C = pickCollection();\n      preCall('insert');\n      C.insert(doc, postCall('insert'));\n    },\n    update: function (processId, field, value) {\n      check([processId, field, value], [String]);\n      var modifer = {};\n      modifer[field] = value; // XXX injection attack?\n\n      var C = pickCollection();\n      // update one message.\n      preCall('update');\n      C.update({fromProcess: processId}, {$set: modifer}, {multi: false}, postCall('update'));\n    },\n    remove: function (processId) {\n      check(processId, String);\n      var C = pickCollection();\n      // remove one message.\n      var obj = C.findOne({fromProcess: processId});\n      if (obj) {\n        preCall('remove');\n        C.remove(obj._id, postCall('remove'));\n      }\n    }\n  });\n\n\n  // XXX publish stats\n  // - currentClients.length\n  // - serverId\n  // - num ddp sessions\n  // - total documents\n}\n\n\n\nif (Meteor.isClient) {\n  // sub to data\n  _.times(PARAMS.numCollections, function (n) {\n    Meteor.subscribe(\"data\", n, processId);\n  });\n\n  // templates\n  Template.params.params = function () {\n    return _.map(PARAMS, function (v, k) {\n      return {key: k, value: v};\n    });\n  };\n\n  Template.status.status = function () {\n    return Meteor.status().status;\n  };\n\n  Template.status.updateRate = function () {\n    return (Session.get('updateAvgs') || []).join(\", \");\n  };\n\n  // XXX count of how many docs are in local collection?\n\n\n  // do stuff periodically\n\n  if (PARAMS.insertsPerSecond) {\n    Meteor.setInterval(function () {\n      Meteor.call('insert', generateDoc());\n    }, 1000 / PARAMS.insertsPerSecond);\n  }\n\n  if (PARAMS.updatesPerSecond) {\n    Meteor.setInterval(function () {\n      Meteor.call('update',\n                  processId,\n                  'Field' + random(PARAMS.documentNumFields),\n                  randomString(PARAMS.documentSize/PARAMS.documentNumFields)\n                 );\n    }, 1000 / PARAMS.updatesPerSecond);\n  }\n\n  if (PARAMS.removesPerSecond) {\n    Meteor.setInterval(function () {\n      Meteor.call('remove', processId);\n    }, 1000 / PARAMS.removesPerSecond);\n  }\n\n\n\n  // XXX very rough per client update rate. we need to measure this\n  // better. ideally, on the server we could get the global update rate\n  var updateCount = 0;\n  var updateHistories = {1: [], 10: [], 100: [], 1000: []};\n  var updateFunc = function () { updateCount += 1; };\n  _.each(Collections, function (C) {\n    C.find({}).observeChanges({\n      added: updateFunc, changed: updateFunc, removed: updateFunc\n    });\n  });\n  Meteor.setInterval(function () {\n    _.each(updateHistories, function (h, max) {\n      h.push(updateCount);\n      if (h.length > max)\n        h.shift();\n    });\n    Session.set('updateAvgs', _.map(updateHistories, function (h) {\n      return _.reduce(h, function(memo, num) {\n        return memo + num;\n      }, 0) / h.length;\n    }));;\n    updateCount = 0;\n  }, 1000);\n\n}\n"
  },
  {
    "path": "examples/unfinished/benchmark/run-local.sh",
    "content": "#!/usr/bin/env bash\n\nPORT=9000\nif [ -z \"$NUM_CLIENTS\" ]; then\n  NUM_CLIENTS=10\nfi\nif [ -z \"$DURATION\" ]; then\n  DURATION=120\nfi\nREPORT_INTERVAL=10\n\nset -e\ntrap 'echo \"FAILED. Killing: $(jobs -pr)\" ; for pid in \"$(jobs -pr)\"; do kill $pid ; done' EXIT\n\nPROJDIR=`dirname $0`\ncd \"$PROJDIR\"\nPROJDIR=`pwd`\n\nSCENARIO=\"${1:-default}\"\n\n# clean up from previous runs\n# XXX this is gross!\npkill -f \"$PROJDIR/.meteor/local/db\" || true\n../../../meteor reset || true\n\n# start the benchmark app\n../../../meteor --production --settings \"scenarios/${SCENARIO}.json\" --port ${PORT} &\nOUTER_PID=$!\n\necho \"Waiting for server to come up\"\nfunction wait_for_port {\n    local N=0\n    while ! curl -v \"$1\" 2>&1 | grep ' 200 ' > /dev/null ; do\n        sleep 1\n        N=$(($N+1))\n        if [ $N -ge $2 ] ; then\n            curl -v \"$1\" || true\n            echo \"Timed out waiting for port $1\"\n            exit 2\n        fi\n    done\n}\nwait_for_port \"http://localhost:${PORT}\" 60\n\n\necho \"Starting phantoms\"\n# start a bunch of phantomjs processes\nPHANTOMSCRIPT=`mktemp -t benchmark-XXXXXXXX`\ncat > \"$PHANTOMSCRIPT\" <<EOF\nvar page = require('webpage').create();\nvar url = 'http://localhost:$PORT';\npage.open(url);\nEOF\nfor ((i = 0 ; i < $NUM_CLIENTS ; i++)) ; do\n    # sleep between each phantom start both to provide a smoother ramp\n    # to the benchmark and because otherwise their PRNGs get set to the\n    # same seed and you get duplicate key errors!\n    sleep 2\n    phantomjs \"$PHANTOMSCRIPT\" &\ndone\n\nps -o cputime,ppid,args | grep \" $OUTER_PID \" | grep main.js || true\nfor ((i = 0 ; i < $DURATION/$REPORT_INTERVAL ; i++)) ; do\n    sleep $REPORT_INTERVAL\n    ps -o cputime,ppid,args | grep \" $OUTER_PID \" | grep main.js || true\ndone\n\n# print totals of all processes (outer, mongo, inner)\necho\necho TOTALS\nps -o cputime,pid,ppid,args | grep \" $OUTER_PID \" | grep -v grep || true\n\n\n# cleanup\ntrap - EXIT\nfor pid in \"$(jobs -pr)\"; do\n    # not sure why we need both, but it seems to help clean up rogue\n    # mongo and phantomjs processes.\n    kill -INT $pid\n    kill $pid\ndone\nrm \"$PHANTOMSCRIPT\"\n\n\n"
  },
  {
    "path": "examples/unfinished/benchmark/scenarios/README.md",
    "content": "Parameters for simulation:\n\n- numCollections\n    how many collections to spread the documents over\n\n- maxAgeSeconds: How long to leave documents in the database. This,\n    combined with all the various rates, determines the steady state\n    database size. In seconds. falsy to disable.\n\nPer-client action rates:\n- insertsPerSecond\n- updatesPerSecond\n- removesPerSecond\n\n- documentSize: bytes of randomness per document.\n    // XXX make this a random distribution?\n- documentNumFields: how many fields of randomness per document.\n"
  },
  {
    "path": "examples/unfinished/benchmark/scenarios/default.json",
    "content": " {\n  \"params\": {\n    \"numCollections\": 1,\n    \"maxAgeSeconds\": 60,\n    \"insertsPerSecond\": 1,\n    \"updatesPerSecond\": 1,\n    \"removesPerSecond\": 0.1,\n    \"documentSize\": 1024,\n    \"documentNumFields\": 8\n  }\n}\n"
  },
  {
    "path": "examples/unfinished/benchmark/scenarios/fast.json",
    "content": " {\n  \"params\": {\n    \"numCollections\": 1,\n    \"maxAgeSeconds\": 60,\n    \"insertsPerSecond\": 5,\n    \"updatesPerSecond\": 5,\n    \"removesPerSecond\": 1,\n    \"documentSize\": 128,\n    \"documentNumFields\": 2\n  }\n}\n"
  },
  {
    "path": "examples/unfinished/benchmark/scenarios/nodata.json",
    "content": "{\n  \"params\": {\n    \"numCollections\": 1\n  }\n}\n"
  },
  {
    "path": "examples/unfinished/benchmark/scenarios/scale10.json",
    "content": " {\n  \"params\": {\n    \"numCollections\": 1,\n    \"maxAgeSeconds\": 60,\n    \"insertsPerSecond\": 10,\n    \"updatesPerSecond\": 10,\n    \"removesPerSecond\": 1,\n    \"documentSize\": 128,\n    \"documentNumFields\": 2\n  }\n}\n"
  },
  {
    "path": "examples/unfinished/benchmark/scenarios/scale100.json",
    "content": " {\n  \"params\": {\n    \"numCollections\": 1,\n    \"maxAgeSeconds\": 60,\n    \"insertsPerSecond\": 100,\n    \"updatesPerSecond\": 100,\n    \"removesPerSecond\": 10,\n    \"documentSize\": 128,\n    \"documentNumFields\": 2\n  }\n}\n"
  },
  {
    "path": "examples/unfinished/benchmark/scenarios/scale20.json",
    "content": " {\n  \"params\": {\n    \"numCollections\": 1,\n    \"maxAgeSeconds\": 60,\n    \"insertsPerSecond\": 20,\n    \"updatesPerSecond\": 20,\n    \"removesPerSecond\": 2,\n    \"documentSize\": 128,\n    \"documentNumFields\": 2\n  }\n}\n"
  },
  {
    "path": "examples/unfinished/benchmark/scenarios/scale40.json",
    "content": " {\n  \"params\": {\n    \"numCollections\": 1,\n    \"maxAgeSeconds\": 60,\n    \"insertsPerSecond\": 40,\n    \"updatesPerSecond\": 40,\n    \"removesPerSecond\": 4,\n    \"documentSize\": 128,\n    \"documentNumFields\": 2\n  }\n}\n"
  },
  {
    "path": "examples/unfinished/benchmark/scenarios/scale50.json",
    "content": " {\n  \"params\": {\n    \"numCollections\": 1,\n    \"maxAgeSeconds\": 60,\n    \"insertsPerSecond\": 50,\n    \"updatesPerSecond\": 50,\n    \"removesPerSecond\": 5,\n    \"documentSize\": 128,\n    \"documentNumFields\": 2\n  }\n}\n"
  },
  {
    "path": "examples/unfinished/blaze-test/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/blaze-test/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nstandard-app-packages\nautopublish\ninsecure\nblaze\nhtmljs\nblaze-tools\n"
  },
  {
    "path": "examples/unfinished/blaze-test/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "examples/unfinished/blaze-test/client/blaze-test.css",
    "content": "/* CSS declarations go here */\n"
  },
  {
    "path": "examples/unfinished/blaze-test/client/blaze-test.html",
    "content": "<head>\n  <title>blaze-test</title>\n</head>\n\n<body>\n\n</body>\n"
  },
  {
    "path": "examples/unfinished/blaze-test/client/blaze-test.js",
    "content": "Meteor.startup(function () {\n\nBlaze._wrapAutorun = function (c) {\n  console.log('Created #' + c._id);\n  var callback = function () {\n    if (c.stopped) {\n      console.log('Stopped #' + c._id);\n    } else {\n      console.log('Invalidated #' + c._id);\n      Deps.afterFlush(function () {\n        c.onInvalidate(callback);\n      });\n    }\n  };\n  c.onInvalidate(callback);\n};\n\ntheNumber = Blaze.Var(0);\ntheColor = Blaze.Var('yellow');\n\nIf = function (conditionVar, contentFunc, elseFunc) {\n  return Blaze.Isolate(function () {\n    return conditionVar.get() ? contentFunc() :\n      (elseFunc ? elseFunc() : null);\n  });\n};\n\nWith = function (dataVar, func) {\n  if (! (this instanceof With))\n    // called without new\n    return new With(dataVar, func);\n\n  Blaze.Controller.call(this);\n\n  this.data = dataVar;\n  this.func = func;\n};\nBlaze.__extends(With, Blaze.Controller);\n_.extend(With.prototype, {\n  render: function () {\n    var func = this.func;\n    return func();\n  }\n});\n\nEvents = function (eventMap, func) {\n  if (! (this instanceof Events))\n    // called without new\n    return new Events(eventMap, func);\n\n  Blaze.Controller.call(this);\n\n  this.eventMap = eventMap;\n  this.func = func;\n};\nBlaze.__extends(Events, Blaze.Controller);\n_.extend(Events.prototype, {\n  render: function () {\n    var func = this.func;\n    return func();\n  },\n  renderToDOM: function () {\n    var range = Blaze.Controller.prototype.renderToDOM.call(this);\n    range.addDOMAugmenter(new Blaze.EventAugmenter(this.eventMap));\n    return range;\n  }\n});\n\nRepeat = function (countVar, contentFunc) {\n  var seq, count;\n  var comp = Deps.autorun(function () {\n    if (! seq) {\n      count = countVar.get();\n      if (typeof count !== 'number')\n        throw new Error(\"Expected number\");\n      var funcs = new Array(count);\n      for (var i = 0; i < count; i++)\n        funcs[i] = contentFunc;\n      seq = new Blaze.Sequence(funcs);\n    } else {\n      var targetCount = countVar.get();\n      while (count < targetCount) {\n        seq.addItem(contentFunc, count);\n        count++;\n      }\n      while (count > targetCount) {\n        seq.removeItem(count-1);\n        count--;\n      }\n    }\n  });\n  Blaze._wrapAutorun(comp);\n  return Blaze.List(seq);\n};\n\nTicker = function () {\n  var self = this;\n  Blaze.Component.call(self);\n  self.time = Blaze.Var(new Date);\n  self.timer = setInterval(function () {\n    self.time.set(new Date);\n  }, 1000);\n};\nBlaze.__extends(Ticker, Blaze.Component);\n_.extend(Ticker.prototype, {\n  render: function () {\n    var self = this;\n    return Blaze.Isolate(function () {\n      return String(self.time.get());\n    });\n  },\n  finalize: function () {\n    clearInterval(this.timer);\n  }\n});\n\nouterRange = Blaze.render(function () {\n  return [HTML.DIV(\n    {style: If(Blaze.Var(function () { return theNumber.get() % 3 === 0; }),\n               function () { return ['background:', theColor.get()]; })},\n    \"The number \", Blaze.Isolate(function () { return theNumber.get(); }), \" is \",\n    If(Blaze.Var(function () {\n      return theNumber.get() % 2 === 0;\n    }), function () {\n      return \"even\";\n    }, function () {\n      return \"odd\";\n    }), \".\"),\n          HTML.UL(\n            Repeat(theNumber,\n                   function () {\n                     return With(Blaze.Var(123), function () {\n                       return Events(\n                         {'click li': function () { console.log('click li'); }},\n                         function () {\n                           return HTML.LI(\n                             Blaze.Isolate(function () {\n                               console.log('Context:', Blaze.currentController.parentController.data.get());\n                               return theNumber.get(); }),\n                             \" - \", new Ticker\n                           );\n                         });\n                     });\n                   }))];\n\n});\nouterRange.attach(document.body);\n\n\n// Now, run:\n//\n// ```\n// theNumber.set(1);\n// theNumber.set(2);\n//\n// outerRange.stop();\n// ```\n\n});\n"
  },
  {
    "path": "examples/unfinished/chat-benchmark/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/chat-benchmark/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\ninsecure\npreserve-inputs\nbootstrap\nrandom\nstandard-app-packages\nfacts\n"
  },
  {
    "path": "examples/unfinished/chat-benchmark/.meteor/release",
    "content": "0.6.5.1\n"
  },
  {
    "path": "examples/unfinished/chat-benchmark/benchmark.css",
    "content": "/* CSS declarations go here */\n"
  },
  {
    "path": "examples/unfinished/chat-benchmark/benchmark.html",
    "content": "<head>\n  <title>benchmark</title>\n</head>\n\n<body>\n  {{> status}}\n\n  {{> params}}\n\n  {{> serverFacts}}\n</body>\n\n<template name=\"status\">\n  <p>Status: {{status}}</p>\n  <p>Update Rate: {{updateRate}}</p>\n</template>\n\n<template name=\"params\">\n  <dl>\n  {{#each params}}\n  <dt>{{key}}</dt><dd>{{value}}</dd>\n  {{/each}}\n  </dl>\n</template>\n\n"
  },
  {
    "path": "examples/unfinished/chat-benchmark/benchmark.js",
    "content": "// Pick which scenario we run. Pass the 'SCENARIO' environment variable\n// to change this. See 'benchmark-scenarios.js' for the list of\n// scenarios.\n\nvar PARAMS = {};\n// XXX settings now has public. could move stuff there and avoid this.\nif (Meteor.isServer) {\n  if (!Meteor.settings.params)\n    throw new Error(\"Must set scenario with Meteor.settings\");\n  __meteor_runtime_config__.PARAMS = PARAMS = Meteor.settings.params;\n} else {\n  PARAMS = __meteor_runtime_config__.PARAMS;\n}\n\n// id for this client or server.\nvar processId = Random.id();\nconsole.log(\"SSS\", processId);\n\n\n//////////////////////////////\n// Helper Functions\n//////////////////////////////\n\nvar random = function (n) {\n  return Math.floor(Random.fraction() * n);\n};\n\nvar randomChars =\n      'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split('');\nvar randomString = function (length) {\n  // XXX make more efficient\n  var ret = '';\n  _.times(length, function () {\n    ret += Random.choice(randomChars);\n  });\n  return ret;\n};\n\n\n//////////////////////////////\n// Data\n//////////////////////////////\n\n\nRooms = new Mongo.Collection(\"rooms\");\nMessages = new Mongo.Collection(\"messages\");\n\n\nif (Meteor.isServer) {\n  // init\n  Meteor.startup(function () {\n    Messages._ensureIndex({room: 1});\n    Messages._ensureIndex({when: 1});\n    Rooms._ensureIndex({random: 1});\n    Rooms._ensureIndex({when: 1});\n  });\n\n  // periodic document cleanup.\n  // XXX only needs to run on one server.\n  // XXX do we even need this with room deletion?\n  if (PARAMS.messageHistorySeconds) {\n    Meteor.setInterval(function () {\n      var when = +(new Date) - PARAMS.messageHistorySeconds*1000;\n      Messages.remove({when: {$lt: when}});\n    }, 1000*PARAMS.messageHistorySeconds / 20);\n  }\n\n  // periodic room cleanup.\n  // XXX only needs to run on one server.\n  if (PARAMS.roomHistorySeconds) {\n    Meteor.setInterval(function () {\n      var when = +(new Date) - PARAMS.roomHistorySeconds*1000;\n      Rooms.remove({when: {$lt: when}});\n    }, 1000*PARAMS.roomHistorySeconds / 20);\n  }\n\n\n\n  Meteor.publish(\"rooms\", function (clientId) {\n    var self = this;\n    check(clientId, String);\n\n    var myRoom = Rooms.findOne(clientId);\n    // yeah, yeah, i'm inserting in a publish function. deal with it.\n    if (!myRoom) {\n      myRoom = {_id: clientId, when: +(new Date()), random: Random.fraction()};\n      Rooms.insert(myRoom);\n    }\n    self.added(\"rooms\", clientId, myRoom);\n\n    var otherRooms = Rooms.find({random: {$gte: Random.fraction()}},\n                                {limit: PARAMS.roomsPerClient,\n                                 order: {random: 1}}).fetch();\n\n    _.each(otherRooms, function (room) {\n      self.added(\"rooms\", room._id, room);\n    });\n\n    self.ready();\n  });\n\n  Meteor.publish(\"messages\", function (roomId) {\n    check(roomId, String);\n    return Messages.find({room: roomId});\n  });\n\n  Meteor.methods({\n    'insert': function (doc) {\n      check(doc, {\n        from: String,\n        room: String,\n        message: String\n      });\n\n      // use server clock, don't trust the client.\n      doc.when = +(new Date);\n\n      Messages.insert(doc);\n    }\n  });\n\n\n  // XXX publish stats\n  // - currentClients.length\n  // - serverId\n  // - num ddp sessions\n  // - total documents\n\n  Facts.setUserIdFilter(function () {return true;});\n}\n\n\n\nif (Meteor.isClient) {\n  var myRooms = [];\n  Meteor.subscribe(\"rooms\", processId, function () {\n    // XXX should autorun to change rooms? meh.\n    var r = Rooms.find({}, {limit: PARAMS.roomsPerClient}).fetch();\n    _.each(r, function (room) {\n      Meteor.subscribe(\"messages\", room._id);\n      myRooms.push(room, room._id);\n    });\n  });\n\n  // templates\n  Template.params.params = function () {\n    return _.map(PARAMS, function (v, k) {\n      return {key: k, value: v};\n    });\n  };\n\n  Template.status.status = function () {\n    return Meteor.status().status;\n  };\n\n  Template.status.updateRate = function () {\n    return (Session.get('updateAvgs') || []).join(\", \");\n  };\n\n  // XXX count of how many docs are in local collection. don't \n\n  // do stuff periodically\n  Meteor.setInterval(function () {\n    if (Random.fraction() < PARAMS.chanceClientIsTalkative) {\n      console.log(\"Talking\");\n      var room = Random.choice(myRooms);\n      if (!room) return;\n      var numMessages = PARAMS.talkativePeriodSeconds *\n            PARAMS.talkativeMessagesPerSecond;\n      _.times(numMessages, function (i) {\n        Meteor.setTimeout(function () {\n          Meteor.call('insert', {\n            from: processId,\n            room: room,\n            message: randomString(PARAMS.messageSize)\n          });\n        }, 1000 * i / PARAMS.talkativeMessagesPerSecond);\n      });\n    }\n  }, PARAMS.talkativePeriodSeconds * 1000);\n\n\n  // XXX very rough per client update rate. we need to measure this\n  // better. ideally, on the server we could get the global update rate\n  var updateCount = 0;\n  var updateHistories = {1: [], 10: [], 100: [], 1000: []};\n  var updateFunc = function () { updateCount += 1; };\n  Messages.find({}).observeChanges({\n    added: updateFunc, changed: updateFunc, removed: updateFunc\n  });\n  Meteor.setInterval(function () {\n    _.each(updateHistories, function (h, max) {\n      h.push(updateCount);\n      if (h.length > max)\n        h.shift();\n    });\n    Session.set('updateAvgs', _.map(updateHistories, function (h) {\n      return _.reduce(h, function(memo, num) {\n        return memo + num;\n      }, 0) / h.length;\n    }));;\n    updateCount = 0;\n  }, 1000);\n\n}\n"
  },
  {
    "path": "examples/unfinished/chat-benchmark/run-local.sh",
    "content": "#!/usr/bin/env bash\n\nPORT=9000\nNUM_CLIENTS=10\nDURATION=120\nREPORT_INTERVAL=10\n\nset -e\ntrap 'echo \"FAILED. Killing: $(jobs -pr)\" ; for pid in \"$(jobs -pr)\"; do kill $pid ; done' EXIT\n\nPROJDIR=`dirname $0`\ncd \"$PROJDIR\"\nPROJDIR=`pwd`\n\nSCENARIO=\"${1:-default}\"\n\n# clean up from previous runs\n# XXX this is gross!\npkill -f \"$PROJDIR/.meteor/local/db\" || true\n../../../meteor reset || true\n\n# start the benchmark app\n../../../meteor --production --settings \"scenarios/${SCENARIO}.json\" --port 9000 &\nOUTER_PID=$!\n\n\n# start a bunch of phantomjs processes\nPHANTOMSCRIPT=`mktemp -t benchmark-XXXXXXXX`\ncat > \"$PHANTOMSCRIPT\" <<EOF\nvar page = require('webpage').create();\nvar url = 'http://localhost:$PORT';\npage.open(url);\nEOF\nfor ((i = 0 ; i < $NUM_CLIENTS ; i++)) ; do\n    # sleep between each phantom start both to provide a smoother ramp\n    # to the benchmark and because otherwise their PRNGs get set to the\n    # same seed and you get duplicate key errors!\n    sleep 2\n    phantomjs \"$PHANTOMSCRIPT\" &\ndone\n\nps -o cputime,ppid,args | grep \" $OUTER_PID \" | grep main.js || true\nfor ((i = 0 ; i < $DURATION/$REPORT_INTERVAL ; i++)) ; do\n    sleep $REPORT_INTERVAL\n    ps -o cputime,ppid,args | grep \" $OUTER_PID \" | grep main.js || true\ndone\n\n# print totals of all processes (outer, mongo, inner)\necho\necho TOTALS\nps -o cputime,pid,ppid,args | grep \" $OUTER_PID \" | grep -v grep || true\n\n\n# cleanup\ntrap - EXIT\nfor pid in \"$(jobs -pr)\"; do\n    # not sure why we need both, but it seems to help clean up rogue\n    # mongo and phantomjs processes.\n    kill -INT $pid\n    kill $pid\ndone\nrm \"$PHANTOMSCRIPT\"\n\n\n"
  },
  {
    "path": "examples/unfinished/chat-benchmark/scenarios/README.md",
    "content": "Each client creates a room when it starts up and joins that room plus\n`roomsPerClient` other rooms.\n\nEvery `talkativePeriodSeconds`, each client has a\n`chanceClientIsTalkative` probability of being \"talkative\". If it is\ntalkative for that period, it will send one `messageSize` sized message\nevery `talkativeMessagesPerSecond` for the duration of the period.\n\nOld messages are deleted every `messageHistorySeconds` seconds. Old\nrooms are deleted every `roomHistorySeconds`. `roomHistorySeconds`\nshould line up with the length a particular client dwells on the site\n(typically part of the phantomjs script used to drive the clients.)\n"
  },
  {
    "path": "examples/unfinished/chat-benchmark/scenarios/default.json",
    "content": "{\n  \"params\": {\n    \"roomsPerClient\": 5,\n    \"messageHistorySeconds\": 600,\n    \"roomHistorySeconds\": 500,\n    \"talkativeMessagesPerSecond\": 0.2,\n    \"talkativePeriodSeconds\": 60,\n    \"chanceClientIsTalkative\": 0.10,\n    \"messageSize\": 140\n  }\n}\n"
  },
  {
    "path": "examples/unfinished/coffeeless/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/coffeeless/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nless\ncoffeescript\nstandard-app-packages\n"
  },
  {
    "path": "examples/unfinished/coffeeless/.meteor/release",
    "content": "0.6.0\n"
  },
  {
    "path": "examples/unfinished/coffeeless/client/coffeeless.coffee",
    "content": "Meteor.subscribe 'presses'\n\nTemplate.button_demo.events =\n  'click input': ->\n     console.log \"press\"\n     Presses.insert {}\n\nTemplate.button_demo.press_count = -> Presses.find({}).length\n"
  },
  {
    "path": "examples/unfinished/coffeeless/client/coffeeless.html",
    "content": "<head>\n  <title>coffeeless</title>\n</head>\n\n<body>\n  <h1>coffeeless</h1>\n\n  Welcome to Meteor! Here is a button for you to press.\n\n  {{> button_demo }}\n\n  <!-- Meteor is an incredibly fast way to create incredibly great\n  websites\n  - in pure Javascript\n\n  - using your tools of choice, from jQuery and backbone to\n  Coffeescript and handlebars\n  -->\n\n  <img class=\"banner\" src=\"/4201645142_ec2e3bb3f8_b.jpg\">\n\n</body>\n\n<template name=\"button_demo\">\n  <div>\n    <input type=\"button\" value=\"Button\"><br>\n\n    This delightful button has\n\n    {{#if never_pressed}}\n      never been pressed! Won't you be the first?\n    {{else}}\n      been pressed {{press_count}} times.\n    {{/if}}\n  </div>\n</template>\n"
  },
  {
    "path": "examples/unfinished/coffeeless/client/coffeeless.less",
    "content": "@red: #842210;\n\nh1 {\n    color: @red;\n}\n\nimg {\n    display: block;\n    position: absolute;\n    top: 0px;\n    right: 0px;\n}\n"
  },
  {
    "path": "examples/unfinished/coffeeless/model.coffee",
    "content": "root = exports ? this # export Presses globally.\nroot.Presses = new Mongo.Collection 'presses'\n\nMeteor.publish 'presses'\n"
  },
  {
    "path": "examples/unfinished/controls/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/controls/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nautopublish\nstandard-app-packages\n"
  },
  {
    "path": "examples/unfinished/controls/.meteor/release",
    "content": "0.6.0\n"
  },
  {
    "path": "examples/unfinished/controls/client/controls.js",
    "content": "var SPEW = function(str) {\n  SPEW.lines.push(str);\n  // use counter to signal invalidation\n  Session.set(\"SPEW_V\", (Session.get(\"SPEW_V\") || 0)+1);\n};\nSPEW.lines = [];\n\nTemplate.radios.events = {\n  'change input': function(event) {\n    //SPEW(\"change \"+event.target.value);\n    if (event.target.checked) {\n      Session.set(\"current_band\", event.target.value);\n    }\n  }\n};\n\nTemplate.radios.current_band = function() {\n  return Session.get(\"current_band\");\n};\n\nTemplate.radios.band_checked = function(b) {\n  return Session.equals(\"current_band\", b) ?\n    'checked=\"checked\"' : '';\n};\n\nTemplate.checkboxes.events = {\n  'change input': function(event) {\n    Session.set(\"dst\", event.target.checked);\n  }\n};\n\nTemplate.checkboxes.dst_checked = function() {\n  return Session.get(\"dst\") ? 'checked=\"checked\"' : '';\n};\n\nTemplate.checkboxes.dst = function() {\n  return Session.get(\"dst\") ? 'Yes' : 'No';\n};\n\nTemplate.spew.lines = function() {\n  Session.get(\"SPEW_V\");\n  return SPEW.lines;\n};\n"
  },
  {
    "path": "examples/unfinished/controls/controls.css",
    "content": "/* CSS declarations go here */\n"
  },
  {
    "path": "examples/unfinished/controls/controls.html",
    "content": "<head>\n  <title>controls</title>\n</head>\n\n<body>\n  {{> radios}}\n  {{> checkboxes}}\n  {{> spew}}\n</body>\n\n<template name=\"radios\">\n  <div>\n    Band:\n    <input type=\"radio\" name=\"bands\" value=\"AM\" {{band_checked \"AM\"}}/>\n    <input type=\"radio\" name=\"bands\" value=\"FM\" {{band_checked \"FM\"}}/>\n    <input type=\"radio\" name=\"bands\" value=\"XM\" {{band_checked \"XM\"}}/>\n    {{current_band}}\n  </div>\n</template>\n\n<template name=\"checkboxes\">\n  <div>\n    Daylight Savings Time:\n    <input type=\"checkbox\" name=\"dst\" value=\"yes\" {{dst_checked}}/>\n    {{dst}}\n  </div>\n</template>\n\n<template name=\"spew\">\n  <div>\n    {{#each lines}}\n      <br>{{this}}\n    {{/each}}\n  </div>\n</template>\n"
  },
  {
    "path": "examples/unfinished/jsparse-docs/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/jsparse-docs/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nautopublish\nstandard-app-packages\n"
  },
  {
    "path": "examples/unfinished/jsparse-docs/.meteor/release",
    "content": "0.6.0\n"
  },
  {
    "path": "examples/unfinished/jsparse-docs/jsparse-docs.css",
    "content": "\np, .topnotes .nodespec { margin: 0.8em; }\n.topnotes {\n    background: #ffd;\n    margin-bottom: 2em;\n    margin-left: 1em;\n    margin-right: 1em;\n    border: 2px solid #ccc;    \n}\n\n.str { font-weight: bold; }\n.token { font-family: monospace; font-size: 110%; font-weight: bold; }\n.token, .tokentype { background: #ddd; padding: 2px 5px; }\n.tokentype { font-size: 85%; }\n.ref { font-style: italic; }\n.punc { font-size: 140%; }\n.comma { color: #fff; }\n.or { padding-left: 3px; padding-right: 3px; }\n\n.nodespec {\n  font-size: 16px;\n  margin: 1em 0;\n  line-height: 20px;\n}\n\n.indent {\n  margin-left: 2em;\n}\n\n.explan {\n  margin-left: 20em;\n  margin-right: 2em;\n  border: 1px solid #ccc;\n}\n\n#page { max-width: 50em; margin: 0 auto; }\n\n.spacer { text-align: center; font-size:50%; font-weight: bold; border-top: 1px solid #999;\n         margin-left: 6em; margin-right: 6em;\n        }\n\ncode { font-weight: bold; }\n"
  },
  {
    "path": "examples/unfinished/jsparse-docs/jsparse-docs.html",
    "content": "<head>\n  <title>jsparse Docs</title>\n</head>\n\n<body>\n  <div id=\"page\">\n    {{> page}}\n  </div>\n</body>\n\n<template name=\"page\">\n\n<div class=\"topnotes\">\n  <p>This is the spec for the JavaScript syntax tree returned by <code>jsparse</code>.</p>\n\n   <p>It's notable that <em>every token</em> from the source code appears in order in this syntax tree, which\n   is a Concrete Syntax Tree (CST) rather than an abstract AST.</p>\n  \n  {{spacer}}\n\n  <p>The tree consists of <strong>nodes</strong>\n    and <strong>tokens</strong>.  A node consists of a name followed\n    by zero or more child nodes or tokens.  A token consists of\n    one or more characters from the source code.</p>\n  <p>For example, the following tree, which might have come from parsing <code>1 + 2</code>,\n    contains nodes named <span class=\"str\">\"binary\"</span>,\n    <span class=\"str\">\"number\"</span>, and <span class=\"str\">\"number\"</span>\n    and the tokens <span class=\"token\">1</span>, <span class=\"token\">+</span>,\n    and <span class=\"token\">2</span>:</p>\n  \n    <p>{{#nodespec}}[\"binary\", [\"number\", `1`], `+`, [\"number\", `2`]]{{/nodespec}}</p>\n\n  {{spacer}}\n    \n    <p>The following notation is used throughout this document to give schematic definitions of\n      the different types of nodes.</p>\n    \n    <p>An <span class=\"ref\">italicized</span> word refers to a list of one or more possible\n      nodes or tokens that could fill a certain spot.  For example, the following is the\n      definition of the <span class=\"str\">\"binary\"</span> node:</p>\n\n    <p>{{#nodespec}}[\"binary\", expression, binaryOp, expression]{{/nodespec}}</p>\n\n    <p>The <span class=\"ref\">expression</span> spot could be filled by one of over 20 types\n      of expression nodes, and if you look up <span class=\"ref\">binaryOp</span> you'll see\n      it refers to any of a list of binary operator tokens.</p>\n\n    <p>A vertical bar (<span class=\"punc or\">|</span>) separates alternatives, of which exactly\n      one must be present in the tree.  An ellipsis (<span class=\"punc\">...</span>) stands\n      for a sequence of <em>zero or more</em> of the preceding item.  For example:</p>\n\n    {{#nodespec}}[\"program\", (statement | functionDecl), ...]{{/nodespec}}\n\n    <p>This definition says that a program node contains zero or more items, each of which may be either a\n      <span class=\"ref\">statement</span> or a <span class=\"ref\">functionDecl</span>.</p>\n\n    <p>A question mark (<span class=\"punct\">?</span>) indicates that the previous item\n      (or items enclosed in parentheses) may or may not present.</p>\n\n    <p>Token classes like <span class=\"tokentype\">IDENTIFIER</span> match any token in the class.  The <span class=\"tokentype\">BOOLEAN</span>, <span class=\"tokentype\">NUMBER</span>, <span class=\"tokentype\">STRING</span>, and <span class=\"tokentype\">REGEX</span> classes are all literals.  An example <span class=\"tokentype\">STRING</span> would be <span class=\"token\">\"hello\"</span>.\n\n      {{spacer}}\n\n     <p>Some definitions with ellipses may seem strangely permissive, such as:</p>\n\n  {{#nodespec}}[\"varStmnt\", `var`, (varDecl | `,`), ..., semi]{{/nodespec}}\n\n     <p>This seems to say that <code>var;</code> and <code>var,,x,</code> are valid statements.\n       The reason for this style of definition is to discourage reliance on exact comma\n       positions, which may occasionally vary between JavaScript implementations and versions.\n       For example, the 5th edition of ECMAScript allows a trailing comma in object literals whereas\n       the 3rd edition doesn't.</p>\n\n     <p>For most applications, the commas aren't that important, and you can read all the varDecls\n       by just skipping any commas you encounter.</p>\n      \n</div>\n\n{{#nodespec}}program:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}[\"program\", (statement | functionDecl), ...]{{/nodespec}}\n</div>\n\n{{#nodespec}}statement:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}[\"expressionStmnt\", expression, semi]{{/nodespec}}\n  <div class=\"explan\">\n    <p>Function calls and assignments are expressions.</p>\n  </div>\n  {{#nodespec}}[\"emptyStmnt\", `;`]{{/nodespec}}\n  <div class=\"explan\">\n    <p>Only an actual <span class=\"token\">;</span> token can create an empty statement.</p>\n  </div>\n  {{#nodespec}}[\"blockStmnt\", `{`, statement, ..., `}`]{{/nodespec}}\n  {{#nodespec}}[\"varStmnt\", `var`, (varDecl | `,`), ..., semi]{{/nodespec}}\n  <div class=\"explan\">\n    <p>You can assume at least one varDecl is present.</p>\n  </div>\n  {{#nodespec}}[\"ifStmnt\", `if`, `(`, expression, `)`, statement, (`else`, statement)?]{{/nodespec}}\n  {{#nodespec}}[\"whileStmnt\", `while`, `(`, expression, `)`, statement]{{/nodespec}}\n  {{#nodespec}}[\"doStmnt\", `do`, statement, `while`, `(`, expression, `)`, semi]{{/nodespec}}\n  {{#nodespec}}[\"forStmnt\", `for`, `(`, forSpec, `)`, statement]{{/nodespec}}\n  {{#nodespec}}[\"returnStmnt\", `return`, (expression | nil), semi]{{/nodespec}}\n  {{#nodespec}}[\"continueStmnt\", `continue`, (IDENTIFIER | nil), semi]{{/nodespec}}\n  {{#nodespec}}[\"breakStmnt\", `break`, (IDENTIFIER | nil), semi]{{/nodespec}}\n  {{#nodespec}}[\"throwStmnt\", `throw`, expression, semi]{{/nodespec}}\n  {{#nodespec}}[\"withStmnt\", `with`, `(`, expression, `)`, statement]{{/nodespec}}\n  {{#nodespec}}[\"switchStmnt\", `switch`, `(`, expression, `)`, `{`, (case | default), ..., `}`]{{/nodespec}}\n  <div class=\"explan\">\n    <p>There's at most one default clause, but it can be anywhere in the list of cases and defaults.</p>\n  </div>\n  {{#nodespec}}[\"tryStmnt\", `try`, statement, (catch | nil), (finally | nil)]{{/nodespec}}\n  <div class=\"explan\">\n    <p>The statement is always a blockStmnt.</p>\n  </div>\n  {{#nodespec}}[\"labelStmnt\", IDENTIFIER, `:`, statement]{{/nodespec}}\n  {{#nodespec}}[\"debuggerStmnt\", `debugger`, semi]{{/nodespec}}\n</div>\n\n{{#nodespec}}functionDecl:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}[\"functionDecl\", `function`, IDENTIFIER, `(`, (IDENTIFIER | `,`), ..., `)`, `{`, (statement | functionDecl), ..., `}`]{{/nodespec}}\n  <div class=\"explan\">\n    <p>Different from a functionExpr only in that the function name is required and not optional.</p>\n  </div>\n</div>\n\n{{#nodespec}}expression:{{/nodespec}}\n<div class=\"indent\">\n{{#nodespec}}[\"this\", `this`]{{/nodespec}}\n{{#nodespec}}[\"null\", `null`]{{/nodespec}}\n{{#nodespec}}[\"number\", NUMBER]{{/nodespec}}\n{{#nodespec}}[\"boolean\", BOOLEAN]{{/nodespec}}\n{{#nodespec}}[\"regex\", REGEX]{{/nodespec}}\n{{#nodespec}}[\"string\", STRING]{{/nodespec}}\n{{#nodespec}}[\"identifier\", IDENTIFIER]{{/nodespec}}\n{{#nodespec}}[\"parens\", `(`, expression, `)`]{{/nodespec}}\n{{#nodespec}}[\"array\", `[`, (expression | `,`), ..., `]`]{{/nodespec}}\n  <div class=\"explan\">\n    <p>All commas are significant because of element elision, and any\n      combination of commas and expressions is possible.\n    The array <code>[,,,7,,8,,]</code> has 7 and 8 as\n    its 3rd and 5th elements.</p>\n  </div>\n{{#nodespec}}[\"object\", `{`, (prop | `,`), ..., `}`]{{/nodespec}}\n{{#nodespec}}[\"functionExpr\", `function`, (IDENTIFIER | nil), `(`, (IDENTIFIER | `,`), ..., `)`, `{`, (statement | functionDecl), ..., `}`]{{/nodespec}}\n{{#nodespec}}[\"dot\", expression, `.`, identifierName]{{/nodespec}}\n{{#nodespec}}[\"bracket\", expression, `[`, expression, `]`]{{/nodespec}}\n{{#nodespec}}[\"call\", expression, `(`, (expression | `,`), ...,  `)`]{{/nodespec}}\n{{#nodespec}}[\"new\", `new`, expression]{{/nodespec}}\n{{#nodespec}}[\"newcall\", `new`, expression, `(`, (expression | `,`), ...,  `)`]{{/nodespec}}\n{{#nodespec}}[\"unary\", unaryOp, expression]{{/nodespec}}\n{{#nodespec}}[\"binary\", expression, binaryOp, expression]{{/nodespec}}\n{{#nodespec}}[\"postfix\", expression, postfixOp]{{/nodespec}}\n{{#nodespec}}[\"ternary\", expression, `?`, expression, `:`, expression]{{/nodespec}}\n{{#nodespec}}[\"assignment\", expression, assignmentOp, expression]{{/nodespec}}\n<div class=\"explan\">\n<p>There is no simple constraint on what the first expression can be.\n  A left-hand-side expression could be a simple identifier like <code>foo</code>,\nor it could be any expression ending in a property access, such as <code>foo().bar[baz]</code>.\nParentheses are also allowed around the left-hand side, so surprisingly <code>((x)) = 3</code>\nis completely legal and equivalent to <code>x = 3</code>.  This is because\nJavaScript evaluates the left-hand side all the way down to the final variable reference.</p>\n</div>\n{{#nodespec}}[\"comma\", (expression | `,`), ...]{{/nodespec}}\n<div class=\"explan\"><p>You can assume there are at least two expressions, since there would have been no comma otherwise.</p></div>\n</div>\n\n{{#nodespec}}nil:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}[\"nil\"]{{/nodespec}}\n  <div class=\"explan\"><p>Serves as a placeholder for optional parts of nodes.</p></div>\n</div>\n\n{{#nodespec}}semi:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}[\";\"] | `;`{{/nodespec}}\n  <div class=\"explan\">\n    <p>An optional semicolon at the end of a statement.  Most semicolons in JavaScript can legally\n    be omitted if a line break follows.  If the semicolon was omitted, a <span class=\"str\">\";\"</span>\n    node takes its place.</p>\n  </div>\n</div>\n\n{{#nodespec}}prop:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}[\"prop\", propertyName, `:`, expression]{{/nodespec}}\n</div>\n\n{{#nodespec}}propertyName:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}[\"idPropName\", identifierName]{{/nodespec}}\n  {{#nodespec}}[\"strPropName\", STRING]{{/nodespec}}\n  {{#nodespec}}[\"numPropName\", NUMBER]{{/nodespec}}\n  <div class=\"explan\">\n    <p>A property name in an object literal can be given as a bare identifier, a quoted string literal,\n    or a number literal.  These nodes indicate which it is.</p>\n  </div>\n</div>\n\n{{#nodespec}}varDecl:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}[\"varDecl\", IDENTIFIER, (`=`, expression)?]{{/nodespec}}\n</div>\n\n{{#nodespec}}forSpec:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}[\"forSpec\", (expression | nil), `;`, (expression | nil), `;`, (expression | nil)]{{/nodespec}}\n  {{#nodespec}}[\"forVarSpec\", `var`, (varDecl | `,`), ..., `;`, (expression | nil), `;`, (expression | nil)]{{/nodespec}}\n  {{#nodespec}}[\"forInSpec\", expression, `in`, expression]{{/nodespec}}\n  {{#nodespec}}[\"forVarInSpec\", `var`, varDecl, `in`, expression]{{/nodespec}}\n  <div class=\"explan\">\n    <p>There are technically four types of for-loops in JavaScript.</p>\n      <p>These definitions suggest some\n      odd possibilities, and interestingly, they work.  The form <code>for (x.foo in y)</code> will actually\n      set <code>x.foo</code> each time through the loop, and <code>for (var x = bar() in y)</code> will call\n      <code>bar()</code> and assign it first thing,\n      even if <code>x</code> is immediately overwritten before the first iteration of the loop.</p>\n    <p>The semicolons are mandatory, even at a line break.</p>\n  </div>\n</div>\n\n{{#nodespec}}case:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}[\"case\", `case`, expression, `:`, statement, ...]{{/nodespec}}\n</div>\n\n{{#nodespec}}default:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}[\"default\", `default`, `:`, statement, ...]{{/nodespec}}\n</div>\n\n{{#nodespec}}catch:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}[\"catch\", `catch`, `(`, IDENTIFIER, `)`, statement]{{/nodespec}}\n  <div class=\"explan\">\n    <p>The statement is always a blockStmnt.</p>\n  </div>\n</div>\n\n{{#nodespec}}finally:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}[\"finally\", `finally`, statement]{{/nodespec}}\n  <div class=\"explan\">\n    <p>The statement is always a blockStmnt.</p>\n  </div>\n</div>\n\n{{#nodespec}}identifierName:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}(IDENTIFIER | KEYWORD | BOOLEAN | `null`){{/nodespec}}\n  <div class=\"explan\">\n    <p>As of ECMAScript 5th edition, keywords and reserved words can be used in some places\n      where an identifier is expected.  For example, <code>x.return()</code> or\n      <code>{true: 'yes'}</code>.</p>\n  </div>\n</div>\n\n{{#nodespec}}unaryOp:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}(`delete` | `void` | `typeof` | `++` | `--` | `+` | `-` | `~` | `!`){{/nodespec}}\n</div>\n\n{{#nodespec}}binaryOp:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}(`*` | `/` | `%` | `+` | `-` | `<<` | `>>` | `>>>` | `<` | `>` | `<=` | `>=` | `instanceof` | `in` | `==` | `!=` | `===` | `!==` | `&` | `^` | `|` | `&&` | `||`){{/nodespec}}\n</div>\n\n{{#nodespec}}postfixOp:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}(`++` | `--`){{/nodespec}}\n</div>\n\n{{#nodespec}}assignmentOp:{{/nodespec}}\n<div class=\"indent\">\n  {{#nodespec}}(`=` | `*=` | `/=` | `%=` | `+=` | `-=` | `<<=` | `>>=` | `>>>=` | `&=` | `^=` | `|=`){{/nodespec}}\n</div>\n\n</template>\n"
  },
  {
    "path": "examples/unfinished/jsparse-docs/jsparse-docs.js",
    "content": "\n\nif (Meteor.isClient) {\n  Template.page.nodespec = function (fn) {\n    var parts = [fn()];\n    var replaceParts = function(regex, replacementFunc) {\n      var newParts = [];\n      _.each(parts, function (part) {\n        if (typeof part !== 'string') {\n          newParts.push(part);\n          return;\n        }\n        regex.lastIndex = 0;\n        var charsTaken = 0;\n        var matchResult;\n        while ((matchResult = regex.exec(part))) {\n          var matchIndex = matchResult.index;\n          if (matchIndex > charsTaken)\n            newParts.push(part.substring(charsTaken, matchIndex));\n          charsTaken = regex.lastIndex;\n          var replacementParts = replacementFunc(matchResult);\n          newParts.push.apply(newParts, _.toArray(replacementParts));\n        }\n        if (charsTaken < part.length)\n          newParts.push(part.slice(charsTaken));\n      });\n      parts = newParts;\n    };\n\n    parts.unshift(['<div class=\"nodespec\">']);\n    parts.push(['</div>']);\n    replaceParts(/\".*?\"/g, function (match) {\n      return [['<span class=\"str\">', Handlebars._escape(match[0]), '</span>']];\n    });\n    replaceParts(/`(.*?)`/g, function (match) {\n      return [['<span class=\"token\">', Handlebars._escape(match[1]), '</span>']];\n    });\n    replaceParts(/[A-Z]{3,}/g, function (match) {\n      return [['<span class=\"tokentype\">', Handlebars._escape(match[0]), '</span>']];\n    });\n    replaceParts(/[a-z]\\w*/g, function (match) {\n      return [['<span class=\"ref\">', Handlebars._escape(match[0]), '</span>']];\n    });\n    replaceParts(/[\\[\\]()|.,*?]/g, function (match) {\n      return [['<span class=\"punc\">'], match[0], ['</span>']];\n    });\n    replaceParts(/,/g, function (match) {\n      return [['<span class=\"comma\">'], match[0], ['</span>']];\n    });\n    replaceParts(/\\|/g, function (match) {\n      return [['<span class=\"or\">'], match[0], ['</span>']];\n    });\n\n    var html = _.map(parts, function (part) {\n      if (typeof part === \"string\")\n        return Handlebars._escape(part);\n      return part.join('');\n    }).join('');\n\n    return new Handlebars.SafeString(html);\n  };\n\n  Template.page.spacer = function () {\n    return new Handlebars.SafeString('<div class=\"spacer\">&nbsp;</div>');\n  };\n\n}\n"
  },
  {
    "path": "examples/unfinished/leaderboard-remote/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/leaderboard-remote/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nautopublish\nstandard-app-packages\n"
  },
  {
    "path": "examples/unfinished/leaderboard-remote/.meteor/release",
    "content": "0.6.0\n"
  },
  {
    "path": "examples/unfinished/leaderboard-remote/client/leaderboard-remote.css",
    "content": "body {\n    width: 400px;\n    margin: 100px auto 0 auto;\n    background-color: white;\n    font-family: 'Helvetica Neue', Helvetica, Arial, san-serif;\n    line-height: 1.3;\n}\n\n#meteor {\n    position: absolute;\n    left: 0px;\n    bottom: 0px;\n    opacity: .25;\n    z-index: -1;\n}\n\nh1 {\n    color: red;\n    font-size: 3em;\n    font-weight: 200;\n    border-style: solid none none none;\n    border-color: red;\n    border-width: 4px;\n}\n\n.button_demo {\n    margin-top: 2em;\n    width: 100%;\n}\n\n.button_demo input {\n    display: block;\n    margin: 0 auto .5em auto;\n    width: 125px;\n}\n\n.button_demo div {\n    text-align: center;\n    color: #777;\n    font-weight: bold;\n}\n"
  },
  {
    "path": "examples/unfinished/leaderboard-remote/client/leaderboard-remote.html",
    "content": "<head>\n  <title>Remote collection demo</title>\n</head>\n\n<body>\n  <div id=\"wrapper\">\n  <img src=\"planes.png\" id=\"meteor\">\n\n  {{> main}}\n  \n  </div>\n</body>\n\n<template name=\"main\">\n  <h1>Average score of top 10 players</h1>\n  {{average_score}}\n\n  <h1>Add a player</h1>\n  <div>\n    Name: <input id=\"name\"><br>\n    Initial score: <input id=\"score\"><br>\n    <button class=\"add\">Add</button>\n    {{#if error}}\n      {{error}}\n    {{/if}}\n  </div>\n\n  <h1>Take points</h1>\n  <div>\n    <button class=\"take-points\">Take 20 points from leader</button>\n  </div>\n</template>\n"
  },
  {
    "path": "examples/unfinished/leaderboard-remote/client/leaderboard-remote.js",
    "content": "Leaderboard = DDP.connect(\"http://leader2.meteor.com/sockjs\");\n\n// XXX I'd rather this be Leaderboard.Players.. can this API be easier?\nPlayers = new Mongo.Collection(\"players\", {manager: Leaderboard});\n\nTemplate.main.events = {\n  'keydown': function () {\n    Session.set(\"error\", null);\n  },\n  'click .add': function () {\n    var name = $('#name').val();\n    var score = $('#score').val();\n\n    if (name.match(/^\\s*$/)) {\n      Session.set(\"error\", \"You must give a name\");\n      return;\n    }\n    if (score.match(/^\\s*$/)) {\n      Session.set(\"error\", \"You must give a score\");\n      return;\n    }\n    score = +score;\n    if (isNaN(score)) {\n      Session.set(\"error\", \"Score must be a number\");\n      return;\n    }\n\n    Players.insert({name: name, score: score});\n    $('#name').val('');\n    $('#score').val('');\n  },\n  'click .take-points': function () {\n    var top = Players.findOne({}, {sort: {score: -1}});\n    if (top)\n      Players.update(top._id, {$inc: {score: -20}});\n  },\n};\n\nTemplate.main.error = function () {\n  return Session.get(\"error\");\n};\n\nTemplate.main.average_score = function () {\n  var count = 0;\n  var total = 0;\n  Players.find().forEach(function (player) {\n    count++;\n    total += player.score;\n  });\n  return total / count;\n};\n"
  },
  {
    "path": "examples/unfinished/movers/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/movers/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nstandard-app-packages\nautopublish\ninsecure\npreserve-inputs\nless\n"
  },
  {
    "path": "examples/unfinished/movers/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "examples/unfinished/movers/client/jquery-ui-sortable.js",
    "content": "/*! jQuery UI - v1.10.3 - 2013-07-30\n* http://jqueryui.com\n* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.sortable.js\n* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */\n\n(function( $, undefined ) {\n\nvar uuid = 0,\n\truniqueId = /^ui-id-\\d+$/;\n\n// $.ui might exist from components with no dependencies, e.g., $.ui.position\n$.ui = $.ui || {};\n\n$.extend( $.ui, {\n\tversion: \"1.10.3\",\n\n\tkeyCode: {\n\t\tBACKSPACE: 8,\n\t\tCOMMA: 188,\n\t\tDELETE: 46,\n\t\tDOWN: 40,\n\t\tEND: 35,\n\t\tENTER: 13,\n\t\tESCAPE: 27,\n\t\tHOME: 36,\n\t\tLEFT: 37,\n\t\tNUMPAD_ADD: 107,\n\t\tNUMPAD_DECIMAL: 110,\n\t\tNUMPAD_DIVIDE: 111,\n\t\tNUMPAD_ENTER: 108,\n\t\tNUMPAD_MULTIPLY: 106,\n\t\tNUMPAD_SUBTRACT: 109,\n\t\tPAGE_DOWN: 34,\n\t\tPAGE_UP: 33,\n\t\tPERIOD: 190,\n\t\tRIGHT: 39,\n\t\tSPACE: 32,\n\t\tTAB: 9,\n\t\tUP: 38\n\t}\n});\n\n// plugins\n$.fn.extend({\n\tfocus: (function( orig ) {\n\t\treturn function( delay, fn ) {\n\t\t\treturn typeof delay === \"number\" ?\n\t\t\t\tthis.each(function() {\n\t\t\t\t\tvar elem = this;\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t$( elem ).focus();\n\t\t\t\t\t\tif ( fn ) {\n\t\t\t\t\t\t\tfn.call( elem );\n\t\t\t\t\t\t}\n\t\t\t\t\t}, delay );\n\t\t\t\t}) :\n\t\t\t\torig.apply( this, arguments );\n\t\t};\n\t})( $.fn.focus ),\n\n\tscrollParent: function() {\n\t\tvar scrollParent;\n\t\tif (($.ui.ie && (/(static|relative)/).test(this.css(\"position\"))) || (/absolute/).test(this.css(\"position\"))) {\n\t\t\tscrollParent = this.parents().filter(function() {\n\t\t\t\treturn (/(relative|absolute|fixed)/).test($.css(this,\"position\")) && (/(auto|scroll)/).test($.css(this,\"overflow\")+$.css(this,\"overflow-y\")+$.css(this,\"overflow-x\"));\n\t\t\t}).eq(0);\n\t\t} else {\n\t\t\tscrollParent = this.parents().filter(function() {\n\t\t\t\treturn (/(auto|scroll)/).test($.css(this,\"overflow\")+$.css(this,\"overflow-y\")+$.css(this,\"overflow-x\"));\n\t\t\t}).eq(0);\n\t\t}\n\n\t\treturn (/fixed/).test(this.css(\"position\")) || !scrollParent.length ? $(document) : scrollParent;\n\t},\n\n\tzIndex: function( zIndex ) {\n\t\tif ( zIndex !== undefined ) {\n\t\t\treturn this.css( \"zIndex\", zIndex );\n\t\t}\n\n\t\tif ( this.length ) {\n\t\t\tvar elem = $( this[ 0 ] ), position, value;\n\t\t\twhile ( elem.length && elem[ 0 ] !== document ) {\n\t\t\t\t// Ignore z-index if position is set to a value where z-index is ignored by the browser\n\t\t\t\t// This makes behavior of this function consistent across browsers\n\t\t\t\t// WebKit always returns auto if the element is positioned\n\t\t\t\tposition = elem.css( \"position\" );\n\t\t\t\tif ( position === \"absolute\" || position === \"relative\" || position === \"fixed\" ) {\n\t\t\t\t\t// IE returns 0 when zIndex is not specified\n\t\t\t\t\t// other browsers return a string\n\t\t\t\t\t// we ignore the case of nested elements with an explicit value of 0\n\t\t\t\t\t// <div style=\"z-index: -10;\"><div style=\"z-index: 0;\"></div></div>\n\t\t\t\t\tvalue = parseInt( elem.css( \"zIndex\" ), 10 );\n\t\t\t\t\tif ( !isNaN( value ) && value !== 0 ) {\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telem = elem.parent();\n\t\t\t}\n\t\t}\n\n\t\treturn 0;\n\t},\n\n\tuniqueId: function() {\n\t\treturn this.each(function() {\n\t\t\tif ( !this.id ) {\n\t\t\t\tthis.id = \"ui-id-\" + (++uuid);\n\t\t\t}\n\t\t});\n\t},\n\n\tremoveUniqueId: function() {\n\t\treturn this.each(function() {\n\t\t\tif ( runiqueId.test( this.id ) ) {\n\t\t\t\t$( this ).removeAttr( \"id\" );\n\t\t\t}\n\t\t});\n\t}\n});\n\n// selectors\nfunction focusable( element, isTabIndexNotNaN ) {\n\tvar map, mapName, img,\n\t\tnodeName = element.nodeName.toLowerCase();\n\tif ( \"area\" === nodeName ) {\n\t\tmap = element.parentNode;\n\t\tmapName = map.name;\n\t\tif ( !element.href || !mapName || map.nodeName.toLowerCase() !== \"map\" ) {\n\t\t\treturn false;\n\t\t}\n\t\timg = $( \"img[usemap=#\" + mapName + \"]\" )[0];\n\t\treturn !!img && visible( img );\n\t}\n\treturn ( /input|select|textarea|button|object/.test( nodeName ) ?\n\t\t!element.disabled :\n\t\t\"a\" === nodeName ?\n\t\t\telement.href || isTabIndexNotNaN :\n\t\t\tisTabIndexNotNaN) &&\n\t\t// the element and all of its ancestors must be visible\n\t\tvisible( element );\n}\n\nfunction visible( element ) {\n\treturn $.expr.filters.visible( element ) &&\n\t\t!$( element ).parents().addBack().filter(function() {\n\t\t\treturn $.css( this, \"visibility\" ) === \"hidden\";\n\t\t}).length;\n}\n\n$.extend( $.expr[ \":\" ], {\n\tdata: $.expr.createPseudo ?\n\t\t$.expr.createPseudo(function( dataName ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn !!$.data( elem, dataName );\n\t\t\t};\n\t\t}) :\n\t\t// support: jQuery <1.8\n\t\tfunction( elem, i, match ) {\n\t\t\treturn !!$.data( elem, match[ 3 ] );\n\t\t},\n\n\tfocusable: function( element ) {\n\t\treturn focusable( element, !isNaN( $.attr( element, \"tabindex\" ) ) );\n\t},\n\n\ttabbable: function( element ) {\n\t\tvar tabIndex = $.attr( element, \"tabindex\" ),\n\t\t\tisTabIndexNaN = isNaN( tabIndex );\n\t\treturn ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );\n\t}\n});\n\n// support: jQuery <1.8\nif ( !$( \"<a>\" ).outerWidth( 1 ).jquery ) {\n\t$.each( [ \"Width\", \"Height\" ], function( i, name ) {\n\t\tvar side = name === \"Width\" ? [ \"Left\", \"Right\" ] : [ \"Top\", \"Bottom\" ],\n\t\t\ttype = name.toLowerCase(),\n\t\t\torig = {\n\t\t\t\tinnerWidth: $.fn.innerWidth,\n\t\t\t\tinnerHeight: $.fn.innerHeight,\n\t\t\t\touterWidth: $.fn.outerWidth,\n\t\t\t\touterHeight: $.fn.outerHeight\n\t\t\t};\n\n\t\tfunction reduce( elem, size, border, margin ) {\n\t\t\t$.each( side, function() {\n\t\t\t\tsize -= parseFloat( $.css( elem, \"padding\" + this ) ) || 0;\n\t\t\t\tif ( border ) {\n\t\t\t\t\tsize -= parseFloat( $.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( margin ) {\n\t\t\t\t\tsize -= parseFloat( $.css( elem, \"margin\" + this ) ) || 0;\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn size;\n\t\t}\n\n\t\t$.fn[ \"inner\" + name ] = function( size ) {\n\t\t\tif ( size === undefined ) {\n\t\t\t\treturn orig[ \"inner\" + name ].call( this );\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\t$( this ).css( type, reduce( this, size ) + \"px\" );\n\t\t\t});\n\t\t};\n\n\t\t$.fn[ \"outer\" + name] = function( size, margin ) {\n\t\t\tif ( typeof size !== \"number\" ) {\n\t\t\t\treturn orig[ \"outer\" + name ].call( this, size );\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\t$( this).css( type, reduce( this, size, true, margin ) + \"px\" );\n\t\t\t});\n\t\t};\n\t});\n}\n\n// support: jQuery <1.8\nif ( !$.fn.addBack ) {\n\t$.fn.addBack = function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t};\n}\n\n// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)\nif ( $( \"<a>\" ).data( \"a-b\", \"a\" ).removeData( \"a-b\" ).data( \"a-b\" ) ) {\n\t$.fn.removeData = (function( removeData ) {\n\t\treturn function( key ) {\n\t\t\tif ( arguments.length ) {\n\t\t\t\treturn removeData.call( this, $.camelCase( key ) );\n\t\t\t} else {\n\t\t\t\treturn removeData.call( this );\n\t\t\t}\n\t\t};\n\t})( $.fn.removeData );\n}\n\n\n\n\n\n// deprecated\n$.ui.ie = !!/msie [\\w.]+/.exec( navigator.userAgent.toLowerCase() );\n\n$.support.selectstart = \"onselectstart\" in document.createElement( \"div\" );\n$.fn.extend({\n\tdisableSelection: function() {\n\t\treturn this.bind( ( $.support.selectstart ? \"selectstart\" : \"mousedown\" ) +\n\t\t\t\".ui-disableSelection\", function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t});\n\t},\n\n\tenableSelection: function() {\n\t\treturn this.unbind( \".ui-disableSelection\" );\n\t}\n});\n\n$.extend( $.ui, {\n\t// $.ui.plugin is deprecated. Use $.widget() extensions instead.\n\tplugin: {\n\t\tadd: function( module, option, set ) {\n\t\t\tvar i,\n\t\t\t\tproto = $.ui[ module ].prototype;\n\t\t\tfor ( i in set ) {\n\t\t\t\tproto.plugins[ i ] = proto.plugins[ i ] || [];\n\t\t\t\tproto.plugins[ i ].push( [ option, set[ i ] ] );\n\t\t\t}\n\t\t},\n\t\tcall: function( instance, name, args ) {\n\t\t\tvar i,\n\t\t\t\tset = instance.plugins[ name ];\n\t\t\tif ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfor ( i = 0; i < set.length; i++ ) {\n\t\t\t\tif ( instance.options[ set[ i ][ 0 ] ] ) {\n\t\t\t\t\tset[ i ][ 1 ].apply( instance.element, args );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// only used by resizable\n\thasScroll: function( el, a ) {\n\n\t\t//If overflow is hidden, the element might have extra content, but the user wants to hide it\n\t\tif ( $( el ).css( \"overflow\" ) === \"hidden\") {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar scroll = ( a && a === \"left\" ) ? \"scrollLeft\" : \"scrollTop\",\n\t\t\thas = false;\n\n\t\tif ( el[ scroll ] > 0 ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// TODO: determine which cases actually cause this to happen\n\t\t// if the element doesn't have the scroll set, see if it's possible to\n\t\t// set the scroll\n\t\tel[ scroll ] = 1;\n\t\thas = ( el[ scroll ] > 0 );\n\t\tel[ scroll ] = 0;\n\t\treturn has;\n\t}\n});\n\n})( jQuery );\n(function( $, undefined ) {\n\nvar uuid = 0,\n\tslice = Array.prototype.slice,\n\t_cleanData = $.cleanData;\n$.cleanData = function( elems ) {\n\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\ttry {\n\t\t\t$( elem ).triggerHandler( \"remove\" );\n\t\t// http://bugs.jquery.com/ticket/8235\n\t\t} catch( e ) {}\n\t}\n\t_cleanData( elems );\n};\n\n$.widget = function( name, base, prototype ) {\n\tvar fullName, existingConstructor, constructor, basePrototype,\n\t\t// proxiedPrototype allows the provided prototype to remain unmodified\n\t\t// so that it can be used as a mixin for multiple widgets (#8876)\n\t\tproxiedPrototype = {},\n\t\tnamespace = name.split( \".\" )[ 0 ];\n\n\tname = name.split( \".\" )[ 1 ];\n\tfullName = namespace + \"-\" + name;\n\n\tif ( !prototype ) {\n\t\tprototype = base;\n\t\tbase = $.Widget;\n\t}\n\n\t// create selector for plugin\n\t$.expr[ \":\" ][ fullName.toLowerCase() ] = function( elem ) {\n\t\treturn !!$.data( elem, fullName );\n\t};\n\n\t$[ namespace ] = $[ namespace ] || {};\n\texistingConstructor = $[ namespace ][ name ];\n\tconstructor = $[ namespace ][ name ] = function( options, element ) {\n\t\t// allow instantiation without \"new\" keyword\n\t\tif ( !this._createWidget ) {\n\t\t\treturn new constructor( options, element );\n\t\t}\n\n\t\t// allow instantiation without initializing for simple inheritance\n\t\t// must use \"new\" keyword (the code above always passes args)\n\t\tif ( arguments.length ) {\n\t\t\tthis._createWidget( options, element );\n\t\t}\n\t};\n\t// extend with the existing constructor to carry over any static properties\n\t$.extend( constructor, existingConstructor, {\n\t\tversion: prototype.version,\n\t\t// copy the object used to create the prototype in case we need to\n\t\t// redefine the widget later\n\t\t_proto: $.extend( {}, prototype ),\n\t\t// track widgets that inherit from this widget in case this widget is\n\t\t// redefined after a widget inherits from it\n\t\t_childConstructors: []\n\t});\n\n\tbasePrototype = new base();\n\t// we need to make the options hash a property directly on the new instance\n\t// otherwise we'll modify the options hash on the prototype that we're\n\t// inheriting from\n\tbasePrototype.options = $.widget.extend( {}, basePrototype.options );\n\t$.each( prototype, function( prop, value ) {\n\t\tif ( !$.isFunction( value ) ) {\n\t\t\tproxiedPrototype[ prop ] = value;\n\t\t\treturn;\n\t\t}\n\t\tproxiedPrototype[ prop ] = (function() {\n\t\t\tvar _super = function() {\n\t\t\t\t\treturn base.prototype[ prop ].apply( this, arguments );\n\t\t\t\t},\n\t\t\t\t_superApply = function( args ) {\n\t\t\t\t\treturn base.prototype[ prop ].apply( this, args );\n\t\t\t\t};\n\t\t\treturn function() {\n\t\t\t\tvar __super = this._super,\n\t\t\t\t\t__superApply = this._superApply,\n\t\t\t\t\treturnValue;\n\n\t\t\t\tthis._super = _super;\n\t\t\t\tthis._superApply = _superApply;\n\n\t\t\t\treturnValue = value.apply( this, arguments );\n\n\t\t\t\tthis._super = __super;\n\t\t\t\tthis._superApply = __superApply;\n\n\t\t\t\treturn returnValue;\n\t\t\t};\n\t\t})();\n\t});\n\tconstructor.prototype = $.widget.extend( basePrototype, {\n\t\t// TODO: remove support for widgetEventPrefix\n\t\t// always use the name + a colon as the prefix, e.g., draggable:start\n\t\t// don't prefix for widgets that aren't DOM-based\n\t\twidgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name\n\t}, proxiedPrototype, {\n\t\tconstructor: constructor,\n\t\tnamespace: namespace,\n\t\twidgetName: name,\n\t\twidgetFullName: fullName\n\t});\n\n\t// If this widget is being redefined then we need to find all widgets that\n\t// are inheriting from it and redefine all of them so that they inherit from\n\t// the new version of this widget. We're essentially trying to replace one\n\t// level in the prototype chain.\n\tif ( existingConstructor ) {\n\t\t$.each( existingConstructor._childConstructors, function( i, child ) {\n\t\t\tvar childPrototype = child.prototype;\n\n\t\t\t// redefine the child widget using the same prototype that was\n\t\t\t// originally used, but inherit from the new version of the base\n\t\t\t$.widget( childPrototype.namespace + \".\" + childPrototype.widgetName, constructor, child._proto );\n\t\t});\n\t\t// remove the list of existing child constructors from the old constructor\n\t\t// so the old child constructors can be garbage collected\n\t\tdelete existingConstructor._childConstructors;\n\t} else {\n\t\tbase._childConstructors.push( constructor );\n\t}\n\n\t$.widget.bridge( name, constructor );\n};\n\n$.widget.extend = function( target ) {\n\tvar input = slice.call( arguments, 1 ),\n\t\tinputIndex = 0,\n\t\tinputLength = input.length,\n\t\tkey,\n\t\tvalue;\n\tfor ( ; inputIndex < inputLength; inputIndex++ ) {\n\t\tfor ( key in input[ inputIndex ] ) {\n\t\t\tvalue = input[ inputIndex ][ key ];\n\t\t\tif ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {\n\t\t\t\t// Clone objects\n\t\t\t\tif ( $.isPlainObject( value ) ) {\n\t\t\t\t\ttarget[ key ] = $.isPlainObject( target[ key ] ) ?\n\t\t\t\t\t\t$.widget.extend( {}, target[ key ], value ) :\n\t\t\t\t\t\t// Don't extend strings, arrays, etc. with objects\n\t\t\t\t\t\t$.widget.extend( {}, value );\n\t\t\t\t// Copy everything else by reference\n\t\t\t\t} else {\n\t\t\t\t\ttarget[ key ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn target;\n};\n\n$.widget.bridge = function( name, object ) {\n\tvar fullName = object.prototype.widgetFullName || name;\n\t$.fn[ name ] = function( options ) {\n\t\tvar isMethodCall = typeof options === \"string\",\n\t\t\targs = slice.call( arguments, 1 ),\n\t\t\treturnValue = this;\n\n\t\t// allow multiple hashes to be passed on init\n\t\toptions = !isMethodCall && args.length ?\n\t\t\t$.widget.extend.apply( null, [ options ].concat(args) ) :\n\t\t\toptions;\n\n\t\tif ( isMethodCall ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar methodValue,\n\t\t\t\t\tinstance = $.data( this, fullName );\n\t\t\t\tif ( !instance ) {\n\t\t\t\t\treturn $.error( \"cannot call methods on \" + name + \" prior to initialization; \" +\n\t\t\t\t\t\t\"attempted to call method '\" + options + \"'\" );\n\t\t\t\t}\n\t\t\t\tif ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === \"_\" ) {\n\t\t\t\t\treturn $.error( \"no such method '\" + options + \"' for \" + name + \" widget instance\" );\n\t\t\t\t}\n\t\t\t\tmethodValue = instance[ options ].apply( instance, args );\n\t\t\t\tif ( methodValue !== instance && methodValue !== undefined ) {\n\t\t\t\t\treturnValue = methodValue && methodValue.jquery ?\n\t\t\t\t\t\treturnValue.pushStack( methodValue.get() ) :\n\t\t\t\t\t\tmethodValue;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tthis.each(function() {\n\t\t\t\tvar instance = $.data( this, fullName );\n\t\t\t\tif ( instance ) {\n\t\t\t\t\tinstance.option( options || {} )._init();\n\t\t\t\t} else {\n\t\t\t\t\t$.data( this, fullName, new object( options, this ) );\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn returnValue;\n\t};\n};\n\n$.Widget = function( /* options, element */ ) {};\n$.Widget._childConstructors = [];\n\n$.Widget.prototype = {\n\twidgetName: \"widget\",\n\twidgetEventPrefix: \"\",\n\tdefaultElement: \"<div>\",\n\toptions: {\n\t\tdisabled: false,\n\n\t\t// callbacks\n\t\tcreate: null\n\t},\n\t_createWidget: function( options, element ) {\n\t\telement = $( element || this.defaultElement || this )[ 0 ];\n\t\tthis.element = $( element );\n\t\tthis.uuid = uuid++;\n\t\tthis.eventNamespace = \".\" + this.widgetName + this.uuid;\n\t\tthis.options = $.widget.extend( {},\n\t\t\tthis.options,\n\t\t\tthis._getCreateOptions(),\n\t\t\toptions );\n\n\t\tthis.bindings = $();\n\t\tthis.hoverable = $();\n\t\tthis.focusable = $();\n\n\t\tif ( element !== this ) {\n\t\t\t$.data( element, this.widgetFullName, this );\n\t\t\tthis._on( true, this.element, {\n\t\t\t\tremove: function( event ) {\n\t\t\t\t\tif ( event.target === element ) {\n\t\t\t\t\t\tthis.destroy();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.document = $( element.style ?\n\t\t\t\t// element within the document\n\t\t\t\telement.ownerDocument :\n\t\t\t\t// element is window or document\n\t\t\t\telement.document || element );\n\t\t\tthis.window = $( this.document[0].defaultView || this.document[0].parentWindow );\n\t\t}\n\n\t\tthis._create();\n\t\tthis._trigger( \"create\", null, this._getCreateEventData() );\n\t\tthis._init();\n\t},\n\t_getCreateOptions: $.noop,\n\t_getCreateEventData: $.noop,\n\t_create: $.noop,\n\t_init: $.noop,\n\n\tdestroy: function() {\n\t\tthis._destroy();\n\t\t// we can probably remove the unbind calls in 2.0\n\t\t// all event bindings should go through this._on()\n\t\tthis.element\n\t\t\t.unbind( this.eventNamespace )\n\t\t\t// 1.9 BC for #7810\n\t\t\t// TODO remove dual storage\n\t\t\t.removeData( this.widgetName )\n\t\t\t.removeData( this.widgetFullName )\n\t\t\t// support: jquery <1.6.3\n\t\t\t// http://bugs.jquery.com/ticket/9413\n\t\t\t.removeData( $.camelCase( this.widgetFullName ) );\n\t\tthis.widget()\n\t\t\t.unbind( this.eventNamespace )\n\t\t\t.removeAttr( \"aria-disabled\" )\n\t\t\t.removeClass(\n\t\t\t\tthis.widgetFullName + \"-disabled \" +\n\t\t\t\t\"ui-state-disabled\" );\n\n\t\t// clean up events and states\n\t\tthis.bindings.unbind( this.eventNamespace );\n\t\tthis.hoverable.removeClass( \"ui-state-hover\" );\n\t\tthis.focusable.removeClass( \"ui-state-focus\" );\n\t},\n\t_destroy: $.noop,\n\n\twidget: function() {\n\t\treturn this.element;\n\t},\n\n\toption: function( key, value ) {\n\t\tvar options = key,\n\t\t\tparts,\n\t\t\tcurOption,\n\t\t\ti;\n\n\t\tif ( arguments.length === 0 ) {\n\t\t\t// don't return a reference to the internal hash\n\t\t\treturn $.widget.extend( {}, this.options );\n\t\t}\n\n\t\tif ( typeof key === \"string\" ) {\n\t\t\t// handle nested keys, e.g., \"foo.bar\" => { foo: { bar: ___ } }\n\t\t\toptions = {};\n\t\t\tparts = key.split( \".\" );\n\t\t\tkey = parts.shift();\n\t\t\tif ( parts.length ) {\n\t\t\t\tcurOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );\n\t\t\t\tfor ( i = 0; i < parts.length - 1; i++ ) {\n\t\t\t\t\tcurOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};\n\t\t\t\t\tcurOption = curOption[ parts[ i ] ];\n\t\t\t\t}\n\t\t\t\tkey = parts.pop();\n\t\t\t\tif ( value === undefined ) {\n\t\t\t\t\treturn curOption[ key ] === undefined ? null : curOption[ key ];\n\t\t\t\t}\n\t\t\t\tcurOption[ key ] = value;\n\t\t\t} else {\n\t\t\t\tif ( value === undefined ) {\n\t\t\t\t\treturn this.options[ key ] === undefined ? null : this.options[ key ];\n\t\t\t\t}\n\t\t\t\toptions[ key ] = value;\n\t\t\t}\n\t\t}\n\n\t\tthis._setOptions( options );\n\n\t\treturn this;\n\t},\n\t_setOptions: function( options ) {\n\t\tvar key;\n\n\t\tfor ( key in options ) {\n\t\t\tthis._setOption( key, options[ key ] );\n\t\t}\n\n\t\treturn this;\n\t},\n\t_setOption: function( key, value ) {\n\t\tthis.options[ key ] = value;\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis.widget()\n\t\t\t\t.toggleClass( this.widgetFullName + \"-disabled ui-state-disabled\", !!value )\n\t\t\t\t.attr( \"aria-disabled\", value );\n\t\t\tthis.hoverable.removeClass( \"ui-state-hover\" );\n\t\t\tthis.focusable.removeClass( \"ui-state-focus\" );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tenable: function() {\n\t\treturn this._setOption( \"disabled\", false );\n\t},\n\tdisable: function() {\n\t\treturn this._setOption( \"disabled\", true );\n\t},\n\n\t_on: function( suppressDisabledCheck, element, handlers ) {\n\t\tvar delegateElement,\n\t\t\tinstance = this;\n\n\t\t// no suppressDisabledCheck flag, shuffle arguments\n\t\tif ( typeof suppressDisabledCheck !== \"boolean\" ) {\n\t\t\thandlers = element;\n\t\t\telement = suppressDisabledCheck;\n\t\t\tsuppressDisabledCheck = false;\n\t\t}\n\n\t\t// no element argument, shuffle and use this.element\n\t\tif ( !handlers ) {\n\t\t\thandlers = element;\n\t\t\telement = this.element;\n\t\t\tdelegateElement = this.widget();\n\t\t} else {\n\t\t\t// accept selectors, DOM elements\n\t\t\telement = delegateElement = $( element );\n\t\t\tthis.bindings = this.bindings.add( element );\n\t\t}\n\n\t\t$.each( handlers, function( event, handler ) {\n\t\t\tfunction handlerProxy() {\n\t\t\t\t// allow widgets to customize the disabled handling\n\t\t\t\t// - disabled as an array instead of boolean\n\t\t\t\t// - disabled class as method for disabling individual parts\n\t\t\t\tif ( !suppressDisabledCheck &&\n\t\t\t\t\t\t( instance.options.disabled === true ||\n\t\t\t\t\t\t\t$( this ).hasClass( \"ui-state-disabled\" ) ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t\t.apply( instance, arguments );\n\t\t\t}\n\n\t\t\t// copy the guid so direct unbinding works\n\t\t\tif ( typeof handler !== \"string\" ) {\n\t\t\t\thandlerProxy.guid = handler.guid =\n\t\t\t\t\thandler.guid || handlerProxy.guid || $.guid++;\n\t\t\t}\n\n\t\t\tvar match = event.match( /^(\\w+)\\s*(.*)$/ ),\n\t\t\t\teventName = match[1] + instance.eventNamespace,\n\t\t\t\tselector = match[2];\n\t\t\tif ( selector ) {\n\t\t\t\tdelegateElement.delegate( selector, eventName, handlerProxy );\n\t\t\t} else {\n\t\t\t\telement.bind( eventName, handlerProxy );\n\t\t\t}\n\t\t});\n\t},\n\n\t_off: function( element, eventName ) {\n\t\teventName = (eventName || \"\").split( \" \" ).join( this.eventNamespace + \" \" ) + this.eventNamespace;\n\t\telement.unbind( eventName ).undelegate( eventName );\n\t},\n\n\t_delay: function( handler, delay ) {\n\t\tfunction handlerProxy() {\n\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t.apply( instance, arguments );\n\t\t}\n\t\tvar instance = this;\n\t\treturn setTimeout( handlerProxy, delay || 0 );\n\t},\n\n\t_hoverable: function( element ) {\n\t\tthis.hoverable = this.hoverable.add( element );\n\t\tthis._on( element, {\n\t\t\tmouseenter: function( event ) {\n\t\t\t\t$( event.currentTarget ).addClass( \"ui-state-hover\" );\n\t\t\t},\n\t\t\tmouseleave: function( event ) {\n\t\t\t\t$( event.currentTarget ).removeClass( \"ui-state-hover\" );\n\t\t\t}\n\t\t});\n\t},\n\n\t_focusable: function( element ) {\n\t\tthis.focusable = this.focusable.add( element );\n\t\tthis._on( element, {\n\t\t\tfocusin: function( event ) {\n\t\t\t\t$( event.currentTarget ).addClass( \"ui-state-focus\" );\n\t\t\t},\n\t\t\tfocusout: function( event ) {\n\t\t\t\t$( event.currentTarget ).removeClass( \"ui-state-focus\" );\n\t\t\t}\n\t\t});\n\t},\n\n\t_trigger: function( type, event, data ) {\n\t\tvar prop, orig,\n\t\t\tcallback = this.options[ type ];\n\n\t\tdata = data || {};\n\t\tevent = $.Event( event );\n\t\tevent.type = ( type === this.widgetEventPrefix ?\n\t\t\ttype :\n\t\t\tthis.widgetEventPrefix + type ).toLowerCase();\n\t\t// the original event may come from any element\n\t\t// so we need to reset the target on the new event\n\t\tevent.target = this.element[ 0 ];\n\n\t\t// copy original event properties over to the new event\n\t\torig = event.originalEvent;\n\t\tif ( orig ) {\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tif ( !( prop in event ) ) {\n\t\t\t\t\tevent[ prop ] = orig[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.element.trigger( event, data );\n\t\treturn !( $.isFunction( callback ) &&\n\t\t\tcallback.apply( this.element[0], [ event ].concat( data ) ) === false ||\n\t\t\tevent.isDefaultPrevented() );\n\t}\n};\n\n$.each( { show: \"fadeIn\", hide: \"fadeOut\" }, function( method, defaultEffect ) {\n\t$.Widget.prototype[ \"_\" + method ] = function( element, options, callback ) {\n\t\tif ( typeof options === \"string\" ) {\n\t\t\toptions = { effect: options };\n\t\t}\n\t\tvar hasOptions,\n\t\t\teffectName = !options ?\n\t\t\t\tmethod :\n\t\t\t\toptions === true || typeof options === \"number\" ?\n\t\t\t\t\tdefaultEffect :\n\t\t\t\t\toptions.effect || defaultEffect;\n\t\toptions = options || {};\n\t\tif ( typeof options === \"number\" ) {\n\t\t\toptions = { duration: options };\n\t\t}\n\t\thasOptions = !$.isEmptyObject( options );\n\t\toptions.complete = callback;\n\t\tif ( options.delay ) {\n\t\t\telement.delay( options.delay );\n\t\t}\n\t\tif ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {\n\t\t\telement[ method ]( options );\n\t\t} else if ( effectName !== method && element[ effectName ] ) {\n\t\t\telement[ effectName ]( options.duration, options.easing, callback );\n\t\t} else {\n\t\t\telement.queue(function( next ) {\n\t\t\t\t$( this )[ method ]();\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback.call( element[ 0 ] );\n\t\t\t\t}\n\t\t\t\tnext();\n\t\t\t});\n\t\t}\n\t};\n});\n\n})( jQuery );\n(function( $, undefined ) {\n\nvar mouseHandled = false;\n$( document ).mouseup( function() {\n\tmouseHandled = false;\n});\n\n$.widget(\"ui.mouse\", {\n\tversion: \"1.10.3\",\n\toptions: {\n\t\tcancel: \"input,textarea,button,select,option\",\n\t\tdistance: 1,\n\t\tdelay: 0\n\t},\n\t_mouseInit: function() {\n\t\tvar that = this;\n\n\t\tthis.element\n\t\t\t.bind(\"mousedown.\"+this.widgetName, function(event) {\n\t\t\t\treturn that._mouseDown(event);\n\t\t\t})\n\t\t\t.bind(\"click.\"+this.widgetName, function(event) {\n\t\t\t\tif (true === $.data(event.target, that.widgetName + \".preventClickEvent\")) {\n\t\t\t\t\t$.removeData(event.target, that.widgetName + \".preventClickEvent\");\n\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\n\t\tthis.started = false;\n\t},\n\n\t// TODO: make sure destroying one instance of mouse doesn't mess with\n\t// other instances of mouse\n\t_mouseDestroy: function() {\n\t\tthis.element.unbind(\".\"+this.widgetName);\n\t\tif ( this._mouseMoveDelegate ) {\n\t\t\t$(document)\n\t\t\t\t.unbind(\"mousemove.\"+this.widgetName, this._mouseMoveDelegate)\n\t\t\t\t.unbind(\"mouseup.\"+this.widgetName, this._mouseUpDelegate);\n\t\t}\n\t},\n\n\t_mouseDown: function(event) {\n\t\t// don't let more than one widget handle mouseStart\n\t\tif( mouseHandled ) { return; }\n\n\t\t// we may have missed mouseup (out of window)\n\t\t(this._mouseStarted && this._mouseUp(event));\n\n\t\tthis._mouseDownEvent = event;\n\n\t\tvar that = this,\n\t\t\tbtnIsLeft = (event.which === 1),\n\t\t\t// event.target.nodeName works around a bug in IE 8 with\n\t\t\t// disabled inputs (#7620)\n\t\t\telIsCancel = (typeof this.options.cancel === \"string\" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);\n\t\tif (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tthis.mouseDelayMet = !this.options.delay;\n\t\tif (!this.mouseDelayMet) {\n\t\t\tthis._mouseDelayTimer = setTimeout(function() {\n\t\t\t\tthat.mouseDelayMet = true;\n\t\t\t}, this.options.delay);\n\t\t}\n\n\t\tif (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {\n\t\t\tthis._mouseStarted = (this._mouseStart(event) !== false);\n\t\t\tif (!this._mouseStarted) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// Click event may never have fired (Gecko & Opera)\n\t\tif (true === $.data(event.target, this.widgetName + \".preventClickEvent\")) {\n\t\t\t$.removeData(event.target, this.widgetName + \".preventClickEvent\");\n\t\t}\n\n\t\t// these delegates are required to keep context\n\t\tthis._mouseMoveDelegate = function(event) {\n\t\t\treturn that._mouseMove(event);\n\t\t};\n\t\tthis._mouseUpDelegate = function(event) {\n\t\t\treturn that._mouseUp(event);\n\t\t};\n\t\t$(document)\n\t\t\t.bind(\"mousemove.\"+this.widgetName, this._mouseMoveDelegate)\n\t\t\t.bind(\"mouseup.\"+this.widgetName, this._mouseUpDelegate);\n\n\t\tevent.preventDefault();\n\n\t\tmouseHandled = true;\n\t\treturn true;\n\t},\n\n\t_mouseMove: function(event) {\n\t\t// IE mouseup check - mouseup happened when mouse was out of window\n\t\tif ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {\n\t\t\treturn this._mouseUp(event);\n\t\t}\n\n\t\tif (this._mouseStarted) {\n\t\t\tthis._mouseDrag(event);\n\t\t\treturn event.preventDefault();\n\t\t}\n\n\t\tif (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {\n\t\t\tthis._mouseStarted =\n\t\t\t\t(this._mouseStart(this._mouseDownEvent, event) !== false);\n\t\t\t(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));\n\t\t}\n\n\t\treturn !this._mouseStarted;\n\t},\n\n\t_mouseUp: function(event) {\n\t\t$(document)\n\t\t\t.unbind(\"mousemove.\"+this.widgetName, this._mouseMoveDelegate)\n\t\t\t.unbind(\"mouseup.\"+this.widgetName, this._mouseUpDelegate);\n\n\t\tif (this._mouseStarted) {\n\t\t\tthis._mouseStarted = false;\n\n\t\t\tif (event.target === this._mouseDownEvent.target) {\n\t\t\t\t$.data(event.target, this.widgetName + \".preventClickEvent\", true);\n\t\t\t}\n\n\t\t\tthis._mouseStop(event);\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_mouseDistanceMet: function(event) {\n\t\treturn (Math.max(\n\t\t\t\tMath.abs(this._mouseDownEvent.pageX - event.pageX),\n\t\t\t\tMath.abs(this._mouseDownEvent.pageY - event.pageY)\n\t\t\t) >= this.options.distance\n\t\t);\n\t},\n\n\t_mouseDelayMet: function(/* event */) {\n\t\treturn this.mouseDelayMet;\n\t},\n\n\t// These are placeholder methods, to be overriden by extending plugin\n\t_mouseStart: function(/* event */) {},\n\t_mouseDrag: function(/* event */) {},\n\t_mouseStop: function(/* event */) {},\n\t_mouseCapture: function(/* event */) { return true; }\n});\n\n})(jQuery);\n(function( $, undefined ) {\n\n/*jshint loopfunc: true */\n\nfunction isOverAxis( x, reference, size ) {\n\treturn ( x > reference ) && ( x < ( reference + size ) );\n}\n\nfunction isFloating(item) {\n\treturn (/left|right/).test(item.css(\"float\")) || (/inline|table-cell/).test(item.css(\"display\"));\n}\n\n$.widget(\"ui.sortable\", $.ui.mouse, {\n\tversion: \"1.10.3\",\n\twidgetEventPrefix: \"sort\",\n\tready: false,\n\toptions: {\n\t\tappendTo: \"parent\",\n\t\taxis: false,\n\t\tconnectWith: false,\n\t\tcontainment: false,\n\t\tcursor: \"auto\",\n\t\tcursorAt: false,\n\t\tdropOnEmpty: true,\n\t\tforcePlaceholderSize: false,\n\t\tforceHelperSize: false,\n\t\tgrid: false,\n\t\thandle: false,\n\t\thelper: \"original\",\n\t\titems: \"> *\",\n\t\topacity: false,\n\t\tplaceholder: false,\n\t\trevert: false,\n\t\tscroll: true,\n\t\tscrollSensitivity: 20,\n\t\tscrollSpeed: 20,\n\t\tscope: \"default\",\n\t\ttolerance: \"intersect\",\n\t\tzIndex: 1000,\n\n\t\t// callbacks\n\t\tactivate: null,\n\t\tbeforeStop: null,\n\t\tchange: null,\n\t\tdeactivate: null,\n\t\tout: null,\n\t\tover: null,\n\t\treceive: null,\n\t\tremove: null,\n\t\tsort: null,\n\t\tstart: null,\n\t\tstop: null,\n\t\tupdate: null\n\t},\n\t_create: function() {\n\n\t\tvar o = this.options;\n\t\tthis.containerCache = {};\n\t\tthis.element.addClass(\"ui-sortable\");\n\n\t\t//Get the items\n\t\tthis.refresh();\n\n\t\t//Let's determine if the items are being displayed horizontally\n\t\tthis.floating = this.items.length ? o.axis === \"x\" || isFloating(this.items[0].item) : false;\n\n\t\t//Let's determine the parent's offset\n\t\tthis.offset = this.element.offset();\n\n\t\t//Initialize mouse events for interaction\n\t\tthis._mouseInit();\n\n\t\t//We're ready to go\n\t\tthis.ready = true;\n\n\t},\n\n\t_destroy: function() {\n\t\tthis.element\n\t\t\t.removeClass(\"ui-sortable ui-sortable-disabled\");\n\t\tthis._mouseDestroy();\n\n\t\tfor ( var i = this.items.length - 1; i >= 0; i-- ) {\n\t\t\tthis.items[i].item.removeData(this.widgetName + \"-item\");\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_setOption: function(key, value){\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis.options[ key ] = value;\n\n\t\t\tthis.widget().toggleClass( \"ui-sortable-disabled\", !!value );\n\t\t} else {\n\t\t\t// Don't call widget base _setOption for disable as it adds ui-state-disabled class\n\t\t\t$.Widget.prototype._setOption.apply(this, arguments);\n\t\t}\n\t},\n\n\t_mouseCapture: function(event, overrideHandle) {\n\t\tvar currentItem = null,\n\t\t\tvalidHandle = false,\n\t\t\tthat = this;\n\n\t\tif (this.reverting) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif(this.options.disabled || this.options.type === \"static\") {\n\t\t\treturn false;\n\t\t}\n\n\t\t//We have to refresh the items data once first\n\t\tthis._refreshItems(event);\n\n\t\t//Find out if the clicked node (or one of its parents) is a actual item in this.items\n\t\t$(event.target).parents().each(function() {\n\t\t\tif($.data(this, that.widgetName + \"-item\") === that) {\n\t\t\t\tcurrentItem = $(this);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tif($.data(event.target, that.widgetName + \"-item\") === that) {\n\t\t\tcurrentItem = $(event.target);\n\t\t}\n\n\t\tif(!currentItem) {\n\t\t\treturn false;\n\t\t}\n\t\tif(this.options.handle && !overrideHandle) {\n\t\t\t$(this.options.handle, currentItem).find(\"*\").addBack().each(function() {\n\t\t\t\tif(this === event.target) {\n\t\t\t\t\tvalidHandle = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\tif(!validHandle) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.currentItem = currentItem;\n\t\tthis._removeCurrentsFromItems();\n\t\treturn true;\n\n\t},\n\n\t_mouseStart: function(event, overrideHandle, noActivation) {\n\n\t\tvar i, body,\n\t\t\to = this.options;\n\n\t\tthis.currentContainer = this;\n\n\t\t//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture\n\t\tthis.refreshPositions();\n\n\t\t//Create and append the visible helper\n\t\tthis.helper = this._createHelper(event);\n\n\t\t//Cache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t/*\n\t\t * - Position generation -\n\t\t * This block generates everything position related - it's the core of draggables.\n\t\t */\n\n\t\t//Cache the margins of the original element\n\t\tthis._cacheMargins();\n\n\t\t//Get the next scrolling parent\n\t\tthis.scrollParent = this.helper.scrollParent();\n\n\t\t//The element's absolute position on the page minus margins\n\t\tthis.offset = this.currentItem.offset();\n\t\tthis.offset = {\n\t\t\ttop: this.offset.top - this.margins.top,\n\t\t\tleft: this.offset.left - this.margins.left\n\t\t};\n\n\t\t$.extend(this.offset, {\n\t\t\tclick: { //Where the click happened, relative to the element\n\t\t\t\tleft: event.pageX - this.offset.left,\n\t\t\t\ttop: event.pageY - this.offset.top\n\t\t\t},\n\t\t\tparent: this._getParentOffset(),\n\t\t\trelative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper\n\t\t});\n\n\t\t// Only after we got the offset, we can change the helper's position to absolute\n\t\t// TODO: Still need to figure out a way to make relative sorting possible\n\t\tthis.helper.css(\"position\", \"absolute\");\n\t\tthis.cssPosition = this.helper.css(\"position\");\n\n\t\t//Generate the original position\n\t\tthis.originalPosition = this._generatePosition(event);\n\t\tthis.originalPageX = event.pageX;\n\t\tthis.originalPageY = event.pageY;\n\n\t\t//Adjust the mouse offset relative to the helper if \"cursorAt\" is supplied\n\t\t(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));\n\n\t\t//Cache the former DOM position\n\t\tthis.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };\n\n\t\t//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way\n\t\tif(this.helper[0] !== this.currentItem[0]) {\n\t\t\tthis.currentItem.hide();\n\t\t}\n\n\t\t//Create the placeholder\n\t\tthis._createPlaceholder();\n\n\t\t//Set a containment if given in the options\n\t\tif(o.containment) {\n\t\t\tthis._setContainment();\n\t\t}\n\n\t\tif( o.cursor && o.cursor !== \"auto\" ) { // cursor option\n\t\t\tbody = this.document.find( \"body\" );\n\n\t\t\t// support: IE\n\t\t\tthis.storedCursor = body.css( \"cursor\" );\n\t\t\tbody.css( \"cursor\", o.cursor );\n\n\t\t\tthis.storedStylesheet = $( \"<style>*{ cursor: \"+o.cursor+\" !important; }</style>\" ).appendTo( body );\n\t\t}\n\n\t\tif(o.opacity) { // opacity option\n\t\t\tif (this.helper.css(\"opacity\")) {\n\t\t\t\tthis._storedOpacity = this.helper.css(\"opacity\");\n\t\t\t}\n\t\t\tthis.helper.css(\"opacity\", o.opacity);\n\t\t}\n\n\t\tif(o.zIndex) { // zIndex option\n\t\t\tif (this.helper.css(\"zIndex\")) {\n\t\t\t\tthis._storedZIndex = this.helper.css(\"zIndex\");\n\t\t\t}\n\t\t\tthis.helper.css(\"zIndex\", o.zIndex);\n\t\t}\n\n\t\t//Prepare scrolling\n\t\tif(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== \"HTML\") {\n\t\t\tthis.overflowOffset = this.scrollParent.offset();\n\t\t}\n\n\t\t//Call callbacks\n\t\tthis._trigger(\"start\", event, this._uiHash());\n\n\t\t//Recache the helper size\n\t\tif(!this._preserveHelperProportions) {\n\t\t\tthis._cacheHelperProportions();\n\t\t}\n\n\n\t\t//Post \"activate\" events to possible containers\n\t\tif( !noActivation ) {\n\t\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\t\tthis.containers[ i ]._trigger( \"activate\", event, this._uiHash( this ) );\n\t\t\t}\n\t\t}\n\n\t\t//Prepare possible droppables\n\t\tif($.ui.ddmanager) {\n\t\t\t$.ui.ddmanager.current = this;\n\t\t}\n\n\t\tif ($.ui.ddmanager && !o.dropBehaviour) {\n\t\t\t$.ui.ddmanager.prepareOffsets(this, event);\n\t\t}\n\n\t\tthis.dragging = true;\n\n\t\tthis.helper.addClass(\"ui-sortable-helper\");\n\t\tthis._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position\n\t\treturn true;\n\n\t},\n\n\t_mouseDrag: function(event) {\n\t\tvar i, item, itemElement, intersection,\n\t\t\to = this.options,\n\t\t\tscrolled = false;\n\n\t\t//Compute the helpers position\n\t\tthis.position = this._generatePosition(event);\n\t\tthis.positionAbs = this._convertPositionTo(\"absolute\");\n\n\t\tif (!this.lastPositionAbs) {\n\t\t\tthis.lastPositionAbs = this.positionAbs;\n\t\t}\n\n\t\t//Do scrolling\n\t\tif(this.options.scroll) {\n\t\t\tif(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== \"HTML\") {\n\n\t\t\t\tif((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {\n\t\t\t\t\tthis.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;\n\t\t\t\t} else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {\n\t\t\t\t\tthis.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;\n\t\t\t\t}\n\n\t\t\t\tif((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {\n\t\t\t\t\tthis.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;\n\t\t\t\t} else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {\n\t\t\t\t\tthis.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {\n\t\t\t\t\tscrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);\n\t\t\t\t} else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {\n\t\t\t\t\tscrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);\n\t\t\t\t}\n\n\t\t\t\tif(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {\n\t\t\t\t\tscrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);\n\t\t\t\t} else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {\n\t\t\t\t\tscrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {\n\t\t\t\t$.ui.ddmanager.prepareOffsets(this, event);\n\t\t\t}\n\t\t}\n\n\t\t//Regenerate the absolute position used for position checks\n\t\tthis.positionAbs = this._convertPositionTo(\"absolute\");\n\n\t\t//Set the helper position\n\t\tif(!this.options.axis || this.options.axis !== \"y\") {\n\t\t\tthis.helper[0].style.left = this.position.left+\"px\";\n\t\t}\n\t\tif(!this.options.axis || this.options.axis !== \"x\") {\n\t\t\tthis.helper[0].style.top = this.position.top+\"px\";\n\t\t}\n\n\t\t//Rearrange\n\t\tfor (i = this.items.length - 1; i >= 0; i--) {\n\n\t\t\t//Cache variables and intersection, continue if no intersection\n\t\t\titem = this.items[i];\n\t\t\titemElement = item.item[0];\n\t\t\tintersection = this._intersectsWithPointer(item);\n\t\t\tif (!intersection) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Only put the placeholder inside the current Container, skip all\n\t\t\t// items form other containers. This works because when moving\n\t\t\t// an item from one container to another the\n\t\t\t// currentContainer is switched before the placeholder is moved.\n\t\t\t//\n\t\t\t// Without this moving items in \"sub-sortables\" can cause the placeholder to jitter\n\t\t\t// beetween the outer and inner container.\n\t\t\tif (item.instance !== this.currentContainer) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// cannot intersect with itself\n\t\t\t// no useless actions that have been done before\n\t\t\t// no action if the item moved is the parent of the item checked\n\t\t\tif (itemElement !== this.currentItem[0] &&\n\t\t\t\tthis.placeholder[intersection === 1 ? \"next\" : \"prev\"]()[0] !== itemElement &&\n\t\t\t\t!$.contains(this.placeholder[0], itemElement) &&\n\t\t\t\t(this.options.type === \"semi-dynamic\" ? !$.contains(this.element[0], itemElement) : true)\n\t\t\t) {\n\n\t\t\t\tthis.direction = intersection === 1 ? \"down\" : \"up\";\n\n\t\t\t\tif (this.options.tolerance === \"pointer\" || this._intersectsWithSides(item)) {\n\t\t\t\t\tthis._rearrange(event, item);\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis._trigger(\"change\", event, this._uiHash());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//Post events to containers\n\t\tthis._contactContainers(event);\n\n\t\t//Interconnect with droppables\n\t\tif($.ui.ddmanager) {\n\t\t\t$.ui.ddmanager.drag(this, event);\n\t\t}\n\n\t\t//Call callbacks\n\t\tthis._trigger(\"sort\", event, this._uiHash());\n\n\t\tthis.lastPositionAbs = this.positionAbs;\n\t\treturn false;\n\n\t},\n\n\t_mouseStop: function(event, noPropagation) {\n\n\t\tif(!event) {\n\t\t\treturn;\n\t\t}\n\n\t\t//If we are using droppables, inform the manager about the drop\n\t\tif ($.ui.ddmanager && !this.options.dropBehaviour) {\n\t\t\t$.ui.ddmanager.drop(this, event);\n\t\t}\n\n\t\tif(this.options.revert) {\n\t\t\tvar that = this,\n\t\t\t\tcur = this.placeholder.offset(),\n\t\t\t\taxis = this.options.axis,\n\t\t\t\tanimation = {};\n\n\t\t\tif ( !axis || axis === \"x\" ) {\n\t\t\t\tanimation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);\n\t\t\t}\n\t\t\tif ( !axis || axis === \"y\" ) {\n\t\t\t\tanimation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);\n\t\t\t}\n\t\t\tthis.reverting = true;\n\t\t\t$(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {\n\t\t\t\tthat._clear(event);\n\t\t\t});\n\t\t} else {\n\t\t\tthis._clear(event, noPropagation);\n\t\t}\n\n\t\treturn false;\n\n\t},\n\n\tcancel: function() {\n\n\t\tif(this.dragging) {\n\n\t\t\tthis._mouseUp({ target: null });\n\n\t\t\tif(this.options.helper === \"original\") {\n\t\t\t\tthis.currentItem.css(this._storedCSS).removeClass(\"ui-sortable-helper\");\n\t\t\t} else {\n\t\t\t\tthis.currentItem.show();\n\t\t\t}\n\n\t\t\t//Post deactivating events to containers\n\t\t\tfor (var i = this.containers.length - 1; i >= 0; i--){\n\t\t\t\tthis.containers[i]._trigger(\"deactivate\", null, this._uiHash(this));\n\t\t\t\tif(this.containers[i].containerCache.over) {\n\t\t\t\t\tthis.containers[i]._trigger(\"out\", null, this._uiHash(this));\n\t\t\t\t\tthis.containers[i].containerCache.over = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tif (this.placeholder) {\n\t\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!\n\t\t\tif(this.placeholder[0].parentNode) {\n\t\t\t\tthis.placeholder[0].parentNode.removeChild(this.placeholder[0]);\n\t\t\t}\n\t\t\tif(this.options.helper !== \"original\" && this.helper && this.helper[0].parentNode) {\n\t\t\t\tthis.helper.remove();\n\t\t\t}\n\n\t\t\t$.extend(this, {\n\t\t\t\thelper: null,\n\t\t\t\tdragging: false,\n\t\t\t\treverting: false,\n\t\t\t\t_noFinalSort: null\n\t\t\t});\n\n\t\t\tif(this.domPosition.prev) {\n\t\t\t\t$(this.domPosition.prev).after(this.currentItem);\n\t\t\t} else {\n\t\t\t\t$(this.domPosition.parent).prepend(this.currentItem);\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tserialize: function(o) {\n\n\t\tvar items = this._getItemsAsjQuery(o && o.connected),\n\t\t\tstr = [];\n\t\to = o || {};\n\n\t\t$(items).each(function() {\n\t\t\tvar res = ($(o.item || this).attr(o.attribute || \"id\") || \"\").match(o.expression || (/(.+)[\\-=_](.+)/));\n\t\t\tif (res) {\n\t\t\t\tstr.push((o.key || res[1]+\"[]\")+\"=\"+(o.key && o.expression ? res[1] : res[2]));\n\t\t\t}\n\t\t});\n\n\t\tif(!str.length && o.key) {\n\t\t\tstr.push(o.key + \"=\");\n\t\t}\n\n\t\treturn str.join(\"&\");\n\n\t},\n\n\ttoArray: function(o) {\n\n\t\tvar items = this._getItemsAsjQuery(o && o.connected),\n\t\t\tret = [];\n\n\t\to = o || {};\n\n\t\titems.each(function() { ret.push($(o.item || this).attr(o.attribute || \"id\") || \"\"); });\n\t\treturn ret;\n\n\t},\n\n\t/* Be careful with the following core functions */\n\t_intersectsWith: function(item) {\n\n\t\tvar x1 = this.positionAbs.left,\n\t\t\tx2 = x1 + this.helperProportions.width,\n\t\t\ty1 = this.positionAbs.top,\n\t\t\ty2 = y1 + this.helperProportions.height,\n\t\t\tl = item.left,\n\t\t\tr = l + item.width,\n\t\t\tt = item.top,\n\t\t\tb = t + item.height,\n\t\t\tdyClick = this.offset.click.top,\n\t\t\tdxClick = this.offset.click.left,\n\t\t\tisOverElementHeight = ( this.options.axis === \"x\" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),\n\t\t\tisOverElementWidth = ( this.options.axis === \"y\" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),\n\t\t\tisOverElement = isOverElementHeight && isOverElementWidth;\n\n\t\tif ( this.options.tolerance === \"pointer\" ||\n\t\t\tthis.options.forcePointerForContainers ||\n\t\t\t(this.options.tolerance !== \"pointer\" && this.helperProportions[this.floating ? \"width\" : \"height\"] > item[this.floating ? \"width\" : \"height\"])\n\t\t) {\n\t\t\treturn isOverElement;\n\t\t} else {\n\n\t\t\treturn (l < x1 + (this.helperProportions.width / 2) && // Right Half\n\t\t\t\tx2 - (this.helperProportions.width / 2) < r && // Left Half\n\t\t\t\tt < y1 + (this.helperProportions.height / 2) && // Bottom Half\n\t\t\t\ty2 - (this.helperProportions.height / 2) < b ); // Top Half\n\n\t\t}\n\t},\n\n\t_intersectsWithPointer: function(item) {\n\n\t\tvar isOverElementHeight = (this.options.axis === \"x\") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),\n\t\t\tisOverElementWidth = (this.options.axis === \"y\") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),\n\t\t\tisOverElement = isOverElementHeight && isOverElementWidth,\n\t\t\tverticalDirection = this._getDragVerticalDirection(),\n\t\t\thorizontalDirection = this._getDragHorizontalDirection();\n\n\t\tif (!isOverElement) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.floating ?\n\t\t\t( ((horizontalDirection && horizontalDirection === \"right\") || verticalDirection === \"down\") ? 2 : 1 )\n\t\t\t: ( verticalDirection && (verticalDirection === \"down\" ? 2 : 1) );\n\n\t},\n\n\t_intersectsWithSides: function(item) {\n\n\t\tvar isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),\n\t\t\tisOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),\n\t\t\tverticalDirection = this._getDragVerticalDirection(),\n\t\t\thorizontalDirection = this._getDragHorizontalDirection();\n\n\t\tif (this.floating && horizontalDirection) {\n\t\t\treturn ((horizontalDirection === \"right\" && isOverRightHalf) || (horizontalDirection === \"left\" && !isOverRightHalf));\n\t\t} else {\n\t\t\treturn verticalDirection && ((verticalDirection === \"down\" && isOverBottomHalf) || (verticalDirection === \"up\" && !isOverBottomHalf));\n\t\t}\n\n\t},\n\n\t_getDragVerticalDirection: function() {\n\t\tvar delta = this.positionAbs.top - this.lastPositionAbs.top;\n\t\treturn delta !== 0 && (delta > 0 ? \"down\" : \"up\");\n\t},\n\n\t_getDragHorizontalDirection: function() {\n\t\tvar delta = this.positionAbs.left - this.lastPositionAbs.left;\n\t\treturn delta !== 0 && (delta > 0 ? \"right\" : \"left\");\n\t},\n\n\trefresh: function(event) {\n\t\tthis._refreshItems(event);\n\t\tthis.refreshPositions();\n\t\treturn this;\n\t},\n\n\t_connectWith: function() {\n\t\tvar options = this.options;\n\t\treturn options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;\n\t},\n\n\t_getItemsAsjQuery: function(connected) {\n\n\t\tvar i, j, cur, inst,\n\t\t\titems = [],\n\t\t\tqueries = [],\n\t\t\tconnectWith = this._connectWith();\n\n\t\tif(connectWith && connected) {\n\t\t\tfor (i = connectWith.length - 1; i >= 0; i--){\n\t\t\t\tcur = $(connectWith[i]);\n\t\t\t\tfor ( j = cur.length - 1; j >= 0; j--){\n\t\t\t\t\tinst = $.data(cur[j], this.widgetFullName);\n\t\t\t\t\tif(inst && inst !== this && !inst.options.disabled) {\n\t\t\t\t\t\tqueries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(\".ui-sortable-helper\").not(\".ui-sortable-placeholder\"), inst]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tqueries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(\".ui-sortable-helper\").not(\".ui-sortable-placeholder\"), this]);\n\n\t\tfor (i = queries.length - 1; i >= 0; i--){\n\t\t\tqueries[i][0].each(function() {\n\t\t\t\titems.push(this);\n\t\t\t});\n\t\t}\n\n\t\treturn $(items);\n\n\t},\n\n\t_removeCurrentsFromItems: function() {\n\n\t\tvar list = this.currentItem.find(\":data(\" + this.widgetName + \"-item)\");\n\n\t\tthis.items = $.grep(this.items, function (item) {\n\t\t\tfor (var j=0; j < list.length; j++) {\n\t\t\t\tif(list[j] === item.item[0]) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t});\n\n\t},\n\n\t_refreshItems: function(event) {\n\n\t\tthis.items = [];\n\t\tthis.containers = [this];\n\n\t\tvar i, j, cur, inst, targetData, _queries, item, queriesLength,\n\t\t\titems = this.items,\n\t\t\tqueries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],\n\t\t\tconnectWith = this._connectWith();\n\n\t\tif(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down\n\t\t\tfor (i = connectWith.length - 1; i >= 0; i--){\n\t\t\t\tcur = $(connectWith[i]);\n\t\t\t\tfor (j = cur.length - 1; j >= 0; j--){\n\t\t\t\t\tinst = $.data(cur[j], this.widgetFullName);\n\t\t\t\t\tif(inst && inst !== this && !inst.options.disabled) {\n\t\t\t\t\t\tqueries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);\n\t\t\t\t\t\tthis.containers.push(inst);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (i = queries.length - 1; i >= 0; i--) {\n\t\t\ttargetData = queries[i][1];\n\t\t\t_queries = queries[i][0];\n\n\t\t\tfor (j=0, queriesLength = _queries.length; j < queriesLength; j++) {\n\t\t\t\titem = $(_queries[j]);\n\n\t\t\t\titem.data(this.widgetName + \"-item\", targetData); // Data for target checking (mouse manager)\n\n\t\t\t\titems.push({\n\t\t\t\t\titem: item,\n\t\t\t\t\tinstance: targetData,\n\t\t\t\t\twidth: 0, height: 0,\n\t\t\t\t\tleft: 0, top: 0\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t},\n\n\trefreshPositions: function(fast) {\n\n\t\t//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change\n\t\tif(this.offsetParent && this.helper) {\n\t\t\tthis.offset.parent = this._getParentOffset();\n\t\t}\n\n\t\tvar i, item, t, p;\n\n\t\tfor (i = this.items.length - 1; i >= 0; i--){\n\t\t\titem = this.items[i];\n\n\t\t\t//We ignore calculating positions of all connected containers when we're not over them\n\t\t\tif(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tt = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;\n\n\t\t\tif (!fast) {\n\t\t\t\titem.width = t.outerWidth();\n\t\t\t\titem.height = t.outerHeight();\n\t\t\t}\n\n\t\t\tp = t.offset();\n\t\t\titem.left = p.left;\n\t\t\titem.top = p.top;\n\t\t}\n\n\t\tif(this.options.custom && this.options.custom.refreshContainers) {\n\t\t\tthis.options.custom.refreshContainers.call(this);\n\t\t} else {\n\t\t\tfor (i = this.containers.length - 1; i >= 0; i--){\n\t\t\t\tp = this.containers[i].element.offset();\n\t\t\t\tthis.containers[i].containerCache.left = p.left;\n\t\t\t\tthis.containers[i].containerCache.top = p.top;\n\t\t\t\tthis.containers[i].containerCache.width\t= this.containers[i].element.outerWidth();\n\t\t\t\tthis.containers[i].containerCache.height = this.containers[i].element.outerHeight();\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_createPlaceholder: function(that) {\n\t\tthat = that || this;\n\t\tvar className,\n\t\t\to = that.options;\n\n\t\tif(!o.placeholder || o.placeholder.constructor === String) {\n\t\t\tclassName = o.placeholder;\n\t\t\to.placeholder = {\n\t\t\t\telement: function() {\n\n\t\t\t\t\tvar nodeName = that.currentItem[0].nodeName.toLowerCase(),\n\t\t\t\t\t\telement = $( \"<\" + nodeName + \">\", that.document[0] )\n\t\t\t\t\t\t\t.addClass(className || that.currentItem[0].className+\" ui-sortable-placeholder\")\n\t\t\t\t\t\t\t.removeClass(\"ui-sortable-helper\");\n\n\t\t\t\t\tif ( nodeName === \"tr\" ) {\n\t\t\t\t\t\tthat.currentItem.children().each(function() {\n\t\t\t\t\t\t\t$( \"<td>&#160;</td>\", that.document[0] )\n\t\t\t\t\t\t\t\t.attr( \"colspan\", $( this ).attr( \"colspan\" ) || 1 )\n\t\t\t\t\t\t\t\t.appendTo( element );\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if ( nodeName === \"img\" ) {\n\t\t\t\t\t\telement.attr( \"src\", that.currentItem.attr( \"src\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !className ) {\n\t\t\t\t\t\telement.css( \"visibility\", \"hidden\" );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn element;\n\t\t\t\t},\n\t\t\t\tupdate: function(container, p) {\n\n\t\t\t\t\t// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that\n\t\t\t\t\t// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified\n\t\t\t\t\tif(className && !o.forcePlaceholderSize) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item\n\t\t\t\t\tif(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css(\"paddingTop\")||0, 10) - parseInt(that.currentItem.css(\"paddingBottom\")||0, 10)); }\n\t\t\t\t\tif(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css(\"paddingLeft\")||0, 10) - parseInt(that.currentItem.css(\"paddingRight\")||0, 10)); }\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t//Create the placeholder\n\t\tthat.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));\n\n\t\t//Append it after the actual current item\n\t\tthat.currentItem.after(that.placeholder);\n\n\t\t//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)\n\t\to.placeholder.update(that, that.placeholder);\n\n\t},\n\n\t_contactContainers: function(event) {\n\t\tvar i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating,\n\t\t\tinnermostContainer = null,\n\t\t\tinnermostIndex = null;\n\n\t\t// get innermost container that intersects with item\n\t\tfor (i = this.containers.length - 1; i >= 0; i--) {\n\n\t\t\t// never consider a container that's located within the item itself\n\t\t\tif($.contains(this.currentItem[0], this.containers[i].element[0])) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif(this._intersectsWith(this.containers[i].containerCache)) {\n\n\t\t\t\t// if we've already found a container and it's more \"inner\" than this, then continue\n\t\t\t\tif(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tinnermostContainer = this.containers[i];\n\t\t\t\tinnermostIndex = i;\n\n\t\t\t} else {\n\t\t\t\t// container doesn't intersect. trigger \"out\" event if necessary\n\t\t\t\tif(this.containers[i].containerCache.over) {\n\t\t\t\t\tthis.containers[i]._trigger(\"out\", event, this._uiHash(this));\n\t\t\t\t\tthis.containers[i].containerCache.over = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\t// if no intersecting containers found, return\n\t\tif(!innermostContainer) {\n\t\t\treturn;\n\t\t}\n\n\t\t// move the item into the container if it's not there already\n\t\tif(this.containers.length === 1) {\n\t\t\tif (!this.containers[innermostIndex].containerCache.over) {\n\t\t\t\tthis.containers[innermostIndex]._trigger(\"over\", event, this._uiHash(this));\n\t\t\t\tthis.containers[innermostIndex].containerCache.over = 1;\n\t\t\t}\n\t\t} else {\n\n\t\t\t//When entering a new container, we will find the item with the least distance and append our item near it\n\t\t\tdist = 10000;\n\t\t\titemWithLeastDistance = null;\n\t\t\tfloating = innermostContainer.floating || isFloating(this.currentItem);\n\t\t\tposProperty = floating ? \"left\" : \"top\";\n\t\t\tsizeProperty = floating ? \"width\" : \"height\";\n\t\t\tbase = this.positionAbs[posProperty] + this.offset.click[posProperty];\n\t\t\tfor (j = this.items.length - 1; j >= 0; j--) {\n\t\t\t\tif(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif(this.items[j].item[0] === this.currentItem[0]) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tcur = this.items[j].item.offset()[posProperty];\n\t\t\t\tnearBottom = false;\n\t\t\t\tif(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){\n\t\t\t\t\tnearBottom = true;\n\t\t\t\t\tcur += this.items[j][sizeProperty];\n\t\t\t\t}\n\n\t\t\t\tif(Math.abs(cur - base) < dist) {\n\t\t\t\t\tdist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];\n\t\t\t\t\tthis.direction = nearBottom ? \"up\": \"down\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Check if dropOnEmpty is enabled\n\t\t\tif(!itemWithLeastDistance && !this.options.dropOnEmpty) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif(this.currentContainer === this.containers[innermostIndex]) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\titemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);\n\t\t\tthis._trigger(\"change\", event, this._uiHash());\n\t\t\tthis.containers[innermostIndex]._trigger(\"change\", event, this._uiHash(this));\n\t\t\tthis.currentContainer = this.containers[innermostIndex];\n\n\t\t\t//Update the placeholder\n\t\t\tthis.options.placeholder.update(this.currentContainer, this.placeholder);\n\n\t\t\tthis.containers[innermostIndex]._trigger(\"over\", event, this._uiHash(this));\n\t\t\tthis.containers[innermostIndex].containerCache.over = 1;\n\t\t}\n\n\n\t},\n\n\t_createHelper: function(event) {\n\n\t\tvar o = this.options,\n\t\t\thelper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === \"clone\" ? this.currentItem.clone() : this.currentItem);\n\n\t\t//Add the helper to the DOM if that didn't happen already\n\t\tif(!helper.parents(\"body\").length) {\n\t\t\t$(o.appendTo !== \"parent\" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);\n\t\t}\n\n\t\tif(helper[0] === this.currentItem[0]) {\n\t\t\tthis._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css(\"position\"), top: this.currentItem.css(\"top\"), left: this.currentItem.css(\"left\") };\n\t\t}\n\n\t\tif(!helper[0].style.width || o.forceHelperSize) {\n\t\t\thelper.width(this.currentItem.width());\n\t\t}\n\t\tif(!helper[0].style.height || o.forceHelperSize) {\n\t\t\thelper.height(this.currentItem.height());\n\t\t}\n\n\t\treturn helper;\n\n\t},\n\n\t_adjustOffsetFromHelper: function(obj) {\n\t\tif (typeof obj === \"string\") {\n\t\t\tobj = obj.split(\" \");\n\t\t}\n\t\tif ($.isArray(obj)) {\n\t\t\tobj = {left: +obj[0], top: +obj[1] || 0};\n\t\t}\n\t\tif (\"left\" in obj) {\n\t\t\tthis.offset.click.left = obj.left + this.margins.left;\n\t\t}\n\t\tif (\"right\" in obj) {\n\t\t\tthis.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\n\t\t}\n\t\tif (\"top\" in obj) {\n\t\t\tthis.offset.click.top = obj.top + this.margins.top;\n\t\t}\n\t\tif (\"bottom\" in obj) {\n\t\t\tthis.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\n\t\t}\n\t},\n\n\t_getParentOffset: function() {\n\n\n\t\t//Get the offsetParent and cache its position\n\t\tthis.offsetParent = this.helper.offsetParent();\n\t\tvar po = this.offsetParent.offset();\n\n\t\t// This is a special case where we need to modify a offset calculated on start, since the following happened:\n\t\t// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent\n\t\t// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that\n\t\t//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag\n\t\tif(this.cssPosition === \"absolute\" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {\n\t\t\tpo.left += this.scrollParent.scrollLeft();\n\t\t\tpo.top += this.scrollParent.scrollTop();\n\t\t}\n\n\t\t// This needs to be actually done for all browsers, since pageX/pageY includes this information\n\t\t// with an ugly IE fix\n\t\tif( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === \"html\" && $.ui.ie)) {\n\t\t\tpo = { top: 0, left: 0 };\n\t\t}\n\n\t\treturn {\n\t\t\ttop: po.top + (parseInt(this.offsetParent.css(\"borderTopWidth\"),10) || 0),\n\t\t\tleft: po.left + (parseInt(this.offsetParent.css(\"borderLeftWidth\"),10) || 0)\n\t\t};\n\n\t},\n\n\t_getRelativeOffset: function() {\n\n\t\tif(this.cssPosition === \"relative\") {\n\t\t\tvar p = this.currentItem.position();\n\t\t\treturn {\n\t\t\t\ttop: p.top - (parseInt(this.helper.css(\"top\"),10) || 0) + this.scrollParent.scrollTop(),\n\t\t\t\tleft: p.left - (parseInt(this.helper.css(\"left\"),10) || 0) + this.scrollParent.scrollLeft()\n\t\t\t};\n\t\t} else {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t},\n\n\t_cacheMargins: function() {\n\t\tthis.margins = {\n\t\t\tleft: (parseInt(this.currentItem.css(\"marginLeft\"),10) || 0),\n\t\t\ttop: (parseInt(this.currentItem.css(\"marginTop\"),10) || 0)\n\t\t};\n\t},\n\n\t_cacheHelperProportions: function() {\n\t\tthis.helperProportions = {\n\t\t\twidth: this.helper.outerWidth(),\n\t\t\theight: this.helper.outerHeight()\n\t\t};\n\t},\n\n\t_setContainment: function() {\n\n\t\tvar ce, co, over,\n\t\t\to = this.options;\n\t\tif(o.containment === \"parent\") {\n\t\t\to.containment = this.helper[0].parentNode;\n\t\t}\n\t\tif(o.containment === \"document\" || o.containment === \"window\") {\n\t\t\tthis.containment = [\n\t\t\t\t0 - this.offset.relative.left - this.offset.parent.left,\n\t\t\t\t0 - this.offset.relative.top - this.offset.parent.top,\n\t\t\t\t$(o.containment === \"document\" ? document : window).width() - this.helperProportions.width - this.margins.left,\n\t\t\t\t($(o.containment === \"document\" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t}\n\n\t\tif(!(/^(document|window|parent)$/).test(o.containment)) {\n\t\t\tce = $(o.containment)[0];\n\t\t\tco = $(o.containment).offset();\n\t\t\tover = ($(ce).css(\"overflow\") !== \"hidden\");\n\n\t\t\tthis.containment = [\n\t\t\t\tco.left + (parseInt($(ce).css(\"borderLeftWidth\"),10) || 0) + (parseInt($(ce).css(\"paddingLeft\"),10) || 0) - this.margins.left,\n\t\t\t\tco.top + (parseInt($(ce).css(\"borderTopWidth\"),10) || 0) + (parseInt($(ce).css(\"paddingTop\"),10) || 0) - this.margins.top,\n\t\t\t\tco.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css(\"borderLeftWidth\"),10) || 0) - (parseInt($(ce).css(\"paddingRight\"),10) || 0) - this.helperProportions.width - this.margins.left,\n\t\t\t\tco.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css(\"borderTopWidth\"),10) || 0) - (parseInt($(ce).css(\"paddingBottom\"),10) || 0) - this.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t}\n\n\t},\n\n\t_convertPositionTo: function(d, pos) {\n\n\t\tif(!pos) {\n\t\t\tpos = this.position;\n\t\t}\n\t\tvar mod = d === \"absolute\" ? 1 : -1,\n\t\t\tscroll = this.cssPosition === \"absolute\" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,\n\t\t\tscrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);\n\n\t\treturn {\n\t\t\ttop: (\n\t\t\t\tpos.top\t+\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\tthis.offset.relative.top * mod +\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.parent.top * mod -\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t( ( this.cssPosition === \"fixed\" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)\n\t\t\t),\n\t\t\tleft: (\n\t\t\t\tpos.left +\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\tthis.offset.relative.left * mod +\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.parent.left * mod\t-\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t( ( this.cssPosition === \"fixed\" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_generatePosition: function(event) {\n\n\t\tvar top, left,\n\t\t\to = this.options,\n\t\t\tpageX = event.pageX,\n\t\t\tpageY = event.pageY,\n\t\t\tscroll = this.cssPosition === \"absolute\" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);\n\n\t\t// This is another very weird special case that only happens for relative elements:\n\t\t// 1. If the css position is relative\n\t\t// 2. and the scroll parent is the document or similar to the offset parent\n\t\t// we have to refresh the relative offset during the scroll so there are no jumps\n\t\tif(this.cssPosition === \"relative\" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {\n\t\t\tthis.offset.relative = this._getRelativeOffset();\n\t\t}\n\n\t\t/*\n\t\t * - Position constraining -\n\t\t * Constrain the position to a mix of grid, containment.\n\t\t */\n\n\t\tif(this.originalPosition) { //If we are not dragging yet, we won't check for options\n\n\t\t\tif(this.containment) {\n\t\t\t\tif(event.pageX - this.offset.click.left < this.containment[0]) {\n\t\t\t\t\tpageX = this.containment[0] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif(event.pageY - this.offset.click.top < this.containment[1]) {\n\t\t\t\t\tpageY = this.containment[1] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t\tif(event.pageX - this.offset.click.left > this.containment[2]) {\n\t\t\t\t\tpageX = this.containment[2] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif(event.pageY - this.offset.click.top > this.containment[3]) {\n\t\t\t\t\tpageY = this.containment[3] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(o.grid) {\n\t\t\t\ttop = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];\n\t\t\t\tpageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;\n\n\t\t\t\tleft = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];\n\t\t\t\tpageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;\n\t\t\t}\n\n\t\t}\n\n\t\treturn {\n\t\t\ttop: (\n\t\t\t\tpageY -\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\tthis.offset.click.top -\t\t\t\t\t\t\t\t\t\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.relative.top\t-\t\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.parent.top +\t\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t( ( this.cssPosition === \"fixed\" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))\n\t\t\t),\n\t\t\tleft: (\n\t\t\t\tpageX -\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\tthis.offset.click.left -\t\t\t\t\t\t\t\t\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.relative.left\t-\t\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.parent.left +\t\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t( ( this.cssPosition === \"fixed\" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_rearrange: function(event, i, a, hardRefresh) {\n\n\t\ta ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === \"down\" ? i.item[0] : i.item[0].nextSibling));\n\n\t\t//Various things done here to improve the performance:\n\t\t// 1. we create a setTimeout, that calls refreshPositions\n\t\t// 2. on the instance, we have a counter variable, that get's higher after every append\n\t\t// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same\n\t\t// 4. this lets only the last addition to the timeout stack through\n\t\tthis.counter = this.counter ? ++this.counter : 1;\n\t\tvar counter = this.counter;\n\n\t\tthis._delay(function() {\n\t\t\tif(counter === this.counter) {\n\t\t\t\tthis.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove\n\t\t\t}\n\t\t});\n\n\t},\n\n\t_clear: function(event, noPropagation) {\n\n\t\tthis.reverting = false;\n\t\t// We delay all events that have to be triggered to after the point where the placeholder has been removed and\n\t\t// everything else normalized again\n\t\tvar i,\n\t\t\tdelayedTriggers = [];\n\n\t\t// We first have to update the dom position of the actual currentItem\n\t\t// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)\n\t\tif(!this._noFinalSort && this.currentItem.parent().length) {\n\t\t\tthis.placeholder.before(this.currentItem);\n\t\t}\n\t\tthis._noFinalSort = null;\n\n\t\tif(this.helper[0] === this.currentItem[0]) {\n\t\t\tfor(i in this._storedCSS) {\n\t\t\t\tif(this._storedCSS[i] === \"auto\" || this._storedCSS[i] === \"static\") {\n\t\t\t\t\tthis._storedCSS[i] = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.currentItem.css(this._storedCSS).removeClass(\"ui-sortable-helper\");\n\t\t} else {\n\t\t\tthis.currentItem.show();\n\t\t}\n\n\t\tif(this.fromOutside && !noPropagation) {\n\t\t\tdelayedTriggers.push(function(event) { this._trigger(\"receive\", event, this._uiHash(this.fromOutside)); });\n\t\t}\n\t\tif((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(\".ui-sortable-helper\")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {\n\t\t\tdelayedTriggers.push(function(event) { this._trigger(\"update\", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed\n\t\t}\n\n\t\t// Check if the items Container has Changed and trigger appropriate\n\t\t// events.\n\t\tif (this !== this.currentContainer) {\n\t\t\tif(!noPropagation) {\n\t\t\t\tdelayedTriggers.push(function(event) { this._trigger(\"remove\", event, this._uiHash()); });\n\t\t\t\tdelayedTriggers.push((function(c) { return function(event) { c._trigger(\"receive\", event, this._uiHash(this)); };  }).call(this, this.currentContainer));\n\t\t\t\tdelayedTriggers.push((function(c) { return function(event) { c._trigger(\"update\", event, this._uiHash(this));  }; }).call(this, this.currentContainer));\n\t\t\t}\n\t\t}\n\n\n\t\t//Post events to containers\n\t\tfor (i = this.containers.length - 1; i >= 0; i--){\n\t\t\tif(!noPropagation) {\n\t\t\t\tdelayedTriggers.push((function(c) { return function(event) { c._trigger(\"deactivate\", event, this._uiHash(this)); };  }).call(this, this.containers[i]));\n\t\t\t}\n\t\t\tif(this.containers[i].containerCache.over) {\n\t\t\t\tdelayedTriggers.push((function(c) { return function(event) { c._trigger(\"out\", event, this._uiHash(this)); };  }).call(this, this.containers[i]));\n\t\t\t\tthis.containers[i].containerCache.over = 0;\n\t\t\t}\n\t\t}\n\n\t\t//Do what was originally in plugins\n\t\tif ( this.storedCursor ) {\n\t\t\tthis.document.find( \"body\" ).css( \"cursor\", this.storedCursor );\n\t\t\tthis.storedStylesheet.remove();\n\t\t}\n\t\tif(this._storedOpacity) {\n\t\t\tthis.helper.css(\"opacity\", this._storedOpacity);\n\t\t}\n\t\tif(this._storedZIndex) {\n\t\t\tthis.helper.css(\"zIndex\", this._storedZIndex === \"auto\" ? \"\" : this._storedZIndex);\n\t\t}\n\n\t\tthis.dragging = false;\n\t\tif(this.cancelHelperRemoval) {\n\t\t\tif(!noPropagation) {\n\t\t\t\tthis._trigger(\"beforeStop\", event, this._uiHash());\n\t\t\t\tfor (i=0; i < delayedTriggers.length; i++) {\n\t\t\t\t\tdelayedTriggers[i].call(this, event);\n\t\t\t\t} //Trigger all delayed events\n\t\t\t\tthis._trigger(\"stop\", event, this._uiHash());\n\t\t\t}\n\n\t\t\tthis.fromOutside = false;\n\t\t\treturn false;\n\t\t}\n\n\t\tif(!noPropagation) {\n\t\t\tthis._trigger(\"beforeStop\", event, this._uiHash());\n\t\t}\n\n\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!\n\t\tthis.placeholder[0].parentNode.removeChild(this.placeholder[0]);\n\n\t\tif(this.helper[0] !== this.currentItem[0]) {\n\t\t\tthis.helper.remove();\n\t\t}\n\t\tthis.helper = null;\n\n\t\tif(!noPropagation) {\n\t\t\tfor (i=0; i < delayedTriggers.length; i++) {\n\t\t\t\tdelayedTriggers[i].call(this, event);\n\t\t\t} //Trigger all delayed events\n\t\t\tthis._trigger(\"stop\", event, this._uiHash());\n\t\t}\n\n\t\tthis.fromOutside = false;\n\t\treturn true;\n\n\t},\n\n\t_trigger: function() {\n\t\tif ($.Widget.prototype._trigger.apply(this, arguments) === false) {\n\t\t\tthis.cancel();\n\t\t}\n\t},\n\n\t_uiHash: function(_inst) {\n\t\tvar inst = _inst || this;\n\t\treturn {\n\t\t\thelper: inst.helper,\n\t\t\tplaceholder: inst.placeholder || $([]),\n\t\t\tposition: inst.position,\n\t\t\toriginalPosition: inst.originalPosition,\n\t\t\toffset: inst.positionAbs,\n\t\t\titem: inst.currentItem,\n\t\t\tsender: _inst ? _inst.element : null\n\t\t};\n\t}\n\n});\n\n})(jQuery);\n"
  },
  {
    "path": "examples/unfinished/movers/movers.html",
    "content": "<head>\n  <title>movers</title>\n</head>\n\n<body>\n  {{> main}}\n</body>\n\n<template name=\"main\">\n<div class=\"container\">\n  <div class=\"item red\">Red</div>\n  <div class=\"item green\">Green</div>\n  <div class=\"item blue\">Blue</div>\n  <div class=\"item yellow\">Yellow</div>\n</div>\n</template>\n"
  },
  {
    "path": "examples/unfinished/movers/movers.js",
    "content": "if (Meteor.isClient) {\n  var moveCount = 0;\n  var MOVE_INTERVAL = 3000;\n  var MOVE_DURATION = 2000;\n\n  doMove = function () {\n    moveCount++;\n    if (moveCount % 2 === 1) {\n      animateToBefore($('.green'), $('.yellow'));\n      animateToBefore($('.red'), null);\n      animateToBefore($('.blue'), null);\n    } else {\n      animateToBefore($('.red'), null);\n      animateToBefore($('.green'), null);\n      animateToBefore($('.blue'), null);\n      animateToBefore($('.yellow'), null);\n    }\n  };\n\n  Meteor.startup(function () {\n    doMove();\n    window.setInterval(doMove, MOVE_INTERVAL);\n  });\n\n\n  animateToBefore = function ($n, $newNext) {\n    // we don't use jQuery's `.css()` for these because we want the\n    // element's own style, not the computed style\n    var oldTop = $n[0].style.top;\n    var oldPosition = $n[0].style.position;\n    var oldZIndex = $n[0].style.zIndex;\n    var oldMarginBottom = $n[0].style.marginBottom;\n\n    var outerHeight = $n.outerHeight(); // not margin\n    var marginBottom = parseInt($n.css('margin-bottom'));\n\n    // TODO: test interesting elements like table rows, etc.\n    var placeholder = $(document.createElement($n[0].nodeName));\n    var placeholderHeight = outerHeight + marginBottom;\n    placeholder.css('height', placeholderHeight);\n    // insert placeholder\n    $n.before(placeholder);\n\n    // move node\n    if ($newNext)\n      $newNext.before($n);\n    else\n      $n.parent().append($n);\n\n    // XXX would tracking \"left\" as well as \"top\" magically get us\n    // horizontal re-ordering?\n    $n.css({marginBottom: -outerHeight,\n            position: 'relative',\n            zIndex: 2,\n            top: 0});\n    var vOffset = placeholder.offset().top - $n.offset().top;\n    $n.css('top', vOffset);\n\n    $({t:0}).animate({t:1}, {\n      duration: MOVE_DURATION,\n      step: function (t, fx) {\n        var curPlaceholderHeight = Math.round(placeholderHeight * (1-t));\n        var curMarginBottom = marginBottom - curPlaceholderHeight;\n        var curTop = (-curPlaceholderHeight +\n                      Math.round((1-t) * (vOffset + placeholderHeight)));\n        $n.css({marginBottom: curMarginBottom,\n                top: curTop});\n        placeholder.css('height', curPlaceholderHeight);\n      },\n      progress: function (a, t) {\n        //          if (t >= 0.5) {\n        //            console.log(a);\n        //            a.stop();\n        //          }\n      },\n      complete: function () {\n        placeholder.remove();\n        $n[0].style.top = oldTop;\n        $n[0].style.position = oldPosition;\n        $n[0].style.zIndex = oldZIndex;\n        $n[0].style.marginBottom = oldMarginBottom;\n      }\n    });\n  };\n\n}\n\nif (Meteor.isServer) {\n  Meteor.startup(function () {\n    // code to run on server at startup\n  });\n}\n"
  },
  {
    "path": "examples/unfinished/movers/movers.less",
    "content": ".item {\n  border: 1px solid black;\n  padding: 10px;\n  font-size: 18px;\n  margin-bottom: 10px;\n  font-weight: bold;\n  position: relative;\n}\n.red { background: #fcc; }\n.blue { background: #ccf; }\n.green { background: #cfc; }\n.yellow { background: #ffc; }\n"
  },
  {
    "path": "examples/unfinished/parse-inspector/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/parse-inspector/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nautopublish\npreserve-inputs\njsparse\nstandard-app-packages\n"
  },
  {
    "path": "examples/unfinished/parse-inspector/.meteor/release",
    "content": "0.6.0\n"
  },
  {
    "path": "examples/unfinished/parse-inspector/parse-inspector.css",
    "content": "\n* { padding: 0; margin: 0; }\nhtml, body { height: 100%; }\n\n#topbar {\n  position: absolute;\n  width: 100%;\n  top: 0;\n  height: 39px;\n  border-bottom: 1px solid #555;\n  overflow: auto;\n  background: #cfc;\n  font-size: 12px;\n}\n\n#topbarinner {\n  padding: 7px;\n  font-family: sans-serif;\n}\n\n#main {\n  position: absolute;\n  width: 100%;\n  top: 40px;\n  bottom: 0;\n}\n\n#inputarea {\n  border: 0;\n  border-right: 1px solid #555;\n  position: absolute;\n  height: 100%;\n  left: 0;\n  right: 50%;\n}\n\n#inputarea textarea {\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  font-family: monospace;\n  font-size: 100%;\n  border: 0;\n}\n\n#outputoptions {\n  position: absolute;\n  left: 50%;\n  right: 0;\n  overflow: visible;\n  bottom: 0;\n  height: 29px;\n  border-top: 1px solid #555;\n\n  background: #ccc;\n}\n\n#output {\n  position: absolute;\n  left: 50%;\n  right: 0;\n  overflow: auto;\n  top: 0;\n  bottom: 30px;\n\n  font-family: monospace;\n}\n\n#outputoptions .output-type {\n  text-decoration: none;\n  font-family: sans-serif;\n  font-size: 14px;\n  display: inline-block;\n  background: #e2e2e2;\n  vertical-align: top;\n  position: relative;\n  top: -1px;\n  padding: 3px 8px;\n  margin-left: 6px;\n  border-bottom-left-radius: 5px;\n  border-bottom-right-radius: 5px;\n  border: 1px solid #777;\n  border-top: 1px solid #555;\n  cursor: pointer;\n}\n\n#outputoptions .output-type.selected {\n  font-weight: bold;\n  background: #fff;\n  border-top: 1px solid #fff;\n}\n\n#inputarea textarea, #output {\n  line-height: 130%;\n}\n\n.lex { border: 1px solid #333; cursor: pointer; }\n\n.lex_keyword { background: #0f0; }\n.lex_identifier { background: #ff0; }\n.lex_punctuation { background: #0ff; }\n.lex_error { background: #f00; }\n.lex_whitespace, .lex_newline, .lex_eof { background: #fcc; }\n.lex_comment { background: #ccc; }\n\n.lex_regex { background: #f0f; }\n.lex_null { background: #dac; }\n.lex_boolean { background: #faf; }\n.lex_number { background: #c3f; }\n.lex_string { background: #fc3; }\n\n.parseerror {\n  background: #f99;\n  border: 1px solid blue;\n  cursor: pointer;\n}\n.parseerrormessage { color: #c00; }\n\n.box {\n  display: inline-block;\n  margin: 5px;\n  margin-top: 0;\n  background: #fff;\n}\n\n.box.statement {\n  display: block;\n}\n\n#output > .box {\n  margin-top: 5px;\n}\n\n.box.named {\n  border: 1px solid #888;\n  border-radius: 5px;\n  cursor: pointer;\n  overflow: hidden;\n  /* position:relative breaks overflow:hidden effect of rounded corners? */\n  position: static;\n}\n\n.box.head {\n  font-family: sans-serif;\n  font-size: 70%;\n  font-weight: bold;\n  display: block;\n  margin-left: 0;\n  margin-right: 0;\n  background: #ccc;\n  color: #000;\n  padding-left: 5px;\n  padding-right: 5px;\n  border-bottom: 1px solid #888;\n}\n\n.box.head:last-child {\n  margin: 0;\n  border-bottom: 0;\n}\n\n.box.token {\n  background: #ddd;\n  /*border: 1px solid #999;*/\n  border: 1px solid #00f;\n  cursor: pointer;\n  font-family: monospace;\n  font-weight: bold;\n  font-size: 120%;\n  padding: 1px;\n}\n\n.box.named[mousehover] {\n  background: #cdf;\n  border: 1px solid #448;\n}\n\n.box.token[mousehover] {\n  background: #ace;\n  border: 1px solid #448;    \n}\n\n.box.named[mousehover] > .box.head {\n  background: #58b;\n  border-bottom: 1px solid #448;\n}\n\n.box.named[mousehover] > .box.head:last-child {\n  border-bottom: 0;\n}\n\n"
  },
  {
    "path": "examples/unfinished/parse-inspector/parse-inspector.html",
    "content": "<head>\n  <title>jsparser</title>\n</head>\n\n<body>\n  {{> page}}\n</body>\n\n<template name=\"page\">\n  <div id=\"topbar\">\n    <div id=\"topbarinner\">\n      This is a demo of the new <code>jsparse</code> package.\n      <strong>Edit</strong> code on the left.\n      <strong>Click</strong> on an outlined box on the right\n      to select it in the code.  The full spec is supported.\n    </div>\n  </div>\n  <div id=\"main\">\n    <div id=\"inputarea\">{{!\nwhitespace is significant here; browser swallows initial\n    newline in textarea\n}}<textarea id=\"inputtextarea\">\n{{input}}</textarea>\n    </div>\n    <div id=\"outputoptions\">\n      {{#each outputTypes}}\n      <ins class=\"output-type {{is_outputtype_selected value}}\">{{name}}</ins>\n      {{/each}}\n    </div>\n    <div id=\"output\">\n      {{output}}\n    </div>\n  </div>\n</template>\n"
  },
  {
    "path": "examples/unfinished/parse-inspector/parse-inspector.js",
    "content": "\n\nif (Meteor.isClient) {\n  Meteor.startup(function () {\n    if (! Session.get(\"input\"))\n      Session.set(\"input\", \"var x = 3\");\n    if (! Session.get(\"output-type\"))\n      Session.set(\"output-type\", \"jsparse\");\n  });\n\n  Template.page.input = function () {\n    return Session.get(\"input\") || '';\n  };\n\n  Template.page.output = function () {\n    var input = Session.get(\"input\") || \"\";\n\n    var outputType = Session.get(\"output-type\");\n\n    if (outputType === \"jslex\") {\n      // LEXER\n\n      var lexer = new JSLexer(input);\n      var html = \"\";\n      var L;\n      do {\n        L = lexer.next();\n        var content;\n        if (L.type() === \"NEWLINE\") {\n          content = '&nbsp;<br>';\n        } else if (L.type() === \"EOF\") {\n          content = Handlebars._escape(\"<EOF>\");\n        } else {\n          content = Handlebars._escape(L.text() || ' ');\n          content = content.replace(/(?!.)\\s/g, '<br>'); // for multiline comments\n          content = content.replace(/\\s/g, '&nbsp;');\n        }\n        html += Spark.setDataContext(\n          L,\n          '<span class=\"lex lex_' + L.type().toLowerCase() + '\" ' +\n            'title=\"' + Handlebars._escape(L.type()) + '\">' +\n            content + '</span>');\n      } while (! L.isError() && ! L.isEOF());\n      return new Handlebars.SafeString(html);\n\n    } else if (outputType === \"jsparse\") {\n\n      // PARSER\n      var html;\n      var tree = null;\n      var parser = new JSParser(input, {includeComments: true});\n      try {\n        tree = parser.getSyntaxTree();\n      } catch (parseError) {\n        var errorLexeme = parser.lexer.lastLexeme;\n\n        html = Handlebars._escape(\n          input.substring(0, errorLexeme.startPos()));\n        html += Spark.setDataContext(\n          errorLexeme,\n          '<span class=\"parseerror\">' +\n            Handlebars._escape(errorLexeme.text() || '<EOF>') +\n            '</span>');\n        html = html.replace(/(?!.)\\s/g, '<br>');\n        html += '<div class=\"parseerrormessage\">' +\n          Handlebars._escape(parseError.toString()) + '</div>';\n      }\n      if (tree) {\n        var curPos = 0;\n        var unclosedInfos = [];\n        var toHtml = function (obj) {\n          if (obj instanceof ParseNode) {\n            var head = obj.name || '';\n            var children = obj.children;\n            var info = { startPos: curPos };\n            var isStatement = (head.indexOf('Stmnt') >= 0 ||\n                               head === \"comment\" ||\n                               head === \"functionDecl\");\n            var html = Spark.setDataContext(\n              info,\n              '<div class=\"box named' + (isStatement ? ' statement' : '') +\n                '\"><div class=\"box head\">' + Handlebars._escape(head) + '</div>' +\n                _.map(children, toHtml).join('') + '</div>');\n            unclosedInfos.push(info);\n            return html;\n          } else if (obj.text) {\n            // token\n            _.each(unclosedInfos, function (info) {\n              info.endPos = curPos;\n            });\n            curPos = obj.endPos();\n            unclosedInfos.length = 0;\n            var text = obj.text();\n            // insert zero-width spaces to allow wrapping\n            text = text.replace(/.{20}/g, \"$&\\u200b\");\n            text = Handlebars._escape(text);\n            text = text.replace(/\\u200b/g, '&#8203;');\n            text = text.replace(/\\n/g, '<br>');\n            return Spark.setDataContext(\n              obj,\n              '<div class=\"box token\">' + text + '</div>');\n          } else {\n            // other?\n            return '<div class=\"box other\">' +\n              Handlebars._escape(JSON.stringify(obj)) + '</div>';\n          }\n        };\n        html = toHtml(tree);\n        curPos = parser.lexer.pos;\n        _.each(unclosedInfos, function (info) {\n          info.endPos = curPos;\n        });\n      }\n\n      return new Handlebars.SafeString(html);\n    }\n    else return ''; // unknown output tab?\n  };\n\n  Template.page.events({\n    'keyup #inputarea textarea': function (event) {\n      var input = event.currentTarget.value;\n      Session.set(\"input\", input);\n    },\n    'mouseover .box.named, mouseover .box.token': function (event) {\n      event.currentTarget.setAttribute('mousehover', 'mousehover');\n      event.stopImmediatePropagation();\n    },\n    'mouseout .box.named, mouseout .box.token': function (event) {\n      event.currentTarget.removeAttribute('mousehover');\n      event.stopImmediatePropagation();\n    },\n    'click .box.token': function (event) {\n      selectInputText(this.startPos(), this.endPos());\n      return false;\n    },\n    'click .box.named': function (event) {\n      selectInputText(this.startPos, this.endPos);\n      return false;\n    },\n    'click .parseerror': function (event) {\n      selectInputText(this.startPos(), this.endPos());\n      return false;\n    },\n    'click .output-type': function (event) {\n      Session.set(\"output-type\", this.value);\n    },\n    'click .lex': function (event) {\n      selectInputText(this.startPos(), this.endPos());\n      return false;\n    }\n  });\n\n  Template.page.outputTypes = [\n    {name: \"JS Lex\", value: \"jslex\"},\n    {name: \"JS Parse\", value: \"jsparse\"}\n  ];\n\n  Template.page.is_outputtype_selected = function (which) {\n    return Session.equals(\"output-type\", which) ? \"selected\" : \"\";\n  };\n\n  var selectTextInArea = function (e, start, end){\n    e.focus();\n    if (e.setSelectionRange) {\n      e.setSelectionRange(start, end);\n    } else if (e.createTextRange) {\n      var r = e.createTextRange();\n      r.collapse(true);\n      r.moveEnd('character', end);\n      r.moveStart('character', start);\n      r.select();\n    }\n  };\n\n  var selectInputText = function (start, end) {\n    var textarea = DomUtils.find(document, '#inputarea textarea');\n    selectTextInArea(textarea, start, end);\n  };\n\n}\n"
  },
  {
    "path": "examples/unfinished/python-ddp-client/README",
    "content": "sudo easy_install ws4py\n"
  },
  {
    "path": "examples/unfinished/python-ddp-client/ddp-client.py",
    "content": "#!/usr/bin/env python2.7\n\nimport sys\nimport json\nimport time\nimport argparse\nimport thread\nimport threading\nimport traceback\n\nfrom ws4py.client.threadedclient import WebSocketClient\nfrom cmd import Cmd\n\n\nDDP_VERSIONS = [\"pre1\"]\n\ndef log(msg):\n    \"\"\"A shortcut to write to the standard error file descriptor\"\"\"\n    sys.stderr.write('{}\\n'.format(msg))\n\n\ndef parse_command(params):\n    \"\"\"Parses a command with a first string param and a second\n    json-encoded param\"\"\"\n    name, args = (params + ' ').split(' ', 1)\n    return name, args and json.loads(args) or []\n\n\nclass DDPClient(WebSocketClient):\n    \"\"\"simple wrapper around Websockets for DDP connections\"\"\"\n    def __init__(self, url, print_raw):\n        WebSocketClient.__init__(self, url)\n        self.print_raw = print_raw\n\n        # We keep track of methods and subs that have been sent from the\n        # client so that we only return to the prompt or quit the app\n        # once we get back all the results from the server.\n        #\n        # `id`\n        #\n        #   The operation id, informed by the client and returned by the\n        #   server to make sure both are talking about the same thing.\n        #\n        # `result_acked`\n        #\n        #   Flag to make sure we were answered.\n        #\n        # `data_acked`\n        #\n        #   Flag to make sure we received the correct data from the\n        #   message we were waiting for.\n        self.pending_condition = threading.Condition()\n        self.pending = {}\n\n\n    def send(self, msg_dict):\n        \"\"\"Send a message through the websocket client and wait for the\n        answer if the message being sent contains an id attribute.\n\n        Also prints to the standard error fd.\n\n        (NOTE: DDP does not require waiting for an answer but this is\n        a simple proof-of-concept client)\"\"\"\n        message = json.dumps(msg_dict)\n        if self.print_raw:\n            log('[RAW] >> {}'.format(message))\n        super(DDPClient, self).send(message)\n\n        # We don't need to wait for certain messages, just for the ones\n        # with ids.\n        if 'id' in msg_dict:\n            self.block_until_return(msg_dict['msg'], msg_dict['id'])\n\n    def block_until_return(self, msg_type, msg_id):\n        \"\"\"Wait until the msg_id that was sent to the server is answered\"\"\"\n        with self.pending_condition:\n            self.pending = {'id': msg_id}\n\n            while self.pending.get('id') is not None:\n                if msg_type == 'method':\n                    # Methods must validate both data and result flag\n                    we_are_good = all((\n                            self.pending.get('result_acked'),\n                            self.pending.get('data_acked')))\n                else:\n                    # Subs just need to validate data flag\n                    we_are_good = self.pending.get('data_acked')\n\n                if we_are_good:\n                    return\n                self.pending_condition.wait()\n\n    def opened(self):\n        \"\"\"Set the connecte flag to true and send the connect message to\n        the server.\"\"\"\n        self.send({\"msg\": \"connect\", \"version\": DDP_VERSIONS[0],\n                   \"support\": DDP_VERSIONS})\n\n    def received_message(self, data):\n        \"\"\"Parse an incoming message and print it. Also update\n        self.pending appropriately\"\"\"\n        if self.print_raw:\n            log('[RAW] << {}'.format(data))\n\n        msg = json.loads(str(data))\n\n        changed_pending = False\n\n        with self.pending_condition:\n            if msg.get('msg') == 'error':\n                log(\"* ERROR {}\".format(msg['reason']))\n                # Reset all pending state\n                self.pending = {}\n                changed_pending = True\n\n            elif msg.get('msg') == 'connected':\n                log(\"* CONNECTED\")\n\n            elif msg.get('msg') == 'failed':\n                log(\"* FAILED; suggested version {}\".format(msg['version']))\n\n            elif msg.get('msg') == 'result':\n                if msg['id'] == self.pending.get('id'):\n                    if msg.get('result'):\n                        log(\"* METHOD RESULT {}\".format(msg['result']))\n                    elif msg.get('error'):\n                        log(\"* ERROR {}\".format(msg['error']['reason']))\n                    else:\n                        log(\"* METHOD FINISHED\")\n                    self.pending.update({'result_acked': True})\n                    changed_pending = True\n\n            elif msg.get('msg') == 'added':\n                log(\"* ADDED {} {}\".format(\n                        msg['collection'], msg['id']))\n                if 'fields' in msg:\n                    for key, value in msg['fields'].items():\n                        log(\"  - FIELD {} {}\".format(key, value))\n            elif msg.get('msg') == 'changed':\n                log(\"* CHANGED {} {}\".format(\n                        msg['collection'], msg['id']))\n                if 'fields' in msg:\n                    for key, value in msg['fields'].items():\n                        log(\"  - FIELD {} {}\".format(key, value))\n                if 'cleared' in msg:\n                    for key in msg['cleared']:\n                        log(\"  - CLEARED {}\".format(key));\n            elif msg.get('msg') == 'removed':\n                log(\"* REMOVED {} {}\".format(\n                        msg['collection'], \", \".join(msg['ids'])))\n            elif msg.get('msg') == 'ready':\n                assert 'subs' in msg\n                if self.pending.get('id') in msg['subs']:\n                    log(\"* READY\")\n                    self.pending.update({'data_acked': True})\n                    changed_pending = True\n            elif msg.get('msg') == 'updated':\n                if self.pending.get('id') in msg['methods']:\n                    log(\"* UPDATED\")\n                    self.pending.update({'data_acked': True})\n                    changed_pending = True\n            elif msg.get('msg') == 'nosub':\n                log(\"* NOSUB\")\n                self.pending.update({'data_acked': True})\n                changed_pending = True\n\n            if changed_pending:\n                self.pending_condition.notify()\n\n    def closed(self, code, reason=None):\n        \"\"\"Called when the connection is closed\"\"\"\n        log('* CONNECTION CLOSED {} {}'.format(code, reason))\n\n    # Overrides WebSocket to run to ensure that if an unhandled exception is\n    # thrown in the thread, we print the exception and *then* kill the main\n    # thread.\n    def run(self):\n        try:\n            super(DDPClient, self).run()\n        except:\n            traceback.print_exc()\n        finally:\n            with self.pending_condition:\n                self.pending_condition.notify()\n            thread.interrupt_main()\n\n\nclass App(Cmd):\n    \"\"\"Main input loop.\"\"\"\n\n    def __init__(self, ddp_endpoint, print_raw):\n        Cmd.__init__(self)\n\n        # Should we print the raw websocket messages in addition to\n        # parsing them?\n        self.print_raw = print_raw\n\n        # This is the websocket client that will actually talk with\n        # meteor\n        self.ddpclient = DDPClient(\n            'ws://' + ddp_endpoint + '/websocket',\n            self.print_raw)\n        self.ddpclient.connect()\n\n        # Showing a fancy prompt string if we're interactive\n        if sys.stdin.isatty():\n            self.prompt = ddp_endpoint + '> '\n        else:\n            self.prompt = ''\n\n        # Initializing the message id counter that will be incremented\n        # by the `next_id() method\n        self.unique_id = 0\n\n    def do_call(self, params):\n        \"\"\"The `call` command\"\"\"\n        try:\n            method_name, params = parse_command(params)\n        except ValueError:\n            log('Error parsing parameter list - try `help call`')\n            return\n        self.ddpclient.send({\n            \"msg\": \"method\",\n            \"method\": method_name,\n            \"params\": params,\n            \"id\": self.next_id(),\n        })\n\n    def do_sub(self, params):\n        \"\"\"The `sub` command\"\"\"\n        try:\n            sub_name, params = parse_command(params)\n        except ValueError:\n            log('Error parsing parameter list - try `help sub`')\n            return\n        self.ddpclient.send({\n            \"msg\": \"sub\",\n            \"name\": sub_name,\n            \"params\": params,\n            \"id\": self.next_id(),\n        })\n\n    def do_EOF(self, line):\n        \"\"\"The `EOF` \"command\"\n\n        It's here to support `cat file | python ddpclient.py`\n        \"\"\"\n        return True\n\n    def do_help(self, line):\n        \"\"\"The `help` command\"\"\"\n\n        msgs = {\n            'call': (\n                'call <method name> <json array of parameters>\\n'\n                '  Calls a remote method\\n'\n                '  Example: call vote [\"foo.meteor.com\"]'),\n            'sub': (\n                'sub <subscription name> [<json array of parameters>]\\n'\n                '  Subscribes to a remote dataset\\n'\n                '  Examples: `sub allApps` or `sub myApp '\n                '[\"foo.meteor.com\"]`'),\n        }\n\n        line = line.strip()\n        if line and line in msgs:\n            return log('\\n' + msgs[line])\n\n        for msg in msgs.values():\n            log('\\n' + msg)\n\n    def emptyline(self):\n        \"\"\"Disable the default Cmd empty line behavior\"\"\"\n        pass\n\n    def next_id(self):\n        \"\"\"Calculates the next id for messages that will be sent to the\n        server\"\"\"\n        self.unique_id = self.unique_id + 1\n        return str(self.unique_id)\n\n\ndef main():\n    \"\"\"Parse the command line arguments and create a new App instance\"\"\"\n    parser = argparse.ArgumentParser(\n        description='A command-line tool for communicating with a DDP server.')\n    parser.add_argument(\n        'ddp_endpoint', metavar='ddp_endpoint',\n        help='DDP websocket endpoint to connect ' +\n        'to, e.g. madewith.meteor.com')\n    parser.add_argument(\n        '--print-raw', dest='print_raw', action=\"store_true\",\n        help='print raw websocket data in addition to parsed results')\n    args = parser.parse_args()\n\n    app = App(args.ddp_endpoint, args.print_raw)\n    try:\n        app.cmdloop()\n    except KeyboardInterrupt:\n        # On Ctrl-C or thread.interrupt_main(), just exit without printing a\n        # traceback.\n        pass\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "examples/unfinished/python-ddp-client/test_input",
    "content": "sub\nsub undefinedSub\nsub undefinedSub someArg\nsub undefinedSub {}\nsub allApps\nsub myApp \"foo.bar\"\nsub myApp [\"foo.meteor.com\"]\n\ncall\ncall undefinedMethod\ncall undefinedMethod yzyz\ncall undefinedMethod {}\ncall vote\ncall vote []\ncall vote [\"foo.meteor.com\"]\ncall vote [\"madewith.meteor.com\"]\ncall vote {}\n\nhelp\nhelp sub\nhelp call\n\n"
  },
  {
    "path": "examples/unfinished/reorderable-list/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/reorderable-list/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nstandard-app-packages\nautopublish\ninsecure\n"
  },
  {
    "path": "examples/unfinished/reorderable-list/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "examples/unfinished/reorderable-list/client/jquery-ui-sortable.js",
    "content": "/*! jQuery UI - v1.10.3 - 2013-07-30\n* http://jqueryui.com\n* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.sortable.js\n* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */\n\n(function( $, undefined ) {\n\nvar uuid = 0,\n\truniqueId = /^ui-id-\\d+$/;\n\n// $.ui might exist from components with no dependencies, e.g., $.ui.position\n$.ui = $.ui || {};\n\n$.extend( $.ui, {\n\tversion: \"1.10.3\",\n\n\tkeyCode: {\n\t\tBACKSPACE: 8,\n\t\tCOMMA: 188,\n\t\tDELETE: 46,\n\t\tDOWN: 40,\n\t\tEND: 35,\n\t\tENTER: 13,\n\t\tESCAPE: 27,\n\t\tHOME: 36,\n\t\tLEFT: 37,\n\t\tNUMPAD_ADD: 107,\n\t\tNUMPAD_DECIMAL: 110,\n\t\tNUMPAD_DIVIDE: 111,\n\t\tNUMPAD_ENTER: 108,\n\t\tNUMPAD_MULTIPLY: 106,\n\t\tNUMPAD_SUBTRACT: 109,\n\t\tPAGE_DOWN: 34,\n\t\tPAGE_UP: 33,\n\t\tPERIOD: 190,\n\t\tRIGHT: 39,\n\t\tSPACE: 32,\n\t\tTAB: 9,\n\t\tUP: 38\n\t}\n});\n\n// plugins\n$.fn.extend({\n\tfocus: (function( orig ) {\n\t\treturn function( delay, fn ) {\n\t\t\treturn typeof delay === \"number\" ?\n\t\t\t\tthis.each(function() {\n\t\t\t\t\tvar elem = this;\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t$( elem ).focus();\n\t\t\t\t\t\tif ( fn ) {\n\t\t\t\t\t\t\tfn.call( elem );\n\t\t\t\t\t\t}\n\t\t\t\t\t}, delay );\n\t\t\t\t}) :\n\t\t\t\torig.apply( this, arguments );\n\t\t};\n\t})( $.fn.focus ),\n\n\tscrollParent: function() {\n\t\tvar scrollParent;\n\t\tif (($.ui.ie && (/(static|relative)/).test(this.css(\"position\"))) || (/absolute/).test(this.css(\"position\"))) {\n\t\t\tscrollParent = this.parents().filter(function() {\n\t\t\t\treturn (/(relative|absolute|fixed)/).test($.css(this,\"position\")) && (/(auto|scroll)/).test($.css(this,\"overflow\")+$.css(this,\"overflow-y\")+$.css(this,\"overflow-x\"));\n\t\t\t}).eq(0);\n\t\t} else {\n\t\t\tscrollParent = this.parents().filter(function() {\n\t\t\t\treturn (/(auto|scroll)/).test($.css(this,\"overflow\")+$.css(this,\"overflow-y\")+$.css(this,\"overflow-x\"));\n\t\t\t}).eq(0);\n\t\t}\n\n\t\treturn (/fixed/).test(this.css(\"position\")) || !scrollParent.length ? $(document) : scrollParent;\n\t},\n\n\tzIndex: function( zIndex ) {\n\t\tif ( zIndex !== undefined ) {\n\t\t\treturn this.css( \"zIndex\", zIndex );\n\t\t}\n\n\t\tif ( this.length ) {\n\t\t\tvar elem = $( this[ 0 ] ), position, value;\n\t\t\twhile ( elem.length && elem[ 0 ] !== document ) {\n\t\t\t\t// Ignore z-index if position is set to a value where z-index is ignored by the browser\n\t\t\t\t// This makes behavior of this function consistent across browsers\n\t\t\t\t// WebKit always returns auto if the element is positioned\n\t\t\t\tposition = elem.css( \"position\" );\n\t\t\t\tif ( position === \"absolute\" || position === \"relative\" || position === \"fixed\" ) {\n\t\t\t\t\t// IE returns 0 when zIndex is not specified\n\t\t\t\t\t// other browsers return a string\n\t\t\t\t\t// we ignore the case of nested elements with an explicit value of 0\n\t\t\t\t\t// <div style=\"z-index: -10;\"><div style=\"z-index: 0;\"></div></div>\n\t\t\t\t\tvalue = parseInt( elem.css( \"zIndex\" ), 10 );\n\t\t\t\t\tif ( !isNaN( value ) && value !== 0 ) {\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telem = elem.parent();\n\t\t\t}\n\t\t}\n\n\t\treturn 0;\n\t},\n\n\tuniqueId: function() {\n\t\treturn this.each(function() {\n\t\t\tif ( !this.id ) {\n\t\t\t\tthis.id = \"ui-id-\" + (++uuid);\n\t\t\t}\n\t\t});\n\t},\n\n\tremoveUniqueId: function() {\n\t\treturn this.each(function() {\n\t\t\tif ( runiqueId.test( this.id ) ) {\n\t\t\t\t$( this ).removeAttr( \"id\" );\n\t\t\t}\n\t\t});\n\t}\n});\n\n// selectors\nfunction focusable( element, isTabIndexNotNaN ) {\n\tvar map, mapName, img,\n\t\tnodeName = element.nodeName.toLowerCase();\n\tif ( \"area\" === nodeName ) {\n\t\tmap = element.parentNode;\n\t\tmapName = map.name;\n\t\tif ( !element.href || !mapName || map.nodeName.toLowerCase() !== \"map\" ) {\n\t\t\treturn false;\n\t\t}\n\t\timg = $( \"img[usemap=#\" + mapName + \"]\" )[0];\n\t\treturn !!img && visible( img );\n\t}\n\treturn ( /input|select|textarea|button|object/.test( nodeName ) ?\n\t\t!element.disabled :\n\t\t\"a\" === nodeName ?\n\t\t\telement.href || isTabIndexNotNaN :\n\t\t\tisTabIndexNotNaN) &&\n\t\t// the element and all of its ancestors must be visible\n\t\tvisible( element );\n}\n\nfunction visible( element ) {\n\treturn $.expr.filters.visible( element ) &&\n\t\t!$( element ).parents().addBack().filter(function() {\n\t\t\treturn $.css( this, \"visibility\" ) === \"hidden\";\n\t\t}).length;\n}\n\n$.extend( $.expr[ \":\" ], {\n\tdata: $.expr.createPseudo ?\n\t\t$.expr.createPseudo(function( dataName ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn !!$.data( elem, dataName );\n\t\t\t};\n\t\t}) :\n\t\t// support: jQuery <1.8\n\t\tfunction( elem, i, match ) {\n\t\t\treturn !!$.data( elem, match[ 3 ] );\n\t\t},\n\n\tfocusable: function( element ) {\n\t\treturn focusable( element, !isNaN( $.attr( element, \"tabindex\" ) ) );\n\t},\n\n\ttabbable: function( element ) {\n\t\tvar tabIndex = $.attr( element, \"tabindex\" ),\n\t\t\tisTabIndexNaN = isNaN( tabIndex );\n\t\treturn ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );\n\t}\n});\n\n// support: jQuery <1.8\nif ( !$( \"<a>\" ).outerWidth( 1 ).jquery ) {\n\t$.each( [ \"Width\", \"Height\" ], function( i, name ) {\n\t\tvar side = name === \"Width\" ? [ \"Left\", \"Right\" ] : [ \"Top\", \"Bottom\" ],\n\t\t\ttype = name.toLowerCase(),\n\t\t\torig = {\n\t\t\t\tinnerWidth: $.fn.innerWidth,\n\t\t\t\tinnerHeight: $.fn.innerHeight,\n\t\t\t\touterWidth: $.fn.outerWidth,\n\t\t\t\touterHeight: $.fn.outerHeight\n\t\t\t};\n\n\t\tfunction reduce( elem, size, border, margin ) {\n\t\t\t$.each( side, function() {\n\t\t\t\tsize -= parseFloat( $.css( elem, \"padding\" + this ) ) || 0;\n\t\t\t\tif ( border ) {\n\t\t\t\t\tsize -= parseFloat( $.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( margin ) {\n\t\t\t\t\tsize -= parseFloat( $.css( elem, \"margin\" + this ) ) || 0;\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn size;\n\t\t}\n\n\t\t$.fn[ \"inner\" + name ] = function( size ) {\n\t\t\tif ( size === undefined ) {\n\t\t\t\treturn orig[ \"inner\" + name ].call( this );\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\t$( this ).css( type, reduce( this, size ) + \"px\" );\n\t\t\t});\n\t\t};\n\n\t\t$.fn[ \"outer\" + name] = function( size, margin ) {\n\t\t\tif ( typeof size !== \"number\" ) {\n\t\t\t\treturn orig[ \"outer\" + name ].call( this, size );\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\t$( this).css( type, reduce( this, size, true, margin ) + \"px\" );\n\t\t\t});\n\t\t};\n\t});\n}\n\n// support: jQuery <1.8\nif ( !$.fn.addBack ) {\n\t$.fn.addBack = function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t};\n}\n\n// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)\nif ( $( \"<a>\" ).data( \"a-b\", \"a\" ).removeData( \"a-b\" ).data( \"a-b\" ) ) {\n\t$.fn.removeData = (function( removeData ) {\n\t\treturn function( key ) {\n\t\t\tif ( arguments.length ) {\n\t\t\t\treturn removeData.call( this, $.camelCase( key ) );\n\t\t\t} else {\n\t\t\t\treturn removeData.call( this );\n\t\t\t}\n\t\t};\n\t})( $.fn.removeData );\n}\n\n\n\n\n\n// deprecated\n$.ui.ie = !!/msie [\\w.]+/.exec( navigator.userAgent.toLowerCase() );\n\n$.support.selectstart = \"onselectstart\" in document.createElement( \"div\" );\n$.fn.extend({\n\tdisableSelection: function() {\n\t\treturn this.bind( ( $.support.selectstart ? \"selectstart\" : \"mousedown\" ) +\n\t\t\t\".ui-disableSelection\", function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t});\n\t},\n\n\tenableSelection: function() {\n\t\treturn this.unbind( \".ui-disableSelection\" );\n\t}\n});\n\n$.extend( $.ui, {\n\t// $.ui.plugin is deprecated. Use $.widget() extensions instead.\n\tplugin: {\n\t\tadd: function( module, option, set ) {\n\t\t\tvar i,\n\t\t\t\tproto = $.ui[ module ].prototype;\n\t\t\tfor ( i in set ) {\n\t\t\t\tproto.plugins[ i ] = proto.plugins[ i ] || [];\n\t\t\t\tproto.plugins[ i ].push( [ option, set[ i ] ] );\n\t\t\t}\n\t\t},\n\t\tcall: function( instance, name, args ) {\n\t\t\tvar i,\n\t\t\t\tset = instance.plugins[ name ];\n\t\t\tif ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfor ( i = 0; i < set.length; i++ ) {\n\t\t\t\tif ( instance.options[ set[ i ][ 0 ] ] ) {\n\t\t\t\t\tset[ i ][ 1 ].apply( instance.element, args );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// only used by resizable\n\thasScroll: function( el, a ) {\n\n\t\t//If overflow is hidden, the element might have extra content, but the user wants to hide it\n\t\tif ( $( el ).css( \"overflow\" ) === \"hidden\") {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar scroll = ( a && a === \"left\" ) ? \"scrollLeft\" : \"scrollTop\",\n\t\t\thas = false;\n\n\t\tif ( el[ scroll ] > 0 ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// TODO: determine which cases actually cause this to happen\n\t\t// if the element doesn't have the scroll set, see if it's possible to\n\t\t// set the scroll\n\t\tel[ scroll ] = 1;\n\t\thas = ( el[ scroll ] > 0 );\n\t\tel[ scroll ] = 0;\n\t\treturn has;\n\t}\n});\n\n})( jQuery );\n(function( $, undefined ) {\n\nvar uuid = 0,\n\tslice = Array.prototype.slice,\n\t_cleanData = $.cleanData;\n$.cleanData = function( elems ) {\n\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\ttry {\n\t\t\t$( elem ).triggerHandler( \"remove\" );\n\t\t// http://bugs.jquery.com/ticket/8235\n\t\t} catch( e ) {}\n\t}\n\t_cleanData( elems );\n};\n\n$.widget = function( name, base, prototype ) {\n\tvar fullName, existingConstructor, constructor, basePrototype,\n\t\t// proxiedPrototype allows the provided prototype to remain unmodified\n\t\t// so that it can be used as a mixin for multiple widgets (#8876)\n\t\tproxiedPrototype = {},\n\t\tnamespace = name.split( \".\" )[ 0 ];\n\n\tname = name.split( \".\" )[ 1 ];\n\tfullName = namespace + \"-\" + name;\n\n\tif ( !prototype ) {\n\t\tprototype = base;\n\t\tbase = $.Widget;\n\t}\n\n\t// create selector for plugin\n\t$.expr[ \":\" ][ fullName.toLowerCase() ] = function( elem ) {\n\t\treturn !!$.data( elem, fullName );\n\t};\n\n\t$[ namespace ] = $[ namespace ] || {};\n\texistingConstructor = $[ namespace ][ name ];\n\tconstructor = $[ namespace ][ name ] = function( options, element ) {\n\t\t// allow instantiation without \"new\" keyword\n\t\tif ( !this._createWidget ) {\n\t\t\treturn new constructor( options, element );\n\t\t}\n\n\t\t// allow instantiation without initializing for simple inheritance\n\t\t// must use \"new\" keyword (the code above always passes args)\n\t\tif ( arguments.length ) {\n\t\t\tthis._createWidget( options, element );\n\t\t}\n\t};\n\t// extend with the existing constructor to carry over any static properties\n\t$.extend( constructor, existingConstructor, {\n\t\tversion: prototype.version,\n\t\t// copy the object used to create the prototype in case we need to\n\t\t// redefine the widget later\n\t\t_proto: $.extend( {}, prototype ),\n\t\t// track widgets that inherit from this widget in case this widget is\n\t\t// redefined after a widget inherits from it\n\t\t_childConstructors: []\n\t});\n\n\tbasePrototype = new base();\n\t// we need to make the options hash a property directly on the new instance\n\t// otherwise we'll modify the options hash on the prototype that we're\n\t// inheriting from\n\tbasePrototype.options = $.widget.extend( {}, basePrototype.options );\n\t$.each( prototype, function( prop, value ) {\n\t\tif ( !$.isFunction( value ) ) {\n\t\t\tproxiedPrototype[ prop ] = value;\n\t\t\treturn;\n\t\t}\n\t\tproxiedPrototype[ prop ] = (function() {\n\t\t\tvar _super = function() {\n\t\t\t\t\treturn base.prototype[ prop ].apply( this, arguments );\n\t\t\t\t},\n\t\t\t\t_superApply = function( args ) {\n\t\t\t\t\treturn base.prototype[ prop ].apply( this, args );\n\t\t\t\t};\n\t\t\treturn function() {\n\t\t\t\tvar __super = this._super,\n\t\t\t\t\t__superApply = this._superApply,\n\t\t\t\t\treturnValue;\n\n\t\t\t\tthis._super = _super;\n\t\t\t\tthis._superApply = _superApply;\n\n\t\t\t\treturnValue = value.apply( this, arguments );\n\n\t\t\t\tthis._super = __super;\n\t\t\t\tthis._superApply = __superApply;\n\n\t\t\t\treturn returnValue;\n\t\t\t};\n\t\t})();\n\t});\n\tconstructor.prototype = $.widget.extend( basePrototype, {\n\t\t// TODO: remove support for widgetEventPrefix\n\t\t// always use the name + a colon as the prefix, e.g., draggable:start\n\t\t// don't prefix for widgets that aren't DOM-based\n\t\twidgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name\n\t}, proxiedPrototype, {\n\t\tconstructor: constructor,\n\t\tnamespace: namespace,\n\t\twidgetName: name,\n\t\twidgetFullName: fullName\n\t});\n\n\t// If this widget is being redefined then we need to find all widgets that\n\t// are inheriting from it and redefine all of them so that they inherit from\n\t// the new version of this widget. We're essentially trying to replace one\n\t// level in the prototype chain.\n\tif ( existingConstructor ) {\n\t\t$.each( existingConstructor._childConstructors, function( i, child ) {\n\t\t\tvar childPrototype = child.prototype;\n\n\t\t\t// redefine the child widget using the same prototype that was\n\t\t\t// originally used, but inherit from the new version of the base\n\t\t\t$.widget( childPrototype.namespace + \".\" + childPrototype.widgetName, constructor, child._proto );\n\t\t});\n\t\t// remove the list of existing child constructors from the old constructor\n\t\t// so the old child constructors can be garbage collected\n\t\tdelete existingConstructor._childConstructors;\n\t} else {\n\t\tbase._childConstructors.push( constructor );\n\t}\n\n\t$.widget.bridge( name, constructor );\n};\n\n$.widget.extend = function( target ) {\n\tvar input = slice.call( arguments, 1 ),\n\t\tinputIndex = 0,\n\t\tinputLength = input.length,\n\t\tkey,\n\t\tvalue;\n\tfor ( ; inputIndex < inputLength; inputIndex++ ) {\n\t\tfor ( key in input[ inputIndex ] ) {\n\t\t\tvalue = input[ inputIndex ][ key ];\n\t\t\tif ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {\n\t\t\t\t// Clone objects\n\t\t\t\tif ( $.isPlainObject( value ) ) {\n\t\t\t\t\ttarget[ key ] = $.isPlainObject( target[ key ] ) ?\n\t\t\t\t\t\t$.widget.extend( {}, target[ key ], value ) :\n\t\t\t\t\t\t// Don't extend strings, arrays, etc. with objects\n\t\t\t\t\t\t$.widget.extend( {}, value );\n\t\t\t\t// Copy everything else by reference\n\t\t\t\t} else {\n\t\t\t\t\ttarget[ key ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn target;\n};\n\n$.widget.bridge = function( name, object ) {\n\tvar fullName = object.prototype.widgetFullName || name;\n\t$.fn[ name ] = function( options ) {\n\t\tvar isMethodCall = typeof options === \"string\",\n\t\t\targs = slice.call( arguments, 1 ),\n\t\t\treturnValue = this;\n\n\t\t// allow multiple hashes to be passed on init\n\t\toptions = !isMethodCall && args.length ?\n\t\t\t$.widget.extend.apply( null, [ options ].concat(args) ) :\n\t\t\toptions;\n\n\t\tif ( isMethodCall ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar methodValue,\n\t\t\t\t\tinstance = $.data( this, fullName );\n\t\t\t\tif ( !instance ) {\n\t\t\t\t\treturn $.error( \"cannot call methods on \" + name + \" prior to initialization; \" +\n\t\t\t\t\t\t\"attempted to call method '\" + options + \"'\" );\n\t\t\t\t}\n\t\t\t\tif ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === \"_\" ) {\n\t\t\t\t\treturn $.error( \"no such method '\" + options + \"' for \" + name + \" widget instance\" );\n\t\t\t\t}\n\t\t\t\tmethodValue = instance[ options ].apply( instance, args );\n\t\t\t\tif ( methodValue !== instance && methodValue !== undefined ) {\n\t\t\t\t\treturnValue = methodValue && methodValue.jquery ?\n\t\t\t\t\t\treturnValue.pushStack( methodValue.get() ) :\n\t\t\t\t\t\tmethodValue;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tthis.each(function() {\n\t\t\t\tvar instance = $.data( this, fullName );\n\t\t\t\tif ( instance ) {\n\t\t\t\t\tinstance.option( options || {} )._init();\n\t\t\t\t} else {\n\t\t\t\t\t$.data( this, fullName, new object( options, this ) );\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn returnValue;\n\t};\n};\n\n$.Widget = function( /* options, element */ ) {};\n$.Widget._childConstructors = [];\n\n$.Widget.prototype = {\n\twidgetName: \"widget\",\n\twidgetEventPrefix: \"\",\n\tdefaultElement: \"<div>\",\n\toptions: {\n\t\tdisabled: false,\n\n\t\t// callbacks\n\t\tcreate: null\n\t},\n\t_createWidget: function( options, element ) {\n\t\telement = $( element || this.defaultElement || this )[ 0 ];\n\t\tthis.element = $( element );\n\t\tthis.uuid = uuid++;\n\t\tthis.eventNamespace = \".\" + this.widgetName + this.uuid;\n\t\tthis.options = $.widget.extend( {},\n\t\t\tthis.options,\n\t\t\tthis._getCreateOptions(),\n\t\t\toptions );\n\n\t\tthis.bindings = $();\n\t\tthis.hoverable = $();\n\t\tthis.focusable = $();\n\n\t\tif ( element !== this ) {\n\t\t\t$.data( element, this.widgetFullName, this );\n\t\t\tthis._on( true, this.element, {\n\t\t\t\tremove: function( event ) {\n\t\t\t\t\tif ( event.target === element ) {\n\t\t\t\t\t\tthis.destroy();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.document = $( element.style ?\n\t\t\t\t// element within the document\n\t\t\t\telement.ownerDocument :\n\t\t\t\t// element is window or document\n\t\t\t\telement.document || element );\n\t\t\tthis.window = $( this.document[0].defaultView || this.document[0].parentWindow );\n\t\t}\n\n\t\tthis._create();\n\t\tthis._trigger( \"create\", null, this._getCreateEventData() );\n\t\tthis._init();\n\t},\n\t_getCreateOptions: $.noop,\n\t_getCreateEventData: $.noop,\n\t_create: $.noop,\n\t_init: $.noop,\n\n\tdestroy: function() {\n\t\tthis._destroy();\n\t\t// we can probably remove the unbind calls in 2.0\n\t\t// all event bindings should go through this._on()\n\t\tthis.element\n\t\t\t.unbind( this.eventNamespace )\n\t\t\t// 1.9 BC for #7810\n\t\t\t// TODO remove dual storage\n\t\t\t.removeData( this.widgetName )\n\t\t\t.removeData( this.widgetFullName )\n\t\t\t// support: jquery <1.6.3\n\t\t\t// http://bugs.jquery.com/ticket/9413\n\t\t\t.removeData( $.camelCase( this.widgetFullName ) );\n\t\tthis.widget()\n\t\t\t.unbind( this.eventNamespace )\n\t\t\t.removeAttr( \"aria-disabled\" )\n\t\t\t.removeClass(\n\t\t\t\tthis.widgetFullName + \"-disabled \" +\n\t\t\t\t\"ui-state-disabled\" );\n\n\t\t// clean up events and states\n\t\tthis.bindings.unbind( this.eventNamespace );\n\t\tthis.hoverable.removeClass( \"ui-state-hover\" );\n\t\tthis.focusable.removeClass( \"ui-state-focus\" );\n\t},\n\t_destroy: $.noop,\n\n\twidget: function() {\n\t\treturn this.element;\n\t},\n\n\toption: function( key, value ) {\n\t\tvar options = key,\n\t\t\tparts,\n\t\t\tcurOption,\n\t\t\ti;\n\n\t\tif ( arguments.length === 0 ) {\n\t\t\t// don't return a reference to the internal hash\n\t\t\treturn $.widget.extend( {}, this.options );\n\t\t}\n\n\t\tif ( typeof key === \"string\" ) {\n\t\t\t// handle nested keys, e.g., \"foo.bar\" => { foo: { bar: ___ } }\n\t\t\toptions = {};\n\t\t\tparts = key.split( \".\" );\n\t\t\tkey = parts.shift();\n\t\t\tif ( parts.length ) {\n\t\t\t\tcurOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );\n\t\t\t\tfor ( i = 0; i < parts.length - 1; i++ ) {\n\t\t\t\t\tcurOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};\n\t\t\t\t\tcurOption = curOption[ parts[ i ] ];\n\t\t\t\t}\n\t\t\t\tkey = parts.pop();\n\t\t\t\tif ( value === undefined ) {\n\t\t\t\t\treturn curOption[ key ] === undefined ? null : curOption[ key ];\n\t\t\t\t}\n\t\t\t\tcurOption[ key ] = value;\n\t\t\t} else {\n\t\t\t\tif ( value === undefined ) {\n\t\t\t\t\treturn this.options[ key ] === undefined ? null : this.options[ key ];\n\t\t\t\t}\n\t\t\t\toptions[ key ] = value;\n\t\t\t}\n\t\t}\n\n\t\tthis._setOptions( options );\n\n\t\treturn this;\n\t},\n\t_setOptions: function( options ) {\n\t\tvar key;\n\n\t\tfor ( key in options ) {\n\t\t\tthis._setOption( key, options[ key ] );\n\t\t}\n\n\t\treturn this;\n\t},\n\t_setOption: function( key, value ) {\n\t\tthis.options[ key ] = value;\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis.widget()\n\t\t\t\t.toggleClass( this.widgetFullName + \"-disabled ui-state-disabled\", !!value )\n\t\t\t\t.attr( \"aria-disabled\", value );\n\t\t\tthis.hoverable.removeClass( \"ui-state-hover\" );\n\t\t\tthis.focusable.removeClass( \"ui-state-focus\" );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tenable: function() {\n\t\treturn this._setOption( \"disabled\", false );\n\t},\n\tdisable: function() {\n\t\treturn this._setOption( \"disabled\", true );\n\t},\n\n\t_on: function( suppressDisabledCheck, element, handlers ) {\n\t\tvar delegateElement,\n\t\t\tinstance = this;\n\n\t\t// no suppressDisabledCheck flag, shuffle arguments\n\t\tif ( typeof suppressDisabledCheck !== \"boolean\" ) {\n\t\t\thandlers = element;\n\t\t\telement = suppressDisabledCheck;\n\t\t\tsuppressDisabledCheck = false;\n\t\t}\n\n\t\t// no element argument, shuffle and use this.element\n\t\tif ( !handlers ) {\n\t\t\thandlers = element;\n\t\t\telement = this.element;\n\t\t\tdelegateElement = this.widget();\n\t\t} else {\n\t\t\t// accept selectors, DOM elements\n\t\t\telement = delegateElement = $( element );\n\t\t\tthis.bindings = this.bindings.add( element );\n\t\t}\n\n\t\t$.each( handlers, function( event, handler ) {\n\t\t\tfunction handlerProxy() {\n\t\t\t\t// allow widgets to customize the disabled handling\n\t\t\t\t// - disabled as an array instead of boolean\n\t\t\t\t// - disabled class as method for disabling individual parts\n\t\t\t\tif ( !suppressDisabledCheck &&\n\t\t\t\t\t\t( instance.options.disabled === true ||\n\t\t\t\t\t\t\t$( this ).hasClass( \"ui-state-disabled\" ) ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t\t.apply( instance, arguments );\n\t\t\t}\n\n\t\t\t// copy the guid so direct unbinding works\n\t\t\tif ( typeof handler !== \"string\" ) {\n\t\t\t\thandlerProxy.guid = handler.guid =\n\t\t\t\t\thandler.guid || handlerProxy.guid || $.guid++;\n\t\t\t}\n\n\t\t\tvar match = event.match( /^(\\w+)\\s*(.*)$/ ),\n\t\t\t\teventName = match[1] + instance.eventNamespace,\n\t\t\t\tselector = match[2];\n\t\t\tif ( selector ) {\n\t\t\t\tdelegateElement.delegate( selector, eventName, handlerProxy );\n\t\t\t} else {\n\t\t\t\telement.bind( eventName, handlerProxy );\n\t\t\t}\n\t\t});\n\t},\n\n\t_off: function( element, eventName ) {\n\t\teventName = (eventName || \"\").split( \" \" ).join( this.eventNamespace + \" \" ) + this.eventNamespace;\n\t\telement.unbind( eventName ).undelegate( eventName );\n\t},\n\n\t_delay: function( handler, delay ) {\n\t\tfunction handlerProxy() {\n\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t.apply( instance, arguments );\n\t\t}\n\t\tvar instance = this;\n\t\treturn setTimeout( handlerProxy, delay || 0 );\n\t},\n\n\t_hoverable: function( element ) {\n\t\tthis.hoverable = this.hoverable.add( element );\n\t\tthis._on( element, {\n\t\t\tmouseenter: function( event ) {\n\t\t\t\t$( event.currentTarget ).addClass( \"ui-state-hover\" );\n\t\t\t},\n\t\t\tmouseleave: function( event ) {\n\t\t\t\t$( event.currentTarget ).removeClass( \"ui-state-hover\" );\n\t\t\t}\n\t\t});\n\t},\n\n\t_focusable: function( element ) {\n\t\tthis.focusable = this.focusable.add( element );\n\t\tthis._on( element, {\n\t\t\tfocusin: function( event ) {\n\t\t\t\t$( event.currentTarget ).addClass( \"ui-state-focus\" );\n\t\t\t},\n\t\t\tfocusout: function( event ) {\n\t\t\t\t$( event.currentTarget ).removeClass( \"ui-state-focus\" );\n\t\t\t}\n\t\t});\n\t},\n\n\t_trigger: function( type, event, data ) {\n\t\tvar prop, orig,\n\t\t\tcallback = this.options[ type ];\n\n\t\tdata = data || {};\n\t\tevent = $.Event( event );\n\t\tevent.type = ( type === this.widgetEventPrefix ?\n\t\t\ttype :\n\t\t\tthis.widgetEventPrefix + type ).toLowerCase();\n\t\t// the original event may come from any element\n\t\t// so we need to reset the target on the new event\n\t\tevent.target = this.element[ 0 ];\n\n\t\t// copy original event properties over to the new event\n\t\torig = event.originalEvent;\n\t\tif ( orig ) {\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tif ( !( prop in event ) ) {\n\t\t\t\t\tevent[ prop ] = orig[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.element.trigger( event, data );\n\t\treturn !( $.isFunction( callback ) &&\n\t\t\tcallback.apply( this.element[0], [ event ].concat( data ) ) === false ||\n\t\t\tevent.isDefaultPrevented() );\n\t}\n};\n\n$.each( { show: \"fadeIn\", hide: \"fadeOut\" }, function( method, defaultEffect ) {\n\t$.Widget.prototype[ \"_\" + method ] = function( element, options, callback ) {\n\t\tif ( typeof options === \"string\" ) {\n\t\t\toptions = { effect: options };\n\t\t}\n\t\tvar hasOptions,\n\t\t\teffectName = !options ?\n\t\t\t\tmethod :\n\t\t\t\toptions === true || typeof options === \"number\" ?\n\t\t\t\t\tdefaultEffect :\n\t\t\t\t\toptions.effect || defaultEffect;\n\t\toptions = options || {};\n\t\tif ( typeof options === \"number\" ) {\n\t\t\toptions = { duration: options };\n\t\t}\n\t\thasOptions = !$.isEmptyObject( options );\n\t\toptions.complete = callback;\n\t\tif ( options.delay ) {\n\t\t\telement.delay( options.delay );\n\t\t}\n\t\tif ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {\n\t\t\telement[ method ]( options );\n\t\t} else if ( effectName !== method && element[ effectName ] ) {\n\t\t\telement[ effectName ]( options.duration, options.easing, callback );\n\t\t} else {\n\t\t\telement.queue(function( next ) {\n\t\t\t\t$( this )[ method ]();\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback.call( element[ 0 ] );\n\t\t\t\t}\n\t\t\t\tnext();\n\t\t\t});\n\t\t}\n\t};\n});\n\n})( jQuery );\n(function( $, undefined ) {\n\nvar mouseHandled = false;\n$( document ).mouseup( function() {\n\tmouseHandled = false;\n});\n\n$.widget(\"ui.mouse\", {\n\tversion: \"1.10.3\",\n\toptions: {\n\t\tcancel: \"input,textarea,button,select,option\",\n\t\tdistance: 1,\n\t\tdelay: 0\n\t},\n\t_mouseInit: function() {\n\t\tvar that = this;\n\n\t\tthis.element\n\t\t\t.bind(\"mousedown.\"+this.widgetName, function(event) {\n\t\t\t\treturn that._mouseDown(event);\n\t\t\t})\n\t\t\t.bind(\"click.\"+this.widgetName, function(event) {\n\t\t\t\tif (true === $.data(event.target, that.widgetName + \".preventClickEvent\")) {\n\t\t\t\t\t$.removeData(event.target, that.widgetName + \".preventClickEvent\");\n\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\n\t\tthis.started = false;\n\t},\n\n\t// TODO: make sure destroying one instance of mouse doesn't mess with\n\t// other instances of mouse\n\t_mouseDestroy: function() {\n\t\tthis.element.unbind(\".\"+this.widgetName);\n\t\tif ( this._mouseMoveDelegate ) {\n\t\t\t$(document)\n\t\t\t\t.unbind(\"mousemove.\"+this.widgetName, this._mouseMoveDelegate)\n\t\t\t\t.unbind(\"mouseup.\"+this.widgetName, this._mouseUpDelegate);\n\t\t}\n\t},\n\n\t_mouseDown: function(event) {\n\t\t// don't let more than one widget handle mouseStart\n\t\tif( mouseHandled ) { return; }\n\n\t\t// we may have missed mouseup (out of window)\n\t\t(this._mouseStarted && this._mouseUp(event));\n\n\t\tthis._mouseDownEvent = event;\n\n\t\tvar that = this,\n\t\t\tbtnIsLeft = (event.which === 1),\n\t\t\t// event.target.nodeName works around a bug in IE 8 with\n\t\t\t// disabled inputs (#7620)\n\t\t\telIsCancel = (typeof this.options.cancel === \"string\" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);\n\t\tif (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tthis.mouseDelayMet = !this.options.delay;\n\t\tif (!this.mouseDelayMet) {\n\t\t\tthis._mouseDelayTimer = setTimeout(function() {\n\t\t\t\tthat.mouseDelayMet = true;\n\t\t\t}, this.options.delay);\n\t\t}\n\n\t\tif (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {\n\t\t\tthis._mouseStarted = (this._mouseStart(event) !== false);\n\t\t\tif (!this._mouseStarted) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// Click event may never have fired (Gecko & Opera)\n\t\tif (true === $.data(event.target, this.widgetName + \".preventClickEvent\")) {\n\t\t\t$.removeData(event.target, this.widgetName + \".preventClickEvent\");\n\t\t}\n\n\t\t// these delegates are required to keep context\n\t\tthis._mouseMoveDelegate = function(event) {\n\t\t\treturn that._mouseMove(event);\n\t\t};\n\t\tthis._mouseUpDelegate = function(event) {\n\t\t\treturn that._mouseUp(event);\n\t\t};\n\t\t$(document)\n\t\t\t.bind(\"mousemove.\"+this.widgetName, this._mouseMoveDelegate)\n\t\t\t.bind(\"mouseup.\"+this.widgetName, this._mouseUpDelegate);\n\n\t\tevent.preventDefault();\n\n\t\tmouseHandled = true;\n\t\treturn true;\n\t},\n\n\t_mouseMove: function(event) {\n\t\t// IE mouseup check - mouseup happened when mouse was out of window\n\t\tif ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {\n\t\t\treturn this._mouseUp(event);\n\t\t}\n\n\t\tif (this._mouseStarted) {\n\t\t\tthis._mouseDrag(event);\n\t\t\treturn event.preventDefault();\n\t\t}\n\n\t\tif (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {\n\t\t\tthis._mouseStarted =\n\t\t\t\t(this._mouseStart(this._mouseDownEvent, event) !== false);\n\t\t\t(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));\n\t\t}\n\n\t\treturn !this._mouseStarted;\n\t},\n\n\t_mouseUp: function(event) {\n\t\t$(document)\n\t\t\t.unbind(\"mousemove.\"+this.widgetName, this._mouseMoveDelegate)\n\t\t\t.unbind(\"mouseup.\"+this.widgetName, this._mouseUpDelegate);\n\n\t\tif (this._mouseStarted) {\n\t\t\tthis._mouseStarted = false;\n\n\t\t\tif (event.target === this._mouseDownEvent.target) {\n\t\t\t\t$.data(event.target, this.widgetName + \".preventClickEvent\", true);\n\t\t\t}\n\n\t\t\tthis._mouseStop(event);\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_mouseDistanceMet: function(event) {\n\t\treturn (Math.max(\n\t\t\t\tMath.abs(this._mouseDownEvent.pageX - event.pageX),\n\t\t\t\tMath.abs(this._mouseDownEvent.pageY - event.pageY)\n\t\t\t) >= this.options.distance\n\t\t);\n\t},\n\n\t_mouseDelayMet: function(/* event */) {\n\t\treturn this.mouseDelayMet;\n\t},\n\n\t// These are placeholder methods, to be overriden by extending plugin\n\t_mouseStart: function(/* event */) {},\n\t_mouseDrag: function(/* event */) {},\n\t_mouseStop: function(/* event */) {},\n\t_mouseCapture: function(/* event */) { return true; }\n});\n\n})(jQuery);\n(function( $, undefined ) {\n\n/*jshint loopfunc: true */\n\nfunction isOverAxis( x, reference, size ) {\n\treturn ( x > reference ) && ( x < ( reference + size ) );\n}\n\nfunction isFloating(item) {\n\treturn (/left|right/).test(item.css(\"float\")) || (/inline|table-cell/).test(item.css(\"display\"));\n}\n\n$.widget(\"ui.sortable\", $.ui.mouse, {\n\tversion: \"1.10.3\",\n\twidgetEventPrefix: \"sort\",\n\tready: false,\n\toptions: {\n\t\tappendTo: \"parent\",\n\t\taxis: false,\n\t\tconnectWith: false,\n\t\tcontainment: false,\n\t\tcursor: \"auto\",\n\t\tcursorAt: false,\n\t\tdropOnEmpty: true,\n\t\tforcePlaceholderSize: false,\n\t\tforceHelperSize: false,\n\t\tgrid: false,\n\t\thandle: false,\n\t\thelper: \"original\",\n\t\titems: \"> *\",\n\t\topacity: false,\n\t\tplaceholder: false,\n\t\trevert: false,\n\t\tscroll: true,\n\t\tscrollSensitivity: 20,\n\t\tscrollSpeed: 20,\n\t\tscope: \"default\",\n\t\ttolerance: \"intersect\",\n\t\tzIndex: 1000,\n\n\t\t// callbacks\n\t\tactivate: null,\n\t\tbeforeStop: null,\n\t\tchange: null,\n\t\tdeactivate: null,\n\t\tout: null,\n\t\tover: null,\n\t\treceive: null,\n\t\tremove: null,\n\t\tsort: null,\n\t\tstart: null,\n\t\tstop: null,\n\t\tupdate: null\n\t},\n\t_create: function() {\n\n\t\tvar o = this.options;\n\t\tthis.containerCache = {};\n\t\tthis.element.addClass(\"ui-sortable\");\n\n\t\t//Get the items\n\t\tthis.refresh();\n\n\t\t//Let's determine if the items are being displayed horizontally\n\t\tthis.floating = this.items.length ? o.axis === \"x\" || isFloating(this.items[0].item) : false;\n\n\t\t//Let's determine the parent's offset\n\t\tthis.offset = this.element.offset();\n\n\t\t//Initialize mouse events for interaction\n\t\tthis._mouseInit();\n\n\t\t//We're ready to go\n\t\tthis.ready = true;\n\n\t},\n\n\t_destroy: function() {\n\t\tthis.element\n\t\t\t.removeClass(\"ui-sortable ui-sortable-disabled\");\n\t\tthis._mouseDestroy();\n\n\t\tfor ( var i = this.items.length - 1; i >= 0; i-- ) {\n\t\t\tthis.items[i].item.removeData(this.widgetName + \"-item\");\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_setOption: function(key, value){\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis.options[ key ] = value;\n\n\t\t\tthis.widget().toggleClass( \"ui-sortable-disabled\", !!value );\n\t\t} else {\n\t\t\t// Don't call widget base _setOption for disable as it adds ui-state-disabled class\n\t\t\t$.Widget.prototype._setOption.apply(this, arguments);\n\t\t}\n\t},\n\n\t_mouseCapture: function(event, overrideHandle) {\n\t\tvar currentItem = null,\n\t\t\tvalidHandle = false,\n\t\t\tthat = this;\n\n\t\tif (this.reverting) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif(this.options.disabled || this.options.type === \"static\") {\n\t\t\treturn false;\n\t\t}\n\n\t\t//We have to refresh the items data once first\n\t\tthis._refreshItems(event);\n\n\t\t//Find out if the clicked node (or one of its parents) is a actual item in this.items\n\t\t$(event.target).parents().each(function() {\n\t\t\tif($.data(this, that.widgetName + \"-item\") === that) {\n\t\t\t\tcurrentItem = $(this);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tif($.data(event.target, that.widgetName + \"-item\") === that) {\n\t\t\tcurrentItem = $(event.target);\n\t\t}\n\n\t\tif(!currentItem) {\n\t\t\treturn false;\n\t\t}\n\t\tif(this.options.handle && !overrideHandle) {\n\t\t\t$(this.options.handle, currentItem).find(\"*\").addBack().each(function() {\n\t\t\t\tif(this === event.target) {\n\t\t\t\t\tvalidHandle = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\tif(!validHandle) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.currentItem = currentItem;\n\t\tthis._removeCurrentsFromItems();\n\t\treturn true;\n\n\t},\n\n\t_mouseStart: function(event, overrideHandle, noActivation) {\n\n\t\tvar i, body,\n\t\t\to = this.options;\n\n\t\tthis.currentContainer = this;\n\n\t\t//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture\n\t\tthis.refreshPositions();\n\n\t\t//Create and append the visible helper\n\t\tthis.helper = this._createHelper(event);\n\n\t\t//Cache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t/*\n\t\t * - Position generation -\n\t\t * This block generates everything position related - it's the core of draggables.\n\t\t */\n\n\t\t//Cache the margins of the original element\n\t\tthis._cacheMargins();\n\n\t\t//Get the next scrolling parent\n\t\tthis.scrollParent = this.helper.scrollParent();\n\n\t\t//The element's absolute position on the page minus margins\n\t\tthis.offset = this.currentItem.offset();\n\t\tthis.offset = {\n\t\t\ttop: this.offset.top - this.margins.top,\n\t\t\tleft: this.offset.left - this.margins.left\n\t\t};\n\n\t\t$.extend(this.offset, {\n\t\t\tclick: { //Where the click happened, relative to the element\n\t\t\t\tleft: event.pageX - this.offset.left,\n\t\t\t\ttop: event.pageY - this.offset.top\n\t\t\t},\n\t\t\tparent: this._getParentOffset(),\n\t\t\trelative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper\n\t\t});\n\n\t\t// Only after we got the offset, we can change the helper's position to absolute\n\t\t// TODO: Still need to figure out a way to make relative sorting possible\n\t\tthis.helper.css(\"position\", \"absolute\");\n\t\tthis.cssPosition = this.helper.css(\"position\");\n\n\t\t//Generate the original position\n\t\tthis.originalPosition = this._generatePosition(event);\n\t\tthis.originalPageX = event.pageX;\n\t\tthis.originalPageY = event.pageY;\n\n\t\t//Adjust the mouse offset relative to the helper if \"cursorAt\" is supplied\n\t\t(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));\n\n\t\t//Cache the former DOM position\n\t\tthis.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };\n\n\t\t//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way\n\t\tif(this.helper[0] !== this.currentItem[0]) {\n\t\t\tthis.currentItem.hide();\n\t\t}\n\n\t\t//Create the placeholder\n\t\tthis._createPlaceholder();\n\n\t\t//Set a containment if given in the options\n\t\tif(o.containment) {\n\t\t\tthis._setContainment();\n\t\t}\n\n\t\tif( o.cursor && o.cursor !== \"auto\" ) { // cursor option\n\t\t\tbody = this.document.find( \"body\" );\n\n\t\t\t// support: IE\n\t\t\tthis.storedCursor = body.css( \"cursor\" );\n\t\t\tbody.css( \"cursor\", o.cursor );\n\n\t\t\tthis.storedStylesheet = $( \"<style>*{ cursor: \"+o.cursor+\" !important; }</style>\" ).appendTo( body );\n\t\t}\n\n\t\tif(o.opacity) { // opacity option\n\t\t\tif (this.helper.css(\"opacity\")) {\n\t\t\t\tthis._storedOpacity = this.helper.css(\"opacity\");\n\t\t\t}\n\t\t\tthis.helper.css(\"opacity\", o.opacity);\n\t\t}\n\n\t\tif(o.zIndex) { // zIndex option\n\t\t\tif (this.helper.css(\"zIndex\")) {\n\t\t\t\tthis._storedZIndex = this.helper.css(\"zIndex\");\n\t\t\t}\n\t\t\tthis.helper.css(\"zIndex\", o.zIndex);\n\t\t}\n\n\t\t//Prepare scrolling\n\t\tif(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== \"HTML\") {\n\t\t\tthis.overflowOffset = this.scrollParent.offset();\n\t\t}\n\n\t\t//Call callbacks\n\t\tthis._trigger(\"start\", event, this._uiHash());\n\n\t\t//Recache the helper size\n\t\tif(!this._preserveHelperProportions) {\n\t\t\tthis._cacheHelperProportions();\n\t\t}\n\n\n\t\t//Post \"activate\" events to possible containers\n\t\tif( !noActivation ) {\n\t\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\t\tthis.containers[ i ]._trigger( \"activate\", event, this._uiHash( this ) );\n\t\t\t}\n\t\t}\n\n\t\t//Prepare possible droppables\n\t\tif($.ui.ddmanager) {\n\t\t\t$.ui.ddmanager.current = this;\n\t\t}\n\n\t\tif ($.ui.ddmanager && !o.dropBehaviour) {\n\t\t\t$.ui.ddmanager.prepareOffsets(this, event);\n\t\t}\n\n\t\tthis.dragging = true;\n\n\t\tthis.helper.addClass(\"ui-sortable-helper\");\n\t\tthis._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position\n\t\treturn true;\n\n\t},\n\n\t_mouseDrag: function(event) {\n\t\tvar i, item, itemElement, intersection,\n\t\t\to = this.options,\n\t\t\tscrolled = false;\n\n\t\t//Compute the helpers position\n\t\tthis.position = this._generatePosition(event);\n\t\tthis.positionAbs = this._convertPositionTo(\"absolute\");\n\n\t\tif (!this.lastPositionAbs) {\n\t\t\tthis.lastPositionAbs = this.positionAbs;\n\t\t}\n\n\t\t//Do scrolling\n\t\tif(this.options.scroll) {\n\t\t\tif(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== \"HTML\") {\n\n\t\t\t\tif((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {\n\t\t\t\t\tthis.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;\n\t\t\t\t} else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {\n\t\t\t\t\tthis.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;\n\t\t\t\t}\n\n\t\t\t\tif((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {\n\t\t\t\t\tthis.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;\n\t\t\t\t} else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {\n\t\t\t\t\tthis.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {\n\t\t\t\t\tscrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);\n\t\t\t\t} else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {\n\t\t\t\t\tscrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);\n\t\t\t\t}\n\n\t\t\t\tif(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {\n\t\t\t\t\tscrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);\n\t\t\t\t} else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {\n\t\t\t\t\tscrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {\n\t\t\t\t$.ui.ddmanager.prepareOffsets(this, event);\n\t\t\t}\n\t\t}\n\n\t\t//Regenerate the absolute position used for position checks\n\t\tthis.positionAbs = this._convertPositionTo(\"absolute\");\n\n\t\t//Set the helper position\n\t\tif(!this.options.axis || this.options.axis !== \"y\") {\n\t\t\tthis.helper[0].style.left = this.position.left+\"px\";\n\t\t}\n\t\tif(!this.options.axis || this.options.axis !== \"x\") {\n\t\t\tthis.helper[0].style.top = this.position.top+\"px\";\n\t\t}\n\n\t\t//Rearrange\n\t\tfor (i = this.items.length - 1; i >= 0; i--) {\n\n\t\t\t//Cache variables and intersection, continue if no intersection\n\t\t\titem = this.items[i];\n\t\t\titemElement = item.item[0];\n\t\t\tintersection = this._intersectsWithPointer(item);\n\t\t\tif (!intersection) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Only put the placeholder inside the current Container, skip all\n\t\t\t// items form other containers. This works because when moving\n\t\t\t// an item from one container to another the\n\t\t\t// currentContainer is switched before the placeholder is moved.\n\t\t\t//\n\t\t\t// Without this moving items in \"sub-sortables\" can cause the placeholder to jitter\n\t\t\t// beetween the outer and inner container.\n\t\t\tif (item.instance !== this.currentContainer) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// cannot intersect with itself\n\t\t\t// no useless actions that have been done before\n\t\t\t// no action if the item moved is the parent of the item checked\n\t\t\tif (itemElement !== this.currentItem[0] &&\n\t\t\t\tthis.placeholder[intersection === 1 ? \"next\" : \"prev\"]()[0] !== itemElement &&\n\t\t\t\t!$.contains(this.placeholder[0], itemElement) &&\n\t\t\t\t(this.options.type === \"semi-dynamic\" ? !$.contains(this.element[0], itemElement) : true)\n\t\t\t) {\n\n\t\t\t\tthis.direction = intersection === 1 ? \"down\" : \"up\";\n\n\t\t\t\tif (this.options.tolerance === \"pointer\" || this._intersectsWithSides(item)) {\n\t\t\t\t\tthis._rearrange(event, item);\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis._trigger(\"change\", event, this._uiHash());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//Post events to containers\n\t\tthis._contactContainers(event);\n\n\t\t//Interconnect with droppables\n\t\tif($.ui.ddmanager) {\n\t\t\t$.ui.ddmanager.drag(this, event);\n\t\t}\n\n\t\t//Call callbacks\n\t\tthis._trigger(\"sort\", event, this._uiHash());\n\n\t\tthis.lastPositionAbs = this.positionAbs;\n\t\treturn false;\n\n\t},\n\n\t_mouseStop: function(event, noPropagation) {\n\n\t\tif(!event) {\n\t\t\treturn;\n\t\t}\n\n\t\t//If we are using droppables, inform the manager about the drop\n\t\tif ($.ui.ddmanager && !this.options.dropBehaviour) {\n\t\t\t$.ui.ddmanager.drop(this, event);\n\t\t}\n\n\t\tif(this.options.revert) {\n\t\t\tvar that = this,\n\t\t\t\tcur = this.placeholder.offset(),\n\t\t\t\taxis = this.options.axis,\n\t\t\t\tanimation = {};\n\n\t\t\tif ( !axis || axis === \"x\" ) {\n\t\t\t\tanimation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);\n\t\t\t}\n\t\t\tif ( !axis || axis === \"y\" ) {\n\t\t\t\tanimation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);\n\t\t\t}\n\t\t\tthis.reverting = true;\n\t\t\t$(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {\n\t\t\t\tthat._clear(event);\n\t\t\t});\n\t\t} else {\n\t\t\tthis._clear(event, noPropagation);\n\t\t}\n\n\t\treturn false;\n\n\t},\n\n\tcancel: function() {\n\n\t\tif(this.dragging) {\n\n\t\t\tthis._mouseUp({ target: null });\n\n\t\t\tif(this.options.helper === \"original\") {\n\t\t\t\tthis.currentItem.css(this._storedCSS).removeClass(\"ui-sortable-helper\");\n\t\t\t} else {\n\t\t\t\tthis.currentItem.show();\n\t\t\t}\n\n\t\t\t//Post deactivating events to containers\n\t\t\tfor (var i = this.containers.length - 1; i >= 0; i--){\n\t\t\t\tthis.containers[i]._trigger(\"deactivate\", null, this._uiHash(this));\n\t\t\t\tif(this.containers[i].containerCache.over) {\n\t\t\t\t\tthis.containers[i]._trigger(\"out\", null, this._uiHash(this));\n\t\t\t\t\tthis.containers[i].containerCache.over = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tif (this.placeholder) {\n\t\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!\n\t\t\tif(this.placeholder[0].parentNode) {\n\t\t\t\tthis.placeholder[0].parentNode.removeChild(this.placeholder[0]);\n\t\t\t}\n\t\t\tif(this.options.helper !== \"original\" && this.helper && this.helper[0].parentNode) {\n\t\t\t\tthis.helper.remove();\n\t\t\t}\n\n\t\t\t$.extend(this, {\n\t\t\t\thelper: null,\n\t\t\t\tdragging: false,\n\t\t\t\treverting: false,\n\t\t\t\t_noFinalSort: null\n\t\t\t});\n\n\t\t\tif(this.domPosition.prev) {\n\t\t\t\t$(this.domPosition.prev).after(this.currentItem);\n\t\t\t} else {\n\t\t\t\t$(this.domPosition.parent).prepend(this.currentItem);\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tserialize: function(o) {\n\n\t\tvar items = this._getItemsAsjQuery(o && o.connected),\n\t\t\tstr = [];\n\t\to = o || {};\n\n\t\t$(items).each(function() {\n\t\t\tvar res = ($(o.item || this).attr(o.attribute || \"id\") || \"\").match(o.expression || (/(.+)[\\-=_](.+)/));\n\t\t\tif (res) {\n\t\t\t\tstr.push((o.key || res[1]+\"[]\")+\"=\"+(o.key && o.expression ? res[1] : res[2]));\n\t\t\t}\n\t\t});\n\n\t\tif(!str.length && o.key) {\n\t\t\tstr.push(o.key + \"=\");\n\t\t}\n\n\t\treturn str.join(\"&\");\n\n\t},\n\n\ttoArray: function(o) {\n\n\t\tvar items = this._getItemsAsjQuery(o && o.connected),\n\t\t\tret = [];\n\n\t\to = o || {};\n\n\t\titems.each(function() { ret.push($(o.item || this).attr(o.attribute || \"id\") || \"\"); });\n\t\treturn ret;\n\n\t},\n\n\t/* Be careful with the following core functions */\n\t_intersectsWith: function(item) {\n\n\t\tvar x1 = this.positionAbs.left,\n\t\t\tx2 = x1 + this.helperProportions.width,\n\t\t\ty1 = this.positionAbs.top,\n\t\t\ty2 = y1 + this.helperProportions.height,\n\t\t\tl = item.left,\n\t\t\tr = l + item.width,\n\t\t\tt = item.top,\n\t\t\tb = t + item.height,\n\t\t\tdyClick = this.offset.click.top,\n\t\t\tdxClick = this.offset.click.left,\n\t\t\tisOverElementHeight = ( this.options.axis === \"x\" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),\n\t\t\tisOverElementWidth = ( this.options.axis === \"y\" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),\n\t\t\tisOverElement = isOverElementHeight && isOverElementWidth;\n\n\t\tif ( this.options.tolerance === \"pointer\" ||\n\t\t\tthis.options.forcePointerForContainers ||\n\t\t\t(this.options.tolerance !== \"pointer\" && this.helperProportions[this.floating ? \"width\" : \"height\"] > item[this.floating ? \"width\" : \"height\"])\n\t\t) {\n\t\t\treturn isOverElement;\n\t\t} else {\n\n\t\t\treturn (l < x1 + (this.helperProportions.width / 2) && // Right Half\n\t\t\t\tx2 - (this.helperProportions.width / 2) < r && // Left Half\n\t\t\t\tt < y1 + (this.helperProportions.height / 2) && // Bottom Half\n\t\t\t\ty2 - (this.helperProportions.height / 2) < b ); // Top Half\n\n\t\t}\n\t},\n\n\t_intersectsWithPointer: function(item) {\n\n\t\tvar isOverElementHeight = (this.options.axis === \"x\") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),\n\t\t\tisOverElementWidth = (this.options.axis === \"y\") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),\n\t\t\tisOverElement = isOverElementHeight && isOverElementWidth,\n\t\t\tverticalDirection = this._getDragVerticalDirection(),\n\t\t\thorizontalDirection = this._getDragHorizontalDirection();\n\n\t\tif (!isOverElement) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.floating ?\n\t\t\t( ((horizontalDirection && horizontalDirection === \"right\") || verticalDirection === \"down\") ? 2 : 1 )\n\t\t\t: ( verticalDirection && (verticalDirection === \"down\" ? 2 : 1) );\n\n\t},\n\n\t_intersectsWithSides: function(item) {\n\n\t\tvar isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),\n\t\t\tisOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),\n\t\t\tverticalDirection = this._getDragVerticalDirection(),\n\t\t\thorizontalDirection = this._getDragHorizontalDirection();\n\n\t\tif (this.floating && horizontalDirection) {\n\t\t\treturn ((horizontalDirection === \"right\" && isOverRightHalf) || (horizontalDirection === \"left\" && !isOverRightHalf));\n\t\t} else {\n\t\t\treturn verticalDirection && ((verticalDirection === \"down\" && isOverBottomHalf) || (verticalDirection === \"up\" && !isOverBottomHalf));\n\t\t}\n\n\t},\n\n\t_getDragVerticalDirection: function() {\n\t\tvar delta = this.positionAbs.top - this.lastPositionAbs.top;\n\t\treturn delta !== 0 && (delta > 0 ? \"down\" : \"up\");\n\t},\n\n\t_getDragHorizontalDirection: function() {\n\t\tvar delta = this.positionAbs.left - this.lastPositionAbs.left;\n\t\treturn delta !== 0 && (delta > 0 ? \"right\" : \"left\");\n\t},\n\n\trefresh: function(event) {\n\t\tthis._refreshItems(event);\n\t\tthis.refreshPositions();\n\t\treturn this;\n\t},\n\n\t_connectWith: function() {\n\t\tvar options = this.options;\n\t\treturn options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;\n\t},\n\n\t_getItemsAsjQuery: function(connected) {\n\n\t\tvar i, j, cur, inst,\n\t\t\titems = [],\n\t\t\tqueries = [],\n\t\t\tconnectWith = this._connectWith();\n\n\t\tif(connectWith && connected) {\n\t\t\tfor (i = connectWith.length - 1; i >= 0; i--){\n\t\t\t\tcur = $(connectWith[i]);\n\t\t\t\tfor ( j = cur.length - 1; j >= 0; j--){\n\t\t\t\t\tinst = $.data(cur[j], this.widgetFullName);\n\t\t\t\t\tif(inst && inst !== this && !inst.options.disabled) {\n\t\t\t\t\t\tqueries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(\".ui-sortable-helper\").not(\".ui-sortable-placeholder\"), inst]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tqueries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(\".ui-sortable-helper\").not(\".ui-sortable-placeholder\"), this]);\n\n\t\tfor (i = queries.length - 1; i >= 0; i--){\n\t\t\tqueries[i][0].each(function() {\n\t\t\t\titems.push(this);\n\t\t\t});\n\t\t}\n\n\t\treturn $(items);\n\n\t},\n\n\t_removeCurrentsFromItems: function() {\n\n\t\tvar list = this.currentItem.find(\":data(\" + this.widgetName + \"-item)\");\n\n\t\tthis.items = $.grep(this.items, function (item) {\n\t\t\tfor (var j=0; j < list.length; j++) {\n\t\t\t\tif(list[j] === item.item[0]) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t});\n\n\t},\n\n\t_refreshItems: function(event) {\n\n\t\tthis.items = [];\n\t\tthis.containers = [this];\n\n\t\tvar i, j, cur, inst, targetData, _queries, item, queriesLength,\n\t\t\titems = this.items,\n\t\t\tqueries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],\n\t\t\tconnectWith = this._connectWith();\n\n\t\tif(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down\n\t\t\tfor (i = connectWith.length - 1; i >= 0; i--){\n\t\t\t\tcur = $(connectWith[i]);\n\t\t\t\tfor (j = cur.length - 1; j >= 0; j--){\n\t\t\t\t\tinst = $.data(cur[j], this.widgetFullName);\n\t\t\t\t\tif(inst && inst !== this && !inst.options.disabled) {\n\t\t\t\t\t\tqueries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);\n\t\t\t\t\t\tthis.containers.push(inst);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (i = queries.length - 1; i >= 0; i--) {\n\t\t\ttargetData = queries[i][1];\n\t\t\t_queries = queries[i][0];\n\n\t\t\tfor (j=0, queriesLength = _queries.length; j < queriesLength; j++) {\n\t\t\t\titem = $(_queries[j]);\n\n\t\t\t\titem.data(this.widgetName + \"-item\", targetData); // Data for target checking (mouse manager)\n\n\t\t\t\titems.push({\n\t\t\t\t\titem: item,\n\t\t\t\t\tinstance: targetData,\n\t\t\t\t\twidth: 0, height: 0,\n\t\t\t\t\tleft: 0, top: 0\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t},\n\n\trefreshPositions: function(fast) {\n\n\t\t//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change\n\t\tif(this.offsetParent && this.helper) {\n\t\t\tthis.offset.parent = this._getParentOffset();\n\t\t}\n\n\t\tvar i, item, t, p;\n\n\t\tfor (i = this.items.length - 1; i >= 0; i--){\n\t\t\titem = this.items[i];\n\n\t\t\t//We ignore calculating positions of all connected containers when we're not over them\n\t\t\tif(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tt = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;\n\n\t\t\tif (!fast) {\n\t\t\t\titem.width = t.outerWidth();\n\t\t\t\titem.height = t.outerHeight();\n\t\t\t}\n\n\t\t\tp = t.offset();\n\t\t\titem.left = p.left;\n\t\t\titem.top = p.top;\n\t\t}\n\n\t\tif(this.options.custom && this.options.custom.refreshContainers) {\n\t\t\tthis.options.custom.refreshContainers.call(this);\n\t\t} else {\n\t\t\tfor (i = this.containers.length - 1; i >= 0; i--){\n\t\t\t\tp = this.containers[i].element.offset();\n\t\t\t\tthis.containers[i].containerCache.left = p.left;\n\t\t\t\tthis.containers[i].containerCache.top = p.top;\n\t\t\t\tthis.containers[i].containerCache.width\t= this.containers[i].element.outerWidth();\n\t\t\t\tthis.containers[i].containerCache.height = this.containers[i].element.outerHeight();\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_createPlaceholder: function(that) {\n\t\tthat = that || this;\n\t\tvar className,\n\t\t\to = that.options;\n\n\t\tif(!o.placeholder || o.placeholder.constructor === String) {\n\t\t\tclassName = o.placeholder;\n\t\t\to.placeholder = {\n\t\t\t\telement: function() {\n\n\t\t\t\t\tvar nodeName = that.currentItem[0].nodeName.toLowerCase(),\n\t\t\t\t\t\telement = $( \"<\" + nodeName + \">\", that.document[0] )\n\t\t\t\t\t\t\t.addClass(className || that.currentItem[0].className+\" ui-sortable-placeholder\")\n\t\t\t\t\t\t\t.removeClass(\"ui-sortable-helper\");\n\n\t\t\t\t\tif ( nodeName === \"tr\" ) {\n\t\t\t\t\t\tthat.currentItem.children().each(function() {\n\t\t\t\t\t\t\t$( \"<td>&#160;</td>\", that.document[0] )\n\t\t\t\t\t\t\t\t.attr( \"colspan\", $( this ).attr( \"colspan\" ) || 1 )\n\t\t\t\t\t\t\t\t.appendTo( element );\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if ( nodeName === \"img\" ) {\n\t\t\t\t\t\telement.attr( \"src\", that.currentItem.attr( \"src\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !className ) {\n\t\t\t\t\t\telement.css( \"visibility\", \"hidden\" );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn element;\n\t\t\t\t},\n\t\t\t\tupdate: function(container, p) {\n\n\t\t\t\t\t// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that\n\t\t\t\t\t// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified\n\t\t\t\t\tif(className && !o.forcePlaceholderSize) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item\n\t\t\t\t\tif(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css(\"paddingTop\")||0, 10) - parseInt(that.currentItem.css(\"paddingBottom\")||0, 10)); }\n\t\t\t\t\tif(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css(\"paddingLeft\")||0, 10) - parseInt(that.currentItem.css(\"paddingRight\")||0, 10)); }\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t//Create the placeholder\n\t\tthat.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));\n\n\t\t//Append it after the actual current item\n\t\tthat.currentItem.after(that.placeholder);\n\n\t\t//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)\n\t\to.placeholder.update(that, that.placeholder);\n\n\t},\n\n\t_contactContainers: function(event) {\n\t\tvar i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating,\n\t\t\tinnermostContainer = null,\n\t\t\tinnermostIndex = null;\n\n\t\t// get innermost container that intersects with item\n\t\tfor (i = this.containers.length - 1; i >= 0; i--) {\n\n\t\t\t// never consider a container that's located within the item itself\n\t\t\tif($.contains(this.currentItem[0], this.containers[i].element[0])) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif(this._intersectsWith(this.containers[i].containerCache)) {\n\n\t\t\t\t// if we've already found a container and it's more \"inner\" than this, then continue\n\t\t\t\tif(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tinnermostContainer = this.containers[i];\n\t\t\t\tinnermostIndex = i;\n\n\t\t\t} else {\n\t\t\t\t// container doesn't intersect. trigger \"out\" event if necessary\n\t\t\t\tif(this.containers[i].containerCache.over) {\n\t\t\t\t\tthis.containers[i]._trigger(\"out\", event, this._uiHash(this));\n\t\t\t\t\tthis.containers[i].containerCache.over = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\t// if no intersecting containers found, return\n\t\tif(!innermostContainer) {\n\t\t\treturn;\n\t\t}\n\n\t\t// move the item into the container if it's not there already\n\t\tif(this.containers.length === 1) {\n\t\t\tif (!this.containers[innermostIndex].containerCache.over) {\n\t\t\t\tthis.containers[innermostIndex]._trigger(\"over\", event, this._uiHash(this));\n\t\t\t\tthis.containers[innermostIndex].containerCache.over = 1;\n\t\t\t}\n\t\t} else {\n\n\t\t\t//When entering a new container, we will find the item with the least distance and append our item near it\n\t\t\tdist = 10000;\n\t\t\titemWithLeastDistance = null;\n\t\t\tfloating = innermostContainer.floating || isFloating(this.currentItem);\n\t\t\tposProperty = floating ? \"left\" : \"top\";\n\t\t\tsizeProperty = floating ? \"width\" : \"height\";\n\t\t\tbase = this.positionAbs[posProperty] + this.offset.click[posProperty];\n\t\t\tfor (j = this.items.length - 1; j >= 0; j--) {\n\t\t\t\tif(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif(this.items[j].item[0] === this.currentItem[0]) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tcur = this.items[j].item.offset()[posProperty];\n\t\t\t\tnearBottom = false;\n\t\t\t\tif(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){\n\t\t\t\t\tnearBottom = true;\n\t\t\t\t\tcur += this.items[j][sizeProperty];\n\t\t\t\t}\n\n\t\t\t\tif(Math.abs(cur - base) < dist) {\n\t\t\t\t\tdist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];\n\t\t\t\t\tthis.direction = nearBottom ? \"up\": \"down\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Check if dropOnEmpty is enabled\n\t\t\tif(!itemWithLeastDistance && !this.options.dropOnEmpty) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif(this.currentContainer === this.containers[innermostIndex]) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\titemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);\n\t\t\tthis._trigger(\"change\", event, this._uiHash());\n\t\t\tthis.containers[innermostIndex]._trigger(\"change\", event, this._uiHash(this));\n\t\t\tthis.currentContainer = this.containers[innermostIndex];\n\n\t\t\t//Update the placeholder\n\t\t\tthis.options.placeholder.update(this.currentContainer, this.placeholder);\n\n\t\t\tthis.containers[innermostIndex]._trigger(\"over\", event, this._uiHash(this));\n\t\t\tthis.containers[innermostIndex].containerCache.over = 1;\n\t\t}\n\n\n\t},\n\n\t_createHelper: function(event) {\n\n\t\tvar o = this.options,\n\t\t\thelper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === \"clone\" ? this.currentItem.clone() : this.currentItem);\n\n\t\t//Add the helper to the DOM if that didn't happen already\n\t\tif(!helper.parents(\"body\").length) {\n\t\t\t$(o.appendTo !== \"parent\" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);\n\t\t}\n\n\t\tif(helper[0] === this.currentItem[0]) {\n\t\t\tthis._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css(\"position\"), top: this.currentItem.css(\"top\"), left: this.currentItem.css(\"left\") };\n\t\t}\n\n\t\tif(!helper[0].style.width || o.forceHelperSize) {\n\t\t\thelper.width(this.currentItem.width());\n\t\t}\n\t\tif(!helper[0].style.height || o.forceHelperSize) {\n\t\t\thelper.height(this.currentItem.height());\n\t\t}\n\n\t\treturn helper;\n\n\t},\n\n\t_adjustOffsetFromHelper: function(obj) {\n\t\tif (typeof obj === \"string\") {\n\t\t\tobj = obj.split(\" \");\n\t\t}\n\t\tif ($.isArray(obj)) {\n\t\t\tobj = {left: +obj[0], top: +obj[1] || 0};\n\t\t}\n\t\tif (\"left\" in obj) {\n\t\t\tthis.offset.click.left = obj.left + this.margins.left;\n\t\t}\n\t\tif (\"right\" in obj) {\n\t\t\tthis.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\n\t\t}\n\t\tif (\"top\" in obj) {\n\t\t\tthis.offset.click.top = obj.top + this.margins.top;\n\t\t}\n\t\tif (\"bottom\" in obj) {\n\t\t\tthis.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\n\t\t}\n\t},\n\n\t_getParentOffset: function() {\n\n\n\t\t//Get the offsetParent and cache its position\n\t\tthis.offsetParent = this.helper.offsetParent();\n\t\tvar po = this.offsetParent.offset();\n\n\t\t// This is a special case where we need to modify a offset calculated on start, since the following happened:\n\t\t// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent\n\t\t// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that\n\t\t//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag\n\t\tif(this.cssPosition === \"absolute\" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {\n\t\t\tpo.left += this.scrollParent.scrollLeft();\n\t\t\tpo.top += this.scrollParent.scrollTop();\n\t\t}\n\n\t\t// This needs to be actually done for all browsers, since pageX/pageY includes this information\n\t\t// with an ugly IE fix\n\t\tif( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === \"html\" && $.ui.ie)) {\n\t\t\tpo = { top: 0, left: 0 };\n\t\t}\n\n\t\treturn {\n\t\t\ttop: po.top + (parseInt(this.offsetParent.css(\"borderTopWidth\"),10) || 0),\n\t\t\tleft: po.left + (parseInt(this.offsetParent.css(\"borderLeftWidth\"),10) || 0)\n\t\t};\n\n\t},\n\n\t_getRelativeOffset: function() {\n\n\t\tif(this.cssPosition === \"relative\") {\n\t\t\tvar p = this.currentItem.position();\n\t\t\treturn {\n\t\t\t\ttop: p.top - (parseInt(this.helper.css(\"top\"),10) || 0) + this.scrollParent.scrollTop(),\n\t\t\t\tleft: p.left - (parseInt(this.helper.css(\"left\"),10) || 0) + this.scrollParent.scrollLeft()\n\t\t\t};\n\t\t} else {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t},\n\n\t_cacheMargins: function() {\n\t\tthis.margins = {\n\t\t\tleft: (parseInt(this.currentItem.css(\"marginLeft\"),10) || 0),\n\t\t\ttop: (parseInt(this.currentItem.css(\"marginTop\"),10) || 0)\n\t\t};\n\t},\n\n\t_cacheHelperProportions: function() {\n\t\tthis.helperProportions = {\n\t\t\twidth: this.helper.outerWidth(),\n\t\t\theight: this.helper.outerHeight()\n\t\t};\n\t},\n\n\t_setContainment: function() {\n\n\t\tvar ce, co, over,\n\t\t\to = this.options;\n\t\tif(o.containment === \"parent\") {\n\t\t\to.containment = this.helper[0].parentNode;\n\t\t}\n\t\tif(o.containment === \"document\" || o.containment === \"window\") {\n\t\t\tthis.containment = [\n\t\t\t\t0 - this.offset.relative.left - this.offset.parent.left,\n\t\t\t\t0 - this.offset.relative.top - this.offset.parent.top,\n\t\t\t\t$(o.containment === \"document\" ? document : window).width() - this.helperProportions.width - this.margins.left,\n\t\t\t\t($(o.containment === \"document\" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t}\n\n\t\tif(!(/^(document|window|parent)$/).test(o.containment)) {\n\t\t\tce = $(o.containment)[0];\n\t\t\tco = $(o.containment).offset();\n\t\t\tover = ($(ce).css(\"overflow\") !== \"hidden\");\n\n\t\t\tthis.containment = [\n\t\t\t\tco.left + (parseInt($(ce).css(\"borderLeftWidth\"),10) || 0) + (parseInt($(ce).css(\"paddingLeft\"),10) || 0) - this.margins.left,\n\t\t\t\tco.top + (parseInt($(ce).css(\"borderTopWidth\"),10) || 0) + (parseInt($(ce).css(\"paddingTop\"),10) || 0) - this.margins.top,\n\t\t\t\tco.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css(\"borderLeftWidth\"),10) || 0) - (parseInt($(ce).css(\"paddingRight\"),10) || 0) - this.helperProportions.width - this.margins.left,\n\t\t\t\tco.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css(\"borderTopWidth\"),10) || 0) - (parseInt($(ce).css(\"paddingBottom\"),10) || 0) - this.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t}\n\n\t},\n\n\t_convertPositionTo: function(d, pos) {\n\n\t\tif(!pos) {\n\t\t\tpos = this.position;\n\t\t}\n\t\tvar mod = d === \"absolute\" ? 1 : -1,\n\t\t\tscroll = this.cssPosition === \"absolute\" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,\n\t\t\tscrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);\n\n\t\treturn {\n\t\t\ttop: (\n\t\t\t\tpos.top\t+\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\tthis.offset.relative.top * mod +\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.parent.top * mod -\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t( ( this.cssPosition === \"fixed\" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)\n\t\t\t),\n\t\t\tleft: (\n\t\t\t\tpos.left +\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\tthis.offset.relative.left * mod +\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.parent.left * mod\t-\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t( ( this.cssPosition === \"fixed\" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_generatePosition: function(event) {\n\n\t\tvar top, left,\n\t\t\to = this.options,\n\t\t\tpageX = event.pageX,\n\t\t\tpageY = event.pageY,\n\t\t\tscroll = this.cssPosition === \"absolute\" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);\n\n\t\t// This is another very weird special case that only happens for relative elements:\n\t\t// 1. If the css position is relative\n\t\t// 2. and the scroll parent is the document or similar to the offset parent\n\t\t// we have to refresh the relative offset during the scroll so there are no jumps\n\t\tif(this.cssPosition === \"relative\" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {\n\t\t\tthis.offset.relative = this._getRelativeOffset();\n\t\t}\n\n\t\t/*\n\t\t * - Position constraining -\n\t\t * Constrain the position to a mix of grid, containment.\n\t\t */\n\n\t\tif(this.originalPosition) { //If we are not dragging yet, we won't check for options\n\n\t\t\tif(this.containment) {\n\t\t\t\tif(event.pageX - this.offset.click.left < this.containment[0]) {\n\t\t\t\t\tpageX = this.containment[0] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif(event.pageY - this.offset.click.top < this.containment[1]) {\n\t\t\t\t\tpageY = this.containment[1] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t\tif(event.pageX - this.offset.click.left > this.containment[2]) {\n\t\t\t\t\tpageX = this.containment[2] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif(event.pageY - this.offset.click.top > this.containment[3]) {\n\t\t\t\t\tpageY = this.containment[3] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(o.grid) {\n\t\t\t\ttop = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];\n\t\t\t\tpageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;\n\n\t\t\t\tleft = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];\n\t\t\t\tpageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;\n\t\t\t}\n\n\t\t}\n\n\t\treturn {\n\t\t\ttop: (\n\t\t\t\tpageY -\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\tthis.offset.click.top -\t\t\t\t\t\t\t\t\t\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.relative.top\t-\t\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.parent.top +\t\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t( ( this.cssPosition === \"fixed\" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))\n\t\t\t),\n\t\t\tleft: (\n\t\t\t\tpageX -\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\tthis.offset.click.left -\t\t\t\t\t\t\t\t\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.relative.left\t-\t\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.parent.left +\t\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t( ( this.cssPosition === \"fixed\" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_rearrange: function(event, i, a, hardRefresh) {\n\n\t\ta ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === \"down\" ? i.item[0] : i.item[0].nextSibling));\n\n\t\t//Various things done here to improve the performance:\n\t\t// 1. we create a setTimeout, that calls refreshPositions\n\t\t// 2. on the instance, we have a counter variable, that get's higher after every append\n\t\t// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same\n\t\t// 4. this lets only the last addition to the timeout stack through\n\t\tthis.counter = this.counter ? ++this.counter : 1;\n\t\tvar counter = this.counter;\n\n\t\tthis._delay(function() {\n\t\t\tif(counter === this.counter) {\n\t\t\t\tthis.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove\n\t\t\t}\n\t\t});\n\n\t},\n\n\t_clear: function(event, noPropagation) {\n\n\t\tthis.reverting = false;\n\t\t// We delay all events that have to be triggered to after the point where the placeholder has been removed and\n\t\t// everything else normalized again\n\t\tvar i,\n\t\t\tdelayedTriggers = [];\n\n\t\t// We first have to update the dom position of the actual currentItem\n\t\t// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)\n\t\tif(!this._noFinalSort && this.currentItem.parent().length) {\n\t\t\tthis.placeholder.before(this.currentItem);\n\t\t}\n\t\tthis._noFinalSort = null;\n\n\t\tif(this.helper[0] === this.currentItem[0]) {\n\t\t\tfor(i in this._storedCSS) {\n\t\t\t\tif(this._storedCSS[i] === \"auto\" || this._storedCSS[i] === \"static\") {\n\t\t\t\t\tthis._storedCSS[i] = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.currentItem.css(this._storedCSS).removeClass(\"ui-sortable-helper\");\n\t\t} else {\n\t\t\tthis.currentItem.show();\n\t\t}\n\n\t\tif(this.fromOutside && !noPropagation) {\n\t\t\tdelayedTriggers.push(function(event) { this._trigger(\"receive\", event, this._uiHash(this.fromOutside)); });\n\t\t}\n\t\tif((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(\".ui-sortable-helper\")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {\n\t\t\tdelayedTriggers.push(function(event) { this._trigger(\"update\", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed\n\t\t}\n\n\t\t// Check if the items Container has Changed and trigger appropriate\n\t\t// events.\n\t\tif (this !== this.currentContainer) {\n\t\t\tif(!noPropagation) {\n\t\t\t\tdelayedTriggers.push(function(event) { this._trigger(\"remove\", event, this._uiHash()); });\n\t\t\t\tdelayedTriggers.push((function(c) { return function(event) { c._trigger(\"receive\", event, this._uiHash(this)); };  }).call(this, this.currentContainer));\n\t\t\t\tdelayedTriggers.push((function(c) { return function(event) { c._trigger(\"update\", event, this._uiHash(this));  }; }).call(this, this.currentContainer));\n\t\t\t}\n\t\t}\n\n\n\t\t//Post events to containers\n\t\tfor (i = this.containers.length - 1; i >= 0; i--){\n\t\t\tif(!noPropagation) {\n\t\t\t\tdelayedTriggers.push((function(c) { return function(event) { c._trigger(\"deactivate\", event, this._uiHash(this)); };  }).call(this, this.containers[i]));\n\t\t\t}\n\t\t\tif(this.containers[i].containerCache.over) {\n\t\t\t\tdelayedTriggers.push((function(c) { return function(event) { c._trigger(\"out\", event, this._uiHash(this)); };  }).call(this, this.containers[i]));\n\t\t\t\tthis.containers[i].containerCache.over = 0;\n\t\t\t}\n\t\t}\n\n\t\t//Do what was originally in plugins\n\t\tif ( this.storedCursor ) {\n\t\t\tthis.document.find( \"body\" ).css( \"cursor\", this.storedCursor );\n\t\t\tthis.storedStylesheet.remove();\n\t\t}\n\t\tif(this._storedOpacity) {\n\t\t\tthis.helper.css(\"opacity\", this._storedOpacity);\n\t\t}\n\t\tif(this._storedZIndex) {\n\t\t\tthis.helper.css(\"zIndex\", this._storedZIndex === \"auto\" ? \"\" : this._storedZIndex);\n\t\t}\n\n\t\tthis.dragging = false;\n\t\tif(this.cancelHelperRemoval) {\n\t\t\tif(!noPropagation) {\n\t\t\t\tthis._trigger(\"beforeStop\", event, this._uiHash());\n\t\t\t\tfor (i=0; i < delayedTriggers.length; i++) {\n\t\t\t\t\tdelayedTriggers[i].call(this, event);\n\t\t\t\t} //Trigger all delayed events\n\t\t\t\tthis._trigger(\"stop\", event, this._uiHash());\n\t\t\t}\n\n\t\t\tthis.fromOutside = false;\n\t\t\treturn false;\n\t\t}\n\n\t\tif(!noPropagation) {\n\t\t\tthis._trigger(\"beforeStop\", event, this._uiHash());\n\t\t}\n\n\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!\n\t\tthis.placeholder[0].parentNode.removeChild(this.placeholder[0]);\n\n\t\tif(this.helper[0] !== this.currentItem[0]) {\n\t\t\tthis.helper.remove();\n\t\t}\n\t\tthis.helper = null;\n\n\t\tif(!noPropagation) {\n\t\t\tfor (i=0; i < delayedTriggers.length; i++) {\n\t\t\t\tdelayedTriggers[i].call(this, event);\n\t\t\t} //Trigger all delayed events\n\t\t\tthis._trigger(\"stop\", event, this._uiHash());\n\t\t}\n\n\t\tthis.fromOutside = false;\n\t\treturn true;\n\n\t},\n\n\t_trigger: function() {\n\t\tif ($.Widget.prototype._trigger.apply(this, arguments) === false) {\n\t\t\tthis.cancel();\n\t\t}\n\t},\n\n\t_uiHash: function(_inst) {\n\t\tvar inst = _inst || this;\n\t\treturn {\n\t\t\thelper: inst.helper,\n\t\t\tplaceholder: inst.placeholder || $([]),\n\t\t\tposition: inst.position,\n\t\t\toriginalPosition: inst.originalPosition,\n\t\t\toffset: inst.positionAbs,\n\t\t\titem: inst.currentItem,\n\t\t\tsender: _inst ? _inst.element : null\n\t\t};\n\t}\n\n});\n\n})(jQuery);\n"
  },
  {
    "path": "examples/unfinished/reorderable-list/client/shark.css",
    "content": "#list div {\n  padding: 10px;\n  height: 19px;\n  border: 1px solid #bbb;\n  margin: 8px;\n  font-weight: bold;\n  cursor: move;\n  width: 400px;\n  background: #eee; }\n\n"
  },
  {
    "path": "examples/unfinished/reorderable-list/client/shark.html",
    "content": "<body>\n  <div id=\"list\">\n    {{#each items}}\n      <div class=\"item\">\n        {{text}}\n      </div>\n    {{/each}}\n  </div>\n</body>\n"
  },
  {
    "path": "examples/unfinished/reorderable-list/client/shark.js",
    "content": "UI.body.items = Items.find({}, { sort: { rank: 1 } });\n\nSimpleRationalRanks = {\n  beforeFirst: function (firstRank) { return firstRank - 1; },\n  between: function (beforeRank, afterRank) { return (beforeRank + afterRank) / 2; },\n  afterLast: function (lastRank) { return lastRank + 1; }\n};\n\nUI.body.rendered = function () {\n  $(this.find('#list')).sortable({ // uses the 'sortable' interaction from jquery ui\n    stop: function (event, ui) { // fired when an item is dropped\n      var el = ui.item.get(0), before = ui.item.prev().get(0), after = ui.item.next().get(0);\n\n      var newRank;\n      if (!before) { // moving to the top of the list\n        newRank = SimpleRationalRanks.beforeFirst(UI.getElementData(after).rank);\n\n      } else if (!after) { // moving to the bottom of the list\n        newRank = SimpleRationalRanks.afterLast(UI.getElementData(before).rank);\n\n      } else {\n        newRank = SimpleRationalRanks.between(\n          UI.getElementData(before).rank,\n          UI.getElementData(after).rank);\n      }\n\n      Items.update(UI.getElementData(el)._id, {$set: {rank: newRank}});\n    }\n  });\n};\n"
  },
  {
    "path": "examples/unfinished/reorderable-list/lib/items.js",
    "content": "Items = new Mongo.Collection(\"items\");\n\nif (Meteor.isServer) {\n  if (Items.find().count() === 0) {\n    _.each(\n      [\"violet\", \"unicorn\", \"flask\", \"jar\", \"leitmotif\", \"rearrange\", \"right\", \"ethereal\"],\n      function (text, index) { Items.insert({text: text, rank: index}); });\n  }\n}\n"
  },
  {
    "path": "examples/unfinished/todos-backbone/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/todos-backbone/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\njquery\nbackbone\nstandard-app-packages\n"
  },
  {
    "path": "examples/unfinished/todos-backbone/.meteor/release",
    "content": "0.6.0\n"
  },
  {
    "path": "examples/unfinished/todos-backbone/body.html",
    "content": "<head>\n<title>Todos</title>\n</head>\n\n<body>\n\n  <!-- Todo App Interface -->\n\n  <div id=\"todoapp\">\n\n    <div class=\"title\">\n      <h1>Todos</h1>\n    </div>\n\n    <div class=\"content\">\n\n      <div id=\"create-todo\">\n        <input id=\"new-todo\" placeholder=\"What needs to be done?\" type=\"text\" />\n        <span class=\"ui-tooltip-top\" style=\"display:none;\">Press Enter to save this task</span>\n      </div>\n\n      <div id=\"todos\">\n        <ul id=\"todo-list\"></ul>\n      </div>\n\n      <div id=\"todo-stats\"></div>\n\n    </div>\n\n  </div>\n\n  <ul id=\"instructions\">\n    <li>Double-click to edit a todo.</li>\n    <li><a href=\"../../docs/todos.html\">View the annotated source.</a></li>\n  </ul>\n\n  <div id=\"credits\">\n    Created by\n    <br />\n    <a href=\"http://jgn.me/\">J&eacute;r&ocirc;me Gravel-Niquet</a>\n  </div>\n\n  <!-- Templates -->\n\n  <script type=\"text/template\" id=\"item-template\">\n    <div class=\"todo <%= done ? 'done' : '' %>\">\n      <div class=\"display\">\n        <input class=\"check\" type=\"checkbox\" <%= done ? 'checked=\"checked\"' : '' %> />\n        <div class=\"todo-text\"></div>\n        <span class=\"todo-destroy\"></span>\n      </div>\n      <div class=\"edit\">\n        <input class=\"todo-input\" type=\"text\" value=\"\" />\n      </div>\n    </div>\n  </script>\n\n  <script type=\"text/template\" id=\"stats-template\">\n    <% if (total) { %>\n      <span class=\"todo-count\">\n        <span class=\"number\"><%= remaining %></span>\n        <span class=\"word\"><%= remaining == 1 ? 'item' : 'items' %></span> left.\n      </span>\n    <% } %>\n    <% if (done) { %>\n      <span class=\"todo-clear\">\n        <a href=\"#\">\n          Clear <span class=\"number-done\"><%= done %></span>\n          completed <span class=\"word-done\"><%= done == 1 ? 'item' : 'items' %></span>\n        </a>\n      </span>\n    <% } %>\n  </script>\n\n</body>\n"
  },
  {
    "path": "examples/unfinished/todos-backbone/client/todos.js",
    "content": "// An example Backbone application contributed by\n// [Jérôme Gravel-Niquet](http://jgn.me/). This demo uses a simple\n// [LocalStorage adapter](backbone-localstorage.html)\n// to persist Backbone models within your browser.\n\n// Load the application once the DOM is ready, using `jQuery.ready`:\n$(function(){\n  // ask for all the todos in my cache\n  Meteor.subscribe('todos');\n\n  // helper functions\n\n  function all () {\n    return Todos.find();\n  };\n\n  function all_done () {\n    return Todos.find({done: true});\n  };\n\n  function all_remaining () {\n    return Todos.find({done: false});\n  };\n\n  function nextOrder () {\n    var todos = Todos.find({}, {sort: {order: -1}, limit: 1});\n    return todos[0] ? todos[0].order + 1 : 1;\n  };\n\n  // Todo Item View\n  // --------------\n\n  // The DOM element for a todo item...\n  window.TodoView = Backbone.View.extend({\n\n    //... is a list tag.\n    tagName:  \"li\",\n\n    // Cache the template function for a single item.\n    template: _.template($('#item-template').html()),\n\n    // The DOM events specific to an item.\n    events: {\n      \"click .check\"              : \"toggleDone\",\n      \"dblclick div.todo-text\"    : \"edit\",\n      \"click span.todo-destroy\"   : \"clear\",\n      \"keypress .todo-input\"      : \"updateOnEnter\"\n    },\n\n    // Re-render the contents of the todo item.\n    render: function() {\n      $(this.el).html(this.template(this.model));\n      this.setText();\n      return this;\n    },\n\n    // To avoid XSS (not that it would be harmful in this particular app),\n    // we use `jQuery.text` to set the contents of the todo item.\n    setText: function() {\n      this.$('.todo-text').text(this.model.text);\n      this.input = this.$('.todo-input');\n      this.input.bind('blur', _.bind(this.close, this)).val(this.model.text);\n    },\n\n    // Toggle the `\"done\"` state of the object.\n    toggleDone: function() {\n      Todos.update(this.model._id, {$set: {done: !this.model.done}});\n    },\n\n    // Switch this view into `\"editing\"` mode, displaying the input field.\n    edit: function() {\n      $(this.el).addClass(\"editing\");\n      this.input.focus();\n    },\n\n    // Close the `\"editing\"` mode, saving changes to the todo.\n    // findLive callback will update this view.\n    close: function() {\n      Todos.update(this.model._id, {$set: {text: this.input.val()}});\n      $(this.el).removeClass(\"editing\");\n    },\n\n    // If you hit `enter`, we're through editing the item.\n    updateOnEnter: function(e) {\n      if (e.keyCode == 13) this.close();\n    },\n\n    // Remove this view from the DOM.\n    remove: function() {\n      $(this.el).remove();\n    },\n\n    // destroy the todo object.  the findLive callback will g/c this view.\n    clear: function() {\n      Todos.remove(this.model._id);\n    }\n  });\n\n  // The Application\n  // ---------------\n\n  // Our overall **AppView** is the top-level piece of UI.\n  window.AppView = Backbone.View.extend({\n\n    // Instead of generating a new element, bind to the existing skeleton of\n    // the App already present in the HTML.\n    el: $(\"#todoapp\"),\n\n    // Our template for the line of statistics at the bottom of the app.\n    statsTemplate: _.template($('#stats-template').html()),\n\n    // Delegated events for creating new items, and clearing done ones.\n    events: {\n      \"keypress #new-todo\":  \"createOnEnter\",\n      \"keyup #new-todo\":     \"showTooltip\",\n      \"click .todo-clear a\": \"clearCompleted\"\n    },\n\n    todos: [],\n\n    // At initialization we bind to the relevant events on the `Todos`\n    // collection, when items are added or changed. Kick things off by\n    // loading any preexisting todos that might be saved in *localStorage*.\n    initialize: function() {\n      var self = this;\n\n      this.input = this.$(\"#new-todo\");\n\n      // spin up the live query.  ignore the return value since we never\n      // stop the query.\n      Todos.findLive({}, {\n        added: function (obj, before_idx) {\n          // add a view node to the DOM\n          var view = new TodoView({model: obj});\n          self.todos.splice(before_idx, 0, view);\n          self.$(\"#todo-list\").append(view.render().el);\n          self.render();\n        },\n        removed: function (obj, at_idx) {\n          // remove the view node from the DOM\n          var view = self.todos.splice(at_idx, 1);\n          view[0].remove();\n          self.render();\n        },\n        changed: function (obj, at_idx) {\n          // update obj in existing view and rerender\n          self.todos[at_idx].model = obj;\n          self.todos[at_idx].render();\n          self.render();\n        },\n        moved: function (old_idx, new_idx) {\n          // unimplemented -- items don't ever move\n        },\n        sort: {'order': 1}\n      });\n    },\n\n    // Re-rendering the App just means refreshing the statistics -- the rest\n    // of the app doesn't change.\n    render: function() {\n      console.log(\"RENDER\", all().length, all_done().length, all_remaining().length);\n\n      this.$('#todo-stats').html(this.statsTemplate({\n        total:      all().length,\n        done:       all_done().length,\n        remaining:  all_remaining().length\n      }));\n    },\n\n    // If you hit return in the main input field, and there is text to save,\n    // create new **Todo** model.\n    createOnEnter: function(e) {\n      var text = this.input.val();\n      if (!text || e.keyCode != 13) return;\n      Todos.insert({text: text, done: false, order: nextOrder()});\n      this.input.val('');\n    },\n\n    // Clear all done todo items, destroying their models.\n    clearCompleted: function() {\n      _.each(all_done(), function (todo) { Todos.remove(todo._id); });\n      return false;\n    },\n\n    // Lazily show the tooltip that tells you to press `enter` to save\n    // a new todo item, after one second.\n    showTooltip: function(e) {\n      var tooltip = this.$(\".ui-tooltip-top\");\n      var val = this.input.val();\n      tooltip.fadeOut();\n      if (this.tooltipTimeout) clearTimeout(this.tooltipTimeout);\n      if (val == '' || val == this.input.attr('placeholder')) return;\n      var show = function(){ tooltip.show().fadeIn(); };\n      this.tooltipTimeout = _.delay(show, 1000);\n    }\n  });\n\n  // Finally, we kick things off by creating the **App**.\n  window.App = new AppView;\n\n});\n"
  },
  {
    "path": "examples/unfinished/todos-backbone/common.js",
    "content": "Todos = new Mongo.Collection(\"todos\");\n//Todos.schema({text: String, done: Boolean, order: Number});\n\nif (Meteor.isServer) {\n  Meteor.publish('todos', function () {\n    return Todos.find();\n  });\n}\n"
  },
  {
    "path": "examples/unfinished/todos-backbone/todos.css",
    "content": "html, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, big, cite, code,\ndel, dfn, em, font, img, ins, kbd, q, s, samp,\nsmall, strike, strong, sub, sup, tt, var,\ndl, dt, dd, ol, ul, li,\nfieldset, form, label, legend,\ntable, caption, tbody, tfoot, thead, tr, th, td {\n  margin: 0;\n  padding: 0;\n  border: 0;\n  outline: 0;\n  font-weight: inherit;\n  font-style: inherit;\n  font-size: 100%;\n  font-family: inherit;\n  vertical-align: baseline;\n}\nbody {\n  line-height: 1;\n  color: black;\n  background: white;\n}\nol, ul {\n  list-style: none;\n}\na img {\n  border: none;\n}\n\nhtml {\n  background: #eeeeee;\n}\n  body {\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 14px;\n    line-height: 1.4em;\n    background: #eeeeee;\n    color: #333333;\n  }\n\n#todoapp {\n  width: 480px;\n  margin: 0 auto 40px;\n  background: white;\n  padding: 20px;\n  -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;\n  -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;\n  -o-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;\n  box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;\n}\n  #todoapp h1 {\n    font-size: 36px;\n    font-weight: bold;\n    text-align: center;\n    padding: 20px 0 30px 0;\n    line-height: 1;\n  }\n\n#create-todo {\n  position: relative;\n}\n  #create-todo input {\n    width: 466px;\n    font-size: 24px;\n    font-family: inherit;\n    line-height: 1.4em;\n    border: 0;\n    outline: none;\n    padding: 6px;\n    border: 1px solid #999999;\n    -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;\n    -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;\n    -o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;\n    box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;\n  }\n    #create-todo input::-webkit-input-placeholder {\n      font-style: italic;\n    }\n  #create-todo span {\n    position: absolute;\n    z-index: 999;\n    width: 170px;\n    left: 50%;\n    margin-left: -85px;\n  }\n\n#todo-list {\n  margin-top: 10px;\n}\n  #todo-list li {\n    padding: 12px 20px 11px 0;\n    position: relative;\n    font-size: 24px;\n    line-height: 1.1em;\n    border-bottom: 1px solid #cccccc;\n  }\n    #todo-list li:after {\n      content: \"\\0020\";\n      display: block;\n      height: 0;\n      clear: both;\n      overflow: hidden;\n      visibility: hidden;\n    }\n    #todo-list li.editing {\n      padding: 0;\n      border-bottom: 0;\n    }\n  #todo-list .editing .display,\n  #todo-list .edit {\n    display: none;\n  }\n    #todo-list .editing .edit {\n      display: block;\n    }\n    #todo-list .editing input {\n      width: 444px;\n      font-size: 24px;\n      font-family: inherit;\n      margin: 0;\n      line-height: 1.6em;\n      border: 0;\n      outline: none;\n      padding: 10px 7px 0px 27px;\n      border: 1px solid #999999;\n      -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;\n      -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;\n      -o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;\n      box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;\n    }\n  #todo-list .check {\n    position: relative;\n    top: 9px;\n    margin: 0 10px 0 7px;\n    float: left;\n  }\n  #todo-list .done .todo-text {\n    text-decoration: line-through;\n    color: #777777;\n  }\n  #todo-list .todo-destroy {\n    position: absolute;\n    right: 5px;\n    top: 14px;\n    display: none;\n    cursor: pointer;\n    width: 20px;\n    height: 20px;\n    background: url(destroy.png) no-repeat 0 0;\n  }\n    #todo-list li:hover .todo-destroy {\n      display: block;\n    }\n    #todo-list .todo-destroy:hover {\n      background-position: 0 -20px;\n    }\n\n#todo-stats {\n  *zoom: 1;\n  margin-top: 10px;\n  color: #777777;\n}\n  #todo-stats:after {\n    content: \"\\0020\";\n    display: block;\n    height: 0;\n    clear: both;\n    overflow: hidden;\n    visibility: hidden;\n  }\n  #todo-stats .todo-count {\n    float: left;\n  }\n    #todo-stats .todo-count .number {\n      font-weight: bold;\n      color: #333333;\n    }\n  #todo-stats .todo-clear {\n    float: right;\n  }\n    #todo-stats .todo-clear a {\n      color: #777777;\n      font-size: 12px;\n    }\n      #todo-stats .todo-clear a:visited {\n        color: #777777;\n      }\n      #todo-stats .todo-clear a:hover {\n        color: #336699;\n      }\n\n#instructions {\n  width: 520px;\n  margin: 10px auto;\n  color: #777777;\n  text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;\n  text-align: center;\n}\n  #instructions a {\n    color: #336699;\n  }\n\n#credits {\n  width: 520px;\n  margin: 30px auto;\n  color: #999;\n  text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;\n  text-align: center;\n}\n  #credits a {\n    color: #888;\n  }\n\n\n/*\n *  François 'cahnory' Germain\n */\n.ui-tooltip, .ui-tooltip-top, .ui-tooltip-right, .ui-tooltip-bottom, .ui-tooltip-left {\n  color:#ffffff;\n  cursor:normal;\n  display:-moz-inline-stack;\n  display:inline-block;\n  font-size:12px;\n  font-family:arial;\n  padding:.5em 1em;\n  position:relative;\n  text-align:center;\n  text-shadow:0 -1px 1px #111111;\n  -webkit-border-top-left-radius:4px ;\n  -webkit-border-top-right-radius:4px ;\n  -webkit-border-bottom-right-radius:4px ;\n  -webkit-border-bottom-left-radius:4px ;\n  -khtml-border-top-left-radius:4px ;\n  -khtml-border-top-right-radius:4px ;\n  -khtml-border-bottom-right-radius:4px ;\n  -khtml-border-bottom-left-radius:4px ;\n  -moz-border-radius-topleft:4px ;\n  -moz-border-radius-topright:4px ;\n  -moz-border-radius-bottomright:4px ;\n  -moz-border-radius-bottomleft:4px ;\n  border-top-left-radius:4px ;\n  border-top-right-radius:4px ;\n  border-bottom-right-radius:4px ;\n  border-bottom-left-radius:4px ;\n  -o-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;\n  -moz-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;\n  -khtml-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;\n  -webkit-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;\n  box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;\n  background-color:#3b3b3b;\n  background-image:-moz-linear-gradient(top,#555555,#222222);\n  background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#555555),color-stop(1,#222222));\n  filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#555555,EndColorStr=#222222);\n  -ms-filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#555555,EndColorStr=#222222);\n}\n.ui-tooltip:after, .ui-tooltip-top:after, .ui-tooltip-right:after, .ui-tooltip-bottom:after, .ui-tooltip-left:after {\n  content:\"\\25B8\";\n  display:block;\n  font-size:2em;\n  height:0;\n  line-height:0;\n  position:absolute;\n}\n.ui-tooltip:after, .ui-tooltip-bottom:after {\n  color:#2a2a2a;\n  bottom:0;\n  left:1px;\n  text-align:center;\n  text-shadow:1px 0 2px #000000;\n  -o-transform:rotate(90deg);\n  -moz-transform:rotate(90deg);\n  -khtml-transform:rotate(90deg);\n  -webkit-transform:rotate(90deg);\n  width:100%;\n}\n.ui-tooltip-top:after {\n  bottom:auto;\n  color:#4f4f4f;\n  left:-2px;\n  top:0;\n  text-align:center;\n  text-shadow:none;\n  -o-transform:rotate(-90deg);\n  -moz-transform:rotate(-90deg);\n  -khtml-transform:rotate(-90deg);\n  -webkit-transform:rotate(-90deg);\n  width:100%;\n}\n.ui-tooltip-right:after {\n  color:#222222;\n  right:-0.375em;\n  top:50%;\n  margin-top:-.05em;\n  text-shadow:0 1px 2px #000000;\n  -o-transform:rotate(0);\n  -moz-transform:rotate(0);\n  -khtml-transform:rotate(0);\n  -webkit-transform:rotate(0);\n}\n.ui-tooltip-left:after {\n  color:#222222;\n  left:-0.375em;\n  top:50%;\n  margin-top:.1em;\n  text-shadow:0 -1px 2px #000000;\n  -o-transform:rotate(180deg);\n  -moz-transform:rotate(180deg);\n  -khtml-transform:rotate(180deg);\n  -webkit-transform:rotate(180deg);\n}\n"
  },
  {
    "path": "examples/unfinished/todos-underscore/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "examples/unfinished/todos-underscore/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\njquery\njquery-layout\njquery-history\nstandard-app-packages\n"
  },
  {
    "path": "examples/unfinished/todos-underscore/.meteor/release",
    "content": "0.6.0\n"
  },
  {
    "path": "examples/unfinished/todos-underscore/body.html",
    "content": "<head>\n<title>Todos</title>\n</head>\n\n<body>\n\n<div class=\"ui-layout-north\">\n  <div id=\"tag-filter\" class=\"tag-list\">\n  </div>\n</div>\n\n<div class=\"ui-layout-center\">\n  <div id=\"items-view\">\n    <input type=\"text\" id=\"new-todo\" placeholder=\"New item, press enter to save.\" />\n    <ul id=\"item-list\"></ul>\n  </div>\n</div>\n\n<div class=\"ui-layout-west\">\n  <div id=\"createList\">\n    <input type=\"text\" id=\"new-list\" placeholder=\"New list name.\" />\n  </div>\n\n  <div id=\"lists\"></div>\n</div>\n\n<div class=\"ui-layout-south\">\n  <div id=\"help\">\n    <p>\n      To get started, create a new todo list in the left sidebar by\n      typing its name in the text box.  Select a list by clicking on its\n      name, and rename by double clicking.  The active list appears in\n      the main window pane.  You can do the usual here: add items, check\n      them off as completed, and destroy items.  You can also tag items\n      with one or more tags, by clicking the blue <b>Add new tag</b>\n      button to the right.  All your in-use tags appear at the top.  You\n      can filter the list items by selecting a tag, or click the\n      leftmost button to return to the full list.\n    </p>\n\n    <p>\n      Inspired by Backbone's\n      <a href=\"http://documentcloud.github.com/backbone/examples/todos/index.html\">Todo Demo</a>,\n      with credit to\n      <a href=\"http://jgn.me/\">J&eacute;r&ocirc;me Gravel-Niquet</a>.\n    </p>\n  </div>\n</div>\n\n<!-- underscore templates -->\n\n<script type=\"text/template\" id=\"tag-filter-template\">\n  <div class=\"tag <%= Session.equals('tag_filter', tag) ? 'selected' : '' %>\">\n    <%= tag || \"Show all todo items\" %>\n  </div>\n</script>\n\n<script type=\"text/template\" id=\"list-template\">\n  <div class=\"list <%= Session.equals('list_id', _id) ? 'selected' : '' %>\">\n    <div class=\"display\">\n      <div class=\"list-name\">\n        <%= name || '<div class=\"empty\">empty</i>' %>\n      </div>\n    </div>\n    <div class=\"edit\">\n      <input class=\"list-name-input\" type=\"text\" value=\"\" />\n    </div>\n  </div>\n</script>\n\n<script type=\"text/template\" id=\"item-template\">\n  <li class=\"todo <%= typeof(done) !== 'undefined' && done ? 'done' : '' %>\">\n    <div class=\"destroy\"></div>\n    <div class=\"display\">\n      <input class=\"check\" type=\"checkbox\" <%= typeof(done) !== 'undefined' && done ? 'checked=\"checked\"' : '' %> />\n      <div class=\"todo-text\"></div>\n    </div>\n    <div class=\"edit\">\n      <input class=\"todo-input\" type=\"text\" value=\"\" />\n    </div>\n    <div class=\"item-tags\">\n      <% _.each(typeof(tags) === 'undefined' ? [] : tags, function (tag) { %>\n      <div class=\"tag\">\n        <div class=\"name\"><%= tag %></div>\n        <div class=\"remove\" name=\"<%= tag %>\"></div>\n      </div>\n      <% }); %>\n      <div class=\"tag addtag\">\n        Add new tag\n      </div>\n      <div class=\"tag edittag\">\n        <input type=\"text\" value=\"\" />\n      </div>\n    </div>\n  </li>\n</script>\n\n</body>\n"
  },
  {
    "path": "examples/unfinished/todos-underscore/client/client.js",
    "content": "// quick jquery extension to bind text inputs to blur and RET.\n$.fn.onBlurOrEnter = function (callback) {\n  this.bind('blur', callback);\n  this.bind('keypress', function (evt) {\n    if (evt.keyCode === 13 && $(this).val())\n      callback.call(this, evt);\n  });\n};\n\n// everything else happens after DOM is ready\n$(function () {\n  $('body').layout({north__minSize: 50,\n                    spacing_open: 10,\n                    north__fxSettings: { direction: \"vertical\" }});\n\n  // cache the template function for a single item.\n  var item_template = _.template($('#item-template').html());\n\n  // this render function could be replaced with a handlebars\n  // template.  underscore template isn't safe for user-entered data\n  // like the item text (XSS).\n  function renderItem (obj) {\n    // generate template for todo\n    var elt = $(item_template(obj));\n\n    // set text through jquery for XSS protection\n    elt.find('.todo-text').text(obj.text);\n\n    // clicking the checkbox toggles done state\n    elt.find('.check').click(function () {\n      Todos.update(obj._id, {$set: {done: !obj.done}});\n    });\n\n    // clicking destroy button removes the item\n    elt.find('.destroy').click(function () {\n      Todos.remove(obj._id);\n    });\n\n    // wire up tag destruction links\n    elt.find('.tag .remove').click(function () {\n      var tag = $(this).attr('name');\n      $(this).parent().fadeOut(500, function () {\n        Todos.update(obj._id, {$pull: {tags: tag}});\n      });\n    });\n\n    // wire up add tag\n    elt.find('.addtag').click(function () {\n      $(this).hide();\n      elt.find('.edittag').show();\n      elt.find('.edittag input').focus();\n    });\n\n    // wire up edit tag\n    elt.find('.edittag input').onBlurOrEnter(function () {\n      elt.find('.edittag').hide();\n      elt.find('.addtag').show();\n      if ($(this).val() !== '')\n        Todos.update(obj._id, {$addToSet: {tags: $(this).val()}});\n    });\n\n    // doubleclick on todo text brings up the editor\n    elt.find('.todo-text').dblclick(function () {\n      elt.addClass('editing');\n\n      var input = elt.find('.todo-input');\n      input.val(obj.text);\n      input.focus();\n      input.select();\n\n      input.onBlurOrEnter(function () {\n        elt.removeClass('editing');\n        if ($(this).val() !== '')\n          Todos.update(obj._id, {$set: {text: elt.find('.todo-input').val()}});\n      });\n    });\n\n    return elt[0];\n  };\n\n  // construct new todo from text box\n  $('#new-todo').bind('keypress', function (evt) {\n    var list_id = Session.get('list_id');\n    var tag = Session.get('tag_filter');\n\n    // prevent creation of a new todo if nothing is selected\n    if (!list_id) return;\n\n    var text = $('#new-todo').val();\n\n    if (evt.keyCode === 13 && text) {\n      var obj = {text: text,\n                 list_id: list_id,\n                 done: false,\n                 timestamp: (new Date()).getTime()};\n      if (tag) obj.tags = [tag];\n\n      Todos.insert(obj);\n      $('#new-todo').val('');\n    }\n  });\n\n  var current_list_stop;\n  function setCurrentList (list_id) {\n    Session.set('list_id', list_id);\n\n    $('#items-view').show();\n\n    // kill current findLive render\n    if (current_list_stop)\n      current_list_stop.stop();\n\n    var query = {list_id: list_id};\n    if (Session.get('tag_filter'))\n      query.tags = Session.get('tag_filter')\n\n    // render individual todo list, stash kill function\n    current_list_stop =\n      Meteor.ui.renderList(Todos, $('#item-list'), {\n        selector: query,\n        sort: {timestamp: 1},\n        render: renderItem,\n        events: {}\n      });\n  };\n\n  // render list of lists in the left sidebar.\n  Meteor.ui.renderList(Lists, $('#lists'), {\n    sort: {name: 1},\n    template: $('#list-template'),\n    events: {\n      'click': function (evt) {\n        window.History.pushState({list_id: this._id},\n                                 \"Todos: \" + this.name,\n                                 \"/\" + this._id);\n      },\n      'dblclick': function (evt) {\n        var list_elt = $(evt.currentTarget);\n        var input = list_elt.find('.list-name-input');\n\n        list_elt.addClass('editing');\n\n        input.val(this.name);\n        input.focus();\n        input.select();\n\n        var _id = this._id;\n        input.onBlurOrEnter(function () {\n          list_elt.removeClass('editing');\n          if (input.val() !== '')\n            Lists.update(_id, {$set: {name: input.val()}});\n        });\n      }\n    }\n  });\n\n  // construct new todo list from text box\n  $('#new-list').bind('keypress', function (evt) {\n    var text = $('#new-list').val();\n\n    if (evt.keyCode === 13 && text) {\n      var list = Lists.insert({name: text});\n      $('#new-list').val('');\n      window.History.pushState({list_id: list._id},\n                               \"Todos: \" + list.name,\n                               \"/\" + list._id);\n    }\n  });\n\n  // tags and filters\n\n  // the tag filter bar is easy to generate using a simple\n  // renderList() against a minimongo query.  since minimongo doesn't\n  // support aggregate queries, construct a local collection to serve\n  // the same purpose, and drive the renderList() off of it.\n\n  var LocalTags = new Mongo.Collection;\n  (function () {\n    function updateLocalTags() {\n      var real = _(Todos.find()).chain().pluck('tags').compact().flatten().uniq().value();\n      real.unshift(null); // XXX fake tag\n\n      var computed = _(LocalTags.find()).pluck('tag');\n\n      _.each(_.difference(real, computed), function (new_tag) {\n        LocalTags.insert({tag: new_tag});\n      });\n\n      _.each(_.difference(computed, real), function (dead_tag) {\n        LocalTags.remove({tag: dead_tag});\n      });\n    };\n\n    Todos.findLive({}, {\n      added: function (obj, before_idx) { _.defer(updateLocalTags); },\n      removed: function (id, at_idx) { _.defer(updateLocalTags); },\n      changed: function (obj, at_idx) { _.defer(updateLocalTags); },\n    });\n  })();\n\n  // findLive() against the computed tag table.  since we also want a\n  // show-all button, arrange for the computed table to always include\n  // a null placeholder tag, and for the template to render that as\n  // \"Show all\".  always begin the user session with a null filter.\n\n  Session.set('tag_filter', null);\n\n  Meteor.ui.renderList(LocalTags, $('#tag-filter'), {\n    sort: {tag: 1},\n    template: $('#tag-filter-template'),\n    events: {\n      'click': function (evt) {\n        if (Session.equals('tag_filter', this.tag))\n          Session.set('tag_filter', null);\n        else\n          Session.set('tag_filter', this.tag);\n\n        setCurrentList(Session.get('list_id'));\n      }\n    }\n  });\n\n  // load list on statechange (which we drive from several places).\n  window.History.Adapter.bind(window, 'statechange', function () {\n    var state = window.History.getState();\n    var list = Lists.find(state.data.list_id);\n    setCurrentList(list._id);\n  });\n\n  // subscribe to all available todo lists.  once the inital load\n  // completes, navigate to the list specified by URL, if any.\n  Meteor.subscribe('lists', function () {\n    var initial_list_id = window.location.pathname.split('/')[1];\n    var list;\n\n    if (initial_list_id) {\n      list = Lists.find(initial_list_id);\n    } else {\n      var lists = Lists.find({}, {sort: {name: 1}, limit: 1});\n      list = lists[0];\n    }\n\n    if (list) {\n      window.History.replaceState({list_id: list._id},\n                                  \"Todos: \" + list.name,\n                                  \"/\" + list._id);\n      // replaceState doesn't always trigger statechange on reload. if\n      // you last reloaded the same page and the state is the same, it\n      // won't fire. so call this here. double calling is not great, but\n      // OK.\n      setCurrentList(list._id);\n    }\n  });\n\n  // subscribe to all the items in each list.  no need for a callback\n  // here: todo items are never queried using collection.find().\n  Meteor.subscribe('todos');\n});\n"
  },
  {
    "path": "examples/unfinished/todos-underscore/common.js",
    "content": "Lists = new Mongo.Collection(\"lists\");\n\nTodos = new Mongo.Collection(\"todos\");\n\n/* Schema support coming soon!\n\nLists.schema({text: String});\n\nTodos.schema({text: String,\n              done: Boolean,\n              tags: [String]});\n*/\n\nif (Meteor.isServer) {\n  Meteor.publish('lists', function () {\n    return Lists.find();\n  });\n\n  Meteor.publish('todos', function () {\n    return Todos.find();\n  });\n}\n"
  },
  {
    "path": "examples/unfinished/todos-underscore/main.css",
    "content": "body {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 1.4em;\n  background: #eeeeee;\n  color: #333333;\n}\n\n.ui-layout-north {\n    background: #dddddd;\n}\n\n#tag-filter {\n    margin: 8px;\n}\n\n#items-view {\n    display: none;\n    margin: 10px;\n}\n\n#new-todo {\n    width: 466px;\n    font-size: 24px;\n    font-family: inherit;\n    line-height: 1.4em;\n    border: 0;\n    outline: none;\n    padding: 6px;\n    border: 1px solid #999999;\n    margin-left: 75px;\n}\n\n.ui-layout-west {\n    padding: 10px;\n    border-right: solid 1px #cccccc;\n}\n\n.ui-layout-south {\n    border-top: solid 1px black;\n    padding: 10px;\n    background: #cccccc;\n}\n\n#help p {\n    margin: 8px;\n}\n\n.ui-layout-center {\n    overflow: auto;\n}                    \n\n#lists .list {\n    margin: 2px;\n    font-weight: bold;\n}\n\n#lists .list-name .empty {\n    font-size: 0.9em;\n    font-style: italic;\n}\n\n#lists .editing .display,\n#lists .edit {\n    display: none;\n}\n#lists .editing .edit {\n    display: block;\n}\n#lists .editing input {\n    font-family: inherit;\n    margin: 0;\n    line-height: 1.6em;\n    border: 0;\n    outline: none;\n    padding: 10px 7px 0px 27px;\n    border: 1px solid #999999;\n}\n#lists .selected {\n    background-color: lightblue;\n}\n\n/* todo items */\n\n#item-list {\n    margin-top: 10px;\n}\n\n#item-list li {\n    margin: 12px;\n    font-size: 24px;\n    line-height: 1.1em;\n    border-bottom: 1px solid #cccccc;\n    height: 50px;\n}\n\n#item-list li:after {\n    content: \"\\0020\";\n    display: block;\n    height: 0;\n    clear: both;\n    overflow: hidden;\n    visibility: hidden;\n}\n\n#item-list .destroy {\n    float: left;\n    width: 20px;\n    height: 20px;\n    cursor: pointer;\n    margin-top: 12px;\n    margin-left: 5px;\n}\n\n#item-list li:hover .destroy {\n    background: url('/destroy.png') no-repeat 0 0;\n}\n\n#item-list li .destroy:hover {\n    background-position: 0 -20px;\n}\n\n#item-list .display {\n    float: left;\n    margin: 9px;\n}\n\n#item-list .check {\n    float: left;\n    margin: 9px;\n}\n\n#item-list .edit {\n    float: left;\n}\n\n#item-list .todo-text {\n    float: left;\n}\n\n#item-list li.editing {\n    padding: 0;\n}\n\n#item-list .editing .display,\n#item-list .edit {\n    display: none;\n}\n\n#item-list .editing .edit {\n    display: block;\n}\n\n#item-list .editing input {\n    width: 444px;\n    font-size: 24px;\n    font-family: inherit;\n    margin-left: 38px;\n    line-height: 1.6em;\n    border: 0;\n    outline: none;\n    border: 1px solid #999999;\n}\n\n#item-list .done .todo-text {\n    text-decoration: line-through;\n    color: #777777;\n}\n\n#item-list .item-tags {\n    float: right;\n}\n\n/* tags */\n\n.tag {\n    float: left;\n\n    color: black;\n    background: #aaaaaa;\n    font-size: 16px;\n    font-weight: bold;\n\n    cursor: pointer;\n\n    border: 1px solid black;\n    border-radius: 2px;\n    -webkit-border-radius: 2px;\n    -moz-border-radius: 2px;\n\n    padding: 1px 3px 1px 3px;\n    margin: 4px;\n}\n\n.tag.addtag {\n    background: lightblue;\n    border: 1px dashed black;\n}\n\n.tag.edittag {\n    display: none;\n}\n\n.tag.selected {\n    background: lightblue;\n}\n\n.tag .name {\n    float: left;\n}\n\n.tag .remove {\n    margin-top: 5px;\n    margin-left: 5px;\n    float: left;\n    width: 16px;\n    height: 16px;\n    background-image: url(\"/close_16.png\");\n}\n\n\n"
  },
  {
    "path": "examples/unfinished/todos-underscore/reset.css",
    "content": "html, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, big, cite, code,\ndel, dfn, em, font, img, ins, kbd, q, s, samp,\nsmall, strike, strong, sub, sup, tt, var,\ndl, dt, dd, ol, ul, li,\nfieldset, form, label, legend,\ntable, caption, tbody, tfoot, thead, tr, th, td {\n  margin: 0;\n  padding: 0;\n  border: 0;\n  outline: 0;\n  font-weight: inherit;\n  font-style: inherit;\n  font-size: 100%;\n  font-family: inherit;\n  vertical-align: baseline;\n}\nbody {\n  line-height: 1;\n  color: black;\n  background: white;\n}\nol, ul {\n  list-style: none;\n}\na img {\n  border: none;\n}\n\n"
  },
  {
    "path": "examples/unfinished/todos-underscore/server/bootstrap.js",
    "content": "// if the database is empty on server start, create some sample data.\nMeteor.startup(function () {\n  if (Lists.find().length === 0) {\n    var list1 = Lists.insert({name: 'Things to do'});\n    Todos.insert({list_id: list1._id,\n                  text: 'Write Meteor app', tags: ['fun']});\n    Todos.insert({list_id: list1._id,\n                  text: 'Drink beer', tags: ['fun', 'yum']});\n\n    var list2 = Lists.insert({name: 'Places to see'});\n    Todos.insert({list_id: list2._id, text: 'San Francisco',\n                  tags: ['yum']});\n    Todos.insert({list_id: list2._id, text: 'Paris',\n                  tags: ['fun']});\n    Todos.insert({list_id: list2._id, text: 'Tokyo'});\n\n    var list3 = Lists.insert({name: 'People to meet'});\n    Todos.insert({list_id: list3._id,\n                  text: 'All the cool kids'});\n  }\n});\n"
  },
  {
    "path": "meteor",
    "content": "#!/usr/bin/env bash\n\nBUNDLE_VERSION=0.6.15\n\n# OS Check. Put here because here is where we download the precompiled\n# bundles that are arch specific.\nUNAME=$(uname)\nif [ \"$UNAME\" != \"Linux\" -a \"$UNAME\" != \"Darwin\" ] ; then\n    if [ \"$UNAME\" != \"FreeBSD\" -a \"$UNAME\" != \"OpenBSD\" -a \"$UNAME\" != \"NetBSD\" ] ; then\n        echo \"Sorry, this OS is not supported.\"\n        exit 1\n    fi\nfi\n\n# The METEOR_UNIVERSAL_FLAG will save the indicator how to handle unofficially\n# support environments. For armvXl boards we are support pre built binaries from\n# bintray. For all other systems we check, that there are system binries available\n# for node and mongo. If METEOR_UNIVERSAL_FLAG is not set, then this runs as same \n# as official meteor installer and starter\nMETEOR_UNIVERSAL_FLAG=\n\nif [ \"$UNAME\" = \"Darwin\" ] ; then\n    if [ \"i386\" != \"$(uname -p)\" -o \"1\" != \"$(sysctl -n hw.cpu64bit_capable 2>/dev/null || echo 0)\" ] ; then\n\n        # Can't just test uname -m = x86_64, because Snow Leopard can\n        # return other values.\n        echo \"Only 64-bit Intel processors are supported at this time.\"\n        exit 1\n    fi\n    ARCH=\"x86_64\"\nelif [ \"$UNAME\" = \"Linux\" ] ; then\n    ARCH=\"$(uname -m)\"\n    if [ \"$ARCH\" != \"i686\" -a \"$ARCH\" != \"x86_64\" ] ; then\n        if [ \"$ARCH\" != \"armv6l\" -a \"$ARCH\" != \"armv7l\" ] ; then\n            # set flag that we are in universal system environment support mode\n            METEOR_UNIVERSAL_FLAG=\"env\"\n        else\n            # set flag that we are in unofficial ARM support mode\n            METEOR_UNIVERSAL_FLAG=\"arm\"\n        fi\n    fi\nelif [ \"$UNAME\" = \"FreeBSD\" -o \"$UNAME\" = \"OpenBSD\" -o \"$UNAME\" = \"NetBSD\" ] ; then\n    ARCH=\"$(uname -m)\"\n    if [ \"$ARCH\" != \"i686\" -a \"$ARCH\" != \"x86_64\" -a \"$ARCH\" != \"amd64\" ] ; then\n        # set flag that we are in universal system environment support mode\n        METEOR_UNIVERSAL_FLAG=\"env\"\n    else\n        # set flag that we are in unofficial xBSD support mode\n        METEOR_UNIVERSAL_FLAG=\"bsd\"\n    fi\nfi\nPLATFORM=\"${UNAME}_${ARCH}\"\n\n# Find the script dir, following symlinks. Note that symlink can be relative or\n# absolute. Too bad 'readlink -f' and 'realpath' (the command-line program) are\n# not portable.  We don't stress about infinite loops or bad links, because the\n# OS has already resolved this symlink chain once in order to actually run the\n# shell script.\nORIG_DIR=\"$(pwd)\"\nSCRIPT=\"$0\"\nwhile true; do\n  # The symlink might be relative, so we have to actually cd to the right place\n  # each time in order to resolve it.\n  cd \"$(dirname \"$SCRIPT\")\"\n  if [ ! -L \"$(basename \"$SCRIPT\")\" ]; then\n    SCRIPT_DIR=\"$(pwd -P)\"\n    break\n  fi\n  SCRIPT=\"$(readlink \"$(basename \"$SCRIPT\")\")\"\ndone\ncd \"$ORIG_DIR\"\n\n\n\nfunction install_dev_bundle {\n    set -e\n    trap \"echo Failed to install dependency kit.\" EXIT\n\n    TARBALL=\"dev_bundle_${PLATFORM}_${BUNDLE_VERSION}.tar.gz\"\n    BUNDLE_TMPDIR=\"$SCRIPT_DIR/dev_bundle.xxx\"\n\n    rm -rf \"$BUNDLE_TMPDIR\"\n    mkdir \"$BUNDLE_TMPDIR\"\n\n    # duplicated in scripts/windows/download-dev-bundle.ps1:\n    DEV_BUNDLE_URL_ROOT=\"https://d3sqy0vbqsdhku.cloudfront.net/\"\n    # If you set $USE_TEST_DEV_BUNDLE_SERVER then we will download\n    # dev bundles copied by copy-dev-bundle-from-jenkins.sh without --prod.\n    # It still only does this if the version number has changed\n    # (setting it won't cause it to automatically delete a prod dev bundle).\n    if [ -n \"$USE_TEST_DEV_BUNDLE_SERVER\" ] ; then\n        DEV_BUNDLE_URL_ROOT=\"https://s3.amazonaws.com/com.meteor.static/test/\"\n    fi\n\n    # test for unofficial supported architecture based dev_bundles\n    if [ -n \"$METEOR_UNIVERSAL_FLAG\" ] ; then\n        # Use bintray release downloads\n        DEV_BUNDLE_URL_ROOT=\"https://dl.bintray.com/4commerce-technologies-ag/meteor-universal/${METEOR_UNIVERSAL_FLAG}_dev_bundles/\"\n    fi\n\n    # test if we can download the dev_bundle tarball\n    function __check_tarball_download() {\n      CHECK_TARBALL=$(curl --head --location --silent \"$DEV_BUNDLE_URL_ROOT$TARBALL\" --output /dev/null --write-out '%{http_code}')\n      # Write down a message instead doing a false download\n      if [ \"$CHECK_TARBALL\" != \"200\" ] ; then\n        if [ -n \"$METEOR_UNIVERSAL_FLAG\" ] ; then\n            # We have identified that there is no pre built dev_bundle available\n            # and we do not provide yet downloadable pre builts for that platform\n            echo \"\"\n            echo \"You are trying to run Meteor on yet not official supported platform: ${PLATFORM}\"\n            echo \"There is currently no pre-built dev_bundle available for your system.\"\n            echo \"Check https://github.com/4commerce-technologies-AG/meteor to get\"\n            echo \"the information how you may generate your own dev_bundle using\"\n            echo \"scripts/generate-dev-bundle.sh\"\n            echo \"\"\n        fi\n        echo \"Unable to download: $DEV_BUNDLE_URL_ROOT$TARBALL\"\n        echo \"Pre-built tarball is not available!\"\n        echo \"\"\n        exit 1\n      fi\n    }\n\n    if [ -f \"$SCRIPT_DIR/$TARBALL\" ] ; then\n        echo \"Skipping download and installing kit from $SCRIPT_DIR/$TARBALL\" >&2\n        tar -xzf \"$SCRIPT_DIR/$TARBALL\" -C \"$BUNDLE_TMPDIR\"\n    elif [ -n \"$SAVE_DEV_BUNDLE_TARBALL\" ] ; then\n        # URL duplicated in tools/server/target.sh.in\n        __check_tarball_download\n        curl --location -# \"$DEV_BUNDLE_URL_ROOT$TARBALL\" >\"$SCRIPT_DIR/$TARBALL\"\n        tar -xzf \"$SCRIPT_DIR/$TARBALL\" -C \"$BUNDLE_TMPDIR\"\n    else\n        __check_tarball_download\n        curl --location -# \"$DEV_BUNDLE_URL_ROOT$TARBALL\" | tar -xzf - -C \"$BUNDLE_TMPDIR\"\n    fi\n\n    # In case that we have to use the universal system environment, make sure\n    # that at least the necessary linked binaries are available and linked to\n    # the correct system binaries. If detect a linked binary just set the link\n    # again to the installed system one after unpacking\n    if [ -L \"$BUNDLE_TMPDIR/bin/node\" ] ; then\n        # test for system installed binaries\n        if [ -z \"$(which node 2>/dev/null)\" -o -z \"$(which npm 2>/dev/null)\" ] ; then\n            echo \"Meteor officially supports only Linux i686 and x86_64 and OSX architecture for now.\"\n            echo \"Meteor universal unofficially supports arm, bsd and universal architectures as well.\"\n            echo \"To use the universal system environment make sure that the necessary binaries are pre-installed.\"\n            echo \"Please make sure that node (compatible to $NODE_VERSION) and npm is installed.\"\n            echo -e \"\\tnode version:\" $(which node 2>/dev/null)\n            echo -e \"\\tnpm version:\" $(which npm 2>/dev/null)\n            exit 1\n        fi\n        # remove the link from dev_bundle tgz and reset new to existing binary\n        rm -f \"$BUNDLE_TMPDIR/bin/node\"\n        rm -f \"$BUNDLE_TMPDIR/bin/npm\"\n        ln -s \"$(which node)\" \"$BUNDLE_TMPDIR/bin/node\"\n        ln -s \"$(which npm)\"  \"$BUNDLE_TMPDIR/bin/npm\"\n    fi\n\n    if [ -L \"$BUNDLE_TMPDIR/mongodb/bin/mongod\" ] ; then\n        # test for system installed binaries\n        if [ -z \"$(which mongo 2>/dev/null)\" -o -z \"$(which mongod 2>/dev/null)\" ] ; then\n            echo \"Meteor officially supports only Linux i686 and x86_64 and OSX architecture for now.\"\n            echo \"Meteor universal unofficially supports arm, bsd and universal architectures as well.\"\n            echo \"To use the universal system environment make sure that the necessary binaries are pre-installed.\"\n            echo \"Please make sure that mongo and mongod is installed.\"\n            echo -e \"\\tmongo version:\" $(which mongo 2>/dev/null)\n            echo -e \"\\tmongod version:\" $(which mongod 2>/dev/null)\n            exit 1\n        fi\n        # remove the link from dev_bundle tgz and reset new to existing binary\n        rm -f \"$BUNDLE_TMPDIR/mongodb/bin/mongo\"\n        rm -f \"$BUNDLE_TMPDIR/mongodb/bin/mongod\"\n        ln -s \"$(which mongo 2>/dev/null)\"  \"$BUNDLE_TMPDIR/mongodb/bin/mongo\"\n        ln -s \"$(which mongod 2>/dev/null)\" \"$BUNDLE_TMPDIR/mongodb/bin/mongod\"\n    fi\n\n    test -x \"${BUNDLE_TMPDIR}/bin/node\" # bomb out if it didn't work, eg no net\n\n    # Delete old dev bundle and rename the new one on top of it.\n    rm -rf \"$SCRIPT_DIR/dev_bundle\"\n    mv \"$BUNDLE_TMPDIR\" \"$SCRIPT_DIR/dev_bundle\"\n\n    echo \"Installed dependency kit v${BUNDLE_VERSION} in dev_bundle.\" >&2\n    echo >&2\n\n    trap - EXIT\n    set +e\n}\n\n\nif [ -d \"$SCRIPT_DIR/.git\" ] || [ -f \"$SCRIPT_DIR/.git\" ]; then\n    # In a checkout.\n    if [ ! -d \"$SCRIPT_DIR/dev_bundle\" ] ; then\n        echo \"It's the first time you've run Meteor from a git checkout.\" >&2\n        echo \"I will download a kit containing all of Meteor's dependencies.\" >&2\n        install_dev_bundle\n    elif [ ! -f \"$SCRIPT_DIR/dev_bundle/.bundle_version.txt\" ] ||\n        grep -qvx \"$BUNDLE_VERSION\" \"$SCRIPT_DIR/dev_bundle/.bundle_version.txt\" ; then\n        echo \"Your dependency kit is out of date. I will download the new one.\" >&2\n        install_dev_bundle\n    fi\n\n    export BABEL_CACHE_DIR=\"$SCRIPT_DIR/.babel-cache\"\nfi\n\nDEV_BUNDLE=\"$SCRIPT_DIR/dev_bundle\"\nMETEOR=\"$SCRIPT_DIR/tools/index.js\"\n\n\n# Bump our file descriptor ulimit as high as it will go. This is a\n# temporary workaround for dependancy watching holding open too many\n# files: https://app.asana.com/0/364581412985/472479912325\nif [ \"$(ulimit -n)\" != \"unlimited\" ] ; then\n    ulimit -n 16384 > /dev/null 2>&1 || \\\n    ulimit -n 8192 > /dev/null 2>&1 || \\\n    ulimit -n 4096 > /dev/null 2>&1 || \\\n    ulimit -n 2048 > /dev/null 2>&1 || \\\n    ulimit -n 1024 > /dev/null 2>&1 || \\\n    ulimit -n 512 > /dev/null 2>&1\nfi\n\n\n# set ENV VAR and include non-core packages per default if $PACKAGE_DIRS\n# is not set already\nif [ -z \"$PACKAGE_DIRS\" ] && [ -d \"$SCRIPT_DIR/packages/non-core\" ] ; then\n  export PACKAGE_DIRS=$SCRIPT_DIR/packages/non-core\nfi\n\n\n# We used to set $NODE_PATH here to include the node_modules from the dev\n# bundle, but now we just get them from the symlink at tools/node_modules. This\n# is better because node_modules directories found via the ancestor walk from\n# the script take precedence over $NODE_PATH; it used to be that users would\n# screw up their meteor installs by have a ~/node_modules\n\nexec \"$DEV_BUNDLE/bin/node\" ${TOOL_NODE_FLAGS} \"$METEOR\" \"$@\"\n"
  },
  {
    "path": "meteor.bat",
    "content": "@echo off\n\nSETLOCAL\nrem only if we are running from a checkout\nIF EXIST \"%~dp0\\.git\" (\n  rem verify that we have 7zip in the path\n  7z.exe --help > nul\n  IF errorlevel 1 (\n    REM For some reason, without quotes this line causes an error\n    echo \"Please install 7z.exe (7-Zip) and put it into your PATH\"\n    exit /b 1\n  )\n\n  rem if dev_bundle is not present, get it\n  IF NOT EXIST \"%~dp0\\dev_bundle\" (\n    REM need `< con` so that we can run this file from Node\n    REM (See http://stackoverflow.com/questions/9155289/calling-powershell-from-nodejs)\n    PowerShell.exe -executionpolicy ByPass -file \"%~dp0\\scripts\\windows\\download-dev-bundle.ps1\" < con\n  )\n\n  rem if dev_bundle is the wrong version, remove it and get a new one\n  PowerShell.exe -executionpolicy ByPass -file \"%~dp0\\scripts\\windows\\check-dev-bundle.ps1\" < con\n\n  IF errorlevel 1 (\n    rmdir /s /q \"%~dp0\\dev_bundle\"\n    IF EXIST \"%~dp0\\dev_bundle\" (\n      echo Couldn't delete old dependency kit. Please try again.\n      exit /b 1\n    )\n    PowerShell.exe -executionpolicy ByPass -file \"%~dp0\\scripts\\windows\\download-dev-bundle.ps1\" < con\n  )\n\n  rem Only set this when we're in a checkout. When running from a release,\n  rem this is correctly set in the top-level `meteor.bat` file\n  SET METEOR_INSTALLATION=%~dp0\n)\n\nSET NODE_PATH=%~dp0\\dev_bundle\\lib\\node_modules\nSET BABEL_CACHE_DIR=%~dp0\\.babel-cache\n\n\"%~dp0\\dev_bundle\\bin\\node.exe\" \"%~dp0\\tools\\index.js\" %*\nENDLOCAL\n\nEXIT /b %ERRORLEVEL%\n\n"
  },
  {
    "path": "packages/.gitignore",
    "content": ".meteor\n*/.meteor"
  },
  {
    "path": "packages/accounts-base/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/accounts-base/README.md",
    "content": "# accounts-base\n\nMeteor's user account system. This package implements the basic functions necessary for user accounts and lets other packages register login services. Some of these services are in the following packages:\n\n- `accounts-password`\n- `accounts-facebook`\n- `accounts-google`\n- `accounts-github`\n- `accounts-twitter`\n- `accounts-meetup`\n- `accounts-weibo`\n\nThere are also login services available in community packages.\n\nFor more information, see the [Meteor docs](http://docs.meteor.com/#accounts_api) and the Meteor Accounts [project page](https://www.meteor.com/accounts).\n"
  },
  {
    "path": "packages/accounts-base/accounts_client.js",
    "content": "import {AccountsCommon} from \"./accounts_common.js\";\n\n/**\n * @summary Constructor for the `Accounts` object on the client.\n * @locus Client\n * @class AccountsClient\n * @extends AccountsCommon\n * @instancename accountsClient\n * @param {Object} options an object with fields:\n * @param {Object} options.connection Optional DDP connection to reuse.\n * @param {String} options.ddpUrl Optional URL for creating a new DDP connection.\n */\nexport class AccountsClient extends AccountsCommon {\n  constructor(options) {\n    super(options);\n\n    this._loggingIn = false;\n    this._loggingInDeps = new Tracker.Dependency;\n\n    this._loginServicesHandle =\n      this.connection.subscribe(\"meteor.loginServiceConfiguration\");\n\n    this._pageLoadLoginCallbacks = [];\n    this._pageLoadLoginAttemptInfo = null;\n\n    // Defined in url_client.js.\n    this._initUrlMatching();\n\n    // Defined in localstorage_token.js.\n    this._initLocalStorage();\n  }\n\n  ///\n  /// CURRENT USER\n  ///\n\n  // @override\n  userId() {\n    return this.connection.userId();\n  }\n\n  // This is mostly just called within this file, but Meteor.loginWithPassword\n  // also uses it to make loggingIn() be true during the beginPasswordExchange\n  // method call too.\n  _setLoggingIn(x) {\n    if (this._loggingIn !== x) {\n      this._loggingIn = x;\n      this._loggingInDeps.changed();\n    }\n  }\n\n  /**\n   * @summary True if a login method (such as `Meteor.loginWithPassword`, `Meteor.loginWithFacebook`, or `Accounts.createUser`) is currently in progress. A reactive data source.\n   * @locus Client\n   */\n  loggingIn() {\n    this._loggingInDeps.depend();\n    return this._loggingIn;\n  }\n\n  /**\n   * @summary Log the user out.\n   * @locus Client\n   * @param {Function} [callback] Optional callback. Called with no arguments on success, or with a single `Error` argument on failure.\n   */\n  logout(callback) {\n    var self = this;\n    self.connection.apply('logout', [], {\n      wait: true\n    }, function (error, result) {\n      if (error) {\n        callback && callback(error);\n      } else {\n        self.makeClientLoggedOut();\n        callback && callback();\n      }\n    });\n  }\n\n  /**\n   * @summary Log out other clients logged in as the current user, but does not log out the client that calls this function.\n   * @locus Client\n   * @param {Function} [callback] Optional callback. Called with no arguments on success, or with a single `Error` argument on failure.\n   */\n  logoutOtherClients(callback) {\n    var self = this;\n\n    // We need to make two method calls: one to replace our current token,\n    // and another to remove all tokens except the current one. We want to\n    // call these two methods one after the other, without any other\n    // methods running between them. For example, we don't want `logout`\n    // to be called in between our two method calls (otherwise the second\n    // method call would return an error). Another example: we don't want\n    // logout to be called before the callback for `getNewToken`;\n    // otherwise we would momentarily log the user out and then write a\n    // new token to localStorage.\n    //\n    // To accomplish this, we make both calls as wait methods, and queue\n    // them one after the other, without spinning off the event loop in\n    // between. Even though we queue `removeOtherTokens` before\n    // `getNewToken`, we won't actually send the `removeOtherTokens` call\n    // until the `getNewToken` callback has finished running, because they\n    // are both wait methods.\n    self.connection.apply(\n      'getNewToken',\n      [],\n      { wait: true },\n      function (err, result) {\n        if (! err) {\n          self._storeLoginToken(\n            self.userId(),\n            result.token,\n            result.tokenExpires\n          );\n        }\n      }\n    );\n\n    self.connection.apply(\n      'removeOtherTokens',\n      [],\n      { wait: true },\n      function (err) {\n        callback && callback(err);\n      }\n    );\n  }\n};\n\nvar Ap = AccountsClient.prototype;\n\n/**\n * @summary True if a login method (such as `Meteor.loginWithPassword`, `Meteor.loginWithFacebook`, or `Accounts.createUser`) is currently in progress. A reactive data source.\n * @locus Client\n * @importFromPackage meteor\n */\nMeteor.loggingIn = function () {\n  return Accounts.loggingIn();\n};\n\n///\n/// LOGIN METHODS\n///\n\n// Call a login method on the server.\n//\n// A login method is a method which on success calls `this.setUserId(id)` and\n// `Accounts._setLoginToken` on the server and returns an object with fields\n// 'id' (containing the user id), 'token' (containing a resume token), and\n// optionally `tokenExpires`.\n//\n// This function takes care of:\n//   - Updating the Meteor.loggingIn() reactive data source\n//   - Calling the method in 'wait' mode\n//   - On success, saving the resume token to localStorage\n//   - On success, calling Accounts.connection.setUserId()\n//   - Setting up an onReconnect handler which logs in with\n//     the resume token\n//\n// Options:\n// - methodName: The method to call (default 'login')\n// - methodArguments: The arguments for the method\n// - validateResult: If provided, will be called with the result of the\n//                 method. If it throws, the client will not be logged in (and\n//                 its error will be passed to the callback).\n// - userCallback: Will be called with no arguments once the user is fully\n//                 logged in, or with the error on error.\n//\nAp.callLoginMethod = function (options) {\n  var self = this;\n\n  options = _.extend({\n    methodName: 'login',\n    methodArguments: [{}],\n    _suppressLoggingIn: false\n  }, options);\n\n  // Set defaults for callback arguments to no-op functions; make sure we\n  // override falsey values too.\n  _.each(['validateResult', 'userCallback'], function (f) {\n    if (!options[f])\n      options[f] = function () {};\n  });\n\n  // Prepare callbacks: user provided and onLogin/onLoginFailure hooks.\n  var loginCallbacks = _.once(function (error) {\n    if (!error) {\n      self._onLoginHook.each(function (callback) {\n        callback();\n        return true;\n      });\n    } else {\n      self._onLoginFailureHook.each(function (callback) {\n        callback();\n        return true;\n      });\n    }\n    options.userCallback.apply(this, arguments);\n  });\n\n  var reconnected = false;\n\n  // We want to set up onReconnect as soon as we get a result token back from\n  // the server, without having to wait for subscriptions to rerun. This is\n  // because if we disconnect and reconnect between getting the result and\n  // getting the results of subscription rerun, we WILL NOT re-send this\n  // method (because we never re-send methods whose results we've received)\n  // but we WILL call loggedInAndDataReadyCallback at \"reconnect quiesce\"\n  // time. This will lead to makeClientLoggedIn(result.id) even though we\n  // haven't actually sent a login method!\n  //\n  // But by making sure that we send this \"resume\" login in that case (and\n  // calling makeClientLoggedOut if it fails), we'll end up with an accurate\n  // client-side userId. (It's important that livedata_connection guarantees\n  // that the \"reconnect quiesce\"-time call to loggedInAndDataReadyCallback\n  // will occur before the callback from the resume login call.)\n  var onResultReceived = function (err, result) {\n    if (err || !result || !result.token) {\n      // Leave onReconnect alone if there was an error, so that if the user was\n      // already logged in they will still get logged in on reconnect.\n      // See issue #4970.\n    } else {\n      self.connection.onReconnect = function () {\n        reconnected = true;\n        // If our token was updated in storage, use the latest one.\n        var storedToken = self._storedLoginToken();\n        if (storedToken) {\n          result = {\n            token: storedToken,\n            tokenExpires: self._storedLoginTokenExpires()\n          };\n        }\n        if (! result.tokenExpires)\n          result.tokenExpires = self._tokenExpiration(new Date());\n        if (self._tokenExpiresSoon(result.tokenExpires)) {\n          self.makeClientLoggedOut();\n        } else {\n          self.callLoginMethod({\n            methodArguments: [{resume: result.token}],\n            // Reconnect quiescence ensures that the user doesn't see an\n            // intermediate state before the login method finishes. So we don't\n            // need to show a logging-in animation.\n            _suppressLoggingIn: true,\n            userCallback: function (error) {\n              var storedTokenNow = self._storedLoginToken();\n              if (error) {\n                // If we had a login error AND the current stored token is the\n                // one that we tried to log in with, then declare ourselves\n                // logged out. If there's a token in storage but it's not the\n                // token that we tried to log in with, we don't know anything\n                // about whether that token is valid or not, so do nothing. The\n                // periodic localStorage poll will decide if we are logged in or\n                // out with this token, if it hasn't already. Of course, even\n                // with this check, another tab could insert a new valid token\n                // immediately before we clear localStorage here, which would\n                // lead to both tabs being logged out, but by checking the token\n                // in storage right now we hope to make that unlikely to happen.\n                //\n                // If there is no token in storage right now, we don't have to\n                // do anything; whatever code removed the token from storage was\n                // responsible for calling `makeClientLoggedOut()`, or the\n                // periodic localStorage poll will call `makeClientLoggedOut`\n                // eventually if another tab wiped the token from storage.\n                if (storedTokenNow && storedTokenNow === result.token) {\n                  self.makeClientLoggedOut();\n                }\n              }\n              // Possibly a weird callback to call, but better than nothing if\n              // there is a reconnect between \"login result received\" and \"data\n              // ready\".\n              loginCallbacks(error);\n            }});\n        }\n      };\n    }\n  };\n\n  // This callback is called once the local cache of the current-user\n  // subscription (and all subscriptions, in fact) are guaranteed to be up to\n  // date.\n  var loggedInAndDataReadyCallback = function (error, result) {\n    // If the login method returns its result but the connection is lost\n    // before the data is in the local cache, it'll set an onReconnect (see\n    // above). The onReconnect will try to log in using the token, and *it*\n    // will call userCallback via its own version of this\n    // loggedInAndDataReadyCallback. So we don't have to do anything here.\n    if (reconnected)\n      return;\n\n    // Note that we need to call this even if _suppressLoggingIn is true,\n    // because it could be matching a _setLoggingIn(true) from a\n    // half-completed pre-reconnect login method.\n    self._setLoggingIn(false);\n    if (error || !result) {\n      error = error || new Error(\n        \"No result from call to \" + options.methodName);\n      loginCallbacks(error);\n      return;\n    }\n    try {\n      options.validateResult(result);\n    } catch (e) {\n      loginCallbacks(e);\n      return;\n    }\n\n    // Make the client logged in. (The user data should already be loaded!)\n    self.makeClientLoggedIn(result.id, result.token, result.tokenExpires);\n    loginCallbacks();\n  };\n\n  if (!options._suppressLoggingIn)\n    self._setLoggingIn(true);\n  self.connection.apply(\n    options.methodName,\n    options.methodArguments,\n    {wait: true, onResultReceived: onResultReceived},\n    loggedInAndDataReadyCallback);\n};\n\nAp.makeClientLoggedOut = function () {\n  // Ensure client was successfully logged in before running logout hooks.\n  if (this.connection._userId) {\n    this._onLogoutHook.each(function (callback) {\n      callback();\n      return true;\n    });\n  }\n  this._unstoreLoginToken();\n  this.connection.setUserId(null);\n  this.connection.onReconnect = null;\n};\n\nAp.makeClientLoggedIn = function (userId, token, tokenExpires) {\n  this._storeLoginToken(userId, token, tokenExpires);\n  this.connection.setUserId(userId);\n};\n\n/**\n * @summary Log the user out.\n * @locus Client\n * @param {Function} [callback] Optional callback. Called with no arguments on success, or with a single `Error` argument on failure.\n * @importFromPackage meteor\n */\nMeteor.logout = function (callback) {\n  return Accounts.logout(callback);\n};\n\n/**\n * @summary Log out other clients logged in as the current user, but does not log out the client that calls this function.\n * @locus Client\n * @param {Function} [callback] Optional callback. Called with no arguments on success, or with a single `Error` argument on failure.\n * @importFromPackage meteor\n */\nMeteor.logoutOtherClients = function (callback) {\n  return Accounts.logoutOtherClients(callback);\n};\n\n\n///\n/// LOGIN SERVICES\n///\n\n// A reactive function returning whether the loginServiceConfiguration\n// subscription is ready. Used by accounts-ui to hide the login button\n// until we have all the configuration loaded\n//\nAp.loginServicesConfigured = function () {\n  return this._loginServicesHandle.ready();\n};\n\n\n// Some login services such as the redirect login flow or the resume\n// login handler can log the user in at page load time.  The\n// Meteor.loginWithX functions have a callback argument, but the\n// callback function instance won't be in memory any longer if the\n// page was reloaded.  The `onPageLoadLogin` function allows a\n// callback to be registered for the case where the login was\n// initiated in a previous VM, and we now have the result of the login\n// attempt in a new VM.\n\n// Register a callback to be called if we have information about a\n// login attempt at page load time.  Call the callback immediately if\n// we already have the page load login attempt info, otherwise stash\n// the callback to be called if and when we do get the attempt info.\n//\nAp.onPageLoadLogin = function (f) {\n  if (this._pageLoadLoginAttemptInfo) {\n    f(this._pageLoadLoginAttemptInfo);\n  } else {\n    this._pageLoadLoginCallbacks.push(f);\n  }\n};\n\n\n// Receive the information about the login attempt at page load time.\n// Call registered callbacks, and also record the info in case\n// someone's callback hasn't been registered yet.\n//\nAp._pageLoadLogin = function (attemptInfo) {\n  if (this._pageLoadLoginAttemptInfo) {\n    Meteor._debug(\"Ignoring unexpected duplicate page load login attempt info\");\n    return;\n  }\n\n  _.each(this._pageLoadLoginCallbacks, function (callback) {\n    callback(attemptInfo);\n  });\n\n  this._pageLoadLoginCallbacks = [];\n  this._pageLoadLoginAttemptInfo = attemptInfo;\n};\n\n\n///\n/// HANDLEBARS HELPERS\n///\n\n// If our app has a Blaze, register the {{currentUser}} and {{loggingIn}}\n// global helpers.\nif (Package.blaze) {\n  /**\n   * @global\n   * @name  currentUser\n   * @isHelper true\n   * @summary Calls [Meteor.user()](#meteor_user). Use `{{#if currentUser}}` to check whether the user is logged in.\n   */\n  Package.blaze.Blaze.Template.registerHelper('currentUser', function () {\n    return Meteor.user();\n  });\n\n  /**\n   * @global\n   * @name  loggingIn\n   * @isHelper true\n   * @summary Calls [Meteor.loggingIn()](#meteor_loggingin).\n   */\n  Package.blaze.Blaze.Template.registerHelper('loggingIn', function () {\n    return Meteor.loggingIn();\n  });\n}\n"
  },
  {
    "path": "packages/accounts-base/accounts_common.js",
    "content": "/**\n * @summary Super-constructor for AccountsClient and AccountsServer.\n * @locus Anywhere\n * @class AccountsCommon\n * @instancename accountsClientOrServer\n * @param options {Object} an object with fields:\n * - connection {Object} Optional DDP connection to reuse.\n * - ddpUrl {String} Optional URL for creating a new DDP connection.\n */\nexport class AccountsCommon {\n  constructor(options) {\n    // Currently this is read directly by packages like accounts-password\n    // and accounts-ui-unstyled.\n    this._options = {};\n\n    // Note that setting this.connection = null causes this.users to be a\n    // LocalCollection, which is not what we want.\n    this.connection = undefined;\n    this._initConnection(options || {});\n\n    // There is an allow call in accounts_server.js that restricts writes to\n    // this collection.\n    this.users = new Mongo.Collection(\"users\", {\n      _preventAutopublish: true,\n      connection: this.connection\n    });\n\n    // Callback exceptions are printed with Meteor._debug and ignored.\n    this._onLoginHook = new Hook({\n      bindEnvironment: false,\n      debugPrintExceptions: \"onLogin callback\"\n    });\n\n    this._onLoginFailureHook = new Hook({\n      bindEnvironment: false,\n      debugPrintExceptions: \"onLoginFailure callback\"\n    });\n\n    this._onLogoutHook = new Hook({\n      bindEnvironment: false,\n      debugPrintExceptions: \"onLogout callback\"\n    });\n  }\n\n  /**\n   * @summary Get the current user id, or `null` if no user is logged in. A reactive data source.\n   * @locus Anywhere but publish functions\n   */\n  userId() {\n    throw new Error(\"userId method not implemented\");\n  }\n\n  /**\n   * @summary Get the current user record, or `null` if no user is logged in. A reactive data source.\n   * @locus Anywhere but publish functions\n   */\n  user() {\n    var userId = this.userId();\n    return userId ? this.users.findOne(userId) : null;\n  }\n\n  // Set up config for the accounts system. Call this on both the client\n  // and the server.\n  //\n  // Note that this method gets overridden on AccountsServer.prototype, but\n  // the overriding method calls the overridden method.\n  //\n  // XXX we should add some enforcement that this is called on both the\n  // client and the server. Otherwise, a user can\n  // 'forbidClientAccountCreation' only on the client and while it looks\n  // like their app is secure, the server will still accept createUser\n  // calls. https://github.com/meteor/meteor/issues/828\n  //\n  // @param options {Object} an object with fields:\n  // - sendVerificationEmail {Boolean}\n  //     Send email address verification emails to new users created from\n  //     client signups.\n  // - forbidClientAccountCreation {Boolean}\n  //     Do not allow clients to create accounts directly.\n  // - restrictCreationByEmailDomain {Function or String}\n  //     Require created users to have an email matching the function or\n  //     having the string as domain.\n  // - loginExpirationInDays {Number}\n  //     Number of days since login until a user is logged out (login token\n  //     expires).\n\n  /**\n   * @summary Set global accounts options.\n   * @locus Anywhere\n   * @param {Object} options\n   * @param {Boolean} options.sendVerificationEmail New users with an email address will receive an address verification email.\n   * @param {Boolean} options.forbidClientAccountCreation Calls to [`createUser`](#accounts_createuser) from the client will be rejected. In addition, if you are using [accounts-ui](#accountsui), the \"Create account\" link will not be available.\n   * @param {String | Function} options.restrictCreationByEmailDomain If set to a string, only allows new users if the domain part of their email address matches the string. If set to a function, only allows new users if the function returns true.  The function is passed the full email address of the proposed new user.  Works with password-based sign-in and external services that expose email addresses (Google, Facebook, GitHub). All existing users still can log in after enabling this option. Example: `Accounts.config({ restrictCreationByEmailDomain: 'school.edu' })`.\n   * @param {Number} options.loginExpirationInDays The number of days from when a user logs in until their token expires and they are logged out. Defaults to 90. Set to `null` to disable login expiration.\n   * @param {String} options.oauthSecretKey When using the `oauth-encryption` package, the 16 byte key using to encrypt sensitive account credentials in the database, encoded in base64.  This option may only be specifed on the server.  See packages/oauth-encryption/README.md for details.\n   */\n  config(options) {\n    var self = this;\n\n    // We don't want users to accidentally only call Accounts.config on the\n    // client, where some of the options will have partial effects (eg removing\n    // the \"create account\" button from accounts-ui if forbidClientAccountCreation\n    // is set, or redirecting Google login to a specific-domain page) without\n    // having their full effects.\n    if (Meteor.isServer) {\n      __meteor_runtime_config__.accountsConfigCalled = true;\n    } else if (!__meteor_runtime_config__.accountsConfigCalled) {\n      // XXX would be nice to \"crash\" the client and replace the UI with an error\n      // message, but there's no trivial way to do this.\n      Meteor._debug(\"Accounts.config was called on the client but not on the \" +\n                    \"server; some configuration options may not take effect.\");\n    }\n\n    // We need to validate the oauthSecretKey option at the time\n    // Accounts.config is called. We also deliberately don't store the\n    // oauthSecretKey in Accounts._options.\n    if (_.has(options, \"oauthSecretKey\")) {\n      if (Meteor.isClient)\n        throw new Error(\"The oauthSecretKey option may only be specified on the server\");\n      if (! Package[\"oauth-encryption\"])\n        throw new Error(\"The oauth-encryption package must be loaded to set oauthSecretKey\");\n      Package[\"oauth-encryption\"].OAuthEncryption.loadKey(options.oauthSecretKey);\n      options = _.omit(options, \"oauthSecretKey\");\n    }\n\n    // validate option keys\n    var VALID_KEYS = [\"sendVerificationEmail\", \"forbidClientAccountCreation\",\n                      \"restrictCreationByEmailDomain\", \"loginExpirationInDays\"];\n    _.each(_.keys(options), function (key) {\n      if (!_.contains(VALID_KEYS, key)) {\n        throw new Error(\"Accounts.config: Invalid key: \" + key);\n      }\n    });\n\n    // set values in Accounts._options\n    _.each(VALID_KEYS, function (key) {\n      if (key in options) {\n        if (key in self._options) {\n          throw new Error(\"Can't set `\" + key + \"` more than once\");\n        }\n        self._options[key] = options[key];\n      }\n    });\n  }\n\n  /**\n   * @summary Register a callback to be called after a login attempt succeeds.\n   * @locus Anywhere\n   * @param {Function} func The callback to be called when login is successful.\n   */\n  onLogin(func) {\n    return this._onLoginHook.register(func);\n  }\n\n  /**\n   * @summary Register a callback to be called after a login attempt fails.\n   * @locus Anywhere\n   * @param {Function} func The callback to be called after the login has failed.\n   */\n  onLoginFailure(func) {\n    return this._onLoginFailureHook.register(func);\n  }\n\n  /**\n   * @summary Register a callback to be called after a logout attempt succeeds.\n   * @locus Anywhere\n   * @param {Function} func The callback to be called when logout is successful.\n   */\n  onLogout(func) {\n    return this._onLogoutHook.register(func);\n  }\n\n  _initConnection(options) {\n    if (! Meteor.isClient) {\n      return;\n    }\n\n    // The connection used by the Accounts system. This is the connection\n    // that will get logged in by Meteor.login(), and this is the\n    // connection whose login state will be reflected by Meteor.userId().\n    //\n    // It would be much preferable for this to be in accounts_client.js,\n    // but it has to be here because it's needed to create the\n    // Meteor.users collection.\n\n    if (options.connection) {\n      this.connection = options.connection;\n    } else if (options.ddpUrl) {\n      this.connection = DDP.connect(options.ddpUrl);\n    } else if (typeof __meteor_runtime_config__ !== \"undefined\" &&\n               __meteor_runtime_config__.ACCOUNTS_CONNECTION_URL) {\n      // Temporary, internal hook to allow the server to point the client\n      // to a different authentication server. This is for a very\n      // particular use case that comes up when implementing a oauth\n      // server. Unsupported and may go away at any point in time.\n      //\n      // We will eventually provide a general way to use account-base\n      // against any DDP connection, not just one special one.\n      this.connection =\n        DDP.connect(__meteor_runtime_config__.ACCOUNTS_CONNECTION_URL);\n    } else {\n      this.connection = Meteor.connection;\n    }\n  }\n\n  _getTokenLifetimeMs() {\n    return (this._options.loginExpirationInDays ||\n            DEFAULT_LOGIN_EXPIRATION_DAYS) * 24 * 60 * 60 * 1000;\n  }\n\n  _tokenExpiration(when) {\n    // We pass when through the Date constructor for backwards compatibility;\n    // `when` used to be a number.\n    return new Date((new Date(when)).getTime() + this._getTokenLifetimeMs());\n  }\n\n  _tokenExpiresSoon(when) {\n    var minLifetimeMs = .1 * this._getTokenLifetimeMs();\n    var minLifetimeCapMs = MIN_TOKEN_LIFETIME_CAP_SECS * 1000;\n    if (minLifetimeMs > minLifetimeCapMs)\n      minLifetimeMs = minLifetimeCapMs;\n    return new Date() > (new Date(when) - minLifetimeMs);\n  }\n}\n\nvar Ap = AccountsCommon.prototype;\n\n// Note that Accounts is defined separately in accounts_client.js and\n// accounts_server.js.\n\n/**\n * @summary Get the current user id, or `null` if no user is logged in. A reactive data source.\n * @locus Anywhere but publish functions\n * @importFromPackage meteor\n */\nMeteor.userId = function () {\n  return Accounts.userId();\n};\n\n/**\n * @summary Get the current user record, or `null` if no user is logged in. A reactive data source.\n * @locus Anywhere but publish functions\n * @importFromPackage meteor\n */\nMeteor.user = function () {\n  return Accounts.user();\n};\n\n// how long (in days) until a login token expires\nvar DEFAULT_LOGIN_EXPIRATION_DAYS = 90;\n// Clients don't try to auto-login with a token that is going to expire within\n// .1 * DEFAULT_LOGIN_EXPIRATION_DAYS, capped at MIN_TOKEN_LIFETIME_CAP_SECS.\n// Tries to avoid abrupt disconnects from expiring tokens.\nvar MIN_TOKEN_LIFETIME_CAP_SECS = 3600; // one hour\n// how often (in milliseconds) we check for expired tokens\nEXPIRE_TOKENS_INTERVAL_MS = 600 * 1000; // 10 minutes\n// how long we wait before logging out clients when Meteor.logoutOtherClients is\n// called\nCONNECTION_CLOSE_DELAY_MS = 10 * 1000;\n\n// loginServiceConfiguration and ConfigError are maintained for backwards compatibility\nMeteor.startup(function () {\n  var ServiceConfiguration =\n    Package['service-configuration'].ServiceConfiguration;\n  Ap.loginServiceConfiguration = ServiceConfiguration.configurations;\n  Ap.ConfigError = ServiceConfiguration.ConfigError;\n});\n\n// Thrown when the user cancels the login process (eg, closes an oauth\n// popup, declines retina scan, etc)\nvar lceName = 'Accounts.LoginCancelledError';\nAp.LoginCancelledError = Meteor.makeErrorType(\n  lceName,\n  function (description) {\n    this.message = description;\n  }\n);\nAp.LoginCancelledError.prototype.name = lceName;\n\n// This is used to transmit specific subclass errors over the wire. We should\n// come up with a more generic way to do this (eg, with some sort of symbolic\n// error code rather than a number).\nAp.LoginCancelledError.numericError = 0x8acdc2f;\n"
  },
  {
    "path": "packages/accounts-base/accounts_rate_limit.js",
    "content": "import {AccountsCommon} from \"./accounts_common.js\";\n\nvar Ap = AccountsCommon.prototype;\nvar defaultRateLimiterRuleId;\n// Removes default rate limiting rule\nAp.removeDefaultRateLimit = function () {\n  const resp = DDPRateLimiter.removeRule(defaultRateLimiterRuleId);\n  defaultRateLimiterRuleId = null;\n  return resp;\n};\n\n// Add a default rule of limiting logins, creating new users and password reset\n// to 5 times every 10 seconds per connection.\nAp.addDefaultRateLimit = function () {\n  if (!defaultRateLimiterRuleId) {\n    defaultRateLimiterRuleId = DDPRateLimiter.addRule({\n      userId: null,\n      clientAddress: null,\n      type: 'method',\n      name: function (name) {\n        return _.contains(['login', 'createUser', 'resetPassword',\n          'forgotPassword'], name);\n      },\n      connectionId: function (connectionId) {\n        return true;\n      }\n    }, 5, 10000);\n  }\n};\n\nAp.addDefaultRateLimit();\n"
  },
  {
    "path": "packages/accounts-base/accounts_reconnect_tests.js",
    "content": "if (Meteor.isServer) {\n  Meteor.methods({\n    getConnectionUserId: function() {\n      return this.userId;\n    }\n  });\n}\n\nif (Meteor.isClient) {\n  Tinytest.addAsync('accounts - reconnect auto-login', function(test, done) {\n    var username1 = 'testuser1-' + Random.id();\n    var username2 = 'testuser2-' + Random.id();\n    var password1 = 'password1-' + Random.id();\n    var password2 = 'password2-' + Random.id();\n    var timeoutHandle;\n    var onLoginStopper;\n\n    loginAsUser1();\n\n    function loginAsUser1() {\n      Accounts.createUser({\n        username: username1,\n        password: password1\n      }, onUser1LoggedIn);\n    }\n\n    function onUser1LoggedIn(err) {\n      test.isUndefined(err, 'Unexpected error logging in as user1');\n      Accounts.createUser({\n        username: username2,\n        password: password2\n      }, onUser2LoggedIn);\n    }\n\n    function onUser2LoggedIn(err) {\n      test.isUndefined(err, 'Unexpected error logging in as user2');\n      onLoginStopper = Accounts.onLogin(onUser2LoggedInAfterReconnect);\n      Meteor.disconnect();\n      Meteor.reconnect();\n    }\n\n    function onUser2LoggedInAfterReconnect() {\n      onLoginStopper.stop();\n      Meteor.loginWithPassword('non-existent-user', 'or-wrong-password',\n        onFailedLogin);\n    }\n\n    function onFailedLogin(err) {\n      test.instanceOf(err, Meteor.Error, 'No Meteor.Error on login failure');\n      onLoginStopper = Accounts.onLogin(onUser2LoggedInAfterReconnectAfterFailedLogin);\n      Meteor.disconnect();\n      Meteor.reconnect();\n      timeoutHandle = Meteor.setTimeout(failTest, 1000);\n    }\n\n    function failTest() {\n      onLoginStopper.stop();\n      test.fail('Issue #4970 has occured.');\n      Meteor.call('getConnectionUserId', checkFinalState);\n    }\n\n    function onUser2LoggedInAfterReconnectAfterFailedLogin() {\n      onLoginStopper.stop();\n      Meteor.clearTimeout(timeoutHandle);\n      Meteor.call('getConnectionUserId', checkFinalState);\n    }\n\n    function checkFinalState(err, connectionUserId) {\n      test.isUndefined(err, 'Unexpected error calling getConnectionUserId');\n      test.equal(connectionUserId, Meteor.userId(),\n        'userId is different on client and server');\n      done();\n    }\n  });\n}\n"
  },
  {
    "path": "packages/accounts-base/accounts_server.js",
    "content": "var crypto = Npm.require('crypto');\n\nimport {AccountsCommon} from \"./accounts_common.js\";\n\n/**\n * @summary Constructor for the `Accounts` namespace on the server.\n * @locus Server\n * @class AccountsServer\n * @extends AccountsCommon\n * @instancename accountsServer\n * @param {Object} server A server object such as `Meteor.server`.\n */\nexport class AccountsServer extends AccountsCommon {\n  // Note that this constructor is less likely to be instantiated multiple\n  // times than the `AccountsClient` constructor, because a single server\n  // can provide only one set of methods.\n  constructor(server) {\n    super();\n\n    this._server = server || Meteor.server;\n    // Set up the server's methods, as if by calling Meteor.methods.\n    this._initServerMethods();\n\n    this._initAccountDataHooks();\n\n    // If autopublish is on, publish these user fields. Login service\n    // packages (eg accounts-google) add to these by calling\n    // addAutopublishFields.  Notably, this isn't implemented with multiple\n    // publishes since DDP only merges only across top-level fields, not\n    // subfields (such as 'services.facebook.accessToken')\n    this._autopublishFields = {\n      loggedInUser: ['profile', 'username', 'emails'],\n      otherUsers: ['profile', 'username']\n    };\n    this._initServerPublications();\n\n    // connectionId -> {connection, loginToken}\n    this._accountData = {};\n\n    // connection id -> observe handle for the login token that this connection is\n    // currently associated with, or a number. The number indicates that we are in\n    // the process of setting up the observe (using a number instead of a single\n    // sentinel allows multiple attempts to set up the observe to identify which\n    // one was theirs).\n    this._userObservesForConnections = {};\n    this._nextUserObserveNumber = 1;  // for the number described above.\n\n    // list of all registered handlers.\n    this._loginHandlers = [];\n\n    setupUsersCollection(this.users);\n    setupDefaultLoginHandlers(this);\n    setExpireTokensInterval(this);\n\n    this._validateLoginHook = new Hook({ bindEnvironment: false });\n    this._validateNewUserHooks = [\n      defaultValidateNewUserHook.bind(this)\n    ];\n\n    this._deleteSavedTokensForAllUsersOnStartup();\n\n    this._skipCaseInsensitiveChecksForTest = {};\n  }\n\n  ///\n  /// CURRENT USER\n  ///\n\n  // @override of \"abstract\" non-implementation in accounts_common.js\n  userId() {\n    // This function only works if called inside a method. In theory, it\n    // could also be called from publish statements, since they also\n    // have a userId associated with them. However, given that publish\n    // functions aren't reactive, using any of the infomation from\n    // Meteor.user() in a publish function will always use the value\n    // from when the function first runs. This is likely not what the\n    // user expects. The way to make this work in a publish is to do\n    // Meteor.find(this.userId).observe and recompute when the user\n    // record changes.\n    var currentInvocation = DDP._CurrentInvocation.get();\n    if (!currentInvocation)\n      throw new Error(\"Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.\");\n    return currentInvocation.userId;\n  }\n\n  ///\n  /// LOGIN HOOKS\n  ///\n\n  /**\n   * @summary Validate login attempts.\n   * @locus Server\n   * @param {Function} func Called whenever a login is attempted (either successful or unsuccessful).  A login can be aborted by returning a falsy value or throwing an exception.\n   */\n  validateLoginAttempt(func) {\n    // Exceptions inside the hook callback are passed up to us.\n    return this._validateLoginHook.register(func);\n  }\n\n  /**\n   * @summary Set restrictions on new user creation.\n   * @locus Server\n   * @param {Function} func Called whenever a new user is created. Takes the new user object, and returns true to allow the creation or false to abort.\n   */\n  validateNewUser(func) {\n    this._validateNewUserHooks.push(func);\n  }\n\n  ///\n  /// CREATE USER HOOKS\n  ///\n\n  /**\n   * @summary Customize new user creation.\n   * @locus Server\n   * @param {Function} func Called whenever a new user is created. Return the new user object, or throw an `Error` to abort the creation.\n   */\n  onCreateUser(func) {\n    if (this._onCreateUserHook) {\n      throw new Error(\"Can only call onCreateUser once\");\n    }\n\n    this._onCreateUserHook = func;\n  }\n};\n\nvar Ap = AccountsServer.prototype;\n\n// Give each login hook callback a fresh cloned copy of the attempt\n// object, but don't clone the connection.\n//\nfunction cloneAttemptWithConnection(connection, attempt) {\n  var clonedAttempt = EJSON.clone(attempt);\n  clonedAttempt.connection = connection;\n  return clonedAttempt;\n}\n\nAp._validateLogin = function (connection, attempt) {\n  this._validateLoginHook.each(function (callback) {\n    var ret;\n    try {\n      ret = callback(cloneAttemptWithConnection(connection, attempt));\n    }\n    catch (e) {\n      attempt.allowed = false;\n      // XXX this means the last thrown error overrides previous error\n      // messages. Maybe this is surprising to users and we should make\n      // overriding errors more explicit. (see\n      // https://github.com/meteor/meteor/issues/1960)\n      attempt.error = e;\n      return true;\n    }\n    if (! ret) {\n      attempt.allowed = false;\n      // don't override a specific error provided by a previous\n      // validator or the initial attempt (eg \"incorrect password\").\n      if (!attempt.error)\n        attempt.error = new Meteor.Error(403, \"Login forbidden\");\n    }\n    return true;\n  });\n};\n\n\nAp._successfulLogin = function (connection, attempt) {\n  this._onLoginHook.each(function (callback) {\n    callback(cloneAttemptWithConnection(connection, attempt));\n    return true;\n  });\n};\n\nAp._failedLogin = function (connection, attempt) {\n  this._onLoginFailureHook.each(function (callback) {\n    callback(cloneAttemptWithConnection(connection, attempt));\n    return true;\n  });\n};\n\nAp._successfulLogout = function () {\n  this._onLogoutHook.each(function (callback) {\n    callback();\n    return true;\n  });\n};\n\n///\n/// LOGIN METHODS\n///\n\n// Login methods return to the client an object containing these\n// fields when the user was logged in successfully:\n//\n//   id: userId\n//   token: *\n//   tokenExpires: *\n//\n// tokenExpires is optional and intends to provide a hint to the\n// client as to when the token will expire. If not provided, the\n// client will call Accounts._tokenExpiration, passing it the date\n// that it received the token.\n//\n// The login method will throw an error back to the client if the user\n// failed to log in.\n//\n//\n// Login handlers and service specific login methods such as\n// `createUser` internally return a `result` object containing these\n// fields:\n//\n//   type:\n//     optional string; the service name, overrides the handler\n//     default if present.\n//\n//   error:\n//     exception; if the user is not allowed to login, the reason why.\n//\n//   userId:\n//     string; the user id of the user attempting to login (if\n//     known), required for an allowed login.\n//\n//   options:\n//     optional object merged into the result returned by the login\n//     method; used by HAMK from SRP.\n//\n//   stampedLoginToken:\n//     optional object with `token` and `when` indicating the login\n//     token is already present in the database, returned by the\n//     \"resume\" login handler.\n//\n// For convenience, login methods can also throw an exception, which\n// is converted into an {error} result.  However, if the id of the\n// user attempting the login is known, a {userId, error} result should\n// be returned instead since the user id is not captured when an\n// exception is thrown.\n//\n// This internal `result` object is automatically converted into the\n// public {id, token, tokenExpires} object returned to the client.\n\n\n// Try a login method, converting thrown exceptions into an {error}\n// result.  The `type` argument is a default, inserted into the result\n// object if not explicitly returned.\n//\nvar tryLoginMethod = function (type, fn) {\n  var result;\n  try {\n    result = fn();\n  }\n  catch (e) {\n    result = {error: e};\n  }\n\n  if (result && !result.type && type)\n    result.type = type;\n\n  return result;\n};\n\n\n// Log in a user on a connection.\n//\n// We use the method invocation to set the user id on the connection,\n// not the connection object directly. setUserId is tied to methods to\n// enforce clear ordering of method application (using wait methods on\n// the client, and a no setUserId after unblock restriction on the\n// server)\n//\n// The `stampedLoginToken` parameter is optional.  When present, it\n// indicates that the login token has already been inserted into the\n// database and doesn't need to be inserted again.  (It's used by the\n// \"resume\" login handler).\nAp._loginUser = function (methodInvocation, userId, stampedLoginToken) {\n  var self = this;\n\n  if (! stampedLoginToken) {\n    stampedLoginToken = self._generateStampedLoginToken();\n    self._insertLoginToken(userId, stampedLoginToken);\n  }\n\n  // This order (and the avoidance of yields) is important to make\n  // sure that when publish functions are rerun, they see a\n  // consistent view of the world: the userId is set and matches\n  // the login token on the connection (not that there is\n  // currently a public API for reading the login token on a\n  // connection).\n  Meteor._noYieldsAllowed(function () {\n    self._setLoginToken(\n      userId,\n      methodInvocation.connection,\n      self._hashLoginToken(stampedLoginToken.token)\n    );\n  });\n\n  methodInvocation.setUserId(userId);\n\n  return {\n    id: userId,\n    token: stampedLoginToken.token,\n    tokenExpires: self._tokenExpiration(stampedLoginToken.when)\n  };\n};\n\n\n// After a login method has completed, call the login hooks.  Note\n// that `attemptLogin` is called for *all* login attempts, even ones\n// which aren't successful (such as an invalid password, etc).\n//\n// If the login is allowed and isn't aborted by a validate login hook\n// callback, log in the user.\n//\nAp._attemptLogin = function (\n  methodInvocation,\n  methodName,\n  methodArgs,\n  result\n) {\n  if (!result)\n    throw new Error(\"result is required\");\n\n  // XXX A programming error in a login handler can lead to this occuring, and\n  // then we don't call onLogin or onLoginFailure callbacks. Should\n  // tryLoginMethod catch this case and turn it into an error?\n  if (!result.userId && !result.error)\n    throw new Error(\"A login method must specify a userId or an error\");\n\n  var user;\n  if (result.userId)\n    user = this.users.findOne(result.userId);\n\n  var attempt = {\n    type: result.type || \"unknown\",\n    allowed: !! (result.userId && !result.error),\n    methodName: methodName,\n    methodArguments: _.toArray(methodArgs)\n  };\n  if (result.error)\n    attempt.error = result.error;\n  if (user)\n    attempt.user = user;\n\n  // _validateLogin may mutate `attempt` by adding an error and changing allowed\n  // to false, but that's the only change it can make (and the user's callbacks\n  // only get a clone of `attempt`).\n  this._validateLogin(methodInvocation.connection, attempt);\n\n  if (attempt.allowed) {\n    var ret = _.extend(\n      this._loginUser(\n        methodInvocation,\n        result.userId,\n        result.stampedLoginToken\n      ),\n      result.options || {}\n    );\n    this._successfulLogin(methodInvocation.connection, attempt);\n    return ret;\n  }\n  else {\n    this._failedLogin(methodInvocation.connection, attempt);\n    throw attempt.error;\n  }\n};\n\n\n// All service specific login methods should go through this function.\n// Ensure that thrown exceptions are caught and that login hook\n// callbacks are still called.\n//\nAp._loginMethod = function (\n  methodInvocation,\n  methodName,\n  methodArgs,\n  type,\n  fn\n) {\n  return this._attemptLogin(\n    methodInvocation,\n    methodName,\n    methodArgs,\n    tryLoginMethod(type, fn)\n  );\n};\n\n\n// Report a login attempt failed outside the context of a normal login\n// method. This is for use in the case where there is a multi-step login\n// procedure (eg SRP based password login). If a method early in the\n// chain fails, it should call this function to report a failure. There\n// is no corresponding method for a successful login; methods that can\n// succeed at logging a user in should always be actual login methods\n// (using either Accounts._loginMethod or Accounts.registerLoginHandler).\nAp._reportLoginFailure = function (\n  methodInvocation,\n  methodName,\n  methodArgs,\n  result\n) {\n  var attempt = {\n    type: result.type || \"unknown\",\n    allowed: false,\n    error: result.error,\n    methodName: methodName,\n    methodArguments: _.toArray(methodArgs)\n  };\n\n  if (result.userId) {\n    attempt.user = this.users.findOne(result.userId);\n  }\n\n  this._validateLogin(methodInvocation.connection, attempt);\n  this._failedLogin(methodInvocation.connection, attempt);\n\n  // _validateLogin may mutate attempt to set a new error message. Return\n  // the modified version.\n  return attempt;\n};\n\n\n///\n/// LOGIN HANDLERS\n///\n\n// The main entry point for auth packages to hook in to login.\n//\n// A login handler is a login method which can return `undefined` to\n// indicate that the login request is not handled by this handler.\n//\n// @param name {String} Optional.  The service name, used by default\n// if a specific service name isn't returned in the result.\n//\n// @param handler {Function} A function that receives an options object\n// (as passed as an argument to the `login` method) and returns one of:\n// - `undefined`, meaning don't handle;\n// - a login method result object\n\nAp.registerLoginHandler = function (name, handler) {\n  if (! handler) {\n    handler = name;\n    name = null;\n  }\n\n  this._loginHandlers.push({\n    name: name,\n    handler: handler\n  });\n};\n\n\n// Checks a user's credentials against all the registered login\n// handlers, and returns a login token if the credentials are valid. It\n// is like the login method, except that it doesn't set the logged-in\n// user on the connection. Throws a Meteor.Error if logging in fails,\n// including the case where none of the login handlers handled the login\n// request. Otherwise, returns {id: userId, token: *, tokenExpires: *}.\n//\n// For example, if you want to login with a plaintext password, `options` could be\n//   { user: { username: <username> }, password: <password> }, or\n//   { user: { email: <email> }, password: <password> }.\n\n// Try all of the registered login handlers until one of them doesn't\n// return `undefined`, meaning it handled this call to `login`. Return\n// that return value.\nAp._runLoginHandlers = function (methodInvocation, options) {\n  for (var i = 0; i < this._loginHandlers.length; ++i) {\n    var handler = this._loginHandlers[i];\n\n    var result = tryLoginMethod(\n      handler.name,\n      function () {\n        return handler.handler.call(methodInvocation, options);\n      }\n    );\n\n    if (result) {\n      return result;\n    }\n\n    if (result !== undefined) {\n      throw new Meteor.Error(400, \"A login handler should return a result or undefined\");\n    }\n  }\n\n  return {\n    type: null,\n    error: new Meteor.Error(400, \"Unrecognized options for login request\")\n  };\n};\n\n// Deletes the given loginToken from the database.\n//\n// For new-style hashed token, this will cause all connections\n// associated with the token to be closed.\n//\n// Any connections associated with old-style unhashed tokens will be\n// in the process of becoming associated with hashed tokens and then\n// they'll get closed.\nAp.destroyToken = function (userId, loginToken) {\n  this.users.update(userId, {\n    $pull: {\n      \"services.resume.loginTokens\": {\n        $or: [\n          { hashedToken: loginToken },\n          { token: loginToken }\n        ]\n      }\n    }\n  });\n};\n\nAp._initServerMethods = function () {\n  // The methods created in this function need to be created here so that\n  // this variable is available in their scope.\n  var accounts = this;\n\n  // This object will be populated with methods and then passed to\n  // accounts._server.methods further below.\n  var methods = {};\n\n  // @returns {Object|null}\n  //   If successful, returns {token: reconnectToken, id: userId}\n  //   If unsuccessful (for example, if the user closed the oauth login popup),\n  //     throws an error describing the reason\n  methods.login = function (options) {\n    var self = this;\n\n    // Login handlers should really also check whatever field they look at in\n    // options, but we don't enforce it.\n    check(options, Object);\n\n    var result = accounts._runLoginHandlers(self, options);\n\n    return accounts._attemptLogin(self, \"login\", arguments, result);\n  };\n\n  methods.logout = function () {\n    var token = accounts._getLoginToken(this.connection.id);\n    accounts._setLoginToken(this.userId, this.connection, null);\n    if (token && this.userId)\n      accounts.destroyToken(this.userId, token);\n    this.setUserId(null);\n    accounts._successfulLogout();\n  };\n\n  // Delete all the current user's tokens and close all open connections logged\n  // in as this user. Returns a fresh new login token that this client can\n  // use. Tests set Accounts._noConnectionCloseDelayForTest to delete tokens\n  // immediately instead of using a delay.\n  //\n  // XXX COMPAT WITH 0.7.2\n  // This single `logoutOtherClients` method has been replaced with two\n  // methods, one that you call to get a new token, and another that you\n  // call to remove all tokens except your own. The new design allows\n  // clients to know when other clients have actually been logged\n  // out. (The `logoutOtherClients` method guarantees the caller that\n  // the other clients will be logged out at some point, but makes no\n  // guarantees about when.) This method is left in for backwards\n  // compatibility, especially since application code might be calling\n  // this method directly.\n  //\n  // @returns {Object} Object with token and tokenExpires keys.\n  methods.logoutOtherClients = function () {\n    var self = this;\n    var user = accounts.users.findOne(self.userId, {\n      fields: {\n        \"services.resume.loginTokens\": true\n      }\n    });\n    if (user) {\n      // Save the current tokens in the database to be deleted in\n      // CONNECTION_CLOSE_DELAY_MS ms. This gives other connections in the\n      // caller's browser time to find the fresh token in localStorage. We save\n      // the tokens in the database in case we crash before actually deleting\n      // them.\n      var tokens = user.services.resume.loginTokens;\n      var newToken = accounts._generateStampedLoginToken();\n      var userId = self.userId;\n      accounts.users.update(userId, {\n        $set: {\n          \"services.resume.loginTokensToDelete\": tokens,\n          \"services.resume.haveLoginTokensToDelete\": true\n        },\n        $push: { \"services.resume.loginTokens\": accounts._hashStampedToken(newToken) }\n      });\n      Meteor.setTimeout(function () {\n        // The observe on Meteor.users will take care of closing the connections\n        // associated with `tokens`.\n        accounts._deleteSavedTokensForUser(userId, tokens);\n      }, accounts._noConnectionCloseDelayForTest ? 0 :\n                        CONNECTION_CLOSE_DELAY_MS);\n      // We do not set the login token on this connection, but instead the\n      // observe closes the connection and the client will reconnect with the\n      // new token.\n      return {\n        token: newToken.token,\n        tokenExpires: accounts._tokenExpiration(newToken.when)\n      };\n    } else {\n      throw new Meteor.Error(\"You are not logged in.\");\n    }\n  };\n\n  // Generates a new login token with the same expiration as the\n  // connection's current token and saves it to the database. Associates\n  // the connection with this new token and returns it. Throws an error\n  // if called on a connection that isn't logged in.\n  //\n  // @returns Object\n  //   If successful, returns { token: <new token>, id: <user id>,\n  //   tokenExpires: <expiration date> }.\n  methods.getNewToken = function () {\n    var self = this;\n    var user = accounts.users.findOne(self.userId, {\n      fields: { \"services.resume.loginTokens\": 1 }\n    });\n    if (! self.userId || ! user) {\n      throw new Meteor.Error(\"You are not logged in.\");\n    }\n    // Be careful not to generate a new token that has a later\n    // expiration than the curren token. Otherwise, a bad guy with a\n    // stolen token could use this method to stop his stolen token from\n    // ever expiring.\n    var currentHashedToken = accounts._getLoginToken(self.connection.id);\n    var currentStampedToken = _.find(\n      user.services.resume.loginTokens,\n      function (stampedToken) {\n        return stampedToken.hashedToken === currentHashedToken;\n      }\n    );\n    if (! currentStampedToken) { // safety belt: this should never happen\n      throw new Meteor.Error(\"Invalid login token\");\n    }\n    var newStampedToken = accounts._generateStampedLoginToken();\n    newStampedToken.when = currentStampedToken.when;\n    accounts._insertLoginToken(self.userId, newStampedToken);\n    return accounts._loginUser(self, self.userId, newStampedToken);\n  };\n\n  // Removes all tokens except the token associated with the current\n  // connection. Throws an error if the connection is not logged\n  // in. Returns nothing on success.\n  methods.removeOtherTokens = function () {\n    var self = this;\n    if (! self.userId) {\n      throw new Meteor.Error(\"You are not logged in.\");\n    }\n    var currentToken = accounts._getLoginToken(self.connection.id);\n    accounts.users.update(self.userId, {\n      $pull: {\n        \"services.resume.loginTokens\": { hashedToken: { $ne: currentToken } }\n      }\n    });\n  };\n\n  // Allow a one-time configuration for a login service. Modifications\n  // to this collection are also allowed in insecure mode.\n  methods.configureLoginService = function (options) {\n    check(options, Match.ObjectIncluding({service: String}));\n    // Don't let random users configure a service we haven't added yet (so\n    // that when we do later add it, it's set up with their configuration\n    // instead of ours).\n    // XXX if service configuration is oauth-specific then this code should\n    //     be in accounts-oauth; if it's not then the registry should be\n    //     in this package\n    if (!(accounts.oauth\n          && _.contains(accounts.oauth.serviceNames(), options.service))) {\n      throw new Meteor.Error(403, \"Service unknown\");\n    }\n\n    var ServiceConfiguration =\n      Package['service-configuration'].ServiceConfiguration;\n    if (ServiceConfiguration.configurations.findOne({service: options.service}))\n      throw new Meteor.Error(403, \"Service \" + options.service + \" already configured\");\n\n    if (_.has(options, \"secret\") && usingOAuthEncryption())\n      options.secret = OAuthEncryption.seal(options.secret);\n\n    ServiceConfiguration.configurations.insert(options);\n  };\n\n  accounts._server.methods(methods);\n};\n\nAp._initAccountDataHooks = function () {\n  var accounts = this;\n\n  accounts._server.onConnection(function (connection) {\n    accounts._accountData[connection.id] = {\n      connection: connection\n    };\n\n    connection.onClose(function () {\n      accounts._removeTokenFromConnection(connection.id);\n      delete accounts._accountData[connection.id];\n    });\n  });\n};\n\nAp._initServerPublications = function () {\n  var accounts = this;\n\n  // Publish all login service configuration fields other than secret.\n  accounts._server.publish(\"meteor.loginServiceConfiguration\", function () {\n    var ServiceConfiguration =\n      Package['service-configuration'].ServiceConfiguration;\n    return ServiceConfiguration.configurations.find({}, {fields: {secret: 0}});\n  }, {is_auto: true}); // not techincally autopublish, but stops the warning.\n\n  // Publish the current user's record to the client.\n  accounts._server.publish(null, function () {\n    if (this.userId) {\n      return accounts.users.find({\n        _id: this.userId\n      }, {\n        fields: {\n          profile: 1,\n          username: 1,\n          emails: 1\n        }\n      });\n    } else {\n      return null;\n    }\n  }, /*suppress autopublish warning*/{is_auto: true});\n\n  // Use Meteor.startup to give other packages a chance to call\n  // addAutopublishFields.\n  Package.autopublish && Meteor.startup(function () {\n    // ['profile', 'username'] -> {profile: 1, username: 1}\n    var toFieldSelector = function (fields) {\n      return _.object(_.map(fields, function (field) {\n        return [field, 1];\n      }));\n    };\n\n    accounts._server.publish(null, function () {\n      if (this.userId) {\n        return accounts.users.find({\n          _id: this.userId\n        }, {\n          fields: toFieldSelector(accounts._autopublishFields.loggedInUser)\n        });\n      } else {\n        return null;\n      }\n    }, /*suppress autopublish warning*/{is_auto: true});\n\n    // XXX this publish is neither dedup-able nor is it optimized by our special\n    // treatment of queries on a specific _id. Therefore this will have O(n^2)\n    // run-time performance every time a user document is changed (eg someone\n    // logging in). If this is a problem, we can instead write a manual publish\n    // function which filters out fields based on 'this.userId'.\n    accounts._server.publish(null, function () {\n      var selector = this.userId ? {\n        _id: { $ne: this.userId }\n      } : {};\n\n      return accounts.users.find(selector, {\n        fields: toFieldSelector(accounts._autopublishFields.otherUsers)\n      });\n    }, /*suppress autopublish warning*/{is_auto: true});\n  });\n};\n\n// Add to the list of fields or subfields to be automatically\n// published if autopublish is on. Must be called from top-level\n// code (ie, before Meteor.startup hooks run).\n//\n// @param opts {Object} with:\n//   - forLoggedInUser {Array} Array of fields published to the logged-in user\n//   - forOtherUsers {Array} Array of fields published to users that aren't logged in\nAp.addAutopublishFields = function (opts) {\n  this._autopublishFields.loggedInUser.push.apply(\n    this._autopublishFields.loggedInUser, opts.forLoggedInUser);\n  this._autopublishFields.otherUsers.push.apply(\n    this._autopublishFields.otherUsers, opts.forOtherUsers);\n};\n\n///\n/// ACCOUNT DATA\n///\n\n// HACK: This is used by 'meteor-accounts' to get the loginToken for a\n// connection. Maybe there should be a public way to do that.\nAp._getAccountData = function (connectionId, field) {\n  var data = this._accountData[connectionId];\n  return data && data[field];\n};\n\nAp._setAccountData = function (connectionId, field, value) {\n  var data = this._accountData[connectionId];\n\n  // safety belt. shouldn't happen. accountData is set in onConnection,\n  // we don't have a connectionId until it is set.\n  if (!data)\n    return;\n\n  if (value === undefined)\n    delete data[field];\n  else\n    data[field] = value;\n};\n\n\n///\n/// RECONNECT TOKENS\n///\n/// support reconnecting using a meteor login token\n\nAp._hashLoginToken = function (loginToken) {\n  var hash = crypto.createHash('sha256');\n  hash.update(loginToken);\n  return hash.digest('base64');\n};\n\n\n// {token, when} => {hashedToken, when}\nAp._hashStampedToken = function (stampedToken) {\n  return _.extend(_.omit(stampedToken, 'token'), {\n    hashedToken: this._hashLoginToken(stampedToken.token)\n  });\n};\n\n\n// Using $addToSet avoids getting an index error if another client\n// logging in simultaneously has already inserted the new hashed\n// token.\nAp._insertHashedLoginToken = function (userId, hashedToken, query) {\n  query = query ? _.clone(query) : {};\n  query._id = userId;\n  this.users.update(query, {\n    $addToSet: {\n      \"services.resume.loginTokens\": hashedToken\n    }\n  });\n};\n\n\n// Exported for tests.\nAp._insertLoginToken = function (userId, stampedToken, query) {\n  this._insertHashedLoginToken(\n    userId,\n    this._hashStampedToken(stampedToken),\n    query\n  );\n};\n\n\nAp._clearAllLoginTokens = function (userId) {\n  this.users.update(userId, {\n    $set: {\n      'services.resume.loginTokens': []\n    }\n  });\n};\n\n// test hook\nAp._getUserObserve = function (connectionId) {\n  return this._userObservesForConnections[connectionId];\n};\n\n// Clean up this connection's association with the token: that is, stop\n// the observe that we started when we associated the connection with\n// this token.\nAp._removeTokenFromConnection = function (connectionId) {\n  if (_.has(this._userObservesForConnections, connectionId)) {\n    var observe = this._userObservesForConnections[connectionId];\n    if (typeof observe === 'number') {\n      // We're in the process of setting up an observe for this connection. We\n      // can't clean up that observe yet, but if we delete the placeholder for\n      // this connection, then the observe will get cleaned up as soon as it has\n      // been set up.\n      delete this._userObservesForConnections[connectionId];\n    } else {\n      delete this._userObservesForConnections[connectionId];\n      observe.stop();\n    }\n  }\n};\n\nAp._getLoginToken = function (connectionId) {\n  return this._getAccountData(connectionId, 'loginToken');\n};\n\n// newToken is a hashed token.\nAp._setLoginToken = function (userId, connection, newToken) {\n  var self = this;\n\n  self._removeTokenFromConnection(connection.id);\n  self._setAccountData(connection.id, 'loginToken', newToken);\n\n  if (newToken) {\n    // Set up an observe for this token. If the token goes away, we need\n    // to close the connection.  We defer the observe because there's\n    // no need for it to be on the critical path for login; we just need\n    // to ensure that the connection will get closed at some point if\n    // the token gets deleted.\n    //\n    // Initially, we set the observe for this connection to a number; this\n    // signifies to other code (which might run while we yield) that we are in\n    // the process of setting up an observe for this connection. Once the\n    // observe is ready to go, we replace the number with the real observe\n    // handle (unless the placeholder has been deleted or replaced by a\n    // different placehold number, signifying that the connection was closed\n    // already -- in this case we just clean up the observe that we started).\n    var myObserveNumber = ++self._nextUserObserveNumber;\n    self._userObservesForConnections[connection.id] = myObserveNumber;\n    Meteor.defer(function () {\n      // If something else happened on this connection in the meantime (it got\n      // closed, or another call to _setLoginToken happened), just do\n      // nothing. We don't need to start an observe for an old connection or old\n      // token.\n      if (self._userObservesForConnections[connection.id] !== myObserveNumber) {\n        return;\n      }\n\n      var foundMatchingUser;\n      // Because we upgrade unhashed login tokens to hashed tokens at\n      // login time, sessions will only be logged in with a hashed\n      // token. Thus we only need to observe hashed tokens here.\n      var observe = self.users.find({\n        _id: userId,\n        'services.resume.loginTokens.hashedToken': newToken\n      }, { fields: { _id: 1 } }).observeChanges({\n        added: function () {\n          foundMatchingUser = true;\n        },\n        removed: function () {\n          connection.close();\n          // The onClose callback for the connection takes care of\n          // cleaning up the observe handle and any other state we have\n          // lying around.\n        }\n      });\n\n      // If the user ran another login or logout command we were waiting for the\n      // defer or added to fire (ie, another call to _setLoginToken occurred),\n      // then we let the later one win (start an observe, etc) and just stop our\n      // observe now.\n      //\n      // Similarly, if the connection was already closed, then the onClose\n      // callback would have called _removeTokenFromConnection and there won't\n      // be an entry in _userObservesForConnections. We can stop the observe.\n      if (self._userObservesForConnections[connection.id] !== myObserveNumber) {\n        observe.stop();\n        return;\n      }\n\n      self._userObservesForConnections[connection.id] = observe;\n\n      if (! foundMatchingUser) {\n        // We've set up an observe on the user associated with `newToken`,\n        // so if the new token is removed from the database, we'll close\n        // the connection. But the token might have already been deleted\n        // before we set up the observe, which wouldn't have closed the\n        // connection because the observe wasn't running yet.\n        connection.close();\n      }\n    });\n  }\n};\n\nfunction setupDefaultLoginHandlers(accounts) {\n  accounts.registerLoginHandler(\"resume\", function (options) {\n    return defaultResumeLoginHandler.call(this, accounts, options);\n  });\n}\n\n// Login handler for resume tokens.\nfunction defaultResumeLoginHandler(accounts, options) {\n  if (!options.resume)\n    return undefined;\n\n  check(options.resume, String);\n\n  var hashedToken = accounts._hashLoginToken(options.resume);\n\n  // First look for just the new-style hashed login token, to avoid\n  // sending the unhashed token to the database in a query if we don't\n  // need to.\n  var user = accounts.users.findOne(\n    {\"services.resume.loginTokens.hashedToken\": hashedToken});\n\n  if (! user) {\n    // If we didn't find the hashed login token, try also looking for\n    // the old-style unhashed token.  But we need to look for either\n    // the old-style token OR the new-style token, because another\n    // client connection logging in simultaneously might have already\n    // converted the token.\n    user = accounts.users.findOne({\n      $or: [\n        {\"services.resume.loginTokens.hashedToken\": hashedToken},\n        {\"services.resume.loginTokens.token\": options.resume}\n      ]\n    });\n  }\n\n  if (! user)\n    return {\n      error: new Meteor.Error(403, \"You've been logged out by the server. Please log in again.\")\n    };\n\n  // Find the token, which will either be an object with fields\n  // {hashedToken, when} for a hashed token or {token, when} for an\n  // unhashed token.\n  var oldUnhashedStyleToken;\n  var token = _.find(user.services.resume.loginTokens, function (token) {\n    return token.hashedToken === hashedToken;\n  });\n  if (token) {\n    oldUnhashedStyleToken = false;\n  } else {\n    token = _.find(user.services.resume.loginTokens, function (token) {\n      return token.token === options.resume;\n    });\n    oldUnhashedStyleToken = true;\n  }\n\n  var tokenExpires = accounts._tokenExpiration(token.when);\n  if (new Date() >= tokenExpires)\n    return {\n      userId: user._id,\n      error: new Meteor.Error(403, \"Your session has expired. Please log in again.\")\n    };\n\n  // Update to a hashed token when an unhashed token is encountered.\n  if (oldUnhashedStyleToken) {\n    // Only add the new hashed token if the old unhashed token still\n    // exists (this avoids resurrecting the token if it was deleted\n    // after we read it).  Using $addToSet avoids getting an index\n    // error if another client logging in simultaneously has already\n    // inserted the new hashed token.\n    accounts.users.update(\n      {\n        _id: user._id,\n        \"services.resume.loginTokens.token\": options.resume\n      },\n      {$addToSet: {\n        \"services.resume.loginTokens\": {\n          \"hashedToken\": hashedToken,\n          \"when\": token.when\n        }\n      }}\n    );\n\n    // Remove the old token *after* adding the new, since otherwise\n    // another client trying to login between our removing the old and\n    // adding the new wouldn't find a token to login with.\n    accounts.users.update(user._id, {\n      $pull: {\n        \"services.resume.loginTokens\": { \"token\": options.resume }\n      }\n    });\n  }\n\n  return {\n    userId: user._id,\n    stampedLoginToken: {\n      token: options.resume,\n      when: token.when\n    }\n  };\n}\n\n// (Also used by Meteor Accounts server and tests).\n//\nAp._generateStampedLoginToken = function () {\n  return {\n    token: Random.secret(),\n    when: new Date\n  };\n};\n\n///\n/// TOKEN EXPIRATION\n///\n\n// Deletes expired tokens from the database and closes all open connections\n// associated with these tokens.\n//\n// Exported for tests. Also, the arguments are only used by\n// tests. oldestValidDate is simulate expiring tokens without waiting\n// for them to actually expire. userId is used by tests to only expire\n// tokens for the test user.\nAp._expireTokens = function (oldestValidDate, userId) {\n  var tokenLifetimeMs = this._getTokenLifetimeMs();\n\n  // when calling from a test with extra arguments, you must specify both!\n  if ((oldestValidDate && !userId) || (!oldestValidDate && userId)) {\n    throw new Error(\"Bad test. Must specify both oldestValidDate and userId.\");\n  }\n\n  oldestValidDate = oldestValidDate ||\n    (new Date(new Date() - tokenLifetimeMs));\n  var userFilter = userId ? {_id: userId} : {};\n\n\n  // Backwards compatible with older versions of meteor that stored login token\n  // timestamps as numbers.\n  this.users.update(_.extend(userFilter, {\n    $or: [\n      { \"services.resume.loginTokens.when\": { $lt: oldestValidDate } },\n      { \"services.resume.loginTokens.when\": { $lt: +oldestValidDate } }\n    ]\n  }), {\n    $pull: {\n      \"services.resume.loginTokens\": {\n        $or: [\n          { when: { $lt: oldestValidDate } },\n          { when: { $lt: +oldestValidDate } }\n        ]\n      }\n    }\n  }, { multi: true });\n  // The observe on Meteor.users will take care of closing connections for\n  // expired tokens.\n};\n\n// @override from accounts_common.js\nAp.config = function (options) {\n  // Call the overridden implementation of the method.\n  var superResult = AccountsCommon.prototype.config.apply(this, arguments);\n\n  // If the user set loginExpirationInDays to null, then we need to clear the\n  // timer that periodically expires tokens.\n  if (_.has(this._options, \"loginExpirationInDays\") &&\n      this._options.loginExpirationInDays === null &&\n      this.expireTokenInterval) {\n    Meteor.clearInterval(this.expireTokenInterval);\n    this.expireTokenInterval = null;\n  }\n\n  return superResult;\n};\n\nfunction setExpireTokensInterval(accounts) {\n  accounts.expireTokenInterval = Meteor.setInterval(function () {\n    accounts._expireTokens();\n  }, EXPIRE_TOKENS_INTERVAL_MS);\n}\n\n\n///\n/// OAuth Encryption Support\n///\n\nvar OAuthEncryption =\n  Package[\"oauth-encryption\"] &&\n  Package[\"oauth-encryption\"].OAuthEncryption;\n\nfunction usingOAuthEncryption() {\n  return OAuthEncryption && OAuthEncryption.keyIsLoaded();\n}\n\n\n// OAuth service data is temporarily stored in the pending credentials\n// collection during the oauth authentication process.  Sensitive data\n// such as access tokens are encrypted without the user id because\n// we don't know the user id yet.  We re-encrypt these fields with the\n// user id included when storing the service data permanently in\n// the users collection.\n//\nfunction pinEncryptedFieldsToUser(serviceData, userId) {\n  _.each(_.keys(serviceData), function (key) {\n    var value = serviceData[key];\n    if (OAuthEncryption && OAuthEncryption.isSealed(value))\n      value = OAuthEncryption.seal(OAuthEncryption.open(value), userId);\n    serviceData[key] = value;\n  });\n}\n\n\n// Encrypt unencrypted login service secrets when oauth-encryption is\n// added.\n//\n// XXX For the oauthSecretKey to be available here at startup, the\n// developer must call Accounts.config({oauthSecretKey: ...}) at load\n// time, instead of in a Meteor.startup block, because the startup\n// block in the app code will run after this accounts-base startup\n// block.  Perhaps we need a post-startup callback?\n\nMeteor.startup(function () {\n  if (! usingOAuthEncryption()) {\n    return;\n  }\n\n  var ServiceConfiguration =\n    Package['service-configuration'].ServiceConfiguration;\n\n  ServiceConfiguration.configurations.find({\n    $and: [{\n      secret: { $exists: true }\n    }, {\n      \"secret.algorithm\": { $exists: false }\n    }]\n  }).forEach(function (config) {\n    ServiceConfiguration.configurations.update(config._id, {\n      $set: {\n        secret: OAuthEncryption.seal(config.secret)\n      }\n    });\n  });\n});\n\n// XXX see comment on Accounts.createUser in passwords_server about adding a\n// second \"server options\" argument.\nfunction defaultCreateUserHook(options, user) {\n  if (options.profile)\n    user.profile = options.profile;\n  return user;\n}\n\n// Called by accounts-password\nAp.insertUserDoc = function (options, user) {\n  // - clone user document, to protect from modification\n  // - add createdAt timestamp\n  // - prepare an _id, so that you can modify other collections (eg\n  // create a first task for every new user)\n  //\n  // XXX If the onCreateUser or validateNewUser hooks fail, we might\n  // end up having modified some other collection\n  // inappropriately. The solution is probably to have onCreateUser\n  // accept two callbacks - one that gets called before inserting\n  // the user document (in which you can modify its contents), and\n  // one that gets called after (in which you should change other\n  // collections)\n  user = _.extend({\n    createdAt: new Date(),\n    _id: Random.id()\n  }, user);\n\n  if (user.services) {\n    _.each(user.services, function (serviceData) {\n      pinEncryptedFieldsToUser(serviceData, user._id);\n    });\n  }\n\n  var fullUser;\n  if (this._onCreateUserHook) {\n    fullUser = this._onCreateUserHook(options, user);\n\n    // This is *not* part of the API. We need this because we can't isolate\n    // the global server environment between tests, meaning we can't test\n    // both having a create user hook set and not having one set.\n    if (fullUser === 'TEST DEFAULT HOOK')\n      fullUser = defaultCreateUserHook(options, user);\n  } else {\n    fullUser = defaultCreateUserHook(options, user);\n  }\n\n  _.each(this._validateNewUserHooks, function (hook) {\n    if (! hook(fullUser))\n      throw new Meteor.Error(403, \"User validation failed\");\n  });\n\n  var userId;\n  try {\n    userId = this.users.insert(fullUser);\n  } catch (e) {\n    // XXX string parsing sucks, maybe\n    // https://jira.mongodb.org/browse/SERVER-3069 will get fixed one day\n    if (e.name !== 'MongoError') throw e;\n    if (e.code !== 11000) throw e;\n    if (e.err.indexOf('emails.address') !== -1)\n      throw new Meteor.Error(403, \"Email already exists.\");\n    if (e.err.indexOf('username') !== -1)\n      throw new Meteor.Error(403, \"Username already exists.\");\n    // XXX better error reporting for services.facebook.id duplicate, etc\n    throw e;\n  }\n  return userId;\n};\n\n// Helper function: returns false if email does not match company domain from\n// the configuration.\nAp._testEmailDomain = function (email) {\n  var domain = this._options.restrictCreationByEmailDomain;\n  return !domain ||\n    (_.isFunction(domain) && domain(email)) ||\n    (_.isString(domain) &&\n      (new RegExp('@' + Meteor._escapeRegExp(domain) + '$', 'i')).test(email));\n};\n\n// Validate new user's email or Google/Facebook/GitHub account's email\nfunction defaultValidateNewUserHook(user) {\n  var self = this;\n  var domain = self._options.restrictCreationByEmailDomain;\n  if (!domain)\n    return true;\n\n  var emailIsGood = false;\n  if (!_.isEmpty(user.emails)) {\n    emailIsGood = _.any(user.emails, function (email) {\n      return self._testEmailDomain(email.address);\n    });\n  } else if (!_.isEmpty(user.services)) {\n    // Find any email of any service and check it\n    emailIsGood = _.any(user.services, function (service) {\n      return service.email && self._testEmailDomain(service.email);\n    });\n  }\n\n  if (emailIsGood)\n    return true;\n\n  if (_.isString(domain))\n    throw new Meteor.Error(403, \"@\" + domain + \" email required\");\n  else\n    throw new Meteor.Error(403, \"Email doesn't match the criteria.\");\n}\n\n///\n/// MANAGING USER OBJECTS\n///\n\n// Updates or creates a user after we authenticate with a 3rd party.\n//\n// @param serviceName {String} Service name (eg, twitter).\n// @param serviceData {Object} Data to store in the user's record\n//        under services[serviceName]. Must include an \"id\" field\n//        which is a unique identifier for the user in the service.\n// @param options {Object, optional} Other options to pass to insertUserDoc\n//        (eg, profile)\n// @returns {Object} Object with token and id keys, like the result\n//        of the \"login\" method.\n//\nAp.updateOrCreateUserFromExternalService = function (\n  serviceName,\n  serviceData,\n  options\n) {\n  options = _.clone(options || {});\n\n  if (serviceName === \"password\" || serviceName === \"resume\")\n    throw new Error(\n      \"Can't use updateOrCreateUserFromExternalService with internal service \"\n        + serviceName);\n  if (!_.has(serviceData, 'id'))\n    throw new Error(\n      \"Service data for service \" + serviceName + \" must include id\");\n\n  // Look for a user with the appropriate service user id.\n  var selector = {};\n  var serviceIdKey = \"services.\" + serviceName + \".id\";\n\n  // XXX Temporary special case for Twitter. (Issue #629)\n  //   The serviceData.id will be a string representation of an integer.\n  //   We want it to match either a stored string or int representation.\n  //   This is to cater to earlier versions of Meteor storing twitter\n  //   user IDs in number form, and recent versions storing them as strings.\n  //   This can be removed once migration technology is in place, and twitter\n  //   users stored with integer IDs have been migrated to string IDs.\n  if (serviceName === \"twitter\" && !isNaN(serviceData.id)) {\n    selector[\"$or\"] = [{},{}];\n    selector[\"$or\"][0][serviceIdKey] = serviceData.id;\n    selector[\"$or\"][1][serviceIdKey] = parseInt(serviceData.id, 10);\n  } else {\n    selector[serviceIdKey] = serviceData.id;\n  }\n\n  var user = this.users.findOne(selector);\n\n  if (user) {\n    pinEncryptedFieldsToUser(serviceData, user._id);\n\n    // We *don't* process options (eg, profile) for update, but we do replace\n    // the serviceData (eg, so that we keep an unexpired access token and\n    // don't cache old email addresses in serviceData.email).\n    // XXX provide an onUpdateUser hook which would let apps update\n    //     the profile too\n    var setAttrs = {};\n    _.each(serviceData, function (value, key) {\n      setAttrs[\"services.\" + serviceName + \".\" + key] = value;\n    });\n\n    // XXX Maybe we should re-use the selector above and notice if the update\n    //     touches nothing?\n    this.users.update(user._id, {\n      $set: setAttrs\n    });\n\n    return {\n      type: serviceName,\n      userId: user._id\n    };\n\n  } else {\n    // Create a new user with the service data. Pass other options through to\n    // insertUserDoc.\n    user = {services: {}};\n    user.services[serviceName] = serviceData;\n    return {\n      type: serviceName,\n      userId: this.insertUserDoc(options, user)\n    };\n  }\n};\n\nfunction setupUsersCollection(users) {\n  ///\n  /// RESTRICTING WRITES TO USER OBJECTS\n  ///\n  users.allow({\n    // clients can modify the profile field of their own document, and\n    // nothing else.\n    update: function (userId, user, fields, modifier) {\n      // make sure it is our record\n      if (user._id !== userId)\n        return false;\n\n      // user can only modify the 'profile' field. sets to multiple\n      // sub-keys (eg profile.foo and profile.bar) are merged into entry\n      // in the fields list.\n      if (fields.length !== 1 || fields[0] !== 'profile')\n        return false;\n\n      return true;\n    },\n    fetch: ['_id'] // we only look at _id.\n  });\n\n  /// DEFAULT INDEXES ON USERS\n  users._ensureIndex('username', {unique: 1, sparse: 1});\n  users._ensureIndex('emails.address', {unique: 1, sparse: 1});\n  users._ensureIndex('services.resume.loginTokens.hashedToken',\n                     {unique: 1, sparse: 1});\n  users._ensureIndex('services.resume.loginTokens.token',\n                     {unique: 1, sparse: 1});\n  // For taking care of logoutOtherClients calls that crashed before the\n  // tokens were deleted.\n  users._ensureIndex('services.resume.haveLoginTokensToDelete',\n                     { sparse: 1 });\n  // For expiring login tokens\n  users._ensureIndex(\"services.resume.loginTokens.when\", { sparse: 1 });\n}\n\n///\n/// CLEAN UP FOR `logoutOtherClients`\n///\n\nAp._deleteSavedTokensForUser = function (userId, tokensToDelete) {\n  if (tokensToDelete) {\n    this.users.update(userId, {\n      $unset: {\n        \"services.resume.haveLoginTokensToDelete\": 1,\n        \"services.resume.loginTokensToDelete\": 1\n      },\n      $pullAll: {\n        \"services.resume.loginTokens\": tokensToDelete\n      }\n    });\n  }\n};\n\nAp._deleteSavedTokensForAllUsersOnStartup = function () {\n  var self = this;\n\n  // If we find users who have saved tokens to delete on startup, delete\n  // them now. It's possible that the server could have crashed and come\n  // back up before new tokens are found in localStorage, but this\n  // shouldn't happen very often. We shouldn't put a delay here because\n  // that would give a lot of power to an attacker with a stolen login\n  // token and the ability to crash the server.\n  Meteor.startup(function () {\n    self.users.find({\n      \"services.resume.haveLoginTokensToDelete\": true\n    }, {\n      \"services.resume.loginTokensToDelete\": 1\n    }).forEach(function (user) {\n      self._deleteSavedTokensForUser(\n        user._id,\n        user.services.resume.loginTokensToDelete\n      );\n    });\n  });\n};\n"
  },
  {
    "path": "packages/accounts-base/accounts_tests.js",
    "content": "Meteor.methods({\n  getCurrentLoginToken: function () {\n    return Accounts._getLoginToken(this.connection.id);\n  }\n});\n\n// XXX it'd be cool to also test that the right thing happens if options\n// *are* validated, but Accounts._options is global state which makes this hard\n// (impossible?)\nTinytest.add('accounts - config validates keys', function (test) {\n  test.throws(function () {\n    Accounts.config({foo: \"bar\"});\n  });\n});\n\n\nvar idsInValidateNewUser = {};\nAccounts.validateNewUser(function (user) {\n  idsInValidateNewUser[user._id] = true;\n  return true;\n});\n\nTinytest.add('accounts - validateNewUser gets passed user with _id', function (test) {\n  var newUserId = Accounts.updateOrCreateUserFromExternalService('foobook', {id: Random.id()}).userId;\n  test.isTrue(newUserId in idsInValidateNewUser);\n});\n\nTinytest.add('accounts - updateOrCreateUserFromExternalService - Facebook', function (test) {\n  var facebookId = Random.id();\n\n  // create an account with facebook\n  var uid1 = Accounts.updateOrCreateUserFromExternalService(\n    'facebook', {id: facebookId, monkey: 42}, {profile: {foo: 1}}).id;\n  var users = Meteor.users.find({\"services.facebook.id\": facebookId}).fetch();\n  test.length(users, 1);\n  test.equal(users[0].profile.foo, 1);\n  test.equal(users[0].services.facebook.monkey, 42);\n\n  // create again with the same id, see that we get the same user.\n  // it should update services.facebook but not profile.\n  var uid2 = Accounts.updateOrCreateUserFromExternalService(\n    'facebook', {id: facebookId, llama: 50},\n    {profile: {foo: 1000, bar: 2}}).id;\n  test.equal(uid1, uid2);\n  users = Meteor.users.find({\"services.facebook.id\": facebookId}).fetch();\n  test.length(users, 1);\n  test.equal(users[0].profile.foo, 1);\n  test.equal(users[0].profile.bar, undefined);\n  test.equal(users[0].services.facebook.llama, 50);\n  // make sure we *don't* lose values not passed this call to\n  // updateOrCreateUserFromExternalService\n  test.equal(users[0].services.facebook.monkey, 42);\n\n  // cleanup\n  Meteor.users.remove(uid1);\n});\n\nTinytest.add('accounts - updateOrCreateUserFromExternalService - Weibo', function (test) {\n  var weiboId1 = Random.id();\n  var weiboId2 = Random.id();\n\n  // users that have different service ids get different users\n  var uid1 = Accounts.updateOrCreateUserFromExternalService(\n    'weibo', {id: weiboId1}, {profile: {foo: 1}}).id;\n  var uid2 = Accounts.updateOrCreateUserFromExternalService(\n    'weibo', {id: weiboId2}, {profile: {bar: 2}}).id;\n  test.equal(Meteor.users.find({\"services.weibo.id\": {$in: [weiboId1, weiboId2]}}).count(), 2);\n  test.equal(Meteor.users.findOne({\"services.weibo.id\": weiboId1}).profile.foo, 1);\n  test.equal(Meteor.users.findOne({\"services.weibo.id\": weiboId1}).emails, undefined);\n  test.equal(Meteor.users.findOne({\"services.weibo.id\": weiboId2}).profile.bar, 2);\n  test.equal(Meteor.users.findOne({\"services.weibo.id\": weiboId2}).emails, undefined);\n\n  // cleanup\n  Meteor.users.remove(uid1);\n  Meteor.users.remove(uid2);\n});\n\nTinytest.add('accounts - updateOrCreateUserFromExternalService - Twitter', function (test) {\n  var twitterIdOld = parseInt(Random.hexString(4), 16);\n  var twitterIdNew = ''+twitterIdOld;\n\n  // create an account with twitter using the old ID format of integer\n  var uid1 = Accounts.updateOrCreateUserFromExternalService(\n    'twitter', {id: twitterIdOld, monkey: 42}, {profile: {foo: 1}}).id;\n  var users = Meteor.users.find({\"services.twitter.id\": twitterIdOld}).fetch();\n  test.length(users, 1);\n  test.equal(users[0].profile.foo, 1);\n  test.equal(users[0].services.twitter.monkey, 42);\n\n  // Update the account with the new ID format of string\n  // test that the existing user is found, and that the ID\n  // gets updated to a string value\n  var uid2 = Accounts.updateOrCreateUserFromExternalService(\n    'twitter', {id: twitterIdNew, monkey: 42}, {profile: {foo: 1}}).id;\n  test.equal(uid1, uid2);\n  users = Meteor.users.find({\"services.twitter.id\": twitterIdNew}).fetch();\n  test.length(users, 1);\n\n  // cleanup\n  Meteor.users.remove(uid1);\n});\n\n\nTinytest.add('accounts - insertUserDoc username', function (test) {\n  var userIn = {\n    username: Random.id()\n  };\n\n  // user does not already exist. create a user object with fields set.\n  var userId = Accounts.insertUserDoc(\n    {profile: {name: 'Foo Bar'}},\n    userIn\n  );\n  var userOut = Meteor.users.findOne(userId);\n\n  test.equal(typeof userOut.createdAt, 'object');\n  test.equal(userOut.profile.name, 'Foo Bar');\n  test.equal(userOut.username, userIn.username);\n\n  // run the hook again. now the user exists, so it throws an error.\n  test.throws(function () {\n    Accounts.insertUserDoc(\n      {profile: {name: 'Foo Bar'}},\n      userIn\n    );\n  }, 'Username already exists.');\n\n  // cleanup\n  Meteor.users.remove(userId);\n});\n\nTinytest.add('accounts - insertUserDoc email', function (test) {\n  var email1 = Random.id();\n  var email2 = Random.id();\n  var email3 = Random.id();\n  var userIn = {\n    emails: [{address: email1, verified: false},\n             {address: email2, verified: true}]\n  };\n\n  // user does not already exist. create a user object with fields set.\n  var userId = Accounts.insertUserDoc(\n    {profile: {name: 'Foo Bar'}},\n    userIn\n  );\n  var userOut = Meteor.users.findOne(userId);\n\n  test.equal(typeof userOut.createdAt, 'object');\n  test.equal(userOut.profile.name, 'Foo Bar');\n  test.equal(userOut.emails, userIn.emails);\n\n  // run the hook again with the exact same emails.\n  // run the hook again. now the user exists, so it throws an error.\n  test.throws(function () {\n    Accounts.insertUserDoc(\n      {profile: {name: 'Foo Bar'}},\n      userIn\n    );\n  }, 'Email already exists.');\n\n  // now with only one of them.\n  test.throws(function () {\n    Accounts.insertUserDoc(\n      {}, {emails: [{address: email1}]}\n    );\n  }, 'Email already exists.');\n\n  test.throws(function () {\n    Accounts.insertUserDoc(\n      {}, {emails: [{address: email2}]}\n    );\n  }, 'Email already exists.');\n\n\n  // a third email works.\n  var userId3 = Accounts.insertUserDoc(\n      {}, {emails: [{address: email3}]}\n  );\n  var user3 = Meteor.users.findOne(userId3);\n  test.equal(typeof user3.createdAt, 'object');\n\n  // cleanup\n  Meteor.users.remove(userId);\n  Meteor.users.remove(userId3);\n});\n\n// More token expiration tests are in accounts-password\nTinytest.addAsync('accounts - expire numeric token', function (test, onComplete) {\n  var userIn = { username: Random.id() };\n  var userId = Accounts.insertUserDoc({ profile: {\n    name: 'Foo Bar'\n  } }, userIn);\n  var date = new Date(new Date() - 5000);\n  Meteor.users.update(userId, {\n    $set: {\n      \"services.resume.loginTokens\": [{\n        hashedToken: Random.id(),\n        when: date\n      }, {\n        hashedToken: Random.id(),\n        when: +date\n      }]\n    }\n  });\n  var observe = Meteor.users.find(userId).observe({\n    changed: function (newUser) {\n      if (newUser.services && newUser.services.resume &&\n          _.isEmpty(newUser.services.resume.loginTokens)) {\n        observe.stop();\n        onComplete();\n      }\n    }\n  });\n  Accounts._expireTokens(new Date(), userId);\n});\n\n\n// Login tokens used to be stored unhashed in the database.  We want\n// to make sure users can still login after upgrading.\nvar insertUnhashedLoginToken = function (userId, stampedToken) {\n  Meteor.users.update(\n    userId,\n    {$push: {'services.resume.loginTokens': stampedToken}}\n  );\n};\n\nTinytest.addAsync('accounts - login token', function (test, onComplete) {\n  // Test that we can login when the database contains a leftover\n  // old style unhashed login token.\n  var userId1 = Accounts.insertUserDoc({}, {username: Random.id()});\n  var stampedToken = Accounts._generateStampedLoginToken();\n  insertUnhashedLoginToken(userId1, stampedToken);\n  var connection = DDP.connect(Meteor.absoluteUrl());\n  connection.call('login', {resume: stampedToken.token});\n  connection.disconnect();\n\n  // Steal the unhashed token from the database and use it to login.\n  // This is a sanity check so that when we *can't* login with a\n  // stolen *hashed* token, we know it's not a problem with the test.\n  var userId2 = Accounts.insertUserDoc({}, {username: Random.id()});\n  insertUnhashedLoginToken(userId2, Accounts._generateStampedLoginToken());\n  var stolenToken = Meteor.users.findOne(userId2).services.resume.loginTokens[0].token;\n  test.isTrue(stolenToken);\n  connection = DDP.connect(Meteor.absoluteUrl());\n  connection.call('login', {resume: stolenToken});\n  connection.disconnect();\n\n  // Now do the same thing, this time with a stolen hashed token.\n  var userId3 = Accounts.insertUserDoc({}, {username: Random.id()});\n  Accounts._insertLoginToken(userId3, Accounts._generateStampedLoginToken());\n  stolenToken = Meteor.users.findOne(userId3).services.resume.loginTokens[0].hashedToken;\n  test.isTrue(stolenToken);\n  connection = DDP.connect(Meteor.absoluteUrl());\n  // evil plan foiled\n  test.throws(\n    function () {\n      connection.call('login', {resume: stolenToken});\n    },\n    /You\\'ve been logged out by the server/\n  );\n  connection.disconnect();\n\n  // Old style unhashed tokens are replaced by hashed tokens when\n  // encountered.  This means that after someone logins once, the\n  // old unhashed token is no longer available to be stolen.\n  var userId4 = Accounts.insertUserDoc({}, {username: Random.id()});\n  var stampedToken = Accounts._generateStampedLoginToken();\n  insertUnhashedLoginToken(userId4, stampedToken);\n  connection = DDP.connect(Meteor.absoluteUrl());\n  connection.call('login', {resume: stampedToken.token});\n  connection.disconnect();\n\n  // The token is no longer available to be stolen.\n  stolenToken = Meteor.users.findOne(userId4).services.resume.loginTokens[0].token;\n  test.isFalse(stolenToken);\n\n  // After the upgrade, the client can still login with their original\n  // unhashed login token.\n  connection = DDP.connect(Meteor.absoluteUrl());\n  connection.call('login', {resume: stampedToken.token});\n  connection.disconnect();\n\n  onComplete();\n});\n\nTinytest.addAsync(\n  'accounts - connection data cleaned up',\n  function (test, onComplete) {\n    makeTestConnection(\n      test,\n      function (clientConn, serverConn) {\n        // onClose callbacks are called in order, so we run after the\n        // close callback in accounts.\n        serverConn.onClose(function () {\n          test.isFalse(Accounts._getAccountData(serverConn.id, 'connection'));\n          onComplete();\n        });\n\n        test.isTrue(Accounts._getAccountData(serverConn.id, 'connection'));\n        serverConn.close();\n      },\n      onComplete\n    );\n  }\n);\n\nTinytest.add(\n  'accounts - get new token',\n  function (test) {\n    // Test that the `getNewToken` method returns us a valid token, with\n    // the same expiration as our original token.\n    var userId = Accounts.insertUserDoc({}, { username: Random.id() });\n    var stampedToken = Accounts._generateStampedLoginToken();\n    Accounts._insertLoginToken(userId, stampedToken);\n    var conn = DDP.connect(Meteor.absoluteUrl());\n    conn.call('login', { resume: stampedToken.token });\n    test.equal(conn.call('getCurrentLoginToken'),\n               Accounts._hashLoginToken(stampedToken.token));\n\n    var newTokenResult = conn.call('getNewToken');\n    test.equal(newTokenResult.tokenExpires,\n               Accounts._tokenExpiration(stampedToken.when));\n    test.equal(conn.call('getCurrentLoginToken'),\n               Accounts._hashLoginToken(newTokenResult.token));\n    conn.disconnect();\n\n    // A second connection should be able to log in with the new token\n    // we got.\n    var secondConn = DDP.connect(Meteor.absoluteUrl());\n    secondConn.call('login', { resume: newTokenResult.token });\n    secondConn.disconnect();\n  }\n);\n\nTinytest.addAsync(\n  'accounts - remove other tokens',\n  function (test, onComplete) {\n    // Test that the `removeOtherTokens` method removes all tokens other\n    // than the caller's token, thereby logging out and closing other\n    // connections.\n    var userId = Accounts.insertUserDoc({}, { username: Random.id() });\n    var stampedTokens = [];\n    var conns = [];\n\n    _.times(2, function (i) {\n      stampedTokens.push(Accounts._generateStampedLoginToken());\n      Accounts._insertLoginToken(userId, stampedTokens[i]);\n      var conn = DDP.connect(Meteor.absoluteUrl());\n      conn.call('login', { resume: stampedTokens[i].token });\n      test.equal(conn.call('getCurrentLoginToken'),\n                 Accounts._hashLoginToken(stampedTokens[i].token));\n      conns.push(conn);\n    });\n\n    conns[0].call('removeOtherTokens');\n    simplePoll(\n      function () {\n        var tokens = _.map(conns, function (conn) {\n          return conn.call('getCurrentLoginToken');\n        });\n        return ! tokens[1] &&\n          tokens[0] === Accounts._hashLoginToken(stampedTokens[0].token);\n      },\n      function () { // success\n        _.each(conns, function (conn) {\n          conn.disconnect();\n        });\n        onComplete();\n      },\n      function () { // timed out\n        throw new Error(\"accounts - remove other tokens timed out\");\n      }\n    );\n  }\n);\n\nTinytest.add(\n  'accounts - hook callbacks can access Meteor.userId()',\n  function (test) {\n    var userId = Accounts.insertUserDoc({}, { username: Random.id() });\n    var stampedToken = Accounts._generateStampedLoginToken();\n    Accounts._insertLoginToken(userId, stampedToken);\n\n    var validateStopper = Accounts.validateLoginAttempt(function(attempt) {\n      test.equal(Meteor.userId(), validateAttemptExpectedUserId, \"validateLoginAttempt\");\n      return true;\n    });\n    var onLoginStopper = Accounts.onLogin(function(attempt) {\n      test.equal(Meteor.userId(), onLoginExpectedUserId, \"onLogin\");\n    });\n    var onLoginFailureStopper = Accounts.onLoginFailure(function(attempt) {\n      test.equal(Meteor.userId(), onLoginFailureExpectedUserId, \"onLoginFailure\");\n    });\n\n    var conn = DDP.connect(Meteor.absoluteUrl());\n\n    // On a new connection, Meteor.userId() should be null until logged in.\n    var validateAttemptExpectedUserId = null;\n    var onLoginExpectedUserId = userId;\n    conn.call('login', { resume: stampedToken.token });\n\n    // Now that the user is logged in on the connection, Meteor.userId() should\n    // return that user.\n    validateAttemptExpectedUserId = userId;\n    conn.call('login', { resume: stampedToken.token });\n\n    // Trigger onLoginFailure callbacks\n    var onLoginFailureExpectedUserId = userId;\n    test.throws(function() { conn.call('login', { resume: \"bogus\" }) }, '403');\n\n    conn.disconnect();\n    validateStopper.stop();\n    onLoginStopper.stop();\n    onLoginFailureStopper.stop();\n  }\n);\n"
  },
  {
    "path": "packages/accounts-base/accounts_url_tests.js",
    "content": "import {AccountsTest} from \"meteor/accounts-base\";\n\nTinytest.add(\"accounts - parse urls for accounts-password\",\n  function (test) {\n    var actions = [\"reset-password\", \"verify-email\", \"enroll-account\"];\n\n    // make sure the callback was called the right number of times\n    var actionsParsed = [];\n\n    _.each(actions, function (hashPart) {\n      var fakeToken = \"asdf\";\n      \n      var hashTokenOnly = \"#/\" + hashPart + \"/\" + fakeToken;\n      AccountsTest.attemptToMatchHash(hashTokenOnly, function (token, action) {\n        test.equal(token, fakeToken);\n        test.equal(action, hashPart);\n\n        // XXX COMPAT WITH 0.9.3\n        if (hashPart === \"reset-password\") {\n          test.equal(Accounts._resetPasswordToken, fakeToken);\n        } else if (hashPart === \"verify-email\") {\n          test.equal(Accounts._verifyEmailToken, fakeToken);\n        } else if (hashPart === \"enroll-account\") {\n          test.equal(Accounts._enrollAccountToken, fakeToken);\n        }\n\n        // Reset variables for the next test\n        Accounts._resetPasswordToken = null;\n        Accounts._verifyEmailToken = null;\n        Accounts._enrollAccountToken = null;\n\n        actionsParsed.push(action);\n      });\n    });\n\n    // make sure each action is called once, in order\n    test.equal(actionsParsed, actions);\n  });\n"
  },
  {
    "path": "packages/accounts-base/client_main.js",
    "content": "import {AccountsClient} from \"./accounts_client.js\";\nimport {AccountsTest} from \"./url_client.js\";\nimport \"./localstorage_token.js\";\n\n/**\n * @namespace Accounts\n * @summary The namespace for all client-side accounts-related methods.\n */\nAccounts = new AccountsClient();\n\n/**\n * @summary A [Mongo.Collection](#collections) containing user documents.\n * @locus Anywhere\n * @type {Mongo.Collection}\n * @importFromPackage meteor\n */\nMeteor.users = Accounts.users;\n\nexport {\n  // Since this file is the main module for the client version of the\n  // accounts-base package, properties of non-entry-point modules need to\n  // be re-exported in order to be accessible to modules that import the\n  // accounts-base package.\n  AccountsClient,\n  AccountsTest,\n};\n"
  },
  {
    "path": "packages/accounts-base/client_tests.js",
    "content": "import \"./accounts_url_tests.js\";\nimport \"./accounts_reconnect_tests.js\";\n"
  },
  {
    "path": "packages/accounts-base/localstorage_token.js",
    "content": "import {AccountsClient} from \"./accounts_client.js\";\nvar Ap = AccountsClient.prototype;\n\n// This file deals with storing a login token and user id in the\n// browser's localStorage facility. It polls local storage every few\n// seconds to synchronize login state between multiple tabs in the same\n// browser.\n\n// Login with a Meteor access token. This is the only public function\n// here.\nMeteor.loginWithToken = function (token, callback) {\n  return Accounts.loginWithToken(token, callback);\n};\n\nAp.loginWithToken = function (token, callback) {\n  this.callLoginMethod({\n    methodArguments: [{\n      resume: token\n    }],\n    userCallback: callback\n  });\n};\n\n// Semi-internal API. Call this function to re-enable auto login after\n// if it was disabled at startup.\nAp._enableAutoLogin = function () {\n  this._autoLoginEnabled = true;\n  this._pollStoredLoginToken();\n};\n\n\n///\n/// STORING\n///\n\n// Call this from the top level of the test file for any test that does\n// logging in and out, to protect multiple tabs running the same tests\n// simultaneously from interfering with each others' localStorage.\nAp._isolateLoginTokenForTest = function () {\n  this.LOGIN_TOKEN_KEY = this.LOGIN_TOKEN_KEY + Random.id();\n  this.USER_ID_KEY = this.USER_ID_KEY + Random.id();\n};\n\nAp._storeLoginToken = function (userId, token, tokenExpires) {\n  Meteor._localStorage.setItem(this.USER_ID_KEY, userId);\n  Meteor._localStorage.setItem(this.LOGIN_TOKEN_KEY, token);\n  if (! tokenExpires)\n    tokenExpires = this._tokenExpiration(new Date());\n  Meteor._localStorage.setItem(this.LOGIN_TOKEN_EXPIRES_KEY, tokenExpires);\n\n  // to ensure that the localstorage poller doesn't end up trying to\n  // connect a second time\n  this._lastLoginTokenWhenPolled = token;\n};\n\nAp._unstoreLoginToken = function () {\n  Meteor._localStorage.removeItem(this.USER_ID_KEY);\n  Meteor._localStorage.removeItem(this.LOGIN_TOKEN_KEY);\n  Meteor._localStorage.removeItem(this.LOGIN_TOKEN_EXPIRES_KEY);\n\n  // to ensure that the localstorage poller doesn't end up trying to\n  // connect a second time\n  this._lastLoginTokenWhenPolled = null;\n};\n\n// This is private, but it is exported for now because it is used by a\n// test in accounts-password.\n//\nAp._storedLoginToken = function () {\n  return Meteor._localStorage.getItem(this.LOGIN_TOKEN_KEY);\n};\n\nAp._storedLoginTokenExpires = function () {\n  return Meteor._localStorage.getItem(this.LOGIN_TOKEN_EXPIRES_KEY);\n};\n\nAp._storedUserId = function () {\n  return Meteor._localStorage.getItem(this.USER_ID_KEY);\n};\n\nAp._unstoreLoginTokenIfExpiresSoon = function () {\n  var tokenExpires = this._storedLoginTokenExpires();\n  if (tokenExpires && this._tokenExpiresSoon(new Date(tokenExpires))) {\n    this._unstoreLoginToken();\n  }\n};\n\n///\n/// AUTO-LOGIN\n///\n\nAp._initLocalStorage = function () {\n  var self = this;\n\n  // Key names to use in localStorage\n  self.LOGIN_TOKEN_KEY = \"Meteor.loginToken\";\n  self.LOGIN_TOKEN_EXPIRES_KEY = \"Meteor.loginTokenExpires\";\n  self.USER_ID_KEY = \"Meteor.userId\";\n\n  var rootUrlPathPrefix = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX;\n  if (rootUrlPathPrefix || this.connection !== Meteor.connection) {\n    // We want to keep using the same keys for existing apps that do not\n    // set a custom ROOT_URL_PATH_PREFIX, so that most users will not have\n    // to log in again after an app updates to a version of Meteor that\n    // contains this code, but it's generally preferable to namespace the\n    // keys so that connections from distinct apps to distinct DDP URLs\n    // will be distinct in Meteor._localStorage.\n    var namespace = \":\" + this.connection._stream.rawUrl;\n    if (rootUrlPathPrefix) {\n      namespace += \":\" + rootUrlPathPrefix;\n    }\n    self.LOGIN_TOKEN_KEY += namespace;\n    self.LOGIN_TOKEN_EXPIRES_KEY += namespace;\n    self.USER_ID_KEY += namespace;\n  }\n\n  if (self._autoLoginEnabled) {\n    // Immediately try to log in via local storage, so that any DDP\n    // messages are sent after we have established our user account\n    self._unstoreLoginTokenIfExpiresSoon();\n    var token = self._storedLoginToken();\n    if (token) {\n      // On startup, optimistically present us as logged in while the\n      // request is in flight. This reduces page flicker on startup.\n      var userId = self._storedUserId();\n      userId && self.connection.setUserId(userId);\n      self.loginWithToken(token, function (err) {\n        if (err) {\n          Meteor._debug(\"Error logging in with token: \" + err);\n          self.makeClientLoggedOut();\n        }\n\n        self._pageLoadLogin({\n          type: \"resume\",\n          allowed: !err,\n          error: err,\n          methodName: \"login\",\n          // XXX This is duplicate code with loginWithToken, but\n          // loginWithToken can also be called at other times besides\n          // page load.\n          methodArguments: [{resume: token}]\n        });\n      });\n    }\n  }\n\n  // Poll local storage every 3 seconds to login if someone logged in in\n  // another tab\n  self._lastLoginTokenWhenPolled = token;\n\n  if (self._pollIntervalTimer) {\n    // Unlikely that _initLocalStorage will be called more than once for\n    // the same AccountsClient instance, but just in case...\n    clearInterval(self._pollIntervalTimer);\n  }\n\n  self._pollIntervalTimer = setInterval(function () {\n    self._pollStoredLoginToken();\n  }, 3000);\n};\n\nAp._pollStoredLoginToken = function () {\n  var self = this;\n\n  if (! self._autoLoginEnabled) {\n    return;\n  }\n\n  var currentLoginToken = self._storedLoginToken();\n\n  // != instead of !== just to make sure undefined and null are treated the same\n  if (self._lastLoginTokenWhenPolled != currentLoginToken) {\n    if (currentLoginToken) {\n      self.loginWithToken(currentLoginToken, function (err) {\n        if (err) {\n          self.makeClientLoggedOut();\n        }\n      });\n    } else {\n      self.logout();\n    }\n  }\n\n  self._lastLoginTokenWhenPolled = currentLoginToken;\n};\n"
  },
  {
    "path": "packages/accounts-base/package.js",
    "content": "Package.describe({\n  summary: \"A user account system\",\n  version: \"1.2.8\"\n});\n\nPackage.onUse(function (api) {\n  api.use('underscore', ['client', 'server']);\n  api.use('ecmascript', ['client', 'server']);\n  api.use('ddp-rate-limiter');\n  api.use('localstorage', 'client');\n  api.use('tracker', 'client');\n  api.use('check', 'server');\n  api.use('random', ['client', 'server']);\n  api.use('ejson', 'server');\n  api.use('callback-hook', ['client', 'server']);\n\n  // use unordered to work around a circular dependency\n  // (service-configuration needs Accounts.connection)\n  api.use('service-configuration', ['client', 'server'], { unordered: true });\n\n  // needed for getting the currently logged-in user\n  api.use('ddp', ['client', 'server']);\n\n  // need this because of the Meteor.users collection but in the future\n  // we'd probably want to abstract this away\n  api.use('mongo', ['client', 'server']);\n\n  // If the 'blaze' package is loaded, we'll define some helpers like\n  // {{currentUser}}.  If not, no biggie.\n  api.use('blaze', 'client', {weak: true});\n\n  // Allow us to detect 'autopublish', and publish some Meteor.users fields if\n  // it's loaded.\n  api.use('autopublish', 'server', {weak: true});\n\n  api.use('oauth-encryption', 'server', {weak: true});\n\n  // Though this \"Accounts\" symbol is the only official Package export for\n  // the accounts-base package, modules that import accounts-base will\n  // have access to anything added to the exports object of the main\n  // module, including AccountsClient and AccountsServer (those symbols\n  // just won't be automatically imported as \"global\" variables).\n  api.export('Accounts');\n\n  // These main modules import all the other modules that comprise the\n  // accounts-base package, and define exports that will be accessible to\n  // modules that import the accounts-base package.\n  api.mainModule('server_main.js', 'server');\n  api.mainModule('client_main.js', 'client');\n});\n\nPackage.onTest(function (api) {\n  api.use([\n    'accounts-base',\n    'ecmascript',\n    'tinytest',\n    'random',\n    'test-helpers',\n    'oauth-encryption',\n    'underscore',\n    'ddp',\n    'accounts-password'\n  ]);\n\n  api.mainModule('server_tests.js', 'server');\n  api.mainModule('client_tests.js', 'client');\n});\n"
  },
  {
    "path": "packages/accounts-base/server_main.js",
    "content": "import {AccountsServer} from \"./accounts_server.js\";\nimport \"./accounts_rate_limit.js\";\nimport \"./url_server.js\";\n\n/**\n * @namespace Accounts\n * @summary The namespace for all server-side accounts-related methods.\n */\nAccounts = new AccountsServer(Meteor.server);\n\n// Users table. Don't use the normal autopublish, since we want to hide\n// some fields. Code to autopublish this is in accounts_server.js.\n// XXX Allow users to configure this collection name.\n\n/**\n * @summary A [Mongo.Collection](#collections) containing user documents.\n * @locus Anywhere\n * @type {Mongo.Collection}\n * @importFromPackage meteor\n*/\nMeteor.users = Accounts.users;\n\nexport {\n  // Since this file is the main module for the server version of the\n  // accounts-base package, properties of non-entry-point modules need to\n  // be re-exported in order to be accessible to modules that import the\n  // accounts-base package.\n  AccountsServer\n};\n"
  },
  {
    "path": "packages/accounts-base/server_tests.js",
    "content": "import \"./accounts_tests.js\";\nimport \"./accounts_reconnect_tests.js\";\n"
  },
  {
    "path": "packages/accounts-base/url_client.js",
    "content": "import {AccountsClient} from \"./accounts_client.js\";\n\nvar Ap = AccountsClient.prototype;\n\n// All of the special hash URLs we support for accounts interactions\nvar accountsPaths = [\"reset-password\", \"verify-email\", \"enroll-account\"];\n\nvar savedHash = window.location.hash;\n\nAp._initUrlMatching = function () {\n  // By default, allow the autologin process to happen.\n  this._autoLoginEnabled = true;\n\n  // We only support one callback per URL.\n  this._accountsCallbacks = {};\n\n  // Try to match the saved value of window.location.hash.\n  this._attemptToMatchHash();\n};\n\n// Separate out this functionality for testing\n\nAp._attemptToMatchHash = function () {\n  attemptToMatchHash(this, savedHash, defaultSuccessHandler);\n};\n\n// Note that both arguments are optional and are currently only passed by\n// accounts_url_tests.js.\nfunction attemptToMatchHash(accounts, hash, success) {\n  _.each(accountsPaths, function (urlPart) {\n    var token;\n\n    var tokenRegex = new RegExp(\"^\\\\#\\\\/\" + urlPart + \"\\\\/(.*)$\");\n    var match = hash.match(tokenRegex);\n\n    if (match) {\n      token = match[1];\n\n      // XXX COMPAT WITH 0.9.3\n      if (urlPart === \"reset-password\") {\n        accounts._resetPasswordToken = token;\n      } else if (urlPart === \"verify-email\") {\n        accounts._verifyEmailToken = token;\n      } else if (urlPart === \"enroll-account\") {\n        accounts._enrollAccountToken = token;\n      }\n    } else {\n      return;\n    }\n\n    // If no handlers match the hash, then maybe it's meant to be consumed\n    // by some entirely different code, so we only clear it the first time\n    // a handler successfully matches. Note that later handlers reuse the\n    // savedHash, so clearing window.location.hash here will not interfere\n    // with their needs.\n    window.location.hash = \"\";\n\n    // Do some stuff with the token we matched\n    success.call(accounts, token, urlPart);\n  });\n}\n\nfunction defaultSuccessHandler(token, urlPart) {\n  var self = this;\n\n  // put login in a suspended state to wait for the interaction to finish\n  self._autoLoginEnabled = false;\n\n  // wait for other packages to register callbacks\n  Meteor.startup(function () {\n    // if a callback has been registered for this kind of token, call it\n    if (self._accountsCallbacks[urlPart]) {\n      self._accountsCallbacks[urlPart](token, function () {\n        self._enableAutoLogin();\n      });\n    }\n  });\n}\n\n// Export for testing\nexport var AccountsTest = {\n  attemptToMatchHash: function (hash, success) {\n    return attemptToMatchHash(Accounts, hash, success);\n  }\n};\n\n// XXX these should be moved to accounts-password eventually. Right now\n// this is prevented by the need to set autoLoginEnabled=false, but in\n// some bright future we won't need to do that anymore.\n\n/**\n * @summary Register a function to call when a reset password link is clicked\n * in an email sent by\n * [`Accounts.sendResetPasswordEmail`](#accounts_sendresetpasswordemail).\n * This function should be called in top-level code, not inside\n * `Meteor.startup()`.\n * @memberof! Accounts\n * @name onResetPasswordLink\n * @param  {Function} callback The function to call. It is given two arguments:\n *\n * 1. `token`: A password reset token that can be passed to\n * [`Accounts.resetPassword`](#accounts_resetpassword).\n * 2. `done`: A function to call when the password reset UI flow is complete. The normal\n * login process is suspended until this function is called, so that the\n * password for user A can be reset even if user B was logged in.\n * @locus Client\n */\nAp.onResetPasswordLink = function (callback) {\n  if (this._accountsCallbacks[\"reset-password\"]) {\n    Meteor._debug(\"Accounts.onResetPasswordLink was called more than once. \" +\n      \"Only one callback added will be executed.\");\n  }\n\n  this._accountsCallbacks[\"reset-password\"] = callback;\n};\n\n/**\n * @summary Register a function to call when an email verification link is\n * clicked in an email sent by\n * [`Accounts.sendVerificationEmail`](#accounts_sendverificationemail).\n * This function should be called in top-level code, not inside\n * `Meteor.startup()`.\n * @memberof! Accounts\n * @name onEmailVerificationLink\n * @param  {Function} callback The function to call. It is given two arguments:\n *\n * 1. `token`: An email verification token that can be passed to\n * [`Accounts.verifyEmail`](#accounts_verifyemail).\n * 2. `done`: A function to call when the email verification UI flow is complete.\n * The normal login process is suspended until this function is called, so\n * that the user can be notified that they are verifying their email before\n * being logged in.\n * @locus Client\n */\nAp.onEmailVerificationLink = function (callback) {\n  if (this._accountsCallbacks[\"verify-email\"]) {\n    Meteor._debug(\"Accounts.onEmailVerificationLink was called more than once. \" +\n      \"Only one callback added will be executed.\");\n  }\n\n  this._accountsCallbacks[\"verify-email\"] = callback;\n};\n\n/**\n * @summary Register a function to call when an account enrollment link is\n * clicked in an email sent by\n * [`Accounts.sendEnrollmentEmail`](#accounts_sendenrollmentemail).\n * This function should be called in top-level code, not inside\n * `Meteor.startup()`.\n * @memberof! Accounts\n * @name onEnrollmentLink\n * @param  {Function} callback The function to call. It is given two arguments:\n *\n * 1. `token`: A password reset token that can be passed to\n * [`Accounts.resetPassword`](#accounts_resetpassword) to give the newly\n * enrolled account a password.\n * 2. `done`: A function to call when the enrollment UI flow is complete.\n * The normal login process is suspended until this function is called, so that\n * user A can be enrolled even if user B was logged in.\n * @locus Client\n */\nAp.onEnrollmentLink = function (callback) {\n  if (this._accountsCallbacks[\"enroll-account\"]) {\n    Meteor._debug(\"Accounts.onEnrollmentLink was called more than once. \" +\n      \"Only one callback added will be executed.\");\n  }\n\n  this._accountsCallbacks[\"enroll-account\"] = callback;\n};\n"
  },
  {
    "path": "packages/accounts-base/url_server.js",
    "content": "import {AccountsServer} from \"./accounts_server.js\";\n\n// XXX These should probably not actually be public?\n\nAccountsServer.prototype.urls = {\n  resetPassword: function (token) {\n    return Meteor.absoluteUrl('#/reset-password/' + token);\n  },\n\n  verifyEmail: function (token) {\n    return Meteor.absoluteUrl('#/verify-email/' + token);\n  },\n\n  enrollAccount: function (token) {\n    return Meteor.absoluteUrl('#/enroll-account/' + token);\n  }\n};\n"
  },
  {
    "path": "packages/accounts-facebook/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/accounts-facebook/README.md",
    "content": "# accounts-facebook\n\nA login service for Facebook. See the [project page](https://www.meteor.com/accounts) on Meteor Accounts for more details."
  },
  {
    "path": "packages/accounts-facebook/facebook.js",
    "content": "Accounts.oauth.registerService('facebook');\n\nif (Meteor.isClient) {\n  Meteor.loginWithFacebook = function(options, callback) {\n    // support a callback without options\n    if (! callback && typeof options === \"function\") {\n      callback = options;\n      options = null;\n    }\n\n    var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback);\n    Facebook.requestCredential(options, credentialRequestCompleteCallback);\n  };\n} else {\n  Accounts.addAutopublishFields({\n    // publish all fields including access token, which can legitimately\n    // be used from the client (if transmitted over ssl or on\n    // localhost). https://developers.facebook.com/docs/concepts/login/access-tokens-and-types/,\n    // \"Sharing of Access Tokens\"\n    forLoggedInUser: ['services.facebook'],\n    forOtherUsers: [\n      // https://www.facebook.com/help/167709519956542\n      'services.facebook.id', 'services.facebook.username', 'services.facebook.gender'\n    ]\n  });\n}\n"
  },
  {
    "path": "packages/accounts-facebook/facebook_login_button.css",
    "content": "#login-buttons-image-facebook {\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAq0lEQVQ4jWP8//8/AyWAhYGBgcEmauYZBgYGYxL1nj2yLN2ECcohVTNcDwsxKlXlhRm6yzwZRAS5GRgYGBhsombC5ZhwaUIGyJrRAVEuwGYzSS7AB/C64MiydKx8ZJfgNeDN+68MDAwIL8D4RLsgIHsJis0wPjKgOAyoE4hcnGwMGkpiBBUbacvA2TfuvaKiC759/3X23NUnOPMDtgTEwMBwloGBgYGR0uwMAGOPLJS9mkQHAAAAAElFTkSuQmCC);\n}\n"
  },
  {
    "path": "packages/accounts-facebook/package.js",
    "content": "Package.describe({\n  summary: \"Login service for Facebook accounts\",\n  version: \"1.0.10\"\n});\n\nPackage.onUse(function(api) {\n  api.use('accounts-base', ['client', 'server']);\n  // Export Accounts (etc) to packages using this one.\n  api.imply('accounts-base', ['client', 'server']);\n  api.use('accounts-oauth', ['client', 'server']);\n  api.use('facebook', ['client', 'server']);\n\n  api.addFiles('facebook_login_button.css', 'client');\n\n  api.addFiles(\"facebook.js\");\n});\n"
  },
  {
    "path": "packages/accounts-github/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/accounts-github/README.md",
    "content": "# accounts-github\n\nA login service for GitHub. See the [project page](https://www.meteor.com/accounts) on Meteor Accounts for more details."
  },
  {
    "path": "packages/accounts-github/github.js",
    "content": "Accounts.oauth.registerService('github');\n\nif (Meteor.isClient) {\n  Meteor.loginWithGithub = function(options, callback) {\n    // support a callback without options\n    if (! callback && typeof options === \"function\") {\n      callback = options;\n      options = null;\n    }\n\n    var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback);\n    Github.requestCredential(options, credentialRequestCompleteCallback);\n  };\n} else {\n  Accounts.addAutopublishFields({\n    // not sure whether the github api can be used from the browser,\n    // thus not sure if we should be sending access tokens; but we do it\n    // for all other oauth2 providers, and it may come in handy.\n    forLoggedInUser: ['services.github'],\n    forOtherUsers: ['services.github.username']\n  });\n}\n"
  },
  {
    "path": "packages/accounts-github/github_login_button.css",
    "content": "#login-buttons-image-github {\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wJGBYxHYxl31wAAAHpSURBVDjLpZI/aFNRFMZ/973bJqGRPopV4qNq/+SpTYnWRhCKilShg9BGcHOM+GfQoZuLk4iLgw4qZNBaHLuIdBNHl7Ta1qdNFI3SihnaNG1MpH3vuiQYQnwZvHCG893zffc751z4z6PX5T5gA1DAKnAaOAQEgAfAVeCpl+CeCrlRuEC6maO4h0A1wl4tPAHMqNUthvrDdHYY7A3t4rDVjeO6rBU2FaABM1WCrBNoi48Mi+nH9yj+KtPibAKwJXfQ5vcRG7soUnYmWEuQgAEIYBv4cGpoILI0Z4tyYYPegS6UguyijZQ6J45GSNmZHzUcJYD2ii2Ajv7efZ8WZ6ZwXFj79hXpayW4O0SL1Nl/8jzZlZ9dQLFS70pgvZKIyGD0yvu5eRmMnrk1PjI81ir1qBACTdPevXj95mVuNX8XKDQc/+T334bZZ104cvzYw2s3J3qAL5WXSsDbf61NNMBu+wOBs+VSyQ84Nfhg028ZGx3/qyy0lC7lgi7lghBitoon03lvB8l0/k7Wnk+8mny0cyXzEcfZxgwfZPTyRMHsOzAFXE9YhtNQIJnOx4FpJXT1eSkn2g0frqMoFrfoCXcqlCOAGwnLuO/l4JymcWl5uRxzXUKghBAiZ5r+WaV4lrCM555zqO+x2d0ftGmpiA/0k70AAAAASUVORK5CYII=);\n}\n"
  },
  {
    "path": "packages/accounts-github/package.js",
    "content": "Package.describe({\n  summary: \"Login service for Github accounts\",\n  version: \"1.0.10\"\n});\n\nPackage.onUse(function(api) {\n  api.use('accounts-base', ['client', 'server']);\n  // Export Accounts (etc) to packages using this one.\n  api.imply('accounts-base', ['client', 'server']);\n  api.use('accounts-oauth', ['client', 'server']);\n  api.use('github', ['client', 'server']);\n\n  api.addFiles('github_login_button.css', 'client');\n\n  api.addFiles(\"github.js\");\n});\n"
  },
  {
    "path": "packages/accounts-google/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/accounts-google/README.md",
    "content": "# accounts-google\n\nA login service for Google. See the [project page](https://www.meteor.com/accounts) on Meteor Accounts for more details."
  },
  {
    "path": "packages/accounts-google/google.js",
    "content": "Accounts.oauth.registerService('google');\n\nif (Meteor.isClient) {\n  Meteor.loginWithGoogle = function(options, callback) {\n    // support a callback without options\n    if (! callback && typeof options === \"function\") {\n      callback = options;\n      options = null;\n    }\n\n    // Use Google's domain-specific login page if we want to restrict creation to\n    // a particular email domain. (Don't use it if restrictCreationByEmailDomain\n    // is a function.) Note that all this does is change Google's UI ---\n    // accounts-base/accounts_server.js still checks server-side that the server\n    // has the proper email address after the OAuth conversation.\n    if (typeof Accounts._options.restrictCreationByEmailDomain === 'string') {\n      options = _.extend({}, options || {});\n      options.loginUrlParameters = _.extend({}, options.loginUrlParameters || {});\n      options.loginUrlParameters.hd = Accounts._options.restrictCreationByEmailDomain;\n    }\n    var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback);\n    Google.requestCredential(options, credentialRequestCompleteCallback);\n  };\n} else {\n  Accounts.addAutopublishFields({\n    forLoggedInUser: _.map(\n      // publish access token since it can be used from the client (if\n      // transmitted over ssl or on\n      // localhost). https://developers.google.com/accounts/docs/OAuth2UserAgent\n      // refresh token probably shouldn't be sent down.\n      Google.whitelistedFields.concat(['accessToken', 'expiresAt']), // don't publish refresh token\n      function (subfield) { return 'services.google.' + subfield; }),\n\n    forOtherUsers: _.map(\n      // even with autopublish, no legitimate web app should be\n      // publishing all users' emails\n      _.without(Google.whitelistedFields, 'email', 'verified_email'),\n      function (subfield) { return 'services.google.' + subfield; })\n  });\n}\n"
  },
  {
    "path": "packages/accounts-google/google_login_button.css",
    "content": "#login-buttons-image-google {\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAADCklEQVQ4jSXSy2ucVRjA4d97zvdNJpPJbTJJE9rYaCINShZtRCFIA1bbLryBUlyoLQjqVl12W7UbN4qb1gtuYhFRRBCDBITaesFbbI3RFBLSptEY05l0ZjLfnMvrov/Bs3gAcF71x6VVHTk+o8nDH+hrH89rUK9Z9Yaen57S3wVtGaMBNGC0IegWKIDxTtVaOHVugZVmH3HX3Zz+4l+W1xvkOjuZfPsspY4CNkZELEgEIJKwYlBjEwjec/mfCMVuorVs76R8+P0KYMmP30U2dT8eIZqAR2ipRcWjEYxGSCRhV08e04oYMoxYLi97EI9YCJ0FHBYbIVGDlUBLwRlLIuYW6chEmQt/rJO09RJjhjEJEYvJYGNhkbUhw43OXtIWDFRq9G87nAaSK6sVRm8r8fzRMWbOX2Xx7ypd7ZET03sQhDOz73DqSJOrd+7HSo4QIu0Nx/4rOzx+cRXZ9+z7+uqJ+3hiepxK3fHZT2tMjXYzOtzL6dmznPzhLexgN0QlxAAYxAlqUqRmkf5j59RlNQ6MFHhgcpCTTx8EUb5e+plD7x4jjg1ANCAgrRQAdR7xKXjBlGyLYi7PxaUmb8z8xcpGHVXLHaXdjI0egKyJiQYTEhSPREVIEUBNC+Mqm+xpz3j0njLPHB2nsh1QgeG+IS48dYbD5YNoo0ZUAbVEuTUoKuBSZOarX/WhyQn6eg2+usDWf0s0tq8zNPYk+WI/Lnge++hlvlyfQ3NdECzGRWKwEEA0qNY251n69kV6+Y0kbaCZoebG2X3oU7pKoyxuXOPe945zs9DCeosGIXoBDyaLdf6ce4Hbk+/Y299ksKtAuaeNsiyw8c1LKIZ95b0MdgxA5giixACpTxEPSau6QdFfI5/2cLPmEW+JAQrtJUJzDXF1dkwHzVodJMX4HFEcQQMaFdPeM0Jb/4PUtzzaLKAhRyJFwo6lbegRNFfk819muV5dR4JBQoQdQ2xFiDmSNDHiaptamR9Gq5cQ18AledrGDpOfeI5Lq8u88smbhMRisoSAgAYghdfn5H/JkHuRZ1owLAAAAABJRU5ErkJggg==);\n}\n"
  },
  {
    "path": "packages/accounts-google/package.js",
    "content": "Package.describe({\n  summary: \"Login service for Google accounts\",\n  version: \"1.0.10\"\n});\n\nPackage.onUse(function(api) {\n  api.use(['underscore', 'random']);\n  api.use('accounts-base', ['client', 'server']);\n  // Export Accounts (etc) to packages using this one.\n  api.imply('accounts-base', ['client', 'server']);\n  api.use('accounts-oauth', ['client', 'server']);\n  api.use('google', ['client', 'server']);\n\n  api.addFiles('google_login_button.css', 'client');\n\n  api.addFiles(\"google.js\");\n});\n"
  },
  {
    "path": "packages/accounts-meetup/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/accounts-meetup/README.md",
    "content": "# accounts-meetup\n\nA login service for Meetup. See the [project page](https://www.meteor.com/accounts) on Meteor Accounts for more details."
  },
  {
    "path": "packages/accounts-meetup/meetup.js",
    "content": "Accounts.oauth.registerService('meetup');\n\nif (Meteor.isClient) {\n  Meteor.loginWithMeetup = function(options, callback) {\n    // support a callback without options\n    if (! callback && typeof options === \"function\") {\n      callback = options;\n      options = null;\n    }\n\n    var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback);\n    Meetup.requestCredential(options, credentialRequestCompleteCallback);\n  };\n} else {\n  Accounts.addAutopublishFields({\n    // publish all fields including access token, which can legitimately\n    // be used from the client (if transmitted over ssl or on\n    // localhost). http://www.meetup.com/meetup_api/auth/#oauth2implicit\n    forLoggedInUser: ['services.meetup'],\n    forOtherUsers: ['services.meetup.id']\n  });\n}\n"
  },
  {
    "path": "packages/accounts-meetup/meetup_login_button.css",
    "content": "#login-buttons-image-meetup.login-image {\n    top: 8px;\n    height: 11px;\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAEJGlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XtShal6dgqJOQ6N4mpGwfb6baqT3uBNwb8AUDZAw9IPCENBmJ72fbAtElThyqqSUh76MQPISbtBVXhu3ZiJ1PEXPX6yznfOec7517bRD1fabWaGVWIlquunc8klZOnFpSeTYrSs9RLA9Sr6U4tkcvNEi7BFffO6+EdigjL7ZHu/k72I796i9zRiSJPwG4VHX0Z+AxRzNRrtksUvwf7+Gm3BtzzHPDTNgQCqwKXfZwSeNHHJz1OIT8JjtAq6xWtCLwGPLzYZi+3YV8DGMiT4VVuG7oiZpGzrZJhcs/hL49xtzH/Dy6bdfTsXYNY+5yluWO4D4neK/ZUvok/17X0HPBLsF+vuUlhfwX4j/rSfAJ4H1H0qZJ9dN7nR19frRTeBt4Fe9FwpwtN+2p1MXscGLHR9SXrmMgjONd1ZxKzpBeA71b4tNhj6JGoyFNp4GHgwUp9qplfmnFW5oTdy7NamcwCI49kv6fN5IAHgD+0rbyoBc3SOjczohbyS1drbq6pQdqumllRC/0ymTtej8gpbbuVwpQfyw66dqEZyxZKxtHpJn+tZnpnEdrYBbueF9qQn93S7HQGGHnYP7w6L+YGHNtd1FJitqPAR+hERCNOFi1i1alKO6RQnjKUxL1GNjwlMsiEhcPLYTEiT9ISbN15OY/jx4SMshe9LaJRpTvHr3C/ybFYP1PZAfwfYrPsMBtnE6SwN9ib7AhLwTrBDgUKcm06FSrTfSj187xPdVQWOk5Q8vxAfSiIUc7Z7xr6zY/+hpqwSyv0I0/QMTRb7RMgBxNodTfSPqdraz/sDjzKBrv4zu2+a2t0/HHzjd2Lbcc2sG7GtsL42K+xLfxtUgI7YHqKlqHK8HbCCXgjHT1cAdMlDetv4FnQ2lLasaOl6vmB0CMmwT/IPszSueHQqv6i/qluqF+oF9TfO2qEGTumJH0qfSv9KH0nfS/9TIp0Wboi/SRdlb6RLgU5u++9nyXYe69fYRPdil1o1WufNSdTTsp75BfllPy8/LI8G7AUuV8ek6fkvfDsCfbNDP0dvRh0CrNqTbV7LfEEGDQPJQadBtfGVMWEq3QWWdufk6ZSNsjG2PQjp3ZcnOWWing6noonSInvi0/Ex+IzAreevPhe+CawpgP1/pMTMDo64G0sTCXIM+KdOnFWRfQKdJvQzV1+Bt8OokmrdtY2yhVX2a+qrykJfMq4Ml3VR4cVzTQVz+UoNne4vcKLoyS+gyKO6EHe+75Fdt0Mbe5bRIf/wjvrVmhbqBN97RD1vxrahvBOfOYzoosH9bq94uejSOQGkVM6sN/7HelL4t10t9F4gPdVzydEOx83Gv+uNxo7XyL/FtFl8z9ZAHF4bBsrEwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAiFJREFUKBV9Ur+PEkEU/t7sLO7yUyB6whmBEPWUxCiaaGFtNDH+D+ZabWxo7GxI7hL/BctrjbXdxYqLV1gIHAq5AIdHCMguByw741vUxMqXzExm5v343vc9+ljdfaOOe69Dnods4ryKRiICRNAAiFdwQvPOb+s7kRa+T8K2MUzGdqR7+OVhYu8dYoDy2W0cBPzHOAmxn3cBMK2XlTvyYuGKvvz8BdTSIxgGSAjOxC5/zAiZEKaJ1dmcgSgGwv+M1o7G4G1e8uXVZ0/91L0yw1TAavU7TBhryDAlJicn6LQ7uFkqQRgCgltBOLz282uflQzFuGdp4OdipYfDIQ0GAxSLRfT7ffYL46jVgmBUt+LcJNvYcdBu1HH72nVY6SRJSQY0w3tbreK43YbN5OQLBTQbDSRTKeRyOcQTcXza30eUYR8e1PD123dktrexYUhIzTyTdQ4wBC25hXw2gylXefTksXamDm3d2MJ4MkG320On08Ho9BSlu2XaKOQxb7YgfaUCZvCqUvH9lUdKaXJdV9u2xZxKYmNiiekw0e31dKNeV+UH94MYeTZfaOlPXROLJWJKswQGKwGk4gloViJQXiuegaCGkCgmU7CymyI6X64C3Wk2k3JYO5jZe+/hOFPSLJHgauuh4cqaByhAEJxBouAvETJp4bhmOJ3GKJdZyiOtdhapSNOMW1yQfBaTheb9X2MV/r4ZplRIROQP21YjK/ThF08c3oOAma3kAAAAAElFTkSuQmCC);\n}\n"
  },
  {
    "path": "packages/accounts-meetup/package.js",
    "content": "Package.describe({\n  summary: \"Login service for Meetup accounts\",\n  version: \"1.0.10\"\n});\n\nPackage.onUse(function(api) {\n  api.use('accounts-base', ['client', 'server']);\n  // Export Accounts (etc) to packages using this one.\n  api.imply('accounts-base', ['client', 'server']);\n  api.use('accounts-oauth', ['client', 'server']);\n  api.use('meetup', ['client', 'server']);\n\n  api.addFiles('meetup_login_button.css', 'client');\n\n  api.addFiles(\"meetup.js\");\n});\n"
  },
  {
    "path": "packages/accounts-meteor-developer/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/accounts-meteor-developer/README.md",
    "content": "# accounts-meteor-developer\n\nA login service for Meteor developer accounts. See the project page on\n[Meteor Accounts](https://www.meteor.com/accounts) and Meteor [Developer\nAccounts](https://www.meteor.com/services/developer-accounts) for more\ndetails."
  },
  {
    "path": "packages/accounts-meteor-developer/meteor-developer-login-button.css",
    "content": "#login-buttons-image-meteor-developer {\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAEJGlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XtShal6dgqJOQ6N4mpGwfb6baqT3uBNwb8AUDZAw9IPCENBmJ72fbAtElThyqqSUh76MQPISbtBVXhu3ZiJ1PEXPX6yznfOec7517bRD1fabWaGVWIlquunc8klZOnFpSeTYrSs9RLA9Sr6U4tkcvNEi7BFffO6+EdigjL7ZHu/k72I796i9zRiSJPwG4VHX0Z+AxRzNRrtksUvwf7+Gm3BtzzHPDTNgQCqwKXfZwSeNHHJz1OIT8JjtAq6xWtCLwGPLzYZi+3YV8DGMiT4VVuG7oiZpGzrZJhcs/hL49xtzH/Dy6bdfTsXYNY+5yluWO4D4neK/ZUvok/17X0HPBLsF+vuUlhfwX4j/rSfAJ4H1H0qZJ9dN7nR19frRTeBt4Fe9FwpwtN+2p1MXscGLHR9SXrmMgjONd1ZxKzpBeA71b4tNhj6JGoyFNp4GHgwUp9qplfmnFW5oTdy7NamcwCI49kv6fN5IAHgD+0rbyoBc3SOjczohbyS1drbq6pQdqumllRC/0ymTtej8gpbbuVwpQfyw66dqEZyxZKxtHpJn+tZnpnEdrYBbueF9qQn93S7HQGGHnYP7w6L+YGHNtd1FJitqPAR+hERCNOFi1i1alKO6RQnjKUxL1GNjwlMsiEhcPLYTEiT9ISbN15OY/jx4SMshe9LaJRpTvHr3C/ybFYP1PZAfwfYrPsMBtnE6SwN9ib7AhLwTrBDgUKcm06FSrTfSj187xPdVQWOk5Q8vxAfSiIUc7Z7xr6zY/+hpqwSyv0I0/QMTRb7RMgBxNodTfSPqdraz/sDjzKBrv4zu2+a2t0/HHzjd2Lbcc2sG7GtsL42K+xLfxtUgI7YHqKlqHK8HbCCXgjHT1cAdMlDetv4FnQ2lLasaOl6vmB0CMmwT/IPszSueHQqv6i/qluqF+oF9TfO2qEGTumJH0qfSv9KH0nfS/9TIp0Wboi/SRdlb6RLgU5u++9nyXYe69fYRPdil1o1WufNSdTTsp75BfllPy8/LI8G7AUuV8ek6fkvfDsCfbNDP0dvRh0CrNqTbV7LfEEGDQPJQadBtfGVMWEq3QWWdufk6ZSNsjG2PQjp3ZcnOWWing6noonSInvi0/Ex+IzAreevPhe+CawpgP1/pMTMDo64G0sTCXIM+KdOnFWRfQKdJvQzV1+Bt8OokmrdtY2yhVX2a+qrykJfMq4Ml3VR4cVzTQVz+UoNne4vcKLoyS+gyKO6EHe+75Fdt0Mbe5bRIf/wjvrVmhbqBN97RD1vxrahvBOfOYzoosH9bq94uejSOQGkVM6sN/7HelL4t10t9F4gPdVzydEOx83Gv+uNxo7XyL/FtFl8z9ZAHF4bBsrEwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAg5JREFUOBFdU7uuqVEQHr/7/RIhJMLZUVGrdAoP4AEUXkC1T6dSKZQ6TyAkEvtUFGqVRKGlkRCFwm27zZkZ/rV/eyXWXP75Zr6ZNQAA8PdP0zTxBYNB9c3j8Sj9V/x7ApPJJIGhYEhkoVDAer0uutfrRbPZ/JaI4k1IB9xuN1itVrher1QA4H6/w/l8hsViAcfjETKZDBAjOBwOcLlcJIYvjcFOp1M+7HY7keFwWMC9Xg+SySSs12sBUHXgeOOxMPh0OkGxWIRAIADz+RxmsxnUajUolUoSy8z42Gw2KcY6MyX2AJFIRHpqt9vcCm63WxyPx0hsxOZrMpm89e3z+dBisTx9DocDiYUYo9FIgVihOYhNfWOr1UJihLlcTiV7JQE0PhFX43O73UQ+Hg+RfNFQke1utytJqGWkJ9dgv99DPB7n1uD78i1Sv7hPwoppt9vlBZbLpdgyA9KQpi4Zy+WyVFAlSdEZcPXBYID5fF5i/X6/SJ4shkLPpZlOp4JdrVZYrVZxOByqXP1+/wmggvrgZWN5iMwilUrh178v7HQ6mM1mxffx5wM3m40kaTab4kskEiJ5ARnHvSCzeBlKptNp0RuNhiT4/PspNrdrACMvg3ygZcFoNIqxWExehenx7nNi3otKpSK66v1ZnX0/fyb+o0hfL5++HxyjA/WCBtxPAoNT0XS5XGrR1PYZiv4Hdhyfo4t1ww8AAAAASUVORK5CYII=);\n}"
  },
  {
    "path": "packages/accounts-meteor-developer/meteor-developer.js",
    "content": "Accounts.oauth.registerService(\"meteor-developer\");\n\nif (Meteor.isClient) {\n  Meteor.loginWithMeteorDeveloperAccount = function (options, callback) {\n    // support a callback without options\n    if (! callback && typeof options === \"function\") {\n      callback = options;\n      options = null;\n    }\n\n    var credentialRequestCompleteCallback =\n          Accounts.oauth.credentialRequestCompleteHandler(callback);\n    MeteorDeveloperAccounts.requestCredential(options, credentialRequestCompleteCallback);\n  };\n} else {\n  Accounts.addAutopublishFields({\n    // publish all fields including access token, which can legitimately be used\n    // from the client (if transmitted over ssl or on localhost).\n    forLoggedInUser: ['services.meteor-developer'],\n    forOtherUsers: [\n      'services.meteor-developer.username',\n      'services.meteor-developer.profile',\n      'services.meteor-developer.id'\n    ]\n  });\n}\n"
  },
  {
    "path": "packages/accounts-meteor-developer/package.js",
    "content": "Package.describe({\n  summary: \"Login service for Meteor developer accounts\",\n  version: \"1.0.10\"\n});\n\nPackage.onUse(function (api) {\n  api.use(['underscore', 'random']);\n  api.use('accounts-base', ['client', 'server']);\n  // Export Accounts (etc) to packages using this one.\n  api.imply('accounts-base', ['client', 'server']);\n  api.use('accounts-oauth', ['client', 'server']);\n  api.use('meteor-developer', ['client', 'server']);\n\n  api.addFiles(\"meteor-developer.js\");\n  api.addFiles(\"meteor-developer-login-button.css\", \"client\");\n});\n"
  },
  {
    "path": "packages/accounts-oauth/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/accounts-oauth/README.md",
    "content": "# accounts-oauth\n\nCommon functionality for OAuth-based login services. See the [project page](https://www.meteor.com/accounts) on Meteor Accounts for more details."
  },
  {
    "path": "packages/accounts-oauth/oauth_client.js",
    "content": "// Documentation for Meteor.loginWithExternalService\n\n/**\n * @name loginWith<ExternalService>\n * @memberOf Meteor\n * @function\n * @summary Log the user in using an external service.\n * @locus Client\n * @param {Object} [options]\n * @param {String[]} options.requestPermissions A list of permissions to request from the user.\n * @param {Boolean} options.requestOfflineToken If true, asks the user for permission to act on their behalf when offline. This stores an additional offline token in the `services` field of the user document. Currently only supported with Google.\n * @param {Object} options.loginUrlParameters Provide additional parameters to the authentication uri. Currently only supported with Google {@url https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters}.\n * @param {String} options.loginHint An email address that the external service will use to pre-fill the login prompt. Currently only supported with Meteor developer accounts and Google accounts. If used with Google, the Google User ID can also be passed.\n * @param {String} options.loginStyle Login style (\"popup\" or \"redirect\", defaults to the login service configuration).  The \"popup\" style opens the login page in a separate popup window, which is generally preferred because the Meteor application doesn't need to be reloaded.  The \"redirect\" style redirects the Meteor application's window to the login page, and the login service provider redirects back to the Meteor application which is then reloaded.  The \"redirect\" style can be used in situations where a popup window can't be opened, such as in a mobile UIWebView.  The \"redirect\" style however relies on session storage which isn't available in Safari private mode, so the \"popup\" style will be forced if session storage can't be used.\n * @param {String} options.redirectUrl If using \"redirect\" login style, the user will be returned to this URL after authorisation has been completed.\n * @param {Function} [callback] Optional callback. Called with no arguments on success, or with a single `Error` argument on failure. The callback cannot be called if you are using the \"redirect\" `loginStyle`, because the app will have reloaded in the meantime; try using [client-side login hooks](#accounts_onlogin) instead.\n * @importFromPackage meteor\n */\n\n// Allow server to specify a specify subclass of errors. We should come\n// up with a more generic way to do this!\nvar convertError = function (err) {\n  if (err && err instanceof Meteor.Error &&\n      err.error === Accounts.LoginCancelledError.numericError)\n    return new Accounts.LoginCancelledError(err.reason);\n  else\n    return err;\n};\n\n\n// For the redirect login flow, the final step is that we're\n// redirected back to the application.  The credentialToken for this\n// login attempt is stored in the reload migration data, and the\n// credentialSecret for a successful login is stored in session\n// storage.\n\nMeteor.startup(function () {\n  var oauth = OAuth.getDataAfterRedirect();\n  if (! oauth)\n    return;\n\n  // We'll only have the credentialSecret if the login completed\n  // successfully.  However we still call the login method anyway to\n  // retrieve the error if the login was unsuccessful.\n\n  var methodName = 'login';\n  var methodArguments = [{oauth: _.pick(oauth, 'credentialToken', 'credentialSecret')}];\n\n  Accounts.callLoginMethod({\n    methodArguments: methodArguments,\n    userCallback: function (err) {\n      // The redirect login flow is complete.  Construct an\n      // `attemptInfo` object with the login result, and report back\n      // to the code which initiated the login attempt\n      // (e.g. accounts-ui, when that package is being used).\n      err = convertError(err);\n      Accounts._pageLoadLogin({\n        type: oauth.loginService,\n        allowed: !err,\n        error: err,\n        methodName: methodName,\n        methodArguments: methodArguments\n      });\n    }\n  });\n});\n\n\n// Send an OAuth login method to the server. If the user authorized\n// access in the popup this should log the user in, otherwise\n// nothing should happen.\nAccounts.oauth.tryLoginAfterPopupClosed = function(credentialToken, callback) {\n  var credentialSecret = OAuth._retrieveCredentialSecret(credentialToken) || null;\n  Accounts.callLoginMethod({\n    methodArguments: [{oauth: {\n      credentialToken: credentialToken,\n      credentialSecret: credentialSecret\n    }}],\n    userCallback: callback && function (err) {\n      callback(convertError(err));\n    }});\n};\n\nAccounts.oauth.credentialRequestCompleteHandler = function(callback) {\n  return function (credentialTokenOrError) {\n    if(credentialTokenOrError && credentialTokenOrError instanceof Error) {\n      callback && callback(credentialTokenOrError);\n    } else {\n      Accounts.oauth.tryLoginAfterPopupClosed(credentialTokenOrError, callback);\n    }\n  };\n};\n"
  },
  {
    "path": "packages/accounts-oauth/oauth_common.js",
    "content": "Accounts.oauth = {};\n\nvar services = {};\n\n// Helper for registering OAuth based accounts packages.\n// On the server, adds an index to the user collection.\nAccounts.oauth.registerService = function (name) {\n  if (_.has(services, name))\n    throw new Error(\"Duplicate service: \" + name);\n  services[name] = true;\n\n  if (Meteor.server) {\n    // Accounts.updateOrCreateUserFromExternalService does a lookup by this id,\n    // so this should be a unique index. You might want to add indexes for other\n    // fields returned by your service (eg services.github.login) but you can do\n    // that in your app.\n    Meteor.users._ensureIndex('services.' + name + '.id',\n                              {unique: 1, sparse: 1});\n  }\n};\n\n// Removes a previously registered service.\n// This will disable logging in with this service, and serviceNames() will not\n// contain it.\n// It's worth noting that already logged in users will remain logged in unless\n// you manually expire their sessions.\nAccounts.oauth.unregisterService = function (name) {\n  if (!_.has(services, name))\n    throw new Error(\"Service not found: \" + name);\n  delete services[name];\n};\n\nAccounts.oauth.serviceNames = function () {\n  return _.keys(services);\n};\n"
  },
  {
    "path": "packages/accounts-oauth/oauth_server.js",
    "content": "// Listen to calls to `login` with an oauth option set. This is where\n// users actually get logged in to meteor via oauth.\nAccounts.registerLoginHandler(function (options) {\n  if (!options.oauth)\n    return undefined; // don't handle\n\n  check(options.oauth, {\n    credentialToken: String,\n    // When an error occurs while retrieving the access token, we store\n    // the error in the pending credentials table, with a secret of\n    // null. The client can call the login method with a secret of null\n    // to retrieve the error.\n    credentialSecret: Match.OneOf(null, String)\n  });\n\n  var result = OAuth.retrieveCredential(options.oauth.credentialToken,\n                                        options.oauth.credentialSecret);\n\n  if (!result) {\n    // OAuth credentialToken is not recognized, which could be either\n    // because the popup was closed by the user before completion, or\n    // some sort of error where the oauth provider didn't talk to our\n    // server correctly and closed the popup somehow.\n    //\n    // We assume it was user canceled and report it as such, using a\n    // numeric code that the client recognizes (XXX this will get\n    // replaced by a symbolic error code at some point\n    // https://trello.com/c/kMkw800Z/53-official-ddp-specification). This\n    // will mask failures where things are misconfigured such that the\n    // server doesn't see the request but does close the window. This\n    // seems unlikely.\n    //\n    // XXX we want `type` to be the service name such as \"facebook\"\n    return { type: \"oauth\",\n             error: new Meteor.Error(\n               Accounts.LoginCancelledError.numericError,\n               \"No matching login attempt found\") };\n  }\n\n  if (result instanceof Error)\n    // We tried to login, but there was a fatal error. Report it back\n    // to the user.\n    throw result;\n  else {\n    if (!_.contains(Accounts.oauth.serviceNames(), result.serviceName)) {\n      // serviceName was not found in the registered services list.\n      // This could happen because the service never registered itself or\n      // unregisterService was called on it.\n      return { type: \"oauth\",\n               error: new Meteor.Error(\n                 Accounts.LoginCancelledError.numericError,\n                 \"No registered oauth service found for: \" + result.serviceName) };\n\n    }\n    return Accounts.updateOrCreateUserFromExternalService(result.serviceName, result.serviceData, result.options);\n  }\n});\n"
  },
  {
    "path": "packages/accounts-oauth/oauth_tests.js",
    "content": "// XXX Add a test to ensure that successful logins call Accounts.updateOrCreateUserFromExternalService\n// XXX Add a test to ensure that a missing or failed loginResult is handled correctly\n"
  },
  {
    "path": "packages/accounts-oauth/package.js",
    "content": "Package.describe({\n  summary: \"Common code for OAuth-based login services\",\n  version: \"1.1.13\"\n});\n\nPackage.onUse(function (api) {\n  api.use('underscore', ['client', 'server']);\n  api.use('random', ['client', 'server']);\n  api.use('check', ['client', 'server']);\n  api.use('webapp', 'server');\n  api.use('accounts-base', ['client', 'server']);\n  // Export Accounts (etc) to packages using this one.\n  api.imply('accounts-base', ['client', 'server']);\n  api.use('oauth');\n\n  api.addFiles('oauth_common.js');\n  api.addFiles('oauth_client.js', 'client');\n  api.addFiles('oauth_server.js', 'server');\n});\n\n\nPackage.onTest(function (api) {\n  api.addFiles(\"oauth_tests.js\", 'server');\n});\n"
  },
  {
    "path": "packages/accounts-password/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/accounts-password/README.md",
    "content": "# accounts-password\n\nA login service that enables secure password-based login. See the [project page](https://www.meteor.com/accounts) on Meteor Accounts for more details.\n"
  },
  {
    "path": "packages/accounts-password/email_templates.js",
    "content": "function greet(welcomeMsg) {\n  return function(user, url) {\n      var greeting = (user.profile && user.profile.name) ?\n            (\"Hello \" + user.profile.name + \",\") : \"Hello,\";\n      return `${greeting}\n\n${welcomeMsg}, simply click the link below.\n\n${url}\n\nThanks.\n`;\n  };\n}\n\n/**\n * @summary Options to customize emails sent from the Accounts system.\n * @locus Server\n * @importFromPackage accounts-base\n */\nAccounts.emailTemplates = {\n  from: \"Meteor Accounts <no-reply@meteor.com>\",\n  siteName: Meteor.absoluteUrl().replace(/^https?:\\/\\//, '').replace(/\\/$/, ''),\n\n  resetPassword: {\n    subject: function(user) {\n      return \"How to reset your password on \" + Accounts.emailTemplates.siteName;\n    },\n    text: function(user, url) {\n      var greeting = (user.profile && user.profile.name) ?\n            (\"Hello \" + user.profile.name + \",\") : \"Hello,\";\n      return `${greeting}\n\nTo reset your password, simply click the link below.\n\n${url}\n\nThanks.\n`;\n    }\n  },\n  verifyEmail: {\n    subject: function(user) {\n      return \"How to verify email address on \" + Accounts.emailTemplates.siteName;\n    },\n    text: greet(\"To verify your account email\")\n  },\n  enrollAccount: {\n    subject: function(user) {\n      return \"An account has been created for you on \" + Accounts.emailTemplates.siteName;\n    },\n    text: greet(\"To start using the service\")\n  }\n};\n"
  },
  {
    "path": "packages/accounts-password/email_tests.js",
    "content": "var resetPasswordToken;\nvar verifyEmailToken;\nvar enrollAccountToken;\n\nAccounts._isolateLoginTokenForTest();\n\nif (Meteor.isServer) {\n  Accounts.removeDefaultRateLimit();\n}\n\ntestAsyncMulti(\"accounts emails - reset password flow\", [\n  function (test, expect) {\n    this.randomSuffix = Random.id();\n    this.email = \"Ada-intercept@example.com\" + this.randomSuffix;\n    // Create the user with another email and add the tested for email later,\n    // so we can test whether forgotPassword respects the passed in email\n    Accounts.createUser({email: \"another@example.com\" + this.randomSuffix, password: 'foobar'},\n      expect((error) => {\n        test.equal(error, undefined);\n        Meteor.call(\"addEmailForTestAndVerify\", this.email);\n      }));\n  },\n  function (test, expect) {\n    Accounts.forgotPassword({email: this.email}, expect((error) => {\n      test.equal(error, undefined);\n    }));\n  },\n  function (test, expect) {\n    Accounts.connection.call(\n      \"getInterceptedEmails\", this.email, expect((error, result) => {\n        test.equal(error, undefined);\n        test.notEqual(result, undefined);\n        test.equal(result.length, 2); // the first is the email verification\n        var options = result[1];\n\n        var re = new RegExp(Meteor.absoluteUrl() + \"#/reset-password/(\\\\S*)\");\n        var match = options.text.match(re);\n        test.isTrue(match);\n        resetPasswordToken = match[1];\n        test.isTrue(options.html.match(re));\n\n        test.equal(options.from, 'test@meteor.com');\n        test.equal(options.headers['My-Custom-Header'], 'Cool');\n      }));\n  },\n  function (test, expect) {\n    Accounts.resetPassword(resetPasswordToken, \"newPassword\", expect((error) => {\n      test.isFalse(error);\n    }));\n  },\n  function (test, expect) {\n    Meteor.logout(expect((error) => {\n      test.equal(error, undefined);\n      test.equal(Meteor.user(), null);\n    }));\n  },\n  function (test, expect) {\n    Meteor.loginWithPassword(\n      {email: this.email}, \"newPassword\",\n      expect((error) => {\n        test.isFalse(error);\n      }));\n  },\n  function (test, expect) {\n    Meteor.logout(expect((error) => {\n      test.equal(error, undefined);\n      test.equal(Meteor.user(), null);\n    }));\n  }\n]);\n\ntestAsyncMulti(`accounts emails - \\\nreset password flow with case insensitive email`, [\n  function (test, expect) {\n    this.randomSuffix = Random.id();\n    this.email = \"Ada-intercept@example.com\" + this.randomSuffix;\n    // Create the user with another email and add the tested for email later,\n    // so we can test whether forgotPassword respects the passed in email\n    Accounts.createUser({email: \"another@example.com\" + this.randomSuffix, password: 'foobar'},\n      expect((error) => {\n        test.equal(error, undefined);\n        Meteor.call(\"addEmailForTestAndVerify\", this.email);\n      }));\n  },\n  function (test, expect) {\n    Accounts.forgotPassword({email: \"ada-intercept@example.com\" + this.randomSuffix}, expect((error) => {\n      test.equal(error, undefined);\n    }));\n  },\n  function (test, expect) {\n    Accounts.connection.call(\n      \"getInterceptedEmails\", this.email, expect((error, result) => {\n        test.equal(error, undefined);\n        test.notEqual(result, undefined);\n        test.equal(result.length, 2); // the first is the email verification\n        var options = result[1];\n\n        var re = new RegExp(Meteor.absoluteUrl() + \"#/reset-password/(\\\\S*)\");\n        var match = options.text.match(re);\n        test.isTrue(match);\n        resetPasswordToken = match[1];\n        test.isTrue(options.html.match(re));\n\n        test.equal(options.from, 'test@meteor.com');\n        test.equal(options.headers['My-Custom-Header'], 'Cool');\n      }));\n  },\n  function (test, expect) {\n    Accounts.resetPassword(resetPasswordToken, \"newPassword\", expect((error) => {\n      test.isFalse(error);\n    }));\n  },\n  function (test, expect) {\n    Meteor.logout(expect((error) => {\n      test.equal(error, undefined);\n      test.equal(Meteor.user(), null);\n    }));\n  },\n  function (test, expect) {\n    Meteor.loginWithPassword(\n      {email: this.email}, \"newPassword\",\n      expect((error) => {\n        test.isFalse(error);\n      }));\n  },\n  function (test, expect) {\n    Meteor.logout(expect((error) => {\n      test.equal(error, undefined);\n      test.equal(Meteor.user(), null);\n    }));\n  }\n]);\n\nvar getVerifyEmailToken = function (email, test, expect) {\n  Accounts.connection.call(\n    \"getInterceptedEmails\", email, expect((error, result) => {\n      test.equal(error, undefined);\n      test.notEqual(result, undefined);\n      test.equal(result.length, 1);\n      var options = result[0];\n\n      var re = new RegExp(Meteor.absoluteUrl() + \"#/verify-email/(\\\\S*)\");\n      var match = options.text.match(re);\n      test.isTrue(match);\n      verifyEmailToken = match[1];\n      test.isTrue(options.html.match(re));\n\n      test.equal(options.from, 'test@meteor.com');\n      test.equal(options.headers['My-Custom-Header'], 'Cool');\n    }));\n};\n\nvar loggedIn = function (test, expect) {\n  return expect((error) => {\n    test.equal(error, undefined);\n    test.isTrue(Meteor.user());\n  });\n};\n\ntestAsyncMulti(\"accounts emails - verify email flow\", [\n  function (test, expect) {\n    this.email = Random.id() + \"-intercept@example.com\";\n    this.anotherEmail = Random.id() + \"-intercept@example.com\";\n    Accounts.createUser(\n      {email: this.email, password: 'foobar'},\n      loggedIn(test, expect));\n  },\n  function (test, expect) {\n    test.equal(Meteor.user().emails.length, 1);\n    test.equal(Meteor.user().emails[0].address, this.email);\n    test.isFalse(Meteor.user().emails[0].verified);\n    // We should NOT be publishing things like verification tokens!\n    test.isFalse(_.has(Meteor.user(), 'services'));\n  },\n  function (test, expect) {\n    getVerifyEmailToken(this.email, test, expect);\n  },\n  function (test, expect) {\n    // Log out, to test that verifyEmail logs us back in.\n    Meteor.logout(expect((error) => {\n      test.equal(error, undefined);\n      test.equal(Meteor.user(), null);\n    }));\n  },\n  function (test, expect) {\n    Accounts.verifyEmail(verifyEmailToken,\n                         loggedIn(test, expect));\n  },\n  function (test, expect) {\n    test.equal(Meteor.user().emails.length, 1);\n    test.equal(Meteor.user().emails[0].address, this.email);\n    test.isTrue(Meteor.user().emails[0].verified);\n  },\n  function (test, expect) {\n    Accounts.connection.call(\n      \"addEmailForTestAndVerify\", this.anotherEmail,\n      expect((error, result) => {\n        test.isFalse(error);\n        test.equal(Meteor.user().emails.length, 2);\n        test.equal(Meteor.user().emails[1].address, this.anotherEmail);\n        test.isFalse(Meteor.user().emails[1].verified);\n      }));\n  },\n  function (test, expect) {\n    getVerifyEmailToken(this.anotherEmail, test, expect);\n  },\n  function (test, expect) {\n    // Log out, to test that verifyEmail logs us back in. (And if we don't\n    // do that, waitUntilLoggedIn won't be able to prevent race conditions.)\n    Meteor.logout(expect((error) => {\n      test.equal(error, undefined);\n      test.equal(Meteor.user(), null);\n    }));\n  },\n  function (test, expect) {\n    Accounts.verifyEmail(verifyEmailToken,\n                         loggedIn(test, expect));\n  },\n  function (test, expect) {\n    test.equal(Meteor.user().emails[1].address, this.anotherEmail);\n    test.isTrue(Meteor.user().emails[1].verified);\n  },\n  function (test, expect) {\n    Meteor.logout(expect((error) => {\n      test.equal(error, undefined);\n      test.equal(Meteor.user(), null);\n    }));\n  }\n]);\n\nvar getEnrollAccountToken = function (email, test, expect) {\n  Accounts.connection.call(\n    \"getInterceptedEmails\", email, expect((error, result) => {\n      test.equal(error, undefined);\n      test.notEqual(result, undefined);\n      test.equal(result.length, 1);\n      var options = result[0];\n\n      var re = new RegExp(Meteor.absoluteUrl() + \"#/enroll-account/(\\\\S*)\")\n      var match = options.text.match(re);\n      test.isTrue(match);\n      enrollAccountToken = match[1];\n      test.isTrue(options.html.match(re));\n\n      test.equal(options.from, 'test@meteor.com');\n      test.equal(options.headers['My-Custom-Header'], 'Cool');\n    }));\n};\n\ntestAsyncMulti(\"accounts emails - enroll account flow\", [\n  function (test, expect) {\n    this.email = Random.id() + \"-intercept@example.com\";\n    Accounts.connection.call(\"createUserOnServer\", this.email,\n      expect((error, result) => {\n        test.isFalse(error);\n        var user = result;\n        test.equal(user.emails.length, 1);\n        test.equal(user.emails[0].address, this.email);\n        test.isFalse(user.emails[0].verified);\n      }));\n  },\n  function (test, expect) {\n    getEnrollAccountToken(this.email, test, expect);\n  },\n  function (test, expect) {\n    Accounts.resetPassword(enrollAccountToken, 'password',\n                           loggedIn(test, expect));\n  },\n  function (test, expect) {\n    test.equal(Meteor.user().emails.length, 1);\n    test.equal(Meteor.user().emails[0].address, this.email);\n    test.isTrue(Meteor.user().emails[0].verified);\n  },\n  function (test, expect) {\n    Meteor.logout(expect((error) => {\n      test.equal(error, undefined);\n      test.equal(Meteor.user(), null);\n    }));\n  },\n  function (test, expect) {\n    Meteor.loginWithPassword({email: this.email}, 'password',\n                             loggedIn(test ,expect));\n  },\n  function (test, expect) {\n    test.equal(Meteor.user().emails.length, 1);\n    test.equal(Meteor.user().emails[0].address, this.email);\n    test.isTrue(Meteor.user().emails[0].verified);\n  },\n  function (test, expect) {\n    Meteor.logout(expect((error) => {\n      test.equal(error, undefined);\n      test.equal(Meteor.user(), null);\n    }));\n  }\n]);\n"
  },
  {
    "path": "packages/accounts-password/email_tests_setup.js",
    "content": "//\n// a mechanism to intercept emails sent to addressing including\n// the string \"intercept\", storing them in an array that can then\n// be retrieved using the getInterceptedEmails method\n//\nvar interceptedEmails = {}; // (email address) -> (array of options)\n\n// add html email templates that just contain the url\nAccounts.emailTemplates.resetPassword.html =\n  Accounts.emailTemplates.enrollAccount.html =\n  Accounts.emailTemplates.verifyEmail.html = function (user, url) {\n    return url;\n  };\n\n// override the from address\nAccounts.emailTemplates.resetPassword.from =\n  Accounts.emailTemplates.enrollAccount.from =\n    Accounts.emailTemplates.verifyEmail.from = function (user) {\n      return 'test@meteor.com';\n    };\n\n// add a custom header to check against\nAccounts.emailTemplates.headers = {\n  'My-Custom-Header' : 'Cool'\n};\n\nEmailTest.hookSend(function (options) {\n  var to = options.to;\n  if (!to || to.indexOf('intercept') === -1) {\n    return true; // go ahead and send\n  } else {\n    if (!interceptedEmails[to])\n      interceptedEmails[to] = [];\n\n    interceptedEmails[to].push(options);\n    return false; // skip sending\n  }\n});\n\nMeteor.methods({\n  getInterceptedEmails: function (email) {\n    check(email, String);\n    return interceptedEmails[email];\n  },\n\n  addEmailForTestAndVerify: function (email) {\n    check(email, String);\n    Meteor.users.update(\n      {_id: this.userId},\n      {$push: {emails: {address: email, verified: false}}});\n    Accounts.sendVerificationEmail(this.userId, email);\n  },\n\n  createUserOnServer: function (email) {\n    check(email, String);\n    var userId = Accounts.createUser({email: email});\n    Accounts.sendEnrollmentEmail(userId);\n    return Meteor.users.findOne(userId);\n  }\n});\n"
  },
  {
    "path": "packages/accounts-password/package.js",
    "content": "Package.describe({\n  summary: \"Password support for accounts\",\n  version: \"1.1.11\"\n});\n\nPackage.onUse(function(api) {\n  api.use('npm-bcrypt@0.8.6_1');\n\n  api.use([\n    'accounts-base',\n    'srp',\n    'sha',\n    'ejson',\n    'ddp'\n  ], ['client', 'server']);\n\n  // Export Accounts (etc) to packages using this one.\n  api.imply('accounts-base', ['client', 'server']);\n\n  api.use('email', ['server']);\n  api.use('random', ['server']);\n  api.use('check');\n  api.use('underscore');\n  api.use('ecmascript');\n\n  api.addFiles('email_templates.js', 'server');\n  api.addFiles('password_server.js', 'server');\n  api.addFiles('password_client.js', 'client');\n});\n\nPackage.onTest(function(api) {\n  api.use(['accounts-password', 'tinytest', 'test-helpers', 'tracker',\n           'accounts-base', 'random', 'email', 'underscore', 'check',\n           'ddp', 'ecmascript']);\n  api.addFiles('password_tests_setup.js', 'server');\n  api.addFiles('password_tests.js', ['client', 'server']);\n  api.addFiles('email_tests_setup.js', 'server');\n  api.addFiles('email_tests.js', 'client');\n});\n"
  },
  {
    "path": "packages/accounts-password/password_client.js",
    "content": "// Attempt to log in with a password.\n//\n// @param selector {String|Object} One of the following:\n//   - {username: (username)}\n//   - {email: (email)}\n//   - a string which may be a username or email, depending on whether\n//     it contains \"@\".\n// @param password {String}\n// @param callback {Function(error|undefined)}\n\n/**\n * @summary Log the user in with a password.\n * @locus Client\n * @param {Object | String} user\n *   Either a string interpreted as a username or an email; or an object with a\n *   single key: `email`, `username` or `id`. Username or email match in a case\n *   insensitive manner.\n * @param {String} password The user's password.\n * @param {Function} [callback] Optional callback.\n *   Called with no arguments on success, or with a single `Error` argument\n *   on failure.\n * @importFromPackage meteor\n */\nMeteor.loginWithPassword = function (selector, password, callback) {\n  if (typeof selector === 'string')\n    if (selector.indexOf('@') === -1)\n      selector = {username: selector};\n    else\n      selector = {email: selector};\n\n  Accounts.callLoginMethod({\n    methodArguments: [{\n      user: selector,\n      password: Accounts._hashPassword(password)\n    }],\n    userCallback: function (error, result) {\n      if (error && error.error === 400 &&\n          error.reason === 'old password format') {\n        // The \"reason\" string should match the error thrown in the\n        // password login handler in password_server.js.\n\n        // XXX COMPAT WITH 0.8.1.3\n        // If this user's last login was with a previous version of\n        // Meteor that used SRP, then the server throws this error to\n        // indicate that we should try again. The error includes the\n        // user's SRP identity. We provide a value derived from the\n        // identity and the password to prove to the server that we know\n        // the password without requiring a full SRP flow, as well as\n        // SHA256(password), which the server bcrypts and stores in\n        // place of the old SRP information for this user.\n        srpUpgradePath({\n          upgradeError: error,\n          userSelector: selector,\n          plaintextPassword: password\n        }, callback);\n      }\n      else if (error) {\n        callback && callback(error);\n      } else {\n        callback && callback();\n      }\n    }\n  });\n};\n\nAccounts._hashPassword = function (password) {\n  return {\n    digest: SHA256(password),\n    algorithm: \"sha-256\"\n  };\n};\n\n// XXX COMPAT WITH 0.8.1.3\n// The server requested an upgrade from the old SRP password format,\n// so supply the needed SRP identity to login. Options:\n//   - upgradeError: the error object that the server returned to tell\n//     us to upgrade from SRP to bcrypt.\n//   - userSelector: selector to retrieve the user object\n//   - plaintextPassword: the password as a string\nvar srpUpgradePath = function (options, callback) {\n  var details;\n  try {\n    details = EJSON.parse(options.upgradeError.details);\n  } catch (e) {}\n  if (!(details && details.format === 'srp')) {\n    callback && callback(\n      new Meteor.Error(400, \"Password is old. Please reset your \" +\n                       \"password.\"));\n  } else {\n    Accounts.callLoginMethod({\n      methodArguments: [{\n        user: options.userSelector,\n        srp: SHA256(details.identity + \":\" + options.plaintextPassword),\n        password: Accounts._hashPassword(options.plaintextPassword)\n      }],\n      userCallback: callback\n    });\n  }\n};\n\n\n// Attempt to log in as a new user.\n\n/**\n * @summary Create a new user.\n * @locus Anywhere\n * @param {Object} options\n * @param {String} options.username A unique name for this user.\n * @param {String} options.email The user's email address.\n * @param {String} options.password The user's password. This is __not__ sent in plain text over the wire.\n * @param {Object} options.profile The user's profile, typically including the `name` field.\n * @param {Function} [callback] Client only, optional callback. Called with no arguments on success, or with a single `Error` argument on failure.\n * @importFromPackage accounts-base\n */\nAccounts.createUser = function (options, callback) {\n  options = _.clone(options); // we'll be modifying options\n\n  if (typeof options.password !== 'string')\n    throw new Error(\"options.password must be a string\");\n  if (!options.password) {\n    callback(new Meteor.Error(400, \"Password may not be empty\"));\n    return;\n  }\n\n  // Replace password with the hashed password.\n  options.password = Accounts._hashPassword(options.password);\n\n  Accounts.callLoginMethod({\n    methodName: 'createUser',\n    methodArguments: [options],\n    userCallback: callback\n  });\n};\n\n// Change password. Must be logged in.\n//\n// @param oldPassword {String|null} By default servers no longer allow\n//   changing password without the old password, but they could so we\n//   support passing no password to the server and letting it decide.\n// @param newPassword {String}\n// @param callback {Function(error|undefined)}\n\n/**\n * @summary Change the current user's password. Must be logged in.\n * @locus Client\n * @param {String} oldPassword The user's current password. This is __not__ sent in plain text over the wire.\n * @param {String} newPassword A new password for the user. This is __not__ sent in plain text over the wire.\n * @param {Function} [callback] Optional callback. Called with no arguments on success, or with a single `Error` argument on failure.\n * @importFromPackage accounts-base\n */\nAccounts.changePassword = function (oldPassword, newPassword, callback) {\n  if (!Meteor.user()) {\n    callback && callback(new Error(\"Must be logged in to change password.\"));\n    return;\n  }\n\n  check(newPassword, String);\n  if (!newPassword) {\n    callback(new Meteor.Error(400, \"Password may not be empty\"));\n    return;\n  }\n\n  Accounts.connection.apply(\n    'changePassword',\n    [oldPassword ? Accounts._hashPassword(oldPassword) : null,\n     Accounts._hashPassword(newPassword)],\n    function (error, result) {\n      if (error || !result) {\n        if (error && error.error === 400 &&\n            error.reason === 'old password format') {\n          // XXX COMPAT WITH 0.8.1.3\n          // The server is telling us to upgrade from SRP to bcrypt, as\n          // in Meteor.loginWithPassword.\n          srpUpgradePath({\n            upgradeError: error,\n            userSelector: { id: Meteor.userId() },\n            plaintextPassword: oldPassword\n          }, function (err) {\n            if (err) {\n              callback && callback(err);\n            } else {\n              // Now that we've successfully migrated from srp to\n              // bcrypt, try changing the password again.\n              Accounts.changePassword(oldPassword, newPassword, callback);\n            }\n          });\n        } else {\n          // A normal error, not an error telling us to upgrade to bcrypt\n          callback && callback(\n            error || new Error(\"No result from changePassword.\"));\n        }\n      } else {\n        callback && callback();\n      }\n    }\n  );\n};\n\n// Sends an email to a user with a link that can be used to reset\n// their password\n//\n// @param options {Object}\n//   - email: (email)\n// @param callback (optional) {Function(error|undefined)}\n\n/**\n * @summary Request a forgot password email.\n * @locus Client\n * @param {Object} options\n * @param {String} options.email The email address to send a password reset link.\n * @param {Function} [callback] Optional callback. Called with no arguments on success, or with a single `Error` argument on failure.\n * @importFromPackage accounts-base\n */\nAccounts.forgotPassword = function(options, callback) {\n  if (!options.email)\n    throw new Error(\"Must pass options.email\");\n  Accounts.connection.call(\"forgotPassword\", options, callback);\n};\n\n// Resets a password based on a token originally created by\n// Accounts.forgotPassword, and then logs in the matching user.\n//\n// @param token {String}\n// @param newPassword {String}\n// @param callback (optional) {Function(error|undefined)}\n\n/**\n * @summary Reset the password for a user using a token received in email. Logs the user in afterwards.\n * @locus Client\n * @param {String} token The token retrieved from the reset password URL.\n * @param {String} newPassword A new password for the user. This is __not__ sent in plain text over the wire.\n * @param {Function} [callback] Optional callback. Called with no arguments on success, or with a single `Error` argument on failure.\n * @importFromPackage accounts-base\n */\nAccounts.resetPassword = function(token, newPassword, callback) {\n  check(token, String);\n  check(newPassword, String);\n\n  if (!newPassword) {\n    callback(new Meteor.Error(400, \"Password may not be empty\"));\n    return;\n  }\n\n  Accounts.callLoginMethod({\n    methodName: 'resetPassword',\n    methodArguments: [token, Accounts._hashPassword(newPassword)],\n    userCallback: callback});\n};\n\n// Verifies a user's email address based on a token originally\n// created by Accounts.sendVerificationEmail\n//\n// @param token {String}\n// @param callback (optional) {Function(error|undefined)}\n\n/**\n * @summary Marks the user's email address as verified. Logs the user in afterwards.\n * @locus Client\n * @param {String} token The token retrieved from the verification URL.\n * @param {Function} [callback] Optional callback. Called with no arguments on success, or with a single `Error` argument on failure.\n * @importFromPackage accounts-base\n */\nAccounts.verifyEmail = function(token, callback) {\n  if (!token)\n    throw new Error(\"Need to pass token\");\n\n  Accounts.callLoginMethod({\n    methodName: 'verifyEmail',\n    methodArguments: [token],\n    userCallback: callback});\n};\n"
  },
  {
    "path": "packages/accounts-password/password_server.js",
    "content": "/// BCRYPT\n\nvar bcrypt = NpmModuleBcrypt;\nvar bcryptHash = Meteor.wrapAsync(bcrypt.hash);\nvar bcryptCompare = Meteor.wrapAsync(bcrypt.compare);\n\n// User records have a 'services.password.bcrypt' field on them to hold\n// their hashed passwords (unless they have a 'services.password.srp'\n// field, in which case they will be upgraded to bcrypt the next time\n// they log in).\n//\n// When the client sends a password to the server, it can either be a\n// string (the plaintext password) or an object with keys 'digest' and\n// 'algorithm' (must be \"sha-256\" for now). The Meteor client always sends\n// password objects { digest: *, algorithm: \"sha-256\" }, but DDP clients\n// that don't have access to SHA can just send plaintext passwords as\n// strings.\n//\n// When the server receives a plaintext password as a string, it always\n// hashes it with SHA256 before passing it into bcrypt. When the server\n// receives a password as an object, it asserts that the algorithm is\n// \"sha-256\" and then passes the digest to bcrypt.\n\n\nAccounts._bcryptRounds = 10;\n\n// Given a 'password' from the client, extract the string that we should\n// bcrypt. 'password' can be one of:\n//  - String (the plaintext password)\n//  - Object with 'digest' and 'algorithm' keys. 'algorithm' must be \"sha-256\".\n//\nvar getPasswordString = function (password) {\n  if (typeof password === \"string\") {\n    password = SHA256(password);\n  } else { // 'password' is an object\n    if (password.algorithm !== \"sha-256\") {\n      throw new Error(\"Invalid password hash algorithm. \" +\n                      \"Only 'sha-256' is allowed.\");\n    }\n    password = password.digest;\n  }\n  return password;\n};\n\n// Use bcrypt to hash the password for storage in the database.\n// `password` can be a string (in which case it will be run through\n// SHA256 before bcrypt) or an object with properties `digest` and\n// `algorithm` (in which case we bcrypt `password.digest`).\n//\nvar hashPassword = function (password) {\n  password = getPasswordString(password);\n  return bcryptHash(password, Accounts._bcryptRounds);\n};\n\n// Check whether the provided password matches the bcrypt'ed password in\n// the database user record. `password` can be a string (in which case\n// it will be run through SHA256 before bcrypt) or an object with\n// properties `digest` and `algorithm` (in which case we bcrypt\n// `password.digest`).\n//\nAccounts._checkPassword = function (user, password) {\n  var result = {\n    userId: user._id\n  };\n\n  password = getPasswordString(password);\n\n  if (! bcryptCompare(password, user.services.password.bcrypt)) {\n    result.error = new Meteor.Error(403, \"Incorrect password\");\n  }\n\n  return result;\n};\nvar checkPassword = Accounts._checkPassword;\n\n///\n/// LOGIN\n///\n\nAccounts._findUserByQuery = function (query) {\n  var user = null;\n\n  if (query.id) {\n    user = Meteor.users.findOne({ _id: query.id });\n  } else {\n    var fieldName;\n    var fieldValue;\n    if (query.username) {\n      fieldName = 'username';\n      fieldValue = query.username;\n    } else if (query.email) {\n      fieldName = 'emails.address';\n      fieldValue = query.email;\n    } else {\n      throw new Error(\"shouldn't happen (validation missed something)\");\n    }\n    var selector = {};\n    selector[fieldName] = fieldValue;\n    user = Meteor.users.findOne(selector);\n    // If user is not found, try a case insensitive lookup\n    if (!user) {\n      selector = selectorForFastCaseInsensitiveLookup(fieldName, fieldValue);\n      var candidateUsers = Meteor.users.find(selector).fetch();\n      // No match if multiple candidates are found\n      if (candidateUsers.length === 1) {\n        user = candidateUsers[0];\n      }\n    }\n  }\n\n  return user;\n};\n\n/**\n * @summary Finds the user with the specified username.\n * First tries to match username case sensitively; if that fails, it\n * tries case insensitively; but if more than one user matches the case\n * insensitive search, it returns null.\n * @locus Server\n * @param {String} username The username to look for\n * @returns {Object} A user if found, else null\n * @importFromPackage accounts-base\n */\nAccounts.findUserByUsername = function (username) {\n  return Accounts._findUserByQuery({\n    username: username\n  });\n};\n\n/**\n * @summary Finds the user with the specified email.\n * First tries to match email case sensitively; if that fails, it\n * tries case insensitively; but if more than one user matches the case\n * insensitive search, it returns null.\n * @locus Server\n * @param {String} email The email address to look for\n * @returns {Object} A user if found, else null\n * @importFromPackage accounts-base\n */\nAccounts.findUserByEmail = function (email) {\n  return Accounts._findUserByQuery({\n    email: email\n  });\n};\n\n// Generates a MongoDB selector that can be used to perform a fast case\n// insensitive lookup for the given fieldName and string. Since MongoDB does\n// not support case insensitive indexes, and case insensitive regex queries\n// are slow, we construct a set of prefix selectors for all permutations of\n// the first 4 characters ourselves. We first attempt to matching against\n// these, and because 'prefix expression' regex queries do use indexes (see\n// http://docs.mongodb.org/v2.6/reference/operator/query/regex/#index-use),\n// this has been found to greatly improve performance (from 1200ms to 5ms in a\n// test with 1.000.000 users).\nvar selectorForFastCaseInsensitiveLookup = function (fieldName, string) {\n  // Performance seems to improve up to 4 prefix characters\n  var prefix = string.substring(0, Math.min(string.length, 4));\n  var orClause = _.map(generateCasePermutationsForString(prefix),\n    function (prefixPermutation) {\n      var selector = {};\n      selector[fieldName] =\n        new RegExp('^' + Meteor._escapeRegExp(prefixPermutation));\n      return selector;\n    });\n  var caseInsensitiveClause = {};\n  caseInsensitiveClause[fieldName] =\n    new RegExp('^' + Meteor._escapeRegExp(string) + '$', 'i')\n  return {$and: [{$or: orClause}, caseInsensitiveClause]};\n}\n\n// Generates permutations of all case variations of a given string.\nvar generateCasePermutationsForString = function (string) {\n  var permutations = [''];\n  for (var i = 0; i < string.length; i++) {\n    var ch = string.charAt(i);\n    permutations = _.flatten(_.map(permutations, function (prefix) {\n      var lowerCaseChar = ch.toLowerCase();\n      var upperCaseChar = ch.toUpperCase();\n      // Don't add unneccesary permutations when ch is not a letter\n      if (lowerCaseChar === upperCaseChar) {\n        return [prefix + ch];\n      } else {\n        return [prefix + lowerCaseChar, prefix + upperCaseChar];\n      }\n    }));\n  }\n  return permutations;\n}\n\nvar checkForCaseInsensitiveDuplicates = function (fieldName, displayName, fieldValue, ownUserId) {\n  // Some tests need the ability to add users with the same case insensitive\n  // value, hence the _skipCaseInsensitiveChecksForTest check\n  var skipCheck = _.has(Accounts._skipCaseInsensitiveChecksForTest, fieldValue);\n\n  if (fieldValue && !skipCheck) {\n    var matchedUsers = Meteor.users.find(\n      selectorForFastCaseInsensitiveLookup(fieldName, fieldValue)).fetch();\n\n    if (matchedUsers.length > 0 &&\n        // If we don't have a userId yet, any match we find is a duplicate\n        (!ownUserId ||\n        // Otherwise, check to see if there are multiple matches or a match\n        // that is not us\n        (matchedUsers.length > 1 || matchedUsers[0]._id !== ownUserId))) {\n      throw new Meteor.Error(403, displayName + \" already exists.\");\n    }\n  }\n};\n\n// XXX maybe this belongs in the check package\nvar NonEmptyString = Match.Where(function (x) {\n  check(x, String);\n  return x.length > 0;\n});\n\nvar userQueryValidator = Match.Where(function (user) {\n  check(user, {\n    id: Match.Optional(NonEmptyString),\n    username: Match.Optional(NonEmptyString),\n    email: Match.Optional(NonEmptyString)\n  });\n  if (_.keys(user).length !== 1)\n    throw new Match.Error(\"User property must have exactly one field\");\n  return true;\n});\n\nvar passwordValidator = Match.OneOf(\n  String,\n  { digest: String, algorithm: String }\n);\n\n// Handler to login with a password.\n//\n// The Meteor client sets options.password to an object with keys\n// 'digest' (set to SHA256(password)) and 'algorithm' (\"sha-256\").\n//\n// For other DDP clients which don't have access to SHA, the handler\n// also accepts the plaintext password in options.password as a string.\n//\n// (It might be nice if servers could turn the plaintext password\n// option off. Or maybe it should be opt-in, not opt-out?\n// Accounts.config option?)\n//\n// Note that neither password option is secure without SSL.\n//\nAccounts.registerLoginHandler(\"password\", function (options) {\n  if (! options.password || options.srp)\n    return undefined; // don't handle\n\n  check(options, {\n    user: userQueryValidator,\n    password: passwordValidator\n  });\n\n\n  var user = Accounts._findUserByQuery(options.user);\n  if (!user)\n    throw new Meteor.Error(403, \"User not found\");\n\n  if (!user.services || !user.services.password ||\n      !(user.services.password.bcrypt || user.services.password.srp))\n    throw new Meteor.Error(403, \"User has no password set\");\n\n  if (!user.services.password.bcrypt) {\n    if (typeof options.password === \"string\") {\n      // The client has presented a plaintext password, and the user is\n      // not upgraded to bcrypt yet. We don't attempt to tell the client\n      // to upgrade to bcrypt, because it might be a standalone DDP\n      // client doesn't know how to do such a thing.\n      var verifier = user.services.password.srp;\n      var newVerifier = SRP.generateVerifier(options.password, {\n        identity: verifier.identity, salt: verifier.salt});\n\n      if (verifier.verifier !== newVerifier.verifier) {\n        return {\n          userId: user._id,\n          error: new Meteor.Error(403, \"Incorrect password\")\n        };\n      }\n\n      return {userId: user._id};\n    } else {\n      // Tell the client to use the SRP upgrade process.\n      throw new Meteor.Error(400, \"old password format\", EJSON.stringify({\n        format: 'srp',\n        identity: user.services.password.srp.identity\n      }));\n    }\n  }\n\n  return checkPassword(\n    user,\n    options.password\n  );\n});\n\n// Handler to login using the SRP upgrade path. To use this login\n// handler, the client must provide:\n//   - srp: H(identity + \":\" + password)\n//   - password: a string or an object with properties 'digest' and 'algorithm'\n//\n// We use `options.srp` to verify that the client knows the correct\n// password without doing a full SRP flow. Once we've checked that, we\n// upgrade the user to bcrypt and remove the SRP information from the\n// user document.\n//\n// The client ends up using this login handler after trying the normal\n// login handler (above), which throws an error telling the client to\n// try the SRP upgrade path.\n//\n// XXX COMPAT WITH 0.8.1.3\nAccounts.registerLoginHandler(\"password\", function (options) {\n  if (!options.srp || !options.password)\n    return undefined; // don't handle\n\n  check(options, {\n    user: userQueryValidator,\n    srp: String,\n    password: passwordValidator\n  });\n\n  var user = Accounts._findUserByQuery(options.user);\n  if (!user)\n    throw new Meteor.Error(403, \"User not found\");\n\n  // Check to see if another simultaneous login has already upgraded\n  // the user record to bcrypt.\n  if (user.services && user.services.password && user.services.password.bcrypt)\n    return checkPassword(user, options.password);\n\n  if (!(user.services && user.services.password && user.services.password.srp))\n    throw new Meteor.Error(403, \"User has no password set\");\n\n  var v1 = user.services.password.srp.verifier;\n  var v2 = SRP.generateVerifier(\n    null,\n    {\n      hashedIdentityAndPassword: options.srp,\n      salt: user.services.password.srp.salt\n    }\n  ).verifier;\n  if (v1 !== v2)\n    return {\n      userId: user._id,\n      error: new Meteor.Error(403, \"Incorrect password\")\n    };\n\n  // Upgrade to bcrypt on successful login.\n  var salted = hashPassword(options.password);\n  Meteor.users.update(\n    user._id,\n    {\n      $unset: { 'services.password.srp': 1 },\n      $set: { 'services.password.bcrypt': salted }\n    }\n  );\n\n  return {userId: user._id};\n});\n\n\n///\n/// CHANGING\n///\n\n/**\n * @summary Change a user's username. Use this instead of updating the\n * database directly. The operation will fail if there is an existing user\n * with a username only differing in case.\n * @locus Server\n * @param {String} userId The ID of the user to update.\n * @param {String} newUsername A new username for the user.\n * @importFromPackage accounts-base\n */\nAccounts.setUsername = function (userId, newUsername) {\n  check(userId, NonEmptyString);\n  check(newUsername, NonEmptyString);\n\n  var user = Meteor.users.findOne(userId);\n  if (!user)\n    throw new Meteor.Error(403, \"User not found\");\n\n  var oldUsername = user.username;\n\n  // Perform a case insensitive check for duplicates before update\n  checkForCaseInsensitiveDuplicates('username', 'Username', newUsername, user._id);\n\n  Meteor.users.update({_id: user._id}, {$set: {username: newUsername}});\n\n  // Perform another check after update, in case a matching user has been\n  // inserted in the meantime\n  try {\n    checkForCaseInsensitiveDuplicates('username', 'Username', newUsername, user._id);\n  } catch (ex) {\n    // Undo update if the check fails\n    Meteor.users.update({_id: user._id}, {$set: {username: oldUsername}});\n    throw ex;\n  }\n};\n\n// Let the user change their own password if they know the old\n// password. `oldPassword` and `newPassword` should be objects with keys\n// `digest` and `algorithm` (representing the SHA256 of the password).\n//\n// XXX COMPAT WITH 0.8.1.3\n// Like the login method, if the user hasn't been upgraded from SRP to\n// bcrypt yet, then this method will throw an 'old password format'\n// error. The client should call the SRP upgrade login handler and then\n// retry this method again.\n//\n// UNLIKE the login method, there is no way to avoid getting SRP upgrade\n// errors thrown. The reasoning for this is that clients using this\n// method directly will need to be updated anyway because we no longer\n// support the SRP flow that they would have been doing to use this\n// method previously.\nMeteor.methods({changePassword: function (oldPassword, newPassword) {\n  check(oldPassword, passwordValidator);\n  check(newPassword, passwordValidator);\n\n  if (!this.userId)\n    throw new Meteor.Error(401, \"Must be logged in\");\n\n  var user = Meteor.users.findOne(this.userId);\n  if (!user)\n    throw new Meteor.Error(403, \"User not found\");\n\n  if (!user.services || !user.services.password ||\n      (!user.services.password.bcrypt && !user.services.password.srp))\n    throw new Meteor.Error(403, \"User has no password set\");\n\n  if (! user.services.password.bcrypt) {\n    throw new Meteor.Error(400, \"old password format\", EJSON.stringify({\n      format: 'srp',\n      identity: user.services.password.srp.identity\n    }));\n  }\n\n  var result = checkPassword(user, oldPassword);\n  if (result.error)\n    throw result.error;\n\n  var hashed = hashPassword(newPassword);\n\n  // It would be better if this removed ALL existing tokens and replaced\n  // the token for the current connection with a new one, but that would\n  // be tricky, so we'll settle for just replacing all tokens other than\n  // the one for the current connection.\n  var currentToken = Accounts._getLoginToken(this.connection.id);\n  Meteor.users.update(\n    { _id: this.userId },\n    {\n      $set: { 'services.password.bcrypt': hashed },\n      $pull: {\n        'services.resume.loginTokens': { hashedToken: { $ne: currentToken } }\n      },\n      $unset: { 'services.password.reset': 1 }\n    }\n  );\n\n  return {passwordChanged: true};\n}});\n\n\n// Force change the users password.\n\n/**\n * @summary Forcibly change the password for a user.\n * @locus Server\n * @param {String} userId The id of the user to update.\n * @param {String} newPassword A new password for the user.\n * @param {Object} [options]\n * @param {Object} options.logout Logout all current connections with this userId (default: true)\n * @importFromPackage accounts-base\n */\nAccounts.setPassword = function (userId, newPlaintextPassword, options) {\n  options = _.extend({logout: true}, options);\n\n  var user = Meteor.users.findOne(userId);\n  if (!user)\n    throw new Meteor.Error(403, \"User not found\");\n\n  var update = {\n    $unset: {\n      'services.password.srp': 1, // XXX COMPAT WITH 0.8.1.3\n      'services.password.reset': 1\n    },\n    $set: {'services.password.bcrypt': hashPassword(newPlaintextPassword)}\n  };\n\n  if (options.logout) {\n    update.$unset['services.resume.loginTokens'] = 1;\n  }\n\n  Meteor.users.update({_id: user._id}, update);\n};\n\n\n///\n/// RESETTING VIA EMAIL\n///\n\n// Method called by a user to request a password reset email. This is\n// the start of the reset process.\nMeteor.methods({forgotPassword: function (options) {\n  check(options, {email: String});\n\n  var user = Accounts.findUserByEmail(options.email);\n  if (!user)\n    throw new Meteor.Error(403, \"User not found\");\n\n  const emails = _.pluck(user.emails || [], 'address');\n  const caseSensitiveEmail = _.find(emails, email => {\n    return email.toLowerCase() === options.email.toLowerCase();\n  });\n\n  Accounts.sendResetPasswordEmail(user._id, caseSensitiveEmail);\n}});\n\n// send the user an email with a link that when opened allows the user\n// to set a new password, without the old password.\n\n/**\n * @summary Send an email with a link the user can use to reset their password.\n * @locus Server\n * @param {String} userId The id of the user to send email to.\n * @param {String} [email] Optional. Which address of the user's to send the email to. This address must be in the user's `emails` list. Defaults to the first email in the list.\n * @importFromPackage accounts-base\n */\nAccounts.sendResetPasswordEmail = function (userId, email) {\n  // Make sure the user exists, and email is one of their addresses.\n  var user = Meteor.users.findOne(userId);\n  if (!user)\n    throw new Error(\"Can't find user\");\n  // pick the first email if we weren't passed an email.\n  if (!email && user.emails && user.emails[0])\n    email = user.emails[0].address;\n  // make sure we have a valid email\n  if (!email || !_.contains(_.pluck(user.emails || [], 'address'), email))\n    throw new Error(\"No such email for user.\");\n\n  var token = Random.secret();\n  var when = new Date();\n  var tokenRecord = {\n    token: token,\n    email: email,\n    when: when\n  };\n  Meteor.users.update(userId, {$set: {\n    \"services.password.reset\": tokenRecord\n  }});\n  // before passing to template, update user object with new token\n  Meteor._ensure(user, 'services', 'password').reset = tokenRecord;\n\n  var resetPasswordUrl = Accounts.urls.resetPassword(token);\n\n  var options = {\n    to: email,\n    from: Accounts.emailTemplates.resetPassword.from\n      ? Accounts.emailTemplates.resetPassword.from(user)\n      : Accounts.emailTemplates.from,\n    subject: Accounts.emailTemplates.resetPassword.subject(user)\n  };\n\n  if (typeof Accounts.emailTemplates.resetPassword.text === 'function') {\n    options.text =\n      Accounts.emailTemplates.resetPassword.text(user, resetPasswordUrl);\n  }\n\n  if (typeof Accounts.emailTemplates.resetPassword.html === 'function')\n    options.html =\n      Accounts.emailTemplates.resetPassword.html(user, resetPasswordUrl);\n\n  if (typeof Accounts.emailTemplates.headers === 'object') {\n    options.headers = Accounts.emailTemplates.headers;\n  }\n\n  Email.send(options);\n};\n\n// send the user an email informing them that their account was created, with\n// a link that when opened both marks their email as verified and forces them\n// to choose their password. The email must be one of the addresses in the\n// user's emails field, or undefined to pick the first email automatically.\n//\n// This is not called automatically. It must be called manually if you\n// want to use enrollment emails.\n\n/**\n * @summary Send an email with a link the user can use to set their initial password.\n * @locus Server\n * @param {String} userId The id of the user to send email to.\n * @param {String} [email] Optional. Which address of the user's to send the email to. This address must be in the user's `emails` list. Defaults to the first email in the list.\n * @importFromPackage accounts-base\n */\nAccounts.sendEnrollmentEmail = function (userId, email) {\n  // XXX refactor! This is basically identical to sendResetPasswordEmail.\n\n  // Make sure the user exists, and email is in their addresses.\n  var user = Meteor.users.findOne(userId);\n  if (!user)\n    throw new Error(\"Can't find user\");\n  // pick the first email if we weren't passed an email.\n  if (!email && user.emails && user.emails[0])\n    email = user.emails[0].address;\n  // make sure we have a valid email\n  if (!email || !_.contains(_.pluck(user.emails || [], 'address'), email))\n    throw new Error(\"No such email for user.\");\n\n  var token = Random.secret();\n  var when = new Date();\n  var tokenRecord = {\n    token: token,\n    email: email,\n    when: when\n  };\n  Meteor.users.update(userId, {$set: {\n    \"services.password.reset\": tokenRecord\n  }});\n\n  // before passing to template, update user object with new token\n  Meteor._ensure(user, 'services', 'password').reset = tokenRecord;\n\n  var enrollAccountUrl = Accounts.urls.enrollAccount(token);\n\n  var options = {\n    to: email,\n    from: Accounts.emailTemplates.enrollAccount.from\n      ? Accounts.emailTemplates.enrollAccount.from(user)\n      : Accounts.emailTemplates.from,\n    subject: Accounts.emailTemplates.enrollAccount.subject(user)\n  };\n\n  if (typeof Accounts.emailTemplates.enrollAccount.text === 'function') {\n    options.text =\n      Accounts.emailTemplates.enrollAccount.text(user, enrollAccountUrl);\n  }\n\n  if (typeof Accounts.emailTemplates.enrollAccount.html === 'function')\n    options.html =\n      Accounts.emailTemplates.enrollAccount.html(user, enrollAccountUrl);\n\n  if (typeof Accounts.emailTemplates.headers === 'object') {\n    options.headers = Accounts.emailTemplates.headers;\n  }\n\n  Email.send(options);\n};\n\n\n// Take token from sendResetPasswordEmail or sendEnrollmentEmail, change\n// the users password, and log them in.\nMeteor.methods({resetPassword: function (token, newPassword) {\n  var self = this;\n  return Accounts._loginMethod(\n    self,\n    \"resetPassword\",\n    arguments,\n    \"password\",\n    function () {\n      check(token, String);\n      check(newPassword, passwordValidator);\n\n      var user = Meteor.users.findOne({\n        \"services.password.reset.token\": token});\n      if (!user)\n        throw new Meteor.Error(403, \"Token expired\");\n      var email = user.services.password.reset.email;\n      if (!_.include(_.pluck(user.emails || [], 'address'), email))\n        return {\n          userId: user._id,\n          error: new Meteor.Error(403, \"Token has invalid email address\")\n        };\n\n      var hashed = hashPassword(newPassword);\n\n      // NOTE: We're about to invalidate tokens on the user, who we might be\n      // logged in as. Make sure to avoid logging ourselves out if this\n      // happens. But also make sure not to leave the connection in a state\n      // of having a bad token set if things fail.\n      var oldToken = Accounts._getLoginToken(self.connection.id);\n      Accounts._setLoginToken(user._id, self.connection, null);\n      var resetToOldToken = function () {\n        Accounts._setLoginToken(user._id, self.connection, oldToken);\n      };\n\n      try {\n        // Update the user record by:\n        // - Changing the password to the new one\n        // - Forgetting about the reset token that was just used\n        // - Verifying their email, since they got the password reset via email.\n        var affectedRecords = Meteor.users.update(\n          {\n            _id: user._id,\n            'emails.address': email,\n            'services.password.reset.token': token\n          },\n          {$set: {'services.password.bcrypt': hashed,\n                  'emails.$.verified': true},\n           $unset: {'services.password.reset': 1,\n                    'services.password.srp': 1}});\n        if (affectedRecords !== 1)\n          return {\n            userId: user._id,\n            error: new Meteor.Error(403, \"Invalid email\")\n          };\n      } catch (err) {\n        resetToOldToken();\n        throw err;\n      }\n\n      // Replace all valid login tokens with new ones (changing\n      // password should invalidate existing sessions).\n      Accounts._clearAllLoginTokens(user._id);\n\n      return {userId: user._id};\n    }\n  );\n}});\n\n///\n/// EMAIL VERIFICATION\n///\n\n\n// send the user an email with a link that when opened marks that\n// address as verified\n\n/**\n * @summary Send an email with a link the user can use verify their email address.\n * @locus Server\n * @param {String} userId The id of the user to send email to.\n * @param {String} [email] Optional. Which address of the user's to send the email to. This address must be in the user's `emails` list. Defaults to the first unverified email in the list.\n * @importFromPackage accounts-base\n */\nAccounts.sendVerificationEmail = function (userId, address) {\n  // XXX Also generate a link using which someone can delete this\n  // account if they own said address but weren't those who created\n  // this account.\n\n  // Make sure the user exists, and address is one of their addresses.\n  var user = Meteor.users.findOne(userId);\n  if (!user)\n    throw new Error(\"Can't find user\");\n  // pick the first unverified address if we weren't passed an address.\n  if (!address) {\n    var email = _.find(user.emails || [],\n                       function (e) { return !e.verified; });\n    address = (email || {}).address;\n\n    if (!address) {\n      throw new Error(\"That user has no unverified email addresses.\");\n    }\n  }\n  // make sure we have a valid address\n  if (!address || !_.contains(_.pluck(user.emails || [], 'address'), address))\n    throw new Error(\"No such email address for user.\");\n\n\n  var tokenRecord = {\n    token: Random.secret(),\n    address: address,\n    when: new Date()};\n  Meteor.users.update(\n    {_id: userId},\n    {$push: {'services.email.verificationTokens': tokenRecord}});\n\n  // before passing to template, update user object with new token\n  Meteor._ensure(user, 'services', 'email');\n  if (!user.services.email.verificationTokens) {\n    user.services.email.verificationTokens = [];\n  }\n  user.services.email.verificationTokens.push(tokenRecord);\n\n  var verifyEmailUrl = Accounts.urls.verifyEmail(tokenRecord.token);\n\n  var options = {\n    to: address,\n    from: Accounts.emailTemplates.verifyEmail.from\n      ? Accounts.emailTemplates.verifyEmail.from(user)\n      : Accounts.emailTemplates.from,\n    subject: Accounts.emailTemplates.verifyEmail.subject(user)\n  };\n\n  if (typeof Accounts.emailTemplates.verifyEmail.text === 'function') {\n    options.text =\n      Accounts.emailTemplates.verifyEmail.text(user, verifyEmailUrl);\n  }\n\n  if (typeof Accounts.emailTemplates.verifyEmail.html === 'function')\n    options.html =\n      Accounts.emailTemplates.verifyEmail.html(user, verifyEmailUrl);\n\n  if (typeof Accounts.emailTemplates.headers === 'object') {\n    options.headers = Accounts.emailTemplates.headers;\n  }\n\n  Email.send(options);\n};\n\n// Take token from sendVerificationEmail, mark the email as verified,\n// and log them in.\nMeteor.methods({verifyEmail: function (token) {\n  var self = this;\n  return Accounts._loginMethod(\n    self,\n    \"verifyEmail\",\n    arguments,\n    \"password\",\n    function () {\n      check(token, String);\n\n      var user = Meteor.users.findOne(\n        {'services.email.verificationTokens.token': token});\n      if (!user)\n        throw new Meteor.Error(403, \"Verify email link expired\");\n\n      var tokenRecord = _.find(user.services.email.verificationTokens,\n                               function (t) {\n                                 return t.token == token;\n                               });\n      if (!tokenRecord)\n        return {\n          userId: user._id,\n          error: new Meteor.Error(403, \"Verify email link expired\")\n        };\n\n      var emailsRecord = _.find(user.emails, function (e) {\n        return e.address == tokenRecord.address;\n      });\n      if (!emailsRecord)\n        return {\n          userId: user._id,\n          error: new Meteor.Error(403, \"Verify email link is for unknown address\")\n        };\n\n      // By including the address in the query, we can use 'emails.$' in the\n      // modifier to get a reference to the specific object in the emails\n      // array. See\n      // http://www.mongodb.org/display/DOCS/Updating/#Updating-The%24positionaloperator)\n      // http://www.mongodb.org/display/DOCS/Updating#Updating-%24pull\n      Meteor.users.update(\n        {_id: user._id,\n         'emails.address': tokenRecord.address},\n        {$set: {'emails.$.verified': true},\n         $pull: {'services.email.verificationTokens': {address: tokenRecord.address}}});\n\n      return {userId: user._id};\n    }\n  );\n}});\n\n/**\n * @summary Add an email address for a user. Use this instead of directly\n * updating the database. The operation will fail if there is a different user\n * with an email only differing in case. If the specified user has an existing\n * email only differing in case however, we replace it.\n * @locus Server\n * @param {String} userId The ID of the user to update.\n * @param {String} newEmail A new email address for the user.\n * @param {Boolean} [verified] Optional - whether the new email address should\n * be marked as verified. Defaults to false.\n * @importFromPackage accounts-base\n */\nAccounts.addEmail = function (userId, newEmail, verified) {\n  check(userId, NonEmptyString);\n  check(newEmail, NonEmptyString);\n  check(verified, Match.Optional(Boolean));\n\n  if (_.isUndefined(verified)) {\n    verified = false;\n  }\n\n  var user = Meteor.users.findOne(userId);\n  if (!user)\n    throw new Meteor.Error(403, \"User not found\");\n\n  // Allow users to change their own email to a version with a different case\n\n  // We don't have to call checkForCaseInsensitiveDuplicates to do a case\n  // insensitive check across all emails in the database here because: (1) if\n  // there is no case-insensitive duplicate between this user and other users,\n  // then we are OK and (2) if this would create a conflict with other users\n  // then there would already be a case-insensitive duplicate and we can't fix\n  // that in this code anyway.\n  var caseInsensitiveRegExp =\n    new RegExp('^' + Meteor._escapeRegExp(newEmail) + '$', 'i');\n\n  var didUpdateOwnEmail = _.any(user.emails, function(email, index) {\n    if (caseInsensitiveRegExp.test(email.address)) {\n      Meteor.users.update({\n        _id: user._id,\n        'emails.address': email.address\n      }, {$set: {\n        'emails.$.address': newEmail,\n        'emails.$.verified': verified\n      }});\n      return true;\n    }\n\n    return false;\n  });\n\n  // In the other updates below, we have to do another call to\n  // checkForCaseInsensitiveDuplicates to make sure that no conflicting values\n  // were added to the database in the meantime. We don't have to do this for\n  // the case where the user is updating their email address to one that is the\n  // same as before, but only different because of capitalization. Read the\n  // big comment above to understand why.\n\n  if (didUpdateOwnEmail) {\n    return;\n  }\n\n  // Perform a case insensitive check for duplicates before update\n  checkForCaseInsensitiveDuplicates('emails.address', 'Email', newEmail, user._id);\n\n  Meteor.users.update({\n    _id: user._id\n  }, {\n    $addToSet: {\n      emails: {\n        address: newEmail,\n        verified: verified\n      }\n    }\n  });\n\n  // Perform another check after update, in case a matching user has been\n  // inserted in the meantime\n  try {\n    checkForCaseInsensitiveDuplicates('emails.address', 'Email', newEmail, user._id);\n  } catch (ex) {\n    // Undo update if the check fails\n    Meteor.users.update({_id: user._id},\n      {$pull: {emails: {address: newEmail}}});\n    throw ex;\n  }\n}\n\n/**\n * @summary Remove an email address for a user. Use this instead of updating\n * the database directly.\n * @locus Server\n * @param {String} userId The ID of the user to update.\n * @param {String} email The email address to remove.\n * @importFromPackage accounts-base\n */\nAccounts.removeEmail = function (userId, email) {\n  check(userId, NonEmptyString);\n  check(email, NonEmptyString);\n\n  var user = Meteor.users.findOne(userId);\n  if (!user)\n    throw new Meteor.Error(403, \"User not found\");\n\n  Meteor.users.update({_id: user._id},\n    {$pull: {emails: {address: email}}});\n}\n\n///\n/// CREATING USERS\n///\n\n// Shared createUser function called from the createUser method, both\n// if originates in client or server code. Calls user provided hooks,\n// does the actual user insertion.\n//\n// returns the user id\nvar createUser = function (options) {\n  // Unknown keys allowed, because a onCreateUserHook can take arbitrary\n  // options.\n  check(options, Match.ObjectIncluding({\n    username: Match.Optional(String),\n    email: Match.Optional(String),\n    password: Match.Optional(passwordValidator)\n  }));\n\n  var username = options.username;\n  var email = options.email;\n  if (!username && !email)\n    throw new Meteor.Error(400, \"Need to set a username or email\");\n\n  var user = {services: {}};\n  if (options.password) {\n    var hashed = hashPassword(options.password);\n    user.services.password = { bcrypt: hashed };\n  }\n\n  if (username)\n    user.username = username;\n  if (email)\n    user.emails = [{address: email, verified: false}];\n\n  // Perform a case insensitive check before insert\n  checkForCaseInsensitiveDuplicates('username', 'Username', username);\n  checkForCaseInsensitiveDuplicates('emails.address', 'Email', email);\n\n  var userId = Accounts.insertUserDoc(options, user);\n  // Perform another check after insert, in case a matching user has been\n  // inserted in the meantime\n  try {\n    checkForCaseInsensitiveDuplicates('username', 'Username', username, userId);\n    checkForCaseInsensitiveDuplicates('emails.address', 'Email', email, userId);\n  } catch (ex) {\n    // Remove inserted user if the check fails\n    Meteor.users.remove(userId);\n    throw ex;\n  }\n  return userId;\n};\n\n// method for create user. Requests come from the client.\nMeteor.methods({createUser: function (options) {\n  var self = this;\n  return Accounts._loginMethod(\n    self,\n    \"createUser\",\n    arguments,\n    \"password\",\n    function () {\n      // createUser() above does more checking.\n      check(options, Object);\n      if (Accounts._options.forbidClientAccountCreation)\n        return {\n          error: new Meteor.Error(403, \"Signups forbidden\")\n        };\n\n      // Create user. result contains id and token.\n      var userId = createUser(options);\n      // safety belt. createUser is supposed to throw on error. send 500 error\n      // instead of sending a verification email with empty userid.\n      if (! userId)\n        throw new Error(\"createUser failed to insert new user\");\n\n      // If `Accounts._options.sendVerificationEmail` is set, register\n      // a token to verify the user's primary email, and send it to\n      // that address.\n      if (options.email && Accounts._options.sendVerificationEmail)\n        Accounts.sendVerificationEmail(userId, options.email);\n\n      // client gets logged in as the new user afterwards.\n      return {userId: userId};\n    }\n  );\n}});\n\n// Create user directly on the server.\n//\n// Unlike the client version, this does not log you in as this user\n// after creation.\n//\n// returns userId or throws an error if it can't create\n//\n// XXX add another argument (\"server options\") that gets sent to onCreateUser,\n// which is always empty when called from the createUser method? eg, \"admin:\n// true\", which we want to prevent the client from setting, but which a custom\n// method calling Accounts.createUser could set?\n//\nAccounts.createUser = function (options, callback) {\n  options = _.clone(options);\n\n  // XXX allow an optional callback?\n  if (callback) {\n    throw new Error(\"Accounts.createUser with callback not supported on the server yet.\");\n  }\n\n  return createUser(options);\n};\n\n///\n/// PASSWORD-SPECIFIC INDEXES ON USERS\n///\nMeteor.users._ensureIndex('services.email.verificationTokens.token',\n                          {unique: 1, sparse: 1});\nMeteor.users._ensureIndex('services.password.reset.token',\n                          {unique: 1, sparse: 1});\n"
  },
  {
    "path": "packages/accounts-password/password_tests.js",
    "content": "Accounts._noConnectionCloseDelayForTest = true;\n\nif (Meteor.isServer) {\n  Accounts.removeDefaultRateLimit();\n  \n  Meteor.methods({\n    getResetToken: function () {\n      var token = Meteor.users.findOne(this.userId).services.password.reset;\n      return token;\n    },\n    addSkipCaseInsensitiveChecksForTest: function (value) {\n      Accounts._skipCaseInsensitiveChecksForTest[value] = true;\n    },\n    removeSkipCaseInsensitiveChecksForTest: function (value) {\n      delete Accounts._skipCaseInsensitiveChecksForTest[value];\n    },\n    countUsersOnServer: function (query) {\n      return Meteor.users.find(query).count();\n    }\n  });\n}\n\nif (Meteor.isClient) (function () {\n\n  // XXX note, only one test can do login/logout things at once! for\n  // now, that is this test.\n\n  Accounts._isolateLoginTokenForTest();\n\n  var addSkipCaseInsensitiveChecksForTest = function (value, test, expect) {\n    Meteor.call('addSkipCaseInsensitiveChecksForTest', value);\n  };\n\n  var removeSkipCaseInsensitiveChecksForTest = function (value, test, expect) {\n    Meteor.call('removeSkipCaseInsensitiveChecksForTest', value);\n  };\n\n  var createUserStep = function (test, expect) {\n    // Hack because Tinytest does not clean the database between tests/runs\n    this.randomSuffix = Random.id(10);\n    this.username = 'AdaLovelace' + this.randomSuffix;\n    this.email =  \"Ada-intercept@lovelace.com\" + this.randomSuffix;\n    this.password = 'password';\n    Accounts.createUser(\n      {username: this.username, email: this.email, password: this.password},\n      loggedInAs(this.username, test, expect));\n  };\n  var logoutStep = function (test, expect) {\n    Meteor.logout(expect(function (error) {\n      if (error) {\n        test.fail(error.message);\n      }\n      test.equal(Meteor.user(), null);\n    }));\n  };\n  var loggedInAs = function (someUsername, test, expect) {\n    return expect(function (error) {\n      if (error) {\n        test.fail(error.message);\n      }\n      test.equal(Meteor.userId() && Meteor.user().username, someUsername);\n    });\n  };\n  var loggedInUserHasEmail = function (someEmail, test, expect) {\n    return expect(function (error) {\n      if (error) {\n        test.fail(error.message);\n      }\n      var user = Meteor.user();\n      test.isTrue(user && _.some(user.emails, function(email) {\n        return email.address === someEmail;\n      }));\n    });\n  };\n  var expectError = function (expectedError, test, expect) {\n    return expect(function (actualError) {\n      test.equal(actualError && actualError.error, expectedError.error);\n      test.equal(actualError && actualError.reason, expectedError.reason);\n    });\n  };\n  var expectUserNotFound = function (test, expect) {\n    return expectError(new Meteor.Error(403, \"User not found\"), test, expect);\n  };\n  var waitForLoggedOutStep = function (test, expect) {\n    pollUntil(expect, function () {\n      return Meteor.userId() === null;\n    }, 10 * 1000, 100);\n  };\n  var invalidateLoginsStep = function (test, expect) {\n    Meteor.call(\"testInvalidateLogins\", 'fail', expect(function (error) {\n      if (error) {\n        test.fail(error.message);\n      }\n    }));\n  };\n  var hideActualLoginErrorStep = function (test, expect) {\n    Meteor.call(\"testInvalidateLogins\", 'hide', expect(function (error) {\n      if (error) {\n        test.fail(error.message);\n      }\n    }));\n  };\n  var validateLoginsStep = function (test, expect) {\n    Meteor.call(\"testInvalidateLogins\", false, expect(function (error) {\n      if (error) {\n        test.fail(error.message);\n      }\n    }));\n  };\n\n  testAsyncMulti(\"passwords - basic login with password\", [\n    function (test, expect) {\n      // setup\n      this.username = Random.id();\n      this.email = Random.id() + '-intercept@example.com';\n      this.password = 'password';\n\n      Accounts.createUser(\n        {username: this.username, email: this.email, password: this.password},\n        loggedInAs(this.username, test, expect));\n    },\n    function (test, expect) {\n      test.notEqual(Meteor.userId(), null);\n    },\n    logoutStep,\n    function (test, expect) {\n      Meteor.loginWithPassword(this.username, this.password,\n                               loggedInAs(this.username, test, expect));\n    },\n    logoutStep,\n    // This next step tests reactive contexts which are reactive on\n    // Meteor.user().\n    function (test, expect) {\n      // Set up a reactive context that only refreshes when Meteor.user() is\n      // invalidated.\n      var loaded = false;\n      var handle = Tracker.autorun(function () {\n        if (Meteor.user() && Meteor.user().emails)\n          loaded = true;\n      });\n      // At the beginning, we're not logged in.\n      test.isFalse(loaded);\n      Meteor.loginWithPassword(this.username, this.password, expect(function (error) {\n        test.equal(error, undefined);\n        test.notEqual(Meteor.userId(), null);\n        // By the time of the login callback, the user should be loaded.\n        test.isTrue(Meteor.user().emails);\n        // Flushing should get us the rerun as well.\n        Tracker.flush();\n        test.isTrue(loaded);\n        handle.stop();\n      }));\n    },\n    logoutStep,\n    function (test, expect) {\n      Meteor.loginWithPassword({username: this.username}, this.password,\n                               loggedInAs(this.username, test, expect));\n    },\n    logoutStep,\n    function (test, expect) {\n      Meteor.loginWithPassword(this.email, this.password,\n                               loggedInAs(this.username, test, expect));\n    },\n    logoutStep,\n    function (test, expect) {\n      Meteor.loginWithPassword({email: this.email}, this.password,\n                               loggedInAs(this.username, test, expect));\n    },\n    logoutStep\n  ]);\n\n\n  testAsyncMulti(\"passwords - plain text passwords\", [\n    function (test, expect) {\n      // setup\n      this.username = Random.id();\n      this.email = Random.id() + '-intercept@example.com';\n      this.password = 'password';\n\n      // create user with raw password (no API, need to invoke callLoginMethod\n      // directly)\n      Accounts.callLoginMethod({\n        methodName: 'createUser',\n        methodArguments: [{username: this.username, password: this.password}],\n        userCallback: loggedInAs(this.username, test, expect)\n      });\n    },\n    logoutStep,\n    // check can login normally with this password.\n    function(test, expect) {\n      Meteor.loginWithPassword({username: this.username}, this.password,\n                               loggedInAs(this.username, test, expect));\n    },\n    logoutStep,\n    // plain text password. no API for this, have to invoke callLoginMethod\n    // directly.\n    function (test, expect) {\n      Accounts.callLoginMethod({\n        // wrong password\n        methodArguments: [{user: {username: this.username}, password: 'wrong'}],\n        userCallback: expect(function (error) {\n          test.isTrue(error);\n          test.isFalse(Meteor.user());\n        })});\n    },\n    function (test, expect) {\n      Accounts.callLoginMethod({\n        // right password\n        methodArguments: [{user: {username: this.username},\n                           password: this.password}],\n        userCallback: loggedInAs(this.username, test, expect)\n      });\n    },\n    logoutStep\n  ]);\n\n  testAsyncMulti(\"passwords - logging in with case insensitive username\", [\n    createUserStep,\n    logoutStep,\n    // We should be able to log in with the username in lower case\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        { username: \"adalovelace\" + this.randomSuffix },\n        this.password,\n        loggedInAs(this.username, test, expect));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - logging in with case insensitive username \" +\n      \"with non-ASCII characters\", [\n    function (test, expect) {\n      // Hack because Tinytest does not clean the database between tests/runs\n      this.randomSuffix = Random.id(10);\n      this.username = 'ÁdaLØvela😈e' + this.randomSuffix;\n      this.password = 'password';\n      Accounts.createUser(\n        {username: this.username, email: this.email, password: this.password},\n        loggedInAs(this.username, test, expect));\n    },\n    logoutStep,\n    // We should be able to log in with the username in lower case\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        { username: \"ádaløvela😈e\" + this.randomSuffix },\n        this.password,\n        loggedInAs(this.username, test, expect));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - logging in with case insensitive username \" +\n      \"should escape regex special characters\", [\n    createUserStep,\n    logoutStep,\n    // We shouldn't be able to log in with a regex expression for the username\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        { username: \".+\" + this.randomSuffix },\n        this.password,\n        expectUserNotFound(test, expect));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - logging in with case insensitive username \" +\n     \"should require a match of the full string\", [\n    createUserStep,\n    logoutStep,\n    // We shouldn't be able to log in with a partial match for the username\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        { username: \"lovelace\" + this.randomSuffix },\n        this.password,\n        expectUserNotFound(test, expect));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - logging in with case insensitive username when \" +\n      \"there are multiple matches\", [\n    createUserStep,\n    logoutStep,\n    function (test, expect) {\n      this.otherUsername = 'Adalovelace' + this.randomSuffix;\n      addSkipCaseInsensitiveChecksForTest(this.otherUsername, test, expect);\n    },\n    // Create another user with a username that only differs in case\n    function (test, expect) {\n      Accounts.createUser(\n        { username: this.otherUsername, password: this.password },\n        loggedInAs(this.otherUsername, test, expect));\n    },\n    function (test, expect) {\n      removeSkipCaseInsensitiveChecksForTest(this.otherUsername, test, expect);\n    },\n    // We shouldn't be able to log in with the username in lower case\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        { username: \"adalovelace\" + this.randomSuffix },\n        this.password,\n        expectUserNotFound(test, expect));\n    },\n    // We should still be able to log in with the username in original case\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        { username: this.username },\n        this.password,\n        loggedInAs(this.username, test, expect));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - creating users with the same case insensitive \" +\n      \"username\", [\n    createUserStep,\n    logoutStep,\n    // Attempting to create another user with a username that only differs in\n    // case should fail\n    function (test, expect) {\n      this.newUsername = 'adalovelace' + this.randomSuffix;\n      Accounts.createUser(\n        { username: this.newUsername, password: this.password },\n        expectError(\n          new Meteor.Error(403, \"Username already exists.\"),\n          test,\n          expect));\n    },\n    // Make sure the new user has not been inserted\n    function (test, expect) {\n      Meteor.call('countUsersOnServer',\n        { username: this.newUsername },\n        expect(function (error, result) {\n          test.equal(result, 0);\n      }));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - logging in with case insensitive email\", [\n    createUserStep,\n    logoutStep,\n    // We should be able to log in with the email in lower case\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        { email: \"ada-intercept@lovelace.com\" + this.randomSuffix },\n        this.password,\n        loggedInAs(this.username, test, expect));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - logging in with case insensitive email should \" +\n      \"escape regex special characters\", [\n    createUserStep,\n    logoutStep,\n    // We shouldn't be able to log in with a regex expression for the email\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        { email: \".+\" + this.randomSuffix },\n        this.password,\n        expectUserNotFound(test, expect));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - logging in with case insensitive email should \" +\n     \"require a match of the full string\", [\n    createUserStep,\n    logoutStep,\n    // We shouldn't be able to log in with a partial match for the email\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        { email: \"com\" + this.randomSuffix },\n        this.password,\n        expectUserNotFound(test, expect));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - logging in with case insensitive email when \" +\n      \"there are multiple matches\", [\n    createUserStep,\n    logoutStep,\n    function (test, expect) {\n      this.otherUsername = 'AdaLovelace' + Random.id(10);\n      this.otherEmail =  \"ADA-intercept@lovelace.com\" + this.randomSuffix;\n      addSkipCaseInsensitiveChecksForTest(this.otherEmail, test, expect);\n    },\n    // Create another user with an email that only differs in case\n    function (test, expect) {\n      Accounts.createUser(\n        { username: this.otherUsername,\n          email: this.otherEmail,\n          password: this.password },\n        loggedInAs(this.otherUsername, test, expect));\n    },\n    function (test, expect) {\n      removeSkipCaseInsensitiveChecksForTest(this.otherUsername, test, expect);\n    },\n    logoutStep,\n    // We shouldn't be able to log in with the email in lower case\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        { email: \"ada-intercept@lovelace.com\" + this.randomSuffix },\n        this.password,\n        expectUserNotFound(test, expect));\n    },\n    // We should still be able to log in with the email in original case\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        { email: this.email },\n        this.password,\n        loggedInAs(this.username, test, expect));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - creating users with the same case insensitive \" +\n      \"email\", [\n    createUserStep,\n    logoutStep,\n    // Attempting to create another user with an email that only differs in\n    // case should fail\n    function (test, expect) {\n      this.newEmail =  \"ada-intercept@lovelace.com\" + this.randomSuffix;\n      Accounts.createUser(\n        { email: this.newEmail, password: this.password },\n        expectError(\n          new Meteor.Error(403, \"Email already exists.\"),\n          test,\n          expect));\n    },\n    // Make sure the new user has not been inserted\n    function (test, expect) {\n      Meteor.call('countUsersOnServer',\n        { 'emails.address': this.newEmail },\n        expect (function (error, result) {\n          test.equal(result, 0);\n        })\n      );\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - changing passwords\", [\n    function (test, expect) {\n      // setup\n      this.username = Random.id();\n      this.email = Random.id() + '-intercept@example.com';\n      this.password = 'password';\n      this.password2 = 'password2';\n\n      Accounts.createUser(\n        { username: this.username, email: this.email, password: this.password },\n        loggedInAs(this.username, test, expect));\n    },\n    // Send a password reset email so that we can test that password\n    // reset tokens get deleted on password change.\n    function (test, expect) {\n      Meteor.call(\"forgotPassword\",\n        { email: this.email }, expect(function (error) {\n        test.isFalse(error);\n      }));\n    },\n    function (test, expect) {\n      var self = this;\n      Meteor.call(\"getResetToken\", expect(function (err, token) {\n        test.isFalse(err);\n        test.isTrue(token);\n        self.token = token;\n      }));\n    },\n    // change password with bad old password. we stay logged in.\n    function (test, expect) {\n      var self = this;\n      Accounts.changePassword('wrong', 'doesntmatter', expect(function (error) {\n        test.isTrue(error);\n        test.equal(Meteor.user().username, self.username);\n      }));\n    },\n    // change password with good old password.\n    function (test, expect) {\n      Accounts.changePassword(this.password, this.password2,\n                              loggedInAs(this.username, test, expect));\n    },\n    function (test, expect) {\n      Meteor.call(\"getResetToken\", expect(function (err, token) {\n        test.isFalse(err);\n        test.isFalse(token);\n      }));\n    },\n    logoutStep,\n    // old password, failed login\n    function (test, expect) {\n      Meteor.loginWithPassword(this.email, this.password, expect(function (error) {\n        test.isTrue(error);\n        test.isFalse(Meteor.user());\n      }));\n    },\n    // new password, success\n    function (test, expect) {\n      Meteor.loginWithPassword(this.email, this.password2,\n                               loggedInAs(this.username, test, expect));\n    },\n    logoutStep\n  ]);\n\n  testAsyncMulti(\"passwords - changing password logs out other clients\", [\n    function (test, expect) {\n      this.username = Random.id();\n      this.email = Random.id() + '-intercept@example.com';\n      this.password = 'password';\n      this.password2 = 'password2';\n      Accounts.createUser(\n        { username: this.username, email: this.email, password: this.password },\n        loggedInAs(this.username, test, expect));\n    },\n    // Log in a second connection as this user.\n    function (test, expect) {\n      var self = this;\n\n      self.secondConn = DDP.connect(Meteor.absoluteUrl());\n      self.secondConn.call('login',\n                { user: { username: self.username }, password: self.password },\n                expect(function (err, result) {\n                  test.isFalse(err);\n                  self.secondConn.setUserId(result.id);\n                  test.isTrue(self.secondConn.userId());\n\n                  self.secondConn.onReconnect = function () {\n                    self.secondConn.apply(\n                      'login',\n                      [{ resume: result.token }],\n                      { wait: true },\n                      function (err, result) {\n                        self.secondConn.setUserId(result && result.id || null);\n                      }\n                    );\n                  };\n                }));\n    },\n    function (test, expect) {\n      var self = this;\n      Accounts.changePassword(self.password, self.password2, expect(function (err) {\n        test.isFalse(err);\n      }));\n    },\n    // Now that we've changed the password, wait until the second\n    // connection gets logged out.\n    function (test, expect) {\n      var self = this;\n      pollUntil(expect, function () {\n        return self.secondConn.userId() === null;\n      }, 10 * 1000, 100);\n    }\n  ]);\n\n\n  testAsyncMulti(\"passwords - new user hooks\", [\n    function (test, expect) {\n      // setup\n      this.username = Random.id();\n      this.email = Random.id() + '-intercept@example.com';\n      this.password = 'password';\n    },\n    // test Accounts.validateNewUser\n    function(test, expect) {\n      Accounts.createUser(\n        {username: this.username, password: this.password,\n         // should fail the new user validators\n         profile: {invalid: true}},\n        expect(function (error) {\n          test.equal(error.error, 403);\n          test.equal(error.reason, \"User validation failed\");\n        }));\n    },\n    logoutStep,\n    function(test, expect) {\n      Accounts.createUser(\n        {username: this.username, password: this.password,\n         // should fail the new user validator with a special\n         // exception\n         profile: {invalidAndThrowException: true}},\n        expect(function (error) {\n          test.equal(\n            error.reason,\n            \"An exception thrown within Accounts.validateNewUser\");\n        }));\n    },\n    // test Accounts.onCreateUser\n    function(test, expect) {\n      Accounts.createUser(\n        {username: this.username, password: this.password,\n         testOnCreateUserHook: true},\n        loggedInAs(this.username, test, expect));\n    },\n    function(test, expect) {\n      test.equal(Meteor.user().profile.touchedByOnCreateUser, true);\n    },\n    logoutStep\n  ]);\n\n\n  testAsyncMulti(\"passwords - Meteor.user()\", [\n    function (test, expect) {\n      // setup\n      this.username = Random.id();\n      this.password = 'password';\n\n      Accounts.createUser(\n        {username: this.username, password: this.password,\n         testOnCreateUserHook: true},\n        loggedInAs(this.username, test, expect));\n    },\n    // test Meteor.user(). This test properly belongs in\n    // accounts-base/accounts_tests.js, but this is where the tests that\n    // actually log in are.\n    function(test, expect) {\n      var self = this;\n      var clientUser = Meteor.user();\n      Accounts.connection.call('testMeteorUser', expect(function (err, result) {\n        test.equal(result._id, clientUser._id);\n        test.equal(result.username, clientUser.username);\n        test.equal(result.username, self.username);\n        test.equal(result.profile.touchedByOnCreateUser, true);\n        test.equal(err, undefined);\n      }));\n    },\n    function(test, expect) {\n      // Test that even with no published fields, we still have a document.\n      Accounts.connection.call('clearUsernameAndProfile', expect(function() {\n        test.isTrue(Meteor.userId());\n        var user = Meteor.user();\n        test.equal(user, {_id: Meteor.userId()});\n      }));\n    },\n    logoutStep,\n    function(test, expect) {\n      var clientUser = Meteor.user();\n      test.equal(clientUser, null);\n      test.equal(Meteor.userId(), null);\n      Accounts.connection.call('testMeteorUser', expect(function (err, result) {\n        test.equal(err, undefined);\n        test.equal(result, null);\n      }));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - allow rules\", [\n    // create a second user to have an id for in a later test\n    function (test, expect) {\n      this.otherUsername = Random.id();\n      Accounts.createUser(\n        {username: this.otherUsername, password: 'dontcare',\n         testOnCreateUserHook: true},\n        loggedInAs(this.otherUsername, test, expect));\n    },\n    function (test, expect) {\n      this.otherUserId = Meteor.userId();\n    },\n    function (test, expect) {\n      // real setup\n      this.username = Random.id();\n      this.password = 'password';\n\n      Accounts.createUser(\n        {username: this.username, password: this.password,\n         testOnCreateUserHook: true},\n        loggedInAs(this.username, test, expect));\n    },\n    // test the default Meteor.users allow rule. This test properly belongs in\n    // accounts-base/accounts_tests.js, but this is where the tests that\n    // actually log in are.\n    function(test, expect) {\n      this.userId = Meteor.userId();\n      test.notEqual(this.userId, null);\n      test.notEqual(this.userId, this.otherUserId);\n      // Can't update fields other than profile.\n      Meteor.users.update(\n        this.userId, {$set: {disallowed: true, 'profile.updated': 42}},\n        expect(function (err) {\n          test.isTrue(err);\n          test.equal(err.error, 403);\n          test.isFalse(_.has(Meteor.user(), 'disallowed'));\n          test.isFalse(_.has(Meteor.user().profile, 'updated'));\n        }));\n    },\n    function(test, expect) {\n      // Can't update another user.\n      Meteor.users.update(\n        this.otherUserId, {$set: {'profile.updated': 42}},\n        expect(function (err) {\n          test.isTrue(err);\n          test.equal(err.error, 403);\n        }));\n    },\n    function(test, expect) {\n      // Can't update using a non-ID selector. (This one is thrown client-side.)\n      test.throws(function () {\n        Meteor.users.update(\n          {username: this.username}, {$set: {'profile.updated': 42}});\n      });\n      test.isFalse(_.has(Meteor.user().profile, 'updated'));\n    },\n    function(test, expect) {\n      // Can update own profile using ID.\n      Meteor.users.update(\n        this.userId, {$set: {'profile.updated': 42}},\n        expect(function (err) {\n          test.isFalse(err);\n          test.equal(42, Meteor.user().profile.updated);\n        }));\n    },\n    logoutStep\n  ]);\n\n\n  testAsyncMulti(\"passwords - tokens\", [\n    function (test, expect) {\n      // setup\n      this.username = Random.id();\n      this.password = 'password';\n\n      Accounts.createUser(\n        {username: this.username, password: this.password},\n        loggedInAs(this.username, test, expect));\n    },\n\n    function (test, expect) {\n      // we can't login with an invalid token\n      var expectLoginError = expect(function (err) {\n        test.isTrue(err);\n      });\n      Meteor.loginWithToken('invalid', expectLoginError);\n    },\n\n    function (test, expect) {\n      // we can login with a valid token\n      var expectLoginOK = expect(function (err) {\n        test.isFalse(err);\n      });\n      Meteor.loginWithToken(Accounts._storedLoginToken(), expectLoginOK);\n    },\n\n    function (test, expect) {\n      // test logging out invalidates our token\n      var expectLoginError = expect(function (err) {\n        test.isTrue(err);\n      });\n      var token = Accounts._storedLoginToken();\n      test.isTrue(token);\n      Meteor.logout(function () {\n        Meteor.loginWithToken(token, expectLoginError);\n      });\n    },\n\n    function (test, expect) {\n      var self = this;\n      // Test that login tokens get expired. We should get logged out when a\n      // token expires, and not be able to log in again with the same token.\n      var expectNoError = expect(function (err) {\n        test.isFalse(err);\n      });\n\n      Meteor.loginWithPassword(this.username, this.password, function (error) {\n        self.token = Accounts._storedLoginToken();\n        test.isTrue(self.token);\n        expectNoError(error);\n        Accounts.connection.call(\"expireTokens\");\n      });\n    },\n    waitForLoggedOutStep,\n    function (test, expect) {\n      var token = Accounts._storedLoginToken();\n      test.isFalse(token);\n    },\n    function (test, expect) {\n      // Test that once expireTokens is finished, we can't login again with our\n      // previous token.\n      Meteor.loginWithToken(this.token, expect(function (err, result) {\n        test.isTrue(err);\n        test.equal(Meteor.userId(), null);\n      }));\n    },\n    logoutStep,\n    function (test, expect) {\n      var self = this;\n      // Test that Meteor.logoutOtherClients logs out a second\n      // authentcated connection while leaving Accounts.connection\n      // logged in.\n      var secondConn = DDP.connect(Meteor.absoluteUrl());\n      var token;\n\n      var expectSecondConnLoggedOut = expect(function (err, result) {\n        test.isTrue(err);\n      });\n\n      var expectAccountsConnLoggedIn = expect(function (err, result) {\n        test.isFalse(err);\n      });\n\n      var expectSecondConnLoggedIn = expect(function (err, result) {\n        test.equal(result.token, token);\n        test.isFalse(err);\n        Meteor.logoutOtherClients(function (err) {\n          test.isFalse(err);\n          secondConn.call('login', { resume: token },\n                          expectSecondConnLoggedOut);\n          Accounts.connection.call('login', {\n            resume: Accounts._storedLoginToken()\n          }, expectAccountsConnLoggedIn);\n        });\n      });\n\n      Meteor.loginWithPassword(\n        self.username,\n        self.password,\n        expect(function (err) {\n          test.isFalse(err);\n          token = Accounts._storedLoginToken();\n          test.isTrue(token);\n          secondConn.call('login', { resume: token },\n                          expectSecondConnLoggedIn);\n        })\n      );\n    },\n    logoutStep,\n\n    // The tests below this point are for the deprecated\n    // `logoutOtherClients` method.\n\n    function (test, expect) {\n      var self = this;\n\n      // Test that Meteor.logoutOtherClients logs out a second authenticated\n      // connection while leaving Accounts.connection logged in.\n      var token;\n      self.secondConn = DDP.connect(Meteor.absoluteUrl());\n\n      var expectLoginError = expect(function (err) {\n        test.isTrue(err);\n      });\n      var expectValidToken = expect(function (err, result) {\n        test.isFalse(err);\n        test.isTrue(result);\n        self.tokenFromLogoutOthers = result.token;\n      });\n      var expectSecondConnLoggedIn = expect(function (err, result) {\n        test.equal(result.token, token);\n        test.isFalse(err);\n        // This test will fail if an unrelated reconnect triggers before the\n        // connection is logged out. In general our tests aren't resilient to\n        // mid-test reconnects.\n        self.secondConn.onReconnect = function () {\n          self.secondConn.call(\"login\", { resume: token }, expectLoginError);\n        };\n        Accounts.connection.call(\"logoutOtherClients\", expectValidToken);\n      });\n\n      Meteor.loginWithPassword(this.username, this.password, expect(function (err) {\n        test.isFalse(err);\n        token = Accounts._storedLoginToken();\n        self.beforeLogoutOthersToken = token;\n        test.isTrue(token);\n        self.secondConn.call(\"login\", { resume: token },\n                             expectSecondConnLoggedIn);\n      }));\n    },\n    // Test that logoutOtherClients logged out Accounts.connection and that the\n    // previous token is no longer valid.\n    waitForLoggedOutStep,\n    function (test, expect) {\n      var self = this;\n      var token = Accounts._storedLoginToken();\n      test.isFalse(token);\n      this.secondConn.close();\n      Meteor.loginWithToken(\n        self.beforeLogoutOthersToken,\n        expect(function (err) {\n          test.isTrue(err);\n          test.isFalse(Meteor.userId());\n        })\n      );\n    },\n    // Test that logoutOtherClients returned a new token that we can use to\n    // log in.\n    function (test, expect) {\n      var self = this;\n      Meteor.loginWithToken(\n        self.tokenFromLogoutOthers,\n        expect(function (err) {\n          test.isFalse(err);\n          test.isTrue(Meteor.userId());\n        })\n      );\n    },\n    logoutStep,\n\n\n\n    function (test, expect) {\n      var self = this;\n      // Test that deleting a user logs out that user's connections.\n      Meteor.loginWithPassword(this.username, this.password, expect(function (err) {\n        test.isFalse(err);\n        Accounts.connection.call(\"removeUser\", self.username);\n      }));\n    },\n    waitForLoggedOutStep\n  ]);\n\n  testAsyncMulti(\"passwords - validateLoginAttempt\", [\n    function (test, expect) {\n      this.username = Random.id();\n      this.password = \"password\";\n\n      Accounts.createUser(\n        {username: this.username, password: this.password},\n        loggedInAs(this.username, test, expect));\n    },\n    logoutStep,\n    invalidateLoginsStep,\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        this.username,\n        this.password,\n        expect(function (error) {\n          test.isTrue(error);\n          test.equal(error.reason, \"Login forbidden\");\n        })\n      );\n    },\n    validateLoginsStep,\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        \"no such user\",\n        \"some password\",\n        expect(function (error) {\n          test.isTrue(error);\n          test.equal(error.reason, 'User not found');\n        })\n      );\n    },\n    hideActualLoginErrorStep,\n    function (test, expect) {\n      Meteor.loginWithPassword(\n        \"no such user\",\n        \"some password\",\n        expect(function (error) {\n          test.isTrue(error);\n          test.equal(error.reason, 'hide actual error');\n        })\n      );\n    },\n    validateLoginsStep\n  ]);\n\n  testAsyncMulti(\"passwords - server onLogin hook\", [\n    function (test, expect) {\n      Meteor.call(\"testCaptureLogins\", expect(function (error) {\n        test.isFalse(error);\n      }));\n    },\n    function (test, expect) {\n      this.username = Random.id();\n      this.password = \"password\";\n\n      Accounts.createUser(\n        {username: this.username, password: this.password},\n        loggedInAs(this.username, test, expect));\n    },\n    function (test, expect) {\n      var self = this;\n      Meteor.call(\"testFetchCapturedLogins\", expect(function (error, logins) {\n        test.isFalse(error);\n        test.equal(logins.length, 1);\n        var login = logins[0];\n        test.isTrue(login.successful);\n        var attempt = login.attempt;\n        test.equal(attempt.type, \"password\");\n        test.isTrue(attempt.allowed);\n        test.equal(attempt.methodArguments[0].username, self.username);\n      }));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - client onLogin hook\", [\n    function (test, expect) {\n      var self = this;\n      this.username = Random.id();\n      this.password = \"password\";\n      this.attempt = false;\n\n      this.onLogin = Accounts.onLogin(function (attempt) {\n        self.attempt = true;\n      });\n\n      Accounts.createUser(\n        {username: this.username, password: this.password},\n        loggedInAs(this.username, test, expect));\n    },\n    function (test, expect) {\n      this.onLogin.stop();\n      test.isTrue(this.attempt);\n      expect(function () {})();\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - server onLogout hook\", [\n    function (test, expect) {\n      Meteor.call(\"testCaptureLogouts\", expect(function (error) {\n        test.isFalse(error);\n      }));\n    },\n    function (test, expect) {\n      this.username = Random.id();\n      this.password = \"password\";\n\n      Accounts.createUser(\n        {username: this.username, password: this.password},\n        loggedInAs(this.username, test, expect));\n    },\n    logoutStep,\n    function (test, expect) {\n      var self = this;\n      Meteor.call(\"testFetchCapturedLogouts\", expect(function (error, logouts) {\n        test.isFalse(error);\n        test.equal(logouts.length, 1);\n        var logout = logouts[0];\n        test.isTrue(logout.successful);\n      }));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - client onLogout hook\", [\n    function (test, expect) {\n      var self = this;\n      this.username = Random.id();\n      this.password = \"password\";\n      this.attempt = false;\n\n      this.onLogout = Accounts.onLogout(function () {\n        self.logoutSuccess = true;\n      });\n\n      Accounts.createUser(\n        {username: this.username, password: this.password},\n        loggedInAs(this.username, test, expect));\n    },\n    logoutStep,\n    function (test, expect) {\n      test.isTrue(this.logoutSuccess);\n      expect(function() {})();\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - server onLoginFailure hook\", [\n    function (test, expect) {\n      this.username = Random.id();\n      this.password = \"password\";\n\n      Accounts.createUser(\n        {username: this.username, password: this.password},\n        loggedInAs(this.username, test, expect));\n    },\n    logoutStep,\n    function (test, expect) {\n      Meteor.call(\"testCaptureLogins\", expect(function (error) {\n        test.isFalse(error);\n      }));\n    },\n    function (test, expect) {\n      Meteor.loginWithPassword(this.username, \"incorrect\", expect(function (error) {\n        test.isTrue(error);\n      }));\n    },\n    function (test, expect) {\n      Meteor.call(\"testFetchCapturedLogins\", expect(function (error, logins) {\n        test.isFalse(error);\n        test.equal(logins.length, 1);\n        var login = logins[0];\n        test.isFalse(login.successful);\n        var attempt = login.attempt;\n        test.equal(attempt.type, \"password\");\n        test.isFalse(attempt.allowed);\n        test.equal(attempt.error.reason, \"Incorrect password\");\n      }));\n    },\n    function (test, expect) {\n      Meteor.call(\"testCaptureLogins\", expect(function (error) {\n        test.isFalse(error);\n      }));\n    },\n    function (test, expect) {\n      Meteor.loginWithPassword(\"no such user\", \"incorrect\", expect(function (error) {\n        test.isTrue(error);\n      }));\n    },\n    function (test, expect) {\n      Meteor.call(\"testFetchCapturedLogins\", expect(function (error, logins) {\n        test.isFalse(error);\n        test.equal(logins.length, 1);\n        var login = logins[0];\n        test.isFalse(login.successful);\n        var attempt = login.attempt;\n        test.equal(attempt.type, \"password\");\n        test.isFalse(attempt.allowed);\n        test.equal(attempt.error.reason, \"User not found\");\n      }));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - client onLoginFailure hook\", [\n    function (test, expect) {\n      var self = this;\n      this.username = Random.id();\n      this.password = \"password\";\n      this.attempt = false;\n\n      this.onLoginFailure = Accounts.onLoginFailure(function () {\n        self.attempt = true;\n      })\n\n      Accounts.createUser(\n        {username: this.username, password: this.password},\n        loggedInAs(this.username, test, expect));\n    },\n    logoutStep,\n    function (test, expect) {\n      Meteor.call(\"testCaptureLogins\", expect(function (error) {\n        test.isFalse(error);\n      }));\n    },\n    function (test, expect) {\n      Meteor.loginWithPassword(this.username, \"incorrect\", expect(function (error) {\n        test.isTrue(error);\n      }));\n    },\n    function (test, expect) {\n      this.onLoginFailure.stop();\n      test.isTrue(this.attempt);\n      expect(function () {})();\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - srp to bcrypt upgrade\", [\n    logoutStep,\n    // Create user with old SRP credentials in the database.\n    function (test, expect) {\n      var self = this;\n      Meteor.call(\"testCreateSRPUser\", expect(function (error, result) {\n        test.isFalse(error);\n        self.username = result;\n      }));\n    },\n    // We are able to login with the old style credentials in the database.\n    function (test, expect) {\n      Meteor.loginWithPassword(this.username, 'abcdef', expect(function (error) {\n        test.isFalse(error);\n      }));\n    },\n    function (test, expect) {\n      Meteor.call(\"testSRPUpgrade\", this.username, expect(function (error) {\n        test.isFalse(error);\n      }));\n    },\n    logoutStep,\n    // After the upgrade to bcrypt we're still able to login.\n    function (test, expect) {\n      Meteor.loginWithPassword(this.username, 'abcdef', expect(function (error) {\n        test.isFalse(error);\n      }));\n    },\n    logoutStep,\n    function (test, expect) {\n      Meteor.call(\"removeUser\", this.username, expect(function (error) {\n        test.isFalse(error);\n      }));\n    }\n  ]);\n\n  testAsyncMulti(\"passwords - srp to bcrypt upgrade via password change\", [\n    logoutStep,\n    // Create user with old SRP credentials in the database.\n    function (test, expect) {\n      var self = this;\n      Meteor.call(\"testCreateSRPUser\", expect(function (error, result) {\n        test.isFalse(error);\n        self.username = result;\n      }));\n    },\n    // Log in with the plaintext password handler, which should NOT upgrade us to bcrypt.\n    function (test, expect) {\n      Accounts.callLoginMethod({\n        methodName: \"login\",\n        methodArguments: [ { user: { username: this.username }, password: \"abcdef\" } ],\n        userCallback: expect(function (err) {\n          test.isFalse(err);\n        })\n      });\n    },\n    function (test, expect) {\n      Meteor.call(\"testNoSRPUpgrade\", this.username, expect(function (error) {\n        test.isFalse(error);\n      }));\n    },\n    // Changing our password should upgrade us to bcrypt.\n    function (test, expect) {\n      Accounts.changePassword(\"abcdef\", \"abcdefg\", expect(function (error) {\n        test.isFalse(error);\n      }));\n    },\n    function (test, expect) {\n      Meteor.call(\"testSRPUpgrade\", this.username, expect(function (error) {\n        test.isFalse(error);\n      }));\n    },\n    // And after the upgrade we should be able to change our password again.\n    function (test, expect) {\n      Accounts.changePassword(\"abcdefg\", \"abcdef\", expect(function (error) {\n        test.isFalse(error);\n      }));\n    },\n    logoutStep\n  ]);\n}) ();\n\n\nif (Meteor.isServer) (function () {\n\n  Tinytest.add(\n    'passwords - setup more than one onCreateUserHook',\n    function (test) {\n      test.throws(function() {\n        Accounts.onCreateUser(function () {});\n      });\n    });\n\n\n  Tinytest.add(\n    'passwords - createUser hooks',\n    function (test) {\n      var username = Random.id();\n      test.throws(function () {\n        // should fail the new user validators\n        Accounts.createUser({username: username, profile: {invalid: true}});\n      });\n\n      var userId = Accounts.createUser({username: username,\n                                        testOnCreateUserHook: true});\n\n      test.isTrue(userId);\n      var user = Meteor.users.findOne(userId);\n      test.equal(user.profile.touchedByOnCreateUser, true);\n    });\n\n\n  Tinytest.add(\n    'passwords - setPassword',\n    function (test) {\n      var username = Random.id();\n      var email = username + '-intercept@example.com';\n\n      var userId = Accounts.createUser({username: username, email: email});\n\n      var user = Meteor.users.findOne(userId);\n      // no services yet.\n      test.equal(user.services.password, undefined);\n\n      // set a new password.\n      Accounts.setPassword(userId, 'new password');\n      user = Meteor.users.findOne(userId);\n      var oldSaltedHash = user.services.password.bcrypt;\n      test.isTrue(oldSaltedHash);\n\n      // Send a reset password email (setting a reset token) and insert a login\n      // token.\n      Accounts.sendResetPasswordEmail(userId, email);\n      Accounts._insertLoginToken(userId, Accounts._generateStampedLoginToken());\n      test.isTrue(Meteor.users.findOne(userId).services.password.reset);\n      test.isTrue(Meteor.users.findOne(userId).services.resume.loginTokens);\n\n      // reset with the same password, see we get a different salted hash\n      Accounts.setPassword(userId, 'new password', {logout: false});\n      user = Meteor.users.findOne(userId);\n      var newSaltedHash = user.services.password.bcrypt;\n      test.isTrue(newSaltedHash);\n      test.notEqual(oldSaltedHash, newSaltedHash);\n      // No more reset token.\n      test.isFalse(Meteor.users.findOne(userId).services.password.reset);\n      // But loginTokens are still here since we did logout: false.\n      test.isTrue(Meteor.users.findOne(userId).services.resume.loginTokens);\n\n      // reset again, see that the login tokens are gone.\n      Accounts.setPassword(userId, 'new password');\n      user = Meteor.users.findOne(userId);\n      var newerSaltedHash = user.services.password.bcrypt;\n      test.isTrue(newerSaltedHash);\n      test.notEqual(oldSaltedHash, newerSaltedHash);\n      test.notEqual(newSaltedHash, newerSaltedHash);\n      // No more tokens.\n      test.isFalse(Meteor.users.findOne(userId).services.password.reset);\n      test.isFalse(Meteor.users.findOne(userId).services.resume.loginTokens);\n\n      // cleanup\n      Meteor.users.remove(userId);\n    });\n\n\n  // This test properly belongs in accounts-base/accounts_tests.js, but\n  // this is where the tests that actually log in are.\n  Tinytest.add('accounts - user() out of context', function (test) {\n    // basic server context, no method.\n    test.throws(function () {\n      Meteor.user();\n    });\n  });\n\n  // XXX would be nice to test\n  // Accounts.config({forbidClientAccountCreation: true})\n\n  Tinytest.addAsync(\n    'passwords - login token observes get cleaned up',\n    function (test, onComplete) {\n      var username = Random.id();\n      Accounts.createUser({\n        username: username,\n        password: 'password'\n      });\n\n      makeTestConnection(\n        test,\n        function (clientConn, serverConn) {\n          serverConn.onClose(function () {\n            test.isFalse(Accounts._getUserObserve(serverConn.id));\n            onComplete();\n          });\n          var result = clientConn.call('login', {\n            user: {username: username},\n            password: 'password'\n          });\n          test.isTrue(result);\n          var token = Accounts._getAccountData(serverConn.id, 'loginToken');\n          test.isTrue(token);\n\n          // We poll here, instead of just checking `_getUserObserve`\n          // once, because the login method defers the creation of the\n          // observe, and setting up the observe yields, so we could end\n          // up here before the observe has been set up.\n          simplePoll(\n            function () {\n              return !! Accounts._getUserObserve(serverConn.id);\n            },\n            function () {\n              test.isTrue(Accounts._getUserObserve(serverConn.id));\n              clientConn.disconnect();\n            },\n            function () {\n              test.fail(\"timed out waiting for user observe for connection \" +\n                        serverConn.id);\n              onComplete();\n            }\n          );\n        },\n        onComplete\n      );\n    }\n  );\n\n  Tinytest.add(\n    'passwords - reset password doesn\\t work if email changed after email sent',\n    function (test) {\n      var username = Random.id();\n      var email = username + '-intercept@example.com';\n\n      var userId = Accounts.createUser({\n        username: username,\n        email: email,\n        password: \"old-password\"\n      });\n\n      var user = Meteor.users.findOne(userId);\n\n      Accounts.sendResetPasswordEmail(userId, email);\n\n      var resetPasswordEmailOptions =\n        Meteor.call(\"getInterceptedEmails\", email)[0];\n\n      var re = new RegExp(Meteor.absoluteUrl() + \"#/reset-password/(\\\\S*)\");\n      var match = resetPasswordEmailOptions.text.match(re);\n      test.isTrue(match);\n      var resetPasswordToken = match[1];\n\n      var newEmail = Random.id() + '-new@example.com';\n      Meteor.users.update(userId, {$set: {\"emails.0.address\": newEmail}});\n\n      test.throws(function () {\n        Meteor.call(\"resetPassword\", resetPasswordToken, \"new-password\");\n      }, /Token has invalid email address/);\n      test.throws(function () {\n        Meteor.call(\"login\", {user: {username: username}, password: \"new-password\"});\n      }, /Incorrect password/);\n    });\n\n  // We should be able to change the username\n  Tinytest.add(\"passwords - change username\", function (test) {\n    var username = Random.id();\n    var userId = Accounts.createUser({\n      username: username\n    });\n\n    test.isTrue(userId);\n\n    var newUsername = Random.id();\n    Accounts.setUsername(userId, newUsername);\n\n    test.equal(Accounts._findUserByQuery({id: userId}).username, newUsername);\n\n    // Test findUserByUsername as well while we're here\n    test.equal(Accounts.findUserByUsername(newUsername)._id, userId);\n  });\n\n  Tinytest.add(\"passwords - change username to a new one only differing \" +\n      \"in case\", function (test) {\n    var username = Random.id() + \"user\";\n    var userId = Accounts.createUser({\n      username: username.toUpperCase()\n    });\n\n    test.isTrue(userId);\n\n    var newUsername = username.toLowerCase();\n    Accounts.setUsername(userId, newUsername);\n\n    test.equal(Accounts._findUserByQuery({id: userId}).username, newUsername);\n  });\n\n  // We should not be able to change the username to one that only\n  // differs in case from an existing one\n  Tinytest.add(\"passwords - change username should fail when there are \" +\n      \"existing users with a username only differing in case\", function (test) {\n    var username = Random.id() + \"user\";\n    var usernameUpper = username.toUpperCase();\n\n    var userId1 = Accounts.createUser({\n      username: username\n    });\n\n    var user2OriginalUsername = Random.id();\n    var userId2 = Accounts.createUser({\n      username: user2OriginalUsername\n    });\n\n    test.isTrue(userId1);\n    test.isTrue(userId2);\n\n    test.throws(function () {\n      Accounts.setUsername(userId2, usernameUpper);\n    }, /Username already exists/);\n\n    test.equal(Accounts._findUserByQuery({id: userId2}).username,\n      user2OriginalUsername);\n  });\n\n  Tinytest.add(\"passwords - add email\", function (test) {\n    var origEmail = Random.id() + \"@turing.com\";\n    var userId = Accounts.createUser({\n      email: origEmail\n    });\n\n    var newEmail = Random.id() + \"@turing.com\";\n    Accounts.addEmail(userId, newEmail);\n\n    var thirdEmail = Random.id() + \"@turing.com\";\n    Accounts.addEmail(userId, thirdEmail, true);\n\n    test.equal(Accounts._findUserByQuery({id: userId}).emails, [\n      { address: origEmail, verified: false },\n      { address: newEmail, verified: false },\n      { address: thirdEmail, verified: true }\n    ]);\n\n    // Test findUserByEmail as well while we're here\n    test.equal(Accounts.findUserByEmail(origEmail)._id, userId);\n  });\n\n  Tinytest.add(\"passwords - add email when the user has an existing email \" +\n      \"only differing in case\", function (test) {\n    var origEmail = Random.id() + \"@turing.com\";\n    var userId = Accounts.createUser({\n      email: origEmail\n    });\n\n    var newEmail = Random.id() + \"@turing.com\";\n    Accounts.addEmail(userId, newEmail);\n\n    var thirdEmail = origEmail.toUpperCase();\n    Accounts.addEmail(userId, thirdEmail, true);\n\n    test.equal(Accounts._findUserByQuery({id: userId}).emails, [\n      { address: thirdEmail, verified: true },\n      { address: newEmail, verified: false }\n    ]);\n  });\n\n  Tinytest.add(\"passwords - add email should fail when there is an existing \" +\n      \"user with an email only differing in case\", function (test) {\n    var user1Email = Random.id() + \"@turing.com\";\n    var userId1 = Accounts.createUser({\n      email: user1Email\n    });\n\n    var user2Email = Random.id() + \"@turing.com\";\n    var userId2 = Accounts.createUser({\n      email: user2Email\n    });\n\n    var dupEmail = user1Email.toUpperCase();\n    test.throws(function () {\n      Accounts.addEmail(userId2, dupEmail);\n    }, /Email already exists/);\n\n    test.equal(Accounts._findUserByQuery({id: userId1}).emails, [\n      { address: user1Email, verified: false }\n    ]);\n\n    test.equal(Accounts._findUserByQuery({id: userId2}).emails, [\n      { address: user2Email, verified: false }\n    ]);\n  });\n\n  Tinytest.add(\"passwords - remove email\", function (test) {\n    var origEmail = Random.id() + \"@turing.com\";\n    var userId = Accounts.createUser({\n      email: origEmail\n    });\n\n    var newEmail = Random.id() + \"@turing.com\";\n    Accounts.addEmail(userId, newEmail);\n\n    var thirdEmail = Random.id() + \"@turing.com\";\n    Accounts.addEmail(userId, thirdEmail, true);\n\n    test.equal(Accounts._findUserByQuery({id: userId}).emails, [\n      { address: origEmail, verified: false },\n      { address: newEmail, verified: false },\n      { address: thirdEmail, verified: true }\n    ]);\n\n    Accounts.removeEmail(userId, newEmail);\n\n    test.equal(Accounts._findUserByQuery({id: userId}).emails, [\n      { address: origEmail, verified: false },\n      { address: thirdEmail, verified: true }\n    ]);\n\n    Accounts.removeEmail(userId, origEmail);\n\n    test.equal(Accounts._findUserByQuery({id: userId}).emails, [\n      { address: thirdEmail, verified: true }\n    ]);\n  });\n\n}) ();\n"
  },
  {
    "path": "packages/accounts-password/password_tests_setup.js",
    "content": "Accounts.validateNewUser(function (user) {\n  if (user.profile && user.profile.invalidAndThrowException)\n    throw new Meteor.Error(403, \"An exception thrown within Accounts.validateNewUser\");\n  return !(user.profile && user.profile.invalid);\n});\n\nAccounts.onCreateUser(function (options, user) {\n  if (options.testOnCreateUserHook) {\n    user.profile = user.profile || {};\n    user.profile.touchedByOnCreateUser = true;\n    return user;\n  } else {\n    return 'TEST DEFAULT HOOK';\n  }\n});\n\n\n// connection id -> action\nvar invalidateLogins = {};\n\n\nMeteor.methods({\n  testInvalidateLogins: function (action) {\n    if (action)\n      invalidateLogins[this.connection.id] = action;\n    else\n      delete invalidateLogins[this.connection.id];\n  }\n});\n\n\nAccounts.validateLoginAttempt(function (attempt) {\n  var action =\n    attempt &&\n    attempt.connection &&\n    invalidateLogins[attempt.connection.id];\n\n  if (! action)\n    return true;\n  else if (action === 'fail')\n    return false;\n  else if (action === 'hide')\n    throw new Meteor.Error(403, 'hide actual error');\n  else\n    throw new Error('unknown action: ' + action);\n});\n\n\n// connection id -> [{successful: boolean, attempt: object}]\nvar capturedLogins = {};\n\nMeteor.methods({\n  testCaptureLogins: function () {\n    capturedLogins[this.connection.id] = [];\n  },\n\n  testCaptureLogouts: function() {\n    capturedLogouts = [];\n  },\n\n  testFetchCapturedLogins: function () {\n    if (capturedLogins[this.connection.id]) {\n      var logins = capturedLogins[this.connection.id];\n      delete capturedLogins[this.connection.id];\n      return logins;\n    }\n    else\n      return [];\n  },\n\n  testFetchCapturedLogouts: function() {\n    return capturedLogouts;\n  }\n});\n\nAccounts.onLogin(function (attempt) {\n  if (!attempt.connection) // if login method called from the server\n    return;\n\n  if (capturedLogins[attempt.connection.id])\n    capturedLogins[attempt.connection.id].push({\n      successful: true,\n      attempt: _.omit(attempt, 'connection')\n    });\n});\n\nAccounts.onLoginFailure(function (attempt) {\n  if (!attempt.connection) // if login method called from the server\n    return;\n\n  if (capturedLogins[attempt.connection.id]) {\n    capturedLogins[attempt.connection.id].push({\n      successful: false,\n      attempt: _.omit(attempt, 'connection')\n    });\n  }\n});\n\nvar capturedLogouts = [];\n\nAccounts.onLogout(function() {\n  capturedLogouts.push({\n    successful: true\n  });\n});\n\n// Because this is global state that affects every client, we can't turn\n// it on and off during the tests. Doing so would mean two simultaneous\n// test runs could collide with each other.\n//\n// We should probably have some sort of server-isolation between\n// multiple test runs. Perhaps a separate server instance per run. This\n// problem isn't unique to this test, there are other places in the code\n// where we do various hacky things to work around the lack of\n// server-side isolation.\n//\n// For now, we just test the one configuration state. You can comment\n// out each configuration option and see that the tests fail.\nAccounts.config({\n  sendVerificationEmail: true\n});\n\n\nMeteor.methods({\n  testMeteorUser: function () { return Meteor.user(); },\n  clearUsernameAndProfile: function () {\n    if (!this.userId)\n      throw new Error(\"Not logged in!\");\n    Meteor.users.update(this.userId,\n                        {$unset: {profile: 1, username: 1}});\n  },\n\n  expireTokens: function () {\n    Accounts._expireTokens(new Date(), this.userId);\n  },\n  removeUser: function (username) {\n    Meteor.users.remove({ \"username\": username });\n  }\n});\n\n\n// Create a user that had previously logged in with SRP.\n\nMeteor.methods({\n  testCreateSRPUser: function () {\n    var username = Random.id();\n    Meteor.users.remove({username: username});\n    var userId = Accounts.createUser({username: username});\n    Meteor.users.update(\n      userId,\n      { '$set': { 'services.password.srp': {\n          \"identity\" : \"iPNrshUEcpOSO5fRDu7o4RRDc9OJBCGGljYpcXCuyg9\",\n          \"salt\" : \"Dk3lFggdEtcHU3aKm6Odx7sdcaIrMskQxBbqtBtFzt6\",\n          \"verifier\" : \"2e8bce266b1357edf6952cc56d979db19f699ced97edfb2854b95972f820b0c7006c1a18e98aad40edf3fe111b87c52ef7dd06b320ce452d01376df2d560fdc4d8e74f7a97bca1f67b3cfaef34dee34dd6c76571c247d762624dc166dab5499da06bc9358528efa75bf74e2e7f5a80d09e60acf8856069ae5cfb080f2239ee76\"\n      } } }\n    );\n    return username;\n  },\n\n  testSRPUpgrade: function (username) {\n    var user = Meteor.users.findOne({username: username});\n    if (user.services && user.services.password && user.services.password.srp)\n      throw new Error(\"srp wasn't removed\");\n    if (!(user.services && user.services.password && user.services.password.bcrypt))\n      throw new Error(\"bcrypt wasn't added\");\n  },\n\n  testNoSRPUpgrade: function (username) {\n    var user = Meteor.users.findOne({username: username});\n    if (user.services && user.services.password && user.services.password.bcrypt)\n      throw new Error(\"bcrypt was added\");\n    if (user.services && user.services.password && ! user.services.password.srp)\n      throw new Error(\"srp was removed\");\n  }\n});\n"
  },
  {
    "path": "packages/accounts-twitter/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/accounts-twitter/README.md",
    "content": "# accounts-twitter\n\nA login service for Twitter. See the [project page](https://www.meteor.com/accounts) on Meteor Accounts for more details.\n"
  },
  {
    "path": "packages/accounts-twitter/package.js",
    "content": "Package.describe({\n  summary: \"Login service for Twitter accounts\",\n  version: \"1.0.10\"\n});\n\nPackage.onUse(function(api) {\n  api.use('underscore', ['server']);\n  api.use('accounts-base', ['client', 'server']);\n  // Export Accounts (etc) to packages using this one.\n  api.imply('accounts-base', ['client', 'server']);\n  api.use('accounts-oauth', ['client', 'server']);\n  api.use('twitter', ['client', 'server']);\n\n  api.use('http', ['client', 'server']);\n\n  api.addFiles('twitter_login_button.css', 'client');\n\n  api.addFiles(\"twitter.js\");\n});\n"
  },
  {
    "path": "packages/accounts-twitter/twitter.js",
    "content": "Accounts.oauth.registerService('twitter');\n\nif (Meteor.isClient) {\n  Meteor.loginWithTwitter = function(options, callback) {\n    // support a callback without options\n    if (! callback && typeof options === \"function\") {\n      callback = options;\n      options = null;\n    }\n\n    var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback);\n    Twitter.requestCredential(options, credentialRequestCompleteCallback);\n  };\n} else {\n  var autopublishedFields = _.map(\n    // don't send access token. https://dev.twitter.com/discussions/5025\n    Twitter.whitelistedFields.concat(['id', 'screenName']),\n    function (subfield) { return 'services.twitter.' + subfield; });\n\n  Accounts.addAutopublishFields({\n    forLoggedInUser: autopublishedFields,\n    forOtherUsers: autopublishedFields\n  });\n}\n"
  },
  {
    "path": "packages/accounts-twitter/twitter_login_button.css",
    "content": "#login-buttons-image-twitter {\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAByklEQVQ4jaVTz0sbQRh92V10l006GaKJCtEtmqMYU0Qpwqb4B6zgXdT0WEr7B0ih4MGLP05CUWMvHkQwglhvGhsvKmJOBhTUQjWU2slilKarrAfdZROTQ8m7fPMx33szb75vXKZpohpwVbEBCNaCMUYopXppAWOMxDNsOPf3H1WIeDoSURYYYwQAKKW6y7KgLe2vam11KyMRZcEpEP6SOkwbUgc4ATAKUF8YW2fXhZejvaHPsc7gvH2DnCfQGEtdxrd/5NRJteUDpVTf+5kLp2WlA6JsCyZv9ChplPKdTfJZkYWhEF3bvnV3fb36NZSY3dP6Q/5V4hFvIAaKPckE8W5pLBIQdwHAthBdPtpJuhpeAwDu74DrP4/R1/Ts4cwBWg/gN+DowoSqTBPezAMAeAHw+suSw4Q7schFApF6af19a+2yLVIB7xR+0Zk75yCveu82FMnMViKHCXcSa3PPVBJAX5BszL2SP2kNwvdy5M1e+S2AogME4HFYPibPpxKZC03nRAp/M+Dx2UWDzTXfpttrx72ikCoVtrrAAwgdXBk9iazxxtpskfhs1O86aHXXpAEcA7ivJGDBDcDnyAsA2FMsi1KB/0bVv/EBBBSY9mZ7PAsAAAAASUVORK5CYII=);\n}\n"
  },
  {
    "path": "packages/accounts-ui/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/accounts-ui/README.md",
    "content": "# accounts-ui\n\nA turn-key user interface for Meteor Accounts.\n\nTo add Accounts and a set of login controls to an application, add the `accounts-ui`\npackage and at least one login provider package:\n`accounts-password`, `accounts-facebook`, `accounts-github`,\n`accounts-google`, `accounts-twitter`, or `accounts-weibo`.\n\nThen simply add the `{{> loginButtons}}` helper to an HTML file.\n\nSee the Meteor Accounts [project page](https://www.meteor.com/accounts) for more info.\n\n## Details\n\nAdding the `{{> loginButtons}}` helper to an HTML file will\nplace a login widget on the page. If there is only one provider configured\nand it is an external service, this will add a login/logout button. If you use\n`accounts-password` or use multiple external login services, this will add\na \"Sign in\" link which opens a dropdown menu with login options. If you plan to\nposition the login dropdown in the right edge of the screen, use\n`{{> loginButtons align=\"right\"}}` in order to get the dropdown to lay\nitself out without expanding off the edge of the screen.\n\nTo configure the behavior of `{{> loginButtons}}`, use\n[`Accounts.ui.config`](http://docs.meteor.com/#accounts_ui_config).\n\n`accounts-ui` also includes modal popup dialogs to handle links from\n[`sendResetPasswordEmail`](http://docs.meteor.com/#accounts_sendresetpasswordemail), [`sendVerificationEmail`](http://docs.meteor.com/#accounts_sendverificationemail),\nand [`sendEnrollmentEmail`](http://docs.meteor.com/#accounts_sendenrollmentemail). These\ndo not have to be manually placed in HTML: they are automatically activated\nwhen the URLs are loaded.\n\nSee the Meteor Accounts [project page](https://www.meteor.com/accounts) for more info."
  },
  {
    "path": "packages/accounts-ui/login_buttons.less",
    "content": "@import \"{accounts-ui-unstyled}/login_buttons.import.less\";\n"
  },
  {
    "path": "packages/accounts-ui/package.js",
    "content": "Package.describe({\n  summary: \"Simple templates to add login widgets to an app\",\n  version: \"1.1.9\"\n});\n\nPackage.onUse(function (api) {\n  // Export Accounts (etc) to packages using this one.\n  api.imply('accounts-base', ['client', 'server']);\n  api.use('accounts-ui-unstyled', 'client');\n  api.use('less', 'client');\n\n  api.addFiles(['login_buttons.less'], 'client');\n});\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/README.md",
    "content": "# accounts-ui-unstyled\n\nA version of `accounts-ui` without the CSS, so that you can add your\nown styling. See the [`accounts-ui`\nREADME](https://atmospherejs.com/meteor/accounts-ui) and the\nMeteor Accounts [project page](https://www.meteor.com/accounts) for\ndetails."
  },
  {
    "path": "packages/accounts-ui-unstyled/accounts_ui.js",
    "content": "/**\n * @summary Accounts UI\n * @namespace\n * @memberOf Accounts\n * @importFromPackage accounts-base\n */\nAccounts.ui = {};\n\nAccounts.ui._options = {\n  requestPermissions: {},\n  requestOfflineToken: {},\n  forceApprovalPrompt: {}\n};\n\n// XXX refactor duplicated code in this function\n\n/**\n * @summary Configure the behavior of [`{{> loginButtons}}`](#accountsui).\n * @locus Client\n * @param {Object} options\n * @param {Object} options.requestPermissions Which [permissions](#requestpermissions) to request from the user for each external service.\n * @param {Object} options.requestOfflineToken To ask the user for permission to act on their behalf when offline, map the relevant external service to `true`. Currently only supported with Google. See [Meteor.loginWithExternalService](#meteor_loginwithexternalservice) for more details.\n * @param {Object} options.forceApprovalPrompt If true, forces the user to approve the app's permissions, even if previously approved. Currently only supported with Google.\n * @param {String} options.passwordSignupFields Which fields to display in the user creation form. One of '`USERNAME_AND_EMAIL`', '`USERNAME_AND_OPTIONAL_EMAIL`', '`USERNAME_ONLY`', or '`EMAIL_ONLY`' (default).\n * @importFromPackage accounts-base\n */\nAccounts.ui.config = function(options) {\n  // validate options keys\n  var VALID_KEYS = ['passwordSignupFields', 'requestPermissions', 'requestOfflineToken', 'forceApprovalPrompt'];\n  _.each(_.keys(options), function (key) {\n    if (!_.contains(VALID_KEYS, key))\n      throw new Error(\"Accounts.ui.config: Invalid key: \" + key);\n  });\n\n  // deal with `passwordSignupFields`\n  if (options.passwordSignupFields) {\n    if (_.contains([\n      \"USERNAME_AND_EMAIL\",\n      \"USERNAME_AND_OPTIONAL_EMAIL\",\n      \"USERNAME_ONLY\",\n      \"EMAIL_ONLY\"\n    ], options.passwordSignupFields)) {\n      if (Accounts.ui._options.passwordSignupFields)\n        throw new Error(\"Accounts.ui.config: Can't set `passwordSignupFields` more than once\");\n      else\n        Accounts.ui._options.passwordSignupFields = options.passwordSignupFields;\n    } else {\n      throw new Error(\"Accounts.ui.config: Invalid option for `passwordSignupFields`: \" + options.passwordSignupFields);\n    }\n  }\n\n  // deal with `requestPermissions`\n  if (options.requestPermissions) {\n    _.each(options.requestPermissions, function (scope, service) {\n      if (Accounts.ui._options.requestPermissions[service]) {\n        throw new Error(\"Accounts.ui.config: Can't set `requestPermissions` more than once for \" + service);\n      } else if (!(scope instanceof Array)) {\n        throw new Error(\"Accounts.ui.config: Value for `requestPermissions` must be an array\");\n      } else {\n        Accounts.ui._options.requestPermissions[service] = scope;\n      }\n    });\n  }\n\n  // deal with `requestOfflineToken`\n  if (options.requestOfflineToken) {\n    _.each(options.requestOfflineToken, function (value, service) {\n      if (service !== 'google')\n        throw new Error(\"Accounts.ui.config: `requestOfflineToken` only supported for Google login at the moment.\");\n\n      if (Accounts.ui._options.requestOfflineToken[service]) {\n        throw new Error(\"Accounts.ui.config: Can't set `requestOfflineToken` more than once for \" + service);\n      } else {\n        Accounts.ui._options.requestOfflineToken[service] = value;\n      }\n    });\n  }\n\n  // deal with `forceApprovalPrompt`\n  if (options.forceApprovalPrompt) {\n    _.each(options.forceApprovalPrompt, function (value, service) {\n      if (service !== 'google')\n        throw new Error(\"Accounts.ui.config: `forceApprovalPrompt` only supported for Google login at the moment.\");\n\n      if (Accounts.ui._options.forceApprovalPrompt[service]) {\n        throw new Error(\"Accounts.ui.config: Can't set `forceApprovalPrompt` more than once for \" + service);\n      } else {\n        Accounts.ui._options.forceApprovalPrompt[service] = value;\n      }\n    });\n  }\n};\n\npasswordSignupFields = function () {\n  return Accounts.ui._options.passwordSignupFields || \"EMAIL_ONLY\";\n};\n\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/accounts_ui_tests.js",
    "content": "// XXX Most of the testing of accounts-ui is done manually, across\n// multiple browsers using examples/unfinished/accounts-ui-helper. We\n// should *definitely* automate this, but Tinytest is generally not\n// the right abstraction to use for this.\n\n\n// XXX it'd be cool to also test that the right thing happens if options\n// *are* validated, but Accounts.ui._options is global state which makes this hard\n// (impossible?)\nTinytest.add('accounts-ui - config validates keys', function (test) {\n  test.throws(function () {\n    Accounts.ui.config({foo: \"bar\"});\n  });\n\n  test.throws(function () {\n    Accounts.ui.config({passwordSignupFields: \"not a valid option\"});\n  });\n\n  test.throws(function () {\n    Accounts.ui.config({requestPermissions: {facebook: \"not an array\"}});\n  });\n\n  test.throws(function () {\n    Accounts.ui.config({forceApprovalPrompt: {facebook: \"only google\"}});\n  });\n});\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/login_buttons.html",
    "content": "<template name=\"loginButtons\">\n  <div id=\"login-buttons\" class=\"login-buttons-dropdown-align-{{align}}\">\n    {{#if currentUser}}\n      {{#if loggingIn}}\n        {{! We aren't actually logged in yet; we're just setting Meteor.userId\n            optimistically during an at-startup login-with-token. We expose this\n            state so other UIs can treat it specially, but we'll just treat it\n            as logged out. }}\n        {{#if dropdown}}\n          {{> _loginButtonsLoggingIn }}\n        {{else}}\n          <div class=\"login-buttons-with-only-one-button\">\n            {{> _loginButtonsLoggingInSingleLoginButton }}\n          </div>\n        {{/if}}\n      {{else}}\n        {{> _loginButtonsLoggedIn}}\n      {{/if}}\n    {{else}}\n      {{> _loginButtonsLoggedOut}}\n    {{/if}}\n  </div>\n</template>\n\n<template name=\"_loginButtonsLoggedIn\">\n  {{#if dropdown}}\n    {{> _loginButtonsLoggedInDropdown}}\n  {{else}}\n    <div class=\"login-buttons-with-only-one-button\">\n      {{> _loginButtonsLoggedInSingleLogoutButton}}\n    </div>\n  {{/if}}\n</template>\n\n<template name=\"_loginButtonsLoggedOut\">\n  {{#if services}} {{! if at least one service is configured }}\n    {{#if configurationLoaded}}\n      {{#if dropdown}} {{! if more than one service configured, or password is configured}}\n        {{> _loginButtonsLoggedOutDropdown}}\n      {{else}}\n        {{#with singleService}} {{! at this point there must be only one configured services }}\n          <div class=\"login-buttons-with-only-one-button\">\n            {{#if loggingIn}}\n              {{> _loginButtonsLoggingInSingleLoginButton}}\n            {{else}}\n              {{> _loginButtonsLoggedOutSingleLoginButton}}\n            {{/if}}\n          </div>\n        {{/with}}\n      {{/if}}\n    {{/if}}\n  {{else}}\n    <div class=\"no-services\">No login services configured</div>\n  {{/if}}\n</template>\n\n<!-- used in various places to display messages to user -->\n<template name=\"_loginButtonsMessages\">\n  {{#if errorMessage}}\n    <div class=\"message error-message\">{{errorMessage}}</div>\n  {{/if}}\n  {{#if infoMessage}}\n    <div class=\"message info-message\">{{infoMessage}}</div>\n  {{/if}}\n</template>\n\n<template name=\"_loginButtonsLoggingIn\">\n  {{> _loginButtonsLoggingInPadding}}\n  <div class=\"loading\">&nbsp;</div>\n  {{> _loginButtonsLoggingInPadding}}\n</template>\n\n<template name=\"_loginButtonsLoggingInPadding\">\n  {{#unless dropdown}}\n    {{! invisible div used for correct height of surrounding div. this ensures\n        that the _loginButtons template is always the same height\n        and the rest of the page doesn't move up and down }}\n    <div class=\"login-buttons-padding\">\n      <div class=\"login-button single-login-button\" style=\"visibility: hidden;\" id=\"login-buttons-logout\">&nbsp;</div>\n    </div>\n  {{else}}\n    {{! just add some padding }}\n    <div class=\"login-buttons-padding\"></div>\n  {{/unless}}\n</template>\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/login_buttons.import.less",
    "content": "//////////////////// MIXINS\n\n// Minimal, well-documented, general-purpose CSS mixins.\n// (Some are same as Bootstrap.)\n\n////////// Box-Sizing: Border-Box\n\n// Setting `box-sizing: border-box` on an element causes the CSS\n// layout algorithm to interpret `width` and `height` declarations\n// as referring to the size of the border box (outside the border),\n// not the content box as usual (inside the padding).\n//\n// This is especially useful for stretching a form element to the\n// width of its container even if the form element has arbitrary\n// padding and borders, which can be done using `width: 100%`.\n//\n// Browser support is IE 8+ and all modern browsers, with the caveat\n// that `-moz-box-sizing` in Firefox is considered to have some\n// buggy or non-compliant behavior.  For example, min/max-width/height\n// may not interact correctly. See\n// https://bugzilla.mozilla.org/show_bug.cgi?id=243412.\n.box-sizing-by-border () {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\n////////// Box-Shadow\n\n.box-shadow (...) {\n  box-shadow: @arguments;\n  -webkit-box-shadow: @arguments; // For Android\n}\n\n////////// Unselectable\n\n.unselectable () {\n  -webkit-user-select: none; // Chrome/Safari\n  -moz-user-select: none; // Firefox\n  -ms-user-select: none; // IE10+\n\n  // These delarations not implemented in browsers yet:\n  -o-user-select: none;\n  user-select: none;\n\n  // In IE <= 9 and Opera, need unselectable=\"on\" in the HTML.\n}\n\n//////////////////// LOGIN BUTTONS\n\n@login-buttons-accounts-dialog-width: 250px;\n@login-buttons-color: #596595;\n@login-buttons-color-border: darken(@login-buttons-color, 10%);\n@login-buttons-color-active: lighten(@login-buttons-color, 10%);\n@login-buttons-color-active-border: darken(@login-buttons-color-active, 10%);\n\n@login-buttons-config-color: darken(#f53, 10%);\n@login-buttons-config-color-border: darken(@login-buttons-config-color, 10%);\n@login-buttons-config-color-active: lighten(@login-buttons-config-color, 10%);\n@login-buttons-config-color-active-border: darken(@login-buttons-config-color-active, 10%);\n\n#login-buttons {\n\n  display: inline-block;\n  margin-right: 0.2px; // Fixes display on IE8: http://www.compsoft.co.uk/Blog/2009/11/inline-block-not-quite-inline-blocking.html\n\n  // This seems to keep the height of the line from\n  // being sensitive to the presence of the unicode down arrow,\n  // which otherwise bumps the baseline down by 1px.\n  line-height: 1;\n\n  .login-button {\n    position: relative; // so that we can position the image absolutely within the button\n  }\n\n  .login-buttons-with-only-one-button {\n    display: inline-block;\n    .login-button { display: inline-block; }\n    .login-text-and-button {\n      display: inline-block;\n    }\n  }\n\n  .login-display-name {\n    display: inline-block;\n    padding-right: 2px;\n    line-height: 1.5;\n    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;\n  }\n  .loading {\n    line-height: 1;\n    background-image: url(data:image/gif;base64,R0lGODlhEAALAPQAAP///wAAANra2tDQ0Orq6gYGBgAAAC4uLoKCgmBgYLq6uiIiIkpKSoqKimRkZL6+viYmJgQEBE5OTubm5tjY2PT09Dg4ONzc3PLy8ra2tqCgoMrKyu7u7gAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCwAAACwAAAAAEAALAAAFLSAgjmRpnqSgCuLKAq5AEIM4zDVw03ve27ifDgfkEYe04kDIDC5zrtYKRa2WQgAh+QQJCwAAACwAAAAAEAALAAAFJGBhGAVgnqhpHIeRvsDawqns0qeN5+y967tYLyicBYE7EYkYAgAh+QQJCwAAACwAAAAAEAALAAAFNiAgjothLOOIJAkiGgxjpGKiKMkbz7SN6zIawJcDwIK9W/HISxGBzdHTuBNOmcJVCyoUlk7CEAAh+QQJCwAAACwAAAAAEAALAAAFNSAgjqQIRRFUAo3jNGIkSdHqPI8Tz3V55zuaDacDyIQ+YrBH+hWPzJFzOQQaeavWi7oqnVIhACH5BAkLAAAALAAAAAAQAAsAAAUyICCOZGme1rJY5kRRk7hI0mJSVUXJtF3iOl7tltsBZsNfUegjAY3I5sgFY55KqdX1GgIAIfkECQsAAAAsAAAAABAACwAABTcgII5kaZ4kcV2EqLJipmnZhWGXaOOitm2aXQ4g7P2Ct2ER4AMul00kj5g0Al8tADY2y6C+4FIIACH5BAkLAAAALAAAAAAQAAsAAAUvICCOZGme5ERRk6iy7qpyHCVStA3gNa/7txxwlwv2isSacYUc+l4tADQGQ1mvpBAAIfkECQsAAAAsAAAAABAACwAABS8gII5kaZ7kRFGTqLLuqnIcJVK0DeA1r/u3HHCXC/aKxJpxhRz6Xi0ANAZDWa+kEAA7AAAAAAAAAAAA);\n    width: 16px;\n    background-position: center center;\n    background-repeat: no-repeat;\n  }\n}\n\n#login-buttons .login-button, .accounts-dialog .login-button {\n  cursor: pointer;\n  .unselectable();\n  padding: 4px 8px;\n\n  font-size: 80%;\n  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;\n  line-height: 1.5;\n\n  text-align: center;\n  color: #fff;\n\n  background: @login-buttons-color;\n  border: 1px solid @login-buttons-color-border;\n\n  border-radius: 4px;\n\n  &:hover {\n    background: @login-buttons-color-active;\n  }\n  &:active {\n    background: @login-buttons-color-active;\n    .box-shadow(0 2px 3px 0 rgba(0, 0, 0, 0.2) inset);\n  }\n\n  &.login-button-disabled, &.login-button-disabled:active {\n    color: #ddd;\n    background: #aaa;\n    border: 1px solid lighten(#aaa, 10%);\n    .box-shadow(none);\n  }\n}\n\n// precendence of this selector is significant\n.accounts-dialog * {\n  // A base for our dialog CSS, to reset browser styles and protect against\n  // the app's CSS.  Dialogs include the dropdown, config modals, and the\n  // reset password modal.  We can't completely isolate the dialogs from\n  // the app's CSS, and that isn't the goal because the app can style them.\n  // This rule is a compromise that should take precedence over some very\n  // broad rules but be overridden by more specific ones.\n\n  // Add more declarations here if they help the dialogs look good\n  // out-of-the-box in more apps.\n\n  padding: 0;\n  margin: 0;\n  line-height: inherit;\n  color: inherit;\n  font: inherit;\n\n  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;\n}\n\n.accounts-dialog .login-button {\n  width: auto;\n  margin-bottom: 4px;\n}\n\n#login-buttons {\n  .login-buttons-padding {\n    display: inline-block;\n    width: 30px;\n  }\n\n  .login-display-name { margin-right: 4px; }\n\n  .configure-button {\n    background: @login-buttons-config-color;\n    border-color: @login-buttons-config-color-border;\n\n    &:active, &:hover {\n      background: @login-buttons-config-color-active;\n      border-color: @login-buttons-config-color-active-border;\n    }\n  }\n\n  .login-image {\n    display: inline-block;\n    position: absolute;\n    left: 6px;\n    top: 6px;\n    width: 16px;\n    height: 16px;\n  }\n\n  .text-besides-image {\n    margin-left: 18px;\n  }\n\n  .no-services { color: red; }\n\n  .login-link-and-dropdown-list {\n    position: relative;\n  }\n  .login-close-text {\n    float: left;\n    position: relative;\n    padding-bottom: 8px;\n  }\n\n  .login-text-and-button .loading, .login-link-and-dropdown-list .loading {\n    display: inline-block;\n  }\n  &.login-buttons-dropdown-align-left #login-dropdown-list .loading {\n    float: right;\n  }\n  &.login-buttons-dropdown-align-right #login-dropdown-list .loading {\n    float: left;\n  }\n\n\n  .login-close-text-clear { clear: both; }\n\n  .or { text-align: center; }\n  .hline { text-decoration: line-through; color: lightgrey; }\n  .or-text { font-weight: bold; }\n\n  #signup-link { float: right; }\n  #forgot-password-link { float: left; }\n  #back-to-login-link { float: right; }\n}\n\n#login-buttons a, .accounts-dialog a {\n    cursor: pointer;\n    text-decoration: underline;\n}\n\n#login-buttons.login-buttons-dropdown-align-right .login-close-text {\n    float: right;\n}\n\n@meteor-accounts-base-padding: 8px;\n@meteor-accounts-dialog-border-width: 1px;\n\n.accounts-dialog {\n  border: @meteor-accounts-dialog-border-width solid #ccc;\n  z-index: 1000;\n  background: white;\n  border-radius: 4px;\n\n  padding: 8px 12px;\n  margin: -8px -12px 0 -12px;\n\n  width: @login-buttons-accounts-dialog-width;\n\n  .box-shadow(0 0 3px 0 rgba(0, 0, 0, 0.2));\n\n  // Labels and links inherit app's font with this line commented out:\n  //font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;\n  font-size: 16px;\n  color: #333;\n\n  // XXX Make the dropdown and dialogs look good without a top-level\n  // line-height: 1.6.  For now, we apply it to everything except\n  // the \"Close\" link, which we want to have the same line-height\n  // as the \"Sign in\" link.\n  & > * { line-height: 1.6; }\n  & > .login-close-text {\n    line-height: inherit;\n    font-size: inherit;\n    font-family: inherit;\n  }\n\n  label, .title {\n    font-size: 80%;\n    margin-top: 7px;\n    margin-bottom: -2px;\n  }\n\n  label {\n    // Bootstrap sets labels as 'display: block;'. Undo that.\n    display: inline;\n  }\n\n  input[type=text], input[type=email], input[type=password] {\n    // Be pixel-accurate in IE 8+ regardless of our borders and\n    // paddings, at the expense of IE 7.\n    // Any heights or widths applied to this element will set the\n    // size of the border box (including padding and borders)\n    // instead of the content box.  This makes it possible to\n    // do width 100%.\n    .box-sizing-by-border();\n    width: 100%;\n    // A fix purely for the \"meteor add bootstrap\" experience.\n    // Bootstrap sets \"height: 20px\" on form fields, which is too\n    // small when applied to the border box.  People have complained\n    // that Bootstrap takes this approach for the sake of IE 7:\n    // https://github.com/twitter/bootstrap/issues/2935\n    // Our work-around is to override Bootstrap's rule (with higher\n    // precedence).\n    &[type] { height: auto; }\n  }\n\n  .login-button-form-submit { margin-top: 8px; }\n  .message { font-size: 80%; margin-top: 8px; line-height: 1.3; }\n  .error-message { color: red; }\n  .info-message { color: green; }\n  .additional-link { font-size: 75%; }\n\n  .accounts-close {\n    position: absolute;\n    top: 0;\n    right: 5px;\n\n    font-size: 20px;\n    font-weight: bold;\n    line-height: 20px;\n    text-decoration: none;\n    color: #000;\n    opacity: 0.4;\n\n    &:hover {\n      opacity: 0.8;\n    }\n  }\n\n  #login-buttons-cancel-reset-password { float: right; }\n  #login-buttons-cancel-enroll-account { float: right; }\n}\n\n#login-dropdown-list {\n  position: absolute;\n  // The top-left of the border-box of the dropdown is absolutely\n  // positioned within its container, so we need to compensate\n  // for the border.  The padding is already compensated for by\n  // negative margins on the dropdown.\n  // XXX We could use negative margins to compensate for the\n  // border too.\n  top: -@meteor-accounts-dialog-border-width;\n  left: -@meteor-accounts-dialog-border-width;\n}\n\n#login-buttons.login-buttons-dropdown-align-right #login-dropdown-list {\n  left: auto;\n  right: -@meteor-accounts-dialog-border-width;\n}\n\n#login-buttons-message-dialog .message {\n    /* we intentionally want it bigger on this dialog since it's the only thing displayed */\n    font-size: 100%;\n}\n\n.accounts-centered-dialog {\n  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;\n\n  z-index: 1001;\n  position: fixed;\n\n  left: 50%;\n  margin-left: -(@login-buttons-accounts-dialog-width\n               + @meteor-accounts-base-padding) / 2;\n\n  top: 50%;\n  margin-top: -40px; /* = approximately -height/2, though height can change */\n}\n\n@configure-login-service-dialog-width: 530px;\n\n#configure-login-service-dialog {\n  width: @configure-login-service-dialog-width;\n  margin-left: -(@configure-login-service-dialog-width\n               + @meteor-accounts-base-padding) / 2;\n  margin-top: -300px; /* = approximately -height/2, though height can change */\n\n  table { width: 100%; }\n  input[type=text] {\n    width: 100%;\n    font-family: \"Courier New\", Courier, monospace;\n  }\n  ol {\n    margin-top: 10px;\n    margin-bottom: 10px;\n\n    li { margin-left: 30px; }\n  }\n  .configuration_labels { width: 30%; }\n  .configuration_inputs { width: 70%; }\n  .new-section { margin-top: 10px; }\n  .url { font-family: \"Courier New\", Courier, monospace; }\n}\n\n#configure-login-service-dialog-save-configuration {\n  float: right;\n}\n\n.configure-login-service-dismiss-button {\n  float: left;\n}\n\n#just-verified-dismiss-button, #messages-dialog-dismiss-button {\n  margin-top: 8px;\n}\n\n.hide-background {\n  position: fixed;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  z-index: 999;\n\n  /* XXX consider replacing with DXImageTransform */\n  background-color: rgb(0.2, 0.2, 0.2); /* fallback for IE7-8 */\n\n  background-color: rgba(0, 0, 0, 0.7);\n}\n\n#login-buttons, .accounts-dialog {\n  input[type=text], input[type=email], input[type=password] {\n    padding: 4px;\n    border: 1px solid #aaa;\n    border-radius: 3px;\n    line-height: 1;\n  }\n}\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/login_buttons.js",
    "content": "// for convenience\nvar loginButtonsSession = Accounts._loginButtonsSession;\n\n// shared between dropdown and single mode\nTemplate.loginButtons.events({\n  'click #login-buttons-logout': function() {\n    Meteor.logout(function () {\n      loginButtonsSession.closeDropdown();\n    });\n  }\n});\n\nTemplate.registerHelper('loginButtons', function () {\n  throw new Error(\"Use {{> loginButtons}} instead of {{loginButtons}}\");\n});\n\n//\n// helpers\n//\n\ndisplayName = function () {\n  var user = Meteor.user();\n  if (!user)\n    return '';\n\n  if (user.profile && user.profile.name)\n    return user.profile.name;\n  if (user.username)\n    return user.username;\n  if (user.emails && user.emails[0] && user.emails[0].address)\n    return user.emails[0].address;\n\n  return '';\n};\n\n// returns an array of the login services used by this app. each\n// element of the array is an object (eg {name: 'facebook'}), since\n// that makes it useful in combination with handlebars {{#each}}.\n//\n// don't cache the output of this function: if called during startup (before\n// oauth packages load) it might not include them all.\n//\n// NOTE: It is very important to have this return password last\n// because of the way we render the different providers in\n// login_buttons_dropdown.html\ngetLoginServices = function () {\n  var self = this;\n\n  // First look for OAuth services.\n  var services = Package['accounts-oauth'] ? Accounts.oauth.serviceNames() : [];\n\n  // Be equally kind to all login services. This also preserves\n  // backwards-compatibility. (But maybe order should be\n  // configurable?)\n  services.sort();\n\n  // Add password, if it's there; it must come last.\n  if (hasPasswordService())\n    services.push('password');\n\n  return _.map(services, function(name) {\n    return {name: name};\n  });\n};\n\nhasPasswordService = function () {\n  return !!Package['accounts-password'];\n};\n\ndropdown = function () {\n  return hasPasswordService() || getLoginServices().length > 1;\n};\n\n// XXX improve these. should this be in accounts-password instead?\n//\n// XXX these will become configurable, and will be validated on\n// the server as well.\nvalidateUsername = function (username) {\n  if (username.length >= 3) {\n    return true;\n  } else {\n    loginButtonsSession.errorMessage(\"Username must be at least 3 characters long\");\n    return false;\n  }\n};\nvalidateEmail = function (email) {\n  if (passwordSignupFields() === \"USERNAME_AND_OPTIONAL_EMAIL\" && email === '')\n    return true;\n\n  if (email.indexOf('@') !== -1) {\n    return true;\n  } else {\n    loginButtonsSession.errorMessage(\"Invalid email\");\n    return false;\n  }\n};\nvalidatePassword = function (password) {\n  if (password.length >= 6) {\n    return true;\n  } else {\n    loginButtonsSession.errorMessage(\"Password must be at least 6 characters long\");\n    return false;\n  }\n};\n\n//\n// loginButtonLoggedOut template\n//\n\nTemplate._loginButtonsLoggedOut.helpers({\n  dropdown: dropdown,\n  services: getLoginServices,\n  singleService: function () {\n    var services = getLoginServices();\n    if (services.length !== 1)\n      throw new Error(\n        \"Shouldn't be rendering this template with more than one configured service\");\n    return services[0];\n  },\n  configurationLoaded: function () {\n    return Accounts.loginServicesConfigured();\n  }\n});\n\n\n//\n// loginButtonsLoggedIn template\n//\n\n  // decide whether we should show a dropdown rather than a row of\n  // buttons\nTemplate._loginButtonsLoggedIn.helpers({\n  dropdown: dropdown\n});\n\n\n\n//\n// loginButtonsLoggedInSingleLogoutButton template\n//\n\nTemplate._loginButtonsLoggedInSingleLogoutButton.helpers({\n  displayName: displayName\n});\n\n\n\n//\n// loginButtonsMessage template\n//\n\nTemplate._loginButtonsMessages.helpers({\n  errorMessage: function () {\n    return loginButtonsSession.get('errorMessage');\n  }\n});\n\nTemplate._loginButtonsMessages.helpers({\n  infoMessage: function () {\n    return loginButtonsSession.get('infoMessage');\n  }\n});\n\n\n//\n// loginButtonsLoggingInPadding template\n//\n\nTemplate._loginButtonsLoggingInPadding.helpers({\n  dropdown: dropdown\n});\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/login_buttons_dialogs.html",
    "content": "<body>\n  {{> _resetPasswordDialog}}\n  {{> _justResetPasswordDialog}}\n  {{> _enrollAccountDialog}}\n  {{> _justVerifiedEmailDialog}}\n  {{> _configureLoginServiceDialog}}\n  {{> _configureLoginOnDesktopDialog}}\n\n  {{! if we're not showing a dropdown, we need some other place to show messages }}\n  {{> _loginButtonsMessagesDialog}}\n</body>\n\n<template name=\"_resetPasswordDialog\">\n  {{#if inResetPasswordFlow}}\n    <div class=\"hide-background\"></div>\n\n    <div class=\"accounts-dialog accounts-centered-dialog\">\n      <label id=\"reset-password-new-password-label\" for=\"reset-password-new-password\">\n        New password\n      </label>\n\n      <div class=\"reset-password-new-password-wrapper\">\n        <input id=\"reset-password-new-password\" type=\"password\" />\n      </div>\n\n      {{> _loginButtonsMessages}}\n\n      <div class=\"login-button login-button-form-submit\" id=\"login-buttons-reset-password-button\">\n        Set password\n      </div>\n\n      <a class=\"accounts-close\" id=\"login-buttons-cancel-reset-password\">&times;</a>\n    </div>\n  {{/if}}\n</template>\n\n<template name=\"_justResetPasswordDialog\">\n  {{#if visible}}\n    <div class=\"accounts-dialog accounts-centered-dialog\">\n      Password reset.\n      You are now logged in as {{displayName}}.\n      <div class=\"login-button\" id=\"just-verified-dismiss-button\">Dismiss</div>\n    </div>\n  {{/if}}\n</template>\n\n<template name=\"_enrollAccountDialog\">\n  {{#if inEnrollAccountFlow}}\n    <div class=\"hide-background\"></div>\n\n    <div class=\"accounts-dialog accounts-centered-dialog\">\n      <label id=\"enroll-account-password-label\" for=\"enroll-account-password\">\n        Choose a password\n      </label>\n\n      <div class=\"enroll-account-password-wrapper\">\n        <input id=\"enroll-account-password\" type=\"password\" />\n      </div>\n\n      {{> _loginButtonsMessages}}\n\n      <div class=\"login-button login-button-form-submit\" id=\"login-buttons-enroll-account-button\">\n        Create account\n      </div>\n\n      <a class=\"accounts-close\" id=\"login-buttons-cancel-enroll-account\">&times;</a>\n    </div>\n  {{/if}}\n</template>\n\n<template name=\"_justVerifiedEmailDialog\">\n  {{#if visible}}\n    <div class=\"accounts-dialog accounts-centered-dialog\">\n      Email verified.\n      You are now logged in as {{displayName}}.\n      <div class=\"login-button\" id=\"just-verified-dismiss-button\">Dismiss</div>\n    </div>\n  {{/if}}\n</template>\n\n<template name=\"_configureLoginServiceDialog\">\n  {{#if visible}}\n    <div id=\"configure-login-service-dialog\" class=\"accounts-dialog accounts-centered-dialog\">\n      {{> configurationSteps}}\n\n      <p>\n        Now, copy over some details.\n      </p>\n      <p>\n        <table>\n          <colgroup>\n            <col span=\"1\" class=\"configuration_labels\">\n            <col span=\"1\" class=\"configuration_inputs\">\n          </colgroup>\n          {{#each configurationFields}}\n            <tr>\n              <td>\n                <label for=\"configure-login-service-dialog-{{property}}\">{{label}}</label>\n              </td>\n              <td>\n                <input id=\"configure-login-service-dialog-{{property}}\" type=\"text\" />\n              </td>\n            </tr>\n          {{/each}}\n        </table>\n      </p>\n      <p class=\"new-section\">\n        Choose the login style:\n      </p>\n      <p>\n        &emsp;<input id=\"configure-login-service-dialog-popupBasedLogin\" type=\"radio\" checked=\"checked\" name=\"loginStyle\" value=\"popup\">\n        <label for=\"configure-login-service-dialog-popupBasedLogin\">Popup-based login (recommended for most applications)</label>\n\n        <br>&emsp;<input id=\"configure-login-service-dialog-redirectBasedLogin\" type=\"radio\" name=\"loginStyle\" value=\"redirect\">\n        <label for=\"configure-login-service-dialog-redirectBasedLogin\">\n          Redirect-based login (special cases explained\n          <a href=\"https://github.com/meteor/meteor/wiki/OAuth-for-mobile-Meteor-clients#popup-versus-redirect-flow\"\n             target=\"_blank\">here</a>)\n        </label>\n      </p>\n      <div class=\"new-section\">\n        <div class=\"login-button configure-login-service-dismiss-button\">\n          I'll do this later\n        </div>\n        <a class=\"accounts-close configure-login-service-dismiss-button\">&times;</a>\n\n        <div class=\"login-button login-button-configure {{#if saveDisabled}}login-button-disabled{{/if}}\"\n             id=\"configure-login-service-dialog-save-configuration\">\n          Save Configuration\n        </div>\n      </div>\n    </div>\n  {{/if}}\n</template>\n\n<template name=\"_loginButtonsMessagesDialog\">\n  {{#if visible}}\n    <div class=\"accounts-dialog accounts-centered-dialog\" id=\"login-buttons-message-dialog\">\n      {{> _loginButtonsMessages}}\n      <div class=\"login-button\" id=\"messages-dialog-dismiss-button\">Dismiss</div>\n    </div>\n  {{/if}}\n</template>\n\n<template name=\"_configureLoginOnDesktopDialog\">\n  {{#if visible}}\n    <div class=\"accounts-dialog accounts-centered-dialog\" id=\"configure-on-desktop-dialog\">\n      <p>\n        Please configure login on a desktop browser.\n      </p>\n      <div class=\"login-button\" id=\"configure-on-desktop-dismiss-button\">Dismiss</div>\n    </div>\n  {{/if}}\n</template>\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/login_buttons_dialogs.js",
    "content": "// for convenience\nvar loginButtonsSession = Accounts._loginButtonsSession;\n\n// since we don't want to pass around the callback that we get from our event\n// handlers, we just make it a variable for the whole file\nvar doneCallback;\n\nAccounts.onResetPasswordLink(function (token, done) {\n  loginButtonsSession.set(\"resetPasswordToken\", token);\n  doneCallback = done;\n});\n\nAccounts.onEnrollmentLink(function (token, done) {\n  loginButtonsSession.set(\"enrollAccountToken\", token);\n  doneCallback = done;\n});\n\nAccounts.onEmailVerificationLink(function (token, done) {\n  Accounts.verifyEmail(token, function (error) {\n    if (! error) {\n      loginButtonsSession.set('justVerifiedEmail', true);\n    }\n\n    done();\n    // XXX show something if there was an error.\n  });\n});\n\n\n//\n// resetPasswordDialog template\n//\n\nTemplate._resetPasswordDialog.events({\n  'click #login-buttons-reset-password-button': function () {\n    resetPassword();\n  },\n  'keypress #reset-password-new-password': function (event) {\n    if (event.keyCode === 13)\n      resetPassword();\n  },\n  'click #login-buttons-cancel-reset-password': function () {\n    loginButtonsSession.set('resetPasswordToken', null);\n    if (doneCallback)\n      doneCallback();\n  }\n});\n\nvar resetPassword = function () {\n  loginButtonsSession.resetMessages();\n  var newPassword = document.getElementById('reset-password-new-password').value;\n  if (!validatePassword(newPassword))\n    return;\n\n  Accounts.resetPassword(\n    loginButtonsSession.get('resetPasswordToken'), newPassword,\n    function (error) {\n      if (error) {\n        loginButtonsSession.errorMessage(error.reason || \"Unknown error\");\n      } else {\n        loginButtonsSession.set('resetPasswordToken', null);\n        loginButtonsSession.set('justResetPassword', true);\n        if (doneCallback)\n          doneCallback();\n      }\n    });\n};\n\nTemplate._resetPasswordDialog.helpers({\n  inResetPasswordFlow: function () {\n    return loginButtonsSession.get('resetPasswordToken');\n  }\n});\n\n//\n// justResetPasswordDialog template\n//\n\nTemplate._justResetPasswordDialog.events({\n  'click #just-verified-dismiss-button': function () {\n    loginButtonsSession.set('justResetPassword', false);\n  }\n});\n\nTemplate._justResetPasswordDialog.helpers({\n  visible: function () {\n    return loginButtonsSession.get('justResetPassword');\n  },\n  displayName: displayName\n});\n\n\n\n//\n// enrollAccountDialog template\n//\n\nTemplate._enrollAccountDialog.events({\n  'click #login-buttons-enroll-account-button': function () {\n    enrollAccount();\n  },\n  'keypress #enroll-account-password': function (event) {\n    if (event.keyCode === 13)\n      enrollAccount();\n  },\n  'click #login-buttons-cancel-enroll-account': function () {\n    loginButtonsSession.set('enrollAccountToken', null);\n    if (doneCallback)\n      doneCallback();\n  }\n});\n\nvar enrollAccount = function () {\n  loginButtonsSession.resetMessages();\n  var password = document.getElementById('enroll-account-password').value;\n  if (!validatePassword(password))\n    return;\n\n  Accounts.resetPassword(\n    loginButtonsSession.get('enrollAccountToken'), password,\n    function (error) {\n      if (error) {\n        loginButtonsSession.errorMessage(error.reason || \"Unknown error\");\n      } else {\n        loginButtonsSession.set('enrollAccountToken', null);\n        if (doneCallback)\n          doneCallback();\n      }\n    });\n};\n\nTemplate._enrollAccountDialog.helpers({\n  inEnrollAccountFlow: function () {\n    return loginButtonsSession.get('enrollAccountToken');\n  }\n});\n\n\n//\n// justVerifiedEmailDialog template\n//\n\nTemplate._justVerifiedEmailDialog.events({\n  'click #just-verified-dismiss-button': function () {\n    loginButtonsSession.set('justVerifiedEmail', false);\n  }\n});\n\nTemplate._justVerifiedEmailDialog.helpers({\n  visible: function () {\n    return loginButtonsSession.get('justVerifiedEmail');\n  },\n  displayName: displayName\n});\n\n\n//\n// loginButtonsMessagesDialog template\n//\n\nTemplate._loginButtonsMessagesDialog.events({\n  'click #messages-dialog-dismiss-button': function () {\n    loginButtonsSession.resetMessages();\n  }\n});\n\nTemplate._loginButtonsMessagesDialog.helpers({\n  visible: function () {\n    var hasMessage = loginButtonsSession.get('infoMessage') || loginButtonsSession.get('errorMessage');\n    return !dropdown() && hasMessage;\n  }\n});\n\n\n//\n// configureLoginServiceDialog template\n//\n\nTemplate._configureLoginServiceDialog.events({\n  'click .configure-login-service-dismiss-button': function () {\n    loginButtonsSession.set('configureLoginServiceDialogVisible', false);\n  },\n  'click #configure-login-service-dialog-save-configuration': function () {\n    if (loginButtonsSession.get('configureLoginServiceDialogVisible') &&\n        ! loginButtonsSession.get('configureLoginServiceDialogSaveDisabled')) {\n      // Prepare the configuration document for this login service\n      var serviceName = loginButtonsSession.get('configureLoginServiceDialogServiceName');\n      var configuration = {\n        service: serviceName\n      };\n\n      // Fetch the value of each input field\n      _.each(configurationFields(), function(field) {\n        configuration[field.property] = document.getElementById(\n          'configure-login-service-dialog-' + field.property).value\n          .replace(/^\\s*|\\s*$/g, \"\"); // trim() doesnt work on IE8;\n      });\n\n      configuration.loginStyle =\n        $('#configure-login-service-dialog input[name=\"loginStyle\"]:checked')\n        .val();\n\n      // Configure this login service\n      Accounts.connection.call(\n        \"configureLoginService\", configuration, function (error, result) {\n          if (error)\n            Meteor._debug(\"Error configuring login service \" + serviceName,\n                          error);\n          else\n            loginButtonsSession.set('configureLoginServiceDialogVisible',\n                                    false);\n        });\n    }\n  },\n  // IE8 doesn't support the 'input' event, so we'll run this on the keyup as\n  // well. (Keeping the 'input' event means that this also fires when you use\n  // the mouse to change the contents of the field, eg 'Cut' menu item.)\n  'input, keyup input': function (event) {\n    // if the event fired on one of the configuration input fields,\n    // check whether we should enable the 'save configuration' button\n    if (event.target.id.indexOf('configure-login-service-dialog') === 0)\n      updateSaveDisabled();\n  }\n});\n\n// check whether the 'save configuration' button should be enabled.\n// this is a really strange way to implement this and a Forms\n// Abstraction would make all of this reactive, and simpler.\nvar updateSaveDisabled = function () {\n  var anyFieldEmpty = _.any(configurationFields(), function(field) {\n    return document.getElementById(\n      'configure-login-service-dialog-' + field.property).value === '';\n  });\n\n  loginButtonsSession.set('configureLoginServiceDialogSaveDisabled', anyFieldEmpty);\n};\n\n// Returns the appropriate template for this login service.  This\n// template should be defined in the service's package\nvar configureLoginServiceDialogTemplateForService = function () {\n  var serviceName = loginButtonsSession.get('configureLoginServiceDialogServiceName');\n  // XXX Service providers should be able to specify their configuration\n  // template name.\n  return Template['configureLoginServiceDialogFor' +\n                  (serviceName === 'meteor-developer' ?\n                   'MeteorDeveloper' :\n                   capitalize(serviceName))];\n};\n\nvar configurationFields = function () {\n  var template = configureLoginServiceDialogTemplateForService();\n  return template.fields();\n};\n\nTemplate._configureLoginServiceDialog.helpers({\n  configurationFields: function () {\n    return configurationFields();\n  },\n  visible: function () {\n    return loginButtonsSession.get('configureLoginServiceDialogVisible');\n  },\n  configurationSteps: function () {\n    // renders the appropriate template\n    return configureLoginServiceDialogTemplateForService();\n  },\n  saveDisabled: function () {\n    return loginButtonsSession.get('configureLoginServiceDialogSaveDisabled');\n  }\n});\n\n// XXX from http://epeli.github.com/underscore.string/lib/underscore.string.js\nvar capitalize = function(str){\n  str = str == null ? '' : String(str);\n  return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\nTemplate._configureLoginOnDesktopDialog.helpers({\n  visible: function () {\n    return loginButtonsSession.get('configureOnDesktopVisible');\n  }\n});\n\nTemplate._configureLoginOnDesktopDialog.events({\n  'click #configure-on-desktop-dismiss-button': function () {\n    loginButtonsSession.set('configureOnDesktopVisible', false);\n  }\n});\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/login_buttons_dropdown.html",
    "content": "<!--           -->\n<!-- LOGGED IN -->\n<!--           -->\n<template name=\"_loginButtonsLoggedInDropdown\">\n  <div class=\"login-link-and-dropdown-list\">\n    <a class=\"login-link-text\" id=\"login-name-link\">\n      {{displayName}} ▾\n    </a>\n\n    {{#if dropdownVisible}}\n      <div id=\"login-dropdown-list\" class=\"accounts-dialog\">\n        <a class=\"login-close-text\">Close</a>\n        <div class=\"login-close-text-clear\"></div>\n\n        {{#if inMessageOnlyFlow}}\n          {{> _loginButtonsMessages}}\n        {{else}}\n          {{#if inChangePasswordFlow}}\n            {{> _loginButtonsChangePassword}}\n          {{else}}\n            {{> _loginButtonsLoggedInDropdownActions}}\n          {{/if}}\n        {{/if}}\n      </div>\n    {{/if}}\n  </div>\n</template>\n\n<template name=\"_loginButtonsLoggedInDropdownActions\">\n  {{#if allowChangingPassword}}\n    <div class=\"login-button\" id=\"login-buttons-open-change-password\">\n      Change password\n    </div>\n  {{/if}}\n\n  <div class=\"login-button\" id=\"login-buttons-logout\">\n    Sign out\n  </div>\n\n  {{> _loginButtonsMessages}}\n</template>\n\n<!--            -->\n<!-- LOGGED OUT -->\n<!--            -->\n<template name=\"_loginButtonsLoggedOutDropdown\">\n  <div class=\"login-link-and-dropdown-list {{additionalClasses}}\">\n    {{#if dropdownVisible}}\n      {{! This text is covered by the dropdown, but duplicating it here\n          makes the position of \"Close\" match the position of this text. }}\n      <a class=\"login-link-text\" id=\"login-sign-in-link\">Sign in ▾</a>\n      <div id=\"login-dropdown-list\" class=\"accounts-dialog\">\n        <a class=\"login-close-text\">Close</a>\n        {{#if loggingIn}}\n          {{> _loginButtonsLoggingIn}}\n        {{/if}}\n        <div class=\"login-close-text-clear\"></div>\n        {{> _loginButtonsLoggedOutAllServices}}\n      </div>\n    {{else}}\n      {{#if loggingIn}}\n        {{! Not normally visible, but if the user closes the dropdown during login.}}\n        {{> _loginButtonsLoggingIn}}\n      {{else}}\n        <a class=\"login-link-text\" id=\"login-sign-in-link\">Sign in ▾</a>\n      {{/if}}\n    {{/if}}\n  </div>\n</template>\n\n<template name=\"_loginButtonsLoggedOutAllServices\">\n  {{#each services}}\n    {{#if isPasswordService}}\n      {{#if hasOtherServices}} {{! the password service will always come last }}\n        {{> _loginButtonsLoggedOutPasswordServiceSeparator}}\n      {{/if}}\n      {{> _loginButtonsLoggedOutPasswordService}}\n    {{else}}\n      {{> _loginButtonsLoggedOutSingleLoginButton}}\n    {{/if}}\n  {{/each}}\n\n  {{#unless hasPasswordService}}\n    {{> _loginButtonsMessages}}\n  {{/unless}}\n</template>\n\n<template name=\"_loginButtonsLoggedOutPasswordServiceSeparator\">\n  <div class=\"or\">\n    <span class=\"hline\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>\n    <span class=\"or-text\">or</span>\n    <span class=\"hline\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>\n  </div>\n</template>\n\n<template name=\"_loginButtonsLoggedOutPasswordService\">\n  {{#if inForgotPasswordFlow}}\n    {{> _forgotPasswordForm}}\n  {{else}}\n    <div class=\"login-form login-password-form\">\n      {{#each fields}}\n        {{> _loginButtonsFormField}}\n      {{/each}}\n\n      {{> _loginButtonsMessages}}\n\n      <div class=\"login-button login-button-form-submit\" id=\"login-buttons-password\">\n        {{#if inSignupFlow}}\n          Create account\n        {{else}}\n          Sign in\n        {{/if}}\n      </div>\n\n      {{#if inLoginFlow}}\n        {{#if showCreateAccountLink}}\n          <div class=\"additional-link-container\">\n            <a id=\"signup-link\" class=\"additional-link\">Create account</a>\n          </div>\n        {{/if}}\n\n        {{#if showForgotPasswordLink}}\n          <div class=\"additional-link-container\">\n            <a id=\"forgot-password-link\" class=\"additional-link\">Forgot password</a>\n          </div>\n        {{/if}}\n      {{/if}}\n\n      {{#if inSignupFlow}}\n        {{> _loginButtonsBackToLoginLink}}\n      {{/if}}\n    </div>\n  {{/if}}\n</template>\n\n<template name=\"_forgotPasswordForm\">\n  <div class=\"login-form\">\n    <div id=\"forgot-password-email-label-and-input\"> {{! XXX we should probably use loginButtonsFormField }}\n      <label id=\"forgot-password-email-label\" for=\"forgot-password-email\">Email</label>\n      <input id=\"forgot-password-email\" type=\"email\"/>\n    </div>\n\n    {{> _loginButtonsMessages}}\n\n    <div class=\"login-button login-button-form-submit\" id=\"login-buttons-forgot-password\">\n      Reset password\n    </div>\n\n    {{> _loginButtonsBackToLoginLink}}\n  </div>\n</template>\n\n<template name=\"_loginButtonsBackToLoginLink\">\n  <div class=\"additional-link-container\">\n    <a id=\"back-to-login-link\" class=\"additional-link\">Sign in</a>\n  </div>\n</template>\n\n\n<!--\nThis strategy for login forms means that browsers' \"Remember password\"\nfunctionality does not work. Different browsers have different\nrequirements for remembering passwords:\n\n- Firefox: Must be an actual form (with a submit button), but you can\ncancel the submit with onsubmit='return false'.\n\n- Safari: Must be an actual form, and the form must actually be\nsubmitted somewhere (though it can target a hidden iframe and go to a\nbogus URL)\n\n- Chrome: Must be an actual form, and the the form elements must be\npresent in the initial HTML, not added to the page with javascript. This\nbasically rules out using normal meteor templates.\n\nhttps://gist.github.com/968927\n-->\n\n<template name=\"_loginButtonsFormField\">\n  {{#if visible}}\n    <div id=\"login-{{fieldName}}-label-and-input\">\n      <label id=\"login-{{fieldName}}-label\" for=\"login-{{fieldName}}\">\n        {{fieldLabel}}\n      </label>\n      <input id=\"login-{{fieldName}}\" type=\"{{inputType}}\" />\n    </div>\n  {{/if}}\n</template>\n\n<template name=\"_loginButtonsChangePassword\">\n  {{#each fields}}\n    {{> _loginButtonsFormField}}\n  {{/each}}\n\n  {{> _loginButtonsMessages}}\n\n  <div class=\"login-button login-button-form-submit\" id=\"login-buttons-do-change-password\">\n    Change password\n  </div>\n</template>\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/login_buttons_dropdown.js",
    "content": "// for convenience\nvar loginButtonsSession = Accounts._loginButtonsSession;\n\n// events shared between loginButtonsLoggedOutDropdown and\n// loginButtonsLoggedInDropdown\nTemplate.loginButtons.events({\n  'click #login-name-link, click #login-sign-in-link': function () {\n    loginButtonsSession.set('dropdownVisible', true);\n  },\n  'click .login-close-text': function () {\n    loginButtonsSession.closeDropdown();\n  }\n});\n\n\n//\n// loginButtonsLoggedInDropdown template and related\n//\n\nTemplate._loginButtonsLoggedInDropdown.events({\n  'click #login-buttons-open-change-password': function() {\n    loginButtonsSession.resetMessages();\n    loginButtonsSession.set('inChangePasswordFlow', true);\n  }\n});\n\nTemplate._loginButtonsLoggedInDropdown.helpers({\n  displayName: displayName,\n\n  inChangePasswordFlow: function () {\n    return loginButtonsSession.get('inChangePasswordFlow');\n  },\n\n  inMessageOnlyFlow: function () {\n    return loginButtonsSession.get('inMessageOnlyFlow');\n  },\n\n  dropdownVisible: function () {\n    return loginButtonsSession.get('dropdownVisible');\n  }\n});\n\nTemplate._loginButtonsLoggedInDropdownActions.helpers({\n  allowChangingPassword: function () {\n    // it would be more correct to check whether the user has a password set,\n    // but in order to do that we'd have to send more data down to the client,\n    // and it'd be preferable not to send down the entire service.password document.\n    //\n    // instead we use the heuristic: if the user has a username or email set.\n    var user = Meteor.user();\n    return user.username || (user.emails && user.emails[0] && user.emails[0].address);\n  }\n});\n\n\n//\n// loginButtonsLoggedOutDropdown template and related\n//\n\nTemplate._loginButtonsLoggedOutDropdown.events({\n  'click #login-buttons-password': function () {\n    loginOrSignup();\n  },\n\n  'keypress #forgot-password-email': function (event) {\n    if (event.keyCode === 13)\n      forgotPassword();\n  },\n\n  'click #login-buttons-forgot-password': function () {\n    forgotPassword();\n  },\n\n  'click #signup-link': function () {\n    loginButtonsSession.resetMessages();\n\n    // store values of fields before swtiching to the signup form\n    var username = trimmedElementValueById('login-username');\n    var email = trimmedElementValueById('login-email');\n    var usernameOrEmail = trimmedElementValueById('login-username-or-email');\n    // notably not trimmed. a password could (?) start or end with a space\n    var password = elementValueById('login-password');\n\n    loginButtonsSession.set('inSignupFlow', true);\n    loginButtonsSession.set('inForgotPasswordFlow', false);\n    // force the ui to update so that we have the approprate fields to fill in\n    Tracker.flush();\n\n    // update new fields with appropriate defaults\n    if (username !== null)\n      document.getElementById('login-username').value = username;\n    else if (email !== null)\n      document.getElementById('login-email').value = email;\n    else if (usernameOrEmail !== null)\n      if (usernameOrEmail.indexOf('@') === -1)\n        document.getElementById('login-username').value = usernameOrEmail;\n    else\n      document.getElementById('login-email').value = usernameOrEmail;\n\n    if (password !== null)\n      document.getElementById('login-password').value = password;\n\n    // Force redrawing the `login-dropdown-list` element because of\n    // a bizarre Chrome bug in which part of the DIV is not redrawn\n    // in case you had tried to unsuccessfully log in before\n    // switching to the signup form.\n    //\n    // Found tip on how to force a redraw on\n    // http://stackoverflow.com/questions/3485365/how-can-i-force-webkit-to-redraw-repaint-to-propagate-style-changes/3485654#3485654\n    var redraw = document.getElementById('login-dropdown-list');\n    redraw.style.display = 'none';\n    redraw.offsetHeight; // it seems that this line does nothing but is necessary for the redraw to work\n    redraw.style.display = 'block';\n  },\n  'click #forgot-password-link': function () {\n    loginButtonsSession.resetMessages();\n\n    // store values of fields before swtiching to the signup form\n    var email = trimmedElementValueById('login-email');\n    var usernameOrEmail = trimmedElementValueById('login-username-or-email');\n\n    loginButtonsSession.set('inSignupFlow', false);\n    loginButtonsSession.set('inForgotPasswordFlow', true);\n    // force the ui to update so that we have the approprate fields to fill in\n    Tracker.flush();\n\n    // update new fields with appropriate defaults\n    if (email !== null)\n      document.getElementById('forgot-password-email').value = email;\n    else if (usernameOrEmail !== null)\n      if (usernameOrEmail.indexOf('@') !== -1)\n        document.getElementById('forgot-password-email').value = usernameOrEmail;\n\n  },\n  'click #back-to-login-link': function () {\n    loginButtonsSession.resetMessages();\n\n    var username = trimmedElementValueById('login-username');\n    var email = trimmedElementValueById('login-email')\n          || trimmedElementValueById('forgot-password-email'); // Ughh. Standardize on names?\n    // notably not trimmed. a password could (?) start or end with a space\n    var password = elementValueById('login-password');\n\n    loginButtonsSession.set('inSignupFlow', false);\n    loginButtonsSession.set('inForgotPasswordFlow', false);\n    // force the ui to update so that we have the approprate fields to fill in\n    Tracker.flush();\n\n    if (document.getElementById('login-username') && username !== null)\n      document.getElementById('login-username').value = username;\n    if (document.getElementById('login-email') && email !== null)\n      document.getElementById('login-email').value = email;\n\n    var usernameOrEmailInput = document.getElementById('login-username-or-email');\n    if (usernameOrEmailInput) {\n      if (email !== null)\n        usernameOrEmailInput.value = email;\n      if (username !== null)\n        usernameOrEmailInput.value = username;\n    }\n\n    if (password !== null)\n      document.getElementById('login-password').value = password;\n  },\n  'keypress #login-username, keypress #login-email, keypress #login-username-or-email, keypress #login-password, keypress #login-password-again': function (event) {\n    if (event.keyCode === 13)\n      loginOrSignup();\n  }\n});\n\nTemplate._loginButtonsLoggedOutDropdown.helpers({\n  // additional classes that can be helpful in styling the dropdown\n  additionalClasses: function () {\n    if (!hasPasswordService()) {\n      return false;\n    } else {\n      if (loginButtonsSession.get('inSignupFlow')) {\n        return 'login-form-create-account';\n      } else if (loginButtonsSession.get('inForgotPasswordFlow')) {\n        return 'login-form-forgot-password';\n      } else {\n        return 'login-form-sign-in';\n      }\n    }\n  },\n\n  dropdownVisible: function () {\n    return loginButtonsSession.get('dropdownVisible');\n  },\n\n  hasPasswordService: hasPasswordService\n});\n\n// return all login services, with password last\nTemplate._loginButtonsLoggedOutAllServices.helpers({\n  services: getLoginServices,\n\n  isPasswordService: function () {\n    return this.name === 'password';\n  },\n\n  hasOtherServices: function () {\n    return getLoginServices().length > 1;\n  },\n\n  hasPasswordService: hasPasswordService\n});\n\nTemplate._loginButtonsLoggedOutPasswordService.helpers({\n  fields: function () {\n    var loginFields = [\n      {fieldName: 'username-or-email', fieldLabel: 'Username or Email',\n       visible: function () {\n         return _.contains(\n           [\"USERNAME_AND_EMAIL\", \"USERNAME_AND_OPTIONAL_EMAIL\"],\n           passwordSignupFields());\n       }},\n      {fieldName: 'username', fieldLabel: 'Username',\n       visible: function () {\n         return passwordSignupFields() === \"USERNAME_ONLY\";\n       }},\n      {fieldName: 'email', fieldLabel: 'Email', inputType: 'email',\n       visible: function () {\n         return passwordSignupFields() === \"EMAIL_ONLY\";\n       }},\n      {fieldName: 'password', fieldLabel: 'Password', inputType: 'password',\n       visible: function () {\n         return true;\n       }}\n    ];\n\n    var signupFields = [\n      {fieldName: 'username', fieldLabel: 'Username',\n       visible: function () {\n         return _.contains(\n           [\"USERNAME_AND_EMAIL\", \"USERNAME_AND_OPTIONAL_EMAIL\", \"USERNAME_ONLY\"],\n           passwordSignupFields());\n       }},\n      {fieldName: 'email', fieldLabel: 'Email', inputType: 'email',\n       visible: function () {\n         return _.contains(\n           [\"USERNAME_AND_EMAIL\", \"EMAIL_ONLY\"],\n           passwordSignupFields());\n       }},\n      {fieldName: 'email', fieldLabel: 'Email (optional)', inputType: 'email',\n       visible: function () {\n         return passwordSignupFields() === \"USERNAME_AND_OPTIONAL_EMAIL\";\n       }},\n      {fieldName: 'password', fieldLabel: 'Password', inputType: 'password',\n       visible: function () {\n         return true;\n       }},\n      {fieldName: 'password-again', fieldLabel: 'Password (again)',\n       inputType: 'password',\n       visible: function () {\n         // No need to make users double-enter their password if\n         // they'll necessarily have an email set, since they can use\n         // the \"forgot password\" flow.\n         return _.contains(\n           [\"USERNAME_AND_OPTIONAL_EMAIL\", \"USERNAME_ONLY\"],\n           passwordSignupFields());\n       }}\n    ];\n\n    return loginButtonsSession.get('inSignupFlow') ? signupFields : loginFields;\n  },\n\n  inForgotPasswordFlow: function () {\n    return loginButtonsSession.get('inForgotPasswordFlow');\n  },\n\n  inLoginFlow: function () {\n    return !loginButtonsSession.get('inSignupFlow') && !loginButtonsSession.get('inForgotPasswordFlow');\n  },\n\n  inSignupFlow: function () {\n    return loginButtonsSession.get('inSignupFlow');\n  },\n\n  showCreateAccountLink: function () {\n    return !Accounts._options.forbidClientAccountCreation;\n  },\n\n  showForgotPasswordLink: function () {\n    return _.contains(\n      [\"USERNAME_AND_EMAIL\", \"USERNAME_AND_OPTIONAL_EMAIL\", \"EMAIL_ONLY\"],\n      passwordSignupFields());\n  }\n});\n\nTemplate._loginButtonsFormField.helpers({\n  inputType: function () {\n    return this.inputType || \"text\";\n  }\n});\n\n\n//\n// loginButtonsChangePassword template\n//\n\nTemplate._loginButtonsChangePassword.events({\n  'keypress #login-old-password, keypress #login-password, keypress #login-password-again': function (event) {\n    if (event.keyCode === 13)\n      changePassword();\n  },\n  'click #login-buttons-do-change-password': function () {\n    changePassword();\n  }\n});\n\nTemplate._loginButtonsChangePassword.helpers({\n  fields: function () {\n    return [\n      {fieldName: 'old-password', fieldLabel: 'Current Password', inputType: 'password',\n       visible: function () {\n         return true;\n       }},\n      {fieldName: 'password', fieldLabel: 'New Password', inputType: 'password',\n       visible: function () {\n         return true;\n       }},\n      {fieldName: 'password-again', fieldLabel: 'New Password (again)',\n       inputType: 'password',\n       visible: function () {\n         // No need to make users double-enter their password if\n         // they'll necessarily have an email set, since they can use\n         // the \"forgot password\" flow.\n         return _.contains(\n           [\"USERNAME_AND_OPTIONAL_EMAIL\", \"USERNAME_ONLY\"],\n           passwordSignupFields());\n       }}\n    ];\n  }\n});\n\n\n//\n// helpers\n//\n\nvar elementValueById = function(id) {\n  var element = document.getElementById(id);\n  if (!element)\n    return null;\n  else\n    return element.value;\n};\n\nvar trimmedElementValueById = function(id) {\n  var element = document.getElementById(id);\n  if (!element)\n    return null;\n  else\n    return element.value.replace(/^\\s*|\\s*$/g, \"\"); // trim() doesn't work on IE8;\n};\n\nvar loginOrSignup = function () {\n  if (loginButtonsSession.get('inSignupFlow'))\n    signup();\n  else\n    login();\n};\n\nvar login = function () {\n  loginButtonsSession.resetMessages();\n\n  var username = trimmedElementValueById('login-username');\n  var email = trimmedElementValueById('login-email');\n  var usernameOrEmail = trimmedElementValueById('login-username-or-email');\n  // notably not trimmed. a password could (?) start or end with a space\n  var password = elementValueById('login-password');\n\n  var loginSelector;\n  if (username !== null) {\n    if (!validateUsername(username))\n      return;\n    else\n      loginSelector = {username: username};\n  } else if (email !== null) {\n    if (!validateEmail(email))\n      return;\n    else\n      loginSelector = {email: email};\n  } else if (usernameOrEmail !== null) {\n    // XXX not sure how we should validate this. but this seems good enough (for now),\n    // since an email must have at least 3 characters anyways\n    if (!validateUsername(usernameOrEmail))\n      return;\n    else\n      loginSelector = usernameOrEmail;\n  } else {\n    throw new Error(\"Unexpected -- no element to use as a login user selector\");\n  }\n\n  Meteor.loginWithPassword(loginSelector, password, function (error, result) {\n    if (error) {\n      loginButtonsSession.errorMessage(error.reason || \"Unknown error\");\n    } else {\n      loginButtonsSession.closeDropdown();\n    }\n  });\n};\n\nvar signup = function () {\n  loginButtonsSession.resetMessages();\n\n  var options = {}; // to be passed to Accounts.createUser\n\n  var username = trimmedElementValueById('login-username');\n  if (username !== null) {\n    if (!validateUsername(username))\n      return;\n    else\n      options.username = username;\n  }\n\n  var email = trimmedElementValueById('login-email');\n  if (email !== null) {\n    if (!validateEmail(email))\n      return;\n    else\n      options.email = email;\n  }\n\n  // notably not trimmed. a password could (?) start or end with a space\n  var password = elementValueById('login-password');\n  if (!validatePassword(password))\n    return;\n  else\n    options.password = password;\n\n  if (!matchPasswordAgainIfPresent())\n    return;\n\n  Accounts.createUser(options, function (error) {\n    if (error) {\n      loginButtonsSession.errorMessage(error.reason || \"Unknown error\");\n    } else {\n      loginButtonsSession.closeDropdown();\n    }\n  });\n};\n\nvar forgotPassword = function () {\n  loginButtonsSession.resetMessages();\n\n  var email = trimmedElementValueById(\"forgot-password-email\");\n  if (email.indexOf('@') !== -1) {\n    Accounts.forgotPassword({email: email}, function (error) {\n      if (error)\n        loginButtonsSession.errorMessage(error.reason || \"Unknown error\");\n      else\n        loginButtonsSession.infoMessage(\"Email sent\");\n    });\n  } else {\n    loginButtonsSession.errorMessage(\"Invalid email\");\n  }\n};\n\nvar changePassword = function () {\n  loginButtonsSession.resetMessages();\n\n  // notably not trimmed. a password could (?) start or end with a space\n  var oldPassword = elementValueById('login-old-password');\n\n  // notably not trimmed. a password could (?) start or end with a space\n  var password = elementValueById('login-password');\n  if (!validatePassword(password))\n    return;\n\n  if (!matchPasswordAgainIfPresent())\n    return;\n\n  Accounts.changePassword(oldPassword, password, function (error) {\n    if (error) {\n      loginButtonsSession.errorMessage(error.reason || \"Unknown error\");\n    } else {\n      loginButtonsSession.set('inChangePasswordFlow', false);\n      loginButtonsSession.set('inMessageOnlyFlow', true);\n      loginButtonsSession.infoMessage(\"Password changed\");\n    }\n  });\n};\n\nvar matchPasswordAgainIfPresent = function () {\n  // notably not trimmed. a password could (?) start or end with a space\n  var passwordAgain = elementValueById('login-password-again');\n  if (passwordAgain !== null) {\n    // notably not trimmed. a password could (?) start or end with a space\n    var password = elementValueById('login-password');\n    if (password !== passwordAgain) {\n      loginButtonsSession.errorMessage(\"Passwords don't match\");\n      return false;\n    }\n  }\n  return true;\n};\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/login_buttons_session.js",
    "content": "var VALID_KEYS = [\n  'dropdownVisible',\n\n  // XXX consider replacing these with one key that has an enum for values.\n  'inSignupFlow',\n  'inForgotPasswordFlow',\n  'inChangePasswordFlow',\n  'inMessageOnlyFlow',\n\n  'errorMessage',\n  'infoMessage',\n\n  // dialogs with messages (info and error)\n  'resetPasswordToken',\n  'enrollAccountToken',\n  'justVerifiedEmail',\n  'justResetPassword',\n\n  'configureLoginServiceDialogVisible',\n  'configureLoginServiceDialogServiceName',\n  'configureLoginServiceDialogSaveDisabled',\n  'configureOnDesktopVisible'\n];\n\nvar validateKey = function (key) {\n  if (!_.contains(VALID_KEYS, key))\n    throw new Error(\"Invalid key in loginButtonsSession: \" + key);\n};\n\nvar KEY_PREFIX = \"Meteor.loginButtons.\";\n\n// XXX This should probably be package scope rather than exported\n// (there was even a comment to that effect here from before we had\n// namespacing) but accounts-ui-viewer uses it, so leave it as is for\n// now\nAccounts._loginButtonsSession = {\n  set: function(key, value) {\n    validateKey(key);\n    if (_.contains(['errorMessage', 'infoMessage'], key))\n      throw new Error(\"Don't set errorMessage or infoMessage directly. Instead, use errorMessage() or infoMessage().\");\n\n    this._set(key, value);\n  },\n\n  _set: function(key, value) {\n    Session.set(KEY_PREFIX + key, value);\n  },\n\n  get: function(key) {\n    validateKey(key);\n    return Session.get(KEY_PREFIX + key);\n  },\n\n  closeDropdown: function () {\n    this.set('inSignupFlow', false);\n    this.set('inForgotPasswordFlow', false);\n    this.set('inChangePasswordFlow', false);\n    this.set('inMessageOnlyFlow', false);\n    this.set('dropdownVisible', false);\n    this.resetMessages();\n  },\n\n  infoMessage: function(message) {\n    this._set(\"errorMessage\", null);\n    this._set(\"infoMessage\", message);\n    this.ensureMessageVisible();\n  },\n\n  errorMessage: function(message) {\n    this._set(\"errorMessage\", message);\n    this._set(\"infoMessage\", null);\n    this.ensureMessageVisible();\n  },\n\n  // is there a visible dialog that shows messages (info and error)\n  isMessageDialogVisible: function () {\n    return this.get('resetPasswordToken') ||\n      this.get('enrollAccountToken') ||\n      this.get('justVerifiedEmail');\n  },\n\n  // ensure that somethings displaying a message (info or error) is\n  // visible.  if a dialog with messages is open, do nothing;\n  // otherwise open the dropdown.\n  //\n  // notably this doesn't matter when only displaying a single login\n  // button since then we have an explicit message dialog\n  // (_loginButtonsMessageDialog), and dropdownVisible is ignored in\n  // this case.\n  ensureMessageVisible: function () {\n    if (!this.isMessageDialogVisible())\n      this.set(\"dropdownVisible\", true);\n  },\n\n  resetMessages: function () {\n    this._set(\"errorMessage\", null);\n    this._set(\"infoMessage\", null);\n  },\n\n  configureService: function (name) {\n    if (Meteor.isCordova) {\n      this.set('configureOnDesktopVisible', true);\n    } else {\n      this.set('configureLoginServiceDialogVisible', true);\n      this.set('configureLoginServiceDialogServiceName', name);\n      this.set('configureLoginServiceDialogSaveDisabled', true);\n    }\n  }\n};\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/login_buttons_single.html",
    "content": "<template name=\"_loginButtonsLoggedOutSingleLoginButton\">\n  <div class=\"login-text-and-button\">\n    <div class=\"login-button single-login-button {{#unless configured}}configure-button{{/unless}}\"\n         id=\"login-buttons-{{name}}\">\n      <div class=\"login-image\" id=\"login-buttons-image-{{name}}\"></div>\n      {{#if configured}}\n        <span class=\"text-besides-image sign-in-text-{{name}}\">Sign in with {{capitalizedName}}</span>\n      {{else}}\n        <span class=\"text-besides-image configure-text-{{name}}\">Configure {{capitalizedName}} Login</span>\n      {{/if}}\n    </div>\n  </div>\n</template>\n\n<template name=\"_loginButtonsLoggingInSingleLoginButton\">\n  <div class=\"login-text-and-button\">\n    {{> _loginButtonsLoggingIn}}\n  </div>\n</template>\n\n<template name=\"_loginButtonsLoggedInSingleLogoutButton\">\n  <div class=\"login-text-and-button\">\n    <div class=\"login-display-name\">\n      {{displayName}}\n    </div>\n    <div class=\"login-button single-login-button\" id=\"login-buttons-logout\">Sign Out</div>\n  </div>\n</template>\n\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/login_buttons_single.js",
    "content": "// for convenience\nvar loginButtonsSession = Accounts._loginButtonsSession;\n\n\nvar loginResultCallback = function (serviceName, err) {\n  if (!err) {\n    loginButtonsSession.closeDropdown();\n  } else if (err instanceof Accounts.LoginCancelledError) {\n    // do nothing\n  } else if (err instanceof ServiceConfiguration.ConfigError) {\n    loginButtonsSession.configureService(serviceName);\n  } else {\n    loginButtonsSession.errorMessage(err.reason || \"Unknown error\");\n  }\n};\n\n\n// In the login redirect flow, we'll have the result of the login\n// attempt at page load time when we're redirected back to the\n// application.  Register a callback to update the UI (i.e. to close\n// the dialog on a successful login or display the error on a failed\n// login).\n//\nAccounts.onPageLoadLogin(function (attemptInfo) {\n  // Ignore if we have a left over login attempt for a service that is no longer registered.\n  if (_.contains(_.pluck(getLoginServices(), \"name\"), attemptInfo.type))\n    loginResultCallback(attemptInfo.type, attemptInfo.error);\n});\n\n\nTemplate._loginButtonsLoggedOutSingleLoginButton.events({\n  'click .login-button': function () {\n    var serviceName = this.name;\n    loginButtonsSession.resetMessages();\n\n    // XXX Service providers should be able to specify their\n    // `Meteor.loginWithX` method name.\n    var loginWithService = Meteor[\"loginWith\" +\n                                  (serviceName === 'meteor-developer' ?\n                                   'MeteorDeveloperAccount' :\n                                   capitalize(serviceName))];\n\n    var options = {}; // use default scope unless specified\n    if (Accounts.ui._options.requestPermissions[serviceName])\n      options.requestPermissions = Accounts.ui._options.requestPermissions[serviceName];\n    if (Accounts.ui._options.requestOfflineToken[serviceName])\n      options.requestOfflineToken = Accounts.ui._options.requestOfflineToken[serviceName];\n    if (Accounts.ui._options.forceApprovalPrompt[serviceName])\n      options.forceApprovalPrompt = Accounts.ui._options.forceApprovalPrompt[serviceName];\n\n    loginWithService(options, function (err) {\n      loginResultCallback(serviceName, err);\n    });\n  }\n});\n\nTemplate._loginButtonsLoggedOutSingleLoginButton.helpers({\n  configured: function () {\n    return !!ServiceConfiguration.configurations.findOne({service: this.name});\n  },\n  capitalizedName: function () {\n    if (this.name === 'github')\n      // XXX we should allow service packages to set their capitalized name\n      return 'GitHub';\n    else if (this.name === 'meteor-developer')\n      return 'Meteor';\n    else\n      return capitalize(this.name);\n  }\n});\n\n// XXX from http://epeli.github.com/underscore.string/lib/underscore.string.js\nvar capitalize = function(str){\n  str = str == null ? '' : String(str);\n  return str.charAt(0).toUpperCase() + str.slice(1);\n};\n"
  },
  {
    "path": "packages/accounts-ui-unstyled/package.js",
    "content": "Package.describe({\n  summary: \"Unstyled version of login widgets\",\n  version: \"1.1.12\"\n});\n\nPackage.onUse(function (api) {\n  api.use(['tracker', 'service-configuration', 'accounts-base',\n           'underscore', 'templating', 'session', 'jquery'], 'client');\n  // Export Accounts (etc) to packages using this one.\n  api.imply('accounts-base', ['client', 'server']);\n\n  // Allow us to call Accounts.oauth.serviceNames, if there are any OAuth\n  // services.\n  api.use('accounts-oauth', {weak: true});\n  // Allow us to directly test if accounts-password (which doesn't use\n  // Accounts.oauth.registerService) exists.\n  api.use('accounts-password', {weak: true});\n\n  api.addFiles([\n    'accounts_ui.js',\n\n    'login_buttons.html',\n    'login_buttons_single.html',\n    'login_buttons_dropdown.html',\n    'login_buttons_dialogs.html',\n\n    'login_buttons_session.js',\n\n    'login_buttons.js',\n    'login_buttons_single.js',\n    'login_buttons_dropdown.js',\n    'login_buttons_dialogs.js'], 'client');\n\n  // The less source defining the default style for accounts-ui. Just adding\n  // this package doesn't actually apply these styles; they need to be\n  // `@import`ed from some non-import less file.  The accounts-ui package does\n  // that for you, or you can do it in your app.\n  api.use('less');\n  api.addFiles('login_buttons.import.less');\n});\n\nPackage.onTest(function (api) {\n  api.use('accounts-ui-unstyled');\n  api.use('tinytest');\n  api.addFiles('accounts_ui_tests.js', 'client');\n});\n"
  },
  {
    "path": "packages/accounts-weibo/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/accounts-weibo/README.md",
    "content": "# accounts-weibo\n\nA login service for Weibo. See the [project page](https://www.meteor.com/accounts) on Meteor Accounts for more details."
  },
  {
    "path": "packages/accounts-weibo/package.js",
    "content": "Package.describe({\n  summary: \"Login service for Sina Weibo accounts\",\n  version: \"1.0.10\"\n});\n\nPackage.onUse(function(api) {\n  api.use('accounts-base', ['client', 'server']);\n  // Export Accounts (etc) to packages using this one.\n  api.imply('accounts-base', ['client', 'server']);\n  api.use('accounts-oauth', ['client', 'server']);\n  api.use('weibo', ['client', 'server']);\n\n  api.addFiles('weibo_login_button.css', 'client');\n\n  api.addFiles(\"weibo.js\");\n});\n"
  },
  {
    "path": "packages/accounts-weibo/weibo.js",
    "content": "Accounts.oauth.registerService('weibo');\n\nif (Meteor.isClient) {\n  Meteor.loginWithWeibo = function(options, callback) {\n    // support a callback without options\n    if (! callback && typeof options === \"function\") {\n      callback = options;\n      options = null;\n    }\n\n    var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback);\n    Weibo.requestCredential(options, credentialRequestCompleteCallback);\n  };\n} else {\n  Accounts.addAutopublishFields({\n    // publish all fields including access token, which can legitimately\n    // be used from the client (if transmitted over ssl or on localhost)\n    forLoggedInUser: ['services.weibo'],\n    forOtherUsers: ['services.weibo.screenName']\n  });\n}\n"
  },
  {
    "path": "packages/accounts-weibo/weibo_login_button.css",
    "content": "#login-buttons-image-weibo {\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAKySURBVDhPY2AgEpR5sjf/nS/6//UkoX+XJltuCvVxkcOp9cyZM1w/r13TuXvmDD9MkYIwg7qrNrubnzFb6J5intPHqrnvCnIwyKIYsmrVKuaFYWEFW2Sk79zX0f6/REHhKFABC0zRsky+rXMSeZdKCTLIHqgUvLAknW8L3IAQDw/RFlbWnQ801P+DNN8D4n0qyk94GRiEjTg5Lbz4+YOCdbhjVmTxbZwex7PUW58t8O1Ukf9gA2IDAoRPWFudfayt9f+mpsb/6yrK/28qKf4/ISf7YZu83K07QMNe6On9nyWusMtVm813azH/UWctZo/vc8TABjB3CApufAzSqKjw/7apyf+nMdH/XxUX/X+RnfX/qY/3/5tqqv/vq6v936KsfB2onltaiEHGx5AteFep4EmGUEHB1Adamv9v6er8fztp0v//79////nr1/+3X778B4N///5/O3jw/0N39//nlBQ/louLd4MMAWImcPhsU1G6DfLvt717wepnz537X0FB4T8fL+//AH///2/evgWL/7l///9dE+P/b4AWTZSWXg/UzAj2/w2gs59mZYEV7d+//z8rE9N/JUXF/w62tiD//a+urIS4BAgeA712Cxg2F40M36alpXGBDTgmI/3hdUU5WEFjff3/wvx8MNvcxARsQE1VFUQ30Et37Oz+P1RV+b/J0nIjUATigmgBvtzH5mb//9++/f/mkyf/A4KC/nv7+oI1W1hb/3/1+fP//9+//39ekP//CVDzTlnZxxtnz1ZBSUDeDAyZh7W13nybOeP/7W1b/09rbf2/FhgWHy9c+P912bL/D11d/l+WEP8/SUR4Ox8DA6pmmEkpHh4ya0JCim4lJGx7kZp8821CwrN7Hh4Pr7m6nDoSET61PjDQichsA3T7//+s/16/5gXSkIAa1AAAh8dhOVd5xHAAAAAASUVORK5CYII=);\n}\n"
  },
  {
    "path": "packages/allow-deny/README.md",
    "content": ""
  },
  {
    "path": "packages/allow-deny/allow-deny-tests.js",
    "content": "// Currently in 'mongo' package\n"
  },
  {
    "path": "packages/allow-deny/allow-deny.js",
    "content": "///\n/// Remote methods and access control.\n///\n\n// Restrict default mutators on collection. allow() and deny() take the\n// same options:\n//\n// options.insert {Function(userId, doc)}\n//   return true to allow/deny adding this document\n//\n// options.update {Function(userId, docs, fields, modifier)}\n//   return true to allow/deny updating these documents.\n//   `fields` is passed as an array of fields that are to be modified\n//\n// options.remove {Function(userId, docs)}\n//   return true to allow/deny removing these documents\n//\n// options.fetch {Array}\n//   Fields to fetch for these validators. If any call to allow or deny\n//   does not have this option then all fields are loaded.\n//\n// allow and deny can be called multiple times. The validators are\n// evaluated as follows:\n// - If neither deny() nor allow() has been called on the collection,\n//   then the request is allowed if and only if the \"insecure\" smart\n//   package is in use.\n// - Otherwise, if any deny() function returns true, the request is denied.\n// - Otherwise, if any allow() function returns true, the request is allowed.\n// - Otherwise, the request is denied.\n//\n// Meteor may call your deny() and allow() functions in any order, and may not\n// call all of them if it is able to make a decision without calling them all\n// (so don't include side effects).\n\nAllowDeny = {\n  CollectionPrototype: {}\n};\n\n// In the `mongo` package, we will extend Mongo.Collection.prototype with these\n// methods\nconst CollectionPrototype = AllowDeny.CollectionPrototype;\n\n/**\n * @summary Allow users to write directly to this collection from client code, subject to limitations you define.\n * @locus Server\n * @method allow\n * @memberOf Mongo.Collection\n * @instance\n * @param {Object} options\n * @param {Function} options.insert,update,remove Functions that look at a proposed modification to the database and return true if it should be allowed.\n * @param {String[]} options.fetch Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your `update` and `remove` functions.\n * @param {Function} options.transform Overrides `transform` on the  [`Collection`](#collections).  Pass `null` to disable transformation.\n */\nCollectionPrototype.allow = function(options) {\n  addValidator(this, 'allow', options);\n};\n\n/**\n * @summary Override `allow` rules.\n * @locus Server\n * @method deny\n * @memberOf Mongo.Collection\n * @instance\n * @param {Object} options\n * @param {Function} options.insert,update,remove Functions that look at a proposed modification to the database and return true if it should be denied, even if an [allow](#allow) rule says otherwise.\n * @param {String[]} options.fetch Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your `update` and `remove` functions.\n * @param {Function} options.transform Overrides `transform` on the  [`Collection`](#collections).  Pass `null` to disable transformation.\n */\nCollectionPrototype.deny = function(options) {\n  addValidator(this, 'deny', options);\n};\n\nCollectionPrototype._defineMutationMethods = function(options) {\n  const self = this;\n  options = options || {};\n\n  // set to true once we call any allow or deny methods. If true, use\n  // allow/deny semantics. If false, use insecure mode semantics.\n  self._restricted = false;\n\n  // Insecure mode (default to allowing writes). Defaults to 'undefined' which\n  // means insecure iff the insecure package is loaded. This property can be\n  // overriden by tests or packages wishing to change insecure mode behavior of\n  // their collections.\n  self._insecure = undefined;\n\n  self._validators = {\n    insert: {allow: [], deny: []},\n    update: {allow: [], deny: []},\n    remove: {allow: [], deny: []},\n    upsert: {allow: [], deny: []}, // dummy arrays; can't set these!\n    fetch: [],\n    fetchAllFields: false\n  };\n\n  if (!self._name)\n    return; // anonymous collection\n\n  // XXX Think about method namespacing. Maybe methods should be\n  // \"Meteor:Mongo:insert/NAME\"?\n  self._prefix = '/' + self._name + '/';\n\n  // Mutation Methods\n  // Minimongo on the server gets no stubs; instead, by default\n  // it wait()s until its result is ready, yielding.\n  // This matches the behavior of macromongo on the server better.\n  // XXX see #MeteorServerNull\n  if (self._connection && (self._connection === Meteor.server || Meteor.isClient)) {\n    const m = {};\n\n    _.each(['insert', 'update', 'remove'], function (method) {\n      const methodName = self._prefix + method;\n\n      if (options.useExisting) {\n        const handlerPropName = Meteor.isClient ? '_methodHandlers' : 'method_handlers';\n        // Do not try to create additional methods if this has already been called.\n        // (Otherwise the .methods() call below will throw an error.)\n        if (self._connection[handlerPropName] &&\n          typeof self._connection[handlerPropName][methodName] === 'function') return;\n      }\n\n      m[methodName] = function (/* ... */) {\n        // All the methods do their own validation, instead of using check().\n        check(arguments, [Match.Any]);\n        const args = _.toArray(arguments);\n        try {\n          // For an insert, if the client didn't specify an _id, generate one\n          // now; because this uses DDP.randomStream, it will be consistent with\n          // what the client generated. We generate it now rather than later so\n          // that if (eg) an allow/deny rule does an insert to the same\n          // collection (not that it really should), the generated _id will\n          // still be the first use of the stream and will be consistent.\n          //\n          // However, we don't actually stick the _id onto the document yet,\n          // because we want allow/deny rules to be able to differentiate\n          // between arbitrary client-specified _id fields and merely\n          // client-controlled-via-randomSeed fields.\n          let generatedId = null;\n          if (method === \"insert\" && !_.has(args[0], '_id')) {\n            generatedId = self._makeNewID();\n          }\n\n          if (this.isSimulation) {\n            // In a client simulation, you can do any mutation (even with a\n            // complex selector).\n            if (generatedId !== null)\n              args[0]._id = generatedId;\n            return self._collection[method].apply(\n              self._collection, args);\n          }\n\n          // This is the server receiving a method call from the client.\n\n          // We don't allow arbitrary selectors in mutations from the client: only\n          // single-ID selectors.\n          if (method !== 'insert')\n            throwIfSelectorIsNotId(args[0], method);\n\n          if (self._restricted) {\n            // short circuit if there is no way it will pass.\n            if (self._validators[method].allow.length === 0) {\n              throw new Meteor.Error(\n                403, \"Access denied. No allow validators set on restricted \" +\n                  \"collection for method '\" + method + \"'.\");\n            }\n\n            const validatedMethodName =\n                  '_validated' + method.charAt(0).toUpperCase() + method.slice(1);\n            args.unshift(this.userId);\n            method === 'insert' && args.push(generatedId);\n            return self[validatedMethodName].apply(self, args);\n          } else if (self._isInsecure()) {\n            if (generatedId !== null)\n              args[0]._id = generatedId;\n            // In insecure mode, allow any mutation (with a simple selector).\n            // XXX This is kind of bogus.  Instead of blindly passing whatever\n            //     we get from the network to this function, we should actually\n            //     know the correct arguments for the function and pass just\n            //     them.  For example, if you have an extraneous extra null\n            //     argument and this is Mongo on the server, the .wrapAsync'd\n            //     functions like update will get confused and pass the\n            //     \"fut.resolver()\" in the wrong slot, where _update will never\n            //     invoke it. Bam, broken DDP connection.  Probably should just\n            //     take this whole method and write it three times, invoking\n            //     helpers for the common code.\n            return self._collection[method].apply(self._collection, args);\n          } else {\n            // In secure mode, if we haven't called allow or deny, then nothing\n            // is permitted.\n            throw new Meteor.Error(403, \"Access denied\");\n          }\n        } catch (e) {\n          if (e.name === 'MongoError' || e.name === 'MinimongoError') {\n            throw new Meteor.Error(409, e.toString());\n          } else {\n            throw e;\n          }\n        }\n      };\n    });\n\n    self._connection.methods(m);\n  }\n};\n\nCollectionPrototype._updateFetch = function (fields) {\n  const self = this;\n\n  if (!self._validators.fetchAllFields) {\n    if (fields) {\n      self._validators.fetch = _.union(self._validators.fetch, fields);\n    } else {\n      self._validators.fetchAllFields = true;\n      // clear fetch just to make sure we don't accidentally read it\n      self._validators.fetch = null;\n    }\n  }\n};\n\nCollectionPrototype._isInsecure = function () {\n  const self = this;\n  if (self._insecure === undefined)\n    return !!Package.insecure;\n  return self._insecure;\n};\n\nCollectionPrototype._validatedInsert = function (userId, doc,\n                                                         generatedId) {\n  const self = this;\n\n  // call user validators.\n  // Any deny returns true means denied.\n  if (_.any(self._validators.insert.deny, function(validator) {\n    return validator(userId, docToValidate(validator, doc, generatedId));\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n  // Any allow returns true means proceed. Throw error if they all fail.\n  if (_.all(self._validators.insert.allow, function(validator) {\n    return !validator(userId, docToValidate(validator, doc, generatedId));\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n\n  // If we generated an ID above, insert it now: after the validation, but\n  // before actually inserting.\n  if (generatedId !== null)\n    doc._id = generatedId;\n\n  self._collection.insert.call(self._collection, doc);\n};\n\n// Simulate a mongo `update` operation while validating that the access\n// control rules set by calls to `allow/deny` are satisfied. If all\n// pass, rewrite the mongo operation to use $in to set the list of\n// document ids to change ##ValidatedChange\nCollectionPrototype._validatedUpdate = function(\n    userId, selector, mutator, options) {\n  const self = this;\n\n  check(mutator, Object);\n\n  options = _.clone(options) || {};\n\n  if (!LocalCollection._selectorIsIdPerhapsAsObject(selector))\n    throw new Error(\"validated update should be of a single ID\");\n\n  // We don't support upserts because they don't fit nicely into allow/deny\n  // rules.\n  if (options.upsert)\n    throw new Meteor.Error(403, \"Access denied. Upserts not \" +\n                           \"allowed in a restricted collection.\");\n\n  const noReplaceError = \"Access denied. In a restricted collection you can only\" +\n        \" update documents, not replace them. Use a Mongo update operator, such \" +\n        \"as '$set'.\";\n\n  // compute modified fields\n  const fields = [];\n  if (_.isEmpty(mutator)) {\n    throw new Meteor.Error(403, noReplaceError);\n  }\n  _.each(mutator, function (params, op) {\n    if (op.charAt(0) !== '$') {\n      throw new Meteor.Error(403, noReplaceError);\n    } else if (!_.has(ALLOWED_UPDATE_OPERATIONS, op)) {\n      throw new Meteor.Error(\n        403, \"Access denied. Operator \" + op + \" not allowed in a restricted collection.\");\n    } else {\n      _.each(_.keys(params), function (field) {\n        // treat dotted fields as if they are replacing their\n        // top-level part\n        if (field.indexOf('.') !== -1)\n          field = field.substring(0, field.indexOf('.'));\n\n        // record the field we are trying to change\n        if (!_.contains(fields, field))\n          fields.push(field);\n      });\n    }\n  });\n\n  const findOptions = {transform: null};\n  if (!self._validators.fetchAllFields) {\n    findOptions.fields = {};\n    _.each(self._validators.fetch, function(fieldName) {\n      findOptions.fields[fieldName] = 1;\n    });\n  }\n\n  const doc = self._collection.findOne(selector, findOptions);\n  if (!doc)  // none satisfied!\n    return 0;\n\n  // call user validators.\n  // Any deny returns true means denied.\n  if (_.any(self._validators.update.deny, function(validator) {\n    const factoriedDoc = transformDoc(validator, doc);\n    return validator(userId,\n                     factoriedDoc,\n                     fields,\n                     mutator);\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n  // Any allow returns true means proceed. Throw error if they all fail.\n  if (_.all(self._validators.update.allow, function(validator) {\n    const factoriedDoc = transformDoc(validator, doc);\n    return !validator(userId,\n                      factoriedDoc,\n                      fields,\n                      mutator);\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n\n  options._forbidReplace = true;\n\n  // Back when we supported arbitrary client-provided selectors, we actually\n  // rewrote the selector to include an _id clause before passing to Mongo to\n  // avoid races, but since selector is guaranteed to already just be an ID, we\n  // don't have to any more.\n\n  return self._collection.update.call(\n    self._collection, selector, mutator, options);\n};\n\n// Only allow these operations in validated updates. Specifically\n// whitelist operations, rather than blacklist, so new complex\n// operations that are added aren't automatically allowed. A complex\n// operation is one that does more than just modify its target\n// field. For now this contains all update operations except '$rename'.\n// http://docs.mongodb.org/manual/reference/operators/#update\nconst ALLOWED_UPDATE_OPERATIONS = {\n  $inc:1, $set:1, $unset:1, $addToSet:1, $pop:1, $pullAll:1, $pull:1,\n  $pushAll:1, $push:1, $bit:1\n};\n\n// Simulate a mongo `remove` operation while validating access control\n// rules. See #ValidatedChange\nCollectionPrototype._validatedRemove = function(userId, selector) {\n  const self = this;\n\n  const findOptions = {transform: null};\n  if (!self._validators.fetchAllFields) {\n    findOptions.fields = {};\n    _.each(self._validators.fetch, function(fieldName) {\n      findOptions.fields[fieldName] = 1;\n    });\n  }\n\n  const doc = self._collection.findOne(selector, findOptions);\n  if (!doc)\n    return 0;\n\n  // call user validators.\n  // Any deny returns true means denied.\n  if (_.any(self._validators.remove.deny, function(validator) {\n    return validator(userId, transformDoc(validator, doc));\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n  // Any allow returns true means proceed. Throw error if they all fail.\n  if (_.all(self._validators.remove.allow, function(validator) {\n    return !validator(userId, transformDoc(validator, doc));\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n\n  // Back when we supported arbitrary client-provided selectors, we actually\n  // rewrote the selector to {_id: {$in: [ids that we found]}} before passing to\n  // Mongo to avoid races, but since selector is guaranteed to already just be\n  // an ID, we don't have to any more.\n\n  return self._collection.remove.call(self._collection, selector);\n};\n\nCollectionPrototype._callMutatorMethod = function _callMutatorMethod(name, args, callback) {\n  if (Meteor.isClient && !callback && !alreadyInSimulation()) {\n    // Client can't block, so it can't report errors by exception,\n    // only by callback. If they forget the callback, give them a\n    // default one that logs the error, so they aren't totally\n    // baffled if their writes don't work because their database is\n    // down.\n    // Don't give a default callback in simulation, because inside stubs we\n    // want to return the results from the local collection immediately and\n    // not force a callback.\n    callback = function (err) {\n      if (err)\n        Meteor._debug(name + \" failed: \" + (err.reason || err.stack));\n    };\n  }\n\n  // For two out of three mutator methods, the first argument is a selector\n  const firstArgIsSelector = name === \"update\" || name === \"remove\";\n  if (firstArgIsSelector && !alreadyInSimulation()) {\n    // If we're about to actually send an RPC, we should throw an error if\n    // this is a non-ID selector, because the mutation methods only allow\n    // single-ID selectors. (If we don't throw here, we'll see flicker.)\n    throwIfSelectorIsNotId(args[0], name);\n  }\n\n  const mutatorMethodName = this._prefix + name;\n  return this._connection.apply(\n    mutatorMethodName, args, { returnStubValue: true }, callback);\n}\n\nfunction transformDoc(validator, doc) {\n  if (validator.transform)\n    return validator.transform(doc);\n  return doc;\n}\n\nfunction docToValidate(validator, doc, generatedId) {\n  let ret = doc;\n  if (validator.transform) {\n    ret = EJSON.clone(doc);\n    // If you set a server-side transform on your collection, then you don't get\n    // to tell the difference between \"client specified the ID\" and \"server\n    // generated the ID\", because transforms expect to get _id.  If you want to\n    // do that check, you can do it with a specific\n    // `C.allow({insert: f, transform: null})` validator.\n    if (generatedId !== null) {\n      ret._id = generatedId;\n    }\n    ret = validator.transform(ret);\n  }\n  return ret;\n}\n\nfunction addValidator(collection, allowOrDeny, options) {\n  // validate keys\n  const VALID_KEYS = ['insert', 'update', 'remove', 'fetch', 'transform'];\n  _.each(_.keys(options), function (key) {\n    if (!_.contains(VALID_KEYS, key))\n      throw new Error(allowOrDeny + \": Invalid key: \" + key);\n  });\n\n  collection._restricted = true;\n\n  _.each(['insert', 'update', 'remove'], function (name) {\n    if (options.hasOwnProperty(name)) {\n      if (!(options[name] instanceof Function)) {\n        throw new Error(allowOrDeny + \": Value for `\" + name + \"` must be a function\");\n      }\n\n      // If the transform is specified at all (including as 'null') in this\n      // call, then take that; otherwise, take the transform from the\n      // collection.\n      if (options.transform === undefined) {\n        options[name].transform = collection._transform;  // already wrapped\n      } else {\n        options[name].transform = LocalCollection.wrapTransform(\n          options.transform);\n      }\n\n      collection._validators[name][allowOrDeny].push(options[name]);\n    }\n  });\n\n  // Only update the fetch fields if we're passed things that affect\n  // fetching. This way allow({}) and allow({insert: f}) don't result in\n  // setting fetchAllFields\n  if (options.update || options.remove || options.fetch) {\n    if (options.fetch && !(options.fetch instanceof Array)) {\n      throw new Error(allowOrDeny + \": Value for `fetch` must be an array\");\n    }\n    collection._updateFetch(options.fetch);\n  }\n}\n\nfunction throwIfSelectorIsNotId(selector, methodName) {\n  if (!LocalCollection._selectorIsIdPerhapsAsObject(selector)) {\n    throw new Meteor.Error(\n      403, \"Not permitted. Untrusted code may only \" + methodName +\n        \" documents by ID.\");\n  }\n};\n\n// Determine if we are in a DDP method simulation\nfunction alreadyInSimulation() {\n  const enclosing = DDP._CurrentInvocation.get();\n  return enclosing && enclosing.isSimulation;\n}\n"
  },
  {
    "path": "packages/allow-deny/package.js",
    "content": "Package.describe({\n  name: 'allow-deny',\n  version: '1.0.5',\n  // Brief, one-line summary of the package.\n  summary: 'Implements functionality for allow/deny and client-side db operations',\n  // URL to the Git repository containing the source code for this package.\n  git: 'https://github.com/meteor/meteor',\n  // By default, Meteor will default to using README.md for documentation.\n  // To avoid submitting documentation, set this field to null.\n  documentation: null\n});\n\nPackage.onUse(function(api) {\n  api.use([\n    'ecmascript',\n    'underscore',\n    'minimongo', // Just for LocalCollection.wrapTransform :[\n    'check',\n    'ejson',\n    'ddp',\n  ]);\n\n  api.addFiles('allow-deny.js');\n  api.export('AllowDeny');\n});\n\nPackage.onTest(function(api) {\n  api.use('ecmascript');\n  api.use('tinytest');\n  api.use('allow-deny');\n  api.addFiles('allow-deny-tests.js');\n});\n"
  },
  {
    "path": "packages/appcache/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/appcache/QA.md",
    "content": "# QA Notes\n\n## Viewing the app cache\n\nChrome: Navigate to chrome://appcache-internals/\n\nFirefox: Open Tools / Advanced / Network.  The section reading \"The\nfollowing websites are allowed to store data for offline use\" will\nshow the amount of data in the app cache (\"1.2 MB\").  If this number\nis 0 the app is permitted to use the app cache but the app cache is\ncurrently turned off.\n\n\n## Setup\n\nCreate a simple static app and add the appcache package.\n\nstatic.html:\n\n````\n<body>\n  some static content\n</body>\n````\n\n\n## App is cached offline\n\nRun Meteor, load the app in the browser, stop Meteor.  Reload the page\nin the browser and observe the content is still visible.\n\n\n## Hot code reload still works\n\nRun Meteor, open the app in the browser.  Make a change to\nstatic.html.  Observe the change appear in the web page.\n\nNote that it is normal when using the app cache for the page reload to\nbe delayed a bit while the browser fetches the changed code in the\nbackground.\n\nWithout app cache: (page goes blank) -> (browser fetches) -> (page renders)\n\nWith app cache: (browser fetches) -> (page goes blank) -> (page renders)\n\n\n## Enabling / disabling the appcache turns the app cache on / off\n\nRun Meteor, open the app in the browser.\n\nDisable your browser in the appcache config.  For example, if you're\nusing Chrome:\n\n````\nif (Meteor.isServer) {\n  Meteor.AppCache.config({\n    chrome: false\n  });\n}\n````\n\nObserve following the hot code reload the app is no longer cached.\n\nEnable your browser again:\n\n````\nif (Meteor.isServer) {\n  Meteor.AppCache.config({\n    chrome: true\n  });\n}\n````\n\nObserve following the hot code reload the app is cached again.\n\n\n## Removing the appcache package turns off app caching\n\nStart Meteor, open the app in the browser.\n\nStop Meteor, remove the appcache package, remove or comment out the\ncall to Meteor.AppCache.config in static.js, start Meteor again.\n\nWait for the browser to reestablish its livedata connection.  Observe\nfollowing the hot code reload that the app is no longer cached.\n"
  },
  {
    "path": "packages/appcache/README.md",
    "content": "# appcache\n\nThe `appcache` package, part of\n[Webapp](https://www.meteor.com/webapp), stores the static parts of a\nMeteor application (the client side Javascript, HTML, CSS, and images)\nin the browser's [application\ncache](https://en.wikipedia.org/wiki/AppCache).\n\n## Using Appcache\n\nTo enable caching\nsimply add the `appcache` package to your project.\n\n* Once a user has visited a Meteor application for the first time and\n  the application has been cached, on subsequent visits the web page\n  loads faster because the browser can load the application out of the\n  cache without contacting the server first.\n\n* Hot code pushes are loaded by the browser in the background while the\n  app continues to run.  Once the new code has been fully loaded the\n  browser is able to switch over to the new code quickly.\n\n* The application cache allows the application to be loaded even when\n  the browser doesn't have an Internet connection, and so enables using\n  the app offline.\n\n(Note however that the `appcache` package by itself doesn't make\n*data* available offline: in an application loaded offline, a Meteor\nCollection will appear to be empty in the client until the Internet\nbecomes available and the browser is able to establish a DDP\nconnection).\n\nTo turn AppCache off for specific browsers use:\n\n    Meteor.AppCache.config({\n      chrome: false,\n      firefox: false\n    });\n\nThe supported browsers that can be enabled or disabled include, but are\nnot limited to, `android`, `chrome`, `chromium`, `chromeMobileIOS`,\n`firefox`, `ie`, `mobileSafari` and `safari`.\n\nBrowsers limit the amount of data they will put in the application\ncache, which can vary due to factors such as how much disk space is\nfree.  Unfortunately if your application goes over the limit rather\nthan disabling the application cache altogether and running the\napplication online, the browser will instead fail that particular\n*update* of the cache, leaving your users running old code.\n\nThus it's best to keep the size of the cache below 5MB.  The\n`appcache` package will print a warning on the Meteor server console\nif the total size of the resources being cached is over 5MB.\n\nIf you have files too large to fit in the cache you can disable\ncaching by URL prefix.  For example,\n\n    Meteor.AppCache.config({onlineOnly: ['/online/']});\n\ncauses files in your `public/online` directory to not be cached, and\nso they will only be available online.  You can then move your large\nfiles into that directory and refer to them at the new URL:\n\n    <img src=\"/online/bigimage.jpg\">\n\nIf you'd prefer not to move your files, you can use the file names\nthemselves as the URL prefix:\n\n    Meteor.AppCache.config({\n      onlineOnly: [\n        '/bigimage.jpg',\n        '/largedata.json'\n      ]\n    });\n\nthough keep in mind that since the exclusion is by prefix (this is a\nlimitation of the application cache manifest), excluding\n`/largedata.json` will also exclude such URLs as\n`/largedata.json.orig` and `/largedata.json/file1`.\n\nFor more information about how Meteor interacts with the application\ncache, see the\n[AppCache page](https://github.com/meteor/meteor/wiki/AppCache)\nin the Meteor wiki.\n"
  },
  {
    "path": "packages/appcache/appcache-client.js",
    "content": "if (window.applicationCache) {\n\nvar appCacheStatuses = [\n  'uncached',\n  'idle',\n  'checking',\n  'downloading',\n  'updateready',\n  'obsolete'\n];\n\nvar updatingAppcache = false;\nvar reloadRetry = null;\nvar appcacheUpdated = false;\n\nReload._onMigrate('appcache', function (retry) {\n  if (appcacheUpdated)\n    return [true];\n\n  // An uncached application (one that does not have a manifest) cannot\n  // be updated.\n  if (window.applicationCache.status === window.applicationCache.UNCACHED)\n    return [true];\n\n  if (!updatingAppcache) {\n    try {\n      window.applicationCache.update();\n    } catch (e) {\n      Meteor._debug('applicationCache update error', e);\n      // There's no point in delaying the reload if we can't update the cache.\n      return [true];\n    }\n    updatingAppcache = true;\n  }\n\n  // Delay migration until the app cache has been updated.\n  reloadRetry = retry;\n  return false;\n});\n\n// If we're migrating and the app cache is now up to date, signal that\n// we're now ready to migrate.\nvar cacheIsNowUpToDate = function () {\n  if (!updatingAppcache)\n    return;\n  appcacheUpdated = true;\n  reloadRetry();\n};\n\nwindow.applicationCache.addEventListener('updateready', cacheIsNowUpToDate, false);\nwindow.applicationCache.addEventListener('noupdate', cacheIsNowUpToDate, false);\n\n// We'll get the obsolete event on a 404 fetching the app.manifest:\n// we had previously been running with an app cache, but the app\n// cache has now been disabled or the appcache package removed.\n// Reload to get the new non-cached code.\n\nwindow.applicationCache.addEventListener('obsolete', (function () {\n  if (reloadRetry) {\n    cacheIsNowUpToDate();\n  } else {\n    appcacheUpdated = true;\n    Reload._reload();\n  }\n}), false);\n\n} // if window.applicationCache\n"
  },
  {
    "path": "packages/appcache/appcache-server.js",
    "content": "var crypto = Npm.require('crypto');\nvar fs = Npm.require('fs');\nvar path = Npm.require('path');\n\nvar _disableSizeCheck = false;\n\nMeteor.AppCache = {\n  config: function (options) {\n    _.each(options, function (value, option) {\n      if (option === 'browsers') {\n        disabledBrowsers = {};\n        _.each(value, function (browser) {\n          disabledBrowsers[browser] = false;\n        });\n      }\n      else if (option === 'onlineOnly') {\n        _.each(value, function (urlPrefix) {\n          RoutePolicy.declare(urlPrefix, 'static-online');\n        });\n      }\n      // option to suppress warnings for tests.\n      else if (option === '_disableSizeCheck') {\n        _disableSizeCheck = value;\n      }\n      else if (value === false) {\n        disabledBrowsers[option] = true;\n      }\n      else if (value === true) {\n        disabledBrowsers[option] = false;\n      } else {\n        throw new Error('Invalid AppCache config option: ' + option);\n      }\n    });\n  }\n};\n\nvar disabledBrowsers = {};\nvar browserDisabled = function (request) {\n  return disabledBrowsers[request.browser.name];\n};\n\nWebApp.addHtmlAttributeHook(function (request) {\n  if (browserDisabled(request))\n    return null;\n  else\n    return { manifest: \"/app.manifest\" };\n});\n\nWebApp.connectHandlers.use(function (req, res, next) {\n  if (req.url !== '/app.manifest') {\n    return next();\n  }\n\n  // Browsers will get confused if we unconditionally serve the\n  // manifest and then disable the app cache for that browser.  If\n  // the app cache had previously been enabled for a browser, it\n  // will continue to fetch the manifest as long as it's available,\n  // even if we now are not including the manifest attribute in the\n  // app HTML.  (Firefox for example will continue to display \"this\n  // website is asking to store data on your computer for offline\n  // use\").  Returning a 404 gets the browser to really turn off the\n  // app cache.\n\n  if (browserDisabled(WebApp.categorizeRequest(req))) {\n    res.writeHead(404);\n    res.end();\n    return;\n  }\n\n  var manifest = \"CACHE MANIFEST\\n\\n\";\n\n  // After the browser has downloaded the app files from the server and\n  // has populated the browser's application cache, the browser will\n  // *only* connect to the server and reload the application if the\n  // *contents* of the app manifest file has changed.\n  //\n  // So to ensure that the client updates if client resources change,\n  // include a hash of client resources in the manifest.\n\n  manifest += \"# \" + WebApp.clientHash() + \"\\n\";\n\n  // When using the autoupdate package, also include\n  // AUTOUPDATE_VERSION.  Otherwise the client will get into an\n  // infinite loop of reloads when the browser doesn't fetch the new\n  // app HTML which contains the new version, and autoupdate will\n  // reload again trying to get the new code.\n\n  if (Package.autoupdate) {\n    var version = Package.autoupdate.Autoupdate.autoupdateVersion;\n    if (version !== WebApp.clientHash())\n      manifest += \"# \" + version + \"\\n\";\n  }\n\n  manifest += \"\\n\";\n\n  manifest += \"CACHE:\" + \"\\n\";\n  manifest += \"/\" + \"\\n\";\n  _.each(WebApp.clientPrograms[WebApp.defaultArch].manifest, function (resource) {\n    if (resource.where === 'client' &&\n        ! RoutePolicy.classify(resource.url)) {\n      manifest += resource.url;\n      // If the resource is not already cacheable (has a query\n      // parameter, presumably with a hash or version of some sort),\n      // put a version with a hash in the cache.\n      //\n      // Avoid putting a non-cacheable asset into the cache, otherwise\n      // the user can't modify the asset until the cache headers\n      // expire.\n      if (!resource.cacheable)\n        manifest += \"?\" + resource.hash;\n\n      manifest += \"\\n\";\n    }\n  });\n  manifest += \"\\n\";\n\n  manifest += \"FALLBACK:\\n\";\n  manifest += \"/ /\" + \"\\n\";\n  // Add a fallback entry for each uncacheable asset we added above.\n  //\n  // This means requests for the bare url (/image.png instead of\n  // /image.png?hash) will work offline. Online, however, the browser\n  // will send a request to the server. Users can remove this extra\n  // request to the server and have the asset served from cache by\n  // specifying the full URL with hash in their code (manually, with\n  // some sort of URL rewriting helper)\n  _.each(WebApp.clientPrograms[WebApp.defaultArch].manifest, function (resource) {\n    if (resource.where === 'client' &&\n        ! RoutePolicy.classify(resource.url) &&\n        !resource.cacheable) {\n      manifest += resource.url + \" \" + resource.url +\n        \"?\" + resource.hash + \"\\n\";\n    }\n  });\n\n  manifest += \"\\n\";\n\n  manifest += \"NETWORK:\\n\";\n  // TODO adding the manifest file to NETWORK should be unnecessary?\n  // Want more testing to be sure.\n  manifest += \"/app.manifest\" + \"\\n\";\n  _.each(\n    [].concat(\n      RoutePolicy.urlPrefixesFor('network'),\n      RoutePolicy.urlPrefixesFor('static-online')\n    ),\n    function (urlPrefix) {\n      manifest += urlPrefix + \"\\n\";\n    }\n  );\n  manifest += \"*\" + \"\\n\";\n\n  // content length needs to be based on bytes\n  var body = new Buffer(manifest);\n\n  res.setHeader('Content-Type', 'text/cache-manifest');\n  res.setHeader('Content-Length', body.length);\n  return res.end(body);\n});\n\nvar sizeCheck = function () {\n  var totalSize = 0;\n  _.each(WebApp.clientPrograms[WebApp.defaultArch].manifest, function (resource) {\n    if (resource.where === 'client' &&\n        ! RoutePolicy.classify(resource.url)) {\n      totalSize += resource.size;\n    }\n  });\n  if (totalSize > 5 * 1024 * 1024) {\n    Meteor._debug(\n      \"** You are using the appcache package but the total size of the\\n\" +\n      \"** cached resources is \" +\n      (totalSize / 1024 / 1024).toFixed(1) + \"MB.\\n\" +\n      \"**\\n\" +\n      \"** This is over the recommended maximum of 5 MB and may break your\\n\" +\n      \"** app in some browsers! See http://docs.meteor.com/#appcache\\n\" +\n      \"** for more information and fixes.\\n\"\n    );\n  }\n};\n\n// Run the size check after user code has had a chance to run. That way,\n// the size check can take into account files that the user does not\n// want cached. Otherwise, the size check warning will still print even\n// if the user excludes their large files with\n// `Meteor.AppCache.config({onlineOnly: files})`.\nMeteor.startup(function () {\n  if (! _disableSizeCheck)\n    sizeCheck();\n});\n"
  },
  {
    "path": "packages/appcache/appcache_tests-client.js",
    "content": "var manifestUrl = '/app.manifest';\n\nvar appcacheTest = function (name, cb) {\n  Tinytest.addAsync('appcache - ' + name, function (test, next) {\n    HTTP.get(manifestUrl, function (err, res) {\n      if (err) {\n        test.fail(err);\n      } else {\n        cb(test, res);\n      }\n      next();\n    });\n  });\n};\n\n\n// Verify that the code status of the HTTP response is \"OK\"\nappcacheTest('presence', function (test, manifest) {\n  test.equal(manifest.statusCode, 200, 'manifest not served');\n});\n\n\n// Verify the content-type HTTP header\nappcacheTest('content type', function (test, manifest) {\n  test.equal(manifest.headers['content-type'], 'text/cache-manifest');\n});\n\n\n// Verify that each section header is only set once.\nappcacheTest('sections uniqueness', function (test, manifest) {\n  var content = manifest.content;\n  var mandatorySectionHeaders = ['CACHE:', 'NETWORK:', 'FALLBACK:'];\n  var optionalSectionHeaders = ['SETTINGS'];\n  _.each(_.union(mandatorySectionHeaders, optionalSectionHeaders),\n         function (sectionHeader) {\n           var globalSearch = new RegExp(sectionHeader, \"g\");\n           var matches = content.match(globalSearch) || [];\n           test.isTrue(matches.length <= 1, sectionHeader + ' is set twice');\n           if (_.contains(mandatorySectionHeaders, sectionHeader)) {\n             test.isTrue(matches.length == 1, sectionHeader + ' is not set');\n           }\n         });\n});\n\n\n// Verify the content of the header and of each section of the manifest using\n// regular expressions. Regular expressions matches malformed URIs but that's\n// not what we're trying to catch here (the user is free to add its own content\n// in the manifest -- even malformed).\nappcacheTest('sections validity', function (test, manifest) {\n  var lines = manifest.content.split('\\n');\n  var i = 0;\n  var currentRegex = null, line = null;\n\n  var nextLine = function () {\n    return lines[i++];\n  };\n\n  var eof = function () {\n    return i >= lines.length;\n  };\n\n  var nextLineMatches = function (expected, n) {\n    n = n || 1;\n    _.times(n, function () {\n      var testFunc = _.isRegExp(expected) ? 'matches' : 'equal';\n      test[testFunc](nextLine(), expected);\n    });\n  };\n\n  // Verify header validity\n  nextLineMatches('CACHE MANIFEST');\n  nextLineMatches('');\n  nextLineMatches(/^# [a-z0-9]+$/i, 2);\n\n\n  // Verify body validity\n  while (! eof()) {\n    line = nextLine();\n\n    // There are three distinct sections: 'CACHE', 'FALLBACK', and 'NETWORK'.\n    // A section start with its name suffixed by a colon. When we read a new\n    // section header, we update the currentRegex expression for the next lines\n    // of the section.\n    // XXX There is also a 'SETTINGS' section, not used by this package. If this\n    // section is used, the test will fail.\n    if (line === 'CACHE:' || line === 'NETWORK:')\n      currentRegex = /^\\S+$/;\n\n    else if (line === 'FALLBACK:')\n      currentRegex = /^\\S+ \\S+$/;\n\n    // Blank lines and lines starting with a `#` (comments) are valid\n    else if (line == '' || line.match(/^#.+/))\n      continue;\n\n    // Outside sections, only blanks lines and comments are valid\n    else if (currentRegex === null)\n      test.fail('Invalid line ' + i + ': ' + line);\n\n    // Inside a section, a star is a valid expression\n    else if (line === '*')\n      continue;\n\n    // If it is not a blank line, not a comment, and not a header it must\n    // match the current section format\n    else\n      test.matches(line, currentRegex, 'line ' + i);\n  }\n});\n\n\n// Verify that resources declared on the server with the `onlineOnly` parameter\n// are present in the network section of the manifest. The `appcache` package\n// also automatically add the manifest (`app.manifest`) add the star symbol to\n// this list and therefore we also check the presence of these two elements.\nappcacheTest('network section content', function (test, manifest) {\n  var shouldBePresentInNetworkSection = [\n    \"/app.manifest\",\n    \"/online/\",\n    \"/bigimage.jpg\",\n    \"/largedata.json\",\n    \"*\"\n  ];\n  var lines = manifest.content.split('\\n');\n  var startNetworkSection = lines.indexOf('NETWORK:');\n\n  // We search the end of the 'NETWORK:' section by looking at the beginning\n  // of any potential other section. By default we set this value to\n  // `lines.length - 1` which is the index of the last line.\n  var otherSections = ['CACHE:', 'FALLBACK:', 'SETTINGS'];\n  var endNetworkSection = _.reduce(otherSections, function (min, sectionName) {\n    var position = lines.indexOf(sectionName);\n    return position > startNetworkSection && position < min ? position : min;\n  }, lines.length - 1);\n\n  // We remove the first line because it's the 'NETWORK:' header line.\n  var networkLines = lines.slice(startNetworkSection + 1, endNetworkSection);\n\n  _.each(shouldBePresentInNetworkSection, function (item) {\n    test.include(networkLines, item);\n  });\n});\n"
  },
  {
    "path": "packages/appcache/appcache_tests-server.js",
    "content": "// For our testing purpose, we don't want the cache manifest to be\n// active, all we want is the cache manifest to be manually request-able\n// so we can read it and verify its validity from the client.  This is\n// because caching the test files would make tests non deterministic\n// depending on the state of the browser cache.  To do that we disable\n// the \"manifest\" attribute of the <html> tag. This runs after appcache\n// registers its hook, so this hook overrides the return value of the\n// real hook. We point to a non-existent file to clear the appcache in\n// case there was previously a site running with appcache on\n// localhost:3000.\nWebApp.addHtmlAttributeHook(function (request) {\n  return { manifest: \"/no-such-file\" };\n});\n\n\n// Let's add some resources in the 'NETWORK' section\nMeteor.AppCache.config({\n  onlineOnly: [\n    '/online/',\n    '/bigimage.jpg',\n    '/largedata.json'\n  ],\n  _disableSizeCheck: true // don't print warnings\n});\n"
  },
  {
    "path": "packages/appcache/package.js",
    "content": "Package.describe({\n  summary: \"Enable the application cache in the browser\",\n  version: \"1.0.11\"\n});\n\nPackage.onUse(function (api) {\n  api.use('webapp', 'server');\n  api.use('reload', 'client');\n  api.use('routepolicy', 'server');\n  api.use('underscore', 'server');\n  api.use('autoupdate', 'server', {weak: true});\n  api.addFiles('appcache-client.js', 'client');\n  api.addFiles('appcache-server.js', 'server');\n});\n\nPackage.onTest(function (api) {\n  api.use('tinytest');\n  api.use('appcache');\n  api.use('http', 'client');\n  api.use('underscore', 'client');\n  api.use('webapp', 'server');\n  api.addFiles('appcache_tests-server.js', 'server');\n  api.addFiles('appcache_tests-client.js', 'client');\n});\n"
  },
  {
    "path": "packages/audit-argument-checks/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/audit-argument-checks/README.md",
    "content": "# Audit-Argument-Checks\n\nThis is an internal Meteor package."
  },
  {
    "path": "packages/audit-argument-checks/package.js",
    "content": "Package.describe({\n  summary: \"Try to detect inadequate input sanitization\",\n  version: '1.0.7'\n});\n\n// This package is empty; its presence is detected by livedata.\n"
  },
  {
    "path": "packages/autopublish/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/autopublish/README.md",
    "content": "# autopublish\n\nPublish all server collections to the client. This package is useful for prototyping an app without worrying about which clients have access to certain data, but should be removed as soon as the app needs to restrict which data is seen by the client.\n\nThe `autopublish` package is automatically added to every Meteor app by `meteor create`."
  },
  {
    "path": "packages/autopublish/package.js",
    "content": "Package.describe({\n  summary: \"(For prototyping only) Publish the entire database to all clients\",\n  version: '1.0.7'\n});\n\n// This package is empty; its presence is detected by several other packages\n// (such as ddp-server and mongo) which check for the presence of\n// Package.autopublish.\n"
  },
  {
    "path": "packages/autoupdate/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/autoupdate/QA.md",
    "content": "# QA Notes\n## Hot Code Push Reload\n\nRun the leaderboard example, and click on one of the names.  Make a\nchange to the leaderboard.html file, see the client reload, and see\nthat the name is still selected.\n\n\n## AUTOUPDATE_VERSION\n\nSet the `AUTOUPDATE_VERSION` environment variable when running the\napplication:\n\n    $ AUTOUPDATE_VERSION=abc meteor\n\nNow when you make an HTML change, it won't appear in the client\nautomatically.  (Note the leader list flickers when the server\nsubscription restarts, but that's not a window reload).\n\nConversely, you can force a client reload (even without making any\nclient code changes) by restarting the server with a new value for\n`AUTOUPDATE_VERSION`.\n\n\n## No Client Reload on Server-only Change\n\nRevert previous changes and run the example without setting\nAUTOUPDATE_VERSION.\n\nNote that it might look like the browser is reloading because the page\ncontent in the leaderboard example will flicker when the server\nrestarts because the example is using autopublish, but that the window\nwon't actually be reloading.\n\nIn the browser console, assign a variable such as `a = true` so that\nyou can easily verify that the client hasn't reloaded.\n\nIn the leaderboard example directory, create the `server` directory\nand add `foo.js`.  See in the browser console that `a` is still\ndefined, indicating the browser hasn't reloaded.\n\n\n## Test with the appcache\n\nAdd the appcache package:\n\n    $ meteor add appcache\n\nAnd do the above tests again.\n\nNote that if 1) AUTOUPDATE_VERSION is set so the client doesn't\nautomatically reload, 2) you make a client change, and 3) you manually\nreload the browser page, you usually *won't* see the updated HTML the\n*first* time you reload (unless the browser happened to check the app\ncache manifest between steps 2 and 3).  This is normal browser app\ncache behavior: the browser populates the app cache in the background,\nso it doesn't wait for new files to download before displaying the web\npage.\n\n\n## Autoupdate.newClientAvailable\n\nUndo previous changes made, such as by using `git checkout .` Reload\nthe client, which will cause the browser to stop using the app cache.\n\nIt's hard to see the `newClientAvailable` reactive variable when the\nclient automatically reloads.  Remove the `hot-code-push` package so you can\nsee the variable without having the client also reload.\n\n    $ meteor remove meteor-base\n    $ meteor add meteor webapp ddp autoupdate\n\nAdd to leaderboard.js:\n\n    Template.leaderboard.helpers({\n      available: function () {\n        return Autoupdate.newClientAvailable().toString();\n      }\n    });\n\nAnd add `{{available}}` to the leaderboard template in\nleaderboard.html.\n\nInitially you'll see `false`, and then when you make a change to the\nleaderboard HTML you'll see the variable change to `true`.  (You won't\nsee the new HTML on the client because you disabled reload).\n\nAmusingly, you can undo the addition you made to the HTML and the \"new\nclient available\" variable will go back to `false` (you now don't have\nclient code available on the server different than what's running in\nthe browser), because by default the client version is based on a hash\nof the client files.\n\n\n## DDP Version Negotiation Failure\n\nA quick way to test DDP version negotiation failure is to force the\nclient to use the wrong DDP version.  At the top of\nlivedata_connection.js:\n\n     var Connection = function (url, options) {\n        var self = this;\n    +   options.supportedDDPVersions = ['abc'];\n\nYou will see the client reload (in the hope that new client code will\nbe available that can successfully negotiation the DDP version).  Each\nreload takes longer than the one before, using an exponential backoff.\n\nIf you remove the `options.supportedDDPVersions` line and allow the\nclient to connect (or manually reload the browser page so you don't\nhave to wait), this will reset the exponential backoff counter.\n\nYou can verify the counter was reset by adding the line back in a\nsecond time, and you'll see the reload cycle start over again with\nfirst reloading quickly, and then again taking longer between tries.\n"
  },
  {
    "path": "packages/autoupdate/README.md",
    "content": "# autoupdate\n\nThis package is the heart of Meteor's Hot Code Push functionality. It has a\nclient component and a server component component. The client component uses a\nDDP API provided by the server to subscribe to the version ID of the most recent\nbuild of the app's client. When it sees that a new version is available, it uses\nthe [reload](https://atmospherejs.com/meteor/reload) package (if included in the\napp) to gracefully save the app's state and reload it in place.\n\n`autoupdate` is part of the [Webapp](https://www.meteor.com/webapp)\nproject.\n"
  },
  {
    "path": "packages/autoupdate/autoupdate_client.js",
    "content": "// Subscribe to the `meteor_autoupdate_clientVersions` collection,\n// which contains the set of acceptable client versions.\n//\n// A \"hard code push\" occurs when the running client version is not in\n// the set of acceptable client versions (or the server updates the\n// collection, there is a published client version marked `current` and\n// the running client version is no longer in the set).\n//\n// When the `reload` package is loaded, a hard code push causes\n// the browser to reload, so that it will load the latest client\n// version from the server.\n//\n// A \"soft code push\" represents the situation when the running client\n// version is in the set of acceptable versions, but there is a newer\n// version available on the server.\n//\n// `Autoupdate.newClientAvailable` is a reactive data source which\n// becomes `true` if there is a new version of the client is available on\n// the server.\n//\n// This package doesn't implement a soft code reload process itself,\n// but `newClientAvailable` could be used for example to display a\n// \"click to reload\" link to the user.\n\n// The client version of the client code currently running in the\n// browser.\nvar autoupdateVersion = __meteor_runtime_config__.autoupdateVersion || \"unknown\";\nvar autoupdateVersionRefreshable =\n  __meteor_runtime_config__.autoupdateVersionRefreshable || \"unknown\";\n\n// The collection of acceptable client versions.\nClientVersions = new Mongo.Collection(\"meteor_autoupdate_clientVersions\");\n\nAutoupdate = {};\n\nAutoupdate.newClientAvailable = function () {\n  return !! ClientVersions.findOne({\n               _id: \"version\",\n               version: {$ne: autoupdateVersion} }) ||\n         !! ClientVersions.findOne({\n               _id: \"version-refreshable\",\n               version: {$ne: autoupdateVersionRefreshable} });\n};\nAutoupdate._ClientVersions = ClientVersions;  // Used by a self-test\n\nvar knownToSupportCssOnLoad = false;\n\nvar retry = new Retry({\n  // Unlike the stream reconnect use of Retry, which we want to be instant\n  // in normal operation, this is a wacky failure. We don't want to retry\n  // right away, we can start slowly.\n  //\n  // A better way than timeconstants here might be to use the knowledge\n  // of when we reconnect to help trigger these retries. Typically, the\n  // server fixing code will result in a restart and reconnect, but\n  // potentially the subscription could have a transient error.\n  minCount: 0, // don't do any immediate retries\n  baseTimeout: 30*1000 // start with 30s\n});\nvar failures = 0;\n\nAutoupdate._retrySubscription = function () {\n  Meteor.subscribe(\"meteor_autoupdate_clientVersions\", {\n    onError: function (error) {\n      Meteor._debug(\"autoupdate subscription failed:\", error);\n      failures++;\n      retry.retryLater(failures, function () {\n        // Just retry making the subscription, don't reload the whole\n        // page. While reloading would catch more cases (for example,\n        // the server went back a version and is now doing old-style hot\n        // code push), it would also be more prone to reload loops,\n        // which look really bad to the user. Just retrying the\n        // subscription over DDP means it is at least possible to fix by\n        // updating the server.\n        Autoupdate._retrySubscription();\n      });\n    },\n    onReady: function () {\n      if (Package.reload) {\n        var checkNewVersionDocument = function (doc) {\n          var self = this;\n          if (doc._id === 'version-refreshable' &&\n              doc.version !== autoupdateVersionRefreshable) {\n            autoupdateVersionRefreshable = doc.version;\n            // Switch out old css links for the new css links. Inspired by:\n            // https://github.com/guard/guard-livereload/blob/master/js/livereload.js#L710\n            var newCss = (doc.assets && doc.assets.allCss) || [];\n            var oldLinks = [];\n            _.each(document.getElementsByTagName('link'), function (link) {\n              if (link.className === '__meteor-css__') {\n                oldLinks.push(link);\n              }\n            });\n\n            var waitUntilCssLoads = function  (link, callback) {\n              var executeCallback = _.once(callback);\n              link.onload = function () {\n                knownToSupportCssOnLoad = true;\n                executeCallback();\n              };\n              if (! knownToSupportCssOnLoad) {\n                var id = Meteor.setInterval(function () {\n                  if (link.sheet) {\n                    executeCallback();\n                    Meteor.clearInterval(id);\n                  }\n                }, 50);\n              }\n            };\n\n            var removeOldLinks = _.after(newCss.length, function () {\n              _.each(oldLinks, function (oldLink) {\n                oldLink.parentNode.removeChild(oldLink);\n              });\n            });\n\n            var attachStylesheetLink = function (newLink) {\n              document.getElementsByTagName(\"head\").item(0).appendChild(newLink);\n\n              waitUntilCssLoads(newLink, function () {\n                Meteor.setTimeout(removeOldLinks, 200);\n              });\n            };\n\n            if (newCss.length !== 0) {\n              _.each(newCss, function (css) {\n                var newLink = document.createElement(\"link\");\n                newLink.setAttribute(\"rel\", \"stylesheet\");\n                newLink.setAttribute(\"type\", \"text/css\");\n                newLink.setAttribute(\"class\", \"__meteor-css__\");\n                newLink.setAttribute(\"href\", Meteor._relativeToSiteRootUrl(css.url));\n                attachStylesheetLink(newLink);\n              });\n            } else {\n              removeOldLinks();\n            }\n\n          }\n          else if (doc._id === 'version' && doc.version !== autoupdateVersion) {\n            handle && handle.stop();\n\n            if (Package.reload) {\n              Package.reload.Reload._reload();\n            }\n          }\n        };\n\n        var handle = ClientVersions.find().observe({\n          added: checkNewVersionDocument,\n          changed: checkNewVersionDocument\n        });\n      }\n    }\n  });\n};\nAutoupdate._retrySubscription();\n"
  },
  {
    "path": "packages/autoupdate/autoupdate_cordova.js",
    "content": "var autoupdateVersionCordova = __meteor_runtime_config__.autoupdateVersionCordova || \"unknown\";\n\n// The collection of acceptable client versions.\nClientVersions = new Mongo.Collection(\"meteor_autoupdate_clientVersions\");\n\nAutoupdate = {};\n\nAutoupdate.newClientAvailable = function() {\n  return !! ClientVersions.findOne({\n    _id: 'version-cordova',\n    version: {$ne: autoupdateVersionCordova}\n  });\n};\n\nvar retry = new Retry({\n  // Unlike the stream reconnect use of Retry, which we want to be instant\n  // in normal operation, this is a wacky failure. We don't want to retry\n  // right away, we can start slowly.\n  //\n  // A better way than timeconstants here might be to use the knowledge\n  // of when we reconnect to help trigger these retries. Typically, the\n  // server fixing code will result in a restart and reconnect, but\n  // potentially the subscription could have a transient error.\n  minCount: 0, // don't do any immediate retries\n  baseTimeout: 30*1000 // start with 30s\n});\nvar failures = 0;\n\nAutoupdate._retrySubscription = function() {\n  var appId = __meteor_runtime_config__.appId;\n  Meteor.subscribe(\"meteor_autoupdate_clientVersions\", appId, {\n    onError: function(error) {\n      console.log(\"autoupdate subscription failed:\", error);\n      failures++;\n      retry.retryLater(failures, function() {\n        // Just retry making the subscription, don't reload the whole\n        // page. While reloading would catch more cases (for example,\n        // the server went back a version and is now doing old-style hot\n        // code push), it would also be more prone to reload loops,\n        // which look really bad to the user. Just retrying the\n        // subscription over DDP means it is at least possible to fix by\n        // updating the server.\n        Autoupdate._retrySubscription();\n      });\n    },\n    onReady: function() {\n      if (Package.reload) {\n        var checkNewVersionDocument = function(doc) {\n          var self = this;\n          if (doc.version !== autoupdateVersionCordova) {\n            newVersionAvailable();\n          }\n        };\n\n        var handle = ClientVersions.find({_id: 'version-cordova'}).observe({\n          added: checkNewVersionDocument,\n          changed: checkNewVersionDocument\n        });\n      }\n    }\n  });\n};\n\nMeteor.startup(function() {\n  WebAppLocalServer.onNewVersionReady(function() {\n    if (Package.reload) {\n      Package.reload.Reload._reload();\n    }\n  });\n\n  Autoupdate._retrySubscription();\n});\n\nvar newVersionAvailable = function() {\n  WebAppLocalServer.checkForUpdates();\n}\n"
  },
  {
    "path": "packages/autoupdate/autoupdate_server.js",
    "content": "// Publish the current client versions to the client.  When a client\n// sees the subscription change and that there is a new version of the\n// client available on the server, it can reload.\n//\n// By default there are two current client versions. The refreshable client\n// version is identified by a hash of the client resources seen by the browser\n// that are refreshable, such as CSS, while the non refreshable client version\n// is identified by a hash of the rest of the client assets\n// (the HTML, code, and static files in the `public` directory).\n//\n// If the environment variable `AUTOUPDATE_VERSION` is set it will be\n// used as the client id instead.  You can use this to control when\n// the client reloads.  For example, if you want to only force a\n// reload on major changes, you can use a custom AUTOUPDATE_VERSION\n// which you only change when something worth pushing to clients\n// immediately happens.\n//\n// The server publishes a `meteor_autoupdate_clientVersions`\n// collection. There are two documents in this collection, a document\n// with _id 'version' which represents the non refreshable client assets,\n// and a document with _id 'version-refreshable' which represents the\n// refreshable client assets. Each document has a 'version' field\n// which is equivalent to the hash of the relevant assets. The refreshable\n// document also contains a list of the refreshable assets, so that the client\n// can swap in the new assets without forcing a page refresh. Clients can\n// observe changes on these documents to detect when there is a new\n// version available.\n//\n// In this implementation only two documents are present in the collection\n// the current refreshable client version and the current nonRefreshable client\n// version.  Developers can easily experiment with different versioning and\n// updating models by forking this package.\n\nvar Future = Npm.require(\"fibers/future\");\n\nAutoupdate = {};\n\n// The collection of acceptable client versions.\nClientVersions = new Mongo.Collection(\"meteor_autoupdate_clientVersions\",\n  { connection: null });\n\n// The client hash includes __meteor_runtime_config__, so wait until\n// all packages have loaded and have had a chance to populate the\n// runtime config before using the client hash as our default auto\n// update version id.\n\n// Note: Tests allow people to override Autoupdate.autoupdateVersion before\n// startup.\nAutoupdate.autoupdateVersion = null;\nAutoupdate.autoupdateVersionRefreshable = null;\nAutoupdate.autoupdateVersionCordova = null;\nAutoupdate.appId = __meteor_runtime_config__.appId = process.env.APP_ID;\n\nvar syncQueue = new Meteor._SynchronousQueue();\n\n// updateVersions can only be called after the server has fully loaded.\nvar updateVersions = function (shouldReloadClientProgram) {\n  // Step 1: load the current client program on the server and update the\n  // hash values in __meteor_runtime_config__.\n  if (shouldReloadClientProgram) {\n    WebAppInternals.reloadClientPrograms();\n  }\n\n  // If we just re-read the client program, or if we don't have an autoupdate\n  // version, calculate it.\n  if (shouldReloadClientProgram || Autoupdate.autoupdateVersion === null) {\n    Autoupdate.autoupdateVersion =\n      process.env.AUTOUPDATE_VERSION ||\n      WebApp.calculateClientHashNonRefreshable();\n  }\n  // If we just recalculated it OR if it was set by (eg) test-in-browser,\n  // ensure it ends up in __meteor_runtime_config__.\n  __meteor_runtime_config__.autoupdateVersion =\n    Autoupdate.autoupdateVersion;\n\n  Autoupdate.autoupdateVersionRefreshable =\n    __meteor_runtime_config__.autoupdateVersionRefreshable =\n      process.env.AUTOUPDATE_VERSION ||\n      WebApp.calculateClientHashRefreshable();\n\n  Autoupdate.autoupdateVersionCordova =\n    __meteor_runtime_config__.autoupdateVersionCordova =\n      process.env.AUTOUPDATE_VERSION ||\n      WebApp.calculateClientHashCordova();\n\n  // Step 2: form the new client boilerplate which contains the updated\n  // assets and __meteor_runtime_config__.\n  if (shouldReloadClientProgram) {\n    WebAppInternals.generateBoilerplate();\n  }\n\n  // XXX COMPAT WITH 0.8.3\n  if (! ClientVersions.findOne({current: true})) {\n    // To ensure apps with version of Meteor prior to 0.9.0 (in\n    // which the structure of documents in `ClientVersions` was\n    // different) also reload.\n    ClientVersions.insert({current: true});\n  }\n\n  if (! ClientVersions.findOne({_id: \"version\"})) {\n    ClientVersions.insert({\n      _id: \"version\",\n      version: Autoupdate.autoupdateVersion\n    });\n  } else {\n    ClientVersions.update(\"version\", { $set: {\n      version: Autoupdate.autoupdateVersion\n    }});\n  }\n\n  if (! ClientVersions.findOne({_id: \"version-cordova\"})) {\n    ClientVersions.insert({\n      _id: \"version-cordova\",\n      version: Autoupdate.autoupdateVersionCordova,\n      refreshable: false\n    });\n  } else {\n    ClientVersions.update(\"version-cordova\", { $set: {\n      version: Autoupdate.autoupdateVersionCordova\n    }});\n  }\n\n  // Use `onListening` here because we need to use\n  // `WebAppInternals.refreshableAssets`, which is only set after\n  // `WebApp.generateBoilerplate` is called by `main` in webapp.\n  WebApp.onListening(function () {\n    if (! ClientVersions.findOne({_id: \"version-refreshable\"})) {\n      ClientVersions.insert({\n        _id: \"version-refreshable\",\n        version: Autoupdate.autoupdateVersionRefreshable,\n        assets: WebAppInternals.refreshableAssets\n      });\n    } else {\n      ClientVersions.update(\"version-refreshable\", { $set: {\n        version: Autoupdate.autoupdateVersionRefreshable,\n        assets: WebAppInternals.refreshableAssets\n      }});\n    }\n  });\n};\n\nMeteor.publish(\n  \"meteor_autoupdate_clientVersions\",\n  function (appId) {\n    // `null` happens when a client doesn't have an appId and passes\n    // `undefined` to `Meteor.subscribe`. `undefined` is translated to\n    // `null` as JSON doesn't have `undefined.\n    check(appId, Match.OneOf(String, undefined, null));\n\n    // Don't notify clients using wrong appId such as mobile apps built with a\n    // different server but pointing at the same local url\n    if (Autoupdate.appId && appId && Autoupdate.appId !== appId)\n      return [];\n\n    return ClientVersions.find();\n  },\n  {is_auto: true}\n);\n\nMeteor.startup(function () {\n  updateVersions(false);\n});\n\nvar fut = new Future();\n\n// We only want 'refresh' to trigger 'updateVersions' AFTER onListen,\n// so we add a queued task that waits for onListen before 'refresh' can queue\n// tasks. Note that the `onListening` callbacks do not fire until after\n// Meteor.startup, so there is no concern that the 'updateVersions' calls from\n// 'refresh' will overlap with the `updateVersions` call from Meteor.startup.\n\nsyncQueue.queueTask(function () {\n  fut.wait();\n});\n\nWebApp.onListening(function () {\n  fut.return();\n});\n\nvar enqueueVersionsRefresh = function () {\n  syncQueue.queueTask(function () {\n    updateVersions(true);\n  });\n};\n\n// Listen for the special {refresh: 'client'} message, which signals that a\n// client asset has changed.\nprocess.on('message', Meteor.bindEnvironment(function (m) {\n  if (m && m.refresh === 'client') {\n    enqueueVersionsRefresh();\n  }\n}, \"handling client refresh message\"));\n\n// Another way to tell the process to refresh: send SIGHUP signal\nprocess.on('SIGHUP', Meteor.bindEnvironment(function () {\n  enqueueVersionsRefresh();\n}, \"handling SIGHUP signal for refresh\"));\n\n"
  },
  {
    "path": "packages/autoupdate/package.js",
    "content": "Package.describe({\n  summary: \"Update the client when new client code is available\",\n  version: '1.2.10'\n});\n\nPackage.onUse(function (api) {\n  api.use([\n    'webapp',\n    'check'\n  ], 'server');\n\n  api.use([\n    'tracker',\n    'retry'\n  ], 'client');\n\n  api.use([\n    'ddp',\n    'mongo',\n    'underscore'\n  ], ['client', 'server']);\n\n  api.use(['http', 'random'], 'web.cordova');\n\n  api.addFiles('autoupdate_server.js', 'server');\n  api.addFiles('autoupdate_client.js', 'web.browser');\n  api.addFiles('autoupdate_cordova.js', 'web.cordova');\n\n  api.export('Autoupdate');\n});\n"
  },
  {
    "path": "packages/babel-compiler/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/babel-compiler/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/babel-compiler/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"acorn\": {\n      \"version\": \"3.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-3.2.0.tgz\",\n      \"from\": \"acorn@>=3.2.0 <3.3.0\"\n    },\n    \"amdefine\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz\",\n      \"from\": \"amdefine@>=0.0.4\"\n    },\n    \"ansi-regex\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz\",\n      \"from\": \"ansi-regex@>=2.0.0 <3.0.0\"\n    },\n    \"ansi-styles\": {\n      \"version\": \"2.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz\",\n      \"from\": \"ansi-styles@>=2.2.1 <3.0.0\"\n    },\n    \"ast-types\": {\n      \"version\": \"0.8.16\",\n      \"resolved\": \"https://registry.npmjs.org/ast-types/-/ast-types-0.8.16.tgz\",\n      \"from\": \"ast-types@>=0.8.16 <0.9.0\"\n    },\n    \"babel-code-frame\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.8.0.tgz\",\n      \"from\": \"babel-code-frame@>=6.8.0 <7.0.0\"\n    },\n    \"babel-core\": {\n      \"version\": \"6.9.1\",\n      \"resolved\": \"https://registry.npmjs.org/babel-core/-/babel-core-6.9.1.tgz\",\n      \"from\": \"babel-core@>=6.9.1 <6.10.0\"\n    },\n    \"babel-generator\": {\n      \"version\": \"6.10.2\",\n      \"resolved\": \"https://registry.npmjs.org/babel-generator/-/babel-generator-6.10.2.tgz\",\n      \"from\": \"babel-generator@>=6.9.0 <7.0.0\"\n    },\n    \"babel-helper-builder-react-jsx\": {\n      \"version\": \"6.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.9.0.tgz\",\n      \"from\": \"babel-helper-builder-react-jsx@>=6.8.0 <7.0.0\"\n    },\n    \"babel-helper-call-delegate\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.8.0.tgz\",\n      \"from\": \"babel-helper-call-delegate@>=6.8.0 <7.0.0\"\n    },\n    \"babel-helper-define-map\": {\n      \"version\": \"6.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.9.0.tgz\",\n      \"from\": \"babel-helper-define-map@>=6.9.0 <7.0.0\"\n    },\n    \"babel-helper-function-name\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.8.0.tgz\",\n      \"from\": \"babel-helper-function-name@>=6.8.0 <7.0.0\"\n    },\n    \"babel-helper-get-function-arity\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.8.0.tgz\",\n      \"from\": \"babel-helper-get-function-arity@>=6.8.0 <7.0.0\"\n    },\n    \"babel-helper-hoist-variables\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.8.0.tgz\",\n      \"from\": \"babel-helper-hoist-variables@>=6.8.0 <7.0.0\"\n    },\n    \"babel-helper-optimise-call-expression\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.8.0.tgz\",\n      \"from\": \"babel-helper-optimise-call-expression@>=6.8.0 <7.0.0\"\n    },\n    \"babel-helper-regex\": {\n      \"version\": \"6.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.9.0.tgz\",\n      \"from\": \"babel-helper-regex@>=6.8.0 <7.0.0\"\n    },\n    \"babel-helper-replace-supers\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.8.0.tgz\",\n      \"from\": \"babel-helper-replace-supers@>=6.8.0 <7.0.0\"\n    },\n    \"babel-helpers\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.8.0.tgz\",\n      \"from\": \"babel-helpers@>=6.8.0 <7.0.0\"\n    },\n    \"babel-messages\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-messages/-/babel-messages-6.8.0.tgz\",\n      \"from\": \"babel-messages@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-check-es2015-constants\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.8.0.tgz\",\n      \"from\": \"babel-plugin-check-es2015-constants@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-syntax-async-functions\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.8.0.tgz\",\n      \"from\": \"babel-plugin-syntax-async-functions@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-syntax-async-generators\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.8.0.tgz\",\n      \"from\": \"babel-plugin-syntax-async-generators@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-syntax-flow\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.8.0.tgz\",\n      \"from\": \"babel-plugin-syntax-flow@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-syntax-jsx\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.8.0.tgz\",\n      \"from\": \"babel-plugin-syntax-jsx@>=6.3.13 <7.0.0\"\n    },\n    \"babel-plugin-syntax-object-rest-spread\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.8.0.tgz\",\n      \"from\": \"babel-plugin-syntax-object-rest-spread@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-syntax-trailing-function-commas\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.8.0.tgz\",\n      \"from\": \"babel-plugin-syntax-trailing-function-commas@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-arrow-functions\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-arrow-functions@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-block-scoped-functions\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-block-scoped-functions@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-block-scoping\": {\n      \"version\": \"6.10.1\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.10.1.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-block-scoping@>=6.10.1 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-classes\": {\n      \"version\": \"6.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.9.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-classes@>=6.9.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-computed-properties\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-computed-properties@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-destructuring\": {\n      \"version\": \"6.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.9.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-destructuring@>=6.9.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-for-of\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-for-of@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-function-name\": {\n      \"version\": \"6.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.9.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-function-name@>=6.9.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-literals\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-literals@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-modules-commonjs\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-modules-commonjs@>=6.8.0 <6.9.0\"\n    },\n    \"babel-plugin-transform-es2015-object-super\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-object-super@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-parameters\": {\n      \"version\": \"6.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.9.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-parameters@>=6.9.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-shorthand-properties\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-shorthand-properties@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-spread\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-spread@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-sticky-regex\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-sticky-regex@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-template-literals\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-template-literals@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-typeof-symbol\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-typeof-symbol@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es2015-unicode-regex\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es2015-unicode-regex@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es3-member-expression-literals\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es3-member-expression-literals/-/babel-plugin-transform-es3-member-expression-literals-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es3-member-expression-literals@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-es3-property-literals\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-es3-property-literals/-/babel-plugin-transform-es3-property-literals-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-es3-property-literals@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-flow-strip-types\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-flow-strip-types@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-object-rest-spread\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-object-rest-spread@>=6.8.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-react-display-name\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-react-display-name@>=6.3.13 <7.0.0\"\n    },\n    \"babel-plugin-transform-react-jsx\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-react-jsx@>=6.3.13 <7.0.0\"\n    },\n    \"babel-plugin-transform-react-jsx-source\": {\n      \"version\": \"6.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.9.0.tgz\",\n      \"from\": \"babel-plugin-transform-react-jsx-source@>=6.3.13 <7.0.0\"\n    },\n    \"babel-plugin-transform-regenerator\": {\n      \"version\": \"6.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.9.0.tgz\",\n      \"from\": \"babel-plugin-transform-regenerator@>=6.9.0 <7.0.0\"\n    },\n    \"babel-plugin-transform-runtime\": {\n      \"version\": \"6.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.9.0.tgz\",\n      \"from\": \"babel-plugin-transform-runtime@>=6.9.0 <6.10.0\"\n    },\n    \"babel-plugin-transform-strict-mode\": {\n      \"version\": \"6.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.8.0.tgz\",\n      \"from\": \"babel-plugin-transform-strict-mode@>=6.8.0 <7.0.0\"\n    },\n    \"babel-preset-meteor\": {\n      \"version\": \"6.11.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-preset-meteor/-/babel-preset-meteor-6.11.0.tgz\",\n      \"from\": \"babel-preset-meteor@>=6.11.0 <6.12.0\"\n    },\n    \"babel-preset-react\": {\n      \"version\": \"6.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.5.0.tgz\",\n      \"from\": \"babel-preset-react@>=6.5.0 <6.6.0\"\n    },\n    \"babel-register\": {\n      \"version\": \"6.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-register/-/babel-register-6.9.0.tgz\",\n      \"from\": \"babel-register@>=6.9.0 <7.0.0\"\n    },\n    \"babel-runtime\": {\n      \"version\": \"6.9.2\",\n      \"resolved\": \"https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.9.2.tgz\",\n      \"from\": \"babel-runtime@>=6.9.2 <6.10.0\"\n    },\n    \"babel-template\": {\n      \"version\": \"6.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-template/-/babel-template-6.9.0.tgz\",\n      \"from\": \"babel-template@>=6.9.0 <6.10.0\"\n    },\n    \"babel-traverse\": {\n      \"version\": \"6.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.9.0.tgz\",\n      \"from\": \"babel-traverse@>=6.9.0 <6.10.0\"\n    },\n    \"babel-types\": {\n      \"version\": \"6.10.2\",\n      \"resolved\": \"https://registry.npmjs.org/babel-types/-/babel-types-6.10.2.tgz\",\n      \"from\": \"babel-types@>=6.10.0 <6.11.0\"\n    },\n    \"babylon\": {\n      \"version\": \"6.8.1\",\n      \"resolved\": \"https://registry.npmjs.org/babylon/-/babylon-6.8.1.tgz\",\n      \"from\": \"babylon@>=6.8.1 <6.9.0\"\n    },\n    \"balanced-match\": {\n      \"version\": \"0.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz\",\n      \"from\": \"balanced-match@>=0.4.1 <0.5.0\"\n    },\n    \"brace-expansion\": {\n      \"version\": \"1.1.5\",\n      \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz\",\n      \"from\": \"brace-expansion@>=1.0.0 <2.0.0\"\n    },\n    \"chalk\": {\n      \"version\": \"1.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz\",\n      \"from\": \"chalk@>=1.1.0 <2.0.0\"\n    },\n    \"concat-map\": {\n      \"version\": \"0.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz\",\n      \"from\": \"concat-map@0.0.1\"\n    },\n    \"convert-source-map\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.2.0.tgz\",\n      \"from\": \"convert-source-map@>=1.2.0 <1.3.0\"\n    },\n    \"core-js\": {\n      \"version\": \"2.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/core-js/-/core-js-2.4.0.tgz\",\n      \"from\": \"core-js@>=2.4.0 <3.0.0\"\n    },\n    \"debug\": {\n      \"version\": \"2.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/debug/-/debug-2.2.0.tgz\",\n      \"from\": \"debug@>=2.1.1 <3.0.0\"\n    },\n    \"detect-indent\": {\n      \"version\": \"3.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/detect-indent/-/detect-indent-3.0.1.tgz\",\n      \"from\": \"detect-indent@>=3.0.1 <4.0.0\"\n    },\n    \"escape-string-regexp\": {\n      \"version\": \"1.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz\",\n      \"from\": \"escape-string-regexp@>=1.0.2 <2.0.0\"\n    },\n    \"esutils\": {\n      \"version\": \"2.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz\",\n      \"from\": \"esutils@>=2.0.2 <3.0.0\"\n    },\n    \"get-stdin\": {\n      \"version\": \"4.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz\",\n      \"from\": \"get-stdin@>=4.0.1 <5.0.0\"\n    },\n    \"globals\": {\n      \"version\": \"8.18.0\",\n      \"resolved\": \"https://registry.npmjs.org/globals/-/globals-8.18.0.tgz\",\n      \"from\": \"globals@>=8.3.0 <9.0.0\"\n    },\n    \"has-ansi\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz\",\n      \"from\": \"has-ansi@>=2.0.0 <3.0.0\"\n    },\n    \"home-or-tmp\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-1.0.0.tgz\",\n      \"from\": \"home-or-tmp@>=1.0.0 <2.0.0\"\n    },\n    \"invariant\": {\n      \"version\": \"2.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/invariant/-/invariant-2.2.1.tgz\",\n      \"from\": \"invariant@>=2.2.0 <3.0.0\"\n    },\n    \"is-finite\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/is-finite/-/is-finite-1.0.1.tgz\",\n      \"from\": \"is-finite@>=1.0.0 <2.0.0\"\n    },\n    \"js-tokens\": {\n      \"version\": \"1.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz\",\n      \"from\": \"js-tokens@>=1.0.2 <2.0.0\"\n    },\n    \"jsesc\": {\n      \"version\": \"0.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz\",\n      \"from\": \"jsesc@>=0.5.0 <0.6.0\"\n    },\n    \"json5\": {\n      \"version\": \"0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/json5/-/json5-0.4.0.tgz\",\n      \"from\": \"json5@>=0.4.0 <0.5.0\"\n    },\n    \"lodash\": {\n      \"version\": \"4.13.1\",\n      \"resolved\": \"https://registry.npmjs.org/lodash/-/lodash-4.13.1.tgz\",\n      \"from\": \"lodash@>=4.13.1 <4.14.0\"\n    },\n    \"loose-envify\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/loose-envify/-/loose-envify-1.2.0.tgz\",\n      \"from\": \"loose-envify@>=1.0.0 <2.0.0\"\n    },\n    \"magic-string\": {\n      \"version\": \"0.15.1\",\n      \"resolved\": \"https://registry.npmjs.org/magic-string/-/magic-string-0.15.1.tgz\",\n      \"from\": \"magic-string@>=0.15.0 <0.16.0\"\n    },\n    \"meteor-babel\": {\n      \"version\": \"0.11.6\",\n      \"resolved\": \"https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.11.6.tgz\",\n      \"from\": \"meteor-babel@0.11.6\"\n    },\n    \"meteor-babel-helpers\": {\n      \"version\": \"0.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/meteor-babel-helpers/-/meteor-babel-helpers-0.0.3.tgz\",\n      \"from\": \"meteor-babel-helpers@0.0.3\"\n    },\n    \"minimatch\": {\n      \"version\": \"2.0.10\",\n      \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz\",\n      \"from\": \"minimatch@>=2.0.3 <3.0.0\"\n    },\n    \"minimist\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz\",\n      \"from\": \"minimist@>=1.1.0 <2.0.0\"\n    },\n    \"mkdirp\": {\n      \"version\": \"0.5.1\",\n      \"resolved\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz\",\n      \"from\": \"mkdirp@>=0.5.1 <0.6.0\",\n      \"dependencies\": {\n        \"minimist\": {\n          \"version\": \"0.0.8\",\n          \"resolved\": \"https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz\",\n          \"from\": \"minimist@0.0.8\"\n        }\n      }\n    },\n    \"ms\": {\n      \"version\": \"0.7.1\",\n      \"resolved\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\",\n      \"from\": \"ms@0.7.1\"\n    },\n    \"number-is-nan\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz\",\n      \"from\": \"number-is-nan@>=1.0.0 <2.0.0\"\n    },\n    \"os-tmpdir\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.1.tgz\",\n      \"from\": \"os-tmpdir@>=1.0.1 <2.0.0\"\n    },\n    \"path-exists\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz\",\n      \"from\": \"path-exists@>=1.0.0 <2.0.0\"\n    },\n    \"path-is-absolute\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz\",\n      \"from\": \"path-is-absolute@>=1.0.0 <2.0.0\"\n    },\n    \"private\": {\n      \"version\": \"0.1.6\",\n      \"resolved\": \"https://registry.npmjs.org/private/-/private-0.1.6.tgz\",\n      \"from\": \"private@>=0.1.6 <0.2.0\"\n    },\n    \"regenerate\": {\n      \"version\": \"1.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/regenerate/-/regenerate-1.3.1.tgz\",\n      \"from\": \"regenerate@>=1.2.1 <2.0.0\"\n    },\n    \"regenerator-runtime\": {\n      \"version\": \"0.9.5\",\n      \"resolved\": \"https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.5.tgz\",\n      \"from\": \"regenerator-runtime@>=0.9.5 <0.10.0\"\n    },\n    \"regexpu-core\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz\",\n      \"from\": \"regexpu-core@>=1.0.0 <2.0.0\"\n    },\n    \"regjsgen\": {\n      \"version\": \"0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz\",\n      \"from\": \"regjsgen@>=0.2.0 <0.3.0\"\n    },\n    \"regjsparser\": {\n      \"version\": \"0.1.5\",\n      \"resolved\": \"https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz\",\n      \"from\": \"regjsparser@>=0.1.4 <0.2.0\"\n    },\n    \"reify\": {\n      \"version\": \"0.3.4\",\n      \"resolved\": \"https://registry.npmjs.org/reify/-/reify-0.3.4.tgz\",\n      \"from\": \"reify@>=0.3.4 <0.4.0\"\n    },\n    \"repeating\": {\n      \"version\": \"1.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz\",\n      \"from\": \"repeating@>=1.1.0 <2.0.0\"\n    },\n    \"shebang-regex\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz\",\n      \"from\": \"shebang-regex@>=1.0.0 <2.0.0\"\n    },\n    \"slash\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/slash/-/slash-1.0.0.tgz\",\n      \"from\": \"slash@>=1.0.0 <2.0.0\"\n    },\n    \"source-map\": {\n      \"version\": \"0.5.6\",\n      \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz\",\n      \"from\": \"source-map@>=0.5.0 <0.6.0\"\n    },\n    \"source-map-support\": {\n      \"version\": \"0.2.10\",\n      \"resolved\": \"https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.10.tgz\",\n      \"from\": \"source-map-support@>=0.2.10 <0.3.0\",\n      \"dependencies\": {\n        \"source-map\": {\n          \"version\": \"0.1.32\",\n          \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz\",\n          \"from\": \"source-map@0.1.32\"\n        }\n      }\n    },\n    \"strip-ansi\": {\n      \"version\": \"3.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz\",\n      \"from\": \"strip-ansi@>=3.0.0 <4.0.0\"\n    },\n    \"supports-color\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz\",\n      \"from\": \"supports-color@>=2.0.0 <3.0.0\"\n    },\n    \"to-fast-properties\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.2.tgz\",\n      \"from\": \"to-fast-properties@>=1.0.1 <2.0.0\"\n    },\n    \"user-home\": {\n      \"version\": \"1.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz\",\n      \"from\": \"user-home@>=1.1.1 <2.0.0\"\n    },\n    \"vlq\": {\n      \"version\": \"0.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/vlq/-/vlq-0.2.1.tgz\",\n      \"from\": \"vlq@>=0.2.1 <0.3.0\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/babel-compiler/README.md",
    "content": "[Babel](http://babeljs.io/) is a parser and transpiler for ECMAScript 2015\nsyntax and beyond, which enables some upcoming JavaScript syntax features\nto be used in today's browsers and runtimes.\n\nMeteor's Babel support consists of the following core packages:\n\n* `babel-compiler` - Exposes the [Babel API](https://babeljs.io/docs/usage/api/)\n  on the symbol `Babel`.  For example, `Babel.compile(source, options)`.\n\n* `babel-runtime` - Meteor versions of the external helpers used by\n  Babel-generated code.  Meteor's core packages must run on IE 8 without\n  polyfills, so these helpers cannot assume the existence of\n  `Object.defineProperty`, `Object.freeze`, and so on.\n\n### Babel API\n\nThe `babel-compiler` package exports the `Babel` symbol, which exposes\nfunctionality provided by the\n[`meteor-babel`](https://www.npmjs.com/package/meteor-babel) NPM package,\nwhich is in turn implmented using the\n[`babel-core`](https://www.npmjs.com/package/babel-core) NPM package.\nNote that you can only use the `babel-compiler` package on the server.\n\nExample:\n\n```js\nvar babelOptions = Babel.getDefaultOptions();\n\n// Modify the default options, if necessary:\nbabelOptions.whitelist = [\n  \"es6.blockScoping\", // For `let`\n  \"es6.arrowFunctions\" // For `=>`\n];\n\nvar result = Babel.compile(\n  \"let square = (x) => x*x;\",\n  babelOptions\n);\n\n// result.code will be something like\n// \"var square = function (x) {\\n  return x * x;\\n};\"\n```\n\nUse `Babel.compile(source)` to transpile code using a set of default\noptions that work well for Meteor code.\n\n### `.babelrc` configuration files\n\nLike other Babel-compiled projects, a Meteor project that uses the\n`ecmascript` package can specify custom Babel plugins and presets (which\nare just groups of plugins) in JSON files named `.babelrc`.\n\nFor example, to enable the Babel\n[transform](https://www.npmjs.com/package/babel-plugin-transform-class-properties)\nthat supports [class\nproperties](https://github.com/jeffmo/es-class-fields-and-static-properties),\nyou should\n\n  1. run `meteor npm install --save-dev babel-plugin-transform-class-properties`\n  2. put the following in a `.babelrc` file in the root of your project:\n```js\n{\n  \"plugins\": [\"transform-class-properties\"]\n}\n```\n\nIf you want to include all Stage 1 transforms (including the class\nproperties plugin), you could use a preset instead:\n\n```sh\nmeteor npm install --save-dev babel-preset-stage-1\n```\n\nand then (in your `.babelrc` file):\n\n```js\n{\n  \"presets\": [\"stage-1\"]\n}\n```\n\nNote that you should never need to include the `es2015` or `react`\ntransforms, as that functionality is already provided by the default\n`babel-preset-meteor` preset.\n\nAny plugins and transforms that you list in your `.babelrc` file will be\nincluded after `babel-preset-meteor`.\n\nTo be considered by the `babel-compiler` package, `.babelrc` files must be\ncontained within your root application directory.\n\n### Resources:\n\n* [API docs](https://babeljs.io/docs/usage/api/)\n* [List of transformers](https://babeljs.io/docs/usage/transformers/)\n"
  },
  {
    "path": "packages/babel-compiler/babel-compiler.js",
    "content": "/**\n * A compiler that can be instantiated with features and used inside\n * Plugin.registerCompiler\n * @param {Object} extraFeatures The same object that getDefaultOptions takes\n */\nBabelCompiler = function BabelCompiler(extraFeatures) {\n  this.extraFeatures = extraFeatures;\n  this._babelrcCache = null;\n  this._babelrcWarnings = Object.create(null);\n};\n\nvar BCp = BabelCompiler.prototype;\nvar excludedFileExtensionPattern = /\\.es5\\.js$/i;\nvar hasOwn = Object.prototype.hasOwnProperty;\n\nBCp.processFilesForTarget = function (inputFiles) {\n  // Reset this cache for each batch processed.\n  this._babelrcCache = null;\n\n  inputFiles.forEach(function (inputFile) {\n    var toBeAdded = this.processOneFileForTarget(inputFile);\n    if (toBeAdded) {\n      inputFile.addJavaScript(toBeAdded);\n    }\n  }, this);\n};\n\n// Returns an object suitable for passing to inputFile.addJavaScript, or\n// null to indicate there was an error, and nothing should be added.\nBCp.processOneFileForTarget = function (inputFile, source) {\n  this._babelrcCache = this._babelrcCache || Object.create(null);\n\n  if (typeof source !== \"string\") {\n    // Other compiler plugins can call processOneFileForTarget with a\n    // source string that's different from inputFile.getContentsAsString()\n    // if they've already done some processing.\n    source = inputFile.getContentsAsString();\n  }\n\n  var packageName = inputFile.getPackageName();\n  var inputFilePath = inputFile.getPathInPackage();\n  var outputFilePath = inputFilePath;\n  var fileOptions = inputFile.getFileOptions();\n  var toBeAdded = {\n    sourcePath: inputFilePath,\n    path: outputFilePath,\n    data: source,\n    hash: inputFile.getSourceHash(),\n    sourceMap: null,\n    bare: !! fileOptions.bare\n  };\n  var cacheDeps = {\n    sourceHash: toBeAdded.hash\n  };\n\n  // If you need to exclude a specific file within a package from Babel\n  // compilation, pass the { transpile: false } options to api.addFiles\n  // when you add that file.\n  if (fileOptions.transpile !== false &&\n      // Bare files should not be transpiled by Babel, because they do not\n      // have access to CommonJS APIs like `require`, `module`, `exports`.\n      ! toBeAdded.bare &&\n      // If you need to exclude a specific file within an app from Babel\n      // compilation, give it the following file extension: .es5.js\n      ! excludedFileExtensionPattern.test(inputFilePath)) {\n\n    var targetCouldBeInternetExplorer8 =\n      inputFile.getArch() === \"web.browser\";\n\n    var extraFeatures = Object.assign({}, this.extraFeatures);\n\n    if (! extraFeatures.hasOwnProperty(\"jscript\")) {\n      // Perform some additional transformations to improve compatibility\n      // in older browsers (e.g. wrapping named function expressions, per\n      // http://kiro.me/blog/nfe_dilemma.html).\n      extraFeatures.jscript = targetCouldBeInternetExplorer8;\n    }\n\n    if (inputFile.isPackageFile()) {\n      // When compiling package files, handle import/export syntax using\n      // the official Babel plugin, so that package authors won't publish\n      // code that relies on module.import and module.export, because such\n      // code would fail on Meteor versions before 1.3.3.  When compiling\n      // application files, however, it's fine to rely on module.import\n      // and module.export, and the developer experience will be much\n      // better for it: faster compilation, real variables, import\n      // statements inside conditional statements, etc.\n      //\n      // TODO Remove this once we are confident enough developers have\n      // updated to a version of Meteor that supports module.import and\n      // module.export.\n      extraFeatures.legacyModules = true;\n    }\n\n    var babelOptions = Babel.getDefaultOptions(extraFeatures);\n\n    this.inferExtraBabelOptions(inputFile, babelOptions, cacheDeps);\n\n    babelOptions.sourceMap = true;\n    babelOptions.filename =\n      babelOptions.sourceFileName = packageName\n      ? \"/packages/\" + packageName + \"/\" + inputFilePath\n      : \"/\" + inputFilePath;\n\n    babelOptions.sourceMapTarget = babelOptions.filename + \".map\";\n\n    try {\n      var result = profile('Babel.compile', function () {\n        return Babel.compile(source, babelOptions, cacheDeps);\n      });\n    } catch (e) {\n      if (e.loc) {\n        inputFile.error({\n          message: e.message,\n          line: e.loc.line,\n          column: e.loc.column,\n        });\n\n        return null;\n      }\n\n      throw e;\n    }\n\n    toBeAdded.data = result.code;\n    toBeAdded.hash = result.hash;\n    toBeAdded.sourceMap = result.map;\n  }\n\n  return toBeAdded;\n};\n\nBCp.setDiskCacheDirectory = function (cacheDir) {\n  Babel.setCacheDir(cacheDir);\n};\n\nfunction profile(name, func) {\n  if (typeof Profile !== 'undefined') {\n    return Profile.time(name, func);\n  } else {\n    return func();\n  }\n};\n\nBCp.inferExtraBabelOptions = function (inputFile, babelOptions, cacheDeps) {\n  if (! inputFile.require ||\n      ! inputFile.findControlFile ||\n      ! inputFile.readAndWatchFile) {\n    return false;\n  }\n\n  return (\n    // If a .babelrc exists, it takes precedence over package.json.\n    this._inferFromBabelRc(inputFile, babelOptions, cacheDeps) ||\n    this._inferFromPackageJson(inputFile, babelOptions, cacheDeps)\n  );\n};\n\nBCp._inferFromBabelRc = function (inputFile, babelOptions, cacheDeps) {\n  var babelrcPath = inputFile.findControlFile(\".babelrc\");\n  if (babelrcPath) {\n    if (! hasOwn.call(this._babelrcCache, babelrcPath)) {\n      this._babelrcCache[babelrcPath] =\n        JSON.parse(inputFile.readAndWatchFile(babelrcPath));\n    }\n\n    return this._inferHelper(\n      inputFile,\n      babelOptions,\n      babelrcPath,\n      this._babelrcCache[babelrcPath],\n      cacheDeps\n    );\n  }\n};\n\nBCp._inferFromPackageJson = function (inputFile, babelOptions, cacheDeps) {\n  var pkgJsonPath = inputFile.findControlFile(\"package.json\");\n  if (pkgJsonPath) {\n    if (! hasOwn.call(this._babelrcCache, pkgJsonPath)) {\n      this._babelrcCache[pkgJsonPath] = JSON.parse(\n        inputFile.readAndWatchFile(pkgJsonPath)\n      ).babel || null;\n    }\n\n    return this._inferHelper(\n      inputFile,\n      babelOptions,\n      pkgJsonPath,\n      this._babelrcCache[pkgJsonPath],\n      cacheDeps\n    );\n  }\n};\n\nBCp._inferHelper = function (\n  inputFile,\n  babelOptions,\n  controlFilePath,\n  babelrc,\n  cacheDeps\n) {\n  if (! babelrc) {\n    return false;\n  }\n\n  var compiler = this;\n  var inferredPresets = [];\n  var result;\n\n  function infer(listName, prefix) {\n    var list = babelrc[listName];\n    if (! Array.isArray(list) || list.length === 0) {\n      return;\n    }\n\n    function req(id) {\n      try {\n        return reqMightThrow(id);\n      } catch (e) {\n        if (e.code !== \"MODULE_NOT_FOUND\") {\n          throw e;\n        }\n\n        if (! hasOwn.call(compiler._babelrcWarnings, id)) {\n          compiler._babelrcWarnings[id] = controlFilePath;\n\n          console.error(\n            \"Warning: unable to resolve \" +\n              JSON.stringify(id) +\n              \" in \" + listName +\n              \" of \" + controlFilePath\n          );\n        }\n\n        return null;\n      }\n    }\n\n    function reqMightThrow(id) {\n      var isTopLevel = \"./\".indexOf(id.charAt(0)) < 0;\n      var presetOrPlugin;\n      var presetOrPluginMeta;\n\n      if (isTopLevel) {\n        try {\n          // If the identifier is top-level, try to prefix it with\n          // \"babel-plugin-\" or \"babel-preset-\".\n          presetOrPlugin = inputFile.require(prefix + id);\n          presetOrPluginMeta = inputFile.require(\n            packageNameFromTopLevelModuleId(prefix + id) + '/package.json');\n        } catch (e) {\n          if (e.code !== \"MODULE_NOT_FOUND\") {\n            throw e;\n          }\n          // Fall back to requiring the plugin as-is if the prefix failed.\n          presetOrPlugin = inputFile.require(id);\n          presetOrPluginMeta = inputFile.require(\n            packageNameFromTopLevelModuleId(id) + '/package.json');\n        }\n\n      } else {\n        // If the identifier is not top-level, but relative or absolute,\n        // then it will be required as-is, so that you can implement your\n        // own Babel plugins locally, rather than always using plugins\n        // installed from npm.\n        presetOrPlugin = inputFile.require(id, controlFilePath);\n\n        // Note that inputFile.readAndWatchFileWithHash converts module\n        // identifers to OS-specific paths if necessary.\n        var absId = inputFile.resolve(id, controlFilePath);\n        var info = inputFile.readAndWatchFileWithHash(absId);\n\n        presetOrPluginMeta = {\n          name: absId,\n          version: info.hash\n        };\n      }\n\n      return {\n        name: presetOrPluginMeta.name,\n        version: presetOrPluginMeta.version,\n        module: presetOrPlugin.__esModule\n          ? presetOrPlugin.default\n          : presetOrPlugin\n      };\n    }\n\n    var filtered = [];\n\n    list.forEach(function (item, i) {\n      if (typeof item === \"string\") {\n        result = req(item);\n        if (! result) return;\n        item = result.module;\n        cacheDeps[result.name] = result.version;\n      } else if (Array.isArray(item) &&\n                 typeof item[0] === \"string\") {\n        item = item.slice(); // defensive copy\n        result = req(item[0]);\n        if (! result) return;\n        item[0] = result.module;\n        cacheDeps[result.name] = result.version;\n      }\n      // else, an object { presets: [], plugins: [] } from meteorBabel, whose\n      // version is used for the cache hash internally.\n\n      filtered.push(item);\n    });\n\n    if (listName === \"plugins\") {\n      // Turn any additional plugins into their own preset, so that they\n      // can come before babel-preset-meteor.\n      inferredPresets.push({ plugins: filtered });\n    } else if (listName === \"presets\") {\n      inferredPresets.push.apply(inferredPresets, filtered);\n    }\n  }\n\n  infer(\"presets\", \"babel-preset-\");\n  infer(\"plugins\", \"babel-plugin-\");\n\n  if (inferredPresets.length > 0) {\n    babelOptions.presets.push.apply(\n      babelOptions.presets,\n      inferredPresets\n    );\n\n    return true;\n  }\n\n  return false;\n};\n\n// 'react-hot-loader/babel' => 'react-hot-loader'\nfunction packageNameFromTopLevelModuleId(id) {\n  return id.split(\"/\", 1)[0];\n}\n"
  },
  {
    "path": "packages/babel-compiler/babel.js",
    "content": "var meteorBabel = Npm.require('meteor-babel');\n\n/**\n * Returns a new object containing default options appropriate for\n */\nfunction getDefaultOptions(extraFeatures) {\n  // See https://github.com/meteor/babel/blob/master/options.js for more\n  // information about what the default options are.\n  var options = meteorBabel.getDefaultOptions(extraFeatures);\n\n  // The sourceMap option should probably be removed from the default\n  // options returned by meteorBabel.getDefaultOptions.\n  delete options.sourceMap;\n\n  return options;\n}\n\nBabel = {\n  getDefaultOptions: getDefaultOptions,\n\n  // Deprecated, now a no-op.\n  validateExtraFeatures: Function.prototype,\n\n  compile: function (source, options) {\n    options = options || getDefaultOptions();\n    return meteorBabel.compile(source, options);\n  },\n\n  setCacheDir: function (cacheDir) {\n    meteorBabel.setCacheDir(cacheDir);\n  }\n};\n"
  },
  {
    "path": "packages/babel-compiler/package.js",
    "content": "Package.describe({\n  name: \"babel-compiler\",\n  summary: \"Parser/transpiler for ECMAScript 2015+ syntax\",\n  // Tracks the npm version below.  Use wrap numbers to increment\n  // without incrementing the npm version.  Hmm-- Apparently this\n  // isn't possible because you can't publish a non-recommended\n  // release with package versions that don't have a pre-release\n  // identifier at the end (eg, -dev)\n  version: '6.8.3'\n});\n\nNpm.depends({\n  'meteor-babel': '0.11.6',\n});\n\nPackage.onUse(function (api) {\n  api.use('ecmascript-runtime');\n\n  api.addFiles([\n    'babel.js',\n    'babel-compiler.js'\n  ], 'server');\n\n  api.export('Babel', 'server');\n  api.export('BabelCompiler', 'server');\n});\n"
  },
  {
    "path": "packages/babel-runtime/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/babel-runtime/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/babel-runtime/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"meteor-babel-helpers\": {\n      \"version\": \"0.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/meteor-babel-helpers/-/meteor-babel-helpers-0.0.3.tgz\",\n      \"from\": \"https://registry.npmjs.org/meteor-babel-helpers/-/meteor-babel-helpers-0.0.3.tgz\"\n    },\n    \"regenerator-runtime\": {\n      \"version\": \"0.9.5\",\n      \"resolved\": \"https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.5.tgz\",\n      \"from\": \"regenerator-runtime@0.9.5\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/babel-runtime/README.md",
    "content": "# babel-runtime\n\nMeteor maintains a version of the runtime helpers needed by Babel-transpiled code.\nIn most cases, the code is copied from Babel's helper implementations, though we\nhave also made some changes.\n\nBenefits of maintaining our own package include:\n\n* IE 8 support.  Babel's helpers target IE 9 and do not work in IE 8, but generally\n  IE 8 support can be achieved with only minor changes.\n\n* Backwards-compatibility.  When the Babel compiler changes, the helpers sometimes\n  change.  Our Babel package can keep old helpers for back-compat.  (If we change\n  over to publishing original ES6 code in packages instead of transpiled code, this\n  becomes less important.)\n\n* Client-side code size.  We've made the helpers file as small as possible.\n\n## Helpers\n\nHelpers needed for each transform **as of [Babel v5.6.15](https://github.com/babel/babel/tree/a1a46882fddc596a47e0e29017c5440ab6d7d9c0/src/babel/transformation/transformers)**:\n\n* es3.propertyLiterals: None\n* es3.memberExpressionLiterals: None\n* es6.arrowFunctions: None\n* es6.templateLiterals\n  * `taggedTemplateLiteralLoose`\n* es6.classes\n  * `inherits`\n  * `classCallCheck`\n  * `createClass` (only for getter/setters)\n  * Excluded because only for decorator support(2): `createDecoratedClass`, `defineDecoratedPropertyDescriptor`\n* es6.constants: None\n* es6.blockScoping: None\n  * Excluded because only for spec mode(1): `temporalUndefined`, `temporalAssertDefined`\n* es6.properties.shorthand: None\n* es6.properties.computed: None\n  * Excluded because only for non-loose mode(1): `defineProperty`\n* es6.parameters: None\n* es6.spread\n  * `bind` (for `new A(...b)`)\n* es6.forOf: None\n* es7.objectRestSpread\n  * `_extends`\n  * Everything in es6.destructuring\n* es6.destructuring\n  * `objectWithoutProperties`\n  * `objectDestructuringEmpty`\n* es7.trailingFunctionCommas: None\n* flow: None\n\nFootnotes:\n\n1. A transform can be run in \"loose,\" normal, or \"spec\" mode, with \"loose\" providing\n   the fastest, most lightweight, and usually most browser-compatible transpilation,\n   while \"spec\" mode tries extra hard to be spec-compliant at the expense of those\n   things.  We've found that \"loose\" mode is the best mode for production code for\n   every transform we've looked at.\n\n2. Decorators are still a Stage 1 proposal and are only implemented in Babel as\n   an experiment."
  },
  {
    "path": "packages/babel-runtime/babel-runtime.js",
    "content": "var hasOwn = Object.prototype.hasOwnProperty;\nvar S = typeof Symbol === \"function\" ? Symbol : {};\nvar iteratorSymbol = S.iterator || \"@@iterator\";\n\nmeteorBabelHelpers = require(\"meteor-babel-helpers\");\n\nvar BabelRuntime = {\n  // es6.templateLiterals\n  // Constructs the object passed to the tag function in a tagged\n  // template literal.\n  taggedTemplateLiteralLoose: function (strings, raw) {\n    // Babel's own version of this calls Object.freeze on `strings` and\n    // `strings.raw`, but it doesn't seem worth the compatibility and\n    // performance concerns.  If you're writing code against this helper,\n    // don't add properties to these objects.\n    strings.raw = raw;\n    return strings;\n  },\n\n  // es6.classes\n  // Checks that a class constructor is being called with `new`, and throws\n  // an error if it is not.\n  classCallCheck: function (instance, Constructor) {\n    if (!(instance instanceof Constructor)) {\n      throw new TypeError(\"Cannot call a class as a function\");\n    }\n  },\n\n  // es6.classes\n  inherits: function (subClass, superClass) {\n    if (typeof superClass !== \"function\" && superClass !== null) {\n      throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass);\n    }\n\n    if (superClass) {\n      if (Object.create) {\n        // All but IE 8\n        subClass.prototype = Object.create(superClass.prototype, {\n          constructor: {\n            value: subClass,\n            enumerable: false,\n            writable: true,\n            configurable: true\n          }\n        });\n      } else {\n        // IE 8 path.  Slightly worse for modern browsers, because `constructor`\n        // is enumerable and shows up in the inspector unnecessarily.\n        // It's not an \"own\" property of any instance though.\n        //\n        // For correctness when writing code,\n        // don't enumerate all the own-and-inherited properties of an instance\n        // of a class and expect not to find `constructor` (but who does that?).\n        var F = function () {\n          this.constructor = subClass;\n        };\n        F.prototype = superClass.prototype;\n        subClass.prototype = new F();\n      }\n\n      // For modern browsers, this would be `subClass.__proto__ = superClass`,\n      // but IE <=10 don't support `__proto__`, and in this case the difference\n      // would be detectable; code that works in modern browsers could easily\n      // fail on IE 8 if we ever used the `__proto__` trick.\n      //\n      // There's no perfect way to make static methods inherited if they are\n      // assigned after declaration of the classes.  The best we can do is\n      // to copy them.  In other words, when you write `class Foo\n      // extends Bar`, we copy the static methods from Bar onto Foo, but future\n      // ones are not copied.\n      //\n      // For correctness when writing code, don't add static methods to a class\n      // after you subclass it.\n\n      // The ecmascript-runtime package provides adequate polyfills for\n      // all of these Object.* functions (and Array#forEach), and anyone\n      // using babel-runtime is almost certainly using it because of the\n      // ecmascript package, which also implies ecmascript-runtime.\n      Object.getOwnPropertyNames(superClass).forEach(function (k) {\n        // This property descriptor dance preserves getter/setter behavior\n        // in browsers that support accessor properties (all except\n        // IE8). In IE8, the superClass can't have accessor properties\n        // anyway, so this code is still safe.\n        var descriptor = Object.getOwnPropertyDescriptor(superClass, k);\n        if (descriptor && typeof descriptor === \"object\") {\n          if (Object.getOwnPropertyDescriptor(subClass, k)) {\n            // If subClass already has a property by this name, then it\n            // would not be inherited, so it should not be copied. This\n            // notably excludes properties like .prototype and .name.\n            return;\n          }\n\n          Object.defineProperty(subClass, k, descriptor);\n        }\n      });\n    }\n  },\n\n  createClass: (function () {\n    var hasDefineProperty = false;\n    try {\n      // IE 8 has a broken Object.defineProperty, so feature-test by\n      // trying to call it.\n      Object.defineProperty({}, 'x', {});\n      hasDefineProperty = true;\n    } catch (e) {}\n\n    function defineProperties(target, props) {\n      for (var i = 0; i < props.length; i++) {\n        var descriptor = props[i];\n        descriptor.enumerable = descriptor.enumerable || false;\n        descriptor.configurable = true;\n        if (\"value\" in descriptor) descriptor.writable = true;\n        Object.defineProperty(target, descriptor.key, descriptor);\n      }\n    }\n\n    return function (Constructor, protoProps, staticProps) {\n      if (! hasDefineProperty) {\n        // e.g. `class Foo { get bar() {} }`.  If you try to use getters and\n        // setters in IE 8, you will get a big nasty error, with or without\n        // Babel.  I don't know of any other syntax features besides getters\n        // and setters that will trigger this error.\n        throw new Error(\n          \"Your browser does not support this type of class property.  \" +\n            \"For example, Internet Explorer 8 does not support getters and \" +\n            \"setters.\");\n      }\n\n      if (protoProps) defineProperties(Constructor.prototype, protoProps);\n      if (staticProps) defineProperties(Constructor, staticProps);\n      return Constructor;\n    };\n  })(),\n\n  \"typeof\": function (obj) {\n    return obj && obj.constructor === Symbol ? \"symbol\" : typeof obj;\n  },\n\n  possibleConstructorReturn: function (self, call) {\n    if (! self) {\n      throw new ReferenceError(\n        \"this hasn't been initialised - super() hasn't been called\"\n      );\n    }\n\n    var callType = typeof call;\n    if (call &&\n        callType === \"function\" ||\n        callType === \"object\") {\n      return call;\n    }\n\n    return self;\n  },\n\n  interopRequireDefault: function (obj) {\n    return obj && obj.__esModule ? obj : { 'default': obj };\n  },\n\n  interopRequireWildcard: function (obj) {\n    if (obj && obj.__esModule) {\n      return obj;\n    }\n\n    var newObj = {};\n\n    if (obj != null) {\n      for (var key in obj) {\n        if (hasOwn.call(obj, key)) {\n          newObj[key] = obj[key];\n        }\n      }\n    }\n\n    newObj[\"default\"] = obj;\n    return newObj;\n  },\n\n  interopExportWildcard: function (obj, defaults) {\n    var newObj = defaults({}, obj);\n    delete newObj[\"default\"];\n    return newObj;\n  },\n\n  defaults: function (obj, defaults) {\n    Object.getOwnPropertyNames(defaults).forEach(function (key) {\n      var desc = Object.getOwnPropertyDescriptor(defaults, key);\n      if (desc && desc.configurable && typeof obj[key] === \"undefined\") {\n        Object.defineProperty(obj, key, desc);\n      }\n    });\n\n    return obj;\n  },\n\n  // es7.objectRestSpread and react (JSX)\n  \"extends\": Object.assign || (function (target) {\n    for (var i = 1; i < arguments.length; i++) {\n      var source = arguments[i];\n      for (var key in source) {\n        if (hasOwn.call(source, key)) {\n          target[key] = source[key];\n        }\n      }\n    }\n    return target;\n  }),\n\n  // es6.destructuring\n  objectWithoutProperties: function (obj, keys) {\n    var target = {};\n    outer: for (var i in obj) {\n      if (! hasOwn.call(obj, i)) continue;\n      for (var j = 0; j < keys.length; j++) {\n        if (keys[j] === i) continue outer;\n      }\n      target[i] = obj[i];\n    }\n    return target;\n  },\n\n  // es6.destructuring\n  objectDestructuringEmpty: function (obj) {\n    if (obj == null) throw new TypeError(\"Cannot destructure undefined\");\n  },\n\n  // es6.spread\n  bind: Function.prototype.bind || (function () {\n    var isCallable = function (value) { return typeof value === 'function'; };\n    var $Object = Object;\n    var to_string = Object.prototype.toString;\n    var array_slice = Array.prototype.slice;\n    var array_concat = Array.prototype.concat;\n    var array_push = Array.prototype.push;\n    var max = Math.max;\n    var Empty = function Empty() {};\n\n    // Copied from es5-shim.js (3ac7942).  See original for more comments.\n    return function bind(that) {\n      var target = this;\n      if (!isCallable(target)) {\n        throw new TypeError('Function.prototype.bind called on incompatible ' + target);\n      }\n\n      var args = array_slice.call(arguments, 1);\n\n      var bound;\n      var binder = function () {\n\n        if (this instanceof bound) {\n          var result = target.apply(\n            this,\n            array_concat.call(args, array_slice.call(arguments))\n          );\n          if ($Object(result) === result) {\n            return result;\n          }\n          return this;\n        } else {\n          return target.apply(\n            that,\n            array_concat.call(args, array_slice.call(arguments))\n          );\n        }\n      };\n\n      var boundLength = max(0, target.length - args.length);\n\n      var boundArgs = [];\n      for (var i = 0; i < boundLength; i++) {\n        array_push.call(boundArgs, '$' + i);\n      }\n\n      // Create a Function from source code so that it has the right `.length`.\n      // Probably not important for Babel.  This code violates CSPs that ban\n      // `eval`, but the browsers that need this polyfill don't have CSP!\n      bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder);\n\n      if (target.prototype) {\n        Empty.prototype = target.prototype;\n        bound.prototype = new Empty();\n        Empty.prototype = null;\n      }\n\n      return bound;\n    };\n\n  })(),\n\n  toConsumableArray: function (arr) {\n    if (Array.isArray(arr)) {\n      for (var i = arr.length - 1, arr2 = Array(i + 1); i >= 0; --i) {\n        arr2[i] = arr[i];\n      }\n\n      return arr2;\n    }\n\n    return Array.from(arr);\n  },\n\n  toArray: function (arr) {\n    return Array.isArray(arr) ? arr : Array.from(arr);\n  },\n\n  slicedToArray: function (iterable, limit) {\n    if (Array.isArray(iterable)) {\n      return iterable;\n    }\n\n    if (iterable) {\n      var it = iterable[iteratorSymbol]();\n      var result = [];\n      var info;\n\n      if (typeof limit !== \"number\") {\n        limit = Infinity;\n      }\n\n      while (result.length < limit &&\n             ! (info = it.next()).done) {\n        result.push(info.value);\n      }\n\n      return result;\n    }\n\n    throw new TypeError(\n      \"Invalid attempt to destructure non-iterable instance\"\n    );\n  },\n\n  slice: Array.prototype.slice\n};\n\n// Use meteorInstall to install all of the above helper functions within\n// node_modules/babel-runtime/helpers.\nObject.keys(BabelRuntime).forEach(function (helperName) {\n  var helpers = {};\n\n  helpers[helperName + \".js\"] = function (require, exports, module) {\n    module.exports = BabelRuntime[helperName];\n  };\n\n  meteorInstall({\n    node_modules: {\n      \"babel-runtime\": {\n        helpers: helpers\n      }\n    }\n  });\n});\n\n// Use meteorInstall to install the regenerator runtime at\n// node_modules/babel-runtime/regenerator.\nmeteorInstall({\n  node_modules: {\n    \"babel-runtime\": {\n      \"regenerator.js\": function (r, e, module) {\n        // Note that we use the require function provided to the\n        // babel-runtime.js file, not the one named 'r' above.\n        var runtime = require(\"regenerator-runtime\");\n\n        // If Promise.asyncApply is defined, use it to wrap calls to\n        // runtime.async so that the entire async function will run in its\n        // own Fiber, not just the code that comes after the first await.\n        if (typeof Promise === \"function\" &&\n            typeof Promise.asyncApply === \"function\") {\n          var realAsync = runtime.async;\n          runtime.async = function () {\n            return Promise.asyncApply(realAsync, runtime, arguments);\n          };\n        }\n\n        module.exports = runtime;\n      }\n    }\n  }\n});\n"
  },
  {
    "path": "packages/babel-runtime/package.js",
    "content": "Package.describe({\n  name: \"babel-runtime\",\n  summary: \"Runtime support for output of Babel transpiler\",\n  version: '0.1.9_1',\n  documentation: 'README.md'\n});\n\nNpm.depends({\n  \"regenerator-runtime\": \"0.9.5\",\n  \"meteor-babel-helpers\": \"0.0.3\"\n});\n\nPackage.onUse(function (api) {\n  // If the es5-shim package is installed, make sure it loads before\n  // babel-runtime, since babel-runtime uses some ES5 APIs like\n  // Object.defineProperties that are buggy in older browsers.\n  api.use(\"es5-shim\", { weak: true });\n  api.use(\"modules\");\n  api.use(\"promise\"); // Needed by Regenerator.\n  api.addFiles(\"babel-runtime.js\");\n  api.export(\"meteorBabelHelpers\");\n});\n"
  },
  {
    "path": "packages/base64/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/base64/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/base64/base64.js",
    "content": "// Base 64 encoding\n\nvar BASE_64_CHARS = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\nvar BASE_64_VALS = {};\n\nfor (var i = 0; i < BASE_64_CHARS.length; i++) {\n  BASE_64_VALS[BASE_64_CHARS.charAt(i)] = i;\n};\n\nBase64 = {};\n\nBase64.encode = function (array) {\n\n  if (typeof array === \"string\") {\n    var str = array;\n    array = Base64.newBinary(str.length);\n    for (var i = 0; i < str.length; i++) {\n      var ch = str.charCodeAt(i);\n      if (ch > 0xFF) {\n        throw new Error(\n          \"Not ascii. Base64.encode can only take ascii strings.\");\n      }\n      array[i] = ch;\n    }\n  }\n\n  var answer = [];\n  var a = null;\n  var b = null;\n  var c = null;\n  var d = null;\n  for (var i = 0; i < array.length; i++) {\n    switch (i % 3) {\n    case 0:\n      a = (array[i] >> 2) & 0x3F;\n      b = (array[i] & 0x03) << 4;\n      break;\n    case 1:\n      b = b | (array[i] >> 4) & 0xF;\n      c = (array[i] & 0xF) << 2;\n      break;\n    case 2:\n      c = c | (array[i] >> 6) & 0x03;\n      d = array[i] & 0x3F;\n      answer.push(getChar(a));\n      answer.push(getChar(b));\n      answer.push(getChar(c));\n      answer.push(getChar(d));\n      a = null;\n      b = null;\n      c = null;\n      d = null;\n      break;\n    }\n  }\n  if (a != null) {\n    answer.push(getChar(a));\n    answer.push(getChar(b));\n    if (c == null)\n      answer.push('=');\n    else\n      answer.push(getChar(c));\n    if (d == null)\n      answer.push('=');\n  }\n  return answer.join(\"\");\n};\n\nvar getChar = function (val) {\n  return BASE_64_CHARS.charAt(val);\n};\n\nvar getVal = function (ch) {\n  if (ch === '=') {\n    return -1;\n  }\n  return BASE_64_VALS[ch];\n};\n\n// XXX This is a weird place for this to live, but it's used both by\n// this package and 'ejson', and we can't put it in 'ejson' without\n// introducing a circular dependency. It should probably be in its own\n// package or as a helper in a package that both 'base64' and 'ejson'\n// use.\nBase64.newBinary = function (len) {\n  if (typeof Uint8Array === 'undefined' || typeof ArrayBuffer === 'undefined') {\n    var ret = [];\n    for (var i = 0; i < len; i++) {\n      ret.push(0);\n    }\n    ret.$Uint8ArrayPolyfill = true;\n    return ret;\n  }\n  return new Uint8Array(new ArrayBuffer(len));\n};\n\nBase64.decode = function (str) {\n  var len = Math.floor((str.length*3)/4);\n  if (str.charAt(str.length - 1) == '=') {\n    len--;\n    if (str.charAt(str.length - 2) == '=')\n      len--;\n  }\n  var arr = Base64.newBinary(len);\n\n  var one = null;\n  var two = null;\n  var three = null;\n\n  var j = 0;\n\n  for (var i = 0; i < str.length; i++) {\n    var c = str.charAt(i);\n    var v = getVal(c);\n    switch (i % 4) {\n    case 0:\n      if (v < 0)\n        throw new Error('invalid base64 string');\n      one = v << 2;\n      break;\n    case 1:\n      if (v < 0)\n        throw new Error('invalid base64 string');\n      one = one | (v >> 4);\n      arr[j++] = one;\n      two = (v & 0x0F) << 4;\n      break;\n    case 2:\n      if (v >= 0) {\n        two = two | (v >> 2);\n        arr[j++] = two;\n        three = (v & 0x03) << 6;\n      }\n      break;\n    case 3:\n      if (v >= 0) {\n        arr[j++] = three | v;\n      }\n      break;\n    }\n  }\n  return arr;\n};\n"
  },
  {
    "path": "packages/base64/base64_test.js",
    "content": "var asciiToArray = function (str) {\n  var arr = Base64.newBinary(str.length);\n  for (var i = 0; i < str.length; i++) {\n    var c = str.charCodeAt(i);\n    if (c > 0xFF) {\n      throw new Error(\"Not ascii\");\n    }\n    arr[i] = c;\n  }\n  return arr;\n};\n\nvar arrayToAscii = function (arr) {\n  var res = [];\n  for (var i = 0; i < arr.length; i++) {\n    res.push(String.fromCharCode(arr[i]));\n  }\n  return res.join(\"\");\n};\n\nTinytest.add(\"base64 - testing the test\", function (test) {\n  test.equal(arrayToAscii(asciiToArray(\"The quick brown fox jumps over the lazy dog\")),\n             \"The quick brown fox jumps over the lazy dog\");\n});\n\nTinytest.add(\"base64 - empty\", function (test) {\n  test.equal(Base64.encode(EJSON.newBinary(0)), \"\");\n  test.equal(Base64.decode(\"\"), EJSON.newBinary(0));\n});\n\n\nTinytest.add(\"base64 - wikipedia examples\", function (test) {\n  var tests = [\n    {txt: \"pleasure.\", res: \"cGxlYXN1cmUu\"},\n    {txt: \"leasure.\", res: \"bGVhc3VyZS4=\"},\n    {txt: \"easure.\", res: \"ZWFzdXJlLg==\"},\n    {txt: \"asure.\", res: \"YXN1cmUu\"},\n    {txt: \"sure.\", res: \"c3VyZS4=\"}\n  ];\n  _.each(tests, function(t) {\n    test.equal(Base64.encode(asciiToArray(t.txt)), t.res);\n    test.equal(arrayToAscii(Base64.decode(t.res)), t.txt);\n  });\n});\n\nTinytest.add(\"base64 - non-text examples\", function (test) {\n  var tests = [\n    {array: [0, 0, 0], b64: \"AAAA\"},\n    {array: [0, 0, 1], b64: \"AAAB\"}\n  ];\n  _.each(tests, function(t) {\n    test.equal(Base64.encode(t.array), t.b64);\n    var expectedAsBinary = EJSON.newBinary(t.array.length);\n    _.each(t.array, function (val, i) {\n      expectedAsBinary[i] = val;\n    });\n    test.equal(Base64.decode(t.b64), expectedAsBinary);\n  });\n});\n"
  },
  {
    "path": "packages/base64/package.js",
    "content": "Package.describe({\n  summary: \"Base64 encoding and decoding\",\n  version: '1.0.9'\n});\n\nPackage.onUse(function (api) {\n  api.export('Base64');\n  api.addFiles('base64.js', ['client', 'server']);\n});\n\nPackage.onTest(function (api) {\n  api.use('base64', ['client', 'server']);\n  api.use(['tinytest', 'underscore', 'ejson']);\n\n  api.addFiles('base64_test.js', ['client', 'server']);\n});\n"
  },
  {
    "path": "packages/binary-heap/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/binary-heap/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/binary-heap/binary-heap-tests.js",
    "content": "Tinytest.add(\"binary-heap - simple max-heap tests\", function (test) {\n  var h = new MaxHeap(function (a, b) { return a-b; });\n  h.set(\"a\", 1);\n  h.set(\"b\", 233);\n  h.set(\"c\", -122);\n  h.set(\"d\", 0);\n  h.set(\"e\", 0);\n\n  test.equal(h.size(), 5);\n  test.equal(h.maxElementId(), \"b\");\n  test.equal(h.get(\"b\"), 233);\n\n  h.remove(\"b\");\n  test.equal(h.size(), 4);\n  test.equal(h.maxElementId(), \"a\");\n  h.set(\"e\", 44);\n  test.equal(h.maxElementId(), \"e\");\n  test.equal(h.get(\"b\"), null);\n  test.isTrue(h.has(\"a\"));\n  test.isFalse(h.has(\"dd\"));\n\n  h.clear();\n  test.isFalse(h.has(\"a\"));\n  test.equal(h.size(), 0);\n  test.equal(h.setDefault(\"a\", 12345), 12345);\n  test.equal(h.setDefault(\"a\", 55555), 12345);\n  test.equal(h.size(), 1);\n  test.equal(h.maxElementId(), \"a\");\n});\n\nTinytest.add(\"binary-heap - big test for max-heap\", function (test) {\n  var positiveNumbers = _.shuffle(_.range(1, 41));\n  var negativeNumbers = _.shuffle(_.range(-1, -41, -1));\n  var allNumbers = negativeNumbers.concat(positiveNumbers);\n\n  var heap = new MaxHeap(function (a, b) { return a-b; });\n  var output = [];\n\n  _.each(allNumbers, function (n) { heap.set(n, n); });\n\n  _.times(positiveNumbers.length + negativeNumbers.length, function () {\n    var maxId = heap.maxElementId();\n    output.push(heap.get(maxId));\n    heap.remove(maxId);\n  });\n\n  allNumbers.sort(function (a, b) { return b-a; });\n\n  test.equal(output, allNumbers);\n});\n\nTinytest.add(\"binary-heap - min-max heap tests\", function (test) {\n  var h = new MinMaxHeap(function (a, b) { return a-b; });\n  h.set(\"a\", 1);\n  h.set(\"b\", 233);\n  h.set(\"c\", -122);\n  h.set(\"d\", 0);\n  h.set(\"e\", 0);\n\n  test.equal(h.size(), 5);\n  test.equal(h.maxElementId(), \"b\");\n  test.equal(h.get(\"b\"), 233);\n  test.equal(h.minElementId(), \"c\");\n\n  h.remove(\"b\");\n  test.equal(h.size(), 4);\n  test.equal(h.minElementId(), \"c\");\n  h.set(\"e\", -123);\n  test.equal(h.minElementId(), \"e\");\n  test.equal(h.get(\"b\"), null);\n  test.isTrue(h.has(\"a\"));\n  test.isFalse(h.has(\"dd\"));\n\n  h.clear();\n  test.isFalse(h.has(\"a\"));\n  test.equal(h.size(), 0);\n  test.equal(h.setDefault(\"a\", 12345), 12345);\n  test.equal(h.setDefault(\"a\", 55555), 12345);\n  test.equal(h.size(), 1);\n  test.equal(h.maxElementId(), \"a\");\n  test.equal(h.minElementId(), \"a\");\n});\n\nTinytest.add(\"binary-heap - big test for min-max-heap\", function (test) {\n  var N = 500;\n  var positiveNumbers = _.shuffle(_.range(1, N + 1));\n  var negativeNumbers = _.shuffle(_.range(-1, -N - 1, -1));\n  var allNumbers = positiveNumbers.concat(negativeNumbers);\n\n  var heap = new MinMaxHeap(function (a, b) { return a-b; });\n  var output = [];\n\n  var initialSets = _.clone(allNumbers);\n  _.each(allNumbers, function (n) {\n    heap.set(n, n);\n    heap._selfCheck();\n    heap._minHeap._selfCheck();\n  });\n\n  allNumbers = _.shuffle(allNumbers);\n  var secondarySets = _.clone(allNumbers);\n\n  _.each(allNumbers, function (n) {\n    heap.set(-n, n);\n    heap._selfCheck();\n    heap._minHeap._selfCheck();\n  });\n\n  _.times(positiveNumbers.length + negativeNumbers.length, function () {\n    var minId = heap.minElementId();\n    output.push(heap.get(minId));\n    heap.remove(minId);\n    heap._selfCheck(); heap._minHeap._selfCheck();\n  });\n\n  test.equal(heap.size(), 0);\n\n  allNumbers.sort(function (a, b) { return a-b; });\n\n  var initialTestText = \"initial sets: \" + initialSets.toString() +\n    \"; secondary sets: \" + secondarySets.toString();\n  test.equal(output, allNumbers, initialTestText);\n\n  _.each(initialSets, function (n) { heap.set(n, n); })\n  _.each(secondarySets, function (n) { heap.set(-n, n); });\n\n  allNumbers.sort(function (a, b) { return b-a; });\n  output = [];\n  _.times(positiveNumbers.length + negativeNumbers.length, function () {\n    var maxId = heap.maxElementId();\n    output.push(heap.get(maxId));\n    heap.remove(maxId);\n    heap._selfCheck(); heap._minHeap._selfCheck();\n  });\n\n  test.equal(output, allNumbers, initialTestText);\n});\n\n"
  },
  {
    "path": "packages/binary-heap/max-heap.js",
    "content": "// Constructor of Heap\n// - comparator - Function - given two items returns a number\n// - options:\n//   - initData - Array - Optional - the initial data in a format:\n//        Object:\n//          - id - String - unique id of the item\n//          - value - Any - the data value\n//      each value is retained\n//   - IdMap - Constructor - Optional - custom IdMap class to store id->index\n//       mappings internally. Standard IdMap is used by default.\nMaxHeap = function (comparator, options) {\n  if (! _.isFunction(comparator))\n    throw new Error('Passed comparator is invalid, should be a comparison function');\n  var self = this;\n\n  // a C-style comparator that is given two values and returns a number,\n  // negative if the first value is less than the second, positive if the second\n  // value is greater than the first and zero if they are equal.\n  self._comparator = comparator;\n\n  options = _.defaults(options || {}, { IdMap: IdMap });\n\n  // _heapIdx maps an id to an index in the Heap array the corresponding value\n  // is located on.\n  self._heapIdx = new options.IdMap;\n\n  // The Heap data-structure implemented as a 0-based contiguous array where\n  // every item on index idx is a node in a complete binary tree. Every node can\n  // have children on indexes idx*2+1 and idx*2+2, except for the leaves. Every\n  // node has a parent on index (idx-1)/2;\n  self._heap = [];\n\n  // If the initial array is passed, we can build the heap in linear time\n  // complexity (O(N)) compared to linearithmic time complexity (O(nlogn)) if\n  // we push elements one by one.\n  if (_.isArray(options.initData))\n    self._initFromData(options.initData);\n};\n\n_.extend(MaxHeap.prototype, {\n  // Builds a new heap in-place in linear time based on passed data\n  _initFromData: function (data) {\n    var self = this;\n\n    self._heap = _.map(data, function (o) {\n      return { id: o.id, value: o.value };\n    });\n\n    _.each(data, function (o, i) {\n      self._heapIdx.set(o.id, i);\n    });\n\n    if (! data.length)\n      return;\n\n    // start from the first non-leaf - the parent of the last leaf\n    for (var i = parentIdx(data.length - 1); i >= 0; i--)\n      self._downHeap(i);\n  },\n\n  _downHeap: function (idx) {\n    var self = this;\n\n    while (leftChildIdx(idx) < self.size()) {\n      var left = leftChildIdx(idx);\n      var right = rightChildIdx(idx);\n      var largest = idx;\n\n      if (left < self.size()) {\n        largest = self._maxIndex(largest, left);\n      }\n      if (right < self.size()) {\n        largest = self._maxIndex(largest, right);\n      }\n\n      if (largest === idx)\n        break;\n\n      self._swap(largest, idx);\n      idx = largest;\n    }\n  },\n\n  _upHeap: function (idx) {\n    var self = this;\n\n    while (idx > 0) {\n      var parent = parentIdx(idx);\n      if (self._maxIndex(parent, idx) === idx) {\n        self._swap(parent, idx)\n        idx = parent;\n      } else {\n        break;\n      }\n    }\n  },\n\n  _maxIndex: function (idxA, idxB) {\n    var self = this;\n    var valueA = self._get(idxA);\n    var valueB = self._get(idxB);\n    return self._comparator(valueA, valueB) >= 0 ? idxA : idxB;\n  },\n\n  // Internal: gets raw data object placed on idxth place in heap\n  _get: function (idx) {\n    var self = this;\n    return self._heap[idx].value;\n  },\n\n  _swap: function (idxA, idxB) {\n    var self = this;\n    var recA = self._heap[idxA];\n    var recB = self._heap[idxB];\n\n    self._heapIdx.set(recA.id, idxB);\n    self._heapIdx.set(recB.id, idxA);\n\n    self._heap[idxA] = recB;\n    self._heap[idxB] = recA;\n  },\n\n  get: function (id) {\n    var self = this;\n    if (! self.has(id))\n      return null;\n    return self._get(self._heapIdx.get(id));\n  },\n  set: function (id, value) {\n    var self = this;\n\n    if (self.has(id)) {\n      if (self.get(id) === value)\n        return;\n\n      var idx = self._heapIdx.get(id);\n      self._heap[idx].value = value;\n\n      // Fix the new value's position\n      // Either bubble new value up if it is greater than its parent\n      self._upHeap(idx);\n      // or bubble it down if it is smaller than one of its children\n      self._downHeap(idx);\n    } else {\n      self._heapIdx.set(id, self._heap.length);\n      self._heap.push({ id: id, value: value });\n      self._upHeap(self._heap.length - 1);\n    }\n  },\n  remove: function (id) {\n    var self = this;\n\n    if (self.has(id)) {\n      var last = self._heap.length - 1;\n      var idx = self._heapIdx.get(id);\n\n      if (idx !== last) {\n        self._swap(idx, last);\n        self._heap.pop();\n        self._heapIdx.remove(id);\n\n        // Fix the swapped value's position\n        self._upHeap(idx);\n        self._downHeap(idx);\n      } else {\n        self._heap.pop();\n        self._heapIdx.remove(id);\n      }\n    }\n  },\n  has: function (id) {\n    var self = this;\n    return self._heapIdx.has(id);\n  },\n  empty: function () {\n    var self = this;\n    return !self.size();\n  },\n  clear: function () {\n    var self = this;\n    self._heap = [];\n    self._heapIdx.clear();\n  },\n  // iterate over values in no particular order\n  forEach: function (iterator) {\n    var self = this;\n    _.each(self._heap, function (obj) {\n      return iterator(obj.value, obj.id);\n    });\n  },\n  size: function () {\n    var self = this;\n    return self._heap.length;\n  },\n  setDefault: function (id, def) {\n    var self = this;\n    if (self.has(id))\n      return self.get(id);\n    self.set(id, def);\n    return def;\n  },\n  clone: function () {\n    var self = this;\n    var clone = new MaxHeap(self._comparator, self._heap);\n    return clone;\n  },\n\n  maxElementId: function () {\n    var self = this;\n    return self.size() ? self._heap[0].id : null;\n  },\n\n  _selfCheck: function () {\n    var self = this;\n    for (var i = 1; i < self._heap.length; i++)\n      if (self._maxIndex(parentIdx(i), i) !== parentIdx(i))\n          throw new Error(\"An item with id \" + self._heap[i].id +\n                          \" has a parent younger than it: \" +\n                          self._heap[parentIdx(i)].id);\n  }\n});\n\nfunction leftChildIdx (i) { return i * 2 + 1; }\nfunction rightChildIdx (i) { return i * 2 + 2; }\nfunction parentIdx (i) { return (i - 1) >> 1; }\n\n"
  },
  {
    "path": "packages/binary-heap/min-heap.js",
    "content": "MinHeap = function (comparator, options) {\n  var self = this;\n  MaxHeap.call(self, function (a, b) {\n    return -comparator(a, b);\n  }, options);\n};\n\nMeteor._inherits(MinHeap, MaxHeap);\n\n_.extend(MinHeap.prototype, {\n  maxElementId: function () {\n    throw new Error(\"Cannot call maxElementId on MinHeap\");\n  },\n  minElementId: function () {\n    var self = this;\n    return MaxHeap.prototype.maxElementId.call(self);\n  }\n});\n\n"
  },
  {
    "path": "packages/binary-heap/min-max-heap.js",
    "content": "// This implementation of Min/Max-Heap is just a subclass of Max-Heap\n// with a Min-Heap as an encapsulated property.\n//\n// Most of the operations are just proxy methods to call the same method on both\n// heaps.\n//\n// This implementation takes 2*N memory but is fairly simple to write and\n// understand. And the constant factor of a simple Heap is usually smaller\n// compared to other two-way priority queues like Min/Max Heaps\n// (http://www.cs.otago.ac.nz/staffpriv/mike/Papers/MinMaxHeaps/MinMaxHeaps.pdf)\n// and Interval Heaps\n// (http://www.cise.ufl.edu/~sahni/dsaac/enrich/c13/double.htm)\nMinMaxHeap = function (comparator, options) {\n  var self = this;\n\n  MaxHeap.call(self, comparator, options);\n  self._minHeap = new MinHeap(comparator, options);\n};\n\nMeteor._inherits(MinMaxHeap, MaxHeap);\n\n_.extend(MinMaxHeap.prototype, {\n  set: function (id, value) {\n    var self = this;\n    MaxHeap.prototype.set.apply(self, arguments);\n    self._minHeap.set(id, value);\n  },\n  remove: function (id) {\n    var self = this;\n    MaxHeap.prototype.remove.apply(self, arguments);\n    self._minHeap.remove(id);\n  },\n  clear: function () {\n    var self = this;\n    MaxHeap.prototype.clear.apply(self, arguments);\n    self._minHeap.clear();\n  },\n  setDefault: function (id, def) {\n    var self = this;\n    MaxHeap.prototype.setDefault.apply(self, arguments);\n    return self._minHeap.setDefault(id, def);\n  },\n  clone: function () {\n    var self = this;\n    var clone = new MinMaxHeap(self._comparator, self._heap);\n    return clone;\n  },\n  minElementId: function () {\n    var self = this;\n    return self._minHeap.minElementId();\n  }\n});\n\n"
  },
  {
    "path": "packages/binary-heap/package.js",
    "content": "Package.describe({\n  summary: \"Binary Heap datastructure implementation\",\n  version: '1.0.9'\n});\n\nPackage.onUse(function (api) {\n  api.export('MaxHeap');\n  api.export('MinHeap');\n  api.export('MinMaxHeap');\n  api.use(['underscore', 'id-map']);\n  api.addFiles(['max-heap.js', 'min-heap.js', 'min-max-heap.js']);\n});\n\nPackage.onTest(function (api) {\n  api.use([\n    'tinytest',\n    'underscore',\n    'binary-heap'\n  ]);\n\n  api.addFiles('binary-heap-tests.js');\n});\n"
  },
  {
    "path": "packages/blaze/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/blaze/README.md",
    "content": "# Blaze\n\nBlaze is a powerful library for creating user interfaces by writing\nreactive HTML templates.  Compared to using a combination of\ntraditional templates and jQuery, Blaze eliminates the need for all\nthe \"update logic\" in your app that listens for data changes and\nmanipulates the DOM.  Instead, familiar template directives like\n\n`{{#if}}` and `{{#each}}` integrate with\n[Tracker's](https://meteor.com/tracker) \"transparent reactivity\" and\n[Minimongo's](https://meteor.com/mini-databases) database cursors so\nthat the DOM updates automatically.\n\nRead more on the Blaze [project page](http://www.meteor.com/blaze).\n\n## Details\n\nBlaze has two major parts:\n\n* A template compiler that compiles template files into JavaScript\n  code that runs against the Blaze runtime library.  Moreover, Blaze\n  provides a compiler toolchain (think LLVM) that can be used to\n  support arbitrary template syntaxes.  The flagship template syntax\n  is Spacebars, a variant of Handlebars, but a community alternative\n  based on Jade is already in use by many apps.\n\n* A reactive DOM engine that builds and manages the DOM at runtime,\n  invoked via templates or directly from the app, which features\n  reactively updating regions, lists, and attributes; event\n  delegation; and many callbacks and hooks to aid the app developer.\n\nBlaze is sometimes compared to frameworks like React, Angular, Ember,\nPolymer, Knockout, and others by virtue of its advanced templating\nsystem.  What sets Blaze apart is a relentless focus on the developer\nexperience, using templating, transparent reactivity, and\ninteroperability with existing libraries to create a gentle learning\ncurve while enabling you to build world-class apps.\n\n## Examples\n\nHere are two Spacebars templates from an example app called\n\"Leaderboard\" which displays a sorted list of top players and their\nscores:\n\n```html\n<template name=\"leaderboard\">\n  <ol class=\"leaderboard\">\n    {{#each players}}\n      {{> player}}\n    {{/each}}\n  </ol>\n</template>\n\n<template name=\"player\">\n  <li class=\"player {{selected}}\">\n    <span class=\"name\">{{name}}</span>\n    <span class=\"score\">{{score}}</span>\n  </li>\n</template>\n```\n\nThe template tags `{{name}}` and `{{score}}` refer to properties of\nthe data context (the current player), while `players` and `selected`\nrefer to helper functions.  Helper functions and event handlers are defined\nin JavaScript:\n\n```javascript\nTemplate.leaderboard.helpers({\n  players: function () {\n    // Perform a reactive database query against minimongo\n    return Players.find({}, { sort: { score: -1, name: 1 } });\n  }\n});\n\nTemplate.player.events({\n  'click': function () {\n    // click on a player to select it\n    Session.set(\"selectedPlayer\", this._id);\n  }\n});\n\nTemplate.player.helpers({\n  selected: function () {\n    return Session.equals(\"selectedPlayer\", this._id) ? \"selected\" : '';\n  }\n});\n```\n\nNo additional UI code is necessary to ensure that the list of players\nstays up-to-date, or that the \"selected\" class is added and removed\nfrom the LI elements as appropriate when the user clicks on a player.\n\nThanks to a powerful template language, it doesn't take much ceremony\nto write a loop, include another template, or bind an attribute (or\npart of an attribute).  And thanks to Tracker's transparent\nreactivity, there's no ceremony around depending on reactive data\nsources like the database or Session; it just happens when you read\nthe value, and when the value changes, the DOM will be updated in a\nfine-grained way.\n\n# Principles\n\n## Gentle Learning Curve\n\nTo get started with Blaze, you don't have to learn a lot of concepts\nor terminology.  As web developers, we are already students of HTML,\nCSS, and JavaScript, which are complex technologies described in thick\nbooks.  Blaze lets you apply your existing knowledge in exciting new\nways without having to read another book first.\n\nMany factors go into making Blaze easy to pick up and use, including\nthe other principles below.  In general, we prefer APIs that lead to\nsimple and obvious-looking application code, and we recognize that\ndevelopers have limited time and energy to learn new and unfamiliar\nterms and syntaxes.\n\nIt may sound obvious to \"keep it simple\" and prioritize the developer\nexperience when creating a system for reactive HTML, but it's also\nchallenging, and we think it's not done often enough!  We use feedback\nfrom the Meteor community to ensure that Blaze's features stay simple,\nunderstandable, and useful.\n\n## Transparent Reactivity\n\nUnder the hood, Blaze uses the [Tracker](https://meteor.com/tracker)\nlibrary to automatically keep track of when to recalculate each\ntemplate helper.  If a helper reads a value from the client-side\ndatabase, for example, the helper will automatically be recalculated\nwhen the value changes.\n\nWhat this means for the developer is simple.  You don't have to\nexplicitly declare when to update the DOM, or even perform any\nexplicit \"data-binding.\"  You don't have to know how Tracker works, or\neven exactly what \"reactivity\" means, to benefit.  The result is less\nthinking and less typing than other approaches.\n\n## Clean Templates\n\nBlaze embraces popular template syntaxes such as Handlebars and Jade\nwhich are clean, readable, and familiar to developers coming from\nother frameworks.\n\nA good template language should clearly distinguish the special\n\"template directives\" (often enclosed in curly braces) from the HTML,\nand it should not obscure the structure of the resulting HTML.  These\nproperties make templating an easy concept to learn after static HTML\n(or alongside it), and make templates easy to read, easy to style with\nCSS, and easy to relate to the DOM.\n\nIn contrast, some newer frameworks try to remake templates as just\nHTML (Angular, Polymer) or replace them with just JavaScript (React).\nThese approaches tend to obscure either the structure of the template,\nor what is a real DOM element and what is not, or both.  In addition,\nsince templates are generally precompiled anyway as a best practice,\nit's really not important that raw template source code be\nbrowser-parsable.  Meanwhile, the developer experience of reading,\nwriting, and maintaining templates is hugely important.\n\n## Plugin Interoperability\n\nWeb developers often share snippets of HTML, JavaScript, and CSS, or\npublish them as libraries, widgets, or jQuery plugins.  They want to\nembed videos, maps, and other third-party content.\n\nBlaze doesn't assume it owns the whole DOM, and it tries to make as\nfew assumptions as possible about the DOM outside of its updates.\nIt hooks into jQuery's clean-up routines to prevent memory leaks,\nand it preserves classes, attributes, and styles added to elements\nby jQuery or any third-party library.\n\nWhile it's certainly possible for Blaze and jQuery to step on each\nother's toes if you aren't careful, there are established patterns for\nkeeping the peace, and Meteor users rightfully expect to be able to\nuse the various widgets and enhancements cooked up by the broader web\ncommunity in their apps.\n\n# Comparisons to other libraries\n\nCompared to Backbone and other libraries that simply re-render\ntemplates, Blaze does much less re-rendering and doesn't suffer from\nthe dreaded \"nested view\" problem, which is when two templates can't\nbe updated independently of each other because one is nested inside\nthe other.  In addition, Blaze automatically determines when\nre-rendering must occur, using Tracker.\n\nCompared to Ember, Blaze offers finer-grained, automatic DOM updates.\nBecause Blaze uses Tracker's transparent reactivity, you don't have to\nperform explicit \"data-binding\" to get data into your template, or\ndeclare the data dependencies of each template helper.\n\nCompared to Angular and Polymer, Blaze has a gentler learning curve,\nsimpler concepts, and nicer template syntax that cleanly separates\ntemplate directives and HTML.  Also, Blaze is targeted at today's\nbrowsers and not designed around a hypothetical \"browser of the\nfuture.\"\n\nCompared to React, Blaze emphasizes HTML templates rather than\nJavaScript component classes.  Templates are more approachable than\nJavaScript code and easier to read, write, and style with CSS.\nInstead of using Tracker, React relies on a combination of explicit\n\"setState\" calls and data-model diffing in order to achieve efficient\nrendering.\n\n# Future Work\n\n### Components\n\nBlaze will get better patterns for creating reusable UI components.\nTemplates already serve as reusable components, to a point.\nImprovements will focus on:\n\n* Argument-handling\n* Local reactive state\n* \"Methods\" that are callable from other components and have side\n  effects, versus the current \"helpers\" which are called from the\n  template language and are \"pure\"\n* Scoping and the lookup chain\n* Inheritance and configuration\n\n### Forms\n\nMost applications have a lot of forms, where input fields and other\nwidgets are used to enter data, which must then be validated and\nturned into database changes.  Server-side frameworks like Rails and\nDjango have well-honed patterns for this, but client-side frameworks\nare typically more lacking, perhaps because they are more estranged\nfrom the database.\n\nMeteor developers have already found ways and built packages to deal\nwith forms and validation, but we think there's a great opportunity to\nmake this part of the core, out-of-the-box Meteor experience.\n\n### Mobile and Animation\n\nBlaze will cater to the needs of the mobile web, including enhanced\nperformance and patterns for touch and other mobile interaction.\n\nWe'll also improve the ease with which developers can integrate\nanimated transitions into their apps.\n\n### JavaScript Expressions in Templates\n\nWe plan to support JavaScript expressions in templates.  This will\nmake templates more expressive, and it will further shorten\napplication code by eliminating the need for a certain class of\none-line helpers.\n\nThe usual argument against allowing JavaScript expressions in a\ntemplate language is one of \"separation of concerns\" -- separating\nbusiness logic from presentation, so that the business logic may be\nbetter organized, maintained, and tested independently.  Meanwhile,\neven \"logicless\" template languages often include some concessions in\nthe form of microsyntax for filtering, querying, and transforming data\nbefore using it.  This special syntax (and its extension mechanisms)\nmust then be learned.\n\nWhile keeping business logic out of templates is indeed good policy,\nthere is a large class of \"presentation logic\" that is not really\nseparable from the concerns of templates and HTML, such as the code to\ncalculate styles and classes to apply to HTML elements or to massage\ndata records into a better form for templating purposes.  In many\ncases where this code is short, it may be more convenient or more\nreadable to embed the code in the template, and it's certainly better\nthan evolving the template syntax in a direction that diverges from\nJavaScript.\n\nBecause templates are already precompiled to JavaScript code, there is\nnothing fundamentally difficult or inelegant about allowing a large\nsubset of JavaScript to be used within templates (see e.g. the project\nRactive.js).\n\n### Other Template Enhancements\n\nSource maps for debugging templates.  Imagine seeing your template\ncode in the browser's debugger!  Pretty slick.\n\nTrue lexical scoping.\n\nBetter support for pluggable template syntax (e.g. Jade-like\ntemplates).  There is already a Jade package in use, but we should\nlearn from it and clarify the abstraction boundary that authors of\ntemplate syntaxes are programming against.\n\n### Pluggable Backends (don't require jQuery)\n\nWhile Blaze currently requires jQuery, it is architected to run\nagainst other \"DOM backends\" using a common adaptor interface.  You\nshould be able to use Zepto, or some very small shim if browser\ncompatibility is not a big deal for your application for some reason.\nAt the moment, no such adaptors besides the jQuery one have been\nwritten.\n\nThe Blaze team experimented with dropping jQuery and talking directly\nto \"modern browsers,\" but it turns out there is about 5-10K of code at\nthe heart of jQuery that you can't throw out even if you don't care\nabout old browsers or supporting jQuery's app-facing API, which is\nrequired just to bring browsers up to the modest expectations of web\ndevelopers.\n\n### Better Stand-alone Support\n\nBlaze will get better support for using it outside of Meteor, such as\nregular stand-alone builds.\n\n# Resources\n\n* [Templates API](http://docs.meteor.com/#templates_api)\n* [Blaze API](http://docs.meteor.com/#blaze)\n* [Spacebars syntax](https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md)\n\n# Packages\n\n* blaze\n* blaze-tools\n* html-tools\n* htmljs\n* spacebars\n* spacebars-compiler\n"
  },
  {
    "path": "packages/blaze/attrs.js",
    "content": "var jsUrlsAllowed = false;\nBlaze._allowJavascriptUrls = function () {\n  jsUrlsAllowed = true;\n};\nBlaze._javascriptUrlsAllowed = function () {\n  return jsUrlsAllowed;\n};\n\n// An AttributeHandler object is responsible for updating a particular attribute\n// of a particular element.  AttributeHandler subclasses implement\n// browser-specific logic for dealing with particular attributes across\n// different browsers.\n//\n// To define a new type of AttributeHandler, use\n// `var FooHandler = AttributeHandler.extend({ update: function ... })`\n// where the `update` function takes arguments `(element, oldValue, value)`.\n// The `element` argument is always the same between calls to `update` on\n// the same instance.  `oldValue` and `value` are each either `null` or\n// a Unicode string of the type that might be passed to the value argument\n// of `setAttribute` (i.e. not an HTML string with character references).\n// When an AttributeHandler is installed, an initial call to `update` is\n// always made with `oldValue = null`.  The `update` method can access\n// `this.name` if the AttributeHandler class is a generic one that applies\n// to multiple attribute names.\n//\n// AttributeHandlers can store custom properties on `this`, as long as they\n// don't use the names `element`, `name`, `value`, and `oldValue`.\n//\n// AttributeHandlers can't influence how attributes appear in rendered HTML,\n// only how they are updated after materialization as DOM.\n\nAttributeHandler = function (name, value) {\n  this.name = name;\n  this.value = value;\n};\nBlaze._AttributeHandler = AttributeHandler;\n\nAttributeHandler.prototype.update = function (element, oldValue, value) {\n  if (value === null) {\n    if (oldValue !== null)\n      element.removeAttribute(this.name);\n  } else {\n    element.setAttribute(this.name, value);\n  }\n};\n\nAttributeHandler.extend = function (options) {\n  var curType = this;\n  var subType = function AttributeHandlerSubtype(/*arguments*/) {\n    AttributeHandler.apply(this, arguments);\n  };\n  subType.prototype = new curType;\n  subType.extend = curType.extend;\n  if (options)\n    _.extend(subType.prototype, options);\n  return subType;\n};\n\n/// Apply the diff between the attributes of \"oldValue\" and \"value\" to \"element.\"\n//\n// Each subclass must implement a parseValue method which takes a string\n// as an input and returns a dict of attributes. The keys of the dict\n// are unique identifiers (ie. css properties in the case of styles), and the\n// values are the entire attribute which will be injected into the element.\n//\n// Extended below to support classes, SVG elements and styles.\n\nvar DiffingAttributeHandler = AttributeHandler.extend({\n  update: function (element, oldValue, value) {\n    if (!this.getCurrentValue || !this.setValue || !this.parseValue)\n      throw new Error(\"Missing methods in subclass of 'DiffingAttributeHandler'\");\n\n    var oldAttrsMap = oldValue ? this.parseValue(oldValue) : {};\n    var newAttrsMap = value ? this.parseValue(value) : {};\n\n    // the current attributes on the element, which we will mutate.\n\n    var attrString = this.getCurrentValue(element);\n    var attrsMap = attrString ? this.parseValue(attrString) : {};\n\n    _.each(_.keys(oldAttrsMap), function (t) {\n      if (! (t in newAttrsMap))\n        delete attrsMap[t];\n    });\n\n    _.each(_.keys(newAttrsMap), function (t) {\n      attrsMap[t] = newAttrsMap[t];\n    });\n\n    this.setValue(element, _.values(attrsMap).join(' '));\n  }\n});\n\nvar ClassHandler = DiffingAttributeHandler.extend({\n  // @param rawValue {String}\n  getCurrentValue: function (element) {\n    return element.className;\n  },\n  setValue: function (element, className) {\n    element.className = className;\n  },\n  parseValue: function (attrString) {\n    var tokens = {};\n\n    _.each(attrString.split(' '), function(token) {\n      if (token)\n        tokens[token] = token;\n    });\n    return tokens;\n  }\n});\n\nvar SVGClassHandler = ClassHandler.extend({\n  getCurrentValue: function (element) {\n    return element.className.baseVal;\n  },\n  setValue: function (element, className) {\n    element.setAttribute('class', className);\n  }\n});\n\nvar StyleHandler = DiffingAttributeHandler.extend({\n  getCurrentValue: function (element) {\n    return element.getAttribute('style');\n  },\n  setValue: function (element, style) {\n    if (style === '') {\n      element.removeAttribute('style');\n    } else {\n      element.setAttribute('style', style);\n    }\n  },\n\n  // Parse a string to produce a map from property to attribute string.\n  //\n  // Example:\n  // \"color:red; foo:12px\" produces a token {color: \"color:red\", foo:\"foo:12px\"}\n  parseValue: function (attrString) {\n    var tokens = {};\n\n    // Regex for parsing a css attribute declaration, taken from css-parse:\n    // https://github.com/reworkcss/css-parse/blob/7cef3658d0bba872cde05a85339034b187cb3397/index.js#L219\n    var regex = /(\\*?[-#\\/\\*\\\\\\w]+(?:\\[[0-9a-z_-]+\\])?)\\s*:\\s*(?:\\'(?:\\\\\\'|.)*?\\'|\"(?:\\\\\"|.)*?\"|\\([^\\)]*?\\)|[^};])+[;\\s]*/g;\n    var match = regex.exec(attrString);\n    while (match) {\n      // match[0] = entire matching string\n      // match[1] = css property\n      // Prefix the token to prevent conflicts with existing properties.\n\n      // XXX No `String.trim` on Safari 4. Swap out $.trim if we want to\n      // remove strong dep on jquery.\n      tokens[' ' + match[1]] = match[0].trim ?\n        match[0].trim() : $.trim(match[0]);\n\n      match = regex.exec(attrString);\n    }\n\n    return tokens;\n  }\n});\n\nvar BooleanHandler = AttributeHandler.extend({\n  update: function (element, oldValue, value) {\n    var name = this.name;\n    if (value == null) {\n      if (oldValue != null)\n        element[name] = false;\n    } else {\n      element[name] = true;\n    }\n  }\n});\n\nvar DOMPropertyHandler = AttributeHandler.extend({\n  update: function (element, oldValue, value) {\n    var name = this.name;\n    if (value !== element[name])\n      element[name] = value;\n  }\n});\n\n// attributes of the type 'xlink:something' should be set using\n// the correct namespace in order to work\nvar XlinkHandler = AttributeHandler.extend({\n  update: function(element, oldValue, value) {\n    var NS = 'http://www.w3.org/1999/xlink';\n    if (value === null) {\n      if (oldValue !== null)\n        element.removeAttributeNS(NS, this.name);\n    } else {\n      element.setAttributeNS(NS, this.name, this.value);\n    }\n  }\n});\n\n// cross-browser version of `instanceof SVGElement`\nvar isSVGElement = function (elem) {\n  return 'ownerSVGElement' in elem;\n};\n\nvar isUrlAttribute = function (tagName, attrName) {\n  // Compiled from http://www.w3.org/TR/REC-html40/index/attributes.html\n  // and\n  // http://www.w3.org/html/wg/drafts/html/master/index.html#attributes-1\n  var urlAttrs = {\n    FORM: ['action'],\n    BODY: ['background'],\n    BLOCKQUOTE: ['cite'],\n    Q: ['cite'],\n    DEL: ['cite'],\n    INS: ['cite'],\n    OBJECT: ['classid', 'codebase', 'data', 'usemap'],\n    APPLET: ['codebase'],\n    A: ['href'],\n    AREA: ['href'],\n    LINK: ['href'],\n    BASE: ['href'],\n    IMG: ['longdesc', 'src', 'usemap'],\n    FRAME: ['longdesc', 'src'],\n    IFRAME: ['longdesc', 'src'],\n    HEAD: ['profile'],\n    SCRIPT: ['src'],\n    INPUT: ['src', 'usemap', 'formaction'],\n    BUTTON: ['formaction'],\n    BASE: ['href'],\n    MENUITEM: ['icon'],\n    HTML: ['manifest'],\n    VIDEO: ['poster']\n  };\n\n  if (attrName === 'itemid') {\n    return true;\n  }\n\n  var urlAttrNames = urlAttrs[tagName] || [];\n  return _.contains(urlAttrNames, attrName);\n};\n\n// To get the protocol for a URL, we let the browser normalize it for\n// us, by setting it as the href for an anchor tag and then reading out\n// the 'protocol' property.\nif (Meteor.isClient) {\n  var anchorForNormalization = document.createElement('A');\n}\n\nvar getUrlProtocol = function (url) {\n  if (Meteor.isClient) {\n    anchorForNormalization.href = url;\n    return (anchorForNormalization.protocol || \"\").toLowerCase();\n  } else {\n    throw new Error('getUrlProtocol not implemented on the server');\n  }\n};\n\n// UrlHandler is an attribute handler for all HTML attributes that take\n// URL values. It disallows javascript: URLs, unless\n// Blaze._allowJavascriptUrls() has been called. To detect javascript:\n// urls, we set the attribute on a dummy anchor element and then read\n// out the 'protocol' property of the attribute.\nvar origUpdate = AttributeHandler.prototype.update;\nvar UrlHandler = AttributeHandler.extend({\n  update: function (element, oldValue, value) {\n    var self = this;\n    var args = arguments;\n\n    if (Blaze._javascriptUrlsAllowed()) {\n      origUpdate.apply(self, args);\n    } else {\n      var isJavascriptProtocol = (getUrlProtocol(value) === \"javascript:\");\n      var isVBScriptProtocol   = (getUrlProtocol(value) === \"vbscript:\");\n      if (isJavascriptProtocol || isVBScriptProtocol) {\n        Blaze._warn(\"URLs that use the 'javascript:' or 'vbscript:' protocol are not \" +\n                    \"allowed in URL attribute values. \" +\n                    \"Call Blaze._allowJavascriptUrls() \" +\n                    \"to enable them.\");\n        origUpdate.apply(self, [element, oldValue, null]);\n      } else {\n        origUpdate.apply(self, args);\n      }\n    }\n  }\n});\n\n// XXX make it possible for users to register attribute handlers!\nmakeAttributeHandler = function (elem, name, value) {\n  // generally, use setAttribute but certain attributes need to be set\n  // by directly setting a JavaScript property on the DOM element.\n  if (name === 'class') {\n    if (isSVGElement(elem)) {\n      return new SVGClassHandler(name, value);\n    } else {\n      return new ClassHandler(name, value);\n    }\n  } else if (name === 'style') {\n    return new StyleHandler(name, value);\n  } else if ((elem.tagName === 'OPTION' && name === 'selected') ||\n             (elem.tagName === 'INPUT' && name === 'checked')) {\n    return new BooleanHandler(name, value);\n  } else if ((elem.tagName === 'TEXTAREA' || elem.tagName === 'INPUT')\n             && name === 'value') {\n    // internally, TEXTAREAs tracks their value in the 'value'\n    // attribute just like INPUTs.\n    return new DOMPropertyHandler(name, value);\n  } else if (name.substring(0,6) === 'xlink:') {\n    return new XlinkHandler(name.substring(6), value);\n  } else if (isUrlAttribute(elem.tagName, name)) {\n    return new UrlHandler(name, value);\n  } else {\n    return new AttributeHandler(name, value);\n  }\n\n  // XXX will need one for 'style' on IE, though modern browsers\n  // seem to handle setAttribute ok.\n};\n\n\nElementAttributesUpdater = function (elem) {\n  this.elem = elem;\n  this.handlers = {};\n};\n\n// Update attributes on `elem` to the dictionary `attrs`, whose\n// values are strings.\nElementAttributesUpdater.prototype.update = function(newAttrs) {\n  var elem = this.elem;\n  var handlers = this.handlers;\n\n  for (var k in handlers) {\n    if (! _.has(newAttrs, k)) {\n      // remove attributes (and handlers) for attribute names\n      // that don't exist as keys of `newAttrs` and so won't\n      // be visited when traversing it.  (Attributes that\n      // exist in the `newAttrs` object but are `null`\n      // are handled later.)\n      var handler = handlers[k];\n      var oldValue = handler.value;\n      handler.value = null;\n      handler.update(elem, oldValue, null);\n      delete handlers[k];\n    }\n  }\n\n  for (var k in newAttrs) {\n    var handler = null;\n    var oldValue;\n    var value = newAttrs[k];\n    if (! _.has(handlers, k)) {\n      if (value !== null) {\n        // make new handler\n        handler = makeAttributeHandler(elem, k, value);\n        handlers[k] = handler;\n        oldValue = null;\n      }\n    } else {\n      handler = handlers[k];\n      oldValue = handler.value;\n    }\n    if (oldValue !== value) {\n      handler.value = value;\n      handler.update(elem, oldValue, value);\n      if (value === null)\n        delete handlers[k];\n    }\n  }\n};\n"
  },
  {
    "path": "packages/blaze/backcompat.js",
    "content": "UI = Blaze;\n\nBlaze.ReactiveVar = ReactiveVar;\nUI._templateInstance = Blaze.Template.instance;\n\nHandlebars = {};\nHandlebars.registerHelper = Blaze.registerHelper;\n\nHandlebars._escape = Blaze._escape;\n\n// Return these from {{...}} helpers to achieve the same as returning\n// strings from {{{...}}} helpers\nHandlebars.SafeString = function(string) {\n  this.string = string;\n};\nHandlebars.SafeString.prototype.toString = function() {\n  return this.string.toString();\n};\n"
  },
  {
    "path": "packages/blaze/builtins.js",
    "content": "Blaze._calculateCondition = function (cond) {\n  if (cond instanceof Array && cond.length === 0)\n    cond = false;\n  return !! cond;\n};\n\n/**\n * @summary Constructs a View that renders content with a data context.\n * @locus Client\n * @param {Object|Function} data An object to use as the data context, or a function returning such an object.  If a function is provided, it will be reactively re-run.\n * @param {Function} contentFunc A Function that returns [*renderable content*](#renderable_content).\n */\nBlaze.With = function (data, contentFunc) {\n  var view = Blaze.View('with', contentFunc);\n\n  view.dataVar = new ReactiveVar;\n\n  view.onViewCreated(function () {\n    if (typeof data === 'function') {\n      // `data` is a reactive function\n      view.autorun(function () {\n        view.dataVar.set(data());\n      }, view.parentView, 'setData');\n    } else {\n      view.dataVar.set(data);\n    }\n  });\n\n  return view;\n};\n\n/**\n * Attaches bindings to the instantiated view.\n * @param {Object} bindings A dictionary of bindings, each binding name\n * corresponds to a value or a function that will be reactively re-run.\n * @param {View} view The target.\n */\nBlaze._attachBindingsToView = function (bindings, view) {\n  view.onViewCreated(function () {\n    _.each(bindings, function (binding, name) {\n      view._scopeBindings[name] = new ReactiveVar;\n      if (typeof binding === 'function') {\n        view.autorun(function () {\n          view._scopeBindings[name].set(binding());\n        }, view.parentView);\n      } else {\n        view._scopeBindings[name].set(binding);\n      }\n    });\n  });\n};\n\n/**\n * @summary Constructs a View setting the local lexical scope in the block.\n * @param {Function} bindings Dictionary mapping names of bindings to\n * values or computations to reactively re-run.\n * @param {Function} contentFunc A Function that returns [*renderable content*](#renderable_content).\n */\nBlaze.Let = function (bindings, contentFunc) {\n  var view = Blaze.View('let', contentFunc);\n  Blaze._attachBindingsToView(bindings, view);\n\n  return view;\n};\n\n/**\n * @summary Constructs a View that renders content conditionally.\n * @locus Client\n * @param {Function} conditionFunc A function to reactively re-run.  Whether the result is truthy or falsy determines whether `contentFunc` or `elseFunc` is shown.  An empty array is considered falsy.\n * @param {Function} contentFunc A Function that returns [*renderable content*](#renderable_content).\n * @param {Function} [elseFunc] Optional.  A Function that returns [*renderable content*](#renderable_content).  If no `elseFunc` is supplied, no content is shown in the \"else\" case.\n */\nBlaze.If = function (conditionFunc, contentFunc, elseFunc, _not) {\n  var conditionVar = new ReactiveVar;\n\n  var view = Blaze.View(_not ? 'unless' : 'if', function () {\n    return conditionVar.get() ? contentFunc() :\n      (elseFunc ? elseFunc() : null);\n  });\n  view.__conditionVar = conditionVar;\n  view.onViewCreated(function () {\n    this.autorun(function () {\n      var cond = Blaze._calculateCondition(conditionFunc());\n      conditionVar.set(_not ? (! cond) : cond);\n    }, this.parentView, 'condition');\n  });\n\n  return view;\n};\n\n/**\n * @summary An inverted [`Blaze.If`](#blaze_if).\n * @locus Client\n * @param {Function} conditionFunc A function to reactively re-run.  If the result is falsy, `contentFunc` is shown, otherwise `elseFunc` is shown.  An empty array is considered falsy.\n * @param {Function} contentFunc A Function that returns [*renderable content*](#renderable_content).\n * @param {Function} [elseFunc] Optional.  A Function that returns [*renderable content*](#renderable_content).  If no `elseFunc` is supplied, no content is shown in the \"else\" case.\n */\nBlaze.Unless = function (conditionFunc, contentFunc, elseFunc) {\n  return Blaze.If(conditionFunc, contentFunc, elseFunc, true /*_not*/);\n};\n\n/**\n * @summary Constructs a View that renders `contentFunc` for each item in a sequence.\n * @locus Client\n * @param {Function} argFunc A function to reactively re-run. The function can\n * return one of two options:\n *\n * 1. An object with two fields: '_variable' and '_sequence'. Each iterates over\n *   '_sequence', it may be a Cursor, an array, null, or undefined. Inside the\n *   Each body you will be able to get the current item from the sequence using\n *   the name specified in the '_variable' field.\n *\n * 2. Just a sequence (Cursor, array, null, or undefined) not wrapped into an\n *   object. Inside the Each body, the current item will be set as the data\n *   context.\n * @param {Function} contentFunc A Function that returns  [*renderable\n * content*](#renderable_content).\n * @param {Function} [elseFunc] A Function that returns [*renderable\n * content*](#renderable_content) to display in the case when there are no items\n * in the sequence.\n */\nBlaze.Each = function (argFunc, contentFunc, elseFunc) {\n  var eachView = Blaze.View('each', function () {\n    var subviews = this.initialSubviews;\n    this.initialSubviews = null;\n    if (this._isCreatedForExpansion) {\n      this.expandedValueDep = new Tracker.Dependency;\n      this.expandedValueDep.depend();\n    }\n    return subviews;\n  });\n  eachView.initialSubviews = [];\n  eachView.numItems = 0;\n  eachView.inElseMode = false;\n  eachView.stopHandle = null;\n  eachView.contentFunc = contentFunc;\n  eachView.elseFunc = elseFunc;\n  eachView.argVar = new ReactiveVar;\n  eachView.variableName = null;\n\n  // update the @index value in the scope of all subviews in the range\n  var updateIndices = function (from, to) {\n    if (to === undefined) {\n      to = eachView.numItems - 1;\n    }\n\n    for (var i = from; i <= to; i++) {\n      var view = eachView._domrange.members[i].view;\n      view._scopeBindings['@index'].set(i);\n    }\n  };\n\n  eachView.onViewCreated(function () {\n    // We evaluate argFunc in an autorun to make sure\n    // Blaze.currentView is always set when it runs (rather than\n    // passing argFunc straight to ObserveSequence).\n    eachView.autorun(function () {\n      // argFunc can return either a sequence as is or a wrapper object with a\n      // _sequence and _variable fields set.\n      var arg = argFunc();\n      if (_.isObject(arg) && _.has(arg, '_sequence')) {\n        eachView.variableName = arg._variable || null;\n        arg = arg._sequence;\n      }\n\n      eachView.argVar.set(arg);\n    }, eachView.parentView, 'collection');\n\n    eachView.stopHandle = ObserveSequence.observe(function () {\n      return eachView.argVar.get();\n    }, {\n      addedAt: function (id, item, index) {\n        Tracker.nonreactive(function () {\n          var newItemView;\n          if (eachView.variableName) {\n            // new-style #each (as in {{#each item in items}})\n            // doesn't create a new data context\n            newItemView = Blaze.View('item', eachView.contentFunc);\n          } else {\n            newItemView = Blaze.With(item, eachView.contentFunc);\n          }\n\n          eachView.numItems++;\n\n          var bindings = {};\n          bindings['@index'] = index;\n          if (eachView.variableName) {\n            bindings[eachView.variableName] = item;\n          }\n          Blaze._attachBindingsToView(bindings, newItemView);\n\n          if (eachView.expandedValueDep) {\n            eachView.expandedValueDep.changed();\n          } else if (eachView._domrange) {\n            if (eachView.inElseMode) {\n              eachView._domrange.removeMember(0);\n              eachView.inElseMode = false;\n            }\n\n            var range = Blaze._materializeView(newItemView, eachView);\n            eachView._domrange.addMember(range, index);\n            updateIndices(index);\n          } else {\n            eachView.initialSubviews.splice(index, 0, newItemView);\n          }\n        });\n      },\n      removedAt: function (id, item, index) {\n        Tracker.nonreactive(function () {\n          eachView.numItems--;\n          if (eachView.expandedValueDep) {\n            eachView.expandedValueDep.changed();\n          } else if (eachView._domrange) {\n            eachView._domrange.removeMember(index);\n            updateIndices(index);\n            if (eachView.elseFunc && eachView.numItems === 0) {\n              eachView.inElseMode = true;\n              eachView._domrange.addMember(\n                Blaze._materializeView(\n                  Blaze.View('each_else',eachView.elseFunc),\n                  eachView), 0);\n            }\n          } else {\n            eachView.initialSubviews.splice(index, 1);\n          }\n        });\n      },\n      changedAt: function (id, newItem, oldItem, index) {\n        Tracker.nonreactive(function () {\n          if (eachView.expandedValueDep) {\n            eachView.expandedValueDep.changed();\n          } else {\n            var itemView;\n            if (eachView._domrange) {\n              itemView = eachView._domrange.getMember(index).view;\n            } else {\n              itemView = eachView.initialSubviews[index];\n            }\n            if (eachView.variableName) {\n              itemView._scopeBindings[eachView.variableName].set(newItem);\n            } else {\n              itemView.dataVar.set(newItem);\n            }\n          }\n        });\n      },\n      movedTo: function (id, item, fromIndex, toIndex) {\n        Tracker.nonreactive(function () {\n          if (eachView.expandedValueDep) {\n            eachView.expandedValueDep.changed();\n          } else if (eachView._domrange) {\n            eachView._domrange.moveMember(fromIndex, toIndex);\n            updateIndices(\n              Math.min(fromIndex, toIndex), Math.max(fromIndex, toIndex));\n          } else {\n            var subviews = eachView.initialSubviews;\n            var itemView = subviews[fromIndex];\n            subviews.splice(fromIndex, 1);\n            subviews.splice(toIndex, 0, itemView);\n          }\n        });\n      }\n    });\n\n    if (eachView.elseFunc && eachView.numItems === 0) {\n      eachView.inElseMode = true;\n      eachView.initialSubviews[0] =\n        Blaze.View('each_else', eachView.elseFunc);\n    }\n  });\n\n  eachView.onViewDestroyed(function () {\n    if (eachView.stopHandle)\n      eachView.stopHandle.stop();\n  });\n\n  return eachView;\n};\n\nBlaze._TemplateWith = function (arg, contentFunc) {\n  var w;\n\n  var argFunc = arg;\n  if (typeof arg !== 'function') {\n    argFunc = function () {\n      return arg;\n    };\n  }\n\n  // This is a little messy.  When we compile `{{> Template.contentBlock}}`, we\n  // wrap it in Blaze._InOuterTemplateScope in order to skip the intermediate\n  // parent Views in the current template.  However, when there's an argument\n  // (`{{> Template.contentBlock arg}}`), the argument needs to be evaluated\n  // in the original scope.  There's no good order to nest\n  // Blaze._InOuterTemplateScope and Spacebars.TemplateWith to achieve this,\n  // so we wrap argFunc to run it in the \"original parentView\" of the\n  // Blaze._InOuterTemplateScope.\n  //\n  // To make this better, reconsider _InOuterTemplateScope as a primitive.\n  // Longer term, evaluate expressions in the proper lexical scope.\n  var wrappedArgFunc = function () {\n    var viewToEvaluateArg = null;\n    if (w.parentView && w.parentView.name === 'InOuterTemplateScope') {\n      viewToEvaluateArg = w.parentView.originalParentView;\n    }\n    if (viewToEvaluateArg) {\n      return Blaze._withCurrentView(viewToEvaluateArg, argFunc);\n    } else {\n      return argFunc();\n    }\n  };\n\n  var wrappedContentFunc = function () {\n    var content = contentFunc.call(this);\n\n    // Since we are generating the Blaze._TemplateWith view for the\n    // user, set the flag on the child view.  If `content` is a template,\n    // construct the View so that we can set the flag.\n    if (content instanceof Blaze.Template) {\n      content = content.constructView();\n    }\n    if (content instanceof Blaze.View) {\n      content._hasGeneratedParent = true;\n    }\n\n    return content;\n  };\n\n  w = Blaze.With(wrappedArgFunc, wrappedContentFunc);\n  w.__isTemplateWith = true;\n  return w;\n};\n\nBlaze._InOuterTemplateScope = function (templateView, contentFunc) {\n  var view = Blaze.View('InOuterTemplateScope', contentFunc);\n  var parentView = templateView.parentView;\n\n  // Hack so that if you call `{{> foo bar}}` and it expands into\n  // `{{#with bar}}{{> foo}}{{/with}}`, and then `foo` is a template\n  // that inserts `{{> Template.contentBlock}}`, the data context for\n  // `Template.contentBlock` is not `bar` but the one enclosing that.\n  if (parentView.__isTemplateWith)\n    parentView = parentView.parentView;\n\n  view.onViewCreated(function () {\n    this.originalParentView = this.parentView;\n    this.parentView = parentView;\n    this.__childDoesntStartNewLexicalScope = true;\n  });\n  return view;\n};\n\n// XXX COMPAT WITH 0.9.0\nBlaze.InOuterTemplateScope = Blaze._InOuterTemplateScope;\n"
  },
  {
    "path": "packages/blaze/dombackend.js",
    "content": "var DOMBackend = {};\nBlaze._DOMBackend = DOMBackend;\n\nvar $jq = (typeof jQuery !== 'undefined' ? jQuery :\n           (typeof Package !== 'undefined' ?\n            Package.jquery && Package.jquery.jQuery : null));\nif (! $jq)\n  throw new Error(\"jQuery not found\");\n\nDOMBackend._$jq = $jq;\n\nDOMBackend.parseHTML = function (html) {\n  // Return an array of nodes.\n  //\n  // jQuery does fancy stuff like creating an appropriate\n  // container element and setting innerHTML on it, as well\n  // as working around various IE quirks.\n  return $jq.parseHTML(html) || [];\n};\n\nDOMBackend.Events = {\n  // `selector` is non-null.  `type` is one type (but\n  // may be in backend-specific form, e.g. have namespaces).\n  // Order fired must be order bound.\n  delegateEvents: function (elem, type, selector, handler) {\n    $jq(elem).on(type, selector, handler);\n  },\n\n  undelegateEvents: function (elem, type, handler) {\n    $jq(elem).off(type, '**', handler);\n  },\n\n  bindEventCapturer: function (elem, type, selector, handler) {\n    var $elem = $jq(elem);\n\n    var wrapper = function (event) {\n      event = $jq.event.fix(event);\n      event.currentTarget = event.target;\n\n      // Note: It might improve jQuery interop if we called into jQuery\n      // here somehow.  Since we don't use jQuery to dispatch the event,\n      // we don't fire any of jQuery's event hooks or anything.  However,\n      // since jQuery can't bind capturing handlers, it's not clear\n      // where we would hook in.  Internal jQuery functions like `dispatch`\n      // are too high-level.\n      var $target = $jq(event.currentTarget);\n      if ($target.is($elem.find(selector)))\n        handler.call(elem, event);\n    };\n\n    handler._meteorui_wrapper = wrapper;\n\n    type = DOMBackend.Events.parseEventType(type);\n    // add *capturing* event listener\n    elem.addEventListener(type, wrapper, true);\n  },\n\n  unbindEventCapturer: function (elem, type, handler) {\n    type = DOMBackend.Events.parseEventType(type);\n    elem.removeEventListener(type, handler._meteorui_wrapper, true);\n  },\n\n  parseEventType: function (type) {\n    // strip off namespaces\n    var dotLoc = type.indexOf('.');\n    if (dotLoc >= 0)\n      return type.slice(0, dotLoc);\n    return type;\n  }\n};\n\n\n///// Removal detection and interoperability.\n\n// For an explanation of this technique, see:\n// http://bugs.jquery.com/ticket/12213#comment:23 .\n//\n// In short, an element is considered \"removed\" when jQuery\n// cleans up its *private* userdata on the element,\n// which we can detect using a custom event with a teardown\n// hook.\n\nvar NOOP = function () {};\n\n// Circular doubly-linked list\nvar TeardownCallback = function (func) {\n  this.next = this;\n  this.prev = this;\n  this.func = func;\n};\n\n// Insert newElt before oldElt in the circular list\nTeardownCallback.prototype.linkBefore = function(oldElt) {\n  this.prev = oldElt.prev;\n  this.next = oldElt;\n  oldElt.prev.next = this;\n  oldElt.prev = this;\n};\n\nTeardownCallback.prototype.unlink = function () {\n  this.prev.next = this.next;\n  this.next.prev = this.prev;\n};\n\nTeardownCallback.prototype.go = function () {\n  var func = this.func;\n  func && func();\n};\n\nTeardownCallback.prototype.stop = TeardownCallback.prototype.unlink;\n\nDOMBackend.Teardown = {\n  _JQUERY_EVENT_NAME: 'blaze_teardown_watcher',\n  _CB_PROP: '$blaze_teardown_callbacks',\n  // Registers a callback function to be called when the given element or\n  // one of its ancestors is removed from the DOM via the backend library.\n  // The callback function is called at most once, and it receives the element\n  // in question as an argument.\n  onElementTeardown: function (elem, func) {\n    var elt = new TeardownCallback(func);\n\n    var propName = DOMBackend.Teardown._CB_PROP;\n    if (! elem[propName]) {\n      // create an empty node that is never unlinked\n      elem[propName] = new TeardownCallback;\n\n      // Set up the event, only the first time.\n      $jq(elem).on(DOMBackend.Teardown._JQUERY_EVENT_NAME, NOOP);\n    }\n\n    elt.linkBefore(elem[propName]);\n\n    return elt; // so caller can call stop()\n  },\n  // Recursively call all teardown hooks, in the backend and registered\n  // through DOMBackend.onElementTeardown.\n  tearDownElement: function (elem) {\n    var elems = [];\n    // Array.prototype.slice.call doesn't work when given a NodeList in\n    // IE8 (\"JScript object expected\").\n    var nodeList = elem.getElementsByTagName('*');\n    for (var i = 0; i < nodeList.length; i++) {\n      elems.push(nodeList[i]);\n    }\n    elems.push(elem);\n    $jq.cleanData(elems);\n  }\n};\n\n$jq.event.special[DOMBackend.Teardown._JQUERY_EVENT_NAME] = {\n  setup: function () {\n    // This \"setup\" callback is important even though it is empty!\n    // Without it, jQuery will call addEventListener, which is a\n    // performance hit, especially with Chrome's async stack trace\n    // feature enabled.\n  },\n  teardown: function() {\n    var elem = this;\n    var callbacks = elem[DOMBackend.Teardown._CB_PROP];\n    if (callbacks) {\n      var elt = callbacks.next;\n      while (elt !== callbacks) {\n        elt.go();\n        elt = elt.next;\n      }\n      callbacks.go();\n\n      elem[DOMBackend.Teardown._CB_PROP] = null;\n    }\n  }\n};\n\n\n// Must use jQuery semantics for `context`, not\n// querySelectorAll's.  In other words, all the parts\n// of `selector` must be found under `context`.\nDOMBackend.findBySelector = function (selector, context) {\n  return $jq(selector, context);\n};\n"
  },
  {
    "path": "packages/blaze/domrange.js",
    "content": "\n// A constant empty array (frozen if the JS engine supports it).\nvar _emptyArray = Object.freeze ? Object.freeze([]) : [];\n\n// `[new] Blaze._DOMRange([nodeAndRangeArray])`\n//\n// A DOMRange consists of an array of consecutive nodes and DOMRanges,\n// which may be replaced at any time with a new array.  If the DOMRange\n// has been attached to the DOM at some location, then updating\n// the array will cause the DOM to be updated at that location.\nBlaze._DOMRange = function (nodeAndRangeArray) {\n  if (! (this instanceof DOMRange))\n    // called without `new`\n    return new DOMRange(nodeAndRangeArray);\n\n  var members = (nodeAndRangeArray || _emptyArray);\n  if (! (members && (typeof members.length) === 'number'))\n    throw new Error(\"Expected array\");\n\n  for (var i = 0; i < members.length; i++)\n    this._memberIn(members[i]);\n\n  this.members = members;\n  this.emptyRangePlaceholder = null;\n  this.attached = false;\n  this.parentElement = null;\n  this.parentRange = null;\n  this.attachedCallbacks = _emptyArray;\n};\nvar DOMRange = Blaze._DOMRange;\n\n// In IE 8, don't use empty text nodes as placeholders\n// in empty DOMRanges, use comment nodes instead.  Using\n// empty text nodes in modern browsers is great because\n// it doesn't clutter the web inspector.  In IE 8, however,\n// it seems to lead in some roundabout way to the OAuth\n// pop-up crashing the browser completely.  In the past,\n// we didn't use empty text nodes on IE 8 because they\n// don't accept JS properties, so just use the same logic\n// even though we don't need to set properties on the\n// placeholder anymore.\nDOMRange._USE_COMMENT_PLACEHOLDERS = (function () {\n  var result = false;\n  var textNode = document.createTextNode(\"\");\n  try {\n    textNode.someProp = true;\n  } catch (e) {\n    // IE 8\n    result = true;\n  }\n  return result;\n})();\n\n// static methods\nDOMRange._insert = function (rangeOrNode, parentElement, nextNode, _isMove) {\n  var m = rangeOrNode;\n  if (m instanceof DOMRange) {\n    m.attach(parentElement, nextNode, _isMove);\n  } else {\n    if (_isMove)\n      DOMRange._moveNodeWithHooks(m, parentElement, nextNode);\n    else\n      DOMRange._insertNodeWithHooks(m, parentElement, nextNode);\n  }\n};\n\nDOMRange._remove = function (rangeOrNode) {\n  var m = rangeOrNode;\n  if (m instanceof DOMRange) {\n    m.detach();\n  } else {\n    DOMRange._removeNodeWithHooks(m);\n  }\n};\n\nDOMRange._removeNodeWithHooks = function (n) {\n  if (! n.parentNode)\n    return;\n  if (n.nodeType === 1 &&\n      n.parentNode._uihooks && n.parentNode._uihooks.removeElement) {\n    n.parentNode._uihooks.removeElement(n);\n  } else {\n    n.parentNode.removeChild(n);\n  }\n};\n\nDOMRange._insertNodeWithHooks = function (n, parent, next) {\n  // `|| null` because IE throws an error if 'next' is undefined\n  next = next || null;\n  if (n.nodeType === 1 &&\n      parent._uihooks && parent._uihooks.insertElement) {\n    parent._uihooks.insertElement(n, next);\n  } else {\n    parent.insertBefore(n, next);\n  }\n};\n\nDOMRange._moveNodeWithHooks = function (n, parent, next) {\n  if (n.parentNode !== parent)\n    return;\n  // `|| null` because IE throws an error if 'next' is undefined\n  next = next || null;\n  if (n.nodeType === 1 &&\n      parent._uihooks && parent._uihooks.moveElement) {\n    parent._uihooks.moveElement(n, next);\n  } else {\n    parent.insertBefore(n, next);\n  }\n};\n\nDOMRange.forElement = function (elem) {\n  if (elem.nodeType !== 1)\n    throw new Error(\"Expected element, found: \" + elem);\n  var range = null;\n  while (elem && ! range) {\n    range = (elem.$blaze_range || null);\n    if (! range)\n      elem = elem.parentNode;\n  }\n  return range;\n};\n\nDOMRange.prototype.attach = function (parentElement, nextNode, _isMove, _isReplace) {\n  // This method is called to insert the DOMRange into the DOM for\n  // the first time, but it's also used internally when\n  // updating the DOM.\n  //\n  // If _isMove is true, move this attached range to a different\n  // location under the same parentElement.\n  if (_isMove || _isReplace) {\n    if (! (this.parentElement === parentElement &&\n           this.attached))\n      throw new Error(\"Can only move or replace an attached DOMRange, and only under the same parent element\");\n  }\n\n  var members = this.members;\n  if (members.length) {\n    this.emptyRangePlaceholder = null;\n    for (var i = 0; i < members.length; i++) {\n      DOMRange._insert(members[i], parentElement, nextNode, _isMove);\n    }\n  } else {\n    var placeholder = (\n      DOMRange._USE_COMMENT_PLACEHOLDERS ?\n        document.createComment(\"\") :\n        document.createTextNode(\"\"));\n    this.emptyRangePlaceholder = placeholder;\n    parentElement.insertBefore(placeholder, nextNode || null);\n  }\n  this.attached = true;\n  this.parentElement = parentElement;\n\n  if (! (_isMove || _isReplace)) {\n    for(var i = 0; i < this.attachedCallbacks.length; i++) {\n      var obj = this.attachedCallbacks[i];\n      obj.attached && obj.attached(this, parentElement);\n    }\n  }\n};\n\nDOMRange.prototype.setMembers = function (newNodeAndRangeArray) {\n  var newMembers = newNodeAndRangeArray;\n  if (! (newMembers && (typeof newMembers.length) === 'number'))\n    throw new Error(\"Expected array\");\n\n  var oldMembers = this.members;\n\n  for (var i = 0; i < oldMembers.length; i++)\n    this._memberOut(oldMembers[i]);\n  for (var i = 0; i < newMembers.length; i++)\n    this._memberIn(newMembers[i]);\n\n  if (! this.attached) {\n    this.members = newMembers;\n  } else {\n    // don't do anything if we're going from empty to empty\n    if (newMembers.length || oldMembers.length) {\n      // detach the old members and insert the new members\n      var nextNode = this.lastNode().nextSibling;\n      var parentElement = this.parentElement;\n      // Use detach/attach, but don't fire attached/detached hooks\n      this.detach(true /*_isReplace*/);\n      this.members = newMembers;\n      this.attach(parentElement, nextNode, false, true /*_isReplace*/);\n    }\n  }\n};\n\nDOMRange.prototype.firstNode = function () {\n  if (! this.attached)\n    throw new Error(\"Must be attached\");\n\n  if (! this.members.length)\n    return this.emptyRangePlaceholder;\n\n  var m = this.members[0];\n  return (m instanceof DOMRange) ? m.firstNode() : m;\n};\n\nDOMRange.prototype.lastNode = function () {\n  if (! this.attached)\n    throw new Error(\"Must be attached\");\n\n  if (! this.members.length)\n    return this.emptyRangePlaceholder;\n\n  var m = this.members[this.members.length - 1];\n  return (m instanceof DOMRange) ? m.lastNode() : m;\n};\n\nDOMRange.prototype.detach = function (_isReplace) {\n  if (! this.attached)\n    throw new Error(\"Must be attached\");\n\n  var oldParentElement = this.parentElement;\n  var members = this.members;\n  if (members.length) {\n    for (var i = 0; i < members.length; i++) {\n      DOMRange._remove(members[i]);\n    }\n  } else {\n    var placeholder = this.emptyRangePlaceholder;\n    this.parentElement.removeChild(placeholder);\n    this.emptyRangePlaceholder = null;\n  }\n\n  if (! _isReplace) {\n    this.attached = false;\n    this.parentElement = null;\n\n    for(var i = 0; i < this.attachedCallbacks.length; i++) {\n      var obj = this.attachedCallbacks[i];\n      obj.detached && obj.detached(this, oldParentElement);\n    }\n  }\n};\n\nDOMRange.prototype.addMember = function (newMember, atIndex, _isMove) {\n  var members = this.members;\n  if (! (atIndex >= 0 && atIndex <= members.length))\n    throw new Error(\"Bad index in range.addMember: \" + atIndex);\n\n  if (! _isMove)\n    this._memberIn(newMember);\n\n  if (! this.attached) {\n    // currently detached; just updated members\n    members.splice(atIndex, 0, newMember);\n  } else if (members.length === 0) {\n    // empty; use the empty-to-nonempty handling of setMembers\n    this.setMembers([newMember]);\n  } else {\n    var nextNode;\n    if (atIndex === members.length) {\n      // insert at end\n      nextNode = this.lastNode().nextSibling;\n    } else {\n      var m = members[atIndex];\n      nextNode = (m instanceof DOMRange) ? m.firstNode() : m;\n    }\n    members.splice(atIndex, 0, newMember);\n    DOMRange._insert(newMember, this.parentElement, nextNode, _isMove);\n  }\n};\n\nDOMRange.prototype.removeMember = function (atIndex, _isMove) {\n  var members = this.members;\n  if (! (atIndex >= 0 && atIndex < members.length))\n    throw new Error(\"Bad index in range.removeMember: \" + atIndex);\n\n  if (_isMove) {\n    members.splice(atIndex, 1);\n  } else {\n    var oldMember = members[atIndex];\n    this._memberOut(oldMember);\n\n    if (members.length === 1) {\n      // becoming empty; use the logic in setMembers\n      this.setMembers(_emptyArray);\n    } else {\n      members.splice(atIndex, 1);\n      if (this.attached)\n        DOMRange._remove(oldMember);\n    }\n  }\n};\n\nDOMRange.prototype.moveMember = function (oldIndex, newIndex) {\n  var member = this.members[oldIndex];\n  this.removeMember(oldIndex, true /*_isMove*/);\n  this.addMember(member, newIndex, true /*_isMove*/);\n};\n\nDOMRange.prototype.getMember = function (atIndex) {\n  var members = this.members;\n  if (! (atIndex >= 0 && atIndex < members.length))\n    throw new Error(\"Bad index in range.getMember: \" + atIndex);\n  return this.members[atIndex];\n};\n\nDOMRange.prototype._memberIn = function (m) {\n  if (m instanceof DOMRange)\n    m.parentRange = this;\n  else if (m.nodeType === 1) // DOM Element\n    m.$blaze_range = this;\n};\n\nDOMRange._destroy = function (m, _skipNodes) {\n  if (m instanceof DOMRange) {\n    if (m.view)\n      Blaze._destroyView(m.view, _skipNodes);\n  } else if ((! _skipNodes) && m.nodeType === 1) {\n    // DOM Element\n    if (m.$blaze_range) {\n      Blaze._destroyNode(m);\n      m.$blaze_range = null;\n    }\n  }\n};\n\nDOMRange.prototype._memberOut = DOMRange._destroy;\n\n// Tear down, but don't remove, the members.  Used when chunks\n// of DOM are being torn down or replaced.\nDOMRange.prototype.destroyMembers = function (_skipNodes) {\n  var members = this.members;\n  for (var i = 0; i < members.length; i++)\n    this._memberOut(members[i], _skipNodes);\n};\n\nDOMRange.prototype.destroy = function (_skipNodes) {\n  DOMRange._destroy(this, _skipNodes);\n};\n\nDOMRange.prototype.containsElement = function (elem) {\n  if (! this.attached)\n    throw new Error(\"Must be attached\");\n\n  // An element is contained in this DOMRange if it's possible to\n  // reach it by walking parent pointers, first through the DOM and\n  // then parentRange pointers.  In other words, the element or some\n  // ancestor of it is at our level of the DOM (a child of our\n  // parentElement), and this element is one of our members or\n  // is a member of a descendant Range.\n\n  // First check that elem is a descendant of this.parentElement,\n  // according to the DOM.\n  if (! Blaze._elementContains(this.parentElement, elem))\n    return false;\n\n  // If elem is not an immediate child of this.parentElement,\n  // walk up to its ancestor that is.\n  while (elem.parentNode !== this.parentElement)\n    elem = elem.parentNode;\n\n  var range = elem.$blaze_range;\n  while (range && range !== this)\n    range = range.parentRange;\n\n  return range === this;\n};\n\nDOMRange.prototype.containsRange = function (range) {\n  if (! this.attached)\n    throw new Error(\"Must be attached\");\n\n  if (! range.attached)\n    return false;\n\n  // A DOMRange is contained in this DOMRange if it's possible\n  // to reach this range by following parent pointers.  If the\n  // DOMRange has the same parentElement, then it should be\n  // a member, or a member of a member etc.  Otherwise, we must\n  // contain its parentElement.\n\n  if (range.parentElement !== this.parentElement)\n    return this.containsElement(range.parentElement);\n\n  if (range === this)\n    return false; // don't contain self\n\n  while (range && range !== this)\n    range = range.parentRange;\n\n  return range === this;\n};\n\nDOMRange.prototype.onAttached = function (attached) {\n  this.onAttachedDetached({ attached: attached });\n};\n\n// callbacks are `attached(range, element)` and\n// `detached(range, element)`, and they may\n// access the `callbacks` object in `this`.\n// The arguments to `detached` are the same\n// range and element that were passed to `attached`.\nDOMRange.prototype.onAttachedDetached = function (callbacks) {\n  if (this.attachedCallbacks === _emptyArray)\n    this.attachedCallbacks = [];\n  this.attachedCallbacks.push(callbacks);\n};\n\nDOMRange.prototype.$ = function (selector) {\n  var self = this;\n\n  var parentNode = this.parentElement;\n  if (! parentNode)\n    throw new Error(\"Can't select in removed DomRange\");\n\n  // Strategy: Find all selector matches under parentNode,\n  // then filter out the ones that aren't in this DomRange\n  // using `DOMRange#containsElement`.  This is\n  // asymptotically slow in the presence of O(N) sibling\n  // content that is under parentNode but not in our range,\n  // so if performance is an issue, the selector should be\n  // run on a child element.\n\n  // Since jQuery can't run selectors on a DocumentFragment,\n  // we don't expect findBySelector to work.\n  if (parentNode.nodeType === 11 /* DocumentFragment */)\n    throw new Error(\"Can't use $ on an offscreen range\");\n\n  var results = Blaze._DOMBackend.findBySelector(selector, parentNode);\n\n  // We don't assume `results` has jQuery API; a plain array\n  // should do just as well.  However, if we do have a jQuery\n  // array, we want to end up with one also, so we use\n  // `.filter`.\n\n  // Function that selects only elements that are actually\n  // in this DomRange, rather than simply descending from\n  // `parentNode`.\n  var filterFunc = function (elem) {\n    // handle jQuery's arguments to filter, where the node\n    // is in `this` and the index is the first argument.\n    if (typeof elem === 'number')\n      elem = this;\n\n    return self.containsElement(elem);\n  };\n\n  if (! results.filter) {\n    // not a jQuery array, and not a browser with\n    // Array.prototype.filter (e.g. IE <9)\n    var newResults = [];\n    for (var i = 0; i < results.length; i++) {\n      var x = results[i];\n      if (filterFunc(x))\n        newResults.push(x);\n    }\n    results = newResults;\n  } else {\n    // `results.filter` is either jQuery's or ECMAScript's `filter`\n    results = results.filter(filterFunc);\n  }\n\n  return results;\n};\n\n// Returns true if element a contains node b and is not node b.\n//\n// The restriction that `a` be an element (not a document fragment,\n// say) is based on what's easy to implement cross-browser.\nBlaze._elementContains = function (a, b) {\n  if (a.nodeType !== 1) // ELEMENT\n    return false;\n  if (a === b)\n    return false;\n\n  if (a.compareDocumentPosition) {\n    return a.compareDocumentPosition(b) & 0x10;\n  } else {\n    // Should be only old IE and maybe other old browsers here.\n    // Modern Safari has both functions but seems to get contains() wrong.\n    // IE can't handle b being a text node.  We work around this\n    // by doing a direct parent test now.\n    b = b.parentNode;\n    if (! (b && b.nodeType === 1)) // ELEMENT\n      return false;\n    if (a === b)\n      return true;\n\n    return a.contains(b);\n  }\n};\n"
  },
  {
    "path": "packages/blaze/events.js",
    "content": "var EventSupport = Blaze._EventSupport = {};\n\nvar DOMBackend = Blaze._DOMBackend;\n\n// List of events to always delegate, never capture.\n// Since jQuery fakes bubbling for certain events in\n// certain browsers (like `submit`), we don't want to\n// get in its way.\n//\n// We could list all known bubbling\n// events here to avoid creating speculative capturers\n// for them, but it would only be an optimization.\nvar eventsToDelegate = EventSupport.eventsToDelegate = {\n  blur: 1, change: 1, click: 1, focus: 1, focusin: 1,\n  focusout: 1, reset: 1, submit: 1\n};\n\nvar EVENT_MODE = EventSupport.EVENT_MODE = {\n  TBD: 0,\n  BUBBLING: 1,\n  CAPTURING: 2\n};\n\nvar NEXT_HANDLERREC_ID = 1;\n\nvar HandlerRec = function (elem, type, selector, handler, recipient) {\n  this.elem = elem;\n  this.type = type;\n  this.selector = selector;\n  this.handler = handler;\n  this.recipient = recipient;\n  this.id = (NEXT_HANDLERREC_ID++);\n\n  this.mode = EVENT_MODE.TBD;\n\n  // It's important that delegatedHandler be a different\n  // instance for each handlerRecord, because its identity\n  // is used to remove it.\n  //\n  // It's also important that the closure have access to\n  // `this` when it is not called with it set.\n  this.delegatedHandler = (function (h) {\n    return function (evt) {\n      if ((! h.selector) && evt.currentTarget !== evt.target)\n        // no selector means only fire on target\n        return;\n      return h.handler.apply(h.recipient, arguments);\n    };\n  })(this);\n\n  // WHY CAPTURE AND DELEGATE: jQuery can't delegate\n  // non-bubbling events, because\n  // event capture doesn't work in IE 8.  However, there\n  // are all sorts of new-fangled non-bubbling events\n  // like \"play\" and \"touchenter\".  We delegate these\n  // events using capture in all browsers except IE 8.\n  // IE 8 doesn't support these events anyway.\n\n  var tryCapturing = elem.addEventListener &&\n        (! _.has(eventsToDelegate,\n                 DOMBackend.Events.parseEventType(type)));\n\n  if (tryCapturing) {\n    this.capturingHandler = (function (h) {\n      return function (evt) {\n        if (h.mode === EVENT_MODE.TBD) {\n          // must be first time we're called.\n          if (evt.bubbles) {\n            // this type of event bubbles, so don't\n            // get called again.\n            h.mode = EVENT_MODE.BUBBLING;\n            DOMBackend.Events.unbindEventCapturer(\n              h.elem, h.type, h.capturingHandler);\n            return;\n          } else {\n            // this type of event doesn't bubble,\n            // so unbind the delegation, preventing\n            // it from ever firing.\n            h.mode = EVENT_MODE.CAPTURING;\n            DOMBackend.Events.undelegateEvents(\n              h.elem, h.type, h.delegatedHandler);\n          }\n        }\n\n        h.delegatedHandler(evt);\n      };\n    })(this);\n\n  } else {\n    this.mode = EVENT_MODE.BUBBLING;\n  }\n};\nEventSupport.HandlerRec = HandlerRec;\n\nHandlerRec.prototype.bind = function () {\n  // `this.mode` may be EVENT_MODE_TBD, in which case we bind both. in\n  // this case, 'capturingHandler' is in charge of detecting the\n  // correct mode and turning off one or the other handlers.\n  if (this.mode !== EVENT_MODE.BUBBLING) {\n    DOMBackend.Events.bindEventCapturer(\n      this.elem, this.type, this.selector || '*',\n      this.capturingHandler);\n  }\n\n  if (this.mode !== EVENT_MODE.CAPTURING)\n    DOMBackend.Events.delegateEvents(\n      this.elem, this.type,\n      this.selector || '*', this.delegatedHandler);\n};\n\nHandlerRec.prototype.unbind = function () {\n  if (this.mode !== EVENT_MODE.BUBBLING)\n    DOMBackend.Events.unbindEventCapturer(this.elem, this.type,\n                                          this.capturingHandler);\n\n  if (this.mode !== EVENT_MODE.CAPTURING)\n    DOMBackend.Events.undelegateEvents(this.elem, this.type,\n                                       this.delegatedHandler);\n};\n\nEventSupport.listen = function (element, events, selector, handler, recipient, getParentRecipient) {\n\n  // Prevent this method from being JITed by Safari.  Due to a\n  // presumed JIT bug in Safari -- observed in Version 7.0.6\n  // (9537.78.2) -- this method may crash the Safari render process if\n  // it is JITed.\n  // Repro: https://github.com/dgreensp/public/tree/master/safari-crash\n  try { element = element; } finally {}\n\n  var eventTypes = [];\n  events.replace(/[^ /]+/g, function (e) {\n    eventTypes.push(e);\n  });\n\n  var newHandlerRecs = [];\n  for (var i = 0, N = eventTypes.length; i < N; i++) {\n    var type = eventTypes[i];\n\n    var eventDict = element.$blaze_events;\n    if (! eventDict)\n      eventDict = (element.$blaze_events = {});\n\n    var info = eventDict[type];\n    if (! info) {\n      info = eventDict[type] = {};\n      info.handlers = [];\n    }\n    var handlerList = info.handlers;\n    var handlerRec = new HandlerRec(\n      element, type, selector, handler, recipient);\n    newHandlerRecs.push(handlerRec);\n    handlerRec.bind();\n    handlerList.push(handlerRec);\n    // Move handlers of enclosing ranges to end, by unbinding and rebinding\n    // them.  In jQuery (or other DOMBackend) this causes them to fire\n    // later when the backend dispatches event handlers.\n    if (getParentRecipient) {\n      for (var r = getParentRecipient(recipient); r;\n           r = getParentRecipient(r)) {\n        // r is an enclosing range (recipient)\n        for (var j = 0, Nj = handlerList.length;\n             j < Nj; j++) {\n          var h = handlerList[j];\n          if (h.recipient === r) {\n            h.unbind();\n            h.bind();\n            handlerList.splice(j, 1); // remove handlerList[j]\n            handlerList.push(h);\n            j--; // account for removed handler\n            Nj--; // don't visit appended handlers\n          }\n        }\n      }\n    }\n  }\n\n  return {\n    // closes over just `element` and `newHandlerRecs`\n    stop: function () {\n      var eventDict = element.$blaze_events;\n      if (! eventDict)\n        return;\n      // newHandlerRecs has only one item unless you specify multiple\n      // event types.  If this code is slow, it's because we have to\n      // iterate over handlerList here.  Clearing a whole handlerList\n      // via stop() methods is O(N^2) in the number of handlers on\n      // an element.\n      for (var i = 0; i < newHandlerRecs.length; i++) {\n        var handlerToRemove = newHandlerRecs[i];\n        var info = eventDict[handlerToRemove.type];\n        if (! info)\n          continue;\n        var handlerList = info.handlers;\n        for (var j = handlerList.length - 1; j >= 0; j--) {\n          if (handlerList[j] === handlerToRemove) {\n            handlerToRemove.unbind();\n            handlerList.splice(j, 1); // remove handlerList[j]\n          }\n        }\n      }\n      newHandlerRecs.length = 0;\n    }\n  };\n};\n"
  },
  {
    "path": "packages/blaze/exceptions.js",
    "content": "var debugFunc;\n\n// We call into user code in many places, and it's nice to catch exceptions\n// propagated from user code immediately so that the whole system doesn't just\n// break.  Catching exceptions is easy; reporting them is hard.  This helper\n// reports exceptions.\n//\n// Usage:\n//\n// ```\n// try {\n//   // ... someStuff ...\n// } catch (e) {\n//   reportUIException(e);\n// }\n// ```\n//\n// An optional second argument overrides the default message.\n\n// Set this to `true` to cause `reportException` to throw\n// the next exception rather than reporting it.  This is\n// useful in unit tests that test error messages.\nBlaze._throwNextException = false;\n\nBlaze._reportException = function (e, msg) {\n  if (Blaze._throwNextException) {\n    Blaze._throwNextException = false;\n    throw e;\n  }\n\n  if (! debugFunc)\n    // adapted from Tracker\n    debugFunc = function () {\n      return (typeof Meteor !== \"undefined\" ? Meteor._debug :\n              ((typeof console !== \"undefined\") && console.log ? console.log :\n               function () {}));\n    };\n\n  // In Chrome, `e.stack` is a multiline string that starts with the message\n  // and contains a stack trace.  Furthermore, `console.log` makes it clickable.\n  // `console.log` supplies the space between the two arguments.\n  debugFunc()(msg || 'Exception caught in template:', e.stack || e.message || e);\n};\n\nBlaze._wrapCatchingExceptions = function (f, where) {\n  if (typeof f !== 'function')\n    return f;\n\n  return function () {\n    try {\n      return f.apply(this, arguments);\n    } catch (e) {\n      Blaze._reportException(e, 'Exception in ' + where + ':');\n    }\n  };\n};\n"
  },
  {
    "path": "packages/blaze/lookup.js",
    "content": "Blaze._globalHelpers = {};\n\n// Documented as Template.registerHelper.\n// This definition also provides back-compat for `UI.registerHelper`.\nBlaze.registerHelper = function (name, func) {\n  Blaze._globalHelpers[name] = func;\n};\n\n// Also documented as Template.deregisterHelper\nBlaze.deregisterHelper = function(name) {\n  delete Blaze._globalHelpers[name];\n}\n\nvar bindIfIsFunction = function (x, target) {\n  if (typeof x !== 'function')\n    return x;\n  return _.bind(x, target);\n};\n\n// If `x` is a function, binds the value of `this` for that function\n// to the current data context.\nvar bindDataContext = function (x) {\n  if (typeof x === 'function') {\n    return function () {\n      var data = Blaze.getData();\n      if (data == null)\n        data = {};\n      return x.apply(data, arguments);\n    };\n  }\n  return x;\n};\n\nBlaze._OLDSTYLE_HELPER = {};\n\nBlaze._getTemplateHelper = function (template, name, tmplInstanceFunc) {\n  // XXX COMPAT WITH 0.9.3\n  var isKnownOldStyleHelper = false;\n\n  if (template.__helpers.has(name)) {\n    var helper = template.__helpers.get(name);\n    if (helper === Blaze._OLDSTYLE_HELPER) {\n      isKnownOldStyleHelper = true;\n    } else if (helper != null) {\n      return wrapHelper(bindDataContext(helper), tmplInstanceFunc);\n    } else {\n      return null;\n    }\n  }\n\n  // old-style helper\n  if (name in template) {\n    // Only warn once per helper\n    if (! isKnownOldStyleHelper) {\n      template.__helpers.set(name, Blaze._OLDSTYLE_HELPER);\n      if (! template._NOWARN_OLDSTYLE_HELPERS) {\n        Blaze._warn('Assigning helper with `' + template.viewName + '.' +\n                    name + ' = ...` is deprecated.  Use `' + template.viewName +\n                    '.helpers(...)` instead.');\n      }\n    }\n    if (template[name] != null) {\n      return wrapHelper(bindDataContext(template[name]), tmplInstanceFunc);\n    }\n  }\n\n  return null;\n};\n\nvar wrapHelper = function (f, templateFunc) {\n  if (typeof f !== \"function\") {\n    return f;\n  }\n\n  return function () {\n    var self = this;\n    var args = arguments;\n\n    return Blaze.Template._withTemplateInstanceFunc(templateFunc, function () {\n      return Blaze._wrapCatchingExceptions(f, 'template helper').apply(self, args);\n    });\n  };\n};\n\nBlaze._lexicalBindingLookup = function (view, name) {\n  var currentView = view;\n  var blockHelpersStack = [];\n\n  // walk up the views stopping at a Spacebars.include or Template view that\n  // doesn't have an InOuterTemplateScope view as a parent\n  do {\n    // skip block helpers views\n    // if we found the binding on the scope, return it\n    if (_.has(currentView._scopeBindings, name)) {\n      var bindingReactiveVar = currentView._scopeBindings[name];\n      return function () {\n        return bindingReactiveVar.get();\n      };\n    }\n  } while (! (currentView.__startsNewLexicalScope &&\n              ! (currentView.parentView &&\n                 currentView.parentView.__childDoesntStartNewLexicalScope))\n           && (currentView = currentView.parentView));\n\n  return null;\n};\n\n// templateInstance argument is provided to be available for possible\n// alternative implementations of this function by 3rd party packages.\nBlaze._getTemplate = function (name, templateInstance) {\n  if ((name in Blaze.Template) && (Blaze.Template[name] instanceof Blaze.Template)) {\n    return Blaze.Template[name];\n  }\n  return null;\n};\n\nBlaze._getGlobalHelper = function (name, templateInstance) {\n  if (Blaze._globalHelpers[name] != null) {\n    return wrapHelper(bindDataContext(Blaze._globalHelpers[name]), templateInstance);\n  }\n  return null;\n};\n\n// Looks up a name, like \"foo\" or \"..\", as a helper of the\n// current template; the name of a template; a global helper;\n// or a property of the data context.  Called on the View of\n// a template (i.e. a View with a `.template` property,\n// where the helpers are).  Used for the first name in a\n// \"path\" in a template tag, like \"foo\" in `{{foo.bar}}` or\n// \"..\" in `{{frobulate ../blah}}`.\n//\n// Returns a function, a non-function value, or null.  If\n// a function is found, it is bound appropriately.\n//\n// NOTE: This function must not establish any reactive\n// dependencies itself.  If there is any reactivity in the\n// value, lookup should return a function.\nBlaze.View.prototype.lookup = function (name, _options) {\n  var template = this.template;\n  var lookupTemplate = _options && _options.template;\n  var helper;\n  var binding;\n  var boundTmplInstance;\n  var foundTemplate;\n\n  if (this.templateInstance) {\n    boundTmplInstance = _.bind(this.templateInstance, this);\n  }\n\n  // 0. looking up the parent data context with the special \"../\" syntax\n  if (/^\\./.test(name)) {\n    // starts with a dot. must be a series of dots which maps to an\n    // ancestor of the appropriate height.\n    if (!/^(\\.)+$/.test(name))\n      throw new Error(\"id starting with dot must be a series of dots\");\n\n    return Blaze._parentData(name.length - 1, true /*_functionWrapped*/);\n\n  }\n\n  // 1. look up a helper on the current template\n  if (template && ((helper = Blaze._getTemplateHelper(template, name, boundTmplInstance)) != null)) {\n    return helper;\n  }\n\n  // 2. look up a binding by traversing the lexical view hierarchy inside the\n  // current template\n  if (template && (binding = Blaze._lexicalBindingLookup(Blaze.currentView, name)) != null) {\n    return binding;\n  }\n\n  // 3. look up a template by name\n  if (lookupTemplate && ((foundTemplate = Blaze._getTemplate(name, boundTmplInstance)) != null)) {\n    return foundTemplate;\n  }\n\n  // 4. look up a global helper\n  if ((helper = Blaze._getGlobalHelper(name, boundTmplInstance)) != null) {\n    return helper;\n  }\n\n  // 5. look up in a data context\n  return function () {\n    var isCalledAsFunction = (arguments.length > 0);\n    var data = Blaze.getData();\n    var x = data && data[name];\n    if (! x) {\n      if (lookupTemplate) {\n        throw new Error(\"No such template: \" + name);\n      } else if (isCalledAsFunction) {\n        throw new Error(\"No such function: \" + name);\n      } else if (name.charAt(0) === '@' && ((x === null) ||\n                                            (x === undefined))) {\n        // Throw an error if the user tries to use a `@directive`\n        // that doesn't exist.  We don't implement all directives\n        // from Handlebars, so there's a potential for confusion\n        // if we fail silently.  On the other hand, we want to\n        // throw late in case some app or package wants to provide\n        // a missing directive.\n        throw new Error(\"Unsupported directive: \" + name);\n      }\n    }\n    if (! data) {\n      return null;\n    }\n    if (typeof x !== 'function') {\n      if (isCalledAsFunction) {\n        throw new Error(\"Can't call non-function: \" + x);\n      }\n      return x;\n    }\n    return x.apply(data, arguments);\n  };\n};\n\n// Implement Spacebars' {{../..}}.\n// @param height {Number} The number of '..'s\nBlaze._parentData = function (height, _functionWrapped) {\n  // If height is null or undefined, we default to 1, the first parent.\n  if (height == null) {\n    height = 1;\n  }\n  var theWith = Blaze.getView('with');\n  for (var i = 0; (i < height) && theWith; i++) {\n    theWith = Blaze.getView(theWith, 'with');\n  }\n\n  if (! theWith)\n    return null;\n  if (_functionWrapped)\n    return function () { return theWith.dataVar.get(); };\n  return theWith.dataVar.get();\n};\n\n\nBlaze.View.prototype.lookupTemplate = function (name) {\n  return this.lookup(name, {template:true});\n};\n"
  },
  {
    "path": "packages/blaze/materializer.js",
    "content": "// Turns HTMLjs into DOM nodes and DOMRanges.\n//\n// - `htmljs`: the value to materialize, which may be any of the htmljs\n//   types (Tag, CharRef, Comment, Raw, array, string, boolean, number,\n//   null, or undefined) or a View or Template (which will be used to\n//   construct a View).\n// - `intoArray`: the array of DOM nodes and DOMRanges to push the output\n//   into (required)\n// - `parentView`: the View we are materializing content for (optional)\n// - `_existingWorkStack`: optional argument, only used for recursive\n//   calls when there is some other _materializeDOM on the call stack.\n//   If _materializeDOM called your function and passed in a workStack,\n//   pass it back when you call _materializeDOM (such as from a workStack\n//   task).\n//\n// Returns `intoArray`, which is especially useful if you pass in `[]`.\nBlaze._materializeDOM = function (htmljs, intoArray, parentView,\n                                  _existingWorkStack) {\n  // In order to use fewer stack frames, materializeDOMInner can push\n  // tasks onto `workStack`, and they will be popped off\n  // and run, last first, after materializeDOMInner returns.  The\n  // reason we use a stack instead of a queue is so that we recurse\n  // depth-first, doing newer tasks first.\n  var workStack = (_existingWorkStack || []);\n  materializeDOMInner(htmljs, intoArray, parentView, workStack);\n\n  if (! _existingWorkStack) {\n    // We created the work stack, so we are responsible for finishing\n    // the work.  Call each \"task\" function, starting with the top\n    // of the stack.\n    while (workStack.length) {\n      // Note that running task() may push new items onto workStack.\n      var task = workStack.pop();\n      task();\n    }\n  }\n\n  return intoArray;\n};\n\nvar materializeDOMInner = function (htmljs, intoArray, parentView, workStack) {\n  if (htmljs == null) {\n    // null or undefined\n    return;\n  }\n\n  switch (typeof htmljs) {\n  case 'string': case 'boolean': case 'number':\n    intoArray.push(document.createTextNode(String(htmljs)));\n    return;\n  case 'object':\n    if (htmljs.htmljsType) {\n      switch (htmljs.htmljsType) {\n      case HTML.Tag.htmljsType:\n        intoArray.push(materializeTag(htmljs, parentView, workStack));\n        return;\n      case HTML.CharRef.htmljsType:\n        intoArray.push(document.createTextNode(htmljs.str));\n        return;\n      case HTML.Comment.htmljsType:\n        intoArray.push(document.createComment(htmljs.sanitizedValue));\n        return;\n      case HTML.Raw.htmljsType:\n        // Get an array of DOM nodes by using the browser's HTML parser\n        // (like innerHTML).\n        var nodes = Blaze._DOMBackend.parseHTML(htmljs.value);\n        for (var i = 0; i < nodes.length; i++)\n          intoArray.push(nodes[i]);\n        return;\n      }\n    } else if (HTML.isArray(htmljs)) {\n      for (var i = htmljs.length-1; i >= 0; i--) {\n        workStack.push(_.bind(Blaze._materializeDOM, null,\n                              htmljs[i], intoArray, parentView, workStack));\n      }\n      return;\n    } else {\n      if (htmljs instanceof Blaze.Template) {\n        htmljs = htmljs.constructView();\n        // fall through to Blaze.View case below\n      }\n      if (htmljs instanceof Blaze.View) {\n        Blaze._materializeView(htmljs, parentView, workStack, intoArray);\n        return;\n      }\n    }\n  }\n\n  throw new Error(\"Unexpected object in htmljs: \" + htmljs);\n};\n\nvar materializeTag = function (tag, parentView, workStack) {\n  var tagName = tag.tagName;\n  var elem;\n  if ((HTML.isKnownSVGElement(tagName) || isSVGAnchor(tag))\n      && document.createElementNS) {\n    // inline SVG\n    elem = document.createElementNS('http://www.w3.org/2000/svg', tagName);\n  } else {\n    // normal elements\n    elem = document.createElement(tagName);\n  }\n\n  var rawAttrs = tag.attrs;\n  var children = tag.children;\n  if (tagName === 'textarea' && tag.children.length &&\n      ! (rawAttrs && ('value' in rawAttrs))) {\n    // Provide very limited support for TEXTAREA tags with children\n    // rather than a \"value\" attribute.\n    // Reactivity in the form of Views nested in the tag's children\n    // won't work.  Compilers should compile textarea contents into\n    // the \"value\" attribute of the tag, wrapped in a function if there\n    // is reactivity.\n    if (typeof rawAttrs === 'function' ||\n        HTML.isArray(rawAttrs)) {\n      throw new Error(\"Can't have reactive children of TEXTAREA node; \" +\n                      \"use the 'value' attribute instead.\");\n    }\n    rawAttrs = _.extend({}, rawAttrs || null);\n    rawAttrs.value = Blaze._expand(children, parentView);\n    children = [];\n  }\n\n  if (rawAttrs) {\n    var attrUpdater = new ElementAttributesUpdater(elem);\n    var updateAttributes = function () {\n      var expandedAttrs = Blaze._expandAttributes(rawAttrs, parentView);\n      var flattenedAttrs = HTML.flattenAttributes(expandedAttrs);\n      var stringAttrs = {};\n      for (var attrName in flattenedAttrs) {\n        stringAttrs[attrName] = Blaze._toText(flattenedAttrs[attrName],\n                                              parentView,\n                                              HTML.TEXTMODE.STRING);\n      }\n      attrUpdater.update(stringAttrs);\n    };\n    var updaterComputation;\n    if (parentView) {\n      updaterComputation =\n        parentView.autorun(updateAttributes, undefined, 'updater');\n    } else {\n      updaterComputation = Tracker.nonreactive(function () {\n        return Tracker.autorun(function () {\n          Tracker._withCurrentView(parentView, updateAttributes);\n        });\n      });\n    }\n    Blaze._DOMBackend.Teardown.onElementTeardown(elem, function attrTeardown() {\n      updaterComputation.stop();\n    });\n  }\n\n  if (children.length) {\n    var childNodesAndRanges = [];\n    // push this function first so that it's done last\n    workStack.push(function () {\n      for (var i = 0; i < childNodesAndRanges.length; i++) {\n        var x = childNodesAndRanges[i];\n        if (x instanceof Blaze._DOMRange)\n          x.attach(elem);\n        else\n          elem.appendChild(x);\n      }\n    });\n    // now push the task that calculates childNodesAndRanges\n    workStack.push(_.bind(Blaze._materializeDOM, null,\n                          children, childNodesAndRanges, parentView,\n                          workStack));\n  }\n\n  return elem;\n};\n\n\nvar isSVGAnchor = function (node) {\n  // We generally aren't able to detect SVG <a> elements because\n  // if \"A\" were in our list of known svg element names, then all\n  // <a> nodes would be created using\n  // `document.createElementNS`. But in the special case of <a\n  // xlink:href=\"...\">, we can at least detect that attribute and\n  // create an SVG <a> tag in that case.\n  //\n  // However, we still have a general problem of knowing when to\n  // use document.createElementNS and when to use\n  // document.createElement; for example, font tags will always\n  // be created as SVG elements which can cause other\n  // problems. #1977\n  return (node.tagName === \"a\" &&\n          node.attrs &&\n          node.attrs[\"xlink:href\"] !== undefined);\n};\n"
  },
  {
    "path": "packages/blaze/microscore.js",
    "content": "// Microscore is a partial polyfill for Underscore.  It implements\n// a subset of Underscore functions, and for some functions it\n// implements a subset of the full functionality.\n//\n// Code written against Microscore should just work with Underscore.\n// The reverse is not true, because Microscore doesn't support\n// all features of every function.  A list of known differences\n// between Underscore and Microscore is given with each function.\n//\n// This file should be curated to keep it small, so that it doesn't\n// grow into Underscore.\n//\n// In the future, we'll figure out something better, like package\n// slices and dead code elimination.\n\nif (typeof _ !== 'undefined')\n  throw new Error(\"If you have Underscore, don't use Microscore\");\n\n_ = {};\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar objectToString = Object.prototype.toString;\n\n// Doesn't support more than two arguments (more than one \"source\"\n// object).\n_.extend = function (tgt, src) {\n  for (var k in src) {\n    if (hasOwnProperty.call(src, k))\n      tgt[k] = src[k];\n  }\n  return tgt;\n};\n\n_.has = function (obj, key) {\n  return hasOwnProperty.call(obj, key);\n};\n\n// Returns a copy of `array` with falsy elements removed.\n_.compact = function (array) {\n  var result = [];\n  for (var i = 0; i < array.length; i++) {\n    var item = array[i];\n    if (item)\n      result.push(item);\n  }\n  return result;\n};\n\n// Returns whether `array` contains an element that is\n// `=== item`.\n_.contains = function (array, item) {\n  for (var i = 0; i < array.length; i++) {\n    if (array[i] === item)\n      return true;\n  }\n  return false;\n};\n\n// Returns `array` filtered to exclude elements that are\n// `=== item`.  Similar to `_.without`.\n_.without = function (array, item) {\n  var result = [];\n  for (var i = 0; i < array.length; i++) {\n    var x = array[i];\n    if (x !== item)\n      result.push(x);\n  }\n  return result;\n};\n\n// Assembles an array by calling `func(oldElement, index)`\n// on each element of `array`.  Assumes argument is an array.\n_.map = function (array, func) {\n  var result = new Array(array.length);\n  for (var i = 0; i < array.length; i++) {\n    result[i] = func(array[i], i);\n  }\n  return result;\n};\n\n// Given an array: Calls `func(element, index)` on each element of\n// `array`.\n//\n// Given an object: Calls `func(value, key)` on each key/value of\n// `obj`.\n//\n// Only REAL arrays are treated as arrays.  No Arguments objects, jQuery\n// objects, etc.  This may be relaxed to the standard Meteor approach\n// if it is too constraining.\n//\n// Doesn't accept `null` as first argument.  Doesn't delegate to built-in\n// `forEach` (which is generally not faster anyway because it calls\n// across the C/JS boundary).  Doesn't mess with JavaScript's built-in\n// behavior if keys are added or removed during iteration (i.e. may\n// or may not visit them).\n\n_.each = function (arrayOrObject, func) {\n  if (objectToString.call(arrayOrObject) === '[object Array]') {\n    var array = arrayOrObject;\n    for (var i = 0; i < array.length; i++) {\n      func(array[i], i);\n    }\n  } else {\n    var obj = arrayOrObject;\n    for (var key in obj) {\n      if (_.has(obj, key))\n        func(obj[key], key);\n    }\n  }\n};\n\n_.bind = function (f, context) {\n  return function () {\n    return f.apply(target, context);\n  };\n};\n"
  },
  {
    "path": "packages/blaze/package.js",
    "content": "Package.describe({\n  summary: \"Meteor Reactive Templating library\",\n  version: '2.1.8'\n});\n\nPackage.onUse(function (api) {\n  api.export(['Blaze', 'UI', 'Handlebars']);\n  api.use('jquery'); // should be a weak dep, by having multiple \"DOM backends\"\n  api.use('tracker');\n  api.use('check');\n  api.use('underscore'); // only the subset in microscore.js\n  api.use('htmljs');\n  api.imply('htmljs');\n  api.use('observe-sequence');\n  api.use('reactive-var');\n\n  api.addFiles([\n    'preamble.js'\n  ]);\n\n  // client-only files\n  api.addFiles([\n    'dombackend.js',\n    'domrange.js',\n    'events.js',\n    'attrs.js',\n    'materializer.js'\n  ], 'client');\n\n  // client and server\n  api.addFiles([\n    'exceptions.js',\n    'view.js',\n    'builtins.js',\n    'lookup.js',\n    'template.js',\n    'backcompat.js'\n  ]);\n});\n\nPackage.onTest(function (api) {\n  api.use('tinytest');\n  api.use('jquery'); // strong dependency, for testing jQuery backend\n  api.use('blaze');\n  api.use('test-helpers');\n  api.use('underscore');\n  api.use('blaze-tools'); // for BlazeTools.toJS\n  api.use('html-tools');\n  api.use('reactive-var');\n  api.use('tracker');\n  api.use('templating');\n\n  api.addFiles('view_tests.js');\n  api.addFiles('render_tests.js', 'client');\n});\n"
  },
  {
    "path": "packages/blaze/preamble.js",
    "content": "/**\n * @namespace Blaze\n * @summary The namespace for all Blaze-related methods and classes.\n */\nBlaze = {};\n\n// Utility to HTML-escape a string.  Included for legacy reasons.\nBlaze._escape = (function() {\n  var escape_map = {\n    \"<\": \"&lt;\",\n    \">\": \"&gt;\",\n    '\"': \"&quot;\",\n    \"'\": \"&#x27;\",\n    \"`\": \"&#x60;\", /* IE allows backtick-delimited attributes?? */\n    \"&\": \"&amp;\"\n  };\n  var escape_one = function(c) {\n    return escape_map[c];\n  };\n\n  return function (x) {\n    return x.replace(/[&<>\"'`]/g, escape_one);\n  };\n})();\n\nBlaze._warn = function (msg) {\n  msg = 'Warning: ' + msg;\n\n  if ((typeof console !== 'undefined') && console.warn) {\n    console.warn(msg);\n  }\n};\n"
  },
  {
    "path": "packages/blaze/render_tests.js",
    "content": "var toCode = BlazeTools.toJS;\n\nvar P = HTML.P;\nvar CharRef = HTML.CharRef;\nvar DIV = HTML.DIV;\nvar Comment = HTML.Comment;\nvar BR = HTML.BR;\nvar A = HTML.A;\nvar UL = HTML.UL;\nvar LI = HTML.LI;\nvar SPAN = HTML.SPAN;\nvar HR = HTML.HR;\nvar TEXTAREA = HTML.TEXTAREA;\nvar INPUT = HTML.INPUT;\n\nvar materialize = function (content, parent) {\n  var func = content;\n  if (typeof content !== 'function') {\n    func = function () {\n      return content;\n    };\n  }\n  Blaze.render(func, parent);\n};\n\nvar toHTML = Blaze.toHTML;\n\nTinytest.add(\"blaze - render - basic\", function (test) {\n  var run = function (input, expectedInnerHTML, expectedHTML, expectedCode) {\n    var div = document.createElement(\"DIV\");\n    materialize(input, div);\n    test.equal(canonicalizeHtml(div.innerHTML), expectedInnerHTML);\n    test.equal(toHTML(input), expectedHTML);\n    if (typeof expectedCode !== 'undefined')\n      test.equal(toCode(input), expectedCode);\n  };\n\n  run(P('Hello'),\n      '<p>Hello</p>',\n      '<p>Hello</p>',\n      'HTML.P(\"Hello\")');\n\n  run([], '', '', '[]');\n  run([null, null], '', '', '[null, null]');\n\n  // Test crazy character references\n\n  // `&zopf;` is \"Mathematical double-struck small z\" a.k.a. \"open-face z\"\n  run(P(CharRef({html: '&zopf;', str: '\\ud835\\udd6b'})),\n      '<p>\\ud835\\udd6b</p>',\n      '<p>&zopf;</p>',\n      'HTML.P(HTML.CharRef({html: \"&zopf;\", str: \"\\\\ud835\\\\udd6b\"}))');\n\n  run(P({id: CharRef({html: '&zopf;', str: '\\ud835\\udd6b'})}, 'Hello'),\n      '<p id=\"\\ud835\\udd6b\">Hello</p>',\n      '<p id=\"&zopf;\">Hello</p>',\n      'HTML.P({id: HTML.CharRef({html: \"&zopf;\", str: \"\\\\ud835\\\\udd6b\"})}, \"Hello\")');\n\n  run(P({id: [CharRef({html: '&zopf;', str: '\\ud835\\udd6b'}), '!']}, 'Hello'),\n      '<p id=\"\\ud835\\udd6b!\">Hello</p>',\n      '<p id=\"&zopf;!\">Hello</p>',\n      'HTML.P({id: [HTML.CharRef({html: \"&zopf;\", str: \"\\\\ud835\\\\udd6b\"}), \"!\"]}, \"Hello\")');\n\n  // Test comments\n\n  run(DIV(Comment('Test')),\n      '<div><!----></div>', // our innerHTML-canonicalization function kills comment contents\n      '<div><!--Test--></div>',\n      'HTML.DIV(HTML.Comment(\"Test\"))');\n\n  // Test arrays\n\n  run([P('Hello'), P('World')],\n      '<p>Hello</p><p>World</p>',\n      '<p>Hello</p><p>World</p>',\n      '[HTML.P(\"Hello\"), HTML.P(\"World\")]');\n\n  // Test slightly more complicated structure\n\n  run(DIV({'class': 'foo'}, UL(LI(P(A({href: '#one'}, 'One'))),\n                               LI(P('Two', BR(), 'Three')))),\n      '<div class=\"foo\"><ul><li><p><a href=\"#one\">One</a></p></li><li><p>Two<br>Three</p></li></ul></div>',\n      '<div class=\"foo\"><ul><li><p><a href=\"#one\">One</a></p></li><li><p>Two<br>Three</p></li></ul></div>',\n      'HTML.DIV({\"class\": \"foo\"}, HTML.UL(HTML.LI(HTML.P(HTML.A({href: \"#one\"}, \"One\"))), HTML.LI(HTML.P(\"Two\", HTML.BR(), \"Three\"))))');\n\n\n  // Test nully attributes\n  run(BR({x: null,\n          y: [[], []],\n          a: [['']]}),\n      '<br a=\"\">',\n      '<br a=\"\">',\n      'HTML.BR({a: [[\"\"]]})');\n\n  run(BR({\n    x: function () { return Blaze.View(function () { return Blaze.View(function () { return []; }); }); },\n    a: function () { return Blaze.View(function () { return Blaze.View(function () { return ''; }); }); }}),\n      '<br a=\"\">',\n      '<br a=\"\">');\n});\n\n// test that we correctly update the 'value' property on input fields\n// rather than the 'value' attribute. the 'value' attribute only sets\n// the initial value.\nTinytest.add(\"blaze - render - input - value\", function (test) {\n  var R = ReactiveVar(\"hello\");\n  var div = document.createElement(\"DIV\");\n  materialize(INPUT({value: function () { return R.get(); }}), div);\n  var inputEl = div.querySelector('input');\n  test.equal(inputEl.value, \"hello\");\n  inputEl.value = \"goodbye\";\n  R.set(\"hola\");\n  Tracker.flush();\n  test.equal(inputEl.value, \"hola\");\n});\n\n// test that we correctly update the 'checked' property rather than\n// the 'checked' attribute on input fields of type 'checkbox'. the\n// 'checked' attribute only sets the initial value.\nTinytest.add(\"blaze - render - input - checked\", function (test) {\n  var R = ReactiveVar(null);\n  var div = document.createElement(\"DIV\");\n  materialize(INPUT({type: \"checkbox\", checked: function () { return R.get(); }}), div);\n  var inputEl = div.querySelector('input');\n  test.equal(inputEl.checked, false);\n  inputEl.checked = true;\n\n  R.set(\"checked\");\n  Tracker.flush();\n  R.set(null);\n  Tracker.flush();\n  test.equal(inputEl.checked, false);\n});\n\nTinytest.add(\"blaze - render - textarea\", function (test) {\n  var run = function (optNode, text, html, code) {\n    if (typeof optNode === 'string') {\n      // called with args (text, html, code)\n      code = html;\n      html = text;\n      text = optNode;\n      optNode = null;\n    }\n    var div = document.createElement(\"DIV\");\n    var node = TEXTAREA({value: optNode || text});\n    materialize(node, div);\n\n    var value = div.querySelector('textarea').value;\n    value = value.replace(/\\r\\n/g, \"\\n\"); // IE8 substitutes \\n with \\r\\n\n    test.equal(value, text);\n\n    test.equal(toHTML(node), html);\n    if (typeof code === 'string')\n      test.equal(toCode(node), code);\n  };\n\n  run('Hello',\n      '<textarea>Hello</textarea>',\n      'HTML.TEXTAREA({value: \"Hello\"})');\n\n  run('\\nHello',\n      '<textarea>\\n\\nHello</textarea>',\n      'HTML.TEXTAREA({value: \"\\\\nHello\"})');\n\n  run('</textarea>',\n      '<textarea>&lt;/textarea></textarea>',\n      'HTML.TEXTAREA({value: \"</textarea>\"})');\n\n  run(CharRef({html: '&amp;', str: '&'}),\n      '&',\n      '<textarea>&amp;</textarea>',\n      'HTML.TEXTAREA({value: HTML.CharRef({html: \"&amp;\", str: \"&\"})})');\n\n  run(function () {\n    return ['a', Blaze.View(function () { return 'b'; }), 'c'];\n  },\n      'abc',\n      '<textarea>abc</textarea>');\n\n  // test that reactivity of textarea \"value\" attribute works...\n  (function () {\n    var R = ReactiveVar('one');\n    var div = document.createElement(\"DIV\");\n    var node = TEXTAREA({value: function () {\n      return Blaze.View(function () {\n        return R.get();\n      });\n    }});\n    materialize(node, div);\n    var textarea = div.querySelector('textarea');\n    test.equal(textarea.value, 'one');\n    R.set('two');\n    Tracker.flush();\n    test.equal(textarea.value, 'two');\n  })();\n\n  // ... while \"content\" reactivity simply doesn't update\n  // (but doesn't throw either)\n  (function () {\n    var R = ReactiveVar('one');\n    var div = document.createElement(\"DIV\");\n    var node = TEXTAREA([Blaze.View(function () {\n      return R.get();\n    })]);\n    materialize(node, div);\n    var textarea = div.querySelector('textarea');\n    test.equal(textarea.value, 'one');\n    R.set('two');\n    Tracker.flush({_throwFirstError: true});\n    test.equal(textarea.value, 'one');\n  })();\n});\n\nTinytest.add(\"blaze - render - view isolation\", function (test) {\n\n  // Reactively change a text node\n  (function () {\n    var R = ReactiveVar('Hello');\n    var test1 = function () {\n      return P(Blaze.View(function () { return R.get(); }));\n    };\n\n    test.equal(toHTML(test1()), '<p>Hello</p>');\n\n    var div = document.createElement(\"DIV\");\n    materialize(test1, div);\n    test.equal(canonicalizeHtml(div.innerHTML), \"<p>Hello</p>\");\n\n    R.set('World');\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"<p>World</p>\");\n  })();\n\n  // Reactively change an array of text nodes\n  (function () {\n    var R = ReactiveVar(['Hello', ' World']);\n    var test1 = function () {\n      return P(Blaze.View(function () { return R.get(); }));\n    };\n\n    test.equal(toHTML(test1()), '<p>Hello World</p>');\n\n    var div = document.createElement(\"DIV\");\n    materialize(test1, div);\n    test.equal(canonicalizeHtml(div.innerHTML), \"<p>Hello World</p>\");\n\n    R.set(['Goodbye', ' World']);\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"<p>Goodbye World</p>\");\n  })();\n\n});\n\n// IE strips malformed styles like \"bar::d\" from the `style`\n// attribute. We detect this to adjust expectations for the StyleHandler\n// test below.\nvar malformedStylesAllowed = function () {\n  var div = document.createElement(\"div\");\n  div.setAttribute(\"style\", \"bar::d;\");\n  return (div.getAttribute(\"style\") === \"bar::d;\");\n};\n\nTinytest.add(\"blaze - render - view GC\", function (test) {\n  // test that removing parent element removes listeners and stops autoruns.\n  (function () {\n    var R = ReactiveVar('Hello');\n    var test1 = P(Blaze.View(function () { return R.get(); }));\n\n    var div = document.createElement(\"DIV\");\n    materialize(test1, div);\n    test.equal(canonicalizeHtml(div.innerHTML), \"<p>Hello</p>\");\n\n    R.set('World');\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"<p>World</p>\");\n\n    test.equal(R._numListeners(), 1);\n\n    $(div).remove();\n\n    test.equal(R._numListeners(), 0);\n\n    R.set('Steve');\n    Tracker.flush();\n    // should not have changed:\n    test.equal(canonicalizeHtml(div.innerHTML), \"<p>World</p>\");\n  })();\n\n});\n\nTinytest.add(\"blaze - render - reactive attributes\", function (test) {\n  (function () {\n    var R = ReactiveVar({'class': ['david gre', CharRef({html: '&euml;', str: '\\u00eb'}), 'nspan'],\n                         id: 'foo'});\n\n    var spanFunc = function () {\n      return SPAN(HTML.Attrs(\n        function () { return R.get(); }));\n    };\n\n    test.equal(Blaze.toHTML(spanFunc()),\n               '<span class=\"david gre&euml;nspan\" id=\"foo\"></span>');\n\n    test.equal(R._numListeners(), 0);\n\n    var div = document.createElement(\"DIV\");\n    Blaze.render(spanFunc, div);\n    test.equal(canonicalizeHtml(div.innerHTML), '<span class=\"david gre\\u00ebnspan\" id=\"foo\"></span>');\n\n    test.equal(R._numListeners(), 1);\n\n    var span = div.firstChild;\n    test.equal(span.nodeName, 'SPAN');\n    span.className += ' blah'; // change the element's class outside of Blaze. this simulates what a jQuery could do\n\n    R.set({'class': 'david smith', id: 'bar'});\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), '<span class=\"david blah smith\" id=\"bar\"></span>');\n    test.equal(R._numListeners(), 1);\n\n    R.set({});\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), '<span class=\"blah\"></span>');\n    test.equal(R._numListeners(), 1);\n\n    $(div).remove();\n\n    test.equal(R._numListeners(), 0);\n  })();\n\n  // Test styles.\n  (function () {\n    // Test the case where there is a semicolon in the css attribute.\n    var R = ReactiveVar({'style': 'foo: \"a;aa\"; bar: b;',\n      id: 'foo'});\n\n    var spanFunc = function () {\n      return SPAN(HTML.Attrs(function () { return R.get(); }));\n    };\n\n    test.equal(Blaze.toHTML(spanFunc()), '<span style=\"foo: &quot;a;aa&quot;; bar: b;\" id=\"foo\"></span>');\n\n    test.equal(R._numListeners(), 0);\n\n    var div = document.createElement(\"DIV\");\n    Blaze.render(spanFunc, div);\n    test.equal(canonicalizeHtml(div.innerHTML), '<span id=\"foo\" style=\"foo: &quot;a;aa&quot;; bar: b\"></span>');\n\n    test.equal(R._numListeners(), 1);\n    var span = div.firstChild;\n    test.equal(span.nodeName, 'SPAN');\n\n    span.setAttribute('style', span.getAttribute('style') + '; jquery-style: hidden');\n\n    R.set({'style': 'foo: \"a;zz;aa\";', id: 'bar'});\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML, true), '<span id=\"bar\" style=\"foo: &quot;a;zz;aa&quot;; jquery-style: hidden\"></span>');\n    test.equal(R._numListeners(), 1);\n\n    R.set({});\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), '<span style=\"jquery-style: hidden\"></span>');\n    test.equal(R._numListeners(), 1);\n\n    $(div).remove();\n\n    test.equal(R._numListeners(), 0);\n  })();\n\n  // Test that identical styles are successfully overwritten.\n  (function () {\n\n    var R = ReactiveVar({'style': 'foo: a;'});\n\n    var spanFunc = function () {\n      return SPAN(HTML.Attrs(function () { return R.get(); }));\n    };\n\n    var div = document.createElement(\"DIV\");\n    document.body.appendChild(div);\n    Blaze.render(spanFunc, div);\n    test.equal(canonicalizeHtml(div.innerHTML), '<span style=\"foo: a\"></span>');\n\n    var span = div.firstChild;\n    test.equal(span.nodeName, 'SPAN');\n    span.setAttribute(\"style\", 'foo: b;');\n    test.equal(canonicalizeHtml(div.innerHTML), '<span style=\"foo: b\"></span>');\n\n    R.set({'style': 'foo: c;'});\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), '<span style=\"foo: c\"></span>');\n\n    // test malformed styles - different expectations in IE (which\n    // strips malformed styles) from other browsers\n    R.set({'style': 'foo: a; bar::d;:e; baz: c;'});\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML),\n      malformedStylesAllowed() ?\n               '<span style=\"foo: a; bar::d; baz: c\"></span>' :\n               '<span style=\"foo: a; baz: c\"></span>');\n\n    // Test strange styles\n    R.set({'style': ' foo: c; constructor: a; __proto__: b;'});\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), '<span style=\"foo: c; constructor: a; __proto__: b\"></span>');\n\n    R.set({});\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), '<span></span>');\n\n    R.set({'style': 'foo: bar;'});\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), '<span style=\"foo: bar\"></span>');\n  })();\n\n  // Test `null`, `undefined`, and `[]` attributes\n  (function () {\n    var R = ReactiveVar({id: 'foo',\n                         aaa: null,\n                         bbb: undefined,\n                         ccc: [],\n                         ddd: [null],\n                         eee: [undefined],\n                         fff: [[]],\n                         ggg: ['x', ['y', ['z']]]});\n\n    var spanFunc = function () {\n      return SPAN(HTML.Attrs(\n        function () { return R.get(); }));\n    };\n\n    test.equal(Blaze.toHTML(spanFunc()), '<span id=\"foo\" ggg=\"xyz\"></span>');\n    test.equal(toCode(SPAN(R.get())),\n               'HTML.SPAN({id: \"foo\", ggg: [\"x\", [\"y\", [\"z\"]]]})');\n\n    var div = document.createElement(\"DIV\");\n    Blaze.render(spanFunc, div);\n    var span = div.firstChild;\n    test.equal(span.nodeName, 'SPAN');\n\n    test.equal(canonicalizeHtml(div.innerHTML), '<span ggg=\"xyz\" id=\"foo\"></span>');\n    R.set({id: 'foo', ggg: [[], [], []]});\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), '<span id=\"foo\"></span>');\n\n    R.set({id: 'foo', ggg: null});\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), '<span id=\"foo\"></span>');\n\n    R.set({id: 'foo', ggg: ''});\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), '<span ggg=\"\" id=\"foo\"></span>');\n\n    $(div).remove();\n\n    test.equal(R._numListeners(), 0);\n  })();\n});\n\nTinytest.add(\"blaze - render - templates and views\", function (test) {\n  (function () {\n    var counter = 1;\n    var buf = [];\n\n    var myTemplate = Blaze.Template(\n      'myTemplate',\n      function () {\n        return [String(this.number),\n                (this.number < 3 ? makeView() : HR())];\n      });\n\n    myTemplate.constructView = function (number) {\n      var view = Template.prototype.constructView.call(this);\n      view.number = number;\n      return view;\n    };\n\n    myTemplate.created = function () {\n      test.isFalse(Tracker.active);\n      var view = this.view;\n      var parent = Blaze.getView(view, 'myTemplate');\n      if (parent) {\n        buf.push('parent of ' + view.number + ' is ' +\n                 parent.number);\n      }\n\n      buf.push('created ' + Template.currentData());\n    };\n\n    myTemplate.onRendered(function () {\n      test.isFalse(Tracker.active);\n      var nodeDescr = function (node) {\n        if (node.nodeType === 8) // comment\n          return '';\n        if (node.nodeType === 3) // text\n          return node.nodeValue;\n\n        return node.nodeName;\n      };\n\n      var view = this.view;\n      var start = view.firstNode();\n      var end = view.lastNode();\n      // skip marker nodes\n      while (start !== end && ! nodeDescr(start))\n        start = start.nextSibling;\n      while (end !== start && ! nodeDescr(end))\n        end = end.previousSibling;\n\n      buf.push('dom-' + Template.currentData() +\n               ' is ' + nodeDescr(start) +'..' +\n               nodeDescr(end));\n    });\n\n    myTemplate.onDestroyed(function () {\n      test.isFalse(Tracker.active);\n      buf.push('destroyed ' + Template.currentData());\n    });\n\n    var makeView = function () {\n      var number = counter++;\n      return Blaze.With(number, function () {\n        return myTemplate.constructView(number);\n      });\n    };\n\n    var div = document.createElement(\"DIV\");\n\n    Blaze.render(makeView, div);\n    buf.push('---flush---');\n    Tracker.flush();\n    test.equal(buf, ['created 1',\n                     'parent of 2 is 1',\n                     'created 2',\n                     'parent of 3 is 2',\n                     'created 3',\n                     '---flush---',\n                     // (proper order for these has not be thought out:)\n                     'dom-3 is 3..HR',\n                     'dom-2 is 2..HR',\n                     'dom-1 is 1..HR']);\n\n    test.equal(canonicalizeHtml(div.innerHTML), '123<hr>');\n\n    buf.length = 0;\n    $(div).remove();\n    buf.sort();\n    test.equal(buf, ['destroyed 1', 'destroyed 2', 'destroyed 3']);\n\n    // Now use toHTML.  Should still get most of the callbacks (not `rendered`).\n\n    buf.length = 0;\n    counter = 1;\n\n    var html = Blaze.toHTML(makeView());\n\n    test.equal(buf, ['created 1',\n                     'parent of 2 is 1',\n                     'created 2',\n                     'parent of 3 is 2',\n                     'created 3',\n                     'destroyed 3',\n                     'destroyed 2',\n                     'destroyed 1']);\n\n    test.equal(html, '123<hr>');\n  })();\n});\n\nTinytest.add(\"blaze - render - findAll\", function (test) {\n  var found = null;\n  var $found = null;\n\n  var myTemplate = new Template(\n    'findAllTest',\n    function() {\n      return DIV([P('first'), P('second')]);\n    });\n  myTemplate.rendered = function() {\n    found = this.findAll('p');\n    $found = this.$('p');\n  };\n\n  var div = document.createElement(\"DIV\");\n\n  Blaze.render(myTemplate, div);\n  Tracker.flush();\n\n  test.equal(_.isArray(found), true);\n  test.equal(_.isArray($found), false);\n  test.equal(found.length, 2);\n  test.equal($found.length, 2);\n});\n\nTinytest.add(\"blaze - render - reactive attributes 2\", function (test) {\n  var R1 = ReactiveVar(['foo']);\n  var R2 = ReactiveVar(['bar']);\n\n  var spanFunc = function () {\n    return SPAN(HTML.Attrs(\n      { blah: function () { return R1.get(); } },\n      function () { return { blah: R2.get() }; }));\n  };\n\n  var div = document.createElement(\"DIV\");\n  Blaze.render(spanFunc, div);\n  var check = function (expected) {\n    test.equal(Blaze.toHTML(spanFunc()), expected);\n    test.equal(canonicalizeHtml(div.innerHTML), expected);\n  };\n  check('<span blah=\"bar\"></span>');\n\n  test.equal(R1._numListeners(), 1);\n  test.equal(R2._numListeners(), 1);\n\n  R2.set([[]]);\n  Tracker.flush();\n  // We combine `['foo']` with what evaluates to `[[[]]]`, which is nully.\n  check('<span blah=\"foo\"></span>');\n\n  R2.set([['']]);\n  Tracker.flush();\n  // We combine `['foo']` with what evaluates to `[[['']]]`, which is non-nully.\n  check('<span blah=\"\"></span>');\n\n  R2.set(null);\n  Tracker.flush();\n  // We combine `['foo']` with `[null]`, which is nully.\n  check('<span blah=\"foo\"></span>');\n\n  R1.set([[], []]);\n  Tracker.flush();\n  // We combine two nully values.\n  check('<span></span>');\n\n  R1.set([[], ['foo']]);\n  Tracker.flush();\n  check('<span blah=\"foo\"></span>');\n\n  // clean up\n\n  $(div).remove();\n\n  test.equal(R1._numListeners(), 0);\n  test.equal(R2._numListeners(), 0);\n});\n\nTinytest.add(\"blaze - render - SVG\", function (test) {\n  if (! document.createElementNS) {\n    // IE 8\n    return;\n  }\n\n  var fillColor = ReactiveVar('red');\n  var classes = ReactiveVar('one two');\n\n  var content = DIV({'class': 'container'}, HTML.SVG(\n    {width: 100, height: 100},\n    HTML.CIRCLE({cx: 50, cy: 50, r: 40,\n                 stroke: 'black', 'stroke-width': 3,\n                 'class': function () { return classes.get(); },\n                 fill: function () { return fillColor.get(); }})));\n\n  var div = document.createElement(\"DIV\");\n  materialize(content, div);\n\n  var circle = div.querySelector('.container > svg > circle');\n  test.equal(circle.getAttribute('fill'), 'red');\n  test.equal(circle.className.baseVal, 'one two');\n\n  fillColor.set('green');\n  classes.set('two three');\n  Tracker.flush();\n  test.equal(circle.getAttribute('fill'), 'green');\n  test.equal(circle.className.baseVal, 'two three');\n\n  test.equal(circle.nodeName, 'circle');\n  test.equal(circle.namespaceURI, \"http://www.w3.org/2000/svg\");\n  test.equal(circle.parentNode.namespaceURI, \"http://www.w3.org/2000/svg\");\n});\n\nTinytest.add(\"ui - attributes\", function (test) {\n  var SPAN = HTML.SPAN;\n  var amp = HTML.CharRef({html: '&amp;', str: '&'});\n\n  test.equal(HTML.toHTML(SPAN({title: ['M', amp, 'Ms']}, 'M', amp, 'M candies')),\n             '<span title=\"M&amp;Ms\">M&amp;M candies</span>');\n});\n"
  },
  {
    "path": "packages/blaze/template.js",
    "content": "// [new] Blaze.Template([viewName], renderFunction)\n//\n// `Blaze.Template` is the class of templates, like `Template.foo` in\n// Meteor, which is `instanceof Template`.\n//\n// `viewKind` is a string that looks like \"Template.foo\" for templates\n// defined by the compiler.\n\n/**\n * @class\n * @summary Constructor for a Template, which is used to construct Views with particular name and content.\n * @locus Client\n * @param {String} [viewName] Optional.  A name for Views constructed by this Template.  See [`view.name`](#view_name).\n * @param {Function} renderFunction A function that returns [*renderable content*](#renderable_content).  This function is used as the `renderFunction` for Views constructed by this Template.\n */\nBlaze.Template = function (viewName, renderFunction) {\n  if (! (this instanceof Blaze.Template))\n    // called without `new`\n    return new Blaze.Template(viewName, renderFunction);\n\n  if (typeof viewName === 'function') {\n    // omitted \"viewName\" argument\n    renderFunction = viewName;\n    viewName = '';\n  }\n  if (typeof viewName !== 'string')\n    throw new Error(\"viewName must be a String (or omitted)\");\n  if (typeof renderFunction !== 'function')\n    throw new Error(\"renderFunction must be a function\");\n\n  this.viewName = viewName;\n  this.renderFunction = renderFunction;\n\n  this.__helpers = new HelperMap;\n  this.__eventMaps = [];\n\n  this._callbacks = {\n    created: [],\n    rendered: [],\n    destroyed: []\n  };\n};\nvar Template = Blaze.Template;\n\nvar HelperMap = function () {};\nHelperMap.prototype.get = function (name) {\n  return this[' '+name];\n};\nHelperMap.prototype.set = function (name, helper) {\n  this[' '+name] = helper;\n};\nHelperMap.prototype.has = function (name) {\n  return (' '+name) in this;\n};\n\n/**\n * @summary Returns true if `value` is a template object like `Template.myTemplate`.\n * @locus Client\n * @param {Any} value The value to test.\n */\nBlaze.isTemplate = function (t) {\n  return (t instanceof Blaze.Template);\n};\n\n/**\n * @name  onCreated\n * @instance\n * @memberOf Template\n * @summary Register a function to be called when an instance of this template is created.\n * @param {Function} callback A function to be added as a callback.\n * @locus Client\n * @importFromPackage templating\n */\nTemplate.prototype.onCreated = function (cb) {\n  this._callbacks.created.push(cb);\n};\n\n/**\n * @name  onRendered\n * @instance\n * @memberOf Template\n * @summary Register a function to be called when an instance of this template is inserted into the DOM.\n * @param {Function} callback A function to be added as a callback.\n * @locus Client\n * @importFromPackage templating\n */\nTemplate.prototype.onRendered = function (cb) {\n  this._callbacks.rendered.push(cb);\n};\n\n/**\n * @name  onDestroyed\n * @instance\n * @memberOf Template\n * @summary Register a function to be called when an instance of this template is removed from the DOM and destroyed.\n * @param {Function} callback A function to be added as a callback.\n * @locus Client\n * @importFromPackage templating\n */\nTemplate.prototype.onDestroyed = function (cb) {\n  this._callbacks.destroyed.push(cb);\n};\n\nTemplate.prototype._getCallbacks = function (which) {\n  var self = this;\n  var callbacks = self[which] ? [self[which]] : [];\n  // Fire all callbacks added with the new API (Template.onRendered())\n  // as well as the old-style callback (e.g. Template.rendered) for\n  // backwards-compatibility.\n  callbacks = callbacks.concat(self._callbacks[which]);\n  return callbacks;\n};\n\nvar fireCallbacks = function (callbacks, template) {\n  Template._withTemplateInstanceFunc(\n    function () { return template; },\n    function () {\n      for (var i = 0, N = callbacks.length; i < N; i++) {\n        callbacks[i].call(template);\n      }\n    });\n};\n\nTemplate.prototype.constructView = function (contentFunc, elseFunc) {\n  var self = this;\n  var view = Blaze.View(self.viewName, self.renderFunction);\n  view.template = self;\n\n  view.templateContentBlock = (\n    contentFunc ? new Template('(contentBlock)', contentFunc) : null);\n  view.templateElseBlock = (\n    elseFunc ? new Template('(elseBlock)', elseFunc) : null);\n\n  if (self.__eventMaps || typeof self.events === 'object') {\n    view._onViewRendered(function () {\n      if (view.renderCount !== 1)\n        return;\n\n      if (! self.__eventMaps.length && typeof self.events === \"object\") {\n        // Provide limited back-compat support for `.events = {...}`\n        // syntax.  Pass `template.events` to the original `.events(...)`\n        // function.  This code must run only once per template, in\n        // order to not bind the handlers more than once, which is\n        // ensured by the fact that we only do this when `__eventMaps`\n        // is falsy, and we cause it to be set now.\n        Template.prototype.events.call(self, self.events);\n      }\n\n      _.each(self.__eventMaps, function (m) {\n        Blaze._addEventMap(view, m, view);\n      });\n    });\n  }\n\n  view._templateInstance = new Blaze.TemplateInstance(view);\n  view.templateInstance = function () {\n    // Update data, firstNode, and lastNode, and return the TemplateInstance\n    // object.\n    var inst = view._templateInstance;\n\n    /**\n     * @instance\n     * @memberOf Blaze.TemplateInstance\n     * @name  data\n     * @summary The data context of this instance's latest invocation.\n     * @locus Client\n     */\n    inst.data = Blaze.getData(view);\n\n    if (view._domrange && !view.isDestroyed) {\n      inst.firstNode = view._domrange.firstNode();\n      inst.lastNode = view._domrange.lastNode();\n    } else {\n      // on 'created' or 'destroyed' callbacks we don't have a DomRange\n      inst.firstNode = null;\n      inst.lastNode = null;\n    }\n\n    return inst;\n  };\n\n  /**\n   * @name  created\n   * @instance\n   * @memberOf Template\n   * @summary Provide a callback when an instance of a template is created.\n   * @locus Client\n   * @deprecated in 1.1\n   */\n  // To avoid situations when new callbacks are added in between view\n  // instantiation and event being fired, decide on all callbacks to fire\n  // immediately and then fire them on the event.\n  var createdCallbacks = self._getCallbacks('created');\n  view.onViewCreated(function () {\n    fireCallbacks(createdCallbacks, view.templateInstance());\n  });\n\n  /**\n   * @name  rendered\n   * @instance\n   * @memberOf Template\n   * @summary Provide a callback when an instance of a template is rendered.\n   * @locus Client\n   * @deprecated in 1.1\n   */\n  var renderedCallbacks = self._getCallbacks('rendered');\n  view.onViewReady(function () {\n    fireCallbacks(renderedCallbacks, view.templateInstance());\n  });\n\n  /**\n   * @name  destroyed\n   * @instance\n   * @memberOf Template\n   * @summary Provide a callback when an instance of a template is destroyed.\n   * @locus Client\n   * @deprecated in 1.1\n   */\n  var destroyedCallbacks = self._getCallbacks('destroyed');\n  view.onViewDestroyed(function () {\n    fireCallbacks(destroyedCallbacks, view.templateInstance());\n  });\n\n  return view;\n};\n\n/**\n * @class\n * @summary The class for template instances\n * @param {Blaze.View} view\n * @instanceName template\n */\nBlaze.TemplateInstance = function (view) {\n  if (! (this instanceof Blaze.TemplateInstance))\n    // called without `new`\n    return new Blaze.TemplateInstance(view);\n\n  if (! (view instanceof Blaze.View))\n    throw new Error(\"View required\");\n\n  view._templateInstance = this;\n\n  /**\n   * @name view\n   * @memberOf Blaze.TemplateInstance\n   * @instance\n   * @summary The [View](#blaze_view) object for this invocation of the template.\n   * @locus Client\n   * @type {Blaze.View}\n   */\n  this.view = view;\n  this.data = null;\n\n  /**\n   * @name firstNode\n   * @memberOf Blaze.TemplateInstance\n   * @instance\n   * @summary The first top-level DOM node in this template instance.\n   * @locus Client\n   * @type {DOMNode}\n   */\n  this.firstNode = null;\n\n  /**\n   * @name lastNode\n   * @memberOf Blaze.TemplateInstance\n   * @instance\n   * @summary The last top-level DOM node in this template instance.\n   * @locus Client\n   * @type {DOMNode}\n   */\n  this.lastNode = null;\n\n  // This dependency is used to identify state transitions in\n  // _subscriptionHandles which could cause the result of\n  // TemplateInstance#subscriptionsReady to change. Basically this is triggered\n  // whenever a new subscription handle is added or when a subscription handle\n  // is removed and they are not ready.\n  this._allSubsReadyDep = new Tracker.Dependency();\n  this._allSubsReady = false;\n\n  this._subscriptionHandles = {};\n};\n\n/**\n * @summary Find all elements matching `selector` in this template instance, and return them as a JQuery object.\n * @locus Client\n * @param {String} selector The CSS selector to match, scoped to the template contents.\n * @returns {DOMNode[]}\n */\nBlaze.TemplateInstance.prototype.$ = function (selector) {\n  var view = this.view;\n  if (! view._domrange)\n    throw new Error(\"Can't use $ on template instance with no DOM\");\n  return view._domrange.$(selector);\n};\n\n/**\n * @summary Find all elements matching `selector` in this template instance.\n * @locus Client\n * @param {String} selector The CSS selector to match, scoped to the template contents.\n * @returns {DOMElement[]}\n */\nBlaze.TemplateInstance.prototype.findAll = function (selector) {\n  return Array.prototype.slice.call(this.$(selector));\n};\n\n/**\n * @summary Find one element matching `selector` in this template instance.\n * @locus Client\n * @param {String} selector The CSS selector to match, scoped to the template contents.\n * @returns {DOMElement}\n */\nBlaze.TemplateInstance.prototype.find = function (selector) {\n  var result = this.$(selector);\n  return result[0] || null;\n};\n\n/**\n * @summary A version of [Tracker.autorun](#tracker_autorun) that is stopped when the template is destroyed.\n * @locus Client\n * @param {Function} runFunc The function to run. It receives one argument: a Tracker.Computation object.\n */\nBlaze.TemplateInstance.prototype.autorun = function (f) {\n  return this.view.autorun(f);\n};\n\n/**\n * @summary A version of [Meteor.subscribe](#meteor_subscribe) that is stopped\n * when the template is destroyed.\n * @return {SubscriptionHandle} The subscription handle to the newly made\n * subscription. Call `handle.stop()` to manually stop the subscription, or\n * `handle.ready()` to find out if this particular subscription has loaded all\n * of its inital data.\n * @locus Client\n * @param {String} name Name of the subscription.  Matches the name of the\n * server's `publish()` call.\n * @param {Any} [arg1,arg2...] Optional arguments passed to publisher function\n * on server.\n * @param {Function|Object} [options] If a function is passed instead of an\n * object, it is interpreted as an `onReady` callback.\n * @param {Function} [options.onReady] Passed to [`Meteor.subscribe`](#meteor_subscribe).\n * @param {Function} [options.onStop] Passed to [`Meteor.subscribe`](#meteor_subscribe).\n * @param {DDP.Connection} [options.connection] The connection on which to make the\n * subscription.\n */\nBlaze.TemplateInstance.prototype.subscribe = function (/* arguments */) {\n  var self = this;\n\n  var subHandles = self._subscriptionHandles;\n  var args = _.toArray(arguments);\n\n  // Duplicate logic from Meteor.subscribe\n  var options = {};\n  if (args.length) {\n    var lastParam = _.last(args);\n\n    // Match pattern to check if the last arg is an options argument\n    var lastParamOptionsPattern = {\n      onReady: Match.Optional(Function),\n      // XXX COMPAT WITH 1.0.3.1 onError used to exist, but now we use\n      // onStop with an error callback instead.\n      onError: Match.Optional(Function),\n      onStop: Match.Optional(Function),\n      connection: Match.Optional(Match.Any)\n    };\n\n    if (_.isFunction(lastParam)) {\n      options.onReady = args.pop();\n    } else if (lastParam && ! _.isEmpty(lastParam) && Match.test(lastParam, lastParamOptionsPattern)) {\n      options = args.pop();\n    }\n  }\n\n  var subHandle;\n  var oldStopped = options.onStop;\n  options.onStop = function (error) {\n    // When the subscription is stopped, remove it from the set of tracked\n    // subscriptions to avoid this list growing without bound\n    delete subHandles[subHandle.subscriptionId];\n\n    // Removing a subscription can only change the result of subscriptionsReady\n    // if we are not ready (that subscription could be the one blocking us being\n    // ready).\n    if (! self._allSubsReady) {\n      self._allSubsReadyDep.changed();\n    }\n\n    if (oldStopped) {\n      oldStopped(error);\n    }\n  };\n\n  var connection = options.connection;\n  var callbacks = _.pick(options, [\"onReady\", \"onError\", \"onStop\"]);\n\n  // The callbacks are passed as the last item in the arguments array passed to\n  // View#subscribe\n  args.push(callbacks);\n\n  // View#subscribe takes the connection as one of the options in the last\n  // argument\n  subHandle = self.view.subscribe.call(self.view, args, {\n    connection: connection\n  });\n\n  if (! _.has(subHandles, subHandle.subscriptionId)) {\n    subHandles[subHandle.subscriptionId] = subHandle;\n\n    // Adding a new subscription will always cause us to transition from ready\n    // to not ready, but if we are already not ready then this can't make us\n    // ready.\n    if (self._allSubsReady) {\n      self._allSubsReadyDep.changed();\n    }\n  }\n\n  return subHandle;\n};\n\n/**\n * @summary A reactive function that returns true when all of the subscriptions\n * called with [this.subscribe](#TemplateInstance-subscribe) are ready.\n * @return {Boolean} True if all subscriptions on this template instance are\n * ready.\n */\nBlaze.TemplateInstance.prototype.subscriptionsReady = function () {\n  this._allSubsReadyDep.depend();\n\n  this._allSubsReady = _.all(this._subscriptionHandles, function (handle) {\n    return handle.ready();\n  });\n\n  return this._allSubsReady;\n};\n\n/**\n * @summary Specify template helpers available to this template.\n * @locus Client\n * @param {Object} helpers Dictionary of helper functions by name.\n * @importFromPackage templating\n */\nTemplate.prototype.helpers = function (dict) {\n  if (! _.isObject(dict)) {\n    throw new Error(\"Helpers dictionary has to be an object\");\n  }\n\n  for (var k in dict)\n    this.__helpers.set(k, dict[k]);\n};\n\n// Kind of like Blaze.currentView but for the template instance.\n// This is a function, not a value -- so that not all helpers\n// are implicitly dependent on the current template instance's `data` property,\n// which would make them dependenct on the data context of the template\n// inclusion.\nTemplate._currentTemplateInstanceFunc = null;\n\nTemplate._withTemplateInstanceFunc = function (templateInstanceFunc, func) {\n  if (typeof func !== 'function')\n    throw new Error(\"Expected function, got: \" + func);\n  var oldTmplInstanceFunc = Template._currentTemplateInstanceFunc;\n  try {\n    Template._currentTemplateInstanceFunc = templateInstanceFunc;\n    return func();\n  } finally {\n    Template._currentTemplateInstanceFunc = oldTmplInstanceFunc;\n  }\n};\n\n/**\n * @summary Specify event handlers for this template.\n * @locus Client\n * @param {EventMap} eventMap Event handlers to associate with this template.\n * @importFromPackage templating\n */\nTemplate.prototype.events = function (eventMap) {\n  if (! _.isObject(eventMap)) {\n    throw new Error(\"Event map has to be an object\");\n  }\n\n  var template = this;\n  var eventMap2 = {};\n  for (var k in eventMap) {\n    eventMap2[k] = (function (k, v) {\n      return function (event/*, ...*/) {\n        var view = this; // passed by EventAugmenter\n        var data = Blaze.getData(event.currentTarget);\n        if (data == null)\n          data = {};\n        var args = Array.prototype.slice.call(arguments);\n        var tmplInstanceFunc = _.bind(view.templateInstance, view);\n        args.splice(1, 0, tmplInstanceFunc());\n\n        return Template._withTemplateInstanceFunc(tmplInstanceFunc, function () {\n          return v.apply(data, args);\n        });\n      };\n    })(k, eventMap[k]);\n  }\n\n  template.__eventMaps.push(eventMap2);\n};\n\n/**\n * @function\n * @name instance\n * @memberOf Template\n * @summary The [template instance](#template_inst) corresponding to the current template helper, event handler, callback, or autorun.  If there isn't one, `null`.\n * @locus Client\n * @returns {Blaze.TemplateInstance}\n * @importFromPackage templating\n */\nTemplate.instance = function () {\n  return Template._currentTemplateInstanceFunc\n    && Template._currentTemplateInstanceFunc();\n};\n\n// Note: Template.currentData() is documented to take zero arguments,\n// while Blaze.getData takes up to one.\n\n/**\n * @summary\n *\n * - Inside an `onCreated`, `onRendered`, or `onDestroyed` callback, returns\n * the data context of the template.\n * - Inside an event handler, returns the data context of the template on which\n * this event handler was defined.\n * - Inside a helper, returns the data context of the DOM node where the helper\n * was used.\n *\n * Establishes a reactive dependency on the result.\n * @locus Client\n * @function\n * @importFromPackage templating\n */\nTemplate.currentData = Blaze.getData;\n\n/**\n * @summary Accesses other data contexts that enclose the current data context.\n * @locus Client\n * @function\n * @param {Integer} [numLevels] The number of levels beyond the current data context to look. Defaults to 1.\n * @importFromPackage templating\n */\nTemplate.parentData = Blaze._parentData;\n\n/**\n * @summary Defines a [helper function](#template_helpers) which can be used from all templates.\n * @locus Client\n * @function\n * @param {String} name The name of the helper function you are defining.\n * @param {Function} function The helper function itself.\n * @importFromPackage templating\n */\nTemplate.registerHelper = Blaze.registerHelper;\n\n/**\n * @summary Removes a global [helper function](#template_helpers).\n * @locus Client\n * @function\n * @param {String} name The name of the helper function you are defining.\n * @importFromPackage templating\n */\nTemplate.deregisterHelper = Blaze.deregisterHelper;\n"
  },
  {
    "path": "packages/blaze/view.js",
    "content": "/// [new] Blaze.View([name], renderMethod)\n///\n/// Blaze.View is the building block of reactive DOM.  Views have\n/// the following features:\n///\n/// * lifecycle callbacks - Views are created, rendered, and destroyed,\n///   and callbacks can be registered to fire when these things happen.\n///\n/// * parent pointer - A View points to its parentView, which is the\n///   View that caused it to be rendered.  These pointers form a\n///   hierarchy or tree of Views.\n///\n/// * render() method - A View's render() method specifies the DOM\n///   (or HTML) content of the View.  If the method establishes\n///   reactive dependencies, it may be re-run.\n///\n/// * a DOMRange - If a View is rendered to DOM, its position and\n///   extent in the DOM are tracked using a DOMRange object.\n///\n/// When a View is constructed by calling Blaze.View, the View is\n/// not yet considered \"created.\"  It doesn't have a parentView yet,\n/// and no logic has been run to initialize the View.  All real\n/// work is deferred until at least creation time, when the onViewCreated\n/// callbacks are fired, which happens when the View is \"used\" in\n/// some way that requires it to be rendered.\n///\n/// ...more lifecycle stuff\n///\n/// `name` is an optional string tag identifying the View.  The only\n/// time it's used is when looking in the View tree for a View of a\n/// particular name; for example, data contexts are stored on Views\n/// of name \"with\".  Names are also useful when debugging, so in\n/// general it's good for functions that create Views to set the name.\n/// Views associated with templates have names of the form \"Template.foo\".\n\n/**\n * @class\n * @summary Constructor for a View, which represents a reactive region of DOM.\n * @locus Client\n * @param {String} [name] Optional.  A name for this type of View.  See [`view.name`](#view_name).\n * @param {Function} renderFunction A function that returns [*renderable content*](#renderable_content).  In this function, `this` is bound to the View.\n */\nBlaze.View = function (name, render) {\n  if (! (this instanceof Blaze.View))\n    // called without `new`\n    return new Blaze.View(name, render);\n\n  if (typeof name === 'function') {\n    // omitted \"name\" argument\n    render = name;\n    name = '';\n  }\n  this.name = name;\n  this._render = render;\n\n  this._callbacks = {\n    created: null,\n    rendered: null,\n    destroyed: null\n  };\n\n  // Setting all properties here is good for readability,\n  // and also may help Chrome optimize the code by keeping\n  // the View object from changing shape too much.\n  this.isCreated = false;\n  this._isCreatedForExpansion = false;\n  this.isRendered = false;\n  this._isAttached = false;\n  this.isDestroyed = false;\n  this._isInRender = false;\n  this.parentView = null;\n  this._domrange = null;\n  // This flag is normally set to false except for the cases when view's parent\n  // was generated as part of expanding some syntactic sugar expressions or\n  // methods.\n  // Ex.: Blaze.renderWithData is an equivalent to creating a view with regular\n  // Blaze.render and wrapping it into {{#with data}}{{/with}} view. Since the\n  // users don't know anything about these generated parent views, Blaze needs\n  // this information to be available on views to make smarter decisions. For\n  // example: removing the generated parent view with the view on Blaze.remove.\n  this._hasGeneratedParent = false;\n  // Bindings accessible to children views (via view.lookup('name')) within the\n  // closest template view.\n  this._scopeBindings = {};\n\n  this.renderCount = 0;\n};\n\nBlaze.View.prototype._render = function () { return null; };\n\nBlaze.View.prototype.onViewCreated = function (cb) {\n  this._callbacks.created = this._callbacks.created || [];\n  this._callbacks.created.push(cb);\n};\n\nBlaze.View.prototype._onViewRendered = function (cb) {\n  this._callbacks.rendered = this._callbacks.rendered || [];\n  this._callbacks.rendered.push(cb);\n};\n\nBlaze.View.prototype.onViewReady = function (cb) {\n  var self = this;\n  var fire = function () {\n    Tracker.afterFlush(function () {\n      if (! self.isDestroyed) {\n        Blaze._withCurrentView(self, function () {\n          cb.call(self);\n        });\n      }\n    });\n  };\n  self._onViewRendered(function onViewRendered() {\n    if (self.isDestroyed)\n      return;\n    if (! self._domrange.attached)\n      self._domrange.onAttached(fire);\n    else\n      fire();\n  });\n};\n\nBlaze.View.prototype.onViewDestroyed = function (cb) {\n  this._callbacks.destroyed = this._callbacks.destroyed || [];\n  this._callbacks.destroyed.push(cb);\n};\nBlaze.View.prototype.removeViewDestroyedListener = function (cb) {\n  var destroyed = this._callbacks.destroyed;\n  if (! destroyed)\n    return;\n  var index = _.lastIndexOf(destroyed, cb);\n  if (index !== -1) {\n    // XXX You'd think the right thing to do would be splice, but _fireCallbacks\n    // gets sad if you remove callbacks while iterating over the list.  Should\n    // change this to use callback-hook or EventEmitter or something else that\n    // properly supports removal.\n    destroyed[index] = null;\n  }\n};\n\n/// View#autorun(func)\n///\n/// Sets up a Tracker autorun that is \"scoped\" to this View in two\n/// important ways: 1) Blaze.currentView is automatically set\n/// on every re-run, and 2) the autorun is stopped when the\n/// View is destroyed.  As with Tracker.autorun, the first run of\n/// the function is immediate, and a Computation object that can\n/// be used to stop the autorun is returned.\n///\n/// View#autorun is meant to be called from View callbacks like\n/// onViewCreated, or from outside the rendering process.  It may not\n/// be called before the onViewCreated callbacks are fired (too early),\n/// or from a render() method (too confusing).\n///\n/// Typically, autoruns that update the state\n/// of the View (as in Blaze.With) should be started from an onViewCreated\n/// callback.  Autoruns that update the DOM should be started\n/// from either onViewCreated (guarded against the absence of\n/// view._domrange), or onViewReady.\nBlaze.View.prototype.autorun = function (f, _inViewScope, displayName) {\n  var self = this;\n\n  // The restrictions on when View#autorun can be called are in order\n  // to avoid bad patterns, like creating a Blaze.View and immediately\n  // calling autorun on it.  A freshly created View is not ready to\n  // have logic run on it; it doesn't have a parentView, for example.\n  // It's when the View is materialized or expanded that the onViewCreated\n  // handlers are fired and the View starts up.\n  //\n  // Letting the render() method call `this.autorun()` is problematic\n  // because of re-render.  The best we can do is to stop the old\n  // autorun and start a new one for each render, but that's a pattern\n  // we try to avoid internally because it leads to helpers being\n  // called extra times, in the case where the autorun causes the\n  // view to re-render (and thus the autorun to be torn down and a\n  // new one established).\n  //\n  // We could lift these restrictions in various ways.  One interesting\n  // idea is to allow you to call `view.autorun` after instantiating\n  // `view`, and automatically wrap it in `view.onViewCreated`, deferring\n  // the autorun so that it starts at an appropriate time.  However,\n  // then we can't return the Computation object to the caller, because\n  // it doesn't exist yet.\n  if (! self.isCreated) {\n    throw new Error(\"View#autorun must be called from the created callback at the earliest\");\n  }\n  if (this._isInRender) {\n    throw new Error(\"Can't call View#autorun from inside render(); try calling it from the created or rendered callback\");\n  }\n  if (Tracker.active) {\n    throw new Error(\"Can't call View#autorun from a Tracker Computation; try calling it from the created or rendered callback\");\n  }\n\n  var templateInstanceFunc = Blaze.Template._currentTemplateInstanceFunc;\n\n  var func = function viewAutorun(c) {\n    return Blaze._withCurrentView(_inViewScope || self, function () {\n      return Blaze.Template._withTemplateInstanceFunc(\n        templateInstanceFunc, function () {\n          return f.call(self, c);\n        });\n    });\n  };\n\n  // Give the autorun function a better name for debugging and profiling.\n  // The `displayName` property is not part of the spec but browsers like Chrome\n  // and Firefox prefer it in debuggers over the name function was declared by.\n  func.displayName =\n    (self.name || 'anonymous') + ':' + (displayName || 'anonymous');\n  var comp = Tracker.autorun(func);\n\n  var stopComputation = function () { comp.stop(); };\n  self.onViewDestroyed(stopComputation);\n  comp.onStop(function () {\n    self.removeViewDestroyedListener(stopComputation);\n  });\n\n  return comp;\n};\n\nBlaze.View.prototype._errorIfShouldntCallSubscribe = function () {\n  var self = this;\n\n  if (! self.isCreated) {\n    throw new Error(\"View#subscribe must be called from the created callback at the earliest\");\n  }\n  if (self._isInRender) {\n    throw new Error(\"Can't call View#subscribe from inside render(); try calling it from the created or rendered callback\");\n  }\n  if (self.isDestroyed) {\n    throw new Error(\"Can't call View#subscribe from inside the destroyed callback, try calling it inside created or rendered.\");\n  }\n};\n\n/**\n * Just like Blaze.View#autorun, but with Meteor.subscribe instead of\n * Tracker.autorun. Stop the subscription when the view is destroyed.\n * @return {SubscriptionHandle} A handle to the subscription so that you can\n * see if it is ready, or stop it manually\n */\nBlaze.View.prototype.subscribe = function (args, options) {\n  var self = this;\n  options = options || {};\n\n  self._errorIfShouldntCallSubscribe();\n\n  var subHandle;\n  if (options.connection) {\n    subHandle = options.connection.subscribe.apply(options.connection, args);\n  } else {\n    subHandle = Meteor.subscribe.apply(Meteor, args);\n  }\n\n  self.onViewDestroyed(function () {\n    subHandle.stop();\n  });\n\n  return subHandle;\n};\n\nBlaze.View.prototype.firstNode = function () {\n  if (! this._isAttached)\n    throw new Error(\"View must be attached before accessing its DOM\");\n\n  return this._domrange.firstNode();\n};\n\nBlaze.View.prototype.lastNode = function () {\n  if (! this._isAttached)\n    throw new Error(\"View must be attached before accessing its DOM\");\n\n  return this._domrange.lastNode();\n};\n\nBlaze._fireCallbacks = function (view, which) {\n  Blaze._withCurrentView(view, function () {\n    Tracker.nonreactive(function fireCallbacks() {\n      var cbs = view._callbacks[which];\n      for (var i = 0, N = (cbs && cbs.length); i < N; i++)\n        cbs[i] && cbs[i].call(view);\n    });\n  });\n};\n\nBlaze._createView = function (view, parentView, forExpansion) {\n  if (view.isCreated)\n    throw new Error(\"Can't render the same View twice\");\n\n  view.parentView = (parentView || null);\n  view.isCreated = true;\n  if (forExpansion)\n    view._isCreatedForExpansion = true;\n\n  Blaze._fireCallbacks(view, 'created');\n};\n\nvar doFirstRender = function (view, initialContent) {\n  var domrange = new Blaze._DOMRange(initialContent);\n  view._domrange = domrange;\n  domrange.view = view;\n  view.isRendered = true;\n  Blaze._fireCallbacks(view, 'rendered');\n\n  var teardownHook = null;\n\n  domrange.onAttached(function attached(range, element) {\n    view._isAttached = true;\n\n    teardownHook = Blaze._DOMBackend.Teardown.onElementTeardown(\n      element, function teardown() {\n        Blaze._destroyView(view, true /* _skipNodes */);\n      });\n  });\n\n  // tear down the teardown hook\n  view.onViewDestroyed(function () {\n    teardownHook && teardownHook.stop();\n    teardownHook = null;\n  });\n\n  return domrange;\n};\n\n// Take an uncreated View `view` and create and render it to DOM,\n// setting up the autorun that updates the View.  Returns a new\n// DOMRange, which has been associated with the View.\n//\n// The private arguments `_workStack` and `_intoArray` are passed in\n// by Blaze._materializeDOM and are only present for recursive calls\n// (when there is some other _materializeView on the stack).  If\n// provided, then we avoid the mutual recursion of calling back into\n// Blaze._materializeDOM so that deep View hierarchies don't blow the\n// stack.  Instead, we push tasks onto workStack for the initial\n// rendering and subsequent setup of the View, and they are done after\n// we return.  When there is a _workStack, we do not return the new\n// DOMRange, but instead push it into _intoArray from a _workStack\n// task.\nBlaze._materializeView = function (view, parentView, _workStack, _intoArray) {\n  Blaze._createView(view, parentView);\n\n  var domrange;\n  var lastHtmljs;\n  // We don't expect to be called in a Computation, but just in case,\n  // wrap in Tracker.nonreactive.\n  Tracker.nonreactive(function () {\n    view.autorun(function doRender(c) {\n      // `view.autorun` sets the current view.\n      view.renderCount++;\n      view._isInRender = true;\n      // Any dependencies that should invalidate this Computation come\n      // from this line:\n      var htmljs = view._render();\n      view._isInRender = false;\n\n      if (! c.firstRun) {\n        Tracker.nonreactive(function doMaterialize() {\n          // re-render\n          var rangesAndNodes = Blaze._materializeDOM(htmljs, [], view);\n          if (! Blaze._isContentEqual(lastHtmljs, htmljs)) {\n            domrange.setMembers(rangesAndNodes);\n            Blaze._fireCallbacks(view, 'rendered');\n          }\n        });\n      }\n      lastHtmljs = htmljs;\n\n      // Causes any nested views to stop immediately, not when we call\n      // `setMembers` the next time around the autorun.  Otherwise,\n      // helpers in the DOM tree to be replaced might be scheduled\n      // to re-run before we have a chance to stop them.\n      Tracker.onInvalidate(function () {\n        if (domrange) {\n          domrange.destroyMembers();\n        }\n      });\n    }, undefined, 'materialize');\n\n    // first render.  lastHtmljs is the first htmljs.\n    var initialContents;\n    if (! _workStack) {\n      initialContents = Blaze._materializeDOM(lastHtmljs, [], view);\n      domrange = doFirstRender(view, initialContents);\n      initialContents = null; // help GC because we close over this scope a lot\n    } else {\n      // We're being called from Blaze._materializeDOM, so to avoid\n      // recursion and save stack space, provide a description of the\n      // work to be done instead of doing it.  Tasks pushed onto\n      // _workStack will be done in LIFO order after we return.\n      // The work will still be done within a Tracker.nonreactive,\n      // because it will be done by some call to Blaze._materializeDOM\n      // (which is always called in a Tracker.nonreactive).\n      initialContents = [];\n      // push this function first so that it happens last\n      _workStack.push(function () {\n        domrange = doFirstRender(view, initialContents);\n        initialContents = null; // help GC because of all the closures here\n        _intoArray.push(domrange);\n      });\n      // now push the task that calculates initialContents\n      _workStack.push(_.bind(Blaze._materializeDOM, null,\n                             lastHtmljs, initialContents, view, _workStack));\n    }\n  });\n\n  if (! _workStack) {\n    return domrange;\n  } else {\n    return null;\n  }\n};\n\n// Expands a View to HTMLjs, calling `render` recursively on all\n// Views and evaluating any dynamic attributes.  Calls the `created`\n// callback, but not the `materialized` or `rendered` callbacks.\n// Destroys the view immediately, unless called in a Tracker Computation,\n// in which case the view will be destroyed when the Computation is\n// invalidated.  If called in a Tracker Computation, the result is a\n// reactive string; that is, the Computation will be invalidated\n// if any changes are made to the view or subviews that might affect\n// the HTML.\nBlaze._expandView = function (view, parentView) {\n  Blaze._createView(view, parentView, true /*forExpansion*/);\n\n  view._isInRender = true;\n  var htmljs = Blaze._withCurrentView(view, function () {\n    return view._render();\n  });\n  view._isInRender = false;\n\n  var result = Blaze._expand(htmljs, view);\n\n  if (Tracker.active) {\n    Tracker.onInvalidate(function () {\n      Blaze._destroyView(view);\n    });\n  } else {\n    Blaze._destroyView(view);\n  }\n\n  return result;\n};\n\n// Options: `parentView`\nBlaze._HTMLJSExpander = HTML.TransformingVisitor.extend();\nBlaze._HTMLJSExpander.def({\n  visitObject: function (x) {\n    if (x instanceof Blaze.Template)\n      x = x.constructView();\n    if (x instanceof Blaze.View)\n      return Blaze._expandView(x, this.parentView);\n\n    // this will throw an error; other objects are not allowed!\n    return HTML.TransformingVisitor.prototype.visitObject.call(this, x);\n  },\n  visitAttributes: function (attrs) {\n    // expand dynamic attributes\n    if (typeof attrs === 'function')\n      attrs = Blaze._withCurrentView(this.parentView, attrs);\n\n    // call super (e.g. for case where `attrs` is an array)\n    return HTML.TransformingVisitor.prototype.visitAttributes.call(this, attrs);\n  },\n  visitAttribute: function (name, value, tag) {\n    // expand attribute values that are functions.  Any attribute value\n    // that contains Views must be wrapped in a function.\n    if (typeof value === 'function')\n      value = Blaze._withCurrentView(this.parentView, value);\n\n    return HTML.TransformingVisitor.prototype.visitAttribute.call(\n      this, name, value, tag);\n  }\n});\n\n// Return Blaze.currentView, but only if it is being rendered\n// (i.e. we are in its render() method).\nvar currentViewIfRendering = function () {\n  var view = Blaze.currentView;\n  return (view && view._isInRender) ? view : null;\n};\n\nBlaze._expand = function (htmljs, parentView) {\n  parentView = parentView || currentViewIfRendering();\n  return (new Blaze._HTMLJSExpander(\n    {parentView: parentView})).visit(htmljs);\n};\n\nBlaze._expandAttributes = function (attrs, parentView) {\n  parentView = parentView || currentViewIfRendering();\n  return (new Blaze._HTMLJSExpander(\n    {parentView: parentView})).visitAttributes(attrs);\n};\n\nBlaze._destroyView = function (view, _skipNodes) {\n  if (view.isDestroyed)\n    return;\n  view.isDestroyed = true;\n\n  Blaze._fireCallbacks(view, 'destroyed');\n\n  // Destroy views and elements recursively.  If _skipNodes,\n  // only recurse up to views, not elements, for the case where\n  // the backend (jQuery) is recursing over the elements already.\n\n  if (view._domrange)\n    view._domrange.destroyMembers(_skipNodes);\n};\n\nBlaze._destroyNode = function (node) {\n  if (node.nodeType === 1)\n    Blaze._DOMBackend.Teardown.tearDownElement(node);\n};\n\n// Are the HTMLjs entities `a` and `b` the same?  We could be\n// more elaborate here but the point is to catch the most basic\n// cases.\nBlaze._isContentEqual = function (a, b) {\n  if (a instanceof HTML.Raw) {\n    return (b instanceof HTML.Raw) && (a.value === b.value);\n  } else if (a == null) {\n    return (b == null);\n  } else {\n    return (a === b) &&\n      ((typeof a === 'number') || (typeof a === 'boolean') ||\n       (typeof a === 'string'));\n  }\n};\n\n/**\n * @summary The View corresponding to the current template helper, event handler, callback, or autorun.  If there isn't one, `null`.\n * @locus Client\n * @type {Blaze.View}\n */\nBlaze.currentView = null;\n\nBlaze._withCurrentView = function (view, func) {\n  var oldView = Blaze.currentView;\n  try {\n    Blaze.currentView = view;\n    return func();\n  } finally {\n    Blaze.currentView = oldView;\n  }\n};\n\n// Blaze.render publicly takes a View or a Template.\n// Privately, it takes any HTMLJS (extended with Views and Templates)\n// except null or undefined, or a function that returns any extended\n// HTMLJS.\nvar checkRenderContent = function (content) {\n  if (content === null)\n    throw new Error(\"Can't render null\");\n  if (typeof content === 'undefined')\n    throw new Error(\"Can't render undefined\");\n\n  if ((content instanceof Blaze.View) ||\n      (content instanceof Blaze.Template) ||\n      (typeof content === 'function'))\n    return;\n\n  try {\n    // Throw if content doesn't look like HTMLJS at the top level\n    // (i.e. verify that this is an HTML.Tag, or an array,\n    // or a primitive, etc.)\n    (new HTML.Visitor).visit(content);\n  } catch (e) {\n    // Make error message suitable for public API\n    throw new Error(\"Expected Template or View\");\n  }\n};\n\n// For Blaze.render and Blaze.toHTML, take content and\n// wrap it in a View, unless it's a single View or\n// Template already.\nvar contentAsView = function (content) {\n  checkRenderContent(content);\n\n  if (content instanceof Blaze.Template) {\n    return content.constructView();\n  } else if (content instanceof Blaze.View) {\n    return content;\n  } else {\n    var func = content;\n    if (typeof func !== 'function') {\n      func = function () {\n        return content;\n      };\n    }\n    return Blaze.View('render', func);\n  }\n};\n\n// For Blaze.renderWithData and Blaze.toHTMLWithData, wrap content\n// in a function, if necessary, so it can be a content arg to\n// a Blaze.With.\nvar contentAsFunc = function (content) {\n  checkRenderContent(content);\n\n  if (typeof content !== 'function') {\n    return function () {\n      return content;\n    };\n  } else {\n    return content;\n  }\n};\n\n/**\n * @summary Renders a template or View to DOM nodes and inserts it into the DOM, returning a rendered [View](#blaze_view) which can be passed to [`Blaze.remove`](#blaze_remove).\n * @locus Client\n * @param {Template|Blaze.View} templateOrView The template (e.g. `Template.myTemplate`) or View object to render.  If a template, a View object is [constructed](#template_constructview).  If a View, it must be an unrendered View, which becomes a rendered View and is returned.\n * @param {DOMNode} parentNode The node that will be the parent of the rendered template.  It must be an Element node.\n * @param {DOMNode} [nextNode] Optional. If provided, must be a child of <em>parentNode</em>; the template will be inserted before this node. If not provided, the template will be inserted as the last child of parentNode.\n * @param {Blaze.View} [parentView] Optional. If provided, it will be set as the rendered View's [`parentView`](#view_parentview).\n */\nBlaze.render = function (content, parentElement, nextNode, parentView) {\n  if (! parentElement) {\n    Blaze._warn(\"Blaze.render without a parent element is deprecated. \" +\n                \"You must specify where to insert the rendered content.\");\n  }\n\n  if (nextNode instanceof Blaze.View) {\n    // handle omitted nextNode\n    parentView = nextNode;\n    nextNode = null;\n  }\n\n  // parentElement must be a DOM node. in particular, can't be the\n  // result of a call to `$`. Can't check if `parentElement instanceof\n  // Node` since 'Node' is undefined in IE8.\n  if (parentElement && typeof parentElement.nodeType !== 'number')\n    throw new Error(\"'parentElement' must be a DOM node\");\n  if (nextNode && typeof nextNode.nodeType !== 'number') // 'nextNode' is optional\n    throw new Error(\"'nextNode' must be a DOM node\");\n\n  parentView = parentView || currentViewIfRendering();\n\n  var view = contentAsView(content);\n  Blaze._materializeView(view, parentView);\n\n  if (parentElement) {\n    view._domrange.attach(parentElement, nextNode);\n  }\n\n  return view;\n};\n\nBlaze.insert = function (view, parentElement, nextNode) {\n  Blaze._warn(\"Blaze.insert has been deprecated.  Specify where to insert the \" +\n              \"rendered content in the call to Blaze.render.\");\n\n  if (! (view && (view._domrange instanceof Blaze._DOMRange)))\n    throw new Error(\"Expected template rendered with Blaze.render\");\n\n  view._domrange.attach(parentElement, nextNode);\n};\n\n/**\n * @summary Renders a template or View to DOM nodes with a data context.  Otherwise identical to `Blaze.render`.\n * @locus Client\n * @param {Template|Blaze.View} templateOrView The template (e.g. `Template.myTemplate`) or View object to render.\n * @param {Object|Function} data The data context to use, or a function returning a data context.  If a function is provided, it will be reactively re-run.\n * @param {DOMNode} parentNode The node that will be the parent of the rendered template.  It must be an Element node.\n * @param {DOMNode} [nextNode] Optional. If provided, must be a child of <em>parentNode</em>; the template will be inserted before this node. If not provided, the template will be inserted as the last child of parentNode.\n * @param {Blaze.View} [parentView] Optional. If provided, it will be set as the rendered View's [`parentView`](#view_parentview).\n */\nBlaze.renderWithData = function (content, data, parentElement, nextNode, parentView) {\n  // We defer the handling of optional arguments to Blaze.render.  At this point,\n  // `nextNode` may actually be `parentView`.\n  return Blaze.render(Blaze._TemplateWith(data, contentAsFunc(content)),\n                          parentElement, nextNode, parentView);\n};\n\n/**\n * @summary Removes a rendered View from the DOM, stopping all reactive updates and event listeners on it. Also destroys the Blaze.Template instance associated with the view.\n * @locus Client\n * @param {Blaze.View} renderedView The return value from `Blaze.render` or `Blaze.renderWithData`, or the `view` property of a Blaze.Template instance. Calling `Blaze.remove(Template.instance().view)` from within a template event handler will destroy the view as well as that template and trigger the template's `onDestroyed` handlers.\n */\nBlaze.remove = function (view) {\n  if (! (view && (view._domrange instanceof Blaze._DOMRange)))\n    throw new Error(\"Expected template rendered with Blaze.render\");\n\n  while (view) {\n    if (! view.isDestroyed) {\n      var range = view._domrange;\n      if (range.attached && ! range.parentRange)\n        range.detach();\n      range.destroy();\n    }\n\n    view = view._hasGeneratedParent && view.parentView;\n  }\n};\n\n/**\n * @summary Renders a template or View to a string of HTML.\n * @locus Client\n * @param {Template|Blaze.View} templateOrView The template (e.g. `Template.myTemplate`) or View object from which to generate HTML.\n */\nBlaze.toHTML = function (content, parentView) {\n  parentView = parentView || currentViewIfRendering();\n\n  return HTML.toHTML(Blaze._expandView(contentAsView(content), parentView));\n};\n\n/**\n * @summary Renders a template or View to HTML with a data context.  Otherwise identical to `Blaze.toHTML`.\n * @locus Client\n * @param {Template|Blaze.View} templateOrView The template (e.g. `Template.myTemplate`) or View object from which to generate HTML.\n * @param {Object|Function} data The data context to use, or a function returning a data context.\n */\nBlaze.toHTMLWithData = function (content, data, parentView) {\n  parentView = parentView || currentViewIfRendering();\n\n  return HTML.toHTML(Blaze._expandView(Blaze._TemplateWith(\n    data, contentAsFunc(content)), parentView));\n};\n\nBlaze._toText = function (htmljs, parentView, textMode) {\n  if (typeof htmljs === 'function')\n    throw new Error(\"Blaze._toText doesn't take a function, just HTMLjs\");\n\n  if ((parentView != null) && ! (parentView instanceof Blaze.View)) {\n    // omitted parentView argument\n    textMode = parentView;\n    parentView = null;\n  }\n  parentView = parentView || currentViewIfRendering();\n\n  if (! textMode)\n    throw new Error(\"textMode required\");\n  if (! (textMode === HTML.TEXTMODE.STRING ||\n         textMode === HTML.TEXTMODE.RCDATA ||\n         textMode === HTML.TEXTMODE.ATTRIBUTE))\n    throw new Error(\"Unknown textMode: \" + textMode);\n\n  return HTML.toText(Blaze._expand(htmljs, parentView), textMode);\n};\n\n/**\n * @summary Returns the current data context, or the data context that was used when rendering a particular DOM element or View from a Meteor template.\n * @locus Client\n * @param {DOMElement|Blaze.View} [elementOrView] Optional.  An element that was rendered by a Meteor, or a View.\n */\nBlaze.getData = function (elementOrView) {\n  var theWith;\n\n  if (! elementOrView) {\n    theWith = Blaze.getView('with');\n  } else if (elementOrView instanceof Blaze.View) {\n    var view = elementOrView;\n    theWith = (view.name === 'with' ? view :\n               Blaze.getView(view, 'with'));\n  } else if (typeof elementOrView.nodeType === 'number') {\n    if (elementOrView.nodeType !== 1)\n      throw new Error(\"Expected DOM element\");\n    theWith = Blaze.getView(elementOrView, 'with');\n  } else {\n    throw new Error(\"Expected DOM element or View\");\n  }\n\n  return theWith ? theWith.dataVar.get() : null;\n};\n\n// For back-compat\nBlaze.getElementData = function (element) {\n  Blaze._warn(\"Blaze.getElementData has been deprecated.  Use \" +\n              \"Blaze.getData(element) instead.\");\n\n  if (element.nodeType !== 1)\n    throw new Error(\"Expected DOM element\");\n\n  return Blaze.getData(element);\n};\n\n// Both arguments are optional.\n\n/**\n * @summary Gets either the current View, or the View enclosing the given DOM element.\n * @locus Client\n * @param {DOMElement} [element] Optional.  If specified, the View enclosing `element` is returned.\n */\nBlaze.getView = function (elementOrView, _viewName) {\n  var viewName = _viewName;\n\n  if ((typeof elementOrView) === 'string') {\n    // omitted elementOrView; viewName present\n    viewName = elementOrView;\n    elementOrView = null;\n  }\n\n  // We could eventually shorten the code by folding the logic\n  // from the other methods into this method.\n  if (! elementOrView) {\n    return Blaze._getCurrentView(viewName);\n  } else if (elementOrView instanceof Blaze.View) {\n    return Blaze._getParentView(elementOrView, viewName);\n  } else if (typeof elementOrView.nodeType === 'number') {\n    return Blaze._getElementView(elementOrView, viewName);\n  } else {\n    throw new Error(\"Expected DOM element or View\");\n  }\n};\n\n// Gets the current view or its nearest ancestor of name\n// `name`.\nBlaze._getCurrentView = function (name) {\n  var view = Blaze.currentView;\n  // Better to fail in cases where it doesn't make sense\n  // to use Blaze._getCurrentView().  There will be a current\n  // view anywhere it does.  You can check Blaze.currentView\n  // if you want to know whether there is one or not.\n  if (! view)\n    throw new Error(\"There is no current view\");\n\n  if (name) {\n    while (view && view.name !== name)\n      view = view.parentView;\n    return view || null;\n  } else {\n    // Blaze._getCurrentView() with no arguments just returns\n    // Blaze.currentView.\n    return view;\n  }\n};\n\nBlaze._getParentView = function (view, name) {\n  var v = view.parentView;\n\n  if (name) {\n    while (v && v.name !== name)\n      v = v.parentView;\n  }\n\n  return v || null;\n};\n\nBlaze._getElementView = function (elem, name) {\n  var range = Blaze._DOMRange.forElement(elem);\n  var view = null;\n  while (range && ! view) {\n    view = (range.view || null);\n    if (! view) {\n      if (range.parentRange)\n        range = range.parentRange;\n      else\n        range = Blaze._DOMRange.forElement(range.parentElement);\n    }\n  }\n\n  if (name) {\n    while (view && view.name !== name)\n      view = view.parentView;\n    return view || null;\n  } else {\n    return view;\n  }\n};\n\nBlaze._addEventMap = function (view, eventMap, thisInHandler) {\n  thisInHandler = (thisInHandler || null);\n  var handles = [];\n\n  if (! view._domrange)\n    throw new Error(\"View must have a DOMRange\");\n\n  view._domrange.onAttached(function attached_eventMaps(range, element) {\n    _.each(eventMap, function (handler, spec) {\n      var clauses = spec.split(/,\\s+/);\n      // iterate over clauses of spec, e.g. ['click .foo', 'click .bar']\n      _.each(clauses, function (clause) {\n        var parts = clause.split(/\\s+/);\n        if (parts.length === 0)\n          return;\n\n        var newEvents = parts.shift();\n        var selector = parts.join(' ');\n        handles.push(Blaze._EventSupport.listen(\n          element, newEvents, selector,\n          function (evt) {\n            if (! range.containsElement(evt.currentTarget))\n              return null;\n            var handlerThis = thisInHandler || this;\n            var handlerArgs = arguments;\n            return Blaze._withCurrentView(view, function () {\n              return handler.apply(handlerThis, handlerArgs);\n            });\n          },\n          range, function (r) {\n            return r.parentRange;\n          }));\n      });\n    });\n  });\n\n  view.onViewDestroyed(function () {\n    _.each(handles, function (h) {\n      h.stop();\n    });\n    handles.length = 0;\n  });\n};\n"
  },
  {
    "path": "packages/blaze/view_tests.js",
    "content": "if (Meteor.isClient) {\n\n  Tinytest.add(\"blaze - view - callbacks\", function (test) {\n    var R = ReactiveVar('foo');\n\n    var buf = '';\n\n    var v = Blaze.View(function () {\n      return R.get();\n    });\n\n    v.onViewCreated(function () {\n      buf += 'c' + v.renderCount;\n    });\n    v._onViewRendered(function () {\n      buf += 'r' + v.renderCount;\n    });\n    v.onViewReady(function () {\n      buf += 'y' + v.renderCount;\n    });\n    v.onViewDestroyed(function () {\n      buf += 'd' + v.renderCount;\n    });\n\n    test.equal(buf, '');\n\n    var div = document.createElement(\"DIV\");\n    test.isFalse(v.isRendered);\n    test.isFalse(v._isAttached);\n    test.equal(canonicalizeHtml(div.innerHTML), \"\");\n    test.throws(function () { v.firstNode(); }, /View must be attached/);\n    test.throws(function () { v.lastNode(); }, /View must be attached/);\n    Blaze.render(v, div);\n    test.equal(buf, 'c0r1');\n    test.equal(typeof (v.firstNode().nodeType), \"number\");\n    test.equal(typeof (v.lastNode().nodeType), \"number\");\n    test.isTrue(v.isRendered);\n    test.isTrue(v._isAttached);\n    test.equal(buf, 'c0r1');\n    test.equal(canonicalizeHtml(div.innerHTML), \"foo\");\n    Tracker.flush();\n    test.equal(buf, 'c0r1y1');\n\n    R.set(\"bar\");\n    Tracker.flush();\n    test.equal(buf, 'c0r1y1r2y2');\n    test.equal(canonicalizeHtml(div.innerHTML), \"bar\");\n\n    Blaze.remove(v);\n    test.equal(buf, 'c0r1y1r2y2d2');\n    test.equal(canonicalizeHtml(div.innerHTML), \"\");\n\n    buf = \"\";\n    R.set(\"baz\");\n    Tracker.flush();\n    test.equal(buf, \"\");\n  });\n\n}\n"
  },
  {
    "path": "packages/blaze-html-templates/README.md",
    "content": "# blaze-html-templates\n\nA meta-package that includes everything you need to compile and run Meteor templates with Spacebars and Blaze.\n\nFor more details, see the documentation of the component packages:\n\n- [templating](https://atmospherejs.com/meteor/templating): compiles `.html` files\n- [blaze](https://atmospherejs.com/meteor/blaze): the runtime library\n- [spacebars](https://atmospherejs.com/meteor/spacebars): the templating language\n"
  },
  {
    "path": "packages/blaze-html-templates/package.js",
    "content": "Package.describe({\n  name: 'blaze-html-templates',\n  version: '1.0.4',\n  // Brief, one-line summary of the package.\n  summary: 'Compile HTML templates into reactive UI with Meteor Blaze',\n  // By default, Meteor will default to using README.md for documentation.\n  // To avoid submitting documentation, set this field to null.\n  documentation: 'README.md'\n});\n\nPackage.onUse(function(api) {\n  api.imply([\n    // A library for reactive user interfaces\n    'blaze',\n\n    // The following packages are basically empty shells that just exist to\n    // satisfy code checking for the existence of a package. Rest assured that\n    // they are not adding any bloat to your bundle.\n    'ui', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.\n    'spacebars', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0\n\n    // Compile .html files into Blaze reactive views\n    'templating'\n  ]);\n});\n"
  },
  {
    "path": "packages/blaze-tools/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/blaze-tools/README.md",
    "content": "# blaze-tools\n\nCompile-time utilities that are likely to be useful to any package\nthat compiles templates for Blaze.\n"
  },
  {
    "path": "packages/blaze-tools/package.js",
    "content": "Package.describe({\n  summary: \"Compile-time tools for Blaze\",\n  version: '1.0.9'\n});\n\nPackage.onUse(function (api) {\n  api.export('BlazeTools');\n\n  api.use('htmljs');\n  api.use('underscore');\n\n  api.addFiles(['preamble.js',\n                 'tokens.js',\n                 'tojs.js']);\n});\n\nPackage.onTest(function (api) {\n  api.use('blaze-tools');\n  api.use('tinytest');\n  api.use('underscore');\n  api.use('html-tools');\n\n  api.addFiles(['token_tests.js']);\n});\n"
  },
  {
    "path": "packages/blaze-tools/preamble.js",
    "content": "BlazeTools = {};\n"
  },
  {
    "path": "packages/blaze-tools/tojs.js",
    "content": "\nBlazeTools.EmitCode = function (value) {\n  if (! (this instanceof BlazeTools.EmitCode))\n    // called without `new`\n    return new BlazeTools.EmitCode(value);\n\n  if (typeof value !== 'string')\n    throw new Error('BlazeTools.EmitCode must be constructed with a string');\n\n  this.value = value;\n};\nBlazeTools.EmitCode.prototype.toJS = function (visitor) {\n  return this.value;\n};\n\n// Turns any JSONable value into a JavaScript literal.\ntoJSLiteral = function (obj) {\n  // See <http://timelessrepo.com/json-isnt-a-javascript-subset> for `\\u2028\\u2029`.\n  // Also escape Unicode surrogates.\n  return (JSON.stringify(obj)\n          .replace(/[\\u2028\\u2029\\ud800-\\udfff]/g, function (c) {\n            return '\\\\u' + ('000' + c.charCodeAt(0).toString(16)).slice(-4);\n          }));\n};\nBlazeTools.toJSLiteral = toJSLiteral;\n\n\n\nvar jsReservedWordSet = (function (set) {\n  _.each(\"abstract else instanceof super boolean enum int switch break export interface synchronized byte extends let this case false long throw catch final native throws char finally new transient class float null true const for package try continue function private typeof debugger goto protected var default if public void delete implements return volatile do import short while double in static with\".split(' '), function (w) {\n    set[w] = 1;\n  });\n  return set;\n})({});\n\ntoObjectLiteralKey = function (k) {\n  if (/^[a-zA-Z$_][a-zA-Z$0-9_]*$/.test(k) && jsReservedWordSet[k] !== 1)\n    return k;\n  return toJSLiteral(k);\n};\nBlazeTools.toObjectLiteralKey = toObjectLiteralKey;\n\nvar hasToJS = function (x) {\n  return x.toJS && (typeof (x.toJS) === 'function');\n};\n\nToJSVisitor = HTML.Visitor.extend();\nToJSVisitor.def({\n  visitNull: function (nullOrUndefined) {\n    return 'null';\n  },\n  visitPrimitive: function (stringBooleanOrNumber) {\n    return toJSLiteral(stringBooleanOrNumber);\n  },\n  visitArray: function (array) {\n    var parts = [];\n    for (var i = 0; i < array.length; i++)\n      parts.push(this.visit(array[i]));\n    return '[' + parts.join(', ') + ']';\n  },\n  visitTag: function (tag) {\n    return this.generateCall(tag.tagName, tag.attrs, tag.children);\n  },\n  visitComment: function (comment) {\n    return this.generateCall('HTML.Comment', null, [comment.value]);\n  },\n  visitCharRef: function (charRef) {\n    return this.generateCall('HTML.CharRef',\n                             {html: charRef.html, str: charRef.str});\n  },\n  visitRaw: function (raw) {\n    return this.generateCall('HTML.Raw', null, [raw.value]);\n  },\n  visitObject: function (x) {\n    if (hasToJS(x)) {\n      return x.toJS(this);\n    }\n\n    throw new Error(\"Unexpected object in HTMLjs in toJS: \" + x);\n  },\n  generateCall: function (name, attrs, children) {\n    var tagSymbol;\n    if (name.indexOf('.') >= 0) {\n      tagSymbol = name;\n    } else if (HTML.isTagEnsured(name)) {\n      tagSymbol = 'HTML.' + HTML.getSymbolName(name);\n    } else {\n      tagSymbol = 'HTML.getTag(' + toJSLiteral(name) + ')';\n    }\n\n    var attrsArray = null;\n    if (attrs) {\n      attrsArray = [];\n      var needsHTMLAttrs = false;\n      if (HTML.isArray(attrs)) {\n        var attrsArray = [];\n        for (var i = 0; i < attrs.length; i++) {\n          var a = attrs[i];\n          if (hasToJS(a)) {\n            attrsArray.push(a.toJS(this));\n            needsHTMLAttrs = true;\n          } else {\n            var attrsObjStr = this.generateAttrsDictionary(attrs[i]);\n            if (attrsObjStr !== null)\n              attrsArray.push(attrsObjStr);\n          }\n        }\n      } else if (hasToJS(attrs)) {\n        attrsArray.push(attrs.toJS(this));\n        needsHTMLAttrs = true;\n      } else {\n        attrsArray.push(this.generateAttrsDictionary(attrs));\n      }\n    }\n    var attrsStr = null;\n    if (attrsArray && attrsArray.length) {\n      if (attrsArray.length === 1 && ! needsHTMLAttrs) {\n        attrsStr = attrsArray[0];\n      } else {\n        attrsStr = 'HTML.Attrs(' + attrsArray.join(', ') + ')';\n      }\n    }\n\n    var argStrs = [];\n    if (attrsStr !== null)\n      argStrs.push(attrsStr);\n\n    if (children) {\n      for (var i = 0; i < children.length; i++)\n        argStrs.push(this.visit(children[i]));\n    }\n\n    return tagSymbol + '(' + argStrs.join(', ') + ')';\n  },\n  generateAttrsDictionary: function (attrsDict) {\n    if (attrsDict.toJS && (typeof (attrsDict.toJS) === 'function')) {\n      // not an attrs dictionary, but something else!  Like a template tag.\n      return attrsDict.toJS(this);\n    }\n\n    var kvStrs = [];\n    for (var k in attrsDict) {\n      if (! HTML.isNully(attrsDict[k]))\n        kvStrs.push(toObjectLiteralKey(k) + ': ' +\n                    this.visit(attrsDict[k]));\n    }\n    if (kvStrs.length)\n      return '{' + kvStrs.join(', ') + '}';\n    return null;\n  }\n});\nBlazeTools.ToJSVisitor = ToJSVisitor;\n\nBlazeTools.toJS = function (content) {\n  return (new ToJSVisitor).visit(content);\n};\n"
  },
  {
    "path": "packages/blaze-tools/token_tests.js",
    "content": "Tinytest.add(\"blaze-tools - token parsers\", function (test) {\n\n  var run = function (func, input, expected) {\n    var scanner = new HTMLTools.Scanner('z' + input);\n    // make sure the parse function respects `scanner.pos`\n    scanner.pos = 1;\n    var result = func(scanner);\n    if (expected === null) {\n      test.equal(scanner.pos, 1);\n      test.equal(result, null);\n    } else {\n      test.isTrue(scanner.isEOF());\n      test.equal(result, expected);\n    }\n  };\n\n  var runValue = function (func, input, expectedValue) {\n    var expected;\n    if (expectedValue === null)\n      expected = null;\n    else\n      expected = { text: input, value: expectedValue };\n    run(func, input, expected);\n  };\n\n  var parseNumber = BlazeTools.parseNumber;\n  var parseIdentifierName = BlazeTools.parseIdentifierName;\n  var parseExtendedIdentifierName = BlazeTools.parseExtendedIdentifierName;\n  var parseStringLiteral = BlazeTools.parseStringLiteral;\n\n  runValue(parseNumber, \"0\", 0);\n  runValue(parseNumber, \"-0\", 0);\n  runValue(parseNumber, \"-\", null);\n  runValue(parseNumber, \".a\", null);\n  runValue(parseNumber, \".1\", 0.1);\n  runValue(parseNumber, \"1.\", 1);\n  runValue(parseNumber, \"1.1\", 1.1);\n  runValue(parseNumber, \"0x\", null);\n  runValue(parseNumber, \"0xa\", 10);\n  runValue(parseNumber, \"-0xa\", -10);\n  runValue(parseNumber, \"1e+1\", 10);\n\n  _.each([parseIdentifierName, parseExtendedIdentifierName], function (f) {\n    run(f, \"a\", \"a\");\n    run(f, \"true\", \"true\");\n    run(f, \"null\", \"null\");\n    run(f, \"if\", \"if\");\n    run(f, \"1\", null);\n    run(f, \"1a\", null);\n    run(f, \"+a\", null);\n    run(f, \"a1\", \"a1\");\n    run(f, \"a1a\", \"a1a\");\n    run(f, \"_a8f_f8d88_\", \"_a8f_f8d88_\");\n  });\n  run(parseIdentifierName, \"@index\", null);\n  run(parseExtendedIdentifierName, \"@index\", \"@index\");\n  run(parseExtendedIdentifierName, \"@something\", \"@something\");\n  run(parseExtendedIdentifierName, \"@\", null);\n\n  runValue(parseStringLiteral, '\"a\"', 'a');\n  runValue(parseStringLiteral, '\"\\'\"', \"'\");\n  runValue(parseStringLiteral, '\\'\"\\'', '\"');\n  runValue(parseStringLiteral, '\"a\\\\\\nb\"', 'ab'); // line continuation\n  runValue(parseStringLiteral, '\"a\\u0062c\"', 'abc');\n  // Note: IE 8 doesn't correctly parse '\\v' in JavaScript.\n  runValue(parseStringLiteral, '\"\\\\0\\\\b\\\\f\\\\n\\\\r\\\\t\\\\v\"', '\\0\\b\\f\\n\\r\\t\\u000b');\n  runValue(parseStringLiteral, '\"\\\\x41\"', 'A');\n  runValue(parseStringLiteral, '\"\\\\\\\\\"', '\\\\');\n  runValue(parseStringLiteral, '\"\\\\\\\"\"', '\\\"');\n  runValue(parseStringLiteral, '\"\\\\\\'\"', '\\'');\n  runValue(parseStringLiteral, \"'\\\\\\\\'\", '\\\\');\n  runValue(parseStringLiteral, \"'\\\\\\\"'\", '\\\"');\n  runValue(parseStringLiteral, \"'\\\\\\''\", '\\'');\n\n  test.throws(function () {\n    run(parseStringLiteral, \"'this is my string\");\n  }, /Unterminated string literal/);\n});\n"
  },
  {
    "path": "packages/blaze-tools/tokens.js",
    "content": "\n// Adapted from source code of http://xregexp.com/plugins/#unicode\nvar unicodeCategories = {\n  Ll: \"0061-007A00B500DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F05210523052505270561-05871D00-1D2B1D6B-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7B2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2CF32D00-2D252D272D2DA641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA661A663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CA78EA791A793A7A1A7A3A7A5A7A7A7A9A7FAFB00-FB06FB13-FB17FF41-FF5A\",\n  Lm: \"02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D6A1D781D9B-1DBF2071207F2090-209C2C7C2C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A7F8A7F9A9CFAA70AADDAAF3AAF4FF70FF9EFF9F\",\n  Lo: \"00AA00BA01BB01C0-01C3029405D0-05EA05F0-05F20620-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150840-085808A008A2-08AC0904-0939093D09500958-09610972-09770979-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-0CB90CBD0CDE0CE00CE10CF10CF20D05-0D0C0D0E-0D100D12-0D3A0D3D0D4E0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC-0EDF0F000F40-0F470F49-0F6C0F88-0F8C1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA10FD-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-1BA01BAE1BAF1BBA-1BE51C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF11CF51CF62135-21382D30-2D672D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31BA31F0-31FF3400-4DB54E00-9FCCA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCAAE0-AAEAAAF2AB01-AB06AB09-AB0EAB11-AB16AB20-AB26AB28-AB2EABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC\",\n  Lt: \"01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC\",\n  Lu: \"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E05200522052405260531-055610A0-10C510C710CD1E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CED2CF2A640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA660A662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BA78DA790A792A7A0A7A2A7A4A7A6A7A8A7AAFF21-FF3A\",\n  Mc: \"0903093B093E-09400949-094C094E094F0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1BAC1BAD1BE71BEA-1BEC1BEE1BF21BF31C24-1C2B1C341C351CE11CF21CF3302E302FA823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BAAEBAAEEAAEFAAF5ABE3ABE4ABE6ABE7ABE9ABEAABEC\",\n  Mn: \"0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065F067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0859-085B08E4-08FE0900-0902093A093C0941-0948094D0951-095709620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F8D-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135D-135F1712-17141732-1734175217531772177317B417B517B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91BAB1BE61BE81BE91BED1BEF-1BF11C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1CF41DC0-1DE61DFC-1DFF20D0-20DC20E120E5-20F02CEF-2CF12D7F2DE0-2DFF302A-302D3099309AA66FA674-A67DA69FA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1AAECAAEDAAF6ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26\",\n  Nd: \"0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19D91A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19\",\n  Nl: \"16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF\",\n  Pc: \"005F203F20402054FE33FE34FE4D-FE4FFF3F\"\n};\n\nvar unicodeClass = function (abbrev) {\n  return '[' +\n    unicodeCategories[abbrev].replace(/[0-9A-F]{4}/ig, \"\\\\u$&\") + ']';\n};\n\n// See ECMA-262 spec, 3rd edition, Section 7.6\n// Match one or more characters that can start an identifier.\n// This is IdentifierStart+.\nvar rIdentifierPrefix = new RegExp(\n  \"^([a-zA-Z$_]+|\\\\\\\\u[0-9a-fA-F]{4}|\" +\n    [unicodeClass('Lu'), unicodeClass('Ll'), unicodeClass('Lt'),\n     unicodeClass('Lm'), unicodeClass('Lo'), unicodeClass('Nl')].join('|') +\n    \")+\");\n// Match one or more characters that can continue an identifier.\n// This is (IdentifierPart and not IdentifierStart)+.\n// To match a full identifier, match rIdentifierPrefix, then\n// match rIdentifierMiddle followed by rIdentifierPrefix until they both fail.\nvar rIdentifierMiddle = new RegExp(\n  \"^([0-9]|\" + [unicodeClass('Mn'), unicodeClass('Mc'), unicodeClass('Nd'),\n                unicodeClass('Pc')].join('|') + \")+\");\n\n\n// See ECMA-262 spec, 3rd edition, Section 7.8.3\nvar rHexLiteral = /^0[xX][0-9a-fA-F]+(?!\\w)/;\nvar rDecLiteral =\n      /^(((0|[1-9][0-9]*)(\\.[0-9]*)?)|\\.[0-9]+)([Ee][+-]?[0-9]+)?(?!\\w)/;\n\n// Section 7.8.4\nvar rStringQuote = /^[\"']/;\n// Match one or more characters besides quotes, backslashes, or line ends\nvar rStringMiddle = /^(?=.)[^\"'\\\\]+?((?!.)|(?=[\"'\\\\]))/;\n// Match one escape sequence, including the backslash.\nvar rEscapeSequence =\n      /^\\\\(['\"\\\\bfnrtv]|0(?![0-9])|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|(?=.)[^ux0-9])/;\n// Match one ES5 line continuation\nvar rLineContinuation =\n      /^\\\\(\\r\\n|[\\u000A\\u000D\\u2028\\u2029])/;\n\n\nBlazeTools.parseNumber = function (scanner) {\n  var startPos = scanner.pos;\n\n  var isNegative = false;\n  if (scanner.peek() === '-') {\n    scanner.pos++;\n    isNegative = true;\n  }\n  // Note that we allow `\"-0xa\"`, unlike `Number(...)`.\n\n  var rest = scanner.rest();\n  var match = rDecLiteral.exec(rest) || rHexLiteral.exec(rest);\n  if (! match) {\n    scanner.pos = startPos;\n    return null;\n  }\n  var matchText = match[0];\n  scanner.pos += matchText.length;\n\n  var text = (isNegative ? '-' : '') + matchText;\n  var value = Number(matchText);\n  value = (isNegative ? -value : value);\n  return { text: text, value: value };\n};\n\nBlazeTools.parseIdentifierName = function (scanner) {\n  var startPos = scanner.pos;\n  var rest = scanner.rest();\n  var match = rIdentifierPrefix.exec(rest);\n  if (! match)\n    return null;\n  scanner.pos += match[0].length;\n  rest = scanner.rest();\n  var foundMore = true;\n\n  while (foundMore) {\n    foundMore = false;\n\n    match = rIdentifierMiddle.exec(rest);\n    if (match) {\n      foundMore = true;\n      scanner.pos += match[0].length;\n      rest = scanner.rest();\n    }\n\n    match = rIdentifierPrefix.exec(rest);\n    if (match) {\n      foundMore = true;\n      scanner.pos += match[0].length;\n      rest = scanner.rest();\n    }\n  }\n\n  return scanner.input.substring(startPos, scanner.pos);\n};\n\nBlazeTools.parseExtendedIdentifierName = function (scanner) {\n  // parse an identifier name optionally preceded by '@'\n  if (scanner.peek() === '@') {\n    scanner.pos++;\n    var afterAt = BlazeTools.parseIdentifierName(scanner);\n    if (afterAt) {\n      return '@' + afterAt;\n    } else {\n      scanner.pos--;\n      return null;\n    }\n  } else {\n    return BlazeTools.parseIdentifierName(scanner);\n  }\n};\n\nBlazeTools.parseStringLiteral = function (scanner) {\n  var startPos = scanner.pos;\n  var rest = scanner.rest();\n  var match = rStringQuote.exec(rest);\n  if (! match)\n    return null;\n\n  var quote = match[0];\n  scanner.pos++;\n  rest = scanner.rest();\n\n  var jsonLiteral = '\"';\n\n  while (match) {\n    match = rStringMiddle.exec(rest);\n    if (match) {\n      jsonLiteral += match[0];\n    } else {\n      match = rEscapeSequence.exec(rest);\n      if (match) {\n        var esc = match[0];\n        // Convert all string escapes to JSON-compatible string escapes, so we\n        // can use JSON.parse for some of the work.  JSON strings are not the\n        // same as JS strings.  They don't support `\\0`, `\\v`, `\\'`, or hex\n        // escapes.\n        if (esc === '\\\\0')\n          jsonLiteral += '\\\\u0000';\n        else if (esc === '\\\\v')\n          // Note: IE 8 doesn't correctly parse '\\v' in JavaScript.\n          jsonLiteral += '\\\\u000b';\n        else if (esc.charAt(1) === 'x')\n          jsonLiteral += '\\\\u00' + esc.slice(2);\n        else if (esc === '\\\\\\'')\n          jsonLiteral += \"'\";\n        else\n          jsonLiteral += esc;\n      } else {\n        match = rLineContinuation.exec(rest);\n        if (! match) {\n          match = rStringQuote.exec(rest);\n          if (match) {\n            var c = match[0];\n            if (c !== quote) {\n              if (c === '\"')\n                jsonLiteral += '\\\\';\n              jsonLiteral += c;\n            }\n          }\n        }\n      }\n    }\n    if (match) {\n      scanner.pos += match[0].length;\n      rest = scanner.rest();\n      if (match[0] === quote)\n        break;\n    }\n  }\n\n  if (! match || match[0] !== quote)\n    scanner.fatal(\"Unterminated string literal\");\n\n  jsonLiteral += '\"';\n  var text = scanner.input.substring(startPos, scanner.pos);\n  var value = JSON.parse(jsonLiteral);\n  return { text: text, value: value };\n};\n"
  },
  {
    "path": "packages/boilerplate-generator/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/boilerplate-generator/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/boilerplate-generator/boilerplate-generator.js",
    "content": "var fs = Npm.require('fs');\nvar path = Npm.require('path');\n\n// Copied from webapp_server\nvar readUtf8FileSync = function (filename) {\n  return Meteor.wrapAsync(fs.readFile)(filename, 'utf8');\n};\n\nBoilerplate = function (arch, manifest, options) {\n  var self = this;\n  options = options || {};\n  self.template = _getTemplate(arch);\n  self.baseData = null;\n  self.func = null;\n\n  self._generateBoilerplateFromManifestAndSource(\n    manifest,\n    self.template,\n    options\n  );\n};\n\n// The 'extraData' argument can be used to extend 'self.baseData'. Its\n// purpose is to allow you to specify data that you might not know at\n// the time that you construct the Boilerplate object. (e.g. it is used\n// by 'webapp' to specify data that is only known at request-time).\nBoilerplate.prototype.toHTML = function (extraData) {\n  var self = this;\n\n  if (! self.baseData || ! self.func)\n    throw new Error('Boilerplate did not instantiate correctly.');\n\n  return  \"<!DOCTYPE html>\\n\" +\n    Blaze.toHTML(Blaze.With(_.extend(self.baseData, extraData),\n                            self.func));\n};\n\n// XXX Exported to allow client-side only changes to rebuild the boilerplate\n// without requiring a full server restart.\n// Produces an HTML string with given manifest and boilerplateSource.\n// Optionally takes urlMapper in case urls from manifest need to be prefixed\n// or rewritten.\n// Optionally takes pathMapper for resolving relative file system paths.\n// Optionally allows to override fields of the data context.\nBoilerplate.prototype._generateBoilerplateFromManifestAndSource =\n  function (manifest, boilerplateSource, options) {\n    var self = this;\n    // map to the identity by default\n    var urlMapper = options.urlMapper || _.identity;\n    var pathMapper = options.pathMapper || _.identity;\n\n    var boilerplateBaseData = {\n      css: [],\n      js: [],\n      head: '',\n      body: '',\n      meteorManifest: JSON.stringify(manifest)\n    };\n\n    // allow the caller to extend the default base data\n    _.extend(boilerplateBaseData, options.baseDataExtension);\n\n    _.each(manifest, function (item) {\n      var urlPath = urlMapper(item.url);\n      var itemObj = { url: urlPath };\n\n      if (options.inline) {\n        itemObj.scriptContent = readUtf8FileSync(\n          pathMapper(item.path));\n        itemObj.inline = true;\n      }\n\n      if (item.type === 'css' && item.where === 'client') {\n        boilerplateBaseData.css.push(itemObj);\n      }\n      if (item.type === 'js' && item.where === 'client') {\n        boilerplateBaseData.js.push(itemObj);\n      }\n      if (item.type === 'head') {\n        boilerplateBaseData.head =\n          readUtf8FileSync(pathMapper(item.path));\n      }\n      if (item.type === 'body') {\n        boilerplateBaseData.body =\n          readUtf8FileSync(pathMapper(item.path));\n      }\n    });\n    var boilerplateRenderCode = SpacebarsCompiler.compile(\n      boilerplateSource, { isBody: true });\n\n    // Note that we are actually depending on eval's local environment capture\n    // so that UI and HTML are visible to the eval'd code.\n    // XXX the template we are evaluating relies on the fact that UI is globally\n      // available.\n    global.UI = UI;\n    self.func = eval(boilerplateRenderCode);\n    self.baseData = boilerplateBaseData;\n};\n\nvar _getTemplate = _.memoize(function (arch) {\n  var filename = 'boilerplate_' + arch + '.html';\n  return Assets.getText(filename);\n});\n"
  },
  {
    "path": "packages/boilerplate-generator/boilerplate_web.browser.html",
    "content": "<html {{htmlAttributes}}>\n<head>\n{{#each css}}  <link rel=\"stylesheet\" type=\"text/css\" class=\"__meteor-css__\" href=\"{{../bundledJsCssUrlRewriteHook url}}\">{{/each}}\n{{{head}}}\n{{{dynamicHead}}}\n</head>\n<body>\n{{{body}}}\n{{{dynamicBody}}}\n{{#if inlineScriptsAllowed}}\n<script type='text/javascript'>__meteor_runtime_config__ = JSON.parse(decodeURIComponent({{meteorRuntimeConfig}}));</script>\n{{else}}\n<script type='text/javascript' src='{{rootUrlPathPrefix}}/meteor_runtime_config.js'></script>\n{{/if}}\n{{#each js}}  <script type=\"text/javascript\" src=\"{{../bundledJsCssUrlRewriteHook url}}\"></script>\n{{/each}}\n{{#each additionalStaticJs}}\n  {{#if ../inlineScriptsAllowed}}\n    <script type='text/javascript'>\n      {{contents}}\n    </script>\n  {{else}}\n    <script type='text/javascript'\n            src='{{rootUrlPathPrefix}}{{pathname}}'></script>\n  {{/if}}\n{{/each}}\n</body>\n</html>\n"
  },
  {
    "path": "packages/boilerplate-generator/boilerplate_web.cordova.html",
    "content": "<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"format-detection\" content=\"telephone=no\">\n  <meta name=\"viewport\" content=\"user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height\">\n  <meta name=\"msapplication-tap-highlight\" content=\"no\">\n  <meta http-equiv=\"Content-Security-Policy\" content=\"default-src * data: blob: 'unsafe-inline' 'unsafe-eval';\">\n\n{{! We are explicitly not using bundledJsCssUrlRewriteHook: in cordova we serve assets up directly from disk, so rewriting the URL does not make sense }}\n\n{{#each css}}  <link rel=\"stylesheet\" type=\"text/css\" class=\"__meteor-css__\" href=\"{{url}}\">{{/each}}\n\n  <script type='text/javascript'>\n    __meteor_runtime_config__ = JSON.parse(decodeURIComponent({{meteorRuntimeConfig}}));\n\n    if (/Android/i.test(navigator.userAgent)) {\n      // When Android app is emulated, it cannot connect to localhost,\n      // instead it should connect to 10.0.2.2\n      // (unless we're using an http proxy; then it works!)\n      if (!__meteor_runtime_config__.httpProxyPort) {\n        __meteor_runtime_config__.ROOT_URL = (__meteor_runtime_config__.ROOT_URL || '').replace(/localhost/i, '10.0.2.2');\n        __meteor_runtime_config__.DDP_DEFAULT_CONNECTION_URL = (__meteor_runtime_config__.DDP_DEFAULT_CONNECTION_URL || '').replace(/localhost/i, '10.0.2.2');\n      }\n    }\n  </script>\n\n  <script type=\"text/javascript\" src=\"/cordova.js\"></script>\n{{#each js}}  <script type=\"text/javascript\" src=\"{{url}}\"></script>\n{{/each}}\n{{#each additionalStaticJs}}\n  {{#if ../inlineScriptsAllowed}}\n    <script type='text/javascript'>\n      {{contents}}\n    </script>\n  {{else}}\n    <script type='text/javascript'\n            src='{{rootUrlPathPrefix}}{{pathname}}'></script>\n  {{/if}}\n{{/each}}\n  {{{head}}}\n</head>\n\n<body>\n  {{{body}}}\n</body>\n</html>\n"
  },
  {
    "path": "packages/boilerplate-generator/package.js",
    "content": "Package.describe({\n  summary: \"Generates the boilerplate html from program's manifest\",\n  version: '1.0.9'\n});\n\nPackage.onUse(function (api) {\n  api.use(['underscore',  'spacebars-compiler',\n           'spacebars', 'htmljs', 'ui'], 'server');\n  api.addFiles(['boilerplate-generator.js'], 'server');\n  api.export(['Boilerplate'], 'server');\n  // These are spacebars templates, but we process them manually with the\n  // spacebars compiler rather than letting the 'templating' package (which\n  // isn't fully supported on the server yet) handle it. That also means that\n  // they don't contain the outer \"<template>\" tag.\n  api.addAssets([\n    'boilerplate_web.browser.html',\n    'boilerplate_web.cordova.html'\n  ], 'server');\n});\n"
  },
  {
    "path": "packages/browser-policy/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/browser-policy/README.md",
    "content": "# browser-policy\n\nThe `browser-policy` family of packages, part of\n[Webapp](https://www.meteor.com/webapp), lets you set security-related\npolicies that will be enforced by newer browsers. These policies help\nyou prevent and mitigate common attacks like cross-site scripting and\nclickjacking.\n\n## Details\n\nWhen you add `browser-policy` to your app, you get default configurations for\nthe HTTP headers X-Frame-Options and Content-Security-Policy. X-Frame-Options\ntells the browser which websites are allowed to frame your app. You should only\nlet trusted websites frame your app, because malicious sites could harm your\nusers with <a href=\"https://www.owasp.org/index.php/Clickjacking\">clickjacking\nattacks</a>.\n<a href=\"https://developer.mozilla.org/en-US/docs/Security/CSP/Introducing_Content_Security_Policy\">Content-Security-Policy</a>\ntells the browser where your app can load content from, which encourages safe\npractices and mitigates the damage of a cross-site-scripting attack.\n`browser-policy` also provides functions for you to configure these policies if\nthe defaults are not suitable.\n\nIf you only want to use Content-Security-Policy or X-Frame-Options but not both,\nyou can add the individual packages `browser-policy-content` or\n`browser-policy-framing` instead of `browser-policy`.\n\nFor most apps, we recommend that you take the following steps:\n\n* Add `browser-policy` to your app to enable a starter policy. With this starter\npolicy, your app's client code will be able to load content (images, scripts,\nfonts, etc.) only from its own origin, except that XMLHttpRequests and WebSocket\nconnections can go to any origin. Further, your app's client code will not be\nable to use functions such as `eval()` that convert strings to code. Users'\nbrowsers will only let your app be framed by web pages on the same origin as\nyour app.\n* You can use the functions described below to customize the policies. If your\napp does not need any inline Javascript such as inline `<script>` tags, we\nrecommend that you modify the policy by calling\n`BrowserPolicy.content.disallowInlineScripts()` in server code. This will result\nin one extra round trip when your app is loaded, but will help prevent\ncross-site scripting attacks by disabling all scripts except those loaded from a\n`script src` attribute.\n\nMeteor determines the browser policy when the server starts up, so you should\ncall `BrowserPolicy` functions on the server in top-level application code or in\n`Meteor.startup`. `BrowserPolicy` functions cannot be used in client code.\n\n## Frame options\n\nBy default, if you add `browser-policy` or `browser-policy-framing`, only web pages on the same origin as your app are allowed to frame your app. You can use\nthe following functions to modify this policy.\n\n<dl>\n\n<dt><code>BrowserPolicy.framing.disallow()</code><dt>\n<dd>Your app will never render inside a frame or iframe.</dd>\n\n<dt><code>BrowserPolicy.framing.restrictToOrigin(origin)</code></dt>\n<dd>\nYour app will only render inside frames loaded by\n<code>origin</code>. You can only call this function once with a\nsingle origin, and cannot use wildcards or specify multiple origins\nthat are allowed to frame your app. (This is a limitation of the\nX-Frame-Options header.) Example values of <code>origin</code> include\n\"http://example.com\" and \"https://foo.example.com\". <b>This value of\nthe X-Frame-Options header is not yet supported in Chrome or Safari\nand will be ignored in those browsers.</b>\n</dd>\n\n\n<dt><code>BrowserPolicy.framing.allowAll()</code><dt>\n<dd>\nThis unsets the X-Frame-Options header, so that your app can be framed by\nany webpage.\n</dd>\n</dl>\n\n## Content options\n\nYou can use the functions in this section to control how different types of\ncontent can be loaded on your site.\n\nYou can use the following functions to adjust policies on where Javascript and\nCSS can be run:\n\n<dl>\n\n<dt><code>BrowserPolicy.content.allowInlineScripts()</code></dt>\n<dd>\nAllows inline <code>&lt;script&gt;</code> tags,\n<code>javascript:</code> URLs, and inline event handlers.  The default\npolicy already allows inline scripts.\n</dd>\n\n<dt><code>BrowserPolicy.content.disallowInlineScripts()</code></dt>\n<dd>\nDisallows inline Javascript. Calling this function results in an extra\nround-trip on page load to retrieve Meteor runtime configuration that\nis usually part of an inline script tag.\n</dd>\n\n<dt><code>BrowserPolicy.content.allowEval()</code></dt>\n<dd>\nAllows the creation of Javascript code from strings using function such as <code>eval()</code>.\n</dd>\n\n<dt><code>BrowserPolicy.content.disallowEval()</code></dt>\n<dd>\nDisallows eval and related functions. The default policy already disallows eval.\n</dd>\n\n<dt><code>BrowserPolicy.content.allowInlineStyles()</code></dt>\n<dd>\nAllows inline style tags and style attributes. The default policy already allows\ninline styles.\n</dd>\n\n<dt><code>BrowserPolicy.content.disallowInlineStyles()</code></dt>\n<dd>\nDisallows inline CSS.\n</dd>\n\n</dl>\n\nFinally, you can configure a whitelist of allowed requests that various types of\ncontent can make. The following functions are defined for the content types\nscript, object, image, media, font, frame, style, and connect.\n\n<dl>\n\n<dt><code>BrowserPolicy.content.allow&lt;ContentType&gt;Origin(origin)</code></dt>\n<dd>\nAllows this type of content to be loaded from the given\norigin. <code>origin</code> is a string and can include an optional\nscheme (such as <code>http</code> or <code>https</code>), an optional\nwildcard at the beginning, and an optional port which can be a\nwildcard. Examples include <code>example.com</code>,\n<code>https://*.example.com</code>, and\n<code>example.com:*</code>. You can call these functions multiple\ntimes with different origins to specify a whitelist of allowed\norigins. Origins that don't specify a protocol will allow content over\nboth HTTP and HTTPS: passing <code>example.com</code> will allow\ncontent from both <code>http://example.com</code> and\n<code>https://example.com</code>.\n<dd>\n\n<dt><code>BrowserPolicy.content.allow&lt;ContentType&gt;DataUrl()</code></dt>\n<dd>\nAllows this type of content to be loaded from a <code>data:</code> URL.\n</dd>\n\n<dt><code>BrowserPolicy.content.allow&lt;ContentType&gt;SameOrigin()</code></dt>\n<dd>\nAllows this type of content to be loaded from the same origin as your app.\n</dd>\n\n<dt><code>BrowserPolicy.content.disallow&lt;ContentType&gt;()</code></dt>\n<dd>\nDisallows this type of content on your app.\n</dd>\n\n</dl>\n\nYou can also set policies for all these types of content at once, using these\nfunctions:\n\n* `BrowserPolicy.content.allowSameOriginForAll()`,\n* `BrowserPolicy.content.allowDataUrlForAll()`,\n* `BrowserPolicy.content.allowOriginForAll(origin)`\n* `BrowserPolicy.content.disallowAll()`\n\nFor example, if you want to allow the\norigin `https://foo.com` for all types of content but you want to disable\n`<object>` tags, you can call\n`BrowserPolicy.content.allowOriginForAll(\"https://foo.com\")` followed by\n`BrowserPolicy.content.disallowObject()`.\n\nOther examples of using the `BrowserPolicy.content` API:\n\n* `BrowserPolicy.content.disallowFont()` causes the browser to disallow all\n`<font>` tags.\n* `BrowserPolicy.content.allowImageOrigin(\"https://example.com\")`\nallows images to have their `src` attributes point to images served from\n`https://example.com`.\n* `BrowserPolicy.content.allowConnectOrigin(\"https://example.com\")` allows XMLHttpRequest\nand WebSocket connections to `https://example.com`.\n* `BrowserPolicy.content.allowFrameOrigin(\"https://example.com\")` allows\nyour site to load the origin `https://example.com` in a frame or\niframe. The `BrowserPolicy.framing` API allows you to control which\nsites can frame your site, while\n`BrowserPolicy.content.allowFrameOrigin` allows you to control which\nsites can be loaded inside frames on your site.\n\nAdding `browser-policy-content` to your app also tells certain\nbrowsers to avoid sniffing content types away from the declared type\n(for example, interpreting a text file as JavaScript), using the\n[X-Content-Type-Options](http://msdn.microsoft.com/en-us/library/ie/gg622941%28v=vs.85%29.aspx)\nheader. To re-enable content sniffing, you can call\n`BrowserPolicy.content.allowContentTypeSniffing()`.\n"
  },
  {
    "path": "packages/browser-policy/browser-policy-test.js",
    "content": "BrowserPolicy._setRunningTest();\n\nvar cspsEqual = function (csp1, csp2) {\n  var cspToObj = function (csp) {\n    csp = csp.substring(0, csp.length - 1);\n    var parts = _.map(csp.split(\"; \"), function (part) {\n      return part.split(\" \");\n    });\n    var keys = _.map(parts, _.first);\n    var values = _.map(parts, _.rest);\n    _.each(values, function (value) {\n      value.sort();\n    });\n    return _.object(keys, values);\n  };\n\n  return EJSON.equals(cspToObj(csp1), cspToObj(csp2));\n};\n\n// It's important to call _reset() at the beginnning of these tests; otherwise\n// the headers left over at the end of the last test run will be used.\n\nTinytest.add(\"browser-policy - csp\", function (test) {\n  var defaultCsp = \"default-src 'self'; script-src 'self' 'unsafe-inline'; \" +\n        \"connect-src * 'self'; img-src data: 'self'; style-src 'self' 'unsafe-inline';\"\n\n  BrowserPolicy.content._reset();\n  // Default policy\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(), defaultCsp));\n  test.isTrue(BrowserPolicy.content._keywordAllowed(\"script-src\", \"'unsafe-inline'\"));\n\n  // Redundant whitelisting (inline scripts already allowed in default policy)\n  BrowserPolicy.content.allowInlineScripts();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(), defaultCsp));\n\n  // Disallow inline scripts\n  BrowserPolicy.content.disallowInlineScripts();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'self'; script-src 'self'; \" +\n                        \"connect-src * 'self'; img-src data: 'self'; style-src 'self' 'unsafe-inline';\"));\n  test.isFalse(BrowserPolicy.content._keywordAllowed(\"script-src\", \"'unsafe-inline'\"));\n\n  // Allow eval\n  BrowserPolicy.content.allowEval();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(), \"default-src 'self'; script-src 'self' 'unsafe-eval'; \" +\n                        \"connect-src * 'self'; img-src data: 'self'; style-src 'self' 'unsafe-inline';\"));\n\n  // Disallow inline styles\n  BrowserPolicy.content.disallowInlineStyles();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(), \"default-src 'self'; script-src 'self' 'unsafe-eval'; \" +\n                        \"connect-src * 'self'; img-src data: 'self'; style-src 'self';\"));\n\n  // Allow data: urls everywhere\n  BrowserPolicy.content.allowDataUrlForAll();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'self' data:; script-src 'self' 'unsafe-eval' data:; \" +\n                        \"connect-src * data: 'self'; img-src data: 'self'; style-src 'self' data:;\"));\n\n  // Disallow everything\n  BrowserPolicy.content.disallowAll();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(), \"default-src 'none';\"));\n  test.isFalse(BrowserPolicy.content._keywordAllowed(\"script-src\", \"'unsafe-inline'\"));\n\n  // Put inline scripts back in\n  BrowserPolicy.content.allowInlineScripts();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'none'; script-src 'unsafe-inline';\"));\n  test.isTrue(BrowserPolicy.content._keywordAllowed(\"script-src\", \"'unsafe-inline'\"));\n\n  // Add 'self' to all content types\n  BrowserPolicy.content.allowSameOriginForAll();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'self'; script-src 'self' 'unsafe-inline';\"));\n  test.isTrue(BrowserPolicy.content._keywordAllowed(\"script-src\", \"'unsafe-inline'\"));\n\n  // Disallow all content except same-origin scripts\n  BrowserPolicy.content.disallowAll();\n  BrowserPolicy.content.allowScriptSameOrigin();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'none'; script-src 'self';\"));\n  test.isFalse(BrowserPolicy.content._keywordAllowed(\"script-src\", \"'unsafe-inline'\"));\n\n  // Starting with all content same origin, disallowScript() and then allow\n  // inline scripts. Result should be that that only inline scripts can execute,\n  // not same-origin scripts.\n  BrowserPolicy.content.disallowAll();\n  BrowserPolicy.content.allowSameOriginForAll();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(), \"default-src 'self';\"));\n  BrowserPolicy.content.disallowScript();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'self'; script-src 'none';\"));\n  test.isFalse(BrowserPolicy.content._keywordAllowed(\"script-src\", \"'unsafe-inline'\"));\n  BrowserPolicy.content.allowInlineScripts();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'self'; script-src 'unsafe-inline';\"));\n  test.isTrue(BrowserPolicy.content._keywordAllowed(\"script-src\", \"'unsafe-inline'\"));\n\n  // Starting with all content same origin, allow inline scripts. (Should result\n  // in both same origin and inline scripts allowed.)\n  BrowserPolicy.content.disallowAll();\n  BrowserPolicy.content.allowSameOriginForAll();\n  BrowserPolicy.content.allowInlineScripts();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'self'; script-src 'self' 'unsafe-inline';\"));\n  BrowserPolicy.content.disallowInlineScripts();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'self'; script-src 'self';\"));\n\n  // Allow same origin for all content, then disallow object entirely.\n  BrowserPolicy.content.disallowAll();\n  BrowserPolicy.content.allowSameOriginForAll();\n  BrowserPolicy.content.disallowObject();\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'self'; object-src 'none';\"));\n\n  // Allow foo.com; it should allow both http://foo.com and\n  // https://foo.com.\n  BrowserPolicy.content.allowImageOrigin(\"foo.com\");\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'self'; object-src 'none'; \" +\n                        \"img-src 'self' http://foo.com https://foo.com;\"));\n  // \"Disallow all <object>\" followed by \"allow foo.com for all\" results\n  // in <object> srcs from foo.com.\n  BrowserPolicy.content.allowOriginForAll(\"foo.com\");\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'self' http://foo.com https://foo.com; \" +\n                        \"object-src http://foo.com https://foo.com; \" +\n                        \"img-src 'self' http://foo.com https://foo.com;\"));\n\n  // Check that trailing slashes are trimmed from origins.\n  BrowserPolicy.content.disallowAll();\n  BrowserPolicy.content.allowFrameOrigin(\"https://foo.com/\");\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'none'; frame-src https://foo.com;\"));\n  BrowserPolicy.content.allowObjectOrigin(\"foo.com//\");\n  test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(),\n                        \"default-src 'none'; frame-src https://foo.com; \" +\n                        \"object-src http://foo.com https://foo.com;\"));\n});\n\nTinytest.add(\"browser-policy - x-frame-options\", function (test) {\n  BrowserPolicy.framing._reset();\n  test.equal(BrowserPolicy.framing._constructXFrameOptions(), \"SAMEORIGIN\");\n  BrowserPolicy.framing.disallow();\n  test.equal(BrowserPolicy.framing._constructXFrameOptions(), \"DENY\");\n  BrowserPolicy.framing.allowAll();\n  test.equal(BrowserPolicy.framing._constructXFrameOptions(), null);\n  BrowserPolicy.framing.restrictToOrigin(\"foo.com\");\n  test.equal(BrowserPolicy.framing._constructXFrameOptions(), \"ALLOW-FROM foo.com\");\n  test.throws(function () {\n    BrowserPolicy.framing.restrictToOrigin(\"bar.com\");\n  });\n});\n\nTinytest.add(\"browser-policy - X-Content-Type-Options\", function (test) {\n  BrowserPolicy.content._reset();\n  test.equal(BrowserPolicy.content._xContentTypeOptions(), \"nosniff\");\n  BrowserPolicy.content.allowContentTypeSniffing();\n  test.equal(BrowserPolicy.content._xContentTypeOptions(), undefined);\n});\n"
  },
  {
    "path": "packages/browser-policy/package.js",
    "content": "Package.describe({\n  summary: \"Configure security policies enforced by the browser\",\n  version: \"1.0.9\"\n});\n\nPackage.onUse(function (api) {\n  api.use(['browser-policy-content', 'browser-policy-framing'], 'server');\n  api.imply(['browser-policy-common'], 'server');\n});\n\nPackage.onTest(function (api) {\n  api.use([\"tinytest\", \"browser-policy\", \"ejson\", \"underscore\"], \"server\");\n  api.addFiles(\"browser-policy-test.js\", \"server\");\n});\n"
  },
  {
    "path": "packages/browser-policy-common/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/browser-policy-common/README.md",
    "content": "# browser-policy-common\n\nThis is one of a family of packages that can be used to easily\nconfigure an app's browser-side security policies. The documentation\nis in the\n[browser-policy](https://atmospherejs.com/meteor/browser-policy)\npackage.\n"
  },
  {
    "path": "packages/browser-policy-common/browser-policy-common.js",
    "content": "BrowserPolicy = {};\n\nvar inTest = false;\n\nBrowserPolicy._runningTest = function () {\n  return inTest;\n};\n\nBrowserPolicy._setRunningTest = function () {\n  inTest = true;\n};\n\nWebApp.connectHandlers.use(function (req, res, next) {\n  // Never set headers inside tests because they could break other tests.\n  if (BrowserPolicy._runningTest())\n    return next();\n\n  var xFrameOptions = BrowserPolicy.framing &&\n        BrowserPolicy.framing._constructXFrameOptions();\n  var csp = BrowserPolicy.content &&\n        BrowserPolicy.content._constructCsp();\n  if (xFrameOptions) {\n    res.setHeader(\"X-Frame-Options\", xFrameOptions);\n  }\n  if (csp) {\n    res.setHeader(\"Content-Security-Policy\", csp);\n  }\n  next();\n});\n\n// We use `rawConnectHandlers` to set X-Content-Type-Options on all\n// requests, including static files.\n// XXX We should probably use `rawConnectHandlers` for X-Frame-Options\n// and Content-Security-Policy too, but let's make sure that doesn't\n// break anything first (e.g. the OAuth popup flow won't work well with\n// a CSP that disallows inline scripts).\nWebApp.rawConnectHandlers.use(function (req, res, next) {\n  if (BrowserPolicy._runningTest())\n    return next();\n\n  var contentTypeOptions = BrowserPolicy.content &&\n        BrowserPolicy.content._xContentTypeOptions();\n  if (contentTypeOptions) {\n    res.setHeader(\"X-Content-Type-Options\", contentTypeOptions);\n  }\n  next();\n});\n"
  },
  {
    "path": "packages/browser-policy-common/package.js",
    "content": "Package.describe({\n  summary: \"Common code for browser-policy packages\",\n  version: \"1.0.10\"\n});\n\nPackage.onUse(function (api) {\n  api.use('webapp', 'server');\n  api.addFiles('browser-policy-common.js', 'server');\n  api.export('BrowserPolicy', 'server');\n});\n"
  },
  {
    "path": "packages/browser-policy-content/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/browser-policy-content/README.md",
    "content": "# browser-policy-content\n\nThis is one of a family of packages that can be used to easily\nconfigure an app's browser-side security policies. The documentation\nis in the\n[browser-policy](https://atmospherejs.com/meteor/browser-policy)\npackage.\n"
  },
  {
    "path": "packages/browser-policy-content/browser-policy-content.js",
    "content": "// By adding this package, you get the following default policy:\n// No eval or other string-to-code, and content can only be loaded from the\n// same origin as the app (except for XHRs and websocket connections, which can\n// go to any origin). Browsers will also be told not to sniff content types\n// away from declared content types (X-Content-Type-Options: nosniff).\n//\n// Apps should call BrowserPolicy.content.disallowInlineScripts() if they are\n// not using any inline script tags and are willing to accept an extra round\n// trip on page load.\n//\n// BrowserPolicy.content functions for tweaking CSP:\n// allowInlineScripts()\n// disallowInlineScripts(): adds extra round-trip to page load time\n// allowInlineStyles()\n// disallowInlineStyles()\n// allowEval()\n// disallowEval()\n//\n// For each type of content (script, object, image, media, font, connect,\n// style), there are the following functions:\n// allow<content type>Origin(origin): allows the type of content to be loaded\n// from the given origin\n// allow<content type>DataUrl(): allows the content to be loaded from data: URLs\n// allow<content type>SameOrigin(): allows the content to be loaded from the\n// same origin\n// disallow<content type>(): disallows this type of content all together (can't\n// be called for script)\n//\n// The following functions allow you to set rules for all types of content at\n// once:\n// allowAllContentOrigin(origin)\n// allowAllContentDataUrl()\n// allowAllContentSameOrigin()\n// disallowAllContent()\n//\n// You can allow content type sniffing by calling\n// `BrowserPolicy.content.allowContentTypeSniffing()`.\n\nvar cspSrcs;\nvar cachedCsp; // Avoid constructing the header out of cspSrcs when possible.\n\n// CSP keywords have to be single-quoted.\nvar keywords = {\n  unsafeInline: \"'unsafe-inline'\",\n  unsafeEval: \"'unsafe-eval'\",\n  self: \"'self'\",\n  none: \"'none'\"\n};\n\n// If false, we set the X-Content-Type-Options header to 'nosniff'.\nvar contentSniffingAllowed = false;\n\nBrowserPolicy.content = {};\n\nvar parseCsp = function (csp) {\n  var policies = csp.split(\"; \");\n  cspSrcs = {};\n  _.each(policies, function (policy) {\n    if (policy[policy.length - 1] === \";\")\n      policy = policy.substring(0, policy.length - 1);\n    var srcs = policy.split(\" \");\n    var directive = srcs[0];\n    if (_.indexOf(srcs, keywords.none) !== -1)\n      cspSrcs[directive] = null;\n    else\n      cspSrcs[directive] = srcs.slice(1);\n  });\n\n  if (cspSrcs[\"default-src\"] === undefined)\n    throw new Error(\"Content Security Policies used with \" +\n                    \"browser-policy must specify a default-src.\");\n\n  // Copy default-src sources to other directives.\n  _.each(cspSrcs, function (sources, directive) {\n    cspSrcs[directive] = _.union(sources || [], cspSrcs[\"default-src\"] || []);\n  });\n};\n\nvar removeCspSrc = function (directive, src) {\n  cspSrcs[directive] = _.without(cspSrcs[directive] || [], src);\n};\n\n// Prepare for a change to cspSrcs. Ensure that we have a key in the dictionary\n// and clear any cached CSP.\nvar prepareForCspDirective = function (directive) {\n  cspSrcs = cspSrcs || {};\n  cachedCsp = null;\n  if (! _.has(cspSrcs, directive))\n    cspSrcs[directive] = _.clone(cspSrcs[\"default-src\"]);\n};\n\n// Add `src` to the list of allowed sources for `directive`, with the\n// following modifications if `src` is an origin:\n// - If `src` does not have a protocol specified, then add both\n//   http://<src> and https://<src>. This is to mask differing\n//   cross-browser behavior; some browsers interpret an origin without a\n//   protocol as http://<src> and some interpret it as both http://<src>\n//   and https://<src>\n// - Trim trailing slashes from `src`, since some browsers interpret\n//   \"foo.com/\" as \"foo.com\" and some don't.\nvar addSourceForDirective = function (directive, src) {\n  if (_.contains(_.values(keywords), src)) {\n    cspSrcs[directive].push(src);\n  } else {\n    src = src.toLowerCase();\n\n    // Trim trailing slashes.\n    src = src.replace(/\\/+$/, '');\n\n    var toAdd = [];\n    // If there is no protocol, add both http:// and https://.\n    if (! /^([a-z0-9.+-]+:)/.test(src)) {\n      toAdd.push(\"http://\" + src);\n      toAdd.push(\"https://\" + src);\n    } else {\n      toAdd.push(src);\n    }\n    _.each(toAdd, function (s) {\n      cspSrcs[directive].push(s);\n    });\n  }\n};\n\nvar setDefaultPolicy = function () {\n  // By default, unsafe inline scripts and styles are allowed, since we expect\n  // many apps will use them for analytics, etc. Unsafe eval is disallowed, and\n  // the only allowable content source is the same origin or data, except for\n  // connect which allows anything (since meteor.com apps make websocket\n  // connections to a lot of different origins).\n  BrowserPolicy.content.setPolicy(\"default-src 'self'; \" +\n                                  \"script-src 'self' 'unsafe-inline'; \" +\n                                  \"connect-src *; \" +\n                                  \"img-src data: 'self'; \" +\n                                  \"style-src 'self' 'unsafe-inline';\");\n  contentSniffingAllowed = false;\n};\n\nvar setWebAppInlineScripts = function (value) {\n  if (! BrowserPolicy._runningTest())\n    WebAppInternals.setInlineScriptsAllowed(value);\n};\n\n_.extend(BrowserPolicy.content, {\n  allowContentTypeSniffing: function () {\n    contentSniffingAllowed = true;\n  },\n  // Exported for tests and browser-policy-common.\n  _constructCsp: function () {\n    if (! cspSrcs || _.isEmpty(cspSrcs))\n      return null;\n\n    if (cachedCsp)\n      return cachedCsp;\n\n    var header = _.map(cspSrcs, function (srcs, directive) {\n      srcs = srcs || [];\n      if (_.isEmpty(srcs))\n        srcs = [keywords.none];\n      var directiveCsp = _.uniq(srcs).join(\" \");\n      return directive + \" \" + directiveCsp + \";\";\n    });\n\n    header = header.join(\" \");\n    cachedCsp = header;\n    return header;\n  },\n  _reset: function () {\n    cachedCsp = null;\n    setDefaultPolicy();\n  },\n\n  setPolicy: function (csp) {\n    cachedCsp = null;\n    parseCsp(csp);\n    setWebAppInlineScripts(\n      BrowserPolicy.content._keywordAllowed(\"script-src\", keywords.unsafeInline)\n    );\n  },\n\n  _keywordAllowed: function (directive, keyword) {\n    return (cspSrcs[directive] &&\n            _.indexOf(cspSrcs[directive], keyword) !== -1);\n  },\n\n  // Helpers for creating content security policies\n\n  allowInlineScripts: function () {\n    prepareForCspDirective(\"script-src\");\n    cspSrcs[\"script-src\"].push(keywords.unsafeInline);\n    setWebAppInlineScripts(true);\n  },\n  disallowInlineScripts: function () {\n    prepareForCspDirective(\"script-src\");\n    removeCspSrc(\"script-src\", keywords.unsafeInline);\n    setWebAppInlineScripts(false);\n  },\n  allowEval: function () {\n    prepareForCspDirective(\"script-src\");\n    cspSrcs[\"script-src\"].push(keywords.unsafeEval);\n  },\n  disallowEval: function () {\n    prepareForCspDirective(\"script-src\");\n    removeCspSrc(\"script-src\", keywords.unsafeEval);\n  },\n  allowInlineStyles: function () {\n    prepareForCspDirective(\"style-src\");\n    cspSrcs[\"style-src\"].push(keywords.unsafeInline);\n  },\n  disallowInlineStyles: function () {\n    prepareForCspDirective(\"style-src\");\n    removeCspSrc(\"style-src\", keywords.unsafeInline);\n  },\n\n  // Functions for setting defaults\n  allowSameOriginForAll: function () {\n    BrowserPolicy.content.allowOriginForAll(keywords.self);\n  },\n  allowDataUrlForAll: function () {\n    BrowserPolicy.content.allowOriginForAll(\"data:\");\n  },\n  allowOriginForAll: function (origin) {\n    prepareForCspDirective(\"default-src\");\n    _.each(_.keys(cspSrcs), function (directive) {\n      addSourceForDirective(directive, origin);\n    });\n  },\n  disallowAll: function () {\n    cachedCsp = null;\n    cspSrcs = {\n      \"default-src\": []\n    };\n    setWebAppInlineScripts(false);\n  },\n\n  _xContentTypeOptions: function () {\n    if (! contentSniffingAllowed) {\n      return \"nosniff\";\n    }\n  }\n});\n\n// allow<Resource>Origin, allow<Resource>Data, allow<Resource>self, and\n// disallow<Resource> methods for each type of resource.\n_.each([\"script\", \"object\", \"img\", \"media\",\n        \"font\", \"connect\", \"style\", \"frame\"],\n       function (resource) {\n         var directive = resource + \"-src\";\n         var methodResource;\n         if (resource !== \"img\") {\n           methodResource = resource.charAt(0).toUpperCase() +\n             resource.slice(1);\n         } else {\n           methodResource = \"Image\";\n         }\n         var allowMethodName = \"allow\" + methodResource + \"Origin\";\n         var disallowMethodName = \"disallow\" + methodResource;\n         var allowDataMethodName = \"allow\" + methodResource + \"DataUrl\";\n         var allowBlobMethodName = \"allow\" + methodResource + \"BlobUrl\";\n         var allowSelfMethodName = \"allow\" + methodResource + \"SameOrigin\";\n\n         var disallow = function () {\n           cachedCsp = null;\n           cspSrcs[directive] = [];\n         };\n\n         BrowserPolicy.content[allowMethodName] = function (src) {\n           prepareForCspDirective(directive);\n           addSourceForDirective(directive, src);\n         };\n         if (resource === \"script\") {\n           BrowserPolicy.content[disallowMethodName] = function () {\n             disallow();\n             setWebAppInlineScripts(false);\n           };\n         } else {\n           BrowserPolicy.content[disallowMethodName] = disallow;\n         }\n         BrowserPolicy.content[allowDataMethodName] = function () {\n           prepareForCspDirective(directive);\n           cspSrcs[directive].push(\"data:\");\n         };\n         BrowserPolicy.content[allowBlobMethodName] = function () {\n           prepareForCspDirective(directive);\n           cspSrcs[directive].push(\"blob:\");\n         };\n         BrowserPolicy.content[allowSelfMethodName] = function () {\n           prepareForCspDirective(directive);\n           cspSrcs[directive].push(keywords.self);\n         };\n       });\n\n\nsetDefaultPolicy();\n"
  },
  {
    "path": "packages/browser-policy-content/package.js",
    "content": "Package.describe({\n  summary: \"Configure content security policies\",\n  version: \"1.0.11\"\n});\n\nPackage.onUse(function (api) {\n  api.imply([\"browser-policy-common\"], \"server\");\n  api.addFiles(\"browser-policy-content.js\", \"server\");\n  api.use([\"underscore\", \"browser-policy-common\", \"webapp\"], \"server\");\n});\n"
  },
  {
    "path": "packages/browser-policy-framing/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/browser-policy-framing/README.md",
    "content": "# browser-policy-framing\n\nThis is one of a family of packages that can be used to easily\nconfigure an app's browser-side security policies. The documentation\nis in the\n[browser-policy](https://atmospherejs.com/meteor/browser-policy)\npackage.\n"
  },
  {
    "path": "packages/browser-policy-framing/browser-policy-framing.js",
    "content": "// By adding this package, you get a default policy where only web pages on the\n// same origin as your app can frame your app.\n//\n// For controlling which origins can frame this app,\n// BrowserPolicy.framing.disallow()\n// BrowserPolicy.framing.restrictToOrigin(origin)\n// BrowserPolicy.framing.allowByAnyOrigin()\n\nvar defaultXFrameOptions = \"SAMEORIGIN\";\nvar xFrameOptions = defaultXFrameOptions;\n\nBrowserPolicy.framing = {};\n\n_.extend(BrowserPolicy.framing, {\n  // Exported for tests and browser-policy-common.\n  _constructXFrameOptions: function () {\n    return xFrameOptions;\n  },\n  _reset: function () {\n    xFrameOptions = defaultXFrameOptions;\n  },\n\n  disallow: function () {\n    xFrameOptions = \"DENY\";\n  },\n  // ALLOW-FROM not supported in Chrome or Safari.\n  restrictToOrigin: function (origin) {\n    // Trying to specify two allow-from throws to prevent users from\n    // accidentally overwriting an allow-from origin when they think they are\n    // adding multiple origins.\n    if (xFrameOptions && xFrameOptions.indexOf(\"ALLOW-FROM\") === 0)\n      throw new Error(\"You can only specify one origin that is allowed to\" +\n                      \" frame this app.\");\n    xFrameOptions = \"ALLOW-FROM \" + origin;\n  },\n  allowAll: function () {\n    xFrameOptions = null;\n  }\n});\n"
  },
  {
    "path": "packages/browser-policy-framing/package.js",
    "content": "Package.describe({\n  summary: \"Restrict which websites can frame your app\",\n  version: \"1.0.11\"\n});\n\nPackage.onUse(function (api) {\n  api.imply([\"browser-policy-common\"], \"server\");\n  api.use([\"underscore\", \"browser-policy-common\"], \"server\");\n  api.addFiles(\"browser-policy-framing.js\", \"server\");\n});\n"
  },
  {
    "path": "packages/caching-compiler/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/caching-compiler/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/caching-compiler/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"async\": {\n      \"version\": \"1.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/async/-/async-1.4.0.tgz\",\n      \"from\": \"https://registry.npmjs.org/async/-/async-1.4.0.tgz\"\n    },\n    \"lru-cache\": {\n      \"version\": \"2.6.4\",\n      \"resolved\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.4.tgz\",\n      \"from\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.4.tgz\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/caching-compiler/README.md",
    "content": "# caching-compiler: caching superclasses for Plugin.registerCompiler\n\nCachingCompiler and MultiFileCachingCompiler are classes designed to be used\nwith Plugin.registerCompiler. They implement in-memory and on-disk caches for\nthe files that they process.\n\nCachingCompiler is for compilers whose files can be processed independently of\neach other (ie, editing one such file only requires that file to be\nrebuilt). MultiFileCachingCompiler is for compilers whose files can depend on\neach other, such as CSS preprocessors with `@import` directives.\n\nYou should subclass CachingCompiler and define the\nfollowing methods: `getCacheKey`, `compileOneFile`, `addCompileResult`, and\n`compileResultSize`.\n\n# CompileResult\n\nThe data that is cached for each file is of a type that is (implicitly) defined\nby your subclass. `caching-compiler` refers to this type as `CompileResult`, but\nthis isn't a single type: it's up to your subclass to decide what type of data\nthis is.  You should document what your subclass's `CompileResult` type is.\n\n# Example usage\n\nYour subclass's compiler should call the superclass compiler specifying the\ncompiler name (used to generate environment variables for debugging and tweaking\nin-memory cache size) and the default cache size.\n\nBy default, CachingCompiler processes each file in \"parallel\". That is, if it\nneeds to yield to read from the disk cache, or if getCacheKey, compileOneFile,\nor addCompileResult yields, it will start processing the next few files. To set\nhow many files can be processed in parallel (including setting it to 1 if your\nsubclass doesn't support any parallelism), pass the maxParallelism option to the\nsuperclass constructor.\n\nFor example (using ES2015 via the ecmascript package):\n\n```js\n// CompileResult is a {source, sourceMap} object.\nclass AwesomeCompiler extends CachingCompiler {\n  constructor() {\n    super({\n      compilerName: 'awesome',\n      defaultCacheSize: 1024*1024*10,\n    });\n  }\n  getCacheKey(inputFile) {\n    return inputFile.getSourceHash();\n  }\n  compileResultSize(compileResult) {\n    return compileResult.source.length + compileResult.sourceMap.length;\n  }\n  compileOneFile(inputFile) {\n    return Awesomifier.compile(inputFile.getContentsAsString());\n  }\n  addCompileResult(inputFile, compileResult) {\n    inputFile.addJavaScript({\n      path: inputFile.getPathInPackage() + '.js',\n      sourcePath: inputFile.getPathInPackage(),\n      data: compileResult.source,\n      sourceMap: compileResult.sourceMap,\n    });\n  }\n}\nPlugin.registerCompile({\n  extensions: ['awesome'],\n}, () => new AwesomeCompiler());\n```\n"
  },
  {
    "path": "packages/caching-compiler/caching-compiler.js",
    "content": "const fs = Plugin.fs;\nconst path = Plugin.path;\nconst createHash = Npm.require('crypto').createHash;\nconst assert = Npm.require('assert');\nconst Future = Npm.require('fibers/future');\nconst LRU = Npm.require('lru-cache');\nconst async = Npm.require('async');\n\n// Base class for CachingCompiler and MultiFileCachingCompiler.\nCachingCompilerBase = class CachingCompilerBase {\n  constructor({\n    compilerName,\n    defaultCacheSize,\n    maxParallelism = 20,\n  }) {\n    this._compilerName = compilerName;\n    this._maxParallelism = maxParallelism;\n    const envVarPrefix = 'METEOR_' + compilerName.toUpperCase() + '_CACHE_';\n\n    const debugEnvVar = envVarPrefix + 'DEBUG';\n    this._cacheDebugEnabled = !! process.env[debugEnvVar];\n\n    const cacheSizeEnvVar = envVarPrefix + 'SIZE';\n    this._cacheSize = +process.env[cacheSizeEnvVar] || defaultCacheSize;\n\n    this._diskCache = null;\n\n    // For testing.\n    this._callCount = 0;\n  }\n\n  // Your subclass must override this method to define the key used to identify\n  // a particular version of an InputFile.\n  //\n  // Given an InputFile (the data type passed to processFilesForTarget as part\n  // of the Plugin.registerCompiler API), returns a cache key that represents\n  // it. This cache key can be any JSON value (it will be converted internally\n  // into a hash).  This should reflect any aspect of the InputFile that affects\n  // the output of `compileOneFile`. Typically you'll want to include\n  // `inputFile.getDeclaredExports()`, and perhaps\n  // `inputFile.getPathInPackage()` or `inputFile.getDeclaredExports` if\n  // `compileOneFile` pays attention to them.\n  //\n  // Note that for MultiFileCachingCompiler, your cache key doesn't need to\n  // include the file's path, because that is automatically taken into account\n  // by the implementation. CachingCompiler subclasses can choose whether or not\n  // to include the file's path in the cache key.\n  getCacheKey(inputFile) {\n    throw Error('CachingCompiler subclass should implement getCacheKey!');\n  }\n\n  // Your subclass must override this method to define how a CompileResult\n  // translates into adding assets to the bundle.\n  //\n  // This method is given an InputFile (the data type passed to\n  // processFilesForTarget as part of the Plugin.registerCompiler API) and a\n  // CompileResult (either returned directly from compileOneFile or read from\n  // the cache).  It should call methods like `inputFile.addJavaScript`\n  // and `inputFile.error`.\n  addCompileResult(inputFile, compileResult) {\n    throw Error('CachingCompiler subclass should implement addCompileResult!');\n  }\n\n  // Your subclass must override this method to define the size of a\n  // CompilerResult (used by the in-memory cache to limit the total amount of\n  // data cached).\n  compileResultSize(compileResult) {\n    throw Error('CachingCompiler subclass should implement compileResultSize!');\n  }\n\n  // Your subclass may override this method to define an alternate way of\n  // stringifying CompilerResults.  Takes a CompileResult and returns a string.\n  stringifyCompileResult(compileResult) {\n    return JSON.stringify(compileResult);\n  }\n  // Your subclass may override this method to define an alternate way of\n  // parsing CompilerResults from string.  Takes a string and returns a\n  // CompileResult.  If the string doesn't represent a valid CompileResult, you\n  // may want to return null instead of throwing, which will make\n  // CachingCompiler ignore the cache.\n  parseCompileResult(stringifiedCompileResult) {\n    return this._parseJSONOrNull(stringifiedCompileResult);\n  }\n  _parseJSONOrNull(json) {\n    try {\n      return JSON.parse(json);\n    } catch (e) {\n      if (e instanceof SyntaxError)\n        return null;\n      throw e;\n    }\n  }\n\n  _cacheDebug(message) {\n    if (!this._cacheDebugEnabled)\n      return;\n    console.log(`CACHE(${ this._compilerName }): ${ message }`);\n  }\n\n  setDiskCacheDirectory(diskCache) {\n    if (this._diskCache)\n      throw Error('setDiskCacheDirectory called twice?');\n    this._diskCache = diskCache;\n  }\n\n  // Since so many compilers will need to calculate the size of a SourceMap in\n  // their compileResultSize, this method is provided.\n  sourceMapSize(sm) {\n    if (! sm) return 0;\n    // sum the length of sources and the mappings, the size of\n    // metadata is ignored, but it is not a big deal\n    return sm.mappings.length\n      + (sm.sourcesContent || []).reduce(function (soFar, current) {\n        return soFar + (current ? current.length : 0);\n      }, 0);\n  }\n\n  // Borrowed from another MIT-licensed project that benjamn wrote:\n  // https://github.com/reactjs/commoner/blob/235d54a12c/lib/util.js#L136-L168\n  _deepHash(val) {\n    const hash = createHash('sha1');\n    let type = typeof val;\n\n    if (val === null) {\n      type = 'null';\n    }\n    hash.update(type + '\\0');\n\n    switch (type) {\n    case 'object':\n      const keys = Object.keys(val);\n\n      // Array keys will already be sorted.\n      if (! Array.isArray(val)) {\n        keys.sort();\n      }\n\n      keys.forEach((key) => {\n        if (typeof val[key] === 'function') {\n          // Silently ignore nested methods, but nevertheless complain below\n          // if the root value is a function.\n          return;\n        }\n\n        hash.update(key + '\\0').update(this._deepHash(val[key]));\n      });\n\n      break;\n\n    case 'function':\n      assert.ok(false, 'cannot hash function objects');\n      break;\n\n    default:\n      hash.update('' + val);\n      break;\n    }\n\n    return hash.digest('hex');\n  }\n\n  // We want to write the file atomically. But we also don't want to block\n  // processing on the file write.\n  _writeFileAsync(filename, contents) {\n    const tempFilename = filename + '.tmp.' + Random.id();\n    fs.writeFile(tempFilename, contents, (err) => {\n      // ignore errors, it's just a cache\n      if (err) {\n        return;\n      }\n      fs.rename(tempFilename, filename, (err) => {\n        // ignore this error too.\n      });\n    });\n  }\n\n  // Helper function. Returns the body of the file as a string, or null if it\n  // doesn't exist.\n  _readFileOrNull(filename) {\n    try {\n      return fs.readFileSync(filename, 'utf8');\n    } catch (e) {\n      if (e && e.code === 'ENOENT')\n        return null;\n      throw e;\n    }\n  }\n}\n\n// CachingCompiler is a class designed to be used with Plugin.registerCompiler\n// which implements in-memory and on-disk caches for the files that it\n// processes.  You should subclass CachingCompiler and define the following\n// methods: getCacheKey, compileOneFile, addCompileResult, and\n// compileResultSize.\n//\n// CachingCompiler assumes that files are processed independently of each other;\n// there is no 'import' directive allowing one file to reference another.  That\n// is, editing one file should only require that file to be rebuilt, not other\n// files.\n//\n// The data that is cached for each file is of a type that is (implicitly)\n// defined by your subclass. CachingCompiler refers to this type as\n// `CompileResult`, but this isn't a single type: it's up to your subclass to\n// decide what type of data this is.  You should document what your subclass's\n// CompileResult type is.\n//\n// Your subclass's compiler should call the superclass compiler specifying the\n// compiler name (used to generate environment variables for debugging and\n// tweaking in-memory cache size) and the default cache size.\n//\n// By default, CachingCompiler processes each file in \"parallel\". That is, if it\n// needs to yield to read from the disk cache, or if getCacheKey,\n// compileOneFile, or addCompileResult yields, it will start processing the next\n// few files. To set how many files can be processed in parallel (including\n// setting it to 1 if your subclass doesn't support any parallelism), pass the\n// maxParallelism option to the superclass constructor.\n//\n// For example (using ES2015 via the ecmascript package):\n//\n//   class AwesomeCompiler extends CachingCompiler {\n//     constructor() {\n//       super({\n//         compilerName: 'awesome',\n//         defaultCacheSize: 1024*1024*10,\n//       });\n//     }\n//     // ... define the other methods\n//   }\n//   Plugin.registerCompile({\n//     extensions: ['awesome'],\n//   }, () => new AwesomeCompiler());\n//\n// XXX maybe compileResultSize and stringifyCompileResult should just be methods\n// on CompileResult? Sort of hard to do that with parseCompileResult.\nCachingCompiler = class CachingCompiler extends CachingCompilerBase {\n  constructor({\n    compilerName,\n    defaultCacheSize,\n    maxParallelism = 20,\n  }) {\n    super({compilerName, defaultCacheSize, maxParallelism});\n\n    // Maps from a hashed cache key to a compileResult.\n    this._cache = new LRU({\n      max: this._cacheSize,\n      length: (value) => this.compileResultSize(value),\n    });\n  }\n\n  // Your subclass must override this method to define the transformation from\n  // InputFile to its cacheable CompileResult).\n  //\n  // Given an InputFile (the data type passed to processFilesForTarget as part\n  // of the Plugin.registerCompiler API), compiles the file and returns a\n  // CompileResult (the cacheable data type specific to your subclass).\n  //\n  // This method is not called on files when a valid cache entry exists in\n  // memory or on disk.\n  //\n  // On a compile error, you should call `inputFile.error` appropriately and\n  // return null; this will not be cached.\n  //\n  // This method should not call `inputFile.addJavaScript` and similar files!\n  // That's what addCompileResult is for.\n  compileOneFile(inputFile) {\n    throw Error('CachingCompiler subclass should implement compileOneFile!');\n  }\n\n  // The processFilesForTarget method from the Plugin.registerCompiler API. If\n  // you have processing you want to perform at the beginning or end of a\n  // processing phase, you may want to override this method and call the\n  // superclass implementation from within your method.\n  processFilesForTarget(inputFiles) {\n    const cacheMisses = [];\n\n    const future = new Future;\n    async.eachLimit(inputFiles, this._maxParallelism, (inputFile, cb) => {\n      let error = null;\n      try {\n        const cacheKey = this._deepHash(this.getCacheKey(inputFile));\n        let compileResult = this._cache.get(cacheKey);\n\n        if (! compileResult) {\n          compileResult = this._readCache(cacheKey);\n          if (compileResult) {\n            this._cacheDebug(`Loaded ${ inputFile.getDisplayPath() }`);\n          }\n        }\n\n        if (! compileResult) {\n          cacheMisses.push(inputFile.getDisplayPath());\n          compileResult = this.compileOneFile(inputFile);\n\n          if (! compileResult) {\n            // compileOneFile should have called inputFile.error.\n            //  We don't cache failures for now.\n            return;\n          }\n\n          // Save what we've compiled.\n          this._cache.set(cacheKey, compileResult);\n          this._writeCacheAsync(cacheKey, compileResult);\n        }\n\n        this.addCompileResult(inputFile, compileResult);\n      } catch (e) {\n        error = e;\n      } finally {\n        cb(error);\n      }\n    }, future.resolver());\n    future.wait();\n\n    if (this._cacheDebugEnabled) {\n      cacheMisses.sort();\n      this._cacheDebug(\n        `Ran (#${ ++this._callCount }) on: ${ JSON.stringify(cacheMisses) }`);\n    }\n  }\n\n  _cacheFilename(cacheKey) {\n    // We want cacheKeys to be hex so that they work on any FS and never end in\n    // .cache.\n    if (!/^[a-f0-9]+$/.test(cacheKey)) {\n      throw Error('bad cacheKey: ' + cacheKey);\n    }\n    return path.join(this._diskCache, cacheKey + '.cache');\n  }\n  // Load a cache entry from disk. Returns the compileResult object\n  // and loads it into the in-memory cache too.\n  _readCache(cacheKey) {\n    if (! this._diskCache) {\n      return null;\n    }\n    const cacheFilename = this._cacheFilename(cacheKey);\n    const compileResult = this._readAndParseCompileResultOrNull(cacheFilename);\n    if (! compileResult) {\n      return null;\n    }\n    this._cache.set(cacheKey, compileResult);\n    return compileResult;\n  }\n  _writeCacheAsync(cacheKey, compileResult) {\n    if (! this._diskCache)\n      return;\n    const cacheFilename = this._cacheFilename(cacheKey);\n    const cacheContents = this.stringifyCompileResult(compileResult);\n    this._writeFileAsync(cacheFilename, cacheContents);\n  }\n\n  // Returns null if the file does not exist or can't be parsed; otherwise\n  // returns the parsed compileResult in the file.\n  _readAndParseCompileResultOrNull(filename) {\n    const raw = this._readFileOrNull(filename);\n    return this.parseCompileResult(raw);\n  }\n}\n"
  },
  {
    "path": "packages/caching-compiler/multi-file-caching-compiler.js",
    "content": "const path = Plugin.path;\nconst Future = Npm.require('fibers/future');\nconst LRU = Npm.require('lru-cache');\nconst async = Npm.require('async');\n\n// MultiFileCachingCompiler is like CachingCompiler, but for implementing\n// languages which allow files to reference each other, such as CSS\n// preprocessors with `@import` directives.\n//\n// Like CachingCompiler, you should subclass MultiFileCachingCompiler and define\n// the following methods: getCacheKey, compileOneFile, addCompileResult, and\n// compileResultSize.  compileOneFile gets an additional allFiles argument and\n// returns an array of referenced import paths in addition to the CompileResult.\n// You may also override isRoot and getAbsoluteImportPath to customize\n// MultiFileCachingCompiler further.\nMultiFileCachingCompiler = class MultiFileCachingCompiler\nextends CachingCompilerBase {\n  constructor({\n    compilerName,\n    defaultCacheSize,\n    maxParallelism\n  }) {\n    super({compilerName, defaultCacheSize, maxParallelism});\n\n    // Maps from absolute import path to { compileResult, cacheKeys }, where\n    // cacheKeys is an object mapping from absolute import path to hashed\n    // cacheKey for each file referenced by this file (including itself).\n    this._cache = new LRU({\n      max: this._cacheSize,\n      // We ignore the size of cacheKeys here.\n      length: (value) => this.compileResultSize(value.compileResult),\n    });\n  }\n\n  // Your subclass must override this method to define the transformation from\n  // InputFile to its cacheable CompileResult).\n  //\n  // Arguments:\n  //   - inputFile is the InputFile to process\n  //   - allFiles is a a Map mapping from absolute import path to InputFile of\n  //     all files being processed in the target\n  // Returns an object with keys:\n  //   - compileResult: the CompileResult (the cacheable data type specific to\n  //     your subclass).\n  //   - referencedImportPaths: an array of absolute import paths of files\n  //     which were refererenced by the current file.  The current file\n  //     is included implicitly.\n  //\n  // This method is not called on files when a valid cache entry exists in\n  // memory or on disk.\n  //\n  // On a compile error, you should call `inputFile.error` appropriately and\n  // return null; this will not be cached.\n  //\n  // This method should not call `inputFile.addJavaScript` and similar files!\n  // That's what addCompileResult is for.\n  compileOneFile(inputFile, allFiles) {\n    throw Error(\n      'MultiFileCachingCompiler subclass should implement compileOneFile!');\n  }\n\n  // Your subclass may override this to declare that a file is not a \"root\" ---\n  // ie, it can be included from other files but is not processed on its own. In\n  // this case, MultiFileCachingCompiler won't waste time trying to look for a\n  // cache for its compilation on disk.\n  isRoot(inputFile) {\n    return true;\n  }\n\n  // Returns the absolute import path for an InputFile. By default, this is a\n  // path is a path of the form \"{package}/path/to/file\" for files in packages\n  // and \"{}/path/to/file\" for files in apps. Your subclass may override and/or\n  // call this method.\n  getAbsoluteImportPath(inputFile) {\n    if (inputFile.getPackageName() === null) {\n      return '{}/' + inputFile.getPathInPackage();\n    }\n    return '{' + inputFile.getPackageName() + '}/'\n      + inputFile.getPathInPackage();\n  }\n\n  // The processFilesForTarget method from the Plugin.registerCompiler API.\n  processFilesForTarget(inputFiles) {\n    const allFiles = new Map;\n    const cacheKeyMap = new Map;\n    const cacheMisses = [];\n\n    inputFiles.forEach((inputFile) => {\n      const importPath = this.getAbsoluteImportPath(inputFile);\n      allFiles.set(importPath, inputFile);\n      cacheKeyMap.set(importPath, this._deepHash(this.getCacheKey(inputFile)));\n    });\n\n    const allProcessedFuture = new Future;\n    async.eachLimit(inputFiles, this._maxParallelism, (inputFile, cb) => {\n      let error = null;\n      try {\n        // If this isn't a root, skip it (and definitely don't waste time\n        // looking for a cache file that won't be there).\n        if (!this.isRoot(inputFile)) {\n          return;\n        }\n\n        const absoluteImportPath = this.getAbsoluteImportPath(inputFile);\n        let cacheEntry = this._cache.get(absoluteImportPath);\n        if (! cacheEntry) {\n          cacheEntry = this._readCache(absoluteImportPath);\n          if (cacheEntry) {\n            this._cacheDebug(`Loaded ${ absoluteImportPath }`);\n          }\n        }\n        if (! (cacheEntry && this._cacheEntryValid(cacheEntry, cacheKeyMap))) {\n          cacheMisses.push(inputFile.getDisplayPath());\n\n          const compileOneFileReturn = this.compileOneFile(inputFile, allFiles);\n          if (! compileOneFileReturn) {\n            // compileOneFile should have called inputFile.error.\n            //  We don't cache failures for now.\n            return;\n          }\n          const {compileResult, referencedImportPaths} = compileOneFileReturn;\n\n          cacheEntry = {\n            compileResult,\n            cacheKeys: {\n              // Include the hashed cache key of the file itself...\n              [absoluteImportPath]: cacheKeyMap.get(absoluteImportPath)\n            }\n          };\n\n          // ... and of the other referenced files.\n          referencedImportPaths.forEach((path) => {\n            if (!cacheKeyMap.has(path)) {\n              throw Error(`Unknown absolute import path ${ path }`);\n            }\n            cacheEntry.cacheKeys[path] = cacheKeyMap.get(path);\n          });\n\n          // Save the cache entry.\n          this._cache.set(absoluteImportPath, cacheEntry);\n          this._writeCacheAsync(absoluteImportPath, cacheEntry);\n        }\n\n        this.addCompileResult(inputFile, cacheEntry.compileResult);\n      } catch (e) {\n        error = e;\n      } finally {\n        cb(error);\n      }\n    }, allProcessedFuture.resolver());\n    allProcessedFuture.wait();\n\n    if (this._cacheDebugEnabled) {\n      cacheMisses.sort();\n      this._cacheDebug(\n        `Ran (#${ ++this._callCount }) on: ${ JSON.stringify(cacheMisses) }`);\n    }\n  }\n\n  _cacheEntryValid(cacheEntry, cacheKeyMap) {\n    return Object.keys(cacheEntry.cacheKeys).every(\n      (path) => cacheEntry.cacheKeys[path] === cacheKeyMap.get(path)\n    );\n  }\n\n  // The format of a cache file on disk is the JSON-stringified cacheKeys\n  // object, a newline, followed by the CompileResult as returned from\n  // this.stringifyCompileResult.\n  _cacheFilename(absoluteImportPath) {\n    return path.join(this._diskCache,\n                     this._deepHash(absoluteImportPath) + '.cache');\n  }\n  // Loads a {compileResult, cacheKeys} cache entry from disk. Returns the whole\n  // cache entry and loads it into the in-memory cache too.\n  _readCache(absoluteImportPath) {\n    if (! this._diskCache) {\n      return null;\n    }\n    const cacheFilename = this._cacheFilename(absoluteImportPath);\n    const raw = this._readFileOrNull(cacheFilename);\n    if (!raw) {\n      return null;\n    }\n\n    // Split on newline.\n    const newlineIndex = raw.indexOf('\\n');\n    if (newlineIndex === -1) {\n      return null;\n    }\n    const cacheKeysString = raw.substring(0, newlineIndex);\n    const compileResultString = raw.substring(newlineIndex + 1);\n\n    const cacheKeys = this._parseJSONOrNull(cacheKeysString);\n    if (!cacheKeys) {\n      return null;\n    }\n    const compileResult = this.parseCompileResult(compileResultString);\n    if (! compileResult) {\n      return null;\n    }\n\n    const cacheEntry = {compileResult, cacheKeys};\n    this._cache.set(absoluteImportPath, cacheEntry);\n    return cacheEntry;\n  }\n  _writeCacheAsync(absoluteImportPath, cacheEntry) {\n    if (! this._diskCache) {\n      return null;\n    }\n    const cacheFilename = this._cacheFilename(absoluteImportPath);\n    const cacheContents =\n            JSON.stringify(cacheEntry.cacheKeys) + '\\n'\n            + this.stringifyCompileResult(cacheEntry.compileResult);\n    this._writeFileAsync(cacheFilename, cacheContents);\n  }\n}\n"
  },
  {
    "path": "packages/caching-compiler/package.js",
    "content": "Package.describe({\n  name: 'caching-compiler',\n  version: '1.0.5_1',\n  summary: 'An easy way to make compiler plugins cache',\n  documentation: 'README.md'\n});\n\nNpm.depends({'lru-cache': '2.6.4',\n             'async': '1.4.0'});\n\nPackage.onUse(function(api) {\n  api.use(['ecmascript', 'random']);\n  api.addFiles(['caching-compiler.js'], 'server');\n  api.addFiles(['multi-file-caching-compiler.js'], 'server');\n  api.export(['CachingCompiler', 'MultiFileCachingCompiler'], 'server');\n});\n"
  },
  {
    "path": "packages/caching-html-compiler/README.md",
    "content": "# caching-html-compiler\n\nProvides a pluggable class used to compile HTML-style templates in Meteor build plugins. This abstracts out a lot of the functionality you would need to implement the following plugins:\n\n1. `templating`\n2. `static-html`\n3. `simple:markdown-templating`\n\nIt provides automatic caching and handles communicating with the build plugin APIs. The actual functions that convert HTML into compiled form are passed in as arguments into the constructor, allowing those functions to be unit tested separately from the caching and file system functionality.\n\n-------\n\n### new CachingHtmlCompiler(name, tagScannerFunc, tagHandlerFunc)\n\nConstructs a new CachingHtmlCompiler that can be passed into `Plugin.registerCompiler`.\n\n#### Arguments\n\n1. `name` The name of the compiler, used when printing errors. Should probably be the same as the name of the build plugin and package it is used in.\n2. `tagScannerFunc` A function that takes a string representing a template file as input, and returns an array of Tag objects. See the README for `templating-tools` for more information about the Tag object.\n3. `tagHandlerFunc` A function that takes an array of Tag objects (the output of the previous argument) and returns an object with `js`, `body`, `head`, and `bodyAttr` properties, which will be added to the app through the build plugin API.\n\n#### Example\n\nHere is some example code from the `templating` package:\n\n```js\nPlugin.registerCompiler({\n  extensions: ['html'],\n  archMatching: 'web',\n  isTemplate: true\n}, () => new CachingHtmlCompiler(\n  \"templating\",\n  TemplatingTools.scanHtmlForTags,\n  TemplatingTools.compileTagsWithSpacebars\n));\n```\n"
  },
  {
    "path": "packages/caching-html-compiler/caching-html-compiler.js",
    "content": "const path = Plugin.path;\n\n// The CompileResult type for this CachingCompiler is the return value of\n// htmlScanner.scan: a {js, head, body, bodyAttrs} object.\nCachingHtmlCompiler = class CachingHtmlCompiler extends CachingCompiler {\n  /**\n   * Constructor for CachingHtmlCompiler\n   * @param  {String} name The name of the compiler, printed in errors -\n   * should probably always be the same as the name of the build\n   * plugin/package\n   * @param  {Function} tagScannerFunc Transforms a template file (commonly\n   * .html) into an array of Tags\n   * @param  {Function} tagHandlerFunc Transforms an array of tags into a\n   * results object with js, body, head, and bodyAttrs properties\n   */\n  constructor(name, tagScannerFunc, tagHandlerFunc) {\n    super({\n      compilerName: name,\n      defaultCacheSize: 1024*1024*10,\n    });\n\n    this._bodyAttrInfo = null;\n\n    this.tagScannerFunc = tagScannerFunc;\n    this.tagHandlerFunc = tagHandlerFunc;\n  }\n\n  // Implements method from CachingCompilerBase\n  compileResultSize(compileResult) {\n    function lengthOrZero(field) {\n      return field ? field.length : 0;\n    }\n    return lengthOrZero(compileResult.head) + lengthOrZero(compileResult.body) +\n      lengthOrZero(compileResult.js);\n  }\n\n  // Overrides method from CachingCompiler\n  processFilesForTarget(inputFiles) {\n    this._bodyAttrInfo = {};\n    super.processFilesForTarget(inputFiles);\n  }\n\n  // Implements method from CachingCompilerBase\n  getCacheKey(inputFile) {\n    // Note: the path is only used for errors, so it doesn't have to be part\n    // of the cache key.\n    return inputFile.getSourceHash();\n  }\n\n  // Implements method from CachingCompiler\n  compileOneFile(inputFile) {\n    const contents = inputFile.getContentsAsString();\n    const inputPath = inputFile.getPathInPackage();\n    try {\n      const tags = this.tagScannerFunc({\n        sourceName: inputPath,\n        contents: contents,\n        tagNames: [\"body\", \"head\", \"template\"]\n      });\n\n      return this.tagHandlerFunc(tags);\n    } catch (e) {\n      if (e instanceof TemplatingTools.CompileError) {\n        inputFile.error({\n          message: e.message,\n          line: e.line\n        });\n        return null;\n      } else {\n        throw e;\n      }\n    }\n  }\n\n  // Implements method from CachingCompilerBase\n  addCompileResult(inputFile, compileResult) {\n    let allJavaScript = \"\";\n\n    if (compileResult.head) {\n      inputFile.addHtml({ section: \"head\", data: compileResult.head });\n    }\n\n    if (compileResult.body) {\n      inputFile.addHtml({ section: \"body\", data: compileResult.body });\n    }\n\n    if (compileResult.js) {\n      allJavaScript += compileResult.js;\n    }\n\n    if (! _.isEmpty(compileResult.bodyAttrs)) {\n      Object.keys(compileResult.bodyAttrs).forEach((attr) => {\n        const value = compileResult.bodyAttrs[attr];\n        if (this._bodyAttrInfo.hasOwnProperty(attr) &&\n            this._bodyAttrInfo[attr].value !== value) {\n          // two conflicting attributes on <body> tags in two different template\n          // files\n          inputFile.error({\n            message:\n            `<body> declarations have conflicting values for the '${ attr }' ` +\n              `attribute in the following files: ` +\n              this._bodyAttrInfo[attr].inputFile.getPathInPackage() +\n              `, ${ inputFile.getPathInPackage() }`\n          });\n        } else {\n          this._bodyAttrInfo[attr] = {inputFile, value};\n        }\n      });\n\n      // Add JavaScript code to set attributes on body\n      allJavaScript +=\n`Meteor.startup(function() {\n  var attrs = ${JSON.stringify(compileResult.bodyAttrs)};\n  for (var prop in attrs) {\n    document.body.setAttribute(prop, attrs[prop]);\n  }\n});\n`;\n    }\n    \n\n    if (allJavaScript) {\n      const filePath = inputFile.getPathInPackage();\n      // XXX this path manipulation may be unnecessarily complex\n      let pathPart = path.dirname(filePath);\n      if (pathPart === '.')\n        pathPart = '';\n      if (pathPart.length && pathPart !== path.sep)\n        pathPart = pathPart + path.sep;\n      const ext = path.extname(filePath);\n      const basename = path.basename(filePath, ext);\n\n      // XXX generate a source map\n\n      inputFile.addJavaScript({\n        path: path.join(pathPart, \"template.\" + basename + \".js\"),\n        data: allJavaScript\n      });\n    }\n  }\n}\n"
  },
  {
    "path": "packages/caching-html-compiler/package.js",
    "content": "Package.describe({\n  version: '1.0.6',\n  // Brief, one-line summary of the package.\n  summary: 'Pluggable class for compiling HTML into templates',\n  // By default, Meteor will default to using README.md for documentation.\n  // To avoid submitting documentation, set this field to null.\n  documentation: 'README.md'\n});\n\nPackage.onUse(function(api) {\n  api.use([\n    'underscore',\n    'caching-compiler',\n    'templating-tools',\n    'ecmascript'\n  ]);\n\n  api.addFiles('caching-html-compiler.js', 'server');\n\n  api.export(\"CachingHtmlCompiler\", 'server');\n});\n"
  },
  {
    "path": "packages/callback-hook/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/callback-hook/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/callback-hook/hook.js",
    "content": "// XXX This pattern is under development. Do not add more callsites\n// using this package for now. See:\n// https://meteor.hackpad.com/Design-proposal-Hooks-YxvgEW06q6f\n//\n// Encapsulates the pattern of registering callbacks on a hook.\n//\n// The `each` method of the hook calls its iterator function argument\n// with each registered callback.  This allows the hook to\n// conditionally decide not to call the callback (if, for example, the\n// observed object has been closed or terminated).\n//\n// By default, callbacks are bound with `Meteor.bindEnvironment`, so they will be\n// called with the Meteor environment of the calling code that\n// registered the callback. Override by passing { bindEnvironment: false }\n// to the constructor.\n//\n// Registering a callback returns an object with a single `stop`\n// method which unregisters the callback.\n//\n// The code is careful to allow a callback to be safely unregistered\n// while the callbacks are being iterated over.\n//\n// If the hook is configured with the `exceptionHandler` option, the\n// handler will be called if a called callback throws an exception.\n// By default (if the exception handler doesn't itself throw an\n// exception, or if the iterator function doesn't return a falsy value\n// to terminate the calling of callbacks), the remaining callbacks\n// will still be called.\n//\n// Alternatively, the `debugPrintExceptions` option can be specified\n// as string describing the callback.  On an exception the string and\n// the exception will be printed to the console log with\n// `Meteor._debug`, and the exception otherwise ignored.\n//\n// If an exception handler isn't specified, exceptions thrown in the\n// callback will propagate up to the iterator function, and will\n// terminate calling the remaining callbacks if not caught.\n\nHook = function (options) {\n  var self = this;\n  options = options || {};\n  self.nextCallbackId = 0;\n  self.callbacks = {};\n  // Whether to wrap callbacks with Meteor.bindEnvironment\n  self.bindEnvironment = true;\n  if (options.bindEnvironment === false)\n    self.bindEnvironment = false;\n\n  if (options.exceptionHandler)\n    self.exceptionHandler = options.exceptionHandler;\n  else if (options.debugPrintExceptions) {\n    if (! _.isString(options.debugPrintExceptions))\n      throw new Error(\"Hook option debugPrintExceptions should be a string\");\n    self.exceptionHandler = options.debugPrintExceptions;\n  }\n};\n\n_.extend(Hook.prototype, {\n  register: function (callback) {\n    var self = this;\n    var exceptionHandler =  self.exceptionHandler || function (exception) {\n      // Note: this relies on the undocumented fact that if bindEnvironment's\n      // onException throws, and you are invoking the callback either in the\n      // browser or from within a Fiber in Node, the exception is propagated.\n      throw exception;\n    };\n\n    if (self.bindEnvironment) {\n      callback = Meteor.bindEnvironment(callback, exceptionHandler);\n    } else {\n      callback = dontBindEnvironment(callback, exceptionHandler);\n    }\n\n    var id = self.nextCallbackId++;\n    self.callbacks[id] = callback;\n\n    return {\n      stop: function () {\n        delete self.callbacks[id];\n      }\n    };\n  },\n\n  // For each registered callback, call the passed iterator function\n  // with the callback.\n  //\n  // The iterator function can choose whether or not to call the\n  // callback.  (For example, it might not call the callback if the\n  // observed object has been closed or terminated).\n  //\n  // The iteration is stopped if the iterator function returns a falsy\n  // value or throws an exception.\n  //\n  each: function (iterator) {\n    var self = this;\n\n    // Invoking bindEnvironment'd callbacks outside of a Fiber in Node doesn't\n    // run them to completion (and exceptions thrown from onException are not\n    // propagated), so we need to be in a Fiber.\n    Meteor._nodeCodeMustBeInFiber();\n\n    var ids = _.keys(self.callbacks);\n    for (var i = 0;  i < ids.length;  ++i) {\n      var id = ids[i];\n      // check to see if the callback was removed during iteration\n      if (_.has(self.callbacks, id)) {\n        var callback = self.callbacks[id];\n\n        if (! iterator(callback))\n          break;\n      }\n    }\n  }\n});\n\n// Copied from Meteor.bindEnvironment and removed all the env stuff.\nvar dontBindEnvironment = function (func, onException, _this) {\n  if (!onException || typeof(onException) === 'string') {\n    var description = onException || \"callback of async function\";\n    onException = function (error) {\n      Meteor._debug(\n        \"Exception in \" + description + \":\",\n        error && error.stack || error\n      );\n    };\n  }\n\n  return function (/* arguments */) {\n    var args = _.toArray(arguments);\n\n    var runAndHandleExceptions = function () {\n      try {\n        var ret = func.apply(_this, args);\n      } catch (e) {\n        onException(e);\n      }\n      return ret;\n    };\n\n    return runAndHandleExceptions();\n  };\n};\n"
  },
  {
    "path": "packages/callback-hook/hook_tests.js",
    "content": "Tinytest.add(\"callback-hook - binds to registrar's env by default\", function (test) {\n  var hook = new Hook();\n  var envVar = new Meteor.EnvironmentVariable;\n  envVar.withValue(\"registrar's value\", function() {\n    hook.register(function() {\n      test.equal(envVar.get(), \"registrar's value\");\n    });\n  });\n  envVar.withValue(\"invoker's value\", function() {\n    hook.each(function(callback) {\n      callback();\n    });\n  });\n});\n\nTinytest.add(\"callback-hook - uses invoker's env with {bindEnvironment: false}\", function (test) {\n  var hook = new Hook({ bindEnvironment: false });\n  var envVar = new Meteor.EnvironmentVariable;\n  envVar.withValue(\"registrar's value\", function() {\n    hook.register(function() {\n      test.equal(envVar.get(), \"invoker's value\");\n    });\n  });\n  envVar.withValue(\"invoker's value\", function() {\n    hook.each(function(callback) {\n      callback();\n    });\n  });\n});\n\nTinytest.add(\"callback-hook - exceptions unhandled with {bindEnvironment: false}\", function (test) {\n  var hook = new Hook({ bindEnvironment: false });\n  hook.register(function() {\n    throw new Error(\"Test error\");\n  });\n  hook.each(function(callback) {\n    test.throws(callback, \"Test error\");\n  });\n});\n\nTinytest.add(\"callback-hook - exceptionHandler used with {bindEnvironment: false}\", function (test) {\n  var exToThrow = new Error(\"Test error\");\n  var thrownEx = null;\n  var hook = new Hook({\n    bindEnvironment: false,\n    exceptionHandler: function (ex) { thrownEx = ex; }\n  });\n  hook.register(function() {\n    throw exToThrow;\n  });\n  hook.each(function(callback) {\n    callback();\n  });\n  test.equal(exToThrow, thrownEx);\n});\n"
  },
  {
    "path": "packages/callback-hook/package.js",
    "content": "Package.describe({\n  summary: \"Register callbacks on a hook\",\n  version: '1.0.9'\n});\n\nPackage.onUse(function (api) {\n  api.use('underscore', ['client', 'server']);\n\n  api.export('Hook');\n\n  api.addFiles('hook.js', ['client', 'server']);\n});\n\nPackage.onTest(function (api) {\n  api.use('callback-hook');\n  api.use('tinytest');\n  api.addFiles('hook_tests.js', 'server');\n});\n"
  },
  {
    "path": "packages/check/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/check/README.md",
    "content": "# check\n\n`check` is a lightweight package for argument checking and general pattern matching. Use it like this:\n\n```\nMeteor.publish(\"chats-in-room\", function (roomId) {\n  // Make sure roomId is a string, not an arbitrary mongo selector object.\n  check(roomId, String);\n  return Chats.find({room: roomId});\n});\n\nMeteor.methods({addChat: function (roomId, message) {\n  check(roomId, String);\n  check(message, {\n    text: String,\n    timestamp: Date,\n    // Optional, but if present must be an array of strings.\n    tags: Match.Optional([String])\n  });\n\n  // ... do something with the message ...\n}});\n```\n\nFor more details see the [`check` section](http://docs.meteor.com/#check_package) of the Meteor docs."
  },
  {
    "path": "packages/check/isPlainObject.js",
    "content": "// Copy of jQuery.isPlainObject for the server side from jQuery v1.11.2.\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar support = {};\n\n// Populate the class2type map\n_.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(name, i) {\n  class2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nfunction type( obj ) {\n  if ( obj == null ) {\n    return obj + \"\";\n  }\n  return typeof obj === \"object\" || typeof obj === \"function\" ?\n    class2type[ toString.call(obj) ] || \"object\" :\n    typeof obj;\n}\n\nfunction isWindow( obj ) {\n  /* jshint eqeqeq: false */\n  return obj != null && obj == obj.window;\n}\n\nexports.isPlainObject = function( obj ) {\n  var key;\n\n  // Must be an Object.\n  // Because of IE, we also have to check the presence of the constructor property.\n  // Make sure that DOM nodes and window objects don't pass through, as well\n  if ( !obj || type(obj) !== \"object\" || obj.nodeType || isWindow( obj ) ) {\n    return false;\n  }\n\n  try {\n    // Not own constructor property must be Object\n    if ( obj.constructor &&\n         !hasOwn.call(obj, \"constructor\") &&\n         !hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n      return false;\n    }\n  } catch ( e ) {\n    // IE8,9 Will throw exceptions on certain host objects #9897\n    return false;\n  }\n\n  // Support: IE<9\n  // Handle iteration over inherited properties before own properties.\n  if ( support.ownLast ) {\n    for ( key in obj ) {\n      return hasOwn.call( obj, key );\n    }\n  }\n\n  // Own properties are enumerated firstly, so to speed up,\n  // if last one is own, then all properties are own.\n  for ( key in obj ) {}\n\n  return key === undefined || hasOwn.call( obj, key );\n};\n"
  },
  {
    "path": "packages/check/match.js",
    "content": "// XXX docs\n\n// Things we explicitly do NOT support:\n//    - heterogenous arrays\n\nvar currentArgumentChecker = new Meteor.EnvironmentVariable;\nvar isPlainObject = require(\"./isPlainObject.js\").isPlainObject;\n\n/**\n * @summary Check that a value matches a [pattern](#matchpatterns).\n * If the value does not match the pattern, throw a `Match.Error`.\n *\n * Particularly useful to assert that arguments to a function have the right\n * types and structure.\n * @locus Anywhere\n * @param {Any} value The value to check\n * @param {MatchPattern} pattern The pattern to match\n * `value` against\n */\nvar check = exports.check = function (value, pattern) {\n  // Record that check got called, if somebody cared.\n  //\n  // We use getOrNullIfOutsideFiber so that it's OK to call check()\n  // from non-Fiber server contexts; the downside is that if you forget to\n  // bindEnvironment on some random callback in your method/publisher,\n  // it might not find the argumentChecker and you'll get an error about\n  // not checking an argument that it looks like you're checking (instead\n  // of just getting a \"Node code must run in a Fiber\" error).\n  var argChecker = currentArgumentChecker.getOrNullIfOutsideFiber();\n  if (argChecker)\n    argChecker.checking(value);\n  var result = testSubtree(value, pattern);\n  if (result) {\n    var err = new Match.Error(result.message);\n    if (result.path) {\n      err.message += \" in field \" + result.path;\n      err.path = result.path;\n    }\n    throw err;\n  }\n};\n\n/**\n * @namespace Match\n * @summary The namespace for all Match types and methods.\n */\nvar Match = exports.Match = {\n  Optional: function (pattern) {\n    return new Optional(pattern);\n  },\n  Maybe: function (pattern) {\n    return new Maybe(pattern);\n  },\n  OneOf: function (/*arguments*/) {\n    return new OneOf(_.toArray(arguments));\n  },\n  Any: ['__any__'],\n  Where: function (condition) {\n    return new Where(condition);\n  },\n  ObjectIncluding: function (pattern) {\n    return new ObjectIncluding(pattern);\n  },\n  ObjectWithValues: function (pattern) {\n    return new ObjectWithValues(pattern);\n  },\n  // Matches only signed 32-bit integers\n  Integer: ['__integer__'],\n\n  // XXX matchers should know how to describe themselves for errors\n  Error: Meteor.makeErrorType(\"Match.Error\", function (msg) {\n    this.message = \"Match error: \" + msg;\n    // The path of the value that failed to match. Initially empty, this gets\n    // populated by catching and rethrowing the exception as it goes back up the\n    // stack.\n    // E.g.: \"vals[3].entity.created\"\n    this.path = \"\";\n    // If this gets sent over DDP, don't give full internal details but at least\n    // provide something better than 500 Internal server error.\n    this.sanitizedError = new Meteor.Error(400, \"Match failed\");\n  }),\n\n  // Tests to see if value matches pattern. Unlike check, it merely returns true\n  // or false (unless an error other than Match.Error was thrown). It does not\n  // interact with _failIfArgumentsAreNotAllChecked.\n  // XXX maybe also implement a Match.match which returns more information about\n  //     failures but without using exception handling or doing what check()\n  //     does with _failIfArgumentsAreNotAllChecked and Meteor.Error conversion\n\n  /**\n   * @summary Returns true if the value matches the pattern.\n   * @locus Anywhere\n   * @param {Any} value The value to check\n   * @param {MatchPattern} pattern The pattern to match `value` against\n   */\n  test: function (value, pattern) {\n    return !testSubtree(value, pattern);\n  },\n\n  // Runs `f.apply(context, args)`. If check() is not called on every element of\n  // `args` (either directly or in the first level of an array), throws an error\n  // (using `description` in the message).\n  //\n  _failIfArgumentsAreNotAllChecked: function (f, context, args, description) {\n    var argChecker = new ArgumentChecker(args, description);\n    var result = currentArgumentChecker.withValue(argChecker, function () {\n      return f.apply(context, args);\n    });\n    // If f didn't itself throw, make sure it checked all of its arguments.\n    argChecker.throwUnlessAllArgumentsHaveBeenChecked();\n    return result;\n  }\n};\n\nvar Optional = function (pattern) {\n  this.pattern = pattern;\n};\n\nvar Maybe = function (pattern) {\n  this.pattern = pattern;\n};\n\nvar OneOf = function (choices) {\n  if (_.isEmpty(choices))\n    throw new Error(\"Must provide at least one choice to Match.OneOf\");\n  this.choices = choices;\n};\n\nvar Where = function (condition) {\n  this.condition = condition;\n};\n\nvar ObjectIncluding = function (pattern) {\n  this.pattern = pattern;\n};\n\nvar ObjectWithValues = function (pattern) {\n  this.pattern = pattern;\n};\n\nvar stringForErrorMessage = function (value, options) {\n  options = options || {};\n\n  if ( value === null ) return \"null\";\n\n  if ( options.onlyShowType ) {\n    return typeof value;\n  }\n\n  // Your average non-object things.  Saves from doing the try/catch below for.\n  if ( typeof value !== \"object\" ) {\n    return EJSON.stringify(value)\n  }\n\n  try {\n    // Find objects with circular references since EJSON doesn't support them yet (Issue #4778 + Unaccepted PR)\n    // If the native stringify is going to choke, EJSON.stringify is going to choke too.\n    JSON.stringify(value);\n  } catch (stringifyError) {\n    if ( stringifyError.name === \"TypeError\" ) {\n      return typeof value;\n    }\n  }\n\n  return EJSON.stringify(value);\n};\n\nvar typeofChecks = [\n  [String, \"string\"],\n  [Number, \"number\"],\n  [Boolean, \"boolean\"],\n  // While we don't allow undefined/function in EJSON, this is good for optional\n  // arguments with OneOf.\n  [Function, \"function\"],\n  [undefined, \"undefined\"]\n];\n\n// Return `false` if it matches. Otherwise, return an object with a `message` and a `path` field.\nvar testSubtree = function (value, pattern) {\n  // Match anything!\n  if (pattern === Match.Any)\n    return false;\n\n  // Basic atomic types.\n  // Do not match boxed objects (e.g. String, Boolean)\n  for (var i = 0; i < typeofChecks.length; ++i) {\n    if (pattern === typeofChecks[i][0]) {\n      if (typeof value === typeofChecks[i][1])\n        return false;\n      return {\n        message: \"Expected \" + typeofChecks[i][1] + \", got \" + stringForErrorMessage(value, { onlyShowType: true }),\n        path: \"\"\n      };\n    }\n  }\n\n  if (pattern === null) {\n    if (value === null) {\n      return false;\n    }\n    return {\n      message: \"Expected null, got \" + stringForErrorMessage(value),\n      path: \"\"\n    };\n  }\n\n  // Strings, numbers, and booleans match literally. Goes well with Match.OneOf.\n  if (typeof pattern === \"string\" || typeof pattern === \"number\" || typeof pattern === \"boolean\") {\n    if (value === pattern)\n      return false;\n    return {\n      message: \"Expected \" + pattern + \", got \" + stringForErrorMessage(value),\n      path: \"\"\n    };\n  }\n\n  // Match.Integer is special type encoded with array\n  if (pattern === Match.Integer) {\n    // There is no consistent and reliable way to check if variable is a 64-bit\n    // integer. One of the popular solutions is to get reminder of division by 1\n    // but this method fails on really large floats with big precision.\n    // E.g.: 1.348192308491824e+23 % 1 === 0 in V8\n    // Bitwise operators work consistantly but always cast variable to 32-bit\n    // signed integer according to JavaScript specs.\n    if (typeof value === \"number\" && (value | 0) === value)\n      return false;\n    return {\n      message: \"Expected Integer, got \" + stringForErrorMessage(value),\n      path: \"\"\n    };\n  }\n\n  // \"Object\" is shorthand for Match.ObjectIncluding({});\n  if (pattern === Object)\n    pattern = Match.ObjectIncluding({});\n\n  // Array (checked AFTER Any, which is implemented as an Array).\n  if (pattern instanceof Array) {\n    if (pattern.length !== 1) {\n      return {\n        message: \"Bad pattern: arrays must have one type element\" + stringForErrorMessage(pattern),\n        path: \"\"\n      };\n    }\n    if (!_.isArray(value) && !_.isArguments(value)) {\n      return {\n        message: \"Expected array, got \" + stringForErrorMessage(value),\n        path: \"\"\n      };\n    }\n\n    for (var i = 0, length = value.length; i < length; i++) {\n      var result = testSubtree(value[i], pattern[0]);\n      if (result) {\n        result.path = _prependPath(i, result.path);\n        return result;\n      }\n    }\n    return false;\n  }\n\n  // Arbitrary validation checks. The condition can return false or throw a\n  // Match.Error (ie, it can internally use check()) to fail.\n  if (pattern instanceof Where) {\n    var result;\n    try {\n      result = pattern.condition(value);\n    } catch (err) {\n      if (!(err instanceof Match.Error))\n        throw err;\n      return {\n        message: err.message,\n        path: err.path\n      };\n    }\n    if (result)\n      return false;\n    // XXX this error is terrible\n    return {\n      message: \"Failed Match.Where validation\",\n      path: \"\"\n    };\n  }\n\n\n  if (pattern instanceof Maybe) {\n    pattern = Match.OneOf(undefined, null, pattern.pattern);\n  }\n  else if (pattern instanceof Optional) {\n    pattern = Match.OneOf(undefined, pattern.pattern);\n  }\n\n  if (pattern instanceof OneOf) {\n    for (var i = 0; i < pattern.choices.length; ++i) {\n      var result = testSubtree(value, pattern.choices[i]);\n      if (!result) {\n        // No error? Yay, return.\n        return false;\n      }\n      // Match errors just mean try another choice.\n    }\n    // XXX this error is terrible\n    return {\n      message: \"Failed Match.OneOf, Match.Maybe or Match.Optional validation\",\n      path: \"\"\n    };\n  }\n\n  // A function that isn't something we special-case is assumed to be a\n  // constructor.\n  if (pattern instanceof Function) {\n    if (value instanceof pattern)\n      return false;\n    return {\n      message: \"Expected \" + (pattern.name ||\"particular constructor\"),\n      path: \"\"\n    };\n  }\n\n  var unknownKeysAllowed = false;\n  var unknownKeyPattern;\n  if (pattern instanceof ObjectIncluding) {\n    unknownKeysAllowed = true;\n    pattern = pattern.pattern;\n  }\n  if (pattern instanceof ObjectWithValues) {\n    unknownKeysAllowed = true;\n    unknownKeyPattern = [pattern.pattern];\n    pattern = {};  // no required keys\n  }\n\n  if (typeof pattern !== \"object\") {\n    return {\n      message: \"Bad pattern: unknown pattern type\",\n      path: \"\"\n    };\n  }\n\n  // An object, with required and optional keys. Note that this does NOT do\n  // structural matches against objects of special types that happen to match\n  // the pattern: this really needs to be a plain old {Object}!\n  if (typeof value !== 'object') {\n    return {\n      message: \"Expected object, got \" + typeof value,\n      path: \"\"\n    };\n  }\n  if (value === null) {\n    return {\n      message: \"Expected object, got null\",\n      path: \"\"\n    };\n  }\n  if (! isPlainObject(value)) {\n    return {\n      message: \"Expected plain object\",\n      path: \"\"\n    };\n  }\n\n  var requiredPatterns = {};\n  var optionalPatterns = {};\n  _.each(pattern, function (subPattern, key) {\n    if (subPattern instanceof Optional || subPattern instanceof Maybe)\n      optionalPatterns[key] = subPattern.pattern;\n    else\n      requiredPatterns[key] = subPattern;\n  });\n\n  //XXX: replace with underscore's _.allKeys if Meteor updates underscore to 1.8+ (or lodash)\n  var allKeys = function(obj){\n    var keys = [];\n    if (_.isObject(obj)){\n      for (var key in obj) keys.push(key);\n    }\n    return keys;\n  }\n\n  for (var keys = allKeys(value), i = 0, length = keys.length; i < length; i++) {\n    var key = keys[i];\n    var subValue = value[key];\n    if (_.has(requiredPatterns, key)) {\n      var result = testSubtree(subValue, requiredPatterns[key]);\n      if (result) {\n        result.path = _prependPath(key, result.path);\n        return result;\n      }\n      delete requiredPatterns[key];\n    } else if (_.has(optionalPatterns, key)) {\n      var result = testSubtree(subValue, optionalPatterns[key]);\n      if (result) {\n        result.path = _prependPath(key, result.path);\n        return result;\n      }\n    } else {\n      if (!unknownKeysAllowed) {\n        return {\n          message: \"Unknown key\",\n          path: key\n        };\n      }\n      if (unknownKeyPattern) {\n        var result = testSubtree(subValue, unknownKeyPattern[0]);\n        if (result) {\n          result.path = _prependPath(key, result.path);\n          return result;\n        }\n      }\n    }\n  }\n\n  var keys = _.keys(requiredPatterns);\n  if (keys.length) {\n    return {\n      message: \"Missing key '\" + keys[0] + \"'\",\n      path: \"\"\n    };\n  }\n};\n\nvar ArgumentChecker = function (args, description) {\n  var self = this;\n  // Make a SHALLOW copy of the arguments. (We'll be doing identity checks\n  // against its contents.)\n  self.args = _.clone(args);\n  // Since the common case will be to check arguments in order, and we splice\n  // out arguments when we check them, make it so we splice out from the end\n  // rather than the beginning.\n  self.args.reverse();\n  self.description = description;\n};\n\n_.extend(ArgumentChecker.prototype, {\n  checking: function (value) {\n    var self = this;\n    if (self._checkingOneValue(value))\n      return;\n    // Allow check(arguments, [String]) or check(arguments.slice(1), [String])\n    // or check([foo, bar], [String]) to count... but only if value wasn't\n    // itself an argument.\n    if (_.isArray(value) || _.isArguments(value)) {\n      _.each(value, _.bind(self._checkingOneValue, self));\n    }\n  },\n  _checkingOneValue: function (value) {\n    var self = this;\n    for (var i = 0; i < self.args.length; ++i) {\n      // Is this value one of the arguments? (This can have a false positive if\n      // the argument is an interned primitive, but it's still a good enough\n      // check.)\n      // (NaN is not === to itself, so we have to check specially.)\n      if (value === self.args[i] || (_.isNaN(value) && _.isNaN(self.args[i]))) {\n        self.args.splice(i, 1);\n        return true;\n      }\n    }\n    return false;\n  },\n  throwUnlessAllArgumentsHaveBeenChecked: function () {\n    var self = this;\n    if (!_.isEmpty(self.args))\n      throw new Error(\"Did not check() all arguments during \" +\n                      self.description);\n  }\n});\n\nvar _jsKeywords = [\"do\", \"if\", \"in\", \"for\", \"let\", \"new\", \"try\", \"var\", \"case\",\n  \"else\", \"enum\", \"eval\", \"false\", \"null\", \"this\", \"true\", \"void\", \"with\",\n  \"break\", \"catch\", \"class\", \"const\", \"super\", \"throw\", \"while\", \"yield\",\n  \"delete\", \"export\", \"import\", \"public\", \"return\", \"static\", \"switch\",\n  \"typeof\", \"default\", \"extends\", \"finally\", \"package\", \"private\", \"continue\",\n  \"debugger\", \"function\", \"arguments\", \"interface\", \"protected\", \"implements\",\n  \"instanceof\"];\n\n// Assumes the base of path is already escaped properly\n// returns key + base\nvar _prependPath = function (key, base) {\n  if ((typeof key) === \"number\" || key.match(/^[0-9]+$/))\n    key = \"[\" + key + \"]\";\n  else if (!key.match(/^[a-z_$][0-9a-z_$]*$/i) || _.contains(_jsKeywords, key))\n    key = JSON.stringify([key]);\n\n  if (base && base[0] !== \"[\")\n    return key + '.' + base;\n  return key + base;\n};\n\n"
  },
  {
    "path": "packages/check/match_test.js",
    "content": "Tinytest.add(\"check - check\", function (test) {\n  var matches = function (value, pattern) {\n    var error;\n    try {\n      check(value, pattern);\n    } catch (e) {\n      error = e;\n    }\n    test.isFalse(error);\n    test.isTrue(Match.test(value, pattern));\n  };\n  var fails = function (value, pattern) {\n    var error;\n    try {\n      check(value, pattern);\n    } catch (e) {\n      error = e;\n    }\n    test.isTrue(error);\n    test.instanceOf(error, Match.Error);\n    test.isFalse(Match.test(value, pattern));\n  };\n\n  // Atoms.\n  var pairs = [\n    [\"foo\", String],\n    [\"\", String],\n    [0, Number],\n    [42.59, Number],\n    [NaN, Number],\n    [Infinity, Number],\n    [true, Boolean],\n    [false, Boolean],\n    [function(){}, Function],\n    [undefined, undefined],\n    [null, null]\n  ];\n  _.each(pairs, function (pair) {\n    matches(pair[0], Match.Any);\n    _.each([String, Number, Boolean, undefined, null], function (type) {\n      if (type === pair[1]) {\n        matches(pair[0], type);\n        matches(pair[0], Match.Optional(type));\n        matches(undefined, Match.Optional(type));\n        matches(pair[0], Match.Maybe(type));\n        matches(undefined, Match.Maybe(type));\n        matches(null, Match.Maybe(type));\n        matches(pair[0], Match.Where(function () {\n          check(pair[0], type);\n          return true;\n        }));\n        matches(pair[0], Match.Where(function () {\n          try {\n            check(pair[0], type);\n            return true;\n          } catch (e) {\n            return false;\n          }\n        }));\n      } else {\n        fails(pair[0], type);\n        matches(pair[0], Match.OneOf(type, pair[1]));\n        matches(pair[0], Match.OneOf(pair[1], type));\n        fails(pair[0], Match.Where(function () {\n          check(pair[0], type);\n          return true;\n        }));\n        fails(pair[0], Match.Where(function () {\n          try {\n            check(pair[0], type);\n            return true;\n          } catch (e) {\n            return false;\n          }\n        }));\n      }\n      if ( type !== null ) fails(null, Match.Optional(type)); // Optional doesn't allow null, but does match on null type\n      fails(pair[0], [type]);\n      fails(pair[0], Object);\n    });\n  });\n  fails(true, Match.OneOf(String, Number, undefined, null, [Boolean]));\n  fails(new String(\"foo\"), String);\n  fails(new Boolean(true), Boolean);\n  fails(new Number(123), Number);\n\n  matches([1, 2, 3], [Number]);\n  matches([], [Number]);\n  fails([1, 2, 3, \"4\"], [Number]);\n  fails([1, 2, 3, [4]], [Number]);\n  matches([1, 2, 3, \"4\"], [Match.OneOf(Number, String)]);\n\n  matches({}, Object);\n  matches({}, {});\n  matches({foo: 42}, Object);\n  fails({foo: 42}, {});\n  matches({a: 1, b:2}, {b: Number, a: Number});\n  fails({a: 1, b:2}, {b: Number});\n  matches({a: 1, b:2}, Match.ObjectIncluding({b: Number}));\n  fails({a: 1, b:2}, Match.ObjectIncluding({b: String}));\n  fails({a: 1, b:2}, Match.ObjectIncluding({c: String}));\n  fails({}, {a: Number});\n\n  // Match.Optional does not match on a null value, unless the allowed type is itself \"null\"\n  fails(null, Match.Optional(String));\n  fails(null, Match.Optional(undefined));\n  matches(null, Match.Optional(null));\n\n  // on the other hand, undefined, works fine for all of them\n  matches(undefined, Match.Optional(String));\n  matches(undefined, Match.Optional(undefined));\n  matches(undefined, Match.Optional(null));\n\n  fails(true, Match.Optional(String)); // different should still fail\n  matches(\"String\", Match.Optional(String)); // same should pass\n\n  matches({}, {a: Match.Optional(Number)});\n  matches({a: 1}, {a: Match.Optional(Number)});\n  fails({a: true}, {a: Match.Optional(Number)});\n  fails({a: undefined}, {a: Match.Optional(Number)});\n\n  // .Maybe requires undefined, null or the allowed type in order to match\n  matches(null, Match.Maybe(String));\n  matches(null, Match.Maybe(undefined));\n  matches(null, Match.Maybe(null));\n\n  matches(undefined, Match.Maybe(String));\n  matches(undefined, Match.Maybe(undefined));\n  matches(undefined, Match.Maybe(null));\n\n  fails(true, Match.Maybe(String)); // different should still fail\n  matches(\"String\", Match.Maybe(String)); // same should pass\n\n  matches({}, {a: Match.Maybe(Number)});\n  matches({a: 1}, {a: Match.Maybe(Number)});\n  fails({a: true}, {a: Match.Maybe(Number)});\n  // Match.Optional means \"or undefined\" at the top level but \"or absent\" in\n  // objects.\n  // Match.Maybe should behave the same as Match.Optional in objects\n  // including handling nulls\n  fails({a: undefined}, {a: Match.Maybe(Number)});\n  fails({a: null}, {a: Match.Maybe(Number)});\n  var F = function () {\n    this.x = 123;\n  };\n  fails(new F, { x: 123 });\n\n  matches({}, Match.ObjectWithValues(Number));\n  matches({x: 1}, Match.ObjectWithValues(Number));\n  matches({x: 1, y: 2}, Match.ObjectWithValues(Number));\n  fails({x: 1, y: \"2\"}, Match.ObjectWithValues(Number));\n\n  matches(\"asdf\", \"asdf\");\n  fails(\"asdf\", \"monkey\");\n  matches(123, 123);\n  fails(123, 456);\n  fails(\"123\", 123);\n  fails(123, \"123\");\n  matches(true, true);\n  matches(false, false);\n  fails(true, false);\n  fails(true, \"true\");\n  fails(\"false\", false);\n\n  matches(/foo/, RegExp);\n  fails(/foo/, String);\n  matches(new Date, Date);\n  fails(new Date, Number);\n  matches(EJSON.newBinary(42), Match.Where(EJSON.isBinary));\n  fails([], Match.Where(EJSON.isBinary));\n\n  matches(42, Match.Where(function (x) { return x % 2 === 0; }));\n  fails(43, Match.Where(function (x) { return x % 2 === 0; }));\n\n  matches({\n    a: \"something\",\n    b: [\n      {x: 42, k: null},\n      {x: 43, k: true, p: [\"yay\"]}\n    ]\n  }, {a: String, b: [Match.ObjectIncluding({\n    x: Number,\n    k: Match.OneOf(null, Boolean)})]});\n\n\n  // Match.Integer\n  matches(-1, Match.Integer);\n  matches(0, Match.Integer);\n  matches(1, Match.Integer);\n  matches(-2147483648, Match.Integer); // INT_MIN\n  matches(2147483647, Match.Integer); // INT_MAX\n  fails(123.33, Match.Integer);\n  fails(.33, Match.Integer);\n  fails(1.348192308491824e+23, Match.Integer);\n  fails(NaN, Match.Integer);\n  fails(Infinity, Match.Integer);\n  fails(-Infinity, Match.Integer);\n  fails({}, Match.Integer);\n  fails([], Match.Integer);\n  fails(function () {}, Match.Integer);\n  fails(new Date, Match.Integer);\n\n\n  // Test non-plain objects.\n  var parentObj = {foo: \"bar\"};\n  var childObj = Object.assign(Object.create(parentObj), {bar: \"foo\"});\n  matches(parentObj, Object);\n  fails(parentObj, {foo: String, bar: String});\n  fails(parentObj, {bar: String});\n  matches(parentObj, {foo: String});\n  fails(childObj, Object);\n  fails(childObj, {foo: String, bar: String});\n  fails(childObj, {bar: String});\n  fails(childObj, {foo: String});\n\n  // Functions\n  var testFunction = function () {};\n  matches(testFunction, Function);\n  fails(5, Function);\n\n  // Circular Reference \"Classes\"\n\n  var TestInstanceChild = function () {};\n  var TestInstanceParent = function (child) {\n    child._parent = this;\n    this.child = child;\n  };\n\n  var testInstanceChild = new TestInstanceChild()\n  var testInstanceParent = new TestInstanceParent(testInstanceChild);\n\n  matches(TestInstanceParent, Function);\n  matches(testInstanceParent, TestInstanceParent);\n  fails(testInstanceChild, TestInstanceParent);\n\n  matches(testInstanceParent, Match.Optional(TestInstanceParent));\n  matches(testInstanceParent, Match.Maybe(TestInstanceParent));\n\n  // Circular Reference Objects\n\n  var circleFoo = {};\n  var circleBar = {};\n  circleFoo.bar = circleBar;\n  circleBar.foo = circleFoo;\n  fails(circleFoo, null);\n\n  // Test that \"arguments\" is treated like an array.\n  var argumentsMatches = function () {\n    matches(arguments, [Number]);\n  };\n  argumentsMatches();\n  argumentsMatches(1);\n  argumentsMatches(1, 2);\n  var argumentsFails = function () {\n    fails(arguments, [Number]);\n  };\n  argumentsFails(\"123\");\n  argumentsFails(1, \"23\");\n});\n\nTinytest.add(\"check - argument checker\", function (test) {\n  var checksAllArguments = function (f /*arguments*/) {\n    Match._failIfArgumentsAreNotAllChecked(\n      f, {}, _.toArray(arguments).slice(1), \"test\");\n  };\n  checksAllArguments(function () {});\n  checksAllArguments(function (x) {check(x, Match.Any);}, undefined);\n  checksAllArguments(function (x) {check(x, Match.Any);}, null);\n  checksAllArguments(function (x) {check(x, Match.Any);}, false);\n  checksAllArguments(function (x) {check(x, Match.Any);}, true);\n  checksAllArguments(function (x) {check(x, Match.Any);}, 0);\n  checksAllArguments(function (a, b, c) {\n    check(a, String);\n    check(b, Boolean);\n    check(c, Match.Optional(Number));\n  }, \"foo\", true);\n  checksAllArguments(function () {\n    check(arguments, [Number]);\n  }, 1, 2, 4);\n  checksAllArguments(function(x) {\n    check(x, Number);\n    check(_.toArray(arguments).slice(1), [String]);\n  }, 1, \"foo\", \"bar\", \"baz\");\n  // NaN values\n  checksAllArguments(function (x) {\n    check(x, Number);\n  }, NaN);\n\n  var doesntCheckAllArguments = function (f /*arguments*/) {\n    try {\n      Match._failIfArgumentsAreNotAllChecked(\n        f, {}, _.toArray(arguments).slice(1), \"test\");\n      test.fail({message: \"expected _failIfArgumentsAreNotAllChecked to throw\"});\n    } catch (e) {\n      test.equal(e.message, \"Did not check() all arguments during test\");\n    }\n  };\n\n  doesntCheckAllArguments(function () {}, undefined);\n  doesntCheckAllArguments(function () {}, null);\n  doesntCheckAllArguments(function () {}, 1);\n  doesntCheckAllArguments(function () {\n    check(_.toArray(arguments).slice(1), [String]);\n  }, 1, \"asdf\", \"foo\");\n  doesntCheckAllArguments(function (x, y) {\n    check(x, Boolean);\n  }, true, false);\n  // One \"true\" check doesn't count for all.\n  doesntCheckAllArguments(function (x, y) {\n    check(x, Boolean);\n  }, true, true);\n  // For non-primitives, we really do require that each arg gets checked.\n  doesntCheckAllArguments(function (x, y) {\n    check(x, [Boolean]);\n    check(x, [Boolean]);\n  }, [true], [true]);\n\n\n  // In an ideal world this test would fail, but we currently can't\n  // differentiate between \"two calls to check x, both of which are true\" and\n  // \"check x and check y, both of which are true\" (for any interned primitive\n  // type).\n  checksAllArguments(function (x, y) {\n    check(x, Boolean);\n    check(x, Boolean);\n  }, true, true);\n});\n\nTinytest.add(\"check - Match error path\", function (test) {\n  var match = function (value, pattern, expectedPath) {\n    try {\n      check(value, pattern);\n    } catch (err) {\n      // XXX just for FF 3.6, its JSON stringification prefers \"\\u000a\" to \"\\n\"\n      err.path = err.path.replace(/\\\\u000a/, \"\\\\n\");\n      if (err.path != expectedPath)\n        test.fail({\n          type: \"match-error-path\",\n          message: \"The path of Match.Error doesn't match.\",\n          pattern: JSON.stringify(pattern),\n          value: JSON.stringify(value),\n          path: err.path,\n          expectedPath: expectedPath\n        });\n    }\n  };\n\n  match({ foo: [ { bar: 3 }, {bar: \"something\"} ] }, { foo: [ { bar: Number } ] }, \"foo[1].bar\");\n  // Complicated case with arrays, $, whitespace and quotes!\n  match([{ $FoO: { \"bar baz\\n\\\"'\": 3 } }], [{ $FoO: { \"bar baz\\n\\\"'\": String } }], \"[0].$FoO[\\\"bar baz\\\\n\\\\\\\"'\\\"]\");\n  // Numbers only, can be accessed w/o quotes\n  match({ \"1231\": 123 }, { \"1231\": String }, \"[1231]\");\n  match({ \"1234abcd\": 123 }, { \"1234abcd\": String }, \"[\\\"1234abcd\\\"]\");\n  match({ $set: { people: \"nice\" } }, { $set: { people: [String] } }, \"$set.people\");\n  match({ _underscore: \"should work\" }, { _underscore: Number }, \"_underscore\");\n  // Nested array looks nice\n  match([[[\"something\", \"here\"], []], [[\"string\", 123]]], [[[String]]], \"[1][0][1]\");\n  // Object nested in arrays should look nice, too!\n  match([[[{ foo: \"something\" }, { foo: \"here\"}],\n          [{ foo: \"asdf\" }]],\n         [[{ foo: 123 }]]],\n        [[[{ foo: String }]]], \"[1][0][0].foo\");\n\n  // JS keyword\n  match({ \"return\": 0 }, { \"return\": String }, \"[\\\"return\\\"]\");\n});\n\nTinytest.add(\"check - Match error message\", function (test) {\n  var match = function (value, pattern, expectedMessage) {\n    try {\n      check(value, pattern);\n    } catch (err) {\n      if (err.message !== \"Match error: \" + expectedMessage)\n        test.fail({\n          type: \"match-error-message\",\n          message: \"The message of Match.Error doesn't match.\",\n          pattern: JSON.stringify(pattern),\n          value: JSON.stringify(value),\n          errorMessage: err.message,\n          expectedErrorMessage: expectedMessage\n        });\n    }\n  };\n\n  match(2, String, \"Expected string, got number\");\n  match({key: 0}, Number, \"Expected number, got object\");\n  match(null, Boolean, \"Expected boolean, got null\");\n  match(\"string\", undefined, \"Expected undefined, got string\");\n  match(true, null, \"Expected null, got true\");\n  match({}, Match.ObjectIncluding({ bar: String }), \"Missing key 'bar'\");\n  match(null, Object, \"Expected object, got null\");\n  match(null, Function, \"Expected function, got null\");\n  match(\"bar\", \"foo\", \"Expected foo, got \\\"bar\\\"\");\n  match(3.14, Match.Integer, \"Expected Integer, got 3.14\");\n  match(false, [Boolean], \"Expected array, got false\");\n  match([null, null], [String], \"Expected string, got null in field [0]\");\n  match(2, {key: 2}, \"Expected object, got number\");\n  match(null, {key: 2}, \"Expected object, got null\");\n  match(new Date, {key: 2}, \"Expected plain object\");\n\n  var TestInstanceChild = function () {};\n  var TestInstanceParent = function (child) {\n    child._parent = this;\n    this.child = child;\n  };\n\n  var testInstanceChild = new TestInstanceChild()\n  var testInstanceParent = new TestInstanceParent(testInstanceChild);\n  match(testInstanceChild, TestInstanceParent, \"Expected \" + (TestInstanceParent.name || \"particular constructor\"));\n\n  var circleFoo = {};\n  var circleBar = {};\n  circleFoo.bar = circleBar;\n  circleBar.foo = circleFoo;\n  match(circleFoo, null, \"Expected null, got object\");\n\n});\n\n// Regression test for https://github.com/meteor/meteor/issues/2136\nMeteor.isServer && Tinytest.addAsync(\"check - non-fiber check works\", function (test, onComplete) {\n  var Fiber = Npm.require('fibers');\n\n  // We can only call test.isTrue inside normal Meteor Fibery code, so give us a\n  // bindEnvironment way to get back.\n  var report = Meteor.bindEnvironment(function (success) {\n    test.isTrue(success);\n    onComplete();\n  });\n\n  // Get out of a fiber with process.nextTick and ensure that we can still use\n  // check.\n  process.nextTick(function () {\n    var success = true;\n    if (Fiber.current)\n      success = false;\n    if (success) {\n      try {\n        check(true, Boolean);\n      } catch (e) {\n        success = false;\n      }\n    }\n    report(success);\n  });\n});\n"
  },
  {
    "path": "packages/check/package.js",
    "content": "Package.describe({\n  summary: \"Check whether a value matches a pattern\",\n  version: '1.2.3'\n});\n\nPackage.onUse(function (api) {\n  api.use('modules');\n  api.use('underscore');\n  api.use('ejson');\n\n  api.mainModule('match.js');\n\n  api.export('check');\n  api.export('Match');\n});\n\nPackage.onTest(function (api) {\n  api.use(['check', 'tinytest', 'underscore', 'ejson', 'ecmascript'], ['client', 'server']);\n\n  api.addFiles('match_test.js', ['client', 'server']);\n});\n"
  },
  {
    "path": "packages/code-prettify/.gitignore",
    "content": ".build*\n.!*"
  },
  {
    "path": "packages/code-prettify/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/code-prettify/lang-apollo.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"com\",/^#[^\\n\\r]*/,null,\"#\"],[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"str\",/^\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)/,null,'\"']],[[\"kwd\",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\\s/,\nnull],[\"typ\",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[ES]?BANK=?|BLOCK|BNKSUM|E?CADR|COUNT\\*?|2?DEC\\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\\s/,null],[\"lit\",/^'(?:-*(?:\\w|\\\\[!-~])(?:[\\w-]*|\\\\[!-~])[!=?]?)?/],[\"pln\",/^-*(?:[!-z]|\\\\[!-~])(?:[\\w-]*|\\\\[!-~])[!=?]?/],[\"pun\",/^[^\\w\\t\\n\\r \"'-);\\\\\\xa0]+/]]),[\"apollo\",\"agc\",\"aea\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-clj.js",
    "content": "/*\n Copyright (C) 2011 Google 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*/\nvar a=null;\nPR.registerLangHandler(PR.createSimpleLexer([[\"opn\",/^[([{]+/,a,\"([{\"],[\"clo\",/^[)\\]}]+/,a,\")]}\"],[\"com\",/^;[^\\n\\r]*/,a,\";\"],[\"pln\",/^[\\t\\n\\r \\xa0]+/,a,\"\\t\\n\\r \\xa0\"],[\"str\",/^\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)/,a,'\"']],[[\"kwd\",/^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\\b/,a],\n[\"typ\",/^:[\\dA-Za-z-]+/]]),[\"clj\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-css.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\f\\r ]+/,null,\" \\t\\r\\n\f\"]],[[\"str\",/^\"(?:[^\\n\\f\\r\"\\\\]|\\\\(?:\\r\\n?|\\n|\\f)|\\\\[\\S\\s])*\"/,null],[\"str\",/^'(?:[^\\n\\f\\r'\\\\]|\\\\(?:\\r\\n?|\\n|\\f)|\\\\[\\S\\s])*'/,null],[\"lang-css-str\",/^url\\(([^\"')]*)\\)/i],[\"kwd\",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\\w-]|$)/i,null],[\"lang-css-kw\",/^(-?(?:[_a-z]|\\\\[\\da-f]+ ?)(?:[\\w-]|\\\\\\\\[\\da-f]+ ?)*)\\s*:/i],[\"com\",/^\\/\\*[^*]*\\*+(?:[^*/][^*]*\\*+)*\\//],[\"com\",\n/^(?:<\\!--|--\\>)/],[\"lit\",/^(?:\\d+|\\d*\\.\\d+)(?:%|[a-z]+)?/i],[\"lit\",/^#[\\da-f]{3,6}/i],[\"pln\",/^-?(?:[_a-z]|\\\\[\\da-f]+ ?)(?:[\\w-]|\\\\\\\\[\\da-f]+ ?)*/i],[\"pun\",/^[^\\s\\w\"']+/]]),[\"css\"]);PR.registerLangHandler(PR.createSimpleLexer([],[[\"kwd\",/^-?(?:[_a-z]|\\\\[\\da-f]+ ?)(?:[\\w-]|\\\\\\\\[\\da-f]+ ?)*/i]]),[\"css-kw\"]);PR.registerLangHandler(PR.createSimpleLexer([],[[\"str\",/^[^\"')]+/]]),[\"css-str\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-go.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"pln\",/^(?:\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)|'(?:[^'\\\\]|\\\\[\\S\\s])+(?:'|$)|`[^`]*(?:`|$))/,null,\"\\\"'\"]],[[\"com\",/^(?:\\/\\/[^\\n\\r]*|\\/\\*[\\S\\s]*?\\*\\/)/],[\"pln\",/^(?:[^\"'/`]|\\/(?![*/]))+/]]),[\"go\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-hs.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t-\\r ]+/,null,\"\\t\\n\u000b\f\\r \"],[\"str\",/^\"(?:[^\\n\\f\\r\"\\\\]|\\\\[\\S\\s])*(?:\"|$)/,null,'\"'],[\"str\",/^'(?:[^\\n\\f\\r'\\\\]|\\\\[^&])'?/,null,\"'\"],[\"lit\",/^(?:0o[0-7]+|0x[\\da-f]+|\\d+(?:\\.\\d+)?(?:e[+-]?\\d+)?)/i,null,\"0123456789\"]],[[\"com\",/^(?:--+[^\\n\\f\\r]*|{-(?:[^-]|-+[^}-])*-})/],[\"kwd\",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\\d'A-Za-z]|$)/,\nnull],[\"pln\",/^(?:[A-Z][\\w']*\\.)*[A-Za-z][\\w']*/],[\"pun\",/^[^\\d\\t-\\r \"'A-Za-z]+/]]),[\"hs\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-lisp.js",
    "content": "var a=null;\nPR.registerLangHandler(PR.createSimpleLexer([[\"opn\",/^\\(+/,a,\"(\"],[\"clo\",/^\\)+/,a,\")\"],[\"com\",/^;[^\\n\\r]*/,a,\";\"],[\"pln\",/^[\\t\\n\\r \\xa0]+/,a,\"\\t\\n\\r \\xa0\"],[\"str\",/^\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)/,a,'\"']],[[\"kwd\",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\\b/,a],\n[\"lit\",/^[+-]?(?:[#0]x[\\da-f]+|\\d+\\/\\d+|(?:\\.\\d+|\\d+(?:\\.\\d*)?)(?:[de][+-]?\\d+)?)/i],[\"lit\",/^'(?:-*(?:\\w|\\\\[!-~])(?:[\\w-]*|\\\\[!-~])[!=?]?)?/],[\"pln\",/^-*(?:[_a-z]|\\\\[!-~])(?:[\\w-]*|\\\\[!-~])[!=?]?/i],[\"pun\",/^[^\\w\\t\\n\\r \"'-);\\\\\\xa0]+/]]),[\"cl\",\"el\",\"lisp\",\"scm\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-lua.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"str\",/^(?:\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)|'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$))/,null,\"\\\"'\"]],[[\"com\",/^--(?:\\[(=*)\\[[\\S\\s]*?(?:]\\1]|$)|[^\\n\\r]*)/],[\"str\",/^\\[(=*)\\[[\\S\\s]*?(?:]\\1]|$)/],[\"kwd\",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\\b/,null],[\"lit\",/^[+-]?(?:0x[\\da-f]+|(?:\\.\\d+|\\d+(?:\\.\\d*)?)(?:e[+-]?\\d+)?)/i],\n[\"pln\",/^[_a-z]\\w*/i],[\"pun\",/^[^\\w\\t\\n\\r \\xa0][^\\w\\t\\n\\r \"'+=\\xa0-]*/]]),[\"lua\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-ml.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"com\",/^#(?:if[\\t\\n\\r \\xa0]+(?:[$_a-z][\\w']*|``[^\\t\\n\\r`]*(?:``|$))|else|endif|light)/i,null,\"#\"],[\"str\",/^(?:\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)|'(?:[^'\\\\]|\\\\[\\S\\s])(?:'|$))/,null,\"\\\"'\"]],[[\"com\",/^(?:\\/\\/[^\\n\\r]*|\\(\\*[\\S\\s]*?\\*\\))/],[\"kwd\",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\\b/],\n[\"lit\",/^[+-]?(?:0x[\\da-f]+|(?:\\.\\d+|\\d+(?:\\.\\d*)?)(?:e[+-]?\\d+)?)/i],[\"pln\",/^(?:[_a-z][\\w']*[!#?]?|``[^\\t\\n\\r`]*(?:``|$))/i],[\"pun\",/^[^\\w\\t\\n\\r \"'\\xa0]+/]]),[\"fs\",\"ml\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-n.js",
    "content": "var a=null;\nPR.registerLangHandler(PR.createSimpleLexer([[\"str\",/^(?:'(?:[^\\n\\r'\\\\]|\\\\.)*'|\"(?:[^\\n\\r\"\\\\]|\\\\.)*(?:\"|$))/,a,'\"'],[\"com\",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\\b|[^\\n\\r]*)/,a,\"#\"],[\"pln\",/^\\s+/,a,\" \\r\\n\\t\\xa0\"]],[[\"str\",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,a],[\"str\",/^<#[^#>]*(?:#>|$)/,a],[\"str\",/^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h|[a-z]\\w*)>/,a],[\"com\",/^\\/\\/[^\\n\\r]*/,a],[\"com\",/^\\/\\*[\\S\\s]*?(?:\\*\\/|$)/,\na],[\"kwd\",/^(?:abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield)\\b/,\na],[\"typ\",/^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\\b/,a],[\"lit\",/^@[$_a-z][\\w$@]*/i,a],[\"typ\",/^@[A-Z]+[a-z][\\w$@]*/,a],[\"pln\",/^'?[$_a-z][\\w$@]*/i,a],[\"lit\",/^(?:0x[\\da-f]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+-]?\\d+)?)[a-z]*/i,a,\"0123456789\"],[\"pun\",/^.[^\\s\\w\"-$'./@`]*/,a]]),[\"n\",\"nemerle\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-proto.js",
    "content": "PR.registerLangHandler(PR.sourceDecorator({keywords:\"bytes,default,double,enum,extend,extensions,false,group,import,max,message,option,optional,package,repeated,required,returns,rpc,service,syntax,to,true\",types:/^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\\b/,cStyleComments:!0}),[\"proto\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-scala.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"str\",/^\"(?:\"\"(?:\"\"?(?!\")|[^\"\\\\]|\\\\.)*\"{0,3}|(?:[^\\n\\r\"\\\\]|\\\\.)*\"?)/,null,'\"'],[\"lit\",/^`(?:[^\\n\\r\\\\`]|\\\\.)*`?/,null,\"`\"],[\"pun\",/^[!#%&(--:-@[-^{-~]+/,null,\"!#%&()*+,-:;<=>?@[\\\\]^{|}~\"]],[[\"str\",/^'(?:[^\\n\\r'\\\\]|\\\\(?:'|[^\\n\\r']+))'/],[\"lit\",/^'[$A-Z_a-z][\\w$]*(?![\\w$'])/],[\"kwd\",/^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\\b/],\n[\"lit\",/^(?:true|false|null|this)\\b/],[\"lit\",/^(?:0(?:[0-7]+|x[\\da-f]+)l?|(?:0|[1-9]\\d*)(?:(?:\\.\\d+)?(?:e[+-]?\\d+)?f?|l?)|\\\\.\\d+(?:e[+-]?\\d+)?f?)/i],[\"typ\",/^[$_]*[A-Z][\\d$A-Z_]*[a-z][\\w$]*/],[\"pln\",/^[$A-Z_a-z][\\w$]*/],[\"com\",/^\\/(?:\\/.*|\\*(?:\\/|\\**[^*/])*(?:\\*+\\/?)?)/],[\"pun\",/^(?:\\.+|\\/)/]]),[\"scala\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-sql.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"str\",/^(?:\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*')/,null,\"\\\"'\"]],[[\"com\",/^(?:--[^\\n\\r]*|\\/\\*[\\S\\s]*?(?:\\*\\/|$))/],[\"kwd\",/^(?:add|all|alter|and|any|as|asc|authorization|backup|begin|between|break|browse|bulk|by|cascade|case|check|checkpoint|close|clustered|coalesce|collate|column|commit|compute|constraint|contains|containstable|continue|convert|create|cross|current|current_date|current_time|current_timestamp|current_user|cursor|database|dbcc|deallocate|declare|default|delete|deny|desc|disk|distinct|distributed|double|drop|dummy|dump|else|end|errlvl|escape|except|exec|execute|exists|exit|fetch|file|fillfactor|for|foreign|freetext|freetexttable|from|full|function|goto|grant|group|having|holdlock|identity|identitycol|identity_insert|if|in|index|inner|insert|intersect|into|is|join|key|kill|left|like|lineno|load|match|merge|national|nocheck|nonclustered|not|null|nullif|of|off|offsets|on|open|opendatasource|openquery|openrowset|openxml|option|or|order|outer|over|percent|plan|precision|primary|print|proc|procedure|public|raiserror|read|readtext|reconfigure|references|replication|restore|restrict|return|revoke|right|rollback|rowcount|rowguidcol|rule|save|schema|select|session_user|set|setuser|shutdown|some|statistics|system_user|table|textsize|then|to|top|tran|transaction|trigger|truncate|tsequal|union|unique|update|updatetext|use|user|using|values|varying|view|waitfor|when|where|while|with|writetext)(?=[^\\w-]|$)/i,\nnull],[\"lit\",/^[+-]?(?:0x[\\da-f]+|(?:\\.\\d+|\\d+(?:\\.\\d*)?)(?:e[+-]?\\d+)?)/i],[\"pln\",/^[_a-z][\\w-]*/i],[\"pun\",/^[^\\w\\t\\n\\r \"'\\xa0][^\\w\\t\\n\\r \"'+\\xa0-]*/]]),[\"sql\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-tex.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"com\",/^%[^\\n\\r]*/,null,\"%\"]],[[\"kwd\",/^\\\\[@-Za-z]+/],[\"kwd\",/^\\\\./],[\"typ\",/^[$&]/],[\"lit\",/[+-]?(?:\\.\\d+|\\d+(?:\\.\\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],[\"pun\",/^[()=[\\]{}]+/]]),[\"latex\",\"tex\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-vhdl.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"]],[[\"str\",/^(?:[box]?\"(?:[^\"]|\"\")*\"|'.')/i],[\"com\",/^--[^\\n\\r]*/],[\"kwd\",/^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\\w-]|$)/i,\nnull],[\"typ\",/^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\\w-]|$)/i,null],[\"typ\",/^'(?:active|ascending|base|delayed|driving|driving_value|event|high|image|instance_name|last_active|last_event|last_value|left|leftof|length|low|path_name|pos|pred|quiet|range|reverse_range|right|rightof|simple_name|stable|succ|transaction|val|value)(?=[^\\w-]|$)/i,null],[\"lit\",/^\\d+(?:_\\d+)*(?:#[\\w.\\\\]+#(?:[+-]?\\d+(?:_\\d+)*)?|(?:\\.\\d+(?:_\\d+)*)?(?:e[+-]?\\d+(?:_\\d+)*)?)/i],\n[\"pln\",/^(?:[a-z]\\w*|\\\\[^\\\\]*\\\\)/i],[\"pun\",/^[^\\w\\t\\n\\r \"'\\xa0][^\\w\\t\\n\\r \"'\\xa0-]*/]]),[\"vhdl\",\"vhd\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-wiki.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\d\\t a-gi-z\\xa0]+/,null,\"\\t \\xa0abcdefgijklmnopqrstuvwxyz0123456789\"],[\"pun\",/^[*=[\\]^~]+/,null,\"=*~^[]\"]],[[\"lang-wiki.meta\",/(?:^^|\\r\\n?|\\n)(#[a-z]+)\\b/],[\"lit\",/^[A-Z][a-z][\\da-z]+[A-Z][a-z][^\\W_]+\\b/],[\"lang-\",/^{{{([\\S\\s]+?)}}}/],[\"lang-\",/^`([^\\n\\r`]+)`/],[\"str\",/^https?:\\/\\/[^\\s#/?]*(?:\\/[^\\s#?]*)?(?:\\?[^\\s#]*)?(?:#\\S*)?/i],[\"pln\",/^(?:\\r\\n|[\\S\\s])[^\\n\\r#*=A-[^`h{~]*/]]),[\"wiki\"]);\nPR.registerLangHandler(PR.createSimpleLexer([[\"kwd\",/^#[a-z]+/i,null,\"#\"]],[]),[\"wiki.meta\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-xq.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"var pln\",/^\\$[\\w-]+/,null,\"$\"]],[[\"pln\",/^[\\s=][<>][\\s=]/],[\"lit\",/^@[\\w-]+/],[\"tag\",/^<\\/?[a-z](?:[\\w-.:]*\\w)?|\\/?>$/i],[\"com\",/^\\(:[\\S\\s]*?:\\)/],[\"pln\",/^[(),/;[\\]{}]$/],[\"str\",/^(?:\"(?:[^\"\\\\{]|\\\\[\\S\\s])*(?:\"|$)|'(?:[^'\\\\{]|\\\\[\\S\\s])*(?:'|$))/,null,\"\\\"'\"],[\"kwd\",/^(?:xquery|where|version|variable|union|typeswitch|treat|to|then|text|stable|sortby|some|self|schema|satisfies|returns|return|ref|processing-instruction|preceding-sibling|preceding|precedes|parent|only|of|node|namespace|module|let|item|intersect|instance|in|import|if|function|for|follows|following-sibling|following|external|except|every|else|element|descending|descendant-or-self|descendant|define|default|declare|comment|child|cast|case|before|attribute|assert|ascending|as|ancestor-or-self|ancestor|after|eq|order|by|or|and|schema-element|document-node|node|at)\\b/],\n[\"typ\",/^(?:xs:yearMonthDuration|xs:unsignedLong|xs:time|xs:string|xs:short|xs:QName|xs:Name|xs:long|xs:integer|xs:int|xs:gYearMonth|xs:gYear|xs:gMonthDay|xs:gDay|xs:float|xs:duration|xs:double|xs:decimal|xs:dayTimeDuration|xs:dateTime|xs:date|xs:byte|xs:boolean|xs:anyURI|xf:yearMonthDuration)\\b/,null],[\"fun pln\",/^(?:xp:dereference|xinc:node-expand|xinc:link-references|xinc:link-expand|xhtml:restructure|xhtml:clean|xhtml:add-lists|xdmp:zip-manifest|xdmp:zip-get|xdmp:zip-create|xdmp:xquery-version|xdmp:word-convert|xdmp:with-namespaces|xdmp:version|xdmp:value|xdmp:user-roles|xdmp:user-last-login|xdmp:user|xdmp:url-encode|xdmp:url-decode|xdmp:uri-is-file|xdmp:uri-format|xdmp:uri-content-type|xdmp:unquote|xdmp:unpath|xdmp:triggers-database|xdmp:trace|xdmp:to-json|xdmp:tidy|xdmp:subbinary|xdmp:strftime|xdmp:spawn-in|xdmp:spawn|xdmp:sleep|xdmp:shutdown|xdmp:set-session-field|xdmp:set-response-encoding|xdmp:set-response-content-type|xdmp:set-response-code|xdmp:set-request-time-limit|xdmp:set|xdmp:servers|xdmp:server-status|xdmp:server-name|xdmp:server|xdmp:security-database|xdmp:security-assert|xdmp:schema-database|xdmp:save|xdmp:role-roles|xdmp:role|xdmp:rethrow|xdmp:restart|xdmp:request-timestamp|xdmp:request-status|xdmp:request-cancel|xdmp:request|xdmp:redirect-response|xdmp:random|xdmp:quote|xdmp:query-trace|xdmp:query-meters|xdmp:product-edition|xdmp:privilege-roles|xdmp:privilege|xdmp:pretty-print|xdmp:powerpoint-convert|xdmp:platform|xdmp:permission|xdmp:pdf-convert|xdmp:path|xdmp:octal-to-integer|xdmp:node-uri|xdmp:node-replace|xdmp:node-kind|xdmp:node-insert-child|xdmp:node-insert-before|xdmp:node-insert-after|xdmp:node-delete|xdmp:node-database|xdmp:mul64|xdmp:modules-root|xdmp:modules-database|xdmp:merging|xdmp:merge-cancel|xdmp:merge|xdmp:md5|xdmp:logout|xdmp:login|xdmp:log-level|xdmp:log|xdmp:lock-release|xdmp:lock-acquire|xdmp:load|xdmp:invoke-in|xdmp:invoke|xdmp:integer-to-octal|xdmp:integer-to-hex|xdmp:http-put|xdmp:http-post|xdmp:http-options|xdmp:http-head|xdmp:http-get|xdmp:http-delete|xdmp:hosts|xdmp:host-status|xdmp:host-name|xdmp:host|xdmp:hex-to-integer|xdmp:hash64|xdmp:hash32|xdmp:has-privilege|xdmp:groups|xdmp:group-serves|xdmp:group-servers|xdmp:group-name|xdmp:group-hosts|xdmp:group|xdmp:get-session-field-names|xdmp:get-session-field|xdmp:get-response-encoding|xdmp:get-response-code|xdmp:get-request-username|xdmp:get-request-user|xdmp:get-request-url|xdmp:get-request-protocol|xdmp:get-request-path|xdmp:get-request-method|xdmp:get-request-header-names|xdmp:get-request-header|xdmp:get-request-field-names|xdmp:get-request-field-filename|xdmp:get-request-field-content-type|xdmp:get-request-field|xdmp:get-request-client-certificate|xdmp:get-request-client-address|xdmp:get-request-body|xdmp:get-current-user|xdmp:get-current-roles|xdmp:get|xdmp:function-name|xdmp:function-module|xdmp:function|xdmp:from-json|xdmp:forests|xdmp:forest-status|xdmp:forest-restore|xdmp:forest-restart|xdmp:forest-name|xdmp:forest-delete|xdmp:forest-databases|xdmp:forest-counts|xdmp:forest-clear|xdmp:forest-backup|xdmp:forest|xdmp:filesystem-file|xdmp:filesystem-directory|xdmp:exists|xdmp:excel-convert|xdmp:eval-in|xdmp:eval|xdmp:estimate|xdmp:email|xdmp:element-content-type|xdmp:elapsed-time|xdmp:document-set-quality|xdmp:document-set-property|xdmp:document-set-properties|xdmp:document-set-permissions|xdmp:document-set-collections|xdmp:document-remove-properties|xdmp:document-remove-permissions|xdmp:document-remove-collections|xdmp:document-properties|xdmp:document-locks|xdmp:document-load|xdmp:document-insert|xdmp:document-get-quality|xdmp:document-get-properties|xdmp:document-get-permissions|xdmp:document-get-collections|xdmp:document-get|xdmp:document-forest|xdmp:document-delete|xdmp:document-add-properties|xdmp:document-add-permissions|xdmp:document-add-collections|xdmp:directory-properties|xdmp:directory-locks|xdmp:directory-delete|xdmp:directory-create|xdmp:directory|xdmp:diacritic-less|xdmp:describe|xdmp:default-permissions|xdmp:default-collections|xdmp:databases|xdmp:database-restore-validate|xdmp:database-restore-status|xdmp:database-restore-cancel|xdmp:database-restore|xdmp:database-name|xdmp:database-forests|xdmp:database-backup-validate|xdmp:database-backup-status|xdmp:database-backup-purge|xdmp:database-backup-cancel|xdmp:database-backup|xdmp:database|xdmp:collection-properties|xdmp:collection-locks|xdmp:collection-delete|xdmp:collation-canonical-uri|xdmp:castable-as|xdmp:can-grant-roles|xdmp:base64-encode|xdmp:base64-decode|xdmp:architecture|xdmp:apply|xdmp:amp-roles|xdmp:amp|xdmp:add64|xdmp:add-response-header|xdmp:access|trgr:trigger-set-recursive|trgr:trigger-set-permissions|trgr:trigger-set-name|trgr:trigger-set-module|trgr:trigger-set-event|trgr:trigger-set-description|trgr:trigger-remove-permissions|trgr:trigger-module|trgr:trigger-get-permissions|trgr:trigger-enable|trgr:trigger-disable|trgr:trigger-database-online-event|trgr:trigger-data-event|trgr:trigger-add-permissions|trgr:remove-trigger|trgr:property-content|trgr:pre-commit|trgr:post-commit|trgr:get-trigger-by-id|trgr:get-trigger|trgr:document-scope|trgr:document-content|trgr:directory-scope|trgr:create-trigger|trgr:collection-scope|trgr:any-property-content|thsr:set-entry|thsr:remove-term|thsr:remove-synonym|thsr:remove-entry|thsr:query-lookup|thsr:lookup|thsr:load|thsr:insert|thsr:expand|thsr:add-synonym|spell:suggest-detailed|spell:suggest|spell:remove-word|spell:make-dictionary|spell:load|spell:levenshtein-distance|spell:is-correct|spell:insert|spell:double-metaphone|spell:add-word|sec:users-collection|sec:user-set-roles|sec:user-set-password|sec:user-set-name|sec:user-set-description|sec:user-set-default-permissions|sec:user-set-default-collections|sec:user-remove-roles|sec:user-privileges|sec:user-get-roles|sec:user-get-description|sec:user-get-default-permissions|sec:user-get-default-collections|sec:user-doc-permissions|sec:user-doc-collections|sec:user-add-roles|sec:unprotect-collection|sec:uid-for-name|sec:set-realm|sec:security-version|sec:security-namespace|sec:security-installed|sec:security-collection|sec:roles-collection|sec:role-set-roles|sec:role-set-name|sec:role-set-description|sec:role-set-default-permissions|sec:role-set-default-collections|sec:role-remove-roles|sec:role-privileges|sec:role-get-roles|sec:role-get-description|sec:role-get-default-permissions|sec:role-get-default-collections|sec:role-doc-permissions|sec:role-doc-collections|sec:role-add-roles|sec:remove-user|sec:remove-role-from-users|sec:remove-role-from-role|sec:remove-role-from-privileges|sec:remove-role-from-amps|sec:remove-role|sec:remove-privilege|sec:remove-amp|sec:protect-collection|sec:privileges-collection|sec:privilege-set-roles|sec:privilege-set-name|sec:privilege-remove-roles|sec:privilege-get-roles|sec:privilege-add-roles|sec:priv-doc-permissions|sec:priv-doc-collections|sec:get-user-names|sec:get-unique-elem-id|sec:get-role-names|sec:get-role-ids|sec:get-privilege|sec:get-distinct-permissions|sec:get-collection|sec:get-amp|sec:create-user-with-role|sec:create-user|sec:create-role|sec:create-privilege|sec:create-amp|sec:collections-collection|sec:collection-set-permissions|sec:collection-remove-permissions|sec:collection-get-permissions|sec:collection-add-permissions|sec:check-admin|sec:amps-collection|sec:amp-set-roles|sec:amp-remove-roles|sec:amp-get-roles|sec:amp-doc-permissions|sec:amp-doc-collections|sec:amp-add-roles|search:unparse|search:suggest|search:snippet|search:search|search:resolve-nodes|search:resolve|search:remove-constraint|search:parse|search:get-default-options|search:estimate|search:check-options|prof:value|prof:reset|prof:report|prof:invoke|prof:eval|prof:enable|prof:disable|prof:allowed|ppt:clean|pki:template-set-request|pki:template-set-name|pki:template-set-key-type|pki:template-set-key-options|pki:template-set-description|pki:template-in-use|pki:template-get-version|pki:template-get-request|pki:template-get-name|pki:template-get-key-type|pki:template-get-key-options|pki:template-get-id|pki:template-get-description|pki:need-certificate|pki:is-temporary|pki:insert-trusted-certificates|pki:insert-template|pki:insert-signed-certificates|pki:insert-certificate-revocation-list|pki:get-trusted-certificate-ids|pki:get-template-ids|pki:get-template-certificate-authority|pki:get-template-by-name|pki:get-template|pki:get-pending-certificate-requests-xml|pki:get-pending-certificate-requests-pem|pki:get-pending-certificate-request|pki:get-certificates-for-template-xml|pki:get-certificates-for-template|pki:get-certificates|pki:get-certificate-xml|pki:get-certificate-pem|pki:get-certificate|pki:generate-temporary-certificate-if-necessary|pki:generate-temporary-certificate|pki:generate-template-certificate-authority|pki:generate-certificate-request|pki:delete-template|pki:delete-certificate|pki:create-template|pdf:make-toc|pdf:insert-toc-headers|pdf:get-toc|pdf:clean|p:status-transition|p:state-transition|p:remove|p:pipelines|p:insert|p:get-by-id|p:get|p:execute|p:create|p:condition|p:collection|p:action|ooxml:runs-merge|ooxml:package-uris|ooxml:package-parts-insert|ooxml:package-parts|msword:clean|mcgm:polygon|mcgm:point|mcgm:geospatial-query-from-elements|mcgm:geospatial-query|mcgm:circle|math:tanh|math:tan|math:sqrt|math:sinh|math:sin|math:pow|math:modf|math:log10|math:log|math:ldexp|math:frexp|math:fmod|math:floor|math:fabs|math:exp|math:cosh|math:cos|math:ceil|math:atan2|math:atan|math:asin|math:acos|map:put|map:map|map:keys|map:get|map:delete|map:count|map:clear|lnk:to|lnk:remove|lnk:insert|lnk:get|lnk:from|lnk:create|kml:polygon|kml:point|kml:interior-polygon|kml:geospatial-query-from-elements|kml:geospatial-query|kml:circle|kml:box|gml:polygon|gml:point|gml:interior-polygon|gml:geospatial-query-from-elements|gml:geospatial-query|gml:circle|gml:box|georss:point|georss:geospatial-query|georss:circle|geo:polygon|geo:point|geo:interior-polygon|geo:geospatial-query-from-elements|geo:geospatial-query|geo:circle|geo:box|fn:zero-or-one|fn:years-from-duration|fn:year-from-dateTime|fn:year-from-date|fn:upper-case|fn:unordered|fn:true|fn:translate|fn:trace|fn:tokenize|fn:timezone-from-time|fn:timezone-from-dateTime|fn:timezone-from-date|fn:sum|fn:subtract-dateTimes-yielding-yearMonthDuration|fn:subtract-dateTimes-yielding-dayTimeDuration|fn:substring-before|fn:substring-after|fn:substring|fn:subsequence|fn:string-to-codepoints|fn:string-pad|fn:string-length|fn:string-join|fn:string|fn:static-base-uri|fn:starts-with|fn:seconds-from-time|fn:seconds-from-duration|fn:seconds-from-dateTime|fn:round-half-to-even|fn:round|fn:root|fn:reverse|fn:resolve-uri|fn:resolve-QName|fn:replace|fn:remove|fn:QName|fn:prefix-from-QName|fn:position|fn:one-or-more|fn:number|fn:not|fn:normalize-unicode|fn:normalize-space|fn:node-name|fn:node-kind|fn:nilled|fn:namespace-uri-from-QName|fn:namespace-uri-for-prefix|fn:namespace-uri|fn:name|fn:months-from-duration|fn:month-from-dateTime|fn:month-from-date|fn:minutes-from-time|fn:minutes-from-duration|fn:minutes-from-dateTime|fn:min|fn:max|fn:matches|fn:lower-case|fn:local-name-from-QName|fn:local-name|fn:last|fn:lang|fn:iri-to-uri|fn:insert-before|fn:index-of|fn:in-scope-prefixes|fn:implicit-timezone|fn:idref|fn:id|fn:hours-from-time|fn:hours-from-duration|fn:hours-from-dateTime|fn:floor|fn:false|fn:expanded-QName|fn:exists|fn:exactly-one|fn:escape-uri|fn:escape-html-uri|fn:error|fn:ends-with|fn:encode-for-uri|fn:empty|fn:document-uri|fn:doc-available|fn:doc|fn:distinct-values|fn:distinct-nodes|fn:default-collation|fn:deep-equal|fn:days-from-duration|fn:day-from-dateTime|fn:day-from-date|fn:data|fn:current-time|fn:current-dateTime|fn:current-date|fn:count|fn:contains|fn:concat|fn:compare|fn:collection|fn:codepoints-to-string|fn:codepoint-equal|fn:ceiling|fn:boolean|fn:base-uri|fn:avg|fn:adjust-time-to-timezone|fn:adjust-dateTime-to-timezone|fn:adjust-date-to-timezone|fn:abs|feed:unsubscribe|feed:subscription|feed:subscribe|feed:request|feed:item|feed:description|excel:clean|entity:enrich|dom:set-pipelines|dom:set-permissions|dom:set-name|dom:set-evaluation-context|dom:set-domain-scope|dom:set-description|dom:remove-pipeline|dom:remove-permissions|dom:remove|dom:get|dom:evaluation-context|dom:domains|dom:domain-scope|dom:create|dom:configuration-set-restart-user|dom:configuration-set-permissions|dom:configuration-set-evaluation-context|dom:configuration-set-default-domain|dom:configuration-get|dom:configuration-create|dom:collection|dom:add-pipeline|dom:add-permissions|dls:retention-rules|dls:retention-rule-remove|dls:retention-rule-insert|dls:retention-rule|dls:purge|dls:node-expand|dls:link-references|dls:link-expand|dls:documents-query|dls:document-versions-query|dls:document-version-uri|dls:document-version-query|dls:document-version-delete|dls:document-version-as-of|dls:document-version|dls:document-update|dls:document-unmanage|dls:document-set-quality|dls:document-set-property|dls:document-set-properties|dls:document-set-permissions|dls:document-set-collections|dls:document-retention-rules|dls:document-remove-properties|dls:document-remove-permissions|dls:document-remove-collections|dls:document-purge|dls:document-manage|dls:document-is-managed|dls:document-insert-and-manage|dls:document-include-query|dls:document-history|dls:document-get-permissions|dls:document-extract-part|dls:document-delete|dls:document-checkout-status|dls:document-checkout|dls:document-checkin|dls:document-add-properties|dls:document-add-permissions|dls:document-add-collections|dls:break-checkout|dls:author-query|dls:as-of-query|dbk:convert|dbg:wait|dbg:value|dbg:stopped|dbg:stop|dbg:step|dbg:status|dbg:stack|dbg:out|dbg:next|dbg:line|dbg:invoke|dbg:function|dbg:finish|dbg:expr|dbg:eval|dbg:disconnect|dbg:detach|dbg:continue|dbg:connect|dbg:clear|dbg:breakpoints|dbg:break|dbg:attached|dbg:attach|cvt:save-converted-documents|cvt:part-uri|cvt:destination-uri|cvt:basepath|cvt:basename|cts:words|cts:word-query-weight|cts:word-query-text|cts:word-query-options|cts:word-query|cts:word-match|cts:walk|cts:uris|cts:uri-match|cts:train|cts:tokenize|cts:thresholds|cts:stem|cts:similar-query-weight|cts:similar-query-nodes|cts:similar-query|cts:shortest-distance|cts:search|cts:score|cts:reverse-query-weight|cts:reverse-query-nodes|cts:reverse-query|cts:remainder|cts:registered-query-weight|cts:registered-query-options|cts:registered-query-ids|cts:registered-query|cts:register|cts:query|cts:quality|cts:properties-query-query|cts:properties-query|cts:polygon-vertices|cts:polygon|cts:point-longitude|cts:point-latitude|cts:point|cts:or-query-queries|cts:or-query|cts:not-query-weight|cts:not-query-query|cts:not-query|cts:near-query-weight|cts:near-query-queries|cts:near-query-options|cts:near-query-distance|cts:near-query|cts:highlight|cts:geospatial-co-occurrences|cts:frequency|cts:fitness|cts:field-words|cts:field-word-query-weight|cts:field-word-query-text|cts:field-word-query-options|cts:field-word-query-field-name|cts:field-word-query|cts:field-word-match|cts:entity-highlight|cts:element-words|cts:element-word-query-weight|cts:element-word-query-text|cts:element-word-query-options|cts:element-word-query-element-name|cts:element-word-query|cts:element-word-match|cts:element-values|cts:element-value-ranges|cts:element-value-query-weight|cts:element-value-query-text|cts:element-value-query-options|cts:element-value-query-element-name|cts:element-value-query|cts:element-value-match|cts:element-value-geospatial-co-occurrences|cts:element-value-co-occurrences|cts:element-range-query-weight|cts:element-range-query-value|cts:element-range-query-options|cts:element-range-query-operator|cts:element-range-query-element-name|cts:element-range-query|cts:element-query-query|cts:element-query-element-name|cts:element-query|cts:element-pair-geospatial-values|cts:element-pair-geospatial-value-match|cts:element-pair-geospatial-query-weight|cts:element-pair-geospatial-query-region|cts:element-pair-geospatial-query-options|cts:element-pair-geospatial-query-longitude-name|cts:element-pair-geospatial-query-latitude-name|cts:element-pair-geospatial-query-element-name|cts:element-pair-geospatial-query|cts:element-pair-geospatial-boxes|cts:element-geospatial-values|cts:element-geospatial-value-match|cts:element-geospatial-query-weight|cts:element-geospatial-query-region|cts:element-geospatial-query-options|cts:element-geospatial-query-element-name|cts:element-geospatial-query|cts:element-geospatial-boxes|cts:element-child-geospatial-values|cts:element-child-geospatial-value-match|cts:element-child-geospatial-query-weight|cts:element-child-geospatial-query-region|cts:element-child-geospatial-query-options|cts:element-child-geospatial-query-element-name|cts:element-child-geospatial-query-child-name|cts:element-child-geospatial-query|cts:element-child-geospatial-boxes|cts:element-attribute-words|cts:element-attribute-word-query-weight|cts:element-attribute-word-query-text|cts:element-attribute-word-query-options|cts:element-attribute-word-query-element-name|cts:element-attribute-word-query-attribute-name|cts:element-attribute-word-query|cts:element-attribute-word-match|cts:element-attribute-values|cts:element-attribute-value-ranges|cts:element-attribute-value-query-weight|cts:element-attribute-value-query-text|cts:element-attribute-value-query-options|cts:element-attribute-value-query-element-name|cts:element-attribute-value-query-attribute-name|cts:element-attribute-value-query|cts:element-attribute-value-match|cts:element-attribute-value-geospatial-co-occurrences|cts:element-attribute-value-co-occurrences|cts:element-attribute-range-query-weight|cts:element-attribute-range-query-value|cts:element-attribute-range-query-options|cts:element-attribute-range-query-operator|cts:element-attribute-range-query-element-name|cts:element-attribute-range-query-attribute-name|cts:element-attribute-range-query|cts:element-attribute-pair-geospatial-values|cts:element-attribute-pair-geospatial-value-match|cts:element-attribute-pair-geospatial-query-weight|cts:element-attribute-pair-geospatial-query-region|cts:element-attribute-pair-geospatial-query-options|cts:element-attribute-pair-geospatial-query-longitude-name|cts:element-attribute-pair-geospatial-query-latitude-name|cts:element-attribute-pair-geospatial-query-element-name|cts:element-attribute-pair-geospatial-query|cts:element-attribute-pair-geospatial-boxes|cts:document-query-uris|cts:document-query|cts:distance|cts:directory-query-uris|cts:directory-query-depth|cts:directory-query|cts:destination|cts:deregister|cts:contains|cts:confidence|cts:collections|cts:collection-query-uris|cts:collection-query|cts:collection-match|cts:classify|cts:circle-radius|cts:circle-center|cts:circle|cts:box-west|cts:box-south|cts:box-north|cts:box-east|cts:box|cts:bearing|cts:arc-intersection|cts:and-query-queries|cts:and-query-options|cts:and-query|cts:and-not-query-positive-query|cts:and-not-query-negative-query|cts:and-not-query|css:get|css:convert|cpf:success|cpf:failure|cpf:document-set-state|cpf:document-set-processing-status|cpf:document-set-last-updated|cpf:document-set-error|cpf:document-get-state|cpf:document-get-processing-status|cpf:document-get-last-updated|cpf:document-get-error|cpf:check-transition|alert:spawn-matching-actions|alert:rule-user-id-query|alert:rule-set-user-id|alert:rule-set-query|alert:rule-set-options|alert:rule-set-name|alert:rule-set-description|alert:rule-set-action|alert:rule-remove|alert:rule-name-query|alert:rule-insert|alert:rule-id-query|alert:rule-get-user-id|alert:rule-get-query|alert:rule-get-options|alert:rule-get-name|alert:rule-get-id|alert:rule-get-description|alert:rule-get-action|alert:rule-action-query|alert:remove-triggers|alert:make-rule|alert:make-log-action|alert:make-config|alert:make-action|alert:invoke-matching-actions|alert:get-my-rules|alert:get-all-rules|alert:get-actions|alert:find-matching-rules|alert:create-triggers|alert:config-set-uri|alert:config-set-trigger-ids|alert:config-set-options|alert:config-set-name|alert:config-set-description|alert:config-set-cpf-domain-names|alert:config-set-cpf-domain-ids|alert:config-insert|alert:config-get-uri|alert:config-get-trigger-ids|alert:config-get-options|alert:config-get-name|alert:config-get-id|alert:config-get-description|alert:config-get-cpf-domain-names|alert:config-get-cpf-domain-ids|alert:config-get|alert:config-delete|alert:action-set-options|alert:action-set-name|alert:action-set-module-root|alert:action-set-module-db|alert:action-set-module|alert:action-set-description|alert:action-remove|alert:action-insert|alert:action-get-options|alert:action-get-name|alert:action-get-module-root|alert:action-get-module-db|alert:action-get-module|alert:action-get-description|zero-or-one|years-from-duration|year-from-dateTime|year-from-date|upper-case|unordered|true|translate|trace|tokenize|timezone-from-time|timezone-from-dateTime|timezone-from-date|sum|subtract-dateTimes-yielding-yearMonthDuration|subtract-dateTimes-yielding-dayTimeDuration|substring-before|substring-after|substring|subsequence|string-to-codepoints|string-pad|string-length|string-join|string|static-base-uri|starts-with|seconds-from-time|seconds-from-duration|seconds-from-dateTime|round-half-to-even|round|root|reverse|resolve-uri|resolve-QName|replace|remove|QName|prefix-from-QName|position|one-or-more|number|not|normalize-unicode|normalize-space|node-name|node-kind|nilled|namespace-uri-from-QName|namespace-uri-for-prefix|namespace-uri|name|months-from-duration|month-from-dateTime|month-from-date|minutes-from-time|minutes-from-duration|minutes-from-dateTime|min|max|matches|lower-case|local-name-from-QName|local-name|last|lang|iri-to-uri|insert-before|index-of|in-scope-prefixes|implicit-timezone|idref|id|hours-from-time|hours-from-duration|hours-from-dateTime|floor|false|expanded-QName|exists|exactly-one|escape-uri|escape-html-uri|error|ends-with|encode-for-uri|empty|document-uri|doc-available|doc|distinct-values|distinct-nodes|default-collation|deep-equal|days-from-duration|day-from-dateTime|day-from-date|data|current-time|current-dateTime|current-date|count|contains|concat|compare|collection|codepoints-to-string|codepoint-equal|ceiling|boolean|base-uri|avg|adjust-time-to-timezone|adjust-dateTime-to-timezone|adjust-date-to-timezone|abs)\\b/],\n[\"pln\",/^[\\w:-]+/],[\"pln\",/^[\\t\\n\\r \\xa0]+/]]),[\"xq\",\"xquery\"]);\n"
  },
  {
    "path": "packages/code-prettify/lang-yaml.js",
    "content": "var a=null;\nPR.registerLangHandler(PR.createSimpleLexer([[\"pun\",/^[:>?|]+/,a,\":|>?\"],[\"dec\",/^%(?:YAML|TAG)[^\\n\\r#]+/,a,\"%\"],[\"typ\",/^&\\S+/,a,\"&\"],[\"typ\",/^!\\S*/,a,\"!\"],[\"str\",/^\"(?:[^\"\\\\]|\\\\.)*(?:\"|$)/,a,'\"'],[\"str\",/^'(?:[^']|'')*(?:'|$)/,a,\"'\"],[\"com\",/^#[^\\n\\r]*/,a,\"#\"],[\"pln\",/^\\s+/,a,\" \\t\\r\\n\"]],[[\"dec\",/^(?:---|\\.\\.\\.)(?:[\\n\\r]|$)/],[\"pun\",/^-/],[\"kwd\",/^\\w+:[\\n\\r ]/],[\"pln\",/^\\w+/]]),[\"yaml\",\"yml\"]);\n"
  },
  {
    "path": "packages/code-prettify/package.js",
    "content": "// Source: http://code.google.com/p/google-code-prettify\n\n// XXX this sucks. I would much rather do this processing at\n// bundle-time on the server, not in the client. (though I'd like to\n// support both..)\n\nvar path = Npm.require('path');\n\nPackage.describe({\n  summary: \"Syntax highlighting of code, from Google\",\n  version: \"1.0.10\"\n});\n\n// XXX this code dumps symbols into the global namespace (directly\n// onto 'window'.) we need to fix that.\nPackage.onUse(function (api) {\n  api.addFiles([\n    'prettify.js',\n    'prettify.css',\n    path.join('styles', 'sunburst.css')], \"client\");\n});\n"
  },
  {
    "path": "packages/code-prettify/prettify.css",
    "content": ".pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}"
  },
  {
    "path": "packages/code-prettify/prettify.js",
    "content": "var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;\n(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:\"0\"<=b&&b<=\"7\"?parseInt(a.substring(1),8):b===\"u\"||b===\"x\"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?\"\\\\x0\":\"\\\\x\")+a.toString(16);a=String.fromCharCode(a);if(a===\"\\\\\"||a===\"-\"||a===\"[\"||a===\"]\")a=\"\\\\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\S\\s]|[^\\\\]/g),a=\n[],b=[],o=f[0]===\"^\",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&\"-\"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=[\"[\"];o&&b.push(\"^\");b.push.apply(b,a);for(c=0;c<\nf.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push(\"-\"),b.push(e(i[1])));b.push(\"]\");return b.join(\"\")}function y(a){for(var f=a.source.match(/\\[(?:[^\\\\\\]]|\\\\[\\S\\s])*]|\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\\\d+|\\\\[^\\dux]|\\(\\?[!:=]|[()^]|[^()[\\\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j===\"(\"?++i:\"\\\\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j===\"(\"?(++i,d[i]===void 0&&(f[c]=\"(?:\")):\"\\\\\"===j.charAt(0)&&\n(j=+j.substring(1))&&j<=i&&(f[c]=\"\\\\\"+d[i]);for(i=c=0;c<b;++c)\"^\"===f[c]&&\"^\"!==f[c+1]&&(f[c]=\"\");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a===\"[\"?f[c]=h(j):a!==\"\\\\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return\"[\"+String.fromCharCode(a&-33,a|32)+\"]\"}));return f.join(\"\")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\\\u[\\da-f]{4}|\\\\x[\\da-f]{2}|\\\\[^UXux]/gi,\"\"))){s=!0;l=!1;break}}for(var r=\n{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(\"\"+g);n.push(\"(?:\"+y(g)+\")\")}return RegExp(n.join(\"|\"),l?\"gi\":\"g\")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if(\"BR\"===g||\"LI\"===g)h[s]=\"\\n\",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\\r\\n?/g,\"\\n\"):g.replace(/[\\t\\n\\r ]+/g,\" \"),h[s]=g,t[s<<1]=y,y+=g.length,\nt[s++<<1|1]=a)}}var e=/(?:^|\\s)nocode(?:\\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue(\"white-space\"));var p=l&&\"pre\"===l.substring(0,3);m(a);return{a:h.join(\"\").replace(/\\n$/,\"\"),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,\"pln\"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===\n\"string\")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b=\"pln\")}if((c=b.length>=5&&\"lang-\"===b.substring(0,5))&&!(o&&typeof o[1]===\"string\"))c=!1,b=\"src\";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),\nl=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=\"\"+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\\S\\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push([\"str\",/^(?:'''(?:[^'\\\\]|\\\\[\\S\\s]|''?(?=[^']))*(?:'''|$)|\"\"\"(?:[^\"\\\\]|\\\\[\\S\\s]|\"\"?(?=[^\"]))*(?:\"\"\"|$)|'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$)|\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$))/,q,\"'\\\"\"]):a.multiLineStrings?m.push([\"str\",/^(?:'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$)|\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)|`(?:[^\\\\`]|\\\\[\\S\\s])*(?:`|$))/,\nq,\"'\\\"`\"]):m.push([\"str\",/^(?:'(?:[^\\n\\r'\\\\]|\\\\.)*(?:'|$)|\"(?:[^\\n\\r\"\\\\]|\\\\.)*(?:\"|$))/,q,\"\\\"'\"]);a.verbatimStrings&&e.push([\"str\",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push([\"com\",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,\"#\"]):m.push([\"com\",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\\b|[^\\n\\r]*)/,q,\"#\"]),e.push([\"str\",/^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h|[a-z]\\w*)>/,q])):m.push([\"com\",/^#[^\\n\\r]*/,\nq,\"#\"]));a.cStyleComments&&(e.push([\"com\",/^\\/\\/[^\\n\\r]*/,q]),e.push([\"com\",/^\\/\\*[\\S\\s]*?(?:\\*\\/|$)/,q]));a.regexLiterals&&e.push([\"lang-regex\",/^(?:^^\\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|,|-=|->|\\/|\\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\\^=|\\^\\^|\\^\\^=|{|\\||\\|=|\\|\\||\\|\\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*(\\/(?=[^*/])(?:[^/[\\\\]|\\\\[\\S\\s]|\\[(?:[^\\\\\\]]|\\\\[\\S\\s])*(?:]|$))+\\/)/]);(h=a.types)&&e.push([\"typ\",h]);a=(\"\"+a.keywords).replace(/^ | $/g,\n\"\");a.length&&e.push([\"kwd\",RegExp(\"^(?:\"+a.replace(/[\\s,]+/g,\"|\")+\")\\\\b\"),q]);m.push([\"pln\",/^\\s+/,q,\" \\r\\n\\t\\xa0\"]);e.push([\"lit\",/^@[$_a-z][\\w$@]*/i,q],[\"typ\",/^(?:[@_]?[A-Z]+[a-z][\\w$@]*|\\w+_t\\b)/,q],[\"pln\",/^[$_a-z][\\w$@]*/i,q],[\"lit\",/^(?:0x[\\da-f]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+-]?\\d+)?)[a-z]*/i,q,\"0123456789\"],[\"pln\",/^\\\\[\\S\\s]?/,q],[\"pun\",/^.[^\\s\\w\"-$'./@\\\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if(\"BR\"===a.nodeName)h(a),\na.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}\nfor(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\\s)nocode(?:\\s|$)/,t=/\\r\\n?|\\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue(\"white-space\"));var p=l&&\"pre\"===l.substring(0,3);for(l=s.createElement(\"LI\");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute(\"value\",\nm);var r=s.createElement(\"OL\");r.className=\"linenums\";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className=\"L\"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode(\"\\xa0\")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn(\"cannot override language handler %s\",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\\s*</.test(m)?\"default-markup\":\"default-code\";return A[a]}function E(a){var m=\na.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\\bMSIE\\b/.test(navigator.userAgent),m=/\\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,\"\\r\"));i.nodeValue=\nj;var u=i.ownerDocument,v=u.createElement(\"SPAN\");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){\"console\"in window&&console.log(w&&w.stack?w.stack:w)}}var v=[\"break,continue,do,else,for,if,return,while\"],w=[[v,\"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"],\n\"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof\"],F=[w,\"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where\"],G=[w,\"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient\"],\nH=[G,\"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var\"],w=[w,\"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN\"],I=[v,\"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None\"],\nJ=[v,\"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END\"],v=[v,\"case,done,elif,esac,eval,fi,function,in,local,set,then,until\"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)/,N=/\\S/,O=u({keywords:[F,H,w,\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\"+\nI,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,[\"default-code\"]);k(x([],[[\"pln\",/^[^<?]+/],[\"dec\",/^<!\\w[^>]*(?:>|$)/],[\"com\",/^<\\!--[\\S\\s]*?(?:--\\>|$)/],[\"lang-\",/^<\\?([\\S\\s]+?)(?:\\?>|$)/],[\"lang-\",/^<%([\\S\\s]+?)(?:%>|$)/],[\"pun\",/^(?:<[%?]|[%?]>)/],[\"lang-\",/^<xmp\\b[^>]*>([\\S\\s]+?)<\\/xmp\\b[^>]*>/i],[\"lang-js\",/^<script\\b[^>]*>([\\S\\s]*?)(<\\/script\\b[^>]*>)/i],[\"lang-css\",/^<style\\b[^>]*>([\\S\\s]*?)(<\\/style\\b[^>]*>)/i],[\"lang-in.tag\",/^(<\\/?[a-z][^<>]*>)/i]]),\n[\"default-markup\",\"htm\",\"html\",\"mxml\",\"xhtml\",\"xml\",\"xsl\"]);k(x([[\"pln\",/^\\s+/,q,\" \\t\\r\\n\"],[\"atv\",/^(?:\"[^\"]*\"?|'[^']*'?)/,q,\"\\\"'\"]],[[\"tag\",/^^<\\/?[a-z](?:[\\w-.:]*\\w)?|\\/?>$/i],[\"atn\",/^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],[\"lang-uq.val\",/^=\\s*([^\\s\"'>]*(?:[^\\s\"'/>]|\\/(?=\\s)))/],[\"pun\",/^[/<->]+/],[\"lang-js\",/^on\\w+\\s*=\\s*\"([^\"]+)\"/i],[\"lang-js\",/^on\\w+\\s*=\\s*'([^']+)'/i],[\"lang-js\",/^on\\w+\\s*=\\s*([^\\s\"'>]+)/i],[\"lang-css\",/^style\\s*=\\s*\"([^\"]+)\"/i],[\"lang-css\",/^style\\s*=\\s*'([^']+)'/i],[\"lang-css\",\n/^style\\s*=\\s*([^\\s\"'>]+)/i]]),[\"in.tag\"]);k(x([],[[\"atv\",/^[\\S\\s]+/]]),[\"uq.val\"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),[\"c\",\"cc\",\"cpp\",\"cxx\",\"cyc\",\"m\"]);k(u({keywords:\"null,true,false\"}),[\"json\"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),[\"cs\"]);k(u({keywords:G,cStyleComments:!0}),[\"java\"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),[\"bsh\",\"csh\",\"sh\"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),\n[\"cv\",\"py\"]);k(u({keywords:\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),[\"perl\",\"pl\",\"pm\"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),[\"rb\"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),[\"js\"]);k(u({keywords:\"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes\",\nhashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),[\"coffee\"]);k(x([],[[\"str\",/^[\\S\\s]+/]]),[\"regex\"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement(\"PRE\");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf(\"prettyprint\")>=0){var k=k.match(g),f,b;if(b=\n!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&\"CODE\"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName===\"pre\"||o.tagName===\"code\"||o.tagName===\"xmp\")&&o.className&&o.className.indexOf(\"prettyprint\")>=0){b=!0;break}b||((b=(b=n.className.match(/\\blinenums\\b(?::(\\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,\n250):a&&a()}for(var e=[document.getElementsByTagName(\"pre\"),document.getElementsByTagName(\"code\"),document.getElementsByTagName(\"xmp\")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\\blang(?:uage)?-([\\w.]+)(?!\\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:\"atn\",PR_ATTRIB_VALUE:\"atv\",PR_COMMENT:\"com\",PR_DECLARATION:\"dec\",PR_KEYWORD:\"kwd\",PR_LITERAL:\"lit\",\nPR_NOCODE:\"nocode\",PR_PLAIN:\"pln\",PR_PUNCTUATION:\"pun\",PR_SOURCE:\"src\",PR_STRING:\"str\",PR_TAG:\"tag\",PR_TYPE:\"typ\"}})();\n"
  },
  {
    "path": "packages/code-prettify/styles/desert.css",
    "content": "/* desert scheme ported from vim to google prettify */\r\npre { display: block; background-color: #333 }\r\npre .nocode { background-color: none; color: #000 }\r\npre .str { color: #ffa0a0 } /* string  - pink */\r\npre .kwd { color: #f0e68c; font-weight: bold }\r\npre .com { color: #87ceeb } /* comment - skyblue */\r\npre .typ { color: #98fb98 } /* type    - lightgreen */\r\npre .lit { color: #cd5c5c } /* literal - darkred */\r\npre .pun { color: #fff }    /* punctuation */\r\npre .pln { color: #fff }    /* plaintext */\r\npre .tag { color: #f0e68c; font-weight: bold } /* html/xml tag    - lightyellow */\r\npre .atn { color: #bdb76b; font-weight: bold } /* attribute name  - khaki */\r\npre .atv { color: #ffa0a0 } /* attribute value - pink */\r\npre .dec { color: #98fb98 } /* decimal         - lightgreen */\r\n\r\n/* Specify class=linenums on a pre to get line numbering */\r\nol.linenums { margin-top: 0; margin-bottom: 0; color: #AEAEAE } /* IE indents via margin-left */\r\nli.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8 { list-style-type: none }\r\n/* Alternate shading for lines */\r\nli.L1,li.L3,li.L5,li.L7,li.L9 { }\r\n\r\n@media print {\r\n  pre { background-color: none }\r\n  pre .str, code .str { color: #060 }\r\n  pre .kwd, code .kwd { color: #006; font-weight: bold }\r\n  pre .com, code .com { color: #600; font-style: italic }\r\n  pre .typ, code .typ { color: #404; font-weight: bold }\r\n  pre .lit, code .lit { color: #044 }\r\n  pre .pun, code .pun { color: #440 }\r\n  pre .pln, code .pln { color: #000 }\r\n  pre .tag, code .tag { color: #006; font-weight: bold }\r\n  pre .atn, code .atn { color: #404 }\r\n  pre .atv, code .atv { color: #060 }\r\n}\r\n"
  },
  {
    "path": "packages/code-prettify/styles/sunburst.css",
    "content": "/* Pretty printing styles. Used with prettify.js. */\n/* Vim sunburst theme by David Leibovic */\n\npre .str, code .str { color: #65B042; } /* string  - green */\npre .kwd, code .kwd { color: #E28964; } /* keyword - dark pink */\npre .com, code .com { color: #AEAEAE; font-style: italic; } /* comment - gray */\npre .typ, code .typ { color: #89bdff; } /* type - light blue */\npre .lit, code .lit { color: #3387CC; } /* literal - blue */\npre .pun, code .pun { color: #fff; } /* punctuation - white */\npre .pln, code .pln { color: #fff; } /* plaintext - white */\npre .tag, code .tag { color: #89bdff; } /* html/xml tag    - light blue */\npre .atn, code .atn { color: #bdb76b; } /* html/xml attribute name  - khaki */\npre .atv, code .atv { color: #65B042; } /* html/xml attribute value - green */\npre .dec, code .dec { color: #3387CC; } /* decimal - blue */\n\npre.prettyprint, code.prettyprint {\n\tbackground-color: #000;\n\t-moz-border-radius: 8px;\n\t-webkit-border-radius: 8px;\n\t-o-border-radius: 8px;\n\t-ms-border-radius: 8px;\n\t-khtml-border-radius: 8px;\n\tborder-radius: 8px;\n}\n\npre.prettyprint {\n\twidth: 95%;\n\tmargin: 1em auto;\n\tpadding: 1em;\n\twhite-space: pre-wrap;\n}\n\n\n/* Specify class=linenums on a pre to get line numbering */\nol.linenums { margin-top: 0; margin-bottom: 0; color: #AEAEAE; } /* IE indents via margin-left */\nli.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8 { list-style-type: none }\n/* Alternate shading for lines */\nli.L1,li.L3,li.L5,li.L7,li.L9 { }\n\n@media print {\n  pre .str, code .str { color: #060; }\n  pre .kwd, code .kwd { color: #006; font-weight: bold; }\n  pre .com, code .com { color: #600; font-style: italic; }\n  pre .typ, code .typ { color: #404; font-weight: bold; }\n  pre .lit, code .lit { color: #044; }\n  pre .pun, code .pun { color: #440; }\n  pre .pln, code .pln { color: #000; }\n  pre .tag, code .tag { color: #006; font-weight: bold; }\n  pre .atn, code .atn { color: #404; }\n  pre .atv, code .atv { color: #060; }\n}\n"
  },
  {
    "path": "packages/coffeescript/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/coffeescript/.npm/plugin/compileCoffeescript/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/coffeescript/.npm/plugin/compileCoffeescript/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/coffeescript/.npm/plugin/compileCoffeescript/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"coffee-script\": {\n      \"version\": \"1.10.0\",\n      \"resolved\": \"https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz\",\n      \"from\": \"coffee-script@1.10.0\"\n    },\n    \"source-map\": {\n      \"version\": \"0.5.6\",\n      \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz\",\n      \"from\": \"https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/coffeescript/README.md",
    "content": "# coffeescript\n\n[CoffeeScript](http://coffeescript.org/) is a little language that\ncompiles into JavaScript. It provides a simple syntax without lots of\nbraces and parentheses.  The code compiles one-to-one into the\nequivalent JS, and there is no interpretation at runtime.\n\nCoffeeScript is supported on both the client and the server. Files\nending with `.coffee`, `.litcoffee`, or `.coffee.md` are automatically\ncompiled to JavaScript.\n\n### Namespacing and CoffeeScript\n\nHere's how CoffeeScript works with Meteor's namespacing.\n\n* Per the usual CoffeeScript convention, CoffeeScript variables are\n  file-scoped by default (visible only in the `.coffee` file where\n  they are defined.)\n\n* When writing a package, CoffeeScript-defined variables can be\n  exported like any other variable (see [Writing\n  Packages](#writingpackages)). Exporting a variable pulls it up to\n  package scope, meaning that it will be visible to all of the code in\n  your app or package (both `.js` and `.coffee` files).\n\n* Package-scope variables declared in `.js` files are visible in any\n  `.coffee` files in the same app or project.\n\n* There is no way to make a package-scope variable from a `.coffee`\n  file other than exporting it. We couldn't figure out a way to make\n  this fit naturally inside the CoffeeScript language. If you want to\n  use package-scope variables with CoffeeScript, one way is to make a\n  short `.js` file that declares all of your package-scope\n  variables. They can then be read, mutated, and extended in `.coffee`\n  files.\n\n* If you want to share variables between `.coffee` files in the same\n  package, and don't want to separately declare them in a `.js` file,\n  we have an experimental feature that you may like. An object called\n  `share` is visible in CoffeeScript code and is shared across all\n  `.coffee` files in the same package. So, you can write `share.foo`\n  for a value that is shared between all CoffeeScript code in a\n  package, but doesn't escape that package.\n\nHeavy CoffeeScript users, please let us know how this arrangement\nworks for you, whether `share` is helpful for you, and anything else\nyou'd like to see changed.\n\n### Modules and CoffeeScript\n\nSee [Modules » CoffeeScript Syntax](http://docs.meteor.com/packages/modules.html#CoffeeScript).\n"
  },
  {
    "path": "packages/coffeescript/package.js",
    "content": "Package.describe({\n  summary: \"Javascript dialect with fewer braces and semicolons\",\n  version: \"1.1.2_1\"\n});\n\nPackage.registerBuildPlugin({\n  name: \"compileCoffeescript\",\n  use: ['caching-compiler', 'ecmascript'],\n  sources: ['plugin/compile-coffeescript.js'],\n  npmDependencies: {\n    \"coffee-script\": \"1.10.0\",\n    \"source-map\": \"0.5.6\"\n  }\n});\n\nPackage.onUse(function (api) {\n  api.use('isobuild:compiler-plugin@1.0.0');\n  api.use('babel-compiler');\n\n  // Because the CoffeeScript plugin now calls\n  // BabelCompiler.prototype.processOneFileForTarget for any raw\n  // JavaScript enclosed by backticks, it must provide the same runtime\n  // environment that the 'ecmascript' package provides. The following\n  // api.imply calls should match those in ../ecmascript/package.js,\n  // except that coffeescript does not api.imply('modules').\n  api.imply('ecmascript-runtime');\n  api.imply('babel-runtime');\n  api.imply('promise');\n});\n\nPackage.onTest(function (api) {\n  api.use(['coffeescript', 'tinytest']);\n  api.use(['coffeescript-test-helper', 'ecmascript'], ['client', 'server']); // Need ecmascript to compile tests/es2015_module.js\n  api.addFiles('tests/bare_test_setup.coffee', ['client'], {bare: true});\n  api.addFiles('tests/bare_tests.js', ['client']);\n  api.addFiles([\n    'tests/coffeescript_test_setup.js',\n    'tests/coffeescript_tests.coffee',\n    'tests/coffeescript_strict_tests.coffee',\n    'tests/es2015_module.js',\n    'tests/litcoffeescript_tests.litcoffee',\n    'tests/litcoffeescript_tests.coffee.md',\n    'tests/coffeescript_tests.js'\n  ], ['client', 'server']);\n});\n"
  },
  {
    "path": "packages/coffeescript/plugin/compile-coffeescript.js",
    "content": "import {\n  SourceMapConsumer,\n  SourceMapGenerator,\n} from 'source-map';\nimport coffee from 'coffee-script';\nimport { BabelCompiler } from 'meteor/babel-compiler';\n\n// The coffee-script compiler overrides Error.prepareStackTrace, mostly for the\n// use of coffee.run which we don't use.  This conflicts with the tool's use of\n// Error.prepareStackTrace to properly show error messages in linked code.\n// Restore the tool's one after coffee-script clobbers it at import time.\nif (Error.METEOR_prepareStackTrace) {\n  Error.prepareStackTrace = Error.METEOR_prepareStackTrace;\n}\n\nPlugin.registerCompiler({\n  extensions: ['coffee', 'litcoffee', 'coffee.md']\n}, () => new CoffeeCompiler());\n\n// The CompileResult for this CachingCompiler is a {source, sourceMap} object.\n\nexport class CoffeeCompiler extends CachingCompiler {\n  constructor() {\n    super({\n      compilerName: 'coffeescript',\n      defaultCacheSize: 1024*1024*10,\n    });\n\n    this.babelCompiler = new BabelCompiler({\n      // Prevent Babel from importing helpers from babel-runtime, since\n      // the CoffeeScript plugin does not imply the modules package, which\n      // means require may not be defined. Note that this in no way\n      // prevents CoffeeScript projects from using the modules package and\n      // putting require or import statements within backticks; it just\n      // won't happen automatically because of Babel.\n      runtime: false\n    });\n  }\n\n  _getCompileOptions(inputFile) {\n    return {\n      bare: true,\n      filename: inputFile.getPathInPackage(),\n      literate: inputFile.getExtension() !== 'coffee',\n      // Return a source map.\n      sourceMap: true,\n      // Include the original source in the source map (sourcesContent field).\n      inline: true,\n      // This becomes the \"file\" field of the source map.\n      generatedFile: '/' + this._outputFilePath(inputFile),\n      // This becomes the \"sources\" field of the source map.\n      sourceFiles: [inputFile.getDisplayPath()],\n    };\n  }\n\n  _outputFilePath(inputFile) {\n    return inputFile.getPathInPackage() + '.js';\n  }\n\n  getCacheKey(inputFile) {\n    return [\n      inputFile.getSourceHash(),\n      inputFile.getDeclaredExports(),\n      this._getCompileOptions(inputFile),\n    ];\n  }\n\n  compileOneFile(inputFile) {\n    const source = inputFile.getContentsAsString();\n    const compileOptions = this._getCompileOptions(inputFile);\n\n    let output;\n    try {\n      output = coffee.compile(source, compileOptions);\n    } catch (e) {\n      inputFile.error({\n        message: e.message,\n        line: e.location && (e.location.first_line + 1),\n        column: e.location && (e.location.first_column + 1)\n      });\n      return null;\n    }\n\n    let sourceMap = JSON.parse(output.v3SourceMap);\n\n    if (source.indexOf('`') !== -1) {\n      // If source contains backticks, pass the coffee output through babel-compiler\n      const doubleRoastedCoffee =\n        this.babelCompiler.processOneFileForTarget(inputFile, output.js);\n\n      if (doubleRoastedCoffee != null &&\n          doubleRoastedCoffee.data != null) {\n        output.js = doubleRoastedCoffee.data;\n\n        if (doubleRoastedCoffee.sourceMap) {\n          // Combine the original CoffeeScript source map with the one\n          // produced by this.babelCompiler.processOneFileForTarget.\n          const smg = new SourceMapGenerator(\n            new SourceMapConsumer(doubleRoastedCoffee.sourceMap));\n          smg.applySourceMap(new SourceMapConsumer(sourceMap));\n          sourceMap = smg.toJSON();\n        } else {\n          // If the .coffee file is contained by a node_modules directory,\n          // then BabelCompiler will not transpile it, and there will be\n          // no sourceMap, but that's fine because the original\n          // CoffeeScript sourceMap will still be valid.\n        }\n      }\n    }\n\n    return addSharedHeader(stripExportedVars(\n      output.js,\n      inputFile.getDeclaredExports().map(e => e.name)\n    ), sourceMap);\n  }\n\n  addCompileResult(inputFile, sourceWithMap) {\n    inputFile.addJavaScript({\n      path: this._outputFilePath(inputFile),\n      sourcePath: inputFile.getPathInPackage(),\n      data: sourceWithMap.source,\n      sourceMap: sourceWithMap.sourceMap,\n      bare: inputFile.getFileOptions().bare\n    });\n  }\n\n  compileResultSize(sourceWithMap) {\n    return sourceWithMap.source.length +\n      this.sourceMapSize(sourceWithMap.sourceMap);\n  }\n}\n\nfunction stripExportedVars(source, exports) {\n  if (!exports || !exports.length)\n    return source;\n  const lines = source.split(\"\\n\");\n\n  // We make the following assumptions, based on the output of CoffeeScript\n  // 1.7.1.\n  //   - The var declaration in question is not indented and is the first such\n  //     var declaration.  (CoffeeScript only produces one var line at each\n  //     scope and there's only one top-level scope.)  All relevant variables\n  //     are actually on this line.\n  //   - The user hasn't used a ###-comment containing a line that looks like\n  //     a var line, to produce something like\n  //        /* bla\n  //        var foo;\n  //        */\n  //     before an actual var line.  (ie, we do NOT attempt to figure out if\n  //     we're inside a /**/ comment, which is produced by ### comments.)\n  //   - The var in question is not assigned to in the declaration, nor are any\n  //     other vars on this line. (CoffeeScript does produce some assignments\n  //     but only for internal helpers generated by CoffeeScript, and they end\n  //     up on subsequent lines.)\n  // XXX relax these assumptions by doing actual JS parsing (eg with jsparse).\n  //     I'd do this now, but there's no easy way to \"unparse\" a jsparse AST.\n  //     Or alternatively, hack the compiler to allow us to specify unbound\n  //     symbols directly.\n\n  for (let i = 0; i < lines.length; i++) {\n    const line = lines[i];\n    const match = /^var (.+)([,;])$/.exec(line);\n    if (!match)\n      continue;\n\n    // If there's an assignment on this line, we assume that there are ONLY\n    // assignments and that the var we are looking for is not declared. (Part\n    // of our strong assumption about the layout of this code.)\n    if (match[1].indexOf('=') !== -1)\n      continue;\n\n    // We want to replace the line with something no shorter, so that all\n    // records in the source map continue to point at valid\n    // characters.\n    function replaceLine(x) {\n      if (x.length >= lines[i].length) {\n        lines[i] = x;\n      } else {\n        lines[i] = x + new Array(1 + (lines[i].length - x.length)).join(' ');\n      }\n    }\n\n    let vars = match[1].split(', ').filter(v => exports.indexOf(v) === -1);\n    if (vars.length) {\n      replaceLine('var ' + vars.join(', ') + match[2]);\n    } else {\n      // We got rid of all the vars on this line. Drop the whole line if this\n      // didn't continue to the next line, otherwise keep just the 'var '.\n      if (match[2] === ';')\n        replaceLine('');\n      else\n        replaceLine('var');\n    }\n    break;\n  }\n\n  return lines.join('\\n');\n}\n\nfunction addSharedHeader(source, sourceMap) {\n  // We want the symbol \"share\" to be visible to all CoffeeScript files in the\n  // package (and shared between them), but not visible to JavaScript\n  // files. (That's because we don't want to introduce two competing ways to\n  // make package-local variables into JS (\"share\" vs assigning to non-var\n  // variables).) The following hack accomplishes that: \"__coffeescriptShare\"\n  // will be visible at the package level and \"share\" at the file level.  This\n  // should work both in \"package\" mode where __coffeescriptShare will be added\n  // as a var in the package closure, and in \"app\" mode where it will end up as\n  // a global.\n  //\n  // This ends in a newline to make the source map easier to adjust.\n  const header = (\"__coffeescriptShare = typeof __coffeescriptShare === 'object' \" +\n                  \"? __coffeescriptShare : {}; \" +\n                  \"var share = __coffeescriptShare;\\n\");\n\n  // If the file begins with \"use strict\", we need to keep that as the first\n  // statement.\n  const processedSource = source.replace(/^(?:((['\"])use strict\\2;)\\n)?/, (match, useStrict) => {\n    if (match) {\n      // There's a \"use strict\"; we keep this as the first statement and insert\n      // our header at the end of the line that it's on. This doesn't change\n      // line numbers or the part of the line that previous may have been\n      // annotated, so we don't need to update the source map.\n      return useStrict + '  ' + header;\n    } else {\n      // There's no use strict, so we can just add the header at the very\n      // beginning. This adds a line to the file, so we update the source map to\n      // add a single un-annotated line to the beginning.\n      sourceMap.mappings = ';' + sourceMap.mappings;\n      return header;\n    }\n  });\n  return {\n    source: processedSource,\n    sourceMap: sourceMap\n  };\n}\n"
  },
  {
    "path": "packages/coffeescript/tests/bare_test_setup.coffee",
    "content": "# Normally, variables should be file-local, but this file is loaded with {bare:\n# true}, so it should be readable by bare_tests.js\n\nVariableSetByCoffeeBareTestSetup = 5678\n"
  },
  {
    "path": "packages/coffeescript/tests/bare_tests.js",
    "content": "Tinytest.add(\"coffeescript - bare\", function (test) {\n  test.equal(VariableSetByCoffeeBareTestSetup, 5678);\n});\n"
  },
  {
    "path": "packages/coffeescript/tests/coffeescript_strict_tests.coffee",
    "content": "'use strict'\n\n# Another variable, which will stay in the var line.\nx = 5\n\n# This adds a utility function to the var line.\ny = []\nx in y\n\nTinytest.add \"coffeescript - shared\", (test) ->\n  test.equal share.coffeeShared, 789\n  test.equal sharedFromJavascript, 135\n"
  },
  {
    "path": "packages/coffeescript/tests/coffeescript_test_setup.js",
    "content": "sharedFromJavascript = 135;\n"
  },
  {
    "path": "packages/coffeescript/tests/coffeescript_tests.coffee",
    "content": "Meteor.__COFFEESCRIPT_PRESENT = true\n\n# This is read in coffeescript_strict_tests.coffee.\nshare.coffeeShared = 789\n\nTinytest.add \"coffeescript - compile\", (test) -> test.isTrue true\n\n\n# import/export statements must be top-level\n`import { Meteor as testingForImportedSymbol123456789 } from \"meteor/meteor\";`\nTinytest.add \"coffeescript - import external package via backticks\", (test) ->\n  test.isTrue testingForImportedSymbol123456789?\n\n`import { testingForImportedModule987654321 } from \"./es2015_module.js\";`\nTinytest.add \"coffeescript - import local module via backticks\", (test) ->\n  test.isTrue testingForImportedModule987654321?\n"
  },
  {
    "path": "packages/coffeescript/tests/coffeescript_tests.js",
    "content": "Tinytest.add(\"coffeescript - presence\", function(test) {\n  test.isTrue(Meteor.__COFFEESCRIPT_PRESENT);\n});\nTinytest.add(\"literate coffeescript - presence\", function(test) {\n  test.isTrue(Meteor.__LITCOFFEESCRIPT_PRESENT);\n  test.isTrue(Meteor.__COFFEEMDSCRIPT_PRESENT);\n});\n\nTinytest.add(\"coffeescript - exported variable\", function(test) {\n  test.equal(COFFEESCRIPT_EXPORTED, 123);\n  test.equal(Package['coffeescript-test-helper'].COFFEESCRIPT_EXPORTED, 123);\n});\n"
  },
  {
    "path": "packages/coffeescript/tests/es2015_module.js",
    "content": "export const testingForImportedModule987654321 = true;\n"
  },
  {
    "path": "packages/coffeescript/tests/litcoffeescript_tests.coffee.md",
    "content": "This file is just the same as `coffeescript_tests.coffee`, first we set a \nproperty, which we check for in `coffeescript_tests.js`, and then a trivial\ntestcase.\n\n    Meteor.__COFFEEMDSCRIPT_PRESENT = true\n    Tinytest.add \"markdown coffeescript - compile\", (test) -> test.isTrue true\n"
  },
  {
    "path": "packages/coffeescript/tests/litcoffeescript_tests.litcoffee",
    "content": "This file is just the same as `coffeescript_tests.coffee`, first we set a \nproperty, which we check for in `coffeescript_tests.js`, and then a trivial\ntestcase.\n\n    Meteor.__LITCOFFEESCRIPT_PRESENT = true\n    Tinytest.add \"literate coffeescript - compile\", (test) -> test.isTrue true\n"
  },
  {
    "path": "packages/coffeescript-test-helper/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/coffeescript-test-helper/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/coffeescript-test-helper/exporting.coffee",
    "content": "COFFEESCRIPT_EXPORTED = 123\n"
  },
  {
    "path": "packages/coffeescript-test-helper/package.js",
    "content": "Package.describe({\n  summary: \"Used by the coffeescript package's tests\",\n  version: \"1.0.7\"\n});\n\nPackage.onUse(function (api) {\n  api.use('coffeescript', ['client', 'server']);\n  api.export('COFFEESCRIPT_EXPORTED');\n  api.addFiles(\"exporting.coffee\", ['client', 'server']);\n});\n"
  },
  {
    "path": "packages/constraint-solver/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/constraint-solver/README.md",
    "content": "# constraint-solver\n\nMeteor Version Solver is an optimizing constraint solver for package\ndependencies. It is used by the Meteor build tool (Isobuild) for apps,\npackages and build plugins.\n\nTo learn more about Meteor Version Solver see the [project page on\nmeteor.com](https://www.meteor.com/version-solver)\n\n"
  },
  {
    "path": "packages/constraint-solver/benchmark-tests.js",
    "content": "// \"Benchmarks\" here are just slow tests of the constraint solver.\n// You can see roughly how long they take by looking at how long the\n// test takes to run.  Because they are slow, they don't run when you\n// run tests unless you turn them on with an environment variable.\n\n// The benchmarks can totally be run on the client, it's just harder to\n// detect the environment variable.\nvar runBenchmarks = Meteor.isServer && !!process.env.CONSTRAINT_SOLVER_BENCHMARK;\n\nvar railsCatalog = getCatalogStub(railsGems);\nvar sinatraCatalog = getCatalogStub(sinatraGems);\n\nrunBenchmarks && Tinytest.add(\"constraint solver - benchmark on gems - sinatra\", function (test) {\n  var r = new ConstraintSolver.PackagesResolver(sinatraCatalog);\n\n  var args = splitArgs({\n    'capistrano': '2.14.2',\n    'data-mapper': '1.2.0',\n    'dm-core': '1.2.0',\n    'dm-sqlite-adapter': '1.2.0',\n    'dm-timestamps': '1.2.0',\n    'haml': '3.1.7',\n    'sass': '3.2.1',\n    'shotgun': '0.9.0',\n    'sinatra': '1.3.5',\n    'sqlite3': '1.3.7'\n  });\n\n  r.resolve(args.dependencies, args.constraints);\n});\n\nrunBenchmarks && Tinytest.add(\"constraint solver - benchmark on gems - rails\", function (test) {\n  var r = new ConstraintSolver.PackagesResolver(railsCatalog);\n\n  var args = splitArgs({\n    'rails': '4.0.4'\n  });\n\n  r.resolve(args.dependencies, args.constraints);\n});\n\nrunBenchmarks && Tinytest.add(\"constraint solver - benchmark on gems - rails, gitlabhq\", function (test) {\n  var r = new ConstraintSolver.PackagesResolver(railsCatalog);\n\n  var args = splitArgs({\n    'rails': '4.0.0',\n    'protected-attributes': null,\n    'rails-observers': null,\n    'actionpack-page-caching': null,\n    'actionpack-action-caching': null,\n    'default-value-for': '3.0.0',\n    'mysql2': null,\n    'devise': '3.0.4',\n    'devise-async': '0.8.0',\n    'omniauth': '1.1.3',\n    'omniauth-google-oauth2': null,\n    'omniauth-twitter': null,\n    'omniauth-github': null,\n    'gitlab-git': '5.7.1',\n    'gitlab-grack': '2.0.0',\n    'gitlab-omniauth-ldap': '1.0.4',\n    'gitlab-gollum-lib': '1.1.0',\n    'gitlab-linguist': '3.0.0',\n    'grape': '0.6.1',\n    'rack-cors': null,\n    'email-validator': '1.4.0',\n    'stamp': null,\n    'enumerize': null,\n    'kaminari': '0.15.1',\n    'haml-rails': null,\n    'carrierwave': null,\n    'fog': '1.3.1',\n    'six': null,\n    'seed-fu': null,\n    'redcarpet': '2.2.2',\n    'github-markup': null,\n    'asciidoctor': null,\n    'unicorn': '4.6.3',\n    'unicorn-worker-killer': null,\n    'state-machine': null,\n    'acts-as-taggable-on': null,\n    'slim': null,\n    'sinatra': null,\n    'sidekiq': null,\n    'httparty': null,\n    'colored': null,\n    'settingslogic': null,\n    'foreman': null,\n    'version-sorter': null,\n    'redis-rails': null,\n    'tinder': '1.9.2',\n    'hipchat': '0.14.0',\n    'gemnasium-gitlab-service': '0.2.1',\n    'slack-notifier': '0.2.0',\n    'd3-rails': '3.1.4',\n    'underscore-rails': '1.4.4',\n    'sanitize': null,\n    'rack-attack': null,\n    'ace-rails-ap': null,\n    'sass-rails': null,\n    'coffee-rails': null,\n    'uglifier': null,\n    'therubyracer': null,\n    'turbolinks': null,\n    'jquery-turbolinks': null,\n    'select2-rails': null,\n    'jquery-atwho-rails': '0.3.3',\n    'jquery-rails': '2.1.3',\n    'jquery-ui-rails': '2.0.2',\n    'modernizr': '2.6.2',\n    'raphael-rails': '2.1.2',\n    'bootstrap-sass': '3.0.0',\n    'font-awesome-rails': '3.2.0',\n    'gitlab-emoji': '0.0.1',\n    'gon': '5.0.0'\n  });\n\n  r.resolve(args.dependencies, args.constraints);\n});\n\nrunBenchmarks && Tinytest.add(\"constraint solver - benchmark on gems - rails, gitlabhq, additions to the existing smaller solution\", function (test) {\n  var r = new ConstraintSolver.PackagesResolver(railsCatalog);\n\n  var args = splitArgs({\n    'rails': '4.0.0',\n    'protected-attributes': null,\n    'rails-observers': null,\n    'actionpack-page-caching': null,\n    'actionpack-action-caching': null,\n    'default-value-for': '3.0.0',\n    'mysql2': null,\n    'devise': '3.0.4',\n    'devise-async': '0.8.0',\n    'omniauth': '1.1.3',\n    'omniauth-google-oauth2': null,\n    'omniauth-twitter': null,\n    'omniauth-github': null,\n    'gitlab-git': '5.7.1',\n    'gitlab-grack': '2.0.0',\n    'gitlab-omniauth-ldap': '1.0.4',\n    'gitlab-gollum-lib': '1.1.0',\n    'gitlab-linguist': '3.0.0',\n    'grape': '0.6.1',\n    'rack-cors': null,\n    'email-validator': '1.4.0',\n    'stamp': null,\n    'enumerize': null,\n    'kaminari': '0.15.1',\n    'haml-rails': null,\n    'carrierwave': null,\n    'fog': '1.3.1',\n    'six': null,\n    'seed-fu': null,\n    'redcarpet': '2.2.2',\n    'github-markup': null,\n    'asciidoctor': null,\n    'unicorn': '4.6.3',\n    'unicorn-worker-killer': null,\n    'state-machine': null,\n    'acts-as-taggable-on': null,\n    'slim': null,\n    'sinatra': null,\n    'sidekiq': null,\n    'httparty': null,\n    'colored': null,\n    'settingslogic': null,\n    'foreman': null,\n    'version-sorter': null,\n    'redis-rails': null,\n    'tinder': '1.9.2',\n    'hipchat': '0.14.0',\n    'gemnasium-gitlab-service': '0.2.1',\n    'slack-notifier': '0.2.0',\n    'd3-rails': '3.1.4',\n    'underscore-rails': '1.4.4',\n    'sanitize': null,\n    'rack-attack': null,\n    'ace-rails-ap': null,\n    'sass-rails': null,\n    'coffee-rails': null,\n    'uglifier': null,\n    'therubyracer': null,\n    'turbolinks': null,\n    'jquery-turbolinks': null,\n    'select2-rails': null,\n    'jquery-atwho-rails': '0.3.3',\n    'jquery-rails': '2.1.3',\n    'jquery-ui-rails': '2.0.2',\n    'modernizr': '2.6.2',\n    'raphael-rails': '2.1.2',\n    'bootstrap-sass': '3.0.0',\n    'font-awesome-rails': '3.2.0',\n    'gitlab-emoji': '0.0.1',\n    'gon': '5.0.0'\n  });\n\n  var previousSolution = {\n    \"actionmailer\": \"4.0.0\",\n    \"actionpack\": \"4.0.0\",\n    \"activemodel\": \"4.0.0\",\n    \"activerecord\": \"4.0.0\",\n    \"activerecord-deprecated-finders\": \"1.0.3\",\n    \"activesupport\": \"4.0.0\",\n    \"arel\": \"4.0.2\",\n    \"asciidoctor\": \"0.1.4\",\n    \"bcrypt\": \"3.1.7\",\n    \"bcrypt-ruby\": \"3.1.5\",\n    \"builder\": \"3.1.4\",\n    \"carrierwave\": \"0.10.0\",\n    \"coffee-rails\": \"4.0.1\",\n    \"coffee-script\": \"2.2.0\",\n    \"coffee-script-source\": \"1.7.0\",\n    \"d3-rails\": \"3.1.10\",\n    \"default-value-for\": \"3.0.0\",\n    \"devise\": \"3.0.4\",\n    \"devise-async\": \"0.8.0\",\n    \"erubis\": \"2.7.0\",\n    \"execjs\": \"2.0.2\",\n    \"faraday\": \"0.9.0\",\n    \"github-markup\": \"1.1.0\",\n    \"haml\": \"4.0.5\",\n    \"haml-rails\": \"0.5.3\",\n    \"hashie\": \"2.0.3\",\n    \"hike\": \"1.2.3\",\n    \"httpauth\": \"0.2.1\",\n    \"i18n\": \"0.6.9\",\n    \"jquery-turbolinks\": \"2.0.2\",\n    \"json\": \"1.8.1\",\n    \"jwt\": \"0.1.10\",\n    \"kaminari\": \"0.15.1\",\n    \"mail\": \"2.5.4\",\n    \"mime-types\": \"1.25.1\",\n    \"minitest\": \"4.7.5\",\n    \"multi-json\": \"1.9.0\",\n    \"multipart-post\": \"2.0.0\",\n    \"oauth\": \"0.4.7\",\n    \"oauth2\": \"0.8.1\",\n    \"omniauth\": \"1.1.4\",\n    \"omniauth-github\": \"1.0.3\",\n    \"omniauth-google-oauth2\": \"0.2.2\",\n    \"omniauth-oauth\": \"1.0.1\",\n    \"omniauth-oauth2\": \"1.1.1\",\n    \"omniauth-twitter\": \"1.0.1\",\n    \"orm-adapter\": \"0.5.0\",\n    \"polyglot\": \"0.3.4\",\n    \"posix-spawn\": \"0.3.8\",\n    \"protected-attributes\": \"1.0.7\",\n    \"rack\": \"1.5.2\",\n    \"rack-test\": \"0.6.2\",\n    \"rails\": \"4.0.4\",\n    \"rails-observers\": \"0.1.2\",\n    \"railties\": \"4.0.0\",\n    \"rake\": \"10.1.1\",\n    \"redcarpet\": \"2.2.2\",\n    \"ref\": \"1.0.5\",\n    \"sass\": \"3.2.17\",\n    \"sass-rails\": \"4.0.2\",\n    \"seed-fu\": \"2.3.0\",\n    \"six\": \"0.2.0\",\n    \"sprockets\": \"2.11.0\",\n    \"sprockets-rails\": \"2.0.1\",\n    \"therubyracer\": \"0.12.1\",\n    \"thor\": \"0.19.1\",\n    \"thread-safe\": \"0.3.1\",\n    \"tilt\": \"1.4.1\",\n    \"treetop\": \"1.4.15\",\n    \"turbolinks\": \"2.2.1\",\n    \"tzinfo\": \"0.3.39\",\n    \"uglifier\": \"2.5.0\",\n    \"warden\": \"1.2.3\"\n  };\n\n  var solution = r.resolve(args.dependencies, args.constraints, { previousSolution: previousSolution }).answer;\n\n  // check that root deps are the same\n  _.each(args.dependencies, function (dep) {\n    if (previousSolution[dep])\n      test.equal(solution[dep], previousSolution[dep], dep);\n  });\n});\n\n\n// Given a set of gems definitions returns a Catalog-like object\nfunction getCatalogStub (gems) {\n  return {\n    getSortedVersionRecords: function (name) {\n      var versions = _.chain(gems)\n        .filter(function (pv) { return pv.name === name; })\n        .pluck('number')\n        .filter(function (v) {\n          return PackageVersion.getValidServerVersion(v);\n        })\n        .sort(PackageVersion.compare)\n        .uniq(true)\n        .value();\n      return _.map(versions, function (version) {\n        var gem = _.find(gems, function (pv) {\n          return pv.name === name && pv.number === version;\n        });\n\n        var packageVersion = {\n          packageName: gem.name,\n          version: gem.number,\n          dependencies: {}\n        };\n\n        _.each(gem.dependencies, function (dep) {\n          var name = dep[0];\n          var constraint = dep[1];\n\n          packageVersion.dependencies[name] = {\n            constraint: constraint,\n            references: [{\n              \"arch\": \"web\"\n            }, {\n              \"arch\": \"os\" }]\n          };\n        });\n\n        return packageVersion;\n      });\n    }\n  };\n}\n"
  },
  {
    "path": "packages/constraint-solver/catalog-cache-tests.js",
    "content": "var CS = ConstraintSolver;\n\nTinytest.add(\"constraint solver - CatalogCache\", function (test) {\n  var cache = new CS.CatalogCache();\n\n  // add package versions out of order; they'll be sorted\n  // when retrieved with getPackageVersions or eachPackage\n  // (but not eachPackageVersion).\n  cache.addPackageVersion(\n    'foo', '1.0.1', [new CS.Dependency('bar@=2.0.0 || =2.0.1'),\n                     new CS.Dependency('bzzz'),\n                     new CS.Dependency('weakly1@1.0.0', {isWeak: true}),\n                     new CS.Dependency('weakly2', {isWeak: true})]);\n  cache.addPackageVersion(\n    'foo', '1.0.0', [new CS.Dependency('bar@=2.0.0')]);\n\n  test.throws(function () {\n    // can't add deps twice\n    cache.addPackageVersion(\n      'foo', '1.0.0', [new CS.Dependency('blah@1.0.0')]);\n  });\n\n  // for these toJSONable tests, the order the strings in the dependency\n  // arrray is not significant and may change.\n  test.equal(cache.toJSONable(), {\n    data: {\n      'foo 1.0.0': ['bar@=2.0.0'],\n      'foo 1.0.1': ['bar@=2.0.0 || =2.0.1', 'bzzz',\n                    '?weakly1@1.0.0', '?weakly2']\n    } });\n  test.equal(CS.CatalogCache.fromJSONable(cache.toJSONable()).toJSONable(), {\n    data: {\n      'foo 1.0.0': ['bar@=2.0.0'],\n      'foo 1.0.1': ['bar@=2.0.0 || =2.0.1', 'bzzz',\n                    '?weakly1@1.0.0', '?weakly2']\n    } });\n\n  var pvs = {};\n  cache.eachPackageVersion(function (pv, deps) {\n    check(pv, CS.PackageAndVersion);\n    check(_.values(deps), [CS.Dependency]);\n    pvs[pv.package+' '+pv.version] = _.keys(deps).sort();\n  });\n  test.equal(pvs, {'foo 1.0.0': ['bar'],\n                   'foo 1.0.1': ['bar', 'bzzz', 'weakly1', 'weakly2']});\n\n  var oneVersion = [];\n  cache.eachPackageVersion(function (pv) {\n    oneVersion.push(pv.toString());\n    return true; // stop\n  });\n  test.equal(oneVersion.length, 1); // don't know which it is\n\n  var foos = [];\n  _.each(cache.getPackageVersions('foo'), function (v) {\n    var depMap = cache.getDependencyMap('foo', v);\n    foos.push([v, _.map(depMap, String).sort()]);\n  });\n  // versions should come out sorted, just like this.\n  test.equal(foos,\n             [['1.0.0', ['bar@=2.0.0']],\n              ['1.0.1', ['?weakly1@1.0.0', '?weakly2',\n                         'bar@=2.0.0 || =2.0.1', 'bzzz']]]);\n\n  test.throws(function () {\n    // package version doesn't exist\n    cache.getDependencyMap('foo', '7.0.0');\n  });\n\n  var versions = [];\n  cache.eachPackage(function (p, vv) {\n    versions.push.apply(versions, vv);\n  });\n  test.equal(versions, [\"1.0.0\", \"1.0.1\"]); // sorted\n\n  cache.addPackageVersion('bar', '1.0.0', []);\n  var onePackage = [];\n  cache.eachPackage(function (p) {\n    test.isTrue(p === 'foo' || p === 'bar');\n    onePackage.push(p);\n    return true;\n  });\n  test.equal(onePackage.length, 1); // don't know which package it is\n});\n"
  },
  {
    "path": "packages/constraint-solver/catalog-cache.js",
    "content": "var CS = ConstraintSolver;\nvar PV = PackageVersion;\n\nvar pvkey = function (pkg, version) {\n  return pkg + \" \" + version;\n};\n\n// Stores the Dependencies for each known PackageAndVersion.\nCS.CatalogCache = function () {\n  // String(PackageAndVersion) -> String -> Dependency.\n  // For example, \"foo 1.0.0\" -> \"bar\" -> Dependency.fromString(\"?bar@1.0.2\").\n  this._dependencies = {};\n  // A map derived from the keys of _dependencies, for ease of iteration.\n  // \"foo\" -> [\"1.0.0\", ...]\n  // Versions in the array are unique but not sorted, unless the `.sorted`\n  // property is set on the array.  The array is never empty.\n  this._versions = {};\n};\n\nCS.CatalogCache.prototype.hasPackageVersion = function (pkg, version) {\n  return _.has(this._dependencies, pvkey(pkg, version));\n};\n\nCS.CatalogCache.prototype.addPackageVersion = function (p, v, deps) {\n  check(p, String);\n  check(v, String);\n  // `deps` must not have any duplicate values of `.packageConstraint.package`\n  check(deps, [CS.Dependency]);\n\n  var key = pvkey(p, v);\n  if (_.has(this._dependencies, key)) {\n    throw new Error(\"Already have an entry for \" + key);\n  }\n\n  if (! _.has(this._versions, p)) {\n    this._versions[p] = [];\n  }\n  this._versions[p].push(v);\n  this._versions[p].sorted = false;\n\n  var depsByPackage = {};\n  this._dependencies[key] = depsByPackage;\n  _.each(deps, function (d) {\n    var p2 = d.packageConstraint.package;\n    if (_.has(depsByPackage, p2)) {\n      throw new Error(\"Can't have two dependencies on \" + p2 +\n                      \" in \" + key);\n    }\n    depsByPackage[p2] = d;\n  });\n};\n\n// Returns the dependencies of a (package, version), stored in a map.\n// The values are Dependency objects; the key for `d` is\n// `d.packageConstraint.package`.  (Don't mutate the map.)\nCS.CatalogCache.prototype.getDependencyMap = function (p, v) {\n  var key = pvkey(p, v);\n  if (! _.has(this._dependencies, key)) {\n    throw new Error(\"No entry for \" + key);\n  }\n  return this._dependencies[key];\n};\n\n// Returns an array of version strings, sorted, possibly empty.\n// (Don't mutate the result.)\nCS.CatalogCache.prototype.getPackageVersions = function (pkg) {\n  var result = (_.has(this._versions, pkg) ?\n                this._versions[pkg] : []);\n  if ((!result.length) || result.sorted) {\n    return result;\n  } else {\n    // sort in place, and record so that we don't sort redundantly\n    // (we'll sort again if more versions are pushed onto the array)\n    var pvParse = _.memoize(PV.parse);\n    result.sort(function (a, b) {\n      return PV.compare(pvParse(a), pvParse(b));\n    });\n    result.sorted = true;\n    return result;\n  }\n};\n\nCS.CatalogCache.prototype.hasPackage = function (pkg) {\n  return _.has(this._versions, pkg);\n};\n\nCS.CatalogCache.prototype.toJSONable = function () {\n  var self = this;\n  var data = {};\n  _.each(self._dependencies, function (depsByPackage, key) {\n    // depsByPackage is a map of String -> Dependency.\n    // Map over the values to get an array of String.\n    data[key] = _.map(depsByPackage, function (dep) {\n      return dep.toString();\n    });\n  });\n  return { data: data };\n};\n\nCS.CatalogCache.fromJSONable = function (obj) {\n  check(obj, { data: Object });\n\n  var cache = new CS.CatalogCache();\n  _.each(obj.data, function (depsArray, pv) {\n    check(depsArray, [String]);\n    pv = CS.PackageAndVersion.fromString(pv);\n    cache.addPackageVersion(\n      pv.package, pv.version,\n      _.map(depsArray, function (str) {\n        return CS.Dependency.fromString(str);\n      }));\n  });\n  return cache;\n};\n\n// Calls `iter` on each PackageAndVersion, with the second argument being\n// a map from package name to Dependency.  If `iter` returns true,\n// iteration is stopped.  There's no particular order to the iteration.\nCS.CatalogCache.prototype.eachPackageVersion = function (iter) {\n  var self = this;\n  _.find(self._dependencies, function (value, key) {\n    var stop = iter(CS.PackageAndVersion.fromString(key), value);\n    return stop;\n  });\n};\n\n// Calls `iter` on each package name, with the second argument being\n// a list of versions present for that package (unique and sorted).\n// If `iter` returns true, iteration is stopped.\nConstraintSolver.CatalogCache.prototype.eachPackage = function (iter) {\n  var self = this;\n  _.find(_.keys(self._versions), function (key) {\n    var stop = iter(key, self.getPackageVersions(key));\n    return stop;\n  });\n};\n"
  },
  {
    "path": "packages/constraint-solver/catalog-loader.js",
    "content": "var PV = PackageVersion;\nvar CS = ConstraintSolver;\n\n// A CatalogLoader does the work of populating a CatalogCache from the\n// Catalog.  When you run a unit test with canned Catalog data, there is\n// a CatalogCache but no CatalogLoader.\n//\n// CatalogLoader acts as a minor cache layer between CatalogCache and\n// the Catalog, because going to the Catalog generally means going to\n// SQLite, i.e. disk, while caching a version in the CatalogCache means\n// that it is available to the solver.  CatalogLoader's private cache\n// allows it to over-read from the Catalog so that it can mediate\n// between the granularity provided by the Catalog and the versions\n// requested by the solver.\n//\n// We rely on the following `catalog` methods:\n//\n// * getSortedVersionRecords(packageName) ->\n//     [{packageName, version, dependencies}]\n//\n//   Where `dependencies` is a map from packageName to\n//   an object of the form `{ constraint: String|null,\n//   references: [{arch: String, optional \"weak\": true}] }`.\n//\n// * getVersion(packageName, version) ->\n//   {packageName, version, dependencies}\n\nCS.CatalogLoader = function (fromCatalog, toCatalogCache) {\n  var self = this;\n\n  self.catalog = fromCatalog;\n  self.catalogCache = toCatalogCache;\n\n  self._sortedVersionRecordsCache = {};\n};\n\nvar convertDeps = function (catalogDeps) {\n  return _.map(catalogDeps, function (dep, pkg) {\n    // The dependency is strong if any of its \"references\"\n    // (for different architectures) are strong.\n    var isStrong = _.any(dep.references, function (ref) {\n      return !ref.weak;\n    });\n\n    var constraint = (dep.constraint || null);\n\n    return new CS.Dependency(new PV.PackageConstraint(pkg, constraint),\n                             isStrong ? null : {isWeak: true});\n  });\n};\n\n// Since we don't fetch different versions of a package independently\n// at the moment, this helper is where we get our data.\nCS.CatalogLoader.prototype._getSortedVersionRecords = function (pkg) {\n  if (! _.has(this._sortedVersionRecordsCache, pkg)) {\n    this._sortedVersionRecordsCache[pkg] =\n      this.catalog.getSortedVersionRecords(pkg);\n  }\n\n  return this._sortedVersionRecordsCache[pkg];\n};\n\nCS.CatalogLoader.prototype.loadSingleVersion = function (pkg, version) {\n  var self = this;\n  var cache = self.catalogCache;\n  if (! cache.hasPackageVersion(pkg, version)) {\n    var rec;\n    if (_.has(self._sortedVersionRecordsCache, pkg)) {\n      rec = _.find(self._sortedVersionRecordsCache[pkg],\n                   function (r) {\n                     return r.version === version;\n                   });\n    } else {\n      rec = self.catalog.getVersion(pkg, version);\n    }\n    if (rec) {\n      var deps = convertDeps(rec.dependencies);\n      cache.addPackageVersion(pkg, version, deps);\n    }\n  }\n};\n\nCS.CatalogLoader.prototype.loadAllVersions = function (pkg) {\n  var self = this;\n  var cache = self.catalogCache;\n  var versionRecs = self._getSortedVersionRecords(pkg);\n  _.each(versionRecs, function (rec) {\n    var version = rec.version;\n    if (! cache.hasPackageVersion(pkg, version)) {\n      var deps = convertDeps(rec.dependencies);\n      cache.addPackageVersion(pkg, version, deps);\n    }\n  });\n};\n\n// Takes an array of package names.  Loads all versions of them and their\n// (strong) dependencies.\nCS.CatalogLoader.prototype.loadAllVersionsRecursive = function (packageList) {\n  var self = this;\n\n  // Within a call to loadAllVersionsRecursive, we only visit each package\n  // at most once.  If we visit a package we've already loaded, it will\n  // lead to a quick scan through the versions in our cache to make sure\n  // they have been loaded into the CatalogCache.\n  var loadQueue = [];\n  var packagesEverEnqueued = {};\n\n  var enqueue = function (pkg) {\n    if (! _.has(packagesEverEnqueued, pkg)) {\n      packagesEverEnqueued[pkg] = true;\n      loadQueue.push(pkg);\n    }\n  };\n\n  _.each(packageList, enqueue);\n\n  while (loadQueue.length) {\n    var pkg = loadQueue.pop();\n    self.loadAllVersions(pkg);\n    _.each(self.catalogCache.getPackageVersions(pkg), function (v) {\n      var depMap = self.catalogCache.getDependencyMap(pkg, v);\n      _.each(depMap, function (dep, package2) {\n        enqueue(package2);\n      });\n    });\n  }\n};\n"
  },
  {
    "path": "packages/constraint-solver/constraint-solver-input.js",
    "content": "var PV = PackageVersion;\nvar CS = ConstraintSolver;\n\n// `check` can be really slow, so this line is a valve that makes it\n// easy to turn off when debugging performance problems.\nvar _check = check;\n\n// The \"Input\" object completely specifies the input to the resolver,\n// and it holds the data loaded from the Catalog as well.  It can be\n// serialized to JSON and read back in for testing purposes.\nCS.Input = function (dependencies, constraints, catalogCache, options) {\n  var self = this;\n  options = options || {};\n\n  // PackageConstraints passed in from the tool to us (where we are a\n  // uniloaded package) will have constructors that we don't recognize\n  // because they come from a different copy of package-version-parser!\n  // Convert them to our PackageConstraint class if necessary.  (This is\n  // just top-level constraints from .meteor/packages or running from\n  // checkout, so it's not a lot of data.)\n  constraints = _.map(constraints, function (c) {\n    if (c instanceof PV.PackageConstraint) {\n      return c;\n    } else {\n      return PV.parsePackageConstraint(c.package, c.constraintString);\n    }\n  });\n\n  // Note that `dependencies` and `constraints` are required (you can't\n  // omit them or pass null), while the other properties have defaults.\n  self.dependencies = dependencies;\n  self.constraints = constraints;\n  // If you add a property, make sure you add it to:\n  // - The `check` statements below\n  // - toJSONable (this file)\n  // - fromJSONable (this file)\n  // - the \"input serialization\" test in constraint-solver-tests.js\n  // If it's an option passed in from the tool, you'll also have to\n  // add it to CS.PackagesResolver#resolve.\n  self.upgrade = options.upgrade || [];\n  self.anticipatedPrereleases = options.anticipatedPrereleases || {};\n  self.previousSolution = options.previousSolution || null;\n  self.allowIncompatibleUpdate = options.allowIncompatibleUpdate || false;\n  self.upgradeIndirectDepPatchVersions =\n    options.upgradeIndirectDepPatchVersions || false;\n\n  _check(self.dependencies, [String]);\n  _check(self.constraints, [PV.PackageConstraint]);\n  _check(self.upgrade, [String]);\n  _check(self.anticipatedPrereleases,\n        Match.ObjectWithValues(Match.ObjectWithValues(Boolean)));\n  _check(self.previousSolution, Match.OneOf(Object, null));\n  _check(self.allowIncompatibleUpdate, Boolean);\n  _check(self.upgradeIndirectDepPatchVersions, Boolean);\n\n  self.catalogCache = catalogCache;\n  _check(self.catalogCache, CS.CatalogCache);\n  // The catalog presumably has valid package names in it, but make sure\n  // there aren't any characters in there somehow that will trip us up\n  // with creating valid variable strings.\n  self.catalogCache.eachPackage(function (packageName) {\n    validatePackageName(packageName);\n  });\n  self.catalogCache.eachPackageVersion(function (packageName, depsMap) {\n    _.each(depsMap, function (deps, depPackageName) {\n      validatePackageName(depPackageName);\n    });\n  });\n\n  _.each(self.dependencies, validatePackageName);\n  _.each(self.upgrade, validatePackageName);\n  _.each(self.constraints, function (c) {\n    validatePackageName(c.package);\n  });\n  if (self.previousSolution) {\n    _.each(_.keys(self.previousSolution),\n           validatePackageName);\n  }\n\n  self._dependencySet = {}; // package name -> true\n  _.each(self.dependencies, function (d) {\n    self._dependencySet[d] = true;\n  });\n  self._upgradeSet = {};\n  _.each(self.upgrade, function (u) {\n    self._upgradeSet[u] = true;\n  });\n};\n\nvalidatePackageName = function (name) {\n  PV.validatePackageName(name);\n  // We have some hard requirements of our own so that packages can be\n  // used as solver variables.  PV.validatePackageName should already\n  // enforce these requirements and more, so these checks are just a\n  // backstop in case it changes under us somehow.\n  if ((name.charAt(0) === '$') || (name.charAt(0) === '-')) {\n    throw new Error(\"First character of package name cannot be: \" +\n                    name.charAt(0));\n  }\n  if (/ /.test(name)) {\n    throw new Error(\"No space allowed in package name\");\n  }\n};\n\nCS.Input.prototype.isKnownPackage = function (p) {\n  return this.catalogCache.hasPackage(p);\n};\n\nCS.Input.prototype.isRootDependency = function (p) {\n  return _.has(this._dependencySet, p);\n};\n\nCS.Input.prototype.isUpgrading = function (p) {\n  return _.has(this._upgradeSet, p);\n};\n\nCS.Input.prototype.isInPreviousSolution = function (p) {\n  return !! (this.previousSolution && _.has(this.previousSolution, p));\n};\n\nfunction getMentionedPackages(input) {\n  var packages = {}; // package -> true\n\n  _.each(input.dependencies, function (pkg) {\n    packages[pkg] = true;\n  });\n  _.each(input.constraints, function (constraint) {\n    packages[constraint.package] = true;\n  });\n  if (input.previousSolution) {\n    _.each(input.previousSolution, function (version, pkg) {\n      packages[pkg] = true;\n    });\n  }\n\n  return _.keys(packages);\n}\n\nCS.Input.prototype.loadFromCatalog = function (catalogLoader) {\n  // Load packages into the cache (if they aren't loaded already).\n  catalogLoader.loadAllVersionsRecursive(getMentionedPackages(this));\n};\n\nCS.Input.prototype.loadOnlyPreviousSolution = function (catalogLoader) {\n  var self = this;\n\n  // load just the exact versions from the previousSolution\n  if (self.previousSolution) {\n    _.each(self.previousSolution, function (version, pkg) {\n      catalogLoader.loadSingleVersion(pkg, version);\n    });\n  }\n};\n\nCS.Input.prototype.isEqual = function (otherInput) {\n  var a = this;\n  var b = otherInput;\n\n  // It would be more efficient to compare the fields directly,\n  // but converting to JSON is much easier to implement.\n  // This equality test is also overly sensitive to order,\n  // missing opportunities to declare two inputs equal when only\n  // the order has changed.\n\n  // Omit `catalogCache` -- it's not actually part of the serialized\n  // input object (it's only in `toJSONable()` for tests).\n  //\n  // Moreover, catalogCache is populated as-needed so their values for\n  // `a` and `b` will very likely be different even if they represent\n  // the same input. So by omitting `catalogCache` we no longer need\n  // to reload the entire relevant part of the catalog from SQLite on\n  // every rebuild!\n  return _.isEqual(\n    _.omit(a.toJSONable(), \"catalogCache\"),\n    _.omit(b.toJSONable(), \"catalogCache\")\n  );\n};\n\nCS.Input.prototype.toJSONable = function () {\n  var self = this;\n  var obj = {\n    dependencies: self.dependencies,\n    constraints: _.map(self.constraints, function (c) {\n      return c.toString();\n    }),\n    catalogCache: self.catalogCache.toJSONable()\n  };\n\n  // For readability of the resulting JSON, only include optional\n  // properties that aren't the default.\n  if (self.upgrade.length) {\n    obj.upgrade = self.upgrade;\n  }\n  if (! _.isEmpty(self.anticipatedPrereleases)) {\n    obj.anticipatedPrereleases = self.anticipatedPrereleases;\n  }\n  if (self.previousSolution !== null) {\n    obj.previousSolution = self.previousSolution;\n  }\n  if (self.allowIncompatibleUpdate) {\n    obj.allowIncompatibleUpdate = true;\n  }\n  if (self.upgradeIndirectDepPatchVersions) {\n    obj.upgradeIndirectDepPatchVersions = true;\n  }\n\n  return obj;\n};\n\nCS.Input.fromJSONable = function (obj) {\n  _check(obj, {\n    dependencies: [String],\n    constraints: [String],\n    catalogCache: Object,\n    anticipatedPrereleases: Match.Optional(\n      Match.ObjectWithValues(Match.ObjectWithValues(Boolean))),\n    previousSolution: Match.Optional(Match.OneOf(Object, null)),\n    upgrade: Match.Optional([String]),\n    allowIncompatibleUpdate: Match.Optional(Boolean),\n    upgradeIndirectDepPatchVersions: Match.Optional(Boolean)\n  });\n\n  return new CS.Input(\n    obj.dependencies,\n    _.map(obj.constraints, function (cstr) {\n      return PV.parsePackageConstraint(cstr);\n    }),\n    CS.CatalogCache.fromJSONable(obj.catalogCache),\n    {\n      upgrade: obj.upgrade,\n      anticipatedPrereleases: obj.anticipatedPrereleases,\n      previousSolution: obj.previousSolution,\n      allowIncompatibleUpdate: obj.allowIncompatibleUpdate,\n      upgradeIndirectDepPatchVersions: obj.upgradeIndirectDepPatchVersions\n    });\n};\n"
  },
  {
    "path": "packages/constraint-solver/constraint-solver-tests.js",
    "content": "var PV = PackageVersion;\nvar CS = ConstraintSolver;\n\nvar makeResolver = function (data) {\n  var Versions = new LocalCollection;\n\n  _.each(data, function (versionDescription) {\n    var packageName = versionDescription.shift();\n    var version = versionDescription.shift();\n    var deps = versionDescription.shift();\n\n    var constructedDeps = {};\n    _.each(deps, function (constraint, name) {\n      constructedDeps[name] = {\n        constraint: constraint,\n        references: [\n          { arch: \"os\" },\n          { arch: \"web.browser\"},\n          { arch: \"web.cordova\"}\n        ]\n      };\n    });\n    Versions.insert({ packageName: packageName, version: version,\n                      dependencies: constructedDeps });\n  });\n\n  var catalogStub = {\n    getSortedVersionRecords: function (name) {\n      var records = Versions.find({packageName: name}).fetch();\n      records.sort(function (a, b) {\n        return PV.compare(a.version, b.version);\n      });\n      return records;\n    }\n  };\n  return new CS.PackagesResolver(catalogStub);\n};\n\nvar defaultResolver = makeResolver([\n  [\"sparky-forms\", \"1.1.2\", {\"forms\": \"=1.0.1\", \"sparkle\": \"=2.1.1\"}],\n  [\"sparky-forms\", \"1.0.0\", {\"awesome-dropdown\": \"=1.4.0\"}],\n  [\"forms\", \"1.0.1\", {\"sparkle\": \"2.1.0\", \"jquery-widgets\": \"1.0.0\"}],\n  [\"sparkle\", \"2.1.0\", {\"jquery\": \"1.8.2\"}],\n  [\"sparkle\", \"2.1.1\", {\"jquery\": \"1.8.2\"}],\n  [\"sparkle\", \"1.0.0\"],\n  [\"awesome-dropdown\", \"1.4.0\", {\"dropdown\": \"=1.2.2\"}],\n  [\"awesome-dropdown\", \"1.5.0\", {\"dropdown\": \"=1.2.2\"}],\n  [\"dropdown\", \"1.2.2\", {\"jquery-widgets\": \"1.0.0\"}],\n  [\"jquery-widgets\", \"1.0.0\", {\"jquery\": \"1.8.0\", \"sparkle\": \"2.1.1\"}],\n  [\"jquery-widgets\", \"1.0.2\", {\"jquery\": \"1.8.0\", \"sparkle\": \"2.1.1\"}],\n  [\"jquery\", \"1.8.0\"],\n  [\"jquery\", \"1.8.2\"]\n]);\n\n// Take a map of `{ dependency: constraint }`, where `dependency`\n// is a package name string and `constraint` is a constraint string,\n// and return an array of dependencies (package name strings)\n// and an array of constraint objects.\n//\n// If a constraint is prefixed with 'w', the dependency is a weak\n// dependency, so it will generate a constraint but not a dependency\n// in the returned arrays.\nsplitArgs = function (deps) {\n  var dependencies = [], constraints = [];\n\n  _.each(deps, function (constr, dep) {\n    if (constr && constr.charAt(0) === 'w') {\n      constr = constr.slice(1);\n    } else {\n      dependencies.push(dep);\n    }\n    if (constr) {\n      constraints.push(PV.parsePackageConstraint(dep + \"@\" + constr));\n    }\n  });\n  return {dependencies: dependencies, constraints: constraints};\n};\n\nvar testWithResolver = function (test, resolver, f) {\n  var answerToString = function (answer) {\n    var pvs = _.map(answer, function (v, p) { return p + ' ' + v; });\n    return pvs.sort().join('\\n');\n  };\n  var t = function (deps, expected, options) {\n    var dependencies = splitArgs(deps).dependencies;\n    var constraints = splitArgs(deps).constraints;\n\n    var resolvedDeps = resolver.resolve(dependencies, constraints, options);\n    test.equal(answerToString(resolvedDeps.answer),\n               answerToString(expected));\n  };\n\n  var FAIL = function (deps, regexp) {\n    test.throws(function () {\n      var dependencies = splitArgs(deps).dependencies;\n      var constraints = splitArgs(deps).constraints;\n\n      var resolvedDeps = resolver.resolve(dependencies, constraints);\n    }, regexp);\n  };\n  f(t, FAIL);\n};\n\nTinytest.add(\"constraint solver - simple exact + regular deps\", function (test) {\n  testWithResolver(test, defaultResolver, function (t) {\n    t({ \"sparky-forms\": \"=1.1.2\" }, {\n      \"sparky-forms\": \"1.1.2\",\n      \"forms\": \"1.0.1\",\n      \"sparkle\": \"2.1.1\",\n      \"jquery-widgets\": \"1.0.2\",\n      \"jquery\": \"1.8.2\"\n    });\n\n    t({ \"sparky-forms\": \"=1.1.2\", \"awesome-dropdown\": \"=1.5.0\" }, {\n      \"sparky-forms\": \"1.1.2\",\n      \"forms\": \"1.0.1\",\n      \"sparkle\": \"2.1.1\",\n      \"jquery-widgets\": \"1.0.2\",\n      \"jquery\": \"1.8.2\",\n      \"awesome-dropdown\": \"1.5.0\",\n      \"dropdown\": \"1.2.2\"\n    });\n  });\n});\n\n\nTinytest.add(\"constraint solver - non-exact direct dependency\", function (test) {\n  testWithResolver(test, defaultResolver, function (t) {\n    // sparky-forms 1.0.0 won't be chosen because it depends on a very old\n    // jquery, which is not compatible with the jquery that\n    // awesome-dropdown uses.\n    t({ \"sparky-forms\": \"1.0.0\", \"awesome-dropdown\": \"=1.5.0\" }, {\n      \"sparky-forms\": \"1.1.2\",\n      \"forms\": \"1.0.1\",\n      \"sparkle\": \"2.1.1\",\n      \"jquery-widgets\": \"1.0.2\",\n      \"jquery\": \"1.8.2\",\n      \"awesome-dropdown\": \"1.5.0\",\n      \"dropdown\": \"1.2.2\"\n    });\n  });\n});\n\nTinytest.add(\"constraint solver - no results\", function (test) {\n  var resolver = makeResolver([\n    [\"bad-1\", \"1.0.0\", {indirect: \"1.0.0\"}],\n    [\"bad-2\", \"1.0.0\", {indirect: \"2.0.0\"}],\n    [\"indirect\", \"1.0.0\"],\n    [\"indirect\", \"2.0.0\"],\n    [\"mytoplevel\", \"1.0.0\", {\"bad-1\": \"1.0.0\", \"bad-2\": \"\"}]\n  ]);\n  testWithResolver(test, resolver, function (t, FAIL) {\n    FAIL({ \"mytoplevel\": \"\" }, function (error) {\n      return error.message.match(/indirect@2\\.0\\.0 is not satisfied by indirect 1\\.0\\.0/)\n        && error.message.match(/^\\* indirect@1\\.0\\.0 <- bad-1 1\\.0\\.0 <- mytoplevel 1.0.0$/m)\n        && error.message.match(/^\\* indirect@2\\.0\\.0 <- bad-2 1\\.0\\.0 <- mytoplevel 1.0.0$/m)\n      // Lines should be unique.\n        && ! error.message.match(/bad-1[^]+bad-1/)\n      // only two constraints listed\n        && ! error.message.match(/onstraints on package \"foo\":[^]+@[^]+@[^]+@/);\n    });\n  });\n\n  resolver = makeResolver([\n    [\"foo\", \"1.0.0\"],\n    [\"foo\", \"1.1.0\"],\n    [\"foo\", \"2.0.0\"],\n    [\"foo\", \"2.1.0\"],\n    [\"bar\", \"1.0.0\", {foo: \"1.0.0\"}]\n  ]);\n  testWithResolver(test, resolver, function (t, FAIL) {\n    FAIL({foo: \"2.0.0\", bar: \"1.0.0\"}, function (error) {\n      return error.message.match(/Constraints on package \"foo\":[^]+top level/) &&\n        error.message.match(/Constraints on package \"foo\":[^]+bar 1.0.0/);\n    });\n  });\n\n  testWithResolver(test, makeResolver([]), function (t, FAIL) {\n    FAIL({foo: \"1.0.0\"}, /unknown package in top-level dependencies: foo/);\n  });\n\n  resolver = makeResolver([\n    [\"foo\", \"2.0.0\"],\n    [\"bar\", \"1.0.0\", {foo: \"\"}]\n  ]);\n  testWithResolver(test, resolver, function (t, FAIL) {\n    FAIL({foo: \"w1.0.0\", bar: \"1.0.0\"},\n         /No version of foo satisfies all constraints: @1.0.0/);\n  });\n});\n\n\nTinytest.add(\"constraint solver - any-of constraint\", function (test) {\n  var resolver = makeResolver([\n    [\"one-of\", \"1.0.0\", {indirect: \"1.0.0 || 2.0.0\"}],\n    [\"important\", \"1.0.0\", {indirect: \"2.0.0\"}],\n    [\"indirect\", \"1.0.0\"],\n    [\"indirect\", \"2.0.0\"]\n  ]);\n\n  testWithResolver(test, resolver, function (t, FAIL) {\n    t({ \"one-of\": \"=1.0.0\", \"important\": \"1.0.0\" }, {\n      \"one-of\": \"1.0.0\",\n      \"important\": \"1.0.0\",\n      \"indirect\": \"2.0.0\"\n    });\n  });\n\n  resolver = makeResolver([\n    [\"one-of\", \"1.0.0\", {indirect: \"1.0.0 || 2.0.0\"}],\n    [\"one-of-equal\", \"1.0.0\", {indirect: \"1.0.0 || =2.0.1\"}],\n    [\"important\", \"1.0.0\", {indirect: \"1.0.0\"}],\n    [\"indirect\", \"1.0.0\"],\n    [\"indirect\", \"2.0.0\"],\n    [\"indirect\", \"2.0.1\"]\n  ]);\n\n  testWithResolver(test, resolver, function (t, FAIL) {\n    t({ \"one-of\": \"=1.0.0\", \"important\": \"1.0.0\" }, {\n      \"one-of\": \"1.0.0\",\n      \"important\": \"1.0.0\",\n      \"indirect\": \"1.0.0\"\n    });\n\n    t({ \"one-of-equal\": \"1.0.0\", \"indirect\": \"2.0.0\" }, {\n      \"one-of-equal\": \"1.0.0\",\n      \"indirect\": \"2.0.1\"\n    });\n\n    t({ \"one-of-equal\": \"1.0.0\", \"one-of\": \"1.0.0\" }, {\n      \"one-of-equal\": \"1.0.0\",\n      \"one-of\": \"1.0.0\",\n      \"indirect\": \"1.0.0\"\n    });\n\n    FAIL({\"one-of-equal\": \"1.0.0\",\n          \"one-of\": \"1.0.0\",\n          \"indirect\" : \"=2.0.0\"}, function (error) {\n            return error.message.match(/Constraints on package \"indirect\":[^]+top level/) &&\n              error.message.match(/Constraints on package \"indirect\":[^]+one-of-equal 1.0.0/);\n          });\n  });\n});\n\nTinytest.add(\"constraint solver - previousSolution\", function (test) {\n  testWithResolver(test, defaultResolver, function (t, FAIL) {\n    // This is what you get if you lock sparky-forms to 1.0.0.\n    t({ \"sparky-forms\": \"=1.0.0\" }, {\n      \"sparky-forms\": \"1.0.0\",\n      \"awesome-dropdown\": \"1.4.0\",\n      \"dropdown\": \"1.2.2\",\n      \"jquery-widgets\": \"1.0.2\",\n      \"jquery\": \"1.8.2\",\n      \"sparkle\": \"2.1.1\"\n    });\n\n    // If you just requires something compatible with 1.0.0, we end up choosing\n    // 1.1.2.\n    t({ \"sparky-forms\": \"1.0.0\" }, {\n      \"sparky-forms\": \"1.1.2\",\n      \"forms\": \"1.0.1\",\n      \"sparkle\": \"2.1.1\",\n      \"jquery-widgets\": \"1.0.2\",\n      \"jquery\": \"1.8.2\"\n    });\n\n    // But if you ask for something compatible with 1.0.0 and have a previous\n    // solution with 1.0.0, the previous solution works (since it is achievable).\n    t({ \"sparky-forms\": \"1.0.0\" }, {\n      \"sparky-forms\": \"1.0.0\",\n      \"awesome-dropdown\": \"1.4.0\",\n      \"dropdown\": \"1.2.2\",\n      \"jquery-widgets\": \"1.0.2\",\n      \"jquery\": \"1.8.2\",\n      \"sparkle\": \"2.1.1\"\n    }, { previousSolution: {\n      \"sparky-forms\": \"1.0.0\"\n    }});\n\n    // On the other hand, if the previous solution is incompatible with the\n    // constraints, it's not an error: we can try something that isn't the\n    // previous solution in this case!\n    t({ \"sparky-forms\": \"1.1.2\" }, {\n      \"sparky-forms\": \"1.1.2\",\n      \"forms\": \"1.0.1\",\n      \"sparkle\": \"2.1.1\",\n      \"jquery-widgets\": \"1.0.2\",\n      \"jquery\": \"1.8.2\"\n    }, { previousSolution: {\n      \"sparky-forms\": \"1.0.0\"\n    }});\n  });\n});\n\n\nTinytest.add(\"constraint solver - no constraint dependency - anything\", function (test) {\n  var versions = defaultResolver.resolve([\"sparkle\"], []).answer;\n  test.isTrue(_.isString(versions.sparkle));\n});\n\n\nTinytest.add(\"constraint solver - no constraint dependency - transitive dep still picked right\", function (test) {\n  var versions = defaultResolver.resolve(\n    [\"sparkle\", \"sparky-forms\"],\n    [PV.parsePackageConstraint(\"sparky-forms@1.1.2\")]).answer;\n  test.equal(versions.sparkle, \"2.1.1\");\n});\n\nTinytest.add(\"constraint solver - input serialization\", function (test) {\n  var json = '{\"dependencies\":[\"sparky-forms\"],\"constraints\":[\"sparky-forms@1.0.0\"],\"catalogCache\":{\"data\":{\"sparky-forms 1.0.0\":[\"awesome-dropdown@=1.4.0\"],\"sparky-forms 1.1.2\":[\"forms@=1.0.1\",\"sparkle@=2.1.1\"],\"sparkle 1.0.0\":[],\"sparkle 2.1.0\":[\"jquery@1.8.2\"],\"sparkle 2.1.1\":[\"jquery@1.8.2\"],\"jquery 1.8.0\":[],\"jquery 1.8.2\":[],\"forms 1.0.1\":[\"sparkle@2.1.0\",\"jquery-widgets@1.0.0\"],\"jquery-widgets 1.0.0\":[\"jquery@1.8.0\",\"sparkle@2.1.1\"],\"jquery-widgets 1.0.2\":[\"jquery@1.8.0\",\"sparkle@2.1.1\"],\"awesome-dropdown 1.4.0\":[\"dropdown@=1.2.2\"],\"awesome-dropdown 1.5.0\":[\"dropdown@=1.2.2\"],\"dropdown 1.2.2\":[\"jquery-widgets@1.0.0\"]}}}';\n\n  var input1 = CS.Input.fromJSONable(JSON.parse(json));\n\n  test.equal(input1.dependencies, [\"sparky-forms\"]);\n  test.isTrue(input1.constraints[0] instanceof PV.PackageConstraint);\n  test.equal(input1.constraints.toString(), \"sparky-forms@1.0.0\");\n  test.isTrue(input1.catalogCache instanceof CS.CatalogCache);\n  test.equal(input1.upgrade, []);\n  test.equal(input1.anticipatedPrereleases, {});\n  test.equal(input1.previousSolution, null);\n  test.equal(input1.allowIncompatibleUpdate, false);\n  test.equal(input1.upgradeIndirectDepPatchVersions, false);\n\n  var obj1 = input1.toJSONable();\n  test.isFalse(_.has(obj1, 'upgrade'));\n  test.isFalse(_.has(obj1, 'anticipatedPrereleases'));\n  test.isFalse(_.has(obj1, 'previousSolution'));\n  var input2 = CS.Input.fromJSONable(obj1);\n  var obj2 = input2.toJSONable();\n\n  test.equal(JSON.stringify(obj1), json);\n  test.equal(JSON.stringify(obj2), json);\n\n  ///// Now a different case:\n\n  var input2 = new CS.Input(\n    ['foo'], [PV.parsePackageConstraint('foo@1.0.0')],\n    new CS.CatalogCache(), {\n      upgrade: ['foo'],\n      anticipatedPrereleases: { foo: { '1.0.0-rc.0': true } },\n      previousSolution: { foo: '1.0.0' },\n      allowIncompatibleUpdate: true,\n      upgradeIndirectDepPatchVersions: true\n    });\n\n  var json2 = JSON.stringify(input2.toJSONable());\n  var input2prime = CS.Input.fromJSONable(JSON.parse(json2));\n  test.equal(input2prime.toJSONable(), {\n    dependencies: [\"foo\"],\n    constraints: [\"foo@1.0.0\"],\n    catalogCache: { data: {} },\n    upgrade: ['foo'],\n    anticipatedPrereleases: { foo: { '1.0.0-rc.0': true } },\n    previousSolution: { foo: '1.0.0' },\n    allowIncompatibleUpdate: true,\n    upgradeIndirectDepPatchVersions: true\n  });\n});\n\nTinytest.add(\"constraint solver - non-existent indirect package\", function (test) {\n  var resolver = makeResolver([\n    [\"foo\", \"1.0.0\", {bar: \"1.0.0\"}]\n  ]);\n  testWithResolver(test, resolver, function (t, FAIL) {\n    FAIL({ \"foo\": \"1.0.0\" }, function (error) {\n      return error.message.match(/unknown package: bar/);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/constraint-solver/constraint-solver.js",
    "content": "var PV = PackageVersion;\nvar CS = ConstraintSolver;\n\n// This is the entry point for the constraint-solver package.  The tool\n// creates a ConstraintSolver.PackagesResolver and calls .resolve on it.\n\nCS.PackagesResolver = function (catalog, options) {\n  var self = this;\n\n  self.catalog = catalog;\n  self.catalogCache = new CS.CatalogCache();\n  self.catalogLoader = new CS.CatalogLoader(self.catalog, self.catalogCache);\n\n  self._options = {\n    nudge: options && options.nudge,\n    Profile: options && options.Profile,\n    // For resultCache, pass in an empty object `{}`, and PackagesResolver\n    // will put data on it.  Pass in the same object again to allow reusing\n    // the result from the previous run.\n    resultCache: options && options.resultCache\n  };\n};\n\n// dependencies - an array of string names of packages (not slices)\n// constraints - an array of PV.PackageConstraints\n// options:\n//  - upgrade - list of dependencies for which upgrade is prioritized higher\n//    than keeping the old version\n//  - previousSolution - mapping from package name to a version that was used in\n//    the previous constraint solver run\n//  - anticipatedPrereleases: mapping from package name to version to true;\n//    included versions are the only pre-releases that are allowed to match\n//    constraints that don't specifically name them during the \"try not to\n//    use unanticipated pre-releases\" pass\n//  - allowIncompatibleUpdate: allows choosing versions of\n//    root dependencies that are incompatible with the previous solution,\n//    if necessary to satisfy all constraints\n//  - upgradeIndirectDepPatchVersions: also upgrade indirect dependencies\n//    to newer patch versions, proactively\n//  - missingPreviousVersionIsError - throw an error if a package version in\n//    previousSolution is not found in the catalog\n//  - supportedIsobuildFeaturePackages - map from package name to list of\n//    version strings of isobuild feature packages that are available in the\n//    catalog\nCS.PackagesResolver.prototype.resolve = function (dependencies, constraints,\n                                                  options) {\n  var self = this;\n  options = options || {};\n  var Profile = (self._options.Profile || CS.DummyProfile);\n\n  var input;\n  Profile.time(\"new CS.Input\", function () {\n    input = new CS.Input(dependencies, constraints, self.catalogCache,\n                         _.pick(options,\n                                'upgrade',\n                                'anticipatedPrereleases',\n                                'previousSolution',\n                                'allowIncompatibleUpdate',\n                                'upgradeIndirectDepPatchVersions'));\n  });\n\n  var resultCache = self._options.resultCache;\n  if (resultCache && resultCache.lastInput &&\n      input.isEqual(resultCache.lastInput)) {\n    return resultCache.lastOutput;\n  }\n\n  if (options.supportedIsobuildFeaturePackages) {\n    _.each(options.supportedIsobuildFeaturePackages, function (versions, pkg) {\n      _.each(versions, function (version) {\n        input.catalogCache.addPackageVersion(pkg, version, []);\n      });\n    });\n  }\n\n  Profile.time(\n    \"Input#loadOnlyPreviousSolution\",\n    function () {\n      input.loadOnlyPreviousSolution(self.catalogLoader);\n    });\n\n  if (options.previousSolution && options.missingPreviousVersionIsError) {\n    // see comment where missingPreviousVersionIsError is passed in\n    Profile.time(\"check for previous versions in catalog\", function () {\n      _.each(options.previousSolution, function (version, pkg) {\n        if (! input.catalogCache.hasPackageVersion(pkg, version)) {\n          CS.throwConstraintSolverError(\n            \"Package version not in catalog: \" + pkg + \" \" + version);\n        }\n      });\n    });\n  }\n\n  var resolveOptions = {\n    nudge: self._options.nudge,\n    Profile: self._options.Profile\n  };\n\n  var output = null;\n  if (options.previousSolution && !input.upgrade && !input.upgradeIndirectDepPatchVersions) {\n    // Try solving first with just the versions from previousSolution in\n    // the catalogCache, so that we don't have to solve the big problem\n    // if we don't have to. But don't do this if we're attempting to upgrade\n    // packages, because that would always result in just using the current\n    // version, hence disabling upgrades.\n    try {\n      output = CS.PackagesResolver._resolveWithInput(input, resolveOptions);\n    } catch (e) {\n      if (e.constraintSolverError) {\n        output = null;\n      } else {\n        throw e;\n      }\n    }\n  }\n\n  if (! output) {\n    // do a solve with all package versions available in the catalog.\n    Profile.time(\n      \"Input#loadFromCatalog\",\n      function () {\n        input.loadFromCatalog(self.catalogLoader);\n      });\n\n    // if we fail to find a solution this time, this will throw.\n    output = CS.PackagesResolver._resolveWithInput(input, resolveOptions);\n  }\n\n  if (resultCache) {\n    resultCache.lastInput = input;\n    resultCache.lastOutput = output;\n  }\n\n  return output;\n};\n\n// Exposed for tests.\n//\n// Options (all optional):\n// - nudge (function to be called when possible to \"nudge\" the progress spinner)\n// - allAnswers (for testing, calculate all possible answers and put an extra\n//   property named \"allAnswers\" on the result)\n// - Profile (the profiler interface in `tools/profile.js`)\nCS.PackagesResolver._resolveWithInput = function (input, options) {\n  options = options || {};\n\n  if (Meteor.isServer &&\n      process.env['METEOR_PRINT_CONSTRAINT_SOLVER_INPUT']) {\n    console.log(\"CONSTRAINT_SOLVER_INPUT = \");\n    console.log(JSON.stringify(input.toJSONable(), null, 2));\n  }\n\n  var solver;\n  (options.Profile || CS.DummyProfile).time(\"new CS.Solver\", function () {\n    solver = new CS.Solver(input, {\n      nudge: options.nudge,\n      Profile: options.Profile\n    });\n  });\n\n  // Disable runtime type checks (they slow things down a bunch)\n  return Logic.disablingAssertions(function () {\n    var result = solver.getAnswer({\n      allAnswers: options.allAnswers\n    });\n    // if we're here, no conflicts were found (or an error would have\n    // been thrown)\n    return result;\n  });\n};\n\n\n// - package: String package name\n// - vConstraint: a PackageVersion.VersionConstraint, or an object\n//   with an `alternatives` property lifted from one.\n// - version: version String\nCS.isConstraintSatisfied = function (pkg, vConstraint, version) {\n  return _.some(vConstraint.alternatives, function (simpleConstraint) {\n    var type = simpleConstraint.type;\n\n    if (type === \"any-reasonable\") {\n      return true;\n    } else if (type === \"exactly\") {\n      var cVersion = simpleConstraint.versionString;\n      return (cVersion === version);\n    } else if (type === 'compatible-with') {\n      var cv = PV.parse(simpleConstraint.versionString);\n      var v = PV.parse(version);\n\n      // If the candidate version is less than the version named in the\n      // constraint, we are not satisfied.\n      if (PV.lessThan(v, cv)) {\n        return false;\n      }\n\n      // To be compatible, the two versions must have the same major version\n      // number.\n      if (v.major !== cv.major) {\n        return false;\n      }\n\n      return true;\n    } else {\n      throw Error(\"Unknown constraint type: \" + type);\n    }\n  });\n};\n\nCS.throwConstraintSolverError = function (message) {\n  var e = new Error(message);\n  e.constraintSolverError = true;\n  throw e;\n};\n\n// This function is duplicated in tools/compiler.js.\nCS.isIsobuildFeaturePackage = function (packageName) {\n  return /^isobuild:/.test(packageName);\n};\n\n\n// Implements the Profile interface (as we use it) but doesn't do\n// anything.\nCS.DummyProfile = function (bucket, f) {\n  return f;\n};\nCS.DummyProfile.time = function (bucket, f) {\n  return f();\n};\n"
  },
  {
    "path": "packages/constraint-solver/datatypes-tests.js",
    "content": "var PV = PackageVersion;\nvar CS = ConstraintSolver;\n\nTinytest.add(\"constraint solver - datatypes - Dependency\", function (test) {\n  _.each([\"foo\", \"foo@1.0.0\"], function (foo) {\n    var d1 = new CS.Dependency(PV.parsePackageConstraint(foo));\n    test.equal(d1.packageConstraint.toString(), foo);\n    test.equal(d1.isWeak, false);\n\n    var d1 = new CS.Dependency(foo);\n    test.equal(d1.packageConstraint.toString(), foo);\n    test.equal(d1.isWeak, false);\n\n    var d2 = new CS.Dependency(foo, { isWeak: false });\n    test.equal(d2.packageConstraint.toString(), foo);\n    test.equal(d2.isWeak, false);\n\n    var d3 = new CS.Dependency(foo, { isWeak: true });\n    test.equal(d3.packageConstraint.toString(), foo);\n    test.equal(d3.isWeak, true);\n\n    var d4 = CS.Dependency.fromString('?'+foo);\n    test.equal(d4.packageConstraint.toString(), foo);\n    test.equal(d4.isWeak, true);\n\n    var d5 = CS.Dependency.fromString(foo);\n    test.equal(d5.packageConstraint.toString(), foo);\n    test.equal(d5.isWeak, false);\n  });\n\n  test.throws(function () {\n    CS.Dependency.fromString('?');\n  });\n\n  test.throws(function () {\n    new CS.Dependency(\"foo\", \"1.0.0\");\n  });\n});\n"
  },
  {
    "path": "packages/constraint-solver/datatypes.js",
    "content": "ConstraintSolver = {};\n\nvar PV = PackageVersion;\nvar CS = ConstraintSolver;\n\n////////// PackageAndVersion\n\n// An ordered pair of (package, version).\nCS.PackageAndVersion = function (pkg, version) {\n  check(pkg, String);\n  check(version, String);\n\n  this.package = pkg;\n  this.version = version;\n};\n\n// The string form of a PackageAndVersion is \"package version\",\n// for example \"foo 1.0.1\".  The reason we don't use an \"@\" is\n// it would look too much like a PackageConstraint.\nCS.PackageAndVersion.prototype.toString = function () {\n  return this.package + \" \" + this.version;\n};\n\nCS.PackageAndVersion.fromString = function (str) {\n  var parts = str.split(' ');\n  if (parts.length === 2 && parts[0] && parts[1]) {\n    return new CS.PackageAndVersion(parts[0], parts[1]);\n  } else {\n    throw new Error(\"Malformed PackageAndVersion: \" + str);\n  }\n};\n\n////////// Dependency\n\n// A Dependency consists of a PackageConstraint (like \"foo@=1.2.3\")\n// and flags, like \"isWeak\".\n\nCS.Dependency = function (packageConstraint, flags) {\n  if (typeof packageConstraint !== 'string') {\n    // this `if` is because Match.OneOf is really, really slow when it fails\n    check(packageConstraint, Match.OneOf(PV.PackageConstraint, String));\n  }\n  if (typeof packageConstraint === 'string') {\n    packageConstraint = PV.parsePackageConstraint(packageConstraint);\n  }\n  if (flags) {\n    check(flags, Object);\n  }\n\n  this.packageConstraint = packageConstraint;\n  this.isWeak = false;\n\n  if (flags) {\n    if (flags.isWeak) {\n      this.isWeak = true;\n    }\n  }\n};\n\n// The string form of a Dependency is `?foo@1.0.0` for a weak\n// reference to package \"foo\" with VersionConstraint \"1.0.0\".\nCS.Dependency.prototype.toString = function () {\n  var ret = this.packageConstraint.toString();\n  if (this.isWeak) {\n    ret = '?' + ret;\n  }\n  return ret;\n};\n\nCS.Dependency.fromString = function (str) {\n  var isWeak = false;\n\n  if (str.charAt(0) === '?') {\n    isWeak = true;\n    str = str.slice(1);\n  }\n\n  var flags = isWeak ? { isWeak: true } : null;\n\n  return new CS.Dependency(str, flags);\n};\n"
  },
  {
    "path": "packages/constraint-solver/gem-test-data.js",
    "content": "// This file contains data for tests in benchmark-tests.js.\n\n// It defines the variables `railsGems` and `sinatraGems`.\n\n// The data has been heavily adapted and is not semantically\n// equivalent to its original source.  It's just a big dataset to\n// throw at the solver that is sort of organic and semi-realistic.\n\nrailsGems = [\n  {\"name\":\"rack-cache\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"htmlentities\",\"number\":\"4.0.0\",\"dependencies\":[]},\n  {\"name\":\"hpricot\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"hpricot\",\"number\":\"1.10.0\",\"dependencies\":[]},\n  {\"name\":\"roauth\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"rack-accept\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"mini-portile\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"actionview\",\"number\":\"4.1.0\",\"dependencies\":[]},\n  {\"name\":\"redis-rack-cache\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"jnunemaker-crack\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"echoe\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"hoe\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"hoe\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"hoe\",\"number\":\"1.20.3\",\"dependencies\":[]},\n  {\"name\":\"hoe\",\"number\":\"2.20.1\",\"dependencies\":[]},\n  {\"name\":\"unicode\",\"number\":\"0.4.4\",\"dependencies\":[]},\n  {\"name\":\"fog-brightbox\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"fog-json\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"fog-core\",\"number\":\"1.21.1\",\"dependencies\":[]},\n  {\"name\":\"mongrel\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"bundler\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"bundler\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"bundler\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"bundler\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"bundler\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"bundler\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"bundler\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"bundler\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"bundler\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"bundler\",\"number\":\"1.8.0\",\"dependencies\":[]},\n  {\"name\":\"bundler\",\"number\":\"1.9.0\",\"dependencies\":[]},\n  {\"name\":\"bundler\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"bcrypt\",\"number\":\"3.1.7\",\"dependencies\":[]},\n  {\"name\":\"bcrypt\",\"number\":\"3.1.6\",\"dependencies\":[]},\n  {\"name\":\"bcrypt\",\"number\":\"3.1.3\",\"dependencies\":[]},\n  {\"name\":\"shotgun\",\"number\":\"0.6.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"shotgun\",\"number\":\"0.4.0\",\"dependencies\":[[\"rack\",null],[\"launchy\",null],[\"launchy\",null]]},\n  {\"name\":\"shotgun\",\"number\":\"0.5.0\",\"dependencies\":[[\"rack\",null],[\"launchy\",null],[\"launchy\",null]]},\n  {\"name\":\"shotgun\",\"number\":\"0.7.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"shotgun\",\"number\":\"0.8.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"shotgun\",\"number\":\"0.2.0\",\"dependencies\":[[\"rack\",null],[\"launchy\",null],[\"rack\",null],[\"launchy\",null]]},\n  {\"name\":\"shotgun\",\"number\":\"0.1.0\",\"dependencies\":[[\"rack\",null],[\"rack\",null]]},\n  {\"name\":\"shotgun\",\"number\":\"0.3.0\",\"dependencies\":[[\"rack\",null],[\"launchy\",null],[\"launchy\",null]]},\n  {\"name\":\"shotgun\",\"number\":\"0.9.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"backports\",\"number\":\"0.15.0\",\"dependencies\":[]},\n  {\"name\":\"backports\",\"number\":\"1.15.0\",\"dependencies\":[]},\n  {\"name\":\"backports\",\"number\":\"2.15.0\",\"dependencies\":[]},\n  {\"name\":\"backports\",\"number\":\"3.15.0\",\"dependencies\":[]},\n  {\"name\":\"sprockets-sass\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"ace-rails-ap\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"ace-rails-ap\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"ace-rails-ap\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"ace-rails-ap\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"ace-rails-ap\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"ace-rails-ap\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"actionmailer\",\"number\":\"4.0.4\",\"dependencies\":[[\"mail\",\"2.5.4\"],[\"actionpack\",\"=4.0.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.17\",\"dependencies\":[[\"mail\",\"2.5.4\"],[\"actionpack\",\"=3.2.17\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"4.0.3\",\"dependencies\":[[\"mail\",\"2.5.4\"],[\"actionpack\",\"=4.0.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"4.0.2\",\"dependencies\":[[\"mail\",\"2.5.4\"],[\"actionpack\",\"=4.0.2\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.16\",\"dependencies\":[[\"mail\",\"2.5.4\"],[\"actionpack\",\"=3.2.16\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"4.0.1\",\"dependencies\":[[\"mail\",\"2.5.4\"],[\"actionpack\",\"=4.0.1\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.15\",\"dependencies\":[[\"mail\",\"2.5.4\"],[\"actionpack\",\"=3.2.15\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"0.9.0\",\"dependencies\":[[\"actionpack\",\"=1.8.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.2.4\",\"dependencies\":[[\"actionpack\",\"=1.12.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.3.2\",\"dependencies\":[[\"actionpack\",\"=1.13.2\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"0.9.1\",\"dependencies\":[[\"actionpack\",\"=1.8.1\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.1.4\",\"dependencies\":[[\"actionpack\",\"=1.11.1\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.2.3\",\"dependencies\":[[\"actionpack\",\"=2.2.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.3.1\",\"dependencies\":[[\"actionpack\",\"=1.13.1\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"0.4.0\",\"dependencies\":[[\"actionpack\",null]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.0.1\",\"dependencies\":[[\"actionpack\",\"=1.9.1\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.4\",\"dependencies\":[[\"actionpack\",\"=2.3.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.15\",\"dependencies\":[[\"actionpack\",\"=3.0.15\"],[\"mail\",\"2.2.19\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.2\",\"dependencies\":[[\"actionpack\",\"=3.2.2\"],[\"mail\",\"2.4.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.11\",\"dependencies\":[[\"actionpack\",\"=2.3.11\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.10\",\"dependencies\":[[\"actionpack\",\"=2.3.10\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.2.5\",\"dependencies\":[[\"actionpack\",\"=1.12.5\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.6\",\"dependencies\":[[\"actionpack\",\"=3.0.6\"],[\"mail\",\"2.2.15\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.16\",\"dependencies\":[[\"actionpack\",\"=3.0.16\"],[\"mail\",\"2.2.19\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.8\",\"dependencies\":[[\"actionpack\",\"=2.3.8\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.1.1\",\"dependencies\":[[\"actionpack\",\"=1.10.1\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.0.0\",\"dependencies\":[[\"actionpack\",\"=2.0.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.1.1\",\"dependencies\":[[\"actionpack\",\"=2.1.1\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.2\",\"dependencies\":[[\"actionpack\",\"=2.3.2\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.2.2\",\"dependencies\":[[\"actionpack\",\"=1.12.2\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"0.7.0\",\"dependencies\":[[\"actionpack\",\"=1.5.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.3\",\"dependencies\":[[\"actionpack\",\"=3.0.3\"],[\"mail\",\"2.2.9\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.10\",\"dependencies\":[[\"actionpack\",\"=3.0.10\"],[\"mail\",\"2.2.19\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.0\",\"dependencies\":[[\"actionpack\",\"=3.0.0\"],[\"mail\",\"2.2.5\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.14\",\"dependencies\":[[\"actionpack\",\"=3.0.14\"],[\"mail\",\"2.2.19\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.1.3\",\"dependencies\":[[\"actionpack\",\"=1.11.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"0.5.0\",\"dependencies\":[[\"actionpack\",null]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.1.0\",\"dependencies\":[[\"actionpack\",\"=3.1.0\"],[\"mail\",\"2.3.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.2.0\",\"dependencies\":[[\"actionpack\",\"=1.12.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.3.5\",\"dependencies\":[[\"actionpack\",\"=1.13.5\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.3.6\",\"dependencies\":[[\"actionpack\",\"=1.13.6\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.0\",\"dependencies\":[[\"actionpack\",\"=3.2.0\"],[\"mail\",\"2.4.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.4\",\"dependencies\":[[\"actionpack\",\"=3.2.4\"],[\"mail\",\"2.4.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.1.2\",\"dependencies\":[[\"actionpack\",\"=2.1.2\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.9\",\"dependencies\":[[\"actionpack\",\"=3.0.9\"],[\"mail\",\"2.2.19\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.1.8\",\"dependencies\":[[\"actionpack\",\"=3.1.8\"],[\"mail\",\"2.3.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.3\",\"dependencies\":[[\"actionpack\",\"=3.2.3\"],[\"mail\",\"2.4.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.5\",\"dependencies\":[[\"actionpack\",\"=3.2.5\"],[\"mail\",\"2.4.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.7\",\"dependencies\":[[\"actionpack\",\"=3.2.7\"],[\"mail\",\"2.4.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.1.4\",\"dependencies\":[[\"actionpack\",\"=3.1.4\"],[\"mail\",\"2.3.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.2.2\",\"dependencies\":[[\"actionpack\",\"=2.2.2\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.2\",\"dependencies\":[[\"actionpack\",\"=3.0.2\"],[\"mail\",\"2.2.9\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.1.2\",\"dependencies\":[[\"actionpack\",\"=1.10.2\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.6\",\"dependencies\":[[\"actionpack\",\"=2.3.6\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.17\",\"dependencies\":[[\"actionpack\",\"=3.0.17\"],[\"mail\",\"2.2.19\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.1.2\",\"dependencies\":[[\"actionpack\",\"=3.1.2\"],[\"mail\",\"2.3.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.1.5\",\"dependencies\":[[\"actionpack\",\"=3.1.5\"],[\"mail\",\"2.3.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.6\",\"dependencies\":[[\"actionpack\",\"=3.2.6\"],[\"mail\",\"2.4.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"0.7.1\",\"dependencies\":[[\"actionpack\",\"=1.5.1\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.0.1\",\"dependencies\":[[\"actionpack\",\"=2.0.1\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.12\",\"dependencies\":[[\"actionpack\",\"=2.3.12\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.0.0\",\"dependencies\":[[\"actionpack\",\"=1.9.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.3.0\",\"dependencies\":[[\"actionpack\",\"=1.13.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.2.1\",\"dependencies\":[[\"actionpack\",\"=1.12.1\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.1\",\"dependencies\":[[\"actionpack\",\"=3.0.1\"],[\"mail\",\"2.2.5\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.7\",\"dependencies\":[[\"actionpack\",\"=3.0.7\"],[\"mail\",\"2.2.15\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.5\",\"dependencies\":[[\"actionpack\",\"=2.3.5\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.0.2\",\"dependencies\":[[\"actionpack\",\"=2.0.2\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"0.6.0\",\"dependencies\":[[\"actionpack\",null]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.7\",\"dependencies\":[[\"actionpack\",\"=2.3.7\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.0.5\",\"dependencies\":[[\"actionpack\",\"=2.0.5\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.12\",\"dependencies\":[[\"actionpack\",\"=3.0.12\"],[\"mail\",\"2.2.19\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.1.0\",\"dependencies\":[[\"actionpack\",\"=2.1.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.11\",\"dependencies\":[[\"actionpack\",\"=3.0.11\"],[\"mail\",\"2.2.19\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.1.7\",\"dependencies\":[[\"actionpack\",\"=3.1.7\"],[\"mail\",\"2.3.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.3.3\",\"dependencies\":[[\"actionpack\",\"=1.13.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.8\",\"dependencies\":[[\"actionpack\",\"=3.0.8\"],[\"mail\",\"2.2.19\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.8\",\"dependencies\":[[\"actionpack\",\"=3.2.8\"],[\"mail\",\"2.4.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"0.6.1\",\"dependencies\":[[\"actionpack\",null]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.4\",\"dependencies\":[[\"actionpack\",\"=3.0.4\"],[\"mail\",\"2.2.15\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.1.5\",\"dependencies\":[[\"actionpack\",\"=1.11.2\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.3.4\",\"dependencies\":[[\"actionpack\",\"=1.13.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"0.3.0\",\"dependencies\":[[\"actionpack\",null]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.1.1\",\"dependencies\":[[\"actionpack\",\"=3.1.1\"],[\"mail\",\"2.3.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.1.3\",\"dependencies\":[[\"actionpack\",\"=3.1.3\"],[\"mail\",\"2.3.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.9\",\"dependencies\":[[\"actionpack\",\"=2.3.9\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.1.6\",\"dependencies\":[[\"actionpack\",\"=3.1.6\"],[\"mail\",\"2.3.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.0.4\",\"dependencies\":[[\"actionpack\",\"=2.0.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.1\",\"dependencies\":[[\"actionpack\",\"=3.2.1\"],[\"mail\",\"2.4.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.14\",\"dependencies\":[[\"actionpack\",\"=2.3.14\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.13\",\"dependencies\":[[\"actionpack\",\"=3.0.13\"],[\"mail\",\"2.2.19\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"1.2.3\",\"dependencies\":[[\"actionpack\",\"=1.12.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"0.8.1\",\"dependencies\":[[\"actionpack\",\"=1.7.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.5\",\"dependencies\":[[\"actionpack\",\"=3.0.5\"],[\"mail\",\"2.2.15\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"0.8.0\",\"dependencies\":[[\"actionpack\",\"=1.6.0\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.3\",\"dependencies\":[[\"actionpack\",\"=2.3.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.9\",\"dependencies\":[[\"actionpack\",\"=3.2.9\"],[\"mail\",\"2.4.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.1.9\",\"dependencies\":[[\"actionpack\",\"=3.1.9\"],[\"mail\",\"2.3.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.10\",\"dependencies\":[[\"actionpack\",\"=3.2.10\"],[\"mail\",\"2.4.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.18\",\"dependencies\":[[\"actionpack\",\"=3.0.18\"],[\"mail\",\"2.2.19\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.19\",\"dependencies\":[[\"actionpack\",\"=3.0.19\"],[\"mail\",\"2.2.19\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.15\",\"dependencies\":[[\"actionpack\",\"=2.3.15\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.11\",\"dependencies\":[[\"actionpack\",\"=3.2.11\"],[\"mail\",\"2.4.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.1.10\",\"dependencies\":[[\"actionpack\",\"=3.1.10\"],[\"mail\",\"2.3.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.0.20\",\"dependencies\":[[\"actionpack\",\"=3.0.20\"],[\"mail\",\"2.2.19\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.16\",\"dependencies\":[[\"actionpack\",\"=2.3.16\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.17\",\"dependencies\":[[\"actionpack\",\"=2.3.17\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.12\",\"dependencies\":[[\"actionpack\",\"=3.2.12\"],[\"mail\",\"2.4.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.1.11\",\"dependencies\":[[\"actionpack\",\"=3.1.11\"],[\"mail\",\"2.3.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"2.3.18\",\"dependencies\":[[\"actionpack\",\"=2.3.18\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.1.12\",\"dependencies\":[[\"actionpack\",\"=3.1.12\"],[\"mail\",\"2.4.4\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.13\",\"dependencies\":[[\"actionpack\",\"=3.2.13\"],[\"mail\",\"2.5.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"4.0.0\",\"dependencies\":[[\"actionpack\",\"=4.0.0\"],[\"mail\",\"2.5.3\"]]},\n  {\"name\":\"actionmailer\",\"number\":\"3.2.14\",\"dependencies\":[[\"actionpack\",\"=3.2.14\"],[\"mail\",\"2.5.4\"]]},\n  {\"name\":\"actionpack\",\"number\":\"4.0.4\",\"dependencies\":[[\"erubis\",\"2.7.0\"],[\"rack-test\",\"0.6.2\"],[\"rack\",\"1.5.2\"],[\"builder\",\"3.1.0\"],[\"activesupport\",\"=4.0.4\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.17\",\"dependencies\":[[\"erubis\",\"2.7.0\"],[\"sprockets\",\"2.2.1\"],[\"journey\",\"1.0.4\"],[\"rack-test\",\"0.6.1\"],[\"rack\",\"1.4.5\"],[\"builder\",\"3.0.0\"],[\"rack-cache\",\"1.2.0\"],[\"activemodel\",\"=3.2.17\"],[\"activesupport\",\"=3.2.17\"]]},\n  {\"name\":\"actionpack\",\"number\":\"4.0.3\",\"dependencies\":[[\"erubis\",\"2.7.0\"],[\"rack-test\",\"0.6.2\"],[\"rack\",\"1.5.2\"],[\"builder\",\"3.1.0\"],[\"activesupport\",\"=4.0.3\"]]},\n  {\"name\":\"actionpack\",\"number\":\"4.0.2\",\"dependencies\":[[\"erubis\",\"2.7.0\"],[\"rack-test\",\"0.6.2\"],[\"rack\",\"1.5.2\"],[\"builder\",\"3.1.0\"],[\"activesupport\",\"=4.0.2\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.16\",\"dependencies\":[[\"erubis\",\"2.7.0\"],[\"sprockets\",\"2.2.1\"],[\"journey\",\"1.0.4\"],[\"rack-test\",\"0.6.1\"],[\"rack\",\"1.4.5\"],[\"builder\",\"3.0.0\"],[\"rack-cache\",\"1.2.0\"],[\"activemodel\",\"=3.2.16\"],[\"activesupport\",\"=3.2.16\"]]},\n  {\"name\":\"actionpack\",\"number\":\"4.0.1\",\"dependencies\":[[\"erubis\",\"2.7.0\"],[\"rack-test\",\"0.6.2\"],[\"rack\",\"1.5.2\"],[\"builder\",\"3.1.0\"],[\"activesupport\",\"=4.0.1\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.15\",\"dependencies\":[[\"erubis\",\"2.7.0\"],[\"sprockets\",\"2.2.1\"],[\"journey\",\"1.0.4\"],[\"rack-test\",\"0.6.1\"],[\"rack\",\"1.4.5\"],[\"builder\",\"3.0.0\"],[\"rack-cache\",\"1.2.0\"],[\"activemodel\",\"=3.2.15\"],[\"activesupport\",\"=3.2.15\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.7\",\"dependencies\":[[\"activesupport\",\"=3.2.7\"],[\"activemodel\",\"=3.2.7\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.0\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.4\"],[\"sprockets\",\"2.1.3\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.7\",\"dependencies\":[[\"activesupport\",\"=3.0.7\"],[\"activemodel\",\"=3.0.7\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.1\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.13\",\"dependencies\":[[\"activesupport\",\"=3.0.13\"],[\"activemodel\",\"=3.0.13\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.5\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.8\",\"dependencies\":[[\"activesupport\",\"=2.3.8\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"actionpack\",\"number\":\"1.12.2\",\"dependencies\":[[\"activesupport\",\"=1.3.1\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.1\",\"dependencies\":[[\"activesupport\",\"=3.0.1\"],[\"activemodel\",\"=3.0.1\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.4.1\"],[\"rack\",\"1.2.1\"],[\"rack-test\",\"0.5.4\"],[\"rack-mount\",\"0.6.12\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.11.2\",\"dependencies\":[[\"activesupport\",\"=1.2.5\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.0\",\"dependencies\":[[\"activesupport\",\"=3.2.0\"],[\"activemodel\",\"=3.2.0\"],[\"rack-cache\",\"1.1.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.0\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.0\"],[\"sprockets\",\"2.1.2\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.1.1\",\"dependencies\":[[\"activesupport\",\"=3.1.1\"],[\"activemodel\",\"=3.1.1\"],[\"rack-cache\",\"1.1.0\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"rack\",\"1.3.2\"],[\"rack-test\",\"0.6.1\"],[\"rack-mount\",\"0.8.2\"],[\"sprockets\",\"2.0.2\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.1.7\",\"dependencies\":[[\"activesupport\",\"=3.1.7\"],[\"activemodel\",\"=3.1.7\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"rack\",\"1.3.6\"],[\"rack-test\",\"0.6.1\"],[\"rack-mount\",\"0.8.2\"],[\"sprockets\",\"2.0.4\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.4\",\"dependencies\":[[\"activesupport\",\"=3.2.4\"],[\"activemodel\",\"=3.2.4\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.0\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.1\"],[\"sprockets\",\"2.1.3\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"actionpack\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.5\",\"dependencies\":[[\"activesupport\",\"=3.0.5\"],[\"activemodel\",\"=3.0.5\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.4.0\"],[\"rack\",\"1.2.1\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.13\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.12\",\"dependencies\":[[\"activesupport\",\"=3.0.12\"],[\"activemodel\",\"=3.0.12\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.5\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.11\",\"dependencies\":[[\"activesupport\",\"=3.0.11\"],[\"activemodel\",\"=3.0.11\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.1\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"actionpack\",\"number\":\"3.1.6\",\"dependencies\":[[\"activesupport\",\"=3.1.6\"],[\"activemodel\",\"=3.1.6\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"rack\",\"1.3.6\"],[\"rack-test\",\"0.6.1\"],[\"rack-mount\",\"0.8.2\"],[\"sprockets\",\"2.0.4\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"actionpack\",\"number\":\"2.0.4\",\"dependencies\":[[\"activesupport\",\"=2.0.4\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.12.3\",\"dependencies\":[[\"activesupport\",\"=1.3.1\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.12.4\",\"dependencies\":[[\"activesupport\",\"=1.3.1\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.6\",\"dependencies\":[[\"activesupport\",\"=3.2.6\"],[\"activemodel\",\"=3.2.6\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.0\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.1\"],[\"sprockets\",\"2.1.3\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.3\",\"dependencies\":[[\"activesupport\",\"=3.0.3\"],[\"activemodel\",\"=3.0.3\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.4.0\"],[\"rack\",\"1.2.1\"],[\"rack-test\",\"0.5.6\"],[\"rack-mount\",\"0.6.13\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.12.5\",\"dependencies\":[[\"activesupport\",\"=1.3.1\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.1.2\",\"dependencies\":[[\"activesupport\",\"=3.1.2\"],[\"activemodel\",\"=3.1.2\"],[\"rack-cache\",\"1.1.0\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"rack\",\"1.3.5\"],[\"rack-test\",\"0.6.1\"],[\"rack-mount\",\"0.8.2\"],[\"sprockets\",\"2.1.0\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.2\",\"dependencies\":[[\"activesupport\",\"=2.3.2\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.10.2\",\"dependencies\":[[\"activesupport\",\"=1.2.2\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"actionpack\",\"number\":\"1.8.0\",\"dependencies\":[[\"activesupport\",\"=1.0.4\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"actionpack\",\"number\":\"3.1.0\",\"dependencies\":[[\"activesupport\",\"=3.1.0\"],[\"activemodel\",\"=3.1.0\"],[\"rack-cache\",\"1.0.3\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"rack\",\"1.3.2\"],[\"rack-test\",\"0.6.1\"],[\"rack-mount\",\"0.8.2\"],[\"sprockets\",\"2.0.0\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.1.2\",\"dependencies\":[[\"activesupport\",\"=2.1.2\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.1.0\",\"dependencies\":[[\"activesupport\",\"=2.1.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.9\",\"dependencies\":[[\"activesupport\",\"=2.3.9\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.14\",\"dependencies\":[[\"activesupport\",\"=2.3.14\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.2.3\",\"dependencies\":[[\"activesupport\",\"=2.2.3\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.13.5\",\"dependencies\":[[\"activesupport\",\"=1.4.4\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.14\",\"dependencies\":[[\"activesupport\",\"=3.0.14\"],[\"activemodel\",\"=3.0.14\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.5\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.11.0\",\"dependencies\":[[\"activesupport\",\"=1.2.3\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.3\",\"dependencies\":[[\"activesupport\",\"=2.3.3\"],[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.2.2\",\"dependencies\":[[\"activesupport\",\"=2.2.2\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.4\",\"dependencies\":[[\"activesupport\",\"=2.3.4\"],[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.7.0\",\"dependencies\":[[\"activesupport\",\"=1.0.3\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.9\",\"dependencies\":[[\"activesupport\",\"=3.0.9\"],[\"activemodel\",\"=3.0.9\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.1\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.10\",\"dependencies\":[[\"activesupport\",\"=3.0.10\"],[\"activemodel\",\"=3.0.10\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.1\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.0\",\"dependencies\":[[\"activesupport\",\"=3.0.0\"],[\"activemodel\",\"=3.0.0\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.4.1\"],[\"rack\",\"1.2.1\"],[\"rack-test\",\"0.5.4\"],[\"rack-mount\",\"0.6.12\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.1.1\",\"dependencies\":[[\"activesupport\",\"=2.1.1\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.13.1\",\"dependencies\":[[\"activesupport\",\"=1.4.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.12\",\"dependencies\":[[\"activesupport\",\"=2.3.12\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.11\",\"dependencies\":[[\"activesupport\",\"=2.3.11\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"0.9.5\",\"dependencies\":[]},\n  {\"name\":\"actionpack\",\"number\":\"2.0.0\",\"dependencies\":[[\"activesupport\",\"=2.0.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.7\",\"dependencies\":[[\"activesupport\",\"=2.3.7\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.6.0\",\"dependencies\":[[\"activesupport\",\"=1.0.2\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.5.0\",\"dependencies\":[[\"activesupport\",\"=1.0.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.6\",\"dependencies\":[[\"activesupport\",\"=2.3.6\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.9.0\",\"dependencies\":[[\"activesupport\",\"=1.1.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.13.6\",\"dependencies\":[[\"activesupport\",\"=1.4.4\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.12.1\",\"dependencies\":[[\"activesupport\",\"=1.3.1\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.0.1\",\"dependencies\":[[\"activesupport\",\"=2.0.1\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.9.1\",\"dependencies\":[[\"activesupport\",\"=1.1.1\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.10.1\",\"dependencies\":[[\"activesupport\",\"=1.2.1\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.12.0\",\"dependencies\":[[\"activesupport\",\"=1.3.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.0.2\",\"dependencies\":[[\"activesupport\",\"=2.0.2\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.0.5\",\"dependencies\":[[\"activesupport\",\"=2.0.5\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.13.4\",\"dependencies\":[[\"activesupport\",\"=1.4.3\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.13.2\",\"dependencies\":[[\"activesupport\",\"=1.4.1\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.1.3\",\"dependencies\":[[\"activesupport\",\"=3.1.3\"],[\"activemodel\",\"=3.1.3\"],[\"rack-cache\",\"1.1.0\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"rack\",\"1.3.5\"],[\"rack-test\",\"0.6.1\"],[\"rack-mount\",\"0.8.2\"],[\"sprockets\",\"2.0.3\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.15\",\"dependencies\":[[\"activesupport\",\"=3.0.15\"],[\"activemodel\",\"=3.0.15\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.5\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.16\",\"dependencies\":[[\"activesupport\",\"=3.0.16\"],[\"activemodel\",\"=3.0.16\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.5\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.1.5\",\"dependencies\":[[\"activesupport\",\"=3.1.5\"],[\"activemodel\",\"=3.1.5\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"rack\",\"1.3.6\"],[\"rack-test\",\"0.6.1\"],[\"rack-mount\",\"0.8.2\"],[\"sprockets\",\"2.0.4\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.17\",\"dependencies\":[[\"activesupport\",\"=3.0.17\"],[\"activemodel\",\"=3.0.17\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.5\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.1.8\",\"dependencies\":[[\"activesupport\",\"=3.1.8\"],[\"activemodel\",\"=3.1.8\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"rack\",\"1.3.6\"],[\"rack-test\",\"0.6.1\"],[\"rack-mount\",\"0.8.2\"],[\"sprockets\",\"2.0.4\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.1\",\"dependencies\":[[\"activesupport\",\"=3.2.1\"],[\"activemodel\",\"=3.2.1\"],[\"rack-cache\",\"1.1.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.0\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.1\"],[\"sprockets\",\"2.1.2\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.8\",\"dependencies\":[[\"activesupport\",\"=3.2.8\"],[\"activemodel\",\"=3.2.8\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.0\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.4\"],[\"sprockets\",\"2.1.3\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.2\",\"dependencies\":[[\"activesupport\",\"=3.0.2\"],[\"activemodel\",\"=3.0.2\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.4.1\"],[\"rack\",\"1.2.1\"],[\"rack-test\",\"0.5.6\"],[\"rack-mount\",\"0.6.13\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.10\",\"dependencies\":[[\"activesupport\",\"=2.3.10\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.6\",\"dependencies\":[[\"activesupport\",\"=3.0.6\"],[\"activemodel\",\"=3.0.6\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.1\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.8\",\"dependencies\":[[\"activesupport\",\"=3.0.8\"],[\"activemodel\",\"=3.0.8\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.1\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.5\",\"dependencies\":[[\"activesupport\",\"=2.3.5\"],[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.4\",\"dependencies\":[[\"activesupport\",\"=3.0.4\"],[\"activemodel\",\"=3.0.4\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.4.0\"],[\"rack\",\"1.2.1\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.13\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.2\",\"dependencies\":[[\"activesupport\",\"=3.2.2\"],[\"activemodel\",\"=3.2.2\"],[\"rack-cache\",\"1.1.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.0\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.1\"],[\"sprockets\",\"2.1.2\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.3\",\"dependencies\":[[\"activesupport\",\"=3.2.3\"],[\"activemodel\",\"=3.2.3\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.0\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.1\"],[\"sprockets\",\"2.1.2\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.5\",\"dependencies\":[[\"activesupport\",\"=3.2.5\"],[\"activemodel\",\"=3.2.5\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.0\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.1\"],[\"sprockets\",\"2.1.3\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.8.1\",\"dependencies\":[[\"activesupport\",\"=1.0.4\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.13.3\",\"dependencies\":[[\"activesupport\",\"=1.4.2\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.13.0\",\"dependencies\":[[\"activesupport\",\"=1.4.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.11.1\",\"dependencies\":[[\"activesupport\",\"=1.2.4\"]]},\n  {\"name\":\"actionpack\",\"number\":\"1.5.1\",\"dependencies\":[[\"activesupport\",\"=1.0.1\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.1.4\",\"dependencies\":[[\"activesupport\",\"=3.1.4\"],[\"activemodel\",\"=3.1.4\"],[\"rack-cache\",\"1.1.0\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"rack\",\"1.3.6\"],[\"rack-test\",\"0.6.1\"],[\"rack-mount\",\"0.8.2\"],[\"sprockets\",\"2.0.3\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.9\",\"dependencies\":[[\"activesupport\",\"=3.2.9\"],[\"activemodel\",\"=3.2.9\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.0\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.4\"],[\"sprockets\",\"2.2.1\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.18\",\"dependencies\":[[\"activesupport\",\"=3.0.18\"],[\"activemodel\",\"=3.0.18\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.5\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.10\",\"dependencies\":[[\"activesupport\",\"=3.2.10\"],[\"activemodel\",\"=3.2.10\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.0\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.4\"],[\"sprockets\",\"2.2.1\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.1.9\",\"dependencies\":[[\"activesupport\",\"=3.1.9\"],[\"activemodel\",\"=3.1.9\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"rack\",\"1.3.6\"],[\"rack-test\",\"0.6.1\"],[\"rack-mount\",\"0.8.2\"],[\"sprockets\",\"2.0.4\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.11\",\"dependencies\":[[\"activesupport\",\"=3.2.11\"],[\"activemodel\",\"=3.2.11\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.0\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.4\"],[\"sprockets\",\"2.2.1\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.19\",\"dependencies\":[[\"activesupport\",\"=3.0.19\"],[\"activemodel\",\"=3.0.19\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.5\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.1.10\",\"dependencies\":[[\"activesupport\",\"=3.1.10\"],[\"activemodel\",\"=3.1.10\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"rack\",\"1.3.6\"],[\"rack-test\",\"0.6.1\"],[\"rack-mount\",\"0.8.2\"],[\"sprockets\",\"2.0.4\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.15\",\"dependencies\":[[\"activesupport\",\"=2.3.15\"],[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.16\",\"dependencies\":[[\"activesupport\",\"=2.3.16\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.0.20\",\"dependencies\":[[\"activesupport\",\"=3.0.20\"],[\"activemodel\",\"=3.0.20\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"],[\"rack\",\"1.2.5\"],[\"rack-test\",\"0.5.7\"],[\"rack-mount\",\"0.6.14\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.17\",\"dependencies\":[[\"activesupport\",\"=2.3.17\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.12\",\"dependencies\":[[\"activesupport\",\"=3.2.12\"],[\"activemodel\",\"=3.2.12\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.5\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.4\"],[\"sprockets\",\"2.2.1\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.1.11\",\"dependencies\":[[\"activesupport\",\"=3.1.11\"],[\"activemodel\",\"=3.1.11\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"rack\",\"1.3.6\"],[\"rack-test\",\"0.6.1\"],[\"rack-mount\",\"0.8.2\"],[\"sprockets\",\"2.0.4\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"2.3.18\",\"dependencies\":[[\"activesupport\",\"=2.3.18\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.1.12\",\"dependencies\":[[\"activesupport\",\"=3.1.12\"],[\"activemodel\",\"=3.1.12\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"rack\",\"1.3.6\"],[\"rack-test\",\"0.6.1\"],[\"rack-mount\",\"0.8.2\"],[\"sprockets\",\"2.0.4\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.13\",\"dependencies\":[[\"activesupport\",\"=3.2.13\"],[\"activemodel\",\"=3.2.13\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.5\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.4\"],[\"sprockets\",\"2.2.1\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"4.0.0\",\"dependencies\":[[\"activesupport\",\"=4.0.0\"],[\"builder\",\"3.1.0\"],[\"rack\",\"1.5.2\"],[\"rack-test\",\"0.6.2\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack\",\"number\":\"3.2.14\",\"dependencies\":[[\"activesupport\",\"=3.2.14\"],[\"activemodel\",\"=3.2.14\"],[\"rack-cache\",\"1.2.0\"],[\"builder\",\"3.0.0\"],[\"rack\",\"1.4.5\"],[\"rack-test\",\"0.6.1\"],[\"journey\",\"1.0.4\"],[\"sprockets\",\"2.2.1\"],[\"erubis\",\"2.7.0\"]]},\n  {\"name\":\"actionpack-action-caching\",\"number\":\"1.1.1\",\"dependencies\":[[\"actionpack\",\"4.0.0\"]]},\n  {\"name\":\"actionpack-action-caching\",\"number\":\"1.1.0\",\"dependencies\":[[\"actionpack\",\"4.0.0\"]]},\n  {\"name\":\"actionpack-action-caching\",\"number\":\"1.0.0\",\"dependencies\":[[\"actionpack\",\"4.0.0\"]]},\n  {\"name\":\"actionpack-page-caching\",\"number\":\"1.0.2\",\"dependencies\":[[\"actionpack\",\"4.0.0\"]]},\n  {\"name\":\"actionpack-page-caching\",\"number\":\"1.0.1\",\"dependencies\":[[\"actionpack\",\"4.0.0\"]]},\n  {\"name\":\"actionpack-page-caching\",\"number\":\"1.0.0\",\"dependencies\":[[\"actionpack\",\"4.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"4.0.4\",\"dependencies\":[[\"builder\",\"3.1.0\"],[\"activesupport\",\"=4.0.4\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.17\",\"dependencies\":[[\"builder\",\"3.0.0\"],[\"activesupport\",\"=3.2.17\"]]},\n  {\"name\":\"activemodel\",\"number\":\"4.0.3\",\"dependencies\":[[\"builder\",\"3.1.0\"],[\"activesupport\",\"=4.0.3\"]]},\n  {\"name\":\"activemodel\",\"number\":\"4.0.2\",\"dependencies\":[[\"builder\",\"3.1.0\"],[\"activesupport\",\"=4.0.2\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.16\",\"dependencies\":[[\"builder\",\"3.0.0\"],[\"activesupport\",\"=3.2.16\"]]},\n  {\"name\":\"activemodel\",\"number\":\"4.0.1\",\"dependencies\":[[\"builder\",\"3.1.0\"],[\"activesupport\",\"=4.0.1\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.15\",\"dependencies\":[[\"builder\",\"3.0.0\"],[\"activesupport\",\"=3.2.15\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.2\",\"dependencies\":[[\"activesupport\",\"=3.0.2\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.4.1\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.7\",\"dependencies\":[[\"activesupport\",\"=3.2.7\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.3\",\"dependencies\":[[\"activesupport\",\"=3.0.3\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.4.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.15\",\"dependencies\":[[\"activesupport\",\"=3.0.15\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.1.1\",\"dependencies\":[[\"activesupport\",\"=3.1.1\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.6\",\"dependencies\":[[\"activesupport\",\"=3.0.6\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.4\",\"dependencies\":[[\"activesupport\",\"=3.2.4\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.5\",\"dependencies\":[[\"activesupport\",\"=3.2.5\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.11\",\"dependencies\":[[\"activesupport\",\"=3.0.11\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.9\",\"dependencies\":[[\"activesupport\",\"=3.0.9\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.5\",\"dependencies\":[[\"activesupport\",\"=3.0.5\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.4.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.7\",\"dependencies\":[[\"activesupport\",\"=3.0.7\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.0\",\"dependencies\":[[\"activesupport\",\"=3.0.0\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.4.1\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.10\",\"dependencies\":[[\"activesupport\",\"=3.0.10\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.1\",\"dependencies\":[[\"activesupport\",\"=3.0.1\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.4.1\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.8\",\"dependencies\":[[\"activesupport\",\"=3.0.8\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.1.2\",\"dependencies\":[[\"activesupport\",\"=3.1.2\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.1\",\"dependencies\":[[\"activesupport\",\"=3.2.1\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.1.5\",\"dependencies\":[[\"activesupport\",\"=3.1.5\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.2\",\"dependencies\":[[\"activesupport\",\"=3.2.2\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.14\",\"dependencies\":[[\"activesupport\",\"=3.0.14\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.16\",\"dependencies\":[[\"activesupport\",\"=3.0.16\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.3\",\"dependencies\":[[\"activesupport\",\"=3.2.3\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.1.6\",\"dependencies\":[[\"activesupport\",\"=3.1.6\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.1.0\",\"dependencies\":[[\"activesupport\",\"=3.1.0\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"],[\"bcrypt-ruby\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.0\",\"dependencies\":[[\"activesupport\",\"=3.2.0\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.1.4\",\"dependencies\":[[\"activesupport\",\"=3.1.4\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.17\",\"dependencies\":[[\"activesupport\",\"=3.0.17\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.1.7\",\"dependencies\":[[\"activesupport\",\"=3.1.7\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.1.8\",\"dependencies\":[[\"activesupport\",\"=3.1.8\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.6\",\"dependencies\":[[\"activesupport\",\"=3.2.6\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.8\",\"dependencies\":[[\"activesupport\",\"=3.2.8\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.4\",\"dependencies\":[[\"activesupport\",\"=3.0.4\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.4.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.12\",\"dependencies\":[[\"activesupport\",\"=3.0.12\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.13\",\"dependencies\":[[\"activesupport\",\"=3.0.13\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.1.3\",\"dependencies\":[[\"activesupport\",\"=3.1.3\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.9\",\"dependencies\":[[\"activesupport\",\"=3.2.9\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.10\",\"dependencies\":[[\"activesupport\",\"=3.2.10\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.18\",\"dependencies\":[[\"activesupport\",\"=3.0.18\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.1.9\",\"dependencies\":[[\"activesupport\",\"=3.1.9\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.1.10\",\"dependencies\":[[\"activesupport\",\"=3.1.10\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.19\",\"dependencies\":[[\"activesupport\",\"=3.0.19\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.11\",\"dependencies\":[[\"activesupport\",\"=3.2.11\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.0.20\",\"dependencies\":[[\"activesupport\",\"=3.0.20\"],[\"builder\",\"2.1.2 || 3.0.0\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.1.11\",\"dependencies\":[[\"activesupport\",\"=3.1.11\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.12\",\"dependencies\":[[\"activesupport\",\"=3.2.12\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.1.12\",\"dependencies\":[[\"activesupport\",\"=3.1.12\"],[\"builder\",\"3.0.0\"],[\"i18n\",\"0.6.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.13\",\"dependencies\":[[\"activesupport\",\"=3.2.13\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"4.0.0\",\"dependencies\":[[\"activesupport\",\"=4.0.0\"],[\"builder\",\"3.1.0\"]]},\n  {\"name\":\"activemodel\",\"number\":\"3.2.14\",\"dependencies\":[[\"activesupport\",\"=3.2.14\"],[\"builder\",\"3.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"4.0.4\",\"dependencies\":[[\"activerecord-deprecated-finders\",\"1.0.2\"],[\"arel\",\"4.0.0 || 5.0.0\"],[\"activemodel\",\"=4.0.4\"],[\"activesupport\",\"=4.0.4\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.17\",\"dependencies\":[[\"tzinfo\",\"0.3.29 || 1.0.0\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"activemodel\",\"=3.2.17\"],[\"activesupport\",\"=3.2.17\"]]},\n  {\"name\":\"activerecord\",\"number\":\"4.0.3\",\"dependencies\":[[\"activerecord-deprecated-finders\",\"1.0.2\"],[\"arel\",\"4.0.0 || 5.0.0\"],[\"activemodel\",\"=4.0.3\"],[\"activesupport\",\"=4.0.3\"]]},\n  {\"name\":\"activerecord\",\"number\":\"4.0.2\",\"dependencies\":[[\"activerecord-deprecated-finders\",\"1.0.2\"],[\"arel\",\"4.0.0 || 5.0.0\"],[\"activemodel\",\"=4.0.2\"],[\"activesupport\",\"=4.0.2\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.16\",\"dependencies\":[[\"tzinfo\",\"0.3.29 || 1.0.0\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"activemodel\",\"=3.2.16\"],[\"activesupport\",\"=3.2.16\"]]},\n  {\"name\":\"activerecord\",\"number\":\"4.0.1\",\"dependencies\":[[\"activerecord-deprecated-finders\",\"1.0.2\"],[\"arel\",\"4.0.0 || 5.0.0\"],[\"activemodel\",\"=4.0.1\"],[\"activesupport\",\"=4.0.1\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.15\",\"dependencies\":[[\"tzinfo\",\"0.3.29 || 1.0.0\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"activemodel\",\"=3.2.15\"],[\"activesupport\",\"=3.2.15\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.1\",\"dependencies\":[[\"activesupport\",\"=3.0.1\"],[\"activemodel\",\"=3.0.1\"],[\"arel\",\"1.0.0 || 2.0.0 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.7\",\"dependencies\":[[\"activesupport\",\"=3.2.7\"],[\"activemodel\",\"=3.2.7\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.1.7\",\"dependencies\":[[\"activesupport\",\"=3.1.7\"],[\"activemodel\",\"=3.1.7\"],[\"arel\",\"2.2.3 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.14.2\",\"dependencies\":[[\"activesupport\",\"=1.3.1\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.0.4\",\"dependencies\":[[\"activesupport\",\"=2.0.4\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.2.3\",\"dependencies\":[[\"activesupport\",\"=2.2.3\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"activerecord\",\"number\":\"1.14.1\",\"dependencies\":[[\"activesupport\",\"=1.3.1\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.6\",\"dependencies\":[[\"activesupport\",\"=3.2.6\"],[\"activemodel\",\"=3.2.6\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.5\",\"dependencies\":[[\"activesupport\",\"=2.3.5\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.15.1\",\"dependencies\":[[\"activesupport\",\"=1.4.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.11\",\"dependencies\":[[\"activesupport\",\"=3.0.11\"],[\"activemodel\",\"=3.0.11\"],[\"arel\",\"2.0.10 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.5\",\"dependencies\":[[\"activesupport\",\"=3.0.5\"],[\"activemodel\",\"=3.0.5\"],[\"arel\",\"2.0.2 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.1.1\",\"dependencies\":[[\"activesupport\",\"=3.1.1\"],[\"activemodel\",\"=3.1.1\"],[\"arel\",\"2.2.1 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.1.3\",\"dependencies\":[[\"activesupport\",\"=3.1.3\"],[\"activemodel\",\"=3.1.3\"],[\"arel\",\"2.2.1 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.15.4\",\"dependencies\":[[\"activesupport\",\"=1.4.3\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.14\",\"dependencies\":[[\"activesupport\",\"=2.3.14\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.10.0\",\"dependencies\":[[\"activesupport\",\"=1.0.4\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.0\",\"dependencies\":[[\"activesupport\",\"=3.0.0\"],[\"activemodel\",\"=3.0.0\"],[\"arel\",\"1.0.0 || 2.0.0 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.8.0\",\"dependencies\":[[\"activesupport\",\"=1.0.1\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.13.2\",\"dependencies\":[[\"activesupport\",\"=1.2.5\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.3\",\"dependencies\":[[\"activesupport\",\"=3.2.3\"],[\"activemodel\",\"=3.2.3\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.15.0\",\"dependencies\":[[\"activesupport\",\"=1.4.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"activerecord\",\"number\":\"2.1.2\",\"dependencies\":[[\"activesupport\",\"=2.1.2\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.9.1\",\"dependencies\":[[\"activesupport\",\"=1.0.3\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.2\",\"dependencies\":[[\"activesupport\",\"=2.3.2\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.11\",\"dependencies\":[[\"activesupport\",\"=2.3.11\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.2\",\"dependencies\":[[\"activesupport\",\"=3.0.2\"],[\"activemodel\",\"=3.0.2\"],[\"arel\",\"2.0.2 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.11.1\",\"dependencies\":[[\"activesupport\",\"=1.1.1\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.12\",\"dependencies\":[[\"activesupport\",\"=3.0.12\"],[\"activemodel\",\"=3.0.12\"],[\"arel\",\"2.0.10 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.2.2\",\"dependencies\":[[\"activesupport\",\"=2.2.2\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.11.0\",\"dependencies\":[[\"activesupport\",\"=1.1.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.1.2\",\"dependencies\":[[\"activesupport\",\"=3.1.2\"],[\"activemodel\",\"=3.1.2\"],[\"arel\",\"2.2.1 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.0\",\"dependencies\":[[\"activesupport\",\"=3.2.0\"],[\"activemodel\",\"=3.2.0\"],[\"arel\",\"3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.4\",\"dependencies\":[[\"activesupport\",\"=2.3.4\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.9.0\",\"dependencies\":[[\"activesupport\",\"=1.0.2\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.14.3\",\"dependencies\":[[\"activesupport\",\"=1.3.1\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.13.1\",\"dependencies\":[[\"activesupport\",\"=1.2.4\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"activerecord\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"activerecord\",\"number\":\"1.15.2\",\"dependencies\":[[\"activesupport\",\"=1.4.1\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.8\",\"dependencies\":[[\"activesupport\",\"=3.0.8\"],[\"activemodel\",\"=3.0.8\"],[\"arel\",\"2.0.10 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.10\",\"dependencies\":[[\"activesupport\",\"=2.3.10\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"activerecord\",\"number\":\"1.15.5\",\"dependencies\":[[\"activesupport\",\"=1.4.4\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.13.0\",\"dependencies\":[[\"activesupport\",\"=1.2.3\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.10.1\",\"dependencies\":[[\"activesupport\",\"=1.0.4\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.15.6\",\"dependencies\":[[\"activesupport\",\"=1.4.4\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.7.0\",\"dependencies\":[[\"activesupport\",\"=1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.6\",\"dependencies\":[[\"activesupport\",\"=3.0.6\"],[\"activemodel\",\"=3.0.6\"],[\"arel\",\"2.0.2 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.3\",\"dependencies\":[[\"activesupport\",\"=3.0.3\"],[\"activemodel\",\"=3.0.3\"],[\"arel\",\"2.0.2 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.7\",\"dependencies\":[[\"activesupport\",\"=2.3.7\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.0.2\",\"dependencies\":[[\"activesupport\",\"=2.0.2\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.1.4\",\"dependencies\":[[\"activesupport\",\"=3.1.4\"],[\"activemodel\",\"=3.1.4\"],[\"arel\",\"2.2.3 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.1.5\",\"dependencies\":[[\"activesupport\",\"=3.1.5\"],[\"activemodel\",\"=3.1.5\"],[\"arel\",\"2.2.3 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.3\",\"dependencies\":[[\"activesupport\",\"=2.3.3\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.1.0\",\"dependencies\":[[\"activesupport\",\"=2.1.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.0.5\",\"dependencies\":[[\"activesupport\",\"=2.0.5\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.15.3\",\"dependencies\":[[\"activesupport\",\"=1.4.2\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.9\",\"dependencies\":[[\"activesupport\",\"=3.0.9\"],[\"activemodel\",\"=3.0.9\"],[\"arel\",\"2.0.10 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.10\",\"dependencies\":[[\"activesupport\",\"=3.0.10\"],[\"activemodel\",\"=3.0.10\"],[\"arel\",\"2.0.10 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.6\",\"dependencies\":[[\"activesupport\",\"=2.3.6\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.12.2\",\"dependencies\":[[\"activesupport\",\"=1.2.2\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.12.1\",\"dependencies\":[[\"activesupport\",\"=1.2.1\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.12\",\"dependencies\":[[\"activesupport\",\"=2.3.12\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.14.4\",\"dependencies\":[[\"activesupport\",\"=1.3.1\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.13\",\"dependencies\":[[\"activesupport\",\"=3.0.13\"],[\"activemodel\",\"=3.0.13\"],[\"arel\",\"2.0.10 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.14\",\"dependencies\":[[\"activesupport\",\"=3.0.14\"],[\"activemodel\",\"=3.0.14\"],[\"arel\",\"2.0.10 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.1.6\",\"dependencies\":[[\"activesupport\",\"=3.1.6\"],[\"activemodel\",\"=3.1.6\"],[\"arel\",\"2.2.3 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.15\",\"dependencies\":[[\"activesupport\",\"=3.0.15\"],[\"activemodel\",\"=3.0.15\"],[\"arel\",\"2.0.10 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.5\",\"dependencies\":[[\"activesupport\",\"=3.2.5\"],[\"activemodel\",\"=3.2.5\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.1.0\",\"dependencies\":[[\"activesupport\",\"=3.1.0\"],[\"activemodel\",\"=3.1.0\"],[\"arel\",\"2.2.1 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.16\",\"dependencies\":[[\"activesupport\",\"=3.0.16\"],[\"activemodel\",\"=3.0.16\"],[\"arel\",\"2.0.10 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.17\",\"dependencies\":[[\"activesupport\",\"=3.0.17\"],[\"activemodel\",\"=3.0.17\"],[\"arel\",\"2.0.10 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.1.8\",\"dependencies\":[[\"activesupport\",\"=3.1.8\"],[\"activemodel\",\"=3.1.8\"],[\"arel\",\"2.2.3 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.8\",\"dependencies\":[[\"activesupport\",\"=3.2.8\"],[\"activemodel\",\"=3.2.8\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.7\",\"dependencies\":[[\"activesupport\",\"=3.0.7\"],[\"activemodel\",\"=3.0.7\"],[\"arel\",\"2.0.2 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.1\",\"dependencies\":[[\"activesupport\",\"=3.2.1\"],[\"activemodel\",\"=3.2.1\"],[\"arel\",\"3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.2\",\"dependencies\":[[\"activesupport\",\"=3.2.2\"],[\"activemodel\",\"=3.2.2\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.0.1\",\"dependencies\":[[\"activesupport\",\"=2.0.1\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.9\",\"dependencies\":[[\"activesupport\",\"=2.3.9\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.4\",\"dependencies\":[[\"activesupport\",\"=3.2.4\"],[\"activemodel\",\"=3.2.4\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.14.0\",\"dependencies\":[[\"activesupport\",\"=1.3.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.4\",\"dependencies\":[[\"activesupport\",\"=3.0.4\"],[\"activemodel\",\"=3.0.4\"],[\"arel\",\"2.0.2 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.1.1\",\"dependencies\":[[\"activesupport\",\"=2.1.1\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.0.0\",\"dependencies\":[[\"activesupport\",\"=2.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.8\",\"dependencies\":[[\"activesupport\",\"=2.3.8\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.9\",\"dependencies\":[[\"activesupport\",\"=3.2.9\"],[\"activemodel\",\"=3.2.9\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.18\",\"dependencies\":[[\"activesupport\",\"=3.0.18\"],[\"activemodel\",\"=3.0.18\"],[\"arel\",\"2.0.10 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.10\",\"dependencies\":[[\"activesupport\",\"=3.2.10\"],[\"activemodel\",\"=3.2.10\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.1.9\",\"dependencies\":[[\"activesupport\",\"=3.1.9\"],[\"activemodel\",\"=3.1.9\"],[\"arel\",\"2.2.3 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.15\",\"dependencies\":[[\"activesupport\",\"=2.3.15\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.11\",\"dependencies\":[[\"activesupport\",\"=3.2.11\"],[\"activemodel\",\"=3.2.11\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.19\",\"dependencies\":[[\"activesupport\",\"=3.0.19\"],[\"activemodel\",\"=3.0.19\"],[\"arel\",\"2.0.10 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.1.10\",\"dependencies\":[[\"activesupport\",\"=3.1.10\"],[\"activemodel\",\"=3.1.10\"],[\"arel\",\"2.2.3 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.0.20\",\"dependencies\":[[\"activesupport\",\"=3.0.20\"],[\"activemodel\",\"=3.0.20\"],[\"arel\",\"2.0.10 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.23 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.16\",\"dependencies\":[[\"activesupport\",\"=2.3.16\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.17\",\"dependencies\":[[\"activesupport\",\"=2.3.17\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.1.11\",\"dependencies\":[[\"activesupport\",\"=3.1.11\"],[\"activemodel\",\"=3.1.11\"],[\"arel\",\"2.2.3 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.12\",\"dependencies\":[[\"activesupport\",\"=3.2.12\"],[\"activemodel\",\"=3.2.12\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"2.3.18\",\"dependencies\":[[\"activesupport\",\"=2.3.18\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.1.12\",\"dependencies\":[[\"activesupport\",\"=3.1.12\"],[\"activemodel\",\"=3.1.12\"],[\"arel\",\"2.2.3 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.13\",\"dependencies\":[[\"activesupport\",\"=3.2.13\"],[\"activemodel\",\"=3.2.13\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord\",\"number\":\"4.0.0\",\"dependencies\":[[\"activesupport\",\"=4.0.0\"],[\"activemodel\",\"=4.0.0\"],[\"arel\",\"4.0.0 || 5.0.0\"],[\"activerecord-deprecated-finders\",\"1.0.2\"]]},\n  {\"name\":\"activerecord\",\"number\":\"3.2.14\",\"dependencies\":[[\"activesupport\",\"=3.2.14\"],[\"activemodel\",\"=3.2.14\"],[\"arel\",\"3.0.2 || 4.0.0 || 5.0.0\"],[\"tzinfo\",\"0.3.29 || 1.0.0\"]]},\n  {\"name\":\"activerecord-deprecated-finders\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"activerecord-deprecated-finders\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"activerecord-deprecated-finders\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"activerecord-deprecated-finders\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"activerecord-deprecated-finders\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"activerecord-deprecated-finders\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"activerecord-deprecated-finders\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"4.0.4\",\"dependencies\":[[\"thread-safe\",\"0.1.0\"],[\"minitest\",\"4.2.0 || 5.0.0\"],[\"tzinfo\",\"0.3.37 || 1.0.0\"],[\"multi-json\",\"1.3.0\"],[\"i18n\",null]]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.17\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"i18n\",null]]},\n  {\"name\":\"activesupport\",\"number\":\"4.0.3\",\"dependencies\":[[\"thread-safe\",\"0.1.0\"],[\"minitest\",\"4.2.0 || 5.0.0\"],[\"tzinfo\",\"0.3.37 || 1.0.0\"],[\"multi-json\",\"1.3.0\"],[\"i18n\",null]]},\n  {\"name\":\"activesupport\",\"number\":\"4.0.2\",\"dependencies\":[[\"thread-safe\",\"0.1.0\"],[\"minitest\",\"4.2.0 || 5.0.0\"],[\"tzinfo\",\"0.3.37 || 1.0.0\"],[\"multi-json\",\"1.3.0\"],[\"i18n\",null]]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.16\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"i18n\",null]]},\n  {\"name\":\"activesupport\",\"number\":\"4.0.1\",\"dependencies\":[[\"thread-safe\",\"0.1.0\"],[\"minitest\",\"4.2.0 || 5.0.0\"],[\"tzinfo\",\"0.3.37 || 1.0.0\"],[\"multi-json\",\"1.3.0\"],[\"i18n\",null]]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.15\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"i18n\",null]]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.10\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.7\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.4.1\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.2.5\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.1.7\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.7\",\"dependencies\":[[\"i18n\",\"0.6.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"1.2.3\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.2\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.9\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.4.3\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.1.2\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.14\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.12\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.3\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.2.2\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.9\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.2\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.5\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.6\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.2.3\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.11\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.4\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.12\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.3\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.1.0\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"1.4.4\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.2\",\"dependencies\":[[\"i18n\",\"0.6.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.1\",\"dependencies\":[[\"i18n\",\"0.6.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.1\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.8\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.13\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.1.2\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.8\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.6\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.5\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.2.4\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.7\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.14\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.4\",\"dependencies\":[[\"i18n\",\"0.6.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.0\",\"dependencies\":[[\"i18n\",\"0.6.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.15\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.16\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.1.1\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.17\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.1.3\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.1.6\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.1.5\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.1.8\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.5\",\"dependencies\":[[\"i18n\",\"0.6.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.8\",\"dependencies\":[[\"i18n\",\"0.6.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.10\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.4.2\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.6\",\"dependencies\":[[\"i18n\",\"0.6.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.4\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.11\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.1.4\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.3\",\"dependencies\":[[\"i18n\",\"0.6.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"2.0.5\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.9\",\"dependencies\":[[\"i18n\",\"0.6.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.18\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.1.9\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.10\",\"dependencies\":[[\"i18n\",\"0.6.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.1.10\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.11\",\"dependencies\":[[\"i18n\",\"0.6.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.15\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.19\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.16\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.0.20\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.1.11\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.17\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.12\",\"dependencies\":[[\"i18n\",\"0.6.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"2.3.18\",\"dependencies\":[]},\n  {\"name\":\"activesupport\",\"number\":\"3.1.12\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.13\",\"dependencies\":[[\"i18n\",\"=0.6.1\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"4.0.0\",\"dependencies\":[[\"i18n\",null],[\"multi-json\",\"1.3.0\"],[\"tzinfo\",\"0.3.37 || 1.0.0\"],[\"minitest\",\"4.2.0 || 5.0.0\"],[\"thread-safe\",\"0.1.0\"]]},\n  {\"name\":\"activesupport\",\"number\":\"3.2.14\",\"dependencies\":[[\"i18n\",null],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"3.0.2\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"3.0.1\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"3.0.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.1.0\",\"dependencies\":[[\"rails\",null]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.1.5\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.11\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.1.8\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.3.1\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.2.1\",\"dependencies\":[[\"rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.2.2\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.0.5\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.1.4\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.3.2\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.12\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.19\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.2.0\",\"dependencies\":[[\"rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.7\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.14\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.1.6\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.8\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.1.7\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.13\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.6\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"0.0.0\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.1.9\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.10\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.16\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.9\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.15\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.18\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"1.0.17\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.0.6\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.1.1\",\"dependencies\":[[\"rails\",null]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.3.3\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.3.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.4.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"acts-as-taggable-on\",\"number\":\"2.4.1\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"addressable\",\"number\":\"2.3.6\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"1.0.1\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0\"]]},\n  {\"name\":\"addressable\",\"number\":\"2.2.3\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.3.2\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.2.5\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"0.1.1\",\"dependencies\":[[\"rake\",null],[\"rspec\",null]]},\n  {\"name\":\"addressable\",\"number\":\"0.1.0\",\"dependencies\":[[\"rake\",null],[\"rspec\",null]]},\n  {\"name\":\"addressable\",\"number\":\"2.0.2\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0\"],[\"launchy\",null]]},\n  {\"name\":\"addressable\",\"number\":\"1.0.2\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0\"]]},\n  {\"name\":\"addressable\",\"number\":\"1.0.0\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0\"]]},\n  {\"name\":\"addressable\",\"number\":\"2.1.0\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0\"],[\"launchy\",null]]},\n  {\"name\":\"addressable\",\"number\":\"2.0.0\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0\"],[\"launchy\",null]]},\n  {\"name\":\"addressable\",\"number\":\"2.2.4\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.2.7\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.2.8\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.2.2\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"1.0.3\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0\"]]},\n  {\"name\":\"addressable\",\"number\":\"2.2.6\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"0.1.2\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0\"]]},\n  {\"name\":\"addressable\",\"number\":\"2.0.1\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0\"],[\"launchy\",null]]},\n  {\"name\":\"addressable\",\"number\":\"1.0.4\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0\"]]},\n  {\"name\":\"addressable\",\"number\":\"2.1.2\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.2.1\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.3.3\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.3.4\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.3.5\",\"dependencies\":[]},\n  {\"name\":\"annotate\",\"number\":\"2.6.2\",\"dependencies\":[[\"activerecord\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"rake\",null]]},\n  {\"name\":\"annotate\",\"number\":\"2.6.1\",\"dependencies\":[[\"activerecord\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"rake\",null]]},\n  {\"name\":\"annotate\",\"number\":\"2.6.0\",\"dependencies\":[[\"activerecord\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"rake\",null]]},\n  {\"name\":\"annotate\",\"number\":\"2.4.0\",\"dependencies\":[]},\n  {\"name\":\"annotate\",\"number\":\"2.5.0\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"arel\",\"number\":\"4.0.2\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"5.0.0\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"3.0.3\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"4.0.1\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"2.0.9\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"0.3.2\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"arel\",\"number\":\"2.0.5\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"2.0.10\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"0.3.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"arel\",\"number\":\"2.1.4\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"3.0.1\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"2.0.7\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"2.1.3\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"0.4.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"arel\",\"number\":\"0.3.3\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"arel\",\"number\":\"2.2.3\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"1.0.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"arel\",\"number\":\"2.0.8\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"1.0.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"arel\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"2.1.2\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"0.3.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"arel\",\"number\":\"2.0.6\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"0.2.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"arel\",\"number\":\"0.2.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"arel\",\"number\":\"0.1.2\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"arel\",\"number\":\"2.2.1\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"2.2.2\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"3.0.2\",\"dependencies\":[]},\n  {\"name\":\"arel\",\"number\":\"4.0.0\",\"dependencies\":[]},\n  {\"name\":\"asciidoctor\",\"number\":\"0.0.4\",\"dependencies\":[[\"json\",null],[\"tilt\",null]]},\n  {\"name\":\"asciidoctor\",\"number\":\"0.0.2\",\"dependencies\":[[\"json\",null],[\"tilt\",null]]},\n  {\"name\":\"asciidoctor\",\"number\":\"0.0.3\",\"dependencies\":[[\"json\",null],[\"tilt\",null]]},\n  {\"name\":\"asciidoctor\",\"number\":\"0.0.1\",\"dependencies\":[[\"json\",null],[\"nokogiri\",null]]},\n  {\"name\":\"asciidoctor\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"asciidoctor\",\"number\":\"0.0.5\",\"dependencies\":[[\"json\",null],[\"tilt\",null]]},\n  {\"name\":\"asciidoctor\",\"number\":\"0.0.7\",\"dependencies\":[[\"json\",null],[\"tilt\",null]]},\n  {\"name\":\"asciidoctor\",\"number\":\"0.0.6\",\"dependencies\":[[\"json\",null],[\"tilt\",null]]},\n  {\"name\":\"asciidoctor\",\"number\":\"0.0.9\",\"dependencies\":[]},\n  {\"name\":\"asciidoctor\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"asciidoctor\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"asciidoctor\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"asciidoctor\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.16\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.15\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.14\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"0.0.9\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"0.0.7\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"0.0.5\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"0.0.8\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"0.0.4\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"0.0.6\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.4\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.5\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.6\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.7\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.8\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.9\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.10\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.11\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.12\",\"dependencies\":[]},\n  {\"name\":\"atomic\",\"number\":\"1.1.13\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"awesome-print\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"axiom-types\",\"number\":\"0.1.0\",\"dependencies\":[[\"thread-safe\",\"0.1.3\"],[\"ice-nine\",\"0.11.0\"],[\"descendants-tracker\",\"0.0.3\"]]},\n  {\"name\":\"axiom-types\",\"number\":\"0.0.5\",\"dependencies\":[[\"ice-nine\",\"0.9.0\"],[\"descendants-tracker\",\"0.0.1\"]]},\n  {\"name\":\"axiom-types\",\"number\":\"0.0.4\",\"dependencies\":[[\"ice-nine\",\"0.9.0\"],[\"descendants-tracker\",\"0.0.1\"]]},\n  {\"name\":\"axiom-types\",\"number\":\"0.0.1\",\"dependencies\":[[\"backports\",\"3.1.1\"],[\"descendants-tracker\",\"0.0.1\"],[\"ice-nine\",\"0.7.0\"]]},\n  {\"name\":\"axiom-types\",\"number\":\"0.0.2\",\"dependencies\":[[\"backports\",\"3.3.2\"],[\"descendants-tracker\",\"0.0.1\"],[\"ice-nine\",\"0.8.0\"]]},\n  {\"name\":\"axiom-types\",\"number\":\"0.0.3\",\"dependencies\":[[\"descendants-tracker\",\"0.0.1\"],[\"ice-nine\",\"0.9.0\"]]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.1.5\",\"dependencies\":[[\"bcrypt\",\"3.1.3\"]]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.1.4\",\"dependencies\":[[\"bcrypt\",\"3.1.3\"]]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.1.3\",\"dependencies\":[[\"bcrypt\",\"3.1.3\"]]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.1.2\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.0.5\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.1.4\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.0.1\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.1.3\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.1.0\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.1.1\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.1.2\",\"dependencies\":[]},\n  {\"name\":\"better-errors\",\"number\":\"1.1.0\",\"dependencies\":[[\"coderay\",\"1.0.0\"],[\"erubis\",\"2.6.6\"]]},\n  {\"name\":\"better-errors\",\"number\":\"1.0.0\",\"dependencies\":[[\"erubis\",\"2.6.6\"],[\"coderay\",\"1.0.0\"]]},\n  {\"name\":\"better-errors\",\"number\":\"1.0.1\",\"dependencies\":[[\"erubis\",\"2.6.6\"],[\"coderay\",\"1.0.0\"]]},\n  {\"name\":\"better-errors\",\"number\":\"0.0.1\",\"dependencies\":[[\"erubis\",null],[\"coderay\",null]]},\n  {\"name\":\"better-errors\",\"number\":\"0.0.2\",\"dependencies\":[[\"erubis\",null],[\"coderay\",null]]},\n  {\"name\":\"better-errors\",\"number\":\"0.0.3\",\"dependencies\":[[\"erubis\",null],[\"coderay\",null]]},\n  {\"name\":\"better-errors\",\"number\":\"0.0.4\",\"dependencies\":[[\"erubis\",null],[\"coderay\",null]]},\n  {\"name\":\"better-errors\",\"number\":\"0.0.5\",\"dependencies\":[[\"erubis\",null],[\"coderay\",null]]},\n  {\"name\":\"better-errors\",\"number\":\"0.0.6\",\"dependencies\":[[\"erubis\",null],[\"coderay\",null]]},\n  {\"name\":\"better-errors\",\"number\":\"0.0.7\",\"dependencies\":[[\"erubis\",null],[\"coderay\",null]]},\n  {\"name\":\"better-errors\",\"number\":\"0.0.8\",\"dependencies\":[[\"erubis\",null],[\"coderay\",null]]},\n  {\"name\":\"better-errors\",\"number\":\"0.1.0\",\"dependencies\":[[\"erubis\",\"2.7.0\"],[\"coderay\",\"1.0.0\"]]},\n  {\"name\":\"better-errors\",\"number\":\"0.1.1\",\"dependencies\":[[\"erubis\",\"2.7.0\"],[\"coderay\",\"1.0.0\"]]},\n  {\"name\":\"better-errors\",\"number\":\"0.2.0\",\"dependencies\":[[\"erubis\",\"2.7.0\"],[\"coderay\",\"1.0.0\"]]},\n  {\"name\":\"better-errors\",\"number\":\"0.3.0\",\"dependencies\":[[\"erubis\",\"2.7.0\"],[\"coderay\",\"1.0.0\"]]},\n  {\"name\":\"better-errors\",\"number\":\"0.3.2\",\"dependencies\":[[\"erubis\",\"2.7.0\"],[\"coderay\",\"1.0.0\"]]},\n  {\"name\":\"better-errors\",\"number\":\"0.5.0\",\"dependencies\":[[\"erubis\",\"2.6.6\"],[\"coderay\",\"1.0.0\"]]},\n  {\"name\":\"better-errors\",\"number\":\"0.6.0\",\"dependencies\":[[\"erubis\",\"2.6.6\"],[\"coderay\",\"1.0.0\"]]},\n  {\"name\":\"better-errors\",\"number\":\"0.7.0\",\"dependencies\":[[\"erubis\",\"2.6.6\"],[\"coderay\",\"1.0.0\"]]},\n  {\"name\":\"better-errors\",\"number\":\"0.7.2\",\"dependencies\":[[\"erubis\",\"2.6.6\"],[\"coderay\",\"1.0.0\"]]},\n  {\"name\":\"better-errors\",\"number\":\"0.8.0\",\"dependencies\":[[\"erubis\",\"2.6.6\"],[\"coderay\",\"1.0.0\"]]},\n  {\"name\":\"better-errors\",\"number\":\"0.9.0\",\"dependencies\":[[\"erubis\",\"2.6.6\"],[\"coderay\",\"1.0.0\"]]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.6.6\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.6.5\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.6.4\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.6.7\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.6.8\",\"dependencies\":[]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.7.1\",\"dependencies\":[[\"debug-inspector\",null]]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.7.0\",\"dependencies\":[[\"debug-inspector\",null]]},\n  {\"name\":\"binding-of-caller\",\"number\":\"0.7.2\",\"dependencies\":[[\"debug-inspector\",null]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"3.1.1\",\"dependencies\":[[\"sass\",\"3.2.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"3.1.0\",\"dependencies\":[[\"sass\",\"3.2.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"3.0.3\",\"dependencies\":[[\"sass\",\"3.2.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"3.0.2\",\"dependencies\":[[\"sass\",\"3.2.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"3.0.1\",\"dependencies\":[[\"sass\",\"3.2.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"3.0.0\",\"dependencies\":[[\"sass\",\"3.2.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"1.2.0\",\"dependencies\":[[\"sass-rails\",null]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"1.4.2\",\"dependencies\":[[\"sass-rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"1.4.1\",\"dependencies\":[[\"sass-rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"1.3.2\",\"dependencies\":[[\"sass-rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"1.3.0\",\"dependencies\":[[\"sass-rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"1.4.3\",\"dependencies\":[[\"sass-rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"1.4.0\",\"dependencies\":[[\"sass-rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"1.4.4\",\"dependencies\":[[\"sass-rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"1.2.1\",\"dependencies\":[[\"sass-rails\",null]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"1.3.1\",\"dependencies\":[[\"sass-rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"2.2.1\",\"dependencies\":[[\"sass\",\"3.2.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"2.2.2\",\"dependencies\":[[\"sass\",\"3.2.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"2.3.0\",\"dependencies\":[[\"sass\",\"3.2.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"2.3.1\",\"dependencies\":[[\"sass\",\"3.2.0\"]]},\n  {\"name\":\"bootstrap-sass\",\"number\":\"2.3.2\",\"dependencies\":[[\"sass\",\"3.2.0\"]]},\n  {\"name\":\"builder\",\"number\":\"3.1.3\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"2.1.2\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"3.0.4\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"1.2.4\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"3.0.1\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"3.0.3\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"3.1.4\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"3.1.1\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"3.1.0\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"1.2.3\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"3.0.2\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"3.1.2\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"3.2.0\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"3.2.1\",\"dependencies\":[]},\n  {\"name\":\"builder\",\"number\":\"3.2.2\",\"dependencies\":[]},\n  {\"name\":\"capybara\",\"number\":\"2.2.1\",\"dependencies\":[[\"xpath\",\"2.0.0\"],[\"rack-test\",null],[\"rack\",\"1.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"nokogiri\",\"1.3.3\"]]},\n  {\"name\":\"capybara\",\"number\":\"2.2.0\",\"dependencies\":[[\"xpath\",\"2.0.0\"],[\"rack-test\",null],[\"rack\",\"1.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"nokogiri\",\"1.3.3\"]]},\n  {\"name\":\"capybara\",\"number\":\"0.3.9\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"culerity\",null],[\"selenium-webdriver\",null],[\"rack\",\"1.0.0\"],[\"rack-test\",null]]},\n  {\"name\":\"capybara\",\"number\":\"0.4.0\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"culerity\",null],[\"celerity\",null],[\"selenium-webdriver\",null],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"xpath\",\"0.1.2 || 1.0.0 || 2.0.0\"]]},\n  {\"name\":\"capybara\",\"number\":\"0.3.5\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"culerity\",null],[\"selenium-webdriver\",null],[\"rack\",\"1.0.0\"],[\"rack-test\",null]]},\n  {\"name\":\"capybara\",\"number\":\"0.1.2\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"culerity\",null],[\"selenium-webdriver\",null],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"database-cleaner\",null]]},\n  {\"name\":\"capybara\",\"number\":\"0.3.7\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"culerity\",null],[\"selenium-webdriver\",null],[\"rack\",\"1.0.0\"],[\"rack-test\",null]]},\n  {\"name\":\"capybara\",\"number\":\"0.1.4\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"culerity\",null],[\"selenium-webdriver\",null],[\"rack\",\"1.0.0\"],[\"rack-test\",null]]},\n  {\"name\":\"capybara\",\"number\":\"0.2.0\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"culerity\",null],[\"selenium-webdriver\",null],[\"rack\",\"1.0.0\"],[\"rack-test\",null]]},\n  {\"name\":\"capybara\",\"number\":\"0.1.0\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"culerity\",null],[\"selenium-webdriver\",null],[\"rack\",\"1.0.0\"],[\"database-cleaner\",null]]},\n  {\"name\":\"capybara\",\"number\":\"0.1.3\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"culerity\",null],[\"selenium-webdriver\",null],[\"rack\",\"1.0.0\"],[\"rack-test\",null]]},\n  {\"name\":\"capybara\",\"number\":\"0.3.0\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"culerity\",null],[\"selenium-webdriver\",null],[\"rack\",\"1.0.0\"],[\"rack-test\",null]]},\n  {\"name\":\"capybara\",\"number\":\"0.3.6\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"culerity\",null],[\"selenium-webdriver\",null],[\"rack\",\"1.0.0\"],[\"rack-test\",null]]},\n  {\"name\":\"capybara\",\"number\":\"0.1.1\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"culerity\",null],[\"selenium-webdriver\",null],[\"rack\",\"1.0.0\"],[\"database-cleaner\",null]]},\n  {\"name\":\"capybara\",\"number\":\"1.1.1\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"selenium-webdriver\",\"2.0.0\"],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"xpath\",\"0.1.4 || 1.0.0 || 2.0.0\"]]},\n  {\"name\":\"capybara\",\"number\":\"0.3.8\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"culerity\",null],[\"selenium-webdriver\",null],[\"rack\",\"1.0.0\"],[\"rack-test\",null]]},\n  {\"name\":\"capybara\",\"number\":\"1.1.0\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"selenium-webdriver\",\"2.0.0\"],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"xpath\",\"0.1.4 || 1.0.0 || 2.0.0\"]]},\n  {\"name\":\"capybara\",\"number\":\"1.1.2\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"selenium-webdriver\",\"2.0.0\"],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"xpath\",\"0.1.4 || 1.0.0 || 2.0.0\"]]},\n  {\"name\":\"capybara\",\"number\":\"1.0.0\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"selenium-webdriver\",\"0.2.0\"],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"xpath\",\"0.1.4 || 1.0.0 || 2.0.0\"]]},\n  {\"name\":\"capybara\",\"number\":\"1.0.1\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"selenium-webdriver\",\"2.0.0\"],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"xpath\",\"0.1.4 || 1.0.0 || 2.0.0\"]]},\n  {\"name\":\"capybara\",\"number\":\"1.1.3\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"selenium-webdriver\",\"2.0.0\"],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"xpath\",\"0.1.4 || 1.0.0 || 2.0.0\"]]},\n  {\"name\":\"capybara\",\"number\":\"2.0.0\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"selenium-webdriver\",\"2.0.0\"],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"xpath\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"capybara\",\"number\":\"2.0.1\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"selenium-webdriver\",\"2.0.0\"],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"xpath\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"capybara\",\"number\":\"1.1.4\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"selenium-webdriver\",\"2.0.0\"],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"xpath\",\"0.1.4 || 1.0.0 || 2.0.0\"]]},\n  {\"name\":\"capybara\",\"number\":\"2.0.2\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"selenium-webdriver\",\"2.0.0\"],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"xpath\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"capybara\",\"number\":\"2.0.3\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"selenium-webdriver\",\"2.0.0\"],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"xpath\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"capybara\",\"number\":\"2.1.0\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"rack-test\",null],[\"xpath\",\"2.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.10.0\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"json\",\"1.7.0\"],[\"activemodel\",\"3.2.0 || 4.0.0\"],[\"activesupport\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.5.5\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.6.0\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"],[\"activemodel\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.6.1\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"],[\"activemodel\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.5.7\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.4.9\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.4.10\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.3.5\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.5.8\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.3.4\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.5.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.5.6\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.4.6\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.5.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.4.8\",\"dependencies\":[[\"activesupport\",\"2.3.8 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.2.4\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.4.7\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.2.3\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.5.3\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.4.4\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.5.2\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.5.4\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.4.5\",\"dependencies\":[]},\n  {\"name\":\"carrierwave\",\"number\":\"0.6.2\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"],[\"activemodel\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.7.0\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"],[\"activemodel\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.7.1\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"],[\"activemodel\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.8.0\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"],[\"activemodel\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"carrierwave\",\"number\":\"0.9.0\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"],[\"activemodel\",\"3.2.0 || 4.0.0\"],[\"json\",\"1.7.0\"]]},\n  {\"name\":\"celluloid\",\"number\":\"0.15.2\",\"dependencies\":[[\"timers\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"celluloid\",\"number\":\"0.7.2\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.0.1\",\"dependencies\":[[\"celluloid\",null]]},\n  {\"name\":\"celluloid\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.11.1\",\"dependencies\":[[\"timers\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"celluloid\",\"number\":\"0.12.0\",\"dependencies\":[[\"timers\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"celluloid\",\"number\":\"0.12.1\",\"dependencies\":[[\"timers\",\"1.0.0 || 2.0.0\"],[\"facter\",\"1.6.12\"]]},\n  {\"name\":\"celluloid\",\"number\":\"0.12.2\",\"dependencies\":[[\"timers\",\"1.0.0 || 2.0.0\"],[\"facter\",\"1.6.12\"]]},\n  {\"name\":\"celluloid\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.11.0\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"celluloid\",\"number\":\"0.12.3\",\"dependencies\":[[\"timers\",\"1.0.0 || 2.0.0\"],[\"facter\",\"1.6.12\"]]},\n  {\"name\":\"celluloid\",\"number\":\"0.15.1\",\"dependencies\":[[\"timers\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"celluloid\",\"number\":\"0.12.4\",\"dependencies\":[[\"timers\",\"1.0.0 || 2.0.0\"],[\"facter\",\"1.6.12\"]]},\n  {\"name\":\"celluloid\",\"number\":\"0.13.0\",\"dependencies\":[[\"timers\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"celluloid\",\"number\":\"0.14.0\",\"dependencies\":[[\"timers\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"celluloid\",\"number\":\"0.14.1\",\"dependencies\":[[\"timers\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"celluloid\",\"number\":\"0.15.0\",\"dependencies\":[[\"timers\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.6.4\",\"dependencies\":[]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.6.8\",\"dependencies\":[]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.6.5\",\"dependencies\":[]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.6.6\",\"dependencies\":[]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.6.7\",\"dependencies\":[]},\n  {\"name\":\"charlock-holmes\",\"number\":\"0.6.9\",\"dependencies\":[]},\n  {\"name\":\"cliver\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"cliver\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"cliver\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"cliver\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"cliver\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"cliver\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"cliver\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"cliver\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"cliver\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"cliver\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"cliver\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"cliver\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"code-analyzer\",\"number\":\"0.4.4\",\"dependencies\":[[\"sexp-processor\",null]]},\n  {\"name\":\"code-analyzer\",\"number\":\"0.4.3\",\"dependencies\":[[\"sexp-processor\",null]]},\n  {\"name\":\"code-analyzer\",\"number\":\"0.1.0\",\"dependencies\":[[\"sexp-processor\",null]]},\n  {\"name\":\"code-analyzer\",\"number\":\"0.1.1\",\"dependencies\":[[\"sexp-processor\",null]]},\n  {\"name\":\"code-analyzer\",\"number\":\"0.2.0\",\"dependencies\":[[\"sexp-processor\",null]]},\n  {\"name\":\"code-analyzer\",\"number\":\"0.3.0\",\"dependencies\":[[\"sexp-processor\",null]]},\n  {\"name\":\"code-analyzer\",\"number\":\"0.3.1\",\"dependencies\":[[\"sexp-processor\",null]]},\n  {\"name\":\"code-analyzer\",\"number\":\"0.3.2\",\"dependencies\":[[\"sexp-processor\",null]]},\n  {\"name\":\"code-analyzer\",\"number\":\"0.4.0\",\"dependencies\":[[\"sexp-processor\",null]]},\n  {\"name\":\"code-analyzer\",\"number\":\"0.4.2\",\"dependencies\":[[\"sexp-processor\",null]]},\n  {\"name\":\"code-analyzer\",\"number\":\"0.4.1\",\"dependencies\":[[\"sexp-processor\",null]]},\n  {\"name\":\"coderay\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"1.0.7\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"1.0.6\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.8.303\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.9.4\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.9.5\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.8.263\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.9.6\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.8.357\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.9.3\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.8.260\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"1.0.5\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.9.2\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.8.273\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.9.8\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.9.7\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.8.270\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"0.8.312\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"1.0.8\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"1.0.9\",\"dependencies\":[]},\n  {\"name\":\"coderay\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"coercible\",\"number\":\"1.0.0\",\"dependencies\":[[\"descendants-tracker\",\"0.0.1\"]]},\n  {\"name\":\"coercible\",\"number\":\"0.0.1\",\"dependencies\":[[\"backports\",\"2.6.0 || 3.0.0\"],[\"descendants-tracker\",\"0.0.1\"]]},\n  {\"name\":\"coercible\",\"number\":\"0.0.2\",\"dependencies\":[[\"backports\",\"2.8.0 || 3.0.0\"],[\"descendants-tracker\",\"0.0.1\"]]},\n  {\"name\":\"coercible\",\"number\":\"0.1.0\",\"dependencies\":[[\"backports\",\"2.8.0 || 3.0.0\"],[\"descendants-tracker\",\"0.0.1\"]]},\n  {\"name\":\"coercible\",\"number\":\"0.2.0\",\"dependencies\":[[\"backports\",\"3.0.0\"],[\"descendants-tracker\",\"0.0.1\"]]},\n  {\"name\":\"coffee-rails\",\"number\":\"4.0.1\",\"dependencies\":[[\"railties\",\"4.0.0\"],[\"coffee-script\",\"2.2.0\"]]},\n  {\"name\":\"coffee-rails\",\"number\":\"3.2.1\",\"dependencies\":[[\"coffee-script\",\"2.2.0\"],[\"railties\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"coffee-rails\",\"number\":\"3.2.0\",\"dependencies\":[[\"coffee-script\",\"2.2.0\"],[\"railties\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"coffee-rails\",\"number\":\"3.1.0\",\"dependencies\":[[\"coffee-script\",\"2.2.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"coffee-rails\",\"number\":\"3.1.1\",\"dependencies\":[[\"coffee-script\",\"2.2.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"coffee-rails\",\"number\":\"3.2.2\",\"dependencies\":[[\"coffee-script\",\"2.2.0\"],[\"railties\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"coffee-rails\",\"number\":\"4.0.0\",\"dependencies\":[[\"coffee-script\",\"2.2.0\"],[\"railties\",\"4.0.0\"]]},\n  {\"name\":\"coffee-script\",\"number\":\"2.1.1\",\"dependencies\":[[\"coffee-script-source\",null]]},\n  {\"name\":\"coffee-script\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"0.2.4\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"0.1.6\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"2.0.0\",\"dependencies\":[[\"coffee-script-source\",null]]},\n  {\"name\":\"coffee-script\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"0.2.6\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"0.2.3\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"0.2.5\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"2.1.3\",\"dependencies\":[[\"coffee-script-source\",null]]},\n  {\"name\":\"coffee-script\",\"number\":\"2.1.2\",\"dependencies\":[[\"coffee-script-source\",null]]},\n  {\"name\":\"coffee-script\",\"number\":\"2.2.0\",\"dependencies\":[[\"coffee-script-source\",null],[\"execjs\",null]]},\n  {\"name\":\"coffee-script\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"2.1.0\",\"dependencies\":[[\"coffee-script-source\",null]]},\n  {\"name\":\"coffee-script\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"coffee-script\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"0.9.6\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"0.9.5\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"0.9.4\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.3.3\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.6.1\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.6.2\",\"dependencies\":[]},\n  {\"name\":\"coffee-script-source\",\"number\":\"1.6.3\",\"dependencies\":[]},\n  {\"name\":\"colored\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"colored\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"colored\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"colorize\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"colorize\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"colorize\",\"number\":\"0.5.6\",\"dependencies\":[]},\n  {\"name\":\"colorize\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"colorize\",\"number\":\"0.5.7\",\"dependencies\":[]},\n  {\"name\":\"colorize\",\"number\":\"0.5.8\",\"dependencies\":[]},\n  {\"name\":\"colorize\",\"number\":\"0.5.5\",\"dependencies\":[[\"hoe\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"connection-pool\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"connection-pool\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"connection-pool\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"connection-pool\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"connection-pool\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"connection-pool\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"connection-pool\",\"number\":\"0.9.2\",\"dependencies\":[]},\n  {\"name\":\"connection-pool\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"connection-pool\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"connection-pool\",\"number\":\"0.9.3\",\"dependencies\":[]},\n  {\"name\":\"connection-pool\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"connection-pool\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"coveralls\",\"number\":\"0.7.0\",\"dependencies\":[[\"simplecov\",null],[\"thor\",null],[\"multi-json\",\"1.3.0\"],[\"term-ansicolor\",null],[\"rest-client\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.6.8\",\"dependencies\":[[\"rest-client\",null],[\"term-ansicolor\",null],[\"multi-json\",\"1.3.0\"],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.6.9\",\"dependencies\":[[\"rest-client\",null],[\"term-ansicolor\",null],[\"multi-json\",\"1.3.0\"],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.5.1\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"json\",null],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.5.2\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"json\",null],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.5.3\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"json\",null],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.5.4\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"json\",null],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.5.5\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"json\",null],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.5.6\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"json\",null],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.5.7\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"json\",null],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.5.8\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"json\",null],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.5.9\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"multi-json\",\"1.3.0\"],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.6.0\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"multi-json\",\"1.3.0\"],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.6.1\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"multi-json\",\"1.3.0\"],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.6.2\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"multi-json\",\"1.3.0\"],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.6.3\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"multi-json\",\"1.3.0\"],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.6.4\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"multi-json\",\"1.3.0\"],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.6.5\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"multi-json\",\"1.3.0\"],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.6.6\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"multi-json\",\"1.3.0\"],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"coveralls\",\"number\":\"0.6.7\",\"dependencies\":[[\"rest-client\",null],[\"colorize\",null],[\"multi-json\",\"1.3.0\"],[\"thor\",null],[\"simplecov\",null]]},\n  {\"name\":\"crack\",\"number\":\"0.4.2\",\"dependencies\":[[\"safe-yaml\",\"1.0.0\"]]},\n  {\"name\":\"crack\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"crack\",\"number\":\"0.1.8\",\"dependencies\":[]},\n  {\"name\":\"crack\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"crack\",\"number\":\"0.1.7\",\"dependencies\":[]},\n  {\"name\":\"crack\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"crack\",\"number\":\"0.1.6\",\"dependencies\":[]},\n  {\"name\":\"crack\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"crack\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"crack\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"crack\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"crack\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"crack\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"crack\",\"number\":\"0.4.0\",\"dependencies\":[[\"safe-yaml\",\"0.9.0 || 1.0.0\"]]},\n  {\"name\":\"crack\",\"number\":\"0.4.1\",\"dependencies\":[[\"safe-yaml\",\"0.9.0 || 1.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.4.3\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.4.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.4.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.4.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.13\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.12\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.11\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.10\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.9\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.8\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.7\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.6\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.5\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.4\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.0.5\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.9.4\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.0.3\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.9.6\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.9.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.9.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.1.3\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.1.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.7.5\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.1.7\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.0.4\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.0.9\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.0.8\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.0.7\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.0.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.0.6\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.1.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.1.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.1.8\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.1.4\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.1.5\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.1.6\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.7.4\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.8.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.9.5\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.9.7\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.10.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.10.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.10.3\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.10.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.0.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"0.0.10\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"2.8.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.0.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.0.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.0.3\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.0.4\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.3\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.0.5\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.0.6\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.0.8\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.1.3\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.1.4\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.1.6\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.1.9\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.1.10\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.2.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.2.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.2.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.2.3\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.2.4\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.2.7\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.2.8\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"d3-rails\",\"number\":\"3.3.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"daemons\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.0.10\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.0.6\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.0.5\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.1.8\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.0.7\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.0.8\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.1.6\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.1.5\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.0.9\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"0.4.4\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.1.4\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"1.1.9\",\"dependencies\":[]},\n  {\"name\":\"daemons\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.7.2\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.6.7\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.6.6\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.6.4\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.2.3\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.6.5\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"database-cleaner\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"debug-inspector\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"debug-inspector\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"default-value-for\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"default-value-for\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"default-value-for\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"default-value-for\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"default-value-for\",\"number\":\"1.0.7\",\"dependencies\":[]},\n  {\"name\":\"default-value-for\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"default-value-for\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"default-value-for\",\"number\":\"1.0.5\",\"dependencies\":[]},\n  {\"name\":\"default-value-for\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"default-value-for\",\"number\":\"1.0.6\",\"dependencies\":[]},\n  {\"name\":\"default-value-for\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"default-value-for\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"default-value-for\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"descendants-tracker\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"descendants-tracker\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"descendants-tracker\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"devise\",\"number\":\"3.2.4\",\"dependencies\":[[\"railties\",\"3.2.6 || 4.0.0\"],[\"thread-safe\",\"0.1.0\"],[\"bcrypt\",\"3.0.0\"],[\"orm-adapter\",\"0.1.0\"],[\"warden\",\"1.2.3\"]]},\n  {\"name\":\"devise\",\"number\":\"3.2.3\",\"dependencies\":[[\"railties\",\"3.2.6 || 4.0.0\"],[\"thread-safe\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"orm-adapter\",\"0.1.0\"],[\"warden\",\"1.2.3\"]]},\n  {\"name\":\"devise\",\"number\":\"3.2.2\",\"dependencies\":[[\"railties\",\"3.2.6 || 4.0.0\"],[\"thread-safe\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"orm-adapter\",\"0.1.0\"],[\"warden\",\"1.2.3\"]]},\n  {\"name\":\"devise\",\"number\":\"3.2.1\",\"dependencies\":[[\"railties\",\"3.2.6 || 4.0.0\"],[\"thread-safe\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"orm-adapter\",\"0.1.0\"],[\"warden\",\"1.2.3\"]]},\n  {\"name\":\"devise\",\"number\":\"3.1.2\",\"dependencies\":[[\"railties\",\"3.2.6 || 4.0.0\"],[\"thread-safe\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"orm-adapter\",\"0.1.0\"],[\"warden\",\"1.2.3\"]]},\n  {\"name\":\"devise\",\"number\":\"3.0.4\",\"dependencies\":[[\"railties\",\"3.2.6 || 4.0.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"orm-adapter\",\"0.1.0\"],[\"warden\",\"1.2.3\"]]},\n  {\"name\":\"devise\",\"number\":\"2.2.8\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"orm-adapter\",\"0.1.0\"],[\"warden\",\"1.2.1\"]]},\n  {\"name\":\"devise\",\"number\":\"3.2.0\",\"dependencies\":[[\"railties\",\"3.2.6 || 4.0.0\"],[\"thread-safe\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"orm-adapter\",\"0.1.0\"],[\"warden\",\"1.2.3\"]]},\n  {\"name\":\"devise\",\"number\":\"3.1.1\",\"dependencies\":[[\"railties\",\"3.2.6 || 4.0.0\"],[\"thread-safe\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"orm-adapter\",\"0.1.0\"],[\"warden\",\"1.2.3\"]]},\n  {\"name\":\"devise\",\"number\":\"1.5.0\",\"dependencies\":[[\"warden\",\"1.1.0\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.5.6\",\"dependencies\":[[\"warden\",\"0.6.3 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.0.2\",\"dependencies\":[[\"warden\",\"1.1.0\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.4.1\",\"dependencies\":[[\"warden\",\"0.5.1 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.0.4\",\"dependencies\":[[\"warden\",\"0.9.4 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.5.2\",\"dependencies\":[[\"warden\",\"1.1.0\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.5.1\",\"dependencies\":[[\"warden\",\"1.1.0\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.2.2\",\"dependencies\":[[\"warden\",\"0.5.1 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.3.4\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.0.8\",\"dependencies\":[[\"warden\",\"0.10.3 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.0.1\",\"dependencies\":[[\"warden\",\"1.1.0\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.1.1\",\"dependencies\":[[\"warden\",\"0.10.7 || 1.0.0\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.0.10\",\"dependencies\":[[\"warden\",\"0.10.3 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.4.3\",\"dependencies\":[[\"warden\",\"0.5.2 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.7.3\",\"dependencies\":[[\"warden\",\"0.6.4 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.0.2\",\"dependencies\":[[\"warden\",\"0.9.3 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.7.0\",\"dependencies\":[[\"warden\",\"0.6.4 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.1.6\",\"dependencies\":[[\"warden\",\"1.0.2\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.5.3\",\"dependencies\":[[\"warden\",\"0.6.1 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.7.4\",\"dependencies\":[[\"warden\",\"0.6.4 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.8.0\",\"dependencies\":[[\"warden\",\"0.8.0 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.0.9\",\"dependencies\":[[\"warden\",\"0.10.3 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.5.5\",\"dependencies\":[[\"warden\",\"0.6.3 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.1.7\",\"dependencies\":[[\"warden\",\"1.0.2\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.9.2\",\"dependencies\":[[\"warden\",\"0.9.0 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.0.3\",\"dependencies\":[[\"warden\",\"0.9.4 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.5.3\",\"dependencies\":[[\"warden\",\"1.1.0\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.5.1\",\"dependencies\":[[\"warden\",\"0.6.0 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.6.3\",\"dependencies\":[[\"warden\",\"0.6.4 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.5.2\",\"dependencies\":[[\"warden\",\"0.6.1 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.4.2\",\"dependencies\":[[\"warden\",\"0.5.1 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.7.1\",\"dependencies\":[[\"warden\",\"0.6.4 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.9.0\",\"dependencies\":[[\"warden\",\"0.9.0 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.6.2\",\"dependencies\":[[\"warden\",\"0.6.3 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.7.2\",\"dependencies\":[[\"warden\",\"0.6.4 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.0.7\",\"dependencies\":[[\"warden\",\"0.10.3 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.1.3\",\"dependencies\":[[\"warden\",\"0.10.7 || 1.0.0\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.1.8\",\"dependencies\":[[\"warden\",\"1.0.2\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.2.1\",\"dependencies\":[[\"warden\",\"0.5.1 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.3.2\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.9.1\",\"dependencies\":[[\"warden\",\"0.9.0 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.6.0\",\"dependencies\":[[\"warden\",\"0.6.3 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.7.5\",\"dependencies\":[[\"warden\",\"0.6.4 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.1.2\",\"dependencies\":[[\"warden\",\"0.10.7 || 1.0.0\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.4.2\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.0.11\",\"dependencies\":[[\"warden\",\"0.10.3 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.2.0\",\"dependencies\":[[\"warden\",\"0.5.1 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.4.0\",\"dependencies\":[[\"warden\",\"0.5.1 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.4.5\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.4.9\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.4.3\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.1.1\",\"dependencies\":[[\"warden\",\"0.5.0 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.1.0\",\"dependencies\":[[\"warden\",\"0.10.7 || 1.0.0\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.3.3\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.3.0\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.1.0\",\"dependencies\":[[\"warden\",\"1.1.1\"],[\"orm-adapter\",\"0.0.7\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.1.1\",\"dependencies\":[[\"warden\",\"1.2.1\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.1.2\",\"dependencies\":[[\"warden\",\"1.2.1\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.5.4\",\"dependencies\":[[\"warden\",\"0.6.3 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.3.1\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.1.0\",\"dependencies\":[[\"warden\",\"0.5.0 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.0.0\",\"dependencies\":[[\"warden\",\"1.1.0\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.1.4\",\"dependencies\":[[\"warden\",\"1.0.2\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.2.1\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.2.0\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.0.0\",\"dependencies\":[[\"warden\",\"0.9.0 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.1.5\",\"dependencies\":[[\"warden\",\"1.0.2\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.1.9\",\"dependencies\":[[\"warden\",\"1.0.2\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.2.3\",\"dependencies\":[[\"warden\",\"0.5.1 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.3.0\",\"dependencies\":[[\"warden\",\"0.5.1 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.0.6\",\"dependencies\":[[\"warden\",\"0.10.3 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.4.8\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.4.1\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.0.1\",\"dependencies\":[[\"warden\",\"0.9.0 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.5.0\",\"dependencies\":[[\"warden\",\"0.5.2 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.0.5\",\"dependencies\":[[\"warden\",\"0.10.2 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.8.1\",\"dependencies\":[[\"warden\",\"0.8.1 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.8.2\",\"dependencies\":[[\"warden\",\"0.8.1 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"0.6.1\",\"dependencies\":[[\"warden\",\"0.6.3 || 1.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.4.7\",\"dependencies\":[[\"warden\",\"1.0.3\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.0.4\",\"dependencies\":[[\"warden\",\"1.1.1\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"3.1.0\",\"dependencies\":[[\"warden\",\"1.2.3\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"thread-safe\",\"0.1.0\"],[\"railties\",\"3.2.6 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.2.0\",\"dependencies\":[[\"warden\",\"1.2.1\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.2.1\",\"dependencies\":[[\"warden\",\"1.2.1\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.2.2\",\"dependencies\":[[\"warden\",\"1.2.1\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.2.3\",\"dependencies\":[[\"warden\",\"1.2.1\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"1.5.4\",\"dependencies\":[[\"warden\",\"1.1.0\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.0.5\",\"dependencies\":[[\"warden\",\"1.1.1\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.1.3\",\"dependencies\":[[\"warden\",\"1.2.1\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.2.4\",\"dependencies\":[[\"warden\",\"1.2.1\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"3.0.0\",\"dependencies\":[[\"warden\",\"1.2.3\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.2.6 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"3.0.1\",\"dependencies\":[[\"warden\",\"1.2.3\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.2.6 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.2.5\",\"dependencies\":[[\"warden\",\"1.2.1\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"3.0.2\",\"dependencies\":[[\"warden\",\"1.2.3\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.2.6 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.2.6\",\"dependencies\":[[\"warden\",\"1.2.1\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"3.0.3\",\"dependencies\":[[\"warden\",\"1.2.3\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.2.6 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.2.7\",\"dependencies\":[[\"warden\",\"1.2.1\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.0.6\",\"dependencies\":[[\"warden\",\"1.1.1\"],[\"orm-adapter\",\"0.0.3\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise\",\"number\":\"2.1.4\",\"dependencies\":[[\"warden\",\"1.2.1\"],[\"orm-adapter\",\"0.1.0\"],[\"bcrypt-ruby\",\"3.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"devise-async\",\"number\":\"0.9.0\",\"dependencies\":[[\"devise\",\"3.2.0\"]]},\n  {\"name\":\"devise-async\",\"number\":\"0.1.0\",\"dependencies\":[[\"devise\",\"1.1.0 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"devise-async\",\"number\":\"0.0.2\",\"dependencies\":[[\"devise\",\"1.1.0 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"devise-async\",\"number\":\"0.2.0\",\"dependencies\":[[\"devise\",\"1.1.0 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"devise-async\",\"number\":\"0.3.0\",\"dependencies\":[[\"devise\",\"1.1.0 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"devise-async\",\"number\":\"0.3.1\",\"dependencies\":[[\"devise\",\"1.1.0 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"devise-async\",\"number\":\"0.0.1\",\"dependencies\":[[\"devise\",null]]},\n  {\"name\":\"devise-async\",\"number\":\"0.1.1\",\"dependencies\":[[\"devise\",\"1.1.0 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"devise-async\",\"number\":\"0.8.0\",\"dependencies\":[[\"devise\",\"2.2.0 || 3.0.0\"]]},\n  {\"name\":\"devise-async\",\"number\":\"0.4.0\",\"dependencies\":[[\"devise\",\"1.1.0 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"devise-async\",\"number\":\"0.5.0\",\"dependencies\":[[\"devise\",\"1.1.0 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"devise-async\",\"number\":\"0.5.1\",\"dependencies\":[[\"devise\",\"1.1.0 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"devise-async\",\"number\":\"0.6.0\",\"dependencies\":[[\"devise\",\"2.2.0 || 3.0.0\"]]},\n  {\"name\":\"devise-async\",\"number\":\"0.7.0\",\"dependencies\":[[\"devise\",\"2.2.0 || 3.0.0\"]]},\n  {\"name\":\"diff-lcs\",\"number\":\"1.2.5\",\"dependencies\":[]},\n  {\"name\":\"diff-lcs\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"diff-lcs\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"diff-lcs\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"diff-lcs\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"diff-lcs\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"diff-lcs\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"diff-lcs\",\"number\":\"1.2.3\",\"dependencies\":[]},\n  {\"name\":\"diff-lcs\",\"number\":\"1.2.4\",\"dependencies\":[]},\n  {\"name\":\"docile\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"docile\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"docile\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"docile\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"docile\",\"number\":\"0.9.2\",\"dependencies\":[]},\n  {\"name\":\"docile\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"docile\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"docile\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"docile\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"docile\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"docile\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"docile\",\"number\":\"1.0.5\",\"dependencies\":[]},\n  {\"name\":\"docile\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"dotenv\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"dotenv\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"dotenv\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"dotenv\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"dotenv\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"dotenv\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"dotenv\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"dotenv\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"dotenv\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"dotenv\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"dotenv\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"1.1.1\",\"dependencies\":[[\"rspec\",\"2.0.0\"]]},\n  {\"name\":\"email-spec\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"0.3.8\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"0.3.6\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"0.6.5\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"1.0.1\",\"dependencies\":[[\"rspec\",\"2.0.0\"]]},\n  {\"name\":\"email-spec\",\"number\":\"0.6.4\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"1.2.1\",\"dependencies\":[[\"mail\",\"2.2.0\"],[\"rspec\",\"2.0.0\"]]},\n  {\"name\":\"email-spec\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"1.2.0\",\"dependencies\":[[\"mail\",\"2.2.0\"],[\"rspec\",\"2.0.0\"]]},\n  {\"name\":\"email-spec\",\"number\":\"0.6.6\",\"dependencies\":[[\"rspec\",null]]},\n  {\"name\":\"email-spec\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"0.3.7\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"0.3.5\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"email-spec\",\"number\":\"1.4.0\",\"dependencies\":[[\"launchy\",\"2.1.0\"],[\"mail\",\"2.2.0\"]]},\n  {\"name\":\"email-spec\",\"number\":\"1.5.0\",\"dependencies\":[[\"launchy\",\"2.1.0\"],[\"mail\",\"2.2.0\"]]},\n  {\"name\":\"email-validator\",\"number\":\"1.2.2\",\"dependencies\":[[\"activemodel\",null]]},\n  {\"name\":\"email-validator\",\"number\":\"1.2.1\",\"dependencies\":[[\"activemodel\",null]]},\n  {\"name\":\"email-validator\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"email-validator\",\"number\":\"1.2.3\",\"dependencies\":[[\"activemodel\",null]]},\n  {\"name\":\"email-validator\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"email-validator\",\"number\":\"1.2.4\",\"dependencies\":[[\"activemodel\",null]]},\n  {\"name\":\"email-validator\",\"number\":\"1.3.0\",\"dependencies\":[[\"activemodel\",null]]},\n  {\"name\":\"email-validator\",\"number\":\"1.4.0\",\"dependencies\":[[\"activemodel\",null]]},\n  {\"name\":\"emoji\",\"number\":\"1.0.1\",\"dependencies\":[[\"json\",null]]},\n  {\"name\":\"emoji\",\"number\":\"1.0.0\",\"dependencies\":[[\"json\",null]]},\n  {\"name\":\"emoji\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"emoji\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"enumerize\",\"number\":\"0.8.0\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.1.1\",\"dependencies\":[[\"activesupport\",\"3.1.3 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.2.2\",\"dependencies\":[[\"activesupport\",\"3.1.3 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.3.0\",\"dependencies\":[[\"activesupport\",\"3.1.3 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.0.2\",\"dependencies\":[[\"activesupport\",\"3.1.3 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.0.3\",\"dependencies\":[[\"activesupport\",\"3.1.3 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.1.0\",\"dependencies\":[[\"activesupport\",\"3.1.3 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.0.4\",\"dependencies\":[[\"activesupport\",\"3.1.3 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.2.1\",\"dependencies\":[[\"activesupport\",\"3.1.3 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.4.0\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.2.0\",\"dependencies\":[[\"activesupport\",\"3.1.3 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.0.1\",\"dependencies\":[[\"activesupport\",\"3.1.3 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.5.0\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.5.1\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.6.0\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.6.1\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"enumerize\",\"number\":\"0.7.0\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"equalizer\",\"number\":\"0.0.9\",\"dependencies\":[]},\n  {\"name\":\"equalizer\",\"number\":\"0.0.8\",\"dependencies\":[]},\n  {\"name\":\"equalizer\",\"number\":\"0.0.1\",\"dependencies\":[[\"backports\",\"2.6.4 || 3.0.0\"],[\"adamantium\",\"0.0.3\"]]},\n  {\"name\":\"equalizer\",\"number\":\"0.0.2\",\"dependencies\":[[\"backports\",\"2.6.4 || 3.0.0\"],[\"adamantium\",\"0.0.3\"]]},\n  {\"name\":\"equalizer\",\"number\":\"0.0.3\",\"dependencies\":[[\"backports\",\"2.7.0 || 3.0.0\"],[\"adamantium\",\"0.0.5\"]]},\n  {\"name\":\"equalizer\",\"number\":\"0.0.4\",\"dependencies\":[[\"backports\",\"2.8.2 || 3.0.0\"],[\"adamantium\",\"0.0.6\"]]},\n  {\"name\":\"equalizer\",\"number\":\"0.0.5\",\"dependencies\":[[\"backports\",\"3.0.0\"],[\"adamantium\",\"0.0.6\"]]},\n  {\"name\":\"equalizer\",\"number\":\"0.0.7\",\"dependencies\":[]},\n  {\"name\":\"erubis\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"erubis\",\"number\":\"2.3.0\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.2.0\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.6.5\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.6.0\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.3.1\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.5.0\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.6.4\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.6.1\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.0.1\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"erubis\",\"number\":\"2.0.0\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.6.2\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.4.1\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.6.6\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.4.0\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.1.0\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"erubis\",\"number\":\"2.6.3\",\"dependencies\":[[\"abstract\",\"1.0.0\"]]},\n  {\"name\":\"erubis\",\"number\":\"2.7.0\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.1.8\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.2.3\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.1.6\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.2.4\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.1.9\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.1.7\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"escape-utils\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.4.5\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.7.2\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.12.10\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.12.6\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.12.4\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.12.0\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.12.2\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.8.1\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.4.4\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"0.12.8\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"eventmachine\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.32.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.32.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.31.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.30.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.29.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.28.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.27.6\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.27.5\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.27.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.27.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.27.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.27.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.27.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.26.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.13.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.20\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.14.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.2.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.9.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.6.5\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.3.5\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.23\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.7.11\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.6.6\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.7.12\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.18\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.7.10\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.16.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.8\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.5.6\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.21\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.16\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.9.6\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.14.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.12.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.5.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.9.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.24\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.15\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.7.6\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.7.7\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.14.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.5.7\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.26\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.7.5\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.3.7\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.3.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.2.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.7.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.16.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.16.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.16.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.16.5\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.17\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.2.6\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.9.5\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.16.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.15.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.10.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.5.8\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.13.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.3.8\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.2.7\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.10\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.14\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.7.9\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.7.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.13\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.14.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.7\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.5.5\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.2.8\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.12\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.15.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.6.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.3.6\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.13.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.13.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.15.5\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.15.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.15.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.13.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.5\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.7.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.9.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.19\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.22\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.15.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.11.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.7.8\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.11\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.0.25\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.16.7\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.16.8\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.16.10\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.16.9\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.17.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.18.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.18.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.18.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.18.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.18.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.18.5\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.19.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.19.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.19.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.19.3\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.19.4\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.19.5\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.20.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.20.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.21.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.22.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.22.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.23.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.24.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.25.0\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.25.1\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.25.2\",\"dependencies\":[]},\n  {\"name\":\"excon\",\"number\":\"0.25.3\",\"dependencies\":[]},\n  {\"name\":\"execjs\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"execjs\",\"number\":\"1.2.9\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.2.7\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.2.11\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.2.10\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"execjs\",\"number\":\"0.4.0\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.2.5\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.2.8\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"0.3.0\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"0.3.2\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.2.0\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.1.3\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.2.1\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.2.6\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.1.0\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.2.4\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.1.1\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"execjs\",\"number\":\"0.3.1\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.4.0\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.2.13\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.3.1\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.2.12\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.2.3\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"execjs\",\"number\":\"0.3.4\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.3.2\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.3.0\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.1.2\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.2.2\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"1.0.0\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"0.3.3\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"execjs\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"execjs\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"execjs\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"4.4.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"4.3.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"1.1.5\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"1.1.3\",\"dependencies\":[[\"activesupport\",\"1.0.0 || 2.0.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"4.0.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"1.2.3\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"1.1.1\",\"dependencies\":[[\"activesupport\",\"1.0.0 || 2.0.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.6.0\",\"dependencies\":[[\"activesupport\",\"2.3.9 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"3.1.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.0.5\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"3.6.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"1.1.0\",\"dependencies\":[[\"activesupport\",\"1.0.0 || 2.0.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"2.6.4\",\"dependencies\":[[\"activesupport\",\"2.3.9 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.6.2\",\"dependencies\":[[\"activesupport\",\"2.3.9 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"3.4.2\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.5.1\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"factory-girl\",\"number\":\"1.1.2\",\"dependencies\":[[\"activesupport\",\"1.0.0 || 2.0.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.3.1\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.4.2\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"factory-girl\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"3.2.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"1.2.4\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"2.4.1\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.5.0\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"factory-girl\",\"number\":\"3.0.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"3.1.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.5.2\",\"dependencies\":[[\"activesupport\",\"2.3.9 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"2.2.0\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.6.1\",\"dependencies\":[[\"activesupport\",\"2.3.9 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"2.4.0\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"factory-girl\",\"number\":\"1.1.4\",\"dependencies\":[[\"activesupport\",\"1.0.0 || 2.0.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"2.6.3\",\"dependencies\":[[\"activesupport\",\"2.3.9 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.3.2\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"factory-girl\",\"number\":\"1.3.3\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"2.1.2\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"factory-girl\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"factory-girl\",\"number\":\"2.3.0\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"factory-girl\",\"number\":\"3.3.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"3.4.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"3.4.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"3.5.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"3.6.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"4.1.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"3.6.2\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl\",\"number\":\"4.2.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"4.4.1\",\"dependencies\":[[\"factory-girl\",\"4.4.0\"],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"4.4.0\",\"dependencies\":[[\"factory-girl\",\"4.4.0\"],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"4.3.0\",\"dependencies\":[[\"factory-girl\",\"4.3.0\"],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"3.6.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"3.6.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"1.3.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"2.2.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"1.1.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"2.0.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"3.4.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"3.4.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"3.5.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"3.5.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"4.0.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"1.2.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"2.1.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"1.4.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"2.3.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"1.0.1\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"1.3.0 || 2.0.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"1.7.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"2.6.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"1.6.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"2.5.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"3.1.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"3.0.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"1.5.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"2.4.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"1.0.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"1.3.0 || 2.0.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"2.0.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"3.2.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"3.3.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"3.3.0 || 4.0.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"4.1.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"4.1.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"4.2.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"4.2.0\"]]},\n  {\"name\":\"factory-girl-rails\",\"number\":\"4.2.1\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"factory-girl\",\"4.2.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.9.0\",\"dependencies\":[[\"multipart-post\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.8.9\",\"dependencies\":[[\"multipart-post\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.5.4\",\"dependencies\":[[\"addressable\",\"2.2.2\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.5.3\",\"dependencies\":[[\"addressable\",\"2.2.2\"],[\"multipart-post\",\"1.0.1 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.4.1\",\"dependencies\":[[\"rack\",null],[\"addressable\",null]]},\n  {\"name\":\"faraday\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"faraday\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"faraday\",\"number\":\"0.5.1\",\"dependencies\":[[\"addressable\",\"2.2.2\"],[\"multipart-post\",\"1.0.1 || 2.0.0\"],[\"rack\",\"1.2.1\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.2.2\",\"dependencies\":[[\"rack\",null],[\"addressable\",null]]},\n  {\"name\":\"faraday\",\"number\":\"0.5.2\",\"dependencies\":[[\"addressable\",\"2.2.2\"],[\"multipart-post\",\"1.0.1 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.7.1\",\"dependencies\":[[\"addressable\",\"2.2.6\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.5.7\",\"dependencies\":[[\"addressable\",\"2.2.4\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.6.1\",\"dependencies\":[[\"addressable\",\"2.2.4\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.2.0\",\"dependencies\":[[\"rack\",null],[\"addressable\",null]]},\n  {\"name\":\"faraday\",\"number\":\"0.4.0\",\"dependencies\":[[\"rack\",null],[\"addressable\",null]]},\n  {\"name\":\"faraday\",\"number\":\"0.3.0\",\"dependencies\":[[\"rack\",null],[\"addressable\",null]]},\n  {\"name\":\"faraday\",\"number\":\"0.4.5\",\"dependencies\":[[\"rack\",\"1.0.1\"],[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.7.6\",\"dependencies\":[[\"addressable\",\"2.2.0\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.3.1\",\"dependencies\":[[\"rack\",null],[\"addressable\",null]]},\n  {\"name\":\"faraday\",\"number\":\"0.5.5\",\"dependencies\":[[\"addressable\",\"2.2.4\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.8.4\",\"dependencies\":[[\"multipart-post\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.7.4\",\"dependencies\":[[\"addressable\",\"2.2.6\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.2.3\",\"dependencies\":[[\"rack\",null],[\"addressable\",null]]},\n  {\"name\":\"faraday\",\"number\":\"0.7.5\",\"dependencies\":[[\"addressable\",\"2.2.6\"],[\"multipart-post\",\"1.1.3 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.7.0\",\"dependencies\":[[\"addressable\",\"2.2.4\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.5.6\",\"dependencies\":[[\"addressable\",\"2.2.4\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.7.3\",\"dependencies\":[[\"addressable\",\"2.2.6\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.7.2\",\"dependencies\":[[\"addressable\",\"2.2.6\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"faraday\",\"number\":\"0.4.2\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"addressable\",\"=2.1.1\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.6.0\",\"dependencies\":[[\"addressable\",\"2.2.4\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rack\",\"1.1.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.2.4\",\"dependencies\":[[\"rack\",null],[\"addressable\",null]]},\n  {\"name\":\"faraday\",\"number\":\"0.5.0\",\"dependencies\":[[\"addressable\",\"2.1.1\"],[\"multipart-post\",\"1.0.1 || 2.0.0\"],[\"rack\",\"1.2.1\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.2.1\",\"dependencies\":[[\"rack\",null],[\"addressable\",null]]},\n  {\"name\":\"faraday\",\"number\":\"0.8.0\",\"dependencies\":[[\"multipart-post\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.8.2\",\"dependencies\":[[\"multipart-post\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.8.1\",\"dependencies\":[[\"multipart-post\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.4.6\",\"dependencies\":[[\"rack\",\"1.0.1\"],[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.4.4\",\"dependencies\":[[\"rack\",\"1.0.1\"],[\"addressable\",\"=2.1.1\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"faraday\",\"number\":\"0.4.3\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"addressable\",\"=2.1.1\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"faraday\",\"number\":\"0.8.5\",\"dependencies\":[[\"multipart-post\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.8.6\",\"dependencies\":[[\"multipart-post\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.8.7\",\"dependencies\":[[\"multipart-post\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"faraday\",\"number\":\"0.8.8\",\"dependencies\":[[\"multipart-post\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.7.0\",\"dependencies\":[[\"faraday\",\"0.7.3\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.6.0\",\"dependencies\":[[\"faraday\",\"0.6.0\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.6.5\",\"dependencies\":[[\"faraday\",\"0.6.0\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.8.0\",\"dependencies\":[[\"faraday\",null]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.1.1\",\"dependencies\":[[\"faraday\",\"0.4.5\"],[\"hashie\",\"0.4.0 || 1.0.0 || 2.0.0\"],[\"multi-json\",\"0.0.4 || 1.0.0\"],[\"multi-xml\",\"0.0.1\"],[\"oauth2\",\"0.0.13\"],[\"roauth\",\"0.0.3\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.8.2\",\"dependencies\":[[\"faraday\",null]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.6.3\",\"dependencies\":[[\"faraday\",\"0.6.0\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.1.5\",\"dependencies\":[[\"faraday\",\"0.5.0\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.3.2\",\"dependencies\":[[\"faraday\",\"0.5.4\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.8.3\",\"dependencies\":[[\"faraday\",null]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.8.1\",\"dependencies\":[[\"faraday\",null]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.8.4\",\"dependencies\":[[\"faraday\",null]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.1.6\",\"dependencies\":[[\"faraday\",\"0.5.0\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.0.5\",\"dependencies\":[[\"faraday\",\"0.4.5\"],[\"hashie\",\"0.4.0 || 1.0.0 || 2.0.0\"],[\"multi-json\",\"0.0.4 || 1.0.0\"],[\"oauth2\",\"0.0.13\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.1.0\",\"dependencies\":[[\"faraday\",\"0.4.5\"],[\"hashie\",\"0.4.0 || 1.0.0 || 2.0.0\"],[\"multi-json\",\"0.0.4 || 1.0.0\"],[\"oauth2\",\"0.0.13\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.2.1\",\"dependencies\":[[\"faraday\",\"0.5.1\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.1.4\",\"dependencies\":[[\"faraday\",\"0.5.0\"],[\"hashie\",\"0.4.0 || 1.0.0 || 2.0.0\"],[\"multi-json\",\"0.0.4 || 1.0.0\"],[\"multi-xml\",\"0.1.0\"],[\"oauth2\",\"0.1.0\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.0.4\",\"dependencies\":[[\"faraday\",\"0.4.5\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.2.0\",\"dependencies\":[[\"faraday\",\"0.5.1\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.1.7\",\"dependencies\":[[\"faraday\",\"0.5.1\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.3.1\",\"dependencies\":[[\"faraday\",\"0.5.3\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.1.3\",\"dependencies\":[[\"faraday\",\"0.4.5\"],[\"hashie\",\"0.4.0 || 1.0.0 || 2.0.0\"],[\"multi-json\",\"0.0.4 || 1.0.0\"],[\"multi-xml\",\"0.1.0\"],[\"oauth2\",\"0.0.13\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.1.2\",\"dependencies\":[[\"faraday\",\"0.4.5\"],[\"hashie\",\"0.4.0 || 1.0.0 || 2.0.0\"],[\"multi-json\",\"0.0.4 || 1.0.0\"],[\"multi-xml\",\"0.0.1\"],[\"oauth2\",\"0.0.13\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.8.7\",\"dependencies\":[[\"faraday\",null]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.8.8\",\"dependencies\":[[\"faraday\",null]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.8.5\",\"dependencies\":[[\"faraday\",null]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.2.3\",\"dependencies\":[[\"faraday\",\"0.5.2\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.3.0\",\"dependencies\":[[\"faraday\",\"0.5.3\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.8.6\",\"dependencies\":[[\"faraday\",null]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.2.2\",\"dependencies\":[[\"faraday\",\"0.5.2\"]]},\n  {\"name\":\"faraday-middleware\",\"number\":\"0.9.0\",\"dependencies\":[[\"faraday\",null]]},\n  {\"name\":\"ffaker\",\"number\":\"1.23.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.22.1\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.22.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.21.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.20.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.19.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.13.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.11.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.8.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"0.3.4\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"0.3.6\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.9.1\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.10.1\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.8.1\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"0.3.5\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"0.3.7\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.12.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.12.1\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.14.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.15.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.16.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.16.1\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.16.2\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.17.0\",\"dependencies\":[]},\n  {\"name\":\"ffaker\",\"number\":\"1.18.0\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.9.3\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"0.5.4\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"1.0.2\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"1.0.9\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"0.5.0\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"0.5.3\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"1.0.4\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"0.5.1\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"1.0.1\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.0.5\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"1.0.11\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.0.3\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"0.6.3\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.0.0\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"0.6.2\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.0.6\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"0.3.0\",\"dependencies\":[[\"bones\",\"2.4.2\"]]},\n  {\"name\":\"ffi\",\"number\":\"1.0.10\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"0.6.0\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"1.1.5\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"0.6.4\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"0.3.2\",\"dependencies\":[[\"bones\",\"2.4.2\"]]},\n  {\"name\":\"ffi\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.1.4\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"0.3.5\",\"dependencies\":[[\"bones\",\"2.4.2\"]]},\n  {\"name\":\"ffi\",\"number\":\"0.3.3\",\"dependencies\":[[\"bones\",\"2.4.2\"]]},\n  {\"name\":\"ffi\",\"number\":\"0.6.1\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"0.3.4\",\"dependencies\":[[\"bones\",\"2.4.2\"]]},\n  {\"name\":\"ffi\",\"number\":\"0.3.1\",\"dependencies\":[[\"bones\",\"2.4.2\"]]},\n  {\"name\":\"ffi\",\"number\":\"1.0.7\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"ffi\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.8.1\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"1.9.0\",\"dependencies\":[]},\n  {\"name\":\"fog\",\"number\":\"1.21.0\",\"dependencies\":[[\"fog-brightbox\",null],[\"nokogiri\",\"1.5.11\"],[\"fog-json\",null],[\"fog-core\",\"1.21.1\"]]},\n  {\"name\":\"fog\",\"number\":\"1.20.0\",\"dependencies\":[[\"nokogiri\",\"1.5.11\"],[\"net-ssh\",\"2.1.3\"],[\"net-scp\",\"1.1.0\"],[\"mime-types\",null],[\"multi-json\",\"1.0.0\"],[\"formatador\",\"0.2.0\"],[\"excon\",\"0.31.0\"],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.19.0\",\"dependencies\":[[\"ruby-hmac\",null],[\"nokogiri\",\"1.5.0\"],[\"net-ssh\",\"2.1.3\"],[\"net-scp\",\"1.1.0\"],[\"mime-types\",null],[\"multi-json\",\"1.0.0\"],[\"formatador\",\"0.2.0\"],[\"excon\",\"0.31.0\"],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.18.0\",\"dependencies\":[[\"ruby-hmac\",null],[\"nokogiri\",\"1.5.0\"],[\"net-ssh\",\"2.1.3\"],[\"net-scp\",\"1.1.0\"],[\"mime-types\",null],[\"multi-json\",\"1.0.0\"],[\"formatador\",\"0.2.0\"],[\"excon\",\"0.28.0\"],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.17.0\",\"dependencies\":[[\"ruby-hmac\",null],[\"nokogiri\",\"1.5.0\"],[\"net-ssh\",\"2.1.3\"],[\"net-scp\",\"1.1.0\"],[\"mime-types\",null],[\"multi-json\",\"1.0.0\"],[\"formatador\",\"0.2.0\"],[\"excon\",\"0.27.0\"],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.16.0\",\"dependencies\":[[\"unicode\",\"0.4.4\"],[\"ruby-hmac\",null],[\"nokogiri\",\"1.5.0\"],[\"net-ssh\",\"2.1.3\"],[\"net-scp\",\"1.1.0\"],[\"mime-types\",null],[\"multi-json\",\"1.0.0\"],[\"formatador\",\"0.2.0\"],[\"excon\",\"0.27.0\"],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.8.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.6.1\"],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.5.2\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.23\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.76\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.1.8\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.26\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.1\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.15\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.3\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.61\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.57\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.16\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.92\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.27\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.1.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.7.4\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.3\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.2.1\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.2\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.1.10\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.13\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.30\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"named-parameters\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.90\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.11.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.6.5\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.3\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.4\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.5\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.25\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.0\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.94\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.10\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.78\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.12\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.8\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.29\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"named-parameters\",\"=0.0.14\"],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.7.2\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.46\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.23\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.14\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.8.1\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.6.1\"],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.6.0\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.80\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.5.1\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.5\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.19\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.15\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.39\",\"dependencies\":[[\"excon\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.77\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.40\",\"dependencies\":[[\"excon\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.3.1\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.13.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.56\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.4.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.14.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.59\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.5.0\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.83\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.65\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.34\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.13\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.41\",\"dependencies\":[[\"excon\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.21\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.6\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.1.0\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.33\",\"dependencies\":[[\"excon\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.7.0\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.64\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.19\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.66\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.84\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.25\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.11\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.27\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"named-parameters\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.8.2\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.6.1\"],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.100\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.37\",\"dependencies\":[[\"excon\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.26\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.20\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.1.3\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.1.4\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.10.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.6.5\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.3\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.4\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.4\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.20\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.6\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.24\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.89\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.32\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.8\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.28\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"named-parameters\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.3\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.81\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.93\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.3.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.12.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.0\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.31\",\"dependencies\":[[\"excon\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.1.1\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.9\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.1.2\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.9.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.3\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.91\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.51\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.29\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.79\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.44\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.21\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.1.2\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.19\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.18\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.1.6\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.96\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.18\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.12\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.43\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.4\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.5.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.14.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.5\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.9.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.6.1\"],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.4\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.20\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.1.5\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.34\",\"dependencies\":[[\"excon\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.69\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.35\",\"dependencies\":[[\"excon\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.3\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.97\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.14\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.95\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.7\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.7\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.16\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.72\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.2\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.23\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.2.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.12.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.18\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.55\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.10\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.21\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.24\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.70\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.82\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.60\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.98\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.58\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.10\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.17\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.17\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.7.1\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.26\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.27\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.1.9\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.99\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.47\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.5.3\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.25\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.62\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.22\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.8\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.24\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.28\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.71\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.0.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.7.3\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.3\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.4\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.33\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.52\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.54\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.6\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.63\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.30\",\"dependencies\":[[\"excon\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.45\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.22\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.13\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.74\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.7\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.88\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.6.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.14.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.67\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.50\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.1\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.73\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.9\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.31\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"named-parameters\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.1.1\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.7.4\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.3\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.28\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.11\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.32\",\"dependencies\":[[\"excon\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.17\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.14\",\"dependencies\":[[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.22\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.87\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.49\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.75\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.85\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.15\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.68\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.42\",\"dependencies\":[[\"excon\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.38\",\"dependencies\":[[\"excon\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.4.0\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.53\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.30\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.9\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.4\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.48\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.36\",\"dependencies\":[[\"excon\",null],[\"mime-types\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.12\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.4.1\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.4\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.0.86\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.2.16\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null],[\"builder\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.3.11\",\"dependencies\":[[\"builder\",null],[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",\"2.0.23\"],[\"nokogiri\",\"1.4.3\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"0.1.7\",\"dependencies\":[[\"excon\",null],[\"formatador\",null],[\"json\",null],[\"mime-types\",null],[\"net-ssh\",null],[\"nokogiri\",null],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.7.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.14.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.8.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.14.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.9.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.14.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.0.4\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.10.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.14.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.1.0\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.10.1\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.20.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.1.0\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.11.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.20.0\"],[\"formatador\",\"0.2.0\"],[\"json\",\"1.7.0\"],[\"mime-types\",null],[\"net-scp\",\"1.1.0\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.11.1\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.20.0\"],[\"formatador\",\"0.2.0\"],[\"json\",\"1.7.0\"],[\"mime-types\",null],[\"net-scp\",\"1.1.0\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.12.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.22.1\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.1.0\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.12.1\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.23.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.1.0\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.14.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.25.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.1.0\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"fog\",\"number\":\"1.13.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.25.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.1.0\"],[\"net-ssh\",\"2.1.3\"],[\"ruby-hmac\",null],[\"nokogiri\",\"1.5.0\"]]},\n  {\"name\":\"fog\",\"number\":\"1.15.0\",\"dependencies\":[[\"builder\",null],[\"excon\",\"0.25.0\"],[\"formatador\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"mime-types\",null],[\"net-scp\",\"1.1.0\"],[\"net-ssh\",\"2.1.3\"],[\"nokogiri\",\"1.5.0\"],[\"ruby-hmac\",null]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"4.0.3\",\"dependencies\":[[\"railties\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"4.0.1\",\"dependencies\":[[\"railties\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"4.0.0\",\"dependencies\":[[\"railties\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"0.3.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"0.2.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"0.4.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"0.2.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"0.1.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"0.4.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"0.5.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"3.0.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"3.0.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"3.1.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"3.2.0\",\"dependencies\":[[\"railties\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"font-awesome-rails\",\"number\":\"3.2.1\",\"dependencies\":[[\"railties\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.2.0\",\"dependencies\":[[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.17.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.24.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.5.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.9.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.13.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.32.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.59.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.42.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.9.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.14.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.1.0\",\"dependencies\":[[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.4.7\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.49.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.15.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.35.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.9.2\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.7.5\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.18.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.54.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.4.5\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.27.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.53.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.43.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.7.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.44.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.38.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.7\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.12.0\",\"dependencies\":[[\"json\",\"1.5.1\"],[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.4.6\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.1.1\",\"dependencies\":[[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.7.2\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.3.2\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.39.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.7\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.21.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.40.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.7\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.4.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.45.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.10.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.34.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.11.1\",\"dependencies\":[[\"json\",\"1.5.1\"],[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.8.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.20.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.46.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.4.2\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.0.1\",\"dependencies\":[[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.52.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.37.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.7\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.5.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.41.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.7.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.23.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.0.2\",\"dependencies\":[[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.7.4\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.33.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.4.4\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.34.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.33.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.22.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.6.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.3.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.37.2\",\"dependencies\":[[\"term-ansicolor\",\"1.0.7\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.51.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.10.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.26.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.57.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.60.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.19.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.7.3\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.4.3\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.31.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.30.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.26.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.30.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.25.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.60.2\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.29.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.13.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.16.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.36.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.50.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.3.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.56.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.55.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.36.1\",\"dependencies\":[[\"term-ansicolor\",\"1.0.7\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.47.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.11.0\",\"dependencies\":[[\"json\",\"1.5.1\"],[\"term-ansicolor\",\"1.0.5\"],[\"thor\",\"0.13.6\"]]},\n  {\"name\":\"foreman\",\"number\":\"0.48.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.58.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.37.0\",\"dependencies\":[[\"term-ansicolor\",\"1.0.7\"],[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.61.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.62.0\",\"dependencies\":[[\"thor\",null]]},\n  {\"name\":\"foreman\",\"number\":\"0.63.0\",\"dependencies\":[[\"thor\",null],[\"dotenv\",null]]},\n  {\"name\":\"formatador\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.6\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.11\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.15\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.14\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.13\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.5\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.4\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.9\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.12\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.2.3\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.7\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.10\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.16\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"formatador\",\"number\":\"0.2.4\",\"dependencies\":[]},\n  {\"name\":\"gemnasium-gitlab-service\",\"number\":\"0.2.1\",\"dependencies\":[[\"rugged\",\"0.19.0\"]]},\n  {\"name\":\"gemnasium-gitlab-service\",\"number\":\"0.1.2\",\"dependencies\":[[\"gitlab-git\",\"3.0.0 || 4.0.0 || 5.0.0\"]]},\n  {\"name\":\"gemnasium-gitlab-service\",\"number\":\"0.1.1\",\"dependencies\":[[\"gitlab-git\",\"5.0.0\"]]},\n  {\"name\":\"gemnasium-gitlab-service\",\"number\":\"0.1.0\",\"dependencies\":[[\"gitlab-git\",\"5.5.0\"]]},\n  {\"name\":\"gherkin-ruby\",\"number\":\"0.3.1\",\"dependencies\":[[\"racc\",null]]},\n  {\"name\":\"gherkin-ruby\",\"number\":\"0.1.0\",\"dependencies\":[[\"rexical\",null],[\"racc\",null]]},\n  {\"name\":\"gherkin-ruby\",\"number\":\"0.2.0\",\"dependencies\":[[\"rexical\",null]]},\n  {\"name\":\"gherkin-ruby\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"gherkin-ruby\",\"number\":\"0.0.1\",\"dependencies\":[[\"parslet\",null]]},\n  {\"name\":\"gherkin-ruby\",\"number\":\"0.0.2\",\"dependencies\":[[\"parslet\",null]]},\n  {\"name\":\"gherkin-ruby\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.6.5\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.6.4\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.5.5\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.5.4\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"github-markdown\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.7.2\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.7.3\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.7.4\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.1.6\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.1.7\",\"dependencies\":[]},\n  {\"name\":\"github-markup\",\"number\":\"0.7.5\",\"dependencies\":[]},\n  {\"name\":\"gitlab-gollum-lib\",\"number\":\"1.1.0\",\"dependencies\":[[\"stringex\",\"1.5.1 || 2.0.0\"],[\"nokogiri\",\"1.5.9\"],[\"sanitize\",\"2.0.3\"],[\"github-markdown\",\"0.5.3\"],[\"github-markup\",null],[\"gitlab-grit\",\"2.6.1\"]]},\n  {\"name\":\"gitlab-gollum-lib\",\"number\":\"1.0.2\",\"dependencies\":[[\"stringex\",\"1.5.1 || 2.0.0\"],[\"nokogiri\",\"1.5.9\"],[\"sanitize\",\"2.0.3\"],[\"github-markdown\",\"0.5.3\"],[\"github-markup\",null],[\"gitlab-pygments.rb\",\"0.5.4\"],[\"gitlab-grit\",\"2.6.1\"]]},\n  {\"name\":\"gitlab-gollum-lib\",\"number\":\"1.0.0\",\"dependencies\":[[\"gitlab-grit\",\"2.5.1\"],[\"github-markup\",null],[\"github-markdown\",\"0.5.3\"],[\"pygments.rb\",\"0.4.2\"],[\"sanitize\",\"2.0.3\"],[\"nokogiri\",\"1.5.9\"],[\"stringex\",\"1.5.1 || 2.0.0\"]]},\n  {\"name\":\"gitlab-gollum-lib\",\"number\":\"1.0.1\",\"dependencies\":[[\"gitlab-grit\",\"2.5.1\"],[\"github-markup\",null],[\"github-markdown\",\"0.5.3\"],[\"pygments.rb\",\"0.4.2\"],[\"sanitize\",\"2.0.3\"],[\"nokogiri\",\"1.5.9\"],[\"stringex\",\"1.5.1 || 2.0.0\"]]},\n  {\"name\":\"gitlab-grack\",\"number\":\"2.0.0\",\"dependencies\":[[\"rack\",\"1.5.1\"]]},\n  {\"name\":\"gitlab-grack\",\"number\":\"1.1.0\",\"dependencies\":[[\"rack\",\"1.4.1\"]]},\n  {\"name\":\"gitlab-grack\",\"number\":\"1.0.0\",\"dependencies\":[[\"rack\",\"1.4.1\"]]},\n  {\"name\":\"gitlab-grack\",\"number\":\"1.0.1\",\"dependencies\":[[\"rack\",\"1.4.1\"]]},\n  {\"name\":\"gitlab-grit\",\"number\":\"2.6.4\",\"dependencies\":[[\"diff-lcs\",\"1.1.0\"],[\"mime-types\",\"1.15.0 || 2.0.0\"],[\"posix-spawn\",\"0.3.6\"],[\"charlock-holmes\",\"0.6.9\"]]},\n  {\"name\":\"gitlab-grit\",\"number\":\"2.6.3\",\"dependencies\":[[\"diff-lcs\",\"1.1.0\"],[\"mime-types\",\"1.15.0 || 2.0.0\"],[\"posix-spawn\",\"0.3.6\"],[\"charlock-holmes\",\"0.6.9\"]]},\n  {\"name\":\"gitlab-grit\",\"number\":\"2.6.2\",\"dependencies\":[[\"diff-lcs\",\"1.1.0\"],[\"mime-types\",\"1.15.0 || 2.0.0\"],[\"posix-spawn\",\"0.3.6\"],[\"charlock-holmes\",\"0.6.9\"]]},\n  {\"name\":\"gitlab-grit\",\"number\":\"2.5.2\",\"dependencies\":[[\"diff-lcs\",\"1.1.0\"],[\"mime-types\",\"1.15.0 || 2.0.0\"],[\"posix-spawn\",\"0.3.6\"],[\"charlock-holmes\",\"0.6.9\"]]},\n  {\"name\":\"gitlab-grit\",\"number\":\"2.6.1\",\"dependencies\":[[\"diff-lcs\",\"1.1.0\"],[\"mime-types\",\"1.15.0 || 2.0.0\"],[\"posix-spawn\",\"0.3.6\"],[\"charlock-holmes\",\"0.6.9\"]]},\n  {\"name\":\"gitlab-grit\",\"number\":\"1.0.0\",\"dependencies\":[[\"posix-spawn\",\"0.3.6\"],[\"mime-types\",\"1.15.0 || 2.0.0\"],[\"diff-lcs\",\"1.1.0\"]]},\n  {\"name\":\"gitlab-grit\",\"number\":\"2.5.0\",\"dependencies\":[[\"posix-spawn\",\"0.3.6\"],[\"mime-types\",\"1.15.0 || 2.0.0\"],[\"diff-lcs\",\"1.1.0\"]]},\n  {\"name\":\"gitlab-grit\",\"number\":\"2.5.1\",\"dependencies\":[[\"charlock-holmes\",\"0.6.9\"],[\"posix-spawn\",\"0.3.6\"],[\"mime-types\",\"1.15.0 || 2.0.0\"],[\"diff-lcs\",\"1.1.0\"]]},\n  {\"name\":\"gitlab-grit\",\"number\":\"2.6.0\",\"dependencies\":[[\"charlock-holmes\",\"0.6.9\"],[\"posix-spawn\",\"0.3.6\"],[\"mime-types\",\"1.15.0 || 2.0.0\"],[\"diff-lcs\",\"1.1.0\"]]},\n  {\"name\":\"gitlab-linguist\",\"number\":\"3.0.0\",\"dependencies\":[[\"mime-types\",\"1.19.0 || 2.0.0\"],[\"escape-utils\",\"0.2.4 || 1.0.0\"],[\"charlock-holmes\",\"0.6.6\"]]},\n  {\"name\":\"gitlab-linguist\",\"number\":\"2.9.6\",\"dependencies\":[[\"gitlab-pygments.rb\",\"0.5.4\"],[\"mime-types\",\"1.19.0 || 2.0.0\"],[\"escape-utils\",\"0.2.4 || 1.0.0\"],[\"charlock-holmes\",\"0.6.6\"]]},\n  {\"name\":\"gitlab-linguist\",\"number\":\"2.9.5\",\"dependencies\":[[\"gitlab-pygments.rb\",\"0.5.4\"],[\"mime-types\",\"1.19.0 || 2.0.0\"],[\"escape-utils\",\"0.3.1 || 1.0.0\"],[\"charlock-holmes\",\"0.6.6\"]]},\n  {\"name\":\"gitlab-emoji\",\"number\":\"0.0.1\",\"dependencies\":[[\"emoji\",\"1.0.1\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"5.7.1\",\"dependencies\":[[\"charlock-holmes\",\"0.6.9\"],[\"rugged\",\"0.19.0\"],[\"activesupport\",\"4.0.0\"],[\"gitlab-grit\",\"2.6.1\"],[\"gitlab-linguist\",\"3.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"5.7.0\",\"dependencies\":[[\"charlock-holmes\",\"0.6.9\"],[\"rugged\",\"0.19.0\"],[\"activesupport\",\"4.0.0\"],[\"gitlab-grit\",\"2.6.1\"],[\"gitlab-linguist\",\"3.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"5.6.0\",\"dependencies\":[[\"charlock-holmes\",\"0.6.9\"],[\"rugged\",\"0.19.0\"],[\"activesupport\",\"4.0.0\"],[\"gitlab-grit\",\"2.6.1\"],[\"gitlab-linguist\",\"3.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"5.5.0\",\"dependencies\":[[\"charlock-holmes\",\"0.6.9\"],[\"rugged\",\"0.19.0\"],[\"activesupport\",\"4.0.0\"],[\"gitlab-grit\",\"2.6.1\"],[\"gitlab-linguist\",\"3.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"5.4.0\",\"dependencies\":[[\"charlock-holmes\",\"0.6.9\"],[\"rugged\",\"0.19.0\"],[\"activesupport\",\"4.0.0\"],[\"gitlab-grit\",\"2.6.1\"],[\"gitlab-linguist\",\"3.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"5.3.0\",\"dependencies\":[[\"charlock-holmes\",\"0.6.9\"],[\"rugged\",\"0.19.0\"],[\"activesupport\",\"4.0.0\"],[\"gitlab-grit\",\"2.6.1\"],[\"gitlab-linguist\",\"3.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"5.2.0\",\"dependencies\":[[\"charlock-holmes\",\"0.6.9\"],[\"rugged\",\"0.19.0\"],[\"activesupport\",\"4.0.0\"],[\"gitlab-grit\",\"2.6.1\"],[\"gitlab-linguist\",\"3.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"5.1.0\",\"dependencies\":[[\"rugged\",\"0.19.0\"],[\"activesupport\",\"4.0.0\"],[\"gitlab-grit\",\"2.6.1\"],[\"gitlab-linguist\",\"3.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"5.0.0\",\"dependencies\":[[\"activesupport\",\"4.0.0\"],[\"gitlab-grit\",\"2.6.1\"],[\"gitlab-linguist\",\"3.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"4.1.0\",\"dependencies\":[[\"activesupport\",\"4.0.0\"],[\"gitlab-grit\",\"2.6.1\"],[\"gitlab-linguist\",\"2.9.5 || 3.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"4.0.0\",\"dependencies\":[[\"activesupport\",\"4.0.0\"],[\"gitlab-pygments.rb\",\"0.5.4\"],[\"gitlab-grit\",\"2.6.1\"],[\"gitlab-linguist\",\"2.9.5 || 3.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"3.1.0\",\"dependencies\":[[\"activesupport\",\"3.2.13 || 4.0.0\"],[\"gitlab-pygments.rb\",\"0.5.4\"],[\"gitlab-grit\",\"2.6.1\"],[\"gitlab-linguist\",\"2.9.5 || 3.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"3.0.1\",\"dependencies\":[[\"activesupport\",\"3.2.13 || 4.0.0\"],[\"gitlab-grit\",\"2.6.1\"],[\"github-linguist\",\"2.3.4\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"3.0.0\",\"dependencies\":[[\"activesupport\",\"3.2.13 || 4.0.0\"],[\"gitlab-pygments.rb\",\"0.5.4\"],[\"gitlab-grit\",\"2.6.1\"],[\"gitlab-linguist\",\"2.9.5 || 3.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.3.1\",\"dependencies\":[[\"activesupport\",\"3.2.13 || 4.0.0\"],[\"gitlab-grit\",\"2.5.2\"],[\"github-linguist\",\"2.3.4\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"2.3.1\",\"dependencies\":[[\"activesupport\",\"3.2.13 || 4.0.0\"],[\"gitlab-grit\",\"2.6.0\"],[\"github-linguist\",\"2.3.4\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"2.3.0\",\"dependencies\":[[\"activesupport\",\"3.2.13 || 4.0.0\"],[\"gitlab-grit\",\"2.6.0\"],[\"github-linguist\",\"2.9.4\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"2.2.0\",\"dependencies\":[[\"activesupport\",\"3.2.13 || 4.0.0\"],[\"gitlab-grit\",\"2.6.0\"],[\"github-linguist\",\"2.3.4\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.0.2\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"grit\",\"2.5.0\"],[\"grit-ext\",\"0.8.1\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.0.1\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"grit\",\"2.5.0\"],[\"grit-ext\",\"0.8.1\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.0.3\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"grit\",\"2.5.0\"],[\"grit-ext\",\"0.8.1\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.0.0\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"grit\",\"2.5.0\"],[\"grit-ext\",\"0.8.1\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.0.4\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"grit\",\"2.5.0\"],[\"grit-ext\",\"0.8.1\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.0.5\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"grit\",\"2.5.0\"],[\"grit-ext\",\"0.8.1\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.0.6\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"grit\",\"2.5.0\"],[\"grit-ext\",\"0.8.1\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.1.0\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"grit\",\"2.5.0\"],[\"grit-ext\",\"0.8.1\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.2.1\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"gitlab-grit\",\"2.5.1\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.2.0\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"gitlab-grit\",\"2.5.1\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.3.0\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"gitlab-grit\",\"2.5.1\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.4.0\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"gitlab-grit\",\"2.6.0\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"1.4.1\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"gitlab-grit\",\"2.6.0\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"2.0.1\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"gitlab-grit\",\"2.6.0\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"2.0.0\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"gitlab-grit\",\"2.6.0\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"2.1.0\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"gitlab-grit\",\"2.6.0\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-git\",\"number\":\"2.1.1\",\"dependencies\":[[\"github-linguist\",\"2.3.4\"],[\"gitlab-grit\",\"2.6.0\"],[\"activesupport\",\"3.2.13 || 4.0.0\"]]},\n  {\"name\":\"gitlab-meta\",\"number\":\"4.0.0\",\"dependencies\":[]},\n  {\"name\":\"gitlab-meta\",\"number\":\"2.8.0\",\"dependencies\":[]},\n  {\"name\":\"gitlab-meta\",\"number\":\"2.9.0\",\"dependencies\":[]},\n  {\"name\":\"gitlab-meta\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"gitlab-meta\",\"number\":\"3.1.0\",\"dependencies\":[]},\n  {\"name\":\"gitlab-meta\",\"number\":\"5.0.0\",\"dependencies\":[]},\n  {\"name\":\"gitlab-meta\",\"number\":\"6.0.0\",\"dependencies\":[]},\n  {\"name\":\"gitlab-omniauth-ldap\",\"number\":\"1.0.4\",\"dependencies\":[[\"rubyntlm\",\"0.1.1\"],[\"pyu-ruby-sasl\",\"0.3.1\"],[\"net-ldap\",\"0.3.1\"],[\"omniauth\",\"1.0.0\"]]},\n  {\"name\":\"gitlab-omniauth-ldap\",\"number\":\"1.0.2\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"net-ldap\",\"0.2.2\"],[\"pyu-ruby-sasl\",\"0.3.1\"],[\"rubyntlm\",\"0.1.1\"]]},\n  {\"name\":\"gitlab-omniauth-ldap\",\"number\":\"1.0.3\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"net-ldap\",\"0.3.1\"],[\"pyu-ruby-sasl\",\"0.3.1\"],[\"rubyntlm\",\"0.1.1\"]]},\n  {\"name\":\"gon\",\"number\":\"5.0.4\",\"dependencies\":[[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"5.0.3\",\"dependencies\":[[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"5.0.2\",\"dependencies\":[[\"json\",\"0.0.0 || 1.0.0\"]]},\n  {\"name\":\"gon\",\"number\":\"5.0.1\",\"dependencies\":[[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"5.0.0\",\"dependencies\":[[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"3.0.2\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"2.0.0\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"rabl\",null],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"2.1.2\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"gon\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"gon\",\"number\":\"2.0.4\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"rabl\",null],[\"jbuilder\",null],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"1.1.0\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"gon\",\"number\":\"1.1.1\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"gon\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"gon\",\"number\":\"2.2.0\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"2.0.6\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"rabl\",null],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"2.0.2\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"rabl\",null],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"gon\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"gon\",\"number\":\"2.0.1\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"rabl\",null],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"gon\",\"number\":\"1.1.3\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"gon\",\"number\":\"1.1.2\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"gon\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"gon\",\"number\":\"2.0.3\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"rabl\",null],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"2.0.5\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"rabl\",null],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"2.1.0\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"2.2.2\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"2.3.0\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"3.0.0\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"3.0.4\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"3.0.5\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"4.0.0\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"3.0.3\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"4.0.1\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"4.0.2\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"4.0.3\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"4.1.0\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"gon\",\"number\":\"4.1.1\",\"dependencies\":[[\"actionpack\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"json\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.6.1\",\"dependencies\":[[\"builder\",null],[\"virtus\",\"1.0.0\"],[\"hashie\",\"1.2.0 || 2.0.0\"],[\"multi-xml\",null],[\"multi-json\",\"1.3.2\"],[\"activesupport\",null],[\"rack-accept\",null],[\"rack-mount\",null],[\"rack\",\"1.3.0\"]]},\n  {\"name\":\"grape\",\"number\":\"0.6.0\",\"dependencies\":[[\"builder\",null],[\"virtus\",null],[\"hashie\",\"1.2.0 || 2.0.0\"],[\"multi-xml\",null],[\"multi-json\",\"1.3.2\"],[\"activesupport\",null],[\"rack-accept\",null],[\"rack-mount\",null],[\"rack\",\"1.3.0\"]]},\n  {\"name\":\"grape\",\"number\":\"0.1.5\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",null],[\"rack-jsonp\",null],[\"multi-json\",null],[\"multi-xml\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.2.1\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",null],[\"multi-json\",null],[\"multi-xml\",null],[\"hashie\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"grape\",\"number\":\"0.1.0\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",\"0.6.13\"],[\"rack-jsonp\",null],[\"json\",null],[\"multi-json\",null],[\"multi-xml\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.1.4\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",null],[\"rack-jsonp\",null],[\"multi-json\",null],[\"multi-xml\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.1.3\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",\"0.6.13\"],[\"rack-jsonp\",null],[\"json\",null],[\"multi-json\",null],[\"multi-xml\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.1.1\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",\"0.6.13\"],[\"rack-jsonp\",null],[\"json\",null],[\"multi-json\",null],[\"multi-xml\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.2.0\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",null],[\"multi-json\",null],[\"multi-xml\",null],[\"hashie\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"grape\",\"number\":\"0.2.2\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",null],[\"rack-accept\",null],[\"activesupport\",null],[\"multi-json\",\"1.3.2\"],[\"multi-xml\",null],[\"hashie\",\"1.2.0 || 2.0.0\"],[\"virtus\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.2.3\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",null],[\"rack-accept\",null],[\"activesupport\",null],[\"multi-json\",\"1.3.2\"],[\"multi-xml\",null],[\"hashie\",\"1.2.0 || 2.0.0\"],[\"virtus\",null],[\"builder\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.2.4\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",null],[\"rack-accept\",null],[\"activesupport\",null],[\"multi-json\",\"1.3.2\"],[\"multi-xml\",null],[\"hashie\",\"1.2.0 || 2.0.0\"],[\"virtus\",null],[\"builder\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.2.5\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",null],[\"rack-accept\",null],[\"activesupport\",null],[\"multi-json\",\"1.3.2\"],[\"multi-xml\",null],[\"hashie\",\"1.2.0 || 2.0.0\"],[\"virtus\",null],[\"builder\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.2.6\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",null],[\"rack-accept\",null],[\"activesupport\",null],[\"multi-json\",\"1.3.2\"],[\"multi-xml\",null],[\"hashie\",\"1.2.0 || 2.0.0\"],[\"virtus\",null],[\"builder\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.3.0\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",null],[\"rack-accept\",null],[\"activesupport\",null],[\"multi-json\",\"1.3.2\"],[\"multi-xml\",null],[\"hashie\",\"1.2.0 || 2.0.0\"],[\"virtus\",null],[\"builder\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.3.1\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",null],[\"rack-accept\",null],[\"activesupport\",null],[\"multi-json\",\"1.3.2\"],[\"multi-xml\",null],[\"hashie\",\"1.2.0 || 2.0.0\"],[\"virtus\",null],[\"builder\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.3.2\",\"dependencies\":[[\"rack\",null],[\"rack-mount\",null],[\"rack-accept\",null],[\"activesupport\",null],[\"multi-json\",\"1.3.2\"],[\"multi-xml\",null],[\"hashie\",\"1.2.0 || 2.0.0\"],[\"virtus\",null],[\"builder\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.4.0\",\"dependencies\":[[\"rack\",\"1.3.0\"],[\"rack-mount\",null],[\"rack-accept\",null],[\"activesupport\",null],[\"multi-json\",\"1.3.2\"],[\"multi-xml\",null],[\"hashie\",\"1.2.0 || 2.0.0\"],[\"virtus\",null],[\"builder\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.4.1\",\"dependencies\":[[\"rack\",\"1.3.0\"],[\"rack-mount\",null],[\"rack-accept\",null],[\"activesupport\",null],[\"multi-json\",\"1.3.2\"],[\"multi-xml\",null],[\"hashie\",\"1.2.0 || 2.0.0\"],[\"virtus\",null],[\"builder\",null]]},\n  {\"name\":\"grape\",\"number\":\"0.5.0\",\"dependencies\":[[\"rack\",\"1.3.0\"],[\"rack-mount\",null],[\"rack-accept\",null],[\"activesupport\",null],[\"multi-json\",\"1.3.2\"],[\"multi-xml\",null],[\"hashie\",\"1.2.0 || 2.0.0\"],[\"virtus\",null],[\"builder\",null]]},\n  {\"name\":\"growl\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"guard\",\"number\":\"2.6.0\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.7.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.5.1\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.6.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.5.0\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.6.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.4.0\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.1.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.3.0\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.1.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.2.5\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.1.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.2.4\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.1.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.2.3\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.1.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.2.2\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.1.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.2.1\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.1.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.2.0\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.1.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.1.1\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.1.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.1.0\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.1.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.0.5\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.0.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.0.4\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.0.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.0.3\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.0.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.0.2\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.0.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.0.1\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.0.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"2.0.0\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.0\"],[\"pry\",null],[\"listen\",\"2.0.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.8.3\",\"dependencies\":[[\"formatador\",null],[\"lumberjack\",\"1.0.2\"],[\"pry\",null],[\"listen\",\"1.3.0 || 2.0.0\"],[\"thor\",null]]},\n  {\"name\":\"guard\",\"number\":\"0.3.2\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.5.1\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"1.2.3\",\"dependencies\":[[\"thor\",null],[\"listen\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.1.0\",\"dependencies\":[[\"thor\",null],[\"listen\",null]]},\n  {\"name\":\"guard\",\"number\":\"0.3.1\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"1.3.2\",\"dependencies\":[[\"thor\",null],[\"listen\",null]]},\n  {\"name\":\"guard\",\"number\":\"0.6.3\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.8.0\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.6.1\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.2.0\",\"dependencies\":[[\"thor\",\"0.14.3\"],[\"open-gem\",\"1.4.2\"]]},\n  {\"name\":\"guard\",\"number\":\"0.9.2\",\"dependencies\":[[\"thor\",\"0.14.6\"],[\"ffi\",null]]},\n  {\"name\":\"guard\",\"number\":\"0.5.0\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.9.3\",\"dependencies\":[[\"thor\",\"0.14.6\"],[\"ffi\",null]]},\n  {\"name\":\"guard\",\"number\":\"0.8.7\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.8.4\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"1.0.3\",\"dependencies\":[[\"thor\",null],[\"ffi\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.1.1\",\"dependencies\":[[\"thor\",null],[\"listen\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.3.0\",\"dependencies\":[[\"thor\",null],[\"listen\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.3.1\",\"dependencies\":[[\"thor\",null],[\"listen\",null]]},\n  {\"name\":\"guard\",\"number\":\"0.8.2\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.1.0\",\"dependencies\":[[\"bundler\",\"1.0.2 || 2.0.0\"],[\"thor\",\"0.14.3\"],[\"sys-uname\",\"0.8.4\"],[\"growl\",\"1.0.3\"],[\"rb-inotify\",\"0.8.1\"],[\"libnotify\",\"0.1.3\"]]},\n  {\"name\":\"guard\",\"number\":\"0.8.8\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.8.1\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.1.1\",\"dependencies\":[[\"bundler\",\"1.0.2 || 2.0.0\"],[\"thor\",\"0.14.3\"],[\"sys-uname\",\"0.8.4\"],[\"growl\",\"1.0.3\"],[\"rb-inotify\",\"0.8.1\"],[\"libnotify\",\"0.1.3\"]]},\n  {\"name\":\"guard\",\"number\":\"0.3.4\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.6.0\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.10.0\",\"dependencies\":[[\"thor\",\"0.14.6\"],[\"ffi\",null]]},\n  {\"name\":\"guard\",\"number\":\"0.2.2\",\"dependencies\":[[\"thor\",\"0.14.3\"],[\"open-gem\",\"1.4.2\"]]},\n  {\"name\":\"guard\",\"number\":\"0.4.1\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.2.1\",\"dependencies\":[[\"thor\",\"0.14.3\"],[\"open-gem\",\"1.4.2\"]]},\n  {\"name\":\"guard\",\"number\":\"0.4.0\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"1.0.2\",\"dependencies\":[[\"thor\",\"0.14.6\"],[\"ffi\",null]]},\n  {\"name\":\"guard\",\"number\":\"0.8.6\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.6.2\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.9.4\",\"dependencies\":[[\"thor\",\"0.14.6\"],[\"ffi\",null]]},\n  {\"name\":\"guard\",\"number\":\"0.9.1\",\"dependencies\":[[\"thor\",\"0.14.6\"],[\"ffi\",null]]},\n  {\"name\":\"guard\",\"number\":\"0.7.0\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.8.3\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"1.0.0\",\"dependencies\":[[\"thor\",\"0.14.6\"],[\"ffi\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.0.1\",\"dependencies\":[[\"thor\",\"0.14.6\"],[\"ffi\",null]]},\n  {\"name\":\"guard\",\"number\":\"0.8.5\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.3.3\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.4.2\",\"dependencies\":[[\"thor\",\"0.14.6\"]]},\n  {\"name\":\"guard\",\"number\":\"0.9.0\",\"dependencies\":[[\"thor\",\"0.14.6\"],[\"ffi\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.2.0\",\"dependencies\":[[\"thor\",null],[\"listen\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.2.2\",\"dependencies\":[[\"thor\",null],[\"listen\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.3.3\",\"dependencies\":[[\"thor\",null],[\"listen\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.4.0\",\"dependencies\":[[\"thor\",null],[\"listen\",null]]},\n  {\"name\":\"guard\",\"number\":\"0.3.0\",\"dependencies\":[[\"thor\",\"0.14.6\"],[\"open-gem\",\"1.4.2\"]]},\n  {\"name\":\"guard\",\"number\":\"1.2.1\",\"dependencies\":[[\"thor\",null],[\"listen\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.5.0\",\"dependencies\":[[\"thor\",null],[\"listen\",null],[\"pry\",null],[\"lumberjack\",\"1.0.2\"]]},\n  {\"name\":\"guard\",\"number\":\"1.5.1\",\"dependencies\":[[\"thor\",null],[\"listen\",null],[\"pry\",null],[\"lumberjack\",\"1.0.2\"]]},\n  {\"name\":\"guard\",\"number\":\"1.5.2\",\"dependencies\":[[\"thor\",null],[\"listen\",null],[\"pry\",null],[\"lumberjack\",\"1.0.2\"]]},\n  {\"name\":\"guard\",\"number\":\"1.5.3\",\"dependencies\":[[\"thor\",null],[\"listen\",null],[\"pry\",null],[\"lumberjack\",\"1.0.2\"]]},\n  {\"name\":\"guard\",\"number\":\"1.5.4\",\"dependencies\":[[\"thor\",null],[\"listen\",null],[\"pry\",null],[\"lumberjack\",\"1.0.2\"]]},\n  {\"name\":\"guard\",\"number\":\"1.6.0\",\"dependencies\":[[\"thor\",null],[\"listen\",null],[\"pry\",null],[\"lumberjack\",\"1.0.2\"]]},\n  {\"name\":\"guard\",\"number\":\"1.6.1\",\"dependencies\":[[\"thor\",null],[\"listen\",null],[\"pry\",null],[\"lumberjack\",\"1.0.2\"]]},\n  {\"name\":\"guard\",\"number\":\"1.6.2\",\"dependencies\":[[\"thor\",null],[\"listen\",null],[\"pry\",null],[\"lumberjack\",\"1.0.2\"],[\"terminal-table\",\"1.4.3\"]]},\n  {\"name\":\"guard\",\"number\":\"1.7.0\",\"dependencies\":[[\"thor\",null],[\"listen\",null],[\"pry\",null],[\"lumberjack\",\"1.0.2\"],[\"formatador\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.8.0\",\"dependencies\":[[\"thor\",null],[\"listen\",\"1.0.0 || 2.0.0\"],[\"pry\",null],[\"lumberjack\",\"1.0.2\"],[\"formatador\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.8.1\",\"dependencies\":[[\"thor\",null],[\"listen\",\"1.0.0 || 2.0.0\"],[\"pry\",null],[\"lumberjack\",\"1.0.2\"],[\"formatador\",null]]},\n  {\"name\":\"guard\",\"number\":\"1.8.2\",\"dependencies\":[[\"thor\",null],[\"listen\",\"1.0.0 || 2.0.0\"],[\"pry\",null],[\"lumberjack\",\"1.0.2\"],[\"formatador\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.2.8\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.1.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.2.7\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.1.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.2.6\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.1.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.2.5\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.1.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.2.4\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.1.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.2.3\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.1.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.2.2\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.1.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.2.1\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.1.1\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.2.0\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.1.1\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.1.1\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.1.1\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.1.0\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.1.1\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.0.4\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.1.1\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.0.3\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.1.1\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.0.2\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.0.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.0.1\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.0.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"4.0.0\",\"dependencies\":[[\"rspec\",\"2.14.0\"],[\"guard\",\"2.0.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"3.1.0\",\"dependencies\":[[\"rspec\",\"2.13.0\"],[\"guard\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.5.10\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"1.0.1\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.1.6\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.7.2\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.7.1\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.5.11\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.4.0\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.5.3\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.1.1\",\"dependencies\":[[\"guard\",\"0.1.0 || 1.0.0 || 2.0.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.1.4\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.7.3\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"1.1.0\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"1.2.0\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"1.0.0\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.7.0\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.5.6\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.5.4\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.5.9\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.1.3\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.5.5\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.5.1\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.5.0\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.4.2\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.5.2\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.4.4\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.3.1\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.1.5\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.5.8\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.1.7\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.1.2\",\"dependencies\":[[\"guard\",\"0.1.0 || 1.0.0 || 2.0.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.1.8\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.3.0\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.1.0\",\"dependencies\":[[\"guard\",\"0.1.0 || 1.0.0 || 2.0.0\"],[\"rspec\",\"2.0.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.2.0\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.4.5\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.4.1\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.4.3\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.6.0\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"1.2.1\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.0.0\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.1.0\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.5.7\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"0.1.9\",\"dependencies\":[[\"guard\",null]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.1.1\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.1.2\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.2.0\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.2.1\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.2.2\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.3.0\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.3.1\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"3.0.3\",\"dependencies\":[[\"guard\",\"1.8.0 || 2.0.0\"],[\"rspec\",\"2.13.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.3.2\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.3.3\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.4.0\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.4.1\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.5.0\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.5.1\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.5.2\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.5.3\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.5.4\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"2.6.0\",\"dependencies\":[[\"guard\",\"1.8.0 || 2.0.0\"],[\"rspec\",\"2.13.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"3.0.0\",\"dependencies\":[[\"guard\",\"1.8.0 || 2.0.0\"],[\"rspec\",\"2.13.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"3.0.1\",\"dependencies\":[[\"guard\",\"1.8.0 || 2.0.0\"],[\"rspec\",\"2.13.0\"]]},\n  {\"name\":\"guard-rspec\",\"number\":\"3.0.2\",\"dependencies\":[[\"guard\",\"1.8.0 || 2.0.0\"],[\"rspec\",\"2.13.0\"]]},\n  {\"name\":\"guard-spinach\",\"number\":\"0.0.3\",\"dependencies\":[[\"spinach\",null],[\"guard\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"guard-spinach\",\"number\":\"0.0.2\",\"dependencies\":[[\"guard\",\"1.1.0 || 2.0.0\"],[\"spinach\",null]]},\n  {\"name\":\"guard-spinach\",\"number\":\"0.0.1\",\"dependencies\":[[\"guard\",null],[\"spinach\",null]]},\n  {\"name\":\"haml\",\"number\":\"4.0.5\",\"dependencies\":[[\"tilt\",null]]},\n  {\"name\":\"haml\",\"number\":\"4.0.4\",\"dependencies\":[[\"tilt\",null]]},\n  {\"name\":\"haml\",\"number\":\"3.0.23\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.13\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.6\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.8.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.4\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.18\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.9\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.9\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.12\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.18\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.1\",\"dependencies\":[[\"yard\",null],[\"maruku\",null]]},\n  {\"name\":\"haml\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.3\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.13\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.16\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.5.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.8.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.16\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.17\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.3\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.4\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.0.5\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.7\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.24\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.11\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.14\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.20\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.7.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.9\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.5\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.7\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.8\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.4\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.2\",\"dependencies\":[[\"yard\",null],[\"maruku\",null]]},\n  {\"name\":\"haml\",\"number\":\"3.0.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.8\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.10\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.6\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.24\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.5\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.3\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.14\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.5\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.0\",\"dependencies\":[[\"yard\",null],[\"maruku\",null]]},\n  {\"name\":\"haml\",\"number\":\"2.2.22\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.23\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.21\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.15\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.11\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.25\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.17\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.21\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.6\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.10\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.5\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.19\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.22\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.15\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.12\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.6\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.7\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.8.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.7.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.10\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.8\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"4.0.0\",\"dependencies\":[[\"tilt\",null]]},\n  {\"name\":\"haml\",\"number\":\"4.0.1\",\"dependencies\":[[\"tilt\",null]]},\n  {\"name\":\"haml\",\"number\":\"4.0.2\",\"dependencies\":[[\"tilt\",null]]},\n  {\"name\":\"haml\",\"number\":\"4.0.3\",\"dependencies\":[[\"tilt\",null]]},\n  {\"name\":\"haml-rails\",\"number\":\"0.5.3\",\"dependencies\":[[\"railties\",\"4.0.1\"],[\"actionpack\",\"4.0.1\"],[\"activesupport\",\"4.0.1\"],[\"haml\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"haml-rails\",\"number\":\"0.5.2\",\"dependencies\":[[\"railties\",\"4.0.1\"],[\"actionpack\",\"4.0.1\"],[\"activesupport\",\"4.0.1\"],[\"haml\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"haml-rails\",\"number\":\"0.5.1\",\"dependencies\":[[\"railties\",\"4.0.0\"],[\"actionpack\",\"4.0.0\"],[\"activesupport\",\"4.0.0\"],[\"haml\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"haml-rails\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"haml-rails\",\"number\":\"0.3.2\",\"dependencies\":[[\"haml\",\"3.0.18 || 4.0.0\"],[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"haml-rails\",\"number\":\"0.3.1\",\"dependencies\":[[\"haml\",\"3.0.18 || 4.0.0\"],[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"haml-rails\",\"number\":\"0.2.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"],[\"haml\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"haml-rails\",\"number\":\"0.3.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"],[\"haml\",\"3.0.18 || 4.0.0\"]]},\n  {\"name\":\"haml-rails\",\"number\":\"0.3.3\",\"dependencies\":[[\"haml\",\"3.0.18 || 4.0.0\"],[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"haml-rails\",\"number\":\"0.3.4\",\"dependencies\":[[\"haml\",\"3.0.0 || 4.0.0\"],[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"haml-rails\",\"number\":\"0.3.5\",\"dependencies\":[[\"haml\",\"3.1.0 || 4.0.0\"],[\"activesupport\",\"3.1.0 || 4.0.0\"],[\"actionpack\",\"3.1.0 || 4.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"haml-rails\",\"number\":\"0.4.0\",\"dependencies\":[[\"haml\",\"3.1.0 || 4.0.0\"],[\"activesupport\",\"3.1.0 || 4.0.0\"],[\"actionpack\",\"3.1.0 || 4.0.0\"],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"hashie\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"0.1.6\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"0.1.8\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"hashie\",\"number\":\"2.0.5\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"hike\",\"number\":\"1.2.3\",\"dependencies\":[]},\n  {\"name\":\"hipchat\",\"number\":\"1.1.0\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"1.0.1\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"1.0.0\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.14.0\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.13.0\",\"dependencies\":[[\"httparty\",\"0.11.0\"]]},\n  {\"name\":\"hipchat\",\"number\":\"0.2.2\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.0.3\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.4.1\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.0.2\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.2.0\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.0.1\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.1.0\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.2.1\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.3.0\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.4.0\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.5.0\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.6.0\",\"dependencies\":[[\"httparty\",null],[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.6.1\",\"dependencies\":[[\"httparty\",null],[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.7.0\",\"dependencies\":[[\"httparty\",null],[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.12.0\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.8.0\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.9.0\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.10.0\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.10.1\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"hipchat\",\"number\":\"0.11.0\",\"dependencies\":[[\"httparty\",null]]},\n  {\"name\":\"http-parser.rb\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"http-parser.rb\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"http-parser.rb\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"http-parser.rb\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"http-parser.rb\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"httparty\",\"number\":\"0.13.0\",\"dependencies\":[[\"multi-xml\",null],[\"json\",\"1.8.0\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.12.0\",\"dependencies\":[[\"multi-xml\",null],[\"json\",\"1.8.0\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.8.1\",\"dependencies\":[[\"multi-json\",null],[\"multi-xml\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.7.3\",\"dependencies\":[[\"crack\",\"=0.1.8\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.6.0\",\"dependencies\":[[\"crack\",\"=0.1.7\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.2.6\",\"dependencies\":[[\"json\",\"1.1.0\"],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.4.4\",\"dependencies\":[[\"crack\",null],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.2.7\",\"dependencies\":[[\"json\",\"1.1.0\"],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.4.3\",\"dependencies\":[[\"crack\",null],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.2.8\",\"dependencies\":[[\"json\",\"1.1.0\"],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.7.4\",\"dependencies\":[[\"crack\",\"=0.1.8\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.5.0\",\"dependencies\":[[\"crack\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.7.6\",\"dependencies\":[[\"crack\",\"=0.1.8\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.7.7\",\"dependencies\":[[\"crack\",\"=0.1.8\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.2.1\",\"dependencies\":[[\"json\",\"1.1.0\"],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.2.9\",\"dependencies\":[[\"json\",\"1.1.0\"],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.5.2\",\"dependencies\":[[\"crack\",\"=0.1.6\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.2.2\",\"dependencies\":[[\"json\",\"1.1.0\"],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.2.4\",\"dependencies\":[[\"json\",\"1.1.0\"],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.3.0\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.2.5\",\"dependencies\":[[\"json\",\"1.1.0\"],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.1.1\",\"dependencies\":[[\"activesupport\",\"2.1.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.1.2\",\"dependencies\":[[\"activesupport\",\"2.1.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.2.0\",\"dependencies\":[[\"json\",\"1.1.0\"],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.1.0\",\"dependencies\":[[\"activesupport\",\"2.1.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.1.6\",\"dependencies\":[[\"activesupport\",\"2.1.0 || 3.0.0 || 4.0.0\"],[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.4.0\",\"dependencies\":[[\"jnunemaker-crack\",null],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.7.2\",\"dependencies\":[[\"crack\",\"=0.1.8\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.2.3\",\"dependencies\":[[\"json\",\"1.1.0\"],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.7.0\",\"dependencies\":[[\"crack\",\"=0.1.8\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.7.8\",\"dependencies\":[[\"crack\",\"=0.1.8\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.8.0\",\"dependencies\":[[\"multi-json\",null],[\"multi-xml\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.8.3\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"multi-xml\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.9.0\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"multi-xml\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.2.10\",\"dependencies\":[[\"json\",\"1.1.0\"],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.1.8\",\"dependencies\":[[\"activesupport\",\"2.1.0 || 3.0.0 || 4.0.0\"],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.4.1\",\"dependencies\":[[\"jnunemaker-crack\",null],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.4.5\",\"dependencies\":[[\"crack\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.1.5\",\"dependencies\":[[\"activesupport\",\"2.1.0 || 3.0.0 || 4.0.0\"],[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.4.2\",\"dependencies\":[[\"crack\",null],[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.3.1\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.1.3\",\"dependencies\":[[\"activesupport\",\"2.1.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.6.1\",\"dependencies\":[[\"crack\",\"=0.1.8\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.1.7\",\"dependencies\":[[\"activesupport\",\"2.1.0 || 3.0.0 || 4.0.0\"],[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.5.1\",\"dependencies\":[[\"crack\",\"=0.1.5\"]]},\n  {\"name\":\"httparty\",\"number\":\"0.8.2\",\"dependencies\":[[\"multi-json\",null],[\"multi-xml\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.10.0\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"multi-xml\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.10.1\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"multi-xml\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.10.2\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"multi-xml\",null]]},\n  {\"name\":\"httparty\",\"number\":\"0.11.0\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"multi-xml\",null]]},\n  {\"name\":\"httpauth\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"httpauth\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"httpauth\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.6.9\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.6.8\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.3.7\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.3.6\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.3.4\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.3.5\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.6.4\",\"dependencies\":[]},\n  {\"name\":\"i18n\",\"number\":\"0.6.5\",\"dependencies\":[]},\n  {\"name\":\"ice-nine\",\"number\":\"0.11.0\",\"dependencies\":[]},\n  {\"name\":\"ice-nine\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"ice-nine\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"ice-nine\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"ice-nine\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"ice-nine\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"ice-nine\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"ice-nine\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"ice-nine\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"ice-nine\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"ice-nine\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"jasmine\",\"number\":\"2.0.0\",\"dependencies\":[[\"phantomjs\",null],[\"rake\",null],[\"rack\",\"1.2.1\"],[\"jasmine-core\",\"2.0.0\"]]},\n  {\"name\":\"jasmine\",\"number\":\"1.0.0\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.1.5 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"],[\"json-pure\",\"1.4.3\"]]},\n  {\"name\":\"jasmine\",\"number\":\"1.0.2\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"rspec\",\"1.3.1 || 2.0.0\"],[\"json-pure\",\"1.4.3\"],[\"selenium-webdriver\",null]]},\n  {\"name\":\"jasmine\",\"number\":\"0.10.2\",\"dependencies\":[[\"rspec\",\"1.1.5 || 2.0.0\"],[\"json\",\"1.1.9\"],[\"rack\",\"1.0.0\"],[\"thin\",\"1.2.4\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"]]},\n  {\"name\":\"jasmine\",\"number\":\"0.11.0\",\"dependencies\":[[\"rspec\",\"1.1.5 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"]]},\n  {\"name\":\"jasmine\",\"number\":\"0.4.3\",\"dependencies\":[[\"rspec\",\"1.1.5 || 2.0.0\"],[\"json\",\"1.1.9\"],[\"rack\",\"1.0.0\"],[\"thin\",\"1.2.4\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"]]},\n  {\"name\":\"jasmine\",\"number\":\"0.4.0\",\"dependencies\":[[\"rspec\",\"1.1.5 || 2.0.0\"],[\"json\",\"1.1.9\"],[\"rack\",\"1.0.0\"],[\"thin\",\"1.2.4\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"]]},\n  {\"name\":\"jasmine\",\"number\":\"1.0.1\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.1.5 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"],[\"json-pure\",\"1.4.3\"]]},\n  {\"name\":\"jasmine\",\"number\":\"0.4.1\",\"dependencies\":[[\"rspec\",\"1.1.5 || 2.0.0\"],[\"json\",\"1.1.9\"],[\"rack\",\"1.0.0\"],[\"thin\",\"1.2.4\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"]]},\n  {\"name\":\"jasmine\",\"number\":\"0.11.1\",\"dependencies\":[[\"rspec\",\"1.1.5 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"]]},\n  {\"name\":\"jasmine\",\"number\":\"0.4.5\",\"dependencies\":[[\"rspec\",\"1.1.5 || 2.0.0\"],[\"json\",\"1.1.9\"],[\"rack\",\"1.0.0\"],[\"thin\",\"1.2.4\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"]]},\n  {\"name\":\"jasmine\",\"number\":\"0.4.6\",\"dependencies\":[[\"rspec\",\"1.1.5 || 2.0.0\"],[\"json\",\"1.1.9\"],[\"rack\",\"1.0.0\"],[\"thin\",\"1.2.4\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"]]},\n  {\"name\":\"jasmine\",\"number\":\"0.4.4\",\"dependencies\":[[\"rspec\",\"1.1.5 || 2.0.0\"],[\"json\",\"1.1.9\"],[\"rack\",\"1.0.0\"],[\"thin\",\"1.2.4\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"]]},\n  {\"name\":\"jasmine\",\"number\":\"0.10.4\",\"dependencies\":[[\"rspec\",\"1.1.5 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"]]},\n  {\"name\":\"jasmine\",\"number\":\"0.4.2\",\"dependencies\":[[\"rspec\",\"1.1.5 || 2.0.0\"],[\"json\",\"1.1.9\"],[\"rack\",\"1.0.0\"],[\"thin\",\"1.2.4\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"]]},\n  {\"name\":\"jasmine\",\"number\":\"0.10.3\",\"dependencies\":[[\"rspec\",\"1.1.5 || 2.0.0\"],[\"json\",\"1.1.9\"],[\"rack\",\"1.0.0\"],[\"thin\",\"1.2.4\"],[\"selenium-rc\",\"2.1.0\"],[\"selenium-client\",\"1.2.17\"]]},\n  {\"name\":\"jasmine\",\"number\":\"1.1.0\",\"dependencies\":[[\"jasmine-core\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rspec\",\"1.3.1 || 2.0.0\"],[\"selenium-webdriver\",null]]},\n  {\"name\":\"jasmine\",\"number\":\"1.1.2\",\"dependencies\":[[\"jasmine-core\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.1.0\"],[\"rspec\",\"1.3.1 || 2.0.0\"],[\"selenium-webdriver\",null]]},\n  {\"name\":\"jasmine\",\"number\":\"1.2.0\",\"dependencies\":[[\"jasmine-core\",\"1.2.0 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"rspec\",\"1.3.1 || 2.0.0\"],[\"selenium-webdriver\",null]]},\n  {\"name\":\"jasmine\",\"number\":\"1.2.1\",\"dependencies\":[[\"jasmine-core\",\"1.2.0 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"rspec\",\"1.3.1 || 2.0.0\"],[\"selenium-webdriver\",null]]},\n  {\"name\":\"jasmine\",\"number\":\"1.3.0\",\"dependencies\":[[\"jasmine-core\",\"1.3.0 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"rspec\",\"1.3.1 || 2.0.0\"],[\"selenium-webdriver\",null]]},\n  {\"name\":\"jasmine\",\"number\":\"1.3.1\",\"dependencies\":[[\"jasmine-core\",\"1.3.1 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"rspec\",\"1.3.1 || 2.0.0\"],[\"selenium-webdriver\",null]]},\n  {\"name\":\"jasmine\",\"number\":\"1.3.2\",\"dependencies\":[[\"jasmine-core\",\"1.3.1 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"rspec\",\"1.3.1 || 2.0.0\"],[\"selenium-webdriver\",null]]},\n  {\"name\":\"jasmine-core\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"jasmine-core\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"jasmine-core\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"jasmine-core\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"jasmine-core\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.4.7\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.4.5\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.1.6\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.1.7\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.2.3\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.2.4\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.2.5\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"jquery-atwho-rails\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"jquery-rails\",\"number\":\"3.1.0\",\"dependencies\":[[\"thor\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.5\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.17\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.19\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"2.0.1\",\"dependencies\":[[\"railties\",\"3.2.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"2.1.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.14\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.18\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"2.1.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.16\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"2.0.3\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.1\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.4\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.2\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"2.0.2\",\"dependencies\":[[\"railties\",\"3.2.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"0.2.6\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.4\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.6\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"0.1.1\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"0.2.2\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"0.1.2\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.7\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"0.2.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.10\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"0.2.4\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.13\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"0.2.5\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.4\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.11\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.12\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.9\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"0.2.1\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.3\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"0.2.3\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.8\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"0.1.3\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"1.0.15\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"0.2.7\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"],[\"thor\",\"0.14.4\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"2.1.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"2.1.3\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"jquery-rails\",\"number\":\"2.1.4\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",null]]},\n  {\"name\":\"jquery-rails\",\"number\":\"2.2.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",null]]},\n  {\"name\":\"jquery-rails\",\"number\":\"2.2.1\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",null]]},\n  {\"name\":\"jquery-rails\",\"number\":\"3.0.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",null]]},\n  {\"name\":\"jquery-rails\",\"number\":\"2.2.2\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",null]]},\n  {\"name\":\"jquery-rails\",\"number\":\"2.3.0\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",null]]},\n  {\"name\":\"jquery-rails\",\"number\":\"3.0.1\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",null]]},\n  {\"name\":\"jquery-rails\",\"number\":\"3.0.2\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",null]]},\n  {\"name\":\"jquery-rails\",\"number\":\"3.0.3\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",null]]},\n  {\"name\":\"jquery-rails\",\"number\":\"3.0.4\",\"dependencies\":[[\"railties\",\"3.0.0 || 4.0.0\"],[\"thor\",null]]},\n  {\"name\":\"jquery-turbolinks\",\"number\":\"2.0.2\",\"dependencies\":[[\"turbolinks\",null],[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-turbolinks\",\"number\":\"0.1.1\",\"dependencies\":[[\"rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-turbolinks\",\"number\":\"0.2.0\",\"dependencies\":[[\"rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-turbolinks\",\"number\":\"0.2.1\",\"dependencies\":[[\"rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-turbolinks\",\"number\":\"1.0.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"turbolinks\",null]]},\n  {\"name\":\"jquery-turbolinks\",\"number\":\"2.0.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"turbolinks\",null]]},\n  {\"name\":\"jquery-turbolinks\",\"number\":\"2.0.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"turbolinks\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"4.2.0\",\"dependencies\":[[\"railties\",\"3.2.16 || 4.0.0\"]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"4.1.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"4.1.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"4.1.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"4.0.5\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"0.4.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"2.0.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"0.1.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"0.2.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"0.0.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"0.0.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"0.2.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"0.5.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"1.1.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"0.2.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"0.3.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"0.4.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"1.0.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"1.1.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"2.0.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"2.0.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"3.0.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"3.0.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"4.0.0\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"4.0.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"4.0.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"4.0.3\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"jquery-ui-rails\",\"number\":\"4.0.4\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"],[\"jquery-rails\",null]]},\n  {\"name\":\"json\",\"number\":\"1.8.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.5\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.5\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.5.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.6\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.2.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.2.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.5.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.6\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.7\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.9\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.5.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.8\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.7\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.5\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.5\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.6\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.6\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.5.5\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.8\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.7\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.8.0\",\"dependencies\":[]},\n  {\"name\":\"jwt\",\"number\":\"0.1.11\",\"dependencies\":[[\"multi-json\",\"1.5.0\"]]},\n  {\"name\":\"jwt\",\"number\":\"0.1.10\",\"dependencies\":[[\"multi-json\",\"1.5.0\"]]},\n  {\"name\":\"jwt\",\"number\":\"0.1.2\",\"dependencies\":[[\"json\",\"1.2.4\"]]},\n  {\"name\":\"jwt\",\"number\":\"0.1.3\",\"dependencies\":[[\"json\",\"1.2.4\"]]},\n  {\"name\":\"jwt\",\"number\":\"0.1.1\",\"dependencies\":[[\"json\",\"1.2.4\"]]},\n  {\"name\":\"jwt\",\"number\":\"0.1.4\",\"dependencies\":[[\"json\",\"1.2.4\"]]},\n  {\"name\":\"jwt\",\"number\":\"0.1.5\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"jwt\",\"number\":\"0.1.6\",\"dependencies\":[[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"jwt\",\"number\":\"0.1.7\",\"dependencies\":[[\"multi-json\",\"1.5.0\"]]},\n  {\"name\":\"jwt\",\"number\":\"0.1.8\",\"dependencies\":[[\"multi-json\",\"1.5.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.15.1\",\"dependencies\":[[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.15.0\",\"dependencies\":[[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.12.3\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.9.8\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.9.1\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.14.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.6.1\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.9.2\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.4.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.3.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.10.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.10.3\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.13.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.12.4\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.9.3\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.8.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.12.1\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.12.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.11.0\",\"dependencies\":[[\"kaminari\",null]]},\n  {\"name\":\"kaminari\",\"number\":\"0.10.4\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.10.1\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.9.13\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.9.7\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.9.12\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.6.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.2.1\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.9.10\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.10.2\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.9.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.9.5\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.2.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.7.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.9.4\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.9.9\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.5.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.1.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.9.6\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.12.2\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kaminari\",\"number\":\"0.14.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"kgio\",\"number\":\"2.9.2\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.9.1\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.9.0\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.8.1\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.4.1\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.6.0\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.3.3\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.5.0\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.4.0\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.4.2\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.7.0\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.3.2\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.3.0\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.3.1\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.7.1\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.7.2\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.7.3\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.7.4\",\"dependencies\":[]},\n  {\"name\":\"kgio\",\"number\":\"2.8.0\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"2.4.2\",\"dependencies\":[[\"addressable\",\"2.3.0\"]]},\n  {\"name\":\"launchy\",\"number\":\"2.4.1\",\"dependencies\":[[\"addressable\",\"2.3.0\"]]},\n  {\"name\":\"launchy\",\"number\":\"2.4.0\",\"dependencies\":[[\"addressable\",\"2.3.0\"]]},\n  {\"name\":\"launchy\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"0.3.7\",\"dependencies\":[[\"rake\",null],[\"configuration\",null]]},\n  {\"name\":\"launchy\",\"number\":\"0.3.5\",\"dependencies\":[[\"rake\",null],[\"configuration\",null]]},\n  {\"name\":\"launchy\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"2.0.5\",\"dependencies\":[[\"addressable\",\"2.2.6\"]]},\n  {\"name\":\"launchy\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"0.3.3\",\"dependencies\":[[\"rake\",null],[\"configuration\",null]]},\n  {\"name\":\"launchy\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"0.4.0\",\"dependencies\":[[\"rake\",null],[\"configuration\",null]]},\n  {\"name\":\"launchy\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"2.0.4\",\"dependencies\":[[\"addressable\",\"2.2.6\"]]},\n  {\"name\":\"launchy\",\"number\":\"2.1.2\",\"dependencies\":[[\"addressable\",\"2.3.0\"]]},\n  {\"name\":\"launchy\",\"number\":\"2.1.0\",\"dependencies\":[[\"addressable\",\"2.2.6\"]]},\n  {\"name\":\"launchy\",\"number\":\"2.1.1\",\"dependencies\":[[\"addressable\",\"2.3.0\"]]},\n  {\"name\":\"launchy\",\"number\":\"2.2.0\",\"dependencies\":[[\"addressable\",\"2.3.0\"]]},\n  {\"name\":\"launchy\",\"number\":\"2.3.0\",\"dependencies\":[[\"addressable\",\"2.3.0\"]]},\n  {\"name\":\"letter-opener\",\"number\":\"1.2.0\",\"dependencies\":[[\"launchy\",\"2.2.0\"]]},\n  {\"name\":\"letter-opener\",\"number\":\"0.0.2\",\"dependencies\":[[\"launchy\",null]]},\n  {\"name\":\"letter-opener\",\"number\":\"0.1.0\",\"dependencies\":[[\"launchy\",\"2.0.4\"]]},\n  {\"name\":\"letter-opener\",\"number\":\"0.0.1\",\"dependencies\":[[\"launchy\",null]]},\n  {\"name\":\"letter-opener\",\"number\":\"1.0.0\",\"dependencies\":[[\"launchy\",\"2.0.4\"]]},\n  {\"name\":\"letter-opener\",\"number\":\"1.1.0\",\"dependencies\":[[\"launchy\",\"2.2.0\"]]},\n  {\"name\":\"letter-opener\",\"number\":\"1.1.1\",\"dependencies\":[[\"launchy\",\"2.2.0\"]]},\n  {\"name\":\"letter-opener\",\"number\":\"1.1.2\",\"dependencies\":[[\"launchy\",\"2.2.0\"]]},\n  {\"name\":\"libv8\",\"number\":\"3.10.8\",\"dependencies\":[]},\n  {\"name\":\"libv8\",\"number\":\"3.11.8\",\"dependencies\":[]},\n  {\"name\":\"libv8\",\"number\":\"3.16.14\",\"dependencies\":[]},\n  {\"name\":\"listen\",\"number\":\"2.7.1\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid-io\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.7.0\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid-io\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.6.2\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid-io\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.6.1\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid-io\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.6.0\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid-io\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.5.0\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid-io\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.4.1\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.4.0\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.3.1\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.2.0\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.1.2\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.1.1\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.1.0\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.0.4\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.0.3\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.0.2\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.0.1\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"2.0.0\",\"dependencies\":[[\"rb-inotify\",null],[\"rb-fsevent\",null],[\"celluloid\",null]]},\n  {\"name\":\"listen\",\"number\":\"0.4.4\",\"dependencies\":[[\"rb-fsevent\",\"0.9.1\"],[\"rb-inotify\",\"0.8.8\"],[\"rb-fchange\",\"0.0.5\"]]},\n  {\"name\":\"listen\",\"number\":\"0.4.2\",\"dependencies\":[[\"rb-fsevent\",\"0.9.1\"],[\"rb-inotify\",\"0.8.8\"],[\"rb-fchange\",\"0.0.5\"]]},\n  {\"name\":\"listen\",\"number\":\"0.3.3\",\"dependencies\":[[\"rb-fsevent\",\"0.9.0\"],[\"rb-inotify\",\"0.8.8\"],[\"rb-fchange\",\"0.0.5\"]]},\n  {\"name\":\"listen\",\"number\":\"0.4.0\",\"dependencies\":[[\"rb-fsevent\",\"0.9.1\"],[\"rb-inotify\",\"0.8.8\"],[\"rb-fchange\",\"0.0.5\"]]},\n  {\"name\":\"listen\",\"number\":\"0.3.1\",\"dependencies\":[[\"rb-fsevent\",\"0.9.0\"],[\"rb-inotify\",\"0.8.8\"],[\"rb-fchange\",\"0.0.5\"]]},\n  {\"name\":\"listen\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"listen\",\"number\":\"0.3.0\",\"dependencies\":[[\"rb-fsevent\",\"0.9.0\"],[\"rb-inotify\",\"0.8.8\"],[\"rb-fchange\",\"0.0.5\"]]},\n  {\"name\":\"listen\",\"number\":\"0.3.2\",\"dependencies\":[[\"rb-fsevent\",\"0.9.0\"],[\"rb-inotify\",\"0.8.8\"],[\"rb-fchange\",\"0.0.5\"]]},\n  {\"name\":\"listen\",\"number\":\"0.4.5\",\"dependencies\":[[\"rb-fsevent\",\"0.9.1\"],[\"rb-inotify\",\"0.8.8\"],[\"rb-fchange\",\"0.0.5\"]]},\n  {\"name\":\"listen\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"listen\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"listen\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"listen\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"listen\",\"number\":\"0.4.6\",\"dependencies\":[[\"rb-fsevent\",\"0.9.1\"],[\"rb-inotify\",\"0.8.8\"],[\"rb-fchange\",\"0.0.5\"]]},\n  {\"name\":\"listen\",\"number\":\"0.2.0\",\"dependencies\":[[\"rb-fsevent\",\"0.9.0\"],[\"rb-inotify\",\"0.8.8\"],[\"rb-fchange\",\"0.0.5\"]]},\n  {\"name\":\"listen\",\"number\":\"0.4.1\",\"dependencies\":[[\"rb-fsevent\",\"0.9.1\"],[\"rb-inotify\",\"0.8.8\"],[\"rb-fchange\",\"0.0.5\"]]},\n  {\"name\":\"listen\",\"number\":\"0.4.3\",\"dependencies\":[[\"rb-fsevent\",\"0.9.1\"],[\"rb-inotify\",\"0.8.8\"],[\"rb-fchange\",\"0.0.5\"]]},\n  {\"name\":\"listen\",\"number\":\"0.4.7\",\"dependencies\":[[\"rb-fsevent\",\"0.9.1\"],[\"rb-inotify\",\"0.8.8\"],[\"rb-fchange\",\"0.0.5\"]]},\n  {\"name\":\"listen\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"listen\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"listen\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"listen\",\"number\":\"0.7.2\",\"dependencies\":[]},\n  {\"name\":\"listen\",\"number\":\"1.3.1\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"0.7.3\",\"dependencies\":[]},\n  {\"name\":\"listen\",\"number\":\"1.0.0\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.0.2\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.0.1\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.0.3\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.1.0\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.1.1\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.1.2\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.1.3\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.1.4\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.1.5\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.1.6\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.2.0\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.2.1\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.2.2\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.2.3\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"listen\",\"number\":\"1.3.0\",\"dependencies\":[[\"rb-fsevent\",null],[\"rb-inotify\",null],[\"rb-kqueue\",null]]},\n  {\"name\":\"lumberjack\",\"number\":\"1.0.5\",\"dependencies\":[]},\n  {\"name\":\"lumberjack\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"lumberjack\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"lumberjack\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"lumberjack\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"lumberjack\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"mail\",\"number\":\"2.1.5\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.3.0\",\"dependencies\":[[\"tlsmail\",null],[\"treetop\",\"1.4.0\"],[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.5\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",null],[\"treetop\",\"1.4.5\"]]},\n  {\"name\":\"mail\",\"number\":\"2.2.14\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.4.1\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.5.3\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.2.5\",\"dependencies\":[[\"treetop\",\"1.4.0\"],[\"activesupport\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"mail\",\"number\":\"2.2.15\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.17\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.18\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.4\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",null],[\"treetop\",\"1.4.5\"]]},\n  {\"name\":\"mail\",\"number\":\"1.3.2\",\"dependencies\":[[\"tlsmail\",null],[\"treetop\",\"1.4.0\"],[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.2.1\",\"dependencies\":[[\"treetop\",\"1.4.0\"],[\"activesupport\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"mail\",\"number\":\"1.4.3\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.13\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.11\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",\"0.5.0\"]]},\n  {\"name\":\"mail\",\"number\":\"2.2.6\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",null],[\"treetop\",\"1.4.5\"]]},\n  {\"name\":\"mail\",\"number\":\"2.2.16\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.7\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",null],[\"treetop\",\"1.4.5\"]]},\n  {\"name\":\"mail\",\"number\":\"2.4.0\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.10\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",\"0.4.1\"]]},\n  {\"name\":\"mail\",\"number\":\"2.1.1\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.1.2\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.5.2\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.2.9\",\"dependencies\":[[\"tlsmail\",null],[\"treetop\",\"1.4.0\"],[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.9\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",\"0.4.1\"]]},\n  {\"name\":\"mail\",\"number\":\"1.3.4\",\"dependencies\":[[\"tlsmail\",null],[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.3\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",null],[\"treetop\",\"1.4.5\"]]},\n  {\"name\":\"mail\",\"number\":\"1.3.5\",\"dependencies\":[[\"tlsmail\",null],[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.2.8\",\"dependencies\":[[\"tlsmail\",null],[\"treetop\",\"1.4.0\"],[\"activesupport\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.2\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",null],[\"treetop\",\"1.4.5\"]]},\n  {\"name\":\"mail\",\"number\":\"2.1.0\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.12\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.3.2\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.4.3\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.3.3\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.0\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null],[\"treetop\",\"1.4.5\"]]},\n  {\"name\":\"mail\",\"number\":\"1.5.4\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.5.1\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.4.1\",\"dependencies\":[[\"tlsmail\",null],[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.2.1\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null],[\"treetop\",\"1.4.5\"]]},\n  {\"name\":\"mail\",\"number\":\"2.1.3\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.0.0\",\"dependencies\":[[\"treetop\",\"1.4.0\"],[\"mime-types\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"mail\",\"number\":\"2.3.0\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.1.0\",\"dependencies\":[[\"treetop\",\"1.4.0\"],[\"activesupport\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"mail\",\"number\":\"2.2.19\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.3.1\",\"dependencies\":[[\"tlsmail\",null],[\"treetop\",\"1.4.0\"],[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.2.6\",\"dependencies\":[[\"tlsmail\",null],[\"treetop\",null],[\"activesupport\",null],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.3.3\",\"dependencies\":[[\"treetop\",null],[\"tlsmail\",null],[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.4.2\",\"dependencies\":[[\"tlsmail\",null],[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.4.0\",\"dependencies\":[[\"tlsmail\",null],[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.0.3\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.5.0\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.0.5\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"1.6.0\",\"dependencies\":[[\"activesupport\",\"2.3.4 || 3.0.0 || 4.0.0\"],[\"mime-types\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.4.4\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.5.2\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.5.3\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"mail\",\"number\":\"2.5.4\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"]]},\n  {\"name\":\"mail\",\"number\":\"2.2.20\",\"dependencies\":[[\"activesupport\",\"2.3.6 || 3.0.0 || 4.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"treetop\",\"1.4.8\"],[\"i18n\",null]]},\n  {\"name\":\"method-source\",\"number\":\"0.6.7\",\"dependencies\":[[\"ruby-parser\",\"2.3.1\"]]},\n  {\"name\":\"method-source\",\"number\":\"0.6.5\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"]]},\n  {\"name\":\"method-source\",\"number\":\"0.3.5\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"]]},\n  {\"name\":\"method-source\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"method-source\",\"number\":\"0.3.2\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"]]},\n  {\"name\":\"method-source\",\"number\":\"0.6.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"]]},\n  {\"name\":\"method-source\",\"number\":\"0.3.3\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"]]},\n  {\"name\":\"method-source\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"method-source\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"method-source\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"method-source\",\"number\":\"0.8.1\",\"dependencies\":[]},\n  {\"name\":\"method-source\",\"number\":\"0.4.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"]]},\n  {\"name\":\"method-source\",\"number\":\"0.3.4\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"]]},\n  {\"name\":\"method-source\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"method-source\",\"number\":\"0.4.1\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"]]},\n  {\"name\":\"method-source\",\"number\":\"0.6.6\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"]]},\n  {\"name\":\"method-source\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"method-source\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"method-source\",\"number\":\"0.8.2\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.25.1\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.17.2\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.15.0\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.18.0\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.17.0\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.17.1\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.19.0\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.20.0\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.20.1\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.21.0\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.22.0\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.23.0\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.24.0\",\"dependencies\":[]},\n  {\"name\":\"mime-types\",\"number\":\"1.25.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.3.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.3.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.2.3\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.2.2\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.2.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.2.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.1.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.0.8\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"1.7.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"1.4.1\",\"dependencies\":[[\"hoe\",\"2.3.0\"]]},\n  {\"name\":\"minitest\",\"number\":\"1.7.2\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.12.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"1.4.0\",\"dependencies\":[[\"hoe\",\"2.1.0\"]]},\n  {\"name\":\"minitest\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.0.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.9.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"1.3.1\",\"dependencies\":[[\"hoe\",\"1.8.2 || 2.0.0\"]]},\n  {\"name\":\"minitest\",\"number\":\"1.4.2\",\"dependencies\":[[\"hoe\",\"2.3.1\"]]},\n  {\"name\":\"minitest\",\"number\":\"1.3.0\",\"dependencies\":[[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"minitest\",\"number\":\"2.10.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.6.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.4.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.11.2\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.5.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"3.0.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.11.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.2.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.3.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.11.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.6.2\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.2.2\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.5.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"3.3.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.3.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"3.1.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.10.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.6.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.7.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.8.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.8.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.9.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.11.3\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.11.4\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"2.12.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"3.2.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"3.4.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"3.5.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.1.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.2.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.3.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.3.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.3.2\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.3.3\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.4.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.5.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.6.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.6.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.6.2\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.7.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.7.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.7.2\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.7.3\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.7.4\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.0.0\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.0.1\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.0.2\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.0.3\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.0.4\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.0.5\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"4.7.5\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.0.6\",\"dependencies\":[]},\n  {\"name\":\"minitest\",\"number\":\"5.0.7\",\"dependencies\":[]},\n  {\"name\":\"modernizr\",\"number\":\"2.5.3\",\"dependencies\":[[\"sprockets\",\"2.0.0\"]]},\n  {\"name\":\"modernizr\",\"number\":\"2.6.1\",\"dependencies\":[[\"sprockets\",\"2.0.0\"]]},\n  {\"name\":\"modernizr\",\"number\":\"2.5.2\",\"dependencies\":[[\"sprockets\",\"2.0.0\"]]},\n  {\"name\":\"modernizr\",\"number\":\"2.6.2\",\"dependencies\":[[\"sprockets\",\"2.0.0\"]]},\n  {\"name\":\"multi-json\",\"number\":\"1.9.2\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.9.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.9.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.8.4\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.8.3\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.8.2\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.8.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.4\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"0.0.5\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.5\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.6\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"0.0.4\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.7\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.3\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.6.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.8.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.2\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.3\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.4\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.5\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.6\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.7\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.8\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.9\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.4.4\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.5.4\",\"dependencies\":[]},\n  {\"name\":\"multi-xml\",\"number\":\"0.5.5\",\"dependencies\":[]},\n  {\"name\":\"multipart-post\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"multipart-post\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"multipart-post\",\"number\":\"1.0.0\",\"dependencies\":[[\"hoe\",\"1.8.2 || 2.0.0\"]]},\n  {\"name\":\"multipart-post\",\"number\":\"0.1.0\",\"dependencies\":[[\"hoe\",\"1.5.3 || 2.0.0\"]]},\n  {\"name\":\"multipart-post\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"multipart-post\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"multipart-post\",\"number\":\"1.1.4\",\"dependencies\":[]},\n  {\"name\":\"multipart-post\",\"number\":\"1.1.5\",\"dependencies\":[]},\n  {\"name\":\"multipart-post\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"multipart-post\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"multipart-post\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.15\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.22\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.21\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.14\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.8\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.5\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.14\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.1.7\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.6\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.7\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.6\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.10\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.1.9\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.1.8\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.9\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.10\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.13\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.8\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.1.6\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.11\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.4\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.18\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.7\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.11\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.5\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.4\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.17\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.16\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.3\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.12\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.9\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.19\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.12\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.2.20\",\"dependencies\":[]},\n  {\"name\":\"mysql2\",\"number\":\"0.3.13\",\"dependencies\":[]},\n  {\"name\":\"net-ldap\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"net-ldap\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"net-ldap\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"net-ldap\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"net-ldap\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"net-ldap\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"net-ldap\",\"number\":\"0.0.5\",\"dependencies\":[]},\n  {\"name\":\"net-ldap\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"net-ldap\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"net-scp\",\"number\":\"1.0.2\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.0.3\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.0.1\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.0.0\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.0.4\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.1.0\",\"dependencies\":[[\"net-ssh\",\"2.6.5\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.1.1\",\"dependencies\":[[\"net-ssh\",\"2.6.5\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.1.2\",\"dependencies\":[[\"net-ssh\",\"2.6.5\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.8.0\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.7.0\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.23\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.5\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.1.4\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.1.1\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.1\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.22\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.18\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"1.1.3\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"0.9.0\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"0.5.0\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.8\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.11\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.7\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.20\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.6\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.1.0\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.1.3\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.13\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.7\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.2\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.2.1\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.3.0\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.24\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.9\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"1.1.2\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.10\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.6\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.19\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.5\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.3\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.10\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.0\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.2.2\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.14\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.8\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.16\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.15\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.17\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.21\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"0.6.0\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.4\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.9\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.1.4\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.5.2\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.1\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.2\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.3\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.4\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.5\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.6\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.7\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.8\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.6.1\",\"dependencies\":[[\"mini-portile\",\"0.5.0\"]]},\n  {\"name\":\"nokogiri\",\"number\":\"1.5.11\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.2.2\",\"dependencies\":[[\"hoe\",\"1.9.0 || 2.0.0\"]]},\n  {\"name\":\"nokogiri\",\"number\":\"1.3.0\",\"dependencies\":[[\"racc\",null],[\"tenderlove-frex\",null],[\"rake-compiler\",null],[\"hoe\",\"1.12.2 || 2.0.0\"]]},\n  {\"name\":\"nokogiri\",\"number\":\"1.0.6\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.4.1\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.0.1\",\"dependencies\":[[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"nokogiri\",\"number\":\"1.4.7\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.0.5\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.0.3\",\"dependencies\":[[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"nokogiri\",\"number\":\"1.4.3\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.3.2\",\"dependencies\":[[\"racc\",null],[\"rexical\",null],[\"rake-compiler\",null],[\"hoe\",\"2.2.0\"]]},\n  {\"name\":\"nokogiri\",\"number\":\"1.2.3\",\"dependencies\":[[\"hoe\",\"1.9.0 || 2.0.0\"]]},\n  {\"name\":\"nokogiri\",\"number\":\"1.4.6\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.4.2\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.5.2\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.5.4\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.3.3\",\"dependencies\":[[\"racc\",null],[\"rexical\",null],[\"rake-compiler\",null],[\"hoe\",\"2.3.2\"]]},\n  {\"name\":\"nokogiri\",\"number\":\"1.0.7\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.3.1\",\"dependencies\":[[\"racc\",null],[\"rexical\",null],[\"rake-compiler\",null],[\"hoe\",\"1.12.2 || 2.0.0\"]]},\n  {\"name\":\"nokogiri\",\"number\":\"1.4.5\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.5.3\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.5.5\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.4.4\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.0.0\",\"dependencies\":[[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"nokogiri\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.0.2\",\"dependencies\":[[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"nokogiri\",\"number\":\"1.5.6\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.5.7\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.5.8\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.5.9\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.5.10\",\"dependencies\":[]},\n  {\"name\":\"nokogiri\",\"number\":\"1.6.0\",\"dependencies\":[[\"mini-portile\",\"0.5.0\"]]},\n  {\"name\":\"oauth\",\"number\":\"0.2.0\",\"dependencies\":[[\"ruby-hmac\",null]]},\n  {\"name\":\"oauth\",\"number\":\"0.4.5\",\"dependencies\":[]},\n  {\"name\":\"oauth\",\"number\":\"0.2.6\",\"dependencies\":[[\"ruby-hmac\",null],[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"oauth\",\"number\":\"0.2.1\",\"dependencies\":[[\"ruby-hmac\",null]]},\n  {\"name\":\"oauth\",\"number\":\"0.3.2\",\"dependencies\":[[\"ruby-hmac\",null],[\"actionpack\",null],[\"rack\",null],[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"oauth\",\"number\":\"0.3.4\",\"dependencies\":[[\"ruby-hmac\",null],[\"actionpack\",null],[\"rack\",null],[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"oauth\",\"number\":\"0.3.0\",\"dependencies\":[[\"ruby-hmac\",null],[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"oauth\",\"number\":\"0.2.4\",\"dependencies\":[[\"ruby-hmac\",null]]},\n  {\"name\":\"oauth\",\"number\":\"0.2.2\",\"dependencies\":[[\"ruby-hmac\",null]]},\n  {\"name\":\"oauth\",\"number\":\"0.4.6\",\"dependencies\":[]},\n  {\"name\":\"oauth\",\"number\":\"0.1.1\",\"dependencies\":[[\"ruby-hmac\",null]]},\n  {\"name\":\"oauth\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"oauth\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"oauth\",\"number\":\"0.3.1\",\"dependencies\":[[\"ruby-hmac\",null],[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"oauth\",\"number\":\"0.3.5\",\"dependencies\":[[\"ruby-hmac\",null],[\"actionpack\",null],[\"rack\",null],[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"oauth\",\"number\":\"0.3.3\",\"dependencies\":[[\"ruby-hmac\",null],[\"actionpack\",null],[\"rack\",null],[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"oauth\",\"number\":\"0.3.6\",\"dependencies\":[[\"ruby-hmac\",null]]},\n  {\"name\":\"oauth\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"oauth\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"oauth\",\"number\":\"0.4.4\",\"dependencies\":[]},\n  {\"name\":\"oauth\",\"number\":\"0.2.7\",\"dependencies\":[[\"ruby-hmac\",null],[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"oauth\",\"number\":\"0.4.7\",\"dependencies\":[]},\n  {\"name\":\"oauth2\",\"number\":\"0.9.3\",\"dependencies\":[[\"jwt\",\"0.1.8\"],[\"rack\",\"1.2.0\"],[\"multi-xml\",\"0.5.0\"],[\"multi-json\",\"1.3.0\"],[\"faraday\",null]]},\n  {\"name\":\"oauth2\",\"number\":\"0.0.12\",\"dependencies\":[[\"faraday\",\"0.4.1\"],[\"multi-json\",null]]},\n  {\"name\":\"oauth2\",\"number\":\"0.6.0\",\"dependencies\":[[\"faraday\",\"0.7.0\"],[\"multi-json\",\"1.0.0\"],[\"httpauth\",\"0.1.0\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.5.1\",\"dependencies\":[[\"faraday\",\"0.7.4\"],[\"multi-json\",\"1.0.3\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"oauth2\",\"number\":\"0.3.0\",\"dependencies\":[[\"faraday\",\"0.6.0\"],[\"multi-json\",\"0.0.4 || 1.0.0\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.0.10\",\"dependencies\":[[\"faraday\",\"0.4.1\"],[\"multi-json\",null]]},\n  {\"name\":\"oauth2\",\"number\":\"0.1.0\",\"dependencies\":[[\"faraday\",\"0.5.0\"],[\"multi-json\",\"0.0.4 || 1.0.0\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.0.5\",\"dependencies\":[[\"faraday\",\"0.3.0\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.5.2\",\"dependencies\":[[\"faraday\",\"0.7.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"oauth2\",\"number\":\"0.4.1\",\"dependencies\":[[\"faraday\",\"0.6.1\"],[\"multi-json\",null]]},\n  {\"name\":\"oauth2\",\"number\":\"0.0.4\",\"dependencies\":[[\"faraday\",\"0.3.0\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"oauth2\",\"number\":\"0.0.8\",\"dependencies\":[[\"faraday\",\"0.4.1\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.0.9\",\"dependencies\":[[\"faraday\",\"0.4.1\"],[\"multi-json\",null]]},\n  {\"name\":\"oauth2\",\"number\":\"0.2.0\",\"dependencies\":[[\"faraday\",\"0.6.0\"],[\"multi-json\",\"0.0.4 || 1.0.0\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.6.1\",\"dependencies\":[[\"faraday\",\"0.7.0\"],[\"multi-json\",\"1.3.0\"],[\"httpauth\",\"0.1.0\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.7.0\",\"dependencies\":[[\"faraday\",\"0.8.0\"],[\"httpauth\",\"0.1.0\"],[\"multi-json\",\"1.3.0\"],[\"rack\",\"1.4.0\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.8.0\",\"dependencies\":[[\"faraday\",\"0.8.0\"],[\"httpauth\",\"0.1.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.2.0\"],[\"jwt\",\"0.1.4\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.0.11\",\"dependencies\":[[\"faraday\",\"0.4.1\"],[\"faraday-middleware\",null],[\"multi-json\",null]]},\n  {\"name\":\"oauth2\",\"number\":\"0.1.1\",\"dependencies\":[[\"faraday\",\"0.5.0\"],[\"multi-json\",\"0.0.4 || 1.0.0\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.4.0\",\"dependencies\":[[\"faraday\",\"0.6.0\"],[\"multi-json\",\"0.0.4 || 1.0.0\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.0.7\",\"dependencies\":[[\"faraday\",\"0.4.1\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.0.6\",\"dependencies\":[[\"faraday\",\"0.3.0\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.0.13\",\"dependencies\":[[\"faraday\",\"0.4.1\"],[\"multi-json\",null]]},\n  {\"name\":\"oauth2\",\"number\":\"0.5.0\",\"dependencies\":[[\"faraday\",null],[\"multi-json\",\"1.0.0\"],[\"faraday\",null]]},\n  {\"name\":\"oauth2\",\"number\":\"0.7.1\",\"dependencies\":[[\"faraday\",\"0.8.0\"],[\"httpauth\",\"0.1.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.4.0\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.9.0\",\"dependencies\":[[\"faraday\",\"0.8.0\"],[\"httpauth\",\"0.1.0\"],[\"multi-json\",\"1.0.0\"],[\"multi-xml\",\"0.5.0\"],[\"rack\",\"1.2.0\"],[\"jwt\",\"0.1.4\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.9.1\",\"dependencies\":[[\"faraday\",\"0.8.0\"],[\"httpauth\",\"0.1.0\"],[\"multi-json\",\"1.0.0\"],[\"multi-xml\",\"0.5.0\"],[\"rack\",\"1.2.0\"],[\"jwt\",\"0.1.4\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.8.1\",\"dependencies\":[[\"faraday\",\"0.8.0\"],[\"httpauth\",\"0.1.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.2.0\"],[\"jwt\",\"0.1.4\"]]},\n  {\"name\":\"oauth2\",\"number\":\"0.9.2\",\"dependencies\":[[\"faraday\",\"0.8.0\"],[\"httpauth\",\"0.2.0\"],[\"multi-json\",\"1.0.0\"],[\"multi-xml\",\"0.5.0\"],[\"rack\",\"1.2.0\"],[\"jwt\",\"0.1.4\"]]},\n  {\"name\":\"omniauth\",\"number\":\"1.2.1\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"hashie\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"omniauth\",\"number\":\"1.0.2\",\"dependencies\":[[\"rack\",null],[\"hashie\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.2.5\",\"dependencies\":[[\"oa-core\",\"=0.2.5\"],[\"oa-oauth\",\"=0.2.5\"],[\"oa-basic\",\"=0.2.5\"],[\"oa-openid\",\"=0.2.5\"],[\"oa-enterprise\",\"=0.2.5\"],[\"oa-more\",\"=0.2.5\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.2.1\",\"dependencies\":[[\"oa-core\",\"=0.2.1\"],[\"oa-oauth\",\"=0.2.1\"],[\"oa-basic\",\"=0.2.1\"],[\"oa-openid\",\"=0.2.1\"],[\"oa-enterprise\",\"=0.2.1\"],[\"oa-more\",\"=0.2.1\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.2.3\",\"dependencies\":[[\"oa-core\",\"=0.2.3\"],[\"oa-oauth\",\"=0.2.3\"],[\"oa-basic\",\"=0.2.3\"],[\"oa-openid\",\"=0.2.3\"],[\"oa-enterprise\",\"=0.2.3\"],[\"oa-more\",\"=0.2.3\"]]},\n  {\"name\":\"omniauth\",\"number\":\"1.1.0\",\"dependencies\":[[\"rack\",null],[\"hashie\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"omniauth\",\"number\":\"1.0.0\",\"dependencies\":[[\"rack\",null],[\"hashie\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.1.2\",\"dependencies\":[[\"oa-core\",\"=0.1.2\"],[\"oa-oauth\",\"=0.1.2\"],[\"oa-basic\",\"=0.1.2\"],[\"oa-openid\",\"=0.1.2\"],[\"oa-enterprise\",\"=0.1.2\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.2.2\",\"dependencies\":[[\"oa-core\",\"=0.2.2\"],[\"oa-oauth\",\"=0.2.2\"],[\"oa-basic\",\"=0.2.2\"],[\"oa-openid\",\"=0.2.2\"],[\"oa-enterprise\",\"=0.2.2\"],[\"oa-more\",\"=0.2.2\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.3.0\",\"dependencies\":[[\"oa-basic\",\"=0.3.0\"],[\"oa-enterprise\",\"=0.3.0\"],[\"oa-core\",\"=0.3.0\"],[\"oa-more\",\"=0.3.0\"],[\"oa-oauth\",\"=0.3.0\"],[\"oa-openid\",\"=0.3.0\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.0.1\",\"dependencies\":[[\"oa-core\",\"0.0.0\"],[\"oa-oauth\",\"0.0.0\"],[\"oa-openid\",\"0.0.0\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.2.0\",\"dependencies\":[[\"oa-core\",\"=0.2.0\"],[\"oa-oauth\",\"=0.2.0\"],[\"oa-basic\",\"=0.2.0\"],[\"oa-openid\",\"=0.2.0\"],[\"oa-enterprise\",\"=0.2.0\"],[\"oa-more\",\"=0.2.0\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.1.6\",\"dependencies\":[[\"oa-core\",\"=0.1.6\"],[\"oa-oauth\",\"=0.1.6\"],[\"oa-basic\",\"=0.1.6\"],[\"oa-openid\",\"=0.1.6\"],[\"oa-enterprise\",\"=0.1.6\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.0.5\",\"dependencies\":[[\"oa-core\",\"=0.0.5\"],[\"oa-oauth\",\"=0.0.5\"],[\"oa-basic\",\"=0.0.5\"],[\"oa-openid\",\"=0.0.5\"],[\"oa-enterprise\",\"=0.0.5\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.1.4\",\"dependencies\":[[\"oa-core\",\"=0.1.4\"],[\"oa-oauth\",\"=0.1.4\"],[\"oa-basic\",\"=0.1.4\"],[\"oa-openid\",\"=0.1.4\"],[\"oa-enterprise\",\"=0.1.4\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.2.4\",\"dependencies\":[[\"oa-core\",\"=0.2.4\"],[\"oa-oauth\",\"=0.2.4\"],[\"oa-basic\",\"=0.2.4\"],[\"oa-openid\",\"=0.2.4\"],[\"oa-enterprise\",\"=0.2.4\"],[\"oa-more\",\"=0.2.4\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.0.4\",\"dependencies\":[[\"oa-core\",\"=0.0.4\"],[\"oa-oauth\",\"=0.0.4\"],[\"oa-basic\",\"=0.0.4\"],[\"oa-openid\",\"=0.0.4\"],[\"oa-enterprise\",\"=0.0.4\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.1.5\",\"dependencies\":[[\"oa-core\",\"=0.1.5\"],[\"oa-oauth\",\"=0.1.5\"],[\"oa-basic\",\"=0.1.5\"],[\"oa-openid\",\"=0.1.5\"],[\"oa-enterprise\",\"=0.1.5\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.1.3\",\"dependencies\":[[\"oa-core\",\"=0.1.3\"],[\"oa-oauth\",\"=0.1.3\"],[\"oa-basic\",\"=0.1.3\"],[\"oa-openid\",\"=0.1.3\"],[\"oa-enterprise\",\"=0.1.3\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.0.3\",\"dependencies\":[[\"oa-core\",\"=0.0.3\"],[\"oa-oauth\",\"=0.0.3\"],[\"oa-basic\",\"=0.0.3\"],[\"oa-openid\",\"=0.0.3\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.1.0\",\"dependencies\":[[\"oa-core\",\"=0.1.0\"],[\"oa-oauth\",\"=0.1.0\"],[\"oa-basic\",\"=0.1.0\"],[\"oa-openid\",\"=0.1.0\"],[\"oa-enterprise\",\"=0.1.0\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.2.6\",\"dependencies\":[[\"oa-basic\",\"=0.2.6\"],[\"oa-enterprise\",\"=0.2.6\"],[\"oa-core\",\"=0.2.6\"],[\"oa-more\",\"=0.2.6\"],[\"oa-oauth\",\"=0.2.6\"],[\"oa-openid\",\"=0.2.6\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.1.1\",\"dependencies\":[[\"oa-core\",\"=0.1.1\"],[\"oa-oauth\",\"=0.1.1\"],[\"oa-basic\",\"=0.1.1\"],[\"oa-openid\",\"=0.1.1\"],[\"oa-enterprise\",\"=0.1.1\"]]},\n  {\"name\":\"omniauth\",\"number\":\"0.3.2\",\"dependencies\":[[\"oa-basic\",\"=0.3.2\"],[\"oa-enterprise\",\"=0.3.2\"],[\"oa-core\",\"=0.3.2\"],[\"oa-more\",\"=0.3.2\"],[\"oa-oauth\",\"=0.3.2\"],[\"oa-openid\",\"=0.3.2\"]]},\n  {\"name\":\"omniauth\",\"number\":\"1.0.1\",\"dependencies\":[[\"rack\",null],[\"hashie\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"omniauth\",\"number\":\"1.0.3\",\"dependencies\":[[\"rack\",null],[\"hashie\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"omniauth\",\"number\":\"1.1.1\",\"dependencies\":[[\"rack\",null],[\"hashie\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"omniauth\",\"number\":\"1.1.2\",\"dependencies\":[[\"hashie\",\"1.2.0 || 2.0.0\"],[\"rack\",null]]},\n  {\"name\":\"omniauth\",\"number\":\"1.1.3\",\"dependencies\":[[\"hashie\",\"1.2.0 || 2.0.0\"],[\"rack\",null]]},\n  {\"name\":\"omniauth\",\"number\":\"1.1.4\",\"dependencies\":[[\"hashie\",\"1.2.0 || 2.0.0\"],[\"rack\",null]]},\n  {\"name\":\"omniauth-github\",\"number\":\"1.0.0\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-github\",\"number\":\"1.0.1\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-github\",\"number\":\"1.0.2\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",\"1.1.0\"]]},\n  {\"name\":\"omniauth-github\",\"number\":\"1.0.3\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",\"1.1.0\"]]},\n  {\"name\":\"omniauth-github\",\"number\":\"1.1.0\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",\"1.1.0\"]]},\n  {\"name\":\"omniauth-github\",\"number\":\"1.1.1\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",\"1.1.0\"]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.2.2\",\"dependencies\":[[\"omniauth-oauth2\",null],[\"omniauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.11\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.0.3\",\"dependencies\":[[\"omniauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.2\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.0.8\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.0.6\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.0.4\",\"dependencies\":[[\"omniauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.8\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.13\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.0.1\",\"dependencies\":[[\"omniauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.0.5\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.0.7\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.0.9\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.0.10\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.0\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.1\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.3\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.6\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.12\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.10\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.9\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.0.2\",\"dependencies\":[[\"omniauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.4\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.7\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.15\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.16\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.17\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.18\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.1.19\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.2.0\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-google-oauth2\",\"number\":\"0.2.1\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",null]]},\n  {\"name\":\"omniauth-oauth\",\"number\":\"1.0.0\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"oauth\",null]]},\n  {\"name\":\"omniauth-oauth\",\"number\":\"1.0.1\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"oauth\",null]]},\n  {\"name\":\"omniauth-oauth2\",\"number\":\"1.1.2\",\"dependencies\":[[\"omniauth\",\"1.2.0\"],[\"oauth2\",\"0.9.3\"],[\"multi-json\",\"1.3.0\"],[\"faraday\",null]]},\n  {\"name\":\"omniauth-oauth2\",\"number\":\"1.1.0\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"oauth2\",\"0.8.0\"]]},\n  {\"name\":\"omniauth-oauth2\",\"number\":\"1.0.2\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"oauth2\",\"0.6.0\"]]},\n  {\"name\":\"omniauth-oauth2\",\"number\":\"1.0.0\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"oauth2\",\"0.5.0\"]]},\n  {\"name\":\"omniauth-oauth2\",\"number\":\"1.0.1\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"oauth2\",\"0.6.0\"]]},\n  {\"name\":\"omniauth-oauth2\",\"number\":\"1.1.1\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"oauth2\",\"0.8.0\"]]},\n  {\"name\":\"omniauth-oauth2\",\"number\":\"1.0.3\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"oauth2\",\"0.8.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"1.0.1\",\"dependencies\":[[\"omniauth-oauth\",\"1.0.0\"],[\"multi-json\",\"1.3.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.10\",\"dependencies\":[[\"multi-json\",\"1.3.0\"],[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.11\",\"dependencies\":[[\"multi-json\",\"1.3.0\"],[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.9\",\"dependencies\":[[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.8\",\"dependencies\":[[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.1\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.2\",\"dependencies\":[[\"omniauth\",\"1.0.0\"],[\"omniauth-oauth2\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.7\",\"dependencies\":[[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.5\",\"dependencies\":[[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.3\",\"dependencies\":[[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.4\",\"dependencies\":[[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.6\",\"dependencies\":[[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.12\",\"dependencies\":[[\"multi-json\",\"1.3.0\"],[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.13\",\"dependencies\":[[\"multi-json\",\"1.3.0\"],[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.14\",\"dependencies\":[[\"multi-json\",\"1.3.0\"],[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.15\",\"dependencies\":[[\"multi-json\",\"1.3.0\"],[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.16\",\"dependencies\":[[\"multi-json\",\"1.3.0\"],[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.17\",\"dependencies\":[[\"multi-json\",\"1.3.0\"],[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"0.0.18\",\"dependencies\":[[\"multi-json\",\"1.3.0\"],[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"omniauth-twitter\",\"number\":\"1.0.0\",\"dependencies\":[[\"multi-json\",\"1.3.0\"],[\"omniauth-oauth\",\"1.0.0\"]]},\n  {\"name\":\"orm-adapter\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"orm-adapter\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"orm-adapter\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"orm-adapter\",\"number\":\"0.0.4\",\"dependencies\":[]},\n  {\"name\":\"orm-adapter\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"orm-adapter\",\"number\":\"0.0.6\",\"dependencies\":[]},\n  {\"name\":\"orm-adapter\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"orm-adapter\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"orm-adapter\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"orm-adapter\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"orm-adapter\",\"number\":\"0.0.5\",\"dependencies\":[]},\n  {\"name\":\"orm-adapter\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"orm-adapter\",\"number\":\"0.0.7\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.17.1\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.17.0\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.10.1\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.13.0\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.12.2\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.11.0\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.12.0\",\"dependencies\":[[\"rake-compiler\",\"0.7.0\"]]},\n  {\"name\":\"pg\",\"number\":\"0.13.1\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.13.2\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.12.1\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.14.0\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.14.1\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.15.0\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.15.1\",\"dependencies\":[]},\n  {\"name\":\"pg\",\"number\":\"0.16.0\",\"dependencies\":[]},\n  {\"name\":\"phantomjs\",\"number\":\"1.9.7\",\"dependencies\":[]},\n  {\"name\":\"phantomjs\",\"number\":\"1.9.2\",\"dependencies\":[]},\n  {\"name\":\"phantomjs\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"phantomjs\",\"number\":\"1.8.1\",\"dependencies\":[[\"poltergeist\",null]]},\n  {\"name\":\"poltergeist\",\"number\":\"1.5.0\",\"dependencies\":[[\"cliver\",\"0.3.1\"],[\"multi-json\",\"1.0.0\"],[\"websocket-driver\",null],[\"capybara\",\"2.1.0\"]]},\n  {\"name\":\"poltergeist\",\"number\":\"1.0.1\",\"dependencies\":[[\"capybara\",\"1.1.0 || 2.0.0\"],[\"multi-json\",\"1.0.0\"],[\"childprocess\",\"0.3.0\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",null]]},\n  {\"name\":\"poltergeist\",\"number\":\"0.2.0\",\"dependencies\":[[\"capybara\",\"1.0.0 || 2.0.0\"],[\"em-websocket\",\"0.3.1\"],[\"json\",\"1.6.0\"],[\"sfl\",\"2.0.0\"]]},\n  {\"name\":\"poltergeist\",\"number\":\"0.1.0\",\"dependencies\":[[\"capybara\",\"1.1.0 || 2.0.0\"],[\"em-websocket\",\"0.3.1\"],[\"json\",\"1.6.0\"]]},\n  {\"name\":\"poltergeist\",\"number\":\"0.5.0\",\"dependencies\":[[\"capybara\",\"1.0.0 || 2.0.0\"],[\"multi-json\",\"1.0.0\"],[\"childprocess\",\"0.3.0\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",null]]},\n  {\"name\":\"poltergeist\",\"number\":\"1.0.0\",\"dependencies\":[[\"capybara\",\"1.1.0 || 2.0.0\"],[\"multi-json\",\"1.0.0\"],[\"childprocess\",\"0.3.0\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",null]]},\n  {\"name\":\"poltergeist\",\"number\":\"0.4.0\",\"dependencies\":[[\"capybara\",\"1.0.0 || 2.0.0\"],[\"json\",\"1.6.0\"],[\"sfl\",\"2.0.0\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",\"0.2.0\"]]},\n  {\"name\":\"poltergeist\",\"number\":\"0.3.0\",\"dependencies\":[[\"capybara\",\"1.0.0 || 2.0.0\"],[\"json\",\"1.6.0\"],[\"sfl\",\"2.0.0\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",\"0.2.0\"]]},\n  {\"name\":\"poltergeist\",\"number\":\"0.6.0\",\"dependencies\":[[\"capybara\",\"1.0.0 || 2.0.0\"],[\"multi-json\",\"1.0.0\"],[\"childprocess\",\"0.3.0\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",null]]},\n  {\"name\":\"poltergeist\",\"number\":\"0.7.0\",\"dependencies\":[[\"capybara\",\"1.1.0 || 2.0.0\"],[\"multi-json\",\"1.0.0\"],[\"childprocess\",\"0.3.0\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",null]]},\n  {\"name\":\"poltergeist\",\"number\":\"1.0.2\",\"dependencies\":[[\"capybara\",\"1.1.0 || 2.0.0\"],[\"multi-json\",\"1.0.0\"],[\"childprocess\",\"0.3.0\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",null]]},\n  {\"name\":\"poltergeist\",\"number\":\"1.1.0\",\"dependencies\":[[\"capybara\",\"2.0.1\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",null]]},\n  {\"name\":\"poltergeist\",\"number\":\"1.1.1\",\"dependencies\":[[\"capybara\",\"2.0.1\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",null]]},\n  {\"name\":\"poltergeist\",\"number\":\"1.2.0\",\"dependencies\":[[\"capybara\",\"2.1.0\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",null]]},\n  {\"name\":\"poltergeist\",\"number\":\"1.3.0\",\"dependencies\":[[\"capybara\",\"2.1.0\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",null]]},\n  {\"name\":\"poltergeist\",\"number\":\"1.1.2\",\"dependencies\":[[\"capybara\",\"2.0.1\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",\"0.4.4\"]]},\n  {\"name\":\"poltergeist\",\"number\":\"1.0.3\",\"dependencies\":[[\"capybara\",\"1.1.0 || 2.0.0\"],[\"multi-json\",\"1.0.0\"],[\"childprocess\",\"0.3.0\"],[\"http-parser.rb\",\"0.5.3\"],[\"faye-websocket\",\"0.4.4\"]]},\n  {\"name\":\"poltergeist\",\"number\":\"1.4.0\",\"dependencies\":[[\"capybara\",\"2.1.0\"],[\"websocket-driver\",null],[\"multi-json\",\"1.0.0\"],[\"cliver\",\"0.2.1\"]]},\n  {\"name\":\"poltergeist\",\"number\":\"1.4.1\",\"dependencies\":[[\"capybara\",\"2.1.0\"],[\"websocket-driver\",null],[\"multi-json\",\"1.0.0\"],[\"cliver\",\"0.2.1\"]]},\n  {\"name\":\"polyglot\",\"number\":\"0.3.4\",\"dependencies\":[]},\n  {\"name\":\"polyglot\",\"number\":\"0.2.5\",\"dependencies\":[[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"polyglot\",\"number\":\"0.2.9\",\"dependencies\":[]},\n  {\"name\":\"polyglot\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"polyglot\",\"number\":\"0.2.3\",\"dependencies\":[]},\n  {\"name\":\"polyglot\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"polyglot\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"polyglot\",\"number\":\"0.2.8\",\"dependencies\":[[\"hoe\",\"2.3.2\"]]},\n  {\"name\":\"polyglot\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"polyglot\",\"number\":\"0.2.6\",\"dependencies\":[[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"polyglot\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"polyglot\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"polyglot\",\"number\":\"0.2.7\",\"dependencies\":[[\"hoe\",\"2.3.2\"]]},\n  {\"name\":\"polyglot\",\"number\":\"0.2.4\",\"dependencies\":[[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"polyglot\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"polyglot\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"posix-spawn\",\"number\":\"0.3.8\",\"dependencies\":[]},\n  {\"name\":\"posix-spawn\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"posix-spawn\",\"number\":\"0.3.5\",\"dependencies\":[]},\n  {\"name\":\"posix-spawn\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"posix-spawn\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"posix-spawn\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"posix-spawn\",\"number\":\"0.3.6\",\"dependencies\":[]},\n  {\"name\":\"protected-attributes\",\"number\":\"1.0.7\",\"dependencies\":[[\"activemodel\",\"4.0.1\"]]},\n  {\"name\":\"protected-attributes\",\"number\":\"1.0.6\",\"dependencies\":[[\"activemodel\",\"4.0.1\"]]},\n  {\"name\":\"protected-attributes\",\"number\":\"1.0.5\",\"dependencies\":[[\"activemodel\",\"4.0.1\"]]},\n  {\"name\":\"protected-attributes\",\"number\":\"1.0.4\",\"dependencies\":[[\"activemodel\",\"4.0.1\"]]},\n  {\"name\":\"protected-attributes\",\"number\":\"1.0.0\",\"dependencies\":[[\"activemodel\",\"4.0.0\"]]},\n  {\"name\":\"protected-attributes\",\"number\":\"1.0.1\",\"dependencies\":[[\"activemodel\",\"4.0.0\"]]},\n  {\"name\":\"protected-attributes\",\"number\":\"1.0.2\",\"dependencies\":[[\"activemodel\",\"4.0.0\"]]},\n  {\"name\":\"protected-attributes\",\"number\":\"1.0.3\",\"dependencies\":[[\"activemodel\",\"4.0.0\"]]},\n  {\"name\":\"pry\",\"number\":\"0.5.6\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.1.2\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"]]},\n  {\"name\":\"pry\",\"number\":\"0.6.6\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.5.2\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.7.1\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.6.2\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.6.3\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.9.6\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"slop\",\"2.1.0 || 3.0.0\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.8.1\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"slop\",\"1.5.2 || 2.0.0 || 3.0.0\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.9.9\",\"dependencies\":[[\"coderay\",\"1.0.5\"],[\"slop\",\"2.4.4 || 3.0.0\"],[\"method-source\",\"0.7.1\"]]},\n  {\"name\":\"pry\",\"number\":\"0.9.3\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"slop\",\"1.9.0 || 2.0.0 || 3.0.0\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.4.8\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.7.7\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.4.6\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.9.5\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"slop\",\"2.1.0 || 3.0.0\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.3.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.2.8\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.2.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"]]},\n  {\"name\":\"pry\",\"number\":\"0.5.7\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.4.2\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.4.4\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.5.4\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.5.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.6.5\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.9.2\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"slop\",\"1.9.0 || 2.0.0 || 3.0.0\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.9.10\",\"dependencies\":[[\"coderay\",\"1.0.5\"],[\"slop\",\"3.3.1\"],[\"method-source\",\"0.8.0\"]]},\n  {\"name\":\"pry\",\"number\":\"0.4.1\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.8.2\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"slop\",\"1.5.2 || 2.0.0 || 3.0.0\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.7.3\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.6.7\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.2.6\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.4.7\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.8.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"slop\",\"1.5.2 || 2.0.0 || 3.0.0\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.8.3\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"slop\",\"1.5.3 || 2.0.0 || 3.0.0\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.5.5\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.7.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.4.3\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.9.7\",\"dependencies\":[[\"ruby-parser\",\"2.3.1\"],[\"coderay\",\"0.9.8 || 1.0.0\"],[\"slop\",\"2.1.0 || 3.0.0\"],[\"method-source\",\"0.6.5\"]]},\n  {\"name\":\"pry\",\"number\":\"0.5.9\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.9.8\",\"dependencies\":[[\"coderay\",\"1.0.5\"],[\"slop\",\"2.4.3 || 3.0.0\"],[\"method-source\",\"0.7.0\"]]},\n  {\"name\":\"pry\",\"number\":\"0.9.1\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"slop\",\"1.9.0 || 2.0.0 || 3.0.0\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.6.1\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.5.8\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.6.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.4.5\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.6.4\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.4.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.7.4\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.6.8\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.9.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"slop\",\"1.9.0 || 2.0.0 || 3.0.0\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.1.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"]]},\n  {\"name\":\"pry\",\"number\":\"0.7.6\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.7.2\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"coderay\",null],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.5.1\",\"dependencies\":[[\"ruby-parser\",\"2.0.5\"],[\"method-source\",null]]},\n  {\"name\":\"pry\",\"number\":\"0.9.11\",\"dependencies\":[[\"coderay\",\"1.0.5\"],[\"slop\",\"3.4.0\"],[\"method-source\",\"0.8.0\"]]},\n  {\"name\":\"pry\",\"number\":\"0.9.12\",\"dependencies\":[[\"coderay\",\"1.0.5\"],[\"slop\",\"3.4.0\"],[\"method-source\",\"0.8.0\"]]},\n  {\"name\":\"pyu-ruby-sasl\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"pyu-ruby-sasl\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"quiet-assets\",\"number\":\"1.0.1\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"quiet-assets\",\"number\":\"1.0.0\",\"dependencies\":[[\"rails\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"quiet-assets\",\"number\":\"1.0.2\",\"dependencies\":[[\"railties\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"racc\",\"number\":\"1.4.11\",\"dependencies\":[]},\n  {\"name\":\"racc\",\"number\":\"1.4.10\",\"dependencies\":[]},\n  {\"name\":\"racc\",\"number\":\"1.4.6\",\"dependencies\":[]},\n  {\"name\":\"racc\",\"number\":\"1.4.8\",\"dependencies\":[]},\n  {\"name\":\"racc\",\"number\":\"1.4.7\",\"dependencies\":[]},\n  {\"name\":\"racc\",\"number\":\"1.4.9\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"0.9.0\",\"dependencies\":[[\"test-spec\",null],[\"camping\",null],[\"fcgi\",null],[\"memcache-client\",null],[\"mongrel\",null],[\"ruby-openid\",\"2.0.0\"],[\"thin\",null]]},\n  {\"name\":\"rack\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.3\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.0.0\",\"dependencies\":[[\"test-spec\",null],[\"camping\",null],[\"fcgi\",null],[\"memcache-client\",null],[\"mongrel\",null],[\"ruby-openid\",\"2.0.0\"],[\"thin\",null]]},\n  {\"name\":\"rack\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.3\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.4\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.5\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.5\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.4\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.6\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.4.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.7\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.4.2\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.1.4\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.6\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.8\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.4.3\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.7\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.4.4\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.1.5\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.9\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.8\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.4.5\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.1.6\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.10\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.5.2\",\"dependencies\":[]},\n  {\"name\":\"rack-accept\",\"number\":\"0.3.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-accept\",\"number\":\"0.1.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-accept\",\"number\":\"0.1.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-accept\",\"number\":\"0.2.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-accept\",\"number\":\"0.4.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-accept\",\"number\":\"0.4.5\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-accept\",\"number\":\"0.4.3\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-accept\",\"number\":\"0.4.4\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-accept\",\"number\":\"0.4.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"3.0.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"2.3.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"0.0.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"0.1.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"1.3.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"1.3.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"1.3.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"0.2.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"0.0.3\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"1.0.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"1.1.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"1.2.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"2.0.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"2.1.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"2.1.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"2.2.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-attack\",\"number\":\"2.2.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-cors\",\"number\":\"0.2.9\",\"dependencies\":[]},\n  {\"name\":\"rack-cors\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"rack-cors\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"rack-cors\",\"number\":\"0.2.4\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-cors\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"rack-cors\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"rack-cors\",\"number\":\"0.2.5\",\"dependencies\":[[\"rack-cors\",null],[\"rack\",null]]},\n  {\"name\":\"rack-cors\",\"number\":\"0.2.6\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-cors\",\"number\":\"0.2.7\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-cors\",\"number\":\"0.2.8\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.9.1\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.9.0\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.5\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.7\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.8\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.17\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.18\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.10\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.19\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.20\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.21\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.22\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.2\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.0\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.3\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.6\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.1\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.9\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.4\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.16\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.23\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.24\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.25\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.26\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.27\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.28\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.29\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.30\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mini-profiler\",\"number\":\"0.1.31\",\"dependencies\":[[\"rack\",\"1.1.3\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.6\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.7.4\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.8.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.7.3\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.2.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.8.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.2.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.5.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.0.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.4\",\"dependencies\":[]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"rack-mount\",\"number\":\"0.2.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"rack-mount\",\"number\":\"0.4.5\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.4.6\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.4.7\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.5.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.7\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.8\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.9\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.10\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.11\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.12\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.5.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.5\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.4.4\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.4.3\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.4.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.4.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.7.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.8.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.8.3\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.13\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.6.14\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.4.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.3.3\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.3.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.3.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.3.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.2.3\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.0.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-mount\",\"number\":\"0.7.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.5.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.5.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.1.3\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.1.4\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"0.1.0\",\"dependencies\":[[\"rack\",null],[\"escape-utils\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.2.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.1.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.0.0\",\"dependencies\":[[\"rack\",null],[\"escape-utils\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.3.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.3.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.4.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.5.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-test\",\"number\":\"0.5.4\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-test\",\"number\":\"0.5.5\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-test\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"rack-test\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"rack-test\",\"number\":\"0.5.3\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-test\",\"number\":\"0.5.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-test\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"rack-test\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"rack-test\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"rack-test\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"rack-test\",\"number\":\"0.5.7\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-test\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"rack-test\",\"number\":\"0.5.6\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-test\",\"number\":\"0.5.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-test\",\"number\":\"0.6.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-test\",\"number\":\"0.6.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rack-test\",\"number\":\"0.6.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"4.0.4\",\"dependencies\":[[\"sprockets-rails\",\"2.0.0\"],[\"bundler\",\"1.3.0 || 2.0.0\"],[\"railties\",\"=4.0.4\"],[\"actionmailer\",\"=4.0.4\"],[\"activerecord\",\"=4.0.4\"],[\"actionpack\",\"=4.0.4\"],[\"activesupport\",\"=4.0.4\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.17\",\"dependencies\":[[\"bundler\",\"1.0.0 || 2.0.0\"],[\"railties\",\"=3.2.17\"],[\"actionmailer\",\"=3.2.17\"],[\"activeresource\",\"=3.2.17\"],[\"activerecord\",\"=3.2.17\"],[\"actionpack\",\"=3.2.17\"],[\"activesupport\",\"=3.2.17\"]]},\n  {\"name\":\"rails\",\"number\":\"4.0.3\",\"dependencies\":[[\"sprockets-rails\",\"2.0.0\"],[\"bundler\",\"1.3.0 || 2.0.0\"],[\"railties\",\"=4.0.3\"],[\"actionmailer\",\"=4.0.3\"],[\"activerecord\",\"=4.0.3\"],[\"actionpack\",\"=4.0.3\"],[\"activesupport\",\"=4.0.3\"]]},\n  {\"name\":\"rails\",\"number\":\"4.0.2\",\"dependencies\":[[\"sprockets-rails\",\"2.0.0\"],[\"bundler\",\"1.3.0 || 2.0.0\"],[\"railties\",\"=4.0.2\"],[\"actionmailer\",\"=4.0.2\"],[\"activerecord\",\"=4.0.2\"],[\"actionpack\",\"=4.0.2\"],[\"activesupport\",\"=4.0.2\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.16\",\"dependencies\":[[\"bundler\",\"1.0.0 || 2.0.0\"],[\"railties\",\"=3.2.16\"],[\"actionmailer\",\"=3.2.16\"],[\"activeresource\",\"=3.2.16\"],[\"activerecord\",\"=3.2.16\"],[\"actionpack\",\"=3.2.16\"],[\"activesupport\",\"=3.2.16\"]]},\n  {\"name\":\"rails\",\"number\":\"4.0.1\",\"dependencies\":[[\"sprockets-rails\",\"2.0.0\"],[\"bundler\",\"1.3.0 || 2.0.0\"],[\"railties\",\"=4.0.1\"],[\"actionmailer\",\"=4.0.1\"],[\"activerecord\",\"=4.0.1\"],[\"actionpack\",\"=4.0.1\"],[\"activesupport\",\"=4.0.1\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.15\",\"dependencies\":[[\"bundler\",\"1.0.0 || 2.0.0\"],[\"railties\",\"=3.2.15\"],[\"actionmailer\",\"=3.2.15\"],[\"activeresource\",\"=3.2.15\"],[\"activerecord\",\"=3.2.15\"],[\"actionpack\",\"=3.2.15\"],[\"activesupport\",\"=3.2.15\"]]},\n  {\"name\":\"rails\",\"number\":\"0.11.0\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.0.2\"],[\"activerecord\",\"=1.9.0\"],[\"actionpack\",\"=1.6.0\"],[\"actionmailer\",\"=0.8.0\"],[\"actionwebservice\",\"=0.6.1\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.2\",\"dependencies\":[[\"activesupport\",\"=3.0.2\"],[\"actionpack\",\"=3.0.2\"],[\"activerecord\",\"=3.0.2\"],[\"activeresource\",\"=3.0.2\"],[\"actionmailer\",\"=3.0.2\"],[\"railties\",\"=3.0.2\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.0\",\"dependencies\":[[\"activesupport\",\"=3.2.0\"],[\"actionpack\",\"=3.2.0\"],[\"activerecord\",\"=3.2.0\"],[\"activeresource\",\"=3.2.0\"],[\"actionmailer\",\"=3.2.0\"],[\"railties\",\"=3.2.0\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.1.5\",\"dependencies\":[[\"activesupport\",\"=3.1.5\"],[\"actionpack\",\"=3.1.5\"],[\"activerecord\",\"=3.1.5\"],[\"activeresource\",\"=3.1.5\"],[\"actionmailer\",\"=3.1.5\"],[\"railties\",\"=3.1.5\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"0.13.0\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.1.0\"],[\"activerecord\",\"=1.11.0\"],[\"actionpack\",\"=1.9.0\"],[\"actionmailer\",\"=1.0.0\"],[\"actionwebservice\",\"=0.8.0\"]]},\n  {\"name\":\"rails\",\"number\":\"0.8.5\",\"dependencies\":[[\"rake\",null],[\"activerecord\",\"1.1.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"actionpack\",null],[\"actionmailer\",null]]},\n  {\"name\":\"rails\",\"number\":\"3.2.5\",\"dependencies\":[[\"activesupport\",\"=3.2.5\"],[\"actionpack\",\"=3.2.5\"],[\"activerecord\",\"=3.2.5\"],[\"activeresource\",\"=3.2.5\"],[\"actionmailer\",\"=3.2.5\"],[\"railties\",\"=3.2.5\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.7\",\"dependencies\":[[\"activesupport\",\"=3.2.7\"],[\"actionpack\",\"=3.2.7\"],[\"activerecord\",\"=3.2.7\"],[\"activeresource\",\"=3.2.7\"],[\"actionmailer\",\"=3.2.7\"],[\"railties\",\"=3.2.7\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.2\",\"dependencies\":[[\"activesupport\",\"=3.2.2\"],[\"actionpack\",\"=3.2.2\"],[\"activerecord\",\"=3.2.2\"],[\"activeresource\",\"=3.2.2\"],[\"actionmailer\",\"=3.2.2\"],[\"railties\",\"=3.2.2\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.5\",\"dependencies\":[[\"activesupport\",\"=3.0.5\"],[\"actionpack\",\"=3.0.5\"],[\"activerecord\",\"=3.0.5\"],[\"activeresource\",\"=3.0.5\"],[\"actionmailer\",\"=3.0.5\"],[\"railties\",\"=3.0.5\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"1.2.1\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.4.0\"],[\"activerecord\",\"=1.15.1\"],[\"actionpack\",\"=1.13.1\"],[\"actionmailer\",\"=1.3.1\"],[\"actionwebservice\",\"=1.2.1\"]]},\n  {\"name\":\"rails\",\"number\":\"2.2.3\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.2.3\"],[\"activerecord\",\"=2.2.3\"],[\"actionpack\",\"=2.2.3\"],[\"actionmailer\",\"=2.2.3\"],[\"activeresource\",\"=2.2.3\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.7\",\"dependencies\":[[\"activesupport\",\"=3.0.7\"],[\"actionpack\",\"=3.0.7\"],[\"activerecord\",\"=3.0.7\"],[\"activeresource\",\"=3.0.7\"],[\"actionmailer\",\"=3.0.7\"],[\"railties\",\"=3.0.7\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"0.9.2\",\"dependencies\":[[\"rake\",null],[\"activerecord\",\"1.3.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"actionpack\",\"1.1.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"actionmailer\",null]]},\n  {\"name\":\"rails\",\"number\":\"2.3.10\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.10\"],[\"activerecord\",\"=2.3.10\"],[\"actionpack\",\"=2.3.10\"],[\"actionmailer\",\"=2.3.10\"],[\"activeresource\",\"=2.3.10\"]]},\n  {\"name\":\"rails\",\"number\":\"2.3.7\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.7\"],[\"activerecord\",\"=2.3.7\"],[\"actionpack\",\"=2.3.7\"],[\"actionmailer\",\"=2.3.7\"],[\"activeresource\",\"=2.3.7\"]]},\n  {\"name\":\"rails\",\"number\":\"0.10.1\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.0.1\"],[\"activerecord\",\"=1.8.0\"],[\"actionpack\",\"=1.5.1\"],[\"actionmailer\",\"=0.7.1\"],[\"actionwebservice\",\"=0.6.0\"]]},\n  {\"name\":\"rails\",\"number\":\"1.2.5\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.4.4\"],[\"activerecord\",\"=1.15.5\"],[\"actionpack\",\"=1.13.5\"],[\"actionmailer\",\"=1.3.5\"],[\"actionwebservice\",\"=1.2.5\"]]},\n  {\"name\":\"rails\",\"number\":\"1.1.1\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.3.1\"],[\"activerecord\",\"=1.14.1\"],[\"actionpack\",\"=1.12.1\"],[\"actionmailer\",\"=1.2.1\"],[\"actionwebservice\",\"=1.1.1\"]]},\n  {\"name\":\"rails\",\"number\":\"0.12.0\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.0.4\"],[\"activerecord\",\"=1.10.0\"],[\"actionpack\",\"=1.8.0\"],[\"actionmailer\",\"=0.9.0\"],[\"actionwebservice\",\"=0.7.0\"]]},\n  {\"name\":\"rails\",\"number\":\"1.2.4\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.4.3\"],[\"activerecord\",\"=1.15.4\"],[\"actionpack\",\"=1.13.4\"],[\"actionmailer\",\"=1.3.4\"],[\"actionwebservice\",\"=1.2.4\"]]},\n  {\"name\":\"rails\",\"number\":\"1.2.3\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.4.2\"],[\"activerecord\",\"=1.15.3\"],[\"actionpack\",\"=1.13.3\"],[\"actionmailer\",\"=1.3.3\"],[\"actionwebservice\",\"=1.2.3\"]]},\n  {\"name\":\"rails\",\"number\":\"2.3.2\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.2\"],[\"activerecord\",\"=2.3.2\"],[\"actionpack\",\"=2.3.2\"],[\"actionmailer\",\"=2.3.2\"],[\"activeresource\",\"=2.3.2\"]]},\n  {\"name\":\"rails\",\"number\":\"0.13.1\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.1.1\"],[\"activerecord\",\"=1.11.1\"],[\"actionpack\",\"=1.9.1\"],[\"actionmailer\",\"=1.0.1\"],[\"actionwebservice\",\"=0.8.1\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.16\",\"dependencies\":[[\"activesupport\",\"=3.0.16\"],[\"actionpack\",\"=3.0.16\"],[\"activerecord\",\"=3.0.16\"],[\"activeresource\",\"=3.0.16\"],[\"actionmailer\",\"=3.0.16\"],[\"railties\",\"=3.0.16\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.1.1\",\"dependencies\":[[\"activesupport\",\"=3.1.1\"],[\"actionpack\",\"=3.1.1\"],[\"activerecord\",\"=3.1.1\"],[\"activeresource\",\"=3.1.1\"],[\"actionmailer\",\"=3.1.1\"],[\"railties\",\"=3.1.1\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.1.6\",\"dependencies\":[[\"activesupport\",\"=3.1.6\"],[\"actionpack\",\"=3.1.6\"],[\"activerecord\",\"=3.1.6\"],[\"activeresource\",\"=3.1.6\"],[\"actionmailer\",\"=3.1.6\"],[\"railties\",\"=3.1.6\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.1\",\"dependencies\":[[\"activesupport\",\"=3.2.1\"],[\"actionpack\",\"=3.2.1\"],[\"activerecord\",\"=3.2.1\"],[\"activeresource\",\"=3.2.1\"],[\"actionmailer\",\"=3.2.1\"],[\"railties\",\"=3.2.1\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"2.0.5\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.0.5\"],[\"activerecord\",\"=2.0.5\"],[\"actionpack\",\"=2.0.5\"],[\"actionmailer\",\"=2.0.5\"],[\"activeresource\",\"=2.0.5\"]]},\n  {\"name\":\"rails\",\"number\":\"2.3.11\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.11\"],[\"activerecord\",\"=2.3.11\"],[\"actionpack\",\"=2.3.11\"],[\"actionmailer\",\"=2.3.11\"],[\"activeresource\",\"=2.3.11\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.12\",\"dependencies\":[[\"activesupport\",\"=3.0.12\"],[\"actionpack\",\"=3.0.12\"],[\"activerecord\",\"=3.0.12\"],[\"activeresource\",\"=3.0.12\"],[\"actionmailer\",\"=3.0.12\"],[\"railties\",\"=3.0.12\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.1\",\"dependencies\":[[\"activesupport\",\"=3.0.1\"],[\"actionpack\",\"=3.0.1\"],[\"activerecord\",\"=3.0.1\"],[\"activeresource\",\"=3.0.1\"],[\"actionmailer\",\"=3.0.1\"],[\"railties\",\"=3.0.1\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"2.3.14\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.14\"],[\"activerecord\",\"=2.3.14\"],[\"actionpack\",\"=2.3.14\"],[\"actionmailer\",\"=2.3.14\"],[\"activeresource\",\"=2.3.14\"]]},\n  {\"name\":\"rails\",\"number\":\"0.14.1\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.2.1\"],[\"activerecord\",\"=1.12.1\"],[\"actionpack\",\"=1.10.1\"],[\"actionmailer\",\"=1.1.1\"],[\"actionwebservice\",\"=0.9.1\"]]},\n  {\"name\":\"rails\",\"number\":\"2.1.1\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.1.1\"],[\"activerecord\",\"=2.1.1\"],[\"actionpack\",\"=2.1.1\"],[\"actionmailer\",\"=2.1.1\"],[\"activeresource\",\"=2.1.1\"]]},\n  {\"name\":\"rails\",\"number\":\"2.0.0\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.0.0\"],[\"activerecord\",\"=2.0.0\"],[\"actionpack\",\"=2.0.0\"],[\"actionmailer\",\"=2.0.0\"],[\"activeresource\",\"=2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"0.14.4\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.2.4\"],[\"activerecord\",\"=1.13.1\"],[\"actionpack\",\"=1.11.1\"],[\"actionmailer\",\"=1.1.4\"],[\"actionwebservice\",\"=0.9.4\"]]},\n  {\"name\":\"rails\",\"number\":\"1.1.4\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.3.1\"],[\"activerecord\",\"=1.14.3\"],[\"actionpack\",\"=1.12.3\"],[\"actionmailer\",\"=1.2.3\"],[\"actionwebservice\",\"=1.1.4\"]]},\n  {\"name\":\"rails\",\"number\":\"2.3.8\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.8\"],[\"activerecord\",\"=2.3.8\"],[\"actionpack\",\"=2.3.8\"],[\"actionmailer\",\"=2.3.8\"],[\"activeresource\",\"=2.3.8\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.14\",\"dependencies\":[[\"activesupport\",\"=3.0.14\"],[\"actionpack\",\"=3.0.14\"],[\"activerecord\",\"=3.0.14\"],[\"activeresource\",\"=3.0.14\"],[\"actionmailer\",\"=3.0.14\"],[\"railties\",\"=3.0.14\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.1.8\",\"dependencies\":[[\"activesupport\",\"=3.1.8\"],[\"actionpack\",\"=3.1.8\"],[\"activerecord\",\"=3.1.8\"],[\"activeresource\",\"=3.1.8\"],[\"actionmailer\",\"=3.1.8\"],[\"railties\",\"=3.1.8\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.6\",\"dependencies\":[[\"activesupport\",\"=3.2.6\"],[\"actionpack\",\"=3.2.6\"],[\"activerecord\",\"=3.2.6\"],[\"activeresource\",\"=3.2.6\"],[\"actionmailer\",\"=3.2.6\"],[\"railties\",\"=3.2.6\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"0.12.1\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.0.4\"],[\"activerecord\",\"=1.10.1\"],[\"actionpack\",\"=1.8.1\"],[\"actionmailer\",\"=0.9.1\"],[\"actionwebservice\",\"=0.7.1\"]]},\n  {\"name\":\"rails\",\"number\":\"3.1.7\",\"dependencies\":[[\"activesupport\",\"=3.1.7\"],[\"actionpack\",\"=3.1.7\"],[\"activerecord\",\"=3.1.7\"],[\"activeresource\",\"=3.1.7\"],[\"actionmailer\",\"=3.1.7\"],[\"railties\",\"=3.1.7\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"0.9.0\",\"dependencies\":[[\"rake\",null],[\"activerecord\",\"1.1.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"actionpack\",null],[\"actionmailer\",null]]},\n  {\"name\":\"rails\",\"number\":\"0.14.3\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.2.3\"],[\"activerecord\",\"=1.13.0\"],[\"actionpack\",\"=1.11.0\"],[\"actionmailer\",\"=1.1.3\"],[\"actionwebservice\",\"=0.9.3\"]]},\n  {\"name\":\"rails\",\"number\":\"1.2.6\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.4.4\"],[\"activerecord\",\"=1.15.6\"],[\"actionpack\",\"=1.13.6\"],[\"actionmailer\",\"=1.3.6\"],[\"actionwebservice\",\"=1.2.6\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.6\",\"dependencies\":[[\"activesupport\",\"=3.0.6\"],[\"actionpack\",\"=3.0.6\"],[\"activerecord\",\"=3.0.6\"],[\"activeresource\",\"=3.0.6\"],[\"actionmailer\",\"=3.0.6\"],[\"railties\",\"=3.0.6\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.3\",\"dependencies\":[[\"activesupport\",\"=3.0.3\"],[\"actionpack\",\"=3.0.3\"],[\"activerecord\",\"=3.0.3\"],[\"activeresource\",\"=3.0.3\"],[\"actionmailer\",\"=3.0.3\"],[\"railties\",\"=3.0.3\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"2.3.6\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.6\"],[\"activerecord\",\"=2.3.6\"],[\"actionpack\",\"=2.3.6\"],[\"actionmailer\",\"=2.3.6\"],[\"activeresource\",\"=2.3.6\"]]},\n  {\"name\":\"rails\",\"number\":\"1.1.5\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.3.1\"],[\"activerecord\",\"=1.14.4\"],[\"actionpack\",\"=1.12.4\"],[\"actionmailer\",\"=1.2.4\"],[\"actionwebservice\",\"=1.1.5\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.9\",\"dependencies\":[[\"activesupport\",\"=3.0.9\"],[\"actionpack\",\"=3.0.9\"],[\"activerecord\",\"=3.0.9\"],[\"activeresource\",\"=3.0.9\"],[\"actionmailer\",\"=3.0.9\"],[\"railties\",\"=3.0.9\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"1.1.2\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.3.1\"],[\"activerecord\",\"=1.14.2\"],[\"actionpack\",\"=1.12.1\"],[\"actionmailer\",\"=1.2.1\"],[\"actionwebservice\",\"=1.1.2\"]]},\n  {\"name\":\"rails\",\"number\":\"0.9.1\",\"dependencies\":[[\"rake\",null],[\"activerecord\",\"1.2.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"actionpack\",\"1.0.1 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"actionmailer\",null]]},\n  {\"name\":\"rails\",\"number\":\"2.2.2\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.2.2\"],[\"activerecord\",\"=2.2.2\"],[\"actionpack\",\"=2.2.2\"],[\"actionmailer\",\"=2.2.2\"],[\"activeresource\",\"=2.2.2\"]]},\n  {\"name\":\"rails\",\"number\":\"1.1.0\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.3.0\"],[\"activerecord\",\"=1.14.0\"],[\"actionpack\",\"=1.12.0\"],[\"actionmailer\",\"=1.2.0\"],[\"actionwebservice\",\"=1.1.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.1.4\",\"dependencies\":[[\"activesupport\",\"=3.1.4\"],[\"actionpack\",\"=3.1.4\"],[\"activerecord\",\"=3.1.4\"],[\"activeresource\",\"=3.1.4\"],[\"actionmailer\",\"=3.1.4\"],[\"railties\",\"=3.1.4\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.17\",\"dependencies\":[[\"activesupport\",\"=3.0.17\"],[\"actionpack\",\"=3.0.17\"],[\"activerecord\",\"=3.0.17\"],[\"activeresource\",\"=3.0.17\"],[\"actionmailer\",\"=3.0.17\"],[\"railties\",\"=3.0.17\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.13\",\"dependencies\":[[\"activesupport\",\"=3.0.13\"],[\"actionpack\",\"=3.0.13\"],[\"activerecord\",\"=3.0.13\"],[\"activeresource\",\"=3.0.13\"],[\"actionmailer\",\"=3.0.13\"],[\"railties\",\"=3.0.13\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"0.10.0\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.0.0\"],[\"activerecord\",\"=1.7.0\"],[\"actionpack\",\"=1.5.0\"],[\"actionmailer\",\"=0.7.0\"],[\"actionwebservice\",\"=0.5.0\"]]},\n  {\"name\":\"rails\",\"number\":\"0.14.2\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.2.2\"],[\"activerecord\",\"=1.12.2\"],[\"actionpack\",\"=1.10.2\"],[\"actionmailer\",\"=1.1.2\"],[\"actionwebservice\",\"=0.9.2\"]]},\n  {\"name\":\"rails\",\"number\":\"1.2.0\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.4.0\"],[\"activerecord\",\"=1.15.0\"],[\"actionpack\",\"=1.13.0\"],[\"actionmailer\",\"=1.3.0\"],[\"actionwebservice\",\"=1.2.0\"]]},\n  {\"name\":\"rails\",\"number\":\"2.3.3\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.3\"],[\"activerecord\",\"=2.3.3\"],[\"actionpack\",\"=2.3.3\"],[\"actionmailer\",\"=2.3.3\"],[\"activeresource\",\"=2.3.3\"]]},\n  {\"name\":\"rails\",\"number\":\"2.0.4\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.0.4\"],[\"activerecord\",\"=2.0.4\"],[\"actionpack\",\"=2.0.4\"],[\"actionmailer\",\"=2.0.4\"],[\"activeresource\",\"=2.0.4\"]]},\n  {\"name\":\"rails\",\"number\":\"1.2.2\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.4.1\"],[\"activerecord\",\"=1.15.2\"],[\"actionpack\",\"=1.13.2\"],[\"actionmailer\",\"=1.3.2\"],[\"actionwebservice\",\"=1.2.2\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.8\",\"dependencies\":[[\"activesupport\",\"=3.0.8\"],[\"actionpack\",\"=3.0.8\"],[\"activerecord\",\"=3.0.8\"],[\"activeresource\",\"=3.0.8\"],[\"actionmailer\",\"=3.0.8\"],[\"railties\",\"=3.0.8\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"0.9.3\",\"dependencies\":[[\"rake\",null],[\"activerecord\",\"1.4.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"actionpack\",\"1.2.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"actionmailer\",null]]},\n  {\"name\":\"rails\",\"number\":\"3.0.15\",\"dependencies\":[[\"activesupport\",\"=3.0.15\"],[\"actionpack\",\"=3.0.15\"],[\"activerecord\",\"=3.0.15\"],[\"activeresource\",\"=3.0.15\"],[\"actionmailer\",\"=3.0.15\"],[\"railties\",\"=3.0.15\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.0\",\"dependencies\":[[\"activesupport\",\"=3.0.0\"],[\"actionpack\",\"=3.0.0\"],[\"activerecord\",\"=3.0.0\"],[\"activeresource\",\"=3.0.0\"],[\"actionmailer\",\"=3.0.0\"],[\"railties\",\"=3.0.0\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"0.9.5\",\"dependencies\":[[\"rake\",null],[\"activerecord\",\"1.6.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"actionpack\",\"1.4.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"actionmailer\",null]]},\n  {\"name\":\"rails\",\"number\":\"0.11.1\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.0.3\"],[\"activerecord\",\"=1.9.1\"],[\"actionpack\",\"=1.7.0\"],[\"actionmailer\",\"=0.8.1\"],[\"actionwebservice\",\"=0.6.2\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.11\",\"dependencies\":[[\"activesupport\",\"=3.0.11\"],[\"actionpack\",\"=3.0.11\"],[\"activerecord\",\"=3.0.11\"],[\"activeresource\",\"=3.0.11\"],[\"actionmailer\",\"=3.0.11\"],[\"railties\",\"=3.0.11\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"0.8.0\",\"dependencies\":[[\"rake\",null],[\"activerecord\",\"1.0.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"actionpack\",null],[\"actionmailer\",null]]},\n  {\"name\":\"rails\",\"number\":\"2.3.9\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.9\"],[\"activerecord\",\"=2.3.9\"],[\"actionpack\",\"=2.3.9\"],[\"actionmailer\",\"=2.3.9\"],[\"activeresource\",\"=2.3.9\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.8\",\"dependencies\":[[\"activesupport\",\"=3.2.8\"],[\"actionpack\",\"=3.2.8\"],[\"activerecord\",\"=3.2.8\"],[\"activeresource\",\"=3.2.8\"],[\"actionmailer\",\"=3.2.8\"],[\"railties\",\"=3.2.8\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"1.0.0\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.2.5\"],[\"activerecord\",\"=1.13.2\"],[\"actionpack\",\"=1.11.2\"],[\"actionmailer\",\"=1.1.5\"],[\"actionwebservice\",\"=1.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"0.9.4\",\"dependencies\":[[\"rake\",null],[\"activerecord\",\"1.5.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"actionpack\",\"1.3.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"actionmailer\",null]]},\n  {\"name\":\"rails\",\"number\":\"2.3.12\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.12\"],[\"activerecord\",\"=2.3.12\"],[\"actionpack\",\"=2.3.12\"],[\"actionmailer\",\"=2.3.12\"],[\"activeresource\",\"=2.3.12\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.10\",\"dependencies\":[[\"activesupport\",\"=3.0.10\"],[\"actionpack\",\"=3.0.10\"],[\"activerecord\",\"=3.0.10\"],[\"activeresource\",\"=3.0.10\"],[\"actionmailer\",\"=3.0.10\"],[\"railties\",\"=3.0.10\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.1.2\",\"dependencies\":[[\"activesupport\",\"=3.1.2\"],[\"actionpack\",\"=3.1.2\"],[\"activerecord\",\"=3.1.2\"],[\"activeresource\",\"=3.1.2\"],[\"actionmailer\",\"=3.1.2\"],[\"railties\",\"=3.1.2\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"2.0.1\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.0.1\"],[\"activerecord\",\"=2.0.1\"],[\"actionpack\",\"=2.0.1\"],[\"actionmailer\",\"=2.0.1\"],[\"activeresource\",\"=2.0.1\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.3\",\"dependencies\":[[\"activesupport\",\"=3.2.3\"],[\"actionpack\",\"=3.2.3\"],[\"activerecord\",\"=3.2.3\"],[\"activeresource\",\"=3.2.3\"],[\"actionmailer\",\"=3.2.3\"],[\"railties\",\"=3.2.3\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.4\",\"dependencies\":[[\"activesupport\",\"=3.2.4\"],[\"actionpack\",\"=3.2.4\"],[\"activerecord\",\"=3.2.4\"],[\"activeresource\",\"=3.2.4\"],[\"actionmailer\",\"=3.2.4\"],[\"railties\",\"=3.2.4\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.1.0\",\"dependencies\":[[\"activesupport\",\"=3.1.0\"],[\"actionpack\",\"=3.1.0\"],[\"activerecord\",\"=3.1.0\"],[\"activeresource\",\"=3.1.0\"],[\"actionmailer\",\"=3.1.0\"],[\"railties\",\"=3.1.0\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.1.3\",\"dependencies\":[[\"activesupport\",\"=3.1.3\"],[\"actionpack\",\"=3.1.3\"],[\"activerecord\",\"=3.1.3\"],[\"activeresource\",\"=3.1.3\"],[\"actionmailer\",\"=3.1.3\"],[\"railties\",\"=3.1.3\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.4\",\"dependencies\":[[\"activesupport\",\"=3.0.4\"],[\"actionpack\",\"=3.0.4\"],[\"activerecord\",\"=3.0.4\"],[\"activeresource\",\"=3.0.4\"],[\"actionmailer\",\"=3.0.4\"],[\"railties\",\"=3.0.4\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"1.1.3\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.3.1\"],[\"activerecord\",\"=1.14.3\"],[\"actionpack\",\"=1.12.2\"],[\"actionmailer\",\"=1.2.2\"],[\"actionwebservice\",\"=1.1.3\"]]},\n  {\"name\":\"rails\",\"number\":\"2.1.2\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.1.2\"],[\"activerecord\",\"=2.1.2\"],[\"actionpack\",\"=2.1.2\"],[\"actionmailer\",\"=2.1.2\"],[\"activeresource\",\"=2.1.2\"]]},\n  {\"name\":\"rails\",\"number\":\"2.3.4\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.4\"],[\"activerecord\",\"=2.3.4\"],[\"actionpack\",\"=2.3.4\"],[\"actionmailer\",\"=2.3.4\"],[\"activeresource\",\"=2.3.4\"]]},\n  {\"name\":\"rails\",\"number\":\"2.3.5\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.5\"],[\"activerecord\",\"=2.3.5\"],[\"actionpack\",\"=2.3.5\"],[\"actionmailer\",\"=2.3.5\"],[\"activeresource\",\"=2.3.5\"]]},\n  {\"name\":\"rails\",\"number\":\"1.1.6\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=1.3.1\"],[\"activerecord\",\"=1.14.4\"],[\"actionpack\",\"=1.12.5\"],[\"actionmailer\",\"=1.2.5\"],[\"actionwebservice\",\"=1.1.6\"]]},\n  {\"name\":\"rails\",\"number\":\"2.1.0\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.1.0\"],[\"activerecord\",\"=2.1.0\"],[\"actionpack\",\"=2.1.0\"],[\"actionmailer\",\"=2.1.0\"],[\"activeresource\",\"=2.1.0\"]]},\n  {\"name\":\"rails\",\"number\":\"2.0.2\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.0.2\"],[\"activerecord\",\"=2.0.2\"],[\"actionpack\",\"=2.0.2\"],[\"actionmailer\",\"=2.0.2\"],[\"activeresource\",\"=2.0.2\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.9\",\"dependencies\":[[\"activesupport\",\"=3.2.9\"],[\"actionpack\",\"=3.2.9\"],[\"activerecord\",\"=3.2.9\"],[\"activeresource\",\"=3.2.9\"],[\"actionmailer\",\"=3.2.9\"],[\"railties\",\"=3.2.9\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.10\",\"dependencies\":[[\"activesupport\",\"=3.2.10\"],[\"actionpack\",\"=3.2.10\"],[\"activerecord\",\"=3.2.10\"],[\"activeresource\",\"=3.2.10\"],[\"actionmailer\",\"=3.2.10\"],[\"railties\",\"=3.2.10\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.18\",\"dependencies\":[[\"activesupport\",\"=3.0.18\"],[\"actionpack\",\"=3.0.18\"],[\"activerecord\",\"=3.0.18\"],[\"activeresource\",\"=3.0.18\"],[\"actionmailer\",\"=3.0.18\"],[\"railties\",\"=3.0.18\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.1.9\",\"dependencies\":[[\"activesupport\",\"=3.1.9\"],[\"actionpack\",\"=3.1.9\"],[\"activerecord\",\"=3.1.9\"],[\"activeresource\",\"=3.1.9\"],[\"actionmailer\",\"=3.1.9\"],[\"railties\",\"=3.1.9\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.11\",\"dependencies\":[[\"activesupport\",\"=3.2.11\"],[\"actionpack\",\"=3.2.11\"],[\"activerecord\",\"=3.2.11\"],[\"activeresource\",\"=3.2.11\"],[\"actionmailer\",\"=3.2.11\"],[\"railties\",\"=3.2.11\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.1.10\",\"dependencies\":[[\"activesupport\",\"=3.1.10\"],[\"actionpack\",\"=3.1.10\"],[\"activerecord\",\"=3.1.10\"],[\"activeresource\",\"=3.1.10\"],[\"actionmailer\",\"=3.1.10\"],[\"railties\",\"=3.1.10\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"2.3.15\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.15\"],[\"activerecord\",\"=2.3.15\"],[\"actionpack\",\"=2.3.15\"],[\"actionmailer\",\"=2.3.15\"],[\"activeresource\",\"=2.3.15\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.19\",\"dependencies\":[[\"activesupport\",\"=3.0.19\"],[\"actionpack\",\"=3.0.19\"],[\"activerecord\",\"=3.0.19\"],[\"activeresource\",\"=3.0.19\"],[\"actionmailer\",\"=3.0.19\"],[\"railties\",\"=3.0.19\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"2.3.16\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.16\"],[\"activerecord\",\"=2.3.16\"],[\"actionpack\",\"=2.3.16\"],[\"actionmailer\",\"=2.3.16\"],[\"activeresource\",\"=2.3.16\"]]},\n  {\"name\":\"rails\",\"number\":\"3.0.20\",\"dependencies\":[[\"activesupport\",\"=3.0.20\"],[\"actionpack\",\"=3.0.20\"],[\"activerecord\",\"=3.0.20\"],[\"activeresource\",\"=3.0.20\"],[\"actionmailer\",\"=3.0.20\"],[\"railties\",\"=3.0.20\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"2.3.17\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.17\"],[\"activerecord\",\"=2.3.17\"],[\"actionpack\",\"=2.3.17\"],[\"actionmailer\",\"=2.3.17\"],[\"activeresource\",\"=2.3.17\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.12\",\"dependencies\":[[\"activesupport\",\"=3.2.12\"],[\"actionpack\",\"=3.2.12\"],[\"activerecord\",\"=3.2.12\"],[\"activeresource\",\"=3.2.12\"],[\"actionmailer\",\"=3.2.12\"],[\"railties\",\"=3.2.12\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.1.11\",\"dependencies\":[[\"activesupport\",\"=3.1.11\"],[\"actionpack\",\"=3.1.11\"],[\"activerecord\",\"=3.1.11\"],[\"activeresource\",\"=3.1.11\"],[\"actionmailer\",\"=3.1.11\"],[\"railties\",\"=3.1.11\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.1.12\",\"dependencies\":[[\"activesupport\",\"=3.1.12\"],[\"actionpack\",\"=3.1.12\"],[\"activerecord\",\"=3.1.12\"],[\"activeresource\",\"=3.1.12\"],[\"actionmailer\",\"=3.1.12\"],[\"railties\",\"=3.1.12\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.13\",\"dependencies\":[[\"activesupport\",\"=3.2.13\"],[\"actionpack\",\"=3.2.13\"],[\"activerecord\",\"=3.2.13\"],[\"activeresource\",\"=3.2.13\"],[\"actionmailer\",\"=3.2.13\"],[\"railties\",\"=3.2.13\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"2.3.18\",\"dependencies\":[[\"rake\",null],[\"activesupport\",\"=2.3.18\"],[\"activerecord\",\"=2.3.18\"],[\"actionpack\",\"=2.3.18\"],[\"actionmailer\",\"=2.3.18\"],[\"activeresource\",\"=2.3.18\"]]},\n  {\"name\":\"rails\",\"number\":\"4.0.0\",\"dependencies\":[[\"activesupport\",\"=4.0.0\"],[\"actionpack\",\"=4.0.0\"],[\"activerecord\",\"=4.0.0\"],[\"actionmailer\",\"=4.0.0\"],[\"railties\",\"=4.0.0\"],[\"bundler\",\"1.3.0 || 2.0.0\"],[\"sprockets-rails\",\"2.0.0\"]]},\n  {\"name\":\"rails\",\"number\":\"3.2.14\",\"dependencies\":[[\"activesupport\",\"=3.2.14\"],[\"actionpack\",\"=3.2.14\"],[\"activerecord\",\"=3.2.14\"],[\"activeresource\",\"=3.2.14\"],[\"actionmailer\",\"=3.2.14\"],[\"railties\",\"=3.2.14\"],[\"bundler\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"rails-observers\",\"number\":\"0.1.0\",\"dependencies\":[[\"railties\",\"4.0.0\"]]},\n  {\"name\":\"rails-observers\",\"number\":\"0.1.1\",\"dependencies\":[[\"railties\",\"4.0.0\"]]},\n  {\"name\":\"rails-observers\",\"number\":\"0.1.2\",\"dependencies\":[[\"activemodel\",\"4.0.0\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.15.2\",\"dependencies\":[[\"ruby-progressbar\",null],[\"require-all\",null],[\"i18n\",null],[\"erubis\",null],[\"colored\",null],[\"code-analyzer\",null],[\"awesome-print\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.15.1\",\"dependencies\":[[\"ruby-progressbar\",null],[\"require-all\",null],[\"i18n\",null],[\"erubis\",null],[\"colored\",null],[\"code-analyzer\",null],[\"awesome-print\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.14.4\",\"dependencies\":[[\"ruby-progressbar\",null],[\"require-all\",null],[\"i18n\",null],[\"erubis\",null],[\"colored\",null],[\"code-analyzer\",null],[\"awesome-print\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.5.1\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.2.0\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.3\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.1.1\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby2ruby\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.25\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.13\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.5.0\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.14\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.4\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby2ruby\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.6\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby2ruby\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.9\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.6.5\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby-progressbar\",\"0.0.9 || 1.0.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"haml\",\"3.0.18 || 4.0.0\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.24\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.0.0\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby-progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"haml\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.5.3\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"progressbar\",\"0.9.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.11.0\",\"dependencies\":[[\"code-analyzer\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null],[\"awesome-print\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.5.3\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.4.2\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"],[\"progressbar\",\"0.9.0\"],[\"colored\",\"1.2.0\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.8.0\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.9.1\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null],[\"awesome-print\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.10.0\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null],[\"awesome-print\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.9.0\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.7.2\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.6.1\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby-progressbar\",\"0.0.9 || 1.0.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.6\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.9\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby2ruby\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.7.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby-progressbar\",\"0.0.9 || 1.0.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"haml\",\"3.0.18 || 4.0.0\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.8.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby-progressbar\",\"0.0.9 || 1.0.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"haml\",\"3.0.18 || 4.0.0\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.8\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.9.0\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby-progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"haml\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.5.5\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"progressbar\",\"0.9.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.4.4\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"],[\"progressbar\",\"0.9.0\"],[\"colored\",\"1.2.0\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.10\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby2ruby\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.5.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"progressbar\",\"0.9.0\"],[\"colored\",\"1.2.0\"],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.22\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.5.1\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"progressbar\",\"0.9.0\"],[\"colored\",\"1.2.0\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.7.4\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby-progressbar\",\"0.0.9 || 1.0.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"haml\",\"3.0.18 || 4.0.0\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.4.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.1.2\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby2ruby\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.19\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.15\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.5\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.8.2\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby-progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"haml\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.6.7\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby-progressbar\",\"0.0.9 || 1.0.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"haml\",\"3.0.18 || 4.0.0\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.10\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.4.0\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.7\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.5.2\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"progressbar\",\"0.9.0\"],[\"colored\",\"1.2.0\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.4.6\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"],[\"progressbar\",\"0.9.0\"],[\"colored\",\"1.2.0\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.4.5\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"],[\"progressbar\",\"0.9.0\"],[\"colored\",\"1.2.0\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.8\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby2ruby\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.10.1\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby-progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"haml\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.23\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.12\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.7.5\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby-progressbar\",\"0.0.9 || 1.0.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"haml\",\"3.0.18 || 4.0.0\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.7.0\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.7.1\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.5.2\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.7.1\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby-progressbar\",\"0.0.9 || 1.0.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"haml\",\"3.0.18 || 4.0.0\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.0\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby2ruby\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.20\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.2\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby2ruby\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.2\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.21\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.3\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby2ruby\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.12\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.16\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.1\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.6.6\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby-progressbar\",\"0.0.9 || 1.0.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"haml\",\"3.0.18 || 4.0.0\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.5\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby2ruby\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.18\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.14\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.15\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.1.0\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.17\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.11\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.13\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.0\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.4\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.11\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.7.3\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby-progressbar\",\"0.0.9 || 1.0.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"haml\",\"3.0.18 || 4.0.0\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.3.0\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.0.1\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby-progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"haml\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.7.2\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby-progressbar\",\"0.0.9 || 1.0.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"haml\",\"3.0.18 || 4.0.0\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.10.0\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby-progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"haml\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.10.1\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null],[\"awesome-print\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.11.1\",\"dependencies\":[[\"code-analyzer\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null],[\"awesome-print\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.2.1\",\"dependencies\":[[\"ruby-parser\",null],[\"ruby2ruby\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.8.1\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby-progressbar\",\"0.0.9 || 1.0.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"haml\",\"3.0.18 || 4.0.0\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.26\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.16\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.4.3\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"],[\"progressbar\",\"0.9.0\"],[\"colored\",\"1.2.0\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.4.1\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"],[\"progressbar\",\"0.9.0\"],[\"colored\",\"1.2.0\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.3.27\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby2ruby\",\"1.2.4\"]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.6.0\",\"dependencies\":[[\"sexp-processor\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"0.5.6\",\"dependencies\":[[\"ruby-parser\",\"2.0.4\"],[\"ruby-progressbar\",\"0.0.9 || 1.0.0\"],[\"colored\",\"1.2.0\"],[\"erubis\",\"2.6.6\"],[\"i18n\",null],[\"activesupport\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.12.0\",\"dependencies\":[[\"code-analyzer\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null],[\"awesome-print\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.13.0\",\"dependencies\":[[\"code-analyzer\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null],[\"awesome-print\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.13.1\",\"dependencies\":[[\"code-analyzer\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null],[\"awesome-print\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.13.2\",\"dependencies\":[[\"code-analyzer\",null],[\"progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null],[\"awesome-print\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.13.3\",\"dependencies\":[[\"code-analyzer\",null],[\"ruby-progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null],[\"awesome-print\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.13.4\",\"dependencies\":[[\"code-analyzer\",null],[\"ruby-progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null],[\"awesome-print\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.13.5\",\"dependencies\":[[\"code-analyzer\",null],[\"ruby-progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null],[\"awesome-print\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.13.8\",\"dependencies\":[[\"code-analyzer\",null],[\"ruby-progressbar\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"activesupport\",null],[\"awesome-print\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.14.0\",\"dependencies\":[[\"activesupport\",null],[\"awesome-print\",null],[\"code-analyzer\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"require-all\",null],[\"ruby-progressbar\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.14.1\",\"dependencies\":[[\"activesupport\",null],[\"awesome-print\",null],[\"code-analyzer\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"require-all\",null],[\"ruby-progressbar\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.14.3\",\"dependencies\":[[\"activesupport\",null],[\"awesome-print\",null],[\"code-analyzer\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"require-all\",null],[\"ruby-progressbar\",null]]},\n  {\"name\":\"rails-best-practices\",\"number\":\"1.14.2\",\"dependencies\":[[\"activesupport\",null],[\"awesome-print\",null],[\"code-analyzer\",null],[\"colored\",null],[\"erubis\",null],[\"i18n\",null],[\"require-all\",null],[\"ruby-progressbar\",null]]},\n  {\"name\":\"railties\",\"number\":\"4.0.4\",\"dependencies\":[[\"thor\",null],[\"rake\",null],[\"actionpack\",\"=4.0.4\"],[\"activesupport\",\"=4.0.4\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.17\",\"dependencies\":[[\"actionpack\",\"=3.2.17\"],[\"activesupport\",\"=3.2.17\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"thor\",null],[\"rack-ssl\",\"1.3.2\"],[\"rake\",null]]},\n  {\"name\":\"railties\",\"number\":\"4.0.3\",\"dependencies\":[[\"thor\",null],[\"rake\",null],[\"actionpack\",\"=4.0.3\"],[\"activesupport\",\"=4.0.3\"]]},\n  {\"name\":\"railties\",\"number\":\"4.0.2\",\"dependencies\":[[\"thor\",null],[\"rake\",null],[\"actionpack\",\"=4.0.2\"],[\"activesupport\",\"=4.0.2\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.16\",\"dependencies\":[[\"actionpack\",\"=3.2.16\"],[\"activesupport\",\"=3.2.16\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"thor\",null],[\"rack-ssl\",\"1.3.2\"],[\"rake\",null]]},\n  {\"name\":\"railties\",\"number\":\"4.0.1\",\"dependencies\":[[\"thor\",null],[\"rake\",null],[\"actionpack\",\"=4.0.1\"],[\"activesupport\",\"=4.0.1\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.15\",\"dependencies\":[[\"actionpack\",\"=3.2.15\"],[\"activesupport\",\"=3.2.15\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"thor\",null],[\"rack-ssl\",\"1.3.2\"],[\"rake\",null]]},\n  {\"name\":\"railties\",\"number\":\"3.0.6\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"activesupport\",\"=3.0.6\"],[\"actionpack\",\"=3.0.6\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.11\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.0.11\"],[\"actionpack\",\"=3.0.11\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.3\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.3\"],[\"actionpack\",\"=3.2.3\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.6\",\"dependencies\":[[\"rake\",null],[\"rack-ssl\",\"1.3.2\"],[\"thor\",null],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.6\"],[\"actionpack\",\"=3.2.6\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.2\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.2\"],[\"actionpack\",\"=3.2.2\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.1\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.0\"],[\"activesupport\",\"=3.0.1\"],[\"actionpack\",\"=3.0.1\"]]},\n  {\"name\":\"railties\",\"number\":\"3.1.7\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.1.7\"],[\"actionpack\",\"=3.1.7\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.2\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"activesupport\",\"=3.0.2\"],[\"actionpack\",\"=3.0.2\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.9\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.0.9\"],[\"actionpack\",\"=3.0.9\"]]},\n  {\"name\":\"railties\",\"number\":\"3.1.3\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.1.3\"],[\"actionpack\",\"=3.1.3\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.5\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"activesupport\",\"=3.0.5\"],[\"actionpack\",\"=3.0.5\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.4\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"activesupport\",\"=3.0.4\"],[\"actionpack\",\"=3.0.4\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.3\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"activesupport\",\"=3.0.3\"],[\"actionpack\",\"=3.0.3\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.0\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.0\"],[\"activesupport\",\"=3.0.0\"],[\"actionpack\",\"=3.0.0\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.16\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.0.16\"],[\"actionpack\",\"=3.0.16\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.7\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"activesupport\",\"=3.0.7\"],[\"actionpack\",\"=3.0.7\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.14\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.0.14\"],[\"actionpack\",\"=3.0.14\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.15\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.0.15\"],[\"actionpack\",\"=3.0.15\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.17\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.0.17\"],[\"actionpack\",\"=3.0.17\"]]},\n  {\"name\":\"railties\",\"number\":\"3.1.6\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.1.6\"],[\"actionpack\",\"=3.1.6\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.4\",\"dependencies\":[[\"rake\",null],[\"rack-ssl\",\"1.3.2\"],[\"thor\",null],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.4\"],[\"actionpack\",\"=3.2.4\"]]},\n  {\"name\":\"railties\",\"number\":\"3.1.5\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.1.5\"],[\"actionpack\",\"=3.1.5\"]]},\n  {\"name\":\"railties\",\"number\":\"3.1.8\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.1.8\"],[\"actionpack\",\"=3.1.8\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.7\",\"dependencies\":[[\"rake\",null],[\"rack-ssl\",\"1.3.2\"],[\"thor\",null],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.7\"],[\"actionpack\",\"=3.2.7\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.8\",\"dependencies\":[[\"rake\",null],[\"rack-ssl\",\"1.3.2\"],[\"thor\",null],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.8\"],[\"actionpack\",\"=3.2.8\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.12\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.0.12\"],[\"actionpack\",\"=3.0.12\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.1\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.1\"],[\"actionpack\",\"=3.2.1\"]]},\n  {\"name\":\"railties\",\"number\":\"3.1.0\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.1.0\"],[\"actionpack\",\"=3.1.0\"]]},\n  {\"name\":\"railties\",\"number\":\"3.1.2\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.1.2\"],[\"actionpack\",\"=3.1.2\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.8\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"activesupport\",\"=3.0.8\"],[\"actionpack\",\"=3.0.8\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.13\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.0.13\"],[\"actionpack\",\"=3.0.13\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.5\",\"dependencies\":[[\"rake\",null],[\"rack-ssl\",\"1.3.2\"],[\"thor\",null],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.5\"],[\"actionpack\",\"=3.2.5\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.0\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.0\"],[\"actionpack\",\"=3.2.0\"]]},\n  {\"name\":\"railties\",\"number\":\"3.1.4\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.1.4\"],[\"actionpack\",\"=3.1.4\"]]},\n  {\"name\":\"railties\",\"number\":\"3.1.1\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.1.1\"],[\"actionpack\",\"=3.1.1\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.10\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.0.10\"],[\"actionpack\",\"=3.0.10\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.9\",\"dependencies\":[[\"rake\",null],[\"rack-ssl\",\"1.3.2\"],[\"thor\",null],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.9\"],[\"actionpack\",\"=3.2.9\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.10\",\"dependencies\":[[\"rake\",null],[\"rack-ssl\",\"1.3.2\"],[\"thor\",null],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.10\"],[\"actionpack\",\"=3.2.10\"]]},\n  {\"name\":\"railties\",\"number\":\"3.1.9\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.1.9\"],[\"actionpack\",\"=3.1.9\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.18\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.0.18\"],[\"actionpack\",\"=3.0.18\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.19\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.0.19\"],[\"actionpack\",\"=3.0.19\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.11\",\"dependencies\":[[\"rake\",null],[\"rack-ssl\",\"1.3.2\"],[\"thor\",null],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.11\"],[\"actionpack\",\"=3.2.11\"]]},\n  {\"name\":\"railties\",\"number\":\"3.1.10\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.1.10\"],[\"actionpack\",\"=3.1.10\"]]},\n  {\"name\":\"railties\",\"number\":\"3.0.20\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.4\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.0.20\"],[\"actionpack\",\"=3.0.20\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.12\",\"dependencies\":[[\"rake\",null],[\"rack-ssl\",\"1.3.2\"],[\"thor\",null],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.12\"],[\"actionpack\",\"=3.2.12\"]]},\n  {\"name\":\"railties\",\"number\":\"3.1.11\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.1.11\"],[\"actionpack\",\"=3.1.11\"]]},\n  {\"name\":\"railties\",\"number\":\"3.2.13\",\"dependencies\":[[\"rake\",null],[\"rack-ssl\",\"1.3.2\"],[\"thor\",null],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.13\"],[\"actionpack\",\"=3.2.13\"]]},\n  {\"name\":\"railties\",\"number\":\"3.1.12\",\"dependencies\":[[\"rake\",null],[\"thor\",\"0.14.6\"],[\"rack-ssl\",\"1.3.2\"],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.1.12\"],[\"actionpack\",\"=3.1.12\"]]},\n  {\"name\":\"railties\",\"number\":\"4.0.0\",\"dependencies\":[[\"activesupport\",\"=4.0.0\"],[\"actionpack\",\"=4.0.0\"],[\"rake\",null],[\"thor\",null]]},\n  {\"name\":\"railties\",\"number\":\"3.2.14\",\"dependencies\":[[\"rake\",null],[\"rack-ssl\",\"1.3.2\"],[\"thor\",null],[\"rdoc\",\"3.4.0 || 4.0.0\"],[\"activesupport\",\"=3.2.14\"],[\"actionpack\",\"=3.2.14\"]]},\n  {\"name\":\"raindrops\",\"number\":\"0.13.0\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.8.1\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.11.0\",\"dependencies\":[]},\n  {\"name\":\"raindrops\",\"number\":\"0.12.0\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"10.2.0\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"10.1.1\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.8.4\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.8.2\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.4.10\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.7.2\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.9.2\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.4.9\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.8.1\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.4.14\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.4.13\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.8.3\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.4.12\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.4.11\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.8.6\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.8.7\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.4.15\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.7.3\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.5.4\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.8.5\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.4.8\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"10.0.0\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.9.3\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.9.4\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"10.0.1\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.9.5\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"10.0.2\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"0.9.6\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"10.0.3\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"10.0.4\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"10.1.0\",\"dependencies\":[]},\n  {\"name\":\"raphael-rails\",\"number\":\"1.5.2\",\"dependencies\":[]},\n  {\"name\":\"raphael-rails\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"raphael-rails\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"raphael-rails\",\"number\":\"2.1.2\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.9.4\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.2.0\",\"dependencies\":[[\"ffi\",\"0.6.3 || 1.0.0\"]]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.2.1\",\"dependencies\":[[\"ffi\",\"0.6.3 || 1.0.0\"]]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.3.8\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.3.10\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.3.6\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.3.9\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.3.5\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.3.4\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.9.2\",\"dependencies\":[]},\n  {\"name\":\"rb-fsevent\",\"number\":\"0.9.3\",\"dependencies\":[]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.9.3\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.9.2\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.5.0\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.3.0\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.8.5\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.8.1\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.5.1\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.4.0\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.8.0\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.7.1\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.7.0\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.6.0\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.2.1\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.8.3\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.8.6\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.8.8\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.8.7\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.8.2\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.7.2\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.8.4\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.9.0\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rb-inotify\",\"number\":\"0.9.1\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"rdoc\",\"number\":\"4.1.1\",\"dependencies\":[[\"json\",\"1.4.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"4.1.0\",\"dependencies\":[[\"json\",\"1.4.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"3.7.0\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.5.10\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.5.11\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.5.8\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.9.0\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.11.0\",\"dependencies\":[[\"json\",\"1.4.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"2.5.3\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.4.1\",\"dependencies\":[[\"minitest\",\"1.3.0 || 2.0.0 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"hoe\",\"1.9.0 || 2.0.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"2.2.1\",\"dependencies\":[[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"2.2.0\",\"dependencies\":[[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"2.5.2\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.0.0\",\"dependencies\":[[\"hoe\",\"1.5.1 || 2.0.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"3.5.0\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.6.0\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.8.0\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.5.1\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.1.0\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.4.2\",\"dependencies\":[[\"minitest\",\"1.3.0 || 2.0.0 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"hoe\",\"1.11.0 || 2.0.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"3.9.2\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.5.3\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.5.1\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.9.3\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.4.0\",\"dependencies\":[[\"minitest\",\"1.3.0 || 2.0.0 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"hoe\",\"1.8.3 || 2.0.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"2.5.9\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.5.2\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.5.7\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.5.4\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.2.0\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.9.1\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.4.0\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.4.3\",\"dependencies\":[[\"minitest\",\"1.3.0 || 2.0.0 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"hoe\",\"1.12.1 || 2.0.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"2.5.0\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.6.1\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.3.0\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.1.0\",\"dependencies\":[[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"3.0.1\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.5.5\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"2.3.0\",\"dependencies\":[[\"minitest\",\"1.3.0 || 2.0.0 || 3.0.0 || 4.0.0 || 5.0.0\"],[\"hoe\",\"1.8.2 || 2.0.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"2.5.6\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.9.4\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.10.0\",\"dependencies\":[[\"json\",\"1.4.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"3.12.0\",\"dependencies\":[[\"json\",\"1.4.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"3.9.5\",\"dependencies\":[]},\n  {\"name\":\"rdoc\",\"number\":\"3.12.1\",\"dependencies\":[[\"json\",\"1.4.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"4.0.0\",\"dependencies\":[[\"json\",\"1.4.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"3.12.2\",\"dependencies\":[[\"json\",\"1.4.0\"]]},\n  {\"name\":\"rdoc\",\"number\":\"4.0.1\",\"dependencies\":[[\"json\",\"1.4.0\"]]},\n  {\"name\":\"redcarpet\",\"number\":\"3.1.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"3.1.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.13.2\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.11.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.14.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.8.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.3.3\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.7.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.14.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.17.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.11.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.10.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.8.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.11.2\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.13.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.5.3\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.11.3\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.10.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.13.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.5.2\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.9.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.8.2\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.14.2\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.15.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.15.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.17.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.16.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.11.4\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.12.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.15.2\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.12.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.12.2\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"1.17.2\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"2.2.1\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"2.2.2\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"2.3.0\",\"dependencies\":[]},\n  {\"name\":\"redcarpet\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"3.0.7\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"3.0.6\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"3.0.5\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.0.11\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"1.0.7\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"0.1.1\",\"dependencies\":[[\"rspec\",null]]},\n  {\"name\":\"redis\",\"number\":\"2.0.5\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.0.8\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.0.7\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.0.10\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.2.2\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.0.12\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"1.0.5\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.0.9\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.2.1\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"0.1.0\",\"dependencies\":[[\"rspec\",null]]},\n  {\"name\":\"redis\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.0.13\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"1.0.6\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"2.0.6\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"3.0.1\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"3.0.2\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"3.0.3\",\"dependencies\":[]},\n  {\"name\":\"redis\",\"number\":\"3.0.4\",\"dependencies\":[]},\n  {\"name\":\"redis-actionpack\",\"number\":\"3.1.4\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"actionpack\",\"=3.1.4\"],[\"redis-rack\",\"=1.3.6\"]]},\n  {\"name\":\"redis-actionpack\",\"number\":\"3.1.3\",\"dependencies\":[[\"redis-store\",\"=1.1.0\"],[\"actionpack\",\"=3.1.3\"],[\"redis-rack\",\"=1.3.5\"]]},\n  {\"name\":\"redis-actionpack\",\"number\":\"3.1.5\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"actionpack\",\"3.1.5 || 4.0.0\"],[\"redis-rack\",\"1.3.6\"]]},\n  {\"name\":\"redis-actionpack\",\"number\":\"3.2.3\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"redis-rack\",\"1.4.0\"],[\"actionpack\",\"3.2.3 || 4.0.0\"]]},\n  {\"name\":\"redis-actionpack\",\"number\":\"3.2.1\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"redis-rack\",\"1.4.0\"],[\"actionpack\",\"=3.2.1\"]]},\n  {\"name\":\"redis-actionpack\",\"number\":\"0.0.0\",\"dependencies\":[]},\n  {\"name\":\"redis-actionpack\",\"number\":\"3.2.2\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"redis-rack\",\"1.4.0\"],[\"actionpack\",\"=3.2.2\"]]},\n  {\"name\":\"redis-actionpack\",\"number\":\"4.0.0\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"redis-rack\",\"1.5.0\"],[\"actionpack\",\"4.0.0\"]]},\n  {\"name\":\"redis-actionpack\",\"number\":\"3.2.4\",\"dependencies\":[[\"redis-store\",\"1.1.4\"],[\"redis-rack\",\"1.4.4\"],[\"actionpack\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"redis-activesupport\",\"number\":\"3.2.5\",\"dependencies\":[[\"activesupport\",\"3.2.0 || 4.0.0\"],[\"redis-store\",\"1.1.0\"]]},\n  {\"name\":\"redis-activesupport\",\"number\":\"3.1.3\",\"dependencies\":[[\"redis-store\",\"=1.1.0\"],[\"activesupport\",\"=3.1.3\"]]},\n  {\"name\":\"redis-activesupport\",\"number\":\"3.1.4\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"activesupport\",\"=3.1.4\"]]},\n  {\"name\":\"redis-activesupport\",\"number\":\"3.1.5\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"activesupport\",\"3.1.5 || 4.0.0\"]]},\n  {\"name\":\"redis-activesupport\",\"number\":\"3.2.3\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"activesupport\",\"3.2.3 || 4.0.0\"]]},\n  {\"name\":\"redis-activesupport\",\"number\":\"3.2.1\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"activesupport\",\"=3.2.1\"]]},\n  {\"name\":\"redis-activesupport\",\"number\":\"3.2.2\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"activesupport\",\"=3.2.2\"]]},\n  {\"name\":\"redis-activesupport\",\"number\":\"0.0.0\",\"dependencies\":[]},\n  {\"name\":\"redis-activesupport\",\"number\":\"4.0.0\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"activesupport\",\"4.0.0\"]]},\n  {\"name\":\"redis-activesupport\",\"number\":\"3.2.4\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"activesupport\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.4.1\",\"dependencies\":[[\"redis\",\"3.0.4\"]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.4.0\",\"dependencies\":[[\"redis\",\"3.0.4\"]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.3.2\",\"dependencies\":[[\"redis\",\"3.0.4\"]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.3.0\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.4.1\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.0.0\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.0.1\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.2.0\",\"dependencies\":[[\"redis\",\"3.0.0\"]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.5.1\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.10.0\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.6.0\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.4.4\",\"dependencies\":[[\"redis\",\"1.0.0 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.2.1\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.4.0\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.2.1\",\"dependencies\":[[\"redis\",\"3.0.0\"]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.4.2\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.5.0\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.7.0\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.8.0\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"0.9.0\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.0.2\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.0.3\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.1.0\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.3.0\",\"dependencies\":[[\"redis\",\"3.0.0\"]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.3.1\",\"dependencies\":[[\"redis\",\"3.0.0\"]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.2.2\",\"dependencies\":[[\"redis\",\"3.0.0\"]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.0.4\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-namespace\",\"number\":\"1.1.1\",\"dependencies\":[[\"redis\",null]]},\n  {\"name\":\"redis-rack\",\"number\":\"1.4.1\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"rack\",\"=1.4.1\"]]},\n  {\"name\":\"redis-rack\",\"number\":\"1.3.5\",\"dependencies\":[[\"redis-store\",\"=1.1.0\"],[\"rack\",\"=1.3.5\"]]},\n  {\"name\":\"redis-rack\",\"number\":\"0.0.0\",\"dependencies\":[]},\n  {\"name\":\"redis-rack\",\"number\":\"1.4.0\",\"dependencies\":[[\"redis-store\",\"=1.1.0\"],[\"rack\",\"=1.4.0\"]]},\n  {\"name\":\"redis-rack\",\"number\":\"1.4.2\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"rack\",\"1.4.1\"]]},\n  {\"name\":\"redis-rack\",\"number\":\"1.3.6\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"rack\",\"=1.3.6\"]]},\n  {\"name\":\"redis-rack\",\"number\":\"1.5.0\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"rack\",\"1.5.0\"]]},\n  {\"name\":\"redis-rack\",\"number\":\"1.4.3\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"rack\",\"1.4.0\"]]},\n  {\"name\":\"redis-rack\",\"number\":\"1.4.4\",\"dependencies\":[[\"redis-store\",\"1.1.4\"],[\"rack\",\"1.4.0\"]]},\n  {\"name\":\"redis-rails\",\"number\":\"3.2.1\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"redis-activesupport\",\"3.2.1 || 4.0.0\"],[\"redis-actionpack\",\"3.2.1 || 4.0.0\"]]},\n  {\"name\":\"redis-rails\",\"number\":\"0.0.0\",\"dependencies\":[]},\n  {\"name\":\"redis-rails\",\"number\":\"3.2.2\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"redis-activesupport\",\"3.2.2 || 4.0.0\"],[\"redis-actionpack\",\"3.2.2 || 4.0.0\"]]},\n  {\"name\":\"redis-rails\",\"number\":\"3.1.5\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"redis-activesupport\",\"3.1.5 || 4.0.0\"],[\"redis-actionpack\",\"3.1.5 || 4.0.0\"]]},\n  {\"name\":\"redis-rails\",\"number\":\"3.2.3\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"redis-activesupport\",\"3.2.3 || 4.0.0\"],[\"redis-actionpack\",\"3.2.3 || 4.0.0\"]]},\n  {\"name\":\"redis-rails\",\"number\":\"3.1.3\",\"dependencies\":[[\"redis-store\",\"=1.1.0\"],[\"redis-activesupport\",\"=3.1.3\"],[\"redis-actionpack\",\"=3.1.3\"]]},\n  {\"name\":\"redis-rails\",\"number\":\"3.1.4\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"redis-activesupport\",\"=3.1.4\"],[\"redis-actionpack\",\"=3.1.4\"]]},\n  {\"name\":\"redis-rails\",\"number\":\"4.0.0\",\"dependencies\":[[\"redis-store\",\"1.1.0\"],[\"redis-activesupport\",\"4.0.0\"],[\"redis-actionpack\",\"4.0.0\"]]},\n  {\"name\":\"redis-rails\",\"number\":\"3.2.4\",\"dependencies\":[[\"redis-store\",\"1.1.4\"],[\"redis-activesupport\",\"3.2.4 || 4.0.0\"],[\"redis-actionpack\",\"3.2.4 || 4.0.0\"]]},\n  {\"name\":\"redis-store\",\"number\":\"0.3.9\",\"dependencies\":[]},\n  {\"name\":\"redis-store\",\"number\":\"0.3.8\",\"dependencies\":[]},\n  {\"name\":\"redis-store\",\"number\":\"0.3.7\",\"dependencies\":[]},\n  {\"name\":\"redis-store\",\"number\":\"1.1.0\",\"dependencies\":[[\"redis\",\"2.2.0 || 3.0.0\"]]},\n  {\"name\":\"redis-store\",\"number\":\"0.3.6\",\"dependencies\":[]},\n  {\"name\":\"redis-store\",\"number\":\"1.1.1\",\"dependencies\":[[\"redis\",\"2.2.0 || 3.0.0\"]]},\n  {\"name\":\"redis-store\",\"number\":\"1.1.3\",\"dependencies\":[[\"redis\",\"2.2.0 || 3.0.0\"]]},\n  {\"name\":\"redis-store\",\"number\":\"1.1.2\",\"dependencies\":[[\"redis\",\"2.2.0 || 3.0.0\"]]},\n  {\"name\":\"redis-store\",\"number\":\"1.1.4\",\"dependencies\":[[\"redis\",\"2.2.0 || 3.0.0\"]]},\n  {\"name\":\"ref\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"ref\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"ref\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"ref\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"ref\",\"number\":\"1.0.5\",\"dependencies\":[]},\n  {\"name\":\"require-all\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"require-all\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"require-all\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"require-all\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"require-all\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"require-all\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"require-all\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"require-all\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"1.3.1\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"1.6.3\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"1.3.0\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"1.1.0\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"1.2.0\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"1.6.0\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"1.5.0\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"1.6.1\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"1.5.1\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"0.8.2\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"0.9.2\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"0.8.1\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"1.4.2\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"1.4.1\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"1.4.0\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"1.6.5\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"1.6.6\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"1.6.7\",\"dependencies\":[[\"mime-types\",\"1.16.0 || 2.0.0\"]]},\n  {\"name\":\"rest-client\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"rest-client\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"2.4.0\",\"dependencies\":[[\"rspec-core\",\"2.4.0\"],[\"rspec-expectations\",\"2.4.0\"],[\"rspec-mocks\",\"2.4.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"2.0.1\",\"dependencies\":[[\"rspec-core\",\"2.0.1\"],[\"rspec-expectations\",\"2.0.1\"],[\"rspec-mocks\",\"2.0.1\"]]},\n  {\"name\":\"rspec\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.1.12\",\"dependencies\":[[\"cucumber\",null],[\"hoe\",\"1.8.2 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"2.6.0\",\"dependencies\":[[\"rspec-core\",\"2.6.0\"],[\"rspec-expectations\",\"2.6.0\"],[\"rspec-mocks\",\"2.6.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.11\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.0.8\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.1.10\",\"dependencies\":[[\"diff-lcs\",null],[\"syntax\",null],[\"hoe\",\"1.8.1 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"2.0.0\",\"dependencies\":[[\"rspec-core\",\"=2.0.0\"],[\"rspec-expectations\",\"=2.0.0\"],[\"rspec-mocks\",\"=2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"1.1.5\",\"dependencies\":[[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"1.2.4\",\"dependencies\":[[\"cucumber\",null],[\"hoe\",\"1.12.1 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.1.7\",\"dependencies\":[[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"2.7.0\",\"dependencies\":[[\"rspec-core\",\"2.7.0\"],[\"rspec-expectations\",\"2.7.0\"],[\"rspec-mocks\",\"2.7.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"1.1.11\",\"dependencies\":[[\"hoe\",\"1.8.1 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.7.2\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.1.4\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.7.4\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.8\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"2.8.0\",\"dependencies\":[[\"rspec-core\",\"2.8.0\"],[\"rspec-expectations\",\"2.8.0\"],[\"rspec-mocks\",\"2.8.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"0.9.2\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.1.6\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.9\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.5\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.1.7\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.0.5\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.0.6\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.14\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.13\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.12\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.2.3\",\"dependencies\":[[\"cucumber\",null],[\"hoe\",\"1.12.1 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"0.9.4\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.8.1\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.2.1\",\"dependencies\":[[\"cucumber\",null],[\"hoe\",\"1.11.0 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"1.1.8\",\"dependencies\":[[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.15\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.2.0\",\"dependencies\":[[\"cucumber\",null],[\"hoe\",\"1.10.0 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.10\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.7\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.6.4\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.7.3\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.0.7\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"2.2.0\",\"dependencies\":[[\"rspec-core\",\"2.2.0\"],[\"rspec-expectations\",\"2.2.0\"],[\"rspec-mocks\",\"2.2.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"0.5.16\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"2.11.0\",\"dependencies\":[[\"rspec-core\",\"2.11.0\"],[\"rspec-expectations\",\"2.11.0\"],[\"rspec-mocks\",\"2.11.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"1.2.9\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.9.3\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.2.2\",\"dependencies\":[[\"cucumber\",null],[\"hoe\",\"1.11.0 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"1.2.6\",\"dependencies\":[[\"cucumber\",null],[\"hoe\",\"1.12.1 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.1.6\",\"dependencies\":[[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.2.5\",\"dependencies\":[[\"cucumber\",null],[\"hoe\",\"1.12.1 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.8.2\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.4\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.1.9\",\"dependencies\":[[\"diff-lcs\",null],[\"spicycode-rcov\",null],[\"syntax\",null],[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"0.0.10\",\"dependencies\":[[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.7.5\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.5.6\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"2.10.0\",\"dependencies\":[[\"rspec-core\",\"2.10.0\"],[\"rspec-expectations\",\"2.10.0\"],[\"rspec-mocks\",\"2.10.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"2.1.0\",\"dependencies\":[[\"rspec-core\",\"2.1.0\"],[\"rspec-expectations\",\"2.1.0\"],[\"rspec-mocks\",\"2.1.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"2.5.0\",\"dependencies\":[[\"rspec-core\",\"2.5.0\"],[\"rspec-expectations\",\"2.5.0\"],[\"rspec-mocks\",\"2.5.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"2.3.0\",\"dependencies\":[[\"rspec-core\",\"2.3.0\"],[\"rspec-expectations\",\"2.3.0\"],[\"rspec-mocks\",\"2.3.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"1.2.7\",\"dependencies\":[[\"cucumber\",null],[\"hoe\",\"2.1.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"2.9.0\",\"dependencies\":[[\"rspec-core\",\"2.9.0\"],[\"rspec-expectations\",\"2.9.0\"],[\"rspec-mocks\",\"2.9.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"1.2.8\",\"dependencies\":[[\"cucumber\",null],[\"hoe\",\"2.3.1\"]]},\n  {\"name\":\"rspec\",\"number\":\"2.12.0\",\"dependencies\":[[\"rspec-core\",\"2.12.0\"],[\"rspec-expectations\",\"2.12.0\"],[\"rspec-mocks\",\"2.12.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"2.13.0\",\"dependencies\":[[\"rspec-core\",\"2.13.0\"],[\"rspec-expectations\",\"2.13.0\"],[\"rspec-mocks\",\"2.13.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"2.14.0\",\"dependencies\":[[\"rspec-core\",\"2.14.0\"],[\"rspec-expectations\",\"2.14.0\"],[\"rspec-mocks\",\"2.14.0\"]]},\n  {\"name\":\"rspec\",\"number\":\"2.14.1\",\"dependencies\":[[\"rspec-core\",\"2.14.0\"],[\"rspec-expectations\",\"2.14.0\"],[\"rspec-mocks\",\"2.14.0\"]]},\n  {\"name\":\"rspec-core\",\"number\":\"2.14.8\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.14.7\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.14.6\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.3.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.10.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.10.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.3.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.2.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.11.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.4.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.9.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.7.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.6.4\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.6.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.6.3\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.8.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.5.2\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.5.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.7.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.11.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.5.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.12.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.12.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.12.2\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.13.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.13.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.14.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.14.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.14.2\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.14.3\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.14.4\",\"dependencies\":[]},\n  {\"name\":\"rspec-core\",\"number\":\"2.14.5\",\"dependencies\":[]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.14.5\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.14.4\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.14.3\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.11.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.6.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.2\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.5.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.2\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.1.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.2\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.3.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.2\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.9.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.0.1\",\"dependencies\":[[\"diff-lcs\",\"1.1.2\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.8.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.2\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.7.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.2\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.2.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.2\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.0.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.2\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.11.3\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.4.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.2\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.9.1\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.10.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.11.1\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.11.2\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.12.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.12.1\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.13.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.14.0\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.14.1\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-expectations\",\"number\":\"2.14.2\",\"dependencies\":[[\"diff-lcs\",\"1.1.3\"]]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.14.6\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.14.5\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.14.4\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.6.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.0.0\",\"dependencies\":[[\"rspec-core\",\"=2.0.0\"],[\"rspec-expectations\",\"=2.0.0\"]]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.0.1\",\"dependencies\":[[\"rspec-core\",\"2.0.1\"],[\"rspec-expectations\",\"2.0.1\"]]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.8.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.5.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.4.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.9.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.11.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.11.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.11.3\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.10.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.3.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.7.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.10.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.11.2\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.12.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.12.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.12.2\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.13.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.13.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.14.0\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.14.1\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.14.2\",\"dependencies\":[]},\n  {\"name\":\"rspec-mocks\",\"number\":\"2.14.3\",\"dependencies\":[]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.14.2\",\"dependencies\":[[\"rspec-mocks\",\"2.14.0\"],[\"rspec-expectations\",\"2.14.0\"],[\"rspec-core\",\"2.14.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"activemodel\",\"3.0.0 || 4.0.0\"],[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.14.1\",\"dependencies\":[[\"rspec-mocks\",\"2.14.0\"],[\"rspec-expectations\",\"2.14.0\"],[\"rspec-core\",\"2.14.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"activemodel\",\"3.0.0 || 4.0.0\"],[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.2.0\",\"dependencies\":[[\"rspec\",\"=1.2.0\"],[\"rack\",null],[\"cucumber\",null],[\"hoe\",\"1.10.0 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.1.8\",\"dependencies\":[[\"rspec\",\"=1.1.8\"],[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.3.2\",\"dependencies\":[[\"rspec\",\"1.3.0 || 2.0.0\"],[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.3.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.3.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.1.12\",\"dependencies\":[[\"rspec\",\"=1.1.12\"],[\"cucumber\",null],[\"hoe\",\"1.8.2 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.1.0\",\"dependencies\":[[\"rspec\",\"2.1.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.1.6\",\"dependencies\":[[\"rspec\",\"=1.1.5\"],[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.1.7\",\"dependencies\":[[\"rspec\",\"=1.1.7\"],[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.0.0\",\"dependencies\":[[\"rspec\",\"=2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.7.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.7.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.8.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.8.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.11.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.10.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.10.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.6.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.6.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.8.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.8.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.1.10\",\"dependencies\":[[\"rspec\",\"1.1.10 || 2.0.0\"],[\"hoe\",\"1.8.1 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.2.6\",\"dependencies\":[[\"rspec\",\"=1.2.6\"],[\"rack\",null],[\"cucumber\",null],[\"hoe\",\"1.12.1 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.5.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.5.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.2.3\",\"dependencies\":[[\"rspec\",\"=1.2.3\"],[\"rack\",null],[\"cucumber\",null],[\"hoe\",\"1.12.1 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.6.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.6.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.9.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.9.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.11.4\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.11.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.3.1\",\"dependencies\":[[\"rspec\",\"1.3.0 || 2.0.0\"],[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.3.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.3.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.2.1\",\"dependencies\":[[\"rspec\",\"=1.2.1\"],[\"rack\",null],[\"cucumber\",null],[\"hoe\",\"1.11.0 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.3.3\",\"dependencies\":[[\"rspec\",\"=1.3.1\"],[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.2.4\",\"dependencies\":[[\"rspec\",\"=1.2.4\"],[\"rack\",null],[\"cucumber\",null],[\"hoe\",\"1.12.1 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.2.0\",\"dependencies\":[[\"rails\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.2.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.4.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.4.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.3.4\",\"dependencies\":[[\"rspec\",\"1.3.1 || 2.0.0\"],[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.3.0\",\"dependencies\":[[\"rspec\",\"1.3.0 || 2.0.0\"],[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.2.2\",\"dependencies\":[[\"rspec\",\"=1.2.2\"],[\"rack\",null],[\"cucumber\",null],[\"hoe\",\"1.11.0 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.1.5\",\"dependencies\":[[\"rspec\",\"=1.1.5\"],[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.2.5\",\"dependencies\":[[\"rspec\",\"=1.2.5\"],[\"rack\",null],[\"cucumber\",null],[\"hoe\",\"1.12.1 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.2.7\",\"dependencies\":[[\"rspec\",\"1.2.7 || 2.0.0\"],[\"rack\",null],[\"cucumber\",null],[\"hoe\",\"2.1.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.0.1\",\"dependencies\":[[\"rspec\",\"2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.2.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.2.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.1.9\",\"dependencies\":[[\"rspec\",\"=1.1.9\"],[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.1.11\",\"dependencies\":[[\"rspec\",\"=1.1.11\"],[\"hoe\",\"1.8.1 || 2.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.4.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.4.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"1.2.9\",\"dependencies\":[[\"rspec\",\"1.2.9 || 2.0.0\"],[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.10.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec\",\"2.10.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.12.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec-core\",\"2.12.0\"],[\"rspec-expectations\",\"2.12.0\"],[\"rspec-mocks\",\"2.12.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.12.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec-core\",\"2.12.0\"],[\"rspec-expectations\",\"2.12.0\"],[\"rspec-mocks\",\"2.12.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.12.2\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec-core\",\"2.12.0\"],[\"rspec-expectations\",\"2.12.0\"],[\"rspec-mocks\",\"2.12.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.13.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec-core\",\"2.13.0\"],[\"rspec-expectations\",\"2.13.0\"],[\"rspec-mocks\",\"2.13.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.13.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec-core\",\"2.13.0\"],[\"rspec-expectations\",\"2.13.0\"],[\"rspec-mocks\",\"2.13.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.13.2\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec-core\",\"2.13.0\"],[\"rspec-expectations\",\"2.13.0\"],[\"rspec-mocks\",\"2.13.0\"]]},\n  {\"name\":\"rspec-rails\",\"number\":\"2.14.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"3.0.0 || 4.0.0\"],[\"railties\",\"3.0.0 || 4.0.0\"],[\"rspec-core\",\"2.14.0\"],[\"rspec-expectations\",\"2.14.0\"],[\"rspec-mocks\",\"2.14.0\"]]},\n  {\"name\":\"ruby-hmac\",\"number\":\"0.3.1\",\"dependencies\":[[\"hoe\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"ruby-hmac\",\"number\":\"0.3.2\",\"dependencies\":[[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"ruby-hmac\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"1.4.2\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"1.4.1\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"0.0.9\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"0.0.10\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"0.11.0\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"ruby-progressbar\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"rubyntlm\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"rubyntlm\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"rubyntlm\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"rubyntlm\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"rubyntlm\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"rubyntlm\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"rubyntlm\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"rubyntlm\",\"number\":\"0.3.4\",\"dependencies\":[]},\n  {\"name\":\"rugged\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"rugged\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"rugged\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"rugged\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"rugged\",\"number\":\"0.16.0\",\"dependencies\":[]},\n  {\"name\":\"rugged\",\"number\":\"0.19.0\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.9.7\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.9.6\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.2.0\",\"dependencies\":[[\"psych\",null]]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.8.2\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.8.1\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.8.3\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.8.4\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.8.5\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.8.6\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.9.2\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.9.3\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.9.4\",\"dependencies\":[]},\n  {\"name\":\"safe-yaml\",\"number\":\"0.9.5\",\"dependencies\":[]},\n  {\"name\":\"sanitize\",\"number\":\"2.1.0\",\"dependencies\":[[\"nokogiri\",\"1.4.4\"]]},\n  {\"name\":\"sanitize\",\"number\":\"1.0.0\",\"dependencies\":[[\"hpricot\",\"0.6.0 || 1.0.0\"]]},\n  {\"name\":\"sanitize\",\"number\":\"1.0.7\",\"dependencies\":[[\"hpricot\",\"0.8.1 || 1.0.0\"]]},\n  {\"name\":\"sanitize\",\"number\":\"2.0.0\",\"dependencies\":[[\"nokogiri\",\"1.4.4\"]]},\n  {\"name\":\"sanitize\",\"number\":\"1.2.0\",\"dependencies\":[[\"nokogiri\",\"1.4.1\"]]},\n  {\"name\":\"sanitize\",\"number\":\"1.0.6\",\"dependencies\":[[\"hpricot\",\"0.6.0 || 1.0.0\"]]},\n  {\"name\":\"sanitize\",\"number\":\"1.0.3\",\"dependencies\":[[\"hpricot\",\"0.6.0 || 1.0.0\"],[\"htmlentities\",\"4.0.0\"]]},\n  {\"name\":\"sanitize\",\"number\":\"1.0.8\",\"dependencies\":[[\"hpricot\",\"0.8.1 || 1.0.0\"]]},\n  {\"name\":\"sanitize\",\"number\":\"1.0.4\",\"dependencies\":[[\"hpricot\",\"0.6.0 || 1.0.0\"],[\"htmlentities\",\"4.0.0\"]]},\n  {\"name\":\"sanitize\",\"number\":\"1.0.2\",\"dependencies\":[[\"hpricot\",\"0.6.0 || 1.0.0\"],[\"htmlentities\",\"4.0.0\"]]},\n  {\"name\":\"sanitize\",\"number\":\"1.0.5\",\"dependencies\":[[\"hpricot\",\"0.6.0 || 1.0.0\"],[\"htmlentities\",\"4.0.0\"]]},\n  {\"name\":\"sanitize\",\"number\":\"1.2.1\",\"dependencies\":[[\"nokogiri\",\"1.4.1\"]]},\n  {\"name\":\"sanitize\",\"number\":\"1.1.0\",\"dependencies\":[[\"nokogiri\",\"1.3.3\"]]},\n  {\"name\":\"sanitize\",\"number\":\"1.0.1\",\"dependencies\":[[\"hpricot\",\"0.6.0 || 1.0.0\"],[\"htmlentities\",\"4.0.0\"]]},\n  {\"name\":\"sanitize\",\"number\":\"2.0.1\",\"dependencies\":[[\"nokogiri\",\"1.4.4\"]]},\n  {\"name\":\"sanitize\",\"number\":\"2.0.2\",\"dependencies\":[[\"nokogiri\",\"1.4.4\"]]},\n  {\"name\":\"sanitize\",\"number\":\"2.0.3\",\"dependencies\":[[\"nokogiri\",\"1.4.4\"],[\"nokogiri\",\"1.4.4\"]]},\n  {\"name\":\"sanitize\",\"number\":\"2.0.4\",\"dependencies\":[[\"nokogiri\",\"1.6.0\"]]},\n  {\"name\":\"sanitize\",\"number\":\"2.0.6\",\"dependencies\":[[\"nokogiri\",\"1.4.4\"]]},\n  {\"name\":\"sanitize\",\"number\":\"2.0.5\",\"dependencies\":[[\"nokogiri\",\"1.4.4\"]]},\n  {\"name\":\"sass\",\"number\":\"3.2.18\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.3.4\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.17\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.16\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.3.3\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.3.2\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.3.1\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.3.0\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"sass\",\"number\":\"3.2.15\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.14\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.13\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.12\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.11\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.6\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.14\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.1\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.13\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.11\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.9\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.18\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.19\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.20\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.7\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.1\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.8\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.0\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.3\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.15\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.12\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.21\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.2\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.4\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.17\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.10\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.5\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.0\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.16\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.2\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.3\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.4\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.5\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.6\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.7\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.8\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.9\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.10\",\"dependencies\":[]},\n  {\"name\":\"sass-rails\",\"number\":\"4.0.2\",\"dependencies\":[[\"sprockets\",\"2.8.0\"],[\"sprockets-rails\",\"2.0.0\"],[\"railties\",\"4.0.0\"],[\"sass\",\"3.2.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"4.0.1\",\"dependencies\":[[\"sprockets-rails\",\"2.0.0\"],[\"railties\",\"4.0.0\"],[\"sass\",\"3.1.10\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.2.0\",\"dependencies\":[[\"sass\",\"3.1.10\"],[\"railties\",\"3.2.0 || 4.0.0\"],[\"tilt\",\"1.3.0 || 2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.1.4\",\"dependencies\":[[\"sass\",\"3.1.4\"],[\"railties\",\"3.1.0 || 4.0.0\"],[\"actionpack\",\"3.1.0 || 4.0.0\"],[\"tilt\",\"1.3.2 || 2.0.0\"],[\"sprockets\",\"2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.2.2\",\"dependencies\":[[\"sass\",\"3.1.10\"],[\"railties\",\"3.2.0 || 4.0.0\"],[\"tilt\",\"1.3.0 || 2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.2.1\",\"dependencies\":[[\"sass\",\"3.1.10\"],[\"railties\",\"3.2.0 || 4.0.0\"],[\"tilt\",\"1.3.0 || 2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.2.4\",\"dependencies\":[[\"sass\",\"3.1.10\"],[\"railties\",\"3.2.0 || 4.0.0\"],[\"tilt\",\"1.3.0 || 2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.2.5\",\"dependencies\":[[\"sass\",\"3.1.10\"],[\"railties\",\"3.2.0 || 4.0.0\"],[\"tilt\",\"1.3.0 || 2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.2.3\",\"dependencies\":[[\"sass\",\"3.1.10\"],[\"railties\",\"3.2.0 || 4.0.0\"],[\"tilt\",\"1.3.0 || 2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.1.1\",\"dependencies\":[[\"sass\",\"3.1.4\"],[\"railties\",\"3.1.0 || 4.0.0\"],[\"actionpack\",\"3.1.0 || 4.0.0\"],[\"tilt\",\"1.3.2 || 2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.1.3\",\"dependencies\":[[\"sass\",\"3.1.4\"],[\"railties\",\"3.1.0 || 4.0.0\"],[\"actionpack\",\"3.1.0 || 4.0.0\"],[\"tilt\",\"1.3.2 || 2.0.0\"],[\"sprockets\",\"2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.1.0\",\"dependencies\":[[\"sass\",\"3.1.4\"],[\"railties\",\"3.1.0 || 4.0.0\"],[\"actionpack\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.1.2\",\"dependencies\":[[\"sass\",\"3.1.4\"],[\"railties\",\"3.1.0 || 4.0.0\"],[\"actionpack\",\"3.1.0 || 4.0.0\"],[\"tilt\",\"1.3.2 || 2.0.0\"],[\"sprockets\",\"2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.1.5\",\"dependencies\":[[\"sass\",\"3.1.10\"],[\"railties\",\"3.1.0 || 4.0.0\"],[\"actionpack\",\"3.1.0 || 4.0.0\"],[\"tilt\",\"1.3.2 || 2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.1.6\",\"dependencies\":[[\"sass\",\"3.1.10\"],[\"railties\",\"3.1.0 || 4.0.0\"],[\"actionpack\",\"3.1.0 || 4.0.0\"],[\"tilt\",\"1.3.2 || 2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.2.6\",\"dependencies\":[[\"sass\",\"3.1.10\"],[\"railties\",\"3.2.0 || 4.0.0\"],[\"tilt\",\"1.3.0 || 2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"3.1.7\",\"dependencies\":[[\"sass\",\"3.1.10\"],[\"railties\",\"3.1.0 || 4.0.0\"],[\"actionpack\",\"3.1.0 || 4.0.0\"],[\"tilt\",\"1.3.2 || 2.0.0\"]]},\n  {\"name\":\"sass-rails\",\"number\":\"4.0.0\",\"dependencies\":[[\"sass\",\"3.1.10\"],[\"railties\",\"4.0.0\"],[\"sprockets-rails\",\"2.0.0\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.4.0\",\"dependencies\":[[\"json\",\"1.8.0\"],[\"rdoc\",\"4.0.0\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.2.18\",\"dependencies\":[[\"rdoc\",\"2.4.2 || 3.0.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.15\",\"dependencies\":[[\"rdoc\",\"3.10.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.2\",\"dependencies\":[[\"rdoc\",\"3.0.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.6\",\"dependencies\":[[\"rdoc\",\"3.0.0 || 4.0.0\"],[\"sanitize\",\"2.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.1\",\"dependencies\":[[\"rdoc\",\"3.0.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.3\",\"dependencies\":[[\"rdoc\",\"3.0.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.2.19\",\"dependencies\":[[\"rdoc\",\"2.4.2 || 3.0.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.2.15\",\"dependencies\":[[\"rdoc\",\"2.4.2 || 3.0.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.0\",\"dependencies\":[[\"rdoc\",\"3.0.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.2.20\",\"dependencies\":[[\"rdoc\",\"=2.4.3\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.4\",\"dependencies\":[[\"rdoc\",\"3.0.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.5\",\"dependencies\":[[\"rdoc\",\"3.0.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.8\",\"dependencies\":[[\"rdoc\",\"3.0.0 || 4.0.0\"],[\"sanitize\",\"2.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.11\",\"dependencies\":[[\"rdoc\",\"3.0.0 || 4.0.0\"],[\"sanitize\",\"2.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.14\",\"dependencies\":[[\"rdoc\",\"3.10.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.16\",\"dependencies\":[[\"rdoc\",\"3.10.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.7\",\"dependencies\":[[\"rdoc\",\"3.0.0 || 4.0.0\"],[\"sanitize\",\"2.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.2.14\",\"dependencies\":[[\"json\",\"1.1.3\"],[\"rdoc\",\"2.4.2 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.2.16\",\"dependencies\":[[\"rdoc\",\"2.4.2 || 3.0.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.9\",\"dependencies\":[[\"rdoc\",\"3.0.0 || 4.0.0\"],[\"sanitize\",\"2.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.10\",\"dependencies\":[[\"rdoc\",\"3.0.0 || 4.0.0\"],[\"sanitize\",\"2.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.2.17\",\"dependencies\":[[\"rdoc\",\"2.4.2 || 3.0.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.18\",\"dependencies\":[[\"rdoc\",\"3.10.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.17\",\"dependencies\":[[\"rdoc\",\"3.10.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.19\",\"dependencies\":[[\"rdoc\",\"3.10.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"sdoc\",\"number\":\"0.3.20\",\"dependencies\":[[\"rdoc\",\"3.10.0 || 4.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"seed-fu\",\"number\":\"2.3.0\",\"dependencies\":[[\"activesupport\",\"3.1.0 || 4.0.0\"],[\"activerecord\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"seed-fu\",\"number\":\"2.0.1\",\"dependencies\":[[\"activerecord\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"seed-fu\",\"number\":\"1.2.3\",\"dependencies\":[[\"rails\",\"2.1.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"seed-fu\",\"number\":\"1.2.2\",\"dependencies\":[[\"rails\",\"2.1.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"seed-fu\",\"number\":\"2.0.0\",\"dependencies\":[[\"activerecord\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"seed-fu\",\"number\":\"2.1.0\",\"dependencies\":[[\"activerecord\",\"3.1.0 || 4.0.0\"],[\"activesupport\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"seed-fu\",\"number\":\"2.2.0\",\"dependencies\":[[\"activerecord\",\"3.1.0 || 4.0.0\"],[\"activesupport\",\"3.1.0 || 4.0.0\"]]},\n  {\"name\":\"seed-fu\",\"number\":\"1.2.1\",\"dependencies\":[[\"rails\",\"2.1.0 || 3.0.0 || 4.0.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.5.4\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.5.3\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.5.2\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.5.1\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.5.0\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.4.9\",\"dependencies\":[[\"sass-rails\",null],[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"0.0.9\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.0.0\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"0.0.2\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"0.0.1\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"2.1.0\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.2.0\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"0.0.7\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"0.0.3\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"0.0.5\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.1.0\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"0.0.4\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"0.0.6\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.1.1\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.2.1\",\"dependencies\":[[\"thor\",\"0.14.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.3.0\",\"dependencies\":[[\"thor\",\"0.14.0\"],[\"sass-rails\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.3.1\",\"dependencies\":[[\"thor\",\"0.14.0\"],[\"sass-rails\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.3.2\",\"dependencies\":[[\"thor\",\"0.14.0\"],[\"sass-rails\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.4.0\",\"dependencies\":[[\"thor\",\"0.14.0\"],[\"sass-rails\",\"3.2.0 || 4.0.0\"]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.4.1\",\"dependencies\":[[\"thor\",\"0.14.0\"],[\"sass-rails\",null]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.4.2\",\"dependencies\":[[\"thor\",\"0.14.0\"],[\"sass-rails\",null]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.4.3\",\"dependencies\":[[\"thor\",\"0.14.0\"],[\"sass-rails\",null]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.4.4\",\"dependencies\":[[\"thor\",\"0.14.0\"],[\"sass-rails\",null]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.4.5\",\"dependencies\":[[\"thor\",\"0.14.0\"],[\"sass-rails\",null]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.4.6\",\"dependencies\":[[\"thor\",\"0.14.0\"],[\"sass-rails\",null]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.4.7\",\"dependencies\":[[\"thor\",\"0.14.0\"],[\"sass-rails\",null]]},\n  {\"name\":\"select2-rails\",\"number\":\"3.4.8\",\"dependencies\":[[\"thor\",\"0.14.0\"],[\"sass-rails\",null]]},\n  {\"name\":\"settingslogic\",\"number\":\"2.0.5\",\"dependencies\":[]},\n  {\"name\":\"settingslogic\",\"number\":\"1.0.0\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"settingslogic\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"settingslogic\",\"number\":\"0.9.0\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"settingslogic\",\"number\":\"2.0.7\",\"dependencies\":[[\"rake\",null],[\"rspec\",null]]},\n  {\"name\":\"settingslogic\",\"number\":\"1.0.2\",\"dependencies\":[[\"activesupport\",null],[\"hoe\",\"1.12.1 || 2.0.0\"]]},\n  {\"name\":\"settingslogic\",\"number\":\"1.0.3\",\"dependencies\":[[\"activesupport\",null],[\"hoe\",\"1.12.1 || 2.0.0\"]]},\n  {\"name\":\"settingslogic\",\"number\":\"2.0.6\",\"dependencies\":[]},\n  {\"name\":\"settingslogic\",\"number\":\"1.0.4\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"settingslogic\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"settingslogic\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"settingslogic\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"settingslogic\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"settingslogic\",\"number\":\"2.0.8\",\"dependencies\":[]},\n  {\"name\":\"settingslogic\",\"number\":\"2.0.9\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.4.2\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.4.1\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.4.0\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"3.1.0\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"3.0.2\",\"dependencies\":[[\"hoe\",\"2.3.0\"]]},\n  {\"name\":\"sexp-processor\",\"number\":\"3.0.5\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"3.0.6\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"3.0.3\",\"dependencies\":[[\"hoe\",\"2.3.3\"]]},\n  {\"name\":\"sexp-processor\",\"number\":\"3.0.4\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"3.0.1\",\"dependencies\":[[\"hoe\",\"1.8.2 || 2.0.0\"]]},\n  {\"name\":\"sexp-processor\",\"number\":\"3.0.8\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"3.0.9\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"3.0.10\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"3.2.0\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.0.1\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"3.0.7\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"3.0.0\",\"dependencies\":[[\"hoe\",\"1.8.0 || 2.0.0\"]]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.0.0\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.1.0\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.1.1\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.1.2\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.1.3\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.1.4\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.1.5\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.2.0\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.2.1\",\"dependencies\":[]},\n  {\"name\":\"sexp-processor\",\"number\":\"4.3.0\",\"dependencies\":[]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"2.5.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"2.4.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"1.3.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"1.1.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"1.2.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"1.4.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"1.4.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"1.4.2\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"bourne\",\"1.1.2\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"1.5.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"bourne\",\"1.2.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"1.5.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"bourne\",\"1.3.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"1.5.2\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"bourne\",\"1.3.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"1.5.4\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"bourne\",\"1.3.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"1.5.5\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"bourne\",\"1.3.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"1.5.6\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"bourne\",\"1.3.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"2.0.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"2.1.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"2.2.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"shoulda-matchers\",\"number\":\"2.3.0\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.17.7\",\"dependencies\":[[\"json\",null],[\"celluloid\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"redis-namespace\",\"1.3.1\"],[\"redis\",\"3.0.6\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.17.6\",\"dependencies\":[[\"json\",null],[\"celluloid\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"redis-namespace\",\"1.3.1\"],[\"redis\",\"3.0.6\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.17.5\",\"dependencies\":[[\"json\",null],[\"celluloid\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"redis-namespace\",\"1.3.1\"],[\"redis\",\"3.0.6\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.17.4\",\"dependencies\":[[\"json\",null],[\"celluloid\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"redis-namespace\",\"1.3.1\"],[\"redis\",\"3.0.6\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.17.3\",\"dependencies\":[[\"json\",null],[\"celluloid\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"redis-namespace\",\"1.3.1\"],[\"redis\",\"3.0.6\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.17.2\",\"dependencies\":[[\"json\",null],[\"celluloid\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"redis-namespace\",\"1.3.1\"],[\"redis\",\"3.0.6\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.17.1\",\"dependencies\":[[\"json\",null],[\"celluloid\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"redis-namespace\",\"1.3.1\"],[\"redis\",\"3.0.6\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.17.0\",\"dependencies\":[[\"json\",null],[\"celluloid\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"redis-namespace\",\"1.3.1\"],[\"redis\",\"3.0.4\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.16.1\",\"dependencies\":[[\"json\",null],[\"celluloid\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"redis-namespace\",\"1.3.1\"],[\"redis\",\"3.0.4\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.16.0\",\"dependencies\":[[\"json\",null],[\"celluloid\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"redis-namespace\",\"1.3.1\"],[\"redis\",\"3.0.4\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.15.2\",\"dependencies\":[[\"json\",null],[\"celluloid\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"redis-namespace\",\"1.3.1\"],[\"redis\",\"3.0.4\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.15.1\",\"dependencies\":[[\"json\",null],[\"celluloid\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"redis-namespace\",\"1.3.1\"],[\"redis\",\"3.0.4\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.15.0\",\"dependencies\":[[\"json\",null],[\"celluloid\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"redis-namespace\",\"1.3.1\"],[\"redis\",\"3.0.4\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.14.1\",\"dependencies\":[[\"redis\",\"3.0.4\"],[\"redis-namespace\",\"1.3.1\"],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",null],[\"json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.0.2\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.11.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.0.3\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.11.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.3.2\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"1.1.4\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.10.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"0.10.1\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",null],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.1.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.11.1\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"1.2.1\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.10.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.2.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.11.1\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.3.1\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"0.8.0\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",null],[\"celluloid\",null],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"0.11.2\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.10.0\"],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"0.9.0\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",null],[\"celluloid\",null],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"0.11.0\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.10.0\"],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"1.0.0\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.10.0\"],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"0.10.0\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",null],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"0.11.1\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.10.0\"],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"0.7.0\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",null],[\"celluloid\",null],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"0.5.0\",\"dependencies\":[[\"redis\",null],[\"connection-pool\",null],[\"celluloid\",null],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"1.1.1\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.10.0\"],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"1.1.0\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.10.0\"],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"1.1.2\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.10.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"1.1.3\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.10.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"0.6.0\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",null],[\"celluloid\",null],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"0.5.1\",\"dependencies\":[[\"redis\",null],[\"connection-pool\",null],[\"celluloid\",null],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"0.9.1\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",null],[\"celluloid\",null],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.0.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.11.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"1.2.0\",\"dependencies\":[[\"redis\",null],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.10.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.2.1\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.11.1\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.3.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.1.1\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.11.1\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.0.1\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.0 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.11.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.3.3\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.4.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.5.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"],[\"sprockets-sass\",null],[\"sass\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.5.1\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"],[\"sprockets-sass\",null],[\"sass\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.5.2\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.5.3\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.5.4\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.6.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"0.9.2 || 1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.6.1\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.6.2\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.6.3\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.6.4\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.6.5\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.7.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.7.1\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.7.2\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.7.3\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.7.4\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.7.5\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.8.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.9.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.10.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"],[\"sinatra\",null],[\"slim\",null],[\"i18n\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.10.1\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.12.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.11.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.13.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.11.1\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",\"0.13.0\"],[\"multi-json\",\"1.0.0\"]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.11.2\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",null],[\"multi-json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.12.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",null],[\"json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.12.1\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",null],[\"json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.12.3\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",null],[\"json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.12.4\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",null],[\"json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.13.0\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",null],[\"json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.13.1\",\"dependencies\":[[\"redis\",\"3.0.0\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",null],[\"json\",null]]},\n  {\"name\":\"sidekiq\",\"number\":\"2.14.0\",\"dependencies\":[[\"redis\",\"3.0.4\"],[\"redis-namespace\",null],[\"connection-pool\",\"1.0.0 || 2.0.0\"],[\"celluloid\",null],[\"json\",null]]},\n  {\"name\":\"simple-oauth\",\"number\":\"0.1.6\",\"dependencies\":[]},\n  {\"name\":\"simple-oauth\",\"number\":\"0.1.8\",\"dependencies\":[]},\n  {\"name\":\"simple-oauth\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"simple-oauth\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"simple-oauth\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"simple-oauth\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"simple-oauth\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"simple-oauth\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"simple-oauth\",\"number\":\"0.1.7\",\"dependencies\":[]},\n  {\"name\":\"simple-oauth\",\"number\":\"0.1.9\",\"dependencies\":[]},\n  {\"name\":\"simple-oauth\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"simplecov\",\"number\":\"0.8.2\",\"dependencies\":[[\"docile\",\"1.1.0\"],[\"simplecov-html\",\"0.8.0\"],[\"multi-json\",null]]},\n  {\"name\":\"simplecov\",\"number\":\"0.8.1\",\"dependencies\":[[\"docile\",\"1.1.0\"],[\"simplecov-html\",\"0.8.0\"],[\"lockfile\",\"2.1.0\"],[\"multi-json\",null]]},\n  {\"name\":\"simplecov\",\"number\":\"0.6.0\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"simplecov-html\",\"0.5.3\"]]},\n  {\"name\":\"simplecov\",\"number\":\"0.5.4\",\"dependencies\":[[\"multi-json\",\"1.0.3\"],[\"simplecov-html\",\"0.5.3\"]]},\n  {\"name\":\"simplecov\",\"number\":\"0.6.4\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"simplecov-html\",\"0.5.3\"]]},\n  {\"name\":\"simplecov\",\"number\":\"0.4.0\",\"dependencies\":[[\"simplecov-html\",\"0.4.0\"]]},\n  {\"name\":\"simplecov\",\"number\":\"0.7.0\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"simplecov-html\",\"0.7.0\"]]},\n  {\"name\":\"simplecov\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"simplecov\",\"number\":\"0.4.1\",\"dependencies\":[[\"simplecov-html\",\"0.4.3\"]]},\n  {\"name\":\"simplecov\",\"number\":\"0.4.2\",\"dependencies\":[[\"simplecov-html\",\"0.4.4\"]]},\n  {\"name\":\"simplecov\",\"number\":\"0.5.3\",\"dependencies\":[[\"multi-json\",\"1.0.3\"],[\"simplecov-html\",\"0.5.3\"]]},\n  {\"name\":\"simplecov\",\"number\":\"0.3.7\",\"dependencies\":[[\"simplecov-html\",null]]},\n  {\"name\":\"simplecov\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"simplecov\",\"number\":\"0.6.3\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"simplecov-html\",\"0.5.3\"]]},\n  {\"name\":\"simplecov\",\"number\":\"0.3.2\",\"dependencies\":[[\"simplecov-html\",null]]},\n  {\"name\":\"simplecov\",\"number\":\"0.3.6\",\"dependencies\":[[\"simplecov-html\",null]]},\n  {\"name\":\"simplecov\",\"number\":\"0.3.5\",\"dependencies\":[[\"simplecov-html\",null]]},\n  {\"name\":\"simplecov\",\"number\":\"0.5.2\",\"dependencies\":[[\"multi-json\",\"1.0.3\"],[\"simplecov-html\",\"0.5.0\"]]},\n  {\"name\":\"simplecov\",\"number\":\"0.3.3\",\"dependencies\":[[\"simplecov-html\",null]]},\n  {\"name\":\"simplecov\",\"number\":\"0.3.9\",\"dependencies\":[[\"simplecov-html\",null]]},\n  {\"name\":\"simplecov\",\"number\":\"0.6.1\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"simplecov-html\",\"0.5.3\"]]},\n  {\"name\":\"simplecov\",\"number\":\"0.6.2\",\"dependencies\":[[\"multi-json\",\"1.3.0\"],[\"simplecov-html\",\"0.5.3\"]]},\n  {\"name\":\"simplecov\",\"number\":\"0.7.1\",\"dependencies\":[[\"multi-json\",\"1.0.0\"],[\"simplecov-html\",\"0.7.1\"]]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.3.8\",\"dependencies\":[]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.4.5\",\"dependencies\":[]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.3.5\",\"dependencies\":[[\"simplecov\",\"0.3.0\"]]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.3.7\",\"dependencies\":[]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.3.1\",\"dependencies\":[[\"simplecov\",null]]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.3.3\",\"dependencies\":[[\"simplecov\",\"0.3.0\"]]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.3.4\",\"dependencies\":[[\"simplecov\",\"0.3.0\"]]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.3.9\",\"dependencies\":[]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.3.0\",\"dependencies\":[[\"simplecov\",null]]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.3.2\",\"dependencies\":[[\"simplecov\",\"0.3.0\"]]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.4.4\",\"dependencies\":[]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"simplecov-html\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"sinatra\",\"number\":\"1.4.4\",\"dependencies\":[[\"rack-protection\",\"1.4.0\"],[\"tilt\",\"1.3.4 || 2.0.0\"],[\"rack\",\"1.4.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.3.3\",\"dependencies\":[[\"rack\",\"0.4.0 || 1.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.1.2\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.2.0\",\"dependencies\":[[\"mongrel\",\"1.0.1\"],[\"rack\",null],[\"rack\",\"=0.3.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.1.6\",\"dependencies\":[[\"mongrel\",\"1.0.1\"],[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"0.2.2\",\"dependencies\":[[\"mongrel\",\"1.0.1\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.1.5\",\"dependencies\":[[\"mongrel\",\"1.0.1\"],[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"0.1.7\",\"dependencies\":[[\"mongrel\",\"1.0.1\"],[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.6\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.3.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"0.1.0\",\"dependencies\":[[\"mongrel\",\"1.0.1\"],[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.3\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.9.2\",\"dependencies\":[[\"rack\",null],[\"shotgun\",null],[\"rack-test\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.0\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.1.3\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.7\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.6\",\"dependencies\":[[\"rack\",\"1.4.0\"],[\"rack-protection\",\"1.3.0\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.2.1\",\"dependencies\":[[\"mongrel\",\"1.0.1\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.3.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.1.4\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.9.5\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.0\",\"dependencies\":[[\"rack\",\"1.3.0\"],[\"rack-protection\",\"1.1.0\"],[\"tilt\",\"1.3.0 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.3.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.1\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.9.6\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"0.9.4\",\"dependencies\":[[\"rack\",null],[\"shotgun\",null],[\"rack-test\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.1.0\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.9.1\",\"dependencies\":[[\"rack\",null],[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"0.9.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.2\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.0.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.8\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.1\",\"dependencies\":[[\"rack\",\"1.3.0\"],[\"rack-protection\",\"1.1.0\"],[\"tilt\",\"1.3.0 || 2.0.0\"],[\"rack\",\"1.3.4\"],[\"rack-protection\",\"1.1.2\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.2\",\"dependencies\":[[\"rack\",\"1.3.6\"],[\"rack-protection\",\"1.2.0\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.3\",\"dependencies\":[[\"rack\",\"1.3.6\"],[\"rack-protection\",\"1.2.0\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.4\",\"dependencies\":[[\"rack\",\"1.4.0\"],[\"rack-protection\",\"1.3.0\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.5\",\"dependencies\":[[\"rack\",\"1.4.0\"],[\"rack-protection\",\"1.3.0\"],[\"tilt\",\"1.3.0 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.9\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"backports\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.4.1\",\"dependencies\":[[\"rack\",\"1.5.2\"],[\"tilt\",\"1.3.4 || 2.0.0\"],[\"rack-protection\",\"1.4.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.4.0\",\"dependencies\":[[\"rack\",\"1.5.2\"],[\"tilt\",\"1.3.4 || 2.0.0\"],[\"rack-protection\",\"1.4.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.4.2\",\"dependencies\":[[\"rack\",\"1.5.2\"],[\"tilt\",\"1.3.4 || 2.0.0\"],[\"rack-protection\",\"1.4.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.4.3\",\"dependencies\":[[\"rack\",\"1.4.0\"],[\"tilt\",\"1.3.4 || 2.0.0\"],[\"rack-protection\",\"1.4.0\"]]},\n  {\"name\":\"six\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"six\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"six\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"six\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"six\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"six\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"six\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"six\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"slack-notifier\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"slack-notifier\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"slack-notifier\",\"number\":\"0.1.1\",\"dependencies\":[[\"httparty\",\"0.11.0\"]]},\n  {\"name\":\"slack-notifier\",\"number\":\"0.1.0\",\"dependencies\":[[\"httparty\",\"0.11.0\"]]},\n  {\"name\":\"slack-notifier\",\"number\":\"0.0.1\",\"dependencies\":[[\"httparty\",\"0.11.0\"]]},\n  {\"name\":\"slack-notifier\",\"number\":\"0.0.2\",\"dependencies\":[[\"httparty\",\"0.11.0\"]]},\n  {\"name\":\"slim\",\"number\":\"2.0.2\",\"dependencies\":[[\"tilt\",\"1.3.3 || 2.0.0\"],[\"temple\",\"0.6.6\"]]},\n  {\"name\":\"slim\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"slim\",\"number\":\"0.8.2\",\"dependencies\":[[\"temple\",\"0.1.6\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.9.0\",\"dependencies\":[[\"temple\",\"0.1.7\"],[\"tilt\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.7.2\",\"dependencies\":[[\"temple\",\"0.1.5\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"1.0.2\",\"dependencies\":[[\"temple\",\"0.3.3\"],[\"tilt\",\"1.3.2 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"1.0.3\",\"dependencies\":[[\"temple\",\"0.3.4\"],[\"tilt\",\"1.3.2 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.7.3\",\"dependencies\":[[\"temple\",\"0.1.5\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"1.1.1\",\"dependencies\":[[\"temple\",\"0.4.0\"],[\"tilt\",\"1.3.2 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.9.2\",\"dependencies\":[[\"temple\",\"0.2.0\"],[\"tilt\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.6.0\",\"dependencies\":[[\"escape-utils\",null]]},\n  {\"name\":\"slim\",\"number\":\"0.9.4\",\"dependencies\":[[\"temple\",\"0.3.0\"],[\"tilt\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.9.3\",\"dependencies\":[[\"temple\",\"0.3.0\"],[\"tilt\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.8.4\",\"dependencies\":[[\"temple\",\"0.1.7\"],[\"tilt\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"slim\",\"number\":\"1.0.4\",\"dependencies\":[[\"temple\",\"0.3.4\"],[\"tilt\",\"1.3.2 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"slim\",\"number\":\"1.0.0\",\"dependencies\":[[\"temple\",\"0.3.0\"],[\"tilt\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.7.1\",\"dependencies\":[[\"temple\",\"0.1.4\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"slim\",\"number\":\"0.7.4\",\"dependencies\":[[\"temple\",\"0.1.6\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.8.1\",\"dependencies\":[[\"temple\",\"0.1.6\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.7.0\",\"dependencies\":[[\"escape-utils\",null],[\"temple\",\"0.1.3\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.8.0\",\"dependencies\":[[\"temple\",\"0.1.6\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.9.1\",\"dependencies\":[[\"temple\",\"0.1.8\"],[\"tilt\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"1.2.2\",\"dependencies\":[[\"temple\",\"0.4.0\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"1.3.0\",\"dependencies\":[[\"temple\",\"0.4.1\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"slim\",\"number\":\"1.0.1\",\"dependencies\":[[\"temple\",\"0.3.0\"],[\"tilt\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"1.3.2\",\"dependencies\":[[\"temple\",\"0.5.0\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"1.3.3\",\"dependencies\":[[\"temple\",\"0.5.5\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.8.3\",\"dependencies\":[[\"temple\",\"0.1.6\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"slim\",\"number\":\"1.2.1\",\"dependencies\":[[\"temple\",\"0.4.0\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"slim\",\"number\":\"1.2.0\",\"dependencies\":[[\"temple\",\"0.4.0\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"slim\",\"number\":\"0.6.1\",\"dependencies\":[[\"escape-utils\",null]]},\n  {\"name\":\"slim\",\"number\":\"1.1.0\",\"dependencies\":[[\"temple\",\"0.3.5\"],[\"tilt\",\"1.3.2 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"1.3.4\",\"dependencies\":[[\"temple\",\"0.5.5\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"1.3.5\",\"dependencies\":[[\"temple\",\"0.5.5\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"1.3.6\",\"dependencies\":[[\"temple\",\"0.5.5\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"1.3.8\",\"dependencies\":[[\"temple\",\"0.6.3\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"1.3.9\",\"dependencies\":[[\"temple\",\"0.6.3\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"2.0.0\",\"dependencies\":[[\"temple\",\"0.6.5\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"slim\",\"number\":\"2.0.1\",\"dependencies\":[[\"temple\",\"0.6.6\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"slop\",\"number\":\"3.5.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.4.7\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.5.5\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.3.1\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.0.3\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"2.4.4\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"2.3.1\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"2.4.1\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.6.1\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"2.3.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.4.1\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.9.1\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.0.2\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.0.1\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.2.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.5.3\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"0.1.9\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.3.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.0.4\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"0.1.7\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.1.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.9.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"2.4.2\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.8.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"0.1.8\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.3.2\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.3.3\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"0.1.6\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"2.4.3\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.5.4\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.1.1\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"2.4.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"1.5.2\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.4.0\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.4.1\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.4.2\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.4.3\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.4.4\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.4.5\",\"dependencies\":[]},\n  {\"name\":\"slop\",\"number\":\"3.4.6\",\"dependencies\":[]},\n  {\"name\":\"spinach\",\"number\":\"0.8.7\",\"dependencies\":[[\"colorize\",\"=0.5.8\"],[\"gherkin-ruby\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.8.6\",\"dependencies\":[[\"colorize\",\"=0.5.8\"],[\"gherkin-ruby\",\"0.3.0\"]]},\n  {\"name\":\"spinach\",\"number\":\"0.5.1\",\"dependencies\":[[\"gherkin-ruby\",\"0.2.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.0.6\",\"dependencies\":[[\"gherkin\",null],[\"minitest\",null],[\"colorize\",null],[\"activesupport\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.3.3\",\"dependencies\":[[\"gherkin-ruby\",\"0.1.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.3.0\",\"dependencies\":[[\"gherkin-ruby\",\"0.1.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.4.0\",\"dependencies\":[[\"gherkin-ruby\",\"0.1.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.1.2\",\"dependencies\":[[\"gherkin\",null],[\"minitest\",null],[\"colorize\",null],[\"hooks\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.4.2\",\"dependencies\":[[\"gherkin-ruby\",\"0.1.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.3.1\",\"dependencies\":[[\"gherkin-ruby\",\"0.1.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.1.1\",\"dependencies\":[[\"gherkin\",null],[\"minitest\",null],[\"colorize\",null],[\"hooks\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.1.3\",\"dependencies\":[[\"gherkin\",null],[\"minitest\",null],[\"colorize\",null],[\"hooks\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.0.1\",\"dependencies\":[[\"gherkin\",null],[\"minitest\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.0.5\",\"dependencies\":[[\"gherkin\",null],[\"minitest\",null],[\"colorize\",null],[\"activesupport\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.0.4\",\"dependencies\":[[\"gherkin\",null],[\"minitest\",null],[\"colorize\",null],[\"activesupport\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.3.4\",\"dependencies\":[[\"gherkin-ruby\",\"0.1.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.1.5\",\"dependencies\":[[\"gherkin\",null],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.1.0\",\"dependencies\":[[\"gherkin\",null],[\"minitest\",null],[\"colorize\",null],[\"hooks\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.1.4\",\"dependencies\":[[\"gherkin\",null],[\"minitest\",null],[\"colorize\",null],[\"hooks\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.5.0\",\"dependencies\":[[\"gherkin-ruby\",\"0.2.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.5.2\",\"dependencies\":[[\"gherkin-ruby\",\"0.2.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.4.1\",\"dependencies\":[[\"gherkin-ruby\",\"0.1.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.0.2\",\"dependencies\":[[\"gherkin\",null],[\"minitest\",null],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.3.2\",\"dependencies\":[[\"gherkin-ruby\",\"0.1.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.6.0\",\"dependencies\":[[\"gherkin-ruby\",\"0.2.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.6.1\",\"dependencies\":[[\"gherkin-ruby\",\"0.2.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.7.0\",\"dependencies\":[[\"gherkin-ruby\",\"0.2.0\"],[\"colorize\",null]]},\n  {\"name\":\"spinach\",\"number\":\"0.8.0\",\"dependencies\":[[\"gherkin-ruby\",\"0.2.1\"],[\"colorize\",\"=0.5.8\"]]},\n  {\"name\":\"spinach\",\"number\":\"0.8.1\",\"dependencies\":[[\"gherkin-ruby\",\"0.2.1\"],[\"colorize\",\"=0.5.8\"]]},\n  {\"name\":\"spinach\",\"number\":\"0.8.2\",\"dependencies\":[[\"gherkin-ruby\",\"0.3.0\"],[\"colorize\",\"=0.5.8\"]]},\n  {\"name\":\"spinach\",\"number\":\"0.8.3\",\"dependencies\":[[\"gherkin-ruby\",\"0.3.0\"],[\"colorize\",\"=0.5.8\"]]},\n  {\"name\":\"spinach\",\"number\":\"0.8.4\",\"dependencies\":[[\"gherkin-ruby\",\"0.3.0\"],[\"colorize\",\"=0.5.8\"]]},\n  {\"name\":\"spinach\",\"number\":\"0.8.5\",\"dependencies\":[[\"gherkin-ruby\",\"0.3.0\"],[\"colorize\",\"=0.5.8\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.0.7\",\"dependencies\":[[\"capybara\",null],[\"spinach\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.0.5\",\"dependencies\":[[\"capybara\",null],[\"spinach\",null],[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.0.1\",\"dependencies\":[[\"capybara\",null],[\"spinach\",\"0.1.0\"],[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.0.2\",\"dependencies\":[[\"capybara\",null],[\"spinach\",\"0.1.0\"],[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.1.1\",\"dependencies\":[[\"capybara\",null],[\"spinach\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.0.6\",\"dependencies\":[[\"capybara\",null],[\"spinach\",null],[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.1.0\",\"dependencies\":[[\"capybara\",null],[\"spinach\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.1.6\",\"dependencies\":[[\"capybara\",\"1.0.0 || 2.0.0\"],[\"spinach\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.1.8\",\"dependencies\":[[\"capybara\",\"1.0.0 || 2.0.0\"],[\"spinach\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.0.3\",\"dependencies\":[[\"capybara\",null],[\"spinach\",null],[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.0.9\",\"dependencies\":[[\"capybara\",null],[\"spinach\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.1.2\",\"dependencies\":[[\"capybara\",null],[\"spinach\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.1.5\",\"dependencies\":[[\"capybara\",null],[\"spinach\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.1.4\",\"dependencies\":[[\"capybara\",null],[\"spinach\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.0.8\",\"dependencies\":[[\"capybara\",null],[\"spinach\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.0.4\",\"dependencies\":[[\"capybara\",null],[\"spinach\",null],[\"rails\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.1.7\",\"dependencies\":[[\"capybara\",\"1.0.0 || 2.0.0\"],[\"spinach\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.2.0\",\"dependencies\":[[\"capybara\",\"2.0.0\"],[\"spinach\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spinach-rails\",\"number\":\"0.2.1\",\"dependencies\":[[\"capybara\",\"2.0.0\"],[\"spinach\",null],[\"railties\",\"3.0.0 || 4.0.0\"]]},\n  {\"name\":\"spork\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.5.6\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.5.8\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.7.7\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.5.10\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.5.9\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.5.7\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.5.5\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.7.4\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.7.8\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.8.4\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.8.1\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.8.3\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.7.5\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.7.2\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.4.4\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.9.2\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.8.5\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.7.6\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.5.11\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.7.3\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.8.2\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.5.4\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"spork\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"0.9.2\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"0.0.11\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"0.0.1\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"spring\",\"number\":\"0.0.2\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"spring\",\"number\":\"0.0.3\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"spring\",\"number\":\"0.0.4\",\"dependencies\":[[\"activesupport\",null]]},\n  {\"name\":\"spring\",\"number\":\"0.0.5\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"0.0.6\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"0.0.7\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"0.0.8\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"0.0.9\",\"dependencies\":[]},\n  {\"name\":\"spring\",\"number\":\"0.0.10\",\"dependencies\":[]},\n  {\"name\":\"spring-commands-rspec\",\"number\":\"1.0.1\",\"dependencies\":[[\"spring\",null]]},\n  {\"name\":\"spring-commands-rspec\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"spring-commands-spinach\",\"number\":\"1.0.0\",\"dependencies\":[[\"spring\",null]]},\n  {\"name\":\"sprockets\",\"number\":\"2.12.0\",\"dependencies\":[[\"tilt\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"multi-json\",\"1.0.0\"],[\"hike\",\"1.2.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.11.0\",\"dependencies\":[[\"tilt\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"multi-json\",\"1.0.0\"],[\"hike\",\"1.2.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.10.1\",\"dependencies\":[[\"tilt\",\"1.1.0 || 2.0.0\"],[\"rack\",\"1.0.0\"],[\"multi-json\",\"1.0.0\"],[\"hike\",\"1.2.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.3.0\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.1.2\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.4.0\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.4.3\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.1.0\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.3.1\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"sprockets\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"sprockets\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"sprockets\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"sprockets\",\"number\":\"2.0.4\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.2.0\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"sprockets\",\"number\":\"2.8.0\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.0.1\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.1.3\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.7.0\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.1.1\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.0.0\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.0.3\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.4.1\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.0.2\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.2.1\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.3.2\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.5.0\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.4.5\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.4.4\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.4.2\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.6.0\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.8.1\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.2.2\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.8.2\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.9.0\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.9.2\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.9.3\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets\",\"number\":\"2.10.0\",\"dependencies\":[[\"hike\",\"1.2.0\"],[\"multi-json\",\"1.0.0\"],[\"rack\",\"1.0.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sprockets-rails\",\"number\":\"2.0.1\",\"dependencies\":[[\"activesupport\",\"3.0.0 || 4.0.0\"],[\"actionpack\",\"4.0.0\"],[\"sprockets\",\"2.8.0\"]]},\n  {\"name\":\"sprockets-rails\",\"number\":\"0.0.0\",\"dependencies\":[]},\n  {\"name\":\"sprockets-rails\",\"number\":\"0.0.1\",\"dependencies\":[[\"sprockets\",\"1.0.2 || 2.0.0\"]]},\n  {\"name\":\"sprockets-rails\",\"number\":\"1.0.0\",\"dependencies\":[[\"sprockets\",\"2.3.1\"],[\"railties\",\"4.0.0\"]]},\n  {\"name\":\"sprockets-rails\",\"number\":\"2.0.0\",\"dependencies\":[[\"sprockets\",\"2.8.0\"],[\"actionpack\",\"4.0.0\"],[\"activesupport\",\"4.0.0\"]]},\n  {\"name\":\"stamp\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"stamp\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"stamp\",\"number\":\"0.1.6\",\"dependencies\":[]},\n  {\"name\":\"stamp\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"stamp\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"stamp\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"stamp\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"stamp\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"stamp\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"stamp\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"stamp\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"stamp\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"stamp\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"stamp\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.7.3\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.8.1\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.7.4\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.7.5\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.9.3\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.9.4\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.10.3\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.10.4\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.10.1\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.7.2\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.7.6\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.9.2\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"0.10.2\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"state-machine\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.4.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.4.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.3.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.2.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.2.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.1.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.3.3\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.5.0\",\"dependencies\":[[\"stringex\",null]]},\n  {\"name\":\"stringex\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.5\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.6\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.7\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.8\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.9\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.10\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.11\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.6.7\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.1.6\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.5.5\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.3.5\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.1.7\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.1.8\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.5.4\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.3.4\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.6.4\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.6.5\",\"dependencies\":[]},\n  {\"name\":\"temple\",\"number\":\"0.6.6\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.3.0\",\"dependencies\":[[\"tins\",\"1.0.0\"]]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.0.5\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.0.7\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"0.0.4\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.0.6\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.1.4\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.1.5\",\"dependencies\":[]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.2.0\",\"dependencies\":[[\"tins\",\"0.8.0 || 1.0.0\"]]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.2.1\",\"dependencies\":[[\"tins\",\"0.8.0 || 1.0.0\"]]},\n  {\"name\":\"term-ansicolor\",\"number\":\"1.2.2\",\"dependencies\":[[\"tins\",\"0.8.0 || 1.0.0\"]]},\n  {\"name\":\"test-after-commit\",\"number\":\"0.2.3\",\"dependencies\":[]},\n  {\"name\":\"test-after-commit\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"test-after-commit\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"test-after-commit\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"test-after-commit\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"test-after-commit\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"test-after-commit\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.12.1\",\"dependencies\":[[\"libv8\",\"3.16.14\"],[\"ref\",null]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.8.1\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.6.2\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.10.0\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.7.5\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.4.8\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.5.5\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.9.10\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.9.2\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.4.4\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.4.5\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.4.7\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.9.3\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.4.6\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.9.9\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.9.8\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.4.9\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.7.4\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.10.1\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.9.5\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.9.4\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.8.2\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.5.4\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.7.2\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.9.6\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.10.2\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.9.0\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.9.1\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.7.3\",\"dependencies\":[]},\n  {\"name\":\"therubyracer\",\"number\":\"0.9.7\",\"dependencies\":[[\"libv8\",\"3.3.10\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.11.0\",\"dependencies\":[[\"ref\",null]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.11.1\",\"dependencies\":[[\"ref\",null],[\"libv8\",\"3.11.8\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.11.2\",\"dependencies\":[[\"ref\",null],[\"libv8\",\"3.11.8\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.11.3\",\"dependencies\":[[\"ref\",null],[\"libv8\",\"3.11.8\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.11.4\",\"dependencies\":[[\"ref\",null],[\"libv8\",\"3.11.8\"]]},\n  {\"name\":\"therubyracer\",\"number\":\"0.12.0\",\"dependencies\":[[\"ref\",null],[\"libv8\",\"3.16.14\"]]},\n  {\"name\":\"thin\",\"number\":\"1.6.2\",\"dependencies\":[[\"daemons\",\"1.0.9\"],[\"eventmachine\",\"1.0.0\"],[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"thin\",\"number\":\"1.6.1\",\"dependencies\":[[\"daemons\",\"1.0.9\"],[\"eventmachine\",\"1.0.0\"],[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"thin\",\"number\":\"1.6.0\",\"dependencies\":[[\"daemons\",\"1.0.9\"],[\"eventmachine\",\"1.0.0\"],[\"rack\",\"1.5.0\"]]},\n  {\"name\":\"thin\",\"number\":\"0.8.2\",\"dependencies\":[[\"rack\",null],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.2.6\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"0.6.4\",\"dependencies\":[[\"rack\",null],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.2.9\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.4.0\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.3.1\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"0.6.3\",\"dependencies\":[[\"rack\",null],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.3.0\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.2.11\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"0.5.2\",\"dependencies\":[[\"eventmachine\",null],[\"rack\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"0.7.0\",\"dependencies\":[[\"rack\",null],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"0.6.2\",\"dependencies\":[[\"rack\",null],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.2.7\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.2.4\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.2.5\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"0.5.0\",\"dependencies\":[[\"eventmachine\",null],[\"rack\",null]]},\n  {\"name\":\"thin\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"thin\",\"number\":\"1.2.1\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.2.10\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.0.0\",\"dependencies\":[[\"rack\",null],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"0.5.4\",\"dependencies\":[[\"rack\",null],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"0.8.0\",\"dependencies\":[[\"rack\",null],[\"daemons\",\"1.0.9\"],[\"eventmachine\",null]]},\n  {\"name\":\"thin\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"thin\",\"number\":\"0.8.1\",\"dependencies\":[[\"rack\",null],[\"daemons\",\"1.0.9\"],[\"eventmachine\",null]]},\n  {\"name\":\"thin\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"thin\",\"number\":\"0.5.3\",\"dependencies\":[[\"rack\",null],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.2.3\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"0.7.1\",\"dependencies\":[[\"rack\",null],[\"daemons\",\"1.0.9\"],[\"eventmachine\",null]]},\n  {\"name\":\"thin\",\"number\":\"1.2.2\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.5.0\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.2.8\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.4.1\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"0.6.1\",\"dependencies\":[[\"rack\",null],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"0.6.0\",\"dependencies\":[[\"rack\",null],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thin\",\"number\":\"1.5.1\",\"dependencies\":[[\"rack\",\"1.0.0\"],[\"eventmachine\",null],[\"daemons\",\"1.0.9\"]]},\n  {\"name\":\"thor\",\"number\":\"0.19.1\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.19.0\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.14.3\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.13.0\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.15.1\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.11.7\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.11.6\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.15.0\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.9.2\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.9.5\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.13.6\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.13.4\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.14.0\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.12.0\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.14.5\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.14.1\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.12.3\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.14.6\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.13.7\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.11.5\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.13.5\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.14.2\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.9.7\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.9.6\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.9.8\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.15.2\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.13.3\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.14.4\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.15.4\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.16.0\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.11.8\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.12.2\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.13.1\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.15.3\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.13.2\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.9.9\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.13.8\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.17.0\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.18.0\",\"dependencies\":[]},\n  {\"name\":\"thor\",\"number\":\"0.18.1\",\"dependencies\":[]},\n  {\"name\":\"thread-safe\",\"number\":\"0.3.1\",\"dependencies\":[[\"atomic\",\"1.1.7\"]]},\n  {\"name\":\"thread-safe\",\"number\":\"0.2.0\",\"dependencies\":[[\"atomic\",\"1.1.7\"]]},\n  {\"name\":\"thread-safe\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"thread-safe\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"thread-safe\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"thread-safe\",\"number\":\"0.1.3\",\"dependencies\":[[\"atomic\",null]]},\n  {\"name\":\"thread-safe\",\"number\":\"0.1.0\",\"dependencies\":[[\"atomic\",null]]},\n  {\"name\":\"thread-safe\",\"number\":\"0.1.1\",\"dependencies\":[[\"atomic\",null]]},\n  {\"name\":\"thread-safe\",\"number\":\"0.1.2\",\"dependencies\":[[\"atomic\",null]]},\n  {\"name\":\"tilt\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.3\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.4\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.5\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.6\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.7\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.4.1\",\"dependencies\":[]},\n  {\"name\":\"timers\",\"number\":\"2.0.0\",\"dependencies\":[[\"hitimes\",null]]},\n  {\"name\":\"timers\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"timers\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"timers\",\"number\":\"0.0.0\",\"dependencies\":[]},\n  {\"name\":\"timers\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"timers\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"tinder\",\"number\":\"1.9.4\",\"dependencies\":[[\"twitter-stream\",\"0.1.0\"],[\"multi-json\",\"1.7.0\"],[\"mime-types\",\"1.19.0 || 2.0.0\"],[\"json\",\"1.8.0\"],[\"hashie\",\"1.0.0 || 2.0.0\"],[\"faraday-middleware\",\"0.9.0\"],[\"faraday\",\"0.8.9\"],[\"eventmachine\",\"1.0.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.4.0\",\"dependencies\":[[\"activesupport\",null],[\"httparty\",null],[\"mime-types\",null],[\"twitter-stream\",null],[\"eventmachine\",null]]},\n  {\"name\":\"tinder\",\"number\":\"0.1.3\",\"dependencies\":[[\"activesupport\",\"0.0.0 || 1.0.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"hpricot\",\"0.0.0 || 1.0.0\"],[\"hoe\",\"1.1.7 || 2.0.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.2.2\",\"dependencies\":[[\"activesupport\",null],[\"hpricot\",null],[\"mime-types\",null]]},\n  {\"name\":\"tinder\",\"number\":\"1.2.0\",\"dependencies\":[[\"activesupport\",null],[\"hpricot\",null],[\"mime-types\",null],[\"hoe\",\"1.8.2 || 2.0.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.5.0\",\"dependencies\":[[\"activesupport\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"eventmachine\",\"0.12.0 || 1.0.0\"],[\"faraday\",null],[\"faraday-middleware\",null],[\"hashie\",\"1.0.0 || 2.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"multi-json\",\"1.0.0\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"twitter-stream\",\"0.1.0\"],[\"activesupport\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"faraday\",null],[\"faraday-middleware\",null]]},\n  {\"name\":\"tinder\",\"number\":\"0.1.0\",\"dependencies\":[[\"activesupport\",\"0.0.0 || 1.0.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"hpricot\",\"0.0.0 || 1.0.0\"],[\"hoe\",\"1.1.7 || 2.0.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.3.0\",\"dependencies\":[[\"activesupport\",null],[\"mime-types\",null]]},\n  {\"name\":\"tinder\",\"number\":\"0.1.9\",\"dependencies\":[[\"activesupport\",null],[\"hpricot\",null],[\"mime-types\",null],[\"hoe\",\"1.8.2 || 2.0.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.4.1\",\"dependencies\":[[\"activesupport\",null],[\"httparty\",null],[\"mime-types\",null],[\"twitter-stream\",null],[\"eventmachine\",null]]},\n  {\"name\":\"tinder\",\"number\":\"0.1.6\",\"dependencies\":[[\"activesupport\",null],[\"hpricot\",null],[\"hoe\",\"1.5.1 || 2.0.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"0.1.4\",\"dependencies\":[[\"activesupport\",\"0.0.0 || 1.0.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"hpricot\",\"0.0.0 || 1.0.0\"],[\"hoe\",\"1.2.1 || 2.0.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.4.3\",\"dependencies\":[[\"activesupport\",null],[\"faraday\",\"0.5.1\"],[\"multipart-post\",null],[\"mime-types\",null],[\"twitter-stream\",null],[\"eventmachine\",null]]},\n  {\"name\":\"tinder\",\"number\":\"1.6.0\",\"dependencies\":[[\"activesupport\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"eventmachine\",\"0.12.0 || 1.0.0\"],[\"faraday\",null],[\"faraday-middleware\",null],[\"hashie\",\"1.0.0 || 2.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"multi-json\",\"1.0.0\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"twitter-stream\",\"0.1.0\"],[\"activesupport\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"faraday\",null],[\"faraday-middleware\",null]]},\n  {\"name\":\"tinder\",\"number\":\"1.1.7\",\"dependencies\":[[\"activesupport\",null],[\"hpricot\",null],[\"hoe\",\"1.7.0 || 2.0.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.2.1\",\"dependencies\":[[\"activesupport\",null],[\"hpricot\",null],[\"mime-types\",null]]},\n  {\"name\":\"tinder\",\"number\":\"0.1.2\",\"dependencies\":[[\"activesupport\",\"0.0.0 || 1.0.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"hpricot\",\"0.0.0 || 1.0.0\"],[\"hoe\",\"1.1.7 || 2.0.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.3.1\",\"dependencies\":[[\"activesupport\",null],[\"httparty\",null],[\"mime-types\",null]]},\n  {\"name\":\"tinder\",\"number\":\"0.1.8\",\"dependencies\":[[\"activesupport\",null],[\"hpricot\",null],[\"mime-types\",null],[\"hoe\",\"1.8.2 || 2.0.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.4.4\",\"dependencies\":[[\"activesupport\",null],[\"faraday\",\"0.5.1\"],[\"multipart-post\",null],[\"mime-types\",null],[\"twitter-stream\",null],[\"eventmachine\",null]]},\n  {\"name\":\"tinder\",\"number\":\"1.8.0\",\"dependencies\":[[\"activesupport\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"eventmachine\",\"0.12.0 || 1.0.0\"],[\"faraday\",null],[\"faraday-middleware\",null],[\"hashie\",\"1.0.0 || 2.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"multi-json\",\"1.0.0\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"twitter-stream\",\"0.1.0\"],[\"activesupport\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"faraday\",null],[\"faraday-middleware\",null]]},\n  {\"name\":\"tinder\",\"number\":\"1.9.0\",\"dependencies\":[[\"activesupport\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"eventmachine\",null],[\"faraday\",\"0.8.0\"],[\"faraday-middleware\",\"0.8.0\"],[\"hashie\",\"1.0.0 || 2.0.0\"],[\"json\",\"1.6.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"multi-json\",\"1.0.0\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"twitter-stream\",\"0.1.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.9.1\",\"dependencies\":[[\"eventmachine\",null],[\"faraday\",\"0.8.0\"],[\"faraday-middleware\",\"0.8.0\"],[\"hashie\",\"1.0.0 || 2.0.0\"],[\"json\",\"1.6.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"multi-json\",\"1.0.0\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"twitter-stream\",\"0.1.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.7.0\",\"dependencies\":[[\"activesupport\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"eventmachine\",\"0.12.0 || 1.0.0\"],[\"faraday\",null],[\"faraday-middleware\",null],[\"hashie\",\"1.0.0 || 2.0.0\"],[\"mime-types\",\"1.16.0 || 2.0.0\"],[\"multi-json\",\"1.0.0\"],[\"multipart-post\",\"1.1.0 || 2.0.0\"],[\"twitter-stream\",\"0.1.0\"],[\"activesupport\",\"2.3.0 || 3.0.0 || 4.0.0\"],[\"faraday\",null],[\"faraday-middleware\",null]]},\n  {\"name\":\"tinder\",\"number\":\"0.1.1\",\"dependencies\":[[\"activesupport\",\"0.0.0 || 1.0.0 || 2.0.0 || 3.0.0 || 4.0.0\"],[\"hpricot\",\"0.0.0 || 1.0.0\"],[\"hoe\",\"1.1.7 || 2.0.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.4.2\",\"dependencies\":[[\"activesupport\",null],[\"faraday\",\"0.5.1\"],[\"multipart-post\",null],[\"mime-types\",null],[\"twitter-stream\",null],[\"eventmachine\",null]]},\n  {\"name\":\"tinder\",\"number\":\"0.1.5\",\"dependencies\":[[\"activesupport\",null],[\"hpricot\",null],[\"hoe\",\"1.4.0 || 2.0.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.9.2\",\"dependencies\":[[\"eventmachine\",\"1.0.0\"],[\"faraday\",\"0.8.0\"],[\"faraday-middleware\",\"0.9.0\"],[\"hashie\",\"1.0.0 || 2.0.0\"],[\"json\",\"1.7.5\"],[\"mime-types\",\"1.19.0 || 2.0.0\"],[\"multi-json\",\"1.5.0\"],[\"twitter-stream\",\"0.1.0\"]]},\n  {\"name\":\"tinder\",\"number\":\"1.9.3\",\"dependencies\":[[\"eventmachine\",\"1.0.0\"],[\"faraday\",\"0.8.0\"],[\"faraday-middleware\",\"0.9.0\"],[\"hashie\",\"1.0.0 || 2.0.0\"],[\"json\",\"1.8.0\"],[\"mime-types\",\"1.19.0 || 2.0.0\"],[\"multi-json\",\"1.7.0\"],[\"twitter-stream\",\"0.1.0\"]]},\n  {\"name\":\"tins\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.13.2\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.13.1\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.13.0\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.12.0\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.11.0\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.6\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.4\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.5.4\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.10\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.14\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.5.6\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.5\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.13\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.8\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.9\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.7\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.5.5\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.12\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.3.11\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.7.2\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.7.4\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.7.3\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.8.2\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.8.3\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.8.4\",\"dependencies\":[]},\n  {\"name\":\"tins\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"treetop\",\"number\":\"1.5.3\",\"dependencies\":[[\"polyglot\",\"0.3.0\"]]},\n  {\"name\":\"treetop\",\"number\":\"1.5.1\",\"dependencies\":[[\"polyglot\",\"0.3.0\"]]},\n  {\"name\":\"treetop\",\"number\":\"1.1.2\",\"dependencies\":[[\"facets\",\"2.0.2\"]]},\n  {\"name\":\"treetop\",\"number\":\"1.4.7\",\"dependencies\":[[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.2.5\",\"dependencies\":[[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.4.5\",\"dependencies\":[[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.4.3\",\"dependencies\":[[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.4.8\",\"dependencies\":[[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"treetop\",\"number\":\"1.4.2\",\"dependencies\":[[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.1.4\",\"dependencies\":[[\"facets\",\"2.0.2\"]]},\n  {\"name\":\"treetop\",\"number\":\"1.4.1\",\"dependencies\":[[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.2.6\",\"dependencies\":[[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.2.0\",\"dependencies\":[[\"facets\",\"2.0.2\"],[\"polyglot\",\"0.0.0\"]]},\n  {\"name\":\"treetop\",\"number\":\"1.2.1\",\"dependencies\":[[\"facets\",\"2.0.2\"],[\"polyglot\",\"0.0.0\"]]},\n  {\"name\":\"treetop\",\"number\":\"1.2.2\",\"dependencies\":[[\"facets\",\"=2.0.2\"],[\"polyglot\",\"0.0.0\"]]},\n  {\"name\":\"treetop\",\"number\":\"1.1.1\",\"dependencies\":[[\"facets\",\"2.0.2\"]]},\n  {\"name\":\"treetop\",\"number\":\"1.1.0\",\"dependencies\":[[\"facets\",\"2.0.2\"]]},\n  {\"name\":\"treetop\",\"number\":\"1.0.2\",\"dependencies\":[[\"facets\",\"2.0.2\"]]},\n  {\"name\":\"treetop\",\"number\":\"1.0.1\",\"dependencies\":[[\"facets\",\"0.0.0\"]]},\n  {\"name\":\"treetop\",\"number\":\"1.0.0\",\"dependencies\":[[\"facets\",\"0.0.0\"]]},\n  {\"name\":\"treetop\",\"number\":\"1.4.10\",\"dependencies\":[[\"polyglot\",null],[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.4.11\",\"dependencies\":[[\"polyglot\",null],[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.3.0\",\"dependencies\":[[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.2.4\",\"dependencies\":[[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.2.3\",\"dependencies\":[[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.4.4\",\"dependencies\":[[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.4.9\",\"dependencies\":[[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.4.12\",\"dependencies\":[[\"polyglot\",null],[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.4.14\",\"dependencies\":[[\"polyglot\",null],[\"polyglot\",null]]},\n  {\"name\":\"treetop\",\"number\":\"1.4.15\",\"dependencies\":[[\"polyglot\",null],[\"polyglot\",null]]},\n  {\"name\":\"turbolinks\",\"number\":\"2.2.1\",\"dependencies\":[[\"coffee-rails\",null]]},\n  {\"name\":\"turbolinks\",\"number\":\"2.2.0\",\"dependencies\":[[\"coffee-rails\",null]]},\n  {\"name\":\"turbolinks\",\"number\":\"2.1.0\",\"dependencies\":[[\"coffee-rails\",null]]},\n  {\"name\":\"turbolinks\",\"number\":\"2.0.0\",\"dependencies\":[[\"coffee-rails\",null]]},\n  {\"name\":\"turbolinks\",\"number\":\"1.3.1\",\"dependencies\":[[\"coffee-rails\",null]]},\n  {\"name\":\"turbolinks\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"turbolinks\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"turbolinks\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"turbolinks\",\"number\":\"0.1.5\",\"dependencies\":[]},\n  {\"name\":\"turbolinks\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"turbolinks\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"turbolinks\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"turbolinks\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"turbolinks\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"turbolinks\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"turbolinks\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"turbolinks\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"turbolinks\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"turbolinks\",\"number\":\"0.5.2\",\"dependencies\":[[\"coffee-rails\",null]]},\n  {\"name\":\"turbolinks\",\"number\":\"0.6.0\",\"dependencies\":[[\"coffee-rails\",null]]},\n  {\"name\":\"turbolinks\",\"number\":\"0.6.1\",\"dependencies\":[[\"coffee-rails\",null]]},\n  {\"name\":\"turbolinks\",\"number\":\"1.0.0\",\"dependencies\":[[\"coffee-rails\",null]]},\n  {\"name\":\"turbolinks\",\"number\":\"1.1.0\",\"dependencies\":[[\"coffee-rails\",null]]},\n  {\"name\":\"turbolinks\",\"number\":\"1.1.1\",\"dependencies\":[[\"coffee-rails\",null]]},\n  {\"name\":\"turbolinks\",\"number\":\"1.2.0\",\"dependencies\":[[\"coffee-rails\",null]]},\n  {\"name\":\"turbolinks\",\"number\":\"1.3.0\",\"dependencies\":[[\"coffee-rails\",null]]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.13\",\"dependencies\":[[\"eventmachine\",\"0.12.8 || 1.0.0\"],[\"simple-oauth\",\"0.1.4\"]]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.14\",\"dependencies\":[[\"eventmachine\",null],[\"simple-oauth\",\"0.1.4\"],[\"http-parser.rb\",\"0.5.1\"]]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.11\",\"dependencies\":[[\"eventmachine\",null],[\"roauth\",null]]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.9\",\"dependencies\":[[\"eventmachine\",null],[\"roauth\",null],[\"eventmachine\",null],[\"roauth\",null]]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.3\",\"dependencies\":[[\"eventmachine\",null]]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.10\",\"dependencies\":[[\"eventmachine\",null],[\"roauth\",null]]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.4\",\"dependencies\":[[\"eventmachine\",null]]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.8\",\"dependencies\":[[\"eventmachine\",null],[\"roauth\",null]]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.7\",\"dependencies\":[[\"eventmachine\",null],[\"roauth\",null]]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.6\",\"dependencies\":[[\"eventmachine\",null]]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.12\",\"dependencies\":[[\"eventmachine\",null],[\"roauth\",null]]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.15\",\"dependencies\":[[\"eventmachine\",null],[\"simple-oauth\",\"0.1.4\"],[\"http-parser.rb\",\"0.5.1\"]]},\n  {\"name\":\"twitter-stream\",\"number\":\"0.1.16\",\"dependencies\":[[\"eventmachine\",null],[\"simple-oauth\",\"0.1.4\"],[\"http-parser.rb\",\"0.5.1\"]]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.39\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.38\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"1.1.0\",\"dependencies\":[[\"thread-safe\",\"0.1.0\"]]},\n  {\"name\":\"tzinfo\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.25\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.26\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.12\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.6\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.19\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.13\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.11\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.10\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.5\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.14\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.15\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.23\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.33\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.4\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.21\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.18\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.3\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.24\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.29\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.7\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.30\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.8\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.22\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.0.4\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.20\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.9\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.17\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.16\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.27\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.28\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.31\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.32\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.34\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.35\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.36\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"0.3.37\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"tzinfo\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"uglifier\",\"number\":\"2.5.0\",\"dependencies\":[[\"json\",\"1.8.0\"],[\"execjs\",null]]},\n  {\"name\":\"uglifier\",\"number\":\"2.4.0\",\"dependencies\":[[\"json\",\"1.8.0\"],[\"execjs\",null]]},\n  {\"name\":\"uglifier\",\"number\":\"2.3.3\",\"dependencies\":[[\"json\",\"1.8.0\"],[\"execjs\",null]]},\n  {\"name\":\"uglifier\",\"number\":\"2.3.2\",\"dependencies\":[[\"json\",\"1.8.0\"],[\"execjs\",null]]},\n  {\"name\":\"uglifier\",\"number\":\"2.3.1\",\"dependencies\":[[\"json\",\"1.8.0\"],[\"execjs\",null]]},\n  {\"name\":\"uglifier\",\"number\":\"2.3.0\",\"dependencies\":[[\"json\",\"1.8.0\"],[\"execjs\",null]]},\n  {\"name\":\"uglifier\",\"number\":\"0.3.0\",\"dependencies\":[[\"therubyracer\",null]]},\n  {\"name\":\"uglifier\",\"number\":\"1.2.5\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.3.0\"]]},\n  {\"name\":\"uglifier\",\"number\":\"0.1.1\",\"dependencies\":[[\"therubyracer\",null]]},\n  {\"name\":\"uglifier\",\"number\":\"0.5.3\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"0.4.0\",\"dependencies\":[[\"therubyracer\",\"0.8.0\"]]},\n  {\"name\":\"uglifier\",\"number\":\"1.0.3\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"1.1.0\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"1.2.3\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"0.5.2\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",null]]},\n  {\"name\":\"uglifier\",\"number\":\"1.2.4\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"0.2.0\",\"dependencies\":[[\"therubyracer\",null]]},\n  {\"name\":\"uglifier\",\"number\":\"1.2.0\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"1.0.0\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"0.5.1\",\"dependencies\":[[\"execjs\",null],[\"json\",null]]},\n  {\"name\":\"uglifier\",\"number\":\"1.0.2\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"0.5.4\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"0.5.0\",\"dependencies\":[[\"execjs\",\"0.1.0 || 1.0.0 || 2.0.0\"],[\"json\",null]]},\n  {\"name\":\"uglifier\",\"number\":\"0.1.0\",\"dependencies\":[[\"therubyracer\",null]]},\n  {\"name\":\"uglifier\",\"number\":\"1.2.1\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"1.2.6\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.3.0\"]]},\n  {\"name\":\"uglifier\",\"number\":\"1.2.7\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.3.0\"]]},\n  {\"name\":\"uglifier\",\"number\":\"1.3.0\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"1.0.4\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"1.0.1\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"1.2.2\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"2.0.0\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"2.0.1\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"2.1.0\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"2.1.1\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"2.1.2\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"2.2.0\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"uglifier\",\"number\":\"2.2.1\",\"dependencies\":[[\"execjs\",null],[\"multi-json\",\"1.0.2\"]]},\n  {\"name\":\"underscore-rails\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"underscore-rails\",\"number\":\"1.5.2\",\"dependencies\":[]},\n  {\"name\":\"underscore-rails\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"underscore-rails\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"underscore-rails\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"underscore-rails\",\"number\":\"1.1.7\",\"dependencies\":[]},\n  {\"name\":\"underscore-rails\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"underscore-rails\",\"number\":\"1.4.1\",\"dependencies\":[]},\n  {\"name\":\"underscore-rails\",\"number\":\"1.4.2\",\"dependencies\":[]},\n  {\"name\":\"underscore-rails\",\"number\":\"1.4.3\",\"dependencies\":[]},\n  {\"name\":\"underscore-rails\",\"number\":\"1.4.4\",\"dependencies\":[]},\n  {\"name\":\"underscore-rails\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"4.8.2\",\"dependencies\":[[\"raindrops\",\"0.7.0\"],[\"kgio\",\"2.6.0\"],[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"4.8.1\",\"dependencies\":[[\"raindrops\",\"0.7.0\"],[\"kgio\",\"2.6.0\"],[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"4.8.0\",\"dependencies\":[[\"raindrops\",\"0.7.0\"],[\"kgio\",\"2.6.0\"],[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"4.7.0\",\"dependencies\":[[\"raindrops\",\"0.7.0\"],[\"kgio\",\"2.6.0\"],[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.8.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"1.1.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.91.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"0.9.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.97.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.2.3\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"0.5.4\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"3.6.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.3.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"0.5.3\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"0.95.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"0.8.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"1.1.3\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.8.3\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.9.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"0.5.2\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"0.9.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"0.8.4\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"1.1.4\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"3.0.1\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.0.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"0.8.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"4.0.1\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.4.0\"],[\"raindrops\",\"0.6.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"4.0.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.4.0\"],[\"raindrops\",\"0.6.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"1.0.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"3.2.1\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.1.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"1.1.5\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.97.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.96.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.93.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"1.0.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.5.1\",\"dependencies\":[]},\n  {\"name\":\"unicorn\",\"number\":\"0.92.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.95.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.98.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"3.0.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.0.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"3.6.1\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.3.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"0.90.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"3.7.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.3.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"0.99.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"1.1.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.96.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"3.6.2\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.3.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"3.5.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.3.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"4.1.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.4.0\"],[\"raindrops\",\"0.6.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"0.94.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"1.1.7\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.991.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.93.5\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.95.3\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.93.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.93.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.93.4\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"3.1.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.0.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"2.0.1\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"1.3.1 || 2.0.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"3.4.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.2.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"2.0.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"1.3.1 || 2.0.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"1.0.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"3.3.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.1.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"1.1.6\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.93.3\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"0.95.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"1.1.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"3.3.1\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.1.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"0.990.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"unicorn\",\"number\":\"4.1.1\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.4.0\"],[\"raindrops\",\"0.6.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"4.2.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.6.0\"],[\"raindrops\",\"0.7.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"4.2.1\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.6.0\"],[\"raindrops\",\"0.7.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"4.3.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.6.0\"],[\"raindrops\",\"0.7.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"4.3.1\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.6.0\"],[\"raindrops\",\"0.7.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"4.4.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.6.0\"],[\"raindrops\",\"0.7.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"4.5.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.6.0\"],[\"raindrops\",\"0.7.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"4.6.0\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.6.0\"],[\"raindrops\",\"0.7.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"4.6.1\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.6.0\"],[\"raindrops\",\"0.7.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"4.6.2\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.6.0\"],[\"raindrops\",\"0.7.0\"]]},\n  {\"name\":\"unicorn\",\"number\":\"4.6.3\",\"dependencies\":[[\"rack\",null],[\"kgio\",\"2.6.0\"],[\"raindrops\",\"0.7.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.4.2\",\"dependencies\":[[\"unicorn\",\"4.0.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.1.0\",\"dependencies\":[[\"unicorn\",\"4.2.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.1.1\",\"dependencies\":[[\"unicorn\",\"4.2.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.1.2\",\"dependencies\":[[\"unicorn\",\"4.0.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.2.0\",\"dependencies\":[[\"unicorn\",\"4.0.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.2.1\",\"dependencies\":[[\"unicorn\",\"4.0.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.2.2\",\"dependencies\":[[\"unicorn\",\"4.0.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.3.0\",\"dependencies\":[[\"unicorn\",\"4.0.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.3.1\",\"dependencies\":[[\"unicorn\",\"4.0.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.3.2\",\"dependencies\":[[\"unicorn\",\"4.0.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.3.3\",\"dependencies\":[[\"unicorn\",\"4.0.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.3.5\",\"dependencies\":[[\"unicorn\",\"4.0.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.3.4\",\"dependencies\":[[\"unicorn\",\"4.0.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.3.6\",\"dependencies\":[[\"unicorn\",\"4.0.0\"]]},\n  {\"name\":\"unicorn-worker-killer\",\"number\":\"0.4.1\",\"dependencies\":[[\"unicorn\",\"4.0.0\"]]},\n  {\"name\":\"version-sorter\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"version-sorter\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"1.0.2\",\"dependencies\":[[\"axiom-types\",\"0.1.0\"],[\"coercible\",\"1.0.0\"],[\"equalizer\",\"0.0.9\"],[\"descendants-tracker\",\"0.0.3\"]]},\n  {\"name\":\"virtus\",\"number\":\"1.0.1\",\"dependencies\":[[\"axiom-types\",\"0.0.5\"],[\"coercible\",\"1.0.0\"],[\"equalizer\",\"0.0.7\"],[\"descendants-tracker\",\"0.0.1\"]]},\n  {\"name\":\"virtus\",\"number\":\"1.0.0\",\"dependencies\":[[\"axiom-types\",\"0.0.5\"],[\"coercible\",\"0.2.0 || 1.0.0\"],[\"equalizer\",\"0.0.7\"],[\"descendants-tracker\",\"0.0.1\"]]},\n  {\"name\":\"virtus\",\"number\":\"0.0.5\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.0.6\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.0.9\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.5.1\",\"dependencies\":[[\"backports\",\"2.6.1 || 3.0.0\"]]},\n  {\"name\":\"virtus\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.4.2\",\"dependencies\":[[\"backports\",\"2.5.3 || 3.0.0\"]]},\n  {\"name\":\"virtus\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.0.8\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.0.10\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.0.4\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.0.7\",\"dependencies\":[]},\n  {\"name\":\"virtus\",\"number\":\"0.4.1\",\"dependencies\":[[\"backports\",\"2.5.1 || 3.0.0\"]]},\n  {\"name\":\"virtus\",\"number\":\"0.5.0\",\"dependencies\":[[\"backports\",\"2.6.1 || 3.0.0\"]]},\n  {\"name\":\"virtus\",\"number\":\"0.5.2\",\"dependencies\":[[\"backports\",\"2.6.1 || 3.0.0\"]]},\n  {\"name\":\"virtus\",\"number\":\"0.5.3\",\"dependencies\":[[\"backports\",\"2.6.1 || 3.0.0\"],[\"descendants-tracker\",\"0.0.1\"]]},\n  {\"name\":\"virtus\",\"number\":\"0.5.4\",\"dependencies\":[[\"backports\",\"2.6.1 || 3.0.0\"],[\"descendants-tracker\",\"0.0.1\"]]},\n  {\"name\":\"virtus\",\"number\":\"0.5.5\",\"dependencies\":[[\"backports\",\"3.3.0\"],[\"descendants-tracker\",\"0.0.1\"]]},\n  {\"name\":\"warden\",\"number\":\"1.0.6\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"1.0.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.9.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.10.5\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.6.3\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.10.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.9.3\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.5.3\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"1.0.3\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"1.0.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.9.6\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.6.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.6.4\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.6.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.10.7\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.10.3\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"warden\",\"number\":\"0.2.3\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.6.5\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.7.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.8.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.8.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.9.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.5.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.5.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.10.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.10.4\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.3.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.6.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.3.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.9.7\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"1.1.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"1.1.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"1.2.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.10.6\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.9.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.9.4\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.4.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.10.1\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.5.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"1.0.4\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.2.2\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"1.0.5\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"0.9.5\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"1.0.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"1.2.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"warden\",\"number\":\"1.2.3\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.17.4\",\"dependencies\":[[\"crack\",null],[\"addressable\",\"2.2.7\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.17.3\",\"dependencies\":[[\"crack\",null],[\"addressable\",\"2.2.7\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.17.2\",\"dependencies\":[[\"crack\",null],[\"addressable\",\"2.2.7\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.17.1\",\"dependencies\":[[\"crack\",null],[\"addressable\",\"2.2.7\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.17.0\",\"dependencies\":[[\"crack\",null],[\"addressable\",\"2.2.7\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.16.1\",\"dependencies\":[[\"crack\",null],[\"addressable\",\"2.2.7\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.16.0\",\"dependencies\":[[\"crack\",null],[\"addressable\",\"2.2.7\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.15.2\",\"dependencies\":[[\"crack\",null],[\"addressable\",\"2.2.7\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.15.0\",\"dependencies\":[[\"crack\",null],[\"addressable\",\"2.2.7\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.14.0\",\"dependencies\":[[\"crack\",null],[\"addressable\",\"2.2.7\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.8.1\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.8.7\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.8.9\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.8.6\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.8.4\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"0.9.0\",\"dependencies\":[[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"webmock\",\"number\":\"0.7.3\",\"dependencies\":[[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.6.0\",\"dependencies\":[[\"addressable\",\"2.2.2\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.8.0\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.3.0\",\"dependencies\":[[\"addressable\",\"2.1.1\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.3.5\",\"dependencies\":[[\"addressable\",\"2.1.1\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.8.5\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.3.2\",\"dependencies\":[[\"addressable\",\"2.1.1\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.7.1\",\"dependencies\":[[\"addressable\",\"2.2.0\"],[\"crack\",null],[\"addressable\",\"2.2.5\"]]},\n  {\"name\":\"webmock\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"webmock\",\"number\":\"1.7.3\",\"dependencies\":[[\"addressable\",\"2.2.0\"],[\"crack\",null],[\"addressable\",\"2.2.5\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.7.6\",\"dependencies\":[[\"addressable\",\"2.2.0\"],[\"crack\",null],[\"addressable\",\"2.2.5\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.2.2\",\"dependencies\":[[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.7.5\",\"dependencies\":[[\"addressable\",\"2.2.0\"],[\"crack\",null],[\"addressable\",\"2.2.5\"]]},\n  {\"name\":\"webmock\",\"number\":\"0.9.1\",\"dependencies\":[[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.3.3\",\"dependencies\":[[\"addressable\",\"2.1.1\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.6.2\",\"dependencies\":[[\"addressable\",\"2.2.2\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.7.8\",\"dependencies\":[[\"addressable\",\"2.2.0\"],[\"crack\",null],[\"addressable\",\"2.2.5\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.3.4\",\"dependencies\":[[\"addressable\",\"2.1.1\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.5.0\",\"dependencies\":[[\"addressable\",\"2.2.2\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.6.1\",\"dependencies\":[[\"addressable\",\"2.2.2\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.2.0\",\"dependencies\":[[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.7.4\",\"dependencies\":[[\"addressable\",\"2.2.0\"],[\"crack\",null],[\"addressable\",\"2.2.5\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.8.2\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.8.3\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"0.8.2\",\"dependencies\":[[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"webmock\",\"number\":\"0.7.1\",\"dependencies\":[]},\n  {\"name\":\"webmock\",\"number\":\"0.8.1\",\"dependencies\":[[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"webmock\",\"number\":\"0.7.2\",\"dependencies\":[[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.7.0\",\"dependencies\":[[\"addressable\",\"2.2.0\"],[\"crack\",null],[\"addressable\",\"2.2.5\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.3.1\",\"dependencies\":[[\"addressable\",\"2.1.1\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.7.2\",\"dependencies\":[[\"addressable\",\"2.2.0\"],[\"crack\",null],[\"addressable\",\"2.2.5\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.7.7\",\"dependencies\":[[\"addressable\",\"2.2.0\"],[\"crack\",null],[\"addressable\",\"2.2.5\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.2.1\",\"dependencies\":[[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.1.0\",\"dependencies\":[[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.6.4\",\"dependencies\":[[\"addressable\",\"2.2.0\"],[\"crack\",null],[\"addressable\",\"2.2.5\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.4.0\",\"dependencies\":[[\"addressable\",\"2.2.2\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.0.0\",\"dependencies\":[[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"webmock\",\"number\":\"0.8.0\",\"dependencies\":[[\"addressable\",\"2.1.1\"]]},\n  {\"name\":\"webmock\",\"number\":\"1.7.10\",\"dependencies\":[[\"addressable\",\"2.2.5\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.8.8\",\"dependencies\":[[\"addressable\",\"2.2.8\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.8.10\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.8.11\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.9.0\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.9.1\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.9.2\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.9.3\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.10.0\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.10.1\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.11.0\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.10.2\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.12.0\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.12.1\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.12.2\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.12.3\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"webmock\",\"number\":\"1.13.0\",\"dependencies\":[[\"addressable\",\"2.2.7\"],[\"crack\",null]]},\n  {\"name\":\"websocket-driver\",\"number\":\"0.3.2\",\"dependencies\":[]},\n  {\"name\":\"websocket-driver\",\"number\":\"0.3.1\",\"dependencies\":[]},\n  {\"name\":\"websocket-driver\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"websocket-driver\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"websocket-driver\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"websocket-driver\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"websocket-driver\",\"number\":\"0.2.2\",\"dependencies\":[]},\n  {\"name\":\"websocket-driver\",\"number\":\"0.2.3\",\"dependencies\":[]},\n  {\"name\":\"xpath\",\"number\":\"0.1.2\",\"dependencies\":[[\"nokogiri\",\"1.3.0\"]]},\n  {\"name\":\"xpath\",\"number\":\"0.1.3\",\"dependencies\":[[\"nokogiri\",\"1.3.0\"]]},\n  {\"name\":\"xpath\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"xpath\",\"number\":\"0.1.1\",\"dependencies\":[[\"nokogiri\",\"1.3.0\"]]},\n  {\"name\":\"xpath\",\"number\":\"0.1.4\",\"dependencies\":[[\"nokogiri\",\"1.3.0\"]]},\n  {\"name\":\"xpath\",\"number\":\"1.0.0\",\"dependencies\":[[\"nokogiri\",\"1.3.0\"]]},\n  {\"name\":\"xpath\",\"number\":\"2.0.0\",\"dependencies\":[[\"nokogiri\",\"1.3.0\"]]}\n];\n\nsinatraGems = [\n  {\"name\":\"launchy\",\"number\":\"2.4.2\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"1.4.2\",\"dependencies\":[]},\n  {\"name\":\"launchy\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"3.20.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"2.20.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"1.20.0\",\"dependencies\":[]},\n  {\"name\":\"rspec\",\"number\":\"0.20.0\",\"dependencies\":[]},\n  {\"name\":\"rake\",\"number\":\"12.0.0\",\"dependencies\":[]},\n  {\"name\":\"echoe\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"ffi\",\"number\":\"0.6.3\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.3.6\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"1.0.1\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"addressable\",\"number\":\"2.2.3\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.3.2\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.2.5\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"0.1.1\",\"dependencies\":[[\"rake\",null],[\"rspec\",null]]},\n  {\"name\":\"addressable\",\"number\":\"0.1.0\",\"dependencies\":[[\"rake\",null],[\"rspec\",null]]},\n  {\"name\":\"addressable\",\"number\":\"2.0.2\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0 || 3.0.0\"],[\"launchy\",null]]},\n  {\"name\":\"addressable\",\"number\":\"1.0.2\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"addressable\",\"number\":\"1.0.0\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"addressable\",\"number\":\"2.1.0\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0 || 3.0.0\"],[\"launchy\",null]]},\n  {\"name\":\"addressable\",\"number\":\"2.0.0\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0 || 3.0.0\"],[\"launchy\",null]]},\n  {\"name\":\"addressable\",\"number\":\"2.2.4\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.2.7\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.2.8\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.2.2\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"1.0.3\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"addressable\",\"number\":\"2.2.6\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"0.1.2\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"addressable\",\"number\":\"2.0.1\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0 || 3.0.0\"],[\"launchy\",null]]},\n  {\"name\":\"addressable\",\"number\":\"1.0.4\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"addressable\",\"number\":\"2.1.2\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.2.1\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.3.3\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.3.4\",\"dependencies\":[]},\n  {\"name\":\"addressable\",\"number\":\"2.3.5\",\"dependencies\":[]},\n  {\"name\":\"bcrypt\",\"number\":\"3.1.7\",\"dependencies\":[]},\n  {\"name\":\"bcrypt\",\"number\":\"3.1.6\",\"dependencies\":[]},\n  {\"name\":\"bcrypt\",\"number\":\"3.1.3\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.1.5\",\"dependencies\":[[\"bcrypt\",\"3.1.3\"]]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.1.4\",\"dependencies\":[[\"bcrypt\",\"3.1.3\"]]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.1.3\",\"dependencies\":[[\"bcrypt\",\"3.1.3\"]]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.1.2\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.0.5\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.1.4\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.0.1\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"2.1.3\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.1.0\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.1.1\",\"dependencies\":[]},\n  {\"name\":\"bcrypt-ruby\",\"number\":\"3.1.2\",\"dependencies\":[]},\n  {\"name\":\"capistrano\",\"number\":\"3.1.0\",\"dependencies\":[[\"i18n\",null],[\"rake\",\"10.0.0 || 11.0.0 || 12.0.0\"],[\"sshkit\",\"1.3.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"3.0.1\",\"dependencies\":[[\"i18n\",null],[\"rake\",\"10.0.0 || 11.0.0 || 12.0.0\"],[\"sshkit\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"3.0.0\",\"dependencies\":[[\"i18n\",null],[\"rake\",\"10.0.0 || 11.0.0 || 12.0.0\"],[\"sshkit\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.21\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.6\",\"dependencies\":[[\"net-ssh\",\"2.0.10\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null],[\"echoe\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"1.1.0\",\"dependencies\":[[\"net-ssh\",\"1.0.8 || 2.0.0\"],[\"net-sftp\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.3.0\",\"dependencies\":[[\"net-ssh\",\"2.0.0\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.1\",\"dependencies\":[[\"net-ssh\",\"2.0.0\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.11\",\"dependencies\":[[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"1.4.1\",\"dependencies\":[[\"rake\",null],[\"net-ssh\",\"1.0.10 || 2.0.0\"],[\"net-sftp\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.11.2\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.13\",\"dependencies\":[[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.20\",\"dependencies\":[[\"net-ssh\",null],[\"net-ssh-gateway\",null],[\"net-sftp\",null],[\"net-scp\",null],[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.17\",\"dependencies\":[[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.4\",\"dependencies\":[[\"net-ssh\",\"2.0.10\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null],[\"echoe\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.0.0\",\"dependencies\":[[\"net-ssh\",\"1.0.10 || 2.0.0\"],[\"net-sftp\",\"1.1.0 || 2.0.0\"],[\"highline\",\"0.0.0 || 1.0.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"1.3.0\",\"dependencies\":[[\"rake\",null],[\"net-ssh\",\"1.0.10 || 2.0.0\"],[\"net-sftp\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.12.0\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.12\",\"dependencies\":[[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.7\",\"dependencies\":[[\"net-ssh\",\"2.0.10\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null],[\"echoe\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.2.0\",\"dependencies\":[[\"net-ssh\",\"1.0.10 || 2.0.0\"],[\"net-sftp\",\"1.1.0 || 2.0.0\"],[\"highline\",null],[\"net-ssh\",\"1.0.10 || 2.0.0\"],[\"net-sftp\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.10\",\"dependencies\":[[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.3\",\"dependencies\":[[\"net-ssh\",\"2.0.0\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null],[\"echoe\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.15\",\"dependencies\":[[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.7.0\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.8\",\"dependencies\":[[\"net-ssh\",\"2.0.10\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null],[\"echoe\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.2\",\"dependencies\":[[\"net-ssh\",\"2.0.0\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null],[\"echoe\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.4.2\",\"dependencies\":[[\"net-ssh\",null],[\"net-sftp\",null],[\"net-scp\",null],[\"net-ssh-gateway\",null],[\"highline\",null],[\"net-ssh\",\"=2.0.0\"],[\"net-sftp\",\"=2.0.0\"],[\"net-scp\",\"=1.0.0\"],[\"net-ssh-gateway\",\"=1.0.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.16\",\"dependencies\":[[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.19\",\"dependencies\":[[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"1.2.0\",\"dependencies\":[[\"rake\",null],[\"net-ssh\",\"1.0.10 || 2.0.0\"],[\"net-sftp\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.5\",\"dependencies\":[[\"net-ssh\",\"2.0.10\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null],[\"echoe\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.18\",\"dependencies\":[[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"1.4.0\",\"dependencies\":[[\"rake\",null],[\"net-ssh\",\"1.0.10 || 2.0.0\"],[\"net-sftp\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.4.3\",\"dependencies\":[[\"net-ssh\",\"2.0.0\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.4.1\",\"dependencies\":[]},\n  {\"name\":\"capistrano\",\"number\":\"1.4.2\",\"dependencies\":[[\"rake\",null],[\"net-ssh\",\"1.0.10 || 2.0.0\"],[\"net-sftp\",\"1.1.0 || 2.0.0\"],[\"net-ssh\",\"1.0.10 || 2.0.0\"],[\"net-sftp\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.9.0\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.8.0\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.9\",\"dependencies\":[[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.4.0\",\"dependencies\":[[\"net-ssh\",\"2.0.0\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.0\",\"dependencies\":[[\"net-ssh\",\"2.0.0\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.1.0\",\"dependencies\":[[\"net-ssh\",\"1.0.10 || 2.0.0\"],[\"net-sftp\",\"1.1.0 || 2.0.0\"],[\"highline\",\"0.0.0 || 1.0.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"1.3.1\",\"dependencies\":[[\"rake\",null],[\"net-ssh\",\"1.0.10 || 2.0.0\"],[\"net-sftp\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.6.0\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.5.14\",\"dependencies\":[[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.0.0\"],[\"highline\",null]]},\n  {\"name\":\"capistrano\",\"number\":\"2.13.5\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.14.1\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.14.2\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.15.2\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.15.1\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.15.0\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.15.3\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.15.4\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"capistrano\",\"number\":\"2.15.5\",\"dependencies\":[[\"highline\",null],[\"net-ssh\",\"2.0.14\"],[\"net-sftp\",\"2.0.0\"],[\"net-scp\",\"1.0.0\"],[\"net-ssh-gateway\",\"1.1.0\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"0.9.4\",\"dependencies\":[[\"dm-core\",\"=0.9.4\"],[\"dm-core\",\"=0.9.4\"],[\"dm-aggregates\",\"=0.9.4\"],[\"dm-migrations\",\"=0.9.4\"],[\"dm-serializer\",\"=0.9.4\"],[\"dm-timestamps\",\"=0.9.4\"],[\"dm-validations\",\"=0.9.4\"],[\"dm-cli\",\"=0.9.4\"],[\"dm-is-tree\",\"=0.9.4\"],[\"dm-observer\",\"=0.9.4\"],[\"dm-types\",\"=0.9.4\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"0.9.9\",\"dependencies\":[[\"dm-core\",\"=0.9.9\"],[\"dm-core\",\"=0.9.9\"],[\"dm-aggregates\",\"=0.9.9\"],[\"dm-migrations\",\"=0.9.9\"],[\"dm-serializer\",\"=0.9.9\"],[\"dm-timestamps\",\"=0.9.9\"],[\"dm-validations\",\"=0.9.9\"],[\"dm-cli\",\"=0.9.9\"],[\"dm-is-tree\",\"=0.9.9\"],[\"dm-observer\",\"=0.9.9\"],[\"dm-types\",\"=0.9.9\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"1.0.2\",\"dependencies\":[[\"dm-core\",\"=1.0.2\"],[\"dm-aggregates\",\"=1.0.2\"],[\"dm-constraints\",\"=1.0.2\"],[\"dm-migrations\",\"=1.0.2\"],[\"dm-transactions\",\"=1.0.2\"],[\"dm-serializer\",\"=1.0.2\"],[\"dm-timestamps\",\"=1.0.2\"],[\"dm-validations\",\"=1.0.2\"],[\"dm-types\",\"=1.0.2\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"0.9.5\",\"dependencies\":[[\"dm-core\",\"=0.9.5\"],[\"dm-core\",\"=0.9.5\"],[\"dm-aggregates\",\"=0.9.5\"],[\"dm-migrations\",\"=0.9.5\"],[\"dm-serializer\",\"=0.9.5\"],[\"dm-timestamps\",\"=0.9.5\"],[\"dm-validations\",\"=0.9.5\"],[\"dm-cli\",\"=0.9.5\"],[\"dm-is-tree\",\"=0.9.5\"],[\"dm-observer\",\"=0.9.5\"],[\"dm-types\",\"=0.9.5\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"1.0.1\",\"dependencies\":[[\"dm-core\",\"=1.0.1\"],[\"dm-aggregates\",\"=1.0.1\"],[\"dm-constraints\",\"=1.0.1\"],[\"dm-migrations\",\"=1.0.1\"],[\"dm-transactions\",\"=1.0.1\"],[\"dm-serializer\",\"=1.0.1\"],[\"dm-timestamps\",\"=1.0.1\"],[\"dm-validations\",\"=1.0.1\"],[\"dm-types\",\"=1.0.1\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"0.9.8\",\"dependencies\":[[\"dm-core\",\"=0.9.8\"],[\"dm-core\",\"=0.9.8\"],[\"dm-aggregates\",\"=0.9.8\"],[\"dm-migrations\",\"=0.9.8\"],[\"dm-serializer\",\"=0.9.8\"],[\"dm-timestamps\",\"=0.9.8\"],[\"dm-validations\",\"=0.9.8\"],[\"dm-cli\",\"=0.9.8\"],[\"dm-is-tree\",\"=0.9.8\"],[\"dm-observer\",\"=0.9.8\"],[\"dm-types\",\"=0.9.8\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"1.0.0\",\"dependencies\":[[\"dm-core\",\"=1.0.0\"],[\"dm-core\",\"=1.0.0\"],[\"dm-aggregates\",\"=1.0.0\"],[\"dm-constraints\",\"=1.0.0\"],[\"dm-migrations\",\"=1.0.0\"],[\"dm-transactions\",\"=1.0.0\"],[\"dm-serializer\",\"=1.0.0\"],[\"dm-timestamps\",\"=1.0.0\"],[\"dm-validations\",\"=1.0.0\"],[\"dm-types\",\"=1.0.0\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"0.10.0\",\"dependencies\":[[\"dm-core\",\"=0.10.0\"],[\"dm-core\",\"=0.10.0\"],[\"dm-aggregates\",\"=0.10.0\"],[\"dm-constraints\",\"=0.10.0\"],[\"dm-migrations\",\"=0.10.0\"],[\"dm-serializer\",\"=0.10.0\"],[\"dm-timestamps\",\"=0.10.0\"],[\"dm-validations\",\"=0.10.0\"],[\"dm-types\",\"=0.10.0\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"0.9.11\",\"dependencies\":[[\"dm-core\",\"=0.9.11\"],[\"dm-core\",\"=0.9.11\"],[\"dm-aggregates\",\"=0.9.11\"],[\"dm-migrations\",\"=0.9.11\"],[\"dm-serializer\",\"=0.9.11\"],[\"dm-timestamps\",\"=0.9.11\"],[\"dm-validations\",\"=0.9.11\"],[\"dm-cli\",\"=0.9.11\"],[\"dm-is-tree\",\"=0.9.11\"],[\"dm-observer\",\"=0.9.11\"],[\"dm-types\",\"=0.9.11\"],[\"hoe\",\"1.11.0\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"0.9.10\",\"dependencies\":[[\"dm-core\",\"=0.9.10\"],[\"dm-core\",\"=0.9.10\"],[\"dm-aggregates\",\"=0.9.10\"],[\"dm-migrations\",\"=0.9.10\"],[\"dm-serializer\",\"=0.9.10\"],[\"dm-timestamps\",\"=0.9.10\"],[\"dm-validations\",\"=0.9.10\"],[\"dm-cli\",\"=0.9.10\"],[\"dm-is-tree\",\"=0.9.10\"],[\"dm-observer\",\"=0.9.10\"],[\"dm-types\",\"=0.9.10\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"0.9.6\",\"dependencies\":[[\"dm-core\",\"=0.9.6\"],[\"dm-core\",\"=0.9.6\"],[\"dm-aggregates\",\"=0.9.6\"],[\"dm-migrations\",\"=0.9.6\"],[\"dm-serializer\",\"=0.9.6\"],[\"dm-timestamps\",\"=0.9.6\"],[\"dm-validations\",\"=0.9.6\"],[\"dm-cli\",\"=0.9.6\"],[\"dm-is-tree\",\"=0.9.6\"],[\"dm-observer\",\"=0.9.6\"],[\"dm-types\",\"=0.9.6\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"0.10.1\",\"dependencies\":[[\"dm-core\",\"=0.10.1\"],[\"dm-core\",\"=0.10.1\"],[\"dm-aggregates\",\"=0.10.1\"],[\"dm-constraints\",\"=0.10.1\"],[\"dm-migrations\",\"=0.10.1\"],[\"dm-serializer\",\"=0.10.1\"],[\"dm-timestamps\",\"=0.10.1\"],[\"dm-validations\",\"=0.10.1\"],[\"dm-types\",\"=0.10.1\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"0.9.2\",\"dependencies\":[[\"dm-core\",null],[\"dm-aggregates\",null],[\"dm-migrations\",null],[\"dm-serializer\",null],[\"dm-timestamps\",null],[\"dm-validations\",null],[\"dm-cli\",null],[\"dm-is-tree\",null],[\"dm-observer\",null],[\"dm-types\",null]]},\n  {\"name\":\"data-mapper\",\"number\":\"0.10.2\",\"dependencies\":[[\"dm-core\",\"0.10.2 || 1.0.0\"],[\"dm-aggregates\",\"0.10.2 || 1.0.0\"],[\"dm-constraints\",\"0.10.2 || 1.0.0\"],[\"dm-migrations\",\"0.10.2 || 1.0.0\"],[\"dm-serializer\",\"0.10.2 || 1.0.0\"],[\"dm-timestamps\",\"0.10.2 || 1.0.0\"],[\"dm-validations\",\"0.10.2 || 1.0.0\"],[\"dm-types\",\"0.10.2 || 1.0.0\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"0.9.3\",\"dependencies\":[[\"dm-core\",\"=0.9.3\"],[\"dm-core\",\"=0.9.3\"],[\"dm-aggregates\",\"=0.9.3\"],[\"dm-migrations\",\"=0.9.3\"],[\"dm-serializer\",\"=0.9.3\"],[\"dm-timestamps\",\"=0.9.3\"],[\"dm-validations\",\"=0.9.3\"],[\"dm-cli\",\"=0.9.3\"],[\"dm-is-tree\",\"=0.9.3\"],[\"dm-observer\",\"=0.9.3\"],[\"dm-types\",\"=0.9.3\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"0.9.7\",\"dependencies\":[[\"dm-core\",\"=0.9.7\"],[\"dm-core\",\"=0.9.7\"],[\"dm-aggregates\",\"=0.9.7\"],[\"dm-migrations\",\"=0.9.7\"],[\"dm-serializer\",\"=0.9.7\"],[\"dm-timestamps\",\"=0.9.7\"],[\"dm-validations\",\"=0.9.7\"],[\"dm-cli\",\"=0.9.7\"],[\"dm-is-tree\",\"=0.9.7\"],[\"dm-observer\",\"=0.9.7\"],[\"dm-types\",\"=0.9.7\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"1.1.0\",\"dependencies\":[[\"dm-core\",\"=1.1.0\"],[\"dm-aggregates\",\"=1.1.0\"],[\"dm-constraints\",\"=1.1.0\"],[\"dm-migrations\",\"=1.1.0\"],[\"dm-transactions\",\"=1.1.0\"],[\"dm-serializer\",\"=1.1.0\"],[\"dm-timestamps\",\"=1.1.0\"],[\"dm-validations\",\"=1.1.0\"],[\"dm-types\",\"=1.1.0\"]]},\n  {\"name\":\"data-mapper\",\"number\":\"1.2.0\",\"dependencies\":[[\"dm-core\",\"1.2.0\"],[\"dm-aggregates\",\"1.2.0\"],[\"dm-constraints\",\"1.2.0\"],[\"dm-migrations\",\"1.2.0\"],[\"dm-transactions\",\"1.2.0\"],[\"dm-serializer\",\"1.2.0\"],[\"dm-timestamps\",\"1.2.0\"],[\"dm-validations\",\"1.2.0\"],[\"dm-types\",\"1.2.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.14\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.9.7\",\"dependencies\":[[\"addressable\",\"2.0.0\"],[\"extlib\",\"0.9.8\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"data-objects\",\"number\":\"0.9.6\",\"dependencies\":[[\"addressable\",\"1.0.3 || 2.0.0\"],[\"extlib\",null],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.9.10\",\"dependencies\":[[\"addressable\",\"2.0.0\"],[\"extlib\",\"0.9.8\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.3\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.5\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.9.2\",\"dependencies\":[[\"addressable\",\"1.0.3 || 2.0.0\"],[\"extlib\",null]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.0\",\"dependencies\":[[\"addressable\",\"2.0.0\"],[\"extlib\",\"0.9.12\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.9.3\",\"dependencies\":[[\"addressable\",\"1.0.3 || 2.0.0\"],[\"extlib\",\"=0.9.3\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.2\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.9.5\",\"dependencies\":[[\"addressable\",\"1.0.3 || 2.0.0\"],[\"extlib\",null],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.9.4\",\"dependencies\":[[\"addressable\",\"1.0.3 || 2.0.0\"],[\"extlib\",\"=0.9.4\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.9.8\",\"dependencies\":[[\"addressable\",\"2.0.0\"],[\"extlib\",\"0.9.8\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.9.9\",\"dependencies\":[[\"addressable\",\"2.0.0\"],[\"extlib\",\"0.9.8\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.9.11\",\"dependencies\":[[\"addressable\",\"2.0.0\"],[\"extlib\",\"0.9.9\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.9.12\",\"dependencies\":[[\"addressable\",\"2.0.0\"],[\"extlib\",\"0.9.12\"],[\"rspec\",\"1.2.0 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.1\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.4\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.6\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.7\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.8\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.9\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.10\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.11\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.12\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"data-objects\",\"number\":\"0.10.13\",\"dependencies\":[[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"1.1.0\",\"dependencies\":[[\"dm-core\",\"1.1.0\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"0.9.8\",\"dependencies\":[[\"dm-core\",\"0.9.8 || 1.0.0\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"0.9.9\",\"dependencies\":[[\"dm-core\",\"0.9.9 || 1.0.0\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"0.10.2\",\"dependencies\":[[\"dm-core\",\"0.10.2 || 1.0.0\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"1.0.2\",\"dependencies\":[[\"dm-core\",\"1.0.2\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"1.0.1\",\"dependencies\":[[\"dm-core\",\"1.0.1\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"1.0.0\",\"dependencies\":[[\"dm-core\",\"1.0.0\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"0.9.5\",\"dependencies\":[[\"dm-core\",\"=0.9.5\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"0.9.2\",\"dependencies\":[[\"dm-core\",\"=0.9.2\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"0.9.7\",\"dependencies\":[[\"dm-core\",\"=0.9.7\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"0.9.10\",\"dependencies\":[[\"dm-core\",\"0.9.10 || 1.0.0\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"0.9.11\",\"dependencies\":[[\"dm-core\",\"=0.9.11\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"0.9.3\",\"dependencies\":[[\"dm-core\",\"=0.9.3\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"dm-aggregates\",\"number\":\"0.10.1\",\"dependencies\":[[\"dm-core\",\"=0.10.1\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"0.9.4\",\"dependencies\":[[\"dm-core\",\"=0.9.4\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"0.9.6\",\"dependencies\":[[\"dm-core\",\"=0.9.6\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-aggregates\",\"number\":\"1.2.0\",\"dependencies\":[[\"dm-core\",\"1.2.0\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"0.9.4\",\"dependencies\":[[\"dm-core\",\"=0.9.4\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"1.0.0\",\"dependencies\":[[\"dm-core\",\"1.0.0\"],[\"dm-migrations\",\"1.0.0\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"0.9.5\",\"dependencies\":[[\"dm-core\",\"=0.9.5\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"dm-constraints\",\"number\":\"1.0.1\",\"dependencies\":[[\"dm-core\",\"1.0.1\"],[\"dm-migrations\",\"1.0.1\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"0.9.9\",\"dependencies\":[[\"dm-core\",\"0.9.9 || 1.0.0\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"0.9.7\",\"dependencies\":[[\"dm-core\",\"=0.9.7\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"0.10.2\",\"dependencies\":[[\"dm-core\",\"0.10.2 || 1.0.0\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"0.9.11\",\"dependencies\":[[\"dm-core\",\"=0.9.11\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"0.9.6\",\"dependencies\":[[\"dm-core\",\"=0.9.6\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"0.10.1\",\"dependencies\":[[\"dm-core\",\"=0.10.1\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"0.9.8\",\"dependencies\":[[\"dm-core\",\"0.9.8 || 1.0.0\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"0.9.10\",\"dependencies\":[[\"dm-core\",\"0.9.10 || 1.0.0\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"1.1.0\",\"dependencies\":[[\"dm-core\",\"1.1.0\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"1.2.0\",\"dependencies\":[[\"dm-core\",\"1.2.0\"]]},\n  {\"name\":\"dm-constraints\",\"number\":\"1.0.2\",\"dependencies\":[[\"dm-core\",\"1.0.2\"],[\"dm-migrations\",\"1.0.2\"]]},\n  {\"name\":\"dm-core\",\"number\":\"1.0.0\",\"dependencies\":[[\"extlib\",\"0.9.15\"],[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"dm-core\",\"number\":\"0.10.1\",\"dependencies\":[[\"extlib\",\"0.9.13\"],[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"dm-core\",\"number\":\"0.10.2\",\"dependencies\":[[\"extlib\",\"0.9.14\"],[\"addressable\",\"2.1.0\"]]},\n  {\"name\":\"dm-core\",\"number\":\"0.9.2\",\"dependencies\":[[\"data-objects\",\"=0.9.2\"],[\"extlib\",\"=0.9.2\"],[\"rspec\",\"1.1.3 || 2.0.0 || 3.0.0\"],[\"addressable\",\"1.0.4 || 2.0.0\"]]},\n  {\"name\":\"dm-core\",\"number\":\"0.9.8\",\"dependencies\":[[\"data-objects\",\"0.9.9\"],[\"extlib\",\"0.9.9\"],[\"addressable\",\"2.0.1\"]]},\n  {\"name\":\"dm-core\",\"number\":\"0.9.11\",\"dependencies\":[[\"data-objects\",\"0.9.11\"],[\"extlib\",\"0.9.11\"],[\"addressable\",\"2.0.2\"]]},\n  {\"name\":\"dm-core\",\"number\":\"0.9.4\",\"dependencies\":[[\"data-objects\",\"=0.9.4\"],[\"extlib\",\"=0.9.4\"],[\"rspec\",\"1.1.3 || 2.0.0 || 3.0.0\"],[\"addressable\",\"1.0.4 || 2.0.0\"]]},\n  {\"name\":\"dm-core\",\"number\":\"1.0.2\",\"dependencies\":[[\"extlib\",\"0.9.15\"],[\"addressable\",\"2.2.0\"]]},\n  {\"name\":\"dm-core\",\"number\":\"0.9.6\",\"dependencies\":[[\"data-objects\",null],[\"extlib\",null],[\"rspec\",\"1.1.3 || 2.0.0 || 3.0.0\"],[\"addressable\",\"1.0.4 || 2.0.0\"]]},\n  {\"name\":\"dm-core\",\"number\":\"0.9.7\",\"dependencies\":[[\"data-objects\",\"0.9.7\"],[\"extlib\",\"0.9.8\"],[\"rspec\",\"1.1.3 || 2.0.0 || 3.0.0\"],[\"addressable\",\"2.0.0\"]]},\n  {\"name\":\"dm-core\",\"number\":\"0.9.10\",\"dependencies\":[[\"data-objects\",\"0.9.11\"],[\"extlib\",\"0.9.10\"],[\"addressable\",\"2.0.1\"]]},\n  {\"name\":\"dm-core\",\"number\":\"0.9.3\",\"dependencies\":[[\"data-objects\",\"=0.9.3\"],[\"extlib\",\"=0.9.3\"],[\"rspec\",\"1.1.3 || 2.0.0 || 3.0.0\"],[\"addressable\",\"1.0.4 || 2.0.0\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-core\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"dm-core\",\"number\":\"0.9.5\",\"dependencies\":[[\"data-objects\",null],[\"extlib\",null],[\"rspec\",\"1.1.3 || 2.0.0 || 3.0.0\"],[\"addressable\",\"1.0.4 || 2.0.0\"]]},\n  {\"name\":\"dm-core\",\"number\":\"1.0.1\",\"dependencies\":[[\"extlib\",\"0.9.15\"],[\"addressable\",\"2.2.0\"]]},\n  {\"name\":\"dm-core\",\"number\":\"0.9.9\",\"dependencies\":[[\"data-objects\",\"0.9.10\"],[\"extlib\",\"0.9.9\"],[\"addressable\",\"2.0.1\"]]},\n  {\"name\":\"dm-core\",\"number\":\"1.2.0\",\"dependencies\":[[\"addressable\",\"2.2.6\"]]},\n  {\"name\":\"dm-core\",\"number\":\"1.1.0\",\"dependencies\":[[\"addressable\",\"2.2.4\"]]},\n  {\"name\":\"dm-core\",\"number\":\"1.2.1\",\"dependencies\":[[\"addressable\",\"2.3.0\"]]},\n  {\"name\":\"dm-do-adapter\",\"number\":\"1.0.2\",\"dependencies\":[[\"data-objects\",\"0.10.2\"],[\"dm-core\",\"1.0.2\"]]},\n  {\"name\":\"dm-do-adapter\",\"number\":\"1.0.1\",\"dependencies\":[[\"data-objects\",\"0.10.2\"],[\"dm-core\",\"1.0.1\"]]},\n  {\"name\":\"dm-do-adapter\",\"number\":\"1.0.0\",\"dependencies\":[[\"data-objects\",\"0.10.1\"],[\"dm-core\",\"1.0.0\"]]},\n  {\"name\":\"dm-do-adapter\",\"number\":\"1.1.0\",\"dependencies\":[[\"data-objects\",\"0.10.2\"],[\"dm-core\",\"1.1.0\"]]},\n  {\"name\":\"dm-do-adapter\",\"number\":\"1.2.0\",\"dependencies\":[[\"data-objects\",\"0.10.6\"],[\"dm-core\",\"1.2.0\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"dm-migrations\",\"number\":\"1.0.1\",\"dependencies\":[[\"dm-core\",\"1.0.1\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"1.1.0\",\"dependencies\":[[\"dm-core\",\"1.1.0\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"0.9.5\",\"dependencies\":[[\"dm-core\",\"=0.9.5\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"0.9.7\",\"dependencies\":[[\"dm-core\",\"0.9.7 || 1.0.0\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"0.9.3\",\"dependencies\":[[\"dm-core\",\"=0.9.3\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"0.9.11\",\"dependencies\":[[\"dm-core\",\"=0.9.11\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"0.10.1\",\"dependencies\":[[\"dm-core\",\"=0.10.1\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"0.9.2\",\"dependencies\":[[\"dm-core\",\"=0.9.2\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"1.0.0\",\"dependencies\":[[\"dm-core\",\"1.0.0\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"0.9.8\",\"dependencies\":[[\"dm-core\",\"0.9.8 || 1.0.0\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"0.9.9\",\"dependencies\":[[\"dm-core\",\"0.9.9 || 1.0.0\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"0.9.4\",\"dependencies\":[[\"dm-core\",\"=0.9.4\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"0.9.6\",\"dependencies\":[[\"dm-core\",\"0.9.5 || 1.0.0\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"0.10.2\",\"dependencies\":[[\"dm-core\",\"0.10.2 || 1.0.0\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"1.0.2\",\"dependencies\":[[\"dm-core\",\"1.0.2\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"1.2.0\",\"dependencies\":[[\"dm-core\",\"1.2.0\"]]},\n  {\"name\":\"dm-migrations\",\"number\":\"0.9.10\",\"dependencies\":[[\"dm-core\",\"0.9.10 || 1.0.0\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"0.10.2\",\"dependencies\":[[\"dm-core\",\"0.10.2 || 1.0.0\"],[\"fastercsv\",\"1.5.0\"],[\"json-pure\",\"1.2.0\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"1.0.2\",\"dependencies\":[[\"dm-core\",\"1.0.2\"],[\"fastercsv\",\"1.5.3\"],[\"json-pure\",\"1.4.0\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"0.9.8\",\"dependencies\":[[\"dm-core\",\"0.9.8 || 1.0.0\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"0.9.10\",\"dependencies\":[[\"dm-core\",\"0.9.10 || 1.0.0\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"0.9.3\",\"dependencies\":[[\"dm-core\",\"=0.9.3\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"0.9.7\",\"dependencies\":[[\"dm-core\",\"=0.9.7\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"0.9.2\",\"dependencies\":[[\"dm-core\",\"=0.9.2\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"dm-serializer\",\"number\":\"0.9.6\",\"dependencies\":[[\"dm-core\",\"=0.9.6\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"1.0.1\",\"dependencies\":[[\"dm-core\",\"1.0.1\"],[\"fastercsv\",\"1.5.3\"],[\"json-pure\",\"1.4.0\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"0.9.11\",\"dependencies\":[[\"dm-core\",\"=0.9.11\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"1.0.0\",\"dependencies\":[[\"dm-core\",\"1.0.0\"],[\"fastercsv\",\"1.5.3\"],[\"json-pure\",\"1.4.3\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"0.9.5\",\"dependencies\":[[\"dm-core\",\"=0.9.5\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"0.9.4\",\"dependencies\":[[\"dm-core\",\"=0.9.4\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"1.1.0\",\"dependencies\":[[\"dm-core\",\"1.1.0\"],[\"fastercsv\",\"1.5.4\"],[\"json\",\"1.4.6\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"1.2.0\",\"dependencies\":[[\"dm-core\",\"1.2.0\"],[\"fastercsv\",\"1.5.4\"],[\"multi-json\",\"1.0.3\"],[\"json\",\"1.5.4\"],[\"json-pure\",\"1.5.4\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"1.2.1\",\"dependencies\":[[\"dm-core\",\"1.2.0\"],[\"fastercsv\",\"1.5.4\"],[\"multi-json\",\"1.0.3\"],[\"json\",\"1.6.1\"],[\"json-pure\",\"1.6.1\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"1.2.2\",\"dependencies\":[[\"fastercsv\",\"1.5.0\"],[\"multi-json\",\"1.0.0\"],[\"json\",\"1.6.0\"],[\"json-pure\",\"1.6.0\"],[\"dm-core\",\"1.2.0\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"0.10.1\",\"dependencies\":[[\"dm-core\",\"=0.10.1\"]]},\n  {\"name\":\"dm-serializer\",\"number\":\"0.9.9\",\"dependencies\":[[\"dm-core\",\"0.9.9 || 1.0.0\"]]},\n  {\"name\":\"dm-sqlite-adapter\",\"number\":\"1.1.0\",\"dependencies\":[[\"do-sqlite3\",\"0.10.2\"],[\"dm-do-adapter\",\"1.1.0\"]]},\n  {\"name\":\"dm-sqlite-adapter\",\"number\":\"1.0.2\",\"dependencies\":[[\"do-sqlite3\",\"0.10.2\"],[\"dm-do-adapter\",\"1.0.2\"]]},\n  {\"name\":\"dm-sqlite-adapter\",\"number\":\"1.0.0\",\"dependencies\":[[\"do-sqlite3\",\"0.10.2\"],[\"dm-do-adapter\",\"1.0.0\"]]},\n  {\"name\":\"dm-sqlite-adapter\",\"number\":\"1.2.0\",\"dependencies\":[[\"do-sqlite3\",\"0.10.6\"],[\"dm-do-adapter\",\"1.2.0\"]]},\n  {\"name\":\"dm-sqlite-adapter\",\"number\":\"1.0.1\",\"dependencies\":[[\"do-sqlite3\",\"0.10.2\"],[\"dm-do-adapter\",\"1.0.1\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"dm-timestamps\",\"number\":\"0.9.2\",\"dependencies\":[[\"dm-core\",\"=0.9.2\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"1.1.0\",\"dependencies\":[[\"dm-core\",\"1.1.0\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"0.10.2\",\"dependencies\":[[\"dm-core\",\"0.10.2 || 1.0.0\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"0.9.3\",\"dependencies\":[[\"dm-core\",\"=0.9.3\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"0.9.4\",\"dependencies\":[[\"dm-core\",\"=0.9.4\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"0.9.9\",\"dependencies\":[[\"dm-core\",\"0.9.9 || 1.0.0\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"0.9.5\",\"dependencies\":[[\"dm-core\",\"=0.9.5\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"0.9.8\",\"dependencies\":[[\"dm-core\",\"0.9.8 || 1.0.0\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"0.10.1\",\"dependencies\":[[\"dm-core\",\"=0.10.1\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"0.9.10\",\"dependencies\":[[\"dm-core\",\"0.9.10 || 1.0.0\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"1.0.2\",\"dependencies\":[[\"dm-core\",\"1.0.2\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"1.0.0\",\"dependencies\":[[\"dm-core\",\"1.0.0\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"0.9.7\",\"dependencies\":[[\"dm-core\",\"=0.9.7\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"0.9.11\",\"dependencies\":[[\"dm-core\",\"=0.9.11\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"1.0.1\",\"dependencies\":[[\"dm-core\",\"1.0.1\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"1.2.0\",\"dependencies\":[[\"dm-core\",\"1.2.0\"]]},\n  {\"name\":\"dm-timestamps\",\"number\":\"0.9.6\",\"dependencies\":[[\"dm-core\",\"=0.9.6\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-transactions\",\"number\":\"1.1.0\",\"dependencies\":[[\"dm-core\",\"1.1.0\"]]},\n  {\"name\":\"dm-transactions\",\"number\":\"1.0.0\",\"dependencies\":[[\"dm-core\",\"1.0.0\"]]},\n  {\"name\":\"dm-transactions\",\"number\":\"1.0.2\",\"dependencies\":[[\"dm-core\",\"1.0.2\"]]},\n  {\"name\":\"dm-transactions\",\"number\":\"1.0.1\",\"dependencies\":[[\"dm-core\",\"1.0.1\"]]},\n  {\"name\":\"dm-transactions\",\"number\":\"1.2.0\",\"dependencies\":[[\"dm-core\",\"1.2.0\"]]},\n  {\"name\":\"dm-types\",\"number\":\"1.2.0\",\"dependencies\":[[\"bcrypt-ruby\",\"3.0.0\"],[\"dm-core\",\"1.2.0\"],[\"fastercsv\",\"1.5.4\"],[\"multi-json\",\"1.0.3\"],[\"json\",\"1.5.4\"],[\"stringex\",\"1.3.0 || 2.0.0\"],[\"uuidtools\",\"2.1.2\"]]},\n  {\"name\":\"dm-types\",\"number\":\"0.10.1\",\"dependencies\":[[\"dm-core\",\"=0.10.1\"]]},\n  {\"name\":\"dm-types\",\"number\":\"0.9.7\",\"dependencies\":[[\"dm-core\",\"=0.9.7\"],[\"uuidtools\",null],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"dm-types\",\"number\":\"0.9.11\",\"dependencies\":[[\"dm-core\",\"=0.9.11\"],[\"addressable\",\"2.0.2\"]]},\n  {\"name\":\"dm-types\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"dm-types\",\"number\":\"0.9.2\",\"dependencies\":[[\"dm-core\",\"=0.9.2\"]]},\n  {\"name\":\"dm-types\",\"number\":\"1.0.2\",\"dependencies\":[[\"dm-core\",\"1.0.2\"],[\"fastercsv\",\"1.5.3\"],[\"json-pure\",\"1.4.0\"],[\"uuidtools\",\"2.1.1\"],[\"stringex\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"dm-types\",\"number\":\"0.9.8\",\"dependencies\":[[\"dm-core\",\"0.9.8 || 1.0.0\"],[\"addressable\",\"2.0.1\"]]},\n  {\"name\":\"dm-types\",\"number\":\"0.9.3\",\"dependencies\":[[\"dm-core\",\"=0.9.3\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-types\",\"number\":\"0.9.4\",\"dependencies\":[[\"dm-core\",\"=0.9.4\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-types\",\"number\":\"0.10.2\",\"dependencies\":[[\"bcrypt-ruby\",\"2.1.2 || 3.0.0\"],[\"dm-core\",\"0.10.2 || 1.0.0\"],[\"fastercsv\",\"1.5.0\"],[\"json-pure\",\"1.2.0\"],[\"uuidtools\",\"2.1.1\"],[\"stringex\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"dm-types\",\"number\":\"1.0.0\",\"dependencies\":[[\"dm-core\",\"1.0.0\"],[\"fastercsv\",\"1.5.3\"],[\"json-pure\",\"1.4.3\"],[\"uuidtools\",\"2.1.1\"],[\"stringex\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"dm-types\",\"number\":\"1.2.1\",\"dependencies\":[[\"bcrypt-ruby\",\"3.0.0\"],[\"dm-core\",\"1.2.0\"],[\"fastercsv\",\"1.5.4\"],[\"multi-json\",\"1.0.3\"],[\"json\",\"1.6.1\"],[\"stringex\",\"1.3.0 || 2.0.0\"],[\"uuidtools\",\"2.1.2\"]]},\n  {\"name\":\"dm-types\",\"number\":\"1.2.2\",\"dependencies\":[[\"bcrypt-ruby\",\"3.0.0\"],[\"fastercsv\",\"1.5.0\"],[\"multi-json\",\"1.0.0\"],[\"json\",\"1.6.0\"],[\"stringex\",\"1.4.0 || 2.0.0\"],[\"uuidtools\",\"2.1.0\"],[\"dm-core\",\"1.2.0\"]]},\n  {\"name\":\"dm-types\",\"number\":\"0.9.6\",\"dependencies\":[[\"dm-core\",\"=0.9.6\"],[\"uuidtools\",null],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-types\",\"number\":\"0.9.9\",\"dependencies\":[[\"dm-core\",\"0.9.9 || 1.0.0\"],[\"addressable\",\"2.0.1\"]]},\n  {\"name\":\"dm-types\",\"number\":\"0.9.5\",\"dependencies\":[[\"dm-core\",\"=0.9.5\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-types\",\"number\":\"1.1.0\",\"dependencies\":[[\"bcrypt-ruby\",\"2.1.4 || 3.0.0\"],[\"dm-core\",\"1.1.0\"],[\"fastercsv\",\"1.5.4\"],[\"json\",\"1.4.6\"],[\"stringex\",\"1.2.0 || 2.0.0\"],[\"uuidtools\",\"2.1.2\"]]},\n  {\"name\":\"dm-types\",\"number\":\"0.9.10\",\"dependencies\":[[\"dm-core\",\"0.9.10 || 1.0.0\"],[\"addressable\",\"2.0.1\"],[\"bcrypt-ruby\",\"2.0.0 || 3.0.0\"],[\"json\",\"1.1.3\"]]},\n  {\"name\":\"dm-types\",\"number\":\"1.0.1\",\"dependencies\":[[\"dm-core\",\"1.0.1\"],[\"fastercsv\",\"1.5.3\"],[\"json-pure\",\"1.4.0\"],[\"uuidtools\",\"2.1.1\"],[\"stringex\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"dm-validations\",\"number\":\"0.10.1\",\"dependencies\":[[\"dm-core\",\"=0.10.1\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"0.9.4\",\"dependencies\":[[\"dm-core\",\"=0.9.4\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"0.10.2\",\"dependencies\":[[\"dm-core\",\"0.10.2 || 1.0.0\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"0.9.7\",\"dependencies\":[[\"dm-core\",\"=0.9.7\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"0.9.6\",\"dependencies\":[[\"dm-core\",\"=0.9.6\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"0.9.5\",\"dependencies\":[[\"dm-core\",\"=0.9.5\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"0.9.3\",\"dependencies\":[[\"dm-core\",\"=0.9.3\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"1.0.0\",\"dependencies\":[[\"dm-core\",\"1.0.0\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"0.9.11\",\"dependencies\":[[\"dm-core\",\"=0.9.11\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"0.9.9\",\"dependencies\":[[\"dm-core\",\"0.9.9 || 1.0.0\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"0.9.2\",\"dependencies\":[[\"dm-core\",\"=0.9.2\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"1.0.1\",\"dependencies\":[[\"dm-core\",\"1.0.1\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"0.9.10\",\"dependencies\":[[\"dm-core\",\"0.9.10 || 1.0.0\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"0.9.8\",\"dependencies\":[[\"dm-core\",\"0.9.8 || 1.0.0\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"1.0.2\",\"dependencies\":[[\"dm-core\",\"1.0.2\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"1.1.0\",\"dependencies\":[[\"dm-core\",\"1.1.0\"]]},\n  {\"name\":\"dm-validations\",\"number\":\"1.2.0\",\"dependencies\":[[\"dm-core\",\"1.2.0\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.14\",\"dependencies\":[[\"data-objects\",\"=0.10.14\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.5\",\"dependencies\":[[\"data-objects\",\"=0.10.5\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.9.8\",\"dependencies\":[[\"data-objects\",\"=0.9.8\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.9.7\",\"dependencies\":[[\"data-objects\",\"=0.9.7\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.2\",\"dependencies\":[[\"data-objects\",\"=0.10.2\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.9\",\"dependencies\":[[\"data-objects\",\"=0.10.9\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.8\",\"dependencies\":[[\"data-objects\",\"=0.10.8\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.1\",\"dependencies\":[[\"data-objects\",\"=0.10.1\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.9.6\",\"dependencies\":[[\"data-objects\",\"=0.9.6\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.9.4\",\"dependencies\":[[\"data-objects\",\"=0.9.4\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.9.12\",\"dependencies\":[[\"addressable\",\"2.0.0\"],[\"extlib\",\"0.9.12\"],[\"data-objects\",\"=0.9.12\"],[\"rspec\",\"1.2.0 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.9.11\",\"dependencies\":[[\"data-objects\",\"=0.9.11\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.4\",\"dependencies\":[[\"data-objects\",\"=0.10.4\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.9.3\",\"dependencies\":[[\"data-objects\",\"=0.9.3\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.2.3\",\"dependencies\":[[\"data-objects\",\"0.0.0\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.9.5\",\"dependencies\":[[\"data-objects\",\"=0.9.5\"],[\"hoe\",\"1.7.0\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.7\",\"dependencies\":[[\"data-objects\",\"=0.10.7\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.0\",\"dependencies\":[[\"addressable\",\"2.0.0\"],[\"extlib\",\"0.9.12\"],[\"data-objects\",\"=0.10.0\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.9.10\",\"dependencies\":[[\"data-objects\",\"=0.9.10\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.2.0\",\"dependencies\":[[\"data-objects\",\"0.0.0\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.2.5\",\"dependencies\":[[\"data-objects\",null]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.9.2\",\"dependencies\":[[\"data-objects\",\"=0.9.2\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.3\",\"dependencies\":[[\"data-objects\",\"=0.10.3\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.2.2\",\"dependencies\":[[\"data-objects\",\"0.0.0\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.9.9\",\"dependencies\":[[\"data-objects\",\"=0.9.9\"],[\"hoe\",\"1.8.2\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.2.1\",\"dependencies\":[[\"data-objects\",\"0.0.0\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.6\",\"dependencies\":[[\"data-objects\",\"=0.10.6\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.10\",\"dependencies\":[[\"data-objects\",\"=0.10.10\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.11\",\"dependencies\":[[\"data-objects\",\"=0.10.11\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.12\",\"dependencies\":[[\"data-objects\",\"=0.10.12\"]]},\n  {\"name\":\"do-sqlite3\",\"number\":\"0.10.13\",\"dependencies\":[[\"data-objects\",\"=0.10.13\"]]},\n  {\"name\":\"fastercsv\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"1.5.3\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"0.1.9\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"0.1.8\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"1.2.3\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"0.2.1\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"0.1.6\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"1.5.4\",\"dependencies\":[]},\n  {\"name\":\"fastercsv\",\"number\":\"1.5.5\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"4.0.5\",\"dependencies\":[[\"tilt\",null]]},\n  {\"name\":\"haml\",\"number\":\"4.0.4\",\"dependencies\":[[\"tilt\",null]]},\n  {\"name\":\"haml\",\"number\":\"3.0.23\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.13\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.6\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.8.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.4\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.18\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.9\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.9\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.12\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.18\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.1\",\"dependencies\":[[\"yard\",null],[\"maruku\",null]]},\n  {\"name\":\"haml\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.3\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.13\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.16\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.5.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.8.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.16\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.17\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.3\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.4\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.0.5\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.7\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.24\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.11\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.14\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.20\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.7.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.9\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.5\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.7\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.8\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.4\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.2\",\"dependencies\":[[\"yard\",null],[\"maruku\",null]]},\n  {\"name\":\"haml\",\"number\":\"3.0.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.8\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.10\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.6\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.24\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.5\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.3\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.14\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.5\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.0\",\"dependencies\":[[\"yard\",null],[\"maruku\",null]]},\n  {\"name\":\"haml\",\"number\":\"2.2.22\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.23\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.21\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.15\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.11\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.25\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.17\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.21\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.6\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.10\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.5\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.2.19\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.22\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.15\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.12\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.0.6\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.0\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.7\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.8.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"1.7.2\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"2.0.10\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"3.1.8\",\"dependencies\":[]},\n  {\"name\":\"haml\",\"number\":\"4.0.0\",\"dependencies\":[[\"tilt\",null]]},\n  {\"name\":\"haml\",\"number\":\"4.0.1\",\"dependencies\":[[\"tilt\",null]]},\n  {\"name\":\"haml\",\"number\":\"4.0.2\",\"dependencies\":[[\"tilt\",null]]},\n  {\"name\":\"haml\",\"number\":\"4.0.3\",\"dependencies\":[[\"tilt\",null]]},\n  {\"name\":\"highline\",\"number\":\"1.6.21\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.20\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.10\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.2.5\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"0.6.1\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.7\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.5\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.9\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.8\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.2.3\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.6\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.2\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.1\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.2.6\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.2.4\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.2.9\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.2.7\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.12\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.14\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.15\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.13\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.11\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.2.8\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.5.2\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.16\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.17\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.18\",\"dependencies\":[]},\n  {\"name\":\"highline\",\"number\":\"1.6.19\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.8.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"0.4.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.5\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"0.4.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.5\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.5.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.6\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.2.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.2.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.5.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.6\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.7\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.9\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.5.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.8\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.7\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"0.4.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.4\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.5\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.5\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.6\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.4.3\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.6\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.5.5\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.6.8\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.7.7\",\"dependencies\":[]},\n  {\"name\":\"json\",\"number\":\"1.8.0\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.8.1\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.1.5\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.4.4\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.4.1\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.1.6\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.6.2\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.2.4\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.7.2\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.5.4\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.6.6\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.6.7\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.7.1\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.2.3\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.5.2\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.5.3\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.1.8\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.4.3\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.4.6\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.1.4\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.6.1\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.4.2\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.4.5\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.1.9\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.1.7\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.6.3\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.6.4\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.6.5\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.7.3\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.7.4\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.7.5\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.7.6\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.7.7\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.5.5\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.6.8\",\"dependencies\":[]},\n  {\"name\":\"json-pure\",\"number\":\"1.8.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.9.2\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.9.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.9.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.8.4\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.8.3\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.8.2\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.8.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.4\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.0.4\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"0.0.5\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.5\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.6\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"0.0.4\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"0.0.2\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"0.0.3\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.7\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.3\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.6.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.6.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.8.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.0\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.1\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.2\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.3\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.4\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.5\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.6\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.7\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.8\",\"dependencies\":[]},\n  {\"name\":\"multi-json\",\"number\":\"1.7.9\",\"dependencies\":[]},\n  {\"name\":\"net-scp\",\"number\":\"1.0.2\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.0.3\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.0.1\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.0.0\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.0.4\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.1.0\",\"dependencies\":[[\"net-ssh\",\"2.6.5\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.1.1\",\"dependencies\":[[\"net-ssh\",\"2.6.5\"]]},\n  {\"name\":\"net-scp\",\"number\":\"1.1.2\",\"dependencies\":[[\"net-ssh\",\"2.6.5\"]]},\n  {\"name\":\"net-sftp\",\"number\":\"1.0.0\",\"dependencies\":[[\"net-ssh\",null]]},\n  {\"name\":\"net-sftp\",\"number\":\"0.5.0\",\"dependencies\":[[\"net-ssh\",null]]},\n  {\"name\":\"net-sftp\",\"number\":\"0.9.0\",\"dependencies\":[[\"net-ssh\",null]]},\n  {\"name\":\"net-sftp\",\"number\":\"1.0.1\",\"dependencies\":[[\"net-ssh\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"net-sftp\",\"number\":\"1.1.0\",\"dependencies\":[[\"net-ssh\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"net-sftp\",\"number\":\"2.0.5\",\"dependencies\":[[\"net-ssh\",\"2.0.9\"]]},\n  {\"name\":\"net-sftp\",\"number\":\"2.0.4\",\"dependencies\":[[\"net-ssh\",\"2.0.9\"]]},\n  {\"name\":\"net-sftp\",\"number\":\"2.0.3\",\"dependencies\":[[\"net-ssh\",\"2.0.9\"]]},\n  {\"name\":\"net-sftp\",\"number\":\"2.0.2\",\"dependencies\":[[\"net-ssh\",\"2.0.9\"],[\"echoe\",null]]},\n  {\"name\":\"net-sftp\",\"number\":\"2.0.1\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-sftp\",\"number\":\"2.0.0\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-sftp\",\"number\":\"1.1.1\",\"dependencies\":[[\"net-ssh\",\"1.0.0 || 2.0.0\"],[\"net-ssh\",\"1.0.0 || 2.0.0\"]]},\n  {\"name\":\"net-sftp\",\"number\":\"2.1.0\",\"dependencies\":[[\"net-ssh\",\"2.6.4\"]]},\n  {\"name\":\"net-sftp\",\"number\":\"2.1.1\",\"dependencies\":[[\"net-ssh\",\"2.6.5\"]]},\n  {\"name\":\"net-sftp\",\"number\":\"2.1.2\",\"dependencies\":[[\"net-ssh\",\"2.6.5\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.8.0\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.7.0\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.23\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.5\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.1.4\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.1.1\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.1\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.22\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.18\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"1.1.3\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"0.9.0\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"0.5.0\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.8\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.11\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.7\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.20\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.6\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.1.0\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.1.3\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.13\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.7\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.2\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.2.1\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.3.0\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.24\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.9\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"1.1.2\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.10\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.6\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.19\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.5\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.3\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.10\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.0\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.2.2\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.14\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.8\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.16\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.15\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.17\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.21\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"0.6.0\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"1.0.4\",\"dependencies\":[[\"needle\",\"1.2.0\"]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.9\",\"dependencies\":[[\"echoe\",null]]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.1.4\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.5.2\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.1\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.2\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.3\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.4\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.5\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.6\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.7\",\"dependencies\":[]},\n  {\"name\":\"net-ssh\",\"number\":\"2.6.8\",\"dependencies\":[]},\n  {\"name\":\"net-ssh-gateway\",\"number\":\"1.0.1\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"],[\"echoe\",null]]},\n  {\"name\":\"net-ssh-gateway\",\"number\":\"1.0.0\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-ssh-gateway\",\"number\":\"1.1.0\",\"dependencies\":[[\"net-ssh\",\"1.99.1 || 2.0.0\"]]},\n  {\"name\":\"net-ssh-gateway\",\"number\":\"1.2.0\",\"dependencies\":[[\"net-ssh\",\"2.6.5\"]]},\n  {\"name\":\"rack\",\"number\":\"0.9.0\",\"dependencies\":[[\"test-spec\",null],[\"camping\",null],[\"fcgi\",null],[\"memcache-client\",null],[\"mongrel\",null],[\"ruby-openid\",\"2.0.0\"],[\"thin\",null]]},\n  {\"name\":\"rack\",\"number\":\"1.1.3\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.3\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.1.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.0.0\",\"dependencies\":[[\"test-spec\",null],[\"camping\",null],[\"fcgi\",null],[\"memcache-client\",null],[\"mongrel\",null],[\"ruby-openid\",\"2.0.0\"],[\"thin\",null]]},\n  {\"name\":\"rack\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.3\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"0.9.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.1.2\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.4\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.5\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.5\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.4\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.6\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.4.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.7\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.4.2\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.1.4\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.6\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.8\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.4.3\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.7\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.4.4\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.1.5\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.9\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.5.0\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.2.8\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.4.5\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.1.6\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.3.10\",\"dependencies\":[]},\n  {\"name\":\"rack\",\"number\":\"1.5.2\",\"dependencies\":[]},\n  {\"name\":\"rack-protection\",\"number\":\"1.5.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.5.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.1.3\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.1.4\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"0.1.0\",\"dependencies\":[[\"rack\",null],[\"escape-utils\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.2.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.1.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.0.0\",\"dependencies\":[[\"rack\",null],[\"escape-utils\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.3.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.3.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.4.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"rack-protection\",\"number\":\"1.5.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"sass\",\"number\":\"3.2.18\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.3.4\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.17\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.16\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.3.3\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.3.2\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.3.1\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.3.0\",\"dependencies\":[[\"rake\",null]]},\n  {\"name\":\"sass\",\"number\":\"3.2.15\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.14\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.13\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.12\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.11\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.6\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.14\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.1\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.13\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.11\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.9\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.18\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.19\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.20\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.7\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.1\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.8\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.0\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.3\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.15\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.12\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.21\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.2\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.4\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.17\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.10\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.5\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.0\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.1.16\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.2\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.3\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.4\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.5\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.6\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.7\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.8\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.9\",\"dependencies\":[]},\n  {\"name\":\"sass\",\"number\":\"3.2.10\",\"dependencies\":[]},\n  {\"name\":\"shotgun\",\"number\":\"0.6.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"shotgun\",\"number\":\"0.4.0\",\"dependencies\":[[\"rack\",null],[\"launchy\",null],[\"launchy\",null]]},\n  {\"name\":\"shotgun\",\"number\":\"0.5.0\",\"dependencies\":[[\"rack\",null],[\"launchy\",null],[\"launchy\",null]]},\n  {\"name\":\"shotgun\",\"number\":\"0.7.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"shotgun\",\"number\":\"0.8.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"shotgun\",\"number\":\"0.2.0\",\"dependencies\":[[\"rack\",null],[\"launchy\",null],[\"rack\",null],[\"launchy\",null]]},\n  {\"name\":\"shotgun\",\"number\":\"0.1.0\",\"dependencies\":[[\"rack\",null],[\"rack\",null]]},\n  {\"name\":\"shotgun\",\"number\":\"0.3.0\",\"dependencies\":[[\"rack\",null],[\"launchy\",null],[\"launchy\",null]]},\n  {\"name\":\"shotgun\",\"number\":\"0.9.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.4.4\",\"dependencies\":[[\"rack-protection\",\"1.4.0\"],[\"tilt\",\"1.3.4 || 2.0.0\"],[\"rack\",\"1.4.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.3.3\",\"dependencies\":[[\"rack\",\"0.4.0 || 1.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.1.2\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.0 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.2.0\",\"dependencies\":[[\"mongrel\",\"1.0.1\"],[\"rack\",null],[\"rack\",\"=0.3.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.1.6\",\"dependencies\":[[\"mongrel\",\"1.0.1\"],[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"0.2.2\",\"dependencies\":[[\"mongrel\",\"1.0.1\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.1.5\",\"dependencies\":[[\"mongrel\",\"1.0.1\"],[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"0.1.7\",\"dependencies\":[[\"mongrel\",\"1.0.1\"],[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.6\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.3.2\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"0.1.0\",\"dependencies\":[[\"mongrel\",\"1.0.1\"],[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.3\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.9.2\",\"dependencies\":[[\"rack\",null],[\"shotgun\",null],[\"rack-test\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.0\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.1.3\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.7\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.6\",\"dependencies\":[[\"rack\",\"1.4.0\"],[\"rack-protection\",\"1.3.0\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.2.1\",\"dependencies\":[[\"mongrel\",\"1.0.1\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.3.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.1.4\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.9.5\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.0\",\"dependencies\":[[\"rack\",\"1.3.0\"],[\"rack-protection\",\"1.1.0\"],[\"tilt\",\"1.3.0 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.3.1\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.1\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.9.6\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"0.9.4\",\"dependencies\":[[\"rack\",null],[\"shotgun\",null],[\"rack-test\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.1.0\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.1.0 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"0.9.1\",\"dependencies\":[[\"rack\",null],[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"0.9.0\",\"dependencies\":[[\"rack\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.2\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.0.0\",\"dependencies\":[[\"rack\",\"1.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.8\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.1\",\"dependencies\":[[\"rack\",\"1.3.0\"],[\"rack-protection\",\"1.1.0\"],[\"tilt\",\"1.3.0 || 2.0.0\"],[\"rack\",\"1.3.4\"],[\"rack-protection\",\"1.1.2\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.2\",\"dependencies\":[[\"rack\",\"1.3.6\"],[\"rack-protection\",\"1.2.0\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.3\",\"dependencies\":[[\"rack\",\"1.3.6\"],[\"rack-protection\",\"1.2.0\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.4\",\"dependencies\":[[\"rack\",\"1.4.0\"],[\"rack-protection\",\"1.3.0\"],[\"tilt\",\"1.3.3 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.3.5\",\"dependencies\":[[\"rack\",\"1.4.0\"],[\"rack-protection\",\"1.3.0\"],[\"tilt\",\"1.3.0 || 2.0.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.2.9\",\"dependencies\":[[\"rack\",\"1.1.0\"],[\"tilt\",\"1.2.2 || 2.0.0\"],[\"backports\",null]]},\n  {\"name\":\"sinatra\",\"number\":\"1.4.1\",\"dependencies\":[[\"rack\",\"1.5.2\"],[\"tilt\",\"1.3.4 || 2.0.0\"],[\"rack-protection\",\"1.4.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.4.0\",\"dependencies\":[[\"rack\",\"1.5.2\"],[\"tilt\",\"1.3.4 || 2.0.0\"],[\"rack-protection\",\"1.4.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.4.2\",\"dependencies\":[[\"rack\",\"1.5.2\"],[\"tilt\",\"1.3.4 || 2.0.0\"],[\"rack-protection\",\"1.4.0\"]]},\n  {\"name\":\"sinatra\",\"number\":\"1.4.3\",\"dependencies\":[[\"rack\",\"1.4.0\"],[\"tilt\",\"1.3.4 || 2.0.0\"],[\"rack-protection\",\"1.4.0\"]]},\n  {\"name\":\"sqlite3\",\"number\":\"1.3.9\",\"dependencies\":[]},\n  {\"name\":\"sqlite3\",\"number\":\"0.0.7\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"sqlite3\",\"number\":\"0.0.0\",\"dependencies\":[]},\n  {\"name\":\"sqlite3\",\"number\":\"0.0.6\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"sqlite3\",\"number\":\"0.0.5\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"sqlite3\",\"number\":\"0.0.4\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"sqlite3\",\"number\":\"0.0.3\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"sqlite3\",\"number\":\"1.3.5\",\"dependencies\":[]},\n  {\"name\":\"sqlite3\",\"number\":\"0.0.8\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"sqlite3\",\"number\":\"1.3.6\",\"dependencies\":[]},\n  {\"name\":\"sqlite3\",\"number\":\"1.3.4\",\"dependencies\":[]},\n  {\"name\":\"sqlite3\",\"number\":\"1.3.3\",\"dependencies\":[]},\n  {\"name\":\"sqlite3\",\"number\":\"0.0.1\",\"dependencies\":[]},\n  {\"name\":\"sqlite3\",\"number\":\"0.0.2\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"sqlite3\",\"number\":\"0.1.0\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"sqlite3\",\"number\":\"0.1.1\",\"dependencies\":[[\"ffi\",null]]},\n  {\"name\":\"sqlite3\",\"number\":\"1.3.7\",\"dependencies\":[]},\n  {\"name\":\"sqlite3\",\"number\":\"1.3.8\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.5.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.5.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.4.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.4.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.3.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.2.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.2.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.2.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.1.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.3.3\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"1.5.0\",\"dependencies\":[[\"stringex\",null]]},\n  {\"name\":\"stringex\",\"number\":\"1.5.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.2\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.3\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.4\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.5\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.6\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.7\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.8\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.9\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.10\",\"dependencies\":[]},\n  {\"name\":\"stringex\",\"number\":\"2.0.11\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"2.0.1\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"2.0.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.2\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.1\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.8.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.2.1\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.9.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.2.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.1.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.3.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.5.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.4.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.2.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.10.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.7.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"0.6.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.3\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.2.2\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.4\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.5\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.6\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.3.7\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.4.0\",\"dependencies\":[]},\n  {\"name\":\"tilt\",\"number\":\"1.4.1\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"1.0.3\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"2.1.0\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"1.0.7\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.1.11 || 2.0.0 || 3.0.0\"],[\"launchy\",null]]},\n  {\"name\":\"uuidtools\",\"number\":\"2.1.1\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"0.1.3\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"1.0.6\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.1.11 || 2.0.0 || 3.0.0\"],[\"launchy\",null]]},\n  {\"name\":\"uuidtools\",\"number\":\"0.1.4\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"1.0.2\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"2.1.2\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"0.1.2\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"0.1.1\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"0.1.0\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"1.0.5\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.1.11 || 2.0.0 || 3.0.0\"],[\"launchy\",null]]},\n  {\"name\":\"uuidtools\",\"number\":\"1.0.0\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"1.0.1\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"2.0.0\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.1.11 || 2.0.0 || 3.0.0\"],[\"launchy\",null]]},\n  {\"name\":\"uuidtools\",\"number\":\"1.0.4\",\"dependencies\":[[\"rake\",null],[\"rspec\",\"1.0.8 || 2.0.0 || 3.0.0\"]]},\n  {\"name\":\"uuidtools\",\"number\":\"2.1.3\",\"dependencies\":[]},\n  {\"name\":\"uuidtools\",\"number\":\"2.1.4\",\"dependencies\":[]}\n];\n"
  },
  {
    "path": "packages/constraint-solver/input-tests.js",
    "content": "var CS = ConstraintSolver;\n\n// \"Input tests\" are the new style of tests that operate by creating a\n// CS.Input (representing a problem statement) and passing it into\n// CS.PackagesResolver.\n// For tests of CS.Input serialization, see constraint-solver-tests.js.\n\n\n// Yeah, we rely on object key order here.  Specifically that\n// if you add a bunch of keys to an object (that look like package\n// names) and then JSON.stringify the object, the keys will appear\n// in that order.  If that's not true, these tests will break.\nvar sortKeys = function (obj) {\n  var result = {};\n  _.each(_.keys(obj).sort(), function (k) {\n    result[k] = obj[k];\n  });\n  return result;\n};\nvar formatSolution = function (obj) {\n  // Note that we use JSON so that it's easy to copy-and-paste test\n  // results into tests.\n  return JSON.stringify({\n    answer: sortKeys(obj.answer),\n    allAnswers: obj.allAnswers && _.map(obj.allAnswers, sortKeys),\n    neededToUseUnanticipatedPrereleases: obj.neededToUseUnanticipatedPrereleases\n  }, null, 2);\n};\n\nvar doTest = function (test, inputJSONable, outputJSONable, options) {\n  var input;\n  if (inputJSONable instanceof CS.Input) {\n    input = inputJSONable;\n  } else {\n    input = CS.Input.fromJSONable(inputJSONable);\n  }\n\n  if (typeof outputJSONable.neededToUseUnanticipatedPrereleases !== 'boolean') {\n    outputJSONable = _.extend(outputJSONable, {\n      neededToUseUnanticipatedPrereleases: (\n        !! outputJSONable.neededToUseUnanticipatedPrereleases)\n    });\n  }\n\n  test.equal(\n    formatSolution(CS.PackagesResolver._resolveWithInput(input, options)),\n    formatSolution(outputJSONable));\n};\n\nvar doFailTest = function (test, inputJSONable, messageExpect) {\n  var input;\n  if (inputJSONable instanceof CS.Input) {\n    input = inputJSONable;\n  } else {\n    input = CS.Input.fromJSONable(inputJSONable);\n  }\n\n  test.throws(function () {\n    try {\n      CS.PackagesResolver._resolveWithInput(input);\n    } catch (e) {\n      if (! e.constraintSolverError) {\n        test.fail(e.message);\n      }\n      throw e;\n    }\n  }, messageExpect);\n};\n\nTinytest.add(\"constraint solver - input - upgrade indirect dependency\", function (test) {\n  doTest(test, {\n    dependencies: [\"foo\"],\n    constraints: [],\n    previousSolution: { foo: \"1.0.0\", bar: \"2.0.0\" },\n    upgrade: [\"bar\"],\n    catalogCache: {\n      data: {\n        \"foo 1.0.0\": [\"bar@2.0.0\"],\n        \"bar 2.0.0\": [],\n        \"bar 2.0.1\": []\n      }\n    }\n  }, {\n    // if you specify an indirect dependency in `meteor update`,\n    // it will get bumped up to a newer version\n    answer: {\n      foo: \"1.0.0\",\n      bar: \"2.0.1\"\n    }\n  });\n});\n\nTinytest.add(\"constraint solver - input - upgrade direct, don't break\", function (test) {\n  doTest(test, {\n    dependencies: [\"foo\", \"bar\"],\n    constraints: [],\n    previousSolution: { foo: \"1.0.0\", bar: \"2.0.0\" },\n    upgrade: [\"bar\"],\n    catalogCache: {\n      data: {\n        \"foo 1.0.0\": [\"bar@2.0.0||3.0.0\"],\n        \"bar 2.0.0\": [],\n        \"bar 3.0.0\": []\n      }\n    }\n  }, {\n    answer: {\n      foo: \"1.0.0\",\n      bar: \"2.0.0\"\n    }\n  });\n\n  // if allowIncompatibleUpdate is set, upgrade bar to 3.0.0\n  doTest(test, {\n    dependencies: [\"foo\", \"bar\"],\n    constraints: [],\n    previousSolution: { foo: \"1.0.0\", bar: \"2.0.0\" },\n    upgrade: [\"bar\"],\n    allowIncompatibleUpdate: true,\n    catalogCache: {\n      data: {\n        \"foo 1.0.0\": [\"bar@2.0.0||3.0.0\"],\n        \"bar 2.0.0\": [],\n        \"bar 3.0.0\": []\n      }\n    }\n  }, {\n    answer: {\n      foo: \"1.0.0\",\n      bar: \"3.0.0\"\n    }\n  });\n});\n\nTinytest.add(\"constraint solver - input - previous solution no patch\", function (test) {\n  doTest(test, {\n    dependencies: [\"foo\"],\n    constraints: [],\n    previousSolution: { foo: \"1.0.0\", bar: \"2.0.0\" },\n    catalogCache: {\n      data: {\n        \"foo 1.0.0\": [\"bar@2.0.0\"],\n        \"foo 1.0.1\": [\"bar@2.0.1\"],\n        \"bar 2.0.0\": [],\n        \"bar 2.0.1\": []\n      }\n    }\n  }, {\n    answer: {\n      foo: \"1.0.0\",\n      bar: \"2.0.0\"\n    }\n  });\n});\n\n\nTinytest.add(\"constraint solver - input - don't break root dep\", function (test) {\n  doTest(test, {\n    dependencies: [\"foo\", \"bar\"],\n    constraints: [],\n    previousSolution: { bar: \"2.0.0\" },\n    upgrade: [],\n    catalogCache: {\n      data: {\n        \"foo 1.0.0\": [\"bar@=2.0.1\"],\n        \"bar 2.0.0\": [],\n        \"bar 2.0.1\": []\n      }\n    }\n  }, {\n    answer: {\n      foo: \"1.0.0\",\n      bar: \"2.0.1\"\n    }\n  });\n\n  doFailTest(test, {\n    dependencies: [\"foo\", \"bar\"],\n    constraints: [],\n    previousSolution: { bar: \"2.0.1\" },\n    upgrade: [],\n    catalogCache: {\n      data: {\n        \"foo 1.0.0\": [\"bar@=2.0.0\"],\n        \"bar 2.0.0\": [],\n        \"bar 2.0.1\": []\n      }\n    }\n  }, 'Potentially incompatible change required to top-level dependency: bar 2.0.0, was 2.0.1.\\nConstraints on package \"bar\":\\n* bar@=2.0.0 <- foo 1.0.0\\n\\nTo allow potentially incompatible changes to top-level dependencies, you must pass --allow-incompatible-update on the command line.');\n});\n\nTinytest.add(\"constraint solver - input - don't pick RCs\", function (test) {\n  // First verify that the solver takes the latest version when\n  // presented with a new root dependency (i.e. one not mentioned in\n  // a previous solution) -- and also that it will take a prerelease if\n  // it has no choice.\n  doTest(test, {\n    dependencies: [\"a\"],\n    constraints: [],\n    catalogCache: {\n      data: {\n        \"a 1.0.0-pre.0\": [],\n        \"a 1.0.0-pre.1\": []\n      }\n    }\n  }, {\n    answer: {\n      a: \"1.0.0-pre.1\"\n    },\n    neededToUseUnanticipatedPrereleases: true\n  });\n\n  // If we have the option to take a non-pre-release version,\n  // we should.\n  doTest(test, {\n    dependencies: [\"a\"],\n    constraints: [],\n    catalogCache: {\n      data: {\n        \"a 0.9.0\": [],\n        \"a 1.0.0-pre.0\": [],\n        \"a 1.0.0-pre.1\": []\n      }\n    }\n  }, {\n    answer: {\n      a: \"0.9.0\"\n    },\n    neededToUseUnanticipatedPrereleases: false\n  });\n\n  // If the prerelease versions are \"anticipated\", take\n  // the latest one.\n  doTest(test, {\n    dependencies: [\"a\"],\n    constraints: [],\n    anticipatedPrereleases: { a: {\n      \"1.0.0-pre.0\": true, \"1.0.0-pre.1\": true } },\n    catalogCache: {\n      data: {\n        \"a 0.9.0\": [],\n        \"a 1.0.0-pre.0\": [],\n        \"a 1.0.0-pre.1\": []\n      }\n    }\n  }, {\n    answer: {\n      a: \"1.0.0-pre.1\"\n    },\n    neededToUseUnanticipatedPrereleases: false\n  });\n\n  // Don't take the unanticipated pre-releases here.\n  doTest(test, {\n    dependencies: [\"a\"],\n    constraints: [\"a@1.0.0\"],\n    catalogCache: {\n      data: {\n        \"a 1.0.0\": [],\n        \"a 1.0.1-pre.0\": [],\n        \"a 1.0.1-pre.1\": []\n      }\n    }\n  }, {\n    answer: {\n      a: \"1.0.0\"\n    },\n    neededToUseUnanticipatedPrereleases: false\n  });\n\n  // If we ask for one prerelease, we might get another.\n  // If it isn't anticipated, it sets the flag on the result\n  // (differs from older behavior).\n  doTest(test, {\n    dependencies: [\"a\"],\n    constraints: [\"a@1.0.1-pre.0\"],\n    anticipatedPrereleases: { a: {\n      \"1.0.0-pre.0\": true } },\n    catalogCache: {\n      data: {\n        \"a 1.0.0\": [],\n        \"a 1.0.1-pre.0\": [],\n        \"a 1.0.1-pre.1\": []\n      }\n    }\n  }, {\n    answer: {\n      a: \"1.0.1-pre.1\"\n    },\n    neededToUseUnanticipatedPrereleases: true\n  });\n\n});\n\nTinytest.add(\"constraint solver - input - previous solution no longer needed\", function (test) {\n  doTest(test, {\n    dependencies: [\"foo\"],\n    constraints: [],\n    previousSolution: { foo: \"1.0.0\", bar: \"1.0.0\" },\n    catalogCache: {\n      data: {\n        \"foo 0.1.0\": [\"bar@1.0.0\"],\n        \"foo 1.0.0\": [],\n        \"bar 1.0.0\": []\n      }\n    }\n  }, {\n    answer: {\n      foo: \"1.0.0\"\n    }\n  });\n});\n\nTinytest.add(\"constraint solver - input - conflicting top-level constraints\", function (test) {\n  // conflicting dependencies don't matter if we don't need the package\n  doTest(test, {\n    dependencies: [],\n    constraints: [\"foo@1.0.0\", \"foo@2.0.0\"],\n    previousSolution: {},\n    catalogCache: {\n      data: {\n        \"foo 1.0.0\": [],\n        \"foo 2.0.0\": []\n      }\n    }\n  }, {\n    answer: {\n    }\n  });\n\n  // ... but they do if we do\n  doFailTest(test, {\n    dependencies: [\"bar\"],\n    constraints: [\"foo@1.0.0\", \"foo@2.0.0\"],\n    previousSolution: {},\n    catalogCache: {\n      data: {\n        \"foo 1.0.0\": [],\n        \"foo 2.0.0\": [],\n        \"bar 1.0.0\": [\"foo\"]\n      }\n    }\n  }, /No version of foo satisfies all constraints: @1.0.0, @2.0.0/);\n});\n\nTinytest.add(\"constraint solver - input - unknown package\", function (test) {\n  doFailTest(test, {\n    dependencies: [\"bar\"],\n    constraints: [],\n    catalogCache: {\n      data: {}\n    }\n  }, /unknown package in top-level dependencies: bar/);\n  doFailTest(test, {\n    dependencies: ['foo'],\n    constraints: [],\n    catalogCache: {\n      data: {\n        \"foo 1.0.0\": [\"bar\"]\n      }\n    }\n  }, /unknown package: bar\\nRequired by: foo 1.0.0/);\n  doFailTest(test, {\n    dependencies: [\"isobuild:bar\"],\n    constraints: [],\n    catalogCache: {\n      data: {}\n    }\n  }, /unsupported Isobuild feature \"isobuild:bar\" in top-level dependencies/);\n  doFailTest(test, {\n    dependencies: ['foo'],\n    constraints: [],\n    catalogCache: {\n      data: {\n        \"foo 1.0.0\": [\"isobuild:bar\"]\n      }\n    }\n  }, /unsupported Isobuild feature \"isobuild:bar\";.*\\nRequired by: foo 1.0.0/);\n});\n\nTinytest.add(\"constraint solver - input - previous indirect deps\", function (test) {\n  doTest(test, {\n    dependencies: [\"a\"],\n    constraints: [],\n    previousSolution: { c: \"1.2.3\" },\n    catalogCache: {\n      data: {\n        \"a 1.0.0\": [\"b\"],\n        \"b 1.0.0\": [\"c\"],\n        \"c 1.0.0\": [],\n        \"c 1.2.2\": [],\n        \"c 1.2.3\": [],\n        \"c 1.2.4\": [],\n        \"c 1.3.0\": [],\n        \"c 2.0.0\": []\n      }\n    }\n  }, {\n    answer: {\n      a: \"1.0.0\",\n      b: \"1.0.0\",\n      c: \"1.2.3\" // take same version as in previous solution\n    }\n  });\n});\n\nTinytest.add(\"constraint solver - input - new indirect deps\", function (test) {\n  doTest(test, {\n    dependencies: [\"a\"],\n    constraints: [],\n    previousSolution: {},\n    catalogCache: {\n      data: {\n        \"a 1.0.0\": [\"b\"],\n        \"b 1.0.0\": [\"c@1.2.0\"],\n        \"c 1.0.0\": [],\n        \"c 1.2.2\": [],\n        \"c 1.2.3\": [],\n        \"c 1.2.4\": [],\n        \"c 1.3.0\": [],\n        \"c 2.0.0\": []\n      }\n    }\n  }, {\n    answer: {\n      a: \"1.0.0\",\n      b: \"1.0.0\",\n      c: \"1.2.4\" // take patches only (use oldest major/minor possible)\n    }\n  });\n});\n\nTinytest.add(\"constraint solver - input - trade-off\", function (test) {\n  doTest(test, {\n    dependencies: [\"a\"],\n    constraints: [],\n    previousSolution: { b: \"1.0.0\", c: \"1.0.0\" },\n    catalogCache: {\n      data: {\n        \"a 1.0.0\": [\"b\", \"c\"],\n        \"b 1.0.0\": [\"x\"],\n        \"b 1.0.1\": [\"y@1.0.0\"],\n        \"b 1.0.2\": [\"y@2.0.0\"],\n        \"c 1.0.0\": [\"x\"],\n        \"c 1.0.1\": [\"y@2.0.0\"],\n        \"c 1.0.2\": [\"x\"],\n        \"c 1.0.3\": [\"y@1.0.0\"],\n        \"y 1.0.0\": [],\n        \"y 2.0.0\": []\n      }\n    }\n  }, {\n    // given a choice between (b,c) being (1.0.1, 1.0.3) or (1.0.2, 1.0.1),\n    // the latter should be preferred; indirect dependencies with a previous\n    // solution should be jointly made as old as possible.\n    answer: {\n      a: \"1.0.0\",\n      b: \"1.0.2\",\n      c: \"1.0.1\",\n      y: \"2.0.0\"\n    }\n  });\n\n  doTest(test, {\n    dependencies: [\"a\", \"b\", \"c\"],\n    constraints: [],\n    previousSolution: {},\n    catalogCache: {\n      data: {\n        \"a 1.0.0\": [\"b\", \"c\"],\n        \"b 1.0.0\": [\"x\"],\n        \"b 1.0.1\": [\"y@1.0.0\"],\n        \"b 1.0.2\": [\"y@2.0.0\"],\n        \"c 1.0.0\": [\"x\"],\n        \"c 1.0.1\": [\"y@2.0.0\"],\n        \"c 1.0.2\": [\"x\"],\n        \"c 1.0.3\": [\"y@1.0.0\"],\n        \"y 1.0.0\": [],\n        \"y 2.0.0\": []\n      }\n    }\n  }, {\n    // now we should prefer \"b\" and \"c\" to jointly be as new as possible,\n    // because they are direct dependencies with no previous solution.\n    answer: {\n      a: \"1.0.0\",\n      b: \"1.0.1\",\n      c: \"1.0.3\",\n      y: \"1.0.0\"\n    }\n  });\n\n});\n\nTinytest.add(\"constraint solver - input - fake PackageConstraint\", function (test) {\n  // The tool gives us PackageConstraint objects constructed with a different\n  // copy of package-version-parser.  If we're not careful in CS.Input or\n  // CS.Solver, this case will throw an error.  See comments in CS.Input.\n  var fakeConstraint = new (function () {});\n  fakeConstraint.package = 'foo';\n  fakeConstraint.constraintString = '2.0.0';\n  fakeConstraint.toString = function () {\n    return 'foo@2.0.0';\n  };\n  fakeConstraint.versionConstraint = new (function () {});\n  fakeConstraint.versionConstraint.raw = '2.0.0';\n  fakeConstraint.versionConstraint.alternatives = [\n    {type: 'compatible-with', versionString: '2.0.0' }\n  ];\n  fakeConstraint.versionConstraint.toString = function () {\n    return '2.0.0';\n  };\n\n  doFailTest(test,\n             new CS.Input([\"foo\", \"bar\"], [fakeConstraint],\n                          CS.CatalogCache.fromJSONable({\n                            data: {\n                              \"foo 1.0.0\": [],\n                              \"foo 2.0.0\": [],\n                              \"bar 1.0.0\": [\"foo@1.0.0\"]\n                            }\n                          })),\n             /Constraint foo@1.0.0 is not satisfied by foo 2.0.0/);\n});\n\nTinytest.add(\"constraint solver - input - stack overflow bug\", function (test) {\n  // This case is taken from the \"solver-error\" branch of the meteor/rectangles\n  // repo.  It's an app running from a release (new-version-solver-2) with an\n  // unsatisfiable constraint in .meteor/packages.  It caused a stack overflow\n  // before logic-solver got smarter about avoiding recursion in formula\n  // generation, and it also tests the case where an unsatisfiable constraint is\n  // in .meteor/packages.\n  //\n  // It's not actually a good test of logic-solver overflowing the stack anymore,\n  // because the constraint-solver is smarter now.\n  doFailTest(test, STACK_OVERFLOW_BUG_INPUT,\n             /No version of follower-livedata satisfies all constraints: @0.9.0/);\n});\n\n\nTinytest.add(\"constraint solver - input - bad package name\", function (test) {\n  test.throws(function () {\n    new CS.Input(['-x'], [], new CS.CatalogCache());\n  }, /may not begin with a hyphen/);\n\n  test.throws(function () {\n    new CS.Input([], [], new CS.CatalogCache(),\n                 { previousSolution: { $a: '1.0.0' } });\n  }, /Package names can only contain/);\n\n  test.throws(function () {\n    new CS.Input([], [], new CS.CatalogCache(),\n                 { upgrade: ['$a'] });\n  }, /Package names can only contain/);\n\n  test.throws(function () {\n    new CS.Input([], [], new CS.CatalogCache(),\n                 { upgrade: ['-a'] });\n  }, /may not begin with a hyphen/);\n});\n\n\nTinytest.add(\"constraint solver - input - slow solve\", function (test) {\n  var input = CS.Input.fromJSONable(SLOW_TEST_DATA);\n\n  test.equal(\n    formatSolution(CS.PackagesResolver._resolveWithInput(input)),\n    formatSolution({\n      \"answer\":{\n        \"autopublish\":\"1.0.2\",\n        \"u2622:persistent-session\":\"0.2.1\",\n        \"blaze\":\"2.0.4\",\n        \"random\":\"1.0.2\",\n        \"mobile-status-bar\":\"1.0.2\",\n        \"deps\":\"1.0.6\",\n        \"follower-livedata\":\"1.0.3\",\n        \"spacebars\":\"1.0.4\",\n        \"spacebars-compiler\":\"1.0.4\",\n        \"launch-screen\":\"1.0.1\",\n        \"iron:location\":\"1.0.6\",\n        \"http\":\"1.0.9\",\n        \"json\":\"1.0.2\",\n        \"check\":\"1.0.3\",\n        \"retry\":\"1.0.2\",\n        \"id-map\":\"1.0.2\",\n        \"reactive-dict\":\"1.0.5\",\n        \"mrt:moment\":\"2.8.1\",\n        \"callback-hook\":\"1.0.2\",\n        \"meteor\":\"1.1.4\",\n        \"fastclick\":\"1.0.2\",\n        \"minifiers\":\"1.1.3\",\n        \"mrt:jquery-ui-sortable\":\"1.10.3\",\n        \"webapp\":\"1.1.5\",\n        \"ejson\":\"1.0.5\",\n        \"skinnygeek1010:parse-form\":\"0.2.1\",\n        \"iron:controller\":\"1.0.6\",\n        \"base64\":\"1.0.2\",\n        \"url\":\"1.0.3\",\n        \"blaze-tools\":\"1.0.2\",\n        \"ddp\":\"1.0.13\",\n        \"iron:core\":\"1.0.6\",\n        \"splendido:accounts-templates-semantic-ui\":\"0.0.4\",\n        \"observe-sequence\":\"1.0.4\",\n        \"reactive-var\":\"1.0.4\",\n        \"webapp-hashing\":\"1.0.2\",\n        \"mongo\":\"1.0.11\",\n        \"htmljs\":\"1.0.3\",\n        \"ui\":\"1.0.5\",\n        \"amplify\":\"1.0.0\",\n        \"meteor-platform\":\"1.2.1\",\n        \"ordered-dict\":\"1.0.2\",\n        \"session\":\"1.0.5\",\n        \"livedata\":\"1.0.12\",\n        \"templating\":\"1.0.10\",\n        \"binary-heap\":\"1.0.2\",\n        \"mizzao:timesync\":\"0.2.2\",\n        \"tracker\":\"1.0.4\",\n        \"autoupdate\":\"1.1.4\",\n        \"html-tools\":\"1.0.3\",\n        \"reload\":\"1.1.2\",\n        \"less\":\"1.0.12\",\n        \"application-configuration\":\"1.0.4\",\n        \"gfk:notifications\":\"1.1.1\",\n        \"underscore\":\"1.0.2\",\n        \"iron:dynamic-template\":\"1.0.6\",\n        \"routepolicy\":\"1.0.3\",\n        \"iron:router\":\"1.0.6\",\n        \"insecure\":\"1.0.2\",\n        \"iron:layout\":\"1.0.6\",\n        \"geojson-utils\":\"1.0.2\",\n        \"minimongo\":\"1.0.6\",\n        \"iron:url\":\"1.0.6\",\n        \"jquery\":\"1.11.2\",\n        \"boilerplate-generator\":\"1.0.2\",\n        \"iron:middleware-stack\":\"1.0.6\",\n        \"logging\":\"1.0.6\"\n      },\n      \"neededToUseUnanticipatedPrereleases\":false\n    }));\n});\n\nTinytest.add(\"constraint solver - input - update unknown\", function (test) {\n  // trying to update an unknown package is currently not an error\n  // at the CS.Input level.  It IS an error in the tool, so this case\n  // won't make it through in actual tool usage.\n  doTest(test, {\n    dependencies: [\"direct\"],\n    constraints: [],\n    previousSolution: {\n      direct: \"1.0.0\"\n    },\n    upgrade: [\"unknown\"],\n    catalogCache: {\n      data: {\n        \"direct 1.0.0\": []\n      }\n    }\n  }, {\n    answer: {\n      direct: \"1.0.0\"\n    }\n  });\n});\n\nTinytest.add(\"constraint solver - input - update indirect deps\", function (test) {\n  // test upgrading an indirect dependency explicitly.\n  // `meteor update indirect` takes it from 1.0.0 to 2.0.0 (with no concern\n  // about bumping the major version because it's not a top-level package,\n  // and the only package that uses it doesn't specify any constraint).\n  doTest(test, {\n    dependencies: [\"direct\"],\n    constraints: [],\n    previousSolution: {\n      direct: \"1.0.0\",\n      indirect: \"1.0.0\"\n    },\n    upgrade: [\"indirect\"],\n    catalogCache: {\n      data: {\n        \"direct 1.0.0\": [\"indirect\"],\n        \"indirect 1.0.0\": [],\n        \"indirect 2.0.0\": []\n      }\n    }\n  }, {\n    answer: {\n      direct: \"1.0.0\",\n      indirect: \"2.0.0\"\n    }\n  });\n\n  // Normally, we don't take patches to indirect dependencies, even when\n  // updating direct dependencies.  This is what would happen if the user\n  // typed `meteor update direct`.\n  doTest(test, {\n    dependencies: [\"direct\"],\n    constraints: [],\n    previousSolution: {\n      direct: \"1.0.0\",\n      indirect: \"1.0.0\"\n    },\n    upgrade: [\"direct\"],\n    catalogCache: {\n      data: {\n        \"direct 1.0.0\": [\"indirect\"],\n        \"direct 1.5.0\": [\"indirect\"],\n        \"direct 2.0.0\": [\"indirect\"],\n        \"indirect 1.0.0\": [],\n        \"indirect 1.0.1\": [],\n        \"indirect 1.1.0\": []\n      }\n    }\n  }, {\n    answer: {\n      direct: \"1.5.0\", // upgraded (but not to higher major version)\n      indirect: \"1.0.0\" // not upgraded\n    }\n  });\n\n  // If upgradeIndirectDepPatchVersions is true, user just typed\n  // `meteor update`.  Take the opportunity to take patches to indirect\n  // dependencies.\n  doTest(test, {\n    dependencies: [\"direct\"],\n    constraints: [],\n    previousSolution: {\n      direct: \"1.0.0\",\n      indirect: \"1.0.0\",\n      indirect2: \"1.0.0\"\n    },\n    upgrade: [\"direct\"],\n    upgradeIndirectDepPatchVersions: true,\n    catalogCache: {\n      data: {\n        \"direct 1.0.0\": [\"indirect\"],\n        \"direct 1.5.0\": [\"indirect\", \"indirect2\"],\n        \"direct 2.0.0\": [\"indirect\"],\n        \"indirect 1.0.0\": [],\n        \"indirect 1.0.0_1\": [],\n        \"indirect 1.0.1\": [],\n        \"indirect 1.1.0\": [],\n        \"indirect2 1.0.0\": [],\n        \"indirect2 1.0.0_1\": [],\n        \"indirect2 1.0.0_2\": [],\n        \"indirect2 1.1.0\": []\n      }\n    }\n  }, {\n    answer: {\n      direct: \"1.5.0\", // upgraded (but not to higher major version)\n      indirect: \"1.0.1\", // patch/wrapNum upgraded to latest\n      indirect2: \"1.0.0_2\" // patch/wrapNum upgraded to latest\n    }\n  });\n});\n\nTinytest.add(\"constraint solver - input - package is only weak dep\", function (test) {\n  doTest(test, {\n    dependencies: [\"foo\"],\n    constraints: [],\n    previousSolution: {},\n    catalogCache: {\n      data: {\n        \"foo 1.0.0\": [\"?bar\"]\n      }\n    }\n  }, {\n    answer: {\n      foo: \"1.0.0\"\n    }\n  });\n});\n"
  },
  {
    "path": "packages/constraint-solver/package.js",
    "content": "Package.describe({\n  summary: \"Given the set of the constraints, picks a satisfying configuration\",\n  version: \"1.0.26\"\n});\n\nPackage.onUse(function (api) {\n  api.export('ConstraintSolver');\n  api.use([\n    'underscore',\n    'check',\n    'package-version-parser',\n    'logic-solver'\n  ]);\n  api.addFiles([\n    'datatypes.js',\n    'catalog-cache.js',\n    'catalog-loader.js',\n    'constraint-solver-input.js',\n    'version-pricer.js',\n    'solver.js',\n    'constraint-solver.js']);\n});\n\nPackage.onTest(function (api) {\n  api.use('constraint-solver');\n  api.use([\n    'tinytest',\n    'minimongo',\n    'package-version-parser',\n    'underscore',\n    'check'\n  ]);\n\n  // Only test the package on the server.  Mainly because of\n  // package-version-parser, which uses the semver npm module,\n  // this package is not \"IE 8 clean\".  However, it works on\n  // modern browsers.\n  var where = ['server'];\n\n  // Data for old big, slow tests, which are hidden behind an environment\n  // variable\n  api.addFiles('gem-test-data.js', where);\n  // Data for a case that used to take 20 seconds with the old solver\n  api.addFiles('slow-test-data.js', where);\n  // Data for a case that used to cause a stack overflow\n  api.addFiles('stack-overflow-bug-test-data.js', where);\n\n  api.addFiles('datatypes-tests.js', where);\n  api.addFiles('catalog-cache-tests.js', where);\n  api.addFiles('constraint-solver-tests.js', where);\n  api.addFiles('benchmark-tests.js', where);\n  api.addFiles('input-tests.js', where);\n  api.addFiles('version-pricer-tests.js', where);\n});\n"
  },
  {
    "path": "packages/constraint-solver/slow-test-data.js",
    "content": "SLOW_TEST_DATA = {\n  \"dependencies\": [\n    \"meteor-platform\",\n    \"autopublish\",\n    \"insecure\",\n    \"iron:router\",\n    \"mizzao:timesync\",\n    \"mrt:jquery-ui-sortable\",\n    \"mrt:moment\",\n    \"skinnygeek1010:parse-form\",\n    \"splendido:accounts-templates-semantic-ui\",\n    \"u2622:persistent-session\",\n    \"gfk:notifications\"\n  ],\n  \"constraints\": [\n    \"meteor-platform\",\n    \"autopublish\",\n    \"insecure\",\n    \"iron:router\",\n    \"mizzao:timesync\",\n    \"mrt:jquery-ui-sortable\",\n    \"mrt:moment\",\n    \"skinnygeek1010:parse-form\",\n    \"splendido:accounts-templates-semantic-ui\",\n    \"u2622:persistent-session\",\n    \"gfk:notifications\",\n    \"accounts-base@=1.1.3\",\n    \"local-test:accounts-base@=1.1.3\",\n    \"accounts-facebook@=1.0.3\",\n    \"accounts-github@=1.0.3\",\n    \"accounts-google@=1.0.3\",\n    \"accounts-meetup@=1.0.3\",\n    \"accounts-meteor-developer@=1.0.3\",\n    \"accounts-oauth@=1.1.3\",\n    \"local-test:accounts-oauth@=1.1.3\",\n    \"accounts-password@=1.0.5\",\n    \"local-test:accounts-password@=1.0.5\",\n    \"accounts-twitter@=1.0.3\",\n    \"accounts-ui-unstyled@=1.1.5\",\n    \"local-test:accounts-ui-unstyled@=1.1.5\",\n    \"accounts-ui@=1.1.4\",\n    \"accounts-weibo@=1.0.3\",\n    \"appcache@=1.0.3\",\n    \"local-test:appcache@=1.0.3\",\n    \"application-configuration@=1.0.4\",\n    \"audit-argument-checks@=1.0.2\",\n    \"autopublish@=1.0.2\",\n    \"autoupdate@=1.1.4\",\n    \"base64@=1.0.2\",\n    \"local-test:base64@=1.0.2\",\n    \"binary-heap@=1.0.2\",\n    \"local-test:binary-heap@=1.0.2\",\n    \"blaze-tools@=1.0.2\",\n    \"local-test:blaze-tools@=1.0.2\",\n    \"blaze@=2.0.4\",\n    \"local-test:blaze@=2.0.4\",\n    \"boilerplate-generator@=1.0.2\",\n    \"browser-policy-common@=1.0.2\",\n    \"browser-policy-content@=1.0.3\",\n    \"browser-policy-framing@=1.0.3\",\n    \"browser-policy@=1.0.3\",\n    \"local-test:browser-policy@=1.0.3\",\n    \"callback-hook@=1.0.2\",\n    \"check@=1.0.3\",\n    \"local-test:check@=1.0.3\",\n    \"code-prettify@=1.0.2\",\n    \"coffeescript-test-helper@=1.0.2\",\n    \"coffeescript@=1.0.5\",\n    \"local-test:coffeescript@=1.0.5\",\n    \"constraint-solver@=1.0.16\",\n    \"local-test:constraint-solver@=1.0.16\",\n    \"ctl-helper@=1.0.5\",\n    \"ctl@=1.0.3\",\n    \"ddp@=1.0.13\",\n    \"local-test:ddp@=1.0.13\",\n    \"deps@=1.0.6\",\n    \"dev-bundle-fetcher@=1.0.2\",\n    \"disable-oplog@=1.0.2\",\n    \"ejson@=1.0.5\",\n    \"local-test:ejson@=1.0.5\",\n    \"email@=1.0.5\",\n    \"local-test:email@=1.0.5\",\n    \"facebook@=1.1.3\",\n    \"facts@=1.0.3\",\n    \"fastclick@=1.0.2\",\n    \"follower-livedata@=1.0.3\",\n    \"force-ssl@=1.0.3\",\n    \"geojson-utils@=1.0.2\",\n    \"local-test:geojson-utils@=1.0.2\",\n    \"github@=1.1.2\",\n    \"google@=1.1.3\",\n    \"handlebars@=1.0.2\",\n    \"html-tools@=1.0.3\",\n    \"local-test:html-tools@=1.0.3\",\n    \"htmljs@=1.0.3\",\n    \"local-test:htmljs@=1.0.3\",\n    \"http@=1.0.9\",\n    \"local-test:http@=1.0.9\",\n    \"id-map@=1.0.2\",\n    \"insecure@=1.0.2\",\n    \"jquery-waypoints@=1.0.2\",\n    \"jquery@=1.11.2\",\n    \"js-analyze-tests@=1.0.2\",\n    \"local-test:js-analyze-tests@=1.0.2\",\n    \"js-analyze@=1.0.4\",\n    \"json@=1.0.2\",\n    \"jsparse@=1.0.2\",\n    \"local-test:jsparse@=1.0.2\",\n    \"launch-screen@=1.0.1\",\n    \"less@=1.0.12\",\n    \"local-test:less@=1.0.12\",\n    \"livedata@=1.0.12\",\n    \"localstorage@=1.0.2\",\n    \"local-test:localstorage@=1.0.2\",\n    \"logging@=1.0.6\",\n    \"local-test:logging@=1.0.6\",\n    \"markdown@=1.0.3\",\n    \"local-test:markdown@=1.0.3\",\n    \"meetup@=1.1.2\",\n    \"meteor-developer@=1.1.2\",\n    \"meteor-platform@=1.2.1\",\n    \"meteor-tool@=1.0.38\",\n    \"meteor@=1.1.4\",\n    \"local-test:meteor@=1.1.4\",\n    \"meyerweb-reset@=1.0.2\",\n    \"minifiers@=1.1.3\",\n    \"local-test:minifiers@=1.1.3\",\n    \"minimongo@=1.0.6\",\n    \"local-test:minimongo@=1.0.6\",\n    \"mobile-status-bar@=1.0.2\",\n    \"mongo-livedata@=1.0.7\",\n    \"mongo@=1.0.11\",\n    \"local-test:mongo@=1.0.11\",\n    \"oauth-encryption@=1.0.2\",\n    \"local-test:oauth-encryption@=1.0.2\",\n    \"oauth@=1.1.3\",\n    \"local-test:oauth@=1.1.3\",\n    \"oauth1@=1.1.3\",\n    \"local-test:oauth1@=1.1.3\",\n    \"oauth2@=1.1.2\",\n    \"local-test:oauth2@=1.1.2\",\n    \"observe-sequence@=1.0.4\",\n    \"local-test:observe-sequence@=1.0.4\",\n    \"ordered-dict@=1.0.2\",\n    \"package-stats-opt-out@=1.0.2\",\n    \"package-version-parser@=3.0.0\",\n    \"local-test:package-version-parser@=3.0.0\",\n    \"preserve-inputs@=1.0.2\",\n    \"random@=1.0.2\",\n    \"local-test:random@=1.0.2\",\n    \"reactive-dict@=1.0.5\",\n    \"local-test:reactive-dict@=1.0.5\",\n    \"reactive-var@=1.0.4\",\n    \"reload-safetybelt@=1.0.2\",\n    \"local-test:reload-safetybelt@=1.0.2\",\n    \"reload@=1.1.2\",\n    \"local-test:reload@=1.1.2\",\n    \"retry@=1.0.2\",\n    \"routepolicy@=1.0.3\",\n    \"local-test:routepolicy@=1.0.3\",\n    \"service-configuration@=1.0.3\",\n    \"session@=1.0.5\",\n    \"local-test:session@=1.0.5\",\n    \"sha@=1.0.2\",\n    \"showdown@=1.0.3\",\n    \"spacebars-compiler@=1.0.4\",\n    \"local-test:spacebars-compiler@=1.0.4\",\n    \"spacebars-tests@=1.0.2\",\n    \"local-test:spacebars-tests@=1.0.2\",\n    \"spacebars@=1.0.4\",\n    \"local-test:spacebars@=1.0.4\",\n    \"spiderable@=1.0.6\",\n    \"local-test:spiderable@=1.0.6\",\n    \"srp@=1.0.2\",\n    \"local-test:srp@=1.0.2\",\n    \"standard-app-packages@=1.0.4\",\n    \"star-translate@=1.0.5\",\n    \"startup@=1.0.2\",\n    \"stylus@=1.0.6\",\n    \"local-test:stylus@=1.0.6\",\n    \"templating@=1.0.10\",\n    \"local-test:templating@=1.0.10\",\n    \"test-helpers@=1.0.3\",\n    \"local-test:test-helpers@=1.0.3\",\n    \"test-in-browser@=1.0.6\",\n    \"test-in-console@=1.0.4\",\n    \"test-server-tests-in-console-once@=1.0.2\",\n    \"tinytest@=1.0.4\",\n    \"tracker@=1.0.4\",\n    \"local-test:tracker@=1.0.4\",\n    \"twitter@=1.1.3\",\n    \"ui@=1.0.5\",\n    \"underscore-tests@=1.0.2\",\n    \"local-test:underscore-tests@=1.0.2\",\n    \"underscore@=1.0.2\",\n    \"local-test:underscore@=1.0.2\",\n    \"url@=1.0.3\",\n    \"webapp-hashing@=1.0.2\",\n    \"local-test:webapp-hashing@=1.0.2\",\n    \"webapp@=1.1.5\",\n    \"local-test:webapp@=1.1.5\",\n    \"weibo@=1.1.2\",\n    \"xmlbuilder@=2.4.5\"\n  ],\n  \"catalogCache\": {\n    \"data\": {\n      \"xmlbuilder 2.4.5\": [\n        \"meteor\"\n      ],\n      \"weibo 1.1.2\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"local-test:webapp 1.1.5\": [\n        \"meteor\",\n        \"tinytest\",\n        \"webapp\",\n        \"http\"\n      ],\n      \"webapp 1.1.5\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"boilerplate-generator\",\n        \"spacebars\",\n        \"htmljs\",\n        \"blaze\",\n        \"webapp-hashing\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"local-test:webapp-hashing 1.0.2\": [\n        \"meteor\",\n        \"tinytest\",\n        \"webapp-hashing\"\n      ],\n      \"webapp-hashing 1.0.2\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"url 1.0.3\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"local-test:underscore 1.0.2\": [\n        \"meteor\"\n      ],\n      \"underscore 1.0.2\": [\n        \"meteor\"\n      ],\n      \"local-test:underscore-tests 1.0.2\": [\n        \"meteor\",\n        \"tinytest\",\n        \"underscore\"\n      ],\n      \"underscore-tests 1.0.2\": [\n        \"meteor\"\n      ],\n      \"ui 1.0.5\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"twitter 1.1.3\": [\n        \"meteor\",\n        \"http\",\n        \"oauth1\",\n        \"oauth\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"local-test:tracker 1.0.4\": [\n        \"meteor\",\n        \"tinytest\",\n        \"tracker\"\n      ],\n      \"tracker 1.0.4\": [\n        \"meteor\"\n      ],\n      \"tinytest 1.0.4\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"ddp\",\n        \"mongo\",\n        \"check\"\n      ],\n      \"test-server-tests-in-console-once 1.0.2\": [\n        \"meteor\",\n        \"tinytest\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"test-in-console 1.0.4\": [\n        \"meteor\",\n        \"tinytest\",\n        \"underscore\",\n        \"random\",\n        \"ejson\",\n        \"check\",\n        \"http\"\n      ],\n      \"test-in-browser 1.0.6\": [\n        \"meteor\",\n        \"tinytest\",\n        \"bootstrap@1.0.1\",\n        \"underscore\",\n        \"session\",\n        \"reload\",\n        \"?autoupdate\",\n        \"random\",\n        \"blaze\",\n        \"templating\",\n        \"spacebars\",\n        \"ddp\",\n        \"tracker\"\n      ],\n      \"bootstrap 1.0.0\": [\n        \"jquery@1.0.0\",\n        \"meteor@1.0.2\"\n      ],\n      \"bootstrap 1.0.1-rc0\": [\n        \"meteor\",\n        \"jquery\"\n      ],\n      \"bootstrap 1.0.1\": [\n        \"jquery@1.0.0\",\n        \"meteor@1.0.3\"\n      ],\n      \"local-test:test-helpers 1.0.3\": [\n        \"meteor\",\n        \"tinytest\",\n        \"test-helpers\",\n        \"underscore\"\n      ],\n      \"test-helpers 1.0.3\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"tinytest\",\n        \"random\",\n        \"ddp\",\n        \"jquery\"\n      ],\n      \"local-test:templating 1.0.10\": [\n        \"meteor\",\n        \"tinytest\",\n        \"htmljs\",\n        \"templating\",\n        \"underscore\",\n        \"spacebars-compiler\",\n        \"test-helpers\",\n        \"session\",\n        \"tracker\",\n        \"minimongo\"\n      ],\n      \"templating 1.0.10\": [\n        \"meteor\",\n        \"underscore\",\n        \"blaze\",\n        \"spacebars-compiler\"\n      ],\n      \"local-test:stylus 1.0.6\": [\n        \"meteor\",\n        \"tinytest\",\n        \"stylus\",\n        \"test-helpers\",\n        \"templating\"\n      ],\n      \"stylus 1.0.6\": [\n        \"meteor\"\n      ],\n      \"startup 1.0.2\": [\n        \"meteor\"\n      ],\n      \"star-translate 1.0.5\": [\n        \"meteor\",\n        \"dev-bundle-fetcher\"\n      ],\n      \"standard-app-packages 1.0.4\": [\n        \"meteor\",\n        \"meteor-platform\"\n      ],\n      \"local-test:srp 1.0.2\": [\n        \"meteor\",\n        \"tinytest\",\n        \"srp\",\n        \"underscore\"\n      ],\n      \"srp 1.0.2\": [\n        \"meteor\",\n        \"random\",\n        \"check\",\n        \"sha\",\n        \"underscore\"\n      ],\n      \"local-test:spiderable 1.0.6\": [\n        \"meteor\",\n        \"spiderable\",\n        \"tinytest\"\n      ],\n      \"spiderable 1.0.6\": [\n        \"meteor\",\n        \"webapp\",\n        \"underscore\",\n        \"templating\"\n      ],\n      \"local-test:spacebars 1.0.4\": [\n        \"meteor\",\n        \"spacebars\",\n        \"tinytest\",\n        \"test-helpers\",\n        \"reactive-var\",\n        \"templating\"\n      ],\n      \"spacebars 1.0.4\": [\n        \"meteor\",\n        \"htmljs\",\n        \"blaze\",\n        \"observe-sequence\",\n        \"templating\"\n      ],\n      \"local-test:spacebars-tests 1.0.2\": [\n        \"meteor\",\n        \"underscore\",\n        \"spacebars\",\n        \"tinytest\",\n        \"jquery\",\n        \"test-helpers\",\n        \"reactive-var\",\n        \"showdown\",\n        \"minimongo\",\n        \"tracker\",\n        \"templating\"\n      ],\n      \"spacebars-tests 1.0.2\": [\n        \"meteor\"\n      ],\n      \"local-test:spacebars-compiler 1.0.4\": [\n        \"meteor\",\n        \"underscore\",\n        \"spacebars-compiler\",\n        \"tinytest\",\n        \"blaze-tools\",\n        \"coffeescript\"\n      ],\n      \"spacebars-compiler 1.0.4\": [\n        \"meteor\",\n        \"htmljs\",\n        \"html-tools\",\n        \"blaze-tools\",\n        \"underscore\",\n        \"minifiers\"\n      ],\n      \"showdown 1.0.3\": [\n        \"meteor\",\n        \"markdown\"\n      ],\n      \"sha 1.0.2\": [\n        \"meteor\"\n      ],\n      \"local-test:session 1.0.5\": [\n        \"meteor\",\n        \"tinytest\",\n        \"tracker\",\n        \"mongo\",\n        \"session\"\n      ],\n      \"session 1.0.5\": [\n        \"meteor\",\n        \"underscore\",\n        \"reactive-dict\",\n        \"ejson\",\n        \"?reload\"\n      ],\n      \"service-configuration 1.0.3\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"mongo\"\n      ],\n      \"local-test:routepolicy 1.0.3\": [\n        \"meteor\",\n        \"routepolicy\",\n        \"tinytest\"\n      ],\n      \"routepolicy 1.0.3\": [\n        \"meteor\",\n        \"underscore\",\n        \"webapp\"\n      ],\n      \"retry 1.0.2\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"local-test:reload 1.1.2\": [\n        \"meteor\",\n        \"tinytest\",\n        \"reload\"\n      ],\n      \"reload 1.1.2\": [\n        \"meteor\",\n        \"underscore\",\n        \"logging\",\n        \"json\"\n      ],\n      \"local-test:reload-safetybelt 1.0.2\": [\n        \"meteor\",\n        \"reload-safetybelt\",\n        \"tinytest\",\n        \"http\",\n        \"webapp\"\n      ],\n      \"reload-safetybelt 1.0.2\": [\n        \"meteor\",\n        \"webapp\"\n      ],\n      \"reactive-var 1.0.4\": [\n        \"meteor\",\n        \"tracker\"\n      ],\n      \"local-test:reactive-dict 1.0.5\": [\n        \"meteor\",\n        \"tinytest\"\n      ],\n      \"reactive-dict 1.0.5\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"?mongo\"\n      ],\n      \"local-test:random 1.0.2\": [\n        \"meteor\",\n        \"random\",\n        \"tinytest\"\n      ],\n      \"random 1.0.2\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"preserve-inputs 1.0.2\": [\n        \"meteor\"\n      ],\n      \"local-test:package-version-parser 3.0.0\": [\n        \"meteor\",\n        \"package-version-parser\",\n        \"tinytest\"\n      ],\n      \"package-version-parser 3.0.0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-stats-opt-out 1.0.2\": [\n        \"meteor\"\n      ],\n      \"ordered-dict 1.0.2\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"local-test:observe-sequence 1.0.4\": [\n        \"meteor\",\n        \"tinytest\",\n        \"observe-sequence\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"observe-sequence 1.0.4\": [\n        \"meteor\",\n        \"tracker\",\n        \"minimongo\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"local-test:oauth2 1.1.2\": [\n        \"meteor\",\n        \"tinytest\",\n        \"random\",\n        \"oauth2\",\n        \"oauth\",\n        \"service-configuration\",\n        \"oauth-encryption\"\n      ],\n      \"oauth2 1.1.2\": [\n        \"meteor\",\n        \"service-configuration\",\n        \"oauth\"\n      ],\n      \"local-test:oauth1 1.1.3\": [\n        \"meteor\",\n        \"tinytest\",\n        \"random\",\n        \"service-configuration\",\n        \"oauth-encryption\",\n        \"oauth1\",\n        \"oauth\"\n      ],\n      \"oauth1 1.1.3\": [\n        \"meteor\",\n        \"random\",\n        \"service-configuration\",\n        \"oauth\",\n        \"underscore\",\n        \"http\",\n        \"mongo\"\n      ],\n      \"local-test:oauth 1.1.3\": [\n        \"meteor\",\n        \"tinytest\",\n        \"random\",\n        \"service-configuration\",\n        \"oauth\"\n      ],\n      \"oauth 1.1.3\": [\n        \"meteor\",\n        \"routepolicy\",\n        \"webapp\",\n        \"mongo\",\n        \"underscore\",\n        \"service-configuration\",\n        \"logging\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"url\",\n        \"reload\",\n        \"base64\"\n      ],\n      \"local-test:oauth-encryption 1.0.2\": [\n        \"meteor\",\n        \"tinytest\",\n        \"oauth-encryption\"\n      ],\n      \"oauth-encryption 1.0.2\": [\n        \"meteor\",\n        \"npm-node-aes-gcm@=0.1.3\",\n        \"underscore\"\n      ],\n      \"npm-node-aes-gcm 0.1.3-win.0\": [\n        \"meteor\"\n      ],\n      \"npm-node-aes-gcm 0.1.3\": [\n        \"meteor\"\n      ],\n      \"local-test:mongo 1.0.11\": [\n        \"meteor\",\n        \"mongo\",\n        \"check\",\n        \"tinytest\",\n        \"underscore\",\n        \"test-helpers\",\n        \"ejson\",\n        \"random\",\n        \"ddp\",\n        \"base64\"\n      ],\n      \"mongo 1.0.11\": [\n        \"meteor\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"minimongo\",\n        \"logging\",\n        \"ddp\",\n        \"tracker\",\n        \"application-configuration\",\n        \"check\",\n        \"binary-heap\",\n        \"?insecure\",\n        \"?autopublish\",\n        \"?disable-oplog\",\n        \"?webapp\",\n        \"?facts\",\n        \"callback-hook\"\n      ],\n      \"mongo-livedata 1.0.7\": [\n        \"meteor\",\n        \"mongo\"\n      ],\n      \"mobile-status-bar 1.0.2\": [\n        \"meteor\"\n      ],\n      \"local-test:minimongo 1.0.6\": [\n        \"meteor\",\n        \"minimongo\",\n        \"tinytest\",\n        \"underscore\",\n        \"ejson\",\n        \"ordered-dict\",\n        \"random\",\n        \"tracker\",\n        \"reactive-var\",\n        \"test-helpers\"\n      ],\n      \"minimongo 1.0.6\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\",\n        \"id-map\",\n        \"ordered-dict\",\n        \"tracker\",\n        \"random\",\n        \"geojson-utils\"\n      ],\n      \"local-test:minifiers 1.1.3\": [\n        \"meteor\",\n        \"minifiers\",\n        \"tinytest\"\n      ],\n      \"minifiers 1.1.3\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"meyerweb-reset 1.0.2\": [\n        \"meteor\"\n      ],\n      \"local-test:meteor 1.1.4\": [\n        \"meteor\",\n        \"underscore\",\n        \"tinytest\",\n        \"test-helpers\"\n      ],\n      \"meteor 1.1.4\": [\n        \"underscore\"\n      ],\n      \"meteor-tool 1.0.38\": [\n        \"meteor\"\n      ],\n      \"meteor-developer 1.1.2\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"meetup 1.1.2\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"local-test:markdown 1.0.3\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"markdown 1.0.3\": [\n        \"meteor\",\n        \"?templating\"\n      ],\n      \"local-test:logging 1.0.6\": [\n        \"meteor\",\n        \"tinytest\",\n        \"underscore\",\n        \"ejson\",\n        \"logging\"\n      ],\n      \"logging 1.0.6\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"local-test:localstorage 1.0.2\": [\n        \"meteor\",\n        \"tinytest\",\n        \"localstorage\"\n      ],\n      \"localstorage 1.0.2\": [\n        \"meteor\",\n        \"random\"\n      ],\n      \"livedata 1.0.12\": [\n        \"meteor\",\n        \"ddp\"\n      ],\n      \"local-test:less 1.0.12\": [\n        \"meteor\",\n        \"test-helpers\",\n        \"tinytest\",\n        \"less\",\n        \"templating\"\n      ],\n      \"less 1.0.12\": [\n        \"meteor\"\n      ],\n      \"launch-screen 1.0.1\": [\n        \"meteor\",\n        \"?blaze\",\n        \"?templating\"\n      ],\n      \"local-test:jsparse 1.0.2\": [\n        \"meteor\",\n        \"tinytest\",\n        \"underscore\",\n        \"jsparse\"\n      ],\n      \"jsparse 1.0.2\": [\n        \"meteor\"\n      ],\n      \"json 1.0.2\": [\n        \"meteor\"\n      ],\n      \"js-analyze 1.0.4\": [],\n      \"local-test:js-analyze-tests 1.0.2\": [\n        \"meteor\",\n        \"tinytest\",\n        \"js-analyze\"\n      ],\n      \"js-analyze-tests 1.0.2\": [\n        \"meteor\"\n      ],\n      \"jquery 1.11.2\": [\n        \"meteor\"\n      ],\n      \"jquery-waypoints 1.0.2\": [\n        \"meteor\",\n        \"jquery\",\n        \"coffeescript\"\n      ],\n      \"id-map 1.0.2\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\"\n      ],\n      \"local-test:http 1.0.9\": [\n        \"meteor\",\n        \"webapp\",\n        \"underscore\",\n        \"random\",\n        \"http\",\n        \"test-helpers\",\n        \"jquery\"\n      ],\n      \"http 1.0.9\": [\n        \"meteor\",\n        \"underscore\",\n        \"url\"\n      ],\n      \"local-test:htmljs 1.0.3\": [\n        \"meteor\",\n        \"htmljs\",\n        \"html-tools\",\n        \"tinytest\",\n        \"underscore\"\n      ],\n      \"htmljs 1.0.3\": [\n        \"meteor\",\n        \"deps\"\n      ],\n      \"local-test:html-tools 1.0.3\": [\n        \"meteor\",\n        \"tinytest\",\n        \"html-tools\",\n        \"underscore\",\n        \"htmljs\",\n        \"blaze-tools\"\n      ],\n      \"html-tools 1.0.3\": [\n        \"meteor\",\n        \"htmljs\"\n      ],\n      \"handlebars 1.0.2\": [\n        \"meteor\"\n      ],\n      \"google 1.1.3\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"github 1.1.2\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"random\"\n      ],\n      \"local-test:geojson-utils 1.0.2\": [\n        \"meteor\",\n        \"tinytest\",\n        \"geojson-utils\"\n      ],\n      \"geojson-utils 1.0.2\": [\n        \"meteor\"\n      ],\n      \"force-ssl 1.0.3\": [\n        \"meteor\",\n        \"webapp\",\n        \"underscore\",\n        \"ddp\"\n      ],\n      \"follower-livedata 1.0.3\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"ddp\",\n        \"ejson\"\n      ],\n      \"fastclick 1.0.2\": [\n        \"meteor\"\n      ],\n      \"facts 1.0.3\": [\n        \"meteor\",\n        \"underscore\",\n        \"?autopublish\",\n        \"ddp\",\n        \"templating\",\n        \"mongo\"\n      ],\n      \"facebook 1.1.3\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"local-test:email 1.0.5\": [\n        \"meteor\",\n        \"email\",\n        \"tinytest\"\n      ],\n      \"email 1.0.5\": [\n        \"meteor\",\n        \"underscore\",\n        \"application-configuration\"\n      ],\n      \"local-test:ejson 1.0.5\": [\n        \"meteor\",\n        \"ejson\",\n        \"tinytest\",\n        \"underscore\"\n      ],\n      \"ejson 1.0.5\": [\n        \"meteor\",\n        \"json\",\n        \"underscore\",\n        \"base64\"\n      ],\n      \"disable-oplog 1.0.2\": [\n        \"meteor\"\n      ],\n      \"dev-bundle-fetcher 1.0.2\": [\n        \"meteor\"\n      ],\n      \"deps 1.0.6\": [\n        \"meteor\",\n        \"tracker\"\n      ],\n      \"local-test:ddp 1.0.13\": [\n        \"meteor\",\n        \"livedata\",\n        \"mongo\",\n        \"test-helpers\",\n        \"underscore\",\n        \"tinytest\",\n        \"random\",\n        \"tracker\",\n        \"minimongo\",\n        \"reactive-var\",\n        \"check\",\n        \"http\"\n      ],\n      \"ddp 1.0.13\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"tracker\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"ctl 1.0.3\": [\n        \"meteor\",\n        \"underscore\",\n        \"ddp\",\n        \"mongo\",\n        \"ctl-helper\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"ctl-helper 1.0.5\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"ddp\",\n        \"mongo\",\n        \"follower-livedata\",\n        \"application-configuration\"\n      ],\n      \"local-test:constraint-solver 1.0.16\": [\n        \"meteor\",\n        \"constraint-solver\",\n        \"tinytest\",\n        \"minimongo\",\n        \"package-version-parser\",\n        \"underscore\"\n      ],\n      \"constraint-solver 1.0.16\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"local-test:coffeescript 1.0.5\": [\n        \"meteor\",\n        \"coffeescript\",\n        \"tinytest\",\n        \"coffeescript-test-helper\"\n      ],\n      \"coffeescript 1.0.5\": [\n        \"meteor\"\n      ],\n      \"coffeescript-test-helper 1.0.2\": [\n        \"meteor\",\n        \"coffeescript\"\n      ],\n      \"code-prettify 1.0.2\": [\n        \"meteor\"\n      ],\n      \"local-test:check 1.0.3\": [\n        \"meteor\",\n        \"check\",\n        \"tinytest\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"check 1.0.3\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"callback-hook 1.0.2\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"local-test:browser-policy 1.0.3\": [\n        \"meteor\",\n        \"tinytest\",\n        \"browser-policy\",\n        \"ejson\"\n      ],\n      \"browser-policy 1.0.3\": [\n        \"meteor\",\n        \"browser-policy-content\",\n        \"browser-policy-framing\",\n        \"browser-policy-common\"\n      ],\n      \"browser-policy-framing 1.0.3\": [\n        \"meteor\",\n        \"underscore\",\n        \"browser-policy-common\"\n      ],\n      \"browser-policy-content 1.0.3\": [\n        \"meteor\",\n        \"underscore\",\n        \"browser-policy-common\",\n        \"webapp\"\n      ],\n      \"browser-policy-common 1.0.2\": [\n        \"meteor\",\n        \"webapp\"\n      ],\n      \"boilerplate-generator 1.0.2\": [\n        \"meteor\",\n        \"underscore\",\n        \"spacebars-compiler\",\n        \"spacebars\",\n        \"htmljs\",\n        \"ui\"\n      ],\n      \"local-test:blaze 2.0.4\": [\n        \"meteor\",\n        \"tinytest\",\n        \"jquery\",\n        \"blaze\",\n        \"test-helpers\",\n        \"underscore\",\n        \"blaze-tools\",\n        \"html-tools\",\n        \"reactive-var\"\n      ],\n      \"blaze 2.0.4\": [\n        \"meteor\",\n        \"jquery\",\n        \"tracker\",\n        \"underscore\",\n        \"htmljs\",\n        \"observe-sequence\",\n        \"reactive-var\"\n      ],\n      \"local-test:blaze-tools 1.0.2\": [\n        \"meteor\",\n        \"blaze-tools\",\n        \"tinytest\",\n        \"underscore\",\n        \"html-tools\"\n      ],\n      \"blaze-tools 1.0.2\": [\n        \"meteor\",\n        \"htmljs\",\n        \"underscore\"\n      ],\n      \"local-test:binary-heap 1.0.2\": [\n        \"meteor\",\n        \"tinytest\",\n        \"binary-heap\"\n      ],\n      \"binary-heap 1.0.2\": [\n        \"meteor\",\n        \"underscore\",\n        \"id-map\"\n      ],\n      \"local-test:base64 1.0.2\": [\n        \"meteor\",\n        \"base64\",\n        \"tinytest\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"base64 1.0.2\": [\n        \"meteor\"\n      ],\n      \"autoupdate 1.1.4\": [\n        \"meteor\",\n        \"webapp\",\n        \"ddp\",\n        \"mongo\",\n        \"underscore\",\n        \"tracker\",\n        \"retry\",\n        \"?reload\",\n        \"http\",\n        \"random\"\n      ],\n      \"audit-argument-checks 1.0.2\": [\n        \"meteor\"\n      ],\n      \"application-configuration 1.0.4\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"ddp\",\n        \"ejson\",\n        \"follower-livedata\",\n        \"mongo\"\n      ],\n      \"local-test:appcache 1.0.3\": [\n        \"meteor\",\n        \"tinytest\",\n        \"appcache\",\n        \"webapp\",\n        \"http\",\n        \"underscore\"\n      ],\n      \"appcache 1.0.3\": [\n        \"meteor\",\n        \"webapp\",\n        \"routepolicy\",\n        \"underscore\",\n        \"?autoupdate\",\n        \"reload\"\n      ],\n      \"accounts-weibo 1.0.3\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"weibo\"\n      ],\n      \"accounts-ui 1.1.4\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-ui-unstyled\",\n        \"less\"\n      ],\n      \"local-test:accounts-ui-unstyled 1.1.5\": [\n        \"meteor\",\n        \"accounts-ui-unstyled\",\n        \"tinytest\"\n      ],\n      \"accounts-ui-unstyled 1.1.5\": [\n        \"meteor\",\n        \"?accounts-oauth\",\n        \"?accounts-password\",\n        \"accounts-base\",\n        \"tracker\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"session\"\n      ],\n      \"accounts-twitter 1.0.3\": [\n        \"meteor\",\n        \"underscore\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"twitter\",\n        \"http\"\n      ],\n      \"local-test:accounts-password 1.0.5\": [\n        \"meteor\",\n        \"accounts-password\",\n        \"tinytest\",\n        \"test-helpers\",\n        \"tracker\",\n        \"accounts-base\",\n        \"random\",\n        \"email\",\n        \"underscore\",\n        \"check\",\n        \"ddp\"\n      ],\n      \"accounts-password 1.0.5\": [\n        \"meteor\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base\",\n        \"srp\",\n        \"sha\",\n        \"email\",\n        \"random\",\n        \"check\",\n        \"underscore\",\n        \"ddp\"\n      ],\n      \"npm-bcrypt 0.7.7\": [\n        \"meteor\"\n      ],\n      \"npm-bcrypt 0.7.8-win.0\": [\n        \"meteor\"\n      ],\n      \"local-test:accounts-oauth 1.1.3\": [\n        \"meteor\"\n      ],\n      \"accounts-oauth 1.1.3\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"check\",\n        \"webapp\",\n        \"accounts-base\",\n        \"oauth\"\n      ],\n      \"accounts-meteor-developer 1.0.3\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"meteor-developer\"\n      ],\n      \"accounts-meetup 1.0.3\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"meetup\"\n      ],\n      \"accounts-google 1.0.3\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"google\"\n      ],\n      \"accounts-github 1.0.3\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"github\"\n      ],\n      \"accounts-facebook 1.0.3\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"facebook\"\n      ],\n      \"local-test:accounts-base 1.1.3\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"tinytest\",\n        \"random\",\n        \"test-helpers\",\n        \"oauth-encryption\"\n      ],\n      \"accounts-base 1.1.3\": [\n        \"meteor\",\n        \"underscore\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"callback-hook\",\n        \"service-configuration\",\n        \"ddp\",\n        \"mongo\",\n        \"?autopublish\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"tracker\",\n        \"?blaze\"\n      ],\n      \"gfk:notifications 1.0.0\": [\n        \"meteor\",\n        \"templating@1.0.0\",\n        \"underscore@1.0.0\",\n        \"less@1.0.0\"\n      ],\n      \"gfk:notifications 1.0.1\": [\n        \"meteor\",\n        \"templating@1.0.0\",\n        \"underscore@1.0.0\",\n        \"less@1.0.0\"\n      ],\n      \"gfk:notifications 1.0.2-v1.0.2\": [\n        \"meteor\",\n        \"templating@1.0.0\",\n        \"underscore@1.0.0\",\n        \"less@1.0.0\"\n      ],\n      \"gfk:notifications 1.0.3-v1.0.3\": [\n        \"meteor\",\n        \"templating@1.0.0\",\n        \"underscore@1.0.0\",\n        \"less@1.0.0\"\n      ],\n      \"gfk:notifications 1.0.4-v1.0.4\": [\n        \"meteor\",\n        \"templating@1.0.0\",\n        \"underscore@1.0.0\",\n        \"less@1.0.0\"\n      ],\n      \"gfk:notifications 1.0.5-v1.0.5\": [\n        \"meteor\",\n        \"templating@1.0.0\",\n        \"underscore@1.0.0\",\n        \"less@1.0.0\"\n      ],\n      \"gfk:notifications 1.0.6\": [\n        \"meteor\",\n        \"templating@1.0.4\",\n        \"underscore@1.0.0\",\n        \"less@1.0.5\",\n        \"mongo@1.0.4\"\n      ],\n      \"gfk:notifications 1.0.7\": [\n        \"meteor\",\n        \"templating@1.0.5\",\n        \"underscore@1.0.0\",\n        \"less@1.0.7\",\n        \"mongo@1.0.4\"\n      ],\n      \"gfk:notifications 1.0.8\": [\n        \"meteor\",\n        \"templating@1.0.5\",\n        \"underscore@1.0.0\",\n        \"less@1.0.7\",\n        \"mongo@1.0.4\"\n      ],\n      \"gfk:notifications 1.0.9\": [\n        \"meteor\",\n        \"templating@1.0.4\",\n        \"underscore@1.0.0\",\n        \"less@1.0.5\",\n        \"mongo@1.0.4\"\n      ],\n      \"gfk:notifications 1.0.11\": [\n        \"meteor\",\n        \"templating@1.0.8\",\n        \"underscore@1.0.1\",\n        \"less@1.0.10\",\n        \"mongo@1.0.4\"\n      ],\n      \"gfk:notifications 1.1.0\": [\n        \"meteor\",\n        \"templating@1.0.9\",\n        \"underscore@1.0.1\",\n        \"less@1.0.11\",\n        \"mongo@1.0.4\"\n      ],\n      \"gfk:notifications 1.1.1\": [\n        \"meteor\",\n        \"templating@1.0.9\",\n        \"underscore@1.0.1\",\n        \"less@1.0.11\",\n        \"mongo@1.0.4\"\n      ],\n      \"u2622:persistent-session 0.1.0\": [\n        \"meteor\",\n        \"amplify@1.0.0\",\n        \"session@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"u2622:persistent-session 0.1.1\": [\n        \"meteor\",\n        \"amplify@1.0.0\",\n        \"session@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"u2622:persistent-session 0.1.2\": [\n        \"meteor\",\n        \"amplify@1.0.0\",\n        \"session@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"u2622:persistent-session 0.1.3\": [\n        \"meteor\",\n        \"jquery@1.0.0\",\n        \"amplify@1.0.0\",\n        \"session@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"u2622:persistent-session 0.1.4\": [\n        \"meteor\",\n        \"jquery@1.0.0\",\n        \"amplify@1.0.0\",\n        \"session@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"u2622:persistent-session 0.2.0\": [\n        \"meteor\",\n        \"jquery@1.0.0\",\n        \"amplify@1.0.0\",\n        \"session@1.0.1\",\n        \"underscore@1.0.0\"\n      ],\n      \"u2622:persistent-session 0.2.1\": [\n        \"meteor\",\n        \"jquery@1.0.0\",\n        \"amplify@1.0.0\",\n        \"session@1.0.1\",\n        \"underscore@1.0.0\"\n      ],\n      \"amplify 1.0.0\": [\n        \"jquery@1.0.0\",\n        \"meteor@1.0.2\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.1\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.2\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.3\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.4\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.20\": [\n        \"meteor\",\n        \"service-configuration@1.0.0\",\n        \"accounts-password@1.0.0\",\n        \"accounts-base@1.0.0\",\n        \"splendido:accounts-templates-core@0.0.20\",\n        \"templating@1.0.4\",\n        \"less@1.0.5\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.21\": [\n        \"meteor\",\n        \"service-configuration@1.0.0\",\n        \"accounts-password@1.0.0\",\n        \"accounts-base@1.0.0\",\n        \"splendido:accounts-templates-core@0.0.21\",\n        \"templating@1.0.4\",\n        \"less@1.0.5\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.24\": [\n        \"meteor\",\n        \"service-configuration@1.0.0\",\n        \"accounts-password@1.0.0\",\n        \"accounts-base@1.0.0\",\n        \"splendido:accounts-templates-core@0.0.24\",\n        \"templating@1.0.4\",\n        \"less@1.0.5\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.25\": [\n        \"meteor\",\n        \"service-configuration@1.0.0\",\n        \"accounts-password@1.0.0\",\n        \"accounts-base@1.0.0\",\n        \"splendido:accounts-templates-core@0.0.25\",\n        \"templating@1.0.4\",\n        \"less@1.0.5\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.26\": [\n        \"meteor\",\n        \"service-configuration@1.0.0\",\n        \"accounts-password@1.0.0\",\n        \"accounts-base@1.0.0\",\n        \"splendido:accounts-templates-core@0.0.26\",\n        \"templating@1.0.4\",\n        \"less@1.0.5\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.27\": [\n        \"meteor\",\n        \"service-configuration@1.0.0\",\n        \"accounts-password@1.0.0\",\n        \"accounts-base@1.0.0\",\n        \"splendido:accounts-templates-core@0.0.27\",\n        \"templating@1.0.4\",\n        \"less@1.0.5\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.28-1\": [\n        \"meteor\",\n        \"service-configuration@1.0.0\",\n        \"accounts-password@1.0.0\",\n        \"accounts-base@1.0.0\",\n        \"splendido:accounts-templates-core@0.0.28\",\n        \"templating@1.0.4\",\n        \"less@1.0.5\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.28\": [\n        \"meteor\",\n        \"service-configuration@1.0.0\",\n        \"accounts-password@1.0.0\",\n        \"accounts-base@1.0.0\",\n        \"splendido:accounts-templates-core@0.0.28\",\n        \"templating@1.0.4\",\n        \"less@1.0.5\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.29\": [\n        \"meteor\",\n        \"service-configuration@1.0.0\",\n        \"accounts-password@1.0.0\",\n        \"accounts-base@1.0.0\",\n        \"splendido:accounts-templates-core@0.0.28\",\n        \"templating@1.0.4\",\n        \"less@1.0.5\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.0.30\": [\n        \"meteor\",\n        \"service-configuration@1.0.0\",\n        \"accounts-password@1.0.0\",\n        \"accounts-base@1.0.0\",\n        \"splendido:accounts-templates-core@0.0.28\",\n        \"templating@1.0.4\",\n        \"less@1.0.5\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.4\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.4\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.5\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.5\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.6\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.6\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.7\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.7\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.8\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.8\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.9\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.9\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.10\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.10\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.11\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.11\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.12\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.12\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.13\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.13\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.14\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.14\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.15\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.15\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.16-iron-v1.1\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.16-iron-v1.1\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.9.16\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.9.16\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.10.0\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.10.0\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-semantic-ui 0.11.0\": [\n        \"meteor\",\n        \"splendido:accounts-templates-core@0.11.0\",\n        \"less@1.0.8\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.0.1\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-core 0.0.2\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-core 0.0.3\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-core 0.0.4\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-core 0.0.5\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-core 0.0.6\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-core 0.0.7\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-core 0.0.8\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-core 0.0.9\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-core 0.0.10\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-core 0.0.11\": [\n        \"meteor\"\n      ],\n      \"splendido:accounts-templates-core 0.0.20\": [\n        \"meteor\",\n        \"check@1.0.0\",\n        \"deps@1.0.1\",\n        \"accounts-base@1.0.0\",\n        \"mrt:accounts-t9n@0.0.13\",\n        \"iron:router@0.9.1\",\n        \"underscore@1.0.0\",\n        \"minimongo@1.0.1\",\n        \"mongo-livedata@1.0.3\",\n        \"sha@1.0.0\",\n        \"templating@1.0.4\"\n      ],\n      \"splendido:accounts-templates-core 0.0.21\": [\n        \"meteor\",\n        \"check@1.0.0\",\n        \"deps@1.0.1\",\n        \"accounts-base@1.0.0\",\n        \"mrt:accounts-t9n@0.0.13\",\n        \"iron:router@0.9.1\",\n        \"underscore@1.0.0\",\n        \"minimongo@1.0.1\",\n        \"mongo-livedata@1.0.3\",\n        \"sha@1.0.0\",\n        \"templating@1.0.4\"\n      ],\n      \"splendido:accounts-templates-core 0.0.22\": [\n        \"meteor\",\n        \"check@1.0.0\",\n        \"deps@1.0.1\",\n        \"accounts-base@1.0.0\",\n        \"mrt:accounts-t9n@0.0.13\",\n        \"iron:router@0.9.1\",\n        \"underscore@1.0.0\",\n        \"minimongo@1.0.1\",\n        \"mongo-livedata@1.0.3\",\n        \"sha@1.0.0\",\n        \"templating@1.0.4\"\n      ],\n      \"splendido:accounts-templates-core 0.0.23\": [\n        \"meteor\",\n        \"check@1.0.0\",\n        \"deps@1.0.1\",\n        \"accounts-base@1.0.0\",\n        \"mrt:accounts-t9n@0.0.13\",\n        \"iron:router@0.9.1\",\n        \"underscore@1.0.0\",\n        \"minimongo@1.0.1\",\n        \"mongo-livedata@1.0.3\",\n        \"sha@1.0.0\",\n        \"templating@1.0.4\"\n      ],\n      \"splendido:accounts-templates-core 0.0.24\": [\n        \"meteor\",\n        \"mrt:accounts-t9n@0.0.13\",\n        \"iron:router@0.9.1\",\n        \"check@1.0.0\",\n        \"deps@1.0.1\",\n        \"accounts-base@1.0.0\",\n        \"underscore@1.0.0\",\n        \"minimongo@1.0.1\",\n        \"mongo-livedata@1.0.3\",\n        \"sha@1.0.0\",\n        \"templating@1.0.4\"\n      ],\n      \"splendido:accounts-templates-core 0.0.25\": [\n        \"meteor\",\n        \"mrt:accounts-t9n@0.0.13\",\n        \"iron:router@0.9.1\",\n        \"check@1.0.0\",\n        \"deps@1.0.1\",\n        \"accounts-base@1.0.0\",\n        \"underscore@1.0.0\",\n        \"minimongo@1.0.1\",\n        \"mongo-livedata@1.0.3\",\n        \"sha@1.0.0\",\n        \"templating@1.0.4\"\n      ],\n      \"splendido:accounts-templates-core 0.0.26\": [\n        \"meteor\",\n        \"softwarerero:accounts-t9n@0.0.17\",\n        \"iron:router@0.9.3\",\n        \"check@1.0.0\",\n        \"deps@1.0.1\",\n        \"accounts-base@1.0.0\",\n        \"underscore@1.0.0\",\n        \"minimongo@1.0.1\",\n        \"mongo-livedata@1.0.3\",\n        \"sha@1.0.0\",\n        \"templating@1.0.4\"\n      ],\n      \"splendido:accounts-templates-core 0.0.27\": [\n        \"meteor\",\n        \"softwarerero:accounts-t9n@0.0.17\",\n        \"iron:router@0.9.3\",\n        \"check@1.0.0\",\n        \"deps@1.0.1\",\n        \"accounts-base@1.0.0\",\n        \"underscore@1.0.0\",\n        \"minimongo@1.0.1\",\n        \"mongo-livedata@1.0.3\",\n        \"sha@1.0.0\",\n        \"templating@1.0.4\"\n      ],\n      \"splendido:accounts-templates-core 0.0.28\": [\n        \"meteor\",\n        \"softwarerero:accounts-t9n@0.0.17\",\n        \"iron:router@0.9.3\",\n        \"check@1.0.0\",\n        \"deps@1.0.1\",\n        \"accounts-base@1.0.0\",\n        \"underscore@1.0.0\",\n        \"minimongo@1.0.1\",\n        \"mongo-livedata@1.0.3\",\n        \"sha@1.0.0\",\n        \"templating@1.0.4\"\n      ],\n      \"splendido:accounts-templates-core 0.9.0\": [\n        \"meteor\",\n        \"check@1.0.0\",\n        \"accounts-base@1.0.1\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@0.0.20\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.1\",\n        \"sha@1.0.0\",\n        \"templating@1.0.5\"\n      ],\n      \"splendido:accounts-templates-core 0.9.1\": [\n        \"meteor\",\n        \"check@1.0.0\",\n        \"accounts-base@1.0.1\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@0.0.20\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.1\",\n        \"sha@1.0.0\",\n        \"templating@1.0.5\"\n      ],\n      \"splendido:accounts-templates-core 0.9.2\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"softwarerero:accounts-t9n@0.0.20\",\n        \"iron:router@0.9.3\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.3\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@0.0.20\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.4\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@0.0.20\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.5\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.6\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.7\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.8\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.9\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.10\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.11\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.12\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.13\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.14\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.15\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.3\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.16-iron-v1.1\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@1.0.0-pre4\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.9.16\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.4\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.10.0\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.4\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"splendido:accounts-templates-core 0.11.0\": [\n        \"meteor\",\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:router@0.9.4\",\n        \"softwarerero:accounts-t9n@1.0.0\",\n        \"blaze@2.0.0\",\n        \"reactive-dict@1.0.2\",\n        \"sha@1.0.0\",\n        \"templating@1.0.6\"\n      ],\n      \"softwarerero:accounts-t9n 0.0.17\": [\n        \"meteor\",\n        \"coffeescript@1.0.2\",\n        \"deps@1.0.1\"\n      ],\n      \"softwarerero:accounts-t9n 0.0.18\": [\n        \"meteor\",\n        \"coffeescript@1.0.2\",\n        \"deps@1.0.1\"\n      ],\n      \"softwarerero:accounts-t9n 0.0.19\": [\n        \"meteor\",\n        \"coffeescript@1.0.2\",\n        \"deps@1.0.1\"\n      ],\n      \"softwarerero:accounts-t9n 0.0.20\": [\n        \"meteor\",\n        \"coffeescript@1.0.2\",\n        \"deps@1.0.1\"\n      ],\n      \"softwarerero:accounts-t9n 1.0.0\": [\n        \"meteor\",\n        \"coffeescript@1.0.2\",\n        \"deps@1.0.1\"\n      ],\n      \"softwarerero:accounts-t9n 1.0.1\": [\n        \"meteor\",\n        \"coffeescript@1.0.2\",\n        \"deps@1.0.1\"\n      ],\n      \"softwarerero:accounts-t9n 1.0.2\": [\n        \"meteor\",\n        \"coffeescript@1.0.2\",\n        \"deps@1.0.1\"\n      ],\n      \"softwarerero:accounts-t9n 1.0.3\": [\n        \"meteor\",\n        \"coffeescript@1.0.2\",\n        \"deps@1.0.1\"\n      ],\n      \"softwarerero:accounts-t9n 1.0.4\": [\n        \"meteor\",\n        \"coffeescript@1.0.2\",\n        \"deps@1.0.1\"\n      ],\n      \"softwarerero:accounts-t9n 1.0.5\": [\n        \"meteor\",\n        \"coffeescript@1.0.2\",\n        \"deps@1.0.1\"\n      ],\n      \"mrt:accounts-t9n 0.0.1\": [\n        \"meteor\",\n        \"coffeescript@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\",\n        \"mrt:just-i18n@0.3.0\"\n      ],\n      \"mrt:accounts-t9n 0.0.2\": [\n        \"meteor\",\n        \"coffeescript@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\",\n        \"mrt:just-i18n@0.3.0\"\n      ],\n      \"mrt:accounts-t9n 0.0.3\": [\n        \"meteor\",\n        \"coffeescript@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:accounts-t9n 0.0.4\": [\n        \"meteor\",\n        \"coffeescript@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:accounts-t9n 0.0.7\": [\n        \"meteor\",\n        \"coffeescript@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:accounts-t9n 0.0.10\": [\n        \"meteor\",\n        \"coffeescript@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:accounts-t9n 0.0.11\": [\n        \"meteor\",\n        \"coffeescript@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:accounts-t9n 0.0.12\": [\n        \"meteor\",\n        \"coffeescript@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:accounts-t9n 0.0.13\": [\n        \"meteor\",\n        \"coffeescript@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:just-i18n 0.1.0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:just-i18n 0.1.1\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:just-i18n 0.2.0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:just-i18n 0.2.1\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:just-i18n 0.2.2\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:just-i18n 0.2.3\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:just-i18n 0.2.4\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mrt:just-i18n 0.3.0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"skinnygeek1010:parse-form 0.1.0\": [\n        \"meteor\",\n        \"jquery@1.0.0\"\n      ],\n      \"skinnygeek1010:parse-form 0.2.0\": [\n        \"meteor\",\n        \"jquery@1.0.0\"\n      ],\n      \"skinnygeek1010:parse-form 0.2.1\": [\n        \"meteor\",\n        \"jquery@1.0.0\"\n      ],\n      \"mrt:moment 1.7.0\": [\n        \"meteor\"\n      ],\n      \"mrt:moment 2.2.1\": [\n        \"meteor\"\n      ],\n      \"mrt:moment 2.5.1\": [\n        \"meteor\"\n      ],\n      \"mrt:moment 2.6.0\": [\n        \"meteor\"\n      ],\n      \"mrt:moment 2.8.1\": [\n        \"meteor\"\n      ],\n      \"mrt:jquery-ui-sortable 1.10.3\": [\n        \"meteor\",\n        \"jquery@1.0.0\"\n      ],\n      \"mizzao:timesync 0.1.0\": [\n        \"meteor\",\n        \"coffeescript@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mizzao:timesync 0.1.1\": [\n        \"meteor\",\n        \"coffeescript@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mizzao:timesync 0.1.2\": [\n        \"meteor\",\n        \"coffeescript@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mizzao:timesync 0.1.3\": [\n        \"meteor\",\n        \"coffeescript@1.0.0\",\n        \"deps@1.0.0\"\n      ],\n      \"mizzao:timesync 0.1.4\": [\n        \"meteor\",\n        \"webapp@1.0.0\",\n        \"deps@1.0.0\",\n        \"http@1.0.0\"\n      ],\n      \"mizzao:timesync 0.1.5\": [\n        \"meteor\",\n        \"webapp@1.0.0\",\n        \"deps@1.0.0\",\n        \"http@1.0.0\"\n      ],\n      \"mizzao:timesync 0.1.6\": [\n        \"meteor\",\n        \"webapp@1.0.0\",\n        \"deps@1.0.0\",\n        \"http@1.0.0\"\n      ],\n      \"mizzao:timesync 0.2.0\": [\n        \"meteor\",\n        \"webapp@1.0.0\",\n        \"deps@1.0.0\",\n        \"http@1.0.0\"\n      ],\n      \"mizzao:timesync 0.2.1\": [\n        \"meteor\",\n        \"webapp@1.0.0\",\n        \"deps@1.0.0\",\n        \"http@1.0.0\"\n      ],\n      \"mizzao:timesync 0.2.2\": [\n        \"meteor\",\n        \"webapp@1.0.0\",\n        \"deps@1.0.0\",\n        \"http@1.0.0\"\n      ],\n      \"iron:router 0.9.0\": [\n        \"meteor\",\n        \"reactive-dict@1.0.0\",\n        \"deps@1.0.0\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.0\",\n        \"webapp@1.0.0\",\n        \"iron:layout@0.3.0\",\n        \"?cmather:iron-router@0.8.2\",\n        \"jquery@1.0.0\",\n        \"ui@1.0.0\"\n      ],\n      \"iron:router 0.9.1\": [\n        \"meteor\",\n        \"reactive-dict@1.0.0\",\n        \"deps@1.0.0\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.0\",\n        \"webapp@1.0.0\",\n        \"iron:layout@0.3.0\",\n        \"?cmather:iron-router@0.8.2\",\n        \"jquery@1.0.0\",\n        \"ui@1.0.0\"\n      ],\n      \"iron:router 0.9.2-rc0\": [\n        \"meteor\",\n        \"reactive-dict@1.0.1-rc0\",\n        \"deps@1.0.2-rc1\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.1-rc0\",\n        \"webapp@1.0.3-rc0\",\n        \"iron:layout@0.4.0-rc0\",\n        \"?cmather:iron-router@0.8.2\",\n        \"jquery@1.0.0\",\n        \"blaze@2.0.0-rc0\"\n      ],\n      \"iron:router 0.9.2-rc2\": [\n        \"meteor\",\n        \"reactive-dict@1.0.1-rc1\",\n        \"deps@1.0.2-rc1\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.1-rc0\",\n        \"webapp@1.0.3-rc0\",\n        \"iron:layout@0.4.0-rc2\",\n        \"?cmather:iron-router@0.8.2\",\n        \"jquery@1.0.0\",\n        \"blaze@2.0.0-rc1\"\n      ],\n      \"iron:router 0.9.3-rc0\": [\n        \"meteor\",\n        \"reactive-dict@1.0.1-rc1\",\n        \"deps@1.0.2-rc1\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.1-rc0\",\n        \"webapp@1.1.0-rc1\",\n        \"iron:layout@0.4.1-rc0\",\n        \"?cmather:iron-router@0.8.2\",\n        \"jquery@1.0.0\",\n        \"blaze@2.0.0-rc1\"\n      ],\n      \"iron:router 0.9.3\": [\n        \"meteor\",\n        \"reactive-dict@1.0.1\",\n        \"deps@1.0.2\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.1\",\n        \"webapp@1.0.3\",\n        \"iron:layout@0.4.1\",\n        \"?cmather:iron-router@0.8.2\",\n        \"jquery@1.0.0\",\n        \"blaze@2.0.0\"\n      ],\n      \"iron:router 0.9.4\": [\n        \"meteor\",\n        \"reactive-dict@1.0.1\",\n        \"deps@1.0.2\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.1\",\n        \"webapp@1.0.3\",\n        \"iron:layout@0.4.1\",\n        \"?cmather:iron-router@0.8.2\",\n        \"jquery@1.0.0\",\n        \"blaze@2.0.0\"\n      ],\n      \"iron:router 1.0.0-pre0\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.0-rc1\",\n        \"ui@1.0.1-rc0\",\n        \"templating@1.0.6-rc0\",\n        \"meteor@1.1.0-rc0\",\n        \"iron:core@1.0.0-pre0\",\n        \"iron:layout@1.0.0-pre0\",\n        \"iron:middleware-stack@1.0.0-pre0\",\n        \"iron:url@1.0.0-pre0\",\n        \"iron:location@1.0.0-pre0\",\n        \"iron:controller@1.0.0-pre0\",\n        \"deps@1.0.2-rc1\"\n      ],\n      \"iron:router 1.0.0-pre1\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.0-pre1\",\n        \"iron:layout@1.0.0-pre1\",\n        \"iron:middleware-stack@1.0.0-pre1\",\n        \"iron:url@1.0.0-pre1\",\n        \"iron:location@1.0.0-pre1\",\n        \"iron:controller@1.0.0-pre1\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:router 1.0.0-pre2\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.0-pre2\",\n        \"iron:layout@1.0.0-pre2\",\n        \"iron:middleware-stack@1.0.0-pre2\",\n        \"iron:url@1.0.0-pre2\",\n        \"iron:location@1.0.0-pre2\",\n        \"iron:controller@1.0.0-pre2\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:router 1.0.0-pre3\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.0-pre3\",\n        \"iron:layout@1.0.0-pre3\",\n        \"iron:middleware-stack@1.0.0-pre3\",\n        \"iron:url@1.0.0-pre3\",\n        \"iron:location@1.0.0-pre3\",\n        \"iron:controller@1.0.0-pre3\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:router 1.0.0-pre4\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.0-pre4\",\n        \"iron:layout@1.0.0-pre4\",\n        \"iron:middleware-stack@1.0.0-pre4\",\n        \"iron:url@1.0.0-pre4\",\n        \"iron:location@1.0.0-pre4\",\n        \"iron:controller@1.0.0-pre4\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:router 1.0.0-pre5\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.0-pre5\",\n        \"iron:layout@1.0.0-pre5\",\n        \"iron:middleware-stack@1.0.0-pre5\",\n        \"iron:url@1.0.0-pre5\",\n        \"iron:location@1.0.0-pre5\",\n        \"iron:controller@1.0.0-pre5\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:router 1.0.0-rc.0\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.0-pre5\",\n        \"iron:layout@1.0.0-pre5\",\n        \"iron:middleware-stack@1.0.0-pre5\",\n        \"iron:url@1.0.0-pre5\",\n        \"iron:location@1.0.0-pre5\",\n        \"iron:controller@1.0.0-pre5\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:router 1.0.0-rc.1\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.0-rc.1\",\n        \"iron:layout@1.0.0-rc.1\",\n        \"iron:middleware-stack@1.0.0-rc.1\",\n        \"iron:url@1.0.0-rc.1\",\n        \"iron:location@1.0.0-rc.1\",\n        \"iron:controller@1.0.0-rc.1\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:router 1.0.0\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.0\",\n        \"iron:layout@1.0.0\",\n        \"iron:middleware-stack@1.0.0\",\n        \"iron:url@1.0.0\",\n        \"iron:location@1.0.0\",\n        \"iron:controller@1.0.0\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:router 1.0.1\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.0\",\n        \"iron:layout@1.0.0\",\n        \"iron:middleware-stack@1.0.0\",\n        \"iron:url@1.0.0\",\n        \"iron:location@1.0.1\",\n        \"iron:controller@1.0.0\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:router 1.0.2\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.2\",\n        \"iron:layout@1.0.2\",\n        \"iron:middleware-stack@1.0.2\",\n        \"iron:url@1.0.2\",\n        \"iron:location@1.0.2\",\n        \"iron:controller@1.0.2\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:router 1.0.3\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.3\",\n        \"iron:layout@1.0.3\",\n        \"iron:middleware-stack@1.0.3\",\n        \"iron:url@1.0.3\",\n        \"iron:location@1.0.3\",\n        \"iron:controller@1.0.3\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:router 1.0.4\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.4\",\n        \"iron:layout@1.0.4\",\n        \"iron:middleware-stack@1.0.4\",\n        \"iron:url@1.0.4\",\n        \"iron:location@1.0.4\",\n        \"iron:controller@1.0.4\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:router 1.0.5\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.4\",\n        \"iron:layout@1.0.5\",\n        \"iron:middleware-stack@1.0.4\",\n        \"iron:url@1.0.4\",\n        \"iron:location@1.0.4\",\n        \"iron:controller@1.0.4\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:router 1.0.6\": [\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\",\n        \"ui@1.0.2\",\n        \"templating@1.0.6\",\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"iron:core@1.0.6\",\n        \"iron:layout@1.0.6\",\n        \"iron:middleware-stack@1.0.6\",\n        \"iron:url@1.0.6\",\n        \"iron:location@1.0.6\",\n        \"iron:controller@1.0.6\",\n        \"deps@1.0.3\"\n      ],\n      \"iron:controller 1.0.0-pre0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2-rc1\",\n        \"reactive-dict@1.0.1-rc1\",\n        \"iron:core@1.0.0-pre0\",\n        \"iron:layout@1.0.0-pre0\",\n        \"iron:dynamic-template@1.0.0-pre0\"\n      ],\n      \"iron:controller 1.0.0-pre1\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-dict@1.0.2\",\n        \"iron:core@1.0.0-pre1\",\n        \"iron:layout@1.0.0-pre1\",\n        \"iron:dynamic-template@1.0.0-pre1\"\n      ],\n      \"iron:controller 1.0.0-pre2\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-dict@1.0.2\",\n        \"iron:core@1.0.0-pre2\",\n        \"iron:layout@1.0.0-pre2\",\n        \"iron:dynamic-template@1.0.0-pre2\"\n      ],\n      \"iron:controller 1.0.0-pre3\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-dict@1.0.2\",\n        \"iron:core@1.0.0-pre3\",\n        \"iron:layout@1.0.0-pre3\",\n        \"iron:dynamic-template@1.0.0-pre3\"\n      ],\n      \"iron:controller 1.0.0-pre4\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-dict@1.0.2\",\n        \"templating@1.0.6\",\n        \"iron:core@1.0.0-pre4\",\n        \"iron:layout@1.0.0-pre4\",\n        \"iron:dynamic-template@1.0.0-pre4\"\n      ],\n      \"iron:controller 1.0.0-pre5\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-dict@1.0.2\",\n        \"templating@1.0.6\",\n        \"iron:core@1.0.0-pre5\",\n        \"iron:layout@1.0.0-pre5\",\n        \"iron:dynamic-template@1.0.0-pre5\"\n      ],\n      \"iron:controller 1.0.0-rc.1\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-dict@1.0.2\",\n        \"templating@1.0.6\",\n        \"iron:core@1.0.0-rc.1\",\n        \"iron:layout@1.0.0-rc.1\",\n        \"iron:dynamic-template@1.0.0-rc.1\"\n      ],\n      \"iron:controller 1.0.0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-dict@1.0.2\",\n        \"templating@1.0.6\",\n        \"iron:core@1.0.0\",\n        \"iron:layout@1.0.0\",\n        \"iron:dynamic-template@1.0.0\"\n      ],\n      \"iron:controller 1.0.2\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-dict@1.0.2\",\n        \"templating@1.0.6\",\n        \"iron:core@1.0.2\",\n        \"iron:layout@1.0.2\",\n        \"iron:dynamic-template@1.0.2\"\n      ],\n      \"iron:controller 1.0.3\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-dict@1.0.2\",\n        \"templating@1.0.6\",\n        \"iron:core@1.0.3\",\n        \"iron:layout@1.0.3\",\n        \"iron:dynamic-template@1.0.3\"\n      ],\n      \"iron:controller 1.0.4\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-dict@1.0.2\",\n        \"templating@1.0.6\",\n        \"iron:core@1.0.4\",\n        \"iron:layout@1.0.4\",\n        \"iron:dynamic-template@1.0.4\"\n      ],\n      \"iron:controller 1.0.6\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-dict@1.0.2\",\n        \"templating@1.0.6\",\n        \"iron:core@1.0.6\",\n        \"iron:layout@1.0.6\",\n        \"iron:dynamic-template@1.0.6\"\n      ],\n      \"iron:dynamic-template 0.3.0\": [\n        \"meteor\",\n        \"blaze@1.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.0\",\n        \"jquery@1.0.0\",\n        \"deps@1.0.0\",\n        \"templating@1.0.0\",\n        \"iron:core@0.3.2\"\n      ],\n      \"iron:dynamic-template 0.4.0-rc0\": [\n        \"meteor\",\n        \"blaze@2.0.0-rc0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.1-rc0\",\n        \"jquery@1.0.0\",\n        \"deps@1.0.2-rc1\",\n        \"templating@1.0.5-rc0\",\n        \"iron:core@0.3.2\"\n      ],\n      \"iron:dynamic-template 0.4.0-rc1\": [\n        \"meteor\",\n        \"blaze@2.0.0-rc1\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.1-rc0\",\n        \"jquery@1.0.0\",\n        \"deps@1.0.2-rc1\",\n        \"templating@1.0.5-rc2\",\n        \"iron:core@0.3.2\"\n      ],\n      \"iron:dynamic-template 0.4.0-rc2\": [\n        \"meteor\",\n        \"blaze@2.0.0-rc1\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.1-rc0\",\n        \"jquery@1.0.0\",\n        \"deps@1.0.2-rc1\",\n        \"templating@1.0.5-rc2\",\n        \"iron:core@0.3.3-rc0\"\n      ],\n      \"iron:dynamic-template 0.4.1-rc0\": [\n        \"meteor\",\n        \"blaze@2.0.0-rc1\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.1-rc0\",\n        \"jquery@1.0.0\",\n        \"deps@1.0.2-rc1\",\n        \"templating@1.0.6-rc0\",\n        \"iron:core@0.3.4-rc0\"\n      ],\n      \"iron:dynamic-template 0.4.1\": [\n        \"meteor\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.1\",\n        \"jquery@1.0.0\",\n        \"deps@1.0.2\",\n        \"templating@1.0.5\",\n        \"iron:core@0.3.4\"\n      ],\n      \"iron:dynamic-template 1.0.0-pre0\": [\n        \"meteor\",\n        \"blaze@2.0.0-rc1\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.1-rc0\",\n        \"jquery@1.0.0\",\n        \"tracker@1.0.2-rc1\",\n        \"reactive-var@1.0.1-rc0\",\n        \"templating@1.0.6-rc0\",\n        \"iron:core@1.0.0-pre0\"\n      ],\n      \"iron:dynamic-template 1.0.0-pre1\": [\n        \"meteor\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.2\",\n        \"jquery@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-var@1.0.1\",\n        \"templating@1.0.6\",\n        \"iron:core@1.0.0-pre1\"\n      ],\n      \"iron:dynamic-template 1.0.0-pre2\": [\n        \"meteor\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.2\",\n        \"jquery@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-var@1.0.1\",\n        \"templating@1.0.6\",\n        \"iron:core@1.0.0-pre2\"\n      ],\n      \"iron:dynamic-template 1.0.0-pre3\": [\n        \"meteor\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.2\",\n        \"jquery@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-var@1.0.1\",\n        \"templating@1.0.6\",\n        \"iron:core@1.0.0-pre3\"\n      ],\n      \"iron:dynamic-template 1.0.0-pre4\": [\n        \"meteor\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.2\",\n        \"jquery@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-var@1.0.1\",\n        \"templating@1.0.6\",\n        \"random@1.0.0\",\n        \"iron:core@1.0.0-pre4\"\n      ],\n      \"iron:dynamic-template 1.0.0-pre5\": [\n        \"meteor\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.2\",\n        \"jquery@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-var@1.0.1\",\n        \"templating@1.0.6\",\n        \"random@1.0.0\",\n        \"iron:core@1.0.0-pre5\"\n      ],\n      \"iron:dynamic-template 1.0.0-rc.1\": [\n        \"meteor\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.2\",\n        \"jquery@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-var@1.0.1\",\n        \"templating@1.0.6\",\n        \"random@1.0.0\",\n        \"iron:core@1.0.0-rc.1\"\n      ],\n      \"iron:dynamic-template 1.0.0\": [\n        \"meteor\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.2\",\n        \"jquery@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-var@1.0.1\",\n        \"templating@1.0.6\",\n        \"random@1.0.0\",\n        \"iron:core@1.0.0\"\n      ],\n      \"iron:dynamic-template 1.0.2\": [\n        \"meteor\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.2\",\n        \"jquery@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-var@1.0.1\",\n        \"templating@1.0.6\",\n        \"random@1.0.0\",\n        \"iron:core@1.0.2\"\n      ],\n      \"iron:dynamic-template 1.0.3\": [\n        \"meteor\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.2\",\n        \"jquery@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-var@1.0.1\",\n        \"templating@1.0.6\",\n        \"random@1.0.0\",\n        \"iron:core@1.0.3\"\n      ],\n      \"iron:dynamic-template 1.0.4\": [\n        \"meteor\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.2\",\n        \"jquery@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-var@1.0.1\",\n        \"templating@1.0.6\",\n        \"random@1.0.0\",\n        \"iron:core@1.0.4\"\n      ],\n      \"iron:dynamic-template 1.0.5\": [\n        \"meteor\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.2\",\n        \"jquery@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-var@1.0.1\",\n        \"templating@1.0.6\",\n        \"random@1.0.0\",\n        \"iron:core@1.0.4\"\n      ],\n      \"iron:dynamic-template 1.0.6\": [\n        \"meteor\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.2\",\n        \"jquery@1.0.0\",\n        \"tracker@1.0.2\",\n        \"reactive-var@1.0.1\",\n        \"templating@1.0.6\",\n        \"random@1.0.0\",\n        \"iron:core@1.0.6\"\n      ],\n      \"iron:location 1.0.0-pre0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2-rc1\",\n        \"jquery@1.0.0\",\n        \"iron:core@1.0.0-pre0\",\n        \"iron:url@1.0.0-pre0\"\n      ],\n      \"iron:location 1.0.0-pre1\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"jquery@1.0.0\",\n        \"iron:core@1.0.0-pre1\",\n        \"iron:url@1.0.0-pre1\"\n      ],\n      \"iron:location 1.0.0-pre2\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"jquery@1.0.0\",\n        \"iron:core@1.0.0-pre2\",\n        \"iron:url@1.0.0-pre2\"\n      ],\n      \"iron:location 1.0.0-pre3\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"jquery@1.0.0\",\n        \"iron:core@1.0.0-pre3\",\n        \"iron:url@1.0.0-pre3\"\n      ],\n      \"iron:location 1.0.0-pre4\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"jquery@1.0.0\",\n        \"iron:core@1.0.0-pre4\",\n        \"iron:url@1.0.0-pre4\"\n      ],\n      \"iron:location 1.0.0-pre5\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"jquery@1.0.0\",\n        \"iron:core@1.0.0-pre5\",\n        \"iron:url@1.0.0-pre5\",\n        \"?appcache@1.0.0-cordova1\"\n      ],\n      \"iron:location 1.0.0-rc.1\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"jquery@1.0.0\",\n        \"iron:core@1.0.0-rc.1\",\n        \"iron:url@1.0.0-rc.1\",\n        \"?appcache@1.0.0-cordova1\"\n      ],\n      \"iron:location 1.0.0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"jquery@1.0.0\",\n        \"iron:core@1.0.0\",\n        \"iron:url@1.0.0\",\n        \"?appcache@1.0.0-cordova1\"\n      ],\n      \"iron:location 1.0.1\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"jquery@1.0.0\",\n        \"iron:core@1.0.0\",\n        \"iron:url@1.0.0\",\n        \"?appcache@1.0.0-cordova1\"\n      ],\n      \"iron:location 1.0.2\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"jquery@1.0.0\",\n        \"iron:core@1.0.2\",\n        \"iron:url@1.0.2\",\n        \"?appcache@1.0.0-cordova1\"\n      ],\n      \"iron:location 1.0.3\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"jquery@1.0.0\",\n        \"iron:core@1.0.3\",\n        \"iron:url@1.0.3\",\n        \"?appcache@1.0.0-cordova1\"\n      ],\n      \"iron:location 1.0.4\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"jquery@1.0.0\",\n        \"iron:core@1.0.4\",\n        \"iron:url@1.0.4\",\n        \"?appcache@1.0.0-cordova1\"\n      ],\n      \"iron:location 1.0.6\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"tracker@1.0.2\",\n        \"jquery@1.0.0\",\n        \"iron:core@1.0.6\",\n        \"iron:url@1.0.6\",\n        \"?appcache@1.0.0-cordova1\"\n      ],\n      \"iron:url 1.0.0-pre0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre0\"\n      ],\n      \"iron:url 1.0.0-pre1\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre1\"\n      ],\n      \"iron:url 1.0.0-pre2\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre2\"\n      ],\n      \"iron:url 1.0.0-pre3\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre3\"\n      ],\n      \"iron:url 1.0.0-pre4\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre4\"\n      ],\n      \"iron:url 1.0.0-pre5\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre5\"\n      ],\n      \"iron:url 1.0.0-rc.1\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-rc.1\"\n      ],\n      \"iron:url 1.0.0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0\"\n      ],\n      \"iron:url 1.0.2\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.2\"\n      ],\n      \"iron:url 1.0.3\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.3\"\n      ],\n      \"iron:url 1.0.4\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.4\"\n      ],\n      \"iron:url 1.0.6\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.6\"\n      ],\n      \"iron:middleware-stack 1.0.0-pre0\": [\n        \"meteor\",\n        \"iron:core@1.0.0-pre0\",\n        \"iron:url@1.0.0-pre0\"\n      ],\n      \"iron:middleware-stack 1.0.0-pre1\": [\n        \"meteor\",\n        \"iron:core@1.0.0-pre1\",\n        \"iron:url@1.0.0-pre1\"\n      ],\n      \"iron:middleware-stack 1.0.0-pre2\": [\n        \"meteor\",\n        \"iron:core@1.0.0-pre2\",\n        \"iron:url@1.0.0-pre2\"\n      ],\n      \"iron:middleware-stack 1.0.0-pre3\": [\n        \"meteor\",\n        \"iron:core@1.0.0-pre3\",\n        \"iron:url@1.0.0-pre3\"\n      ],\n      \"iron:middleware-stack 1.0.0-pre4\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre4\",\n        \"iron:url@1.0.0-pre4\"\n      ],\n      \"iron:middleware-stack 1.0.0-pre5\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre5\",\n        \"iron:url@1.0.0-pre5\"\n      ],\n      \"iron:middleware-stack 1.0.0-rc.1\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-rc.1\",\n        \"iron:url@1.0.0-rc.1\"\n      ],\n      \"iron:middleware-stack 1.0.0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0\",\n        \"iron:url@1.0.0\"\n      ],\n      \"iron:middleware-stack 1.0.2\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.2\",\n        \"iron:url@1.0.2\"\n      ],\n      \"iron:middleware-stack 1.0.3\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.3\",\n        \"iron:url@1.0.3\"\n      ],\n      \"iron:middleware-stack 1.0.4\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.4\",\n        \"iron:url@1.0.4\"\n      ],\n      \"iron:middleware-stack 1.0.6\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.6\",\n        \"iron:url@1.0.6\"\n      ],\n      \"iron:core 0.3.0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.0\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 0.3.1\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.0\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 0.3.2\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.0\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 0.3.3-rc0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.1-rc0\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 0.3.4-rc0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.1-rc0\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 0.3.4\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.1\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 1.0.0-pre0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.1-rc0\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 1.0.0-pre1\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.2\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 1.0.0-pre2\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.2\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 1.0.0-pre3\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.2\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 1.0.0-pre4\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.2\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 1.0.0-pre5\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.2\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 1.0.0-rc.1\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.2\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 1.0.0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.2\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 1.0.2\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.2\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 1.0.3\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.2\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 1.0.4\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.2\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"iron:core 1.0.6\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.2\",\n        \"?cmather:iron-core@0.2.0\"\n      ],\n      \"cmather:iron-core 0.1.0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.0\"\n      ],\n      \"cmather:iron-core 0.2.0\": [\n        \"meteor\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.0\"\n      ],\n      \"cmather:iron-router 0.5.3\": [\n        \"meteor\"\n      ],\n      \"cmather:iron-router 0.5.4\": [\n        \"meteor\"\n      ],\n      \"cmather:iron-router 0.6.0\": [\n        \"meteor\",\n        \"reactive-dict@1.0.0\",\n        \"deps@1.0.0\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.0\",\n        \"webapp@1.0.0\",\n        \"templating@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"jquery@1.0.0\"\n      ],\n      \"cmather:iron-router 0.6.1\": [\n        \"meteor\",\n        \"reactive-dict@1.0.0\",\n        \"deps@1.0.0\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.0\",\n        \"webapp@1.0.0\",\n        \"templating@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"jquery@1.0.0\"\n      ],\n      \"cmather:iron-router 0.6.2\": [\n        \"meteor\",\n        \"reactive-dict@1.0.0\",\n        \"deps@1.0.0\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.0\",\n        \"webapp@1.0.0\",\n        \"templating@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"jquery@1.0.0\"\n      ],\n      \"cmather:iron-router 0.6.3\": [\n        \"meteor\",\n        \"reactive-dict@1.0.0\",\n        \"deps@1.0.0\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.0\",\n        \"webapp@1.0.0\",\n        \"templating@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"jquery@1.0.0\"\n      ],\n      \"cmather:iron-router 0.6.4\": [\n        \"meteor\",\n        \"reactive-dict@1.0.0\",\n        \"deps@1.0.0\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.0\",\n        \"webapp@1.0.0\",\n        \"templating@1.0.0\",\n        \"handlebars@1.0.0\",\n        \"jquery@1.0.0\"\n      ],\n      \"cmather:iron-router 0.7.0\": [\n        \"meteor\"\n      ],\n      \"cmather:iron-router 0.7.1\": [\n        \"meteor\"\n      ],\n      \"cmather:iron-router 0.8.0\": [\n        \"meteor\"\n      ],\n      \"cmather:iron-router 0.8.1\": [\n        \"meteor\"\n      ],\n      \"cmather:iron-router 0.8.2\": [\n        \"meteor\",\n        \"reactive-dict@1.0.0\",\n        \"deps@1.0.0\",\n        \"underscore@1.0.0\",\n        \"ejson@1.0.0\",\n        \"cmather:iron-layout@0.2.0\",\n        \"webapp@1.0.0\",\n        \"jquery@1.0.0\",\n        \"ui@1.0.0\"\n      ],\n      \"cmather:iron-layout 0.1.0\": [\n        \"meteor\"\n      ],\n      \"cmather:iron-layout 0.1.1\": [\n        \"meteor\"\n      ],\n      \"cmather:iron-layout 0.1.2\": [\n        \"meteor\"\n      ],\n      \"cmather:iron-layout 0.2.0\": [\n        \"templating@1.0.0\",\n        \"ui@1.0.0\",\n        \"meteor@1.0.0\",\n        \"underscore@1.0.0\",\n        \"cmather:iron-core@0.2.0\",\n        \"cmather:iron-dynamic-template@0.2.1\",\n        \"?cmather:blaze-layout@0.2.5\"\n      ],\n      \"cmather:blaze-layout 0.0.1\": [\n        \"meteor\"\n      ],\n      \"cmather:blaze-layout 0.1.0\": [\n        \"meteor\"\n      ],\n      \"cmather:blaze-layout 0.2.0\": [\n        \"meteor\"\n      ],\n      \"cmather:blaze-layout 0.2.1\": [\n        \"meteor\"\n      ],\n      \"cmather:blaze-layout 0.2.2\": [\n        \"meteor\"\n      ],\n      \"cmather:blaze-layout 0.2.3\": [\n        \"meteor\"\n      ],\n      \"cmather:blaze-layout 0.2.4\": [\n        \"meteor\"\n      ],\n      \"cmather:blaze-layout 0.2.5\": [\n        \"meteor\",\n        \"templating@1.0.0\",\n        \"ui@1.0.0\",\n        \"reactive-dict@1.0.0\",\n        \"underscore@1.0.0\",\n        \"?iron-router@0.8.2\"\n      ],\n      \"cmather:iron-dynamic-template 0.1.0\": [\n        \"meteor\"\n      ],\n      \"cmather:iron-dynamic-template 0.2.0\": [\n        \"meteor\"\n      ],\n      \"cmather:iron-dynamic-template 0.2.1\": [\n        \"meteor\",\n        \"blaze@1.0.0\",\n        \"underscore@1.0.0\",\n        \"ui@1.0.0\",\n        \"spacebars@1.0.0\",\n        \"jquery@1.0.0\",\n        \"deps@1.0.0\",\n        \"templating@1.0.0\",\n        \"cmather:iron-core@0.2.0\"\n      ],\n      \"iron:layout 0.3.0\": [\n        \"templating@1.0.0\",\n        \"ui@1.0.0\",\n        \"meteor@1.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@0.3.2\",\n        \"iron:dynamic-template@0.3.0\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 0.4.0-rc0\": [\n        \"meteor\",\n        \"templating@1.0.5-rc0\",\n        \"blaze@2.0.0-rc0\",\n        \"underscore@1.0.0\",\n        \"iron:core@0.3.2\",\n        \"iron:dynamic-template@0.4.0-rc0\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 0.4.0-rc1\": [\n        \"meteor\",\n        \"templating@1.0.5-rc2\",\n        \"blaze@2.0.0-rc1\",\n        \"underscore@1.0.0\",\n        \"iron:core@0.3.2\",\n        \"iron:dynamic-template@0.4.0-rc1\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 0.4.0-rc2\": [\n        \"meteor\",\n        \"templating@1.0.5-rc2\",\n        \"blaze@2.0.0-rc1\",\n        \"underscore@1.0.0\",\n        \"iron:core@0.3.3-rc0\",\n        \"iron:dynamic-template@0.4.0-rc2\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 0.4.1-rc0\": [\n        \"meteor\",\n        \"templating@1.0.6-rc0\",\n        \"blaze@2.0.0-rc1\",\n        \"underscore@1.0.0\",\n        \"iron:core@0.3.4-rc0\",\n        \"iron:dynamic-template@0.4.1-rc0\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 0.4.1\": [\n        \"meteor\",\n        \"templating@1.0.5\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@0.3.4\",\n        \"iron:dynamic-template@0.4.1\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 1.0.0-pre0\": [\n        \"meteor\",\n        \"templating@1.0.6-rc0\",\n        \"blaze@2.0.0-rc1\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre0\",\n        \"iron:dynamic-template@1.0.0-pre0\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 1.0.0-pre1\": [\n        \"meteor\",\n        \"templating@1.0.6\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre1\",\n        \"iron:dynamic-template@1.0.0-pre1\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 1.0.0-pre2\": [\n        \"meteor\",\n        \"templating@1.0.6\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre2\",\n        \"iron:dynamic-template@1.0.0-pre2\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 1.0.0-pre3\": [\n        \"meteor\",\n        \"templating@1.0.6\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre3\",\n        \"iron:dynamic-template@1.0.0-pre3\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 1.0.0-pre4\": [\n        \"meteor\",\n        \"templating@1.0.6\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre4\",\n        \"iron:dynamic-template@1.0.0-pre4\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 1.0.0-pre5\": [\n        \"meteor\",\n        \"templating@1.0.6\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-pre5\",\n        \"iron:dynamic-template@1.0.0-pre5\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 1.0.0-rc.1\": [\n        \"meteor\",\n        \"templating@1.0.6\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0-rc.1\",\n        \"iron:dynamic-template@1.0.0-rc.1\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 1.0.0\": [\n        \"meteor\",\n        \"templating@1.0.6\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.0\",\n        \"iron:dynamic-template@1.0.0\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 1.0.2\": [\n        \"meteor\",\n        \"templating@1.0.6\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.2\",\n        \"iron:dynamic-template@1.0.2\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 1.0.3\": [\n        \"meteor\",\n        \"templating@1.0.6\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.3\",\n        \"iron:dynamic-template@1.0.3\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 1.0.4\": [\n        \"meteor\",\n        \"templating@1.0.6\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.4\",\n        \"iron:dynamic-template@1.0.4\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 1.0.5\": [\n        \"meteor\",\n        \"templating@1.0.6\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.4\",\n        \"iron:dynamic-template@1.0.5\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"iron:layout 1.0.6\": [\n        \"meteor\",\n        \"templating@1.0.6\",\n        \"blaze@2.0.0\",\n        \"underscore@1.0.0\",\n        \"iron:core@1.0.6\",\n        \"iron:dynamic-template@1.0.6\",\n        \"?cmather:blaze-layout@0.2.5\",\n        \"?cmather:iron-layout@0.2.0\"\n      ],\n      \"insecure 1.0.2\": [\n        \"meteor\"\n      ],\n      \"autopublish 1.0.2\": [\n        \"meteor\"\n      ],\n      \"meteor-platform 1.2.1\": [\n        \"meteor\",\n        \"reload\",\n        \"autoupdate\",\n        \"webapp\",\n        \"logging\",\n        \"tracker\",\n        \"deps\",\n        \"session\",\n        \"ddp\",\n        \"livedata\",\n        \"mongo\",\n        \"blaze\",\n        \"ui\",\n        \"spacebars\",\n        \"templating\",\n        \"check\",\n        \"underscore\",\n        \"jquery\",\n        \"random\",\n        \"ejson\",\n        \"launch-screen\",\n        \"fastclick\",\n        \"mobile-status-bar\"\n      ]\n    }\n  },\n  \"previousSolution\": {}\n};\n"
  },
  {
    "path": "packages/constraint-solver/solver.js",
    "content": "var CS = ConstraintSolver;\nvar PV = PackageVersion;\n\nvar pvVar = function (p, v) {\n  return p + ' ' + v;\n};\n\n// The \"inner solver\".  You construct it with a ConstraintSolver.Input object\n// (which specifies the problem) and then call .getAnswer() on it.\n\nCS.Solver = function (input, options) {\n  var self = this;\n  check(input, CS.Input);\n\n  self.input = input;\n  self.errors = []; // [String]\n\n  self.pricer = new CS.VersionPricer();\n  self.getConstraintFormula = _.memoize(_getConstraintFormula,\n                                         function (p, vConstraint) {\n                                           return p + \"@\" + vConstraint.raw;\n                                         });\n\n  self.options = options || {};\n  self.Profile = (self.options.Profile || CS.DummyProfile);\n\n  self.steps = [];\n  self.stepsByName = {};\n\n  self.analysis = {};\n\n  self.Profile.time(\"Solver#analyze\", function () {\n    self.analyze();\n  });\n\n  self.logic = null; // Logic.Solver, initialized later\n};\n\nCS.Solver.prototype.throwAnyErrors = function () {\n  if (this.errors.length) {\n    var multiline = _.any(this.errors, function (e) {\n      return /\\n/.test(e);\n    });\n    CS.throwConstraintSolverError(this.errors.join(\n      multiline ? '\\n\\n' : '\\n'));\n  }\n};\n\nCS.Solver.prototype.getVersions = function (pkg) {\n  var self = this;\n  if (_.has(self.analysis.allowedVersions, pkg)) {\n    return self.analysis.allowedVersions[pkg];\n  } else {\n    return self.input.catalogCache.getPackageVersions(pkg);\n  }\n};\n\n// Populates `self.analysis` with various data structures derived from the\n// input.  May also throw errors, and may call methods that rely on\n// analysis once that particular analysis is done (e.g. `self.getVersions`\n// which relies on `self.analysis.allowedVersions`.\nCS.Solver.prototype.analyze = function () {\n  var self = this;\n  var analysis = self.analysis;\n  var input = self.input;\n  var cache = input.catalogCache;\n  var Profile = self.Profile;\n\n  ////////// ANALYZE ALLOWED VERSIONS\n  // (An \"allowed version\" is one that isn't ruled out by a top-level\n  // constraint.)\n\n  // package -> array of version strings.  If a package has an entry in\n  // this map, then only the versions in the array are allowed for\n  // consideration.\n  analysis.allowedVersions = {};\n  analysis.packagesWithNoAllowedVersions = {}; // package -> [constraints]\n\n  // Process top-level constraints, applying them right now by\n  // limiting what package versions we even consider.  This speeds up\n  // solving, especially given the equality constraints on core\n  // packages.  For versions we don't allow, we get to avoid generating\n  // Constraint objects for their constraints, which saves us both\n  // clause generation time and solver work up through the point where we\n  // determine there are no conflicts between constraints.\n  //\n  // we can't throw any errors yet, because `input.constraints`\n  // doesn't establish any dependencies (so we don't know if it's a\n  // problem that some package has no legal versions), but we can\n  // track such packages in packagesWithNoAllowedVersions so that we\n  // throw a good error later.\n  Profile.time(\"analyze allowed versions\", function () {\n    _.each(_.groupBy(input.constraints, 'package'), function (cs, p) {\n      var versions = cache.getPackageVersions(p);\n      if (! versions.length) {\n        // deal with wholly unknown packages later\n        return;\n      }\n      _.each(cs, function (constr) {\n        versions = _.filter(versions, function (v) {\n          return CS.isConstraintSatisfied(p, constr.versionConstraint, v);\n        });\n      });\n      if (! versions.length) {\n        analysis.packagesWithNoAllowedVersions[p] = _.filter(cs, function (c) {\n          return !! c.constraintString;\n        });\n      }\n      analysis.allowedVersions[p] = versions;\n    });\n  });\n\n  ////////// ANALYZE ROOT DEPENDENCIES\n\n  // Collect root dependencies that we've never heard of.\n  analysis.unknownRootDeps = [];\n  // Collect \"previous solution\" versions of root dependencies.\n  analysis.previousRootDepVersions = [];\n\n  Profile.time(\"analyze root dependencies\", function () {\n    _.each(input.dependencies, function (p) {\n      if (! input.isKnownPackage(p)) {\n        analysis.unknownRootDeps.push(p);\n      } else if (input.isInPreviousSolution(p) &&\n                 ! input.isUpgrading(p)) {\n        analysis.previousRootDepVersions.push(new CS.PackageAndVersion(\n          p, input.previousSolution[p]));\n      }\n    });\n\n    // throw if there are unknown packages in root deps\n    if (analysis.unknownRootDeps.length) {\n      _.each(analysis.unknownRootDeps, function (p) {\n        if (CS.isIsobuildFeaturePackage(p)) {\n          self.errors.push(\n            'unsupported Isobuild feature \"' + p +\n            '\" in top-level dependencies; see ' +\n            'https://github.com/meteor/meteor/wiki/Isobuild-Feature-Packages ' +\n            'for a list of features and the minimum Meteor release required'\n          );\n        } else {\n          self.errors.push('unknown package in top-level dependencies: ' + p);\n        }\n      });\n      self.throwAnyErrors();\n    }\n  });\n\n  ////////// ANALYZE REACHABILITY\n\n  // A \"reachable\" package is one that is either a root dependency or\n  // a strong dependency of any \"allowed\" version of a reachable package.\n  // In other words, we walk all strong dependencies starting\n  // with the root dependencies, and visiting all allowed versions of each\n  // package.\n  //\n  // This analysis is mainly done for performance, because if there are\n  // extraneous packages in the CatalogCache (for whatever reason) we\n  // want to spend as little time on them as possible.  It also establishes\n  // the universe of possible \"known\" and \"unknown\" packages we might\n  // come across.\n  //\n  // A more nuanced reachability analysis that takes versions into account\n  // is probably possible.\n\n  // package name -> true\n  analysis.reachablePackages = {};\n  // package name -> package versions asking for it (in pvVar form)\n  analysis.unknownPackages = {};\n\n  var markReachable = function (p) {\n    analysis.reachablePackages[p] = true;\n\n    _.each(self.getVersions(p), function (v) {\n      _.each(cache.getDependencyMap(p, v), function (dep) {\n        // `dep` is a CS.Dependency\n        var p2 = dep.packageConstraint.package;\n        if (! input.isKnownPackage(p2)) {\n          // record this package so we will generate a variable\n          // for it.  we'll try not to select it, and ultimately\n          // throw an error if we are forced to.\n          if (! _.has(analysis.unknownPackages, p2)) {\n            analysis.unknownPackages[p2] = [];\n          }\n          analysis.unknownPackages[p2].push(pvVar(p, v));\n        } else {\n          if (! dep.isWeak) {\n            if (! _.has(analysis.reachablePackages, p2)) {\n              markReachable(p2);\n            }\n          }\n        }\n      });\n    });\n  };\n\n  Profile.time(\"analyze reachability\", function () {\n    _.each(input.dependencies, markReachable);\n  });\n\n  ////////// ANALYZE CONSTRAINTS\n\n  // Array of CS.Solver.Constraint\n  analysis.constraints = [];\n  // packages `foo` such that there's a simple top-level equality\n  // constraint about `foo`.  package name -> true.\n  analysis.topLevelEqualityConstrainedPackages = {};\n\n  Profile.time(\"analyze constraints\", function () {\n    // top-level constraints\n    _.each(input.constraints, function (c) {\n      if (c.constraintString) {\n        analysis.constraints.push(new CS.Solver.Constraint(\n          null, c.package, c.versionConstraint,\n          \"constraint#\" + analysis.constraints.length));\n\n        if (c.versionConstraint.alternatives.length === 1 &&\n            c.versionConstraint.alternatives[0].type === 'exactly') {\n          analysis.topLevelEqualityConstrainedPackages[c.package] = true;\n        }\n      }\n    });\n\n    // constraints specified in package dependencies\n    _.each(_.keys(analysis.reachablePackages), function (p) {\n      _.each(self.getVersions(p), function (v) {\n        var pv = pvVar(p, v);\n        _.each(cache.getDependencyMap(p, v), function (dep) {\n          // `dep` is a CS.Dependency\n          var p2 = dep.packageConstraint.package;\n          if (input.isKnownPackage(p2) &&\n              dep.packageConstraint.constraintString) {\n            analysis.constraints.push(new CS.Solver.Constraint(\n              pv, p2, dep.packageConstraint.versionConstraint,\n              \"constraint#\" + analysis.constraints.length));\n          }\n        });\n      });\n    });\n  });\n\n  ////////// ANALYZE PRE-RELEASES\n\n  Profile.time(\"analyze pre-releases\", function () {\n    var unanticipatedPrereleases = [];\n    _.each(_.keys(analysis.reachablePackages), function (p) {\n      var anticipatedPrereleases = input.anticipatedPrereleases[p];\n      _.each(self.getVersions(p), function (v) {\n        if (/-/.test(v) && ! (anticipatedPrereleases &&\n                              _.has(anticipatedPrereleases, v))) {\n          unanticipatedPrereleases.push(pvVar(p, v));\n        }\n      });\n    });\n    analysis.unanticipatedPrereleases = unanticipatedPrereleases;\n  });\n};\n\nvar WholeNumber = Match.Where(Logic.isWholeNumber);\n\n// A Step consists of a name, an array of terms, and an array of weights.\n// Steps are optimized one by one.  Optimizing a Step means to find\n// the minimum whole number value for the weighted sum of the terms,\n// and then to enforce in the solver that the weighted sum be that number.\n// Thus, when the Steps are optimized in sequence, earlier Steps take\n// precedence and will stay minimized while later Steps are optimized.\n//\n// A term can be a package name, a package version, or any other variable\n// name or Logic formula.\n//\n// A weight is a non-negative integer.  The weights array can be a single\n// weight (which is used for all terms).\n//\n// The terms and weights arguments each default to [].  You can add terms\n// with weights using addTerm.\n//\n// options is optional.\nCS.Solver.Step = function (name, terms, weights) {\n  check(name, String);\n  terms = terms || [];\n  check(terms, [String]);\n  weights = (weights == null ? [] : weights);\n  check(weights, Match.OneOf([WholeNumber], WholeNumber));\n\n  this.name = name;\n\n  // mutable:\n  this.terms = terms;\n  this.weights = weights;\n  this.optimum = null; // set when optimized\n};\n\n// If weights is a single number, you can omit the weight argument.\n// Adds a term.  If weight is 0, addTerm may skip it.\nCS.Solver.Step.prototype.addTerm = function (term, weight) {\n  if (weight == null) {\n    if (typeof this.weights !== 'number') {\n      throw new Error(\"Must specify a weight\");\n    }\n    weight = this.weights;\n  }\n  check(weight, WholeNumber);\n  if (weight !== 0) {\n    this.terms.push(term);\n    if (typeof this.weights === 'number') {\n      if (weight !== this.weights) {\n        throw new Error(\"Can't specify a different weight now: \" +\n                        weight + \" != \" + this.weights);\n      }\n    } else {\n      this.weights.push(weight);\n    }\n  }\n};\n\nvar DEBUG = false;\n\n// Call as one of:\n// * minimize(step, options)\n// * minimize([step1, step2, ...], options)\n// * minimize(stepName, costTerms, costWeights, options)\nCS.Solver.prototype.minimize = function (step, options) {\n  var self = this;\n\n  if (_.isArray(step)) {\n    // minimize([steps...], options)\n    _.each(step, function (st) {\n      self.minimize(st, options);\n    });\n    return;\n  }\n\n  if (typeof step === 'string') {\n    // minimize(stepName, costTerms, costWeights, options)\n    var stepName_ = arguments[0];\n    var costTerms_ = arguments[1];\n    var costWeights_ = arguments[2];\n    var options_ = arguments[3];\n    if (costWeights_ && typeof costWeights_ === 'object' &&\n        ! _.isArray(costWeights_)) {\n      options_ = costWeights_;\n      costWeights_ = null;\n    }\n    var theStep = new CS.Solver.Step(\n      stepName_, costTerms_, (costWeights_ == null ? 1 : costWeights_));\n    self.minimize(theStep, options_);\n    return;\n  }\n\n  // minimize(step, options);\n\n  self.Profile.time(\"minimize \" + step.name, function () {\n\n    var logic = self.logic;\n\n    self.steps.push(step);\n    self.stepsByName[step.name] = step;\n\n    if (DEBUG) {\n      console.log(\"--- MINIMIZING \" + step.name);\n    }\n\n    var costWeights = step.weights;\n    var costTerms = step.terms;\n\n    var optimized = groupMutuallyExclusiveTerms(costTerms, costWeights);\n\n    self.setSolution(logic.minimizeWeightedSum(\n      self.solution, optimized.costTerms, optimized.costWeights, {\n        progress: function (status, cost) {\n          if (self.options.nudge) {\n            self.options.nudge();\n          }\n          if (DEBUG) {\n            if (status === 'improving') {\n              console.log(cost + \" ... trying to improve ...\");\n            } else if (status === 'trying') {\n              console.log(\"... trying \" + cost + \" ... \");\n            }\n          }\n        },\n        strategy: (options && options.strategy)\n      }));\n\n    step.optimum = self.solution.getWeightedSum(costTerms, costWeights);\n    if (DEBUG) {\n      console.log(step.optimum + \" is optimal\");\n\n      if (step.optimum) {\n        _.each(costTerms, function (t, i) {\n          var w = (typeof costWeights === 'number' ? costWeights :\n                   costWeights[i]);\n          if (w && self.solution.evaluate(t)) {\n            console.log(\"    \" + w + \": \" + t);\n          }\n        });\n      }\n    }\n  });\n};\n\n// This is a correctness-preserving performance optimization.\n//\n// Cost functions often have many terms where both the package name\n// and the weight are the same.  For example, when optimizing major\n// version, we might have `(foo 3.0.0)*2 + (foo 3.0.1)*2 ...`.  It's\n// more efficient to give the solver `((foo 3.0.0) OR (foo 3.0.1) OR\n// ...)*2 + ...`, because it separates the question of whether to use\n// ANY `foo 3.x.x` variable from the question of which one.  Other\n// constraints already enforce the fact that `foo 3.0.0` and `foo 3.0.1`\n// are mutually exclusive variables.  We can use that fact to \"relax\"\n// that relationship for the purposes of the weighted sum.\n//\n// Note that shuffling up the order of terms unnecessarily seems to\n// impact performance, so it's significant that we group by package\n// first, then weight, rather than vice versa.\nvar groupMutuallyExclusiveTerms = function (costTerms, costWeights) {\n  // Return a key for a term, such that terms with the same key are\n  // guaranteed to be mutually exclusive.  We assume each term is\n  // a variable representing either a package or a package version.\n  // We take a prefix of the variable name up to and including the\n  // first space.  So \"foo 1.0.0\" becomes \"foo \" and \"foo\" stays \"foo\".\n  var getTermKey = function (t) {\n    var firstSpace = t.indexOf(' ');\n    return firstSpace < 0 ? t : t.slice(0, firstSpace+1);\n  };\n\n  // costWeights, as usual, may be a number or an array\n  if (typeof costWeights === 'number') {\n    return {\n      costTerms: _.map(_.groupBy(costTerms, getTermKey), function (group) {\n        return Logic.or(group);\n      }),\n      costWeights: costWeights\n    };\n  } else if (! costTerms.length) {\n    return { costTerms: costTerms, costWeights: costWeights };\n  } else {\n    var weightedTerms = _.zip(costWeights, costTerms);\n    var newWeightedTerms = _.map(_.groupBy(weightedTerms, function (wt) {\n      // construct a string from the weight and term key, for grouping\n      // purposes.  since the weight comes first, there's no ambiguity\n      // and the separator char could be pretty much anything.\n      return wt[0] + ' ' + getTermKey(wt[1]);\n    }), function (wts) {\n      return [wts[0][0], Logic.or(_.pluck(wts, 1))];\n    });\n    return {\n      costTerms: _.pluck(newWeightedTerms, 1),\n      costWeights: _.pluck(newWeightedTerms, 0)\n    };\n  }\n\n};\n\n// Determine the non-zero contributions to the cost function in `step`\n// based on the current solution, returning a map from term (usually\n// the name of a package or package version) to positive integer cost.\nCS.Solver.prototype.getStepContributions = function (step) {\n  var self = this;\n  var solution = self.solution;\n  var contributions = {};\n  var weights = step.weights;\n  _.each(step.terms, function (t, i) {\n    var w = (typeof weights === 'number' ? weights : weights[i]);\n    if (w && self.solution.evaluate(t)) {\n      contributions[t] = w;\n    }\n  });\n  return contributions;\n};\n\nvar addCostsToSteps = function (pkg, versions, costs, steps) {\n  var pvs = _.map(versions, function (v) {\n    return pvVar(pkg, v);\n  });\n  for (var j = 0; j < steps.length; j++) {\n    var step = steps[j];\n    var costList = costs[j];\n    if (costList.length !== versions.length) {\n      throw new Error(\"Assertion failure: Bad lengths in addCostsToSteps\");\n    }\n    for (var i = 0; i < versions.length; i++) {\n      step.addTerm(pvs[i], costList[i]);\n    }\n  }\n};\n\n// Get an array of \"Steps\" that, when minimized in order, optimizes\n// the package version costs of `packages` (an array of String package\n// names) according to `pricerMode`, which may be\n// `CS.VersionPricer.MODE_UPDATE` or a similar mode constant.\n// Wraps `VersionPricer#priceVersions`, which is tasked with calculating\n// the cost of every version of every package.  This function iterates\n// over `packages` and puts the result into `Step` objects.\nCS.Solver.prototype.getVersionCostSteps = function (stepBaseName, packages,\n                                                    pricerMode) {\n  var self = this;\n  var major = new CS.Solver.Step(stepBaseName + '_major');\n  var minor = new CS.Solver.Step(stepBaseName + '_minor');\n  var patch = new CS.Solver.Step(stepBaseName + '_patch');\n  var rest = new CS.Solver.Step(stepBaseName + '_rest');\n\n  self.Profile.time(\n    \"calculate \" + stepBaseName + \" version costs\",\n    function () {\n      _.each(packages, function (p) {\n        var versions = self.getVersions(p);\n        if (versions.length >= 2) {\n          var costs = self.pricer.priceVersions(versions, pricerMode);\n          addCostsToSteps(p, versions, costs, [major, minor, patch, rest]);\n        }\n      });\n    });\n\n  return [major, minor, patch, rest];\n};\n\n// Like `getVersionCostSteps`, but wraps\n// `VersionPricer#priceVersionsWithPrevious` instead of `#priceVersions`.\n// The cost function is \"distance\" from the previous versions passed in\n// as `packageAndVersion`.  (Actually it's a complicated function of the\n// previous and new version.)\nCS.Solver.prototype.getVersionDistanceSteps = function (stepBaseName,\n                                                        packageAndVersions,\n                                                        takePatches) {\n  var self = this;\n\n  var incompat = new CS.Solver.Step(stepBaseName + '_incompat');\n  var major = new CS.Solver.Step(stepBaseName + '_major');\n  var minor = new CS.Solver.Step(stepBaseName + '_minor');\n  var patch = new CS.Solver.Step(stepBaseName + '_patch');\n  var rest = new CS.Solver.Step(stepBaseName + '_rest');\n\n  self.Profile.time(\n    \"calculate \" + stepBaseName + \" distance costs\",\n    function () {\n      _.each(packageAndVersions, function (pvArg) {\n        var pkg = pvArg.package;\n        var previousVersion = pvArg.version;\n        var versions = self.getVersions(pkg);\n        if (versions.length >= 2) {\n          var costs = self.pricer.priceVersionsWithPrevious(\n            versions, previousVersion, takePatches);\n          addCostsToSteps(pkg, versions, costs,\n                          [incompat, major, minor, patch, rest]);\n        }\n      });\n    });\n\n  return [incompat, major, minor, patch, rest];\n};\n\nCS.Solver.prototype.currentVersionMap = function () {\n  var self = this;\n  var pvs = [];\n  _.each(self.solution.getTrueVars(), function (x) {\n    if (x.indexOf(' ') >= 0) {\n      // all variables with spaces in them are PackageAndVersions\n      var pv = CS.PackageAndVersion.fromString(x);\n      pvs.push(pv);\n    }\n  });\n\n  var versionMap = {};\n  _.each(pvs, function (pv) {\n    if (_.has(versionMap, pv.package)) {\n      throw new Error(\"Assertion failure: Selected two versions of \" +\n                      pv.package + \", \" +versionMap[pv.package] +\n                      \" and \" + pv.version);\n    }\n    versionMap[pv.package] = pv.version;\n  });\n\n  return versionMap;\n};\n\n// Called to re-assign `self.solution` after a call to `self.logic.solve()`,\n// `solveAssuming`, or `minimize`.\nCS.Solver.prototype.setSolution = function (solution) {\n  var self = this;\n  self.solution = solution;\n  if (! self.solution) {\n    throw new Error(\"Unexpected unsatisfiability\");\n  }\n  // When we query a Solution, we always want to treat unknown variables\n  // as \"false\".  Logic Solver normally throws an error if you ask it\n  // to evaluate a formula containing a variable that isn't found in any\n  // constraints, as a courtesy to help catch bugs, but we treat\n  // variables as an open class of predicates (\"foo\" means package foo\n  // is selected, for example), and we don't ensure that every package\n  // or package version we might ask about is registered with the Solver.\n  // For example, when we go to explain a conflict or generate an error\n  // about an unknown package, we may ask about packages that were\n  // forbidden in an early analysis of the problem and never entered\n  // into the Solver.\n  self.solution.ignoreUnknownVariables();\n};\n\nCS.Solver.prototype.getAnswer = function (options) {\n  var self = this;\n  return self.Profile.time(\"Solver#getAnswer\", function () {\n    return self._getAnswer(options);\n  });\n};\n\nCS.Solver.prototype._getAnswer = function (options) {\n  var self = this;\n  var input = self.input;\n  var analysis = self.analysis;\n  var cache = input.catalogCache;\n  var allAnswers = (options && options.allAnswers); // for tests\n  var Profile = self.Profile;\n\n  var logic;\n  Profile.time(\"new Logic.Solver (MiniSat start-up)\", function () {\n    logic = self.logic = new Logic.Solver();\n  });\n\n  // require root dependencies\n  Profile.time(\"require root dependencies\", function () {\n    _.each(input.dependencies, function (p) {\n      logic.require(p);\n    });\n  });\n\n  // generate package version variables for known, reachable packages\n  Profile.time(\"generate package variables\", function () {\n    _.each(_.keys(analysis.reachablePackages), function (p) {\n      if (! _.has(analysis.packagesWithNoAllowedVersions, p)) {\n        var versionVars = _.map(self.getVersions(p),\n                                function (v) {\n                                  return pvVar(p, v);\n                                });\n        // At most one of [\"foo 1.0.0\", \"foo 1.0.1\", ...] is true.\n        logic.require(Logic.atMostOne(versionVars));\n        // The variable \"foo\" is true if and only if at least one of the\n        // variables [\"foo 1.0.0\", \"foo 1.0.1\", ...] is true.\n        logic.require(Logic.equiv(p, Logic.or(versionVars)));\n      }\n    });\n  });\n\n  // generate strong dependency requirements\n  Profile.time(\"generate dependency requirements\", function () {\n    _.each(_.keys(analysis.reachablePackages), function (p) {\n      _.each(self.getVersions(p), function (v) {\n        _.each(cache.getDependencyMap(p, v), function (dep) {\n          // `dep` is a CS.Dependency\n          if (! dep.isWeak) {\n            var p2 = dep.packageConstraint.package;\n            logic.require(Logic.implies(pvVar(p, v), p2));\n          }\n        });\n      });\n    });\n  });\n\n  // generate constraints -- but technically don't enforce them, because\n  // we haven't forced the conflictVars to be false\n  Profile.time(\"generate constraints\", function () {\n    _.each(analysis.constraints, function (c) {\n      // We logically require that EITHER a constraint is marked as a\n      // conflict OR it comes from a package version that is not selected\n      // OR its constraint formula must be true.\n      // (The constraint formula says that if toPackage is selected,\n      // then a version of it that satisfies our constraint must be true.)\n      logic.require(\n        Logic.or(c.conflictVar,\n                 c.fromVar ? Logic.not(c.fromVar) : [],\n                 self.getConstraintFormula(c.toPackage, c.vConstraint)));\n    });\n  });\n\n  // Establish the invariant of self.solution being a valid solution.\n  // From now on, if we add some new logical requirement to the solver\n  // that isn't necessarily true of `self.solution`, we must\n  // recalculate `self.solution` and pass the new value to\n  // self.setSolution.  It is our job to obtain the new solution in a\n  // way that ensures the solution exists and doesn't put the solver\n  // in an unsatisfiable state.  There are several ways to do this:\n  //\n  // * Calling `logic.solve()` and immediately throwing a fatal error\n  //   if there's no solution (not calling `setSolution` at all)\n  // * Calling `logic.solve()` in a situation where we know we have\n  //   not made the problem unsatisfiable\n  // * Calling `logic.solveAssuming(...)` and checking the result, only\n  //   using the solution if it exists\n  // * Calling `minimize()`, which always maintains satisfiability\n\n  Profile.time(\"pre-solve\", function () {\n    self.setSolution(logic.solve());\n  });\n  // There is always a solution at this point, namely,\n  // select all packages (including unknown packages), select\n  // any version of each known package (excluding packages with\n  // \"no allowed versions\"), and set all conflictVars\n  // to true.\n\n  // Forbid packages with no versions allowed by top-level constraints,\n  // which we didn't do earlier because we needed to establish an\n  // initial solution before asking the solver if it's possible to\n  // not use these packages.\n  Profile.time(\"forbid packages with no matching versions\", function () {\n    _.each(analysis.packagesWithNoAllowedVersions, function (constrs, p) {\n      var newSolution = logic.solveAssuming(Logic.not(p));\n      if (newSolution) {\n        self.setSolution(newSolution);\n        logic.forbid(p);\n      } else {\n        var error =\n          'No version of ' + p + ' satisfies all constraints: ' +\n            _.map(constrs, function (constr) {\n              return '@' + constr.constraintString;\n            }).join(', ');\n        error += '\\n' + self.listConstraintsOnPackage(p);\n        self.errors.push(error);\n      }\n    });\n    self.throwAnyErrors();\n  });\n\n  // try not to use any unknown packages.  If the minimum is greater\n  // than 0, we'll throw an error later, after we apply the constraints\n  // and the cost function, so that we can explain the problem to the\n  // user in a convincing way.\n  self.minimize('unknown_packages', _.keys(analysis.unknownPackages));\n\n  // try not to set the conflictVar on any constraint.  If the minimum\n  // is greater than 0, we'll throw an error later, after we've run the\n  // cost function, so we can show a better error.\n  // If there are conflicts, this minimization can be time-consuming\n  // (several seconds or more).  The strategy 'bottom-up' helps by\n  // looking for solutions with few conflicts first.\n  self.minimize('conflicts', _.pluck(analysis.constraints, 'conflictVar'),\n                { strategy: 'bottom-up' });\n\n  // Try not to use \"unanticipated\" prerelease versions\n  self.minimize('unanticipated_prereleases',\n                analysis.unanticipatedPrereleases);\n\n  var previousRootSteps = self.getVersionDistanceSteps(\n    'previous_root', analysis.previousRootDepVersions);\n  // the \"previous_root_incompat\" step\n  var previousRootIncompat = previousRootSteps[0];\n  // the \"previous_root_major\", \"previous_root_minor\", etc. steps\n  var previousRootVersionParts = previousRootSteps.slice(1);\n\n  var toUpdate = _.filter(input.upgrade, function (p) {\n    return analysis.reachablePackages[p] === true;\n  });\n\n  // make sure packages that are being updated can still count as\n  // a previous_root for the purposes of previous_root_incompat\n  Profile.time(\"add terms to previous_root_incompat\", function () {\n    _.each(toUpdate, function (p) {\n      if (input.isRootDependency(p) && input.isInPreviousSolution(p)) {\n        var parts = self.pricer.partitionVersions(\n          self.getVersions(p), input.previousSolution[p]);\n        _.each(parts.older.concat(parts.higherMajor), function (v) {\n          previousRootIncompat.addTerm(pvVar(p, v), 1);\n        });\n      }\n    });\n  });\n\n  if (! input.allowIncompatibleUpdate) {\n    // Enforce that we don't make breaking changes to your root dependencies,\n    // unless you pass --allow-incompatible-update.  It will actually be enforced\n    // farther down, but for now, we want to apply this constraint before handling\n    // updates.\n    self.minimize(previousRootIncompat);\n  }\n\n  self.minimize(self.getVersionCostSteps(\n    'update', toUpdate, CS.VersionPricer.MODE_UPDATE));\n\n  if (input.allowIncompatibleUpdate) {\n    // If you pass `--allow-incompatible-update`, we will still try to minimize\n    // version changes to root deps that break compatibility, but with a lower\n    // priority than taking as-new-as-possible versions for `meteor update`.\n    self.minimize(previousRootIncompat);\n  }\n\n  self.minimize(previousRootVersionParts);\n\n  var otherPrevious = _.filter(_.map(input.previousSolution, function (v, p) {\n    return new CS.PackageAndVersion(p, v);\n  }), function (pv) {\n    var p = pv.package;\n    return analysis.reachablePackages[p] === true &&\n      ! input.isRootDependency(p);\n  });\n\n  self.minimize(self.getVersionDistanceSteps(\n    'previous_indirect', otherPrevious,\n    input.upgradeIndirectDepPatchVersions));\n\n  var newRootDeps = _.filter(input.dependencies, function (p) {\n    return ! input.isInPreviousSolution(p);\n  });\n\n  self.minimize(self.getVersionCostSteps(\n    'new_root', newRootDeps, CS.VersionPricer.MODE_UPDATE));\n\n  // Lock down versions of all root, previous, and updating packages that\n  // are currently selected.  The reason to do this is to save the solver\n  // a bunch of work (i.e. improve performance) by not asking it to\n  // optimize the \"unimportant\" packages while also twiddling the versions\n  // of the \"important\" packages, which would just multiply the search space.\n  //\n  // The important packages are root deps, packages in the previous solution,\n  // and packages being upgraded.  At this point, we either have unique\n  // versions for them, or else there is some kind of trade-off, like a\n  // situation where raising the version of one package and lowering the\n  // version of another produces the same cost -- a tie between two solutions.\n  // If we have a tie, it probably won't be broken by the unimportant\n  // packages, so we'll end up going with whatever we picked anyway.  (Note\n  // that we have already taken the unimportant packages into account in that\n  // we are only considering solutions where SOME versions can be chosen for\n  // them.)  Even if optimizing the unimportant packages (coming up next)\n  // was able to break a tie in the important packages, we care so little\n  // about the versions of the unimportant packages that it's a very weak\n  // signal.  In other words, the user might be better off with some tie-breaker\n  // that looks only at the important packages anyway.\n  Profile.time(\"lock down important versions\", function () {\n    _.each(self.currentVersionMap(), function (v, pkg) {\n      if (input.isRootDependency(pkg) ||\n          input.isInPreviousSolution(pkg) ||\n          input.isUpgrading(pkg)) {\n        logic.require(Logic.implies(pkg, pvVar(pkg, v)));\n      }\n    });\n  });\n\n  // new, indirect packages are the lowest priority\n  var otherPackages = [];\n  _.each(_.keys(analysis.reachablePackages), function (p) {\n    if (! (input.isRootDependency(p) ||\n           input.isInPreviousSolution(p) ||\n           input.isUpgrading(p))) {\n      otherPackages.push(p);\n    }\n  });\n\n  self.minimize(self.getVersionCostSteps(\n    'new_indirect', otherPackages,\n    CS.VersionPricer.MODE_GRAVITY_WITH_PATCHES));\n\n  self.minimize('total_packages', _.keys(analysis.reachablePackages));\n\n  // throw errors about unknown packages\n  if (self.stepsByName['unknown_packages'].optimum > 0) {\n    Profile.time(\"generate error for unknown packages\", function () {\n      var unknownPackages = _.keys(analysis.unknownPackages);\n      var unknownPackagesNeeded = _.filter(unknownPackages, function (p) {\n        return self.solution.evaluate(p);\n      });\n      _.each(unknownPackagesNeeded, function (p) {\n        var requirers = _.filter(analysis.unknownPackages[p], function (pv) {\n          return self.solution.evaluate(pv);\n        });\n        var errorStr;\n        if (CS.isIsobuildFeaturePackage(p)) {\n          errorStr = 'unsupported Isobuild feature \"' + p + '\"; see ' +\n            'https://github.com/meteor/meteor/wiki/Isobuild-Feature-Packages ' +\n            'for a list of features and the minimum Meteor release required';\n        } else {\n          errorStr = 'unknown package: ' + p;\n        }\n        _.each(requirers, function (pv) {\n          errorStr += '\\nRequired by: ' + pv;\n        });\n        self.errors.push(errorStr);\n      });\n    });\n    self.throwAnyErrors();\n  }\n\n  // throw errors about conflicts\n  if (self.stepsByName['conflicts'].optimum > 0) {\n    self.throwConflicts();\n  }\n\n  if ((! input.allowIncompatibleUpdate) &&\n      self.stepsByName['previous_root_incompat'].optimum > 0) {\n    // we have some \"incompatible root changes\", where we needed to change a\n    // version of a root dependency to a new version incompatible with the\n    // original, but --allow-incompatible-update hasn't been passed in.\n    // these are in the form of PackageAndVersion strings that we need.\n    var incompatRootChanges = _.keys(self.getStepContributions(\n      self.stepsByName['previous_root_incompat']));\n\n    Profile.time(\"generate errors for incompatible root change\", function () {\n      var numActualErrors = 0;\n      _.each(incompatRootChanges, function (pvStr) {\n        var pv = CS.PackageAndVersion.fromString(pvStr);\n        // exclude packages with top-level equality constraints (added by user\n        // or by the tool pinning a version)\n        if (! _.has(analysis.topLevelEqualityConstrainedPackages, pv.package)) {\n          var prevVersion = input.previousSolution[pv.package];\n          self.errors.push(\n            'Potentially incompatible change required to ' +\n              'top-level dependency: ' +\n              pvStr + ', was ' + prevVersion + '.\\n' +\n              self.listConstraintsOnPackage(pv.package));\n          numActualErrors++;\n        }\n      });\n      if (numActualErrors) {\n        self.errors.push(\n          'To allow potentially incompatible changes to top-level ' +\n            'dependencies, you must pass --allow-incompatible-update ' +\n            'on the command line.');\n      }\n    });\n    self.throwAnyErrors();\n  }\n\n  var result = {\n    neededToUseUnanticipatedPrereleases: (\n      self.stepsByName['unanticipated_prereleases'].optimum > 0),\n    answer: Profile.time(\"generate version map\", function () {\n      return self.currentVersionMap();\n    })\n  };\n\n  if (allAnswers) {\n    Profile.time(\"generate all answers\", function () {\n      var allAnswersList = [result.answer];\n      var nextAnswer = function () {\n        var formula = self.solution.getFormula();\n        var newSolution = logic.solveAssuming(Logic.not(formula));\n        if (newSolution) {\n          self.setSolution(newSolution);\n          logic.forbid(formula);\n        }\n        return newSolution;\n      };\n      while (nextAnswer()) {\n        allAnswersList.push(self.currentVersionMap());\n      }\n      result.allAnswers = allAnswersList;\n    });\n  };\n\n  return result;\n};\n\n// Get a list of package-version variables that satisfy a given constraint.\nvar getOkVersions = function (toPackage, vConstraint, targetVersions) {\n  return _.compact(_.map(targetVersions, function (v) {\n    if (CS.isConstraintSatisfied(toPackage, vConstraint, v)) {\n      return pvVar(toPackage, v);\n    } else {\n      return null;\n    }\n  }));\n};\n\n// The CS.Solver constructor turns this into a memoized method.\n// Memoizing the Formula object reduces clause generation a lot.\nvar _getConstraintFormula = function (toPackage, vConstraint) {\n  var self = this;\n\n  var targetVersions = self.getVersions(toPackage);\n  var okVersions = getOkVersions(toPackage, vConstraint, targetVersions);\n\n  if (okVersions.length === targetVersions.length) {\n    return Logic.TRUE;\n  } else {\n    return Logic.or(Logic.not(toPackage), okVersions);\n  }\n};\n\nCS.Solver.prototype.listConstraintsOnPackage = function (pkg) {\n  var self = this;\n  var constraints = self.analysis.constraints;\n\n  var result = 'Constraints on package \"' + pkg + '\":';\n\n  _.each(constraints, function (c) {\n    if (c.toPackage === pkg) {\n      var paths;\n      if (c.fromVar) {\n        paths = self.getPathsToPackageVersion(\n          CS.PackageAndVersion.fromString(c.fromVar));\n      } else {\n        paths = [['top level']];\n      }\n      _.each(paths, function (path) {\n        result += '\\n* ' + (new PV.PackageConstraint(\n          pkg, c.vConstraint.raw)) + ' <- ' + path.join(' <- ');\n      });\n    }\n  });\n\n  return result;\n};\n\nCS.Solver.prototype.throwConflicts = function () {\n  var self = this;\n\n  var solution = self.solution;\n  var constraints = self.analysis.constraints;\n\n  self.Profile.time(\"generate error about conflicts\", function () {\n    _.each(constraints, function (c) {\n      // c is a CS.Solver.Constraint\n      if (solution.evaluate(c.conflictVar)) {\n        // skipped this constraint\n        var possibleVersions = self.getVersions(c.toPackage);\n        var chosenVersion = _.find(possibleVersions, function (v) {\n          return solution.evaluate(pvVar(c.toPackage, v));\n        });\n        if (! chosenVersion) {\n          // this can't happen, because for a constraint to be a problem,\n          // we must have chosen some version of the package it applies to!\n          throw new Error(\"Internal error: Version not found\");\n        }\n        var error = (\n          'Conflict: Constraint ' + (new PV.PackageConstraint(\n            c.toPackage, c.vConstraint)) +\n            ' is not satisfied by ' + c.toPackage + ' ' + chosenVersion + '.');\n\n        error += '\\n' + self.listConstraintsOnPackage(c.toPackage);\n\n        // Avoid printing exactly the same error twice.  eg, if we have two\n        // different packages which have the same unsatisfiable constraint.\n        if (self.errors.indexOf(error) === -1) {\n          self.errors.push(error);\n        }\n      }\n    });\n  });\n\n  // always throws, never returns\n  self.throwAnyErrors();\n\n  throw new Error(\"Internal error: conflicts could not be explained\");\n};\n\n// Takes a PackageVersion and returns an array of arrays of PackageVersions.\n// If the `packageVersion` is not selected in `self.solution`, returns\n// an empty array.  Otherwise, returns an array of all paths from\n// root dependencies to the package, in reverse order.  In other words,\n// the first element of each path is `packageVersion`,\n// and the last element is the selected version of a root dependency.\n//\n// Ok, it isn't all paths.  Because that would be crazy (combinatorial\n// explosion).  It stops at root dependencies and tries to filter out\n// ones that are definitely longer than another.\nCS.Solver.prototype.getPathsToPackageVersion = function (packageAndVersion) {\n  check(packageAndVersion, CS.PackageAndVersion);\n  var self = this;\n  var input = self.input;\n  var cache = input.catalogCache;\n  var solution = self.solution;\n\n  var versionMap = self.currentVersionMap();\n  var hasDep = function (p1, p2) {\n    // Include weak dependencies, because their constraints matter.\n    return _.has(cache.getDependencyMap(p1, versionMap[p1]), p2);\n  };\n  var allPackages = _.keys(versionMap);\n\n  var getPaths = function (pv, _ignorePackageSet) {\n    if (! solution.evaluate(pv.toString())) {\n      return [];\n    }\n    var pkg = pv.package;\n\n    if (input.isRootDependency(pkg)) {\n      return [[pv]];\n    }\n\n    var newIgnorePackageSet = _.clone(_ignorePackageSet);\n    newIgnorePackageSet[pkg] = true;\n\n    var paths = [];\n    var shortestLength = null;\n\n    _.each(allPackages, function (p) {\n      if ((! _.has(newIgnorePackageSet, p)) &&\n          solution.evaluate(p) &&\n          hasDep(p, pkg)) {\n        var newPV = new CS.PackageAndVersion(p, versionMap[p]);\n        _.each(getPaths(newPV, newIgnorePackageSet), function (path) {\n          var newPath = [pv].concat(path);\n          if ((! paths.length) || newPath.length < shortestLength) {\n            paths.push(newPath);\n            shortestLength = newPath.length;\n          }\n        });\n      }\n    });\n\n    return paths;\n  };\n\n  return getPaths(packageAndVersion, {});\n};\n\n\nCS.Solver.Constraint = function (fromVar, toPackage, vConstraint, conflictVar) {\n  this.fromVar = fromVar;\n  this.toPackage = toPackage;\n  this.vConstraint = vConstraint;\n  this.conflictVar = conflictVar;\n\n  // this.fromVar is a return value of pvVar(p, v), or null for a\n  // top-level constraint\n  check(this.fromVar, Match.OneOf(String, null));\n  check(this.toPackage, String); // package name\n  check(this.vConstraint, PV.VersionConstraint);\n  check(this.conflictVar, String);\n};\n"
  },
  {
    "path": "packages/constraint-solver/stack-overflow-bug-test-data.js",
    "content": "STACK_OVERFLOW_BUG_INPUT = {\n  \"dependencies\": [\n    \"meteor-platform\",\n    \"autopublish\",\n    \"insecure\",\n    \"avital:react-in-blaze\",\n    \"less\",\n    \"follower-livedata\"\n  ],\n  \"constraints\": [\n    \"meteor-platform\",\n    \"autopublish\",\n    \"insecure\",\n    \"avital:react-in-blaze\",\n    \"less\",\n    \"follower-livedata@0.9.0\",\n    \"accounts-base@=1.2.0-rc.0\",\n    \"accounts-facebook@=1.0.4-rc.0\",\n    \"accounts-github@=1.0.4-rc.0\",\n    \"accounts-google@=1.0.4-rc.0\",\n    \"accounts-meetup@=1.0.4-rc.0\",\n    \"accounts-meteor-developer@=1.0.4-rc.0\",\n    \"accounts-oauth@=1.1.4-rc.0\",\n    \"accounts-password@=1.1.0-rc.0\",\n    \"accounts-twitter@=1.0.4-rc.0\",\n    \"accounts-ui-unstyled@=1.1.7-rc.0\",\n    \"accounts-ui@=1.1.5-rc.0\",\n    \"accounts-weibo@=1.0.4-rc.0\",\n    \"appcache@=1.0.4-rc.0\",\n    \"audit-argument-checks@=1.0.3-rc.0\",\n    \"autopublish@=1.0.3-rc.0\",\n    \"autoupdate@=1.2.0-rc.0\",\n    \"base64@=1.0.3-rc.0\",\n    \"binary-heap@=1.0.3-rc.0\",\n    \"blaze-tools@=1.0.3-rc.0\",\n    \"blaze@=2.1.0-rc.0\",\n    \"boilerplate-generator@=1.0.3-rc.0\",\n    \"browser-policy-common@=1.0.3-rc.0\",\n    \"browser-policy-content@=1.0.4-rc.0\",\n    \"browser-policy-framing@=1.0.4-rc.0\",\n    \"browser-policy@=1.0.4-rc.0\",\n    \"callback-hook@=1.0.3-rc.0\",\n    \"check@=1.0.5-rc.0\",\n    \"code-prettify@=1.0.3-rc.0\",\n    \"coffeescript-test-helper@=1.0.3-rc.0\",\n    \"coffeescript@=1.0.6-rc.0\",\n    \"constraint-solver@=1.0.19-rc.0\",\n    \"ddp@=1.1.0-rc.0\",\n    \"deps@=1.0.7-rc.0\",\n    \"disable-oplog@=1.0.3-rc.0\",\n    \"ejson@=1.0.6-rc.0\",\n    \"email@=1.0.6-rc.0\",\n    \"facebook@=1.1.4-rc.0\",\n    \"facts@=1.0.4-rc.0\",\n    \"fastclick@=1.0.3-rc.0\",\n    \"force-ssl@=1.0.4-rc.0\",\n    \"geojson-utils@=1.0.3-rc.0\",\n    \"github@=1.1.3-rc.0\",\n    \"google@=1.1.5-rc.0\",\n    \"handlebars@=1.0.3-rc.0\",\n    \"html-tools@=1.0.4-rc.0\",\n    \"htmljs@=1.0.4-rc.0\",\n    \"http@=1.1.0-rc.0\",\n    \"id-map@=1.0.3-rc.0\",\n    \"insecure@=1.0.3-rc.0\",\n    \"jquery-waypoints@=1.0.3-rc.0\",\n    \"jquery@=1.11.3-rc.0_2\",\n    \"js-analyze-tests@=1.0.3-rc.0\",\n    \"js-analyze@=1.0.5-rc.0\",\n    \"json@=1.0.3-rc.0\",\n    \"jsparse@=1.0.3-rc.0\",\n    \"launch-screen@=1.0.2-rc.0\",\n    \"less@=1.0.14-rc.0\",\n    \"livedata@=1.0.13-rc.0\",\n    \"localstorage@=1.0.3-rc.0\",\n    \"logging@=1.0.7-rc.0\",\n    \"logic-solver@=1.0.0-rc.0\",\n    \"markdown@=1.0.4-rc.0\",\n    \"meetup@=1.1.3-rc.0\",\n    \"meteor-developer@=1.1.3-rc.0\",\n    \"meteor-platform@=1.2.2-rc.0\",\n    \"meteor@=1.1.5-rc.0\",\n    \"meyerweb-reset@=1.0.3-rc.0\",\n    \"minifiers@=1.1.5-rc.0\",\n    \"minimongo@=1.0.7-rc.0\",\n    \"mobile-status-bar@=1.0.3-rc.0\",\n    \"mongo-livedata@=1.0.8-rc.0\",\n    \"mongo@=1.1.0-rc.0\",\n    \"oauth-encryption@=1.0.3-rc.0\",\n    \"oauth@=1.1.4-rc.0\",\n    \"oauth1@=1.1.4-rc.0\",\n    \"oauth2@=1.1.3-rc.0\",\n    \"observe-sequence@=1.0.5-rc.0\",\n    \"ordered-dict@=1.0.3-rc.0\",\n    \"package-stats-opt-out@=1.0.3-rc.0\",\n    \"package-version-parser@=3.0.3-rc.0\",\n    \"preserve-inputs@=1.0.3-rc.0\",\n    \"random@=1.0.3-rc.0\",\n    \"reactive-dict@=1.1.0-rc.0\",\n    \"reactive-var@=1.0.5-rc.0\",\n    \"reload-safetybelt@=1.0.3-rc.0\",\n    \"reload@=1.1.3-rc.0\",\n    \"retry@=1.0.3-rc.0\",\n    \"routepolicy@=1.0.5-rc.0\",\n    \"service-configuration@=1.0.4-rc.0\",\n    \"session@=1.1.0-rc.0\",\n    \"sha@=1.0.3-rc.0\",\n    \"showdown@=1.0.4-rc.0\",\n    \"spacebars-compiler@=1.0.5-rc.0\",\n    \"spacebars-tests@=1.0.3-rc.0\",\n    \"spacebars@=1.0.6-rc.0\",\n    \"spiderable@=1.0.7-rc.0\",\n    \"srp@=1.0.3-rc.0\",\n    \"standard-app-packages@=1.0.5-rc.0\",\n    \"startup@=1.0.3-rc.0\",\n    \"stylus@=1.0.7-rc.0\",\n    \"templating@=1.1.1-rc.0\",\n    \"test-helpers@=1.0.4-rc.0\",\n    \"test-in-browser@=1.0.7-rc.0\",\n    \"test-in-console@=1.0.5-rc.0\",\n    \"test-server-tests-in-console-once@=1.0.3-rc.0\",\n    \"tinytest@=1.0.5-rc.0\",\n    \"tracker@=1.0.6-rc.0\",\n    \"twitter@=1.1.4-rc.0\",\n    \"ui@=1.0.6-rc.0\",\n    \"underscore-tests@=1.0.3-rc.0\",\n    \"underscore@=1.0.3-rc.0\",\n    \"url@=1.0.4-rc.0\",\n    \"webapp-hashing@=1.0.3-rc.0\",\n    \"webapp@=1.2.0-rc.0\",\n    \"weibo@=1.1.3-rc.0\",\n    \"xmlbuilder@=2.4.6-rc.0\"\n  ],\n  \"catalogCache\": {\n    \"data\": {\n      \"xmlbuilder 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"xmlbuilder 2.4.4-pre.0\": [\n        \"meteor@1.1.2-pre.3\"\n      ],\n      \"xmlbuilder 2.4.4-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"xmlbuilder 2.4.4-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"xmlbuilder 2.4.4\": [\n        \"meteor@1.1.2\"\n      ],\n      \"xmlbuilder 2.4.5-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"xmlbuilder 2.4.5-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"xmlbuilder 2.4.5-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"xmlbuilder 2.4.5-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"xmlbuilder 2.4.5-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"xmlbuilder 2.4.5-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"xmlbuilder 2.4.5-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"xmlbuilder 2.4.5-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"xmlbuilder 2.4.5-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"xmlbuilder 2.4.5-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"xmlbuilder 2.4.5-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"xmlbuilder 2.4.5-winr.1\": [\n        \"meteor@1.1.5-winr.3\"\n      ],\n      \"xmlbuilder 2.4.5-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"xmlbuilder 2.4.5\": [\n        \"meteor@1.1.4\"\n      ],\n      \"xmlbuilder 2.4.6-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"xmlbuilder 2.4.6-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"xmlbuilder 2.4.6-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"xmlbuilder 2.4.6-winr.2\": [\n        \"meteor@1.1.5-winr.6\"\n      ],\n      \"weibo 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"oauth2@10.0.0-glasser.isopacket.0\",\n        \"oauth@10.0.0-glasser.isopacket.0\",\n        \"http@10.0.0-glasser.isopacket.0\",\n        \"service-configuration@10.0.0-glasser.isopacket.0\",\n        \"templating@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\"\n      ],\n      \"weibo 1.0.0\": [\n        \"http@1.0.2\",\n        \"meteor@1.0.2\",\n        \"oauth@1.0.0\",\n        \"oauth2@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.0\",\n        \"templating@1.0.4\"\n      ],\n      \"weibo 1.0.1-glasser1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"weibo 1.0.1-rc0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"weibo 1.0.1\": [\n        \"http@1.0.4\",\n        \"meteor@1.0.3\",\n        \"oauth@1.0.1\",\n        \"oauth2@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.5\"\n      ],\n      \"weibo 1.0.2-ekate\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"weibo 1.1.0-rc0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"weibo 1.1.0\": [\n        \"http@1.0.5\",\n        \"meteor@1.1.0\",\n        \"oauth@1.1.0\",\n        \"oauth2@1.1.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.6\"\n      ],\n      \"weibo 1.1.1-pre.0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"weibo 1.1.1-pre.1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"weibo 1.1.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"oauth2@1.1.1-pre.2\",\n        \"oauth@1.1.1-pre.2\",\n        \"http@1.0.7-pre.2\",\n        \"service-configuration@1.0.2-pre.2\",\n        \"templating@1.0.8-pre.2\",\n        \"random@1.0.1-pre.2\"\n      ],\n      \"weibo 1.1.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"oauth2@1.1.1-rc.0\",\n        \"oauth@1.1.1-rc.0\",\n        \"http@1.0.7-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"templating@1.0.8-rc.0\",\n        \"random@1.0.1-rc.0\"\n      ],\n      \"weibo 1.1.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"oauth2@1.1.1-win.0\",\n        \"oauth@1.1.2-win.0\",\n        \"http@1.0.8-win.0\",\n        \"service-configuration@1.0.2-win.0\",\n        \"templating@1.0.9-win.0\",\n        \"random@1.0.1-win.0\"\n      ],\n      \"weibo 1.1.1\": [\n        \"meteor@1.1.2\",\n        \"oauth2@1.1.1\",\n        \"oauth@1.1.1\",\n        \"http@1.0.7\",\n        \"service-configuration@1.0.2\",\n        \"templating@1.0.8\",\n        \"random@1.0.1\"\n      ],\n      \"weibo 1.1.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"oauth2@1.1.2-ipc.0\",\n        \"oauth@1.1.3-ipc.0\",\n        \"http@1.0.9-ipc.0\",\n        \"service-configuration@1.0.3-ipc.0\",\n        \"templating@1.0.10-ipc.0\",\n        \"random@1.0.2-ipc.0\"\n      ],\n      \"weibo 1.1.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"oauth2@1.1.2-rc.1\",\n        \"oauth@1.1.3-rc.1\",\n        \"http@1.0.9-rc.1\",\n        \"service-configuration@1.0.3-rc.1\",\n        \"templating@1.0.10-rc.1\",\n        \"random@1.0.2-rc.1\"\n      ],\n      \"weibo 1.1.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"oauth2@1.1.2-slava.0\",\n        \"oauth@1.1.3-slava.0\",\n        \"http@1.0.9-slava.0\",\n        \"service-configuration@1.0.3-slava.0\",\n        \"templating@1.0.10-slava.0\",\n        \"random@1.0.2-slava.0\"\n      ],\n      \"weibo 1.1.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"oauth2@1.1.2-win.0\",\n        \"oauth@1.1.3-win.0\",\n        \"http@1.0.9-win.0\",\n        \"service-configuration@1.0.3-win.0\",\n        \"templating@1.0.10-win.0\",\n        \"random@1.0.2-win.0\"\n      ],\n      \"weibo 1.1.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"oauth2@1.1.2-winr.0\",\n        \"oauth@1.1.3-winr.0\",\n        \"http@1.0.9-winr.0\",\n        \"service-configuration@1.0.3-winr.0\",\n        \"templating@1.0.10-winr.0\",\n        \"random@1.0.2-winr.0\"\n      ],\n      \"weibo 1.1.2\": [\n        \"meteor@1.1.4\",\n        \"oauth2@1.1.2\",\n        \"oauth@1.1.3\",\n        \"http@1.0.9\",\n        \"service-configuration@1.0.3\",\n        \"templating@1.0.10\",\n        \"random@1.0.2\"\n      ],\n      \"weibo 1.1.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"oauth2@1.1.3-winr.2\",\n        \"oauth@1.1.4-winr.2\",\n        \"http@1.0.10-eachin.0\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"templating@1.0.11-eachin.0\",\n        \"random@1.0.3-eachin.0\"\n      ],\n      \"weibo 1.1.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"oauth2@1.1.3-eachin.43\",\n        \"oauth@1.1.4-eachin.43\",\n        \"http@1.0.10-eachin.43\",\n        \"service-configuration@1.0.4-eachin.43\",\n        \"templating@1.0.12-eachin.43\",\n        \"random@1.0.3-eachin.43\"\n      ],\n      \"weibo 1.1.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"oauth2@1.1.3-githubble.0\",\n        \"oauth@1.1.4-githubble.0\",\n        \"http@1.0.10-githubble.0\",\n        \"service-configuration@1.0.4-githubble.0\",\n        \"templating@1.0.12-githubble.0\",\n        \"random@1.0.3-githubble.0\"\n      ],\n      \"weibo 1.1.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"oauth2@1.1.3-githubble.2\",\n        \"oauth@1.1.4-githubble.2\",\n        \"http@1.0.10-githubble.2\",\n        \"service-configuration@1.0.4-githubble.2\",\n        \"templating@1.0.12-githubble.2\",\n        \"random@1.0.3-githubble.2\"\n      ],\n      \"weibo 1.1.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"oauth2@1.1.3-githubble.42\",\n        \"oauth@1.1.4-githubble.42\",\n        \"http@1.0.10-githubble.42\",\n        \"service-configuration@1.0.4-githubble.42\",\n        \"templating@1.0.12-githubble.42\",\n        \"random@1.0.3-githubble.42\"\n      ],\n      \"weibo 1.1.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"oauth2@1.1.3-githubble.43\",\n        \"oauth@1.1.4-githubble.43\",\n        \"http@1.0.10-githubble.43\",\n        \"service-configuration@1.0.4-githubble.43\",\n        \"templating@1.0.12-githubble.43\",\n        \"random@1.0.3-githubble.43\"\n      ],\n      \"weibo 1.1.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"oauth2@1.1.3-rc.0\",\n        \"oauth@1.1.4-rc.0\",\n        \"http@1.1.0-rc.0\",\n        \"service-configuration@1.0.4-rc.0\",\n        \"templating@1.1.0-rc.0\",\n        \"random@1.0.3-rc.0\"\n      ],\n      \"weibo 1.1.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"oauth2@1.1.3-winr.0\",\n        \"oauth@1.1.4-winr.0\",\n        \"http@1.0.10-winr.0\",\n        \"service-configuration@1.0.4-winr.0\",\n        \"templating@1.0.11-winr.0\",\n        \"random@1.0.3-winr.0\"\n      ],\n      \"weibo 1.1.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"oauth2@1.1.3-winr.1\",\n        \"oauth@1.1.4-winr.1\",\n        \"http@1.0.10-winr.1\",\n        \"service-configuration@1.0.4-winr.1\",\n        \"templating@1.0.11-winr.1\",\n        \"random@1.0.3-winr.1\"\n      ],\n      \"weibo 1.1.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"oauth2@1.1.3-winr.2\",\n        \"oauth@1.1.4-winr.2\",\n        \"http@1.0.10-winr.4\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"templating@1.0.11-winr.4\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"weibo 1.1.3-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"oauth2@1.1.3-winr.2\",\n        \"oauth@1.1.4-winr.3\",\n        \"http@1.0.11-winr.5\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"templating@1.0.12-winr.7\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"webapp 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"logging@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"routepolicy@10.0.0-glasser.isopacket.0\",\n        \"boilerplate-generator@10.0.0-glasser.isopacket.0\",\n        \"spacebars@10.0.0-glasser.isopacket.0\",\n        \"htmljs@10.0.0-glasser.isopacket.0\",\n        \"blaze@10.0.0-glasser.isopacket.0\",\n        \"webapp-hashing@10.0.0-glasser.isopacket.0\",\n        \"application-configuration@10.0.0-glasser.isopacket.0\",\n        \"follower-livedata@10.0.0-glasser.isopacket.0\"\n      ],\n      \"webapp 1.0.0\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"spacebars-compiler\",\n        \"spacebars\",\n        \"htmljs\",\n        \"ui\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.0.1\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"spacebars-compiler\",\n        \"spacebars\",\n        \"htmljs\",\n        \"ui\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.0.2-a-simple-test\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"spacebars-compiler\",\n        \"spacebars\",\n        \"htmljs\",\n        \"ui\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.0.2-cordova1\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"boilerplate-generator\",\n        \"webapp-hashing\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.0.2-cordova4\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"boilerplate-generator\",\n        \"webapp-hashing\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.0.2-ekate3\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"spacebars-compiler\",\n        \"spacebars\",\n        \"htmljs\",\n        \"ui\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.0.2-glasser1\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"spacebars-compiler\",\n        \"spacebars\",\n        \"htmljs\",\n        \"ui\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.0.2\": [\n        \"application-configuration@1.0.0\",\n        \"follower-livedata@1.0.0\",\n        \"htmljs@1.0.0\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.2\",\n        \"routepolicy@1.0.0\",\n        \"spacebars@1.0.0\",\n        \"spacebars-compiler@1.0.1\",\n        \"ui@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"webapp 1.0.3-glasser1\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"boilerplate-generator\",\n        \"spacebars\",\n        \"htmljs\",\n        \"blaze\",\n        \"webapp-hashing\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.0.3-rc0\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"spacebars-compiler\",\n        \"spacebars\",\n        \"htmljs\",\n        \"blaze\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.0.3\": [\n        \"application-configuration@1.0.1\",\n        \"blaze@2.0.0\",\n        \"follower-livedata@1.0.1\",\n        \"htmljs@1.0.0\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.3\",\n        \"routepolicy@1.0.0\",\n        \"spacebars@1.0.1\",\n        \"spacebars-compiler@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"webapp 1.0.4-ekate\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"boilerplate-generator\",\n        \"spacebars\",\n        \"htmljs\",\n        \"blaze\",\n        \"webapp-hashing\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.1.0-rc1\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"boilerplate-generator\",\n        \"spacebars\",\n        \"htmljs\",\n        \"blaze\",\n        \"webapp-hashing\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.1.1-rc1\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"boilerplate-generator\",\n        \"spacebars\",\n        \"htmljs\",\n        \"blaze\",\n        \"webapp-hashing\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.1.1-rc2\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"boilerplate-generator\",\n        \"spacebars\",\n        \"htmljs\",\n        \"blaze\",\n        \"webapp-hashing\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.1.1-rc3\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"boilerplate-generator\",\n        \"spacebars\",\n        \"htmljs\",\n        \"blaze\",\n        \"webapp-hashing\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.1.1-rc4\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"boilerplate-generator\",\n        \"spacebars\",\n        \"htmljs\",\n        \"blaze\",\n        \"webapp-hashing\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.1.1\": [\n        \"application-configuration@1.0.2\",\n        \"blaze@2.0.0\",\n        \"boilerplate-generator@1.0.0\",\n        \"follower-livedata@1.0.1\",\n        \"htmljs@1.0.1\",\n        \"logging@1.0.3\",\n        \"meteor@1.1.0\",\n        \"routepolicy@1.0.1\",\n        \"spacebars@1.0.1\",\n        \"underscore@1.0.0\",\n        \"webapp-hashing@1.0.0\"\n      ],\n      \"webapp 1.1.2-rc0\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"boilerplate-generator\",\n        \"spacebars\",\n        \"htmljs\",\n        \"blaze\",\n        \"webapp-hashing\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.1.2\": [\n        \"application-configuration@1.0.2\",\n        \"blaze@2.0.1\",\n        \"boilerplate-generator@1.0.0\",\n        \"follower-livedata@1.0.1\",\n        \"htmljs@1.0.1\",\n        \"logging@1.0.3\",\n        \"meteor@1.1.1\",\n        \"routepolicy@1.0.1\",\n        \"spacebars@1.0.2\",\n        \"underscore@1.0.0\",\n        \"webapp-hashing@1.0.0\"\n      ],\n      \"webapp 1.1.3-nim.0\": [\n        \"meteor@1.1.2-nim.0\",\n        \"logging@1.0.4-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"routepolicy@1.0.2-rc.0\",\n        \"boilerplate-generator@1.0.1-rc.0\",\n        \"spacebars@1.0.3-rc.0\",\n        \"htmljs@1.0.2-rc.0\",\n        \"blaze@2.0.2-rc.0\",\n        \"webapp-hashing@1.0.1-rc.0\",\n        \"application-configuration@1.0.3-rc.0\",\n        \"follower-livedata@1.0.2-rc.0\"\n      ],\n      \"webapp 1.1.3-pre.0\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"boilerplate-generator\",\n        \"spacebars\",\n        \"htmljs\",\n        \"blaze\",\n        \"webapp-hashing\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.1.3-pre.1\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"routepolicy\",\n        \"boilerplate-generator\",\n        \"spacebars\",\n        \"htmljs\",\n        \"blaze\",\n        \"webapp-hashing\",\n        \"application-configuration\",\n        \"follower-livedata\"\n      ],\n      \"webapp 1.1.3-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"logging@1.0.4-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"routepolicy@1.0.2-pre.2\",\n        \"boilerplate-generator@1.0.1-pre.2\",\n        \"spacebars@1.0.3-pre.2\",\n        \"htmljs@1.0.2-pre.2\",\n        \"blaze@2.0.2-pre.2\",\n        \"webapp-hashing@1.0.1-pre.2\",\n        \"application-configuration@1.0.3-pre.2\",\n        \"follower-livedata@1.0.2-pre.2\"\n      ],\n      \"webapp 1.1.3-pre.3\": [\n        \"meteor@1.1.2-pre.3\",\n        \"logging@1.0.4-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"routepolicy@1.0.2-pre.2\",\n        \"boilerplate-generator@1.0.1-pre.3\",\n        \"spacebars@1.0.3-pre.2\",\n        \"htmljs@1.0.2-pre.3\",\n        \"blaze@2.0.2-pre.2\",\n        \"webapp-hashing@1.0.1-pre.2\",\n        \"application-configuration@1.0.3-pre.2\",\n        \"follower-livedata@1.0.2-pre.2\"\n      ],\n      \"webapp 1.1.3-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"logging@1.0.4-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"routepolicy@1.0.2-rc.0\",\n        \"boilerplate-generator@1.0.1-rc.0\",\n        \"spacebars@1.0.3-rc.0\",\n        \"htmljs@1.0.2-rc.0\",\n        \"blaze@2.0.2-rc.0\",\n        \"webapp-hashing@1.0.1-rc.0\",\n        \"application-configuration@1.0.3-rc.0\",\n        \"follower-livedata@1.0.2-rc.0\"\n      ],\n      \"webapp 1.1.3-rc.1\": [\n        \"meteor@1.1.2-ekate.1\",\n        \"logging@1.0.4-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"routepolicy@1.0.2-rc.0\",\n        \"boilerplate-generator@1.0.1-rc.0\",\n        \"spacebars@1.0.3-rc.0\",\n        \"htmljs@1.0.2-rc.0\",\n        \"blaze@2.0.2-rc.0\",\n        \"webapp-hashing@1.0.1-rc.0\",\n        \"application-configuration@1.0.3-rc.0\",\n        \"follower-livedata@1.0.2-rc.0\"\n      ],\n      \"webapp 1.1.3-rc.2\": [\n        \"meteor@1.1.2-rc.3\",\n        \"logging@1.0.4-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"routepolicy@1.0.2-rc.0\",\n        \"boilerplate-generator@1.0.1-rc.0\",\n        \"spacebars@1.0.3-rc.0\",\n        \"htmljs@1.0.2-rc.0\",\n        \"blaze@2.0.2-rc.0\",\n        \"webapp-hashing@1.0.1-rc.0\",\n        \"application-configuration@1.0.3-rc.0\",\n        \"follower-livedata@1.0.2-rc.0\"\n      ],\n      \"webapp 1.1.3\": [\n        \"meteor@1.1.2\",\n        \"logging@1.0.4\",\n        \"underscore@1.0.1\",\n        \"routepolicy@1.0.2\",\n        \"boilerplate-generator@1.0.1\",\n        \"spacebars@1.0.3\",\n        \"htmljs@1.0.2\",\n        \"blaze@2.0.2\",\n        \"webapp-hashing@1.0.1\",\n        \"application-configuration@1.0.3\",\n        \"follower-livedata@1.0.2\"\n      ],\n      \"webapp 1.1.4-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"logging@1.0.5-rc.0\",\n        \"underscore@1.0.1\",\n        \"routepolicy@1.0.2\",\n        \"boilerplate-generator@1.0.1\",\n        \"spacebars@1.0.3\",\n        \"htmljs@1.0.2\",\n        \"blaze@2.0.3-rc.0\",\n        \"webapp-hashing@1.0.1\",\n        \"application-configuration@1.0.3\",\n        \"follower-livedata@1.0.2\"\n      ],\n      \"webapp 1.1.4-rc.1\": [\n        \"meteor@1.1.3-rc.0\",\n        \"logging@1.0.5-rc.0\",\n        \"underscore@1.0.1\",\n        \"routepolicy@1.0.2\",\n        \"boilerplate-generator@1.0.1\",\n        \"spacebars@1.0.3\",\n        \"htmljs@1.0.2\",\n        \"blaze@2.0.3-rc.0\",\n        \"webapp-hashing@1.0.1\",\n        \"application-configuration@1.0.3\",\n        \"follower-livedata@1.0.2\"\n      ],\n      \"webapp 1.1.4-rc.2\": [\n        \"meteor@1.1.3-rc.0\",\n        \"logging@1.0.5-rc.0\",\n        \"underscore@1.0.1\",\n        \"routepolicy@1.0.2\",\n        \"boilerplate-generator@1.0.1\",\n        \"spacebars@1.0.3\",\n        \"htmljs@1.0.2\",\n        \"blaze@2.0.3-rc.0\",\n        \"webapp-hashing@1.0.1\",\n        \"application-configuration@1.0.3\",\n        \"follower-livedata@1.0.2\"\n      ],\n      \"webapp 1.1.4-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"logging@1.0.5-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"routepolicy@1.0.2-win.0\",\n        \"boilerplate-generator@1.0.1-win.0\",\n        \"spacebars@1.0.3-win.0\",\n        \"htmljs@1.0.2-win.0\",\n        \"blaze@2.0.3-win.0\",\n        \"webapp-hashing@1.0.1-win.0\",\n        \"application-configuration@1.0.3-win.0\",\n        \"follower-livedata@1.0.2-win.0\"\n      ],\n      \"webapp 1.1.4\": [\n        \"meteor@1.1.3\",\n        \"logging@1.0.5\",\n        \"underscore@1.0.1\",\n        \"routepolicy@1.0.2\",\n        \"boilerplate-generator@1.0.1\",\n        \"spacebars@1.0.3\",\n        \"htmljs@1.0.2\",\n        \"blaze@2.0.3\",\n        \"webapp-hashing@1.0.1\",\n        \"application-configuration@1.0.3\",\n        \"follower-livedata@1.0.2\"\n      ],\n      \"webapp 1.1.5-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"logging@1.0.6-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"routepolicy@1.0.3-ipc.0\",\n        \"boilerplate-generator@1.0.2-ipc.0\",\n        \"spacebars@1.0.4-ipc.0\",\n        \"htmljs@1.0.3-ipc.0\",\n        \"blaze@2.0.4-ipc.0\",\n        \"webapp-hashing@1.0.2-ipc.0\",\n        \"application-configuration@1.0.4-ipc.0\",\n        \"follower-livedata@1.0.3-ipc.0\"\n      ],\n      \"webapp 1.1.5-ipc.1\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"logging@1.0.6-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"routepolicy@1.0.3-ipc.0\",\n        \"boilerplate-generator@1.0.2-ipc.0\",\n        \"spacebars@1.0.4-ipc.0\",\n        \"htmljs@1.0.3-ipc.0\",\n        \"blaze@2.0.4-ipc.1\",\n        \"webapp-hashing@1.0.2-ipc.0\",\n        \"application-configuration@1.0.4-ipc.0\",\n        \"follower-livedata@1.0.3-ipc.0\"\n      ],\n      \"webapp 1.1.5-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"logging@1.0.6-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"routepolicy@1.0.3-rc.1\",\n        \"boilerplate-generator@1.0.2-rc.1\",\n        \"spacebars@1.0.4-rc.1\",\n        \"htmljs@1.0.3-rc.1\",\n        \"blaze@2.0.4-rc.1\",\n        \"webapp-hashing@1.0.2-rc.1\",\n        \"application-configuration@1.0.4-rc.1\",\n        \"follower-livedata@1.0.3-rc.1\"\n      ],\n      \"webapp 1.1.5-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"logging@1.0.6-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"routepolicy@1.0.3-slava.0\",\n        \"boilerplate-generator@1.0.2-slava.0\",\n        \"spacebars@1.0.4-slava.0\",\n        \"htmljs@1.0.3-slava.0\",\n        \"blaze@2.0.4-slava.0\",\n        \"webapp-hashing@1.0.2-slava.0\",\n        \"application-configuration@1.0.4-slava.0\",\n        \"follower-livedata@1.0.3-slava.0\"\n      ],\n      \"webapp 1.1.5-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"logging@1.0.6-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"routepolicy@1.0.3-win.0\",\n        \"boilerplate-generator@1.0.2-win.0\",\n        \"spacebars@1.0.4-win.0\",\n        \"htmljs@1.0.3-win.0\",\n        \"blaze@2.0.4-win.0\",\n        \"webapp-hashing@1.0.2-win.0\",\n        \"application-configuration@1.0.4-win.0\",\n        \"follower-livedata@1.0.3-win.0\"\n      ],\n      \"webapp 1.1.5-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"logging@1.0.6-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"routepolicy@1.0.3-winr.0\",\n        \"boilerplate-generator@1.0.2-winr.0\",\n        \"spacebars@1.0.4-winr.0\",\n        \"htmljs@1.0.3-winr.0\",\n        \"blaze@2.0.4-winr.0\",\n        \"webapp-hashing@1.0.2-winr.0\",\n        \"application-configuration@1.0.4-winr.0\",\n        \"follower-livedata@1.0.3-winr.0\"\n      ],\n      \"webapp 1.1.5\": [\n        \"meteor@1.1.4\",\n        \"logging@1.0.6\",\n        \"underscore@1.0.2\",\n        \"routepolicy@1.0.3\",\n        \"boilerplate-generator@1.0.2\",\n        \"spacebars@1.0.4\",\n        \"htmljs@1.0.3\",\n        \"blaze@2.0.4\",\n        \"webapp-hashing@1.0.2\",\n        \"application-configuration@1.0.4\",\n        \"follower-livedata@1.0.3\"\n      ],\n      \"webapp 1.1.6-cordova41\": [\n        \"meteor@1.1.4\",\n        \"logging@1.0.6\",\n        \"underscore@1.0.2\",\n        \"routepolicy@1.0.3\",\n        \"boilerplate-generator@1.0.2\",\n        \"spacebars@1.0.4\",\n        \"htmljs@1.0.3\",\n        \"blaze@2.0.4\",\n        \"webapp-hashing@1.0.2\",\n        \"application-configuration@1.0.4\",\n        \"follower-livedata@1.0.3\"\n      ],\n      \"webapp 1.1.6-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"logging@1.0.6-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"routepolicy@1.0.4-winr.4\",\n        \"boilerplate-generator@1.0.3-winr.2\",\n        \"spacebars@1.0.5-winr.5\",\n        \"htmljs@1.0.4-winr.2\",\n        \"blaze@2.0.5-eachin.0\",\n        \"webapp-hashing@1.0.3-winr.2\"\n      ],\n      \"webapp 1.1.6-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"logging@1.0.6-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"routepolicy@1.0.4-winr.4\",\n        \"boilerplate-generator@1.0.3-winr.2\",\n        \"spacebars@1.0.5-winr.5\",\n        \"htmljs@1.0.4-winr.2\",\n        \"blaze@2.0.5-githubble.0\",\n        \"webapp-hashing@1.0.3-winr.2\"\n      ],\n      \"webapp 1.1.6-pw.1\": [\n        \"meteor@1.1.4\",\n        \"logging@1.0.6\",\n        \"underscore@1.0.2\",\n        \"routepolicy@1.0.3\",\n        \"boilerplate-generator@1.0.2\",\n        \"spacebars@1.0.4\",\n        \"htmljs@1.0.3\",\n        \"blaze@2.0.4\",\n        \"webapp-hashing@1.0.2\",\n        \"application-configuration@1.0.4\",\n        \"follower-livedata@1.0.3\"\n      ],\n      \"webapp 1.1.6-rc.0\": [\n        \"meteor@1.1.4\",\n        \"logging@1.0.6\",\n        \"underscore@1.0.2\",\n        \"routepolicy@1.0.4-rc.0\",\n        \"boilerplate-generator@1.0.2\",\n        \"spacebars@1.0.5-rc.0\",\n        \"htmljs@1.0.3\",\n        \"blaze@2.0.4\",\n        \"webapp-hashing@1.0.2\",\n        \"application-configuration@1.0.4\",\n        \"follower-livedata@1.0.3\"\n      ],\n      \"webapp 1.1.6-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"logging@1.0.7-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"routepolicy@1.0.4-winr.0\",\n        \"boilerplate-generator@1.0.3-winr.0\",\n        \"spacebars@1.0.5-winr.0\",\n        \"htmljs@1.0.4-winr.0\",\n        \"blaze@2.0.5-winr.0\",\n        \"webapp-hashing@1.0.3-winr.0\",\n        \"application-configuration@1.0.5-winr.0\",\n        \"follower-livedata@1.0.4-winr.0\"\n      ],\n      \"webapp 1.1.6-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"logging@1.0.7-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"routepolicy@1.0.4-winr.1\",\n        \"boilerplate-generator@1.0.3-winr.1\",\n        \"spacebars@1.0.5-winr.1\",\n        \"htmljs@1.0.4-winr.1\",\n        \"blaze@2.0.5-winr.1\",\n        \"webapp-hashing@1.0.3-winr.1\",\n        \"application-configuration@1.0.5-winr.1\",\n        \"follower-livedata@1.0.4-winr.1\"\n      ],\n      \"webapp 1.1.6-winr.2\": [\n        \"meteor@1.1.5-winr.2\",\n        \"logging@1.0.6\",\n        \"underscore@1.0.2\",\n        \"routepolicy@1.0.4-winr.2\",\n        \"boilerplate-generator@1.0.2\",\n        \"spacebars@1.0.5-winr.2\",\n        \"htmljs@1.0.3\",\n        \"blaze@2.0.4\",\n        \"webapp-hashing@1.0.2\",\n        \"application-configuration@1.0.4\",\n        \"follower-livedata@1.0.3\"\n      ],\n      \"webapp 1.1.6-winr.3\": [\n        \"meteor@1.1.5-winr.3\",\n        \"logging@1.0.6\",\n        \"underscore@1.0.2\",\n        \"routepolicy@1.0.4-winr.3\",\n        \"boilerplate-generator@1.0.2\",\n        \"spacebars@1.0.5-winr.3\",\n        \"htmljs@1.0.3\",\n        \"blaze@2.0.4\",\n        \"webapp-hashing@1.0.2\",\n        \"application-configuration@1.0.4\",\n        \"follower-livedata@1.0.3\"\n      ],\n      \"webapp 1.1.6-winr.4\": [\n        \"meteor@1.1.5-winr.4\",\n        \"logging@1.0.6-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"routepolicy@1.0.4-winr.4\",\n        \"boilerplate-generator@1.0.3-winr.2\",\n        \"spacebars@1.0.5-winr.4\",\n        \"htmljs@1.0.4-winr.2\",\n        \"blaze@2.0.5-winr.2\",\n        \"webapp-hashing@1.0.3-winr.2\",\n        \"application-configuration@1.0.5-winr.2\",\n        \"follower-livedata@1.0.4-winr.2\"\n      ],\n      \"webapp 1.1.6-winr.5\": [\n        \"meteor@1.1.5-winr.4\",\n        \"logging@1.0.6-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"routepolicy@1.0.4-winr.4\",\n        \"boilerplate-generator@1.0.3-winr.2\",\n        \"spacebars@1.0.5-winr.4\",\n        \"htmljs@1.0.4-winr.2\",\n        \"blaze@2.0.5-winr.2\",\n        \"webapp-hashing@1.0.3-winr.2\",\n        \"application-configuration@1.0.5-winr.2\",\n        \"follower-livedata@1.0.4-winr.2\"\n      ],\n      \"webapp 1.1.6-winr.6\": [\n        \"meteor@1.1.5-winr.5\",\n        \"logging@1.0.6-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"routepolicy@1.0.4-winr.4\",\n        \"boilerplate-generator@1.0.3-winr.2\",\n        \"spacebars@1.0.5-winr.5\",\n        \"htmljs@1.0.4-winr.2\",\n        \"blaze@2.0.5-winr.3\",\n        \"webapp-hashing@1.0.3-winr.2\"\n      ],\n      \"webapp 1.1.6\": [\n        \"meteor@1.1.4\",\n        \"logging@1.0.6\",\n        \"underscore@1.0.2\",\n        \"routepolicy@1.0.4\",\n        \"boilerplate-generator@1.0.2\",\n        \"spacebars@1.0.5\",\n        \"htmljs@1.0.3\",\n        \"blaze@2.0.4\",\n        \"webapp-hashing@1.0.2\",\n        \"application-configuration@1.0.4\",\n        \"follower-livedata@1.0.3\"\n      ],\n      \"webapp 1.1.7-blz.0\": [\n        \"meteor@1.1.5-blz.0\",\n        \"logging@1.0.6\",\n        \"underscore@1.0.2\",\n        \"routepolicy@1.0.4\",\n        \"boilerplate-generator@1.0.2\",\n        \"spacebars@1.0.5\",\n        \"htmljs@1.0.3\",\n        \"blaze@2.0.5-blz.1\",\n        \"webapp-hashing@1.0.2\"\n      ],\n      \"webapp 1.1.7-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"logging@1.0.6-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"routepolicy@1.0.4-eachin.43\",\n        \"boilerplate-generator@1.0.3-eachin.43\",\n        \"spacebars@1.0.5-eachin.43\",\n        \"htmljs@1.0.4-eachin.43\",\n        \"blaze@2.0.5-eachin.43\",\n        \"webapp-hashing@1.0.3-eachin.43\"\n      ],\n      \"webapp 1.1.7-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"logging@1.0.6-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"routepolicy@1.0.4-winr.4\",\n        \"boilerplate-generator@1.0.3-winr.2\",\n        \"spacebars@1.0.5-winr.5\",\n        \"htmljs@1.0.4-winr.2\",\n        \"blaze@2.0.5-githubble.0\",\n        \"webapp-hashing@1.0.3-winr.2\"\n      ],\n      \"webapp 1.1.7-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"logging@1.0.6-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"routepolicy@1.0.4-githubble.2\",\n        \"boilerplate-generator@1.0.3-githubble.2\",\n        \"spacebars@1.0.5-githubble.2\",\n        \"htmljs@1.0.4-githubble.2\",\n        \"blaze@2.0.5-githubble.2\",\n        \"webapp-hashing@1.0.3-githubble.2\"\n      ],\n      \"webapp 1.1.7-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"logging@1.0.6-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"routepolicy@1.0.4-githubble.42\",\n        \"boilerplate-generator@1.0.3-githubble.42\",\n        \"spacebars@1.0.5-githubble.42\",\n        \"htmljs@1.0.4-githubble.42\",\n        \"blaze@2.0.5-githubble.42\",\n        \"webapp-hashing@1.0.3-githubble.42\"\n      ],\n      \"webapp 1.1.7-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"logging@1.0.6-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"routepolicy@1.0.4-githubble.43\",\n        \"boilerplate-generator@1.0.3-githubble.43\",\n        \"spacebars@1.0.5-githubble.43\",\n        \"htmljs@1.0.4-githubble.43\",\n        \"blaze@2.0.5-githubble.43\",\n        \"webapp-hashing@1.0.3-githubble.43\"\n      ],\n      \"webapp 1.1.7-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"logging@1.0.6\",\n        \"underscore@1.0.2\",\n        \"routepolicy@1.0.4\",\n        \"boilerplate-generator@1.0.2\",\n        \"spacebars@1.0.5\",\n        \"htmljs@1.0.3\",\n        \"blaze@2.0.5-vs.1\",\n        \"webapp-hashing@1.0.2\"\n      ],\n      \"webapp 1.1.7-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"logging@1.0.6\",\n        \"underscore@1.0.2\",\n        \"routepolicy@1.0.4\",\n        \"boilerplate-generator@1.0.2\",\n        \"spacebars@1.0.5\",\n        \"htmljs@1.0.3\",\n        \"blaze@2.0.5-vs.2\",\n        \"webapp-hashing@1.0.2\"\n      ],\n      \"webapp 1.1.7-winr.6\": [\n        \"meteor@1.1.5-winr.6\",\n        \"logging@1.0.6-winr.3\",\n        \"underscore@1.0.3-winr.2\",\n        \"routepolicy@1.0.4-winr.4\",\n        \"boilerplate-generator@1.0.3-winr.3\",\n        \"webapp-hashing@1.0.3-winr.2\"\n      ],\n      \"webapp 1.2.0-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"logging@1.0.7-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"routepolicy@1.0.5-rc.0\",\n        \"boilerplate-generator@1.0.3-rc.0\",\n        \"webapp-hashing@1.0.3-rc.0\"\n      ],\n      \"application-configuration 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"logging@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"ddp@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\",\n        \"follower-livedata@10.0.0-glasser.isopacket.0\",\n        \"mongo@10.0.0-glasser.isopacket.0\"\n      ],\n      \"application-configuration 1.0.0\": [\n        \"ejson@1.0.0\",\n        \"follower-livedata@1.0.0\",\n        \"livedata@1.0.7\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.2\",\n        \"mongo-livedata@1.0.3\",\n        \"underscore@1.0.0\"\n      ],\n      \"application-configuration 1.0.1-glasser1\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"ddp\",\n        \"ejson\",\n        \"follower-livedata\",\n        \"mongo\"\n      ],\n      \"application-configuration 1.0.1-rc0\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"ddp\",\n        \"ejson\",\n        \"follower-livedata\",\n        \"mongo\"\n      ],\n      \"application-configuration 1.0.1\": [\n        \"ddp@1.0.8\",\n        \"ejson@1.0.1\",\n        \"follower-livedata@1.0.1\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.3\",\n        \"mongo@1.0.4\",\n        \"underscore@1.0.0\"\n      ],\n      \"application-configuration 1.0.2-ekate\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"ddp\",\n        \"ejson\",\n        \"follower-livedata\",\n        \"mongo\"\n      ],\n      \"application-configuration 1.0.2-rc0\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"ddp\",\n        \"ejson\",\n        \"follower-livedata\",\n        \"mongo\"\n      ],\n      \"application-configuration 1.0.2\": [\n        \"ddp@1.0.8\",\n        \"ejson@1.0.2\",\n        \"follower-livedata@1.0.1\",\n        \"logging@1.0.3\",\n        \"meteor@1.1.0\",\n        \"mongo@1.0.5\",\n        \"underscore@1.0.0\"\n      ],\n      \"application-configuration 1.0.3-pre.0\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"ddp\",\n        \"ejson\",\n        \"follower-livedata\",\n        \"mongo\"\n      ],\n      \"application-configuration 1.0.3-pre.1\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"ddp\",\n        \"ejson\",\n        \"follower-livedata\",\n        \"mongo\"\n      ],\n      \"application-configuration 1.0.3-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"logging@1.0.4-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"ddp@1.0.10-pre.2\",\n        \"ejson@1.0.4-pre.2\",\n        \"follower-livedata@1.0.2-pre.2\",\n        \"mongo@1.0.7-pre.2\"\n      ],\n      \"application-configuration 1.0.3-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"logging@1.0.4-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"ddp@1.0.10-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"follower-livedata@1.0.2-rc.0\",\n        \"mongo@1.0.7-rc.0\"\n      ],\n      \"application-configuration 1.0.3-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"logging@1.0.5-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"ddp@1.0.11-win.0\",\n        \"ejson@1.0.4-win.0\",\n        \"follower-livedata@1.0.2-win.0\",\n        \"mongo@1.0.8-win.0\"\n      ],\n      \"application-configuration 1.0.3\": [\n        \"meteor@1.1.2\",\n        \"logging@1.0.4\",\n        \"underscore@1.0.1\",\n        \"ddp@1.0.10\",\n        \"ejson@1.0.4\",\n        \"follower-livedata@1.0.2\",\n        \"mongo@1.0.7\"\n      ],\n      \"application-configuration 1.0.4-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"logging@1.0.6-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"ddp@1.0.12-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"follower-livedata@1.0.3-ipc.0\",\n        \"mongo@1.0.9-ipc.0\"\n      ],\n      \"application-configuration 1.0.4-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"logging@1.0.6-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"ddp@1.0.13-rc.1\",\n        \"ejson@1.0.5-rc.1\",\n        \"follower-livedata@1.0.3-rc.1\",\n        \"mongo@1.0.10-rc.1\"\n      ],\n      \"application-configuration 1.0.4-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"logging@1.0.6-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"ddp@1.0.13-slava.0\",\n        \"ejson@1.0.5-slava.0\",\n        \"follower-livedata@1.0.3-slava.0\",\n        \"mongo@1.0.10-slava.0\"\n      ],\n      \"application-configuration 1.0.4-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"logging@1.0.6-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"ddp@1.0.12-win.0\",\n        \"ejson@1.0.5-win.0\",\n        \"follower-livedata@1.0.3-win.0\",\n        \"mongo@1.0.9-win.0\"\n      ],\n      \"application-configuration 1.0.4-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"logging@1.0.6-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"ddp@1.0.13-winr.0\",\n        \"ejson@1.0.5-winr.0\",\n        \"follower-livedata@1.0.3-winr.0\",\n        \"mongo@1.0.10-winr.0\"\n      ],\n      \"application-configuration 1.0.4\": [\n        \"meteor@1.1.4\",\n        \"logging@1.0.6\",\n        \"underscore@1.0.2\",\n        \"ddp@1.0.13\",\n        \"ejson@1.0.5\",\n        \"follower-livedata@1.0.3\",\n        \"mongo@1.0.10\"\n      ],\n      \"application-configuration 1.0.5-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"logging@1.0.7-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"ddp@1.0.14-winr.0\",\n        \"ejson@1.0.6-winr.0\",\n        \"follower-livedata@1.0.4-winr.0\",\n        \"mongo@1.0.11-winr.0\"\n      ],\n      \"application-configuration 1.0.5-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"logging@1.0.7-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"ddp@1.0.14-winr.1\",\n        \"ejson@1.0.6-winr.1\",\n        \"follower-livedata@1.0.4-winr.1\",\n        \"mongo@1.0.11-winr.1\"\n      ],\n      \"application-configuration 1.0.5-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"logging@1.0.6-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"ddp@1.0.14-winr.4\",\n        \"ejson@1.0.6-winr.2\",\n        \"follower-livedata@1.0.4-winr.2\",\n        \"mongo@1.0.12-winr.2\"\n      ],\n      \"webapp-hashing 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\"\n      ],\n      \"webapp-hashing 1.0.0-cordova1\": [\n        \"meteor@1.1.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"webapp-hashing 1.0.0\": [\n        \"meteor@1.1.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"webapp-hashing 1.0.1-pre.0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"webapp-hashing 1.0.1-pre.1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"webapp-hashing 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\"\n      ],\n      \"webapp-hashing 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"webapp-hashing 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\"\n      ],\n      \"webapp-hashing 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\"\n      ],\n      \"webapp-hashing 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\"\n      ],\n      \"webapp-hashing 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\"\n      ],\n      \"webapp-hashing 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\"\n      ],\n      \"webapp-hashing 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\"\n      ],\n      \"webapp-hashing 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\"\n      ],\n      \"webapp-hashing 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\"\n      ],\n      \"webapp-hashing 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\"\n      ],\n      \"webapp-hashing 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\"\n      ],\n      \"webapp-hashing 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\"\n      ],\n      \"webapp-hashing 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\"\n      ],\n      \"webapp-hashing 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\"\n      ],\n      \"webapp-hashing 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"webapp-hashing 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\"\n      ],\n      \"webapp-hashing 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\"\n      ],\n      \"webapp-hashing 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"url 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\"\n      ],\n      \"url 1.0.0-ekate\": [\n        \"meteor\"\n      ],\n      \"url 1.0.0-glasser1\": [\n        \"meteor\"\n      ],\n      \"url 1.0.0-rc0\": [\n        \"meteor\"\n      ],\n      \"url 1.0.0\": [\n        \"meteor@1.1.0\"\n      ],\n      \"url 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"url 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"url 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"url 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"url 1.0.1-refreshpolicy.1\": [\n        \"meteor@1.1.2-refreshpolicy.1\",\n        \"underscore@1.0.1\"\n      ],\n      \"url 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"url 1.0.2-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\"\n      ],\n      \"url 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\"\n      ],\n      \"url 1.0.2\": [\n        \"meteor@1.1.3\",\n        \"underscore@1.0.1\"\n      ],\n      \"url 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\"\n      ],\n      \"url 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\"\n      ],\n      \"url 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\"\n      ],\n      \"url 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\"\n      ],\n      \"url 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\"\n      ],\n      \"url 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\"\n      ],\n      \"url 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\"\n      ],\n      \"url 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\"\n      ],\n      \"url 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\"\n      ],\n      \"url 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\"\n      ],\n      \"url 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\"\n      ],\n      \"url 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"url 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\"\n      ],\n      \"url 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\"\n      ],\n      \"url 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"underscore 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"underscore 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"underscore 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"underscore 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"underscore 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"underscore 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"underscore 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"underscore 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"underscore 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"underscore 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"underscore 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"underscore 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"underscore 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"underscore 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"underscore 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"underscore 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"underscore 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"underscore 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"underscore 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"underscore 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"underscore 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"underscore 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"underscore 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"underscore 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"underscore-tests 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"underscore-tests 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"underscore-tests 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"underscore-tests 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"underscore-tests 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"underscore-tests 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"underscore-tests 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"underscore-tests 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"underscore-tests 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"underscore-tests 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"underscore-tests 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"underscore-tests 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"underscore-tests 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"underscore-tests 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"underscore-tests 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"underscore-tests 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"underscore-tests 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"underscore-tests 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"underscore-tests 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"underscore-tests 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"underscore-tests 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"underscore-tests 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"underscore-tests 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"underscore-tests 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"ui 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"blaze@10.0.0-glasser.isopacket.0\"\n      ],\n      \"ui 1.0.0\": [\n        \"blaze@1.0.3\",\n        \"deps@1.0.1\",\n        \"ejson@1.0.0\",\n        \"htmljs@1.0.0\",\n        \"jquery@1.0.0\",\n        \"meteor@1.0.2\",\n        \"minimongo@1.0.1\",\n        \"observe-sequence@1.0.1\",\n        \"ordered-dict@1.0.0\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"ui 1.0.1-rc0\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"ui 1.0.1\": [\n        \"blaze@2.0.0\",\n        \"meteor@1.0.3\"\n      ],\n      \"ui 1.0.2\": [\n        \"blaze@2.0.0\",\n        \"meteor@1.0.3\"\n      ],\n      \"ui 1.0.3-rc0\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"ui 1.0.3\": [\n        \"blaze@2.0.1\",\n        \"meteor@1.1.1\"\n      ],\n      \"ui 1.0.4-pre.0\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"ui 1.0.4-pre.1\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"ui 1.0.4-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"blaze@2.0.2-pre.2\"\n      ],\n      \"ui 1.0.4-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"blaze@2.0.2-rc.0\"\n      ],\n      \"ui 1.0.4-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"blaze@2.0.3-win.0\"\n      ],\n      \"ui 1.0.4\": [\n        \"meteor@1.1.2\",\n        \"blaze@2.0.2\"\n      ],\n      \"ui 1.0.5-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"blaze@2.0.4-ipc.0\"\n      ],\n      \"ui 1.0.5-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"blaze@2.0.4-rc.1\"\n      ],\n      \"ui 1.0.5-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"blaze@2.0.4-slava.0\"\n      ],\n      \"ui 1.0.5-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"blaze@2.0.4-win.0\"\n      ],\n      \"ui 1.0.5-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"blaze@2.0.4-winr.0\"\n      ],\n      \"ui 1.0.5\": [\n        \"meteor@1.1.4\",\n        \"blaze@2.0.4\"\n      ],\n      \"ui 1.0.6-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"blaze@2.0.5-eachin.0\"\n      ],\n      \"ui 1.0.6-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"blaze@2.0.5-eachin.43\"\n      ],\n      \"ui 1.0.6-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"blaze@2.0.5-githubble.0\"\n      ],\n      \"ui 1.0.6-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"blaze@2.0.5-githubble.2\"\n      ],\n      \"ui 1.0.6-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"blaze@2.0.5-githubble.42\"\n      ],\n      \"ui 1.0.6-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"blaze@2.0.5-githubble.43\"\n      ],\n      \"ui 1.0.6-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"blaze@2.1.0-rc.0\"\n      ],\n      \"ui 1.0.6-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"blaze@2.0.5-winr.0\"\n      ],\n      \"ui 1.0.6-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"blaze@2.0.5-winr.1\"\n      ],\n      \"ui 1.0.6-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"blaze@2.0.5-winr.2\"\n      ],\n      \"twitter 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"http@10.0.0-glasser.isopacket.0\",\n        \"oauth1@10.0.0-glasser.isopacket.0\",\n        \"oauth@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"service-configuration@10.0.0-glasser.isopacket.0\",\n        \"templating@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\"\n      ],\n      \"twitter 1.0.0\": [\n        \"http@1.0.2\",\n        \"meteor@1.0.2\",\n        \"oauth@1.0.0\",\n        \"oauth1@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.0\",\n        \"templating@1.0.4\",\n        \"underscore@1.0.0\"\n      ],\n      \"twitter 1.0.1-glasser1\": [\n        \"meteor\",\n        \"http\",\n        \"oauth1\",\n        \"oauth\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"twitter 1.0.1-rc0\": [\n        \"meteor\",\n        \"http\",\n        \"oauth1\",\n        \"oauth\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"twitter 1.0.1\": [\n        \"http@1.0.4\",\n        \"meteor@1.0.3\",\n        \"oauth@1.0.1\",\n        \"oauth1@1.0.1\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.5\",\n        \"underscore@1.0.0\"\n      ],\n      \"twitter 1.0.2-ekate\": [\n        \"meteor\",\n        \"http\",\n        \"oauth1\",\n        \"oauth\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"twitter 1.1.0-rc0\": [\n        \"meteor\",\n        \"http\",\n        \"oauth1\",\n        \"oauth\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"twitter 1.1.0-rc1\": [\n        \"meteor\",\n        \"http\",\n        \"oauth1\",\n        \"oauth\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"twitter 1.1.0\": [\n        \"http@1.0.5\",\n        \"meteor@1.1.0\",\n        \"oauth@1.1.0\",\n        \"oauth1@1.1.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.6\",\n        \"underscore@1.0.0\"\n      ],\n      \"twitter 1.1.1-pre.0\": [\n        \"meteor\",\n        \"http\",\n        \"oauth1\",\n        \"oauth\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"twitter 1.1.1-pre.1\": [\n        \"meteor\",\n        \"http\",\n        \"oauth1\",\n        \"oauth\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"twitter 1.1.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"http@1.0.7-pre.2\",\n        \"oauth1@1.1.1-pre.2\",\n        \"oauth@1.1.1-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"service-configuration@1.0.2-pre.2\",\n        \"templating@1.0.8-pre.2\",\n        \"random@1.0.1-pre.2\"\n      ],\n      \"twitter 1.1.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"http@1.0.7-rc.0\",\n        \"oauth1@1.1.1-rc.0\",\n        \"oauth@1.1.1-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"templating@1.0.8-rc.0\",\n        \"random@1.0.1-rc.0\"\n      ],\n      \"twitter 1.1.1\": [\n        \"meteor@1.1.2\",\n        \"http@1.0.7\",\n        \"oauth1@1.1.1\",\n        \"oauth@1.1.1\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"templating@1.0.8\",\n        \"random@1.0.1\"\n      ],\n      \"twitter 1.1.2-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"http@1.0.8-rc.6\",\n        \"oauth1@1.1.2-rc.0\",\n        \"oauth@1.1.2-rc.0\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"templating@1.0.9-rc.2\",\n        \"random@1.0.1\"\n      ],\n      \"twitter 1.1.2-rc.1\": [\n        \"meteor@1.1.3-rc.0\",\n        \"http@1.0.8-rc.6\",\n        \"oauth1@1.1.2-rc.0\",\n        \"oauth@1.1.2-rc.1\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"templating@1.0.9-rc.2\",\n        \"random@1.0.1\"\n      ],\n      \"twitter 1.1.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"http@1.0.8-win.0\",\n        \"oauth1@1.1.2-win.0\",\n        \"oauth@1.1.2-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"service-configuration@1.0.2-win.0\",\n        \"templating@1.0.9-win.0\",\n        \"random@1.0.1-win.0\"\n      ],\n      \"twitter 1.1.2\": [\n        \"meteor@1.1.3\",\n        \"http@1.0.8\",\n        \"oauth1@1.1.2\",\n        \"oauth@1.1.2\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"templating@1.0.9\",\n        \"random@1.0.1\"\n      ],\n      \"twitter 1.1.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"http@1.0.9-ipc.0\",\n        \"oauth1@1.1.3-ipc.0\",\n        \"oauth@1.1.3-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"service-configuration@1.0.3-ipc.0\",\n        \"templating@1.0.10-ipc.0\",\n        \"random@1.0.2-ipc.0\"\n      ],\n      \"twitter 1.1.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"http@1.0.9-rc.1\",\n        \"oauth1@1.1.3-rc.1\",\n        \"oauth@1.1.3-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"service-configuration@1.0.3-rc.1\",\n        \"templating@1.0.10-rc.1\",\n        \"random@1.0.2-rc.1\"\n      ],\n      \"twitter 1.1.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"http@1.0.9-slava.0\",\n        \"oauth1@1.1.3-slava.0\",\n        \"oauth@1.1.3-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"service-configuration@1.0.3-slava.0\",\n        \"templating@1.0.10-slava.0\",\n        \"random@1.0.2-slava.0\"\n      ],\n      \"twitter 1.1.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"http@1.0.9-win.0\",\n        \"oauth1@1.1.3-win.0\",\n        \"oauth@1.1.3-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"service-configuration@1.0.3-win.0\",\n        \"templating@1.0.10-win.0\",\n        \"random@1.0.2-win.0\"\n      ],\n      \"twitter 1.1.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"http@1.0.9-winr.0\",\n        \"oauth1@1.1.3-winr.0\",\n        \"oauth@1.1.3-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"service-configuration@1.0.3-winr.0\",\n        \"templating@1.0.10-winr.0\",\n        \"random@1.0.2-winr.0\"\n      ],\n      \"twitter 1.1.3\": [\n        \"meteor@1.1.4\",\n        \"http@1.0.9\",\n        \"oauth1@1.1.3\",\n        \"oauth@1.1.3\",\n        \"underscore@1.0.2\",\n        \"service-configuration@1.0.3\",\n        \"templating@1.0.10\",\n        \"random@1.0.2\"\n      ],\n      \"twitter 1.1.4-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"http@1.0.10-eachin.0\",\n        \"oauth1@1.1.4-winr.2\",\n        \"oauth@1.1.4-winr.2\",\n        \"underscore@1.0.3-eachin.0\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"templating@1.0.11-eachin.0\",\n        \"random@1.0.3-eachin.0\"\n      ],\n      \"twitter 1.1.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"http@1.0.10-eachin.43\",\n        \"oauth1@1.1.4-eachin.43\",\n        \"oauth@1.1.4-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"service-configuration@1.0.4-eachin.43\",\n        \"templating@1.0.12-eachin.43\",\n        \"random@1.0.3-eachin.43\"\n      ],\n      \"twitter 1.1.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"http@1.0.10-githubble.0\",\n        \"oauth1@1.1.4-githubble.0\",\n        \"oauth@1.1.4-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"service-configuration@1.0.4-githubble.0\",\n        \"templating@1.0.12-githubble.0\",\n        \"random@1.0.3-githubble.0\"\n      ],\n      \"twitter 1.1.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"http@1.0.10-githubble.2\",\n        \"oauth1@1.1.4-githubble.2\",\n        \"oauth@1.1.4-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"service-configuration@1.0.4-githubble.2\",\n        \"templating@1.0.12-githubble.2\",\n        \"random@1.0.3-githubble.2\"\n      ],\n      \"twitter 1.1.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"http@1.0.10-githubble.42\",\n        \"oauth1@1.1.4-githubble.42\",\n        \"oauth@1.1.4-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"service-configuration@1.0.4-githubble.42\",\n        \"templating@1.0.12-githubble.42\",\n        \"random@1.0.3-githubble.42\"\n      ],\n      \"twitter 1.1.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"http@1.0.10-githubble.43\",\n        \"oauth1@1.1.4-githubble.43\",\n        \"oauth@1.1.4-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"service-configuration@1.0.4-githubble.43\",\n        \"templating@1.0.12-githubble.43\",\n        \"random@1.0.3-githubble.43\"\n      ],\n      \"twitter 1.1.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"http@1.1.0-rc.0\",\n        \"oauth1@1.1.4-rc.0\",\n        \"oauth@1.1.4-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"service-configuration@1.0.4-rc.0\",\n        \"templating@1.1.0-rc.0\",\n        \"random@1.0.3-rc.0\"\n      ],\n      \"twitter 1.1.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"http@1.0.10-winr.0\",\n        \"oauth1@1.1.4-winr.0\",\n        \"oauth@1.1.4-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"service-configuration@1.0.4-winr.0\",\n        \"templating@1.0.11-winr.0\",\n        \"random@1.0.3-winr.0\"\n      ],\n      \"twitter 1.1.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"http@1.0.10-winr.1\",\n        \"oauth1@1.1.4-winr.1\",\n        \"oauth@1.1.4-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"service-configuration@1.0.4-winr.1\",\n        \"templating@1.0.11-winr.1\",\n        \"random@1.0.3-winr.1\"\n      ],\n      \"twitter 1.1.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"http@1.0.10-winr.4\",\n        \"oauth1@1.1.4-winr.2\",\n        \"oauth@1.1.4-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"templating@1.0.11-winr.4\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"twitter 1.1.4-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"http@1.0.11-winr.5\",\n        \"oauth1@1.1.4-winr.2\",\n        \"oauth@1.1.4-winr.3\",\n        \"underscore@1.0.3-winr.2\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"templating@1.0.12-winr.7\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"tracker 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"tracker 1.0.2-rc0\": [\n        \"meteor\"\n      ],\n      \"tracker 1.0.2-rc1\": [\n        \"meteor\"\n      ],\n      \"tracker 1.0.2\": [\n        \"meteor@1.0.3\"\n      ],\n      \"tracker 1.0.3-pre.0\": [\n        \"meteor\"\n      ],\n      \"tracker 1.0.3-pre.1\": [\n        \"meteor\"\n      ],\n      \"tracker 1.0.3-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"tracker 1.0.3-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"tracker 1.0.3-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"tracker 1.0.3\": [\n        \"meteor@1.1.2\"\n      ],\n      \"tracker 1.0.4-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"tracker 1.0.4-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"tracker 1.0.4-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"tracker 1.0.4-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"tracker 1.0.4-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"tracker 1.0.4\": [\n        \"meteor@1.1.4\"\n      ],\n      \"tracker 1.0.5-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"tracker 1.0.5-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"tracker 1.0.5-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"tracker 1.0.5-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"tracker 1.0.5-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"tracker 1.0.5-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"tracker 1.0.5-rc.0\": [\n        \"meteor@1.1.4\"\n      ],\n      \"tracker 1.0.5-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"tracker 1.0.5-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"tracker 1.0.5-winr.2\": [\n        \"meteor@1.1.5-winr.2\"\n      ],\n      \"tracker 1.0.5-winr.3\": [\n        \"meteor@1.1.5-winr.3\"\n      ],\n      \"tracker 1.0.5-winr.4\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"tracker 1.0.5\": [\n        \"meteor@1.1.4\"\n      ],\n      \"tracker 1.0.6-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"tracker 1.0.6-winr.4\": [\n        \"meteor@1.1.5-winr.6\"\n      ],\n      \"tinytest 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"ddp@10.0.0-glasser.isopacket.0\",\n        \"mongo@10.0.0-glasser.isopacket.0\",\n        \"check@10.0.0-glasser.isopacket.0\"\n      ],\n      \"tinytest 1.0.0\": [\n        \"check@1.0.0\",\n        \"livedata@1.0.7\",\n        \"meteor@1.0.2\",\n        \"mongo-livedata@1.0.3\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"tinytest 1.0.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"ddp\",\n        \"mongo\",\n        \"check\"\n      ],\n      \"tinytest 1.0.1\": [\n        \"check@1.0.0\",\n        \"ddp@1.0.8\",\n        \"meteor@1.0.3\",\n        \"mongo@1.0.4\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"tinytest 1.0.2-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"ddp\",\n        \"mongo\",\n        \"check\"\n      ],\n      \"tinytest 1.0.2\": [\n        \"check@1.0.1\",\n        \"ddp@1.0.9\",\n        \"meteor@1.1.1\",\n        \"mongo@1.0.6\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"tinytest 1.0.3-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"ddp\",\n        \"mongo\",\n        \"check\"\n      ],\n      \"tinytest 1.0.3-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"ddp\",\n        \"mongo\",\n        \"check\"\n      ],\n      \"tinytest 1.0.3-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"ddp@1.0.10-pre.2\",\n        \"mongo@1.0.7-pre.2\",\n        \"check@1.0.2-pre.2\"\n      ],\n      \"tinytest 1.0.3-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ddp@1.0.10-rc.0\",\n        \"mongo@1.0.7-rc.0\",\n        \"check@1.0.2-rc.0\"\n      ],\n      \"tinytest 1.0.3-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"random@1.0.1-win.0\",\n        \"ddp@1.0.11-win.0\",\n        \"mongo@1.0.8-win.0\",\n        \"check@1.0.2-win.0\"\n      ],\n      \"tinytest 1.0.3\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"random@1.0.1\",\n        \"ddp@1.0.10\",\n        \"mongo@1.0.7\",\n        \"check@1.0.2\"\n      ],\n      \"tinytest 1.0.4-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"ddp@1.0.12-ipc.0\",\n        \"mongo@1.0.9-ipc.0\",\n        \"check@1.0.3-ipc.0\"\n      ],\n      \"tinytest 1.0.4-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"ddp@1.0.13-rc.1\",\n        \"mongo@1.0.10-rc.1\",\n        \"check@1.0.3-rc.1\"\n      ],\n      \"tinytest 1.0.4-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"ddp@1.0.13-slava.0\",\n        \"mongo@1.0.10-slava.0\",\n        \"check@1.0.3-slava.0\"\n      ],\n      \"tinytest 1.0.4-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"random@1.0.2-win.0\",\n        \"ddp@1.0.12-win.0\",\n        \"mongo@1.0.9-win.0\",\n        \"check@1.0.3-win.0\"\n      ],\n      \"tinytest 1.0.4-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"ddp@1.0.13-winr.0\",\n        \"mongo@1.0.10-winr.0\",\n        \"check@1.0.3-winr.0\"\n      ],\n      \"tinytest 1.0.4\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"random@1.0.2\",\n        \"ddp@1.0.13\",\n        \"mongo@1.0.10\",\n        \"check@1.0.3\"\n      ],\n      \"tinytest 1.0.5-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"random@1.0.3-eachin.0\",\n        \"ddp@1.0.14-eachin.0\",\n        \"mongo@1.0.12-eachin.0\",\n        \"check@1.0.4-win.0\"\n      ],\n      \"tinytest 1.0.5-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"ddp@1.0.15-eachin.43\",\n        \"mongo@1.0.12-eachin.45\",\n        \"check@1.0.4-eachin.43\"\n      ],\n      \"tinytest 1.0.5-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"random@1.0.3-githubble.0\",\n        \"ddp@1.0.15-githubble.0\",\n        \"mongo@1.0.12-githubble.0\",\n        \"check@1.0.4-win.0\"\n      ],\n      \"tinytest 1.0.5-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"ddp@1.0.15-githubble.2\",\n        \"mongo@1.0.12-githubble.2\",\n        \"check@1.0.4-win.0\"\n      ],\n      \"tinytest 1.0.5-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"ddp@1.0.15-githubble.42\",\n        \"mongo@1.0.12-githubble.42\",\n        \"check@1.0.4-win.0\"\n      ],\n      \"tinytest 1.0.5-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"ddp@1.0.15-githubble.43\",\n        \"mongo@1.0.12-githubble.43\",\n        \"check@1.0.4-githubble.43\"\n      ],\n      \"tinytest 1.0.5-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"ddp@1.1.0-rc.0\",\n        \"mongo@1.1.0-rc.0\",\n        \"check@1.0.5-rc.0\"\n      ],\n      \"tinytest 1.0.5-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"ddp@1.0.14-winr.0\",\n        \"mongo@1.0.11-winr.0\",\n        \"check@1.0.4-winr.0\"\n      ],\n      \"tinytest 1.0.5-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"ddp@1.0.14-winr.1\",\n        \"mongo@1.0.11-winr.1\",\n        \"check@1.0.4-winr.1\"\n      ],\n      \"tinytest 1.0.5-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"ddp@1.0.14-winr.4\",\n        \"mongo@1.0.12-winr.2\",\n        \"check@1.0.4-win.0\"\n      ],\n      \"tinytest 1.0.5-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"ddp@1.0.15-winr.6\",\n        \"mongo@1.0.12-winr.6\",\n        \"check@1.0.5-win.0\"\n      ],\n      \"test-server-tests-in-console-once 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"tinytest@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\"\n      ],\n      \"test-server-tests-in-console-once 1.0.0\": [\n        \"ejson@1.0.0\",\n        \"meteor@1.0.2\",\n        \"tinytest@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"test-server-tests-in-console-once 1.0.1-pre.0\": [\n        \"meteor\",\n        \"tinytest\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"test-server-tests-in-console-once 1.0.1-pre.1\": [\n        \"meteor\",\n        \"tinytest\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"test-server-tests-in-console-once 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"tinytest@1.0.3-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"ejson@1.0.4-pre.2\"\n      ],\n      \"test-server-tests-in-console-once 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"tinytest@1.0.3-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\"\n      ],\n      \"test-server-tests-in-console-once 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"tinytest@1.0.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"ejson@1.0.4-win.0\"\n      ],\n      \"test-server-tests-in-console-once 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"tinytest@1.0.3\",\n        \"underscore@1.0.1\",\n        \"ejson@1.0.4\"\n      ],\n      \"test-server-tests-in-console-once 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"tinytest@1.0.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\"\n      ],\n      \"test-server-tests-in-console-once 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"tinytest@1.0.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"ejson@1.0.5-rc.1\"\n      ],\n      \"test-server-tests-in-console-once 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"tinytest@1.0.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"ejson@1.0.5-slava.0\"\n      ],\n      \"test-server-tests-in-console-once 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"tinytest@1.0.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"ejson@1.0.5-win.0\"\n      ],\n      \"test-server-tests-in-console-once 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"tinytest@1.0.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"ejson@1.0.5-winr.0\"\n      ],\n      \"test-server-tests-in-console-once 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"tinytest@1.0.4\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\"\n      ],\n      \"test-server-tests-in-console-once 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"tinytest@1.0.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"ejson@1.0.6-eachin.0\"\n      ],\n      \"test-server-tests-in-console-once 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"tinytest@1.0.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"ejson@1.0.6-eachin.43\"\n      ],\n      \"test-server-tests-in-console-once 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"tinytest@1.0.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"ejson@1.0.6-githubble.0\"\n      ],\n      \"test-server-tests-in-console-once 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"tinytest@1.0.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"ejson@1.0.6-githubble.2\"\n      ],\n      \"test-server-tests-in-console-once 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"tinytest@1.0.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"ejson@1.0.6-githubble.42\"\n      ],\n      \"test-server-tests-in-console-once 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"tinytest@1.0.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"ejson@1.0.6-githubble.43\"\n      ],\n      \"test-server-tests-in-console-once 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"tinytest@1.0.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"ejson@1.0.6-rc.0\"\n      ],\n      \"test-server-tests-in-console-once 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"tinytest@1.0.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"ejson@1.0.6-winr.0\"\n      ],\n      \"test-server-tests-in-console-once 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"tinytest@1.0.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\"\n      ],\n      \"test-server-tests-in-console-once 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"tinytest@1.0.5-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\"\n      ],\n      \"test-in-console 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"tinytest@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\",\n        \"check@10.0.0-glasser.isopacket.0\",\n        \"http@10.0.0-glasser.isopacket.0\"\n      ],\n      \"test-in-console 1.0.0-cordova4\": [\n        \"meteor\",\n        \"tinytest\",\n        \"underscore\",\n        \"random\",\n        \"ejson\",\n        \"check\",\n        \"http\"\n      ],\n      \"test-in-console 1.0.0\": [\n        \"check@1.0.0\",\n        \"ejson@1.0.0\",\n        \"http@1.0.2\",\n        \"meteor@1.0.2\",\n        \"random@1.0.0\",\n        \"tinytest@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"test-in-console 1.0.1-rc0\": [\n        \"meteor\",\n        \"tinytest\",\n        \"underscore\",\n        \"random\",\n        \"ejson\",\n        \"check\",\n        \"http\"\n      ],\n      \"test-in-console 1.0.1\": [\n        \"check@1.0.0\",\n        \"ejson@1.0.1\",\n        \"http@1.0.4\",\n        \"meteor@1.0.3\",\n        \"random@1.0.0\",\n        \"tinytest@1.0.1\",\n        \"underscore@1.0.0\"\n      ],\n      \"test-in-console 1.0.2-ekate\": [\n        \"meteor\",\n        \"tinytest\",\n        \"underscore\",\n        \"random\",\n        \"ejson\",\n        \"check\",\n        \"http\"\n      ],\n      \"test-in-console 1.0.2-rc0\": [\n        \"meteor\",\n        \"tinytest\",\n        \"underscore\",\n        \"random\",\n        \"ejson\",\n        \"check\",\n        \"http\"\n      ],\n      \"test-in-console 1.0.2\": [\n        \"check@1.0.1\",\n        \"ejson@1.0.3\",\n        \"http@1.0.6\",\n        \"meteor@1.1.1\",\n        \"random@1.0.0\",\n        \"tinytest@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"test-in-console 1.0.3-pre.0\": [\n        \"meteor\",\n        \"tinytest\",\n        \"underscore\",\n        \"random\",\n        \"ejson\",\n        \"check\",\n        \"http\"\n      ],\n      \"test-in-console 1.0.3-pre.1\": [\n        \"meteor\",\n        \"tinytest\",\n        \"underscore\",\n        \"random\",\n        \"ejson\",\n        \"check\",\n        \"http\"\n      ],\n      \"test-in-console 1.0.3-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"tinytest@1.0.3-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"ejson@1.0.4-pre.2\",\n        \"check@1.0.2-pre.2\",\n        \"http@1.0.7-pre.2\"\n      ],\n      \"test-in-console 1.0.3-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"tinytest@1.0.3-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"http@1.0.7-rc.0\"\n      ],\n      \"test-in-console 1.0.3-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"tinytest@1.0.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"random@1.0.1-win.0\",\n        \"ejson@1.0.4-win.0\",\n        \"check@1.0.2-win.0\",\n        \"http@1.0.8-win.0\"\n      ],\n      \"test-in-console 1.0.3\": [\n        \"meteor@1.1.2\",\n        \"tinytest@1.0.3\",\n        \"underscore@1.0.1\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"check@1.0.2\",\n        \"http@1.0.7\"\n      ],\n      \"test-in-console 1.0.4-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"tinytest@1.0.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"check@1.0.3-ipc.0\",\n        \"http@1.0.9-ipc.0\"\n      ],\n      \"test-in-console 1.0.4-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"tinytest@1.0.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"ejson@1.0.5-rc.1\",\n        \"check@1.0.3-rc.1\",\n        \"http@1.0.9-rc.1\"\n      ],\n      \"test-in-console 1.0.4-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"tinytest@1.0.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"ejson@1.0.5-slava.0\",\n        \"check@1.0.3-slava.0\",\n        \"http@1.0.9-slava.0\"\n      ],\n      \"test-in-console 1.0.4-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"tinytest@1.0.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"random@1.0.2-win.0\",\n        \"ejson@1.0.5-win.0\",\n        \"check@1.0.3-win.0\",\n        \"http@1.0.9-win.0\"\n      ],\n      \"test-in-console 1.0.4-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"tinytest@1.0.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"ejson@1.0.5-winr.0\",\n        \"check@1.0.3-winr.0\",\n        \"http@1.0.9-winr.0\"\n      ],\n      \"test-in-console 1.0.4\": [\n        \"meteor@1.1.4\",\n        \"tinytest@1.0.4\",\n        \"underscore@1.0.2\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"check@1.0.3\",\n        \"http@1.0.9\"\n      ],\n      \"test-in-console 1.0.5-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"tinytest@1.0.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"random@1.0.3-eachin.0\",\n        \"ejson@1.0.6-eachin.0\",\n        \"check@1.0.4-win.0\",\n        \"http@1.0.10-eachin.0\"\n      ],\n      \"test-in-console 1.0.5-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"tinytest@1.0.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"ejson@1.0.6-eachin.43\",\n        \"check@1.0.4-eachin.43\",\n        \"http@1.0.10-eachin.43\"\n      ],\n      \"test-in-console 1.0.5-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"tinytest@1.0.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"random@1.0.3-githubble.0\",\n        \"ejson@1.0.6-githubble.0\",\n        \"check@1.0.4-win.0\",\n        \"http@1.0.10-githubble.0\"\n      ],\n      \"test-in-console 1.0.5-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"tinytest@1.0.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"ejson@1.0.6-githubble.2\",\n        \"check@1.0.4-win.0\",\n        \"http@1.0.10-githubble.2\"\n      ],\n      \"test-in-console 1.0.5-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"tinytest@1.0.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"ejson@1.0.6-githubble.42\",\n        \"check@1.0.4-win.0\",\n        \"http@1.0.10-githubble.42\"\n      ],\n      \"test-in-console 1.0.5-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"tinytest@1.0.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"ejson@1.0.6-githubble.43\",\n        \"check@1.0.4-githubble.43\",\n        \"http@1.0.10-githubble.43\"\n      ],\n      \"test-in-console 1.0.5-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"tinytest@1.0.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"ejson@1.0.6-rc.0\",\n        \"check@1.0.5-rc.0\",\n        \"http@1.1.0-rc.0\"\n      ],\n      \"test-in-console 1.0.5-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"tinytest@1.0.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"ejson@1.0.6-winr.0\",\n        \"check@1.0.4-winr.0\",\n        \"http@1.0.10-winr.0\"\n      ],\n      \"test-in-console 1.0.5-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"tinytest@1.0.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\",\n        \"check@1.0.4-winr.1\",\n        \"http@1.0.10-winr.1\"\n      ],\n      \"test-in-console 1.0.5-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"tinytest@1.0.5-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"check@1.0.4-win.0\",\n        \"http@1.0.10-winr.4\"\n      ],\n      \"test-in-browser 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"tinytest@10.0.0-glasser.isopacket.0\",\n        \"bootstrap@1.0.1\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"session@10.0.0-glasser.isopacket.0\",\n        \"reload@10.0.0-glasser.isopacket.0\",\n        \"?autoupdate@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"blaze@10.0.0-glasser.isopacket.0\",\n        \"templating@10.0.0-glasser.isopacket.0\",\n        \"spacebars@10.0.0-glasser.isopacket.0\",\n        \"ddp@10.0.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\"\n      ],\n      \"test-in-browser 1.0.0\": [\n        \"meteor\",\n        \"tinytest\",\n        \"bootstrap\",\n        \"underscore\",\n        \"session\",\n        \"reload\",\n        \"?autoupdate\",\n        \"random\",\n        \"ui\",\n        \"templating\",\n        \"spacebars\",\n        \"livedata\",\n        \"deps\"\n      ],\n      \"test-in-browser 1.0.3\": [\n        \"?autoupdate@1.0.4\",\n        \"bootstrap@1.0.0\",\n        \"deps@1.0.1\",\n        \"livedata@1.0.7\",\n        \"meteor@1.0.2\",\n        \"random@1.0.0\",\n        \"reload@1.0.0\",\n        \"session@1.0.0\",\n        \"spacebars@1.0.0\",\n        \"templating@1.0.4\",\n        \"tinytest@1.0.0\",\n        \"ui@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"test-in-browser 1.0.4-rc0\": [\n        \"meteor\",\n        \"tinytest\",\n        \"bootstrap\",\n        \"underscore\",\n        \"session\",\n        \"reload\",\n        \"?autoupdate\",\n        \"random\",\n        \"blaze\",\n        \"templating\",\n        \"spacebars\",\n        \"livedata\",\n        \"tracker\"\n      ],\n      \"test-in-browser 1.0.4-rc1\": [\n        \"meteor\",\n        \"tinytest\",\n        \"bootstrap\",\n        \"underscore\",\n        \"session\",\n        \"reload\",\n        \"?autoupdate\",\n        \"random\",\n        \"blaze\",\n        \"templating\",\n        \"spacebars\",\n        \"ddp\",\n        \"tracker\"\n      ],\n      \"test-in-browser 1.0.4\": [\n        \"?autoupdate@1.0.6\",\n        \"blaze@2.0.0\",\n        \"bootstrap@1.0.1\",\n        \"ddp@1.0.8\",\n        \"meteor@1.0.3\",\n        \"random@1.0.0\",\n        \"reload@1.0.1\",\n        \"session@1.0.1\",\n        \"spacebars@1.0.1\",\n        \"templating@1.0.5\",\n        \"tinytest@1.0.1\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"test-in-browser 1.0.5-pre.0\": [\n        \"meteor\",\n        \"tinytest\",\n        \"bootstrap\",\n        \"underscore\",\n        \"session\",\n        \"reload\",\n        \"?autoupdate\",\n        \"random\",\n        \"blaze\",\n        \"templating\",\n        \"spacebars\",\n        \"ddp\",\n        \"tracker\"\n      ],\n      \"test-in-browser 1.0.5-pre.1\": [\n        \"meteor\",\n        \"tinytest\",\n        \"bootstrap\",\n        \"underscore\",\n        \"session\",\n        \"reload\",\n        \"?autoupdate\",\n        \"random\",\n        \"blaze\",\n        \"templating\",\n        \"spacebars\",\n        \"ddp\",\n        \"tracker\"\n      ],\n      \"test-in-browser 1.0.5-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"tinytest@1.0.3-pre.2\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.1-pre.2\",\n        \"session@1.0.3-pre.2\",\n        \"reload@1.1.1-pre.2\",\n        \"?autoupdate@1.1.2-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"blaze@2.0.2-pre.2\",\n        \"templating@1.0.8-pre.2\",\n        \"spacebars@1.0.3-pre.2\",\n        \"ddp@1.0.10-pre.2\",\n        \"tracker@1.0.3-pre.2\"\n      ],\n      \"test-in-browser 1.0.5-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"tinytest@1.0.3-rc.0\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.1-rc.0\",\n        \"session@1.0.3-rc.0\",\n        \"reload@1.1.1-rc.0\",\n        \"?autoupdate@1.1.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"blaze@2.0.2-rc.0\",\n        \"templating@1.0.8-rc.0\",\n        \"spacebars@1.0.3-rc.0\",\n        \"ddp@1.0.10-rc.0\",\n        \"tracker@1.0.3-rc.0\"\n      ],\n      \"test-in-browser 1.0.5-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"tinytest@1.0.3-win.0\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.1-win.0\",\n        \"session@1.0.4-win.0\",\n        \"reload@1.1.1-win.0\",\n        \"?autoupdate@1.1.3-win.0\",\n        \"random@1.0.1-win.0\",\n        \"blaze@2.0.3-win.0\",\n        \"templating@1.0.9-win.0\",\n        \"spacebars@1.0.3-win.0\",\n        \"ddp@1.0.11-win.0\",\n        \"tracker@1.0.3-win.0\"\n      ],\n      \"test-in-browser 1.0.5\": [\n        \"meteor@1.1.2\",\n        \"tinytest@1.0.3\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.1\",\n        \"session@1.0.3\",\n        \"reload@1.1.1\",\n        \"?autoupdate@1.1.2\",\n        \"random@1.0.1\",\n        \"blaze@2.0.2\",\n        \"templating@1.0.8\",\n        \"spacebars@1.0.3\",\n        \"ddp@1.0.10\",\n        \"tracker@1.0.3\"\n      ],\n      \"test-in-browser 1.0.6-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"tinytest@1.0.4-ipc.0\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.2-ipc.0\",\n        \"session@1.0.5-ipc.0\",\n        \"reload@1.1.2-ipc.0\",\n        \"?autoupdate@1.1.4-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"blaze@2.0.4-ipc.0\",\n        \"templating@1.0.10-ipc.0\",\n        \"spacebars@1.0.4-ipc.0\",\n        \"ddp@1.0.12-ipc.0\",\n        \"tracker@1.0.4-ipc.0\"\n      ],\n      \"test-in-browser 1.0.6-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"tinytest@1.0.4-rc.1\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"session@1.0.5-rc.1\",\n        \"reload@1.1.2-rc.1\",\n        \"?autoupdate@1.1.4-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"blaze@2.0.4-rc.1\",\n        \"templating@1.0.10-rc.1\",\n        \"spacebars@1.0.4-rc.1\",\n        \"ddp@1.0.13-rc.1\",\n        \"tracker@1.0.4-rc.1\"\n      ],\n      \"test-in-browser 1.0.6-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"tinytest@1.0.4-slava.0\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.2-slava.0\",\n        \"session@1.0.5-slava.0\",\n        \"reload@1.1.2-slava.0\",\n        \"?autoupdate@1.1.4-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"blaze@2.0.4-slava.0\",\n        \"templating@1.0.10-slava.0\",\n        \"spacebars@1.0.4-slava.0\",\n        \"ddp@1.0.13-slava.0\",\n        \"tracker@1.0.4-slava.0\"\n      ],\n      \"test-in-browser 1.0.6-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"tinytest@1.0.4-win.0\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.2-win.0\",\n        \"session@1.0.5-win.0\",\n        \"reload@1.1.2-win.0\",\n        \"?autoupdate@1.1.4-win.0\",\n        \"random@1.0.2-win.0\",\n        \"blaze@2.0.4-win.0\",\n        \"templating@1.0.10-win.0\",\n        \"spacebars@1.0.4-win.0\",\n        \"ddp@1.0.12-win.0\",\n        \"tracker@1.0.4-win.0\"\n      ],\n      \"test-in-browser 1.0.6-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"tinytest@1.0.4-winr.0\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.2-winr.0\",\n        \"session@1.0.5-winr.0\",\n        \"reload@1.1.2-winr.0\",\n        \"?autoupdate@1.1.4-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"blaze@2.0.4-winr.0\",\n        \"templating@1.0.10-winr.0\",\n        \"spacebars@1.0.4-winr.0\",\n        \"ddp@1.0.13-winr.0\",\n        \"tracker@1.0.4-winr.0\"\n      ],\n      \"test-in-browser 1.0.6\": [\n        \"meteor@1.1.4\",\n        \"tinytest@1.0.4\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.2\",\n        \"session@1.0.5\",\n        \"reload@1.1.2\",\n        \"?autoupdate@1.1.4\",\n        \"random@1.0.2\",\n        \"blaze@2.0.4\",\n        \"templating@1.0.10\",\n        \"spacebars@1.0.4\",\n        \"ddp@1.0.13\",\n        \"tracker@1.0.4\"\n      ],\n      \"test-in-browser 1.0.7-blz.0\": [\n        \"meteor@1.1.4\",\n        \"tinytest@1.0.4\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.2\",\n        \"session@1.0.5\",\n        \"reload@1.1.2\",\n        \"?autoupdate@1.1.5\",\n        \"random@1.0.2\",\n        \"blaze@2.0.5-blz.0\",\n        \"templating@1.0.11\",\n        \"spacebars@1.0.5\",\n        \"ddp@1.0.15-blz.0\",\n        \"tracker@1.0.5\"\n      ],\n      \"test-in-browser 1.0.7-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"tinytest@1.0.5-eachin.0\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.3-eachin.0\",\n        \"session@1.0.6-eachin.0\",\n        \"reload@1.1.3-eachin.0\",\n        \"?autoupdate@1.1.5-eachin.0\",\n        \"random@1.0.3-eachin.0\",\n        \"blaze@2.0.5-eachin.0\",\n        \"templating@1.0.11-eachin.0\",\n        \"spacebars@1.0.5-eachin.0\",\n        \"ddp@1.0.14-eachin.0\",\n        \"tracker@1.0.5-eachin.0\"\n      ],\n      \"test-in-browser 1.0.7-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"tinytest@1.0.5-eachin.43\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.3-eachin.43\",\n        \"session@1.0.6-eachin.43\",\n        \"reload@1.1.3-eachin.43\",\n        \"?autoupdate@1.1.6-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"blaze@2.0.5-eachin.43\",\n        \"templating@1.0.12-eachin.43\",\n        \"spacebars@1.0.5-eachin.43\",\n        \"ddp@1.0.15-eachin.43\",\n        \"tracker@1.0.5-eachin.43\"\n      ],\n      \"test-in-browser 1.0.7-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"tinytest@1.0.5-githubble.0\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.3-githubble.0\",\n        \"session@1.0.6-githubble.0\",\n        \"reload@1.1.3-githubble.0\",\n        \"?autoupdate@1.1.6-githubble.0\",\n        \"random@1.0.3-githubble.0\",\n        \"blaze@2.0.5-githubble.0\",\n        \"templating@1.0.12-githubble.0\",\n        \"spacebars@1.0.5-githubble.0\",\n        \"ddp@1.0.15-githubble.0\",\n        \"tracker@1.0.5-githubble.0\"\n      ],\n      \"test-in-browser 1.0.7-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"tinytest@1.0.5-githubble.2\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.3-githubble.2\",\n        \"session@1.0.6-githubble.2\",\n        \"reload@1.1.3-githubble.2\",\n        \"?autoupdate@1.1.6-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"blaze@2.0.5-githubble.2\",\n        \"templating@1.0.12-githubble.2\",\n        \"spacebars@1.0.5-githubble.2\",\n        \"ddp@1.0.15-githubble.2\",\n        \"tracker@1.0.5-githubble.2\"\n      ],\n      \"test-in-browser 1.0.7-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"tinytest@1.0.5-githubble.42\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.3-githubble.42\",\n        \"session@1.0.6-githubble.42\",\n        \"reload@1.1.3-githubble.42\",\n        \"?autoupdate@1.1.6-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"blaze@2.0.5-githubble.42\",\n        \"templating@1.0.12-githubble.42\",\n        \"spacebars@1.0.5-githubble.42\",\n        \"ddp@1.0.15-githubble.42\",\n        \"tracker@1.0.5-githubble.42\"\n      ],\n      \"test-in-browser 1.0.7-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"tinytest@1.0.5-githubble.43\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.3-githubble.43\",\n        \"session@1.0.6-githubble.43\",\n        \"reload@1.1.3-githubble.43\",\n        \"?autoupdate@1.1.6-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"blaze@2.0.5-githubble.43\",\n        \"templating@1.0.12-githubble.43\",\n        \"spacebars@1.0.5-githubble.43\",\n        \"ddp@1.0.15-githubble.43\",\n        \"tracker@1.0.5-githubble.43\"\n      ],\n      \"test-in-browser 1.0.7-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"tinytest@1.0.5-rc.0\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.3-rc.0\",\n        \"session@1.1.0-rc.0\",\n        \"reload@1.1.3-rc.0\",\n        \"?autoupdate@1.2.0-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"blaze@2.1.0-rc.0\",\n        \"templating@1.1.0-rc.0\",\n        \"spacebars@1.0.6-rc.0\",\n        \"ddp@1.1.0-rc.0\",\n        \"tracker@1.0.6-rc.0\"\n      ],\n      \"test-in-browser 1.0.7-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"tinytest@1.0.4\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.2\",\n        \"session@1.0.5\",\n        \"reload@1.1.2\",\n        \"?autoupdate@1.1.5\",\n        \"random@1.0.2\",\n        \"blaze@2.0.5-vs.1\",\n        \"templating@1.0.12-vs.1\",\n        \"spacebars@1.0.5\",\n        \"ddp@1.0.15-vs.1\",\n        \"tracker@1.0.5\"\n      ],\n      \"test-in-browser 1.0.7-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"tinytest@1.0.4\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.2\",\n        \"session@1.0.5\",\n        \"reload@1.1.2\",\n        \"?autoupdate@1.1.5\",\n        \"random@1.0.2\",\n        \"blaze@2.0.5-vs.2\",\n        \"templating@1.0.12-vs.2\",\n        \"spacebars@1.0.5\",\n        \"ddp@1.0.15-vs.2\",\n        \"tracker@1.0.5\"\n      ],\n      \"test-in-browser 1.0.7-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"tinytest@1.0.5-winr.0\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.3-winr.0\",\n        \"session@1.0.6-winr.0\",\n        \"reload@1.1.3-winr.0\",\n        \"?autoupdate@1.1.5-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"blaze@2.0.5-winr.0\",\n        \"templating@1.0.11-winr.0\",\n        \"spacebars@1.0.5-winr.0\",\n        \"ddp@1.0.14-winr.0\",\n        \"tracker@1.0.5-winr.0\"\n      ],\n      \"test-in-browser 1.0.7-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"tinytest@1.0.5-winr.1\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"session@1.0.6-winr.1\",\n        \"reload@1.1.3-winr.1\",\n        \"?autoupdate@1.1.5-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"blaze@2.0.5-winr.1\",\n        \"templating@1.0.11-winr.1\",\n        \"spacebars@1.0.5-winr.1\",\n        \"ddp@1.0.14-winr.1\",\n        \"tracker@1.0.5-winr.1\"\n      ],\n      \"test-in-browser 1.0.7-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"tinytest@1.0.5-winr.2\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.3-winr.2\",\n        \"session@1.0.6-winr.2\",\n        \"reload@1.1.3-winr.3\",\n        \"?autoupdate@1.1.5-winr.4\",\n        \"random@1.0.3-winr.2\",\n        \"blaze@2.0.5-winr.2\",\n        \"templating@1.0.11-winr.4\",\n        \"spacebars@1.0.5-winr.4\",\n        \"ddp@1.0.14-winr.4\",\n        \"tracker@1.0.5-winr.4\"\n      ],\n      \"test-in-browser 1.0.7-winr.3\": [\n        \"meteor@1.1.5-winr.5\",\n        \"tinytest@1.0.5-winr.2\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.3-winr.2\",\n        \"session@1.0.6-winr.2\",\n        \"reload@1.1.3-winr.3\",\n        \"?autoupdate@1.1.5-winr.4\",\n        \"random@1.0.3-winr.2\",\n        \"blaze@2.0.5-winr.3\",\n        \"templating@1.0.11-winr.6\",\n        \"spacebars@1.0.5-winr.5\",\n        \"ddp@1.0.14-winr.5\",\n        \"tracker@1.0.5-winr.4\"\n      ],\n      \"test-in-browser 1.0.7-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"tinytest@1.0.5-winr.3\",\n        \"bootstrap@1.0.1\",\n        \"underscore@1.0.3-winr.2\",\n        \"session@1.0.6-winr.3\",\n        \"reload@1.1.3-winr.3\",\n        \"?autoupdate@1.1.6-winr.4\",\n        \"random@1.0.3-winr.2\",\n        \"blaze@2.0.5-winr.5\",\n        \"templating@1.0.12-winr.7\",\n        \"spacebars@1.0.6-winr.5\",\n        \"ddp@1.0.15-winr.6\",\n        \"tracker@1.0.6-winr.4\"\n      ],\n      \"bootstrap 1.0.0\": [\n        \"jquery@1.0.0\",\n        \"meteor@1.0.2\"\n      ],\n      \"bootstrap 1.0.1-rc0\": [\n        \"meteor\",\n        \"jquery\"\n      ],\n      \"bootstrap 1.0.1\": [\n        \"jquery@1.0.0\",\n        \"meteor@1.0.3\"\n      ],\n      \"test-helpers 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\",\n        \"tinytest@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"ddp@10.0.0-glasser.isopacket.0\",\n        \"jquery@1.5.0-glasser.isopacket.0\"\n      ],\n      \"test-helpers 1.0.0\": [\n        \"deps@1.0.1\",\n        \"ejson@1.0.0\",\n        \"jquery@1.0.0\",\n        \"livedata@1.0.7\",\n        \"meteor@1.0.2\",\n        \"random@1.0.0\",\n        \"tinytest@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"test-helpers 1.0.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"tinytest\",\n        \"random\",\n        \"livedata\",\n        \"jquery\"\n      ],\n      \"test-helpers 1.0.1-rc1\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"tinytest\",\n        \"random\",\n        \"ddp\",\n        \"jquery\"\n      ],\n      \"test-helpers 1.0.1\": [\n        \"ddp@1.0.8\",\n        \"ejson@1.0.1\",\n        \"jquery@1.0.0\",\n        \"meteor@1.0.3\",\n        \"random@1.0.0\",\n        \"tinytest@1.0.1\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"test-helpers 1.0.2-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"tinytest\",\n        \"random\",\n        \"ddp\",\n        \"jquery\"\n      ],\n      \"test-helpers 1.0.2-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"tinytest\",\n        \"random\",\n        \"ddp\",\n        \"jquery\"\n      ],\n      \"test-helpers 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"ejson@1.0.4-pre.2\",\n        \"tinytest@1.0.3-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"ddp@1.0.10-pre.2\",\n        \"jquery@1.0.1-pre.2\"\n      ],\n      \"test-helpers 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"tinytest@1.0.3-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ddp@1.0.10-rc.0\",\n        \"jquery@1.0.1-rc.0\"\n      ],\n      \"test-helpers 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"tracker@1.0.3-win.0\",\n        \"ejson@1.0.4-win.0\",\n        \"tinytest@1.0.3-win.0\",\n        \"random@1.0.1-win.0\",\n        \"ddp@1.0.11-win.0\",\n        \"jquery@1.0.1-win.0\"\n      ],\n      \"test-helpers 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"ejson@1.0.4\",\n        \"tinytest@1.0.3\",\n        \"random@1.0.1\",\n        \"ddp@1.0.10\",\n        \"jquery@1.0.1\"\n      ],\n      \"test-helpers 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"tinytest@1.0.4-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"ddp@1.0.12-ipc.0\",\n        \"jquery@1.0.2-ipc.0\"\n      ],\n      \"test-helpers 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"tracker@1.0.4-rc.1\",\n        \"ejson@1.0.5-rc.1\",\n        \"tinytest@1.0.4-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"ddp@1.0.13-rc.1\",\n        \"jquery@1.0.2-rc.1\"\n      ],\n      \"test-helpers 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"tracker@1.0.4-slava.0\",\n        \"ejson@1.0.5-slava.0\",\n        \"tinytest@1.0.4-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"ddp@1.0.13-slava.0\",\n        \"jquery@1.0.2-slava.0\"\n      ],\n      \"test-helpers 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"tracker@1.0.4-win.0\",\n        \"ejson@1.0.5-win.0\",\n        \"tinytest@1.0.4-win.0\",\n        \"random@1.0.2-win.0\",\n        \"ddp@1.0.12-win.0\",\n        \"jquery@1.0.2-win.0\"\n      ],\n      \"test-helpers 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"tracker@1.0.4-winr.0\",\n        \"ejson@1.0.5-winr.0\",\n        \"tinytest@1.0.4-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"ddp@1.0.13-winr.0\",\n        \"jquery@1.0.2-winr.0\"\n      ],\n      \"test-helpers 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.4\",\n        \"ejson@1.0.5\",\n        \"tinytest@1.0.4\",\n        \"random@1.0.2\",\n        \"ddp@1.0.13\",\n        \"jquery@1.0.2\"\n      ],\n      \"test-helpers 1.0.4-blz.0\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5\",\n        \"ejson@1.0.5\",\n        \"tinytest@1.0.4\",\n        \"random@1.0.2\",\n        \"ddp@1.0.15-blz.0\",\n        \"jquery@1.11.3\"\n      ],\n      \"test-helpers 1.0.4-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"tracker@1.0.5-eachin.0\",\n        \"ejson@1.0.6-eachin.0\",\n        \"tinytest@1.0.5-eachin.0\",\n        \"random@1.0.3-eachin.0\",\n        \"ddp@1.0.14-eachin.0\",\n        \"jquery@1.11.3-winr.2_1\"\n      ],\n      \"test-helpers 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"tracker@1.0.5-eachin.43\",\n        \"ejson@1.0.6-eachin.43\",\n        \"tinytest@1.0.5-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"ddp@1.0.15-eachin.43\",\n        \"jquery@1.11.3-eachin.43_1\"\n      ],\n      \"test-helpers 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"tracker@1.0.5-githubble.0\",\n        \"ejson@1.0.6-githubble.0\",\n        \"tinytest@1.0.5-githubble.0\",\n        \"random@1.0.3-githubble.0\",\n        \"ddp@1.0.15-githubble.0\",\n        \"jquery@1.11.3-githubble.0_1\"\n      ],\n      \"test-helpers 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"tracker@1.0.5-githubble.2\",\n        \"ejson@1.0.6-githubble.2\",\n        \"tinytest@1.0.5-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"ddp@1.0.15-githubble.2\",\n        \"jquery@1.11.3-githubble.2_1\"\n      ],\n      \"test-helpers 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"tracker@1.0.5-githubble.42\",\n        \"ejson@1.0.6-githubble.42\",\n        \"tinytest@1.0.5-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"ddp@1.0.15-githubble.42\",\n        \"jquery@1.11.3-githubble.42_1\"\n      ],\n      \"test-helpers 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"tracker@1.0.5-githubble.43\",\n        \"ejson@1.0.6-githubble.43\",\n        \"tinytest@1.0.5-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"ddp@1.0.15-githubble.43\",\n        \"jquery@1.11.3-githubble.43_1\"\n      ],\n      \"test-helpers 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"tracker@1.0.6-rc.0\",\n        \"ejson@1.0.6-rc.0\",\n        \"tinytest@1.0.5-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"ddp@1.1.0-rc.0\",\n        \"jquery@1.11.3-rc.0_2\"\n      ],\n      \"test-helpers 1.0.4-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5\",\n        \"ejson@1.0.5\",\n        \"tinytest@1.0.4\",\n        \"random@1.0.2\",\n        \"ddp@1.0.15-vs.1\",\n        \"jquery@1.11.3\"\n      ],\n      \"test-helpers 1.0.4-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5\",\n        \"ejson@1.0.5\",\n        \"tinytest@1.0.4\",\n        \"random@1.0.2\",\n        \"ddp@1.0.15-vs.2\",\n        \"jquery@1.11.3\"\n      ],\n      \"test-helpers 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"tracker@1.0.5-winr.0\",\n        \"ejson@1.0.6-winr.0\",\n        \"tinytest@1.0.5-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"ddp@1.0.14-winr.0\",\n        \"jquery@1.0.3-winr.0\"\n      ],\n      \"test-helpers 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"tracker@1.0.5-winr.1\",\n        \"ejson@1.0.6-winr.1\",\n        \"tinytest@1.0.5-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"ddp@1.0.14-winr.1\",\n        \"jquery@1.0.3-winr.1\"\n      ],\n      \"test-helpers 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"ejson@1.0.6-winr.2\",\n        \"tinytest@1.0.5-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"ddp@1.0.14-winr.4\",\n        \"jquery@1.11.3-winr.2\"\n      ],\n      \"test-helpers 1.0.4-winr.3\": [\n        \"meteor@1.1.5-winr.5\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"ejson@1.0.6-winr.2\",\n        \"tinytest@1.0.5-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"ddp@1.0.14-winr.5\",\n        \"jquery@1.11.3-winr.2_1\"\n      ],\n      \"templating 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"blaze@10.0.0-glasser.isopacket.0\"\n      ],\n      \"templating 1.0.0\": [\n        \"meteor\",\n        \"ui\"\n      ],\n      \"templating 1.0.1\": [\n        \"meteor\",\n        \"ui\"\n      ],\n      \"templating 1.0.2\": [\n        \"meteor\",\n        \"ui\"\n      ],\n      \"templating 1.0.3\": [\n        \"meteor\",\n        \"ui\"\n      ],\n      \"templating 1.0.4-cordova1\": [\n        \"meteor\",\n        \"ui\"\n      ],\n      \"templating 1.0.4-cordova4\": [\n        \"meteor\",\n        \"ui\"\n      ],\n      \"templating 1.0.4\": [\n        \"meteor@1.0.2\",\n        \"ui@1.0.0\"\n      ],\n      \"templating 1.0.5-glasser1\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"templating 1.0.5-rc0\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"templating 1.0.5-rc2\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"templating 1.0.5\": [\n        \"blaze@2.0.0\",\n        \"meteor@1.0.3\"\n      ],\n      \"templating 1.0.6-ekate\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"templating 1.0.6-rc0\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"templating 1.0.6-rc1\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"templating 1.0.6-rc2\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"templating 1.0.6\": [\n        \"blaze@2.0.0\",\n        \"meteor@1.1.0\"\n      ],\n      \"templating 1.0.7-greenspan1\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"templating 1.0.7-greenspan3\": [\n        \"meteor@1.1.2-pre.0\",\n        \"blaze@2.0.2-pre.0\"\n      ],\n      \"templating 1.0.7-rc.1\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"templating 1.0.7-rc0\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"templating 1.0.7\": [\n        \"blaze@2.0.1\",\n        \"meteor@1.1.1\"\n      ],\n      \"templating 1.0.8-nim.0\": [\n        \"meteor@1.1.2-nim.0\",\n        \"blaze@2.0.2-rc.0\"\n      ],\n      \"templating 1.0.8-pre.0\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"templating 1.0.8-pre.1\": [\n        \"meteor\",\n        \"blaze\"\n      ],\n      \"templating 1.0.8-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"blaze@2.0.2-pre.2\"\n      ],\n      \"templating 1.0.8-pre.3\": [\n        \"meteor@1.1.2-pre.3\",\n        \"blaze@2.0.2-pre.2\"\n      ],\n      \"templating 1.0.8-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"blaze@2.0.2-rc.0\"\n      ],\n      \"templating 1.0.8-rc.1\": [\n        \"meteor@1.1.2-ekate.1\",\n        \"blaze@2.0.2-rc.0\"\n      ],\n      \"templating 1.0.8-rc.2\": [\n        \"meteor@1.1.2-rc.3\",\n        \"blaze@2.0.2-rc.0\"\n      ],\n      \"templating 1.0.8-rc.3\": [\n        \"meteor@1.1.2-rc.3\",\n        \"underscore@1.0.1-rc.0\",\n        \"blaze@2.0.2-rc.0\"\n      ],\n      \"templating 1.0.8\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"blaze@2.0.2\"\n      ],\n      \"templating 1.0.8_1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"blaze@2.0.2\"\n      ],\n      \"templating 1.0.9-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\",\n        \"blaze@2.0.3-rc.0\"\n      ],\n      \"templating 1.0.9-rc.1\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\",\n        \"blaze@2.0.3-rc.0\"\n      ],\n      \"templating 1.0.9-rc.2\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\",\n        \"blaze@2.0.3-rc.0\"\n      ],\n      \"templating 1.0.9-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"blaze@2.0.3-win.0\"\n      ],\n      \"templating 1.0.9\": [\n        \"meteor@1.1.3\",\n        \"underscore@1.0.1\",\n        \"blaze@2.0.3\"\n      ],\n      \"templating 1.0.10-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"blaze@2.0.4-ipc.0\",\n        \"spacebars-compiler@1.0.4-ipc.0\"\n      ],\n      \"templating 1.0.10-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"blaze@2.0.4-rc.1\",\n        \"spacebars-compiler@1.0.4-rc.1\"\n      ],\n      \"templating 1.0.10-rc.2\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"blaze@2.0.4-rc.1\",\n        \"spacebars-compiler@1.0.4-rc.1\"\n      ],\n      \"templating 1.0.10-rc.3\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"blaze@2.0.4-rc.1\",\n        \"spacebars-compiler@1.0.4-rc.1\"\n      ],\n      \"templating 1.0.10-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"blaze@2.0.4-slava.0\",\n        \"spacebars-compiler@1.0.4-slava.0\"\n      ],\n      \"templating 1.0.10-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"blaze@2.0.4-win.0\"\n      ],\n      \"templating 1.0.10-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"blaze@2.0.4-winr.0\",\n        \"spacebars-compiler@1.0.4-winr.0\"\n      ],\n      \"templating 1.0.10-winr.1\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"blaze@2.0.4-winr.0\",\n        \"spacebars-compiler@1.0.4-winr.0\"\n      ],\n      \"templating 1.0.10\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"blaze@2.0.4\",\n        \"spacebars-compiler@1.0.4\"\n      ],\n      \"templating 1.0.11-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-winr.2\",\n        \"blaze@2.0.5-eachin.0\",\n        \"spacebars-compiler@1.0.5-eachin.0\"\n      ],\n      \"templating 1.0.11-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-winr.2\",\n        \"blaze@2.0.5-githubble.0\",\n        \"spacebars-compiler@1.0.5-githubble.0\"\n      ],\n      \"templating 1.0.11-rc.0\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"blaze@2.0.4\",\n        \"spacebars-compiler@1.0.4\"\n      ],\n      \"templating 1.0.11-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"blaze@2.0.5-winr.0\",\n        \"spacebars-compiler@1.0.5-winr.0\"\n      ],\n      \"templating 1.0.11-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"blaze@2.0.5-winr.1\",\n        \"spacebars-compiler@1.0.5-winr.1\"\n      ],\n      \"templating 1.0.11-winr.2\": [\n        \"meteor@1.1.5-winr.2\",\n        \"underscore@1.0.2\",\n        \"blaze@2.0.4\",\n        \"spacebars-compiler@1.0.4\"\n      ],\n      \"templating 1.0.11-winr.3\": [\n        \"meteor@1.1.5-winr.3\",\n        \"underscore@1.0.2\",\n        \"blaze@2.0.4\",\n        \"spacebars-compiler@1.0.4\"\n      ],\n      \"templating 1.0.11-winr.4\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"blaze@2.0.5-winr.2\",\n        \"spacebars-compiler@1.0.5-winr.2\"\n      ],\n      \"templating 1.0.11-winr.5\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"blaze@2.0.5-winr.2\",\n        \"spacebars-compiler@1.0.5-winr.2\"\n      ],\n      \"templating 1.0.11-winr.6\": [\n        \"meteor@1.1.5-winr.5\",\n        \"underscore@1.0.3-winr.2\",\n        \"blaze@2.0.5-winr.3\",\n        \"spacebars-compiler@1.0.5-winr.2\"\n      ],\n      \"templating 1.0.11\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"blaze@2.0.4\",\n        \"spacebars-compiler@1.0.4\"\n      ],\n      \"templating 1.0.12-blz.0\": [\n        \"meteor@1.1.5-blz.0\",\n        \"underscore@1.0.2\",\n        \"blaze@2.0.5-blz.1\",\n        \"spacebars-compiler@1.0.4\"\n      ],\n      \"templating 1.0.12-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"blaze@2.0.5-eachin.43\",\n        \"spacebars-compiler@1.0.5-eachin.43\"\n      ],\n      \"templating 1.0.12-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-winr.2\",\n        \"blaze@2.0.5-githubble.0\",\n        \"spacebars-compiler@1.0.5-githubble.0\"\n      ],\n      \"templating 1.0.12-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"blaze@2.0.5-githubble.2\",\n        \"spacebars-compiler@1.0.5-githubble.2\"\n      ],\n      \"templating 1.0.12-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"blaze@2.0.5-githubble.42\",\n        \"spacebars-compiler@1.0.5-githubble.42\"\n      ],\n      \"templating 1.0.12-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"blaze@2.0.5-githubble.43\",\n        \"spacebars-compiler@1.0.5-githubble.43\"\n      ],\n      \"templating 1.0.12-oplog-backlog.0\": [\n        \"meteor@1.1.5-oplog-backlog.0\",\n        \"underscore@1.0.2\",\n        \"blaze@2.0.4\",\n        \"spacebars-compiler@1.0.4\"\n      ],\n      \"templating 1.0.12-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"underscore@1.0.2\",\n        \"blaze@2.0.5-vs.1\",\n        \"spacebars-compiler@1.0.4\"\n      ],\n      \"templating 1.0.12-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"underscore@1.0.2\",\n        \"blaze@2.0.5-vs.2\",\n        \"spacebars-compiler@1.0.4\"\n      ],\n      \"templating 1.0.12-winr.6\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"blaze@2.0.5-winr.4\",\n        \"spacebars-compiler@1.0.5-winr.3\"\n      ],\n      \"templating 1.0.12-winr.7\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"blaze@2.0.5-winr.5\",\n        \"spacebars-compiler@1.0.5-winr.4\"\n      ],\n      \"templating 1.1.0-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"blaze@2.1.0-rc.0\",\n        \"minifiers@1.1.4-rc.0\",\n        \"spacebars-compiler@1.0.5-rc.0\"\n      ],\n      \"templating 1.1.1-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"blaze@2.1.0-rc.0\",\n        \"minifiers@1.1.5-rc.0\",\n        \"spacebars-compiler@1.0.5-rc.0\"\n      ],\n      \"stylus 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"stylus 0.46.3-cordova1\": [\n        \"meteor\"\n      ],\n      \"stylus 0.46.3-glasser1\": [\n        \"meteor\"\n      ],\n      \"stylus 0.46.3\": [\n        \"meteor\"\n      ],\n      \"stylus 1.0.0\": [\n        \"meteor\"\n      ],\n      \"stylus 1.0.1\": [\n        \"meteor\"\n      ],\n      \"stylus 1.0.2\": [\n        \"meteor\"\n      ],\n      \"stylus 1.0.3-cordova4\": [\n        \"meteor\"\n      ],\n      \"stylus 1.0.3-ekate\": [\n        \"meteor\"\n      ],\n      \"stylus 1.0.3-glasser1\": [\n        \"meteor\"\n      ],\n      \"stylus 1.0.3-rc1\": [\n        \"meteor\"\n      ],\n      \"stylus 1.0.3\": [\n        \"meteor@1.0.2\"\n      ],\n      \"stylus 1.0.4\": [\n        \"meteor@1.1.0\"\n      ],\n      \"stylus 1.0.5-pre.0\": [\n        \"meteor\"\n      ],\n      \"stylus 1.0.5-pre.1\": [\n        \"meteor\"\n      ],\n      \"stylus 1.0.5-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"stylus 1.0.5-pre.3\": [\n        \"meteor@1.1.2-pre.3\"\n      ],\n      \"stylus 1.0.5-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"stylus 1.0.5-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"stylus 1.0.5\": [\n        \"meteor@1.1.2\"\n      ],\n      \"stylus 1.0.6-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"stylus 1.0.6-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"stylus 1.0.6-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"stylus 1.0.6-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"stylus 1.0.6-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"stylus 1.0.6\": [\n        \"meteor@1.1.4\"\n      ],\n      \"stylus 1.0.7-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"stylus 1.0.7-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"stylus 1.0.7-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"stylus 1.0.7-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"stylus 1.0.7-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"stylus 1.0.7-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"stylus 1.0.7-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"stylus 1.0.7-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"stylus 1.0.7-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"stylus 1.0.7-winr.3\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"startup 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"startup 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"startup 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"startup 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"startup 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"startup 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"startup 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"startup 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"startup 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"startup 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"startup 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"startup 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"startup 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"startup 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"startup 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"startup 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"startup 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"startup 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"startup 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"startup 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"startup 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"startup 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"startup 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"standard-app-packages 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"meteor-platform@10.0.0-glasser.isopacket.0\"\n      ],\n      \"standard-app-packages 1.0.0-cordova1\": [\n        \"meteor\",\n        \"reload\",\n        \"autoupdate\",\n        \"webapp\",\n        \"logging\",\n        \"deps\",\n        \"session\",\n        \"livedata\",\n        \"mongo-livedata\",\n        \"ui\",\n        \"spacebars\",\n        \"templating\",\n        \"check\",\n        \"underscore\",\n        \"jquery\",\n        \"random\",\n        \"ejson\",\n        \"fastclick\",\n        \"mobile-status-bar\"\n      ],\n      \"standard-app-packages 1.0.0\": [\n        \"autoupdate@1.0.4\",\n        \"check@1.0.0\",\n        \"deps@1.0.1\",\n        \"ejson@1.0.0\",\n        \"jquery@1.0.0\",\n        \"livedata@1.0.7\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.2\",\n        \"mongo-livedata@1.0.3\",\n        \"random@1.0.0\",\n        \"reload@1.0.0\",\n        \"session@1.0.0\",\n        \"spacebars@1.0.0\",\n        \"templating@1.0.4\",\n        \"ui@1.0.0\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.2\"\n      ],\n      \"standard-app-packages 1.0.1-rc0\": [\n        \"meteor\",\n        \"meteor-platform\"\n      ],\n      \"standard-app-packages 1.0.1\": [\n        \"meteor@1.0.3\",\n        \"meteor-platform@1.0.1\"\n      ],\n      \"standard-app-packages 1.0.2-rc0\": [\n        \"meteor\",\n        \"meteor-platform\"\n      ],\n      \"standard-app-packages 1.0.2\": [\n        \"meteor@1.1.1\",\n        \"meteor-platform@1.1.1\"\n      ],\n      \"standard-app-packages 1.0.3-nim.2\": [\n        \"meteor@1.1.2-nim.0\",\n        \"meteor-platform@1.1.2-nim.1\"\n      ],\n      \"standard-app-packages 1.0.3-pre.0\": [\n        \"meteor\",\n        \"meteor-platform\"\n      ],\n      \"standard-app-packages 1.0.3-pre.1\": [\n        \"meteor\",\n        \"meteor-platform\"\n      ],\n      \"standard-app-packages 1.0.3-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"meteor-platform@1.1.2-pre.2\"\n      ],\n      \"standard-app-packages 1.0.3-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"meteor-platform@1.1.2-rc.0\"\n      ],\n      \"standard-app-packages 1.0.3-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"meteor-platform@1.2.0-win.0\"\n      ],\n      \"standard-app-packages 1.0.3\": [\n        \"meteor@1.1.2\",\n        \"meteor-platform@1.1.2\"\n      ],\n      \"standard-app-packages 1.0.4-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"meteor-platform@1.2.1-ipc.0\"\n      ],\n      \"standard-app-packages 1.0.4-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"meteor-platform@1.2.1-rc.1\"\n      ],\n      \"standard-app-packages 1.0.4-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"meteor-platform@1.2.1-slava.0\"\n      ],\n      \"standard-app-packages 1.0.4-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"meteor-platform@1.2.1-win.0\"\n      ],\n      \"standard-app-packages 1.0.4-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"meteor-platform@1.2.1-winr.0\"\n      ],\n      \"standard-app-packages 1.0.4\": [\n        \"meteor@1.1.4\",\n        \"meteor-platform@1.2.1\"\n      ],\n      \"standard-app-packages 1.0.5-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"meteor-platform@1.2.1-eachin.0\"\n      ],\n      \"standard-app-packages 1.0.5-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"meteor-platform@1.2.2-eachin.43\"\n      ],\n      \"standard-app-packages 1.0.5-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"meteor-platform@1.2.2-githubble.0\"\n      ],\n      \"standard-app-packages 1.0.5-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"meteor-platform@1.2.2-githubble.1\"\n      ],\n      \"standard-app-packages 1.0.5-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"meteor-platform@1.2.2-githubble.42\"\n      ],\n      \"standard-app-packages 1.0.5-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"meteor-platform@1.2.2-githubble.43\"\n      ],\n      \"standard-app-packages 1.0.5-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"meteor-platform@1.2.2-rc.0\"\n      ],\n      \"standard-app-packages 1.0.5-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"meteor-platform@1.2.2-winr.0\"\n      ],\n      \"standard-app-packages 1.0.5-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"meteor-platform@1.2.2-winr.1\"\n      ],\n      \"standard-app-packages 1.0.5-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"meteor-platform@1.2.1-winr.3\"\n      ],\n      \"srp 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"check@10.0.0-glasser.isopacket.0\",\n        \"sha@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\"\n      ],\n      \"srp 1.0.0\": [\n        \"check@1.0.0\",\n        \"meteor@1.0.2\",\n        \"random@1.0.0\",\n        \"sha@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"srp 1.0.1-pre.0\": [\n        \"meteor\",\n        \"random\",\n        \"check\",\n        \"sha\",\n        \"underscore\"\n      ],\n      \"srp 1.0.1-pre.1\": [\n        \"meteor@1.1.2-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"check@1.0.2-pre.2\",\n        \"sha@1.0.1-pre.2\",\n        \"underscore@1.0.1-pre.2\"\n      ],\n      \"srp 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"sha@1.0.1-rc.0\",\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"srp 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"random@1.0.1-win.0\",\n        \"check@1.0.2-win.0\",\n        \"sha@1.0.1-win.0\",\n        \"underscore@1.0.1-win.0\"\n      ],\n      \"srp 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"random@1.0.1\",\n        \"check@1.0.2\",\n        \"sha@1.0.1\",\n        \"underscore@1.0.1\"\n      ],\n      \"srp 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"check@1.0.3-ipc.0\",\n        \"sha@1.0.2-ipc.0\",\n        \"underscore@1.0.2-ipc.0\"\n      ],\n      \"srp 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"check@1.0.3-rc.1\",\n        \"sha@1.0.2-rc.1\",\n        \"underscore@1.0.2-rc.1\"\n      ],\n      \"srp 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"check@1.0.3-slava.0\",\n        \"sha@1.0.2-slava.0\",\n        \"underscore@1.0.2-slava.0\"\n      ],\n      \"srp 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"random@1.0.2-win.0\",\n        \"check@1.0.3-win.0\",\n        \"sha@1.0.2-win.0\",\n        \"underscore@1.0.2-win.0\"\n      ],\n      \"srp 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"check@1.0.3-winr.0\",\n        \"sha@1.0.2-winr.0\",\n        \"underscore@1.0.2-winr.0\"\n      ],\n      \"srp 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"random@1.0.2\",\n        \"check@1.0.3\",\n        \"sha@1.0.2\",\n        \"underscore@1.0.2\"\n      ],\n      \"srp 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"check@1.0.4-eachin.43\",\n        \"sha@1.0.3-eachin.43\",\n        \"underscore@1.0.3-eachin.43\"\n      ],\n      \"srp 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"random@1.0.3-githubble.0\",\n        \"check@1.0.4-win.0\",\n        \"sha@1.0.3-githubble.0\",\n        \"underscore@1.0.3-githubble.0\"\n      ],\n      \"srp 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"check@1.0.4-win.0\",\n        \"sha@1.0.3-githubble.2\",\n        \"underscore@1.0.3-githubble.2\"\n      ],\n      \"srp 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"check@1.0.4-win.0\",\n        \"sha@1.0.3-githubble.42\",\n        \"underscore@1.0.3-githubble.42\"\n      ],\n      \"srp 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"check@1.0.4-githubble.43\",\n        \"sha@1.0.3-githubble.43\",\n        \"underscore@1.0.3-githubble.43\"\n      ],\n      \"srp 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"check@1.0.5-rc.0\",\n        \"sha@1.0.3-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"srp 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"check@1.0.4-winr.0\",\n        \"sha@1.0.3-winr.0\",\n        \"underscore@1.0.3-winr.0\"\n      ],\n      \"srp 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"check@1.0.4-winr.1\",\n        \"sha@1.0.3-winr.1\",\n        \"underscore@1.0.3-winr.1\"\n      ],\n      \"srp 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"random@1.0.3-winr.2\",\n        \"check@1.0.4-win.0\",\n        \"sha@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"spiderable 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"webapp@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"templating@10.0.0-glasser.isopacket.0\"\n      ],\n      \"spiderable 1.0.0\": [\n        \"meteor\",\n        \"webapp\",\n        \"underscore\",\n        \"templating\"\n      ],\n      \"spiderable 1.0.1-cordova4\": [\n        \"meteor\",\n        \"webapp\",\n        \"underscore\",\n        \"templating\"\n      ],\n      \"spiderable 1.0.1\": [\n        \"meteor@1.0.2\",\n        \"templating@1.0.4\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.2\"\n      ],\n      \"spiderable 1.0.2-rc1\": [\n        \"meteor\",\n        \"webapp\",\n        \"underscore\",\n        \"templating\"\n      ],\n      \"spiderable 1.0.2\": [\n        \"meteor@1.0.2\",\n        \"templating@1.0.4\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.2\"\n      ],\n      \"spiderable 1.0.3-rc0\": [\n        \"meteor\",\n        \"webapp\",\n        \"underscore\",\n        \"templating\"\n      ],\n      \"spiderable 1.0.3\": [\n        \"meteor@1.0.3\",\n        \"templating@1.0.5\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.3\"\n      ],\n      \"spiderable 1.0.4-pre.0\": [\n        \"meteor\",\n        \"webapp\",\n        \"underscore\",\n        \"templating\"\n      ],\n      \"spiderable 1.0.4-pre.1\": [\n        \"meteor\",\n        \"webapp\",\n        \"underscore\",\n        \"templating\"\n      ],\n      \"spiderable 1.0.4-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"webapp@1.1.3-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"templating@1.0.8-pre.2\"\n      ],\n      \"spiderable 1.0.4-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"webapp@1.1.3-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"templating@1.0.8-rc.0\"\n      ],\n      \"spiderable 1.0.4\": [\n        \"meteor@1.1.2\",\n        \"webapp@1.1.3\",\n        \"underscore@1.0.1\",\n        \"templating@1.0.8\"\n      ],\n      \"spiderable 1.0.5-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"webapp@1.1.4-rc.2\",\n        \"underscore@1.0.1\",\n        \"templating@1.0.9-rc.1\"\n      ],\n      \"spiderable 1.0.5-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"webapp@1.1.4-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"templating@1.0.9-win.0\"\n      ],\n      \"spiderable 1.0.5\": [\n        \"meteor@1.1.3\",\n        \"webapp@1.1.4\",\n        \"underscore@1.0.1\",\n        \"templating@1.0.9\"\n      ],\n      \"spiderable 1.0.6-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"webapp@1.1.5-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"templating@1.0.10-ipc.0\"\n      ],\n      \"spiderable 1.0.6-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"webapp@1.1.5-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"templating@1.0.10-rc.1\"\n      ],\n      \"spiderable 1.0.6-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"webapp@1.1.5-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"templating@1.0.10-slava.0\"\n      ],\n      \"spiderable 1.0.6-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"webapp@1.1.5-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"templating@1.0.10-win.0\"\n      ],\n      \"spiderable 1.0.6-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"webapp@1.1.5-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"templating@1.0.10-winr.0\"\n      ],\n      \"spiderable 1.0.6\": [\n        \"meteor@1.1.4\",\n        \"webapp@1.1.5\",\n        \"underscore@1.0.2\",\n        \"templating@1.0.10\"\n      ],\n      \"spiderable 1.0.7-blz.0\": [\n        \"meteor@1.1.4\",\n        \"webapp@1.1.6\",\n        \"underscore@1.0.2\",\n        \"templating@1.0.11\"\n      ],\n      \"spiderable 1.0.7-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"webapp@1.1.7-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"templating@1.0.12-eachin.43\"\n      ],\n      \"spiderable 1.0.7-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"webapp@1.1.7-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"templating@1.0.12-githubble.0\"\n      ],\n      \"spiderable 1.0.7-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"webapp@1.1.7-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"templating@1.0.12-githubble.2\"\n      ],\n      \"spiderable 1.0.7-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"webapp@1.1.7-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"templating@1.0.12-githubble.42\"\n      ],\n      \"spiderable 1.0.7-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"webapp@1.1.7-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"templating@1.0.12-githubble.43\"\n      ],\n      \"spiderable 1.0.7-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"webapp@1.2.0-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"templating@1.1.0-rc.0\"\n      ],\n      \"spiderable 1.0.7-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"webapp@1.1.7-vs.1\",\n        \"underscore@1.0.2\",\n        \"templating@1.0.12-vs.1\"\n      ],\n      \"spiderable 1.0.7-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"webapp@1.1.7-vs.2\",\n        \"underscore@1.0.2\",\n        \"templating@1.0.12-vs.2\"\n      ],\n      \"spiderable 1.0.7-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"webapp@1.1.6-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"templating@1.0.11-winr.0\"\n      ],\n      \"spiderable 1.0.7-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"webapp@1.1.6-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"templating@1.0.11-winr.1\"\n      ],\n      \"spiderable 1.0.7-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"webapp@1.1.6-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"templating@1.0.11-winr.4\"\n      ],\n      \"spiderable 1.0.7-winr.3\": [\n        \"meteor@1.1.5-winr.5\",\n        \"webapp@1.1.6-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"templating@1.0.11-winr.6\"\n      ],\n      \"spacebars 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"htmljs@10.0.0-glasser.isopacket.0\",\n        \"blaze@10.0.0-glasser.isopacket.0\",\n        \"observe-sequence@10.0.0-glasser.isopacket.0\",\n        \"templating@10.0.0-glasser.isopacket.0\"\n      ],\n      \"spacebars 1.0.0\": [\n        \"htmljs@1.0.0\",\n        \"meteor@1.0.2\",\n        \"observe-sequence@1.0.1\",\n        \"templating@1.0.4\",\n        \"ui@1.0.0\"\n      ],\n      \"spacebars 1.0.1-rc0\": [\n        \"meteor\",\n        \"htmljs\",\n        \"blaze\",\n        \"observe-sequence\",\n        \"templating\"\n      ],\n      \"spacebars 1.0.1-rc1\": [\n        \"meteor\",\n        \"htmljs\",\n        \"blaze\",\n        \"observe-sequence\",\n        \"templating\"\n      ],\n      \"spacebars 1.0.1\": [\n        \"blaze@2.0.0\",\n        \"htmljs@1.0.0\",\n        \"meteor@1.0.3\",\n        \"observe-sequence@1.0.2\",\n        \"templating@1.0.5\"\n      ],\n      \"spacebars 1.0.2-ekate\": [\n        \"meteor\",\n        \"htmljs\",\n        \"blaze\",\n        \"observe-sequence\",\n        \"templating\"\n      ],\n      \"spacebars 1.0.2-rc0\": [\n        \"meteor\",\n        \"htmljs\",\n        \"blaze\",\n        \"observe-sequence\",\n        \"templating\"\n      ],\n      \"spacebars 1.0.2\": [\n        \"blaze@2.0.1\",\n        \"htmljs@1.0.1\",\n        \"meteor@1.1.1\",\n        \"observe-sequence@1.0.2\",\n        \"templating@1.0.7\"\n      ],\n      \"spacebars 1.0.3-pre.0\": [\n        \"meteor\",\n        \"htmljs\",\n        \"blaze\",\n        \"observe-sequence\",\n        \"templating\"\n      ],\n      \"spacebars 1.0.3-pre.1\": [\n        \"meteor\",\n        \"htmljs\",\n        \"blaze\",\n        \"observe-sequence\",\n        \"templating\"\n      ],\n      \"spacebars 1.0.3-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"htmljs@1.0.2-pre.2\",\n        \"blaze@2.0.2-pre.2\",\n        \"observe-sequence@1.0.3-pre.2\",\n        \"templating@1.0.8-pre.2\"\n      ],\n      \"spacebars 1.0.3-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"htmljs@1.0.2-rc.0\",\n        \"blaze@2.0.2-rc.0\",\n        \"observe-sequence@1.0.3-rc.0\",\n        \"templating@1.0.8-rc.0\"\n      ],\n      \"spacebars 1.0.3-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"htmljs@1.0.2-win.0\",\n        \"blaze@2.0.3-win.0\",\n        \"observe-sequence@1.0.3-win.0\",\n        \"templating@1.0.9-win.0\"\n      ],\n      \"spacebars 1.0.3\": [\n        \"meteor@1.1.2\",\n        \"htmljs@1.0.2\",\n        \"blaze@2.0.2\",\n        \"observe-sequence@1.0.3\",\n        \"templating@1.0.8\"\n      ],\n      \"spacebars 1.0.4-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"htmljs@1.0.3-ipc.0\",\n        \"blaze@2.0.4-ipc.0\",\n        \"observe-sequence@1.0.4-ipc.0\",\n        \"templating@1.0.10-ipc.0\"\n      ],\n      \"spacebars 1.0.4-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"htmljs@1.0.3-rc.1\",\n        \"blaze@2.0.4-rc.1\",\n        \"observe-sequence@1.0.4-rc.1\",\n        \"templating@1.0.10-rc.1\"\n      ],\n      \"spacebars 1.0.4-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"htmljs@1.0.3-slava.0\",\n        \"blaze@2.0.4-slava.0\",\n        \"observe-sequence@1.0.4-slava.0\",\n        \"templating@1.0.10-slava.0\"\n      ],\n      \"spacebars 1.0.4-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"htmljs@1.0.3-win.0\",\n        \"blaze@2.0.4-win.0\",\n        \"observe-sequence@1.0.4-win.0\",\n        \"templating@1.0.10-win.0\"\n      ],\n      \"spacebars 1.0.4-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"htmljs@1.0.3-winr.0\",\n        \"blaze@2.0.4-winr.0\",\n        \"observe-sequence@1.0.4-winr.0\",\n        \"templating@1.0.10-winr.0\"\n      ],\n      \"spacebars 1.0.4\": [\n        \"meteor@1.1.4\",\n        \"htmljs@1.0.3\",\n        \"blaze@2.0.4\",\n        \"observe-sequence@1.0.4\",\n        \"templating@1.0.10\"\n      ],\n      \"spacebars 1.0.5-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"htmljs@1.0.4-eachin.0\",\n        \"tracker@1.0.5-eachin.0\",\n        \"blaze@2.0.5-eachin.0\",\n        \"observe-sequence@1.0.5-winr.2\",\n        \"templating@1.0.11-eachin.0\",\n        \"underscore@1.0.3-eachin.0\"\n      ],\n      \"spacebars 1.0.5-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"htmljs@1.0.4-eachin.43\",\n        \"tracker@1.0.5-eachin.43\",\n        \"blaze@2.0.5-eachin.43\",\n        \"observe-sequence@1.0.5-eachin.43\",\n        \"templating@1.0.12-eachin.43\",\n        \"underscore@1.0.3-eachin.43\"\n      ],\n      \"spacebars 1.0.5-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"htmljs@1.0.4-githubble.0\",\n        \"tracker@1.0.5-githubble.0\",\n        \"blaze@2.0.5-githubble.0\",\n        \"observe-sequence@1.0.5-githubble.0\",\n        \"templating@1.0.12-githubble.0\",\n        \"underscore@1.0.3-githubble.0\"\n      ],\n      \"spacebars 1.0.5-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"htmljs@1.0.4-githubble.2\",\n        \"tracker@1.0.5-githubble.2\",\n        \"blaze@2.0.5-githubble.2\",\n        \"observe-sequence@1.0.5-githubble.2\",\n        \"templating@1.0.12-githubble.2\",\n        \"underscore@1.0.3-githubble.2\"\n      ],\n      \"spacebars 1.0.5-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"htmljs@1.0.4-githubble.42\",\n        \"tracker@1.0.5-githubble.42\",\n        \"blaze@2.0.5-githubble.42\",\n        \"observe-sequence@1.0.5-githubble.42\",\n        \"templating@1.0.12-githubble.42\",\n        \"underscore@1.0.3-githubble.42\"\n      ],\n      \"spacebars 1.0.5-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"htmljs@1.0.4-githubble.43\",\n        \"tracker@1.0.5-githubble.43\",\n        \"blaze@2.0.5-githubble.43\",\n        \"observe-sequence@1.0.5-githubble.43\",\n        \"templating@1.0.12-githubble.43\",\n        \"underscore@1.0.3-githubble.43\"\n      ],\n      \"spacebars 1.0.5-rc.0\": [\n        \"meteor@1.1.4\",\n        \"htmljs@1.0.3\",\n        \"tracker@1.0.5-rc.0\",\n        \"blaze@2.0.4\",\n        \"observe-sequence@1.0.4\",\n        \"templating@1.0.11-rc.0\"\n      ],\n      \"spacebars 1.0.5-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"htmljs@1.0.4-winr.0\",\n        \"blaze@2.0.5-winr.0\",\n        \"observe-sequence@1.0.5-winr.0\",\n        \"templating@1.0.11-winr.0\"\n      ],\n      \"spacebars 1.0.5-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"htmljs@1.0.4-winr.1\",\n        \"blaze@2.0.5-winr.1\",\n        \"observe-sequence@1.0.5-winr.1\",\n        \"templating@1.0.11-winr.1\"\n      ],\n      \"spacebars 1.0.5-winr.2\": [\n        \"meteor@1.1.5-winr.2\",\n        \"htmljs@1.0.3\",\n        \"tracker@1.0.5-winr.2\",\n        \"blaze@2.0.4\",\n        \"observe-sequence@1.0.4\",\n        \"templating@1.0.11-winr.2\"\n      ],\n      \"spacebars 1.0.5-winr.3\": [\n        \"meteor@1.1.5-winr.3\",\n        \"htmljs@1.0.3\",\n        \"tracker@1.0.5-winr.3\",\n        \"blaze@2.0.4\",\n        \"observe-sequence@1.0.4\",\n        \"templating@1.0.11-winr.3\"\n      ],\n      \"spacebars 1.0.5-winr.4\": [\n        \"meteor@1.1.5-winr.4\",\n        \"htmljs@1.0.4-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"blaze@2.0.5-winr.2\",\n        \"observe-sequence@1.0.5-winr.2\",\n        \"templating@1.0.11-winr.4\"\n      ],\n      \"spacebars 1.0.5-winr.5\": [\n        \"meteor@1.1.5-winr.5\",\n        \"htmljs@1.0.4-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"blaze@2.0.5-winr.3\",\n        \"observe-sequence@1.0.5-winr.2\",\n        \"templating@1.0.11-winr.6\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"spacebars 1.0.5\": [\n        \"meteor@1.1.4\",\n        \"htmljs@1.0.3\",\n        \"tracker@1.0.5\",\n        \"blaze@2.0.4\",\n        \"observe-sequence@1.0.4\",\n        \"templating@1.0.11\"\n      ],\n      \"spacebars 1.0.6-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"htmljs@1.0.4-rc.0\",\n        \"tracker@1.0.6-rc.0\",\n        \"blaze@2.1.0-rc.0\",\n        \"observe-sequence@1.0.5-rc.0\",\n        \"templating@1.1.0-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"spacebars 1.0.6-winr.5\": [\n        \"meteor@1.1.5-winr.6\",\n        \"htmljs@1.0.4-winr.2\",\n        \"tracker@1.0.6-winr.4\",\n        \"blaze@2.0.5-winr.5\",\n        \"observe-sequence@1.0.5-winr.3\",\n        \"templating@1.0.12-winr.7\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"spacebars-tests 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"spacebars-tests 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"spacebars-tests 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"spacebars-tests 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"spacebars-tests 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"spacebars-tests 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"spacebars-tests 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"spacebars-tests 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"spacebars-tests 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"spacebars-tests 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"spacebars-tests 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"spacebars-tests 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"spacebars-tests 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"spacebars-tests 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"spacebars-tests 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"spacebars-tests 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"spacebars-tests 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"spacebars-tests 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"spacebars-tests 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"spacebars-tests 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"spacebars-tests 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"spacebars-tests 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"spacebars-tests 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"spacebars-tests 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"spacebars-compiler 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"htmljs@10.0.0-glasser.isopacket.0\",\n        \"html-tools@10.0.0-glasser.isopacket.0\",\n        \"blaze-tools@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"minifiers@10.0.0-glasser.isopacket.0\"\n      ],\n      \"spacebars-compiler 1.0.0\": [\n        \"meteor\",\n        \"htmljs\",\n        \"html-tools\",\n        \"blaze-tools\",\n        \"underscore\",\n        \"minifiers\"\n      ],\n      \"spacebars-compiler 1.0.1\": [\n        \"blaze-tools@1.0.0\",\n        \"html-tools@1.0.0\",\n        \"htmljs@1.0.0\",\n        \"meteor@1.0.2\",\n        \"minifiers@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"spacebars-compiler 1.0.2-rc0\": [\n        \"meteor\",\n        \"htmljs\",\n        \"html-tools\",\n        \"blaze-tools\",\n        \"underscore\",\n        \"minifiers\"\n      ],\n      \"spacebars-compiler 1.0.2\": [\n        \"blaze-tools@1.0.0\",\n        \"html-tools@1.0.0\",\n        \"htmljs@1.0.0\",\n        \"meteor@1.0.3\",\n        \"minifiers@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"spacebars-compiler 1.0.3-pre.0\": [\n        \"meteor\",\n        \"htmljs\",\n        \"html-tools\",\n        \"blaze-tools\",\n        \"underscore\",\n        \"minifiers\"\n      ],\n      \"spacebars-compiler 1.0.3-pre.1\": [\n        \"meteor\",\n        \"htmljs\",\n        \"html-tools\",\n        \"blaze-tools\",\n        \"underscore\",\n        \"minifiers\"\n      ],\n      \"spacebars-compiler 1.0.3-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"htmljs@1.0.2-pre.2\",\n        \"html-tools@1.0.2-pre.2\",\n        \"blaze-tools@1.0.1-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"minifiers@1.1.1-pre.2\"\n      ],\n      \"spacebars-compiler 1.0.3-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"htmljs@1.0.2-rc.0\",\n        \"html-tools@1.0.2-rc.0\",\n        \"blaze-tools@1.0.1-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"minifiers@1.1.1-rc.0\"\n      ],\n      \"spacebars-compiler 1.0.3-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"htmljs@1.0.2-win.0\",\n        \"html-tools@1.0.2-win.0\",\n        \"blaze-tools@1.0.1-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"minifiers@1.1.2-win.0\"\n      ],\n      \"spacebars-compiler 1.0.3\": [\n        \"meteor@1.1.2\",\n        \"htmljs@1.0.2\",\n        \"html-tools@1.0.2\",\n        \"blaze-tools@1.0.1\",\n        \"underscore@1.0.1\",\n        \"minifiers@1.1.1\"\n      ],\n      \"spacebars-compiler 1.0.4-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"htmljs@1.0.3-ipc.0\",\n        \"html-tools@1.0.3-ipc.0\",\n        \"blaze-tools@1.0.2-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"minifiers@1.1.3-ipc.0\"\n      ],\n      \"spacebars-compiler 1.0.4-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"htmljs@1.0.3-rc.1\",\n        \"html-tools@1.0.3-rc.1\",\n        \"blaze-tools@1.0.2-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"minifiers@1.1.3-rc.1\"\n      ],\n      \"spacebars-compiler 1.0.4-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"htmljs@1.0.3-slava.0\",\n        \"html-tools@1.0.3-slava.0\",\n        \"blaze-tools@1.0.2-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"minifiers@1.1.3-slava.0\"\n      ],\n      \"spacebars-compiler 1.0.4-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"htmljs@1.0.3-win.0\",\n        \"html-tools@1.0.3-win.0\",\n        \"blaze-tools@1.0.2-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"minifiers@1.1.3-win.0\"\n      ],\n      \"spacebars-compiler 1.0.4-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"htmljs@1.0.3-winr.0\",\n        \"html-tools@1.0.3-winr.0\",\n        \"blaze-tools@1.0.2-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"minifiers@1.1.3-winr.0\"\n      ],\n      \"spacebars-compiler 1.0.4\": [\n        \"meteor@1.1.4\",\n        \"htmljs@1.0.3\",\n        \"html-tools@1.0.3\",\n        \"blaze-tools@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minifiers@1.1.3\"\n      ],\n      \"spacebars-compiler 1.0.5-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"htmljs@1.0.4-winr.2\",\n        \"html-tools@1.0.3-winr.3\",\n        \"blaze-tools@1.0.3-eachin.0\",\n        \"underscore@1.0.3-winr.2\",\n        \"minifiers@1.1.4-winr.4\"\n      ],\n      \"spacebars-compiler 1.0.5-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"htmljs@1.0.4-eachin.43\",\n        \"html-tools@1.0.3-eachin.43\",\n        \"blaze-tools@1.0.3-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"minifiers@1.1.4-eachin.43\"\n      ],\n      \"spacebars-compiler 1.0.5-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"htmljs@1.0.4-winr.2\",\n        \"html-tools@1.0.3-winr.3\",\n        \"blaze-tools@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"minifiers@1.1.4-winr.4\"\n      ],\n      \"spacebars-compiler 1.0.5-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"htmljs@1.0.4-githubble.2\",\n        \"html-tools@1.0.3-githubble.2\",\n        \"blaze-tools@1.0.3-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"minifiers@1.1.4-githubble.2\"\n      ],\n      \"spacebars-compiler 1.0.5-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"htmljs@1.0.4-githubble.42\",\n        \"html-tools@1.0.3-githubble.42\",\n        \"blaze-tools@1.0.3-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"minifiers@1.1.4-githubble.42\"\n      ],\n      \"spacebars-compiler 1.0.5-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"htmljs@1.0.4-githubble.43\",\n        \"html-tools@1.0.3-githubble.43\",\n        \"blaze-tools@1.0.3-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"minifiers@1.1.4-githubble.43\"\n      ],\n      \"spacebars-compiler 1.0.5-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"htmljs@1.0.4-rc.0\",\n        \"html-tools@1.0.4-rc.0\",\n        \"blaze-tools@1.0.3-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"?minifiers@1.1.4-rc.0\"\n      ],\n      \"spacebars-compiler 1.0.5-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"htmljs@1.0.4-winr.0\",\n        \"html-tools@1.0.4-winr.0\",\n        \"blaze-tools@1.0.3-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"minifiers@1.1.4-winr.0\"\n      ],\n      \"spacebars-compiler 1.0.5-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"htmljs@1.0.4-winr.1\",\n        \"html-tools@1.0.4-winr.1\",\n        \"blaze-tools@1.0.3-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"minifiers@1.1.4-winr.1\"\n      ],\n      \"spacebars-compiler 1.0.5-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"htmljs@1.0.4-winr.2\",\n        \"html-tools@1.0.3-winr.3\",\n        \"blaze-tools@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"minifiers@1.1.4-winr.2\"\n      ],\n      \"spacebars-compiler 1.0.5-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"htmljs@1.0.4-winr.2\",\n        \"html-tools@1.0.3-winr.3\",\n        \"blaze-tools@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"minifiers@1.1.4-winr.4\"\n      ],\n      \"spacebars-compiler 1.0.5-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"htmljs@1.0.4-winr.2\",\n        \"html-tools@1.0.4-winr.3\",\n        \"blaze-tools@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"minifiers@1.1.4-winr.4\"\n      ],\n      \"showdown 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"markdown@10.0.0-glasser.isopacket.0\"\n      ],\n      \"showdown 0.3.1-cordova1\": [\n        \"meteor\",\n        \"?templating\"\n      ],\n      \"showdown 0.3.1-glasser1\": [\n        \"meteor\",\n        \"?templating\"\n      ],\n      \"showdown 0.3.1\": [\n        \"meteor\",\n        \"?templating\"\n      ],\n      \"showdown 1.0.0\": [\n        \"meteor@1.0.2\",\n        \"?templating@1.0.4\"\n      ],\n      \"showdown 1.0.1-rc0\": [\n        \"meteor\",\n        \"?templating\"\n      ],\n      \"showdown 1.0.1\": [\n        \"meteor@1.0.3\",\n        \"?templating@1.0.5\"\n      ],\n      \"showdown 1.0.2-pre.0\": [\n        \"meteor\",\n        \"markdown\"\n      ],\n      \"showdown 1.0.2-pre.1\": [\n        \"meteor\",\n        \"markdown\"\n      ],\n      \"showdown 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"markdown@1.0.2-pre.2\"\n      ],\n      \"showdown 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"markdown@1.0.2-rc.0\"\n      ],\n      \"showdown 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"markdown@1.0.2-win.0\"\n      ],\n      \"showdown 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"markdown@1.0.2\"\n      ],\n      \"showdown 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"markdown@1.0.3-ipc.0\"\n      ],\n      \"showdown 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"markdown@1.0.3-rc.1\"\n      ],\n      \"showdown 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"markdown@1.0.3-slava.0\"\n      ],\n      \"showdown 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"markdown@1.0.3-win.0\"\n      ],\n      \"showdown 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"markdown@1.0.3-winr.0\"\n      ],\n      \"showdown 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"markdown@1.0.3\"\n      ],\n      \"showdown 1.0.4-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"markdown@1.0.4-winr.2\"\n      ],\n      \"showdown 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"markdown@1.0.4-eachin.43\"\n      ],\n      \"showdown 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"markdown@1.0.4-githubble.0\"\n      ],\n      \"showdown 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"markdown@1.0.4-githubble.2\"\n      ],\n      \"showdown 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"markdown@1.0.4-githubble.42\"\n      ],\n      \"showdown 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"markdown@1.0.4-githubble.43\"\n      ],\n      \"showdown 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"markdown@1.0.4-rc.0\"\n      ],\n      \"showdown 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"markdown@1.0.4-winr.0\"\n      ],\n      \"showdown 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"markdown@1.0.4-winr.1\"\n      ],\n      \"showdown 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"markdown@1.0.4-winr.2\"\n      ],\n      \"sha 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"sha 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"sha 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"sha 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"sha 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"sha 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"sha 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"sha 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"sha 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"sha 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"sha 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"sha 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"sha 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"sha 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"sha 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"sha 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"sha 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"sha 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"sha 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"sha 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"sha 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"sha 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"sha 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"session 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"reactive-dict@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\",\n        \"?reload@10.0.0-glasser.isopacket.0\"\n      ],\n      \"session 1.0.0\": [\n        \"ejson@1.0.0\",\n        \"meteor@1.0.2\",\n        \"reactive-dict@1.0.0\",\n        \"?reload@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"session 1.0.1-glasser1\": [\n        \"meteor\",\n        \"underscore\",\n        \"reactive-dict\",\n        \"ejson\",\n        \"?reload\"\n      ],\n      \"session 1.0.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"reactive-dict\",\n        \"ejson\",\n        \"?reload\"\n      ],\n      \"session 1.0.1\": [\n        \"ejson@1.0.1\",\n        \"meteor@1.0.3\",\n        \"reactive-dict@1.0.1\",\n        \"?reload@1.0.1\",\n        \"underscore@1.0.0\"\n      ],\n      \"session 1.0.2-ekate\": [\n        \"meteor\",\n        \"underscore\",\n        \"reactive-dict\",\n        \"ejson\",\n        \"?reload\"\n      ],\n      \"session 1.0.2-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"reactive-dict\",\n        \"ejson\",\n        \"?reload\"\n      ],\n      \"session 1.0.2\": [\n        \"ejson@1.0.3\",\n        \"meteor@1.1.1\",\n        \"reactive-dict@1.0.3\",\n        \"?reload@1.1.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"session 1.0.3-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"reactive-dict\",\n        \"ejson\",\n        \"?reload\"\n      ],\n      \"session 1.0.3-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"reactive-dict\",\n        \"ejson\",\n        \"?reload\"\n      ],\n      \"session 1.0.3-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"reactive-dict@1.0.4-pre.2\",\n        \"ejson@1.0.4-pre.2\",\n        \"?reload@1.1.1-pre.2\"\n      ],\n      \"session 1.0.3-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"reactive-dict@1.0.4-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"?reload@1.1.1-rc.0\"\n      ],\n      \"session 1.0.3-refreshpolicy.1\": [\n        \"meteor@1.1.2-refreshpolicy.1\",\n        \"underscore@1.0.1\",\n        \"reactive-dict@1.0.4\",\n        \"ejson@1.0.4\",\n        \"?reload@1.1.1\"\n      ],\n      \"session 1.0.3\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"reactive-dict@1.0.4\",\n        \"ejson@1.0.4\",\n        \"?reload@1.1.1\"\n      ],\n      \"session 1.0.4-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\",\n        \"reactive-dict@1.0.4\",\n        \"ejson@1.0.4\",\n        \"?reload@1.1.1\"\n      ],\n      \"session 1.0.4-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"reactive-dict@1.0.4-win.0\",\n        \"ejson@1.0.4-win.0\",\n        \"?reload@1.1.1-win.0\"\n      ],\n      \"session 1.0.4\": [\n        \"meteor@1.1.3\",\n        \"underscore@1.0.1\",\n        \"reactive-dict@1.0.4\",\n        \"ejson@1.0.4\",\n        \"?reload@1.1.1\"\n      ],\n      \"session 1.0.5-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"reactive-dict@1.0.5-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"?reload@1.1.2-ipc.0\"\n      ],\n      \"session 1.0.5-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"reactive-dict@1.0.5-rc.1\",\n        \"ejson@1.0.5-rc.1\",\n        \"?reload@1.1.2-rc.1\"\n      ],\n      \"session 1.0.5-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"reactive-dict@1.0.5-slava.0\",\n        \"ejson@1.0.5-slava.0\",\n        \"?reload@1.1.2-slava.0\"\n      ],\n      \"session 1.0.5-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"reactive-dict@1.0.5-win.0\",\n        \"ejson@1.0.5-win.0\",\n        \"?reload@1.1.2-win.0\"\n      ],\n      \"session 1.0.5-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"reactive-dict@1.0.5-winr.0\",\n        \"ejson@1.0.5-winr.0\",\n        \"?reload@1.1.2-winr.0\"\n      ],\n      \"session 1.0.5\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"reactive-dict@1.0.5\",\n        \"ejson@1.0.5\",\n        \"?reload@1.1.2\"\n      ],\n      \"session 1.0.6-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"reactive-dict@1.0.6-eachin.0\",\n        \"ejson@1.0.6-eachin.0\",\n        \"?reload@1.1.3-eachin.0\"\n      ],\n      \"session 1.0.6-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"reactive-dict@1.0.6-eachin.43\",\n        \"ejson@1.0.6-eachin.43\",\n        \"?reload@1.1.3-eachin.43\"\n      ],\n      \"session 1.0.6-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"reactive-dict@1.0.6-githubble.0\",\n        \"ejson@1.0.6-githubble.0\",\n        \"?reload@1.1.3-githubble.0\"\n      ],\n      \"session 1.0.6-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"reactive-dict@1.0.6-githubble.2\",\n        \"ejson@1.0.6-githubble.2\",\n        \"?reload@1.1.3-githubble.2\"\n      ],\n      \"session 1.0.6-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"reactive-dict@1.0.6-githubble.42\",\n        \"ejson@1.0.6-githubble.42\",\n        \"?reload@1.1.3-githubble.42\"\n      ],\n      \"session 1.0.6-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"reactive-dict@1.0.6-githubble.43\",\n        \"ejson@1.0.6-githubble.43\",\n        \"?reload@1.1.3-githubble.43\"\n      ],\n      \"session 1.0.6-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"reactive-dict@1.0.6-winr.0\",\n        \"ejson@1.0.6-winr.0\",\n        \"?reload@1.1.3-winr.0\"\n      ],\n      \"session 1.0.6-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"reactive-dict@1.0.6-winr.1\",\n        \"ejson@1.0.6-winr.1\",\n        \"?reload@1.1.3-winr.1\"\n      ],\n      \"session 1.0.6-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"reactive-dict@1.0.6-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"?reload@1.1.3-winr.3\"\n      ],\n      \"session 1.0.6-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"reactive-dict@1.0.6-winr.3\",\n        \"ejson@1.0.6-winr.2\",\n        \"?reload@1.1.3-winr.3\"\n      ],\n      \"session 1.1.0-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"reactive-dict@1.1.0-rc.0\",\n        \"ejson@1.0.6-rc.0\",\n        \"?reload@1.1.3-rc.0\"\n      ],\n      \"service-configuration 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"accounts-base@10.0.0-glasser.isopacket.0\",\n        \"mongo@10.0.0-glasser.isopacket.0\"\n      ],\n      \"service-configuration 1.0.0\": [\n        \"accounts-base@1.0.0\",\n        \"meteor@1.0.2\",\n        \"mongo-livedata@1.0.3\"\n      ],\n      \"service-configuration 1.0.1-rc0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"mongo\"\n      ],\n      \"service-configuration 1.0.1\": [\n        \"accounts-base@1.0.1\",\n        \"meteor@1.0.3\",\n        \"mongo@1.0.4\"\n      ],\n      \"service-configuration 1.0.2-pre.0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"mongo\"\n      ],\n      \"service-configuration 1.0.2-pre.1\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"mongo\"\n      ],\n      \"service-configuration 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"accounts-base@1.1.2-pre.2\",\n        \"mongo@1.0.7-pre.2\"\n      ],\n      \"service-configuration 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"accounts-base@1.1.2-rc.0\",\n        \"mongo@1.0.7-rc.0\"\n      ],\n      \"service-configuration 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"accounts-base@1.1.2-win.0\",\n        \"mongo@1.0.8-win.0\"\n      ],\n      \"service-configuration 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"accounts-base@1.1.2\",\n        \"mongo@1.0.7\"\n      ],\n      \"service-configuration 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"accounts-base@1.1.3-ipc.0\",\n        \"mongo@1.0.9-ipc.0\"\n      ],\n      \"service-configuration 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"accounts-base@1.1.3-rc.1\",\n        \"mongo@1.0.10-rc.1\"\n      ],\n      \"service-configuration 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"accounts-base@1.1.3-slava.0\",\n        \"mongo@1.0.10-slava.0\"\n      ],\n      \"service-configuration 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"accounts-base@1.1.3-win.0\",\n        \"mongo@1.0.9-win.0\"\n      ],\n      \"service-configuration 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"accounts-base@1.1.3-winr.0\",\n        \"mongo@1.0.10-winr.0\"\n      ],\n      \"service-configuration 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"accounts-base@1.1.3\",\n        \"mongo@1.0.10\"\n      ],\n      \"service-configuration 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"accounts-base@1.1.4-eachin.43\",\n        \"mongo@1.0.12-eachin.45\"\n      ],\n      \"service-configuration 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"accounts-base@1.1.4-githubble.0\",\n        \"mongo@1.0.12-githubble.0\"\n      ],\n      \"service-configuration 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"accounts-base@1.1.4-githubble.2\",\n        \"mongo@1.0.12-githubble.2\"\n      ],\n      \"service-configuration 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"accounts-base@1.1.4-githubble.42\",\n        \"mongo@1.0.12-githubble.42\"\n      ],\n      \"service-configuration 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"accounts-base@1.1.4-githubble.43\",\n        \"mongo@1.0.12-githubble.43\"\n      ],\n      \"service-configuration 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"accounts-base@1.2.0-rc.0\",\n        \"mongo@1.1.0-rc.0\"\n      ],\n      \"service-configuration 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"accounts-base@1.1.4-winr.0\",\n        \"mongo@1.0.11-winr.0\"\n      ],\n      \"service-configuration 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"accounts-base@1.1.4-winr.1\",\n        \"mongo@1.0.11-winr.1\"\n      ],\n      \"service-configuration 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"accounts-base@1.1.4-winr.2\",\n        \"mongo@1.0.12-winr.2\"\n      ],\n      \"routepolicy 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"webapp@10.0.0-glasser.isopacket.0\"\n      ],\n      \"routepolicy 1.0.0-cordova1\": [\n        \"meteor@1.1.0\",\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\"\n      ],\n      \"routepolicy 1.0.0\": [\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.2\"\n      ],\n      \"routepolicy 1.0.1\": [\n        \"meteor@1.1.0\",\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\"\n      ],\n      \"routepolicy 1.0.2-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"webapp\"\n      ],\n      \"routepolicy 1.0.2-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"webapp\"\n      ],\n      \"routepolicy 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"webapp@1.1.3-pre.2\"\n      ],\n      \"routepolicy 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"webapp@1.1.3-rc.0\"\n      ],\n      \"routepolicy 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"webapp@1.1.4-win.0\"\n      ],\n      \"routepolicy 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"webapp@1.1.3\"\n      ],\n      \"routepolicy 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"webapp@1.1.5-ipc.0\"\n      ],\n      \"routepolicy 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"webapp@1.1.5-rc.1\"\n      ],\n      \"routepolicy 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"webapp@1.1.5-slava.0\"\n      ],\n      \"routepolicy 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"webapp@1.1.5-win.0\"\n      ],\n      \"routepolicy 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"webapp@1.1.5-winr.0\"\n      ],\n      \"routepolicy 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"webapp@1.1.5\"\n      ],\n      \"routepolicy 1.0.4-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"webapp@1.1.6-eachin.0\"\n      ],\n      \"routepolicy 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"webapp@1.1.7-eachin.43\"\n      ],\n      \"routepolicy 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"webapp@1.1.7-githubble.0\"\n      ],\n      \"routepolicy 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"webapp@1.1.7-githubble.2\"\n      ],\n      \"routepolicy 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"webapp@1.1.7-githubble.42\"\n      ],\n      \"routepolicy 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"webapp@1.1.7-githubble.43\"\n      ],\n      \"routepolicy 1.0.4-rc.0\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"webapp@1.1.6-rc.0\"\n      ],\n      \"routepolicy 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"webapp@1.1.6-winr.0\"\n      ],\n      \"routepolicy 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"webapp@1.1.6-winr.1\"\n      ],\n      \"routepolicy 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.2\",\n        \"underscore@1.0.2\",\n        \"webapp@1.1.6-winr.2\"\n      ],\n      \"routepolicy 1.0.4-winr.3\": [\n        \"meteor@1.1.5-winr.3\",\n        \"underscore@1.0.2\",\n        \"webapp@1.1.6-winr.3\"\n      ],\n      \"routepolicy 1.0.4-winr.4\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"webapp@1.1.6-winr.4\"\n      ],\n      \"routepolicy 1.0.4\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"webapp@1.1.6\"\n      ],\n      \"routepolicy 1.0.5-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"webapp@1.2.0-rc.0\"\n      ],\n      \"routepolicy 1.0.5-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"webapp@1.1.7-winr.6\"\n      ],\n      \"retry 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\"\n      ],\n      \"retry 1.0.0\": [\n        \"meteor@1.0.2\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"retry 1.0.1-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"retry 1.0.1-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"retry 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"random@1.0.1-pre.2\"\n      ],\n      \"retry 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"random@1.0.1-rc.0\"\n      ],\n      \"retry 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"random@1.0.1-win.0\"\n      ],\n      \"retry 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"random@1.0.1\"\n      ],\n      \"retry 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"random@1.0.2-ipc.0\"\n      ],\n      \"retry 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"random@1.0.2-rc.1\"\n      ],\n      \"retry 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"random@1.0.2-slava.0\"\n      ],\n      \"retry 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"random@1.0.2-win.0\"\n      ],\n      \"retry 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"random@1.0.2-winr.0\"\n      ],\n      \"retry 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"random@1.0.2\"\n      ],\n      \"retry 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"random@1.0.3-eachin.0\"\n      ],\n      \"retry 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"random@1.0.3-eachin.43\"\n      ],\n      \"retry 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"random@1.0.3-githubble.0\"\n      ],\n      \"retry 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"random@1.0.3-githubble.2\"\n      ],\n      \"retry 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"random@1.0.3-githubble.42\"\n      ],\n      \"retry 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"random@1.0.3-githubble.43\"\n      ],\n      \"retry 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"random@1.0.3-rc.0\"\n      ],\n      \"retry 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"random@1.0.3-winr.0\"\n      ],\n      \"retry 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"random@1.0.3-winr.1\"\n      ],\n      \"retry 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"reload 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"logging@10.0.0-glasser.isopacket.0\",\n        \"json@10.0.0-glasser.isopacket.0\"\n      ],\n      \"reload 1.0.0\": [\n        \"json@1.0.0\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"reload 1.0.1-glasser1\": [\n        \"meteor\",\n        \"underscore\",\n        \"logging\",\n        \"json\"\n      ],\n      \"reload 1.0.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"logging\",\n        \"json\"\n      ],\n      \"reload 1.0.1\": [\n        \"json@1.0.0\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.3\",\n        \"underscore@1.0.0\"\n      ],\n      \"reload 1.0.2-ekate\": [\n        \"meteor\",\n        \"underscore\",\n        \"logging\",\n        \"json\"\n      ],\n      \"reload 1.1.0-rc1\": [\n        \"meteor\",\n        \"underscore\",\n        \"logging\",\n        \"json\"\n      ],\n      \"reload 1.1.0\": [\n        \"json@1.0.0\",\n        \"logging@1.0.3\",\n        \"meteor@1.1.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"reload 1.1.1-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"logging\",\n        \"json\"\n      ],\n      \"reload 1.1.1-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"logging\",\n        \"json\"\n      ],\n      \"reload 1.1.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"logging@1.0.4-pre.2\",\n        \"json@1.0.1-pre.2\"\n      ],\n      \"reload 1.1.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"logging@1.0.4-rc.0\",\n        \"json@1.0.1-rc.0\"\n      ],\n      \"reload 1.1.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"logging@1.0.5-win.0\",\n        \"json@1.0.1-win.0\"\n      ],\n      \"reload 1.1.1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"logging@1.0.4\",\n        \"json@1.0.1\"\n      ],\n      \"reload 1.1.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"logging@1.0.6-ipc.0\",\n        \"json@1.0.2-ipc.0\"\n      ],\n      \"reload 1.1.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"logging@1.0.6-rc.1\",\n        \"json@1.0.2-rc.1\"\n      ],\n      \"reload 1.1.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"logging@1.0.6-slava.0\",\n        \"json@1.0.2-slava.0\"\n      ],\n      \"reload 1.1.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"logging@1.0.6-win.0\",\n        \"json@1.0.2-win.0\"\n      ],\n      \"reload 1.1.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"logging@1.0.6-winr.0\",\n        \"json@1.0.2-winr.0\"\n      ],\n      \"reload 1.1.2\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"logging@1.0.6\",\n        \"json@1.0.2\"\n      ],\n      \"reload 1.1.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"logging@1.0.6-eachin.0\",\n        \"json@1.0.3-eachin.0\"\n      ],\n      \"reload 1.1.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"logging@1.0.6-eachin.43\",\n        \"json@1.0.3-eachin.43\"\n      ],\n      \"reload 1.1.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"logging@1.0.6-githubble.0\",\n        \"json@1.0.3-githubble.0\"\n      ],\n      \"reload 1.1.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"logging@1.0.6-githubble.2\",\n        \"json@1.0.3-githubble.2\"\n      ],\n      \"reload 1.1.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"logging@1.0.6-githubble.42\",\n        \"json@1.0.3-githubble.42\"\n      ],\n      \"reload 1.1.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"logging@1.0.6-githubble.43\",\n        \"json@1.0.3-githubble.43\"\n      ],\n      \"reload 1.1.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"logging@1.0.7-rc.0\",\n        \"json@1.0.3-rc.0\"\n      ],\n      \"reload 1.1.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"logging@1.0.7-winr.0\",\n        \"json@1.0.3-winr.0\"\n      ],\n      \"reload 1.1.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"logging@1.0.7-winr.1\",\n        \"json@1.0.3-winr.1\"\n      ],\n      \"reload 1.1.3-winr.2\": [\n        \"meteor@1.1.5-winr.3\",\n        \"underscore@1.0.3-winr.1\",\n        \"logging@1.0.6-winr.1\",\n        \"json@1.0.3-winr.1\"\n      ],\n      \"reload 1.1.3-winr.3\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"logging@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\"\n      ],\n      \"reload-safetybelt 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"webapp@10.0.0-glasser.isopacket.0\"\n      ],\n      \"reload-safetybelt 1.0.0\": [\n        \"meteor@1.0.2\",\n        \"webapp@1.0.2\"\n      ],\n      \"reload-safetybelt 1.0.1-pre.0\": [\n        \"meteor\",\n        \"webapp\"\n      ],\n      \"reload-safetybelt 1.0.1-pre.1\": [\n        \"meteor\",\n        \"webapp\"\n      ],\n      \"reload-safetybelt 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"webapp@1.1.3-pre.2\"\n      ],\n      \"reload-safetybelt 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"webapp@1.1.3-rc.0\"\n      ],\n      \"reload-safetybelt 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"webapp@1.1.4-win.0\"\n      ],\n      \"reload-safetybelt 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"webapp@1.1.3\"\n      ],\n      \"reload-safetybelt 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"webapp@1.1.5-ipc.0\"\n      ],\n      \"reload-safetybelt 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"webapp@1.1.5-rc.1\"\n      ],\n      \"reload-safetybelt 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"webapp@1.1.5-slava.0\"\n      ],\n      \"reload-safetybelt 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"webapp@1.1.5-win.0\"\n      ],\n      \"reload-safetybelt 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"webapp@1.1.5-winr.0\"\n      ],\n      \"reload-safetybelt 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"webapp@1.1.5\"\n      ],\n      \"reload-safetybelt 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"webapp@1.1.6-eachin.0\"\n      ],\n      \"reload-safetybelt 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"webapp@1.1.7-eachin.43\"\n      ],\n      \"reload-safetybelt 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"webapp@1.1.7-githubble.0\"\n      ],\n      \"reload-safetybelt 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"webapp@1.1.7-githubble.2\"\n      ],\n      \"reload-safetybelt 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"webapp@1.1.7-githubble.42\"\n      ],\n      \"reload-safetybelt 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"webapp@1.1.7-githubble.43\"\n      ],\n      \"reload-safetybelt 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"webapp@1.2.0-rc.0\"\n      ],\n      \"reload-safetybelt 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"webapp@1.1.6-winr.0\"\n      ],\n      \"reload-safetybelt 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"webapp@1.1.6-winr.1\"\n      ],\n      \"reload-safetybelt 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"webapp@1.1.6-winr.4\"\n      ],\n      \"reactive-var 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\"\n      ],\n      \"reactive-var 1.0.1-rc0\": [\n        \"meteor\",\n        \"tracker\"\n      ],\n      \"reactive-var 1.0.1\": [\n        \"meteor@1.0.3\",\n        \"tracker@1.0.2\"\n      ],\n      \"reactive-var 1.0.2-ekate\": [\n        \"meteor\",\n        \"tracker\"\n      ],\n      \"reactive-var 1.0.2-rc0\": [\n        \"meteor\",\n        \"tracker\"\n      ],\n      \"reactive-var 1.0.2\": [\n        \"meteor@1.1.1\",\n        \"tracker@1.0.2\"\n      ],\n      \"reactive-var 1.0.3-pre.0\": [\n        \"meteor\",\n        \"tracker\"\n      ],\n      \"reactive-var 1.0.3-pre.1\": [\n        \"meteor\",\n        \"tracker\"\n      ],\n      \"reactive-var 1.0.3-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"tracker@1.0.3-pre.2\"\n      ],\n      \"reactive-var 1.0.3-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"tracker@1.0.3-rc.0\"\n      ],\n      \"reactive-var 1.0.3-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"tracker@1.0.3-win.0\"\n      ],\n      \"reactive-var 1.0.3\": [\n        \"meteor@1.1.2\",\n        \"tracker@1.0.3\"\n      ],\n      \"reactive-var 1.0.4-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"tracker@1.0.4-ipc.0\"\n      ],\n      \"reactive-var 1.0.4-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"tracker@1.0.4-rc.1\"\n      ],\n      \"reactive-var 1.0.4-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"tracker@1.0.4-slava.0\"\n      ],\n      \"reactive-var 1.0.4-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"tracker@1.0.4-win.0\"\n      ],\n      \"reactive-var 1.0.4-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"tracker@1.0.4-winr.0\"\n      ],\n      \"reactive-var 1.0.4\": [\n        \"meteor@1.1.4\",\n        \"tracker@1.0.4\"\n      ],\n      \"reactive-var 1.0.5-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"tracker@1.0.5-eachin.0\"\n      ],\n      \"reactive-var 1.0.5-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"tracker@1.0.5-eachin.43\"\n      ],\n      \"reactive-var 1.0.5-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"tracker@1.0.5-githubble.0\"\n      ],\n      \"reactive-var 1.0.5-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"tracker@1.0.5-githubble.2\"\n      ],\n      \"reactive-var 1.0.5-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"tracker@1.0.5-githubble.42\"\n      ],\n      \"reactive-var 1.0.5-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"tracker@1.0.5-githubble.43\"\n      ],\n      \"reactive-var 1.0.5-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"tracker@1.0.6-rc.0\"\n      ],\n      \"reactive-var 1.0.5-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"tracker@1.0.5-winr.0\"\n      ],\n      \"reactive-var 1.0.5-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"tracker@1.0.5-winr.1\"\n      ],\n      \"reactive-var 1.0.5-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"tracker@1.0.5-winr.4\"\n      ],\n      \"reactive-dict 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\",\n        \"?mongo@10.0.0-glasser.isopacket.0\"\n      ],\n      \"reactive-dict 1.0.0\": [\n        \"deps@1.0.1\",\n        \"ejson@1.0.0\",\n        \"meteor@1.0.2\",\n        \"?mongo-livedata@1.0.3\",\n        \"underscore@1.0.0\"\n      ],\n      \"reactive-dict 1.0.1-glasser1\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"?mongo\"\n      ],\n      \"reactive-dict 1.0.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"?mongo-livedata\"\n      ],\n      \"reactive-dict 1.0.1-rc1\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"?mongo\"\n      ],\n      \"reactive-dict 1.0.1\": [\n        \"ejson@1.0.1\",\n        \"meteor@1.0.3\",\n        \"?mongo@1.0.4\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"reactive-dict 1.0.2-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"?mongo\"\n      ],\n      \"reactive-dict 1.0.2\": [\n        \"ejson@1.0.1\",\n        \"meteor@1.0.3\",\n        \"?mongo@1.0.4\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"reactive-dict 1.0.3-ekate\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"?mongo\"\n      ],\n      \"reactive-dict 1.0.3-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"?mongo\"\n      ],\n      \"reactive-dict 1.0.3-rc1\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"?mongo\"\n      ],\n      \"reactive-dict 1.0.3\": [\n        \"ejson@1.0.3\",\n        \"meteor@1.1.1\",\n        \"?mongo@1.0.6\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"reactive-dict 1.0.4-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"?mongo\"\n      ],\n      \"reactive-dict 1.0.4-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"tracker\",\n        \"ejson\",\n        \"?mongo\"\n      ],\n      \"reactive-dict 1.0.4-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"ejson@1.0.4-pre.2\",\n        \"?mongo@1.0.7-pre.2\"\n      ],\n      \"reactive-dict 1.0.4-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"?mongo@1.0.7-rc.0\"\n      ],\n      \"reactive-dict 1.0.4-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"tracker@1.0.3-win.0\",\n        \"ejson@1.0.4-win.0\",\n        \"?mongo@1.0.8-win.0\"\n      ],\n      \"reactive-dict 1.0.4\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"ejson@1.0.4\",\n        \"?mongo@1.0.7\"\n      ],\n      \"reactive-dict 1.0.5-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"?mongo@1.0.9-ipc.0\"\n      ],\n      \"reactive-dict 1.0.5-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"tracker@1.0.4-rc.1\",\n        \"ejson@1.0.5-rc.1\",\n        \"?mongo@1.0.10-rc.1\"\n      ],\n      \"reactive-dict 1.0.5-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"tracker@1.0.4-slava.0\",\n        \"ejson@1.0.5-slava.0\",\n        \"?mongo@1.0.10-slava.0\"\n      ],\n      \"reactive-dict 1.0.5-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"tracker@1.0.4-win.0\",\n        \"ejson@1.0.5-win.0\",\n        \"?mongo@1.0.9-win.0\"\n      ],\n      \"reactive-dict 1.0.5-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"tracker@1.0.4-winr.0\",\n        \"ejson@1.0.5-winr.0\",\n        \"?mongo@1.0.10-winr.0\"\n      ],\n      \"reactive-dict 1.0.5\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.4\",\n        \"ejson@1.0.5\",\n        \"?mongo@1.0.10\"\n      ],\n      \"reactive-dict 1.0.6-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"tracker@1.0.5-eachin.0\",\n        \"ejson@1.0.6-eachin.0\",\n        \"?mongo@1.0.12-eachin.0\"\n      ],\n      \"reactive-dict 1.0.6-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"tracker@1.0.5-eachin.43\",\n        \"ejson@1.0.6-eachin.43\",\n        \"?mongo@1.0.12-eachin.45\"\n      ],\n      \"reactive-dict 1.0.6-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"tracker@1.0.5-githubble.0\",\n        \"ejson@1.0.6-githubble.0\",\n        \"?mongo@1.0.12-githubble.0\"\n      ],\n      \"reactive-dict 1.0.6-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"tracker@1.0.5-githubble.2\",\n        \"ejson@1.0.6-githubble.2\",\n        \"?mongo@1.0.12-githubble.2\"\n      ],\n      \"reactive-dict 1.0.6-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"tracker@1.0.5-githubble.42\",\n        \"ejson@1.0.6-githubble.42\",\n        \"?mongo@1.0.12-githubble.42\"\n      ],\n      \"reactive-dict 1.0.6-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"tracker@1.0.5-githubble.43\",\n        \"ejson@1.0.6-githubble.43\",\n        \"?mongo@1.0.12-githubble.43\"\n      ],\n      \"reactive-dict 1.0.6-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"tracker@1.0.5-winr.0\",\n        \"ejson@1.0.6-winr.0\",\n        \"?mongo@1.0.11-winr.0\"\n      ],\n      \"reactive-dict 1.0.6-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"tracker@1.0.5-winr.1\",\n        \"ejson@1.0.6-winr.1\",\n        \"?mongo@1.0.11-winr.1\"\n      ],\n      \"reactive-dict 1.0.6-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"ejson@1.0.6-winr.2\",\n        \"?mongo@1.0.12-winr.2\"\n      ],\n      \"reactive-dict 1.0.6-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"ejson@1.0.6-winr.2\",\n        \"?mongo@1.0.12-winr.5\"\n      ],\n      \"reactive-dict 1.0.6-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.6-winr.4\",\n        \"ejson@1.0.6-winr.2\",\n        \"?mongo@1.0.12-winr.6\"\n      ],\n      \"reactive-dict 1.1.0-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"tracker@1.0.6-rc.0\",\n        \"ejson@1.0.6-rc.0\",\n        \"?mongo@1.1.0-rc.0\"\n      ],\n      \"random 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\"\n      ],\n      \"random 1.0.0\": [\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"random 1.0.1-pre.0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"random 1.0.1-pre.1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"random 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\"\n      ],\n      \"random 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"random 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\"\n      ],\n      \"random 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\"\n      ],\n      \"random 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\"\n      ],\n      \"random 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\"\n      ],\n      \"random 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\"\n      ],\n      \"random 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\"\n      ],\n      \"random 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\"\n      ],\n      \"random 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\"\n      ],\n      \"random 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\"\n      ],\n      \"random 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\"\n      ],\n      \"random 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\"\n      ],\n      \"random 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\"\n      ],\n      \"random 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\"\n      ],\n      \"random 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\"\n      ],\n      \"random 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"random 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\"\n      ],\n      \"random 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\"\n      ],\n      \"random 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"preserve-inputs 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"preserve-inputs 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"preserve-inputs 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"preserve-inputs 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"preserve-inputs 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"preserve-inputs 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"preserve-inputs 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"preserve-inputs 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"preserve-inputs 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"preserve-inputs 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"preserve-inputs 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"preserve-inputs 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"preserve-inputs 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"preserve-inputs 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"preserve-inputs 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"preserve-inputs 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"preserve-inputs 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"preserve-inputs 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"preserve-inputs 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"preserve-inputs 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"preserve-inputs 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"preserve-inputs 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"preserve-inputs 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"package-version-parser 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\"\n      ],\n      \"package-version-parser 1.0.0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 1.0.1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 1.0.2\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 1.0.3\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 1.0.4\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 1.0.5-cordova4\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 1.0.5\": [\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"package-version-parser 1.0.6-rc1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 1.0.6\": [\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"package-version-parser 1.0.7-glasser1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 1.0.8-rc1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 1.0.8\": [\n        \"meteor@1.1.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"package-version-parser 2.0.0-ekate\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 2.0.0-rc.2\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 2.0.0-rc.3\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 2.0.0-rc0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 2.0.0-rc1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 2.0.0\": [\n        \"meteor@1.1.1\",\n        \"underscore@1.0.0\"\n      ],\n      \"package-version-parser 2.0.1-pre.0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 2.0.1-rc.0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 2.0.1\": [\n        \"meteor@1.1.1\",\n        \"underscore@1.0.0\"\n      ],\n      \"package-version-parser 2.0.2-pre.0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 2.0.2-pre.1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"package-version-parser 2.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\"\n      ],\n      \"package-version-parser 2.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"package-version-parser 2.0.2-rc.1\": [\n        \"meteor@1.1.2-rc.3\",\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"package-version-parser 2.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\"\n      ],\n      \"package-version-parser 2.0.2\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\"\n      ],\n      \"package-version-parser 2.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\"\n      ],\n      \"package-version-parser 2.0.3-ipc.1\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\"\n      ],\n      \"package-version-parser 2.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\"\n      ],\n      \"package-version-parser 2.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\"\n      ],\n      \"package-version-parser 2.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\"\n      ],\n      \"package-version-parser 2.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\"\n      ],\n      \"package-version-parser 2.0.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\"\n      ],\n      \"package-version-parser 2.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\"\n      ],\n      \"package-version-parser 2.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\"\n      ],\n      \"package-version-parser 3.0.0-rc.0\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\"\n      ],\n      \"package-version-parser 3.0.0\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\"\n      ],\n      \"package-version-parser 3.0.1-blz.0\": [\n        \"meteor@1.1.5-blz.0\",\n        \"underscore@1.0.2\"\n      ],\n      \"package-version-parser 3.0.1-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\"\n      ],\n      \"package-version-parser 3.0.1-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\"\n      ],\n      \"package-version-parser 3.0.1-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\"\n      ],\n      \"package-version-parser 3.0.1-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\"\n      ],\n      \"package-version-parser 3.0.1-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\"\n      ],\n      \"package-version-parser 3.0.1-winr.0\": [\n        \"meteor@1.1.5-winr.2\",\n        \"underscore@1.0.2\"\n      ],\n      \"package-version-parser 3.0.1-winr.1\": [\n        \"meteor@1.1.5-winr.3\",\n        \"underscore@1.0.2\"\n      ],\n      \"package-version-parser 3.0.1-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"package-version-parser 3.0.1-winr.3\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"package-version-parser 3.0.1-winr.4\": [\n        \"meteor@1.1.5-winr.5\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"package-version-parser 3.0.2-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"package-version-parser 3.0.2-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"underscore@1.0.2\"\n      ],\n      \"package-version-parser 3.0.2-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"underscore@1.0.2\"\n      ],\n      \"package-version-parser 3.0.2-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"package-version-parser 3.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"package-stats-opt-out 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"package-stats-opt-out 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"package-stats-opt-out 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"package-stats-opt-out 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"package-stats-opt-out 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"package-stats-opt-out 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"package-stats-opt-out 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"package-stats-opt-out 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"package-stats-opt-out 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"package-stats-opt-out 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"package-stats-opt-out 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"package-stats-opt-out 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"package-stats-opt-out 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"package-stats-opt-out 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"package-stats-opt-out 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"package-stats-opt-out 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"package-stats-opt-out 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"package-stats-opt-out 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"package-stats-opt-out 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"package-stats-opt-out 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"package-stats-opt-out 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"package-stats-opt-out 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"package-stats-opt-out 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"package-stats-opt-out 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"ordered-dict 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\"\n      ],\n      \"ordered-dict 1.0.0\": [\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"ordered-dict 1.0.1-pre.0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"ordered-dict 1.0.1-pre.1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"ordered-dict 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\"\n      ],\n      \"ordered-dict 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"ordered-dict 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\"\n      ],\n      \"ordered-dict 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\"\n      ],\n      \"ordered-dict 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\"\n      ],\n      \"ordered-dict 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\"\n      ],\n      \"ordered-dict 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\"\n      ],\n      \"ordered-dict 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\"\n      ],\n      \"ordered-dict 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\"\n      ],\n      \"ordered-dict 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\"\n      ],\n      \"ordered-dict 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\"\n      ],\n      \"ordered-dict 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\"\n      ],\n      \"ordered-dict 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\"\n      ],\n      \"ordered-dict 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\"\n      ],\n      \"ordered-dict 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\"\n      ],\n      \"ordered-dict 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\"\n      ],\n      \"ordered-dict 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"ordered-dict 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\"\n      ],\n      \"ordered-dict 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\"\n      ],\n      \"ordered-dict 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"observe-sequence 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\",\n        \"minimongo@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\"\n      ],\n      \"observe-sequence 1.0.0\": [\n        \"meteor\",\n        \"deps\",\n        \"minimongo\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"observe-sequence 1.0.1\": [\n        \"deps@1.0.1\",\n        \"meteor@1.0.2\",\n        \"minimongo@1.0.1\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"observe-sequence 1.0.2-rc0\": [\n        \"meteor\",\n        \"tracker\",\n        \"minimongo\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"observe-sequence 1.0.2\": [\n        \"meteor@1.0.3\",\n        \"minimongo@1.0.2\",\n        \"random@1.0.0\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"observe-sequence 1.0.3-pre.0\": [\n        \"meteor\",\n        \"tracker\",\n        \"minimongo\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"observe-sequence 1.0.3-pre.1\": [\n        \"meteor\",\n        \"tracker\",\n        \"minimongo\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"observe-sequence 1.0.3-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"minimongo@1.0.4-pre.3\",\n        \"underscore@1.0.1-pre.2\",\n        \"random@1.0.1-pre.2\"\n      ],\n      \"observe-sequence 1.0.3-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"minimongo@1.0.4-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"random@1.0.1-rc.0\"\n      ],\n      \"observe-sequence 1.0.3-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"tracker@1.0.3-win.0\",\n        \"minimongo@1.0.5-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"random@1.0.1-win.0\"\n      ],\n      \"observe-sequence 1.0.3\": [\n        \"meteor@1.1.2\",\n        \"tracker@1.0.3\",\n        \"minimongo@1.0.4\",\n        \"underscore@1.0.1\",\n        \"random@1.0.1\"\n      ],\n      \"observe-sequence 1.0.4-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"minimongo@1.0.6-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"random@1.0.2-ipc.0\"\n      ],\n      \"observe-sequence 1.0.4-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"tracker@1.0.4-rc.1\",\n        \"minimongo@1.0.6-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"random@1.0.2-rc.1\"\n      ],\n      \"observe-sequence 1.0.4-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"tracker@1.0.4-slava.0\",\n        \"minimongo@1.0.6-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"random@1.0.2-slava.0\"\n      ],\n      \"observe-sequence 1.0.4-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"tracker@1.0.4-win.0\",\n        \"minimongo@1.0.6-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"random@1.0.2-win.0\"\n      ],\n      \"observe-sequence 1.0.4-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"tracker@1.0.4-winr.0\",\n        \"minimongo@1.0.6-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"random@1.0.2-winr.0\"\n      ],\n      \"observe-sequence 1.0.4\": [\n        \"meteor@1.1.4\",\n        \"tracker@1.0.4\",\n        \"minimongo@1.0.6\",\n        \"underscore@1.0.2\",\n        \"random@1.0.2\"\n      ],\n      \"observe-sequence 1.0.5-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"tracker@1.0.5-eachin.43\",\n        \"minimongo@1.0.7-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"random@1.0.3-eachin.43\"\n      ],\n      \"observe-sequence 1.0.5-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"tracker@1.0.5-githubble.0\",\n        \"minimongo@1.0.7-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"random@1.0.3-githubble.0\"\n      ],\n      \"observe-sequence 1.0.5-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"tracker@1.0.5-githubble.2\",\n        \"minimongo@1.0.7-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"random@1.0.3-githubble.2\"\n      ],\n      \"observe-sequence 1.0.5-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"tracker@1.0.5-githubble.42\",\n        \"minimongo@1.0.7-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"random@1.0.3-githubble.42\"\n      ],\n      \"observe-sequence 1.0.5-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"tracker@1.0.5-githubble.43\",\n        \"minimongo@1.0.7-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"random@1.0.3-githubble.43\"\n      ],\n      \"observe-sequence 1.0.5-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"tracker@1.0.6-rc.0\",\n        \"minimongo@1.0.7-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"random@1.0.3-rc.0\"\n      ],\n      \"observe-sequence 1.0.5-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"tracker@1.0.5-winr.0\",\n        \"minimongo@1.0.7-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"random@1.0.3-winr.0\"\n      ],\n      \"observe-sequence 1.0.5-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"tracker@1.0.5-winr.1\",\n        \"minimongo@1.0.7-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"random@1.0.3-winr.1\"\n      ],\n      \"observe-sequence 1.0.5-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"tracker@1.0.5-winr.4\",\n        \"minimongo@1.0.7-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"observe-sequence 1.0.5-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"tracker@1.0.6-winr.4\",\n        \"minimongo@1.0.7-winr.3\",\n        \"underscore@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"oauth2 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"service-configuration@10.0.0-glasser.isopacket.0\",\n        \"oauth@10.0.0-glasser.isopacket.0\"\n      ],\n      \"oauth2 1.0.0-glasser1\": [\n        \"meteor\",\n        \"service-configuration\",\n        \"oauth\"\n      ],\n      \"oauth2 1.0.0\": [\n        \"meteor@1.0.2\",\n        \"oauth@1.0.0\",\n        \"service-configuration@1.0.0\"\n      ],\n      \"oauth2 1.0.1-ekate\": [\n        \"meteor\",\n        \"service-configuration\",\n        \"oauth\"\n      ],\n      \"oauth2 1.1.0-rc0\": [\n        \"meteor\",\n        \"service-configuration\",\n        \"oauth\"\n      ],\n      \"oauth2 1.1.0\": [\n        \"meteor@1.1.0\",\n        \"oauth@1.1.0\",\n        \"service-configuration@1.0.1\"\n      ],\n      \"oauth2 1.1.1-pre.0\": [\n        \"meteor\",\n        \"service-configuration\",\n        \"oauth\"\n      ],\n      \"oauth2 1.1.1-pre.1\": [\n        \"meteor\",\n        \"service-configuration\",\n        \"oauth\"\n      ],\n      \"oauth2 1.1.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"service-configuration@1.0.2-pre.2\",\n        \"oauth@1.1.1-pre.2\"\n      ],\n      \"oauth2 1.1.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"oauth@1.1.1-rc.0\"\n      ],\n      \"oauth2 1.1.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"service-configuration@1.0.2-win.0\",\n        \"oauth@1.1.2-win.0\"\n      ],\n      \"oauth2 1.1.1\": [\n        \"meteor@1.1.2\",\n        \"service-configuration@1.0.2\",\n        \"oauth@1.1.1\"\n      ],\n      \"oauth2 1.1.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"service-configuration@1.0.3-ipc.0\",\n        \"oauth@1.1.3-ipc.0\"\n      ],\n      \"oauth2 1.1.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"service-configuration@1.0.3-rc.1\",\n        \"oauth@1.1.3-rc.1\"\n      ],\n      \"oauth2 1.1.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"service-configuration@1.0.3-slava.0\",\n        \"oauth@1.1.3-slava.0\"\n      ],\n      \"oauth2 1.1.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"service-configuration@1.0.3-win.0\",\n        \"oauth@1.1.3-win.0\"\n      ],\n      \"oauth2 1.1.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"service-configuration@1.0.3-winr.0\",\n        \"oauth@1.1.3-winr.0\"\n      ],\n      \"oauth2 1.1.2\": [\n        \"meteor@1.1.4\",\n        \"service-configuration@1.0.3\",\n        \"oauth@1.1.3\"\n      ],\n      \"oauth2 1.1.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"service-configuration@1.0.4-eachin.43\",\n        \"oauth@1.1.4-eachin.43\"\n      ],\n      \"oauth2 1.1.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"service-configuration@1.0.4-githubble.0\",\n        \"oauth@1.1.4-githubble.0\"\n      ],\n      \"oauth2 1.1.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"service-configuration@1.0.4-githubble.2\",\n        \"oauth@1.1.4-githubble.2\"\n      ],\n      \"oauth2 1.1.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"service-configuration@1.0.4-githubble.42\",\n        \"oauth@1.1.4-githubble.42\"\n      ],\n      \"oauth2 1.1.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"service-configuration@1.0.4-githubble.43\",\n        \"oauth@1.1.4-githubble.43\"\n      ],\n      \"oauth2 1.1.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"service-configuration@1.0.4-rc.0\",\n        \"oauth@1.1.4-rc.0\"\n      ],\n      \"oauth2 1.1.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"service-configuration@1.0.4-winr.0\",\n        \"oauth@1.1.4-winr.0\"\n      ],\n      \"oauth2 1.1.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"service-configuration@1.0.4-winr.1\",\n        \"oauth@1.1.4-winr.1\"\n      ],\n      \"oauth2 1.1.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"oauth@1.1.4-winr.2\"\n      ],\n      \"oauth1 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"service-configuration@10.0.0-glasser.isopacket.0\",\n        \"oauth@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"http@10.0.0-glasser.isopacket.0\",\n        \"mongo@10.0.0-glasser.isopacket.0\"\n      ],\n      \"oauth1 1.0.0-cordova4\": [\n        \"meteor\",\n        \"random\",\n        \"service-configuration\",\n        \"oauth\",\n        \"underscore\",\n        \"http\"\n      ],\n      \"oauth1 1.0.0\": [\n        \"http@1.0.2\",\n        \"meteor@1.0.2\",\n        \"oauth@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"oauth1 1.0.1-glasser1\": [\n        \"meteor\",\n        \"random\",\n        \"service-configuration\",\n        \"oauth\",\n        \"underscore\",\n        \"http\",\n        \"mongo\"\n      ],\n      \"oauth1 1.0.1-rc0\": [\n        \"meteor\",\n        \"random\",\n        \"service-configuration\",\n        \"oauth\",\n        \"underscore\",\n        \"http\"\n      ],\n      \"oauth1 1.0.1-rc1\": [\n        \"meteor\",\n        \"random\",\n        \"service-configuration\",\n        \"oauth\",\n        \"underscore\",\n        \"http\",\n        \"mongo\"\n      ],\n      \"oauth1 1.0.1\": [\n        \"http@1.0.4\",\n        \"meteor@1.0.3\",\n        \"mongo@1.0.4\",\n        \"oauth@1.0.1\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"underscore@1.0.0\"\n      ],\n      \"oauth1 1.0.2-ekate\": [\n        \"meteor\",\n        \"random\",\n        \"service-configuration\",\n        \"oauth\",\n        \"underscore\",\n        \"http\",\n        \"mongo\"\n      ],\n      \"oauth1 1.1.0-rc0\": [\n        \"meteor\",\n        \"random\",\n        \"service-configuration\",\n        \"oauth\",\n        \"underscore\",\n        \"http\",\n        \"mongo\"\n      ],\n      \"oauth1 1.1.0\": [\n        \"http@1.0.5\",\n        \"meteor@1.1.0\",\n        \"mongo@1.0.5\",\n        \"oauth@1.1.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"underscore@1.0.0\"\n      ],\n      \"oauth1 1.1.1-pre.0\": [\n        \"meteor\",\n        \"random\",\n        \"service-configuration\",\n        \"oauth\",\n        \"underscore\",\n        \"http\",\n        \"mongo\"\n      ],\n      \"oauth1 1.1.1-pre.1\": [\n        \"meteor\",\n        \"random\",\n        \"service-configuration\",\n        \"oauth\",\n        \"underscore\",\n        \"http\",\n        \"mongo\"\n      ],\n      \"oauth1 1.1.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"service-configuration@1.0.2-pre.2\",\n        \"oauth@1.1.1-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"http@1.0.7-pre.2\",\n        \"mongo@1.0.7-pre.2\"\n      ],\n      \"oauth1 1.1.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"oauth@1.1.1-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"http@1.0.7-rc.0\",\n        \"mongo@1.0.7-rc.0\"\n      ],\n      \"oauth1 1.1.1\": [\n        \"meteor@1.1.2\",\n        \"random@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"oauth@1.1.1\",\n        \"underscore@1.0.1\",\n        \"http@1.0.7\",\n        \"mongo@1.0.7\"\n      ],\n      \"oauth1 1.1.2-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"random@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"oauth@1.1.2-rc.0\",\n        \"underscore@1.0.1\",\n        \"http@1.0.8-rc.6\",\n        \"mongo@1.0.8-rc.1\"\n      ],\n      \"oauth1 1.1.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"random@1.0.1-win.0\",\n        \"service-configuration@1.0.2-win.0\",\n        \"oauth@1.1.2-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"http@1.0.8-win.0\",\n        \"mongo@1.0.8-win.0\"\n      ],\n      \"oauth1 1.1.2\": [\n        \"meteor@1.1.3\",\n        \"random@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"oauth@1.1.2\",\n        \"underscore@1.0.1\",\n        \"http@1.0.8\",\n        \"mongo@1.0.8\"\n      ],\n      \"oauth1 1.1.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"service-configuration@1.0.3-ipc.0\",\n        \"oauth@1.1.3-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"http@1.0.9-ipc.0\",\n        \"mongo@1.0.9-ipc.0\"\n      ],\n      \"oauth1 1.1.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"service-configuration@1.0.3-rc.1\",\n        \"oauth@1.1.3-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"http@1.0.9-rc.1\",\n        \"mongo@1.0.10-rc.1\"\n      ],\n      \"oauth1 1.1.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"service-configuration@1.0.3-slava.0\",\n        \"oauth@1.1.3-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"http@1.0.9-slava.0\",\n        \"mongo@1.0.10-slava.0\"\n      ],\n      \"oauth1 1.1.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"random@1.0.2-win.0\",\n        \"service-configuration@1.0.3-win.0\",\n        \"oauth@1.1.3-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"http@1.0.9-win.0\",\n        \"mongo@1.0.9-win.0\"\n      ],\n      \"oauth1 1.1.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"service-configuration@1.0.3-winr.0\",\n        \"oauth@1.1.3-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"http@1.0.9-winr.0\",\n        \"mongo@1.0.10-winr.0\"\n      ],\n      \"oauth1 1.1.3\": [\n        \"meteor@1.1.4\",\n        \"random@1.0.2\",\n        \"service-configuration@1.0.3\",\n        \"oauth@1.1.3\",\n        \"underscore@1.0.2\",\n        \"http@1.0.9\",\n        \"mongo@1.0.10\"\n      ],\n      \"oauth1 1.1.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"service-configuration@1.0.4-eachin.43\",\n        \"oauth@1.1.4-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"http@1.0.10-eachin.43\",\n        \"mongo@1.0.12-eachin.45\"\n      ],\n      \"oauth1 1.1.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"random@1.0.3-githubble.0\",\n        \"service-configuration@1.0.4-githubble.0\",\n        \"oauth@1.1.4-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"http@1.0.10-githubble.0\",\n        \"mongo@1.0.12-githubble.0\"\n      ],\n      \"oauth1 1.1.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"service-configuration@1.0.4-githubble.2\",\n        \"oauth@1.1.4-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"http@1.0.10-githubble.2\",\n        \"mongo@1.0.12-githubble.2\"\n      ],\n      \"oauth1 1.1.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"service-configuration@1.0.4-githubble.42\",\n        \"oauth@1.1.4-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"http@1.0.10-githubble.42\",\n        \"mongo@1.0.12-githubble.42\"\n      ],\n      \"oauth1 1.1.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"service-configuration@1.0.4-githubble.43\",\n        \"oauth@1.1.4-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"http@1.0.10-githubble.43\",\n        \"mongo@1.0.12-githubble.43\"\n      ],\n      \"oauth1 1.1.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"service-configuration@1.0.4-rc.0\",\n        \"oauth@1.1.4-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"http@1.1.0-rc.0\",\n        \"mongo@1.1.0-rc.0\"\n      ],\n      \"oauth1 1.1.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"service-configuration@1.0.4-winr.0\",\n        \"oauth@1.1.4-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"http@1.0.10-winr.0\",\n        \"mongo@1.0.11-winr.0\"\n      ],\n      \"oauth1 1.1.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"service-configuration@1.0.4-winr.1\",\n        \"oauth@1.1.4-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"http@1.0.10-winr.1\",\n        \"mongo@1.0.11-winr.1\"\n      ],\n      \"oauth1 1.1.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"random@1.0.3-winr.2\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"oauth@1.1.4-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"http@1.0.10-winr.4\",\n        \"mongo@1.0.12-winr.2\"\n      ],\n      \"oauth 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"routepolicy@10.0.0-glasser.isopacket.0\",\n        \"webapp@10.0.0-glasser.isopacket.0\",\n        \"mongo@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"service-configuration@10.0.0-glasser.isopacket.0\",\n        \"logging@10.0.0-glasser.isopacket.0\",\n        \"?oauth-encryption@10.0.0-glasser.isopacket.0\",\n        \"localstorage@10.0.0-glasser.isopacket.0\",\n        \"url@10.0.0-glasser.isopacket.0\",\n        \"reload@10.0.0-glasser.isopacket.0\",\n        \"base64@10.0.0-glasser.isopacket.0\"\n      ],\n      \"oauth 1.0.0\": [\n        \"localstorage@1.0.0\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.2\",\n        \"mongo-livedata@1.0.3\",\n        \"?oauth-encryption@1.0.0\",\n        \"routepolicy@1.0.0\",\n        \"service-configuration@1.0.0\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.2\"\n      ],\n      \"oauth 1.0.1-glasser1\": [\n        \"meteor\",\n        \"routepolicy\",\n        \"webapp\",\n        \"mongo\",\n        \"underscore\",\n        \"service-configuration\",\n        \"logging\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"url\",\n        \"reload\"\n      ],\n      \"oauth 1.0.1-rc0\": [\n        \"meteor\",\n        \"routepolicy\",\n        \"webapp\",\n        \"mongo\",\n        \"underscore\",\n        \"service-configuration\",\n        \"logging\",\n        \"?oauth-encryption\",\n        \"localstorage\"\n      ],\n      \"oauth 1.0.1\": [\n        \"localstorage@1.0.0\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.3\",\n        \"mongo@1.0.4\",\n        \"?oauth-encryption@1.0.0\",\n        \"routepolicy@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.3\"\n      ],\n      \"oauth 1.0.2-ekate\": [\n        \"meteor\",\n        \"routepolicy\",\n        \"webapp\",\n        \"mongo\",\n        \"underscore\",\n        \"service-configuration\",\n        \"logging\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"url\",\n        \"reload\"\n      ],\n      \"oauth 1.1.0-rc0\": [\n        \"meteor\",\n        \"routepolicy\",\n        \"webapp\",\n        \"mongo\",\n        \"underscore\",\n        \"service-configuration\",\n        \"logging\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"url\",\n        \"reload\"\n      ],\n      \"oauth 1.1.0-rc1\": [\n        \"meteor\",\n        \"routepolicy\",\n        \"webapp\",\n        \"mongo\",\n        \"underscore\",\n        \"service-configuration\",\n        \"logging\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"url\",\n        \"reload\"\n      ],\n      \"oauth 1.1.0-rc2\": [\n        \"meteor\",\n        \"routepolicy\",\n        \"webapp\",\n        \"mongo\",\n        \"underscore\",\n        \"service-configuration\",\n        \"logging\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"url\",\n        \"reload\",\n        \"base64\"\n      ],\n      \"oauth 1.1.0-rc3\": [\n        \"meteor\",\n        \"routepolicy\",\n        \"webapp\",\n        \"mongo\",\n        \"underscore\",\n        \"service-configuration\",\n        \"logging\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"url\",\n        \"reload\",\n        \"base64\"\n      ],\n      \"oauth 1.1.0\": [\n        \"base64@1.0.0\",\n        \"localstorage@1.0.0\",\n        \"logging@1.0.3\",\n        \"meteor@1.1.0\",\n        \"mongo@1.0.5\",\n        \"?oauth-encryption@1.0.0\",\n        \"reload@1.1.0\",\n        \"routepolicy@1.0.1\",\n        \"service-configuration@1.0.1\",\n        \"underscore@1.0.0\",\n        \"url@1.0.0\",\n        \"webapp@1.1.1\"\n      ],\n      \"oauth 1.1.1-pre.0\": [\n        \"meteor\",\n        \"routepolicy\",\n        \"webapp\",\n        \"mongo\",\n        \"underscore\",\n        \"service-configuration\",\n        \"logging\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"url\",\n        \"reload\",\n        \"base64\"\n      ],\n      \"oauth 1.1.1-pre.1\": [\n        \"meteor\",\n        \"routepolicy\",\n        \"webapp\",\n        \"mongo\",\n        \"underscore\",\n        \"service-configuration\",\n        \"logging\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"url\",\n        \"reload\",\n        \"base64\"\n      ],\n      \"oauth 1.1.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"routepolicy@1.0.2-pre.2\",\n        \"webapp@1.1.3-pre.2\",\n        \"mongo@1.0.7-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"service-configuration@1.0.2-pre.2\",\n        \"logging@1.0.4-pre.2\",\n        \"?oauth-encryption@1.0.1-pre.2\",\n        \"localstorage@1.0.1-pre.2\",\n        \"url@1.0.1-pre.2\",\n        \"reload@1.1.1-pre.2\",\n        \"base64@1.0.1-pre.2\"\n      ],\n      \"oauth 1.1.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"routepolicy@1.0.2-rc.0\",\n        \"webapp@1.1.3-rc.0\",\n        \"mongo@1.0.7-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"logging@1.0.4-rc.0\",\n        \"?oauth-encryption@1.0.1-rc.0\",\n        \"localstorage@1.0.1-rc.0\",\n        \"url@1.0.1-rc.0\",\n        \"reload@1.1.1-rc.0\",\n        \"base64@1.0.1-rc.0\"\n      ],\n      \"oauth 1.1.1\": [\n        \"meteor@1.1.2\",\n        \"routepolicy@1.0.2\",\n        \"webapp@1.1.3\",\n        \"mongo@1.0.7\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"logging@1.0.4\",\n        \"?oauth-encryption@1.0.1\",\n        \"localstorage@1.0.1\",\n        \"url@1.0.1\",\n        \"reload@1.1.1\",\n        \"base64@1.0.1\"\n      ],\n      \"oauth 1.1.2-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"routepolicy@1.0.2\",\n        \"webapp@1.1.4-rc.2\",\n        \"mongo@1.0.8-rc.1\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"logging@1.0.5-rc.0\",\n        \"?oauth-encryption@1.0.1\",\n        \"localstorage@1.0.1\",\n        \"url@1.0.2-rc.0\",\n        \"reload@1.1.1\",\n        \"base64@1.0.1\"\n      ],\n      \"oauth 1.1.2-rc.1\": [\n        \"meteor@1.1.3-rc.0\",\n        \"routepolicy@1.0.2\",\n        \"webapp@1.1.4-rc.2\",\n        \"mongo@1.0.8-rc.1\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"logging@1.0.5-rc.0\",\n        \"?oauth-encryption@1.0.1\",\n        \"localstorage@1.0.1\",\n        \"url@1.0.2-rc.0\",\n        \"reload@1.1.1\",\n        \"base64@1.0.1\"\n      ],\n      \"oauth 1.1.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"routepolicy@1.0.2-win.0\",\n        \"webapp@1.1.4-win.0\",\n        \"mongo@1.0.8-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"service-configuration@1.0.2-win.0\",\n        \"logging@1.0.5-win.0\",\n        \"?oauth-encryption@1.0.1-win.0\",\n        \"localstorage@1.0.1-win.0\",\n        \"url@1.0.2-win.0\",\n        \"reload@1.1.1-win.0\",\n        \"base64@1.0.1-win.0\"\n      ],\n      \"oauth 1.1.2\": [\n        \"meteor@1.1.3\",\n        \"routepolicy@1.0.2\",\n        \"webapp@1.1.4\",\n        \"mongo@1.0.8\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"logging@1.0.5\",\n        \"?oauth-encryption@1.0.1\",\n        \"localstorage@1.0.1\",\n        \"url@1.0.2\",\n        \"reload@1.1.1\",\n        \"base64@1.0.1\"\n      ],\n      \"oauth 1.1.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"routepolicy@1.0.3-ipc.0\",\n        \"webapp@1.1.5-ipc.0\",\n        \"mongo@1.0.9-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"service-configuration@1.0.3-ipc.0\",\n        \"logging@1.0.6-ipc.0\",\n        \"?oauth-encryption@1.0.2-ipc.0\",\n        \"localstorage@1.0.2-ipc.0\",\n        \"url@1.0.3-ipc.0\",\n        \"reload@1.1.2-ipc.0\",\n        \"base64@1.0.2-ipc.0\"\n      ],\n      \"oauth 1.1.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"routepolicy@1.0.3-rc.1\",\n        \"webapp@1.1.5-rc.1\",\n        \"mongo@1.0.10-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"service-configuration@1.0.3-rc.1\",\n        \"logging@1.0.6-rc.1\",\n        \"?oauth-encryption@1.0.2-rc.1\",\n        \"localstorage@1.0.2-rc.1\",\n        \"url@1.0.3-rc.1\",\n        \"reload@1.1.2-rc.1\",\n        \"base64@1.0.2-rc.1\"\n      ],\n      \"oauth 1.1.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"routepolicy@1.0.3-slava.0\",\n        \"webapp@1.1.5-slava.0\",\n        \"mongo@1.0.10-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"service-configuration@1.0.3-slava.0\",\n        \"logging@1.0.6-slava.0\",\n        \"?oauth-encryption@1.0.2-slava.0\",\n        \"localstorage@1.0.2-slava.0\",\n        \"url@1.0.3-slava.0\",\n        \"reload@1.1.2-slava.0\",\n        \"base64@1.0.2-slava.0\"\n      ],\n      \"oauth 1.1.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"routepolicy@1.0.3-win.0\",\n        \"webapp@1.1.5-win.0\",\n        \"mongo@1.0.9-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"service-configuration@1.0.3-win.0\",\n        \"logging@1.0.6-win.0\",\n        \"?oauth-encryption@1.0.1-win.1\",\n        \"localstorage@1.0.2-win.0\",\n        \"url@1.0.3-win.0\",\n        \"reload@1.1.2-win.0\",\n        \"base64@1.0.2-win.0\"\n      ],\n      \"oauth 1.1.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"routepolicy@1.0.3-winr.0\",\n        \"webapp@1.1.5-winr.0\",\n        \"mongo@1.0.10-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"service-configuration@1.0.3-winr.0\",\n        \"logging@1.0.6-winr.0\",\n        \"?oauth-encryption@1.0.2-winr.0\",\n        \"localstorage@1.0.2-winr.0\",\n        \"url@1.0.3-winr.0\",\n        \"reload@1.1.2-winr.0\",\n        \"base64@1.0.2-winr.0\"\n      ],\n      \"oauth 1.1.3\": [\n        \"meteor@1.1.4\",\n        \"routepolicy@1.0.3\",\n        \"webapp@1.1.5\",\n        \"mongo@1.0.10\",\n        \"underscore@1.0.2\",\n        \"service-configuration@1.0.3\",\n        \"logging@1.0.6\",\n        \"?oauth-encryption@1.0.2\",\n        \"localstorage@1.0.2\",\n        \"url@1.0.3\",\n        \"reload@1.1.2\",\n        \"base64@1.0.2\"\n      ],\n      \"oauth 1.1.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"routepolicy@1.0.4-eachin.43\",\n        \"webapp@1.1.7-eachin.43\",\n        \"mongo@1.0.12-eachin.45\",\n        \"underscore@1.0.3-eachin.43\",\n        \"service-configuration@1.0.4-eachin.43\",\n        \"logging@1.0.6-eachin.43\",\n        \"?oauth-encryption@1.0.3-eachin.43\",\n        \"localstorage@1.0.3-eachin.43\",\n        \"url@1.0.4-eachin.43\",\n        \"reload@1.1.3-eachin.43\",\n        \"base64@1.0.3-eachin.43\"\n      ],\n      \"oauth 1.1.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"routepolicy@1.0.4-githubble.0\",\n        \"webapp@1.1.7-githubble.0\",\n        \"mongo@1.0.12-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"service-configuration@1.0.4-githubble.0\",\n        \"logging@1.0.6-githubble.0\",\n        \"?oauth-encryption@1.0.3-githubble.0\",\n        \"localstorage@1.0.3-githubble.0\",\n        \"url@1.0.4-githubble.0\",\n        \"reload@1.1.3-githubble.0\",\n        \"base64@1.0.3-githubble.0\"\n      ],\n      \"oauth 1.1.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"routepolicy@1.0.4-githubble.2\",\n        \"webapp@1.1.7-githubble.2\",\n        \"mongo@1.0.12-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"service-configuration@1.0.4-githubble.2\",\n        \"logging@1.0.6-githubble.2\",\n        \"?oauth-encryption@1.0.3-githubble.2\",\n        \"localstorage@1.0.3-githubble.2\",\n        \"url@1.0.4-githubble.2\",\n        \"reload@1.1.3-githubble.2\",\n        \"base64@1.0.3-githubble.2\"\n      ],\n      \"oauth 1.1.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"routepolicy@1.0.4-githubble.42\",\n        \"webapp@1.1.7-githubble.42\",\n        \"mongo@1.0.12-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"service-configuration@1.0.4-githubble.42\",\n        \"logging@1.0.6-githubble.42\",\n        \"?oauth-encryption@1.0.3-githubble.42\",\n        \"localstorage@1.0.3-githubble.42\",\n        \"url@1.0.4-githubble.42\",\n        \"reload@1.1.3-githubble.42\",\n        \"base64@1.0.3-githubble.42\"\n      ],\n      \"oauth 1.1.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"routepolicy@1.0.4-githubble.43\",\n        \"webapp@1.1.7-githubble.43\",\n        \"mongo@1.0.12-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"service-configuration@1.0.4-githubble.43\",\n        \"logging@1.0.6-githubble.43\",\n        \"?oauth-encryption@1.0.3-githubble.43\",\n        \"localstorage@1.0.3-githubble.43\",\n        \"url@1.0.4-githubble.43\",\n        \"reload@1.1.3-githubble.43\",\n        \"base64@1.0.3-githubble.43\"\n      ],\n      \"oauth 1.1.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"routepolicy@1.0.5-rc.0\",\n        \"webapp@1.2.0-rc.0\",\n        \"mongo@1.1.0-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"service-configuration@1.0.4-rc.0\",\n        \"logging@1.0.7-rc.0\",\n        \"?oauth-encryption@1.0.3-rc.0\",\n        \"localstorage@1.0.3-rc.0\",\n        \"url@1.0.4-rc.0\",\n        \"reload@1.1.3-rc.0\",\n        \"base64@1.0.3-rc.0\"\n      ],\n      \"oauth 1.1.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"routepolicy@1.0.4-winr.0\",\n        \"webapp@1.1.6-winr.0\",\n        \"mongo@1.0.11-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"service-configuration@1.0.4-winr.0\",\n        \"logging@1.0.7-winr.0\",\n        \"?oauth-encryption@1.0.3-winr.0\",\n        \"localstorage@1.0.3-winr.0\",\n        \"url@1.0.4-winr.0\",\n        \"reload@1.1.3-winr.0\",\n        \"base64@1.0.3-winr.0\"\n      ],\n      \"oauth 1.1.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"routepolicy@1.0.4-winr.1\",\n        \"webapp@1.1.6-winr.1\",\n        \"mongo@1.0.11-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"service-configuration@1.0.4-winr.1\",\n        \"logging@1.0.7-winr.1\",\n        \"?oauth-encryption@1.0.3-winr.1\",\n        \"localstorage@1.0.3-winr.1\",\n        \"url@1.0.4-winr.1\",\n        \"reload@1.1.3-winr.1\",\n        \"base64@1.0.3-winr.1\"\n      ],\n      \"oauth 1.1.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"routepolicy@1.0.4-winr.4\",\n        \"webapp@1.1.6-winr.4\",\n        \"mongo@1.0.12-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"logging@1.0.6-winr.2\",\n        \"?oauth-encryption@1.0.3-winr.4\",\n        \"localstorage@1.0.3-winr.2\",\n        \"url@1.0.4-winr.2\",\n        \"reload@1.1.3-winr.3\",\n        \"base64@1.0.3-winr.2\"\n      ],\n      \"oauth 1.1.4-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"routepolicy@1.0.4-winr.4\",\n        \"webapp@1.1.7-winr.6\",\n        \"mongo@1.0.12-winr.5\",\n        \"underscore@1.0.3-winr.2\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"logging@1.0.6-winr.3\",\n        \"?oauth-encryption@1.0.3-winr.4\",\n        \"localstorage@1.0.3-winr.2\",\n        \"url@1.0.4-winr.2\",\n        \"reload@1.1.3-winr.3\",\n        \"base64@1.0.3-winr.2\"\n      ],\n      \"oauth-encryption 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"npm-node-aes-gcm@=0.1.3\",\n        \"underscore@10.0.0-glasser.isopacket.0\"\n      ],\n      \"oauth-encryption 1.0.0\": [\n        \"meteor@1.0.2\",\n        \"npm-node-aes-gcm@=0.1.3\",\n        \"underscore@1.0.0\"\n      ],\n      \"oauth-encryption 1.0.1-pre.0\": [\n        \"meteor\",\n        \"npm-node-aes-gcm@=0.1.3\",\n        \"underscore\"\n      ],\n      \"oauth-encryption 1.0.1-pre.1\": [\n        \"meteor\",\n        \"npm-node-aes-gcm@=0.1.3\",\n        \"underscore\"\n      ],\n      \"oauth-encryption 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"npm-node-aes-gcm@=0.1.3\",\n        \"underscore@1.0.1-pre.2\"\n      ],\n      \"oauth-encryption 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"npm-node-aes-gcm@=0.1.3\",\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"oauth-encryption 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"junk:npm-node-aes-gcm@=0.1.3\",\n        \"underscore@1.0.1-win.0\"\n      ],\n      \"oauth-encryption 1.0.1-win.1\": [\n        \"meteor@1.1.3-win.0\",\n        \"npm-node-aes-gcm@=0.1.3-win.0\",\n        \"underscore@1.0.1-win.0\"\n      ],\n      \"oauth-encryption 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"npm-node-aes-gcm@=0.1.3\",\n        \"underscore@1.0.1\"\n      ],\n      \"oauth-encryption 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"npm-node-aes-gcm@=0.1.3\",\n        \"underscore@1.0.2-ipc.0\"\n      ],\n      \"oauth-encryption 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"npm-node-aes-gcm@=0.1.3\",\n        \"underscore@1.0.2-rc.1\"\n      ],\n      \"oauth-encryption 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"npm-node-aes-gcm@=0.1.3\",\n        \"underscore@1.0.2-slava.0\"\n      ],\n      \"oauth-encryption 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"npm-node-aes-gcm@=0.1.3-win.0\",\n        \"underscore@1.0.2-winr.0\"\n      ],\n      \"oauth-encryption 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"npm-node-aes-gcm@=0.1.3\",\n        \"underscore@1.0.2\"\n      ],\n      \"oauth-encryption 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"npm-node-aes-gcm@0.1.4-winr.1\",\n        \"underscore@1.0.3-eachin.0\"\n      ],\n      \"oauth-encryption 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"npm-node-aes-gcm@0.1.4-winr.1\",\n        \"underscore@1.0.3-eachin.43\"\n      ],\n      \"oauth-encryption 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"npm-node-aes-gcm@0.1.4-winr.1\",\n        \"underscore@1.0.3-githubble.0\"\n      ],\n      \"oauth-encryption 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"npm-node-aes-gcm@0.1.4-winr.1\",\n        \"underscore@1.0.3-githubble.2\"\n      ],\n      \"oauth-encryption 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"npm-node-aes-gcm@0.1.4-winr.1\",\n        \"underscore@1.0.3-githubble.42\"\n      ],\n      \"oauth-encryption 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"npm-node-aes-gcm@0.1.4-winr.1\",\n        \"underscore@1.0.3-githubble.43\"\n      ],\n      \"oauth-encryption 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"npm-node-aes-gcm@=0.1.3_1\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"oauth-encryption 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\"\n      ],\n      \"oauth-encryption 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\"\n      ],\n      \"oauth-encryption 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.1\",\n        \"npm-node-aes-gcm@0.1.4-winr.1\",\n        \"underscore@1.0.3-winr.1\"\n      ],\n      \"oauth-encryption 1.0.3-winr.3\": [\n        \"meteor@1.1.5-winr.3\",\n        \"npm-node-aes-gcm@0.1.4-winr.1\",\n        \"underscore@1.0.2\"\n      ],\n      \"oauth-encryption 1.0.3-winr.4\": [\n        \"meteor@1.1.5-winr.4\",\n        \"npm-node-aes-gcm@0.1.4-winr.1\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"junk:npm-node-aes-gcm 0.1.3\": [\n        \"meteor\"\n      ],\n      \"npm-node-aes-gcm 0.1.3-win.0\": [\n        \"meteor\"\n      ],\n      \"npm-node-aes-gcm 0.1.3\": [\n        \"meteor\"\n      ],\n      \"npm-node-aes-gcm 0.1.3_1\": [\n        \"meteor\"\n      ],\n      \"npm-node-aes-gcm 0.1.4-winr.0\": [\n        \"meteor\"\n      ],\n      \"npm-node-aes-gcm 0.1.4-winr.1\": [\n        \"meteor\"\n      ],\n      \"mongo 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\",\n        \"json@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"minimongo@10.0.0-glasser.isopacket.0\",\n        \"logging@10.0.0-glasser.isopacket.0\",\n        \"ddp@10.0.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\",\n        \"application-configuration@10.0.0-glasser.isopacket.0\",\n        \"check@10.0.0-glasser.isopacket.0\",\n        \"binary-heap@10.0.0-glasser.isopacket.0\",\n        \"?insecure@10.0.0-glasser.isopacket.0\",\n        \"?autopublish@10.0.0-glasser.isopacket.0\",\n        \"?disable-oplog@10.0.0-glasser.isopacket.0\",\n        \"?webapp@10.0.0-glasser.isopacket.0\",\n        \"?facts@10.0.0-glasser.isopacket.0\",\n        \"callback-hook@10.0.0-glasser.isopacket.0\"\n      ],\n      \"mongo 1.0.4-rc0\": [\n        \"meteor\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"minimongo\",\n        \"logging\",\n        \"ddp\",\n        \"tracker\",\n        \"application-configuration\",\n        \"check\",\n        \"binary-heap\",\n        \"?insecure\",\n        \"?autopublish\",\n        \"?disable-oplog\",\n        \"?webapp\",\n        \"?facts\",\n        \"callback-hook\"\n      ],\n      \"mongo 1.0.4-rc1\": [\n        \"meteor\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"minimongo\",\n        \"logging\",\n        \"ddp\",\n        \"tracker\",\n        \"application-configuration\",\n        \"check\",\n        \"binary-heap\",\n        \"?insecure\",\n        \"?autopublish\",\n        \"?disable-oplog\",\n        \"?webapp\",\n        \"?facts\",\n        \"callback-hook\"\n      ],\n      \"mongo 1.0.4\": [\n        \"application-configuration@1.0.1\",\n        \"?autopublish@1.0.0\",\n        \"binary-heap@1.0.0\",\n        \"callback-hook@1.0.0\",\n        \"check@1.0.0\",\n        \"ddp@1.0.8\",\n        \"?disable-oplog@1.0.0\",\n        \"ejson@1.0.1\",\n        \"?facts@1.0.1\",\n        \"?insecure@1.0.0\",\n        \"json@1.0.0\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.3\",\n        \"minimongo@1.0.2\",\n        \"random@1.0.0\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\",\n        \"?webapp@1.0.3\"\n      ],\n      \"mongo 1.0.5-ekate\": [\n        \"meteor\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"minimongo\",\n        \"logging\",\n        \"ddp\",\n        \"tracker\",\n        \"application-configuration\",\n        \"check\",\n        \"binary-heap\",\n        \"?insecure\",\n        \"?autopublish\",\n        \"?disable-oplog\",\n        \"?webapp\",\n        \"?facts\",\n        \"callback-hook\"\n      ],\n      \"mongo 1.0.5\": [\n        \"application-configuration@1.0.2\",\n        \"?autopublish@1.0.0\",\n        \"binary-heap@1.0.0\",\n        \"callback-hook@1.0.0\",\n        \"check@1.0.0\",\n        \"ddp@1.0.8\",\n        \"?disable-oplog@1.0.0\",\n        \"ejson@1.0.2\",\n        \"?facts@1.0.1\",\n        \"?insecure@1.0.0\",\n        \"json@1.0.0\",\n        \"logging@1.0.3\",\n        \"meteor@1.1.0\",\n        \"minimongo@1.0.3\",\n        \"random@1.0.0\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\",\n        \"?webapp@1.1.1\"\n      ],\n      \"mongo 1.0.6-rc0\": [\n        \"meteor\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"minimongo\",\n        \"logging\",\n        \"ddp\",\n        \"tracker\",\n        \"application-configuration\",\n        \"check\",\n        \"binary-heap\",\n        \"?insecure\",\n        \"?autopublish\",\n        \"?disable-oplog\",\n        \"?webapp\",\n        \"?facts\",\n        \"callback-hook\"\n      ],\n      \"mongo 1.0.6\": [\n        \"application-configuration@1.0.2\",\n        \"?autopublish@1.0.0\",\n        \"binary-heap@1.0.0\",\n        \"callback-hook@1.0.0\",\n        \"check@1.0.1\",\n        \"ddp@1.0.9\",\n        \"?disable-oplog@1.0.0\",\n        \"ejson@1.0.3\",\n        \"?facts@1.0.1\",\n        \"?insecure@1.0.0\",\n        \"json@1.0.0\",\n        \"logging@1.0.3\",\n        \"meteor@1.1.1\",\n        \"minimongo@1.0.3\",\n        \"random@1.0.0\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\",\n        \"?webapp@1.1.2\"\n      ],\n      \"mongo 1.0.7-pre.0\": [\n        \"meteor\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"minimongo\",\n        \"logging\",\n        \"ddp\",\n        \"tracker\",\n        \"application-configuration\",\n        \"check\",\n        \"binary-heap\",\n        \"?insecure\",\n        \"?autopublish\",\n        \"?disable-oplog\",\n        \"?webapp\",\n        \"?facts\",\n        \"callback-hook\"\n      ],\n      \"mongo 1.0.7-pre.1\": [\n        \"meteor\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"minimongo\",\n        \"logging\",\n        \"ddp\",\n        \"tracker\",\n        \"application-configuration\",\n        \"check\",\n        \"binary-heap\",\n        \"?insecure\",\n        \"?autopublish\",\n        \"?disable-oplog\",\n        \"?webapp\",\n        \"?facts\",\n        \"callback-hook\"\n      ],\n      \"mongo 1.0.7-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"ejson@1.0.4-pre.2\",\n        \"json@1.0.1-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"minimongo@1.0.4-pre.3\",\n        \"logging@1.0.4-pre.2\",\n        \"ddp@1.0.10-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"application-configuration@1.0.3-pre.2\",\n        \"check@1.0.2-pre.2\",\n        \"binary-heap@1.0.1-pre.2\",\n        \"?insecure@1.0.1-pre.2\",\n        \"?autopublish@1.0.1-pre.2\",\n        \"?disable-oplog@1.0.1-pre.2\",\n        \"?webapp@1.1.3-pre.2\",\n        \"?facts@1.0.2-pre.2\",\n        \"callback-hook@1.0.1-pre.2\"\n      ],\n      \"mongo 1.0.7-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"json@1.0.1-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"minimongo@1.0.4-rc.0\",\n        \"logging@1.0.4-rc.0\",\n        \"ddp@1.0.10-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"application-configuration@1.0.3-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"binary-heap@1.0.1-rc.0\",\n        \"?insecure@1.0.1-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"?disable-oplog@1.0.1-rc.0\",\n        \"?webapp@1.1.3-rc.0\",\n        \"?facts@1.0.2-rc.0\",\n        \"callback-hook@1.0.1-rc.0\"\n      ],\n      \"mongo 1.0.7\": [\n        \"meteor@1.1.2\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"json@1.0.1\",\n        \"underscore@1.0.1\",\n        \"minimongo@1.0.4\",\n        \"logging@1.0.4\",\n        \"ddp@1.0.10\",\n        \"tracker@1.0.3\",\n        \"application-configuration@1.0.3\",\n        \"check@1.0.2\",\n        \"binary-heap@1.0.1\",\n        \"?insecure@1.0.1\",\n        \"?autopublish@1.0.1\",\n        \"?disable-oplog@1.0.1\",\n        \"?webapp@1.1.3\",\n        \"?facts@1.0.2\",\n        \"callback-hook@1.0.1\"\n      ],\n      \"mongo 1.0.7_1\": [\n        \"meteor@1.1.2\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"json@1.0.1\",\n        \"underscore@1.0.1\",\n        \"minimongo@1.0.4\",\n        \"logging@1.0.4\",\n        \"ddp@1.0.10\",\n        \"tracker@1.0.3\",\n        \"application-configuration@1.0.3\",\n        \"check@1.0.2\",\n        \"binary-heap@1.0.1\",\n        \"?insecure@1.0.1\",\n        \"?autopublish@1.0.1\",\n        \"?disable-oplog@1.0.1\",\n        \"?webapp@1.1.3\",\n        \"?facts@1.0.2\",\n        \"callback-hook@1.0.1\"\n      ],\n      \"mongo 1.0.8-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"json@1.0.1\",\n        \"underscore@1.0.1\",\n        \"minimongo@1.0.5-rc.0\",\n        \"logging@1.0.5-rc.0\",\n        \"ddp@1.0.11-rc.0\",\n        \"tracker@1.0.3\",\n        \"application-configuration@1.0.3\",\n        \"check@1.0.2\",\n        \"binary-heap@1.0.1\",\n        \"?insecure@1.0.1\",\n        \"?autopublish@1.0.1\",\n        \"?disable-oplog@1.0.1\",\n        \"?webapp@1.1.4-rc.0\",\n        \"?facts@1.0.2\",\n        \"callback-hook@1.0.1\"\n      ],\n      \"mongo 1.0.8-rc.1\": [\n        \"meteor@1.1.3-rc.0\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"json@1.0.1\",\n        \"underscore@1.0.1\",\n        \"minimongo@1.0.5-rc.0\",\n        \"logging@1.0.5-rc.0\",\n        \"ddp@1.0.11-rc.1\",\n        \"tracker@1.0.3\",\n        \"application-configuration@1.0.3\",\n        \"check@1.0.2\",\n        \"binary-heap@1.0.1\",\n        \"?insecure@1.0.1\",\n        \"?autopublish@1.0.1\",\n        \"?disable-oplog@1.0.1\",\n        \"?webapp@1.1.4-rc.1\",\n        \"?facts@1.0.2\",\n        \"callback-hook@1.0.1\"\n      ],\n      \"mongo 1.0.8-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"random@1.0.1-win.0\",\n        \"ejson@1.0.4-win.0\",\n        \"json@1.0.1-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"minimongo@1.0.5-win.0\",\n        \"logging@1.0.5-win.0\",\n        \"ddp@1.0.11-win.0\",\n        \"tracker@1.0.3-win.0\",\n        \"application-configuration@1.0.3-win.0\",\n        \"check@1.0.2-win.0\",\n        \"binary-heap@1.0.1-win.0\",\n        \"?insecure@1.0.1-win.0\",\n        \"?autopublish@1.0.1-win.0\",\n        \"?disable-oplog@1.0.1-win.0\",\n        \"?webapp@1.1.4-win.0\",\n        \"?facts@1.0.2-win.0\",\n        \"callback-hook@1.0.1-win.0\"\n      ],\n      \"mongo 1.0.8\": [\n        \"meteor@1.1.3\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"json@1.0.1\",\n        \"underscore@1.0.1\",\n        \"minimongo@1.0.5\",\n        \"logging@1.0.5\",\n        \"ddp@1.0.11\",\n        \"tracker@1.0.3\",\n        \"application-configuration@1.0.3\",\n        \"check@1.0.2\",\n        \"binary-heap@1.0.1\",\n        \"?insecure@1.0.1\",\n        \"?autopublish@1.0.1\",\n        \"?disable-oplog@1.0.1\",\n        \"?webapp@1.1.4\",\n        \"?facts@1.0.2\",\n        \"callback-hook@1.0.1\"\n      ],\n      \"mongo 1.0.9-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"json@1.0.2-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"minimongo@1.0.6-ipc.0\",\n        \"logging@1.0.6-ipc.0\",\n        \"ddp@1.0.12-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"application-configuration@1.0.4-ipc.0\",\n        \"check@1.0.3-ipc.0\",\n        \"binary-heap@1.0.2-ipc.0\",\n        \"?insecure@1.0.2-ipc.0\",\n        \"?autopublish@1.0.2-ipc.0\",\n        \"?disable-oplog@1.0.2-ipc.0\",\n        \"?webapp@1.1.5-ipc.0\",\n        \"?facts@1.0.3-ipc.0\",\n        \"callback-hook@1.0.2-ipc.0\"\n      ],\n      \"mongo 1.0.9-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"random@1.0.2-win.0\",\n        \"ejson@1.0.5-win.0\",\n        \"json@1.0.2-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"minimongo@1.0.6-win.0\",\n        \"logging@1.0.6-win.0\",\n        \"ddp@1.0.12-win.0\",\n        \"tracker@1.0.4-win.0\",\n        \"application-configuration@1.0.4-win.0\",\n        \"check@1.0.3-win.0\",\n        \"binary-heap@1.0.2-win.0\",\n        \"?insecure@1.0.2-win.0\",\n        \"?autopublish@1.0.2-win.0\",\n        \"?disable-oplog@1.0.2-win.0\",\n        \"?webapp@1.1.5-win.0\",\n        \"?facts@1.0.3-win.0\",\n        \"callback-hook@1.0.2-win.0\"\n      ],\n      \"mongo 1.0.9\": [\n        \"meteor@1.1.3\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"json@1.0.1\",\n        \"underscore@1.0.1\",\n        \"minimongo@1.0.5\",\n        \"logging@1.0.5\",\n        \"ddp@1.0.12\",\n        \"tracker@1.0.3\",\n        \"application-configuration@1.0.3\",\n        \"check@1.0.2\",\n        \"binary-heap@1.0.1\",\n        \"?insecure@1.0.1\",\n        \"?autopublish@1.0.1\",\n        \"?disable-oplog@1.0.1\",\n        \"?webapp@1.1.4\",\n        \"?facts@1.0.2\",\n        \"callback-hook@1.0.1\"\n      ],\n      \"mongo 1.0.10-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"json@1.0.2-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"minimongo@1.0.6-ipc.1\",\n        \"logging@1.0.6-ipc.0\",\n        \"ddp@1.0.13-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"application-configuration@1.0.4-ipc.0\",\n        \"check@1.0.3-ipc.1\",\n        \"binary-heap@1.0.2-ipc.0\",\n        \"?insecure@1.0.2-ipc.0\",\n        \"?autopublish@1.0.2-ipc.0\",\n        \"?disable-oplog@1.0.2-ipc.0\",\n        \"?webapp@1.1.5-ipc.1\",\n        \"?facts@1.0.3-ipc.0\",\n        \"callback-hook@1.0.2-ipc.0\"\n      ],\n      \"mongo 1.0.10-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"ejson@1.0.5-rc.1\",\n        \"json@1.0.2-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"minimongo@1.0.6-rc.1\",\n        \"logging@1.0.6-rc.1\",\n        \"ddp@1.0.13-rc.1\",\n        \"tracker@1.0.4-rc.1\",\n        \"application-configuration@1.0.4-rc.1\",\n        \"check@1.0.3-rc.1\",\n        \"binary-heap@1.0.2-rc.1\",\n        \"?insecure@1.0.2-rc.1\",\n        \"?autopublish@1.0.2-rc.1\",\n        \"?disable-oplog@1.0.2-rc.1\",\n        \"?webapp@1.1.5-rc.1\",\n        \"?facts@1.0.3-rc.1\",\n        \"callback-hook@1.0.2-rc.1\"\n      ],\n      \"mongo 1.0.10-rc.2\": [\n        \"meteor@1.1.4-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"ejson@1.0.5-rc.1\",\n        \"json@1.0.2-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"minimongo@1.0.6-rc.1\",\n        \"logging@1.0.6-rc.1\",\n        \"ddp@1.0.13-rc.1\",\n        \"tracker@1.0.4-rc.1\",\n        \"application-configuration@1.0.4-rc.1\",\n        \"check@1.0.3-rc.1\",\n        \"binary-heap@1.0.2-rc.1\",\n        \"?insecure@1.0.2-rc.1\",\n        \"?autopublish@1.0.2-rc.1\",\n        \"?disable-oplog@1.0.2-rc.1\",\n        \"?webapp@1.1.5-rc.1\",\n        \"?facts@1.0.3-rc.1\",\n        \"callback-hook@1.0.2-rc.1\"\n      ],\n      \"mongo 1.0.10-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"ejson@1.0.5-slava.0\",\n        \"json@1.0.2-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"minimongo@1.0.6-slava.0\",\n        \"logging@1.0.6-slava.0\",\n        \"ddp@1.0.13-slava.0\",\n        \"tracker@1.0.4-slava.0\",\n        \"application-configuration@1.0.4-slava.0\",\n        \"check@1.0.3-slava.0\",\n        \"binary-heap@1.0.2-slava.0\",\n        \"?insecure@1.0.2-slava.0\",\n        \"?autopublish@1.0.2-slava.0\",\n        \"?disable-oplog@1.0.2-slava.0\",\n        \"?webapp@1.1.5-slava.0\",\n        \"?facts@1.0.3-slava.0\",\n        \"callback-hook@1.0.2-slava.0\"\n      ],\n      \"mongo 1.0.10-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"ejson@1.0.5-winr.0\",\n        \"json@1.0.2-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"minimongo@1.0.6-winr.0\",\n        \"logging@1.0.6-winr.0\",\n        \"ddp@1.0.13-winr.0\",\n        \"tracker@1.0.4-winr.0\",\n        \"application-configuration@1.0.4-winr.0\",\n        \"check@1.0.3-winr.0\",\n        \"binary-heap@1.0.2-winr.0\",\n        \"?insecure@1.0.2-winr.0\",\n        \"?autopublish@1.0.2-winr.0\",\n        \"?disable-oplog@1.0.2-winr.0\",\n        \"?webapp@1.1.5-winr.0\",\n        \"?facts@1.0.3-winr.0\",\n        \"callback-hook@1.0.2-winr.0\"\n      ],\n      \"mongo 1.0.10\": [\n        \"meteor@1.1.4\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"logging@1.0.6\",\n        \"ddp@1.0.13\",\n        \"tracker@1.0.4\",\n        \"application-configuration@1.0.4\",\n        \"check@1.0.3\",\n        \"binary-heap@1.0.2\",\n        \"?insecure@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?disable-oplog@1.0.2\",\n        \"?webapp@1.1.5\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\"\n      ],\n      \"mongo 1.0.11-cordova41\": [\n        \"meteor@1.1.4\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"logging@1.0.6\",\n        \"ddp@1.0.13\",\n        \"tracker@1.0.4\",\n        \"application-configuration@1.0.4\",\n        \"check@1.0.3\",\n        \"binary-heap@1.0.2\",\n        \"?insecure@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?disable-oplog@1.0.2\",\n        \"?webapp@1.1.6-cordova41\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\"\n      ],\n      \"mongo 1.0.11-pw.1\": [\n        \"meteor@1.1.4\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"logging@1.0.6\",\n        \"ddp@1.0.13\",\n        \"tracker@1.0.4\",\n        \"application-configuration@1.0.4\",\n        \"check@1.0.3\",\n        \"binary-heap@1.0.2\",\n        \"?insecure@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?disable-oplog@1.0.2\",\n        \"?webapp@1.1.6-pw.1\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\"\n      ],\n      \"mongo 1.0.11-rc.1\": [\n        \"meteor@1.1.4\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"logging@1.0.6\",\n        \"ddp@1.0.13\",\n        \"tracker@1.0.4\",\n        \"application-configuration@1.0.4\",\n        \"check@1.0.3\",\n        \"binary-heap@1.0.2\",\n        \"?insecure@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?disable-oplog@1.0.2\",\n        \"?webapp@1.1.5\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\"\n      ],\n      \"mongo 1.0.11-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"ejson@1.0.6-winr.0\",\n        \"json@1.0.3-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"minimongo@1.0.7-winr.0\",\n        \"logging@1.0.7-winr.0\",\n        \"ddp@1.0.14-winr.0\",\n        \"tracker@1.0.5-winr.0\",\n        \"application-configuration@1.0.5-winr.0\",\n        \"check@1.0.4-winr.0\",\n        \"binary-heap@1.0.3-winr.0\",\n        \"?insecure@1.0.3-winr.0\",\n        \"?autopublish@1.0.3-winr.0\",\n        \"?disable-oplog@1.0.3-winr.0\",\n        \"?webapp@1.1.6-winr.0\",\n        \"?facts@1.0.4-winr.0\",\n        \"callback-hook@1.0.3-winr.0\"\n      ],\n      \"mongo 1.0.11-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\",\n        \"json@1.0.3-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"minimongo@1.0.7-winr.1\",\n        \"logging@1.0.7-winr.1\",\n        \"ddp@1.0.14-winr.1\",\n        \"tracker@1.0.5-winr.1\",\n        \"application-configuration@1.0.5-winr.1\",\n        \"check@1.0.4-winr.1\",\n        \"binary-heap@1.0.3-winr.1\",\n        \"?insecure@1.0.3-winr.1\",\n        \"?autopublish@1.0.3-winr.1\",\n        \"?disable-oplog@1.0.3-winr.1\",\n        \"?webapp@1.1.6-winr.1\",\n        \"?facts@1.0.4-winr.1\",\n        \"callback-hook@1.0.3-winr.1\"\n      ],\n      \"mongo 1.0.11\": [\n        \"meteor@1.1.4\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"logging@1.0.6\",\n        \"ddp@1.0.13\",\n        \"tracker@1.0.4\",\n        \"application-configuration@1.0.4\",\n        \"check@1.0.3\",\n        \"binary-heap@1.0.2\",\n        \"?insecure@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?disable-oplog@1.0.2\",\n        \"?webapp@1.1.5\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\"\n      ],\n      \"mongo 1.0.12-blz.0\": [\n        \"meteor@1.1.5-blz.0\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"logging@1.0.6\",\n        \"ddp@1.0.15-blz.1\",\n        \"tracker@1.0.5\",\n        \"check@1.0.4\",\n        \"binary-heap@1.0.2\",\n        \"?insecure@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?disable-oplog@1.0.2\",\n        \"?webapp@1.1.7-blz.0\",\n        \"?facts@1.0.4-blz.0\",\n        \"callback-hook@1.0.2\"\n      ],\n      \"mongo 1.0.12-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.3\",\n        \"logging@1.0.6-winr.2\",\n        \"ddp@1.0.14-eachin.0\",\n        \"tracker@1.0.5-winr.4\",\n        \"check@1.0.4-win.0\",\n        \"binary-heap@1.0.3-winr.2\",\n        \"?insecure@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?disable-oplog@1.0.3-winr.2\",\n        \"?webapp@1.1.6-eachin.0\",\n        \"?facts@1.0.4-winr.3\",\n        \"callback-hook@1.0.3-winr.2\"\n      ],\n      \"mongo 1.0.12-eachin.45\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"ejson@1.0.6-eachin.43\",\n        \"json@1.0.3-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"minimongo@1.0.7-eachin.43\",\n        \"logging@1.0.6-eachin.43\",\n        \"ddp@1.0.15-eachin.43\",\n        \"tracker@1.0.5-eachin.43\",\n        \"check@1.0.4-eachin.43\",\n        \"binary-heap@1.0.3-eachin.43\",\n        \"?insecure@1.0.3-eachin.43\",\n        \"?autopublish@1.0.3-eachin.43\",\n        \"?disable-oplog@1.0.3-eachin.43\",\n        \"?webapp@1.1.7-eachin.43\",\n        \"?facts@1.0.4-eachin.43\",\n        \"callback-hook@1.0.3-eachin.43\"\n      ],\n      \"mongo 1.0.12-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.3\",\n        \"logging@1.0.6-winr.2\",\n        \"ddp@1.0.14-githubble.0\",\n        \"tracker@1.0.5-winr.4\",\n        \"check@1.0.4-win.0\",\n        \"binary-heap@1.0.3-winr.2\",\n        \"?insecure@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?disable-oplog@1.0.3-winr.2\",\n        \"?webapp@1.1.6-githubble.0\",\n        \"?facts@1.0.4-winr.3\",\n        \"callback-hook@1.0.3-winr.2\"\n      ],\n      \"mongo 1.0.12-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"ejson@1.0.6-githubble.2\",\n        \"json@1.0.3-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"minimongo@1.0.7-githubble.2\",\n        \"logging@1.0.6-githubble.2\",\n        \"ddp@1.0.15-githubble.2\",\n        \"tracker@1.0.5-githubble.2\",\n        \"check@1.0.4-win.0\",\n        \"binary-heap@1.0.3-githubble.2\",\n        \"?insecure@1.0.3-githubble.2\",\n        \"?autopublish@1.0.3-githubble.2\",\n        \"?disable-oplog@1.0.3-githubble.2\",\n        \"?webapp@1.1.7-githubble.2\",\n        \"?facts@1.0.4-githubble.2\",\n        \"callback-hook@1.0.3-githubble.2\"\n      ],\n      \"mongo 1.0.12-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"ejson@1.0.6-githubble.42\",\n        \"json@1.0.3-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"minimongo@1.0.7-githubble.42\",\n        \"logging@1.0.6-githubble.42\",\n        \"ddp@1.0.15-githubble.42\",\n        \"tracker@1.0.5-githubble.42\",\n        \"check@1.0.4-win.0\",\n        \"binary-heap@1.0.3-githubble.42\",\n        \"?insecure@1.0.3-githubble.42\",\n        \"?autopublish@1.0.3-githubble.42\",\n        \"?disable-oplog@1.0.3-githubble.42\",\n        \"?webapp@1.1.7-githubble.42\",\n        \"?facts@1.0.4-githubble.42\",\n        \"callback-hook@1.0.3-githubble.42\"\n      ],\n      \"mongo 1.0.12-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"ejson@1.0.6-githubble.43\",\n        \"json@1.0.3-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"minimongo@1.0.7-githubble.43\",\n        \"logging@1.0.6-githubble.43\",\n        \"ddp@1.0.15-githubble.43\",\n        \"tracker@1.0.5-githubble.43\",\n        \"check@1.0.4-githubble.43\",\n        \"binary-heap@1.0.3-githubble.43\",\n        \"?insecure@1.0.3-githubble.43\",\n        \"?autopublish@1.0.3-githubble.43\",\n        \"?disable-oplog@1.0.3-githubble.43\",\n        \"?webapp@1.1.7-githubble.43\",\n        \"?facts@1.0.4-githubble.43\",\n        \"callback-hook@1.0.3-githubble.43\"\n      ],\n      \"mongo 1.0.12-githubble.44\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"ejson@1.0.6-githubble.43\",\n        \"json@1.0.3-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"minimongo@1.0.7-githubble.43\",\n        \"logging@1.0.6-githubble.43\",\n        \"ddp@1.0.15-githubble.43\",\n        \"tracker@1.0.5-githubble.43\",\n        \"check@1.0.4-githubble.43\",\n        \"binary-heap@1.0.3-githubble.43\",\n        \"?insecure@1.0.3-githubble.43\",\n        \"?autopublish@1.0.3-githubble.43\",\n        \"?disable-oplog@1.0.3-githubble.43\",\n        \"?webapp@1.1.7-githubble.43\",\n        \"?facts@1.0.4-githubble.43\",\n        \"callback-hook@1.0.3-githubble.43\"\n      ],\n      \"mongo 1.0.12-githubble.45\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"ejson@1.0.6-githubble.43\",\n        \"json@1.0.3-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"minimongo@1.0.7-githubble.43\",\n        \"logging@1.0.6-githubble.43\",\n        \"ddp@1.0.15-githubble.43\",\n        \"tracker@1.0.5-githubble.43\",\n        \"check@1.0.4-githubble.43\",\n        \"binary-heap@1.0.3-githubble.43\",\n        \"?insecure@1.0.3-githubble.43\",\n        \"?autopublish@1.0.3-githubble.43\",\n        \"?disable-oplog@1.0.3-githubble.43\",\n        \"?webapp@1.1.7-githubble.43\",\n        \"?facts@1.0.4-githubble.43\",\n        \"callback-hook@1.0.3-githubble.43\"\n      ],\n      \"mongo 1.0.12-oplog-backlog.0\": [\n        \"meteor@1.1.5-oplog-backlog.0\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"logging@1.0.6\",\n        \"ddp@1.0.15-oplog-backlog.0\",\n        \"tracker@1.0.5\",\n        \"application-configuration@1.0.4\",\n        \"check@1.0.4\",\n        \"binary-heap@1.0.2\",\n        \"?insecure@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?disable-oplog@1.0.2\",\n        \"?webapp@1.1.6\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\"\n      ],\n      \"mongo 1.0.12-oplog-backlog.1\": [\n        \"meteor@1.1.5-oplog-backlog.0\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"logging@1.0.6\",\n        \"ddp@1.0.15-oplog-backlog.0\",\n        \"tracker@1.0.5\",\n        \"application-configuration@1.0.4\",\n        \"check@1.0.4\",\n        \"binary-heap@1.0.2\",\n        \"?insecure@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?disable-oplog@1.0.2\",\n        \"?webapp@1.1.6\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\"\n      ],\n      \"mongo 1.0.12-oplog-backlog.2\": [\n        \"meteor@1.1.5-oplog-backlog.0\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"logging@1.0.6\",\n        \"ddp@1.0.15-oplog-backlog.0\",\n        \"tracker@1.0.5\",\n        \"application-configuration@1.0.4\",\n        \"check@1.0.4\",\n        \"binary-heap@1.0.2\",\n        \"?insecure@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?disable-oplog@1.0.2\",\n        \"?webapp@1.1.6\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\"\n      ],\n      \"mongo 1.0.12-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"logging@1.0.6\",\n        \"ddp@1.0.15-vs.1\",\n        \"tracker@1.0.5\",\n        \"check@1.0.4\",\n        \"binary-heap@1.0.2\",\n        \"?insecure@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?disable-oplog@1.0.2\",\n        \"?webapp@1.1.7-vs.1\",\n        \"?facts@1.0.4-vs.1\",\n        \"callback-hook@1.0.2\"\n      ],\n      \"mongo 1.0.12-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"logging@1.0.6\",\n        \"ddp@1.0.15-vs.2\",\n        \"tracker@1.0.5\",\n        \"check@1.0.4\",\n        \"binary-heap@1.0.2\",\n        \"?insecure@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?disable-oplog@1.0.2\",\n        \"?webapp@1.1.7-vs.2\",\n        \"?facts@1.0.4-vs.2\",\n        \"callback-hook@1.0.2\"\n      ],\n      \"mongo 1.0.12-winr.0\": [\n        \"meteor@1.1.5-winr.2\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"logging@1.0.6\",\n        \"ddp@1.0.14-winr.2\",\n        \"tracker@1.0.5-winr.2\",\n        \"application-configuration@1.0.4\",\n        \"check@1.0.4-win.0\",\n        \"binary-heap@1.0.2\",\n        \"?insecure@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?disable-oplog@1.0.2\",\n        \"?webapp@1.1.6-winr.2\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\"\n      ],\n      \"mongo 1.0.12-winr.1\": [\n        \"meteor@1.1.5-winr.3\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"logging@1.0.6\",\n        \"ddp@1.0.14-winr.3\",\n        \"tracker@1.0.5-winr.3\",\n        \"application-configuration@1.0.4\",\n        \"check@1.0.4-win.0\",\n        \"binary-heap@1.0.2\",\n        \"?insecure@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?disable-oplog@1.0.2\",\n        \"?webapp@1.1.6-winr.3\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\"\n      ],\n      \"mongo 1.0.12-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.2\",\n        \"logging@1.0.6-winr.2\",\n        \"ddp@1.0.14-winr.4\",\n        \"tracker@1.0.5-winr.4\",\n        \"application-configuration@1.0.5-winr.2\",\n        \"check@1.0.4-win.0\",\n        \"binary-heap@1.0.3-winr.2\",\n        \"?insecure@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?disable-oplog@1.0.3-winr.2\",\n        \"?webapp@1.1.6-winr.4\",\n        \"?facts@1.0.4-winr.2\",\n        \"callback-hook@1.0.3-winr.2\"\n      ],\n      \"mongo 1.0.12-winr.3\": [\n        \"meteor@1.1.5-winr.4\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.2\",\n        \"logging@1.0.6-winr.2\",\n        \"ddp@1.0.14-winr.4\",\n        \"tracker@1.0.5-winr.4\",\n        \"application-configuration@1.0.5-winr.2\",\n        \"check@1.0.4-win.0\",\n        \"binary-heap@1.0.3-winr.2\",\n        \"?insecure@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?disable-oplog@1.0.3-winr.2\",\n        \"?webapp@1.1.6-winr.5\",\n        \"?facts@1.0.4-winr.2\",\n        \"callback-hook@1.0.3-winr.2\"\n      ],\n      \"mongo 1.0.12-winr.4\": [\n        \"meteor@1.1.5-winr.5\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.3\",\n        \"logging@1.0.6-winr.2\",\n        \"ddp@1.0.14-winr.5\",\n        \"tracker@1.0.5-winr.4\",\n        \"check@1.0.4-win.0\",\n        \"binary-heap@1.0.3-winr.2\",\n        \"?insecure@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?disable-oplog@1.0.3-winr.2\",\n        \"?webapp@1.1.6-winr.6\",\n        \"?facts@1.0.4-winr.3\",\n        \"callback-hook@1.0.3-winr.2\"\n      ],\n      \"mongo 1.0.12-winr.5\": [\n        \"meteor@1.1.5-winr.6\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.3\",\n        \"logging@1.0.6-winr.3\",\n        \"ddp@1.0.15-winr.5\",\n        \"tracker@1.0.5-winr.4\",\n        \"check@1.0.4-win.0\",\n        \"binary-heap@1.0.3-winr.2\",\n        \"?insecure@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?disable-oplog@1.0.3-winr.2\",\n        \"?webapp@1.1.7-winr.6\",\n        \"?facts@1.0.4-winr.3\",\n        \"callback-hook@1.0.3-winr.2\"\n      ],\n      \"mongo 1.0.12-winr.6\": [\n        \"meteor@1.1.5-winr.6\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.3\",\n        \"logging@1.0.7-winr.3\",\n        \"ddp@1.0.15-winr.6\",\n        \"tracker@1.0.6-winr.4\",\n        \"check@1.0.5-win.0\",\n        \"binary-heap@1.0.3-winr.2\",\n        \"?insecure@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?disable-oplog@1.0.3-winr.2\",\n        \"?webapp@1.1.7-winr.6\",\n        \"?facts@1.0.4-winr.4\",\n        \"callback-hook@1.0.3-winr.2\"\n      ],\n      \"mongo 1.0.12-winr.7\": [\n        \"meteor@1.1.5-winr.6\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.4\",\n        \"logging@1.0.7-winr.3\",\n        \"ddp@1.0.15-winr.6\",\n        \"tracker@1.0.6-winr.4\",\n        \"check@1.0.5-win.0\",\n        \"binary-heap@1.0.3-winr.2\",\n        \"?insecure@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?disable-oplog@1.0.3-winr.2\",\n        \"?webapp@1.1.7-winr.6\",\n        \"?facts@1.0.4-winr.4\",\n        \"callback-hook@1.0.3-winr.2\"\n      ],\n      \"mongo 1.1.0-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"ejson@1.0.6-rc.0\",\n        \"json@1.0.3-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"minimongo@1.0.7-rc.0\",\n        \"logging@1.0.7-rc.0\",\n        \"ddp@1.1.0-rc.0\",\n        \"tracker@1.0.6-rc.0\",\n        \"check@1.0.5-rc.0\",\n        \"binary-heap@1.0.3-rc.0\",\n        \"?insecure@1.0.3-rc.0\",\n        \"?autopublish@1.0.3-rc.0\",\n        \"?disable-oplog@1.0.3-rc.0\",\n        \"?webapp@1.2.0-rc.0\",\n        \"?facts@1.0.4-rc.0\",\n        \"callback-hook@1.0.3-rc.0\"\n      ],\n      \"mongo-livedata 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"mongo@10.0.0-glasser.isopacket.0\"\n      ],\n      \"mongo-livedata 1.0.0\": [\n        \"meteor\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"minimongo\",\n        \"logging\",\n        \"livedata\",\n        \"deps\",\n        \"application-configuration\",\n        \"check\",\n        \"binary-heap\",\n        \"?insecure\",\n        \"?autopublish\",\n        \"?disable-oplog\",\n        \"?webapp\",\n        \"?facts\",\n        \"callback-hook\"\n      ],\n      \"mongo-livedata 1.0.1\": [\n        \"meteor\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"minimongo\",\n        \"logging\",\n        \"livedata\",\n        \"deps\",\n        \"application-configuration\",\n        \"check\",\n        \"binary-heap\",\n        \"?insecure\",\n        \"?autopublish\",\n        \"?disable-oplog\",\n        \"?webapp\",\n        \"?facts\",\n        \"callback-hook\"\n      ],\n      \"mongo-livedata 1.0.2\": [\n        \"meteor\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"minimongo\",\n        \"logging\",\n        \"livedata\",\n        \"deps\",\n        \"application-configuration\",\n        \"check\",\n        \"binary-heap\",\n        \"?insecure\",\n        \"?autopublish\",\n        \"?disable-oplog\",\n        \"?webapp\",\n        \"?facts\",\n        \"callback-hook\"\n      ],\n      \"mongo-livedata 1.0.3-cordova4\": [\n        \"meteor\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"minimongo\",\n        \"logging\",\n        \"livedata\",\n        \"deps\",\n        \"application-configuration\",\n        \"check\",\n        \"binary-heap\",\n        \"?insecure\",\n        \"?autopublish\",\n        \"?disable-oplog\",\n        \"?webapp\",\n        \"?facts\",\n        \"callback-hook\"\n      ],\n      \"mongo-livedata 1.0.3\": [\n        \"application-configuration@1.0.0\",\n        \"?autopublish@1.0.0\",\n        \"binary-heap@1.0.0\",\n        \"callback-hook@1.0.0\",\n        \"check@1.0.0\",\n        \"deps@1.0.1\",\n        \"?disable-oplog@1.0.0\",\n        \"ejson@1.0.0\",\n        \"?facts@1.0.0\",\n        \"?insecure@1.0.0\",\n        \"json@1.0.0\",\n        \"livedata@1.0.7\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.2\",\n        \"minimongo@1.0.1\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\",\n        \"?webapp@1.0.2\"\n      ],\n      \"mongo-livedata 1.0.4-rc0\": [\n        \"meteor\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"minimongo\",\n        \"logging\",\n        \"livedata\",\n        \"tracker\",\n        \"application-configuration\",\n        \"check\",\n        \"binary-heap\",\n        \"?insecure\",\n        \"?autopublish\",\n        \"?disable-oplog\",\n        \"?webapp\",\n        \"?facts\",\n        \"callback-hook\"\n      ],\n      \"mongo-livedata 1.0.4-rc1\": [\n        \"meteor\",\n        \"mongo\"\n      ],\n      \"mongo-livedata 1.0.4\": [\n        \"meteor@1.0.3\",\n        \"mongo@1.0.4\"\n      ],\n      \"mongo-livedata 1.0.5-rc0\": [\n        \"meteor\",\n        \"mongo\"\n      ],\n      \"mongo-livedata 1.0.5\": [\n        \"meteor@1.1.1\",\n        \"mongo@1.0.6\"\n      ],\n      \"mongo-livedata 1.0.6-pre.0\": [\n        \"meteor\",\n        \"mongo\"\n      ],\n      \"mongo-livedata 1.0.6-pre.1\": [\n        \"meteor\",\n        \"mongo\"\n      ],\n      \"mongo-livedata 1.0.6-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"mongo@1.0.7-pre.2\"\n      ],\n      \"mongo-livedata 1.0.6-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"mongo@1.0.7-rc.0\"\n      ],\n      \"mongo-livedata 1.0.6-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"mongo@1.0.8-win.0\"\n      ],\n      \"mongo-livedata 1.0.6\": [\n        \"meteor@1.1.2\",\n        \"mongo@1.0.7\"\n      ],\n      \"mongo-livedata 1.0.7-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"mongo@1.0.9-ipc.0\"\n      ],\n      \"mongo-livedata 1.0.7-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"mongo@1.0.10-rc.1\"\n      ],\n      \"mongo-livedata 1.0.7-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"mongo@1.0.10-slava.0\"\n      ],\n      \"mongo-livedata 1.0.7-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"mongo@1.0.9-win.0\"\n      ],\n      \"mongo-livedata 1.0.7-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"mongo@1.0.10-winr.0\"\n      ],\n      \"mongo-livedata 1.0.7\": [\n        \"meteor@1.1.4\",\n        \"mongo@1.0.10\"\n      ],\n      \"mongo-livedata 1.0.8-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"mongo@1.0.12-eachin.0\"\n      ],\n      \"mongo-livedata 1.0.8-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"mongo@1.0.12-eachin.45\"\n      ],\n      \"mongo-livedata 1.0.8-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"mongo@1.0.12-githubble.0\"\n      ],\n      \"mongo-livedata 1.0.8-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"mongo@1.0.12-githubble.2\"\n      ],\n      \"mongo-livedata 1.0.8-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"mongo@1.0.12-githubble.42\"\n      ],\n      \"mongo-livedata 1.0.8-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"mongo@1.0.12-githubble.43\"\n      ],\n      \"mongo-livedata 1.0.8-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"mongo@1.1.0-rc.0\"\n      ],\n      \"mongo-livedata 1.0.8-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"mongo@1.0.11-winr.0\"\n      ],\n      \"mongo-livedata 1.0.8-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"mongo@1.0.11-winr.1\"\n      ],\n      \"mongo-livedata 1.0.8-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"mongo@1.0.12-winr.2\"\n      ],\n      \"mobile-status-bar 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"mobile-status-bar 1.0.0-cordova1\": [\n        \"meteor\"\n      ],\n      \"mobile-status-bar 1.0.0-cordova2\": [\n        \"meteor\"\n      ],\n      \"mobile-status-bar 1.0.0-cordova3\": [\n        \"meteor@1.1.0\"\n      ],\n      \"mobile-status-bar 1.0.0\": [\n        \"meteor@1.1.0\"\n      ],\n      \"mobile-status-bar 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"mobile-status-bar 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"mobile-status-bar 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"mobile-status-bar 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"mobile-status-bar 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"mobile-status-bar 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"mobile-status-bar 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"mobile-status-bar 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"mobile-status-bar 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"mobile-status-bar 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"mobile-status-bar 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"mobile-status-bar 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"mobile-status-bar 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"mobile-status-bar 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"mobile-status-bar 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"mobile-status-bar 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"mobile-status-bar 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"mobile-status-bar 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"mobile-status-bar 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"mobile-status-bar 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"mobile-status-bar 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"mobile-status-bar 1.0.3-winr.3\": [\n        \"meteor@1.1.5-winr.6\"\n      ],\n      \"minimongo 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"json@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\",\n        \"id-map@10.0.0-glasser.isopacket.0\",\n        \"ordered-dict@10.0.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"geojson-utils@10.0.0-glasser.isopacket.0\"\n      ],\n      \"minimongo 1.0.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\",\n        \"id-map\",\n        \"ordered-dict\",\n        \"deps\",\n        \"random\",\n        \"geojson-utils\"\n      ],\n      \"minimongo 1.0.1-cordova1\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\",\n        \"id-map\",\n        \"ordered-dict\",\n        \"deps\",\n        \"random\",\n        \"geojson-utils\"\n      ],\n      \"minimongo 1.0.1\": [\n        \"deps@1.0.1\",\n        \"ejson@1.0.0\",\n        \"geojson-utils@1.0.0\",\n        \"id-map@1.0.0\",\n        \"json@1.0.0\",\n        \"meteor@1.0.2\",\n        \"ordered-dict@1.0.0\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"minimongo 1.0.2-glasser1\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\",\n        \"id-map\",\n        \"ordered-dict\",\n        \"tracker\",\n        \"random\",\n        \"geojson-utils\"\n      ],\n      \"minimongo 1.0.2-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\",\n        \"id-map\",\n        \"ordered-dict\",\n        \"tracker\",\n        \"random\",\n        \"geojson-utils\"\n      ],\n      \"minimongo 1.0.2-rc1\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\",\n        \"id-map\",\n        \"ordered-dict\",\n        \"tracker\",\n        \"random\",\n        \"geojson-utils\"\n      ],\n      \"minimongo 1.0.2-rc2\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\",\n        \"id-map\",\n        \"ordered-dict\",\n        \"tracker\",\n        \"random\",\n        \"geojson-utils\"\n      ],\n      \"minimongo 1.0.2\": [\n        \"ejson@1.0.1\",\n        \"geojson-utils@1.0.0\",\n        \"id-map@1.0.0\",\n        \"json@1.0.0\",\n        \"meteor@1.0.3\",\n        \"ordered-dict@1.0.0\",\n        \"random@1.0.0\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"minimongo 1.0.3-ekate\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\",\n        \"id-map\",\n        \"ordered-dict\",\n        \"tracker\",\n        \"random\",\n        \"geojson-utils\"\n      ],\n      \"minimongo 1.0.3-rc1\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\",\n        \"id-map\",\n        \"ordered-dict\",\n        \"tracker\",\n        \"random\",\n        \"geojson-utils\"\n      ],\n      \"minimongo 1.0.3\": [\n        \"ejson@1.0.2\",\n        \"geojson-utils@1.0.0\",\n        \"id-map@1.0.0\",\n        \"json@1.0.0\",\n        \"meteor@1.1.0\",\n        \"ordered-dict@1.0.0\",\n        \"random@1.0.0\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"minimongo 1.0.4-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\",\n        \"id-map\",\n        \"ordered-dict\",\n        \"tracker\",\n        \"random\",\n        \"geojson-utils\"\n      ],\n      \"minimongo 1.0.4-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\",\n        \"id-map\",\n        \"ordered-dict\",\n        \"tracker\",\n        \"random\",\n        \"geojson-utils\"\n      ],\n      \"minimongo 1.0.4-pre.2\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\",\n        \"id-map\",\n        \"ordered-dict\",\n        \"tracker\",\n        \"random\",\n        \"geojson-utils\"\n      ],\n      \"minimongo 1.0.4-pre.3\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"json@1.0.1-pre.2\",\n        \"ejson@1.0.4-pre.2\",\n        \"id-map@1.0.1-pre.2\",\n        \"ordered-dict@1.0.1-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"geojson-utils@1.0.1-pre.2\"\n      ],\n      \"minimongo 1.0.4-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"json@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"id-map@1.0.1-rc.0\",\n        \"ordered-dict@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"geojson-utils@1.0.1-rc.0\"\n      ],\n      \"minimongo 1.0.4-refreshpolicy.1\": [\n        \"meteor@1.1.2-refreshpolicy.1\",\n        \"underscore@1.0.1\",\n        \"json@1.0.1\",\n        \"ejson@1.0.4\",\n        \"id-map@1.0.1\",\n        \"ordered-dict@1.0.1\",\n        \"tracker@1.0.3\",\n        \"random@1.0.1\",\n        \"geojson-utils@1.0.1\"\n      ],\n      \"minimongo 1.0.4\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"json@1.0.1\",\n        \"ejson@1.0.4\",\n        \"id-map@1.0.1\",\n        \"ordered-dict@1.0.1\",\n        \"tracker@1.0.3\",\n        \"random@1.0.1\",\n        \"geojson-utils@1.0.1\"\n      ],\n      \"minimongo 1.0.5-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\",\n        \"json@1.0.1\",\n        \"ejson@1.0.4\",\n        \"id-map@1.0.1\",\n        \"ordered-dict@1.0.1\",\n        \"tracker@1.0.3\",\n        \"random@1.0.1\",\n        \"geojson-utils@1.0.1\"\n      ],\n      \"minimongo 1.0.5-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"json@1.0.1-win.0\",\n        \"ejson@1.0.4-win.0\",\n        \"id-map@1.0.1-win.0\",\n        \"ordered-dict@1.0.1-win.0\",\n        \"tracker@1.0.3-win.0\",\n        \"random@1.0.1-win.0\",\n        \"geojson-utils@1.0.1-win.0\"\n      ],\n      \"minimongo 1.0.5\": [\n        \"meteor@1.1.3\",\n        \"underscore@1.0.1\",\n        \"json@1.0.1\",\n        \"ejson@1.0.4\",\n        \"id-map@1.0.1\",\n        \"ordered-dict@1.0.1\",\n        \"tracker@1.0.3\",\n        \"random@1.0.1\",\n        \"geojson-utils@1.0.1\"\n      ],\n      \"minimongo 1.0.6-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"json@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"id-map@1.0.2-ipc.0\",\n        \"ordered-dict@1.0.2-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"geojson-utils@1.0.2-ipc.0\"\n      ],\n      \"minimongo 1.0.6-ipc.1\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"json@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"id-map@1.0.2-ipc.0\",\n        \"ordered-dict@1.0.2-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"geojson-utils@1.0.2-ipc.0\"\n      ],\n      \"minimongo 1.0.6-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"json@1.0.2-rc.1\",\n        \"ejson@1.0.5-rc.1\",\n        \"id-map@1.0.2-rc.1\",\n        \"ordered-dict@1.0.2-rc.1\",\n        \"tracker@1.0.4-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"geojson-utils@1.0.2-rc.1\"\n      ],\n      \"minimongo 1.0.6-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"json@1.0.2-slava.0\",\n        \"ejson@1.0.5-slava.0\",\n        \"id-map@1.0.2-slava.0\",\n        \"ordered-dict@1.0.2-slava.0\",\n        \"tracker@1.0.4-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"geojson-utils@1.0.2-slava.0\"\n      ],\n      \"minimongo 1.0.6-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"json@1.0.2-win.0\",\n        \"ejson@1.0.5-win.0\",\n        \"id-map@1.0.2-win.0\",\n        \"ordered-dict@1.0.2-win.0\",\n        \"tracker@1.0.4-win.0\",\n        \"random@1.0.2-win.0\",\n        \"geojson-utils@1.0.2-win.0\"\n      ],\n      \"minimongo 1.0.6-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"json@1.0.2-winr.0\",\n        \"ejson@1.0.5-winr.0\",\n        \"id-map@1.0.2-winr.0\",\n        \"ordered-dict@1.0.2-winr.0\",\n        \"tracker@1.0.4-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"geojson-utils@1.0.2-winr.0\"\n      ],\n      \"minimongo 1.0.6\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"json@1.0.2\",\n        \"ejson@1.0.5\",\n        \"id-map@1.0.2\",\n        \"ordered-dict@1.0.2\",\n        \"tracker@1.0.4\",\n        \"random@1.0.2\",\n        \"geojson-utils@1.0.2\"\n      ],\n      \"minimongo 1.0.7-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"json@1.0.3-eachin.0\",\n        \"ejson@1.0.6-eachin.0\",\n        \"id-map@1.0.3-eachin.0\",\n        \"ordered-dict@1.0.3-eachin.0\",\n        \"tracker@1.0.5-eachin.0\",\n        \"random@1.0.3-eachin.0\",\n        \"geojson-utils@1.0.3-eachin.0\"\n      ],\n      \"minimongo 1.0.7-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"json@1.0.3-eachin.43\",\n        \"ejson@1.0.6-eachin.43\",\n        \"id-map@1.0.3-eachin.43\",\n        \"ordered-dict@1.0.3-eachin.43\",\n        \"tracker@1.0.5-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"geojson-utils@1.0.3-eachin.43\"\n      ],\n      \"minimongo 1.0.7-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"json@1.0.3-githubble.0\",\n        \"ejson@1.0.6-githubble.0\",\n        \"id-map@1.0.3-githubble.0\",\n        \"ordered-dict@1.0.3-githubble.0\",\n        \"tracker@1.0.5-githubble.0\",\n        \"random@1.0.3-githubble.0\",\n        \"geojson-utils@1.0.3-githubble.0\"\n      ],\n      \"minimongo 1.0.7-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"json@1.0.3-githubble.2\",\n        \"ejson@1.0.6-githubble.2\",\n        \"id-map@1.0.3-githubble.2\",\n        \"ordered-dict@1.0.3-githubble.2\",\n        \"tracker@1.0.5-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"geojson-utils@1.0.3-githubble.2\"\n      ],\n      \"minimongo 1.0.7-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"json@1.0.3-githubble.42\",\n        \"ejson@1.0.6-githubble.42\",\n        \"id-map@1.0.3-githubble.42\",\n        \"ordered-dict@1.0.3-githubble.42\",\n        \"tracker@1.0.5-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"geojson-utils@1.0.3-githubble.42\"\n      ],\n      \"minimongo 1.0.7-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"json@1.0.3-githubble.43\",\n        \"ejson@1.0.6-githubble.43\",\n        \"id-map@1.0.3-githubble.43\",\n        \"ordered-dict@1.0.3-githubble.43\",\n        \"tracker@1.0.5-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"geojson-utils@1.0.3-githubble.43\"\n      ],\n      \"minimongo 1.0.7-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"json@1.0.3-rc.0\",\n        \"ejson@1.0.6-rc.0\",\n        \"id-map@1.0.3-rc.0\",\n        \"ordered-dict@1.0.3-rc.0\",\n        \"tracker@1.0.6-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"geojson-utils@1.0.3-rc.0\"\n      ],\n      \"minimongo 1.0.7-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"json@1.0.3-winr.0\",\n        \"ejson@1.0.6-winr.0\",\n        \"id-map@1.0.3-winr.0\",\n        \"ordered-dict@1.0.3-winr.0\",\n        \"tracker@1.0.5-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"geojson-utils@1.0.3-winr.0\"\n      ],\n      \"minimongo 1.0.7-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"json@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\",\n        \"id-map@1.0.3-winr.1\",\n        \"ordered-dict@1.0.3-winr.1\",\n        \"tracker@1.0.5-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"geojson-utils@1.0.3-winr.1\"\n      ],\n      \"minimongo 1.0.7-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"id-map@1.0.3-winr.2\",\n        \"ordered-dict@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"random@1.0.3-winr.2\",\n        \"geojson-utils@1.0.3-winr.2\"\n      ],\n      \"minimongo 1.0.7-winr.3\": [\n        \"meteor@1.1.5-winr.5\",\n        \"underscore@1.0.3-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"id-map@1.0.3-winr.2\",\n        \"ordered-dict@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"random@1.0.3-winr.2\",\n        \"geojson-utils@1.0.3-winr.2\"\n      ],\n      \"minimongo 1.0.7-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"id-map@1.0.3-winr.2\",\n        \"ordered-dict@1.0.3-winr.2\",\n        \"tracker@1.0.6-winr.4\",\n        \"random@1.0.3-winr.2\",\n        \"geojson-utils@1.0.3-winr.2\"\n      ],\n      \"minifiers 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\"\n      ],\n      \"minifiers 1.0.0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"minifiers 1.0.1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"minifiers 1.0.2-glasser1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"minifiers 1.0.2\": [\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"minifiers 1.0.3-ekate\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"minifiers 1.1.0-rc0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"minifiers 1.1.0\": [\n        \"meteor@1.1.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"minifiers 1.1.1-pre.0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"minifiers 1.1.1-pre.1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"minifiers 1.1.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\"\n      ],\n      \"minifiers 1.1.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"minifiers 1.1.1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\"\n      ],\n      \"minifiers 1.1.1_1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\"\n      ],\n      \"minifiers 1.1.2-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\"\n      ],\n      \"minifiers 1.1.2-rc.1\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\"\n      ],\n      \"minifiers 1.1.2-rc.2\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\"\n      ],\n      \"minifiers 1.1.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\"\n      ],\n      \"minifiers 1.1.2\": [\n        \"meteor@1.1.3\",\n        \"underscore@1.0.1\"\n      ],\n      \"minifiers 1.1.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\"\n      ],\n      \"minifiers 1.1.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\"\n      ],\n      \"minifiers 1.1.3-rc.2\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\"\n      ],\n      \"minifiers 1.1.3-rc.3\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\"\n      ],\n      \"minifiers 1.1.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\"\n      ],\n      \"minifiers 1.1.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\"\n      ],\n      \"minifiers 1.1.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\"\n      ],\n      \"minifiers 1.1.3-winr.1\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\"\n      ],\n      \"minifiers 1.1.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\"\n      ],\n      \"minifiers 1.1.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\"\n      ],\n      \"minifiers 1.1.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\"\n      ],\n      \"minifiers 1.1.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\"\n      ],\n      \"minifiers 1.1.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\"\n      ],\n      \"minifiers 1.1.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\"\n      ],\n      \"minifiers 1.1.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"minifiers 1.1.4-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"underscore@1.0.2\"\n      ],\n      \"minifiers 1.1.4-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"underscore@1.0.2\"\n      ],\n      \"minifiers 1.1.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\"\n      ],\n      \"minifiers 1.1.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\"\n      ],\n      \"minifiers 1.1.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"minifiers 1.1.4-winr.3\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"minifiers 1.1.4-winr.4\": [\n        \"meteor@1.1.5-winr.5\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"minifiers 1.1.5-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"meyerweb-reset 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"meyerweb-reset 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"meyerweb-reset 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"meyerweb-reset 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"meyerweb-reset 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"meyerweb-reset 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"meyerweb-reset 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"meyerweb-reset 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"meyerweb-reset 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"meyerweb-reset 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"meyerweb-reset 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"meyerweb-reset 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"meyerweb-reset 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"meyerweb-reset 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"meyerweb-reset 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"meyerweb-reset 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"meyerweb-reset 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"meyerweb-reset 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"meyerweb-reset 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"meyerweb-reset 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"meyerweb-reset 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"meyerweb-reset 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"meyerweb-reset 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"meteor 1.0.0\": [\n        \"underscore\"\n      ],\n      \"meteor 1.0.1\": [\n        \"underscore\"\n      ],\n      \"meteor 1.0.2-cordova1\": [\n        \"underscore\"\n      ],\n      \"meteor 1.0.2-cordova4\": [\n        \"underscore\"\n      ],\n      \"meteor 1.0.2\": [\n        \"underscore@1.0.0\"\n      ],\n      \"meteor 1.0.3-rc0\": [\n        \"underscore\"\n      ],\n      \"meteor 1.0.3-rc1\": [\n        \"underscore\"\n      ],\n      \"meteor 1.0.3\": [\n        \"underscore@1.0.0\"\n      ],\n      \"meteor 1.0.4-cordova6\": [\n        \"underscore\"\n      ],\n      \"meteor 1.0.5-ekate\": [\n        \"underscore\"\n      ],\n      \"meteor 1.1.0-rc0\": [\n        \"underscore\"\n      ],\n      \"meteor 1.1.0-rc1\": [\n        \"underscore\"\n      ],\n      \"meteor 1.1.0-rc2\": [\n        \"underscore\"\n      ],\n      \"meteor 1.1.0\": [\n        \"underscore@1.0.0\"\n      ],\n      \"meteor 1.1.1-rc.1\": [\n        \"underscore\"\n      ],\n      \"meteor 1.1.1-rc0\": [\n        \"underscore\"\n      ],\n      \"meteor 1.1.1\": [\n        \"underscore@1.0.0\"\n      ],\n      \"meteor 1.1.2-ekate.1\": [\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"meteor 1.1.2-nim.0\": [\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"meteor 1.1.2-pre.0\": [\n        \"underscore\"\n      ],\n      \"meteor 1.1.2-pre.1\": [\n        \"underscore\"\n      ],\n      \"meteor 1.1.2-pre.2\": [\n        \"underscore@1.0.1-pre.2\"\n      ],\n      \"meteor 1.1.2-pre.3\": [\n        \"underscore@1.0.1-pre.2\"\n      ],\n      \"meteor 1.1.2-rc.0\": [\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"meteor 1.1.2-rc.1\": [\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"meteor 1.1.2-rc.2\": [\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"meteor 1.1.2-rc.3\": [\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"meteor 1.1.2-refreshpolicy.1\": [\n        \"underscore@1.0.1\"\n      ],\n      \"meteor 1.1.2\": [\n        \"underscore@1.0.1\"\n      ],\n      \"meteor 1.1.3-rc.0\": [\n        \"underscore@1.0.1\"\n      ],\n      \"meteor 1.1.3-win.0\": [\n        \"underscore@1.0.1-win.0\"\n      ],\n      \"meteor 1.1.3\": [\n        \"underscore@1.0.1\"\n      ],\n      \"meteor 1.1.4-ipc.0\": [\n        \"underscore@1.0.2-ipc.0\"\n      ],\n      \"meteor 1.1.4-rc.1\": [\n        \"underscore@1.0.2-rc.1\"\n      ],\n      \"meteor 1.1.4-slava.0\": [\n        \"underscore@1.0.2-slava.0\"\n      ],\n      \"meteor 1.1.4-win.0\": [\n        \"underscore@1.0.2-win.0\"\n      ],\n      \"meteor 1.1.4-winr.0\": [\n        \"underscore@1.0.2-winr.0\"\n      ],\n      \"meteor 1.1.4\": [\n        \"underscore@1.0.2\"\n      ],\n      \"meteor 1.1.5-blz.0\": [\n        \"underscore@1.0.2\"\n      ],\n      \"meteor 1.1.5-eachin.0\": [\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"meteor 1.1.5-eachin.43\": [\n        \"underscore@1.0.3-eachin.43\"\n      ],\n      \"meteor 1.1.5-githubble.0\": [\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"meteor 1.1.5-githubble.2\": [\n        \"underscore@1.0.3-githubble.2\"\n      ],\n      \"meteor 1.1.5-githubble.42\": [\n        \"underscore@1.0.3-githubble.42\"\n      ],\n      \"meteor 1.1.5-githubble.43\": [\n        \"underscore@1.0.3-githubble.43\"\n      ],\n      \"meteor 1.1.5-oplog-backlog.0\": [\n        \"underscore@1.0.2\"\n      ],\n      \"meteor 1.1.5-rc.0\": [\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"meteor 1.1.5-vs.1\": [\n        \"underscore@1.0.2\"\n      ],\n      \"meteor 1.1.5-vs.2\": [\n        \"underscore@1.0.2\"\n      ],\n      \"meteor 1.1.5-winr.0\": [\n        \"underscore@1.0.3-winr.0\"\n      ],\n      \"meteor 1.1.5-winr.1\": [\n        \"underscore@1.0.3-winr.1\"\n      ],\n      \"meteor 1.1.5-winr.2\": [\n        \"underscore@1.0.2\"\n      ],\n      \"meteor 1.1.5-winr.3\": [\n        \"underscore@1.0.2\"\n      ],\n      \"meteor 1.1.5-winr.4\": [\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"meteor 1.1.5-winr.5\": [\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"meteor 1.1.5-winr.6\": [\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"meteor 1.5.0-glasser.isopacket.0\": [\n        \"underscore@10.0.0-glasser.isopacket.0\"\n      ],\n      \"meteor-developer 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"oauth2@10.0.0-glasser.isopacket.0\",\n        \"oauth@10.0.0-glasser.isopacket.0\",\n        \"http@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"service-configuration@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"templating@10.0.0-glasser.isopacket.0\"\n      ],\n      \"meteor-developer 1.0.0\": [\n        \"http@1.0.2\",\n        \"meteor@1.0.2\",\n        \"oauth@1.0.0\",\n        \"oauth2@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.0\",\n        \"templating@1.0.4\",\n        \"underscore@1.0.0\"\n      ],\n      \"meteor-developer 1.0.1-glasser1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"meteor-developer 1.0.1-rc0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"meteor-developer 1.0.1\": [\n        \"http@1.0.4\",\n        \"meteor@1.0.3\",\n        \"oauth@1.0.1\",\n        \"oauth2@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.5\",\n        \"underscore@1.0.0\"\n      ],\n      \"meteor-developer 1.0.2-ekate\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"meteor-developer 1.1.0-rc0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"meteor-developer 1.1.0\": [\n        \"http@1.0.5\",\n        \"meteor@1.1.0\",\n        \"oauth@1.1.0\",\n        \"oauth2@1.1.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.6\",\n        \"underscore@1.0.0\"\n      ],\n      \"meteor-developer 1.1.1-pre.0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"meteor-developer 1.1.1-pre.1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"meteor-developer 1.1.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"oauth2@1.1.1-pre.2\",\n        \"oauth@1.1.1-pre.2\",\n        \"http@1.0.7-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"service-configuration@1.0.2-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"templating@1.0.8-pre.2\"\n      ],\n      \"meteor-developer 1.1.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"oauth2@1.1.1-rc.0\",\n        \"oauth@1.1.1-rc.0\",\n        \"http@1.0.7-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"templating@1.0.8-rc.0\"\n      ],\n      \"meteor-developer 1.1.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"oauth2@1.1.1-win.0\",\n        \"oauth@1.1.2-win.0\",\n        \"http@1.0.8-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"service-configuration@1.0.2-win.0\",\n        \"random@1.0.1-win.0\",\n        \"templating@1.0.9-win.0\"\n      ],\n      \"meteor-developer 1.1.1\": [\n        \"meteor@1.1.2\",\n        \"oauth2@1.1.1\",\n        \"oauth@1.1.1\",\n        \"http@1.0.7\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"random@1.0.1\",\n        \"templating@1.0.8\"\n      ],\n      \"meteor-developer 1.1.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"oauth2@1.1.2-ipc.0\",\n        \"oauth@1.1.3-ipc.0\",\n        \"http@1.0.9-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"service-configuration@1.0.3-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"templating@1.0.10-ipc.0\"\n      ],\n      \"meteor-developer 1.1.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"oauth2@1.1.2-rc.1\",\n        \"oauth@1.1.3-rc.1\",\n        \"http@1.0.9-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"service-configuration@1.0.3-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"templating@1.0.10-rc.1\"\n      ],\n      \"meteor-developer 1.1.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"oauth2@1.1.2-slava.0\",\n        \"oauth@1.1.3-slava.0\",\n        \"http@1.0.9-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"service-configuration@1.0.3-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"templating@1.0.10-slava.0\"\n      ],\n      \"meteor-developer 1.1.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"oauth2@1.1.2-win.0\",\n        \"oauth@1.1.3-win.0\",\n        \"http@1.0.9-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"service-configuration@1.0.3-win.0\",\n        \"random@1.0.2-win.0\",\n        \"templating@1.0.10-win.0\"\n      ],\n      \"meteor-developer 1.1.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"oauth2@1.1.2-winr.0\",\n        \"oauth@1.1.3-winr.0\",\n        \"http@1.0.9-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"service-configuration@1.0.3-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"templating@1.0.10-winr.0\"\n      ],\n      \"meteor-developer 1.1.2\": [\n        \"meteor@1.1.4\",\n        \"oauth2@1.1.2\",\n        \"oauth@1.1.3\",\n        \"http@1.0.9\",\n        \"underscore@1.0.2\",\n        \"service-configuration@1.0.3\",\n        \"random@1.0.2\",\n        \"templating@1.0.10\"\n      ],\n      \"meteor-developer 1.1.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"oauth2@1.1.3-eachin.43\",\n        \"oauth@1.1.4-eachin.43\",\n        \"http@1.0.10-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"service-configuration@1.0.4-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"templating@1.0.12-eachin.43\"\n      ],\n      \"meteor-developer 1.1.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"oauth2@1.1.3-githubble.0\",\n        \"oauth@1.1.4-githubble.0\",\n        \"http@1.0.10-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"service-configuration@1.0.4-githubble.0\",\n        \"random@1.0.3-githubble.0\",\n        \"templating@1.0.12-githubble.0\"\n      ],\n      \"meteor-developer 1.1.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"oauth2@1.1.3-githubble.2\",\n        \"oauth@1.1.4-githubble.2\",\n        \"http@1.0.10-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"service-configuration@1.0.4-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"templating@1.0.12-githubble.2\"\n      ],\n      \"meteor-developer 1.1.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"oauth2@1.1.3-githubble.42\",\n        \"oauth@1.1.4-githubble.42\",\n        \"http@1.0.10-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"service-configuration@1.0.4-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"templating@1.0.12-githubble.42\"\n      ],\n      \"meteor-developer 1.1.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"oauth2@1.1.3-githubble.43\",\n        \"oauth@1.1.4-githubble.43\",\n        \"http@1.0.10-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"service-configuration@1.0.4-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"templating@1.0.12-githubble.43\"\n      ],\n      \"meteor-developer 1.1.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"oauth2@1.1.3-rc.0\",\n        \"oauth@1.1.4-rc.0\",\n        \"http@1.1.0-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"service-configuration@1.0.4-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"templating@1.1.0-rc.0\"\n      ],\n      \"meteor-developer 1.1.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"oauth2@1.1.3-winr.0\",\n        \"oauth@1.1.4-winr.0\",\n        \"http@1.0.10-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"service-configuration@1.0.4-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"templating@1.0.11-winr.0\"\n      ],\n      \"meteor-developer 1.1.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"oauth2@1.1.3-winr.1\",\n        \"oauth@1.1.4-winr.1\",\n        \"http@1.0.10-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"service-configuration@1.0.4-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"templating@1.0.11-winr.1\"\n      ],\n      \"meteor-developer 1.1.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"oauth2@1.1.3-winr.2\",\n        \"oauth@1.1.4-winr.2\",\n        \"http@1.0.10-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"templating@1.0.11-winr.4\"\n      ],\n      \"meteor-developer 1.1.3-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"oauth2@1.1.3-winr.2\",\n        \"oauth@1.1.4-winr.3\",\n        \"http@1.0.11-winr.5\",\n        \"underscore@1.0.3-winr.2\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"templating@1.0.12-winr.7\"\n      ],\n      \"meetup 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"oauth2@10.0.0-glasser.isopacket.0\",\n        \"oauth@10.0.0-glasser.isopacket.0\",\n        \"http@10.0.0-glasser.isopacket.0\",\n        \"service-configuration@10.0.0-glasser.isopacket.0\",\n        \"templating@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\"\n      ],\n      \"meetup 1.0.0-cordova1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"meetup 1.0.0-ekate\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"meetup 1.0.0-glasser1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"meetup 1.0.0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"meetup 1.0.1\": [\n        \"http@1.0.2\",\n        \"meteor@1.0.2\",\n        \"oauth@1.0.0\",\n        \"oauth2@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.0\",\n        \"templating@1.0.4\",\n        \"underscore@1.0.0\"\n      ],\n      \"meetup 1.0.2-glasser1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"meetup 1.0.2-rc0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"meetup 1.0.2\": [\n        \"http@1.0.4\",\n        \"meteor@1.0.3\",\n        \"oauth@1.0.1\",\n        \"oauth2@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.5\",\n        \"underscore@1.0.0\"\n      ],\n      \"meetup 1.0.3-ekate\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"meetup 1.1.0-rc0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"meetup 1.1.0\": [\n        \"http@1.0.5\",\n        \"meteor@1.1.0\",\n        \"oauth@1.1.0\",\n        \"oauth2@1.1.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.6\",\n        \"underscore@1.0.0\"\n      ],\n      \"meetup 1.1.1-pre.0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"meetup 1.1.1-pre.1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"meetup 1.1.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"oauth2@1.1.1-pre.2\",\n        \"oauth@1.1.1-pre.2\",\n        \"http@1.0.7-pre.2\",\n        \"service-configuration@1.0.2-pre.2\",\n        \"templating@1.0.8-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"random@1.0.1-pre.2\"\n      ],\n      \"meetup 1.1.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"oauth2@1.1.1-rc.0\",\n        \"oauth@1.1.1-rc.0\",\n        \"http@1.0.7-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"templating@1.0.8-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"random@1.0.1-rc.0\"\n      ],\n      \"meetup 1.1.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"oauth2@1.1.1-win.0\",\n        \"oauth@1.1.2-win.0\",\n        \"http@1.0.8-win.0\",\n        \"service-configuration@1.0.2-win.0\",\n        \"templating@1.0.9-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"random@1.0.1-win.0\"\n      ],\n      \"meetup 1.1.1\": [\n        \"meteor@1.1.2\",\n        \"oauth2@1.1.1\",\n        \"oauth@1.1.1\",\n        \"http@1.0.7\",\n        \"service-configuration@1.0.2\",\n        \"templating@1.0.8\",\n        \"underscore@1.0.1\",\n        \"random@1.0.1\"\n      ],\n      \"meetup 1.1.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"oauth2@1.1.2-ipc.0\",\n        \"oauth@1.1.3-ipc.0\",\n        \"http@1.0.9-ipc.0\",\n        \"service-configuration@1.0.3-ipc.0\",\n        \"templating@1.0.10-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"random@1.0.2-ipc.0\"\n      ],\n      \"meetup 1.1.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"oauth2@1.1.2-rc.1\",\n        \"oauth@1.1.3-rc.1\",\n        \"http@1.0.9-rc.1\",\n        \"service-configuration@1.0.3-rc.1\",\n        \"templating@1.0.10-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"random@1.0.2-rc.1\"\n      ],\n      \"meetup 1.1.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"oauth2@1.1.2-slava.0\",\n        \"oauth@1.1.3-slava.0\",\n        \"http@1.0.9-slava.0\",\n        \"service-configuration@1.0.3-slava.0\",\n        \"templating@1.0.10-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"random@1.0.2-slava.0\"\n      ],\n      \"meetup 1.1.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"oauth2@1.1.2-win.0\",\n        \"oauth@1.1.3-win.0\",\n        \"http@1.0.9-win.0\",\n        \"service-configuration@1.0.3-win.0\",\n        \"templating@1.0.10-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"random@1.0.2-win.0\"\n      ],\n      \"meetup 1.1.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"oauth2@1.1.2-winr.0\",\n        \"oauth@1.1.3-winr.0\",\n        \"http@1.0.9-winr.0\",\n        \"service-configuration@1.0.3-winr.0\",\n        \"templating@1.0.10-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"random@1.0.2-winr.0\"\n      ],\n      \"meetup 1.1.2\": [\n        \"meteor@1.1.4\",\n        \"oauth2@1.1.2\",\n        \"oauth@1.1.3\",\n        \"http@1.0.9\",\n        \"service-configuration@1.0.3\",\n        \"templating@1.0.10\",\n        \"underscore@1.0.2\",\n        \"random@1.0.2\"\n      ],\n      \"meetup 1.1.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"oauth2@1.1.3-eachin.43\",\n        \"oauth@1.1.4-eachin.43\",\n        \"http@1.0.10-eachin.43\",\n        \"service-configuration@1.0.4-eachin.43\",\n        \"templating@1.0.12-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"random@1.0.3-eachin.43\"\n      ],\n      \"meetup 1.1.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"oauth2@1.1.3-githubble.0\",\n        \"oauth@1.1.4-githubble.0\",\n        \"http@1.0.10-githubble.0\",\n        \"service-configuration@1.0.4-githubble.0\",\n        \"templating@1.0.12-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"random@1.0.3-githubble.0\"\n      ],\n      \"meetup 1.1.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"oauth2@1.1.3-githubble.2\",\n        \"oauth@1.1.4-githubble.2\",\n        \"http@1.0.10-githubble.2\",\n        \"service-configuration@1.0.4-githubble.2\",\n        \"templating@1.0.12-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"random@1.0.3-githubble.2\"\n      ],\n      \"meetup 1.1.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"oauth2@1.1.3-githubble.42\",\n        \"oauth@1.1.4-githubble.42\",\n        \"http@1.0.10-githubble.42\",\n        \"service-configuration@1.0.4-githubble.42\",\n        \"templating@1.0.12-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"random@1.0.3-githubble.42\"\n      ],\n      \"meetup 1.1.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"oauth2@1.1.3-githubble.43\",\n        \"oauth@1.1.4-githubble.43\",\n        \"http@1.0.10-githubble.43\",\n        \"service-configuration@1.0.4-githubble.43\",\n        \"templating@1.0.12-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"random@1.0.3-githubble.43\"\n      ],\n      \"meetup 1.1.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"oauth2@1.1.3-rc.0\",\n        \"oauth@1.1.4-rc.0\",\n        \"http@1.1.0-rc.0\",\n        \"service-configuration@1.0.4-rc.0\",\n        \"templating@1.1.0-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"random@1.0.3-rc.0\"\n      ],\n      \"meetup 1.1.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"oauth2@1.1.3-winr.0\",\n        \"oauth@1.1.4-winr.0\",\n        \"http@1.0.10-winr.0\",\n        \"service-configuration@1.0.4-winr.0\",\n        \"templating@1.0.11-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"random@1.0.3-winr.0\"\n      ],\n      \"meetup 1.1.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"oauth2@1.1.3-winr.1\",\n        \"oauth@1.1.4-winr.1\",\n        \"http@1.0.10-winr.1\",\n        \"service-configuration@1.0.4-winr.1\",\n        \"templating@1.0.11-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"random@1.0.3-winr.1\"\n      ],\n      \"meetup 1.1.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"oauth2@1.1.3-winr.2\",\n        \"oauth@1.1.4-winr.2\",\n        \"http@1.0.10-winr.4\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"templating@1.0.11-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"meetup 1.1.3-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"oauth2@1.1.3-winr.2\",\n        \"oauth@1.1.4-winr.3\",\n        \"http@1.0.11-winr.5\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"templating@1.0.12-winr.7\",\n        \"underscore@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"meetup 1.5.0-glasser1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"templating\",\n        \"underscore\",\n        \"random\"\n      ],\n      \"markdown 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"?templating@10.0.0-glasser.isopacket.0\"\n      ],\n      \"markdown 1.0.2-pre.0\": [\n        \"meteor\",\n        \"?templating\"\n      ],\n      \"markdown 1.0.2-pre.1\": [\n        \"meteor\",\n        \"?templating\"\n      ],\n      \"markdown 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"?templating@1.0.8-pre.2\"\n      ],\n      \"markdown 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"?templating@1.0.8-rc.0\"\n      ],\n      \"markdown 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"?templating@1.0.9-win.0\"\n      ],\n      \"markdown 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"?templating@1.0.8\"\n      ],\n      \"markdown 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"?templating@1.0.10-ipc.0\"\n      ],\n      \"markdown 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"?templating@1.0.10-rc.1\"\n      ],\n      \"markdown 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"?templating@1.0.10-slava.0\"\n      ],\n      \"markdown 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"?templating@1.0.10-win.0\"\n      ],\n      \"markdown 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"?templating@1.0.10-winr.0\"\n      ],\n      \"markdown 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"?templating@1.0.10\"\n      ],\n      \"markdown 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"?templating@1.0.12-eachin.43\"\n      ],\n      \"markdown 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"?templating@1.0.12-githubble.0\"\n      ],\n      \"markdown 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"?templating@1.0.12-githubble.2\"\n      ],\n      \"markdown 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"?templating@1.0.12-githubble.42\"\n      ],\n      \"markdown 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"?templating@1.0.12-githubble.43\"\n      ],\n      \"markdown 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"?templating@1.1.0-rc.0\"\n      ],\n      \"markdown 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"?templating@1.0.11-winr.0\"\n      ],\n      \"markdown 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"?templating@1.0.11-winr.1\"\n      ],\n      \"markdown 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"?templating@1.0.11-winr.4\"\n      ],\n      \"logic-solver 0.0.2-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"check@1.0.4\",\n        \"underscore@1.0.2\"\n      ],\n      \"logic-solver 0.0.2-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"check@1.0.4\",\n        \"underscore@1.0.2\"\n      ],\n      \"logic-solver 1.0.0-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"check@1.0.5-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"logging 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\"\n      ],\n      \"logging 1.0.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"logging 1.0.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"logging 1.0.2-cordova1\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"logging 1.0.2-cordova2\": [\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"logging 1.0.2\": [\n        \"ejson@1.0.0\",\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"logging 1.0.3-ekate\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"logging 1.0.3\": [\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"logging 1.0.4-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"logging 1.0.4-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"logging 1.0.4-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"ejson@1.0.4-pre.2\"\n      ],\n      \"logging 1.0.4-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\"\n      ],\n      \"logging 1.0.4\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"ejson@1.0.4\"\n      ],\n      \"logging 1.0.5-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\",\n        \"ejson@1.0.4\"\n      ],\n      \"logging 1.0.5-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"ejson@1.0.4-win.0\"\n      ],\n      \"logging 1.0.5\": [\n        \"meteor@1.1.3\",\n        \"underscore@1.0.1\",\n        \"ejson@1.0.4\"\n      ],\n      \"logging 1.0.6-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"ejson@1.0.6-eachin.0\"\n      ],\n      \"logging 1.0.6-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"ejson@1.0.6-eachin.43\"\n      ],\n      \"logging 1.0.6-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"ejson@1.0.6-githubble.0\"\n      ],\n      \"logging 1.0.6-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"ejson@1.0.6-githubble.2\"\n      ],\n      \"logging 1.0.6-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"ejson@1.0.6-githubble.42\"\n      ],\n      \"logging 1.0.6-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"ejson@1.0.6-githubble.43\"\n      ],\n      \"logging 1.0.6-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\"\n      ],\n      \"logging 1.0.6-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"ejson@1.0.5-rc.1\"\n      ],\n      \"logging 1.0.6-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"ejson@1.0.5-slava.0\"\n      ],\n      \"logging 1.0.6-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"ejson@1.0.5-win.0\"\n      ],\n      \"logging 1.0.6-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"ejson@1.0.5-winr.0\"\n      ],\n      \"logging 1.0.6-winr.1\": [\n        \"meteor@1.1.5-winr.3\",\n        \"underscore@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\"\n      ],\n      \"logging 1.0.6-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\"\n      ],\n      \"logging 1.0.6-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\"\n      ],\n      \"logging 1.0.6\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\"\n      ],\n      \"logging 1.0.7-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"ejson@1.0.6-rc.0\"\n      ],\n      \"logging 1.0.7-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"ejson@1.0.6-winr.0\"\n      ],\n      \"logging 1.0.7-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\"\n      ],\n      \"logging 1.0.7-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\"\n      ],\n      \"localstorage 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\"\n      ],\n      \"localstorage 1.0.0\": [\n        \"meteor@1.0.2\",\n        \"random@1.0.0\"\n      ],\n      \"localstorage 1.0.1-pre.0\": [\n        \"meteor\",\n        \"random\"\n      ],\n      \"localstorage 1.0.1-pre.1\": [\n        \"meteor\",\n        \"random\"\n      ],\n      \"localstorage 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"random@1.0.1-pre.2\"\n      ],\n      \"localstorage 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"random@1.0.1-rc.0\"\n      ],\n      \"localstorage 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"random@1.0.1-win.0\"\n      ],\n      \"localstorage 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"random@1.0.1\"\n      ],\n      \"localstorage 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"random@1.0.2-ipc.0\"\n      ],\n      \"localstorage 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"random@1.0.2-rc.1\"\n      ],\n      \"localstorage 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"random@1.0.2-slava.0\"\n      ],\n      \"localstorage 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"random@1.0.2-win.0\"\n      ],\n      \"localstorage 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"random@1.0.2-winr.0\"\n      ],\n      \"localstorage 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"random@1.0.2\"\n      ],\n      \"localstorage 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"random@1.0.3-eachin.43\"\n      ],\n      \"localstorage 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"random@1.0.3-githubble.0\"\n      ],\n      \"localstorage 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"random@1.0.3-githubble.2\"\n      ],\n      \"localstorage 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"random@1.0.3-githubble.42\"\n      ],\n      \"localstorage 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"random@1.0.3-githubble.43\"\n      ],\n      \"localstorage 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"random@1.0.3-rc.0\"\n      ],\n      \"localstorage 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"random@1.0.3-winr.0\"\n      ],\n      \"localstorage 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"random@1.0.3-winr.1\"\n      ],\n      \"localstorage 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"livedata 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"ddp@10.0.0-glasser.isopacket.0\"\n      ],\n      \"livedata 1.0.0\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"deps\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"livedata 1.0.1\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"deps\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"livedata 1.0.2\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"deps\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"livedata 1.0.3\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"deps\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"livedata 1.0.4\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"deps\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"livedata 1.0.5\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"deps\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"livedata 1.0.6-cordova3\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"deps\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"livedata 1.0.6-glasser1\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"deps\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"livedata 1.0.6\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"deps\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"livedata 1.0.7\": [\n        \"?audit-argument-checks@1.0.0\",\n        \"?autopublish@1.0.0\",\n        \"callback-hook@1.0.0\",\n        \"check@1.0.0\",\n        \"deps@1.0.1\",\n        \"ejson@1.0.0\",\n        \"?facts@1.0.0\",\n        \"json@1.0.0\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.2\",\n        \"minimongo@1.0.1\",\n        \"random@1.0.0\",\n        \"?reload@1.0.0\",\n        \"retry@1.0.0\",\n        \"?routepolicy@1.0.0\",\n        \"underscore@1.0.0\",\n        \"?webapp@1.0.2\"\n      ],\n      \"livedata 1.0.8-rc0\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"tracker\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"livedata 1.0.8-rc1\": [\n        \"meteor\",\n        \"ddp\"\n      ],\n      \"livedata 1.0.8\": [\n        \"ddp@1.0.8\",\n        \"meteor@1.0.3\"\n      ],\n      \"livedata 1.0.9\": [\n        \"ddp@1.0.8\",\n        \"meteor@1.0.3\"\n      ],\n      \"livedata 1.0.10-rc0\": [\n        \"meteor\",\n        \"ddp\"\n      ],\n      \"livedata 1.0.10\": [\n        \"ddp@1.0.9\",\n        \"meteor@1.1.1\"\n      ],\n      \"livedata 1.0.11-pre.0\": [\n        \"meteor\",\n        \"ddp\"\n      ],\n      \"livedata 1.0.11-pre.1\": [\n        \"meteor\",\n        \"ddp\"\n      ],\n      \"livedata 1.0.11-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"ddp@1.0.10-pre.2\"\n      ],\n      \"livedata 1.0.11-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"ddp@1.0.10-rc.0\"\n      ],\n      \"livedata 1.0.11-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"ddp@1.0.11-win.0\"\n      ],\n      \"livedata 1.0.11\": [\n        \"meteor@1.1.2\",\n        \"ddp@1.0.10\"\n      ],\n      \"livedata 1.0.12-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"ddp@1.0.12-ipc.0\"\n      ],\n      \"livedata 1.0.12-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"ddp@1.0.13-rc.1\"\n      ],\n      \"livedata 1.0.12-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"ddp@1.0.13-slava.0\"\n      ],\n      \"livedata 1.0.12-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"ddp@1.0.12-win.0\"\n      ],\n      \"livedata 1.0.12-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"ddp@1.0.13-winr.0\"\n      ],\n      \"livedata 1.0.12\": [\n        \"meteor@1.1.4\",\n        \"ddp@1.0.13\"\n      ],\n      \"livedata 1.0.13-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"ddp@1.0.14-eachin.0\"\n      ],\n      \"livedata 1.0.13-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"ddp@1.0.15-eachin.43\"\n      ],\n      \"livedata 1.0.13-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"ddp@1.0.15-githubble.0\"\n      ],\n      \"livedata 1.0.13-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"ddp@1.0.15-githubble.2\"\n      ],\n      \"livedata 1.0.13-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"ddp@1.0.15-githubble.42\"\n      ],\n      \"livedata 1.0.13-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"ddp@1.0.15-githubble.43\"\n      ],\n      \"livedata 1.0.13-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"ddp@1.1.0-rc.0\"\n      ],\n      \"livedata 1.0.13-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"ddp@1.0.14-winr.0\"\n      ],\n      \"livedata 1.0.13-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"ddp@1.0.14-winr.1\"\n      ],\n      \"livedata 1.0.13-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"ddp@1.0.14-winr.4\"\n      ],\n      \"launch-screen 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"?blaze@10.0.0-glasser.isopacket.0\",\n        \"?templating@10.0.0-glasser.isopacket.0\"\n      ],\n      \"launch-screen 1.0.0-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"?blaze@2.0.3-rc.0\",\n        \"?templating@1.0.9-rc.0\"\n      ],\n      \"launch-screen 1.0.0-refreshpolicy.1\": [\n        \"meteor@1.1.2-refreshpolicy.1\",\n        \"?blaze@2.0.2-refreshpolicy.1\",\n        \"?templating@1.0.8\"\n      ],\n      \"launch-screen 1.0.0-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"?blaze@2.0.3-win.0\",\n        \"?templating@1.0.9-win.0\"\n      ],\n      \"launch-screen 1.0.0\": [\n        \"meteor@1.1.3\",\n        \"?blaze@2.0.3\",\n        \"?templating@1.0.9\"\n      ],\n      \"launch-screen 1.0.1-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"?blaze@2.0.5-eachin.0\",\n        \"?templating@1.0.11-eachin.0\"\n      ],\n      \"launch-screen 1.0.1-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"?blaze@2.0.5-eachin.43\",\n        \"?templating@1.0.12-eachin.43\"\n      ],\n      \"launch-screen 1.0.1-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"?blaze@2.0.5-githubble.0\",\n        \"?templating@1.0.12-githubble.0\"\n      ],\n      \"launch-screen 1.0.1-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"?blaze@2.0.5-githubble.2\",\n        \"?templating@1.0.12-githubble.2\"\n      ],\n      \"launch-screen 1.0.1-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"?blaze@2.0.5-githubble.42\",\n        \"?templating@1.0.12-githubble.42\"\n      ],\n      \"launch-screen 1.0.1-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"?blaze@2.0.5-githubble.43\",\n        \"?templating@1.0.12-githubble.43\"\n      ],\n      \"launch-screen 1.0.1-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"?blaze@2.0.4-ipc.0\",\n        \"?templating@1.0.10-ipc.0\"\n      ],\n      \"launch-screen 1.0.1-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"?blaze@2.0.4-rc.1\",\n        \"?templating@1.0.10-rc.1\"\n      ],\n      \"launch-screen 1.0.1-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"?blaze@2.0.4-slava.0\",\n        \"?templating@1.0.10-slava.0\"\n      ],\n      \"launch-screen 1.0.1-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"?blaze@2.0.4-win.0\",\n        \"?templating@1.0.10-win.0\"\n      ],\n      \"launch-screen 1.0.1-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"?blaze@2.0.4-winr.0\",\n        \"?templating@1.0.10-winr.0\"\n      ],\n      \"launch-screen 1.0.1-winr.1\": [\n        \"meteor@1.1.5-winr.3\",\n        \"?blaze@2.0.5-winr.1\",\n        \"?templating@1.0.11-winr.3\"\n      ],\n      \"launch-screen 1.0.1-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"?blaze@2.0.5-winr.2\",\n        \"?templating@1.0.11-winr.4\"\n      ],\n      \"launch-screen 1.0.1-winr.3\": [\n        \"meteor@1.1.5-winr.5\",\n        \"?blaze@2.0.5-winr.3\",\n        \"?templating@1.0.11-winr.6\"\n      ],\n      \"launch-screen 1.0.1-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"?blaze@2.0.5-winr.4\",\n        \"?templating@1.0.12-winr.6\"\n      ],\n      \"launch-screen 1.0.1\": [\n        \"meteor@1.1.4\",\n        \"?blaze@2.0.4\",\n        \"?templating@1.0.10\"\n      ],\n      \"launch-screen 1.0.2-blz.0\": [\n        \"meteor@1.1.4\",\n        \"?blaze@2.0.5-blz.0\",\n        \"?templating@1.0.11\"\n      ],\n      \"launch-screen 1.0.2-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"?blaze@2.1.0-rc.0\",\n        \"?templating@1.1.0-rc.0\"\n      ],\n      \"launch-screen 1.0.2-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"?blaze@2.0.5-vs.1\",\n        \"?templating@1.0.12-vs.1\"\n      ],\n      \"launch-screen 1.0.2-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"?blaze@2.0.5-vs.2\",\n        \"?templating@1.0.12-vs.2\"\n      ],\n      \"launch-screen 1.0.2-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"?blaze@2.0.5-winr.0\",\n        \"?templating@1.0.11-winr.0\"\n      ],\n      \"launch-screen 1.0.2-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"?blaze@2.0.5-winr.1\",\n        \"?templating@1.0.11-winr.1\"\n      ],\n      \"launch-screen 1.0.2-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"?blaze@2.0.5-winr.5\",\n        \"?templating@1.0.12-winr.7\"\n      ],\n      \"jsparse 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"jsparse 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"jsparse 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"jsparse 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"jsparse 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"jsparse 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"jsparse 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"jsparse 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"jsparse 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"jsparse 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"jsparse 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"jsparse 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"jsparse 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"jsparse 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"jsparse 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"jsparse 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"jsparse 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"jsparse 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"jsparse 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"jsparse 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"jsparse 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"jsparse 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"jsparse 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"json 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"json 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"json 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"json 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"json 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"json 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"json 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"json 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"json 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"json 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"json 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"json 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"json 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"json 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"json 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"json 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"json 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"json 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"json 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"json 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"json 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"json 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"json 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"json 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"js-analyze 0.0.0-glasser-isopacket.0\": [],\n      \"js-analyze 1.0.0\": [],\n      \"js-analyze 1.0.1\": [],\n      \"js-analyze 1.0.2\": [],\n      \"js-analyze 1.0.3-pre.0\": [],\n      \"js-analyze 1.0.3-pre.1\": [],\n      \"js-analyze 1.0.3-pre.2\": [],\n      \"js-analyze 1.0.3-rc.0\": [],\n      \"js-analyze 1.0.3-win.0\": [],\n      \"js-analyze 1.0.3\": [],\n      \"js-analyze 1.0.4-ipc.0\": [],\n      \"js-analyze 1.0.4-rc.1\": [],\n      \"js-analyze 1.0.4-slava.0\": [],\n      \"js-analyze 1.0.4-win.0\": [],\n      \"js-analyze 1.0.4-winr.0\": [],\n      \"js-analyze 1.0.4\": [],\n      \"js-analyze 1.0.5-eachin.0\": [],\n      \"js-analyze 1.0.5-eachin.43\": [],\n      \"js-analyze 1.0.5-githubble.0\": [],\n      \"js-analyze 1.0.5-githubble.2\": [],\n      \"js-analyze 1.0.5-githubble.42\": [],\n      \"js-analyze 1.0.5-githubble.43\": [],\n      \"js-analyze 1.0.5-rc.0\": [],\n      \"js-analyze 1.0.5-winr.0\": [],\n      \"js-analyze 1.0.5-winr.1\": [],\n      \"js-analyze 1.0.5-winr.2\": [],\n      \"js-analyze-tests 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"js-analyze-tests 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"js-analyze-tests 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"js-analyze-tests 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"js-analyze-tests 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"js-analyze-tests 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"js-analyze-tests 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"js-analyze-tests 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"js-analyze-tests 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"js-analyze-tests 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"js-analyze-tests 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"js-analyze-tests 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"js-analyze-tests 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"js-analyze-tests 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"js-analyze-tests 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"js-analyze-tests 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"js-analyze-tests 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"js-analyze-tests 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"js-analyze-tests 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"js-analyze-tests 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"js-analyze-tests 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"js-analyze-tests 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"js-analyze-tests 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"jquery 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"jquery 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"jquery 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"jquery 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"jquery 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"jquery 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"jquery 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"jquery 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"jquery 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"jquery 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"jquery 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"jquery 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"jquery 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"jquery 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"jquery 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"jquery 1.5.0-glasser.isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"jquery 1.11.3-eachin.43_1\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"jquery 1.11.3-githubble.0_1\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"jquery 1.11.3-githubble.2_1\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"jquery 1.11.3-githubble.42_1\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"jquery 1.11.3-githubble.43_1\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"jquery 1.11.3-rc.0\": [\n        \"meteor@1.1.4\"\n      ],\n      \"jquery 1.11.3-rc.0_2\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"jquery 1.11.3-winr.0\": [\n        \"meteor@1.1.5-winr.2\"\n      ],\n      \"jquery 1.11.3-winr.1\": [\n        \"meteor@1.1.5-winr.3\"\n      ],\n      \"jquery 1.11.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"jquery 1.11.3-winr.2_1\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"jquery 1.11.3\": [\n        \"meteor@1.1.4\"\n      ],\n      \"jquery-waypoints 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"jquery@1.5.0-glasser.isopacket.0\",\n        \"coffeescript@10.0.0-glasser.isopacket.0\"\n      ],\n      \"jquery-waypoints 1.0.0\": [\n        \"coffeescript@1.0.2\",\n        \"jquery@1.0.0\",\n        \"meteor@1.0.2\"\n      ],\n      \"jquery-waypoints 1.0.1-pre.0\": [\n        \"meteor\",\n        \"jquery\",\n        \"coffeescript\"\n      ],\n      \"jquery-waypoints 1.0.1-pre.1\": [\n        \"meteor\",\n        \"jquery\",\n        \"coffeescript\"\n      ],\n      \"jquery-waypoints 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"jquery@1.0.1-pre.2\",\n        \"coffeescript@1.0.4-pre.2\"\n      ],\n      \"jquery-waypoints 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"jquery@1.0.1-rc.0\",\n        \"coffeescript@1.0.4-rc.0\"\n      ],\n      \"jquery-waypoints 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"jquery@1.0.1-win.0\",\n        \"coffeescript@1.0.4-win.0\"\n      ],\n      \"jquery-waypoints 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"jquery@1.0.1\",\n        \"coffeescript@1.0.4\"\n      ],\n      \"jquery-waypoints 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"jquery@1.0.2-ipc.0\",\n        \"coffeescript@1.0.5-ipc.0\"\n      ],\n      \"jquery-waypoints 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"jquery@1.0.2-rc.1\",\n        \"coffeescript@1.0.5-rc.1\"\n      ],\n      \"jquery-waypoints 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"jquery@1.0.2-slava.0\",\n        \"coffeescript@1.0.5-slava.0\"\n      ],\n      \"jquery-waypoints 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"jquery@1.0.2-win.0\",\n        \"coffeescript@1.0.5-win.0\"\n      ],\n      \"jquery-waypoints 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"jquery@1.0.2-winr.0\",\n        \"coffeescript@1.0.5-winr.0\"\n      ],\n      \"jquery-waypoints 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"jquery@1.0.2\",\n        \"coffeescript@1.0.5\"\n      ],\n      \"jquery-waypoints 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"jquery@1.11.3-eachin.43_1\",\n        \"coffeescript@1.0.6-eachin.43\"\n      ],\n      \"jquery-waypoints 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"jquery@1.11.3-githubble.0_1\",\n        \"coffeescript@1.0.6-githubble.0\"\n      ],\n      \"jquery-waypoints 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"jquery@1.11.3-githubble.2_1\",\n        \"coffeescript@1.0.6-githubble.2\"\n      ],\n      \"jquery-waypoints 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"jquery@1.11.3-githubble.42_1\",\n        \"coffeescript@1.0.6-githubble.42\"\n      ],\n      \"jquery-waypoints 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"jquery@1.11.3-githubble.43_1\",\n        \"coffeescript@1.0.6-githubble.43\"\n      ],\n      \"jquery-waypoints 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"jquery@1.11.3-rc.0_2\",\n        \"coffeescript@1.0.6-rc.0\"\n      ],\n      \"jquery-waypoints 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"jquery@1.0.3-winr.0\",\n        \"coffeescript@1.0.6-winr.0\"\n      ],\n      \"jquery-waypoints 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"jquery@1.0.3-winr.1\",\n        \"coffeescript@1.0.6-winr.1\"\n      ],\n      \"jquery-waypoints 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"jquery@1.11.3-winr.2\",\n        \"coffeescript@1.0.6-winr.2\"\n      ],\n      \"id-map 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"json@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\"\n      ],\n      \"id-map 1.0.0\": [\n        \"ejson@1.0.0\",\n        \"json@1.0.0\",\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"id-map 1.0.1-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\"\n      ],\n      \"id-map 1.0.1-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"json\",\n        \"ejson\"\n      ],\n      \"id-map 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"json@1.0.1-pre.2\",\n        \"ejson@1.0.4-pre.2\"\n      ],\n      \"id-map 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"json@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\"\n      ],\n      \"id-map 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"json@1.0.1-win.0\",\n        \"ejson@1.0.4-win.0\"\n      ],\n      \"id-map 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"json@1.0.1\",\n        \"ejson@1.0.4\"\n      ],\n      \"id-map 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"json@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\"\n      ],\n      \"id-map 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"json@1.0.2-rc.1\",\n        \"ejson@1.0.5-rc.1\"\n      ],\n      \"id-map 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"json@1.0.2-slava.0\",\n        \"ejson@1.0.5-slava.0\"\n      ],\n      \"id-map 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"json@1.0.2-win.0\",\n        \"ejson@1.0.5-win.0\"\n      ],\n      \"id-map 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"json@1.0.2-winr.0\",\n        \"ejson@1.0.5-winr.0\"\n      ],\n      \"id-map 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"json@1.0.2\",\n        \"ejson@1.0.5\"\n      ],\n      \"id-map 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"json@1.0.3-eachin.0\",\n        \"ejson@1.0.6-eachin.0\"\n      ],\n      \"id-map 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"json@1.0.3-eachin.43\",\n        \"ejson@1.0.6-eachin.43\"\n      ],\n      \"id-map 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"json@1.0.3-githubble.0\",\n        \"ejson@1.0.6-githubble.0\"\n      ],\n      \"id-map 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"json@1.0.3-githubble.2\",\n        \"ejson@1.0.6-githubble.2\"\n      ],\n      \"id-map 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"json@1.0.3-githubble.42\",\n        \"ejson@1.0.6-githubble.42\"\n      ],\n      \"id-map 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"json@1.0.3-githubble.43\",\n        \"ejson@1.0.6-githubble.43\"\n      ],\n      \"id-map 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"json@1.0.3-rc.0\",\n        \"ejson@1.0.6-rc.0\"\n      ],\n      \"id-map 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"json@1.0.3-winr.0\",\n        \"ejson@1.0.6-winr.0\"\n      ],\n      \"id-map 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"json@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\"\n      ],\n      \"id-map 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\"\n      ],\n      \"http 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"url@10.0.0-glasser.isopacket.0\"\n      ],\n      \"http 1.0.0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"http 1.0.1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"http 1.0.2\": [\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"http 1.0.3-rc1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"http 1.0.3\": [\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"http 1.0.4-glasser1\": [\n        \"meteor\",\n        \"underscore\",\n        \"url\"\n      ],\n      \"http 1.0.4-rc0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"http 1.0.4\": [\n        \"meteor@1.0.3\",\n        \"underscore@1.0.0\"\n      ],\n      \"http 1.0.5-ekate\": [\n        \"meteor\",\n        \"underscore\",\n        \"url\"\n      ],\n      \"http 1.0.5-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"url\"\n      ],\n      \"http 1.0.5\": [\n        \"meteor@1.1.0\",\n        \"underscore@1.0.0\",\n        \"url@1.0.0\"\n      ],\n      \"http 1.0.6-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"url\"\n      ],\n      \"http 1.0.6\": [\n        \"meteor@1.1.1\",\n        \"underscore@1.0.0\",\n        \"url@1.0.0\"\n      ],\n      \"http 1.0.7-nim.0\": [\n        \"meteor@1.1.2-nim.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"url@1.0.1-rc.0\"\n      ],\n      \"http 1.0.7-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"url\"\n      ],\n      \"http 1.0.7-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"url\"\n      ],\n      \"http 1.0.7-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"url@1.0.1-pre.2\"\n      ],\n      \"http 1.0.7-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"url@1.0.1-rc.0\"\n      ],\n      \"http 1.0.7-rc.1\": [\n        \"meteor@1.1.2-ekate.1\",\n        \"underscore@1.0.1-rc.0\",\n        \"url@1.0.1-rc.0\"\n      ],\n      \"http 1.0.7-rc.2\": [\n        \"meteor@1.1.2-rc.2\",\n        \"underscore@1.0.1-rc.0\",\n        \"url@1.0.1-rc.0\"\n      ],\n      \"http 1.0.7-rc.3\": [\n        \"meteor@1.1.2-rc.3\",\n        \"underscore@1.0.1-rc.0\",\n        \"url@1.0.1-rc.0\"\n      ],\n      \"http 1.0.7-rc.4\": [\n        \"meteor@1.1.2-rc.3\",\n        \"underscore@1.0.1-rc.0\",\n        \"url@1.0.1-rc.0\"\n      ],\n      \"http 1.0.7-rc.5\": [\n        \"meteor@1.1.2-rc.3\",\n        \"underscore@1.0.1-rc.0\",\n        \"url@1.0.1-rc.0\"\n      ],\n      \"http 1.0.7-refreshpolicy.1\": [\n        \"meteor@1.1.2-refreshpolicy.1\",\n        \"underscore@1.0.1\",\n        \"url@1.0.1-refreshpolicy.1\"\n      ],\n      \"http 1.0.7\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"url@1.0.1\"\n      ],\n      \"http 1.0.7_1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"url@1.0.1\"\n      ],\n      \"http 1.0.8-rc.0\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"url@1.0.1\"\n      ],\n      \"http 1.0.8-rc.1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"url@1.0.1\"\n      ],\n      \"http 1.0.8-rc.2\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\",\n        \"url@1.0.2-rc.0\"\n      ],\n      \"http 1.0.8-rc.3\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\",\n        \"url@1.0.2-rc.0\"\n      ],\n      \"http 1.0.8-rc.4\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\",\n        \"url@1.0.2-rc.0\"\n      ],\n      \"http 1.0.8-rc.5\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\",\n        \"url@1.0.2-rc.0\"\n      ],\n      \"http 1.0.8-rc.6\": [\n        \"meteor@1.1.3-rc.0\",\n        \"underscore@1.0.1\",\n        \"url@1.0.2-rc.0\"\n      ],\n      \"http 1.0.8-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"url@1.0.2-win.0\"\n      ],\n      \"http 1.0.8\": [\n        \"meteor@1.1.3\",\n        \"underscore@1.0.1\",\n        \"url@1.0.2\"\n      ],\n      \"http 1.0.9-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"url@1.0.3-ipc.0\"\n      ],\n      \"http 1.0.9-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"url@1.0.3-rc.1\"\n      ],\n      \"http 1.0.9-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"url@1.0.3-slava.0\"\n      ],\n      \"http 1.0.9-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"url@1.0.3-win.0\"\n      ],\n      \"http 1.0.9-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"url@1.0.3-winr.0\"\n      ],\n      \"http 1.0.9\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"url@1.0.3\"\n      ],\n      \"http 1.0.10-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"url@1.0.4-winr.2\"\n      ],\n      \"http 1.0.10-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"url@1.0.4-eachin.43\"\n      ],\n      \"http 1.0.10-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"url@1.0.4-githubble.0\"\n      ],\n      \"http 1.0.10-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"url@1.0.4-githubble.2\"\n      ],\n      \"http 1.0.10-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"url@1.0.4-githubble.42\"\n      ],\n      \"http 1.0.10-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"url@1.0.4-githubble.43\"\n      ],\n      \"http 1.0.10-rc.0\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"url@1.0.3\"\n      ],\n      \"http 1.0.10-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"url@1.0.4-winr.0\"\n      ],\n      \"http 1.0.10-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"url@1.0.4-winr.1\"\n      ],\n      \"http 1.0.10-winr.2\": [\n        \"meteor@1.1.5-winr.2\",\n        \"underscore@1.0.2\",\n        \"url@1.0.3\"\n      ],\n      \"http 1.0.10-winr.3\": [\n        \"meteor@1.1.5-winr.3\",\n        \"underscore@1.0.2\",\n        \"url@1.0.3\"\n      ],\n      \"http 1.0.10-winr.4\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"url@1.0.4-winr.2\"\n      ],\n      \"http 1.0.10-winr.5\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"url@1.0.4-winr.2\"\n      ],\n      \"http 1.0.10\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"url@1.0.3\"\n      ],\n      \"http 1.0.11-winr.5\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"url@1.0.4-winr.2\"\n      ],\n      \"http 1.1.0-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"url@1.0.4-rc.0\"\n      ],\n      \"htmljs 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"deps@10.0.0-glasser.isopacket.0\"\n      ],\n      \"htmljs 1.0.0-cordova1\": [\n        \"deps@1.0.3\",\n        \"meteor@1.1.0\"\n      ],\n      \"htmljs 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"htmljs 1.0.1\": [\n        \"deps@1.0.3\",\n        \"meteor@1.1.0\"\n      ],\n      \"htmljs 1.0.2-pre.0\": [\n        \"meteor\",\n        \"deps\"\n      ],\n      \"htmljs 1.0.2-pre.1\": [\n        \"meteor\",\n        \"deps\"\n      ],\n      \"htmljs 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"deps@1.0.5-pre.2\"\n      ],\n      \"htmljs 1.0.2-pre.3\": [\n        \"meteor@1.1.2-pre.3\",\n        \"deps@1.0.5-pre.2\"\n      ],\n      \"htmljs 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"deps@1.0.5-rc.0\"\n      ],\n      \"htmljs 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"deps@1.0.5-win.0\"\n      ],\n      \"htmljs 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"deps@1.0.5\"\n      ],\n      \"htmljs 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"deps@1.0.6-ipc.0\"\n      ],\n      \"htmljs 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"deps@1.0.6-rc.1\"\n      ],\n      \"htmljs 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"deps@1.0.6-slava.0\"\n      ],\n      \"htmljs 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"deps@1.0.6-win.0\"\n      ],\n      \"htmljs 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"deps@1.0.6-winr.0\"\n      ],\n      \"htmljs 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"deps@1.0.6\"\n      ],\n      \"htmljs 1.0.4-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"deps@1.0.7-eachin.0\"\n      ],\n      \"htmljs 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"deps@1.0.7-eachin.43\"\n      ],\n      \"htmljs 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"deps@1.0.7-githubble.0\"\n      ],\n      \"htmljs 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"deps@1.0.7-githubble.2\"\n      ],\n      \"htmljs 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"deps@1.0.7-githubble.42\"\n      ],\n      \"htmljs 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"deps@1.0.7-githubble.43\"\n      ],\n      \"htmljs 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"deps@1.0.7-rc.0\"\n      ],\n      \"htmljs 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"deps@1.0.7-winr.0\"\n      ],\n      \"htmljs 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"deps@1.0.7-winr.1\"\n      ],\n      \"htmljs 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"deps@1.0.7-winr.2\"\n      ],\n      \"html-tools 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"htmljs@10.0.0-glasser.isopacket.0\"\n      ],\n      \"html-tools 1.0.0\": [\n        \"htmljs@1.0.0\",\n        \"meteor@1.0.2\"\n      ],\n      \"html-tools 1.0.1-rc0\": [\n        \"meteor\",\n        \"htmljs\"\n      ],\n      \"html-tools 1.0.1\": [\n        \"htmljs@1.0.1\",\n        \"meteor@1.1.1\"\n      ],\n      \"html-tools 1.0.2-pre.0\": [\n        \"meteor\",\n        \"htmljs\"\n      ],\n      \"html-tools 1.0.2-pre.1\": [\n        \"meteor\",\n        \"htmljs\"\n      ],\n      \"html-tools 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"htmljs@1.0.2-pre.2\"\n      ],\n      \"html-tools 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"htmljs@1.0.2-rc.0\"\n      ],\n      \"html-tools 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"htmljs@1.0.2-win.0\"\n      ],\n      \"html-tools 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"htmljs@1.0.2\"\n      ],\n      \"html-tools 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"htmljs@1.0.4-eachin.0\"\n      ],\n      \"html-tools 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"htmljs@1.0.4-eachin.43\"\n      ],\n      \"html-tools 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"htmljs@1.0.4-githubble.0\"\n      ],\n      \"html-tools 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"htmljs@1.0.4-githubble.2\"\n      ],\n      \"html-tools 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"htmljs@1.0.4-githubble.42\"\n      ],\n      \"html-tools 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"htmljs@1.0.4-githubble.43\"\n      ],\n      \"html-tools 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"htmljs@1.0.3-ipc.0\"\n      ],\n      \"html-tools 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"htmljs@1.0.3-rc.1\"\n      ],\n      \"html-tools 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"htmljs@1.0.3-slava.0\"\n      ],\n      \"html-tools 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"htmljs@1.0.3-win.0\"\n      ],\n      \"html-tools 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"htmljs@1.0.3-winr.0\"\n      ],\n      \"html-tools 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.2\",\n        \"htmljs@1.0.3\"\n      ],\n      \"html-tools 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.3\",\n        \"htmljs@1.0.3\"\n      ],\n      \"html-tools 1.0.3-winr.3\": [\n        \"meteor@1.1.5-winr.4\",\n        \"htmljs@1.0.4-winr.2\"\n      ],\n      \"html-tools 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"htmljs@1.0.3\"\n      ],\n      \"html-tools 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"htmljs@1.0.4-rc.0\"\n      ],\n      \"html-tools 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"htmljs@1.0.4-winr.0\"\n      ],\n      \"html-tools 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"htmljs@1.0.4-winr.1\"\n      ],\n      \"html-tools 1.0.4-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"htmljs@1.0.4-winr.2\"\n      ],\n      \"handlebars 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"handlebars 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"handlebars 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"handlebars 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"handlebars 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"handlebars 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"handlebars 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"handlebars 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"handlebars 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"handlebars 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"handlebars 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"handlebars 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"handlebars 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"handlebars 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"handlebars 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"handlebars 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"handlebars 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"handlebars 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"handlebars 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"handlebars 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"handlebars 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"handlebars 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"handlebars 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"handlebars 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"google 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"oauth2@10.0.0-glasser.isopacket.0\",\n        \"oauth@10.0.0-glasser.isopacket.0\",\n        \"http@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"service-configuration@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"templating@10.0.0-glasser.isopacket.0\"\n      ],\n      \"google 1.0.0\": [\n        \"http@1.0.2\",\n        \"meteor@1.0.2\",\n        \"oauth@1.0.0\",\n        \"oauth2@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.0\",\n        \"templating@1.0.4\",\n        \"underscore@1.0.0\"\n      ],\n      \"google 1.0.1-glasser1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"google 1.0.1-rc0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"google 1.0.1\": [\n        \"http@1.0.4\",\n        \"meteor@1.0.3\",\n        \"oauth@1.0.1\",\n        \"oauth2@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.5\",\n        \"underscore@1.0.0\"\n      ],\n      \"google 1.0.2-ekate\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"google 1.1.0-rc0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"google 1.1.0\": [\n        \"http@1.0.5\",\n        \"meteor@1.1.0\",\n        \"oauth@1.1.0\",\n        \"oauth2@1.1.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.6\",\n        \"underscore@1.0.0\"\n      ],\n      \"google 1.1.1-pre.0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"google 1.1.1-pre.1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"random\",\n        \"templating\"\n      ],\n      \"google 1.1.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"oauth2@1.1.1-pre.2\",\n        \"oauth@1.1.1-pre.2\",\n        \"http@1.0.7-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"service-configuration@1.0.2-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"templating@1.0.8-pre.2\"\n      ],\n      \"google 1.1.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"oauth2@1.1.1-rc.0\",\n        \"oauth@1.1.1-rc.0\",\n        \"http@1.0.7-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"templating@1.0.8-rc.0\"\n      ],\n      \"google 1.1.1\": [\n        \"meteor@1.1.2\",\n        \"oauth2@1.1.1\",\n        \"oauth@1.1.1\",\n        \"http@1.0.7\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"random@1.0.1\",\n        \"templating@1.0.8\"\n      ],\n      \"google 1.1.2-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"oauth2@1.1.1\",\n        \"oauth@1.1.1\",\n        \"http@1.0.8-rc.4\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"random@1.0.1\",\n        \"templating@1.0.9-rc.1\"\n      ],\n      \"google 1.1.2-rc.1\": [\n        \"meteor@1.1.3-rc.0\",\n        \"oauth2@1.1.1\",\n        \"oauth@1.1.1\",\n        \"http@1.0.8-rc.5\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"random@1.0.1\",\n        \"templating@1.0.9-rc.2\"\n      ],\n      \"google 1.1.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"oauth2@1.1.1-win.0\",\n        \"oauth@1.1.2-win.0\",\n        \"http@1.0.8-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"service-configuration@1.0.2-win.0\",\n        \"random@1.0.1-win.0\",\n        \"templating@1.0.9-win.0\"\n      ],\n      \"google 1.1.2\": [\n        \"meteor@1.1.3\",\n        \"oauth2@1.1.1\",\n        \"oauth@1.1.2\",\n        \"http@1.0.8\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"random@1.0.1\",\n        \"templating@1.0.9\"\n      ],\n      \"google 1.1.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"oauth2@1.1.2-ipc.0\",\n        \"oauth@1.1.3-ipc.0\",\n        \"http@1.0.9-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"service-configuration@1.0.3-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"templating@1.0.10-ipc.0\"\n      ],\n      \"google 1.1.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"oauth2@1.1.2-rc.1\",\n        \"oauth@1.1.3-rc.1\",\n        \"http@1.0.9-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"service-configuration@1.0.3-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"templating@1.0.10-rc.1\"\n      ],\n      \"google 1.1.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"oauth2@1.1.2-slava.0\",\n        \"oauth@1.1.3-slava.0\",\n        \"http@1.0.9-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"service-configuration@1.0.3-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"templating@1.0.10-slava.0\"\n      ],\n      \"google 1.1.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"oauth2@1.1.2-win.0\",\n        \"oauth@1.1.3-win.0\",\n        \"http@1.0.9-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"service-configuration@1.0.3-win.0\",\n        \"random@1.0.2-win.0\",\n        \"templating@1.0.10-win.0\"\n      ],\n      \"google 1.1.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"oauth2@1.1.2-winr.0\",\n        \"oauth@1.1.3-winr.0\",\n        \"http@1.0.9-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"service-configuration@1.0.3-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"templating@1.0.10-winr.0\"\n      ],\n      \"google 1.1.3\": [\n        \"meteor@1.1.4\",\n        \"oauth2@1.1.2\",\n        \"oauth@1.1.3\",\n        \"http@1.0.9\",\n        \"underscore@1.0.2\",\n        \"service-configuration@1.0.3\",\n        \"random@1.0.2\",\n        \"templating@1.0.10\"\n      ],\n      \"google 1.1.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"oauth2@1.1.3-eachin.43\",\n        \"oauth@1.1.4-eachin.43\",\n        \"http@1.0.10-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"service-configuration@1.0.4-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"templating@1.0.12-eachin.43\"\n      ],\n      \"google 1.1.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"oauth2@1.1.3-githubble.0\",\n        \"oauth@1.1.4-githubble.0\",\n        \"http@1.0.10-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"service-configuration@1.0.4-githubble.0\",\n        \"random@1.0.3-githubble.0\",\n        \"templating@1.0.12-githubble.0\"\n      ],\n      \"google 1.1.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"oauth2@1.1.3-githubble.2\",\n        \"oauth@1.1.4-githubble.2\",\n        \"http@1.0.10-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"service-configuration@1.0.4-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"templating@1.0.12-githubble.2\"\n      ],\n      \"google 1.1.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"oauth2@1.1.3-githubble.42\",\n        \"oauth@1.1.4-githubble.42\",\n        \"http@1.0.10-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"service-configuration@1.0.4-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"templating@1.0.12-githubble.42\"\n      ],\n      \"google 1.1.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"oauth2@1.1.3-githubble.43\",\n        \"oauth@1.1.4-githubble.43\",\n        \"http@1.0.10-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"service-configuration@1.0.4-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"templating@1.0.12-githubble.43\"\n      ],\n      \"google 1.1.4-rc.0\": [\n        \"meteor@1.1.4\",\n        \"oauth2@1.1.2\",\n        \"oauth@1.1.3\",\n        \"http@1.0.10-rc.0\",\n        \"underscore@1.0.2\",\n        \"service-configuration@1.0.3\",\n        \"random@1.0.2\",\n        \"templating@1.0.11-rc.0\"\n      ],\n      \"google 1.1.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"oauth2@1.1.3-winr.0\",\n        \"oauth@1.1.4-winr.0\",\n        \"http@1.0.10-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"service-configuration@1.0.4-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"templating@1.0.11-winr.0\"\n      ],\n      \"google 1.1.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"oauth2@1.1.3-winr.1\",\n        \"oauth@1.1.4-winr.1\",\n        \"http@1.0.10-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"service-configuration@1.0.4-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"templating@1.0.11-winr.1\"\n      ],\n      \"google 1.1.4-winr.2\": [\n        \"meteor@1.1.5-winr.2\",\n        \"oauth2@1.1.2\",\n        \"oauth@1.1.4-winr.0\",\n        \"http@1.0.10-winr.2\",\n        \"underscore@1.0.2\",\n        \"service-configuration@1.0.3\",\n        \"random@1.0.2\",\n        \"templating@1.0.11-winr.2\"\n      ],\n      \"google 1.1.4-winr.3\": [\n        \"meteor@1.1.5-winr.3\",\n        \"oauth2@1.1.2\",\n        \"oauth@1.1.4-winr.1\",\n        \"http@1.0.10-winr.3\",\n        \"underscore@1.0.2\",\n        \"service-configuration@1.0.3\",\n        \"random@1.0.2\",\n        \"templating@1.0.11-winr.3\"\n      ],\n      \"google 1.1.4-winr.4\": [\n        \"meteor@1.1.5-winr.4\",\n        \"oauth2@1.1.3-winr.2\",\n        \"oauth@1.1.4-winr.2\",\n        \"http@1.0.10-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"templating@1.0.11-winr.4\"\n      ],\n      \"google 1.1.4\": [\n        \"meteor@1.1.4\",\n        \"oauth2@1.1.2\",\n        \"oauth@1.1.3\",\n        \"http@1.0.10\",\n        \"underscore@1.0.2\",\n        \"service-configuration@1.0.3\",\n        \"random@1.0.2\",\n        \"templating@1.0.11\"\n      ],\n      \"google 1.1.5-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"oauth2@1.1.3-rc.0\",\n        \"oauth@1.1.4-rc.0\",\n        \"http@1.1.0-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"service-configuration@1.0.4-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"templating@1.1.0-rc.0\"\n      ],\n      \"google 1.1.5-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"oauth2@1.1.3-winr.2\",\n        \"oauth@1.1.4-winr.3\",\n        \"http@1.0.11-winr.5\",\n        \"underscore@1.0.3-winr.2\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"templating@1.0.12-winr.7\"\n      ],\n      \"github 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"oauth2@10.0.0-glasser.isopacket.0\",\n        \"oauth@10.0.0-glasser.isopacket.0\",\n        \"http@10.0.0-glasser.isopacket.0\",\n        \"service-configuration@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"templating@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\"\n      ],\n      \"github 1.0.0\": [\n        \"http@1.0.2\",\n        \"meteor@1.0.2\",\n        \"oauth@1.0.0\",\n        \"oauth2@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.0\",\n        \"templating@1.0.4\",\n        \"underscore@1.0.0\"\n      ],\n      \"github 1.0.1-glasser1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"random\"\n      ],\n      \"github 1.0.1-rc0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"random\"\n      ],\n      \"github 1.0.1\": [\n        \"http@1.0.4\",\n        \"meteor@1.0.3\",\n        \"oauth@1.0.1\",\n        \"oauth2@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.5\",\n        \"underscore@1.0.0\"\n      ],\n      \"github 1.0.2-ekate\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"random\"\n      ],\n      \"github 1.1.0-rc0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"random\"\n      ],\n      \"github 1.1.0-rc1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"random\"\n      ],\n      \"github 1.1.0\": [\n        \"http@1.0.5\",\n        \"meteor@1.1.0\",\n        \"oauth@1.1.0\",\n        \"oauth2@1.1.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.6\",\n        \"underscore@1.0.0\"\n      ],\n      \"github 1.1.1-pre.0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"random\"\n      ],\n      \"github 1.1.1-pre.1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"random\"\n      ],\n      \"github 1.1.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"oauth2@1.1.1-pre.2\",\n        \"oauth@1.1.1-pre.2\",\n        \"http@1.0.7-pre.2\",\n        \"service-configuration@1.0.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"templating@1.0.8-pre.2\",\n        \"random@1.0.1-pre.2\"\n      ],\n      \"github 1.1.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"oauth2@1.1.1-rc.0\",\n        \"oauth@1.1.1-rc.0\",\n        \"http@1.0.7-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"templating@1.0.8-rc.0\",\n        \"random@1.0.1-rc.0\"\n      ],\n      \"github 1.1.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"oauth2@1.1.1-win.0\",\n        \"oauth@1.1.2-win.0\",\n        \"http@1.0.8-win.0\",\n        \"service-configuration@1.0.2-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"templating@1.0.9-win.0\",\n        \"random@1.0.1-win.0\"\n      ],\n      \"github 1.1.1\": [\n        \"meteor@1.1.2\",\n        \"oauth2@1.1.1\",\n        \"oauth@1.1.1\",\n        \"http@1.0.7\",\n        \"service-configuration@1.0.2\",\n        \"underscore@1.0.1\",\n        \"templating@1.0.8\",\n        \"random@1.0.1\"\n      ],\n      \"github 1.1.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"oauth2@1.1.2-ipc.0\",\n        \"oauth@1.1.3-ipc.0\",\n        \"http@1.0.9-ipc.0\",\n        \"service-configuration@1.0.3-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"templating@1.0.10-ipc.0\",\n        \"random@1.0.2-ipc.0\"\n      ],\n      \"github 1.1.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"oauth2@1.1.2-rc.1\",\n        \"oauth@1.1.3-rc.1\",\n        \"http@1.0.9-rc.1\",\n        \"service-configuration@1.0.3-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"templating@1.0.10-rc.1\",\n        \"random@1.0.2-rc.1\"\n      ],\n      \"github 1.1.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"oauth2@1.1.2-slava.0\",\n        \"oauth@1.1.3-slava.0\",\n        \"http@1.0.9-slava.0\",\n        \"service-configuration@1.0.3-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"templating@1.0.10-slava.0\",\n        \"random@1.0.2-slava.0\"\n      ],\n      \"github 1.1.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"oauth2@1.1.2-win.0\",\n        \"oauth@1.1.3-win.0\",\n        \"http@1.0.9-win.0\",\n        \"service-configuration@1.0.3-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"templating@1.0.10-win.0\",\n        \"random@1.0.2-win.0\"\n      ],\n      \"github 1.1.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"oauth2@1.1.2-winr.0\",\n        \"oauth@1.1.3-winr.0\",\n        \"http@1.0.9-winr.0\",\n        \"service-configuration@1.0.3-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"templating@1.0.10-winr.0\",\n        \"random@1.0.2-winr.0\"\n      ],\n      \"github 1.1.2\": [\n        \"meteor@1.1.4\",\n        \"oauth2@1.1.2\",\n        \"oauth@1.1.3\",\n        \"http@1.0.9\",\n        \"service-configuration@1.0.3\",\n        \"underscore@1.0.2\",\n        \"templating@1.0.10\",\n        \"random@1.0.2\"\n      ],\n      \"github 1.1.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"oauth2@1.1.3-eachin.43\",\n        \"oauth@1.1.4-eachin.43\",\n        \"http@1.0.10-eachin.43\",\n        \"service-configuration@1.0.4-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"templating@1.0.12-eachin.43\",\n        \"random@1.0.3-eachin.43\"\n      ],\n      \"github 1.1.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"oauth2@1.1.3-githubble.0\",\n        \"oauth@1.1.4-githubble.0\",\n        \"http@1.0.10-githubble.0\",\n        \"service-configuration@1.0.4-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"templating@1.0.12-githubble.0\",\n        \"random@1.0.3-githubble.0\"\n      ],\n      \"github 1.1.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"oauth2@1.1.3-githubble.2\",\n        \"oauth@1.1.4-githubble.2\",\n        \"http@1.0.10-githubble.2\",\n        \"service-configuration@1.0.4-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"templating@1.0.12-githubble.2\",\n        \"random@1.0.3-githubble.2\"\n      ],\n      \"github 1.1.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"oauth2@1.1.3-githubble.42\",\n        \"oauth@1.1.4-githubble.42\",\n        \"http@1.0.10-githubble.42\",\n        \"service-configuration@1.0.4-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"templating@1.0.12-githubble.42\",\n        \"random@1.0.3-githubble.42\"\n      ],\n      \"github 1.1.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"oauth2@1.1.3-githubble.43\",\n        \"oauth@1.1.4-githubble.43\",\n        \"http@1.0.10-githubble.43\",\n        \"service-configuration@1.0.4-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"templating@1.0.12-githubble.43\",\n        \"random@1.0.3-githubble.43\"\n      ],\n      \"github 1.1.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"oauth2@1.1.3-rc.0\",\n        \"oauth@1.1.4-rc.0\",\n        \"http@1.1.0-rc.0\",\n        \"service-configuration@1.0.4-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"templating@1.1.0-rc.0\",\n        \"random@1.0.3-rc.0\"\n      ],\n      \"github 1.1.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"oauth2@1.1.3-winr.0\",\n        \"oauth@1.1.4-winr.0\",\n        \"http@1.0.10-winr.0\",\n        \"service-configuration@1.0.4-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"templating@1.0.11-winr.0\",\n        \"random@1.0.3-winr.0\"\n      ],\n      \"github 1.1.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"oauth2@1.1.3-winr.1\",\n        \"oauth@1.1.4-winr.1\",\n        \"http@1.0.10-winr.1\",\n        \"service-configuration@1.0.4-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"templating@1.0.11-winr.1\",\n        \"random@1.0.3-winr.1\"\n      ],\n      \"github 1.1.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"oauth2@1.1.3-winr.2\",\n        \"oauth@1.1.4-winr.2\",\n        \"http@1.0.10-winr.4\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"templating@1.0.11-winr.4\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"github 1.1.3-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"oauth2@1.1.3-winr.2\",\n        \"oauth@1.1.4-winr.3\",\n        \"http@1.0.11-winr.5\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"templating@1.0.12-winr.7\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"geojson-utils 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"geojson-utils 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"geojson-utils 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"geojson-utils 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"geojson-utils 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"geojson-utils 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"geojson-utils 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"geojson-utils 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"geojson-utils 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"geojson-utils 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"geojson-utils 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"geojson-utils 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"geojson-utils 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"geojson-utils 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"geojson-utils 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"geojson-utils 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"geojson-utils 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"geojson-utils 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"geojson-utils 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"geojson-utils 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"geojson-utils 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"geojson-utils 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"geojson-utils 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"geojson-utils 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"force-ssl 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"webapp@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"ddp@10.0.0-glasser.isopacket.0\"\n      ],\n      \"force-ssl 1.0.0\": [\n        \"livedata@1.0.7\",\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.2\"\n      ],\n      \"force-ssl 1.0.1-rc0\": [\n        \"meteor\",\n        \"webapp\",\n        \"underscore\",\n        \"ddp\"\n      ],\n      \"force-ssl 1.0.1\": [\n        \"ddp@1.0.8\",\n        \"meteor@1.0.3\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.3\"\n      ],\n      \"force-ssl 1.0.2-pre.0\": [\n        \"meteor\",\n        \"webapp\",\n        \"underscore\",\n        \"ddp\"\n      ],\n      \"force-ssl 1.0.2-pre.1\": [\n        \"meteor\",\n        \"webapp\",\n        \"underscore\",\n        \"ddp\"\n      ],\n      \"force-ssl 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"webapp@1.1.3-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"ddp@1.0.10-pre.2\"\n      ],\n      \"force-ssl 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"webapp@1.1.3-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"ddp@1.0.10-rc.0\"\n      ],\n      \"force-ssl 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"webapp@1.1.4-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"ddp@1.0.11-win.0\"\n      ],\n      \"force-ssl 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"webapp@1.1.3\",\n        \"underscore@1.0.1\",\n        \"ddp@1.0.10\"\n      ],\n      \"force-ssl 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"webapp@1.1.5-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"ddp@1.0.12-ipc.0\"\n      ],\n      \"force-ssl 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"webapp@1.1.5-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"ddp@1.0.13-rc.1\"\n      ],\n      \"force-ssl 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"webapp@1.1.5-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"ddp@1.0.13-slava.0\"\n      ],\n      \"force-ssl 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"webapp@1.1.5-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"ddp@1.0.12-win.0\"\n      ],\n      \"force-ssl 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"webapp@1.1.5-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"ddp@1.0.13-winr.0\"\n      ],\n      \"force-ssl 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"webapp@1.1.5\",\n        \"underscore@1.0.2\",\n        \"ddp@1.0.13\"\n      ],\n      \"force-ssl 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"webapp@1.1.7-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"ddp@1.0.15-eachin.43\"\n      ],\n      \"force-ssl 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"webapp@1.1.7-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"ddp@1.0.15-githubble.0\"\n      ],\n      \"force-ssl 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"webapp@1.1.7-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"ddp@1.0.15-githubble.2\"\n      ],\n      \"force-ssl 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"webapp@1.1.7-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"ddp@1.0.15-githubble.42\"\n      ],\n      \"force-ssl 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"webapp@1.1.7-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"ddp@1.0.15-githubble.43\"\n      ],\n      \"force-ssl 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"webapp@1.2.0-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"ddp@1.1.0-rc.0\"\n      ],\n      \"force-ssl 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"webapp@1.1.6-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"ddp@1.0.14-winr.0\"\n      ],\n      \"force-ssl 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"webapp@1.1.6-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"ddp@1.0.14-winr.1\"\n      ],\n      \"force-ssl 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"webapp@1.1.6-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"ddp@1.0.14-winr.4\"\n      ],\n      \"fastclick 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"fastclick 1.0.0-cordova1\": [\n        \"meteor@1.1.0\"\n      ],\n      \"fastclick 1.0.0\": [\n        \"meteor@1.1.0\"\n      ],\n      \"fastclick 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"fastclick 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"fastclick 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"fastclick 1.0.1-pre.3\": [\n        \"meteor@1.1.2-pre.3\"\n      ],\n      \"fastclick 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"fastclick 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"fastclick 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"fastclick 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"fastclick 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"fastclick 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"fastclick 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"fastclick 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"fastclick 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"fastclick 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"fastclick 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"fastclick 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"fastclick 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"fastclick 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"fastclick 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"fastclick 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"fastclick 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"fastclick 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"fastclick 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"facts 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"?autopublish@10.0.0-glasser.isopacket.0\",\n        \"ddp@10.0.0-glasser.isopacket.0\",\n        \"templating@10.0.0-glasser.isopacket.0\",\n        \"mongo@10.0.0-glasser.isopacket.0\"\n      ],\n      \"facts 1.0.0\": [\n        \"?autopublish@1.0.0\",\n        \"livedata@1.0.7\",\n        \"meteor@1.0.2\",\n        \"mongo-livedata@1.0.3\",\n        \"templating@1.0.4\",\n        \"underscore@1.0.0\"\n      ],\n      \"facts 1.0.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"?autopublish\",\n        \"livedata\",\n        \"templating\",\n        \"mongo-livedata\"\n      ],\n      \"facts 1.0.1-rc1\": [\n        \"meteor\",\n        \"underscore\",\n        \"?autopublish\",\n        \"ddp\",\n        \"templating\",\n        \"mongo\"\n      ],\n      \"facts 1.0.1\": [\n        \"?autopublish@1.0.0\",\n        \"ddp@1.0.8\",\n        \"meteor@1.0.3\",\n        \"mongo@1.0.4\",\n        \"templating@1.0.5\",\n        \"underscore@1.0.0\"\n      ],\n      \"facts 1.0.2-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"?autopublish\",\n        \"ddp\",\n        \"templating\",\n        \"mongo\"\n      ],\n      \"facts 1.0.2-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"?autopublish\",\n        \"ddp\",\n        \"templating\",\n        \"mongo\"\n      ],\n      \"facts 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"?autopublish@1.0.1-pre.2\",\n        \"ddp@1.0.10-pre.2\",\n        \"templating@1.0.8-pre.2\",\n        \"mongo@1.0.7-pre.2\"\n      ],\n      \"facts 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"ddp@1.0.10-rc.0\",\n        \"templating@1.0.8-rc.0\",\n        \"mongo@1.0.7-rc.0\"\n      ],\n      \"facts 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"?autopublish@1.0.1-win.0\",\n        \"ddp@1.0.11-win.0\",\n        \"templating@1.0.9-win.0\",\n        \"mongo@1.0.8-win.0\"\n      ],\n      \"facts 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"?autopublish@1.0.1\",\n        \"ddp@1.0.10\",\n        \"templating@1.0.8\",\n        \"mongo@1.0.7\"\n      ],\n      \"facts 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"?autopublish@1.0.2-ipc.0\",\n        \"ddp@1.0.12-ipc.0\",\n        \"templating@1.0.10-ipc.0\",\n        \"mongo@1.0.9-ipc.0\"\n      ],\n      \"facts 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"?autopublish@1.0.2-rc.1\",\n        \"ddp@1.0.13-rc.1\",\n        \"templating@1.0.10-rc.1\",\n        \"mongo@1.0.10-rc.1\"\n      ],\n      \"facts 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"?autopublish@1.0.2-slava.0\",\n        \"ddp@1.0.13-slava.0\",\n        \"templating@1.0.10-slava.0\",\n        \"mongo@1.0.10-slava.0\"\n      ],\n      \"facts 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"?autopublish@1.0.2-win.0\",\n        \"ddp@1.0.12-win.0\",\n        \"templating@1.0.10-win.0\",\n        \"mongo@1.0.9-win.0\"\n      ],\n      \"facts 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"?autopublish@1.0.2-winr.0\",\n        \"ddp@1.0.13-winr.0\",\n        \"templating@1.0.10-winr.0\",\n        \"mongo@1.0.10-winr.0\"\n      ],\n      \"facts 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"ddp@1.0.13\",\n        \"templating@1.0.10\",\n        \"mongo@1.0.10\"\n      ],\n      \"facts 1.0.4-blz.0\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"ddp@1.0.15-blz.0\",\n        \"templating@1.0.11\",\n        \"mongo@1.0.11\"\n      ],\n      \"facts 1.0.4-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"?autopublish@1.0.3-eachin.0\",\n        \"ddp@1.0.14-eachin.0\",\n        \"templating@1.0.11-eachin.0\",\n        \"mongo@1.0.12-eachin.0\"\n      ],\n      \"facts 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"?autopublish@1.0.3-eachin.43\",\n        \"ddp@1.0.15-eachin.43\",\n        \"templating@1.0.12-eachin.43\",\n        \"mongo@1.0.12-eachin.45\"\n      ],\n      \"facts 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"?autopublish@1.0.3-githubble.0\",\n        \"ddp@1.0.15-githubble.0\",\n        \"templating@1.0.12-githubble.0\",\n        \"mongo@1.0.12-githubble.0\"\n      ],\n      \"facts 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"?autopublish@1.0.3-githubble.2\",\n        \"ddp@1.0.15-githubble.2\",\n        \"templating@1.0.12-githubble.2\",\n        \"mongo@1.0.12-githubble.2\"\n      ],\n      \"facts 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"?autopublish@1.0.3-githubble.42\",\n        \"ddp@1.0.15-githubble.42\",\n        \"templating@1.0.12-githubble.42\",\n        \"mongo@1.0.12-githubble.42\"\n      ],\n      \"facts 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"?autopublish@1.0.3-githubble.43\",\n        \"ddp@1.0.15-githubble.43\",\n        \"templating@1.0.12-githubble.43\",\n        \"mongo@1.0.12-githubble.43\"\n      ],\n      \"facts 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"?autopublish@1.0.3-rc.0\",\n        \"ddp@1.1.0-rc.0\",\n        \"templating@1.1.0-rc.0\",\n        \"mongo@1.1.0-rc.0\"\n      ],\n      \"facts 1.0.4-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"underscore@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"ddp@1.0.15-vs.1\",\n        \"templating@1.0.12-vs.1\",\n        \"mongo@1.0.12-vs.1\"\n      ],\n      \"facts 1.0.4-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"underscore@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"ddp@1.0.15-vs.2\",\n        \"templating@1.0.12-vs.2\",\n        \"mongo@1.0.12-vs.2\"\n      ],\n      \"facts 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"?autopublish@1.0.3-winr.0\",\n        \"ddp@1.0.14-winr.0\",\n        \"templating@1.0.11-winr.0\",\n        \"mongo@1.0.11-winr.0\"\n      ],\n      \"facts 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"?autopublish@1.0.3-winr.1\",\n        \"ddp@1.0.14-winr.1\",\n        \"templating@1.0.11-winr.1\",\n        \"mongo@1.0.11-winr.1\"\n      ],\n      \"facts 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"ddp@1.0.14-winr.4\",\n        \"templating@1.0.11-winr.4\",\n        \"mongo@1.0.12-winr.2\"\n      ],\n      \"facts 1.0.4-winr.3\": [\n        \"meteor@1.1.5-winr.5\",\n        \"underscore@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"ddp@1.0.14-winr.5\",\n        \"templating@1.0.11-winr.6\",\n        \"mongo@1.0.12-winr.4\"\n      ],\n      \"facts 1.0.4-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"ddp@1.0.15-winr.6\",\n        \"templating@1.0.12-winr.7\",\n        \"mongo@1.0.12-winr.6\"\n      ],\n      \"facebook 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"oauth2@10.0.0-glasser.isopacket.0\",\n        \"oauth@10.0.0-glasser.isopacket.0\",\n        \"http@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"service-configuration@10.0.0-glasser.isopacket.0\",\n        \"templating@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\"\n      ],\n      \"facebook 1.0.0\": [\n        \"http@1.0.2\",\n        \"meteor@1.0.2\",\n        \"oauth@1.0.0\",\n        \"oauth2@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.0\",\n        \"templating@1.0.4\",\n        \"underscore@1.0.0\"\n      ],\n      \"facebook 1.0.1-glasser1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"facebook 1.0.1-rc0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"facebook 1.0.1\": [\n        \"http@1.0.4\",\n        \"meteor@1.0.3\",\n        \"oauth@1.0.1\",\n        \"oauth2@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.5\",\n        \"underscore@1.0.0\"\n      ],\n      \"facebook 1.0.2-ekate\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"facebook 1.1.0-rc0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"facebook 1.1.0\": [\n        \"http@1.0.5\",\n        \"meteor@1.1.0\",\n        \"oauth@1.1.0\",\n        \"oauth2@1.1.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"templating@1.0.6\",\n        \"underscore@1.0.0\"\n      ],\n      \"facebook 1.1.1-pre.0\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"facebook 1.1.1-pre.1\": [\n        \"meteor\",\n        \"oauth2\",\n        \"oauth\",\n        \"http\",\n        \"underscore\",\n        \"service-configuration\",\n        \"templating\",\n        \"random\"\n      ],\n      \"facebook 1.1.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"oauth2@1.1.1-pre.2\",\n        \"oauth@1.1.1-pre.2\",\n        \"http@1.0.7-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"service-configuration@1.0.2-pre.2\",\n        \"templating@1.0.8-pre.2\",\n        \"random@1.0.1-pre.2\"\n      ],\n      \"facebook 1.1.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"oauth2@1.1.1-rc.0\",\n        \"oauth@1.1.1-rc.0\",\n        \"http@1.0.7-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"templating@1.0.8-rc.0\",\n        \"random@1.0.1-rc.0\"\n      ],\n      \"facebook 1.1.1\": [\n        \"meteor@1.1.2\",\n        \"oauth2@1.1.1\",\n        \"oauth@1.1.1\",\n        \"http@1.0.7\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"templating@1.0.8\",\n        \"random@1.0.1\"\n      ],\n      \"facebook 1.1.2-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"oauth2@1.1.1\",\n        \"oauth@1.1.2-rc.0\",\n        \"http@1.0.8-rc.6\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"templating@1.0.9-rc.2\",\n        \"random@1.0.1\"\n      ],\n      \"facebook 1.1.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"oauth2@1.1.1-win.0\",\n        \"oauth@1.1.2-win.0\",\n        \"http@1.0.8-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"service-configuration@1.0.2-win.0\",\n        \"templating@1.0.9-win.0\",\n        \"random@1.0.1-win.0\"\n      ],\n      \"facebook 1.1.2\": [\n        \"meteor@1.1.3\",\n        \"oauth2@1.1.1\",\n        \"oauth@1.1.2\",\n        \"http@1.0.8\",\n        \"underscore@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"templating@1.0.9\",\n        \"random@1.0.1\"\n      ],\n      \"facebook 1.1.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"oauth2@1.1.2-ipc.0\",\n        \"oauth@1.1.3-ipc.0\",\n        \"http@1.0.9-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"service-configuration@1.0.3-ipc.0\",\n        \"templating@1.0.10-ipc.0\",\n        \"random@1.0.2-ipc.0\"\n      ],\n      \"facebook 1.1.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"oauth2@1.1.2-rc.1\",\n        \"oauth@1.1.3-rc.1\",\n        \"http@1.0.9-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"service-configuration@1.0.3-rc.1\",\n        \"templating@1.0.10-rc.1\",\n        \"random@1.0.2-rc.1\"\n      ],\n      \"facebook 1.1.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"oauth2@1.1.2-slava.0\",\n        \"oauth@1.1.3-slava.0\",\n        \"http@1.0.9-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"service-configuration@1.0.3-slava.0\",\n        \"templating@1.0.10-slava.0\",\n        \"random@1.0.2-slava.0\"\n      ],\n      \"facebook 1.1.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"oauth2@1.1.2-win.0\",\n        \"oauth@1.1.3-win.0\",\n        \"http@1.0.9-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"service-configuration@1.0.3-win.0\",\n        \"templating@1.0.10-win.0\",\n        \"random@1.0.2-win.0\"\n      ],\n      \"facebook 1.1.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"oauth2@1.1.2-winr.0\",\n        \"oauth@1.1.3-winr.0\",\n        \"http@1.0.9-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"service-configuration@1.0.3-winr.0\",\n        \"templating@1.0.10-winr.0\",\n        \"random@1.0.2-winr.0\"\n      ],\n      \"facebook 1.1.3\": [\n        \"meteor@1.1.4\",\n        \"oauth2@1.1.2\",\n        \"oauth@1.1.3\",\n        \"http@1.0.9\",\n        \"underscore@1.0.2\",\n        \"service-configuration@1.0.3\",\n        \"templating@1.0.10\",\n        \"random@1.0.2\"\n      ],\n      \"facebook 1.1.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"oauth2@1.1.3-eachin.43\",\n        \"oauth@1.1.4-eachin.43\",\n        \"http@1.0.10-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"service-configuration@1.0.4-eachin.43\",\n        \"templating@1.0.12-eachin.43\",\n        \"random@1.0.3-eachin.43\"\n      ],\n      \"facebook 1.1.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"oauth2@1.1.3-githubble.0\",\n        \"oauth@1.1.4-githubble.0\",\n        \"http@1.0.10-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"service-configuration@1.0.4-githubble.0\",\n        \"templating@1.0.12-githubble.0\",\n        \"random@1.0.3-githubble.0\"\n      ],\n      \"facebook 1.1.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"oauth2@1.1.3-githubble.2\",\n        \"oauth@1.1.4-githubble.2\",\n        \"http@1.0.10-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"service-configuration@1.0.4-githubble.2\",\n        \"templating@1.0.12-githubble.2\",\n        \"random@1.0.3-githubble.2\"\n      ],\n      \"facebook 1.1.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"oauth2@1.1.3-githubble.42\",\n        \"oauth@1.1.4-githubble.42\",\n        \"http@1.0.10-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"service-configuration@1.0.4-githubble.42\",\n        \"templating@1.0.12-githubble.42\",\n        \"random@1.0.3-githubble.42\"\n      ],\n      \"facebook 1.1.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"oauth2@1.1.3-githubble.43\",\n        \"oauth@1.1.4-githubble.43\",\n        \"http@1.0.10-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"service-configuration@1.0.4-githubble.43\",\n        \"templating@1.0.12-githubble.43\",\n        \"random@1.0.3-githubble.43\"\n      ],\n      \"facebook 1.1.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"oauth2@1.1.3-rc.0\",\n        \"oauth@1.1.4-rc.0\",\n        \"http@1.1.0-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"service-configuration@1.0.4-rc.0\",\n        \"templating@1.1.0-rc.0\",\n        \"random@1.0.3-rc.0\"\n      ],\n      \"facebook 1.1.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"oauth2@1.1.3-winr.0\",\n        \"oauth@1.1.4-winr.0\",\n        \"http@1.0.10-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"service-configuration@1.0.4-winr.0\",\n        \"templating@1.0.11-winr.0\",\n        \"random@1.0.3-winr.0\"\n      ],\n      \"facebook 1.1.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"oauth2@1.1.3-winr.1\",\n        \"oauth@1.1.4-winr.1\",\n        \"http@1.0.10-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"service-configuration@1.0.4-winr.1\",\n        \"templating@1.0.11-winr.1\",\n        \"random@1.0.3-winr.1\"\n      ],\n      \"facebook 1.1.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"oauth2@1.1.3-winr.2\",\n        \"oauth@1.1.4-winr.2\",\n        \"http@1.0.10-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"templating@1.0.11-winr.4\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"facebook 1.1.4-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"oauth2@1.1.3-winr.2\",\n        \"oauth@1.1.4-winr.3\",\n        \"http@1.0.11-winr.5\",\n        \"underscore@1.0.3-winr.2\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"templating@1.0.12-winr.7\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"email 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"application-configuration@10.0.0-glasser.isopacket.0\"\n      ],\n      \"email 1.0.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"application-configuration\"\n      ],\n      \"email 1.0.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"application-configuration\"\n      ],\n      \"email 1.0.2\": [\n        \"application-configuration@1.0.0\",\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"email 1.0.3-ekate\": [\n        \"meteor\",\n        \"underscore\",\n        \"application-configuration\"\n      ],\n      \"email 1.0.3-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"application-configuration\"\n      ],\n      \"email 1.0.3\": [\n        \"application-configuration@1.0.2\",\n        \"meteor@1.1.1\",\n        \"underscore@1.0.0\"\n      ],\n      \"email 1.0.4-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"application-configuration\"\n      ],\n      \"email 1.0.4-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"application-configuration\"\n      ],\n      \"email 1.0.4-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"application-configuration@1.0.3-pre.2\"\n      ],\n      \"email 1.0.4-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"application-configuration@1.0.3-rc.0\"\n      ],\n      \"email 1.0.4-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"application-configuration@1.0.3-win.0\"\n      ],\n      \"email 1.0.4\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"application-configuration@1.0.3\"\n      ],\n      \"email 1.0.5-blz.0\": [\n        \"meteor@1.1.5-blz.0\",\n        \"underscore@1.0.2\"\n      ],\n      \"email 1.0.5-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"application-configuration@1.0.4-ipc.0\"\n      ],\n      \"email 1.0.5-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"application-configuration@1.0.4-rc.1\"\n      ],\n      \"email 1.0.5-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"application-configuration@1.0.4-slava.0\"\n      ],\n      \"email 1.0.5-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"application-configuration@1.0.4-win.0\"\n      ],\n      \"email 1.0.5-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"application-configuration@1.0.4-winr.0\"\n      ],\n      \"email 1.0.5\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"application-configuration@1.0.4\"\n      ],\n      \"email 1.0.6-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\"\n      ],\n      \"email 1.0.6-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\"\n      ],\n      \"email 1.0.6-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\"\n      ],\n      \"email 1.0.6-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\"\n      ],\n      \"email 1.0.6-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\"\n      ],\n      \"email 1.0.6-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"email 1.0.6-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"underscore@1.0.2\"\n      ],\n      \"email 1.0.6-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"underscore@1.0.2\"\n      ],\n      \"email 1.0.6-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"application-configuration@1.0.5-winr.0\"\n      ],\n      \"email 1.0.6-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"application-configuration@1.0.5-winr.1\"\n      ],\n      \"email 1.0.6-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"application-configuration@1.0.5-winr.2\"\n      ],\n      \"email 1.0.6-winr.3\": [\n        \"meteor@1.1.5-winr.5\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"email 1.0.6-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"ejson 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"json@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"base64@10.0.0-glasser.isopacket.0\"\n      ],\n      \"ejson 1.0.0\": [\n        \"json@1.0.0\",\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"ejson 1.0.1-rc0\": [\n        \"meteor\",\n        \"json\",\n        \"underscore\"\n      ],\n      \"ejson 1.0.1\": [\n        \"json@1.0.0\",\n        \"meteor@1.0.3\",\n        \"underscore@1.0.0\"\n      ],\n      \"ejson 1.0.2-ekate\": [\n        \"meteor\",\n        \"json\",\n        \"underscore\"\n      ],\n      \"ejson 1.0.2-rc0\": [\n        \"meteor\",\n        \"json\",\n        \"underscore\",\n        \"base64\"\n      ],\n      \"ejson 1.0.2\": [\n        \"base64@1.0.0\",\n        \"json@1.0.0\",\n        \"meteor@1.1.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"ejson 1.0.3-rc0\": [\n        \"meteor\",\n        \"json\",\n        \"underscore\",\n        \"base64\"\n      ],\n      \"ejson 1.0.3\": [\n        \"base64@1.0.0\",\n        \"json@1.0.0\",\n        \"meteor@1.1.1\",\n        \"underscore@1.0.0\"\n      ],\n      \"ejson 1.0.4-pre.0\": [\n        \"meteor\",\n        \"json\",\n        \"underscore\",\n        \"base64\"\n      ],\n      \"ejson 1.0.4-pre.1\": [\n        \"meteor\",\n        \"json\",\n        \"underscore\",\n        \"base64\"\n      ],\n      \"ejson 1.0.4-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"json@1.0.1-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"base64@1.0.1-pre.2\"\n      ],\n      \"ejson 1.0.4-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"json@1.0.1-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"base64@1.0.1-rc.0\"\n      ],\n      \"ejson 1.0.4-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"json@1.0.1-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"base64@1.0.1-win.0\"\n      ],\n      \"ejson 1.0.4\": [\n        \"meteor@1.1.2\",\n        \"json@1.0.1\",\n        \"underscore@1.0.1\",\n        \"base64@1.0.1\"\n      ],\n      \"ejson 1.0.5-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"json@1.0.2-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"base64@1.0.2-ipc.0\"\n      ],\n      \"ejson 1.0.5-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"json@1.0.2-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"base64@1.0.2-rc.1\"\n      ],\n      \"ejson 1.0.5-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"json@1.0.2-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"base64@1.0.2-slava.0\"\n      ],\n      \"ejson 1.0.5-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"json@1.0.2-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"base64@1.0.2-win.0\"\n      ],\n      \"ejson 1.0.5-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"json@1.0.2-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"base64@1.0.2-winr.0\"\n      ],\n      \"ejson 1.0.5\": [\n        \"meteor@1.1.4\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"base64@1.0.2\"\n      ],\n      \"ejson 1.0.6-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"json@1.0.3-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"base64@1.0.3-eachin.0\"\n      ],\n      \"ejson 1.0.6-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"json@1.0.3-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"base64@1.0.3-eachin.43\"\n      ],\n      \"ejson 1.0.6-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"json@1.0.3-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"base64@1.0.3-githubble.0\"\n      ],\n      \"ejson 1.0.6-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"json@1.0.3-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"base64@1.0.3-githubble.2\"\n      ],\n      \"ejson 1.0.6-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"json@1.0.3-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"base64@1.0.3-githubble.42\"\n      ],\n      \"ejson 1.0.6-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"json@1.0.3-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"base64@1.0.3-githubble.43\"\n      ],\n      \"ejson 1.0.6-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"json@1.0.3-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"base64@1.0.3-rc.0\"\n      ],\n      \"ejson 1.0.6-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"json@1.0.3-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"base64@1.0.3-winr.0\"\n      ],\n      \"ejson 1.0.6-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"json@1.0.3-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"base64@1.0.3-winr.1\"\n      ],\n      \"ejson 1.0.6-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"base64@1.0.3-winr.2\"\n      ],\n      \"disable-oplog 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"disable-oplog 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"disable-oplog 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"disable-oplog 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"disable-oplog 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"disable-oplog 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"disable-oplog 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"disable-oplog 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"disable-oplog 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"disable-oplog 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"disable-oplog 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"disable-oplog 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"disable-oplog 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"disable-oplog 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"disable-oplog 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"disable-oplog 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"disable-oplog 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"disable-oplog 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"disable-oplog 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"disable-oplog 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"disable-oplog 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"disable-oplog 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"disable-oplog 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"disable-oplog 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"deps 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\"\n      ],\n      \"deps 1.0.0\": [\n        \"meteor\"\n      ],\n      \"deps 1.0.1\": [\n        \"meteor@1.0.2\"\n      ],\n      \"deps 1.0.2-rc0\": [\n        \"meteor\",\n        \"tracker\"\n      ],\n      \"deps 1.0.2-rc1\": [\n        \"meteor\",\n        \"tracker\"\n      ],\n      \"deps 1.0.2\": [\n        \"meteor@1.0.3\",\n        \"tracker@1.0.2\"\n      ],\n      \"deps 1.0.3\": [\n        \"meteor@1.0.3\",\n        \"tracker@1.0.2\"\n      ],\n      \"deps 1.0.4-rc0\": [\n        \"meteor\",\n        \"tracker\"\n      ],\n      \"deps 1.0.4\": [\n        \"meteor@1.1.1\",\n        \"tracker@1.0.2\"\n      ],\n      \"deps 1.0.5-pre.0\": [\n        \"meteor\",\n        \"tracker\"\n      ],\n      \"deps 1.0.5-pre.1\": [\n        \"meteor\",\n        \"tracker\"\n      ],\n      \"deps 1.0.5-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"tracker@1.0.3-pre.2\"\n      ],\n      \"deps 1.0.5-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"tracker@1.0.3-rc.0\"\n      ],\n      \"deps 1.0.5-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"tracker@1.0.3-win.0\"\n      ],\n      \"deps 1.0.5\": [\n        \"meteor@1.1.2\",\n        \"tracker@1.0.3\"\n      ],\n      \"deps 1.0.6-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"tracker@1.0.4-ipc.0\"\n      ],\n      \"deps 1.0.6-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"tracker@1.0.4-rc.1\"\n      ],\n      \"deps 1.0.6-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"tracker@1.0.4-slava.0\"\n      ],\n      \"deps 1.0.6-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"tracker@1.0.4-win.0\"\n      ],\n      \"deps 1.0.6-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"tracker@1.0.4-winr.0\"\n      ],\n      \"deps 1.0.6\": [\n        \"meteor@1.1.4\",\n        \"tracker@1.0.4\"\n      ],\n      \"deps 1.0.7-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"tracker@1.0.5-eachin.0\"\n      ],\n      \"deps 1.0.7-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"tracker@1.0.5-eachin.43\"\n      ],\n      \"deps 1.0.7-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"tracker@1.0.5-githubble.0\"\n      ],\n      \"deps 1.0.7-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"tracker@1.0.5-githubble.2\"\n      ],\n      \"deps 1.0.7-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"tracker@1.0.5-githubble.42\"\n      ],\n      \"deps 1.0.7-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"tracker@1.0.5-githubble.43\"\n      ],\n      \"deps 1.0.7-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"tracker@1.0.6-rc.0\"\n      ],\n      \"deps 1.0.7-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"tracker@1.0.5-winr.0\"\n      ],\n      \"deps 1.0.7-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"tracker@1.0.5-winr.1\"\n      ],\n      \"deps 1.0.7-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"tracker@1.0.5-winr.4\"\n      ],\n      \"ddp 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"check@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\",\n        \"json@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\",\n        \"logging@10.0.0-glasser.isopacket.0\",\n        \"retry@10.0.0-glasser.isopacket.0\",\n        \"?webapp@10.0.0-glasser.isopacket.0\",\n        \"?routepolicy@10.0.0-glasser.isopacket.0\",\n        \"?audit-argument-checks@10.0.0-glasser.isopacket.0\",\n        \"?autopublish@10.0.0-glasser.isopacket.0\",\n        \"?facts@10.0.0-glasser.isopacket.0\",\n        \"callback-hook@10.0.0-glasser.isopacket.0\",\n        \"minimongo@10.0.0-glasser.isopacket.0\",\n        \"?reload@10.0.0-glasser.isopacket.0\"\n      ],\n      \"ddp 1.0.1-ekate\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"tracker\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"ddp 1.0.8-rc0\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"tracker\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"ddp 1.0.8\": [\n        \"?audit-argument-checks@1.0.0\",\n        \"?autopublish@1.0.0\",\n        \"callback-hook@1.0.0\",\n        \"check@1.0.0\",\n        \"ejson@1.0.1\",\n        \"?facts@1.0.1\",\n        \"json@1.0.0\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.3\",\n        \"minimongo@1.0.2\",\n        \"random@1.0.0\",\n        \"?reload@1.0.1\",\n        \"retry@1.0.0\",\n        \"?routepolicy@1.0.0\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\",\n        \"?webapp@1.0.3\"\n      ],\n      \"ddp 1.0.9-rc0\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"tracker\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"ddp 1.0.9\": [\n        \"?audit-argument-checks@1.0.0\",\n        \"?autopublish@1.0.0\",\n        \"callback-hook@1.0.0\",\n        \"check@1.0.1\",\n        \"ejson@1.0.3\",\n        \"?facts@1.0.1\",\n        \"json@1.0.0\",\n        \"logging@1.0.3\",\n        \"meteor@1.1.1\",\n        \"minimongo@1.0.3\",\n        \"random@1.0.0\",\n        \"?reload@1.1.0\",\n        \"retry@1.0.0\",\n        \"?routepolicy@1.0.1\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\",\n        \"?webapp@1.1.2\"\n      ],\n      \"ddp 1.0.10-nim.0\": [\n        \"meteor@1.1.2-nim.0\",\n        \"check@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"json@1.0.1-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"logging@1.0.4-rc.0\",\n        \"retry@1.0.1-rc.0\",\n        \"?webapp@1.1.3-nim.0\",\n        \"?routepolicy@1.0.2-rc.0\",\n        \"?audit-argument-checks@1.0.1-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"?facts@1.0.2-rc.0\",\n        \"callback-hook@1.0.1-rc.0\",\n        \"minimongo@1.0.4-rc.0\",\n        \"?reload@1.1.1-rc.0\"\n      ],\n      \"ddp 1.0.10-pre.0\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"tracker\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"ddp 1.0.10-pre.1\": [\n        \"meteor\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"json\",\n        \"underscore\",\n        \"tracker\",\n        \"logging\",\n        \"retry\",\n        \"?webapp\",\n        \"?routepolicy\",\n        \"?audit-argument-checks\",\n        \"?autopublish\",\n        \"?facts\",\n        \"callback-hook\",\n        \"minimongo\",\n        \"?reload\"\n      ],\n      \"ddp 1.0.10-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"check@1.0.2-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"ejson@1.0.4-pre.2\",\n        \"json@1.0.1-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"logging@1.0.4-pre.2\",\n        \"retry@1.0.1-pre.2\",\n        \"?webapp@1.1.3-pre.2\",\n        \"?routepolicy@1.0.2-pre.2\",\n        \"?audit-argument-checks@1.0.1-pre.2\",\n        \"?autopublish@1.0.1-pre.2\",\n        \"?facts@1.0.2-pre.2\",\n        \"callback-hook@1.0.1-pre.2\",\n        \"minimongo@1.0.4-pre.3\",\n        \"?reload@1.1.1-pre.2\"\n      ],\n      \"ddp 1.0.10-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"json@1.0.1-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"logging@1.0.4-rc.0\",\n        \"retry@1.0.1-rc.0\",\n        \"?webapp@1.1.3-rc.0\",\n        \"?routepolicy@1.0.2-rc.0\",\n        \"?audit-argument-checks@1.0.1-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"?facts@1.0.2-rc.0\",\n        \"callback-hook@1.0.1-rc.0\",\n        \"minimongo@1.0.4-rc.0\",\n        \"?reload@1.1.1-rc.0\"\n      ],\n      \"ddp 1.0.10-rc.1\": [\n        \"meteor@1.1.2-ekate.1\",\n        \"check@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"json@1.0.1-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"logging@1.0.4-rc.0\",\n        \"retry@1.0.1-rc.0\",\n        \"?webapp@1.1.3-rc.1\",\n        \"?routepolicy@1.0.2-rc.0\",\n        \"?audit-argument-checks@1.0.1-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"?facts@1.0.2-rc.0\",\n        \"callback-hook@1.0.1-rc.0\",\n        \"minimongo@1.0.4-rc.0\",\n        \"?reload@1.1.1-rc.0\"\n      ],\n      \"ddp 1.0.10-rc.2\": [\n        \"meteor@1.1.2-rc.2\",\n        \"check@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"json@1.0.1-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"logging@1.0.4-rc.0\",\n        \"retry@1.0.1-rc.0\",\n        \"?webapp@1.1.3-rc.2\",\n        \"?routepolicy@1.0.2-rc.0\",\n        \"?audit-argument-checks@1.0.1-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"?facts@1.0.2-rc.0\",\n        \"callback-hook@1.0.1-rc.0\",\n        \"minimongo@1.0.4-rc.0\",\n        \"?reload@1.1.1-rc.0\"\n      ],\n      \"ddp 1.0.10-rc.3\": [\n        \"meteor@1.1.2-rc.3\",\n        \"check@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"json@1.0.1-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"logging@1.0.4-rc.0\",\n        \"retry@1.0.1-rc.0\",\n        \"?webapp@1.1.3-rc.2\",\n        \"?routepolicy@1.0.2-rc.0\",\n        \"?audit-argument-checks@1.0.1-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"?facts@1.0.2-rc.0\",\n        \"callback-hook@1.0.1-rc.0\",\n        \"minimongo@1.0.4-rc.0\",\n        \"?reload@1.1.1-rc.0\"\n      ],\n      \"ddp 1.0.10-refreshpolicy.1\": [\n        \"meteor@1.1.2-refreshpolicy.1\",\n        \"check@1.0.2\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"json@1.0.1\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"logging@1.0.4\",\n        \"retry@1.0.1\",\n        \"?webapp@1.1.3\",\n        \"?routepolicy@1.0.2\",\n        \"?audit-argument-checks@1.0.1\",\n        \"?autopublish@1.0.1\",\n        \"?facts@1.0.2\",\n        \"callback-hook@1.0.1\",\n        \"minimongo@1.0.4-refreshpolicy.1\",\n        \"?reload@1.1.1\"\n      ],\n      \"ddp 1.0.10\": [\n        \"meteor@1.1.2\",\n        \"check@1.0.2\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"json@1.0.1\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"logging@1.0.4\",\n        \"retry@1.0.1\",\n        \"?webapp@1.1.3\",\n        \"?routepolicy@1.0.2\",\n        \"?audit-argument-checks@1.0.1\",\n        \"?autopublish@1.0.1\",\n        \"?facts@1.0.2\",\n        \"callback-hook@1.0.1\",\n        \"minimongo@1.0.4\",\n        \"?reload@1.1.1\"\n      ],\n      \"ddp 1.0.11-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"check@1.0.2\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"json@1.0.1\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"logging@1.0.5-rc.0\",\n        \"retry@1.0.1\",\n        \"?webapp@1.1.4-rc.0\",\n        \"?routepolicy@1.0.2\",\n        \"?audit-argument-checks@1.0.1\",\n        \"?autopublish@1.0.1\",\n        \"?facts@1.0.2\",\n        \"callback-hook@1.0.1\",\n        \"minimongo@1.0.5-rc.0\",\n        \"?reload@1.1.1\"\n      ],\n      \"ddp 1.0.11-rc.1\": [\n        \"meteor@1.1.3-rc.0\",\n        \"check@1.0.2\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"json@1.0.1\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"logging@1.0.5-rc.0\",\n        \"retry@1.0.1\",\n        \"?webapp@1.1.4-rc.1\",\n        \"?routepolicy@1.0.2\",\n        \"?audit-argument-checks@1.0.1\",\n        \"?autopublish@1.0.1\",\n        \"?facts@1.0.2\",\n        \"callback-hook@1.0.1\",\n        \"minimongo@1.0.5-rc.0\",\n        \"?reload@1.1.1\"\n      ],\n      \"ddp 1.0.11-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"check@1.0.2-win.0\",\n        \"random@1.0.1-win.0\",\n        \"ejson@1.0.4-win.0\",\n        \"json@1.0.1-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"tracker@1.0.3-win.0\",\n        \"logging@1.0.5-win.0\",\n        \"retry@1.0.1-win.0\",\n        \"?webapp@1.1.4-win.0\",\n        \"?routepolicy@1.0.2-win.0\",\n        \"?audit-argument-checks@1.0.1-win.0\",\n        \"?autopublish@1.0.1-win.0\",\n        \"?facts@1.0.2-win.0\",\n        \"callback-hook@1.0.1-win.0\",\n        \"minimongo@1.0.5-win.0\",\n        \"?reload@1.1.1-win.0\"\n      ],\n      \"ddp 1.0.11\": [\n        \"meteor@1.1.3\",\n        \"check@1.0.2\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"json@1.0.1\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"logging@1.0.5\",\n        \"retry@1.0.1\",\n        \"?webapp@1.1.4\",\n        \"?routepolicy@1.0.2\",\n        \"?audit-argument-checks@1.0.1\",\n        \"?autopublish@1.0.1\",\n        \"?facts@1.0.2\",\n        \"callback-hook@1.0.1\",\n        \"minimongo@1.0.5\",\n        \"?reload@1.1.1\"\n      ],\n      \"ddp 1.0.12-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"check@1.0.3-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"json@1.0.2-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"logging@1.0.6-ipc.0\",\n        \"retry@1.0.2-ipc.0\",\n        \"?webapp@1.1.5-ipc.0\",\n        \"?routepolicy@1.0.3-ipc.0\",\n        \"?audit-argument-checks@1.0.2-ipc.0\",\n        \"?autopublish@1.0.2-ipc.0\",\n        \"?facts@1.0.3-ipc.0\",\n        \"callback-hook@1.0.2-ipc.0\",\n        \"minimongo@1.0.6-ipc.0\",\n        \"?reload@1.1.2-ipc.0\"\n      ],\n      \"ddp 1.0.12-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"check@1.0.3-win.0\",\n        \"random@1.0.2-win.0\",\n        \"ejson@1.0.5-win.0\",\n        \"json@1.0.2-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"tracker@1.0.4-win.0\",\n        \"logging@1.0.6-win.0\",\n        \"retry@1.0.2-win.0\",\n        \"?webapp@1.1.5-win.0\",\n        \"?routepolicy@1.0.3-win.0\",\n        \"?audit-argument-checks@1.0.2-win.0\",\n        \"?autopublish@1.0.2-win.0\",\n        \"?facts@1.0.3-win.0\",\n        \"callback-hook@1.0.2-win.0\",\n        \"minimongo@1.0.6-win.0\",\n        \"?reload@1.1.2-win.0\"\n      ],\n      \"ddp 1.0.12\": [\n        \"meteor@1.1.3\",\n        \"check@1.0.2\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"json@1.0.1\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"logging@1.0.5\",\n        \"retry@1.0.1\",\n        \"?webapp@1.1.4\",\n        \"?routepolicy@1.0.2\",\n        \"?audit-argument-checks@1.0.1\",\n        \"?autopublish@1.0.1\",\n        \"?facts@1.0.2\",\n        \"callback-hook@1.0.1\",\n        \"minimongo@1.0.5\",\n        \"?reload@1.1.1\"\n      ],\n      \"ddp 1.0.13-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"check@1.0.3-ipc.1\",\n        \"random@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"json@1.0.2-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"logging@1.0.6-ipc.0\",\n        \"retry@1.0.2-ipc.0\",\n        \"?webapp@1.1.5-ipc.1\",\n        \"?routepolicy@1.0.3-ipc.0\",\n        \"?audit-argument-checks@1.0.2-ipc.0\",\n        \"?autopublish@1.0.2-ipc.0\",\n        \"?facts@1.0.3-ipc.0\",\n        \"callback-hook@1.0.2-ipc.0\",\n        \"minimongo@1.0.6-ipc.1\",\n        \"?reload@1.1.2-ipc.0\"\n      ],\n      \"ddp 1.0.13-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"check@1.0.3-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"ejson@1.0.5-rc.1\",\n        \"json@1.0.2-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"tracker@1.0.4-rc.1\",\n        \"logging@1.0.6-rc.1\",\n        \"retry@1.0.2-rc.1\",\n        \"?webapp@1.1.5-rc.1\",\n        \"?routepolicy@1.0.3-rc.1\",\n        \"?audit-argument-checks@1.0.2-rc.1\",\n        \"?autopublish@1.0.2-rc.1\",\n        \"?facts@1.0.3-rc.1\",\n        \"callback-hook@1.0.2-rc.1\",\n        \"minimongo@1.0.6-rc.1\",\n        \"?reload@1.1.2-rc.1\"\n      ],\n      \"ddp 1.0.13-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"check@1.0.3-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"ejson@1.0.5-slava.0\",\n        \"json@1.0.2-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"tracker@1.0.4-slava.0\",\n        \"logging@1.0.6-slava.0\",\n        \"retry@1.0.2-slava.0\",\n        \"?webapp@1.1.5-slava.0\",\n        \"?routepolicy@1.0.3-slava.0\",\n        \"?audit-argument-checks@1.0.2-slava.0\",\n        \"?autopublish@1.0.2-slava.0\",\n        \"?facts@1.0.3-slava.0\",\n        \"callback-hook@1.0.2-slava.0\",\n        \"minimongo@1.0.6-slava.0\",\n        \"?reload@1.1.2-slava.0\"\n      ],\n      \"ddp 1.0.13-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"check@1.0.3-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"ejson@1.0.5-winr.0\",\n        \"json@1.0.2-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"tracker@1.0.4-winr.0\",\n        \"logging@1.0.6-winr.0\",\n        \"retry@1.0.2-winr.0\",\n        \"?webapp@1.1.5-winr.0\",\n        \"?routepolicy@1.0.3-winr.0\",\n        \"?audit-argument-checks@1.0.2-winr.0\",\n        \"?autopublish@1.0.2-winr.0\",\n        \"?facts@1.0.3-winr.0\",\n        \"callback-hook@1.0.2-winr.0\",\n        \"minimongo@1.0.6-winr.0\",\n        \"?reload@1.1.2-winr.0\"\n      ],\n      \"ddp 1.0.13\": [\n        \"meteor@1.1.4\",\n        \"check@1.0.3\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.4\",\n        \"logging@1.0.6\",\n        \"retry@1.0.2\",\n        \"?webapp@1.1.5\",\n        \"?routepolicy@1.0.3\",\n        \"?audit-argument-checks@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"?reload@1.1.2\"\n      ],\n      \"ddp 1.0.14-compression.0\": [\n        \"meteor@1.1.4\",\n        \"check@1.0.3\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.4\",\n        \"logging@1.0.6\",\n        \"retry@1.0.2\",\n        \"?webapp@1.1.5\",\n        \"?routepolicy@1.0.3\",\n        \"?audit-argument-checks@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"?reload@1.1.2\"\n      ],\n      \"ddp 1.0.14-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"logging@1.0.6-winr.2\",\n        \"retry@1.0.3-winr.2\",\n        \"?webapp@1.1.6-eachin.0\",\n        \"?routepolicy@1.0.4-winr.4\",\n        \"?audit-argument-checks@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?facts@1.0.4-winr.3\",\n        \"callback-hook@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.3\",\n        \"?reload@1.1.3-winr.3\"\n      ],\n      \"ddp 1.0.14-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"logging@1.0.6-winr.2\",\n        \"retry@1.0.3-winr.2\",\n        \"?webapp@1.1.6-githubble.0\",\n        \"?routepolicy@1.0.4-winr.4\",\n        \"?audit-argument-checks@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?facts@1.0.4-winr.3\",\n        \"callback-hook@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.3\",\n        \"?reload@1.1.3-winr.3\"\n      ],\n      \"ddp 1.0.14-rc.0\": [\n        \"meteor@1.1.4\",\n        \"check@1.0.4-rc.0\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5-rc.0\",\n        \"logging@1.0.6\",\n        \"retry@1.0.2\",\n        \"?webapp@1.1.6-rc.0\",\n        \"?routepolicy@1.0.4-rc.0\",\n        \"?audit-argument-checks@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"?reload@1.1.2\"\n      ],\n      \"ddp 1.0.14-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"check@1.0.4-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"ejson@1.0.6-winr.0\",\n        \"json@1.0.3-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"tracker@1.0.5-winr.0\",\n        \"logging@1.0.7-winr.0\",\n        \"retry@1.0.3-winr.0\",\n        \"?webapp@1.1.6-winr.0\",\n        \"?routepolicy@1.0.4-winr.0\",\n        \"?audit-argument-checks@1.0.3-winr.0\",\n        \"?autopublish@1.0.3-winr.0\",\n        \"?facts@1.0.4-winr.0\",\n        \"callback-hook@1.0.3-winr.0\",\n        \"minimongo@1.0.7-winr.0\",\n        \"?reload@1.1.3-winr.0\"\n      ],\n      \"ddp 1.0.14-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"check@1.0.4-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\",\n        \"json@1.0.3-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"tracker@1.0.5-winr.1\",\n        \"logging@1.0.7-winr.1\",\n        \"retry@1.0.3-winr.1\",\n        \"?webapp@1.1.6-winr.1\",\n        \"?routepolicy@1.0.4-winr.1\",\n        \"?audit-argument-checks@1.0.3-winr.1\",\n        \"?autopublish@1.0.3-winr.1\",\n        \"?facts@1.0.4-winr.1\",\n        \"callback-hook@1.0.3-winr.1\",\n        \"minimongo@1.0.7-winr.1\",\n        \"?reload@1.1.3-winr.1\"\n      ],\n      \"ddp 1.0.14-winr.2\": [\n        \"meteor@1.1.5-winr.2\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5-winr.2\",\n        \"logging@1.0.6\",\n        \"retry@1.0.2\",\n        \"?webapp@1.1.6-winr.2\",\n        \"?routepolicy@1.0.4-winr.2\",\n        \"?audit-argument-checks@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"?reload@1.1.2\"\n      ],\n      \"ddp 1.0.14-winr.3\": [\n        \"meteor@1.1.5-winr.3\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5-winr.3\",\n        \"logging@1.0.6\",\n        \"retry@1.0.2\",\n        \"?webapp@1.1.6-winr.3\",\n        \"?routepolicy@1.0.4-winr.3\",\n        \"?audit-argument-checks@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"?reload@1.1.2\"\n      ],\n      \"ddp 1.0.14-winr.4\": [\n        \"meteor@1.1.5-winr.4\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"logging@1.0.6-winr.2\",\n        \"retry@1.0.3-winr.2\",\n        \"?webapp@1.1.6-winr.4\",\n        \"?routepolicy@1.0.4-winr.4\",\n        \"?audit-argument-checks@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?facts@1.0.4-winr.2\",\n        \"callback-hook@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.2\",\n        \"?reload@1.1.3-winr.3\"\n      ],\n      \"ddp 1.0.14-winr.5\": [\n        \"meteor@1.1.5-winr.5\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"logging@1.0.6-winr.2\",\n        \"retry@1.0.3-winr.2\",\n        \"?webapp@1.1.6-winr.6\",\n        \"?routepolicy@1.0.4-winr.4\",\n        \"?audit-argument-checks@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?facts@1.0.4-winr.3\",\n        \"callback-hook@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.3\",\n        \"?reload@1.1.3-winr.3\"\n      ],\n      \"ddp 1.0.14\": [\n        \"meteor@1.1.4\",\n        \"check@1.0.4\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5\",\n        \"logging@1.0.6\",\n        \"retry@1.0.2\",\n        \"?webapp@1.1.6\",\n        \"?routepolicy@1.0.4\",\n        \"?audit-argument-checks@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"?reload@1.1.2\"\n      ],\n      \"ddp 1.0.15-blz.0\": [\n        \"meteor@1.1.4\",\n        \"check@1.0.4\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5\",\n        \"logging@1.0.6\",\n        \"retry@1.0.2\",\n        \"?webapp@1.1.6\",\n        \"?routepolicy@1.0.4\",\n        \"?audit-argument-checks@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?facts@1.0.4-blz.0\",\n        \"callback-hook@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"?reload@1.1.2\"\n      ],\n      \"ddp 1.0.15-blz.1\": [\n        \"meteor@1.1.5-blz.0\",\n        \"check@1.0.4\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5\",\n        \"logging@1.0.6\",\n        \"retry@1.0.2\",\n        \"?webapp@1.1.7-blz.0\",\n        \"?routepolicy@1.0.4\",\n        \"?audit-argument-checks@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?facts@1.0.4-blz.0\",\n        \"callback-hook@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"?reload@1.1.2\"\n      ],\n      \"ddp 1.0.15-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"check@1.0.4-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"ejson@1.0.6-eachin.43\",\n        \"json@1.0.3-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"tracker@1.0.5-eachin.43\",\n        \"logging@1.0.6-eachin.43\",\n        \"retry@1.0.3-eachin.43\",\n        \"?webapp@1.1.7-eachin.43\",\n        \"?routepolicy@1.0.4-eachin.43\",\n        \"?audit-argument-checks@1.0.3-eachin.43\",\n        \"?autopublish@1.0.3-eachin.43\",\n        \"?facts@1.0.4-eachin.43\",\n        \"callback-hook@1.0.3-eachin.43\",\n        \"minimongo@1.0.7-eachin.43\",\n        \"?reload@1.1.3-eachin.43\"\n      ],\n      \"ddp 1.0.15-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"logging@1.0.6-winr.2\",\n        \"retry@1.0.3-winr.2\",\n        \"?webapp@1.1.7-githubble.0\",\n        \"?routepolicy@1.0.4-winr.4\",\n        \"?audit-argument-checks@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?facts@1.0.4-winr.3\",\n        \"callback-hook@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.3\",\n        \"?reload@1.1.3-winr.3\"\n      ],\n      \"ddp 1.0.15-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.3-githubble.2\",\n        \"ejson@1.0.6-githubble.2\",\n        \"json@1.0.3-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"tracker@1.0.5-githubble.2\",\n        \"logging@1.0.6-githubble.2\",\n        \"retry@1.0.3-githubble.2\",\n        \"?webapp@1.1.7-githubble.2\",\n        \"?routepolicy@1.0.4-githubble.2\",\n        \"?audit-argument-checks@1.0.3-githubble.2\",\n        \"?autopublish@1.0.3-githubble.2\",\n        \"?facts@1.0.4-githubble.2\",\n        \"callback-hook@1.0.3-githubble.2\",\n        \"minimongo@1.0.7-githubble.2\",\n        \"?reload@1.1.3-githubble.2\"\n      ],\n      \"ddp 1.0.15-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.3-githubble.42\",\n        \"ejson@1.0.6-githubble.42\",\n        \"json@1.0.3-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"tracker@1.0.5-githubble.42\",\n        \"logging@1.0.6-githubble.42\",\n        \"retry@1.0.3-githubble.42\",\n        \"?webapp@1.1.7-githubble.42\",\n        \"?routepolicy@1.0.4-githubble.42\",\n        \"?audit-argument-checks@1.0.3-githubble.42\",\n        \"?autopublish@1.0.3-githubble.42\",\n        \"?facts@1.0.4-githubble.42\",\n        \"callback-hook@1.0.3-githubble.42\",\n        \"minimongo@1.0.7-githubble.42\",\n        \"?reload@1.1.3-githubble.42\"\n      ],\n      \"ddp 1.0.15-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"check@1.0.4-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"ejson@1.0.6-githubble.43\",\n        \"json@1.0.3-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"tracker@1.0.5-githubble.43\",\n        \"logging@1.0.6-githubble.43\",\n        \"retry@1.0.3-githubble.43\",\n        \"?webapp@1.1.7-githubble.43\",\n        \"?routepolicy@1.0.4-githubble.43\",\n        \"?audit-argument-checks@1.0.3-githubble.43\",\n        \"?autopublish@1.0.3-githubble.43\",\n        \"?facts@1.0.4-githubble.43\",\n        \"callback-hook@1.0.3-githubble.43\",\n        \"minimongo@1.0.7-githubble.43\",\n        \"?reload@1.1.3-githubble.43\"\n      ],\n      \"ddp 1.0.15-oplog-backlog.0\": [\n        \"meteor@1.1.5-oplog-backlog.0\",\n        \"check@1.0.4\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5\",\n        \"logging@1.0.6\",\n        \"retry@1.0.2\",\n        \"?webapp@1.1.6\",\n        \"?routepolicy@1.0.4\",\n        \"?audit-argument-checks@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?facts@1.0.3\",\n        \"callback-hook@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"?reload@1.1.2\"\n      ],\n      \"ddp 1.0.15-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"check@1.0.4\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5\",\n        \"logging@1.0.6\",\n        \"retry@1.0.2\",\n        \"?webapp@1.1.7-vs.1\",\n        \"?routepolicy@1.0.4\",\n        \"?audit-argument-checks@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?facts@1.0.4-vs.1\",\n        \"callback-hook@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"?reload@1.1.2\"\n      ],\n      \"ddp 1.0.15-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"check@1.0.4\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"json@1.0.2\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5\",\n        \"logging@1.0.6\",\n        \"retry@1.0.2\",\n        \"?webapp@1.1.7-vs.2\",\n        \"?routepolicy@1.0.4\",\n        \"?audit-argument-checks@1.0.2\",\n        \"?autopublish@1.0.2\",\n        \"?facts@1.0.4-vs.2\",\n        \"callback-hook@1.0.2\",\n        \"minimongo@1.0.6\",\n        \"?reload@1.1.2\"\n      ],\n      \"ddp 1.0.15-winr.5\": [\n        \"meteor@1.1.5-winr.6\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"logging@1.0.6-winr.3\",\n        \"retry@1.0.3-winr.2\",\n        \"?webapp@1.1.7-winr.6\",\n        \"?routepolicy@1.0.4-winr.4\",\n        \"?audit-argument-checks@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?facts@1.0.4-winr.3\",\n        \"callback-hook@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.3\",\n        \"?reload@1.1.3-winr.3\"\n      ],\n      \"ddp 1.0.15-winr.6\": [\n        \"meteor@1.1.5-winr.6\",\n        \"check@1.0.5-win.0\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"json@1.0.3-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.6-winr.4\",\n        \"logging@1.0.7-winr.3\",\n        \"retry@1.0.3-winr.2\",\n        \"?webapp@1.1.7-winr.6\",\n        \"?routepolicy@1.0.5-winr.4\",\n        \"?audit-argument-checks@1.0.3-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?facts@1.0.4-winr.4\",\n        \"callback-hook@1.0.3-winr.2\",\n        \"minimongo@1.0.7-winr.3\",\n        \"?reload@1.1.3-winr.3\"\n      ],\n      \"ddp 1.1.0-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"check@1.0.5-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"ejson@1.0.6-rc.0\",\n        \"json@1.0.3-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"tracker@1.0.6-rc.0\",\n        \"logging@1.0.7-rc.0\",\n        \"retry@1.0.3-rc.0\",\n        \"?webapp@1.2.0-rc.0\",\n        \"?routepolicy@1.0.5-rc.0\",\n        \"?audit-argument-checks@1.0.3-rc.0\",\n        \"?autopublish@1.0.3-rc.0\",\n        \"?facts@1.0.4-rc.0\",\n        \"callback-hook@1.0.3-rc.0\",\n        \"minimongo@1.0.7-rc.0\",\n        \"?reload@1.1.3-rc.0\"\n      ],\n      \"constraint-solver 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\",\n        \"check@10.0.0-glasser.isopacket.0\",\n        \"package-version-parser@10.0.0-glasser.isopacket.0\",\n        \"binary-heap@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\"\n      ],\n      \"constraint-solver 1.0.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.2\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.3\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.4\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.5-cordova1\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.5-cordova3\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.5-ekate\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.5-ekate-more\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.5-glasser1\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.5\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.6\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.7\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.8\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.9-cordova4\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.9\": [\n        \"binary-heap@1.0.0\",\n        \"check@1.0.0\",\n        \"ejson@1.0.0\",\n        \"meteor@1.0.2\",\n        \"package-version-parser@1.0.5\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"constraint-solver 1.0.10-cordova5\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.10-rc1\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.10\": [\n        \"binary-heap@1.0.0\",\n        \"check@1.0.0\",\n        \"ejson@1.0.0\",\n        \"meteor@1.0.2\",\n        \"package-version-parser@1.0.6\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"constraint-solver 1.0.11-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.11\": [\n        \"binary-heap@1.0.0\",\n        \"check@1.0.0\",\n        \"ejson@1.0.1\",\n        \"meteor@1.0.3\",\n        \"package-version-parser@1.0.6\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"constraint-solver 1.0.12-cordova6\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.12-rc1\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.12\": [\n        \"binary-heap@1.0.0\",\n        \"check@1.0.0\",\n        \"ejson@1.0.2\",\n        \"meteor@1.1.0\",\n        \"package-version-parser@1.0.8\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"constraint-solver 1.0.13-ekate\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.14-exp\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.14-exp1\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.14-exp2\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.14-exp3\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.14-exp4\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.14-exp5\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.14-exp6\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.14-exp7\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.14-exp8\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.14-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.14-rc1\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.14\": [\n        \"binary-heap@1.0.0\",\n        \"check@1.0.1\",\n        \"ejson@1.0.3\",\n        \"meteor@1.1.1\",\n        \"package-version-parser@2.0.0\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"constraint-solver 1.0.15-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.15-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\",\n        \"check\",\n        \"package-version-parser\",\n        \"binary-heap\",\n        \"random\"\n      ],\n      \"constraint-solver 1.0.15-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"ejson@1.0.4-pre.2\",\n        \"check@1.0.2-pre.2\",\n        \"package-version-parser@2.0.2-pre.2\",\n        \"binary-heap@1.0.1-pre.2\",\n        \"random@1.0.1-pre.2\"\n      ],\n      \"constraint-solver 1.0.15-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"package-version-parser@2.0.2-rc.0\",\n        \"binary-heap@1.0.1-rc.0\",\n        \"random@1.0.1-rc.0\"\n      ],\n      \"constraint-solver 1.0.15-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"ejson@1.0.4-win.0\",\n        \"check@1.0.2-win.0\",\n        \"package-version-parser@2.0.2-win.0\",\n        \"binary-heap@1.0.1-win.0\",\n        \"random@1.0.1-win.0\"\n      ],\n      \"constraint-solver 1.0.15\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"ejson@1.0.4\",\n        \"check@1.0.2\",\n        \"package-version-parser@2.0.2\",\n        \"binary-heap@1.0.1\",\n        \"random@1.0.1\"\n      ],\n      \"constraint-solver 1.0.16-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"check@1.0.3-ipc.0\",\n        \"package-version-parser@2.0.3-ipc.0\",\n        \"binary-heap@1.0.2-ipc.0\",\n        \"random@1.0.2-ipc.0\"\n      ],\n      \"constraint-solver 1.0.16-ipc.1\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"check@1.0.3-ipc.0\",\n        \"package-version-parser@2.0.3-ipc.0\",\n        \"binary-heap@1.0.2-ipc.0\",\n        \"random@1.0.2-ipc.0\"\n      ],\n      \"constraint-solver 1.0.16-ipc.2\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"check@1.0.3-ipc.0\",\n        \"package-version-parser@2.0.3-ipc.0\",\n        \"binary-heap@1.0.2-ipc.0\",\n        \"random@1.0.2-ipc.0\"\n      ],\n      \"constraint-solver 1.0.16-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"ejson@1.0.5-rc.1\",\n        \"check@1.0.3-rc.1\",\n        \"package-version-parser@2.0.3-rc.1\",\n        \"binary-heap@1.0.2-rc.1\",\n        \"random@1.0.2-rc.1\"\n      ],\n      \"constraint-solver 1.0.16-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"ejson@1.0.5-slava.0\",\n        \"check@1.0.3-slava.0\",\n        \"package-version-parser@2.0.3-slava.0\",\n        \"binary-heap@1.0.2-slava.0\",\n        \"random@1.0.2-slava.0\"\n      ],\n      \"constraint-solver 1.0.16-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"ejson@1.0.5-win.0\",\n        \"check@1.0.3-win.0\",\n        \"package-version-parser@2.0.3-win.0\",\n        \"binary-heap@1.0.2-win.0\",\n        \"random@1.0.2-win.0\"\n      ],\n      \"constraint-solver 1.0.16-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"ejson@1.0.5-winr.0\",\n        \"check@1.0.3-winr.0\",\n        \"package-version-parser@2.0.3-winr.0\",\n        \"binary-heap@1.0.2-winr.0\",\n        \"random@1.0.2-winr.0\"\n      ],\n      \"constraint-solver 1.0.16\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\",\n        \"check@1.0.3\",\n        \"package-version-parser@2.0.3\",\n        \"binary-heap@1.0.2\",\n        \"random@1.0.2\"\n      ],\n      \"constraint-solver 1.0.17-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"ejson@1.0.6-eachin.43\",\n        \"check@1.0.4-eachin.43\",\n        \"package-version-parser@3.0.1-eachin.43\",\n        \"binary-heap@1.0.3-eachin.43\",\n        \"random@1.0.3-eachin.43\"\n      ],\n      \"constraint-solver 1.0.17-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"ejson@1.0.6-githubble.0\",\n        \"check@1.0.4-win.0\",\n        \"package-version-parser@3.0.1-githubble.0\",\n        \"binary-heap@1.0.3-githubble.0\",\n        \"random@1.0.3-githubble.0\"\n      ],\n      \"constraint-solver 1.0.17-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"ejson@1.0.6-githubble.2\",\n        \"check@1.0.4-win.0\",\n        \"package-version-parser@3.0.1-githubble.2\",\n        \"binary-heap@1.0.3-githubble.2\",\n        \"random@1.0.3-githubble.2\"\n      ],\n      \"constraint-solver 1.0.17-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"ejson@1.0.6-githubble.42\",\n        \"check@1.0.4-win.0\",\n        \"package-version-parser@3.0.1-githubble.42\",\n        \"binary-heap@1.0.3-githubble.42\",\n        \"random@1.0.3-githubble.42\"\n      ],\n      \"constraint-solver 1.0.17-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"ejson@1.0.6-githubble.43\",\n        \"check@1.0.4-githubble.43\",\n        \"package-version-parser@3.0.1-githubble.43\",\n        \"binary-heap@1.0.3-githubble.43\",\n        \"random@1.0.3-githubble.43\"\n      ],\n      \"constraint-solver 1.0.17-rc.0\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\",\n        \"check@1.0.4-rc.0\",\n        \"package-version-parser@3.0.0-rc.0\",\n        \"binary-heap@1.0.2\",\n        \"random@1.0.2\"\n      ],\n      \"constraint-solver 1.0.17-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"ejson@1.0.6-winr.0\",\n        \"check@1.0.4-winr.0\",\n        \"package-version-parser@2.0.4-winr.0\",\n        \"binary-heap@1.0.3-winr.0\",\n        \"random@1.0.3-winr.0\"\n      ],\n      \"constraint-solver 1.0.17-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\",\n        \"check@1.0.4-winr.1\",\n        \"package-version-parser@2.0.4-winr.1\",\n        \"binary-heap@1.0.3-winr.1\",\n        \"random@1.0.3-winr.1\"\n      ],\n      \"constraint-solver 1.0.17-winr.2\": [\n        \"meteor@1.1.5-winr.2\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\",\n        \"check@1.0.4-win.0\",\n        \"package-version-parser@3.0.1-winr.0\",\n        \"binary-heap@1.0.2\",\n        \"random@1.0.2\"\n      ],\n      \"constraint-solver 1.0.17-winr.3\": [\n        \"meteor@1.1.5-winr.3\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\",\n        \"check@1.0.4-win.0\",\n        \"package-version-parser@3.0.1-winr.1\",\n        \"binary-heap@1.0.2\",\n        \"random@1.0.2\"\n      ],\n      \"constraint-solver 1.0.17-winr.4\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"check@1.0.4-win.0\",\n        \"package-version-parser@3.0.1-winr.2\",\n        \"binary-heap@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"constraint-solver 1.0.17-winr.5\": [\n        \"meteor@1.1.5-winr.5\",\n        \"underscore@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"check@1.0.4-win.0\",\n        \"package-version-parser@3.0.1-winr.4\",\n        \"binary-heap@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"constraint-solver 1.0.17\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\",\n        \"check@1.0.4\",\n        \"package-version-parser@3.0.0\",\n        \"binary-heap@1.0.2\",\n        \"random@1.0.2\"\n      ],\n      \"constraint-solver 1.0.18-blz.0\": [\n        \"meteor@1.1.5-blz.0\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\",\n        \"check@1.0.4\",\n        \"package-version-parser@3.0.1-blz.0\",\n        \"binary-heap@1.0.2\",\n        \"random@1.0.2\"\n      ],\n      \"constraint-solver 1.0.18-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"ejson@1.0.6-rc.0\",\n        \"check@1.0.5-rc.0\",\n        \"package-version-parser@3.0.2-rc.0\",\n        \"binary-heap@1.0.3-rc.0\",\n        \"random@1.0.3-rc.0\"\n      ],\n      \"constraint-solver 1.0.18-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\",\n        \"check@1.0.4\",\n        \"package-version-parser@3.0.2-vs.1\",\n        \"binary-heap@1.0.2\",\n        \"random@1.0.2\",\n        \"logic-solver@0.0.2-vs.1\"\n      ],\n      \"constraint-solver 1.0.18-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\",\n        \"check@1.0.4\",\n        \"package-version-parser@3.0.2-vs.2\",\n        \"binary-heap@1.0.2\",\n        \"random@1.0.2\",\n        \"logic-solver@0.0.2-vs.2\"\n      ],\n      \"constraint-solver 1.0.18-winr.5\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"check@1.0.5-win.0\",\n        \"package-version-parser@3.0.2-winr.4\",\n        \"binary-heap@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"constraint-solver 1.0.19-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"ejson@1.0.6-rc.0\",\n        \"check@1.0.5-rc.0\",\n        \"package-version-parser@3.0.3-rc.0\",\n        \"binary-heap@1.0.3-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"logic-solver@1.0.0-rc.0\"\n      ],\n      \"coffeescript 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"coffeescript 1.0.0\": [\n        \"meteor\"\n      ],\n      \"coffeescript 1.0.1\": [\n        \"meteor\"\n      ],\n      \"coffeescript 1.0.2-cordova4\": [\n        \"meteor\"\n      ],\n      \"coffeescript 1.0.2-ekate\": [\n        \"meteor\"\n      ],\n      \"coffeescript 1.0.2-glasser1\": [\n        \"meteor\"\n      ],\n      \"coffeescript 1.0.2-rc1\": [\n        \"meteor\"\n      ],\n      \"coffeescript 1.0.2\": [\n        \"meteor@1.0.2\"\n      ],\n      \"coffeescript 1.0.3-ekate\": [\n        \"meteor\"\n      ],\n      \"coffeescript 1.0.3\": [\n        \"meteor@1.1.0\"\n      ],\n      \"coffeescript 1.0.4-pre.0\": [\n        \"meteor\"\n      ],\n      \"coffeescript 1.0.4-pre.1\": [\n        \"meteor\"\n      ],\n      \"coffeescript 1.0.4-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"coffeescript 1.0.4-pre.3\": [\n        \"meteor@1.1.2-pre.3\"\n      ],\n      \"coffeescript 1.0.4-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"coffeescript 1.0.4-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"coffeescript 1.0.4\": [\n        \"meteor@1.1.2\"\n      ],\n      \"coffeescript 1.0.5-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"coffeescript 1.0.5-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"coffeescript 1.0.5-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"coffeescript 1.0.5-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"coffeescript 1.0.5-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"coffeescript 1.0.5\": [\n        \"meteor@1.1.4\"\n      ],\n      \"coffeescript 1.0.6-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"coffeescript 1.0.6-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"coffeescript 1.0.6-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"coffeescript 1.0.6-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"coffeescript 1.0.6-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"coffeescript 1.0.6-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"coffeescript 1.0.6-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"coffeescript 1.0.6-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"coffeescript 1.0.6-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"coffeescript-test-helper 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"coffeescript@10.0.0-glasser.isopacket.0\"\n      ],\n      \"coffeescript-test-helper 1.0.0\": [\n        \"coffeescript@1.0.2\",\n        \"meteor@1.0.2\"\n      ],\n      \"coffeescript-test-helper 1.0.1-pre.0\": [\n        \"meteor\",\n        \"coffeescript\"\n      ],\n      \"coffeescript-test-helper 1.0.1-pre.1\": [\n        \"meteor\",\n        \"coffeescript\"\n      ],\n      \"coffeescript-test-helper 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"coffeescript@1.0.4-pre.2\"\n      ],\n      \"coffeescript-test-helper 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"coffeescript@1.0.4-rc.0\"\n      ],\n      \"coffeescript-test-helper 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"coffeescript@1.0.4-win.0\"\n      ],\n      \"coffeescript-test-helper 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"coffeescript@1.0.4\"\n      ],\n      \"coffeescript-test-helper 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"coffeescript@1.0.5-ipc.0\"\n      ],\n      \"coffeescript-test-helper 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"coffeescript@1.0.5-rc.1\"\n      ],\n      \"coffeescript-test-helper 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"coffeescript@1.0.5-slava.0\"\n      ],\n      \"coffeescript-test-helper 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"coffeescript@1.0.5-win.0\"\n      ],\n      \"coffeescript-test-helper 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"coffeescript@1.0.5-winr.0\"\n      ],\n      \"coffeescript-test-helper 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"coffeescript@1.0.5\"\n      ],\n      \"coffeescript-test-helper 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"coffeescript@1.0.6-eachin.43\"\n      ],\n      \"coffeescript-test-helper 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"coffeescript@1.0.6-githubble.0\"\n      ],\n      \"coffeescript-test-helper 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"coffeescript@1.0.6-githubble.2\"\n      ],\n      \"coffeescript-test-helper 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"coffeescript@1.0.6-githubble.42\"\n      ],\n      \"coffeescript-test-helper 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"coffeescript@1.0.6-githubble.43\"\n      ],\n      \"coffeescript-test-helper 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"coffeescript@1.0.6-rc.0\"\n      ],\n      \"coffeescript-test-helper 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"coffeescript@1.0.6-winr.0\"\n      ],\n      \"coffeescript-test-helper 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"coffeescript@1.0.6-winr.1\"\n      ],\n      \"coffeescript-test-helper 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"coffeescript@1.0.6-winr.2\"\n      ],\n      \"code-prettify 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"code-prettify 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"code-prettify 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"code-prettify 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"code-prettify 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"code-prettify 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"code-prettify 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"code-prettify 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"code-prettify 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"code-prettify 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"code-prettify 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"code-prettify 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"code-prettify 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"code-prettify 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"code-prettify 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"code-prettify 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"code-prettify 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"code-prettify 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"code-prettify 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"code-prettify 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"code-prettify 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"code-prettify 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"code-prettify 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"check 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\"\n      ],\n      \"check 1.0.0\": [\n        \"ejson@1.0.0\",\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"check 1.0.1-ekate\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"check 1.0.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"check 1.0.1\": [\n        \"ejson@1.0.3\",\n        \"meteor@1.1.1\",\n        \"underscore@1.0.0\"\n      ],\n      \"check 1.0.2-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"check 1.0.2-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"ejson\"\n      ],\n      \"check 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"ejson@1.0.4-pre.2\"\n      ],\n      \"check 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\"\n      ],\n      \"check 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"ejson@1.0.4-win.0\"\n      ],\n      \"check 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"ejson@1.0.4\"\n      ],\n      \"check 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\"\n      ],\n      \"check 1.0.3-ipc.1\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\"\n      ],\n      \"check 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"ejson@1.0.5-rc.1\"\n      ],\n      \"check 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"ejson@1.0.5-slava.0\"\n      ],\n      \"check 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"ejson@1.0.5-win.0\"\n      ],\n      \"check 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"ejson@1.0.5-winr.0\"\n      ],\n      \"check 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\"\n      ],\n      \"check 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"ejson@1.0.6-eachin.43\"\n      ],\n      \"check 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"ejson@1.0.6-githubble.43\"\n      ],\n      \"check 1.0.4-rc.0\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\"\n      ],\n      \"check 1.0.4-win.0\": [\n        \"meteor@1.1.5-winr.2\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\"\n      ],\n      \"check 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"ejson@1.0.6-winr.0\"\n      ],\n      \"check 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\"\n      ],\n      \"check 1.0.4\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"ejson@1.0.5\"\n      ],\n      \"check 1.0.5-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"ejson@1.0.6-rc.0\"\n      ],\n      \"check 1.0.5-win.0\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\"\n      ],\n      \"callback-hook 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\"\n      ],\n      \"callback-hook 1.0.0\": [\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"callback-hook 1.0.1-pre.0\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"callback-hook 1.0.1-pre.1\": [\n        \"meteor\",\n        \"underscore\"\n      ],\n      \"callback-hook 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\"\n      ],\n      \"callback-hook 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"callback-hook 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\"\n      ],\n      \"callback-hook 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\"\n      ],\n      \"callback-hook 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\"\n      ],\n      \"callback-hook 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\"\n      ],\n      \"callback-hook 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\"\n      ],\n      \"callback-hook 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\"\n      ],\n      \"callback-hook 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\"\n      ],\n      \"callback-hook 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\"\n      ],\n      \"callback-hook 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\"\n      ],\n      \"callback-hook 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\"\n      ],\n      \"callback-hook 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\"\n      ],\n      \"callback-hook 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\"\n      ],\n      \"callback-hook 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\"\n      ],\n      \"callback-hook 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\"\n      ],\n      \"callback-hook 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"callback-hook 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\"\n      ],\n      \"callback-hook 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\"\n      ],\n      \"callback-hook 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"browser-policy 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"browser-policy-content@10.0.0-glasser.isopacket.0\",\n        \"browser-policy-framing@10.0.0-glasser.isopacket.0\",\n        \"browser-policy-common@10.0.0-glasser.isopacket.0\"\n      ],\n      \"browser-policy 1.0.0\": [\n        \"browser-policy-common@1.0.0\",\n        \"browser-policy-content@1.0.0\",\n        \"browser-policy-framing@1.0.0\",\n        \"meteor@1.0.2\"\n      ],\n      \"browser-policy 1.0.1-rc0\": [\n        \"meteor\",\n        \"browser-policy-content\",\n        \"browser-policy-framing\",\n        \"browser-policy-common\"\n      ],\n      \"browser-policy 1.0.1\": [\n        \"browser-policy-common@1.0.0\",\n        \"browser-policy-content@1.0.1\",\n        \"browser-policy-framing@1.0.1\",\n        \"meteor@1.1.1\"\n      ],\n      \"browser-policy 1.0.2-pre.0\": [\n        \"meteor\",\n        \"browser-policy-content\",\n        \"browser-policy-framing\",\n        \"browser-policy-common\"\n      ],\n      \"browser-policy 1.0.2-pre.1\": [\n        \"meteor\",\n        \"browser-policy-content\",\n        \"browser-policy-framing\",\n        \"browser-policy-common\"\n      ],\n      \"browser-policy 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"browser-policy-content@1.0.2-pre.2\",\n        \"browser-policy-framing@1.0.2-pre.2\",\n        \"browser-policy-common@1.0.1-pre.2\"\n      ],\n      \"browser-policy 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"browser-policy-content@1.0.2-rc.0\",\n        \"browser-policy-framing@1.0.2-rc.0\",\n        \"browser-policy-common@1.0.1-rc.0\"\n      ],\n      \"browser-policy 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"browser-policy-content@1.0.2-win.0\",\n        \"browser-policy-framing@1.0.2-win.0\",\n        \"browser-policy-common@1.0.1-win.0\"\n      ],\n      \"browser-policy 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"browser-policy-content@1.0.2\",\n        \"browser-policy-framing@1.0.2\",\n        \"browser-policy-common@1.0.1\"\n      ],\n      \"browser-policy 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"browser-policy-content@1.0.3-ipc.0\",\n        \"browser-policy-framing@1.0.3-ipc.0\",\n        \"browser-policy-common@1.0.2-ipc.0\"\n      ],\n      \"browser-policy 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"browser-policy-content@1.0.3-rc.1\",\n        \"browser-policy-framing@1.0.3-rc.1\",\n        \"browser-policy-common@1.0.2-rc.1\"\n      ],\n      \"browser-policy 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"browser-policy-content@1.0.3-slava.0\",\n        \"browser-policy-framing@1.0.3-slava.0\",\n        \"browser-policy-common@1.0.2-slava.0\"\n      ],\n      \"browser-policy 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"browser-policy-content@1.0.3-win.0\",\n        \"browser-policy-framing@1.0.3-win.0\",\n        \"browser-policy-common@1.0.2-win.0\"\n      ],\n      \"browser-policy 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"browser-policy-content@1.0.3-winr.0\",\n        \"browser-policy-framing@1.0.3-winr.0\",\n        \"browser-policy-common@1.0.2-winr.0\"\n      ],\n      \"browser-policy 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"browser-policy-content@1.0.3\",\n        \"browser-policy-framing@1.0.3\",\n        \"browser-policy-common@1.0.2\"\n      ],\n      \"browser-policy 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"browser-policy-content@1.0.4-eachin.43\",\n        \"browser-policy-framing@1.0.4-eachin.43\",\n        \"browser-policy-common@1.0.3-eachin.43\"\n      ],\n      \"browser-policy 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"browser-policy-content@1.0.4-githubble.0\",\n        \"browser-policy-framing@1.0.4-githubble.0\",\n        \"browser-policy-common@1.0.3-githubble.0\"\n      ],\n      \"browser-policy 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"browser-policy-content@1.0.4-githubble.2\",\n        \"browser-policy-framing@1.0.4-githubble.2\",\n        \"browser-policy-common@1.0.3-githubble.2\"\n      ],\n      \"browser-policy 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"browser-policy-content@1.0.4-githubble.42\",\n        \"browser-policy-framing@1.0.4-githubble.42\",\n        \"browser-policy-common@1.0.3-githubble.42\"\n      ],\n      \"browser-policy 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"browser-policy-content@1.0.4-githubble.43\",\n        \"browser-policy-framing@1.0.4-githubble.43\",\n        \"browser-policy-common@1.0.3-githubble.43\"\n      ],\n      \"browser-policy 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"browser-policy-content@1.0.4-rc.0\",\n        \"browser-policy-framing@1.0.4-rc.0\",\n        \"browser-policy-common@1.0.3-rc.0\"\n      ],\n      \"browser-policy 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"browser-policy-content@1.0.4-winr.0\",\n        \"browser-policy-framing@1.0.4-winr.0\",\n        \"browser-policy-common@1.0.3-winr.0\"\n      ],\n      \"browser-policy 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"browser-policy-content@1.0.4-winr.1\",\n        \"browser-policy-framing@1.0.4-winr.1\",\n        \"browser-policy-common@1.0.3-winr.1\"\n      ],\n      \"browser-policy 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"browser-policy-content@1.0.4-winr.2\",\n        \"browser-policy-framing@1.0.4-winr.2\",\n        \"browser-policy-common@1.0.3-winr.2\"\n      ],\n      \"browser-policy-framing 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"browser-policy-common@10.0.0-glasser.isopacket.0\"\n      ],\n      \"browser-policy-framing 1.0.0\": [\n        \"browser-policy-common@1.0.0\",\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"browser-policy-framing 1.0.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"browser-policy-common\"\n      ],\n      \"browser-policy-framing 1.0.1\": [\n        \"browser-policy-common@1.0.0\",\n        \"meteor@1.1.1\",\n        \"underscore@1.0.0\"\n      ],\n      \"browser-policy-framing 1.0.2-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"browser-policy-common\"\n      ],\n      \"browser-policy-framing 1.0.2-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"browser-policy-common\"\n      ],\n      \"browser-policy-framing 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"browser-policy-common@1.0.1-pre.2\"\n      ],\n      \"browser-policy-framing 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"browser-policy-common@1.0.1-rc.0\"\n      ],\n      \"browser-policy-framing 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"browser-policy-common@1.0.1-win.0\"\n      ],\n      \"browser-policy-framing 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"browser-policy-common@1.0.1\"\n      ],\n      \"browser-policy-framing 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"browser-policy-common@1.0.2-ipc.0\"\n      ],\n      \"browser-policy-framing 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"browser-policy-common@1.0.2-rc.1\"\n      ],\n      \"browser-policy-framing 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"browser-policy-common@1.0.2-slava.0\"\n      ],\n      \"browser-policy-framing 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"browser-policy-common@1.0.2-win.0\"\n      ],\n      \"browser-policy-framing 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"browser-policy-common@1.0.2-winr.0\"\n      ],\n      \"browser-policy-framing 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"browser-policy-common@1.0.2\"\n      ],\n      \"browser-policy-framing 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"browser-policy-common@1.0.3-eachin.43\"\n      ],\n      \"browser-policy-framing 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"browser-policy-common@1.0.3-githubble.0\"\n      ],\n      \"browser-policy-framing 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"browser-policy-common@1.0.3-githubble.2\"\n      ],\n      \"browser-policy-framing 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"browser-policy-common@1.0.3-githubble.42\"\n      ],\n      \"browser-policy-framing 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"browser-policy-common@1.0.3-githubble.43\"\n      ],\n      \"browser-policy-framing 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"browser-policy-common@1.0.3-rc.0\"\n      ],\n      \"browser-policy-framing 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"browser-policy-common@1.0.3-winr.0\"\n      ],\n      \"browser-policy-framing 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"browser-policy-common@1.0.3-winr.1\"\n      ],\n      \"browser-policy-framing 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"browser-policy-common@1.0.3-winr.2\"\n      ],\n      \"browser-policy-content 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"browser-policy-common@10.0.0-glasser.isopacket.0\",\n        \"webapp@10.0.0-glasser.isopacket.0\"\n      ],\n      \"browser-policy-content 1.0.0\": [\n        \"browser-policy-common@1.0.0\",\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.2\"\n      ],\n      \"browser-policy-content 1.0.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"browser-policy-common\",\n        \"webapp\"\n      ],\n      \"browser-policy-content 1.0.1\": [\n        \"browser-policy-common@1.0.0\",\n        \"meteor@1.1.1\",\n        \"underscore@1.0.0\",\n        \"webapp@1.1.2\"\n      ],\n      \"browser-policy-content 1.0.2-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"browser-policy-common\",\n        \"webapp\"\n      ],\n      \"browser-policy-content 1.0.2-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"browser-policy-common\",\n        \"webapp\"\n      ],\n      \"browser-policy-content 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"browser-policy-common@1.0.1-pre.2\",\n        \"webapp@1.1.3-pre.2\"\n      ],\n      \"browser-policy-content 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"browser-policy-common@1.0.1-rc.0\",\n        \"webapp@1.1.3-rc.0\"\n      ],\n      \"browser-policy-content 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"browser-policy-common@1.0.1-win.0\",\n        \"webapp@1.1.4-win.0\"\n      ],\n      \"browser-policy-content 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"browser-policy-common@1.0.1\",\n        \"webapp@1.1.3\"\n      ],\n      \"browser-policy-content 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"browser-policy-common@1.0.2-ipc.0\",\n        \"webapp@1.1.5-ipc.0\"\n      ],\n      \"browser-policy-content 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"browser-policy-common@1.0.2-rc.1\",\n        \"webapp@1.1.5-rc.1\"\n      ],\n      \"browser-policy-content 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"browser-policy-common@1.0.2-slava.0\",\n        \"webapp@1.1.5-slava.0\"\n      ],\n      \"browser-policy-content 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"browser-policy-common@1.0.2-win.0\",\n        \"webapp@1.1.5-win.0\"\n      ],\n      \"browser-policy-content 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"browser-policy-common@1.0.2-winr.0\",\n        \"webapp@1.1.5-winr.0\"\n      ],\n      \"browser-policy-content 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"browser-policy-common@1.0.2\",\n        \"webapp@1.1.5\"\n      ],\n      \"browser-policy-content 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"browser-policy-common@1.0.3-eachin.43\",\n        \"webapp@1.1.7-eachin.43\"\n      ],\n      \"browser-policy-content 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"browser-policy-common@1.0.3-githubble.0\",\n        \"webapp@1.1.7-githubble.0\"\n      ],\n      \"browser-policy-content 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"browser-policy-common@1.0.3-githubble.2\",\n        \"webapp@1.1.7-githubble.2\"\n      ],\n      \"browser-policy-content 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"browser-policy-common@1.0.3-githubble.42\",\n        \"webapp@1.1.7-githubble.42\"\n      ],\n      \"browser-policy-content 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"browser-policy-common@1.0.3-githubble.43\",\n        \"webapp@1.1.7-githubble.43\"\n      ],\n      \"browser-policy-content 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"browser-policy-common@1.0.3-rc.0\",\n        \"webapp@1.2.0-rc.0\"\n      ],\n      \"browser-policy-content 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"browser-policy-common@1.0.3-winr.0\",\n        \"webapp@1.1.6-winr.0\"\n      ],\n      \"browser-policy-content 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"browser-policy-common@1.0.3-winr.1\",\n        \"webapp@1.1.6-winr.1\"\n      ],\n      \"browser-policy-content 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"browser-policy-common@1.0.3-winr.2\",\n        \"webapp@1.1.6-winr.4\"\n      ],\n      \"browser-policy-common 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"webapp@10.0.0-glasser.isopacket.0\"\n      ],\n      \"browser-policy-common 1.0.0\": [\n        \"meteor@1.0.2\",\n        \"webapp@1.0.2\"\n      ],\n      \"browser-policy-common 1.0.1-pre.0\": [\n        \"meteor\",\n        \"webapp\"\n      ],\n      \"browser-policy-common 1.0.1-pre.1\": [\n        \"meteor\",\n        \"webapp\"\n      ],\n      \"browser-policy-common 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"webapp@1.1.3-pre.2\"\n      ],\n      \"browser-policy-common 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"webapp@1.1.3-rc.0\"\n      ],\n      \"browser-policy-common 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"webapp@1.1.4-win.0\"\n      ],\n      \"browser-policy-common 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"webapp@1.1.3\"\n      ],\n      \"browser-policy-common 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"webapp@1.1.5-ipc.0\"\n      ],\n      \"browser-policy-common 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"webapp@1.1.5-rc.1\"\n      ],\n      \"browser-policy-common 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"webapp@1.1.5-slava.0\"\n      ],\n      \"browser-policy-common 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"webapp@1.1.5-win.0\"\n      ],\n      \"browser-policy-common 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"webapp@1.1.5-winr.0\"\n      ],\n      \"browser-policy-common 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"webapp@1.1.5\"\n      ],\n      \"browser-policy-common 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"webapp@1.1.7-eachin.43\"\n      ],\n      \"browser-policy-common 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"webapp@1.1.7-githubble.0\"\n      ],\n      \"browser-policy-common 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"webapp@1.1.7-githubble.2\"\n      ],\n      \"browser-policy-common 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"webapp@1.1.7-githubble.42\"\n      ],\n      \"browser-policy-common 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"webapp@1.1.7-githubble.43\"\n      ],\n      \"browser-policy-common 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"webapp@1.2.0-rc.0\"\n      ],\n      \"browser-policy-common 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"webapp@1.1.6-winr.0\"\n      ],\n      \"browser-policy-common 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"webapp@1.1.6-winr.1\"\n      ],\n      \"browser-policy-common 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"webapp@1.1.6-winr.4\"\n      ],\n      \"boilerplate-generator 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"spacebars-compiler@10.0.0-glasser.isopacket.0\",\n        \"spacebars@10.0.0-glasser.isopacket.0\",\n        \"htmljs@10.0.0-glasser.isopacket.0\",\n        \"ui@10.0.0-glasser.isopacket.0\"\n      ],\n      \"boilerplate-generator 1.0.0-cordova1\": [\n        \"meteor\",\n        \"underscore\",\n        \"spacebars-compiler\",\n        \"spacebars\",\n        \"htmljs\",\n        \"ui\"\n      ],\n      \"boilerplate-generator 1.0.0-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"spacebars-compiler\",\n        \"spacebars\",\n        \"htmljs\",\n        \"ui\"\n      ],\n      \"boilerplate-generator 1.0.0-rc1\": [\n        \"meteor\",\n        \"underscore\",\n        \"spacebars-compiler\",\n        \"spacebars\",\n        \"htmljs\",\n        \"ui\"\n      ],\n      \"boilerplate-generator 1.0.0\": [\n        \"htmljs@1.0.1\",\n        \"meteor@1.1.0\",\n        \"spacebars@1.0.1\",\n        \"spacebars-compiler@1.0.2\",\n        \"ui@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"boilerplate-generator 1.0.1-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"spacebars-compiler\",\n        \"spacebars\",\n        \"htmljs\",\n        \"ui\"\n      ],\n      \"boilerplate-generator 1.0.1-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"spacebars-compiler\",\n        \"spacebars\",\n        \"htmljs\",\n        \"ui\"\n      ],\n      \"boilerplate-generator 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"spacebars-compiler@1.0.3-pre.2\",\n        \"spacebars@1.0.3-pre.2\",\n        \"htmljs@1.0.2-pre.2\",\n        \"ui@1.0.4-pre.2\"\n      ],\n      \"boilerplate-generator 1.0.1-pre.3\": [\n        \"meteor@1.1.2-pre.3\",\n        \"underscore@1.0.1-pre.2\",\n        \"spacebars-compiler@1.0.3-pre.2\",\n        \"spacebars@1.0.3-pre.2\",\n        \"htmljs@1.0.2-pre.3\",\n        \"ui@1.0.4-pre.2\"\n      ],\n      \"boilerplate-generator 1.0.1-pre.4\": [\n        \"meteor@1.1.2-pre.3\",\n        \"underscore@1.0.1-pre.2\",\n        \"spacebars-compiler@1.0.3-pre.2\",\n        \"spacebars@1.0.3-pre.2\",\n        \"htmljs@1.0.2-pre.3\",\n        \"ui@1.0.4-pre.2\"\n      ],\n      \"boilerplate-generator 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"spacebars-compiler@1.0.3-rc.0\",\n        \"spacebars@1.0.3-rc.0\",\n        \"htmljs@1.0.2-rc.0\",\n        \"ui@1.0.4-rc.0\"\n      ],\n      \"boilerplate-generator 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"spacebars-compiler@1.0.3-win.0\",\n        \"spacebars@1.0.3-win.0\",\n        \"htmljs@1.0.2-win.0\",\n        \"ui@1.0.4-win.0\"\n      ],\n      \"boilerplate-generator 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"spacebars-compiler@1.0.3\",\n        \"spacebars@1.0.3\",\n        \"htmljs@1.0.2\",\n        \"ui@1.0.4\"\n      ],\n      \"boilerplate-generator 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"spacebars-compiler@1.0.4-ipc.0\",\n        \"spacebars@1.0.4-ipc.0\",\n        \"htmljs@1.0.3-ipc.0\",\n        \"ui@1.0.5-ipc.0\"\n      ],\n      \"boilerplate-generator 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"spacebars-compiler@1.0.4-rc.1\",\n        \"spacebars@1.0.4-rc.1\",\n        \"htmljs@1.0.3-rc.1\",\n        \"ui@1.0.5-rc.1\"\n      ],\n      \"boilerplate-generator 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"spacebars-compiler@1.0.4-slava.0\",\n        \"spacebars@1.0.4-slava.0\",\n        \"htmljs@1.0.3-slava.0\",\n        \"ui@1.0.5-slava.0\"\n      ],\n      \"boilerplate-generator 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"spacebars-compiler@1.0.4-win.0\",\n        \"spacebars@1.0.4-win.0\",\n        \"htmljs@1.0.3-win.0\",\n        \"ui@1.0.5-win.0\"\n      ],\n      \"boilerplate-generator 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"spacebars-compiler@1.0.4-winr.0\",\n        \"spacebars@1.0.4-winr.0\",\n        \"htmljs@1.0.3-winr.0\",\n        \"ui@1.0.5-winr.0\"\n      ],\n      \"boilerplate-generator 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"spacebars-compiler@1.0.4\",\n        \"spacebars@1.0.4\",\n        \"htmljs@1.0.3\",\n        \"ui@1.0.5\"\n      ],\n      \"boilerplate-generator 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"spacebars-compiler@1.0.5-eachin.0\",\n        \"spacebars@1.0.5-eachin.0\",\n        \"htmljs@1.0.4-eachin.0\",\n        \"ui@1.0.6-eachin.0\"\n      ],\n      \"boilerplate-generator 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"spacebars-compiler@1.0.5-eachin.43\",\n        \"spacebars@1.0.5-eachin.43\",\n        \"htmljs@1.0.4-eachin.43\",\n        \"ui@1.0.6-eachin.43\"\n      ],\n      \"boilerplate-generator 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"spacebars-compiler@1.0.5-githubble.0\",\n        \"spacebars@1.0.5-githubble.0\",\n        \"htmljs@1.0.4-githubble.0\",\n        \"ui@1.0.6-githubble.0\"\n      ],\n      \"boilerplate-generator 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"spacebars-compiler@1.0.5-githubble.2\",\n        \"spacebars@1.0.5-githubble.2\",\n        \"htmljs@1.0.4-githubble.2\",\n        \"ui@1.0.6-githubble.2\"\n      ],\n      \"boilerplate-generator 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"spacebars-compiler@1.0.5-githubble.42\",\n        \"spacebars@1.0.5-githubble.42\",\n        \"htmljs@1.0.4-githubble.42\",\n        \"ui@1.0.6-githubble.42\"\n      ],\n      \"boilerplate-generator 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"spacebars-compiler@1.0.5-githubble.43\",\n        \"spacebars@1.0.5-githubble.43\",\n        \"htmljs@1.0.4-githubble.43\",\n        \"ui@1.0.6-githubble.43\"\n      ],\n      \"boilerplate-generator 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"spacebars-compiler@1.0.5-rc.0\",\n        \"spacebars@1.0.6-rc.0\",\n        \"htmljs@1.0.4-rc.0\",\n        \"ui@1.0.6-rc.0\"\n      ],\n      \"boilerplate-generator 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"spacebars-compiler@1.0.5-winr.0\",\n        \"spacebars@1.0.5-winr.0\",\n        \"htmljs@1.0.4-winr.0\",\n        \"ui@1.0.6-winr.0\"\n      ],\n      \"boilerplate-generator 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"spacebars-compiler@1.0.5-winr.1\",\n        \"spacebars@1.0.5-winr.1\",\n        \"htmljs@1.0.4-winr.1\",\n        \"ui@1.0.6-winr.1\"\n      ],\n      \"boilerplate-generator 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"spacebars-compiler@1.0.5-winr.2\",\n        \"spacebars@1.0.5-winr.4\",\n        \"htmljs@1.0.4-winr.2\",\n        \"ui@1.0.6-winr.2\"\n      ],\n      \"boilerplate-generator 1.0.3-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"spacebars-compiler@1.0.5-winr.3\",\n        \"spacebars@1.0.5-winr.5\",\n        \"htmljs@1.0.4-winr.2\",\n        \"ui@1.0.6-winr.2\"\n      ],\n      \"blaze 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"jquery@1.5.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"htmljs@10.0.0-glasser.isopacket.0\",\n        \"observe-sequence@10.0.0-glasser.isopacket.0\",\n        \"reactive-var@10.0.0-glasser.isopacket.0\"\n      ],\n      \"blaze 1.0.0\": [\n        \"meteor\",\n        \"jquery\",\n        \"deps\",\n        \"underscore\",\n        \"htmljs\",\n        \"observe-sequence\"\n      ],\n      \"blaze 1.0.1\": [\n        \"meteor\",\n        \"jquery\",\n        \"deps\",\n        \"underscore\",\n        \"htmljs\",\n        \"observe-sequence\"\n      ],\n      \"blaze 1.0.2\": [\n        \"meteor\",\n        \"jquery\",\n        \"deps\",\n        \"underscore\",\n        \"htmljs\",\n        \"observe-sequence\"\n      ],\n      \"blaze 1.0.3\": [\n        \"deps@1.0.1\",\n        \"htmljs@1.0.0\",\n        \"jquery@1.0.0\",\n        \"meteor@1.0.2\",\n        \"observe-sequence@1.0.1\",\n        \"underscore@1.0.0\"\n      ],\n      \"blaze 1.0.4-rc0\": [\n        \"meteor\",\n        \"jquery\",\n        \"tracker\",\n        \"underscore\",\n        \"htmljs\",\n        \"observe-sequence\",\n        \"reactive-var\"\n      ],\n      \"blaze 2.0.0-rc0\": [\n        \"meteor\",\n        \"jquery\",\n        \"tracker\",\n        \"underscore\",\n        \"htmljs\",\n        \"observe-sequence\",\n        \"reactive-var\"\n      ],\n      \"blaze 2.0.0-rc1\": [\n        \"meteor\",\n        \"jquery\",\n        \"tracker\",\n        \"underscore\",\n        \"htmljs\",\n        \"observe-sequence\",\n        \"reactive-var\"\n      ],\n      \"blaze 2.0.0\": [\n        \"htmljs@1.0.0\",\n        \"jquery@1.0.0\",\n        \"meteor@1.0.3\",\n        \"observe-sequence@1.0.2\",\n        \"reactive-var@1.0.1\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"blaze 2.0.1-ekate\": [\n        \"meteor\",\n        \"jquery\",\n        \"tracker\",\n        \"underscore\",\n        \"htmljs\",\n        \"observe-sequence\",\n        \"reactive-var\"\n      ],\n      \"blaze 2.0.1-rc0\": [\n        \"meteor\",\n        \"jquery\",\n        \"tracker\",\n        \"underscore\",\n        \"htmljs\",\n        \"observe-sequence\",\n        \"reactive-var\"\n      ],\n      \"blaze 2.0.1\": [\n        \"htmljs@1.0.1\",\n        \"jquery@1.0.0\",\n        \"meteor@1.1.1\",\n        \"observe-sequence@1.0.2\",\n        \"reactive-var@1.0.2\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"blaze 2.0.2-pre.0\": [\n        \"meteor\",\n        \"jquery\",\n        \"tracker\",\n        \"underscore\",\n        \"htmljs\",\n        \"observe-sequence\",\n        \"reactive-var\"\n      ],\n      \"blaze 2.0.2-pre.1\": [\n        \"meteor\",\n        \"jquery\",\n        \"tracker\",\n        \"underscore\",\n        \"htmljs\",\n        \"observe-sequence\",\n        \"reactive-var\"\n      ],\n      \"blaze 2.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"jquery@1.0.1-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"htmljs@1.0.2-pre.2\",\n        \"observe-sequence@1.0.3-pre.2\",\n        \"reactive-var@1.0.3-pre.2\"\n      ],\n      \"blaze 2.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"jquery@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"htmljs@1.0.2-rc.0\",\n        \"observe-sequence@1.0.3-rc.0\",\n        \"reactive-var@1.0.3-rc.0\"\n      ],\n      \"blaze 2.0.2-refreshpolicy.1\": [\n        \"meteor@1.1.2-refreshpolicy.1\",\n        \"jquery@1.0.1\",\n        \"tracker@1.0.3\",\n        \"underscore@1.0.1\",\n        \"htmljs@1.0.2\",\n        \"observe-sequence@1.0.3\",\n        \"reactive-var@1.0.3\"\n      ],\n      \"blaze 2.0.2\": [\n        \"meteor@1.1.2\",\n        \"jquery@1.0.1\",\n        \"tracker@1.0.3\",\n        \"underscore@1.0.1\",\n        \"htmljs@1.0.2\",\n        \"observe-sequence@1.0.3\",\n        \"reactive-var@1.0.3\"\n      ],\n      \"blaze 2.0.3-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"jquery@1.0.1\",\n        \"tracker@1.0.3\",\n        \"underscore@1.0.1\",\n        \"htmljs@1.0.2\",\n        \"observe-sequence@1.0.3\",\n        \"reactive-var@1.0.3\"\n      ],\n      \"blaze 2.0.3-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"jquery@1.0.1-win.0\",\n        \"tracker@1.0.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"htmljs@1.0.2-win.0\",\n        \"observe-sequence@1.0.3-win.0\",\n        \"reactive-var@1.0.3-win.0\"\n      ],\n      \"blaze 2.0.3\": [\n        \"meteor@1.1.3\",\n        \"jquery@1.0.1\",\n        \"tracker@1.0.3\",\n        \"underscore@1.0.1\",\n        \"htmljs@1.0.2\",\n        \"observe-sequence@1.0.3\",\n        \"reactive-var@1.0.3\"\n      ],\n      \"blaze 2.0.4-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"jquery@1.0.2-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"htmljs@1.0.3-ipc.0\",\n        \"observe-sequence@1.0.4-ipc.0\",\n        \"reactive-var@1.0.4-ipc.0\"\n      ],\n      \"blaze 2.0.4-ipc.1\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"jquery@1.0.2-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"htmljs@1.0.3-ipc.0\",\n        \"observe-sequence@1.0.4-ipc.0\",\n        \"reactive-var@1.0.4-ipc.0\"\n      ],\n      \"blaze 2.0.4-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"jquery@1.0.2-rc.1\",\n        \"tracker@1.0.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"htmljs@1.0.3-rc.1\",\n        \"observe-sequence@1.0.4-rc.1\",\n        \"reactive-var@1.0.4-rc.1\"\n      ],\n      \"blaze 2.0.4-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"jquery@1.0.2-slava.0\",\n        \"tracker@1.0.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"htmljs@1.0.3-slava.0\",\n        \"observe-sequence@1.0.4-slava.0\",\n        \"reactive-var@1.0.4-slava.0\"\n      ],\n      \"blaze 2.0.4-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"jquery@1.0.2-win.0\",\n        \"tracker@1.0.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"htmljs@1.0.3-win.0\",\n        \"observe-sequence@1.0.4-win.0\",\n        \"reactive-var@1.0.4-win.0\"\n      ],\n      \"blaze 2.0.4-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"jquery@1.0.2-winr.0\",\n        \"tracker@1.0.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"htmljs@1.0.3-winr.0\",\n        \"observe-sequence@1.0.4-winr.0\",\n        \"reactive-var@1.0.4-winr.0\"\n      ],\n      \"blaze 2.0.4\": [\n        \"meteor@1.1.4\",\n        \"jquery@1.0.2\",\n        \"tracker@1.0.4\",\n        \"underscore@1.0.2\",\n        \"htmljs@1.0.3\",\n        \"observe-sequence@1.0.4\",\n        \"reactive-var@1.0.4\"\n      ],\n      \"blaze 2.0.5-blz.0\": [\n        \"meteor@1.1.4\",\n        \"jquery@1.11.3\",\n        \"tracker@1.0.5\",\n        \"underscore@1.0.2\",\n        \"htmljs@1.0.3\",\n        \"observe-sequence@1.0.4\",\n        \"reactive-var@1.0.4\"\n      ],\n      \"blaze 2.0.5-blz.1\": [\n        \"meteor@1.1.5-blz.0\",\n        \"jquery@1.11.3\",\n        \"tracker@1.0.5\",\n        \"underscore@1.0.2\",\n        \"htmljs@1.0.3\",\n        \"observe-sequence@1.0.4\",\n        \"reactive-var@1.0.4\"\n      ],\n      \"blaze 2.0.5-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"jquery@1.11.3-winr.2_1\",\n        \"tracker@1.0.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"htmljs@1.0.4-winr.2\",\n        \"observe-sequence@1.0.5-winr.2\",\n        \"reactive-var@1.0.5-winr.2\"\n      ],\n      \"blaze 2.0.5-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"jquery@1.11.3-eachin.43_1\",\n        \"tracker@1.0.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"htmljs@1.0.4-eachin.43\",\n        \"observe-sequence@1.0.5-eachin.43\",\n        \"reactive-var@1.0.5-eachin.43\"\n      ],\n      \"blaze 2.0.5-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"jquery@1.11.3-winr.2_1\",\n        \"tracker@1.0.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"htmljs@1.0.4-winr.2\",\n        \"observe-sequence@1.0.5-winr.2\",\n        \"reactive-var@1.0.5-winr.2\"\n      ],\n      \"blaze 2.0.5-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"jquery@1.11.3-githubble.2_1\",\n        \"tracker@1.0.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"htmljs@1.0.4-githubble.2\",\n        \"observe-sequence@1.0.5-githubble.2\",\n        \"reactive-var@1.0.5-githubble.2\"\n      ],\n      \"blaze 2.0.5-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"jquery@1.11.3-githubble.42_1\",\n        \"tracker@1.0.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"htmljs@1.0.4-githubble.42\",\n        \"observe-sequence@1.0.5-githubble.42\",\n        \"reactive-var@1.0.5-githubble.42\"\n      ],\n      \"blaze 2.0.5-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"jquery@1.11.3-githubble.43_1\",\n        \"tracker@1.0.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"htmljs@1.0.4-githubble.43\",\n        \"observe-sequence@1.0.5-githubble.43\",\n        \"reactive-var@1.0.5-githubble.43\"\n      ],\n      \"blaze 2.0.5-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"jquery@1.11.3\",\n        \"tracker@1.0.5\",\n        \"underscore@1.0.2\",\n        \"htmljs@1.0.3\",\n        \"observe-sequence@1.0.4\",\n        \"reactive-var@1.0.4\"\n      ],\n      \"blaze 2.0.5-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"jquery@1.11.3\",\n        \"tracker@1.0.5\",\n        \"underscore@1.0.2\",\n        \"htmljs@1.0.3\",\n        \"observe-sequence@1.0.4\",\n        \"reactive-var@1.0.4\"\n      ],\n      \"blaze 2.0.5-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"jquery@1.0.3-winr.0\",\n        \"tracker@1.0.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"htmljs@1.0.4-winr.0\",\n        \"observe-sequence@1.0.5-winr.0\",\n        \"reactive-var@1.0.5-winr.0\"\n      ],\n      \"blaze 2.0.5-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"jquery@1.0.3-winr.1\",\n        \"tracker@1.0.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"htmljs@1.0.4-winr.1\",\n        \"observe-sequence@1.0.5-winr.1\",\n        \"reactive-var@1.0.5-winr.1\"\n      ],\n      \"blaze 2.0.5-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"jquery@1.11.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"htmljs@1.0.4-winr.2\",\n        \"observe-sequence@1.0.5-winr.2\",\n        \"reactive-var@1.0.5-winr.2\"\n      ],\n      \"blaze 2.0.5-winr.3\": [\n        \"meteor@1.1.5-winr.5\",\n        \"jquery@1.11.3-winr.2_1\",\n        \"tracker@1.0.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"htmljs@1.0.4-winr.2\",\n        \"observe-sequence@1.0.5-winr.2\",\n        \"reactive-var@1.0.5-winr.2\"\n      ],\n      \"blaze 2.0.5-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"jquery@1.11.3-winr.2_1\",\n        \"tracker@1.0.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"htmljs@1.0.4-winr.2\",\n        \"observe-sequence@1.0.5-winr.2\",\n        \"reactive-var@1.0.5-winr.2\"\n      ],\n      \"blaze 2.0.5-winr.5\": [\n        \"meteor@1.1.5-winr.6\",\n        \"jquery@1.11.3-winr.2_1\",\n        \"tracker@1.0.6-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"htmljs@1.0.4-winr.2\",\n        \"observe-sequence@1.0.5-winr.3\",\n        \"reactive-var@1.0.5-winr.2\"\n      ],\n      \"blaze 2.1.0-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"jquery@1.11.3-rc.0_2\",\n        \"tracker@1.0.6-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"htmljs@1.0.4-rc.0\",\n        \"observe-sequence@1.0.5-rc.0\",\n        \"reactive-var@1.0.5-rc.0\"\n      ],\n      \"blaze-tools 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"htmljs@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\"\n      ],\n      \"blaze-tools 1.0.0\": [\n        \"htmljs@1.0.0\",\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"blaze-tools 1.0.1-pre.0\": [\n        \"meteor\",\n        \"htmljs\",\n        \"underscore\"\n      ],\n      \"blaze-tools 1.0.1-pre.1\": [\n        \"meteor\",\n        \"htmljs\",\n        \"underscore\"\n      ],\n      \"blaze-tools 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"htmljs@1.0.2-pre.2\",\n        \"underscore@1.0.1-pre.2\"\n      ],\n      \"blaze-tools 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"htmljs@1.0.2-rc.0\",\n        \"underscore@1.0.1-rc.0\"\n      ],\n      \"blaze-tools 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"htmljs@1.0.2-win.0\",\n        \"underscore@1.0.1-win.0\"\n      ],\n      \"blaze-tools 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"htmljs@1.0.2\",\n        \"underscore@1.0.1\"\n      ],\n      \"blaze-tools 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"htmljs@1.0.3-ipc.0\",\n        \"underscore@1.0.2-ipc.0\"\n      ],\n      \"blaze-tools 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"htmljs@1.0.3-rc.1\",\n        \"underscore@1.0.2-rc.1\"\n      ],\n      \"blaze-tools 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"htmljs@1.0.3-slava.0\",\n        \"underscore@1.0.2-slava.0\"\n      ],\n      \"blaze-tools 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"htmljs@1.0.3-win.0\",\n        \"underscore@1.0.2-win.0\"\n      ],\n      \"blaze-tools 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"htmljs@1.0.3-winr.0\",\n        \"underscore@1.0.2-winr.0\"\n      ],\n      \"blaze-tools 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"htmljs@1.0.3\",\n        \"underscore@1.0.2\"\n      ],\n      \"blaze-tools 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"htmljs@1.0.4-winr.2\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"blaze-tools 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"htmljs@1.0.4-eachin.43\",\n        \"underscore@1.0.3-eachin.43\"\n      ],\n      \"blaze-tools 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"htmljs@1.0.4-githubble.0\",\n        \"underscore@1.0.3-githubble.0\"\n      ],\n      \"blaze-tools 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"htmljs@1.0.4-githubble.2\",\n        \"underscore@1.0.3-githubble.2\"\n      ],\n      \"blaze-tools 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"htmljs@1.0.4-githubble.42\",\n        \"underscore@1.0.3-githubble.42\"\n      ],\n      \"blaze-tools 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"htmljs@1.0.4-githubble.43\",\n        \"underscore@1.0.3-githubble.43\"\n      ],\n      \"blaze-tools 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"htmljs@1.0.4-rc.0\",\n        \"underscore@1.0.3-rc.0\"\n      ],\n      \"blaze-tools 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"htmljs@1.0.4-winr.0\",\n        \"underscore@1.0.3-winr.0\"\n      ],\n      \"blaze-tools 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"htmljs@1.0.4-winr.1\",\n        \"underscore@1.0.3-winr.1\"\n      ],\n      \"blaze-tools 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"htmljs@1.0.4-winr.2\",\n        \"underscore@1.0.3-winr.2\"\n      ],\n      \"binary-heap 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"id-map@10.0.0-glasser.isopacket.0\"\n      ],\n      \"binary-heap 1.0.0\": [\n        \"id-map@1.0.0\",\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"binary-heap 1.0.1-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"id-map\"\n      ],\n      \"binary-heap 1.0.1-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"id-map\"\n      ],\n      \"binary-heap 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"id-map@1.0.1-pre.2\"\n      ],\n      \"binary-heap 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"id-map@1.0.1-rc.0\"\n      ],\n      \"binary-heap 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"id-map@1.0.1-win.0\"\n      ],\n      \"binary-heap 1.0.1\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"id-map@1.0.1\"\n      ],\n      \"binary-heap 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"id-map@1.0.2-ipc.0\"\n      ],\n      \"binary-heap 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"id-map@1.0.2-rc.1\"\n      ],\n      \"binary-heap 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"id-map@1.0.2-slava.0\"\n      ],\n      \"binary-heap 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"id-map@1.0.2-win.0\"\n      ],\n      \"binary-heap 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"id-map@1.0.2-winr.0\"\n      ],\n      \"binary-heap 1.0.2\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"id-map@1.0.2\"\n      ],\n      \"binary-heap 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"id-map@1.0.3-eachin.0\"\n      ],\n      \"binary-heap 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"id-map@1.0.3-eachin.43\"\n      ],\n      \"binary-heap 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"id-map@1.0.3-githubble.0\"\n      ],\n      \"binary-heap 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"id-map@1.0.3-githubble.2\"\n      ],\n      \"binary-heap 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"id-map@1.0.3-githubble.42\"\n      ],\n      \"binary-heap 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"id-map@1.0.3-githubble.43\"\n      ],\n      \"binary-heap 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"id-map@1.0.3-rc.0\"\n      ],\n      \"binary-heap 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"id-map@1.0.3-winr.0\"\n      ],\n      \"binary-heap 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"id-map@1.0.3-winr.1\"\n      ],\n      \"binary-heap 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"id-map@1.0.3-winr.2\"\n      ],\n      \"base64 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"base64 1.0.0-rc0\": [\n        \"meteor\"\n      ],\n      \"base64 1.0.0\": [\n        \"meteor@1.1.0\"\n      ],\n      \"base64 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"base64 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"base64 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"base64 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"base64 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"base64 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"base64 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"base64 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"base64 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"base64 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"base64 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"base64 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"base64 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"base64 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"base64 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"base64 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"base64 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"base64 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"base64 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"base64 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"base64 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"base64 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"autoupdate 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"webapp@10.0.0-glasser.isopacket.0\",\n        \"ddp@10.0.0-glasser.isopacket.0\",\n        \"mongo@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\",\n        \"retry@10.0.0-glasser.isopacket.0\",\n        \"?reload@10.0.0-glasser.isopacket.0\",\n        \"http@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\"\n      ],\n      \"autoupdate 1.0.0\": [\n        \"meteor\",\n        \"webapp\",\n        \"livedata\",\n        \"mongo-livedata\",\n        \"underscore\",\n        \"deps\",\n        \"retry\",\n        \"?reload\"\n      ],\n      \"autoupdate 1.0.1\": [\n        \"meteor\",\n        \"webapp\",\n        \"livedata\",\n        \"mongo-livedata\",\n        \"underscore\",\n        \"deps\",\n        \"retry\",\n        \"?reload\"\n      ],\n      \"autoupdate 1.0.2\": [\n        \"meteor\",\n        \"webapp\",\n        \"livedata\",\n        \"mongo-livedata\",\n        \"underscore\",\n        \"deps\",\n        \"retry\",\n        \"?reload\"\n      ],\n      \"autoupdate 1.0.3\": [\n        \"meteor\",\n        \"webapp\",\n        \"livedata\",\n        \"mongo-livedata\",\n        \"underscore\",\n        \"deps\",\n        \"retry\",\n        \"?reload\"\n      ],\n      \"autoupdate 1.0.4-cordova1\": [\n        \"meteor\",\n        \"webapp\",\n        \"livedata\",\n        \"mongo-livedata\",\n        \"underscore\",\n        \"deps\",\n        \"retry\",\n        \"?reload\",\n        \"http\"\n      ],\n      \"autoupdate 1.0.4-cordova2\": [\n        \"meteor\",\n        \"webapp\",\n        \"livedata\",\n        \"mongo-livedata\",\n        \"underscore\",\n        \"deps\",\n        \"retry\",\n        \"?reload\",\n        \"http\"\n      ],\n      \"autoupdate 1.0.4-cordova4\": [\n        \"meteor\",\n        \"webapp\",\n        \"livedata\",\n        \"mongo-livedata\",\n        \"underscore\",\n        \"deps\",\n        \"retry\",\n        \"?reload\",\n        \"http\"\n      ],\n      \"autoupdate 1.0.4\": [\n        \"deps@1.0.1\",\n        \"livedata@1.0.7\",\n        \"meteor@1.0.2\",\n        \"mongo-livedata@1.0.3\",\n        \"?reload@1.0.0\",\n        \"retry@1.0.0\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.2\"\n      ],\n      \"autoupdate 1.0.5-cordova5\": [\n        \"meteor\",\n        \"webapp\",\n        \"livedata\",\n        \"mongo-livedata\",\n        \"underscore\",\n        \"deps\",\n        \"retry\",\n        \"random\",\n        \"?reload\",\n        \"http\"\n      ],\n      \"autoupdate 1.0.5-rc1\": [\n        \"meteor\",\n        \"webapp\",\n        \"livedata\",\n        \"mongo-livedata\",\n        \"underscore\",\n        \"deps\",\n        \"retry\",\n        \"?reload\"\n      ],\n      \"autoupdate 1.0.5\": [\n        \"deps@1.0.1\",\n        \"livedata@1.0.7\",\n        \"meteor@1.0.2\",\n        \"mongo-livedata@1.0.3\",\n        \"?reload@1.0.0\",\n        \"retry@1.0.0\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.2\"\n      ],\n      \"autoupdate 1.0.6-rc0\": [\n        \"meteor\",\n        \"webapp\",\n        \"livedata\",\n        \"mongo-livedata\",\n        \"underscore\",\n        \"tracker\",\n        \"retry\",\n        \"?reload\"\n      ],\n      \"autoupdate 1.0.6-rc1\": [\n        \"meteor\",\n        \"webapp\",\n        \"ddp\",\n        \"mongo\",\n        \"underscore\",\n        \"tracker\",\n        \"retry\",\n        \"?reload\"\n      ],\n      \"autoupdate 1.0.6\": [\n        \"ddp@1.0.8\",\n        \"meteor@1.0.3\",\n        \"mongo@1.0.4\",\n        \"?reload@1.0.1\",\n        \"retry@1.0.0\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.3\"\n      ],\n      \"autoupdate 1.0.7-cordova6\": [\n        \"meteor\",\n        \"webapp\",\n        \"ddp\",\n        \"mongo\",\n        \"underscore\",\n        \"tracker\",\n        \"retry\",\n        \"?reload\",\n        \"http\"\n      ],\n      \"autoupdate 1.0.7-ekate\": [\n        \"meteor\",\n        \"webapp\",\n        \"ddp\",\n        \"mongo\",\n        \"underscore\",\n        \"tracker\",\n        \"retry\",\n        \"?reload\",\n        \"http\"\n      ],\n      \"autoupdate 1.0.7-glasser1\": [\n        \"meteor\",\n        \"webapp\",\n        \"ddp\",\n        \"mongo\",\n        \"underscore\",\n        \"tracker\",\n        \"retry\",\n        \"?reload\",\n        \"http\"\n      ],\n      \"autoupdate 1.1.0-rc0\": [\n        \"meteor\",\n        \"webapp\",\n        \"ddp\",\n        \"mongo\",\n        \"underscore\",\n        \"tracker\",\n        \"retry\",\n        \"?reload\",\n        \"http\"\n      ],\n      \"autoupdate 1.1.0-rc1\": [\n        \"meteor\",\n        \"webapp\",\n        \"ddp\",\n        \"mongo\",\n        \"underscore\",\n        \"tracker\",\n        \"retry\",\n        \"?reload\",\n        \"http\"\n      ],\n      \"autoupdate 1.1.0\": [\n        \"ddp@1.0.8\",\n        \"http@1.0.5\",\n        \"meteor@1.1.0\",\n        \"mongo@1.0.5\",\n        \"?reload@1.1.0\",\n        \"retry@1.0.0\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\"\n      ],\n      \"autoupdate 1.1.1-rc0\": [\n        \"meteor\",\n        \"webapp\",\n        \"ddp\",\n        \"mongo\",\n        \"underscore\",\n        \"tracker\",\n        \"retry\",\n        \"?reload\",\n        \"http\"\n      ],\n      \"autoupdate 1.1.1\": [\n        \"ddp@1.0.9\",\n        \"http@1.0.6\",\n        \"meteor@1.1.1\",\n        \"mongo@1.0.6\",\n        \"?reload@1.1.0\",\n        \"retry@1.0.0\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\",\n        \"webapp@1.1.2\"\n      ],\n      \"autoupdate 1.1.2-nim.0\": [\n        \"meteor@1.1.2-nim.0\",\n        \"webapp@1.1.3-nim.0\",\n        \"ddp@1.0.10-nim.0\",\n        \"mongo@1.0.7-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"retry@1.0.1-rc.0\",\n        \"?reload@1.1.1-rc.0\",\n        \"http@1.0.7-nim.0\"\n      ],\n      \"autoupdate 1.1.2-pre.0\": [\n        \"meteor\",\n        \"webapp\",\n        \"ddp\",\n        \"mongo\",\n        \"underscore\",\n        \"tracker\",\n        \"retry\",\n        \"?reload\",\n        \"http\"\n      ],\n      \"autoupdate 1.1.2-pre.1\": [\n        \"meteor\",\n        \"webapp\",\n        \"ddp\",\n        \"mongo\",\n        \"underscore\",\n        \"tracker\",\n        \"retry\",\n        \"?reload\",\n        \"http\"\n      ],\n      \"autoupdate 1.1.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"webapp@1.1.3-pre.2\",\n        \"ddp@1.0.10-pre.2\",\n        \"mongo@1.0.7-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"retry@1.0.1-pre.2\",\n        \"?reload@1.1.1-pre.2\",\n        \"http@1.0.7-pre.2\"\n      ],\n      \"autoupdate 1.1.2-pre.3\": [\n        \"meteor@1.1.2-pre.3\",\n        \"webapp@1.1.3-pre.3\",\n        \"ddp@1.0.10-pre.2\",\n        \"mongo@1.0.7-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"retry@1.0.1-pre.2\",\n        \"?reload@1.1.1-pre.2\",\n        \"http@1.0.7-pre.2\"\n      ],\n      \"autoupdate 1.1.2-pre.4\": [\n        \"meteor@1.1.2-pre.3\",\n        \"webapp@1.1.3-pre.3\",\n        \"ddp@1.0.10-pre.2\",\n        \"mongo@1.0.7-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"retry@1.0.1-pre.2\",\n        \"?reload@1.1.1-pre.2\",\n        \"http@1.0.7-pre.2\"\n      ],\n      \"autoupdate 1.1.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"webapp@1.1.3-rc.0\",\n        \"ddp@1.0.10-rc.0\",\n        \"mongo@1.0.7-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"retry@1.0.1-rc.0\",\n        \"?reload@1.1.1-rc.0\",\n        \"http@1.0.7-rc.0\"\n      ],\n      \"autoupdate 1.1.2-rc.1\": [\n        \"meteor@1.1.2-ekate.1\",\n        \"webapp@1.1.3-rc.1\",\n        \"ddp@1.0.10-rc.1\",\n        \"mongo@1.0.7-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"retry@1.0.1-rc.0\",\n        \"?reload@1.1.1-rc.0\",\n        \"http@1.0.7-rc.1\"\n      ],\n      \"autoupdate 1.1.2-rc.2\": [\n        \"meteor@1.1.2-rc.2\",\n        \"webapp@1.1.3-rc.2\",\n        \"ddp@1.0.10-rc.2\",\n        \"mongo@1.0.7-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"retry@1.0.1-rc.0\",\n        \"?reload@1.1.1-rc.0\",\n        \"http@1.0.7-rc.2\"\n      ],\n      \"autoupdate 1.1.2-rc.3\": [\n        \"meteor@1.1.2-rc.2\",\n        \"webapp@1.1.3-rc.2\",\n        \"ddp@1.0.10-rc.2\",\n        \"mongo@1.0.7-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"retry@1.0.1-rc.0\",\n        \"?reload@1.1.1-rc.0\",\n        \"http@1.0.7-rc.2\"\n      ],\n      \"autoupdate 1.1.2-rc.4\": [\n        \"meteor@1.1.2-rc.3\",\n        \"webapp@1.1.3-rc.2\",\n        \"ddp@1.0.10-rc.3\",\n        \"mongo@1.0.7-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"retry@1.0.1-rc.0\",\n        \"?reload@1.1.1-rc.0\",\n        \"http@1.0.7-rc.4\"\n      ],\n      \"autoupdate 1.1.2-refreshpolicy.1\": [\n        \"meteor@1.1.2-refreshpolicy.1\",\n        \"webapp@1.1.3\",\n        \"ddp@1.0.10-refreshpolicy.1\",\n        \"mongo@1.0.7\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"retry@1.0.1\",\n        \"?reload@1.1.1\",\n        \"http@1.0.7-refreshpolicy.1\"\n      ],\n      \"autoupdate 1.1.2\": [\n        \"meteor@1.1.2\",\n        \"webapp@1.1.3\",\n        \"ddp@1.0.10\",\n        \"mongo@1.0.7\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"retry@1.0.1\",\n        \"?reload@1.1.1\",\n        \"http@1.0.7\"\n      ],\n      \"autoupdate 1.1.3-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"webapp@1.1.4-rc.0\",\n        \"ddp@1.0.11-rc.0\",\n        \"mongo@1.0.8-rc.0\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"retry@1.0.1\",\n        \"?reload@1.1.1\",\n        \"http@1.0.7\"\n      ],\n      \"autoupdate 1.1.3-rc.1\": [\n        \"meteor@1.1.3-rc.0\",\n        \"webapp@1.1.4-rc.2\",\n        \"ddp@1.0.11-rc.1\",\n        \"mongo@1.0.8-rc.1\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"retry@1.0.1\",\n        \"?reload@1.1.1\",\n        \"http@1.0.8-rc.3\",\n        \"random@1.0.1\"\n      ],\n      \"autoupdate 1.1.3-rc.2\": [\n        \"meteor@1.1.3-rc.0\",\n        \"webapp@1.1.4-rc.2\",\n        \"ddp@1.0.11-rc.1\",\n        \"mongo@1.0.8-rc.1\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"retry@1.0.1\",\n        \"?reload@1.1.1\",\n        \"http@1.0.8-rc.4\",\n        \"random@1.0.1\"\n      ],\n      \"autoupdate 1.1.3-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"webapp@1.1.4-win.0\",\n        \"ddp@1.0.11-win.0\",\n        \"mongo@1.0.8-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"tracker@1.0.3-win.0\",\n        \"retry@1.0.1-win.0\",\n        \"?reload@1.1.1-win.0\",\n        \"http@1.0.8-win.0\",\n        \"random@1.0.1-win.0\"\n      ],\n      \"autoupdate 1.1.3\": [\n        \"meteor@1.1.3\",\n        \"webapp@1.1.4\",\n        \"ddp@1.0.11\",\n        \"mongo@1.0.8\",\n        \"underscore@1.0.1\",\n        \"tracker@1.0.3\",\n        \"retry@1.0.1\",\n        \"?reload@1.1.1\",\n        \"http@1.0.8\",\n        \"random@1.0.1\"\n      ],\n      \"autoupdate 1.1.4-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"webapp@1.1.5-ipc.0\",\n        \"ddp@1.0.12-ipc.0\",\n        \"mongo@1.0.9-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"retry@1.0.2-ipc.0\",\n        \"?reload@1.1.2-ipc.0\",\n        \"http@1.0.9-ipc.0\",\n        \"random@1.0.2-ipc.0\"\n      ],\n      \"autoupdate 1.1.4-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"webapp@1.1.5-rc.1\",\n        \"ddp@1.0.13-rc.1\",\n        \"mongo@1.0.10-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"tracker@1.0.4-rc.1\",\n        \"retry@1.0.2-rc.1\",\n        \"?reload@1.1.2-rc.1\",\n        \"http@1.0.9-rc.1\",\n        \"random@1.0.2-rc.1\"\n      ],\n      \"autoupdate 1.1.4-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"webapp@1.1.5-slava.0\",\n        \"ddp@1.0.13-slava.0\",\n        \"mongo@1.0.10-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"tracker@1.0.4-slava.0\",\n        \"retry@1.0.2-slava.0\",\n        \"?reload@1.1.2-slava.0\",\n        \"http@1.0.9-slava.0\",\n        \"random@1.0.2-slava.0\"\n      ],\n      \"autoupdate 1.1.4-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"webapp@1.1.5-win.0\",\n        \"ddp@1.0.12-win.0\",\n        \"mongo@1.0.9-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"tracker@1.0.4-win.0\",\n        \"retry@1.0.2-win.0\",\n        \"?reload@1.1.2-win.0\",\n        \"http@1.0.9-win.0\",\n        \"random@1.0.2-win.0\"\n      ],\n      \"autoupdate 1.1.4-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"webapp@1.1.5-winr.0\",\n        \"ddp@1.0.13-winr.0\",\n        \"mongo@1.0.10-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"tracker@1.0.4-winr.0\",\n        \"retry@1.0.2-winr.0\",\n        \"?reload@1.1.2-winr.0\",\n        \"http@1.0.9-winr.0\",\n        \"random@1.0.2-winr.0\"\n      ],\n      \"autoupdate 1.1.4\": [\n        \"meteor@1.1.4\",\n        \"webapp@1.1.5\",\n        \"ddp@1.0.13\",\n        \"mongo@1.0.10\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.4\",\n        \"retry@1.0.2\",\n        \"?reload@1.1.2\",\n        \"http@1.0.9\",\n        \"random@1.0.2\"\n      ],\n      \"autoupdate 1.1.5-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"webapp@1.1.6-eachin.0\",\n        \"ddp@1.0.14-eachin.0\",\n        \"mongo@1.0.12-eachin.0\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"retry@1.0.3-winr.2\",\n        \"?reload@1.1.3-winr.3\",\n        \"http@1.0.10-winr.5\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"autoupdate 1.1.5-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"webapp@1.1.6-githubble.0\",\n        \"ddp@1.0.14-githubble.0\",\n        \"mongo@1.0.12-githubble.0\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"retry@1.0.3-winr.2\",\n        \"?reload@1.1.3-winr.3\",\n        \"http@1.0.10-winr.5\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"autoupdate 1.1.5-rc.0\": [\n        \"meteor@1.1.4\",\n        \"webapp@1.1.6-rc.0\",\n        \"ddp@1.0.13\",\n        \"mongo@1.0.11\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5-rc.0\",\n        \"retry@1.0.2\",\n        \"?reload@1.1.2\",\n        \"http@1.0.10-rc.0\",\n        \"random@1.0.2\"\n      ],\n      \"autoupdate 1.1.5-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"webapp@1.1.6-winr.0\",\n        \"ddp@1.0.14-winr.0\",\n        \"mongo@1.0.11-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"tracker@1.0.5-winr.0\",\n        \"retry@1.0.3-winr.0\",\n        \"?reload@1.1.3-winr.0\",\n        \"http@1.0.10-winr.0\",\n        \"random@1.0.3-winr.0\"\n      ],\n      \"autoupdate 1.1.5-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"webapp@1.1.6-winr.1\",\n        \"ddp@1.0.14-winr.1\",\n        \"mongo@1.0.11-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"tracker@1.0.5-winr.1\",\n        \"retry@1.0.3-winr.1\",\n        \"?reload@1.1.3-winr.1\",\n        \"http@1.0.10-winr.1\",\n        \"random@1.0.3-winr.1\"\n      ],\n      \"autoupdate 1.1.5-winr.2\": [\n        \"meteor@1.1.5-winr.2\",\n        \"webapp@1.1.6-winr.2\",\n        \"ddp@1.0.14-winr.2\",\n        \"mongo@1.0.12-winr.0\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5-winr.2\",\n        \"retry@1.0.2\",\n        \"?reload@1.1.2\",\n        \"http@1.0.10-winr.2\",\n        \"random@1.0.2\"\n      ],\n      \"autoupdate 1.1.5-winr.3\": [\n        \"meteor@1.1.5-winr.3\",\n        \"webapp@1.1.6-winr.3\",\n        \"ddp@1.0.14-winr.3\",\n        \"mongo@1.0.12-winr.1\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5-winr.3\",\n        \"retry@1.0.2\",\n        \"?reload@1.1.2\",\n        \"http@1.0.10-winr.3\",\n        \"random@1.0.2\"\n      ],\n      \"autoupdate 1.1.5-winr.4\": [\n        \"meteor@1.1.5-winr.4\",\n        \"webapp@1.1.6-winr.4\",\n        \"ddp@1.0.14-winr.4\",\n        \"mongo@1.0.12-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"retry@1.0.3-winr.2\",\n        \"?reload@1.1.3-winr.3\",\n        \"http@1.0.10-winr.4\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"autoupdate 1.1.5\": [\n        \"meteor@1.1.4\",\n        \"webapp@1.1.6\",\n        \"ddp@1.0.14\",\n        \"mongo@1.0.11\",\n        \"underscore@1.0.2\",\n        \"tracker@1.0.5\",\n        \"retry@1.0.2\",\n        \"?reload@1.1.2\",\n        \"http@1.0.10\",\n        \"random@1.0.2\"\n      ],\n      \"autoupdate 1.1.6-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"webapp@1.1.7-eachin.43\",\n        \"ddp@1.0.15-eachin.43\",\n        \"mongo@1.0.12-eachin.45\",\n        \"underscore@1.0.3-eachin.43\",\n        \"tracker@1.0.5-eachin.43\",\n        \"retry@1.0.3-eachin.43\",\n        \"?reload@1.1.3-eachin.43\",\n        \"http@1.0.10-eachin.43\",\n        \"random@1.0.3-eachin.43\"\n      ],\n      \"autoupdate 1.1.6-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"webapp@1.1.7-githubble.0\",\n        \"ddp@1.0.15-githubble.0\",\n        \"mongo@1.0.12-githubble.0\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"retry@1.0.3-winr.2\",\n        \"?reload@1.1.3-winr.3\",\n        \"http@1.0.10-winr.5\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"autoupdate 1.1.6-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"webapp@1.1.7-githubble.2\",\n        \"ddp@1.0.15-githubble.2\",\n        \"mongo@1.0.12-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"tracker@1.0.5-githubble.2\",\n        \"retry@1.0.3-githubble.2\",\n        \"?reload@1.1.3-githubble.2\",\n        \"http@1.0.10-githubble.2\",\n        \"random@1.0.3-githubble.2\"\n      ],\n      \"autoupdate 1.1.6-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"webapp@1.1.7-githubble.42\",\n        \"ddp@1.0.15-githubble.42\",\n        \"mongo@1.0.12-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"tracker@1.0.5-githubble.42\",\n        \"retry@1.0.3-githubble.42\",\n        \"?reload@1.1.3-githubble.42\",\n        \"http@1.0.10-githubble.42\",\n        \"random@1.0.3-githubble.42\"\n      ],\n      \"autoupdate 1.1.6-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"webapp@1.1.7-githubble.43\",\n        \"ddp@1.0.15-githubble.43\",\n        \"mongo@1.0.12-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"tracker@1.0.5-githubble.43\",\n        \"retry@1.0.3-githubble.43\",\n        \"?reload@1.1.3-githubble.43\",\n        \"http@1.0.10-githubble.43\",\n        \"random@1.0.3-githubble.43\"\n      ],\n      \"autoupdate 1.1.6-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"webapp@1.1.7-winr.6\",\n        \"ddp@1.0.15-winr.5\",\n        \"mongo@1.0.12-winr.5\",\n        \"underscore@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"retry@1.0.3-winr.2\",\n        \"?reload@1.1.3-winr.3\",\n        \"http@1.0.10-winr.5\",\n        \"random@1.0.3-winr.2\"\n      ],\n      \"autoupdate 1.2.0-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"webapp@1.2.0-rc.0\",\n        \"ddp@1.1.0-rc.0\",\n        \"mongo@1.1.0-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"tracker@1.0.6-rc.0\",\n        \"retry@1.0.3-rc.0\",\n        \"?reload@1.1.3-rc.0\",\n        \"http@1.1.0-rc.0\",\n        \"random@1.0.3-rc.0\"\n      ],\n      \"audit-argument-checks 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"audit-argument-checks 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"audit-argument-checks 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"audit-argument-checks 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"audit-argument-checks 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"audit-argument-checks 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"audit-argument-checks 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"audit-argument-checks 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"audit-argument-checks 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"audit-argument-checks 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"audit-argument-checks 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"audit-argument-checks 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"audit-argument-checks 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"audit-argument-checks 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"audit-argument-checks 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"audit-argument-checks 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"audit-argument-checks 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"audit-argument-checks 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"audit-argument-checks 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"audit-argument-checks 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"audit-argument-checks 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"audit-argument-checks 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"audit-argument-checks 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"audit-argument-checks 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"appcache 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"webapp@10.0.0-glasser.isopacket.0\",\n        \"routepolicy@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"?autoupdate@10.0.0-glasser.isopacket.0\",\n        \"reload@10.0.0-glasser.isopacket.0\"\n      ],\n      \"appcache 1.0.0-cordova1\": [\n        \"?autoupdate@1.1.0\",\n        \"meteor@1.1.0\",\n        \"reload@1.1.0\",\n        \"routepolicy@1.0.0-cordova1\",\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\"\n      ],\n      \"appcache 1.0.0\": [\n        \"?autoupdate@1.0.4\",\n        \"meteor@1.0.2\",\n        \"reload@1.0.0\",\n        \"routepolicy@1.0.0\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.2\"\n      ],\n      \"appcache 1.0.1\": [\n        \"?autoupdate@1.1.0\",\n        \"meteor@1.1.0\",\n        \"reload@1.1.0\",\n        \"routepolicy@1.0.1\",\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\"\n      ],\n      \"appcache 1.0.2-pre.0\": [\n        \"meteor\",\n        \"webapp\",\n        \"routepolicy\",\n        \"underscore\",\n        \"?autoupdate\",\n        \"reload\"\n      ],\n      \"appcache 1.0.2-pre.1\": [\n        \"meteor\",\n        \"webapp\",\n        \"routepolicy\",\n        \"underscore\",\n        \"?autoupdate\",\n        \"reload\"\n      ],\n      \"appcache 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"webapp@1.1.3-pre.2\",\n        \"routepolicy@1.0.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"?autoupdate@1.1.2-pre.2\",\n        \"reload@1.1.1-pre.2\"\n      ],\n      \"appcache 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"webapp@1.1.3-rc.0\",\n        \"routepolicy@1.0.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"?autoupdate@1.1.2-rc.0\",\n        \"reload@1.1.1-rc.0\"\n      ],\n      \"appcache 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"webapp@1.1.4-win.0\",\n        \"routepolicy@1.0.2-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"?autoupdate@1.1.3-win.0\",\n        \"reload@1.1.1-win.0\"\n      ],\n      \"appcache 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"webapp@1.1.3\",\n        \"routepolicy@1.0.2\",\n        \"underscore@1.0.1\",\n        \"?autoupdate@1.1.2\",\n        \"reload@1.1.1\"\n      ],\n      \"appcache 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"webapp@1.1.5-ipc.0\",\n        \"routepolicy@1.0.3-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"?autoupdate@1.1.4-ipc.0\",\n        \"reload@1.1.2-ipc.0\"\n      ],\n      \"appcache 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"webapp@1.1.5-rc.1\",\n        \"routepolicy@1.0.3-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"?autoupdate@1.1.4-rc.1\",\n        \"reload@1.1.2-rc.1\"\n      ],\n      \"appcache 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"webapp@1.1.5-slava.0\",\n        \"routepolicy@1.0.3-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"?autoupdate@1.1.4-slava.0\",\n        \"reload@1.1.2-slava.0\"\n      ],\n      \"appcache 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"webapp@1.1.5-win.0\",\n        \"routepolicy@1.0.3-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"?autoupdate@1.1.4-win.0\",\n        \"reload@1.1.2-win.0\"\n      ],\n      \"appcache 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"webapp@1.1.5-winr.0\",\n        \"routepolicy@1.0.3-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"?autoupdate@1.1.4-winr.0\",\n        \"reload@1.1.2-winr.0\"\n      ],\n      \"appcache 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"webapp@1.1.5\",\n        \"routepolicy@1.0.3\",\n        \"underscore@1.0.2\",\n        \"?autoupdate@1.1.4\",\n        \"reload@1.1.2\"\n      ],\n      \"appcache 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"webapp@1.1.7-eachin.43\",\n        \"routepolicy@1.0.4-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"?autoupdate@1.1.6-eachin.43\",\n        \"reload@1.1.3-eachin.43\"\n      ],\n      \"appcache 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"webapp@1.1.7-githubble.0\",\n        \"routepolicy@1.0.4-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"?autoupdate@1.1.6-githubble.0\",\n        \"reload@1.1.3-githubble.0\"\n      ],\n      \"appcache 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"webapp@1.1.7-githubble.2\",\n        \"routepolicy@1.0.4-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"?autoupdate@1.1.6-githubble.2\",\n        \"reload@1.1.3-githubble.2\"\n      ],\n      \"appcache 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"webapp@1.1.7-githubble.42\",\n        \"routepolicy@1.0.4-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"?autoupdate@1.1.6-githubble.42\",\n        \"reload@1.1.3-githubble.42\"\n      ],\n      \"appcache 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"webapp@1.1.7-githubble.43\",\n        \"routepolicy@1.0.4-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"?autoupdate@1.1.6-githubble.43\",\n        \"reload@1.1.3-githubble.43\"\n      ],\n      \"appcache 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"webapp@1.2.0-rc.0\",\n        \"routepolicy@1.0.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"?autoupdate@1.2.0-rc.0\",\n        \"reload@1.1.3-rc.0\"\n      ],\n      \"appcache 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"webapp@1.1.6-winr.0\",\n        \"routepolicy@1.0.4-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"?autoupdate@1.1.5-winr.0\",\n        \"reload@1.1.3-winr.0\"\n      ],\n      \"appcache 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"webapp@1.1.6-winr.1\",\n        \"routepolicy@1.0.4-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"?autoupdate@1.1.5-winr.1\",\n        \"reload@1.1.3-winr.1\"\n      ],\n      \"appcache 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"webapp@1.1.6-winr.4\",\n        \"routepolicy@1.0.4-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"?autoupdate@1.1.5-winr.4\",\n        \"reload@1.1.3-winr.3\"\n      ],\n      \"accounts-weibo 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"accounts-base@10.0.0-glasser.isopacket.0\",\n        \"accounts-oauth@10.0.0-glasser.isopacket.0\",\n        \"weibo@10.0.0-glasser.isopacket.0\"\n      ],\n      \"accounts-weibo 1.0.0\": [\n        \"accounts-base@1.0.0\",\n        \"accounts-oauth@1.0.0\",\n        \"meteor@1.0.2\",\n        \"weibo@1.0.0\"\n      ],\n      \"accounts-weibo 1.0.1-rc0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"weibo\"\n      ],\n      \"accounts-weibo 1.0.1\": [\n        \"accounts-base@1.1.1\",\n        \"accounts-oauth@1.1.1\",\n        \"meteor@1.1.1\",\n        \"weibo@1.1.0\"\n      ],\n      \"accounts-weibo 1.0.2-pre.0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"weibo\"\n      ],\n      \"accounts-weibo 1.0.2-pre.1\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"weibo\"\n      ],\n      \"accounts-weibo 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"accounts-base@1.1.2-pre.2\",\n        \"accounts-oauth@1.1.2-pre.2\",\n        \"weibo@1.1.1-pre.2\"\n      ],\n      \"accounts-weibo 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"accounts-base@1.1.2-rc.0\",\n        \"accounts-oauth@1.1.2-rc.0\",\n        \"weibo@1.1.1-rc.0\"\n      ],\n      \"accounts-weibo 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"accounts-base@1.1.2-win.0\",\n        \"accounts-oauth@1.1.2-win.0\",\n        \"weibo@1.1.1-win.0\"\n      ],\n      \"accounts-weibo 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"accounts-base@1.1.2\",\n        \"accounts-oauth@1.1.2\",\n        \"weibo@1.1.1\"\n      ],\n      \"accounts-weibo 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"accounts-base@1.1.3-ipc.0\",\n        \"accounts-oauth@1.1.3-ipc.0\",\n        \"weibo@1.1.2-ipc.0\"\n      ],\n      \"accounts-weibo 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"accounts-base@1.1.3-rc.1\",\n        \"accounts-oauth@1.1.3-rc.1\",\n        \"weibo@1.1.2-rc.1\"\n      ],\n      \"accounts-weibo 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"accounts-base@1.1.3-slava.0\",\n        \"accounts-oauth@1.1.3-slava.0\",\n        \"weibo@1.1.2-slava.0\"\n      ],\n      \"accounts-weibo 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"accounts-base@1.1.3-win.0\",\n        \"accounts-oauth@1.1.3-win.0\",\n        \"weibo@1.1.2-win.0\"\n      ],\n      \"accounts-weibo 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"accounts-base@1.1.3-winr.0\",\n        \"accounts-oauth@1.1.3-winr.0\",\n        \"weibo@1.1.2-winr.0\"\n      ],\n      \"accounts-weibo 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"accounts-base@1.1.3\",\n        \"accounts-oauth@1.1.3\",\n        \"weibo@1.1.2\"\n      ],\n      \"accounts-weibo 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"accounts-base@1.1.4-eachin.43\",\n        \"accounts-oauth@1.1.4-eachin.43\",\n        \"weibo@1.1.3-eachin.43\"\n      ],\n      \"accounts-weibo 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"accounts-base@1.1.4-githubble.0\",\n        \"accounts-oauth@1.1.4-githubble.0\",\n        \"weibo@1.1.3-githubble.0\"\n      ],\n      \"accounts-weibo 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"accounts-base@1.1.4-githubble.2\",\n        \"accounts-oauth@1.1.4-githubble.2\",\n        \"weibo@1.1.3-githubble.2\"\n      ],\n      \"accounts-weibo 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"accounts-base@1.1.4-githubble.42\",\n        \"accounts-oauth@1.1.4-githubble.42\",\n        \"weibo@1.1.3-githubble.42\"\n      ],\n      \"accounts-weibo 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"accounts-base@1.1.4-githubble.43\",\n        \"accounts-oauth@1.1.4-githubble.43\",\n        \"weibo@1.1.3-githubble.43\"\n      ],\n      \"accounts-weibo 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"accounts-base@1.2.0-rc.0\",\n        \"accounts-oauth@1.1.4-rc.0\",\n        \"weibo@1.1.3-rc.0\"\n      ],\n      \"accounts-weibo 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"accounts-base@1.1.4-winr.0\",\n        \"accounts-oauth@1.1.4-winr.0\",\n        \"weibo@1.1.3-winr.0\"\n      ],\n      \"accounts-weibo 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"accounts-base@1.1.4-winr.1\",\n        \"accounts-oauth@1.1.4-winr.1\",\n        \"weibo@1.1.3-winr.1\"\n      ],\n      \"accounts-weibo 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"accounts-base@1.1.4-winr.2\",\n        \"accounts-oauth@1.1.4-winr.2\",\n        \"weibo@1.1.3-winr.2\"\n      ],\n      \"accounts-ui 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"accounts-base@10.0.0-glasser.isopacket.0\",\n        \"accounts-ui-unstyled@10.0.0-glasser.isopacket.0\",\n        \"less@10.0.0-glasser.isopacket.0\"\n      ],\n      \"accounts-ui 1.0.0-glasser1\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-ui-unstyled\",\n        \"less\"\n      ],\n      \"accounts-ui 1.0.0\": [\n        \"accounts-base@1.0.0\",\n        \"accounts-ui-unstyled@1.0.0\",\n        \"less@1.0.5\",\n        \"meteor@1.0.2\"\n      ],\n      \"accounts-ui 1.0.1-ekate\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-ui-unstyled\",\n        \"less\"\n      ],\n      \"accounts-ui 1.1.0-rc0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-ui-unstyled\",\n        \"less\"\n      ],\n      \"accounts-ui 1.1.0-rc1\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-ui-unstyled\",\n        \"less\"\n      ],\n      \"accounts-ui 1.1.0\": [\n        \"accounts-base@1.1.0\",\n        \"accounts-ui-unstyled@1.1.1\",\n        \"less@1.0.8\",\n        \"meteor@1.1.0\"\n      ],\n      \"accounts-ui 1.1.1-rc0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-ui-unstyled\",\n        \"less\"\n      ],\n      \"accounts-ui 1.1.1\": [\n        \"accounts-base@1.1.1\",\n        \"accounts-ui-unstyled@1.1.2\",\n        \"less@1.0.9\",\n        \"meteor@1.1.1\"\n      ],\n      \"accounts-ui 1.1.2-pre.0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-ui-unstyled\",\n        \"less\"\n      ],\n      \"accounts-ui 1.1.2-pre.1\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-ui-unstyled\",\n        \"less\"\n      ],\n      \"accounts-ui 1.1.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"accounts-base@1.1.2-pre.2\",\n        \"accounts-ui-unstyled@1.1.3-pre.2\",\n        \"less@1.0.10-pre.2\"\n      ],\n      \"accounts-ui 1.1.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"accounts-base@1.1.2-rc.0\",\n        \"accounts-ui-unstyled@1.1.3-rc.0\",\n        \"less@1.0.10-rc.0\"\n      ],\n      \"accounts-ui 1.1.2\": [\n        \"meteor@1.1.2\",\n        \"accounts-base@1.1.2\",\n        \"accounts-ui-unstyled@1.1.3\",\n        \"less@1.0.10\"\n      ],\n      \"accounts-ui 1.1.3-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"accounts-base@1.1.2\",\n        \"accounts-ui-unstyled@1.1.4-rc.0\",\n        \"less@1.0.11-rc.4\"\n      ],\n      \"accounts-ui 1.1.3-rc.1\": [\n        \"meteor@1.1.3-rc.0\",\n        \"accounts-base@1.1.2\",\n        \"accounts-ui-unstyled@1.1.4-rc.1\",\n        \"less@1.0.11-rc.6\"\n      ],\n      \"accounts-ui 1.1.3-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"accounts-base@1.1.2-win.0\",\n        \"accounts-ui-unstyled@1.1.4-win.0\",\n        \"less@1.0.11-win.0\"\n      ],\n      \"accounts-ui 1.1.3\": [\n        \"meteor@1.1.3\",\n        \"accounts-base@1.1.2\",\n        \"accounts-ui-unstyled@1.1.4\",\n        \"less@1.0.11\"\n      ],\n      \"accounts-ui 1.1.4-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"accounts-base@1.1.3-ipc.0\",\n        \"accounts-ui-unstyled@1.1.5-ipc.0\",\n        \"less@1.0.12-ipc.0\"\n      ],\n      \"accounts-ui 1.1.4-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"accounts-base@1.1.3-rc.1\",\n        \"accounts-ui-unstyled@1.1.5-rc.1\",\n        \"less@1.0.12-rc.1\"\n      ],\n      \"accounts-ui 1.1.4-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"accounts-base@1.1.3-slava.0\",\n        \"accounts-ui-unstyled@1.1.5-slava.0\",\n        \"less@1.0.12-slava.0\"\n      ],\n      \"accounts-ui 1.1.4-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"accounts-base@1.1.3-win.0\",\n        \"accounts-ui-unstyled@1.1.5-win.0\",\n        \"less@1.0.12-win.0\"\n      ],\n      \"accounts-ui 1.1.4-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"accounts-base@1.1.3-winr.0\",\n        \"accounts-ui-unstyled@1.1.5-winr.0\",\n        \"less@1.0.12-winr.0\"\n      ],\n      \"accounts-ui 1.1.4\": [\n        \"meteor@1.1.4\",\n        \"accounts-base@1.1.3\",\n        \"accounts-ui-unstyled@1.1.5\",\n        \"less@1.0.12\"\n      ],\n      \"accounts-ui 1.1.5-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"accounts-base@1.1.4-eachin.43\",\n        \"accounts-ui-unstyled@1.1.6-eachin.43\",\n        \"less@1.0.13-eachin.43\"\n      ],\n      \"accounts-ui 1.1.5-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"accounts-base@1.1.4-githubble.0\",\n        \"accounts-ui-unstyled@1.1.6-githubble.0\",\n        \"less@1.0.13-githubble.0\"\n      ],\n      \"accounts-ui 1.1.5-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"accounts-base@1.1.4-githubble.2\",\n        \"accounts-ui-unstyled@1.1.6-githubble.2\",\n        \"less@1.0.13-githubble.2\"\n      ],\n      \"accounts-ui 1.1.5-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"accounts-base@1.1.4-githubble.42\",\n        \"accounts-ui-unstyled@1.1.6-githubble.42\",\n        \"less@1.0.13-githubble.42\"\n      ],\n      \"accounts-ui 1.1.5-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"accounts-base@1.1.4-githubble.43\",\n        \"accounts-ui-unstyled@1.1.6-githubble.43\",\n        \"less@1.0.13-githubble.43\"\n      ],\n      \"accounts-ui 1.1.5-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"accounts-base@1.2.0-rc.0\",\n        \"accounts-ui-unstyled@1.1.7-rc.0\",\n        \"less@1.0.13-rc.0\"\n      ],\n      \"accounts-ui 1.1.5-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"accounts-base@1.1.4-winr.0\",\n        \"accounts-ui-unstyled@1.1.6-winr.0\",\n        \"less@1.0.13-winr.0\"\n      ],\n      \"accounts-ui 1.1.5-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"accounts-base@1.1.4-winr.1\",\n        \"accounts-ui-unstyled@1.1.6-winr.1\",\n        \"less@1.0.13-winr.1\"\n      ],\n      \"accounts-ui 1.1.5-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"accounts-base@1.1.4-winr.2\",\n        \"accounts-ui-unstyled@1.1.6-winr.4\",\n        \"less@1.0.13-winr.2\"\n      ],\n      \"accounts-ui-unstyled 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"?accounts-oauth@10.0.0-glasser.isopacket.0\",\n        \"?accounts-password@10.0.0-glasser.isopacket.0\",\n        \"accounts-base@10.0.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\",\n        \"service-configuration@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"templating@10.0.0-glasser.isopacket.0\",\n        \"session@10.0.0-glasser.isopacket.0\"\n      ],\n      \"accounts-ui-unstyled 1.0.0\": [\n        \"accounts-base@1.0.0\",\n        \"?accounts-oauth@1.0.0\",\n        \"?accounts-password@1.0.0\",\n        \"deps@1.0.1\",\n        \"meteor@1.0.2\",\n        \"service-configuration@1.0.0\",\n        \"session@1.0.0\",\n        \"templating@1.0.4\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-ui-unstyled 1.0.1-glasser1\": [\n        \"meteor\",\n        \"?accounts-oauth\",\n        \"?accounts-password\",\n        \"accounts-base\",\n        \"tracker\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"session\"\n      ],\n      \"accounts-ui-unstyled 1.0.1-rc0\": [\n        \"meteor\",\n        \"?accounts-oauth\",\n        \"?accounts-password\",\n        \"accounts-base\",\n        \"tracker\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"session\"\n      ],\n      \"accounts-ui-unstyled 1.0.1\": [\n        \"accounts-base@1.0.1\",\n        \"?accounts-oauth@1.0.0\",\n        \"?accounts-password@1.0.1\",\n        \"meteor@1.0.3\",\n        \"service-configuration@1.0.1\",\n        \"session@1.0.1\",\n        \"templating@1.0.5\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-ui-unstyled 1.0.2-ekate\": [\n        \"meteor\",\n        \"?accounts-oauth\",\n        \"?accounts-password\",\n        \"accounts-base\",\n        \"tracker\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"session\"\n      ],\n      \"accounts-ui-unstyled 1.1.0-rc0\": [\n        \"meteor\",\n        \"?accounts-oauth\",\n        \"?accounts-password\",\n        \"accounts-base\",\n        \"tracker\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"session\"\n      ],\n      \"accounts-ui-unstyled 1.1.1-rc0\": [\n        \"meteor\",\n        \"?accounts-oauth\",\n        \"?accounts-password\",\n        \"accounts-base\",\n        \"tracker\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"session\"\n      ],\n      \"accounts-ui-unstyled 1.1.1\": [\n        \"accounts-base@1.1.0\",\n        \"?accounts-oauth@1.1.0\",\n        \"?accounts-password@1.0.1\",\n        \"meteor@1.1.0\",\n        \"service-configuration@1.0.1\",\n        \"session@1.0.1\",\n        \"templating@1.0.6\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.2-rc0\": [\n        \"meteor\",\n        \"?accounts-oauth\",\n        \"?accounts-password\",\n        \"accounts-base\",\n        \"tracker\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"session\"\n      ],\n      \"accounts-ui-unstyled 1.1.2\": [\n        \"accounts-base@1.1.1\",\n        \"?accounts-oauth@1.1.1\",\n        \"?accounts-password@1.0.2\",\n        \"meteor@1.1.1\",\n        \"service-configuration@1.0.1\",\n        \"session@1.0.2\",\n        \"templating@1.0.7\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.3-pre.0\": [\n        \"meteor\",\n        \"?accounts-oauth\",\n        \"?accounts-password\",\n        \"accounts-base\",\n        \"tracker\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"session\"\n      ],\n      \"accounts-ui-unstyled 1.1.3-pre.1\": [\n        \"meteor\",\n        \"?accounts-oauth\",\n        \"?accounts-password\",\n        \"accounts-base\",\n        \"tracker\",\n        \"service-configuration\",\n        \"underscore\",\n        \"templating\",\n        \"session\"\n      ],\n      \"accounts-ui-unstyled 1.1.3-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"?accounts-oauth@1.1.2-pre.2\",\n        \"?accounts-password@1.0.3-pre.2\",\n        \"accounts-base@1.1.2-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"service-configuration@1.0.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"templating@1.0.8-pre.2\",\n        \"session@1.0.3-pre.2\"\n      ],\n      \"accounts-ui-unstyled 1.1.3-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"?accounts-oauth@1.1.2-rc.0\",\n        \"?accounts-password@1.0.3-rc.0\",\n        \"accounts-base@1.1.2-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"templating@1.0.8-rc.0\",\n        \"session@1.0.3-rc.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.3-refreshpolicy.1\": [\n        \"meteor@1.1.2-refreshpolicy.1\",\n        \"?accounts-oauth@1.1.2\",\n        \"?accounts-password@1.0.3-refreshpolicy.1\",\n        \"accounts-base@1.1.2\",\n        \"tracker@1.0.3\",\n        \"service-configuration@1.0.2\",\n        \"underscore@1.0.1\",\n        \"templating@1.0.8\",\n        \"session@1.0.3-refreshpolicy.1\"\n      ],\n      \"accounts-ui-unstyled 1.1.3\": [\n        \"meteor@1.1.2\",\n        \"?accounts-oauth@1.1.2\",\n        \"?accounts-password@1.0.3\",\n        \"accounts-base@1.1.2\",\n        \"tracker@1.0.3\",\n        \"service-configuration@1.0.2\",\n        \"underscore@1.0.1\",\n        \"templating@1.0.8\",\n        \"session@1.0.3\"\n      ],\n      \"accounts-ui-unstyled 1.1.4-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"?accounts-oauth@1.1.2\",\n        \"?accounts-password@1.0.4-rc.0\",\n        \"accounts-base@1.1.2\",\n        \"tracker@1.0.3\",\n        \"service-configuration@1.0.2\",\n        \"underscore@1.0.1\",\n        \"templating@1.0.9-rc.0\",\n        \"session@1.0.4-rc.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.4-rc.1\": [\n        \"meteor@1.1.3-rc.0\",\n        \"?accounts-oauth@1.1.2\",\n        \"?accounts-password@1.0.4-rc.0\",\n        \"accounts-base@1.1.2\",\n        \"tracker@1.0.3\",\n        \"service-configuration@1.0.2\",\n        \"underscore@1.0.1\",\n        \"templating@1.0.9-rc.2\",\n        \"session@1.0.4-rc.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.4-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"?accounts-oauth@1.1.2-win.0\",\n        \"?accounts-password@1.0.4-win.0\",\n        \"accounts-base@1.1.2-win.0\",\n        \"tracker@1.0.3-win.0\",\n        \"service-configuration@1.0.2-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"templating@1.0.9-win.0\",\n        \"session@1.0.4-win.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.4\": [\n        \"meteor@1.1.3\",\n        \"?accounts-oauth@1.1.2\",\n        \"?accounts-password@1.0.4\",\n        \"accounts-base@1.1.2\",\n        \"tracker@1.0.3\",\n        \"service-configuration@1.0.2\",\n        \"underscore@1.0.1\",\n        \"templating@1.0.9\",\n        \"session@1.0.4\"\n      ],\n      \"accounts-ui-unstyled 1.1.5-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"?accounts-oauth@1.1.3-ipc.0\",\n        \"?accounts-password@1.0.5-ipc.0\",\n        \"accounts-base@1.1.3-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"service-configuration@1.0.3-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"templating@1.0.10-ipc.0\",\n        \"session@1.0.5-ipc.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.5-ipc.1\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"?accounts-oauth@1.1.3-ipc.0\",\n        \"?accounts-password@1.0.5-ipc.0\",\n        \"accounts-base@1.1.3-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"service-configuration@1.0.3-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"templating@1.0.10-ipc.0\",\n        \"session@1.0.5-ipc.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.5-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"?accounts-oauth@1.1.3-rc.1\",\n        \"?accounts-password@1.0.5-rc.1\",\n        \"accounts-base@1.1.3-rc.1\",\n        \"tracker@1.0.4-rc.1\",\n        \"service-configuration@1.0.3-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"templating@1.0.10-rc.1\",\n        \"session@1.0.5-rc.1\"\n      ],\n      \"accounts-ui-unstyled 1.1.5-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"?accounts-oauth@1.1.3-slava.0\",\n        \"?accounts-password@1.0.5-slava.0\",\n        \"accounts-base@1.1.3-slava.0\",\n        \"tracker@1.0.4-slava.0\",\n        \"service-configuration@1.0.3-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"templating@1.0.10-slava.0\",\n        \"session@1.0.5-slava.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.5-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"?accounts-oauth@1.1.3-win.0\",\n        \"?accounts-password@1.0.4-win.2\",\n        \"accounts-base@1.1.3-win.0\",\n        \"tracker@1.0.4-win.0\",\n        \"service-configuration@1.0.3-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"templating@1.0.10-win.0\",\n        \"session@1.0.5-win.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.5-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"?accounts-oauth@1.1.3-winr.0\",\n        \"?accounts-password@1.0.5-winr.0\",\n        \"accounts-base@1.1.3-winr.0\",\n        \"tracker@1.0.4-winr.0\",\n        \"service-configuration@1.0.3-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"templating@1.0.10-winr.0\",\n        \"session@1.0.5-winr.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.5\": [\n        \"meteor@1.1.4\",\n        \"?accounts-oauth@1.1.3\",\n        \"?accounts-password@1.0.5\",\n        \"accounts-base@1.1.3\",\n        \"tracker@1.0.4\",\n        \"service-configuration@1.0.3\",\n        \"underscore@1.0.2\",\n        \"templating@1.0.10\",\n        \"session@1.0.5\"\n      ],\n      \"accounts-ui-unstyled 1.1.6-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"?accounts-oauth@1.1.4-eachin.43\",\n        \"?accounts-password@1.0.6-eachin.43\",\n        \"accounts-base@1.1.4-eachin.43\",\n        \"tracker@1.0.5-eachin.43\",\n        \"service-configuration@1.0.4-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"templating@1.0.12-eachin.43\",\n        \"session@1.0.6-eachin.43\"\n      ],\n      \"accounts-ui-unstyled 1.1.6-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"?accounts-oauth@1.1.4-githubble.0\",\n        \"?accounts-password@1.0.6-githubble.0\",\n        \"accounts-base@1.1.4-githubble.0\",\n        \"tracker@1.0.5-githubble.0\",\n        \"service-configuration@1.0.4-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"templating@1.0.12-githubble.0\",\n        \"session@1.0.6-githubble.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.6-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"?accounts-oauth@1.1.4-githubble.2\",\n        \"?accounts-password@1.0.6-githubble.2\",\n        \"accounts-base@1.1.4-githubble.2\",\n        \"tracker@1.0.5-githubble.2\",\n        \"service-configuration@1.0.4-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"templating@1.0.12-githubble.2\",\n        \"session@1.0.6-githubble.2\"\n      ],\n      \"accounts-ui-unstyled 1.1.6-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"?accounts-oauth@1.1.4-githubble.42\",\n        \"?accounts-password@1.0.6-githubble.42\",\n        \"accounts-base@1.1.4-githubble.42\",\n        \"tracker@1.0.5-githubble.42\",\n        \"service-configuration@1.0.4-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"templating@1.0.12-githubble.42\",\n        \"session@1.0.6-githubble.42\"\n      ],\n      \"accounts-ui-unstyled 1.1.6-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"?accounts-oauth@1.1.4-githubble.43\",\n        \"?accounts-password@1.0.6-githubble.43\",\n        \"accounts-base@1.1.4-githubble.43\",\n        \"tracker@1.0.5-githubble.43\",\n        \"service-configuration@1.0.4-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"templating@1.0.12-githubble.43\",\n        \"session@1.0.6-githubble.43\"\n      ],\n      \"accounts-ui-unstyled 1.1.6-rc.0\": [\n        \"meteor@1.1.4\",\n        \"?accounts-oauth@1.1.3\",\n        \"?accounts-password@1.0.5\",\n        \"accounts-base@1.1.3\",\n        \"tracker@1.0.5-rc.0\",\n        \"service-configuration@1.0.3\",\n        \"underscore@1.0.2\",\n        \"templating@1.0.11-rc.0\",\n        \"session@1.0.5\"\n      ],\n      \"accounts-ui-unstyled 1.1.6-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"?accounts-oauth@1.1.4-winr.0\",\n        \"?accounts-password@1.0.6-winr.0\",\n        \"accounts-base@1.1.4-winr.0\",\n        \"tracker@1.0.5-winr.0\",\n        \"service-configuration@1.0.4-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"templating@1.0.11-winr.0\",\n        \"session@1.0.6-winr.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.6-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"?accounts-oauth@1.1.4-winr.1\",\n        \"?accounts-password@1.0.6-winr.1\",\n        \"accounts-base@1.1.4-winr.1\",\n        \"tracker@1.0.5-winr.1\",\n        \"service-configuration@1.0.4-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"templating@1.0.11-winr.1\",\n        \"session@1.0.6-winr.1\"\n      ],\n      \"accounts-ui-unstyled 1.1.6-winr.2\": [\n        \"meteor@1.1.5-winr.2\",\n        \"?accounts-oauth@1.1.3\",\n        \"?accounts-password@1.0.6-winr.3\",\n        \"accounts-base@1.1.3\",\n        \"tracker@1.0.5-winr.2\",\n        \"service-configuration@1.0.3\",\n        \"underscore@1.0.2\",\n        \"templating@1.0.11-winr.2\",\n        \"session@1.0.5\"\n      ],\n      \"accounts-ui-unstyled 1.1.6-winr.3\": [\n        \"meteor@1.1.5-winr.3\",\n        \"?accounts-oauth@1.1.3\",\n        \"?accounts-password@1.0.6-winr.4\",\n        \"accounts-base@1.1.3\",\n        \"tracker@1.0.5-winr.3\",\n        \"service-configuration@1.0.3\",\n        \"underscore@1.0.2\",\n        \"templating@1.0.11-winr.3\",\n        \"session@1.0.5\"\n      ],\n      \"accounts-ui-unstyled 1.1.6-winr.4\": [\n        \"meteor@1.1.5-winr.4\",\n        \"?accounts-oauth@1.1.4-winr.2\",\n        \"?accounts-password@1.0.6-winr.5\",\n        \"accounts-base@1.1.4-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"templating@1.0.11-winr.4\",\n        \"session@1.0.6-winr.2\"\n      ],\n      \"accounts-ui-unstyled 1.1.6\": [\n        \"meteor@1.1.4\",\n        \"?accounts-oauth@1.1.3\",\n        \"?accounts-password@1.0.6\",\n        \"accounts-base@1.1.3\",\n        \"tracker@1.0.5\",\n        \"service-configuration@1.0.3\",\n        \"underscore@1.0.2\",\n        \"templating@1.0.11\",\n        \"session@1.0.5\"\n      ],\n      \"accounts-ui-unstyled 1.1.7-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"?accounts-oauth@1.1.4-rc.0\",\n        \"?accounts-password@1.1.0-rc.0\",\n        \"accounts-base@1.2.0-rc.0\",\n        \"tracker@1.0.6-rc.0\",\n        \"service-configuration@1.0.4-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"templating@1.1.0-rc.0\",\n        \"session@1.1.0-rc.0\"\n      ],\n      \"accounts-ui-unstyled 1.1.7-winr.4\": [\n        \"meteor@1.1.5-winr.6\",\n        \"?accounts-oauth@1.1.4-winr.2\",\n        \"?accounts-password@1.0.7-winr.6\",\n        \"accounts-base@1.1.4-winr.3\",\n        \"tracker@1.0.6-winr.4\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"templating@1.0.12-winr.7\",\n        \"session@1.0.6-winr.3\"\n      ],\n      \"accounts-twitter 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"accounts-base@10.0.0-glasser.isopacket.0\",\n        \"accounts-oauth@10.0.0-glasser.isopacket.0\",\n        \"twitter@10.0.0-glasser.isopacket.0\",\n        \"http@10.0.0-glasser.isopacket.0\"\n      ],\n      \"accounts-twitter 1.0.0-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"twitter\",\n        \"http\"\n      ],\n      \"accounts-twitter 1.0.0\": [\n        \"accounts-base@1.0.0\",\n        \"accounts-oauth@1.0.0\",\n        \"http@1.0.2\",\n        \"meteor@1.0.2\",\n        \"twitter@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-twitter 1.0.1\": [\n        \"accounts-base@1.1.1\",\n        \"accounts-oauth@1.1.1\",\n        \"http@1.0.6\",\n        \"meteor@1.1.1\",\n        \"twitter@1.1.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-twitter 1.0.2-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"twitter\",\n        \"http\"\n      ],\n      \"accounts-twitter 1.0.2-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"twitter\",\n        \"http\"\n      ],\n      \"accounts-twitter 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"accounts-base@1.1.2-pre.2\",\n        \"accounts-oauth@1.1.2-pre.2\",\n        \"twitter@1.1.1-pre.2\",\n        \"http@1.0.7-pre.2\"\n      ],\n      \"accounts-twitter 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"accounts-base@1.1.2-rc.0\",\n        \"accounts-oauth@1.1.2-rc.0\",\n        \"twitter@1.1.1-rc.0\",\n        \"http@1.0.7-rc.0\"\n      ],\n      \"accounts-twitter 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"accounts-base@1.1.2-win.0\",\n        \"accounts-oauth@1.1.2-win.0\",\n        \"twitter@1.1.2-win.0\",\n        \"http@1.0.8-win.0\"\n      ],\n      \"accounts-twitter 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"accounts-base@1.1.2\",\n        \"accounts-oauth@1.1.2\",\n        \"twitter@1.1.1\",\n        \"http@1.0.7\"\n      ],\n      \"accounts-twitter 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"accounts-base@1.1.3-ipc.0\",\n        \"accounts-oauth@1.1.3-ipc.0\",\n        \"twitter@1.1.3-ipc.0\",\n        \"http@1.0.9-ipc.0\"\n      ],\n      \"accounts-twitter 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"accounts-base@1.1.3-rc.1\",\n        \"accounts-oauth@1.1.3-rc.1\",\n        \"twitter@1.1.3-rc.1\",\n        \"http@1.0.9-rc.1\"\n      ],\n      \"accounts-twitter 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"accounts-base@1.1.3-slava.0\",\n        \"accounts-oauth@1.1.3-slava.0\",\n        \"twitter@1.1.3-slava.0\",\n        \"http@1.0.9-slava.0\"\n      ],\n      \"accounts-twitter 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"accounts-base@1.1.3-win.0\",\n        \"accounts-oauth@1.1.3-win.0\",\n        \"twitter@1.1.3-win.0\",\n        \"http@1.0.9-win.0\"\n      ],\n      \"accounts-twitter 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"accounts-base@1.1.3-winr.0\",\n        \"accounts-oauth@1.1.3-winr.0\",\n        \"twitter@1.1.3-winr.0\",\n        \"http@1.0.9-winr.0\"\n      ],\n      \"accounts-twitter 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"accounts-base@1.1.3\",\n        \"accounts-oauth@1.1.3\",\n        \"twitter@1.1.3\",\n        \"http@1.0.9\"\n      ],\n      \"accounts-twitter 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"accounts-base@1.1.4-eachin.43\",\n        \"accounts-oauth@1.1.4-eachin.43\",\n        \"twitter@1.1.4-eachin.43\",\n        \"http@1.0.10-eachin.43\"\n      ],\n      \"accounts-twitter 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"accounts-base@1.1.4-githubble.0\",\n        \"accounts-oauth@1.1.4-githubble.0\",\n        \"twitter@1.1.4-githubble.0\",\n        \"http@1.0.10-githubble.0\"\n      ],\n      \"accounts-twitter 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"accounts-base@1.1.4-githubble.2\",\n        \"accounts-oauth@1.1.4-githubble.2\",\n        \"twitter@1.1.4-githubble.2\",\n        \"http@1.0.10-githubble.2\"\n      ],\n      \"accounts-twitter 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"accounts-base@1.1.4-githubble.42\",\n        \"accounts-oauth@1.1.4-githubble.42\",\n        \"twitter@1.1.4-githubble.42\",\n        \"http@1.0.10-githubble.42\"\n      ],\n      \"accounts-twitter 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"accounts-base@1.1.4-githubble.43\",\n        \"accounts-oauth@1.1.4-githubble.43\",\n        \"twitter@1.1.4-githubble.43\",\n        \"http@1.0.10-githubble.43\"\n      ],\n      \"accounts-twitter 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"accounts-base@1.2.0-rc.0\",\n        \"accounts-oauth@1.1.4-rc.0\",\n        \"twitter@1.1.4-rc.0\",\n        \"http@1.1.0-rc.0\"\n      ],\n      \"accounts-twitter 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"accounts-base@1.1.4-winr.0\",\n        \"accounts-oauth@1.1.4-winr.0\",\n        \"twitter@1.1.4-winr.0\",\n        \"http@1.0.10-winr.0\"\n      ],\n      \"accounts-twitter 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"accounts-base@1.1.4-winr.1\",\n        \"accounts-oauth@1.1.4-winr.1\",\n        \"twitter@1.1.4-winr.1\",\n        \"http@1.0.10-winr.1\"\n      ],\n      \"accounts-twitter 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"accounts-base@1.1.4-winr.2\",\n        \"accounts-oauth@1.1.4-winr.2\",\n        \"twitter@1.1.4-winr.2\",\n        \"http@1.0.10-winr.4\"\n      ],\n      \"accounts-password 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@10.0.0-glasser.isopacket.0\",\n        \"srp@10.0.0-glasser.isopacket.0\",\n        \"sha@10.0.0-glasser.isopacket.0\",\n        \"email@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"check@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"ddp@10.0.0-glasser.isopacket.0\"\n      ],\n      \"accounts-password 1.0.0\": [\n        \"accounts-base@1.0.0\",\n        \"check@1.0.0\",\n        \"email@1.0.2\",\n        \"livedata@1.0.7\",\n        \"meteor@1.0.2\",\n        \"npm-bcrypt@=0.7.7\",\n        \"random@1.0.0\",\n        \"sha@1.0.0\",\n        \"srp@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-password 1.0.1-rc0\": [\n        \"meteor\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base\",\n        \"srp\",\n        \"sha\",\n        \"email\",\n        \"random\",\n        \"check\",\n        \"underscore\",\n        \"livedata\"\n      ],\n      \"accounts-password 1.0.1-rc1\": [\n        \"meteor\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base\",\n        \"srp\",\n        \"sha\",\n        \"email\",\n        \"random\",\n        \"check\",\n        \"underscore\",\n        \"ddp\"\n      ],\n      \"accounts-password 1.0.1\": [\n        \"accounts-base@1.0.1\",\n        \"check@1.0.0\",\n        \"ddp@1.0.8\",\n        \"email@1.0.2\",\n        \"meteor@1.0.3\",\n        \"npm-bcrypt@=0.7.7\",\n        \"random@1.0.0\",\n        \"sha@1.0.0\",\n        \"srp@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-password 1.0.2-ekate\": [\n        \"meteor\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base\",\n        \"srp\",\n        \"sha\",\n        \"email\",\n        \"random\",\n        \"check\",\n        \"underscore\",\n        \"ddp\"\n      ],\n      \"accounts-password 1.0.2-rc0\": [\n        \"meteor\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base\",\n        \"srp\",\n        \"sha\",\n        \"email\",\n        \"random\",\n        \"check\",\n        \"underscore\",\n        \"ddp\"\n      ],\n      \"accounts-password 1.0.2\": [\n        \"accounts-base@1.1.1\",\n        \"check@1.0.1\",\n        \"ddp@1.0.9\",\n        \"email@1.0.3\",\n        \"meteor@1.1.1\",\n        \"npm-bcrypt@=0.7.7\",\n        \"random@1.0.0\",\n        \"sha@1.0.0\",\n        \"srp@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-password 1.0.3-pre.0\": [\n        \"meteor\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base\",\n        \"srp\",\n        \"sha\",\n        \"email\",\n        \"random\",\n        \"check\",\n        \"underscore\",\n        \"ddp\"\n      ],\n      \"accounts-password 1.0.3-pre.1\": [\n        \"meteor\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base\",\n        \"srp\",\n        \"sha\",\n        \"email\",\n        \"random\",\n        \"check\",\n        \"underscore\",\n        \"ddp\"\n      ],\n      \"accounts-password 1.0.3-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.2-pre.2\",\n        \"srp@1.0.1-pre.1\",\n        \"sha@1.0.1-pre.2\",\n        \"email@1.0.4-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"check@1.0.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"ddp@1.0.10-pre.2\"\n      ],\n      \"accounts-password 1.0.3-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.2-rc.0\",\n        \"srp@1.0.1-rc.0\",\n        \"sha@1.0.1-rc.0\",\n        \"email@1.0.4-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"ddp@1.0.10-rc.0\"\n      ],\n      \"accounts-password 1.0.3-refreshpolicy.1\": [\n        \"meteor@1.1.2-refreshpolicy.1\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.2\",\n        \"srp@1.0.1\",\n        \"sha@1.0.1\",\n        \"email@1.0.4\",\n        \"random@1.0.1\",\n        \"check@1.0.2\",\n        \"underscore@1.0.1\",\n        \"ddp@1.0.10-refreshpolicy.1\"\n      ],\n      \"accounts-password 1.0.3\": [\n        \"meteor@1.1.2\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.2\",\n        \"srp@1.0.1\",\n        \"sha@1.0.1\",\n        \"email@1.0.4\",\n        \"random@1.0.1\",\n        \"check@1.0.2\",\n        \"underscore@1.0.1\",\n        \"ddp@1.0.10\"\n      ],\n      \"accounts-password 1.0.4-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.2\",\n        \"srp@1.0.1\",\n        \"sha@1.0.1\",\n        \"email@1.0.4\",\n        \"random@1.0.1\",\n        \"check@1.0.2\",\n        \"underscore@1.0.1\",\n        \"ddp@1.0.11-rc.0\"\n      ],\n      \"accounts-password 1.0.4-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"junk:npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.2-win.0\",\n        \"srp@1.0.1-win.0\",\n        \"sha@1.0.1-win.0\",\n        \"email@1.0.4-win.0\",\n        \"random@1.0.1-win.0\",\n        \"check@1.0.2-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"ddp@1.0.11-win.0\"\n      ],\n      \"accounts-password 1.0.4-win.1\": [\n        \"meteor@1.1.3-win.0\",\n        \"junk:npm-bcrypt@=0.7.8\",\n        \"accounts-base@1.1.2-win.0\",\n        \"srp@1.0.1-win.0\",\n        \"sha@1.0.1-win.0\",\n        \"email@1.0.4-win.0\",\n        \"random@1.0.1-win.0\",\n        \"check@1.0.2-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"ddp@1.0.11-win.0\"\n      ],\n      \"accounts-password 1.0.4-win.2\": [\n        \"meteor@1.1.3-win.0\",\n        \"npm-bcrypt@=0.7.8-win.0\",\n        \"accounts-base@1.1.2-win.0\",\n        \"srp@1.0.1-win.0\",\n        \"sha@1.0.1-win.0\",\n        \"email@1.0.4-win.0\",\n        \"random@1.0.1-win.0\",\n        \"check@1.0.2-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"ddp@1.0.11-win.0\"\n      ],\n      \"accounts-password 1.0.4\": [\n        \"meteor@1.1.3\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.2\",\n        \"srp@1.0.1\",\n        \"sha@1.0.1\",\n        \"email@1.0.4\",\n        \"random@1.0.1\",\n        \"check@1.0.2\",\n        \"underscore@1.0.1\",\n        \"ddp@1.0.11\"\n      ],\n      \"accounts-password 1.0.5-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.3-ipc.0\",\n        \"srp@1.0.2-ipc.0\",\n        \"sha@1.0.2-ipc.0\",\n        \"email@1.0.5-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"check@1.0.3-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"ddp@1.0.12-ipc.0\"\n      ],\n      \"accounts-password 1.0.5-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.3-rc.1\",\n        \"srp@1.0.2-rc.1\",\n        \"sha@1.0.2-rc.1\",\n        \"email@1.0.5-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"check@1.0.3-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"ddp@1.0.13-rc.1\"\n      ],\n      \"accounts-password 1.0.5-rc.2\": [\n        \"meteor@1.1.4-rc.1\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.3-rc.1\",\n        \"srp@1.0.2-rc.1\",\n        \"sha@1.0.2-rc.1\",\n        \"email@1.0.5-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"check@1.0.3-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"ddp@1.0.13-rc.1\"\n      ],\n      \"accounts-password 1.0.5-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.3-slava.0\",\n        \"srp@1.0.2-slava.0\",\n        \"sha@1.0.2-slava.0\",\n        \"email@1.0.5-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"check@1.0.3-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"ddp@1.0.13-slava.0\"\n      ],\n      \"accounts-password 1.0.5-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"npm-bcrypt@=0.7.8-win.0\",\n        \"accounts-base@1.1.3-winr.0\",\n        \"srp@1.0.2-winr.0\",\n        \"sha@1.0.2-winr.0\",\n        \"email@1.0.5-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"check@1.0.3-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"ddp@1.0.13-winr.0\"\n      ],\n      \"accounts-password 1.0.5\": [\n        \"meteor@1.1.4\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.3\",\n        \"srp@1.0.2\",\n        \"sha@1.0.2\",\n        \"email@1.0.5\",\n        \"random@1.0.2\",\n        \"check@1.0.3\",\n        \"underscore@1.0.2\",\n        \"ddp@1.0.13\"\n      ],\n      \"accounts-password 1.0.6-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"npm-bcrypt@0.7.8-winr.3\",\n        \"accounts-base@1.1.4-eachin.43\",\n        \"srp@1.0.3-eachin.43\",\n        \"sha@1.0.3-eachin.43\",\n        \"email@1.0.6-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"check@1.0.4-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"ddp@1.0.15-eachin.43\"\n      ],\n      \"accounts-password 1.0.6-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"npm-bcrypt@0.7.8-winr.3\",\n        \"accounts-base@1.1.4-githubble.0\",\n        \"srp@1.0.3-githubble.0\",\n        \"sha@1.0.3-githubble.0\",\n        \"email@1.0.6-githubble.0\",\n        \"random@1.0.3-githubble.0\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"ddp@1.0.15-githubble.0\"\n      ],\n      \"accounts-password 1.0.6-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"npm-bcrypt@0.7.8-winr.3\",\n        \"accounts-base@1.1.4-githubble.2\",\n        \"srp@1.0.3-githubble.2\",\n        \"sha@1.0.3-githubble.2\",\n        \"email@1.0.6-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.3-githubble.2\",\n        \"ddp@1.0.15-githubble.2\"\n      ],\n      \"accounts-password 1.0.6-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"npm-bcrypt@0.7.8-winr.3\",\n        \"accounts-base@1.1.4-githubble.42\",\n        \"srp@1.0.3-githubble.42\",\n        \"sha@1.0.3-githubble.42\",\n        \"email@1.0.6-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.3-githubble.42\",\n        \"ddp@1.0.15-githubble.42\"\n      ],\n      \"accounts-password 1.0.6-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"npm-bcrypt@0.7.8-winr.3\",\n        \"accounts-base@1.1.4-githubble.43\",\n        \"srp@1.0.3-githubble.43\",\n        \"sha@1.0.3-githubble.43\",\n        \"email@1.0.6-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"check@1.0.4-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"ddp@1.0.15-githubble.43\"\n      ],\n      \"accounts-password 1.0.6-rc.0\": [\n        \"meteor@1.1.4\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.3\",\n        \"srp@1.0.2\",\n        \"sha@1.0.2\",\n        \"email@1.0.5\",\n        \"random@1.0.2\",\n        \"check@1.0.4-rc.0\",\n        \"underscore@1.0.2\",\n        \"ddp@1.0.14-rc.0\"\n      ],\n      \"accounts-password 1.0.6-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"accounts-base@1.1.4-winr.0\",\n        \"srp@1.0.3-winr.0\",\n        \"sha@1.0.3-winr.0\",\n        \"email@1.0.6-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"check@1.0.4-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"ddp@1.0.14-winr.0\"\n      ],\n      \"accounts-password 1.0.6-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"accounts-base@1.1.4-winr.1\",\n        \"srp@1.0.3-winr.1\",\n        \"sha@1.0.3-winr.1\",\n        \"email@1.0.6-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"check@1.0.4-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"ddp@1.0.14-winr.1\"\n      ],\n      \"accounts-password 1.0.6-winr.2\": [\n        \"meteor@1.1.5-winr.1\",\n        \"npm-bcrypt@0.7.8-winr.3\",\n        \"accounts-base@1.1.4-winr.1\",\n        \"srp@1.0.3-winr.1\",\n        \"sha@1.0.3-winr.1\",\n        \"email@1.0.6-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"check@1.0.4-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"ddp@1.0.14-winr.1\"\n      ],\n      \"accounts-password 1.0.6-winr.3\": [\n        \"meteor@1.1.5-winr.2\",\n        \"npm-bcrypt@0.7.8-winr.3\",\n        \"accounts-base@1.1.3\",\n        \"srp@1.0.2\",\n        \"sha@1.0.2\",\n        \"email@1.0.5\",\n        \"random@1.0.2\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.2\",\n        \"ddp@1.0.14-winr.2\"\n      ],\n      \"accounts-password 1.0.6-winr.4\": [\n        \"meteor@1.1.5-winr.3\",\n        \"npm-bcrypt@0.7.8-winr.3\",\n        \"accounts-base@1.1.3\",\n        \"srp@1.0.2\",\n        \"sha@1.0.2\",\n        \"email@1.0.5\",\n        \"random@1.0.2\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.2\",\n        \"ddp@1.0.14-winr.3\"\n      ],\n      \"accounts-password 1.0.6-winr.5\": [\n        \"meteor@1.1.5-winr.4\",\n        \"npm-bcrypt@0.7.8-winr.3\",\n        \"accounts-base@1.1.4-winr.2\",\n        \"srp@1.0.3-winr.2\",\n        \"sha@1.0.3-winr.2\",\n        \"email@1.0.6-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.3-winr.2\",\n        \"ddp@1.0.14-winr.4\"\n      ],\n      \"accounts-password 1.0.6-winr.6\": [\n        \"meteor@1.1.5-winr.5\",\n        \"npm-bcrypt@0.7.8-winr.3\",\n        \"accounts-base@1.1.4-winr.2\",\n        \"srp@1.0.3-winr.2\",\n        \"sha@1.0.3-winr.2\",\n        \"email@1.0.6-winr.3\",\n        \"random@1.0.3-winr.2\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.3-winr.2\",\n        \"ddp@1.0.14-winr.5\"\n      ],\n      \"accounts-password 1.0.6\": [\n        \"meteor@1.1.4\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.3\",\n        \"srp@1.0.2\",\n        \"sha@1.0.2\",\n        \"email@1.0.5\",\n        \"random@1.0.2\",\n        \"check@1.0.4\",\n        \"underscore@1.0.2\",\n        \"ddp@1.0.14\"\n      ],\n      \"accounts-password 1.0.7-blz.0\": [\n        \"meteor@1.1.4\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.3\",\n        \"srp@1.0.2\",\n        \"sha@1.0.2\",\n        \"email@1.0.5\",\n        \"random@1.0.2\",\n        \"check@1.0.4\",\n        \"underscore@1.0.2\",\n        \"ddp@1.0.15-blz.0\"\n      ],\n      \"accounts-password 1.0.7-vs.1\": [\n        \"meteor@1.1.5-vs.1\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.3\",\n        \"srp@1.0.2\",\n        \"sha@1.0.2\",\n        \"email@1.0.6-vs.1\",\n        \"random@1.0.2\",\n        \"check@1.0.4\",\n        \"underscore@1.0.2\",\n        \"ddp@1.0.15-vs.1\"\n      ],\n      \"accounts-password 1.0.7-vs.2\": [\n        \"meteor@1.1.5-vs.2\",\n        \"npm-bcrypt@=0.7.7\",\n        \"accounts-base@1.1.3\",\n        \"srp@1.0.2\",\n        \"sha@1.0.2\",\n        \"email@1.0.6-vs.2\",\n        \"random@1.0.2\",\n        \"check@1.0.4\",\n        \"underscore@1.0.2\",\n        \"ddp@1.0.15-vs.2\"\n      ],\n      \"accounts-password 1.0.7-winr.6\": [\n        \"meteor@1.1.5-winr.6\",\n        \"npm-bcrypt@0.7.8-winr.3\",\n        \"accounts-base@1.1.4-winr.3\",\n        \"srp@1.0.3-winr.2\",\n        \"sha@1.0.3-winr.2\",\n        \"email@1.0.6-winr.4\",\n        \"random@1.0.3-winr.2\",\n        \"check@1.0.5-win.0\",\n        \"underscore@1.0.3-winr.2\",\n        \"ddp@1.0.15-winr.6\"\n      ],\n      \"accounts-password 1.1.0-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"npm-bcrypt@=0.7.8_1\",\n        \"accounts-base@1.2.0-rc.0\",\n        \"srp@1.0.3-rc.0\",\n        \"sha@1.0.3-rc.0\",\n        \"email@1.0.6-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"check@1.0.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"ddp@1.1.0-rc.0\"\n      ],\n      \"junk:npm-bcrypt 0.7.7\": [\n        \"meteor\"\n      ],\n      \"junk:npm-bcrypt 0.7.8\": [\n        \"meteor\"\n      ],\n      \"junk:npm-bcrypt 0.7.11\": [\n        \"meteor\"\n      ],\n      \"npm-bcrypt 0.7.7\": [\n        \"meteor\"\n      ],\n      \"npm-bcrypt 0.7.8-win.0\": [\n        \"meteor\"\n      ],\n      \"npm-bcrypt 0.7.8-winr.1\": [\n        \"meteor\"\n      ],\n      \"npm-bcrypt 0.7.8-winr.3\": [\n        \"meteor\"\n      ],\n      \"npm-bcrypt 0.7.8_1\": [\n        \"meteor\"\n      ],\n      \"accounts-oauth 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"check@10.0.0-glasser.isopacket.0\",\n        \"webapp@10.0.0-glasser.isopacket.0\",\n        \"accounts-base@10.0.0-glasser.isopacket.0\",\n        \"oauth@10.0.0-glasser.isopacket.0\"\n      ],\n      \"accounts-oauth 1.0.0-glasser1\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"check\",\n        \"webapp\",\n        \"accounts-base\",\n        \"oauth\"\n      ],\n      \"accounts-oauth 1.0.0\": [\n        \"accounts-base@1.0.0\",\n        \"check@1.0.0\",\n        \"meteor@1.0.2\",\n        \"oauth@1.0.0\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.2\"\n      ],\n      \"accounts-oauth 1.0.1-ekate\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"check\",\n        \"webapp\",\n        \"accounts-base\",\n        \"oauth\"\n      ],\n      \"accounts-oauth 1.1.0-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"check\",\n        \"webapp\",\n        \"accounts-base\",\n        \"oauth\"\n      ],\n      \"accounts-oauth 1.1.0\": [\n        \"accounts-base@1.1.0\",\n        \"check@1.0.0\",\n        \"meteor@1.1.0\",\n        \"oauth@1.1.0\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\"\n      ],\n      \"accounts-oauth 1.1.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"check\",\n        \"webapp\",\n        \"accounts-base\",\n        \"oauth\"\n      ],\n      \"accounts-oauth 1.1.1\": [\n        \"accounts-base@1.1.1\",\n        \"check@1.0.1\",\n        \"meteor@1.1.1\",\n        \"oauth@1.1.0\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\",\n        \"webapp@1.1.2\"\n      ],\n      \"accounts-oauth 1.1.2-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"check\",\n        \"webapp\",\n        \"accounts-base\",\n        \"oauth\"\n      ],\n      \"accounts-oauth 1.1.2-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"check\",\n        \"webapp\",\n        \"accounts-base\",\n        \"oauth\"\n      ],\n      \"accounts-oauth 1.1.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"check@1.0.2-pre.2\",\n        \"webapp@1.1.3-pre.2\",\n        \"accounts-base@1.1.2-pre.2\",\n        \"oauth@1.1.1-pre.2\"\n      ],\n      \"accounts-oauth 1.1.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"webapp@1.1.3-rc.0\",\n        \"accounts-base@1.1.2-rc.0\",\n        \"oauth@1.1.1-rc.0\"\n      ],\n      \"accounts-oauth 1.1.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"random@1.0.1-win.0\",\n        \"check@1.0.2-win.0\",\n        \"webapp@1.1.4-win.0\",\n        \"accounts-base@1.1.2-win.0\",\n        \"oauth@1.1.2-win.0\"\n      ],\n      \"accounts-oauth 1.1.2\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"random@1.0.1\",\n        \"check@1.0.2\",\n        \"webapp@1.1.3\",\n        \"accounts-base@1.1.2\",\n        \"oauth@1.1.1\"\n      ],\n      \"accounts-oauth 1.1.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"check@1.0.3-ipc.0\",\n        \"webapp@1.1.5-ipc.0\",\n        \"accounts-base@1.1.3-ipc.0\",\n        \"oauth@1.1.3-ipc.0\"\n      ],\n      \"accounts-oauth 1.1.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"check@1.0.3-rc.1\",\n        \"webapp@1.1.5-rc.1\",\n        \"accounts-base@1.1.3-rc.1\",\n        \"oauth@1.1.3-rc.1\"\n      ],\n      \"accounts-oauth 1.1.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"check@1.0.3-slava.0\",\n        \"webapp@1.1.5-slava.0\",\n        \"accounts-base@1.1.3-slava.0\",\n        \"oauth@1.1.3-slava.0\"\n      ],\n      \"accounts-oauth 1.1.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"random@1.0.2-win.0\",\n        \"check@1.0.3-win.0\",\n        \"webapp@1.1.5-win.0\",\n        \"accounts-base@1.1.3-win.0\",\n        \"oauth@1.1.3-win.0\"\n      ],\n      \"accounts-oauth 1.1.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"check@1.0.3-winr.0\",\n        \"webapp@1.1.5-winr.0\",\n        \"accounts-base@1.1.3-winr.0\",\n        \"oauth@1.1.3-winr.0\"\n      ],\n      \"accounts-oauth 1.1.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"random@1.0.2\",\n        \"check@1.0.3\",\n        \"webapp@1.1.5\",\n        \"accounts-base@1.1.3\",\n        \"oauth@1.1.3\"\n      ],\n      \"accounts-oauth 1.1.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"check@1.0.4-eachin.43\",\n        \"webapp@1.1.7-eachin.43\",\n        \"accounts-base@1.1.4-eachin.43\",\n        \"oauth@1.1.4-eachin.43\"\n      ],\n      \"accounts-oauth 1.1.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"random@1.0.3-githubble.0\",\n        \"check@1.0.4-win.0\",\n        \"webapp@1.1.7-githubble.0\",\n        \"accounts-base@1.1.4-githubble.0\",\n        \"oauth@1.1.4-githubble.0\"\n      ],\n      \"accounts-oauth 1.1.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"check@1.0.4-win.0\",\n        \"webapp@1.1.7-githubble.2\",\n        \"accounts-base@1.1.4-githubble.2\",\n        \"oauth@1.1.4-githubble.2\"\n      ],\n      \"accounts-oauth 1.1.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"check@1.0.4-win.0\",\n        \"webapp@1.1.7-githubble.42\",\n        \"accounts-base@1.1.4-githubble.42\",\n        \"oauth@1.1.4-githubble.42\"\n      ],\n      \"accounts-oauth 1.1.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"check@1.0.4-githubble.43\",\n        \"webapp@1.1.7-githubble.43\",\n        \"accounts-base@1.1.4-githubble.43\",\n        \"oauth@1.1.4-githubble.43\"\n      ],\n      \"accounts-oauth 1.1.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"check@1.0.5-rc.0\",\n        \"webapp@1.2.0-rc.0\",\n        \"accounts-base@1.2.0-rc.0\",\n        \"oauth@1.1.4-rc.0\"\n      ],\n      \"accounts-oauth 1.1.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"check@1.0.4-winr.0\",\n        \"webapp@1.1.6-winr.0\",\n        \"accounts-base@1.1.4-winr.0\",\n        \"oauth@1.1.4-winr.0\"\n      ],\n      \"accounts-oauth 1.1.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"check@1.0.4-winr.1\",\n        \"webapp@1.1.6-winr.1\",\n        \"accounts-base@1.1.4-winr.1\",\n        \"oauth@1.1.4-winr.1\"\n      ],\n      \"accounts-oauth 1.1.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"check@1.0.4-win.0\",\n        \"webapp@1.1.6-winr.4\",\n        \"accounts-base@1.1.4-winr.2\",\n        \"oauth@1.1.4-winr.2\"\n      ],\n      \"accounts-meteor-developer 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"accounts-base@10.0.0-glasser.isopacket.0\",\n        \"accounts-oauth@10.0.0-glasser.isopacket.0\",\n        \"meteor-developer@10.0.0-glasser.isopacket.0\"\n      ],\n      \"accounts-meteor-developer 1.0.0\": [\n        \"accounts-base@1.0.0\",\n        \"accounts-oauth@1.0.0\",\n        \"meteor@1.0.2\",\n        \"meteor-developer@1.0.0\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-meteor-developer 1.0.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"meteor-developer\"\n      ],\n      \"accounts-meteor-developer 1.0.1\": [\n        \"accounts-base@1.1.1\",\n        \"accounts-oauth@1.1.1\",\n        \"meteor@1.1.1\",\n        \"meteor-developer@1.1.0\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-meteor-developer 1.0.2-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"meteor-developer\"\n      ],\n      \"accounts-meteor-developer 1.0.2-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"meteor-developer\"\n      ],\n      \"accounts-meteor-developer 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"accounts-base@1.1.2-pre.2\",\n        \"accounts-oauth@1.1.2-pre.2\",\n        \"meteor-developer@1.1.1-pre.2\"\n      ],\n      \"accounts-meteor-developer 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"accounts-base@1.1.2-rc.0\",\n        \"accounts-oauth@1.1.2-rc.0\",\n        \"meteor-developer@1.1.1-rc.0\"\n      ],\n      \"accounts-meteor-developer 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"random@1.0.1-win.0\",\n        \"accounts-base@1.1.2-win.0\",\n        \"accounts-oauth@1.1.2-win.0\",\n        \"meteor-developer@1.1.1-win.0\"\n      ],\n      \"accounts-meteor-developer 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"random@1.0.1\",\n        \"accounts-base@1.1.2\",\n        \"accounts-oauth@1.1.2\",\n        \"meteor-developer@1.1.1\"\n      ],\n      \"accounts-meteor-developer 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"accounts-base@1.1.3-ipc.0\",\n        \"accounts-oauth@1.1.3-ipc.0\",\n        \"meteor-developer@1.1.2-ipc.0\"\n      ],\n      \"accounts-meteor-developer 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"accounts-base@1.1.3-rc.1\",\n        \"accounts-oauth@1.1.3-rc.1\",\n        \"meteor-developer@1.1.2-rc.1\"\n      ],\n      \"accounts-meteor-developer 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"accounts-base@1.1.3-slava.0\",\n        \"accounts-oauth@1.1.3-slava.0\",\n        \"meteor-developer@1.1.2-slava.0\"\n      ],\n      \"accounts-meteor-developer 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"random@1.0.2-win.0\",\n        \"accounts-base@1.1.3-win.0\",\n        \"accounts-oauth@1.1.3-win.0\",\n        \"meteor-developer@1.1.2-win.0\"\n      ],\n      \"accounts-meteor-developer 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"accounts-base@1.1.3-winr.0\",\n        \"accounts-oauth@1.1.3-winr.0\",\n        \"meteor-developer@1.1.2-winr.0\"\n      ],\n      \"accounts-meteor-developer 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"random@1.0.2\",\n        \"accounts-base@1.1.3\",\n        \"accounts-oauth@1.1.3\",\n        \"meteor-developer@1.1.2\"\n      ],\n      \"accounts-meteor-developer 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"accounts-base@1.1.4-eachin.43\",\n        \"accounts-oauth@1.1.4-eachin.43\",\n        \"meteor-developer@1.1.3-eachin.43\"\n      ],\n      \"accounts-meteor-developer 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"random@1.0.3-githubble.0\",\n        \"accounts-base@1.1.4-githubble.0\",\n        \"accounts-oauth@1.1.4-githubble.0\",\n        \"meteor-developer@1.1.3-githubble.0\"\n      ],\n      \"accounts-meteor-developer 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"accounts-base@1.1.4-githubble.2\",\n        \"accounts-oauth@1.1.4-githubble.2\",\n        \"meteor-developer@1.1.3-githubble.2\"\n      ],\n      \"accounts-meteor-developer 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"accounts-base@1.1.4-githubble.42\",\n        \"accounts-oauth@1.1.4-githubble.42\",\n        \"meteor-developer@1.1.3-githubble.42\"\n      ],\n      \"accounts-meteor-developer 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"accounts-base@1.1.4-githubble.43\",\n        \"accounts-oauth@1.1.4-githubble.43\",\n        \"meteor-developer@1.1.3-githubble.43\"\n      ],\n      \"accounts-meteor-developer 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"accounts-base@1.2.0-rc.0\",\n        \"accounts-oauth@1.1.4-rc.0\",\n        \"meteor-developer@1.1.3-rc.0\"\n      ],\n      \"accounts-meteor-developer 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"accounts-base@1.1.4-winr.0\",\n        \"accounts-oauth@1.1.4-winr.0\",\n        \"meteor-developer@1.1.3-winr.0\"\n      ],\n      \"accounts-meteor-developer 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"accounts-base@1.1.4-winr.1\",\n        \"accounts-oauth@1.1.4-winr.1\",\n        \"meteor-developer@1.1.3-winr.1\"\n      ],\n      \"accounts-meteor-developer 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"accounts-base@1.1.4-winr.2\",\n        \"accounts-oauth@1.1.4-winr.2\",\n        \"meteor-developer@1.1.3-winr.2\"\n      ],\n      \"accounts-meetup 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"accounts-base@10.0.0-glasser.isopacket.0\",\n        \"accounts-oauth@10.0.0-glasser.isopacket.0\",\n        \"meetup@10.0.0-glasser.isopacket.0\"\n      ],\n      \"accounts-meetup 1.0.0\": [\n        \"accounts-base@1.0.0\",\n        \"accounts-oauth@1.0.0\",\n        \"meetup@1.0.1\",\n        \"meteor@1.0.2\"\n      ],\n      \"accounts-meetup 1.0.1--rc0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"meetup\"\n      ],\n      \"accounts-meetup 1.0.1-rc0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"meetup\"\n      ],\n      \"accounts-meetup 1.0.1\": [\n        \"accounts-base@1.1.1\",\n        \"accounts-oauth@1.1.1\",\n        \"meetup@1.1.0\",\n        \"meteor@1.1.1\"\n      ],\n      \"accounts-meetup 1.0.2-pre.0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"meetup\"\n      ],\n      \"accounts-meetup 1.0.2-pre.1\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"meetup\"\n      ],\n      \"accounts-meetup 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"accounts-base@1.1.2-pre.2\",\n        \"accounts-oauth@1.1.2-pre.2\",\n        \"meetup@1.1.1-pre.2\"\n      ],\n      \"accounts-meetup 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"accounts-base@1.1.2-rc.0\",\n        \"accounts-oauth@1.1.2-rc.0\",\n        \"meetup@1.1.1-rc.0\"\n      ],\n      \"accounts-meetup 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"accounts-base@1.1.2-win.0\",\n        \"accounts-oauth@1.1.2-win.0\",\n        \"meetup@1.1.1-win.0\"\n      ],\n      \"accounts-meetup 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"accounts-base@1.1.2\",\n        \"accounts-oauth@1.1.2\",\n        \"meetup@1.1.1\"\n      ],\n      \"accounts-meetup 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"accounts-base@1.1.3-ipc.0\",\n        \"accounts-oauth@1.1.3-ipc.0\",\n        \"meetup@1.1.2-ipc.0\"\n      ],\n      \"accounts-meetup 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"accounts-base@1.1.3-rc.1\",\n        \"accounts-oauth@1.1.3-rc.1\",\n        \"meetup@1.1.2-rc.1\"\n      ],\n      \"accounts-meetup 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"accounts-base@1.1.3-slava.0\",\n        \"accounts-oauth@1.1.3-slava.0\",\n        \"meetup@1.1.2-slava.0\"\n      ],\n      \"accounts-meetup 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"accounts-base@1.1.3-win.0\",\n        \"accounts-oauth@1.1.3-win.0\",\n        \"meetup@1.1.2-win.0\"\n      ],\n      \"accounts-meetup 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"accounts-base@1.1.3-winr.0\",\n        \"accounts-oauth@1.1.3-winr.0\",\n        \"meetup@1.1.2-winr.0\"\n      ],\n      \"accounts-meetup 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"accounts-base@1.1.3\",\n        \"accounts-oauth@1.1.3\",\n        \"meetup@1.1.2\"\n      ],\n      \"accounts-meetup 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"accounts-base@1.1.4-eachin.43\",\n        \"accounts-oauth@1.1.4-eachin.43\",\n        \"meetup@1.1.3-eachin.43\"\n      ],\n      \"accounts-meetup 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"accounts-base@1.1.4-githubble.0\",\n        \"accounts-oauth@1.1.4-githubble.0\",\n        \"meetup@1.1.3-githubble.0\"\n      ],\n      \"accounts-meetup 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"accounts-base@1.1.4-githubble.2\",\n        \"accounts-oauth@1.1.4-githubble.2\",\n        \"meetup@1.1.3-githubble.2\"\n      ],\n      \"accounts-meetup 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"accounts-base@1.1.4-githubble.42\",\n        \"accounts-oauth@1.1.4-githubble.42\",\n        \"meetup@1.1.3-githubble.42\"\n      ],\n      \"accounts-meetup 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"accounts-base@1.1.4-githubble.43\",\n        \"accounts-oauth@1.1.4-githubble.43\",\n        \"meetup@1.1.3-githubble.43\"\n      ],\n      \"accounts-meetup 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"accounts-base@1.2.0-rc.0\",\n        \"accounts-oauth@1.1.4-rc.0\",\n        \"meetup@1.1.3-rc.0\"\n      ],\n      \"accounts-meetup 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"accounts-base@1.1.4-winr.0\",\n        \"accounts-oauth@1.1.4-winr.0\",\n        \"meetup@1.1.3-winr.0\"\n      ],\n      \"accounts-meetup 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"accounts-base@1.1.4-winr.1\",\n        \"accounts-oauth@1.1.4-winr.1\",\n        \"meetup@1.1.3-winr.1\"\n      ],\n      \"accounts-meetup 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"accounts-base@1.1.4-winr.2\",\n        \"accounts-oauth@1.1.4-winr.2\",\n        \"meetup@1.1.3-winr.2\"\n      ],\n      \"accounts-google 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"accounts-base@10.0.0-glasser.isopacket.0\",\n        \"accounts-oauth@10.0.0-glasser.isopacket.0\",\n        \"google@10.0.0-glasser.isopacket.0\"\n      ],\n      \"accounts-google 1.0.0\": [\n        \"accounts-base@1.0.0\",\n        \"accounts-oauth@1.0.0\",\n        \"google@1.0.0\",\n        \"meteor@1.0.2\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-google 1.0.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"google\"\n      ],\n      \"accounts-google 1.0.1\": [\n        \"accounts-base@1.1.1\",\n        \"accounts-oauth@1.1.1\",\n        \"google@1.1.0\",\n        \"meteor@1.1.1\",\n        \"random@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-google 1.0.2-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"google\"\n      ],\n      \"accounts-google 1.0.2-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"random\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"google\"\n      ],\n      \"accounts-google 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"accounts-base@1.1.2-pre.2\",\n        \"accounts-oauth@1.1.2-pre.2\",\n        \"google@1.1.1-pre.2\"\n      ],\n      \"accounts-google 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"accounts-base@1.1.2-rc.0\",\n        \"accounts-oauth@1.1.2-rc.0\",\n        \"google@1.1.1-rc.0\"\n      ],\n      \"accounts-google 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"random@1.0.1-win.0\",\n        \"accounts-base@1.1.2-win.0\",\n        \"accounts-oauth@1.1.2-win.0\",\n        \"google@1.1.2-win.0\"\n      ],\n      \"accounts-google 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"random@1.0.1\",\n        \"accounts-base@1.1.2\",\n        \"accounts-oauth@1.1.2\",\n        \"google@1.1.1\"\n      ],\n      \"accounts-google 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"accounts-base@1.1.3-ipc.0\",\n        \"accounts-oauth@1.1.3-ipc.0\",\n        \"google@1.1.3-ipc.0\"\n      ],\n      \"accounts-google 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"accounts-base@1.1.3-rc.1\",\n        \"accounts-oauth@1.1.3-rc.1\",\n        \"google@1.1.3-rc.1\"\n      ],\n      \"accounts-google 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"accounts-base@1.1.3-slava.0\",\n        \"accounts-oauth@1.1.3-slava.0\",\n        \"google@1.1.3-slava.0\"\n      ],\n      \"accounts-google 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"random@1.0.2-win.0\",\n        \"accounts-base@1.1.3-win.0\",\n        \"accounts-oauth@1.1.3-win.0\",\n        \"google@1.1.3-win.0\"\n      ],\n      \"accounts-google 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"accounts-base@1.1.3-winr.0\",\n        \"accounts-oauth@1.1.3-winr.0\",\n        \"google@1.1.3-winr.0\"\n      ],\n      \"accounts-google 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"random@1.0.2\",\n        \"accounts-base@1.1.3\",\n        \"accounts-oauth@1.1.3\",\n        \"google@1.1.3\"\n      ],\n      \"accounts-google 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"accounts-base@1.1.4-eachin.43\",\n        \"accounts-oauth@1.1.4-eachin.43\",\n        \"google@1.1.4-eachin.43\"\n      ],\n      \"accounts-google 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"random@1.0.3-githubble.0\",\n        \"accounts-base@1.1.4-githubble.0\",\n        \"accounts-oauth@1.1.4-githubble.0\",\n        \"google@1.1.4-githubble.0\"\n      ],\n      \"accounts-google 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"random@1.0.3-githubble.2\",\n        \"accounts-base@1.1.4-githubble.2\",\n        \"accounts-oauth@1.1.4-githubble.2\",\n        \"google@1.1.4-githubble.2\"\n      ],\n      \"accounts-google 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"random@1.0.3-githubble.42\",\n        \"accounts-base@1.1.4-githubble.42\",\n        \"accounts-oauth@1.1.4-githubble.42\",\n        \"google@1.1.4-githubble.42\"\n      ],\n      \"accounts-google 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"accounts-base@1.1.4-githubble.43\",\n        \"accounts-oauth@1.1.4-githubble.43\",\n        \"google@1.1.4-githubble.43\"\n      ],\n      \"accounts-google 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"accounts-base@1.2.0-rc.0\",\n        \"accounts-oauth@1.1.4-rc.0\",\n        \"google@1.1.5-rc.0\"\n      ],\n      \"accounts-google 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"accounts-base@1.1.4-winr.0\",\n        \"accounts-oauth@1.1.4-winr.0\",\n        \"google@1.1.4-winr.0\"\n      ],\n      \"accounts-google 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"accounts-base@1.1.4-winr.1\",\n        \"accounts-oauth@1.1.4-winr.1\",\n        \"google@1.1.4-winr.1\"\n      ],\n      \"accounts-google 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"accounts-base@1.1.4-winr.2\",\n        \"accounts-oauth@1.1.4-winr.2\",\n        \"google@1.1.4-winr.4\"\n      ],\n      \"accounts-github 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"accounts-base@10.0.0-glasser.isopacket.0\",\n        \"accounts-oauth@10.0.0-glasser.isopacket.0\",\n        \"github@10.0.0-glasser.isopacket.0\"\n      ],\n      \"accounts-github 1.0.0\": [\n        \"accounts-base@1.0.0\",\n        \"accounts-oauth@1.0.0\",\n        \"github@1.0.0\",\n        \"meteor@1.0.2\"\n      ],\n      \"accounts-github 1.0.1-rc0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"github\"\n      ],\n      \"accounts-github 1.0.1\": [\n        \"accounts-base@1.1.1\",\n        \"accounts-oauth@1.1.1\",\n        \"github@1.1.0\",\n        \"meteor@1.1.1\"\n      ],\n      \"accounts-github 1.0.2-pre.0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"github\"\n      ],\n      \"accounts-github 1.0.2-pre.1\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"github\"\n      ],\n      \"accounts-github 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"accounts-base@1.1.2-pre.2\",\n        \"accounts-oauth@1.1.2-pre.2\",\n        \"github@1.1.1-pre.2\"\n      ],\n      \"accounts-github 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"accounts-base@1.1.2-rc.0\",\n        \"accounts-oauth@1.1.2-rc.0\",\n        \"github@1.1.1-rc.0\"\n      ],\n      \"accounts-github 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"accounts-base@1.1.2-win.0\",\n        \"accounts-oauth@1.1.2-win.0\",\n        \"github@1.1.1-win.0\"\n      ],\n      \"accounts-github 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"accounts-base@1.1.2\",\n        \"accounts-oauth@1.1.2\",\n        \"github@1.1.1\"\n      ],\n      \"accounts-github 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"accounts-base@1.1.3-ipc.0\",\n        \"accounts-oauth@1.1.3-ipc.0\",\n        \"github@1.1.2-ipc.0\"\n      ],\n      \"accounts-github 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"accounts-base@1.1.3-rc.1\",\n        \"accounts-oauth@1.1.3-rc.1\",\n        \"github@1.1.2-rc.1\"\n      ],\n      \"accounts-github 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"accounts-base@1.1.3-slava.0\",\n        \"accounts-oauth@1.1.3-slava.0\",\n        \"github@1.1.2-slava.0\"\n      ],\n      \"accounts-github 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"accounts-base@1.1.3-win.0\",\n        \"accounts-oauth@1.1.3-win.0\",\n        \"github@1.1.2-win.0\"\n      ],\n      \"accounts-github 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"accounts-base@1.1.3-winr.0\",\n        \"accounts-oauth@1.1.3-winr.0\",\n        \"github@1.1.2-winr.0\"\n      ],\n      \"accounts-github 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"accounts-base@1.1.3\",\n        \"accounts-oauth@1.1.3\",\n        \"github@1.1.2\"\n      ],\n      \"accounts-github 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"accounts-base@1.1.4-eachin.43\",\n        \"accounts-oauth@1.1.4-eachin.43\",\n        \"github@1.1.3-eachin.43\"\n      ],\n      \"accounts-github 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"accounts-base@1.1.4-githubble.0\",\n        \"accounts-oauth@1.1.4-githubble.0\",\n        \"github@1.1.3-githubble.0\"\n      ],\n      \"accounts-github 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"accounts-base@1.1.4-githubble.2\",\n        \"accounts-oauth@1.1.4-githubble.2\",\n        \"github@1.1.3-githubble.2\"\n      ],\n      \"accounts-github 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"accounts-base@1.1.4-githubble.42\",\n        \"accounts-oauth@1.1.4-githubble.42\",\n        \"github@1.1.3-githubble.42\"\n      ],\n      \"accounts-github 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"accounts-base@1.1.4-githubble.43\",\n        \"accounts-oauth@1.1.4-githubble.43\",\n        \"github@1.1.3-githubble.43\"\n      ],\n      \"accounts-github 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"accounts-base@1.2.0-rc.0\",\n        \"accounts-oauth@1.1.4-rc.0\",\n        \"github@1.1.3-rc.0\"\n      ],\n      \"accounts-github 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"accounts-base@1.1.4-winr.0\",\n        \"accounts-oauth@1.1.4-winr.0\",\n        \"github@1.1.3-winr.0\"\n      ],\n      \"accounts-github 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"accounts-base@1.1.4-winr.1\",\n        \"accounts-oauth@1.1.4-winr.1\",\n        \"github@1.1.3-winr.1\"\n      ],\n      \"accounts-github 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"accounts-base@1.1.4-winr.2\",\n        \"accounts-oauth@1.1.4-winr.2\",\n        \"github@1.1.3-winr.2\"\n      ],\n      \"accounts-facebook 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"accounts-base@10.0.0-glasser.isopacket.0\",\n        \"accounts-oauth@10.0.0-glasser.isopacket.0\",\n        \"facebook@10.0.0-glasser.isopacket.0\"\n      ],\n      \"accounts-facebook 1.0.0\": [\n        \"accounts-base@1.0.0\",\n        \"accounts-oauth@1.0.0\",\n        \"facebook@1.0.0\",\n        \"meteor@1.0.2\"\n      ],\n      \"accounts-facebook 1.0.1-rc0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"facebook\"\n      ],\n      \"accounts-facebook 1.0.1\": [\n        \"accounts-base@1.1.1\",\n        \"accounts-oauth@1.1.1\",\n        \"facebook@1.1.0\",\n        \"meteor@1.1.1\"\n      ],\n      \"accounts-facebook 1.0.2-pre.0\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"facebook\"\n      ],\n      \"accounts-facebook 1.0.2-pre.1\": [\n        \"meteor\",\n        \"accounts-base\",\n        \"accounts-oauth\",\n        \"facebook\"\n      ],\n      \"accounts-facebook 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"accounts-base@1.1.2-pre.2\",\n        \"accounts-oauth@1.1.2-pre.2\",\n        \"facebook@1.1.1-pre.2\"\n      ],\n      \"accounts-facebook 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"accounts-base@1.1.2-rc.0\",\n        \"accounts-oauth@1.1.2-rc.0\",\n        \"facebook@1.1.1-rc.0\"\n      ],\n      \"accounts-facebook 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"accounts-base@1.1.2-win.0\",\n        \"accounts-oauth@1.1.2-win.0\",\n        \"facebook@1.1.2-win.0\"\n      ],\n      \"accounts-facebook 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"accounts-base@1.1.2\",\n        \"accounts-oauth@1.1.2\",\n        \"facebook@1.1.1\"\n      ],\n      \"accounts-facebook 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"accounts-base@1.1.3-ipc.0\",\n        \"accounts-oauth@1.1.3-ipc.0\",\n        \"facebook@1.1.3-ipc.0\"\n      ],\n      \"accounts-facebook 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"accounts-base@1.1.3-rc.1\",\n        \"accounts-oauth@1.1.3-rc.1\",\n        \"facebook@1.1.3-rc.1\"\n      ],\n      \"accounts-facebook 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"accounts-base@1.1.3-slava.0\",\n        \"accounts-oauth@1.1.3-slava.0\",\n        \"facebook@1.1.3-slava.0\"\n      ],\n      \"accounts-facebook 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"accounts-base@1.1.3-win.0\",\n        \"accounts-oauth@1.1.3-win.0\",\n        \"facebook@1.1.3-win.0\"\n      ],\n      \"accounts-facebook 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"accounts-base@1.1.3-winr.0\",\n        \"accounts-oauth@1.1.3-winr.0\",\n        \"facebook@1.1.3-winr.0\"\n      ],\n      \"accounts-facebook 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"accounts-base@1.1.3\",\n        \"accounts-oauth@1.1.3\",\n        \"facebook@1.1.3\"\n      ],\n      \"accounts-facebook 1.0.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"accounts-base@1.1.4-eachin.43\",\n        \"accounts-oauth@1.1.4-eachin.43\",\n        \"facebook@1.1.4-eachin.43\"\n      ],\n      \"accounts-facebook 1.0.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"accounts-base@1.1.4-githubble.0\",\n        \"accounts-oauth@1.1.4-githubble.0\",\n        \"facebook@1.1.4-githubble.0\"\n      ],\n      \"accounts-facebook 1.0.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"accounts-base@1.1.4-githubble.2\",\n        \"accounts-oauth@1.1.4-githubble.2\",\n        \"facebook@1.1.4-githubble.2\"\n      ],\n      \"accounts-facebook 1.0.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"accounts-base@1.1.4-githubble.42\",\n        \"accounts-oauth@1.1.4-githubble.42\",\n        \"facebook@1.1.4-githubble.42\"\n      ],\n      \"accounts-facebook 1.0.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"accounts-base@1.1.4-githubble.43\",\n        \"accounts-oauth@1.1.4-githubble.43\",\n        \"facebook@1.1.4-githubble.43\"\n      ],\n      \"accounts-facebook 1.0.4-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"accounts-base@1.2.0-rc.0\",\n        \"accounts-oauth@1.1.4-rc.0\",\n        \"facebook@1.1.4-rc.0\"\n      ],\n      \"accounts-facebook 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"accounts-base@1.1.4-winr.0\",\n        \"accounts-oauth@1.1.4-winr.0\",\n        \"facebook@1.1.4-winr.0\"\n      ],\n      \"accounts-facebook 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"accounts-base@1.1.4-winr.1\",\n        \"accounts-oauth@1.1.4-winr.1\",\n        \"facebook@1.1.4-winr.1\"\n      ],\n      \"accounts-facebook 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"accounts-base@1.1.4-winr.2\",\n        \"accounts-oauth@1.1.4-winr.2\",\n        \"facebook@1.1.4-winr.2\"\n      ],\n      \"accounts-base 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"check@10.0.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\",\n        \"callback-hook@10.0.0-glasser.isopacket.0\",\n        \"service-configuration@10.0.0-glasser.isopacket.0\",\n        \"ddp@10.0.0-glasser.isopacket.0\",\n        \"mongo@10.0.0-glasser.isopacket.0\",\n        \"?autopublish@10.0.0-glasser.isopacket.0\",\n        \"?oauth-encryption@10.0.0-glasser.isopacket.0\",\n        \"localstorage@10.0.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\",\n        \"?blaze@10.0.0-glasser.isopacket.0\"\n      ],\n      \"accounts-base 1.0.0\": [\n        \"?autopublish@1.0.0\",\n        \"callback-hook@1.0.0\",\n        \"check@1.0.0\",\n        \"deps@1.0.1\",\n        \"ejson@1.0.0\",\n        \"livedata@1.0.7\",\n        \"localstorage@1.0.0\",\n        \"meteor@1.0.2\",\n        \"mongo-livedata@1.0.3\",\n        \"?oauth-encryption@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.0\",\n        \"?ui@1.0.0\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-base 1.0.1-glasser1\": [\n        \"meteor\",\n        \"underscore\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"callback-hook\",\n        \"service-configuration\",\n        \"ddp\",\n        \"mongo\",\n        \"?autopublish\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"tracker\",\n        \"?blaze\"\n      ],\n      \"accounts-base 1.0.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"callback-hook\",\n        \"service-configuration\",\n        \"livedata\",\n        \"mongo-livedata\",\n        \"?autopublish\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"tracker\",\n        \"?blaze\"\n      ],\n      \"accounts-base 1.0.1-rc1\": [\n        \"meteor\",\n        \"underscore\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"callback-hook\",\n        \"service-configuration\",\n        \"ddp\",\n        \"mongo\",\n        \"?autopublish\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"tracker\",\n        \"?blaze\"\n      ],\n      \"accounts-base 1.0.1\": [\n        \"?autopublish@1.0.0\",\n        \"?blaze@2.0.0\",\n        \"callback-hook@1.0.0\",\n        \"check@1.0.0\",\n        \"ddp@1.0.8\",\n        \"ejson@1.0.1\",\n        \"localstorage@1.0.0\",\n        \"meteor@1.0.3\",\n        \"mongo@1.0.4\",\n        \"?oauth-encryption@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-base 1.0.2-ekate\": [\n        \"meteor\",\n        \"underscore\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"callback-hook\",\n        \"service-configuration\",\n        \"ddp\",\n        \"mongo\",\n        \"?autopublish\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"tracker\",\n        \"?blaze\"\n      ],\n      \"accounts-base 1.1.0-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"callback-hook\",\n        \"service-configuration\",\n        \"ddp\",\n        \"mongo\",\n        \"?autopublish\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"tracker\",\n        \"?blaze\"\n      ],\n      \"accounts-base 1.1.0\": [\n        \"?autopublish@1.0.0\",\n        \"?blaze@2.0.0\",\n        \"callback-hook@1.0.0\",\n        \"check@1.0.0\",\n        \"ddp@1.0.8\",\n        \"ejson@1.0.2\",\n        \"localstorage@1.0.0\",\n        \"meteor@1.1.0\",\n        \"mongo@1.0.5\",\n        \"?oauth-encryption@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-base 1.1.1-rc0\": [\n        \"meteor\",\n        \"underscore\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"callback-hook\",\n        \"service-configuration\",\n        \"ddp\",\n        \"mongo\",\n        \"?autopublish\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"tracker\",\n        \"?blaze\"\n      ],\n      \"accounts-base 1.1.1\": [\n        \"?autopublish@1.0.0\",\n        \"?blaze@2.0.1\",\n        \"callback-hook@1.0.0\",\n        \"check@1.0.1\",\n        \"ddp@1.0.9\",\n        \"ejson@1.0.3\",\n        \"localstorage@1.0.0\",\n        \"meteor@1.1.1\",\n        \"mongo@1.0.6\",\n        \"?oauth-encryption@1.0.0\",\n        \"random@1.0.0\",\n        \"service-configuration@1.0.1\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"accounts-base 1.1.2-ekate.2\": [\n        \"meteor@1.1.2-ekate.1\",\n        \"underscore@1.0.1-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"callback-hook@1.0.1-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"ddp@1.0.10-rc.1\",\n        \"mongo@1.0.7-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"?oauth-encryption@1.0.1-rc.0\",\n        \"localstorage@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"?blaze@2.0.2-rc.0\"\n      ],\n      \"accounts-base 1.1.2-ekate.4\": [\n        \"meteor@1.1.2-ekate.1\",\n        \"underscore@1.0.1-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"callback-hook@1.0.1-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"ddp@1.0.10-rc.1\",\n        \"mongo@1.0.7-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"?oauth-encryption@1.0.1-rc.0\",\n        \"localstorage@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"?blaze@2.0.2-rc.0\"\n      ],\n      \"accounts-base 1.1.2-ekate.5\": [\n        \"meteor@1.1.2-ekate.1\",\n        \"underscore@1.0.1-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"callback-hook@1.0.1-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"ddp@1.0.10-rc.1\",\n        \"mongo@1.0.7-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"?oauth-encryption@1.0.1-rc.0\",\n        \"localstorage@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"?blaze@2.0.2-rc.0\"\n      ],\n      \"accounts-base 1.1.2-nim.0\": [\n        \"meteor@1.1.2-nim.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"callback-hook@1.0.1-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"ddp@1.0.10-nim.0\",\n        \"mongo@1.0.7-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"?oauth-encryption@1.0.1-rc.0\",\n        \"localstorage@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"?blaze@2.0.2-rc.0\"\n      ],\n      \"accounts-base 1.1.2-pre.0\": [\n        \"meteor\",\n        \"underscore\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"callback-hook\",\n        \"service-configuration\",\n        \"ddp\",\n        \"mongo\",\n        \"?autopublish\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"tracker\",\n        \"?blaze\"\n      ],\n      \"accounts-base 1.1.2-pre.1\": [\n        \"meteor\",\n        \"underscore\",\n        \"check\",\n        \"random\",\n        \"ejson\",\n        \"callback-hook\",\n        \"service-configuration\",\n        \"ddp\",\n        \"mongo\",\n        \"?autopublish\",\n        \"?oauth-encryption\",\n        \"localstorage\",\n        \"tracker\",\n        \"?blaze\"\n      ],\n      \"accounts-base 1.1.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"check@1.0.2-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"ejson@1.0.4-pre.2\",\n        \"callback-hook@1.0.1-pre.2\",\n        \"service-configuration@1.0.2-pre.2\",\n        \"ddp@1.0.10-pre.2\",\n        \"mongo@1.0.7-pre.2\",\n        \"?autopublish@1.0.1-pre.2\",\n        \"?oauth-encryption@1.0.1-pre.2\",\n        \"localstorage@1.0.1-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"?blaze@2.0.2-pre.2\"\n      ],\n      \"accounts-base 1.1.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"callback-hook@1.0.1-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"ddp@1.0.10-rc.0\",\n        \"mongo@1.0.7-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"?oauth-encryption@1.0.1-rc.0\",\n        \"localstorage@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"?blaze@2.0.2-rc.0\"\n      ],\n      \"accounts-base 1.1.2-rc.1\": [\n        \"meteor@1.1.2-ekate.1\",\n        \"underscore@1.0.1-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"callback-hook@1.0.1-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"ddp@1.0.10-rc.1\",\n        \"mongo@1.0.7-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"?oauth-encryption@1.0.1-rc.0\",\n        \"localstorage@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"?blaze@2.0.2-rc.0\"\n      ],\n      \"accounts-base 1.1.2-rc.2\": [\n        \"meteor@1.1.2-rc.2\",\n        \"underscore@1.0.1-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"callback-hook@1.0.1-rc.0\",\n        \"service-configuration@1.0.2-rc.0\",\n        \"ddp@1.0.10-rc.2\",\n        \"mongo@1.0.7-rc.0\",\n        \"?autopublish@1.0.1-rc.0\",\n        \"?oauth-encryption@1.0.1-rc.0\",\n        \"localstorage@1.0.1-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"?blaze@2.0.2-rc.0\"\n      ],\n      \"accounts-base 1.1.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"check@1.0.2-win.0\",\n        \"random@1.0.1-win.0\",\n        \"ejson@1.0.4-win.0\",\n        \"callback-hook@1.0.1-win.0\",\n        \"service-configuration@1.0.2-win.0\",\n        \"ddp@1.0.11-win.0\",\n        \"mongo@1.0.8-win.0\",\n        \"?autopublish@1.0.1-win.0\",\n        \"?oauth-encryption@1.0.1-win.0\",\n        \"localstorage@1.0.1-win.0\",\n        \"tracker@1.0.3-win.0\",\n        \"?blaze@2.0.3-win.0\"\n      ],\n      \"accounts-base 1.1.2\": [\n        \"meteor@1.1.2\",\n        \"underscore@1.0.1\",\n        \"check@1.0.2\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"callback-hook@1.0.1\",\n        \"service-configuration@1.0.2\",\n        \"ddp@1.0.10\",\n        \"mongo@1.0.7\",\n        \"?autopublish@1.0.1\",\n        \"?oauth-encryption@1.0.1\",\n        \"localstorage@1.0.1\",\n        \"tracker@1.0.3\",\n        \"?blaze@2.0.2\"\n      ],\n      \"accounts-base 1.1.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"check@1.0.3-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"callback-hook@1.0.2-ipc.0\",\n        \"service-configuration@1.0.3-ipc.0\",\n        \"ddp@1.0.12-ipc.0\",\n        \"mongo@1.0.9-ipc.0\",\n        \"?autopublish@1.0.2-ipc.0\",\n        \"?oauth-encryption@1.0.2-ipc.0\",\n        \"localstorage@1.0.2-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"?blaze@2.0.4-ipc.0\"\n      ],\n      \"accounts-base 1.1.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"check@1.0.3-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"ejson@1.0.5-rc.1\",\n        \"callback-hook@1.0.2-rc.1\",\n        \"service-configuration@1.0.3-rc.1\",\n        \"ddp@1.0.13-rc.1\",\n        \"mongo@1.0.10-rc.1\",\n        \"?autopublish@1.0.2-rc.1\",\n        \"?oauth-encryption@1.0.2-rc.1\",\n        \"localstorage@1.0.2-rc.1\",\n        \"tracker@1.0.4-rc.1\",\n        \"?blaze@2.0.4-rc.1\"\n      ],\n      \"accounts-base 1.1.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"check@1.0.3-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"ejson@1.0.5-slava.0\",\n        \"callback-hook@1.0.2-slava.0\",\n        \"service-configuration@1.0.3-slava.0\",\n        \"ddp@1.0.13-slava.0\",\n        \"mongo@1.0.10-slava.0\",\n        \"?autopublish@1.0.2-slava.0\",\n        \"?oauth-encryption@1.0.2-slava.0\",\n        \"localstorage@1.0.2-slava.0\",\n        \"tracker@1.0.4-slava.0\",\n        \"?blaze@2.0.4-slava.0\"\n      ],\n      \"accounts-base 1.1.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"check@1.0.3-win.0\",\n        \"random@1.0.2-win.0\",\n        \"ejson@1.0.5-win.0\",\n        \"callback-hook@1.0.2-win.0\",\n        \"service-configuration@1.0.3-win.0\",\n        \"ddp@1.0.12-win.0\",\n        \"mongo@1.0.9-win.0\",\n        \"?autopublish@1.0.2-win.0\",\n        \"?oauth-encryption@1.0.1-win.1\",\n        \"localstorage@1.0.2-win.0\",\n        \"tracker@1.0.4-win.0\",\n        \"?blaze@2.0.4-win.0\"\n      ],\n      \"accounts-base 1.1.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"check@1.0.3-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"ejson@1.0.5-winr.0\",\n        \"callback-hook@1.0.2-winr.0\",\n        \"service-configuration@1.0.3-winr.0\",\n        \"ddp@1.0.13-winr.0\",\n        \"mongo@1.0.10-winr.0\",\n        \"?autopublish@1.0.2-winr.0\",\n        \"?oauth-encryption@1.0.2-winr.0\",\n        \"localstorage@1.0.2-winr.0\",\n        \"tracker@1.0.4-winr.0\",\n        \"?blaze@2.0.4-winr.0\"\n      ],\n      \"accounts-base 1.1.3\": [\n        \"meteor@1.1.4\",\n        \"underscore@1.0.2\",\n        \"check@1.0.3\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"callback-hook@1.0.2\",\n        \"service-configuration@1.0.3\",\n        \"ddp@1.0.13\",\n        \"mongo@1.0.10\",\n        \"?autopublish@1.0.2\",\n        \"?oauth-encryption@1.0.2\",\n        \"localstorage@1.0.2\",\n        \"tracker@1.0.4\",\n        \"?blaze@2.0.4\"\n      ],\n      \"accounts-base 1.1.4-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"check@1.0.4-eachin.43\",\n        \"random@1.0.3-eachin.43\",\n        \"ejson@1.0.6-eachin.43\",\n        \"callback-hook@1.0.3-eachin.43\",\n        \"service-configuration@1.0.4-eachin.43\",\n        \"ddp@1.0.15-eachin.43\",\n        \"mongo@1.0.12-eachin.45\",\n        \"?autopublish@1.0.3-eachin.43\",\n        \"?oauth-encryption@1.0.3-eachin.43\",\n        \"localstorage@1.0.3-eachin.43\",\n        \"tracker@1.0.5-eachin.43\",\n        \"?blaze@2.0.5-eachin.43\"\n      ],\n      \"accounts-base 1.1.4-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.3-githubble.0\",\n        \"ejson@1.0.6-githubble.0\",\n        \"callback-hook@1.0.3-githubble.0\",\n        \"service-configuration@1.0.4-githubble.0\",\n        \"ddp@1.0.15-githubble.0\",\n        \"mongo@1.0.12-githubble.0\",\n        \"?autopublish@1.0.3-githubble.0\",\n        \"?oauth-encryption@1.0.3-githubble.0\",\n        \"localstorage@1.0.3-githubble.0\",\n        \"tracker@1.0.5-githubble.0\",\n        \"?blaze@2.0.5-githubble.0\"\n      ],\n      \"accounts-base 1.1.4-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\",\n        \"underscore@1.0.3-githubble.2\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.3-githubble.2\",\n        \"ejson@1.0.6-githubble.2\",\n        \"callback-hook@1.0.3-githubble.2\",\n        \"service-configuration@1.0.4-githubble.2\",\n        \"ddp@1.0.15-githubble.2\",\n        \"mongo@1.0.12-githubble.2\",\n        \"?autopublish@1.0.3-githubble.2\",\n        \"?oauth-encryption@1.0.3-githubble.2\",\n        \"localstorage@1.0.3-githubble.2\",\n        \"tracker@1.0.5-githubble.2\",\n        \"?blaze@2.0.5-githubble.2\"\n      ],\n      \"accounts-base 1.1.4-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"underscore@1.0.3-githubble.42\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.3-githubble.42\",\n        \"ejson@1.0.6-githubble.42\",\n        \"callback-hook@1.0.3-githubble.42\",\n        \"service-configuration@1.0.4-githubble.42\",\n        \"ddp@1.0.15-githubble.42\",\n        \"mongo@1.0.12-githubble.42\",\n        \"?autopublish@1.0.3-githubble.42\",\n        \"?oauth-encryption@1.0.3-githubble.42\",\n        \"localstorage@1.0.3-githubble.42\",\n        \"tracker@1.0.5-githubble.42\",\n        \"?blaze@2.0.5-githubble.42\"\n      ],\n      \"accounts-base 1.1.4-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"check@1.0.4-githubble.43\",\n        \"random@1.0.3-githubble.43\",\n        \"ejson@1.0.6-githubble.43\",\n        \"callback-hook@1.0.3-githubble.43\",\n        \"service-configuration@1.0.4-githubble.43\",\n        \"ddp@1.0.15-githubble.43\",\n        \"mongo@1.0.12-githubble.43\",\n        \"?autopublish@1.0.3-githubble.43\",\n        \"?oauth-encryption@1.0.3-githubble.43\",\n        \"localstorage@1.0.3-githubble.43\",\n        \"tracker@1.0.5-githubble.43\",\n        \"?blaze@2.0.5-githubble.43\"\n      ],\n      \"accounts-base 1.1.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"check@1.0.4-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"ejson@1.0.6-winr.0\",\n        \"callback-hook@1.0.3-winr.0\",\n        \"service-configuration@1.0.4-winr.0\",\n        \"ddp@1.0.14-winr.0\",\n        \"mongo@1.0.11-winr.0\",\n        \"?autopublish@1.0.3-winr.0\",\n        \"?oauth-encryption@1.0.3-winr.0\",\n        \"localstorage@1.0.3-winr.0\",\n        \"tracker@1.0.5-winr.0\",\n        \"?blaze@2.0.5-winr.0\"\n      ],\n      \"accounts-base 1.1.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"check@1.0.4-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\",\n        \"callback-hook@1.0.3-winr.1\",\n        \"service-configuration@1.0.4-winr.1\",\n        \"ddp@1.0.14-winr.1\",\n        \"mongo@1.0.11-winr.1\",\n        \"?autopublish@1.0.3-winr.1\",\n        \"?oauth-encryption@1.0.3-winr.1\",\n        \"localstorage@1.0.3-winr.1\",\n        \"tracker@1.0.5-winr.1\",\n        \"?blaze@2.0.5-winr.1\"\n      ],\n      \"accounts-base 1.1.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"underscore@1.0.3-winr.2\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"callback-hook@1.0.3-winr.2\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"ddp@1.0.14-winr.4\",\n        \"mongo@1.0.12-winr.2\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?oauth-encryption@1.0.3-winr.4\",\n        \"localstorage@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"?blaze@2.0.5-winr.2\"\n      ],\n      \"accounts-base 1.1.4-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"underscore@1.0.3-winr.2\",\n        \"check@1.0.4-win.0\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"callback-hook@1.0.3-winr.2\",\n        \"service-configuration@1.0.4-winr.2\",\n        \"ddp@1.0.15-winr.5\",\n        \"mongo@1.0.12-winr.5\",\n        \"?autopublish@1.0.3-winr.2\",\n        \"?oauth-encryption@1.0.3-winr.4\",\n        \"localstorage@1.0.3-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"?blaze@2.0.5-winr.4\"\n      ],\n      \"accounts-base 1.2.0-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"check@1.0.5-rc.0\",\n        \"random@1.0.3-rc.0\",\n        \"ejson@1.0.6-rc.0\",\n        \"callback-hook@1.0.3-rc.0\",\n        \"service-configuration@1.0.4-rc.0\",\n        \"ddp@1.1.0-rc.0\",\n        \"mongo@1.1.0-rc.0\",\n        \"?autopublish@1.0.3-rc.0\",\n        \"?oauth-encryption@1.0.3-rc.0\",\n        \"localstorage@1.0.3-rc.0\",\n        \"tracker@1.0.6-rc.0\",\n        \"?blaze@2.1.0-rc.0\"\n      ],\n      \"follower-livedata 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"logging@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"ddp@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\"\n      ],\n      \"follower-livedata 1.0.0\": [\n        \"ejson@1.0.0\",\n        \"livedata@1.0.7\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.2\",\n        \"underscore@1.0.0\"\n      ],\n      \"follower-livedata 1.0.1-rc0\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"ddp\",\n        \"ejson\"\n      ],\n      \"follower-livedata 1.0.1\": [\n        \"ddp@1.0.8\",\n        \"ejson@1.0.1\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.3\",\n        \"underscore@1.0.0\"\n      ],\n      \"follower-livedata 1.0.2-pre.0\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"ddp\",\n        \"ejson\"\n      ],\n      \"follower-livedata 1.0.2-pre.1\": [\n        \"meteor\",\n        \"logging\",\n        \"underscore\",\n        \"ddp\",\n        \"ejson\"\n      ],\n      \"follower-livedata 1.0.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"logging@1.0.4-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"ddp@1.0.10-pre.2\",\n        \"ejson@1.0.4-pre.2\"\n      ],\n      \"follower-livedata 1.0.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"logging@1.0.4-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"ddp@1.0.10-rc.0\",\n        \"ejson@1.0.4-rc.0\"\n      ],\n      \"follower-livedata 1.0.2-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"logging@1.0.5-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"ddp@1.0.11-win.0\",\n        \"ejson@1.0.4-win.0\"\n      ],\n      \"follower-livedata 1.0.2\": [\n        \"meteor@1.1.2\",\n        \"logging@1.0.4\",\n        \"underscore@1.0.1\",\n        \"ddp@1.0.10\",\n        \"ejson@1.0.4\"\n      ],\n      \"follower-livedata 1.0.3-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"logging@1.0.6-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"ddp@1.0.12-ipc.0\",\n        \"ejson@1.0.5-ipc.0\"\n      ],\n      \"follower-livedata 1.0.3-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"logging@1.0.6-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"ddp@1.0.13-rc.1\",\n        \"ejson@1.0.5-rc.1\"\n      ],\n      \"follower-livedata 1.0.3-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"logging@1.0.6-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"ddp@1.0.13-slava.0\",\n        \"ejson@1.0.5-slava.0\"\n      ],\n      \"follower-livedata 1.0.3-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"logging@1.0.6-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"ddp@1.0.12-win.0\",\n        \"ejson@1.0.5-win.0\"\n      ],\n      \"follower-livedata 1.0.3-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"logging@1.0.6-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"ddp@1.0.13-winr.0\",\n        \"ejson@1.0.5-winr.0\"\n      ],\n      \"follower-livedata 1.0.3\": [\n        \"meteor@1.1.4\",\n        \"logging@1.0.6\",\n        \"underscore@1.0.2\",\n        \"ddp@1.0.13\",\n        \"ejson@1.0.5\"\n      ],\n      \"follower-livedata 1.0.4-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"logging@1.0.7-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"ddp@1.0.14-winr.0\",\n        \"ejson@1.0.6-winr.0\"\n      ],\n      \"follower-livedata 1.0.4-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"logging@1.0.7-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"ddp@1.0.14-winr.1\",\n        \"ejson@1.0.6-winr.1\"\n      ],\n      \"follower-livedata 1.0.4-winr.2\": [\n        \"meteor@1.1.5-winr.4\",\n        \"logging@1.0.6-winr.2\",\n        \"underscore@1.0.3-winr.2\",\n        \"ddp@1.0.14-winr.4\",\n        \"ejson@1.0.6-winr.2\"\n      ],\n      \"less 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"less 1.0.0\": [\n        \"meteor\"\n      ],\n      \"less 1.0.1\": [\n        \"meteor\"\n      ],\n      \"less 1.0.2\": [\n        \"meteor\"\n      ],\n      \"less 1.0.3\": [\n        \"meteor\"\n      ],\n      \"less 1.0.4\": [\n        \"meteor\"\n      ],\n      \"less 1.0.5-cordova4\": [\n        \"meteor\"\n      ],\n      \"less 1.0.5\": [\n        \"meteor@1.0.2\"\n      ],\n      \"less 1.0.6-rc1\": [\n        \"meteor\"\n      ],\n      \"less 1.0.6\": [\n        \"meteor@1.0.2\"\n      ],\n      \"less 1.0.7-rc0\": [\n        \"meteor\"\n      ],\n      \"less 1.0.7-rc1\": [\n        \"meteor\"\n      ],\n      \"less 1.0.7\": [\n        \"meteor@1.0.3\"\n      ],\n      \"less 1.0.8-cordova6\": [\n        \"meteor\"\n      ],\n      \"less 1.0.8-ekate\": [\n        \"meteor\"\n      ],\n      \"less 1.0.8-glasser1\": [\n        \"meteor\"\n      ],\n      \"less 1.0.8-rc1\": [\n        \"meteor\"\n      ],\n      \"less 1.0.8-rc2\": [\n        \"meteor\"\n      ],\n      \"less 1.0.8-rc3\": [\n        \"meteor\"\n      ],\n      \"less 1.0.8-rc4\": [\n        \"meteor\"\n      ],\n      \"less 1.0.8-rc5\": [\n        \"meteor\"\n      ],\n      \"less 1.0.8\": [\n        \"meteor@1.1.0\"\n      ],\n      \"less 1.0.9-rc0\": [\n        \"meteor\"\n      ],\n      \"less 1.0.9\": [\n        \"meteor@1.1.1\"\n      ],\n      \"less 1.0.10-nim.0\": [\n        \"meteor@1.1.2-nim.0\"\n      ],\n      \"less 1.0.10-pre.0\": [\n        \"meteor\"\n      ],\n      \"less 1.0.10-pre.1\": [\n        \"meteor\"\n      ],\n      \"less 1.0.10-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"less 1.0.10-pre.3\": [\n        \"meteor@1.1.2-pre.3\"\n      ],\n      \"less 1.0.10-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"less 1.0.10-rc.1\": [\n        \"meteor@1.1.2-ekate.1\"\n      ],\n      \"less 1.0.10-rc.2\": [\n        \"meteor@1.1.2-rc.2\"\n      ],\n      \"less 1.0.10-rc.3\": [\n        \"meteor@1.1.2-rc.3\"\n      ],\n      \"less 1.0.10-rc.4\": [\n        \"meteor@1.1.2-rc.3\"\n      ],\n      \"less 1.0.10-rc.5\": [\n        \"meteor@1.1.2-rc.3\"\n      ],\n      \"less 1.0.10-refreshpolicy.1\": [\n        \"meteor@1.1.2-refreshpolicy.1\"\n      ],\n      \"less 1.0.10\": [\n        \"meteor@1.1.2\"\n      ],\n      \"less 1.0.10_1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"less 1.0.10_2\": [\n        \"meteor@1.1.2\"\n      ],\n      \"less 1.0.11-rc.0\": [\n        \"meteor@1.1.2\"\n      ],\n      \"less 1.0.11-rc.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"less 1.0.11-rc.2\": [\n        \"meteor@1.1.3-rc.0\"\n      ],\n      \"less 1.0.11-rc.3\": [\n        \"meteor@1.1.3-rc.0\"\n      ],\n      \"less 1.0.11-rc.4\": [\n        \"meteor@1.1.3-rc.0\"\n      ],\n      \"less 1.0.11-rc.5\": [\n        \"meteor@1.1.3-rc.0\"\n      ],\n      \"less 1.0.11-rc.6\": [\n        \"meteor@1.1.3-rc.0\"\n      ],\n      \"less 1.0.11-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"less 1.0.11\": [\n        \"meteor@1.1.3\"\n      ],\n      \"less 1.0.12-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"less 1.0.12-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"less 1.0.12-rc.2\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"less 1.0.12-rc.3\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"less 1.0.12-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"less 1.0.12-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"less 1.0.12-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"less 1.0.12\": [\n        \"meteor@1.1.4\"\n      ],\n      \"less 1.0.13-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"less 1.0.13-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"less 1.0.13-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"less 1.0.13-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"less 1.0.13-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"less 1.0.13-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"less 1.0.13-vs.1\": [\n        \"meteor@1.1.5-vs.1\"\n      ],\n      \"less 1.0.13-vs.2\": [\n        \"meteor@1.1.5-vs.2\"\n      ],\n      \"less 1.0.13-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"less 1.0.13-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"less 1.0.13-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"less 1.0.13-winr.3\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"less 1.0.14-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"avital:react-in-blaze 0.0.1\": [\n        \"meteor\",\n        \"templating@1.0.11\"\n      ],\n      \"avital:react-in-blaze 0.0.2\": [\n        \"meteor\",\n        \"templating@1.0.11\",\n        \"hipertracker:reactjs@0.0.8\"\n      ],\n      \"avital:react-in-blaze 0.0.3\": [\n        \"meteor\",\n        \"templating@1.0.11\",\n        \"hipertracker:reactjs@0.0.8\"\n      ],\n      \"hipertracker:reactjs 0.0.2\": [\n        \"meteor\"\n      ],\n      \"hipertracker:reactjs 0.0.3\": [\n        \"meteor\"\n      ],\n      \"hipertracker:reactjs 0.0.4\": [\n        \"meteor\"\n      ],\n      \"hipertracker:reactjs 0.0.5\": [\n        \"meteor\"\n      ],\n      \"hipertracker:reactjs 0.0.6\": [\n        \"meteor\"\n      ],\n      \"hipertracker:reactjs 0.0.7\": [\n        \"meteor\"\n      ],\n      \"hipertracker:reactjs 0.0.8\": [\n        \"meteor\"\n      ],\n      \"insecure 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"insecure 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"insecure 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"insecure 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"insecure 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"insecure 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"insecure 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"insecure 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"insecure 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"insecure 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"insecure 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"insecure 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"insecure 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"insecure 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"insecure 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"insecure 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"insecure 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"insecure 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"insecure 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"insecure 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"insecure 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"insecure 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"insecure 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"insecure 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"autopublish 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\"\n      ],\n      \"autopublish 1.0.0\": [\n        \"meteor@1.0.2\"\n      ],\n      \"autopublish 1.0.1-pre.0\": [\n        \"meteor\"\n      ],\n      \"autopublish 1.0.1-pre.1\": [\n        \"meteor\"\n      ],\n      \"autopublish 1.0.1-pre.2\": [\n        \"meteor@1.1.2-pre.2\"\n      ],\n      \"autopublish 1.0.1-rc.0\": [\n        \"meteor@1.1.2-rc.0\"\n      ],\n      \"autopublish 1.0.1-win.0\": [\n        \"meteor@1.1.3-win.0\"\n      ],\n      \"autopublish 1.0.1\": [\n        \"meteor@1.1.2\"\n      ],\n      \"autopublish 1.0.2-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\"\n      ],\n      \"autopublish 1.0.2-rc.1\": [\n        \"meteor@1.1.4-rc.1\"\n      ],\n      \"autopublish 1.0.2-slava.0\": [\n        \"meteor@1.1.4-slava.0\"\n      ],\n      \"autopublish 1.0.2-win.0\": [\n        \"meteor@1.1.4-win.0\"\n      ],\n      \"autopublish 1.0.2-winr.0\": [\n        \"meteor@1.1.4-winr.0\"\n      ],\n      \"autopublish 1.0.2\": [\n        \"meteor@1.1.4\"\n      ],\n      \"autopublish 1.0.3-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\"\n      ],\n      \"autopublish 1.0.3-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\"\n      ],\n      \"autopublish 1.0.3-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\"\n      ],\n      \"autopublish 1.0.3-githubble.2\": [\n        \"meteor@1.1.5-githubble.2\"\n      ],\n      \"autopublish 1.0.3-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\"\n      ],\n      \"autopublish 1.0.3-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\"\n      ],\n      \"autopublish 1.0.3-rc.0\": [\n        \"meteor@1.1.5-rc.0\"\n      ],\n      \"autopublish 1.0.3-winr.0\": [\n        \"meteor@1.1.5-winr.0\"\n      ],\n      \"autopublish 1.0.3-winr.1\": [\n        \"meteor@1.1.5-winr.1\"\n      ],\n      \"autopublish 1.0.3-winr.2\": [\n        \"meteor@1.1.5-winr.4\"\n      ],\n      \"meteor-platform 0.0.0-glasser-isopacket.0\": [\n        \"meteor@1.5.0-glasser.isopacket.0\",\n        \"reload@10.0.0-glasser.isopacket.0\",\n        \"autoupdate@10.0.0-glasser.isopacket.0\",\n        \"webapp@10.0.0-glasser.isopacket.0\",\n        \"logging@10.0.0-glasser.isopacket.0\",\n        \"tracker@10.0.0-glasser.isopacket.0\",\n        \"deps@10.0.0-glasser.isopacket.0\",\n        \"session@10.0.0-glasser.isopacket.0\",\n        \"ddp@10.0.0-glasser.isopacket.0\",\n        \"livedata@10.0.0-glasser.isopacket.0\",\n        \"mongo@10.0.0-glasser.isopacket.0\",\n        \"blaze@10.0.0-glasser.isopacket.0\",\n        \"ui@10.0.0-glasser.isopacket.0\",\n        \"spacebars@10.0.0-glasser.isopacket.0\",\n        \"templating@10.0.0-glasser.isopacket.0\",\n        \"check@10.0.0-glasser.isopacket.0\",\n        \"underscore@10.0.0-glasser.isopacket.0\",\n        \"jquery@1.5.0-glasser.isopacket.0\",\n        \"random@10.0.0-glasser.isopacket.0\",\n        \"ejson@10.0.0-glasser.isopacket.0\",\n        \"launch-screen@10.0.0-glasser.isopacket.0\",\n        \"fastclick@10.0.0-glasser.isopacket.0\",\n        \"mobile-status-bar@10.0.0-glasser.isopacket.0\"\n      ],\n      \"meteor-platform 0.0.1\": [\n        \"meteor\"\n      ],\n      \"meteor-platform 1.0.1-glasser1\": [\n        \"meteor\",\n        \"reload\",\n        \"autoupdate\",\n        \"webapp\",\n        \"logging\",\n        \"tracker\",\n        \"session\",\n        \"ddp\",\n        \"mongo\",\n        \"blaze\",\n        \"spacebars\",\n        \"templating\",\n        \"check\",\n        \"underscore\",\n        \"jquery\",\n        \"random\",\n        \"ejson\",\n        \"fastclick\",\n        \"mobile-status-bar\"\n      ],\n      \"meteor-platform 1.0.1-rc0\": [\n        \"meteor\",\n        \"reload\",\n        \"autoupdate\",\n        \"webapp\",\n        \"logging\",\n        \"tracker\",\n        \"session\",\n        \"livedata\",\n        \"mongo-livedata\",\n        \"blaze\",\n        \"spacebars\",\n        \"templating\",\n        \"check\",\n        \"underscore\",\n        \"jquery\",\n        \"random\",\n        \"ejson\"\n      ],\n      \"meteor-platform 1.0.1-rc1\": [\n        \"meteor\",\n        \"reload\",\n        \"autoupdate\",\n        \"webapp\",\n        \"logging\",\n        \"tracker\",\n        \"session\",\n        \"ddp\",\n        \"mongo\",\n        \"blaze\",\n        \"spacebars\",\n        \"templating\",\n        \"check\",\n        \"underscore\",\n        \"jquery\",\n        \"random\",\n        \"ejson\"\n      ],\n      \"meteor-platform 1.0.1\": [\n        \"autoupdate@1.0.6\",\n        \"blaze@2.0.0\",\n        \"check@1.0.0\",\n        \"ddp@1.0.8\",\n        \"ejson@1.0.1\",\n        \"jquery@1.0.0\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.3\",\n        \"mongo@1.0.4\",\n        \"random@1.0.0\",\n        \"reload@1.0.1\",\n        \"session@1.0.1\",\n        \"spacebars@1.0.1\",\n        \"templating@1.0.5\",\n        \"tracker@1.0.2\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.3\"\n      ],\n      \"meteor-platform 1.0.2\": [\n        \"autoupdate@1.0.6\",\n        \"blaze@2.0.0\",\n        \"check@1.0.0\",\n        \"ddp@1.0.8\",\n        \"deps@1.0.3\",\n        \"ejson@1.0.1\",\n        \"jquery@1.0.0\",\n        \"livedata@1.0.9\",\n        \"logging@1.0.2\",\n        \"meteor@1.0.3\",\n        \"mongo@1.0.4\",\n        \"random@1.0.0\",\n        \"reload@1.0.1\",\n        \"session@1.0.1\",\n        \"spacebars@1.0.1\",\n        \"templating@1.0.5\",\n        \"tracker@1.0.2\",\n        \"ui@1.0.2\",\n        \"underscore@1.0.0\",\n        \"webapp@1.0.3\"\n      ],\n      \"meteor-platform 1.0.3-ekate\": [\n        \"meteor\",\n        \"reload\",\n        \"autoupdate\",\n        \"webapp\",\n        \"logging\",\n        \"tracker\",\n        \"deps\",\n        \"session\",\n        \"ddp\",\n        \"livedata\",\n        \"mongo\",\n        \"blaze\",\n        \"ui\",\n        \"spacebars\",\n        \"templating\",\n        \"check\",\n        \"underscore\",\n        \"jquery\",\n        \"random\",\n        \"ejson\",\n        \"fastclick\",\n        \"mobile-status-bar\"\n      ],\n      \"meteor-platform 1.1.0-rc0\": [\n        \"meteor\",\n        \"reload\",\n        \"autoupdate\",\n        \"webapp\",\n        \"logging\",\n        \"tracker\",\n        \"session\",\n        \"ddp\",\n        \"mongo\",\n        \"blaze\",\n        \"spacebars\",\n        \"templating\",\n        \"check\",\n        \"underscore\",\n        \"jquery\",\n        \"random\",\n        \"ejson\",\n        \"fastclick\",\n        \"mobile-status-bar\"\n      ],\n      \"meteor-platform 1.1.0-rc1\": [\n        \"meteor\",\n        \"reload\",\n        \"autoupdate\",\n        \"webapp\",\n        \"logging\",\n        \"tracker\",\n        \"deps\",\n        \"session\",\n        \"ddp\",\n        \"livedata\",\n        \"mongo\",\n        \"blaze\",\n        \"ui\",\n        \"spacebars\",\n        \"templating\",\n        \"check\",\n        \"underscore\",\n        \"jquery\",\n        \"random\",\n        \"ejson\",\n        \"fastclick\",\n        \"mobile-status-bar\"\n      ],\n      \"meteor-platform 1.1.0-rc2\": [\n        \"meteor\",\n        \"reload\",\n        \"autoupdate\",\n        \"webapp\",\n        \"logging\",\n        \"tracker\",\n        \"deps\",\n        \"session\",\n        \"ddp\",\n        \"livedata\",\n        \"mongo\",\n        \"blaze\",\n        \"ui\",\n        \"spacebars\",\n        \"templating\",\n        \"check\",\n        \"underscore\",\n        \"jquery\",\n        \"random\",\n        \"ejson\",\n        \"fastclick\",\n        \"mobile-status-bar\"\n      ],\n      \"meteor-platform 1.1.0\": [\n        \"autoupdate@1.1.0\",\n        \"blaze@2.0.0\",\n        \"check@1.0.0\",\n        \"ddp@1.0.8\",\n        \"deps@1.0.3\",\n        \"ejson@1.0.2\",\n        \"fastclick@1.0.0\",\n        \"jquery@1.0.0\",\n        \"livedata@1.0.9\",\n        \"logging@1.0.3\",\n        \"meteor@1.1.0\",\n        \"mobile-status-bar@1.0.0\",\n        \"mongo@1.0.5\",\n        \"random@1.0.0\",\n        \"reload@1.1.0\",\n        \"session@1.0.1\",\n        \"spacebars@1.0.1\",\n        \"templating@1.0.6\",\n        \"tracker@1.0.2\",\n        \"ui@1.0.2\",\n        \"underscore@1.0.0\",\n        \"webapp@1.1.1\"\n      ],\n      \"meteor-platform 1.1.1-rc0\": [\n        \"meteor\",\n        \"reload\",\n        \"autoupdate\",\n        \"webapp\",\n        \"logging\",\n        \"tracker\",\n        \"deps\",\n        \"session\",\n        \"ddp\",\n        \"livedata\",\n        \"mongo\",\n        \"blaze\",\n        \"ui\",\n        \"spacebars\",\n        \"templating\",\n        \"check\",\n        \"underscore\",\n        \"jquery\",\n        \"random\",\n        \"ejson\",\n        \"fastclick\",\n        \"mobile-status-bar\"\n      ],\n      \"meteor-platform 1.1.1\": [\n        \"autoupdate@1.1.1\",\n        \"blaze@2.0.1\",\n        \"check@1.0.1\",\n        \"ddp@1.0.9\",\n        \"deps@1.0.4\",\n        \"ejson@1.0.3\",\n        \"fastclick@1.0.0\",\n        \"jquery@1.0.0\",\n        \"livedata@1.0.10\",\n        \"logging@1.0.3\",\n        \"meteor@1.1.1\",\n        \"mobile-status-bar@1.0.0\",\n        \"mongo@1.0.6\",\n        \"random@1.0.0\",\n        \"reload@1.1.0\",\n        \"session@1.0.2\",\n        \"spacebars@1.0.2\",\n        \"templating@1.0.7\",\n        \"tracker@1.0.2\",\n        \"ui@1.0.3\",\n        \"underscore@1.0.0\",\n        \"webapp@1.1.2\"\n      ],\n      \"meteor-platform 1.1.2-nim.1\": [\n        \"meteor@1.1.2-nim.0\",\n        \"reload@1.1.1-rc.0\",\n        \"autoupdate@1.1.2-nim.0\",\n        \"webapp@1.1.3-nim.0\",\n        \"logging@1.0.4-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"deps@1.0.5-rc.0\",\n        \"session@1.0.3-rc.0\",\n        \"ddp@1.0.10-nim.0\",\n        \"livedata@1.0.11-rc.0\",\n        \"mongo@1.0.7-rc.0\",\n        \"blaze@2.0.2-rc.0\",\n        \"ui@1.0.4-rc.0\",\n        \"spacebars@1.0.3-rc.0\",\n        \"templating@1.0.8-nim.0\",\n        \"check@1.0.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"jquery@1.0.1-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"fastclick@1.0.1-rc.0\",\n        \"mobile-status-bar@1.0.1-rc.0\"\n      ],\n      \"meteor-platform 1.1.2-pre.0\": [\n        \"meteor\",\n        \"reload\",\n        \"autoupdate\",\n        \"webapp\",\n        \"logging\",\n        \"tracker\",\n        \"deps\",\n        \"session\",\n        \"ddp\",\n        \"livedata\",\n        \"mongo\",\n        \"blaze\",\n        \"ui\",\n        \"spacebars\",\n        \"templating\",\n        \"check\",\n        \"underscore\",\n        \"jquery\",\n        \"random\",\n        \"ejson\",\n        \"fastclick\",\n        \"mobile-status-bar\"\n      ],\n      \"meteor-platform 1.1.2-pre.1\": [\n        \"meteor\",\n        \"reload\",\n        \"autoupdate\",\n        \"webapp\",\n        \"logging\",\n        \"tracker\",\n        \"deps\",\n        \"session\",\n        \"ddp\",\n        \"livedata\",\n        \"mongo\",\n        \"blaze\",\n        \"ui\",\n        \"spacebars\",\n        \"templating\",\n        \"check\",\n        \"underscore\",\n        \"jquery\",\n        \"random\",\n        \"ejson\",\n        \"fastclick\",\n        \"mobile-status-bar\"\n      ],\n      \"meteor-platform 1.1.2-pre.2\": [\n        \"meteor@1.1.2-pre.2\",\n        \"reload@1.1.1-pre.2\",\n        \"autoupdate@1.1.2-pre.2\",\n        \"webapp@1.1.3-pre.2\",\n        \"logging@1.0.4-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"deps@1.0.5-pre.2\",\n        \"session@1.0.3-pre.2\",\n        \"ddp@1.0.10-pre.2\",\n        \"livedata@1.0.11-pre.2\",\n        \"mongo@1.0.7-pre.2\",\n        \"blaze@2.0.2-pre.2\",\n        \"ui@1.0.4-pre.2\",\n        \"spacebars@1.0.3-pre.2\",\n        \"templating@1.0.8-pre.2\",\n        \"check@1.0.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"jquery@1.0.1-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"ejson@1.0.4-pre.2\",\n        \"fastclick@1.0.1-pre.2\",\n        \"mobile-status-bar@1.0.1-pre.2\"\n      ],\n      \"meteor-platform 1.1.2-pre.3\": [\n        \"meteor@1.1.2-pre.3\",\n        \"reload@1.1.1-pre.2\",\n        \"autoupdate@1.1.2-pre.3\",\n        \"webapp@1.1.3-pre.3\",\n        \"logging@1.0.4-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"deps@1.0.5-pre.2\",\n        \"session@1.0.3-pre.2\",\n        \"ddp@1.0.10-pre.2\",\n        \"livedata@1.0.11-pre.2\",\n        \"mongo@1.0.7-pre.2\",\n        \"blaze@2.0.2-pre.2\",\n        \"ui@1.0.4-pre.2\",\n        \"spacebars@1.0.3-pre.2\",\n        \"templating@1.0.8-pre.3\",\n        \"check@1.0.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"jquery@1.0.1-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"ejson@1.0.4-pre.2\",\n        \"fastclick@1.0.1-pre.3\",\n        \"mobile-status-bar@1.0.1-pre.2\"\n      ],\n      \"meteor-platform 1.1.2-pre.4\": [\n        \"meteor@1.1.2-pre.3\",\n        \"reload@1.1.1-pre.2\",\n        \"autoupdate@1.1.2-pre.4\",\n        \"webapp@1.1.3-pre.3\",\n        \"logging@1.0.4-pre.2\",\n        \"tracker@1.0.3-pre.2\",\n        \"deps@1.0.5-pre.2\",\n        \"session@1.0.3-pre.2\",\n        \"ddp@1.0.10-pre.2\",\n        \"livedata@1.0.11-pre.2\",\n        \"mongo@1.0.7-pre.2\",\n        \"blaze@2.0.2-pre.2\",\n        \"ui@1.0.4-pre.2\",\n        \"spacebars@1.0.3-pre.2\",\n        \"templating@1.0.8-pre.3\",\n        \"check@1.0.2-pre.2\",\n        \"underscore@1.0.1-pre.2\",\n        \"jquery@1.0.1-pre.2\",\n        \"random@1.0.1-pre.2\",\n        \"ejson@1.0.4-pre.2\",\n        \"fastclick@1.0.1-pre.3\",\n        \"mobile-status-bar@1.0.1-pre.2\"\n      ],\n      \"meteor-platform 1.1.2-rc.0\": [\n        \"meteor@1.1.2-rc.0\",\n        \"reload@1.1.1-rc.0\",\n        \"autoupdate@1.1.2-rc.0\",\n        \"webapp@1.1.3-rc.0\",\n        \"logging@1.0.4-rc.0\",\n        \"tracker@1.0.3-rc.0\",\n        \"deps@1.0.5-rc.0\",\n        \"session@1.0.3-rc.0\",\n        \"ddp@1.0.10-rc.0\",\n        \"livedata@1.0.11-rc.0\",\n        \"mongo@1.0.7-rc.0\",\n        \"blaze@2.0.2-rc.0\",\n        \"ui@1.0.4-rc.0\",\n        \"spacebars@1.0.3-rc.0\",\n        \"templating@1.0.8-rc.0\",\n        \"check@1.0.2-rc.0\",\n        \"underscore@1.0.1-rc.0\",\n        \"jquery@1.0.1-rc.0\",\n        \"random@1.0.1-rc.0\",\n        \"ejson@1.0.4-rc.0\",\n        \"fastclick@1.0.1-rc.0\",\n        \"mobile-status-bar@1.0.1-rc.0\"\n      ],\n      \"meteor-platform 1.1.2-refreshpolicy.1\": [\n        \"meteor@1.1.2-refreshpolicy.1\",\n        \"reload@1.1.1\",\n        \"autoupdate@1.1.2-refreshpolicy.1\",\n        \"webapp@1.1.3\",\n        \"logging@1.0.4\",\n        \"tracker@1.0.3\",\n        \"deps@1.0.5\",\n        \"session@1.0.3-refreshpolicy.1\",\n        \"ddp@1.0.10-refreshpolicy.1\",\n        \"livedata@1.0.11\",\n        \"mongo@1.0.7\",\n        \"blaze@2.0.2-refreshpolicy.1\",\n        \"ui@1.0.4\",\n        \"spacebars@1.0.3\",\n        \"templating@1.0.8\",\n        \"check@1.0.2\",\n        \"underscore@1.0.1\",\n        \"jquery@1.0.1\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"launch-screen@1.0.0-refreshpolicy.1\",\n        \"fastclick@1.0.1\",\n        \"mobile-status-bar@1.0.1\"\n      ],\n      \"meteor-platform 1.1.2\": [\n        \"meteor@1.1.2\",\n        \"reload@1.1.1\",\n        \"autoupdate@1.1.2\",\n        \"webapp@1.1.3\",\n        \"logging@1.0.4\",\n        \"tracker@1.0.3\",\n        \"deps@1.0.5\",\n        \"session@1.0.3\",\n        \"ddp@1.0.10\",\n        \"livedata@1.0.11\",\n        \"mongo@1.0.7\",\n        \"blaze@2.0.2\",\n        \"ui@1.0.4\",\n        \"spacebars@1.0.3\",\n        \"templating@1.0.8\",\n        \"check@1.0.2\",\n        \"underscore@1.0.1\",\n        \"jquery@1.0.1\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"fastclick@1.0.1\",\n        \"mobile-status-bar@1.0.1\"\n      ],\n      \"meteor-platform 1.2.0-rc.0\": [\n        \"meteor@1.1.3-rc.0\",\n        \"reload@1.1.1\",\n        \"autoupdate@1.1.3-rc.0\",\n        \"webapp@1.1.4-rc.0\",\n        \"logging@1.0.5-rc.0\",\n        \"tracker@1.0.3\",\n        \"deps@1.0.5\",\n        \"session@1.0.4-rc.0\",\n        \"ddp@1.0.11-rc.0\",\n        \"livedata@1.0.11\",\n        \"mongo@1.0.8-rc.0\",\n        \"blaze@2.0.3-rc.0\",\n        \"ui@1.0.4\",\n        \"spacebars@1.0.3\",\n        \"templating@1.0.9-rc.0\",\n        \"check@1.0.2\",\n        \"underscore@1.0.1\",\n        \"jquery@1.0.1\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"launch-screen@1.0.0-rc.0\",\n        \"fastclick@1.0.1\",\n        \"mobile-status-bar@1.0.1\"\n      ],\n      \"meteor-platform 1.2.0-win.0\": [\n        \"meteor@1.1.3-win.0\",\n        \"reload@1.1.1-win.0\",\n        \"autoupdate@1.1.3-win.0\",\n        \"webapp@1.1.4-win.0\",\n        \"logging@1.0.5-win.0\",\n        \"tracker@1.0.3-win.0\",\n        \"deps@1.0.5-win.0\",\n        \"session@1.0.4-win.0\",\n        \"ddp@1.0.11-win.0\",\n        \"livedata@1.0.11-win.0\",\n        \"mongo@1.0.8-win.0\",\n        \"blaze@2.0.3-win.0\",\n        \"ui@1.0.4-win.0\",\n        \"spacebars@1.0.3-win.0\",\n        \"templating@1.0.9-win.0\",\n        \"check@1.0.2-win.0\",\n        \"underscore@1.0.1-win.0\",\n        \"jquery@1.0.1-win.0\",\n        \"random@1.0.1-win.0\",\n        \"ejson@1.0.4-win.0\",\n        \"launch-screen@1.0.0-win.0\",\n        \"fastclick@1.0.1-win.0\",\n        \"mobile-status-bar@1.0.1-win.0\"\n      ],\n      \"meteor-platform 1.2.0\": [\n        \"meteor@1.1.3\",\n        \"reload@1.1.1\",\n        \"autoupdate@1.1.3\",\n        \"webapp@1.1.4\",\n        \"logging@1.0.5\",\n        \"tracker@1.0.3\",\n        \"deps@1.0.5\",\n        \"session@1.0.4\",\n        \"ddp@1.0.11\",\n        \"livedata@1.0.11\",\n        \"mongo@1.0.8\",\n        \"blaze@2.0.3\",\n        \"ui@1.0.4\",\n        \"spacebars@1.0.3\",\n        \"templating@1.0.9\",\n        \"check@1.0.2\",\n        \"underscore@1.0.1\",\n        \"jquery@1.0.1\",\n        \"random@1.0.1\",\n        \"ejson@1.0.4\",\n        \"launch-screen@1.0.0\",\n        \"fastclick@1.0.1\",\n        \"mobile-status-bar@1.0.1\"\n      ],\n      \"meteor-platform 1.2.1-eachin.0\": [\n        \"meteor@1.1.5-eachin.0\",\n        \"reload@1.1.3-eachin.0\",\n        \"autoupdate@1.1.5-eachin.0\",\n        \"webapp@1.1.6-eachin.0\",\n        \"logging@1.0.6-eachin.0\",\n        \"tracker@1.0.5-eachin.0\",\n        \"deps@1.0.7-eachin.0\",\n        \"session@1.0.6-eachin.0\",\n        \"ddp@1.0.14-eachin.0\",\n        \"livedata@1.0.13-eachin.0\",\n        \"mongo@1.0.12-eachin.0\",\n        \"blaze@2.0.5-eachin.0\",\n        \"ui@1.0.6-eachin.0\",\n        \"spacebars@1.0.5-eachin.0\",\n        \"templating@1.0.11-eachin.0\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.3-eachin.0\",\n        \"jquery@1.11.3-winr.2_1\",\n        \"random@1.0.3-eachin.0\",\n        \"ejson@1.0.6-eachin.0\",\n        \"launch-screen@1.0.1-eachin.0\",\n        \"fastclick@1.0.3-eachin.0\",\n        \"mobile-status-bar@1.0.3-winr.2\"\n      ],\n      \"meteor-platform 1.2.1-ipc.0\": [\n        \"meteor@1.1.4-ipc.0\",\n        \"reload@1.1.2-ipc.0\",\n        \"autoupdate@1.1.4-ipc.0\",\n        \"webapp@1.1.5-ipc.0\",\n        \"logging@1.0.6-ipc.0\",\n        \"tracker@1.0.4-ipc.0\",\n        \"deps@1.0.6-ipc.0\",\n        \"session@1.0.5-ipc.0\",\n        \"ddp@1.0.12-ipc.0\",\n        \"livedata@1.0.12-ipc.0\",\n        \"mongo@1.0.9-ipc.0\",\n        \"blaze@2.0.4-ipc.0\",\n        \"ui@1.0.5-ipc.0\",\n        \"spacebars@1.0.4-ipc.0\",\n        \"templating@1.0.10-ipc.0\",\n        \"check@1.0.3-ipc.0\",\n        \"underscore@1.0.2-ipc.0\",\n        \"jquery@1.0.2-ipc.0\",\n        \"random@1.0.2-ipc.0\",\n        \"ejson@1.0.5-ipc.0\",\n        \"launch-screen@1.0.1-ipc.0\",\n        \"fastclick@1.0.2-ipc.0\",\n        \"mobile-status-bar@1.0.2-ipc.0\"\n      ],\n      \"meteor-platform 1.2.1-rc.1\": [\n        \"meteor@1.1.4-rc.1\",\n        \"reload@1.1.2-rc.1\",\n        \"autoupdate@1.1.4-rc.1\",\n        \"webapp@1.1.5-rc.1\",\n        \"logging@1.0.6-rc.1\",\n        \"tracker@1.0.4-rc.1\",\n        \"deps@1.0.6-rc.1\",\n        \"session@1.0.5-rc.1\",\n        \"ddp@1.0.13-rc.1\",\n        \"livedata@1.0.12-rc.1\",\n        \"mongo@1.0.10-rc.1\",\n        \"blaze@2.0.4-rc.1\",\n        \"ui@1.0.5-rc.1\",\n        \"spacebars@1.0.4-rc.1\",\n        \"templating@1.0.10-rc.1\",\n        \"check@1.0.3-rc.1\",\n        \"underscore@1.0.2-rc.1\",\n        \"jquery@1.0.2-rc.1\",\n        \"random@1.0.2-rc.1\",\n        \"ejson@1.0.5-rc.1\",\n        \"launch-screen@1.0.1-rc.1\",\n        \"fastclick@1.0.2-rc.1\",\n        \"mobile-status-bar@1.0.2-rc.1\"\n      ],\n      \"meteor-platform 1.2.1-slava.0\": [\n        \"meteor@1.1.4-slava.0\",\n        \"reload@1.1.2-slava.0\",\n        \"autoupdate@1.1.4-slava.0\",\n        \"webapp@1.1.5-slava.0\",\n        \"logging@1.0.6-slava.0\",\n        \"tracker@1.0.4-slava.0\",\n        \"deps@1.0.6-slava.0\",\n        \"session@1.0.5-slava.0\",\n        \"ddp@1.0.13-slava.0\",\n        \"livedata@1.0.12-slava.0\",\n        \"mongo@1.0.10-slava.0\",\n        \"blaze@2.0.4-slava.0\",\n        \"ui@1.0.5-slava.0\",\n        \"spacebars@1.0.4-slava.0\",\n        \"templating@1.0.10-slava.0\",\n        \"check@1.0.3-slava.0\",\n        \"underscore@1.0.2-slava.0\",\n        \"jquery@1.0.2-slava.0\",\n        \"random@1.0.2-slava.0\",\n        \"ejson@1.0.5-slava.0\",\n        \"launch-screen@1.0.1-slava.0\",\n        \"fastclick@1.0.2-slava.0\",\n        \"mobile-status-bar@1.0.2-slava.0\"\n      ],\n      \"meteor-platform 1.2.1-win.0\": [\n        \"meteor@1.1.4-win.0\",\n        \"reload@1.1.2-win.0\",\n        \"autoupdate@1.1.4-win.0\",\n        \"webapp@1.1.5-win.0\",\n        \"logging@1.0.6-win.0\",\n        \"tracker@1.0.4-win.0\",\n        \"deps@1.0.6-win.0\",\n        \"session@1.0.5-win.0\",\n        \"ddp@1.0.12-win.0\",\n        \"livedata@1.0.12-win.0\",\n        \"mongo@1.0.9-win.0\",\n        \"blaze@2.0.4-win.0\",\n        \"ui@1.0.5-win.0\",\n        \"spacebars@1.0.4-win.0\",\n        \"templating@1.0.10-win.0\",\n        \"check@1.0.3-win.0\",\n        \"underscore@1.0.2-win.0\",\n        \"jquery@1.0.2-win.0\",\n        \"random@1.0.2-win.0\",\n        \"ejson@1.0.5-win.0\",\n        \"launch-screen@1.0.1-win.0\",\n        \"fastclick@1.0.2-win.0\",\n        \"mobile-status-bar@1.0.2-win.0\"\n      ],\n      \"meteor-platform 1.2.1-winr.0\": [\n        \"meteor@1.1.4-winr.0\",\n        \"reload@1.1.2-winr.0\",\n        \"autoupdate@1.1.4-winr.0\",\n        \"webapp@1.1.5-winr.0\",\n        \"logging@1.0.6-winr.0\",\n        \"tracker@1.0.4-winr.0\",\n        \"deps@1.0.6-winr.0\",\n        \"session@1.0.5-winr.0\",\n        \"ddp@1.0.13-winr.0\",\n        \"livedata@1.0.12-winr.0\",\n        \"mongo@1.0.10-winr.0\",\n        \"blaze@2.0.4-winr.0\",\n        \"ui@1.0.5-winr.0\",\n        \"spacebars@1.0.4-winr.0\",\n        \"templating@1.0.10-winr.0\",\n        \"check@1.0.3-winr.0\",\n        \"underscore@1.0.2-winr.0\",\n        \"jquery@1.0.2-winr.0\",\n        \"random@1.0.2-winr.0\",\n        \"ejson@1.0.5-winr.0\",\n        \"launch-screen@1.0.1-winr.0\",\n        \"fastclick@1.0.2-winr.0\",\n        \"mobile-status-bar@1.0.2-winr.0\"\n      ],\n      \"meteor-platform 1.2.1-winr.1\": [\n        \"meteor@1.1.5-winr.3\",\n        \"reload@1.1.3-winr.1\",\n        \"autoupdate@1.1.5-winr.3\",\n        \"webapp@1.1.6-winr.3\",\n        \"logging@1.0.6\",\n        \"tracker@1.0.5-winr.3\",\n        \"deps@1.0.7-winr.1\",\n        \"session@1.0.6-winr.1\",\n        \"ddp@1.0.14-winr.3\",\n        \"livedata@1.0.13-winr.1\",\n        \"mongo@1.0.12-winr.1\",\n        \"blaze@2.0.5-winr.1\",\n        \"ui@1.0.6-winr.1\",\n        \"spacebars@1.0.5-winr.3\",\n        \"templating@1.0.11-winr.3\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.3-winr.1\",\n        \"jquery@1.11.3-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\",\n        \"launch-screen@1.0.1\",\n        \"fastclick@1.0.3-winr.1\",\n        \"mobile-status-bar@1.0.3-winr.1\"\n      ],\n      \"meteor-platform 1.2.1-winr.2\": [\n        \"meteor@1.1.5-winr.3\",\n        \"reload@1.1.3-winr.2\",\n        \"autoupdate@1.1.5-winr.3\",\n        \"webapp@1.1.6-winr.3\",\n        \"logging@1.0.6-winr.1\",\n        \"tracker@1.0.5-winr.3\",\n        \"deps@1.0.7-winr.1\",\n        \"session@1.0.6-winr.1\",\n        \"ddp@1.0.14-winr.3\",\n        \"livedata@1.0.13-winr.1\",\n        \"mongo@1.0.12-winr.1\",\n        \"blaze@2.0.5-winr.1\",\n        \"ui@1.0.6-winr.1\",\n        \"spacebars@1.0.5-winr.3\",\n        \"templating@1.0.11-winr.3\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.3-winr.1\",\n        \"jquery@1.11.3-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\",\n        \"launch-screen@1.0.1-winr.1\",\n        \"fastclick@1.0.3-winr.1\",\n        \"mobile-status-bar@1.0.3-winr.1\"\n      ],\n      \"meteor-platform 1.2.1-winr.3\": [\n        \"meteor@1.1.5-winr.4\",\n        \"reload@1.1.3-winr.3\",\n        \"autoupdate@1.1.5-winr.4\",\n        \"webapp@1.1.6-winr.4\",\n        \"logging@1.0.6-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"deps@1.0.7-winr.2\",\n        \"session@1.0.6-winr.2\",\n        \"ddp@1.0.14-winr.4\",\n        \"livedata@1.0.13-winr.2\",\n        \"mongo@1.0.12-winr.2\",\n        \"blaze@2.0.5-winr.2\",\n        \"ui@1.0.6-winr.2\",\n        \"spacebars@1.0.5-winr.4\",\n        \"templating@1.0.11-winr.4\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.3-winr.2\",\n        \"jquery@1.11.3-winr.2\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"launch-screen@1.0.1-winr.2\",\n        \"fastclick@1.0.3-winr.2\",\n        \"mobile-status-bar@1.0.3-winr.2\"\n      ],\n      \"meteor-platform 1.2.1\": [\n        \"meteor@1.1.4\",\n        \"reload@1.1.2\",\n        \"autoupdate@1.1.4\",\n        \"webapp@1.1.5\",\n        \"logging@1.0.6\",\n        \"tracker@1.0.4\",\n        \"deps@1.0.6\",\n        \"session@1.0.5\",\n        \"ddp@1.0.13\",\n        \"livedata@1.0.12\",\n        \"mongo@1.0.10\",\n        \"blaze@2.0.4\",\n        \"ui@1.0.5\",\n        \"spacebars@1.0.4\",\n        \"templating@1.0.10\",\n        \"check@1.0.3\",\n        \"underscore@1.0.2\",\n        \"jquery@1.0.2\",\n        \"random@1.0.2\",\n        \"ejson@1.0.5\",\n        \"launch-screen@1.0.1\",\n        \"fastclick@1.0.2\",\n        \"mobile-status-bar@1.0.2\"\n      ],\n      \"meteor-platform 1.2.2-eachin.43\": [\n        \"meteor@1.1.5-eachin.43\",\n        \"reload@1.1.3-eachin.43\",\n        \"autoupdate@1.1.6-eachin.43\",\n        \"webapp@1.1.7-eachin.43\",\n        \"logging@1.0.6-eachin.43\",\n        \"tracker@1.0.5-eachin.43\",\n        \"deps@1.0.7-eachin.43\",\n        \"session@1.0.6-eachin.43\",\n        \"ddp@1.0.15-eachin.43\",\n        \"livedata@1.0.13-eachin.43\",\n        \"mongo@1.0.12-eachin.45\",\n        \"blaze@2.0.5-eachin.43\",\n        \"ui@1.0.6-eachin.43\",\n        \"spacebars@1.0.5-eachin.43\",\n        \"templating@1.0.12-eachin.43\",\n        \"check@1.0.4-eachin.43\",\n        \"underscore@1.0.3-eachin.43\",\n        \"jquery@1.11.3-eachin.43_1\",\n        \"random@1.0.3-eachin.43\",\n        \"ejson@1.0.6-eachin.43\",\n        \"launch-screen@1.0.1-eachin.43\",\n        \"fastclick@1.0.3-eachin.43\",\n        \"mobile-status-bar@1.0.3-eachin.43\"\n      ],\n      \"meteor-platform 1.2.2-githubble.0\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"reload@1.1.3-winr.3\",\n        \"autoupdate@1.1.6-githubble.0\",\n        \"webapp@1.1.7-githubble.0\",\n        \"logging@1.0.6-winr.2\",\n        \"tracker@1.0.5-winr.4\",\n        \"deps@1.0.7-winr.2\",\n        \"session@1.0.6-winr.2\",\n        \"ddp@1.0.15-githubble.0\",\n        \"livedata@1.0.13-winr.2\",\n        \"mongo@1.0.12-githubble.0\",\n        \"blaze@2.0.5-githubble.0\",\n        \"ui@1.0.6-winr.2\",\n        \"spacebars@1.0.5-winr.5\",\n        \"templating@1.0.12-githubble.0\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.3-winr.2\",\n        \"jquery@1.11.3-winr.2_1\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"launch-screen@1.0.1-winr.3\",\n        \"fastclick@1.0.3-winr.2\",\n        \"mobile-status-bar@1.0.3-winr.2\"\n      ],\n      \"meteor-platform 1.2.2-githubble.1\": [\n        \"meteor@1.1.5-githubble.0\",\n        \"reload@1.1.3-githubble.0\",\n        \"autoupdate@1.1.6-githubble.0\",\n        \"webapp@1.1.7-githubble.0\",\n        \"logging@1.0.6-githubble.0\",\n        \"tracker@1.0.5-githubble.0\",\n        \"deps@1.0.7-githubble.0\",\n        \"session@1.0.6-githubble.0\",\n        \"ddp@1.0.15-githubble.0\",\n        \"livedata@1.0.13-githubble.0\",\n        \"mongo@1.0.12-githubble.0\",\n        \"blaze@2.0.5-githubble.0\",\n        \"ui@1.0.6-githubble.0\",\n        \"spacebars@1.0.5-githubble.0\",\n        \"templating@1.0.12-githubble.0\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.3-githubble.0\",\n        \"jquery@1.11.3-githubble.0_1\",\n        \"random@1.0.3-githubble.0\",\n        \"ejson@1.0.6-githubble.0\",\n        \"launch-screen@1.0.1-githubble.0\",\n        \"fastclick@1.0.3-githubble.0\",\n        \"mobile-status-bar@1.0.3-githubble.0\"\n      ],\n      \"meteor-platform 1.2.2-githubble.42\": [\n        \"meteor@1.1.5-githubble.42\",\n        \"reload@1.1.3-githubble.42\",\n        \"autoupdate@1.1.6-githubble.42\",\n        \"webapp@1.1.7-githubble.42\",\n        \"logging@1.0.6-githubble.42\",\n        \"tracker@1.0.5-githubble.42\",\n        \"deps@1.0.7-githubble.42\",\n        \"session@1.0.6-githubble.42\",\n        \"ddp@1.0.15-githubble.42\",\n        \"livedata@1.0.13-githubble.42\",\n        \"mongo@1.0.12-githubble.42\",\n        \"blaze@2.0.5-githubble.42\",\n        \"ui@1.0.6-githubble.42\",\n        \"spacebars@1.0.5-githubble.42\",\n        \"templating@1.0.12-githubble.42\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.3-githubble.42\",\n        \"jquery@1.11.3-githubble.42_1\",\n        \"random@1.0.3-githubble.42\",\n        \"ejson@1.0.6-githubble.42\",\n        \"launch-screen@1.0.1-githubble.42\",\n        \"fastclick@1.0.3-githubble.42\",\n        \"mobile-status-bar@1.0.3-githubble.42\"\n      ],\n      \"meteor-platform 1.2.2-githubble.43\": [\n        \"meteor@1.1.5-githubble.43\",\n        \"reload@1.1.3-githubble.43\",\n        \"autoupdate@1.1.6-githubble.43\",\n        \"webapp@1.1.7-githubble.43\",\n        \"logging@1.0.6-githubble.43\",\n        \"tracker@1.0.5-githubble.43\",\n        \"deps@1.0.7-githubble.43\",\n        \"session@1.0.6-githubble.43\",\n        \"ddp@1.0.15-githubble.43\",\n        \"livedata@1.0.13-githubble.43\",\n        \"mongo@1.0.12-githubble.43\",\n        \"blaze@2.0.5-githubble.43\",\n        \"ui@1.0.6-githubble.43\",\n        \"spacebars@1.0.5-githubble.43\",\n        \"templating@1.0.12-githubble.43\",\n        \"check@1.0.4-githubble.43\",\n        \"underscore@1.0.3-githubble.43\",\n        \"jquery@1.11.3-githubble.43_1\",\n        \"random@1.0.3-githubble.43\",\n        \"ejson@1.0.6-githubble.43\",\n        \"launch-screen@1.0.1-githubble.43\",\n        \"fastclick@1.0.3-githubble.43\",\n        \"mobile-status-bar@1.0.3-githubble.43\"\n      ],\n      \"meteor-platform 1.2.2-rc.0\": [\n        \"meteor@1.1.5-rc.0\",\n        \"reload@1.1.3-rc.0\",\n        \"autoupdate@1.2.0-rc.0\",\n        \"webapp@1.2.0-rc.0\",\n        \"logging@1.0.7-rc.0\",\n        \"tracker@1.0.6-rc.0\",\n        \"deps@1.0.7-rc.0\",\n        \"session@1.1.0-rc.0\",\n        \"ddp@1.1.0-rc.0\",\n        \"livedata@1.0.13-rc.0\",\n        \"mongo@1.1.0-rc.0\",\n        \"blaze@2.1.0-rc.0\",\n        \"ui@1.0.6-rc.0\",\n        \"spacebars@1.0.6-rc.0\",\n        \"templating@1.1.0-rc.0\",\n        \"check@1.0.5-rc.0\",\n        \"underscore@1.0.3-rc.0\",\n        \"jquery@1.11.3-rc.0_2\",\n        \"random@1.0.3-rc.0\",\n        \"ejson@1.0.6-rc.0\",\n        \"launch-screen@1.0.2-rc.0\",\n        \"fastclick@1.0.3-rc.0\",\n        \"mobile-status-bar@1.0.3-rc.0\"\n      ],\n      \"meteor-platform 1.2.2-winr.0\": [\n        \"meteor@1.1.5-winr.0\",\n        \"reload@1.1.3-winr.0\",\n        \"autoupdate@1.1.5-winr.0\",\n        \"webapp@1.1.6-winr.0\",\n        \"logging@1.0.7-winr.0\",\n        \"tracker@1.0.5-winr.0\",\n        \"deps@1.0.7-winr.0\",\n        \"session@1.0.6-winr.0\",\n        \"ddp@1.0.14-winr.0\",\n        \"livedata@1.0.13-winr.0\",\n        \"mongo@1.0.11-winr.0\",\n        \"blaze@2.0.5-winr.0\",\n        \"ui@1.0.6-winr.0\",\n        \"spacebars@1.0.5-winr.0\",\n        \"templating@1.0.11-winr.0\",\n        \"check@1.0.4-winr.0\",\n        \"underscore@1.0.3-winr.0\",\n        \"jquery@1.0.3-winr.0\",\n        \"random@1.0.3-winr.0\",\n        \"ejson@1.0.6-winr.0\",\n        \"launch-screen@1.0.2-winr.0\",\n        \"fastclick@1.0.3-winr.0\",\n        \"mobile-status-bar@1.0.3-winr.0\"\n      ],\n      \"meteor-platform 1.2.2-winr.1\": [\n        \"meteor@1.1.5-winr.1\",\n        \"reload@1.1.3-winr.1\",\n        \"autoupdate@1.1.5-winr.1\",\n        \"webapp@1.1.6-winr.1\",\n        \"logging@1.0.7-winr.1\",\n        \"tracker@1.0.5-winr.1\",\n        \"deps@1.0.7-winr.1\",\n        \"session@1.0.6-winr.1\",\n        \"ddp@1.0.14-winr.1\",\n        \"livedata@1.0.13-winr.1\",\n        \"mongo@1.0.11-winr.1\",\n        \"blaze@2.0.5-winr.1\",\n        \"ui@1.0.6-winr.1\",\n        \"spacebars@1.0.5-winr.1\",\n        \"templating@1.0.11-winr.1\",\n        \"check@1.0.4-winr.1\",\n        \"underscore@1.0.3-winr.1\",\n        \"jquery@1.0.3-winr.1\",\n        \"random@1.0.3-winr.1\",\n        \"ejson@1.0.6-winr.1\",\n        \"launch-screen@1.0.2-winr.1\",\n        \"fastclick@1.0.3-winr.1\",\n        \"mobile-status-bar@1.0.3-winr.1\"\n      ],\n      \"meteor-platform 1.2.2-winr.3\": [\n        \"meteor@1.1.5-winr.6\",\n        \"reload@1.1.3-winr.3\",\n        \"autoupdate@1.1.6-winr.4\",\n        \"webapp@1.1.7-winr.6\",\n        \"logging@1.0.6-winr.3\",\n        \"tracker@1.0.5-winr.4\",\n        \"deps@1.0.7-winr.2\",\n        \"session@1.0.6-winr.3\",\n        \"ddp@1.0.15-winr.5\",\n        \"livedata@1.0.13-winr.2\",\n        \"mongo@1.0.12-winr.5\",\n        \"blaze@2.0.5-winr.4\",\n        \"ui@1.0.6-winr.2\",\n        \"spacebars@1.0.5-winr.5\",\n        \"templating@1.0.12-winr.6\",\n        \"check@1.0.4-win.0\",\n        \"underscore@1.0.3-winr.2\",\n        \"jquery@1.11.3-winr.2_1\",\n        \"random@1.0.3-winr.2\",\n        \"ejson@1.0.6-winr.2\",\n        \"launch-screen@1.0.1-winr.4\",\n        \"fastclick@1.0.3-winr.2\",\n        \"mobile-status-bar@1.0.3-winr.3\"\n      ]\n    }\n  },\n  \"anticipatedPrereleases\": {\n    \"accounts-base\": {\n      \"1.2.0-rc.0\": true\n    },\n    \"accounts-facebook\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"accounts-github\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"accounts-google\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"accounts-meetup\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"accounts-meteor-developer\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"accounts-oauth\": {\n      \"1.1.4-rc.0\": true\n    },\n    \"accounts-password\": {\n      \"1.1.0-rc.0\": true\n    },\n    \"accounts-twitter\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"accounts-ui-unstyled\": {\n      \"1.1.7-rc.0\": true\n    },\n    \"accounts-ui\": {\n      \"1.1.5-rc.0\": true\n    },\n    \"accounts-weibo\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"appcache\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"audit-argument-checks\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"autopublish\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"autoupdate\": {\n      \"1.2.0-rc.0\": true\n    },\n    \"base64\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"binary-heap\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"blaze-tools\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"blaze\": {\n      \"2.1.0-rc.0\": true\n    },\n    \"boilerplate-generator\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"browser-policy-common\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"browser-policy-content\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"browser-policy-framing\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"browser-policy\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"callback-hook\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"check\": {\n      \"1.0.5-rc.0\": true\n    },\n    \"code-prettify\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"coffeescript-test-helper\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"coffeescript\": {\n      \"1.0.6-rc.0\": true\n    },\n    \"constraint-solver\": {\n      \"1.0.19-rc.0\": true\n    },\n    \"ddp\": {\n      \"1.1.0-rc.0\": true\n    },\n    \"deps\": {\n      \"1.0.7-rc.0\": true\n    },\n    \"disable-oplog\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"ejson\": {\n      \"1.0.6-rc.0\": true\n    },\n    \"email\": {\n      \"1.0.6-rc.0\": true\n    },\n    \"facebook\": {\n      \"1.1.4-rc.0\": true\n    },\n    \"facts\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"fastclick\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"force-ssl\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"geojson-utils\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"github\": {\n      \"1.1.3-rc.0\": true\n    },\n    \"google\": {\n      \"1.1.5-rc.0\": true\n    },\n    \"handlebars\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"html-tools\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"htmljs\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"http\": {\n      \"1.1.0-rc.0\": true\n    },\n    \"id-map\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"insecure\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"jquery-waypoints\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"jquery\": {\n      \"1.11.3-rc.0_2\": true\n    },\n    \"js-analyze-tests\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"js-analyze\": {\n      \"1.0.5-rc.0\": true\n    },\n    \"json\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"jsparse\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"launch-screen\": {\n      \"1.0.2-rc.0\": true\n    },\n    \"less\": {\n      \"1.0.14-rc.0\": true\n    },\n    \"livedata\": {\n      \"1.0.13-rc.0\": true\n    },\n    \"localstorage\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"logging\": {\n      \"1.0.7-rc.0\": true\n    },\n    \"logic-solver\": {\n      \"1.0.0-rc.0\": true\n    },\n    \"markdown\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"meetup\": {\n      \"1.1.3-rc.0\": true\n    },\n    \"meteor-developer\": {\n      \"1.1.3-rc.0\": true\n    },\n    \"meteor-platform\": {\n      \"1.2.2-rc.0\": true\n    },\n    \"meteor\": {\n      \"1.1.5-rc.0\": true\n    },\n    \"meyerweb-reset\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"minifiers\": {\n      \"1.1.5-rc.0\": true\n    },\n    \"minimongo\": {\n      \"1.0.7-rc.0\": true\n    },\n    \"mobile-status-bar\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"mongo-livedata\": {\n      \"1.0.8-rc.0\": true\n    },\n    \"mongo\": {\n      \"1.1.0-rc.0\": true\n    },\n    \"oauth-encryption\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"oauth\": {\n      \"1.1.4-rc.0\": true\n    },\n    \"oauth1\": {\n      \"1.1.4-rc.0\": true\n    },\n    \"oauth2\": {\n      \"1.1.3-rc.0\": true\n    },\n    \"observe-sequence\": {\n      \"1.0.5-rc.0\": true\n    },\n    \"ordered-dict\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"package-stats-opt-out\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"package-version-parser\": {\n      \"3.0.3-rc.0\": true\n    },\n    \"preserve-inputs\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"random\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"reactive-dict\": {\n      \"1.1.0-rc.0\": true\n    },\n    \"reactive-var\": {\n      \"1.0.5-rc.0\": true\n    },\n    \"reload-safetybelt\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"reload\": {\n      \"1.1.3-rc.0\": true\n    },\n    \"retry\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"routepolicy\": {\n      \"1.0.5-rc.0\": true\n    },\n    \"service-configuration\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"session\": {\n      \"1.1.0-rc.0\": true\n    },\n    \"sha\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"showdown\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"spacebars-compiler\": {\n      \"1.0.5-rc.0\": true\n    },\n    \"spacebars-tests\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"spacebars\": {\n      \"1.0.6-rc.0\": true\n    },\n    \"spiderable\": {\n      \"1.0.7-rc.0\": true\n    },\n    \"srp\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"standard-app-packages\": {\n      \"1.0.5-rc.0\": true\n    },\n    \"startup\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"stylus\": {\n      \"1.0.7-rc.0\": true\n    },\n    \"templating\": {\n      \"1.1.1-rc.0\": true\n    },\n    \"test-helpers\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"test-in-browser\": {\n      \"1.0.7-rc.0\": true\n    },\n    \"test-in-console\": {\n      \"1.0.5-rc.0\": true\n    },\n    \"test-server-tests-in-console-once\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"tinytest\": {\n      \"1.0.5-rc.0\": true\n    },\n    \"tracker\": {\n      \"1.0.6-rc.0\": true\n    },\n    \"twitter\": {\n      \"1.1.4-rc.0\": true\n    },\n    \"ui\": {\n      \"1.0.6-rc.0\": true\n    },\n    \"underscore-tests\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"underscore\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"url\": {\n      \"1.0.4-rc.0\": true\n    },\n    \"webapp-hashing\": {\n      \"1.0.3-rc.0\": true\n    },\n    \"webapp\": {\n      \"1.2.0-rc.0\": true\n    },\n    \"weibo\": {\n      \"1.1.3-rc.0\": true\n    },\n    \"xmlbuilder\": {\n      \"2.4.6-rc.0\": true\n    }\n  },\n  \"previousSolution\": {}\n};\n"
  },
  {
    "path": "packages/constraint-solver/version-pricer-tests.js",
    "content": "var CS = ConstraintSolver;\nvar PV = PackageVersion;\n\n\nTinytest.add(\"constraint solver - version pricer\", function (test) {\n\n  var pricer = new CS.VersionPricer();\n\n  var testScanVersions = function (versions, mode, options, expected) {\n    if (options && _.isArray(options)) {\n      expected = options;\n      options = null;\n    }\n    var result, tuples;\n    // Accepts either a mode like CS.VersionPricer.MODE_UPDATE or\n    // an object that looks like `{ previous: version }`\n    if (_.isObject(mode) && mode.previous) {\n      result = pricer.priceVersionsWithPrevious(versions, mode.previous);\n      tuples = _.zip(versions, result[0], result[1], result[2], result[3],\n                     result[4]);\n    } else {\n      result = pricer.priceVersions(versions, mode, options);\n      tuples = _.zip(versions, result[0], result[1], result[2], result[3]);\n    }\n    test.equal(tuples.length, expected.length);\n    test.equal(_.pluck(tuples, 0), versions);\n    _.each(_.zip(tuples, expected), function (x) {\n      var tuple = x[0];\n      var expectedTuple = x[1];\n      if (typeof expectedTuple[0] !== 'string') {\n        test.equal(tuple.slice(1), expectedTuple);\n      } else {\n        test.equal(tuple, expectedTuple);\n      }\n    });\n  };\n\n  test.equal(pricer.partitionVersions([\"1.0.0\", \"2.5.0\", \"2.6.1\", \"3.0.0\"],\n                                      \"2.5.0\"),\n             { older: [\"1.0.0\"],\n               compatible: [\"2.5.0\", \"2.6.1\"],\n               higherMajor: [\"3.0.0\"] });\n\n  test.equal(pricer.priceVersions([\"1.0.0\", \"1.0.1\", \"2.0.0\"],\n                                  CS.VersionPricer.MODE_UPDATE),\n             [[1, 1, 0], [0, 0, 0], [1, 0, 0], [0, 0, 0]]);\n\n  testScanVersions([\"1.0.0\", \"2.0.0\"], CS.VersionPricer.MODE_UPDATE,\n                   [[\"1.0.0\",1,0,0,0], // major version behind\n                    [\"2.0.0\",0,0,0,0]]); // latest version\n\n  testScanVersions([\"0.0.2\", \"0.5.0\", \"7.1.2\"], CS.VersionPricer.MODE_UPDATE,\n                   [[\"0.0.2\",1,1,0,0], // major and a minor version behind\n                    [\"0.5.0\",1,0,0,0], // major version behind\n                    [\"7.1.2\",0,0,0,0]]); // latest version\n\n  testScanVersions([\"0.0.2\", \"0.5.0\", \"7.1.2\"], CS.VersionPricer.MODE_GRAVITY,\n                   [[\"0.0.2\",0,0,0,0], // oldest\n                    [\"0.5.0\",0,1,0,0], // a minor version newer\n                    [\"7.1.2\",1,0,0,0]]); // a major version newer\n\n  testScanVersions([\"0.0.1-pre.0\", \"0.0.1-pre.1\", \"0.0.1-pre.2\"],\n                   CS.VersionPricer.MODE_UPDATE,\n                   [[0,0,0,2], [0,0,0,1], [0,0,0,0]]);\n\n  testScanVersions([\"0.0.1-pre.0\", \"0.0.1-pre.1\", \"0.0.1-pre.2\"],\n                   CS.VersionPricer.MODE_UPDATE, {versionAfter:\"3.4.5-pre.7\"},\n                   [[1,0,0,2], [1,0,0,1], [1,0,0,0]]);\n\n  testScanVersions([\"1.0.0\", \"1.0.1\", \"1.0.2\", \"1.0.3\",\n                    \"1.1.0\", \"1.1.1\",\n                    \"1.2.0-pre.0\", \"1.2.0\", \"1.2.1\", \"1.2.2-pre.0\", \"1.2.2\",\n                    \"2.0.0\", \"2.0.1\", \"2.0.2\",\n                    \"2.1.0\",\n                    \"2.5.0\",\n                    \"2.5.1\",\n                    \"3.0.0\",\n                    \"4.0.0-pre.0\", \"4.0.0\", \"4.0.0_1\"],\n                   CS.VersionPricer.MODE_UPDATE,\n                   [[\"1.0.0\", 3, 2, 3, 0],\n                    [\"1.0.1\", 3, 2, 2, 0],\n                    [\"1.0.2\", 3, 2, 1, 0],\n                    [\"1.0.3\", 3, 2, 0, 0],\n                    [\"1.1.0\", 3, 1, 1, 0],\n                    [\"1.1.1\", 3, 1, 0, 0],\n                    [\"1.2.0-pre.0\", 3, 0, 2, 1],\n                    [\"1.2.0\", 3, 0, 2, 0],\n                    [\"1.2.1\", 3, 0, 1, 0],\n                    [\"1.2.2-pre.0\", 3, 0, 0, 1],\n                    [\"1.2.2\", 3, 0, 0, 0],\n                    [\"2.0.0\", 2, 2, 2, 0],\n                    [\"2.0.1\", 2, 2, 1, 0],\n                    [\"2.0.2\", 2, 2, 0, 0],\n                    [\"2.1.0\", 2, 1, 0, 0],\n                    [\"2.5.0\", 2, 0, 1, 0],\n                    [\"2.5.1\", 2, 0, 0, 0],\n                    [\"3.0.0\", 1, 0, 0, 0],\n                    [\"4.0.0-pre.0\", 0, 0, 0, 2],\n                    [\"4.0.0\", 0, 0, 0, 1],\n                    [\"4.0.0_1\", 0, 0, 0, 0]]);\n\n  testScanVersions([\"1.0.0\", \"1.0.1\", \"1.0.2\", \"1.0.3\",\n                    \"1.1.0\", \"1.1.1\",\n                    \"1.2.0-pre.0\", \"1.2.0\", \"1.2.1\", \"1.2.2-pre.0\", \"1.2.2\",\n                    \"2.0.0\", \"2.0.1\", \"2.0.2\",\n                    \"2.1.0\",\n                    \"2.5.0\",\n                    \"2.5.1\",\n                    \"3.0.0\",\n                    \"4.0.0-pre.0\", \"4.0.0\", \"4.0.0_1\"],\n                   CS.VersionPricer.MODE_GRAVITY,\n                   [[\"1.0.0\", 0, 0, 0, 0],\n                    [\"1.0.1\", 0, 0, 1, 0],\n                    [\"1.0.2\", 0, 0, 2, 0],\n                    [\"1.0.3\", 0, 0, 3, 0],\n                    [\"1.1.0\", 0, 1, 0, 0],\n                    [\"1.1.1\", 0, 1, 1, 0],\n                    [\"1.2.0-pre.0\", 0, 2, 0, 0],\n                    [\"1.2.0\", 0, 2, 0, 1],\n                    [\"1.2.1\", 0, 2, 1, 0],\n                    [\"1.2.2-pre.0\", 0, 2, 2, 0],\n                    [\"1.2.2\", 0, 2, 2, 1],\n                    [\"2.0.0\", 1, 0, 0, 0],\n                    [\"2.0.1\", 1, 0, 1, 0],\n                    [\"2.0.2\", 1, 0, 2, 0],\n                    [\"2.1.0\", 1, 1, 0, 0],\n                    [\"2.5.0\", 1, 2, 0, 0],\n                    [\"2.5.1\", 1, 2, 1, 0],\n                    [\"3.0.0\", 2, 0, 0, 0],\n                    [\"4.0.0-pre.0\", 3, 0, 0, 0],\n                    [\"4.0.0\", 3, 0, 0, 1],\n                    [\"4.0.0_1\", 3, 0, 0, 2]]);\n\n  testScanVersions([\"1.0.0\", \"1.0.1\", \"1.0.2\", \"1.0.3\",\n                    \"1.1.0\", \"1.1.1\",\n                    \"1.2.0-pre.0\", \"1.2.0\", \"1.2.1\", \"1.2.2-pre.0\", \"1.2.2\",\n                    \"2.0.0\", \"2.0.1\", \"2.0.2\",\n                    \"2.1.0\",\n                    \"2.5.0\",\n                    \"2.5.1\",\n                    \"3.0.0\",\n                    \"4.0.0-pre.0\", \"4.0.0\", \"4.0.0_1\"],\n                   CS.VersionPricer.MODE_GRAVITY_WITH_PATCHES,\n                   [[\"1.0.0\", 0, 0, 3, 0],\n                    [\"1.0.1\", 0, 0, 2, 0],\n                    [\"1.0.2\", 0, 0, 1, 0],\n                    [\"1.0.3\", 0, 0, 0, 0],\n                    [\"1.1.0\", 0, 1, 1, 0],\n                    [\"1.1.1\", 0, 1, 0, 0],\n                    [\"1.2.0-pre.0\", 0, 2, 2, 1],\n                    [\"1.2.0\", 0, 2, 2, 0],\n                    [\"1.2.1\", 0, 2, 1, 0],\n                    [\"1.2.2-pre.0\", 0, 2, 0, 1],\n                    [\"1.2.2\", 0, 2, 0, 0],\n                    [\"2.0.0\", 1, 0, 2, 0],\n                    [\"2.0.1\", 1, 0, 1, 0],\n                    [\"2.0.2\", 1, 0, 0, 0],\n                    [\"2.1.0\", 1, 1, 0, 0],\n                    [\"2.5.0\", 1, 2, 1, 0],\n                    [\"2.5.1\", 1, 2, 0, 0],\n                    [\"3.0.0\", 2, 0, 0, 0],\n                    [\"4.0.0-pre.0\", 3, 0, 0, 2],\n                    [\"4.0.0\", 3, 0, 0, 1],\n                    [\"4.0.0_1\", 3, 0, 0, 0]]);\n\n\n  testScanVersions([\"1.0.0\", \"1.0.1\", \"1.0.2\", \"1.0.3\",\n                    \"1.1.0\", \"1.1.1\",\n                    \"1.2.0-pre.0\", \"1.2.0\", \"1.2.1\", \"1.2.2-pre.0\", \"1.2.2\",\n                    \"2.0.0\", \"2.0.1\", \"2.0.2\",\n                    \"2.1.0\",\n                    \"2.5.0\",\n                    \"2.5.1\",\n                    \"3.0.0\",\n                    \"4.0.0-pre.0\", \"4.0.0\", \"4.0.0_1\"],\n                   { previous: \"1.2.0\" },\n                   // This part is like UPDATE, without the major cost\n                   [[\"1.0.0\", 1, 0, 2, 3, 0],\n                    [\"1.0.1\", 1, 0, 2, 2, 0],\n                    [\"1.0.2\", 1, 0, 2, 1, 0],\n                    [\"1.0.3\", 1, 0, 2, 0, 0],\n                    [\"1.1.0\", 1, 0, 1, 1, 0],\n                    [\"1.1.1\", 1, 0, 1, 0, 0],\n                    // This part is like UPDATE, without the minor cost\n                    [\"1.2.0-pre.0\", 1, 0, 0, 0, 1],\n                    // This part is like GRAVITY, without the major/minor cost\n                    [\"1.2.0\", 0, 0, 0, 0, 0],\n                    [\"1.2.1\", 0, 0, 0, 1, 0],\n                    [\"1.2.2-pre.0\", 0, 0, 0, 2, 0],\n                    [\"1.2.2\", 0, 0, 0, 2, 1],\n                    // This part is like GRAVITY_WITH_PATCHES\n                    [\"2.0.0\", 1, 1, 0, 2, 0],\n                    [\"2.0.1\", 1, 1, 0, 1, 0],\n                    [\"2.0.2\", 1, 1, 0, 0, 0],\n                    [\"2.1.0\", 1, 1, 1, 0, 0],\n                    [\"2.5.0\", 1, 1, 2, 1, 0],\n                    [\"2.5.1\", 1, 1, 2, 0, 0],\n                    [\"3.0.0\", 1, 2, 0, 0, 0],\n                    [\"4.0.0-pre.0\", 1, 3, 0, 0, 2],\n                    [\"4.0.0\", 1, 3, 0, 0, 1],\n                    [\"4.0.0_1\", 1, 3, 0, 0, 0]]);\n\n});\n"
  },
  {
    "path": "packages/constraint-solver/version-pricer.js",
    "content": "var CS = ConstraintSolver;\nvar PV = PackageVersion;\n\nCS.VersionPricer = function () {\n  var self = this;\n\n  // self.getVersionInfo(versionString) returns an object\n  // that contains at least { major, minor, patch }.\n  //\n  // The VersionPricer instance stores a memoization table for\n  // efficiency.\n  self.getVersionInfo = _.memoize(PV.parse);\n};\n\nCS.VersionPricer.MODE_UPDATE = 1;\nCS.VersionPricer.MODE_GRAVITY = 2;\nCS.VersionPricer.MODE_GRAVITY_WITH_PATCHES = 3;\n\n// priceVersions(versions, mode, options) calculates small integer\n// costs for each version, based on whether each part of the version\n// is low or high relative to the other versions with the same higher\n// parts.\n//\n// For example, if \"1.2.0\" and \"1.2.1\" are the only 1.2.x versions\n// in the versions array, they will be assigned PATCH costs of\n// 1 and 0 in UPDATE mode (penalizing the older version), or 0 and 1\n// in GRAVITY mode (penalizing the newer version).  When optimizing,\n// the solver will prioritizing minimizing MAJOR costs, then MINOR\n// costs, then PATCH costs, and then \"REST\" costs (which penalizing\n// being old or new within versions that have the same major, minor,\n// AND patch).\n//\n// - `versions` - Array of version strings in sorted order\n// - `mode` - A MODE constant\n// - `options`:\n//   - `versionAfter` - if provided, the next newer version not in the\n//     array but that would come next.\n//   - `versionBefore` - if provided, the next older version not in the\n//     the array but that would come before it.\n//\n// Returns: an array of 4 arrays, each of length versions.length,\n// containing the MAJOR, MINOR, PATCH, and REST costs corresponding\n// to the versions.\n//\n// MODE_UPDATE penalizes versions for being old (because we want\n// them to be new), while the MODE_GRAVITY penalizes versions for\n// being new (because we are trying to apply \"version gravity\" and\n// prefer older versions).  MODE_GRAVITY_WITH_PATCHES applies gravity\n// to the major and minor parts of the version, but prefers updates\n// to the patch and rest of the version.\n//\n// Use `versionAfter` when scanning a partial array of versions\n// if you want the newest version in the array to have a non-zero\n// weight in MODE_UPDATE.  For example, the versions\n// `[\"1.0.0\", \"1.0.1\"]` will be considered to have an out-of-date\n// version if versionAfter is `\"2.0.0\"`.  The costs returned\n// won't be the same as if the whole array was scanned at once,\n// but this option is useful in order to apply MODE_UPDATE to some\n// versions and MODE_GRAVITY to others, for example.\n//\n// `versionBefore` is used in an analogous way with the GRAVITY modes.\n//\n// The easiest way to implement this function would be to partition\n// `versions` into subarrays of versions with the same major part,\n// and then partition those arrays based on the minor parts, and\n// so on.  However, that's a lot of array allocations -- O(N) or\n// thereabouts.  So instead we use a linear scan backwards through\n// the versions array.\nCS.VersionPricer.prototype.priceVersions = function (versions, mode, options) {\n  var self = this;\n\n  var getMajorMinorPatch = function (v) {\n    var vInfo = self.getVersionInfo(v);\n    return [vInfo.major, vInfo.minor, vInfo.patch];\n  };\n\n  var MAJOR = 0, MINOR = 1, PATCH = 2, REST = 3;\n  var gravity; // array of MAJOR, MINOR, PATCH, REST\n\n  switch (mode) {\n  case CS.VersionPricer.MODE_UPDATE:\n    gravity = [false, false, false, false];\n    break;\n  case CS.VersionPricer.MODE_GRAVITY:\n    gravity = [true, true, true, true];\n    break;\n  case CS.VersionPricer.MODE_GRAVITY_WITH_PATCHES:\n    gravity = [true, true, false, false];\n    break;\n  default:\n    throw new Error(\"Bad mode: \" + mode);\n  }\n\n  var lastMajorMinorPatch = null;\n  if (options && options.versionAfter) {\n    lastMajorMinorPatch = getMajorMinorPatch(options.versionAfter);\n  }\n  // `costs` contains arrays of whole numbers, each of which will\n  // have a length of versions.length.  This is what we will return.\n  var costs = [[], [], [], []]; // MAJOR, MINOR, PATCH, REST\n  // How many in a row of the same MAJOR, MINOR, or PATCH have we seen?\n  var countOfSame = [0, 0, 0];\n\n  // Track how old each part of versions[i] is, in terms of how many\n  // greater values there are for that part among versions with the\n  // same higher parts.  For example, oldness[REST] counts the number\n  // of versions after versions[i] with the same MAJOR, MINOR, and REST.\n  // oldness[PATCH] counts the number of *different* higher values for\n  // for PATCH among later versions with the same MAJOR and MINOR parts.\n  var oldness = [0, 0, 0, 0];\n\n  // Walk the array backwards\n  for (var i = versions.length - 1; i >= 0; i--) {\n    var v = versions[i];\n    var majorMinorPatch = getMajorMinorPatch(v);\n    if (lastMajorMinorPatch) {\n      for (var k = MAJOR; k <= REST; k++) {\n        if (k === REST || majorMinorPatch[k] !== lastMajorMinorPatch[k]) {\n          // For the highest part that changed, bumped the oldness\n          // and clear the lower oldnesses.\n          oldness[k]++;\n          for (var m = k+1; m <= REST; m++) {\n            if (gravity[m]) {\n              // if we should actually be counting \"newness\" instead of\n              // oldness, flip the count.  Instead of [0, 1, 1, 2, 3],\n              // for example, make it [3, 2, 2, 1, 0].  This is the place\n              // to do it, because we have just \"closed out\" a run.\n              flipLastN(costs[m], countOfSame[m-1], oldness[m]);\n            }\n            countOfSame[m-1] = 0;\n            oldness[m] = 0;\n          }\n          break;\n        }\n      }\n    }\n    for (var k = MAJOR; k <= REST; k++) {\n      costs[k].push(oldness[k]);\n      if (k !== REST) {\n        countOfSame[k]++;\n      }\n    }\n    lastMajorMinorPatch = majorMinorPatch;\n  }\n  if (options && options.versionBefore && versions.length) {\n    // bump the appropriate value of oldness, as if we ran the loop\n    // one more time\n    majorMinorPatch = getMajorMinorPatch(options.versionBefore);\n    for (var k = MAJOR; k <= REST; k++) {\n      if (k === REST || majorMinorPatch[k] !== lastMajorMinorPatch[k]) {\n        oldness[k]++;\n        break;\n      }\n    }\n  }\n\n  // Flip the MAJOR costs if we have MAJOR gravity -- subtracting them\n  // all from oldness[MAJOR] -- and likewise for other parts if countOfSame\n  // is > 0 for the next highest part (meaning we didn't get a chance to\n  // flip some of the costs because the loop ended).\n  for (var k = MAJOR; k <= REST; k++) {\n    if (gravity[k]) {\n      flipLastN(costs[k], k === MAJOR ? costs[k].length : countOfSame[k-1],\n                oldness[k]);\n    }\n  }\n\n  // We pushed costs onto the arrays in reverse order.  Reverse the cost\n  // arrays in place before returning them.\n  return [costs[MAJOR].reverse(),\n          costs[MINOR].reverse(),\n          costs[PATCH].reverse(),\n          costs[REST].reverse()];\n};\n\n// \"Flip\" the last N elements of array in place by subtracting each\n// one from `max`.  For example, if `a` is `[3,0,1,1,2]`, then calling\n// `flipLastN(a, 4, 2)` mutates `a` into `[3,2,1,1,0]`.\nvar flipLastN = function (array, N, max) {\n  var len = array.length;\n  for (var i = 0; i < N; i++) {\n    var j = len - 1 - i;\n    array[j] = max - array[j];\n  }\n};\n\n// Partition a sorted array of versions into three arrays, containing\n// the versions that are `older` than the `target` version,\n// `compatible` with it, or have a `higherMajor` version.\n//\n// For example, `[\"1.0.0\", \"2.5.0\", \"2.6.1\", \"3.0.0\"]` with a target of\n// `\"2.5.0\"` returns `{ older: [\"1.0.0\"], compatible: [\"2.5.0\", \"2.6.1\"],\n// higherMajor: [\"3.0.0\"] }`.\nCS.VersionPricer.prototype.partitionVersions = function (versions, target) {\n  var self = this;\n  var firstGteIndex = versions.length;\n  var higherMajorIndex = versions.length;\n  var targetVInfo = self.getVersionInfo(target);\n  for (var i = 0; i < versions.length; i++) {\n    var v = versions[i];\n    var vInfo = self.getVersionInfo(v);\n    if (firstGteIndex === versions.length &&\n        ! PV.lessThan(vInfo, targetVInfo)) {\n      firstGteIndex = i;\n    }\n    if (vInfo.major > targetVInfo.major) {\n      higherMajorIndex = i;\n      break;\n    }\n  }\n  return { older: versions.slice(0, firstGteIndex),\n           compatible: versions.slice(firstGteIndex, higherMajorIndex),\n           higherMajor: versions.slice(higherMajorIndex) };\n};\n\n// Use a combination of calls to priceVersions with different modes in order\n// to generate costs for versions relative to a \"previous solution\" version\n// (called the \"target\" here).\nCS.VersionPricer.prototype.priceVersionsWithPrevious = function (\n  versions, target, takePatches) {\n\n  var self = this;\n  var parts = self.partitionVersions(versions, target);\n\n  var result1 = self.priceVersions(parts.older, CS.VersionPricer.MODE_UPDATE,\n                                   { versionAfter: target });\n  // Usually, it's better to remain as close as possible to the target\n  // version, but prefer higher patch versions (and wrapNums, etc.) if\n  // we were passed `takePatches`.\n  var result2 = self.priceVersions(parts.compatible,\n                                   (takePatches ?\n                                    CS.VersionPricer.MODE_GRAVITY_WITH_PATCHES :\n                                    CS.VersionPricer.MODE_GRAVITY));\n  // If we're already bumping the major version, might as well take patches.\n  var result3 = self.priceVersions(parts.higherMajor,\n                                   CS.VersionPricer.MODE_GRAVITY_WITH_PATCHES,\n                                   // not actually the version right before, but\n                                   // gives the `major` cost the bump it needs\n                                   { versionBefore: target });\n\n  // Generate a fifth array, incompat, which has a 1 for each incompatible\n  // version and a 0 for each compatible version.\n  var incompat = [];\n  var i;\n  for (i = 0; i < parts.older.length; i++) {\n    incompat.push(1);\n  }\n  for (i = 0; i < parts.compatible.length; i++) {\n    incompat.push(0);\n  }\n  for (i = 0; i < parts.higherMajor.length; i++) {\n    incompat.push(1);\n  }\n\n  return [\n    incompat,\n    result1[0].concat(result2[0], result3[0]),\n    result1[1].concat(result2[1], result3[1]),\n    result1[2].concat(result2[2], result3[2]),\n    result1[3].concat(result2[3], result3[3])\n  ];\n};\n"
  },
  {
    "path": "packages/crosswalk/package.js",
    "content": "Package.describe({\n  summary: \"Makes your Cordova application use the Crosswalk WebView \\\ninstead of the System WebView on Android\",\n  version: '1.6.2',\n  documentation: null\n});\n\nCordova.depends({\n  'cordova-plugin-crosswalk-webview': '1.6.0'\n});\n"
  },
  {
    "path": "packages/ddp/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/ddp/DDP.md",
    "content": "# DDP Specification\n\nDDP is a protocol between a client and a server that supports two operations:\n\n * Remote procedure calls by the client to the server.\n * The client subscribing to a set of documents, and the server keeping the\n   client informed about the contents of those documents as they change over\n   time.\n\nThis document specifies the version \"1\" of DDP. It's a rough description of\nthe protocol and not intended to be entirely definitive.\n\n## General Message Structure:\n\nDDP may use either SockJS or WebSockets as a lower-level message transport. (For\nnow, you connect via SockJS at the URL `/sockjs` and via WebSockets at the URL\n`/websocket`. The latter is likely to change to be the main app URL specifying a\nWebSocket subprotocol.)\n\nDDP messages are JSON objects, with some fields specified to be EJSON.  Each one\nhas a `msg` field that specifies the message type, as well as other fields\ndepending on message type.\n\nThe client and the server must ignore any unknown fields in messages.  Future\nminor revisions of DDP might add extra fields without changing the DDP version;\nthe client must therefore silently ignore unknown fields.  However, the client\nmust not send extra fields other than those documented in the DDP protocol, in\ncase these extra fields have meaning to future servers.  On the server, all\nfield changes must be optional/ignorable for compatability with older clients;\notherwise a new protocol version would be required.\n\n## Establishing a DDP Connection:\n\n### Messages:\n\n * `connect` (client -> server)\n   - `session`: string (if trying to reconnect to an existing DDP session)\n   - `version`: string (the proposed protocol version)\n   - `support`: array of strings (protocol versions supported by the client,\n      in order of preference)\n * `connected` (server->client)\n   - `session`: string (an identifier for the DDP session)\n * `failed` (server->client)\n   - `version`: string (a suggested protocol version to connect with)\n\n### Procedure:\n\nThe server may send an initial message which is a JSON object lacking\na `msg` key. If so, the client should ignore it. The client does not\nhave to wait for this message. (The message was once used to help\nimplement Meteor's hot code reload feature; it is now only included to\nforce old clients to update).\n\n * The client sends a `connect` message.\n * If the server is willing to speak the `version` of the protocol specified in\n   the `connect` message, it sends back a `connected` message.\n * Otherwise the server sends back a `failed` message with a version of DDP it\n   would rather speak, informed by the `connect` message's `support` field, and\n   closes the underlying transport.\n * The client is then free to attempt to connect again speaking a different\n   version of DDP. It can do that by sending another `connect` message on a new\n   connection. The client may optimistically send more messages after the\n   `connect` message, assuming that the server will support the proposed\n   protocol version. If the server does not support that version, it must ignore\n   those additional messages.\n\nThe versions in the `support` field of the client's `connect` message\nare ordered according to the client's preference, most preferred\nfirst. If, according to this ordering, the `version` proposed by the\nclient is not the best version that the server supports, the server\nmust force the client to switch to the better version by sending a\n`failed` message.\n\nWhen a client is connecting to a server for the first time it will\ntypically set `version` equal to its most preferred version. If\ndesired, the client can then remember the version that is ultimately\nnegotiated with the server and begin with that version in future\nconnections. The client can rely on the server sending a `failed`\nmessage if a better version is possible as a result of the client or\nthe server having been upgraded.\n\n## Heartbeats\n\n### Messages:\n\n * `ping`\n   - `id`: optional string (identifier used to correlate with response)\n * `pong`\n   - `id`: optional string (same as received in the `ping` message)\n\n### Procedure:\n\nAt any time after the connection is established either side may send a `ping`\nmessage. The sender may chose to include an `id` field in the `ping`\nmessage. When the other side receives a `ping` it must immediately respond with\na `pong` message. If the received `ping` message includes an `id` field, the\n`pong` message must include the same `id` field.\n\n## Managing Data:\n\n### Messages:\n\n * `sub` (client -> server):\n   - `id`: string (an arbitrary client-determined identifier for this subscription)\n   - `name`: string (the name of the subscription)\n   - `params`: optional array of EJSON items (parameters to the subscription)\n * `unsub` (client -> server):\n   - `id`: string (the id passed to 'sub')\n * `nosub` (server -> client):\n   - `id`: string (the id passed to 'sub')\n   - `error`: optional Error (an error raised by the subscription as it\n    concludes, or sub-not-found)\n * `added` (server -> client):\n   - `collection`: string (collection name)\n   - `id`: string (document ID)\n   - `fields`: optional object with EJSON values\n * `changed` (server -> client):\n   - `collection`: string (collection name)\n   - `id`: string (document ID)\n   - `fields`: optional object with EJSON values\n   - `cleared`: optional array of strings (field names to delete)\n * `removed` (server -> client):\n   - `collection`: string (collection name)\n   - `id`: string (document ID)\n * `ready` (server -> client):\n   - `subs`: array of strings (ids passed to 'sub' which have sent their\n     initial batch of data)\n * `addedBefore` (server -> client):\n   - `collection`: string (collection name)\n   - `id`: string (document ID)\n   - `fields`: optional object with EJSON values\n   - `before`: string or null (the document ID to add the document before,\n     or null to add at the end)\n * `movedBefore` (server -> client):\n   - `collection`: string\n   - `id`: string (the document ID)\n   - `before`: string or null (the document ID to move the document before, or\n     null to move to the end)\n\n### Procedure:\n\n * The client specifies sets of information it is interested in by sending\n   `sub` messages to the server.\n\n * At any time, but generally informed by the `sub` messages, the server can\n   send data messages to the client.  Data consist of `added`, `changed`, and\n   `removed` messages.  These messages model a local set of data the client\n   should keep track of.\n\n   - An `added` message indicates a document was added to the local set. The ID\n     of the document is specified in the `id` field, and the fields of the\n     document are specified in the `fields` field.  Minimongo interperets the\n     string id field in a special way that transforms it to the _id field of\n     Mongo documents.\n\n   - A `changed` message indicates a document in the local set has new values\n     for some fields or has had some fields removed. The `id` field is the ID of\n     the document that has changed.  The `fields` object, if present, indicates\n     fields in the document that should be replaced with new values.  The\n     `cleared` field contains an array of fields that are no longer in the\n     document.\n\n   - A `removed` message indicates a document was removed from the local\n     set. The `id` field is the ID of the document.\n\n * A collection is either ordered, or not. If a collection is ordered,\n   the `added` message is replaced by `addedBefore`, which\n   additionally contains the ID of the document after the one being\n   added in the `before` field.  If the document is being added at the\n   end, `before` is set to null. For a given collection, the server\n   should only send `added` messages or `addedBefore` messages, not a\n   mixture of both, and should only send `movedBefore` messages for a\n   collection with `addedBefore` messages.\n\n   NOTE: The ordered collection DDP messages are not currently used by Meteor.\n   They will likely be used by Meteor in the future.\n\n * The client maintains one set of data per collection.  Each subscription does\n   not get its own datastore, but rather overlapping subscriptions cause the\n   server to send the union of facts about the one collection's data.  For\n   example, if subscription A says document `x` has fields `{foo: 1, bar: 2}`\n   and subscription B says document `x` has fields `{foo: 1, baz:3}`, then the\n   client will be informed that document `x` has fields `{foo: 1, bar: 2, baz:\n   3}`.  If field values from different subscriptions conflict with each other,\n   the server should send one of the possible field values.\n\n * When one or more subscriptions have finished sending their initial batch of\n   data, the server will send a `ready` message with their IDs.\n\n## Remote Procedure Calls:\n\n### Messages:\n\n * `method` (client -> server):\n   - `method`: string (method name)\n   - `params`: optional array of EJSON items (parameters to the method)\n   - `id`: string (an arbitrary client-determined identifier for this method call)\n   - `randomSeed`: optional JSON value (an arbitrary client-determined seed\n     for pseudo-random generators)\n * `result` (server -> client):\n   - `id`: string (the id passed to 'method')\n   - `error`: optional Error (an error thrown by the method (or method-not-found)\n   - `result`: optional EJSON item (the return value of the method, if any)\n * `updated` (server -> client):\n   - `methods`: array of strings (ids passed to 'method', all of whose writes\n     have been reflected in data messages)\n\n### Procedure:\n\n * The client sends a `method` message to the server\n\n * The server responds with a `result` message to the client, carrying either\n   the result of the method call, or an appropriate error.\n\n * Method calls can affect data that the client is subscribed to.  Once the\n   server has finished sending the client all the relevant data messages based\n   on this procedure call, the server should send an `updated` message to the\n   client with this method's ID.\n\n * There is no particular required ordering between `result` and `updated`\n   messages for a method call.\n\n * The client may provide a randomSeed JSON value.  If provided, this value is\n   used to seed pseudo-random number generation.  By using the same seed with\n   the same algorithm, the same pseudo-random values can be generated on the\n   client and the server.  In particular, this is used for generating ids for\n   newly created documents.  If randomSeed is not provided, then values\n   generated on the server and the client will not be identical.\n\n * Currently randomSeed is expected to be a string, and the algorithm by which\n   values are produced from this is not yet documented.  It will likely be\n   formally specified in future when we are confident that the complete\n   requirements are known, or when a compatible implementation requires this\n   to be specified.\n\n## Errors:\n\nErrors appear in `result` and `nosub` messages in an optional error field. An\nerror is an Object with the following fields:\n\n * `error`: string (previously a number. See appendix 3)\n * `reason`: optional string\n * `details`: optional string\n\nSuch an Error is used to represent errors raised by the method or subscription,\nas well as an attempt to subscribe to an unknown subscription or call an unknown\nmethod.\n\nOther erroneous messages sent from the client to the server can result in\nreceiving a top-level `msg: 'error'` message in response. These conditions\ninclude:\n\n * sending messages which are not valid JSON objects\n * unknown `msg` type\n * other malformed client requests (not including required fields)\n * sending anything other than `connect` as the first message, or sending\n   `connect` as a non-initial message\n\nThe error message contains the following fields:\n\n * `reason`: string describing the error\n * `offendingMessage`: if the original message parsed properly, it is included\n   here\n\n## Appendix: EJSON\n\nEJSON is a way of embedding more than the built-in JSON types in JSON.  It\nsupports all types built into JSON as plain JSON, plus the following:\n\n**Dates:**\n\n    {\"$date\": MILLISECONDS_SINCE_EPOCH}\n\n**Binary data:**\n\n    {\"$binary\": BASE_64_STRING}\n\n(The base 64 string has `+` and `/` as characters 62 and 63, and has no maximum line length)\n\n**Escaped things** that might otherwise look like EJSON types:\n\n    {\"$escape\": THING}\n\nFor example, here is the JSON value `{$date: 10000}` stored in EJSON:\n\n    {\"$escape\": {\"$date\": 10000}}\n\nNote that escaping only causes keys to be literal for one level down; you can\nhave further EJSON inside.  For example, the following is the key `$date` mapped\nto a Date object:\n\n    {\"$escape\": {\"$date\": {\"$date\": 32491}}}\n\n**User-specified types:**\n\n    {\"$type\": TYPENAME, \"$value\": VALUE}\n\nImplementations of EJSON should try to preserve key order where they can.  Users\nof EJSON should not rely on key order, if possible.\n\n> MongoDB relies on key order.  When using EJSON with MongoDB, the\n> implementation of EJSON must preserve key order.\n\n\n## Appendix 2: randomSeed backward/forward compatibility\n\nrandomSeed was added into DDP pre2, but it does not break backward or forward\ncompatibility.\n\nIf the client stub and the server produce documents that are different in any\nway, Meteor will reconcile this difference. This may cause 'flicker' in the UI\nas the values change on the client to reflect what happened on the server, but\nthe final result will be correct: the server and the client will agree.\n\nConsistent id generation / randomSeed does not alter the syncing process, and\nthus will (at worst) be the same:\n\n* If neither the server nor the client support randomSeed, we will get the\nclassical/flicker behavior.\n\n* If the client supports randomSeed, but the server does not, the server will\nignore randomSeed, as it ignores any unknown properties in a DDP method call.\nDifferent ids will be generated, but this will be fixed by syncing.\n\n* If the server supports randomSeed, but the client does not, the server will\ngenerate unseeded random values (providing a randomSeed is optional); different\nids will be generated; and again this will be fixed by syncing.\n\n* If both client and server support randomSeed, but different ids are\ngenerated, either because the generation procedure is buggy, or the stub\nbehaves differently to the server, then syncing will fix this.\n\n* If both client and server support randomSeed, in the normal case the ids\ngenerated will be the same, and syncing will be a no-op.\n\n\n## Appendix 3: Error message `error` field can be a string or a number\n\nIn the `pre1` and `pre2` specifications for DDP, the `error` field on error\nmessages was documented as a number, and in practice often matched the closest\nHTTP error code.\n\nIt is typically better to be specific about the type of error being returned, so\nnew code should use strings like `'wrong-password'` instead of `401`. To support\nboth the new string error codes and the old number codes, a DDP client should\naccept a string or a number in this field. Many meteor packages, including some\ncore packages, still use the old numeric codes.\n\n\n## Version History\n\n`pre1` was the first version of DDP\n\n`pre2` added keep-alive (ping & pong messages), and randomSeed.\n\n`1` should be considered the first official version of DDP. The type of the\nerror code field has been clarified to reflect the behavior of existing clients\nand servers.\n"
  },
  {
    "path": "packages/ddp/README.md",
    "content": "# ddp\n\nDDP (Distributed Data Protocol) is the stateful websocket protocol\nthat Meteor uses to communicate between the client and the server. For\nmore information about DDP, see the [DDP project\npage](https://www.meteor.com/ddp) or the [DDP\nspecification](https://github.com/meteor/meteor/blob/devel/packages/ddp/DDP.md).\n\nThis package is used by nearly every Meteor application and provides a\nfull implementation of DDP in JavaScript. API documentation is on the\n[main Meteor documentation page](http://docs.meteor.com/), under\n\"Publish and subscribe\", \"Methods\", and \"Server connections\". Note in\nparticular that clients can use\n[`DDP.connect`](http://docs.meteor.com/#ddp_connect) to open a DDP\nconnection to any DDP service on the Internet.\n\n### Supported platforms\n\nCurrently the `ddp` package provides both the DDP client and the server in the same package. We plan to separate it out into separate `ddp-client` and `ddp-server` packages in the future. The client in `ddp` works with all supported Isobuild architectures, including browsers (`web.browser.*`), mobile devices (`web.cordova.*`), and node.js (`os.*`), using an appropriate transport for each. The server in `ddp` only works under node.js at present, due to the lack of a good way to run a websocket server in the browser. Maybe one day this will change with WebRTC.\n\n### Supported transports\n\n`ddp` supports the standard DDP transport, stringified EJSON over websockets. It also supports a second transport, EJSON over HTTP long polling. It will automatically fall back to this transport if websockets are not available. This is not as efficient as websockets, but it works in older browsers. It uses the [sockjs](https://github.com/sockjs) library for long polling.\n\nThe sockjs-based long polling transport is not part of the official DDP standard. This is because, although sockjs works well, there is not a formal written standard for its behavior. It uses many different websocket emulation strategies for the widest possible browser compatibility, and standardizing all of these strategies would take a great deal of effort. Plus, websockets are widely available, so the need for this alternative transport will go away in the not-too-distant future. For now, if you are writing your own DDP implementation and want to interoperate with `ddp` on old browsers that don't have websockets, just use sockjs directly.\n\nWhen using the sockjs transport, `ddp` has some special functionality to get around a limitation of long polling. Web browsers put a limit on the total number of HTTP connections that can be open to a particular domain at any one time, across all browser tabs. This is a potential problem for any app that uses long polling and that might be opened in multiple tabs. When too many tabs have been opened, the app can no longer connect to the server, since each of the tabs is holding open a long polling HTTP connection and the limit is hit. If this is an issue, `ddp` can be configured to use a randomly generated subdomain for each long polling connection. This requires an appropriate wildcard DNS record on the server and appropriate proxy configuration. Meteor wires all of this up automatically when deploying an app with `meteor deploy`.\n\n### Notable features\n\n**Database driver integration.** `ddp` works well with the Meteor Project's [full-stack database drivers](https://www.meteor.com/full-stack-db-drivers). For example, if you are using the `mongo` package, then when you create a Mongo collection with `MyCollection = new Mongo.Collection(\"mycollection\")` on the client, the Mongo driver will automatically register with `ddp` to receive incoming data for `mycollection` and use it to keep `MyCollection` up to date. In other words, it automatically wires up replication for all of your remote collections.\n\n**Automatic latency compensation.** `ddp` includes a full\nimplementation of fine-grained latency compensation, so users see\ntheir screen update instantly when they make changes, without having\nto wait for a server round trip. It will cooperate with any\nfull-stack DB drivers that are in use to snapshot and restore records\nas necessary.\n\n**Transparent reconnection.** If the DDP client loses its connection to the server, it will automatically reconnect, transparently to the application. Any subscriptions will be re-established and resynchronized without disturbing the application, and any outstanding method calls will be retried. However, this retrying could lead to duplicate method calls if the connection is lost after the server has received the method call, but before the client reads the result. This can be avoided just as it is with REST, by including a unique code as a parameter to the method. A future version of DDP will solve this on the protocol level (see Future Work).\n\n**Authentication.** `ddp`'s authentication hooks work great with [Meteor Accounts](https://www.meteor.com/accounts), a set of packages which provides a full suite of authentication functionality, from password-based accounts with email verification and password recovery, to OAuth login using services like Facebook and Twitter.\n\n**Input sanitization.** On the server, you can use the `check` function, provided by the [match](https://atmospherejs.com/meteor/match) package, to easily validate the types of arguments passed by the client. Using a simple pattern language, you can also `check` whether objects have the expected keps and array elements have the right type. In production code, add the [audit-argument-checks](https://atmospherejs.com/meteor/audit-argument-checks) package, and `ddp` will make sure that every value passed from the client is validated with `check`, and throw an exception if not. But be careful. The check only happens after the code has run, so while it will catch the vast majority of sanitization failures, it's not a perfect guarantee of safety.\n\n**Tracker-aware.** `ddp` obeys the simple [Tracker](https://www.meteor.com/tracker) convention for transparent reactivity. Values such as the current connection status (are we online?), subscription readiness (is the `newsFeed` done loading or should we show a progress indicator?), and the currently logged-in user (what username should we show in the status area at the top of page?) all work as reactive variables.\n\n**Default connection.** Normally you open a DDP connection with `myconn = DDP.connect(url)`, and then work with the connection with calls like `myconn.subscribe(\"newsFeed\")` or `myconn.call(\"transferBalance\")`. But if you build and deploy your app with the other Meteor tools, then a DDP server instance is automatically set up on the server, and each client is configured to automatically open a connection to that server on startup. You can work then with this \"default connection\" and \"default server\" with easy aliases like `Meteor.subscribe` and `Meteor.call`.\n\n**Connection lifecycle hooks.** Servers can run code when connections are established or closed. This can be used to update the database to show which users are online, making it easily to create presence features like a live-updating \"Friends Online Now\" list.\n\n**CRUD boilerplate and quickstart packages.** The [full-stack database drivers](https://www.meteor.com/full-stack-db-drivers) provide some helpful functionality that is worth mentioning here, even though it is actually part of those database packages, not `ddp`. They provide general-purpose `create`, `update`, and `delete` methods for each database collection, so that it is not necessary to write methods for basic CRUD operations. A system of `allow` and `deny` rules is used to control what each user can do. And two \"quickstart\" packages are provided, for quick prototyping and to help new developers learn Meteor. The `insecure` package turns off `allow`/`deny` rule checking for the generic `create`, `update`, and `delete` methods. The `autopublish` package automatically subscribes every connected client to the full contents of every database collection.\n"
  },
  {
    "path": "packages/ddp/package.js",
    "content": "Package.describe({\n  summary: \"Meteor's latency-compensated distributed data framework\",\n  version: '1.2.5'\n});\n\nPackage.onUse(function (api) {\n  api.use(['ddp-client'], ['client', 'server']);\n  api.use(['ddp-server'], 'server');\n\n  api.export('DDP');\n  api.export('DDPServer', 'server');\n\n  api.imply('ddp-client');\n  api.imply('ddp-server');\n});\n"
  },
  {
    "path": "packages/ddp-client/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/ddp-client/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/ddp-client/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"faye-websocket\": {\n      \"version\": \"0.9.4\",\n      \"resolved\": \"https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.4.tgz\",\n      \"from\": \"https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.4.tgz\",\n      \"dependencies\": {\n        \"websocket-driver\": {\n          \"version\": \"0.5.4\",\n          \"resolved\": \"https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.5.4.tgz\",\n          \"from\": \"https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.5.4.tgz\",\n          \"dependencies\": {\n            \"websocket-extensions\": {\n              \"version\": \"0.1.1\",\n              \"resolved\": \"https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz\"\n            }\n          }\n        }\n      }\n    },\n    \"lolex\": {\n      \"version\": \"1.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/lolex/-/lolex-1.4.0.tgz\",\n      \"from\": \"lolex@1.4.0\"\n    },\n    \"permessage-deflate\": {\n      \"version\": \"0.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/permessage-deflate/-/permessage-deflate-0.1.3.tgz\",\n      \"from\": \"https://registry.npmjs.org/permessage-deflate/-/permessage-deflate-0.1.3.tgz\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/ddp-client/client_convenience.js",
    "content": "// Meteor.refresh can be called on the client (if you're in common code) but it\n// only has an effect on the server.\nMeteor.refresh = function (notification) {\n};\n\nif (Meteor.isClient) {\n  // By default, try to connect back to the same endpoint as the page\n  // was served from.\n  //\n  // XXX We should be doing this a different way. Right now we don't\n  // include ROOT_URL_PATH_PREFIX when computing ddpUrl. (We don't\n  // include it on the server when computing\n  // DDP_DEFAULT_CONNECTION_URL, and we don't include it in our\n  // default, '/'.) We get by with this because DDP.connect then\n  // forces the URL passed to it to be interpreted relative to the\n  // app's deploy path, even if it is absolute. Instead, we should\n  // make DDP_DEFAULT_CONNECTION_URL, if set, include the path prefix;\n  // make the default ddpUrl be '' rather that '/'; and make\n  // _translateUrl in stream_client_common.js not force absolute paths\n  // to be treated like relative paths. See also\n  // stream_client_common.js #RationalizingRelativeDDPURLs\n  var ddpUrl = '/';\n  if (typeof __meteor_runtime_config__ !== \"undefined\") {\n    if (__meteor_runtime_config__.DDP_DEFAULT_CONNECTION_URL)\n      ddpUrl = __meteor_runtime_config__.DDP_DEFAULT_CONNECTION_URL;\n  }\n\n  var retry = new Retry();\n\n  var onDDPVersionNegotiationFailure = function (description) {\n    Meteor._debug(description);\n    if (Package.reload) {\n      var migrationData = Package.reload.Reload._migrationData('livedata') || {};\n      var failures = migrationData.DDPVersionNegotiationFailures || 0;\n      ++failures;\n      Package.reload.Reload._onMigrate('livedata', function () {\n        return [true, {DDPVersionNegotiationFailures: failures}];\n      });\n      retry.retryLater(failures, function () {\n        Package.reload.Reload._reload();\n      });\n    }\n  };\n\n  Meteor.connection =\n    DDP.connect(ddpUrl, {\n      onDDPVersionNegotiationFailure: onDDPVersionNegotiationFailure\n    });\n\n  // Proxy the public methods of Meteor.connection so they can\n  // be called directly on Meteor.\n  _.each(['subscribe', 'methods', 'call', 'apply', 'status', 'reconnect',\n          'disconnect'],\n         function (name) {\n           Meteor[name] = _.bind(Meteor.connection[name], Meteor.connection);\n         });\n} else {\n  // Never set up a default connection on the server. Don't even map\n  // subscribe/call/etc onto Meteor.\n  Meteor.connection = null;\n}\n\n// Meteor.connection used to be called\n// Meteor.default_connection. Provide backcompat as a courtesy even\n// though it was never documented.\n// XXX COMPAT WITH 0.6.4\nMeteor.default_connection = Meteor.connection;\n\n// We should transition from Meteor.connect to DDP.connect.\n// XXX COMPAT WITH 0.6.4\nMeteor.connect = DDP.connect;\n"
  },
  {
    "path": "packages/ddp-client/id_map.js",
    "content": "MongoIDMap = function () {\n  var self = this;\n  IdMap.call(self, MongoID.idStringify, MongoID.idParse);\n};\n\nMeteor._inherits(MongoIDMap, IdMap);\n"
  },
  {
    "path": "packages/ddp-client/livedata_common.js",
    "content": "LivedataTest.SUPPORTED_DDP_VERSIONS = DDPCommon.SUPPORTED_DDP_VERSIONS;\n\n// This is private but it's used in a few places. accounts-base uses\n// it to get the current user. Meteor.setTimeout and friends clear\n// it. We can probably find a better way to factor this.\nDDP._CurrentInvocation = new Meteor.EnvironmentVariable;\n"
  },
  {
    "path": "packages/ddp-client/livedata_connection.js",
    "content": "if (Meteor.isServer) {\n  var path = Npm.require('path');\n  var Fiber = Npm.require('fibers');\n  var Future = Npm.require(path.join('fibers', 'future'));\n}\n\n// @param url {String|Object} URL to Meteor app,\n//   or an object as a test hook (see code)\n// Options:\n//   reloadWithOutstanding: is it OK to reload if there are outstanding methods?\n//   headers: extra headers to send on the websockets connection, for\n//     server-to-server DDP only\n//   _sockjsOptions: Specifies options to pass through to the sockjs client\n//   onDDPNegotiationVersionFailure: callback when version negotiation fails.\n//\n// XXX There should be a way to destroy a DDP connection, causing all\n// outstanding method calls to fail.\n//\n// XXX Our current way of handling failure and reconnection is great\n// for an app (where we want to tolerate being disconnected as an\n// expect state, and keep trying forever to reconnect) but cumbersome\n// for something like a command line tool that wants to make a\n// connection, call a method, and print an error if connection\n// fails. We should have better usability in the latter case (while\n// still transparently reconnecting if it's just a transient failure\n// or the server migrating us).\nvar Connection = function (url, options) {\n  var self = this;\n  options = _.extend({\n    onConnected: function () {},\n    onDDPVersionNegotiationFailure: function (description) {\n      Meteor._debug(description);\n    },\n    heartbeatInterval: 17500,\n    heartbeatTimeout: 15000,\n    npmFayeOptions: {},\n    // These options are only for testing.\n    reloadWithOutstanding: false,\n    supportedDDPVersions: DDPCommon.SUPPORTED_DDP_VERSIONS,\n    retry: true,\n    respondToPings: true,\n    // When updates are coming within this ms interval, batch them together.\n    bufferedWritesInterval: 5,\n    // Flush buffers immediately if writes are happening continuously for more than this many ms.\n    bufferedWritesMaxAge: 500\n  }, options);\n\n  // If set, called when we reconnect, queuing method calls _before_ the\n  // existing outstanding ones. This is the only data member that is part of the\n  // public API!\n  self.onReconnect = null;\n\n  // as a test hook, allow passing a stream instead of a url.\n  if (typeof url === \"object\") {\n    self._stream = url;\n  } else {\n    self._stream = new LivedataTest.ClientStream(url, {\n      retry: options.retry,\n      headers: options.headers,\n      _sockjsOptions: options._sockjsOptions,\n      // Used to keep some tests quiet, or for other cases in which\n      // the right thing to do with connection errors is to silently\n      // fail (e.g. sending package usage stats). At some point we\n      // should have a real API for handling client-stream-level\n      // errors.\n      _dontPrintErrors: options._dontPrintErrors,\n      connectTimeoutMs: options.connectTimeoutMs,\n      npmFayeOptions: options.npmFayeOptions\n    });\n  }\n\n  self._lastSessionId = null;\n  self._versionSuggestion = null;  // The last proposed DDP version.\n  self._version = null;   // The DDP version agreed on by client and server.\n  self._stores = {}; // name -> object with methods\n  self._methodHandlers = {}; // name -> func\n  self._nextMethodId = 1;\n  self._supportedDDPVersions = options.supportedDDPVersions;\n\n  self._heartbeatInterval = options.heartbeatInterval;\n  self._heartbeatTimeout = options.heartbeatTimeout;\n\n  // Tracks methods which the user has tried to call but which have not yet\n  // called their user callback (ie, they are waiting on their result or for all\n  // of their writes to be written to the local cache). Map from method ID to\n  // MethodInvoker object.\n  self._methodInvokers = {};\n\n  // Tracks methods which the user has called but whose result messages have not\n  // arrived yet.\n  //\n  // _outstandingMethodBlocks is an array of blocks of methods. Each block\n  // represents a set of methods that can run at the same time. The first block\n  // represents the methods which are currently in flight; subsequent blocks\n  // must wait for previous blocks to be fully finished before they can be sent\n  // to the server.\n  //\n  // Each block is an object with the following fields:\n  // - methods: a list of MethodInvoker objects\n  // - wait: a boolean; if true, this block had a single method invoked with\n  //         the \"wait\" option\n  //\n  // There will never be adjacent blocks with wait=false, because the only thing\n  // that makes methods need to be serialized is a wait method.\n  //\n  // Methods are removed from the first block when their \"result\" is\n  // received. The entire first block is only removed when all of the in-flight\n  // methods have received their results (so the \"methods\" list is empty) *AND*\n  // all of the data written by those methods are visible in the local cache. So\n  // it is possible for the first block's methods list to be empty, if we are\n  // still waiting for some objects to quiesce.\n  //\n  // Example:\n  //  _outstandingMethodBlocks = [\n  //    {wait: false, methods: []},\n  //    {wait: true, methods: [<MethodInvoker for 'login'>]},\n  //    {wait: false, methods: [<MethodInvoker for 'foo'>,\n  //                            <MethodInvoker for 'bar'>]}]\n  // This means that there were some methods which were sent to the server and\n  // which have returned their results, but some of the data written by\n  // the methods may not be visible in the local cache. Once all that data is\n  // visible, we will send a 'login' method. Once the login method has returned\n  // and all the data is visible (including re-running subs if userId changes),\n  // we will send the 'foo' and 'bar' methods in parallel.\n  self._outstandingMethodBlocks = [];\n\n  // method ID -> array of objects with keys 'collection' and 'id', listing\n  // documents written by a given method's stub. keys are associated with\n  // methods whose stub wrote at least one document, and whose data-done message\n  // has not yet been received.\n  self._documentsWrittenByStub = {};\n  // collection -> IdMap of \"server document\" object. A \"server document\" has:\n  // - \"document\": the version of the document according the\n  //   server (ie, the snapshot before a stub wrote it, amended by any changes\n  //   received from the server)\n  //   It is undefined if we think the document does not exist\n  // - \"writtenByStubs\": a set of method IDs whose stubs wrote to the document\n  //   whose \"data done\" messages have not yet been processed\n  self._serverDocuments = {};\n\n  // Array of callbacks to be called after the next update of the local\n  // cache. Used for:\n  //  - Calling methodInvoker.dataVisible and sub ready callbacks after\n  //    the relevant data is flushed.\n  //  - Invoking the callbacks of \"half-finished\" methods after reconnect\n  //    quiescence. Specifically, methods whose result was received over the old\n  //    connection (so we don't re-send it) but whose data had not been made\n  //    visible.\n  self._afterUpdateCallbacks = [];\n\n  // In two contexts, we buffer all incoming data messages and then process them\n  // all at once in a single update:\n  //   - During reconnect, we buffer all data messages until all subs that had\n  //     been ready before reconnect are ready again, and all methods that are\n  //     active have returned their \"data done message\"; then\n  //   - During the execution of a \"wait\" method, we buffer all data messages\n  //     until the wait method gets its \"data done\" message. (If the wait method\n  //     occurs during reconnect, it doesn't get any special handling.)\n  // all data messages are processed in one update.\n  //\n  // The following fields are used for this \"quiescence\" process.\n\n  // This buffers the messages that aren't being processed yet.\n  self._messagesBufferedUntilQuiescence = [];\n  // Map from method ID -> true. Methods are removed from this when their\n  // \"data done\" message is received, and we will not quiesce until it is\n  // empty.\n  self._methodsBlockingQuiescence = {};\n  // map from sub ID -> true for subs that were ready (ie, called the sub\n  // ready callback) before reconnect but haven't become ready again yet\n  self._subsBeingRevived = {}; // map from sub._id -> true\n  // if true, the next data update should reset all stores. (set during\n  // reconnect.)\n  self._resetStores = false;\n\n  // name -> array of updates for (yet to be created) collections\n  self._updatesForUnknownStores = {};\n  // if we're blocking a migration, the retry func\n  self._retryMigrate = null;\n\n  self.__flushBufferedWrites = Meteor.bindEnvironment(\n    self._flushBufferedWrites, \"flushing DDP buffered writes\", self);\n  // Collection name -> array of messages.\n  self._bufferedWrites = {};\n  // When current buffer of updates must be flushed at, in ms timestamp.\n  self._bufferedWritesFlushAt = null;\n  // Timeout handle for the next processing of all pending writes\n  self._bufferedWritesFlushHandle = null;\n\n  self._bufferedWritesInterval = options.bufferedWritesInterval;\n  self._bufferedWritesMaxAge = options.bufferedWritesMaxAge;\n\n  // metadata for subscriptions.  Map from sub ID to object with keys:\n  //   - id\n  //   - name\n  //   - params\n  //   - inactive (if true, will be cleaned up if not reused in re-run)\n  //   - ready (has the 'ready' message been received?)\n  //   - readyCallback (an optional callback to call when ready)\n  //   - errorCallback (an optional callback to call if the sub terminates with\n  //                    an error, XXX COMPAT WITH 1.0.3.1)\n  //   - stopCallback (an optional callback to call when the sub terminates\n  //     for any reason, with an error argument if an error triggered the stop)\n  self._subscriptions = {};\n\n  // Reactive userId.\n  self._userId = null;\n  self._userIdDeps = new Tracker.Dependency;\n\n  // Block auto-reload while we're waiting for method responses.\n  if (Meteor.isClient && Package.reload && !options.reloadWithOutstanding) {\n    Package.reload.Reload._onMigrate(function (retry) {\n      if (!self._readyToMigrate()) {\n        if (self._retryMigrate)\n          throw new Error(\"Two migrations in progress?\");\n        self._retryMigrate = retry;\n        return false;\n      } else {\n        return [true];\n      }\n    });\n  }\n\n  var onMessage = function (raw_msg) {\n    try {\n      var msg = DDPCommon.parseDDP(raw_msg);\n    } catch (e) {\n      Meteor._debug(\"Exception while parsing DDP\", e);\n      return;\n    }\n\n    // Any message counts as receiving a pong, as it demonstrates that\n    // the server is still alive.\n    if (self._heartbeat) {\n      self._heartbeat.messageReceived();\n    }\n\n    if (msg === null || !msg.msg) {\n      // XXX COMPAT WITH 0.6.6. ignore the old welcome message for back\n      // compat.  Remove this 'if' once the server stops sending welcome\n      // messages (stream_server.js).\n      if (! (msg && msg.server_id))\n        Meteor._debug(\"discarding invalid livedata message\", msg);\n      return;\n    }\n\n    if (msg.msg === 'connected') {\n      self._version = self._versionSuggestion;\n      self._livedata_connected(msg);\n      options.onConnected();\n    }\n    else if (msg.msg === 'failed') {\n      if (_.contains(self._supportedDDPVersions, msg.version)) {\n        self._versionSuggestion = msg.version;\n        self._stream.reconnect({_force: true});\n      } else {\n        var description =\n              \"DDP version negotiation failed; server requested version \" + msg.version;\n        self._stream.disconnect({_permanent: true, _error: description});\n        options.onDDPVersionNegotiationFailure(description);\n      }\n    }\n    else if (msg.msg === 'ping' && options.respondToPings) {\n      self._send({msg: \"pong\", id: msg.id});\n    }\n    else if (msg.msg === 'pong') {\n      // noop, as we assume everything's a pong\n    }\n    else if (_.include(['added', 'changed', 'removed', 'ready', 'updated'], msg.msg))\n      self._livedata_data(msg);\n    else if (msg.msg === 'nosub')\n      self._livedata_nosub(msg);\n    else if (msg.msg === 'result')\n      self._livedata_result(msg);\n    else if (msg.msg === 'error')\n      self._livedata_error(msg);\n    else\n      Meteor._debug(\"discarding unknown livedata message type\", msg);\n  };\n\n  var onReset = function () {\n    // Send a connect message at the beginning of the stream.\n    // NOTE: reset is called even on the first connection, so this is\n    // the only place we send this message.\n    var msg = {msg: 'connect'};\n    if (self._lastSessionId)\n      msg.session = self._lastSessionId;\n    msg.version = self._versionSuggestion || self._supportedDDPVersions[0];\n    self._versionSuggestion = msg.version;\n    msg.support = self._supportedDDPVersions;\n    self._send(msg);\n\n    // Mark non-retry calls as failed. This has to be done early as getting these methods out of the\n    // current block is pretty important to making sure that quiescence is properly calculated, as\n    // well as possibly moving on to another useful block.\n\n    // Only bother testing if there is an outstandingMethodBlock (there might not be, especially if\n    // we are connecting for the first time.\n    if (self._outstandingMethodBlocks.length > 0) {\n      // If there is an outstanding method block, we only care about the first one as that is the\n      // one that could have already sent messages with no response, that are not allowed to retry.\n      _.each(self._outstandingMethodBlocks[0].methods, function(methodInvoker) {\n        // If the message wasn't sent or it's allowed to retry, do nothing.\n        if (methodInvoker.sentMessage && methodInvoker.noRetry) {\n          // The next loop serves to get the index in the current method block of this method.\n          var currentMethodBlock = self._outstandingMethodBlocks[0].methods;\n          var loopMethod;\n          for (var i = 0; i < currentMethodBlock.length; i++) {\n            loopMethod = currentMethodBlock[i];\n            if (loopMethod.methodId === methodInvoker.methodId) {\n              break;\n            }\n          }\n\n          // Remove from current method block. This may leave the block empty, but we\n          // don't move on to the next block until the callback has been delivered, in\n          // _outstandingMethodFinished.\n          currentMethodBlock.splice(i, 1);\n\n          // Make sure that the method is told that it failed.\n          methodInvoker.receiveResult(new Meteor.Error('invocation-failed',\n            'Method invocation might have failed due to dropped connection. ' +\n            'Failing because `noRetry` option was passed to Meteor.apply.'));\n        }\n      });\n    }\n\n    // Now, to minimize setup latency, go ahead and blast out all of\n    // our pending methods ands subscriptions before we've even taken\n    // the necessary RTT to know if we successfully reconnected. (1)\n    // They're supposed to be idempotent, and where they are not,\n    // they can block retry in apply; (2) even if we did reconnect,\n    // we're not sure what messages might have gotten lost\n    // (in either direction) since we were disconnected (TCP being\n    // sloppy about that.)\n\n    // If the current block of methods all got their results (but didn't all get\n    // their data visible), discard the empty block now.\n    if (! _.isEmpty(self._outstandingMethodBlocks) &&\n        _.isEmpty(self._outstandingMethodBlocks[0].methods)) {\n      self._outstandingMethodBlocks.shift();\n    }\n\n    // Mark all messages as unsent, they have not yet been sent on this\n    // connection.\n    _.each(self._methodInvokers, function (m) {\n      m.sentMessage = false;\n    });\n\n    // If an `onReconnect` handler is set, call it first. Go through\n    // some hoops to ensure that methods that are called from within\n    // `onReconnect` get executed _before_ ones that were originally\n    // outstanding (since `onReconnect` is used to re-establish auth\n    // certificates)\n    if (self.onReconnect)\n      self._callOnReconnectAndSendAppropriateOutstandingMethods();\n    else\n      self._sendOutstandingMethods();\n\n    // add new subscriptions at the end. this way they take effect after\n    // the handlers and we don't see flicker.\n    _.each(self._subscriptions, function (sub, id) {\n      self._send({\n        msg: 'sub',\n        id: id,\n        name: sub.name,\n        params: sub.params\n      });\n    });\n  };\n\n  var onDisconnect = function () {\n    if (self._heartbeat) {\n      self._heartbeat.stop();\n      self._heartbeat = null;\n    }\n  };\n\n  if (Meteor.isServer) {\n    self._stream.on('message', Meteor.bindEnvironment(onMessage, \"handling DDP message\"));\n    self._stream.on('reset', Meteor.bindEnvironment(onReset, \"handling DDP reset\"));\n    self._stream.on('disconnect', Meteor.bindEnvironment(onDisconnect, \"handling DDP disconnect\"));\n  } else {\n    self._stream.on('message', onMessage);\n    self._stream.on('reset', onReset);\n    self._stream.on('disconnect', onDisconnect);\n  }\n};\n\n// A MethodInvoker manages sending a method to the server and calling the user's\n// callbacks. On construction, it registers itself in the connection's\n// _methodInvokers map; it removes itself once the method is fully finished and\n// the callback is invoked. This occurs when it has both received a result,\n// and the data written by it is fully visible.\nvar MethodInvoker = function (options) {\n  var self = this;\n\n  // Public (within this file) fields.\n  self.methodId = options.methodId;\n  self.sentMessage = false;\n\n  self._callback = options.callback;\n  self._connection = options.connection;\n  self._message = options.message;\n  self._onResultReceived = options.onResultReceived || function () {};\n  self._wait = options.wait;\n  self.noRetry = options.noRetry;\n  self._methodResult = null;\n  self._dataVisible = false;\n\n  // Register with the connection.\n  self._connection._methodInvokers[self.methodId] = self;\n};\n_.extend(MethodInvoker.prototype, {\n  // Sends the method message to the server. May be called additional times if\n  // we lose the connection and reconnect before receiving a result.\n  sendMessage: function () {\n    var self = this;\n    // This function is called before sending a method (including resending on\n    // reconnect). We should only (re)send methods where we don't already have a\n    // result!\n    if (self.gotResult())\n      throw new Error(\"sendingMethod is called on method with result\");\n\n\n    // If we're re-sending it, it doesn't matter if data was written the first\n    // time.\n    self._dataVisible = false;\n    self.sentMessage = true;\n\n    // If this is a wait method, make all data messages be buffered until it is\n    // done.\n    if (self._wait)\n      self._connection._methodsBlockingQuiescence[self.methodId] = true;\n\n    // Actually send the message.\n    self._connection._send(self._message);\n  },\n  // Invoke the callback, if we have both a result and know that all data has\n  // been written to the local cache.\n  _maybeInvokeCallback: function () {\n    var self = this;\n    if (self._methodResult && self._dataVisible) {\n      // Call the callback. (This won't throw: the callback was wrapped with\n      // bindEnvironment.)\n      self._callback(self._methodResult[0], self._methodResult[1]);\n\n      // Forget about this method.\n      delete self._connection._methodInvokers[self.methodId];\n\n      // Let the connection know that this method is finished, so it can try to\n      // move on to the next block of methods.\n      self._connection._outstandingMethodFinished();\n    }\n  },\n  // Call with the result of the method from the server. Only may be called\n  // once; once it is called, you should not call sendMessage again.\n  // If the user provided an onResultReceived callback, call it immediately.\n  // Then invoke the main callback if data is also visible.\n  receiveResult: function (err, result) {\n    var self = this;\n    if (self.gotResult())\n      throw new Error(\"Methods should only receive results once\");\n    self._methodResult = [err, result];\n    self._onResultReceived(err, result);\n    self._maybeInvokeCallback();\n  },\n  // Call this when all data written by the method is visible. This means that\n  // the method has returns its \"data is done\" message *AND* all server\n  // documents that are buffered at that time have been written to the local\n  // cache. Invokes the main callback if the result has been received.\n  dataVisible: function () {\n    var self = this;\n    self._dataVisible = true;\n    self._maybeInvokeCallback();\n  },\n  // True if receiveResult has been called.\n  gotResult: function () {\n    var self = this;\n    return !!self._methodResult;\n  }\n});\n\n_.extend(Connection.prototype, {\n  // 'name' is the name of the data on the wire that should go in the\n  // store. 'wrappedStore' should be an object with methods beginUpdate, update,\n  // endUpdate, saveOriginals, retrieveOriginals. see Collection for an example.\n  registerStore: function (name, wrappedStore) {\n    var self = this;\n\n    if (name in self._stores)\n      return false;\n\n    // Wrap the input object in an object which makes any store method not\n    // implemented by 'store' into a no-op.\n    var store = {};\n    _.each(['update', 'beginUpdate', 'endUpdate', 'saveOriginals',\n            'retrieveOriginals', 'getDoc',\n\t\t\t'_getCollection'], function (method) {\n              store[method] = function () {\n                return (wrappedStore[method]\n                        ? wrappedStore[method].apply(wrappedStore, arguments)\n                        : undefined);\n              };\n            });\n\n    self._stores[name] = store;\n\n    var queued = self._updatesForUnknownStores[name];\n    if (queued) {\n      store.beginUpdate(queued.length, false);\n      _.each(queued, function (msg) {\n        store.update(msg);\n      });\n      store.endUpdate();\n      delete self._updatesForUnknownStores[name];\n    }\n\n    return true;\n  },\n\n  /**\n   * @memberOf Meteor\n   * @importFromPackage meteor\n   * @summary Subscribe to a record set.  Returns a handle that provides\n   * `stop()` and `ready()` methods.\n   * @locus Client\n   * @param {String} name Name of the subscription.  Matches the name of the\n   * server's `publish()` call.\n   * @param {EJSONable} [arg1,arg2...] Optional arguments passed to publisher\n   * function on server.\n   * @param {Function|Object} [callbacks] Optional. May include `onStop`\n   * and `onReady` callbacks. If there is an error, it is passed as an\n   * argument to `onStop`. If a function is passed instead of an object, it\n   * is interpreted as an `onReady` callback.\n   */\n  subscribe: function (name /* .. [arguments] .. (callback|callbacks) */) {\n    var self = this;\n\n    var params = Array.prototype.slice.call(arguments, 1);\n    var callbacks = {};\n    if (params.length) {\n      var lastParam = params[params.length - 1];\n      if (_.isFunction(lastParam)) {\n        callbacks.onReady = params.pop();\n      } else if (lastParam &&\n        // XXX COMPAT WITH 1.0.3.1 onError used to exist, but now we use\n        // onStop with an error callback instead.\n        _.any([lastParam.onReady, lastParam.onError, lastParam.onStop],\n          _.isFunction)) {\n        callbacks = params.pop();\n      }\n    }\n\n    // Is there an existing sub with the same name and param, run in an\n    // invalidated Computation? This will happen if we are rerunning an\n    // existing computation.\n    //\n    // For example, consider a rerun of:\n    //\n    //     Tracker.autorun(function () {\n    //       Meteor.subscribe(\"foo\", Session.get(\"foo\"));\n    //       Meteor.subscribe(\"bar\", Session.get(\"bar\"));\n    //     });\n    //\n    // If \"foo\" has changed but \"bar\" has not, we will match the \"bar\"\n    // subcribe to an existing inactive subscription in order to not\n    // unsub and resub the subscription unnecessarily.\n    //\n    // We only look for one such sub; if there are N apparently-identical subs\n    // being invalidated, we will require N matching subscribe calls to keep\n    // them all active.\n    var existing = _.find(self._subscriptions, function (sub) {\n      return sub.inactive && sub.name === name &&\n        EJSON.equals(sub.params, params);\n    });\n\n    var id;\n    if (existing) {\n      id = existing.id;\n      existing.inactive = false; // reactivate\n\n      if (callbacks.onReady) {\n        // If the sub is not already ready, replace any ready callback with the\n        // one provided now. (It's not really clear what users would expect for\n        // an onReady callback inside an autorun; the semantics we provide is\n        // that at the time the sub first becomes ready, we call the last\n        // onReady callback provided, if any.)\n        if (!existing.ready)\n          existing.readyCallback = callbacks.onReady;\n      }\n\n      // XXX COMPAT WITH 1.0.3.1 we used to have onError but now we call\n      // onStop with an optional error argument\n      if (callbacks.onError) {\n        // Replace existing callback if any, so that errors aren't\n        // double-reported.\n        existing.errorCallback = callbacks.onError;\n      }\n\n      if (callbacks.onStop) {\n        existing.stopCallback = callbacks.onStop;\n      }\n    } else {\n      // New sub! Generate an id, save it locally, and send message.\n      id = Random.id();\n      self._subscriptions[id] = {\n        id: id,\n        name: name,\n        params: EJSON.clone(params),\n        inactive: false,\n        ready: false,\n        readyDeps: new Tracker.Dependency,\n        readyCallback: callbacks.onReady,\n        // XXX COMPAT WITH 1.0.3.1 #errorCallback\n        errorCallback: callbacks.onError,\n        stopCallback: callbacks.onStop,\n        connection: self,\n        remove: function() {\n          delete this.connection._subscriptions[this.id];\n          this.ready && this.readyDeps.changed();\n        },\n        stop: function() {\n          this.connection._send({msg: 'unsub', id: id});\n          this.remove();\n\n          if (callbacks.onStop) {\n            callbacks.onStop();\n          }\n        }\n      };\n      self._send({msg: 'sub', id: id, name: name, params: params});\n    }\n\n    // return a handle to the application.\n    var handle = {\n      stop: function () {\n        if (!_.has(self._subscriptions, id))\n          return;\n\n        self._subscriptions[id].stop();\n      },\n      ready: function () {\n        // return false if we've unsubscribed.\n        if (!_.has(self._subscriptions, id))\n          return false;\n        var record = self._subscriptions[id];\n        record.readyDeps.depend();\n        return record.ready;\n      },\n      subscriptionId: id\n    };\n\n    if (Tracker.active) {\n      // We're in a reactive computation, so we'd like to unsubscribe when the\n      // computation is invalidated... but not if the rerun just re-subscribes\n      // to the same subscription!  When a rerun happens, we use onInvalidate\n      // as a change to mark the subscription \"inactive\" so that it can\n      // be reused from the rerun.  If it isn't reused, it's killed from\n      // an afterFlush.\n      Tracker.onInvalidate(function (c) {\n        if (_.has(self._subscriptions, id))\n          self._subscriptions[id].inactive = true;\n\n        Tracker.afterFlush(function () {\n          if (_.has(self._subscriptions, id) &&\n              self._subscriptions[id].inactive)\n            handle.stop();\n        });\n      });\n    }\n\n    return handle;\n  },\n\n  // options:\n  // - onLateError {Function(error)} called if an error was received after the ready event.\n  //     (errors received before ready cause an error to be thrown)\n  _subscribeAndWait: function (name, args, options) {\n    var self = this;\n    var f = new Future();\n    var ready = false;\n    var handle;\n    args = args || [];\n    args.push({\n      onReady: function () {\n        ready = true;\n        f['return']();\n      },\n      onError: function (e) {\n        if (!ready)\n          f['throw'](e);\n        else\n          options && options.onLateError && options.onLateError(e);\n      }\n    });\n\n    handle = self.subscribe.apply(self, [name].concat(args));\n    f.wait();\n    return handle;\n  },\n\n  methods: function (methods) {\n    var self = this;\n    _.each(methods, function (func, name) {\n      if (typeof func !== 'function')\n        throw new Error(\"Method '\" + name + \"' must be a function\");\n      if (self._methodHandlers[name])\n        throw new Error(\"A method named '\" + name + \"' is already defined\");\n      self._methodHandlers[name] = func;\n    });\n  },\n\n  /**\n   * @memberOf Meteor\n   * @importFromPackage meteor\n   * @summary Invokes a method passing any number of arguments.\n   * @locus Anywhere\n   * @param {String} name Name of method to invoke\n   * @param {EJSONable} [arg1,arg2...] Optional method arguments\n   * @param {Function} [asyncCallback] Optional callback, which is called asynchronously with the error or result after the method is complete. If not provided, the method runs synchronously if possible (see below).\n   */\n  call: function (name /* .. [arguments] .. callback */) {\n    // if it's a function, the last argument is the result callback,\n    // not a parameter to the remote method.\n    var args = Array.prototype.slice.call(arguments, 1);\n    if (args.length && typeof args[args.length - 1] === \"function\")\n      var callback = args.pop();\n    return this.apply(name, args, callback);\n  },\n\n  // @param options {Optional Object}\n  //   wait: Boolean - Should we wait to call this until all current methods\n  //                   are fully finished, and block subsequent method calls\n  //                   until this method is fully finished?\n  //                   (does not affect methods called from within this method)\n  //   onResultReceived: Function - a callback to call as soon as the method\n  //                                result is received. the data written by\n  //                                the method may not yet be in the cache!\n  //   returnStubValue: Boolean - If true then in cases where we would have\n  //                              otherwise discarded the stub's return value\n  //                              and returned undefined, instead we go ahead\n  //                              and return it.  Specifically, this is any\n  //                              time other than when (a) we are already\n  //                              inside a stub or (b) we are in Node and no\n  //                              callback was provided.  Currently we require\n  //                              this flag to be explicitly passed to reduce\n  //                              the likelihood that stub return values will\n  //                              be confused with server return values; we\n  //                              may improve this in future.\n  // @param callback {Optional Function}\n\n  /**\n   * @memberOf Meteor\n   * @importFromPackage meteor\n   * @summary Invoke a method passing an array of arguments.\n   * @locus Anywhere\n   * @param {String} name Name of method to invoke\n   * @param {EJSONable[]} args Method arguments\n   * @param {Object} [options]\n   * @param {Boolean} options.wait (Client only) If true, don't send this method until all previous method calls have completed, and don't send any subsequent method calls until this one is completed.\n   * @param {Function} options.onResultReceived (Client only) This callback is invoked with the error or result of the method (just like `asyncCallback`) as soon as the error or result is available. The local cache may not yet reflect the writes performed by the method.\n   * @param {Boolean} options.noRetry (Client only) if true, don't send this method again on reload, simply call the callback an error with the error code 'invocation-failed'.\n   * @param {Function} [asyncCallback] Optional callback; same semantics as in [`Meteor.call`](#meteor_call).\n   */\n  apply: function (name, args, options, callback) {\n    var self = this;\n\n    // We were passed 3 arguments. They may be either (name, args, options)\n    // or (name, args, callback)\n    if (!callback && typeof options === 'function') {\n      callback = options;\n      options = {};\n    }\n    options = options || {};\n\n    if (callback) {\n      // XXX would it be better form to do the binding in stream.on,\n      // or caller, instead of here?\n      // XXX improve error message (and how we report it)\n      callback = Meteor.bindEnvironment(\n        callback,\n        \"delivering result of invoking '\" + name + \"'\"\n      );\n    }\n\n    // Keep our args safe from mutation (eg if we don't send the message for a\n    // while because of a wait method).\n    args = EJSON.clone(args);\n\n    // Lazily allocate method ID once we know that it'll be needed.\n    var methodId = (function () {\n      var id;\n      return function () {\n        if (id === undefined)\n          id = '' + (self._nextMethodId++);\n        return id;\n      };\n    })();\n\n    var enclosing = DDP._CurrentInvocation.get();\n    var alreadyInSimulation = enclosing && enclosing.isSimulation;\n\n    // Lazily generate a randomSeed, only if it is requested by the stub.\n    // The random streams only have utility if they're used on both the client\n    // and the server; if the client doesn't generate any 'random' values\n    // then we don't expect the server to generate any either.\n    // Less commonly, the server may perform different actions from the client,\n    // and may in fact generate values where the client did not, but we don't\n    // have any client-side values to match, so even here we may as well just\n    // use a random seed on the server.  In that case, we don't pass the\n    // randomSeed to save bandwidth, and we don't even generate it to save a\n    // bit of CPU and to avoid consuming entropy.\n    var randomSeed = null;\n    var randomSeedGenerator = function () {\n      if (randomSeed === null) {\n        randomSeed = DDPCommon.makeRpcSeed(enclosing, name);\n      }\n      return randomSeed;\n    };\n\n    // Run the stub, if we have one. The stub is supposed to make some\n    // temporary writes to the database to give the user a smooth experience\n    // until the actual result of executing the method comes back from the\n    // server (whereupon the temporary writes to the database will be reversed\n    // during the beginUpdate/endUpdate process.)\n    //\n    // Normally, we ignore the return value of the stub (even if it is an\n    // exception), in favor of the real return value from the server. The\n    // exception is if the *caller* is a stub. In that case, we're not going\n    // to do a RPC, so we use the return value of the stub as our return\n    // value.\n\n    var stub = self._methodHandlers[name];\n    if (stub) {\n      var setUserId = function(userId) {\n        self.setUserId(userId);\n      };\n\n      var invocation = new DDPCommon.MethodInvocation({\n        isSimulation: true,\n        userId: self.userId(),\n        setUserId: setUserId,\n        randomSeed: function () { return randomSeedGenerator(); }\n      });\n\n      if (!alreadyInSimulation)\n        self._saveOriginals();\n\n      try {\n        // Note that unlike in the corresponding server code, we never audit\n        // that stubs check() their arguments.\n        var stubReturnValue = DDP._CurrentInvocation.withValue(invocation, function () {\n          if (Meteor.isServer) {\n            // Because saveOriginals and retrieveOriginals aren't reentrant,\n            // don't allow stubs to yield.\n            return Meteor._noYieldsAllowed(function () {\n              // re-clone, so that the stub can't affect our caller's values\n              return stub.apply(invocation, EJSON.clone(args));\n            });\n          } else {\n            return stub.apply(invocation, EJSON.clone(args));\n          }\n        });\n      }\n      catch (e) {\n        var exception = e;\n      }\n\n      if (!alreadyInSimulation)\n        self._retrieveAndStoreOriginals(methodId());\n    }\n\n    // If we're in a simulation, stop and return the result we have,\n    // rather than going on to do an RPC. If there was no stub,\n    // we'll end up returning undefined.\n    if (alreadyInSimulation) {\n      if (callback) {\n        callback(exception, stubReturnValue);\n        return undefined;\n      }\n      if (exception)\n        throw exception;\n      return stubReturnValue;\n    }\n\n    // If an exception occurred in a stub, and we're ignoring it\n    // because we're doing an RPC and want to use what the server\n    // returns instead, log it so the developer knows\n    // (unless they explicitly ask to see the error).\n    //\n    // Tests can set the 'expected' flag on an exception so it won't\n    // go to log.\n    if (exception) {\n      if (options.throwStubExceptions) {\n        throw exception;\n      } else if (!exception.expected) {\n        Meteor._debug(\"Exception while simulating the effect of invoking '\" +\n          name + \"'\", exception, exception.stack);\n      }\n    }\n\n\n    // At this point we're definitely doing an RPC, and we're going to\n    // return the value of the RPC to the caller.\n\n    // If the caller didn't give a callback, decide what to do.\n    if (!callback) {\n      if (Meteor.isClient) {\n        // On the client, we don't have fibers, so we can't block. The\n        // only thing we can do is to return undefined and discard the\n        // result of the RPC. If an error occurred then print the error\n        // to the console.\n        callback = function (err) {\n          err && Meteor._debug(\"Error invoking Method '\" + name + \"':\",\n                               err.message);\n        };\n      } else {\n        // On the server, make the function synchronous. Throw on\n        // errors, return on success.\n        var future = new Future;\n        callback = future.resolver();\n      }\n    }\n    // Send the RPC. Note that on the client, it is important that the\n    // stub have finished before we send the RPC, so that we know we have\n    // a complete list of which local documents the stub wrote.\n    var message = {\n      msg: 'method',\n      method: name,\n      params: args,\n      id: methodId()\n    };\n\n    // Send the randomSeed only if we used it\n    if (randomSeed !== null) {\n      message.randomSeed = randomSeed;\n    }\n\n    var methodInvoker = new MethodInvoker({\n      methodId: methodId(),\n      callback: callback,\n      connection: self,\n      onResultReceived: options.onResultReceived,\n      wait: !!options.wait,\n      message: message,\n      noRetry: !!options.noRetry\n    });\n\n    if (options.wait) {\n      // It's a wait method! Wait methods go in their own block.\n      self._outstandingMethodBlocks.push(\n        {wait: true, methods: [methodInvoker]});\n    } else {\n      // Not a wait method. Start a new block if the previous block was a wait\n      // block, and add it to the last block of methods.\n      if (_.isEmpty(self._outstandingMethodBlocks) ||\n          _.last(self._outstandingMethodBlocks).wait)\n        self._outstandingMethodBlocks.push({wait: false, methods: []});\n      _.last(self._outstandingMethodBlocks).methods.push(methodInvoker);\n    }\n\n    // If we added it to the first block, send it out now.\n    if (self._outstandingMethodBlocks.length === 1)\n      methodInvoker.sendMessage();\n\n    // If we're using the default callback on the server,\n    // block waiting for the result.\n    if (future) {\n      return future.wait();\n    }\n    return options.returnStubValue ? stubReturnValue : undefined;\n  },\n\n  // Before calling a method stub, prepare all stores to track changes and allow\n  // _retrieveAndStoreOriginals to get the original versions of changed\n  // documents.\n  _saveOriginals: function () {\n    var self = this;\n    _.each(self._stores, function (s) {\n      s.saveOriginals();\n    });\n  },\n  // Retrieves the original versions of all documents modified by the stub for\n  // method 'methodId' from all stores and saves them to _serverDocuments (keyed\n  // by document) and _documentsWrittenByStub (keyed by method ID).\n  _retrieveAndStoreOriginals: function (methodId) {\n    var self = this;\n    if (self._documentsWrittenByStub[methodId])\n      throw new Error(\"Duplicate methodId in _retrieveAndStoreOriginals\");\n\n    var docsWritten = [];\n    _.each(self._stores, function (s, collection) {\n      var originals = s.retrieveOriginals();\n      // not all stores define retrieveOriginals\n      if (!originals)\n        return;\n      originals.forEach(function (doc, id) {\n        docsWritten.push({collection: collection, id: id});\n        if (!_.has(self._serverDocuments, collection))\n          self._serverDocuments[collection] = new MongoIDMap;\n        var serverDoc = self._serverDocuments[collection].setDefault(id, {});\n        if (serverDoc.writtenByStubs) {\n          // We're not the first stub to write this doc. Just add our method ID\n          // to the record.\n          serverDoc.writtenByStubs[methodId] = true;\n        } else {\n          // First stub! Save the original value and our method ID.\n          serverDoc.document = doc;\n          serverDoc.flushCallbacks = [];\n          serverDoc.writtenByStubs = {};\n          serverDoc.writtenByStubs[methodId] = true;\n        }\n      });\n    });\n    if (!_.isEmpty(docsWritten)) {\n      self._documentsWrittenByStub[methodId] = docsWritten;\n    }\n  },\n\n  // This is very much a private function we use to make the tests\n  // take up fewer server resources after they complete.\n  _unsubscribeAll: function () {\n    var self = this;\n    _.each(_.clone(self._subscriptions), function (sub, id) {\n      // Avoid killing the autoupdate subscription so that developers\n      // still get hot code pushes when writing tests.\n      //\n      // XXX it's a hack to encode knowledge about autoupdate here,\n      // but it doesn't seem worth it yet to have a special API for\n      // subscriptions to preserve after unit tests.\n      if (sub.name !== 'meteor_autoupdate_clientVersions') {\n        self._subscriptions[id].stop();\n      }\n    });\n  },\n\n  // Sends the DDP stringification of the given message object\n  _send: function (obj) {\n    var self = this;\n    self._stream.send(DDPCommon.stringifyDDP(obj));\n  },\n\n  // We detected via DDP-level heartbeats that we've lost the\n  // connection.  Unlike `disconnect` or `close`, a lost connection\n  // will be automatically retried.\n  _lostConnection: function (error) {\n    var self = this;\n    self._stream._lostConnection(error);\n  },\n\n  /**\n   * @summary Get the current connection status. A reactive data source.\n   * @locus Client\n   * @memberOf Meteor\n   * @importFromPackage meteor\n   */\n  status: function (/*passthrough args*/) {\n    var self = this;\n    return self._stream.status.apply(self._stream, arguments);\n  },\n\n  /**\n   * @summary Force an immediate reconnection attempt if the client is not connected to the server.\n\n  This method does nothing if the client is already connected.\n   * @locus Client\n   * @memberOf Meteor\n   * @importFromPackage meteor\n   */\n  reconnect: function (/*passthrough args*/) {\n    var self = this;\n    return self._stream.reconnect.apply(self._stream, arguments);\n  },\n\n  /**\n   * @summary Disconnect the client from the server.\n   * @locus Client\n   * @memberOf Meteor\n   * @importFromPackage meteor\n   */\n  disconnect: function (/*passthrough args*/) {\n    var self = this;\n    return self._stream.disconnect.apply(self._stream, arguments);\n  },\n\n  close: function () {\n    var self = this;\n    return self._stream.disconnect({_permanent: true});\n  },\n\n  ///\n  /// Reactive user system\n  ///\n  userId: function () {\n    var self = this;\n    if (self._userIdDeps)\n      self._userIdDeps.depend();\n    return self._userId;\n  },\n\n  setUserId: function (userId) {\n    var self = this;\n    // Avoid invalidating dependents if setUserId is called with current value.\n    if (self._userId === userId)\n      return;\n    self._userId = userId;\n    if (self._userIdDeps)\n      self._userIdDeps.changed();\n  },\n\n  // Returns true if we are in a state after reconnect of waiting for subs to be\n  // revived or early methods to finish their data, or we are waiting for a\n  // \"wait\" method to finish.\n  _waitingForQuiescence: function () {\n    var self = this;\n    return (! _.isEmpty(self._subsBeingRevived) ||\n            ! _.isEmpty(self._methodsBlockingQuiescence));\n  },\n\n  // Returns true if any method whose message has been sent to the server has\n  // not yet invoked its user callback.\n  _anyMethodsAreOutstanding: function () {\n    var self = this;\n    return _.any(_.pluck(self._methodInvokers, 'sentMessage'));\n  },\n\n  _livedata_connected: function (msg) {\n    var self = this;\n\n    if (self._version !== 'pre1' && self._heartbeatInterval !== 0) {\n      self._heartbeat = new DDPCommon.Heartbeat({\n        heartbeatInterval: self._heartbeatInterval,\n        heartbeatTimeout: self._heartbeatTimeout,\n        onTimeout: function () {\n          self._lostConnection(\n            new DDP.ConnectionError(\"DDP heartbeat timed out\"));\n        },\n        sendPing: function () {\n          self._send({msg: 'ping'});\n        }\n      });\n      self._heartbeat.start();\n    }\n\n    // If this is a reconnect, we'll have to reset all stores.\n    if (self._lastSessionId)\n      self._resetStores = true;\n\n    if (typeof (msg.session) === \"string\") {\n      var reconnectedToPreviousSession = (self._lastSessionId === msg.session);\n      self._lastSessionId = msg.session;\n    }\n\n    if (reconnectedToPreviousSession) {\n      // Successful reconnection -- pick up where we left off.  Note that right\n      // now, this never happens: the server never connects us to a previous\n      // session, because DDP doesn't provide enough data for the server to know\n      // what messages the client has processed. We need to improve DDP to make\n      // this possible, at which point we'll probably need more code here.\n      return;\n    }\n\n    // Server doesn't have our data any more. Re-sync a new session.\n\n    // Forget about messages we were buffering for unknown collections. They'll\n    // be resent if still relevant.\n    self._updatesForUnknownStores = {};\n\n    if (self._resetStores) {\n      // Forget about the effects of stubs. We'll be resetting all collections\n      // anyway.\n      self._documentsWrittenByStub = {};\n      self._serverDocuments = {};\n    }\n\n    // Clear _afterUpdateCallbacks.\n    self._afterUpdateCallbacks = [];\n\n    // Mark all named subscriptions which are ready (ie, we already called the\n    // ready callback) as needing to be revived.\n    // XXX We should also block reconnect quiescence until unnamed subscriptions\n    //     (eg, autopublish) are done re-publishing to avoid flicker!\n    self._subsBeingRevived = {};\n    _.each(self._subscriptions, function (sub, id) {\n      if (sub.ready)\n        self._subsBeingRevived[id] = true;\n    });\n\n    // Arrange for \"half-finished\" methods to have their callbacks run, and\n    // track methods that were sent on this connection so that we don't\n    // quiesce until they are all done.\n    //\n    // Start by clearing _methodsBlockingQuiescence: methods sent before\n    // reconnect don't matter, and any \"wait\" methods sent on the new connection\n    // that we drop here will be restored by the loop below.\n    self._methodsBlockingQuiescence = {};\n    if (self._resetStores) {\n      _.each(self._methodInvokers, function (invoker) {\n        if (invoker.gotResult()) {\n          // This method already got its result, but it didn't call its callback\n          // because its data didn't become visible. We did not resend the\n          // method RPC. We'll call its callback when we get a full quiesce,\n          // since that's as close as we'll get to \"data must be visible\".\n          self._afterUpdateCallbacks.push(_.bind(invoker.dataVisible, invoker));\n        } else if (invoker.sentMessage) {\n          // This method has been sent on this connection (maybe as a resend\n          // from the last connection, maybe from onReconnect, maybe just very\n          // quickly before processing the connected message).\n          //\n          // We don't need to do anything special to ensure its callbacks get\n          // called, but we'll count it as a method which is preventing\n          // reconnect quiescence. (eg, it might be a login method that was run\n          // from onReconnect, and we don't want to see flicker by seeing a\n          // logged-out state.)\n          self._methodsBlockingQuiescence[invoker.methodId] = true;\n        }\n      });\n    }\n\n    self._messagesBufferedUntilQuiescence = [];\n\n    // If we're not waiting on any methods or subs, we can reset the stores and\n    // call the callbacks immediately.\n    if (!self._waitingForQuiescence()) {\n      if (self._resetStores) {\n        _.each(self._stores, function (s) {\n          s.beginUpdate(0, true);\n          s.endUpdate();\n        });\n        self._resetStores = false;\n      }\n      self._runAfterUpdateCallbacks();\n    }\n  },\n\n\n  _processOneDataMessage: function (msg, updates) {\n    var self = this;\n    // Using underscore here so as not to need to capitalize.\n    self['_process_' + msg.msg](msg, updates);\n  },\n\n\n  _livedata_data: function (msg) {\n    var self = this;\n\n    if (self._waitingForQuiescence()) {\n      self._messagesBufferedUntilQuiescence.push(msg);\n\n      if (msg.msg === \"nosub\")\n        delete self._subsBeingRevived[msg.id];\n\n      _.each(msg.subs || [], function (subId) {\n        delete self._subsBeingRevived[subId];\n      });\n      _.each(msg.methods || [], function (methodId) {\n        delete self._methodsBlockingQuiescence[methodId];\n      });\n\n      if (self._waitingForQuiescence())\n        return;\n\n      // No methods or subs are blocking quiescence!\n      // We'll now process and all of our buffered messages, reset all stores,\n      // and apply them all at once.\n      _.each(self._messagesBufferedUntilQuiescence, function (bufferedMsg) {\n        self._processOneDataMessage(bufferedMsg, self._bufferedWrites);\n      });\n      self._messagesBufferedUntilQuiescence = [];\n    } else {\n      self._processOneDataMessage(msg, self._bufferedWrites);\n    }\n\n    // Immediately flush writes when:\n    //  1. Buffering is disabled. Or;\n    //  2. any non-(added/changed/removed) message arrives.\n    var standardWrite = _.include(['added', 'changed', 'removed'], msg.msg);\n    if (self._bufferedWritesInterval === 0 || !standardWrite) {\n      self._flushBufferedWrites();\n      return;\n    }\n\n    if (self._bufferedWritesFlushAt === null) {\n      self._bufferedWritesFlushAt = new Date().valueOf() + self._bufferedWritesMaxAge;\n    }\n    else if (self._bufferedWritesFlushAt < new Date().valueOf()) {\n      self._flushBufferedWrites();\n      return;\n    }\n\n    if (self._bufferedWritesFlushHandle) {\n      clearTimeout(self._bufferedWritesFlushHandle);\n    }\n    self._bufferedWritesFlushHandle = setTimeout(self.__flushBufferedWrites,\n                                                      self._bufferedWritesInterval);\n  },\n\n  _flushBufferedWrites: function () {\n    var self = this;\n    if (self._bufferedWritesFlushHandle) {\n      clearTimeout(self._bufferedWritesFlushHandle);\n      self._bufferedWritesFlushHandle = null;\n    }\n\n    self._bufferedWritesFlushAt = null;\n    // We need to clear the buffer before passing it to\n    //  performWrites. As there's no guarantee that it\n    //  will exit cleanly.\n    var writes = self._bufferedWrites;\n    self._bufferedWrites = {};\n    self._performWrites(writes);\n  },\n\n  _performWrites: function(updates){\n    var self = this;\n\n    if (self._resetStores || !_.isEmpty(updates)) {\n      // Begin a transactional update of each store.\n      _.each(self._stores, function (s, storeName) {\n        s.beginUpdate(_.has(updates, storeName) ? updates[storeName].length : 0,\n                      self._resetStores);\n      });\n      self._resetStores = false;\n\n      _.each(updates, function (updateMessages, storeName) {\n        var store = self._stores[storeName];\n        if (store) {\n          _.each(updateMessages, function (updateMessage) {\n            store.update(updateMessage);\n          });\n        } else {\n          // Nobody's listening for this data. Queue it up until\n          // someone wants it.\n          // XXX memory use will grow without bound if you forget to\n          // create a collection or just don't care about it... going\n          // to have to do something about that.\n          if (!_.has(self._updatesForUnknownStores, storeName))\n            self._updatesForUnknownStores[storeName] = [];\n          Array.prototype.push.apply(self._updatesForUnknownStores[storeName],\n                                     updateMessages);\n        }\n      });\n\n      // End update transaction.\n      _.each(self._stores, function (s) { s.endUpdate(); });\n    }\n\n    self._runAfterUpdateCallbacks();\n  },\n\n  // Call any callbacks deferred with _runWhenAllServerDocsAreFlushed whose\n  // relevant docs have been flushed, as well as dataVisible callbacks at\n  // reconnect-quiescence time.\n  _runAfterUpdateCallbacks: function () {\n    var self = this;\n    var callbacks = self._afterUpdateCallbacks;\n    self._afterUpdateCallbacks = [];\n    _.each(callbacks, function (c) {\n      c();\n    });\n  },\n\n  _pushUpdate: function (updates, collection, msg) {\n    var self = this;\n    if (!_.has(updates, collection)) {\n      updates[collection] = [];\n    }\n    updates[collection].push(msg);\n  },\n\n  _getServerDoc: function (collection, id) {\n    var self = this;\n    if (!_.has(self._serverDocuments, collection))\n      return null;\n    var serverDocsForCollection = self._serverDocuments[collection];\n    return serverDocsForCollection.get(id) || null;\n  },\n\n  _process_added: function (msg, updates) {\n    var self = this;\n    var id = MongoID.idParse(msg.id);\n    var serverDoc = self._getServerDoc(msg.collection, id);\n    if (serverDoc) {\n      // Some outstanding stub wrote here.\n      var isExisting = (serverDoc.document !== undefined);\n\n      serverDoc.document = msg.fields || {};\n      serverDoc.document._id = id;\n\n      if (self._resetStores) {\n        // During reconnect the server is sending adds for existing ids.\n        // Always push an update so that document stays in the store after\n        // reset. Use current version of the document for this update, so\n        // that stub-written values are preserved.\n        var currentDoc = self._stores[msg.collection].getDoc(msg.id);\n        if (currentDoc !== undefined)\n          msg.fields = currentDoc;\n\n        self._pushUpdate(updates, msg.collection, msg);\n      } else if (isExisting) {\n        throw new Error(\"Server sent add for existing id: \" + msg.id);\n      }\n    } else {\n      self._pushUpdate(updates, msg.collection, msg);\n    }\n  },\n\n  _process_changed: function (msg, updates) {\n    var self = this;\n    var serverDoc = self._getServerDoc(\n      msg.collection, MongoID.idParse(msg.id));\n    if (serverDoc) {\n      if (serverDoc.document === undefined)\n        throw new Error(\"Server sent changed for nonexisting id: \" + msg.id);\n      DiffSequence.applyChanges(serverDoc.document, msg.fields);\n    } else {\n      self._pushUpdate(updates, msg.collection, msg);\n    }\n  },\n\n  _process_removed: function (msg, updates) {\n    var self = this;\n    var serverDoc = self._getServerDoc(\n      msg.collection, MongoID.idParse(msg.id));\n    if (serverDoc) {\n      // Some outstanding stub wrote here.\n      if (serverDoc.document === undefined)\n        throw new Error(\"Server sent removed for nonexisting id:\" + msg.id);\n      serverDoc.document = undefined;\n    } else {\n      self._pushUpdate(updates, msg.collection, {\n        msg: 'removed',\n        collection: msg.collection,\n        id: msg.id\n      });\n    }\n  },\n\n  _process_updated: function (msg, updates) {\n    var self = this;\n    // Process \"method done\" messages.\n    _.each(msg.methods, function (methodId) {\n      _.each(self._documentsWrittenByStub[methodId], function (written) {\n        var serverDoc = self._getServerDoc(written.collection, written.id);\n        if (!serverDoc)\n          throw new Error(\"Lost serverDoc for \" + JSON.stringify(written));\n        if (!serverDoc.writtenByStubs[methodId])\n          throw new Error(\"Doc \" + JSON.stringify(written) +\n                          \" not written by  method \" + methodId);\n        delete serverDoc.writtenByStubs[methodId];\n        if (_.isEmpty(serverDoc.writtenByStubs)) {\n          // All methods whose stubs wrote this method have completed! We can\n          // now copy the saved document to the database (reverting the stub's\n          // change if the server did not write to this object, or applying the\n          // server's writes if it did).\n\n          // This is a fake ddp 'replace' message.  It's just for talking\n          // between livedata connections and minimongo.  (We have to stringify\n          // the ID because it's supposed to look like a wire message.)\n          self._pushUpdate(updates, written.collection, {\n            msg: 'replace',\n            id: MongoID.idStringify(written.id),\n            replace: serverDoc.document\n          });\n          // Call all flush callbacks.\n          _.each(serverDoc.flushCallbacks, function (c) {\n            c();\n          });\n\n          // Delete this completed serverDocument. Don't bother to GC empty\n          // IdMaps inside self._serverDocuments, since there probably aren't\n          // many collections and they'll be written repeatedly.\n          self._serverDocuments[written.collection].remove(written.id);\n        }\n      });\n      delete self._documentsWrittenByStub[methodId];\n\n      // We want to call the data-written callback, but we can't do so until all\n      // currently buffered messages are flushed.\n      var callbackInvoker = self._methodInvokers[methodId];\n      if (!callbackInvoker)\n        throw new Error(\"No callback invoker for method \" + methodId);\n      self._runWhenAllServerDocsAreFlushed(\n        _.bind(callbackInvoker.dataVisible, callbackInvoker));\n    });\n  },\n\n  _process_ready: function (msg, updates) {\n    var self = this;\n    // Process \"sub ready\" messages. \"sub ready\" messages don't take effect\n    // until all current server documents have been flushed to the local\n    // database. We can use a write fence to implement this.\n    _.each(msg.subs, function (subId) {\n      self._runWhenAllServerDocsAreFlushed(function () {\n        var subRecord = self._subscriptions[subId];\n        // Did we already unsubscribe?\n        if (!subRecord)\n          return;\n        // Did we already receive a ready message? (Oops!)\n        if (subRecord.ready)\n          return;\n        subRecord.ready = true;\n        subRecord.readyCallback && subRecord.readyCallback();\n        subRecord.readyDeps.changed();\n      });\n    });\n  },\n\n  // Ensures that \"f\" will be called after all documents currently in\n  // _serverDocuments have been written to the local cache. f will not be called\n  // if the connection is lost before then!\n  _runWhenAllServerDocsAreFlushed: function (f) {\n    var self = this;\n    var runFAfterUpdates = function () {\n      self._afterUpdateCallbacks.push(f);\n    };\n    var unflushedServerDocCount = 0;\n    var onServerDocFlush = function () {\n      --unflushedServerDocCount;\n      if (unflushedServerDocCount === 0) {\n        // This was the last doc to flush! Arrange to run f after the updates\n        // have been applied.\n        runFAfterUpdates();\n      }\n    };\n    _.each(self._serverDocuments, function (collectionDocs) {\n      collectionDocs.forEach(function (serverDoc) {\n        var writtenByStubForAMethodWithSentMessage = _.any(\n          serverDoc.writtenByStubs, function (dummy, methodId) {\n            var invoker = self._methodInvokers[methodId];\n            return invoker && invoker.sentMessage;\n          });\n        if (writtenByStubForAMethodWithSentMessage) {\n          ++unflushedServerDocCount;\n          serverDoc.flushCallbacks.push(onServerDocFlush);\n        }\n      });\n    });\n    if (unflushedServerDocCount === 0) {\n      // There aren't any buffered docs --- we can call f as soon as the current\n      // round of updates is applied!\n      runFAfterUpdates();\n    }\n  },\n\n  _livedata_nosub: function (msg) {\n    var self = this;\n\n    // First pass it through _livedata_data, which only uses it to help get\n    // towards quiescence.\n    self._livedata_data(msg);\n\n    // Do the rest of our processing immediately, with no\n    // buffering-until-quiescence.\n\n    // we weren't subbed anyway, or we initiated the unsub.\n    if (!_.has(self._subscriptions, msg.id))\n      return;\n\n    // XXX COMPAT WITH 1.0.3.1 #errorCallback\n    var errorCallback = self._subscriptions[msg.id].errorCallback;\n    var stopCallback = self._subscriptions[msg.id].stopCallback;\n\n    self._subscriptions[msg.id].remove();\n\n    var meteorErrorFromMsg = function (msgArg) {\n      return msgArg && msgArg.error && new Meteor.Error(\n        msgArg.error.error, msgArg.error.reason, msgArg.error.details);\n    }\n\n    // XXX COMPAT WITH 1.0.3.1 #errorCallback\n    if (errorCallback && msg.error) {\n      errorCallback(meteorErrorFromMsg(msg));\n    }\n\n    if (stopCallback) {\n      stopCallback(meteorErrorFromMsg(msg));\n    }\n  },\n\n  _process_nosub: function () {\n    // This is called as part of the \"buffer until quiescence\" process, but\n    // nosub's effect is always immediate. It only goes in the buffer at all\n    // because it's possible for a nosub to be the thing that triggers\n    // quiescence, if we were waiting for a sub to be revived and it dies\n    // instead.\n  },\n\n  _livedata_result: function (msg) {\n    // id, result or error. error has error (code), reason, details\n\n    var self = this;\n\n    // Lets make sure there are no buffered writes before returning result.\n    if (!_.isEmpty(self._bufferedWrites)) {\n      self._flushBufferedWrites();\n    }\n\n    // find the outstanding request\n    // should be O(1) in nearly all realistic use cases\n    if (_.isEmpty(self._outstandingMethodBlocks)) {\n      Meteor._debug(\"Received method result but no methods outstanding\");\n      return;\n    }\n    var currentMethodBlock = self._outstandingMethodBlocks[0].methods;\n    var m;\n    for (var i = 0; i < currentMethodBlock.length; i++) {\n      m = currentMethodBlock[i];\n      if (m.methodId === msg.id)\n        break;\n    }\n\n    if (!m) {\n      Meteor._debug(\"Can't match method response to original method call\", msg);\n      return;\n    }\n\n    // Remove from current method block. This may leave the block empty, but we\n    // don't move on to the next block until the callback has been delivered, in\n    // _outstandingMethodFinished.\n    currentMethodBlock.splice(i, 1);\n\n    if (_.has(msg, 'error')) {\n      m.receiveResult(new Meteor.Error(\n        msg.error.error, msg.error.reason,\n        msg.error.details));\n    } else {\n      // msg.result may be undefined if the method didn't return a\n      // value\n      m.receiveResult(undefined, msg.result);\n    }\n  },\n\n  // Called by MethodInvoker after a method's callback is invoked.  If this was\n  // the last outstanding method in the current block, runs the next block. If\n  // there are no more methods, consider accepting a hot code push.\n  _outstandingMethodFinished: function () {\n    var self = this;\n    if (self._anyMethodsAreOutstanding())\n      return;\n\n    // No methods are outstanding. This should mean that the first block of\n    // methods is empty. (Or it might not exist, if this was a method that\n    // half-finished before disconnect/reconnect.)\n    if (! _.isEmpty(self._outstandingMethodBlocks)) {\n      var firstBlock = self._outstandingMethodBlocks.shift();\n      if (! _.isEmpty(firstBlock.methods))\n        throw new Error(\"No methods outstanding but nonempty block: \" +\n                        JSON.stringify(firstBlock));\n\n      // Send the outstanding methods now in the first block.\n      if (!_.isEmpty(self._outstandingMethodBlocks))\n        self._sendOutstandingMethods();\n    }\n\n    // Maybe accept a hot code push.\n    self._maybeMigrate();\n  },\n\n  // Sends messages for all the methods in the first block in\n  // _outstandingMethodBlocks.\n  _sendOutstandingMethods: function() {\n    var self = this;\n    if (_.isEmpty(self._outstandingMethodBlocks))\n      return;\n    _.each(self._outstandingMethodBlocks[0].methods, function (m) {\n      m.sendMessage();\n    });\n  },\n\n  _livedata_error: function (msg) {\n    Meteor._debug(\"Received error from server: \", msg.reason);\n    if (msg.offendingMessage)\n      Meteor._debug(\"For: \", msg.offendingMessage);\n  },\n\n  _callOnReconnectAndSendAppropriateOutstandingMethods: function() {\n    var self = this;\n    var oldOutstandingMethodBlocks = self._outstandingMethodBlocks;\n    self._outstandingMethodBlocks = [];\n\n    self.onReconnect();\n\n    if (_.isEmpty(oldOutstandingMethodBlocks))\n      return;\n\n    // We have at least one block worth of old outstanding methods to try\n    // again. First: did onReconnect actually send anything? If not, we just\n    // restore all outstanding methods and run the first block.\n    if (_.isEmpty(self._outstandingMethodBlocks)) {\n      self._outstandingMethodBlocks = oldOutstandingMethodBlocks;\n      self._sendOutstandingMethods();\n      return;\n    }\n\n    // OK, there are blocks on both sides. Special case: merge the last block of\n    // the reconnect methods with the first block of the original methods, if\n    // neither of them are \"wait\" blocks.\n    if (!_.last(self._outstandingMethodBlocks).wait &&\n        !oldOutstandingMethodBlocks[0].wait) {\n      _.each(oldOutstandingMethodBlocks[0].methods, function (m) {\n        _.last(self._outstandingMethodBlocks).methods.push(m);\n\n        // If this \"last block\" is also the first block, send the message.\n        if (self._outstandingMethodBlocks.length === 1)\n          m.sendMessage();\n      });\n\n      oldOutstandingMethodBlocks.shift();\n    }\n\n    // Now add the rest of the original blocks on.\n    _.each(oldOutstandingMethodBlocks, function (block) {\n      self._outstandingMethodBlocks.push(block);\n    });\n  },\n\n  // We can accept a hot code push if there are no methods in flight.\n  _readyToMigrate: function() {\n    var self = this;\n    return _.isEmpty(self._methodInvokers);\n  },\n\n  // If we were blocking a migration, see if it's now possible to continue.\n  // Call whenever the set of outstanding/blocked methods shrinks.\n  _maybeMigrate: function () {\n    var self = this;\n    if (self._retryMigrate && self._readyToMigrate()) {\n      self._retryMigrate();\n      self._retryMigrate = null;\n    }\n  }\n});\n\nLivedataTest.Connection = Connection;\n\n// @param url {String} URL to Meteor app,\n//     e.g.:\n//     \"subdomain.meteor.com\",\n//     \"http://subdomain.meteor.com\",\n//     \"/\",\n//     \"ddp+sockjs://ddp--****-foo.meteor.com/sockjs\"\n\n/**\n * @summary Connect to the server of a different Meteor application to subscribe to its document sets and invoke its remote methods.\n * @locus Anywhere\n * @param {String} url The URL of another Meteor application.\n */\nDDP.connect = function (url, options) {\n  var ret = new Connection(url, options);\n  allConnections.push(ret); // hack. see below.\n  return ret;\n};\n\n// Hack for `spiderable` package: a way to see if the page is done\n// loading all the data it needs.\n//\nallConnections = [];\nDDP._allSubscriptionsReady = function () {\n  return _.all(allConnections, function (conn) {\n    return _.all(conn._subscriptions, function (sub) {\n      return sub.ready;\n    });\n  });\n};\n"
  },
  {
    "path": "packages/ddp-client/livedata_connection_tests.js",
    "content": "import lolex from 'lolex';\n\nvar newConnection = function (stream, options) {\n  // Some of these tests leave outstanding methods with no result yet\n  // returned. This should not block us from re-running tests when sources\n  // change.\n  return new LivedataTest.Connection(stream, _.extend({\n    reloadWithOutstanding: true,\n    bufferedWritesInterval: 0\n  }, options));\n};\n\nvar makeConnectMessage = function (session) {\n  var msg = {\n    msg: 'connect',\n    version: LivedataTest.SUPPORTED_DDP_VERSIONS[0],\n    support: LivedataTest.SUPPORTED_DDP_VERSIONS\n  };\n\n  if (session)\n    msg.session = session;\n  return msg;\n};\n\n// Tests that stream got a message that matches expected.\n// Expected is normally an object, and allows a wildcard value of '*',\n// which will then match any value.\n// Returns the message (parsed as a JSON object if expected is an object);\n// which is particularly handy if you want to extract a value that was\n// matched as a wildcard.\nvar testGotMessage = function (test, stream, expected) {\n  if (stream.sent.length === 0) {\n    test.fail({error: 'no message received', expected: expected});\n    return undefined;\n  }\n\n  var got = stream.sent.shift();\n\n  if (typeof got === 'string' && typeof expected === 'object')\n    got = JSON.parse(got);\n\n  // An expected value of '*' matches any value, and the matching value (or\n  // array of matching values, if there are multiple) is returned from this\n  // function.\n  if (typeof expected === 'object') {\n    var keysWithStarValues = [];\n    _.each(expected, function (v, k) {\n      if (v === '*')\n        keysWithStarValues.push(k);\n    });\n    _.each(keysWithStarValues, function (k) {\n      expected[k] = got[k];\n    });\n  }\n\n  test.equal(got, expected);\n  return got;\n};\n\nvar startAndConnect = function(test, stream) {\n  stream.reset(); // initial connection start.\n\n  testGotMessage(test, stream, makeConnectMessage());\n  test.length(stream.sent, 0);\n\n  stream.receive({msg: 'connected', session: SESSION_ID});\n  test.length(stream.sent, 0);\n};\n\nvar SESSION_ID = '17';\n\nTinytest.add(\"livedata stub - receive data\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n\n  startAndConnect(test, stream);\n\n  // data comes in for unknown collection.\n  var coll_name = Random.id();\n  stream.receive({msg: 'added', collection: coll_name, id: '1234',\n                  fields: {a: 1}});\n  // break throught the black box and test internal state\n  test.length(conn._updatesForUnknownStores[coll_name], 1);\n\n  // XXX: Test that the old signature of passing manager directly instead of in\n  // options works.\n  var coll = new Mongo.Collection(coll_name, conn);\n\n  // queue has been emptied and doc is in db.\n  test.isUndefined(conn._updatesForUnknownStores[coll_name]);\n  test.equal(coll.find({}).fetch(), [{_id:'1234', a:1}]);\n\n  // second message. applied directly to the db.\n  stream.receive({msg: 'changed', collection: coll_name, id: '1234',\n                  fields: {a:2}});\n  test.equal(coll.find({}).fetch(), [{_id:'1234', a:2}]);\n  test.isUndefined(conn._updatesForUnknownStores[coll_name]);\n});\n\nTinytest.add(\"livedata stub - buffering data\", function (test) {\n  // Install special setTimeout that allows tick-by-tick control in tests using sinonjs 'lolex'\n  // This needs to be before the connection is instantiated.\n  const clock = lolex.install();\n  const tick = (timeout) => clock.tick(timeout);\n\n  const stream = new StubStream();\n  const conn = newConnection(stream, {\n    bufferedWritesInterval: 10,\n    bufferedWritesMaxAge: 40,\n  });\n\n  startAndConnect(test, stream);\n\n  const coll_name = Random.id();\n  const coll = new Mongo.Collection(coll_name, conn);\n\n  const testDocCount = (count) => test.equal(coll.find({}).count(), count);\n\n  const addDoc = () => {\n    stream.receive({\n      msg: 'added',\n      collection: coll_name,\n      id: Random.id(),\n      fields: {}\n    });\n  };\n\n  // Starting at 0 ticks.  At this point we haven't advanced the fake clock at all.\n\n  addDoc(); // 1st Doc\n  testDocCount(0);  // No doc been recognized yet because it's buffered, waiting for more.\n  tick(6); // 6 total ticks\n  testDocCount(0); // Ensure that the doc still hasn't shown up, despite the clock moving forward.\n  tick(4) // 10 total ticks, 1st buffer interval\n  testDocCount(1); // No other docs have arrived, so we 'see' the 1st doc.\n\n  addDoc(); // 2nd doc\n  tick(1); // 11 total ticks (1 since last flush)\n  testDocCount(1); // Again, second doc hasn't arrived because we're waiting for more...\n  tick(9); // 20 total ticks (10 ticks since last flush & the 2nd 10-tick interval)\n  testDocCount(2); // Now we're here and got the second document.\n\n  // Add several docs, frequently enough that we buffer multiple times before the next flush.\n  addDoc(); // 3 docs\n  tick(6); // 26 ticks (6 since last flush)\n  addDoc(); // 4 docs\n  tick(6); // 32 ticks (12 since last flush)\n  addDoc(); // 5 docs\n  tick(6); // 38 ticks (18 since last flush)\n  addDoc(); // 6 docs\n  tick(6); // 44 ticks (24 since last flush)\n  addDoc(); // 7 docs\n  tick(9); // 53 ticks (33 since last flush)\n  addDoc(); // 8 docs\n  tick(9); // 62 ticks! (42 ticks since last flush, over max-age - next interval triggers flush)\n  testDocCount(2); // Still at 2 from before! (Just making sure)\n  tick(1); // Ok, 63 ticks (10 since last doc, so this should cause the flush of all the docs)\n  testDocCount(8); // See all the docs.\n\n  // Put things back how they were.\n  clock.uninstall();\n});\n\nTinytest.add(\"livedata stub - subscribe\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n\n  startAndConnect(test, stream);\n\n  // subscribe\n  var callback_fired = false;\n  var sub = conn.subscribe('my_data', function () {\n    callback_fired = true;\n  });\n  test.isFalse(callback_fired);\n\n  test.length(stream.sent, 1);\n  var message = JSON.parse(stream.sent.shift());\n  var id = message.id;\n  delete message.id;\n  test.equal(message, {msg: 'sub', name: 'my_data', params: []});\n\n  var reactivelyReady = false;\n  var autorunHandle = Tracker.autorun(function () {\n    reactivelyReady = sub.ready();\n  });\n  test.isFalse(reactivelyReady);\n\n  // get the sub satisfied. callback fires.\n  stream.receive({msg: 'ready', 'subs': [id]});\n  test.isTrue(callback_fired);\n  Tracker.flush();\n  test.isTrue(reactivelyReady);\n\n  // Unsubscribe.\n  sub.stop();\n  test.length(stream.sent, 1);\n  message = JSON.parse(stream.sent.shift());\n  test.equal(message, {msg: 'unsub', id: id});\n  Tracker.flush();\n  test.isFalse(reactivelyReady);\n\n  // Resubscribe.\n  conn.subscribe('my_data');\n  test.length(stream.sent, 1);\n  message = JSON.parse(stream.sent.shift());\n  var id2 = message.id;\n  test.notEqual(id, id2);\n  delete message.id;\n  test.equal(message, {msg: 'sub', name: 'my_data', params: []});\n});\n\n\nTinytest.add(\"livedata stub - reactive subscribe\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n\n  startAndConnect(test, stream);\n\n  var rFoo = new ReactiveVar('foo1');\n  var rBar = new ReactiveVar('bar1');\n\n  var onReadyCount = {};\n  var onReady = function (tag) {\n    return function () {\n      if (_.has(onReadyCount, tag))\n        ++onReadyCount[tag];\n      else\n        onReadyCount[tag] = 1;\n    };\n  };\n\n  // Subscribe to some subs.\n  var stopperHandle, completerHandle;\n  var autorunHandle = Tracker.autorun(function () {\n    conn.subscribe(\"foo\", rFoo.get(), onReady(rFoo.get()));\n    conn.subscribe(\"bar\", rBar.get(), onReady(rBar.get()));\n    completerHandle = conn.subscribe(\"completer\", onReady(\"completer\"));\n    stopperHandle = conn.subscribe(\"stopper\", onReady(\"stopper\"));\n  });\n\n  var completerReady;\n  var readyAutorunHandle = Tracker.autorun(function() {\n    completerReady = completerHandle.ready();\n  });\n\n  // Check sub messages. (Assume they are sent in the order executed.)\n  test.length(stream.sent, 4);\n  var message = JSON.parse(stream.sent.shift());\n  var idFoo1 = message.id;\n  delete message.id;\n  test.equal(message, {msg: 'sub', name: 'foo', params: ['foo1']});\n\n  message = JSON.parse(stream.sent.shift());\n  var idBar1 = message.id;\n  delete message.id;\n  test.equal(message, {msg: 'sub', name: 'bar', params: ['bar1']});\n\n  message = JSON.parse(stream.sent.shift());\n  var idCompleter = message.id;\n  delete message.id;\n  test.equal(message, {msg: 'sub', name: 'completer', params: []});\n\n  message = JSON.parse(stream.sent.shift());\n  var idStopper = message.id;\n  delete message.id;\n  test.equal(message, {msg: 'sub', name: 'stopper', params: []});\n\n  // Haven't hit onReady yet.\n  test.equal(onReadyCount, {});\n  Tracker.flush();\n  test.isFalse(completerReady);\n\n  // \"completer\" gets ready now. its callback should fire.\n  stream.receive({msg: 'ready', 'subs': [idCompleter]});\n  test.equal(onReadyCount, {completer: 1});\n  test.length(stream.sent, 0);\n  Tracker.flush();\n  test.isTrue(completerReady);\n\n  // Stop 'stopper'.\n  stopperHandle.stop();\n  test.length(stream.sent, 1);\n  message = JSON.parse(stream.sent.shift());\n  test.equal(message, {msg: 'unsub', id: idStopper});\n\n  test.equal(onReadyCount, {completer: 1});\n  Tracker.flush();\n  test.isTrue(completerReady);\n\n  // Change the foo subscription and flush. We should sub to the new foo\n  // subscription, re-sub to the stopper subscription, and then unsub from the old\n  // foo subscription.  The bar subscription should be unaffected. The completer\n  // subscription should *NOT* call its new onReady callback, because we only\n  // call at most one onReady for a given reactively-saved subscription.\n  // The completerHandle should have been reestablished to the ready handle.\n  rFoo.set(\"foo2\");\n  Tracker.flush();\n  test.length(stream.sent, 3);\n\n  message = JSON.parse(stream.sent.shift());\n  var idFoo2 = message.id;\n  delete message.id;\n  test.equal(message, {msg: 'sub', name: 'foo', params: ['foo2']});\n\n  message = JSON.parse(stream.sent.shift());\n  var idStopperAgain = message.id;\n  delete message.id;\n  test.equal(message, {msg: 'sub', name: 'stopper', params: []});\n\n  message = JSON.parse(stream.sent.shift());\n  test.equal(message, {msg: 'unsub', id: idFoo1});\n\n  test.equal(onReadyCount, {completer: 1});\n  test.isTrue(completerReady);\n\n  // Ready the stopper and bar subs. Completing stopper should call only the\n  // onReady from the new subscription because they were separate subscriptions\n  // started at different times and the first one was explicitly torn down by\n  // the client; completing bar should call only the onReady from the new\n  // subscription because we only call at most one onReady per reactively-saved\n  // subscription.\n  stream.receive({msg: 'ready', 'subs': [idStopperAgain, idBar1]});\n  test.equal(onReadyCount, {completer: 1, bar1: 1, stopper: 1});\n\n  // Shut down the autorun. This should unsub us from all current subs at flush\n  // time.\n  autorunHandle.stop();\n  Tracker.flush();\n  test.isFalse(completerReady);\n  readyAutorunHandle.stop();\n\n  test.length(stream.sent, 4);\n  // The order of unsubs here is not important.\n  var unsubMessages = _.map(stream.sent, JSON.parse);\n  stream.sent.length = 0;\n  test.equal(_.unique(_.pluck(unsubMessages, 'msg')), ['unsub']);\n  var actualIds = _.pluck(unsubMessages, 'id');\n  var expectedIds = [idFoo2, idBar1, idCompleter, idStopperAgain];\n  actualIds.sort();\n  expectedIds.sort();\n  test.equal(actualIds, expectedIds);\n});\n\nTinytest.add(\"livedata stub - reactive subscribe handle correct\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n\n  startAndConnect(test, stream);\n\n  var rFoo = new ReactiveVar('foo1');\n\n  // Subscribe to some subs.\n  var fooHandle, fooReady;\n  var autorunHandle = Tracker.autorun(function () {\n    fooHandle = conn.subscribe(\"foo\", rFoo.get());\n    Tracker.autorun(function() {\n      fooReady = fooHandle.ready();\n    });\n  });\n\n  var message = JSON.parse(stream.sent.shift());\n  var idFoo1 = message.id;\n  delete message.id;\n  test.equal(message, {msg: 'sub', name: 'foo', params: ['foo1']});\n\n  // Not ready yet\n  Tracker.flush();\n  test.isFalse(fooHandle.ready());\n  test.isFalse(fooReady);\n\n  // change the argument to foo. This will make a new handle, which isn't ready\n  // the ready autorun should invalidate, reading the new false value, and\n  // setting up a new dep which goes true soon\n  rFoo.set(\"foo2\");\n  Tracker.flush();\n  test.length(stream.sent, 2);\n\n  message = JSON.parse(stream.sent.shift());\n  var idFoo2 = message.id;\n  delete message.id;\n  test.equal(message, {msg: 'sub', name: 'foo', params: ['foo2']});\n\n  message = JSON.parse(stream.sent.shift());\n  test.equal(message, {msg: 'unsub', id: idFoo1});\n\n  Tracker.flush();\n  test.isFalse(fooHandle.ready());\n  test.isFalse(fooReady);\n\n  // \"foo\" gets ready now. The handle should be ready and the autorun rerun\n  stream.receive({msg: 'ready', 'subs': [idFoo2]});\n  test.length(stream.sent, 0);\n  Tracker.flush();\n  test.isTrue(fooHandle.ready());\n  test.isTrue(fooReady);\n\n  // change the argument to foo. This will make a new handle, which isn't ready\n  // the ready autorun should invalidate, making fooReady false too\n  rFoo.set(\"foo3\");\n  Tracker.flush();\n  test.length(stream.sent, 2);\n\n  message = JSON.parse(stream.sent.shift());\n  var idFoo3 = message.id;\n  delete message.id;\n  test.equal(message, {msg: 'sub', name: 'foo', params: ['foo3']});\n\n  message = JSON.parse(stream.sent.shift());\n  test.equal(message, {msg: 'unsub', id: idFoo2});\n\n  Tracker.flush();\n  test.isFalse(fooHandle.ready());\n  test.isFalse(fooReady);\n\n  // \"foo\" gets ready again\n  stream.receive({msg: 'ready', 'subs': [idFoo3]});\n  test.length(stream.sent, 0);\n  Tracker.flush();\n  test.isTrue(fooHandle.ready());\n  test.isTrue(fooReady);\n\n  autorunHandle.stop();\n});\n\nTinytest.add(\"livedata stub - this\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n\n  startAndConnect(test, stream);\n  conn.methods({test_this: function() {\n    test.isTrue(this.isSimulation);\n    this.unblock(); // should be a no-op\n  }});\n\n  // should throw no exceptions\n  conn.call('test_this', _.identity);\n  // satisfy method, quiesce connection\n  var message = JSON.parse(stream.sent.shift());\n  test.isUndefined(message.randomSeed);\n  test.equal(message, {msg: 'method', method: 'test_this',\n                       params: [], id:message.id});\n  test.length(stream.sent, 0);\n\n  stream.receive({msg: 'result', id:message.id, result:null});\n  stream.receive({msg: 'updated', 'methods': [message.id]});\n\n});\n\nif (Meteor.isClient) {\n  Tinytest.add(\"livedata stub - methods\", function (test) {\n    var stream = new StubStream();\n    var conn = newConnection(stream);\n\n    startAndConnect(test, stream);\n\n    var collName = Random.id();\n    var coll = new Mongo.Collection(collName, {connection: conn});\n\n    // setup method\n    conn.methods({do_something: function (x) {\n      coll.insert({value: x});\n    }});\n\n    // setup observers\n    var counts = {added: 0, removed: 0, changed: 0, moved: 0};\n    var handle = coll.find({}).observe(\n      { addedAt: function () { counts.added += 1; },\n        removedAt: function () { counts.removed += 1; },\n        changedAt: function () { counts.changed += 1; },\n        movedTo: function () { counts.moved += 1; }\n      });\n\n\n    // call method with results callback\n    var callback1Fired = false;\n    conn.call('do_something', 'friday!', function (err, res) {\n      test.isUndefined(err);\n      test.equal(res, '1234');\n      callback1Fired = true;\n    });\n    test.isFalse(callback1Fired);\n\n    // observers saw the method run.\n    test.equal(counts, {added: 1, removed: 0, changed: 0, moved: 0});\n\n    // get response from server\n    var message = testGotMessage(test, stream, {msg: 'method',\n                                                method: 'do_something',\n                                                params: ['friday!'],\n                                                id: '*',\n                                                randomSeed: '*'});\n\n    test.equal(coll.find({}).count(), 1);\n    test.equal(coll.find({value: 'friday!'}).count(), 1);\n    var docId = coll.findOne({value: 'friday!'})._id;\n\n    // results does not yet result in callback, because data is not\n    // ready.\n    stream.receive({msg: 'result', id:message.id, result: \"1234\"});\n    test.isFalse(callback1Fired);\n\n    // result message doesn't affect data\n    test.equal(coll.find({}).count(), 1);\n    test.equal(coll.find({value: 'friday!'}).count(), 1);\n    test.equal(counts, {added: 1, removed: 0, changed: 0, moved: 0});\n\n    // data methods do not show up (not quiescent yet)\n    stream.receive({msg: 'added', collection: collName, id: MongoID.idStringify(docId),\n                    fields: {value: 'tuesday'}});\n    test.equal(coll.find({}).count(), 1);\n    test.equal(coll.find({value: 'friday!'}).count(), 1);\n    test.equal(counts, {added: 1, removed: 0, changed: 0, moved: 0});\n\n    // send another methods (unknown on client)\n    var callback2Fired = false;\n    conn.call('do_something_else', 'monday', function (err, res) {\n      callback2Fired = true;\n    });\n    test.isFalse(callback1Fired);\n    test.isFalse(callback2Fired);\n\n    // test we still send a method request to server\n    var message2 = JSON.parse(stream.sent.shift());\n    test.isUndefined(message2.randomSeed);\n    test.equal(message2, {msg: 'method', method: 'do_something_else',\n                          params: ['monday'], id: message2.id});\n\n    // get the first data satisfied message. changes are applied to database even\n    // though another method is outstanding, because the other method didn't have\n    // a stub. and its callback is called.\n    stream.receive({msg: 'updated', 'methods': [message.id]});\n    test.isTrue(callback1Fired);\n    test.isFalse(callback2Fired);\n\n    test.equal(coll.find({}).count(), 1);\n    test.equal(coll.find({value: 'tuesday'}).count(), 1);\n    test.equal(counts, {added: 1, removed: 0, changed: 1, moved: 0});\n\n    // second result\n    stream.receive({msg: 'result', id:message2.id, result:\"bupkis\"});\n    test.isFalse(callback2Fired);\n\n    // get second satisfied; no new changes are applied.\n    stream.receive({msg: 'updated', 'methods': [message2.id]});\n    test.isTrue(callback2Fired);\n\n    test.equal(coll.find({}).count(), 1);\n    test.equal(coll.find({value: 'tuesday', _id: docId}).count(), 1);\n    test.equal(counts, {added: 1, removed: 0, changed: 1, moved: 0});\n\n    handle.stop();\n  });\n}\n\nTinytest.add(\"livedata stub - mutating method args\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n\n  startAndConnect(test, stream);\n\n  conn.methods({mutateArgs: function (arg) {\n    arg.foo = 42;\n  }});\n\n  conn.call('mutateArgs', {foo: 50}, _.identity);\n\n  // Method should be called with original arg, not mutated arg.\n  var message = JSON.parse(stream.sent.shift());\n  test.isUndefined(message.randomSeed);\n  test.equal(message, {msg: 'method', method: 'mutateArgs',\n                       params: [{foo: 50}], id: message.id});\n  test.length(stream.sent, 0);\n});\n\nvar observeCursor = function (test, cursor) {\n  var counts = {added: 0, removed: 0, changed: 0, moved: 0};\n  var expectedCounts = _.clone(counts);\n  var handle = cursor.observe(\n    { addedAt: function () { counts.added += 1; },\n      removedAt: function () { counts.removed += 1; },\n      changedAt: function () { counts.changed += 1; },\n      movedTo: function () { counts.moved += 1; }\n    });\n  return {\n    stop: _.bind(handle.stop, handle),\n    expectCallbacks: function (delta) {\n      _.each(delta, function (mod, field) {\n        expectedCounts[field] += mod;\n      });\n      test.equal(counts, expectedCounts);\n    }\n  };\n};\n\n// method calls another method in simulation. see not sent.\nif (Meteor.isClient) {\n  Tinytest.add(\"livedata stub - methods calling methods\", function (test) {\n    var stream = new StubStream();\n    var conn = newConnection(stream);\n\n    startAndConnect(test, stream);\n\n    var coll_name = Random.id();\n    var coll = new Mongo.Collection(coll_name, {connection: conn});\n\n    // setup methods\n    conn.methods({\n      do_something: function () {\n        conn.call('do_something_else');\n      },\n      do_something_else: function () {\n        coll.insert({a: 1});\n      }\n    });\n\n    var o = observeCursor(test, coll.find());\n\n    // call method.\n    conn.call('do_something', _.identity);\n\n    // see we only send message for outer methods\n    var message = testGotMessage(test, stream, {msg: 'method',\n                                                method: 'do_something',\n                                                params: [],\n                                                id: '*',\n                                                randomSeed: '*'});\n    test.length(stream.sent, 0);\n\n    // but inner method runs locally.\n    o.expectCallbacks({added: 1});\n    test.equal(coll.find().count(), 1);\n    var docId = coll.findOne()._id;\n    test.equal(coll.findOne(), {_id: docId, a: 1});\n\n    // we get the results\n    stream.receive({msg: 'result', id:message.id, result:\"1234\"});\n\n    // get data from the method. data from this doc does not show up yet, but data\n    // from another doc does.\n    stream.receive({msg: 'added', collection: coll_name, id: MongoID.idStringify(docId),\n                    fields: {value: 'tuesday'}});\n    o.expectCallbacks();\n    test.equal(coll.findOne(docId), {_id: docId, a: 1});\n    stream.receive({msg: 'added', collection: coll_name, id: 'monkey',\n                    fields: {value: 'bla'}});\n    o.expectCallbacks({added: 1});\n    test.equal(coll.findOne(docId), {_id: docId, a: 1});\n    var newDoc = coll.findOne({value: 'bla'});\n    test.isTrue(newDoc);\n    test.equal(newDoc, {_id: newDoc._id, value: 'bla'});\n\n    // get method satisfied. all data shows up. the 'a' field is reverted and\n    // 'value' field is set.\n    stream.receive({msg: 'updated', 'methods': [message.id]});\n    o.expectCallbacks({changed: 1});\n    test.equal(coll.findOne(docId), {_id: docId, value: 'tuesday'});\n    test.equal(coll.findOne(newDoc._id), {_id: newDoc._id, value: 'bla'});\n\n    o.stop();\n  });\n}\nTinytest.add(\"livedata stub - method call before connect\", function (test) {\n  var stream = new StubStream;\n  var conn = newConnection(stream);\n\n  var callbackOutput = [];\n  conn.call('someMethod', function (err, result) {\n    callbackOutput.push(result);\n  });\n  test.equal(callbackOutput, []);\n\n  // the real stream drops all output pre-connection\n  stream.sent.length = 0;\n\n  // Now connect.\n  stream.reset();\n\n  testGotMessage(test, stream, makeConnectMessage());\n  testGotMessage(test, stream, {msg: 'method', method: 'someMethod',\n                                params: [], id: '*'});\n});\n\nTinytest.add(\"livedata stub - reconnect\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n\n  startAndConnect(test, stream);\n\n  var collName = Random.id();\n  var coll = new Mongo.Collection(collName, {connection: conn});\n\n  var o = observeCursor(test, coll.find());\n\n  // subscribe\n  var subCallbackFired = false;\n  var sub = conn.subscribe('my_data', function () {\n    subCallbackFired = true;\n  });\n  test.isFalse(subCallbackFired);\n\n  var subMessage = JSON.parse(stream.sent.shift());\n  test.equal(subMessage, {msg: 'sub', name: 'my_data', params: [],\n                          id: subMessage.id});\n\n  // get some data. it shows up.\n  stream.receive({msg: 'added', collection: collName,\n                  id: '1234', fields: {a:1}});\n\n  test.equal(coll.find({}).count(), 1);\n  o.expectCallbacks({added: 1});\n  test.isFalse(subCallbackFired);\n\n  stream.receive({msg: 'changed', collection: collName,\n                  id: '1234', fields: {b:2}});\n  stream.receive({msg: 'ready',\n                  subs: [subMessage.id] // satisfy sub\n                 });\n  test.isTrue(subCallbackFired);\n  subCallbackFired = false; // re-arm for test that it doesn't fire again.\n\n  test.equal(coll.find({a:1, b:2}).count(), 1);\n  o.expectCallbacks({changed: 1});\n\n  // call method.\n  var methodCallbackFired = false;\n  conn.call('do_something', function () {\n    methodCallbackFired = true;\n  });\n\n  conn.apply('do_something_else', [], {wait: true}, _.identity);\n  conn.apply('do_something_later', [], _.identity);\n\n  test.isFalse(methodCallbackFired);\n\n  // The non-wait method should send, but not the wait method.\n  var methodMessage = JSON.parse(stream.sent.shift());\n  test.isUndefined(methodMessage.randomSeed);\n  test.equal(methodMessage, {msg: 'method', method: 'do_something',\n                             params: [], id:methodMessage.id});\n  test.equal(stream.sent.length, 0);\n\n  // more data. shows up immediately because there was no relevant method stub.\n  stream.receive({msg: 'changed', collection: collName,\n                  id: '1234', fields: {c:3}});\n  test.equal(coll.findOne('1234'), {_id: '1234', a: 1, b: 2, c: 3});\n  o.expectCallbacks({changed: 1});\n\n  // stream reset. reconnect!  we send a connect, our pending method, and our\n  // sub. The wait method still is blocked.\n  stream.reset();\n\n  testGotMessage(test, stream, makeConnectMessage(SESSION_ID));\n  testGotMessage(test, stream, methodMessage);\n  testGotMessage(test, stream, subMessage);\n\n  // reconnect with different session id\n  stream.receive({msg: 'connected', session: SESSION_ID + 1});\n\n  // resend data. doesn't show up: we're in reconnect quiescence.\n  stream.receive({msg: 'added', collection: collName,\n                  id: '1234', fields: {a:1, b:2, c:3, d: 4}});\n  stream.receive({msg: 'added', collection: collName,\n                  id: '2345', fields: {e: 5}});\n  test.equal(coll.findOne('1234'), {_id: '1234', a: 1, b: 2, c: 3});\n  test.isFalse(coll.findOne('2345'));\n  o.expectCallbacks();\n\n  // satisfy and return the method\n  stream.receive({msg: 'updated',\n                  methods: [methodMessage.id]});\n  test.isFalse(methodCallbackFired);\n  stream.receive({msg: 'result', id:methodMessage.id, result:\"bupkis\"});\n  // The callback still doesn't fire (and we don't send the wait method): we're\n  // still in global quiescence\n  test.isFalse(methodCallbackFired);\n  test.equal(stream.sent.length, 0);\n\n  // still no update.\n  test.equal(coll.findOne('1234'), {_id: '1234', a: 1, b: 2, c: 3});\n  test.isFalse(coll.findOne('2345'));\n  o.expectCallbacks();\n\n  // re-satisfy sub\n  stream.receive({msg: 'ready', subs: [subMessage.id]});\n\n  // now the doc changes and method callback is called, and the wait method is\n  // sent. the sub callback isn't re-called.\n  test.isTrue(methodCallbackFired);\n  test.isFalse(subCallbackFired);\n  test.equal(coll.findOne('1234'), {_id: '1234', a: 1, b: 2, c: 3, d: 4});\n  test.equal(coll.findOne('2345'), {_id: '2345', e: 5});\n  o.expectCallbacks({added: 1, changed: 1});\n\n  var waitMethodMessage = JSON.parse(stream.sent.shift());\n  test.isUndefined(waitMethodMessage.randomSeed);\n  test.equal(waitMethodMessage, {msg: 'method', method: 'do_something_else',\n                                 params: [], id: waitMethodMessage.id});\n  test.equal(stream.sent.length, 0);\n  stream.receive({msg: 'result', id: waitMethodMessage.id, result: \"bupkis\"});\n  test.equal(stream.sent.length, 0);\n  stream.receive({msg: 'updated', methods: [waitMethodMessage.id]});\n\n  // wait method done means we can send the third method\n  test.equal(stream.sent.length, 1);\n  var laterMethodMessage = JSON.parse(stream.sent.shift());\n  test.isUndefined(laterMethodMessage.randomSeed);\n  test.equal(laterMethodMessage, {msg: 'method', method: 'do_something_later',\n                                  params: [], id: laterMethodMessage.id});\n\n  o.stop();\n});\n\nif (Meteor.isClient) {\n  Tinytest.add(\"livedata stub - reconnect non-idempotent method\", function(test) {\n    // This test is for https://github.com/meteor/meteor/issues/6108\n    var stream = new StubStream();\n    var conn = newConnection(stream);\n\n    startAndConnect(test, stream);\n\n    var methodCallbackFired = false;\n    var methodCallbackErrored = false;\n    // call with noRetry true so that the method should fail to retry on reconnect.\n    conn.apply('do_something', [], {noRetry: true}, function(error) {\n      methodCallbackFired = true;\n      // failure on reconnect should trigger an error.\n      if (error && error.error === 'invocation-failed') {\n        methodCallbackErrored = true;\n      }\n    });\n\n    //The method has not succeeded yet\n    test.isFalse(methodCallbackFired);\n    // reconnect.\n    stream.sent.shift();\n    // \"receive the message\"\n    stream.reset();\n\n    // verify that a reconnect message was sent.\n    testGotMessage(test, stream, makeConnectMessage(SESSION_ID));\n\n    // Make sure that the stream triggers connection.\n    stream.receive({msg: 'connected', session: SESSION_ID + 1});\n\n    //The method callback should fire even though the stream has not sent a response.\n    //the callback should have been fired with an error.\n    test.isTrue(methodCallbackFired);\n    test.isTrue(methodCallbackErrored);\n\n    // verify that the method message was not sent.\n    test.isUndefined(stream.sent.shift());\n  });\n}\n\nif (Meteor.isClient) {\n  Tinytest.add(\"livedata stub - reconnect method which only got result\", function (test) {\n    var stream = new StubStream;\n    var conn = newConnection(stream);\n    startAndConnect(test, stream);\n\n    var collName = Random.id();\n    var coll = new Mongo.Collection(collName, {connection: conn});\n    var o = observeCursor(test, coll.find());\n\n    conn.methods({writeSomething: function () {\n      // stub write\n      coll.insert({foo: 'bar'});\n    }});\n\n    test.equal(coll.find({foo: 'bar'}).count(), 0);\n\n    // Call a method. We'll get the result but not data-done before reconnect.\n    var callbackOutput = [];\n    var onResultReceivedOutput = [];\n    conn.apply('writeSomething', [],\n               {onResultReceived: function (err, result) {\n                 onResultReceivedOutput.push(result);\n               }},\n               function (err, result) {\n                 callbackOutput.push(result);\n               });\n    // Stub write is visible.\n    test.equal(coll.find({foo: 'bar'}).count(), 1);\n    var stubWrittenId = coll.findOne({foo: 'bar'})._id;\n    o.expectCallbacks({added: 1});\n    // Callback not called.\n    test.equal(callbackOutput, []);\n    test.equal(onResultReceivedOutput, []);\n    // Method sent.\n    var methodId = testGotMessage(\n      test, stream, {msg: 'method', method: 'writeSomething',\n                     params: [], id: '*', randomSeed: '*'}).id;\n    test.equal(stream.sent.length, 0);\n\n    // Get some data.\n    stream.receive({msg: 'added', collection: collName,\n                    id: MongoID.idStringify(stubWrittenId), fields: {baz: 42}});\n    // It doesn't show up yet.\n    test.equal(coll.find().count(), 1);\n    test.equal(coll.findOne(stubWrittenId), {_id: stubWrittenId, foo: 'bar'});\n    o.expectCallbacks();\n\n    // Get the result.\n    stream.receive({msg: 'result', id: methodId, result: 'bla'});\n    // Data unaffected.\n    test.equal(coll.find().count(), 1);\n    test.equal(coll.findOne(stubWrittenId), {_id: stubWrittenId, foo: 'bar'});\n    o.expectCallbacks();\n    // Callback not called, but onResultReceived is.\n    test.equal(callbackOutput, []);\n    test.equal(onResultReceivedOutput, ['bla']);\n\n    // Reset stream. Method does NOT get resent, because its result is already\n    // in. Reconnect quiescence happens as soon as 'connected' is received because\n    // there are no pending methods or subs in need of revival.\n    stream.reset();\n    testGotMessage(test, stream, makeConnectMessage(SESSION_ID));\n    // Still holding out hope for session resumption, so nothing updated yet.\n    test.equal(coll.find().count(), 1);\n    test.equal(coll.findOne(stubWrittenId), {_id: stubWrittenId, foo: 'bar'});\n    o.expectCallbacks();\n    test.equal(callbackOutput, []);\n\n    // Receive 'connected': time for reconnect quiescence! Data gets updated\n    // locally (ie, data is reset) and callback gets called.\n    stream.receive({msg: 'connected', session: SESSION_ID + 1});\n    test.equal(coll.find().count(), 0);\n    o.expectCallbacks({removed: 1});\n    test.equal(callbackOutput, ['bla']);\n    test.equal(onResultReceivedOutput, ['bla']);\n    stream.receive({msg: 'added', collection: collName,\n                    id: MongoID.idStringify(stubWrittenId), fields: {baz: 42}});\n    test.equal(coll.findOne(stubWrittenId), {_id: stubWrittenId, baz: 42});\n    o.expectCallbacks({added: 1});\n\n\n\n\n    // Run method again. We're going to do the same thing this time, except we're\n    // also going to use an onReconnect to insert another method at reconnect\n    // time, which will delay reconnect quiescence.\n    conn.apply('writeSomething', [],\n               {onResultReceived: function (err, result) {\n                 onResultReceivedOutput.push(result);\n               }},\n               function (err, result) {\n                 callbackOutput.push(result);\n               });\n    // Stub write is visible.\n    test.equal(coll.find({foo: 'bar'}).count(), 1);\n    var stubWrittenId2 = coll.findOne({foo: 'bar'})._id;\n    o.expectCallbacks({added: 1});\n    // Callback not called.\n    test.equal(callbackOutput, ['bla']);\n    test.equal(onResultReceivedOutput, ['bla']);\n    // Method sent.\n    var methodId2 = testGotMessage(\n      test, stream, {msg: 'method', method: 'writeSomething',\n                     params: [], id: '*', randomSeed: '*'}).id;\n    test.equal(stream.sent.length, 0);\n\n    // Get some data.\n    stream.receive({msg: 'added', collection: collName,\n                    id: MongoID.idStringify(stubWrittenId2), fields: {baz: 42}});\n    // It doesn't show up yet.\n    test.equal(coll.find().count(), 2);\n    test.equal(coll.findOne(stubWrittenId2), {_id: stubWrittenId2, foo: 'bar'});\n    o.expectCallbacks();\n\n    // Get the result.\n    stream.receive({msg: 'result', id: methodId2, result: 'blab'});\n    // Data unaffected.\n    test.equal(coll.find().count(), 2);\n    test.equal(coll.findOne(stubWrittenId2), {_id: stubWrittenId2, foo: 'bar'});\n    o.expectCallbacks();\n    // Callback not called, but onResultReceived is.\n    test.equal(callbackOutput, ['bla']);\n    test.equal(onResultReceivedOutput, ['bla', 'blab']);\n    conn.onReconnect = function () {\n      conn.call('slowMethod', function (err, result) {\n        callbackOutput.push(result);\n      });\n    };\n\n    // Reset stream. Method does NOT get resent, because its result is already in,\n    // but slowMethod gets called via onReconnect. Reconnect quiescence is now\n    // blocking on slowMethod.\n    stream.reset();\n    testGotMessage(test, stream, makeConnectMessage(SESSION_ID + 1));\n    var slowMethodId = testGotMessage(\n      test, stream,\n      {msg: 'method', method: 'slowMethod', params: [], id: '*'}).id;\n    // Still holding out hope for session resumption, so nothing updated yet.\n    test.equal(coll.find().count(), 2);\n    test.equal(coll.findOne(stubWrittenId2), {_id: stubWrittenId2, foo: 'bar'});\n    o.expectCallbacks();\n    test.equal(callbackOutput, ['bla']);\n\n    // Receive 'connected'... but no reconnect quiescence yet due to slowMethod.\n    stream.receive({msg: 'connected', session: SESSION_ID + 2});\n    test.equal(coll.find().count(), 2);\n    test.equal(coll.findOne(stubWrittenId2), {_id: stubWrittenId2, foo: 'bar'});\n    o.expectCallbacks();\n    test.equal(callbackOutput, ['bla']);\n\n    // Receive data matching our stub. It doesn't take effect yet.\n    stream.receive({msg: 'added', collection: collName,\n                    id: MongoID.idStringify(stubWrittenId2), fields: {foo: 'bar'}});\n    o.expectCallbacks();\n\n    // slowMethod is done writing, so we get full reconnect quiescence (but no\n    // slowMethod callback)... ie, a reset followed by applying the data we just\n    // got, as well as calling the callback from the method that half-finished\n    // before reset. The net effect is deleting doc 'stubWrittenId'.\n    stream.receive({msg: 'updated', methods: [slowMethodId]});\n    test.equal(coll.find().count(), 1);\n    test.equal(coll.findOne(stubWrittenId2), {_id: stubWrittenId2, foo: 'bar'});\n    o.expectCallbacks({removed: 1});\n    test.equal(callbackOutput, ['bla', 'blab']);\n\n    // slowMethod returns a value now.\n    stream.receive({msg: 'result', id: slowMethodId, result: 'slow'});\n    o.expectCallbacks();\n    test.equal(callbackOutput, ['bla', 'blab', 'slow']);\n\n    o.stop();\n  });\n}\nTinytest.add(\"livedata stub - reconnect method which only got data\", function (test) {\n  var stream = new StubStream;\n  var conn = newConnection(stream);\n  startAndConnect(test, stream);\n\n  var collName = Random.id();\n  var coll = new Mongo.Collection(collName, {connection: conn});\n  var o = observeCursor(test, coll.find());\n\n  // Call a method. We'll get the data-done message but not the result before\n  // reconnect.\n  var callbackOutput = [];\n  var onResultReceivedOutput = [];\n  conn.apply('doLittle', [],\n             {onResultReceived: function (err, result) {\n               onResultReceivedOutput.push(result);\n             }},\n             function (err, result) {\n               callbackOutput.push(result);\n             });\n  // Callbacks not called.\n  test.equal(callbackOutput, []);\n  test.equal(onResultReceivedOutput, []);\n  // Method sent.\n  var methodId = testGotMessage(\n    test, stream, {msg: 'method', method: 'doLittle',\n                   params: [], id: '*'}).id;\n  test.equal(stream.sent.length, 0);\n\n  // Get some data.\n  stream.receive({msg: 'added', collection: collName,\n                  id: 'photo', fields: {baz: 42}});\n  // It shows up instantly because the stub didn't write anything.\n  test.equal(coll.find().count(), 1);\n  test.equal(coll.findOne('photo'), {_id: 'photo', baz: 42});\n  o.expectCallbacks({added: 1});\n\n  // Get the data-done message.\n  stream.receive({msg: 'updated', methods: [methodId]});\n  // Data still here.\n  test.equal(coll.find().count(), 1);\n  test.equal(coll.findOne('photo'), {_id: 'photo', baz: 42});\n  o.expectCallbacks();\n  // Method callback not called yet (no result yet).\n  test.equal(callbackOutput, []);\n  test.equal(onResultReceivedOutput, []);\n\n  // Reset stream. Method gets resent (with same ID), and blocks reconnect\n  // quiescence.\n  stream.reset();\n  testGotMessage(test, stream, makeConnectMessage(SESSION_ID));\n  testGotMessage(\n    test, stream, {msg: 'method', method: 'doLittle',\n                   params: [], id: methodId});\n  // Still holding out hope for session resumption, so nothing updated yet.\n  test.equal(coll.find().count(), 1);\n  test.equal(coll.findOne('photo'), {_id: 'photo', baz: 42});\n  o.expectCallbacks();\n  test.equal(callbackOutput, []);\n  test.equal(onResultReceivedOutput, []);\n\n  // Receive 'connected'. Still blocking on reconnect quiescence.\n  stream.receive({msg: 'connected', session: SESSION_ID + 1});\n  test.equal(coll.find().count(), 1);\n  test.equal(coll.findOne('photo'), {_id: 'photo', baz: 42});\n  o.expectCallbacks();\n  test.equal(callbackOutput, []);\n  test.equal(onResultReceivedOutput, []);\n\n  // Receive method result. onResultReceived is called but the main callback\n  // isn't (ie, we don't get confused by the fact that we got data-done the\n  // *FIRST* time through).\n  stream.receive({msg: 'result', id: methodId, result: 'res'});\n  test.equal(callbackOutput, []);\n  test.equal(onResultReceivedOutput, ['res']);\n\n  // Now we get data-done. Collection is reset and callback is called.\n  stream.receive({msg: 'updated', methods: [methodId]});\n  test.equal(coll.find().count(), 0);\n  o.expectCallbacks({removed: 1});\n  test.equal(callbackOutput, ['res']);\n  test.equal(onResultReceivedOutput, ['res']);\n\n  o.stop();\n});\nif (Meteor.isClient) {\n  Tinytest.add(\"livedata stub - multiple stubs same doc\", function (test) {\n    var stream = new StubStream;\n    var conn = newConnection(stream);\n    startAndConnect(test, stream);\n\n    var collName = Random.id();\n    var coll = new Mongo.Collection(collName, {connection: conn});\n    var o = observeCursor(test, coll.find());\n\n    conn.methods({\n      insertSomething: function () {\n        // stub write\n        coll.insert({foo: 'bar'});\n      },\n      updateIt: function (id) {\n        coll.update(id, {$set: {baz: 42}});\n      }\n    });\n\n    test.equal(coll.find().count(), 0);\n\n    // Call the insert method.\n    conn.call('insertSomething', _.identity);\n    // Stub write is visible.\n    test.equal(coll.find({foo: 'bar'}).count(), 1);\n    var stubWrittenId = coll.findOne({foo: 'bar'})._id;\n    o.expectCallbacks({added: 1});\n    // Method sent.\n    var insertMethodId = testGotMessage(\n      test, stream, {msg: 'method', method: 'insertSomething',\n                     params: [], id: '*', randomSeed: '*'}).id;\n    test.equal(stream.sent.length, 0);\n\n    // Call update method.\n    conn.call('updateIt', stubWrittenId, _.identity);\n    // This stub write is visible too.\n    test.equal(coll.find().count(), 1);\n    test.equal(coll.findOne(stubWrittenId),\n               {_id: stubWrittenId, foo: 'bar', baz: 42});\n    o.expectCallbacks({changed: 1});\n    // Method sent.\n    var updateMethodId = testGotMessage(\n      test, stream, {msg: 'method', method: 'updateIt',\n                     params: [stubWrittenId], id: '*'}).id;\n    test.equal(stream.sent.length, 0);\n\n    // Get some data... slightly different than what we wrote.\n    stream.receive({msg: 'added', collection: collName,\n                    id: MongoID.idStringify(stubWrittenId), fields: {foo: 'barb', other: 'field',\n                                                                    other2: 'bla'}});\n    // It doesn't show up yet.\n    test.equal(coll.find().count(), 1);\n    test.equal(coll.findOne(stubWrittenId),\n               {_id: stubWrittenId, foo: 'bar', baz: 42});\n    o.expectCallbacks();\n\n    // And get the first method-done. Still no updates to minimongo: we can't\n    // quiesce the doc until the second method is done.\n    stream.receive({msg: 'updated', methods: [insertMethodId]});\n    test.equal(coll.find().count(), 1);\n    test.equal(coll.findOne(stubWrittenId),\n               {_id: stubWrittenId, foo: 'bar', baz: 42});\n    o.expectCallbacks();\n\n    // More data. Not quite what we wrote. Also ignored for now.\n    stream.receive({msg: 'changed', collection: collName,\n                    id: MongoID.idStringify(stubWrittenId), fields: {baz: 43}, cleared: ['other']});\n    test.equal(coll.find().count(), 1);\n    test.equal(coll.findOne(stubWrittenId),\n               {_id: stubWrittenId, foo: 'bar', baz: 42});\n    o.expectCallbacks();\n\n    // Second data-ready. Now everything takes effect!\n    stream.receive({msg: 'updated', methods: [updateMethodId]});\n    test.equal(coll.find().count(), 1);\n    test.equal(coll.findOne(stubWrittenId),\n               {_id: stubWrittenId, foo: 'barb', other2: 'bla',\n                baz: 43});\n    o.expectCallbacks({changed: 1});\n\n    o.stop();\n  });\n}\n\nif (Meteor.isClient) {\n  Tinytest.add(\"livedata stub - unsent methods don't block quiescence\", function (test) {\n    // This test is for https://github.com/meteor/meteor/issues/555\n\n    var stream = new StubStream;\n    var conn = newConnection(stream);\n    startAndConnect(test, stream);\n\n    var collName = Random.id();\n    var coll = new Mongo.Collection(collName, {connection: conn});\n\n    conn.methods({\n      insertSomething: function () {\n        // stub write\n        coll.insert({foo: 'bar'});\n      }\n    });\n\n    test.equal(coll.find().count(), 0);\n\n    // Call a random method (no-op)\n    conn.call('no-op', _.identity);\n    // Call a wait method\n    conn.apply('no-op', [], {wait: true}, _.identity);\n    // Call a method with a stub that writes.\n    conn.call('insertSomething', _.identity);\n\n\n    // Stub write is visible.\n    test.equal(coll.find({foo: 'bar'}).count(), 1);\n    var stubWrittenId = coll.findOne({foo: 'bar'})._id;\n\n    // first method sent\n    var firstMethodId = testGotMessage(\n      test, stream, {msg: 'method', method: 'no-op',\n                     params: [], id: '*'}).id;\n    test.equal(stream.sent.length, 0);\n\n    // ack the first method\n    stream.receive({msg: 'updated', methods: [firstMethodId]});\n    stream.receive({msg: 'result', id: firstMethodId});\n\n    // Wait method sent.\n    var waitMethodId = testGotMessage(\n      test, stream, {msg: 'method', method: 'no-op',\n                     params: [], id: '*'}).id;\n    test.equal(stream.sent.length, 0);\n\n    // ack the wait method\n    stream.receive({msg: 'updated', methods: [waitMethodId]});\n    stream.receive({msg: 'result', id: waitMethodId});\n\n    // insert method sent.\n    var insertMethodId = testGotMessage(\n      test, stream, {msg: 'method', method: 'insertSomething',\n                     params: [], id: '*', randomSeed: '*'}).id;\n    test.equal(stream.sent.length, 0);\n\n    // ack the insert method\n    stream.receive({msg: 'updated', methods: [insertMethodId]});\n    stream.receive({msg: 'result', id: insertMethodId});\n\n    // simulation reverted.\n    test.equal(coll.find({foo: 'bar'}).count(), 0);\n\n  });\n}\nTinytest.add(\"livedata stub - reactive resub\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n\n  startAndConnect(test, stream);\n\n  var readiedSubs = {};\n  var markAllReady = function () {\n    // synthesize a \"ready\" message in response to any \"sub\"\n    // message with an id we haven't seen before\n    _.each(stream.sent, function (msg) {\n      msg = JSON.parse(msg);\n      if (msg.msg === 'sub' && ! _.has(readiedSubs, msg.id)) {\n        stream.receive({msg: 'ready', subs: [msg.id]});\n        readiedSubs[msg.id] = true;\n      }\n    });\n  };\n\n  var fooArg = new ReactiveVar('A');\n  var fooReady = 0;\n\n  var inner;\n  var outer = Tracker.autorun(function () {\n    inner = Tracker.autorun(function () {\n      conn.subscribe(\"foo-sub\", fooArg.get(),\n                     function () { fooReady++; });\n    });\n  });\n\n  markAllReady();\n  test.equal(fooReady, 1);\n\n  // Rerun the inner autorun with different subscription\n  // arguments.  Detect the re-sub via onReady.\n  fooArg.set('B');\n  test.isTrue(inner.invalidated);\n  Tracker.flush();\n  test.isFalse(inner.invalidated);\n  markAllReady();\n  test.equal(fooReady, 2);\n\n  // Rerun inner again with same args; should be no re-sub.\n  inner.invalidate();\n  test.isTrue(inner.invalidated);\n  Tracker.flush();\n  test.isFalse(inner.invalidated);\n  markAllReady();\n  test.equal(fooReady, 2);\n\n  // Rerun outer!  Should still be no re-sub even though\n  // the inner computation is stopped and a new one is\n  // started.\n  outer.invalidate();\n  test.isTrue(inner.invalidated);\n  Tracker.flush();\n  test.isFalse(inner.invalidated);\n  markAllReady();\n  test.equal(fooReady, 2);\n\n  // Change the subscription.  Now we should get an onReady.\n  fooArg.set('C');\n  Tracker.flush();\n  markAllReady();\n  test.equal(fooReady, 3);\n});\n\n\n\nTinytest.add(\"livedata connection - reactive userId\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n\n  test.equal(conn.userId(), null);\n  conn.setUserId(1337);\n  test.equal(conn.userId(), 1337);\n});\n\nTinytest.add(\"livedata connection - two wait methods\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n  startAndConnect(test, stream);\n\n  var collName = Random.id();\n  var coll = new Mongo.Collection(collName, {connection: conn});\n\n  // setup method\n  conn.methods({do_something: function (x) {}});\n\n  var responses = [];\n  conn.apply('do_something', ['one!'], function() { responses.push('one'); });\n  var one_message = JSON.parse(stream.sent.shift());\n  test.equal(one_message.params, ['one!']);\n\n  conn.apply('do_something', ['two!'], {wait: true}, function() {\n    responses.push('two');\n  });\n  // 'two!' isn't sent yet, because it's a wait method.\n  test.equal(stream.sent.length, 0);\n\n  conn.apply('do_something', ['three!'], function() {\n    responses.push('three');\n  });\n  conn.apply('do_something', ['four!'], function() {\n    responses.push('four');\n  });\n\n  conn.apply('do_something', ['five!'], {wait: true}, function() {\n    responses.push('five');\n  });\n\n  conn.apply('do_something', ['six!'], function() { responses.push('six'); });\n\n  // Verify that we did not send any more methods since we are still waiting on\n  // 'one!'.\n  test.equal(stream.sent.length, 0);\n\n  // Receive some data. \"one\" is not a wait method and there are no stubs, so it\n  // gets applied immediately.\n  test.equal(coll.find().count(), 0);\n  stream.receive({msg: 'added', collection: collName,\n                  id: 'foo', fields: {x: 1}});\n  test.equal(coll.find().count(), 1);\n  test.equal(coll.findOne('foo'), {_id: 'foo', x: 1});\n\n  // Let \"one!\" finish. Both messages are required to fire the callback.\n  stream.receive({msg: 'result', id: one_message.id});\n  test.equal(responses, []);\n  stream.receive({msg: 'updated', methods: [one_message.id]});\n  test.equal(responses, ['one']);\n\n  // Now we've send out \"two!\".\n  var two_message = JSON.parse(stream.sent.shift());\n  test.equal(two_message.params, ['two!']);\n\n  // But still haven't sent \"three!\".\n  test.equal(stream.sent.length, 0);\n\n  // Receive more data. \"two\" is a wait method, so the data doesn't get applied\n  // yet.\n  stream.receive({msg: 'changed', collection: collName,\n                  id: 'foo', fields: {y: 3}});\n  test.equal(coll.find().count(), 1);\n  test.equal(coll.findOne('foo'), {_id: 'foo', x: 1});\n\n  // Let \"two!\" finish, with its end messages in the opposite order to \"one!\".\n  stream.receive({msg: 'updated', methods: [two_message.id]});\n  test.equal(responses, ['one']);\n  test.equal(stream.sent.length, 0);\n  // data-done message is enough to allow data to be written.\n  test.equal(coll.find().count(), 1);\n  test.equal(coll.findOne('foo'), {_id: 'foo', x: 1, y: 3});\n  stream.receive({msg: 'result', id: two_message.id});\n  test.equal(responses, ['one', 'two']);\n\n  // Verify that we just sent \"three!\" and \"four!\" now that we got\n  // responses for \"one!\" and \"two!\"\n  test.equal(stream.sent.length, 2);\n  var three_message = JSON.parse(stream.sent.shift());\n  test.equal(three_message.params, ['three!']);\n  var four_message = JSON.parse(stream.sent.shift());\n  test.equal(four_message.params, ['four!']);\n\n  // Out of order response is OK for non-wait methods.\n  stream.receive({msg: 'result', id: three_message.id});\n  stream.receive({msg: 'result', id: four_message.id});\n  stream.receive({msg: 'updated', methods: [four_message.id]});\n  test.equal(responses, ['one', 'two', 'four']);\n  test.equal(stream.sent.length, 0);\n\n  // Let three finish too.\n  stream.receive({msg: 'updated', methods: [three_message.id]});\n  test.equal(responses, ['one', 'two', 'four', 'three']);\n\n  // Verify that we just sent \"five!\" (the next wait method).\n  test.equal(stream.sent.length, 1);\n  var five_message = JSON.parse(stream.sent.shift());\n  test.equal(five_message.params, ['five!']);\n  test.equal(responses, ['one', 'two', 'four', 'three']);\n\n  // Let five finish.\n  stream.receive({msg: 'result', id: five_message.id});\n  stream.receive({msg: 'updated', methods: [five_message.id]});\n  test.equal(responses, ['one', 'two', 'four', 'three', 'five']);\n\n  var six_message = JSON.parse(stream.sent.shift());\n  test.equal(six_message.params, ['six!']);\n});\n\nTinytest.add(\"livedata connection - onReconnect prepends messages correctly with a wait method\", function(test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n  startAndConnect(test, stream);\n\n  // setup method\n  conn.methods({do_something: function (x) {}});\n\n  conn.onReconnect = function() {\n    conn.apply('do_something', ['reconnect zero'], _.identity);\n    conn.apply('do_something', ['reconnect one'], _.identity);\n    conn.apply('do_something', ['reconnect two'], {wait: true}, _.identity);\n    conn.apply('do_something', ['reconnect three'], _.identity);\n  };\n\n  conn.apply('do_something', ['one'], _.identity);\n  conn.apply('do_something', ['two'], {wait: true}, _.identity);\n  conn.apply('do_something', ['three'], _.identity);\n\n  // reconnect\n  stream.sent = [];\n  stream.reset();\n  testGotMessage(test, stream, makeConnectMessage(conn._lastSessionId));\n\n  // Test that we sent what we expect to send, and we're blocked on\n  // what we expect to be blocked. The subsequent logic to correctly\n  // read the wait flag is tested separately.\n  test.equal(_.map(stream.sent, function(msg) {\n    return JSON.parse(msg).params[0];\n  }), ['reconnect zero', 'reconnect one']);\n\n  // white-box test:\n  test.equal(_.map(conn._outstandingMethodBlocks, function (block) {\n    return [block.wait, _.map(block.methods, function (method) {\n      return method._message.params[0];\n    })];\n  }), [\n    [false, ['reconnect zero', 'reconnect one']],\n    [true, ['reconnect two']],\n    [false, ['reconnect three', 'one']],\n    [true, ['two']],\n    [false, ['three']]\n  ]);\n});\n\nTinytest.add(\"livedata connection - ping without id\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n  startAndConnect(test, stream);\n\n  stream.receive({msg: 'ping'});\n  testGotMessage(test, stream, {msg: 'pong'});\n});\n\nTinytest.add(\"livedata connection - ping with id\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n  startAndConnect(test, stream);\n\n  var id = Random.id();\n  stream.receive({msg: 'ping', id: id});\n  testGotMessage(test, stream, {msg: 'pong', id: id});\n});\n\n_.each(LivedataTest.SUPPORTED_DDP_VERSIONS, function (version) {\n  Tinytest.addAsync(\"livedata connection - ping from \" + version,\n                    function (test, onComplete) {\n    var connection = new LivedataTest.Connection(getSelfConnectionUrl(), {\n      reloadWithOutstanding: true,\n      supportedDDPVersions: [version],\n      onDDPVersionNegotiationFailure: function () { test.fail(); onComplete(); },\n      onConnected: function () {\n        test.equal(connection._version, version);\n        // It's a little naughty to access _stream and _send, but it works...\n        connection._stream.on('message', function (json) {\n          var msg = JSON.parse(json);\n          var done = false;\n          if (msg.msg === 'pong') {\n            test.notEqual(version, \"pre1\");\n            done = true;\n          } else if (msg.msg === 'error') {\n            // Version pre1 does not play ping-pong\n            test.equal(version, \"pre1\");\n            done = true;\n          } else {\n            Meteor._debug(\"Got unexpected message: \" + json);\n          }\n          if (done) {\n            connection._stream.disconnect({_permanent: true});\n            onComplete();\n          }\n        });\n        connection._send({msg: 'ping'});\n      }\n    });\n  });\n});\n\nvar getSelfConnectionUrl = function () {\n  if (Meteor.isClient) {\n    var ddpUrl = Meteor._relativeToSiteRootUrl(\"/\");\n    if (typeof __meteor_runtime_config__ !== \"undefined\") {\n      if (__meteor_runtime_config__.DDP_DEFAULT_CONNECTION_URL)\n        ddpUrl = __meteor_runtime_config__.DDP_DEFAULT_CONNECTION_URL;\n    }\n    return ddpUrl;\n  } else {\n    return Meteor.absoluteUrl();\n  }\n};\n\nif (Meteor.isServer) {\n  Meteor.methods({\n    reverse: function (arg) {\n      // Return something notably different from reverse.meteor.com.\n      return arg.split(\"\").reverse().join(\"\") + \" LOCAL\";\n    }\n  });\n}\n\ntestAsyncMulti(\"livedata connection - reconnect to a different server\", [\n  function (test, expect) {\n    var self = this;\n    self.conn = DDP.connect(\"reverse.meteor.com\");\n    pollUntil(expect, function () {\n      return self.conn.status().connected;\n    }, 5000, 100, true); // poll until connected, but don't fail if we don't connect\n  },\n  function (test, expect) {\n    var self = this;\n    self.doTest = self.conn.status().connected;\n    if (self.doTest) {\n      self.conn.call(\"reverse\", \"foo\", expect(function (err, res) {\n        test.equal(res, \"oof\");\n      }));\n    }\n  },\n  function (test, expect) {\n    var self = this;\n    if (self.doTest) {\n      self.conn.reconnect({url: getSelfConnectionUrl()});\n      self.conn.call(\"reverse\", \"bar\", expect(function (err, res) {\n        test.equal(res, \"rab LOCAL\");\n      }));\n    }\n  }\n]);\n\nTinytest.addAsync(\"livedata connection - version negotiation requires renegotiating\",\n                  function (test, onComplete) {\n  var connection = new LivedataTest.Connection(getSelfConnectionUrl(), {\n    reloadWithOutstanding: true,\n    supportedDDPVersions: [\"garbled\", LivedataTest.SUPPORTED_DDP_VERSIONS[0]],\n    onDDPVersionNegotiationFailure: function () { test.fail(); onComplete(); },\n    onConnected: function () {\n      test.equal(connection._version, LivedataTest.SUPPORTED_DDP_VERSIONS[0]);\n      connection._stream.disconnect({_permanent: true});\n      onComplete();\n    }\n  });\n});\n\nTinytest.addAsync(\"livedata connection - version negotiation error\",\n                  function (test, onComplete) {\n  var connection = new LivedataTest.Connection(getSelfConnectionUrl(), {\n    reloadWithOutstanding: true,\n    supportedDDPVersions: [\"garbled\", \"more garbled\"],\n    onDDPVersionNegotiationFailure: function () {\n      test.equal(connection.status().status, \"failed\");\n      test.matches(connection.status().reason, /DDP version negotiation failed/);\n      test.isFalse(connection.status().connected);\n      onComplete();\n    },\n    onConnected: function () {\n      test.fail();\n      onComplete();\n    }\n  });\n});\n\nTinytest.add(\"livedata connection - onReconnect prepends messages correctly without a wait method\", function(test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n  startAndConnect(test, stream);\n\n  // setup method\n  conn.methods({do_something: function (x) {}});\n\n  conn.onReconnect = function() {\n    conn.apply('do_something', ['reconnect one'], _.identity);\n    conn.apply('do_something', ['reconnect two'], _.identity);\n    conn.apply('do_something', ['reconnect three'], _.identity);\n  };\n\n  conn.apply('do_something', ['one'], _.identity);\n  conn.apply('do_something', ['two'], {wait: true}, _.identity);\n  conn.apply('do_something', ['three'], {wait: true}, _.identity);\n  conn.apply('do_something', ['four'], _.identity);\n\n  // reconnect\n  stream.sent = [];\n  stream.reset();\n  testGotMessage(test, stream, makeConnectMessage(conn._lastSessionId));\n\n  // Test that we sent what we expect to send, and we're blocked on\n  // what we expect to be blocked. The subsequent logic to correctly\n  // read the wait flag is tested separately.\n  test.equal(_.map(stream.sent, function(msg) {\n    return JSON.parse(msg).params[0];\n  }), ['reconnect one', 'reconnect two', 'reconnect three', 'one']);\n\n  // white-box test:\n  test.equal(_.map(conn._outstandingMethodBlocks, function (block) {\n    return [block.wait, _.map(block.methods, function (method) {\n      return method._message.params[0];\n    })];\n  }), [\n    [false, ['reconnect one', 'reconnect two', 'reconnect three', 'one']],\n    [true, ['two']],\n    [true, ['three']],\n    [false, ['four']]\n  ]);\n});\n\nTinytest.add(\"livedata connection - onReconnect with sent messages\", function(test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n  startAndConnect(test, stream);\n\n  // setup method\n  conn.methods({do_something: function (x) {}});\n\n  conn.onReconnect = function() {\n    conn.apply('do_something', ['login'], {wait: true}, _.identity);\n  };\n\n  conn.apply('do_something', ['one'], _.identity);\n\n  // initial connect\n  stream.sent = [];\n  stream.reset();\n  testGotMessage(\n    test, stream, makeConnectMessage(conn._lastSessionId));\n\n  // Test that we sent just the login message.\n  var loginId = testGotMessage(\n    test, stream, {msg: 'method', method: 'do_something',\n                   params: ['login'], id: '*'}).id;\n\n  // we connect.\n  stream.receive({msg: 'connected', session: Random.id()});\n  test.length(stream.sent, 0);\n\n  // login got result (but not yet data)\n  stream.receive({msg: 'result', id: loginId, result: 'foo'});\n  test.length(stream.sent, 0);\n\n  // login got data. now we send next method.\n  stream.receive({msg: 'updated', methods: [loginId]});\n\n  testGotMessage(\n    test, stream, {msg: 'method', method: 'do_something',\n                   params: ['one'], id: '*'}).id;\n});\n\n\n\nTinytest.add(\"livedata stub - reconnect double wait method\", function (test) {\n  var stream = new StubStream;\n  var conn = newConnection(stream);\n  startAndConnect(test, stream);\n\n  var output = [];\n  conn.onReconnect = function () {\n    conn.apply('reconnectMethod', [], {wait: true}, function (err, result) {\n      output.push('reconnect');\n    });\n  };\n\n  conn.apply('halfwayMethod', [], {wait: true}, function (err, result) {\n    output.push('halfway');\n  });\n\n  test.equal(output, []);\n  // Method sent.\n  var halfwayId = testGotMessage(\n    test, stream, {msg: 'method', method: 'halfwayMethod',\n                   params: [], id: '*'}).id;\n  test.equal(stream.sent.length, 0);\n\n  // Get the result. This means it will not be resent.\n  stream.receive({msg: 'result', id: halfwayId, result: 'bla'});\n  // Callback not called.\n  test.equal(output, []);\n\n  // Reset stream. halfwayMethod does NOT get resent, but reconnectMethod does!\n  // Reconnect quiescence happens when reconnectMethod is done.\n  stream.reset();\n  testGotMessage(test, stream, makeConnectMessage(SESSION_ID));\n  var reconnectId = testGotMessage(\n    test, stream, {msg: 'method', method: 'reconnectMethod',\n                   params: [], id: '*'}).id;\n  test.length(stream.sent, 0);\n  // Still holding out hope for session resumption, so no callbacks yet.\n  test.equal(output, []);\n\n  // Receive 'connected', but reconnect quiescence is blocking on\n  // reconnectMethod.\n  stream.receive({msg: 'connected', session: SESSION_ID + 1});\n  test.equal(output, []);\n\n  // Data-done for reconnectMethod. This gets us to reconnect quiescence, so\n  // halfwayMethod's callback fires. reconnectMethod's is still waiting on its\n  // result.\n  stream.receive({msg: 'updated', methods: [reconnectId]});\n  test.equal(output.shift(), 'halfway');\n  test.equal(output, []);\n\n  // Get result of reconnectMethod. Its callback fires.\n  stream.receive({msg: 'result', id: reconnectId, result: 'foo'});\n  test.equal(output.shift(), 'reconnect');\n  test.equal(output, []);\n\n  // Call another method. It should be delivered immediately. This is a\n  // regression test for a case where it never got delivered because there was\n  // an empty block in _outstandingMethodBlocks blocking it from being sent.\n  conn.call('lastMethod', _.identity);\n  testGotMessage(test, stream,\n                 {msg: 'method', method: 'lastMethod', params: [], id: '*'});\n});\n\nTinytest.add(\"livedata stub - subscribe errors\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n\n  startAndConnect(test, stream);\n\n  // subscribe\n  var onReadyFired = false;\n  var subErrorInStopped = null;\n  var subErrorInError = null;\n\n  conn.subscribe('unknownSub', {\n    onReady: function () {\n      onReadyFired = true;\n    },\n\n    // We now have two ways to get the error from a subscription:\n    // 1. onStop, which is called no matter what when the subscription is\n    //    stopped (a lifecycle callback)\n    // 2. onError, which is deprecated and is called only if there is an\n    //    error\n    onStop: function (error) {\n      subErrorInStopped = error;\n    },\n    onError: function (error) {\n      subErrorInError = error;\n    }\n  });\n\n  test.isFalse(onReadyFired);\n  test.equal(subErrorInStopped, null);\n\n  // XXX COMPAT WITH 1.0.3.1 #errorCallback\n  test.equal(subErrorInError, null);\n\n  var subMessage = JSON.parse(stream.sent.shift());\n  test.equal(subMessage, {msg: 'sub', name: 'unknownSub', params: [],\n                          id: subMessage.id});\n\n  // Reject the sub.\n  stream.receive({msg: 'nosub', id: subMessage.id,\n                  error: new Meteor.Error(404, \"Subscription not found\")});\n  test.isFalse(onReadyFired);\n\n  // Check the error passed to the stopped callback was correct\n  test.instanceOf(subErrorInStopped, Meteor.Error);\n  test.equal(subErrorInStopped.error, 404);\n  test.equal(subErrorInStopped.reason, \"Subscription not found\");\n\n  // Check the error passed to the error callback was correct\n  // XXX COMPAT WITH 1.0.3.1 #errorCallback\n  test.instanceOf(subErrorInError, Meteor.Error);\n  test.equal(subErrorInError.error, 404);\n  test.equal(subErrorInError.reason, \"Subscription not found\");\n\n  // stream reset: reconnect!\n  stream.reset();\n  // We send a connect.\n  testGotMessage(test, stream, makeConnectMessage(SESSION_ID));\n  // We should NOT re-sub to the sub, because we processed the error.\n  test.length(stream.sent, 0);\n  test.isFalse(onReadyFired);\n});\n\nTinytest.add(\"livedata stub - subscribe stop\", function (test) {\n  var stream = new StubStream();\n  var conn = newConnection(stream);\n\n  startAndConnect(test, stream);\n\n  // subscribe\n  var onReadyFired = false;\n  var onStopFired = false;\n  var subErrorInStopped = null;\n\n  var sub = conn.subscribe('my_data', {\n    onStop: function (error) {\n      onStopFired = true;\n      subErrorInStopped = error;\n    }\n  });\n\n  test.equal(subErrorInStopped, null);\n\n  sub.stop();\n\n  test.isTrue(onStopFired);\n  test.equal(subErrorInStopped, undefined);\n});\n\nif (Meteor.isClient) {\n  Tinytest.add(\"livedata stub - stubs before connected\", function (test) {\n    var stream = new StubStream();\n    var conn = newConnection(stream);\n\n    var collName = Random.id();\n    var coll = new Mongo.Collection(collName, {connection: conn});\n\n    // Start and send \"connect\", but DON'T get 'connected' quite yet.\n    stream.reset(); // initial connection start.\n\n    testGotMessage(test, stream, makeConnectMessage());\n    test.length(stream.sent, 0);\n\n    // Insert a document. The stub updates \"conn\" directly.\n    coll.insert({_id: \"foo\", bar: 42}, _.identity);\n    test.equal(coll.find().count(), 1);\n    test.equal(coll.findOne(), {_id: \"foo\", bar: 42});\n    // It also sends the method message.\n    var methodMessage = JSON.parse(stream.sent.shift());\n    test.isUndefined(methodMessage.randomSeed);\n    test.equal(methodMessage, {msg: 'method', method: '/' + collName + '/insert',\n                               params: [{_id: \"foo\", bar: 42}],\n                               id: methodMessage.id});\n    test.length(stream.sent, 0);\n\n    // Now receive a connected message. This should not clear the\n    // _documentsWrittenByStub state!\n    stream.receive({msg: 'connected', session: SESSION_ID});\n    test.length(stream.sent, 0);\n    test.equal(coll.find().count(), 1);\n\n    // Now receive the \"updated\" message for the method. This should revert the\n    // insert.\n    stream.receive({msg: 'updated', methods: [methodMessage.id]});\n    test.length(stream.sent, 0);\n    test.equal(coll.find().count(), 0);\n  });\n}\n\nif (Meteor.isClient) {\n  Tinytest.add(\"livedata stub - method call between reset and quiescence\", function (test) {\n    var stream = new StubStream();\n    var conn = newConnection(stream);\n\n    startAndConnect(test, stream);\n\n    var collName = Random.id();\n    var coll = new Mongo.Collection(collName, {connection: conn});\n\n    conn.methods({\n      update_value: function () {\n        coll.update('aaa', {value: 222});\n      }\n    });\n\n    // Set up test subscription.\n    var sub = conn.subscribe('test_data');\n    var subMessage = JSON.parse(stream.sent.shift());\n    test.equal(subMessage, {msg: 'sub', name: 'test_data',\n                            params: [], id:subMessage.id});\n    test.length(stream.sent, 0);\n\n    var subDocMessage = {msg: 'added', collection: collName,\n                         id: 'aaa', fields: {value: 111}};\n\n    var subReadyMessage = {msg: 'ready', 'subs': [subMessage.id]};\n\n    stream.receive(subDocMessage);\n    stream.receive(subReadyMessage);\n    test.isTrue(coll.findOne('aaa').value == 111);\n\n    // Initiate reconnect.\n    stream.reset();\n    testGotMessage(test, stream, makeConnectMessage(SESSION_ID));\n    testGotMessage(test, stream, subMessage);\n    stream.receive({msg: 'connected', session: SESSION_ID + 1});\n\n    // Now in reconnect, can still see the document.\n    test.isTrue(coll.findOne('aaa').value == 111);\n\n    conn.call('update_value');\n\n    // Observe the stub-written value.\n    test.isTrue(coll.findOne('aaa').value == 222);\n\n    var methodMessage = JSON.parse(stream.sent.shift());\n    test.equal(methodMessage, {msg: 'method', method: 'update_value',\n                               params: [], id:methodMessage.id});\n    test.length(stream.sent, 0);\n\n    stream.receive(subDocMessage);\n    stream.receive(subReadyMessage);\n\n    // By this point quiescence is reached and stores have been reset.\n\n    // The stub-written value is still there.\n    test.isTrue(coll.findOne('aaa').value == 222);\n\n    stream.receive({msg: 'changed', collection: collName,\n                         id: 'aaa', fields: {value: 333}});\n    stream.receive({msg: 'updated', 'methods': [methodMessage.id]});\n    stream.receive({msg: 'result', id:methodMessage.id, result:null});\n\n    // Server wrote a different value, make sure it's visible now.\n    test.isTrue(coll.findOne('aaa').value == 333);\n  });\n}\n\n// XXX also test:\n// - reconnect, with session resume.\n// - restart on update flag\n// - on_update event\n// - reloading when the app changes, including session migration\n"
  },
  {
    "path": "packages/ddp-client/livedata_test_service.js",
    "content": "Meteor.methods({\n  nothing: function () {\n    // No need to check if there are no arguments.\n  },\n  echo: function (/* arguments */) {\n    check(arguments, [Match.Any]);\n    return _.toArray(arguments);\n  },\n  echoOne: function (/*arguments*/) {\n    check(arguments, [Match.Any]);\n    return arguments[0];\n  },\n  exception: function (where, options) {\n    check(where, String);\n    check(options, Match.Optional({\n      intended: Match.Optional(Boolean),\n      throwThroughFuture: Match.Optional(Boolean)\n    }));\n    options = options || {};\n    var shouldThrow =\n      (Meteor.isServer && where === \"server\") ||\n      (Meteor.isClient && where === \"client\") ||\n      where === \"both\";\n\n    if (shouldThrow) {\n      var e;\n      if (options.intended)\n        e = new Meteor.Error(999, \"Client-visible test exception\");\n      else\n        e = new Error(\"Test method throwing an exception\");\n      e.expected = true;\n\n      // We used to improperly serialize errors that were thrown through a\n      // future first.\n      if (Meteor.isServer && options.throwThroughFuture) {\n        var Future = Npm.require('fibers/future');\n        var f = new Future;\n        f['throw'](e);\n        e = f.wait();\n      }\n      throw e;\n    }\n  },\n  setUserId: function(userId) {\n    check(userId, Match.OneOf(String, null));\n    this.setUserId(userId);\n  }\n});\n\n// Methods to help test applying methods with `wait: true`: delayedTrue returns\n// true 1s after being run unless makeDelayedTrueImmediatelyReturnFalse was run\n// in the meanwhile. Increasing the timeout makes the \"wait: true\" test slower;\n// decreasing the timeout makes the \"wait: false\" test flakier (ie, the timeout\n// could fire before processing the second method).\nif (Meteor.isServer) {\n  // Keys are random tokens, used to isolate multiple test invocations from each\n  // other.\n  var waiters = {};\n\n  var path = Npm.require('path');\n  var Future = Npm.require(path.join('fibers', 'future'));\n\n  var returnThroughFuture = function (token, returnValue) {\n    // Make sure that when we call return, the fields are already cleared.\n    var record = waiters[token];\n    if (!record)\n      return;\n    delete waiters[token];\n    record.future['return'](returnValue);\n  };\n\n  Meteor.methods({\n    delayedTrue: function(token) {\n      check(token, String);\n      var record = waiters[token] = {\n        future: new Future(),\n        timer: Meteor.setTimeout(function() {\n          returnThroughFuture(token, true);\n        }, 1000)\n      };\n\n      this.unblock();\n      return record.future.wait();\n    },\n    makeDelayedTrueImmediatelyReturnFalse: function(token) {\n      check(token, String);\n      var record = waiters[token];\n      if (!record)\n        return; // since delayedTrue's timeout had already run\n      clearTimeout(record.timer);\n      returnThroughFuture(token, false);\n    }\n  });\n}\n\n/*****/\n\nLedger = new Mongo.Collection(\"ledger\");\nLedger.allow({\n  insert: function() { return true; },\n  update: function() { return true; },\n  remove: function() { return true; },\n  fetch: []\n});\n\nMeteor.startup(function () {\n  if (Meteor.isServer)\n    Ledger.remove({}); // XXX can this please be Ledger.remove()?\n});\n\nif (Meteor.isServer)\n  Meteor.publish('ledger', function (world) {\n    check(world, String);\n    return Ledger.find({world: world});\n  });\n\nMeteor.methods({\n  'ledger/transfer': function (world, from_name, to_name, amount, cheat) {\n    check(world, String);\n    check(from_name, String);\n    check(to_name, String);\n    check(amount, Number);\n    check(cheat, Match.Optional(Boolean));\n    var from = Ledger.findOne({name: from_name, world: world});\n    var to = Ledger.findOne({name: to_name, world: world});\n\n    if (Meteor.isServer)\n      cheat = false;\n\n    if (!from)\n      throw new Meteor.Error(404,\n                             \"No such account \" + from_name + \" in \" + world);\n\n    if (!to)\n      throw new Meteor.Error(404,\n                             \"No such account \" + to_name + \" in \" + world);\n\n    if (from.balance < amount && !cheat)\n      throw new Meteor.Error(409, \"Insufficient funds\");\n\n    Ledger.update(from._id, {$inc: {balance: -amount}});\n    Ledger.update(to._id, {$inc: {balance: amount}});\n  }\n});\n\n/*****/\n\n/// Helpers for \"livedata - changing userid reruns subscriptions...\"\n\nobjectsWithUsers = new Mongo.Collection(\"objectsWithUsers\");\n\nif (Meteor.isServer) {\n  objectsWithUsers.remove({});\n  objectsWithUsers.insert({name: \"owned by none\", ownerUserIds: [null]});\n  objectsWithUsers.insert({name: \"owned by one - a\", ownerUserIds: [\"1\"]});\n  objectsWithUsers.insert({name: \"owned by one/two - a\", ownerUserIds: [\"1\", \"2\"]});\n  objectsWithUsers.insert({name: \"owned by one/two - b\", ownerUserIds: [\"1\", \"2\"]});\n  objectsWithUsers.insert({name: \"owned by two - a\", ownerUserIds: [\"2\"]});\n  objectsWithUsers.insert({name: \"owned by two - b\", ownerUserIds: [\"2\"]});\n\n  Meteor.publish(\"objectsWithUsers\", function() {\n    return objectsWithUsers.find({ownerUserIds: this.userId},\n                                 {fields: {ownerUserIds: 0}});\n  });\n\n  (function () {\n    var userIdWhenStopped = {};\n    Meteor.publish(\"recordUserIdOnStop\", function (key) {\n      check(key, String);\n      var self = this;\n      self.onStop(function() {\n        userIdWhenStopped[key] = self.userId;\n      });\n    });\n\n    Meteor.methods({\n      userIdWhenStopped: function (key) {\n        check(key, String);\n        return userIdWhenStopped[key];\n      }\n    });\n  })();\n}\n\n/*****/\n\n/// Helper for \"livedata - setUserId fails when called on server\"\n\nif (Meteor.isServer) {\n  Meteor.startup(function() {\n    errorThrownWhenCallingSetUserIdDirectlyOnServer = null;\n    try {\n      Meteor.call(\"setUserId\", \"1000\");\n    } catch (e) {\n      errorThrownWhenCallingSetUserIdDirectlyOnServer = e;\n    }\n  });\n}\n\n/// Helper for \"livedata - no setUserId after unblock\"\n\nif (Meteor.isServer) {\n  Meteor.methods({\n    setUserIdAfterUnblock: function () {\n      this.unblock();\n      var threw = false;\n      var originalUserId = this.userId;\n      try {\n        // Calling setUserId after unblock should throw an error (and not mutate\n        // userId).\n        this.setUserId(originalUserId + \"bla\");\n      } catch (e) {\n        threw = true;\n      }\n      return threw && this.userId === originalUserId;\n    }\n  });\n}\n\n/*****/\n\n/// Helper for \"livedata - overlapping universal subs\"\n\nif (Meteor.isServer) {\n  (function(){\n    var collName = \"overlappingUniversalSubs\";\n    var universalSubscribers = [[], []];\n\n    _.each([0, 1], function (index) {\n      Meteor.publish(null, function () {\n        var sub = this;\n        universalSubscribers[index].push(sub);\n        sub.onStop(function () {\n          universalSubscribers[index] = _.without(\n            universalSubscribers[index], sub);\n        });\n      });\n    });\n\n    Meteor.methods({\n      testOverlappingSubs: function (token) {\n        check(token, String);\n        _.each(universalSubscribers[0], function (sub) {\n          sub.added(collName, token, {});\n        });\n        _.each(universalSubscribers[1], function (sub) {\n          sub.added(collName, token, {});\n        });\n        _.each(universalSubscribers[0], function (sub) {\n          sub.removed(collName, token);\n        });\n      }\n    });\n  })();\n}\n\n/// Helper for \"livedata - runtime universal sub creation\"\n\nif (Meteor.isServer) {\n  Meteor.methods({\n    runtimeUniversalSubCreation: function (token) {\n      check(token, String);\n      Meteor.publish(null, function () {\n        this.added(\"runtimeSubCreation\", token, {});\n      });\n    }\n  });\n}\n\n/// Helper for \"livedata - publisher errors\"\n\nif (Meteor.isServer) {\n  Meteor.publish(\"publisherErrors\", function (collName, options) {\n    check(collName, String);\n    // See below to see what options are accepted.\n    check(options, Object);\n    var sub = this;\n\n    // First add a random item, which should be cleaned up. We use ready/onReady\n    // to make sure that the second test block is only called after the added is\n    // processed, so that there's any chance of the coll.find().count() failing.\n    sub.added(collName, Random.id(), {foo: 42});\n    sub.ready();\n\n    if (options.stopInHandler) {\n      sub.stop();\n      return;\n    }\n\n    var error;\n    if (options.internalError) {\n      error = new Error(\"Egads!\");\n      error.expected = true;  // don't log\n    } else {\n      error = new Meteor.Error(412, \"Explicit error\");\n    }\n    if (options.throwInHandler) {\n      throw error;\n    } else if (options.errorInHandler) {\n      sub.error(error);\n    } else if (options.throwWhenUserIdSet) {\n      if (sub.userId)\n        throw error;\n    } else if (options.errorLater) {\n      Meteor.defer(function () {\n        sub.error(error);\n      });\n    }\n  });\n}\n\n\n/*****/\n\n/// Helpers for \"livedata - publish multiple cursors\"\nOne = new Mongo.Collection(\"collectionOne\");\nTwo = new Mongo.Collection(\"collectionTwo\");\n\nif (Meteor.isServer) {\n  One.remove({});\n  One.insert({name: \"value1\"});\n  One.insert({name: \"value2\"});\n\n  Two.remove({});\n  Two.insert({name: \"value3\"});\n  Two.insert({name: \"value4\"});\n  Two.insert({name: \"value5\"});\n\n  Meteor.publish(\"multiPublish\", function (options) {\n    // See below to see what options are accepted.\n    check(options, Object);\n    if (options.normal) {\n      return [\n        One.find(),\n        Two.find()\n      ];\n    } else if (options.dup) {\n      // Suppress the log of the expected internal error.\n      Meteor._suppress_log(1);\n      return [\n        One.find(),\n        One.find({name: \"value2\"}), // multiple cursors for one collection - error\n        Two.find()\n      ];\n    } else if (options.notCursor) {\n      // Suppress the log of the expected internal error.\n      Meteor._suppress_log(1);\n      return [\n        One.find(),\n        \"not a cursor\",\n        Two.find()\n      ];\n    } else\n      throw \"unexpected options\";\n  });\n}\n\n\n/// Helper for \"livedata - result by value\"\nvar resultByValueArrays = {};\nMeteor.methods({\n  'getArray': function (testId) {\n    if (! _.has(resultByValueArrays, testId))\n      resultByValueArrays[testId] = [];\n    return resultByValueArrays[testId];\n  },\n  'pushToArray': function (testId, value) {\n    if (! _.has(resultByValueArrays, testId))\n      resultByValueArrays[testId] = [];\n    resultByValueArrays[testId].push(value);\n  }\n});\n"
  },
  {
    "path": "packages/ddp-client/livedata_tests.js",
    "content": "// XXX should check error codes\nvar failure = function (test, code, reason) {\n  return function (error, result) {\n    test.equal(result, undefined);\n    test.isTrue(error && typeof error === \"object\");\n    if (error && typeof error === \"object\") {\n      if (typeof code === \"number\") {\n        test.instanceOf(error, Meteor.Error);\n        code && test.equal(error.error, code);\n        reason && test.equal(error.reason, reason);\n        // XXX should check that other keys aren't present.. should\n        // probably use something like the Matcher we used to have\n      } else {\n        // for normal Javascript errors\n        test.instanceOf(error, Error);\n        test.equal(error.message, code);\n      }\n    }\n  };\n};\n\nvar failureOnStopped = function (test, code, reason) {\n  var f = failure(test, code, reason);\n\n  return function (error) {\n    if (error) {\n      f(error);\n    }\n  }\n};\n\nTinytest.add(\"livedata - Meteor.Error\", function (test) {\n  var error = new Meteor.Error(123, \"kittens\", \"puppies\");\n  test.instanceOf(error, Meteor.Error);\n  test.instanceOf(error, Error);\n  test.equal(error.error, 123);\n  test.equal(error.reason, \"kittens\");\n  test.equal(error.details, \"puppies\");\n});\n\nif (Meteor.isServer) {\n  Tinytest.add(\"livedata - version negotiation\", function (test) {\n    var versionCheck = function (clientVersions, serverVersions, expected) {\n      test.equal(\n        DDPServer._calculateVersion(clientVersions, serverVersions),\n        expected);\n    };\n\n    versionCheck([\"A\", \"B\", \"C\"], [\"A\", \"B\", \"C\"], \"A\");\n    versionCheck([\"B\", \"C\"], [\"A\", \"B\", \"C\"], \"B\");\n    versionCheck([\"A\", \"B\", \"C\"], [\"B\", \"C\"], \"B\");\n    versionCheck([\"foo\", \"bar\", \"baz\"], [\"A\", \"B\", \"C\"], \"A\");\n  });\n}\n\nTinytest.add(\"livedata - methods with colliding names\", function (test) {\n  var x = Random.id();\n  var m = {};\n  m[x] = function () {};\n  Meteor.methods(m);\n\n  test.throws(function () {\n    Meteor.methods(m);\n  });\n});\n\nTinytest.add(\"livedata - non-function method\", function (test) {\n  var x = Random.id();\n  var m = {};\n  m[x] = 'kitten';\n\n  test.throws(function () {\n    Meteor.methods(m);\n  });\n});\n\nvar echoTest = function (item) {\n  return function (test, expect) {\n    if (Meteor.isServer) {\n      test.equal(Meteor.call(\"echo\", item), [item]);\n      test.equal(Meteor.call(\"echoOne\", item), item);\n    }\n    if (Meteor.isClient)\n      test.equal(Meteor.call(\"echo\", item), undefined);\n\n    test.equal(Meteor.call(\"echo\", item, expect(undefined, [item])), undefined);\n    test.equal(Meteor.call(\"echoOne\", item, expect(undefined, item)), undefined);\n  };\n};\n\ntestAsyncMulti(\"livedata - basic method invocation\", [\n  // Unknown methods\n  function (test, expect) {\n    if (Meteor.isServer) {\n      // On server, with no callback, throws exception\n      try {\n        var ret = Meteor.call(\"unknown method\");\n      } catch (e) {\n        test.equal(e.error, 404);\n        var threw = true;\n      }\n      test.isTrue(threw);\n      test.equal(ret, undefined);\n    }\n\n    if (Meteor.isClient) {\n      // On client, with no callback, just returns undefined\n      var ret = Meteor.call(\"unknown method\");\n      test.equal(ret, undefined);\n    }\n\n    // On either, with a callback, calls the callback and does not throw\n    var ret = Meteor.call(\"unknown method\",\n                          expect(failure(test, 404, \"Method 'unknown method' not found\")));\n    test.equal(ret, undefined);\n  },\n\n  function (test, expect) {\n    // make sure 'undefined' is preserved as such, instead of turning\n    // into null (JSON does not have 'undefined' so there is special\n    // code for this)\n    if (Meteor.isServer)\n      test.equal(Meteor.call(\"nothing\"), undefined);\n    if (Meteor.isClient)\n      test.equal(Meteor.call(\"nothing\"), undefined);\n\n    test.equal(Meteor.call(\"nothing\", expect(undefined, undefined)), undefined);\n  },\n\n  function (test, expect) {\n    if (Meteor.isServer)\n      test.equal(Meteor.call(\"echo\"), []);\n    if (Meteor.isClient)\n      test.equal(Meteor.call(\"echo\"), undefined);\n\n    test.equal(Meteor.call(\"echo\", expect(undefined, [])), undefined);\n  },\n\n  echoTest(new Date()),\n  echoTest({d: new Date(), s: \"foobarbaz\"}),\n  echoTest([new Date(), \"foobarbaz\"]),\n  echoTest(new Mongo.ObjectID()),\n  echoTest({o: new Mongo.ObjectID()}),\n  echoTest({$date: 30}), // literal\n  echoTest({$literal: {$date: 30}}),\n  echoTest(12),\n  echoTest(Infinity),\n  echoTest(-Infinity),\n\n  function (test, expect) {\n    if (Meteor.isServer)\n      test.equal(Meteor.call(\"echo\", 12, {x: 13}), [12, {x: 13}]);\n    if (Meteor.isClient)\n      test.equal(Meteor.call(\"echo\", 12, {x: 13}), undefined);\n\n    test.equal(Meteor.call(\"echo\", 12, {x: 13},\n                           expect(undefined, [12, {x: 13}])), undefined);\n  },\n\n  // test that `wait: false` is respected\n  function (test, expect) {\n    if (Meteor.isClient) {\n      // For test isolation\n      var token = Random.id();\n      Meteor.apply(\n        \"delayedTrue\", [token], {wait: false}, expect(function(err, res) {\n          test.equal(res, false);\n        }));\n      Meteor.apply(\"makeDelayedTrueImmediatelyReturnFalse\", [token]);\n    }\n  },\n\n  // test that `wait: true` is respected\n  function(test, expect) {\n    if (Meteor.isClient) {\n      var token = Random.id();\n      Meteor.apply(\n        \"delayedTrue\", [token], {wait: true}, expect(function(err, res) {\n          test.equal(res, true);\n        }));\n      Meteor.apply(\"makeDelayedTrueImmediatelyReturnFalse\", [token]);\n    }\n  },\n\n  function (test, expect) {\n    // No callback\n\n    if (Meteor.isServer) {\n      test.throws(function () {\n        Meteor.call(\"exception\", \"both\");\n      });\n      test.throws(function () {\n        Meteor.call(\"exception\", \"server\");\n      });\n      // No exception, because no code will run on the client\n      test.equal(Meteor.call(\"exception\", \"client\"), undefined);\n    }\n\n    if (Meteor.isClient) {\n      // The client exception is thrown away because it's in the\n      // stub. The server exception is throw away because we didn't\n      // give a callback.\n      test.equal(Meteor.call(\"exception\", \"both\"), undefined);\n      test.equal(Meteor.call(\"exception\", \"server\"), undefined);\n      test.equal(Meteor.call(\"exception\", \"client\"), undefined);\n\n      // If we pass throwStubExceptions then we *should* see thrown exceptions\n      // on the client\n      test.throws(function () {\n        Meteor.apply(\"exception\", [\"both\"], {throwStubExceptions: true});\n      });\n      test.equal(\n        Meteor.apply(\"exception\", [\"server\"], {throwStubExceptions: true}),\n        undefined);\n      test.throws(function () {\n        Meteor.apply(\"exception\", [\"client\"], {throwStubExceptions: true});\n      });\n    }\n\n    // With callback\n\n    if (Meteor.isClient) {\n      test.equal(\n        Meteor.call(\"exception\", \"both\",\n                    expect(failure(test, 500, \"Internal server error\"))),\n        undefined);\n      test.equal(\n        Meteor.call(\"exception\", \"server\",\n                    expect(failure(test, 500, \"Internal server error\"))),\n        undefined);\n      test.equal(Meteor.call(\"exception\", \"client\"), undefined);\n    }\n\n    if (Meteor.isServer) {\n      test.equal(\n        Meteor.call(\"exception\", \"both\",\n                    expect(failure(test, \"Test method throwing an exception\"))),\n        undefined);\n      test.equal(\n        Meteor.call(\"exception\", \"server\",\n                    expect(failure(test, \"Test method throwing an exception\"))),\n        undefined);\n      test.equal(Meteor.call(\"exception\", \"client\"), undefined);\n    }\n  },\n\n  function (test, expect) {\n    if (Meteor.isServer) {\n      var threw = false;\n      try {\n        Meteor.call(\"exception\", \"both\", {intended: true});\n      } catch (e) {\n        threw = true;\n        test.equal(e.error, 999);\n        test.equal(e.reason, \"Client-visible test exception\");\n      }\n      test.isTrue(threw);\n      threw = false;\n      try {\n        Meteor.call(\"exception\", \"both\", {intended: true,\n                                          throwThroughFuture: true});\n      } catch (e) {\n        threw = true;\n        test.equal(e.error, 999);\n        test.equal(e.reason, \"Client-visible test exception\");\n      }\n      test.isTrue(threw);\n    }\n\n    if (Meteor.isClient) {\n      test.equal(\n        Meteor.call(\"exception\", \"both\", {intended: true},\n                    expect(failure(test, 999,\n                                   \"Client-visible test exception\"))),\n        undefined);\n      test.equal(\n        Meteor.call(\"exception\", \"server\", {intended: true},\n                    expect(failure(test, 999,\n                                   \"Client-visible test exception\"))),\n        undefined);\n      test.equal(\n        Meteor.call(\"exception\", \"server\", {intended: true,\n                                            throwThroughFuture: true},\n                    expect(failure(test, 999,\n                                   \"Client-visible test exception\"))),\n        undefined);\n    }\n  }\n]);\n\n\n\n\nvar checkBalances = function (test, a, b) {\n  var alice = Ledger.findOne({name: \"alice\", world: test.runId()});\n  var bob = Ledger.findOne({name: \"bob\", world: test.runId()});\n  test.equal(alice.balance, a);\n  test.equal(bob.balance, b);\n};\n\n// would be nice to have a database-aware test harness of some kind --\n// this is a big hack (and XXX pollutes the global test namespace)\ntestAsyncMulti(\"livedata - compound methods\", [\n  function (test, expect) {\n    if (Meteor.isClient)\n      Meteor.subscribe(\"ledger\", test.runId(), expect());\n\n    Ledger.insert({name: \"alice\", balance: 100, world: test.runId()},\n                  expect(function () {}));\n    Ledger.insert({name: \"bob\", balance: 50, world: test.runId()},\n                  expect(function () {}));\n  },\n  function (test, expect) {\n    Meteor.call('ledger/transfer', test.runId(), \"alice\", \"bob\", 10,\n                expect(function(err, result) {\n                  test.equal(err, undefined);\n                  test.equal(result, undefined);\n                  checkBalances(test, 90, 60);\n                }));\n    checkBalances(test, 90, 60);\n  },\n  function (test, expect) {\n    Meteor.call('ledger/transfer', test.runId(), \"alice\", \"bob\", 100, true,\n                expect(function (err, result) {\n                  failure(test, 409)(err, result);\n                  // Balances are reverted back to pre-stub values.\n                  checkBalances(test, 90, 60);\n                }));\n\n    if (Meteor.isClient)\n      // client can fool itself by cheating, but only until the sync\n      // finishes\n      checkBalances(test, -10, 160);\n    else\n      checkBalances(test, 90, 60);\n  }\n]);\n\n// Replaces the Connection's `_livedata_data` method to push incoming\n// messages on a given collection to an array. This can be used to\n// verify that the right data is sent on the wire\n//\n// @param messages {Array} The array to which to append the messages\n// @return {Function} A function to call to undo the eavesdropping\nvar eavesdropOnCollection = function(livedata_connection,\n                                     collection_name, messages) {\n  var old_livedata_data = _.bind(\n    livedata_connection._livedata_data, livedata_connection);\n\n  // Kind of gross since all tests past this one will run with this\n  // hook set up. That's probably fine since we only check a specific\n  // collection but still...\n  //\n  // Should we consider having a separate connection per Tinytest or\n  // some similar scheme?\n  livedata_connection._livedata_data = function(msg) {\n    if (msg.collection && msg.collection === collection_name) {\n      messages.push(msg);\n    }\n    old_livedata_data(msg);\n  };\n\n  return function() {\n    livedata_connection._livedata_data = old_livedata_data;\n  };\n};\n\nif (Meteor.isClient) {\n  testAsyncMulti(\"livedata - changing userid reruns subscriptions without flapping data on the wire\", [\n    function(test, expect) {\n      var messages = [];\n      var undoEavesdrop = eavesdropOnCollection(\n        Meteor.connection, \"objectsWithUsers\", messages);\n\n      // A helper for testing incoming set and unset messages\n      // XXX should this be extracted as a general helper together with\n      // eavesdropOnCollection?\n      var expectMessages = function(expectedAddedMessageCount,\n                                    expectedRemovedMessageCount,\n                                    expectedNamesInCollection) {\n        var actualAddedMessageCount = 0;\n        var actualRemovedMessageCount = 0;\n        _.each(messages, function (msg) {\n          if (msg.msg === 'added')\n            ++actualAddedMessageCount;\n          else if (msg.msg === 'removed')\n            ++actualRemovedMessageCount;\n          else\n            test.fail({unexpected: JSON.stringify(msg)});\n        });\n        test.equal(actualAddedMessageCount, expectedAddedMessageCount);\n        test.equal(actualRemovedMessageCount, expectedRemovedMessageCount);\n        expectedNamesInCollection.sort();\n        test.equal(_.pluck(objectsWithUsers.find({}, {sort: ['name']}).fetch(),\n                           'name'),\n                   expectedNamesInCollection);\n        messages.length = 0; // clear messages without creating a new object\n      };\n\n      // make sure we're not already logged in. can happen if accounts\n      // tests fail oddly.\n      Meteor.apply(\"setUserId\", [null], {wait: true}, expect(function () {}));\n\n      Meteor.subscribe(\"objectsWithUsers\", expect(function() {\n        expectMessages(1, 0, [\"owned by none\"]);\n        Meteor.apply(\"setUserId\", [\"1\"], {wait: true}, afterFirstSetUserId);\n      }));\n\n      var afterFirstSetUserId = expect(function() {\n        expectMessages(3, 1, [\n          \"owned by one - a\",\n          \"owned by one/two - a\",\n          \"owned by one/two - b\"]);\n        Meteor.apply(\"setUserId\", [\"2\"], {wait: true}, afterSecondSetUserId);\n      });\n\n      var afterSecondSetUserId = expect(function() {\n        expectMessages(2, 1, [\n          \"owned by one/two - a\",\n          \"owned by one/two - b\",\n          \"owned by two - a\",\n          \"owned by two - b\"]);\n        Meteor.apply(\"setUserId\", [\"2\"], {wait: true}, afterThirdSetUserId);\n      });\n\n      var afterThirdSetUserId = expect(function() {\n        // Nothing should have been sent since the results of the\n        // query are the same (\"don't flap data on the wire\")\n        expectMessages(0, 0, [\n          \"owned by one/two - a\",\n          \"owned by one/two - b\",\n          \"owned by two - a\",\n          \"owned by two - b\"]);\n        undoEavesdrop();\n      });\n    }, function(test, expect) {\n      var key = Random.id();\n      Meteor.subscribe(\"recordUserIdOnStop\", key);\n      Meteor.apply(\"setUserId\", [\"100\"], {wait: true}, expect(function () {}));\n      Meteor.apply(\"setUserId\", [\"101\"], {wait: true}, expect(function () {}));\n      Meteor.call(\"userIdWhenStopped\", key, expect(function (err, result) {\n        test.isFalse(err);\n        test.equal(result, \"100\");\n      }));\n      // clean up\n      Meteor.apply(\"setUserId\", [null], {wait: true}, expect(function () {}));\n    }\n  ]);\n}\n\nTinytest.add(\"livedata - setUserId error when called from server\", function(test) {\n  if (Meteor.isServer) {\n    test.equal(errorThrownWhenCallingSetUserIdDirectlyOnServer.message,\n               \"Can't call setUserId on a server initiated method call\");\n  }\n});\n\n\nif (Meteor.isServer) {\n  var pubHandles = {};\n};\nMeteor.methods({\n  \"livedata/setup\" : function (id) {\n    check(id, String);\n    if (Meteor.isServer) {\n      pubHandles[id] = {};\n      Meteor.publish(\"pub1\"+id, function () {\n        pubHandles[id].pub1 = this;\n        this.ready();\n      });\n      Meteor.publish(\"pub2\"+id, function () {\n        pubHandles[id].pub2 = this;\n        this.ready();\n      });\n\n    }\n  },\n  \"livedata/pub1go\" : function (id) {\n    check(id, String);\n    if (Meteor.isServer) {\n\n      pubHandles[id].pub1.added(\"MultiPubCollection\" + id, \"foo\", {a: \"aa\"});\n      return 1;\n    }\n    return 0;\n  },\n  \"livedata/pub2go\" : function (id) {\n    check(id, String);\n    if (Meteor.isServer) {\n      pubHandles[id].pub2.added(\"MultiPubCollection\" + id , \"foo\", {b: \"bb\"});\n      return 2;\n    }\n    return 0;\n  }\n});\n\nif (Meteor.isClient) {\n  (function () {\n    var MultiPub;\n    var id = Random.id();\n    testAsyncMulti(\"livedata - added from two different subs\", [\n      function (test, expect) {\n        Meteor.call('livedata/setup', id, expect(function () {}));\n      },\n      function (test, expect) {\n        MultiPub = new Mongo.Collection(\"MultiPubCollection\" + id);\n        var sub1 = Meteor.subscribe(\"pub1\"+id, expect(function () {}));\n        var sub2 = Meteor.subscribe(\"pub2\"+id, expect(function () {}));\n      },\n      function (test, expect) {\n        Meteor.call(\"livedata/pub1go\", id, expect(function (err, res) {test.equal(res, 1);}));\n      },\n      function (test, expect) {\n        test.equal(MultiPub.findOne(\"foo\"), {_id: \"foo\", a: \"aa\"});\n      },\n      function (test, expect) {\n        Meteor.call(\"livedata/pub2go\", id, expect(function (err, res) {test.equal(res, 2);}));\n      },\n      function (test, expect) {\n        test.equal(MultiPub.findOne(\"foo\"), {_id: \"foo\", a: \"aa\", b: \"bb\"});\n      }\n    ]);\n  })();\n};\n\nif (Meteor.isClient) {\n  testAsyncMulti(\"livedata - overlapping universal subs\", [\n    function (test, expect) {\n      var coll = new Mongo.Collection(\"overlappingUniversalSubs\");\n      var token = Random.id();\n      test.isFalse(coll.findOne(token));\n      Meteor.call(\"testOverlappingSubs\", token, expect(function (err) {\n        test.isFalse(err);\n        test.isTrue(coll.findOne(token));\n      }));\n    }\n  ]);\n\n  testAsyncMulti(\"livedata - runtime universal sub creation\", [\n    function (test, expect) {\n      var coll = new Mongo.Collection(\"runtimeSubCreation\");\n      var token = Random.id();\n      test.isFalse(coll.findOne(token));\n      Meteor.call(\"runtimeUniversalSubCreation\", token, expect(function (err) {\n        test.isFalse(err);\n        test.isTrue(coll.findOne(token));\n      }));\n    }\n  ]);\n\n  testAsyncMulti(\"livedata - no setUserId after unblock\", [\n    function (test, expect) {\n      Meteor.call(\"setUserIdAfterUnblock\", expect(function (err, result) {\n        test.isFalse(err);\n        test.isTrue(result);\n      }));\n    }\n  ]);\n\n  testAsyncMulti(\"livedata - publisher errors with onError callback\", (function () {\n    var conn, collName, coll;\n    var errorFromRerun;\n    var gotErrorFromStopper = false;\n    return [\n      function (test, expect) {\n        // Use a separate connection so that we can safely check to see if\n        // conn._subscriptions is empty.\n        conn = new LivedataTest.Connection('/',\n                                           {reloadWithOutstanding: true});\n        collName = Random.id();\n        coll = new Mongo.Collection(collName, {connection: conn});\n\n        var testSubError = function (options) {\n          conn.subscribe(\"publisherErrors\", collName, options, {\n            onReady: expect(),\n            onError: expect(\n              failure(test,\n                      options.internalError ? 500 : 412,\n                      options.internalError ? \"Internal server error\"\n                                            : \"Explicit error\"))\n          });\n        };\n        testSubError({throwInHandler: true});\n        testSubError({throwInHandler: true, internalError: true});\n        testSubError({errorInHandler: true});\n        testSubError({errorInHandler: true, internalError: true});\n        testSubError({errorLater: true});\n        testSubError({errorLater: true, internalError: true});\n      },\n      function (test, expect) {\n        test.equal(coll.find().count(), 0);\n        test.equal(_.size(conn._subscriptions), 0);  // white-box test\n\n        conn.subscribe(\"publisherErrors\",\n                       collName, {throwWhenUserIdSet: true}, {\n          onReady: expect(),\n          onError: function (error) {\n            errorFromRerun = error;\n          }\n        });\n      },\n      function (test, expect) {\n        // Because the last subscription is ready, we should have a document.\n        test.equal(coll.find().count(), 1);\n        test.isFalse(errorFromRerun);\n        test.equal(_.size(conn._subscriptions), 1);  // white-box test\n        conn.call('setUserId', 'bla', expect(function(){}));\n      },\n      function (test, expect) {\n        // Now that we've re-run, we should have stopped the subscription,\n        // gotten a error, and lost the document.\n        test.equal(coll.find().count(), 0);\n        test.isTrue(errorFromRerun);\n        test.instanceOf(errorFromRerun, Meteor.Error);\n        test.equal(errorFromRerun.error, 412);\n        test.equal(errorFromRerun.reason, \"Explicit error\");\n        test.equal(_.size(conn._subscriptions), 0);  // white-box test\n\n        conn.subscribe(\"publisherErrors\", collName, {stopInHandler: true}, {\n          onError: function() { gotErrorFromStopper = true; }\n        });\n        // Call a method. This method won't be processed until the publisher's\n        // function returns, so blocking on it being done ensures that we've\n        // gotten the removed/nosub/etc.\n        conn.call('nothing', expect(function(){}));\n      },\n      function (test, expect) {\n        test.equal(coll.find().count(), 0);\n        // sub.stop does NOT call onError.\n        test.isFalse(gotErrorFromStopper);\n        test.equal(_.size(conn._subscriptions), 0);  // white-box test\n        conn._stream.disconnect({_permanent: true});\n      }\n    ];})());\n\n  testAsyncMulti(\"livedata - publisher errors with onStop callback\", (function () {\n    var conn, collName, coll;\n    var errorFromRerun;\n    var gotErrorFromStopper = false;\n    return [\n      function (test, expect) {\n        // Use a separate connection so that we can safely check to see if\n        // conn._subscriptions is empty.\n        conn = new LivedataTest.Connection('/',\n                                           {reloadWithOutstanding: true});\n        collName = Random.id();\n        coll = new Mongo.Collection(collName, {connection: conn});\n\n        var testSubError = function (options) {\n          conn.subscribe(\"publisherErrors\", collName, options, {\n            onReady: expect(),\n            onStop: expect(\n              failureOnStopped(test,\n                      options.internalError ? 500 : 412,\n                      options.internalError ? \"Internal server error\"\n                                            : \"Explicit error\"))\n          });\n        };\n        testSubError({throwInHandler: true});\n        testSubError({throwInHandler: true, internalError: true});\n        testSubError({errorInHandler: true});\n        testSubError({errorInHandler: true, internalError: true});\n        testSubError({errorLater: true});\n        testSubError({errorLater: true, internalError: true});\n      },\n      function (test, expect) {\n        test.equal(coll.find().count(), 0);\n        test.equal(_.size(conn._subscriptions), 0);  // white-box test\n\n        conn.subscribe(\"publisherErrors\",\n                       collName, {throwWhenUserIdSet: true}, {\n          onReady: expect(),\n          onStop: function (error) {\n            errorFromRerun = error;\n          }\n        });\n      },\n      function (test, expect) {\n        // Because the last subscription is ready, we should have a document.\n        test.equal(coll.find().count(), 1);\n        test.isFalse(errorFromRerun);\n        test.equal(_.size(conn._subscriptions), 1);  // white-box test\n        conn.call('setUserId', 'bla', expect(function(){}));\n      },\n      function (test, expect) {\n        // Now that we've re-run, we should have stopped the subscription,\n        // gotten a error, and lost the document.\n        test.equal(coll.find().count(), 0);\n        test.isTrue(errorFromRerun);\n        test.instanceOf(errorFromRerun, Meteor.Error);\n        test.equal(errorFromRerun.error, 412);\n        test.equal(errorFromRerun.reason, \"Explicit error\");\n        test.equal(_.size(conn._subscriptions), 0);  // white-box test\n\n        conn.subscribe(\"publisherErrors\", collName, {stopInHandler: true}, {\n          onStop: function(error) {\n            if (error) {\n              gotErrorFromStopper = true;\n            }\n          }\n        });\n        // Call a method. This method won't be processed until the publisher's\n        // function returns, so blocking on it being done ensures that we've\n        // gotten the removed/nosub/etc.\n        conn.call('nothing', expect(function(){}));\n      },\n      function (test, expect) {\n        test.equal(coll.find().count(), 0);\n        // sub.stop does NOT call onError.\n        test.isFalse(gotErrorFromStopper);\n        test.equal(_.size(conn._subscriptions), 0);  // white-box test\n        conn._stream.disconnect({_permanent: true});\n      }\n    ];})());\n\n  testAsyncMulti(\"livedata - publish multiple cursors\", [\n    function (test, expect) {\n      var sub = Meteor.subscribe(\"multiPublish\", {normal: 1}, {\n        onReady: expect(function () {\n          test.isTrue(sub.ready());\n          test.equal(One.find().count(), 2);\n          test.equal(Two.find().count(), 3);\n        }),\n        onError: failure()\n      });\n    },\n    function (test, expect) {\n      Meteor.subscribe(\"multiPublish\", {dup: 1}, {\n        onReady: failure(),\n        onError: expect(failure(test, 500, \"Internal server error\"))\n      });\n    },\n    function (test, expect) {\n      Meteor.subscribe(\"multiPublish\", {notCursor: 1}, {\n        onReady: failure(),\n        onError: expect(failure(test, 500, \"Internal server error\"))\n      });\n    }\n  ]);\n}\n\nvar selfUrl = Meteor.isServer\n      ? Meteor.absoluteUrl() : Meteor._relativeToSiteRootUrl('/');\n\nif (Meteor.isServer) {\n  Meteor.methods({\n    \"s2s\": function (arg) {\n      check(arg, String);\n      return \"s2s \" + arg;\n    }\n  });\n}\n(function () {\n  testAsyncMulti(\"livedata - connect works from both client and server\", [\n    function (test, expect) {\n      var self = this;\n      self.conn = DDP.connect(selfUrl);\n      pollUntil(expect, function () {\n        return self.conn.status().connected;\n      }, 10000);\n    },\n\n    function (test, expect) {\n      var self = this;\n      if (self.conn.status().connected) {\n        self.conn.call('s2s', 'foo', expect(function (err, res) {\n          if (err)\n            throw err;\n          test.equal(res, \"s2s foo\");\n        }));\n      }\n    }\n  ]);\n})();\n\nif (Meteor.isServer) {\n  (function () {\n    testAsyncMulti(\"livedata - method call on server blocks in a fiber way\", [\n      function (test, expect) {\n        var self = this;\n        self.conn = DDP.connect(selfUrl);\n        pollUntil(expect, function () {\n          return self.conn.status().connected;\n        }, 10000);\n      },\n\n      function (test, expect) {\n        var self = this;\n        if (self.conn.status().connected) {\n          test.equal(self.conn.call('s2s', 'foo'), \"s2s foo\");\n        }\n      }\n    ]);\n  })();\n}\n\n(function () {\n  testAsyncMulti(\"livedata - connect fails to unknown place\", [\n    function (test, expect) {\n      var self = this;\n      self.conn = DDP.connect(\"example.com\", {_dontPrintErrors: true});\n      Meteor.setTimeout(expect(function () {\n        test.isFalse(self.conn.status().connected, \"Not connected\");\n        self.conn.close();\n      }), 500);\n    }\n  ]);\n})();\n\nif (Meteor.isServer) {\n  Meteor.publish(\"publisherCloning\", function () {\n    var self = this;\n    var fields = {x: {y: 42}};\n    self.added(\"publisherCloning\", \"a\", fields);\n    fields.x.y = 43;\n    self.changed(\"publisherCloning\", \"a\", fields);\n    self.ready();\n  });\n} else {\n  var PublisherCloningCollection = new Mongo.Collection(\"publisherCloning\");\n  testAsyncMulti(\"livedata - publish callbacks clone\", [\n    function (test, expect) {\n      Meteor.subscribe(\"publisherCloning\", {normal: 1}, {\n        onReady: expect(function () {\n          test.equal(PublisherCloningCollection.findOne(), {\n            _id: \"a\",\n            x: {y: 43}});\n        }),\n        onError: failure()\n      });\n    }\n  ]);\n}\n\ntestAsyncMulti(\"livedata - result by value\", [\n  function (test, expect) {\n    var self = this;\n    self.testId = Random.id();\n    Meteor.call('getArray', self.testId, expect(function (error, firstResult) {\n      test.isFalse(error);\n      test.isTrue(firstResult);\n      self.firstResult = firstResult;\n    }));\n  }, function (test, expect) {\n    var self = this;\n    Meteor.call('pushToArray', self.testId, 'xxx', expect(function (error) {\n      test.isFalse(error);\n    }));\n  }, function (test, expect) {\n    var self = this;\n    Meteor.call('getArray', self.testId, expect(function (error, secondResult) {\n      test.isFalse(error);\n      test.equal(self.firstResult.length + 1, secondResult.length);\n    }));\n  }\n]);\n\n// XXX some things to test in greater detail:\n// staying in simulation mode\n// time warp\n// serialization / beginAsync(true) / beginAsync(false)\n// malformed messages (need raw wire access)\n// method completion/satisfaction\n// subscriptions (multiple APIs, including autorun?)\n// subscription completion\n// subscription attribute shadowing\n// server method calling methods on other server (eg, should simulate)\n// subscriptions and methods being idempotent\n// reconnection\n// reconnection not resulting in method re-execution\n// reconnection tolerating all kinds of lost messages (including data)\n// [probably lots more]\n"
  },
  {
    "path": "packages/ddp-client/namespace.js",
    "content": "/**\n * @namespace DDP\n * @summary Namespace for DDP-related methods/classes.\n */\nDDP          = {};\nLivedataTest = {};\n"
  },
  {
    "path": "packages/ddp-client/package.js",
    "content": "Package.describe({\n  summary: \"Meteor's latency-compensated distributed data client\",\n  version: '1.2.8_1',\n  documentation: null\n});\n\nNpm.depends({\n  \"faye-websocket\": \"0.9.4\",\n  \"lolex\": \"1.4.0\",\n  \"permessage-deflate\": \"0.1.3\"\n});\n\nPackage.onUse(function (api) {\n  api.use(['check', 'random', 'ejson', 'underscore', 'tracker',\n           'retry', 'id-map'],\n          ['client', 'server']);\n\n  // common functionality\n  api.use('ddp-common', ['client', 'server']);\n\n  api.use('reload', 'client', {weak: true});\n\n  // we depend on _diffObjects, _applyChanges,\n  api.use('diff-sequence', ['client', 'server']);\n  // _idParse, _idStringify.\n  api.use('mongo-id', ['client', 'server']);\n\n  api.addFiles('namespace.js', ['client', 'server']);\n\n  api.addFiles('id_map.js', ['client', 'server']);\n  api.addFiles(['sockjs-0.3.4.js', 'stream_client_sockjs.js'], 'client');\n  api.addFiles('stream_client_nodejs.js', 'server');\n  api.addFiles('stream_client_common.js', ['client', 'server']);\n\n  api.addFiles('livedata_common.js', ['client', 'server']);\n  api.addFiles('random_stream.js', ['client', 'server']);\n\n  api.addFiles('livedata_connection.js', ['client', 'server']);\n\n  api.addFiles('client_convenience.js', 'client');\n\n  api.export('DDP');\n  api.export('LivedataTest', {testOnly: true});\n});\n\n\nPackage.onTest(function (api) {\n  api.use('livedata', ['client', 'server']);\n  api.use('mongo', ['client', 'server']);\n  api.use('test-helpers', ['client', 'server']);\n  api.use([\n    'ecmascript',\n    'underscore',\n    'tinytest',\n    'random',\n    'tracker',\n    'reactive-var',\n    'mongo-id',\n    'diff-sequence',\n    'ejson'\n  ]);\n\n  api.addFiles('stub_stream.js');\n  api.addFiles('livedata_connection_tests.js', ['client', 'server']);\n  api.addFiles('livedata_tests.js', ['client', 'server']);\n  api.addFiles('livedata_test_service.js', ['client', 'server']);\n  api.addFiles('random_stream_tests.js', ['client', 'server']);\n\n  api.use('http', 'client');\n  api.addFiles(['stream_tests.js'], 'client');\n  api.addFiles('stream_client_tests.js', 'server');\n  api.use('check', ['client', 'server']);\n});\n"
  },
  {
    "path": "packages/ddp-client/random_stream.js",
    "content": "// Returns the named sequence of pseudo-random values.\n// The scope will be DDP._CurrentInvocation.get(), so the stream will produce\n// consistent values for method calls on the client and server.\nDDP.randomStream = function (name) {\n  var scope = DDP._CurrentInvocation.get();\n  return DDPCommon.RandomStream.get(scope, name);\n};\n\n\n"
  },
  {
    "path": "packages/ddp-client/random_stream_tests.js",
    "content": "Tinytest.add(\"livedata - DDP.randomStream\", function (test) {\n  var randomSeed = Random.id();\n  var context = { randomSeed: randomSeed };\n\n  var sequence = DDP._CurrentInvocation.withValue(context, function () {\n    return DDP.randomStream('1');\n  });\n\n  var seeds = sequence.alea.args;\n\n  test.equal(seeds.length, 2);\n  test.equal(seeds[0], randomSeed);\n  test.equal(seeds[1], '1');\n\n  var id1 = sequence.id();\n\n  // Clone the sequence by building it the same way RandomStream.get does\n  var sequenceClone = Random.createWithSeeds.apply(null, seeds);\n  var id1Cloned = sequenceClone.id();\n  var id2Cloned = sequenceClone.id();\n  test.equal(id1, id1Cloned);\n\n  // We should get the same sequence when we use the same key\n  sequence = DDP._CurrentInvocation.withValue(context, function () {\n    return DDP.randomStream('1');\n  });\n  seeds = sequence.alea.args;\n  test.equal(seeds.length, 2);\n  test.equal(seeds[0], randomSeed);\n  test.equal(seeds[1], '1');\n\n  // But we should be at the 'next' position in the stream\n  var id2 = sequence.id();\n\n  // Technically these could be equal, but likely to be a bug if hit\n  // http://search.dilbert.com/comic/Random%20Number%20Generator\n  test.notEqual(id1, id2);\n\n  test.equal(id2, id2Cloned);\n});\n\nTinytest.add(\"livedata - DDP.randomStream with no-args\", function (test) {\n  DDP.randomStream().id();\n});\n"
  },
  {
    "path": "packages/ddp-client/sockjs-0.3.4.js",
    "content": "// XXX METEOR changes in <METEOR>\n\n/* SockJS client, version 0.3.4, http://sockjs.org, MIT License\n\nCopyright (c) 2011-2012 VMware, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// <METEOR> Commented out JSO implementation (use json package instead).\n// JSON2 by Douglas Crockford (minified).\n// var JSON;JSON||(JSON={}),function(){function str(a,b){var c,d,e,f,g=gap,h,i=b[a];i&&typeof i==\"object\"&&typeof i.toJSON==\"function\"&&(i=i.toJSON(a)),typeof rep==\"function\"&&(i=rep.call(b,a,i));switch(typeof i){case\"string\":return quote(i);case\"number\":return isFinite(i)?String(i):\"null\";case\"boolean\":case\"null\":return String(i);case\"object\":if(!i)return\"null\";gap+=indent,h=[];if(Object.prototype.toString.apply(i)===\"[object Array]\"){f=i.length;for(c=0;c<f;c+=1)h[c]=str(c,i)||\"null\";e=h.length===0?\"[]\":gap?\"[\\n\"+gap+h.join(\",\\n\"+gap)+\"\\n\"+g+\"]\":\"[\"+h.join(\",\")+\"]\",gap=g;return e}if(rep&&typeof rep==\"object\"){f=rep.length;for(c=0;c<f;c+=1)typeof rep[c]==\"string\"&&(d=rep[c],e=str(d,i),e&&h.push(quote(d)+(gap?\": \":\":\")+e))}else for(d in i)Object.prototype.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&h.push(quote(d)+(gap?\": \":\":\")+e));e=h.length===0?\"{}\":gap?\"{\\n\"+gap+h.join(\",\\n\"+gap)+\"\\n\"+g+\"}\":\"{\"+h.join(\",\")+\"}\",gap=g;return e}}function quote(a){escapable.lastIndex=0;return escapable.test(a)?'\"'+a.replace(escapable,function(a){var b=meta[a];return typeof b==\"string\"?b:\"\\\\u\"+(\"0000\"+a.charCodeAt(0).toString(16)).slice(-4)})+'\"':'\"'+a+'\"'}function f(a){return a<10?\"0\"+a:a}\"use strict\",typeof Date.prototype.toJSON!=\"function\"&&(Date.prototype.toJSON=function(a){return isFinite(this.valueOf())?this.getUTCFullYear()+\"-\"+f(this.getUTCMonth()+1)+\"-\"+f(this.getUTCDate())+\"T\"+f(this.getUTCHours())+\":\"+f(this.getUTCMinutes())+\":\"+f(this.getUTCSeconds())+\"Z\":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()});var cx=/[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,escapable=/[\\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,gap,indent,meta={\"\\b\":\"\\\\b\",\"\\t\":\"\\\\t\",\"\\n\":\"\\\\n\",\"\\f\":\"\\\\f\",\"\\r\":\"\\\\r\",'\"':'\\\\\"',\"\\\\\":\"\\\\\\\\\"},rep;typeof JSON.stringify!=\"function\"&&(JSON.stringify=function(a,b,c){var d;gap=\"\",indent=\"\";if(typeof c==\"number\")for(d=0;d<c;d+=1)indent+=\" \";else typeof c==\"string\"&&(indent=c);rep=b;if(!b||typeof b==\"function\"||typeof b==\"object\"&&typeof b.length==\"number\")return str(\"\",{\"\":a});throw new Error(\"JSON.stringify\")}),typeof JSON.parse!=\"function\"&&(JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&typeof e==\"object\")for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=walk(e,c),d!==undefined?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return\"\\\\u\"+(\"0000\"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\\],:{}\\s]*$/.test(text.replace(/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\"@\").replace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\"]\").replace(/(?:^|:|,)(?:\\s*\\[)+/g,\"\"))){j=eval(\"(\"+text+\")\");return typeof reviver==\"function\"?walk({\"\":j},\"\"):j}throw new SyntaxError(\"JSON.parse\")})}()\n// </METEOR>\n\n//     [*] Including lib/index.js\n// Public object\nSockJS = (function(){\n              var _document = document;\n              var _window = window;\n              var utils = {};\n\n\n//         [*] Including lib/reventtarget.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\n/* Simplified implementation of DOM2 EventTarget.\n *   http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget\n */\nvar REventTarget = function() {};\nREventTarget.prototype.addEventListener = function (eventType, listener) {\n    if(!this._listeners) {\n         this._listeners = {};\n    }\n    if(!(eventType in this._listeners)) {\n        this._listeners[eventType] = [];\n    }\n    var arr = this._listeners[eventType];\n    if(utils.arrIndexOf(arr, listener) === -1) {\n        arr.push(listener);\n    }\n    return;\n};\n\nREventTarget.prototype.removeEventListener = function (eventType, listener) {\n    if(!(this._listeners && (eventType in this._listeners))) {\n        return;\n    }\n    var arr = this._listeners[eventType];\n    var idx = utils.arrIndexOf(arr, listener);\n    if (idx !== -1) {\n        if(arr.length > 1) {\n            this._listeners[eventType] = arr.slice(0, idx).concat( arr.slice(idx+1) );\n        } else {\n            delete this._listeners[eventType];\n        }\n        return;\n    }\n    return;\n};\n\nREventTarget.prototype.dispatchEvent = function (event) {\n    var t = event.type;\n    var args = Array.prototype.slice.call(arguments, 0);\n    if (this['on'+t]) {\n        this['on'+t].apply(this, args);\n    }\n    if (this._listeners && t in this._listeners) {\n        for(var i=0; i < this._listeners[t].length; i++) {\n            this._listeners[t][i].apply(this, args);\n        }\n    }\n};\n//         [*] End of lib/reventtarget.js\n\n\n//         [*] Including lib/simpleevent.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar SimpleEvent = function(type, obj) {\n    this.type = type;\n    if (typeof obj !== 'undefined') {\n        for(var k in obj) {\n            if (!obj.hasOwnProperty(k)) continue;\n            this[k] = obj[k];\n        }\n    }\n};\n\nSimpleEvent.prototype.toString = function() {\n    var r = [];\n    for(var k in this) {\n        if (!this.hasOwnProperty(k)) continue;\n        var v = this[k];\n        if (typeof v === 'function') v = '[function]';\n        r.push(k + '=' + v);\n    }\n    return 'SimpleEvent(' + r.join(', ') + ')';\n};\n//         [*] End of lib/simpleevent.js\n\n\n//         [*] Including lib/eventemitter.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar EventEmitter = function(events) {\n    var that = this;\n    that._events = events || [];\n    that._listeners = {};\n};\nEventEmitter.prototype.emit = function(type) {\n    var that = this;\n    that._verifyType(type);\n    if (that._nuked) return;\n\n    var args = Array.prototype.slice.call(arguments, 1);\n    if (that['on'+type]) {\n        that['on'+type].apply(that, args);\n    }\n    if (type in that._listeners) {\n        for(var i = 0; i < that._listeners[type].length; i++) {\n            that._listeners[type][i].apply(that, args);\n        }\n    }\n};\n\nEventEmitter.prototype.on = function(type, callback) {\n    var that = this;\n    that._verifyType(type);\n    if (that._nuked) return;\n\n    if (!(type in that._listeners)) {\n        that._listeners[type] = [];\n    }\n    that._listeners[type].push(callback);\n};\n\nEventEmitter.prototype._verifyType = function(type) {\n    var that = this;\n    if (utils.arrIndexOf(that._events, type) === -1) {\n        utils.log('Event ' + JSON.stringify(type) +\n                  ' not listed ' + JSON.stringify(that._events) +\n                  ' in ' + that);\n    }\n};\n\nEventEmitter.prototype.nuke = function() {\n    var that = this;\n    that._nuked = true;\n    for(var i=0; i<that._events.length; i++) {\n        delete that[that._events[i]];\n    }\n    that._listeners = {};\n};\n//         [*] End of lib/eventemitter.js\n\n\n//         [*] Including lib/utils.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar random_string_chars = 'abcdefghijklmnopqrstuvwxyz0123456789_';\nutils.random_string = function(length, max) {\n    max = max || random_string_chars.length;\n    var i, ret = [];\n    for(i=0; i < length; i++) {\n        ret.push( random_string_chars.substr(Math.floor(Math.random() * max),1) );\n    }\n    return ret.join('');\n};\nutils.random_number = function(max) {\n    return Math.floor(Math.random() * max);\n};\nutils.random_number_string = function(max) {\n    var t = (''+(max - 1)).length;\n    var p = Array(t+1).join('0');\n    return (p + utils.random_number(max)).slice(-t);\n};\n\n// Assuming that url looks like: http://asdasd:111/asd\nutils.getOrigin = function(url) {\n    url += '/';\n    var parts = url.split('/').slice(0, 3);\n    return parts.join('/');\n};\n\nutils.isSameOriginUrl = function(url_a, url_b) {\n    // location.origin would do, but it's not always available.\n    if (!url_b) url_b = _window.location.href;\n\n    return (url_a.split('/').slice(0,3).join('/')\n                ===\n            url_b.split('/').slice(0,3).join('/'));\n};\n\n// <METEOR>\n// https://github.com/sockjs/sockjs-client/issues/79\nutils.isSameOriginScheme = function(url_a, url_b) {\n    if (!url_b) url_b = _window.location.href;\n\n    return (url_a.split(':')[0]\n                ===\n            url_b.split(':')[0]);\n};\n// </METEOR>\n\n\nutils.getParentDomain = function(url) {\n    // ipv4 ip address\n    if (/^[0-9.]*$/.test(url)) return url;\n    // ipv6 ip address\n    if (/^\\[/.test(url)) return url;\n    // no dots\n    if (!(/[.]/.test(url))) return url;\n\n    var parts = url.split('.').slice(1);\n    return parts.join('.');\n};\n\nutils.objectExtend = function(dst, src) {\n    for(var k in src) {\n        if (src.hasOwnProperty(k)) {\n            dst[k] = src[k];\n        }\n    }\n    return dst;\n};\n\nvar WPrefix = '_jp';\n\nutils.polluteGlobalNamespace = function() {\n    if (!(WPrefix in _window)) {\n        _window[WPrefix] = {};\n    }\n};\n\nutils.closeFrame = function (code, reason) {\n    return 'c'+JSON.stringify([code, reason]);\n};\n\nutils.userSetCode = function (code) {\n    return code === 1000 || (code >= 3000 && code <= 4999);\n};\n\n// See: http://www.erg.abdn.ac.uk/~gerrit/dccp/notes/ccid2/rto_estimator/\n// and RFC 2988.\nutils.countRTO = function (rtt) {\n    var rto;\n    if (rtt > 100) {\n        rto = 3 * rtt; // rto > 300msec\n    } else {\n        rto = rtt + 200; // 200msec < rto <= 300msec\n    }\n    return rto;\n}\n\nutils.log = function() {\n    if (_window.console && console.log && console.log.apply) {\n        console.log.apply(console, arguments);\n    }\n};\n\nutils.bind = function(fun, that) {\n    if (fun.bind) {\n        return fun.bind(that);\n    } else {\n        return function() {\n            return fun.apply(that, arguments);\n        };\n    }\n};\n\nutils.flatUrl = function(url) {\n    return url.indexOf('?') === -1 && url.indexOf('#') === -1;\n};\n\n// `relativeTo` is an optional absolute URL. If provided, `url` will be\n// interpreted relative to `relativeTo`. Defaults to `document.location`.\n// <METEOR>\nutils.amendUrl = function(url, relativeTo) {\n    var baseUrl;\n    if (relativeTo === undefined) {\n      baseUrl = _document.location;\n    } else {\n      var protocolMatch = /^([a-z0-9.+-]+:)/i.exec(relativeTo);\n      if (protocolMatch) {\n        var protocol = protocolMatch[0].toLowerCase();\n        var rest = relativeTo.substring(protocol.length);\n        var hostMatch = /[a-z0-9\\.-]+(:[0-9]+)?/.exec(rest);\n        if (hostMatch)\n          var host = hostMatch[0];\n      }\n      if (! protocol || ! host)\n        throw new Error(\"relativeTo must be an absolute url\");\n      baseUrl = {\n        protocol: protocol,\n        host: host\n      };\n    }\n    if (!url) {\n        throw new Error('Wrong url for SockJS');\n    }\n    if (!utils.flatUrl(url)) {\n        throw new Error('Only basic urls are supported in SockJS');\n    }\n\n    //  '//abc' --> 'http://abc'\n    if (url.indexOf('//') === 0) {\n        url = baseUrl.protocol + url;\n    }\n    // '/abc' --> 'http://localhost:1234/abc'\n    if (url.indexOf('/') === 0) {\n        url = baseUrl.protocol + '//' + baseUrl.host + url;\n    }\n    // </METEOR>\n    // strip trailing slashes\n    url = url.replace(/[/]+$/,'');\n\n    // We have a full url here, with proto and host. For some browsers\n    // http://localhost:80/ is not in the same origin as http://localhost/\n\t// Remove explicit :80 or :443 in such cases. See #74\n    var parts = url.split(\"/\");\n    if ((parts[0] === \"http:\" && /:80$/.test(parts[2])) ||\n\t    (parts[0] === \"https:\" && /:443$/.test(parts[2]))) {\n\t\tparts[2] = parts[2].replace(/:(80|443)$/, \"\");\n\t}\n    url = parts.join(\"/\");\n    return url;\n};\n\n// IE doesn't support [].indexOf.\nutils.arrIndexOf = function(arr, obj){\n    for(var i=0; i < arr.length; i++){\n        if(arr[i] === obj){\n            return i;\n        }\n    }\n    return -1;\n};\n\nutils.arrSkip = function(arr, obj) {\n    var idx = utils.arrIndexOf(arr, obj);\n    if (idx === -1) {\n        return arr.slice();\n    } else {\n        var dst = arr.slice(0, idx);\n        return dst.concat(arr.slice(idx+1));\n    }\n};\n\n// Via: https://gist.github.com/1133122/2121c601c5549155483f50be3da5305e83b8c5df\nutils.isArray = Array.isArray || function(value) {\n    return {}.toString.call(value).indexOf('Array') >= 0\n};\n\nutils.delay = function(t, fun) {\n    if(typeof t === 'function') {\n        fun = t;\n        t = 0;\n    }\n    return setTimeout(fun, t);\n};\n\n\n// Chars worth escaping, as defined by Douglas Crockford:\n//   https://github.com/douglascrockford/JSON-js/blob/47a9882cddeb1e8529e07af9736218075372b8ac/json2.js#L196\nvar json_escapable = /[\\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n    json_lookup = {\n\"\\u0000\":\"\\\\u0000\",\"\\u0001\":\"\\\\u0001\",\"\\u0002\":\"\\\\u0002\",\"\\u0003\":\"\\\\u0003\",\n\"\\u0004\":\"\\\\u0004\",\"\\u0005\":\"\\\\u0005\",\"\\u0006\":\"\\\\u0006\",\"\\u0007\":\"\\\\u0007\",\n\"\\b\":\"\\\\b\",\"\\t\":\"\\\\t\",\"\\n\":\"\\\\n\",\"\\u000b\":\"\\\\u000b\",\"\\f\":\"\\\\f\",\"\\r\":\"\\\\r\",\n\"\\u000e\":\"\\\\u000e\",\"\\u000f\":\"\\\\u000f\",\"\\u0010\":\"\\\\u0010\",\"\\u0011\":\"\\\\u0011\",\n\"\\u0012\":\"\\\\u0012\",\"\\u0013\":\"\\\\u0013\",\"\\u0014\":\"\\\\u0014\",\"\\u0015\":\"\\\\u0015\",\n\"\\u0016\":\"\\\\u0016\",\"\\u0017\":\"\\\\u0017\",\"\\u0018\":\"\\\\u0018\",\"\\u0019\":\"\\\\u0019\",\n\"\\u001a\":\"\\\\u001a\",\"\\u001b\":\"\\\\u001b\",\"\\u001c\":\"\\\\u001c\",\"\\u001d\":\"\\\\u001d\",\n\"\\u001e\":\"\\\\u001e\",\"\\u001f\":\"\\\\u001f\",\"\\\"\":\"\\\\\\\"\",\"\\\\\":\"\\\\\\\\\",\n\"\\u007f\":\"\\\\u007f\",\"\\u0080\":\"\\\\u0080\",\"\\u0081\":\"\\\\u0081\",\"\\u0082\":\"\\\\u0082\",\n\"\\u0083\":\"\\\\u0083\",\"\\u0084\":\"\\\\u0084\",\"\\u0085\":\"\\\\u0085\",\"\\u0086\":\"\\\\u0086\",\n\"\\u0087\":\"\\\\u0087\",\"\\u0088\":\"\\\\u0088\",\"\\u0089\":\"\\\\u0089\",\"\\u008a\":\"\\\\u008a\",\n\"\\u008b\":\"\\\\u008b\",\"\\u008c\":\"\\\\u008c\",\"\\u008d\":\"\\\\u008d\",\"\\u008e\":\"\\\\u008e\",\n\"\\u008f\":\"\\\\u008f\",\"\\u0090\":\"\\\\u0090\",\"\\u0091\":\"\\\\u0091\",\"\\u0092\":\"\\\\u0092\",\n\"\\u0093\":\"\\\\u0093\",\"\\u0094\":\"\\\\u0094\",\"\\u0095\":\"\\\\u0095\",\"\\u0096\":\"\\\\u0096\",\n\"\\u0097\":\"\\\\u0097\",\"\\u0098\":\"\\\\u0098\",\"\\u0099\":\"\\\\u0099\",\"\\u009a\":\"\\\\u009a\",\n\"\\u009b\":\"\\\\u009b\",\"\\u009c\":\"\\\\u009c\",\"\\u009d\":\"\\\\u009d\",\"\\u009e\":\"\\\\u009e\",\n\"\\u009f\":\"\\\\u009f\",\"\\u00ad\":\"\\\\u00ad\",\"\\u0600\":\"\\\\u0600\",\"\\u0601\":\"\\\\u0601\",\n\"\\u0602\":\"\\\\u0602\",\"\\u0603\":\"\\\\u0603\",\"\\u0604\":\"\\\\u0604\",\"\\u070f\":\"\\\\u070f\",\n\"\\u17b4\":\"\\\\u17b4\",\"\\u17b5\":\"\\\\u17b5\",\"\\u200c\":\"\\\\u200c\",\"\\u200d\":\"\\\\u200d\",\n\"\\u200e\":\"\\\\u200e\",\"\\u200f\":\"\\\\u200f\",\"\\u2028\":\"\\\\u2028\",\"\\u2029\":\"\\\\u2029\",\n\"\\u202a\":\"\\\\u202a\",\"\\u202b\":\"\\\\u202b\",\"\\u202c\":\"\\\\u202c\",\"\\u202d\":\"\\\\u202d\",\n\"\\u202e\":\"\\\\u202e\",\"\\u202f\":\"\\\\u202f\",\"\\u2060\":\"\\\\u2060\",\"\\u2061\":\"\\\\u2061\",\n\"\\u2062\":\"\\\\u2062\",\"\\u2063\":\"\\\\u2063\",\"\\u2064\":\"\\\\u2064\",\"\\u2065\":\"\\\\u2065\",\n\"\\u2066\":\"\\\\u2066\",\"\\u2067\":\"\\\\u2067\",\"\\u2068\":\"\\\\u2068\",\"\\u2069\":\"\\\\u2069\",\n\"\\u206a\":\"\\\\u206a\",\"\\u206b\":\"\\\\u206b\",\"\\u206c\":\"\\\\u206c\",\"\\u206d\":\"\\\\u206d\",\n\"\\u206e\":\"\\\\u206e\",\"\\u206f\":\"\\\\u206f\",\"\\ufeff\":\"\\\\ufeff\",\"\\ufff0\":\"\\\\ufff0\",\n\"\\ufff1\":\"\\\\ufff1\",\"\\ufff2\":\"\\\\ufff2\",\"\\ufff3\":\"\\\\ufff3\",\"\\ufff4\":\"\\\\ufff4\",\n\"\\ufff5\":\"\\\\ufff5\",\"\\ufff6\":\"\\\\ufff6\",\"\\ufff7\":\"\\\\ufff7\",\"\\ufff8\":\"\\\\ufff8\",\n\"\\ufff9\":\"\\\\ufff9\",\"\\ufffa\":\"\\\\ufffa\",\"\\ufffb\":\"\\\\ufffb\",\"\\ufffc\":\"\\\\ufffc\",\n\"\\ufffd\":\"\\\\ufffd\",\"\\ufffe\":\"\\\\ufffe\",\"\\uffff\":\"\\\\uffff\"};\n\n// Some extra characters that Chrome gets wrong, and substitutes with\n// something else on the wire.\nvar extra_escapable = /[\\x00-\\x1f\\ud800-\\udfff\\ufffe\\uffff\\u0300-\\u0333\\u033d-\\u0346\\u034a-\\u034c\\u0350-\\u0352\\u0357-\\u0358\\u035c-\\u0362\\u0374\\u037e\\u0387\\u0591-\\u05af\\u05c4\\u0610-\\u0617\\u0653-\\u0654\\u0657-\\u065b\\u065d-\\u065e\\u06df-\\u06e2\\u06eb-\\u06ec\\u0730\\u0732-\\u0733\\u0735-\\u0736\\u073a\\u073d\\u073f-\\u0741\\u0743\\u0745\\u0747\\u07eb-\\u07f1\\u0951\\u0958-\\u095f\\u09dc-\\u09dd\\u09df\\u0a33\\u0a36\\u0a59-\\u0a5b\\u0a5e\\u0b5c-\\u0b5d\\u0e38-\\u0e39\\u0f43\\u0f4d\\u0f52\\u0f57\\u0f5c\\u0f69\\u0f72-\\u0f76\\u0f78\\u0f80-\\u0f83\\u0f93\\u0f9d\\u0fa2\\u0fa7\\u0fac\\u0fb9\\u1939-\\u193a\\u1a17\\u1b6b\\u1cda-\\u1cdb\\u1dc0-\\u1dcf\\u1dfc\\u1dfe\\u1f71\\u1f73\\u1f75\\u1f77\\u1f79\\u1f7b\\u1f7d\\u1fbb\\u1fbe\\u1fc9\\u1fcb\\u1fd3\\u1fdb\\u1fe3\\u1feb\\u1fee-\\u1fef\\u1ff9\\u1ffb\\u1ffd\\u2000-\\u2001\\u20d0-\\u20d1\\u20d4-\\u20d7\\u20e7-\\u20e9\\u2126\\u212a-\\u212b\\u2329-\\u232a\\u2adc\\u302b-\\u302c\\uaab2-\\uaab3\\uf900-\\ufa0d\\ufa10\\ufa12\\ufa15-\\ufa1e\\ufa20\\ufa22\\ufa25-\\ufa26\\ufa2a-\\ufa2d\\ufa30-\\ufa6d\\ufa70-\\ufad9\\ufb1d\\ufb1f\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40-\\ufb41\\ufb43-\\ufb44\\ufb46-\\ufb4e\\ufff0-\\uffff]/g,\n    extra_lookup;\n\n// JSON Quote string. Use native implementation when possible.\nvar JSONQuote = (JSON && JSON.stringify) || function(string) {\n    json_escapable.lastIndex = 0;\n    if (json_escapable.test(string)) {\n        string = string.replace(json_escapable, function(a) {\n            return json_lookup[a];\n        });\n    }\n    return '\"' + string + '\"';\n};\n\n// This may be quite slow, so let's delay until user actually uses bad\n// characters.\nvar unroll_lookup = function(escapable) {\n    var i;\n    var unrolled = {}\n    var c = []\n    for(i=0; i<65536; i++) {\n        c.push( String.fromCharCode(i) );\n    }\n    escapable.lastIndex = 0;\n    c.join('').replace(escapable, function (a) {\n        unrolled[ a ] = '\\\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\n        return '';\n    });\n    escapable.lastIndex = 0;\n    return unrolled;\n};\n\n// Quote string, also taking care of unicode characters that browsers\n// often break. Especially, take care of unicode surrogates:\n//    http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters#Surrogates\nutils.quote = function(string) {\n    var quoted = JSONQuote(string);\n\n    // In most cases this should be very fast and good enough.\n    extra_escapable.lastIndex = 0;\n    if(!extra_escapable.test(quoted)) {\n        return quoted;\n    }\n\n    if(!extra_lookup) extra_lookup = unroll_lookup(extra_escapable);\n\n    return quoted.replace(extra_escapable, function(a) {\n        return extra_lookup[a];\n    });\n}\n\nvar _all_protocols = ['websocket',\n                      'xdr-streaming',\n                      'xhr-streaming',\n                      'iframe-eventsource',\n                      'iframe-htmlfile',\n                      'xdr-polling',\n                      'xhr-polling',\n                      'iframe-xhr-polling',\n                      'jsonp-polling'];\n\nutils.probeProtocols = function() {\n    var probed = {};\n    for(var i=0; i<_all_protocols.length; i++) {\n        var protocol = _all_protocols[i];\n        // User can have a typo in protocol name.\n        probed[protocol] = SockJS[protocol] &&\n                           SockJS[protocol].enabled();\n    }\n    return probed;\n};\n\nutils.detectProtocols = function(probed, protocols_whitelist, info) {\n    var pe = {},\n        protocols = [];\n    if (!protocols_whitelist) protocols_whitelist = _all_protocols;\n    for(var i=0; i<protocols_whitelist.length; i++) {\n        var protocol = protocols_whitelist[i];\n        pe[protocol] = probed[protocol];\n    }\n    var maybe_push = function(protos) {\n        var proto = protos.shift();\n        if (pe[proto]) {\n            protocols.push(proto);\n        } else {\n            if (protos.length > 0) {\n                maybe_push(protos);\n            }\n        }\n    }\n\n    // 1. Websocket\n    if (info.websocket !== false) {\n        maybe_push(['websocket']);\n    }\n\n    // 2. Streaming\n    if (pe['xhr-streaming'] && !info.null_origin) {\n        protocols.push('xhr-streaming');\n    } else {\n        if (pe['xdr-streaming'] && !info.cookie_needed && !info.null_origin) {\n            protocols.push('xdr-streaming');\n        } else {\n            maybe_push(['iframe-eventsource',\n                        'iframe-htmlfile']);\n        }\n    }\n\n    // 3. Polling\n    if (pe['xhr-polling'] && !info.null_origin) {\n        protocols.push('xhr-polling');\n    } else {\n        if (pe['xdr-polling'] && !info.cookie_needed && !info.null_origin) {\n            protocols.push('xdr-polling');\n        } else {\n            maybe_push(['iframe-xhr-polling',\n                        'jsonp-polling']);\n        }\n    }\n    return protocols;\n}\n//         [*] End of lib/utils.js\n\n\n//         [*] Including lib/dom.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\n// May be used by htmlfile jsonp and transports.\nvar MPrefix = '_sockjs_global';\nutils.createHook = function() {\n    var window_id = 'a' + utils.random_string(8);\n    if (!(MPrefix in _window)) {\n        var map = {};\n        _window[MPrefix] = function(window_id) {\n            if (!(window_id in map)) {\n                map[window_id] = {\n                    id: window_id,\n                    del: function() {delete map[window_id];}\n                };\n            }\n            return map[window_id];\n        }\n    }\n    return _window[MPrefix](window_id);\n};\n\n\n\nutils.attachMessage = function(listener) {\n    utils.attachEvent('message', listener);\n};\nutils.attachEvent = function(event, listener) {\n    if (typeof _window.addEventListener !== 'undefined') {\n        _window.addEventListener(event, listener, false);\n    } else {\n        // IE quirks.\n        // According to: http://stevesouders.com/misc/test-postmessage.php\n        // the message gets delivered only to 'document', not 'window'.\n        _document.attachEvent(\"on\" + event, listener);\n        // I get 'window' for ie8.\n        _window.attachEvent(\"on\" + event, listener);\n    }\n};\n\nutils.detachMessage = function(listener) {\n    utils.detachEvent('message', listener);\n};\nutils.detachEvent = function(event, listener) {\n    if (typeof _window.addEventListener !== 'undefined') {\n        _window.removeEventListener(event, listener, false);\n    } else {\n        _document.detachEvent(\"on\" + event, listener);\n        _window.detachEvent(\"on\" + event, listener);\n    }\n};\n\n\nvar on_unload = {};\n// Things registered after beforeunload are to be called immediately.\nvar after_unload = false;\n\nvar trigger_unload_callbacks = function() {\n    for(var ref in on_unload) {\n        on_unload[ref]();\n        delete on_unload[ref];\n    };\n};\n\nvar unload_triggered = function() {\n    if(after_unload) return;\n    after_unload = true;\n    trigger_unload_callbacks();\n};\n\n// 'unload' alone is not reliable in opera within an iframe, but we\n// can't use `beforeunload` as IE fires it on javascript: links.\nutils.attachEvent('unload', unload_triggered);\n\nutils.unload_add = function(listener) {\n    var ref = utils.random_string(8);\n    on_unload[ref] = listener;\n    if (after_unload) {\n        utils.delay(trigger_unload_callbacks);\n    }\n    return ref;\n};\nutils.unload_del = function(ref) {\n    if (ref in on_unload)\n        delete on_unload[ref];\n};\n\n\nutils.createIframe = function (iframe_url, error_callback) {\n    var iframe = _document.createElement('iframe');\n    var tref, unload_ref;\n    var unattach = function() {\n        clearTimeout(tref);\n        // Explorer had problems with that.\n        try {iframe.onload = null;} catch (x) {}\n        iframe.onerror = null;\n    };\n    var cleanup = function() {\n        if (iframe) {\n            unattach();\n            // This timeout makes chrome fire onbeforeunload event\n            // within iframe. Without the timeout it goes straight to\n            // onunload.\n            setTimeout(function() {\n                if(iframe) {\n                    iframe.parentNode.removeChild(iframe);\n                }\n                iframe = null;\n            }, 0);\n            utils.unload_del(unload_ref);\n        }\n    };\n    var onerror = function(r) {\n        if (iframe) {\n            cleanup();\n            error_callback(r);\n        }\n    };\n    var post = function(msg, origin) {\n        try {\n            // When the iframe is not loaded, IE raises an exception\n            // on 'contentWindow'.\n            if (iframe && iframe.contentWindow) {\n                iframe.contentWindow.postMessage(msg, origin);\n            }\n        } catch (x) {};\n    };\n\n    iframe.src = iframe_url;\n    iframe.style.display = 'none';\n    iframe.style.position = 'absolute';\n    iframe.onerror = function(){onerror('onerror');};\n    iframe.onload = function() {\n        // `onload` is triggered before scripts on the iframe are\n        // executed. Give it few seconds to actually load stuff.\n        clearTimeout(tref);\n        tref = setTimeout(function(){onerror('onload timeout');}, 2000);\n    };\n    _document.body.appendChild(iframe);\n    tref = setTimeout(function(){onerror('timeout');}, 15000);\n    unload_ref = utils.unload_add(cleanup);\n    return {\n        post: post,\n        cleanup: cleanup,\n        loaded: unattach\n    };\n};\n\nutils.createHtmlfile = function (iframe_url, error_callback) {\n    var doc = new ActiveXObject('htmlfile');\n    var tref, unload_ref;\n    var iframe;\n    var unattach = function() {\n        clearTimeout(tref);\n    };\n    var cleanup = function() {\n        if (doc) {\n            unattach();\n            utils.unload_del(unload_ref);\n            iframe.parentNode.removeChild(iframe);\n            iframe = doc = null;\n            CollectGarbage();\n        }\n    };\n    var onerror = function(r)  {\n        if (doc) {\n            cleanup();\n            error_callback(r);\n        }\n    };\n    var post = function(msg, origin) {\n        try {\n            // When the iframe is not loaded, IE raises an exception\n            // on 'contentWindow'.\n            if (iframe && iframe.contentWindow) {\n                iframe.contentWindow.postMessage(msg, origin);\n            }\n        } catch (x) {};\n    };\n\n    doc.open();\n    doc.write('<html><s' + 'cript>' +\n              'document.domain=\"' + document.domain + '\";' +\n              '</s' + 'cript></html>');\n    doc.close();\n    doc.parentWindow[WPrefix] = _window[WPrefix];\n    var c = doc.createElement('div');\n    doc.body.appendChild(c);\n    iframe = doc.createElement('iframe');\n    c.appendChild(iframe);\n    iframe.src = iframe_url;\n    tref = setTimeout(function(){onerror('timeout');}, 15000);\n    unload_ref = utils.unload_add(cleanup);\n    return {\n        post: post,\n        cleanup: cleanup,\n        loaded: unattach\n    };\n};\n//         [*] End of lib/dom.js\n\n\n//         [*] Including lib/dom2.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar AbstractXHRObject = function(){};\nAbstractXHRObject.prototype = new EventEmitter(['chunk', 'finish']);\n\nAbstractXHRObject.prototype._start = function(method, url, payload, opts) {\n    var that = this;\n\n    try {\n        that.xhr = new XMLHttpRequest();\n    } catch(x) {};\n\n    if (!that.xhr) {\n        try {\n            that.xhr = new _window.ActiveXObject('Microsoft.XMLHTTP');\n        } catch(x) {};\n    }\n    if (_window.ActiveXObject || _window.XDomainRequest) {\n        // IE8 caches even POSTs\n        url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date);\n    }\n\n    // Explorer tends to keep connection open, even after the\n    // tab gets closed: http://bugs.jquery.com/ticket/5280\n    that.unload_ref = utils.unload_add(function(){that._cleanup(true);});\n    try {\n        that.xhr.open(method, url, true);\n    } catch(e) {\n        // IE raises an exception on wrong port.\n        that.emit('finish', 0, '');\n        that._cleanup();\n        return;\n    };\n\n    if (!opts || !opts.no_credentials) {\n        // Mozilla docs says https://developer.mozilla.org/en/XMLHttpRequest :\n        // \"This never affects same-site requests.\"\n        that.xhr.withCredentials = 'true';\n    }\n    if (opts && opts.headers) {\n        for(var key in opts.headers) {\n            that.xhr.setRequestHeader(key, opts.headers[key]);\n        }\n    }\n\n    that.xhr.onreadystatechange = function() {\n        if (that.xhr) {\n            var x = that.xhr;\n            switch (x.readyState) {\n            case 3:\n                // IE doesn't like peeking into responseText or status\n                // on Microsoft.XMLHTTP and readystate=3\n                try {\n                    var status = x.status;\n                    var text = x.responseText;\n                } catch (x) {};\n                // IE returns 1223 for 204: http://bugs.jquery.com/ticket/1450\n                if (status === 1223) status = 204;\n\n                // IE does return readystate == 3 for 404 answers.\n                if (text && text.length > 0) {\n                    that.emit('chunk', status, text);\n                }\n                break;\n            case 4:\n                var status = x.status;\n                // IE returns 1223 for 204: http://bugs.jquery.com/ticket/1450\n                if (status === 1223) status = 204;\n\n                that.emit('finish', status, x.responseText);\n                that._cleanup(false);\n                break;\n            }\n        }\n    };\n    that.xhr.send(payload);\n};\n\nAbstractXHRObject.prototype._cleanup = function(abort) {\n    var that = this;\n    if (!that.xhr) return;\n    utils.unload_del(that.unload_ref);\n\n    // IE needs this field to be a function\n    that.xhr.onreadystatechange = function(){};\n\n    if (abort) {\n        try {\n            that.xhr.abort();\n        } catch(x) {};\n    }\n    that.unload_ref = that.xhr = null;\n};\n\nAbstractXHRObject.prototype.close = function() {\n    var that = this;\n    that.nuke();\n    that._cleanup(true);\n};\n\nvar XHRCorsObject = utils.XHRCorsObject = function() {\n    var that = this, args = arguments;\n    utils.delay(function(){that._start.apply(that, args);});\n};\nXHRCorsObject.prototype = new AbstractXHRObject();\n\nvar XHRLocalObject = utils.XHRLocalObject = function(method, url, payload) {\n    var that = this;\n    utils.delay(function(){\n        that._start(method, url, payload, {\n            no_credentials: true\n        });\n    });\n};\nXHRLocalObject.prototype = new AbstractXHRObject();\n\n\n\n// References:\n//   http://ajaxian.com/archives/100-line-ajax-wrapper\n//   http://msdn.microsoft.com/en-us/library/cc288060(v=VS.85).aspx\nvar XDRObject = utils.XDRObject = function(method, url, payload) {\n    var that = this;\n    utils.delay(function(){that._start(method, url, payload);});\n};\nXDRObject.prototype = new EventEmitter(['chunk', 'finish']);\nXDRObject.prototype._start = function(method, url, payload) {\n    var that = this;\n    var xdr = new XDomainRequest();\n    // IE caches even POSTs\n    url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date);\n\n    var onerror = xdr.ontimeout = xdr.onerror = function() {\n        that.emit('finish', 0, '');\n        that._cleanup(false);\n    };\n    xdr.onprogress = function() {\n        that.emit('chunk', 200, xdr.responseText);\n    };\n    xdr.onload = function() {\n        that.emit('finish', 200, xdr.responseText);\n        that._cleanup(false);\n    };\n    that.xdr = xdr;\n    that.unload_ref = utils.unload_add(function(){that._cleanup(true);});\n    try {\n        // Fails with AccessDenied if port number is bogus\n        that.xdr.open(method, url);\n        that.xdr.send(payload);\n    } catch(x) {\n        onerror();\n    }\n};\n\nXDRObject.prototype._cleanup = function(abort) {\n    var that = this;\n    if (!that.xdr) return;\n    utils.unload_del(that.unload_ref);\n\n    that.xdr.ontimeout = that.xdr.onerror = that.xdr.onprogress =\n        that.xdr.onload = null;\n    if (abort) {\n        try {\n            that.xdr.abort();\n        } catch(x) {};\n    }\n    that.unload_ref = that.xdr = null;\n};\n\nXDRObject.prototype.close = function() {\n    var that = this;\n    that.nuke();\n    that._cleanup(true);\n};\n\n// 1. Is natively via XHR\n// 2. Is natively via XDR\n// 3. Nope, but postMessage is there so it should work via the Iframe.\n// 4. Nope, sorry.\nutils.isXHRCorsCapable = function() {\n    if (_window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()) {\n        return 1;\n    }\n    // XDomainRequest doesn't work if page is served from file://\n    if (_window.XDomainRequest && _document.domain) {\n        return 2;\n    }\n    if (IframeTransport.enabled()) {\n        return 3;\n    }\n    return 4;\n};\n//         [*] End of lib/dom2.js\n\n\n//         [*] Including lib/sockjs.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar SockJS = function(url, dep_protocols_whitelist, options) {\n    if (!(this instanceof SockJS)) {\n        // makes `new` optional\n        return new SockJS(url, dep_protocols_whitelist, options);\n    }\n\n    var that = this, protocols_whitelist;\n    that._options = {devel: false, debug: false, protocols_whitelist: [],\n                     info: undefined, rtt: undefined};\n    if (options) {\n        utils.objectExtend(that._options, options);\n    }\n    that._base_url = utils.amendUrl(url);\n    that._server = that._options.server || utils.random_number_string(1000);\n    if (that._options.protocols_whitelist &&\n        that._options.protocols_whitelist.length) {\n        protocols_whitelist = that._options.protocols_whitelist;\n    } else {\n        // Deprecated API\n        if (typeof dep_protocols_whitelist === 'string' &&\n            dep_protocols_whitelist.length > 0) {\n            protocols_whitelist = [dep_protocols_whitelist];\n        } else if (utils.isArray(dep_protocols_whitelist)) {\n            protocols_whitelist = dep_protocols_whitelist\n        } else {\n            protocols_whitelist = null;\n        }\n        if (protocols_whitelist) {\n            that._debug('Deprecated API: Use \"protocols_whitelist\" option ' +\n                        'instead of supplying protocol list as a second ' +\n                        'parameter to SockJS constructor.');\n        }\n    }\n    that._protocols = [];\n    that.protocol = null;\n    that.readyState = SockJS.CONNECTING;\n    that._ir = createInfoReceiver(that._base_url);\n    that._ir.onfinish = function(info, rtt) {\n        that._ir = null;\n        if (info) {\n            if (that._options.info) {\n                // Override if user supplies the option\n                info = utils.objectExtend(info, that._options.info);\n            }\n            if (that._options.rtt) {\n                rtt = that._options.rtt;\n            }\n            that._applyInfo(info, rtt, protocols_whitelist);\n            that._didClose();\n        } else {\n            that._didClose(1002, 'Can\\'t connect to server', true);\n        }\n    };\n};\n// Inheritance\nSockJS.prototype = new REventTarget();\n\nSockJS.version = \"0.3.4\";\n\nSockJS.CONNECTING = 0;\nSockJS.OPEN = 1;\nSockJS.CLOSING = 2;\nSockJS.CLOSED = 3;\n\nSockJS.prototype._debug = function() {\n    if (this._options.debug)\n        utils.log.apply(utils, arguments);\n};\n\nSockJS.prototype._dispatchOpen = function() {\n    var that = this;\n    if (that.readyState === SockJS.CONNECTING) {\n        if (that._transport_tref) {\n            clearTimeout(that._transport_tref);\n            that._transport_tref = null;\n        }\n        that.readyState = SockJS.OPEN;\n        that.dispatchEvent(new SimpleEvent(\"open\"));\n    } else {\n        // The server might have been restarted, and lost track of our\n        // connection.\n        that._didClose(1006, \"Server lost session\");\n    }\n};\n\nSockJS.prototype._dispatchMessage = function(data) {\n    var that = this;\n    if (that.readyState !== SockJS.OPEN)\n            return;\n    that.dispatchEvent(new SimpleEvent(\"message\", {data: data}));\n};\n\nSockJS.prototype._dispatchHeartbeat = function(data) {\n    var that = this;\n    if (that.readyState !== SockJS.OPEN)\n        return;\n    that.dispatchEvent(new SimpleEvent('heartbeat', {}));\n};\n\nSockJS.prototype._didClose = function(code, reason, force) {\n    var that = this;\n    if (that.readyState !== SockJS.CONNECTING &&\n        that.readyState !== SockJS.OPEN &&\n        that.readyState !== SockJS.CLOSING)\n            throw new Error('INVALID_STATE_ERR');\n    if (that._ir) {\n        that._ir.nuke();\n        that._ir = null;\n    }\n\n    if (that._transport) {\n        that._transport.doCleanup();\n        that._transport = null;\n    }\n\n    var close_event = new SimpleEvent(\"close\", {\n        code: code,\n        reason: reason,\n        wasClean: utils.userSetCode(code)});\n\n    if (!utils.userSetCode(code) &&\n        that.readyState === SockJS.CONNECTING && !force) {\n        if (that._try_next_protocol(close_event)) {\n            return;\n        }\n        close_event = new SimpleEvent(\"close\", {code: 2000,\n                                                reason: \"All transports failed\",\n                                                wasClean: false,\n                                                last_event: close_event});\n    }\n    that.readyState = SockJS.CLOSED;\n\n    utils.delay(function() {\n                   that.dispatchEvent(close_event);\n                });\n};\n\nSockJS.prototype._didMessage = function(data) {\n    var that = this;\n    var type = data.slice(0, 1);\n    switch(type) {\n    case 'o':\n        that._dispatchOpen();\n        break;\n    case 'a':\n        var payload = JSON.parse(data.slice(1) || '[]');\n        for(var i=0; i < payload.length; i++){\n            that._dispatchMessage(payload[i]);\n        }\n        break;\n    case 'm':\n        var payload = JSON.parse(data.slice(1) || 'null');\n        that._dispatchMessage(payload);\n        break;\n    case 'c':\n        var payload = JSON.parse(data.slice(1) || '[]');\n        that._didClose(payload[0], payload[1]);\n        break;\n    case 'h':\n        that._dispatchHeartbeat();\n        break;\n    }\n};\n\nSockJS.prototype._try_next_protocol = function(close_event) {\n    var that = this;\n    if (that.protocol) {\n        that._debug('Closed transport:', that.protocol, ''+close_event);\n        that.protocol = null;\n    }\n    if (that._transport_tref) {\n        clearTimeout(that._transport_tref);\n        that._transport_tref = null;\n    }\n\n    while(1) {\n        var protocol = that.protocol = that._protocols.shift();\n        if (!protocol) {\n            return false;\n        }\n        // Some protocols require access to `body`, what if were in\n        // the `head`?\n        if (SockJS[protocol] &&\n            SockJS[protocol].need_body === true &&\n            (!_document.body ||\n             (typeof _document.readyState !== 'undefined'\n              && _document.readyState !== 'complete'))) {\n            that._protocols.unshift(protocol);\n            that.protocol = 'waiting-for-load';\n            utils.attachEvent('load', function(){\n                that._try_next_protocol();\n            });\n            return true;\n        }\n\n        if (!SockJS[protocol] ||\n              !SockJS[protocol].enabled(that._options)) {\n            that._debug('Skipping transport:', protocol);\n        } else {\n            var roundTrips = SockJS[protocol].roundTrips || 1;\n            var to = ((that._options.rto || 0) * roundTrips) || 5000;\n            that._transport_tref = utils.delay(to, function() {\n                if (that.readyState === SockJS.CONNECTING) {\n                    // I can't understand how it is possible to run\n                    // this timer, when the state is CLOSED, but\n                    // apparently in IE everythin is possible.\n                    that._didClose(2007, \"Transport timeouted\");\n                }\n            });\n\n            var connid = utils.random_string(8);\n            var trans_url = that._base_url + '/' + that._server + '/' + connid;\n            that._debug('Opening transport:', protocol, ' url:'+trans_url,\n                        ' RTO:'+that._options.rto);\n            that._transport = new SockJS[protocol](that, trans_url,\n                                                   that._base_url);\n            return true;\n        }\n    }\n};\n\nSockJS.prototype.close = function(code, reason) {\n    var that = this;\n    if (code && !utils.userSetCode(code))\n        throw new Error(\"INVALID_ACCESS_ERR\");\n    if(that.readyState !== SockJS.CONNECTING &&\n       that.readyState !== SockJS.OPEN) {\n        return false;\n    }\n    that.readyState = SockJS.CLOSING;\n    that._didClose(code || 1000, reason || \"Normal closure\");\n    return true;\n};\n\nSockJS.prototype.send = function(data) {\n    var that = this;\n    if (that.readyState === SockJS.CONNECTING)\n        throw new Error('INVALID_STATE_ERR');\n    if (that.readyState === SockJS.OPEN) {\n        that._transport.doSend(utils.quote('' + data));\n    }\n    return true;\n};\n\nSockJS.prototype._applyInfo = function(info, rtt, protocols_whitelist) {\n    var that = this;\n    that._options.info = info;\n    that._options.rtt = rtt;\n    that._options.rto = utils.countRTO(rtt);\n    that._options.info.null_origin = !_document.domain;\n    // Servers can override base_url, eg to provide a randomized domain name and\n    // avoid browser per-domain connection limits.\n    if (info.base_url)\n      // <METEOR>\n      that._base_url = utils.amendUrl(info.base_url, that._base_url);\n      // </METEOR>\n    var probed = utils.probeProtocols();\n    that._protocols = utils.detectProtocols(probed, protocols_whitelist, info);\n// <METEOR>\n// https://github.com/sockjs/sockjs-client/issues/79\n    // Hack to avoid XDR when using different protocols\n    // We're on IE trying to do cross-protocol. jsonp only.\n    if (!utils.isSameOriginScheme(that._base_url) &&\n        2 === utils.isXHRCorsCapable()) {\n        that._protocols = ['jsonp-polling'];\n    }\n// </METEOR>\n};\n//         [*] End of lib/sockjs.js\n\n\n//         [*] Including lib/trans-websocket.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar WebSocketTransport = SockJS.websocket = function(ri, trans_url) {\n    var that = this;\n    var url = trans_url + '/websocket';\n    if (url.slice(0, 5) === 'https') {\n        url = 'wss' + url.slice(5);\n    } else {\n        url = 'ws' + url.slice(4);\n    }\n    that.ri = ri;\n    that.url = url;\n    var Constructor = _window.WebSocket || _window.MozWebSocket;\n\n    that.ws = new Constructor(that.url);\n    that.ws.onmessage = function(e) {\n        that.ri._didMessage(e.data);\n    };\n    // Firefox has an interesting bug. If a websocket connection is\n    // created after onunload, it stays alive even when user\n    // navigates away from the page. In such situation let's lie -\n    // let's not open the ws connection at all. See:\n    // https://github.com/sockjs/sockjs-client/issues/28\n    // https://bugzilla.mozilla.org/show_bug.cgi?id=696085\n    that.unload_ref = utils.unload_add(function(){that.ws.close()});\n    that.ws.onclose = function() {\n        that.ri._didMessage(utils.closeFrame(1006, \"WebSocket connection broken\"));\n    };\n};\n\nWebSocketTransport.prototype.doSend = function(data) {\n    this.ws.send('[' + data + ']');\n};\n\nWebSocketTransport.prototype.doCleanup = function() {\n    var that = this;\n    var ws = that.ws;\n    if (ws) {\n        ws.onmessage = ws.onclose = null;\n        ws.close();\n        utils.unload_del(that.unload_ref);\n        that.unload_ref = that.ri = that.ws = null;\n    }\n};\n\nWebSocketTransport.enabled = function() {\n    return !!(_window.WebSocket || _window.MozWebSocket);\n};\n\n// In theory, ws should require 1 round trip. But in chrome, this is\n// not very stable over SSL. Most likely a ws connection requires a\n// separate SSL connection, in which case 2 round trips are an\n// absolute minumum.\nWebSocketTransport.roundTrips = 2;\n//         [*] End of lib/trans-websocket.js\n\n\n//         [*] Including lib/trans-sender.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar BufferedSender = function() {};\nBufferedSender.prototype.send_constructor = function(sender) {\n    var that = this;\n    that.send_buffer = [];\n    that.sender = sender;\n};\nBufferedSender.prototype.doSend = function(message) {\n    var that = this;\n    that.send_buffer.push(message);\n    if (!that.send_stop) {\n        that.send_schedule();\n    }\n};\n\n// For polling transports in a situation when in the message callback,\n// new message is being send. If the sending connection was started\n// before receiving one, it is possible to saturate the network and\n// timeout due to the lack of receiving socket. To avoid that we delay\n// sending messages by some small time, in order to let receiving\n// connection be started beforehand. This is only a halfmeasure and\n// does not fix the big problem, but it does make the tests go more\n// stable on slow networks.\nBufferedSender.prototype.send_schedule_wait = function() {\n    var that = this;\n    var tref;\n    that.send_stop = function() {\n        that.send_stop = null;\n        clearTimeout(tref);\n    };\n    tref = utils.delay(25, function() {\n        that.send_stop = null;\n        that.send_schedule();\n    });\n};\n\nBufferedSender.prototype.send_schedule = function() {\n    var that = this;\n    if (that.send_buffer.length > 0) {\n        var payload = '[' + that.send_buffer.join(',') + ']';\n        that.send_stop = that.sender(that.trans_url, payload, function(success, abort_reason) {\n            that.send_stop = null;\n            if (success === false) {\n                that.ri._didClose(1006, 'Sending error ' + abort_reason);\n            } else {\n                that.send_schedule_wait();\n            }\n        });\n        that.send_buffer = [];\n    }\n};\n\nBufferedSender.prototype.send_destructor = function() {\n    var that = this;\n    if (that._send_stop) {\n        that._send_stop();\n    }\n    that._send_stop = null;\n};\n\nvar jsonPGenericSender = function(url, payload, callback) {\n    var that = this;\n\n    if (!('_send_form' in that)) {\n        var form = that._send_form = _document.createElement('form');\n        var area = that._send_area = _document.createElement('textarea');\n        area.name = 'd';\n        form.style.display = 'none';\n        form.style.position = 'absolute';\n        form.method = 'POST';\n        form.enctype = 'application/x-www-form-urlencoded';\n        form.acceptCharset = \"UTF-8\";\n        form.appendChild(area);\n        _document.body.appendChild(form);\n    }\n    var form = that._send_form;\n    var area = that._send_area;\n    var id = 'a' + utils.random_string(8);\n    form.target = id;\n    form.action = url + '/jsonp_send?i=' + id;\n\n    var iframe;\n    try {\n        // ie6 dynamic iframes with target=\"\" support (thanks Chris Lambacher)\n        iframe = _document.createElement('<iframe name=\"'+ id +'\">');\n    } catch(x) {\n        iframe = _document.createElement('iframe');\n        iframe.name = id;\n    }\n    iframe.id = id;\n    form.appendChild(iframe);\n    iframe.style.display = 'none';\n\n    try {\n        area.value = payload;\n    } catch(e) {\n        utils.log('Your browser is seriously broken. Go home! ' + e.message);\n    }\n    form.submit();\n\n    var completed = function(e) {\n        if (!iframe.onerror) return;\n        iframe.onreadystatechange = iframe.onerror = iframe.onload = null;\n        // Opera mini doesn't like if we GC iframe\n        // immediately, thus this timeout.\n        utils.delay(500, function() {\n                       iframe.parentNode.removeChild(iframe);\n                       iframe = null;\n                   });\n        area.value = '';\n        // It is not possible to detect if the iframe succeeded or\n        // failed to submit our form.\n        callback(true);\n    };\n    iframe.onerror = iframe.onload = completed;\n    iframe.onreadystatechange = function(e) {\n        if (iframe.readyState == 'complete') completed();\n    };\n    return completed;\n};\n\nvar createAjaxSender = function(AjaxObject) {\n    return function(url, payload, callback) {\n        var xo = new AjaxObject('POST', url + '/xhr_send', payload);\n        xo.onfinish = function(status, text) {\n            callback(status === 200 || status === 204,\n                     'http status ' + status);\n        };\n        return function(abort_reason) {\n            callback(false, abort_reason);\n        };\n    };\n};\n//         [*] End of lib/trans-sender.js\n\n\n//         [*] Including lib/trans-jsonp-receiver.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\n// Parts derived from Socket.io:\n//    https://github.com/LearnBoost/socket.io/blob/0.6.17/lib/socket.io/transports/jsonp-polling.js\n// and jQuery-JSONP:\n//    https://code.google.com/p/jquery-jsonp/source/browse/trunk/core/jquery.jsonp.js\nvar jsonPGenericReceiver = function(url, callback) {\n    var tref;\n    var script = _document.createElement('script');\n    var script2;  // Opera synchronous load trick.\n    var close_script = function(frame) {\n        if (script2) {\n            script2.parentNode.removeChild(script2);\n            script2 = null;\n        }\n        if (script) {\n            clearTimeout(tref);\n            // Unfortunately, you can't really abort script loading of\n            // the script.\n            script.parentNode.removeChild(script);\n            script.onreadystatechange = script.onerror =\n                script.onload = script.onclick = null;\n            script = null;\n            callback(frame);\n            callback = null;\n        }\n    };\n\n    // IE9 fires 'error' event after orsc or before, in random order.\n    var loaded_okay = false;\n    var error_timer = null;\n\n    script.id = 'a' + utils.random_string(8);\n    script.src = url;\n    script.type = 'text/javascript';\n    script.charset = 'UTF-8';\n    script.onerror = function(e) {\n        if (!error_timer) {\n            // Delay firing close_script.\n            error_timer = setTimeout(function() {\n                if (!loaded_okay) {\n                    close_script(utils.closeFrame(\n                        1006,\n                        \"JSONP script loaded abnormally (onerror)\"));\n                }\n            }, 1000);\n        }\n    };\n    script.onload = function(e) {\n        close_script(utils.closeFrame(1006, \"JSONP script loaded abnormally (onload)\"));\n    };\n\n    script.onreadystatechange = function(e) {\n        if (/loaded|closed/.test(script.readyState)) {\n            if (script && script.htmlFor && script.onclick) {\n                loaded_okay = true;\n                try {\n                    // In IE, actually execute the script.\n                    script.onclick();\n                } catch (x) {}\n            }\n            if (script) {\n                close_script(utils.closeFrame(1006, \"JSONP script loaded abnormally (onreadystatechange)\"));\n            }\n        }\n    };\n    // IE: event/htmlFor/onclick trick.\n    // One can't rely on proper order for onreadystatechange. In order to\n    // make sure, set a 'htmlFor' and 'event' properties, so that\n    // script code will be installed as 'onclick' handler for the\n    // script object. Later, onreadystatechange, manually execute this\n    // code. FF and Chrome doesn't work with 'event' and 'htmlFor'\n    // set. For reference see:\n    //   http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html\n    // Also, read on that about script ordering:\n    //   http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order\n    if (typeof script.async === 'undefined' && _document.attachEvent) {\n        // According to mozilla docs, in recent browsers script.async defaults\n        // to 'true', so we may use it to detect a good browser:\n        // https://developer.mozilla.org/en/HTML/Element/script\n        if (!/opera/i.test(navigator.userAgent)) {\n            // Naively assume we're in IE\n            try {\n                script.htmlFor = script.id;\n                script.event = \"onclick\";\n            } catch (x) {}\n            script.async = true;\n        } else {\n            // Opera, second sync script hack\n            script2 = _document.createElement('script');\n            script2.text = \"try{var a = document.getElementById('\"+script.id+\"'); if(a)a.onerror();}catch(x){};\";\n            script.async = script2.async = false;\n        }\n    }\n    if (typeof script.async !== 'undefined') {\n        script.async = true;\n    }\n\n    // Fallback mostly for Konqueror - stupid timer, 35 seconds shall be plenty.\n    tref = setTimeout(function() {\n                          close_script(utils.closeFrame(1006, \"JSONP script loaded abnormally (timeout)\"));\n                      }, 35000);\n\n    var head = _document.getElementsByTagName('head')[0];\n    head.insertBefore(script, head.firstChild);\n    if (script2) {\n        head.insertBefore(script2, head.firstChild);\n    }\n    return close_script;\n};\n//         [*] End of lib/trans-jsonp-receiver.js\n\n\n//         [*] Including lib/trans-jsonp-polling.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\n// The simplest and most robust transport, using the well-know cross\n// domain hack - JSONP. This transport is quite inefficient - one\n// mssage could use up to one http request. But at least it works almost\n// everywhere.\n// Known limitations:\n//   o you will get a spinning cursor\n//   o for Konqueror a dumb timer is needed to detect errors\n\n\nvar JsonPTransport = SockJS['jsonp-polling'] = function(ri, trans_url) {\n    utils.polluteGlobalNamespace();\n    var that = this;\n    that.ri = ri;\n    that.trans_url = trans_url;\n    that.send_constructor(jsonPGenericSender);\n    that._schedule_recv();\n};\n\n// Inheritnace\nJsonPTransport.prototype = new BufferedSender();\n\nJsonPTransport.prototype._schedule_recv = function() {\n    var that = this;\n    var callback = function(data) {\n        that._recv_stop = null;\n        if (data) {\n            // no data - heartbeat;\n            if (!that._is_closing) {\n                that.ri._didMessage(data);\n            }\n        }\n        // The message can be a close message, and change is_closing state.\n        if (!that._is_closing) {\n            that._schedule_recv();\n        }\n    };\n    that._recv_stop = jsonPReceiverWrapper(that.trans_url + '/jsonp',\n                                           jsonPGenericReceiver, callback);\n};\n\nJsonPTransport.enabled = function() {\n    return true;\n};\n\nJsonPTransport.need_body = true;\n\n\nJsonPTransport.prototype.doCleanup = function() {\n    var that = this;\n    that._is_closing = true;\n    if (that._recv_stop) {\n        that._recv_stop();\n    }\n    that.ri = that._recv_stop = null;\n    that.send_destructor();\n};\n\n\n// Abstract away code that handles global namespace pollution.\nvar jsonPReceiverWrapper = function(url, constructReceiver, user_callback) {\n    var id = 'a' + utils.random_string(6);\n    var url_id = url + '?c=' + escape(WPrefix + '.' + id);\n\n    // Unfortunately it is not possible to abort loading of the\n    // script. We need to keep track of frake close frames.\n    var aborting = 0;\n\n    // Callback will be called exactly once.\n    var callback = function(frame) {\n        switch(aborting) {\n        case 0:\n            // Normal behaviour - delete hook _and_ emit message.\n            delete _window[WPrefix][id];\n            user_callback(frame);\n            break;\n        case 1:\n            // Fake close frame - emit but don't delete hook.\n            user_callback(frame);\n            aborting = 2;\n            break;\n        case 2:\n            // Got frame after connection was closed, delete hook, don't emit.\n            delete _window[WPrefix][id];\n            break;\n        }\n    };\n\n    var close_script = constructReceiver(url_id, callback);\n    _window[WPrefix][id] = close_script;\n    var stop = function() {\n        if (_window[WPrefix][id]) {\n            aborting = 1;\n            _window[WPrefix][id](utils.closeFrame(1000, \"JSONP user aborted read\"));\n        }\n    };\n    return stop;\n};\n//         [*] End of lib/trans-jsonp-polling.js\n\n\n//         [*] Including lib/trans-xhr.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar AjaxBasedTransport = function() {};\nAjaxBasedTransport.prototype = new BufferedSender();\n\nAjaxBasedTransport.prototype.run = function(ri, trans_url,\n                                            url_suffix, Receiver, AjaxObject) {\n    var that = this;\n    that.ri = ri;\n    that.trans_url = trans_url;\n    that.send_constructor(createAjaxSender(AjaxObject));\n    that.poll = new Polling(ri, Receiver,\n                            trans_url + url_suffix, AjaxObject);\n};\n\nAjaxBasedTransport.prototype.doCleanup = function() {\n    var that = this;\n    if (that.poll) {\n        that.poll.abort();\n        that.poll = null;\n    }\n};\n\n// xhr-streaming\nvar XhrStreamingTransport = SockJS['xhr-streaming'] = function(ri, trans_url) {\n    this.run(ri, trans_url, '/xhr_streaming', XhrReceiver, utils.XHRCorsObject);\n};\n\nXhrStreamingTransport.prototype = new AjaxBasedTransport();\n\nXhrStreamingTransport.enabled = function() {\n    // Support for CORS Ajax aka Ajax2? Opera 12 claims CORS but\n    // doesn't do streaming.\n    return (_window.XMLHttpRequest &&\n            'withCredentials' in new XMLHttpRequest() &&\n            (!/opera/i.test(navigator.userAgent)));\n};\nXhrStreamingTransport.roundTrips = 2; // preflight, ajax\n\n// Safari gets confused when a streaming ajax request is started\n// before onload. This causes the load indicator to spin indefinetely.\nXhrStreamingTransport.need_body = true;\n\n\n// According to:\n//   http://stackoverflow.com/questions/1641507/detect-browser-support-for-cross-domain-xmlhttprequests\n//   http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/\n\n\n// xdr-streaming\nvar XdrStreamingTransport = SockJS['xdr-streaming'] = function(ri, trans_url) {\n    this.run(ri, trans_url, '/xhr_streaming', XhrReceiver, utils.XDRObject);\n};\n\nXdrStreamingTransport.prototype = new AjaxBasedTransport();\n\nXdrStreamingTransport.enabled = function() {\n    return !!_window.XDomainRequest;\n};\nXdrStreamingTransport.roundTrips = 2; // preflight, ajax\n\n\n\n// xhr-polling\nvar XhrPollingTransport = SockJS['xhr-polling'] = function(ri, trans_url) {\n    this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XHRCorsObject);\n};\n\nXhrPollingTransport.prototype = new AjaxBasedTransport();\n\nXhrPollingTransport.enabled = XhrStreamingTransport.enabled;\nXhrPollingTransport.roundTrips = 2; // preflight, ajax\n\n\n// xdr-polling\nvar XdrPollingTransport = SockJS['xdr-polling'] = function(ri, trans_url) {\n    this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XDRObject);\n};\n\nXdrPollingTransport.prototype = new AjaxBasedTransport();\n\nXdrPollingTransport.enabled = XdrStreamingTransport.enabled;\nXdrPollingTransport.roundTrips = 2; // preflight, ajax\n//         [*] End of lib/trans-xhr.js\n\n\n//         [*] Including lib/trans-iframe.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\n// Few cool transports do work only for same-origin. In order to make\n// them working cross-domain we shall use iframe, served form the\n// remote domain. New browsers, have capabilities to communicate with\n// cross domain iframe, using postMessage(). In IE it was implemented\n// from IE 8+, but of course, IE got some details wrong:\n//    http://msdn.microsoft.com/en-us/library/cc197015(v=VS.85).aspx\n//    http://stevesouders.com/misc/test-postmessage.php\n\nvar IframeTransport = function() {};\n\nIframeTransport.prototype.i_constructor = function(ri, trans_url, base_url) {\n    var that = this;\n    that.ri = ri;\n    that.origin = utils.getOrigin(base_url);\n    that.base_url = base_url;\n    that.trans_url = trans_url;\n\n    var iframe_url = base_url + '/iframe.html';\n    if (that.ri._options.devel) {\n        iframe_url += '?t=' + (+new Date);\n    }\n    that.window_id = utils.random_string(8);\n    iframe_url += '#' + that.window_id;\n\n    that.iframeObj = utils.createIframe(iframe_url, function(r) {\n                                            that.ri._didClose(1006, \"Unable to load an iframe (\" + r + \")\");\n                                        });\n\n    that.onmessage_cb = utils.bind(that.onmessage, that);\n    utils.attachMessage(that.onmessage_cb);\n};\n\nIframeTransport.prototype.doCleanup = function() {\n    var that = this;\n    if (that.iframeObj) {\n        utils.detachMessage(that.onmessage_cb);\n        try {\n            // When the iframe is not loaded, IE raises an exception\n            // on 'contentWindow'.\n            if (that.iframeObj.iframe.contentWindow) {\n                that.postMessage('c');\n            }\n        } catch (x) {}\n        that.iframeObj.cleanup();\n        that.iframeObj = null;\n        that.onmessage_cb = that.iframeObj = null;\n    }\n};\n\nIframeTransport.prototype.onmessage = function(e) {\n    var that = this;\n    if (e.origin !== that.origin) return;\n    var window_id = e.data.slice(0, 8);\n    var type = e.data.slice(8, 9);\n    var data = e.data.slice(9);\n\n    if (window_id !== that.window_id) return;\n\n    switch(type) {\n    case 's':\n        that.iframeObj.loaded();\n        that.postMessage('s', JSON.stringify([SockJS.version, that.protocol, that.trans_url, that.base_url]));\n        break;\n    case 't':\n        that.ri._didMessage(data);\n        break;\n    }\n};\n\nIframeTransport.prototype.postMessage = function(type, data) {\n    var that = this;\n    that.iframeObj.post(that.window_id + type + (data || ''), that.origin);\n};\n\nIframeTransport.prototype.doSend = function (message) {\n    this.postMessage('m', message);\n};\n\nIframeTransport.enabled = function() {\n    // postMessage misbehaves in konqueror 4.6.5 - the messages are delivered with\n    // huge delay, or not at all.\n    var konqueror = navigator && navigator.userAgent && navigator.userAgent.indexOf('Konqueror') !== -1;\n    return ((typeof _window.postMessage === 'function' ||\n            typeof _window.postMessage === 'object') && (!konqueror));\n};\n//         [*] End of lib/trans-iframe.js\n\n\n//         [*] Including lib/trans-iframe-within.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar curr_window_id;\n\nvar postMessage = function (type, data) {\n    if(parent !== _window) {\n        parent.postMessage(curr_window_id + type + (data || ''), '*');\n    } else {\n        utils.log(\"Can't postMessage, no parent window.\", type, data);\n    }\n};\n\nvar FacadeJS = function() {};\nFacadeJS.prototype._didClose = function (code, reason) {\n    postMessage('t', utils.closeFrame(code, reason));\n};\nFacadeJS.prototype._didMessage = function (frame) {\n    postMessage('t', frame);\n};\nFacadeJS.prototype._doSend = function (data) {\n    this._transport.doSend(data);\n};\nFacadeJS.prototype._doCleanup = function () {\n    this._transport.doCleanup();\n};\n\nutils.parent_origin = undefined;\n\nSockJS.bootstrap_iframe = function() {\n    var facade;\n    curr_window_id = _document.location.hash.slice(1);\n    var onMessage = function(e) {\n        if(e.source !== parent) return;\n        if(typeof utils.parent_origin === 'undefined')\n            utils.parent_origin = e.origin;\n        if (e.origin !== utils.parent_origin) return;\n\n        var window_id = e.data.slice(0, 8);\n        var type = e.data.slice(8, 9);\n        var data = e.data.slice(9);\n        if (window_id !== curr_window_id) return;\n        switch(type) {\n        case 's':\n            var p = JSON.parse(data);\n            var version = p[0];\n            var protocol = p[1];\n            var trans_url = p[2];\n            var base_url = p[3];\n            if (version !== SockJS.version) {\n                utils.log(\"Incompatibile SockJS! Main site uses:\" +\n                          \" \\\"\" + version + \"\\\", the iframe:\" +\n                          \" \\\"\" + SockJS.version + \"\\\".\");\n            }\n            if (!utils.flatUrl(trans_url) || !utils.flatUrl(base_url)) {\n                utils.log(\"Only basic urls are supported in SockJS\");\n                return;\n            }\n\n            if (!utils.isSameOriginUrl(trans_url) ||\n                !utils.isSameOriginUrl(base_url)) {\n                utils.log(\"Can't connect to different domain from within an \" +\n                          \"iframe. (\" + JSON.stringify([_window.location.href, trans_url, base_url]) +\n                          \")\");\n                return;\n            }\n            facade = new FacadeJS();\n            facade._transport = new FacadeJS[protocol](facade, trans_url, base_url);\n            break;\n        case 'm':\n            facade._doSend(data);\n            break;\n        case 'c':\n            if (facade)\n                facade._doCleanup();\n            facade = null;\n            break;\n        }\n    };\n\n    // alert('test ticker');\n    // facade = new FacadeJS();\n    // facade._transport = new FacadeJS['w-iframe-xhr-polling'](facade, 'http://host.com:9999/ticker/12/basd');\n\n    utils.attachMessage(onMessage);\n\n    // Start\n    postMessage('s');\n};\n//         [*] End of lib/trans-iframe-within.js\n\n\n//         [*] Including lib/info.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar InfoReceiver = function(base_url, AjaxObject) {\n    var that = this;\n    utils.delay(function(){that.doXhr(base_url, AjaxObject);});\n};\n\nInfoReceiver.prototype = new EventEmitter(['finish']);\n\nInfoReceiver.prototype.doXhr = function(base_url, AjaxObject) {\n    var that = this;\n    var t0 = (new Date()).getTime();\n\n// <METEOR>\n  // https://github.com/sockjs/sockjs-client/pull/129\n  // var xo = new AjaxObject('GET', base_url + '/info');\n\n    var xo = new AjaxObject(\n      // add cachebusting parameter to url to work around a chrome bug:\n      // https://code.google.com/p/chromium/issues/detail?id=263981\n      // or misbehaving proxies.\n      'GET', base_url + '/info?cb=' + utils.random_string(10))\n// </METEOR>\n\n    var tref = utils.delay(8000,\n                           function(){xo.ontimeout();});\n\n    xo.onfinish = function(status, text) {\n        clearTimeout(tref);\n        tref = null;\n        if (status === 200) {\n            var rtt = (new Date()).getTime() - t0;\n            var info = JSON.parse(text);\n            if (typeof info !== 'object') info = {};\n            that.emit('finish', info, rtt);\n        } else {\n            that.emit('finish');\n        }\n    };\n    xo.ontimeout = function() {\n        xo.close();\n        that.emit('finish');\n    };\n};\n\nvar InfoReceiverIframe = function(base_url) {\n    var that = this;\n    var go = function() {\n        var ifr = new IframeTransport();\n        ifr.protocol = 'w-iframe-info-receiver';\n        var fun = function(r) {\n            if (typeof r === 'string' && r.substr(0,1) === 'm') {\n                var d = JSON.parse(r.substr(1));\n                var info = d[0], rtt = d[1];\n                that.emit('finish', info, rtt);\n            } else {\n                that.emit('finish');\n            }\n            ifr.doCleanup();\n            ifr = null;\n        };\n        var mock_ri = {\n            _options: {},\n            _didClose: fun,\n            _didMessage: fun\n        };\n        ifr.i_constructor(mock_ri, base_url, base_url);\n    }\n    if(!_document.body) {\n        utils.attachEvent('load', go);\n    } else {\n        go();\n    }\n};\nInfoReceiverIframe.prototype = new EventEmitter(['finish']);\n\n\nvar InfoReceiverFake = function() {\n    // It may not be possible to do cross domain AJAX to get the info\n    // data, for example for IE7. But we want to run JSONP, so let's\n    // fake the response, with rtt=2s (rto=6s).\n    var that = this;\n    utils.delay(function() {\n        that.emit('finish', {}, 2000);\n    });\n};\nInfoReceiverFake.prototype = new EventEmitter(['finish']);\n\nvar createInfoReceiver = function(base_url) {\n    if (utils.isSameOriginUrl(base_url)) {\n        // If, for some reason, we have SockJS locally - there's no\n        // need to start up the complex machinery. Just use ajax.\n        return new InfoReceiver(base_url, utils.XHRLocalObject);\n    }\n    switch (utils.isXHRCorsCapable()) {\n    case 1:\n        // XHRLocalObject -> no_credentials=true\n        return new InfoReceiver(base_url, utils.XHRLocalObject);\n    case 2:\n// <METEOR>\n// https://github.com/sockjs/sockjs-client/issues/79\n        // XDR doesn't work across different schemes\n        // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx\n        if (utils.isSameOriginScheme(base_url))\n            return new InfoReceiver(base_url, utils.XDRObject);\n        else\n            return new InfoReceiverFake();\n// </METEOR>\n    case 3:\n        // Opera\n        return new InfoReceiverIframe(base_url);\n    default:\n        // IE 7\n        return new InfoReceiverFake();\n    };\n};\n\n\nvar WInfoReceiverIframe = FacadeJS['w-iframe-info-receiver'] = function(ri, _trans_url, base_url) {\n    var ir = new InfoReceiver(base_url, utils.XHRLocalObject);\n    ir.onfinish = function(info, rtt) {\n        ri._didMessage('m'+JSON.stringify([info, rtt]));\n        ri._didClose();\n    }\n};\nWInfoReceiverIframe.prototype.doCleanup = function() {};\n//         [*] End of lib/info.js\n\n\n//         [*] Including lib/trans-iframe-eventsource.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar EventSourceIframeTransport = SockJS['iframe-eventsource'] = function () {\n    var that = this;\n    that.protocol = 'w-iframe-eventsource';\n    that.i_constructor.apply(that, arguments);\n};\n\nEventSourceIframeTransport.prototype = new IframeTransport();\n\nEventSourceIframeTransport.enabled = function () {\n    return ('EventSource' in _window) && IframeTransport.enabled();\n};\n\nEventSourceIframeTransport.need_body = true;\nEventSourceIframeTransport.roundTrips = 3; // html, javascript, eventsource\n\n\n// w-iframe-eventsource\nvar EventSourceTransport = FacadeJS['w-iframe-eventsource'] = function(ri, trans_url) {\n    this.run(ri, trans_url, '/eventsource', EventSourceReceiver, utils.XHRLocalObject);\n}\nEventSourceTransport.prototype = new AjaxBasedTransport();\n//         [*] End of lib/trans-iframe-eventsource.js\n\n\n//         [*] Including lib/trans-iframe-xhr-polling.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar XhrPollingIframeTransport = SockJS['iframe-xhr-polling'] = function () {\n    var that = this;\n    that.protocol = 'w-iframe-xhr-polling';\n    that.i_constructor.apply(that, arguments);\n};\n\nXhrPollingIframeTransport.prototype = new IframeTransport();\n\nXhrPollingIframeTransport.enabled = function () {\n    return _window.XMLHttpRequest && IframeTransport.enabled();\n};\n\nXhrPollingIframeTransport.need_body = true;\nXhrPollingIframeTransport.roundTrips = 3; // html, javascript, xhr\n\n\n// w-iframe-xhr-polling\nvar XhrPollingITransport = FacadeJS['w-iframe-xhr-polling'] = function(ri, trans_url) {\n    this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XHRLocalObject);\n};\n\nXhrPollingITransport.prototype = new AjaxBasedTransport();\n//         [*] End of lib/trans-iframe-xhr-polling.js\n\n\n//         [*] Including lib/trans-iframe-htmlfile.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\n// This transport generally works in any browser, but will cause a\n// spinning cursor to appear in any browser other than IE.\n// We may test this transport in all browsers - why not, but in\n// production it should be only run in IE.\n\nvar HtmlFileIframeTransport = SockJS['iframe-htmlfile'] = function () {\n    var that = this;\n    that.protocol = 'w-iframe-htmlfile';\n    that.i_constructor.apply(that, arguments);\n};\n\n// Inheritance.\nHtmlFileIframeTransport.prototype = new IframeTransport();\n\nHtmlFileIframeTransport.enabled = function() {\n    return IframeTransport.enabled();\n};\n\nHtmlFileIframeTransport.need_body = true;\nHtmlFileIframeTransport.roundTrips = 3; // html, javascript, htmlfile\n\n\n// w-iframe-htmlfile\nvar HtmlFileTransport = FacadeJS['w-iframe-htmlfile'] = function(ri, trans_url) {\n    this.run(ri, trans_url, '/htmlfile', HtmlfileReceiver, utils.XHRLocalObject);\n};\nHtmlFileTransport.prototype = new AjaxBasedTransport();\n//         [*] End of lib/trans-iframe-htmlfile.js\n\n\n//         [*] Including lib/trans-polling.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar Polling = function(ri, Receiver, recv_url, AjaxObject) {\n    var that = this;\n    that.ri = ri;\n    that.Receiver = Receiver;\n    that.recv_url = recv_url;\n    that.AjaxObject = AjaxObject;\n    that._scheduleRecv();\n};\n\nPolling.prototype._scheduleRecv = function() {\n    var that = this;\n    var poll = that.poll = new that.Receiver(that.recv_url, that.AjaxObject);\n    var msg_counter = 0;\n    poll.onmessage = function(e) {\n        msg_counter += 1;\n        that.ri._didMessage(e.data);\n    };\n    poll.onclose = function(e) {\n        that.poll = poll = poll.onmessage = poll.onclose = null;\n        if (!that.poll_is_closing) {\n            if (e.reason === 'permanent') {\n                that.ri._didClose(1006, 'Polling error (' + e.reason + ')');\n            } else {\n                that._scheduleRecv();\n            }\n        }\n    };\n};\n\nPolling.prototype.abort = function() {\n    var that = this;\n    that.poll_is_closing = true;\n    if (that.poll) {\n        that.poll.abort();\n    }\n};\n//         [*] End of lib/trans-polling.js\n\n\n//         [*] Including lib/trans-receiver-eventsource.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar EventSourceReceiver = function(url) {\n    var that = this;\n    var es = new EventSource(url);\n    es.onmessage = function(e) {\n        that.dispatchEvent(new SimpleEvent('message',\n                                           {'data': unescape(e.data)}));\n    };\n    that.es_close = es.onerror = function(e, abort_reason) {\n        // ES on reconnection has readyState = 0 or 1.\n        // on network error it's CLOSED = 2\n        var reason = abort_reason ? 'user' :\n            (es.readyState !== 2 ? 'network' : 'permanent');\n        that.es_close = es.onmessage = es.onerror = null;\n        // EventSource reconnects automatically.\n        es.close();\n        es = null;\n        // Safari and chrome < 15 crash if we close window before\n        // waiting for ES cleanup. See:\n        //   https://code.google.com/p/chromium/issues/detail?id=89155\n        utils.delay(200, function() {\n                        that.dispatchEvent(new SimpleEvent('close', {reason: reason}));\n                    });\n    };\n};\n\nEventSourceReceiver.prototype = new REventTarget();\n\nEventSourceReceiver.prototype.abort = function() {\n    var that = this;\n    if (that.es_close) {\n        that.es_close({}, true);\n    }\n};\n//         [*] End of lib/trans-receiver-eventsource.js\n\n\n//         [*] Including lib/trans-receiver-htmlfile.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar _is_ie_htmlfile_capable;\nvar isIeHtmlfileCapable = function() {\n    if (_is_ie_htmlfile_capable === undefined) {\n        if ('ActiveXObject' in _window) {\n            try {\n                _is_ie_htmlfile_capable = !!new ActiveXObject('htmlfile');\n            } catch (x) {}\n        } else {\n            _is_ie_htmlfile_capable = false;\n        }\n    }\n    return _is_ie_htmlfile_capable;\n};\n\n\nvar HtmlfileReceiver = function(url) {\n    var that = this;\n    utils.polluteGlobalNamespace();\n\n    that.id = 'a' + utils.random_string(6, 26);\n    url += ((url.indexOf('?') === -1) ? '?' : '&') +\n        'c=' + escape(WPrefix + '.' + that.id);\n\n    var constructor = isIeHtmlfileCapable() ?\n        utils.createHtmlfile : utils.createIframe;\n\n    var iframeObj;\n    _window[WPrefix][that.id] = {\n        start: function () {\n            iframeObj.loaded();\n        },\n        message: function (data) {\n            that.dispatchEvent(new SimpleEvent('message', {'data': data}));\n        },\n        stop: function () {\n            that.iframe_close({}, 'network');\n        }\n    };\n    that.iframe_close = function(e, abort_reason) {\n        iframeObj.cleanup();\n        that.iframe_close = iframeObj = null;\n        delete _window[WPrefix][that.id];\n        that.dispatchEvent(new SimpleEvent('close', {reason: abort_reason}));\n    };\n    iframeObj = constructor(url, function(e) {\n                                that.iframe_close({}, 'permanent');\n                            });\n};\n\nHtmlfileReceiver.prototype = new REventTarget();\n\nHtmlfileReceiver.prototype.abort = function() {\n    var that = this;\n    if (that.iframe_close) {\n        that.iframe_close({}, 'user');\n    }\n};\n//         [*] End of lib/trans-receiver-htmlfile.js\n\n\n//         [*] Including lib/trans-receiver-xhr.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\nvar XhrReceiver = function(url, AjaxObject) {\n    var that = this;\n    var buf_pos = 0;\n\n    that.xo = new AjaxObject('POST', url, null);\n    that.xo.onchunk = function(status, text) {\n        if (status !== 200) return;\n        while (1) {\n            var buf = text.slice(buf_pos);\n            var p = buf.indexOf('\\n');\n            if (p === -1) break;\n            buf_pos += p+1;\n            var msg = buf.slice(0, p);\n            that.dispatchEvent(new SimpleEvent('message', {data: msg}));\n        }\n    };\n    that.xo.onfinish = function(status, text) {\n        that.xo.onchunk(status, text);\n        that.xo = null;\n        var reason = status === 200 ? 'network' : 'permanent';\n        that.dispatchEvent(new SimpleEvent('close', {reason: reason}));\n    }\n};\n\nXhrReceiver.prototype = new REventTarget();\n\nXhrReceiver.prototype.abort = function() {\n    var that = this;\n    if (that.xo) {\n        that.xo.close();\n        that.dispatchEvent(new SimpleEvent('close', {reason: 'user'}));\n        that.xo = null;\n    }\n};\n//         [*] End of lib/trans-receiver-xhr.js\n\n\n//         [*] Including lib/test-hooks.js\n/*\n * ***** BEGIN LICENSE BLOCK *****\n * Copyright (c) 2011-2012 VMware, Inc.\n *\n * For the license see COPYING.\n * ***** END LICENSE BLOCK *****\n */\n\n// For testing\nSockJS.getUtils = function(){\n    return utils;\n};\n\nSockJS.getIframeTransport = function(){\n    return IframeTransport;\n};\n//         [*] End of lib/test-hooks.js\n\n                  return SockJS;\n          })();\nif ('_sockjs_onload' in window) setTimeout(_sockjs_onload, 1);\n\n// AMD compliance\nif (typeof define === 'function' && define.amd) {\n    define('sockjs', [], function(){return SockJS;});\n}\n//     [*] End of lib/index.js\n\n// [*] End of lib/all.js\n"
  },
  {
    "path": "packages/ddp-client/stream_client_common.js",
    "content": "// XXX from Underscore.String (http://epeli.github.com/underscore.string/)\nvar startsWith = function(str, starts) {\n  return str.length >= starts.length &&\n    str.substring(0, starts.length) === starts;\n};\nvar endsWith = function(str, ends) {\n  return str.length >= ends.length &&\n    str.substring(str.length - ends.length) === ends;\n};\n\n// @param url {String} URL to Meteor app, eg:\n//   \"/\" or \"madewith.meteor.com\" or \"https://foo.meteor.com\"\n//   or \"ddp+sockjs://ddp--****-foo.meteor.com/sockjs\"\n// @returns {String} URL to the endpoint with the specific scheme and subPath, e.g.\n// for scheme \"http\" and subPath \"sockjs\"\n//   \"http://subdomain.meteor.com/sockjs\" or \"/sockjs\"\n//   or \"https://ddp--1234-foo.meteor.com/sockjs\"\nvar translateUrl =  function(url, newSchemeBase, subPath) {\n  if (! newSchemeBase) {\n    newSchemeBase = \"http\";\n  }\n\n  var ddpUrlMatch = url.match(/^ddp(i?)\\+sockjs:\\/\\//);\n  var httpUrlMatch = url.match(/^http(s?):\\/\\//);\n  var newScheme;\n  if (ddpUrlMatch) {\n    // Remove scheme and split off the host.\n    var urlAfterDDP = url.substr(ddpUrlMatch[0].length);\n    newScheme = ddpUrlMatch[1] === \"i\" ? newSchemeBase : newSchemeBase + \"s\";\n    var slashPos = urlAfterDDP.indexOf('/');\n    var host =\n          slashPos === -1 ? urlAfterDDP : urlAfterDDP.substr(0, slashPos);\n    var rest = slashPos === -1 ? '' : urlAfterDDP.substr(slashPos);\n\n    // In the host (ONLY!), change '*' characters into random digits. This\n    // allows different stream connections to connect to different hostnames\n    // and avoid browser per-hostname connection limits.\n    host = host.replace(/\\*/g, function () {\n      return Math.floor(Random.fraction()*10);\n    });\n\n    return newScheme + '://' + host + rest;\n  } else if (httpUrlMatch) {\n    newScheme = !httpUrlMatch[1] ? newSchemeBase : newSchemeBase + \"s\";\n    var urlAfterHttp = url.substr(httpUrlMatch[0].length);\n    url = newScheme + \"://\" + urlAfterHttp;\n  }\n\n  // Prefix FQDNs but not relative URLs\n  if (url.indexOf(\"://\") === -1 && !startsWith(url, \"/\")) {\n    url = newSchemeBase + \"://\" + url;\n  }\n\n  // XXX This is not what we should be doing: if I have a site\n  // deployed at \"/foo\", then DDP.connect(\"/\") should actually connect\n  // to \"/\", not to \"/foo\". \"/\" is an absolute path. (Contrast: if\n  // deployed at \"/foo\", it would be reasonable for DDP.connect(\"bar\")\n  // to connect to \"/foo/bar\").\n  //\n  // We should make this properly honor absolute paths rather than\n  // forcing the path to be relative to the site root. Simultaneously,\n  // we should set DDP_DEFAULT_CONNECTION_URL to include the site\n  // root. See also client_convenience.js #RationalizingRelativeDDPURLs\n  url = Meteor._relativeToSiteRootUrl(url);\n\n  if (endsWith(url, \"/\"))\n    return url + subPath;\n  else\n    return url + \"/\" + subPath;\n};\n\ntoSockjsUrl = function (url) {\n  return translateUrl(url, \"http\", \"sockjs\");\n};\n\ntoWebsocketUrl = function (url) {\n  var ret = translateUrl(url, \"ws\", \"websocket\");\n  return ret;\n};\n\nLivedataTest.toSockjsUrl = toSockjsUrl;\n\n \n_.extend(LivedataTest.ClientStream.prototype, {\n\n  // Register for callbacks.\n  on: function (name, callback) {\n    var self = this;\n\n    if (name !== 'message' && name !== 'reset' && name !== 'disconnect')\n      throw new Error(\"unknown event type: \" + name);\n\n    if (!self.eventCallbacks[name])\n      self.eventCallbacks[name] = [];\n    self.eventCallbacks[name].push(callback);\n  },\n\n\n  _initCommon: function (options) {\n    var self = this;\n    options = options || {};\n\n    //// Constants\n\n    // how long to wait until we declare the connection attempt\n    // failed.\n    self.CONNECT_TIMEOUT = options.connectTimeoutMs || 10000;\n\n    self.eventCallbacks = {}; // name -> [callback]\n\n    self._forcedToDisconnect = false;\n\n    //// Reactive status\n    self.currentStatus = {\n      status: \"connecting\",\n      connected: false,\n      retryCount: 0\n    };\n\n\n    self.statusListeners = typeof Tracker !== 'undefined' && new Tracker.Dependency;\n    self.statusChanged = function () {\n      if (self.statusListeners)\n        self.statusListeners.changed();\n    };\n\n    //// Retry logic\n    self._retry = new Retry;\n    self.connectionTimer = null;\n\n  },\n\n  // Trigger a reconnect.\n  reconnect: function (options) {\n    var self = this;\n    options = options || {};\n\n    if (options.url) {\n      self._changeUrl(options.url);\n    }\n\n    if (options._sockjsOptions) {\n      self.options._sockjsOptions = options._sockjsOptions;\n    }\n\n    if (self.currentStatus.connected) {\n      if (options._force || options.url) {\n        // force reconnect.\n        self._lostConnection(new DDP.ForcedReconnectError);\n      } // else, noop.\n      return;\n    }\n\n    // if we're mid-connection, stop it.\n    if (self.currentStatus.status === \"connecting\") {\n      // Pretend it's a clean close.\n      self._lostConnection();\n    }\n\n    self._retry.clear();\n    self.currentStatus.retryCount -= 1; // don't count manual retries\n    self._retryNow();\n  },\n\n  disconnect: function (options) {\n    var self = this;\n    options = options || {};\n\n    // Failed is permanent. If we're failed, don't let people go back\n    // online by calling 'disconnect' then 'reconnect'.\n    if (self._forcedToDisconnect)\n      return;\n\n    // If _permanent is set, permanently disconnect a stream. Once a stream\n    // is forced to disconnect, it can never reconnect. This is for\n    // error cases such as ddp version mismatch, where trying again\n    // won't fix the problem.\n    if (options._permanent) {\n      self._forcedToDisconnect = true;\n    }\n\n    self._cleanup();\n    self._retry.clear();\n\n    self.currentStatus = {\n      status: (options._permanent ? \"failed\" : \"offline\"),\n      connected: false,\n      retryCount: 0\n    };\n\n    if (options._permanent && options._error)\n      self.currentStatus.reason = options._error;\n\n    self.statusChanged();\n  },\n\n  // maybeError is set unless it's a clean protocol-level close.\n  _lostConnection: function (maybeError) {\n    var self = this;\n\n    self._cleanup(maybeError);\n    self._retryLater(maybeError); // sets status. no need to do it here.\n  },\n\n  // fired when we detect that we've gone online. try to reconnect\n  // immediately.\n  _online: function () {\n    // if we've requested to be offline by disconnecting, don't reconnect.\n    if (this.currentStatus.status != \"offline\")\n      this.reconnect();\n  },\n\n  _retryLater: function (maybeError) {\n    var self = this;\n\n    var timeout = 0;\n    if (self.options.retry ||\n        (maybeError && maybeError.errorType === \"DDP.ForcedReconnectError\")) {\n      timeout = self._retry.retryLater(\n        self.currentStatus.retryCount,\n        _.bind(self._retryNow, self)\n      );\n      self.currentStatus.status = \"waiting\";\n      self.currentStatus.retryTime = (new Date()).getTime() + timeout;\n    } else {\n      self.currentStatus.status = \"failed\";\n      delete self.currentStatus.retryTime;\n    }\n\n    self.currentStatus.connected = false;\n    self.statusChanged();\n  },\n\n  _retryNow: function () {\n    var self = this;\n\n    if (self._forcedToDisconnect)\n      return;\n\n    self.currentStatus.retryCount += 1;\n    self.currentStatus.status = \"connecting\";\n    self.currentStatus.connected = false;\n    delete self.currentStatus.retryTime;\n    self.statusChanged();\n\n    self._launchConnection();\n  },\n\n\n  // Get current status. Reactive.\n  status: function () {\n    var self = this;\n    if (self.statusListeners)\n      self.statusListeners.depend();\n    return self.currentStatus;\n  }\n});\n\nDDP.ConnectionError = Meteor.makeErrorType(\n  \"DDP.ConnectionError\", function (message) {\n    var self = this;\n    self.message = message;\n});\n\nDDP.ForcedReconnectError = Meteor.makeErrorType(\n  \"DDP.ForcedReconnectError\", function () {});\n"
  },
  {
    "path": "packages/ddp-client/stream_client_nodejs.js",
    "content": "// @param endpoint {String} URL to Meteor app\n//   \"http://subdomain.meteor.com/\" or \"/\" or\n//   \"ddp+sockjs://foo-**.meteor.com/sockjs\"\n//\n// We do some rewriting of the URL to eventually make it \"ws://\" or \"wss://\",\n// whatever was passed in.  At the very least, what Meteor.absoluteUrl() returns\n// us should work.\n//\n// We don't do any heartbeating. (The logic that did this in sockjs was removed,\n// because it used a built-in sockjs mechanism. We could do it with WebSocket\n// ping frames or with DDP-level messages.)\nLivedataTest.ClientStream = function (endpoint, options) {\n  var self = this;\n  options = options || {};\n\n  self.options = _.extend({\n    retry: true\n  }, options);\n\n  self.client = null;  // created in _launchConnection\n  self.endpoint = endpoint;\n\n  self.headers = self.options.headers || {};\n  self.npmFayeOptions = self.options.npmFayeOptions || {};\n\n  self._initCommon(self.options);\n\n  //// Kickoff!\n  self._launchConnection();\n};\n\n_.extend(LivedataTest.ClientStream.prototype, {\n\n  // data is a utf8 string. Data sent while not connected is dropped on\n  // the floor, and it is up the user of this API to retransmit lost\n  // messages on 'reset'\n  send: function (data) {\n    var self = this;\n    if (self.currentStatus.connected) {\n      self.client.send(data);\n    }\n  },\n\n  // Changes where this connection points\n  _changeUrl: function (url) {\n    var self = this;\n    self.endpoint = url;\n  },\n\n  _onConnect: function (client) {\n    var self = this;\n\n    if (client !== self.client) {\n      // This connection is not from the last call to _launchConnection.\n      // But _launchConnection calls _cleanup which closes previous connections.\n      // It's our belief that this stifles future 'open' events, but maybe\n      // we are wrong?\n      throw new Error(\"Got open from inactive client \" + !!self.client);\n    }\n\n    if (self._forcedToDisconnect) {\n      // We were asked to disconnect between trying to open the connection and\n      // actually opening it. Let's just pretend this never happened.\n      self.client.close();\n      self.client = null;\n      return;\n    }\n\n    if (self.currentStatus.connected) {\n      // We already have a connection. It must have been the case that we\n      // started two parallel connection attempts (because we wanted to\n      // 'reconnect now' on a hanging connection and we had no way to cancel the\n      // connection attempt.) But this shouldn't happen (similarly to the client\n      // !== self.client check above).\n      throw new Error(\"Two parallel connections?\");\n    }\n\n    self._clearConnectionTimer();\n\n    // update status\n    self.currentStatus.status = \"connected\";\n    self.currentStatus.connected = true;\n    self.currentStatus.retryCount = 0;\n    self.statusChanged();\n\n    // fire resets. This must come after status change so that clients\n    // can call send from within a reset callback.\n    _.each(self.eventCallbacks.reset, function (callback) { callback(); });\n  },\n\n  _cleanup: function (maybeError) {\n    var self = this;\n\n    self._clearConnectionTimer();\n    if (self.client) {\n      var client = self.client;\n      self.client = null;\n      client.close();\n\n      _.each(self.eventCallbacks.disconnect, function (callback) {\n        callback(maybeError);\n      });\n    }\n  },\n\n  _clearConnectionTimer: function () {\n    var self = this;\n\n    if (self.connectionTimer) {\n      clearTimeout(self.connectionTimer);\n      self.connectionTimer = null;\n    }\n  },\n\n  _getProxyUrl: function (targetUrl) {\n    var self = this;\n    // Similar to code in tools/http-helpers.js.\n    var proxy = process.env.HTTP_PROXY || process.env.http_proxy || null;\n    // if we're going to a secure url, try the https_proxy env variable first.\n    if (targetUrl.match(/^wss:/)) {\n      proxy = process.env.HTTPS_PROXY || process.env.https_proxy || proxy;\n    }\n    return proxy;\n  },\n\n  _launchConnection: function () {\n    var self = this;\n    self._cleanup(); // cleanup the old socket, if there was one.\n\n    // Since server-to-server DDP is still an experimental feature, we only\n    // require the module if we actually create a server-to-server\n    // connection.\n    var FayeWebSocket = Npm.require('faye-websocket');\n    var deflate = Npm.require('permessage-deflate');\n\n    var targetUrl = toWebsocketUrl(self.endpoint);\n    var fayeOptions = {\n      headers: self.headers,\n      extensions: [deflate]\n    };\n    fayeOptions = _.extend(fayeOptions, self.npmFayeOptions);\n    var proxyUrl = self._getProxyUrl(targetUrl);\n    if (proxyUrl) {\n      fayeOptions.proxy = { origin: proxyUrl };\n    };\n\n    // We would like to specify 'ddp' as the subprotocol here. The npm module we\n    // used to use as a client would fail the handshake if we ask for a\n    // subprotocol and the server doesn't send one back (and sockjs doesn't).\n    // Faye doesn't have that behavior; it's unclear from reading RFC 6455 if\n    // Faye is erroneous or not.  So for now, we don't specify protocols.\n    var subprotocols = [];\n\n    var client = self.client = new FayeWebSocket.Client(\n      targetUrl, subprotocols, fayeOptions);\n\n    self._clearConnectionTimer();\n    self.connectionTimer = Meteor.setTimeout(\n      function () {\n        self._lostConnection(\n          new DDP.ConnectionError(\"DDP connection timed out\"));\n      },\n      self.CONNECT_TIMEOUT);\n\n    self.client.on('open', Meteor.bindEnvironment(function () {\n      return self._onConnect(client);\n    }, \"stream connect callback\"));\n\n    var clientOnIfCurrent = function (event, description, f) {\n      self.client.on(event, Meteor.bindEnvironment(function () {\n        // Ignore events from any connection we've already cleaned up.\n        if (client !== self.client)\n          return;\n        f.apply(this, arguments);\n      }, description));\n    };\n\n    clientOnIfCurrent('error', 'stream error callback', function (error) {\n      if (!self.options._dontPrintErrors)\n        Meteor._debug(\"stream error\", error.message);\n\n      // Faye's 'error' object is not a JS error (and among other things,\n      // doesn't stringify well). Convert it to one.\n      self._lostConnection(new DDP.ConnectionError(error.message));\n    });\n\n\n    clientOnIfCurrent('close', 'stream close callback', function () {\n      self._lostConnection();\n    });\n\n\n    clientOnIfCurrent('message', 'stream message callback', function (message) {\n      // Ignore binary frames, where message.data is a Buffer\n      if (typeof message.data !== \"string\")\n        return;\n\n      _.each(self.eventCallbacks.message, function (callback) {\n        callback(message.data);\n      });\n    });\n  }\n});\n"
  },
  {
    "path": "packages/ddp-client/stream_client_sockjs.js",
    "content": "// @param url {String} URL to Meteor app\n//   \"http://subdomain.meteor.com/\" or \"/\" or\n//   \"ddp+sockjs://foo-**.meteor.com/sockjs\"\nLivedataTest.ClientStream = function (url, options) {\n  var self = this;\n  self.options = _.extend({\n    retry: true\n  }, options);\n  self._initCommon(self.options);\n\n  //// Constants\n\n\n  // how long between hearing heartbeat from the server until we declare\n  // the connection dead. heartbeats come every 45s (stream_server.js)\n  //\n  // NOTE: this is a older timeout mechanism. We now send heartbeats at\n  // the DDP level (https://github.com/meteor/meteor/pull/1865), and\n  // expect those timeouts to kill a non-responsive connection before\n  // this timeout fires. This is kept around for compatibility (when\n  // talking to a server that doesn't support DDP heartbeats) and can be\n  // removed later.\n  self.HEARTBEAT_TIMEOUT = 100*1000;\n\n  self.rawUrl = url;\n  self.socket = null;\n\n  self.heartbeatTimer = null;\n\n  // Listen to global 'online' event if we are running in a browser.\n  // (IE8 does not support addEventListener)\n  if (typeof window !== 'undefined' && window.addEventListener)\n    window.addEventListener(\"online\", _.bind(self._online, self),\n                            false /* useCapture. make FF3.6 happy. */);\n\n  //// Kickoff!\n  self._launchConnection();\n};\n\n_.extend(LivedataTest.ClientStream.prototype, {\n\n  // data is a utf8 string. Data sent while not connected is dropped on\n  // the floor, and it is up the user of this API to retransmit lost\n  // messages on 'reset'\n  send: function (data) {\n    var self = this;\n    if (self.currentStatus.connected) {\n      self.socket.send(data);\n    }\n  },\n\n  // Changes where this connection points\n  _changeUrl: function (url) {\n    var self = this;\n    self.rawUrl = url;\n  },\n\n  _connected: function () {\n    var self = this;\n\n    if (self.connectionTimer) {\n      clearTimeout(self.connectionTimer);\n      self.connectionTimer = null;\n    }\n\n    if (self.currentStatus.connected) {\n      // already connected. do nothing. this probably shouldn't happen.\n      return;\n    }\n\n    // update status\n    self.currentStatus.status = \"connected\";\n    self.currentStatus.connected = true;\n    self.currentStatus.retryCount = 0;\n    self.statusChanged();\n\n    // fire resets. This must come after status change so that clients\n    // can call send from within a reset callback.\n    _.each(self.eventCallbacks.reset, function (callback) { callback(); });\n\n  },\n\n  _cleanup: function (maybeError) {\n    var self = this;\n\n    self._clearConnectionAndHeartbeatTimers();\n    if (self.socket) {\n      self.socket.onmessage = self.socket.onclose\n        = self.socket.onerror = self.socket.onheartbeat = function () {};\n      self.socket.close();\n      self.socket = null;\n    }\n\n    _.each(self.eventCallbacks.disconnect, function (callback) {\n      callback(maybeError);\n    });\n  },\n\n  _clearConnectionAndHeartbeatTimers: function () {\n    var self = this;\n    if (self.connectionTimer) {\n      clearTimeout(self.connectionTimer);\n      self.connectionTimer = null;\n    }\n    if (self.heartbeatTimer) {\n      clearTimeout(self.heartbeatTimer);\n      self.heartbeatTimer = null;\n    }\n  },\n\n  _heartbeat_timeout: function () {\n    var self = this;\n    Meteor._debug(\"Connection timeout. No sockjs heartbeat received.\");\n    self._lostConnection(new DDP.ConnectionError(\"Heartbeat timed out\"));\n  },\n\n  _heartbeat_received: function () {\n    var self = this;\n    // If we've already permanently shut down this stream, the timeout is\n    // already cleared, and we don't need to set it again.\n    if (self._forcedToDisconnect)\n      return;\n    if (self.heartbeatTimer)\n      clearTimeout(self.heartbeatTimer);\n    self.heartbeatTimer = setTimeout(\n      _.bind(self._heartbeat_timeout, self),\n      self.HEARTBEAT_TIMEOUT);\n  },\n\n  _sockjsProtocolsWhitelist: function () {\n    // only allow polling protocols. no streaming.  streaming\n    // makes safari spin.\n    var protocolsWhitelist = [\n      'xdr-polling', 'xhr-polling', 'iframe-xhr-polling', 'jsonp-polling'];\n\n    // iOS 4 and 5 and below crash when using websockets over certain\n    // proxies. this seems to be resolved with iOS 6. eg\n    // https://github.com/LearnBoost/socket.io/issues/193#issuecomment-7308865.\n    //\n    // iOS <4 doesn't support websockets at all so sockjs will just\n    // immediately fall back to http\n    var noWebsockets = navigator &&\n          /iPhone|iPad|iPod/.test(navigator.userAgent) &&\n          /OS 4_|OS 5_/.test(navigator.userAgent);\n\n    if (!noWebsockets)\n      protocolsWhitelist = ['websocket'].concat(protocolsWhitelist);\n\n    return protocolsWhitelist;\n  },\n\n  _launchConnection: function () {\n    var self = this;\n    self._cleanup(); // cleanup the old socket, if there was one.\n\n    var options = _.extend({\n      protocols_whitelist:self._sockjsProtocolsWhitelist()\n    }, self.options._sockjsOptions);\n\n    // Convert raw URL to SockJS URL each time we open a connection, so that we\n    // can connect to random hostnames and get around browser per-host\n    // connection limits.\n    self.socket = new SockJS(toSockjsUrl(self.rawUrl), undefined, options);\n    self.socket.onopen = function (data) {\n      self._connected();\n    };\n    self.socket.onmessage = function (data) {\n      self._heartbeat_received();\n\n      if (self.currentStatus.connected)\n        _.each(self.eventCallbacks.message, function (callback) {\n          callback(data.data);\n        });\n    };\n    self.socket.onclose = function () {\n      self._lostConnection();\n    };\n    self.socket.onerror = function () {\n      // XXX is this ever called?\n      Meteor._debug(\"stream error\", _.toArray(arguments), (new Date()).toDateString());\n    };\n\n    self.socket.onheartbeat =  function () {\n      self._heartbeat_received();\n    };\n\n    if (self.connectionTimer)\n      clearTimeout(self.connectionTimer);\n    self.connectionTimer = setTimeout(function () {\n      self._lostConnection(\n        new DDP.ConnectionError(\"DDP connection timed out\"));\n    }, self.CONNECT_TIMEOUT);\n  }\n});\n"
  },
  {
    "path": "packages/ddp-client/stream_client_tests.js",
    "content": "var Fiber = Npm.require('fibers');\n\ntestAsyncMulti(\"stream client - callbacks run in a fiber\", [\n  function (test, expect) {\n    var stream = new LivedataTest.ClientStream(Meteor.absoluteUrl());\n\n    var messageFired = false;\n    var resetFired = false;\n\n    stream.on('message', expect(function () {\n      test.isTrue(Fiber.current);\n      if (resetFired)\n        stream.disconnect();\n      messageFired = true;\n    }));\n\n    stream.on('reset', expect(function () {\n      test.isTrue(Fiber.current);\n      if (messageFired)\n        stream.disconnect();\n      resetFired = true;\n    }));\n  }\n]);\n"
  },
  {
    "path": "packages/ddp-client/stream_tests.js",
    "content": "Tinytest.add(\"stream - status\", function (test) {\n  // Very basic test. Just see that it runs and returns something. Not a\n  // lot of coverage, but enough that it would have caught a recent bug.\n  var status = Meteor.status();\n  test.equal(typeof status, \"object\");\n  test.isTrue(status.status);\n  // Make sure backward-compatiblity names are defined.\n  test.equal(status.retryCount, status.retryCount);\n  test.equal(status.retryTime, status.retryTime);\n});\n\ntestAsyncMulti(\"stream - reconnect\", [\n  function (test, expect) {\n    var callback = _.once(expect(function() {\n      var status;\n      status = Meteor.status();\n      test.equal(status.status, \"connected\");\n\n      Meteor.reconnect();\n      status = Meteor.status();\n      test.equal(status.status, \"connected\");\n\n      Meteor.reconnect({_force: true});\n      status = Meteor.status();\n      test.equal(status.status, \"waiting\");\n    }));\n\n    if (Meteor.status().status !== \"connected\")\n      Meteor.connection._stream.on('reset', callback);\n    else\n      callback();\n  }\n]);\n\n// Disconnecting and reconnecting transitions through the correct statuses.\ntestAsyncMulti(\"stream - basic disconnect\", [\n  function (test, expect) {\n    var history = [];\n    var stream = new LivedataTest.ClientStream(\"/\");\n    var onTestComplete = expect(function (unexpectedHistory) {\n      stream.disconnect();\n      if (unexpectedHistory) {\n        test.fail(\"Unexpected status history: \" +\n                  JSON.stringify(unexpectedHistory));\n      }\n    });\n\n    Tracker.autorun(function() {\n      var status = stream.status();\n\n      if (_.last(history) !== status.status) {\n        history.push(status.status);\n\n        if (_.isEqual(history, [\"connecting\"])) {\n          // do nothing; wait for the next state\n        } else if (_.isEqual(history, [\"connecting\", \"connected\"])) {\n          stream.disconnect();\n        } else if (_.isEqual(history, [\"connecting\", \"connected\", \"offline\"])) {\n          stream.reconnect();\n        } else if (_.isEqual(history, [\"connecting\", \"connected\", \"offline\",\n                                       \"connecting\"])) {\n          // do nothing; wait for the next state\n        } else if (_.isEqual(history, [\"connecting\", \"connected\", \"offline\",\n                                \"connecting\", \"connected\"])) {\n          onTestComplete();\n        } else {\n          onTestComplete(history);\n        }\n      }\n    });\n  }\n]);\n\n// Remain offline if the online event is received while offline.\ntestAsyncMulti(\"stream - disconnect remains offline\", [\n  function (test, expect) {\n    var history = [];\n    var stream = new LivedataTest.ClientStream(\"/\");\n    var onTestComplete = expect(function (unexpectedHistory) {\n      stream.disconnect();\n      if (unexpectedHistory) {\n        test.fail(\"Unexpected status history: \" +\n                  JSON.stringify(unexpectedHistory));\n      }\n    });\n\n    Tracker.autorun(function() {\n      var status = stream.status();\n\n      if (_.last(history) !== status.status) {\n        history.push(status.status);\n\n        if (_.isEqual(history, [\"connecting\"])) {\n          // do nothing; wait for the next status\n        } else if (_.isEqual(history, [\"connecting\", \"connected\"])) {\n          stream.disconnect();\n        } else if (_.isEqual(history, [\"connecting\", \"connected\", \"offline\"])) {\n          stream._online();\n          test.isTrue(status.status === \"offline\");\n          onTestComplete();\n        } else {\n          onTestComplete(history);\n        }\n      }\n    });\n  }\n]);\n\nTinytest.add(\"stream - sockjs urls are computed correctly\", function(test) {\n  var testHasSockjsUrl = function(raw, expectedSockjsUrl) {\n    var actual = LivedataTest.toSockjsUrl(raw);\n    if (expectedSockjsUrl instanceof RegExp)\n      test.isTrue(actual.match(expectedSockjsUrl), actual);\n    else\n      test.equal(actual, expectedSockjsUrl);\n  };\n\n  testHasSockjsUrl(\"http://subdomain.meteor.com/\",\n                   \"http://subdomain.meteor.com/sockjs\");\n  testHasSockjsUrl(\"http://subdomain.meteor.com\",\n                   \"http://subdomain.meteor.com/sockjs\");\n  testHasSockjsUrl(\"subdomain.meteor.com/\",\n                   \"http://subdomain.meteor.com/sockjs\");\n  testHasSockjsUrl(\"subdomain.meteor.com\",\n                   \"http://subdomain.meteor.com/sockjs\");\n  testHasSockjsUrl(\"/\", Meteor._relativeToSiteRootUrl(\"/sockjs\"));\n\n  testHasSockjsUrl(\"http://localhost:3000/\", \"http://localhost:3000/sockjs\");\n  testHasSockjsUrl(\"http://localhost:3000\", \"http://localhost:3000/sockjs\");\n  testHasSockjsUrl(\"localhost:3000\", \"http://localhost:3000/sockjs\");\n\n  testHasSockjsUrl(\"https://subdomain.meteor.com/\",\n                   \"https://subdomain.meteor.com/sockjs\");\n  testHasSockjsUrl(\"https://subdomain.meteor.com\",\n                   \"https://subdomain.meteor.com/sockjs\");\n\n  testHasSockjsUrl(\"ddp+sockjs://ddp--****-foo.meteor.com/sockjs\",\n                   /^https:\\/\\/ddp--\\d\\d\\d\\d-foo\\.meteor\\.com\\/sockjs$/);\n  testHasSockjsUrl(\"ddpi+sockjs://ddp--****-foo.meteor.com/sockjs\",\n                   /^http:\\/\\/ddp--\\d\\d\\d\\d-foo\\.meteor\\.com\\/sockjs$/);\n});\n\ntestAsyncMulti(\"stream - /websocket is a websocket endpoint\", [\n  function(test, expect) {\n    //\n    // Verify that /websocket and /websocket/ don't return the main page\n    //\n    _.each(['/websocket', '/websocket/'], function(path) {\n      HTTP.get(Meteor._relativeToSiteRootUrl(path), expect(function(error, result) {\n        test.isNotNull(error);\n        test.equal('Not a valid websocket request', result.content);\n      }));\n    });\n\n    //\n    // For sanity, also verify that /websockets and /websockets/ return\n    // the main page\n    //\n\n    // Somewhat contorted but we can't call nested expects (XXX why?)\n    var pageContent;\n    var wrappedCallback = expect(function(error, result) {\n      test.isNull(error);\n      test.equal(pageContent, result.content);\n    });\n\n    HTTP.get(Meteor.absoluteUrl('/'), expect(function(error, result) {\n      test.isNull(error);\n      pageContent = result.content;\n\n      _.each(['/websockets', '/websockets/'], function(path) {\n        HTTP.get(Meteor.absoluteUrl(path), wrappedCallback);\n      });\n    }));\n  }\n]);\n"
  },
  {
    "path": "packages/ddp-client/stub_stream.js",
    "content": "StubStream = function () {\n  var self = this;\n\n  self.sent = [];\n  self.callbacks = {};\n};\n\n\n_.extend(StubStream.prototype, {\n  // Methods from Stream\n  on: function (name, callback) {\n    var self = this;\n\n    if (!self.callbacks[name])\n      self.callbacks[name] = [callback];\n    else\n      self.callbacks[name].push(callback);\n  },\n\n  send: function (data) {\n    var self = this;\n    self.sent.push(data);\n  },\n\n  status: function () {\n    return {status: \"connected\", fake: true};\n  },\n\n  reconnect: function () {\n    // no-op\n  },\n\n  _lostConnection: function () {\n    // no-op\n  },\n\n  // Methods for tests\n  receive: function (data) {\n    var self = this;\n\n    if (typeof data === 'object') {\n      data = EJSON.stringify(data);\n    }\n\n    _.each(self.callbacks['message'], function (cb) {\n      cb(data);\n    });\n  },\n\n  reset: function () {\n    var self = this;\n    _.each(self.callbacks['reset'], function (cb) {\n      cb();\n    });\n  },\n\n  // Provide a tag to detect stub streams.\n  // We don't log heartbeat failures on stub streams, for example.\n  _isStub: true\n});\n"
  },
  {
    "path": "packages/ddp-common/heartbeat.js",
    "content": "// Heartbeat options:\n//   heartbeatInterval: interval to send pings, in milliseconds.\n//   heartbeatTimeout: timeout to close the connection if a reply isn't\n//     received, in milliseconds.\n//   sendPing: function to call to send a ping on the connection.\n//   onTimeout: function to call to close the connection.\n\nDDPCommon.Heartbeat = function (options) {\n  var self = this;\n\n  self.heartbeatInterval = options.heartbeatInterval;\n  self.heartbeatTimeout = options.heartbeatTimeout;\n  self._sendPing = options.sendPing;\n  self._onTimeout = options.onTimeout;\n  self._seenPacket = false;\n\n  self._heartbeatIntervalHandle = null;\n  self._heartbeatTimeoutHandle = null;\n};\n\n_.extend(DDPCommon.Heartbeat.prototype, {\n  stop: function () {\n    var self = this;\n    self._clearHeartbeatIntervalTimer();\n    self._clearHeartbeatTimeoutTimer();\n  },\n\n  start: function () {\n    var self = this;\n    self.stop();\n    self._startHeartbeatIntervalTimer();\n  },\n\n  _startHeartbeatIntervalTimer: function () {\n    var self = this;\n    self._heartbeatIntervalHandle = Meteor.setInterval(\n      _.bind(self._heartbeatIntervalFired, self),\n      self.heartbeatInterval\n    );\n  },\n\n  _startHeartbeatTimeoutTimer: function () {\n    var self = this;\n    self._heartbeatTimeoutHandle = Meteor.setTimeout(\n      _.bind(self._heartbeatTimeoutFired, self),\n      self.heartbeatTimeout\n    );\n  },\n\n  _clearHeartbeatIntervalTimer: function () {\n    var self = this;\n    if (self._heartbeatIntervalHandle) {\n      Meteor.clearInterval(self._heartbeatIntervalHandle);\n      self._heartbeatIntervalHandle = null;\n    }\n  },\n\n  _clearHeartbeatTimeoutTimer: function () {\n    var self = this;\n    if (self._heartbeatTimeoutHandle) {\n      Meteor.clearTimeout(self._heartbeatTimeoutHandle);\n      self._heartbeatTimeoutHandle = null;\n    }\n  },\n\n  // The heartbeat interval timer is fired when we should send a ping.\n  _heartbeatIntervalFired: function () {\n    var self = this;\n    // don't send ping if we've seen a packet since we last checked,\n    // *or* if we have already sent a ping and are awaiting a timeout.\n    // That shouldn't happen, but it's possible if\n    // `self.heartbeatInterval` is smaller than\n    // `self.heartbeatTimeout`.\n    if (! self._seenPacket && ! self._heartbeatTimeoutHandle) {\n      self._sendPing();\n      // Set up timeout, in case a pong doesn't arrive in time.\n      self._startHeartbeatTimeoutTimer();\n    }\n    self._seenPacket = false;\n  },\n\n  // The heartbeat timeout timer is fired when we sent a ping, but we\n  // timed out waiting for the pong.\n  _heartbeatTimeoutFired: function () {\n    var self = this;\n    self._heartbeatTimeoutHandle = null;\n    self._onTimeout();\n  },\n\n  messageReceived: function () {\n    var self = this;\n    // Tell periodic checkin that we have seen a packet, and thus it\n    // does not need to send a ping this cycle.\n    self._seenPacket = true;\n    // If we were waiting for a pong, we got it.\n    if (self._heartbeatTimeoutHandle) {\n      self._clearHeartbeatTimeoutTimer();\n    }\n  }\n});\n"
  },
  {
    "path": "packages/ddp-common/method_invocation.js",
    "content": "// Instance name is this because it is usually referred to as this inside a\n// method definition\n/**\n * @summary The state for a single invocation of a method, referenced by this\n * inside a method definition.\n * @param {Object} options\n * @instanceName this\n */\nDDPCommon.MethodInvocation = function (options) {\n  var self = this;\n\n  // true if we're running not the actual method, but a stub (that is,\n  // if we're on a client (which may be a browser, or in the future a\n  // server connecting to another server) and presently running a\n  // simulation of a server-side method for latency compensation\n  // purposes). not currently true except in a client such as a browser,\n  // since there's usually no point in running stubs unless you have a\n  // zero-latency connection to the user.\n\n  /**\n   * @summary Access inside a method invocation.  Boolean value, true if this invocation is a stub.\n   * @locus Anywhere\n   * @name  isSimulation\n   * @memberOf DDPCommon.MethodInvocation\n   * @instance\n   * @type {Boolean}\n   */\n  this.isSimulation = options.isSimulation;\n\n  // call this function to allow other method invocations (from the\n  // same client) to continue running without waiting for this one to\n  // complete.\n  this._unblock = options.unblock || function () {};\n  this._calledUnblock = false;\n\n  // current user id\n\n  /**\n   * @summary The id of the user that made this method call, or `null` if no user was logged in.\n   * @locus Anywhere\n   * @name  userId\n   * @memberOf DDPCommon.MethodInvocation\n   * @instance\n   */\n  this.userId = options.userId;\n\n  // sets current user id in all appropriate server contexts and\n  // reruns subscriptions\n  this._setUserId = options.setUserId || function () {};\n\n  // On the server, the connection this method call came in on.\n\n  /**\n   * @summary Access inside a method invocation. The [connection](#meteor_onconnection) that this method was received on. `null` if the method is not associated with a connection, eg. a server initiated method call. Calls to methods made from a server method which was in turn initiated from the client share the same `connection`. \n   * @locus Server\n   * @name  connection\n   * @memberOf DDPCommon.MethodInvocation\n   * @instance\n   */\n  this.connection = options.connection;\n\n  // The seed for randomStream value generation\n  this.randomSeed = options.randomSeed;\n\n  // This is set by RandomStream.get; and holds the random stream state\n  this.randomStream = null;\n};\n\n_.extend(DDPCommon.MethodInvocation.prototype, {\n  /**\n   * @summary Call inside a method invocation.  Allow subsequent method from this client to begin running in a new fiber.\n   * @locus Server\n   * @memberOf DDPCommon.MethodInvocation\n   * @instance\n   */\n  unblock: function () {\n    var self = this;\n    self._calledUnblock = true;\n    self._unblock();\n  },\n\n  /**\n   * @summary Set the logged in user.\n   * @locus Server\n   * @memberOf DDPCommon.MethodInvocation\n   * @instance\n   * @param {String | null} userId The value that should be returned by `userId` on this connection.\n   */\n  setUserId: function(userId) {\n    var self = this;\n    if (self._calledUnblock)\n      throw new Error(\"Can't call setUserId in a method after calling unblock\");\n    self.userId = userId;\n    self._setUserId(userId);\n  }\n});\n\n"
  },
  {
    "path": "packages/ddp-common/namespace.js",
    "content": "/**\n * @namespace DDPCommon\n * @summary Namespace for DDPCommon-related methods/classes. Shared between \n * `ddp-client` and `ddp-server`, where the ddp-client is the implementation\n * of a ddp client for both client AND server; and the ddp server is the\n * implementation of the livedata server and stream server. Common \n * functionality shared between both can be shared under this namespace\n */\nDDPCommon = {};\n"
  },
  {
    "path": "packages/ddp-common/package.js",
    "content": "Package.describe({\n  summary: \"Code shared beween ddp-client and ddp-server\",\n  version: '1.2.6',\n  documentation: null\n});\n\nPackage.onUse(function (api) {\n  api.use(['check', 'random', 'ejson', 'underscore', 'tracker',\n           'retry'],\n          ['client', 'server']);\n\n  api.addFiles('namespace.js');\n\n  api.addFiles('heartbeat.js', ['client', 'server']);\n  api.addFiles('utils.js', ['client', 'server']);\n  api.addFiles('method_invocation.js', ['client', 'server']);\n  api.addFiles('random_stream.js', ['client', 'server']);\n\n  api.export('DDPCommon');\n});\n\nPackage.onTest(function (api) {\n  // XXX we should write unit tests for heartbeat\n});\n"
  },
  {
    "path": "packages/ddp-common/random_stream.js",
    "content": "// RandomStream allows for generation of pseudo-random values, from a seed.\n//\n// We use this for consistent 'random' numbers across the client and server.\n// We want to generate probably-unique IDs on the client, and we ideally want\n// the server to generate the same IDs when it executes the method.\n//\n// For generated values to be the same, we must seed ourselves the same way,\n// and we must keep track of the current state of our pseudo-random generators.\n// We call this state the scope. By default, we use the current DDP method\n// invocation as our scope.  DDP now allows the client to specify a randomSeed.\n// If a randomSeed is provided it will be used to seed our random sequences.\n// In this way, client and server method calls will generate the same values.\n//\n// We expose multiple named streams; each stream is independent\n// and is seeded differently (but predictably from the name).\n// By using multiple streams, we support reordering of requests,\n// as long as they occur on different streams.\n//\n// @param options {Optional Object}\n//   seed: Array or value - Seed value(s) for the generator.\n//                          If an array, will be used as-is\n//                          If a value, will be converted to a single-value array\n//                          If omitted, a random array will be used as the seed.\nDDPCommon.RandomStream = function (options) {\n  var self = this;\n\n  this.seed = [].concat(options.seed || randomToken());\n\n  this.sequences = {};\n};\n\n// Returns a random string of sufficient length for a random seed.\n// This is a placeholder function; a similar function is planned\n// for Random itself; when that is added we should remove this function,\n// and call Random's randomToken instead.\nfunction randomToken() {\n  return Random.hexString(20);\n};\n\n// Returns the random stream with the specified name, in the specified\n// scope. If a scope is passed, then we use that to seed a (not\n// cryptographically secure) PRNG using the fast Alea algorithm.  If\n// scope is null (or otherwise falsey) then we use a generated seed.\n//\n// However, scope will normally be the current DDP method invocation,\n// so we'll use the stream with the specified name, and we should get\n// consistent values on the client and server sides of a method call.\nDDPCommon.RandomStream.get = function (scope, name) {\n  if (!name) {\n    name = \"default\";\n  }\n  if (!scope) {\n    // There was no scope passed in; the sequence won't actually be\n    // reproducible. but make it fast (and not cryptographically\n    // secure) anyways, so that the behavior is similar to what you'd\n    // get by passing in a scope.\n    return Random.insecure;\n  }\n  var randomStream = scope.randomStream;\n  if (!randomStream) {\n    scope.randomStream = randomStream = new DDPCommon.RandomStream({\n      seed: scope.randomSeed\n    });\n  }\n  return randomStream._sequence(name);\n};\n\n\n// Creates a randomSeed for passing to a method call.\n// Note that we take enclosing as an argument,\n// though we expect it to be DDP._CurrentInvocation.get()\n// However, we often evaluate makeRpcSeed lazily, and thus the relevant\n// invocation may not be the one currently in scope.\n// If enclosing is null, we'll use Random and values won't be repeatable.\nDDPCommon.makeRpcSeed = function (enclosing, methodName) {\n  var stream = DDPCommon.RandomStream.get(enclosing, '/rpc/' + methodName);\n  return stream.hexString(20);\n};\n\n_.extend(DDPCommon.RandomStream.prototype, {\n  // Get a random sequence with the specified name, creating it if does not exist.\n  // New sequences are seeded with the seed concatenated with the name.\n  // By passing a seed into Random.create, we use the Alea generator.\n  _sequence: function (name) {\n    var self = this;\n\n    var sequence = self.sequences[name] || null;\n    if (sequence === null) {\n      var sequenceSeed = self.seed.concat(name);\n      for (var i = 0; i < sequenceSeed.length; i++) {\n        if (_.isFunction(sequenceSeed[i])) {\n          sequenceSeed[i] = sequenceSeed[i]();\n        }\n      }\n      self.sequences[name] = sequence = Random.createWithSeeds.apply(null, sequenceSeed);\n    }\n    return sequence;\n  }\n});\n"
  },
  {
    "path": "packages/ddp-common/utils.js",
    "content": "DDPCommon.SUPPORTED_DDP_VERSIONS = [ '1', 'pre2', 'pre1' ];\n\nDDPCommon.parseDDP = function (stringMessage) {\n  try {\n    var msg = JSON.parse(stringMessage);\n  } catch (e) {\n    Meteor._debug(\"Discarding message with invalid JSON\", stringMessage);\n    return null;\n  }\n  // DDP messages must be objects.\n  if (msg === null || typeof msg !== 'object') {\n    Meteor._debug(\"Discarding non-object DDP message\", stringMessage);\n    return null;\n  }\n\n  // massage msg to get it into \"abstract ddp\" rather than \"wire ddp\" format.\n\n  // switch between \"cleared\" rep of unsetting fields and \"undefined\"\n  // rep of same\n  if (_.has(msg, 'cleared')) {\n    if (!_.has(msg, 'fields'))\n      msg.fields = {};\n    _.each(msg.cleared, function (clearKey) {\n      msg.fields[clearKey] = undefined;\n    });\n    delete msg.cleared;\n  }\n\n  _.each(['fields', 'params', 'result'], function (field) {\n    if (_.has(msg, field))\n      msg[field] = EJSON._adjustTypesFromJSONValue(msg[field]);\n  });\n\n  return msg;\n};\n\nDDPCommon.stringifyDDP = function (msg) {\n  var copy = EJSON.clone(msg);\n  // swizzle 'changed' messages from 'fields undefined' rep to 'fields\n  // and cleared' rep\n  if (_.has(msg, 'fields')) {\n    var cleared = [];\n    _.each(msg.fields, function (value, key) {\n      if (value === undefined) {\n        cleared.push(key);\n        delete copy.fields[key];\n      }\n    });\n    if (!_.isEmpty(cleared))\n      copy.cleared = cleared;\n    if (_.isEmpty(copy.fields))\n      delete copy.fields;\n  }\n  // adjust types to basic\n  _.each(['fields', 'params', 'result'], function (field) {\n    if (_.has(copy, field))\n      copy[field] = EJSON._adjustTypesToJSONValue(copy[field]);\n  });\n  if (msg.id && typeof msg.id !== 'string') {\n    throw new Error(\"Message id is not a string\");\n  }\n  return JSON.stringify(copy);\n};\n\n"
  },
  {
    "path": "packages/ddp-rate-limiter/README.md",
    "content": "DDP Rate Limiter package\n===\n\nA rate limiter added directly to DDP that provides an API to add rules to\nMeteor methods and collections.\n\n### Pre-defined Defaults\n\nIf the `accounts-base` package is added to your\nproject, there are default rules added to limit logins, new user registration\nand password resets calls to a limit of 5 requests per 10 seconds per\nconnection.\nThese provide a basic solution to dictionary attacks where a malicious user\nattempts to guess the passwords of legitimate users by attempting all possible\npasswords. To remove the default rule, a user can add\n`Accounts.removeDefaultRateLimit()` to any server side code and the default\nrate limit will be removed.\n\n### Configuration\n\nThe `DDPRateLimiter` is configured with a set of rules. Each rule is a set of\nkeys to be inspected with filters on those keys to specify all DDP messages\nthat satisfy the rule. Each of these possible messages that satisfy the rule\nis given a bucket by creating a unique string composed of all the keys in the\nrule and the values from the message. After each rule's specified time\ninterval, all the buckets are deleted. A rate limit is said to have been hit\nwhen a bucket has reached the rule's capacity, at which point errors will be\nreturned for that input until the buckets are reset.\n\nA rule is defined as a set of key-value pairs where the keys are one or more\nof `userId`, `clientAddress`, `type`, `name`, and `connectionId`. The values\ncan either be null, primitives or functions. When you want to rate limit some\nusers but not others, a rule can match invocations using a function in a way\nthat is determined at run time based on the database or other data. In our\nexample, we check the database to avoid rate limiting admin users.\n\nWhen we add the rule to DDPRateLimiter, we also specify the number of messages\nthat we allow and the time interval on which the rate limit is reset.\n\n### Example Usage\n\nFor example, let's add a rule for all login methods that restrict all users\nbut admins to 5 login attempts per second:\n\n```javascript\n// Define a rule that matches login attempts by non-admin users\nvar loginRule = {\n  userId: function (userId) {\n    return Meteor.users.findOne(userId).type !== 'Admin';\n  },\n  type: 'method',\n  name: 'login'\n}\n// Add the rule, allowing up to 5 messages every 1000 milliseconds.\nDDPRateLimiter.addRule(loginRule, 5, 1000);\n```\n\nFor more information, check out the documentation on the [DDP Rate Limiter]\n(http://docs.meteor.com/#ddpratelimiter).\n"
  },
  {
    "path": "packages/ddp-rate-limiter/ddp-rate-limiter-test-service.js",
    "content": "Meteor.methods({\n  // Adds in a new rule with the specific intervalTime and connectionId as\n  // passed in to speed up testing & allow the rule to apply to the connection\n  // testing the rate limit.\n  addRuleToDDPRateLimiter: function () {\n    var connection = this.connection;\n    connection.lastRateLimitEvent = connection.lastRateLimitEvent || {};\n    connection.lastMethodName = connection.lastMethodName || '';\n    // XXX In Javascript v8 engine, we are currently guaranteed the ordering of\n    // the keys in objects as they are listed. This may change in future\n    // iterations of v8 for performance reasons and will potentially break this\n    // test.\n    //\n    // This is important because we use `connection.lastMethodName` to\n    // ignore the \"getLastRateLimitEvent\" method so that it can return\n    // the actual last rate limit event rather than the one\n    // corresponding to the method call to \"getLastRateLimitEvent\".\n    this.ruleId = DDPRateLimiter.addRule({\n      name: function (name) {\n        connection.lastMethodName = name;\n        if (name !== 'getLastRateLimitEvent') {\n          connection.lastRateLimitEvent.name = name;\n        }\n        return name !== \"a-method-that-is-not-rate-limited\";\n      },\n      userId: function (userId) {\n        connection.lastRateLimitEvent.userId = userId;\n        return true;\n      },\n      type: function (type) {\n        // Special check to return proper name since 'getLastRateLimitEvent'\n        // is another method call\n        if (connection.lastMethodName !== 'getLastRateLimitEvent'){\n          connection.lastRateLimitEvent.type = type;\n        }\n        return true;\n      },\n      clientAddress: function (clientAddress) {\n        connection.lastRateLimitEvent.clientAddress = clientAddress\n        return true;\n      },\n      connectionId: this.connection.id\n    }, RATE_LIMIT_NUM_CALLS, RATE_LIMIT_INTERVAL_TIME_MS);\n\n    return this.ruleId;\n  },\n  getLastRateLimitEvent: function () {\n    return this.connection.lastRateLimitEvent;\n  },\n  // Server side method to remove rule from DDP Rate Limiter\n  removeRuleFromDDPRateLimiter: function (id) {\n    return DDPRateLimiter.removeRule(id);\n  },\n  // Print all the server rules for debugging purposes.\n  printCurrentListOfRules: function () {\n    console.log('Current list of rules :', DDPRateLimiter.printRules());\n  },\n  removeUserByUsername: function (username) {\n    Meteor.users.remove({username: username});\n  },\n  dummyMethod: function () {\n    return \"yup\";\n  },\n  'a-method-that-is-not-rate-limited': function () {\n    return \"not-rate-limited\";\n  },\n  addDefaultAccountsRateLimitRule: function () {\n    Accounts.addDefaultRateLimit();\n  },\n  removeDefaultAccountsRateLimitRule: function () {\n    return Accounts.removeDefaultRateLimit();\n  }\n});\n\nMeteor.publish(\"testSubscription\", function () {\n  return [];\n});\n"
  },
  {
    "path": "packages/ddp-rate-limiter/ddp-rate-limiter-tests-common.js",
    "content": "// Common settings for DDPRateLimiter tests.\nRATE_LIMIT_NUM_CALLS = 5;\nRATE_LIMIT_INTERVAL_TIME_MS = 5000;"
  },
  {
    "path": "packages/ddp-rate-limiter/ddp-rate-limiter-tests.js",
    "content": "// Test that we do hit the default login rate limit.\n// XXX Removed to fix testing as other packages currently hit the default rate\n// limit.\ntestAsyncMulti(\"ddp rate limiter - default rate limit\", [\n  function (test, expect) {\n    // Add in the default rate limiter rule\n    Meteor.call('addDefaultAccountsRateLimitRule');\n    _.extend(this, createTestUser(test, expect));\n  },\n  function (test, expect) {\n    Meteor.logout(expect(function (error) {\n      test.equal(error, undefined);\n      test.equal(Meteor.user(), null);\n    }));\n  },\n  function (test, expect) {\n    var self = this;\n\n    callFnMultipleTimesThenExpectResult(test, expect,\n      Meteor.loginWithPassword.bind(Meteor, self.username, 'fakePassword'),\n      {\n        expectedError: 403,\n        expectedResult: undefined,\n        expectedRateLimitWillBeHit: true,\n        expectedIntervalTimeInMs: 10000\n      }\n    );\n  },\n  function (test, expect) {\n    Meteor.call(\"removeUserByUsername\", this.username, expect(function () {}));\n    // Remove the default rate limiter rule\n    Meteor.call('removeDefaultAccountsRateLimitRule');\n  }\n]);\n\ntestAsyncMulti(\"ddp rate limiter - matchers get passed correct arguments\", [\n  function (test, expect) {\n    _.extend(this, createTestUser(test, expect));\n  },\n  function (test, expect) {\n    var self = this;\n    Meteor.call(\"addRuleToDDPRateLimiter\", expect(function(error, result) {\n     self.ruleId = result;\n    }));\n  },\n  function (test, expect) {\n    callFnMultipleTimesThenExpectResult(test, expect,\n      Meteor.call.bind(Meteor, 'dummyMethod'),\n      {\n        expectedError: undefined,\n        expectedResult: \"yup\",\n        expectedRateLimitWillBeHit: true\n      }\n    );\n  },\n  function (test, expect) {\n    var self = this;\n    Meteor.call(\n      \"getLastRateLimitEvent\", expect(function (error, result) {\n        test.equal(error, undefined);\n        test.equal(result.userId, Meteor.userId());\n        test.equal(result.type, \"method\");\n        test.equal(result.name, \"dummyMethod\");\n        test.isNotUndefined(result.clientAddress, \"clientAddress is not defined\");\n      }));\n  },\n  function (test, expect) {\n    Meteor.call(\"removeUserByUsername\", this.username, expect(function () {}));\n  },\n  function (test, expect) {\n    var self = this;\n    // Cleanup\n    Meteor.call('removeRuleFromDDPRateLimiter', self.ruleId,\n      expect(function(error, result) {\n        test.equal(result,true);\n    }));\n  }\n]);\n\ntestAsyncMulti(\"ddp rate limiter - we can return with type 'subscription'\", [\n  function (test, expect) {\n    var self = this;\n    Meteor.call(\"addRuleToDDPRateLimiter\", expect(\n      function(error, result) {\n        self.ruleId = result;\n      }));\n  },\n  function (test, expect) {\n    Meteor.subscribe('testSubscription');\n    Meteor.call('getLastRateLimitEvent', expect(function(error, result){\n      test.equal(error, undefined);\n      test.equal(result.type, \"subscription\");\n      test.equal(result.name, \"testSubscription\");\n      test.isNotUndefined(result.clientAddress, \"clientAddress is not defined\");\n    }));\n  },\n  function (test, expect) {\n    var self = this;\n    // Cleanup\n    Meteor.call('removeRuleFromDDPRateLimiter', self.ruleId,\n      expect(function(error, result) {\n        test.equal(result, true);\n    }));\n  }\n]);\n\ntestAsyncMulti(\"ddp rate limiter - rate limits to subscriptions\", [\n  function (test, expect) {\n    var self = this;\n    Meteor.call(\"addRuleToDDPRateLimiter\", expect(\n      function(error, result) {\n        self.ruleId = result;\n      })\n    );\n  },\n  function (test, expect) {\n    this.doSub = function (cb) {\n      Meteor.subscribe('testSubscription', {\n        onReady: function () {\n          cb(null, true);\n        },\n        onStop: function (error) {\n          cb(error, undefined);\n        }\n      });\n    };\n\n    callFnMultipleTimesThenExpectResult(test, expect, this.doSub,\n      {\n        expectedError: null,\n        expectedResult: true,\n        expectedRateLimitWillBeHit: true\n      }\n    );\n  },\n  function (test, expect) {\n    // After removing rule, subscriptions are no longer rate limited.\n    var self = this;\n    Meteor.call('removeRuleFromDDPRateLimiter', self.ruleId,\n      expect(function(error, result) {\n        test.equal(result,true);\n    }));\n  },\n  function (test, expect) {\n    callFnMultipleTimesThenExpectResult(test, expect, this.doSub,\n    {\n      expectedError: null,\n      expectedResult: true,\n      expectedIntervalTimeInMs: false\n    });\n\n    callFnMultipleTimesThenExpectResult(test, expect, this.doSub,\n    {\n      expectedError: null,\n      expectedResult: true,\n      expectedIntervalTimeInMs: false\n    });\n  }\n]);\n\n\n// - If you wait 5 seconds you are no longer rate limited\ntestAsyncMulti(\"ddp rate limiter - rate limit resets after \" +\n  \"RATE_LIMIT_INTERVAL_TIME_MS\", [\n  function (test, expect) {\n    _.extend(this, createTestUser(test, expect));\n  },\n  function (test, expect) {\n    var self = this;\n    Meteor.call(\"addRuleToDDPRateLimiter\", expect(function(error, result) {\n     self.ruleId = result;\n    }));\n  },\n\n  function (test, expect) {\n    callFnMultipleTimesThenExpectResult(test, expect,\n      Meteor.call.bind(Meteor, 'dummyMethod'),\n      {\n        expectedError: undefined,\n        expectedResult: \"yup\",\n        expectedRateLimitWillBeHit: true\n      }\n    );\n  },\n  function (test, expect) {\n    Meteor.setTimeout(expect(), RATE_LIMIT_INTERVAL_TIME_MS);\n  },\n  function (test, expect) {\n    callFnMultipleTimesThenExpectResult(test, expect,\n      Meteor.call.bind(Meteor, 'dummyMethod'),\n      {\n        expectedError: undefined,\n        expectedResult: \"yup\",\n        expectedRateLimitWillBeHit: true\n      }\n    );\n  },\n  function (test, expect) {\n    var self = this;\n    Meteor.call('removeRuleFromDDPRateLimiter', self.ruleId,\n      expect(function(error, result) {\n        test.equal(result, true);\n    }));\n  }\n]);\n\ntestAsyncMulti(\"ddp rate limiter - 'a-method-that-is-not-rate-limited' is not\" +\n  \" rate limited\", [\n  function (test, expect) {\n    var self = this;\n    Meteor.call('addRuleToDDPRateLimiter', expect(function(error, result){\n      self.ruleId = result;\n    }));\n  },\n  function (test, expect) {\n    callFnMultipleTimesThenExpectResult(test, expect,\n      Meteor.call.bind(Meteor, 'a-method-that-is-not-rate-limited'),\n      {\n        expectedError: undefined,\n        expectedResult: \"not-rate-limited\",\n        expectedRateLimitWillBeHit: false\n      });\n  },\n  function (test, expect) {\n    var self = this;\n    Meteor.call('removeRuleFromDDPRateLimiter', self.ruleId,\n      expect(function(error, result) {\n        test.equal(result, true);\n    }));\n  }\n]);\n\n// When we have a rate limited client and we remove the rate limit rule,\n// all requests should be allowed immediately afterwards.\ntestAsyncMulti(\"ddp rate limiter - test removing rule with rateLimited \" +\n  \"client lets them send new queries\", [\n  function (test, expect) {\n    _.extend(this, createTestUser(test, expect));\n  },\n  function (test, expect) {\n    var self = this;\n    Meteor.call(\"addRuleToDDPRateLimiter\", expect(function(error, result) {\n     self.ruleId = result;\n    }));\n  },\n  function (test, expect) {\n    Meteor.logout(expect(function (error) {\n      test.equal(error, undefined);\n      test.equal(Meteor.user(), null);\n    }));\n  },\n  function (test, expect) {\n    var self = this;\n    // By removing the rule from the DDP rate limiter, we no longer restrict\n    // them even though they were rate limited\n    Meteor.call('removeRuleFromDDPRateLimiter', self.ruleId,\n      expect(function(error, result) {\n        test.equal(result,true);\n    }));\n  },\n  function (test, expect) {\n    callFnMultipleTimesThenExpectResult(test, expect,\n      Meteor.call.bind(Meteor, 'dummyMethod'),\n      {\n        expectedError: undefined,\n        expectedResult: \"yup\",\n        expectedRateLimitWillBeHit: false\n      }\n    );\n\n    callFnMultipleTimesThenExpectResult(test, expect,\n      Meteor.call.bind(Meteor, 'dummyMethod'),\n      {\n        expectedError: undefined,\n        expectedResult: \"yup\",\n        expectedRateLimitWillBeHit: false\n      }\n    );\n  },\n  function (test, expect) {\n    Meteor.call(\"removeUserByUsername\", this.username, expect(function () {}));\n  }\n]);\n\nfunction createTestUser(test, expect) {\n  const username = Random.id();\n  const email = Random.id() + '-intercept@example.com';\n  const password = 'password';\n\n  Accounts.createUser({\n    username: username,\n    email: email,\n    password: password\n  },\n  expect(function (error, result) {\n    test.equal(error, undefined);\n    test.notEqual(Meteor.userId(), null);\n  }));\n\n  return {username, email, password};\n};\n\n/**\n * A utility function that runs an arbitrary JavaScript function with a single\n * Node-style callback argument multiple times, verifying that the callback is\n * fired with certain arguments; then run the function one more time,\n * conditionally verifying that the callback is now fired with the \"too-many-\n * request\" rate limit error.\n *\n * @param             test                       As in testAsyncMulti\n * @param             expect                     As in testAsyncMulti\n * @param  {Function} fn                         [description]\n * @param             expectedError              expected error before hitting\n *                                               rate limit\n * @param             expectedResult             result expected before hitting\n *                                               rate limit\n * @param  {boolean}   expectedRateLimitWillBeHit Should we hit rate limit\n */\nfunction callFnMultipleTimesThenExpectResult(\n  test, expect, fn, {expectedError, expectedResult, expectedRateLimitWillBeHit,\n  expectedIntervalTimeInMs}) {\n\n  for (var i = 0; i < RATE_LIMIT_NUM_CALLS; i++) {\n    fn(expect(function (error, result) {\n      test.equal(error && error.error, expectedError);\n      test.equal(result, expectedResult);\n    }));\n  }\n\n  fn(expect(function (error, result) {\n    if (expectedRateLimitWillBeHit) {\n      test.equal(error && error.error, 'too-many-requests', 'error : ' + error);\n      test.isTrue(error &&  error.details.timeToReset <\n        expectedIntervalTimeInMs || RATE_LIMIT_INTERVAL_TIME_MS, 'too long');\n      test.equal(result, undefined, 'result is not undefined');\n    } else {\n      test.equal(error && error.error, expectedError);\n      test.equal(result, expectedResult);\n    }\n  }));\n}"
  },
  {
    "path": "packages/ddp-rate-limiter/ddp-rate-limiter.js",
    "content": "// Rate Limiter built into DDP with a default error message. See README or\n// online documentation for more details.\nDDPRateLimiter = {};\n\nvar errorMessage = function (rateLimitResult) {\n  return \"Error, too many requests. Please slow down. You must wait \" +\n    Math.ceil(rateLimitResult.timeToReset / 1000) + \" seconds before \" +\n    \"trying again.\";\n};\nvar rateLimiter = new RateLimiter();\n\nDDPRateLimiter.getErrorMessage = function (rateLimitResult) {\n  if (typeof errorMessage === 'function')\n    return errorMessage(rateLimitResult);\n  else\n    return errorMessage;\n};\n\n/**\n * @summary Set error message text when method or subscription rate limit\n * exceeded.\n * @param {string|function} message Functions are passed in an object with a\n * `timeToReset` field that specifies the number of milliseconds until the next\n * method or subscription is allowed to run. The function must return a string\n * of the error message.\n * @locus Server\n */\nDDPRateLimiter.setErrorMessage = function (message) {\n  errorMessage = message;\n};\n\n/**\n * @summary\n * Add a rule that matches against a stream of events describing method or\n * subscription attempts. Each event is an object with the following\n * properties:\n *\n * - `type`: Either \"method\" or \"subscription\"\n * - `name`: The name of the method or subscription being called\n * - `userId`: The user ID attempting the method or subscription\n * - `connectionId`: A string representing the user's DDP connection\n * - `clientAddress`: The IP address of the user\n *\n * Returns unique `ruleId` that can be passed to `removeRule`.\n *\n * @param {Object} matcher\n *   Matchers specify which events are counted towards a rate limit. A matcher\n *   is an object that has a subset of the same properties as the event objects\n *   described above. Each value in a matcher object is one of the following:\n *\n *   - a string: for the event to satisfy the matcher, this value must be equal\n *   to the value of the same property in the event object\n *\n *   - a function: for the event to satisfy the matcher, the function must\n *   evaluate to true when passed the value of the same property\n *   in the event object\n *\n * Here's how events are counted: Each event that satisfies the matcher's\n * filter is mapped to a bucket. Buckets are uniquely determined by the\n * event object's values for all properties present in both the matcher and\n * event objects.\n *\n * @param {number} numRequests  number of requests allowed per time interval.\n * Default = 10.\n * @param {number} timeInterval time interval in milliseconds after which\n * rule's counters are reset. Default = 1000.\n * @locus Server\n */\nDDPRateLimiter.addRule = function (matcher, numRequests, timeInterval) {\n  return rateLimiter.addRule(matcher, numRequests, timeInterval);\n};\n\nDDPRateLimiter.printRules = function () {\n  return rateLimiter.rules;\n};\n\n/**\n * @summary Removes the specified rule from the rate limiter. If rule had\n * hit a rate limit, that limit is removed as well.\n * @param  {string} id 'ruleId' returned from `addRule`\n * @return {boolean}    True if a rule was removed.\n * @locus Server\n */\nDDPRateLimiter.removeRule = function (id) {\n  return rateLimiter.removeRule(id);\n};\n\n// This is accessed inside livedata_server.js, but shouldn't be called by any\n// user.\nDDPRateLimiter._increment = function (input) {\n  rateLimiter.increment(input);\n};\n\nDDPRateLimiter._check = function (input) {\n  return rateLimiter.check(input);\n};\n"
  },
  {
    "path": "packages/ddp-rate-limiter/package.js",
    "content": "Package.describe({\n  name: 'ddp-rate-limiter',\n  version: '1.0.5',\n  // Brief, one-line summary of the package.\n  summary: 'The DDPRateLimiter allows users to add rate limits to DDP' +\n  ' methods and subscriptions.',\n  // URL to the Git repository containing the source code for this package.\n  git: '',\n  // By default, Meteor will default to using README.md for documentation.\n  // To avoid submitting documentation, set this field to null.\n  documentation: 'README.md'\n});\n\nPackage.onUse(function(api) {\n  api.use('rate-limit', 'server');\n  api.export('DDPRateLimiter', 'server');\n  api.addFiles('ddp-rate-limiter.js', 'server');\n});\n\nPackage.onTest(function(api) {\n  api.use('underscore');\n  api.use(['accounts-password', 'tinytest', 'test-helpers', 'tracker',\n           'accounts-base', 'random', 'email', 'underscore', 'check',\n           'ddp', 'ecmascript', 'es5-shim']);\n  api.use('ddp-rate-limiter');\n\n  api.addFiles('ddp-rate-limiter-tests-common.js');\n  api.addFiles('ddp-rate-limiter-test-service.js', 'server');\n  api.addFiles('ddp-rate-limiter-tests.js', 'client');\n});\n"
  },
  {
    "path": "packages/ddp-server/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/ddp-server/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/ddp-server/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"permessage-deflate\": {\n      \"version\": \"0.1.5\",\n      \"resolved\": \"https://registry.npmjs.org/permessage-deflate/-/permessage-deflate-0.1.5.tgz\",\n      \"from\": \"https://registry.npmjs.org/permessage-deflate/-/permessage-deflate-0.1.5.tgz\"\n    },\n    \"sockjs\": {\n      \"version\": \"0.3.17\",\n      \"resolved\": \"https://registry.npmjs.org/sockjs/-/sockjs-0.3.17.tgz\",\n      \"from\": \"https://registry.npmjs.org/sockjs/-/sockjs-0.3.17.tgz\",\n      \"dependencies\": {\n        \"faye-websocket\": {\n          \"version\": \"0.10.0\",\n          \"resolved\": \"https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz\",\n          \"dependencies\": {\n            \"websocket-driver\": {\n              \"version\": \"0.6.5\",\n              \"resolved\": \"https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz\",\n              \"from\": \"https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz\",\n              \"dependencies\": {\n                \"websocket-extensions\": {\n                  \"version\": \"0.1.1\",\n                  \"resolved\": \"https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz\"\n                }\n              }\n            }\n          }\n        },\n        \"uuid\": {\n          \"version\": \"2.0.2\",\n          \"resolved\": \"https://registry.npmjs.org/uuid/-/uuid-2.0.2.tgz\",\n          \"from\": \"https://registry.npmjs.org/uuid/-/uuid-2.0.2.tgz\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/ddp-server/crossbar.js",
    "content": "// A \"crossbar\" is a class that provides structured notification registration.\n// See _match for the definition of how a notification matches a trigger.\n// All notifications and triggers must have a string key named 'collection'.\n\nDDPServer._Crossbar = function (options) {\n  var self = this;\n  options = options || {};\n\n  self.nextId = 1;\n  // map from collection name (string) -> listener id -> object. each object has\n  // keys 'trigger', 'callback'.  As a hack, the empty string means \"no\n  // collection\".\n  self.listenersByCollection = {};\n  self.factPackage = options.factPackage || \"livedata\";\n  self.factName = options.factName || null;\n};\n\n_.extend(DDPServer._Crossbar.prototype, {\n  // msg is a trigger or a notification\n  _collectionForMessage: function (msg) {\n    var self = this;\n    if (! _.has(msg, 'collection')) {\n      return '';\n    } else if (typeof(msg.collection) === 'string') {\n      if (msg.collection === '')\n        throw Error(\"Message has empty collection!\");\n      return msg.collection;\n    } else {\n      throw Error(\"Message has non-string collection!\");\n    }\n  },\n\n  // Listen for notification that match 'trigger'. A notification\n  // matches if it has the key-value pairs in trigger as a\n  // subset. When a notification matches, call 'callback', passing\n  // the actual notification.\n  //\n  // Returns a listen handle, which is an object with a method\n  // stop(). Call stop() to stop listening.\n  //\n  // XXX It should be legal to call fire() from inside a listen()\n  // callback?\n  listen: function (trigger, callback) {\n    var self = this;\n    var id = self.nextId++;\n\n    var collection = self._collectionForMessage(trigger);\n    var record = {trigger: EJSON.clone(trigger), callback: callback};\n    if (! _.has(self.listenersByCollection, collection)) {\n      self.listenersByCollection[collection] = {};\n    }\n    self.listenersByCollection[collection][id] = record;\n\n    if (self.factName && Package.facts) {\n      Package.facts.Facts.incrementServerFact(\n        self.factPackage, self.factName, 1);\n    }\n\n    return {\n      stop: function () {\n        if (self.factName && Package.facts) {\n          Package.facts.Facts.incrementServerFact(\n            self.factPackage, self.factName, -1);\n        }\n        delete self.listenersByCollection[collection][id];\n        if (_.isEmpty(self.listenersByCollection[collection])) {\n          delete self.listenersByCollection[collection];\n        }\n      }\n    };\n  },\n\n  // Fire the provided 'notification' (an object whose attribute\n  // values are all JSON-compatibile) -- inform all matching listeners\n  // (registered with listen()).\n  //\n  // If fire() is called inside a write fence, then each of the\n  // listener callbacks will be called inside the write fence as well.\n  //\n  // The listeners may be invoked in parallel, rather than serially.\n  fire: function (notification) {\n    var self = this;\n\n    var collection = self._collectionForMessage(notification);\n\n    if (! _.has(self.listenersByCollection, collection)) {\n      return;\n    }\n\n    var listenersForCollection = self.listenersByCollection[collection];\n    var callbackIds = [];\n    _.each(listenersForCollection, function (l, id) {\n      if (self._matches(notification, l.trigger)) {\n        callbackIds.push(id);\n      }\n    });\n\n    // Listener callbacks can yield, so we need to first find all the ones that\n    // match in a single iteration over self.listenersByCollection (which can't\n    // be mutated during this iteration), and then invoke the matching\n    // callbacks, checking before each call to ensure they haven't stopped.\n    // Note that we don't have to check that\n    // self.listenersByCollection[collection] still === listenersForCollection,\n    // because the only way that stops being true is if listenersForCollection\n    // first gets reduced down to the empty object (and then never gets\n    // increased again).\n    _.each(callbackIds, function (id) {\n      if (_.has(listenersForCollection, id)) {\n        listenersForCollection[id].callback(notification);\n      }\n    });\n  },\n\n  // A notification matches a trigger if all keys that exist in both are equal.\n  //\n  // Examples:\n  //  N:{collection: \"C\"} matches T:{collection: \"C\"}\n  //    (a non-targeted write to a collection matches a\n  //     non-targeted query)\n  //  N:{collection: \"C\", id: \"X\"} matches T:{collection: \"C\"}\n  //    (a targeted write to a collection matches a non-targeted query)\n  //  N:{collection: \"C\"} matches T:{collection: \"C\", id: \"X\"}\n  //    (a non-targeted write to a collection matches a\n  //     targeted query)\n  //  N:{collection: \"C\", id: \"X\"} matches T:{collection: \"C\", id: \"X\"}\n  //    (a targeted write to a collection matches a targeted query targeted\n  //     at the same document)\n  //  N:{collection: \"C\", id: \"X\"} does not match T:{collection: \"C\", id: \"Y\"}\n  //    (a targeted write to a collection does not match a targeted query\n  //     targeted at a different document)\n  _matches: function (notification, trigger) {\n    // Most notifications that use the crossbar have a string `collection` and\n    // maybe an `id` that is a string or ObjectID. We're already dividing up\n    // triggers by collection, but let's fast-track \"nope, different ID\" (and\n    // avoid the overly generic EJSON.equals). This makes a noticeable\n    // performance difference; see https://github.com/meteor/meteor/pull/3697\n    if (typeof(notification.id) === 'string' &&\n        typeof(trigger.id) === 'string' &&\n        notification.id !== trigger.id) {\n      return false;\n    }\n    if (notification.id instanceof MongoID.ObjectID &&\n        trigger.id instanceof MongoID.ObjectID &&\n        ! notification.id.equals(trigger.id)) {\n      return false;\n    }\n\n    return _.all(trigger, function (triggerValue, key) {\n      return !_.has(notification, key) ||\n        EJSON.equals(triggerValue, notification[key]);\n    });\n  }\n});\n\n// The \"invalidation crossbar\" is a specific instance used by the DDP server to\n// implement write fence notifications. Listener callbacks on this crossbar\n// should call beginWrite on the current write fence before they return, if they\n// want to delay the write fence from firing (ie, the DDP method-data-updated\n// message from being sent).\nDDPServer._InvalidationCrossbar = new DDPServer._Crossbar({\n  factName: \"invalidation-crossbar-listeners\"\n});\n"
  },
  {
    "path": "packages/ddp-server/crossbar_tests.js",
    "content": "// White box tests of invalidation crossbar matching function.\n// Note: the current crossbar match function is designed specifically\n// to ensure that a modification that targets a specific ID does not\n// notify a query that is watching a different specific ID. (And to\n// keep separate collections separate.) Other than that, there's no\n// deep meaning to the matching function, and it could be changed later\n// as long as it preserves that property.\nTinytest.add('livedata - crossbar', function (test) {\n  var crossbar = new DDPServer._Crossbar;\n  test.isTrue(crossbar._matches({collection: \"C\"},\n                                {collection: \"C\"}));\n  test.isTrue(crossbar._matches({collection: \"C\", id: \"X\"},\n                                {collection: \"C\"}));\n  test.isTrue(crossbar._matches({collection: \"C\"},\n                                {collection: \"C\", id: \"X\"}));\n  test.isTrue(crossbar._matches({collection: \"C\", id: \"X\"},\n                                {collection: \"C\"}));\n\n  test.isFalse(crossbar._matches({collection: \"C\", id: \"X\"},\n                                 {collection: \"C\", id: \"Y\"}));\n\n  // Test that stopped listens definitely don't fire.\n  var calledFirst = false;\n  var calledSecond = false;\n  var trigger = {collection: \"C\"};\n  var secondHandle;\n  crossbar.listen(trigger, function (notification) {\n    // This test assumes that listeners will be called in the order\n    // registered. It's not wrong for the crossbar to do something different,\n    // but the test won't be valid in that case, so make it fail so we notice.\n    calledFirst = true;\n    if (calledSecond) {\n      test.fail({\n        type: \"test_assumption_failed\",\n        message: \"test assumed that listeners would be called in the order registered\"\n      });\n    } else {\n      secondHandle.stop();\n    }\n  });\n  secondHandle = crossbar.listen(trigger, function (notification) {\n    // This should not get invoked, because it should be stopped by the other\n    // listener!\n    calledSecond = true;\n  });\n  crossbar.fire(trigger);\n  test.isTrue(calledFirst);\n  test.isFalse(calledSecond);\n});\n"
  },
  {
    "path": "packages/ddp-server/livedata_server.js",
    "content": "DDPServer = {};\n\nvar Fiber = Npm.require('fibers');\n\n// This file contains classes:\n// * Session - The server's connection to a single DDP client\n// * Subscription - A single subscription for a single client\n// * Server - An entire server that may talk to > 1 client. A DDP endpoint.\n//\n// Session and Subscription are file scope. For now, until we freeze\n// the interface, Server is package scope (in the future it should be\n// exported.)\n\n// Represents a single document in a SessionCollectionView\nvar SessionDocumentView = function () {\n  var self = this;\n  self.existsIn = {}; // set of subscriptionHandle\n  self.dataByKey = {}; // key-> [ {subscriptionHandle, value} by precedence]\n};\n\nDDPServer._SessionDocumentView = SessionDocumentView;\n\n\n_.extend(SessionDocumentView.prototype, {\n\n  getFields: function () {\n    var self = this;\n    var ret = {};\n    _.each(self.dataByKey, function (precedenceList, key) {\n      ret[key] = precedenceList[0].value;\n    });\n    return ret;\n  },\n\n  clearField: function (subscriptionHandle, key, changeCollector) {\n    var self = this;\n    // Publish API ignores _id if present in fields\n    if (key === \"_id\")\n      return;\n    var precedenceList = self.dataByKey[key];\n\n    // It's okay to clear fields that didn't exist. No need to throw\n    // an error.\n    if (!precedenceList)\n      return;\n\n    var removedValue = undefined;\n    for (var i = 0; i < precedenceList.length; i++) {\n      var precedence = precedenceList[i];\n      if (precedence.subscriptionHandle === subscriptionHandle) {\n        // The view's value can only change if this subscription is the one that\n        // used to have precedence.\n        if (i === 0)\n          removedValue = precedence.value;\n        precedenceList.splice(i, 1);\n        break;\n      }\n    }\n    if (_.isEmpty(precedenceList)) {\n      delete self.dataByKey[key];\n      changeCollector[key] = undefined;\n    } else if (removedValue !== undefined &&\n               !EJSON.equals(removedValue, precedenceList[0].value)) {\n      changeCollector[key] = precedenceList[0].value;\n    }\n  },\n\n  changeField: function (subscriptionHandle, key, value,\n                         changeCollector, isAdd) {\n    var self = this;\n    // Publish API ignores _id if present in fields\n    if (key === \"_id\")\n      return;\n\n    // Don't share state with the data passed in by the user.\n    value = EJSON.clone(value);\n\n    if (!_.has(self.dataByKey, key)) {\n      self.dataByKey[key] = [{subscriptionHandle: subscriptionHandle,\n                              value: value}];\n      changeCollector[key] = value;\n      return;\n    }\n    var precedenceList = self.dataByKey[key];\n    var elt;\n    if (!isAdd) {\n      elt = _.find(precedenceList, function (precedence) {\n        return precedence.subscriptionHandle === subscriptionHandle;\n      });\n    }\n\n    if (elt) {\n      if (elt === precedenceList[0] && !EJSON.equals(value, elt.value)) {\n        // this subscription is changing the value of this field.\n        changeCollector[key] = value;\n      }\n      elt.value = value;\n    } else {\n      // this subscription is newly caring about this field\n      precedenceList.push({subscriptionHandle: subscriptionHandle, value: value});\n    }\n\n  }\n});\n\n/**\n * Represents a client's view of a single collection\n * @param {String} collectionName Name of the collection it represents\n * @param {Object.<String, Function>} sessionCallbacks The callbacks for added, changed, removed\n * @class SessionCollectionView\n */\nvar SessionCollectionView = function (collectionName, sessionCallbacks) {\n  var self = this;\n  self.collectionName = collectionName;\n  self.documents = {};\n  self.callbacks = sessionCallbacks;\n};\n\nDDPServer._SessionCollectionView = SessionCollectionView;\n\n\n_.extend(SessionCollectionView.prototype, {\n\n  isEmpty: function () {\n    var self = this;\n    return _.isEmpty(self.documents);\n  },\n\n  diff: function (previous) {\n    var self = this;\n    DiffSequence.diffObjects(previous.documents, self.documents, {\n      both: _.bind(self.diffDocument, self),\n\n      rightOnly: function (id, nowDV) {\n        self.callbacks.added(self.collectionName, id, nowDV.getFields());\n      },\n\n      leftOnly: function (id, prevDV) {\n        self.callbacks.removed(self.collectionName, id);\n      }\n    });\n  },\n\n  diffDocument: function (id, prevDV, nowDV) {\n    var self = this;\n    var fields = {};\n    DiffSequence.diffObjects(prevDV.getFields(), nowDV.getFields(), {\n      both: function (key, prev, now) {\n        if (!EJSON.equals(prev, now))\n          fields[key] = now;\n      },\n      rightOnly: function (key, now) {\n        fields[key] = now;\n      },\n      leftOnly: function(key, prev) {\n        fields[key] = undefined;\n      }\n    });\n    self.callbacks.changed(self.collectionName, id, fields);\n  },\n\n  added: function (subscriptionHandle, id, fields) {\n    var self = this;\n    var docView = self.documents[id];\n    var added = false;\n    if (!docView) {\n      added = true;\n      docView = new SessionDocumentView();\n      self.documents[id] = docView;\n    }\n    docView.existsIn[subscriptionHandle] = true;\n    var changeCollector = {};\n    _.each(fields, function (value, key) {\n      docView.changeField(\n        subscriptionHandle, key, value, changeCollector, true);\n    });\n    if (added)\n      self.callbacks.added(self.collectionName, id, changeCollector);\n    else\n      self.callbacks.changed(self.collectionName, id, changeCollector);\n  },\n\n  changed: function (subscriptionHandle, id, changed) {\n    var self = this;\n    var changedResult = {};\n    var docView = self.documents[id];\n    if (!docView)\n      throw new Error(\"Could not find element with id \" + id + \" to change\");\n    _.each(changed, function (value, key) {\n      if (value === undefined)\n        docView.clearField(subscriptionHandle, key, changedResult);\n      else\n        docView.changeField(subscriptionHandle, key, value, changedResult);\n    });\n    self.callbacks.changed(self.collectionName, id, changedResult);\n  },\n\n  removed: function (subscriptionHandle, id) {\n    var self = this;\n    var docView = self.documents[id];\n    if (!docView) {\n      var err = new Error(\"Removed nonexistent document \" + id);\n      throw err;\n    }\n    delete docView.existsIn[subscriptionHandle];\n    if (_.isEmpty(docView.existsIn)) {\n      // it is gone from everyone\n      self.callbacks.removed(self.collectionName, id);\n      delete self.documents[id];\n    } else {\n      var changed = {};\n      // remove this subscription from every precedence list\n      // and record the changes\n      _.each(docView.dataByKey, function (precedenceList, key) {\n        docView.clearField(subscriptionHandle, key, changed);\n      });\n\n      self.callbacks.changed(self.collectionName, id, changed);\n    }\n  }\n});\n\n/******************************************************************************/\n/* Session                                                                    */\n/******************************************************************************/\n\nvar Session = function (server, version, socket, options) {\n  var self = this;\n  self.id = Random.id();\n\n  self.server = server;\n  self.version = version;\n\n  self.initialized = false;\n  self.socket = socket;\n\n  // set to null when the session is destroyed. multiple places below\n  // use this to determine if the session is alive or not.\n  self.inQueue = new Meteor._DoubleEndedQueue();\n\n  self.blocked = false;\n  self.workerRunning = false;\n\n  // Sub objects for active subscriptions\n  self._namedSubs = {};\n  self._universalSubs = [];\n\n  self.userId = null;\n\n  self.collectionViews = {};\n\n  // Set this to false to not send messages when collectionViews are\n  // modified. This is done when rerunning subs in _setUserId and those messages\n  // are calculated via a diff instead.\n  self._isSending = true;\n\n  // If this is true, don't start a newly-created universal publisher on this\n  // session. The session will take care of starting it when appropriate.\n  self._dontStartNewUniversalSubs = false;\n\n  // when we are rerunning subscriptions, any ready messages\n  // we want to buffer up for when we are done rerunning subscriptions\n  self._pendingReady = [];\n\n  // List of callbacks to call when this connection is closed.\n  self._closeCallbacks = [];\n\n\n  // XXX HACK: If a sockjs connection, save off the URL. This is\n  // temporary and will go away in the near future.\n  self._socketUrl = socket.url;\n\n  // Allow tests to disable responding to pings.\n  self._respondToPings = options.respondToPings;\n\n  // This object is the public interface to the session. In the public\n  // API, it is called the `connection` object.  Internally we call it\n  // a `connectionHandle` to avoid ambiguity.\n  self.connectionHandle = {\n    id: self.id,\n    close: function () {\n      self.close();\n    },\n    onClose: function (fn) {\n      var cb = Meteor.bindEnvironment(fn, \"connection onClose callback\");\n      if (self.inQueue) {\n        self._closeCallbacks.push(cb);\n      } else {\n        // if we're already closed, call the callback.\n        Meteor.defer(cb);\n      }\n    },\n    clientAddress: self._clientAddress(),\n    httpHeaders: self.socket.headers\n  };\n\n  self.send({ msg: 'connected', session: self.id });\n\n  // On initial connect, spin up all the universal publishers.\n  Fiber(function () {\n    self.startUniversalSubs();\n  }).run();\n\n  if (version !== 'pre1' && options.heartbeatInterval !== 0) {\n    self.heartbeat = new DDPCommon.Heartbeat({\n      heartbeatInterval: options.heartbeatInterval,\n      heartbeatTimeout: options.heartbeatTimeout,\n      onTimeout: function () {\n        self.close();\n      },\n      sendPing: function () {\n        self.send({msg: 'ping'});\n      }\n    });\n    self.heartbeat.start();\n  }\n\n  Package.facts && Package.facts.Facts.incrementServerFact(\n    \"livedata\", \"sessions\", 1);\n};\n\n_.extend(Session.prototype, {\n\n  sendReady: function (subscriptionIds) {\n    var self = this;\n    if (self._isSending)\n      self.send({msg: \"ready\", subs: subscriptionIds});\n    else {\n      _.each(subscriptionIds, function (subscriptionId) {\n        self._pendingReady.push(subscriptionId);\n      });\n    }\n  },\n\n  sendAdded: function (collectionName, id, fields) {\n    var self = this;\n    if (self._isSending)\n      self.send({msg: \"added\", collection: collectionName, id: id, fields: fields});\n  },\n\n  sendChanged: function (collectionName, id, fields) {\n    var self = this;\n    if (_.isEmpty(fields))\n      return;\n\n    if (self._isSending) {\n      self.send({\n        msg: \"changed\",\n        collection: collectionName,\n        id: id,\n        fields: fields\n      });\n    }\n  },\n\n  sendRemoved: function (collectionName, id) {\n    var self = this;\n    if (self._isSending)\n      self.send({msg: \"removed\", collection: collectionName, id: id});\n  },\n\n  getSendCallbacks: function () {\n    var self = this;\n    return {\n      added: _.bind(self.sendAdded, self),\n      changed: _.bind(self.sendChanged, self),\n      removed: _.bind(self.sendRemoved, self)\n    };\n  },\n\n  getCollectionView: function (collectionName) {\n    var self = this;\n    if (_.has(self.collectionViews, collectionName)) {\n      return self.collectionViews[collectionName];\n    }\n    var ret = new SessionCollectionView(collectionName,\n                                        self.getSendCallbacks());\n    self.collectionViews[collectionName] = ret;\n    return ret;\n  },\n\n  added: function (subscriptionHandle, collectionName, id, fields) {\n    var self = this;\n    var view = self.getCollectionView(collectionName);\n    view.added(subscriptionHandle, id, fields);\n  },\n\n  removed: function (subscriptionHandle, collectionName, id) {\n    var self = this;\n    var view = self.getCollectionView(collectionName);\n    view.removed(subscriptionHandle, id);\n    if (view.isEmpty()) {\n      delete self.collectionViews[collectionName];\n    }\n  },\n\n  changed: function (subscriptionHandle, collectionName, id, fields) {\n    var self = this;\n    var view = self.getCollectionView(collectionName);\n    view.changed(subscriptionHandle, id, fields);\n  },\n\n  startUniversalSubs: function () {\n    var self = this;\n    // Make a shallow copy of the set of universal handlers and start them. If\n    // additional universal publishers start while we're running them (due to\n    // yielding), they will run separately as part of Server.publish.\n    var handlers = _.clone(self.server.universal_publish_handlers);\n    _.each(handlers, function (handler) {\n      self._startSubscription(handler);\n    });\n  },\n\n  // Destroy this session and unregister it at the server.\n  close: function () {\n    var self = this;\n\n    // Destroy this session, even if it's not registered at the\n    // server. Stop all processing and tear everything down. If a socket\n    // was attached, close it.\n\n    // Already destroyed.\n    if (! self.inQueue)\n      return;\n\n    // Drop the merge box data immediately.\n    self.inQueue = null;\n    self.collectionViews = {};\n\n    if (self.heartbeat) {\n      self.heartbeat.stop();\n      self.heartbeat = null;\n    }\n\n    if (self.socket) {\n      self.socket.close();\n      self.socket._meteorSession = null;\n    }\n\n    Package.facts && Package.facts.Facts.incrementServerFact(\n      \"livedata\", \"sessions\", -1);\n\n    Meteor.defer(function () {\n      // stop callbacks can yield, so we defer this on close.\n      // sub._isDeactivated() detects that we set inQueue to null and\n      // treats it as semi-deactivated (it will ignore incoming callbacks, etc).\n      self._deactivateAllSubscriptions();\n\n      // Defer calling the close callbacks, so that the caller closing\n      // the session isn't waiting for all the callbacks to complete.\n      _.each(self._closeCallbacks, function (callback) {\n        callback();\n      });\n    });\n\n    // Unregister the session.\n    self.server._removeSession(self);\n  },\n\n  // Send a message (doing nothing if no socket is connected right now.)\n  // It should be a JSON object (it will be stringified.)\n  send: function (msg) {\n    var self = this;\n    if (self.socket) {\n      if (Meteor._printSentDDP)\n        Meteor._debug(\"Sent DDP\", DDPCommon.stringifyDDP(msg));\n      self.socket.send(DDPCommon.stringifyDDP(msg));\n    }\n  },\n\n  // Send a connection error.\n  sendError: function (reason, offendingMessage) {\n    var self = this;\n    var msg = {msg: 'error', reason: reason};\n    if (offendingMessage)\n      msg.offendingMessage = offendingMessage;\n    self.send(msg);\n  },\n\n  // Process 'msg' as an incoming message. (But as a guard against\n  // race conditions during reconnection, ignore the message if\n  // 'socket' is not the currently connected socket.)\n  //\n  // We run the messages from the client one at a time, in the order\n  // given by the client. The message handler is passed an idempotent\n  // function 'unblock' which it may call to allow other messages to\n  // begin running in parallel in another fiber (for example, a method\n  // that wants to yield.) Otherwise, it is automatically unblocked\n  // when it returns.\n  //\n  // Actually, we don't have to 'totally order' the messages in this\n  // way, but it's the easiest thing that's correct. (unsub needs to\n  // be ordered against sub, methods need to be ordered against each\n  // other.)\n  processMessage: function (msg_in) {\n    var self = this;\n    if (!self.inQueue) // we have been destroyed.\n      return;\n\n    // Respond to ping and pong messages immediately without queuing.\n    // If the negotiated DDP version is \"pre1\" which didn't support\n    // pings, preserve the \"pre1\" behavior of responding with a \"bad\n    // request\" for the unknown messages.\n    //\n    // Fibers are needed because heartbeat uses Meteor.setTimeout, which\n    // needs a Fiber. We could actually use regular setTimeout and avoid\n    // these new fibers, but it is easier to just make everything use\n    // Meteor.setTimeout and not think too hard.\n    //\n    // Any message counts as receiving a pong, as it demonstrates that\n    // the client is still alive.\n    if (self.heartbeat) {\n      Fiber(function () {\n        self.heartbeat.messageReceived();\n      }).run();\n    }\n\n    if (self.version !== 'pre1' && msg_in.msg === 'ping') {\n      if (self._respondToPings)\n        self.send({msg: \"pong\", id: msg_in.id});\n      return;\n    }\n    if (self.version !== 'pre1' && msg_in.msg === 'pong') {\n      // Since everything is a pong, nothing to do\n      return;\n    }\n\n    self.inQueue.push(msg_in);\n    if (self.workerRunning)\n      return;\n    self.workerRunning = true;\n\n    var processNext = function () {\n      var msg = self.inQueue && self.inQueue.shift();\n      if (!msg) {\n        self.workerRunning = false;\n        return;\n      }\n\n      Fiber(function () {\n        var blocked = true;\n\n        var unblock = function () {\n          if (!blocked)\n            return; // idempotent\n          blocked = false;\n          processNext();\n        };\n\n        if (_.has(self.protocol_handlers, msg.msg))\n          self.protocol_handlers[msg.msg].call(self, msg, unblock);\n        else\n          self.sendError('Bad request', msg);\n        unblock(); // in case the handler didn't already do it\n      }).run();\n    };\n\n    processNext();\n  },\n\n  protocol_handlers: {\n    sub: function (msg) {\n      var self = this;\n\n      // reject malformed messages\n      if (typeof (msg.id) !== \"string\" ||\n          typeof (msg.name) !== \"string\" ||\n          (('params' in msg) && !(msg.params instanceof Array))) {\n        self.sendError(\"Malformed subscription\", msg);\n        return;\n      }\n\n      if (!self.server.publish_handlers[msg.name]) {\n        self.send({\n          msg: 'nosub', id: msg.id,\n          error: new Meteor.Error(404, `Subscription '${msg.name}' not found`)});\n        return;\n      }\n\n      if (_.has(self._namedSubs, msg.id))\n        // subs are idempotent, or rather, they are ignored if a sub\n        // with that id already exists. this is important during\n        // reconnect.\n        return;\n\n      // XXX It'd be much better if we had generic hooks where any package can\n      // hook into subscription handling, but in the mean while we special case\n      // ddp-rate-limiter package. This is also done for weak requirements to\n      // add the ddp-rate-limiter package in case we don't have Accounts. A\n      // user trying to use the ddp-rate-limiter must explicitly require it.\n      if (Package['ddp-rate-limiter']) {\n        var DDPRateLimiter = Package['ddp-rate-limiter'].DDPRateLimiter;\n        var rateLimiterInput = {\n          userId: self.userId,\n          clientAddress: self.connectionHandle.clientAddress,\n          type: \"subscription\",\n          name: msg.name,\n          connectionId: self.id\n        };\n\n        DDPRateLimiter._increment(rateLimiterInput);\n        var rateLimitResult = DDPRateLimiter._check(rateLimiterInput);\n        if (!rateLimitResult.allowed) {\n          self.send({\n            msg: 'nosub', id: msg.id,\n            error: new Meteor.Error(\n              'too-many-requests',\n              DDPRateLimiter.getErrorMessage(rateLimitResult),\n              {timeToReset: rateLimitResult.timeToReset})\n          });\n          return;\n        }\n      }\n\n      var handler = self.server.publish_handlers[msg.name];\n\n      self._startSubscription(handler, msg.id, msg.params, msg.name);\n\n    },\n\n    unsub: function (msg) {\n      var self = this;\n\n      self._stopSubscription(msg.id);\n    },\n\n    method: function (msg, unblock) {\n      var self = this;\n\n      // reject malformed messages\n      // For now, we silently ignore unknown attributes,\n      // for forwards compatibility.\n      if (typeof (msg.id) !== \"string\" ||\n          typeof (msg.method) !== \"string\" ||\n          (('params' in msg) && !(msg.params instanceof Array)) ||\n          (('randomSeed' in msg) && (typeof msg.randomSeed !== \"string\"))) {\n        self.sendError(\"Malformed method invocation\", msg);\n        return;\n      }\n\n      var randomSeed = msg.randomSeed || null;\n\n      // set up to mark the method as satisfied once all observers\n      // (and subscriptions) have reacted to any writes that were\n      // done.\n      var fence = new DDPServer._WriteFence;\n      fence.onAllCommitted(function () {\n        // Retire the fence so that future writes are allowed.\n        // This means that callbacks like timers are free to use\n        // the fence, and if they fire before it's armed (for\n        // example, because the method waits for them) their\n        // writes will be included in the fence.\n        fence.retire();\n        self.send({\n          msg: 'updated', methods: [msg.id]});\n      });\n\n      // find the handler\n      var handler = self.server.method_handlers[msg.method];\n      if (!handler) {\n        self.send({\n          msg: 'result', id: msg.id,\n          error: new Meteor.Error(404, `Method '${msg.method}' not found`)});\n        fence.arm();\n        return;\n      }\n\n      var setUserId = function(userId) {\n        self._setUserId(userId);\n      };\n\n      var invocation = new DDPCommon.MethodInvocation({\n        isSimulation: false,\n        userId: self.userId,\n        setUserId: setUserId,\n        unblock: unblock,\n        connection: self.connectionHandle,\n        randomSeed: randomSeed\n      });\n\n      const promise = new Promise((resolve, reject) => {\n        // XXX It'd be better if we could hook into method handlers better but\n        // for now, we need to check if the ddp-rate-limiter exists since we\n        // have a weak requirement for the ddp-rate-limiter package to be added\n        // to our application.\n        if (Package['ddp-rate-limiter']) {\n          var DDPRateLimiter = Package['ddp-rate-limiter'].DDPRateLimiter;\n          var rateLimiterInput = {\n            userId: self.userId,\n            clientAddress: self.connectionHandle.clientAddress,\n            type: \"method\",\n            name: msg.method,\n            connectionId: self.id\n          };\n          DDPRateLimiter._increment(rateLimiterInput);\n          var rateLimitResult = DDPRateLimiter._check(rateLimiterInput)\n          if (!rateLimitResult.allowed) {\n            reject(new Meteor.Error(\n              \"too-many-requests\",\n              DDPRateLimiter.getErrorMessage(rateLimitResult),\n              {timeToReset: rateLimitResult.timeToReset}\n            ));\n            return;\n          }\n        }\n\n        resolve(DDPServer._CurrentWriteFence.withValue(\n          fence,\n          () => DDP._CurrentInvocation.withValue(\n            invocation,\n            () => maybeAuditArgumentChecks(\n              handler, invocation, msg.params,\n              \"call to '\" + msg.method + \"'\"\n            )\n          )\n        ));\n      });\n\n      function finish() {\n        fence.arm();\n        unblock();\n      }\n\n      const payload = {\n        msg: \"result\",\n        id: msg.id\n      };\n\n      promise.then((result) => {\n        finish();\n        if (result !== undefined) {\n          payload.result = result;\n        }\n        self.send(payload);\n      }, (exception) => {\n        finish();\n        payload.error = wrapInternalException(\n          exception,\n          `while invoking method '${msg.method}'`\n        );\n        self.send(payload);\n      });\n    }\n  },\n\n  _eachSub: function (f) {\n    var self = this;\n    _.each(self._namedSubs, f);\n    _.each(self._universalSubs, f);\n  },\n\n  _diffCollectionViews: function (beforeCVs) {\n    var self = this;\n    DiffSequence.diffObjects(beforeCVs, self.collectionViews, {\n      both: function (collectionName, leftValue, rightValue) {\n        rightValue.diff(leftValue);\n      },\n      rightOnly: function (collectionName, rightValue) {\n        _.each(rightValue.documents, function (docView, id) {\n          self.sendAdded(collectionName, id, docView.getFields());\n        });\n      },\n      leftOnly: function (collectionName, leftValue) {\n        _.each(leftValue.documents, function (doc, id) {\n          self.sendRemoved(collectionName, id);\n        });\n      }\n    });\n  },\n\n  // Sets the current user id in all appropriate contexts and reruns\n  // all subscriptions\n  _setUserId: function(userId) {\n    var self = this;\n\n    if (userId !== null && typeof userId !== \"string\")\n      throw new Error(\"setUserId must be called on string or null, not \" +\n                      typeof userId);\n\n    // Prevent newly-created universal subscriptions from being added to our\n    // session; they will be found below when we call startUniversalSubs.\n    //\n    // (We don't have to worry about named subscriptions, because we only add\n    // them when we process a 'sub' message. We are currently processing a\n    // 'method' message, and the method did not unblock, because it is illegal\n    // to call setUserId after unblock. Thus we cannot be concurrently adding a\n    // new named subscription.)\n    self._dontStartNewUniversalSubs = true;\n\n    // Prevent current subs from updating our collectionViews and call their\n    // stop callbacks. This may yield.\n    self._eachSub(function (sub) {\n      sub._deactivate();\n    });\n\n    // All subs should now be deactivated. Stop sending messages to the client,\n    // save the state of the published collections, reset to an empty view, and\n    // update the userId.\n    self._isSending = false;\n    var beforeCVs = self.collectionViews;\n    self.collectionViews = {};\n    self.userId = userId;\n\n    // Save the old named subs, and reset to having no subscriptions.\n    var oldNamedSubs = self._namedSubs;\n    self._namedSubs = {};\n    self._universalSubs = [];\n\n    _.each(oldNamedSubs, function (sub, subscriptionId) {\n      self._namedSubs[subscriptionId] = sub._recreate();\n      // nb: if the handler throws or calls this.error(), it will in fact\n      // immediately send its 'nosub'. This is OK, though.\n      self._namedSubs[subscriptionId]._runHandler();\n    });\n\n    // Allow newly-created universal subs to be started on our connection in\n    // parallel with the ones we're spinning up here, and spin up universal\n    // subs.\n    self._dontStartNewUniversalSubs = false;\n    self.startUniversalSubs();\n\n    // Start sending messages again, beginning with the diff from the previous\n    // state of the world to the current state. No yields are allowed during\n    // this diff, so that other changes cannot interleave.\n    Meteor._noYieldsAllowed(function () {\n      self._isSending = true;\n      self._diffCollectionViews(beforeCVs);\n      if (!_.isEmpty(self._pendingReady)) {\n        self.sendReady(self._pendingReady);\n        self._pendingReady = [];\n      }\n    });\n  },\n\n  _startSubscription: function (handler, subId, params, name) {\n    var self = this;\n\n    var sub = new Subscription(\n      self, handler, subId, params, name);\n    if (subId)\n      self._namedSubs[subId] = sub;\n    else\n      self._universalSubs.push(sub);\n\n    sub._runHandler();\n  },\n\n  // tear down specified subscription\n  _stopSubscription: function (subId, error) {\n    var self = this;\n\n    var subName = null;\n\n    if (subId && self._namedSubs[subId]) {\n      subName = self._namedSubs[subId]._name;\n      self._namedSubs[subId]._removeAllDocuments();\n      self._namedSubs[subId]._deactivate();\n      delete self._namedSubs[subId];\n    }\n\n    var response = {msg: 'nosub', id: subId};\n\n    if (error) {\n      response.error = wrapInternalException(\n        error,\n        subName ? (\"from sub \" + subName + \" id \" + subId)\n          : (\"from sub id \" + subId));\n    }\n\n    self.send(response);\n  },\n\n  // tear down all subscriptions. Note that this does NOT send removed or nosub\n  // messages, since we assume the client is gone.\n  _deactivateAllSubscriptions: function () {\n    var self = this;\n\n    _.each(self._namedSubs, function (sub, id) {\n      sub._deactivate();\n    });\n    self._namedSubs = {};\n\n    _.each(self._universalSubs, function (sub) {\n      sub._deactivate();\n    });\n    self._universalSubs = [];\n  },\n\n  // Determine the remote client's IP address, based on the\n  // HTTP_FORWARDED_COUNT environment variable representing how many\n  // proxies the server is behind.\n  _clientAddress: function () {\n    var self = this;\n\n    // For the reported client address for a connection to be correct,\n    // the developer must set the HTTP_FORWARDED_COUNT environment\n    // variable to an integer representing the number of hops they\n    // expect in the `x-forwarded-for` header. E.g., set to \"1\" if the\n    // server is behind one proxy.\n    //\n    // This could be computed once at startup instead of every time.\n    var httpForwardedCount = parseInt(process.env['HTTP_FORWARDED_COUNT']) || 0;\n\n    if (httpForwardedCount === 0)\n      return self.socket.remoteAddress;\n\n    var forwardedFor = self.socket.headers[\"x-forwarded-for\"];\n    if (! _.isString(forwardedFor))\n      return null;\n    forwardedFor = forwardedFor.trim().split(/\\s*,\\s*/);\n\n    // Typically the first value in the `x-forwarded-for` header is\n    // the original IP address of the client connecting to the first\n    // proxy.  However, the end user can easily spoof the header, in\n    // which case the first value(s) will be the fake IP address from\n    // the user pretending to be a proxy reporting the original IP\n    // address value.  By counting HTTP_FORWARDED_COUNT back from the\n    // end of the list, we ensure that we get the IP address being\n    // reported by *our* first proxy.\n\n    if (httpForwardedCount < 0 || httpForwardedCount > forwardedFor.length)\n      return null;\n\n    return forwardedFor[forwardedFor.length - httpForwardedCount];\n  }\n});\n\n/******************************************************************************/\n/* Subscription                                                               */\n/******************************************************************************/\n\n// ctor for a sub handle: the input to each publish function\n\n// Instance name is this because it's usually referred to as this inside a\n// publish\n/**\n * @summary The server's side of a subscription\n * @class Subscription\n * @instanceName this\n */\nvar Subscription = function (\n    session, handler, subscriptionId, params, name) {\n  var self = this;\n  self._session = session; // type is Session\n\n  /**\n   * @summary Access inside the publish function. The incoming [connection](#meteor_onconnection) for this subscription.\n   * @locus Server\n   * @name  connection\n   * @memberOf Subscription\n   * @instance\n   */\n  self.connection = session.connectionHandle; // public API object\n\n  self._handler = handler;\n\n  // my subscription ID (generated by client, undefined for universal subs).\n  self._subscriptionId = subscriptionId;\n  // undefined for universal subs\n  self._name = name;\n\n  self._params = params || [];\n\n  // Only named subscriptions have IDs, but we need some sort of string\n  // internally to keep track of all subscriptions inside\n  // SessionDocumentViews. We use this subscriptionHandle for that.\n  if (self._subscriptionId) {\n    self._subscriptionHandle = 'N' + self._subscriptionId;\n  } else {\n    self._subscriptionHandle = 'U' + Random.id();\n  }\n\n  // has _deactivate been called?\n  self._deactivated = false;\n\n  // stop callbacks to g/c this sub.  called w/ zero arguments.\n  self._stopCallbacks = [];\n\n  // the set of (collection, documentid) that this subscription has\n  // an opinion about\n  self._documents = {};\n\n  // remember if we are ready.\n  self._ready = false;\n\n  // Part of the public API: the user of this sub.\n\n  /**\n   * @summary Access inside the publish function. The id of the logged-in user, or `null` if no user is logged in.\n   * @locus Server\n   * @memberOf Subscription\n   * @name  userId\n   * @instance\n   */\n  self.userId = session.userId;\n\n  // For now, the id filter is going to default to\n  // the to/from DDP methods on MongoID, to\n  // specifically deal with mongo/minimongo ObjectIds.\n\n  // Later, you will be able to make this be \"raw\"\n  // if you want to publish a collection that you know\n  // just has strings for keys and no funny business, to\n  // a ddp consumer that isn't minimongo\n\n  self._idFilter = {\n    idStringify: MongoID.idStringify,\n    idParse: MongoID.idParse\n  };\n\n  Package.facts && Package.facts.Facts.incrementServerFact(\n    \"livedata\", \"subscriptions\", 1);\n};\n\n_.extend(Subscription.prototype, {\n  _runHandler: function () {\n    // XXX should we unblock() here? Either before running the publish\n    // function, or before running _publishCursor.\n    //\n    // Right now, each publish function blocks all future publishes and\n    // methods waiting on data from Mongo (or whatever else the function\n    // blocks on). This probably slows page load in common cases.\n\n    var self = this;\n    try {\n      var res = maybeAuditArgumentChecks(\n        self._handler, self, EJSON.clone(self._params),\n        // It's OK that this would look weird for universal subscriptions,\n        // because they have no arguments so there can never be an\n        // audit-argument-checks failure.\n        \"publisher '\" + self._name + \"'\");\n    } catch (e) {\n      self.error(e);\n      return;\n    }\n\n    // Did the handler call this.error or this.stop?\n    if (self._isDeactivated())\n      return;\n\n    self._publishHandlerResult(res);\n  },\n\n  _publishHandlerResult: function (res) {\n    // SPECIAL CASE: Instead of writing their own callbacks that invoke\n    // this.added/changed/ready/etc, the user can just return a collection\n    // cursor or array of cursors from the publish function; we call their\n    // _publishCursor method which starts observing the cursor and publishes the\n    // results. Note that _publishCursor does NOT call ready().\n    //\n    // XXX This uses an undocumented interface which only the Mongo cursor\n    // interface publishes. Should we make this interface public and encourage\n    // users to implement it themselves? Arguably, it's unnecessary; users can\n    // already write their own functions like\n    //   var publishMyReactiveThingy = function (name, handler) {\n    //     Meteor.publish(name, function () {\n    //       var reactiveThingy = handler();\n    //       reactiveThingy.publishMe();\n    //     });\n    //   };\n\n    var self = this;\n    var isCursor = function (c) {\n      return c && c._publishCursor;\n    };\n    if (isCursor(res)) {\n      try {\n        res._publishCursor(self);\n      } catch (e) {\n        self.error(e);\n        return;\n      }\n      // _publishCursor only returns after the initial added callbacks have run.\n      // mark subscription as ready.\n      self.ready();\n    } else if (_.isArray(res)) {\n      // check all the elements are cursors\n      if (! _.all(res, isCursor)) {\n        self.error(new Error(\"Publish function returned an array of non-Cursors\"));\n        return;\n      }\n      // find duplicate collection names\n      // XXX we should support overlapping cursors, but that would require the\n      // merge box to allow overlap within a subscription\n      var collectionNames = {};\n      for (var i = 0; i < res.length; ++i) {\n        var collectionName = res[i]._getCollectionName();\n        if (_.has(collectionNames, collectionName)) {\n          self.error(new Error(\n            \"Publish function returned multiple cursors for collection \" +\n              collectionName));\n          return;\n        }\n        collectionNames[collectionName] = true;\n      };\n\n      try {\n        _.each(res, function (cur) {\n          cur._publishCursor(self);\n        });\n      } catch (e) {\n        self.error(e);\n        return;\n      }\n      self.ready();\n    } else if (res) {\n      // truthy values other than cursors or arrays are probably a\n      // user mistake (possible returning a Mongo document via, say,\n      // `coll.findOne()`).\n      self.error(new Error(\"Publish function can only return a Cursor or \"\n                           + \"an array of Cursors\"));\n    }\n  },\n\n  // This calls all stop callbacks and prevents the handler from updating any\n  // SessionCollectionViews further. It's used when the user unsubscribes or\n  // disconnects, as well as during setUserId re-runs. It does *NOT* send\n  // removed messages for the published objects; if that is necessary, call\n  // _removeAllDocuments first.\n  _deactivate: function() {\n    var self = this;\n    if (self._deactivated)\n      return;\n    self._deactivated = true;\n    self._callStopCallbacks();\n    Package.facts && Package.facts.Facts.incrementServerFact(\n      \"livedata\", \"subscriptions\", -1);\n  },\n\n  _callStopCallbacks: function () {\n    var self = this;\n    // tell listeners, so they can clean up\n    var callbacks = self._stopCallbacks;\n    self._stopCallbacks = [];\n    _.each(callbacks, function (callback) {\n      callback();\n    });\n  },\n\n  // Send remove messages for every document.\n  _removeAllDocuments: function () {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      _.each(self._documents, function(collectionDocs, collectionName) {\n        // Iterate over _.keys instead of the dictionary itself, since we'll be\n        // mutating it.\n        _.each(_.keys(collectionDocs), function (strId) {\n          self.removed(collectionName, self._idFilter.idParse(strId));\n        });\n      });\n    });\n  },\n\n  // Returns a new Subscription for the same session with the same\n  // initial creation parameters. This isn't a clone: it doesn't have\n  // the same _documents cache, stopped state or callbacks; may have a\n  // different _subscriptionHandle, and gets its userId from the\n  // session, not from this object.\n  _recreate: function () {\n    var self = this;\n    return new Subscription(\n      self._session, self._handler, self._subscriptionId, self._params,\n      self._name);\n  },\n\n  /**\n   * @summary Call inside the publish function.  Stops this client's subscription, triggering a call on the client to the `onStop` callback passed to [`Meteor.subscribe`](#meteor_subscribe), if any. If `error` is not a [`Meteor.Error`](#meteor_error), it will be [sanitized](#meteor_error).\n   * @locus Server\n   * @param {Error} error The error to pass to the client.\n   * @instance\n   * @memberOf Subscription\n   */\n  error: function (error) {\n    var self = this;\n    if (self._isDeactivated())\n      return;\n    self._session._stopSubscription(self._subscriptionId, error);\n  },\n\n  // Note that while our DDP client will notice that you've called stop() on the\n  // server (and clean up its _subscriptions table) we don't actually provide a\n  // mechanism for an app to notice this (the subscribe onError callback only\n  // triggers if there is an error).\n\n  /**\n   * @summary Call inside the publish function.  Stops this client's subscription and invokes the client's `onStop` callback with no error.\n   * @locus Server\n   * @instance\n   * @memberOf Subscription\n   */\n  stop: function () {\n    var self = this;\n    if (self._isDeactivated())\n      return;\n    self._session._stopSubscription(self._subscriptionId);\n  },\n\n  /**\n   * @summary Call inside the publish function.  Registers a callback function to run when the subscription is stopped.\n   * @locus Server\n   * @memberOf Subscription\n   * @instance\n   * @param {Function} func The callback function\n   */\n  onStop: function (callback) {\n    var self = this;\n    if (self._isDeactivated())\n      callback();\n    else\n      self._stopCallbacks.push(callback);\n  },\n\n  // This returns true if the sub has been deactivated, *OR* if the session was\n  // destroyed but the deferred call to _deactivateAllSubscriptions hasn't\n  // happened yet.\n  _isDeactivated: function () {\n    var self = this;\n    return self._deactivated || self._session.inQueue === null;\n  },\n\n  /**\n   * @summary Call inside the publish function.  Informs the subscriber that a document has been added to the record set.\n   * @locus Server\n   * @memberOf Subscription\n   * @instance\n   * @param {String} collection The name of the collection that contains the new document.\n   * @param {String} id The new document's ID.\n   * @param {Object} fields The fields in the new document.  If `_id` is present it is ignored.\n   */\n  added: function (collectionName, id, fields) {\n    var self = this;\n    if (self._isDeactivated())\n      return;\n    id = self._idFilter.idStringify(id);\n    Meteor._ensure(self._documents, collectionName)[id] = true;\n    self._session.added(self._subscriptionHandle, collectionName, id, fields);\n  },\n\n  /**\n   * @summary Call inside the publish function.  Informs the subscriber that a document in the record set has been modified.\n   * @locus Server\n   * @memberOf Subscription\n   * @instance\n   * @param {String} collection The name of the collection that contains the changed document.\n   * @param {String} id The changed document's ID.\n   * @param {Object} fields The fields in the document that have changed, together with their new values.  If a field is not present in `fields` it was left unchanged; if it is present in `fields` and has a value of `undefined` it was removed from the document.  If `_id` is present it is ignored.\n   */\n  changed: function (collectionName, id, fields) {\n    var self = this;\n    if (self._isDeactivated())\n      return;\n    id = self._idFilter.idStringify(id);\n    self._session.changed(self._subscriptionHandle, collectionName, id, fields);\n  },\n\n  /**\n   * @summary Call inside the publish function.  Informs the subscriber that a document has been removed from the record set.\n   * @locus Server\n   * @memberOf Subscription\n   * @instance\n   * @param {String} collection The name of the collection that the document has been removed from.\n   * @param {String} id The ID of the document that has been removed.\n   */\n  removed: function (collectionName, id) {\n    var self = this;\n    if (self._isDeactivated())\n      return;\n    id = self._idFilter.idStringify(id);\n    // We don't bother to delete sets of things in a collection if the\n    // collection is empty.  It could break _removeAllDocuments.\n    delete self._documents[collectionName][id];\n    self._session.removed(self._subscriptionHandle, collectionName, id);\n  },\n\n  /**\n   * @summary Call inside the publish function.  Informs the subscriber that an initial, complete snapshot of the record set has been sent.  This will trigger a call on the client to the `onReady` callback passed to  [`Meteor.subscribe`](#meteor_subscribe), if any.\n   * @locus Server\n   * @memberOf Subscription\n   * @instance\n   */\n  ready: function () {\n    var self = this;\n    if (self._isDeactivated())\n      return;\n    if (!self._subscriptionId)\n      return;  // unnecessary but ignored for universal sub\n    if (!self._ready) {\n      self._session.sendReady([self._subscriptionId]);\n      self._ready = true;\n    }\n  }\n});\n\n/******************************************************************************/\n/* Server                                                                     */\n/******************************************************************************/\n\nServer = function (options) {\n  var self = this;\n\n  // The default heartbeat interval is 30 seconds on the server and 35\n  // seconds on the client.  Since the client doesn't need to send a\n  // ping as long as it is receiving pings, this means that pings\n  // normally go from the server to the client.\n  //\n  // Note: Troposphere depends on the ability to mutate\n  // Meteor.server.options.heartbeatTimeout! This is a hack, but it's life.\n  self.options = _.defaults(options || {}, {\n    heartbeatInterval: 15000,\n    heartbeatTimeout: 15000,\n    // For testing, allow responding to pings to be disabled.\n    respondToPings: true\n  });\n\n  // Map of callbacks to call when a new connection comes in to the\n  // server and completes DDP version negotiation. Use an object instead\n  // of an array so we can safely remove one from the list while\n  // iterating over it.\n  self.onConnectionHook = new Hook({\n    debugPrintExceptions: \"onConnection callback\"\n  });\n\n  self.publish_handlers = {};\n  self.universal_publish_handlers = [];\n\n  self.method_handlers = {};\n\n  self.sessions = {}; // map from id to session\n\n  self.stream_server = new StreamServer;\n\n  self.stream_server.register(function (socket) {\n    // socket implements the SockJSConnection interface\n    socket._meteorSession = null;\n\n    var sendError = function (reason, offendingMessage) {\n      var msg = {msg: 'error', reason: reason};\n      if (offendingMessage)\n        msg.offendingMessage = offendingMessage;\n      socket.send(DDPCommon.stringifyDDP(msg));\n    };\n\n    socket.on('data', function (raw_msg) {\n      if (Meteor._printReceivedDDP) {\n        Meteor._debug(\"Received DDP\", raw_msg);\n      }\n      try {\n        try {\n          var msg = DDPCommon.parseDDP(raw_msg);\n        } catch (err) {\n          sendError('Parse error');\n          return;\n        }\n        if (msg === null || !msg.msg) {\n          sendError('Bad request', msg);\n          return;\n        }\n\n        if (msg.msg === 'connect') {\n          if (socket._meteorSession) {\n            sendError(\"Already connected\", msg);\n            return;\n          }\n          Fiber(function () {\n            self._handleConnect(socket, msg);\n          }).run();\n          return;\n        }\n\n        if (!socket._meteorSession) {\n          sendError('Must connect first', msg);\n          return;\n        }\n        socket._meteorSession.processMessage(msg);\n      } catch (e) {\n        // XXX print stack nicely\n        Meteor._debug(\"Internal exception while processing message\", msg,\n                      e.message, e.stack);\n      }\n    });\n\n    socket.on('close', function () {\n      if (socket._meteorSession) {\n        Fiber(function () {\n          socket._meteorSession.close();\n        }).run();\n      }\n    });\n  });\n};\n\n_.extend(Server.prototype, {\n\n  /**\n   * @summary Register a callback to be called when a new DDP connection is made to the server.\n   * @locus Server\n   * @param {function} callback The function to call when a new DDP connection is established.\n   * @memberOf Meteor\n   * @importFromPackage meteor\n   */\n  onConnection: function (fn) {\n    var self = this;\n    return self.onConnectionHook.register(fn);\n  },\n\n  _handleConnect: function (socket, msg) {\n    var self = this;\n\n    // The connect message must specify a version and an array of supported\n    // versions, and it must claim to support what it is proposing.\n    if (!(typeof (msg.version) === 'string' &&\n          _.isArray(msg.support) &&\n          _.all(msg.support, _.isString) &&\n          _.contains(msg.support, msg.version))) {\n      socket.send(DDPCommon.stringifyDDP({msg: 'failed',\n                                version: DDPCommon.SUPPORTED_DDP_VERSIONS[0]}));\n      socket.close();\n      return;\n    }\n\n    // In the future, handle session resumption: something like:\n    //  socket._meteorSession = self.sessions[msg.session]\n    var version = calculateVersion(msg.support, DDPCommon.SUPPORTED_DDP_VERSIONS);\n\n    if (msg.version !== version) {\n      // The best version to use (according to the client's stated preferences)\n      // is not the one the client is trying to use. Inform them about the best\n      // version to use.\n      socket.send(DDPCommon.stringifyDDP({msg: 'failed', version: version}));\n      socket.close();\n      return;\n    }\n\n    // Yay, version matches! Create a new session.\n    // Note: Troposphere depends on the ability to mutate\n    // Meteor.server.options.heartbeatTimeout! This is a hack, but it's life.\n    socket._meteorSession = new Session(self, version, socket, self.options);\n    self.sessions[socket._meteorSession.id] = socket._meteorSession;\n    self.onConnectionHook.each(function (callback) {\n      if (socket._meteorSession)\n        callback(socket._meteorSession.connectionHandle);\n      return true;\n    });\n  },\n  /**\n   * Register a publish handler function.\n   *\n   * @param name {String} identifier for query\n   * @param handler {Function} publish handler\n   * @param options {Object}\n   *\n   * Server will call handler function on each new subscription,\n   * either when receiving DDP sub message for a named subscription, or on\n   * DDP connect for a universal subscription.\n   *\n   * If name is null, this will be a subscription that is\n   * automatically established and permanently on for all connected\n   * client, instead of a subscription that can be turned on and off\n   * with subscribe().\n   *\n   * options to contain:\n   *  - (mostly internal) is_auto: true if generated automatically\n   *    from an autopublish hook. this is for cosmetic purposes only\n   *    (it lets us determine whether to print a warning suggesting\n   *    that you turn off autopublish.)\n   */\n\n  /**\n   * @summary Publish a record set.\n   * @memberOf Meteor\n   * @importFromPackage meteor\n   * @locus Server\n   * @param {String} name Name of the record set.  If `null`, the set has no name, and the record set is automatically sent to all connected clients.\n   * @param {Function} func Function called on the server each time a client subscribes.  Inside the function, `this` is the publish handler object, described below.  If the client passed arguments to `subscribe`, the function is called with the same arguments.\n   */\n  publish: function (name, handler, options) {\n    var self = this;\n\n    options = options || {};\n\n    if (name && name in self.publish_handlers) {\n      Meteor._debug(\"Ignoring duplicate publish named '\" + name + \"'\");\n      return;\n    }\n\n    if (Package.autopublish && !options.is_auto) {\n      // They have autopublish on, yet they're trying to manually\n      // picking stuff to publish. They probably should turn off\n      // autopublish. (This check isn't perfect -- if you create a\n      // publish before you turn on autopublish, it won't catch\n      // it. But this will definitely handle the simple case where\n      // you've added the autopublish package to your app, and are\n      // calling publish from your app code.)\n      if (!self.warned_about_autopublish) {\n        self.warned_about_autopublish = true;\n        Meteor._debug(\n\"** You've set up some data subscriptions with Meteor.publish(), but\\n\" +\n\"** you still have autopublish turned on. Because autopublish is still\\n\" +\n\"** on, your Meteor.publish() calls won't have much effect. All data\\n\" +\n\"** will still be sent to all clients.\\n\" +\n\"**\\n\" +\n\"** Turn off autopublish by removing the autopublish package:\\n\" +\n\"**\\n\" +\n\"**   $ meteor remove autopublish\\n\" +\n\"**\\n\" +\n\"** .. and make sure you have Meteor.publish() and Meteor.subscribe() calls\\n\" +\n\"** for each collection that you want clients to see.\\n\");\n      }\n    }\n\n    if (name)\n      self.publish_handlers[name] = handler;\n    else {\n      self.universal_publish_handlers.push(handler);\n      // Spin up the new publisher on any existing session too. Run each\n      // session's subscription in a new Fiber, so that there's no change for\n      // self.sessions to change while we're running this loop.\n      _.each(self.sessions, function (session) {\n        if (!session._dontStartNewUniversalSubs) {\n          Fiber(function() {\n            session._startSubscription(handler);\n          }).run();\n        }\n      });\n    }\n  },\n\n  _removeSession: function (session) {\n    var self = this;\n    if (self.sessions[session.id]) {\n      delete self.sessions[session.id];\n    }\n  },\n\n  /**\n   * @summary Defines functions that can be invoked over the network by clients.\n   * @locus Anywhere\n   * @param {Object} methods Dictionary whose keys are method names and values are functions.\n   * @memberOf Meteor\n   * @importFromPackage meteor\n   */\n  methods: function (methods) {\n    var self = this;\n    _.each(methods, function (func, name) {\n      if (typeof func !== 'function')\n        throw new Error(\"Method '\" + name + \"' must be a function\");\n      if (self.method_handlers[name])\n        throw new Error(\"A method named '\" + name + \"' is already defined\");\n      self.method_handlers[name] = func;\n    });\n  },\n\n  call: function (name /*, arguments */) {\n    // if it's a function, the last argument is the result callback,\n    // not a parameter to the remote method.\n    var args = Array.prototype.slice.call(arguments, 1);\n    if (args.length && typeof args[args.length - 1] === \"function\")\n      var callback = args.pop();\n    return this.apply(name, args, callback);\n  },\n\n  // @param options {Optional Object}\n  // @param callback {Optional Function}\n  apply: function (name, args, options, callback) {\n    var self = this;\n\n    // We were passed 3 arguments. They may be either (name, args, options)\n    // or (name, args, callback)\n    if (!callback && typeof options === 'function') {\n      callback = options;\n      options = {};\n    }\n    options = options || {};\n\n    if (callback)\n      // It's not really necessary to do this, since we immediately\n      // run the callback in this fiber before returning, but we do it\n      // anyway for regularity.\n      // XXX improve error message (and how we report it)\n      callback = Meteor.bindEnvironment(\n        callback,\n        \"delivering result of invoking '\" + name + \"'\"\n      );\n\n    // Run the handler\n    var handler = self.method_handlers[name];\n    var exception;\n    if (!handler) {\n      exception = new Meteor.Error(404, `Method '${name}' not found`);\n    } else {\n      // If this is a method call from within another method, get the\n      // user state from the outer method, otherwise don't allow\n      // setUserId to be called\n      var userId = null;\n      var setUserId = function() {\n        throw new Error(\"Can't call setUserId on a server initiated method call\");\n      };\n      var connection = null;\n      var currentInvocation = DDP._CurrentInvocation.get();\n      if (currentInvocation) {\n        userId = currentInvocation.userId;\n        setUserId = function(userId) {\n          currentInvocation.setUserId(userId);\n        };\n        connection = currentInvocation.connection;\n      }\n\n      var invocation = new DDPCommon.MethodInvocation({\n        isSimulation: false,\n        userId: userId,\n        setUserId: setUserId,\n        connection: connection,\n        randomSeed: DDPCommon.makeRpcSeed(currentInvocation, name)\n      });\n      try {\n        var result = DDP._CurrentInvocation.withValue(invocation, function () {\n          return maybeAuditArgumentChecks(\n            handler, invocation, EJSON.clone(args), \"internal call to '\" +\n              name + \"'\");\n        });\n        result = EJSON.clone(result);\n      } catch (e) {\n        exception = e;\n      }\n    }\n\n    // Return the result in whichever way the caller asked for it. Note that we\n    // do NOT block on the write fence in an analogous way to how the client\n    // blocks on the relevant data being visible, so you are NOT guaranteed that\n    // cursor observe callbacks have fired when your callback is invoked. (We\n    // can change this if there's a real use case.)\n    if (callback) {\n      callback(exception, result);\n      return undefined;\n    }\n    if (exception)\n      throw exception;\n    return result;\n  },\n\n  _urlForSession: function (sessionId) {\n    var self = this;\n    var session = self.sessions[sessionId];\n    if (session)\n      return session._socketUrl;\n    else\n      return null;\n  }\n});\n\nvar calculateVersion = function (clientSupportedVersions,\n                                 serverSupportedVersions) {\n  var correctVersion = _.find(clientSupportedVersions, function (version) {\n    return _.contains(serverSupportedVersions, version);\n  });\n  if (!correctVersion) {\n    correctVersion = serverSupportedVersions[0];\n  }\n  return correctVersion;\n};\n\nDDPServer._calculateVersion = calculateVersion;\n\n\n// \"blind\" exceptions other than those that were deliberately thrown to signal\n// errors to the client\nvar wrapInternalException = function (exception, context) {\n  if (!exception || exception instanceof Meteor.Error)\n    return exception;\n\n  // tests can set the 'expected' flag on an exception so it won't go to the\n  // server log\n  if (!exception.expected) {\n    Meteor._debug(\"Exception \" + context, exception.stack);\n    if (exception.sanitizedError) {\n      Meteor._debug(\"Sanitized and reported to the client as:\", exception.sanitizedError.message);\n      Meteor._debug();\n    }\n  }\n\n  // Did the error contain more details that could have been useful if caught in\n  // server code (or if thrown from non-client-originated code), but also\n  // provided a \"sanitized\" version with more context than 500 Internal server\n  // error? Use that.\n  if (exception.sanitizedError) {\n    if (exception.sanitizedError instanceof Meteor.Error)\n      return exception.sanitizedError;\n    Meteor._debug(\"Exception \" + context + \" provides a sanitizedError that \" +\n                  \"is not a Meteor.Error; ignoring\");\n  }\n\n  return new Meteor.Error(500, \"Internal server error\");\n};\n\n\n// Audit argument checks, if the audit-argument-checks package exists (it is a\n// weak dependency of this package).\nvar maybeAuditArgumentChecks = function (f, context, args, description) {\n  args = args || [];\n  if (Package['audit-argument-checks']) {\n    return Match._failIfArgumentsAreNotAllChecked(\n      f, context, args, description);\n  }\n  return f.apply(context, args);\n};\n"
  },
  {
    "path": "packages/ddp-server/livedata_server_tests.js",
    "content": "var Fiber = Npm.require('fibers');\n\n\nTinytest.addAsync(\n  \"livedata server - connectionHandle.onClose()\",\n  function (test, onComplete) {\n    makeTestConnection(\n      test,\n      function (clientConn, serverConn) {\n        // On the server side, wait for the connection to be closed.\n        serverConn.onClose(function () {\n          test.isTrue(true);\n          // Add a new onClose after the connection is already\n          // closed. See that it fires.\n          serverConn.onClose(function () {\n            onComplete();\n          });\n        });\n        // Close the connection from the client.\n        clientConn.disconnect();\n      },\n      onComplete\n    );\n  }\n);\n\nTinytest.addAsync(\n  \"livedata server - connectionHandle.close()\",\n  function (test, onComplete) {\n    makeTestConnection(\n      test,\n      function (clientConn, serverConn) {\n        // Wait for the connection to be closed from the server side.\n        simplePoll(\n          function () {\n            return ! clientConn.status().connected;\n          },\n          onComplete,\n          function () {\n            test.fail(\"timeout waiting for the connection to be closed on the server side\");\n            onComplete();\n          }\n        );\n\n        // Close the connection from the server.\n        serverConn.close();\n      },\n      onComplete\n    );\n  }\n);\n\n\ntestAsyncMulti(\n  \"livedata server - onConnection doesn't get callback after stop.\",\n  [function (test, expect) {\n    var afterStop = false;\n    var expectStop1 = expect();\n    var stopHandle1 = Meteor.onConnection(function (conn) {\n      stopHandle2.stop();\n      stopHandle1.stop();\n      afterStop = true;\n      // yield to the event loop for a moment to see that no other calls\n      // to listener2 are called.\n      Meteor.setTimeout(expectStop1, 10);\n    });\n    var stopHandle2 = Meteor.onConnection(function (conn) {\n      test.isFalse(afterStop);\n    });\n\n    // trigger a connection\n    var expectConnection = expect();\n    makeTestConnection(\n      test,\n      function (clientConn, serverConn) {\n        // Close the connection from the client.\n        clientConn.disconnect();\n        expectConnection();\n      },\n      expectConnection\n    );\n  }]\n);\n\n\nMeteor.methods({\n  livedata_server_test_inner: function () {\n    return this.connection.id;\n  },\n\n  livedata_server_test_outer: function () {\n    return Meteor.call('livedata_server_test_inner');\n  }\n});\n\n\nTinytest.addAsync(\n  \"livedata server - connection in method invocation\",\n  function (test, onComplete) {\n    makeTestConnection(\n      test,\n      function (clientConn, serverConn) {\n        var res = clientConn.call('livedata_server_test_inner');\n        test.equal(res, serverConn.id);\n        clientConn.disconnect();\n        onComplete();\n      },\n      onComplete\n    );\n  }\n);\n\n\nTinytest.addAsync(\n  \"livedata server - connection in nested method invocation\",\n  function (test, onComplete) {\n    makeTestConnection(\n      test,\n      function (clientConn, serverConn) {\n        var res = clientConn.call('livedata_server_test_outer');\n        test.equal(res, serverConn.id);\n        clientConn.disconnect();\n        onComplete();\n      },\n      onComplete\n    );\n  }\n);\n\n\n// connectionId -> callback\nvar onSubscription = {};\n\nMeteor.publish(\"livedata_server_test_sub\", function (connectionId) {\n  var callback = onSubscription[connectionId];\n  if (callback)\n    callback(this);\n  this.stop();\n});\n\n\nTinytest.addAsync(\n  \"livedata server - connection in publish function\",\n  function (test, onComplete) {\n    makeTestConnection(\n      test,\n      function (clientConn, serverConn) {\n        onSubscription[serverConn.id] = function (subscription) {\n          delete onSubscription[serverConn.id];\n          test.equal(subscription.connection.id, serverConn.id);\n          clientConn.disconnect();\n          onComplete();\n        };\n        clientConn.subscribe(\"livedata_server_test_sub\", serverConn.id);\n      }\n    );\n  }\n);\n\nMeteor.methods({\n  testResolvedPromise(arg) {\n    const invocation1 = DDP._CurrentInvocation.get();\n    return new Promise.resolve(arg).then(result => {\n      const invocation2 = DDP._CurrentInvocation.get();\n      // This equality holds because Promise callbacks are bound to the\n      // dynamic environment where .then was called.\n      if (invocation1 !== invocation2) {\n        throw new Meteor.Error(\"invocation mismatch\");\n      }\n      return result + \" after waiting\";\n    });\n  },\n\n  testRejectedPromise(arg) {\n    return new Promise.resolve(arg).then(result => {\n      throw new Meteor.Error(result + \" raised Meteor.Error\");\n    });\n  }\n});\n\nTinytest.addAsync(\n  \"livedata server - waiting for Promise\",\n  (test, onComplete) => makeTestConnection(test, (clientConn, serverConn) => {\n    test.equal(\n      clientConn.call(\"testResolvedPromise\", \"clientConn.call\"),\n      \"clientConn.call after waiting\"\n    );\n\n    const clientCallPromise = new Promise(\n      (resolve, reject) => clientConn.call(\n        \"testResolvedPromise\",\n        \"clientConn.call with callback\",\n        (error, result) => error ? reject(error) : resolve(result)\n      )\n    );\n\n    const clientCallRejectedPromise = new Promise(resolve => {\n      clientConn.call(\n        \"testRejectedPromise\",\n        \"with callback\",\n        (error, result) => resolve(error.message)\n      );\n    });\n\n    Promise.all([\n      clientCallPromise,\n      clientCallRejectedPromise,\n    ]).then(results => test.equal(results, [\n      \"clientConn.call with callback after waiting\",\n      \"[with callback raised Meteor.Error]\",\n    ]), error => test.fail(error))\n      .then(onComplete);\n  })\n);\n"
  },
  {
    "path": "packages/ddp-server/package.js",
    "content": "Package.describe({\n  summary: \"Meteor's latency-compensated distributed data server\",\n  version: '1.2.8_1',\n  documentation: null\n});\n\nNpm.depends({\n  \"permessage-deflate\": \"0.1.5\",\n  sockjs: \"0.3.17\"\n});\n\nPackage.onUse(function (api) {\n  api.use(['check', 'random', 'ejson', 'underscore',\n           'retry', 'mongo-id', 'diff-sequence', 'ecmascript'],\n          'server');\n\n  // common functionality\n  api.use('ddp-common', 'server'); // heartbeat\n  api.use('ddp-rate-limiter', 'server', {weak: true});\n  // Transport\n  api.use('ddp-client', 'server');\n  api.imply('ddp-client');\n\n  api.use(['webapp', 'routepolicy'], 'server');\n\n  // Detect whether or not the user wants us to audit argument checks.\n  api.use(['audit-argument-checks'], 'server', {weak: true});\n\n  // Allow us to detect 'autopublish', so we can print a warning if the user\n  // runs Meteor.publish while it's loaded.\n  api.use('autopublish', 'server', {weak: true});\n\n  // If the facts package is loaded, publish some statistics.\n  api.use('facts', 'server', {weak: true});\n\n  api.use('callback-hook', 'server');\n\n  // we depend on LocalCollection._diffObjects, _applyChanges,\n  // _idParse, _idStringify.\n  api.use('minimongo', 'server');\n\n  api.export('DDPServer', 'server');\n\n  api.addFiles('stream_server.js', 'server');\n\n  api.addFiles('livedata_server.js', 'server');\n  api.addFiles('writefence.js', 'server');\n  api.addFiles('crossbar.js', 'server');\n\n  api.addFiles('server_convenience.js', 'server');\n});\n\n\n\nPackage.onTest(function (api) {\n  api.use('ecmascript', ['client', 'server']);\n  api.use('livedata', ['client', 'server']);\n  api.use('mongo', ['client', 'server']);\n  api.use('test-helpers', ['client', 'server']);\n  api.use(['underscore', 'tinytest', 'random', 'tracker', 'minimongo', 'reactive-var']);\n\n  api.addFiles('livedata_server_tests.js', 'server');\n  api.addFiles('session_view_tests.js', ['server']);\n  api.addFiles('crossbar_tests.js', ['server']);\n});\n"
  },
  {
    "path": "packages/ddp-server/server_convenience.js",
    "content": "if (process.env.DDP_DEFAULT_CONNECTION_URL) {\n  __meteor_runtime_config__.DDP_DEFAULT_CONNECTION_URL =\n    process.env.DDP_DEFAULT_CONNECTION_URL;\n}\n\nMeteor.server = new Server;\n\nMeteor.refresh = function (notification) {\n  DDPServer._InvalidationCrossbar.fire(notification);\n};\n\n// Proxy the public methods of Meteor.server so they can\n// be called directly on Meteor.\n_.each(['publish', 'methods', 'call', 'apply', 'onConnection'],\n       function (name) {\n         Meteor[name] = _.bind(Meteor.server[name], Meteor.server);\n       });\n\n// Meteor.server used to be called Meteor.default_server. Provide\n// backcompat as a courtesy even though it was never documented.\n// XXX COMPAT WITH 0.6.4\nMeteor.default_server = Meteor.server;\n"
  },
  {
    "path": "packages/ddp-server/session_view_tests.js",
    "content": "var newView = function(test) {\n  var results = [];\n  var view = new DDPServer._SessionCollectionView('test', {\n    added: function (collection, id, fields) {\n      results.push({fun: 'added', id: id, fields: fields});\n    },\n    changed: function (collection, id, changed) {\n      if (_.isEmpty(changed))\n        return;\n      results.push({fun: 'changed', id: id, changed: changed});\n    },\n    removed: function (collection, id) {\n      results.push({fun: 'removed', id: id});\n    }\n  });\n  var v = {\n    view: view,\n    results: results\n  };\n  _.each([\"added\", \"changed\", \"removed\"], function (it) {\n    v[it] = _.bind(view[it], view);\n  });\n  v.expectResult = function (result) {\n    test.equal(results.shift(), result);\n  };\n  v.expectNoResult = function () {\n    test.equal(results, []);\n  };\n  v.drain = function() {\n    var ret = results;\n    results = [];\n    return ret;\n  };\n  return v;\n};\n\nTinytest.add('livedata - sessionview - exists reveal', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\", \"A1\", {});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {}});\n  v.expectNoResult();\n\n  v.added(\"B\", \"A1\", {});\n  v.expectNoResult();\n\n  v.removed(\"A\", \"A1\");\n  v.expectNoResult();\n\n  v.removed(\"B\", \"A1\");\n  v.expectResult({fun: 'removed', id: \"A1\"});\n  v.expectNoResult();\n});\n\nTinytest.add('livedata - sessionview - added a second field in another sub', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\", \"A1\", {a: \"foo\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {a: \"foo\"}});\n  v.expectNoResult();\n\n  v.added(\"B\", \"A1\", {a: \"foo\", b: \"bar\"});\n  v.expectResult({fun: 'changed', 'id': \"A1\", changed: {b: \"bar\"}});\n\n  v.removed(\"A\", \"A1\");\n  v.expectNoResult();\n\n  v.removed(\"B\", \"A1\");\n  v.expectResult({fun: 'removed', id: \"A1\"});\n  v.expectNoResult();\n});\n\n\nTinytest.add('livedata - sessionview - field reveal', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\"}});\n  v.expectNoResult();\n\n  v.added(\"B\",  \"A1\", {foo: \"baz\"});\n  v.removed(\"A\", \"A1\");\n  v.expectResult({fun: 'changed', id: \"A1\", changed: {foo: \"baz\"}});\n  v.expectNoResult();\n  // Somewhere in here we must have changed foo to baz. Legal either on the\n  // added or on the removed, but only once.\n\n  v.removed(\"B\", \"A1\");\n  v.expectResult({fun: 'removed', id: \"A1\"});\n  v.expectNoResult();\n});\n\nTinytest.add('livedata - sessionview - field change', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\"}});\n  v.expectNoResult();\n\n  v.changed(\"A\", \"A1\", {foo: \"baz\"}, []);\n  v.expectResult({fun: 'changed', id: \"A1\", changed: {foo: \"baz\"}});\n  v.expectNoResult();\n\n  v.removed(\"A\", \"A1\");\n  v.expectResult({fun: 'removed', id: \"A1\"});\n  v.expectNoResult();\n});\n\nTinytest.add('livedata - sessionview - field clear', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\"}});\n  v.expectNoResult();\n\n  v.changed(\"A\", \"A1\", {foo: undefined});\n  v.expectResult({fun: 'changed', id: \"A1\", changed: {foo: undefined}});\n  v.expectNoResult();\n\n  v.removed(\"A\", \"A1\");\n  v.expectResult({fun: 'removed', id: \"A1\"});\n  v.expectNoResult();\n});\n\nTinytest.add('livedata - sessionview - change makes a new field', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\"}});\n  v.expectNoResult();\n\n  v.changed(\"A\", \"A1\", {baz:\"quux\"});\n  v.expectResult({fun: 'changed', id: \"A1\", changed: {baz: \"quux\"}});\n  v.expectNoResult();\n});\n\nTinytest.add('livedata - sessionview - add, remove, add', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\"}});\n  v.expectNoResult();\n\n  v.removed(\"A\", \"A1\");\n  v.expectResult({fun: 'removed', id: \"A1\"});\n  v.expectNoResult();\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\"}});\n  v.expectNoResult();\n\n});\n\nTinytest.add('livedata - sessionview - field clear reveal', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\"}});\n  v.expectNoResult();\n\n\n  v.added(\"B\",  \"A1\", {foo: \"baz\"});\n  v.changed(\"A\", \"A1\", {foo: undefined});\n  v.expectResult({fun: 'changed', id: \"A1\", changed: {foo: \"baz\"}});\n  v.expectNoResult();\n\n  v.removed(\"A\", \"A1\");\n  v.expectNoResult();\n  v.removed(\"B\", \"A1\");\n  v.expectResult({fun: 'removed', id: \"A1\"});\n  v.expectNoResult();\n});\n\nTinytest.add('livedata - sessionview - change to canonical value produces no change', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\"}});\n  v.expectNoResult();\n\n\n  v.added(\"B\",  \"A1\", {foo: \"baz\"});\n  var canon = \"bar\";\n  var maybeResults = v.drain();\n  if (!_.isEmpty(maybeResults)) {\n    // if something happened, it was a change message to baz.\n    // if nothing did, canon is still bar.\n    test.length(maybeResults, 1);\n    test.equal(maybeResults[0], {fun: 'changed', id: \"A1\", changed: {foo: \"baz\"}});\n    canon = \"baz\";\n  }\n  v.changed(\"B\", \"A1\", {foo: canon});\n  v.expectNoResult();\n\n  v.removed(\"A\", \"A1\");\n  v.expectNoResult();\n  v.removed(\"B\", \"A1\");\n  v.expectResult({fun: 'removed', id: \"A1\"});\n  v.expectNoResult();\n});\n\nTinytest.add('livedata - sessionview - new field of canonical value produces no change', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\"}});\n  v.expectNoResult();\n\n\n  v.added(\"B\",  \"A1\", {});\n\n  v.changed(\"B\", \"A1\", {foo: \"bar\"});\n  v.expectNoResult();\n\n  v.removed(\"A\", \"A1\");\n  v.expectNoResult();\n  v.removed(\"B\", \"A1\");\n  v.expectResult({fun: 'removed', id: \"A1\"});\n  v.expectNoResult();\n});\n\nTinytest.add('livedata - sessionview - clear all clears only once', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\"}});\n  v.expectNoResult();\n\n  v.added(\"B\",  \"A1\", {foo: \"bar\"});\n  v.added(\"C\",  \"A1\", {foo: \"bar\"});\n  v.changed(\"A\", \"A1\", {foo: undefined});\n  v.changed(\"B\", \"A1\", {foo: undefined});\n  v.changed(\"C\", \"A1\", {foo: undefined});\n  v.expectResult({fun: 'changed', id: \"A1\", changed: {foo: undefined}});\n  v.expectNoResult();\n\n  v.removed(\"A\", \"A1\");\n  v.expectNoResult();\n  v.removed(\"B\", \"A1\");\n  v.expectNoResult();\n});\n\nTinytest.add('livedata - sessionview - change all changes only once', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\"}});\n  v.expectNoResult();\n\n  v.added(\"B\",  \"A1\", {foo: \"bar\"});\n  v.added(\"C\",  \"A1\", {foo: \"bar\"});\n  v.changed(\"B\", \"A1\", {foo: \"baz\"});\n  v.changed(\"A\", \"A1\", {foo: \"baz\"});\n  v.changed(\"C\", \"A1\", {foo: \"baz\"});\n  v.expectResult({fun: 'changed', id: \"A1\", changed: {foo: \"baz\"}});\n  v.expectNoResult();\n\n  v.removed(\"A\", \"A1\");\n  v.expectNoResult();\n  v.removed(\"B\", \"A1\");\n  v.expectNoResult();\n});\n\nTinytest.add('livedata - sessionview - multiple operations at once in a change', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\", baz: \"quux\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\", baz: \"quux\"}});\n  v.expectNoResult();\n\n\n  v.added(\"B\",  \"A1\", {foo: \"baz\"});\n  v.changed(\"A\", \"A1\", {thing: \"stuff\", foo: undefined, baz: undefined});\n  v.expectResult({fun: 'changed', id: \"A1\", changed: {foo: \"baz\", thing: \"stuff\", baz: undefined}});\n  v.expectNoResult();\n\n  v.removed(\"A\", \"A1\");\n  v.expectResult({fun: 'changed', id: \"A1\", changed: {thing: undefined}});\n  v.expectNoResult();\n  v.removed(\"B\", \"A1\");\n  v.expectResult({fun: 'removed', id: \"A1\"});\n  v.expectNoResult();\n});\n\nTinytest.add('livedata - sessionview - more than one document', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\", baz: \"quux\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\", baz: \"quux\"}});\n  v.expectNoResult();\n\n\n  v.added(\"A\", \"A2\", {foo: \"baz\"});\n  v.expectResult({fun: 'added', id: \"A2\", fields: {foo: \"baz\"}});\n  v.changed(\"A\", \"A1\", {thing: \"stuff\", foo: undefined, baz: undefined});\n  v.expectResult({fun: 'changed', id: \"A1\", changed: {thing: \"stuff\", foo: undefined, baz: undefined}});\n  v.expectNoResult();\n\n  v.removed(\"A\", \"A1\");\n  v.expectResult({fun: 'removed', id: \"A1\"});\n  v.expectNoResult();\n  v.removed(\"A\", \"A2\");\n  v.expectResult({fun: 'removed', id: \"A2\"});\n  v.expectNoResult();\n\n});\n\nTinytest.add('livedata - sessionview - multiple docs removed', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\", baz: \"quux\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\", baz: \"quux\"}});\n  v.expectNoResult();\n\n\n  v.added(\"A\", \"A2\", {foo: \"baz\"});\n  v.expectResult({fun: 'added', id: \"A2\", fields: {foo: \"baz\"}});\n  v.expectNoResult();\n\n  v.removed(\"A\", \"A1\");\n  v.expectResult({fun: 'removed', id: \"A1\"});\n  v.removed(\"A\", \"A2\");\n  v.expectResult({fun: 'removed', id: \"A2\"});\n  v.expectNoResult();\n});\n\n\nTinytest.add('livedata - sessionview - complicated sequence', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\",  \"A1\", {foo: \"bar\", baz: \"quux\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: \"bar\", baz: \"quux\"}});\n  v.expectNoResult();\n\n  v.added(\"A\", \"A2\", {foo: \"eats\"});\n  v.expectResult({fun: 'added', id: \"A2\", fields: {foo: \"eats\"}});\n\n  v.added(\"B\",  \"A1\", {foo: \"baz\"});\n  v.changed(\"A\", \"A1\", {thing: \"stuff\", foo: undefined, baz: undefined});\n  v.expectResult({fun: 'changed', id: \"A1\", changed: {foo: \"baz\", thing: \"stuff\", baz: undefined}});\n  v.expectNoResult();\n\n  v.removed(\"A\", \"A1\");\n  v.removed(\"A\", \"A2\");\n  v.expectResult({fun: 'changed', id: \"A1\", changed: {thing: undefined}});\n  v.expectResult({fun: 'removed', id: \"A2\"});\n  v.expectNoResult();\n  v.removed(\"B\", \"A1\");\n  v.expectResult({fun: 'removed', id: \"A1\"});\n  v.expectNoResult();\n});\n\nTinytest.add('livedata - sessionview - added becomes changed', function (test) {\n  var v = newView(test);\n\n  v.added('A',  \"A1\", {foo: 'bar'});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {foo: 'bar'}});\n\n  v.added('B',  \"A1\", {hi: 'there'});\n  v.expectResult({fun: 'changed', id: 'A1', changed: {hi: 'there'}});\n\n  v.removed('A', 'A1');\n  v.expectResult({fun: 'changed', id: 'A1', changed: {foo: undefined}});\n\n  v.removed('B', 'A1');\n  v.expectResult({fun: 'removed', id: 'A1'});\n});\n\nTinytest.add('livedata - sessionview - weird key names', function (test) {\n  var v = newView(test);\n\n  v.added('A',  \"A1\", {});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {}});\n\n  v.changed('A',  \"A1\", {constructor: 'bla'});\n  v.expectResult({fun: 'changed', id: 'A1', changed: {constructor: 'bla'}});\n});\n\nTinytest.add('livedata - sessionview - clear undefined value', function (test) {\n  var v = newView(test);\n\n  v.added(\"A\", \"A1\", {field: \"value\"});\n  v.expectResult({fun: 'added', id: \"A1\", fields: {field: \"value\"}});\n  v.expectNoResult();\n\n  v.changed(\"A\", \"A1\", {field: undefined});\n  v.expectResult({fun: 'changed', id: 'A1', changed: {field: undefined}});\n  v.expectNoResult();\n\n  v.changed(\"A\", \"A1\", {field: undefined});\n  v.expectNoResult();\n\n});\n"
  },
  {
    "path": "packages/ddp-server/stream_server.js",
    "content": "var url = Npm.require('url');\n\n// By default, we use the permessage-deflate extension with default\n// configuration. If $SERVER_WEBSOCKET_COMPRESSION is set, then it must be valid\n// JSON. If it represents a falsey value, then we do not use permessage-deflate\n// at all; otherwise, the JSON value is used as an argument to deflate's\n// configure method; see\n// https://github.com/faye/permessage-deflate-node/blob/master/README.md\n//\n// (We do this in an _.once instead of at startup, because we don't want to\n// crash the tool during isopacket load if your JSON doesn't parse. This is only\n// a problem because the tool has to load the DDP server code just in order to\n// be a DDP client; see https://github.com/meteor/meteor/issues/3452 .)\nvar websocketExtensions = _.once(function () {\n  var extensions = [];\n\n  var websocketCompressionConfig = process.env.SERVER_WEBSOCKET_COMPRESSION\n        ? JSON.parse(process.env.SERVER_WEBSOCKET_COMPRESSION) : {};\n  if (websocketCompressionConfig) {\n    extensions.push(Npm.require('permessage-deflate').configure(\n      websocketCompressionConfig\n    ));\n  }\n\n  return extensions;\n});\n\nvar pathPrefix = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX ||  \"\";\n\nStreamServer = function () {\n  var self = this;\n  self.registration_callbacks = [];\n  self.open_sockets = [];\n\n  // Because we are installing directly onto WebApp.httpServer instead of using\n  // WebApp.app, we have to process the path prefix ourselves.\n  self.prefix = pathPrefix + '/sockjs';\n  RoutePolicy.declare(self.prefix + '/', 'network');\n\n  // set up sockjs\n  var sockjs = Npm.require('sockjs');\n  var serverOptions = {\n    prefix: self.prefix,\n    log: function() {},\n    // this is the default, but we code it explicitly because we depend\n    // on it in stream_client:HEARTBEAT_TIMEOUT\n    heartbeat_delay: 45000,\n    // The default disconnect_delay is 5 seconds, but if the server ends up CPU\n    // bound for that much time, SockJS might not notice that the user has\n    // reconnected because the timer (of disconnect_delay ms) can fire before\n    // SockJS processes the new connection. Eventually we'll fix this by not\n    // combining CPU-heavy processing with SockJS termination (eg a proxy which\n    // converts to Unix sockets) but for now, raise the delay.\n    disconnect_delay: 60 * 1000,\n    // Set the USE_JSESSIONID environment variable to enable setting the\n    // JSESSIONID cookie. This is useful for setting up proxies with\n    // session affinity.\n    jsessionid: !!process.env.USE_JSESSIONID\n  };\n\n  // If you know your server environment (eg, proxies) will prevent websockets\n  // from ever working, set $DISABLE_WEBSOCKETS and SockJS clients (ie,\n  // browsers) will not waste time attempting to use them.\n  // (Your server will still have a /websocket endpoint.)\n  if (process.env.DISABLE_WEBSOCKETS) {\n    serverOptions.websocket = false;\n  } else {\n    serverOptions.faye_server_options = {\n      extensions: websocketExtensions()\n    };\n  }\n\n  self.server = sockjs.createServer(serverOptions);\n\n  // Install the sockjs handlers, but we want to keep around our own particular\n  // request handler that adjusts idle timeouts while we have an outstanding\n  // request.  This compensates for the fact that sockjs removes all listeners\n  // for \"request\" to add its own.\n  WebApp.httpServer.removeListener(\n    'request', WebApp._timeoutAdjustmentRequestCallback);\n  self.server.installHandlers(WebApp.httpServer);\n  WebApp.httpServer.addListener(\n    'request', WebApp._timeoutAdjustmentRequestCallback);\n\n  // Support the /websocket endpoint\n  self._redirectWebsocketEndpoint();\n\n  self.server.on('connection', function (socket) {\n    socket.send = function (data) {\n      socket.write(data);\n    };\n    socket.on('close', function () {\n      self.open_sockets = _.without(self.open_sockets, socket);\n    });\n    self.open_sockets.push(socket);\n\n    // XXX COMPAT WITH 0.6.6. Send the old style welcome message, which\n    // will force old clients to reload. Remove this once we're not\n    // concerned about people upgrading from a pre-0.7.0 release. Also,\n    // remove the clause in the client that ignores the welcome message\n    // (livedata_connection.js)\n    socket.send(JSON.stringify({server_id: \"0\"}));\n\n    // call all our callbacks when we get a new socket. they will do the\n    // work of setting up handlers and such for specific messages.\n    _.each(self.registration_callbacks, function (callback) {\n      callback(socket);\n    });\n  });\n\n};\n\n_.extend(StreamServer.prototype, {\n  // call my callback when a new socket connects.\n  // also call it for all current connections.\n  register: function (callback) {\n    var self = this;\n    self.registration_callbacks.push(callback);\n    _.each(self.all_sockets(), function (socket) {\n      callback(socket);\n    });\n  },\n\n  // get a list of all sockets\n  all_sockets: function () {\n    var self = this;\n    return _.values(self.open_sockets);\n  },\n\n  // Redirect /websocket to /sockjs/websocket in order to not expose\n  // sockjs to clients that want to use raw websockets\n  _redirectWebsocketEndpoint: function() {\n    var self = this;\n    // Unfortunately we can't use a connect middleware here since\n    // sockjs installs itself prior to all existing listeners\n    // (meaning prior to any connect middlewares) so we need to take\n    // an approach similar to overshadowListeners in\n    // https://github.com/sockjs/sockjs-node/blob/cf820c55af6a9953e16558555a31decea554f70e/src/utils.coffee\n    _.each(['request', 'upgrade'], function(event) {\n      var httpServer = WebApp.httpServer;\n      var oldHttpServerListeners = httpServer.listeners(event).slice(0);\n      httpServer.removeAllListeners(event);\n\n      // request and upgrade have different arguments passed but\n      // we only care about the first one which is always request\n      var newListener = function(request /*, moreArguments */) {\n        // Store arguments for use within the closure below\n        var args = arguments;\n\n        // Rewrite /websocket and /websocket/ urls to /sockjs/websocket while\n        // preserving query string.\n        var parsedUrl = url.parse(request.url);\n        if (parsedUrl.pathname === pathPrefix + '/websocket' ||\n            parsedUrl.pathname === pathPrefix + '/websocket/') {\n          parsedUrl.pathname = self.prefix + '/websocket';\n          request.url = url.format(parsedUrl);\n        }\n        _.each(oldHttpServerListeners, function(oldListener) {\n          oldListener.apply(httpServer, args);\n        });\n      };\n      httpServer.addListener(event, newListener);\n    });\n  }\n});\n"
  },
  {
    "path": "packages/ddp-server/writefence.js",
    "content": "var path = Npm.require('path');\nvar Future = Npm.require(path.join('fibers', 'future'));\n\n// A write fence collects a group of writes, and provides a callback\n// when all of the writes are fully committed and propagated (all\n// observers have been notified of the write and acknowledged it.)\n//\nDDPServer._WriteFence = function () {\n  var self = this;\n\n  self.armed = false;\n  self.fired = false;\n  self.retired = false;\n  self.outstanding_writes = 0;\n  self.before_fire_callbacks = [];\n  self.completion_callbacks = [];\n};\n\n// The current write fence. When there is a current write fence, code\n// that writes to databases should register their writes with it using\n// beginWrite().\n//\nDDPServer._CurrentWriteFence = new Meteor.EnvironmentVariable;\n\n_.extend(DDPServer._WriteFence.prototype, {\n  // Start tracking a write, and return an object to represent it. The\n  // object has a single method, committed(). This method should be\n  // called when the write is fully committed and propagated. You can\n  // continue to add writes to the WriteFence up until it is triggered\n  // (calls its callbacks because all writes have committed.)\n  beginWrite: function () {\n    var self = this;\n\n    if (self.retired)\n      return { committed: function () {} };\n\n    if (self.fired)\n      throw new Error(\"fence has already activated -- too late to add writes\");\n\n    self.outstanding_writes++;\n    var committed = false;\n    return {\n      committed: function () {\n        if (committed)\n          throw new Error(\"committed called twice on the same write\");\n        committed = true;\n        self.outstanding_writes--;\n        self._maybeFire();\n      }\n    };\n  },\n\n  // Arm the fence. Once the fence is armed, and there are no more\n  // uncommitted writes, it will activate.\n  arm: function () {\n    var self = this;\n    if (self === DDPServer._CurrentWriteFence.get())\n      throw Error(\"Can't arm the current fence\");\n    self.armed = true;\n    self._maybeFire();\n  },\n\n  // Register a function to be called once before firing the fence.\n  // Callback function can add new writes to the fence, in which case\n  // it won't fire until those writes are done as well.\n  onBeforeFire: function (func) {\n    var self = this;\n    if (self.fired)\n      throw new Error(\"fence has already activated -- too late to \" +\n                      \"add a callback\");\n    self.before_fire_callbacks.push(func);\n  },\n\n  // Register a function to be called when the fence fires.\n  onAllCommitted: function (func) {\n    var self = this;\n    if (self.fired)\n      throw new Error(\"fence has already activated -- too late to \" +\n                      \"add a callback\");\n    self.completion_callbacks.push(func);\n  },\n\n  // Convenience function. Arms the fence, then blocks until it fires.\n  armAndWait: function () {\n    var self = this;\n    var future = new Future;\n    self.onAllCommitted(function () {\n      future['return']();\n    });\n    self.arm();\n    future.wait();\n  },\n\n  _maybeFire: function () {\n    var self = this;\n    if (self.fired)\n      throw new Error(\"write fence already activated?\");\n    if (self.armed && !self.outstanding_writes) {\n      function invokeCallback (func) {\n        try {\n          func(self);\n        } catch (err) {\n          Meteor._debug(\"exception in write fence callback:\", err);\n        }\n      }\n\n      self.outstanding_writes++;\n      while (self.before_fire_callbacks.length > 0) {\n        var callbacks = self.before_fire_callbacks;\n        self.before_fire_callbacks = [];\n        _.each(callbacks, invokeCallback);\n      }\n      self.outstanding_writes--;\n\n      if (!self.outstanding_writes) {\n        self.fired = true;\n        var callbacks = self.completion_callbacks;\n        self.completion_callbacks = [];\n        _.each(callbacks, invokeCallback);\n      }\n    }\n  },\n\n  // Deactivate this fence so that adding more writes has no effect.\n  // The fence must have already fired.\n  retire: function () {\n    var self = this;\n    if (! self.fired)\n      throw new Error(\"Can't retire a fence that hasn't fired.\");\n    self.retired = true;\n  }\n});\n"
  },
  {
    "path": "packages/deprecated/README",
    "content": "These packages are no longer actively maintained by MDG.  Seek\ncommunity alternatives instead.\n\nNote that these packages still exist in atmosphere, and you can still\nbuild a package that depends on one of them by specifying an explicit\npackage version.\n"
  },
  {
    "path": "packages/deprecated/amplify/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/deprecated/amplify/amplify.js",
    "content": "/*!\n * Amplify 1.1.2\n *\n * Copyright 2011 - 2013 appendTo LLC. (http://appendto.com/team)\n * Dual licensed under the MIT or GPL licenses.\n * http://appendto.com/open-source-licenses\n *\n * http://amplifyjs.com\n */\n(function( global, undefined ) {\n\nvar slice = [].slice,\n\tsubscriptions = {};\n\nvar amplify = global.amplify = {\n\tpublish: function( topic ) {\n\t\tif ( typeof topic !== \"string\" ) {\n\t\t\tthrow new Error( \"You must provide a valid topic to publish.\" );\n\t\t}\n\n\t\tvar args = slice.call( arguments, 1 ),\n\t\t\ttopicSubscriptions,\n\t\t\tsubscription,\n\t\t\tlength,\n\t\t\ti = 0,\n\t\t\tret;\n\n\t\tif ( !subscriptions[ topic ] ) {\n\t\t\treturn true;\n\t\t}\n\n\t\ttopicSubscriptions = subscriptions[ topic ].slice();\n\t\tfor ( length = topicSubscriptions.length; i < length; i++ ) {\n\t\t\tsubscription = topicSubscriptions[ i ];\n\t\t\tret = subscription.callback.apply( subscription.context, args );\n\t\t\tif ( ret === false ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn ret !== false;\n\t},\n\n\tsubscribe: function( topic, context, callback, priority ) {\n\t\tif ( typeof topic !== \"string\" ) {\n\t\t\tthrow new Error( \"You must provide a valid topic to create a subscription.\" );\n\t\t}\n\n\t\tif ( arguments.length === 3 && typeof callback === \"number\" ) {\n\t\t\tpriority = callback;\n\t\t\tcallback = context;\n\t\t\tcontext = null;\n\t\t}\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = context;\n\t\t\tcontext = null;\n\t\t}\n\t\tpriority = priority || 10;\n\n\t\tvar topicIndex = 0,\n\t\t\ttopics = topic.split( /\\s/ ),\n\t\t\ttopicLength = topics.length,\n\t\t\tadded;\n\t\tfor ( ; topicIndex < topicLength; topicIndex++ ) {\n\t\t\ttopic = topics[ topicIndex ];\n\t\t\tadded = false;\n\t\t\tif ( !subscriptions[ topic ] ) {\n\t\t\t\tsubscriptions[ topic ] = [];\n\t\t\t}\n\n\t\t\tvar i = subscriptions[ topic ].length - 1,\n\t\t\t\tsubscriptionInfo = {\n\t\t\t\t\tcallback: callback,\n\t\t\t\t\tcontext: context,\n\t\t\t\t\tpriority: priority\n\t\t\t\t};\n\n\t\t\tfor ( ; i >= 0; i-- ) {\n\t\t\t\tif ( subscriptions[ topic ][ i ].priority <= priority ) {\n\t\t\t\t\tsubscriptions[ topic ].splice( i + 1, 0, subscriptionInfo );\n\t\t\t\t\tadded = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !added ) {\n\t\t\t\tsubscriptions[ topic ].unshift( subscriptionInfo );\n\t\t\t}\n\t\t}\n\n\t\treturn callback;\n\t},\n\n\tunsubscribe: function( topic, context, callback ) {\n\t\tif ( typeof topic !== \"string\" ) {\n\t\t\tthrow new Error( \"You must provide a valid topic to remove a subscription.\" );\n\t\t}\n\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = context;\n\t\t\tcontext = null;\n\t\t}\n\n\t\tif ( !subscriptions[ topic ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar length = subscriptions[ topic ].length,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tif ( subscriptions[ topic ][ i ].callback === callback ) {\n\t\t\t\tif ( !context || subscriptions[ topic ][ i ].context === context ) {\n\t\t\t\t\tsubscriptions[ topic ].splice( i, 1 );\n\t\t\t\t\t\n\t\t\t\t\t// Adjust counter and length for removed item\n\t\t\t\t\ti--;\n\t\t\t\t\tlength--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\n}( this ) );\n\n(function( amplify, undefined ) {\n\nvar store = amplify.store = function( key, value, options ) {\n\tvar type = store.type;\n\tif ( options && options.type && options.type in store.types ) {\n\t\ttype = options.type;\n\t}\n\treturn store.types[ type ]( key, value, options || {} );\n};\n\nstore.types = {};\nstore.type = null;\nstore.addType = function( type, storage ) {\n\tif ( !store.type ) {\n\t\tstore.type = type;\n\t}\n\n\tstore.types[ type ] = storage;\n\tstore[ type ] = function( key, value, options ) {\n\t\toptions = options || {};\n\t\toptions.type = type;\n\t\treturn store( key, value, options );\n\t};\n};\nstore.error = function() {\n\treturn \"amplify.store quota exceeded\";\n};\n\nvar rprefix = /^__amplify__/;\nfunction createFromStorageInterface( storageType, storage ) {\n\tstore.addType( storageType, function( key, value, options ) {\n\t\tvar storedValue, parsed, i, remove,\n\t\t\tret = value,\n\t\t\tnow = (new Date()).getTime();\n\n\t\tif ( !key ) {\n\t\t\tret = {};\n\t\t\tremove = [];\n\t\t\ti = 0;\n\t\t\ttry {\n\t\t\t\t// accessing the length property works around a localStorage bug\n\t\t\t\t// in Firefox 4.0 where the keys don't update cross-page\n\t\t\t\t// we assign to key just to avoid Closure Compiler from removing\n\t\t\t\t// the access as \"useless code\"\n\t\t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=662511\n\t\t\t\tkey = storage.length;\n\n\t\t\t\twhile ( key = storage.key( i++ ) ) {\n\t\t\t\t\tif ( rprefix.test( key ) ) {\n\t\t\t\t\t\tparsed = JSON.parse( storage.getItem( key ) );\n\t\t\t\t\t\tif ( parsed.expires && parsed.expires <= now ) {\n\t\t\t\t\t\t\tremove.push( key );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tret[ key.replace( rprefix, \"\" ) ] = parsed.data;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\twhile ( key = remove.pop() ) {\n\t\t\t\t\tstorage.removeItem( key );\n\t\t\t\t}\n\t\t\t} catch ( error ) {}\n\t\t\treturn ret;\n\t\t}\n\n\t\t// protect against name collisions with direct storage\n\t\tkey = \"__amplify__\" + key;\n\n\t\tif ( value === undefined ) {\n\t\t\tstoredValue = storage.getItem( key );\n\t\t\tparsed = storedValue ? JSON.parse( storedValue ) : { expires: -1 };\n\t\t\tif ( parsed.expires && parsed.expires <= now ) {\n\t\t\t\tstorage.removeItem( key );\n\t\t\t} else {\n\t\t\t\treturn parsed.data;\n\t\t\t}\n\t\t} else {\n\t\t\tif ( value === null ) {\n\t\t\t\tstorage.removeItem( key );\n\t\t\t} else {\n\t\t\t\tparsed = JSON.stringify({\n\t\t\t\t\tdata: value,\n\t\t\t\t\texpires: options.expires ? now + options.expires : null\n\t\t\t\t});\n\t\t\t\ttry {\n\t\t\t\t\tstorage.setItem( key, parsed );\n\t\t\t\t// quota exceeded\n\t\t\t\t} catch( error ) {\n\t\t\t\t\t// expire old data and try again\n\t\t\t\t\tstore[ storageType ]();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tstorage.setItem( key, parsed );\n\t\t\t\t\t} catch( error ) {\n\t\t\t\t\t\tthrow store.error();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t});\n}\n\n// localStorage + sessionStorage\n// IE 8+, Firefox 3.5+, Safari 4+, Chrome 4+, Opera 10.5+, iPhone 2+, Android 2+\nfor ( var webStorageType in { localStorage: 1, sessionStorage: 1 } ) {\n\t// try/catch for file protocol in Firefox and Private Browsing in Safari 5\n\ttry {\n\t\t// Safari 5 in Private Browsing mode exposes localStorage\n\t\t// but doesn't allow storing data, so we attempt to store and remove an item.\n\t\t// This will unfortunately give us a false negative if we're at the limit.\n\t\twindow[ webStorageType ].setItem( \"__amplify__\", \"x\" );\n\t\twindow[ webStorageType ].removeItem( \"__amplify__\" );\n\t\tcreateFromStorageInterface( webStorageType, window[ webStorageType ] );\n\t} catch( e ) {}\n}\n\n// globalStorage\n// non-standard: Firefox 2+\n// https://developer.mozilla.org/en/dom/storage#globalStorage\nif ( !store.types.localStorage && window.globalStorage ) {\n\t// try/catch for file protocol in Firefox\n\ttry {\n\t\tcreateFromStorageInterface( \"globalStorage\",\n\t\t\twindow.globalStorage[ window.location.hostname ] );\n\t\t// Firefox 2.0 and 3.0 have sessionStorage and globalStorage\n\t\t// make sure we default to globalStorage\n\t\t// but don't default to globalStorage in 3.5+ which also has localStorage\n\t\tif ( store.type === \"sessionStorage\" ) {\n\t\t\tstore.type = \"globalStorage\";\n\t\t}\n\t} catch( e ) {}\n}\n\n// userData\n// non-standard: IE 5+\n// http://msdn.microsoft.com/en-us/library/ms531424(v=vs.85).aspx\n(function() {\n\t// IE 9 has quirks in userData that are a huge pain\n\t// rather than finding a way to detect these quirks\n\t// we just don't register userData if we have localStorage\n\tif ( store.types.localStorage ) {\n\t\treturn;\n\t}\n\n\t// append to html instead of body so we can do this from the head\n\tvar div = document.createElement( \"div\" ),\n\t\tattrKey = \"amplify\";\n\tdiv.style.display = \"none\";\n\tdocument.getElementsByTagName( \"head\" )[ 0 ].appendChild( div );\n\n\t// we can't feature detect userData support\n\t// so just try and see if it fails\n\t// surprisingly, even just adding the behavior isn't enough for a failure\n\t// so we need to load the data as well\n\ttry {\n\t\tdiv.addBehavior( \"#default#userdata\" );\n\t\tdiv.load( attrKey );\n\t} catch( e ) {\n\t\tdiv.parentNode.removeChild( div );\n\t\treturn;\n\t}\n\n\tstore.addType( \"userData\", function( key, value, options ) {\n\t\tdiv.load( attrKey );\n\t\tvar attr, parsed, prevValue, i, remove,\n\t\t\tret = value,\n\t\t\tnow = (new Date()).getTime();\n\n\t\tif ( !key ) {\n\t\t\tret = {};\n\t\t\tremove = [];\n\t\t\ti = 0;\n\t\t\twhile ( attr = div.XMLDocument.documentElement.attributes[ i++ ] ) {\n\t\t\t\tparsed = JSON.parse( attr.value );\n\t\t\t\tif ( parsed.expires && parsed.expires <= now ) {\n\t\t\t\t\tremove.push( attr.name );\n\t\t\t\t} else {\n\t\t\t\t\tret[ attr.name ] = parsed.data;\n\t\t\t\t}\n\t\t\t}\n\t\t\twhile ( key = remove.pop() ) {\n\t\t\t\tdiv.removeAttribute( key );\n\t\t\t}\n\t\t\tdiv.save( attrKey );\n\t\t\treturn ret;\n\t\t}\n\n\t\t// convert invalid characters to dashes\n\t\t// http://www.w3.org/TR/REC-xml/#NT-Name\n\t\t// simplified to assume the starting character is valid\n\t\t// also removed colon as it is invalid in HTML attribute names\n\t\tkey = key.replace( /[^\\-._0-9A-Za-z\\xb7\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\u037d\\u037f-\\u1fff\\u200c-\\u200d\\u203f\\u2040\\u2070-\\u218f]/g, \"-\" );\n\t\t// adjust invalid starting character to deal with our simplified sanitization\n\t\tkey = key.replace( /^-/, \"_-\" );\n\n\t\tif ( value === undefined ) {\n\t\t\tattr = div.getAttribute( key );\n\t\t\tparsed = attr ? JSON.parse( attr ) : { expires: -1 };\n\t\t\tif ( parsed.expires && parsed.expires <= now ) {\n\t\t\t\tdiv.removeAttribute( key );\n\t\t\t} else {\n\t\t\t\treturn parsed.data;\n\t\t\t}\n\t\t} else {\n\t\t\tif ( value === null ) {\n\t\t\t\tdiv.removeAttribute( key );\n\t\t\t} else {\n\t\t\t\t// we need to get the previous value in case we need to rollback\n\t\t\t\tprevValue = div.getAttribute( key );\n\t\t\t\tparsed = JSON.stringify({\n\t\t\t\t\tdata: value,\n\t\t\t\t\texpires: (options.expires ? (now + options.expires) : null)\n\t\t\t\t});\n\t\t\t\tdiv.setAttribute( key, parsed );\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tdiv.save( attrKey );\n\t\t// quota exceeded\n\t\t} catch ( error ) {\n\t\t\t// roll the value back to the previous value\n\t\t\tif ( prevValue === null ) {\n\t\t\t\tdiv.removeAttribute( key );\n\t\t\t} else {\n\t\t\t\tdiv.setAttribute( key, prevValue );\n\t\t\t}\n\n\t\t\t// expire old data and try again\n\t\t\tstore.userData();\n\t\t\ttry {\n\t\t\t\tdiv.setAttribute( key, parsed );\n\t\t\t\tdiv.save( attrKey );\n\t\t\t} catch ( error ) {\n\t\t\t\t// roll the value back to the previous value\n\t\t\t\tif ( prevValue === null ) {\n\t\t\t\t\tdiv.removeAttribute( key );\n\t\t\t\t} else {\n\t\t\t\t\tdiv.setAttribute( key, prevValue );\n\t\t\t\t}\n\t\t\t\tthrow store.error();\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t});\n}() );\n\n// in-memory storage\n// fallback for all browsers to enable the API even if we can't persist data\n(function() {\n\tvar memory = {},\n\t\ttimeout = {};\n\n\tfunction copy( obj ) {\n\t\treturn obj === undefined ? undefined : JSON.parse( JSON.stringify( obj ) );\n\t}\n\n\tstore.addType( \"memory\", function( key, value, options ) {\n\t\tif ( !key ) {\n\t\t\treturn copy( memory );\n\t\t}\n\n\t\tif ( value === undefined ) {\n\t\t\treturn copy( memory[ key ] );\n\t\t}\n\n\t\tif ( timeout[ key ] ) {\n\t\t\tclearTimeout( timeout[ key ] );\n\t\t\tdelete timeout[ key ];\n\t\t}\n\n\t\tif ( value === null ) {\n\t\t\tdelete memory[ key ];\n\t\t\treturn null;\n\t\t}\n\n\t\tmemory[ key ] = value;\n\t\tif ( options.expires ) {\n\t\t\ttimeout[ key ] = setTimeout(function() {\n\t\t\t\tdelete memory[ key ];\n\t\t\t\tdelete timeout[ key ];\n\t\t\t}, options.expires );\n\t\t}\n\n\t\treturn value;\n\t});\n}() );\n\n}( this.amplify = this.amplify || {} ) );\n\n/*global amplify*/\n\n(function( amplify, undefined ) {\n'use strict';\n\nfunction noop() {}\nfunction isFunction( obj ) {\n\treturn ({}).toString.call( obj ) === \"[object Function]\";\n}\n\nfunction async( fn ) {\n\tvar isAsync = false;\n\tsetTimeout(function() {\n\t\tisAsync = true;\n\t}, 1 );\n\treturn function() {\n\t\tvar that = this,\n\t\t\targs = arguments;\n\t\tif ( isAsync ) {\n\t\t\tfn.apply( that, args );\n\t\t} else {\n\t\t\tsetTimeout(function() {\n\t\t\t\tfn.apply( that, args );\n\t\t\t}, 1 );\n\t\t}\n\t};\n}\n\namplify.request = function( resourceId, data, callback ) {\n\t// default to an empty hash just so we can handle a missing resourceId\n\t// in one place\n\tvar settings = resourceId || {};\n\n\tif ( typeof settings === \"string\" ) {\n\t\tif ( isFunction( data ) ) {\n\t\t\tcallback = data;\n\t\t\tdata = {};\n\t\t}\n\t\tsettings = {\n\t\t\tresourceId: resourceId,\n\t\t\tdata: data || {},\n\t\t\tsuccess: callback\n\t\t};\n\t}\n\n\tvar request = { abort: noop },\n\t\tresource = amplify.request.resources[ settings.resourceId ],\n\t\tsuccess = settings.success || noop,\n\t\terror = settings.error || noop;\n\n\tsettings.success = async( function( data, status ) {\n\t\tstatus = status || \"success\";\n\t\tamplify.publish( \"request.success\", settings, data, status );\n\t\tamplify.publish( \"request.complete\", settings, data, status );\n\t\tsuccess( data, status );\n\t});\n\n\tsettings.error = async( function( data, status ) {\n\t\tstatus = status || \"error\";\n\t\tamplify.publish( \"request.error\", settings, data, status );\n\t\tamplify.publish( \"request.complete\", settings, data, status );\n\t\terror( data, status );\n\t});\n\n\tif ( !resource ) {\n\t\tif ( !settings.resourceId ) {\n\t\t\tthrow \"amplify.request: no resourceId provided\";\n\t\t}\n\t\tthrow \"amplify.request: unknown resourceId: \" + settings.resourceId;\n\t}\n\n\tif ( !amplify.publish( \"request.before\", settings ) ) {\n\t\tsettings.error( null, \"abort\" );\n\t\treturn;\n\t}\n\n\tamplify.request.resources[ settings.resourceId ]( settings, request );\n\treturn request;\n};\n\namplify.request.types = {};\namplify.request.resources = {};\namplify.request.define = function( resourceId, type, settings ) {\n\tif ( typeof type === \"string\" ) {\n\t\tif ( !( type in amplify.request.types ) ) {\n\t\t\tthrow \"amplify.request.define: unknown type: \" + type;\n\t\t}\n\n\t\tsettings.resourceId = resourceId;\n\t\tamplify.request.resources[ resourceId ] =\n\t\t\tamplify.request.types[ type ]( settings );\n\t} else {\n\t\t// no pre-processor or settings for one-off types (don't invoke)\n\t\tamplify.request.resources[ resourceId ] = type;\n\t}\n};\n\n}( amplify ) );\n\n\n(function( amplify, $, undefined ) {\n'use strict';\n\nvar xhrProps = [ \"status\", \"statusText\", \"responseText\", \"responseXML\", \"readyState\" ],\n\t\trurlData = /\\{([^\\}]+)\\}/g;\n\namplify.request.types.ajax = function( defnSettings ) {\n\tdefnSettings = $.extend({\n\t\ttype: \"GET\"\n\t}, defnSettings );\n\n\treturn function( settings, request ) {\n\t\tvar xhr, handleResponse,\n\t\t\turl = defnSettings.url,\n\t\t\tabort = request.abort,\n\t\t\tajaxSettings = $.extend( true, {}, defnSettings, { data: settings.data } ),\n\t\t\taborted = false,\n\t\t\tampXHR = {\n\t\t\t\treadyState: 0,\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\treturn xhr.setRequestHeader( name, value );\n\t\t\t\t},\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn xhr.getAllResponseHeaders();\n\t\t\t\t},\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\treturn xhr.getResponseHeader( key );\n\t\t\t\t},\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\treturn xhr.overrideMimeType( type );\n\t\t\t\t},\n\t\t\t\tabort: function() {\n\t\t\t\t\taborted = true;\n\t\t\t\t\ttry {\n\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t// IE 7 throws an error when trying to abort\n\t\t\t\t\t} catch( e ) {}\n\t\t\t\t\thandleResponse( null, \"abort\" );\n\t\t\t\t},\n\t\t\t\tsuccess: function( data, status ) {\n\t\t\t\t\tsettings.success( data, status );\n\t\t\t\t},\n\t\t\t\terror: function( data, status ) {\n\t\t\t\t\tsettings.error( data, status );\n\t\t\t\t}\n\t\t\t};\n\n\t\thandleResponse = function( data, status ) {\n\t\t\t$.each( xhrProps, function( i, key ) {\n\t\t\t\ttry {\n\t\t\t\t\tampXHR[ key ] = xhr[ key ];\n\t\t\t\t} catch( e ) {}\n\t\t\t});\n\t\t\t// Playbook returns \"HTTP/1.1 200 OK\"\n\t\t\t// TODO: something also returns \"OK\", what?\n\t\t\tif ( /OK$/.test( ampXHR.statusText ) ) {\n\t\t\t\tampXHR.statusText = \"success\";\n\t\t\t}\n\t\t\tif ( data === undefined ) {\n\t\t\t\t// TODO: add support for ajax errors with data\n\t\t\t\tdata = null;\n\t\t\t}\n\t\t\tif ( aborted ) {\n\t\t\t\tstatus = \"abort\";\n\t\t\t}\n\t\t\tif ( /timeout|error|abort/.test( status ) ) {\n\t\t\t\tampXHR.error( data, status );\n\t\t\t} else {\n\t\t\t\tampXHR.success( data, status );\n\t\t\t}\n\t\t\t// avoid handling a response multiple times\n\t\t\t// this can happen if a request is aborted\n\t\t\t// TODO: figure out if this breaks polling or multi-part responses\n\t\t\thandleResponse = $.noop;\n\t\t};\n\n\t\tamplify.publish( \"request.ajax.preprocess\",\n\t\t\tdefnSettings, settings, ajaxSettings, ampXHR );\n\n\t\t$.extend( ajaxSettings, {\n\t\t\tisJSONP: function () {\n\t\t\t\treturn (/jsonp/gi).test(this.dataType);\n\t\t\t},\n\t\t\tcacheURL: function () {\n\t\t\t\tif (!this.isJSONP()) {\n\t\t\t\t\treturn this.url;\n\t\t\t\t}\n\n\t\t\t\tvar callbackName = 'callback';\n\n\t\t\t\t// possible for the callback function name to be overridden\n\t\t\t\tif (this.hasOwnProperty('jsonp')) {\n\t\t\t\t\tif (this.jsonp !== false) {\n\t\t\t\t\t\tcallbackName = this.jsonp;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (this.hasOwnProperty('jsonpCallback')) {\n\t\t\t\t\t\t\tcallbackName = this.jsonpCallback;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// search and replace callback parameter in query string with empty string\n\t\t\t\tvar callbackRegex = new RegExp('&?' + callbackName + '=[^&]*&?', 'gi');\n\t\t\t\treturn this.url.replace(callbackRegex, '');\n\t\t\t},\n\t\t\tsuccess: function( data, status ) {\n\t\t\t\thandleResponse( data, status );\n\t\t\t},\n\t\t\terror: function( _xhr, status ) {\n\t\t\t\thandleResponse( null, status );\n\t\t\t},\n\t\t\tbeforeSend: function( _xhr, _ajaxSettings ) {\n\t\t\t\txhr = _xhr;\n\t\t\t\tajaxSettings = _ajaxSettings;\n\t\t\t\tvar ret = defnSettings.beforeSend ?\n\t\t\t\t\tdefnSettings.beforeSend.call( this, ampXHR, ajaxSettings ) : true;\n\t\t\t\treturn ret && amplify.publish( \"request.before.ajax\",\n\t\t\t\t\tdefnSettings, settings, ajaxSettings, ampXHR );\n\t\t\t}\n\t\t});\n\n\t\t// cache all JSONP requests\n\t\tif (ajaxSettings.cache && ajaxSettings.isJSONP()) {\n\t\t\t$.extend(ajaxSettings, {\n\t\t\t\tcache: true\n\t\t\t});\n\t\t}\n\n\t\t$.ajax( ajaxSettings );\n\n\t\trequest.abort = function() {\n\t\t\tampXHR.abort();\n\t\t\tabort.call( this );\n\t\t};\n\t};\n};\n\n\n\namplify.subscribe( \"request.ajax.preprocess\", function( defnSettings, settings, ajaxSettings ) {\n\tvar mappedKeys = [],\n\t\tdata = ajaxSettings.data;\n\n\tif ( typeof data === \"string\" ) {\n\t\treturn;\n\t}\n\n\tdata = $.extend( true, {}, defnSettings.data, data );\n\n\tajaxSettings.url = ajaxSettings.url.replace( rurlData, function ( m, key ) {\n\t\tif ( key in data ) {\n\t\t\tmappedKeys.push( key );\n\t\t\treturn data[ key ];\n\t\t}\n\t});\n\n\t// We delete the keys later so duplicates are still replaced\n\t$.each( mappedKeys, function ( i, key ) {\n\t\tdelete data[ key ];\n\t});\n\n\tajaxSettings.data = data;\n});\n\n\n\namplify.subscribe( \"request.ajax.preprocess\", function( defnSettings, settings, ajaxSettings ) {\n\tvar data = ajaxSettings.data,\n\t\tdataMap = defnSettings.dataMap;\n\n\tif ( !dataMap || typeof data === \"string\" ) {\n\t\treturn;\n\t}\n\n\tif ( $.isFunction( dataMap ) ) {\n\t\tajaxSettings.data = dataMap( data );\n\t} else {\n\t\t$.each( defnSettings.dataMap, function( orig, replace ) {\n\t\t\tif ( orig in data ) {\n\t\t\t\tdata[ replace ] = data[ orig ];\n\t\t\t\tdelete data[ orig ];\n\t\t\t}\n\t\t});\n\t\tajaxSettings.data = data;\n\t}\n});\n\n\n\nvar cache = amplify.request.cache = {\n\t_key: function( resourceId, url, data ) {\n\t\tdata = url + data;\n\t\tvar length = data.length,\n\t\t\ti = 0;\n\n\t\t/*jshint bitwise:false*/\n\t\tfunction chunk() {\n\t\t\treturn data.charCodeAt( i++ ) << 24 |\n\t\t\t\tdata.charCodeAt( i++ ) << 16 |\n\t\t\t\tdata.charCodeAt( i++ ) << 8 |\n\t\t\t\tdata.charCodeAt( i++ ) << 0;\n\t\t}\n\n\t\tvar checksum = chunk();\n\t\twhile ( i < length ) {\n\t\t\tchecksum ^= chunk();\n\t\t}\n\t\t/*jshint bitwise:true*/\n\n\t\treturn \"request-\" + resourceId + \"-\" + checksum;\n\t},\n\n\t_default: (function() {\n\t\tvar memoryStore = {};\n\t\treturn function( resource, settings, ajaxSettings, ampXHR ) {\n\t\t\t// data is already converted to a string by the time we get here\n\t\t\tvar cacheKey = cache._key( settings.resourceId,\n\t\t\t\t\tajaxSettings.cacheURL(), ajaxSettings.data ),\n\t\t\t\tduration = resource.cache;\n\n\t\t\tif ( cacheKey in memoryStore ) {\n\t\t\t\tampXHR.success( memoryStore[ cacheKey ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar success = ampXHR.success;\n\t\t\tampXHR.success = function( data ) {\n\t\t\t\tmemoryStore[ cacheKey ] = data;\n\t\t\t\tif ( typeof duration === \"number\" ) {\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tdelete memoryStore[ cacheKey ];\n\t\t\t\t\t}, duration );\n\t\t\t\t}\n\t\t\t\tsuccess.apply( this, arguments );\n\t\t\t};\n\t\t};\n\t}())\n};\n\nif ( amplify.store ) {\n\t$.each( amplify.store.types, function( type ) {\n\t\tcache[ type ] = function( resource, settings, ajaxSettings, ampXHR ) {\n\t\t\tvar cacheKey = cache._key( settings.resourceId,\n\t\t\t\t\tajaxSettings.cacheURL(), ajaxSettings.data ),\n\t\t\t\tcached = amplify.store[ type ]( cacheKey );\n\n\t\t\tif ( cached ) {\n\t\t\t\tajaxSettings.success( cached );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar success = ampXHR.success;\n\t\t\tampXHR.success = function( data ) {\n\t\t\t\tamplify.store[ type ]( cacheKey, data, { expires: resource.cache.expires } );\n\t\t\t\tsuccess.apply( this, arguments );\n\t\t\t};\n\t\t};\n\t});\n\tcache.persist = cache[ amplify.store.type ];\n}\n\namplify.subscribe( \"request.before.ajax\", function( resource ) {\n\tvar cacheType = resource.cache;\n\tif ( cacheType ) {\n\t\t// normalize between objects and strings/booleans/numbers\n\t\tcacheType = cacheType.type || cacheType;\n\t\treturn cache[ cacheType in cache ? cacheType : \"_default\" ]\n\t\t\t.apply( this, arguments );\n\t}\n});\n\n\n\namplify.request.decoders = {\n\t// http://labs.omniti.com/labs/jsend\n\tjsend: function( data, status, ampXHR, success, error ) {\n\t\tif ( data.status === \"success\" ) {\n\t\t\tsuccess( data.data );\n\t\t} else if ( data.status === \"fail\" ) {\n\t\t\terror( data.data, \"fail\" );\n\t\t} else if ( data.status === \"error\" ) {\n\t\t\tdelete data.status;\n\t\t\terror( data, \"error\" );\n\t\t} else {\n\t\t\terror( null, \"error\" );\n\t\t}\n\t}\n};\n\namplify.subscribe( \"request.before.ajax\", function( resource, settings, ajaxSettings, ampXHR ) {\n\tvar _success = ampXHR.success,\n\t\t_error = ampXHR.error,\n\t\tdecoder = $.isFunction( resource.decoder ) ?\n\t\t\tresource.decoder :\n\t\t\tresource.decoder in amplify.request.decoders ?\n\t\t\t\tamplify.request.decoders[ resource.decoder ] :\n\t\t\t\tamplify.request.decoders._default;\n\n\tif ( !decoder ) {\n\t\treturn;\n\t}\n\n\tfunction success( data, status ) {\n\t\t_success( data, status );\n\t}\n\tfunction error( data, status ) {\n\t\t_error( data, status );\n\t}\n\tampXHR.success = function( data, status ) {\n\t\tdecoder( data, status, ampXHR, success, error );\n\t};\n\tampXHR.error = function( data, status ) {\n\t\tdecoder( data, status, ampXHR, success, error );\n\t};\n});\n\n}( amplify, jQuery ) );\n"
  },
  {
    "path": "packages/deprecated/amplify/package.js",
    "content": "Package.describe({\n  summary: \"API for Persistent Storage, PubSub and Request\",\n  version: \"1.0.0\"\n});\n\nPackage.onUse(function (api) {\n  api.use('jquery', 'client');\n  api.addFiles('amplify.js', 'client');\n});\n"
  },
  {
    "path": "packages/deprecated/backbone/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/deprecated/backbone/backbone.js",
    "content": "//     Backbone.js 0.9.2\n\n//     (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.\n//     Backbone may be freely distributed under the MIT license.\n//     For all details and documentation:\n//     http://backbonejs.org\n\n// Meteor changes occur inside <METEOR> </METEOR> -- dgreenspan\n\n(function(){\n\n  // Initial Setup\n  // -------------\n\n  // Save a reference to the global object (`window` in the browser, `global`\n  // on the server).\n  var root = this;\n\n  // Save the previous value of the `Backbone` variable, so that it can be\n  // restored later on, if `noConflict` is used.\n  var previousBackbone = root.Backbone;\n\n  // Create a local reference to slice/splice.\n  var slice = Array.prototype.slice;\n  var splice = Array.prototype.splice;\n\n  // The top-level namespace. All public Backbone classes and modules will\n  // be attached to this. Exported for both CommonJS and the browser.\n  var Backbone;\n  if (typeof exports !== 'undefined') {\n    Backbone = exports;\n  } else {\n    Backbone = root.Backbone = {};\n  }\n\n  // Current version of the library. Keep in sync with `package.json`.\n  Backbone.VERSION = '0.9.2';\n\n  // Require Underscore, if we're on the server, and it's not already present.\n  // <METEOR> Commented these lines out; we have _ via api.use.\n  // var _ = root._;\n  // if (!_ && (typeof require !== 'undefined')) _ = require('underscore');\n  // </METEOR>\n\n  // For Backbone's purposes, jQuery, Zepto, or Ender owns the `$` variable.\n  var $ = root.jQuery || root.Zepto || root.ender;\n\n  // Set the JavaScript library that will be used for DOM manipulation and\n  // Ajax calls (a.k.a. the `$` variable). By default Backbone will use: jQuery,\n  // Zepto, or Ender; but the `setDomLibrary()` method lets you inject an\n  // alternate JavaScript library (or a mock library for testing your views\n  // outside of a browser).\n  Backbone.setDomLibrary = function(lib) {\n    $ = lib;\n  };\n\n  // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable\n  // to its previous owner. Returns a reference to this Backbone object.\n  Backbone.noConflict = function() {\n    root.Backbone = previousBackbone;\n    return this;\n  };\n\n  // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option\n  // will fake `\"PUT\"` and `\"DELETE\"` requests via the `_method` parameter and\n  // set a `X-Http-Method-Override` header.\n  Backbone.emulateHTTP = false;\n\n  // Turn on `emulateJSON` to support legacy servers that can't deal with direct\n  // `application/json` requests ... will encode the body as\n  // `application/x-www-form-urlencoded` instead and will send the model in a\n  // form param named `model`.\n  Backbone.emulateJSON = false;\n\n  // Backbone.Events\n  // -----------------\n\n  // Regular expression used to split event strings\n  var eventSplitter = /\\s+/;\n\n  // A module that can be mixed in to *any object* in order to provide it with\n  // custom events. You may bind with `on` or remove with `off` callback functions\n  // to an event; trigger`-ing an event fires all callbacks in succession.\n  //\n  //     var object = {};\n  //     _.extend(object, Backbone.Events);\n  //     object.on('expand', function(){ alert('expanded'); });\n  //     object.trigger('expand');\n  //\n  var Events = Backbone.Events = {\n\n    // Bind one or more space separated events, `events`, to a `callback`\n    // function. Passing `\"all\"` will bind the callback to all events fired.\n    on: function(events, callback, context) {\n\n      var calls, event, node, tail, list;\n      if (!callback) return this;\n      events = events.split(eventSplitter);\n      calls = this._callbacks || (this._callbacks = {});\n\n      // Create an immutable callback list, allowing traversal during\n      // modification.  The tail is an empty object that will always be used\n      // as the next node.\n      while (event = events.shift()) {\n        list = calls[event];\n        node = list ? list.tail : {};\n        node.next = tail = {};\n        node.context = context;\n        node.callback = callback;\n        calls[event] = {tail: tail, next: list ? list.next : node};\n      }\n\n      return this;\n    },\n\n    // Remove one or many callbacks. If `context` is null, removes all callbacks\n    // with that function. If `callback` is null, removes all callbacks for the\n    // event. If `events` is null, removes all bound callbacks for all events.\n    off: function(events, callback, context) {\n      var event, calls, node, tail, cb, ctx;\n\n      // No events, or removing *all* events.\n      if (!(calls = this._callbacks)) return;\n      if (!(events || callback || context)) {\n        delete this._callbacks;\n        return this;\n      }\n\n      // Loop through the listed events and contexts, splicing them out of the\n      // linked list of callbacks if appropriate.\n      events = events ? events.split(eventSplitter) : _.keys(calls);\n      while (event = events.shift()) {\n        node = calls[event];\n        delete calls[event];\n        if (!node || !(callback || context)) continue;\n        // Create a new list, omitting the indicated callbacks.\n        tail = node.tail;\n        while ((node = node.next) !== tail) {\n          cb = node.callback;\n          ctx = node.context;\n          if ((callback && cb !== callback) || (context && ctx !== context)) {\n            this.on(event, cb, ctx);\n          }\n        }\n      }\n\n      return this;\n    },\n\n    // Trigger one or many events, firing all bound callbacks. Callbacks are\n    // passed the same arguments as `trigger` is, apart from the event name\n    // (unless you're listening on `\"all\"`, which will cause your callback to\n    // receive the true name of the event as the first argument).\n    trigger: function(events) {\n      var event, node, calls, tail, args, all, rest;\n      if (!(calls = this._callbacks)) return this;\n      all = calls.all;\n      events = events.split(eventSplitter);\n      rest = slice.call(arguments, 1);\n\n      // For each event, walk through the linked list of callbacks twice,\n      // first to trigger the event, then to trigger any `\"all\"` callbacks.\n      while (event = events.shift()) {\n        if (node = calls[event]) {\n          tail = node.tail;\n          while ((node = node.next) !== tail) {\n            node.callback.apply(node.context || this, rest);\n          }\n        }\n        if (node = all) {\n          tail = node.tail;\n          args = [event].concat(rest);\n          while ((node = node.next) !== tail) {\n            node.callback.apply(node.context || this, args);\n          }\n        }\n      }\n\n      return this;\n    }\n\n  };\n\n  // Aliases for backwards compatibility.\n  Events.bind   = Events.on;\n  Events.unbind = Events.off;\n\n  // Backbone.Model\n  // --------------\n\n  // Create a new model, with defined attributes. A client id (`cid`)\n  // is automatically generated and assigned for you.\n  var Model = Backbone.Model = function(attributes, options) {\n    var defaults;\n    attributes || (attributes = {});\n    if (options && options.parse) attributes = this.parse(attributes);\n    if (defaults = getValue(this, 'defaults')) {\n      attributes = _.extend({}, defaults, attributes);\n    }\n    if (options && options.collection) this.collection = options.collection;\n    this.attributes = {};\n    this._escapedAttributes = {};\n    this.cid = _.uniqueId('c');\n    this.changed = {};\n    this._silent = {};\n    this._pending = {};\n    this.set(attributes, {silent: true});\n    // Reset change tracking.\n    this.changed = {};\n    this._silent = {};\n    this._pending = {};\n    this._previousAttributes = _.clone(this.attributes);\n    this.initialize.apply(this, arguments);\n  };\n\n  // Attach all inheritable methods to the Model prototype.\n  _.extend(Model.prototype, Events, {\n\n    // A hash of attributes whose current and previous value differ.\n    changed: null,\n\n    // A hash of attributes that have silently changed since the last time\n    // `change` was called.  Will become pending attributes on the next call.\n    _silent: null,\n\n    // A hash of attributes that have changed since the last `'change'` event\n    // began.\n    _pending: null,\n\n    // The default name for the JSON `id` attribute is `\"id\"`. MongoDB and\n    // CouchDB users may want to set this to `\"_id\"`.\n    idAttribute: 'id',\n\n    // Initialize is an empty function by default. Override it with your own\n    // initialization logic.\n    initialize: function(){},\n\n    // Return a copy of the model's `attributes` object.\n    toJSON: function(options) {\n      return _.clone(this.attributes);\n    },\n\n    // Get the value of an attribute.\n    get: function(attr) {\n      return this.attributes[attr];\n    },\n\n    // Get the HTML-escaped value of an attribute.\n    escape: function(attr) {\n      var html;\n      if (html = this._escapedAttributes[attr]) return html;\n      var val = this.get(attr);\n      return this._escapedAttributes[attr] = _.escape(val == null ? '' : '' + val);\n    },\n\n    // Returns `true` if the attribute contains a value that is not null\n    // or undefined.\n    has: function(attr) {\n      return this.get(attr) != null;\n    },\n\n    // Set a hash of model attributes on the object, firing `\"change\"` unless\n    // you choose to silence it.\n    set: function(key, value, options) {\n      var attrs, attr, val;\n\n      // Handle both `\"key\", value` and `{key: value}` -style arguments.\n      if (_.isObject(key) || key == null) {\n        attrs = key;\n        options = value;\n      } else {\n        attrs = {};\n        attrs[key] = value;\n      }\n\n      // Extract attributes and options.\n      options || (options = {});\n      if (!attrs) return this;\n      if (attrs instanceof Model) attrs = attrs.attributes;\n      if (options.unset) for (attr in attrs) attrs[attr] = void 0;\n\n      // Run validation.\n      if (!this._validate(attrs, options)) return false;\n\n      // Check for changes of `id`.\n      if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];\n\n      var changes = options.changes = {};\n      var now = this.attributes;\n      var escaped = this._escapedAttributes;\n      var prev = this._previousAttributes || {};\n\n      // For each `set` attribute...\n      for (attr in attrs) {\n        val = attrs[attr];\n\n        // If the new and current value differ, record the change.\n        if (!_.isEqual(now[attr], val) || (options.unset && _.has(now, attr))) {\n          delete escaped[attr];\n          (options.silent ? this._silent : changes)[attr] = true;\n        }\n\n        // Update or delete the current value.\n        options.unset ? delete now[attr] : now[attr] = val;\n\n        // If the new and previous value differ, record the change.  If not,\n        // then remove changes for this attribute.\n        if (!_.isEqual(prev[attr], val) || (_.has(now, attr) != _.has(prev, attr))) {\n          this.changed[attr] = val;\n          if (!options.silent) this._pending[attr] = true;\n        } else {\n          delete this.changed[attr];\n          delete this._pending[attr];\n        }\n      }\n\n      // Fire the `\"change\"` events.\n      if (!options.silent) this.change(options);\n      return this;\n    },\n\n    // Remove an attribute from the model, firing `\"change\"` unless you choose\n    // to silence it. `unset` is a noop if the attribute doesn't exist.\n    unset: function(attr, options) {\n      (options || (options = {})).unset = true;\n      return this.set(attr, null, options);\n    },\n\n    // Clear all attributes on the model, firing `\"change\"` unless you choose\n    // to silence it.\n    clear: function(options) {\n      (options || (options = {})).unset = true;\n      return this.set(_.clone(this.attributes), options);\n    },\n\n    // Fetch the model from the server. If the server's representation of the\n    // model differs from its current attributes, they will be overriden,\n    // triggering a `\"change\"` event.\n    fetch: function(options) {\n      options = options ? _.clone(options) : {};\n      var model = this;\n      var success = options.success;\n      options.success = function(resp, status, xhr) {\n        if (!model.set(model.parse(resp, xhr), options)) return false;\n        if (success) success(model, resp);\n      };\n      options.error = Backbone.wrapError(options.error, model, options);\n      return (this.sync || Backbone.sync).call(this, 'read', this, options);\n    },\n\n    // Set a hash of model attributes, and sync the model to the server.\n    // If the server returns an attributes hash that differs, the model's\n    // state will be `set` again.\n    save: function(key, value, options) {\n      var attrs, current;\n\n      // Handle both `(\"key\", value)` and `({key: value})` -style calls.\n      if (_.isObject(key) || key == null) {\n        attrs = key;\n        options = value;\n      } else {\n        attrs = {};\n        attrs[key] = value;\n      }\n      options = options ? _.clone(options) : {};\n\n      // If we're \"wait\"-ing to set changed attributes, validate early.\n      if (options.wait) {\n        if (!this._validate(attrs, options)) return false;\n        current = _.clone(this.attributes);\n      }\n\n      // Regular saves `set` attributes before persisting to the server.\n      var silentOptions = _.extend({}, options, {silent: true});\n      if (attrs && !this.set(attrs, options.wait ? silentOptions : options)) {\n        return false;\n      }\n\n      // After a successful server-side save, the client is (optionally)\n      // updated with the server-side state.\n      var model = this;\n      var success = options.success;\n      options.success = function(resp, status, xhr) {\n        var serverAttrs = model.parse(resp, xhr);\n        if (options.wait) {\n          delete options.wait;\n          serverAttrs = _.extend(attrs || {}, serverAttrs);\n        }\n        if (!model.set(serverAttrs, options)) return false;\n        if (success) {\n          success(model, resp);\n        } else {\n          model.trigger('sync', model, resp, options);\n        }\n      };\n\n      // Finish configuring and sending the Ajax request.\n      options.error = Backbone.wrapError(options.error, model, options);\n      var method = this.isNew() ? 'create' : 'update';\n      var xhr = (this.sync || Backbone.sync).call(this, method, this, options);\n      if (options.wait) this.set(current, silentOptions);\n      return xhr;\n    },\n\n    // Destroy this model on the server if it was already persisted.\n    // Optimistically removes the model from its collection, if it has one.\n    // If `wait: true` is passed, waits for the server to respond before removal.\n    destroy: function(options) {\n      options = options ? _.clone(options) : {};\n      var model = this;\n      var success = options.success;\n\n      var triggerDestroy = function() {\n        model.trigger('destroy', model, model.collection, options);\n      };\n\n      if (this.isNew()) {\n        triggerDestroy();\n        return false;\n      }\n\n      options.success = function(resp) {\n        if (options.wait) triggerDestroy();\n        if (success) {\n          success(model, resp);\n        } else {\n          model.trigger('sync', model, resp, options);\n        }\n      };\n\n      options.error = Backbone.wrapError(options.error, model, options);\n      var xhr = (this.sync || Backbone.sync).call(this, 'delete', this, options);\n      if (!options.wait) triggerDestroy();\n      return xhr;\n    },\n\n    // Default URL for the model's representation on the server -- if you're\n    // using Backbone's restful methods, override this to change the endpoint\n    // that will be called.\n    url: function() {\n      var base = getValue(this, 'urlRoot') || getValue(this.collection, 'url') || urlError();\n      if (this.isNew()) return base;\n      return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + encodeURIComponent(this.id);\n    },\n\n    // **parse** converts a response into the hash of attributes to be `set` on\n    // the model. The default implementation is just to pass the response along.\n    parse: function(resp, xhr) {\n      return resp;\n    },\n\n    // Create a new model with identical attributes to this one.\n    clone: function() {\n      return new this.constructor(this.attributes);\n    },\n\n    // A model is new if it has never been saved to the server, and lacks an id.\n    isNew: function() {\n      return this.id == null;\n    },\n\n    // Call this method to manually fire a `\"change\"` event for this model and\n    // a `\"change:attribute\"` event for each changed attribute.\n    // Calling this will cause all objects observing the model to update.\n    change: function(options) {\n      options || (options = {});\n      var changing = this._changing;\n      this._changing = true;\n\n      // Silent changes become pending changes.\n      for (var attr in this._silent) this._pending[attr] = true;\n\n      // Silent changes are triggered.\n      var changes = _.extend({}, options.changes, this._silent);\n      this._silent = {};\n      for (var attr in changes) {\n        this.trigger('change:' + attr, this, this.get(attr), options);\n      }\n      if (changing) return this;\n\n      // Continue firing `\"change\"` events while there are pending changes.\n      while (!_.isEmpty(this._pending)) {\n        this._pending = {};\n        this.trigger('change', this, options);\n        // Pending and silent changes still remain.\n        for (var attr in this.changed) {\n          if (this._pending[attr] || this._silent[attr]) continue;\n          delete this.changed[attr];\n        }\n        this._previousAttributes = _.clone(this.attributes);\n      }\n\n      this._changing = false;\n      return this;\n    },\n\n    // Determine if the model has changed since the last `\"change\"` event.\n    // If you specify an attribute name, determine if that attribute has changed.\n    hasChanged: function(attr) {\n      if (!arguments.length) return !_.isEmpty(this.changed);\n      return _.has(this.changed, attr);\n    },\n\n    // Return an object containing all the attributes that have changed, or\n    // false if there are no changed attributes. Useful for determining what\n    // parts of a view need to be updated and/or what attributes need to be\n    // persisted to the server. Unset attributes will be set to undefined.\n    // You can also pass an attributes object to diff against the model,\n    // determining if there *would be* a change.\n    changedAttributes: function(diff) {\n      if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;\n      var val, changed = false, old = this._previousAttributes;\n      for (var attr in diff) {\n        if (_.isEqual(old[attr], (val = diff[attr]))) continue;\n        (changed || (changed = {}))[attr] = val;\n      }\n      return changed;\n    },\n\n    // Get the previous value of an attribute, recorded at the time the last\n    // `\"change\"` event was fired.\n    previous: function(attr) {\n      if (!arguments.length || !this._previousAttributes) return null;\n      return this._previousAttributes[attr];\n    },\n\n    // Get all of the attributes of the model at the time of the previous\n    // `\"change\"` event.\n    previousAttributes: function() {\n      return _.clone(this._previousAttributes);\n    },\n\n    // Check if the model is currently in a valid state. It's only possible to\n    // get into an *invalid* state if you're using silent changes.\n    isValid: function() {\n      return !this.validate(this.attributes);\n    },\n\n    // Run validation against the next complete set of model attributes,\n    // returning `true` if all is well. If a specific `error` callback has\n    // been passed, call that instead of firing the general `\"error\"` event.\n    _validate: function(attrs, options) {\n      if (options.silent || !this.validate) return true;\n      attrs = _.extend({}, this.attributes, attrs);\n      var error = this.validate(attrs, options);\n      if (!error) return true;\n      if (options && options.error) {\n        options.error(this, error, options);\n      } else {\n        this.trigger('error', this, error, options);\n      }\n      return false;\n    }\n\n  });\n\n  // Backbone.Collection\n  // -------------------\n\n  // Provides a standard collection class for our sets of models, ordered\n  // or unordered. If a `comparator` is specified, the Collection will maintain\n  // its models in sort order, as they're added and removed.\n  var Collection = Backbone.Collection = function(models, options) {\n    options || (options = {});\n    if (options.model) this.model = options.model;\n    if (options.comparator) this.comparator = options.comparator;\n    this._reset();\n    this.initialize.apply(this, arguments);\n    if (models) this.reset(models, {silent: true, parse: options.parse});\n  };\n\n  // Define the Collection's inheritable methods.\n  _.extend(Collection.prototype, Events, {\n\n    // The default model for a collection is just a **Backbone.Model**.\n    // This should be overridden in most cases.\n    model: Model,\n\n    // Initialize is an empty function by default. Override it with your own\n    // initialization logic.\n    initialize: function(){},\n\n    // The JSON representation of a Collection is an array of the\n    // models' attributes.\n    toJSON: function(options) {\n      return this.map(function(model){ return model.toJSON(options); });\n    },\n\n    // Add a model, or list of models to the set. Pass **silent** to avoid\n    // firing the `add` event for every new model.\n    add: function(models, options) {\n      var i, index, length, model, cid, id, cids = {}, ids = {}, dups = [];\n      options || (options = {});\n      models = _.isArray(models) ? models.slice() : [models];\n\n      // Begin by turning bare objects into model references, and preventing\n      // invalid models or duplicate models from being added.\n      for (i = 0, length = models.length; i < length; i++) {\n        if (!(model = models[i] = this._prepareModel(models[i], options))) {\n          throw new Error(\"Can't add an invalid model to a collection\");\n        }\n        cid = model.cid;\n        id = model.id;\n        if (cids[cid] || this._byCid[cid] || ((id != null) && (ids[id] || this._byId[id]))) {\n          dups.push(i);\n          continue;\n        }\n        cids[cid] = ids[id] = model;\n      }\n\n      // Remove duplicates.\n      i = dups.length;\n      while (i--) {\n        models.splice(dups[i], 1);\n      }\n\n      // Listen to added models' events, and index models for lookup by\n      // `id` and by `cid`.\n      for (i = 0, length = models.length; i < length; i++) {\n        (model = models[i]).on('all', this._onModelEvent, this);\n        this._byCid[model.cid] = model;\n        if (model.id != null) this._byId[model.id] = model;\n      }\n\n      // Insert models into the collection, re-sorting if needed, and triggering\n      // `add` events unless silenced.\n      this.length += length;\n      index = options.at != null ? options.at : this.models.length;\n      splice.apply(this.models, [index, 0].concat(models));\n      if (this.comparator) this.sort({silent: true});\n      if (options.silent) return this;\n      for (i = 0, length = this.models.length; i < length; i++) {\n        if (!cids[(model = this.models[i]).cid]) continue;\n        options.index = i;\n        model.trigger('add', model, this, options);\n      }\n      return this;\n    },\n\n    // Remove a model, or a list of models from the set. Pass silent to avoid\n    // firing the `remove` event for every model removed.\n    remove: function(models, options) {\n      var i, l, index, model;\n      options || (options = {});\n      models = _.isArray(models) ? models.slice() : [models];\n      for (i = 0, l = models.length; i < l; i++) {\n        model = this.getByCid(models[i]) || this.get(models[i]);\n        if (!model) continue;\n        delete this._byId[model.id];\n        delete this._byCid[model.cid];\n        index = this.indexOf(model);\n        this.models.splice(index, 1);\n        this.length--;\n        if (!options.silent) {\n          options.index = index;\n          model.trigger('remove', model, this, options);\n        }\n        this._removeReference(model);\n      }\n      return this;\n    },\n\n    // Add a model to the end of the collection.\n    push: function(model, options) {\n      model = this._prepareModel(model, options);\n      this.add(model, options);\n      return model;\n    },\n\n    // Remove a model from the end of the collection.\n    pop: function(options) {\n      var model = this.at(this.length - 1);\n      this.remove(model, options);\n      return model;\n    },\n\n    // Add a model to the beginning of the collection.\n    unshift: function(model, options) {\n      model = this._prepareModel(model, options);\n      this.add(model, _.extend({at: 0}, options));\n      return model;\n    },\n\n    // Remove a model from the beginning of the collection.\n    shift: function(options) {\n      var model = this.at(0);\n      this.remove(model, options);\n      return model;\n    },\n\n    // Get a model from the set by id.\n    get: function(id) {\n      if (id == null) return void 0;\n      return this._byId[id.id != null ? id.id : id];\n    },\n\n    // Get a model from the set by client id.\n    getByCid: function(cid) {\n      return cid && this._byCid[cid.cid || cid];\n    },\n\n    // Get the model at the given index.\n    at: function(index) {\n      return this.models[index];\n    },\n\n    // Return models with matching attributes. Useful for simple cases of `filter`.\n    where: function(attrs) {\n      if (_.isEmpty(attrs)) return [];\n      return this.filter(function(model) {\n        for (var key in attrs) {\n          if (attrs[key] !== model.get(key)) return false;\n        }\n        return true;\n      });\n    },\n\n    // Force the collection to re-sort itself. You don't need to call this under\n    // normal circumstances, as the set will maintain sort order as each item\n    // is added.\n    sort: function(options) {\n      options || (options = {});\n      if (!this.comparator) throw new Error('Cannot sort a set without a comparator');\n      var boundComparator = _.bind(this.comparator, this);\n      if (this.comparator.length == 1) {\n        this.models = this.sortBy(boundComparator);\n      } else {\n        this.models.sort(boundComparator);\n      }\n      if (!options.silent) this.trigger('reset', this, options);\n      return this;\n    },\n\n    // Pluck an attribute from each model in the collection.\n    pluck: function(attr) {\n      return _.map(this.models, function(model){ return model.get(attr); });\n    },\n\n    // When you have more items than you want to add or remove individually,\n    // you can reset the entire set with a new list of models, without firing\n    // any `add` or `remove` events. Fires `reset` when finished.\n    reset: function(models, options) {\n      models  || (models = []);\n      options || (options = {});\n      for (var i = 0, l = this.models.length; i < l; i++) {\n        this._removeReference(this.models[i]);\n      }\n      this._reset();\n      this.add(models, _.extend({silent: true}, options));\n      if (!options.silent) this.trigger('reset', this, options);\n      return this;\n    },\n\n    // Fetch the default set of models for this collection, resetting the\n    // collection when they arrive. If `add: true` is passed, appends the\n    // models to the collection instead of resetting.\n    fetch: function(options) {\n      options = options ? _.clone(options) : {};\n      if (options.parse === undefined) options.parse = true;\n      var collection = this;\n      var success = options.success;\n      options.success = function(resp, status, xhr) {\n        collection[options.add ? 'add' : 'reset'](collection.parse(resp, xhr), options);\n        if (success) success(collection, resp);\n      };\n      options.error = Backbone.wrapError(options.error, collection, options);\n      return (this.sync || Backbone.sync).call(this, 'read', this, options);\n    },\n\n    // Create a new instance of a model in this collection. Add the model to the\n    // collection immediately, unless `wait: true` is passed, in which case we\n    // wait for the server to agree.\n    create: function(model, options) {\n      var coll = this;\n      options = options ? _.clone(options) : {};\n      model = this._prepareModel(model, options);\n      if (!model) return false;\n      if (!options.wait) coll.add(model, options);\n      var success = options.success;\n      options.success = function(nextModel, resp, xhr) {\n        if (options.wait) coll.add(nextModel, options);\n        if (success) {\n          success(nextModel, resp);\n        } else {\n          nextModel.trigger('sync', model, resp, options);\n        }\n      };\n      model.save(null, options);\n      return model;\n    },\n\n    // **parse** converts a response into a list of models to be added to the\n    // collection. The default implementation is just to pass it through.\n    parse: function(resp, xhr) {\n      return resp;\n    },\n\n    // Proxy to _'s chain. Can't be proxied the same way the rest of the\n    // underscore methods are proxied because it relies on the underscore\n    // constructor.\n    chain: function () {\n      return _(this.models).chain();\n    },\n\n    // Reset all internal state. Called when the collection is reset.\n    _reset: function(options) {\n      this.length = 0;\n      this.models = [];\n      this._byId  = {};\n      this._byCid = {};\n    },\n\n    // Prepare a model or hash of attributes to be added to this collection.\n    _prepareModel: function(model, options) {\n      options || (options = {});\n      if (!(model instanceof Model)) {\n        var attrs = model;\n        options.collection = this;\n        model = new this.model(attrs, options);\n        if (!model._validate(model.attributes, options)) model = false;\n      } else if (!model.collection) {\n        model.collection = this;\n      }\n      return model;\n    },\n\n    // Internal method to remove a model's ties to a collection.\n    _removeReference: function(model) {\n      if (this == model.collection) {\n        delete model.collection;\n      }\n      model.off('all', this._onModelEvent, this);\n    },\n\n    // Internal method called every time a model in the set fires an event.\n    // Sets need to update their indexes when models change ids. All other\n    // events simply proxy through. \"add\" and \"remove\" events that originate\n    // in other collections are ignored.\n    _onModelEvent: function(event, model, collection, options) {\n      if ((event == 'add' || event == 'remove') && collection != this) return;\n      if (event == 'destroy') {\n        this.remove(model, options);\n      }\n      if (model && event === 'change:' + model.idAttribute) {\n        delete this._byId[model.previous(model.idAttribute)];\n        this._byId[model.id] = model;\n      }\n      this.trigger.apply(this, arguments);\n    }\n\n  });\n\n  // Underscore methods that we want to implement on the Collection.\n  var methods = ['forEach', 'each', 'map', 'reduce', 'reduceRight', 'find',\n    'detect', 'filter', 'select', 'reject', 'every', 'all', 'some', 'any',\n    'include', 'contains', 'invoke', 'max', 'min', 'sortBy', 'sortedIndex',\n    'toArray', 'size', 'first', 'initial', 'rest', 'last', 'without', 'indexOf',\n    'shuffle', 'lastIndexOf', 'isEmpty', 'groupBy'];\n\n  // Mix in each Underscore method as a proxy to `Collection#models`.\n  _.each(methods, function(method) {\n    Collection.prototype[method] = function() {\n      return _[method].apply(_, [this.models].concat(_.toArray(arguments)));\n    };\n  });\n\n  // Backbone.Router\n  // -------------------\n\n  // Routers map faux-URLs to actions, and fire events when routes are\n  // matched. Creating a new one sets its `routes` hash, if not set statically.\n  var Router = Backbone.Router = function(options) {\n    options || (options = {});\n    if (options.routes) this.routes = options.routes;\n    this._bindRoutes();\n    this.initialize.apply(this, arguments);\n  };\n\n  // Cached regular expressions for matching named param parts and splatted\n  // parts of route strings.\n  var namedParam    = /:\\w+/g;\n  var splatParam    = /\\*\\w+/g;\n  var escapeRegExp  = /[-[\\]{}()+?.,\\\\^$|#\\s]/g;\n\n  // Set up all inheritable **Backbone.Router** properties and methods.\n  _.extend(Router.prototype, Events, {\n\n    // Initialize is an empty function by default. Override it with your own\n    // initialization logic.\n    initialize: function(){},\n\n    // Manually bind a single named route to a callback. For example:\n    //\n    //     this.route('search/:query/p:num', 'search', function(query, num) {\n    //       ...\n    //     });\n    //\n    route: function(route, name, callback) {\n      Backbone.history || (Backbone.history = new History);\n      if (!_.isRegExp(route)) route = this._routeToRegExp(route);\n      if (!callback) callback = this[name];\n      Backbone.history.route(route, _.bind(function(fragment) {\n        var args = this._extractParameters(route, fragment);\n        callback && callback.apply(this, args);\n        this.trigger.apply(this, ['route:' + name].concat(args));\n        Backbone.history.trigger('route', this, name, args);\n      }, this));\n      return this;\n    },\n\n    // Simple proxy to `Backbone.history` to save a fragment into the history.\n    navigate: function(fragment, options) {\n      Backbone.history.navigate(fragment, options);\n    },\n\n    // Bind all defined routes to `Backbone.history`. We have to reverse the\n    // order of the routes here to support behavior where the most general\n    // routes can be defined at the bottom of the route map.\n    _bindRoutes: function() {\n      if (!this.routes) return;\n      var routes = [];\n      for (var route in this.routes) {\n        routes.unshift([route, this.routes[route]]);\n      }\n      for (var i = 0, l = routes.length; i < l; i++) {\n        this.route(routes[i][0], routes[i][1], this[routes[i][1]]);\n      }\n    },\n\n    // Convert a route string into a regular expression, suitable for matching\n    // against the current location hash.\n    _routeToRegExp: function(route) {\n      route = route.replace(escapeRegExp, '\\\\$&')\n                   .replace(namedParam, '([^\\/]+)')\n                   .replace(splatParam, '(.*?)');\n      return new RegExp('^' + route + '$');\n    },\n\n    // Given a route, and a URL fragment that it matches, return the array of\n    // extracted parameters.\n    _extractParameters: function(route, fragment) {\n      return route.exec(fragment).slice(1);\n    }\n\n  });\n\n  // Backbone.History\n  // ----------------\n\n  // Handles cross-browser history management, based on URL fragments. If the\n  // browser does not support `onhashchange`, falls back to polling.\n  var History = Backbone.History = function() {\n    this.handlers = [];\n    _.bindAll(this, 'checkUrl');\n  };\n\n  // Cached regex for cleaning leading hashes and slashes .\n  var routeStripper = /^[#\\/]/;\n\n  // Cached regex for detecting MSIE.\n  var isExplorer = /msie [\\w.]+/;\n\n  // Has the history handling already been started?\n  History.started = false;\n\n  // Set up all inheritable **Backbone.History** properties and methods.\n  _.extend(History.prototype, Events, {\n\n    // The default interval to poll for hash changes, if necessary, is\n    // twenty times a second.\n    interval: 50,\n\n    // Gets the true hash value. Cannot use location.hash directly due to bug\n    // in Firefox where location.hash will always be decoded.\n    getHash: function(windowOverride) {\n      var loc = windowOverride ? windowOverride.location : window.location;\n      var match = loc.href.match(/#(.*)$/);\n      return match ? match[1] : '';\n    },\n\n    // Get the cross-browser normalized URL fragment, either from the URL,\n    // the hash, or the override.\n    getFragment: function(fragment, forcePushState) {\n      if (fragment == null) {\n        if (this._hasPushState || forcePushState) {\n          fragment = window.location.pathname;\n          var search = window.location.search;\n          if (search) fragment += search;\n        } else {\n          fragment = this.getHash();\n        }\n      }\n      if (!fragment.indexOf(this.options.root)) fragment = fragment.substr(this.options.root.length);\n      return fragment.replace(routeStripper, '');\n    },\n\n    // Start the hash change handling, returning `true` if the current URL matches\n    // an existing route, and `false` otherwise.\n    start: function(options) {\n      if (History.started) throw new Error(\"Backbone.history has already been started\");\n      // <METEOR>\n      if (typeof window === 'undefined')\n        throw new Error(\"Backbone.History is client-only, can't start on the server\");\n      // </METEOR>\n      History.started = true;\n\n      // Figure out the initial configuration. Do we need an iframe?\n      // Is pushState desired ... is it available?\n      this.options          = _.extend({}, {root: '/'}, this.options, options);\n      this._wantsHashChange = this.options.hashChange !== false;\n      this._wantsPushState  = !!this.options.pushState;\n      this._hasPushState    = !!(this.options.pushState && window.history && window.history.pushState);\n      var fragment          = this.getFragment();\n      var docMode           = document.documentMode;\n      var oldIE             = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));\n\n      if (oldIE) {\n        this.iframe = $('<iframe src=\"javascript:0\" tabindex=\"-1\" />').hide().appendTo('body')[0].contentWindow;\n        this.navigate(fragment);\n      }\n\n      // Depending on whether we're using pushState or hashes, and whether\n      // 'onhashchange' is supported, determine how we check the URL state.\n      if (this._hasPushState) {\n        $(window).bind('popstate', this.checkUrl);\n      } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) {\n        $(window).bind('hashchange', this.checkUrl);\n      } else if (this._wantsHashChange) {\n        this._checkUrlInterval = setInterval(this.checkUrl, this.interval);\n      }\n\n      // Determine if we need to change the base url, for a pushState link\n      // opened by a non-pushState browser.\n      this.fragment = fragment;\n      var loc = window.location;\n      var atRoot  = loc.pathname == this.options.root;\n\n      // If we've started off with a route from a `pushState`-enabled browser,\n      // but we're currently in a browser that doesn't support it...\n      if (this._wantsHashChange && this._wantsPushState && !this._hasPushState && !atRoot) {\n        this.fragment = this.getFragment(null, true);\n        window.location.replace(this.options.root + '#' + this.fragment);\n        // Return immediately as browser will do redirect to new url\n        return true;\n\n      // Or if we've started out with a hash-based route, but we're currently\n      // in a browser where it could be `pushState`-based instead...\n      } else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) {\n        this.fragment = this.getHash().replace(routeStripper, '');\n        window.history.replaceState({}, document.title, loc.protocol + '//' + loc.host + this.options.root + this.fragment);\n      }\n\n      if (!this.options.silent) {\n        return this.loadUrl();\n      }\n    },\n\n    // Disable Backbone.history, perhaps temporarily. Not useful in a real app,\n    // but possibly useful for unit testing Routers.\n    stop: function() {\n      $(window).unbind('popstate', this.checkUrl).unbind('hashchange', this.checkUrl);\n      clearInterval(this._checkUrlInterval);\n      History.started = false;\n    },\n\n    // Add a route to be tested when the fragment changes. Routes added later\n    // may override previous routes.\n    route: function(route, callback) {\n      this.handlers.unshift({route: route, callback: callback});\n    },\n\n    // Checks the current URL to see if it has changed, and if it has,\n    // calls `loadUrl`, normalizing across the hidden iframe.\n    checkUrl: function(e) {\n      var current = this.getFragment();\n      if (current == this.fragment && this.iframe) current = this.getFragment(this.getHash(this.iframe));\n      if (current == this.fragment) return false;\n      if (this.iframe) this.navigate(current);\n      this.loadUrl() || this.loadUrl(this.getHash());\n    },\n\n    // Attempt to load the current URL fragment. If a route succeeds with a\n    // match, returns `true`. If no defined routes matches the fragment,\n    // returns `false`.\n    loadUrl: function(fragmentOverride) {\n      var fragment = this.fragment = this.getFragment(fragmentOverride);\n      var matched = _.any(this.handlers, function(handler) {\n        if (handler.route.test(fragment)) {\n          handler.callback(fragment);\n          return true;\n        }\n      });\n      return matched;\n    },\n\n    // Save a fragment into the hash history, or replace the URL state if the\n    // 'replace' option is passed. You are responsible for properly URL-encoding\n    // the fragment in advance.\n    //\n    // The options object can contain `trigger: true` if you wish to have the\n    // route callback be fired (not usually desirable), or `replace: true`, if\n    // you wish to modify the current URL without adding an entry to the history.\n    navigate: function(fragment, options) {\n      if (!History.started) return false;\n      if (!options || options === true) options = {trigger: options};\n      var frag = (fragment || '').replace(routeStripper, '');\n      if (this.fragment == frag) return;\n\n      // If pushState is available, we use it to set the fragment as a real URL.\n      if (this._hasPushState) {\n        if (frag.indexOf(this.options.root) != 0) frag = this.options.root + frag;\n        this.fragment = frag;\n        window.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, frag);\n\n      // If hash changes haven't been explicitly disabled, update the hash\n      // fragment to store history.\n      } else if (this._wantsHashChange) {\n        this.fragment = frag;\n        this._updateHash(window.location, frag, options.replace);\n        if (this.iframe && (frag != this.getFragment(this.getHash(this.iframe)))) {\n          // Opening and closing the iframe tricks IE7 and earlier to push a history entry on hash-tag change.\n          // When replace is true, we don't want this.\n          if(!options.replace) this.iframe.document.open().close();\n          this._updateHash(this.iframe.location, frag, options.replace);\n        }\n\n      // If you've told us that you explicitly don't want fallback hashchange-\n      // based history, then `navigate` becomes a page refresh.\n      } else {\n        window.location.assign(this.options.root + fragment);\n      }\n      if (options.trigger) this.loadUrl(fragment);\n    },\n\n    // Update the hash location, either replacing the current entry, or adding\n    // a new one to the browser history.\n    _updateHash: function(location, fragment, replace) {\n      if (replace) {\n        location.replace(location.toString().replace(/(javascript:|#).*$/, '') + '#' + fragment);\n      } else {\n        location.hash = fragment;\n      }\n    }\n  });\n\n  // Backbone.View\n  // -------------\n\n  // Creating a Backbone.View creates its initial element outside of the DOM,\n  // if an existing element is not provided...\n  var View = Backbone.View = function(options) {\n    this.cid = _.uniqueId('view');\n    this._configure(options || {});\n    this._ensureElement();\n    this.initialize.apply(this, arguments);\n    this.delegateEvents();\n  };\n\n  // Cached regex to split keys for `delegate`.\n  var delegateEventSplitter = /^(\\S+)\\s*(.*)$/;\n\n  // List of view options to be merged as properties.\n  var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName'];\n\n  // Set up all inheritable **Backbone.View** properties and methods.\n  _.extend(View.prototype, Events, {\n\n    // The default `tagName` of a View's element is `\"div\"`.\n    tagName: 'div',\n\n    // jQuery delegate for element lookup, scoped to DOM elements within the\n    // current view. This should be prefered to global lookups where possible.\n    $: function(selector) {\n      return this.$el.find(selector);\n    },\n\n    // Initialize is an empty function by default. Override it with your own\n    // initialization logic.\n    initialize: function(){},\n\n    // **render** is the core function that your view should override, in order\n    // to populate its element (`this.el`), with the appropriate HTML. The\n    // convention is for **render** to always return `this`.\n    render: function() {\n      return this;\n    },\n\n    // Remove this view from the DOM. Note that the view isn't present in the\n    // DOM by default, so calling this method may be a no-op.\n    remove: function() {\n      this.$el.remove();\n      return this;\n    },\n\n    // For small amounts of DOM Elements, where a full-blown template isn't\n    // needed, use **make** to manufacture elements, one at a time.\n    //\n    //     var el = this.make('li', {'class': 'row'}, this.model.escape('title'));\n    //\n    make: function(tagName, attributes, content) {\n      var el = document.createElement(tagName);\n      if (attributes) $(el).attr(attributes);\n      if (content) $(el).html(content);\n      return el;\n    },\n\n    // Change the view's element (`this.el` property), including event\n    // re-delegation.\n    setElement: function(element, delegate) {\n      if (this.$el) this.undelegateEvents();\n      this.$el = (element instanceof $) ? element : $(element);\n      this.el = this.$el[0];\n      if (delegate !== false) this.delegateEvents();\n      return this;\n    },\n\n    // Set callbacks, where `this.events` is a hash of\n    //\n    // *{\"event selector\": \"callback\"}*\n    //\n    //     {\n    //       'mousedown .title':  'edit',\n    //       'click .button':     'save'\n    //       'click .open':       function(e) { ... }\n    //     }\n    //\n    // pairs. Callbacks will be bound to the view, with `this` set properly.\n    // Uses event delegation for efficiency.\n    // Omitting the selector binds the event to `this.el`.\n    // This only works for delegate-able events: not `focus`, `blur`, and\n    // not `change`, `submit`, and `reset` in Internet Explorer.\n    delegateEvents: function(events) {\n      if (!(events || (events = getValue(this, 'events')))) return;\n      this.undelegateEvents();\n      for (var key in events) {\n        var method = events[key];\n        if (!_.isFunction(method)) method = this[events[key]];\n        if (!method) throw new Error('Method \"' + events[key] + '\" does not exist');\n        var match = key.match(delegateEventSplitter);\n        var eventName = match[1], selector = match[2];\n        method = _.bind(method, this);\n        eventName += '.delegateEvents' + this.cid;\n        if (selector === '') {\n          this.$el.bind(eventName, method);\n        } else {\n          this.$el.delegate(selector, eventName, method);\n        }\n      }\n    },\n\n    // Clears all callbacks previously bound to the view with `delegateEvents`.\n    // You usually don't need to use this, but may wish to if you have multiple\n    // Backbone views attached to the same DOM element.\n    undelegateEvents: function() {\n      this.$el.unbind('.delegateEvents' + this.cid);\n    },\n\n    // Performs the initial configuration of a View with a set of options.\n    // Keys with special meaning *(model, collection, id, className)*, are\n    // attached directly to the view.\n    _configure: function(options) {\n      if (this.options) options = _.extend({}, this.options, options);\n      for (var i = 0, l = viewOptions.length; i < l; i++) {\n        var attr = viewOptions[i];\n        if (options[attr]) this[attr] = options[attr];\n      }\n      this.options = options;\n    },\n\n    // Ensure that the View has a DOM element to render into.\n    // If `this.el` is a string, pass it through `$()`, take the first\n    // matching element, and re-assign it to `el`. Otherwise, create\n    // an element from the `id`, `className` and `tagName` properties.\n    _ensureElement: function() {\n      if (!this.el) {\n        var attrs = getValue(this, 'attributes') || {};\n        if (this.id) attrs.id = this.id;\n        if (this.className) attrs['class'] = this.className;\n        this.setElement(this.make(this.tagName, attrs), false);\n      } else {\n        this.setElement(this.el, false);\n      }\n    }\n\n  });\n\n  // The self-propagating extend function that Backbone classes use.\n  var extend = function (protoProps, classProps) {\n    var child = inherits(this, protoProps, classProps);\n    child.extend = this.extend;\n    return child;\n  };\n\n  // Set up inheritance for the model, collection, and view.\n  Model.extend = Collection.extend = Router.extend = View.extend = extend;\n\n  // Backbone.sync\n  // -------------\n\n  // Map from CRUD to HTTP for our default `Backbone.sync` implementation.\n  var methodMap = {\n    'create': 'POST',\n    'update': 'PUT',\n    'delete': 'DELETE',\n    'read':   'GET'\n  };\n\n  // Override this function to change the manner in which Backbone persists\n  // models to the server. You will be passed the type of request, and the\n  // model in question. By default, makes a RESTful Ajax request\n  // to the model's `url()`. Some possible customizations could be:\n  //\n  // * Use `setTimeout` to batch rapid-fire updates into a single request.\n  // * Send up the models as XML instead of JSON.\n  // * Persist models via WebSockets instead of Ajax.\n  //\n  // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests\n  // as `POST`, with a `_method` parameter containing the true HTTP method,\n  // as well as all requests with the body as `application/x-www-form-urlencoded`\n  // instead of `application/json` with the model in a param named `model`.\n  // Useful when interfacing with server-side languages like **PHP** that make\n  // it difficult to read the body of `PUT` requests.\n  Backbone.sync = function(method, model, options) {\n    var type = methodMap[method];\n\n    // Default options, unless specified.\n    options || (options = {});\n\n    // Default JSON-request options.\n    var params = {type: type, dataType: 'json'};\n\n    // Ensure that we have a URL.\n    if (!options.url) {\n      params.url = getValue(model, 'url') || urlError();\n    }\n\n    // Ensure that we have the appropriate request data.\n    if (!options.data && model && (method == 'create' || method == 'update')) {\n      params.contentType = 'application/json';\n      params.data = JSON.stringify(model.toJSON());\n    }\n\n    // For older servers, emulate JSON by encoding the request into an HTML-form.\n    if (Backbone.emulateJSON) {\n      params.contentType = 'application/x-www-form-urlencoded';\n      params.data = params.data ? {model: params.data} : {};\n    }\n\n    // For older servers, emulate HTTP by mimicking the HTTP method with `_method`\n    // And an `X-HTTP-Method-Override` header.\n    if (Backbone.emulateHTTP) {\n      if (type === 'PUT' || type === 'DELETE') {\n        if (Backbone.emulateJSON) params.data._method = type;\n        params.type = 'POST';\n        params.beforeSend = function(xhr) {\n          xhr.setRequestHeader('X-HTTP-Method-Override', type);\n        };\n      }\n    }\n\n    // Don't process data on a non-GET request.\n    if (params.type !== 'GET' && !Backbone.emulateJSON) {\n      params.processData = false;\n    }\n\n    // Make the request, allowing the user to override any Ajax options.\n    return $.ajax(_.extend(params, options));\n  };\n\n  // Wrap an optional error callback with a fallback error event.\n  Backbone.wrapError = function(onError, originalModel, options) {\n    return function(model, resp) {\n      resp = model === originalModel ? resp : model;\n      if (onError) {\n        onError(originalModel, resp, options);\n      } else {\n        originalModel.trigger('error', originalModel, resp, options);\n      }\n    };\n  };\n\n  // Helpers\n  // -------\n\n  // Shared empty constructor function to aid in prototype-chain creation.\n  var ctor = function(){};\n\n  // Helper function to correctly set up the prototype chain, for subclasses.\n  // Similar to `goog.inherits`, but uses a hash of prototype properties and\n  // class properties to be extended.\n  var inherits = function(parent, protoProps, staticProps) {\n    var child;\n\n    // The constructor function for the new subclass is either defined by you\n    // (the \"constructor\" property in your `extend` definition), or defaulted\n    // by us to simply call the parent's constructor.\n    if (protoProps && protoProps.hasOwnProperty('constructor')) {\n      child = protoProps.constructor;\n    } else {\n      child = function(){ parent.apply(this, arguments); };\n    }\n\n    // Inherit class (static) properties from parent.\n    _.extend(child, parent);\n\n    // Set the prototype chain to inherit from `parent`, without calling\n    // `parent`'s constructor function.\n    ctor.prototype = parent.prototype;\n    child.prototype = new ctor();\n\n    // Add prototype properties (instance properties) to the subclass,\n    // if supplied.\n    if (protoProps) _.extend(child.prototype, protoProps);\n\n    // Add static properties to the constructor function, if supplied.\n    if (staticProps) _.extend(child, staticProps);\n\n    // Correctly set child's `prototype.constructor`.\n    child.prototype.constructor = child;\n\n    // Set a convenience property in case the parent's prototype is needed later.\n    child.__super__ = parent.prototype;\n\n    return child;\n  };\n\n  // Helper function to get a value from a Backbone object as a property\n  // or as a function.\n  var getValue = function(object, prop) {\n    if (!(object && object[prop])) return null;\n    return _.isFunction(object[prop]) ? object[prop]() : object[prop];\n  };\n\n  // Throw an error when a URL is needed, and none is supplied.\n  var urlError = function() {\n    throw new Error('A \"url\" property or function must be specified');\n  };\n\n}).call(this);\n"
  },
  {
    "path": "packages/deprecated/backbone/package.js",
    "content": "Package.describe({\n  summary: \"A minimalist client-side MVC framework\",\n  version: \"1.0.0\"\n});\n\nPackage.onUse(function (api) {\n  // XXX Backbone requires either jquery or zepto\n  api.use([\"jquery\", \"json\", \"underscore\"]);\n\n  api.addFiles(\"backbone.js\");\n});\n"
  },
  {
    "path": "packages/deprecated/bootstrap/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/deprecated/bootstrap/css/bootstrap-override.css",
    "content": "/*\n * XXX Hack to make bootstrap work when bundled. This needs to be included\n * _after_ the standard bootstrap css files.\n *\n * After being bundled, all CSS is minified and served from the \"/\" dir.\n * Thus, we need to provide absolute paths to the icons here.\n */\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  background-image: url(\"/packages/bootstrap/img/glyphicons-halflings.png\");\n}\n/*\n * Selectors borrowed from bootstrap.css.  For all releases of bootstrap, when\n * we upgrade, update this file to borrow the selectors from where bootstrap.css\n * references any .png.  When we update to using .less instead, use the less\n * directives in a less file instead.\n */\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:focus > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > li > a:focus > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:focus > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"],\n.dropdown-submenu:focus > a > [class*=\" icon-\"] {\n  background-image: url(\"/packages/bootstrap/img/glyphicons-halflings-white.png\");\n}\n"
  },
  {
    "path": "packages/deprecated/bootstrap/css/bootstrap-responsive.css",
    "content": "/*!\n * Bootstrap Responsive v2.3.0\n *\n * Copyright 2012 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 @twitter by @mdo and @fat.\n */\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\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.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n@-ms-viewport {\n  width: device-width;\n}\n\n.hidden {\n  display: none;\n  visibility: hidden;\n}\n\n.visible-phone {\n  display: none !important;\n}\n\n.visible-tablet {\n  display: none !important;\n}\n\n.hidden-desktop {\n  display: none !important;\n}\n\n.visible-desktop {\n  display: inherit !important;\n}\n\n@media (min-width: 768px) and (max-width: 979px) {\n  .hidden-desktop {\n    display: inherit !important;\n  }\n  .visible-desktop {\n    display: none !important ;\n  }\n  .visible-tablet {\n    display: inherit !important;\n  }\n  .hidden-tablet {\n    display: none !important;\n  }\n}\n\n@media (max-width: 767px) {\n  .hidden-desktop {\n    display: inherit !important;\n  }\n  .visible-desktop {\n    display: none !important;\n  }\n  .visible-phone {\n    display: inherit !important;\n  }\n  .hidden-phone {\n    display: none !important;\n  }\n}\n\n.visible-print {\n  display: none !important;\n}\n\n@media print {\n  .visible-print {\n    display: inherit !important;\n  }\n  .hidden-print {\n    display: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .row {\n    margin-left: -30px;\n    *zoom: 1;\n  }\n  .row:before,\n  .row:after {\n    display: table;\n    line-height: 0;\n    content: \"\";\n  }\n  .row:after {\n    clear: both;\n  }\n  [class*=\"span\"] {\n    float: left;\n    min-height: 1px;\n    margin-left: 30px;\n  }\n  .container,\n  .navbar-static-top .container,\n  .navbar-fixed-top .container,\n  .navbar-fixed-bottom .container {\n    width: 1170px;\n  }\n  .span12 {\n    width: 1170px;\n  }\n  .span11 {\n    width: 1070px;\n  }\n  .span10 {\n    width: 970px;\n  }\n  .span9 {\n    width: 870px;\n  }\n  .span8 {\n    width: 770px;\n  }\n  .span7 {\n    width: 670px;\n  }\n  .span6 {\n    width: 570px;\n  }\n  .span5 {\n    width: 470px;\n  }\n  .span4 {\n    width: 370px;\n  }\n  .span3 {\n    width: 270px;\n  }\n  .span2 {\n    width: 170px;\n  }\n  .span1 {\n    width: 70px;\n  }\n  .offset12 {\n    margin-left: 1230px;\n  }\n  .offset11 {\n    margin-left: 1130px;\n  }\n  .offset10 {\n    margin-left: 1030px;\n  }\n  .offset9 {\n    margin-left: 930px;\n  }\n  .offset8 {\n    margin-left: 830px;\n  }\n  .offset7 {\n    margin-left: 730px;\n  }\n  .offset6 {\n    margin-left: 630px;\n  }\n  .offset5 {\n    margin-left: 530px;\n  }\n  .offset4 {\n    margin-left: 430px;\n  }\n  .offset3 {\n    margin-left: 330px;\n  }\n  .offset2 {\n    margin-left: 230px;\n  }\n  .offset1 {\n    margin-left: 130px;\n  }\n  .row-fluid {\n    width: 100%;\n    *zoom: 1;\n  }\n  .row-fluid:before,\n  .row-fluid:after {\n    display: table;\n    line-height: 0;\n    content: \"\";\n  }\n  .row-fluid:after {\n    clear: both;\n  }\n  .row-fluid [class*=\"span\"] {\n    display: block;\n    float: left;\n    width: 100%;\n    min-height: 30px;\n    margin-left: 2.564102564102564%;\n    *margin-left: 2.5109110747408616%;\n    -webkit-box-sizing: border-box;\n       -moz-box-sizing: border-box;\n            box-sizing: border-box;\n  }\n  .row-fluid [class*=\"span\"]:first-child {\n    margin-left: 0;\n  }\n  .row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n    margin-left: 2.564102564102564%;\n  }\n  .row-fluid .span12 {\n    width: 100%;\n    *width: 99.94680851063829%;\n  }\n  .row-fluid .span11 {\n    width: 91.45299145299145%;\n    *width: 91.39979996362975%;\n  }\n  .row-fluid .span10 {\n    width: 82.90598290598291%;\n    *width: 82.8527914166212%;\n  }\n  .row-fluid .span9 {\n    width: 74.35897435897436%;\n    *width: 74.30578286961266%;\n  }\n  .row-fluid .span8 {\n    width: 65.81196581196582%;\n    *width: 65.75877432260411%;\n  }\n  .row-fluid .span7 {\n    width: 57.26495726495726%;\n    *width: 57.21176577559556%;\n  }\n  .row-fluid .span6 {\n    width: 48.717948717948715%;\n    *width: 48.664757228587014%;\n  }\n  .row-fluid .span5 {\n    width: 40.17094017094017%;\n    *width: 40.11774868157847%;\n  }\n  .row-fluid .span4 {\n    width: 31.623931623931625%;\n    *width: 31.570740134569924%;\n  }\n  .row-fluid .span3 {\n    width: 23.076923076923077%;\n    *width: 23.023731587561375%;\n  }\n  .row-fluid .span2 {\n    width: 14.52991452991453%;\n    *width: 14.476723040552828%;\n  }\n  .row-fluid .span1 {\n    width: 5.982905982905983%;\n    *width: 5.929714493544281%;\n  }\n  .row-fluid .offset12 {\n    margin-left: 105.12820512820512%;\n    *margin-left: 105.02182214948171%;\n  }\n  .row-fluid .offset12:first-child {\n    margin-left: 102.56410256410257%;\n    *margin-left: 102.45771958537915%;\n  }\n  .row-fluid .offset11 {\n    margin-left: 96.58119658119658%;\n    *margin-left: 96.47481360247316%;\n  }\n  .row-fluid .offset11:first-child {\n    margin-left: 94.01709401709402%;\n    *margin-left: 93.91071103837061%;\n  }\n  .row-fluid .offset10 {\n    margin-left: 88.03418803418803%;\n    *margin-left: 87.92780505546462%;\n  }\n  .row-fluid .offset10:first-child {\n    margin-left: 85.47008547008548%;\n    *margin-left: 85.36370249136206%;\n  }\n  .row-fluid .offset9 {\n    margin-left: 79.48717948717949%;\n    *margin-left: 79.38079650845607%;\n  }\n  .row-fluid .offset9:first-child {\n    margin-left: 76.92307692307693%;\n    *margin-left: 76.81669394435352%;\n  }\n  .row-fluid .offset8 {\n    margin-left: 70.94017094017094%;\n    *margin-left: 70.83378796144753%;\n  }\n  .row-fluid .offset8:first-child {\n    margin-left: 68.37606837606839%;\n    *margin-left: 68.26968539734497%;\n  }\n  .row-fluid .offset7 {\n    margin-left: 62.393162393162385%;\n    *margin-left: 62.28677941443899%;\n  }\n  .row-fluid .offset7:first-child {\n    margin-left: 59.82905982905982%;\n    *margin-left: 59.72267685033642%;\n  }\n  .row-fluid .offset6 {\n    margin-left: 53.84615384615384%;\n    *margin-left: 53.739770867430444%;\n  }\n  .row-fluid .offset6:first-child {\n    margin-left: 51.28205128205128%;\n    *margin-left: 51.175668303327875%;\n  }\n  .row-fluid .offset5 {\n    margin-left: 45.299145299145295%;\n    *margin-left: 45.1927623204219%;\n  }\n  .row-fluid .offset5:first-child {\n    margin-left: 42.73504273504273%;\n    *margin-left: 42.62865975631933%;\n  }\n  .row-fluid .offset4 {\n    margin-left: 36.75213675213675%;\n    *margin-left: 36.645753773413354%;\n  }\n  .row-fluid .offset4:first-child {\n    margin-left: 34.18803418803419%;\n    *margin-left: 34.081651209310785%;\n  }\n  .row-fluid .offset3 {\n    margin-left: 28.205128205128204%;\n    *margin-left: 28.0987452264048%;\n  }\n  .row-fluid .offset3:first-child {\n    margin-left: 25.641025641025642%;\n    *margin-left: 25.53464266230224%;\n  }\n  .row-fluid .offset2 {\n    margin-left: 19.65811965811966%;\n    *margin-left: 19.551736679396257%;\n  }\n  .row-fluid .offset2:first-child {\n    margin-left: 17.094017094017094%;\n    *margin-left: 16.98763411529369%;\n  }\n  .row-fluid .offset1 {\n    margin-left: 11.11111111111111%;\n    *margin-left: 11.004728132387708%;\n  }\n  .row-fluid .offset1:first-child {\n    margin-left: 8.547008547008547%;\n    *margin-left: 8.440625568285142%;\n  }\n  input,\n  textarea,\n  .uneditable-input {\n    margin-left: 0;\n  }\n  .controls-row [class*=\"span\"] + [class*=\"span\"] {\n    margin-left: 30px;\n  }\n  input.span12,\n  textarea.span12,\n  .uneditable-input.span12 {\n    width: 1156px;\n  }\n  input.span11,\n  textarea.span11,\n  .uneditable-input.span11 {\n    width: 1056px;\n  }\n  input.span10,\n  textarea.span10,\n  .uneditable-input.span10 {\n    width: 956px;\n  }\n  input.span9,\n  textarea.span9,\n  .uneditable-input.span9 {\n    width: 856px;\n  }\n  input.span8,\n  textarea.span8,\n  .uneditable-input.span8 {\n    width: 756px;\n  }\n  input.span7,\n  textarea.span7,\n  .uneditable-input.span7 {\n    width: 656px;\n  }\n  input.span6,\n  textarea.span6,\n  .uneditable-input.span6 {\n    width: 556px;\n  }\n  input.span5,\n  textarea.span5,\n  .uneditable-input.span5 {\n    width: 456px;\n  }\n  input.span4,\n  textarea.span4,\n  .uneditable-input.span4 {\n    width: 356px;\n  }\n  input.span3,\n  textarea.span3,\n  .uneditable-input.span3 {\n    width: 256px;\n  }\n  input.span2,\n  textarea.span2,\n  .uneditable-input.span2 {\n    width: 156px;\n  }\n  input.span1,\n  textarea.span1,\n  .uneditable-input.span1 {\n    width: 56px;\n  }\n  .thumbnails {\n    margin-left: -30px;\n  }\n  .thumbnails > li {\n    margin-left: 30px;\n  }\n  .row-fluid .thumbnails {\n    margin-left: 0;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 979px) {\n  .row {\n    margin-left: -20px;\n    *zoom: 1;\n  }\n  .row:before,\n  .row:after {\n    display: table;\n    line-height: 0;\n    content: \"\";\n  }\n  .row:after {\n    clear: both;\n  }\n  [class*=\"span\"] {\n    float: left;\n    min-height: 1px;\n    margin-left: 20px;\n  }\n  .container,\n  .navbar-static-top .container,\n  .navbar-fixed-top .container,\n  .navbar-fixed-bottom .container {\n    width: 724px;\n  }\n  .span12 {\n    width: 724px;\n  }\n  .span11 {\n    width: 662px;\n  }\n  .span10 {\n    width: 600px;\n  }\n  .span9 {\n    width: 538px;\n  }\n  .span8 {\n    width: 476px;\n  }\n  .span7 {\n    width: 414px;\n  }\n  .span6 {\n    width: 352px;\n  }\n  .span5 {\n    width: 290px;\n  }\n  .span4 {\n    width: 228px;\n  }\n  .span3 {\n    width: 166px;\n  }\n  .span2 {\n    width: 104px;\n  }\n  .span1 {\n    width: 42px;\n  }\n  .offset12 {\n    margin-left: 764px;\n  }\n  .offset11 {\n    margin-left: 702px;\n  }\n  .offset10 {\n    margin-left: 640px;\n  }\n  .offset9 {\n    margin-left: 578px;\n  }\n  .offset8 {\n    margin-left: 516px;\n  }\n  .offset7 {\n    margin-left: 454px;\n  }\n  .offset6 {\n    margin-left: 392px;\n  }\n  .offset5 {\n    margin-left: 330px;\n  }\n  .offset4 {\n    margin-left: 268px;\n  }\n  .offset3 {\n    margin-left: 206px;\n  }\n  .offset2 {\n    margin-left: 144px;\n  }\n  .offset1 {\n    margin-left: 82px;\n  }\n  .row-fluid {\n    width: 100%;\n    *zoom: 1;\n  }\n  .row-fluid:before,\n  .row-fluid:after {\n    display: table;\n    line-height: 0;\n    content: \"\";\n  }\n  .row-fluid:after {\n    clear: both;\n  }\n  .row-fluid [class*=\"span\"] {\n    display: block;\n    float: left;\n    width: 100%;\n    min-height: 30px;\n    margin-left: 2.7624309392265194%;\n    *margin-left: 2.709239449864817%;\n    -webkit-box-sizing: border-box;\n       -moz-box-sizing: border-box;\n            box-sizing: border-box;\n  }\n  .row-fluid [class*=\"span\"]:first-child {\n    margin-left: 0;\n  }\n  .row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n    margin-left: 2.7624309392265194%;\n  }\n  .row-fluid .span12 {\n    width: 100%;\n    *width: 99.94680851063829%;\n  }\n  .row-fluid .span11 {\n    width: 91.43646408839778%;\n    *width: 91.38327259903608%;\n  }\n  .row-fluid .span10 {\n    width: 82.87292817679558%;\n    *width: 82.81973668743387%;\n  }\n  .row-fluid .span9 {\n    width: 74.30939226519337%;\n    *width: 74.25620077583166%;\n  }\n  .row-fluid .span8 {\n    width: 65.74585635359117%;\n    *width: 65.69266486422946%;\n  }\n  .row-fluid .span7 {\n    width: 57.18232044198895%;\n    *width: 57.12912895262725%;\n  }\n  .row-fluid .span6 {\n    width: 48.61878453038674%;\n    *width: 48.56559304102504%;\n  }\n  .row-fluid .span5 {\n    width: 40.05524861878453%;\n    *width: 40.00205712942283%;\n  }\n  .row-fluid .span4 {\n    width: 31.491712707182323%;\n    *width: 31.43852121782062%;\n  }\n  .row-fluid .span3 {\n    width: 22.92817679558011%;\n    *width: 22.87498530621841%;\n  }\n  .row-fluid .span2 {\n    width: 14.3646408839779%;\n    *width: 14.311449394616199%;\n  }\n  .row-fluid .span1 {\n    width: 5.801104972375691%;\n    *width: 5.747913483013988%;\n  }\n  .row-fluid .offset12 {\n    margin-left: 105.52486187845304%;\n    *margin-left: 105.41847889972962%;\n  }\n  .row-fluid .offset12:first-child {\n    margin-left: 102.76243093922652%;\n    *margin-left: 102.6560479605031%;\n  }\n  .row-fluid .offset11 {\n    margin-left: 96.96132596685082%;\n    *margin-left: 96.8549429881274%;\n  }\n  .row-fluid .offset11:first-child {\n    margin-left: 94.1988950276243%;\n    *margin-left: 94.09251204890089%;\n  }\n  .row-fluid .offset10 {\n    margin-left: 88.39779005524862%;\n    *margin-left: 88.2914070765252%;\n  }\n  .row-fluid .offset10:first-child {\n    margin-left: 85.6353591160221%;\n    *margin-left: 85.52897613729868%;\n  }\n  .row-fluid .offset9 {\n    margin-left: 79.8342541436464%;\n    *margin-left: 79.72787116492299%;\n  }\n  .row-fluid .offset9:first-child {\n    margin-left: 77.07182320441989%;\n    *margin-left: 76.96544022569647%;\n  }\n  .row-fluid .offset8 {\n    margin-left: 71.2707182320442%;\n    *margin-left: 71.16433525332079%;\n  }\n  .row-fluid .offset8:first-child {\n    margin-left: 68.50828729281768%;\n    *margin-left: 68.40190431409427%;\n  }\n  .row-fluid .offset7 {\n    margin-left: 62.70718232044199%;\n    *margin-left: 62.600799341718584%;\n  }\n  .row-fluid .offset7:first-child {\n    margin-left: 59.94475138121547%;\n    *margin-left: 59.838368402492065%;\n  }\n  .row-fluid .offset6 {\n    margin-left: 54.14364640883978%;\n    *margin-left: 54.037263430116376%;\n  }\n  .row-fluid .offset6:first-child {\n    margin-left: 51.38121546961326%;\n    *margin-left: 51.27483249088986%;\n  }\n  .row-fluid .offset5 {\n    margin-left: 45.58011049723757%;\n    *margin-left: 45.47372751851417%;\n  }\n  .row-fluid .offset5:first-child {\n    margin-left: 42.81767955801105%;\n    *margin-left: 42.71129657928765%;\n  }\n  .row-fluid .offset4 {\n    margin-left: 37.01657458563536%;\n    *margin-left: 36.91019160691196%;\n  }\n  .row-fluid .offset4:first-child {\n    margin-left: 34.25414364640884%;\n    *margin-left: 34.14776066768544%;\n  }\n  .row-fluid .offset3 {\n    margin-left: 28.45303867403315%;\n    *margin-left: 28.346655695309746%;\n  }\n  .row-fluid .offset3:first-child {\n    margin-left: 25.69060773480663%;\n    *margin-left: 25.584224756083227%;\n  }\n  .row-fluid .offset2 {\n    margin-left: 19.88950276243094%;\n    *margin-left: 19.783119783707537%;\n  }\n  .row-fluid .offset2:first-child {\n    margin-left: 17.12707182320442%;\n    *margin-left: 17.02068884448102%;\n  }\n  .row-fluid .offset1 {\n    margin-left: 11.32596685082873%;\n    *margin-left: 11.219583872105325%;\n  }\n  .row-fluid .offset1:first-child {\n    margin-left: 8.56353591160221%;\n    *margin-left: 8.457152932878806%;\n  }\n  input,\n  textarea,\n  .uneditable-input {\n    margin-left: 0;\n  }\n  .controls-row [class*=\"span\"] + [class*=\"span\"] {\n    margin-left: 20px;\n  }\n  input.span12,\n  textarea.span12,\n  .uneditable-input.span12 {\n    width: 710px;\n  }\n  input.span11,\n  textarea.span11,\n  .uneditable-input.span11 {\n    width: 648px;\n  }\n  input.span10,\n  textarea.span10,\n  .uneditable-input.span10 {\n    width: 586px;\n  }\n  input.span9,\n  textarea.span9,\n  .uneditable-input.span9 {\n    width: 524px;\n  }\n  input.span8,\n  textarea.span8,\n  .uneditable-input.span8 {\n    width: 462px;\n  }\n  input.span7,\n  textarea.span7,\n  .uneditable-input.span7 {\n    width: 400px;\n  }\n  input.span6,\n  textarea.span6,\n  .uneditable-input.span6 {\n    width: 338px;\n  }\n  input.span5,\n  textarea.span5,\n  .uneditable-input.span5 {\n    width: 276px;\n  }\n  input.span4,\n  textarea.span4,\n  .uneditable-input.span4 {\n    width: 214px;\n  }\n  input.span3,\n  textarea.span3,\n  .uneditable-input.span3 {\n    width: 152px;\n  }\n  input.span2,\n  textarea.span2,\n  .uneditable-input.span2 {\n    width: 90px;\n  }\n  input.span1,\n  textarea.span1,\n  .uneditable-input.span1 {\n    width: 28px;\n  }\n}\n\n@media (max-width: 767px) {\n  body {\n    padding-right: 20px;\n    padding-left: 20px;\n  }\n  .navbar-fixed-top,\n  .navbar-fixed-bottom,\n  .navbar-static-top {\n    margin-right: -20px;\n    margin-left: -20px;\n  }\n  .container-fluid {\n    padding: 0;\n  }\n  .dl-horizontal dt {\n    float: none;\n    width: auto;\n    clear: none;\n    text-align: left;\n  }\n  .dl-horizontal dd {\n    margin-left: 0;\n  }\n  .container {\n    width: auto;\n  }\n  .row-fluid {\n    width: 100%;\n  }\n  .row,\n  .thumbnails {\n    margin-left: 0;\n  }\n  .thumbnails > li {\n    float: none;\n    margin-left: 0;\n  }\n  [class*=\"span\"],\n  .uneditable-input[class*=\"span\"],\n  .row-fluid [class*=\"span\"] {\n    display: block;\n    float: none;\n    width: 100%;\n    margin-left: 0;\n    -webkit-box-sizing: border-box;\n       -moz-box-sizing: border-box;\n            box-sizing: border-box;\n  }\n  .span12,\n  .row-fluid .span12 {\n    width: 100%;\n    -webkit-box-sizing: border-box;\n       -moz-box-sizing: border-box;\n            box-sizing: border-box;\n  }\n  .row-fluid [class*=\"offset\"]:first-child {\n    margin-left: 0;\n  }\n  .input-large,\n  .input-xlarge,\n  .input-xxlarge,\n  input[class*=\"span\"],\n  select[class*=\"span\"],\n  textarea[class*=\"span\"],\n  .uneditable-input {\n    display: block;\n    width: 100%;\n    min-height: 30px;\n    -webkit-box-sizing: border-box;\n       -moz-box-sizing: border-box;\n            box-sizing: border-box;\n  }\n  .input-prepend input,\n  .input-append input,\n  .input-prepend input[class*=\"span\"],\n  .input-append input[class*=\"span\"] {\n    display: inline-block;\n    width: auto;\n  }\n  .controls-row [class*=\"span\"] + [class*=\"span\"] {\n    margin-left: 0;\n  }\n  .modal {\n    position: fixed;\n    top: 20px;\n    right: 20px;\n    left: 20px;\n    width: auto;\n    margin: 0;\n  }\n  .modal.fade {\n    top: -100px;\n  }\n  .modal.fade.in {\n    top: 20px;\n  }\n}\n\n@media (max-width: 480px) {\n  .nav-collapse {\n    -webkit-transform: translate3d(0, 0, 0);\n  }\n  .page-header h1 small {\n    display: block;\n    line-height: 20px;\n  }\n  input[type=\"checkbox\"],\n  input[type=\"radio\"] {\n    border: 1px solid #ccc;\n  }\n  .form-horizontal .control-label {\n    float: none;\n    width: auto;\n    padding-top: 0;\n    text-align: left;\n  }\n  .form-horizontal .controls {\n    margin-left: 0;\n  }\n  .form-horizontal .control-list {\n    padding-top: 0;\n  }\n  .form-horizontal .form-actions {\n    padding-right: 10px;\n    padding-left: 10px;\n  }\n  .media .pull-left,\n  .media .pull-right {\n    display: block;\n    float: none;\n    margin-bottom: 10px;\n  }\n  .media-object {\n    margin-right: 0;\n    margin-left: 0;\n  }\n  .modal {\n    top: 10px;\n    right: 10px;\n    left: 10px;\n  }\n  .modal-header .close {\n    padding: 10px;\n    margin: -10px;\n  }\n  .carousel-caption {\n    position: static;\n  }\n}\n\n@media (max-width: 979px) {\n  body {\n    padding-top: 0;\n  }\n  .navbar-fixed-top,\n  .navbar-fixed-bottom {\n    position: static;\n  }\n  .navbar-fixed-top {\n    margin-bottom: 20px;\n  }\n  .navbar-fixed-bottom {\n    margin-top: 20px;\n  }\n  .navbar-fixed-top .navbar-inner,\n  .navbar-fixed-bottom .navbar-inner {\n    padding: 5px;\n  }\n  .navbar .container {\n    width: auto;\n    padding: 0;\n  }\n  .navbar .brand {\n    padding-right: 10px;\n    padding-left: 10px;\n    margin: 0 0 0 -5px;\n  }\n  .nav-collapse {\n    clear: both;\n  }\n  .nav-collapse .nav {\n    float: none;\n    margin: 0 0 10px;\n  }\n  .nav-collapse .nav > li {\n    float: none;\n  }\n  .nav-collapse .nav > li > a {\n    margin-bottom: 2px;\n  }\n  .nav-collapse .nav > .divider-vertical {\n    display: none;\n  }\n  .nav-collapse .nav .nav-header {\n    color: #777777;\n    text-shadow: none;\n  }\n  .nav-collapse .nav > li > a,\n  .nav-collapse .dropdown-menu a {\n    padding: 9px 15px;\n    font-weight: bold;\n    color: #777777;\n    -webkit-border-radius: 3px;\n       -moz-border-radius: 3px;\n            border-radius: 3px;\n  }\n  .nav-collapse .btn {\n    padding: 4px 10px 4px;\n    font-weight: normal;\n    -webkit-border-radius: 4px;\n       -moz-border-radius: 4px;\n            border-radius: 4px;\n  }\n  .nav-collapse .dropdown-menu li + li a {\n    margin-bottom: 2px;\n  }\n  .nav-collapse .nav > li > a:hover,\n  .nav-collapse .nav > li > a:focus,\n  .nav-collapse .dropdown-menu a:hover,\n  .nav-collapse .dropdown-menu a:focus {\n    background-color: #f2f2f2;\n  }\n  .navbar-inverse .nav-collapse .nav > li > a,\n  .navbar-inverse .nav-collapse .dropdown-menu a {\n    color: #999999;\n  }\n  .navbar-inverse .nav-collapse .nav > li > a:hover,\n  .navbar-inverse .nav-collapse .nav > li > a:focus,\n  .navbar-inverse .nav-collapse .dropdown-menu a:hover,\n  .navbar-inverse .nav-collapse .dropdown-menu a:focus {\n    background-color: #111111;\n  }\n  .nav-collapse.in .btn-group {\n    padding: 0;\n    margin-top: 5px;\n  }\n  .nav-collapse .dropdown-menu {\n    position: static;\n    top: auto;\n    left: auto;\n    display: none;\n    float: none;\n    max-width: none;\n    padding: 0;\n    margin: 0 15px;\n    background-color: transparent;\n    border: none;\n    -webkit-border-radius: 0;\n       -moz-border-radius: 0;\n            border-radius: 0;\n    -webkit-box-shadow: none;\n       -moz-box-shadow: none;\n            box-shadow: none;\n  }\n  .nav-collapse .open > .dropdown-menu {\n    display: block;\n  }\n  .nav-collapse .dropdown-menu:before,\n  .nav-collapse .dropdown-menu:after {\n    display: none;\n  }\n  .nav-collapse .dropdown-menu .divider {\n    display: none;\n  }\n  .nav-collapse .nav > li > .dropdown-menu:before,\n  .nav-collapse .nav > li > .dropdown-menu:after {\n    display: none;\n  }\n  .nav-collapse .navbar-form,\n  .nav-collapse .navbar-search {\n    float: none;\n    padding: 10px 15px;\n    margin: 10px 0;\n    border-top: 1px solid #f2f2f2;\n    border-bottom: 1px solid #f2f2f2;\n    -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n       -moz-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  .navbar-inverse .nav-collapse .navbar-form,\n  .navbar-inverse .nav-collapse .navbar-search {\n    border-top-color: #111111;\n    border-bottom-color: #111111;\n  }\n  .navbar .nav-collapse .nav.pull-right {\n    float: none;\n    margin-left: 0;\n  }\n  .nav-collapse,\n  .nav-collapse.collapse {\n    height: 0;\n    overflow: hidden;\n  }\n  .navbar .btn-navbar {\n    display: block;\n  }\n  .navbar-static .navbar-inner {\n    padding-right: 10px;\n    padding-left: 10px;\n  }\n}\n\n@media (min-width: 980px) {\n  .nav-collapse.collapse {\n    height: auto !important;\n    overflow: visible !important;\n  }\n}\n"
  },
  {
    "path": "packages/deprecated/bootstrap/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.3.0\n *\n * Copyright 2012 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 @twitter by @mdo and @fat.\n */\n\n.clearfix {\n  *zoom: 1;\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\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.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\naudio:not([controls]) {\n  display: none;\n}\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\na:hover,\na:active {\n  outline: 0;\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  width: auto\\9;\n  height: auto;\n  max-width: 100%;\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\n\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\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-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\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: 0.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}\n\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\n\na {\n  color: #0088cc;\n  text-decoration: none;\n}\n\na:hover,\na:focus {\n  color: #005580;\n  text-decoration: underline;\n}\n\n.img-rounded {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.img-circle {\n  -webkit-border-radius: 500px;\n     -moz-border-radius: 500px;\n          border-radius: 500px;\n}\n\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row:after {\n  clear: both;\n}\n\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.span12 {\n  width: 940px;\n}\n\n.span11 {\n  width: 860px;\n}\n\n.span10 {\n  width: 780px;\n}\n\n.span9 {\n  width: 700px;\n}\n\n.span8 {\n  width: 620px;\n}\n\n.span7 {\n  width: 540px;\n}\n\n.span6 {\n  width: 460px;\n}\n\n.span5 {\n  width: 380px;\n}\n\n.span4 {\n  width: 300px;\n}\n\n.span3 {\n  width: 220px;\n}\n\n.span2 {\n  width: 140px;\n}\n\n.span1 {\n  width: 60px;\n}\n\n.offset12 {\n  margin-left: 980px;\n}\n\n.offset11 {\n  margin-left: 900px;\n}\n\n.offset10 {\n  margin-left: 820px;\n}\n\n.offset9 {\n  margin-left: 740px;\n}\n\n.offset8 {\n  margin-left: 660px;\n}\n\n.offset7 {\n  margin-left: 580px;\n}\n\n.offset6 {\n  margin-left: 500px;\n}\n\n.offset5 {\n  margin-left: 420px;\n}\n\n.offset4 {\n  margin-left: 340px;\n}\n\n.offset3 {\n  margin-left: 260px;\n}\n\n.offset2 {\n  margin-left: 180px;\n}\n\n.offset1 {\n  margin-left: 100px;\n}\n\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.row-fluid:after {\n  clear: both;\n}\n\n.row-fluid [class*=\"span\"] {\n  display: block;\n  float: left;\n  width: 100%;\n  min-height: 30px;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n\n.row-fluid .controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 2.127659574468085%;\n}\n\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.container-fluid:after {\n  clear: both;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\n\nsmall {\n  font-size: 85%;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nem {\n  font-style: italic;\n}\n\ncite {\n  font-style: normal;\n}\n\n.muted {\n  color: #999999;\n}\n\na.muted:hover,\na.muted:focus {\n  color: #808080;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\na.text-warning:hover,\na.text-warning:focus {\n  color: #a47e3c;\n}\n\n.text-error {\n  color: #b94a48;\n}\n\na.text-error:hover,\na.text-error:focus {\n  color: #953b39;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\na.text-info:hover,\na.text-info:focus {\n  color: #2d6987;\n}\n\n.text-success {\n  color: #468847;\n}\n\na.text-success:hover,\na.text-success:focus {\n  color: #356635;\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  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 20px;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  line-height: 40px;\n}\n\nh1 {\n  font-size: 38.5px;\n}\n\nh2 {\n  font-size: 31.5px;\n}\n\nh3 {\n  font-size: 24.5px;\n}\n\nh4 {\n  font-size: 17.5px;\n}\n\nh5 {\n  font-size: 14px;\n}\n\nh6 {\n  font-size: 11.9px;\n}\n\nh1 small {\n  font-size: 24.5px;\n}\n\nh2 small {\n  font-size: 17.5px;\n}\n\nh3 small {\n  font-size: 14px;\n}\n\nh4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\n\nli {\n  line-height: 20px;\n}\n\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n}\n\nul.inline > li,\nol.inline > li {\n  display: inline-block;\n  *display: inline;\n  padding-right: 5px;\n  padding-left: 5px;\n  *zoom: 1;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 20px;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 10px;\n}\n\n.dl-horizontal {\n  *zoom: 1;\n}\n\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.dl-horizontal:after {\n  clear: both;\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\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\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: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  margin-bottom: 0;\n  font-size: 17.5px;\n  font-weight: 300;\n  line-height: 1.25;\n}\n\nblockquote small {\n  display: block;\n  line-height: 20px;\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: 20px;\n}\n\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  white-space: nowrap;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\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;\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\nform {\n  margin: 0 0 20px;\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: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\n\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  vertical-align: middle;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\n\ntextarea {\n  height: auto;\n}\n\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-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 linear 0.2s, box-shadow linear 0.2s;\n     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n       -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n          transition: border linear 0.2s, box-shadow linear 0.2s;\n}\n\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n     -moz-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\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  *margin-top: 0;\n  line-height: normal;\n}\n\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\n\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\n\nselect {\n  width: 220px;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect:focus,\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\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n}\n\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\n\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\n\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.radio,\n.checkbox {\n  min-height: 20px;\n  padding-left: 20px;\n}\n\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n\n.input-mini {\n  width: 60px;\n}\n\n.input-small {\n  width: 90px;\n}\n\n.input-medium {\n  width: 150px;\n}\n\n.input-large {\n  width: 210px;\n}\n\n.input-xlarge {\n  width: 270px;\n}\n\n.input-xxlarge {\n  width: 530px;\n}\n\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\n\ninput.span12,\ntextarea.span12,\n.uneditable-input.span12 {\n  width: 926px;\n}\n\ninput.span11,\ntextarea.span11,\n.uneditable-input.span11 {\n  width: 846px;\n}\n\ninput.span10,\ntextarea.span10,\n.uneditable-input.span10 {\n  width: 766px;\n}\n\ninput.span9,\ntextarea.span9,\n.uneditable-input.span9 {\n  width: 686px;\n}\n\ninput.span8,\ntextarea.span8,\n.uneditable-input.span8 {\n  width: 606px;\n}\n\ninput.span7,\ntextarea.span7,\n.uneditable-input.span7 {\n  width: 526px;\n}\n\ninput.span6,\ntextarea.span6,\n.uneditable-input.span6 {\n  width: 446px;\n}\n\ninput.span5,\ntextarea.span5,\n.uneditable-input.span5 {\n  width: 366px;\n}\n\ninput.span4,\ntextarea.span4,\n.uneditable-input.span4 {\n  width: 286px;\n}\n\ninput.span3,\ntextarea.span3,\n.uneditable-input.span3 {\n  width: 206px;\n}\n\ninput.span2,\ntextarea.span2,\n.uneditable-input.span2 {\n  width: 126px;\n}\n\ninput.span1,\ntextarea.span1,\n.uneditable-input.span1 {\n  width: 46px;\n}\n\n.controls-row {\n  *zoom: 1;\n}\n\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.controls-row:after {\n  clear: both;\n}\n\n.controls-row [class*=\"span\"],\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n.control-group.warning .control-label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-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.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n     -moz-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.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.control-group.error .control-label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-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.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n     -moz-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.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.control-group.success .control-label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-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.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n     -moz-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.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.control-group.info .control-label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n     -moz-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.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\n\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\n\ninput:focus:invalid:focus,\ntextarea:focus:invalid:focus,\nselect:focus:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n     -moz-box-shadow: 0 0 6px #f8b9b7;\n          box-shadow: 0 0 6px #f8b9b7;\n}\n\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.help-block,\n.help-inline {\n  color: #595959;\n}\n\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  padding-left: 5px;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.input-append,\n.input-prepend {\n  display: inline-block;\n  margin-bottom: 10px;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input,\n.input-append .dropdown-menu,\n.input-prepend .dropdown-menu,\n.input-append .popover,\n.input-prepend .popover {\n  font-size: 14px;\n}\n\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  vertical-align: top;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn,\n.input-append .btn-group > .dropdown-toggle,\n.input-prepend .btn-group > .dropdown-toggle {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-append input + .btn-group .btn:last-child,\n.input-append select + .btn-group .btn:last-child,\n.input-append .uneditable-input + .btn-group .btn:last-child {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-append .add-on,\n.input-append .btn,\n.input-append .btn-group {\n  margin-left: -1px;\n}\n\n.input-append .add-on:last-child,\n.input-append .btn:last-child,\n.input-append .btn-group:last-child > .dropdown-toggle {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.input-prepend.input-append input + .btn-group .btn,\n.input-prepend.input-append select + .btn-group .btn,\n.input-prepend.input-append .uneditable-input + .btn-group .btn {\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.input-prepend.input-append .btn-group:first-child {\n  margin-left: 0;\n}\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n/* Allow for input prepend/append in search forms */\n\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n     -moz-border-radius: 0 14px 14px 0;\n          border-radius: 0 14px 14px 0;\n}\n\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n     -moz-border-radius: 14px 0 0 14px;\n          border-radius: 14px 0 0 14px;\n}\n\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n.control-group {\n  margin-bottom: 10px;\n}\n\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-horizontal .control-group:after {\n  clear: both;\n}\n\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block,\n.form-horizontal .uneditable-input + .help-block,\n.form-horizontal .input-prepend + .help-block,\n.form-horizontal .input-append + .help-block {\n  margin-top: 10px;\n}\n\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table th {\n  font-weight: bold;\n}\n\n.table thead th {\n  vertical-align: bottom;\n}\n\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\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 th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n\n.table-bordered thead:first-child tr:first-child > th:first-child,\n.table-bordered tbody:first-child tr:first-child > td:first-child,\n.table-bordered tbody:first-child tr:first-child > th:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered thead:first-child tr:first-child > th:last-child,\n.table-bordered tbody:first-child tr:first-child > td:last-child,\n.table-bordered tbody:first-child tr:first-child > th:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:first-child,\n.table-bordered tbody:last-child tr:last-child > td:first-child,\n.table-bordered tbody:last-child tr:last-child > th:first-child,\n.table-bordered tfoot:last-child tr:last-child > td:first-child,\n.table-bordered tfoot:last-child tr:last-child > th:first-child {\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.table-bordered thead:last-child tr:last-child > th:last-child,\n.table-bordered tbody:last-child tr:last-child > td:last-child,\n.table-bordered tbody:last-child tr:last-child > th:last-child,\n.table-bordered tfoot:last-child tr:last-child > td:last-child,\n.table-bordered tfoot:last-child tr:last-child > th:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {\n  -webkit-border-bottom-left-radius: 0;\n          border-bottom-left-radius: 0;\n  -moz-border-radius-bottomleft: 0;\n}\n\n.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 0;\n          border-bottom-right-radius: 0;\n  -moz-border-radius-bottomright: 0;\n}\n\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\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 td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n\n.table td.span1,\n.table th.span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n\n.table td.span2,\n.table th.span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n\n.table td.span3,\n.table th.span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n\n.table td.span4,\n.table th.span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n\n.table td.span5,\n.table th.span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n\n.table td.span6,\n.table th.span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n\n.table td.span7,\n.table th.span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n\n.table td.span8,\n.table th.span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n\n.table td.span9,\n.table th.span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n\n.table td.span10,\n.table th.span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n\n.table td.span11,\n.table th.span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n\n.table td.span12,\n.table th.span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n\n.table tbody tr.success > td {\n  background-color: #dff0d8;\n}\n\n.table tbody tr.error > td {\n  background-color: #f2dede;\n}\n\n.table tbody tr.warning > td {\n  background-color: #fcf8e3;\n}\n\n.table tbody tr.info > td {\n  background-color: #d9edf7;\n}\n\n.table-hover tbody tr.success:hover > td {\n  background-color: #d0e9c6;\n}\n\n.table-hover tbody tr.error:hover > td {\n  background-color: #ebcccc;\n}\n\n.table-hover tbody tr.warning:hover > td {\n  background-color: #faf2cc;\n}\n\n.table-hover tbody tr.info:hover > td {\n  background-color: #c4e3f3;\n}\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 1px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n}\n\n/* White icons with optional class, or on hover/focus/active states of certain elements */\n\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:focus > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > li > a:focus > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:focus > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"],\n.dropdown-submenu:focus > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n\n.icon-glass {\n  background-position: 0      0;\n}\n\n.icon-music {\n  background-position: -24px 0;\n}\n\n.icon-search {\n  background-position: -48px 0;\n}\n\n.icon-envelope {\n  background-position: -72px 0;\n}\n\n.icon-heart {\n  background-position: -96px 0;\n}\n\n.icon-star {\n  background-position: -120px 0;\n}\n\n.icon-star-empty {\n  background-position: -144px 0;\n}\n\n.icon-user {\n  background-position: -168px 0;\n}\n\n.icon-film {\n  background-position: -192px 0;\n}\n\n.icon-th-large {\n  background-position: -216px 0;\n}\n\n.icon-th {\n  background-position: -240px 0;\n}\n\n.icon-th-list {\n  background-position: -264px 0;\n}\n\n.icon-ok {\n  background-position: -288px 0;\n}\n\n.icon-remove {\n  background-position: -312px 0;\n}\n\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n\n.icon-off {\n  background-position: -384px 0;\n}\n\n.icon-signal {\n  background-position: -408px 0;\n}\n\n.icon-cog {\n  background-position: -432px 0;\n}\n\n.icon-trash {\n  background-position: -456px 0;\n}\n\n.icon-home {\n  background-position: 0 -24px;\n}\n\n.icon-file {\n  background-position: -24px -24px;\n}\n\n.icon-time {\n  background-position: -48px -24px;\n}\n\n.icon-road {\n  background-position: -72px -24px;\n}\n\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n\n.icon-download {\n  background-position: -120px -24px;\n}\n\n.icon-upload {\n  background-position: -144px -24px;\n}\n\n.icon-inbox {\n  background-position: -168px -24px;\n}\n\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n\n.icon-repeat {\n  background-position: -216px -24px;\n}\n\n.icon-refresh {\n  background-position: -240px -24px;\n}\n\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n\n.icon-lock {\n  background-position: -287px -24px;\n}\n\n.icon-flag {\n  background-position: -312px -24px;\n}\n\n.icon-headphones {\n  background-position: -336px -24px;\n}\n\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n\n.icon-barcode {\n  background-position: -456px -24px;\n}\n\n.icon-tag {\n  background-position: 0 -48px;\n}\n\n.icon-tags {\n  background-position: -25px -48px;\n}\n\n.icon-book {\n  background-position: -48px -48px;\n}\n\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n\n.icon-print {\n  background-position: -96px -48px;\n}\n\n.icon-camera {\n  background-position: -120px -48px;\n}\n\n.icon-font {\n  background-position: -144px -48px;\n}\n\n.icon-bold {\n  background-position: -167px -48px;\n}\n\n.icon-italic {\n  background-position: -192px -48px;\n}\n\n.icon-text-height {\n  background-position: -216px -48px;\n}\n\n.icon-text-width {\n  background-position: -240px -48px;\n}\n\n.icon-align-left {\n  background-position: -264px -48px;\n}\n\n.icon-align-center {\n  background-position: -288px -48px;\n}\n\n.icon-align-right {\n  background-position: -312px -48px;\n}\n\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n\n.icon-list {\n  background-position: -360px -48px;\n}\n\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n\n.icon-picture {\n  background-position: -456px -48px;\n}\n\n.icon-pencil {\n  background-position: 0 -72px;\n}\n\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n\n.icon-adjust {\n  background-position: -48px -72px;\n}\n\n.icon-tint {\n  background-position: -72px -72px;\n}\n\n.icon-edit {\n  background-position: -96px -72px;\n}\n\n.icon-share {\n  background-position: -120px -72px;\n}\n\n.icon-check {\n  background-position: -144px -72px;\n}\n\n.icon-move {\n  background-position: -168px -72px;\n}\n\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n\n.icon-backward {\n  background-position: -240px -72px;\n}\n\n.icon-play {\n  background-position: -264px -72px;\n}\n\n.icon-pause {\n  background-position: -288px -72px;\n}\n\n.icon-stop {\n  background-position: -312px -72px;\n}\n\n.icon-forward {\n  background-position: -336px -72px;\n}\n\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n\n.icon-eject {\n  background-position: -408px -72px;\n}\n\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n\n.icon-plus {\n  background-position: -408px -96px;\n}\n\n.icon-minus {\n  background-position: -433px -96px;\n}\n\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n\n.icon-gift {\n  background-position: -24px -120px;\n}\n\n.icon-leaf {\n  background-position: -48px -120px;\n}\n\n.icon-fire {\n  background-position: -72px -120px;\n}\n\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n\n.icon-plane {\n  background-position: -168px -120px;\n}\n\n.icon-calendar {\n  background-position: -192px -120px;\n}\n\n.icon-random {\n  width: 16px;\n  background-position: -216px -120px;\n}\n\n.icon-comment {\n  background-position: -240px -120px;\n}\n\n.icon-magnet {\n  background-position: -264px -120px;\n}\n\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n\n.icon-retweet {\n  background-position: -336px -120px;\n}\n\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n\n.icon-folder-close {\n  width: 16px;\n  background-position: -384px -120px;\n}\n\n.icon-folder-open {\n  width: 16px;\n  background-position: -408px -120px;\n}\n\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n\n.icon-hdd {\n  background-position: 0 -144px;\n}\n\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n\n.icon-bell {\n  background-position: -48px -144px;\n}\n\n.icon-certificate {\n  background-position: -72px -144px;\n}\n\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n\n.icon-globe {\n  background-position: -336px -144px;\n}\n\n.icon-wrench {\n  background-position: -360px -144px;\n}\n\n.icon-tasks {\n  background-position: -384px -144px;\n}\n\n.icon-filter {\n  background-position: -408px -144px;\n}\n\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\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 #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\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  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.dropdown-menu > li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus,\n.dropdown-submenu:hover > a,\n.dropdown-submenu:focus > a {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', 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: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', 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: default;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open {\n  *z-index: 1000;\n}\n\n.open > .dropdown-menu {\n  display: block;\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.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n     -moz-border-radius: 0 6px 6px 6px;\n          border-radius: 0 6px 6px 6px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  -webkit-border-radius: 5px 5px 5px 0;\n     -moz-border-radius: 5px 5px 5px 0;\n          border-radius: 5px 5px 5px 0;\n}\n\n.dropdown-submenu > a:after {\n  display: block;\n  float: right;\n  width: 0;\n  height: 0;\n  margin-top: 5px;\n  margin-right: -10px;\n  border-color: transparent;\n  border-left-color: #cccccc;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  content: \" \";\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.dropdown .dropdown-menu .nav-header {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\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  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n     -moz-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  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n     -moz-transition: opacity 0.15s linear;\n       -o-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n     -moz-transition: height 0.35s ease;\n       -o-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.collapse.in {\n  height: auto;\n}\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\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.4;\n  filter: alpha(opacity=40);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.btn {\n  display: inline-block;\n  *display: inline;\n  padding: 4px 12px;\n  margin-bottom: 0;\n  *margin-left: .3em;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  cursor: pointer;\n  background-color: #f5f5f5;\n  *background-color: #e6e6e6;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  border: 1px solid #cccccc;\n  *border: 0;\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  border-bottom-color: #b3b3b3;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn:hover,\n.btn:focus,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n\n.btn:first-child {\n  *margin-left: 0;\n}\n\n.btn:hover,\n.btn:focus {\n  color: #333333;\n  text-decoration: none;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n     -moz-transition: background-position 0.1s linear;\n       -o-transition: background-position 0.1s linear;\n          transition: background-position 0.1s linear;\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.active,\n.btn:active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-large {\n  padding: 11px 19px;\n  font-size: 17.5px;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n.btn-small {\n  padding: 2px 10px;\n  font-size: 11.9px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n.btn-mini {\n  padding: 0 6px;\n  font-size: 10.5px;\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\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.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  *background-color: #0044cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:focus,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  *background-color: #f89406;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:focus,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  *background-color: #bd362f;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:focus,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  *background-color: #51a351;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:focus,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  *background-color: #2f96b4;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:focus,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  *background-color: #222222;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-inverse:hover,\n.btn-inverse:focus,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link {\n  color: #0088cc;\n  cursor: pointer;\n  border-color: transparent;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-link:hover,\n.btn-link:focus {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover,\n.btn-link[disabled]:focus {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-group {\n  position: relative;\n  display: inline-block;\n  *display: inline;\n  *margin-left: .3em;\n  font-size: 0;\n  white-space: nowrap;\n  vertical-align: middle;\n  *zoom: 1;\n}\n\n.btn-group:first-child {\n  *margin-left: 0;\n}\n\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-toolbar {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-size: 0;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: 14px;\n}\n\n.btn-group > .btn-mini {\n  font-size: 10.5px;\n}\n\n.btn-group > .btn-small {\n  font-size: 11.9px;\n}\n\n.btn-group > .btn-large {\n  font-size: 17.5px;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\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-top: 5px;\n  padding-right: 8px;\n  *padding-bottom: 5px;\n  padding-left: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group > .btn-mini + .dropdown-toggle {\n  *padding-top: 2px;\n  padding-right: 5px;\n  *padding-bottom: 2px;\n  padding-left: 5px;\n}\n\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  *padding-top: 7px;\n  padding-right: 12px;\n  *padding-bottom: 7px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n\n.btn-large .caret {\n  margin-top: 6px;\n}\n\n.btn-large .caret {\n  border-top-width: 5px;\n  border-right-width: 5px;\n  border-left-width: 5px;\n}\n\n.btn-mini .caret,\n.btn-small .caret {\n  margin-top: 8px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.btn-group-vertical > .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.btn-group-vertical > .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n     -moz-border-radius: 6px 6px 0 0;\n          border-radius: 6px 6px 0 0;\n}\n\n.btn-group-vertical > .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.alert,\n.alert h4 {\n  color: #c09853;\n}\n\n.alert h4 {\n  margin: 0;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success h4 {\n  color: #468847;\n}\n\n.alert-danger,\n.alert-error {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger h4,\n.alert-error h4 {\n  color: #b94a48;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info h4 {\n  color: #3a87ad;\n}\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\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.nav {\n  margin-bottom: 20px;\n  margin-left: 0;\n  list-style: none;\n}\n\n.nav > li > a {\n  display: block;\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 > a > img {\n  max-width: none;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n.nav-list {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 0;\n}\n\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-right: -15px;\n  margin-left: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n\n.nav-list > .active > a,\n.nav-list > .active > a:hover,\n.nav-list > .active > a:focus {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n     -moz-border-radius: 4px 4px 0 0;\n          border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover,\n.nav-tabs > li > a:focus {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover,\n.nav-tabs > .active > a:focus {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n     -moz-border-radius: 5px;\n          border-radius: 5px;\n}\n\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover,\n.nav-pills > .active > a:focus {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n\n.nav-tabs.nav-stacked > li > a:hover,\n.nav-tabs.nav-stacked > li > a:focus {\n  z-index: 2;\n  border-color: #ddd;\n}\n\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n}\n\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.nav .dropdown-toggle .caret {\n  margin-top: 6px;\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n}\n\n.nav .dropdown-toggle:hover .caret,\n.nav .dropdown-toggle:focus .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n\n/* move down carets for tabs */\n\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.nav > .dropdown.active > a:hover,\n.nav > .dropdown.active > a:focus {\n  cursor: pointer;\n}\n\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover,\n.nav > li.dropdown.open.active > a:focus {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret,\n.nav li.dropdown.open a:focus .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tabs-stacked .open > a:hover,\n.tabs-stacked .open > a:focus {\n  border-color: #999999;\n}\n\n.tabbable {\n  *zoom: 1;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content {\n  overflow: auto;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\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.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover,\n.tabs-below > .nav-tabs > li > a:focus {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover,\n.tabs-below > .nav-tabs > .active > a:focus {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover,\n.tabs-left > .nav-tabs > li > a:focus {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover,\n.tabs-left > .nav-tabs .active > a:focus {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover,\n.tabs-right > .nav-tabs > li > a:focus {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover,\n.tabs-right > .nav-tabs .active > a:focus {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.nav > .disabled > a {\n  color: #999999;\n}\n\n.nav > .disabled > a:hover,\n.nav > .disabled > a:focus {\n  text-decoration: none;\n  cursor: default;\n  background-color: transparent;\n}\n\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  margin-bottom: 20px;\n  overflow: visible;\n}\n\n.navbar-inner {\n  min-height: 40px;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n}\n\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-inner:after {\n  clear: both;\n}\n\n.navbar .container {\n  width: auto;\n}\n\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n.navbar .brand {\n  display: block;\n  float: left;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .brand:hover,\n.navbar .brand:focus {\n  text-decoration: none;\n}\n\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n  color: #777777;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover,\n.navbar-link:focus {\n  color: #333333;\n}\n\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-right: 1px solid #ffffff;\n  border-left: 1px solid #f2f2f2;\n}\n\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn,\n.navbar .input-prepend .btn-group,\n.navbar .input-append .btn-group {\n  margin-top: 0;\n}\n\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.navbar-form:after {\n  clear: both;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 5px;\n  white-space: nowrap;\n}\n\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.navbar-search .search-query {\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\n          border-radius: 15px;\n}\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0;\n}\n\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\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  margin-bottom: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-right: 0;\n  padding-left: 0;\n  -webkit-border-radius: 0;\n     -moz-border-radius: 0;\n          border-radius: 0;\n}\n\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n\n.navbar .nav > li {\n  float: left;\n}\n\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  color: #333333;\n  text-decoration: none;\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  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-right: 5px;\n  margin-left: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  *background-color: #e5e5e5;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:focus,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n     -moz-border-radius: 1px;\n          border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n.navbar .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  left: 9px;\n  display: inline-block;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.navbar .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  left: 10px;\n  display: inline-block;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  top: auto;\n  bottom: -7px;\n  border-top: 7px solid #ccc;\n  border-bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.2);\n}\n\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  top: auto;\n  bottom: -6px;\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n}\n\n.navbar .nav li.dropdown > a:hover .caret,\n.navbar .nav li.dropdown > a:focus .caret {\n  border-top-color: #333333;\n  border-bottom-color: #333333;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #555555;\n  background-color: #e5e5e5;\n}\n\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  border-color: #252525;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n}\n\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover,\n.navbar-inverse .brand:focus,\n.navbar-inverse .nav > li > a:focus {\n  color: #ffffff;\n}\n\n.navbar-inverse .brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover,\n.navbar-inverse .navbar-link:focus {\n  color: #ffffff;\n}\n\n.navbar-inverse .divider-vertical {\n  border-right-color: #222222;\n  border-left-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  color: #ffffff;\n  background-color: #111111;\n}\n\n.navbar-inverse .nav li.dropdown > a:hover .caret,\n.navbar-inverse .nav li.dropdown > a:focus .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n     -moz-transition: none;\n       -o-transition: none;\n          transition: none;\n}\n\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  outline: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n}\n\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  *background-color: #040404;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:focus,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n  *display: inline;\n  text-shadow: 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n\n.breadcrumb > li > .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  margin: 20px 0;\n}\n\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  margin-bottom: 0;\n  margin-left: 0;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  *zoom: 1;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.pagination ul > li {\n  display: inline;\n}\n\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 20px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination ul > li > a:hover,\n.pagination ul > li > a:focus,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover,\n.pagination ul > .disabled > a:focus {\n  color: #999999;\n  cursor: default;\n  background-color: transparent;\n}\n\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-bottom-left-radius: 4px;\n          border-bottom-left-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n          border-top-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-top-right-radius: 4px;\n          border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n          border-bottom-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n\n.pagination-centered {\n  text-align: center;\n}\n\n.pagination-right {\n  text-align: right;\n}\n\n.pagination-large ul > li > a,\n.pagination-large ul > li > span {\n  padding: 11px 19px;\n  font-size: 17.5px;\n}\n\n.pagination-large ul > li:first-child > a,\n.pagination-large ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 6px;\n          border-bottom-left-radius: 6px;\n  -webkit-border-top-left-radius: 6px;\n          border-top-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  -moz-border-radius-topleft: 6px;\n}\n\n.pagination-large ul > li:last-child > a,\n.pagination-large ul > li:last-child > span {\n  -webkit-border-top-right-radius: 6px;\n          border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n          border-bottom-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  -moz-border-radius-bottomright: 6px;\n}\n\n.pagination-mini ul > li:first-child > a,\n.pagination-small ul > li:first-child > a,\n.pagination-mini ul > li:first-child > span,\n.pagination-small ul > li:first-child > span {\n  -webkit-border-bottom-left-radius: 3px;\n          border-bottom-left-radius: 3px;\n  -webkit-border-top-left-radius: 3px;\n          border-top-left-radius: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  -moz-border-radius-topleft: 3px;\n}\n\n.pagination-mini ul > li:last-child > a,\n.pagination-small ul > li:last-child > a,\n.pagination-mini ul > li:last-child > span,\n.pagination-small ul > li:last-child > span {\n  -webkit-border-top-right-radius: 3px;\n          border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n          border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n}\n\n.pagination-small ul > li > a,\n.pagination-small ul > li > span {\n  padding: 2px 10px;\n  font-size: 11.9px;\n}\n\n.pagination-mini ul > li > a,\n.pagination-mini ul > li > span {\n  padding: 0 6px;\n  font-size: 10.5px;\n}\n\n.pager {\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n  *zoom: 1;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  line-height: 0;\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: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n     -moz-border-radius: 15px;\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: default;\n  background-color: #fff;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.modal {\n  position: fixed;\n  top: 10%;\n  left: 50%;\n  z-index: 1050;\n  width: 560px;\n  margin-left: -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding-box;\n          background-clip: padding-box;\n}\n\n.modal.fade {\n  top: -25%;\n  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;\n     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;\n       -o-transition: opacity 0.3s linear, top 0.3s ease-out;\n          transition: opacity 0.3s linear, top 0.3s ease-out;\n}\n\n.modal.fade.in {\n  top: 10%;\n}\n\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.modal-header .close {\n  margin-top: 2px;\n}\n\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n\n.modal-body {\n  position: relative;\n  max-height: 400px;\n  padding: 15px;\n  overflow-y: auto;\n}\n\n.modal-form {\n  margin-bottom: 0;\n}\n\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n     -moz-border-radius: 0 0 6px 6px;\n          border-radius: 0 0 6px 6px;\n  *zoom: 1;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n     -moz-box-shadow: inset 0 1px 0 #ffffff;\n          box-shadow: inset 0 1px 0 #ffffff;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  line-height: 0;\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.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  font-size: 11px;\n  line-height: 1.4;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\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: 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\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.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.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 #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\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  -webkit-border-radius: 5px 5px 0 0;\n     -moz-border-radius: 5px 5px 0 0;\n          border-radius: 5px 5px 0 0;\n}\n\n.popover-title:empty {\n  display: none;\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: #999;\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}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, 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}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999;\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}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999;\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}\n\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.thumbnails:after {\n  clear: both;\n}\n\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n     -moz-transition: all 0.2s ease-in-out;\n       -o-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\na.thumbnail:hover,\na.thumbnail:focus {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\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  margin-left: 0;\n  list-style: none;\n}\n\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n}\n\n.label {\n  -webkit-border-radius: 3px;\n     -moz-border-radius: 3px;\n          border-radius: 3px;\n}\n\n.badge {\n  padding-right: 9px;\n  padding-left: 9px;\n  -webkit-border-radius: 9px;\n     -moz-border-radius: 9px;\n          border-radius: 9px;\n}\n\n.label:empty,\n.badge:empty {\n  display: none;\n}\n\na.label:hover,\na.label:focus,\na.badge:hover,\na.badge:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\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: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\n          border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n     -moz-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  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-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-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n     -moz-transition: width 0.6s ease;\n       -o-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n\n.progress-striped .bar {\n  background-color: #149bdf;\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: -o-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  -webkit-background-size: 40px 40px;\n     -moz-background-size: 40px 40px;\n       -o-background-size: 40px 40px;\n          background-size: 40px 40px;\n}\n\n.progress.active .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-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\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: -o-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-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\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: -o-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-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n\n.progress-info.progress-striped .bar,\n.progress-striped .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: -o-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-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\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: -o-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  -webkit-border-radius: 4px;\n     -moz-border-radius: 4px;\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}\n\n.accordion-toggle {\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  margin-bottom: 20px;\n  line-height: 1;\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     -moz-transition: 0.6s ease-in-out left;\n       -o-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  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: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.right {\n  right: 15px;\n  left: auto;\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-indicators {\n  position: absolute;\n  top: 15px;\n  right: 15px;\n  z-index: 5;\n  margin: 0;\n  list-style: none;\n}\n\n.carousel-indicators li {\n  display: block;\n  float: left;\n  width: 10px;\n  height: 10px;\n  margin-left: 5px;\n  text-indent: -999px;\n  background-color: #ccc;\n  background-color: rgba(255, 255, 255, 0.25);\n  border-radius: 5px;\n}\n\n.carousel-indicators .active {\n  background-color: #fff;\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel-caption h4,\n.carousel-caption p {\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel-caption p {\n  margin-bottom: 0;\n}\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n     -moz-border-radius: 6px;\n          border-radius: 6px;\n}\n\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  letter-spacing: -1px;\n  color: inherit;\n}\n\n.hero-unit li {\n  line-height: 30px;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none;\n}\n\n.show {\n  display: block;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "packages/deprecated/bootstrap/js/bootstrap.js",
    "content": "/* ===================================================\n * bootstrap-transition.js v2.3.0\n * http://twitter.github.com/bootstrap/javascript.html#transitions\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 ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n  /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)\n   * ======================================================= */\n\n  $(function () {\n\n    $.support.transition = (function () {\n\n      var transitionEnd = (function () {\n\n        var el = document.createElement('bootstrap')\n          , transEndEventNames = {\n               'WebkitTransition' : 'webkitTransitionEnd'\n            ,  'MozTransition'    : 'transitionend'\n            ,  'OTransition'      : 'oTransitionEnd otransitionend'\n            ,  'transition'       : 'transitionend'\n            }\n          , name\n\n        for (name in transEndEventNames){\n          if (el.style[name] !== undefined) {\n            return transEndEventNames[name]\n          }\n        }\n\n      }())\n\n      return transitionEnd && {\n        end: transitionEnd\n      }\n\n    })()\n\n  })\n\n}(window.jQuery);/* ==========================================================\n * bootstrap-alert.js v2.3.0\n * http://twitter.github.com/bootstrap/javascript.html#alerts\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 ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* ALERT CLASS DEFINITION\n  * ====================== */\n\n  var dismiss = '[data-dismiss=\"alert\"]'\n    , Alert = function (el) {\n        $(el).on('click', dismiss, this.close)\n      }\n\n  Alert.prototype.close = function (e) {\n    var $this = $(this)\n      , selector = $this.attr('data-target')\n      , $parent\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    $parent = $(selector)\n\n    e && e.preventDefault()\n\n    $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())\n\n    $parent.trigger(e = $.Event('close'))\n\n    if (e.isDefaultPrevented()) return\n\n    $parent.removeClass('in')\n\n    function removeElement() {\n      $parent\n        .trigger('closed')\n        .remove()\n    }\n\n    $.support.transition && $parent.hasClass('fade') ?\n      $parent.on($.support.transition.end, removeElement) :\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        , data = $this.data('alert')\n      if (!data) $this.data('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.alert.data-api', dismiss, Alert.prototype.close)\n\n}(window.jQuery);/* ============================================================\n * bootstrap-button.js v2.3.0\n * http://twitter.github.com/bootstrap/javascript.html#buttons\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 ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* BUTTON PUBLIC CLASS DEFINITION\n  * ============================== */\n\n  var Button = function (element, options) {\n    this.$element = $(element)\n    this.options = $.extend({}, $.fn.button.defaults, options)\n  }\n\n  Button.prototype.setState = function (state) {\n    var d = 'disabled'\n      , $el = this.$element\n      , data = $el.data()\n      , val = $el.is('input') ? 'val' : 'html'\n\n    state = state + 'Text'\n    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-radio\"]')\n\n    $parent && $parent\n      .find('.active')\n      .removeClass('active')\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        , data = $this.data('button')\n        , options = typeof option == 'object' && option\n      if (!data) $this.data('button', (data = new Button(this, options)))\n      if (option == 'toggle') data.toggle()\n      else if (option) data.setState(option)\n    })\n  }\n\n  $.fn.button.defaults = {\n    loadingText: 'loading...'\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.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  })\n\n}(window.jQuery);/* ==========================================================\n * bootstrap-carousel.js v2.3.0\n * http://twitter.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 ($) {\n\n  \"use strict\"; // jshint ;_;\n\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.options.pause == 'hover' && this.$element\n      .on('mouseenter', $.proxy(this.pause, this))\n      .on('mouseleave', $.proxy(this.cycle, this))\n  }\n\n  Carousel.prototype = {\n\n    cycle: function (e) {\n      if (!e) this.paused = false\n      if (this.interval) clearInterval(this.interval);\n      this.options.interval\n        && !this.paused\n        && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))\n      return this\n    }\n\n  , getActiveIndex: function () {\n      this.$active = this.$element.find('.item.active')\n      this.$items = this.$active.parent().children()\n      return this.$items.index(this.$active)\n    }\n\n  , to: function (pos) {\n      var activeIndex = this.getActiveIndex()\n        , that = this\n\n      if (pos > (this.$items.length - 1) || pos < 0) return\n\n      if (this.sliding) {\n        return this.$element.one('slid', function () {\n          that.to(pos)\n        })\n      }\n\n      if (activeIndex == pos) {\n        return this.pause().cycle()\n      }\n\n      return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))\n    }\n\n  , pause: function (e) {\n      if (!e) this.paused = true\n      if (this.$element.find('.next, .prev').length && $.support.transition.end) {\n        this.$element.trigger($.support.transition.end)\n        this.cycle()\n      }\n      clearInterval(this.interval)\n      this.interval = null\n      return this\n    }\n\n  , next: function () {\n      if (this.sliding) return\n      return this.slide('next')\n    }\n\n  , prev: function () {\n      if (this.sliding) return\n      return this.slide('prev')\n    }\n\n  , slide: function (type, next) {\n      var $active = this.$element.find('.item.active')\n        , $next = next || $active[type]()\n        , isCycling = this.interval\n        , direction = type == 'next' ? 'left' : 'right'\n        , fallback  = type == 'next' ? 'first' : 'last'\n        , that = this\n        , e\n\n      this.sliding = true\n\n      isCycling && this.pause()\n\n      $next = $next.length ? $next : this.$element.find('.item')[fallback]()\n\n      e = $.Event('slide', {\n        relatedTarget: $next[0]\n      , direction: direction\n      })\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        this.$element.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      } 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\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        , data = $this.data('carousel')\n        , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)\n        , action = typeof option == 'string' ? option : options.slide\n      if (!data) $this.data('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.defaults = {\n    interval: 5000\n  , pause: 'hover'\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 /* CAROUSEL DATA-API\n  * ================= */\n\n  $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {\n    var $this = $(this), href\n      , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n      , options = $.extend({}, $target.data(), $this.data())\n      , slideIndex\n\n    $target.carousel(options)\n\n    if (slideIndex = $this.attr('data-slide-to')) {\n      $target.data('carousel').pause().to(slideIndex).cycle()\n    }\n\n    e.preventDefault()\n  })\n\n}(window.jQuery);/* =============================================================\n * bootstrap-collapse.js v2.3.0\n * http://twitter.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 ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* COLLAPSE PUBLIC CLASS DEFINITION\n  * ================================ */\n\n  var Collapse = function (element, options) {\n    this.$element = $(element)\n    this.options = $.extend({}, $.fn.collapse.defaults, options)\n\n    if (this.options.parent) {\n      this.$parent = $(this.options.parent)\n    }\n\n    this.options.toggle && this.toggle()\n  }\n\n  Collapse.prototype = {\n\n    constructor: Collapse\n\n  , dimension: function () {\n      var hasWidth = this.$element.hasClass('width')\n      return hasWidth ? 'width' : 'height'\n    }\n\n  , show: function () {\n      var dimension\n        , scroll\n        , actives\n        , hasData\n\n      if (this.transitioning || this.$element.hasClass('in')) return\n\n      dimension = this.dimension()\n      scroll = $.camelCase(['scroll', dimension].join('-'))\n      actives = this.$parent && this.$parent.find('> .accordion-group > .in')\n\n      if (actives && actives.length) {\n        hasData = actives.data('collapse')\n        if (hasData && hasData.transitioning) return\n        actives.collapse('hide')\n        hasData || actives.data('collapse', null)\n      }\n\n      this.$element[dimension](0)\n      this.transition('addClass', $.Event('show'), 'shown')\n      $.support.transition && this.$element[dimension](this.$element[0][scroll])\n    }\n\n  , hide: function () {\n      var dimension\n      if (this.transitioning || !this.$element.hasClass('in')) return\n      dimension = this.dimension()\n      this.reset(this.$element[dimension]())\n      this.transition('removeClass', $.Event('hide'), 'hidden')\n      this.$element[dimension](0)\n    }\n\n  , reset: function (size) {\n      var dimension = this.dimension()\n\n      this.$element\n        .removeClass('collapse')\n        [dimension](size || 'auto')\n        [0].offsetWidth\n\n      this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')\n\n      return this\n    }\n\n  , transition: function (method, startEvent, completeEvent) {\n      var that = this\n        , complete = function () {\n            if (startEvent.type == 'show') that.reset()\n            that.transitioning = 0\n            that.$element.trigger(completeEvent)\n          }\n\n      this.$element.trigger(startEvent)\n\n      if (startEvent.isDefaultPrevented()) return\n\n      this.transitioning = 1\n\n      this.$element[method]('in')\n\n      $.support.transition && this.$element.hasClass('collapse') ?\n        this.$element.one($.support.transition.end, complete) :\n        complete()\n    }\n\n  , toggle: function () {\n      this[this.$element.hasClass('in') ? 'hide' : 'show']()\n    }\n\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        , data = $this.data('collapse')\n        , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option)\n      if (!data) $this.data('collapse', (data = new Collapse(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.collapse.defaults = {\n    toggle: true\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.collapse.data-api', '[data-toggle=collapse]', function (e) {\n    var $this = $(this), href\n      , target = $this.attr('data-target')\n        || e.preventDefault()\n        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '') //strip for ie7\n      , option = $(target).data('collapse') ? 'toggle' : $this.data()\n    $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')\n    $(target).collapse(option)\n  })\n\n}(window.jQuery);/* ============================================================\n * bootstrap-dropdown.js v2.3.0\n * http://twitter.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 ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* DROPDOWN CLASS DEFINITION\n  * ========================= */\n\n  var toggle = '[data-toggle=dropdown]'\n    , Dropdown = function (element) {\n        var $el = $(element).on('click.dropdown.data-api', this.toggle)\n        $('html').on('click.dropdown.data-api', function () {\n          $el.parent().removeClass('open')\n        })\n      }\n\n  Dropdown.prototype = {\n\n    constructor: Dropdown\n\n  , toggle: function (e) {\n      var $this = $(this)\n        , $parent\n        , isActive\n\n      if ($this.is('.disabled, :disabled')) return\n\n      $parent = getParent($this)\n\n      isActive = $parent.hasClass('open')\n\n      clearMenus()\n\n      if (!isActive) {\n        $parent.toggleClass('open')\n      }\n\n      $this.focus()\n\n      return false\n    }\n\n  , keydown: function (e) {\n      var $this\n        , $items\n        , $active\n        , $parent\n        , isActive\n        , index\n\n      if (!/(38|40|27)/.test(e.keyCode)) return\n\n      $this = $(this)\n\n      e.preventDefault()\n      e.stopPropagation()\n\n      if ($this.is('.disabled, :disabled')) return\n\n      $parent = getParent($this)\n\n      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      $items = $('[role=menu] li:not(.divider):visible a', $parent)\n\n      if (!$items.length) return\n\n      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\n        .eq(index)\n        .focus()\n    }\n\n  }\n\n  function clearMenus() {\n    $(toggle).each(function () {\n      getParent($(this)).removeClass('open')\n    })\n  }\n\n  function getParent($this) {\n    var selector = $this.attr('data-target')\n      , $parent\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    $parent = selector && $(selector)\n\n    if (!$parent || !$parent.length) $parent = $this.parent()\n\n    return $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        , data = $this.data('dropdown')\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.dropdown.data-api', clearMenus)\n    .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })\n    .on('.dropdown-menu', function (e) { e.stopPropagation() })\n    .on('click.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)\n    .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)\n\n}(window.jQuery);\n/* =========================================================\n * bootstrap-modal.js v2.3.0\n * http://twitter.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 ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* MODAL CLASS DEFINITION\n  * ====================== */\n\n  var Modal = function (element, options) {\n    this.options = options\n    this.$element = $(element)\n      .delegate('[data-dismiss=\"modal\"]', 'click.dismiss.modal', $.proxy(this.hide, this))\n    this.options.remote && this.$element.find('.modal-body').load(this.options.remote)\n  }\n\n  Modal.prototype = {\n\n      constructor: Modal\n\n    , toggle: function () {\n        return this[!this.isShown ? 'show' : 'hide']()\n      }\n\n    , show: function () {\n        var that = this\n          , e = $.Event('show')\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.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :\n            that.$element.focus().trigger('shown')\n\n        })\n      }\n\n    , hide: function (e) {\n        e && e.preventDefault()\n\n        var that = this\n\n        e = $.Event('hide')\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.modal')\n\n        this.$element\n          .removeClass('in')\n          .attr('aria-hidden', true)\n\n        $.support.transition && this.$element.hasClass('fade') ?\n          this.hideWithTransition() :\n          this.hideModal()\n      }\n\n    , enforceFocus: function () {\n        var that = this\n        $(document).on('focusin.modal', function (e) {\n          if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {\n            that.$element.focus()\n          }\n        })\n      }\n\n    , escape: function () {\n        var that = this\n        if (this.isShown && this.options.keyboard) {\n          this.$element.on('keyup.dismiss.modal', function ( e ) {\n            e.which == 27 && that.hide()\n          })\n        } else if (!this.isShown) {\n          this.$element.off('keyup.dismiss.modal')\n        }\n      }\n\n    , hideWithTransition: function () {\n        var that = this\n          , timeout = setTimeout(function () {\n              that.$element.off($.support.transition.end)\n              that.hideModal()\n            }, 500)\n\n        this.$element.one($.support.transition.end, function () {\n          clearTimeout(timeout)\n          that.hideModal()\n        })\n      }\n\n    , hideModal: function () {\n        var that = this\n        this.$element.hide()\n        this.backdrop(function () {\n          that.removeBackdrop()\n          that.$element.trigger('hidden')\n        })\n      }\n\n    , removeBackdrop: function () {\n        this.$backdrop.remove()\n        this.$backdrop = null\n      }\n\n    , backdrop: function (callback) {\n        var that = this\n          , 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.$backdrop.click(\n            this.options.backdrop == 'static' ?\n              $.proxy(this.$element[0].focus, this.$element[0])\n            : $.proxy(this.hide, this)\n          )\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.one($.support.transition.end, callback) :\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.one($.support.transition.end, callback) :\n            callback()\n\n        } else if (callback) {\n          callback()\n        }\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        , data = $this.data('modal')\n        , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)\n      if (!data) $this.data('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.defaults = {\n      backdrop: true\n    , keyboard: true\n    , show: true\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.modal.data-api', '[data-toggle=\"modal\"]', function (e) {\n    var $this = $(this)\n      , href = $this.attr('href')\n      , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\\s]+$)/, ''))) //strip for ie7\n      , 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.focus()\n      })\n  })\n\n}(window.jQuery);\n/* ===========================================================\n * bootstrap-tooltip.js v2.3.0\n * http://twitter.github.com/bootstrap/javascript.html#tooltips\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 ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* TOOLTIP PUBLIC CLASS DEFINITION\n  * =============================== */\n\n  var Tooltip = function (element, options) {\n    this.init('tooltip', element, options)\n  }\n\n  Tooltip.prototype = {\n\n    constructor: Tooltip\n\n  , init: function (type, element, options) {\n      var eventIn\n        , eventOut\n        , triggers\n        , trigger\n        , i\n\n      this.type = type\n      this.$element = $(element)\n      this.options = this.getOptions(options)\n      this.enabled = true\n\n      triggers = this.options.trigger.split(' ')\n\n      for (i = triggers.length; i--;) {\n        trigger = triggers[i]\n        if (trigger == 'click') {\n          this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))\n        } else if (trigger != 'manual') {\n          eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'\n          eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'\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  , getOptions: function (options) {\n      options = $.extend({}, $.fn[this.type].defaults, 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  , enter: function (e) {\n      var self = $(e.currentTarget)[this.type](this._options).data(this.type)\n\n      if (!self.options.delay || !self.options.delay.show) return self.show()\n\n      clearTimeout(this.timeout)\n      self.hoverState = 'in'\n      this.timeout = setTimeout(function() {\n        if (self.hoverState == 'in') self.show()\n      }, self.options.delay.show)\n    }\n\n  , leave: function (e) {\n      var self = $(e.currentTarget)[this.type](this._options).data(this.type)\n\n      if (this.timeout) clearTimeout(this.timeout)\n      if (!self.options.delay || !self.options.delay.hide) return self.hide()\n\n      self.hoverState = 'out'\n      this.timeout = setTimeout(function() {\n        if (self.hoverState == 'out') self.hide()\n      }, self.options.delay.hide)\n    }\n\n  , show: function () {\n      var $tip\n        , pos\n        , actualWidth\n        , actualHeight\n        , placement\n        , tp\n        , e = $.Event('show')\n\n      if (this.hasContent() && this.enabled) {\n        this.$element.trigger(e)\n        if (e.isDefaultPrevented()) return\n        $tip = this.tip()\n        this.setContent()\n\n        if (this.options.animation) {\n          $tip.addClass('fade')\n        }\n\n        placement = typeof this.options.placement == 'function' ?\n          this.options.placement.call(this, $tip[0], this.$element[0]) :\n          this.options.placement\n\n        $tip\n          .detach()\n          .css({ top: 0, left: 0, display: 'block' })\n\n        this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)\n\n        pos = this.getPosition()\n\n        actualWidth = $tip[0].offsetWidth\n        actualHeight = $tip[0].offsetHeight\n\n        switch (placement) {\n          case 'bottom':\n            tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}\n            break\n          case 'top':\n            tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}\n            break\n          case 'left':\n            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}\n            break\n          case 'right':\n            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}\n            break\n        }\n\n        this.applyPlacement(tp, placement)\n        this.$element.trigger('shown')\n      }\n    }\n\n  , applyPlacement: function(offset, placement){\n      var $tip = this.tip()\n        , width = $tip[0].offsetWidth\n        , height = $tip[0].offsetHeight\n        , actualWidth\n        , actualHeight\n        , delta\n        , replace\n\n      $tip\n        .offset(offset)\n        .addClass(placement)\n        .addClass('in')\n\n      actualWidth = $tip[0].offsetWidth\n      actualHeight = $tip[0].offsetHeight\n\n      if (placement == 'top' && actualHeight != height) {\n        offset.top = offset.top + height - actualHeight\n        replace = true\n      }\n\n      if (placement == 'bottom' || placement == 'top') {\n        delta = 0\n\n        if (offset.left < 0){\n          delta = offset.left * -2\n          offset.left = 0\n          $tip.offset(offset)\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  , replaceArrow: function(delta, dimension, position){\n      this\n        .arrow()\n        .css(position, delta ? (50 * (1 - delta / dimension) + \"%\") : '')\n    }\n\n  , setContent: function () {\n      var $tip = this.tip()\n        , 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  , hide: function () {\n      var that = this\n        , $tip = this.tip()\n        , e = $.Event('hide')\n\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n\n      $tip.removeClass('in')\n\n      function removeWithAnimation() {\n        var timeout = setTimeout(function () {\n          $tip.off($.support.transition.end).detach()\n        }, 500)\n\n        $tip.one($.support.transition.end, function () {\n          clearTimeout(timeout)\n          $tip.detach()\n        })\n      }\n\n      $.support.transition && this.$tip.hasClass('fade') ?\n        removeWithAnimation() :\n        $tip.detach()\n\n      this.$element.trigger('hidden')\n\n      return this\n    }\n\n  , 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  , hasContent: function () {\n      return this.getTitle()\n    }\n\n  , 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  , getTitle: function () {\n      var title\n        , $e = this.$element\n        , 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  , tip: function () {\n      return this.$tip = this.$tip || $(this.options.template)\n    }\n\n  , arrow: function(){\n      return this.$arrow = this.$arrow || this.tip().find(\".tooltip-arrow\")\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 () {\n      this.enabled = true\n    }\n\n  , disable: function () {\n      this.enabled = false\n    }\n\n  , toggleEnabled: function () {\n      this.enabled = !this.enabled\n    }\n\n  , toggle: function (e) {\n      var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this\n      self.tip().hasClass('in') ? self.hide() : self.show()\n    }\n\n  , destroy: function () {\n      this.hide().$element.off('.' + this.type).removeData(this.type)\n    }\n\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        , data = $this.data('tooltip')\n        , options = typeof option == 'object' && option\n      if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tooltip.Constructor = Tooltip\n\n  $.fn.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\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 * bootstrap-popover.js v2.3.0\n * http://twitter.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 ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* POPOVER PUBLIC CLASS DEFINITION\n  * =============================== */\n\n  var Popover = function (element, options) {\n    this.init('popover', element, options)\n  }\n\n\n  /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js\n     ========================================== */\n\n  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {\n\n    constructor: Popover\n\n  , setContent: function () {\n      var $tip = this.tip()\n        , title = this.getTitle()\n        , 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\n  , hasContent: function () {\n      return this.getTitle() || this.getContent()\n    }\n\n  , getContent: function () {\n      var content\n        , $e = this.$element\n        , o = this.options\n\n      content = (typeof o.content == 'function' ? o.content.call($e[0]) :  o.content)\n        || $e.attr('data-content')\n\n      return content\n    }\n\n  , tip: function () {\n      if (!this.$tip) {\n        this.$tip = $(this.options.template)\n      }\n      return this.$tip\n    }\n\n  , destroy: function () {\n      this.hide().$element.off('.' + this.type).removeData(this.type)\n    }\n\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        , data = $this.data('popover')\n        , options = typeof option == 'object' && option\n      if (!data) $this.data('popover', (data = new Popover(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.popover.Constructor = Popover\n\n  $.fn.popover.defaults = $.extend({} , $.fn.tooltip.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 /* POPOVER NO CONFLICT\n  * =================== */\n\n  $.fn.popover.noConflict = function () {\n    $.fn.popover = old\n    return this\n  }\n\n}(window.jQuery);\n/* =============================================================\n * bootstrap-scrollspy.js v2.3.0\n * http://twitter.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 ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* SCROLLSPY CLASS DEFINITION\n  * ========================== */\n\n  function ScrollSpy(element, options) {\n    var process = $.proxy(this.process, this)\n      , $element = $(element).is('body') ? $(window) : $(element)\n      , href\n    this.options = $.extend({}, $.fn.scrollspy.defaults, options)\n    this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)\n    this.selector = (this.options.target\n      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n      || '') + ' .nav li > a'\n    this.$body = $('body')\n    this.refresh()\n    this.process()\n  }\n\n  ScrollSpy.prototype = {\n\n      constructor: ScrollSpy\n\n    , refresh: function () {\n        var self = this\n          , $targets\n\n        this.offsets = $([])\n        this.targets = $([])\n\n        $targets = this.$body\n          .find(this.selector)\n          .map(function () {\n            var $el = $(this)\n              , href = $el.data('target') || $el.attr('href')\n              , $href = /^#\\w/.test(href) && $(href)\n            return ( $href\n              && $href.length\n              && [[ $href.position().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    , process: function () {\n        var scrollTop = this.$scrollElement.scrollTop() + this.options.offset\n          , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight\n          , maxScroll = scrollHeight - this.$scrollElement.height()\n          , offsets = this.offsets\n          , targets = this.targets\n          , activeTarget = this.activeTarget\n          , i\n\n        if (scrollTop >= maxScroll) {\n          return activeTarget != (i = targets.last()[0])\n            && 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    , activate: function (target) {\n        var active\n          , selector\n\n        this.activeTarget = target\n\n        $(this.selector)\n          .parent('.active')\n          .removeClass('active')\n\n        selector = this.selector\n          + '[data-target=\"' + target + '\"],'\n          + this.selector + '[href=\"' + target + '\"]'\n\n        active = $(selector)\n          .parent('li')\n          .addClass('active')\n\n        if (active.parent('.dropdown-menu').length)  {\n          active = active.closest('li.dropdown').addClass('active')\n        }\n\n        active.trigger('activate')\n      }\n\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        , data = $this.data('scrollspy')\n        , options = typeof option == 'object' && option\n      if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.scrollspy.Constructor = ScrollSpy\n\n  $.fn.scrollspy.defaults = {\n    offset: 10\n  }\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 * bootstrap-tab.js v2.3.0\n * http://twitter.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 ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* TAB CLASS DEFINITION\n  * ==================== */\n\n  var Tab = function (element) {\n    this.element = $(element)\n  }\n\n  Tab.prototype = {\n\n    constructor: Tab\n\n  , show: function () {\n      var $this = this.element\n        , $ul = $this.closest('ul:not(.dropdown-menu)')\n        , selector = $this.attr('data-target')\n        , previous\n        , $target\n        , e\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      previous = $ul.find('.active:last a')[0]\n\n      e = $.Event('show', {\n        relatedTarget: previous\n      })\n\n      $this.trigger(e)\n\n      if (e.isDefaultPrevented()) return\n\n      $target = $(selector)\n\n      this.activate($this.parent('li'), $ul)\n      this.activate($target, $target.parent(), function () {\n        $this.trigger({\n          type: 'shown'\n        , relatedTarget: previous\n        })\n      })\n    }\n\n  , activate: function ( element, container, callback) {\n      var $active = container.find('> .active')\n        , 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.one($.support.transition.end, next) :\n        next()\n\n      $active.removeClass('in')\n    }\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        , data = $this.data('tab')\n      if (!data) $this.data('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.tab.data-api', '[data-toggle=\"tab\"], [data-toggle=\"pill\"]', function (e) {\n    e.preventDefault()\n    $(this).tab('show')\n  })\n\n}(window.jQuery);/* =============================================================\n * bootstrap-typeahead.js v2.3.0\n * http://twitter.github.com/bootstrap/javascript.html#typeahead\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($){\n\n  \"use strict\"; // jshint ;_;\n\n\n /* TYPEAHEAD PUBLIC CLASS DEFINITION\n  * ================================= */\n\n  var Typeahead = function (element, options) {\n    this.$element = $(element)\n    this.options = $.extend({}, $.fn.typeahead.defaults, options)\n    this.matcher = this.options.matcher || this.matcher\n    this.sorter = this.options.sorter || this.sorter\n    this.highlighter = this.options.highlighter || this.highlighter\n    this.updater = this.options.updater || this.updater\n    this.source = this.options.source\n    this.$menu = $(this.options.menu)\n    this.shown = false\n    this.listen()\n  }\n\n  Typeahead.prototype = {\n\n    constructor: Typeahead\n\n  , select: function () {\n      var val = this.$menu.find('.active').attr('data-value')\n      this.$element\n        .val(this.updater(val))\n        .change()\n      return this.hide()\n    }\n\n  , updater: function (item) {\n      return item\n    }\n\n  , show: function () {\n      var pos = $.extend({}, this.$element.position(), {\n        height: this.$element[0].offsetHeight\n      })\n\n      this.$menu\n        .insertAfter(this.$element)\n        .css({\n          top: pos.top + pos.height\n        , left: pos.left\n        })\n        .show()\n\n      this.shown = true\n      return this\n    }\n\n  , hide: function () {\n      this.$menu.hide()\n      this.shown = false\n      return this\n    }\n\n  , lookup: function (event) {\n      var items\n\n      this.query = this.$element.val()\n\n      if (!this.query || this.query.length < this.options.minLength) {\n        return this.shown ? this.hide() : this\n      }\n\n      items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source\n\n      return items ? this.process(items) : this\n    }\n\n  , process: function (items) {\n      var that = this\n\n      items = $.grep(items, function (item) {\n        return that.matcher(item)\n      })\n\n      items = this.sorter(items)\n\n      if (!items.length) {\n        return this.shown ? this.hide() : this\n      }\n\n      return this.render(items.slice(0, this.options.items)).show()\n    }\n\n  , matcher: function (item) {\n      return ~item.toLowerCase().indexOf(this.query.toLowerCase())\n    }\n\n  , sorter: function (items) {\n      var beginswith = []\n        , caseSensitive = []\n        , caseInsensitive = []\n        , item\n\n      while (item = items.shift()) {\n        if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)\n        else if (~item.indexOf(this.query)) caseSensitive.push(item)\n        else caseInsensitive.push(item)\n      }\n\n      return beginswith.concat(caseSensitive, caseInsensitive)\n    }\n\n  , highlighter: function (item) {\n      var query = this.query.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, '\\\\$&')\n      return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {\n        return '<strong>' + match + '</strong>'\n      })\n    }\n\n  , render: function (items) {\n      var that = this\n\n      items = $(items).map(function (i, item) {\n        i = $(that.options.item).attr('data-value', item)\n        i.find('a').html(that.highlighter(item))\n        return i[0]\n      })\n\n      items.first().addClass('active')\n      this.$menu.html(items)\n      return this\n    }\n\n  , next: function (event) {\n      var active = this.$menu.find('.active').removeClass('active')\n        , next = active.next()\n\n      if (!next.length) {\n        next = $(this.$menu.find('li')[0])\n      }\n\n      next.addClass('active')\n    }\n\n  , prev: function (event) {\n      var active = this.$menu.find('.active').removeClass('active')\n        , prev = active.prev()\n\n      if (!prev.length) {\n        prev = this.$menu.find('li').last()\n      }\n\n      prev.addClass('active')\n    }\n\n  , listen: function () {\n      this.$element\n        .on('focus',    $.proxy(this.focus, this))\n        .on('blur',     $.proxy(this.blur, this))\n        .on('keypress', $.proxy(this.keypress, this))\n        .on('keyup',    $.proxy(this.keyup, this))\n\n      if (this.eventSupported('keydown')) {\n        this.$element.on('keydown', $.proxy(this.keydown, this))\n      }\n\n      this.$menu\n        .on('click', $.proxy(this.click, this))\n        .on('mouseenter', 'li', $.proxy(this.mouseenter, this))\n        .on('mouseleave', 'li', $.proxy(this.mouseleave, this))\n    }\n\n  , eventSupported: function(eventName) {\n      var isSupported = eventName in this.$element\n      if (!isSupported) {\n        this.$element.setAttribute(eventName, 'return;')\n        isSupported = typeof this.$element[eventName] === 'function'\n      }\n      return isSupported\n    }\n\n  , move: function (e) {\n      if (!this.shown) return\n\n      switch(e.keyCode) {\n        case 9: // tab\n        case 13: // enter\n        case 27: // escape\n          e.preventDefault()\n          break\n\n        case 38: // up arrow\n          e.preventDefault()\n          this.prev()\n          break\n\n        case 40: // down arrow\n          e.preventDefault()\n          this.next()\n          break\n      }\n\n      e.stopPropagation()\n    }\n\n  , keydown: function (e) {\n      this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27])\n      this.move(e)\n    }\n\n  , keypress: function (e) {\n      if (this.suppressKeyPressRepeat) return\n      this.move(e)\n    }\n\n  , keyup: function (e) {\n      switch(e.keyCode) {\n        case 40: // down arrow\n        case 38: // up arrow\n        case 16: // shift\n        case 17: // ctrl\n        case 18: // alt\n          break\n\n        case 9: // tab\n        case 13: // enter\n          if (!this.shown) return\n          this.select()\n          break\n\n        case 27: // escape\n          if (!this.shown) return\n          this.hide()\n          break\n\n        default:\n          this.lookup()\n      }\n\n      e.stopPropagation()\n      e.preventDefault()\n  }\n\n  , focus: function (e) {\n      this.focused = true\n    }\n\n  , blur: function (e) {\n      this.focused = false\n      if (!this.mousedover && this.shown) this.hide()\n    }\n\n  , click: function (e) {\n      e.stopPropagation()\n      e.preventDefault()\n      this.select()\n      this.$element.focus()\n    }\n\n  , mouseenter: function (e) {\n      this.mousedover = true\n      this.$menu.find('.active').removeClass('active')\n      $(e.currentTarget).addClass('active')\n    }\n\n  , mouseleave: function (e) {\n      this.mousedover = false\n      if (!this.focused && this.shown) this.hide()\n    }\n\n  }\n\n\n  /* TYPEAHEAD PLUGIN DEFINITION\n   * =========================== */\n\n  var old = $.fn.typeahead\n\n  $.fn.typeahead = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('typeahead')\n        , options = typeof option == 'object' && option\n      if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.typeahead.defaults = {\n    source: []\n  , items: 8\n  , menu: '<ul class=\"typeahead dropdown-menu\"></ul>'\n  , item: '<li><a href=\"#\"></a></li>'\n  , minLength: 1\n  }\n\n  $.fn.typeahead.Constructor = Typeahead\n\n\n /* TYPEAHEAD NO CONFLICT\n  * =================== */\n\n  $.fn.typeahead.noConflict = function () {\n    $.fn.typeahead = old\n    return this\n  }\n\n\n /* TYPEAHEAD DATA-API\n  * ================== */\n\n  $(document).on('focus.typeahead.data-api', '[data-provide=\"typeahead\"]', function (e) {\n    var $this = $(this)\n    if ($this.data('typeahead')) return\n    $this.typeahead($this.data())\n  })\n\n}(window.jQuery);\n/* ==========================================================\n * bootstrap-affix.js v2.3.0\n * http://twitter.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 ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* AFFIX CLASS DEFINITION\n  * ====================== */\n\n  var Affix = function (element, options) {\n    this.options = $.extend({}, $.fn.affix.defaults, options)\n    this.$window = $(window)\n      .on('scroll.affix.data-api', $.proxy(this.checkPosition, this))\n      .on('click.affix.data-api',  $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this))\n    this.$element = $(element)\n    this.checkPosition()\n  }\n\n  Affix.prototype.checkPosition = function () {\n    if (!this.$element.is(':visible')) return\n\n    var scrollHeight = $(document).height()\n      , scrollTop = this.$window.scrollTop()\n      , position = this.$element.offset()\n      , offset = this.options.offset\n      , offsetBottom = offset.bottom\n      , offsetTop = offset.top\n      , reset = 'affix affix-top affix-bottom'\n      , affix\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    affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ?\n      false    : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ?\n      'bottom' : offsetTop != null && scrollTop <= offsetTop ?\n      'top'    : false\n\n    if (this.affixed === affix) return\n\n    this.affixed = affix\n    this.unpin = affix == 'bottom' ? position.top - scrollTop : null\n\n    this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''))\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        , data = $this.data('affix')\n        , options = typeof option == 'object' && option\n      if (!data) $this.data('affix', (data = new Affix(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.affix.Constructor = Affix\n\n  $.fn.affix.defaults = {\n    offset: 0\n  }\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        , data = $spy.data()\n\n      data.offset = data.offset || {}\n\n      data.offsetBottom && (data.offset.bottom = data.offsetBottom)\n      data.offsetTop && (data.offset.top = data.offsetTop)\n\n      $spy.affix(data)\n    })\n  })\n\n\n}(window.jQuery);\n"
  },
  {
    "path": "packages/deprecated/bootstrap/package.js",
    "content": "Package.describe({\n  summary: \"Front-end framework from Twitter\",\n  version: \"1.0.1\"\n});\n\nPackage.onUse(function (api) {\n  api.use('jquery');\n\n  var path = Npm.require('path');\n  api.addFiles(path.join('css', 'bootstrap.css'), 'client');\n  api.addFiles(path.join('css', 'bootstrap-responsive.css'), 'client');\n  api.addFiles(path.join('js', 'bootstrap.js'), 'client');\n  api.addFiles(path.join('img', 'glyphicons-halflings.png'), 'client');\n  api.addFiles(path.join('img', 'glyphicons-halflings-white.png'), 'client');\n\n  // XXX this makes the paths to the icon sets absolute. it needs\n  // to be included _after_ the standard bootstrap css so\n  // that its styles take precedence.\n  api.addFiles(path.join('css', 'bootstrap-override.css'), 'client');\n});\n"
  },
  {
    "path": "packages/deprecated/d3/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/deprecated/d3/d3.v3.js",
    "content": "d3 = function() {\n  var d3 = {\n    version: \"3.1.4\"\n  };\n  if (!Date.now) Date.now = function() {\n    return +new Date();\n  };\n  var d3_document = document, d3_window = window;\n  try {\n    d3_document.createElement(\"div\").style.setProperty(\"opacity\", 0, \"\");\n  } catch (error) {\n    var d3_style_prototype = d3_window.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;\n    d3_style_prototype.setProperty = function(name, value, priority) {\n      d3_style_setProperty.call(this, name, value + \"\", priority);\n    };\n  }\n  d3.ascending = function(a, b) {\n    return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;\n  };\n  d3.descending = function(a, b) {\n    return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;\n  };\n  d3.min = function(array, f) {\n    var i = -1, n = array.length, a, b;\n    if (arguments.length === 1) {\n      while (++i < n && ((a = array[i]) == null || a != a)) a = undefined;\n      while (++i < n) if ((b = array[i]) != null && a > b) a = b;\n    } else {\n      while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined;\n      while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;\n    }\n    return a;\n  };\n  d3.max = function(array, f) {\n    var i = -1, n = array.length, a, b;\n    if (arguments.length === 1) {\n      while (++i < n && ((a = array[i]) == null || a != a)) a = undefined;\n      while (++i < n) if ((b = array[i]) != null && b > a) a = b;\n    } else {\n      while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined;\n      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;\n    }\n    return a;\n  };\n  d3.extent = function(array, f) {\n    var i = -1, n = array.length, a, b, c;\n    if (arguments.length === 1) {\n      while (++i < n && ((a = c = array[i]) == null || a != a)) a = c = undefined;\n      while (++i < n) if ((b = array[i]) != null) {\n        if (a > b) a = b;\n        if (c < b) c = b;\n      }\n    } else {\n      while (++i < n && ((a = c = f.call(array, array[i], i)) == null || a != a)) a = undefined;\n      while (++i < n) if ((b = f.call(array, array[i], i)) != null) {\n        if (a > b) a = b;\n        if (c < b) c = b;\n      }\n    }\n    return [ a, c ];\n  };\n  d3.sum = function(array, f) {\n    var s = 0, n = array.length, a, i = -1;\n    if (arguments.length === 1) {\n      while (++i < n) if (!isNaN(a = +array[i])) s += a;\n    } else {\n      while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a;\n    }\n    return s;\n  };\n  function d3_number(x) {\n    return x != null && !isNaN(x);\n  }\n  d3.mean = function(array, f) {\n    var n = array.length, a, m = 0, i = -1, j = 0;\n    if (arguments.length === 1) {\n      while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;\n    } else {\n      while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;\n    }\n    return j ? m : undefined;\n  };\n  d3.quantile = function(values, p) {\n    var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;\n    return e ? v + e * (values[h] - v) : v;\n  };\n  d3.median = function(array, f) {\n    if (arguments.length > 1) array = array.map(f);\n    array = array.filter(d3_number);\n    return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined;\n  };\n  d3.bisector = function(f) {\n    return {\n      left: function(a, x, lo, hi) {\n        if (arguments.length < 3) lo = 0;\n        if (arguments.length < 4) hi = a.length;\n        while (lo < hi) {\n          var mid = lo + hi >>> 1;\n          if (f.call(a, a[mid], mid) < x) lo = mid + 1; else hi = mid;\n        }\n        return lo;\n      },\n      right: function(a, x, lo, hi) {\n        if (arguments.length < 3) lo = 0;\n        if (arguments.length < 4) hi = a.length;\n        while (lo < hi) {\n          var mid = lo + hi >>> 1;\n          if (x < f.call(a, a[mid], mid)) hi = mid; else lo = mid + 1;\n        }\n        return lo;\n      }\n    };\n  };\n  var d3_bisector = d3.bisector(function(d) {\n    return d;\n  });\n  d3.bisectLeft = d3_bisector.left;\n  d3.bisect = d3.bisectRight = d3_bisector.right;\n  d3.shuffle = function(array) {\n    var m = array.length, t, i;\n    while (m) {\n      i = Math.random() * m-- | 0;\n      t = array[m], array[m] = array[i], array[i] = t;\n    }\n    return array;\n  };\n  d3.permute = function(array, indexes) {\n    var permutes = [], i = -1, n = indexes.length;\n    while (++i < n) permutes[i] = array[indexes[i]];\n    return permutes;\n  };\n  d3.zip = function() {\n    if (!(n = arguments.length)) return [];\n    for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) {\n      for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) {\n        zip[j] = arguments[j][i];\n      }\n    }\n    return zips;\n  };\n  function d3_zipLength(d) {\n    return d.length;\n  }\n  d3.transpose = function(matrix) {\n    return d3.zip.apply(d3, matrix);\n  };\n  d3.keys = function(map) {\n    var keys = [];\n    for (var key in map) keys.push(key);\n    return keys;\n  };\n  d3.values = function(map) {\n    var values = [];\n    for (var key in map) values.push(map[key]);\n    return values;\n  };\n  d3.entries = function(map) {\n    var entries = [];\n    for (var key in map) entries.push({\n      key: key,\n      value: map[key]\n    });\n    return entries;\n  };\n  d3.merge = function(arrays) {\n    return Array.prototype.concat.apply([], arrays);\n  };\n  d3.range = function(start, stop, step) {\n    if (arguments.length < 3) {\n      step = 1;\n      if (arguments.length < 2) {\n        stop = start;\n        start = 0;\n      }\n    }\n    if ((stop - start) / step === Infinity) throw new Error(\"infinite range\");\n    var range = [], k = d3_range_integerScale(Math.abs(step)), i = -1, j;\n    start *= k, stop *= k, step *= k;\n    if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k);\n    return range;\n  };\n  function d3_range_integerScale(x) {\n    var k = 1;\n    while (x * k % 1) k *= 10;\n    return k;\n  }\n  function d3_class(ctor, properties) {\n    try {\n      for (var key in properties) {\n        Object.defineProperty(ctor.prototype, key, {\n          value: properties[key],\n          enumerable: false\n        });\n      }\n    } catch (e) {\n      ctor.prototype = properties;\n    }\n  }\n  d3.map = function(object) {\n    var map = new d3_Map();\n    for (var key in object) map.set(key, object[key]);\n    return map;\n  };\n  function d3_Map() {}\n  d3_class(d3_Map, {\n    has: function(key) {\n      return d3_map_prefix + key in this;\n    },\n    get: function(key) {\n      return this[d3_map_prefix + key];\n    },\n    set: function(key, value) {\n      return this[d3_map_prefix + key] = value;\n    },\n    remove: function(key) {\n      key = d3_map_prefix + key;\n      return key in this && delete this[key];\n    },\n    keys: function() {\n      var keys = [];\n      this.forEach(function(key) {\n        keys.push(key);\n      });\n      return keys;\n    },\n    values: function() {\n      var values = [];\n      this.forEach(function(key, value) {\n        values.push(value);\n      });\n      return values;\n    },\n    entries: function() {\n      var entries = [];\n      this.forEach(function(key, value) {\n        entries.push({\n          key: key,\n          value: value\n        });\n      });\n      return entries;\n    },\n    forEach: function(f) {\n      for (var key in this) {\n        if (key.charCodeAt(0) === d3_map_prefixCode) {\n          f.call(this, key.substring(1), this[key]);\n        }\n      }\n    }\n  });\n  var d3_map_prefix = \"\\0\", d3_map_prefixCode = d3_map_prefix.charCodeAt(0);\n  d3.nest = function() {\n    var nest = {}, keys = [], sortKeys = [], sortValues, rollup;\n    function map(mapType, array, depth) {\n      if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;\n      var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values;\n      while (++i < n) {\n        if (values = valuesByKey.get(keyValue = key(object = array[i]))) {\n          values.push(object);\n        } else {\n          valuesByKey.set(keyValue, [ object ]);\n        }\n      }\n      if (mapType) {\n        object = mapType();\n        setter = function(keyValue, values) {\n          object.set(keyValue, map(mapType, values, depth));\n        };\n      } else {\n        object = {};\n        setter = function(keyValue, values) {\n          object[keyValue] = map(mapType, values, depth);\n        };\n      }\n      valuesByKey.forEach(setter);\n      return object;\n    }\n    function entries(map, depth) {\n      if (depth >= keys.length) return map;\n      var array = [], sortKey = sortKeys[depth++];\n      map.forEach(function(key, keyMap) {\n        array.push({\n          key: key,\n          values: entries(keyMap, depth)\n        });\n      });\n      return sortKey ? array.sort(function(a, b) {\n        return sortKey(a.key, b.key);\n      }) : array;\n    }\n    nest.map = function(array, mapType) {\n      return map(mapType, array, 0);\n    };\n    nest.entries = function(array) {\n      return entries(map(d3.map, array, 0), 0);\n    };\n    nest.key = function(d) {\n      keys.push(d);\n      return nest;\n    };\n    nest.sortKeys = function(order) {\n      sortKeys[keys.length - 1] = order;\n      return nest;\n    };\n    nest.sortValues = function(order) {\n      sortValues = order;\n      return nest;\n    };\n    nest.rollup = function(f) {\n      rollup = f;\n      return nest;\n    };\n    return nest;\n  };\n  d3.set = function(array) {\n    var set = new d3_Set();\n    if (array) for (var i = 0; i < array.length; i++) set.add(array[i]);\n    return set;\n  };\n  function d3_Set() {}\n  d3_class(d3_Set, {\n    has: function(value) {\n      return d3_map_prefix + value in this;\n    },\n    add: function(value) {\n      this[d3_map_prefix + value] = true;\n      return value;\n    },\n    remove: function(value) {\n      value = d3_map_prefix + value;\n      return value in this && delete this[value];\n    },\n    values: function() {\n      var values = [];\n      this.forEach(function(value) {\n        values.push(value);\n      });\n      return values;\n    },\n    forEach: function(f) {\n      for (var value in this) {\n        if (value.charCodeAt(0) === d3_map_prefixCode) {\n          f.call(this, value.substring(1));\n        }\n      }\n    }\n  });\n  d3.behavior = {};\n  d3.rebind = function(target, source) {\n    var i = 1, n = arguments.length, method;\n    while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);\n    return target;\n  };\n  function d3_rebind(target, source, method) {\n    return function() {\n      var value = method.apply(source, arguments);\n      return value === source ? target : value;\n    };\n  }\n  d3.dispatch = function() {\n    var dispatch = new d3_dispatch(), i = -1, n = arguments.length;\n    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);\n    return dispatch;\n  };\n  function d3_dispatch() {}\n  d3_dispatch.prototype.on = function(type, listener) {\n    var i = type.indexOf(\".\"), name = \"\";\n    if (i >= 0) {\n      name = type.substring(i + 1);\n      type = type.substring(0, i);\n    }\n    if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);\n    if (arguments.length === 2) {\n      if (listener == null) for (type in this) {\n        if (this.hasOwnProperty(type)) this[type].on(name, null);\n      }\n      return this;\n    }\n  };\n  function d3_dispatch_event(dispatch) {\n    var listeners = [], listenerByName = new d3_Map();\n    function event() {\n      var z = listeners, i = -1, n = z.length, l;\n      while (++i < n) if (l = z[i].on) l.apply(this, arguments);\n      return dispatch;\n    }\n    event.on = function(name, listener) {\n      var l = listenerByName.get(name), i;\n      if (arguments.length < 2) return l && l.on;\n      if (l) {\n        l.on = null;\n        listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));\n        listenerByName.remove(name);\n      }\n      if (listener) listeners.push(listenerByName.set(name, {\n        on: listener\n      }));\n      return dispatch;\n    };\n    return event;\n  }\n  d3.event = null;\n  function d3_eventCancel() {\n    d3.event.stopPropagation();\n    d3.event.preventDefault();\n  }\n  function d3_eventSource() {\n    var e = d3.event, s;\n    while (s = e.sourceEvent) e = s;\n    return e;\n  }\n  function d3_eventDispatch(target) {\n    var dispatch = new d3_dispatch(), i = 0, n = arguments.length;\n    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);\n    dispatch.of = function(thiz, argumentz) {\n      return function(e1) {\n        try {\n          var e0 = e1.sourceEvent = d3.event;\n          e1.target = target;\n          d3.event = e1;\n          dispatch[e1.type].apply(thiz, argumentz);\n        } finally {\n          d3.event = e0;\n        }\n      };\n    };\n    return dispatch;\n  }\n  d3.mouse = function(container) {\n    return d3_mousePoint(container, d3_eventSource());\n  };\n  var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0;\n  function d3_mousePoint(container, e) {\n    var svg = container.ownerSVGElement || container;\n    if (svg.createSVGPoint) {\n      var point = svg.createSVGPoint();\n      if (d3_mouse_bug44083 < 0 && (d3_window.scrollX || d3_window.scrollY)) {\n        svg = d3.select(d3_document.body).append(\"svg\").style(\"position\", \"absolute\").style(\"top\", 0).style(\"left\", 0);\n        var ctm = svg[0][0].getScreenCTM();\n        d3_mouse_bug44083 = !(ctm.f || ctm.e);\n        svg.remove();\n      }\n      if (d3_mouse_bug44083) {\n        point.x = e.pageX;\n        point.y = e.pageY;\n      } else {\n        point.x = e.clientX;\n        point.y = e.clientY;\n      }\n      point = point.matrixTransform(container.getScreenCTM().inverse());\n      return [ point.x, point.y ];\n    }\n    var rect = container.getBoundingClientRect();\n    return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];\n  }\n  var d3_array = d3_arraySlice;\n  function d3_arrayCopy(pseudoarray) {\n    var i = -1, n = pseudoarray.length, array = [];\n    while (++i < n) array.push(pseudoarray[i]);\n    return array;\n  }\n  function d3_arraySlice(pseudoarray) {\n    return Array.prototype.slice.call(pseudoarray);\n  }\n  try {\n    d3_array(d3_document.documentElement.childNodes)[0].nodeType;\n  } catch (e) {\n    d3_array = d3_arrayCopy;\n  }\n  var d3_arraySubclass = [].__proto__ ? function(array, prototype) {\n    array.__proto__ = prototype;\n  } : function(array, prototype) {\n    for (var property in prototype) array[property] = prototype[property];\n  };\n  d3.touches = function(container, touches) {\n    if (arguments.length < 2) touches = d3_eventSource().touches;\n    return touches ? d3_array(touches).map(function(touch) {\n      var point = d3_mousePoint(container, touch);\n      point.identifier = touch.identifier;\n      return point;\n    }) : [];\n  };\n  d3.behavior.drag = function() {\n    var event = d3_eventDispatch(drag, \"drag\", \"dragstart\", \"dragend\"), origin = null;\n    function drag() {\n      this.on(\"mousedown.drag\", mousedown).on(\"touchstart.drag\", mousedown);\n    }\n    function mousedown() {\n      var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null, offset, origin_ = point(), moved = 0;\n      var w = d3.select(d3_window).on(touchId != null ? \"touchmove.drag-\" + touchId : \"mousemove.drag\", dragmove).on(touchId != null ? \"touchend.drag-\" + touchId : \"mouseup.drag\", dragend, true);\n      if (origin) {\n        offset = origin.apply(target, arguments);\n        offset = [ offset.x - origin_[0], offset.y - origin_[1] ];\n      } else {\n        offset = [ 0, 0 ];\n      }\n      if (touchId == null) d3_eventCancel();\n      event_({\n        type: \"dragstart\"\n      });\n      function point() {\n        var p = target.parentNode;\n        return touchId != null ? d3.touches(p).filter(function(p) {\n          return p.identifier === touchId;\n        })[0] : d3.mouse(p);\n      }\n      function dragmove() {\n        if (!target.parentNode) return dragend();\n        var p = point(), dx = p[0] - origin_[0], dy = p[1] - origin_[1];\n        moved |= dx | dy;\n        origin_ = p;\n        d3_eventCancel();\n        event_({\n          type: \"drag\",\n          x: p[0] + offset[0],\n          y: p[1] + offset[1],\n          dx: dx,\n          dy: dy\n        });\n      }\n      function dragend() {\n        event_({\n          type: \"dragend\"\n        });\n        if (moved) {\n          d3_eventCancel();\n          if (d3.event.target === eventTarget) w.on(\"click.drag\", click, true);\n        }\n        w.on(touchId != null ? \"touchmove.drag-\" + touchId : \"mousemove.drag\", null).on(touchId != null ? \"touchend.drag-\" + touchId : \"mouseup.drag\", null);\n      }\n      function click() {\n        d3_eventCancel();\n        w.on(\"click.drag\", null);\n      }\n    }\n    drag.origin = function(x) {\n      if (!arguments.length) return origin;\n      origin = x;\n      return drag;\n    };\n    return d3.rebind(drag, event, \"on\");\n  };\n  function d3_selection(groups) {\n    d3_arraySubclass(groups, d3_selectionPrototype);\n    return groups;\n  }\n  var d3_select = function(s, n) {\n    return n.querySelector(s);\n  }, d3_selectAll = function(s, n) {\n    return n.querySelectorAll(s);\n  }, d3_selectRoot = d3_document.documentElement, d3_selectMatcher = d3_selectRoot.matchesSelector || d3_selectRoot.webkitMatchesSelector || d3_selectRoot.mozMatchesSelector || d3_selectRoot.msMatchesSelector || d3_selectRoot.oMatchesSelector, d3_selectMatches = function(n, s) {\n    return d3_selectMatcher.call(n, s);\n  };\n  if (typeof Sizzle === \"function\") {\n    d3_select = function(s, n) {\n      return Sizzle(s, n)[0] || null;\n    };\n    d3_selectAll = function(s, n) {\n      return Sizzle.uniqueSort(Sizzle(s, n));\n    };\n    d3_selectMatches = Sizzle.matchesSelector;\n  }\n  var d3_selectionPrototype = [];\n  d3.selection = function() {\n    return d3_selectionRoot;\n  };\n  d3.selection.prototype = d3_selectionPrototype;\n  d3_selectionPrototype.select = function(selector) {\n    var subgroups = [], subgroup, subnode, group, node;\n    if (typeof selector !== \"function\") selector = d3_selection_selector(selector);\n    for (var j = -1, m = this.length; ++j < m; ) {\n      subgroups.push(subgroup = []);\n      subgroup.parentNode = (group = this[j]).parentNode;\n      for (var i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) {\n          subgroup.push(subnode = selector.call(node, node.__data__, i));\n          if (subnode && \"__data__\" in node) subnode.__data__ = node.__data__;\n        } else {\n          subgroup.push(null);\n        }\n      }\n    }\n    return d3_selection(subgroups);\n  };\n  function d3_selection_selector(selector) {\n    return function() {\n      return d3_select(selector, this);\n    };\n  }\n  d3_selectionPrototype.selectAll = function(selector) {\n    var subgroups = [], subgroup, node;\n    if (typeof selector !== \"function\") selector = d3_selection_selectorAll(selector);\n    for (var j = -1, m = this.length; ++j < m; ) {\n      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) {\n          subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i)));\n          subgroup.parentNode = node;\n        }\n      }\n    }\n    return d3_selection(subgroups);\n  };\n  function d3_selection_selectorAll(selector) {\n    return function() {\n      return d3_selectAll(selector, this);\n    };\n  }\n  var d3_nsPrefix = {\n    svg: \"http://www.w3.org/2000/svg\",\n    xhtml: \"http://www.w3.org/1999/xhtml\",\n    xlink: \"http://www.w3.org/1999/xlink\",\n    xml: \"http://www.w3.org/XML/1998/namespace\",\n    xmlns: \"http://www.w3.org/2000/xmlns/\"\n  };\n  d3.ns = {\n    prefix: d3_nsPrefix,\n    qualify: function(name) {\n      var i = name.indexOf(\":\"), prefix = name;\n      if (i >= 0) {\n        prefix = name.substring(0, i);\n        name = name.substring(i + 1);\n      }\n      return d3_nsPrefix.hasOwnProperty(prefix) ? {\n        space: d3_nsPrefix[prefix],\n        local: name\n      } : name;\n    }\n  };\n  d3_selectionPrototype.attr = function(name, value) {\n    if (arguments.length < 2) {\n      if (typeof name === \"string\") {\n        var node = this.node();\n        name = d3.ns.qualify(name);\n        return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);\n      }\n      for (value in name) this.each(d3_selection_attr(value, name[value]));\n      return this;\n    }\n    return this.each(d3_selection_attr(name, value));\n  };\n  function d3_selection_attr(name, value) {\n    name = d3.ns.qualify(name);\n    function attrNull() {\n      this.removeAttribute(name);\n    }\n    function attrNullNS() {\n      this.removeAttributeNS(name.space, name.local);\n    }\n    function attrConstant() {\n      this.setAttribute(name, value);\n    }\n    function attrConstantNS() {\n      this.setAttributeNS(name.space, name.local, value);\n    }\n    function attrFunction() {\n      var x = value.apply(this, arguments);\n      if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);\n    }\n    function attrFunctionNS() {\n      var x = value.apply(this, arguments);\n      if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);\n    }\n    return value == null ? name.local ? attrNullNS : attrNull : typeof value === \"function\" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;\n  }\n  function d3_collapse(s) {\n    return s.trim().replace(/\\s+/g, \" \");\n  }\n  d3.requote = function(s) {\n    return s.replace(d3_requote_re, \"\\\\$&\");\n  };\n  var d3_requote_re = /[\\\\\\^\\$\\*\\+\\?\\|\\[\\]\\(\\)\\.\\{\\}]/g;\n  d3_selectionPrototype.classed = function(name, value) {\n    if (arguments.length < 2) {\n      if (typeof name === \"string\") {\n        var node = this.node(), n = (name = name.trim().split(/^|\\s+/g)).length, i = -1;\n        if (value = node.classList) {\n          while (++i < n) if (!value.contains(name[i])) return false;\n        } else {\n          value = node.getAttribute(\"class\");\n          while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;\n        }\n        return true;\n      }\n      for (value in name) this.each(d3_selection_classed(value, name[value]));\n      return this;\n    }\n    return this.each(d3_selection_classed(name, value));\n  };\n  function d3_selection_classedRe(name) {\n    return new RegExp(\"(?:^|\\\\s+)\" + d3.requote(name) + \"(?:\\\\s+|$)\", \"g\");\n  }\n  function d3_selection_classed(name, value) {\n    name = name.trim().split(/\\s+/).map(d3_selection_classedName);\n    var n = name.length;\n    function classedConstant() {\n      var i = -1;\n      while (++i < n) name[i](this, value);\n    }\n    function classedFunction() {\n      var i = -1, x = value.apply(this, arguments);\n      while (++i < n) name[i](this, x);\n    }\n    return typeof value === \"function\" ? classedFunction : classedConstant;\n  }\n  function d3_selection_classedName(name) {\n    var re = d3_selection_classedRe(name);\n    return function(node, value) {\n      if (c = node.classList) return value ? c.add(name) : c.remove(name);\n      var c = node.getAttribute(\"class\") || \"\";\n      if (value) {\n        re.lastIndex = 0;\n        if (!re.test(c)) node.setAttribute(\"class\", d3_collapse(c + \" \" + name));\n      } else {\n        node.setAttribute(\"class\", d3_collapse(c.replace(re, \" \")));\n      }\n    };\n  }\n  d3_selectionPrototype.style = function(name, value, priority) {\n    var n = arguments.length;\n    if (n < 3) {\n      if (typeof name !== \"string\") {\n        if (n < 2) value = \"\";\n        for (priority in name) this.each(d3_selection_style(priority, name[priority], value));\n        return this;\n      }\n      if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name);\n      priority = \"\";\n    }\n    return this.each(d3_selection_style(name, value, priority));\n  };\n  function d3_selection_style(name, value, priority) {\n    function styleNull() {\n      this.style.removeProperty(name);\n    }\n    function styleConstant() {\n      this.style.setProperty(name, value, priority);\n    }\n    function styleFunction() {\n      var x = value.apply(this, arguments);\n      if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);\n    }\n    return value == null ? styleNull : typeof value === \"function\" ? styleFunction : styleConstant;\n  }\n  d3_selectionPrototype.property = function(name, value) {\n    if (arguments.length < 2) {\n      if (typeof name === \"string\") return this.node()[name];\n      for (value in name) this.each(d3_selection_property(value, name[value]));\n      return this;\n    }\n    return this.each(d3_selection_property(name, value));\n  };\n  function d3_selection_property(name, value) {\n    function propertyNull() {\n      delete this[name];\n    }\n    function propertyConstant() {\n      this[name] = value;\n    }\n    function propertyFunction() {\n      var x = value.apply(this, arguments);\n      if (x == null) delete this[name]; else this[name] = x;\n    }\n    return value == null ? propertyNull : typeof value === \"function\" ? propertyFunction : propertyConstant;\n  }\n  d3_selectionPrototype.text = function(value) {\n    return arguments.length ? this.each(typeof value === \"function\" ? function() {\n      var v = value.apply(this, arguments);\n      this.textContent = v == null ? \"\" : v;\n    } : value == null ? function() {\n      this.textContent = \"\";\n    } : function() {\n      this.textContent = value;\n    }) : this.node().textContent;\n  };\n  d3_selectionPrototype.html = function(value) {\n    return arguments.length ? this.each(typeof value === \"function\" ? function() {\n      var v = value.apply(this, arguments);\n      this.innerHTML = v == null ? \"\" : v;\n    } : value == null ? function() {\n      this.innerHTML = \"\";\n    } : function() {\n      this.innerHTML = value;\n    }) : this.node().innerHTML;\n  };\n  d3_selectionPrototype.append = function(name) {\n    name = d3.ns.qualify(name);\n    function append() {\n      return this.appendChild(d3_document.createElementNS(this.namespaceURI, name));\n    }\n    function appendNS() {\n      return this.appendChild(d3_document.createElementNS(name.space, name.local));\n    }\n    return this.select(name.local ? appendNS : append);\n  };\n  d3_selectionPrototype.insert = function(name, before) {\n    name = d3.ns.qualify(name);\n    if (typeof before !== \"function\") before = d3_selection_selector(before);\n    function insert(d, i) {\n      return this.insertBefore(d3_document.createElementNS(this.namespaceURI, name), before.call(this, d, i));\n    }\n    function insertNS(d, i) {\n      return this.insertBefore(d3_document.createElementNS(name.space, name.local), before.call(this, d, i));\n    }\n    return this.select(name.local ? insertNS : insert);\n  };\n  d3_selectionPrototype.remove = function() {\n    return this.each(function() {\n      var parent = this.parentNode;\n      if (parent) parent.removeChild(this);\n    });\n  };\n  d3_selectionPrototype.data = function(value, key) {\n    var i = -1, n = this.length, group, node;\n    if (!arguments.length) {\n      value = new Array(n = (group = this[0]).length);\n      while (++i < n) {\n        if (node = group[i]) {\n          value[i] = node.__data__;\n        }\n      }\n      return value;\n    }\n    function bind(group, groupData) {\n      var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;\n      if (key) {\n        var nodeByKeyValue = new d3_Map(), dataByKeyValue = new d3_Map(), keyValues = [], keyValue;\n        for (i = -1; ++i < n; ) {\n          keyValue = key.call(node = group[i], node.__data__, i);\n          if (nodeByKeyValue.has(keyValue)) {\n            exitNodes[i] = node;\n          } else {\n            nodeByKeyValue.set(keyValue, node);\n          }\n          keyValues.push(keyValue);\n        }\n        for (i = -1; ++i < m; ) {\n          keyValue = key.call(groupData, nodeData = groupData[i], i);\n          if (node = nodeByKeyValue.get(keyValue)) {\n            updateNodes[i] = node;\n            node.__data__ = nodeData;\n          } else if (!dataByKeyValue.has(keyValue)) {\n            enterNodes[i] = d3_selection_dataNode(nodeData);\n          }\n          dataByKeyValue.set(keyValue, nodeData);\n          nodeByKeyValue.remove(keyValue);\n        }\n        for (i = -1; ++i < n; ) {\n          if (nodeByKeyValue.has(keyValues[i])) {\n            exitNodes[i] = group[i];\n          }\n        }\n      } else {\n        for (i = -1; ++i < n0; ) {\n          node = group[i];\n          nodeData = groupData[i];\n          if (node) {\n            node.__data__ = nodeData;\n            updateNodes[i] = node;\n          } else {\n            enterNodes[i] = d3_selection_dataNode(nodeData);\n          }\n        }\n        for (;i < m; ++i) {\n          enterNodes[i] = d3_selection_dataNode(groupData[i]);\n        }\n        for (;i < n; ++i) {\n          exitNodes[i] = group[i];\n        }\n      }\n      enterNodes.update = updateNodes;\n      enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;\n      enter.push(enterNodes);\n      update.push(updateNodes);\n      exit.push(exitNodes);\n    }\n    var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);\n    if (typeof value === \"function\") {\n      while (++i < n) {\n        bind(group = this[i], value.call(group, group.parentNode.__data__, i));\n      }\n    } else {\n      while (++i < n) {\n        bind(group = this[i], value);\n      }\n    }\n    update.enter = function() {\n      return enter;\n    };\n    update.exit = function() {\n      return exit;\n    };\n    return update;\n  };\n  function d3_selection_dataNode(data) {\n    return {\n      __data__: data\n    };\n  }\n  d3_selectionPrototype.datum = function(value) {\n    return arguments.length ? this.property(\"__data__\", value) : this.property(\"__data__\");\n  };\n  d3_selectionPrototype.filter = function(filter) {\n    var subgroups = [], subgroup, group, node;\n    if (typeof filter !== \"function\") filter = d3_selection_filter(filter);\n    for (var j = 0, m = this.length; j < m; j++) {\n      subgroups.push(subgroup = []);\n      subgroup.parentNode = (group = this[j]).parentNode;\n      for (var i = 0, n = group.length; i < n; i++) {\n        if ((node = group[i]) && filter.call(node, node.__data__, i)) {\n          subgroup.push(node);\n        }\n      }\n    }\n    return d3_selection(subgroups);\n  };\n  function d3_selection_filter(selector) {\n    return function() {\n      return d3_selectMatches(this, selector);\n    };\n  }\n  d3_selectionPrototype.order = function() {\n    for (var j = -1, m = this.length; ++j < m; ) {\n      for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {\n        if (node = group[i]) {\n          if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);\n          next = node;\n        }\n      }\n    }\n    return this;\n  };\n  d3_selectionPrototype.sort = function(comparator) {\n    comparator = d3_selection_sortComparator.apply(this, arguments);\n    for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);\n    return this.order();\n  };\n  function d3_selection_sortComparator(comparator) {\n    if (!arguments.length) comparator = d3.ascending;\n    return function(a, b) {\n      return !a - !b || comparator(a.__data__, b.__data__);\n    };\n  }\n  function d3_noop() {}\n  d3_selectionPrototype.on = function(type, listener, capture) {\n    var n = arguments.length;\n    if (n < 3) {\n      if (typeof type !== \"string\") {\n        if (n < 2) listener = false;\n        for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));\n        return this;\n      }\n      if (n < 2) return (n = this.node()[\"__on\" + type]) && n._;\n      capture = false;\n    }\n    return this.each(d3_selection_on(type, listener, capture));\n  };\n  function d3_selection_on(type, listener, capture) {\n    var name = \"__on\" + type, i = type.indexOf(\".\"), wrap = d3_selection_onListener;\n    if (i > 0) type = type.substring(0, i);\n    var filter = d3_selection_onFilters.get(type);\n    if (filter) type = filter, wrap = d3_selection_onFilter;\n    function onRemove() {\n      var l = this[name];\n      if (l) {\n        this.removeEventListener(type, l, l.$);\n        delete this[name];\n      }\n    }\n    function onAdd() {\n      var l = wrap(listener, d3_array(arguments));\n      onRemove.call(this);\n      this.addEventListener(type, this[name] = l, l.$ = capture);\n      l._ = listener;\n    }\n    function removeAll() {\n      var re = new RegExp(\"^__on([^.]+)\" + d3.requote(type) + \"$\"), match;\n      for (var name in this) {\n        if (match = name.match(re)) {\n          var l = this[name];\n          this.removeEventListener(match[1], l, l.$);\n          delete this[name];\n        }\n      }\n    }\n    return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll;\n  }\n  var d3_selection_onFilters = d3.map({\n    mouseenter: \"mouseover\",\n    mouseleave: \"mouseout\"\n  });\n  d3_selection_onFilters.forEach(function(k) {\n    if (\"on\" + k in d3_document) d3_selection_onFilters.remove(k);\n  });\n  function d3_selection_onListener(listener, argumentz) {\n    return function(e) {\n      var o = d3.event;\n      d3.event = e;\n      argumentz[0] = this.__data__;\n      try {\n        listener.apply(this, argumentz);\n      } finally {\n        d3.event = o;\n      }\n    };\n  }\n  function d3_selection_onFilter(listener, argumentz) {\n    var l = d3_selection_onListener(listener, argumentz);\n    return function(e) {\n      var target = this, related = e.relatedTarget;\n      if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) {\n        l.call(target, e);\n      }\n    };\n  }\n  d3_selectionPrototype.each = function(callback) {\n    return d3_selection_each(this, function(node, i, j) {\n      callback.call(node, node.__data__, i, j);\n    });\n  };\n  function d3_selection_each(groups, callback) {\n    for (var j = 0, m = groups.length; j < m; j++) {\n      for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {\n        if (node = group[i]) callback(node, i, j);\n      }\n    }\n    return groups;\n  }\n  d3_selectionPrototype.call = function(callback) {\n    var args = d3_array(arguments);\n    callback.apply(args[0] = this, args);\n    return this;\n  };\n  d3_selectionPrototype.empty = function() {\n    return !this.node();\n  };\n  d3_selectionPrototype.node = function() {\n    for (var j = 0, m = this.length; j < m; j++) {\n      for (var group = this[j], i = 0, n = group.length; i < n; i++) {\n        var node = group[i];\n        if (node) return node;\n      }\n    }\n    return null;\n  };\n  function d3_selection_enter(selection) {\n    d3_arraySubclass(selection, d3_selection_enterPrototype);\n    return selection;\n  }\n  var d3_selection_enterPrototype = [];\n  d3.selection.enter = d3_selection_enter;\n  d3.selection.enter.prototype = d3_selection_enterPrototype;\n  d3_selection_enterPrototype.append = d3_selectionPrototype.append;\n  d3_selection_enterPrototype.insert = d3_selectionPrototype.insert;\n  d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;\n  d3_selection_enterPrototype.node = d3_selectionPrototype.node;\n  d3_selection_enterPrototype.select = function(selector) {\n    var subgroups = [], subgroup, subnode, upgroup, group, node;\n    for (var j = -1, m = this.length; ++j < m; ) {\n      upgroup = (group = this[j]).update;\n      subgroups.push(subgroup = []);\n      subgroup.parentNode = group.parentNode;\n      for (var i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) {\n          subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i));\n          subnode.__data__ = node.__data__;\n        } else {\n          subgroup.push(null);\n        }\n      }\n    }\n    return d3_selection(subgroups);\n  };\n  d3_selectionPrototype.transition = function() {\n    var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = Object.create(d3_transitionInherit);\n    transition.time = Date.now();\n    for (var j = -1, m = this.length; ++j < m; ) {\n      subgroups.push(subgroup = []);\n      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) d3_transitionNode(node, i, id, transition);\n        subgroup.push(node);\n      }\n    }\n    return d3_transition(subgroups, id);\n  };\n  var d3_selectionRoot = d3_selection([ [ d3_document ] ]);\n  d3_selectionRoot[0].parentNode = d3_selectRoot;\n  d3.select = function(selector) {\n    return typeof selector === \"string\" ? d3_selectionRoot.select(selector) : d3_selection([ [ selector ] ]);\n  };\n  d3.selectAll = function(selector) {\n    return typeof selector === \"string\" ? d3_selectionRoot.selectAll(selector) : d3_selection([ d3_array(selector) ]);\n  };\n  d3.behavior.zoom = function() {\n    var translate = [ 0, 0 ], translate0, scale = 1, scale0, scaleExtent = d3_behavior_zoomInfinity, event = d3_eventDispatch(zoom, \"zoom\"), x0, x1, y0, y1, touchtime;\n    function zoom() {\n      this.on(\"mousedown.zoom\", mousedown).on(\"mousemove.zoom\", mousemove).on(d3_behavior_zoomWheel + \".zoom\", mousewheel).on(\"dblclick.zoom\", dblclick).on(\"touchstart.zoom\", touchstart).on(\"touchmove.zoom\", touchmove).on(\"touchend.zoom\", touchstart);\n    }\n    zoom.translate = function(x) {\n      if (!arguments.length) return translate;\n      translate = x.map(Number);\n      rescale();\n      return zoom;\n    };\n    zoom.scale = function(x) {\n      if (!arguments.length) return scale;\n      scale = +x;\n      rescale();\n      return zoom;\n    };\n    zoom.scaleExtent = function(x) {\n      if (!arguments.length) return scaleExtent;\n      scaleExtent = x == null ? d3_behavior_zoomInfinity : x.map(Number);\n      return zoom;\n    };\n    zoom.x = function(z) {\n      if (!arguments.length) return x1;\n      x1 = z;\n      x0 = z.copy();\n      translate = [ 0, 0 ];\n      scale = 1;\n      return zoom;\n    };\n    zoom.y = function(z) {\n      if (!arguments.length) return y1;\n      y1 = z;\n      y0 = z.copy();\n      translate = [ 0, 0 ];\n      scale = 1;\n      return zoom;\n    };\n    function location(p) {\n      return [ (p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale ];\n    }\n    function point(l) {\n      return [ l[0] * scale + translate[0], l[1] * scale + translate[1] ];\n    }\n    function scaleTo(s) {\n      scale = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));\n    }\n    function translateTo(p, l) {\n      l = point(l);\n      translate[0] += p[0] - l[0];\n      translate[1] += p[1] - l[1];\n    }\n    function rescale() {\n      if (x1) x1.domain(x0.range().map(function(x) {\n        return (x - translate[0]) / scale;\n      }).map(x0.invert));\n      if (y1) y1.domain(y0.range().map(function(y) {\n        return (y - translate[1]) / scale;\n      }).map(y0.invert));\n    }\n    function dispatch(event) {\n      rescale();\n      d3.event.preventDefault();\n      event({\n        type: \"zoom\",\n        scale: scale,\n        translate: translate\n      });\n    }\n    function mousedown() {\n      var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, moved = 0, w = d3.select(d3_window).on(\"mousemove.zoom\", mousemove).on(\"mouseup.zoom\", mouseup), l = location(d3.mouse(target));\n      d3_window.focus();\n      d3_eventCancel();\n      function mousemove() {\n        moved = 1;\n        translateTo(d3.mouse(target), l);\n        dispatch(event_);\n      }\n      function mouseup() {\n        if (moved) d3_eventCancel();\n        w.on(\"mousemove.zoom\", null).on(\"mouseup.zoom\", null);\n        if (moved && d3.event.target === eventTarget) w.on(\"click.zoom\", click, true);\n      }\n      function click() {\n        d3_eventCancel();\n        w.on(\"click.zoom\", null);\n      }\n    }\n    function mousewheel() {\n      if (!translate0) translate0 = location(d3.mouse(this));\n      scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * scale);\n      translateTo(d3.mouse(this), translate0);\n      dispatch(event.of(this, arguments));\n    }\n    function mousemove() {\n      translate0 = null;\n    }\n    function dblclick() {\n      var p = d3.mouse(this), l = location(p), k = Math.log(scale) / Math.LN2;\n      scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1));\n      translateTo(p, l);\n      dispatch(event.of(this, arguments));\n    }\n    function touchstart() {\n      var touches = d3.touches(this), now = Date.now();\n      scale0 = scale;\n      translate0 = {};\n      touches.forEach(function(t) {\n        translate0[t.identifier] = location(t);\n      });\n      d3_eventCancel();\n      if (touches.length === 1) {\n        if (now - touchtime < 500) {\n          var p = touches[0], l = location(touches[0]);\n          scaleTo(scale * 2);\n          translateTo(p, l);\n          dispatch(event.of(this, arguments));\n        }\n        touchtime = now;\n      }\n    }\n    function touchmove() {\n      var touches = d3.touches(this), p0 = touches[0], l0 = translate0[p0.identifier];\n      if (p1 = touches[1]) {\n        var p1, l1 = translate0[p1.identifier];\n        p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];\n        l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];\n        scaleTo(d3.event.scale * scale0);\n      }\n      translateTo(p0, l0);\n      touchtime = null;\n      dispatch(event.of(this, arguments));\n    }\n    return d3.rebind(zoom, event, \"on\");\n  };\n  var d3_behavior_zoomInfinity = [ 0, Infinity ];\n  var d3_behavior_zoomDelta, d3_behavior_zoomWheel = \"onwheel\" in d3_document ? (d3_behavior_zoomDelta = function() {\n    return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);\n  }, \"wheel\") : \"onmousewheel\" in d3_document ? (d3_behavior_zoomDelta = function() {\n    return d3.event.wheelDelta;\n  }, \"mousewheel\") : (d3_behavior_zoomDelta = function() {\n    return -d3.event.detail;\n  }, \"MozMousePixelScroll\");\n  function d3_Color() {}\n  d3_Color.prototype.toString = function() {\n    return this.rgb() + \"\";\n  };\n  d3.hsl = function(h, s, l) {\n    return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse(\"\" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l);\n  };\n  function d3_hsl(h, s, l) {\n    return new d3_Hsl(h, s, l);\n  }\n  function d3_Hsl(h, s, l) {\n    this.h = h;\n    this.s = s;\n    this.l = l;\n  }\n  var d3_hslPrototype = d3_Hsl.prototype = new d3_Color();\n  d3_hslPrototype.brighter = function(k) {\n    k = Math.pow(.7, arguments.length ? k : 1);\n    return d3_hsl(this.h, this.s, this.l / k);\n  };\n  d3_hslPrototype.darker = function(k) {\n    k = Math.pow(.7, arguments.length ? k : 1);\n    return d3_hsl(this.h, this.s, k * this.l);\n  };\n  d3_hslPrototype.rgb = function() {\n    return d3_hsl_rgb(this.h, this.s, this.l);\n  };\n  function d3_hsl_rgb(h, s, l) {\n    var m1, m2;\n    h = h % 360;\n    if (h < 0) h += 360;\n    s = s < 0 ? 0 : s > 1 ? 1 : s;\n    l = l < 0 ? 0 : l > 1 ? 1 : l;\n    m2 = l <= .5 ? l * (1 + s) : l + s - l * s;\n    m1 = 2 * l - m2;\n    function v(h) {\n      if (h > 360) h -= 360; else if (h < 0) h += 360;\n      if (h < 60) return m1 + (m2 - m1) * h / 60;\n      if (h < 180) return m2;\n      if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;\n      return m1;\n    }\n    function vv(h) {\n      return Math.round(v(h) * 255);\n    }\n    return d3_rgb(vv(h + 120), vv(h), vv(h - 120));\n  }\n  var π = Math.PI, ε = 1e-6, d3_radians = π / 180, d3_degrees = 180 / π;\n  function d3_sgn(x) {\n    return x > 0 ? 1 : x < 0 ? -1 : 0;\n  }\n  function d3_acos(x) {\n    return Math.acos(Math.max(-1, Math.min(1, x)));\n  }\n  function d3_asin(x) {\n    return x > 1 ? π / 2 : x < -1 ? -π / 2 : Math.asin(x);\n  }\n  function d3_sinh(x) {\n    return (Math.exp(x) - Math.exp(-x)) / 2;\n  }\n  function d3_cosh(x) {\n    return (Math.exp(x) + Math.exp(-x)) / 2;\n  }\n  function d3_haversin(x) {\n    return (x = Math.sin(x / 2)) * x;\n  }\n  d3.hcl = function(h, c, l) {\n    return arguments.length === 1 ? h instanceof d3_Hcl ? d3_hcl(h.h, h.c, h.l) : h instanceof d3_Lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : d3_hcl(+h, +c, +l);\n  };\n  function d3_hcl(h, c, l) {\n    return new d3_Hcl(h, c, l);\n  }\n  function d3_Hcl(h, c, l) {\n    this.h = h;\n    this.c = c;\n    this.l = l;\n  }\n  var d3_hclPrototype = d3_Hcl.prototype = new d3_Color();\n  d3_hclPrototype.brighter = function(k) {\n    return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));\n  };\n  d3_hclPrototype.darker = function(k) {\n    return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));\n  };\n  d3_hclPrototype.rgb = function() {\n    return d3_hcl_lab(this.h, this.c, this.l).rgb();\n  };\n  function d3_hcl_lab(h, c, l) {\n    return d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);\n  }\n  d3.lab = function(l, a, b) {\n    return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b);\n  };\n  function d3_lab(l, a, b) {\n    return new d3_Lab(l, a, b);\n  }\n  function d3_Lab(l, a, b) {\n    this.l = l;\n    this.a = a;\n    this.b = b;\n  }\n  var d3_lab_K = 18;\n  var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;\n  var d3_labPrototype = d3_Lab.prototype = new d3_Color();\n  d3_labPrototype.brighter = function(k) {\n    return d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);\n  };\n  d3_labPrototype.darker = function(k) {\n    return d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);\n  };\n  d3_labPrototype.rgb = function() {\n    return d3_lab_rgb(this.l, this.a, this.b);\n  };\n  function d3_lab_rgb(l, a, b) {\n    var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;\n    x = d3_lab_xyz(x) * d3_lab_X;\n    y = d3_lab_xyz(y) * d3_lab_Y;\n    z = d3_lab_xyz(z) * d3_lab_Z;\n    return d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));\n  }\n  function d3_lab_hcl(l, a, b) {\n    return d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l);\n  }\n  function d3_lab_xyz(x) {\n    return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;\n  }\n  function d3_xyz_lab(x) {\n    return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;\n  }\n  function d3_xyz_rgb(r) {\n    return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));\n  }\n  d3.rgb = function(r, g, b) {\n    return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse(\"\" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b);\n  };\n  function d3_rgb(r, g, b) {\n    return new d3_Rgb(r, g, b);\n  }\n  function d3_Rgb(r, g, b) {\n    this.r = r;\n    this.g = g;\n    this.b = b;\n  }\n  var d3_rgbPrototype = d3_Rgb.prototype = new d3_Color();\n  d3_rgbPrototype.brighter = function(k) {\n    k = Math.pow(.7, arguments.length ? k : 1);\n    var r = this.r, g = this.g, b = this.b, i = 30;\n    if (!r && !g && !b) return d3_rgb(i, i, i);\n    if (r && r < i) r = i;\n    if (g && g < i) g = i;\n    if (b && b < i) b = i;\n    return d3_rgb(Math.min(255, Math.floor(r / k)), Math.min(255, Math.floor(g / k)), Math.min(255, Math.floor(b / k)));\n  };\n  d3_rgbPrototype.darker = function(k) {\n    k = Math.pow(.7, arguments.length ? k : 1);\n    return d3_rgb(Math.floor(k * this.r), Math.floor(k * this.g), Math.floor(k * this.b));\n  };\n  d3_rgbPrototype.hsl = function() {\n    return d3_rgb_hsl(this.r, this.g, this.b);\n  };\n  d3_rgbPrototype.toString = function() {\n    return \"#\" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);\n  };\n  function d3_rgb_hex(v) {\n    return v < 16 ? \"0\" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);\n  }\n  function d3_rgb_parse(format, rgb, hsl) {\n    var r = 0, g = 0, b = 0, m1, m2, name;\n    m1 = /([a-z]+)\\((.*)\\)/i.exec(format);\n    if (m1) {\n      m2 = m1[2].split(\",\");\n      switch (m1[1]) {\n       case \"hsl\":\n        {\n          return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);\n        }\n\n       case \"rgb\":\n        {\n          return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));\n        }\n      }\n    }\n    if (name = d3_rgb_names.get(format)) return rgb(name.r, name.g, name.b);\n    if (format != null && format.charAt(0) === \"#\") {\n      if (format.length === 4) {\n        r = format.charAt(1);\n        r += r;\n        g = format.charAt(2);\n        g += g;\n        b = format.charAt(3);\n        b += b;\n      } else if (format.length === 7) {\n        r = format.substring(1, 3);\n        g = format.substring(3, 5);\n        b = format.substring(5, 7);\n      }\n      r = parseInt(r, 16);\n      g = parseInt(g, 16);\n      b = parseInt(b, 16);\n    }\n    return rgb(r, g, b);\n  }\n  function d3_rgb_hsl(r, g, b) {\n    var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;\n    if (d) {\n      s = l < .5 ? d / (max + min) : d / (2 - max - min);\n      if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;\n      h *= 60;\n    } else {\n      s = h = 0;\n    }\n    return d3_hsl(h, s, l);\n  }\n  function d3_rgb_lab(r, g, b) {\n    r = d3_rgb_xyz(r);\n    g = d3_rgb_xyz(g);\n    b = d3_rgb_xyz(b);\n    var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);\n    return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));\n  }\n  function d3_rgb_xyz(r) {\n    return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);\n  }\n  function d3_rgb_parseNumber(c) {\n    var f = parseFloat(c);\n    return c.charAt(c.length - 1) === \"%\" ? Math.round(f * 2.55) : f;\n  }\n  var d3_rgb_names = d3.map({\n    aliceblue: \"#f0f8ff\",\n    antiquewhite: \"#faebd7\",\n    aqua: \"#00ffff\",\n    aquamarine: \"#7fffd4\",\n    azure: \"#f0ffff\",\n    beige: \"#f5f5dc\",\n    bisque: \"#ffe4c4\",\n    black: \"#000000\",\n    blanchedalmond: \"#ffebcd\",\n    blue: \"#0000ff\",\n    blueviolet: \"#8a2be2\",\n    brown: \"#a52a2a\",\n    burlywood: \"#deb887\",\n    cadetblue: \"#5f9ea0\",\n    chartreuse: \"#7fff00\",\n    chocolate: \"#d2691e\",\n    coral: \"#ff7f50\",\n    cornflowerblue: \"#6495ed\",\n    cornsilk: \"#fff8dc\",\n    crimson: \"#dc143c\",\n    cyan: \"#00ffff\",\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: \"#ff00ff\",\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: \"#778899\",\n    lightslategrey: \"#778899\",\n    lightsteelblue: \"#b0c4de\",\n    lightyellow: \"#ffffe0\",\n    lime: \"#00ff00\",\n    limegreen: \"#32cd32\",\n    linen: \"#faf0e6\",\n    magenta: \"#ff00ff\",\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: \"#ff0000\",\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: \"#ffffff\",\n    whitesmoke: \"#f5f5f5\",\n    yellow: \"#ffff00\",\n    yellowgreen: \"#9acd32\"\n  });\n  d3_rgb_names.forEach(function(key, value) {\n    d3_rgb_names.set(key, d3_rgb_parse(value, d3_rgb, d3_hsl_rgb));\n  });\n  function d3_functor(v) {\n    return typeof v === \"function\" ? v : function() {\n      return v;\n    };\n  }\n  d3.functor = d3_functor;\n  function d3_identity(d) {\n    return d;\n  }\n  d3.xhr = function(url, mimeType, callback) {\n    var xhr = {}, dispatch = d3.dispatch(\"progress\", \"load\", \"error\"), headers = {}, response = d3_identity, request = new (d3_window.XDomainRequest && /^(http(s)?:)?\\/\\//.test(url) ? XDomainRequest : XMLHttpRequest)();\n    \"onload\" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {\n      request.readyState > 3 && respond();\n    };\n    function respond() {\n      var s = request.status;\n      !s && request.responseText || s >= 200 && s < 300 || s === 304 ? dispatch.load.call(xhr, response.call(xhr, request)) : dispatch.error.call(xhr, request);\n    }\n    request.onprogress = function(event) {\n      var o = d3.event;\n      d3.event = event;\n      try {\n        dispatch.progress.call(xhr, request);\n      } finally {\n        d3.event = o;\n      }\n    };\n    xhr.header = function(name, value) {\n      name = (name + \"\").toLowerCase();\n      if (arguments.length < 2) return headers[name];\n      if (value == null) delete headers[name]; else headers[name] = value + \"\";\n      return xhr;\n    };\n    xhr.mimeType = function(value) {\n      if (!arguments.length) return mimeType;\n      mimeType = value == null ? null : value + \"\";\n      return xhr;\n    };\n    xhr.response = function(value) {\n      response = value;\n      return xhr;\n    };\n    [ \"get\", \"post\" ].forEach(function(method) {\n      xhr[method] = function() {\n        return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));\n      };\n    });\n    xhr.send = function(method, data, callback) {\n      if (arguments.length === 2 && typeof data === \"function\") callback = data, data = null;\n      request.open(method, url, true);\n      if (mimeType != null && !(\"accept\" in headers)) headers[\"accept\"] = mimeType + \",*/*\";\n      if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);\n      if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);\n      if (callback != null) xhr.on(\"error\", callback).on(\"load\", function(request) {\n        callback(null, request);\n      });\n      request.send(data == null ? null : data);\n      return xhr;\n    };\n    xhr.abort = function() {\n      request.abort();\n      return xhr;\n    };\n    d3.rebind(xhr, dispatch, \"on\");\n    if (arguments.length === 2 && typeof mimeType === \"function\") callback = mimeType,\n    mimeType = null;\n    return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));\n  };\n  function d3_xhr_fixCallback(callback) {\n    return callback.length === 1 ? function(error, request) {\n      callback(error == null ? request : null);\n    } : callback;\n  }\n  function d3_dsv(delimiter, mimeType) {\n    var reFormat = new RegExp('[\"' + delimiter + \"\\n]\"), delimiterCode = delimiter.charCodeAt(0);\n    function dsv(url, row, callback) {\n      if (arguments.length < 3) callback = row, row = null;\n      var xhr = d3.xhr(url, mimeType, callback);\n      xhr.row = function(_) {\n        return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;\n      };\n      return xhr.row(row);\n    }\n    function response(request) {\n      return dsv.parse(request.responseText);\n    }\n    function typedResponse(f) {\n      return function(request) {\n        return dsv.parse(request.responseText, f);\n      };\n    }\n    dsv.parse = function(text, f) {\n      var o;\n      return dsv.parseRows(text, function(row, i) {\n        if (o) return o(row, i - 1);\n        var a = new Function(\"d\", \"return {\" + row.map(function(name, i) {\n          return JSON.stringify(name) + \": d[\" + i + \"]\";\n        }).join(\",\") + \"}\");\n        o = f ? function(row, i) {\n          return f(a(row), i);\n        } : a;\n      });\n    };\n    dsv.parseRows = function(text, f) {\n      var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;\n      function token() {\n        if (I >= N) return EOF;\n        if (eol) return eol = false, EOL;\n        var j = I;\n        if (text.charCodeAt(j) === 34) {\n          var i = j;\n          while (i++ < N) {\n            if (text.charCodeAt(i) === 34) {\n              if (text.charCodeAt(i + 1) !== 34) break;\n              ++i;\n            }\n          }\n          I = i + 2;\n          var c = text.charCodeAt(i + 1);\n          if (c === 13) {\n            eol = true;\n            if (text.charCodeAt(i + 2) === 10) ++I;\n          } else if (c === 10) {\n            eol = true;\n          }\n          return text.substring(j + 1, i).replace(/\"\"/g, '\"');\n        }\n        while (I < N) {\n          var c = text.charCodeAt(I++), k = 1;\n          if (c === 10) eol = true; else if (c === 13) {\n            eol = true;\n            if (text.charCodeAt(I) === 10) ++I, ++k;\n          } else if (c !== delimiterCode) continue;\n          return text.substring(j, I - k);\n        }\n        return text.substring(j);\n      }\n      while ((t = token()) !== EOF) {\n        var a = [];\n        while (t !== EOL && t !== EOF) {\n          a.push(t);\n          t = token();\n        }\n        if (f && !(a = f(a, n++))) continue;\n        rows.push(a);\n      }\n      return rows;\n    };\n    dsv.format = function(rows) {\n      if (Array.isArray(rows[0])) return dsv.formatRows(rows);\n      var fieldSet = new d3_Set(), fields = [];\n      rows.forEach(function(row) {\n        for (var field in row) {\n          if (!fieldSet.has(field)) {\n            fields.push(fieldSet.add(field));\n          }\n        }\n      });\n      return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) {\n        return fields.map(function(field) {\n          return formatValue(row[field]);\n        }).join(delimiter);\n      })).join(\"\\n\");\n    };\n    dsv.formatRows = function(rows) {\n      return rows.map(formatRow).join(\"\\n\");\n    };\n    function formatRow(row) {\n      return row.map(formatValue).join(delimiter);\n    }\n    function formatValue(text) {\n      return reFormat.test(text) ? '\"' + text.replace(/\\\"/g, '\"\"') + '\"' : text;\n    }\n    return dsv;\n  }\n  d3.csv = d3_dsv(\",\", \"text/csv\");\n  d3.tsv = d3_dsv(\"\\t\", \"text/tab-separated-values\");\n  var d3_timer_id = 0, d3_timer_byId = {}, d3_timer_queue = null, d3_timer_interval, d3_timer_timeout;\n  d3.timer = function(callback, delay, then) {\n    if (arguments.length < 3) {\n      if (arguments.length < 2) delay = 0; else if (!isFinite(delay)) return;\n      then = Date.now();\n    }\n    var timer = d3_timer_byId[callback.id];\n    if (timer && timer.callback === callback) {\n      timer.then = then;\n      timer.delay = delay;\n    } else d3_timer_byId[callback.id = ++d3_timer_id] = d3_timer_queue = {\n      callback: callback,\n      then: then,\n      delay: delay,\n      next: d3_timer_queue\n    };\n    if (!d3_timer_interval) {\n      d3_timer_timeout = clearTimeout(d3_timer_timeout);\n      d3_timer_interval = 1;\n      d3_timer_frame(d3_timer_step);\n    }\n  };\n  function d3_timer_step() {\n    var elapsed, now = Date.now(), t1 = d3_timer_queue;\n    while (t1) {\n      elapsed = now - t1.then;\n      if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed);\n      t1 = t1.next;\n    }\n    var delay = d3_timer_flush() - now;\n    if (delay > 24) {\n      if (isFinite(delay)) {\n        clearTimeout(d3_timer_timeout);\n        d3_timer_timeout = setTimeout(d3_timer_step, delay);\n      }\n      d3_timer_interval = 0;\n    } else {\n      d3_timer_interval = 1;\n      d3_timer_frame(d3_timer_step);\n    }\n  }\n  d3.timer.flush = function() {\n    var elapsed, now = Date.now(), t1 = d3_timer_queue;\n    while (t1) {\n      elapsed = now - t1.then;\n      if (!t1.delay) t1.flush = t1.callback(elapsed);\n      t1 = t1.next;\n    }\n    d3_timer_flush();\n  };\n  function d3_timer_flush() {\n    var t0 = null, t1 = d3_timer_queue, then = Infinity;\n    while (t1) {\n      if (t1.flush) {\n        delete d3_timer_byId[t1.callback.id];\n        t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next;\n      } else {\n        then = Math.min(then, t1.then + t1.delay);\n        t1 = (t0 = t1).next;\n      }\n    }\n    return then;\n  }\n  var d3_timer_frame = d3_window.requestAnimationFrame || d3_window.webkitRequestAnimationFrame || d3_window.mozRequestAnimationFrame || d3_window.oRequestAnimationFrame || d3_window.msRequestAnimationFrame || function(callback) {\n    setTimeout(callback, 17);\n  };\n  var d3_format_decimalPoint = \".\", d3_format_thousandsSeparator = \",\", d3_format_grouping = [ 3, 3 ];\n  var d3_formatPrefixes = [ \"y\", \"z\", \"a\", \"f\", \"p\", \"n\", \"µ\", \"m\", \"\", \"k\", \"M\", \"G\", \"T\", \"P\", \"E\", \"Z\", \"Y\" ].map(d3_formatPrefix);\n  d3.formatPrefix = function(value, precision) {\n    var i = 0;\n    if (value) {\n      if (value < 0) value *= -1;\n      if (precision) value = d3.round(value, d3_format_precision(value, precision));\n      i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);\n      i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3));\n    }\n    return d3_formatPrefixes[8 + i / 3];\n  };\n  function d3_formatPrefix(d, i) {\n    var k = Math.pow(10, Math.abs(8 - i) * 3);\n    return {\n      scale: i > 8 ? function(d) {\n        return d / k;\n      } : function(d) {\n        return d * k;\n      },\n      symbol: d\n    };\n  }\n  d3.round = function(x, n) {\n    return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);\n  };\n  d3.format = function(specifier) {\n    var match = d3_format_re.exec(specifier), fill = match[1] || \" \", align = match[2] || \">\", sign = match[3] || \"\", basePrefix = match[4] || \"\", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, suffix = \"\", integer = false;\n    if (precision) precision = +precision.substring(1);\n    if (zfill || fill === \"0\" && align === \"=\") {\n      zfill = fill = \"0\";\n      align = \"=\";\n      if (comma) width -= Math.floor((width - 1) / 4);\n    }\n    switch (type) {\n     case \"n\":\n      comma = true;\n      type = \"g\";\n      break;\n\n     case \"%\":\n      scale = 100;\n      suffix = \"%\";\n      type = \"f\";\n      break;\n\n     case \"p\":\n      scale = 100;\n      suffix = \"%\";\n      type = \"r\";\n      break;\n\n     case \"b\":\n     case \"o\":\n     case \"x\":\n     case \"X\":\n      if (basePrefix) basePrefix = \"0\" + type.toLowerCase();\n\n     case \"c\":\n     case \"d\":\n      integer = true;\n      precision = 0;\n      break;\n\n     case \"s\":\n      scale = -1;\n      type = \"r\";\n      break;\n    }\n    if (basePrefix === \"#\") basePrefix = \"\";\n    if (type == \"r\" && !precision) type = \"g\";\n    if (precision != null) {\n      if (type == \"g\") precision = Math.max(1, Math.min(21, precision)); else if (type == \"e\" || type == \"f\") precision = Math.max(0, Math.min(20, precision));\n    }\n    type = d3_format_types.get(type) || d3_format_typeDefault;\n    var zcomma = zfill && comma;\n    return function(value) {\n      if (integer && value % 1) return \"\";\n      var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, \"-\") : sign;\n      if (scale < 0) {\n        var prefix = d3.formatPrefix(value, precision);\n        value = prefix.scale(value);\n        suffix = prefix.symbol;\n      } else {\n        value *= scale;\n      }\n      value = type(value, precision);\n      if (!zfill && comma) value = d3_format_group(value);\n      var length = basePrefix.length + value.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : \"\";\n      if (zcomma) value = d3_format_group(padding + value);\n      if (d3_format_decimalPoint) value.replace(\".\", d3_format_decimalPoint);\n      negative += basePrefix;\n      return (align === \"<\" ? negative + value + padding : align === \">\" ? padding + negative + value : align === \"^\" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + suffix;\n    };\n  };\n  var d3_format_re = /(?:([^{])?([<>=^]))?([+\\- ])?(#)?(0)?(\\d+)?(,)?(\\.-?\\d+)?([a-z%])?/i;\n  var d3_format_types = d3.map({\n    b: function(x) {\n      return x.toString(2);\n    },\n    c: function(x) {\n      return String.fromCharCode(x);\n    },\n    o: function(x) {\n      return x.toString(8);\n    },\n    x: function(x) {\n      return x.toString(16);\n    },\n    X: function(x) {\n      return x.toString(16).toUpperCase();\n    },\n    g: function(x, p) {\n      return x.toPrecision(p);\n    },\n    e: function(x, p) {\n      return x.toExponential(p);\n    },\n    f: function(x, p) {\n      return x.toFixed(p);\n    },\n    r: function(x, p) {\n      return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));\n    }\n  });\n  function d3_format_precision(x, p) {\n    return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);\n  }\n  function d3_format_typeDefault(x) {\n    return x + \"\";\n  }\n  var d3_format_group = d3_identity;\n  if (d3_format_grouping) {\n    var d3_format_groupingLength = d3_format_grouping.length;\n    d3_format_group = function(value) {\n      var i = value.lastIndexOf(\".\"), f = i >= 0 ? \".\" + value.substring(i + 1) : (i = value.length,\n      \"\"), t = [], j = 0, g = d3_format_grouping[0];\n      while (i > 0 && g > 0) {\n        t.push(value.substring(i -= g, i + g));\n        g = d3_format_grouping[j = (j + 1) % d3_format_groupingLength];\n      }\n      return t.reverse().join(d3_format_thousandsSeparator || \"\") + f;\n    };\n  }\n  d3.geo = {};\n  d3.geo.stream = function(object, listener) {\n    if (d3_geo_streamObjectType.hasOwnProperty(object.type)) {\n      d3_geo_streamObjectType[object.type](object, listener);\n    } else {\n      d3_geo_streamGeometry(object, listener);\n    }\n  };\n  function d3_geo_streamGeometry(geometry, listener) {\n    if (d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {\n      d3_geo_streamGeometryType[geometry.type](geometry, listener);\n    }\n  }\n  var d3_geo_streamObjectType = {\n    Feature: function(feature, listener) {\n      d3_geo_streamGeometry(feature.geometry, listener);\n    },\n    FeatureCollection: function(object, listener) {\n      var features = object.features, i = -1, n = features.length;\n      while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);\n    }\n  };\n  var d3_geo_streamGeometryType = {\n    Sphere: function(object, listener) {\n      listener.sphere();\n    },\n    Point: function(object, listener) {\n      var coordinate = object.coordinates;\n      listener.point(coordinate[0], coordinate[1]);\n    },\n    MultiPoint: function(object, listener) {\n      var coordinates = object.coordinates, i = -1, n = coordinates.length, coordinate;\n      while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]);\n    },\n    LineString: function(object, listener) {\n      d3_geo_streamLine(object.coordinates, listener, 0);\n    },\n    MultiLineString: function(object, listener) {\n      var coordinates = object.coordinates, i = -1, n = coordinates.length;\n      while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);\n    },\n    Polygon: function(object, listener) {\n      d3_geo_streamPolygon(object.coordinates, listener);\n    },\n    MultiPolygon: function(object, listener) {\n      var coordinates = object.coordinates, i = -1, n = coordinates.length;\n      while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);\n    },\n    GeometryCollection: function(object, listener) {\n      var geometries = object.geometries, i = -1, n = geometries.length;\n      while (++i < n) d3_geo_streamGeometry(geometries[i], listener);\n    }\n  };\n  function d3_geo_streamLine(coordinates, listener, closed) {\n    var i = -1, n = coordinates.length - closed, coordinate;\n    listener.lineStart();\n    while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]);\n    listener.lineEnd();\n  }\n  function d3_geo_streamPolygon(coordinates, listener) {\n    var i = -1, n = coordinates.length;\n    listener.polygonStart();\n    while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);\n    listener.polygonEnd();\n  }\n  d3.geo.area = function(object) {\n    d3_geo_areaSum = 0;\n    d3.geo.stream(object, d3_geo_area);\n    return d3_geo_areaSum;\n  };\n  var d3_geo_areaSum, d3_geo_areaRingU, d3_geo_areaRingV;\n  var d3_geo_area = {\n    sphere: function() {\n      d3_geo_areaSum += 4 * π;\n    },\n    point: d3_noop,\n    lineStart: d3_noop,\n    lineEnd: d3_noop,\n    polygonStart: function() {\n      d3_geo_areaRingU = 1, d3_geo_areaRingV = 0;\n      d3_geo_area.lineStart = d3_geo_areaRingStart;\n    },\n    polygonEnd: function() {\n      var area = 2 * Math.atan2(d3_geo_areaRingV, d3_geo_areaRingU);\n      d3_geo_areaSum += area < 0 ? 4 * π + area : area;\n      d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;\n    }\n  };\n  function d3_geo_areaRingStart() {\n    var λ00, φ00, λ0, cosφ0, sinφ0;\n    d3_geo_area.point = function(λ, φ) {\n      d3_geo_area.point = nextPoint;\n      λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4),\n      sinφ0 = Math.sin(φ);\n    };\n    function nextPoint(λ, φ) {\n      λ *= d3_radians;\n      φ = φ * d3_radians / 2 + π / 4;\n      var dλ = λ - λ0, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u0 = d3_geo_areaRingU, v0 = d3_geo_areaRingV, u = cosφ0 * cosφ + k * Math.cos(dλ), v = k * Math.sin(dλ);\n      d3_geo_areaRingU = u0 * u - v0 * v;\n      d3_geo_areaRingV = v0 * u + u0 * v;\n      λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;\n    }\n    d3_geo_area.lineEnd = function() {\n      nextPoint(λ00, φ00);\n    };\n  }\n  d3.geo.bounds = d3_geo_bounds(d3_identity);\n  function d3_geo_bounds(projectStream) {\n    var x0, y0, x1, y1;\n    var bound = {\n      point: boundPoint,\n      lineStart: d3_noop,\n      lineEnd: d3_noop,\n      polygonStart: function() {\n        bound.lineEnd = boundPolygonLineEnd;\n      },\n      polygonEnd: function() {\n        bound.point = boundPoint;\n      }\n    };\n    function boundPoint(x, y) {\n      if (x < x0) x0 = x;\n      if (x > x1) x1 = x;\n      if (y < y0) y0 = y;\n      if (y > y1) y1 = y;\n    }\n    function boundPolygonLineEnd() {\n      bound.point = bound.lineEnd = d3_noop;\n    }\n    return function(feature) {\n      y1 = x1 = -(x0 = y0 = Infinity);\n      d3.geo.stream(feature, projectStream(bound));\n      return [ [ x0, y0 ], [ x1, y1 ] ];\n    };\n  }\n  d3.geo.centroid = function(object) {\n    d3_geo_centroidDimension = d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;\n    d3.geo.stream(object, d3_geo_centroid);\n    var m;\n    if (d3_geo_centroidW && Math.abs(m = Math.sqrt(d3_geo_centroidX * d3_geo_centroidX + d3_geo_centroidY * d3_geo_centroidY + d3_geo_centroidZ * d3_geo_centroidZ)) > ε) {\n      return [ Math.atan2(d3_geo_centroidY, d3_geo_centroidX) * d3_degrees, Math.asin(Math.max(-1, Math.min(1, d3_geo_centroidZ / m))) * d3_degrees ];\n    }\n  };\n  var d3_geo_centroidDimension, d3_geo_centroidW, d3_geo_centroidX, d3_geo_centroidY, d3_geo_centroidZ;\n  var d3_geo_centroid = {\n    sphere: function() {\n      if (d3_geo_centroidDimension < 2) {\n        d3_geo_centroidDimension = 2;\n        d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;\n      }\n    },\n    point: d3_geo_centroidPoint,\n    lineStart: d3_geo_centroidLineStart,\n    lineEnd: d3_geo_centroidLineEnd,\n    polygonStart: function() {\n      if (d3_geo_centroidDimension < 2) {\n        d3_geo_centroidDimension = 2;\n        d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;\n      }\n      d3_geo_centroid.lineStart = d3_geo_centroidRingStart;\n    },\n    polygonEnd: function() {\n      d3_geo_centroid.lineStart = d3_geo_centroidLineStart;\n    }\n  };\n  function d3_geo_centroidPoint(λ, φ) {\n    if (d3_geo_centroidDimension) return;\n    ++d3_geo_centroidW;\n    λ *= d3_radians;\n    var cosφ = Math.cos(φ *= d3_radians);\n    d3_geo_centroidX += (cosφ * Math.cos(λ) - d3_geo_centroidX) / d3_geo_centroidW;\n    d3_geo_centroidY += (cosφ * Math.sin(λ) - d3_geo_centroidY) / d3_geo_centroidW;\n    d3_geo_centroidZ += (Math.sin(φ) - d3_geo_centroidZ) / d3_geo_centroidW;\n  }\n  function d3_geo_centroidRingStart() {\n    var λ00, φ00;\n    d3_geo_centroidDimension = 1;\n    d3_geo_centroidLineStart();\n    d3_geo_centroidDimension = 2;\n    var linePoint = d3_geo_centroid.point;\n    d3_geo_centroid.point = function(λ, φ) {\n      linePoint(λ00 = λ, φ00 = φ);\n    };\n    d3_geo_centroid.lineEnd = function() {\n      d3_geo_centroid.point(λ00, φ00);\n      d3_geo_centroidLineEnd();\n      d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;\n    };\n  }\n  function d3_geo_centroidLineStart() {\n    var x0, y0, z0;\n    if (d3_geo_centroidDimension > 1) return;\n    if (d3_geo_centroidDimension < 1) {\n      d3_geo_centroidDimension = 1;\n      d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;\n    }\n    d3_geo_centroid.point = function(λ, φ) {\n      λ *= d3_radians;\n      var cosφ = Math.cos(φ *= d3_radians);\n      x0 = cosφ * Math.cos(λ);\n      y0 = cosφ * Math.sin(λ);\n      z0 = Math.sin(φ);\n      d3_geo_centroid.point = nextPoint;\n    };\n    function nextPoint(λ, φ) {\n      λ *= d3_radians;\n      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);\n      d3_geo_centroidW += w;\n      d3_geo_centroidX += w * (x0 + (x0 = x));\n      d3_geo_centroidY += w * (y0 + (y0 = y));\n      d3_geo_centroidZ += w * (z0 + (z0 = z));\n    }\n  }\n  function d3_geo_centroidLineEnd() {\n    d3_geo_centroid.point = d3_geo_centroidPoint;\n  }\n  function d3_geo_cartesian(spherical) {\n    var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ);\n    return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ];\n  }\n  function d3_geo_cartesianDot(a, b) {\n    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\n  }\n  function d3_geo_cartesianCross(a, b) {\n    return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ];\n  }\n  function d3_geo_cartesianAdd(a, b) {\n    a[0] += b[0];\n    a[1] += b[1];\n    a[2] += b[2];\n  }\n  function d3_geo_cartesianScale(vector, k) {\n    return [ vector[0] * k, vector[1] * k, vector[2] * k ];\n  }\n  function d3_geo_cartesianNormalize(d) {\n    var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);\n    d[0] /= l;\n    d[1] /= l;\n    d[2] /= l;\n  }\n  function d3_true() {\n    return true;\n  }\n  function d3_geo_spherical(cartesian) {\n    return [ Math.atan2(cartesian[1], cartesian[0]), Math.asin(Math.max(-1, Math.min(1, cartesian[2]))) ];\n  }\n  function d3_geo_sphericalEqual(a, b) {\n    return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε;\n  }\n  function d3_geo_clipPolygon(segments, compare, inside, interpolate, listener) {\n    var subject = [], clip = [];\n    segments.forEach(function(segment) {\n      if ((n = segment.length - 1) <= 0) return;\n      var n, p0 = segment[0], p1 = segment[n];\n      if (d3_geo_sphericalEqual(p0, p1)) {\n        listener.lineStart();\n        for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);\n        listener.lineEnd();\n        return;\n      }\n      var a = {\n        point: p0,\n        points: segment,\n        other: null,\n        visited: false,\n        entry: true,\n        subject: true\n      }, b = {\n        point: p0,\n        points: [ p0 ],\n        other: a,\n        visited: false,\n        entry: false,\n        subject: false\n      };\n      a.other = b;\n      subject.push(a);\n      clip.push(b);\n      a = {\n        point: p1,\n        points: [ p1 ],\n        other: null,\n        visited: false,\n        entry: false,\n        subject: true\n      };\n      b = {\n        point: p1,\n        points: [ p1 ],\n        other: a,\n        visited: false,\n        entry: true,\n        subject: false\n      };\n      a.other = b;\n      subject.push(a);\n      clip.push(b);\n    });\n    clip.sort(compare);\n    d3_geo_clipPolygonLinkCircular(subject);\n    d3_geo_clipPolygonLinkCircular(clip);\n    if (!subject.length) return;\n    if (inside) for (var i = 1, e = !inside(clip[0].point), n = clip.length; i < n; ++i) {\n      clip[i].entry = e = !e;\n    }\n    var start = subject[0], current, points, point;\n    while (1) {\n      current = start;\n      while (current.visited) if ((current = current.next) === start) return;\n      points = current.points;\n      listener.lineStart();\n      do {\n        current.visited = current.other.visited = true;\n        if (current.entry) {\n          if (current.subject) {\n            for (var i = 0; i < points.length; i++) listener.point((point = points[i])[0], point[1]);\n          } else {\n            interpolate(current.point, current.next.point, 1, listener);\n          }\n          current = current.next;\n        } else {\n          if (current.subject) {\n            points = current.prev.points;\n            for (var i = points.length; --i >= 0; ) listener.point((point = points[i])[0], point[1]);\n          } else {\n            interpolate(current.point, current.prev.point, -1, listener);\n          }\n          current = current.prev;\n        }\n        current = current.other;\n        points = current.points;\n      } while (!current.visited);\n      listener.lineEnd();\n    }\n  }\n  function d3_geo_clipPolygonLinkCircular(array) {\n    if (!(n = array.length)) return;\n    var n, i = 0, a = array[0], b;\n    while (++i < n) {\n      a.next = b = array[i];\n      b.prev = a;\n      a = b;\n    }\n    a.next = b = array[0];\n    b.prev = a;\n  }\n  function d3_geo_clip(pointVisible, clipLine, interpolate) {\n    return function(listener) {\n      var line = clipLine(listener);\n      var clip = {\n        point: point,\n        lineStart: lineStart,\n        lineEnd: lineEnd,\n        polygonStart: function() {\n          clip.point = pointRing;\n          clip.lineStart = ringStart;\n          clip.lineEnd = ringEnd;\n          invisible = false;\n          invisibleArea = visibleArea = 0;\n          segments = [];\n          listener.polygonStart();\n        },\n        polygonEnd: function() {\n          clip.point = point;\n          clip.lineStart = lineStart;\n          clip.lineEnd = lineEnd;\n          segments = d3.merge(segments);\n          if (segments.length) {\n            d3_geo_clipPolygon(segments, d3_geo_clipSort, null, interpolate, listener);\n          } else if (visibleArea < -ε || invisible && invisibleArea < -ε) {\n            listener.lineStart();\n            interpolate(null, null, 1, listener);\n            listener.lineEnd();\n          }\n          listener.polygonEnd();\n          segments = null;\n        },\n        sphere: function() {\n          listener.polygonStart();\n          listener.lineStart();\n          interpolate(null, null, 1, listener);\n          listener.lineEnd();\n          listener.polygonEnd();\n        }\n      };\n      function point(λ, φ) {\n        if (pointVisible(λ, φ)) listener.point(λ, φ);\n      }\n      function pointLine(λ, φ) {\n        line.point(λ, φ);\n      }\n      function lineStart() {\n        clip.point = pointLine;\n        line.lineStart();\n      }\n      function lineEnd() {\n        clip.point = point;\n        line.lineEnd();\n      }\n      var segments, visibleArea, invisibleArea, invisible;\n      var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), ring;\n      function pointRing(λ, φ) {\n        ringListener.point(λ, φ);\n        ring.push([ λ, φ ]);\n      }\n      function ringStart() {\n        ringListener.lineStart();\n        ring = [];\n      }\n      function ringEnd() {\n        pointRing(ring[0][0], ring[0][1]);\n        ringListener.lineEnd();\n        var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;\n        if (!n) {\n          invisible = true;\n          invisibleArea += d3_geo_clipAreaRing(ring, -1);\n          ring = null;\n          return;\n        }\n        ring = null;\n        if (clean & 1) {\n          segment = ringSegments[0];\n          visibleArea += d3_geo_clipAreaRing(segment, 1);\n          var n = segment.length - 1, i = -1, point;\n          listener.lineStart();\n          while (++i < n) listener.point((point = segment[i])[0], point[1]);\n          listener.lineEnd();\n          return;\n        }\n        if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));\n        segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));\n      }\n      return clip;\n    };\n  }\n  function d3_geo_clipSegmentLength1(segment) {\n    return segment.length > 1;\n  }\n  function d3_geo_clipBufferListener() {\n    var lines = [], line;\n    return {\n      lineStart: function() {\n        lines.push(line = []);\n      },\n      point: function(λ, φ) {\n        line.push([ λ, φ ]);\n      },\n      lineEnd: d3_noop,\n      buffer: function() {\n        var buffer = lines;\n        lines = [];\n        line = null;\n        return buffer;\n      },\n      rejoin: function() {\n        if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));\n      }\n    };\n  }\n  function d3_geo_clipAreaRing(ring, invisible) {\n    if (!(n = ring.length)) return 0;\n    var n, i = 0, area = 0, p = ring[0], λ = p[0], φ = p[1], cosφ = Math.cos(φ), x0 = Math.atan2(invisible * Math.sin(λ) * cosφ, Math.sin(φ)), y0 = 1 - invisible * Math.cos(λ) * cosφ, x1 = x0, x, y;\n    while (++i < n) {\n      p = ring[i];\n      cosφ = Math.cos(φ = p[1]);\n      x = Math.atan2(invisible * Math.sin(λ = p[0]) * cosφ, Math.sin(φ));\n      y = 1 - invisible * Math.cos(λ) * cosφ;\n      if (Math.abs(y0 - 2) < ε && Math.abs(y - 2) < ε) continue;\n      if (Math.abs(y) < ε || Math.abs(y0) < ε) {} else if (Math.abs(Math.abs(x - x0) - π) < ε) {\n        if (y + y0 > 2) area += 4 * (x - x0);\n      } else if (Math.abs(y0 - 2) < ε) area += 4 * (x - x1); else area += ((3 * π + x - x0) % (2 * π) - π) * (y0 + y);\n      x1 = x0, x0 = x, y0 = y;\n    }\n    return area;\n  }\n  function d3_geo_clipSort(a, b) {\n    return ((a = a.point)[0] < 0 ? a[1] - π / 2 - ε : π / 2 - a[1]) - ((b = b.point)[0] < 0 ? b[1] - π / 2 - ε : π / 2 - b[1]);\n  }\n  var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate);\n  function d3_geo_clipAntimeridianLine(listener) {\n    var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean;\n    return {\n      lineStart: function() {\n        listener.lineStart();\n        clean = 1;\n      },\n      point: function(λ1, φ1) {\n        var sλ1 = λ1 > 0 ? π : -π, dλ = Math.abs(λ1 - λ0);\n        if (Math.abs(dλ - π) < ε) {\n          listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? π / 2 : -π / 2);\n          listener.point(sλ0, φ0);\n          listener.lineEnd();\n          listener.lineStart();\n          listener.point(sλ1, φ0);\n          listener.point(λ1, φ0);\n          clean = 0;\n        } else if (sλ0 !== sλ1 && dλ >= π) {\n          if (Math.abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;\n          if (Math.abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;\n          φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);\n          listener.point(sλ0, φ0);\n          listener.lineEnd();\n          listener.lineStart();\n          listener.point(sλ1, φ0);\n          clean = 0;\n        }\n        listener.point(λ0 = λ1, φ0 = φ1);\n        sλ0 = sλ1;\n      },\n      lineEnd: function() {\n        listener.lineEnd();\n        λ0 = φ0 = NaN;\n      },\n      clean: function() {\n        return 2 - clean;\n      }\n    };\n  }\n  function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {\n    var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1);\n    return Math.abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2;\n  }\n  function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {\n    var φ;\n    if (from == null) {\n      φ = direction * π / 2;\n      listener.point(-π, φ);\n      listener.point(0, φ);\n      listener.point(π, φ);\n      listener.point(π, 0);\n      listener.point(π, -φ);\n      listener.point(0, -φ);\n      listener.point(-π, -φ);\n      listener.point(-π, 0);\n      listener.point(-π, φ);\n    } else if (Math.abs(from[0] - to[0]) > ε) {\n      var s = (from[0] < to[0] ? 1 : -1) * π;\n      φ = direction * s / 2;\n      listener.point(-s, φ);\n      listener.point(0, φ);\n      listener.point(s, φ);\n    } else {\n      listener.point(to[0], to[1]);\n    }\n  }\n  function d3_geo_clipCircle(radius) {\n    var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = Math.abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);\n    return d3_geo_clip(visible, clipLine, interpolate);\n    function visible(λ, φ) {\n      return Math.cos(λ) * Math.cos(φ) > cr;\n    }\n    function clipLine(listener) {\n      var point0, c0, v0, v00, clean;\n      return {\n        lineStart: function() {\n          v00 = v0 = false;\n          clean = 1;\n        },\n        point: function(λ, φ) {\n          var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;\n          if (!point0 && (v00 = v0 = v)) listener.lineStart();\n          if (v !== v0) {\n            point2 = intersect(point0, point1);\n            if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {\n              point1[0] += ε;\n              point1[1] += ε;\n              v = visible(point1[0], point1[1]);\n            }\n          }\n          if (v !== v0) {\n            clean = 0;\n            if (v) {\n              listener.lineStart();\n              point2 = intersect(point1, point0);\n              listener.point(point2[0], point2[1]);\n            } else {\n              point2 = intersect(point0, point1);\n              listener.point(point2[0], point2[1]);\n              listener.lineEnd();\n            }\n            point0 = point2;\n          } else if (notHemisphere && point0 && smallRadius ^ v) {\n            var t;\n            if (!(c & c0) && (t = intersect(point1, point0, true))) {\n              clean = 0;\n              if (smallRadius) {\n                listener.lineStart();\n                listener.point(t[0][0], t[0][1]);\n                listener.point(t[1][0], t[1][1]);\n                listener.lineEnd();\n              } else {\n                listener.point(t[1][0], t[1][1]);\n                listener.lineEnd();\n                listener.lineStart();\n                listener.point(t[0][0], t[0][1]);\n              }\n            }\n          }\n          if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {\n            listener.point(point1[0], point1[1]);\n          }\n          point0 = point1, v0 = v, c0 = c;\n        },\n        lineEnd: function() {\n          if (v0) listener.lineEnd();\n          point0 = null;\n        },\n        clean: function() {\n          return clean | (v00 && v0) << 1;\n        }\n      };\n    }\n    function intersect(a, b, two) {\n      var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b);\n      var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;\n      if (!determinant) return !two && a;\n      var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2);\n      d3_geo_cartesianAdd(A, B);\n      var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);\n      if (t2 < 0) return;\n      var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu);\n      d3_geo_cartesianAdd(q, A);\n      q = d3_geo_spherical(q);\n      if (!two) return q;\n      var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z;\n      if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;\n      var δλ = λ1 - λ0, polar = Math.abs(δλ - π) < ε, meridian = polar || δλ < ε;\n      if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;\n      if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (Math.abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {\n        var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);\n        d3_geo_cartesianAdd(q1, A);\n        return [ q, d3_geo_spherical(q1) ];\n      }\n    }\n    function code(λ, φ) {\n      var r = smallRadius ? radius : π - radius, code = 0;\n      if (λ < -r) code |= 1; else if (λ > r) code |= 2;\n      if (φ < -r) code |= 4; else if (φ > r) code |= 8;\n      return code;\n    }\n  }\n  var d3_geo_clipViewMAX = 1e9;\n  function d3_geo_clipView(x0, y0, x1, y1) {\n    return function(listener) {\n      var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), segments, polygon, ring;\n      var clip = {\n        point: point,\n        lineStart: lineStart,\n        lineEnd: lineEnd,\n        polygonStart: function() {\n          listener = bufferListener;\n          segments = [];\n          polygon = [];\n        },\n        polygonEnd: function() {\n          listener = listener_;\n          if ((segments = d3.merge(segments)).length) {\n            listener.polygonStart();\n            d3_geo_clipPolygon(segments, compare, inside, interpolate, listener);\n            listener.polygonEnd();\n          } else if (insidePolygon([ x0, y0 ])) {\n            listener.polygonStart(), listener.lineStart();\n            interpolate(null, null, 1, listener);\n            listener.lineEnd(), listener.polygonEnd();\n          }\n          segments = polygon = ring = null;\n        }\n      };\n      function inside(point) {\n        var a = corner(point, -1), i = insidePolygon([ a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0 ]);\n        return i;\n      }\n      function insidePolygon(p) {\n        var wn = 0, n = polygon.length, y = p[1];\n        for (var i = 0; i < n; ++i) {\n          for (var j = 1, v = polygon[i], m = v.length, a = v[0]; j < m; ++j) {\n            b = v[j];\n            if (a[1] <= y) {\n              if (b[1] > y && isLeft(a, b, p) > 0) ++wn;\n            } else {\n              if (b[1] <= y && isLeft(a, b, p) < 0) --wn;\n            }\n            a = b;\n          }\n        }\n        return wn !== 0;\n      }\n      function isLeft(a, b, c) {\n        return (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]);\n      }\n      function interpolate(from, to, direction, listener) {\n        var a = 0, a1 = 0;\n        if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) {\n          do {\n            listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);\n          } while ((a = (a + direction + 4) % 4) !== a1);\n        } else {\n          listener.point(to[0], to[1]);\n        }\n      }\n      function visible(x, y) {\n        return x0 <= x && x <= x1 && y0 <= y && y <= y1;\n      }\n      function point(x, y) {\n        if (visible(x, y)) listener.point(x, y);\n      }\n      var x__, y__, v__, x_, y_, v_, first;\n      function lineStart() {\n        clip.point = linePoint;\n        if (polygon) polygon.push(ring = []);\n        first = true;\n        v_ = false;\n        x_ = y_ = NaN;\n      }\n      function lineEnd() {\n        if (segments) {\n          linePoint(x__, y__);\n          if (v__ && v_) bufferListener.rejoin();\n          segments.push(bufferListener.buffer());\n        }\n        clip.point = point;\n        if (v_) listener.lineEnd();\n      }\n      function linePoint(x, y) {\n        x = Math.max(-d3_geo_clipViewMAX, Math.min(d3_geo_clipViewMAX, x));\n        y = Math.max(-d3_geo_clipViewMAX, Math.min(d3_geo_clipViewMAX, y));\n        var v = visible(x, y);\n        if (polygon) ring.push([ x, y ]);\n        if (first) {\n          x__ = x, y__ = y, v__ = v;\n          first = false;\n          if (v) {\n            listener.lineStart();\n            listener.point(x, y);\n          }\n        } else {\n          if (v && v_) listener.point(x, y); else {\n            var a = [ x_, y_ ], b = [ x, y ];\n            if (clipLine(a, b)) {\n              if (!v_) {\n                listener.lineStart();\n                listener.point(a[0], a[1]);\n              }\n              listener.point(b[0], b[1]);\n              if (!v) listener.lineEnd();\n            } else {\n              listener.lineStart();\n              listener.point(x, y);\n            }\n          }\n        }\n        x_ = x, y_ = y, v_ = v;\n      }\n      return clip;\n    };\n    function corner(p, direction) {\n      return Math.abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : Math.abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : Math.abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;\n    }\n    function compare(a, b) {\n      return comparePoints(a.point, b.point);\n    }\n    function comparePoints(a, b) {\n      var ca = corner(a, 1), cb = corner(b, 1);\n      return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];\n    }\n    function clipLine(a, b) {\n      var dx = b[0] - a[0], dy = b[1] - a[1], t = [ 0, 1 ];\n      if (Math.abs(dx) < ε && Math.abs(dy) < ε) return x0 <= a[0] && a[0] <= x1 && y0 <= a[1] && a[1] <= y1;\n      if (d3_geo_clipViewT(x0 - a[0], dx, t) && d3_geo_clipViewT(a[0] - x1, -dx, t) && d3_geo_clipViewT(y0 - a[1], dy, t) && d3_geo_clipViewT(a[1] - y1, -dy, t)) {\n        if (t[1] < 1) {\n          b[0] = a[0] + t[1] * dx;\n          b[1] = a[1] + t[1] * dy;\n        }\n        if (t[0] > 0) {\n          a[0] += t[0] * dx;\n          a[1] += t[0] * dy;\n        }\n        return true;\n      }\n      return false;\n    }\n  }\n  function d3_geo_clipViewT(num, denominator, t) {\n    if (Math.abs(denominator) < ε) return num <= 0;\n    var u = num / denominator;\n    if (denominator > 0) {\n      if (u > t[1]) return false;\n      if (u > t[0]) t[0] = u;\n    } else {\n      if (u < t[0]) return false;\n      if (u < t[1]) t[1] = u;\n    }\n    return true;\n  }\n  function d3_geo_compose(a, b) {\n    function compose(x, y) {\n      return x = a(x, y), b(x[0], x[1]);\n    }\n    if (a.invert && b.invert) compose.invert = function(x, y) {\n      return x = b.invert(x, y), x && a.invert(x[0], x[1]);\n    };\n    return compose;\n  }\n  function d3_geo_resample(project) {\n    var δ2 = .5, maxDepth = 16;\n    function resample(stream) {\n      var λ0, x0, y0, a0, b0, c0;\n      var resample = {\n        point: point,\n        lineStart: lineStart,\n        lineEnd: lineEnd,\n        polygonStart: function() {\n          stream.polygonStart();\n          resample.lineStart = polygonLineStart;\n        },\n        polygonEnd: function() {\n          stream.polygonEnd();\n          resample.lineStart = lineStart;\n        }\n      };\n      function point(x, y) {\n        x = project(x, y);\n        stream.point(x[0], x[1]);\n      }\n      function lineStart() {\n        x0 = NaN;\n        resample.point = linePoint;\n        stream.lineStart();\n      }\n      function linePoint(λ, φ) {\n        var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ);\n        resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);\n        stream.point(x0, y0);\n      }\n      function lineEnd() {\n        resample.point = point;\n        stream.lineEnd();\n      }\n      function polygonLineStart() {\n        var λ00, φ00, x00, y00, a00, b00, c00;\n        lineStart();\n        resample.point = function(λ, φ) {\n          linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;\n          resample.point = linePoint;\n        };\n        resample.lineEnd = function() {\n          resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);\n          resample.lineEnd = lineEnd;\n          lineEnd();\n        };\n      }\n      return resample;\n    }\n    function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {\n      var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy;\n      if (d2 > 4 * δ2 && depth--) {\n        var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = Math.abs(Math.abs(c) - 1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2;\n        if (dz * dz / d2 > δ2 || Math.abs((dx * dx2 + dy * dy2) / d2 - .5) > .3) {\n          resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);\n          stream.point(x2, y2);\n          resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);\n        }\n      }\n    }\n    resample.precision = function(_) {\n      if (!arguments.length) return Math.sqrt(δ2);\n      maxDepth = (δ2 = _ * _) > 0 && 16;\n      return resample;\n    };\n    return resample;\n  }\n  d3.geo.projection = d3_geo_projection;\n  d3.geo.projectionMutator = d3_geo_projectionMutator;\n  function d3_geo_projection(project) {\n    return d3_geo_projectionMutator(function() {\n      return project;\n    })();\n  }\n  function d3_geo_projectionMutator(projectAt) {\n    var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) {\n      x = project(x, y);\n      return [ x[0] * k + δx, δy - x[1] * k ];\n    }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null;\n    function projection(point) {\n      point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);\n      return [ point[0] * k + δx, δy - point[1] * k ];\n    }\n    function invert(point) {\n      point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);\n      return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];\n    }\n    projection.stream = function(stream) {\n      return d3_geo_projectionRadiansRotate(rotate, preclip(projectResample(postclip(stream))));\n    };\n    projection.clipAngle = function(_) {\n      if (!arguments.length) return clipAngle;\n      preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);\n      return projection;\n    };\n    projection.clipExtent = function(_) {\n      if (!arguments.length) return clipExtent;\n      clipExtent = _;\n      postclip = _ == null ? d3_identity : d3_geo_clipView(_[0][0], _[0][1], _[1][0], _[1][1]);\n      return projection;\n    };\n    projection.scale = function(_) {\n      if (!arguments.length) return k;\n      k = +_;\n      return reset();\n    };\n    projection.translate = function(_) {\n      if (!arguments.length) return [ x, y ];\n      x = +_[0];\n      y = +_[1];\n      return reset();\n    };\n    projection.center = function(_) {\n      if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ];\n      λ = _[0] % 360 * d3_radians;\n      φ = _[1] % 360 * d3_radians;\n      return reset();\n    };\n    projection.rotate = function(_) {\n      if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ];\n      δλ = _[0] % 360 * d3_radians;\n      δφ = _[1] % 360 * d3_radians;\n      δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;\n      return reset();\n    };\n    d3.rebind(projection, projectResample, \"precision\");\n    function reset() {\n      projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);\n      var center = project(λ, φ);\n      δx = x - center[0] * k;\n      δy = y + center[1] * k;\n      return projection;\n    }\n    return function() {\n      project = projectAt.apply(this, arguments);\n      projection.invert = project.invert && invert;\n      return reset();\n    };\n  }\n  function d3_geo_projectionRadiansRotate(rotate, stream) {\n    return {\n      point: function(x, y) {\n        y = rotate(x * d3_radians, y * d3_radians), x = y[0];\n        stream.point(x > π ? x - 2 * π : x < -π ? x + 2 * π : x, y[1]);\n      },\n      sphere: function() {\n        stream.sphere();\n      },\n      lineStart: function() {\n        stream.lineStart();\n      },\n      lineEnd: function() {\n        stream.lineEnd();\n      },\n      polygonStart: function() {\n        stream.polygonStart();\n      },\n      polygonEnd: function() {\n        stream.polygonEnd();\n      }\n    };\n  }\n  function d3_geo_equirectangular(λ, φ) {\n    return [ λ, φ ];\n  }\n  (d3.geo.equirectangular = function() {\n    return d3_geo_projection(d3_geo_equirectangular);\n  }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;\n  d3.geo.rotation = function(rotate) {\n    rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);\n    function forward(coordinates) {\n      coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);\n      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;\n    }\n    forward.invert = function(coordinates) {\n      coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);\n      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;\n    };\n    return forward;\n  };\n  function d3_geo_rotation(δλ, δφ, δγ) {\n    return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_equirectangular;\n  }\n  function d3_geo_forwardRotationλ(δλ) {\n    return function(λ, φ) {\n      return λ += δλ, [ λ > π ? λ - 2 * π : λ < -π ? λ + 2 * π : λ, φ ];\n    };\n  }\n  function d3_geo_rotationλ(δλ) {\n    var rotation = d3_geo_forwardRotationλ(δλ);\n    rotation.invert = d3_geo_forwardRotationλ(-δλ);\n    return rotation;\n  }\n  function d3_geo_rotationφγ(δφ, δγ) {\n    var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ);\n    function rotation(λ, φ) {\n      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ;\n      return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), Math.asin(Math.max(-1, Math.min(1, k * cosδγ + y * sinδγ))) ];\n    }\n    rotation.invert = function(λ, φ) {\n      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ;\n      return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), Math.asin(Math.max(-1, Math.min(1, k * cosδφ - x * sinδφ))) ];\n    };\n    return rotation;\n  }\n  d3.geo.circle = function() {\n    var origin = [ 0, 0 ], angle, precision = 6, interpolate;\n    function circle() {\n      var center = typeof origin === \"function\" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = [];\n      interpolate(null, null, 1, {\n        point: function(x, y) {\n          ring.push(x = rotate(x, y));\n          x[0] *= d3_degrees, x[1] *= d3_degrees;\n        }\n      });\n      return {\n        type: \"Polygon\",\n        coordinates: [ ring ]\n      };\n    }\n    circle.origin = function(x) {\n      if (!arguments.length) return origin;\n      origin = x;\n      return circle;\n    };\n    circle.angle = function(x) {\n      if (!arguments.length) return angle;\n      interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);\n      return circle;\n    };\n    circle.precision = function(_) {\n      if (!arguments.length) return precision;\n      interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);\n      return circle;\n    };\n    return circle.angle(90);\n  };\n  function d3_geo_circleInterpolate(radius, precision) {\n    var cr = Math.cos(radius), sr = Math.sin(radius);\n    return function(from, to, direction, listener) {\n      if (from != null) {\n        from = d3_geo_circleAngle(cr, from);\n        to = d3_geo_circleAngle(cr, to);\n        if (direction > 0 ? from < to : from > to) from += direction * 2 * π;\n      } else {\n        from = radius + direction * 2 * π;\n        to = radius;\n      }\n      var point;\n      for (var step = direction * precision, t = from; direction > 0 ? t > to : t < to; t -= step) {\n        listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]);\n      }\n    };\n  }\n  function d3_geo_circleAngle(cr, point) {\n    var a = d3_geo_cartesian(point);\n    a[0] -= cr;\n    d3_geo_cartesianNormalize(a);\n    var angle = d3_acos(-a[1]);\n    return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);\n  }\n  d3.geo.distance = function(a, b) {\n    var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t;\n    return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);\n  };\n  d3.geo.graticule = function() {\n    var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5;\n    function graticule() {\n      return {\n        type: \"MultiLineString\",\n        coordinates: lines()\n      };\n    }\n    function lines() {\n      return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) {\n        return Math.abs(x % DX) > ε;\n      }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) {\n        return Math.abs(y % DY) > ε;\n      }).map(y));\n    }\n    graticule.lines = function() {\n      return lines().map(function(coordinates) {\n        return {\n          type: \"LineString\",\n          coordinates: coordinates\n        };\n      });\n    };\n    graticule.outline = function() {\n      return {\n        type: \"Polygon\",\n        coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ]\n      };\n    };\n    graticule.extent = function(_) {\n      if (!arguments.length) return graticule.minorExtent();\n      return graticule.majorExtent(_).minorExtent(_);\n    };\n    graticule.majorExtent = function(_) {\n      if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ];\n      X0 = +_[0][0], X1 = +_[1][0];\n      Y0 = +_[0][1], Y1 = +_[1][1];\n      if (X0 > X1) _ = X0, X0 = X1, X1 = _;\n      if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;\n      return graticule.precision(precision);\n    };\n    graticule.minorExtent = function(_) {\n      if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];\n      x0 = +_[0][0], x1 = +_[1][0];\n      y0 = +_[0][1], y1 = +_[1][1];\n      if (x0 > x1) _ = x0, x0 = x1, x1 = _;\n      if (y0 > y1) _ = y0, y0 = y1, y1 = _;\n      return graticule.precision(precision);\n    };\n    graticule.step = function(_) {\n      if (!arguments.length) return graticule.minorStep();\n      return graticule.majorStep(_).minorStep(_);\n    };\n    graticule.majorStep = function(_) {\n      if (!arguments.length) return [ DX, DY ];\n      DX = +_[0], DY = +_[1];\n      return graticule;\n    };\n    graticule.minorStep = function(_) {\n      if (!arguments.length) return [ dx, dy ];\n      dx = +_[0], dy = +_[1];\n      return graticule;\n    };\n    graticule.precision = function(_) {\n      if (!arguments.length) return precision;\n      precision = +_;\n      x = d3_geo_graticuleX(y0, y1, 90);\n      y = d3_geo_graticuleY(x0, x1, precision);\n      X = d3_geo_graticuleX(Y0, Y1, 90);\n      Y = d3_geo_graticuleY(X0, X1, precision);\n      return graticule;\n    };\n    return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]);\n  };\n  function d3_geo_graticuleX(y0, y1, dy) {\n    var y = d3.range(y0, y1 - ε, dy).concat(y1);\n    return function(x) {\n      return y.map(function(y) {\n        return [ x, y ];\n      });\n    };\n  }\n  function d3_geo_graticuleY(x0, x1, dx) {\n    var x = d3.range(x0, x1 - ε, dx).concat(x1);\n    return function(y) {\n      return x.map(function(x) {\n        return [ x, y ];\n      });\n    };\n  }\n  function d3_source(d) {\n    return d.source;\n  }\n  function d3_target(d) {\n    return d.target;\n  }\n  d3.geo.greatArc = function() {\n    var source = d3_source, source_, target = d3_target, target_;\n    function greatArc() {\n      return {\n        type: \"LineString\",\n        coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ]\n      };\n    }\n    greatArc.distance = function() {\n      return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments));\n    };\n    greatArc.source = function(_) {\n      if (!arguments.length) return source;\n      source = _, source_ = typeof _ === \"function\" ? null : _;\n      return greatArc;\n    };\n    greatArc.target = function(_) {\n      if (!arguments.length) return target;\n      target = _, target_ = typeof _ === \"function\" ? null : _;\n      return greatArc;\n    };\n    greatArc.precision = function() {\n      return arguments.length ? greatArc : 0;\n    };\n    return greatArc;\n  };\n  d3.geo.interpolate = function(source, target) {\n    return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);\n  };\n  function d3_geo_interpolate(x0, y0, x1, y1) {\n    var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d);\n    var interpolate = d ? function(t) {\n      var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;\n      return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ];\n    } : function() {\n      return [ x0 * d3_degrees, y0 * d3_degrees ];\n    };\n    interpolate.distance = d;\n    return interpolate;\n  }\n  d3.geo.length = function(object) {\n    d3_geo_lengthSum = 0;\n    d3.geo.stream(object, d3_geo_length);\n    return d3_geo_lengthSum;\n  };\n  var d3_geo_lengthSum;\n  var d3_geo_length = {\n    sphere: d3_noop,\n    point: d3_noop,\n    lineStart: d3_geo_lengthLineStart,\n    lineEnd: d3_noop,\n    polygonStart: d3_noop,\n    polygonEnd: d3_noop\n  };\n  function d3_geo_lengthLineStart() {\n    var λ0, sinφ0, cosφ0;\n    d3_geo_length.point = function(λ, φ) {\n      λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);\n      d3_geo_length.point = nextPoint;\n    };\n    d3_geo_length.lineEnd = function() {\n      d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;\n    };\n    function nextPoint(λ, φ) {\n      var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = Math.abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t);\n      d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);\n      λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;\n    }\n  }\n  function d3_geo_conic(projectAt) {\n    var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1);\n    p.parallels = function(_) {\n      if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ];\n      return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);\n    };\n    return p;\n  }\n  function d3_geo_conicEqualArea(φ0, φ1) {\n    var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n;\n    function forward(λ, φ) {\n      var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;\n      return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ];\n    }\n    forward.invert = function(x, y) {\n      var ρ0_y = ρ0 - y;\n      return [ Math.atan2(x, ρ0_y) / n, Math.asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ];\n    };\n    return forward;\n  }\n  (d3.geo.conicEqualArea = function() {\n    return d3_geo_conic(d3_geo_conicEqualArea);\n  }).raw = d3_geo_conicEqualArea;\n  d3.geo.albersUsa = function() {\n    var lower48 = d3.geo.conicEqualArea().rotate([ 98, 0 ]).center([ 0, 38 ]).parallels([ 29.5, 45.5 ]);\n    var alaska = d3.geo.conicEqualArea().rotate([ 160, 0 ]).center([ 0, 60 ]).parallels([ 55, 65 ]);\n    var hawaii = d3.geo.conicEqualArea().rotate([ 160, 0 ]).center([ 0, 20 ]).parallels([ 8, 18 ]);\n    var puertoRico = d3.geo.conicEqualArea().rotate([ 60, 0 ]).center([ 0, 10 ]).parallels([ 8, 18 ]);\n    var alaskaInvert, hawaiiInvert, puertoRicoInvert;\n    function albersUsa(coordinates) {\n      return projection(coordinates)(coordinates);\n    }\n    function projection(point) {\n      var lon = point[0], lat = point[1];\n      return lat > 50 ? alaska : lon < -140 ? hawaii : lat < 21 ? puertoRico : lower48;\n    }\n    albersUsa.invert = function(coordinates) {\n      return alaskaInvert(coordinates) || hawaiiInvert(coordinates) || puertoRicoInvert(coordinates) || lower48.invert(coordinates);\n    };\n    albersUsa.scale = function(x) {\n      if (!arguments.length) return lower48.scale();\n      lower48.scale(x);\n      alaska.scale(x * .6);\n      hawaii.scale(x);\n      puertoRico.scale(x * 1.5);\n      return albersUsa.translate(lower48.translate());\n    };\n    albersUsa.translate = function(x) {\n      if (!arguments.length) return lower48.translate();\n      var dz = lower48.scale(), dx = x[0], dy = x[1];\n      lower48.translate(x);\n      alaska.translate([ dx - .4 * dz, dy + .17 * dz ]);\n      hawaii.translate([ dx - .19 * dz, dy + .2 * dz ]);\n      puertoRico.translate([ dx + .58 * dz, dy + .43 * dz ]);\n      alaskaInvert = d3_geo_albersUsaInvert(alaska, [ [ -180, 50 ], [ -130, 72 ] ]);\n      hawaiiInvert = d3_geo_albersUsaInvert(hawaii, [ [ -164, 18 ], [ -154, 24 ] ]);\n      puertoRicoInvert = d3_geo_albersUsaInvert(puertoRico, [ [ -67.5, 17.5 ], [ -65, 19 ] ]);\n      return albersUsa;\n    };\n    return albersUsa.scale(1e3);\n  };\n  function d3_geo_albersUsaInvert(projection, extent) {\n    var a = projection(extent[0]), b = projection([ .5 * (extent[0][0] + extent[1][0]), extent[0][1] ]), c = projection([ extent[1][0], extent[0][1] ]), d = projection(extent[1]);\n    var dya = b[1] - a[1], dxa = b[0] - a[0], dyb = c[1] - b[1], dxb = c[0] - b[0];\n    var ma = dya / dxa, mb = dyb / dxb;\n    var cx = .5 * (ma * mb * (a[1] - c[1]) + mb * (a[0] + b[0]) - ma * (b[0] + c[0])) / (mb - ma), cy = (.5 * (a[0] + b[0]) - cx) / ma + .5 * (a[1] + b[1]);\n    var dx0 = d[0] - cx, dy0 = d[1] - cy, dx1 = a[0] - cx, dy1 = a[1] - cy, r0 = dx0 * dx0 + dy0 * dy0, r1 = dx1 * dx1 + dy1 * dy1;\n    var a0 = Math.atan2(dy0, dx0), a1 = Math.atan2(dy1, dx1);\n    return function(coordinates) {\n      var dx = coordinates[0] - cx, dy = coordinates[1] - cy, r = dx * dx + dy * dy, a = Math.atan2(dy, dx);\n      if (r0 < r && r < r1 && a0 < a && a < a1) return projection.invert(coordinates);\n    };\n  }\n  var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {\n    point: d3_noop,\n    lineStart: d3_noop,\n    lineEnd: d3_noop,\n    polygonStart: function() {\n      d3_geo_pathAreaPolygon = 0;\n      d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;\n    },\n    polygonEnd: function() {\n      d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;\n      d3_geo_pathAreaSum += Math.abs(d3_geo_pathAreaPolygon / 2);\n    }\n  };\n  function d3_geo_pathAreaRingStart() {\n    var x00, y00, x0, y0;\n    d3_geo_pathArea.point = function(x, y) {\n      d3_geo_pathArea.point = nextPoint;\n      x00 = x0 = x, y00 = y0 = y;\n    };\n    function nextPoint(x, y) {\n      d3_geo_pathAreaPolygon += y0 * x - x0 * y;\n      x0 = x, y0 = y;\n    }\n    d3_geo_pathArea.lineEnd = function() {\n      nextPoint(x00, y00);\n    };\n  }\n  function d3_geo_pathBuffer() {\n    var pointCircle = d3_geo_pathCircle(4.5), buffer = [];\n    var stream = {\n      point: point,\n      lineStart: function() {\n        stream.point = pointLineStart;\n      },\n      lineEnd: lineEnd,\n      polygonStart: function() {\n        stream.lineEnd = lineEndPolygon;\n      },\n      polygonEnd: function() {\n        stream.lineEnd = lineEnd;\n        stream.point = point;\n      },\n      pointRadius: function(_) {\n        pointCircle = d3_geo_pathCircle(_);\n        return stream;\n      },\n      result: function() {\n        if (buffer.length) {\n          var result = buffer.join(\"\");\n          buffer = [];\n          return result;\n        }\n      }\n    };\n    function point(x, y) {\n      buffer.push(\"M\", x, \",\", y, pointCircle);\n    }\n    function pointLineStart(x, y) {\n      buffer.push(\"M\", x, \",\", y);\n      stream.point = pointLine;\n    }\n    function pointLine(x, y) {\n      buffer.push(\"L\", x, \",\", y);\n    }\n    function lineEnd() {\n      stream.point = point;\n    }\n    function lineEndPolygon() {\n      buffer.push(\"Z\");\n    }\n    return stream;\n  }\n  var d3_geo_pathCentroid = {\n    point: d3_geo_pathCentroidPoint,\n    lineStart: d3_geo_pathCentroidLineStart,\n    lineEnd: d3_geo_pathCentroidLineEnd,\n    polygonStart: function() {\n      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;\n    },\n    polygonEnd: function() {\n      d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;\n      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;\n      d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;\n    }\n  };\n  function d3_geo_pathCentroidPoint(x, y) {\n    if (d3_geo_centroidDimension) return;\n    d3_geo_centroidX += x;\n    d3_geo_centroidY += y;\n    ++d3_geo_centroidZ;\n  }\n  function d3_geo_pathCentroidLineStart() {\n    var x0, y0;\n    if (d3_geo_centroidDimension !== 1) {\n      if (d3_geo_centroidDimension < 1) {\n        d3_geo_centroidDimension = 1;\n        d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;\n      } else return;\n    }\n    d3_geo_pathCentroid.point = function(x, y) {\n      d3_geo_pathCentroid.point = nextPoint;\n      x0 = x, y0 = y;\n    };\n    function nextPoint(x, y) {\n      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);\n      d3_geo_centroidX += z * (x0 + x) / 2;\n      d3_geo_centroidY += z * (y0 + y) / 2;\n      d3_geo_centroidZ += z;\n      x0 = x, y0 = y;\n    }\n  }\n  function d3_geo_pathCentroidLineEnd() {\n    d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;\n  }\n  function d3_geo_pathCentroidRingStart() {\n    var x00, y00, x0, y0;\n    if (d3_geo_centroidDimension < 2) {\n      d3_geo_centroidDimension = 2;\n      d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;\n    }\n    d3_geo_pathCentroid.point = function(x, y) {\n      d3_geo_pathCentroid.point = nextPoint;\n      x00 = x0 = x, y00 = y0 = y;\n    };\n    function nextPoint(x, y) {\n      var z = y0 * x - x0 * y;\n      d3_geo_centroidX += z * (x0 + x);\n      d3_geo_centroidY += z * (y0 + y);\n      d3_geo_centroidZ += z * 3;\n      x0 = x, y0 = y;\n    }\n    d3_geo_pathCentroid.lineEnd = function() {\n      nextPoint(x00, y00);\n    };\n  }\n  function d3_geo_pathContext(context) {\n    var pointRadius = 4.5;\n    var stream = {\n      point: point,\n      lineStart: function() {\n        stream.point = pointLineStart;\n      },\n      lineEnd: lineEnd,\n      polygonStart: function() {\n        stream.lineEnd = lineEndPolygon;\n      },\n      polygonEnd: function() {\n        stream.lineEnd = lineEnd;\n        stream.point = point;\n      },\n      pointRadius: function(_) {\n        pointRadius = _;\n        return stream;\n      },\n      result: d3_noop\n    };\n    function point(x, y) {\n      context.moveTo(x, y);\n      context.arc(x, y, pointRadius, 0, 2 * π);\n    }\n    function pointLineStart(x, y) {\n      context.moveTo(x, y);\n      stream.point = pointLine;\n    }\n    function pointLine(x, y) {\n      context.lineTo(x, y);\n    }\n    function lineEnd() {\n      stream.point = point;\n    }\n    function lineEndPolygon() {\n      context.closePath();\n    }\n    return stream;\n  }\n  d3.geo.path = function() {\n    var pointRadius = 4.5, projection, context, projectStream, contextStream;\n    function path(object) {\n      if (object) d3.geo.stream(object, projectStream(contextStream.pointRadius(typeof pointRadius === \"function\" ? +pointRadius.apply(this, arguments) : pointRadius)));\n      return contextStream.result();\n    }\n    path.area = function(object) {\n      d3_geo_pathAreaSum = 0;\n      d3.geo.stream(object, projectStream(d3_geo_pathArea));\n      return d3_geo_pathAreaSum;\n    };\n    path.centroid = function(object) {\n      d3_geo_centroidDimension = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;\n      d3.geo.stream(object, projectStream(d3_geo_pathCentroid));\n      return d3_geo_centroidZ ? [ d3_geo_centroidX / d3_geo_centroidZ, d3_geo_centroidY / d3_geo_centroidZ ] : undefined;\n    };\n    path.bounds = function(object) {\n      return d3_geo_bounds(projectStream)(object);\n    };\n    path.projection = function(_) {\n      if (!arguments.length) return projection;\n      projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;\n      return path;\n    };\n    path.context = function(_) {\n      if (!arguments.length) return context;\n      contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);\n      return path;\n    };\n    path.pointRadius = function(_) {\n      if (!arguments.length) return pointRadius;\n      pointRadius = typeof _ === \"function\" ? _ : +_;\n      return path;\n    };\n    return path.projection(d3.geo.albersUsa()).context(null);\n  };\n  function d3_geo_pathCircle(radius) {\n    return \"m0,\" + radius + \"a\" + radius + \",\" + radius + \" 0 1,1 0,\" + -2 * radius + \"a\" + radius + \",\" + radius + \" 0 1,1 0,\" + +2 * radius + \"z\";\n  }\n  function d3_geo_pathProjectStream(project) {\n    var resample = d3_geo_resample(function(λ, φ) {\n      return project([ λ * d3_degrees, φ * d3_degrees ]);\n    });\n    return function(stream) {\n      stream = resample(stream);\n      return {\n        point: function(λ, φ) {\n          stream.point(λ * d3_radians, φ * d3_radians);\n        },\n        sphere: function() {\n          stream.sphere();\n        },\n        lineStart: function() {\n          stream.lineStart();\n        },\n        lineEnd: function() {\n          stream.lineEnd();\n        },\n        polygonStart: function() {\n          stream.polygonStart();\n        },\n        polygonEnd: function() {\n          stream.polygonEnd();\n        }\n      };\n    };\n  }\n  d3.geo.albers = function() {\n    return d3.geo.conicEqualArea().parallels([ 29.5, 45.5 ]).rotate([ 98, 0 ]).center([ 0, 38 ]).scale(1e3);\n  };\n  function d3_geo_azimuthal(scale, angle) {\n    function azimuthal(λ, φ) {\n      var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ);\n      return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ];\n    }\n    azimuthal.invert = function(x, y) {\n      var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c);\n      return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ];\n    };\n    return azimuthal;\n  }\n  var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) {\n    return Math.sqrt(2 / (1 + cosλcosφ));\n  }, function(ρ) {\n    return 2 * Math.asin(ρ / 2);\n  });\n  (d3.geo.azimuthalEqualArea = function() {\n    return d3_geo_projection(d3_geo_azimuthalEqualArea);\n  }).raw = d3_geo_azimuthalEqualArea;\n  var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) {\n    var c = Math.acos(cosλcosφ);\n    return c && c / Math.sin(c);\n  }, d3_identity);\n  (d3.geo.azimuthalEquidistant = function() {\n    return d3_geo_projection(d3_geo_azimuthalEquidistant);\n  }).raw = d3_geo_azimuthalEquidistant;\n  function d3_geo_conicConformal(φ0, φ1) {\n    var cosφ0 = Math.cos(φ0), t = function(φ) {\n      return Math.tan(π / 4 + φ / 2);\n    }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n;\n    if (!n) return d3_geo_mercator;\n    function forward(λ, φ) {\n      var ρ = Math.abs(Math.abs(φ) - π / 2) < ε ? 0 : F / Math.pow(t(φ), n);\n      return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ];\n    }\n    forward.invert = function(x, y) {\n      var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y);\n      return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - π / 2 ];\n    };\n    return forward;\n  }\n  (d3.geo.conicConformal = function() {\n    return d3_geo_conic(d3_geo_conicConformal);\n  }).raw = d3_geo_conicConformal;\n  function d3_geo_conicEquidistant(φ0, φ1) {\n    var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0;\n    if (Math.abs(n) < ε) return d3_geo_equirectangular;\n    function forward(λ, φ) {\n      var ρ = G - φ;\n      return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ];\n    }\n    forward.invert = function(x, y) {\n      var ρ0_y = G - y;\n      return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ];\n    };\n    return forward;\n  }\n  (d3.geo.conicEquidistant = function() {\n    return d3_geo_conic(d3_geo_conicEquidistant);\n  }).raw = d3_geo_conicEquidistant;\n  var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) {\n    return 1 / cosλcosφ;\n  }, Math.atan);\n  (d3.geo.gnomonic = function() {\n    return d3_geo_projection(d3_geo_gnomonic);\n  }).raw = d3_geo_gnomonic;\n  function d3_geo_mercator(λ, φ) {\n    return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ];\n  }\n  d3_geo_mercator.invert = function(x, y) {\n    return [ x, 2 * Math.atan(Math.exp(y)) - π / 2 ];\n  };\n  function d3_geo_mercatorProjection(project) {\n    var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto;\n    m.scale = function() {\n      var v = scale.apply(m, arguments);\n      return v === m ? clipAuto ? m.clipExtent(null) : m : v;\n    };\n    m.translate = function() {\n      var v = translate.apply(m, arguments);\n      return v === m ? clipAuto ? m.clipExtent(null) : m : v;\n    };\n    m.clipExtent = function(_) {\n      var v = clipExtent.apply(m, arguments);\n      if (v === m) {\n        if (clipAuto = _ == null) {\n          var k = π * scale(), t = translate();\n          clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]);\n        }\n      } else if (clipAuto) {\n        v = null;\n      }\n      return v;\n    };\n    return m.clipExtent(null);\n  }\n  (d3.geo.mercator = function() {\n    return d3_geo_mercatorProjection(d3_geo_mercator);\n  }).raw = d3_geo_mercator;\n  var d3_geo_orthographic = d3_geo_azimuthal(function() {\n    return 1;\n  }, Math.asin);\n  (d3.geo.orthographic = function() {\n    return d3_geo_projection(d3_geo_orthographic);\n  }).raw = d3_geo_orthographic;\n  var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) {\n    return 1 / (1 + cosλcosφ);\n  }, function(ρ) {\n    return 2 * Math.atan(ρ);\n  });\n  (d3.geo.stereographic = function() {\n    return d3_geo_projection(d3_geo_stereographic);\n  }).raw = d3_geo_stereographic;\n  function d3_geo_transverseMercator(λ, φ) {\n    var B = Math.cos(φ) * Math.sin(λ);\n    return [ Math.log((1 + B) / (1 - B)) / 2, Math.atan2(Math.tan(φ), Math.cos(λ)) ];\n  }\n  d3_geo_transverseMercator.invert = function(x, y) {\n    return [ Math.atan2(d3_sinh(x), Math.cos(y)), d3_asin(Math.sin(y) / d3_cosh(x)) ];\n  };\n  (d3.geo.transverseMercator = function() {\n    return d3_geo_mercatorProjection(d3_geo_transverseMercator);\n  }).raw = d3_geo_transverseMercator;\n  d3.geom = {};\n  d3.svg = {};\n  function d3_svg_line(projection) {\n    var x = d3_svg_lineX, y = d3_svg_lineY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;\n    function line(data) {\n      var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);\n      function segment() {\n        segments.push(\"M\", interpolate(projection(points), tension));\n      }\n      while (++i < n) {\n        if (defined.call(this, d = data[i], i)) {\n          points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);\n        } else if (points.length) {\n          segment();\n          points = [];\n        }\n      }\n      if (points.length) segment();\n      return segments.length ? segments.join(\"\") : null;\n    }\n    line.x = function(_) {\n      if (!arguments.length) return x;\n      x = _;\n      return line;\n    };\n    line.y = function(_) {\n      if (!arguments.length) return y;\n      y = _;\n      return line;\n    };\n    line.defined = function(_) {\n      if (!arguments.length) return defined;\n      defined = _;\n      return line;\n    };\n    line.interpolate = function(_) {\n      if (!arguments.length) return interpolateKey;\n      if (typeof _ === \"function\") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;\n      return line;\n    };\n    line.tension = function(_) {\n      if (!arguments.length) return tension;\n      tension = _;\n      return line;\n    };\n    return line;\n  }\n  d3.svg.line = function() {\n    return d3_svg_line(d3_identity);\n  };\n  function d3_svg_lineX(d) {\n    return d[0];\n  }\n  function d3_svg_lineY(d) {\n    return d[1];\n  }\n  var d3_svg_lineInterpolators = d3.map({\n    linear: d3_svg_lineLinear,\n    \"linear-closed\": d3_svg_lineLinearClosed,\n    \"step-before\": d3_svg_lineStepBefore,\n    \"step-after\": d3_svg_lineStepAfter,\n    basis: d3_svg_lineBasis,\n    \"basis-open\": d3_svg_lineBasisOpen,\n    \"basis-closed\": d3_svg_lineBasisClosed,\n    bundle: d3_svg_lineBundle,\n    cardinal: d3_svg_lineCardinal,\n    \"cardinal-open\": d3_svg_lineCardinalOpen,\n    \"cardinal-closed\": d3_svg_lineCardinalClosed,\n    monotone: d3_svg_lineMonotone\n  });\n  d3_svg_lineInterpolators.forEach(function(key, value) {\n    value.key = key;\n    value.closed = /-closed$/.test(key);\n  });\n  function d3_svg_lineLinear(points) {\n    return points.join(\"L\");\n  }\n  function d3_svg_lineLinearClosed(points) {\n    return d3_svg_lineLinear(points) + \"Z\";\n  }\n  function d3_svg_lineStepBefore(points) {\n    var i = 0, n = points.length, p = points[0], path = [ p[0], \",\", p[1] ];\n    while (++i < n) path.push(\"V\", (p = points[i])[1], \"H\", p[0]);\n    return path.join(\"\");\n  }\n  function d3_svg_lineStepAfter(points) {\n    var i = 0, n = points.length, p = points[0], path = [ p[0], \",\", p[1] ];\n    while (++i < n) path.push(\"H\", (p = points[i])[0], \"V\", p[1]);\n    return path.join(\"\");\n  }\n  function d3_svg_lineCardinalOpen(points, tension) {\n    return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension));\n  }\n  function d3_svg_lineCardinalClosed(points, tension) {\n    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]),\n    points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));\n  }\n  function d3_svg_lineCardinal(points, tension) {\n    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));\n  }\n  function d3_svg_lineHermite(points, tangents) {\n    if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {\n      return d3_svg_lineLinear(points);\n    }\n    var quad = points.length != tangents.length, path = \"\", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;\n    if (quad) {\n      path += \"Q\" + (p[0] - t0[0] * 2 / 3) + \",\" + (p[1] - t0[1] * 2 / 3) + \",\" + p[0] + \",\" + p[1];\n      p0 = points[1];\n      pi = 2;\n    }\n    if (tangents.length > 1) {\n      t = tangents[1];\n      p = points[pi];\n      pi++;\n      path += \"C\" + (p0[0] + t0[0]) + \",\" + (p0[1] + t0[1]) + \",\" + (p[0] - t[0]) + \",\" + (p[1] - t[1]) + \",\" + p[0] + \",\" + p[1];\n      for (var i = 2; i < tangents.length; i++, pi++) {\n        p = points[pi];\n        t = tangents[i];\n        path += \"S\" + (p[0] - t[0]) + \",\" + (p[1] - t[1]) + \",\" + p[0] + \",\" + p[1];\n      }\n    }\n    if (quad) {\n      var lp = points[pi];\n      path += \"Q\" + (p[0] + t[0] * 2 / 3) + \",\" + (p[1] + t[1] * 2 / 3) + \",\" + lp[0] + \",\" + lp[1];\n    }\n    return path;\n  }\n  function d3_svg_lineCardinalTangents(points, tension) {\n    var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;\n    while (++i < n) {\n      p0 = p1;\n      p1 = p2;\n      p2 = points[i];\n      tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);\n    }\n    return tangents;\n  }\n  function d3_svg_lineBasis(points) {\n    if (points.length < 3) return d3_svg_lineLinear(points);\n    var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, \",\", y0 ];\n    d3_svg_lineBasisBezier(path, px, py);\n    while (++i < n) {\n      pi = points[i];\n      px.shift();\n      px.push(pi[0]);\n      py.shift();\n      py.push(pi[1]);\n      d3_svg_lineBasisBezier(path, px, py);\n    }\n    i = -1;\n    while (++i < 2) {\n      px.shift();\n      px.push(pi[0]);\n      py.shift();\n      py.push(pi[1]);\n      d3_svg_lineBasisBezier(path, px, py);\n    }\n    return path.join(\"\");\n  }\n  function d3_svg_lineBasisOpen(points) {\n    if (points.length < 4) return d3_svg_lineLinear(points);\n    var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];\n    while (++i < 3) {\n      pi = points[i];\n      px.push(pi[0]);\n      py.push(pi[1]);\n    }\n    path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + \",\" + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));\n    --i;\n    while (++i < n) {\n      pi = points[i];\n      px.shift();\n      px.push(pi[0]);\n      py.shift();\n      py.push(pi[1]);\n      d3_svg_lineBasisBezier(path, px, py);\n    }\n    return path.join(\"\");\n  }\n  function d3_svg_lineBasisClosed(points) {\n    var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];\n    while (++i < 4) {\n      pi = points[i % n];\n      px.push(pi[0]);\n      py.push(pi[1]);\n    }\n    path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];\n    --i;\n    while (++i < m) {\n      pi = points[i % n];\n      px.shift();\n      px.push(pi[0]);\n      py.shift();\n      py.push(pi[1]);\n      d3_svg_lineBasisBezier(path, px, py);\n    }\n    return path.join(\"\");\n  }\n  function d3_svg_lineBundle(points, tension) {\n    var n = points.length - 1;\n    if (n) {\n      var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;\n      while (++i <= n) {\n        p = points[i];\n        t = i / n;\n        p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);\n        p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);\n      }\n    }\n    return d3_svg_lineBasis(points);\n  }\n  function d3_svg_lineDot4(a, b) {\n    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];\n  }\n  var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];\n  function d3_svg_lineBasisBezier(path, x, y) {\n    path.push(\"C\", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));\n  }\n  function d3_svg_lineSlope(p0, p1) {\n    return (p1[1] - p0[1]) / (p1[0] - p0[0]);\n  }\n  function d3_svg_lineFiniteDifferences(points) {\n    var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);\n    while (++i < j) {\n      m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;\n    }\n    m[i] = d;\n    return m;\n  }\n  function d3_svg_lineMonotoneTangents(points) {\n    var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;\n    while (++i < j) {\n      d = d3_svg_lineSlope(points[i], points[i + 1]);\n      if (Math.abs(d) < 1e-6) {\n        m[i] = m[i + 1] = 0;\n      } else {\n        a = m[i] / d;\n        b = m[i + 1] / d;\n        s = a * a + b * b;\n        if (s > 9) {\n          s = d * 3 / Math.sqrt(s);\n          m[i] = s * a;\n          m[i + 1] = s * b;\n        }\n      }\n    }\n    i = -1;\n    while (++i <= j) {\n      s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));\n      tangents.push([ s || 0, m[i] * s || 0 ]);\n    }\n    return tangents;\n  }\n  function d3_svg_lineMonotone(points) {\n    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));\n  }\n  d3.geom.hull = function(vertices) {\n    var x = d3_svg_lineX, y = d3_svg_lineY;\n    if (arguments.length) return hull(vertices);\n    function hull(data) {\n      if (data.length < 3) return [];\n      var fx = d3_functor(x), fy = d3_functor(y), n = data.length, vertices, plen = n - 1, points = [], stack = [], d, i, j, h = 0, x1, y1, x2, y2, u, v, a, sp;\n      if (fx === d3_svg_lineX && y === d3_svg_lineY) vertices = data; else for (i = 0,\n      vertices = []; i < n; ++i) {\n        vertices.push([ +fx.call(this, d = data[i], i), +fy.call(this, d, i) ]);\n      }\n      for (i = 1; i < n; ++i) {\n        if (vertices[i][1] < vertices[h][1]) {\n          h = i;\n        } else if (vertices[i][1] == vertices[h][1]) {\n          h = vertices[i][0] < vertices[h][0] ? i : h;\n        }\n      }\n      for (i = 0; i < n; ++i) {\n        if (i === h) continue;\n        y1 = vertices[i][1] - vertices[h][1];\n        x1 = vertices[i][0] - vertices[h][0];\n        points.push({\n          angle: Math.atan2(y1, x1),\n          index: i\n        });\n      }\n      points.sort(function(a, b) {\n        return a.angle - b.angle;\n      });\n      a = points[0].angle;\n      v = points[0].index;\n      u = 0;\n      for (i = 1; i < plen; ++i) {\n        j = points[i].index;\n        if (a == points[i].angle) {\n          x1 = vertices[v][0] - vertices[h][0];\n          y1 = vertices[v][1] - vertices[h][1];\n          x2 = vertices[j][0] - vertices[h][0];\n          y2 = vertices[j][1] - vertices[h][1];\n          if (x1 * x1 + y1 * y1 >= x2 * x2 + y2 * y2) {\n            points[i].index = -1;\n          } else {\n            points[u].index = -1;\n            a = points[i].angle;\n            u = i;\n            v = j;\n          }\n        } else {\n          a = points[i].angle;\n          u = i;\n          v = j;\n        }\n      }\n      stack.push(h);\n      for (i = 0, j = 0; i < 2; ++j) {\n        if (points[j].index !== -1) {\n          stack.push(points[j].index);\n          i++;\n        }\n      }\n      sp = stack.length;\n      for (;j < plen; ++j) {\n        if (points[j].index === -1) continue;\n        while (!d3_geom_hullCCW(stack[sp - 2], stack[sp - 1], points[j].index, vertices)) {\n          --sp;\n        }\n        stack[sp++] = points[j].index;\n      }\n      var poly = [];\n      for (i = 0; i < sp; ++i) {\n        poly.push(data[stack[i]]);\n      }\n      return poly;\n    }\n    hull.x = function(_) {\n      return arguments.length ? (x = _, hull) : x;\n    };\n    hull.y = function(_) {\n      return arguments.length ? (y = _, hull) : y;\n    };\n    return hull;\n  };\n  function d3_geom_hullCCW(i1, i2, i3, v) {\n    var t, a, b, c, d, e, f;\n    t = v[i1];\n    a = t[0];\n    b = t[1];\n    t = v[i2];\n    c = t[0];\n    d = t[1];\n    t = v[i3];\n    e = t[0];\n    f = t[1];\n    return (f - b) * (c - a) - (d - b) * (e - a) > 0;\n  }\n  d3.geom.polygon = function(coordinates) {\n    coordinates.area = function() {\n      var i = 0, n = coordinates.length, area = coordinates[n - 1][1] * coordinates[0][0] - coordinates[n - 1][0] * coordinates[0][1];\n      while (++i < n) {\n        area += coordinates[i - 1][1] * coordinates[i][0] - coordinates[i - 1][0] * coordinates[i][1];\n      }\n      return area * .5;\n    };\n    coordinates.centroid = function(k) {\n      var i = -1, n = coordinates.length, x = 0, y = 0, a, b = coordinates[n - 1], c;\n      if (!arguments.length) k = -1 / (6 * coordinates.area());\n      while (++i < n) {\n        a = b;\n        b = coordinates[i];\n        c = a[0] * b[1] - b[0] * a[1];\n        x += (a[0] + b[0]) * c;\n        y += (a[1] + b[1]) * c;\n      }\n      return [ x * k, y * k ];\n    };\n    coordinates.clip = function(subject) {\n      var input, i = -1, n = coordinates.length, j, m, a = coordinates[n - 1], b, c, d;\n      while (++i < n) {\n        input = subject.slice();\n        subject.length = 0;\n        b = coordinates[i];\n        c = input[(m = input.length) - 1];\n        j = -1;\n        while (++j < m) {\n          d = input[j];\n          if (d3_geom_polygonInside(d, a, b)) {\n            if (!d3_geom_polygonInside(c, a, b)) {\n              subject.push(d3_geom_polygonIntersect(c, d, a, b));\n            }\n            subject.push(d);\n          } else if (d3_geom_polygonInside(c, a, b)) {\n            subject.push(d3_geom_polygonIntersect(c, d, a, b));\n          }\n          c = d;\n        }\n        a = b;\n      }\n      return subject;\n    };\n    return coordinates;\n  };\n  function d3_geom_polygonInside(p, a, b) {\n    return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);\n  }\n  function d3_geom_polygonIntersect(c, d, a, b) {\n    var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);\n    return [ x1 + ua * x21, y1 + ua * y21 ];\n  }\n  d3.geom.delaunay = function(vertices) {\n    var edges = vertices.map(function() {\n      return [];\n    }), triangles = [];\n    d3_geom_voronoiTessellate(vertices, function(e) {\n      edges[e.region.l.index].push(vertices[e.region.r.index]);\n    });\n    edges.forEach(function(edge, i) {\n      var v = vertices[i], cx = v[0], cy = v[1];\n      edge.forEach(function(v) {\n        v.angle = Math.atan2(v[0] - cx, v[1] - cy);\n      });\n      edge.sort(function(a, b) {\n        return a.angle - b.angle;\n      });\n      for (var j = 0, m = edge.length - 1; j < m; j++) {\n        triangles.push([ v, edge[j], edge[j + 1] ]);\n      }\n    });\n    return triangles;\n  };\n  d3.geom.voronoi = function(points) {\n    var size = null, x = d3_svg_lineX, y = d3_svg_lineY, clip;\n    if (arguments.length) return voronoi(points);\n    function voronoi(data) {\n      var points, polygons = data.map(function() {\n        return [];\n      }), fx = d3_functor(x), fy = d3_functor(y), d, i, n = data.length, Z = 1e6;\n      if (fx === d3_svg_lineX && fy === d3_svg_lineY) points = data; else for (points = [],\n      i = 0; i < n; ++i) {\n        points.push([ +fx.call(this, d = data[i], i), +fy.call(this, d, i) ]);\n      }\n      d3_geom_voronoiTessellate(points, function(e) {\n        var s1, s2, x1, x2, y1, y2;\n        if (e.a === 1 && e.b >= 0) {\n          s1 = e.ep.r;\n          s2 = e.ep.l;\n        } else {\n          s1 = e.ep.l;\n          s2 = e.ep.r;\n        }\n        if (e.a === 1) {\n          y1 = s1 ? s1.y : -Z;\n          x1 = e.c - e.b * y1;\n          y2 = s2 ? s2.y : Z;\n          x2 = e.c - e.b * y2;\n        } else {\n          x1 = s1 ? s1.x : -Z;\n          y1 = e.c - e.a * x1;\n          x2 = s2 ? s2.x : Z;\n          y2 = e.c - e.a * x2;\n        }\n        var v1 = [ x1, y1 ], v2 = [ x2, y2 ];\n        polygons[e.region.l.index].push(v1, v2);\n        polygons[e.region.r.index].push(v1, v2);\n      });\n      polygons = polygons.map(function(polygon, i) {\n        var cx = points[i][0], cy = points[i][1], angle = polygon.map(function(v) {\n          return Math.atan2(v[0] - cx, v[1] - cy);\n        }), order = d3.range(polygon.length).sort(function(a, b) {\n          return angle[a] - angle[b];\n        });\n        return order.filter(function(d, i) {\n          return !i || angle[d] - angle[order[i - 1]] > ε;\n        }).map(function(d) {\n          return polygon[d];\n        });\n      });\n      polygons.forEach(function(polygon, i) {\n        var n = polygon.length;\n        if (!n) return polygon.push([ -Z, -Z ], [ -Z, Z ], [ Z, Z ], [ Z, -Z ]);\n        if (n > 2) return;\n        var p0 = points[i], p1 = polygon[0], p2 = polygon[1], x0 = p0[0], y0 = p0[1], x1 = p1[0], y1 = p1[1], x2 = p2[0], y2 = p2[1], dx = Math.abs(x2 - x1), dy = y2 - y1;\n        if (Math.abs(dy) < ε) {\n          var y = y0 < y1 ? -Z : Z;\n          polygon.push([ -Z, y ], [ Z, y ]);\n        } else if (dx < ε) {\n          var x = x0 < x1 ? -Z : Z;\n          polygon.push([ x, -Z ], [ x, Z ]);\n        } else {\n          var y = (x2 - x1) * (y1 - y0) < (x1 - x0) * (y2 - y1) ? Z : -Z, z = Math.abs(dy) - dx;\n          if (Math.abs(z) < ε) {\n            polygon.push([ dy < 0 ? y : -y, y ]);\n          } else {\n            if (z > 0) y *= -1;\n            polygon.push([ -Z, y ], [ Z, y ]);\n          }\n        }\n      });\n      if (clip) for (i = 0; i < n; ++i) clip(polygons[i]);\n      for (i = 0; i < n; ++i) polygons[i].point = data[i];\n      return polygons;\n    }\n    voronoi.x = function(_) {\n      return arguments.length ? (x = _, voronoi) : x;\n    };\n    voronoi.y = function(_) {\n      return arguments.length ? (y = _, voronoi) : y;\n    };\n    voronoi.size = function(_) {\n      if (!arguments.length) return size;\n      if (_ == null) {\n        clip = null;\n      } else {\n        size = [ +_[0], +_[1] ];\n        clip = d3.geom.polygon([ [ 0, 0 ], [ 0, size[1] ], size, [ size[0], 0 ] ]).clip;\n      }\n      return voronoi;\n    };\n    voronoi.links = function(data) {\n      var points, graph = data.map(function() {\n        return [];\n      }), links = [], fx = d3_functor(x), fy = d3_functor(y), d, i, n = data.length;\n      if (fx === d3_svg_lineX && fy === d3_svg_lineY) points = data; else for (i = 0; i < n; ++i) {\n        points.push([ +fx.call(this, d = data[i], i), +fy.call(this, d, i) ]);\n      }\n      d3_geom_voronoiTessellate(points, function(e) {\n        var l = e.region.l.index, r = e.region.r.index;\n        if (graph[l][r]) return;\n        graph[l][r] = graph[r][l] = true;\n        links.push({\n          source: data[l],\n          target: data[r]\n        });\n      });\n      return links;\n    };\n    voronoi.triangles = function(data) {\n      if (x === d3_svg_lineX && y === d3_svg_lineY) return d3.geom.delaunay(data);\n      var points, point, fx = d3_functor(x), fy = d3_functor(y), d, i, n;\n      for (i = 0, points = [], n = data.length; i < n; ++i) {\n        point = [ +fx.call(this, d = data[i], i), +fy.call(this, d, i) ];\n        point.data = d;\n        points.push(point);\n      }\n      return d3.geom.delaunay(points).map(function(triangle) {\n        return triangle.map(function(point) {\n          return point.data;\n        });\n      });\n    };\n    return voronoi;\n  };\n  var d3_geom_voronoiOpposite = {\n    l: \"r\",\n    r: \"l\"\n  };\n  function d3_geom_voronoiTessellate(points, callback) {\n    var Sites = {\n      list: points.map(function(v, i) {\n        return {\n          index: i,\n          x: v[0],\n          y: v[1]\n        };\n      }).sort(function(a, b) {\n        return a.y < b.y ? -1 : a.y > b.y ? 1 : a.x < b.x ? -1 : a.x > b.x ? 1 : 0;\n      }),\n      bottomSite: null\n    };\n    var EdgeList = {\n      list: [],\n      leftEnd: null,\n      rightEnd: null,\n      init: function() {\n        EdgeList.leftEnd = EdgeList.createHalfEdge(null, \"l\");\n        EdgeList.rightEnd = EdgeList.createHalfEdge(null, \"l\");\n        EdgeList.leftEnd.r = EdgeList.rightEnd;\n        EdgeList.rightEnd.l = EdgeList.leftEnd;\n        EdgeList.list.unshift(EdgeList.leftEnd, EdgeList.rightEnd);\n      },\n      createHalfEdge: function(edge, side) {\n        return {\n          edge: edge,\n          side: side,\n          vertex: null,\n          l: null,\n          r: null\n        };\n      },\n      insert: function(lb, he) {\n        he.l = lb;\n        he.r = lb.r;\n        lb.r.l = he;\n        lb.r = he;\n      },\n      leftBound: function(p) {\n        var he = EdgeList.leftEnd;\n        do {\n          he = he.r;\n        } while (he != EdgeList.rightEnd && Geom.rightOf(he, p));\n        he = he.l;\n        return he;\n      },\n      del: function(he) {\n        he.l.r = he.r;\n        he.r.l = he.l;\n        he.edge = null;\n      },\n      right: function(he) {\n        return he.r;\n      },\n      left: function(he) {\n        return he.l;\n      },\n      leftRegion: function(he) {\n        return he.edge == null ? Sites.bottomSite : he.edge.region[he.side];\n      },\n      rightRegion: function(he) {\n        return he.edge == null ? Sites.bottomSite : he.edge.region[d3_geom_voronoiOpposite[he.side]];\n      }\n    };\n    var Geom = {\n      bisect: function(s1, s2) {\n        var newEdge = {\n          region: {\n            l: s1,\n            r: s2\n          },\n          ep: {\n            l: null,\n            r: null\n          }\n        };\n        var dx = s2.x - s1.x, dy = s2.y - s1.y, adx = dx > 0 ? dx : -dx, ady = dy > 0 ? dy : -dy;\n        newEdge.c = s1.x * dx + s1.y * dy + (dx * dx + dy * dy) * .5;\n        if (adx > ady) {\n          newEdge.a = 1;\n          newEdge.b = dy / dx;\n          newEdge.c /= dx;\n        } else {\n          newEdge.b = 1;\n          newEdge.a = dx / dy;\n          newEdge.c /= dy;\n        }\n        return newEdge;\n      },\n      intersect: function(el1, el2) {\n        var e1 = el1.edge, e2 = el2.edge;\n        if (!e1 || !e2 || e1.region.r == e2.region.r) {\n          return null;\n        }\n        var d = e1.a * e2.b - e1.b * e2.a;\n        if (Math.abs(d) < 1e-10) {\n          return null;\n        }\n        var xint = (e1.c * e2.b - e2.c * e1.b) / d, yint = (e2.c * e1.a - e1.c * e2.a) / d, e1r = e1.region.r, e2r = e2.region.r, el, e;\n        if (e1r.y < e2r.y || e1r.y == e2r.y && e1r.x < e2r.x) {\n          el = el1;\n          e = e1;\n        } else {\n          el = el2;\n          e = e2;\n        }\n        var rightOfSite = xint >= e.region.r.x;\n        if (rightOfSite && el.side === \"l\" || !rightOfSite && el.side === \"r\") {\n          return null;\n        }\n        return {\n          x: xint,\n          y: yint\n        };\n      },\n      rightOf: function(he, p) {\n        var e = he.edge, topsite = e.region.r, rightOfSite = p.x > topsite.x;\n        if (rightOfSite && he.side === \"l\") {\n          return 1;\n        }\n        if (!rightOfSite && he.side === \"r\") {\n          return 0;\n        }\n        if (e.a === 1) {\n          var dyp = p.y - topsite.y, dxp = p.x - topsite.x, fast = 0, above = 0;\n          if (!rightOfSite && e.b < 0 || rightOfSite && e.b >= 0) {\n            above = fast = dyp >= e.b * dxp;\n          } else {\n            above = p.x + p.y * e.b > e.c;\n            if (e.b < 0) {\n              above = !above;\n            }\n            if (!above) {\n              fast = 1;\n            }\n          }\n          if (!fast) {\n            var dxs = topsite.x - e.region.l.x;\n            above = e.b * (dxp * dxp - dyp * dyp) < dxs * dyp * (1 + 2 * dxp / dxs + e.b * e.b);\n            if (e.b < 0) {\n              above = !above;\n            }\n          }\n        } else {\n          var yl = e.c - e.a * p.x, t1 = p.y - yl, t2 = p.x - topsite.x, t3 = yl - topsite.y;\n          above = t1 * t1 > t2 * t2 + t3 * t3;\n        }\n        return he.side === \"l\" ? above : !above;\n      },\n      endPoint: function(edge, side, site) {\n        edge.ep[side] = site;\n        if (!edge.ep[d3_geom_voronoiOpposite[side]]) return;\n        callback(edge);\n      },\n      distance: function(s, t) {\n        var dx = s.x - t.x, dy = s.y - t.y;\n        return Math.sqrt(dx * dx + dy * dy);\n      }\n    };\n    var EventQueue = {\n      list: [],\n      insert: function(he, site, offset) {\n        he.vertex = site;\n        he.ystar = site.y + offset;\n        for (var i = 0, list = EventQueue.list, l = list.length; i < l; i++) {\n          var next = list[i];\n          if (he.ystar > next.ystar || he.ystar == next.ystar && site.x > next.vertex.x) {\n            continue;\n          } else {\n            break;\n          }\n        }\n        list.splice(i, 0, he);\n      },\n      del: function(he) {\n        for (var i = 0, ls = EventQueue.list, l = ls.length; i < l && ls[i] != he; ++i) {}\n        ls.splice(i, 1);\n      },\n      empty: function() {\n        return EventQueue.list.length === 0;\n      },\n      nextEvent: function(he) {\n        for (var i = 0, ls = EventQueue.list, l = ls.length; i < l; ++i) {\n          if (ls[i] == he) return ls[i + 1];\n        }\n        return null;\n      },\n      min: function() {\n        var elem = EventQueue.list[0];\n        return {\n          x: elem.vertex.x,\n          y: elem.ystar\n        };\n      },\n      extractMin: function() {\n        return EventQueue.list.shift();\n      }\n    };\n    EdgeList.init();\n    Sites.bottomSite = Sites.list.shift();\n    var newSite = Sites.list.shift(), newIntStar;\n    var lbnd, rbnd, llbnd, rrbnd, bisector;\n    var bot, top, temp, p, v;\n    var e, pm;\n    while (true) {\n      if (!EventQueue.empty()) {\n        newIntStar = EventQueue.min();\n      }\n      if (newSite && (EventQueue.empty() || newSite.y < newIntStar.y || newSite.y == newIntStar.y && newSite.x < newIntStar.x)) {\n        lbnd = EdgeList.leftBound(newSite);\n        rbnd = EdgeList.right(lbnd);\n        bot = EdgeList.rightRegion(lbnd);\n        e = Geom.bisect(bot, newSite);\n        bisector = EdgeList.createHalfEdge(e, \"l\");\n        EdgeList.insert(lbnd, bisector);\n        p = Geom.intersect(lbnd, bisector);\n        if (p) {\n          EventQueue.del(lbnd);\n          EventQueue.insert(lbnd, p, Geom.distance(p, newSite));\n        }\n        lbnd = bisector;\n        bisector = EdgeList.createHalfEdge(e, \"r\");\n        EdgeList.insert(lbnd, bisector);\n        p = Geom.intersect(bisector, rbnd);\n        if (p) {\n          EventQueue.insert(bisector, p, Geom.distance(p, newSite));\n        }\n        newSite = Sites.list.shift();\n      } else if (!EventQueue.empty()) {\n        lbnd = EventQueue.extractMin();\n        llbnd = EdgeList.left(lbnd);\n        rbnd = EdgeList.right(lbnd);\n        rrbnd = EdgeList.right(rbnd);\n        bot = EdgeList.leftRegion(lbnd);\n        top = EdgeList.rightRegion(rbnd);\n        v = lbnd.vertex;\n        Geom.endPoint(lbnd.edge, lbnd.side, v);\n        Geom.endPoint(rbnd.edge, rbnd.side, v);\n        EdgeList.del(lbnd);\n        EventQueue.del(rbnd);\n        EdgeList.del(rbnd);\n        pm = \"l\";\n        if (bot.y > top.y) {\n          temp = bot;\n          bot = top;\n          top = temp;\n          pm = \"r\";\n        }\n        e = Geom.bisect(bot, top);\n        bisector = EdgeList.createHalfEdge(e, pm);\n        EdgeList.insert(llbnd, bisector);\n        Geom.endPoint(e, d3_geom_voronoiOpposite[pm], v);\n        p = Geom.intersect(llbnd, bisector);\n        if (p) {\n          EventQueue.del(llbnd);\n          EventQueue.insert(llbnd, p, Geom.distance(p, bot));\n        }\n        p = Geom.intersect(bisector, rrbnd);\n        if (p) {\n          EventQueue.insert(bisector, p, Geom.distance(p, bot));\n        }\n      } else {\n        break;\n      }\n    }\n    for (lbnd = EdgeList.right(EdgeList.leftEnd); lbnd != EdgeList.rightEnd; lbnd = EdgeList.right(lbnd)) {\n      callback(lbnd.edge);\n    }\n  }\n  d3.geom.quadtree = function(points, x1, y1, x2, y2) {\n    var x = d3_svg_lineX, y = d3_svg_lineY, compat;\n    if (compat = arguments.length) {\n      x = d3_geom_quadtreeCompatX;\n      y = d3_geom_quadtreeCompatY;\n      if (compat === 3) {\n        y2 = y1;\n        x2 = x1;\n        y1 = x1 = 0;\n      }\n      return quadtree(points);\n    }\n    function quadtree(data) {\n      var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_;\n      if (x1 != null) {\n        x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2;\n      } else {\n        x2_ = y2_ = -(x1_ = y1_ = Infinity);\n        xs = [], ys = [];\n        n = data.length;\n        if (compat) for (i = 0; i < n; ++i) {\n          d = data[i];\n          if (d.x < x1_) x1_ = d.x;\n          if (d.y < y1_) y1_ = d.y;\n          if (d.x > x2_) x2_ = d.x;\n          if (d.y > y2_) y2_ = d.y;\n          xs.push(d.x);\n          ys.push(d.y);\n        } else for (i = 0; i < n; ++i) {\n          var x_ = +fx(d = data[i], i), y_ = +fy(d, i);\n          if (x_ < x1_) x1_ = x_;\n          if (y_ < y1_) y1_ = y_;\n          if (x_ > x2_) x2_ = x_;\n          if (y_ > y2_) y2_ = y_;\n          xs.push(x_);\n          ys.push(y_);\n        }\n      }\n      var dx = x2_ - x1_, dy = y2_ - y1_;\n      if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy;\n      function insert(n, d, x, y, x1, y1, x2, y2) {\n        if (isNaN(x) || isNaN(y)) return;\n        if (n.leaf) {\n          var nx = n.x, ny = n.y;\n          if (nx != null) {\n            if (Math.abs(nx - x) + Math.abs(ny - y) < .01) {\n              insertChild(n, d, x, y, x1, y1, x2, y2);\n            } else {\n              var nPoint = n.point;\n              n.x = n.y = n.point = null;\n              insertChild(n, nPoint, nx, ny, x1, y1, x2, y2);\n              insertChild(n, d, x, y, x1, y1, x2, y2);\n            }\n          } else {\n            n.x = x, n.y = y, n.point = d;\n          }\n        } else {\n          insertChild(n, d, x, y, x1, y1, x2, y2);\n        }\n      }\n      function insertChild(n, d, x, y, x1, y1, x2, y2) {\n        var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = x >= sx, bottom = y >= sy, i = (bottom << 1) + right;\n        n.leaf = false;\n        n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());\n        if (right) x1 = sx; else x2 = sx;\n        if (bottom) y1 = sy; else y2 = sy;\n        insert(n, d, x, y, x1, y1, x2, y2);\n      }\n      var root = d3_geom_quadtreeNode();\n      root.add = function(d) {\n        insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_);\n      };\n      root.visit = function(f) {\n        d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_);\n      };\n      i = -1;\n      if (x1 == null) {\n        while (++i < n) {\n          insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_);\n        }\n        --i;\n      } else data.forEach(root.add);\n      xs = ys = data = d = null;\n      return root;\n    }\n    quadtree.x = function(_) {\n      return arguments.length ? (x = _, quadtree) : x;\n    };\n    quadtree.y = function(_) {\n      return arguments.length ? (y = _, quadtree) : y;\n    };\n    quadtree.size = function(_) {\n      if (!arguments.length) return x1 == null ? null : [ x2, y2 ];\n      if (_ == null) {\n        x1 = y1 = x2 = y2 = null;\n      } else {\n        x1 = y1 = 0;\n        x2 = +_[0], y2 = +_[1];\n      }\n      return quadtree;\n    };\n    return quadtree;\n  };\n  function d3_geom_quadtreeCompatX(d) {\n    return d.x;\n  }\n  function d3_geom_quadtreeCompatY(d) {\n    return d.y;\n  }\n  function d3_geom_quadtreeNode() {\n    return {\n      leaf: true,\n      nodes: [],\n      point: null,\n      x: null,\n      y: null\n    };\n  }\n  function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {\n    if (!f(node, x1, y1, x2, y2)) {\n      var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;\n      if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);\n      if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);\n      if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);\n      if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);\n    }\n  }\n  d3.interpolateRgb = d3_interpolateRgb;\n  function d3_interpolateRgb(a, b) {\n    a = d3.rgb(a);\n    b = d3.rgb(b);\n    var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;\n    return function(t) {\n      return \"#\" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));\n    };\n  }\n  d3.transform = function(string) {\n    var g = d3_document.createElementNS(d3.ns.prefix.svg, \"g\");\n    return (d3.transform = function(string) {\n      g.setAttribute(\"transform\", string);\n      var t = g.transform.baseVal.consolidate();\n      return new d3_transform(t ? t.matrix : d3_transformIdentity);\n    })(string);\n  };\n  function d3_transform(m) {\n    var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;\n    if (r0[0] * r1[1] < r1[0] * r0[1]) {\n      r0[0] *= -1;\n      r0[1] *= -1;\n      kx *= -1;\n      kz *= -1;\n    }\n    this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;\n    this.translate = [ m.e, m.f ];\n    this.scale = [ kx, ky ];\n    this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;\n  }\n  d3_transform.prototype.toString = function() {\n    return \"translate(\" + this.translate + \")rotate(\" + this.rotate + \")skewX(\" + this.skew + \")scale(\" + this.scale + \")\";\n  };\n  function d3_transformDot(a, b) {\n    return a[0] * b[0] + a[1] * b[1];\n  }\n  function d3_transformNormalize(a) {\n    var k = Math.sqrt(d3_transformDot(a, a));\n    if (k) {\n      a[0] /= k;\n      a[1] /= k;\n    }\n    return k;\n  }\n  function d3_transformCombine(a, b, k) {\n    a[0] += k * b[0];\n    a[1] += k * b[1];\n    return a;\n  }\n  var d3_transformIdentity = {\n    a: 1,\n    b: 0,\n    c: 0,\n    d: 1,\n    e: 0,\n    f: 0\n  };\n  d3.interpolateNumber = d3_interpolateNumber;\n  function d3_interpolateNumber(a, b) {\n    b -= a;\n    return function(t) {\n      return a + b * t;\n    };\n  }\n  d3.interpolateTransform = d3_interpolateTransform;\n  function d3_interpolateTransform(a, b) {\n    var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale;\n    if (ta[0] != tb[0] || ta[1] != tb[1]) {\n      s.push(\"translate(\", null, \",\", null, \")\");\n      q.push({\n        i: 1,\n        x: d3_interpolateNumber(ta[0], tb[0])\n      }, {\n        i: 3,\n        x: d3_interpolateNumber(ta[1], tb[1])\n      });\n    } else if (tb[0] || tb[1]) {\n      s.push(\"translate(\" + tb + \")\");\n    } else {\n      s.push(\"\");\n    }\n    if (ra != rb) {\n      if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;\n      q.push({\n        i: s.push(s.pop() + \"rotate(\", null, \")\") - 2,\n        x: d3_interpolateNumber(ra, rb)\n      });\n    } else if (rb) {\n      s.push(s.pop() + \"rotate(\" + rb + \")\");\n    }\n    if (wa != wb) {\n      q.push({\n        i: s.push(s.pop() + \"skewX(\", null, \")\") - 2,\n        x: d3_interpolateNumber(wa, wb)\n      });\n    } else if (wb) {\n      s.push(s.pop() + \"skewX(\" + wb + \")\");\n    }\n    if (ka[0] != kb[0] || ka[1] != kb[1]) {\n      n = s.push(s.pop() + \"scale(\", null, \",\", null, \")\");\n      q.push({\n        i: n - 4,\n        x: d3_interpolateNumber(ka[0], kb[0])\n      }, {\n        i: n - 2,\n        x: d3_interpolateNumber(ka[1], kb[1])\n      });\n    } else if (kb[0] != 1 || kb[1] != 1) {\n      s.push(s.pop() + \"scale(\" + kb + \")\");\n    }\n    n = q.length;\n    return function(t) {\n      var i = -1, o;\n      while (++i < n) s[(o = q[i]).i] = o.x(t);\n      return s.join(\"\");\n    };\n  }\n  d3.interpolateObject = d3_interpolateObject;\n  function d3_interpolateObject(a, b) {\n    var i = {}, c = {}, k;\n    for (k in a) {\n      if (k in b) {\n        i[k] = d3_interpolateByName(k)(a[k], b[k]);\n      } else {\n        c[k] = a[k];\n      }\n    }\n    for (k in b) {\n      if (!(k in a)) {\n        c[k] = b[k];\n      }\n    }\n    return function(t) {\n      for (k in i) c[k] = i[k](t);\n      return c;\n    };\n  }\n  d3.interpolateString = d3_interpolateString;\n  function d3_interpolateString(a, b) {\n    var m, i, j, s0 = 0, s1 = 0, s = [], q = [], n, o;\n    d3_interpolate_number.lastIndex = 0;\n    for (i = 0; m = d3_interpolate_number.exec(b); ++i) {\n      if (m.index) s.push(b.substring(s0, s1 = m.index));\n      q.push({\n        i: s.length,\n        x: m[0]\n      });\n      s.push(null);\n      s0 = d3_interpolate_number.lastIndex;\n    }\n    if (s0 < b.length) s.push(b.substring(s0));\n    for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) {\n      o = q[i];\n      if (o.x == m[0]) {\n        if (o.i) {\n          if (s[o.i + 1] == null) {\n            s[o.i - 1] += o.x;\n            s.splice(o.i, 1);\n            for (j = i + 1; j < n; ++j) q[j].i--;\n          } else {\n            s[o.i - 1] += o.x + s[o.i + 1];\n            s.splice(o.i, 2);\n            for (j = i + 1; j < n; ++j) q[j].i -= 2;\n          }\n        } else {\n          if (s[o.i + 1] == null) {\n            s[o.i] = o.x;\n          } else {\n            s[o.i] = o.x + s[o.i + 1];\n            s.splice(o.i + 1, 1);\n            for (j = i + 1; j < n; ++j) q[j].i--;\n          }\n        }\n        q.splice(i, 1);\n        n--;\n        i--;\n      } else {\n        o.x = d3_interpolateNumber(parseFloat(m[0]), parseFloat(o.x));\n      }\n    }\n    while (i < n) {\n      o = q.pop();\n      if (s[o.i + 1] == null) {\n        s[o.i] = o.x;\n      } else {\n        s[o.i] = o.x + s[o.i + 1];\n        s.splice(o.i + 1, 1);\n      }\n      n--;\n    }\n    if (s.length === 1) {\n      return s[0] == null ? q[0].x : function() {\n        return b;\n      };\n    }\n    return function(t) {\n      for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t);\n      return s.join(\"\");\n    };\n  }\n  var d3_interpolate_number = /[-+]?(?:\\d+\\.?\\d*|\\.?\\d+)(?:[eE][-+]?\\d+)?/g;\n  d3.interpolate = d3_interpolate;\n  function d3_interpolate(a, b) {\n    var i = d3.interpolators.length, f;\n    while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;\n    return f;\n  }\n  function d3_interpolateByName(name) {\n    return name == \"transform\" ? d3_interpolateTransform : d3_interpolate;\n  }\n  d3.interpolators = [ d3_interpolateObject, function(a, b) {\n    return Array.isArray(b) && d3_interpolateArray(a, b);\n  }, function(a, b) {\n    return (typeof a === \"string\" || typeof b === \"string\") && d3_interpolateString(a + \"\", b + \"\");\n  }, function(a, b) {\n    return (typeof b === \"string\" ? d3_rgb_names.has(b) || /^(#|rgb\\(|hsl\\()/.test(b) : b instanceof d3_Color) && d3_interpolateRgb(a, b);\n  }, function(a, b) {\n    return !isNaN(a = +a) && !isNaN(b = +b) && d3_interpolateNumber(a, b);\n  } ];\n  d3.interpolateArray = d3_interpolateArray;\n  function d3_interpolateArray(a, b) {\n    var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;\n    for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));\n    for (;i < na; ++i) c[i] = a[i];\n    for (;i < nb; ++i) c[i] = b[i];\n    return function(t) {\n      for (i = 0; i < n0; ++i) c[i] = x[i](t);\n      return c;\n    };\n  }\n  var d3_ease_default = function() {\n    return d3_identity;\n  };\n  var d3_ease = d3.map({\n    linear: d3_ease_default,\n    poly: d3_ease_poly,\n    quad: function() {\n      return d3_ease_quad;\n    },\n    cubic: function() {\n      return d3_ease_cubic;\n    },\n    sin: function() {\n      return d3_ease_sin;\n    },\n    exp: function() {\n      return d3_ease_exp;\n    },\n    circle: function() {\n      return d3_ease_circle;\n    },\n    elastic: d3_ease_elastic,\n    back: d3_ease_back,\n    bounce: function() {\n      return d3_ease_bounce;\n    }\n  });\n  var d3_ease_mode = d3.map({\n    \"in\": d3_identity,\n    out: d3_ease_reverse,\n    \"in-out\": d3_ease_reflect,\n    \"out-in\": function(f) {\n      return d3_ease_reflect(d3_ease_reverse(f));\n    }\n  });\n  d3.ease = function(name) {\n    var i = name.indexOf(\"-\"), t = i >= 0 ? name.substring(0, i) : name, m = i >= 0 ? name.substring(i + 1) : \"in\";\n    t = d3_ease.get(t) || d3_ease_default;\n    m = d3_ease_mode.get(m) || d3_identity;\n    return d3_ease_clamp(m(t.apply(null, Array.prototype.slice.call(arguments, 1))));\n  };\n  function d3_ease_clamp(f) {\n    return function(t) {\n      return t <= 0 ? 0 : t >= 1 ? 1 : f(t);\n    };\n  }\n  function d3_ease_reverse(f) {\n    return function(t) {\n      return 1 - f(1 - t);\n    };\n  }\n  function d3_ease_reflect(f) {\n    return function(t) {\n      return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));\n    };\n  }\n  function d3_ease_quad(t) {\n    return t * t;\n  }\n  function d3_ease_cubic(t) {\n    return t * t * t;\n  }\n  function d3_ease_cubicInOut(t) {\n    if (t <= 0) return 0;\n    if (t >= 1) return 1;\n    var t2 = t * t, t3 = t2 * t;\n    return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);\n  }\n  function d3_ease_poly(e) {\n    return function(t) {\n      return Math.pow(t, e);\n    };\n  }\n  function d3_ease_sin(t) {\n    return 1 - Math.cos(t * π / 2);\n  }\n  function d3_ease_exp(t) {\n    return Math.pow(2, 10 * (t - 1));\n  }\n  function d3_ease_circle(t) {\n    return 1 - Math.sqrt(1 - t * t);\n  }\n  function d3_ease_elastic(a, p) {\n    var s;\n    if (arguments.length < 2) p = .45;\n    if (arguments.length) s = p / (2 * π) * Math.asin(1 / a); else a = 1, s = p / 4;\n    return function(t) {\n      return 1 + a * Math.pow(2, 10 * -t) * Math.sin((t - s) * 2 * π / p);\n    };\n  }\n  function d3_ease_back(s) {\n    if (!s) s = 1.70158;\n    return function(t) {\n      return t * t * ((s + 1) * t - s);\n    };\n  }\n  function d3_ease_bounce(t) {\n    return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;\n  }\n  d3.interpolateHcl = d3_interpolateHcl;\n  function d3_interpolateHcl(a, b) {\n    a = d3.hcl(a);\n    b = d3.hcl(b);\n    var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;\n    if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;\n    return function(t) {\n      return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + \"\";\n    };\n  }\n  d3.interpolateHsl = d3_interpolateHsl;\n  function d3_interpolateHsl(a, b) {\n    a = d3.hsl(a);\n    b = d3.hsl(b);\n    var h0 = a.h, s0 = a.s, l0 = a.l, h1 = b.h - h0, s1 = b.s - s0, l1 = b.l - l0;\n    if (h1 > 180) h1 -= 360; else if (h1 < -180) h1 += 360;\n    return function(t) {\n      return d3_hsl_rgb(h0 + h1 * t, s0 + s1 * t, l0 + l1 * t) + \"\";\n    };\n  }\n  d3.interpolateLab = d3_interpolateLab;\n  function d3_interpolateLab(a, b) {\n    a = d3.lab(a);\n    b = d3.lab(b);\n    var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;\n    return function(t) {\n      return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + \"\";\n    };\n  }\n  d3.interpolateRound = d3_interpolateRound;\n  function d3_interpolateRound(a, b) {\n    b -= a;\n    return function(t) {\n      return Math.round(a + b * t);\n    };\n  }\n  function d3_uninterpolateNumber(a, b) {\n    b = b - (a = +a) ? 1 / (b - a) : 0;\n    return function(x) {\n      return (x - a) * b;\n    };\n  }\n  function d3_uninterpolateClamp(a, b) {\n    b = b - (a = +a) ? 1 / (b - a) : 0;\n    return function(x) {\n      return Math.max(0, Math.min(1, (x - a) * b));\n    };\n  }\n  d3.layout = {};\n  d3.layout.bundle = function() {\n    return function(links) {\n      var paths = [], i = -1, n = links.length;\n      while (++i < n) paths.push(d3_layout_bundlePath(links[i]));\n      return paths;\n    };\n  };\n  function d3_layout_bundlePath(link) {\n    var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ];\n    while (start !== lca) {\n      start = start.parent;\n      points.push(start);\n    }\n    var k = points.length;\n    while (end !== lca) {\n      points.splice(k, 0, end);\n      end = end.parent;\n    }\n    return points;\n  }\n  function d3_layout_bundleAncestors(node) {\n    var ancestors = [], parent = node.parent;\n    while (parent != null) {\n      ancestors.push(node);\n      node = parent;\n      parent = parent.parent;\n    }\n    ancestors.push(node);\n    return ancestors;\n  }\n  function d3_layout_bundleLeastCommonAncestor(a, b) {\n    if (a === b) return a;\n    var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null;\n    while (aNode === bNode) {\n      sharedNode = aNode;\n      aNode = aNodes.pop();\n      bNode = bNodes.pop();\n    }\n    return sharedNode;\n  }\n  d3.layout.chord = function() {\n    var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords;\n    function relayout() {\n      var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j;\n      chords = [];\n      groups = [];\n      k = 0, i = -1;\n      while (++i < n) {\n        x = 0, j = -1;\n        while (++j < n) {\n          x += matrix[i][j];\n        }\n        groupSums.push(x);\n        subgroupIndex.push(d3.range(n));\n        k += x;\n      }\n      if (sortGroups) {\n        groupIndex.sort(function(a, b) {\n          return sortGroups(groupSums[a], groupSums[b]);\n        });\n      }\n      if (sortSubgroups) {\n        subgroupIndex.forEach(function(d, i) {\n          d.sort(function(a, b) {\n            return sortSubgroups(matrix[i][a], matrix[i][b]);\n          });\n        });\n      }\n      k = (2 * π - padding * n) / k;\n      x = 0, i = -1;\n      while (++i < n) {\n        x0 = x, j = -1;\n        while (++j < n) {\n          var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k;\n          subgroups[di + \"-\" + dj] = {\n            index: di,\n            subindex: dj,\n            startAngle: a0,\n            endAngle: a1,\n            value: v\n          };\n        }\n        groups[di] = {\n          index: di,\n          startAngle: x0,\n          endAngle: x,\n          value: (x - x0) / k\n        };\n        x += padding;\n      }\n      i = -1;\n      while (++i < n) {\n        j = i - 1;\n        while (++j < n) {\n          var source = subgroups[i + \"-\" + j], target = subgroups[j + \"-\" + i];\n          if (source.value || target.value) {\n            chords.push(source.value < target.value ? {\n              source: target,\n              target: source\n            } : {\n              source: source,\n              target: target\n            });\n          }\n        }\n      }\n      if (sortChords) resort();\n    }\n    function resort() {\n      chords.sort(function(a, b) {\n        return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2);\n      });\n    }\n    chord.matrix = function(x) {\n      if (!arguments.length) return matrix;\n      n = (matrix = x) && matrix.length;\n      chords = groups = null;\n      return chord;\n    };\n    chord.padding = function(x) {\n      if (!arguments.length) return padding;\n      padding = x;\n      chords = groups = null;\n      return chord;\n    };\n    chord.sortGroups = function(x) {\n      if (!arguments.length) return sortGroups;\n      sortGroups = x;\n      chords = groups = null;\n      return chord;\n    };\n    chord.sortSubgroups = function(x) {\n      if (!arguments.length) return sortSubgroups;\n      sortSubgroups = x;\n      chords = null;\n      return chord;\n    };\n    chord.sortChords = function(x) {\n      if (!arguments.length) return sortChords;\n      sortChords = x;\n      if (chords) resort();\n      return chord;\n    };\n    chord.chords = function() {\n      if (!chords) relayout();\n      return chords;\n    };\n    chord.groups = function() {\n      if (!groups) relayout();\n      return groups;\n    };\n    return chord;\n  };\n  d3.layout.force = function() {\n    var force = {}, event = d3.dispatch(\"start\", \"tick\", \"end\"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, gravity = .1, theta = .8, nodes = [], links = [], distances, strengths, charges;\n    function repulse(node) {\n      return function(quad, x1, _, x2) {\n        if (quad.point !== node) {\n          var dx = quad.cx - node.x, dy = quad.cy - node.y, dn = 1 / Math.sqrt(dx * dx + dy * dy);\n          if ((x2 - x1) * dn < theta) {\n            var k = quad.charge * dn * dn;\n            node.px -= dx * k;\n            node.py -= dy * k;\n            return true;\n          }\n          if (quad.point && isFinite(dn)) {\n            var k = quad.pointCharge * dn * dn;\n            node.px -= dx * k;\n            node.py -= dy * k;\n          }\n        }\n        return !quad.charge;\n      };\n    }\n    force.tick = function() {\n      if ((alpha *= .99) < .005) {\n        event.end({\n          type: \"end\",\n          alpha: alpha = 0\n        });\n        return true;\n      }\n      var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y;\n      for (i = 0; i < m; ++i) {\n        o = links[i];\n        s = o.source;\n        t = o.target;\n        x = t.x - s.x;\n        y = t.y - s.y;\n        if (l = x * x + y * y) {\n          l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;\n          x *= l;\n          y *= l;\n          t.x -= x * (k = s.weight / (t.weight + s.weight));\n          t.y -= y * k;\n          s.x += x * (k = 1 - k);\n          s.y += y * k;\n        }\n      }\n      if (k = alpha * gravity) {\n        x = size[0] / 2;\n        y = size[1] / 2;\n        i = -1;\n        if (k) while (++i < n) {\n          o = nodes[i];\n          o.x += (x - o.x) * k;\n          o.y += (y - o.y) * k;\n        }\n      }\n      if (charge) {\n        d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges);\n        i = -1;\n        while (++i < n) {\n          if (!(o = nodes[i]).fixed) {\n            q.visit(repulse(o));\n          }\n        }\n      }\n      i = -1;\n      while (++i < n) {\n        o = nodes[i];\n        if (o.fixed) {\n          o.x = o.px;\n          o.y = o.py;\n        } else {\n          o.x -= (o.px - (o.px = o.x)) * friction;\n          o.y -= (o.py - (o.py = o.y)) * friction;\n        }\n      }\n      event.tick({\n        type: \"tick\",\n        alpha: alpha\n      });\n    };\n    force.nodes = function(x) {\n      if (!arguments.length) return nodes;\n      nodes = x;\n      return force;\n    };\n    force.links = function(x) {\n      if (!arguments.length) return links;\n      links = x;\n      return force;\n    };\n    force.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return force;\n    };\n    force.linkDistance = function(x) {\n      if (!arguments.length) return linkDistance;\n      linkDistance = typeof x === \"function\" ? x : +x;\n      return force;\n    };\n    force.distance = force.linkDistance;\n    force.linkStrength = function(x) {\n      if (!arguments.length) return linkStrength;\n      linkStrength = typeof x === \"function\" ? x : +x;\n      return force;\n    };\n    force.friction = function(x) {\n      if (!arguments.length) return friction;\n      friction = +x;\n      return force;\n    };\n    force.charge = function(x) {\n      if (!arguments.length) return charge;\n      charge = typeof x === \"function\" ? x : +x;\n      return force;\n    };\n    force.gravity = function(x) {\n      if (!arguments.length) return gravity;\n      gravity = +x;\n      return force;\n    };\n    force.theta = function(x) {\n      if (!arguments.length) return theta;\n      theta = +x;\n      return force;\n    };\n    force.alpha = function(x) {\n      if (!arguments.length) return alpha;\n      x = +x;\n      if (alpha) {\n        if (x > 0) alpha = x; else alpha = 0;\n      } else if (x > 0) {\n        event.start({\n          type: \"start\",\n          alpha: alpha = x\n        });\n        d3.timer(force.tick);\n      }\n      return force;\n    };\n    force.start = function() {\n      var i, j, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;\n      for (i = 0; i < n; ++i) {\n        (o = nodes[i]).index = i;\n        o.weight = 0;\n      }\n      for (i = 0; i < m; ++i) {\n        o = links[i];\n        if (typeof o.source == \"number\") o.source = nodes[o.source];\n        if (typeof o.target == \"number\") o.target = nodes[o.target];\n        ++o.source.weight;\n        ++o.target.weight;\n      }\n      for (i = 0; i < n; ++i) {\n        o = nodes[i];\n        if (isNaN(o.x)) o.x = position(\"x\", w);\n        if (isNaN(o.y)) o.y = position(\"y\", h);\n        if (isNaN(o.px)) o.px = o.x;\n        if (isNaN(o.py)) o.py = o.y;\n      }\n      distances = [];\n      if (typeof linkDistance === \"function\") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance;\n      strengths = [];\n      if (typeof linkStrength === \"function\") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength;\n      charges = [];\n      if (typeof charge === \"function\") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge;\n      function position(dimension, size) {\n        var neighbors = neighbor(i), j = -1, m = neighbors.length, x;\n        while (++j < m) if (!isNaN(x = neighbors[j][dimension])) return x;\n        return Math.random() * size;\n      }\n      function neighbor() {\n        if (!neighbors) {\n          neighbors = [];\n          for (j = 0; j < n; ++j) {\n            neighbors[j] = [];\n          }\n          for (j = 0; j < m; ++j) {\n            var o = links[j];\n            neighbors[o.source.index].push(o.target);\n            neighbors[o.target.index].push(o.source);\n          }\n        }\n        return neighbors[i];\n      }\n      return force.resume();\n    };\n    force.resume = function() {\n      return force.alpha(.1);\n    };\n    force.stop = function() {\n      return force.alpha(0);\n    };\n    force.drag = function() {\n      if (!drag) drag = d3.behavior.drag().origin(d3_identity).on(\"dragstart.force\", d3_layout_forceDragstart).on(\"drag.force\", dragmove).on(\"dragend.force\", d3_layout_forceDragend);\n      if (!arguments.length) return drag;\n      this.on(\"mouseover.force\", d3_layout_forceMouseover).on(\"mouseout.force\", d3_layout_forceMouseout).call(drag);\n    };\n    function dragmove(d) {\n      d.px = d3.event.x, d.py = d3.event.y;\n      force.resume();\n    }\n    return d3.rebind(force, event, \"on\");\n  };\n  function d3_layout_forceDragstart(d) {\n    d.fixed |= 2;\n  }\n  function d3_layout_forceDragend(d) {\n    d.fixed &= ~6;\n  }\n  function d3_layout_forceMouseover(d) {\n    d.fixed |= 4;\n    d.px = d.x, d.py = d.y;\n  }\n  function d3_layout_forceMouseout(d) {\n    d.fixed &= ~4;\n  }\n  function d3_layout_forceAccumulate(quad, alpha, charges) {\n    var cx = 0, cy = 0;\n    quad.charge = 0;\n    if (!quad.leaf) {\n      var nodes = quad.nodes, n = nodes.length, i = -1, c;\n      while (++i < n) {\n        c = nodes[i];\n        if (c == null) continue;\n        d3_layout_forceAccumulate(c, alpha, charges);\n        quad.charge += c.charge;\n        cx += c.charge * c.cx;\n        cy += c.charge * c.cy;\n      }\n    }\n    if (quad.point) {\n      if (!quad.leaf) {\n        quad.point.x += Math.random() - .5;\n        quad.point.y += Math.random() - .5;\n      }\n      var k = alpha * charges[quad.point.index];\n      quad.charge += quad.pointCharge = k;\n      cx += k * quad.point.x;\n      cy += k * quad.point.y;\n    }\n    quad.cx = cx / quad.charge;\n    quad.cy = cy / quad.charge;\n  }\n  var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1;\n  d3.layout.hierarchy = function() {\n    var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;\n    function recurse(node, depth, nodes) {\n      var childs = children.call(hierarchy, node, depth);\n      node.depth = depth;\n      nodes.push(node);\n      if (childs && (n = childs.length)) {\n        var i = -1, n, c = node.children = [], v = 0, j = depth + 1, d;\n        while (++i < n) {\n          d = recurse(childs[i], j, nodes);\n          d.parent = node;\n          c.push(d);\n          v += d.value;\n        }\n        if (sort) c.sort(sort);\n        if (value) node.value = v;\n      } else if (value) {\n        node.value = +value.call(hierarchy, node, depth) || 0;\n      }\n      return node;\n    }\n    function revalue(node, depth) {\n      var children = node.children, v = 0;\n      if (children && (n = children.length)) {\n        var i = -1, n, j = depth + 1;\n        while (++i < n) v += revalue(children[i], j);\n      } else if (value) {\n        v = +value.call(hierarchy, node, depth) || 0;\n      }\n      if (value) node.value = v;\n      return v;\n    }\n    function hierarchy(d) {\n      var nodes = [];\n      recurse(d, 0, nodes);\n      return nodes;\n    }\n    hierarchy.sort = function(x) {\n      if (!arguments.length) return sort;\n      sort = x;\n      return hierarchy;\n    };\n    hierarchy.children = function(x) {\n      if (!arguments.length) return children;\n      children = x;\n      return hierarchy;\n    };\n    hierarchy.value = function(x) {\n      if (!arguments.length) return value;\n      value = x;\n      return hierarchy;\n    };\n    hierarchy.revalue = function(root) {\n      revalue(root, 0);\n      return root;\n    };\n    return hierarchy;\n  };\n  function d3_layout_hierarchyRebind(object, hierarchy) {\n    d3.rebind(object, hierarchy, \"sort\", \"children\", \"value\");\n    object.nodes = object;\n    object.links = d3_layout_hierarchyLinks;\n    return object;\n  }\n  function d3_layout_hierarchyChildren(d) {\n    return d.children;\n  }\n  function d3_layout_hierarchyValue(d) {\n    return d.value;\n  }\n  function d3_layout_hierarchySort(a, b) {\n    return b.value - a.value;\n  }\n  function d3_layout_hierarchyLinks(nodes) {\n    return d3.merge(nodes.map(function(parent) {\n      return (parent.children || []).map(function(child) {\n        return {\n          source: parent,\n          target: child\n        };\n      });\n    }));\n  }\n  d3.layout.partition = function() {\n    var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];\n    function position(node, x, dx, dy) {\n      var children = node.children;\n      node.x = x;\n      node.y = node.depth * dy;\n      node.dx = dx;\n      node.dy = dy;\n      if (children && (n = children.length)) {\n        var i = -1, n, c, d;\n        dx = node.value ? dx / node.value : 0;\n        while (++i < n) {\n          position(c = children[i], x, d = c.value * dx, dy);\n          x += d;\n        }\n      }\n    }\n    function depth(node) {\n      var children = node.children, d = 0;\n      if (children && (n = children.length)) {\n        var i = -1, n;\n        while (++i < n) d = Math.max(d, depth(children[i]));\n      }\n      return 1 + d;\n    }\n    function partition(d, i) {\n      var nodes = hierarchy.call(this, d, i);\n      position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));\n      return nodes;\n    }\n    partition.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return partition;\n    };\n    return d3_layout_hierarchyRebind(partition, hierarchy);\n  };\n  d3.layout.pie = function() {\n    var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = 2 * π;\n    function pie(data) {\n      var values = data.map(function(d, i) {\n        return +value.call(pie, d, i);\n      });\n      var a = +(typeof startAngle === \"function\" ? startAngle.apply(this, arguments) : startAngle);\n      var k = ((typeof endAngle === \"function\" ? endAngle.apply(this, arguments) : endAngle) - a) / d3.sum(values);\n      var index = d3.range(data.length);\n      if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {\n        return values[j] - values[i];\n      } : function(i, j) {\n        return sort(data[i], data[j]);\n      });\n      var arcs = [];\n      index.forEach(function(i) {\n        var d;\n        arcs[i] = {\n          data: data[i],\n          value: d = values[i],\n          startAngle: a,\n          endAngle: a += d * k\n        };\n      });\n      return arcs;\n    }\n    pie.value = function(x) {\n      if (!arguments.length) return value;\n      value = x;\n      return pie;\n    };\n    pie.sort = function(x) {\n      if (!arguments.length) return sort;\n      sort = x;\n      return pie;\n    };\n    pie.startAngle = function(x) {\n      if (!arguments.length) return startAngle;\n      startAngle = x;\n      return pie;\n    };\n    pie.endAngle = function(x) {\n      if (!arguments.length) return endAngle;\n      endAngle = x;\n      return pie;\n    };\n    return pie;\n  };\n  var d3_layout_pieSortByValue = {};\n  d3.layout.stack = function() {\n    var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;\n    function stack(data, index) {\n      var series = data.map(function(d, i) {\n        return values.call(stack, d, i);\n      });\n      var points = series.map(function(d) {\n        return d.map(function(v, i) {\n          return [ x.call(stack, v, i), y.call(stack, v, i) ];\n        });\n      });\n      var orders = order.call(stack, points, index);\n      series = d3.permute(series, orders);\n      points = d3.permute(points, orders);\n      var offsets = offset.call(stack, points, index);\n      var n = series.length, m = series[0].length, i, j, o;\n      for (j = 0; j < m; ++j) {\n        out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);\n        for (i = 1; i < n; ++i) {\n          out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);\n        }\n      }\n      return data;\n    }\n    stack.values = function(x) {\n      if (!arguments.length) return values;\n      values = x;\n      return stack;\n    };\n    stack.order = function(x) {\n      if (!arguments.length) return order;\n      order = typeof x === \"function\" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;\n      return stack;\n    };\n    stack.offset = function(x) {\n      if (!arguments.length) return offset;\n      offset = typeof x === \"function\" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;\n      return stack;\n    };\n    stack.x = function(z) {\n      if (!arguments.length) return x;\n      x = z;\n      return stack;\n    };\n    stack.y = function(z) {\n      if (!arguments.length) return y;\n      y = z;\n      return stack;\n    };\n    stack.out = function(z) {\n      if (!arguments.length) return out;\n      out = z;\n      return stack;\n    };\n    return stack;\n  };\n  function d3_layout_stackX(d) {\n    return d.x;\n  }\n  function d3_layout_stackY(d) {\n    return d.y;\n  }\n  function d3_layout_stackOut(d, y0, y) {\n    d.y0 = y0;\n    d.y = y;\n  }\n  var d3_layout_stackOrders = d3.map({\n    \"inside-out\": function(data) {\n      var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {\n        return max[a] - max[b];\n      }), top = 0, bottom = 0, tops = [], bottoms = [];\n      for (i = 0; i < n; ++i) {\n        j = index[i];\n        if (top < bottom) {\n          top += sums[j];\n          tops.push(j);\n        } else {\n          bottom += sums[j];\n          bottoms.push(j);\n        }\n      }\n      return bottoms.reverse().concat(tops);\n    },\n    reverse: function(data) {\n      return d3.range(data.length).reverse();\n    },\n    \"default\": d3_layout_stackOrderDefault\n  });\n  var d3_layout_stackOffsets = d3.map({\n    silhouette: function(data) {\n      var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];\n      for (j = 0; j < m; ++j) {\n        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];\n        if (o > max) max = o;\n        sums.push(o);\n      }\n      for (j = 0; j < m; ++j) {\n        y0[j] = (max - sums[j]) / 2;\n      }\n      return y0;\n    },\n    wiggle: function(data) {\n      var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];\n      y0[0] = o = o0 = 0;\n      for (j = 1; j < m; ++j) {\n        for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];\n        for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {\n          for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {\n            s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;\n          }\n          s2 += s3 * data[i][j][1];\n        }\n        y0[j] = o -= s1 ? s2 / s1 * dx : 0;\n        if (o < o0) o0 = o;\n      }\n      for (j = 0; j < m; ++j) y0[j] -= o0;\n      return y0;\n    },\n    expand: function(data) {\n      var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];\n      for (j = 0; j < m; ++j) {\n        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];\n        if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k;\n      }\n      for (j = 0; j < m; ++j) y0[j] = 0;\n      return y0;\n    },\n    zero: d3_layout_stackOffsetZero\n  });\n  function d3_layout_stackOrderDefault(data) {\n    return d3.range(data.length);\n  }\n  function d3_layout_stackOffsetZero(data) {\n    var j = -1, m = data[0].length, y0 = [];\n    while (++j < m) y0[j] = 0;\n    return y0;\n  }\n  function d3_layout_stackMaxIndex(array) {\n    var i = 1, j = 0, v = array[0][1], k, n = array.length;\n    for (;i < n; ++i) {\n      if ((k = array[i][1]) > v) {\n        j = i;\n        v = k;\n      }\n    }\n    return j;\n  }\n  function d3_layout_stackReduceSum(d) {\n    return d.reduce(d3_layout_stackSum, 0);\n  }\n  function d3_layout_stackSum(p, d) {\n    return p + d[1];\n  }\n  d3.layout.histogram = function() {\n    var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;\n    function histogram(data, i) {\n      var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;\n      while (++i < m) {\n        bin = bins[i] = [];\n        bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);\n        bin.y = 0;\n      }\n      if (m > 0) {\n        i = -1;\n        while (++i < n) {\n          x = values[i];\n          if (x >= range[0] && x <= range[1]) {\n            bin = bins[d3.bisect(thresholds, x, 1, m) - 1];\n            bin.y += k;\n            bin.push(data[i]);\n          }\n        }\n      }\n      return bins;\n    }\n    histogram.value = function(x) {\n      if (!arguments.length) return valuer;\n      valuer = x;\n      return histogram;\n    };\n    histogram.range = function(x) {\n      if (!arguments.length) return ranger;\n      ranger = d3_functor(x);\n      return histogram;\n    };\n    histogram.bins = function(x) {\n      if (!arguments.length) return binner;\n      binner = typeof x === \"number\" ? function(range) {\n        return d3_layout_histogramBinFixed(range, x);\n      } : d3_functor(x);\n      return histogram;\n    };\n    histogram.frequency = function(x) {\n      if (!arguments.length) return frequency;\n      frequency = !!x;\n      return histogram;\n    };\n    return histogram;\n  };\n  function d3_layout_histogramBinSturges(range, values) {\n    return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));\n  }\n  function d3_layout_histogramBinFixed(range, n) {\n    var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];\n    while (++x <= n) f[x] = m * x + b;\n    return f;\n  }\n  function d3_layout_histogramRange(values) {\n    return [ d3.min(values), d3.max(values) ];\n  }\n  d3.layout.tree = function() {\n    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];\n    function tree(d, i) {\n      var nodes = hierarchy.call(this, d, i), root = nodes[0];\n      function firstWalk(node, previousSibling) {\n        var children = node.children, layout = node._tree;\n        if (children && (n = children.length)) {\n          var n, firstChild = children[0], previousChild, ancestor = firstChild, child, i = -1;\n          while (++i < n) {\n            child = children[i];\n            firstWalk(child, previousChild);\n            ancestor = apportion(child, previousChild, ancestor);\n            previousChild = child;\n          }\n          d3_layout_treeShift(node);\n          var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);\n          if (previousSibling) {\n            layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);\n            layout.mod = layout.prelim - midpoint;\n          } else {\n            layout.prelim = midpoint;\n          }\n        } else {\n          if (previousSibling) {\n            layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);\n          }\n        }\n      }\n      function secondWalk(node, x) {\n        node.x = node._tree.prelim + x;\n        var children = node.children;\n        if (children && (n = children.length)) {\n          var i = -1, n;\n          x += node._tree.mod;\n          while (++i < n) {\n            secondWalk(children[i], x);\n          }\n        }\n      }\n      function apportion(node, previousSibling, ancestor) {\n        if (previousSibling) {\n          var vip = node, vop = node, vim = previousSibling, vom = node.parent.children[0], sip = vip._tree.mod, sop = vop._tree.mod, sim = vim._tree.mod, som = vom._tree.mod, shift;\n          while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {\n            vom = d3_layout_treeLeft(vom);\n            vop = d3_layout_treeRight(vop);\n            vop._tree.ancestor = node;\n            shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);\n            if (shift > 0) {\n              d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);\n              sip += shift;\n              sop += shift;\n            }\n            sim += vim._tree.mod;\n            sip += vip._tree.mod;\n            som += vom._tree.mod;\n            sop += vop._tree.mod;\n          }\n          if (vim && !d3_layout_treeRight(vop)) {\n            vop._tree.thread = vim;\n            vop._tree.mod += sim - sop;\n          }\n          if (vip && !d3_layout_treeLeft(vom)) {\n            vom._tree.thread = vip;\n            vom._tree.mod += sip - som;\n            ancestor = node;\n          }\n        }\n        return ancestor;\n      }\n      d3_layout_treeVisitAfter(root, function(node, previousSibling) {\n        node._tree = {\n          ancestor: node,\n          prelim: 0,\n          mod: 0,\n          change: 0,\n          shift: 0,\n          number: previousSibling ? previousSibling._tree.number + 1 : 0\n        };\n      });\n      firstWalk(root);\n      secondWalk(root, -root._tree.prelim);\n      var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost), right = d3_layout_treeSearch(root, d3_layout_treeRightmost), deep = d3_layout_treeSearch(root, d3_layout_treeDeepest), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2, y1 = deep.depth || 1;\n      d3_layout_treeVisitAfter(root, function(node) {\n        node.x = (node.x - x0) / (x1 - x0) * size[0];\n        node.y = node.depth / y1 * size[1];\n        delete node._tree;\n      });\n      return nodes;\n    }\n    tree.separation = function(x) {\n      if (!arguments.length) return separation;\n      separation = x;\n      return tree;\n    };\n    tree.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return tree;\n    };\n    return d3_layout_hierarchyRebind(tree, hierarchy);\n  };\n  function d3_layout_treeSeparation(a, b) {\n    return a.parent == b.parent ? 1 : 2;\n  }\n  function d3_layout_treeLeft(node) {\n    var children = node.children;\n    return children && children.length ? children[0] : node._tree.thread;\n  }\n  function d3_layout_treeRight(node) {\n    var children = node.children, n;\n    return children && (n = children.length) ? children[n - 1] : node._tree.thread;\n  }\n  function d3_layout_treeSearch(node, compare) {\n    var children = node.children;\n    if (children && (n = children.length)) {\n      var child, n, i = -1;\n      while (++i < n) {\n        if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {\n          node = child;\n        }\n      }\n    }\n    return node;\n  }\n  function d3_layout_treeRightmost(a, b) {\n    return a.x - b.x;\n  }\n  function d3_layout_treeLeftmost(a, b) {\n    return b.x - a.x;\n  }\n  function d3_layout_treeDeepest(a, b) {\n    return a.depth - b.depth;\n  }\n  function d3_layout_treeVisitAfter(node, callback) {\n    function visit(node, previousSibling) {\n      var children = node.children;\n      if (children && (n = children.length)) {\n        var child, previousChild = null, i = -1, n;\n        while (++i < n) {\n          child = children[i];\n          visit(child, previousChild);\n          previousChild = child;\n        }\n      }\n      callback(node, previousSibling);\n    }\n    visit(node, null);\n  }\n  function d3_layout_treeShift(node) {\n    var shift = 0, change = 0, children = node.children, i = children.length, child;\n    while (--i >= 0) {\n      child = children[i]._tree;\n      child.prelim += shift;\n      child.mod += shift;\n      shift += child.shift + (change += child.change);\n    }\n  }\n  function d3_layout_treeMove(ancestor, node, shift) {\n    ancestor = ancestor._tree;\n    node = node._tree;\n    var change = shift / (node.number - ancestor.number);\n    ancestor.change += change;\n    node.change -= change;\n    node.shift += shift;\n    node.prelim += shift;\n    node.mod += shift;\n  }\n  function d3_layout_treeAncestor(vim, node, ancestor) {\n    return vim._tree.ancestor.parent == node.parent ? vim._tree.ancestor : ancestor;\n  }\n  d3.layout.pack = function() {\n    var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ];\n    function pack(d, i) {\n      var nodes = hierarchy.call(this, d, i), root = nodes[0];\n      root.x = 0;\n      root.y = 0;\n      d3_layout_treeVisitAfter(root, function(d) {\n        d.r = Math.sqrt(d.value);\n      });\n      d3_layout_treeVisitAfter(root, d3_layout_packSiblings);\n      var w = size[0], h = size[1], k = Math.max(2 * root.r / w, 2 * root.r / h);\n      if (padding > 0) {\n        var dr = padding * k / 2;\n        d3_layout_treeVisitAfter(root, function(d) {\n          d.r += dr;\n        });\n        d3_layout_treeVisitAfter(root, d3_layout_packSiblings);\n        d3_layout_treeVisitAfter(root, function(d) {\n          d.r -= dr;\n        });\n        k = Math.max(2 * root.r / w, 2 * root.r / h);\n      }\n      d3_layout_packTransform(root, w / 2, h / 2, 1 / k);\n      return nodes;\n    }\n    pack.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return pack;\n    };\n    pack.padding = function(_) {\n      if (!arguments.length) return padding;\n      padding = +_;\n      return pack;\n    };\n    return d3_layout_hierarchyRebind(pack, hierarchy);\n  };\n  function d3_layout_packSort(a, b) {\n    return a.value - b.value;\n  }\n  function d3_layout_packInsert(a, b) {\n    var c = a._pack_next;\n    a._pack_next = b;\n    b._pack_prev = a;\n    b._pack_next = c;\n    c._pack_prev = b;\n  }\n  function d3_layout_packSplice(a, b) {\n    a._pack_next = b;\n    b._pack_prev = a;\n  }\n  function d3_layout_packIntersects(a, b) {\n    var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;\n    return dr * dr - dx * dx - dy * dy > .001;\n  }\n  function d3_layout_packSiblings(node) {\n    if (!(nodes = node.children) || !(n = nodes.length)) return;\n    var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;\n    function bound(node) {\n      xMin = Math.min(node.x - node.r, xMin);\n      xMax = Math.max(node.x + node.r, xMax);\n      yMin = Math.min(node.y - node.r, yMin);\n      yMax = Math.max(node.y + node.r, yMax);\n    }\n    nodes.forEach(d3_layout_packLink);\n    a = nodes[0];\n    a.x = -a.r;\n    a.y = 0;\n    bound(a);\n    if (n > 1) {\n      b = nodes[1];\n      b.x = b.r;\n      b.y = 0;\n      bound(b);\n      if (n > 2) {\n        c = nodes[2];\n        d3_layout_packPlace(a, b, c);\n        bound(c);\n        d3_layout_packInsert(a, c);\n        a._pack_prev = c;\n        d3_layout_packInsert(c, b);\n        b = a._pack_next;\n        for (i = 3; i < n; i++) {\n          d3_layout_packPlace(a, b, c = nodes[i]);\n          var isect = 0, s1 = 1, s2 = 1;\n          for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {\n            if (d3_layout_packIntersects(j, c)) {\n              isect = 1;\n              break;\n            }\n          }\n          if (isect == 1) {\n            for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {\n              if (d3_layout_packIntersects(k, c)) {\n                break;\n              }\n            }\n          }\n          if (isect) {\n            if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);\n            i--;\n          } else {\n            d3_layout_packInsert(a, c);\n            b = c;\n            bound(c);\n          }\n        }\n      }\n    }\n    var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;\n    for (i = 0; i < n; i++) {\n      c = nodes[i];\n      c.x -= cx;\n      c.y -= cy;\n      cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));\n    }\n    node.r = cr;\n    nodes.forEach(d3_layout_packUnlink);\n  }\n  function d3_layout_packLink(node) {\n    node._pack_next = node._pack_prev = node;\n  }\n  function d3_layout_packUnlink(node) {\n    delete node._pack_next;\n    delete node._pack_prev;\n  }\n  function d3_layout_packTransform(node, x, y, k) {\n    var children = node.children;\n    node.x = x += k * node.x;\n    node.y = y += k * node.y;\n    node.r *= k;\n    if (children) {\n      var i = -1, n = children.length;\n      while (++i < n) d3_layout_packTransform(children[i], x, y, k);\n    }\n  }\n  function d3_layout_packPlace(a, b, c) {\n    var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;\n    if (db && (dx || dy)) {\n      var da = b.r + c.r, dc = dx * dx + dy * dy;\n      da *= da;\n      db *= db;\n      var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);\n      c.x = a.x + x * dx + y * dy;\n      c.y = a.y + x * dy - y * dx;\n    } else {\n      c.x = a.x + db;\n      c.y = a.y;\n    }\n  }\n  d3.layout.cluster = function() {\n    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];\n    function cluster(d, i) {\n      var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;\n      d3_layout_treeVisitAfter(root, function(node) {\n        var children = node.children;\n        if (children && children.length) {\n          node.x = d3_layout_clusterX(children);\n          node.y = d3_layout_clusterY(children);\n        } else {\n          node.x = previousNode ? x += separation(node, previousNode) : 0;\n          node.y = 0;\n          previousNode = node;\n        }\n      });\n      var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;\n      d3_layout_treeVisitAfter(root, function(node) {\n        node.x = (node.x - x0) / (x1 - x0) * size[0];\n        node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];\n      });\n      return nodes;\n    }\n    cluster.separation = function(x) {\n      if (!arguments.length) return separation;\n      separation = x;\n      return cluster;\n    };\n    cluster.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return cluster;\n    };\n    return d3_layout_hierarchyRebind(cluster, hierarchy);\n  };\n  function d3_layout_clusterY(children) {\n    return 1 + d3.max(children, function(child) {\n      return child.y;\n    });\n  }\n  function d3_layout_clusterX(children) {\n    return children.reduce(function(x, child) {\n      return x + child.x;\n    }, 0) / children.length;\n  }\n  function d3_layout_clusterLeft(node) {\n    var children = node.children;\n    return children && children.length ? d3_layout_clusterLeft(children[0]) : node;\n  }\n  function d3_layout_clusterRight(node) {\n    var children = node.children, n;\n    return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;\n  }\n  d3.layout.treemap = function() {\n    var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = \"squarify\", ratio = .5 * (1 + Math.sqrt(5));\n    function scale(children, k) {\n      var i = -1, n = children.length, child, area;\n      while (++i < n) {\n        area = (child = children[i]).value * (k < 0 ? 0 : k);\n        child.area = isNaN(area) || area <= 0 ? 0 : area;\n      }\n    }\n    function squarify(node) {\n      var children = node.children;\n      if (children && children.length) {\n        var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === \"slice\" ? rect.dx : mode === \"dice\" ? rect.dy : mode === \"slice-dice\" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n;\n        scale(remaining, rect.dx * rect.dy / node.value);\n        row.area = 0;\n        while ((n = remaining.length) > 0) {\n          row.push(child = remaining[n - 1]);\n          row.area += child.area;\n          if (mode !== \"squarify\" || (score = worst(row, u)) <= best) {\n            remaining.pop();\n            best = score;\n          } else {\n            row.area -= row.pop().area;\n            position(row, u, rect, false);\n            u = Math.min(rect.dx, rect.dy);\n            row.length = row.area = 0;\n            best = Infinity;\n          }\n        }\n        if (row.length) {\n          position(row, u, rect, true);\n          row.length = row.area = 0;\n        }\n        children.forEach(squarify);\n      }\n    }\n    function stickify(node) {\n      var children = node.children;\n      if (children && children.length) {\n        var rect = pad(node), remaining = children.slice(), child, row = [];\n        scale(remaining, rect.dx * rect.dy / node.value);\n        row.area = 0;\n        while (child = remaining.pop()) {\n          row.push(child);\n          row.area += child.area;\n          if (child.z != null) {\n            position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);\n            row.length = row.area = 0;\n          }\n        }\n        children.forEach(stickify);\n      }\n    }\n    function worst(row, u) {\n      var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;\n      while (++i < n) {\n        if (!(r = row[i].area)) continue;\n        if (r < rmin) rmin = r;\n        if (r > rmax) rmax = r;\n      }\n      s *= s;\n      u *= u;\n      return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;\n    }\n    function position(row, u, rect, flush) {\n      var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;\n      if (u == rect.dx) {\n        if (flush || v > rect.dy) v = rect.dy;\n        while (++i < n) {\n          o = row[i];\n          o.x = x;\n          o.y = y;\n          o.dy = v;\n          x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);\n        }\n        o.z = true;\n        o.dx += rect.x + rect.dx - x;\n        rect.y += v;\n        rect.dy -= v;\n      } else {\n        if (flush || v > rect.dx) v = rect.dx;\n        while (++i < n) {\n          o = row[i];\n          o.x = x;\n          o.y = y;\n          o.dx = v;\n          y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);\n        }\n        o.z = false;\n        o.dy += rect.y + rect.dy - y;\n        rect.x += v;\n        rect.dx -= v;\n      }\n    }\n    function treemap(d) {\n      var nodes = stickies || hierarchy(d), root = nodes[0];\n      root.x = 0;\n      root.y = 0;\n      root.dx = size[0];\n      root.dy = size[1];\n      if (stickies) hierarchy.revalue(root);\n      scale([ root ], root.dx * root.dy / root.value);\n      (stickies ? stickify : squarify)(root);\n      if (sticky) stickies = nodes;\n      return nodes;\n    }\n    treemap.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return treemap;\n    };\n    treemap.padding = function(x) {\n      if (!arguments.length) return padding;\n      function padFunction(node) {\n        var p = x.call(treemap, node, node.depth);\n        return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === \"number\" ? [ p, p, p, p ] : p);\n      }\n      function padConstant(node) {\n        return d3_layout_treemapPad(node, x);\n      }\n      var type;\n      pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === \"function\" ? padFunction : type === \"number\" ? (x = [ x, x, x, x ],\n      padConstant) : padConstant;\n      return treemap;\n    };\n    treemap.round = function(x) {\n      if (!arguments.length) return round != Number;\n      round = x ? Math.round : Number;\n      return treemap;\n    };\n    treemap.sticky = function(x) {\n      if (!arguments.length) return sticky;\n      sticky = x;\n      stickies = null;\n      return treemap;\n    };\n    treemap.ratio = function(x) {\n      if (!arguments.length) return ratio;\n      ratio = x;\n      return treemap;\n    };\n    treemap.mode = function(x) {\n      if (!arguments.length) return mode;\n      mode = x + \"\";\n      return treemap;\n    };\n    return d3_layout_hierarchyRebind(treemap, hierarchy);\n  };\n  function d3_layout_treemapPadNull(node) {\n    return {\n      x: node.x,\n      y: node.y,\n      dx: node.dx,\n      dy: node.dy\n    };\n  }\n  function d3_layout_treemapPad(node, padding) {\n    var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];\n    if (dx < 0) {\n      x += dx / 2;\n      dx = 0;\n    }\n    if (dy < 0) {\n      y += dy / 2;\n      dy = 0;\n    }\n    return {\n      x: x,\n      y: y,\n      dx: dx,\n      dy: dy\n    };\n  }\n  d3.random = {\n    normal: function(µ, σ) {\n      var n = arguments.length;\n      if (n < 2) σ = 1;\n      if (n < 1) µ = 0;\n      return function() {\n        var x, y, r;\n        do {\n          x = Math.random() * 2 - 1;\n          y = Math.random() * 2 - 1;\n          r = x * x + y * y;\n        } while (!r || r > 1);\n        return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);\n      };\n    },\n    logNormal: function() {\n      var random = d3.random.normal.apply(d3, arguments);\n      return function() {\n        return Math.exp(random());\n      };\n    },\n    irwinHall: function(m) {\n      return function() {\n        for (var s = 0, j = 0; j < m; j++) s += Math.random();\n        return s / m;\n      };\n    }\n  };\n  d3.scale = {};\n  function d3_scaleExtent(domain) {\n    var start = domain[0], stop = domain[domain.length - 1];\n    return start < stop ? [ start, stop ] : [ stop, start ];\n  }\n  function d3_scaleRange(scale) {\n    return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());\n  }\n  function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {\n    var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);\n    return function(x) {\n      return i(u(x));\n    };\n  }\n  function d3_scale_nice(domain, nice) {\n    var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;\n    if (x1 < x0) {\n      dx = i0, i0 = i1, i1 = dx;\n      dx = x0, x0 = x1, x1 = dx;\n    }\n    if (nice = nice(x1 - x0)) {\n      domain[i0] = nice.floor(x0);\n      domain[i1] = nice.ceil(x1);\n    }\n    return domain;\n  }\n  function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {\n    var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;\n    if (domain[k] < domain[0]) {\n      domain = domain.slice().reverse();\n      range = range.slice().reverse();\n    }\n    while (++j <= k) {\n      u.push(uninterpolate(domain[j - 1], domain[j]));\n      i.push(interpolate(range[j - 1], range[j]));\n    }\n    return function(x) {\n      var j = d3.bisect(domain, x, 1, k) - 1;\n      return i[j](u[j](x));\n    };\n  }\n  d3.scale.linear = function() {\n    return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false);\n  };\n  function d3_scale_linear(domain, range, interpolate, clamp) {\n    var output, input;\n    function rescale() {\n      var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;\n      output = linear(domain, range, uninterpolate, interpolate);\n      input = linear(range, domain, uninterpolate, d3_interpolate);\n      return scale;\n    }\n    function scale(x) {\n      return output(x);\n    }\n    scale.invert = function(y) {\n      return input(y);\n    };\n    scale.domain = function(x) {\n      if (!arguments.length) return domain;\n      domain = x.map(Number);\n      return rescale();\n    };\n    scale.range = function(x) {\n      if (!arguments.length) return range;\n      range = x;\n      return rescale();\n    };\n    scale.rangeRound = function(x) {\n      return scale.range(x).interpolate(d3_interpolateRound);\n    };\n    scale.clamp = function(x) {\n      if (!arguments.length) return clamp;\n      clamp = x;\n      return rescale();\n    };\n    scale.interpolate = function(x) {\n      if (!arguments.length) return interpolate;\n      interpolate = x;\n      return rescale();\n    };\n    scale.ticks = function(m) {\n      return d3_scale_linearTicks(domain, m);\n    };\n    scale.tickFormat = function(m, format) {\n      return d3_scale_linearTickFormat(domain, m, format);\n    };\n    scale.nice = function() {\n      d3_scale_nice(domain, d3_scale_linearNice);\n      return rescale();\n    };\n    scale.copy = function() {\n      return d3_scale_linear(domain, range, interpolate, clamp);\n    };\n    return rescale();\n  }\n  function d3_scale_linearRebind(scale, linear) {\n    return d3.rebind(scale, linear, \"range\", \"rangeRound\", \"interpolate\", \"clamp\");\n  }\n  function d3_scale_linearNice(dx) {\n    dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1);\n    return dx && {\n      floor: function(x) {\n        return Math.floor(x / dx) * dx;\n      },\n      ceil: function(x) {\n        return Math.ceil(x / dx) * dx;\n      }\n    };\n  }\n  function d3_scale_linearTickRange(domain, m) {\n    var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;\n    if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;\n    extent[0] = Math.ceil(extent[0] / step) * step;\n    extent[1] = Math.floor(extent[1] / step) * step + step * .5;\n    extent[2] = step;\n    return extent;\n  }\n  function d3_scale_linearTicks(domain, m) {\n    return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));\n  }\n  function d3_scale_linearTickFormat(domain, m, format) {\n    var precision = -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01);\n    return d3.format(format ? format.replace(d3_format_re, function(a, b, c, d, e, f, g, h, i, j) {\n      return [ b, c, d, e, f, g, h, i || \".\" + (precision - (j === \"%\") * 2), j ].join(\"\");\n    }) : \",.\" + precision + \"f\");\n  }\n  d3.scale.log = function() {\n    return d3_scale_log(d3.scale.linear().domain([ 0, Math.LN10 ]), 10, d3_scale_logp, d3_scale_powp);\n  };\n  function d3_scale_log(linear, base, log, pow) {\n    function scale(x) {\n      return linear(log(x));\n    }\n    scale.invert = function(x) {\n      return pow(linear.invert(x));\n    };\n    scale.domain = function(x) {\n      if (!arguments.length) return linear.domain().map(pow);\n      if (x[0] < 0) log = d3_scale_logn, pow = d3_scale_pown; else log = d3_scale_logp,\n      pow = d3_scale_powp;\n      linear.domain(x.map(log));\n      return scale;\n    };\n    scale.base = function(_) {\n      if (!arguments.length) return base;\n      base = +_;\n      return scale;\n    };\n    scale.nice = function() {\n      linear.domain(d3_scale_nice(linear.domain(), d3_scale_logNice(base)));\n      return scale;\n    };\n    scale.ticks = function() {\n      var extent = d3_scaleExtent(linear.domain()), ticks = [];\n      if (extent.every(isFinite)) {\n        var b = Math.log(base), i = Math.floor(extent[0] / b), j = Math.ceil(extent[1] / b), u = pow(extent[0]), v = pow(extent[1]), n = base % 1 ? 2 : base;\n        if (log === d3_scale_logn) {\n          ticks.push(-Math.pow(base, -i));\n          for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(-Math.pow(base, -i) * k);\n        } else {\n          for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(Math.pow(base, i) * k);\n          ticks.push(Math.pow(base, i));\n        }\n        for (i = 0; ticks[i] < u; i++) {}\n        for (j = ticks.length; ticks[j - 1] > v; j--) {}\n        ticks = ticks.slice(i, j);\n      }\n      return ticks;\n    };\n    scale.tickFormat = function(n, format) {\n      if (arguments.length < 2) format = d3_scale_logFormat;\n      if (!arguments.length) return format;\n      var b = Math.log(base), k = Math.max(.1, n / scale.ticks().length), f = log === d3_scale_logn ? (e = -1e-12,\n      Math.floor) : (e = 1e-12, Math.ceil), e;\n      return function(d) {\n        return d / pow(b * f(log(d) / b + e)) <= k ? format(d) : \"\";\n      };\n    };\n    scale.copy = function() {\n      return d3_scale_log(linear.copy(), base, log, pow);\n    };\n    return d3_scale_linearRebind(scale, linear);\n  }\n  var d3_scale_logFormat = d3.format(\".0e\");\n  function d3_scale_logp(x) {\n    return Math.log(x < 0 ? 0 : x);\n  }\n  function d3_scale_powp(x) {\n    return Math.exp(x);\n  }\n  function d3_scale_logn(x) {\n    return -Math.log(x > 0 ? 0 : -x);\n  }\n  function d3_scale_pown(x) {\n    return -Math.exp(-x);\n  }\n  function d3_scale_logNice(base) {\n    base = Math.log(base);\n    var nice = {\n      floor: function(x) {\n        return Math.floor(x / base) * base;\n      },\n      ceil: function(x) {\n        return Math.ceil(x / base) * base;\n      }\n    };\n    return function() {\n      return nice;\n    };\n  }\n  d3.scale.pow = function() {\n    return d3_scale_pow(d3.scale.linear(), 1);\n  };\n  function d3_scale_pow(linear, exponent) {\n    var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);\n    function scale(x) {\n      return linear(powp(x));\n    }\n    scale.invert = function(x) {\n      return powb(linear.invert(x));\n    };\n    scale.domain = function(x) {\n      if (!arguments.length) return linear.domain().map(powb);\n      linear.domain(x.map(powp));\n      return scale;\n    };\n    scale.ticks = function(m) {\n      return d3_scale_linearTicks(scale.domain(), m);\n    };\n    scale.tickFormat = function(m, format) {\n      return d3_scale_linearTickFormat(scale.domain(), m, format);\n    };\n    scale.nice = function() {\n      return scale.domain(d3_scale_nice(scale.domain(), d3_scale_linearNice));\n    };\n    scale.exponent = function(x) {\n      if (!arguments.length) return exponent;\n      var domain = scale.domain();\n      powp = d3_scale_powPow(exponent = x);\n      powb = d3_scale_powPow(1 / exponent);\n      return scale.domain(domain);\n    };\n    scale.copy = function() {\n      return d3_scale_pow(linear.copy(), exponent);\n    };\n    return d3_scale_linearRebind(scale, linear);\n  }\n  function d3_scale_powPow(e) {\n    return function(x) {\n      return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);\n    };\n  }\n  d3.scale.sqrt = function() {\n    return d3.scale.pow().exponent(.5);\n  };\n  d3.scale.ordinal = function() {\n    return d3_scale_ordinal([], {\n      t: \"range\",\n      a: [ [] ]\n    });\n  };\n  function d3_scale_ordinal(domain, ranger) {\n    var index, range, rangeBand;\n    function scale(x) {\n      return range[((index.get(x) || index.set(x, domain.push(x))) - 1) % range.length];\n    }\n    function steps(start, step) {\n      return d3.range(domain.length).map(function(i) {\n        return start + step * i;\n      });\n    }\n    scale.domain = function(x) {\n      if (!arguments.length) return domain;\n      domain = [];\n      index = new d3_Map();\n      var i = -1, n = x.length, xi;\n      while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));\n      return scale[ranger.t].apply(scale, ranger.a);\n    };\n    scale.range = function(x) {\n      if (!arguments.length) return range;\n      range = x;\n      rangeBand = 0;\n      ranger = {\n        t: \"range\",\n        a: arguments\n      };\n      return scale;\n    };\n    scale.rangePoints = function(x, padding) {\n      if (arguments.length < 2) padding = 0;\n      var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding);\n      range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step);\n      rangeBand = 0;\n      ranger = {\n        t: \"rangePoints\",\n        a: arguments\n      };\n      return scale;\n    };\n    scale.rangeBands = function(x, padding, outerPadding) {\n      if (arguments.length < 2) padding = 0;\n      if (arguments.length < 3) outerPadding = padding;\n      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);\n      range = steps(start + step * outerPadding, step);\n      if (reverse) range.reverse();\n      rangeBand = step * (1 - padding);\n      ranger = {\n        t: \"rangeBands\",\n        a: arguments\n      };\n      return scale;\n    };\n    scale.rangeRoundBands = function(x, padding, outerPadding) {\n      if (arguments.length < 2) padding = 0;\n      if (arguments.length < 3) outerPadding = padding;\n      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step;\n      range = steps(start + Math.round(error / 2), step);\n      if (reverse) range.reverse();\n      rangeBand = Math.round(step * (1 - padding));\n      ranger = {\n        t: \"rangeRoundBands\",\n        a: arguments\n      };\n      return scale;\n    };\n    scale.rangeBand = function() {\n      return rangeBand;\n    };\n    scale.rangeExtent = function() {\n      return d3_scaleExtent(ranger.a[0]);\n    };\n    scale.copy = function() {\n      return d3_scale_ordinal(domain, ranger);\n    };\n    return scale.domain(domain);\n  }\n  d3.scale.category10 = function() {\n    return d3.scale.ordinal().range(d3_category10);\n  };\n  d3.scale.category20 = function() {\n    return d3.scale.ordinal().range(d3_category20);\n  };\n  d3.scale.category20b = function() {\n    return d3.scale.ordinal().range(d3_category20b);\n  };\n  d3.scale.category20c = function() {\n    return d3.scale.ordinal().range(d3_category20c);\n  };\n  var d3_category10 = [ \"#1f77b4\", \"#ff7f0e\", \"#2ca02c\", \"#d62728\", \"#9467bd\", \"#8c564b\", \"#e377c2\", \"#7f7f7f\", \"#bcbd22\", \"#17becf\" ];\n  var d3_category20 = [ \"#1f77b4\", \"#aec7e8\", \"#ff7f0e\", \"#ffbb78\", \"#2ca02c\", \"#98df8a\", \"#d62728\", \"#ff9896\", \"#9467bd\", \"#c5b0d5\", \"#8c564b\", \"#c49c94\", \"#e377c2\", \"#f7b6d2\", \"#7f7f7f\", \"#c7c7c7\", \"#bcbd22\", \"#dbdb8d\", \"#17becf\", \"#9edae5\" ];\n  var d3_category20b = [ \"#393b79\", \"#5254a3\", \"#6b6ecf\", \"#9c9ede\", \"#637939\", \"#8ca252\", \"#b5cf6b\", \"#cedb9c\", \"#8c6d31\", \"#bd9e39\", \"#e7ba52\", \"#e7cb94\", \"#843c39\", \"#ad494a\", \"#d6616b\", \"#e7969c\", \"#7b4173\", \"#a55194\", \"#ce6dbd\", \"#de9ed6\" ];\n  var d3_category20c = [ \"#3182bd\", \"#6baed6\", \"#9ecae1\", \"#c6dbef\", \"#e6550d\", \"#fd8d3c\", \"#fdae6b\", \"#fdd0a2\", \"#31a354\", \"#74c476\", \"#a1d99b\", \"#c7e9c0\", \"#756bb1\", \"#9e9ac8\", \"#bcbddc\", \"#dadaeb\", \"#636363\", \"#969696\", \"#bdbdbd\", \"#d9d9d9\" ];\n  d3.scale.quantile = function() {\n    return d3_scale_quantile([], []);\n  };\n  function d3_scale_quantile(domain, range) {\n    var thresholds;\n    function rescale() {\n      var k = 0, q = range.length;\n      thresholds = [];\n      while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);\n      return scale;\n    }\n    function scale(x) {\n      if (isNaN(x = +x)) return NaN;\n      return range[d3.bisect(thresholds, x)];\n    }\n    scale.domain = function(x) {\n      if (!arguments.length) return domain;\n      domain = x.filter(function(d) {\n        return !isNaN(d);\n      }).sort(d3.ascending);\n      return rescale();\n    };\n    scale.range = function(x) {\n      if (!arguments.length) return range;\n      range = x;\n      return rescale();\n    };\n    scale.quantiles = function() {\n      return thresholds;\n    };\n    scale.copy = function() {\n      return d3_scale_quantile(domain, range);\n    };\n    return rescale();\n  }\n  d3.scale.quantize = function() {\n    return d3_scale_quantize(0, 1, [ 0, 1 ]);\n  };\n  function d3_scale_quantize(x0, x1, range) {\n    var kx, i;\n    function scale(x) {\n      return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];\n    }\n    function rescale() {\n      kx = range.length / (x1 - x0);\n      i = range.length - 1;\n      return scale;\n    }\n    scale.domain = function(x) {\n      if (!arguments.length) return [ x0, x1 ];\n      x0 = +x[0];\n      x1 = +x[x.length - 1];\n      return rescale();\n    };\n    scale.range = function(x) {\n      if (!arguments.length) return range;\n      range = x;\n      return rescale();\n    };\n    scale.copy = function() {\n      return d3_scale_quantize(x0, x1, range);\n    };\n    return rescale();\n  }\n  d3.scale.threshold = function() {\n    return d3_scale_threshold([ .5 ], [ 0, 1 ]);\n  };\n  function d3_scale_threshold(domain, range) {\n    function scale(x) {\n      return range[d3.bisect(domain, x)];\n    }\n    scale.domain = function(_) {\n      if (!arguments.length) return domain;\n      domain = _;\n      return scale;\n    };\n    scale.range = function(_) {\n      if (!arguments.length) return range;\n      range = _;\n      return scale;\n    };\n    scale.copy = function() {\n      return d3_scale_threshold(domain, range);\n    };\n    return scale;\n  }\n  d3.scale.identity = function() {\n    return d3_scale_identity([ 0, 1 ]);\n  };\n  function d3_scale_identity(domain) {\n    function identity(x) {\n      return +x;\n    }\n    identity.invert = identity;\n    identity.domain = identity.range = function(x) {\n      if (!arguments.length) return domain;\n      domain = x.map(identity);\n      return identity;\n    };\n    identity.ticks = function(m) {\n      return d3_scale_linearTicks(domain, m);\n    };\n    identity.tickFormat = function(m, format) {\n      return d3_scale_linearTickFormat(domain, m, format);\n    };\n    identity.copy = function() {\n      return d3_scale_identity(domain);\n    };\n    return identity;\n  }\n  d3.svg.arc = function() {\n    var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;\n    function arc() {\n      var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0,\n      a0 = a1, a1 = da), a1 - a0), df = da < π ? \"0\" : \"1\", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1);\n      return da >= d3_svg_arcMax ? r0 ? \"M0,\" + r1 + \"A\" + r1 + \",\" + r1 + \" 0 1,1 0,\" + -r1 + \"A\" + r1 + \",\" + r1 + \" 0 1,1 0,\" + r1 + \"M0,\" + r0 + \"A\" + r0 + \",\" + r0 + \" 0 1,0 0,\" + -r0 + \"A\" + r0 + \",\" + r0 + \" 0 1,0 0,\" + r0 + \"Z\" : \"M0,\" + r1 + \"A\" + r1 + \",\" + r1 + \" 0 1,1 0,\" + -r1 + \"A\" + r1 + \",\" + r1 + \" 0 1,1 0,\" + r1 + \"Z\" : r0 ? \"M\" + r1 * c0 + \",\" + r1 * s0 + \"A\" + r1 + \",\" + r1 + \" 0 \" + df + \",1 \" + r1 * c1 + \",\" + r1 * s1 + \"L\" + r0 * c1 + \",\" + r0 * s1 + \"A\" + r0 + \",\" + r0 + \" 0 \" + df + \",0 \" + r0 * c0 + \",\" + r0 * s0 + \"Z\" : \"M\" + r1 * c0 + \",\" + r1 * s0 + \"A\" + r1 + \",\" + r1 + \" 0 \" + df + \",1 \" + r1 * c1 + \",\" + r1 * s1 + \"L0,0\" + \"Z\";\n    }\n    arc.innerRadius = function(v) {\n      if (!arguments.length) return innerRadius;\n      innerRadius = d3_functor(v);\n      return arc;\n    };\n    arc.outerRadius = function(v) {\n      if (!arguments.length) return outerRadius;\n      outerRadius = d3_functor(v);\n      return arc;\n    };\n    arc.startAngle = function(v) {\n      if (!arguments.length) return startAngle;\n      startAngle = d3_functor(v);\n      return arc;\n    };\n    arc.endAngle = function(v) {\n      if (!arguments.length) return endAngle;\n      endAngle = d3_functor(v);\n      return arc;\n    };\n    arc.centroid = function() {\n      var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;\n      return [ Math.cos(a) * r, Math.sin(a) * r ];\n    };\n    return arc;\n  };\n  var d3_svg_arcOffset = -π / 2, d3_svg_arcMax = 2 * π - 1e-6;\n  function d3_svg_arcInnerRadius(d) {\n    return d.innerRadius;\n  }\n  function d3_svg_arcOuterRadius(d) {\n    return d.outerRadius;\n  }\n  function d3_svg_arcStartAngle(d) {\n    return d.startAngle;\n  }\n  function d3_svg_arcEndAngle(d) {\n    return d.endAngle;\n  }\n  d3.svg.line.radial = function() {\n    var line = d3_svg_line(d3_svg_lineRadial);\n    line.radius = line.x, delete line.x;\n    line.angle = line.y, delete line.y;\n    return line;\n  };\n  function d3_svg_lineRadial(points) {\n    var point, i = -1, n = points.length, r, a;\n    while (++i < n) {\n      point = points[i];\n      r = point[0];\n      a = point[1] + d3_svg_arcOffset;\n      point[0] = r * Math.cos(a);\n      point[1] = r * Math.sin(a);\n    }\n    return points;\n  }\n  function d3_svg_area(projection) {\n    var x0 = d3_svg_lineX, x1 = d3_svg_lineX, y0 = 0, y1 = d3_svg_lineY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = \"L\", tension = .7;\n    function area(data) {\n      var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {\n        return x;\n      } : d3_functor(x1), fy1 = y0 === y1 ? function() {\n        return y;\n      } : d3_functor(y1), x, y;\n      function segment() {\n        segments.push(\"M\", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), \"Z\");\n      }\n      while (++i < n) {\n        if (defined.call(this, d = data[i], i)) {\n          points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);\n          points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);\n        } else if (points0.length) {\n          segment();\n          points0 = [];\n          points1 = [];\n        }\n      }\n      if (points0.length) segment();\n      return segments.length ? segments.join(\"\") : null;\n    }\n    area.x = function(_) {\n      if (!arguments.length) return x1;\n      x0 = x1 = _;\n      return area;\n    };\n    area.x0 = function(_) {\n      if (!arguments.length) return x0;\n      x0 = _;\n      return area;\n    };\n    area.x1 = function(_) {\n      if (!arguments.length) return x1;\n      x1 = _;\n      return area;\n    };\n    area.y = function(_) {\n      if (!arguments.length) return y1;\n      y0 = y1 = _;\n      return area;\n    };\n    area.y0 = function(_) {\n      if (!arguments.length) return y0;\n      y0 = _;\n      return area;\n    };\n    area.y1 = function(_) {\n      if (!arguments.length) return y1;\n      y1 = _;\n      return area;\n    };\n    area.defined = function(_) {\n      if (!arguments.length) return defined;\n      defined = _;\n      return area;\n    };\n    area.interpolate = function(_) {\n      if (!arguments.length) return interpolateKey;\n      if (typeof _ === \"function\") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;\n      interpolateReverse = interpolate.reverse || interpolate;\n      L = interpolate.closed ? \"M\" : \"L\";\n      return area;\n    };\n    area.tension = function(_) {\n      if (!arguments.length) return tension;\n      tension = _;\n      return area;\n    };\n    return area;\n  }\n  d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;\n  d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;\n  d3.svg.area = function() {\n    return d3_svg_area(d3_identity);\n  };\n  d3.svg.area.radial = function() {\n    var area = d3_svg_area(d3_svg_lineRadial);\n    area.radius = area.x, delete area.x;\n    area.innerRadius = area.x0, delete area.x0;\n    area.outerRadius = area.x1, delete area.x1;\n    area.angle = area.y, delete area.y;\n    area.startAngle = area.y0, delete area.y0;\n    area.endAngle = area.y1, delete area.y1;\n    return area;\n  };\n  d3.svg.chord = function() {\n    var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;\n    function chord(d, i) {\n      var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);\n      return \"M\" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + \"Z\";\n    }\n    function subgroup(self, f, d, i) {\n      var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;\n      return {\n        r: r,\n        a0: a0,\n        a1: a1,\n        p0: [ r * Math.cos(a0), r * Math.sin(a0) ],\n        p1: [ r * Math.cos(a1), r * Math.sin(a1) ]\n      };\n    }\n    function equals(a, b) {\n      return a.a0 == b.a0 && a.a1 == b.a1;\n    }\n    function arc(r, p, a) {\n      return \"A\" + r + \",\" + r + \" 0 \" + +(a > π) + \",1 \" + p;\n    }\n    function curve(r0, p0, r1, p1) {\n      return \"Q 0,0 \" + p1;\n    }\n    chord.radius = function(v) {\n      if (!arguments.length) return radius;\n      radius = d3_functor(v);\n      return chord;\n    };\n    chord.source = function(v) {\n      if (!arguments.length) return source;\n      source = d3_functor(v);\n      return chord;\n    };\n    chord.target = function(v) {\n      if (!arguments.length) return target;\n      target = d3_functor(v);\n      return chord;\n    };\n    chord.startAngle = function(v) {\n      if (!arguments.length) return startAngle;\n      startAngle = d3_functor(v);\n      return chord;\n    };\n    chord.endAngle = function(v) {\n      if (!arguments.length) return endAngle;\n      endAngle = d3_functor(v);\n      return chord;\n    };\n    return chord;\n  };\n  function d3_svg_chordRadius(d) {\n    return d.radius;\n  }\n  d3.svg.diagonal = function() {\n    var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection;\n    function diagonal(d, i) {\n      var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {\n        x: p0.x,\n        y: m\n      }, {\n        x: p3.x,\n        y: m\n      }, p3 ];\n      p = p.map(projection);\n      return \"M\" + p[0] + \"C\" + p[1] + \" \" + p[2] + \" \" + p[3];\n    }\n    diagonal.source = function(x) {\n      if (!arguments.length) return source;\n      source = d3_functor(x);\n      return diagonal;\n    };\n    diagonal.target = function(x) {\n      if (!arguments.length) return target;\n      target = d3_functor(x);\n      return diagonal;\n    };\n    diagonal.projection = function(x) {\n      if (!arguments.length) return projection;\n      projection = x;\n      return diagonal;\n    };\n    return diagonal;\n  };\n  function d3_svg_diagonalProjection(d) {\n    return [ d.x, d.y ];\n  }\n  d3.svg.diagonal.radial = function() {\n    var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;\n    diagonal.projection = function(x) {\n      return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;\n    };\n    return diagonal;\n  };\n  function d3_svg_diagonalRadialProjection(projection) {\n    return function() {\n      var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset;\n      return [ r * Math.cos(a), r * Math.sin(a) ];\n    };\n  }\n  d3.svg.symbol = function() {\n    var type = d3_svg_symbolType, size = d3_svg_symbolSize;\n    function symbol(d, i) {\n      return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));\n    }\n    symbol.type = function(x) {\n      if (!arguments.length) return type;\n      type = d3_functor(x);\n      return symbol;\n    };\n    symbol.size = function(x) {\n      if (!arguments.length) return size;\n      size = d3_functor(x);\n      return symbol;\n    };\n    return symbol;\n  };\n  function d3_svg_symbolSize() {\n    return 64;\n  }\n  function d3_svg_symbolType() {\n    return \"circle\";\n  }\n  function d3_svg_symbolCircle(size) {\n    var r = Math.sqrt(size / π);\n    return \"M0,\" + r + \"A\" + r + \",\" + r + \" 0 1,1 0,\" + -r + \"A\" + r + \",\" + r + \" 0 1,1 0,\" + r + \"Z\";\n  }\n  var d3_svg_symbols = d3.map({\n    circle: d3_svg_symbolCircle,\n    cross: function(size) {\n      var r = Math.sqrt(size / 5) / 2;\n      return \"M\" + -3 * r + \",\" + -r + \"H\" + -r + \"V\" + -3 * r + \"H\" + r + \"V\" + -r + \"H\" + 3 * r + \"V\" + r + \"H\" + r + \"V\" + 3 * r + \"H\" + -r + \"V\" + r + \"H\" + -3 * r + \"Z\";\n    },\n    diamond: function(size) {\n      var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;\n      return \"M0,\" + -ry + \"L\" + rx + \",0\" + \" 0,\" + ry + \" \" + -rx + \",0\" + \"Z\";\n    },\n    square: function(size) {\n      var r = Math.sqrt(size) / 2;\n      return \"M\" + -r + \",\" + -r + \"L\" + r + \",\" + -r + \" \" + r + \",\" + r + \" \" + -r + \",\" + r + \"Z\";\n    },\n    \"triangle-down\": function(size) {\n      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;\n      return \"M0,\" + ry + \"L\" + rx + \",\" + -ry + \" \" + -rx + \",\" + -ry + \"Z\";\n    },\n    \"triangle-up\": function(size) {\n      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;\n      return \"M0,\" + -ry + \"L\" + rx + \",\" + ry + \" \" + -rx + \",\" + ry + \"Z\";\n    }\n  });\n  d3.svg.symbolTypes = d3_svg_symbols.keys();\n  var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);\n  function d3_transition(groups, id) {\n    d3_arraySubclass(groups, d3_transitionPrototype);\n    groups.id = id;\n    return groups;\n  }\n  var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit = {\n    ease: d3_ease_cubicInOut,\n    delay: 0,\n    duration: 250\n  };\n  d3_transitionPrototype.call = d3_selectionPrototype.call;\n  d3_transitionPrototype.empty = d3_selectionPrototype.empty;\n  d3_transitionPrototype.node = d3_selectionPrototype.node;\n  d3.transition = function(selection) {\n    return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition();\n  };\n  d3.transition.prototype = d3_transitionPrototype;\n  d3_transitionPrototype.select = function(selector) {\n    var id = this.id, subgroups = [], subgroup, subnode, node;\n    if (typeof selector !== \"function\") selector = d3_selection_selector(selector);\n    for (var j = -1, m = this.length; ++j < m; ) {\n      subgroups.push(subgroup = []);\n      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {\n        if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i))) {\n          if (\"__data__\" in node) subnode.__data__ = node.__data__;\n          d3_transitionNode(subnode, i, id, node.__transition__[id]);\n          subgroup.push(subnode);\n        } else {\n          subgroup.push(null);\n        }\n      }\n    }\n    return d3_transition(subgroups, id);\n  };\n  d3_transitionPrototype.selectAll = function(selector) {\n    var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition;\n    if (typeof selector !== \"function\") selector = d3_selection_selectorAll(selector);\n    for (var j = -1, m = this.length; ++j < m; ) {\n      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) {\n          transition = node.__transition__[id];\n          subnodes = selector.call(node, node.__data__, i);\n          subgroups.push(subgroup = []);\n          for (var k = -1, o = subnodes.length; ++k < o; ) {\n            d3_transitionNode(subnode = subnodes[k], k, id, transition);\n            subgroup.push(subnode);\n          }\n        }\n      }\n    }\n    return d3_transition(subgroups, id);\n  };\n  d3_transitionPrototype.filter = function(filter) {\n    var subgroups = [], subgroup, group, node;\n    if (typeof filter !== \"function\") filter = d3_selection_filter(filter);\n    for (var j = 0, m = this.length; j < m; j++) {\n      subgroups.push(subgroup = []);\n      for (var group = this[j], i = 0, n = group.length; i < n; i++) {\n        if ((node = group[i]) && filter.call(node, node.__data__, i)) {\n          subgroup.push(node);\n        }\n      }\n    }\n    return d3_transition(subgroups, this.id, this.time).ease(this.ease());\n  };\n  d3_transitionPrototype.tween = function(name, tween) {\n    var id = this.id;\n    if (arguments.length < 2) return this.node().__transition__[id].tween.get(name);\n    return d3_selection_each(this, tween == null ? function(node) {\n      node.__transition__[id].tween.remove(name);\n    } : function(node) {\n      node.__transition__[id].tween.set(name, tween);\n    });\n  };\n  function d3_transition_tween(groups, name, value, tween) {\n    var id = groups.id;\n    return d3_selection_each(groups, typeof value === \"function\" ? function(node, i, j) {\n      node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j)));\n    } : (value = tween(value), function(node) {\n      node.__transition__[id].tween.set(name, value);\n    }));\n  }\n  d3_transitionPrototype.attr = function(nameNS, value) {\n    if (arguments.length < 2) {\n      for (value in nameNS) this.attr(value, nameNS[value]);\n      return this;\n    }\n    var interpolate = d3_interpolateByName(nameNS), name = d3.ns.qualify(nameNS);\n    function attrNull() {\n      this.removeAttribute(name);\n    }\n    function attrNullNS() {\n      this.removeAttributeNS(name.space, name.local);\n    }\n    return d3_transition_tween(this, \"attr.\" + nameNS, value, function(b) {\n      function attrString() {\n        var a = this.getAttribute(name), i;\n        return a !== b && (i = interpolate(a, b), function(t) {\n          this.setAttribute(name, i(t));\n        });\n      }\n      function attrStringNS() {\n        var a = this.getAttributeNS(name.space, name.local), i;\n        return a !== b && (i = interpolate(a, b), function(t) {\n          this.setAttributeNS(name.space, name.local, i(t));\n        });\n      }\n      return b == null ? name.local ? attrNullNS : attrNull : (b += \"\", name.local ? attrStringNS : attrString);\n    });\n  };\n  d3_transitionPrototype.attrTween = function(nameNS, tween) {\n    var name = d3.ns.qualify(nameNS);\n    function attrTween(d, i) {\n      var f = tween.call(this, d, i, this.getAttribute(name));\n      return f && function(t) {\n        this.setAttribute(name, f(t));\n      };\n    }\n    function attrTweenNS(d, i) {\n      var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));\n      return f && function(t) {\n        this.setAttributeNS(name.space, name.local, f(t));\n      };\n    }\n    return this.tween(\"attr.\" + nameNS, name.local ? attrTweenNS : attrTween);\n  };\n  d3_transitionPrototype.style = function(name, value, priority) {\n    var n = arguments.length;\n    if (n < 3) {\n      if (typeof name !== \"string\") {\n        if (n < 2) value = \"\";\n        for (priority in name) this.style(priority, name[priority], value);\n        return this;\n      }\n      priority = \"\";\n    }\n    var interpolate = d3_interpolateByName(name);\n    function styleNull() {\n      this.style.removeProperty(name);\n    }\n    return d3_transition_tween(this, \"style.\" + name, value, function(b) {\n      function styleString() {\n        var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i;\n        return a !== b && (i = interpolate(a, b), function(t) {\n          this.style.setProperty(name, i(t), priority);\n        });\n      }\n      return b == null ? styleNull : (b += \"\", styleString);\n    });\n  };\n  d3_transitionPrototype.styleTween = function(name, tween, priority) {\n    if (arguments.length < 3) priority = \"\";\n    return this.tween(\"style.\" + name, function(d, i) {\n      var f = tween.call(this, d, i, d3_window.getComputedStyle(this, null).getPropertyValue(name));\n      return f && function(t) {\n        this.style.setProperty(name, f(t), priority);\n      };\n    });\n  };\n  d3_transitionPrototype.text = function(value) {\n    return d3_transition_tween(this, \"text\", value, d3_transition_text);\n  };\n  function d3_transition_text(b) {\n    if (b == null) b = \"\";\n    return function() {\n      this.textContent = b;\n    };\n  }\n  d3_transitionPrototype.remove = function() {\n    return this.each(\"end.transition\", function() {\n      var p;\n      if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this);\n    });\n  };\n  d3_transitionPrototype.ease = function(value) {\n    var id = this.id;\n    if (arguments.length < 1) return this.node().__transition__[id].ease;\n    if (typeof value !== \"function\") value = d3.ease.apply(d3, arguments);\n    return d3_selection_each(this, function(node) {\n      node.__transition__[id].ease = value;\n    });\n  };\n  d3_transitionPrototype.delay = function(value) {\n    var id = this.id;\n    return d3_selection_each(this, typeof value === \"function\" ? function(node, i, j) {\n      node.__transition__[id].delay = value.call(node, node.__data__, i, j) | 0;\n    } : (value |= 0, function(node) {\n      node.__transition__[id].delay = value;\n    }));\n  };\n  d3_transitionPrototype.duration = function(value) {\n    var id = this.id;\n    return d3_selection_each(this, typeof value === \"function\" ? function(node, i, j) {\n      node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j) | 0);\n    } : (value = Math.max(1, value | 0), function(node) {\n      node.__transition__[id].duration = value;\n    }));\n  };\n  d3_transitionPrototype.each = function(type, listener) {\n    var id = this.id;\n    if (arguments.length < 2) {\n      var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;\n      d3_transitionInheritId = id;\n      d3_selection_each(this, function(node, i, j) {\n        d3_transitionInherit = node.__transition__[id];\n        type.call(node, node.__data__, i, j);\n      });\n      d3_transitionInherit = inherit;\n      d3_transitionInheritId = inheritId;\n    } else {\n      d3_selection_each(this, function(node) {\n        node.__transition__[id].event.on(type, listener);\n      });\n    }\n    return this;\n  };\n  d3_transitionPrototype.transition = function() {\n    var id0 = this.id, id1 = ++d3_transitionId, subgroups = [], subgroup, group, node, transition;\n    for (var j = 0, m = this.length; j < m; j++) {\n      subgroups.push(subgroup = []);\n      for (var group = this[j], i = 0, n = group.length; i < n; i++) {\n        if (node = group[i]) {\n          transition = Object.create(node.__transition__[id0]);\n          transition.delay += transition.duration;\n          d3_transitionNode(node, i, id1, transition);\n        }\n        subgroup.push(node);\n      }\n    }\n    return d3_transition(subgroups, id1);\n  };\n  function d3_transitionNode(node, i, id, inherit) {\n    var lock = node.__transition__ || (node.__transition__ = {\n      active: 0,\n      count: 0\n    }), transition = lock[id];\n    if (!transition) {\n      var time = inherit.time;\n      transition = lock[id] = {\n        tween: new d3_Map(),\n        event: d3.dispatch(\"start\", \"end\"),\n        time: time,\n        ease: inherit.ease,\n        delay: inherit.delay,\n        duration: inherit.duration\n      };\n      ++lock.count;\n      d3.timer(function(elapsed) {\n        var d = node.__data__, ease = transition.ease, event = transition.event, delay = transition.delay, duration = transition.duration, tweened = [];\n        return delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time), 1;\n        function start(elapsed) {\n          if (lock.active > id) return stop();\n          lock.active = id;\n          event.start.call(node, d, i);\n          transition.tween.forEach(function(key, value) {\n            if (value = value.call(node, d, i)) {\n              tweened.push(value);\n            }\n          });\n          if (!tick(elapsed)) d3.timer(tick, 0, time);\n          return 1;\n        }\n        function tick(elapsed) {\n          if (lock.active !== id) return stop();\n          var t = (elapsed - delay) / duration, e = ease(t), n = tweened.length;\n          while (n > 0) {\n            tweened[--n].call(node, e);\n          }\n          if (t >= 1) {\n            stop();\n            event.end.call(node, d, i);\n            return 1;\n          }\n        }\n        function stop() {\n          if (--lock.count) delete lock[id]; else delete node.__transition__;\n          return 1;\n        }\n      }, 0, time);\n      return transition;\n    }\n  }\n  d3.svg.axis = function() {\n    var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, tickMajorSize = 6, tickMinorSize = 6, tickEndSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_, tickSubdivide = 0;\n    function axis(g) {\n      g.each(function() {\n        var g = d3.select(this);\n        var ticks = tickValues == null ? scale.ticks ? scale.ticks.apply(scale, tickArguments_) : scale.domain() : tickValues, tickFormat = tickFormat_ == null ? scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments_) : String : tickFormat_;\n        var subticks = d3_svg_axisSubdivide(scale, ticks, tickSubdivide), subtick = g.selectAll(\".tick.minor\").data(subticks, String), subtickEnter = subtick.enter().insert(\"line\", \".tick\").attr(\"class\", \"tick minor\").style(\"opacity\", 1e-6), subtickExit = d3.transition(subtick.exit()).style(\"opacity\", 1e-6).remove(), subtickUpdate = d3.transition(subtick).style(\"opacity\", 1);\n        var tick = g.selectAll(\".tick.major\").data(ticks, String), tickEnter = tick.enter().insert(\"g\", \"path\").attr(\"class\", \"tick major\").style(\"opacity\", 1e-6), tickExit = d3.transition(tick.exit()).style(\"opacity\", 1e-6).remove(), tickUpdate = d3.transition(tick).style(\"opacity\", 1), tickTransform;\n        var range = d3_scaleRange(scale), path = g.selectAll(\".domain\").data([ 0 ]), pathUpdate = (path.enter().append(\"path\").attr(\"class\", \"domain\"),\n        d3.transition(path));\n        var scale1 = scale.copy(), scale0 = this.__chart__ || scale1;\n        this.__chart__ = scale1;\n        tickEnter.append(\"line\");\n        tickEnter.append(\"text\");\n        var lineEnter = tickEnter.select(\"line\"), lineUpdate = tickUpdate.select(\"line\"), text = tick.select(\"text\").text(tickFormat), textEnter = tickEnter.select(\"text\"), textUpdate = tickUpdate.select(\"text\");\n        switch (orient) {\n         case \"bottom\":\n          {\n            tickTransform = d3_svg_axisX;\n            subtickEnter.attr(\"y2\", tickMinorSize);\n            subtickUpdate.attr(\"x2\", 0).attr(\"y2\", tickMinorSize);\n            lineEnter.attr(\"y2\", tickMajorSize);\n            textEnter.attr(\"y\", Math.max(tickMajorSize, 0) + tickPadding);\n            lineUpdate.attr(\"x2\", 0).attr(\"y2\", tickMajorSize);\n            textUpdate.attr(\"x\", 0).attr(\"y\", Math.max(tickMajorSize, 0) + tickPadding);\n            text.attr(\"dy\", \".71em\").style(\"text-anchor\", \"middle\");\n            pathUpdate.attr(\"d\", \"M\" + range[0] + \",\" + tickEndSize + \"V0H\" + range[1] + \"V\" + tickEndSize);\n            break;\n          }\n\n         case \"top\":\n          {\n            tickTransform = d3_svg_axisX;\n            subtickEnter.attr(\"y2\", -tickMinorSize);\n            subtickUpdate.attr(\"x2\", 0).attr(\"y2\", -tickMinorSize);\n            lineEnter.attr(\"y2\", -tickMajorSize);\n            textEnter.attr(\"y\", -(Math.max(tickMajorSize, 0) + tickPadding));\n            lineUpdate.attr(\"x2\", 0).attr(\"y2\", -tickMajorSize);\n            textUpdate.attr(\"x\", 0).attr(\"y\", -(Math.max(tickMajorSize, 0) + tickPadding));\n            text.attr(\"dy\", \"0em\").style(\"text-anchor\", \"middle\");\n            pathUpdate.attr(\"d\", \"M\" + range[0] + \",\" + -tickEndSize + \"V0H\" + range[1] + \"V\" + -tickEndSize);\n            break;\n          }\n\n         case \"left\":\n          {\n            tickTransform = d3_svg_axisY;\n            subtickEnter.attr(\"x2\", -tickMinorSize);\n            subtickUpdate.attr(\"x2\", -tickMinorSize).attr(\"y2\", 0);\n            lineEnter.attr(\"x2\", -tickMajorSize);\n            textEnter.attr(\"x\", -(Math.max(tickMajorSize, 0) + tickPadding));\n            lineUpdate.attr(\"x2\", -tickMajorSize).attr(\"y2\", 0);\n            textUpdate.attr(\"x\", -(Math.max(tickMajorSize, 0) + tickPadding)).attr(\"y\", 0);\n            text.attr(\"dy\", \".32em\").style(\"text-anchor\", \"end\");\n            pathUpdate.attr(\"d\", \"M\" + -tickEndSize + \",\" + range[0] + \"H0V\" + range[1] + \"H\" + -tickEndSize);\n            break;\n          }\n\n         case \"right\":\n          {\n            tickTransform = d3_svg_axisY;\n            subtickEnter.attr(\"x2\", tickMinorSize);\n            subtickUpdate.attr(\"x2\", tickMinorSize).attr(\"y2\", 0);\n            lineEnter.attr(\"x2\", tickMajorSize);\n            textEnter.attr(\"x\", Math.max(tickMajorSize, 0) + tickPadding);\n            lineUpdate.attr(\"x2\", tickMajorSize).attr(\"y2\", 0);\n            textUpdate.attr(\"x\", Math.max(tickMajorSize, 0) + tickPadding).attr(\"y\", 0);\n            text.attr(\"dy\", \".32em\").style(\"text-anchor\", \"start\");\n            pathUpdate.attr(\"d\", \"M\" + tickEndSize + \",\" + range[0] + \"H0V\" + range[1] + \"H\" + tickEndSize);\n            break;\n          }\n        }\n        if (scale.ticks) {\n          tickEnter.call(tickTransform, scale0);\n          tickUpdate.call(tickTransform, scale1);\n          tickExit.call(tickTransform, scale1);\n          subtickEnter.call(tickTransform, scale0);\n          subtickUpdate.call(tickTransform, scale1);\n          subtickExit.call(tickTransform, scale1);\n        } else {\n          var dx = scale1.rangeBand() / 2, x = function(d) {\n            return scale1(d) + dx;\n          };\n          tickEnter.call(tickTransform, x);\n          tickUpdate.call(tickTransform, x);\n        }\n      });\n    }\n    axis.scale = function(x) {\n      if (!arguments.length) return scale;\n      scale = x;\n      return axis;\n    };\n    axis.orient = function(x) {\n      if (!arguments.length) return orient;\n      orient = x in d3_svg_axisOrients ? x + \"\" : d3_svg_axisDefaultOrient;\n      return axis;\n    };\n    axis.ticks = function() {\n      if (!arguments.length) return tickArguments_;\n      tickArguments_ = arguments;\n      return axis;\n    };\n    axis.tickValues = function(x) {\n      if (!arguments.length) return tickValues;\n      tickValues = x;\n      return axis;\n    };\n    axis.tickFormat = function(x) {\n      if (!arguments.length) return tickFormat_;\n      tickFormat_ = x;\n      return axis;\n    };\n    axis.tickSize = function(x, y) {\n      if (!arguments.length) return tickMajorSize;\n      var n = arguments.length - 1;\n      tickMajorSize = +x;\n      tickMinorSize = n > 1 ? +y : tickMajorSize;\n      tickEndSize = n > 0 ? +arguments[n] : tickMajorSize;\n      return axis;\n    };\n    axis.tickPadding = function(x) {\n      if (!arguments.length) return tickPadding;\n      tickPadding = +x;\n      return axis;\n    };\n    axis.tickSubdivide = function(x) {\n      if (!arguments.length) return tickSubdivide;\n      tickSubdivide = +x;\n      return axis;\n    };\n    return axis;\n  };\n  var d3_svg_axisDefaultOrient = \"bottom\", d3_svg_axisOrients = {\n    top: 1,\n    right: 1,\n    bottom: 1,\n    left: 1\n  };\n  function d3_svg_axisX(selection, x) {\n    selection.attr(\"transform\", function(d) {\n      return \"translate(\" + x(d) + \",0)\";\n    });\n  }\n  function d3_svg_axisY(selection, y) {\n    selection.attr(\"transform\", function(d) {\n      return \"translate(0,\" + y(d) + \")\";\n    });\n  }\n  function d3_svg_axisSubdivide(scale, ticks, m) {\n    subticks = [];\n    if (m && ticks.length > 1) {\n      var extent = d3_scaleExtent(scale.domain()), subticks, i = -1, n = ticks.length, d = (ticks[1] - ticks[0]) / ++m, j, v;\n      while (++i < n) {\n        for (j = m; --j > 0; ) {\n          if ((v = +ticks[i] - j * d) >= extent[0]) {\n            subticks.push(v);\n          }\n        }\n      }\n      for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1]; ) {\n        subticks.push(v);\n      }\n    }\n    return subticks;\n  }\n  d3.svg.brush = function() {\n    var event = d3_eventDispatch(brush, \"brushstart\", \"brush\", \"brushend\"), x = null, y = null, resizes = d3_svg_brushResizes[0], extent = [ [ 0, 0 ], [ 0, 0 ] ], extentDomain;\n    function brush(g) {\n      g.each(function() {\n        var g = d3.select(this), bg = g.selectAll(\".background\").data([ 0 ]), fg = g.selectAll(\".extent\").data([ 0 ]), tz = g.selectAll(\".resize\").data(resizes, String), e;\n        g.style(\"pointer-events\", \"all\").on(\"mousedown.brush\", brushstart).on(\"touchstart.brush\", brushstart);\n        bg.enter().append(\"rect\").attr(\"class\", \"background\").style(\"visibility\", \"hidden\").style(\"cursor\", \"crosshair\");\n        fg.enter().append(\"rect\").attr(\"class\", \"extent\").style(\"cursor\", \"move\");\n        tz.enter().append(\"g\").attr(\"class\", function(d) {\n          return \"resize \" + d;\n        }).style(\"cursor\", function(d) {\n          return d3_svg_brushCursor[d];\n        }).append(\"rect\").attr(\"x\", function(d) {\n          return /[ew]$/.test(d) ? -3 : null;\n        }).attr(\"y\", function(d) {\n          return /^[ns]/.test(d) ? -3 : null;\n        }).attr(\"width\", 6).attr(\"height\", 6).style(\"visibility\", \"hidden\");\n        tz.style(\"display\", brush.empty() ? \"none\" : null);\n        tz.exit().remove();\n        if (x) {\n          e = d3_scaleRange(x);\n          bg.attr(\"x\", e[0]).attr(\"width\", e[1] - e[0]);\n          redrawX(g);\n        }\n        if (y) {\n          e = d3_scaleRange(y);\n          bg.attr(\"y\", e[0]).attr(\"height\", e[1] - e[0]);\n          redrawY(g);\n        }\n        redraw(g);\n      });\n    }\n    function redraw(g) {\n      g.selectAll(\".resize\").attr(\"transform\", function(d) {\n        return \"translate(\" + extent[+/e$/.test(d)][0] + \",\" + extent[+/^s/.test(d)][1] + \")\";\n      });\n    }\n    function redrawX(g) {\n      g.select(\".extent\").attr(\"x\", extent[0][0]);\n      g.selectAll(\".extent,.n>rect,.s>rect\").attr(\"width\", extent[1][0] - extent[0][0]);\n    }\n    function redrawY(g) {\n      g.select(\".extent\").attr(\"y\", extent[0][1]);\n      g.selectAll(\".extent,.e>rect,.w>rect\").attr(\"height\", extent[1][1] - extent[0][1]);\n    }\n    function brushstart() {\n      var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed(\"extent\"), center, origin = mouse(), offset;\n      var w = d3.select(d3_window).on(\"mousemove.brush\", brushmove).on(\"mouseup.brush\", brushend).on(\"touchmove.brush\", brushmove).on(\"touchend.brush\", brushend).on(\"keydown.brush\", keydown).on(\"keyup.brush\", keyup);\n      if (dragging) {\n        origin[0] = extent[0][0] - origin[0];\n        origin[1] = extent[0][1] - origin[1];\n      } else if (resizing) {\n        var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);\n        offset = [ extent[1 - ex][0] - origin[0], extent[1 - ey][1] - origin[1] ];\n        origin[0] = extent[ex][0];\n        origin[1] = extent[ey][1];\n      } else if (d3.event.altKey) center = origin.slice();\n      g.style(\"pointer-events\", \"none\").selectAll(\".resize\").style(\"display\", null);\n      d3.select(\"body\").style(\"cursor\", eventTarget.style(\"cursor\"));\n      event_({\n        type: \"brushstart\"\n      });\n      brushmove();\n      d3_eventCancel();\n      function mouse() {\n        var touches = d3.event.changedTouches;\n        return touches ? d3.touches(target, touches)[0] : d3.mouse(target);\n      }\n      function keydown() {\n        if (d3.event.keyCode == 32) {\n          if (!dragging) {\n            center = null;\n            origin[0] -= extent[1][0];\n            origin[1] -= extent[1][1];\n            dragging = 2;\n          }\n          d3_eventCancel();\n        }\n      }\n      function keyup() {\n        if (d3.event.keyCode == 32 && dragging == 2) {\n          origin[0] += extent[1][0];\n          origin[1] += extent[1][1];\n          dragging = 0;\n          d3_eventCancel();\n        }\n      }\n      function brushmove() {\n        var point = mouse(), moved = false;\n        if (offset) {\n          point[0] += offset[0];\n          point[1] += offset[1];\n        }\n        if (!dragging) {\n          if (d3.event.altKey) {\n            if (!center) center = [ (extent[0][0] + extent[1][0]) / 2, (extent[0][1] + extent[1][1]) / 2 ];\n            origin[0] = extent[+(point[0] < center[0])][0];\n            origin[1] = extent[+(point[1] < center[1])][1];\n          } else center = null;\n        }\n        if (resizingX && move1(point, x, 0)) {\n          redrawX(g);\n          moved = true;\n        }\n        if (resizingY && move1(point, y, 1)) {\n          redrawY(g);\n          moved = true;\n        }\n        if (moved) {\n          redraw(g);\n          event_({\n            type: \"brush\",\n            mode: dragging ? \"move\" : \"resize\"\n          });\n        }\n      }\n      function move1(point, scale, i) {\n        var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], size = extent[1][i] - extent[0][i], min, max;\n        if (dragging) {\n          r0 -= position;\n          r1 -= size + position;\n        }\n        min = Math.max(r0, Math.min(r1, point[i]));\n        if (dragging) {\n          max = (min += position) + size;\n        } else {\n          if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));\n          if (position < min) {\n            max = min;\n            min = position;\n          } else {\n            max = position;\n          }\n        }\n        if (extent[0][i] !== min || extent[1][i] !== max) {\n          extentDomain = null;\n          extent[0][i] = min;\n          extent[1][i] = max;\n          return true;\n        }\n      }\n      function brushend() {\n        brushmove();\n        g.style(\"pointer-events\", \"all\").selectAll(\".resize\").style(\"display\", brush.empty() ? \"none\" : null);\n        d3.select(\"body\").style(\"cursor\", null);\n        w.on(\"mousemove.brush\", null).on(\"mouseup.brush\", null).on(\"touchmove.brush\", null).on(\"touchend.brush\", null).on(\"keydown.brush\", null).on(\"keyup.brush\", null);\n        event_({\n          type: \"brushend\"\n        });\n        d3_eventCancel();\n      }\n    }\n    brush.x = function(z) {\n      if (!arguments.length) return x;\n      x = z;\n      resizes = d3_svg_brushResizes[!x << 1 | !y];\n      return brush;\n    };\n    brush.y = function(z) {\n      if (!arguments.length) return y;\n      y = z;\n      resizes = d3_svg_brushResizes[!x << 1 | !y];\n      return brush;\n    };\n    brush.extent = function(z) {\n      var x0, x1, y0, y1, t;\n      if (!arguments.length) {\n        z = extentDomain || extent;\n        if (x) {\n          x0 = z[0][0], x1 = z[1][0];\n          if (!extentDomain) {\n            x0 = extent[0][0], x1 = extent[1][0];\n            if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);\n            if (x1 < x0) t = x0, x0 = x1, x1 = t;\n          }\n        }\n        if (y) {\n          y0 = z[0][1], y1 = z[1][1];\n          if (!extentDomain) {\n            y0 = extent[0][1], y1 = extent[1][1];\n            if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);\n            if (y1 < y0) t = y0, y0 = y1, y1 = t;\n          }\n        }\n        return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];\n      }\n      extentDomain = [ [ 0, 0 ], [ 0, 0 ] ];\n      if (x) {\n        x0 = z[0], x1 = z[1];\n        if (y) x0 = x0[0], x1 = x1[0];\n        extentDomain[0][0] = x0, extentDomain[1][0] = x1;\n        if (x.invert) x0 = x(x0), x1 = x(x1);\n        if (x1 < x0) t = x0, x0 = x1, x1 = t;\n        extent[0][0] = x0 | 0, extent[1][0] = x1 | 0;\n      }\n      if (y) {\n        y0 = z[0], y1 = z[1];\n        if (x) y0 = y0[1], y1 = y1[1];\n        extentDomain[0][1] = y0, extentDomain[1][1] = y1;\n        if (y.invert) y0 = y(y0), y1 = y(y1);\n        if (y1 < y0) t = y0, y0 = y1, y1 = t;\n        extent[0][1] = y0 | 0, extent[1][1] = y1 | 0;\n      }\n      return brush;\n    };\n    brush.clear = function() {\n      extentDomain = null;\n      extent[0][0] = extent[0][1] = extent[1][0] = extent[1][1] = 0;\n      return brush;\n    };\n    brush.empty = function() {\n      return x && extent[0][0] === extent[1][0] || y && extent[0][1] === extent[1][1];\n    };\n    return d3.rebind(brush, event, \"on\");\n  };\n  var d3_svg_brushCursor = {\n    n: \"ns-resize\",\n    e: \"ew-resize\",\n    s: \"ns-resize\",\n    w: \"ew-resize\",\n    nw: \"nwse-resize\",\n    ne: \"nesw-resize\",\n    se: \"nwse-resize\",\n    sw: \"nesw-resize\"\n  };\n  var d3_svg_brushResizes = [ [ \"n\", \"e\", \"s\", \"w\", \"nw\", \"ne\", \"se\", \"sw\" ], [ \"e\", \"w\" ], [ \"n\", \"s\" ], [] ];\n  d3.time = {};\n  var d3_time = Date, d3_time_daySymbols = [ \"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\" ];\n  function d3_time_utc() {\n    this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]);\n  }\n  d3_time_utc.prototype = {\n    getDate: function() {\n      return this._.getUTCDate();\n    },\n    getDay: function() {\n      return this._.getUTCDay();\n    },\n    getFullYear: function() {\n      return this._.getUTCFullYear();\n    },\n    getHours: function() {\n      return this._.getUTCHours();\n    },\n    getMilliseconds: function() {\n      return this._.getUTCMilliseconds();\n    },\n    getMinutes: function() {\n      return this._.getUTCMinutes();\n    },\n    getMonth: function() {\n      return this._.getUTCMonth();\n    },\n    getSeconds: function() {\n      return this._.getUTCSeconds();\n    },\n    getTime: function() {\n      return this._.getTime();\n    },\n    getTimezoneOffset: function() {\n      return 0;\n    },\n    valueOf: function() {\n      return this._.valueOf();\n    },\n    setDate: function() {\n      d3_time_prototype.setUTCDate.apply(this._, arguments);\n    },\n    setDay: function() {\n      d3_time_prototype.setUTCDay.apply(this._, arguments);\n    },\n    setFullYear: function() {\n      d3_time_prototype.setUTCFullYear.apply(this._, arguments);\n    },\n    setHours: function() {\n      d3_time_prototype.setUTCHours.apply(this._, arguments);\n    },\n    setMilliseconds: function() {\n      d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);\n    },\n    setMinutes: function() {\n      d3_time_prototype.setUTCMinutes.apply(this._, arguments);\n    },\n    setMonth: function() {\n      d3_time_prototype.setUTCMonth.apply(this._, arguments);\n    },\n    setSeconds: function() {\n      d3_time_prototype.setUTCSeconds.apply(this._, arguments);\n    },\n    setTime: function() {\n      d3_time_prototype.setTime.apply(this._, arguments);\n    }\n  };\n  var d3_time_prototype = Date.prototype;\n  var d3_time_formatDateTime = \"%a %b %e %X %Y\", d3_time_formatDate = \"%m/%d/%Y\", d3_time_formatTime = \"%H:%M:%S\";\n  var d3_time_days = [ \"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\" ], d3_time_dayAbbreviations = [ \"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\" ], d3_time_months = [ \"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\" ], d3_time_monthAbbreviations = [ \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\" ];\n  function d3_time_interval(local, step, number) {\n    function round(date) {\n      var d0 = local(date), d1 = offset(d0, 1);\n      return date - d0 < d1 - date ? d0 : d1;\n    }\n    function ceil(date) {\n      step(date = local(new d3_time(date - 1)), 1);\n      return date;\n    }\n    function offset(date, k) {\n      step(date = new d3_time(+date), k);\n      return date;\n    }\n    function range(t0, t1, dt) {\n      var time = ceil(t0), times = [];\n      if (dt > 1) {\n        while (time < t1) {\n          if (!(number(time) % dt)) times.push(new Date(+time));\n          step(time, 1);\n        }\n      } else {\n        while (time < t1) times.push(new Date(+time)), step(time, 1);\n      }\n      return times;\n    }\n    function range_utc(t0, t1, dt) {\n      try {\n        d3_time = d3_time_utc;\n        var utc = new d3_time_utc();\n        utc._ = t0;\n        return range(utc, t1, dt);\n      } finally {\n        d3_time = Date;\n      }\n    }\n    local.floor = local;\n    local.round = round;\n    local.ceil = ceil;\n    local.offset = offset;\n    local.range = range;\n    var utc = local.utc = d3_time_interval_utc(local);\n    utc.floor = utc;\n    utc.round = d3_time_interval_utc(round);\n    utc.ceil = d3_time_interval_utc(ceil);\n    utc.offset = d3_time_interval_utc(offset);\n    utc.range = range_utc;\n    return local;\n  }\n  function d3_time_interval_utc(method) {\n    return function(date, k) {\n      try {\n        d3_time = d3_time_utc;\n        var utc = new d3_time_utc();\n        utc._ = date;\n        return method(utc, k)._;\n      } finally {\n        d3_time = Date;\n      }\n    };\n  }\n  d3.time.year = d3_time_interval(function(date) {\n    date = d3.time.day(date);\n    date.setMonth(0, 1);\n    return date;\n  }, function(date, offset) {\n    date.setFullYear(date.getFullYear() + offset);\n  }, function(date) {\n    return date.getFullYear();\n  });\n  d3.time.years = d3.time.year.range;\n  d3.time.years.utc = d3.time.year.utc.range;\n  d3.time.day = d3_time_interval(function(date) {\n    var day = new d3_time(1970, 0);\n    day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());\n    return day;\n  }, function(date, offset) {\n    date.setDate(date.getDate() + offset);\n  }, function(date) {\n    return date.getDate() - 1;\n  });\n  d3.time.days = d3.time.day.range;\n  d3.time.days.utc = d3.time.day.utc.range;\n  d3.time.dayOfYear = function(date) {\n    var year = d3.time.year(date);\n    return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);\n  };\n  d3_time_daySymbols.forEach(function(day, i) {\n    day = day.toLowerCase();\n    i = 7 - i;\n    var interval = d3.time[day] = d3_time_interval(function(date) {\n      (date = d3.time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);\n      return date;\n    }, function(date, offset) {\n      date.setDate(date.getDate() + Math.floor(offset) * 7);\n    }, function(date) {\n      var day = d3.time.year(date).getDay();\n      return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);\n    });\n    d3.time[day + \"s\"] = interval.range;\n    d3.time[day + \"s\"].utc = interval.utc.range;\n    d3.time[day + \"OfYear\"] = function(date) {\n      var day = d3.time.year(date).getDay();\n      return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7);\n    };\n  });\n  d3.time.week = d3.time.sunday;\n  d3.time.weeks = d3.time.sunday.range;\n  d3.time.weeks.utc = d3.time.sunday.utc.range;\n  d3.time.weekOfYear = d3.time.sundayOfYear;\n  d3.time.format = function(template) {\n    var n = template.length;\n    function format(date) {\n      var string = [], i = -1, j = 0, c, p, f;\n      while (++i < n) {\n        if (template.charCodeAt(i) === 37) {\n          string.push(template.substring(j, i));\n          if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i);\n          if (f = d3_time_formats[c]) c = f(date, p == null ? c === \"e\" ? \" \" : \"0\" : p);\n          string.push(c);\n          j = i + 1;\n        }\n      }\n      string.push(template.substring(j, i));\n      return string.join(\"\");\n    }\n    format.parse = function(string) {\n      var d = {\n        y: 1900,\n        m: 0,\n        d: 1,\n        H: 0,\n        M: 0,\n        S: 0,\n        L: 0\n      }, i = d3_time_parse(d, template, string, 0);\n      if (i != string.length) return null;\n      if (\"p\" in d) d.H = d.H % 12 + d.p * 12;\n      var date = new d3_time();\n      date.setFullYear(d.y, d.m, d.d);\n      date.setHours(d.H, d.M, d.S, d.L);\n      return date;\n    };\n    format.toString = function() {\n      return template;\n    };\n    return format;\n  };\n  function d3_time_parse(date, template, string, j) {\n    var c, p, i = 0, n = template.length, m = string.length;\n    while (i < n) {\n      if (j >= m) return -1;\n      c = template.charCodeAt(i++);\n      if (c === 37) {\n        p = d3_time_parsers[template.charAt(i++)];\n        if (!p || (j = p(date, string, j)) < 0) return -1;\n      } else if (c != string.charCodeAt(j++)) {\n        return -1;\n      }\n    }\n    return j;\n  }\n  function d3_time_formatRe(names) {\n    return new RegExp(\"^(?:\" + names.map(d3.requote).join(\"|\") + \")\", \"i\");\n  }\n  function d3_time_formatLookup(names) {\n    var map = new d3_Map(), i = -1, n = names.length;\n    while (++i < n) map.set(names[i].toLowerCase(), i);\n    return map;\n  }\n  function d3_time_formatPad(value, fill, width) {\n    value += \"\";\n    var length = value.length;\n    return length < width ? new Array(width - length + 1).join(fill) + value : value;\n  }\n  var d3_time_dayRe = d3_time_formatRe(d3_time_days), d3_time_dayAbbrevRe = d3_time_formatRe(d3_time_dayAbbreviations), d3_time_monthRe = d3_time_formatRe(d3_time_months), d3_time_monthLookup = d3_time_formatLookup(d3_time_months), d3_time_monthAbbrevRe = d3_time_formatRe(d3_time_monthAbbreviations), d3_time_monthAbbrevLookup = d3_time_formatLookup(d3_time_monthAbbreviations);\n  var d3_time_formatPads = {\n    \"-\": \"\",\n    _: \" \",\n    \"0\": \"0\"\n  };\n  var d3_time_formats = {\n    a: function(d) {\n      return d3_time_dayAbbreviations[d.getDay()];\n    },\n    A: function(d) {\n      return d3_time_days[d.getDay()];\n    },\n    b: function(d) {\n      return d3_time_monthAbbreviations[d.getMonth()];\n    },\n    B: function(d) {\n      return d3_time_months[d.getMonth()];\n    },\n    c: d3.time.format(d3_time_formatDateTime),\n    d: function(d, p) {\n      return d3_time_formatPad(d.getDate(), p, 2);\n    },\n    e: function(d, p) {\n      return d3_time_formatPad(d.getDate(), p, 2);\n    },\n    H: function(d, p) {\n      return d3_time_formatPad(d.getHours(), p, 2);\n    },\n    I: function(d, p) {\n      return d3_time_formatPad(d.getHours() % 12 || 12, p, 2);\n    },\n    j: function(d, p) {\n      return d3_time_formatPad(1 + d3.time.dayOfYear(d), p, 3);\n    },\n    L: function(d, p) {\n      return d3_time_formatPad(d.getMilliseconds(), p, 3);\n    },\n    m: function(d, p) {\n      return d3_time_formatPad(d.getMonth() + 1, p, 2);\n    },\n    M: function(d, p) {\n      return d3_time_formatPad(d.getMinutes(), p, 2);\n    },\n    p: function(d) {\n      return d.getHours() >= 12 ? \"PM\" : \"AM\";\n    },\n    S: function(d, p) {\n      return d3_time_formatPad(d.getSeconds(), p, 2);\n    },\n    U: function(d, p) {\n      return d3_time_formatPad(d3.time.sundayOfYear(d), p, 2);\n    },\n    w: function(d) {\n      return d.getDay();\n    },\n    W: function(d, p) {\n      return d3_time_formatPad(d3.time.mondayOfYear(d), p, 2);\n    },\n    x: d3.time.format(d3_time_formatDate),\n    X: d3.time.format(d3_time_formatTime),\n    y: function(d, p) {\n      return d3_time_formatPad(d.getFullYear() % 100, p, 2);\n    },\n    Y: function(d, p) {\n      return d3_time_formatPad(d.getFullYear() % 1e4, p, 4);\n    },\n    Z: d3_time_zone,\n    \"%\": function() {\n      return \"%\";\n    }\n  };\n  var d3_time_parsers = {\n    a: d3_time_parseWeekdayAbbrev,\n    A: d3_time_parseWeekday,\n    b: d3_time_parseMonthAbbrev,\n    B: d3_time_parseMonth,\n    c: d3_time_parseLocaleFull,\n    d: d3_time_parseDay,\n    e: d3_time_parseDay,\n    H: d3_time_parseHour24,\n    I: d3_time_parseHour24,\n    L: d3_time_parseMilliseconds,\n    m: d3_time_parseMonthNumber,\n    M: d3_time_parseMinutes,\n    p: d3_time_parseAmPm,\n    S: d3_time_parseSeconds,\n    x: d3_time_parseLocaleDate,\n    X: d3_time_parseLocaleTime,\n    y: d3_time_parseYear,\n    Y: d3_time_parseFullYear\n  };\n  function d3_time_parseWeekdayAbbrev(date, string, i) {\n    d3_time_dayAbbrevRe.lastIndex = 0;\n    var n = d3_time_dayAbbrevRe.exec(string.substring(i));\n    return n ? i += n[0].length : -1;\n  }\n  function d3_time_parseWeekday(date, string, i) {\n    d3_time_dayRe.lastIndex = 0;\n    var n = d3_time_dayRe.exec(string.substring(i));\n    return n ? i += n[0].length : -1;\n  }\n  function d3_time_parseMonthAbbrev(date, string, i) {\n    d3_time_monthAbbrevRe.lastIndex = 0;\n    var n = d3_time_monthAbbrevRe.exec(string.substring(i));\n    return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i += n[0].length) : -1;\n  }\n  function d3_time_parseMonth(date, string, i) {\n    d3_time_monthRe.lastIndex = 0;\n    var n = d3_time_monthRe.exec(string.substring(i));\n    return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i += n[0].length) : -1;\n  }\n  function d3_time_parseLocaleFull(date, string, i) {\n    return d3_time_parse(date, d3_time_formats.c.toString(), string, i);\n  }\n  function d3_time_parseLocaleDate(date, string, i) {\n    return d3_time_parse(date, d3_time_formats.x.toString(), string, i);\n  }\n  function d3_time_parseLocaleTime(date, string, i) {\n    return d3_time_parse(date, d3_time_formats.X.toString(), string, i);\n  }\n  function d3_time_parseFullYear(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 4));\n    return n ? (date.y = +n[0], i += n[0].length) : -1;\n  }\n  function d3_time_parseYear(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 2));\n    return n ? (date.y = d3_time_expandYear(+n[0]), i += n[0].length) : -1;\n  }\n  function d3_time_expandYear(d) {\n    return d + (d > 68 ? 1900 : 2e3);\n  }\n  function d3_time_parseMonthNumber(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 2));\n    return n ? (date.m = n[0] - 1, i += n[0].length) : -1;\n  }\n  function d3_time_parseDay(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 2));\n    return n ? (date.d = +n[0], i += n[0].length) : -1;\n  }\n  function d3_time_parseHour24(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 2));\n    return n ? (date.H = +n[0], i += n[0].length) : -1;\n  }\n  function d3_time_parseMinutes(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 2));\n    return n ? (date.M = +n[0], i += n[0].length) : -1;\n  }\n  function d3_time_parseSeconds(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 2));\n    return n ? (date.S = +n[0], i += n[0].length) : -1;\n  }\n  function d3_time_parseMilliseconds(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.substring(i, i + 3));\n    return n ? (date.L = +n[0], i += n[0].length) : -1;\n  }\n  var d3_time_numberRe = /^\\s*\\d+/;\n  function d3_time_parseAmPm(date, string, i) {\n    var n = d3_time_amPmLookup.get(string.substring(i, i += 2).toLowerCase());\n    return n == null ? -1 : (date.p = n, i);\n  }\n  var d3_time_amPmLookup = d3.map({\n    am: 0,\n    pm: 1\n  });\n  function d3_time_zone(d) {\n    var z = d.getTimezoneOffset(), zs = z > 0 ? \"-\" : \"+\", zh = ~~(Math.abs(z) / 60), zm = Math.abs(z) % 60;\n    return zs + d3_time_formatPad(zh, \"0\", 2) + d3_time_formatPad(zm, \"0\", 2);\n  }\n  d3.time.format.utc = function(template) {\n    var local = d3.time.format(template);\n    function format(date) {\n      try {\n        d3_time = d3_time_utc;\n        var utc = new d3_time();\n        utc._ = date;\n        return local(utc);\n      } finally {\n        d3_time = Date;\n      }\n    }\n    format.parse = function(string) {\n      try {\n        d3_time = d3_time_utc;\n        var date = local.parse(string);\n        return date && date._;\n      } finally {\n        d3_time = Date;\n      }\n    };\n    format.toString = local.toString;\n    return format;\n  };\n  var d3_time_formatIso = d3.time.format.utc(\"%Y-%m-%dT%H:%M:%S.%LZ\");\n  d3.time.format.iso = Date.prototype.toISOString && +new Date(\"2000-01-01T00:00:00.000Z\") ? d3_time_formatIsoNative : d3_time_formatIso;\n  function d3_time_formatIsoNative(date) {\n    return date.toISOString();\n  }\n  d3_time_formatIsoNative.parse = function(string) {\n    var date = new Date(string);\n    return isNaN(date) ? null : date;\n  };\n  d3_time_formatIsoNative.toString = d3_time_formatIso.toString;\n  d3.time.second = d3_time_interval(function(date) {\n    return new d3_time(Math.floor(date / 1e3) * 1e3);\n  }, function(date, offset) {\n    date.setTime(date.getTime() + Math.floor(offset) * 1e3);\n  }, function(date) {\n    return date.getSeconds();\n  });\n  d3.time.seconds = d3.time.second.range;\n  d3.time.seconds.utc = d3.time.second.utc.range;\n  d3.time.minute = d3_time_interval(function(date) {\n    return new d3_time(Math.floor(date / 6e4) * 6e4);\n  }, function(date, offset) {\n    date.setTime(date.getTime() + Math.floor(offset) * 6e4);\n  }, function(date) {\n    return date.getMinutes();\n  });\n  d3.time.minutes = d3.time.minute.range;\n  d3.time.minutes.utc = d3.time.minute.utc.range;\n  d3.time.hour = d3_time_interval(function(date) {\n    var timezone = date.getTimezoneOffset() / 60;\n    return new d3_time((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);\n  }, function(date, offset) {\n    date.setTime(date.getTime() + Math.floor(offset) * 36e5);\n  }, function(date) {\n    return date.getHours();\n  });\n  d3.time.hours = d3.time.hour.range;\n  d3.time.hours.utc = d3.time.hour.utc.range;\n  d3.time.month = d3_time_interval(function(date) {\n    date = d3.time.day(date);\n    date.setDate(1);\n    return date;\n  }, function(date, offset) {\n    date.setMonth(date.getMonth() + offset);\n  }, function(date) {\n    return date.getMonth();\n  });\n  d3.time.months = d3.time.month.range;\n  d3.time.months.utc = d3.time.month.utc.range;\n  function d3_time_scale(linear, methods, format) {\n    function scale(x) {\n      return linear(x);\n    }\n    scale.invert = function(x) {\n      return d3_time_scaleDate(linear.invert(x));\n    };\n    scale.domain = function(x) {\n      if (!arguments.length) return linear.domain().map(d3_time_scaleDate);\n      linear.domain(x);\n      return scale;\n    };\n    scale.nice = function(m) {\n      return scale.domain(d3_scale_nice(scale.domain(), function() {\n        return m;\n      }));\n    };\n    scale.ticks = function(m, k) {\n      var extent = d3_time_scaleExtent(scale.domain());\n      if (typeof m !== \"function\") {\n        var span = extent[1] - extent[0], target = span / m, i = d3.bisect(d3_time_scaleSteps, target);\n        if (i == d3_time_scaleSteps.length) return methods.year(extent, m);\n        if (!i) return linear.ticks(m).map(d3_time_scaleDate);\n        if (Math.log(target / d3_time_scaleSteps[i - 1]) < Math.log(d3_time_scaleSteps[i] / target)) --i;\n        m = methods[i];\n        k = m[1];\n        m = m[0].range;\n      }\n      return m(extent[0], new Date(+extent[1] + 1), k);\n    };\n    scale.tickFormat = function() {\n      return format;\n    };\n    scale.copy = function() {\n      return d3_time_scale(linear.copy(), methods, format);\n    };\n    return d3.rebind(scale, linear, \"range\", \"rangeRound\", \"interpolate\", \"clamp\");\n  }\n  function d3_time_scaleExtent(domain) {\n    var start = domain[0], stop = domain[domain.length - 1];\n    return start < stop ? [ start, stop ] : [ stop, start ];\n  }\n  function d3_time_scaleDate(t) {\n    return new Date(t);\n  }\n  function d3_time_scaleFormat(formats) {\n    return function(date) {\n      var i = formats.length - 1, f = formats[i];\n      while (!f[1](date)) f = formats[--i];\n      return f[0](date);\n    };\n  }\n  function d3_time_scaleSetYear(y) {\n    var d = new Date(y, 0, 1);\n    d.setFullYear(y);\n    return d;\n  }\n  function d3_time_scaleGetYear(d) {\n    var y = d.getFullYear(), d0 = d3_time_scaleSetYear(y), d1 = d3_time_scaleSetYear(y + 1);\n    return y + (d - d0) / (d1 - d0);\n  }\n  var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ];\n  var d3_time_scaleLocalMethods = [ [ d3.time.second, 1 ], [ d3.time.second, 5 ], [ d3.time.second, 15 ], [ d3.time.second, 30 ], [ d3.time.minute, 1 ], [ d3.time.minute, 5 ], [ d3.time.minute, 15 ], [ d3.time.minute, 30 ], [ d3.time.hour, 1 ], [ d3.time.hour, 3 ], [ d3.time.hour, 6 ], [ d3.time.hour, 12 ], [ d3.time.day, 1 ], [ d3.time.day, 2 ], [ d3.time.week, 1 ], [ d3.time.month, 1 ], [ d3.time.month, 3 ], [ d3.time.year, 1 ] ];\n  var d3_time_scaleLocalFormats = [ [ d3.time.format(\"%Y\"), d3_true ], [ d3.time.format(\"%B\"), function(d) {\n    return d.getMonth();\n  } ], [ d3.time.format(\"%b %d\"), function(d) {\n    return d.getDate() != 1;\n  } ], [ d3.time.format(\"%a %d\"), function(d) {\n    return d.getDay() && d.getDate() != 1;\n  } ], [ d3.time.format(\"%I %p\"), function(d) {\n    return d.getHours();\n  } ], [ d3.time.format(\"%I:%M\"), function(d) {\n    return d.getMinutes();\n  } ], [ d3.time.format(\":%S\"), function(d) {\n    return d.getSeconds();\n  } ], [ d3.time.format(\".%L\"), function(d) {\n    return d.getMilliseconds();\n  } ] ];\n  var d3_time_scaleLinear = d3.scale.linear(), d3_time_scaleLocalFormat = d3_time_scaleFormat(d3_time_scaleLocalFormats);\n  d3_time_scaleLocalMethods.year = function(extent, m) {\n    return d3_time_scaleLinear.domain(extent.map(d3_time_scaleGetYear)).ticks(m).map(d3_time_scaleSetYear);\n  };\n  d3.time.scale = function() {\n    return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);\n  };\n  var d3_time_scaleUTCMethods = d3_time_scaleLocalMethods.map(function(m) {\n    return [ m[0].utc, m[1] ];\n  });\n  var d3_time_scaleUTCFormats = [ [ d3.time.format.utc(\"%Y\"), d3_true ], [ d3.time.format.utc(\"%B\"), function(d) {\n    return d.getUTCMonth();\n  } ], [ d3.time.format.utc(\"%b %d\"), function(d) {\n    return d.getUTCDate() != 1;\n  } ], [ d3.time.format.utc(\"%a %d\"), function(d) {\n    return d.getUTCDay() && d.getUTCDate() != 1;\n  } ], [ d3.time.format.utc(\"%I %p\"), function(d) {\n    return d.getUTCHours();\n  } ], [ d3.time.format.utc(\"%I:%M\"), function(d) {\n    return d.getUTCMinutes();\n  } ], [ d3.time.format.utc(\":%S\"), function(d) {\n    return d.getUTCSeconds();\n  } ], [ d3.time.format.utc(\".%L\"), function(d) {\n    return d.getUTCMilliseconds();\n  } ] ];\n  var d3_time_scaleUTCFormat = d3_time_scaleFormat(d3_time_scaleUTCFormats);\n  function d3_time_scaleUTCSetYear(y) {\n    var d = new Date(Date.UTC(y, 0, 1));\n    d.setUTCFullYear(y);\n    return d;\n  }\n  function d3_time_scaleUTCGetYear(d) {\n    var y = d.getUTCFullYear(), d0 = d3_time_scaleUTCSetYear(y), d1 = d3_time_scaleUTCSetYear(y + 1);\n    return y + (d - d0) / (d1 - d0);\n  }\n  d3_time_scaleUTCMethods.year = function(extent, m) {\n    return d3_time_scaleLinear.domain(extent.map(d3_time_scaleUTCGetYear)).ticks(m).map(d3_time_scaleUTCSetYear);\n  };\n  d3.time.scale.utc = function() {\n    return d3_time_scale(d3.scale.linear(), d3_time_scaleUTCMethods, d3_time_scaleUTCFormat);\n  };\n  d3.text = function() {\n    return d3.xhr.apply(d3, arguments).response(d3_text);\n  };\n  function d3_text(request) {\n    return request.responseText;\n  }\n  d3.json = function(url, callback) {\n    return d3.xhr(url, \"application/json\", callback).response(d3_json);\n  };\n  function d3_json(request) {\n    return JSON.parse(request.responseText);\n  }\n  d3.html = function(url, callback) {\n    return d3.xhr(url, \"text/html\", callback).response(d3_html);\n  };\n  function d3_html(request) {\n    var range = d3_document.createRange();\n    range.selectNode(d3_document.body);\n    return range.createContextualFragment(request.responseText);\n  }\n  d3.xml = function() {\n    return d3.xhr.apply(d3, arguments).response(d3_xml);\n  };\n  function d3_xml(request) {\n    return request.responseXML;\n  }\n  return d3;\n}();\n"
  },
  {
    "path": "packages/deprecated/d3/package.js",
    "content": "Package.describe({\n  summary: \"Library for manipulating documents based on data\",\n  version: \"1.0.0\"\n});\n\nPackage.onUse(function (api) {\n  api.export('d3', 'client');\n  api.addFiles('d3.v3.js', 'client');\n});\n"
  },
  {
    "path": "packages/deps/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/deps/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/deps/package.js",
    "content": "// XXX rename package?\n\nPackage.describe({\n  summary: \"Deprecated: Use the 'tracker' package instead.\",\n  version: '1.0.12'\n});\n\nPackage.onUse(function (api) {\n  api.use('tracker');\n  api.imply('tracker');\n\n  // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.\n  //\n  // (in particular, packages that have a weak dependency on this\n  // package, since then exported symbols live on the\n  // `Package.deps` object)\n  api.export('Tracker');\n  api.export('Deps');\n});\n"
  },
  {
    "path": "packages/diff-sequence/diff.js",
    "content": "DiffSequence = {};\n\n// ordered: bool.\n// old_results and new_results: collections of documents.\n//    if ordered, they are arrays.\n//    if unordered, they are IdMaps\nDiffSequence.diffQueryChanges = function (ordered, oldResults, newResults,\n                                              observer, options) {\n  if (ordered)\n    DiffSequence.diffQueryOrderedChanges(\n      oldResults, newResults, observer, options);\n  else\n    DiffSequence.diffQueryUnorderedChanges(\n      oldResults, newResults, observer, options);\n};\n\nDiffSequence.diffQueryUnorderedChanges = function (oldResults, newResults,\n                                                       observer, options) {\n  options = options || {};\n  var projectionFn = options.projectionFn || EJSON.clone;\n\n  if (observer.movedBefore) {\n    throw new Error(\"_diffQueryUnordered called with a movedBefore observer!\");\n  }\n\n  newResults.forEach(function (newDoc, id) {\n    var oldDoc = oldResults.get(id);\n    if (oldDoc) {\n      if (observer.changed && !EJSON.equals(oldDoc, newDoc)) {\n        var projectedNew = projectionFn(newDoc);\n        var projectedOld = projectionFn(oldDoc);\n        var changedFields =\n              DiffSequence.makeChangedFields(projectedNew, projectedOld);\n        if (! _.isEmpty(changedFields)) {\n          observer.changed(id, changedFields);\n        }\n      }\n    } else if (observer.added) {\n      var fields = projectionFn(newDoc);\n      delete fields._id;\n      observer.added(newDoc._id, fields);\n    }\n  });\n\n  if (observer.removed) {\n    oldResults.forEach(function (oldDoc, id) {\n      if (!newResults.has(id))\n        observer.removed(id);\n    });\n  }\n};\n\n\nDiffSequence.diffQueryOrderedChanges = function (old_results, new_results,\n                                                     observer, options) {\n  options = options || {};\n  var projectionFn = options.projectionFn || EJSON.clone;\n\n  var new_presence_of_id = {};\n  _.each(new_results, function (doc) {\n    if (new_presence_of_id[doc._id])\n      Meteor._debug(\"Duplicate _id in new_results\");\n    new_presence_of_id[doc._id] = true;\n  });\n\n  var old_index_of_id = {};\n  _.each(old_results, function (doc, i) {\n    if (doc._id in old_index_of_id)\n      Meteor._debug(\"Duplicate _id in old_results\");\n    old_index_of_id[doc._id] = i;\n  });\n\n  // ALGORITHM:\n  //\n  // To determine which docs should be considered \"moved\" (and which\n  // merely change position because of other docs moving) we run\n  // a \"longest common subsequence\" (LCS) algorithm.  The LCS of the\n  // old doc IDs and the new doc IDs gives the docs that should NOT be\n  // considered moved.\n\n  // To actually call the appropriate callbacks to get from the old state to the\n  // new state:\n\n  // First, we call removed() on all the items that only appear in the old\n  // state.\n\n  // Then, once we have the items that should not move, we walk through the new\n  // results array group-by-group, where a \"group\" is a set of items that have\n  // moved, anchored on the end by an item that should not move.  One by one, we\n  // move each of those elements into place \"before\" the anchoring end-of-group\n  // item, and fire changed events on them if necessary.  Then we fire a changed\n  // event on the anchor, and move on to the next group.  There is always at\n  // least one group; the last group is anchored by a virtual \"null\" id at the\n  // end.\n\n  // Asymptotically: O(N k) where k is number of ops, or potentially\n  // O(N log N) if inner loop of LCS were made to be binary search.\n\n\n  //////// LCS (longest common sequence, with respect to _id)\n  // (see Wikipedia article on Longest Increasing Subsequence,\n  // where the LIS is taken of the sequence of old indices of the\n  // docs in new_results)\n  //\n  // unmoved: the output of the algorithm; members of the LCS,\n  // in the form of indices into new_results\n  var unmoved = [];\n  // max_seq_len: length of LCS found so far\n  var max_seq_len = 0;\n  // seq_ends[i]: the index into new_results of the last doc in a\n  // common subsequence of length of i+1 <= max_seq_len\n  var N = new_results.length;\n  var seq_ends = new Array(N);\n  // ptrs:  the common subsequence ending with new_results[n] extends\n  // a common subsequence ending with new_results[ptr[n]], unless\n  // ptr[n] is -1.\n  var ptrs = new Array(N);\n  // virtual sequence of old indices of new results\n  var old_idx_seq = function(i_new) {\n    return old_index_of_id[new_results[i_new]._id];\n  };\n  // for each item in new_results, use it to extend a common subsequence\n  // of length j <= max_seq_len\n  for(var i=0; i<N; i++) {\n    if (old_index_of_id[new_results[i]._id] !== undefined) {\n      var j = max_seq_len;\n      // this inner loop would traditionally be a binary search,\n      // but scanning backwards we will likely find a subseq to extend\n      // pretty soon, bounded for example by the total number of ops.\n      // If this were to be changed to a binary search, we'd still want\n      // to scan backwards a bit as an optimization.\n      while (j > 0) {\n        if (old_idx_seq(seq_ends[j-1]) < old_idx_seq(i))\n          break;\n        j--;\n      }\n\n      ptrs[i] = (j === 0 ? -1 : seq_ends[j-1]);\n      seq_ends[j] = i;\n      if (j+1 > max_seq_len)\n        max_seq_len = j+1;\n    }\n  }\n\n  // pull out the LCS/LIS into unmoved\n  var idx = (max_seq_len === 0 ? -1 : seq_ends[max_seq_len-1]);\n  while (idx >= 0) {\n    unmoved.push(idx);\n    idx = ptrs[idx];\n  }\n  // the unmoved item list is built backwards, so fix that\n  unmoved.reverse();\n\n  // the last group is always anchored by the end of the result list, which is\n  // an id of \"null\"\n  unmoved.push(new_results.length);\n\n  _.each(old_results, function (doc) {\n    if (!new_presence_of_id[doc._id])\n      observer.removed && observer.removed(doc._id);\n  });\n  // for each group of things in the new_results that is anchored by an unmoved\n  // element, iterate through the things before it.\n  var startOfGroup = 0;\n  _.each(unmoved, function (endOfGroup) {\n    var groupId = new_results[endOfGroup] ? new_results[endOfGroup]._id : null;\n    var oldDoc, newDoc, fields, projectedNew, projectedOld;\n    for (var i = startOfGroup; i < endOfGroup; i++) {\n      newDoc = new_results[i];\n      if (!_.has(old_index_of_id, newDoc._id)) {\n        fields = projectionFn(newDoc);\n        delete fields._id;\n        observer.addedBefore && observer.addedBefore(newDoc._id, fields, groupId);\n        observer.added && observer.added(newDoc._id, fields);\n      } else {\n        // moved\n        oldDoc = old_results[old_index_of_id[newDoc._id]];\n        projectedNew = projectionFn(newDoc);\n        projectedOld = projectionFn(oldDoc);\n        fields = DiffSequence.makeChangedFields(projectedNew, projectedOld);\n        if (!_.isEmpty(fields)) {\n          observer.changed && observer.changed(newDoc._id, fields);\n        }\n        observer.movedBefore && observer.movedBefore(newDoc._id, groupId);\n      }\n    }\n    if (groupId) {\n      newDoc = new_results[endOfGroup];\n      oldDoc = old_results[old_index_of_id[newDoc._id]];\n      projectedNew = projectionFn(newDoc);\n      projectedOld = projectionFn(oldDoc);\n      fields = DiffSequence.makeChangedFields(projectedNew, projectedOld);\n      if (!_.isEmpty(fields)) {\n        observer.changed && observer.changed(newDoc._id, fields);\n      }\n    }\n    startOfGroup = endOfGroup+1;\n  });\n\n\n};\n\n\n// General helper for diff-ing two objects.\n// callbacks is an object like so:\n// { leftOnly: function (key, leftValue) {...},\n//   rightOnly: function (key, rightValue) {...},\n//   both: function (key, leftValue, rightValue) {...},\n// }\nDiffSequence.diffObjects = function (left, right, callbacks) {\n  _.each(left, function (leftValue, key) {\n    if (_.has(right, key))\n      callbacks.both && callbacks.both(key, leftValue, right[key]);\n    else\n      callbacks.leftOnly && callbacks.leftOnly(key, leftValue);\n  });\n  if (callbacks.rightOnly) {\n    _.each(right, function(rightValue, key) {\n      if (!_.has(left, key))\n        callbacks.rightOnly(key, rightValue);\n    });\n  }\n};\n\n\nDiffSequence.makeChangedFields = function (newDoc, oldDoc) {\n  var fields = {};\n  DiffSequence.diffObjects(oldDoc, newDoc, {\n    leftOnly: function (key, value) {\n      fields[key] = undefined;\n    },\n    rightOnly: function (key, value) {\n      fields[key] = value;\n    },\n    both: function (key, leftValue, rightValue) {\n      if (!EJSON.equals(leftValue, rightValue))\n        fields[key] = rightValue;\n    }\n  });\n  return fields;\n};\n\nDiffSequence.applyChanges = function (doc, changeFields) {\n  _.each(changeFields, function (value, key) {\n    if (value === undefined)\n      delete doc[key];\n    else\n      doc[key] = value;\n  });\n};\n\n"
  },
  {
    "path": "packages/diff-sequence/package.js",
    "content": "Package.describe({\n  summary: \"An implementation of a diff algorithm on arrays and objects.\",\n  version: '1.0.6',\n  documentation: null\n});\n\nPackage.onUse(function (api) {\n  api.export('DiffSequence');\n  api.use(['underscore', 'ejson']);\n  api.addFiles([\n    'diff.js'\n  ]);\n});\n\nPackage.onTest(function (api) {\n  api.use([\n    'tinytest',\n    'underscore',\n    'ejson'\n  ]);\n\n  api.use('diff-sequence');\n  api.addFiles([\n    'tests.js'\n  ]);\n});\n"
  },
  {
    "path": "packages/diff-sequence/tests.js",
    "content": "Tinytest.add(\"diff-sequence - diff changes ordering\", function (test) {\n  var makeDocs = function (ids) {\n    return _.map(ids, function (id) { return {_id: id};});\n  };\n  var testMutation = function (a, b) {\n    var aa = makeDocs(a);\n    var bb = makeDocs(b);\n    var aaCopy = EJSON.clone(aa);\n    DiffSequence.diffQueryOrderedChanges(aa, bb, {\n\n      addedBefore: function (id, doc, before) {\n        if (before === null) {\n          aaCopy.push( _.extend({_id: id}, doc));\n          return;\n        }\n        for (var i = 0; i < aaCopy.length; i++) {\n          if (aaCopy[i]._id === before) {\n            aaCopy.splice(i, 0, _.extend({_id: id}, doc));\n            return;\n          }\n        }\n      },\n      movedBefore: function (id, before) {\n        var found;\n        for (var i = 0; i < aaCopy.length; i++) {\n          if (aaCopy[i]._id === id) {\n            found = aaCopy[i];\n            aaCopy.splice(i, 1);\n          }\n        }\n        if (before === null) {\n          aaCopy.push( _.extend({_id: id}, found));\n          return;\n        }\n        for (i = 0; i < aaCopy.length; i++) {\n          if (aaCopy[i]._id === before) {\n            aaCopy.splice(i, 0, _.extend({_id: id}, found));\n            return;\n          }\n        }\n      },\n      removed: function (id) {\n        var found;\n        for (var i = 0; i < aaCopy.length; i++) {\n          if (aaCopy[i]._id === id) {\n            found = aaCopy[i];\n            aaCopy.splice(i, 1);\n          }\n        }\n      }\n    });\n    test.equal(aaCopy, bb);\n  };\n\n  var testBothWays = function (a, b) {\n    testMutation(a, b);\n    testMutation(b, a);\n  };\n\n  testBothWays([\"a\", \"b\", \"c\"], [\"c\", \"b\", \"a\"]);\n  testBothWays([\"a\", \"b\", \"c\"], []);\n  testBothWays([\"a\", \"b\", \"c\"], [\"e\",\"f\"]);\n  testBothWays([\"a\", \"b\", \"c\", \"d\"], [\"c\", \"b\", \"a\"]);\n  testBothWays(['A','B','C','D','E','F','G','H','I'],\n               ['A','B','F','G','C','D','I','L','M','N','H']);\n  testBothWays(['A','B','C','D','E','F','G','H','I'],['A','B','C','D','F','G','H','E','I']);\n});\n\nTinytest.add(\"diff-sequence - diff\", function (test) {\n\n  // test correctness\n\n  var diffTest = function(origLen, newOldIdx) {\n    var oldResults = new Array(origLen);\n    for (var i = 1; i <= origLen; i++)\n      oldResults[i-1] = {_id: i};\n\n    var newResults = _.map(newOldIdx, function(n) {\n      var doc = {_id: Math.abs(n)};\n      if (n < 0)\n        doc.changed = true;\n      return doc;\n    });\n    var find = function (arr, id) {\n      for (var i = 0; i < arr.length; i++) {\n        if (EJSON.equals(arr[i]._id, id))\n          return i;\n      }\n      return -1;\n    };\n\n    var results = _.clone(oldResults);\n    var observer = {\n      addedBefore: function(id, fields, before) {\n        var before_idx;\n        if (before === null)\n          before_idx = results.length;\n        else\n          before_idx = find (results, before);\n        var doc = _.extend({_id: id}, fields);\n        test.isFalse(before_idx < 0 || before_idx > results.length);\n        results.splice(before_idx, 0, doc);\n      },\n      removed: function(id) {\n        var at_idx = find (results, id);\n        test.isFalse(at_idx < 0 || at_idx >= results.length);\n        results.splice(at_idx, 1);\n      },\n      changed: function(id, fields) {\n        var at_idx = find (results, id);\n        var oldDoc = results[at_idx];\n        var doc = EJSON.clone(oldDoc);\n        DiffSequence.applyChanges(doc, fields);\n        test.isFalse(at_idx < 0 || at_idx >= results.length);\n        test.equal(doc._id, oldDoc._id);\n        results[at_idx] = doc;\n      },\n      movedBefore: function(id, before) {\n        var old_idx = find(results, id);\n        var new_idx;\n        if (before === null)\n          new_idx = results.length;\n        else\n          new_idx = find (results, before);\n        if (new_idx > old_idx)\n          new_idx--;\n        test.isFalse(old_idx < 0 || old_idx >= results.length);\n        test.isFalse(new_idx < 0 || new_idx >= results.length);\n        results.splice(new_idx, 0, results.splice(old_idx, 1)[0]);\n      }\n    };\n\n    DiffSequence.diffQueryOrderedChanges(oldResults, newResults, observer);\n    test.equal(results, newResults);\n  };\n\n  // edge cases and cases run into during debugging\n  diffTest(5, [5, 1, 2, 3, 4]);\n  diffTest(0, [1, 2, 3, 4]);\n  diffTest(4, []);\n  diffTest(7, [4, 5, 6, 7, 1, 2, 3]);\n  diffTest(7, [5, 6, 7, 1, 2, 3, 4]);\n  diffTest(10, [7, 4, 11, 6, 12, 1, 5]);\n  diffTest(3, [3, 2, 1]);\n  diffTest(10, [2, 7, 4, 6, 11, 3, 8, 9]);\n  diffTest(0, []);\n  diffTest(1, []);\n  diffTest(0, [1]);\n  diffTest(1, [1]);\n  diffTest(5, [1, 2, 3, 4, 5]);\n\n  // interaction between \"changed\" and other ops\n  diffTest(5, [-5, -1, 2, -3, 4]);\n  diffTest(7, [-4, -5, 6, 7, -1, 2, 3]);\n  diffTest(7, [5, 6, -7, 1, 2, -3, 4]);\n  diffTest(10, [7, -4, 11, 6, 12, -1, 5]);\n  diffTest(3, [-3, -2, -1]);\n  diffTest(10, [-2, 7, 4, 6, 11, -3, -8, 9]);\n});\n\n"
  },
  {
    "path": "packages/disable-oplog/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/disable-oplog/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/disable-oplog/package.js",
    "content": "Package.describe({\n  summary: \"Disables oplog tailing\",\n  version: '1.0.7'\n});\n\n// This package is empty; its presence is detected by mongo-livedata.\n"
  },
  {
    "path": "packages/ecmascript/README.md",
    "content": "# [ecmascript](https://github.com/meteor/meteor/tree/devel/packages/ecmascript)\n\nThis package lets you use new JavaScript language features that are part\nof the [ECMAScript 2015\nspecification](http://www.ecma-international.org/ecma-262/6.0/) but are\nnot yet supported by all engines or browsers. Unsupported syntax is\nautomatically translated into standard JavaScript that behaves the same\nway.\n\n[This video](https://www.youtube.com/watch?v=05Z6YGiZKmE) from the July\n2015 Meteor Devshop gives an overview of how the package works, and what\nit provides.\n\nRead more at http://docs.meteor.com/#/full/ecmascript\n\n## Usage\n\nThe `ecmascript` package registers a compiler plugin that transpiles\nECMAScript 2015+ to ECMAScript 5 (standard JS) in all `.js` files. By\ndefault, this package is pre-installed for all new apps and packages.\n\nTo add this package to an existing app, run the following command from\nyour app directory:\n\n```bash\nmeteor add ecmascript\n```\n\nTo add the `ecmascript` package to an existing package, include the\nstatement `api.use('ecmascript');` in the `Package.onUse` callback in your\n`package.js` file:\n\n```js\nPackage.onUse(function (api) {\n  api.use('ecmascript');\n});\n```\n\n## Supported ES2015 Features\n\n### Syntax\n\nThe `ecmascript` package uses [Babel](http://babeljs.io/) to compile\nES2015 syntax to ES5 syntax. Many but not all ES2015 features can be\nsimulated by Babel, and `ecmascript` enables most of the features\nsupported by Babel.\n\nHere is a list of the Babel transformers that are currently enabled:\n\n* [`es3.propertyLiterals`](https://babeljs.io/docs/advanced/transformers/es3/property-literals/)<br>\n  Makes it safe to use reserved keywords like `catch` as unquoted keys in\n  object literals. For example, `{ catch: 123 }` is translated to `{ \"catch\": 123 }`.\n\n* [`es3.memberExpressionLiterals`](https://babeljs.io/docs/advanced/transformers/es3/member-expression-literals/)<br>\n  Makes it safe to use reserved keywords as property names. For\n  example, `object.catch` is translated to `object[\"catch\"]`.\n\n* [`es6.arrowFunctions`](http://babeljs.io/docs/learn-es2015/#arrows)<br>\n  Provides a shorthand for function expressions. For example,\n  `[1, 2, 3].map(x => x + 1)` evaluates to `[2, 3, 4]`. If `this` is used\n  in the body of the arrow function, it will be automatically bound to the\n  value of `this` in the enclosing scope.\n\n* [`es6.literals`](http://babeljs.io/docs/learn-es2015/#binary-and-octal-literals)<br>\n  Adds support for binary and octal numeric literals. For example,\n  `0b111110111 === 503` and `0o767 === 503`.\n\n* [`es6.templateLiterals`](http://babeljs.io/docs/learn-es2015/#template-strings)<br>\n  Enables multi-line strings delimited by backticks instead of quotation\n  marks, with variable interpolation:\n  ```js\n  var name = \"Ben\";\n  var message = `My name is:\n  ${name}`;\n  ```\n\n* [`es6.classes`](http://babeljs.io/docs/learn-es2015/#classes)<br>\n  Enables `class` syntax:\n  ```js\n  class Base {\n    constructor(a, b) {\n      this.value = a * b;\n    }\n  }\n\n  class Derived extends Base {\n    constructor(a, b) {\n      super(a + 1, b + 1);\n    }\n  }\n\n  var d = new Derived(2, 3);\n  d.value; // 12\n  ```\n\n* [`es6.constants`](https://babeljs.io/docs/learn-es2015/#let-const)<br>\n  Allows defining block-scoped variables that are not allowed to be\n  redefined:\n  ```js\n  const GOLDEN_RATIO = (1 + Math.sqrt(5)) / 2;\n\n  // This reassignment will be forbidden by the compiler:\n  GOLDEN_RATIO = \"new value\";\n  ```\n\n* [`es6.blockScoping`](http://babeljs.io/docs/learn-es2015/#let-const)<br>\n  Enables the `let` and `const` keywords as alternatives to `var`. The key\n  difference is that variables defined using `let` or `const` are\n  visible only within the block where they are declared, rather than being\n  visible anywhere in the enclosing function. For example:\n  ```js\n  function example(condition) {\n    let x = 0;\n    if (condition) {\n      let x = 1;\n      console.log(x);\n    } else {\n      console.log(x);\n      x = 2;\n    }\n    return x;\n  }\n\n  example(true); // logs 1, returns 0\n  example(false); // logs 0, returns 2\n  ```\n\n* [`es6.properties.shorthand`](https://babeljs.io/docs/learn-es2015/#enhanced-object-literals)<br>\n  Allows omitting the value of an object literal property when the desired\n  value is held by a variable that has the same name as the property\n  key. For example, instead of writing `{ x: x, y: y, z: \"asdf\" }` you can\n  just write `{ x, y, z: \"asdf\" }`. Methods can also be written without\n  the `: function` property syntax:\n  ```js\n  var obj = {\n    oldWay: function (a, b) { ... },\n    newWay(a, b) { ... }\n  };\n  ```\n\n* [`es6.properties.computed`](http://babeljs.io/docs/learn-es2015/#enhanced-object-literals)<br>\n  Allows object literal properties with dynamically computed keys:\n  ```js\n  var counter = 0;\n  function getKeyName() {\n    return \"key\" + counter++;\n  }\n\n  var obj = {\n    [getKeyName()]: \"zero\",\n    [getKeyName()]: \"one\",\n  };\n\n  obj.key0; // \"zero\"\n  obj.key1; // \"one\"\n  ```\n\n* [`es6.parameters`](http://babeljs.io/docs/learn-es2015/#default-rest-spread)<br>\n  Default expressions for function parameters, evaluated whenever the parameter\n  is `undefined`, `...rest` parameters for capturing remaining\n  arguments without using the `arguments` object:\n  ```js\n  function add(a = 0, ...rest) {\n    rest.forEach(n => a += n);\n    return a;\n  }\n\n  add(); // 0\n  add(1, 2, 3); // 6\n  ```\n\n* [`es6.spread`](http://babeljs.io/docs/learn-es2015/#default-rest-spread)<br>\n  Allows an array of arguments to be interpolated into a list of arguments\n  to a function call, `new` expression, or array literal, without using\n  `Function.prototype.apply`:\n  ```js\n  add(1, ...[2, 3, 4], 5); // 15\n  new Node(\"name\", ...children);\n  [1, ...[2, 3, 4], 5]; // [1, 2, 3, 4, 5]\n  ```\n\n* [`es6.forOf`](http://babeljs.io/docs/learn-es2015/#iterators-for-of)<br>\n  Provides an easy way to iterate over the elements of a collection:\n  ```js\n  let sum = 0;\n  for (var x of [1, 2, 3]) {\n    sum += x;\n  }\n  x; // 6\n  ```\n\n* [`es6.destructuring`](http://babeljs.io/docs/learn-es2015/#destructuring)<br>\n  Destructuring is the technique of using an array or object pattern on\n  the left-hand side of an assignment or declaration, in place of the\n  usual variable or parameter, so that certain sub-properties of the value\n  on the right-hand side will be bound to identifiers that appear within the\n  pattern. Perhaps the simplest example is swapping two variables without\n  using a temporary variable:\n  ```js\n  [a, b] = [b, a];\n  ```\n  Extracting a specific property from an object:\n  ```js\n  let { username: name } = user;\n  // is equivalent to\n  let name = user.username;\n  ```\n  Instead of taking a single opaque `options` parameter, a function can\n  use an object destructuring pattern to name the expected options:\n  ```js\n  function run({ command, args, callback }) { ... }\n\n  run({\n    command: \"git\",\n    args: [\"status\", \".\"],\n    callback(error, status) { ... },\n    unused: \"whatever\"\n  });\n  ```\n\n* [`es7.objectRestSpread`](https://github.com/sebmarkbage/ecmascript-rest-spread)<br>\n  Supports catch-all `...rest` properties in object literal declarations\n  and assignments:\n  ```js\n  let { x, y, ...rest } = { x: 1, y: 2, a: 3, b: 4 };\n  x; // 1\n  y; // 2\n  rest; // { a: 3, b: 4 }\n  ```\n  Also enables `...spread` properties in object literal expressions:\n  ```js\n  let n = { x, y, ...rest };\n  n; // { x: 1, y: 2, a: 3, b: 4 }\n  ```\n\n* [`es7.trailingFunctionCommas`](https://github.com/jeffmo/es-trailing-function-commas)<br>\n  Allows the final parameter of a function to be followed by a comma,\n  provided that parameter is not a `...rest` parameter.\n\n* [`flow`](https://babeljs.io/docs/advanced/transformers/other/flow/)<br>\n  Permits the use of [Flow](http://flowtype.org/) type annotations. These\n  annotations are simply stripped from the code, so they have no effect on\n  the code's behavior, but you can run the `flow` tool over your code to\n  check the types if desired.\n\n### Polyfills\n\nThe ECMAScript 2015 standard library has grown to include new APIs and\ndata structures, some of which can be implemented (\"polyfilled\") using\nJavaScript that runs in all engines and browsers today. Here are three new\nconstructors that are guaranteed to be available when the `ecmascript`\npackage is installed:\n\n* [`Promise`](https://github.com/meteor/promise)<br>\n  A `Promise` allows its owner to wait for a value that might not be\n  available yet. See [this tutorial](https://www.promisejs.org/) for more\n  details about the API and motivation. The Meteor `Promise`\n  implementation is especially useful because it runs all callback\n  functions in recycled `Fiber`s, so you can use any Meteor API, including\n  those that yield (e.g. `HTTP.get`, `Meteor.call`, or `MongoCollection`),\n  and you never have to call `Meteor.bindEnvironment`.\n\n* [`Map`](https://github.com/zloirock/core-js#map)<br>\n  An associative key-value data structure where the keys can be any\n  JavaScript value (not just strings). Lookup and insertion take constant\n  time.\n\n* [`Set`](https://github.com/zloirock/core-js#set)<br>\n  A collection of unique JavaScript values of any type. Lookup and\n  insertion take constant time.\n\n* [`Symbol`](https://github.com/zloirock/core-js#ecmascript-6-symbol)<br>\n  An implementation of the global\n  [`Symbol`](http://www.2ality.com/2014/12/es6-symbols.html)s namespace\n  that enables a number of other ES2015 features, such as `for`-`of` loops\n  and `Symbol.iterator` methods: `[1,2,3][Symbol.iterator]()`.\n\n* Polyfills for the following [`Object`](https://github.com/zloirock/core-js#ecmascript-6-object)-related methods:\n  * `Object.assign`\n  * `Object.is`\n  * `Object.setPrototypeOf`\n  * `Object.prototype.toString` (fixes `@@toStringTag` support)<br>\n\n  Complete reference [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object).\n\n* Polyfills for the following [`String`](https://github.com/zloirock/core-js#ecmascript-6-string)-related methods:\n  * `String.fromCodePoint`\n  * `String.raw`\n  * `String.prototype.includes`\n  * `String.prototype.startsWith`\n  * `String.prototype.endsWith`\n  * `String.prototype.repeat`\n  * `String.prototype.codePointAt`\n  * `String.prototype.trim`<br>\n\n  Complete reference [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String).\n\n* Polyfills for the following [`Array`](https://github.com/zloirock/core-js#ecmascript-6-array)-related methods:\n  * `Array.from`\n  * `Array.of`\n  * `Array.prototype.copyWithin`\n  * `Array.prototype.fill`\n  * `Array.prototype.find`\n  * `Array.prototype.findIndex`\n\n  Complete reference [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array).\n\n* Polyfills for the following [`Function`](https://github.com/zloirock/core-js#ecmascript-6-function)-related properties:\n  * `Function.prototype.name` (fixes IE9+)\n  * `Function.prototype[Symbol.hasInstance]` (fixes IE9+)\n\n  Complete reference [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array).\n"
  },
  {
    "path": "packages/ecmascript/bare-test-file.js",
    "content": "// Since this file is added with bare: true, this variable will be accessible\n// in package scope.\nvar exportedFromBareFile = \"Yes\";\n"
  },
  {
    "path": "packages/ecmascript/bare-test.js",
    "content": "Tinytest.add(\"ecmascript - bare files work\", function (test) {\n  // This is defined in bare-file.js\n  test.equal(exportedFromBareFile, \"Yes\");\n});\n"
  },
  {
    "path": "packages/ecmascript/ecmascript.js",
    "content": "ECMAScript = {\n  compileForShell(command) {\n    const babelOptions = Babel.getDefaultOptions();\n    babelOptions.sourceMap = false;\n    babelOptions.ast = false;\n    return Babel.compile(command, babelOptions).code;\n  }\n};\n"
  },
  {
    "path": "packages/ecmascript/package.js",
    "content": "Package.describe({\n  name: 'ecmascript',\n  version: '0.4.6_1',\n  summary: 'Compiler plugin that supports ES2015+ in all .js files',\n  documentation: 'README.md'\n});\n\nPackage.registerBuildPlugin({\n  name: 'compile-ecmascript',\n  use: ['babel-compiler'],\n  sources: ['plugin.js']\n});\n\nPackage.onUse(function (api) {\n  api.use('isobuild:compiler-plugin@1.0.0');\n  api.use('babel-compiler');\n\n  // The following api.imply calls should match those in\n  // ../coffeescript/package.js.\n  api.imply('modules');\n  api.imply('ecmascript-runtime');\n  api.imply('babel-runtime');\n  api.imply('promise');\n\n  api.addFiles(\"ecmascript.js\", \"server\");\n  api.export(\"ECMAScript\", \"server\");\n});\n\nPackage.onTest(function (api) {\n  api.use([\"tinytest\", \"underscore\"]);\n  api.use([\"es5-shim\", \"ecmascript\", \"babel-compiler\"]);\n  api.addFiles(\"runtime-tests.js\");\n  api.addFiles(\"transpilation-tests.js\", \"server\");\n\n  api.addFiles(\"bare-test.js\");\n  api.addFiles(\"bare-test-file.js\", [\"client\", \"server\"], {\n    bare: true\n  });\n});\n"
  },
  {
    "path": "packages/ecmascript/plugin.js",
    "content": "Plugin.registerCompiler({\n  extensions: ['js', 'jsx'],\n}, function () {\n  return new BabelCompiler({\n    react: true\n  });\n});\n"
  },
  {
    "path": "packages/ecmascript/runtime-tests.js",
    "content": "Tinytest.add(\"ecmascript - runtime - template literals\", (test) => {\n  function dump(pieces) {\n    var copy = {};\n    // Can't use _.extend({}, pieces) because es5-shim adds enumerable\n    // methods to Array.prototype, and _.extend has no own property check.\n    _.each(_.keys(pieces), key => copy[key] = pieces[key]);\n    return [copy, _.toArray(arguments).slice(1)];\n  };\n  const foo = 'B';\n  // uses `babelHelpers.taggedTemplateLiteralLoose`\n  test.equal(`\\u0041${foo}C`, 'ABC');\n  test.equal(dump`\\u0041${foo}C`,\n             [{0:'A', 1: 'C', raw: ['\\\\u0041', 'C']},\n              ['B']]);\n});\n\nTinytest.add(\"ecmascript - runtime - classes - basic\", (test) => {\n  {\n    class Foo {\n      constructor(x) {\n        this.x = x;\n      }\n    }\n\n    test.throws(() => {\n      Foo(); // called without `new`\n    });\n\n    test.equal((new Foo(3)).x, 3);\n  }\n\n  {\n    class Bar {\n      constructor(x) {\n        this.x = x;\n      }\n    }\n    class Foo extends Bar {}\n\n    test.throws(() => {\n      Foo(); // called without `new`\n    });\n\n    test.equal((new Foo(3)).x, 3);\n    test.isTrue((new Foo(3)) instanceof Foo);\n    test.isTrue((new Foo(3)) instanceof Bar);\n  }\n\n  {\n    class Foo {\n      static staticMethod() {\n        return 'classy';\n      }\n\n      prototypeMethod() {\n        return 'prototypical';\n      }\n    }\n\n    test.equal(Foo.staticMethod(), 'classy');\n    test.equal((new Foo).prototypeMethod(), 'prototypical');\n  }\n});\n\nTinytest.add(\"ecmascript - runtime - classes - use before declare\", (test) => {\n  const x = function asdf() {};\n  if (typeof asdf === 'function') {\n    // We seem to be in IE 8, where function names leak into the enclosing\n    // scope, contrary to the spec.  In this case, Babel does not (currently)\n    // throw an error if you use a class before you declare it.  (Of course,\n    // any other browser can tell the developer they screwed up!)\n    test.expect_fail();\n  }\n\n  test.throws(() => {\n    new Foo(); // use before definition\n    class Foo {}\n  });\n});\n\n\nTinytest.add(\"ecmascript - runtime - classes - inheritance\", (test) => {\n\n  // uses `babelHelpers.inherits`\n  {\n    class Foo {\n      static static1() {\n        return 1;\n      }\n    }\n    Foo.static2 = function () {\n      return 2;\n    };\n\n    // static methods are inherited!\n    class Bar extends Foo {}\n\n    test.equal(Foo.static1(), 1);\n    test.equal(Foo.static2(), 2);\n    test.equal(Bar.static1(), 1);\n    test.equal(Bar.static2(), 2);\n  }\n\n  {\n    const buf = [];\n    class Foo {\n      constructor() {\n        buf.push('hi');\n      }\n    }\n\n    class Bar extends Foo {}\n\n    new Bar();\n    // derived class with no constructor gets a default constructor\n    // that calls the super constructor\n    test.equal(buf, ['hi']);\n  }\n});\n\nTinytest.add(\"ecmascript - runtime - classes - computed props\", (test) => {\n  {\n    const frob = \"inc\";\n\n    class Foo {\n      static [frob](n) { return n+1; }\n    }\n\n    test.equal(Foo.inc(3), 4);\n  }\n});\n\nif (Meteor.isServer) {\n  // getters and setters don't work in all clients, but they should work\n  // in classes on browsers that support them in the first place, and on\n  // the server.  (Technically they just need a working\n  // Object.defineProperty, found in IE9+ and all modern environments.)\n  Tinytest.add(\"ecmascript - runtime - classes - getters/setters\", (test) => {\n    // uses `babelHelpers.createClass`\n    class Foo {\n      get two() { return 1+1; }\n      static get three() { return 1+1+1; }\n    }\n\n    test.equal((new Foo).two, 2);\n    test.equal(Foo.three, 3);\n  });\n}\n\nTinytest.add(\"ecmascript - runtime - block scope\", (test) => {\n  {\n    const buf = [];\n    const thunks = [];\n    function print(x) {\n      buf.push(x);\n    };\n    function doLater(f) {\n      thunks.push(f);\n    };\n\n    for (let i = 0; i < 3; i++) {\n      print(i);\n    }\n    test.equal(buf, [0, 1, 2]);\n    buf.length = 0;\n\n    for (let i = 0; i < 3; i++) {\n      doLater(() => {\n        print(i);\n      });\n    }\n\n    _.each(thunks, f => f());\n    test.equal(buf, [0, 1, 2]);\n  }\n});\n\nTinytest.add(\"ecmascript - runtime - classes - super\", (test) => {\n  {\n    class Class1 {\n      foo() { return 123; }\n      static bar() { return 1; }\n    }\n    class Class2 extends Class1 {}\n    class Class3 extends Class2 {\n      foo() {\n        return super.foo() + Class3.bar();\n      }\n    }\n\n    test.equal((new Class3).foo(), 124);\n  }\n\n  {\n    class Foo {\n      constructor(value) { this.value = value; }\n      x() { return this.value; }\n    }\n\n    class Bar extends Foo {\n      constructor() { super(123); }\n      x() { return super.x(); }\n    }\n\n    test.equal((new Bar).x(), 123);\n  }\n});\n\nTinytest.add(\"ecmascript - runtime - object rest/spread\", (test) => {\n  const middle = {b:2, c:3};\n  // uses `babelHelpers._extends`\n  const full = {a:1, ...middle, d:4};\n  test.equal(full, {a:1, b:2, c:3, d:4});\n});\n\nTinytest.add(\"ecmascript - runtime - spread args to new\", (test) => {\n\n  const Foo = function (one, two, three) {\n    test.isTrue(this instanceof Foo);\n    test.equal(one, 1);\n    test.equal(two, 2);\n    test.equal(three, 3);\n    this.created = true;\n  };\n\n  const oneTwo = [1, 2];\n\n  // uses `babelHelpers.bind`\n  const foo = new Foo(...oneTwo, 3);\n  test.isTrue(foo.created);\n});\n\nTinytest.add(\"ecmascript - runtime - Map spread\", (test) => {\n  const map = new Map;\n\n  map.set(0, 1);\n  map.set(1, 2);\n  map.set(2, 3);\n\n  test.equal([...map], [\n    [0, 1],\n    [1, 2],\n    [2, 3]\n  ]);\n});\n\nTinytest.add(\"ecmascript - runtime - Set spread\", (test) => {\n  const set = new Set;\n\n  set.add(\"a\");\n  set.add(1);\n  set.add(false);\n\n  test.equal([...set], [\"a\", 1, false]);\n});\n\nTinytest.add(\"ecmascript - runtime - destructuring\", (test) => {\n  // uses `babelHelpers.objectWithoutProperties` and\n  // `babelHelpers.objectDestructuringEmpty`\n\n  const obj = {a:1, b:2};\n  const {a, ...rest} = obj;\n  test.equal(a, 1);\n  test.equal(rest, {b:2});\n\n  const {} = {};\n\n  test.throws(() => {\n    const {} = null;\n  }, /Cannot destructure undefined/);\n\n  const [x, y, z] = function*() {\n    let x = 1;\n    while (true) {\n      yield x++;\n    }\n  }();\n\n  test.equal(x, 1);\n  test.equal(y, 2);\n  test.equal(z, 3);\n});\n\nTinytest.addAsync(\"ecmascript - runtime - misc support\", (test, done) => {\n  // Verify that the runtime was installed.\n  test.equal(typeof meteorBabelHelpers, \"object\");\n  test.equal(typeof meteorBabelHelpers.sanitizeForInObject, \"function\");\n\n  class Base {\n    constructor(...args) {\n      this.sum = 0;\n      args.forEach(arg => this.sum += arg);\n    }\n\n    static inherited() {\n      return \"inherited\";\n    }\n  }\n\n  class Derived extends Base {\n    constructor() {\n      super(1, 2, 3);\n    }\n  }\n\n  // Check that static methods are inherited.\n  test.equal(Derived.inherited(), \"inherited\");\n\n  const d = new Derived();\n  test.equal(d.sum, 6);\n\n  const expectedError = new Error(\"expected\");\n\n  Promise.resolve(\"working\").then(result => {\n    test.equal(result, \"working\");\n    throw expectedError;\n  }).catch(error => {\n    test.equal(error, expectedError);\n    if (Meteor.isServer) {\n      const Fiber = Npm.require(\"fibers\");\n      // Make sure the Promise polyfill runs callbacks in a Fiber.\n      test.instanceOf(Fiber.current, Fiber);\n    }\n  }).then(done, error => test.exception(error));\n});\n"
  },
  {
    "path": "packages/ecmascript/transpilation-tests.js",
    "content": "// These are tests of Babel's generated output.  Write tests here when a runtime\n// test won't do.  Some tests also serve to catch when Babel changes its output,\n// such as when it changes its runtime helpers!\n\nfunction transform(input) {\n  return Babel.compile(input).code;\n};\n\nfunction contains(haystack, needle) {\n  return haystack.indexOf(needle) >= 0;\n};\n\nTinytest.add(\"ecmascript - transpilation - const\", (test) => {\n  // make sure `const` is turned into `var` (rather than passing\n  // through, such as when you have es6.blockScoping on but\n  // es6.constants off)\n  const output = transform('const x = 5;');\n  test.isFalse(contains(output, 'const'));\n  test.isTrue(contains(output, 'var'));\n});\n\nTinytest.add(\"ecmascript - transpilation - class methods\", (test) => {\n  const output = transform(\n`class Foo {\n  static staticMethod() {\n    return 'classy';\n  }\n\n  prototypeMethod() {\n    return 'prototypical';\n  }\n\n  [computedMethod]() {\n    return 'computed';\n  }\n}`);\n\n  // test that we are in \"loose\" mode and methods of classes are still\n  // assigned in a simple matter that does rely on Object.defineProperty.\n  test.isTrue(contains(output, 'Foo.staticMethod = function staticMethod('));\n  test.isTrue(contains(output,\n                       'Foo.prototype.prototypeMethod = function prototypeMethod('));\n  test.isTrue(contains(output, 'Foo.prototype[computedMethod] = function ('));\n  test.isFalse(contains(output, 'createClass'));\n});\n\nTinytest.add(\"ecmascript - transpilation - helpers - classCallCheck\", (test) => {\n  const output = transform(`\nclass Foo {\n  constructor(x) {\n    this.x = x;\n  }\n}`);\n\n  // test that the classCallCheck helper is still in use\n  test.isTrue(contains(output, 'helpers/classCallCheck'));\n});\n\nTinytest.add(\"ecmascript - transpilation - helpers - inherits\", (test) => {\n  const output = transform(`\nclass Foo {}\nclass Bar extends Foo {}\n`);\n\n  test.isTrue(contains(output, 'helpers/inherits'));\n});\n\nTinytest.add(\"ecmascript - transpilation - helpers - bind\", (test) => {\n  const output = transform(`\n  var foo = new Foo(...oneTwo, 3);\n`);\n\n  test.isTrue(output.match(/\\.bind\\b/));\n});\n\nTinytest.add(\"ecmascript - transpilation - helpers - extends\", (test) => {\n  const output = transform(`\n  var full = {a:1, ...middle, d:4};\n`);\n\n  test.isTrue(contains(output, 'helpers/extends'));\n});\n\nTinytest.add(\"ecmascript - transpilation - helpers - objectWithoutProperties\", (test) => {\n  const output = transform(`\nvar {a, ...rest} = obj;\n`);\n\n  test.isTrue(contains(output, 'helpers/objectWithoutProperties'));\n});\n\nTinytest.add(\"ecmascript - transpilation - helpers - objectDestructuringEmpty\", (test) => {\n  const output = transform(`\nvar {} = null;\n`);\n\n  test.isTrue(contains(output, 'helpers/objectDestructuringEmpty'));\n});\n\nTinytest.add(\"ecmascript - transpilation - helpers - taggedTemplateLiteralLoose\", (test) => {\n  const output = transform(`\nvar x = asdf\\`A\\${foo}C\\`\n`);\n\n  test.isTrue(contains(output, 'helpers/taggedTemplateLiteralLoose'));\n});\n\nTinytest.add(\"ecmascript - transpilation - helpers - createClass\", (test) => {\n  const output = transform(`\nclass Foo {\n  get blah() { return 123; }\n}\n`);\n\n  test.isTrue(contains(output, 'helpers/createClass'));\n});\n\nTinytest.add(\"ecmascript - transpilation - flow\", (test) => {\n  const output = transform(\n    'var foo = function (one: any, two: number, three?): string {};');\n  test.isTrue(contains(output, '(one, two, three)'));\n});\n"
  },
  {
    "path": "packages/ecmascript-runtime/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/ecmascript-runtime/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/ecmascript-runtime/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"meteor-ecmascript-runtime\": {\n      \"version\": \"0.2.6\",\n      \"resolved\": \"https://registry.npmjs.org/meteor-ecmascript-runtime/-/meteor-ecmascript-runtime-0.2.6.tgz\",\n      \"from\": \"https://registry.npmjs.org/meteor-ecmascript-runtime/-/meteor-ecmascript-runtime-0.2.6.tgz\",\n      \"dependencies\": {\n        \"core-js\": {\n          \"version\": \"1.2.1\",\n          \"resolved\": \"https://registry.npmjs.org/core-js/-/core-js-1.2.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/core-js/-/core-js-1.2.1.tgz\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/ecmascript-runtime/README.md",
    "content": "# ecmascript-runtime [![Build Status](https://travis-ci.org/meteor/ecmascript-runtime.svg?branch=master)](https://travis-ci.org/meteor/ecmascript-runtime)\n\nPolyfills for new ECMAScript 2015 APIs like Map and Set\n"
  },
  {
    "path": "packages/ecmascript-runtime/package.js",
    "content": "Package.describe({\n  name: \"ecmascript-runtime\",\n  version: \"0.2.11_1\",\n  summary: \"Polyfills for new ECMAScript 2015 APIs like Map and Set\",\n  git: \"https://github.com/meteor/ecmascript-runtime\",\n  documentation: \"README.md\"\n});\n\nNpm.depends({\n  \"meteor-ecmascript-runtime\": \"0.2.6\",\n});\n\nPackage.onUse(function(api) {\n  // If the es5-shim package is installed, make sure it loads before\n  // ecmascript-runtime, since ecmascript-runtime uses some ES5 APIs like\n  // Object.defineProperties that are buggy in older browsers.\n  api.use(\"es5-shim\", { weak: true });\n\n  api.use(\"modules\");\n  api.use(\"promise\");\n\n  api.mainModule(\"runtime.js\");\n\n  api.export(\"Symbol\");\n  api.export(\"Map\");\n  api.export(\"Set\");\n});\n\nPackage.onTest(function(api) {\n  api.use(\"tinytest\");\n  api.use(\"check\");\n  api.use(\"es5-shim\");\n  api.use(\"ecmascript-runtime\");\n  api.addFiles(\"runtime-tests.js\");\n});\n"
  },
  {
    "path": "packages/ecmascript-runtime/runtime-tests.js",
    "content": "Tinytest.add(\"ecmascript-containers - Map\", function (test) {\n  test.equal(typeof Map, \"function\");\n  var key = {};\n  var map = new Map;\n\n  test.equal(map.entries().next(), {\n    value: undefined,\n    done: true\n  });\n\n  map.set(key, 1234);\n\n  test.equal(map.entries().next(), {\n    value: [key, 1234],\n    done: false\n  });\n});\n\nTinytest.add(\"ecmascript-containers - Set\", function (test) {\n  test.equal(typeof Set, \"function\");\n  var key = {};\n  var set = new Set;\n\n  test.equal(set.values().next(), {\n    value: undefined,\n    done: true\n  });\n\n  set.add(key);\n\n  test.equal(set.values().next(), {\n    value: key,\n    done: false\n  });\n});\n\nTinytest.add(\"core-js - Array\", function (test) {\n  test.equal(Array.from(\"123\", Number), [1, 2, 3]);\n  test.equal(Array.of(1, 3, 5), [1, 3, 5]);\n  test.equal(\n    Array(5).fill(\"oyez\"),\n    [\"oyez\", \"oyez\", \"oyez\", \"oyez\", \"oyez\"]\n  );\n\n  function isOdd(n) {\n    return n % 2;\n  }\n\n  test.equal([2, 3, 4].find(isOdd), 3);\n  test.equal([2, 3, 4].findIndex(isOdd), 1);\n});\n\nTinytest.add(\"core-js - Number\", function () {\n  // Make sure https://github.com/grigio/meteor-babel/issues/5 is not a\n  // problem for us.\n  check(1234, Number);\n});\n\nTinytest.add(\"core-js - Object\", function (test) {\n  test.equal(typeof Object.assign, \"function\");\n  test.equal(typeof Object.is, \"function\");\n  test.equal(typeof Object.setPrototypeOf, \"function\");\n  test.equal(typeof Object.getPrototypeOf, \"function\");\n});\n\nTinytest.add(\"core-js - String\", function (test) {\n  test.equal(typeof \"asdf\".startsWith, \"function\");\n  test.equal(typeof \"asdf\".endsWith, \"function\");\n  test.equal(typeof \"asdf\".repeat, \"function\");\n  test.equal(typeof \"asdf\".trim, \"function\");\n});\n\nTinytest.add(\"core-js - Symbol\", function (test) {\n  test.equal(typeof Symbol, \"function\");\n  test.equal(\n    typeof Array.prototype[Symbol.iterator],\n    \"function\"\n  );\n});\n\nTinytest.add(\"core-js - Function\", function (test) {\n  test.equal(\n    typeof Function.prototype[Symbol.hasInstance],\n    \"function\"\n  );\n\n  function Constructor() {};\n  test.equal(Constructor[Symbol.hasInstance](new Constructor), true);\n  test.equal(Constructor[Symbol.hasInstance]({}), false);\n});\n"
  },
  {
    "path": "packages/ecmascript-runtime/runtime.js",
    "content": "// TODO Allow just api.mainModule(\"meteor-ecmascript-runtime\");\nmodule.exports = require(\"meteor-ecmascript-runtime\");\n"
  },
  {
    "path": "packages/ejson/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/ejson/README.md",
    "content": "# ejson\n\nEJSON is an extension of JSON to support more types. It supports all JSON-safe\ntypes, as well as:\n\n - **Date** - JavaScript `Date`\n - **Binary** - JavaScript `Uint8Array` or the\n   result of [`EJSON.newBinary`](http://docs.meteor.com/#ejson_new_binary)\n - **User-defined types** - see [`EJSON.addType`](http://docs.meteor.com/#ejson_add_type)\n\nAll EJSON serializations are also valid JSON.  For example an object with a date\nand a binary buffer would be serialized in EJSON as:\n\n    {\n      \"d\": {\"$date\": 1358205756553},\n      \"b\": {\"$binary\": \"c3VyZS4=\"}\n    }\n\nFor more details, see the [EJSON section](http://docs.meteor.com/#ejson) of the Meteor docs."
  },
  {
    "path": "packages/ejson/custom_models_for_tests.js",
    "content": "function Address (city, state) {\n  this.city = city;\n  this.state = state;\n}\n\nAddress.prototype = {\n  constructor: Address,\n\n  typeName: function () {\n    return \"Address\";\n  },\n\n  toJSONValue: function () {\n    return {\n      city: this.city,\n      state: this.state\n    };\n  }\n}\n\nEJSON.addType(\"Address\", function fromJSONValue(value) {\n  return new Address(value.city, value.state);\n});\n\nfunction Person (name, dob, address) {\n  this.name = name;\n  this.dob = dob;\n  this.address = address;\n}\n\nPerson.prototype = {\n  constructor: Person,\n\n  typeName: function () {\n    return \"Person\";\n  },\n\n  toJSONValue: function () {\n    return {\n      name: this.name,\n      dob: EJSON.toJSONValue(this.dob),\n      address: EJSON.toJSONValue(this.address)\n    };\n  }\n}\n\n_.extend(Person, {\n  fromJSONValue: function(value) {\n    return new Person(\n      value.name,\n      EJSON.fromJSONValue(value.dob),\n      EJSON.fromJSONValue(value.address)\n    );\n  }\n});\n\nEJSON.addType(\"Person\", Person.fromJSONValue);\n\nfunction Holder (content) {\n  this.content = content;\n}\n\nHolder.prototype = {\n  constructor: Holder,\n\n  typeName: function () {\n    return \"Holder\";\n  },\n\n  toJSONValue: function () {\n    return this.content;\n  }\n}\n\n_.extend(Holder, {\n  fromJSONValue: function(value) {\n    return new Holder(value);\n  }\n});\n\nEJSON.addType(\"Holder\", Holder.fromJSONValue);\n\n_.extend(EJSONTest, {\n  Address: Address,\n  Person: Person,\n  Holder: Holder\n});\n"
  },
  {
    "path": "packages/ejson/ejson.js",
    "content": "/**\n * @namespace\n * @summary Namespace for EJSON functions\n */\nEJSON = {};\nEJSONTest = {};\n\n\n\n// Custom type interface definition\n/**\n * @class CustomType\n * @instanceName customType\n * @memberOf EJSON\n * @summary The interface that a class must satisfy to be able to become an\n * EJSON custom type via EJSON.addType.\n */\n\n/**\n * @function typeName\n * @memberOf EJSON.CustomType\n * @summary Return the tag used to identify this type.  This must match the tag used to register this type with [`EJSON.addType`](#ejson_add_type).\n * @locus Anywhere\n * @instance\n */\n\n/**\n * @function toJSONValue\n * @memberOf EJSON.CustomType\n * @summary Serialize this instance into a JSON-compatible value.\n * @locus Anywhere\n * @instance\n */\n\n/**\n * @function clone\n * @memberOf EJSON.CustomType\n * @summary Return a value `r` such that `this.equals(r)` is true, and modifications to `r` do not affect `this` and vice versa.\n * @locus Anywhere\n * @instance\n */\n\n/**\n * @function equals\n * @memberOf EJSON.CustomType\n * @summary Return `true` if `other` has a value equal to `this`; `false` otherwise.\n * @locus Anywhere\n * @param {Object} other Another object to compare this to.\n * @instance\n */\n\n\nvar customTypes = {};\n// Add a custom type, using a method of your choice to get to and\n// from a basic JSON-able representation.  The factory argument\n// is a function of JSON-able --> your object\n// The type you add must have:\n// - A toJSONValue() method, so that Meteor can serialize it\n// - a typeName() method, to show how to look it up in our type table.\n// It is okay if these methods are monkey-patched on.\n// EJSON.clone will use toJSONValue and the given factory to produce\n// a clone, but you may specify a method clone() that will be\n// used instead.\n// Similarly, EJSON.equals will use toJSONValue to make comparisons,\n// but you may provide a method equals() instead.\n/**\n * @summary Add a custom datatype to EJSON.\n * @locus Anywhere\n * @param {String} name A tag for your custom type; must be unique among custom data types defined in your project, and must match the result of your type's `typeName` method.\n * @param {Function} factory A function that deserializes a JSON-compatible value into an instance of your type.  This should match the serialization performed by your type's `toJSONValue` method.\n */\nEJSON.addType = function (name, factory) {\n  if (_.has(customTypes, name))\n    throw new Error(\"Type \" + name + \" already present\");\n  customTypes[name] = factory;\n};\n\nvar isInfOrNan = function (obj) {\n  return _.isNaN(obj) || obj === Infinity || obj === -Infinity;\n};\n\nvar builtinConverters = [\n  { // Date\n    matchJSONValue: function (obj) {\n      return _.has(obj, '$date') && _.size(obj) === 1;\n    },\n    matchObject: function (obj) {\n      return obj instanceof Date;\n    },\n    toJSONValue: function (obj) {\n      return {$date: obj.getTime()};\n    },\n    fromJSONValue: function (obj) {\n      return new Date(obj.$date);\n    }\n  },\n  { // NaN, Inf, -Inf. (These are the only objects with typeof !== 'object'\n    // which we match.)\n    matchJSONValue: function (obj) {\n      return _.has(obj, '$InfNaN') && _.size(obj) === 1;\n    },\n    matchObject: isInfOrNan,\n    toJSONValue: function (obj) {\n      var sign;\n      if (_.isNaN(obj))\n        sign = 0;\n      else if (obj === Infinity)\n        sign = 1;\n      else\n        sign = -1;\n      return {$InfNaN: sign};\n    },\n    fromJSONValue: function (obj) {\n      return obj.$InfNaN/0;\n    }\n  },\n  { // Binary\n    matchJSONValue: function (obj) {\n      return _.has(obj, '$binary') && _.size(obj) === 1;\n    },\n    matchObject: function (obj) {\n      return typeof Uint8Array !== 'undefined' && obj instanceof Uint8Array\n        || (obj && _.has(obj, '$Uint8ArrayPolyfill'));\n    },\n    toJSONValue: function (obj) {\n      return {$binary: Base64.encode(obj)};\n    },\n    fromJSONValue: function (obj) {\n      return Base64.decode(obj.$binary);\n    }\n  },\n  { // Escaping one level\n    matchJSONValue: function (obj) {\n      return _.has(obj, '$escape') && _.size(obj) === 1;\n    },\n    matchObject: function (obj) {\n      if (_.isEmpty(obj) || _.size(obj) > 2) {\n        return false;\n      }\n      return _.any(builtinConverters, function (converter) {\n        return converter.matchJSONValue(obj);\n      });\n    },\n    toJSONValue: function (obj) {\n      var newObj = {};\n      _.each(obj, function (value, key) {\n        newObj[key] = EJSON.toJSONValue(value);\n      });\n      return {$escape: newObj};\n    },\n    fromJSONValue: function (obj) {\n      var newObj = {};\n      _.each(obj.$escape, function (value, key) {\n        newObj[key] = EJSON.fromJSONValue(value);\n      });\n      return newObj;\n    }\n  },\n  { // Custom\n    matchJSONValue: function (obj) {\n      return _.has(obj, '$type') && _.has(obj, '$value') && _.size(obj) === 2;\n    },\n    matchObject: function (obj) {\n      return EJSON._isCustomType(obj);\n    },\n    toJSONValue: function (obj) {\n      var jsonValue = Meteor._noYieldsAllowed(function () {\n        return obj.toJSONValue();\n      });\n      return {$type: obj.typeName(), $value: jsonValue};\n    },\n    fromJSONValue: function (obj) {\n      var typeName = obj.$type;\n      if (!_.has(customTypes, typeName))\n        throw new Error(\"Custom EJSON type \" + typeName + \" is not defined\");\n      var converter = customTypes[typeName];\n      return Meteor._noYieldsAllowed(function () {\n        return converter(obj.$value);\n      });\n    }\n  }\n];\n\nEJSON._isCustomType = function (obj) {\n  return obj &&\n    typeof obj.toJSONValue === 'function' &&\n    typeof obj.typeName === 'function' &&\n    _.has(customTypes, obj.typeName());\n};\n\nEJSON._getTypes = function () {\n  return customTypes;\n};\n\nEJSON._getConverters = function () {\n  return builtinConverters;\n};\n\n// for both arrays and objects, in-place modification.\nvar adjustTypesToJSONValue =\nEJSON._adjustTypesToJSONValue = function (obj) {\n  // Is it an atom that we need to adjust?\n  if (obj === null)\n    return null;\n  var maybeChanged = toJSONValueHelper(obj);\n  if (maybeChanged !== undefined)\n    return maybeChanged;\n\n  // Other atoms are unchanged.\n  if (typeof obj !== 'object')\n    return obj;\n\n  // Iterate over array or object structure.\n  _.each(obj, function (value, key) {\n    if (typeof value !== 'object' && value !== undefined &&\n        !isInfOrNan(value))\n      return; // continue\n\n    var changed = toJSONValueHelper(value);\n    if (changed) {\n      obj[key] = changed;\n      return; // on to the next key\n    }\n    // if we get here, value is an object but not adjustable\n    // at this level.  recurse.\n    adjustTypesToJSONValue(value);\n  });\n  return obj;\n};\n\n// Either return the JSON-compatible version of the argument, or undefined (if\n// the item isn't itself replaceable, but maybe some fields in it are)\nvar toJSONValueHelper = function (item) {\n  for (var i = 0; i < builtinConverters.length; i++) {\n    var converter = builtinConverters[i];\n    if (converter.matchObject(item)) {\n      return converter.toJSONValue(item);\n    }\n  }\n  return undefined;\n};\n\n/**\n * @summary Serialize an EJSON-compatible value into its plain JSON representation.\n * @locus Anywhere\n * @param {EJSON} val A value to serialize to plain JSON.\n */\nEJSON.toJSONValue = function (item) {\n  var changed = toJSONValueHelper(item);\n  if (changed !== undefined)\n    return changed;\n  if (typeof item === 'object') {\n    item = EJSON.clone(item);\n    adjustTypesToJSONValue(item);\n  }\n  return item;\n};\n\n// for both arrays and objects. Tries its best to just\n// use the object you hand it, but may return something\n// different if the object you hand it itself needs changing.\n//\nvar adjustTypesFromJSONValue =\nEJSON._adjustTypesFromJSONValue = function (obj) {\n  if (obj === null)\n    return null;\n  var maybeChanged = fromJSONValueHelper(obj);\n  if (maybeChanged !== obj)\n    return maybeChanged;\n\n  // Other atoms are unchanged.\n  if (typeof obj !== 'object')\n    return obj;\n\n  _.each(obj, function (value, key) {\n    if (typeof value === 'object') {\n      var changed = fromJSONValueHelper(value);\n      if (value !== changed) {\n        obj[key] = changed;\n        return;\n      }\n      // if we get here, value is an object but not adjustable\n      // at this level.  recurse.\n      adjustTypesFromJSONValue(value);\n    }\n  });\n  return obj;\n};\n\n// Either return the argument changed to have the non-json\n// rep of itself (the Object version) or the argument itself.\n\n// DOES NOT RECURSE.  For actually getting the fully-changed value, use\n// EJSON.fromJSONValue\nvar fromJSONValueHelper = function (value) {\n  if (typeof value === 'object' && value !== null) {\n    if (_.size(value) <= 2\n        && _.all(value, function (v, k) {\n          return typeof k === 'string' && k.substr(0, 1) === '$';\n        })) {\n      for (var i = 0; i < builtinConverters.length; i++) {\n        var converter = builtinConverters[i];\n        if (converter.matchJSONValue(value)) {\n          return converter.fromJSONValue(value);\n        }\n      }\n    }\n  }\n  return value;\n};\n\n/**\n * @summary Deserialize an EJSON value from its plain JSON representation.\n * @locus Anywhere\n * @param {JSONCompatible} val A value to deserialize into EJSON.\n */\nEJSON.fromJSONValue = function (item) {\n  var changed = fromJSONValueHelper(item);\n  if (changed === item && typeof item === 'object') {\n    item = EJSON.clone(item);\n    adjustTypesFromJSONValue(item);\n    return item;\n  } else {\n    return changed;\n  }\n};\n\n/**\n * @summary Serialize a value to a string.\n\nFor EJSON values, the serialization fully represents the value. For non-EJSON values, serializes the same way as `JSON.stringify`.\n * @locus Anywhere\n * @param {EJSON} val A value to stringify.\n * @param {Object} [options]\n * @param {Boolean | Integer | String} options.indent Indents objects and arrays for easy readability.  When `true`, indents by 2 spaces; when an integer, indents by that number of spaces; and when a string, uses the string as the indentation pattern.\n * @param {Boolean} options.canonical When `true`, stringifies keys in an object in sorted order.\n */\nEJSON.stringify = function (item, options) {\n  var json = EJSON.toJSONValue(item);\n  if (options && (options.canonical || options.indent)) {\n    return EJSON._canonicalStringify(json, options);\n  } else {\n    return JSON.stringify(json);\n  }\n};\n\n/**\n * @summary Parse a string into an EJSON value. Throws an error if the string is not valid EJSON.\n * @locus Anywhere\n * @param {String} str A string to parse into an EJSON value.\n */\nEJSON.parse = function (item) {\n  if (typeof item !== 'string')\n    throw new Error(\"EJSON.parse argument should be a string\");\n  return EJSON.fromJSONValue(JSON.parse(item));\n};\n\n/**\n * @summary Returns true if `x` is a buffer of binary data, as returned from [`EJSON.newBinary`](#ejson_new_binary).\n * @param {Object} x The variable to check.\n * @locus Anywhere\n */\nEJSON.isBinary = function (obj) {\n  return !!((typeof Uint8Array !== 'undefined' && obj instanceof Uint8Array) ||\n    (obj && obj.$Uint8ArrayPolyfill));\n};\n\n/**\n * @summary Return true if `a` and `b` are equal to each other.  Return false otherwise.  Uses the `equals` method on `a` if present, otherwise performs a deep comparison.\n * @locus Anywhere\n * @param {EJSON} a\n * @param {EJSON} b\n * @param {Object} [options]\n * @param {Boolean} options.keyOrderSensitive Compare in key sensitive order, if supported by the JavaScript implementation.  For example, `{a: 1, b: 2}` is equal to `{b: 2, a: 1}` only when `keyOrderSensitive` is `false`.  The default is `false`.\n */\nEJSON.equals = function (a, b, options) {\n  var i;\n  var keyOrderSensitive = !!(options && options.keyOrderSensitive);\n  if (a === b)\n    return true;\n  if (_.isNaN(a) && _.isNaN(b))\n    return true; // This differs from the IEEE spec for NaN equality, b/c we don't want\n                 // anything ever with a NaN to be poisoned from becoming equal to anything.\n  if (!a || !b) // if either one is falsy, they'd have to be === to be equal\n    return false;\n  if (!(typeof a === 'object' && typeof b === 'object'))\n    return false;\n  if (a instanceof Date && b instanceof Date)\n    return a.valueOf() === b.valueOf();\n  if (EJSON.isBinary(a) && EJSON.isBinary(b)) {\n    if (a.length !== b.length)\n      return false;\n    for (i = 0; i < a.length; i++) {\n      if (a[i] !== b[i])\n        return false;\n    }\n    return true;\n  }\n  if (typeof (a.equals) === 'function')\n    return a.equals(b, options);\n  if (typeof (b.equals) === 'function')\n    return b.equals(a, options);\n  if (a instanceof Array) {\n    if (!(b instanceof Array))\n      return false;\n    if (a.length !== b.length)\n      return false;\n    for (i = 0; i < a.length; i++) {\n      if (!EJSON.equals(a[i], b[i], options))\n        return false;\n    }\n    return true;\n  }\n  // fallback for custom types that don't implement their own equals\n  switch (EJSON._isCustomType(a) + EJSON._isCustomType(b)) {\n    case 1: return false;\n    case 2: return EJSON.equals(EJSON.toJSONValue(a), EJSON.toJSONValue(b));\n  }\n  // fall back to structural equality of objects\n  var ret;\n  if (keyOrderSensitive) {\n    var bKeys = [];\n    _.each(b, function (val, x) {\n        bKeys.push(x);\n    });\n    i = 0;\n    ret = _.all(a, function (val, x) {\n      if (i >= bKeys.length) {\n        return false;\n      }\n      if (x !== bKeys[i]) {\n        return false;\n      }\n      if (!EJSON.equals(val, b[bKeys[i]], options)) {\n        return false;\n      }\n      i++;\n      return true;\n    });\n    return ret && i === bKeys.length;\n  } else {\n    i = 0;\n    ret = _.all(a, function (val, key) {\n      if (!_.has(b, key)) {\n        return false;\n      }\n      if (!EJSON.equals(val, b[key], options)) {\n        return false;\n      }\n      i++;\n      return true;\n    });\n    return ret && _.size(b) === i;\n  }\n};\n\n/**\n * @summary Return a deep copy of `val`.\n * @locus Anywhere\n * @param {EJSON} val A value to copy.\n */\nEJSON.clone = function (v) {\n  var ret;\n  if (typeof v !== \"object\")\n    return v;\n  if (v === null)\n    return null; // null has typeof \"object\"\n  if (v instanceof Date)\n    return new Date(v.getTime());\n  // RegExps are not really EJSON elements (eg we don't define a serialization\n  // for them), but they're immutable anyway, so we can support them in clone.\n  if (v instanceof RegExp)\n    return v;\n  if (EJSON.isBinary(v)) {\n    ret = EJSON.newBinary(v.length);\n    for (var i = 0; i < v.length; i++) {\n      ret[i] = v[i];\n    }\n    return ret;\n  }\n  // XXX: Use something better than underscore's isArray\n  if (_.isArray(v) || _.isArguments(v)) {\n    // For some reason, _.map doesn't work in this context on Opera (weird test\n    // failures).\n    ret = [];\n    for (i = 0; i < v.length; i++)\n      ret[i] = EJSON.clone(v[i]);\n    return ret;\n  }\n  // handle general user-defined typed Objects if they have a clone method\n  if (typeof v.clone === 'function') {\n    return v.clone();\n  }\n  // handle other custom types\n  if (EJSON._isCustomType(v)) {\n    return EJSON.fromJSONValue(EJSON.clone(EJSON.toJSONValue(v)), true);\n  }\n  // handle other objects\n  ret = {};\n  _.each(v, function (value, key) {\n    ret[key] = EJSON.clone(value);\n  });\n  return ret;\n};\n\n/**\n * @summary Allocate a new buffer of binary data that EJSON can serialize.\n * @locus Anywhere\n * @param {Number} size The number of bytes of binary data to allocate.\n */\n// EJSON.newBinary is the public documented API for this functionality,\n// but the implementation is in the 'base64' package to avoid\n// introducing a circular dependency. (If the implementation were here,\n// then 'base64' would have to use EJSON.newBinary, and 'ejson' would\n// also have to use 'base64'.)\nEJSON.newBinary = Base64.newBinary;\n"
  },
  {
    "path": "packages/ejson/ejson_test.js",
    "content": "Tinytest.add(\"ejson - keyOrderSensitive\", function (test) {\n  test.isTrue(EJSON.equals({\n    a: {b: 1, c: 2},\n    d: {e: 3, f: 4}\n  }, {\n    d: {f: 4, e: 3},\n    a: {c: 2, b: 1}\n  }));\n\n  test.isFalse(EJSON.equals({\n    a: {b: 1, c: 2},\n    d: {e: 3, f: 4}\n  }, {\n    d: {f: 4, e: 3},\n    a: {c: 2, b: 1}\n  }, {keyOrderSensitive: true}));\n\n  test.isFalse(EJSON.equals({\n    a: {b: 1, c: 2},\n    d: {e: 3, f: 4}\n  }, {\n    a: {c: 2, b: 1},\n    d: {f: 4, e: 3}\n  }, {keyOrderSensitive: true}));\n  test.isFalse(EJSON.equals({a: {}}, {a: {b:2}}, {keyOrderSensitive: true}));\n  test.isFalse(EJSON.equals({a: {b:2}}, {a: {}}, {keyOrderSensitive: true}));\n});\n\nTinytest.add(\"ejson - nesting and literal\", function (test) {\n  var d = new Date;\n  var obj = {$date: d};\n  var eObj = EJSON.toJSONValue(obj);\n  var roundTrip = EJSON.fromJSONValue(eObj);\n  test.equal(obj, roundTrip);\n});\n\nTinytest.add(\"ejson - some equality tests\", function (test) {\n  test.isTrue(EJSON.equals({a: 1, b: 2, c: 3}, {a: 1, c: 3, b: 2}));\n  test.isFalse(EJSON.equals({a: 1, b: 2}, {a: 1, c: 3, b: 2}));\n  test.isFalse(EJSON.equals({a: 1, b: 2, c: 3}, {a: 1, b: 2}));\n  test.isFalse(EJSON.equals({a: 1, b: 2, c: 3}, {a: 1, c: 3, b: 4}));\n  test.isFalse(EJSON.equals({a: {}}, {a: {b:2}}));\n  test.isFalse(EJSON.equals({a: {b:2}}, {a: {}}));\n});\n\nTinytest.add(\"ejson - equality and falsiness\", function (test) {\n  test.isTrue(EJSON.equals(null, null));\n  test.isTrue(EJSON.equals(undefined, undefined));\n  test.isFalse(EJSON.equals({foo: \"foo\"}, null));\n  test.isFalse(EJSON.equals(null, {foo: \"foo\"}));\n  test.isFalse(EJSON.equals(undefined, {foo: \"foo\"}));\n  test.isFalse(EJSON.equals({foo: \"foo\"}, undefined));\n});\n\nTinytest.add(\"ejson - NaN and Inf\", function (test) {\n  test.equal(EJSON.parse(\"{\\\"$InfNaN\\\": 1}\"), Infinity);\n  test.equal(EJSON.parse(\"{\\\"$InfNaN\\\": -1}\"), -Infinity);\n  test.isTrue(_.isNaN(EJSON.parse(\"{\\\"$InfNaN\\\": 0}\")));\n  test.equal(EJSON.parse(EJSON.stringify(Infinity)), Infinity);\n  test.equal(EJSON.parse(EJSON.stringify(-Infinity)), -Infinity);\n  test.isTrue(_.isNaN(EJSON.parse(EJSON.stringify(NaN))));\n  test.isTrue(EJSON.equals(NaN, NaN));\n  test.isTrue(EJSON.equals(Infinity, Infinity));\n  test.isTrue(EJSON.equals(-Infinity, -Infinity));\n  test.isFalse(EJSON.equals(Infinity, -Infinity));\n  test.isFalse(EJSON.equals(Infinity, NaN));\n  test.isFalse(EJSON.equals(Infinity, 0));\n  test.isFalse(EJSON.equals(NaN, 0));\n\n  test.isTrue(EJSON.equals(\n    EJSON.parse(\"{\\\"a\\\": {\\\"$InfNaN\\\": 1}}\"),\n    {a: Infinity}\n  ));\n  test.isTrue(EJSON.equals(\n    EJSON.parse(\"{\\\"a\\\": {\\\"$InfNaN\\\": 0}}\"),\n    {a: NaN}\n  ));\n});\n\nTinytest.add(\"ejson - clone\", function (test) {\n  var cloneTest = function (x, identical) {\n    var y = EJSON.clone(x);\n    test.isTrue(EJSON.equals(x, y));\n    test.equal(x === y, !!identical);\n  };\n  cloneTest(null, true);\n  cloneTest(undefined, true);\n  cloneTest(42, true);\n  cloneTest(\"asdf\", true);\n  cloneTest([1, 2, 3]);\n  cloneTest([1, \"fasdf\", {foo: 42}]);\n  cloneTest({x: 42, y: \"asdf\"});\n\n  var testCloneArgs = function (/*arguments*/) {\n    var clonedArgs = EJSON.clone(arguments);\n    test.equal(clonedArgs, [1, 2, \"foo\", [4]]);\n  };\n  testCloneArgs(1, 2, \"foo\", [4]);\n});\n\nTinytest.add(\"ejson - stringify\", function (test) {\n  test.equal(EJSON.stringify(null), \"null\");\n  test.equal(EJSON.stringify(true), \"true\");\n  test.equal(EJSON.stringify(false), \"false\");\n  test.equal(EJSON.stringify(123), \"123\");\n  test.equal(EJSON.stringify(\"abc\"), \"\\\"abc\\\"\");\n\n  test.equal(EJSON.stringify([1, 2, 3]),\n     \"[1,2,3]\"\n  );\n  test.equal(EJSON.stringify([1, 2, 3], {indent: true}),\n    \"[\\n  1,\\n  2,\\n  3\\n]\"\n  );\n  test.equal(EJSON.stringify([1, 2, 3], {canonical: false}),\n    \"[1,2,3]\"\n  );\n  test.equal(EJSON.stringify([1, 2, 3], {indent: true, canonical: false}),\n    \"[\\n  1,\\n  2,\\n  3\\n]\"\n  );\n\n  test.equal(EJSON.stringify([1, 2, 3], {indent: 4}),\n    \"[\\n    1,\\n    2,\\n    3\\n]\"\n  );\n  test.equal(EJSON.stringify([1, 2, 3], {indent: '--'}),\n    \"[\\n--1,\\n--2,\\n--3\\n]\"\n  );\n\n  test.equal(\n    EJSON.stringify(\n      {b: [2, {d: 4, c: 3}], a: 1},\n      {canonical: true}\n    ),\n    \"{\\\"a\\\":1,\\\"b\\\":[2,{\\\"c\\\":3,\\\"d\\\":4}]}\"\n  );\n  test.equal(\n    EJSON.stringify(\n      {b: [2, {d: 4, c: 3}], a: 1},\n      {\n        indent: true,\n        canonical: true\n      }\n    ),\n    \"{\\n\" +\n    \"  \\\"a\\\": 1,\\n\" +\n    \"  \\\"b\\\": [\\n\" +\n    \"    2,\\n\" +\n    \"    {\\n\" +\n    \"      \\\"c\\\": 3,\\n\" +\n    \"      \\\"d\\\": 4\\n\" +\n    \"    }\\n\" +\n    \"  ]\\n\" +\n    \"}\"\n  );\n  test.equal(\n    EJSON.stringify(\n      {b: [2, {d: 4, c: 3}], a: 1},\n      {canonical: false}\n    ),\n    \"{\\\"b\\\":[2,{\\\"d\\\":4,\\\"c\\\":3}],\\\"a\\\":1}\"\n  );\n  test.equal(\n    EJSON.stringify(\n      {b: [2, {d: 4, c: 3}], a: 1},\n      {indent: true, canonical: false}\n    ),\n    \"{\\n\" +\n    \"  \\\"b\\\": [\\n\" +\n    \"    2,\\n\" +\n    \"    {\\n\" +\n    \"      \\\"d\\\": 4,\\n\" +\n    \"      \\\"c\\\": 3\\n\" +\n    \"    }\\n\" +\n    \"  ],\\n\" +\n    \"  \\\"a\\\": 1\\n\" +\n    \"}\"\n\n  );\n});\n\nTinytest.add(\"ejson - parse\", function (test) {\n  test.equal(EJSON.parse(\"[1,2,3]\"), [1,2,3]);\n  test.throws(\n    function () { EJSON.parse(null) },\n    /argument should be a string/\n  );\n});\n\nTinytest.add(\"ejson - custom types\", function (test) {\n  var testSameConstructors = function (obj, compareWith) {\n    test.equal(obj.constructor, compareWith.constructor);\n    if (typeof obj === 'object') {\n      _.each(obj, function(value, key) {\n        testSameConstructors(value, compareWith[key]);\n      });\n    }\n  }\n  var testReallyEqual = function (obj, compareWith) {\n    test.equal(obj, compareWith);\n    testSameConstructors(obj, compareWith);\n  }\n  var testRoundTrip = function (obj) {\n    var str = EJSON.stringify(obj);\n    var roundTrip = EJSON.parse(str);\n    testReallyEqual(obj, roundTrip);\n  }\n  var testCustomObject = function (obj) {\n    testRoundTrip(obj);\n    testReallyEqual(obj, EJSON.clone(obj));\n  }\n\n  var a = new EJSONTest.Address('Montreal', 'Quebec');\n  testCustomObject( {address: a} );\n  // Test that difference is detected even if they\n  // have similar toJSONValue results:\n  var nakedA = {city: 'Montreal', state: 'Quebec'};\n  test.notEqual(nakedA, a);\n  test.notEqual(a, nakedA);\n  var holder = new EJSONTest.Holder(nakedA);\n  test.equal(holder.toJSONValue(), a.toJSONValue()); // sanity check\n  test.notEqual(holder, a);\n  test.notEqual(a, holder);\n\n\n  var d = new Date;\n  var obj = new EJSONTest.Person(\"John Doe\", d, a);\n  testCustomObject( obj );\n\n  // Test clone is deep:\n  var clone = EJSON.clone(obj);\n  clone.address.city = 'Sherbrooke';\n  test.notEqual( obj, clone );\n});\n"
  },
  {
    "path": "packages/ejson/package.js",
    "content": "Package.describe({\n  summary: \"Extended and Extensible JSON library\",\n  version: '1.0.12'\n});\n\nPackage.onUse(function (api) {\n  api.use(['underscore', 'base64']);\n  api.export('EJSON');\n  api.export('EJSONTest', {testOnly: true});\n  api.addFiles('ejson.js', ['client', 'server']);\n  api.addFiles('stringify.js', ['client', 'server']);\n});\n\nPackage.onTest(function (api) {\n  api.use('ejson', ['client', 'server']);\n  api.use(['tinytest', 'underscore']);\n\n  api.addFiles('custom_models_for_tests.js', ['client', 'server']);\n  api.addFiles('ejson_test.js', ['client', 'server']);\n});\n"
  },
  {
    "path": "packages/ejson/stringify.js",
    "content": "// Based on json2.js from https://github.com/douglascrockford/JSON-js\n//\n//    json2.js\n//    2012-10-08\n//\n//    Public Domain.\n//\n//    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n\nfunction quote(string) {\n  return JSON.stringify(string);\n}\n\nvar str = function (key, holder, singleIndent, outerIndent, canonical) {\n\n  // Produce a string from holder[key].\n\n  var i;          // The loop counter.\n  var k;          // The member key.\n  var v;          // The member value.\n  var length;\n  var innerIndent = outerIndent;\n  var partial;\n  var value = holder[key];\n\n  // What happens next depends on the value's type.\n\n  switch (typeof value) {\n  case 'string':\n    return quote(value);\n  case 'number':\n    // JSON numbers must be finite. Encode non-finite numbers as null.\n    return isFinite(value) ? String(value) : 'null';\n  case 'boolean':\n    return String(value);\n  // If the type is 'object', we might be dealing with an object or an array or\n  // null.\n  case 'object':\n    // Due to a specification blunder in ECMAScript, typeof null is 'object',\n    // so watch out for that case.\n    if (!value) {\n      return 'null';\n    }\n    // Make an array to hold the partial results of stringifying this object value.\n    innerIndent = outerIndent + singleIndent;\n    partial = [];\n\n    // Is the value an array?\n    if (_.isArray(value) || _.isArguments(value)) {\n\n      // The value is an array. Stringify every element. Use null as a placeholder\n      // for non-JSON values.\n\n      length = value.length;\n      for (i = 0; i < length; i += 1) {\n        partial[i] = str(i, value, singleIndent, innerIndent, canonical) || 'null';\n      }\n\n      // Join all of the elements together, separated with commas, and wrap them in\n      // brackets.\n\n      if (partial.length === 0) {\n        v = '[]';\n      } else if (innerIndent) {\n        v = '[\\n' + innerIndent + partial.join(',\\n' + innerIndent) + '\\n' + outerIndent + ']';\n      } else {\n        v = '[' + partial.join(',') + ']';\n      }\n      return v;\n    }\n\n\n    // Iterate through all of the keys in the object.\n    var keys = _.keys(value);\n    if (canonical)\n      keys = keys.sort();\n    _.each(keys, function (k) {\n      v = str(k, value, singleIndent, innerIndent, canonical);\n      if (v) {\n        partial.push(quote(k) + (innerIndent ? ': ' : ':') + v);\n      }\n    });\n\n\n    // Join all of the member texts together, separated with commas,\n    // and wrap them in braces.\n\n    if (partial.length === 0) {\n      v = '{}';\n    } else if (innerIndent) {\n      v = '{\\n' + innerIndent + partial.join(',\\n' + innerIndent) + '\\n' + outerIndent + '}';\n    } else {\n      v = '{' + partial.join(',') + '}';\n    }\n    return v;\n  }\n}\n\n// If the JSON object does not yet have a stringify method, give it one.\n\nEJSON._canonicalStringify = function (value, options) {\n  // Make a fake root object containing our value under the key of ''.\n  // Return the result of stringifying the value.\n  options = _.extend({\n    indent: \"\",\n    canonical: false\n  }, options);\n  if (options.indent === true) {\n    options.indent = \"  \";\n  } else if (typeof options.indent === 'number') {\n    var newIndent = \"\";\n    for (var i = 0; i < options.indent; i++) {\n      newIndent += ' ';\n    }\n    options.indent = newIndent;\n  }\n  return str('', {'': value}, options.indent, \"\", options.canonical);\n};\n"
  },
  {
    "path": "packages/email/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/email/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/email/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/email/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"mailcomposer\": {\n      \"version\": \"0.1.15\",\n      \"resolved\": \"https://registry.npmjs.org/mailcomposer/-/mailcomposer-0.1.15.tgz\",\n      \"from\": \"https://registry.npmjs.org/mailcomposer/-/mailcomposer-0.1.15.tgz\",\n      \"dependencies\": {\n        \"mimelib-noiconv\": {\n          \"version\": \"0.1.9\",\n          \"resolved\": \"https://registry.npmjs.org/mimelib-noiconv/-/mimelib-noiconv-0.1.9.tgz\",\n          \"from\": \"https://registry.npmjs.org/mimelib-noiconv/-/mimelib-noiconv-0.1.9.tgz\"\n        }\n      }\n    },\n    \"simplesmtp\": {\n      \"version\": \"0.3.10\",\n      \"resolved\": \"https://registry.npmjs.org/simplesmtp/-/simplesmtp-0.3.10.tgz\",\n      \"from\": \"https://registry.npmjs.org/simplesmtp/-/simplesmtp-0.3.10.tgz\",\n      \"dependencies\": {\n        \"rai\": {\n          \"version\": \"0.1.7\",\n          \"resolved\": \"https://registry.npmjs.org/rai/-/rai-0.1.7.tgz\",\n          \"from\": \"https://registry.npmjs.org/rai/-/rai-0.1.7.tgz\"\n        },\n        \"xoauth2\": {\n          \"version\": \"0.1.8\",\n          \"resolved\": \"https://registry.npmjs.org/xoauth2/-/xoauth2-0.1.8.tgz\",\n          \"from\": \"https://registry.npmjs.org/xoauth2/-/xoauth2-0.1.8.tgz\"\n        }\n      }\n    },\n    \"stream-buffers\": {\n      \"version\": \"0.2.5\",\n      \"resolved\": \"https://registry.npmjs.org/stream-buffers/-/stream-buffers-0.2.5.tgz\",\n      \"from\": \"https://registry.npmjs.org/stream-buffers/-/stream-buffers-0.2.5.tgz\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/email/README.md",
    "content": "# email\n\nThe `email` package allows sending email from a Meteor app.\n\nTo see how to use it, read the [`email` section](http://docs.meteor.com/#email) of the Meteor docs."
  },
  {
    "path": "packages/email/email.js",
    "content": "var Future = Npm.require('fibers/future');\nvar urlModule = Npm.require('url');\n\nEmail = {};\nEmailTest = {};\n\nEmailInternals = {\n  NpmModules: {\n    mailcomposer: {\n      version: Npm.require('mailcomposer/package.json').version,\n      module: Npm.require('mailcomposer')\n    }\n  }\n};\n\nvar MailComposer = EmailInternals.NpmModules.mailcomposer.module.MailComposer;\n\nvar makePool = function (mailUrlString) {\n  var mailUrl = urlModule.parse(mailUrlString);\n  if (mailUrl.protocol !== 'smtp:' && mailUrl.protocol !== 'smtps:')\n    throw new Error(\"Email protocol in $MAIL_URL (\" +\n                    mailUrlString + \") must be 'smtp' or 'smtps'\");\n\n  var port = +(mailUrl.port);\n  var auth = false;\n  if (mailUrl.auth) {\n    var parts = mailUrl.auth.split(':', 2);\n    auth = {user: parts[0],\n            pass: parts[1]};\n  }\n\n  var simplesmtp = Npm.require('simplesmtp');\n  var pool = simplesmtp.createClientPool(\n    port,  // Defaults to 25\n    mailUrl.hostname,  // Defaults to \"localhost\"\n    { secureConnection: (port === 465) || (mailUrl.protocol === 'smtps:'),\n      // XXX allow maxConnections to be configured?\n      auth: auth });\n\n  pool._future_wrapped_sendMail = _.bind(Future.wrap(pool.sendMail), pool);\n  return pool;\n};\n\nvar getPool = function() {\n  // We delay this check until the first call to Email.send, in case someone\n  // set process.env.MAIL_URL in startup code. Then we store in a cache until\n  // process.env.MAIL_URL changes.\n  var url = process.env.MAIL_URL;\n  if (this.cacheKey === undefined || this.cacheKey !== url) {\n    this.cacheKey = url;\n    this.cache = url ? makePool(url) : null;\n  }\n  return this.cache;\n}\n\nvar next_devmode_mail_id = 0;\nvar output_stream = process.stdout;\n\n// Testing hooks\nEmailTest.overrideOutputStream = function (stream) {\n  next_devmode_mail_id = 0;\n  output_stream = stream;\n};\n\nEmailTest.restoreOutputStream = function () {\n  output_stream = process.stdout;\n};\n\nvar devModeSend = function (mc) {\n  var devmode_mail_id = next_devmode_mail_id++;\n\n  var stream = output_stream;\n\n  // This approach does not prevent other writers to stdout from interleaving.\n  stream.write(\"====== BEGIN MAIL #\" + devmode_mail_id + \" ======\\n\");\n  stream.write(\"(Mail not sent; to enable sending, set the MAIL_URL \" +\n               \"environment variable.)\\n\");\n  mc.streamMessage();\n  mc.pipe(stream, {end: false});\n  var future = new Future;\n  mc.on('end', function () {\n    stream.write(\"====== END MAIL #\" + devmode_mail_id + \" ======\\n\");\n    future['return']();\n  });\n  future.wait();\n};\n\nvar smtpSend = function (pool, mc) {\n  pool._future_wrapped_sendMail(mc).wait();\n};\n\n/**\n * Mock out email sending (eg, during a test.) This is private for now.\n *\n * f receives the arguments to Email.send and should return true to go\n * ahead and send the email (or at least, try subsequent hooks), or\n * false to skip sending.\n */\nvar sendHooks = [];\nEmailTest.hookSend = function (f) {\n  sendHooks.push(f);\n};\n\n// Old comment below\n/**\n * Send an email.\n *\n * Connects to the mail server configured via the MAIL_URL environment\n * variable. If unset, prints formatted message to stdout. The \"from\" option\n * is required, and at least one of \"to\", \"cc\", and \"bcc\" must be provided;\n * all other options are optional.\n *\n * @param options\n * @param options.from {String} RFC5322 \"From:\" address\n * @param options.to {String|String[]} RFC5322 \"To:\" address[es]\n * @param options.cc {String|String[]} RFC5322 \"Cc:\" address[es]\n * @param options.bcc {String|String[]} RFC5322 \"Bcc:\" address[es]\n * @param options.replyTo {String|String[]} RFC5322 \"Reply-To:\" address[es]\n * @param options.subject {String} RFC5322 \"Subject:\" line\n * @param options.text {String} RFC5322 mail body (plain text)\n * @param options.html {String} RFC5322 mail body (HTML)\n * @param options.headers {Object} custom RFC5322 headers (dictionary)\n */\n\n// New API doc comment below\n/**\n * @summary Send an email. Throws an `Error` on failure to contact mail server\n * or if mail server returns an error. All fields should match\n * [RFC5322](http://tools.ietf.org/html/rfc5322) specification.\n *\n * If the `MAIL_URL` environment variable is set, actually sends the email.\n * Otherwise, prints the contents of the email to standard out.\n *\n * Note that this package is based on mailcomposer version `0.1.15`, so make\n * sure to refer to the documentation for that version if using the\n * `attachments` or `mailComposer` options.\n * [Click here to read the mailcomposer 0.1.15 docs](https://github.com/andris9/mailcomposer/blob/7c0422b2de2dc61a60ba27cfa3353472f662aeb5/README.md).\n *\n * @locus Server\n * @param {Object} options\n * @param {String} options.from \"From:\" address (required)\n * @param {String|String[]} options.to,cc,bcc,replyTo\n *   \"To:\", \"Cc:\", \"Bcc:\", and \"Reply-To:\" addresses\n * @param {String} [options.subject]  \"Subject:\" line\n * @param {String} [options.text|html] Mail body (in plain text and/or HTML)\n * @param {Object} [options.headers] Dictionary of custom headers\n * @param {Object[]} [options.attachments] Array of attachment objects, as\n * described in the [mailcomposer documentation](https://github.com/andris9/mailcomposer/blob/7c0422b2de2dc61a60ba27cfa3353472f662aeb5/README.md#add-attachments).\n * @param {MailComposer} [options.mailComposer] A [MailComposer](https://github.com/andris9/mailcomposer)\n * object representing the message to be sent. Overrides all other options. You\n * can access the `mailcomposer` npm module at\n * `EmailInternals.NpmModules.mailcomposer.module`.\n */\nEmail.send = function (options) {\n  for (var i = 0; i < sendHooks.length; i++)\n    if (! sendHooks[i](options))\n      return;\n\n  var mc;\n  if (options.mailComposer) {\n    mc = options.mailComposer;\n  } else {\n    mc = new MailComposer();\n\n    // setup message data\n    mc.setMessageOption({\n      from: options.from,\n      to: options.to,\n      cc: options.cc,\n      bcc: options.bcc,\n      replyTo: options.replyTo,\n      subject: options.subject,\n      text: options.text,\n      html: options.html\n    });\n\n    _.each(options.headers, function (value, name) {\n      mc.addHeader(name, value);\n    });\n\n    if (!options.headers || !options.headers.hasOwnProperty('Date')) {\n      mc.addHeader('Date', new Date().toUTCString().replace(/GMT/, '+0000'));\n    }\n\n    _.each(options.attachments, function(attachment){\n      mc.addAttachment(attachment);\n    });\n  }\n\n  var pool = getPool();\n  if (pool) {\n    smtpSend(pool, mc);\n  } else {\n    devModeSend(mc);\n  }\n};\n"
  },
  {
    "path": "packages/email/email_tests.js",
    "content": "var streamBuffers = Npm.require('stream-buffers');\n\nvar devWarningBanner = \"(Mail not sent; to enable \" +\n  \"sending, set the MAIL_URL environment variable.)\\n\";\n\nfunction smokeEmailTest(testFunction) {\n  // This only tests dev mode, so don't run the test if this is deployed.\n  if (process.env.MAIL_URL) return;\n\n  try {\n    var stream = new streamBuffers.WritableStreamBuffer;\n    EmailTest.overrideOutputStream(stream);\n\n    testFunction(stream);\n\n  } finally {\n    EmailTest.restoreOutputStream();\n  }\n}\n\nTinytest.add(\"email - fully customizable\", function (test) {\n  smokeEmailTest(function(stream) {\n    Email.send({\n      from: \"foo@example.com\",\n      to: \"bar@example.com\",\n      cc: [\"friends@example.com\", \"enemies@example.com\"],\n      subject: \"This is the subject\",\n      text: \"This is the body\\nof the message\\nFrom us.\",\n      headers: {\n        'X-Meteor-Test': 'a custom header',\n        'Date': 'dummy',\n      },\n    });\n    // XXX brittle if mailcomposer changes header order, etc\n    test.equal(stream.getContentsAsString(\"utf8\"),\n               \"====== BEGIN MAIL #0 ======\\n\" +\n               devWarningBanner +\n               \"MIME-Version: 1.0\\r\\n\" +\n               \"X-Meteor-Test: a custom header\\r\\n\" +\n               \"Date: dummy\\r\\n\" +\n               \"From: foo@example.com\\r\\n\" +\n               \"To: bar@example.com\\r\\n\" +\n               \"Cc: friends@example.com, enemies@example.com\\r\\n\" +\n               \"Subject: This is the subject\\r\\n\" +\n               \"Content-Type: text/plain; charset=utf-8\\r\\n\" +\n               \"Content-Transfer-Encoding: quoted-printable\\r\\n\" +\n               \"\\r\\n\" +\n               \"This is the body\\r\\n\" +\n               \"of the message\\r\\n\" +\n               \"From us.\\r\\n\" +\n               \"====== END MAIL #0 ======\\n\");\n  });\n});\n\nTinytest.add(\"email - undefined headers sends properly\", function (test) {\n  smokeEmailTest(function (stream) {\n    Email.send({\n      from: \"foo@example.com\",\n      to: \"bar@example.com\",\n      subject: \"This is the subject\",\n      text: \"This is the body\\nof the message\\nFrom us.\",\n    });\n\n    test.matches(stream.getContentsAsString(\"utf8\"),\n      /^====== BEGIN MAIL #0 ======$[\\s\\S]+^To: bar@example.com$/m);\n  });\n});\n\nTinytest.add(\"email - multiple e-mails same stream\", function (test) {\n  smokeEmailTest(function (stream) {\n    // Test if date header is automaticall generated, if not specified\n    Email.send({\n      from: \"foo@example.com\",\n      to: \"bar@example.com\",\n      subject: \"This is the subject\",\n      text: \"This is the body\\nof the message\\nFrom us.\",\n    });\n\n    var contents;\n\n    contents = stream.getContentsAsString(\"utf8\");\n    test.matches(contents, /^====== BEGIN MAIL #0 ======$/m);\n    test.matches(contents, /^From: foo@example.com$/m);\n    test.matches(contents, /^To: bar@example.com$/m);\n\n    Email.send({\n      from: \"qux@example.com\",\n      to: \"baz@example.com\",\n      subject: \"This is important\",\n      text: \"This is another message\\nFrom Qux.\",\n    });\n\n    contents = stream.getContentsAsString(\"utf8\");\n    test.matches(contents, /^====== BEGIN MAIL #1 ======$/m);\n    test.matches(contents, /^From: qux@example.com$/m);\n    test.matches(contents, /^To: baz@example.com$/m);\n\n  });\n});\n\nTinytest.add(\"email - using mail composer\", function (test) {\n  smokeEmailTest(function (stream) {\n    // Test direct MailComposer usage.\n    var mc = new EmailInternals.NpmModules.mailcomposer.module.MailComposer;\n    mc.setMessageOption({\n      from: \"a@b.com\",\n      text: \"body\"\n    });\n    Email.send({mailComposer: mc});\n    test.equal(stream.getContentsAsString(\"utf8\"),\n               \"====== BEGIN MAIL #0 ======\\n\" +\n               devWarningBanner +\n               \"MIME-Version: 1.0\\r\\n\" +\n               \"From: a@b.com\\r\\n\" +\n               \"Content-Type: text/plain; charset=utf-8\\r\\n\" +\n               \"Content-Transfer-Encoding: quoted-printable\\r\\n\" +\n               \"\\r\\n\" +\n               \"body\\r\\n\" +\n               \"====== END MAIL #0 ======\\n\");\n  });\n});\n\nTinytest.add(\"email - date auto generated\", function (test) {\n  smokeEmailTest(function (stream) {\n    // Test if date header is automaticall generated, if not specified\n    Email.send({\n      from: \"foo@example.com\",\n      to: \"bar@example.com\",\n      subject: \"This is the subject\",\n      text: \"This is the body\\nof the message\\nFrom us.\",\n      headers: {\n        'X-Meteor-Test': 'a custom header',\n      },\n    });\n\n    test.matches(stream.getContentsAsString(\"utf8\"),\n                 /^Date: .+$/m);\n  });\n});\n"
  },
  {
    "path": "packages/email/package.js",
    "content": "Package.describe({\n  summary: \"Send email messages\",\n  version: \"1.0.14_1\"\n});\n\nNpm.depends({\n  // Pinned at older version. 0.1.16+ uses mimelib, not mimelib-noiconv which is\n  // much bigger. We need a better solution.\n  mailcomposer: \"0.1.15\",\n  simplesmtp: \"0.3.10\",\n  \"stream-buffers\": \"0.2.5\"});\n\nPackage.onUse(function (api) {\n  api.use('underscore', 'server');\n  api.export(['Email', 'EmailInternals'], 'server');\n  api.export('EmailTest', 'server', {testOnly: true});\n  api.addFiles('email.js', 'server');\n});\n\nPackage.onTest(function (api) {\n  api.use('email', 'server');\n  api.use('tinytest');\n  api.addFiles('email_tests.js', 'server');\n});\n"
  },
  {
    "path": "packages/es5-shim/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/es5-shim/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/es5-shim/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"es5-shim\": {\n      \"version\": \"4.5.7\",\n      \"resolved\": \"https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.7.tgz\",\n      \"from\": \"https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.7.tgz\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/es5-shim/README.md",
    "content": "# es5-shim\n\nThis package improves ECMAScript 5 compliance in all browers, particularly older browsers, and especially Internet Explorer 8 (and earlier).\n\nLike the `ecmascript` package, `es5-shim` is [installed by default](https://github.com/meteor/meteor/blob/22bd755918/tools/static-assets/skel/.meteor/packages#L11) for all new apps. Though it technically can be removed, the expectation is that it will only be removed if the app author wishes to install an equivalent package instead (e.g. something based on [`core-js`](https://github.com/zloirock/core-js)), or wishes to drop support for older browsers altogether.\n\nGiven these assumptions, as of Meteor 1.2, packages may safely begin to rely on ES5 features that are patched or polyfilled by `es5-shim`. Packages are discouraged from depending directly on `es5-shim`, however, as that would make it considerably more difficult for app authors to remove or replace the package.\n"
  },
  {
    "path": "packages/es5-shim/client.js",
    "content": "require(\"./import_globals.js\");\nrequire(\"es5-shim/es5-shim.js\");\nrequire(\"es5-shim/es5-sham.js\");\nrequire(\"./console.js\");\nrequire(\"./export_globals.js\");\n"
  },
  {
    "path": "packages/es5-shim/console.js",
    "content": "var hasOwn = Object.prototype.hasOwnProperty;\n\nfunction wrap(method) {\n  var original = console[method];\n  if (original && typeof original === \"object\") {\n    // Turn callable console method objects into actual functions.\n    console[method] = function () {\n      return Function.prototype.apply.call(\n        original, console, arguments\n      );\n    };\n  }\n}\n\nif (typeof console === \"object\" &&\n    // In older Internet Explorers, methods like console.log are actually\n    // callable objects rather than functions.\n    typeof console.log === \"object\") {\n  for (var method in console) {\n    // In most browsers, this hasOwn check will fail for all console\n    // methods anyway, but fortunately in IE8 the method objects we care\n    // about are own properties.\n    if (hasOwn.call(console, method)) {\n      wrap(method);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/es5-shim/export_globals.js",
    "content": "if (global.Date !== Date) {\n  global.Date = Date;\n}\n\nif (global.parseInt !== parseInt) {\n  global.parseInt = parseInt;\n}\n\nif (global.parseFloat !== parseFloat) {\n  global.parseFloat = parseFloat;\n}\n\nvar Sp = String.prototype;\nif (Sp.replace !== originalStringReplace) {\n  // Restore the original value of String#replace, because the es5-shim\n  // reimplementation is buggy. See also import_globals.js.\n  Sp.replace = originalStringReplace;\n}\n"
  },
  {
    "path": "packages/es5-shim/import_globals.js",
    "content": "// Because the es5-{shim,sham}.js code assigns to Date and parseInt,\n// Meteor treats them as package variables, and so declares them as\n// variables in package scope, which causes some references to Date and\n// parseInt in the shim/sham code to refer to those undefined package\n// variables. The simplest solution seems to be to initialize the package\n// variables to their appropriate global values.\nDate = global.Date;\nparseInt = global.parseInt;\nparseFloat = global.parseFloat;\n\n// Save the original String#replace method, because es5-shim's\n// reimplementation of it causes problems in markdown/showdown.js.\n// This original method will be restored in export_globals.js.\noriginalStringReplace = String.prototype.replace;\n"
  },
  {
    "path": "packages/es5-shim/package.js",
    "content": "Package.describe({\n  name: \"es5-shim\",\n  version: \"4.5.12_1\",\n  summary: \"Shims and polyfills to improve ECMAScript 5 support\",\n  documentation: \"README.md\"\n});\n\nNpm.depends({\n  \"es5-shim\": \"4.5.7\"\n});\n\nPackage.onUse(function(api) {\n  api.use(\"modules\");\n  api.mainModule(\"client.js\", \"client\");\n  api.mainModule(\"server.js\", \"server\");\n});\n"
  },
  {
    "path": "packages/es5-shim/server.js",
    "content": "require(\"./import_globals.js\");\nrequire(\"es5-shim/es5-shim.js\");\nrequire(\"./export_globals.js\");\n"
  },
  {
    "path": "packages/facebook/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/facebook/README.md",
    "content": "# facebook\n\nAn implementation of the Facebook OAuth flow. See the [project page](https://www.meteor.com/accounts) on Meteor Accounts for more details. XXX link"
  },
  {
    "path": "packages/facebook/facebook_client.js",
    "content": "Facebook = {};\n\n// Request Facebook credentials for the user\n//\n// @param options {optional}\n// @param credentialRequestCompleteCallback {Function} Callback function to call on\n//   completion. Takes one argument, credentialToken on success, or Error on\n//   error.\nFacebook.requestCredential = function (options, credentialRequestCompleteCallback) {\n  // support both (options, callback) and (callback).\n  if (!credentialRequestCompleteCallback && typeof options === 'function') {\n    credentialRequestCompleteCallback = options;\n    options = {};\n  }\n\n  var config = ServiceConfiguration.configurations.findOne({service: 'facebook'});\n  if (!config) {\n    credentialRequestCompleteCallback && credentialRequestCompleteCallback(\n      new ServiceConfiguration.ConfigError());\n    return;\n  }\n\n  var credentialToken = Random.secret();\n  var mobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i.test(navigator.userAgent);\n  var display = mobile ? 'touch' : 'popup';\n\n  var scope = \"email\";\n  if (options && options.requestPermissions)\n    scope = options.requestPermissions.join(',');\n\n  var loginStyle = OAuth._loginStyle('facebook', config, options);\n\n  var loginUrl =\n        'https://www.facebook.com/v2.2/dialog/oauth?client_id=' + config.appId +\n        '&redirect_uri=' + OAuth._redirectUri('facebook', config) +\n        '&display=' + display + '&scope=' + scope +\n        '&state=' + OAuth._stateParam(loginStyle, credentialToken, options && options.redirectUrl);\n\n  // Handle authentication type (e.g. for force login you need authType: \"reauthenticate\")\n  if (options && options.authType) {\n    loginUrl += \"&authType=\" + encodeURIComponent(options.authType);\n  }\n\n  OAuth.launchLogin({\n    loginService: \"facebook\",\n    loginStyle: loginStyle,\n    loginUrl: loginUrl,\n    credentialRequestCompleteCallback: credentialRequestCompleteCallback,\n    credentialToken: credentialToken\n  });\n};\n"
  },
  {
    "path": "packages/facebook/facebook_configure.html",
    "content": "<template name=\"configureLoginServiceDialogForFacebook\">\n  <p>\n    First, you'll need to register your app on Facebook. Follow these steps:\n  </p>\n  <ol>\n    <li>\n      Visit <a href=\"https://developers.facebook.com/apps\" target=\"_blank\">https://developers.facebook.com/apps</a>\n    </li>\n    <li>\n      Click \"Add a New App\".\n    </li>\n    <li>\n      Select \"Website\" and type a name for your app.\n    </li>\n    <li>\n      Click \"Create New Facebook App ID\".\n    </li>\n    <li>\n      Select a category in the dropdown and click \"Create App ID\".\n    </li>\n    <li>\n      Under \"Tell us about your website\", set Site URL to: <span class=\"url\">{{siteUrl}}</span> and click \"Next\".\n    </li>\n    <li>\n      Click \"Skip to Developer Dashboard\".\n    </li>\n    <li>\n      Go to the \"Settings\" tab and add an email address under \"Contact Email\". Click \"Save Changes\".\n    </li>\n    <li>\n      Go to the \"Status & Review\" tab and select Yes for \"Do you want to make this app and\n      all its live features available to the general public?\". Click \"Confirm\".\n    </li>\n    <li>\n      Go back to the Dashboard tab.\n    </li>\n  </ol>\n</template>\n"
  },
  {
    "path": "packages/facebook/facebook_configure.js",
    "content": "Template.configureLoginServiceDialogForFacebook.helpers({\n  siteUrl: function () {\n    return Meteor.absoluteUrl();\n  }\n});\n\nTemplate.configureLoginServiceDialogForFacebook.fields = function () {\n  return [\n    {property: 'appId', label: 'App ID'},\n    {property: 'secret', label: 'App Secret'}\n  ];\n};\n"
  },
  {
    "path": "packages/facebook/facebook_server.js",
    "content": "Facebook = {};\n\nvar querystring = Npm.require('querystring');\n\n\nOAuth.registerService('facebook', 2, null, function(query) {\n\n  var response = getTokenResponse(query);\n  var accessToken = response.accessToken;\n\n  // include all fields from facebook\n  // http://developers.facebook.com/docs/reference/login/public-profile-and-friend-list/\n  var whitelisted = ['id', 'email', 'name', 'first_name',\n      'last_name', 'link', 'gender', 'locale', 'age_range'];\n\n  var identity = getIdentity(accessToken, whitelisted);\n\n  var serviceData = {\n    accessToken: accessToken,\n    expiresAt: (+new Date) + (1000 * response.expiresIn)\n  };\n\n\n  var fields = _.pick(identity, whitelisted);\n  _.extend(serviceData, fields);\n\n  return {\n    serviceData: serviceData,\n    options: {profile: {name: identity.name}}\n  };\n});\n\n// checks whether a string parses as JSON\nvar isJSON = function (str) {\n  try {\n    JSON.parse(str);\n    return true;\n  } catch (e) {\n    return false;\n  }\n};\n\n// returns an object containing:\n// - accessToken\n// - expiresIn: lifetime of token in seconds\nvar getTokenResponse = function (query) {\n  var config = ServiceConfiguration.configurations.findOne({service: 'facebook'});\n  if (!config)\n    throw new ServiceConfiguration.ConfigError();\n\n  var responseContent;\n  try {\n    // Request an access token\n    responseContent = HTTP.get(\n      \"https://graph.facebook.com/v2.2/oauth/access_token\", {\n        params: {\n          client_id: config.appId,\n          redirect_uri: OAuth._redirectUri('facebook', config),\n          client_secret: OAuth.openSecret(config.secret),\n          code: query.code\n        }\n      }).content;\n  } catch (err) {\n    throw _.extend(new Error(\"Failed to complete OAuth handshake with Facebook. \" + err.message),\n                   {response: err.response});\n  }\n\n  // If 'responseContent' parses as JSON, it is an error.\n  // XXX which facebook error causes this behvaior?\n  if (isJSON(responseContent)) {\n    throw new Error(\"Failed to complete OAuth handshake with Facebook. \" + responseContent);\n  }\n\n  // Success!  Extract the facebook access token and expiration\n  // time from the response\n  var parsedResponse = querystring.parse(responseContent);\n  var fbAccessToken = parsedResponse.access_token;\n  var fbExpires = parsedResponse.expires;\n\n  if (!fbAccessToken) {\n    throw new Error(\"Failed to complete OAuth handshake with facebook \" +\n                    \"-- can't find access token in HTTP response. \" + responseContent);\n  }\n  return {\n    accessToken: fbAccessToken,\n    expiresIn: fbExpires\n  };\n};\n\nvar getIdentity = function (accessToken, fields) {\n  try {\n    return HTTP.get(\"https://graph.facebook.com/v2.4/me\", {\n      params: {\n        access_token: accessToken,\n        fields: fields\n      }\n    }).data;\n  } catch (err) {\n    throw _.extend(new Error(\"Failed to fetch identity from Facebook. \" + err.message),\n                   {response: err.response});\n  }\n};\n\nFacebook.retrieveCredential = function(credentialToken, credentialSecret) {\n  return OAuth.retrieveCredential(credentialToken, credentialSecret);\n};\n"
  },
  {
    "path": "packages/facebook/package.js",
    "content": "Package.describe({\n  summary: \"Facebook OAuth flow\",\n  version: \"1.2.8\"\n});\n\nPackage.onUse(function(api) {\n  api.use('oauth2', ['client', 'server']);\n  api.use('oauth', ['client', 'server']);\n  api.use('http', ['server']);\n  api.use('templating', 'client');\n  api.use('underscore', 'server');\n  api.use('random', 'client');\n  api.use('service-configuration', ['client', 'server']);\n\n  api.export('Facebook');\n\n  api.addFiles(\n    ['facebook_configure.html', 'facebook_configure.js'],\n    'client');\n\n  api.addFiles('facebook_server.js', 'server');\n  api.addFiles('facebook_client.js', 'client');\n});\n"
  },
  {
    "path": "packages/facts/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/facts/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/facts/facts.html",
    "content": "<template name='serverFacts'>\n  <ul>\n    {{#each factsByPackage}}\n      <li>{{ _id }}\n        <dl>\n          {{#each facts}}\n            <dt>{{ name }}</dt>\n            <dd>{{ value }}</dd>\n          {{/each}}\n        </dl>\n      </li>\n    {{/each}}\n  </ul>\n</template>\n"
  },
  {
    "path": "packages/facts/facts.js",
    "content": "Facts = {};\n\nvar serverFactsCollection = 'meteor_Facts_server';\n\nif (Meteor.isServer) {\n  // By default, we publish facts to no user if autopublish is off, and to all\n  // users if autopublish is on.\n  var userIdFilter = function (userId) {\n    return !!Package.autopublish;\n  };\n\n  // XXX make this take effect at runtime too?\n  Facts.setUserIdFilter = function (filter) {\n    userIdFilter = filter;\n  };\n\n  // XXX Use a minimongo collection instead and hook up an observeChanges\n  // directly to a publish.\n  var factsByPackage = {};\n  var activeSubscriptions = [];\n\n  // Make factsByPackage data available to the server environment\n  Facts._factsByPackage = factsByPackage;\n\n  Facts.incrementServerFact = function (pkg, fact, increment) {\n    if (!_.has(factsByPackage, pkg)) {\n      factsByPackage[pkg] = {};\n      factsByPackage[pkg][fact] = increment;\n      _.each(activeSubscriptions, function (sub) {\n        sub.added(serverFactsCollection, pkg, factsByPackage[pkg]);\n      });\n      return;\n    }\n\n    var packageFacts = factsByPackage[pkg];\n    if (!_.has(packageFacts, fact))\n      factsByPackage[pkg][fact] = 0;\n    factsByPackage[pkg][fact] += increment;\n    var changedField = {};\n    changedField[fact] = factsByPackage[pkg][fact];\n    _.each(activeSubscriptions, function (sub) {\n      sub.changed(serverFactsCollection, pkg, changedField);\n    });\n  };\n\n  // Deferred, because we have an unordered dependency on livedata.\n  // XXX is this safe? could somebody try to connect before Meteor.publish is\n  // called?\n  Meteor.defer(function () {\n    // XXX Also publish facts-by-package.\n    Meteor.publish(\"meteor_facts\", function () {\n      var sub = this;\n      if (!userIdFilter(this.userId)) {\n        sub.ready();\n        return;\n      }\n      activeSubscriptions.push(sub);\n      _.each(factsByPackage, function (facts, pkg) {\n        sub.added(serverFactsCollection, pkg, facts);\n      });\n      sub.onStop(function () {\n        activeSubscriptions = _.without(activeSubscriptions, sub);\n      });\n      sub.ready();\n    }, {is_auto: true});\n  });\n} else {\n  Facts.server = new Mongo.Collection(serverFactsCollection);\n\n  Template.serverFacts.helpers({\n    factsByPackage: function () {\n      return Facts.server.find();\n    },\n    facts: function () {\n      var factArray = [];\n      _.each(this, function (value, name) {\n        if (name !== '_id')\n          factArray.push({name: name, value: value});\n      });\n      return factArray;\n    }\n  });\n\n  // Subscribe when the template is first made, and unsubscribe when it\n  // is removed. If for some reason puts two copies of the template on\n  // the screen at once, we'll subscribe twice. Meh.\n  Template.serverFacts.onCreated(function () {\n    this._stopHandle = Meteor.subscribe(\"meteor_facts\");\n  });\n  Template.serverFacts.onDestroyed(function () {\n    if (this._stopHandle) {\n      this._stopHandle.stop();\n      this._stopHandle = null;\n    }\n  });\n}\n"
  },
  {
    "path": "packages/facts/package.js",
    "content": "Package.describe({\n  summary: \"Publish internal app statistics\",\n  version: '1.0.8'\n});\n\nPackage.onUse(function (api) {\n  api.use(['underscore'], ['client', 'server']);\n  api.use(['templating', 'mongo', 'ddp'], ['client']);\n\n  // Detect whether autopublish is used.\n  api.use('autopublish', 'server', {weak: true});\n\n  // Unordered dependency on livedata, since livedata has a (weak) dependency on\n  // us.\n  api.use('ddp', 'server', {unordered: true});\n\n  api.addFiles('facts.html', ['client']);\n  api.addFiles('facts.js', ['client', 'server']);\n\n  api.export('Facts');\n});\n"
  },
  {
    "path": "packages/fastclick/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/fastclick/README.md",
    "content": "# fastclick\n\nFastClick is a simple, easy-to-use library for eliminating the 300ms delay\nbetween a physical tap and the firing of a `click` event on mobile browsers. The\naim is to make your application feel less laggy and more responsive while\navoiding any interference with your current logic.\n\nFastClick is developed by [FT Labs](http://labs.ft.com/), part of the Financial\nTimes.\n\nFor more info see the original repo:\n[ftlabs/fastclick](https://github.com/ftlabs/fastclick).\n\n\nThis package is included by default on all Meteor Phonegap/Cordova apps. If you\nwould like to use Fastclick for mobile web as well, add it to your app directly\nwith `meteor add fastclick`.\n\nIn case you want to disable FastClick for certain elements, you can add the\n`needsclick` class as described in the [advanced section](https://github.com/ftlabs/fastclick#ignore-certain-elements-with-needsclick)\nof the FastClick documentation:\n\n```html\n<a class=\"needsclick\">Ignored by FastClick</a>\n```\n"
  },
  {
    "path": "packages/fastclick/fastclick.js",
    "content": "\t/**\n\t * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs.\n\t *\n\t * @codingstandard ftlabs-jsv2\n\t * @copyright The Financial Times Limited [All Rights Reserved]\n\t * @license MIT License (see LICENSE.txt)\n\t */\n\n\t/*jslint browser:true, node:true*/\n\t/*global define, Event, Node*/\n\n\n\t/**\n\t * Instantiate fast-clicking listeners on the specified layer.\n\t *\n\t * @constructor\n\t * @param {Element} layer The layer to listen on\n\t * @param {Object} [options={}] The options to override the defaults\n\t */\n\tfunction FastClick(layer, options) {\n    'use strict';\n\t\tvar oldOnClick;\n\n\t\toptions = options || {};\n\n\t\t/**\n\t\t * Whether a click is currently being tracked.\n\t\t *\n\t\t * @type boolean\n\t\t */\n\t\tthis.trackingClick = false;\n\n\n\t\t/**\n\t\t * Timestamp for when click tracking started.\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.trackingClickStart = 0;\n\n\n\t\t/**\n\t\t * The element being tracked for a click.\n\t\t *\n\t\t * @type EventTarget\n\t\t */\n\t\tthis.targetElement = null;\n\n\n\t\t/**\n\t\t * X-coordinate of touch start event.\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.touchStartX = 0;\n\n\n\t\t/**\n\t\t * Y-coordinate of touch start event.\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.touchStartY = 0;\n\n\n\t\t/**\n\t\t * ID of the last touch, retrieved from Touch.identifier.\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.lastTouchIdentifier = 0;\n\n\n\t\t/**\n\t\t * Touchmove boundary, beyond which a click will be cancelled.\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.touchBoundary = options.touchBoundary || 10;\n\n\n\t\t/**\n\t\t * The FastClick layer.\n\t\t *\n\t\t * @type Element\n\t\t */\n\t\tthis.layer = layer;\n\n\t\t/**\n\t\t * The minimum time between tap(touchstart and touchend) events\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.tapDelay = options.tapDelay || 200;\n\n\t\t/**\n\t\t * The maximum time for a tap\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.tapTimeout = options.tapTimeout || 700;\n\n\t\tif (FastClick.notNeeded(layer)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Some old versions of Android don't have Function.prototype.bind\n\t\tfunction bind(method, context) {\n\t\t\treturn function() { return method.apply(context, arguments); };\n\t\t}\n\n\n\t\tvar methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];\n\t\tvar context = this;\n\t\tfor (var i = 0, l = methods.length; i < l; i++) {\n\t\t\tcontext[methods[i]] = bind(context[methods[i]], context);\n\t\t}\n\n\t\t// Set up event handlers as required\n\t\tif (deviceIsAndroid) {\n\t\t\tlayer.addEventListener('mouseover', this.onMouse, true);\n\t\t\tlayer.addEventListener('mousedown', this.onMouse, true);\n\t\t\tlayer.addEventListener('mouseup', this.onMouse, true);\n\t\t}\n\n\t\tlayer.addEventListener('click', this.onClick, true);\n\t\tlayer.addEventListener('touchstart', this.onTouchStart, false);\n\t\tlayer.addEventListener('touchmove', this.onTouchMove, false);\n\t\tlayer.addEventListener('touchend', this.onTouchEnd, false);\n\t\tlayer.addEventListener('touchcancel', this.onTouchCancel, false);\n\n\t\t// Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)\n\t\t// which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick\n\t\t// layer when they are cancelled.\n\t\tif (!Event.prototype.stopImmediatePropagation) {\n\t\t\tlayer.removeEventListener = function(type, callback, capture) {\n\t\t\t\tvar rmv = Node.prototype.removeEventListener;\n\t\t\t\tif (type === 'click') {\n\t\t\t\t\trmv.call(layer, type, callback.hijacked || callback, capture);\n\t\t\t\t} else {\n\t\t\t\t\trmv.call(layer, type, callback, capture);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tlayer.addEventListener = function(type, callback, capture) {\n\t\t\t\tvar adv = Node.prototype.addEventListener;\n\t\t\t\tif (type === 'click') {\n\t\t\t\t\tadv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {\n\t\t\t\t\t\tif (!event.propagationStopped) {\n\t\t\t\t\t\t\tcallback(event);\n\t\t\t\t\t\t}\n\t\t\t\t\t}), capture);\n\t\t\t\t} else {\n\t\t\t\t\tadv.call(layer, type, callback, capture);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t// If a handler is already declared in the element's onclick attribute, it will be fired before\n\t\t// FastClick's onClick handler. Fix this by pulling out the user-defined handler function and\n\t\t// adding it as listener.\n\t\tif (typeof layer.onclick === 'function') {\n\n\t\t\t// Android browser on at least 3.2 requires a new reference to the function in layer.onclick\n\t\t\t// - the old one won't work if passed to addEventListener directly.\n\t\t\toldOnClick = layer.onclick;\n\t\t\tlayer.addEventListener('click', function(event) {\n\t\t\t\toldOnClick(event);\n\t\t\t}, false);\n\t\t\tlayer.onclick = null;\n\t\t}\n\t}\n\n\t/**\n\t* Windows Phone 8.1 fakes user agent string to look like Android and iPhone.\n\t*\n\t* @type boolean\n\t*/\n\tvar deviceIsWindowsPhone = navigator.userAgent.indexOf(\"Windows Phone\") >= 0;\n\n\t/**\n\t * Android requires exceptions.\n\t *\n\t * @type boolean\n\t */\n\tvar deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone;\n\n\n\t/**\n\t * iOS requires exceptions.\n\t *\n\t * @type boolean\n\t */\n\tvar deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone;\n\n\n\t/**\n\t * iOS 4 requires an exception for select elements.\n\t *\n\t * @type boolean\n\t */\n\tvar deviceIsIOS4 = deviceIsIOS && (/OS 4_\\d(_\\d)?/).test(navigator.userAgent);\n\n\n\t/**\n\t * iOS 6.0-7.* requires the target element to be manually derived\n\t *\n\t * @type boolean\n\t */\n\tvar deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\\d/).test(navigator.userAgent);\n\n\t/**\n\t * BlackBerry requires exceptions.\n\t *\n\t * @type boolean\n\t */\n\tvar deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0;\n\n\t/**\n\t * Determine whether a given element requires a native click.\n\t *\n\t * @param {EventTarget|Element} target Target DOM element\n\t * @returns {boolean} Returns true if the element needs a native click\n\t */\n\tFastClick.prototype.needsClick = function(target) {\n\t\tswitch (target.nodeName.toLowerCase()) {\n\n\t\t// Don't send a synthetic click to disabled inputs (issue #62)\n\t\tcase 'button':\n\t\tcase 'select':\n\t\tcase 'textarea':\n\t\t\tif (target.disabled) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tbreak;\n\t\tcase 'input':\n\n\t\t\t// File inputs need real clicks on iOS 6 due to a browser bug (issue #68)\n\t\t\tif ((deviceIsIOS && target.type === 'file') || target.disabled) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tbreak;\n\t\tcase 'label':\n\t\tcase 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames\n\t\tcase 'video':\n\t\t\treturn true;\n\t\t}\n\n\t\treturn (/\\bneedsclick\\b/).test(target.className);\n\t};\n\n\n\t/**\n\t * Determine whether a given element requires a call to focus to simulate click into element.\n\t *\n\t * @param {EventTarget|Element} target Target DOM element\n\t * @returns {boolean} Returns true if the element requires a call to focus to simulate native click.\n\t */\n\tFastClick.prototype.needsFocus = function(target) {\n\t\tswitch (target.nodeName.toLowerCase()) {\n\t\tcase 'textarea':\n\t\t\treturn true;\n\t\tcase 'select':\n\t\t\treturn !deviceIsAndroid;\n\t\tcase 'input':\n\t\t\tswitch (target.type) {\n\t\t\tcase 'button':\n\t\t\tcase 'checkbox':\n\t\t\tcase 'file':\n\t\t\tcase 'image':\n\t\t\tcase 'radio':\n\t\t\tcase 'submit':\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// No point in attempting to focus disabled inputs\n\t\t\treturn !target.disabled && !target.readOnly;\n\t\tdefault:\n\t\t\treturn (/\\bneedsfocus\\b/).test(target.className);\n\t\t}\n\t};\n\n\n\t/**\n\t * Send a click event to the specified element.\n\t *\n\t * @param {EventTarget|Element} targetElement\n\t * @param {Event} event\n\t */\n\tFastClick.prototype.sendClick = function(targetElement, event) {\n\t\tvar clickEvent, touch;\n\n\t\t// On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24)\n\t\tif (document.activeElement && document.activeElement !== targetElement) {\n\t\t\tdocument.activeElement.blur();\n\t\t}\n\n\t\ttouch = event.changedTouches[0];\n\n\t\t// Synthesise a click event, with an extra attribute so it can be tracked\n\t\tclickEvent = document.createEvent('MouseEvents');\n\t\tclickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);\n\t\tclickEvent.forwardedTouchEvent = true;\n\t\ttargetElement.dispatchEvent(clickEvent);\n\t};\n\n\tFastClick.prototype.determineEventType = function(targetElement) {\n\n\t\t//Issue #159: Android Chrome Select Box does not open with a synthetic click event\n\t\tif (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {\n\t\t\treturn 'mousedown';\n\t\t}\n\n\t\treturn 'click';\n\t};\n\n\n\t/**\n\t * @param {EventTarget|Element} targetElement\n\t */\n\tFastClick.prototype.focus = function(targetElement) {\n\t\tvar length;\n\n\t\t// Issue #160: on iOS 7, some input elements (e.g. date datetime month) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724.\n\t\tif (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month') {\n\t\t\tlength = targetElement.value.length;\n\t\t\ttargetElement.setSelectionRange(length, length);\n\t\t} else {\n\t\t\ttargetElement.focus();\n\t\t}\n\t};\n\n\n\t/**\n\t * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it.\n\t *\n\t * @param {EventTarget|Element} targetElement\n\t */\n\tFastClick.prototype.updateScrollParent = function(targetElement) {\n\t\tvar scrollParent, parentElement;\n\n\t\tscrollParent = targetElement.fastClickScrollParent;\n\n\t\t// Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the\n\t\t// target element was moved to another parent.\n\t\tif (!scrollParent || !scrollParent.contains(targetElement)) {\n\t\t\tparentElement = targetElement;\n\t\t\tdo {\n\t\t\t\tif (parentElement.scrollHeight > parentElement.offsetHeight) {\n\t\t\t\t\tscrollParent = parentElement;\n\t\t\t\t\ttargetElement.fastClickScrollParent = parentElement;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tparentElement = parentElement.parentElement;\n\t\t\t} while (parentElement);\n\t\t}\n\n\t\t// Always update the scroll top tracker if possible.\n\t\tif (scrollParent) {\n\t\t\tscrollParent.fastClickLastScrollTop = scrollParent.scrollTop;\n\t\t}\n\t};\n\n\n\t/**\n\t * @param {EventTarget} targetElement\n\t * @returns {Element|EventTarget}\n\t */\n\tFastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {\n\n\t\t// On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node.\n\t\tif (eventTarget.nodeType === Node.TEXT_NODE) {\n\t\t\treturn eventTarget.parentNode;\n\t\t}\n\n\t\treturn eventTarget;\n\t};\n\n\n\t/**\n\t * On touch start, record the position and scroll offset.\n\t *\n\t * @param {Event} event\n\t * @returns {boolean}\n\t */\n\tFastClick.prototype.onTouchStart = function(event) {\n\t\tvar targetElement, touch, selection;\n\n\t\t// Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111).\n\t\tif (event.targetTouches.length > 1) {\n\t\t\treturn true;\n\t\t}\n\n\t\ttargetElement = this.getTargetElementFromEventTarget(event.target);\n\t\ttouch = event.targetTouches[0];\n\n\t\tif (deviceIsIOS) {\n\n\t\t\t// Only trusted events will deselect text on iOS (issue #49)\n\t\t\tselection = window.getSelection();\n\t\t\tif (selection.rangeCount && !selection.isCollapsed) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (!deviceIsIOS4) {\n\n\t\t\t\t// Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23):\n\t\t\t\t// when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched\n\t\t\t\t// with the same identifier as the touch event that previously triggered the click that triggered the alert.\n\t\t\t\t// Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an\n\t\t\t\t// immediately preceeding touch event (issue #52), so this fix is unavailable on that platform.\n\t\t\t\t// Issue 120: touch.identifier is 0 when Chrome dev tools 'Emulate touch events' is set with an iOS device UA string,\n\t\t\t\t// which causes all touch events to be ignored. As this block only applies to iOS, and iOS identifiers are always long,\n\t\t\t\t// random integers, it's safe to to continue if the identifier is 0 here.\n\t\t\t\tif (touch.identifier && touch.identifier === this.lastTouchIdentifier) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tthis.lastTouchIdentifier = touch.identifier;\n\n\t\t\t\t// If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and:\n\t\t\t\t// 1) the user does a fling scroll on the scrollable layer\n\t\t\t\t// 2) the user stops the fling scroll with another tap\n\t\t\t\t// then the event.target of the last 'touchend' event will be the element that was under the user's finger\n\t\t\t\t// when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check\n\t\t\t\t// is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42).\n\t\t\t\tthis.updateScrollParent(targetElement);\n\t\t\t}\n\t\t}\n\n\t\tthis.trackingClick = true;\n\t\tthis.trackingClickStart = event.timeStamp;\n\t\tthis.targetElement = targetElement;\n\n\t\tthis.touchStartX = touch.pageX;\n\t\tthis.touchStartY = touch.pageY;\n\n\t\t// Prevent phantom clicks on fast double-tap (issue #36)\n\t\tif ((event.timeStamp - this.lastClickTime) < this.tapDelay) {\n\t\t\tevent.preventDefault();\n\t\t}\n\n\t\treturn true;\n\t};\n\n\n\t/**\n\t * Based on a touchmove event object, check whether the touch has moved past a boundary since it started.\n\t *\n\t * @param {Event} event\n\t * @returns {boolean}\n\t */\n\tFastClick.prototype.touchHasMoved = function(event) {\n\t\tvar touch = event.changedTouches[0], boundary = this.touchBoundary;\n\n\t\tif (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t};\n\n\n\t/**\n\t * Update the last position.\n\t *\n\t * @param {Event} event\n\t * @returns {boolean}\n\t */\n\tFastClick.prototype.onTouchMove = function(event) {\n\t\tif (!this.trackingClick) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// If the touch has moved, cancel the click tracking\n\t\tif (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {\n\t\t\tthis.trackingClick = false;\n\t\t\tthis.targetElement = null;\n\t\t}\n\n\t\treturn true;\n\t};\n\n\n\t/**\n\t * Attempt to find the labelled control for the given label element.\n\t *\n\t * @param {EventTarget|HTMLLabelElement} labelElement\n\t * @returns {Element|null}\n\t */\n\tFastClick.prototype.findControl = function(labelElement) {\n\n\t\t// Fast path for newer browsers supporting the HTML5 control attribute\n\t\tif (labelElement.control !== undefined) {\n\t\t\treturn labelElement.control;\n\t\t}\n\n\t\t// All browsers under test that support touch events also support the HTML5 htmlFor attribute\n\t\tif (labelElement.htmlFor) {\n\t\t\treturn document.getElementById(labelElement.htmlFor);\n\t\t}\n\n\t\t// If no for attribute exists, attempt to retrieve the first labellable descendant element\n\t\t// the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label\n\t\treturn labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');\n\t};\n\n\n\t/**\n\t * On touch end, determine whether to send a click event at once.\n\t *\n\t * @param {Event} event\n\t * @returns {boolean}\n\t */\n\tFastClick.prototype.onTouchEnd = function(event) {\n\t\tvar forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;\n\n\t\tif (!this.trackingClick) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Prevent phantom clicks on fast double-tap (issue #36)\n\t\tif ((event.timeStamp - this.lastClickTime) < this.tapDelay) {\n\t\t\tthis.cancelNextClick = true;\n\t\t\treturn true;\n\t\t}\n\n\t\tif ((event.timeStamp - this.trackingClickStart) > this.tapTimeout) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Reset to prevent wrong click cancel on input (issue #156).\n\t\tthis.cancelNextClick = false;\n\n\t\tthis.lastClickTime = event.timeStamp;\n\n\t\ttrackingClickStart = this.trackingClickStart;\n\t\tthis.trackingClick = false;\n\t\tthis.trackingClickStart = 0;\n\n\t\t// On some iOS devices, the targetElement supplied with the event is invalid if the layer\n\t\t// is performing a transition or scroll, and has to be re-detected manually. Note that\n\t\t// for this to function correctly, it must be called *after* the event target is checked!\n\t\t// See issue #57; also filed as rdar://13048589 .\n\t\tif (deviceIsIOSWithBadTarget) {\n\t\t\ttouch = event.changedTouches[0];\n\n\t\t\t// In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null\n\t\t\ttargetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;\n\t\t\ttargetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;\n\t\t}\n\n\t\ttargetTagName = targetElement.tagName.toLowerCase();\n\t\tif (targetTagName === 'label') {\n\t\t\tforElement = this.findControl(targetElement);\n\t\t\tif (forElement) {\n\t\t\t\tthis.focus(targetElement);\n\t\t\t\tif (deviceIsAndroid) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\ttargetElement = forElement;\n\t\t\t}\n\t\t} else if (this.needsFocus(targetElement)) {\n\n\t\t\t// Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through.\n\t\t\t// Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37).\n\t\t\tif ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) {\n\t\t\t\tthis.targetElement = null;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tthis.focus(targetElement);\n\t\t\tthis.sendClick(targetElement, event);\n\n\t\t\t// Select elements need the event to go through on iOS 4, otherwise the selector menu won't open.\n\t\t\t// Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others)\n\t\t\tif (!deviceIsIOS || targetTagName !== 'select') {\n\t\t\t\tthis.targetElement = null;\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\tif (deviceIsIOS && !deviceIsIOS4) {\n\n\t\t\t// Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled\n\t\t\t// and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42).\n\t\t\tscrollParent = targetElement.fastClickScrollParent;\n\t\t\tif (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// Prevent the actual click from going though - unless the target node is marked as requiring\n\t\t// real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted.\n\t\tif (!this.needsClick(targetElement)) {\n\t\t\tevent.preventDefault();\n\t\t\tthis.sendClick(targetElement, event);\n\t\t}\n\n\t\treturn false;\n\t};\n\n\n\t/**\n\t * On touch cancel, stop tracking the click.\n\t *\n\t * @returns {void}\n\t */\n\tFastClick.prototype.onTouchCancel = function() {\n\t\tthis.trackingClick = false;\n\t\tthis.targetElement = null;\n\t};\n\n\n\t/**\n\t * Determine mouse events which should be permitted.\n\t *\n\t * @param {Event} event\n\t * @returns {boolean}\n\t */\n\tFastClick.prototype.onMouse = function(event) {\n\n\t\t// If a target element was never set (because a touch event was never fired) allow the event\n\t\tif (!this.targetElement) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (event.forwardedTouchEvent) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Programmatically generated events targeting a specific element should be permitted\n\t\tif (!event.cancelable) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Derive and check the target element to see whether the mouse event needs to be permitted;\n\t\t// unless explicitly enabled, prevent non-touch click events from triggering actions,\n\t\t// to prevent ghost/doubleclicks.\n\t\tif (!this.needsClick(this.targetElement) || this.cancelNextClick) {\n\n\t\t\t// Prevent any user-added listeners declared on FastClick element from being fired.\n\t\t\tif (event.stopImmediatePropagation) {\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t} else {\n\n\t\t\t\t// Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)\n\t\t\t\tevent.propagationStopped = true;\n\t\t\t}\n\n\t\t\t// Cancel the event\n\t\t\tevent.stopPropagation();\n\t\t\tevent.preventDefault();\n\n\t\t\treturn false;\n\t\t}\n\n\t\t// If the mouse event is permitted, return true for the action to go through.\n\t\treturn true;\n\t};\n\n\n\t/**\n\t * On actual clicks, determine whether this is a touch-generated click, a click action occurring\n\t * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or\n\t * an actual click which should be permitted.\n\t *\n\t * @param {Event} event\n\t * @returns {boolean}\n\t */\n\tFastClick.prototype.onClick = function(event) {\n\t\tvar permitted;\n\n\t\t// It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early.\n\t\tif (this.trackingClick) {\n\t\t\tthis.targetElement = null;\n\t\t\tthis.trackingClick = false;\n\t\t\treturn true;\n\t\t}\n\n\t\t// Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target.\n\t\tif (event.target.type === 'submit' && event.detail === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tpermitted = this.onMouse(event);\n\n\t\t// Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through.\n\t\tif (!permitted) {\n\t\t\tthis.targetElement = null;\n\t\t}\n\n\t\t// If clicks are permitted, return true for the action to go through.\n\t\treturn permitted;\n\t};\n\n\n\t/**\n\t * Remove all FastClick's event listeners.\n\t *\n\t * @returns {void}\n\t */\n\tFastClick.prototype.destroy = function() {\n\t\tvar layer = this.layer;\n\n\t\tif (deviceIsAndroid) {\n\t\t\tlayer.removeEventListener('mouseover', this.onMouse, true);\n\t\t\tlayer.removeEventListener('mousedown', this.onMouse, true);\n\t\t\tlayer.removeEventListener('mouseup', this.onMouse, true);\n\t\t}\n\n\t\tlayer.removeEventListener('click', this.onClick, true);\n\t\tlayer.removeEventListener('touchstart', this.onTouchStart, false);\n\t\tlayer.removeEventListener('touchmove', this.onTouchMove, false);\n\t\tlayer.removeEventListener('touchend', this.onTouchEnd, false);\n\t\tlayer.removeEventListener('touchcancel', this.onTouchCancel, false);\n\t};\n\n\n\t/**\n\t * Check whether FastClick is needed.\n\t *\n\t * @param {Element} layer The layer to listen on\n\t */\n\tFastClick.notNeeded = function(layer) {\n\t\tvar metaViewport;\n\t\tvar chromeVersion;\n\t\tvar blackberryVersion;\n\t\tvar firefoxVersion;\n\n\t\t// Devices that don't support touch don't need FastClick\n\t\tif (typeof window.ontouchstart === 'undefined') {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Chrome version - zero for other browsers\n\t\tchromeVersion = +(/Chrome\\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];\n\n\t\tif (chromeVersion) {\n\n\t\t\tif (deviceIsAndroid) {\n\t\t\t\tmetaViewport = document.querySelector('meta[name=viewport]');\n\n\t\t\t\tif (metaViewport) {\n\t\t\t\t\t// Chrome on Android with user-scalable=\"no\" doesn't need FastClick (issue #89)\n\t\t\t\t\tif (metaViewport.content.indexOf('user-scalable=no') !== -1) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t// Chrome 32 and above with width=device-width or less don't need FastClick\n\t\t\t\t\tif (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Chrome desktop doesn't need FastClick (issue #15)\n\t\t\t} else {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tif (deviceIsBlackBerry10) {\n\t\t\tblackberryVersion = navigator.userAgent.match(/Version\\/([0-9]*)\\.([0-9]*)/);\n\n\t\t\t// BlackBerry 10.3+ does not require Fastclick library.\n\t\t\t// https://github.com/ftlabs/fastclick/issues/251\n\t\t\tif (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) {\n\t\t\t\tmetaViewport = document.querySelector('meta[name=viewport]');\n\n\t\t\t\tif (metaViewport) {\n\t\t\t\t\t// user-scalable=no eliminates click delay.\n\t\t\t\t\tif (metaViewport.content.indexOf('user-scalable=no') !== -1) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t// width=device-width (or less than device-width) eliminates click delay.\n\t\t\t\t\tif (document.documentElement.scrollWidth <= window.outerWidth) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97)\n\t\tif (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Firefox version - zero for other browsers\n\t\tfirefoxVersion = +(/Firefox\\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];\n\n\t\tif (firefoxVersion >= 27) {\n\t\t\t// Firefox 27+ does not have tap delay if the content is not zoomable - https://bugzilla.mozilla.org/show_bug.cgi?id=922896\n\n\t\t\tmetaViewport = document.querySelector('meta[name=viewport]');\n\t\t\tif (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// IE11: prefixed -ms-touch-action is no longer supported and it's recomended to use non-prefixed version\n\t\t// http://msdn.microsoft.com/en-us/library/windows/apps/Hh767313.aspx\n\t\tif (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t};\n\n\n\t/**\n\t * Factory method for creating a FastClick object\n\t *\n\t * @param {Element} layer The layer to listen on\n\t * @param {Object} [options={}] The options to override the defaults\n\t */\n\tFastClick.attach = function(layer, options) {\n\t\treturn new FastClick(layer, options);\n\t};\n\n\n\tif (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {\n\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine(function() {\n\t\t\treturn FastClick;\n\t\t});\n\t} else if (typeof module !== 'undefined' && module.exports) {\n\t\tmodule.exports = FastClick.attach;\n\t\tmodule.exports.FastClick = FastClick;\n\t} else {\n\t\twindow.FastClick = FastClick;\n\t}\n"
  },
  {
    "path": "packages/fastclick/package.js",
    "content": "Package.describe({\n  summary: \"Faster touch events on mobile\",\n  version: '1.0.12'\n});\n\nPackage.onUse(function (api) {\n  api.export('FastClick', 'web');\n\n  api.addFiles(['pre.js', 'fastclick.js', 'post.js'], 'web');\n});\n"
  },
  {
    "path": "packages/fastclick/post.js",
    "content": "// This exports object was created in pre.js.  Now copy the 'FastClick' object\n// from it into the package-scope variable `FastClick`, which will get exported.\n\nFastClick = module.exports.FastClick;\n\nMeteor.startup(function () {\n  FastClick.attach(document.body);\n});\n"
  },
  {
    "path": "packages/fastclick/pre.js",
    "content": "// Define an object named module.exports. This will cause fastclick.js to put\n// FastClick as a field on it, instead of in the global namespace.\n// See also post.js.\nmodule = {\n  exports: {}\n};\n"
  },
  {
    "path": "packages/force-ssl/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/force-ssl/README.md",
    "content": "# force-ssl\n\nThis package, part of [Webapp](https://www.meteor.com/webapp), causes\nMeteor to redirect insecure connections (HTTP) to a secure URL\n(HTTPS). Use this package to ensure that communication to the server\nis always encrypted to protect users from active spoofing attacks.\n\nTo simplify development, unencrypted connections from `localhost` are\nalways accepted over HTTP.\n\nApplication bundles (`meteor bundle`) do not include an HTTPS server or\ncertificate. A proxy server that terminates SSL in front of a Meteor\nbundle must set the standard `x-forwarded-proto` header for the\n`force-ssl` package to work.\n\nApplications deployed to `meteor.com` subdomains with\n`meteor deploy` are automatically served via HTTPS using Meteor's\ncertificate.\n"
  },
  {
    "path": "packages/force-ssl/force_ssl_common.js",
    "content": "_.extend(Meteor.absoluteUrl.defaultOptions, {secure: true});\n"
  },
  {
    "path": "packages/force-ssl/force_ssl_server.js",
    "content": "var url = Npm.require(\"url\");\n\n// Unfortunately we can't use a connect middleware here since\n// sockjs installs itself prior to all existing listeners\n// (meaning prior to any connect middlewares) so we need to take\n// an approach similar to overshadowListeners in\n// https://github.com/sockjs/sockjs-node/blob/cf820c55af6a9953e16558555a31decea554f70e/src/utils.coffee\n\nvar httpServer = WebApp.httpServer;\nvar oldHttpServerListeners = httpServer.listeners('request').slice(0);\nhttpServer.removeAllListeners('request');\nhttpServer.addListener('request', function (req, res) {\n\n  // allow connections if they have been handled w/ ssl already\n  // (either by us or by a proxy) OR the connection is entirely over\n  // localhost (development mode).\n  //\n  // Note: someone could trick us into serving over non-ssl by setting\n  // x-forwarded-for or x-forwarded-proto. Not much we can do there if\n  // we still want to operate behind proxies.\n\n  var remoteAddress =\n        req.connection.remoteAddress || req.socket.remoteAddress;\n  // Determine if the connection is only over localhost. Both we\n  // received it on localhost, and all proxies involved received on\n  // localhost.\n  var localhostRegexp = /^\\s*(127\\.0\\.0\\.1|::1)\\s*$/;\n  var isLocal = (\n    localhostRegexp.test(remoteAddress) &&\n      (!req.headers['x-forwarded-for'] ||\n       _.all(req.headers['x-forwarded-for'].split(','), function (x) {\n         return localhostRegexp.test(x);\n       })));\n\n  // Determine if the connection was over SSL at any point. Either we\n  // received it as SSL, or a proxy did and translated it for us.\n  var isSsl = req.connection.pair ||\n      (req.headers['x-forwarded-proto'] &&\n       req.headers['x-forwarded-proto'].indexOf('https') !== -1);\n\n  if (!isLocal && !isSsl) {\n    // connection is not cool. send a 302 redirect!\n\n    var host = url.parse(Meteor.absoluteUrl()).hostname;\n\n    // strip off the port number. If we went to a URL with a custom\n    // port, we don't know what the custom SSL port is anyway.\n    host = host.replace(/:\\d+$/, '');\n\n    res.writeHead(302, {\n      'Location': 'https://' + host + req.url,\n      'Access-Control-Allow-Origin': '*'\n    });\n    res.end();\n    return;\n  }\n\n  // connection is OK. Proceed normally.\n  var args = arguments;\n  _.each(oldHttpServerListeners, function(oldListener) {\n    oldListener.apply(httpServer, args);\n  });\n});\n\n\n// NOTE: this doesn't handle websockets!\n//\n// Websockets come in via the 'upgrade' request. We can override this,\n// however the problem is we're not sure if the websocket is actually\n// encrypted. We don't get x-forwarded-for or x-forwarded-proto on\n// websockets. It's possible the 'sec-websocket-origin' header does\n// what we want, but that's not clear.\n//\n// For now, this package allows raw unencrypted DDP connections over\n// websockets.\n"
  },
  {
    "path": "packages/force-ssl/package.js",
    "content": "Package.describe({\n  summary: \"Require this application to use HTTPS\",\n  version: \"1.0.12\",\n  prodOnly: true\n});\n\nPackage.onUse(function (api) {\n  api.use('webapp', 'server');\n  api.use('underscore');\n  // make sure we come after livedata, so we load after the sockjs\n  // server has been instantiated.\n  api.use('ddp', 'server');\n\n  api.addFiles('force_ssl_common.js', ['client', 'server']);\n  api.addFiles('force_ssl_server.js', 'server');\n\n  // Another thing we could do is add a force_ssl_client.js file that\n  // makes sure document.location.protocol is 'https'. If it detected\n  // the code was loaded from a non-localhost non-https site, it would\n  // stop the app from working and pop up an error box or something.\n});\n"
  },
  {
    "path": "packages/geojson-utils/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/geojson-utils/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/geojson-utils/geojson-utils.js",
    "content": "(function () {\n  var gju = {};\n\n  // Export the geojson object for **CommonJS**\n  if (typeof module !== 'undefined' && module.exports) {\n    module.exports = gju;\n  }\n\n  // adapted from http://www.kevlindev.com/gui/math/intersection/Intersection.js\n  gju.lineStringsIntersect = function (l1, l2) {\n    var intersects = [];\n    for (var i = 0; i <= l1.coordinates.length - 2; ++i) {\n      for (var j = 0; j <= l2.coordinates.length - 2; ++j) {\n        var a1 = {\n          x: l1.coordinates[i][1],\n          y: l1.coordinates[i][0]\n        },\n          a2 = {\n            x: l1.coordinates[i + 1][1],\n            y: l1.coordinates[i + 1][0]\n          },\n          b1 = {\n            x: l2.coordinates[j][1],\n            y: l2.coordinates[j][0]\n          },\n          b2 = {\n            x: l2.coordinates[j + 1][1],\n            y: l2.coordinates[j + 1][0]\n          },\n          ua_t = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x),\n          ub_t = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x),\n          u_b = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);\n        if (u_b != 0) {\n          var ua = ua_t / u_b,\n            ub = ub_t / u_b;\n          if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {\n            intersects.push({\n              'type': 'Point',\n              'coordinates': [a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y)]\n            });\n          }\n        }\n      }\n    }\n    if (intersects.length == 0) intersects = false;\n    return intersects;\n  }\n\n  // Bounding Box\n\n  function boundingBoxAroundPolyCoords (coords) {\n    var xAll = [], yAll = []\n\n    for (var i = 0; i < coords[0].length; i++) {\n      xAll.push(coords[0][i][1])\n      yAll.push(coords[0][i][0])\n    }\n\n    xAll = xAll.sort(function (a,b) { return a - b })\n    yAll = yAll.sort(function (a,b) { return a - b })\n\n    return [ [xAll[0], yAll[0]], [xAll[xAll.length - 1], yAll[yAll.length - 1]] ]\n  }\n\n  gju.pointInBoundingBox = function (point, bounds) {\n    return !(point.coordinates[1] < bounds[0][0] || point.coordinates[1] > bounds[1][0] || point.coordinates[0] < bounds[0][1] || point.coordinates[0] > bounds[1][1]) \n  }\n\n  // Point in Polygon\n  // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html#Listing the Vertices\n\n  function pnpoly (x,y,coords) {\n    var vert = [ [0,0] ]\n\n    for (var i = 0; i < coords.length; i++) {\n      for (var j = 0; j < coords[i].length; j++) {\n        vert.push(coords[i][j])\n      }\n      vert.push([0,0])\n    }\n\n    var inside = false\n    for (var i = 0, j = vert.length - 1; i < vert.length; j = i++) {\n      if (((vert[i][0] > y) != (vert[j][0] > y)) && (x < (vert[j][1] - vert[i][1]) * (y - vert[i][0]) / (vert[j][0] - vert[i][0]) + vert[i][1])) inside = !inside\n    }\n\n    return inside\n  }\n\n  gju.pointInPolygon = function (p, poly) {\n    var coords = (poly.type == \"Polygon\") ? [ poly.coordinates ] : poly.coordinates\n\n    var insideBox = false\n    for (var i = 0; i < coords.length; i++) {\n      if (gju.pointInBoundingBox(p, boundingBoxAroundPolyCoords(coords[i]))) insideBox = true\n    }\n    if (!insideBox) return false\n\n    var insidePoly = false\n    for (var i = 0; i < coords.length; i++) {\n      if (pnpoly(p.coordinates[1], p.coordinates[0], coords[i])) insidePoly = true\n    }\n\n    return insidePoly\n  }\n\n  gju.numberToRadius = function (number) {\n    return number * Math.PI / 180;\n  }\n\n  gju.numberToDegree = function (number) {\n    return number * 180 / Math.PI;\n  }\n\n  // written with help from @tautologe\n  gju.drawCircle = function (radiusInMeters, centerPoint, steps) {\n    var center = [centerPoint.coordinates[1], centerPoint.coordinates[0]],\n      dist = (radiusInMeters / 1000) / 6371,\n      // convert meters to radiant\n      radCenter = [gju.numberToRadius(center[0]), gju.numberToRadius(center[1])],\n      steps = steps || 15,\n      // 15 sided circle\n      poly = [[center[0], center[1]]];\n    for (var i = 0; i < steps; i++) {\n      var brng = 2 * Math.PI * i / steps;\n      var lat = Math.asin(Math.sin(radCenter[0]) * Math.cos(dist)\n              + Math.cos(radCenter[0]) * Math.sin(dist) * Math.cos(brng));\n      var lng = radCenter[1] + Math.atan2(Math.sin(brng) * Math.sin(dist) * Math.cos(radCenter[0]),\n                                          Math.cos(dist) - Math.sin(radCenter[0]) * Math.sin(lat));\n      poly[i] = [];\n      poly[i][1] = gju.numberToDegree(lat);\n      poly[i][0] = gju.numberToDegree(lng);\n    }\n    return {\n      \"type\": \"Polygon\",\n      \"coordinates\": [poly]\n    };\n  }\n\n  // assumes rectangle starts at lower left point\n  gju.rectangleCentroid = function (rectangle) {\n    var bbox = rectangle.coordinates[0];\n    var xmin = bbox[0][0],\n      ymin = bbox[0][1],\n      xmax = bbox[2][0],\n      ymax = bbox[2][1];\n    var xwidth = xmax - xmin;\n    var ywidth = ymax - ymin;\n    return {\n      'type': 'Point',\n      'coordinates': [xmin + xwidth / 2, ymin + ywidth / 2]\n    };\n  }\n\n  // from http://www.movable-type.co.uk/scripts/latlong.html\n  gju.pointDistance = function (pt1, pt2) {\n    var lon1 = pt1.coordinates[0],\n      lat1 = pt1.coordinates[1],\n      lon2 = pt2.coordinates[0],\n      lat2 = pt2.coordinates[1],\n      dLat = gju.numberToRadius(lat2 - lat1),\n      dLon = gju.numberToRadius(lon2 - lon1),\n      a = Math.pow(Math.sin(dLat / 2), 2) + Math.cos(gju.numberToRadius(lat1))\n        * Math.cos(gju.numberToRadius(lat2)) * Math.pow(Math.sin(dLon / 2), 2),\n      c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n    // Earth radius is 6371 km\n    return (6371 * c) * 1000; // returns meters\n  },\n\n  // checks if geometry lies entirely within a circle\n  // works with Point, LineString, Polygon\n  gju.geometryWithinRadius = function (geometry, center, radius) {\n    if (geometry.type == 'Point') {\n      return gju.pointDistance(geometry, center) <= radius;\n    } else if (geometry.type == 'LineString' || geometry.type == 'Polygon') {\n      var point = {};\n      var coordinates;\n      if (geometry.type == 'Polygon') {\n        // it's enough to check the exterior ring of the Polygon\n        coordinates = geometry.coordinates[0];\n      } else {\n        coordinates = geometry.coordinates;\n      }\n      for (var i in coordinates) {\n        point.coordinates = coordinates[i];\n        if (gju.pointDistance(point, center) > radius) {\n          return false;\n        }\n      }\n    }\n    return true;\n  }\n\n  // adapted from http://paulbourke.net/geometry/polyarea/javascript.txt\n  gju.area = function (polygon) {\n    var area = 0;\n    // TODO: polygon holes at coordinates[1]\n    var points = polygon.coordinates[0];\n    var j = points.length - 1;\n    var p1, p2;\n\n    for (var i = 0; i < points.length; j = i++) {\n      var p1 = {\n        x: points[i][1],\n        y: points[i][0]\n      };\n      var p2 = {\n        x: points[j][1],\n        y: points[j][0]\n      };\n      area += p1.x * p2.y;\n      area -= p1.y * p2.x;\n    }\n\n    area /= 2;\n    return area;\n  },\n\n  // adapted from http://paulbourke.net/geometry/polyarea/javascript.txt\n  gju.centroid = function (polygon) {\n    var f, x = 0,\n      y = 0;\n    // TODO: polygon holes at coordinates[1]\n    var points = polygon.coordinates[0];\n    var j = points.length - 1;\n    var p1, p2;\n\n    for (var i = 0; i < points.length; j = i++) {\n      var p1 = {\n        x: points[i][1],\n        y: points[i][0]\n      };\n      var p2 = {\n        x: points[j][1],\n        y: points[j][0]\n      };\n      f = p1.x * p2.y - p2.x * p1.y;\n      x += (p1.x + p2.x) * f;\n      y += (p1.y + p2.y) * f;\n    }\n\n    f = gju.area(polygon) * 6;\n    return {\n      'type': 'Point',\n      'coordinates': [y / f, x / f]\n    };\n  },\n\n  gju.simplify = function (source, kink) { /* source[] array of geojson points */\n    /* kink\tin metres, kinks above this depth kept  */\n    /* kink depth is the height of the triangle abc where a-b and b-c are two consecutive line segments */\n    kink = kink || 20;\n    source = source.map(function (o) {\n      return {\n        lng: o.coordinates[0],\n        lat: o.coordinates[1]\n      }\n    });\n\n    var n_source, n_stack, n_dest, start, end, i, sig;\n    var dev_sqr, max_dev_sqr, band_sqr;\n    var x12, y12, d12, x13, y13, d13, x23, y23, d23;\n    var F = (Math.PI / 180.0) * 0.5;\n    var index = new Array(); /* aray of indexes of source points to include in the reduced line */\n    var sig_start = new Array(); /* indices of start & end of working section */\n    var sig_end = new Array();\n\n    /* check for simple cases */\n\n    if (source.length < 3) return (source); /* one or two points */\n\n    /* more complex case. initialize stack */\n\n    n_source = source.length;\n    band_sqr = kink * 360.0 / (2.0 * Math.PI * 6378137.0); /* Now in degrees */\n    band_sqr *= band_sqr;\n    n_dest = 0;\n    sig_start[0] = 0;\n    sig_end[0] = n_source - 1;\n    n_stack = 1;\n\n    /* while the stack is not empty  ... */\n    while (n_stack > 0) {\n\n      /* ... pop the top-most entries off the stacks */\n\n      start = sig_start[n_stack - 1];\n      end = sig_end[n_stack - 1];\n      n_stack--;\n\n      if ((end - start) > 1) { /* any intermediate points ? */\n\n        /* ... yes, so find most deviant intermediate point to\n        either side of line joining start & end points */\n\n        x12 = (source[end].lng() - source[start].lng());\n        y12 = (source[end].lat() - source[start].lat());\n        if (Math.abs(x12) > 180.0) x12 = 360.0 - Math.abs(x12);\n        x12 *= Math.cos(F * (source[end].lat() + source[start].lat())); /* use avg lat to reduce lng */\n        d12 = (x12 * x12) + (y12 * y12);\n\n        for (i = start + 1, sig = start, max_dev_sqr = -1.0; i < end; i++) {\n\n          x13 = source[i].lng() - source[start].lng();\n          y13 = source[i].lat() - source[start].lat();\n          if (Math.abs(x13) > 180.0) x13 = 360.0 - Math.abs(x13);\n          x13 *= Math.cos(F * (source[i].lat() + source[start].lat()));\n          d13 = (x13 * x13) + (y13 * y13);\n\n          x23 = source[i].lng() - source[end].lng();\n          y23 = source[i].lat() - source[end].lat();\n          if (Math.abs(x23) > 180.0) x23 = 360.0 - Math.abs(x23);\n          x23 *= Math.cos(F * (source[i].lat() + source[end].lat()));\n          d23 = (x23 * x23) + (y23 * y23);\n\n          if (d13 >= (d12 + d23)) dev_sqr = d23;\n          else if (d23 >= (d12 + d13)) dev_sqr = d13;\n          else dev_sqr = (x13 * y12 - y13 * x12) * (x13 * y12 - y13 * x12) / d12; // solve triangle\n          if (dev_sqr > max_dev_sqr) {\n            sig = i;\n            max_dev_sqr = dev_sqr;\n          }\n        }\n\n        if (max_dev_sqr < band_sqr) { /* is there a sig. intermediate point ? */\n          /* ... no, so transfer current start point */\n          index[n_dest] = start;\n          n_dest++;\n        } else { /* ... yes, so push two sub-sections on stack for further processing */\n          n_stack++;\n          sig_start[n_stack - 1] = sig;\n          sig_end[n_stack - 1] = end;\n          n_stack++;\n          sig_start[n_stack - 1] = start;\n          sig_end[n_stack - 1] = sig;\n        }\n      } else { /* ... no intermediate points, so transfer current start point */\n        index[n_dest] = start;\n        n_dest++;\n      }\n    }\n\n    /* transfer last point */\n    index[n_dest] = n_source - 1;\n    n_dest++;\n\n    /* make return array */\n    var r = new Array();\n    for (var i = 0; i < n_dest; i++)\n      r.push(source[index[i]]);\n\n    return r.map(function (o) {\n      return {\n        type: \"Point\",\n        coordinates: [o.lng, o.lat]\n      }\n    });\n  }\n\n  // http://www.movable-type.co.uk/scripts/latlong.html#destPoint\n  gju.destinationPoint = function (pt, brng, dist) {\n    dist = dist/6371;  // convert dist to angular distance in radians\n    brng = gju.numberToRadius(brng);\n\n    var lat1 = gju.numberToRadius(pt.coordinates[0]);\n    var lon1 = gju.numberToRadius(pt.coordinates[1]);\n\n    var lat2 = Math.asin( Math.sin(lat1)*Math.cos(dist) +\n                          Math.cos(lat1)*Math.sin(dist)*Math.cos(brng) );\n    var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(dist)*Math.cos(lat1),\n                                 Math.cos(dist)-Math.sin(lat1)*Math.sin(lat2));\n    lon2 = (lon2+3*Math.PI) % (2*Math.PI) - Math.PI;  // normalise to -180..+180º\n\n    return {\n      'type': 'Point',\n      'coordinates': [gju.numberToDegree(lat2), gju.numberToDegree(lon2)]\n    };\n  };\n\n})();\n"
  },
  {
    "path": "packages/geojson-utils/geojson-utils.tests.js",
    "content": "var gju = GeoJSON;\n\nTinytest.add(\"geojson-utils - line intersects\", function (test) {\n  var diagonalUp = { \"type\": \"LineString\",\"coordinates\": [\n    [0, 0], [10, 10]\n  ]}\n  var diagonalDown = { \"type\": \"LineString\",\"coordinates\": [\n    [10, 0], [0, 10]\n  ]}\n  var farAway = { \"type\": \"LineString\",\"coordinates\": [\n    [100, 100], [110, 110]\n  ]}\n\n  test.isTrue(gju.lineStringsIntersect(diagonalUp, diagonalDown));\n  test.isFalse(gju.lineStringsIntersect(diagonalUp, farAway));\n});\n\n// Used by two tests\nvar box = {\n  \"type\": \"Polygon\",\n  \"coordinates\": [\n    [ [0, 0], [10, 0], [10, 10], [0, 10] ]\n  ]\n};\n\nTinytest.add(\"geojson-utils - inside/outside of the box\", function (test) {\n\n  var inBox = {\"type\": \"Point\", \"coordinates\": [5, 5]}\n  var outBox = {\"type\": \"Point\", \"coordinates\": [15, 15]}\n\n  test.isTrue(gju.pointInPolygon(inBox, box));\n  test.isFalse(gju.pointInPolygon(outBox, box));\n});\n\nTinytest.add(\"geojson-utils - drawCircle\", function (test) {\n  test.length(gju.drawCircle(10, {\"type\": \"Point\", \"coordinates\": [0, 0]}).\n               coordinates[0], 15);\n  test.length(gju.drawCircle(10, {\"type\": \"Point\", \"coordinates\": [0, 0]}, 50).\n              coordinates[0], 50);\n});\n\nTinytest.add(\"geojson-utils - centroid\", function (test) {\n  var centroid = gju.rectangleCentroid(box)\n  test.equal(centroid.coordinates[0], 5);\n  test.equal(centroid.coordinates[1], 5);\n});\n\nTinytest.add(\"geojson-utils - point distance\", function (test) {\n  var fairyLand = {\"type\": \"Point\",\n    \"coordinates\": [-122.260000705719, 37.80919060818706]}\n  var navalBase = {\"type\": \"Point\",\n    \"coordinates\": [-122.32083320617676, 37.78774223089045]}\n  test.equal(Math.floor(gju.pointDistance(fairyLand, navalBase)), 5852);\n});\n\nTinytest.add(\"geojson-utils - points distance generated tests\", function (test) {\n  // Pairs of points we will be looking a distance between\n  var tests = [[[-19.416501816827804,-13.442164216190577], [8.694866622798145,-8.511979941977188]],\n    [[151.2841189110186,-56.14564002258703], [167.77983197313733,0.05544793023727834]],\n    [[100.28413630579598,-88.02313695591874], [36.48786173714325,53.44207073468715]],\n    [[-70.34899035631679,76.51596869179048], [154.91605914011598,-73.60970971290953]],\n    [[96.28682994353585,58.77288202662021], [-118.33936230326071,72.07877089688554]],\n    [[140.35530551429838,10.507104953983799], [-67.73368513956666,38.075836981181055]],\n    [[69.55582775664516,86.25450283149257], [-18.446230484172702,6.116170521359891]],\n    [[163.83647522330284,-65.7211532376241], [-159.2198902608361,-78.42975475382991]],\n    [[-178.9383797585033,-54.87420454365201], [-175.35227065649815,-84.04084282391705]],\n    [[-48.63219943456352,11.284161149058491], [-179.12627786491066,-51.95622375886887]],\n    [[140.29684206470847,-67.20720696030185], [-109.37452355003916,36.03131077555008]],\n    [[-154.6698773431126,58.322094617411494], [61.18583445576951,-4.3424885796848685]],\n    [[122.5562841903884,10.43972848681733], [-11.756078708684072,-43.86124441982247]],\n    [[-67.91648306301795,-86.38826347864233], [163.577536230674,12.987319261068478]],\n    [[91.65140007715672,17.595150742679834], [135.80393003183417,22.307532118167728]],\n    [[-112.70280818711035,34.45729674655013], [-127.42168210959062,-25.51327457977459]],\n    [[-161.55807900894433,-77.40711871231906], [-92.66313794790767,-89.12077954714186]],\n    [[39.966264681424946,9.890176948625594], [-159.88646019320004,40.60383598925546]],\n    [[-57.48232689569704,86.64061016729102], [59.53941993578337,-75.73194969259202]],\n    [[-142.0938081513159,80.76813141163439], [14.891517050098628,64.56322408467531]]];\n\n  // correct distance between two points\n  var answers = [3115066.2536578891, 6423493.2321747802, 15848950.0402601473,\n    18714226.5425080135, 5223022.7731127860, 13874476.3135112207,\n    9314403.3309389465, 1831929.5917785936, 3244710.9344544266,\n    13691492.4666933995, 14525055.6462231465, 13261602.4336371962,\n    14275427.5511620939, 11699799.3615680672, 4628773.1129429890,\n    6846704.0253010122, 1368055.9401701286, 14041503.0409814864,\n    18560499.7346975356, 3793112.6186894816];\n\n  _.each(tests, function (pair, testN) {\n    var distance = GeoJSON.pointDistance.apply(this, _.map(pair, toGeoJSONPoint));\n    test.isTrue(Math.abs(distance - answers[testN]) < 0.000001,\n      \"Wrong distance between points \" + JSON.stringify(pair) + \": \" + distance + \", \" + Math.abs(distance - answers[testN]) + \" differenc\");\n  });\n\n  function toGeoJSONPoint (coordinates) {\n    return { type: \"Point\", coordinates: coordinates };\n  }\n});\n\n"
  },
  {
    "path": "packages/geojson-utils/main.js",
    "content": "exports.GeoJSON = require(\"./geojson-utils.js\");\n"
  },
  {
    "path": "packages/geojson-utils/package.js",
    "content": "Package.describe({\n  summary: 'GeoJSON utility functions (from https://github.com/maxogden/geojson-js-utils)',\n  version: '1.0.9'\n});\n\nPackage.onUse(function (api) {\n  api.use('modules');\n  api.export('GeoJSON');\n  api.mainModule('main.js');\n});\n\nPackage.onTest(function (api) {\n  api.use('tinytest');\n  api.use('underscore');\n  api.use('geojson-utils');\n  api.addFiles(['geojson-utils.tests.js'], 'client');\n});\n"
  },
  {
    "path": "packages/github/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/github/README.md",
    "content": "# github\n\nAn implementation of the GitHub OAuth flow. See the [project page](https://www.meteor.com/accounts) on Meteor Accounts for more details. XXX link"
  },
  {
    "path": "packages/github/github_client.js",
    "content": "Github = {};\n\n// Request Github credentials for the user\n// @param options {optional}\n// @param credentialRequestCompleteCallback {Function} Callback function to call on\n//   completion. Takes one argument, credentialToken on success, or Error on\n//   error.\nGithub.requestCredential = function (options, credentialRequestCompleteCallback) {\n  // support both (options, callback) and (callback).\n  if (!credentialRequestCompleteCallback && typeof options === 'function') {\n    credentialRequestCompleteCallback = options;\n    options = {};\n  }\n\n  var config = ServiceConfiguration.configurations.findOne({service: 'github'});\n  if (!config) {\n    credentialRequestCompleteCallback && credentialRequestCompleteCallback(\n      new ServiceConfiguration.ConfigError());\n    return;\n  }\n  var credentialToken = Random.secret();\n\n  var scope = (options && options.requestPermissions) || ['user:email'];\n  var flatScope = _.map(scope, encodeURIComponent).join('+');\n\n  var loginStyle = OAuth._loginStyle('github', config, options);\n\n  var loginUrl =\n    'https://github.com/login/oauth/authorize' +\n    '?client_id=' + config.clientId +\n    '&scope=' + flatScope +\n    '&redirect_uri=' + OAuth._redirectUri('github', config) +\n    '&state=' + OAuth._stateParam(loginStyle, credentialToken, options && options.redirectUrl);\n\n  OAuth.launchLogin({\n    loginService: \"github\",\n    loginStyle: loginStyle,\n    loginUrl: loginUrl,\n    credentialRequestCompleteCallback: credentialRequestCompleteCallback,\n    credentialToken: credentialToken,\n    popupOptions: {width: 900, height: 450}\n  });\n};\n"
  },
  {
    "path": "packages/github/github_configure.html",
    "content": "<template name=\"configureLoginServiceDialogForGithub\">\n  <p>\n    First, you'll need to get a Github Client ID. Follow these steps:\n  </p>\n  <ol>\n    <li>\n      Visit <a href=\"https://github.com/settings/applications/new\" target=\"blank\">https://github.com/settings/applications/new</a>\n    </li>\n    <li>\n      Set Homepage URL to: <span class=\"url\">{{siteUrl}}</span>\n    </li>\n    <li>\n      Set Authorization callback URL to: <span class=\"url\">{{siteUrl}}_oauth/github</span>\n    </li>\n  </ol>\n</template>\n"
  },
  {
    "path": "packages/github/github_configure.js",
    "content": "Template.configureLoginServiceDialogForGithub.helpers({\n  siteUrl: function () {\n    return Meteor.absoluteUrl();\n  }\n});\n\nTemplate.configureLoginServiceDialogForGithub.fields = function () {\n  return [\n    {property: 'clientId', label: 'Client ID'},\n    {property: 'secret', label: 'Client Secret'}\n  ];\n};\n"
  },
  {
    "path": "packages/github/github_server.js",
    "content": "Github = {};\n\nOAuth.registerService('github', 2, null, function(query) {\n\n  var accessToken = getAccessToken(query);\n  var identity = getIdentity(accessToken);\n  var emails = getEmails(accessToken);\n  var primaryEmail = _.findWhere(emails, {primary: true});\n\n  return {\n    serviceData: {\n      id: identity.id,\n      accessToken: OAuth.sealSecret(accessToken),\n      email: identity.email || (primaryEmail && primaryEmail.email) || '',\n      username: identity.login,\n      emails: emails\n    },\n    options: {profile: {name: identity.name}}\n  };\n});\n\n// http://developer.github.com/v3/#user-agent-required\nvar userAgent = \"Meteor\";\nif (Meteor.release)\n  userAgent += \"/\" + Meteor.release;\n\nvar getAccessToken = function (query) {\n  var config = ServiceConfiguration.configurations.findOne({service: 'github'});\n  if (!config)\n    throw new ServiceConfiguration.ConfigError();\n\n  var response;\n  try {\n    response = HTTP.post(\n      \"https://github.com/login/oauth/access_token\", {\n        headers: {\n          Accept: 'application/json',\n          \"User-Agent\": userAgent\n        },\n        params: {\n          code: query.code,\n          client_id: config.clientId,\n          client_secret: OAuth.openSecret(config.secret),\n          redirect_uri: OAuth._redirectUri('github', config),\n          state: query.state\n        }\n      });\n  } catch (err) {\n    throw _.extend(new Error(\"Failed to complete OAuth handshake with Github. \" + err.message),\n                   {response: err.response});\n  }\n  if (response.data.error) { // if the http response was a json object with an error attribute\n    throw new Error(\"Failed to complete OAuth handshake with GitHub. \" + response.data.error);\n  } else {\n    return response.data.access_token;\n  }\n};\n\nvar getIdentity = function (accessToken) {\n  try {\n    return HTTP.get(\n      \"https://api.github.com/user\", {\n        headers: {\"User-Agent\": userAgent}, // http://developer.github.com/v3/#user-agent-required\n        params: {access_token: accessToken}\n      }).data;\n  } catch (err) {\n    throw _.extend(new Error(\"Failed to fetch identity from Github. \" + err.message),\n                   {response: err.response});\n  }\n};\n\nvar getEmails = function (accessToken) {\n  try {\n    return HTTP.get(\n      \"https://api.github.com/user/emails\", {\n        headers: {\"User-Agent\": userAgent}, // http://developer.github.com/v3/#user-agent-required\n        params: {access_token: accessToken}\n      }).data;\n  } catch (err) {\n    return [];\n  }\n};\n\nGithub.retrieveCredential = function(credentialToken, credentialSecret) {\n  return OAuth.retrieveCredential(credentialToken, credentialSecret);\n};\n"
  },
  {
    "path": "packages/github/package.js",
    "content": "Package.describe({\n  summary: \"Github OAuth flow\",\n  version: \"1.1.8\"\n});\n\nPackage.onUse(function(api) {\n  api.use('oauth2', ['client', 'server']);\n  api.use('oauth', ['client', 'server']);\n  api.use('http', ['server']);\n  api.use('underscore', 'client');\n  api.use('templating', 'client');\n  api.use('random', 'client');\n  api.use('service-configuration', ['client', 'server']);\n\n  api.export('Github');\n\n  api.addFiles(\n    ['github_configure.html', 'github_configure.js'],\n    'client');\n\n  api.addFiles('github_server.js', 'server');\n  api.addFiles('github_client.js', 'client');\n});\n"
  },
  {
    "path": "packages/google/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/google/README.md",
    "content": "# google\n\nAn implementation of the Google OAuth flow. See the [project page](https://www.meteor.com/accounts) on Meteor Accounts for more details. XXX link"
  },
  {
    "path": "packages/google/google_client.js",
    "content": "Google = {};\n\n// Request Google credentials for the user\n// @param options {optional}\n// @param credentialRequestCompleteCallback {Function} Callback function to call on\n//   completion. Takes one argument, credentialToken on success, or Error on\n//   error.\nGoogle.requestCredential = function (options, credentialRequestCompleteCallback) {\n  // support both (options, callback) and (callback).\n  if (!credentialRequestCompleteCallback && typeof options === 'function') {\n    credentialRequestCompleteCallback = options;\n    options = {};\n  } else if (!options) {\n    options = {};\n  }\n\n  var config = ServiceConfiguration.configurations.findOne({service: 'google'});\n  if (!config) {\n    credentialRequestCompleteCallback && credentialRequestCompleteCallback(\n      new ServiceConfiguration.ConfigError());\n    return;\n  }\n\n  var credentialToken = Random.secret();\n\n  // always need this to get user id from google.\n  var requiredScope = ['profile'];\n  var scope = ['email'];\n  if (options.requestPermissions)\n    scope = options.requestPermissions;\n  scope = _.union(scope, requiredScope);\n\n  var loginUrlParameters = {};\n  if (config.loginUrlParameters){\n    _.extend(loginUrlParameters, config.loginUrlParameters)\n  }\n  if (options.loginUrlParameters){\n    _.extend(loginUrlParameters, options.loginUrlParameters)\n  }\n  var ILLEGAL_PARAMETERS = ['response_type', 'client_id', 'scope', 'redirect_uri', 'state'];\n    // validate options keys\n  _.each(_.keys(loginUrlParameters), function (key) {\n    if (_.contains(ILLEGAL_PARAMETERS, key))\n      throw new Error(\"Google.requestCredential: Invalid loginUrlParameter: \" + key);\n  });\n\n  // backwards compatible options\n  if (options.requestOfflineToken != null){\n    loginUrlParameters.access_type = options.requestOfflineToken ? 'offline' : 'online'\n  }\n  if (options.prompt != null) {\n    loginUrlParameters.prompt = options.prompt;\n  } else if (options.forceApprovalPrompt) {\n    loginUrlParameters.prompt = 'consent'\n  }\n\n  if (options.loginHint) {\n    loginUrlParameters.login_hint = options.loginHint;\n  }\n\n  var loginStyle = OAuth._loginStyle('google', config, options);\n  // https://developers.google.com/accounts/docs/OAuth2WebServer#formingtheurl\n  _.extend(loginUrlParameters, {\n    \"response_type\": \"code\",\n    \"client_id\":  config.clientId,\n    \"scope\": scope.join(' '), // space delimited\n    \"redirect_uri\": OAuth._redirectUri('google', config),\n    \"state\": OAuth._stateParam(loginStyle, credentialToken, options.redirectUrl)\n  });\n  var loginUrl = 'https://accounts.google.com/o/oauth2/auth?' +\n    _.map(loginUrlParameters, function(value, param){\n      return encodeURIComponent(param) + '=' + encodeURIComponent(value);\n    }).join(\"&\");\n\n  OAuth.launchLogin({\n    loginService: \"google\",\n    loginStyle: loginStyle,\n    loginUrl: loginUrl,\n    credentialRequestCompleteCallback: credentialRequestCompleteCallback,\n    credentialToken: credentialToken,\n    popupOptions: { height: 600 }\n  });\n};\n"
  },
  {
    "path": "packages/google/google_configure.html",
    "content": "<template name=\"configureLoginServiceDialogForGoogle\">\n  <p>\n    First, you'll need to get a Google Client ID. Follow these steps:\n  </p>\n  <ol>\n    <li>\n      Visit <a href=\"https://console.developers.google.com/\" target=\"blank\">https://console.developers.google.com/</a>\n    </li>\n    <li>\n      \"Create Project\", if needed. Wait for Google to finish provisioning.\n    </li>\n    <li>\n      On the left sidebar, go to \"Credentials\" and, on the right, \"OAuth consent screen\". Make sure to enter an email address and a product name, and save.\n    </li>\n    <li>\n      On the left sidebar, go to \"Credentials\". Click the \"Create credentials\" button, then select \"OAuth client ID\" as the type.\n    </li>\n    <li>\n      Select \"Web application\" as your application type.\n    </li>\n    <li>\n     Set Authorized Javascript Origins to: <span class=\"url\">{{siteUrl}}</span>\n    </li>\n    <li>\n      Set Authorized Redirect URI to: <span class=\"url\">{{siteUrl}}_oauth/google</span>\n    </li>\n    <li>\n      Finish by clicking \"Create\".\n    </li>\n  </ol>\n</template>\n"
  },
  {
    "path": "packages/google/google_configure.js",
    "content": "Template.configureLoginServiceDialogForGoogle.helpers({\n  siteUrl: function () {\n    return Meteor.absoluteUrl();\n  }\n});\n\nTemplate.configureLoginServiceDialogForGoogle.fields = function () {\n  return [\n    {property: 'clientId', label: 'Client ID'},\n    {property: 'secret', label: 'Client secret'}\n  ];\n};\n"
  },
  {
    "path": "packages/google/google_server.js",
    "content": "Google = {};\n\n// https://developers.google.com/accounts/docs/OAuth2Login#userinfocall\nGoogle.whitelistedFields = ['id', 'email', 'verified_email', 'name', 'given_name',\n                   'family_name', 'picture', 'locale', 'timezone', 'gender'];\n\n\nOAuth.registerService('google', 2, null, function(query) {\n\n  var response = getTokens(query);\n  var expiresAt = (+new Date) + (1000 * parseInt(response.expiresIn, 10));\n  var accessToken = response.accessToken;\n  var idToken = response.idToken;\n  var scopes = getScopes(accessToken);\n  var identity = getIdentity(accessToken);\n\n  var serviceData = {\n    accessToken: accessToken,\n    idToken: idToken,\n    expiresAt: expiresAt,\n    scope: scopes\n  };\n\n  var fields = _.pick(identity, Google.whitelistedFields);\n  _.extend(serviceData, fields);\n\n  // only set the token in serviceData if it's there. this ensures\n  // that we don't lose old ones (since we only get this on the first\n  // log in attempt)\n  if (response.refreshToken)\n    serviceData.refreshToken = response.refreshToken;\n\n  return {\n    serviceData: serviceData,\n    options: {profile: {name: identity.name}}\n  };\n});\n\n// returns an object containing:\n// - accessToken\n// - expiresIn: lifetime of token in seconds\n// - refreshToken, if this is the first authorization request\nvar getTokens = function (query) {\n  var config = ServiceConfiguration.configurations.findOne({service: 'google'});\n  if (!config)\n    throw new ServiceConfiguration.ConfigError();\n\n  var response;\n  try {\n    response = HTTP.post(\n      \"https://accounts.google.com/o/oauth2/token\", {params: {\n        code: query.code,\n        client_id: config.clientId,\n        client_secret: OAuth.openSecret(config.secret),\n        redirect_uri: OAuth._redirectUri('google', config),\n        grant_type: 'authorization_code'\n      }});\n  } catch (err) {\n    throw _.extend(new Error(\"Failed to complete OAuth handshake with Google. \" + err.message),\n                   {response: err.response});\n  }\n\n  if (response.data.error) { // if the http response was a json object with an error attribute\n    throw new Error(\"Failed to complete OAuth handshake with Google. \" + response.data.error);\n  } else {\n    return {\n      accessToken: response.data.access_token,\n      refreshToken: response.data.refresh_token,\n      expiresIn: response.data.expires_in,\n      idToken: response.data.id_token\n    };\n  }\n};\n\nvar getIdentity = function (accessToken) {\n  try {\n    return HTTP.get(\n      \"https://www.googleapis.com/oauth2/v1/userinfo\",\n      {params: {access_token: accessToken}}).data;\n  } catch (err) {\n    throw _.extend(new Error(\"Failed to fetch identity from Google. \" + err.message),\n                   {response: err.response});\n  }\n};\n\nvar getScopes = function (accessToken) {\n  try {\n    return HTTP.get(\n      \"https://www.googleapis.com/oauth2/v1/tokeninfo\",\n      {params: {access_token: accessToken}}).data.scope.split(' ');\n  } catch (err) {\n    throw _.extend(new Error(\"Failed to fetch tokeninfo from Google. \" + err.message),\n                   {response: err.response});\n  }\n};\n\nGoogle.retrieveCredential = function(credentialToken, credentialSecret) {\n  return OAuth.retrieveCredential(credentialToken, credentialSecret);\n};\n"
  },
  {
    "path": "packages/google/package.js",
    "content": "Package.describe({\n  summary: \"Google OAuth flow\",\n  version: \"1.1.13\"\n});\n\nPackage.onUse(function(api) {\n  api.use('oauth2', ['client', 'server']);\n  api.use('oauth', ['client', 'server']);\n  api.use('http', ['server']);\n  api.use(['underscore', 'service-configuration'], ['client', 'server']);\n  api.use(['random', 'templating'], 'client');\n\n  api.export('Google');\n\n  api.addFiles(\n    ['google_configure.html', 'google_configure.js'],\n    'client');\n\n  api.addFiles('google_server.js', 'server');\n  api.addFiles('google_client.js', 'client');\n});\n"
  },
  {
    "path": "packages/handlebars/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/handlebars/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/handlebars/package.js",
    "content": "Package.describe({\n  summary: \"Deprecated\",\n  version: '1.0.7'\n});\n\nPackage.onUse(function (api) {\n// XXX we unfortunately we can't do this since `meteor test-packages`\n// tries to load all packages.\n//\n//  throw new Error(\n//    \"The 'handlebars' package is deprecated. \"\n//      + \"`Handlebars.registerHelper` is now `Template.registerHelper`.\");\n});\n"
  },
  {
    "path": "packages/hot-code-push/README.md",
    "content": "# hot-code-push\n\nEnables Meteor's hot code push functionality in development and production by\nincluding the `autoupdate` and `reload` packages in your app.\n"
  },
  {
    "path": "packages/hot-code-push/hot-code-push-tests.js",
    "content": "// Write your tests here!\n// Here is an example.\nTinytest.add('example', function (test) {\n  test.equal(true, true);\n});\n"
  },
  {
    "path": "packages/hot-code-push/hot-code-push.js",
    "content": "// Write your package code here!\n"
  },
  {
    "path": "packages/hot-code-push/package.js",
    "content": "Package.describe({\n  name: 'hot-code-push',\n  version: '1.0.4',\n  // Brief, one-line summary of the package.\n  summary: 'Update the client in place when new code is available.',\n  // URL to the Git repository containing the source code for this package.\n  git: 'https://github.com/meteor/meteor',\n  // By default, Meteor will default to using README.md for documentation.\n  // To avoid submitting documentation, set this field to null.\n  documentation: 'README.md'\n});\n\nPackage.onUse(function(api) {\n  // Notifies the client when new versions of the app are available\n  api.imply('autoupdate');\n\n  // Reloads the page with an API to maintain data across the reload\n  api.imply('reload');\n});\n"
  },
  {
    "path": "packages/html-tools/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/html-tools/README.md",
    "content": "# html-tools\n\nA lightweight HTML tokenizer and parser which outputs to the HTMLjs\nobject representation.  Special hooks allow the syntax to be extended\nto parse an HTML-like template language like Spacebars.\n\n```\nHTMLTools.parseFragment(\"<div class=greeting>Hello<br>World</div>\")\n\n=> HTML.DIV({'class':'greeting'}, \"Hello\", HTML.BR(), \"World\"))\n```\n\nThis package is used by the Spacebars compiler, which normally only\nruns at bundle time but can also be used at runtime on the client or\nserver.\n\n## Invoking the Parser\n\n`HTMLTools.parseFragment(input, options)` - Takes an input string or Scanner object and returns HTMLjs.\n\nIn the basic case, where no options are passed, `parseFragment` will consume the entire input (the full string or the rest of the Scanner).\n\nThe options are as follows:\n\n#### getTemplateTag\n\nThis option extends the HTML parser to parse template tags such as `{{foo}}`.\n\n`getTemplateTag: function (scanner, templateTagPosition) { ... }` - A function for the parser to call after every HTML token and at various positions within tags.  If the function returns an instanceof `HTMLTools.TemplateTag`, it is inserted into the HTMLjs tree at the appropriate location.  The constructor is `HTMLTools.TemplateTag(props)`, where props is an object whose properties are copied to the `TemplateTag` instance.  You can also call the constructor with no arguments and assign whatever properties you want, or you can subclass `TemplateTag`.\n\nThere are four possible outcomes when `getTemplateTag` is called:\n\n* Not a template tag - Leave the scanner as is, and return `null`.  A quick peek at the next character should bail to this case if the start of a template tag is not seen.\n* Bad template tag - Call `scanner.fatal`, which aborts parsing completely.  Once the beginning of a template tag is seen, `getTemplateTag` will generally want to commit, and either succeed or fail trying).\n* Good template tag - Advance the scanner to the end of the template tag and return an `HTMLTools.TemplateTag` object.\n* Comment tag - Advance the scanner and return `null`.  For example, a Spacebars comment is `{{! foo}}`.\n\nThe `templateTagPosition` argument to `getTemplateTag` is one of:\n\n* `HTMLTools.TEMPLATE_TAG_POSITION.ELEMENT` - At \"element level,\" meaning somewhere an HTML tag could be.\n* `HTMLTools.TEMPLATE_TAG_POSITION.IN_START_TAG` - Inside a start tag, as in `<div {{foo}}>`, where you might otherwise find `name=value`.\n* `HTMLTools.TEMPLATE_TAG_POSITION.IN_ATTRIBUTE` - Inside the value of an HTML attribute, as in `<div class={{foo}}>`.\n* `HTMLTools.TEMPLATE_TAG_POSITION.IN_RCDATA` - Inside a TEXTAREA or a block helper inside an attribute, where character references are allowed (\"replaced character data\") but not tags.\n* `HTMLTools.TEMPLATE_TAG_POSITION.IN_RAWTEXT` - In a context where character references are not parsed, such as a script tag, style tag, or markdown helper.\n\nIt's completely normal for `getTemplateTag` to invoke `HTMLTools.parseFragment` recursively on the same scanner (see `shouldStop`).  If it does so, the same value of `getTemplateTag` must be passed to the second invocation.\n\nAt the moment, template tags must begin with `{`.  The parser does not try calling `getTemplateTag` for every character of an HTML document, only at token boundaries, and it knows to always end a token at `{`.\n\n#### textMode\n\nThe `textMode` option, if present, causes the parser to parse text (such as the contents of a `<textarea>` tag or part of an attribute) instead of HTML.  In a text mode, for example, the input `\"<\"` is not a parse error (because a bare `<` is allowed in a textarea or attribute).\n\nThe value of `textMode` must be one of:\n\n* `HTML.TEXTMODE.RCDATA` - Interpret character references (the usual case)\n* `HTML.TEXTMODE.STRING` - Don't interpret character references (the RAWTEXT case)\n\n#### shouldStop\n\n`shouldStop: function (scanner) { ... }` - A function that the parser invokes between tokens to check whether it should stop parsing.  The function should return a boolean value.\n\nThe `shouldStop` function provides a way to put a \"wall\" in the input stream for the purpose of parsing HTML content embedded in a template tag.  For example, take the template `{{#if happy}}yay{{/if}}`.  The scanner will be advanced to the start of the word `yay` before `parseFragment` is called to parse the contents of the tag.  (Note that the caller happens to be the `getTemplateTag` function of an enclosing `parseFragment`.)  When parsing from `yay`, the `shouldStop` function is used to end the fragment at `{{/if}}`, which, like `{{/blah}}` or `{{else}}`, couldn't possibly be actual content that belongs in the fragment.  Even if HTML tags are not closed, as in the malformed template `{{#if foo}}<div>{{else}}`, the fragment stops at the `{{else}}`, and the error is an unclosed `<div>` (before the parser notices the unclosed `{{#if}}`).\n\n## HTMLTools.Scanner class\n\nTo write `getTemplateTag` and `shouldStop` functions, you have to\ninterface with the `HTMLTools.Scanner` class used by html-tools.  It's a\ngeneral class that could be used by any parser/lexer/tokenizer.\n\nA Scanner has an immutable source document and a mutable pointer into\nthe document.\n\n* `new Scanner(input)` - constructs a Scanner with source string `input`\n* `scanner.input` (read-only) - the entire source string\n* `scanner.pos` (read/write) - the current index into the source string\n\nScanners provide these methods for convenience:\n\n* `scanner.rest()` - `input.slice(pos)` (the rest of the document)\n* `scanner.peek()` - `input.charAt(pos)` (the next character)\n* `scanner.isEOF()` - true if `pos` is at or beyond the end of `input`\n* `scanner.fatal(msg)` - throw an error indicating a problem at `pos`\n\nEven though `scanner.rest()` performs a substring operation, it should be considered fast and O(1), because all known JavaScript runtimes in use have constant-time substring.  It would be possible, but extremely clumsy, to avoid such a substring operation while performing the usual business of a parser, which is to try to match a regex anchored at a particular index.\n\nFunctions that take scanners generally have three possible outcomes:\n\n* Success:  Advance `scanner.pos` and return some truthy value\n* Failure: Leave `scanner.pos` alone and return `null`\n* Fatal: Throw an exception via `scanner.fatal`\n\nIt's particularly important that in the Failure case, the function restores the scanner to the state it found it.  This makes it possible to immediately try another parse function when one fails and form alternations such as `foo(scanner) || bar(scanner)`.\n\nIt's often easiest to avoid the Failure case altogether, writing parse functions that always succeed or throw.  This requires less bookkeeping and leads to good error messages.  A Failure case may be added if it is simple to check for up front and makes the function easier to use in an alternation.  We say a function has \"committed\" or \"will succeed or fail fatally trying\" when it has reached a point where it must return a value or throw.  Any parse function that has moved the scanner position and not remembered the original position is necessarily committed.  Usually, committing is completely natural in the context of the language being parsed; for example, `{{` in a template always starts a template tag or throws an error about a malformed template tag.\n\n## HTML Dialect\n\nHTML has many dialects and potential degrees of permissiveness.  We\nuse the WHATWG syntax spec and are pretty strict, failing on any\n\"parse error\" cases, which basically means the input has to be\nvalid \"HTML5\" (except for the template tags).\n\nHTML syntax references:\n\n* [Human-readable syntax guide](http://developers.whatwg.org/syntax.html#syntax)\n* [Tokenization state machine](http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html)\n\nThe WHATWG parser without error recovery is strict compared to\nbrowsers (which will recover from almost anything), but lenient\ncompared to the now-defunct XHTML spec (which required lowercase tag\nnames and lots more escaping of special characters).\n\nThe following are examples of **errors**:\n\n* A stray or unclosed `<` character\n* An unknown character reference like `&asdf;`\n* Self-closing tags like `<div/>` (except for BR, HR, INPUT, and other \"void\" elements)\n* End tags for void elements (BR, HR, INPUT, etc.)\n* Missing end tags, in most cases (e.g. missing `</div>`)\n\nThe following are **permitted**:\n\n* Bare `>` characters\n* Bare `&` that can't be confused with a character reference\n* Uppercase or lowercase tag and attribute names (case insensitive)\n* Unquoted and valueless attributes - `<input type=checkbox checked>`\n* Most characters in attribute values - `<img alt=x,y>`\n* Embedded SVG elements\n\nNote: Currently you have to close your Ps, LIs, and other tags for\nwhich the spec allows the end tag to be omitted in many cases\n\n## Character References\n\nThis package contains a lookup table for all known named character references in HTML, of which there are over 2,000, from `&Aacute;` (capital A, acute accent) to `&zwnj;` (zero-width non-joiner), as well as code for interpreting numeric character entities like `&#65;`.\n\nSince character references are parsed into `HTML.CharRef` objects which contain both the raw and interpreted form, we never have to convert between the forms except at parse time.\n\n"
  },
  {
    "path": "packages/html-tools/charref.js",
    "content": "\n// http://www.whatwg.org/specs/web-apps/current-work/multipage/entities.json\n\n\n// Note that some entities don't have a final semicolon!  These are used to\n// make `&lt` (for example) with no semicolon a parse error but `&abcde` not.\n\nvar ENTITIES = {\n  \"&Aacute;\": { \"codepoints\": [193], \"characters\": \"\\u00C1\" },\n  \"&Aacute\": { \"codepoints\": [193], \"characters\": \"\\u00C1\" },\n  \"&aacute;\": { \"codepoints\": [225], \"characters\": \"\\u00E1\" },\n  \"&aacute\": { \"codepoints\": [225], \"characters\": \"\\u00E1\" },\n  \"&Abreve;\": { \"codepoints\": [258], \"characters\": \"\\u0102\" },\n  \"&abreve;\": { \"codepoints\": [259], \"characters\": \"\\u0103\" },\n  \"&ac;\": { \"codepoints\": [8766], \"characters\": \"\\u223E\" },\n  \"&acd;\": { \"codepoints\": [8767], \"characters\": \"\\u223F\" },\n  \"&acE;\": { \"codepoints\": [8766, 819], \"characters\": \"\\u223E\\u0333\" },\n  \"&Acirc;\": { \"codepoints\": [194], \"characters\": \"\\u00C2\" },\n  \"&Acirc\": { \"codepoints\": [194], \"characters\": \"\\u00C2\" },\n  \"&acirc;\": { \"codepoints\": [226], \"characters\": \"\\u00E2\" },\n  \"&acirc\": { \"codepoints\": [226], \"characters\": \"\\u00E2\" },\n  \"&acute;\": { \"codepoints\": [180], \"characters\": \"\\u00B4\" },\n  \"&acute\": { \"codepoints\": [180], \"characters\": \"\\u00B4\" },\n  \"&Acy;\": { \"codepoints\": [1040], \"characters\": \"\\u0410\" },\n  \"&acy;\": { \"codepoints\": [1072], \"characters\": \"\\u0430\" },\n  \"&AElig;\": { \"codepoints\": [198], \"characters\": \"\\u00C6\" },\n  \"&AElig\": { \"codepoints\": [198], \"characters\": \"\\u00C6\" },\n  \"&aelig;\": { \"codepoints\": [230], \"characters\": \"\\u00E6\" },\n  \"&aelig\": { \"codepoints\": [230], \"characters\": \"\\u00E6\" },\n  \"&af;\": { \"codepoints\": [8289], \"characters\": \"\\u2061\" },\n  \"&Afr;\": { \"codepoints\": [120068], \"characters\": \"\\uD835\\uDD04\" },\n  \"&afr;\": { \"codepoints\": [120094], \"characters\": \"\\uD835\\uDD1E\" },\n  \"&Agrave;\": { \"codepoints\": [192], \"characters\": \"\\u00C0\" },\n  \"&Agrave\": { \"codepoints\": [192], \"characters\": \"\\u00C0\" },\n  \"&agrave;\": { \"codepoints\": [224], \"characters\": \"\\u00E0\" },\n  \"&agrave\": { \"codepoints\": [224], \"characters\": \"\\u00E0\" },\n  \"&alefsym;\": { \"codepoints\": [8501], \"characters\": \"\\u2135\" },\n  \"&aleph;\": { \"codepoints\": [8501], \"characters\": \"\\u2135\" },\n  \"&Alpha;\": { \"codepoints\": [913], \"characters\": \"\\u0391\" },\n  \"&alpha;\": { \"codepoints\": [945], \"characters\": \"\\u03B1\" },\n  \"&Amacr;\": { \"codepoints\": [256], \"characters\": \"\\u0100\" },\n  \"&amacr;\": { \"codepoints\": [257], \"characters\": \"\\u0101\" },\n  \"&amalg;\": { \"codepoints\": [10815], \"characters\": \"\\u2A3F\" },\n  \"&amp;\": { \"codepoints\": [38], \"characters\": \"\\u0026\" },\n  \"&amp\": { \"codepoints\": [38], \"characters\": \"\\u0026\" },\n  \"&AMP;\": { \"codepoints\": [38], \"characters\": \"\\u0026\" },\n  \"&AMP\": { \"codepoints\": [38], \"characters\": \"\\u0026\" },\n  \"&andand;\": { \"codepoints\": [10837], \"characters\": \"\\u2A55\" },\n  \"&And;\": { \"codepoints\": [10835], \"characters\": \"\\u2A53\" },\n  \"&and;\": { \"codepoints\": [8743], \"characters\": \"\\u2227\" },\n  \"&andd;\": { \"codepoints\": [10844], \"characters\": \"\\u2A5C\" },\n  \"&andslope;\": { \"codepoints\": [10840], \"characters\": \"\\u2A58\" },\n  \"&andv;\": { \"codepoints\": [10842], \"characters\": \"\\u2A5A\" },\n  \"&ang;\": { \"codepoints\": [8736], \"characters\": \"\\u2220\" },\n  \"&ange;\": { \"codepoints\": [10660], \"characters\": \"\\u29A4\" },\n  \"&angle;\": { \"codepoints\": [8736], \"characters\": \"\\u2220\" },\n  \"&angmsdaa;\": { \"codepoints\": [10664], \"characters\": \"\\u29A8\" },\n  \"&angmsdab;\": { \"codepoints\": [10665], \"characters\": \"\\u29A9\" },\n  \"&angmsdac;\": { \"codepoints\": [10666], \"characters\": \"\\u29AA\" },\n  \"&angmsdad;\": { \"codepoints\": [10667], \"characters\": \"\\u29AB\" },\n  \"&angmsdae;\": { \"codepoints\": [10668], \"characters\": \"\\u29AC\" },\n  \"&angmsdaf;\": { \"codepoints\": [10669], \"characters\": \"\\u29AD\" },\n  \"&angmsdag;\": { \"codepoints\": [10670], \"characters\": \"\\u29AE\" },\n  \"&angmsdah;\": { \"codepoints\": [10671], \"characters\": \"\\u29AF\" },\n  \"&angmsd;\": { \"codepoints\": [8737], \"characters\": \"\\u2221\" },\n  \"&angrt;\": { \"codepoints\": [8735], \"characters\": \"\\u221F\" },\n  \"&angrtvb;\": { \"codepoints\": [8894], \"characters\": \"\\u22BE\" },\n  \"&angrtvbd;\": { \"codepoints\": [10653], \"characters\": \"\\u299D\" },\n  \"&angsph;\": { \"codepoints\": [8738], \"characters\": \"\\u2222\" },\n  \"&angst;\": { \"codepoints\": [197], \"characters\": \"\\u00C5\" },\n  \"&angzarr;\": { \"codepoints\": [9084], \"characters\": \"\\u237C\" },\n  \"&Aogon;\": { \"codepoints\": [260], \"characters\": \"\\u0104\" },\n  \"&aogon;\": { \"codepoints\": [261], \"characters\": \"\\u0105\" },\n  \"&Aopf;\": { \"codepoints\": [120120], \"characters\": \"\\uD835\\uDD38\" },\n  \"&aopf;\": { \"codepoints\": [120146], \"characters\": \"\\uD835\\uDD52\" },\n  \"&apacir;\": { \"codepoints\": [10863], \"characters\": \"\\u2A6F\" },\n  \"&ap;\": { \"codepoints\": [8776], \"characters\": \"\\u2248\" },\n  \"&apE;\": { \"codepoints\": [10864], \"characters\": \"\\u2A70\" },\n  \"&ape;\": { \"codepoints\": [8778], \"characters\": \"\\u224A\" },\n  \"&apid;\": { \"codepoints\": [8779], \"characters\": \"\\u224B\" },\n  \"&apos;\": { \"codepoints\": [39], \"characters\": \"\\u0027\" },\n  \"&ApplyFunction;\": { \"codepoints\": [8289], \"characters\": \"\\u2061\" },\n  \"&approx;\": { \"codepoints\": [8776], \"characters\": \"\\u2248\" },\n  \"&approxeq;\": { \"codepoints\": [8778], \"characters\": \"\\u224A\" },\n  \"&Aring;\": { \"codepoints\": [197], \"characters\": \"\\u00C5\" },\n  \"&Aring\": { \"codepoints\": [197], \"characters\": \"\\u00C5\" },\n  \"&aring;\": { \"codepoints\": [229], \"characters\": \"\\u00E5\" },\n  \"&aring\": { \"codepoints\": [229], \"characters\": \"\\u00E5\" },\n  \"&Ascr;\": { \"codepoints\": [119964], \"characters\": \"\\uD835\\uDC9C\" },\n  \"&ascr;\": { \"codepoints\": [119990], \"characters\": \"\\uD835\\uDCB6\" },\n  \"&Assign;\": { \"codepoints\": [8788], \"characters\": \"\\u2254\" },\n  \"&ast;\": { \"codepoints\": [42], \"characters\": \"\\u002A\" },\n  \"&asymp;\": { \"codepoints\": [8776], \"characters\": \"\\u2248\" },\n  \"&asympeq;\": { \"codepoints\": [8781], \"characters\": \"\\u224D\" },\n  \"&Atilde;\": { \"codepoints\": [195], \"characters\": \"\\u00C3\" },\n  \"&Atilde\": { \"codepoints\": [195], \"characters\": \"\\u00C3\" },\n  \"&atilde;\": { \"codepoints\": [227], \"characters\": \"\\u00E3\" },\n  \"&atilde\": { \"codepoints\": [227], \"characters\": \"\\u00E3\" },\n  \"&Auml;\": { \"codepoints\": [196], \"characters\": \"\\u00C4\" },\n  \"&Auml\": { \"codepoints\": [196], \"characters\": \"\\u00C4\" },\n  \"&auml;\": { \"codepoints\": [228], \"characters\": \"\\u00E4\" },\n  \"&auml\": { \"codepoints\": [228], \"characters\": \"\\u00E4\" },\n  \"&awconint;\": { \"codepoints\": [8755], \"characters\": \"\\u2233\" },\n  \"&awint;\": { \"codepoints\": [10769], \"characters\": \"\\u2A11\" },\n  \"&backcong;\": { \"codepoints\": [8780], \"characters\": \"\\u224C\" },\n  \"&backepsilon;\": { \"codepoints\": [1014], \"characters\": \"\\u03F6\" },\n  \"&backprime;\": { \"codepoints\": [8245], \"characters\": \"\\u2035\" },\n  \"&backsim;\": { \"codepoints\": [8765], \"characters\": \"\\u223D\" },\n  \"&backsimeq;\": { \"codepoints\": [8909], \"characters\": \"\\u22CD\" },\n  \"&Backslash;\": { \"codepoints\": [8726], \"characters\": \"\\u2216\" },\n  \"&Barv;\": { \"codepoints\": [10983], \"characters\": \"\\u2AE7\" },\n  \"&barvee;\": { \"codepoints\": [8893], \"characters\": \"\\u22BD\" },\n  \"&barwed;\": { \"codepoints\": [8965], \"characters\": \"\\u2305\" },\n  \"&Barwed;\": { \"codepoints\": [8966], \"characters\": \"\\u2306\" },\n  \"&barwedge;\": { \"codepoints\": [8965], \"characters\": \"\\u2305\" },\n  \"&bbrk;\": { \"codepoints\": [9141], \"characters\": \"\\u23B5\" },\n  \"&bbrktbrk;\": { \"codepoints\": [9142], \"characters\": \"\\u23B6\" },\n  \"&bcong;\": { \"codepoints\": [8780], \"characters\": \"\\u224C\" },\n  \"&Bcy;\": { \"codepoints\": [1041], \"characters\": \"\\u0411\" },\n  \"&bcy;\": { \"codepoints\": [1073], \"characters\": \"\\u0431\" },\n  \"&bdquo;\": { \"codepoints\": [8222], \"characters\": \"\\u201E\" },\n  \"&becaus;\": { \"codepoints\": [8757], \"characters\": \"\\u2235\" },\n  \"&because;\": { \"codepoints\": [8757], \"characters\": \"\\u2235\" },\n  \"&Because;\": { \"codepoints\": [8757], \"characters\": \"\\u2235\" },\n  \"&bemptyv;\": { \"codepoints\": [10672], \"characters\": \"\\u29B0\" },\n  \"&bepsi;\": { \"codepoints\": [1014], \"characters\": \"\\u03F6\" },\n  \"&bernou;\": { \"codepoints\": [8492], \"characters\": \"\\u212C\" },\n  \"&Bernoullis;\": { \"codepoints\": [8492], \"characters\": \"\\u212C\" },\n  \"&Beta;\": { \"codepoints\": [914], \"characters\": \"\\u0392\" },\n  \"&beta;\": { \"codepoints\": [946], \"characters\": \"\\u03B2\" },\n  \"&beth;\": { \"codepoints\": [8502], \"characters\": \"\\u2136\" },\n  \"&between;\": { \"codepoints\": [8812], \"characters\": \"\\u226C\" },\n  \"&Bfr;\": { \"codepoints\": [120069], \"characters\": \"\\uD835\\uDD05\" },\n  \"&bfr;\": { \"codepoints\": [120095], \"characters\": \"\\uD835\\uDD1F\" },\n  \"&bigcap;\": { \"codepoints\": [8898], \"characters\": \"\\u22C2\" },\n  \"&bigcirc;\": { \"codepoints\": [9711], \"characters\": \"\\u25EF\" },\n  \"&bigcup;\": { \"codepoints\": [8899], \"characters\": \"\\u22C3\" },\n  \"&bigodot;\": { \"codepoints\": [10752], \"characters\": \"\\u2A00\" },\n  \"&bigoplus;\": { \"codepoints\": [10753], \"characters\": \"\\u2A01\" },\n  \"&bigotimes;\": { \"codepoints\": [10754], \"characters\": \"\\u2A02\" },\n  \"&bigsqcup;\": { \"codepoints\": [10758], \"characters\": \"\\u2A06\" },\n  \"&bigstar;\": { \"codepoints\": [9733], \"characters\": \"\\u2605\" },\n  \"&bigtriangledown;\": { \"codepoints\": [9661], \"characters\": \"\\u25BD\" },\n  \"&bigtriangleup;\": { \"codepoints\": [9651], \"characters\": \"\\u25B3\" },\n  \"&biguplus;\": { \"codepoints\": [10756], \"characters\": \"\\u2A04\" },\n  \"&bigvee;\": { \"codepoints\": [8897], \"characters\": \"\\u22C1\" },\n  \"&bigwedge;\": { \"codepoints\": [8896], \"characters\": \"\\u22C0\" },\n  \"&bkarow;\": { \"codepoints\": [10509], \"characters\": \"\\u290D\" },\n  \"&blacklozenge;\": { \"codepoints\": [10731], \"characters\": \"\\u29EB\" },\n  \"&blacksquare;\": { \"codepoints\": [9642], \"characters\": \"\\u25AA\" },\n  \"&blacktriangle;\": { \"codepoints\": [9652], \"characters\": \"\\u25B4\" },\n  \"&blacktriangledown;\": { \"codepoints\": [9662], \"characters\": \"\\u25BE\" },\n  \"&blacktriangleleft;\": { \"codepoints\": [9666], \"characters\": \"\\u25C2\" },\n  \"&blacktriangleright;\": { \"codepoints\": [9656], \"characters\": \"\\u25B8\" },\n  \"&blank;\": { \"codepoints\": [9251], \"characters\": \"\\u2423\" },\n  \"&blk12;\": { \"codepoints\": [9618], \"characters\": \"\\u2592\" },\n  \"&blk14;\": { \"codepoints\": [9617], \"characters\": \"\\u2591\" },\n  \"&blk34;\": { \"codepoints\": [9619], \"characters\": \"\\u2593\" },\n  \"&block;\": { \"codepoints\": [9608], \"characters\": \"\\u2588\" },\n  \"&bne;\": { \"codepoints\": [61, 8421], \"characters\": \"\\u003D\\u20E5\" },\n  \"&bnequiv;\": { \"codepoints\": [8801, 8421], \"characters\": \"\\u2261\\u20E5\" },\n  \"&bNot;\": { \"codepoints\": [10989], \"characters\": \"\\u2AED\" },\n  \"&bnot;\": { \"codepoints\": [8976], \"characters\": \"\\u2310\" },\n  \"&Bopf;\": { \"codepoints\": [120121], \"characters\": \"\\uD835\\uDD39\" },\n  \"&bopf;\": { \"codepoints\": [120147], \"characters\": \"\\uD835\\uDD53\" },\n  \"&bot;\": { \"codepoints\": [8869], \"characters\": \"\\u22A5\" },\n  \"&bottom;\": { \"codepoints\": [8869], \"characters\": \"\\u22A5\" },\n  \"&bowtie;\": { \"codepoints\": [8904], \"characters\": \"\\u22C8\" },\n  \"&boxbox;\": { \"codepoints\": [10697], \"characters\": \"\\u29C9\" },\n  \"&boxdl;\": { \"codepoints\": [9488], \"characters\": \"\\u2510\" },\n  \"&boxdL;\": { \"codepoints\": [9557], \"characters\": \"\\u2555\" },\n  \"&boxDl;\": { \"codepoints\": [9558], \"characters\": \"\\u2556\" },\n  \"&boxDL;\": { \"codepoints\": [9559], \"characters\": \"\\u2557\" },\n  \"&boxdr;\": { \"codepoints\": [9484], \"characters\": \"\\u250C\" },\n  \"&boxdR;\": { \"codepoints\": [9554], \"characters\": \"\\u2552\" },\n  \"&boxDr;\": { \"codepoints\": [9555], \"characters\": \"\\u2553\" },\n  \"&boxDR;\": { \"codepoints\": [9556], \"characters\": \"\\u2554\" },\n  \"&boxh;\": { \"codepoints\": [9472], \"characters\": \"\\u2500\" },\n  \"&boxH;\": { \"codepoints\": [9552], \"characters\": \"\\u2550\" },\n  \"&boxhd;\": { \"codepoints\": [9516], \"characters\": \"\\u252C\" },\n  \"&boxHd;\": { \"codepoints\": [9572], \"characters\": \"\\u2564\" },\n  \"&boxhD;\": { \"codepoints\": [9573], \"characters\": \"\\u2565\" },\n  \"&boxHD;\": { \"codepoints\": [9574], \"characters\": \"\\u2566\" },\n  \"&boxhu;\": { \"codepoints\": [9524], \"characters\": \"\\u2534\" },\n  \"&boxHu;\": { \"codepoints\": [9575], \"characters\": \"\\u2567\" },\n  \"&boxhU;\": { \"codepoints\": [9576], \"characters\": \"\\u2568\" },\n  \"&boxHU;\": { \"codepoints\": [9577], \"characters\": \"\\u2569\" },\n  \"&boxminus;\": { \"codepoints\": [8863], \"characters\": \"\\u229F\" },\n  \"&boxplus;\": { \"codepoints\": [8862], \"characters\": \"\\u229E\" },\n  \"&boxtimes;\": { \"codepoints\": [8864], \"characters\": \"\\u22A0\" },\n  \"&boxul;\": { \"codepoints\": [9496], \"characters\": \"\\u2518\" },\n  \"&boxuL;\": { \"codepoints\": [9563], \"characters\": \"\\u255B\" },\n  \"&boxUl;\": { \"codepoints\": [9564], \"characters\": \"\\u255C\" },\n  \"&boxUL;\": { \"codepoints\": [9565], \"characters\": \"\\u255D\" },\n  \"&boxur;\": { \"codepoints\": [9492], \"characters\": \"\\u2514\" },\n  \"&boxuR;\": { \"codepoints\": [9560], \"characters\": \"\\u2558\" },\n  \"&boxUr;\": { \"codepoints\": [9561], \"characters\": \"\\u2559\" },\n  \"&boxUR;\": { \"codepoints\": [9562], \"characters\": \"\\u255A\" },\n  \"&boxv;\": { \"codepoints\": [9474], \"characters\": \"\\u2502\" },\n  \"&boxV;\": { \"codepoints\": [9553], \"characters\": \"\\u2551\" },\n  \"&boxvh;\": { \"codepoints\": [9532], \"characters\": \"\\u253C\" },\n  \"&boxvH;\": { \"codepoints\": [9578], \"characters\": \"\\u256A\" },\n  \"&boxVh;\": { \"codepoints\": [9579], \"characters\": \"\\u256B\" },\n  \"&boxVH;\": { \"codepoints\": [9580], \"characters\": \"\\u256C\" },\n  \"&boxvl;\": { \"codepoints\": [9508], \"characters\": \"\\u2524\" },\n  \"&boxvL;\": { \"codepoints\": [9569], \"characters\": \"\\u2561\" },\n  \"&boxVl;\": { \"codepoints\": [9570], \"characters\": \"\\u2562\" },\n  \"&boxVL;\": { \"codepoints\": [9571], \"characters\": \"\\u2563\" },\n  \"&boxvr;\": { \"codepoints\": [9500], \"characters\": \"\\u251C\" },\n  \"&boxvR;\": { \"codepoints\": [9566], \"characters\": \"\\u255E\" },\n  \"&boxVr;\": { \"codepoints\": [9567], \"characters\": \"\\u255F\" },\n  \"&boxVR;\": { \"codepoints\": [9568], \"characters\": \"\\u2560\" },\n  \"&bprime;\": { \"codepoints\": [8245], \"characters\": \"\\u2035\" },\n  \"&breve;\": { \"codepoints\": [728], \"characters\": \"\\u02D8\" },\n  \"&Breve;\": { \"codepoints\": [728], \"characters\": \"\\u02D8\" },\n  \"&brvbar;\": { \"codepoints\": [166], \"characters\": \"\\u00A6\" },\n  \"&brvbar\": { \"codepoints\": [166], \"characters\": \"\\u00A6\" },\n  \"&bscr;\": { \"codepoints\": [119991], \"characters\": \"\\uD835\\uDCB7\" },\n  \"&Bscr;\": { \"codepoints\": [8492], \"characters\": \"\\u212C\" },\n  \"&bsemi;\": { \"codepoints\": [8271], \"characters\": \"\\u204F\" },\n  \"&bsim;\": { \"codepoints\": [8765], \"characters\": \"\\u223D\" },\n  \"&bsime;\": { \"codepoints\": [8909], \"characters\": \"\\u22CD\" },\n  \"&bsolb;\": { \"codepoints\": [10693], \"characters\": \"\\u29C5\" },\n  \"&bsol;\": { \"codepoints\": [92], \"characters\": \"\\u005C\" },\n  \"&bsolhsub;\": { \"codepoints\": [10184], \"characters\": \"\\u27C8\" },\n  \"&bull;\": { \"codepoints\": [8226], \"characters\": \"\\u2022\" },\n  \"&bullet;\": { \"codepoints\": [8226], \"characters\": \"\\u2022\" },\n  \"&bump;\": { \"codepoints\": [8782], \"characters\": \"\\u224E\" },\n  \"&bumpE;\": { \"codepoints\": [10926], \"characters\": \"\\u2AAE\" },\n  \"&bumpe;\": { \"codepoints\": [8783], \"characters\": \"\\u224F\" },\n  \"&Bumpeq;\": { \"codepoints\": [8782], \"characters\": \"\\u224E\" },\n  \"&bumpeq;\": { \"codepoints\": [8783], \"characters\": \"\\u224F\" },\n  \"&Cacute;\": { \"codepoints\": [262], \"characters\": \"\\u0106\" },\n  \"&cacute;\": { \"codepoints\": [263], \"characters\": \"\\u0107\" },\n  \"&capand;\": { \"codepoints\": [10820], \"characters\": \"\\u2A44\" },\n  \"&capbrcup;\": { \"codepoints\": [10825], \"characters\": \"\\u2A49\" },\n  \"&capcap;\": { \"codepoints\": [10827], \"characters\": \"\\u2A4B\" },\n  \"&cap;\": { \"codepoints\": [8745], \"characters\": \"\\u2229\" },\n  \"&Cap;\": { \"codepoints\": [8914], \"characters\": \"\\u22D2\" },\n  \"&capcup;\": { \"codepoints\": [10823], \"characters\": \"\\u2A47\" },\n  \"&capdot;\": { \"codepoints\": [10816], \"characters\": \"\\u2A40\" },\n  \"&CapitalDifferentialD;\": { \"codepoints\": [8517], \"characters\": \"\\u2145\" },\n  \"&caps;\": { \"codepoints\": [8745, 65024], \"characters\": \"\\u2229\\uFE00\" },\n  \"&caret;\": { \"codepoints\": [8257], \"characters\": \"\\u2041\" },\n  \"&caron;\": { \"codepoints\": [711], \"characters\": \"\\u02C7\" },\n  \"&Cayleys;\": { \"codepoints\": [8493], \"characters\": \"\\u212D\" },\n  \"&ccaps;\": { \"codepoints\": [10829], \"characters\": \"\\u2A4D\" },\n  \"&Ccaron;\": { \"codepoints\": [268], \"characters\": \"\\u010C\" },\n  \"&ccaron;\": { \"codepoints\": [269], \"characters\": \"\\u010D\" },\n  \"&Ccedil;\": { \"codepoints\": [199], \"characters\": \"\\u00C7\" },\n  \"&Ccedil\": { \"codepoints\": [199], \"characters\": \"\\u00C7\" },\n  \"&ccedil;\": { \"codepoints\": [231], \"characters\": \"\\u00E7\" },\n  \"&ccedil\": { \"codepoints\": [231], \"characters\": \"\\u00E7\" },\n  \"&Ccirc;\": { \"codepoints\": [264], \"characters\": \"\\u0108\" },\n  \"&ccirc;\": { \"codepoints\": [265], \"characters\": \"\\u0109\" },\n  \"&Cconint;\": { \"codepoints\": [8752], \"characters\": \"\\u2230\" },\n  \"&ccups;\": { \"codepoints\": [10828], \"characters\": \"\\u2A4C\" },\n  \"&ccupssm;\": { \"codepoints\": [10832], \"characters\": \"\\u2A50\" },\n  \"&Cdot;\": { \"codepoints\": [266], \"characters\": \"\\u010A\" },\n  \"&cdot;\": { \"codepoints\": [267], \"characters\": \"\\u010B\" },\n  \"&cedil;\": { \"codepoints\": [184], \"characters\": \"\\u00B8\" },\n  \"&cedil\": { \"codepoints\": [184], \"characters\": \"\\u00B8\" },\n  \"&Cedilla;\": { \"codepoints\": [184], \"characters\": \"\\u00B8\" },\n  \"&cemptyv;\": { \"codepoints\": [10674], \"characters\": \"\\u29B2\" },\n  \"&cent;\": { \"codepoints\": [162], \"characters\": \"\\u00A2\" },\n  \"&cent\": { \"codepoints\": [162], \"characters\": \"\\u00A2\" },\n  \"&centerdot;\": { \"codepoints\": [183], \"characters\": \"\\u00B7\" },\n  \"&CenterDot;\": { \"codepoints\": [183], \"characters\": \"\\u00B7\" },\n  \"&cfr;\": { \"codepoints\": [120096], \"characters\": \"\\uD835\\uDD20\" },\n  \"&Cfr;\": { \"codepoints\": [8493], \"characters\": \"\\u212D\" },\n  \"&CHcy;\": { \"codepoints\": [1063], \"characters\": \"\\u0427\" },\n  \"&chcy;\": { \"codepoints\": [1095], \"characters\": \"\\u0447\" },\n  \"&check;\": { \"codepoints\": [10003], \"characters\": \"\\u2713\" },\n  \"&checkmark;\": { \"codepoints\": [10003], \"characters\": \"\\u2713\" },\n  \"&Chi;\": { \"codepoints\": [935], \"characters\": \"\\u03A7\" },\n  \"&chi;\": { \"codepoints\": [967], \"characters\": \"\\u03C7\" },\n  \"&circ;\": { \"codepoints\": [710], \"characters\": \"\\u02C6\" },\n  \"&circeq;\": { \"codepoints\": [8791], \"characters\": \"\\u2257\" },\n  \"&circlearrowleft;\": { \"codepoints\": [8634], \"characters\": \"\\u21BA\" },\n  \"&circlearrowright;\": { \"codepoints\": [8635], \"characters\": \"\\u21BB\" },\n  \"&circledast;\": { \"codepoints\": [8859], \"characters\": \"\\u229B\" },\n  \"&circledcirc;\": { \"codepoints\": [8858], \"characters\": \"\\u229A\" },\n  \"&circleddash;\": { \"codepoints\": [8861], \"characters\": \"\\u229D\" },\n  \"&CircleDot;\": { \"codepoints\": [8857], \"characters\": \"\\u2299\" },\n  \"&circledR;\": { \"codepoints\": [174], \"characters\": \"\\u00AE\" },\n  \"&circledS;\": { \"codepoints\": [9416], \"characters\": \"\\u24C8\" },\n  \"&CircleMinus;\": { \"codepoints\": [8854], \"characters\": \"\\u2296\" },\n  \"&CirclePlus;\": { \"codepoints\": [8853], \"characters\": \"\\u2295\" },\n  \"&CircleTimes;\": { \"codepoints\": [8855], \"characters\": \"\\u2297\" },\n  \"&cir;\": { \"codepoints\": [9675], \"characters\": \"\\u25CB\" },\n  \"&cirE;\": { \"codepoints\": [10691], \"characters\": \"\\u29C3\" },\n  \"&cire;\": { \"codepoints\": [8791], \"characters\": \"\\u2257\" },\n  \"&cirfnint;\": { \"codepoints\": [10768], \"characters\": \"\\u2A10\" },\n  \"&cirmid;\": { \"codepoints\": [10991], \"characters\": \"\\u2AEF\" },\n  \"&cirscir;\": { \"codepoints\": [10690], \"characters\": \"\\u29C2\" },\n  \"&ClockwiseContourIntegral;\": { \"codepoints\": [8754], \"characters\": \"\\u2232\" },\n  \"&CloseCurlyDoubleQuote;\": { \"codepoints\": [8221], \"characters\": \"\\u201D\" },\n  \"&CloseCurlyQuote;\": { \"codepoints\": [8217], \"characters\": \"\\u2019\" },\n  \"&clubs;\": { \"codepoints\": [9827], \"characters\": \"\\u2663\" },\n  \"&clubsuit;\": { \"codepoints\": [9827], \"characters\": \"\\u2663\" },\n  \"&colon;\": { \"codepoints\": [58], \"characters\": \"\\u003A\" },\n  \"&Colon;\": { \"codepoints\": [8759], \"characters\": \"\\u2237\" },\n  \"&Colone;\": { \"codepoints\": [10868], \"characters\": \"\\u2A74\" },\n  \"&colone;\": { \"codepoints\": [8788], \"characters\": \"\\u2254\" },\n  \"&coloneq;\": { \"codepoints\": [8788], \"characters\": \"\\u2254\" },\n  \"&comma;\": { \"codepoints\": [44], \"characters\": \"\\u002C\" },\n  \"&commat;\": { \"codepoints\": [64], \"characters\": \"\\u0040\" },\n  \"&comp;\": { \"codepoints\": [8705], \"characters\": \"\\u2201\" },\n  \"&compfn;\": { \"codepoints\": [8728], \"characters\": \"\\u2218\" },\n  \"&complement;\": { \"codepoints\": [8705], \"characters\": \"\\u2201\" },\n  \"&complexes;\": { \"codepoints\": [8450], \"characters\": \"\\u2102\" },\n  \"&cong;\": { \"codepoints\": [8773], \"characters\": \"\\u2245\" },\n  \"&congdot;\": { \"codepoints\": [10861], \"characters\": \"\\u2A6D\" },\n  \"&Congruent;\": { \"codepoints\": [8801], \"characters\": \"\\u2261\" },\n  \"&conint;\": { \"codepoints\": [8750], \"characters\": \"\\u222E\" },\n  \"&Conint;\": { \"codepoints\": [8751], \"characters\": \"\\u222F\" },\n  \"&ContourIntegral;\": { \"codepoints\": [8750], \"characters\": \"\\u222E\" },\n  \"&copf;\": { \"codepoints\": [120148], \"characters\": \"\\uD835\\uDD54\" },\n  \"&Copf;\": { \"codepoints\": [8450], \"characters\": \"\\u2102\" },\n  \"&coprod;\": { \"codepoints\": [8720], \"characters\": \"\\u2210\" },\n  \"&Coproduct;\": { \"codepoints\": [8720], \"characters\": \"\\u2210\" },\n  \"&copy;\": { \"codepoints\": [169], \"characters\": \"\\u00A9\" },\n  \"&copy\": { \"codepoints\": [169], \"characters\": \"\\u00A9\" },\n  \"&COPY;\": { \"codepoints\": [169], \"characters\": \"\\u00A9\" },\n  \"&COPY\": { \"codepoints\": [169], \"characters\": \"\\u00A9\" },\n  \"&copysr;\": { \"codepoints\": [8471], \"characters\": \"\\u2117\" },\n  \"&CounterClockwiseContourIntegral;\": { \"codepoints\": [8755], \"characters\": \"\\u2233\" },\n  \"&crarr;\": { \"codepoints\": [8629], \"characters\": \"\\u21B5\" },\n  \"&cross;\": { \"codepoints\": [10007], \"characters\": \"\\u2717\" },\n  \"&Cross;\": { \"codepoints\": [10799], \"characters\": \"\\u2A2F\" },\n  \"&Cscr;\": { \"codepoints\": [119966], \"characters\": \"\\uD835\\uDC9E\" },\n  \"&cscr;\": { \"codepoints\": [119992], \"characters\": \"\\uD835\\uDCB8\" },\n  \"&csub;\": { \"codepoints\": [10959], \"characters\": \"\\u2ACF\" },\n  \"&csube;\": { \"codepoints\": [10961], \"characters\": \"\\u2AD1\" },\n  \"&csup;\": { \"codepoints\": [10960], \"characters\": \"\\u2AD0\" },\n  \"&csupe;\": { \"codepoints\": [10962], \"characters\": \"\\u2AD2\" },\n  \"&ctdot;\": { \"codepoints\": [8943], \"characters\": \"\\u22EF\" },\n  \"&cudarrl;\": { \"codepoints\": [10552], \"characters\": \"\\u2938\" },\n  \"&cudarrr;\": { \"codepoints\": [10549], \"characters\": \"\\u2935\" },\n  \"&cuepr;\": { \"codepoints\": [8926], \"characters\": \"\\u22DE\" },\n  \"&cuesc;\": { \"codepoints\": [8927], \"characters\": \"\\u22DF\" },\n  \"&cularr;\": { \"codepoints\": [8630], \"characters\": \"\\u21B6\" },\n  \"&cularrp;\": { \"codepoints\": [10557], \"characters\": \"\\u293D\" },\n  \"&cupbrcap;\": { \"codepoints\": [10824], \"characters\": \"\\u2A48\" },\n  \"&cupcap;\": { \"codepoints\": [10822], \"characters\": \"\\u2A46\" },\n  \"&CupCap;\": { \"codepoints\": [8781], \"characters\": \"\\u224D\" },\n  \"&cup;\": { \"codepoints\": [8746], \"characters\": \"\\u222A\" },\n  \"&Cup;\": { \"codepoints\": [8915], \"characters\": \"\\u22D3\" },\n  \"&cupcup;\": { \"codepoints\": [10826], \"characters\": \"\\u2A4A\" },\n  \"&cupdot;\": { \"codepoints\": [8845], \"characters\": \"\\u228D\" },\n  \"&cupor;\": { \"codepoints\": [10821], \"characters\": \"\\u2A45\" },\n  \"&cups;\": { \"codepoints\": [8746, 65024], \"characters\": \"\\u222A\\uFE00\" },\n  \"&curarr;\": { \"codepoints\": [8631], \"characters\": \"\\u21B7\" },\n  \"&curarrm;\": { \"codepoints\": [10556], \"characters\": \"\\u293C\" },\n  \"&curlyeqprec;\": { \"codepoints\": [8926], \"characters\": \"\\u22DE\" },\n  \"&curlyeqsucc;\": { \"codepoints\": [8927], \"characters\": \"\\u22DF\" },\n  \"&curlyvee;\": { \"codepoints\": [8910], \"characters\": \"\\u22CE\" },\n  \"&curlywedge;\": { \"codepoints\": [8911], \"characters\": \"\\u22CF\" },\n  \"&curren;\": { \"codepoints\": [164], \"characters\": \"\\u00A4\" },\n  \"&curren\": { \"codepoints\": [164], \"characters\": \"\\u00A4\" },\n  \"&curvearrowleft;\": { \"codepoints\": [8630], \"characters\": \"\\u21B6\" },\n  \"&curvearrowright;\": { \"codepoints\": [8631], \"characters\": \"\\u21B7\" },\n  \"&cuvee;\": { \"codepoints\": [8910], \"characters\": \"\\u22CE\" },\n  \"&cuwed;\": { \"codepoints\": [8911], \"characters\": \"\\u22CF\" },\n  \"&cwconint;\": { \"codepoints\": [8754], \"characters\": \"\\u2232\" },\n  \"&cwint;\": { \"codepoints\": [8753], \"characters\": \"\\u2231\" },\n  \"&cylcty;\": { \"codepoints\": [9005], \"characters\": \"\\u232D\" },\n  \"&dagger;\": { \"codepoints\": [8224], \"characters\": \"\\u2020\" },\n  \"&Dagger;\": { \"codepoints\": [8225], \"characters\": \"\\u2021\" },\n  \"&daleth;\": { \"codepoints\": [8504], \"characters\": \"\\u2138\" },\n  \"&darr;\": { \"codepoints\": [8595], \"characters\": \"\\u2193\" },\n  \"&Darr;\": { \"codepoints\": [8609], \"characters\": \"\\u21A1\" },\n  \"&dArr;\": { \"codepoints\": [8659], \"characters\": \"\\u21D3\" },\n  \"&dash;\": { \"codepoints\": [8208], \"characters\": \"\\u2010\" },\n  \"&Dashv;\": { \"codepoints\": [10980], \"characters\": \"\\u2AE4\" },\n  \"&dashv;\": { \"codepoints\": [8867], \"characters\": \"\\u22A3\" },\n  \"&dbkarow;\": { \"codepoints\": [10511], \"characters\": \"\\u290F\" },\n  \"&dblac;\": { \"codepoints\": [733], \"characters\": \"\\u02DD\" },\n  \"&Dcaron;\": { \"codepoints\": [270], \"characters\": \"\\u010E\" },\n  \"&dcaron;\": { \"codepoints\": [271], \"characters\": \"\\u010F\" },\n  \"&Dcy;\": { \"codepoints\": [1044], \"characters\": \"\\u0414\" },\n  \"&dcy;\": { \"codepoints\": [1076], \"characters\": \"\\u0434\" },\n  \"&ddagger;\": { \"codepoints\": [8225], \"characters\": \"\\u2021\" },\n  \"&ddarr;\": { \"codepoints\": [8650], \"characters\": \"\\u21CA\" },\n  \"&DD;\": { \"codepoints\": [8517], \"characters\": \"\\u2145\" },\n  \"&dd;\": { \"codepoints\": [8518], \"characters\": \"\\u2146\" },\n  \"&DDotrahd;\": { \"codepoints\": [10513], \"characters\": \"\\u2911\" },\n  \"&ddotseq;\": { \"codepoints\": [10871], \"characters\": \"\\u2A77\" },\n  \"&deg;\": { \"codepoints\": [176], \"characters\": \"\\u00B0\" },\n  \"&deg\": { \"codepoints\": [176], \"characters\": \"\\u00B0\" },\n  \"&Del;\": { \"codepoints\": [8711], \"characters\": \"\\u2207\" },\n  \"&Delta;\": { \"codepoints\": [916], \"characters\": \"\\u0394\" },\n  \"&delta;\": { \"codepoints\": [948], \"characters\": \"\\u03B4\" },\n  \"&demptyv;\": { \"codepoints\": [10673], \"characters\": \"\\u29B1\" },\n  \"&dfisht;\": { \"codepoints\": [10623], \"characters\": \"\\u297F\" },\n  \"&Dfr;\": { \"codepoints\": [120071], \"characters\": \"\\uD835\\uDD07\" },\n  \"&dfr;\": { \"codepoints\": [120097], \"characters\": \"\\uD835\\uDD21\" },\n  \"&dHar;\": { \"codepoints\": [10597], \"characters\": \"\\u2965\" },\n  \"&dharl;\": { \"codepoints\": [8643], \"characters\": \"\\u21C3\" },\n  \"&dharr;\": { \"codepoints\": [8642], \"characters\": \"\\u21C2\" },\n  \"&DiacriticalAcute;\": { \"codepoints\": [180], \"characters\": \"\\u00B4\" },\n  \"&DiacriticalDot;\": { \"codepoints\": [729], \"characters\": \"\\u02D9\" },\n  \"&DiacriticalDoubleAcute;\": { \"codepoints\": [733], \"characters\": \"\\u02DD\" },\n  \"&DiacriticalGrave;\": { \"codepoints\": [96], \"characters\": \"\\u0060\" },\n  \"&DiacriticalTilde;\": { \"codepoints\": [732], \"characters\": \"\\u02DC\" },\n  \"&diam;\": { \"codepoints\": [8900], \"characters\": \"\\u22C4\" },\n  \"&diamond;\": { \"codepoints\": [8900], \"characters\": \"\\u22C4\" },\n  \"&Diamond;\": { \"codepoints\": [8900], \"characters\": \"\\u22C4\" },\n  \"&diamondsuit;\": { \"codepoints\": [9830], \"characters\": \"\\u2666\" },\n  \"&diams;\": { \"codepoints\": [9830], \"characters\": \"\\u2666\" },\n  \"&die;\": { \"codepoints\": [168], \"characters\": \"\\u00A8\" },\n  \"&DifferentialD;\": { \"codepoints\": [8518], \"characters\": \"\\u2146\" },\n  \"&digamma;\": { \"codepoints\": [989], \"characters\": \"\\u03DD\" },\n  \"&disin;\": { \"codepoints\": [8946], \"characters\": \"\\u22F2\" },\n  \"&div;\": { \"codepoints\": [247], \"characters\": \"\\u00F7\" },\n  \"&divide;\": { \"codepoints\": [247], \"characters\": \"\\u00F7\" },\n  \"&divide\": { \"codepoints\": [247], \"characters\": \"\\u00F7\" },\n  \"&divideontimes;\": { \"codepoints\": [8903], \"characters\": \"\\u22C7\" },\n  \"&divonx;\": { \"codepoints\": [8903], \"characters\": \"\\u22C7\" },\n  \"&DJcy;\": { \"codepoints\": [1026], \"characters\": \"\\u0402\" },\n  \"&djcy;\": { \"codepoints\": [1106], \"characters\": \"\\u0452\" },\n  \"&dlcorn;\": { \"codepoints\": [8990], \"characters\": \"\\u231E\" },\n  \"&dlcrop;\": { \"codepoints\": [8973], \"characters\": \"\\u230D\" },\n  \"&dollar;\": { \"codepoints\": [36], \"characters\": \"\\u0024\" },\n  \"&Dopf;\": { \"codepoints\": [120123], \"characters\": \"\\uD835\\uDD3B\" },\n  \"&dopf;\": { \"codepoints\": [120149], \"characters\": \"\\uD835\\uDD55\" },\n  \"&Dot;\": { \"codepoints\": [168], \"characters\": \"\\u00A8\" },\n  \"&dot;\": { \"codepoints\": [729], \"characters\": \"\\u02D9\" },\n  \"&DotDot;\": { \"codepoints\": [8412], \"characters\": \"\\u20DC\" },\n  \"&doteq;\": { \"codepoints\": [8784], \"characters\": \"\\u2250\" },\n  \"&doteqdot;\": { \"codepoints\": [8785], \"characters\": \"\\u2251\" },\n  \"&DotEqual;\": { \"codepoints\": [8784], \"characters\": \"\\u2250\" },\n  \"&dotminus;\": { \"codepoints\": [8760], \"characters\": \"\\u2238\" },\n  \"&dotplus;\": { \"codepoints\": [8724], \"characters\": \"\\u2214\" },\n  \"&dotsquare;\": { \"codepoints\": [8865], \"characters\": \"\\u22A1\" },\n  \"&doublebarwedge;\": { \"codepoints\": [8966], \"characters\": \"\\u2306\" },\n  \"&DoubleContourIntegral;\": { \"codepoints\": [8751], \"characters\": \"\\u222F\" },\n  \"&DoubleDot;\": { \"codepoints\": [168], \"characters\": \"\\u00A8\" },\n  \"&DoubleDownArrow;\": { \"codepoints\": [8659], \"characters\": \"\\u21D3\" },\n  \"&DoubleLeftArrow;\": { \"codepoints\": [8656], \"characters\": \"\\u21D0\" },\n  \"&DoubleLeftRightArrow;\": { \"codepoints\": [8660], \"characters\": \"\\u21D4\" },\n  \"&DoubleLeftTee;\": { \"codepoints\": [10980], \"characters\": \"\\u2AE4\" },\n  \"&DoubleLongLeftArrow;\": { \"codepoints\": [10232], \"characters\": \"\\u27F8\" },\n  \"&DoubleLongLeftRightArrow;\": { \"codepoints\": [10234], \"characters\": \"\\u27FA\" },\n  \"&DoubleLongRightArrow;\": { \"codepoints\": [10233], \"characters\": \"\\u27F9\" },\n  \"&DoubleRightArrow;\": { \"codepoints\": [8658], \"characters\": \"\\u21D2\" },\n  \"&DoubleRightTee;\": { \"codepoints\": [8872], \"characters\": \"\\u22A8\" },\n  \"&DoubleUpArrow;\": { \"codepoints\": [8657], \"characters\": \"\\u21D1\" },\n  \"&DoubleUpDownArrow;\": { \"codepoints\": [8661], \"characters\": \"\\u21D5\" },\n  \"&DoubleVerticalBar;\": { \"codepoints\": [8741], \"characters\": \"\\u2225\" },\n  \"&DownArrowBar;\": { \"codepoints\": [10515], \"characters\": \"\\u2913\" },\n  \"&downarrow;\": { \"codepoints\": [8595], \"characters\": \"\\u2193\" },\n  \"&DownArrow;\": { \"codepoints\": [8595], \"characters\": \"\\u2193\" },\n  \"&Downarrow;\": { \"codepoints\": [8659], \"characters\": \"\\u21D3\" },\n  \"&DownArrowUpArrow;\": { \"codepoints\": [8693], \"characters\": \"\\u21F5\" },\n  \"&DownBreve;\": { \"codepoints\": [785], \"characters\": \"\\u0311\" },\n  \"&downdownarrows;\": { \"codepoints\": [8650], \"characters\": \"\\u21CA\" },\n  \"&downharpoonleft;\": { \"codepoints\": [8643], \"characters\": \"\\u21C3\" },\n  \"&downharpoonright;\": { \"codepoints\": [8642], \"characters\": \"\\u21C2\" },\n  \"&DownLeftRightVector;\": { \"codepoints\": [10576], \"characters\": \"\\u2950\" },\n  \"&DownLeftTeeVector;\": { \"codepoints\": [10590], \"characters\": \"\\u295E\" },\n  \"&DownLeftVectorBar;\": { \"codepoints\": [10582], \"characters\": \"\\u2956\" },\n  \"&DownLeftVector;\": { \"codepoints\": [8637], \"characters\": \"\\u21BD\" },\n  \"&DownRightTeeVector;\": { \"codepoints\": [10591], \"characters\": \"\\u295F\" },\n  \"&DownRightVectorBar;\": { \"codepoints\": [10583], \"characters\": \"\\u2957\" },\n  \"&DownRightVector;\": { \"codepoints\": [8641], \"characters\": \"\\u21C1\" },\n  \"&DownTeeArrow;\": { \"codepoints\": [8615], \"characters\": \"\\u21A7\" },\n  \"&DownTee;\": { \"codepoints\": [8868], \"characters\": \"\\u22A4\" },\n  \"&drbkarow;\": { \"codepoints\": [10512], \"characters\": \"\\u2910\" },\n  \"&drcorn;\": { \"codepoints\": [8991], \"characters\": \"\\u231F\" },\n  \"&drcrop;\": { \"codepoints\": [8972], \"characters\": \"\\u230C\" },\n  \"&Dscr;\": { \"codepoints\": [119967], \"characters\": \"\\uD835\\uDC9F\" },\n  \"&dscr;\": { \"codepoints\": [119993], \"characters\": \"\\uD835\\uDCB9\" },\n  \"&DScy;\": { \"codepoints\": [1029], \"characters\": \"\\u0405\" },\n  \"&dscy;\": { \"codepoints\": [1109], \"characters\": \"\\u0455\" },\n  \"&dsol;\": { \"codepoints\": [10742], \"characters\": \"\\u29F6\" },\n  \"&Dstrok;\": { \"codepoints\": [272], \"characters\": \"\\u0110\" },\n  \"&dstrok;\": { \"codepoints\": [273], \"characters\": \"\\u0111\" },\n  \"&dtdot;\": { \"codepoints\": [8945], \"characters\": \"\\u22F1\" },\n  \"&dtri;\": { \"codepoints\": [9663], \"characters\": \"\\u25BF\" },\n  \"&dtrif;\": { \"codepoints\": [9662], \"characters\": \"\\u25BE\" },\n  \"&duarr;\": { \"codepoints\": [8693], \"characters\": \"\\u21F5\" },\n  \"&duhar;\": { \"codepoints\": [10607], \"characters\": \"\\u296F\" },\n  \"&dwangle;\": { \"codepoints\": [10662], \"characters\": \"\\u29A6\" },\n  \"&DZcy;\": { \"codepoints\": [1039], \"characters\": \"\\u040F\" },\n  \"&dzcy;\": { \"codepoints\": [1119], \"characters\": \"\\u045F\" },\n  \"&dzigrarr;\": { \"codepoints\": [10239], \"characters\": \"\\u27FF\" },\n  \"&Eacute;\": { \"codepoints\": [201], \"characters\": \"\\u00C9\" },\n  \"&Eacute\": { \"codepoints\": [201], \"characters\": \"\\u00C9\" },\n  \"&eacute;\": { \"codepoints\": [233], \"characters\": \"\\u00E9\" },\n  \"&eacute\": { \"codepoints\": [233], \"characters\": \"\\u00E9\" },\n  \"&easter;\": { \"codepoints\": [10862], \"characters\": \"\\u2A6E\" },\n  \"&Ecaron;\": { \"codepoints\": [282], \"characters\": \"\\u011A\" },\n  \"&ecaron;\": { \"codepoints\": [283], \"characters\": \"\\u011B\" },\n  \"&Ecirc;\": { \"codepoints\": [202], \"characters\": \"\\u00CA\" },\n  \"&Ecirc\": { \"codepoints\": [202], \"characters\": \"\\u00CA\" },\n  \"&ecirc;\": { \"codepoints\": [234], \"characters\": \"\\u00EA\" },\n  \"&ecirc\": { \"codepoints\": [234], \"characters\": \"\\u00EA\" },\n  \"&ecir;\": { \"codepoints\": [8790], \"characters\": \"\\u2256\" },\n  \"&ecolon;\": { \"codepoints\": [8789], \"characters\": \"\\u2255\" },\n  \"&Ecy;\": { \"codepoints\": [1069], \"characters\": \"\\u042D\" },\n  \"&ecy;\": { \"codepoints\": [1101], \"characters\": \"\\u044D\" },\n  \"&eDDot;\": { \"codepoints\": [10871], \"characters\": \"\\u2A77\" },\n  \"&Edot;\": { \"codepoints\": [278], \"characters\": \"\\u0116\" },\n  \"&edot;\": { \"codepoints\": [279], \"characters\": \"\\u0117\" },\n  \"&eDot;\": { \"codepoints\": [8785], \"characters\": \"\\u2251\" },\n  \"&ee;\": { \"codepoints\": [8519], \"characters\": \"\\u2147\" },\n  \"&efDot;\": { \"codepoints\": [8786], \"characters\": \"\\u2252\" },\n  \"&Efr;\": { \"codepoints\": [120072], \"characters\": \"\\uD835\\uDD08\" },\n  \"&efr;\": { \"codepoints\": [120098], \"characters\": \"\\uD835\\uDD22\" },\n  \"&eg;\": { \"codepoints\": [10906], \"characters\": \"\\u2A9A\" },\n  \"&Egrave;\": { \"codepoints\": [200], \"characters\": \"\\u00C8\" },\n  \"&Egrave\": { \"codepoints\": [200], \"characters\": \"\\u00C8\" },\n  \"&egrave;\": { \"codepoints\": [232], \"characters\": \"\\u00E8\" },\n  \"&egrave\": { \"codepoints\": [232], \"characters\": \"\\u00E8\" },\n  \"&egs;\": { \"codepoints\": [10902], \"characters\": \"\\u2A96\" },\n  \"&egsdot;\": { \"codepoints\": [10904], \"characters\": \"\\u2A98\" },\n  \"&el;\": { \"codepoints\": [10905], \"characters\": \"\\u2A99\" },\n  \"&Element;\": { \"codepoints\": [8712], \"characters\": \"\\u2208\" },\n  \"&elinters;\": { \"codepoints\": [9191], \"characters\": \"\\u23E7\" },\n  \"&ell;\": { \"codepoints\": [8467], \"characters\": \"\\u2113\" },\n  \"&els;\": { \"codepoints\": [10901], \"characters\": \"\\u2A95\" },\n  \"&elsdot;\": { \"codepoints\": [10903], \"characters\": \"\\u2A97\" },\n  \"&Emacr;\": { \"codepoints\": [274], \"characters\": \"\\u0112\" },\n  \"&emacr;\": { \"codepoints\": [275], \"characters\": \"\\u0113\" },\n  \"&empty;\": { \"codepoints\": [8709], \"characters\": \"\\u2205\" },\n  \"&emptyset;\": { \"codepoints\": [8709], \"characters\": \"\\u2205\" },\n  \"&EmptySmallSquare;\": { \"codepoints\": [9723], \"characters\": \"\\u25FB\" },\n  \"&emptyv;\": { \"codepoints\": [8709], \"characters\": \"\\u2205\" },\n  \"&EmptyVerySmallSquare;\": { \"codepoints\": [9643], \"characters\": \"\\u25AB\" },\n  \"&emsp13;\": { \"codepoints\": [8196], \"characters\": \"\\u2004\" },\n  \"&emsp14;\": { \"codepoints\": [8197], \"characters\": \"\\u2005\" },\n  \"&emsp;\": { \"codepoints\": [8195], \"characters\": \"\\u2003\" },\n  \"&ENG;\": { \"codepoints\": [330], \"characters\": \"\\u014A\" },\n  \"&eng;\": { \"codepoints\": [331], \"characters\": \"\\u014B\" },\n  \"&ensp;\": { \"codepoints\": [8194], \"characters\": \"\\u2002\" },\n  \"&Eogon;\": { \"codepoints\": [280], \"characters\": \"\\u0118\" },\n  \"&eogon;\": { \"codepoints\": [281], \"characters\": \"\\u0119\" },\n  \"&Eopf;\": { \"codepoints\": [120124], \"characters\": \"\\uD835\\uDD3C\" },\n  \"&eopf;\": { \"codepoints\": [120150], \"characters\": \"\\uD835\\uDD56\" },\n  \"&epar;\": { \"codepoints\": [8917], \"characters\": \"\\u22D5\" },\n  \"&eparsl;\": { \"codepoints\": [10723], \"characters\": \"\\u29E3\" },\n  \"&eplus;\": { \"codepoints\": [10865], \"characters\": \"\\u2A71\" },\n  \"&epsi;\": { \"codepoints\": [949], \"characters\": \"\\u03B5\" },\n  \"&Epsilon;\": { \"codepoints\": [917], \"characters\": \"\\u0395\" },\n  \"&epsilon;\": { \"codepoints\": [949], \"characters\": \"\\u03B5\" },\n  \"&epsiv;\": { \"codepoints\": [1013], \"characters\": \"\\u03F5\" },\n  \"&eqcirc;\": { \"codepoints\": [8790], \"characters\": \"\\u2256\" },\n  \"&eqcolon;\": { \"codepoints\": [8789], \"characters\": \"\\u2255\" },\n  \"&eqsim;\": { \"codepoints\": [8770], \"characters\": \"\\u2242\" },\n  \"&eqslantgtr;\": { \"codepoints\": [10902], \"characters\": \"\\u2A96\" },\n  \"&eqslantless;\": { \"codepoints\": [10901], \"characters\": \"\\u2A95\" },\n  \"&Equal;\": { \"codepoints\": [10869], \"characters\": \"\\u2A75\" },\n  \"&equals;\": { \"codepoints\": [61], \"characters\": \"\\u003D\" },\n  \"&EqualTilde;\": { \"codepoints\": [8770], \"characters\": \"\\u2242\" },\n  \"&equest;\": { \"codepoints\": [8799], \"characters\": \"\\u225F\" },\n  \"&Equilibrium;\": { \"codepoints\": [8652], \"characters\": \"\\u21CC\" },\n  \"&equiv;\": { \"codepoints\": [8801], \"characters\": \"\\u2261\" },\n  \"&equivDD;\": { \"codepoints\": [10872], \"characters\": \"\\u2A78\" },\n  \"&eqvparsl;\": { \"codepoints\": [10725], \"characters\": \"\\u29E5\" },\n  \"&erarr;\": { \"codepoints\": [10609], \"characters\": \"\\u2971\" },\n  \"&erDot;\": { \"codepoints\": [8787], \"characters\": \"\\u2253\" },\n  \"&escr;\": { \"codepoints\": [8495], \"characters\": \"\\u212F\" },\n  \"&Escr;\": { \"codepoints\": [8496], \"characters\": \"\\u2130\" },\n  \"&esdot;\": { \"codepoints\": [8784], \"characters\": \"\\u2250\" },\n  \"&Esim;\": { \"codepoints\": [10867], \"characters\": \"\\u2A73\" },\n  \"&esim;\": { \"codepoints\": [8770], \"characters\": \"\\u2242\" },\n  \"&Eta;\": { \"codepoints\": [919], \"characters\": \"\\u0397\" },\n  \"&eta;\": { \"codepoints\": [951], \"characters\": \"\\u03B7\" },\n  \"&ETH;\": { \"codepoints\": [208], \"characters\": \"\\u00D0\" },\n  \"&ETH\": { \"codepoints\": [208], \"characters\": \"\\u00D0\" },\n  \"&eth;\": { \"codepoints\": [240], \"characters\": \"\\u00F0\" },\n  \"&eth\": { \"codepoints\": [240], \"characters\": \"\\u00F0\" },\n  \"&Euml;\": { \"codepoints\": [203], \"characters\": \"\\u00CB\" },\n  \"&Euml\": { \"codepoints\": [203], \"characters\": \"\\u00CB\" },\n  \"&euml;\": { \"codepoints\": [235], \"characters\": \"\\u00EB\" },\n  \"&euml\": { \"codepoints\": [235], \"characters\": \"\\u00EB\" },\n  \"&euro;\": { \"codepoints\": [8364], \"characters\": \"\\u20AC\" },\n  \"&excl;\": { \"codepoints\": [33], \"characters\": \"\\u0021\" },\n  \"&exist;\": { \"codepoints\": [8707], \"characters\": \"\\u2203\" },\n  \"&Exists;\": { \"codepoints\": [8707], \"characters\": \"\\u2203\" },\n  \"&expectation;\": { \"codepoints\": [8496], \"characters\": \"\\u2130\" },\n  \"&exponentiale;\": { \"codepoints\": [8519], \"characters\": \"\\u2147\" },\n  \"&ExponentialE;\": { \"codepoints\": [8519], \"characters\": \"\\u2147\" },\n  \"&fallingdotseq;\": { \"codepoints\": [8786], \"characters\": \"\\u2252\" },\n  \"&Fcy;\": { \"codepoints\": [1060], \"characters\": \"\\u0424\" },\n  \"&fcy;\": { \"codepoints\": [1092], \"characters\": \"\\u0444\" },\n  \"&female;\": { \"codepoints\": [9792], \"characters\": \"\\u2640\" },\n  \"&ffilig;\": { \"codepoints\": [64259], \"characters\": \"\\uFB03\" },\n  \"&fflig;\": { \"codepoints\": [64256], \"characters\": \"\\uFB00\" },\n  \"&ffllig;\": { \"codepoints\": [64260], \"characters\": \"\\uFB04\" },\n  \"&Ffr;\": { \"codepoints\": [120073], \"characters\": \"\\uD835\\uDD09\" },\n  \"&ffr;\": { \"codepoints\": [120099], \"characters\": \"\\uD835\\uDD23\" },\n  \"&filig;\": { \"codepoints\": [64257], \"characters\": \"\\uFB01\" },\n  \"&FilledSmallSquare;\": { \"codepoints\": [9724], \"characters\": \"\\u25FC\" },\n  \"&FilledVerySmallSquare;\": { \"codepoints\": [9642], \"characters\": \"\\u25AA\" },\n  \"&fjlig;\": { \"codepoints\": [102, 106], \"characters\": \"\\u0066\\u006A\" },\n  \"&flat;\": { \"codepoints\": [9837], \"characters\": \"\\u266D\" },\n  \"&fllig;\": { \"codepoints\": [64258], \"characters\": \"\\uFB02\" },\n  \"&fltns;\": { \"codepoints\": [9649], \"characters\": \"\\u25B1\" },\n  \"&fnof;\": { \"codepoints\": [402], \"characters\": \"\\u0192\" },\n  \"&Fopf;\": { \"codepoints\": [120125], \"characters\": \"\\uD835\\uDD3D\" },\n  \"&fopf;\": { \"codepoints\": [120151], \"characters\": \"\\uD835\\uDD57\" },\n  \"&forall;\": { \"codepoints\": [8704], \"characters\": \"\\u2200\" },\n  \"&ForAll;\": { \"codepoints\": [8704], \"characters\": \"\\u2200\" },\n  \"&fork;\": { \"codepoints\": [8916], \"characters\": \"\\u22D4\" },\n  \"&forkv;\": { \"codepoints\": [10969], \"characters\": \"\\u2AD9\" },\n  \"&Fouriertrf;\": { \"codepoints\": [8497], \"characters\": \"\\u2131\" },\n  \"&fpartint;\": { \"codepoints\": [10765], \"characters\": \"\\u2A0D\" },\n  \"&frac12;\": { \"codepoints\": [189], \"characters\": \"\\u00BD\" },\n  \"&frac12\": { \"codepoints\": [189], \"characters\": \"\\u00BD\" },\n  \"&frac13;\": { \"codepoints\": [8531], \"characters\": \"\\u2153\" },\n  \"&frac14;\": { \"codepoints\": [188], \"characters\": \"\\u00BC\" },\n  \"&frac14\": { \"codepoints\": [188], \"characters\": \"\\u00BC\" },\n  \"&frac15;\": { \"codepoints\": [8533], \"characters\": \"\\u2155\" },\n  \"&frac16;\": { \"codepoints\": [8537], \"characters\": \"\\u2159\" },\n  \"&frac18;\": { \"codepoints\": [8539], \"characters\": \"\\u215B\" },\n  \"&frac23;\": { \"codepoints\": [8532], \"characters\": \"\\u2154\" },\n  \"&frac25;\": { \"codepoints\": [8534], \"characters\": \"\\u2156\" },\n  \"&frac34;\": { \"codepoints\": [190], \"characters\": \"\\u00BE\" },\n  \"&frac34\": { \"codepoints\": [190], \"characters\": \"\\u00BE\" },\n  \"&frac35;\": { \"codepoints\": [8535], \"characters\": \"\\u2157\" },\n  \"&frac38;\": { \"codepoints\": [8540], \"characters\": \"\\u215C\" },\n  \"&frac45;\": { \"codepoints\": [8536], \"characters\": \"\\u2158\" },\n  \"&frac56;\": { \"codepoints\": [8538], \"characters\": \"\\u215A\" },\n  \"&frac58;\": { \"codepoints\": [8541], \"characters\": \"\\u215D\" },\n  \"&frac78;\": { \"codepoints\": [8542], \"characters\": \"\\u215E\" },\n  \"&frasl;\": { \"codepoints\": [8260], \"characters\": \"\\u2044\" },\n  \"&frown;\": { \"codepoints\": [8994], \"characters\": \"\\u2322\" },\n  \"&fscr;\": { \"codepoints\": [119995], \"characters\": \"\\uD835\\uDCBB\" },\n  \"&Fscr;\": { \"codepoints\": [8497], \"characters\": \"\\u2131\" },\n  \"&gacute;\": { \"codepoints\": [501], \"characters\": \"\\u01F5\" },\n  \"&Gamma;\": { \"codepoints\": [915], \"characters\": \"\\u0393\" },\n  \"&gamma;\": { \"codepoints\": [947], \"characters\": \"\\u03B3\" },\n  \"&Gammad;\": { \"codepoints\": [988], \"characters\": \"\\u03DC\" },\n  \"&gammad;\": { \"codepoints\": [989], \"characters\": \"\\u03DD\" },\n  \"&gap;\": { \"codepoints\": [10886], \"characters\": \"\\u2A86\" },\n  \"&Gbreve;\": { \"codepoints\": [286], \"characters\": \"\\u011E\" },\n  \"&gbreve;\": { \"codepoints\": [287], \"characters\": \"\\u011F\" },\n  \"&Gcedil;\": { \"codepoints\": [290], \"characters\": \"\\u0122\" },\n  \"&Gcirc;\": { \"codepoints\": [284], \"characters\": \"\\u011C\" },\n  \"&gcirc;\": { \"codepoints\": [285], \"characters\": \"\\u011D\" },\n  \"&Gcy;\": { \"codepoints\": [1043], \"characters\": \"\\u0413\" },\n  \"&gcy;\": { \"codepoints\": [1075], \"characters\": \"\\u0433\" },\n  \"&Gdot;\": { \"codepoints\": [288], \"characters\": \"\\u0120\" },\n  \"&gdot;\": { \"codepoints\": [289], \"characters\": \"\\u0121\" },\n  \"&ge;\": { \"codepoints\": [8805], \"characters\": \"\\u2265\" },\n  \"&gE;\": { \"codepoints\": [8807], \"characters\": \"\\u2267\" },\n  \"&gEl;\": { \"codepoints\": [10892], \"characters\": \"\\u2A8C\" },\n  \"&gel;\": { \"codepoints\": [8923], \"characters\": \"\\u22DB\" },\n  \"&geq;\": { \"codepoints\": [8805], \"characters\": \"\\u2265\" },\n  \"&geqq;\": { \"codepoints\": [8807], \"characters\": \"\\u2267\" },\n  \"&geqslant;\": { \"codepoints\": [10878], \"characters\": \"\\u2A7E\" },\n  \"&gescc;\": { \"codepoints\": [10921], \"characters\": \"\\u2AA9\" },\n  \"&ges;\": { \"codepoints\": [10878], \"characters\": \"\\u2A7E\" },\n  \"&gesdot;\": { \"codepoints\": [10880], \"characters\": \"\\u2A80\" },\n  \"&gesdoto;\": { \"codepoints\": [10882], \"characters\": \"\\u2A82\" },\n  \"&gesdotol;\": { \"codepoints\": [10884], \"characters\": \"\\u2A84\" },\n  \"&gesl;\": { \"codepoints\": [8923, 65024], \"characters\": \"\\u22DB\\uFE00\" },\n  \"&gesles;\": { \"codepoints\": [10900], \"characters\": \"\\u2A94\" },\n  \"&Gfr;\": { \"codepoints\": [120074], \"characters\": \"\\uD835\\uDD0A\" },\n  \"&gfr;\": { \"codepoints\": [120100], \"characters\": \"\\uD835\\uDD24\" },\n  \"&gg;\": { \"codepoints\": [8811], \"characters\": \"\\u226B\" },\n  \"&Gg;\": { \"codepoints\": [8921], \"characters\": \"\\u22D9\" },\n  \"&ggg;\": { \"codepoints\": [8921], \"characters\": \"\\u22D9\" },\n  \"&gimel;\": { \"codepoints\": [8503], \"characters\": \"\\u2137\" },\n  \"&GJcy;\": { \"codepoints\": [1027], \"characters\": \"\\u0403\" },\n  \"&gjcy;\": { \"codepoints\": [1107], \"characters\": \"\\u0453\" },\n  \"&gla;\": { \"codepoints\": [10917], \"characters\": \"\\u2AA5\" },\n  \"&gl;\": { \"codepoints\": [8823], \"characters\": \"\\u2277\" },\n  \"&glE;\": { \"codepoints\": [10898], \"characters\": \"\\u2A92\" },\n  \"&glj;\": { \"codepoints\": [10916], \"characters\": \"\\u2AA4\" },\n  \"&gnap;\": { \"codepoints\": [10890], \"characters\": \"\\u2A8A\" },\n  \"&gnapprox;\": { \"codepoints\": [10890], \"characters\": \"\\u2A8A\" },\n  \"&gne;\": { \"codepoints\": [10888], \"characters\": \"\\u2A88\" },\n  \"&gnE;\": { \"codepoints\": [8809], \"characters\": \"\\u2269\" },\n  \"&gneq;\": { \"codepoints\": [10888], \"characters\": \"\\u2A88\" },\n  \"&gneqq;\": { \"codepoints\": [8809], \"characters\": \"\\u2269\" },\n  \"&gnsim;\": { \"codepoints\": [8935], \"characters\": \"\\u22E7\" },\n  \"&Gopf;\": { \"codepoints\": [120126], \"characters\": \"\\uD835\\uDD3E\" },\n  \"&gopf;\": { \"codepoints\": [120152], \"characters\": \"\\uD835\\uDD58\" },\n  \"&grave;\": { \"codepoints\": [96], \"characters\": \"\\u0060\" },\n  \"&GreaterEqual;\": { \"codepoints\": [8805], \"characters\": \"\\u2265\" },\n  \"&GreaterEqualLess;\": { \"codepoints\": [8923], \"characters\": \"\\u22DB\" },\n  \"&GreaterFullEqual;\": { \"codepoints\": [8807], \"characters\": \"\\u2267\" },\n  \"&GreaterGreater;\": { \"codepoints\": [10914], \"characters\": \"\\u2AA2\" },\n  \"&GreaterLess;\": { \"codepoints\": [8823], \"characters\": \"\\u2277\" },\n  \"&GreaterSlantEqual;\": { \"codepoints\": [10878], \"characters\": \"\\u2A7E\" },\n  \"&GreaterTilde;\": { \"codepoints\": [8819], \"characters\": \"\\u2273\" },\n  \"&Gscr;\": { \"codepoints\": [119970], \"characters\": \"\\uD835\\uDCA2\" },\n  \"&gscr;\": { \"codepoints\": [8458], \"characters\": \"\\u210A\" },\n  \"&gsim;\": { \"codepoints\": [8819], \"characters\": \"\\u2273\" },\n  \"&gsime;\": { \"codepoints\": [10894], \"characters\": \"\\u2A8E\" },\n  \"&gsiml;\": { \"codepoints\": [10896], \"characters\": \"\\u2A90\" },\n  \"&gtcc;\": { \"codepoints\": [10919], \"characters\": \"\\u2AA7\" },\n  \"&gtcir;\": { \"codepoints\": [10874], \"characters\": \"\\u2A7A\" },\n  \"&gt;\": { \"codepoints\": [62], \"characters\": \"\\u003E\" },\n  \"&gt\": { \"codepoints\": [62], \"characters\": \"\\u003E\" },\n  \"&GT;\": { \"codepoints\": [62], \"characters\": \"\\u003E\" },\n  \"&GT\": { \"codepoints\": [62], \"characters\": \"\\u003E\" },\n  \"&Gt;\": { \"codepoints\": [8811], \"characters\": \"\\u226B\" },\n  \"&gtdot;\": { \"codepoints\": [8919], \"characters\": \"\\u22D7\" },\n  \"&gtlPar;\": { \"codepoints\": [10645], \"characters\": \"\\u2995\" },\n  \"&gtquest;\": { \"codepoints\": [10876], \"characters\": \"\\u2A7C\" },\n  \"&gtrapprox;\": { \"codepoints\": [10886], \"characters\": \"\\u2A86\" },\n  \"&gtrarr;\": { \"codepoints\": [10616], \"characters\": \"\\u2978\" },\n  \"&gtrdot;\": { \"codepoints\": [8919], \"characters\": \"\\u22D7\" },\n  \"&gtreqless;\": { \"codepoints\": [8923], \"characters\": \"\\u22DB\" },\n  \"&gtreqqless;\": { \"codepoints\": [10892], \"characters\": \"\\u2A8C\" },\n  \"&gtrless;\": { \"codepoints\": [8823], \"characters\": \"\\u2277\" },\n  \"&gtrsim;\": { \"codepoints\": [8819], \"characters\": \"\\u2273\" },\n  \"&gvertneqq;\": { \"codepoints\": [8809, 65024], \"characters\": \"\\u2269\\uFE00\" },\n  \"&gvnE;\": { \"codepoints\": [8809, 65024], \"characters\": \"\\u2269\\uFE00\" },\n  \"&Hacek;\": { \"codepoints\": [711], \"characters\": \"\\u02C7\" },\n  \"&hairsp;\": { \"codepoints\": [8202], \"characters\": \"\\u200A\" },\n  \"&half;\": { \"codepoints\": [189], \"characters\": \"\\u00BD\" },\n  \"&hamilt;\": { \"codepoints\": [8459], \"characters\": \"\\u210B\" },\n  \"&HARDcy;\": { \"codepoints\": [1066], \"characters\": \"\\u042A\" },\n  \"&hardcy;\": { \"codepoints\": [1098], \"characters\": \"\\u044A\" },\n  \"&harrcir;\": { \"codepoints\": [10568], \"characters\": \"\\u2948\" },\n  \"&harr;\": { \"codepoints\": [8596], \"characters\": \"\\u2194\" },\n  \"&hArr;\": { \"codepoints\": [8660], \"characters\": \"\\u21D4\" },\n  \"&harrw;\": { \"codepoints\": [8621], \"characters\": \"\\u21AD\" },\n  \"&Hat;\": { \"codepoints\": [94], \"characters\": \"\\u005E\" },\n  \"&hbar;\": { \"codepoints\": [8463], \"characters\": \"\\u210F\" },\n  \"&Hcirc;\": { \"codepoints\": [292], \"characters\": \"\\u0124\" },\n  \"&hcirc;\": { \"codepoints\": [293], \"characters\": \"\\u0125\" },\n  \"&hearts;\": { \"codepoints\": [9829], \"characters\": \"\\u2665\" },\n  \"&heartsuit;\": { \"codepoints\": [9829], \"characters\": \"\\u2665\" },\n  \"&hellip;\": { \"codepoints\": [8230], \"characters\": \"\\u2026\" },\n  \"&hercon;\": { \"codepoints\": [8889], \"characters\": \"\\u22B9\" },\n  \"&hfr;\": { \"codepoints\": [120101], \"characters\": \"\\uD835\\uDD25\" },\n  \"&Hfr;\": { \"codepoints\": [8460], \"characters\": \"\\u210C\" },\n  \"&HilbertSpace;\": { \"codepoints\": [8459], \"characters\": \"\\u210B\" },\n  \"&hksearow;\": { \"codepoints\": [10533], \"characters\": \"\\u2925\" },\n  \"&hkswarow;\": { \"codepoints\": [10534], \"characters\": \"\\u2926\" },\n  \"&hoarr;\": { \"codepoints\": [8703], \"characters\": \"\\u21FF\" },\n  \"&homtht;\": { \"codepoints\": [8763], \"characters\": \"\\u223B\" },\n  \"&hookleftarrow;\": { \"codepoints\": [8617], \"characters\": \"\\u21A9\" },\n  \"&hookrightarrow;\": { \"codepoints\": [8618], \"characters\": \"\\u21AA\" },\n  \"&hopf;\": { \"codepoints\": [120153], \"characters\": \"\\uD835\\uDD59\" },\n  \"&Hopf;\": { \"codepoints\": [8461], \"characters\": \"\\u210D\" },\n  \"&horbar;\": { \"codepoints\": [8213], \"characters\": \"\\u2015\" },\n  \"&HorizontalLine;\": { \"codepoints\": [9472], \"characters\": \"\\u2500\" },\n  \"&hscr;\": { \"codepoints\": [119997], \"characters\": \"\\uD835\\uDCBD\" },\n  \"&Hscr;\": { \"codepoints\": [8459], \"characters\": \"\\u210B\" },\n  \"&hslash;\": { \"codepoints\": [8463], \"characters\": \"\\u210F\" },\n  \"&Hstrok;\": { \"codepoints\": [294], \"characters\": \"\\u0126\" },\n  \"&hstrok;\": { \"codepoints\": [295], \"characters\": \"\\u0127\" },\n  \"&HumpDownHump;\": { \"codepoints\": [8782], \"characters\": \"\\u224E\" },\n  \"&HumpEqual;\": { \"codepoints\": [8783], \"characters\": \"\\u224F\" },\n  \"&hybull;\": { \"codepoints\": [8259], \"characters\": \"\\u2043\" },\n  \"&hyphen;\": { \"codepoints\": [8208], \"characters\": \"\\u2010\" },\n  \"&Iacute;\": { \"codepoints\": [205], \"characters\": \"\\u00CD\" },\n  \"&Iacute\": { \"codepoints\": [205], \"characters\": \"\\u00CD\" },\n  \"&iacute;\": { \"codepoints\": [237], \"characters\": \"\\u00ED\" },\n  \"&iacute\": { \"codepoints\": [237], \"characters\": \"\\u00ED\" },\n  \"&ic;\": { \"codepoints\": [8291], \"characters\": \"\\u2063\" },\n  \"&Icirc;\": { \"codepoints\": [206], \"characters\": \"\\u00CE\" },\n  \"&Icirc\": { \"codepoints\": [206], \"characters\": \"\\u00CE\" },\n  \"&icirc;\": { \"codepoints\": [238], \"characters\": \"\\u00EE\" },\n  \"&icirc\": { \"codepoints\": [238], \"characters\": \"\\u00EE\" },\n  \"&Icy;\": { \"codepoints\": [1048], \"characters\": \"\\u0418\" },\n  \"&icy;\": { \"codepoints\": [1080], \"characters\": \"\\u0438\" },\n  \"&Idot;\": { \"codepoints\": [304], \"characters\": \"\\u0130\" },\n  \"&IEcy;\": { \"codepoints\": [1045], \"characters\": \"\\u0415\" },\n  \"&iecy;\": { \"codepoints\": [1077], \"characters\": \"\\u0435\" },\n  \"&iexcl;\": { \"codepoints\": [161], \"characters\": \"\\u00A1\" },\n  \"&iexcl\": { \"codepoints\": [161], \"characters\": \"\\u00A1\" },\n  \"&iff;\": { \"codepoints\": [8660], \"characters\": \"\\u21D4\" },\n  \"&ifr;\": { \"codepoints\": [120102], \"characters\": \"\\uD835\\uDD26\" },\n  \"&Ifr;\": { \"codepoints\": [8465], \"characters\": \"\\u2111\" },\n  \"&Igrave;\": { \"codepoints\": [204], \"characters\": \"\\u00CC\" },\n  \"&Igrave\": { \"codepoints\": [204], \"characters\": \"\\u00CC\" },\n  \"&igrave;\": { \"codepoints\": [236], \"characters\": \"\\u00EC\" },\n  \"&igrave\": { \"codepoints\": [236], \"characters\": \"\\u00EC\" },\n  \"&ii;\": { \"codepoints\": [8520], \"characters\": \"\\u2148\" },\n  \"&iiiint;\": { \"codepoints\": [10764], \"characters\": \"\\u2A0C\" },\n  \"&iiint;\": { \"codepoints\": [8749], \"characters\": \"\\u222D\" },\n  \"&iinfin;\": { \"codepoints\": [10716], \"characters\": \"\\u29DC\" },\n  \"&iiota;\": { \"codepoints\": [8489], \"characters\": \"\\u2129\" },\n  \"&IJlig;\": { \"codepoints\": [306], \"characters\": \"\\u0132\" },\n  \"&ijlig;\": { \"codepoints\": [307], \"characters\": \"\\u0133\" },\n  \"&Imacr;\": { \"codepoints\": [298], \"characters\": \"\\u012A\" },\n  \"&imacr;\": { \"codepoints\": [299], \"characters\": \"\\u012B\" },\n  \"&image;\": { \"codepoints\": [8465], \"characters\": \"\\u2111\" },\n  \"&ImaginaryI;\": { \"codepoints\": [8520], \"characters\": \"\\u2148\" },\n  \"&imagline;\": { \"codepoints\": [8464], \"characters\": \"\\u2110\" },\n  \"&imagpart;\": { \"codepoints\": [8465], \"characters\": \"\\u2111\" },\n  \"&imath;\": { \"codepoints\": [305], \"characters\": \"\\u0131\" },\n  \"&Im;\": { \"codepoints\": [8465], \"characters\": \"\\u2111\" },\n  \"&imof;\": { \"codepoints\": [8887], \"characters\": \"\\u22B7\" },\n  \"&imped;\": { \"codepoints\": [437], \"characters\": \"\\u01B5\" },\n  \"&Implies;\": { \"codepoints\": [8658], \"characters\": \"\\u21D2\" },\n  \"&incare;\": { \"codepoints\": [8453], \"characters\": \"\\u2105\" },\n  \"&in;\": { \"codepoints\": [8712], \"characters\": \"\\u2208\" },\n  \"&infin;\": { \"codepoints\": [8734], \"characters\": \"\\u221E\" },\n  \"&infintie;\": { \"codepoints\": [10717], \"characters\": \"\\u29DD\" },\n  \"&inodot;\": { \"codepoints\": [305], \"characters\": \"\\u0131\" },\n  \"&intcal;\": { \"codepoints\": [8890], \"characters\": \"\\u22BA\" },\n  \"&int;\": { \"codepoints\": [8747], \"characters\": \"\\u222B\" },\n  \"&Int;\": { \"codepoints\": [8748], \"characters\": \"\\u222C\" },\n  \"&integers;\": { \"codepoints\": [8484], \"characters\": \"\\u2124\" },\n  \"&Integral;\": { \"codepoints\": [8747], \"characters\": \"\\u222B\" },\n  \"&intercal;\": { \"codepoints\": [8890], \"characters\": \"\\u22BA\" },\n  \"&Intersection;\": { \"codepoints\": [8898], \"characters\": \"\\u22C2\" },\n  \"&intlarhk;\": { \"codepoints\": [10775], \"characters\": \"\\u2A17\" },\n  \"&intprod;\": { \"codepoints\": [10812], \"characters\": \"\\u2A3C\" },\n  \"&InvisibleComma;\": { \"codepoints\": [8291], \"characters\": \"\\u2063\" },\n  \"&InvisibleTimes;\": { \"codepoints\": [8290], \"characters\": \"\\u2062\" },\n  \"&IOcy;\": { \"codepoints\": [1025], \"characters\": \"\\u0401\" },\n  \"&iocy;\": { \"codepoints\": [1105], \"characters\": \"\\u0451\" },\n  \"&Iogon;\": { \"codepoints\": [302], \"characters\": \"\\u012E\" },\n  \"&iogon;\": { \"codepoints\": [303], \"characters\": \"\\u012F\" },\n  \"&Iopf;\": { \"codepoints\": [120128], \"characters\": \"\\uD835\\uDD40\" },\n  \"&iopf;\": { \"codepoints\": [120154], \"characters\": \"\\uD835\\uDD5A\" },\n  \"&Iota;\": { \"codepoints\": [921], \"characters\": \"\\u0399\" },\n  \"&iota;\": { \"codepoints\": [953], \"characters\": \"\\u03B9\" },\n  \"&iprod;\": { \"codepoints\": [10812], \"characters\": \"\\u2A3C\" },\n  \"&iquest;\": { \"codepoints\": [191], \"characters\": \"\\u00BF\" },\n  \"&iquest\": { \"codepoints\": [191], \"characters\": \"\\u00BF\" },\n  \"&iscr;\": { \"codepoints\": [119998], \"characters\": \"\\uD835\\uDCBE\" },\n  \"&Iscr;\": { \"codepoints\": [8464], \"characters\": \"\\u2110\" },\n  \"&isin;\": { \"codepoints\": [8712], \"characters\": \"\\u2208\" },\n  \"&isindot;\": { \"codepoints\": [8949], \"characters\": \"\\u22F5\" },\n  \"&isinE;\": { \"codepoints\": [8953], \"characters\": \"\\u22F9\" },\n  \"&isins;\": { \"codepoints\": [8948], \"characters\": \"\\u22F4\" },\n  \"&isinsv;\": { \"codepoints\": [8947], \"characters\": \"\\u22F3\" },\n  \"&isinv;\": { \"codepoints\": [8712], \"characters\": \"\\u2208\" },\n  \"&it;\": { \"codepoints\": [8290], \"characters\": \"\\u2062\" },\n  \"&Itilde;\": { \"codepoints\": [296], \"characters\": \"\\u0128\" },\n  \"&itilde;\": { \"codepoints\": [297], \"characters\": \"\\u0129\" },\n  \"&Iukcy;\": { \"codepoints\": [1030], \"characters\": \"\\u0406\" },\n  \"&iukcy;\": { \"codepoints\": [1110], \"characters\": \"\\u0456\" },\n  \"&Iuml;\": { \"codepoints\": [207], \"characters\": \"\\u00CF\" },\n  \"&Iuml\": { \"codepoints\": [207], \"characters\": \"\\u00CF\" },\n  \"&iuml;\": { \"codepoints\": [239], \"characters\": \"\\u00EF\" },\n  \"&iuml\": { \"codepoints\": [239], \"characters\": \"\\u00EF\" },\n  \"&Jcirc;\": { \"codepoints\": [308], \"characters\": \"\\u0134\" },\n  \"&jcirc;\": { \"codepoints\": [309], \"characters\": \"\\u0135\" },\n  \"&Jcy;\": { \"codepoints\": [1049], \"characters\": \"\\u0419\" },\n  \"&jcy;\": { \"codepoints\": [1081], \"characters\": \"\\u0439\" },\n  \"&Jfr;\": { \"codepoints\": [120077], \"characters\": \"\\uD835\\uDD0D\" },\n  \"&jfr;\": { \"codepoints\": [120103], \"characters\": \"\\uD835\\uDD27\" },\n  \"&jmath;\": { \"codepoints\": [567], \"characters\": \"\\u0237\" },\n  \"&Jopf;\": { \"codepoints\": [120129], \"characters\": \"\\uD835\\uDD41\" },\n  \"&jopf;\": { \"codepoints\": [120155], \"characters\": \"\\uD835\\uDD5B\" },\n  \"&Jscr;\": { \"codepoints\": [119973], \"characters\": \"\\uD835\\uDCA5\" },\n  \"&jscr;\": { \"codepoints\": [119999], \"characters\": \"\\uD835\\uDCBF\" },\n  \"&Jsercy;\": { \"codepoints\": [1032], \"characters\": \"\\u0408\" },\n  \"&jsercy;\": { \"codepoints\": [1112], \"characters\": \"\\u0458\" },\n  \"&Jukcy;\": { \"codepoints\": [1028], \"characters\": \"\\u0404\" },\n  \"&jukcy;\": { \"codepoints\": [1108], \"characters\": \"\\u0454\" },\n  \"&Kappa;\": { \"codepoints\": [922], \"characters\": \"\\u039A\" },\n  \"&kappa;\": { \"codepoints\": [954], \"characters\": \"\\u03BA\" },\n  \"&kappav;\": { \"codepoints\": [1008], \"characters\": \"\\u03F0\" },\n  \"&Kcedil;\": { \"codepoints\": [310], \"characters\": \"\\u0136\" },\n  \"&kcedil;\": { \"codepoints\": [311], \"characters\": \"\\u0137\" },\n  \"&Kcy;\": { \"codepoints\": [1050], \"characters\": \"\\u041A\" },\n  \"&kcy;\": { \"codepoints\": [1082], \"characters\": \"\\u043A\" },\n  \"&Kfr;\": { \"codepoints\": [120078], \"characters\": \"\\uD835\\uDD0E\" },\n  \"&kfr;\": { \"codepoints\": [120104], \"characters\": \"\\uD835\\uDD28\" },\n  \"&kgreen;\": { \"codepoints\": [312], \"characters\": \"\\u0138\" },\n  \"&KHcy;\": { \"codepoints\": [1061], \"characters\": \"\\u0425\" },\n  \"&khcy;\": { \"codepoints\": [1093], \"characters\": \"\\u0445\" },\n  \"&KJcy;\": { \"codepoints\": [1036], \"characters\": \"\\u040C\" },\n  \"&kjcy;\": { \"codepoints\": [1116], \"characters\": \"\\u045C\" },\n  \"&Kopf;\": { \"codepoints\": [120130], \"characters\": \"\\uD835\\uDD42\" },\n  \"&kopf;\": { \"codepoints\": [120156], \"characters\": \"\\uD835\\uDD5C\" },\n  \"&Kscr;\": { \"codepoints\": [119974], \"characters\": \"\\uD835\\uDCA6\" },\n  \"&kscr;\": { \"codepoints\": [120000], \"characters\": \"\\uD835\\uDCC0\" },\n  \"&lAarr;\": { \"codepoints\": [8666], \"characters\": \"\\u21DA\" },\n  \"&Lacute;\": { \"codepoints\": [313], \"characters\": \"\\u0139\" },\n  \"&lacute;\": { \"codepoints\": [314], \"characters\": \"\\u013A\" },\n  \"&laemptyv;\": { \"codepoints\": [10676], \"characters\": \"\\u29B4\" },\n  \"&lagran;\": { \"codepoints\": [8466], \"characters\": \"\\u2112\" },\n  \"&Lambda;\": { \"codepoints\": [923], \"characters\": \"\\u039B\" },\n  \"&lambda;\": { \"codepoints\": [955], \"characters\": \"\\u03BB\" },\n  \"&lang;\": { \"codepoints\": [10216], \"characters\": \"\\u27E8\" },\n  \"&Lang;\": { \"codepoints\": [10218], \"characters\": \"\\u27EA\" },\n  \"&langd;\": { \"codepoints\": [10641], \"characters\": \"\\u2991\" },\n  \"&langle;\": { \"codepoints\": [10216], \"characters\": \"\\u27E8\" },\n  \"&lap;\": { \"codepoints\": [10885], \"characters\": \"\\u2A85\" },\n  \"&Laplacetrf;\": { \"codepoints\": [8466], \"characters\": \"\\u2112\" },\n  \"&laquo;\": { \"codepoints\": [171], \"characters\": \"\\u00AB\" },\n  \"&laquo\": { \"codepoints\": [171], \"characters\": \"\\u00AB\" },\n  \"&larrb;\": { \"codepoints\": [8676], \"characters\": \"\\u21E4\" },\n  \"&larrbfs;\": { \"codepoints\": [10527], \"characters\": \"\\u291F\" },\n  \"&larr;\": { \"codepoints\": [8592], \"characters\": \"\\u2190\" },\n  \"&Larr;\": { \"codepoints\": [8606], \"characters\": \"\\u219E\" },\n  \"&lArr;\": { \"codepoints\": [8656], \"characters\": \"\\u21D0\" },\n  \"&larrfs;\": { \"codepoints\": [10525], \"characters\": \"\\u291D\" },\n  \"&larrhk;\": { \"codepoints\": [8617], \"characters\": \"\\u21A9\" },\n  \"&larrlp;\": { \"codepoints\": [8619], \"characters\": \"\\u21AB\" },\n  \"&larrpl;\": { \"codepoints\": [10553], \"characters\": \"\\u2939\" },\n  \"&larrsim;\": { \"codepoints\": [10611], \"characters\": \"\\u2973\" },\n  \"&larrtl;\": { \"codepoints\": [8610], \"characters\": \"\\u21A2\" },\n  \"&latail;\": { \"codepoints\": [10521], \"characters\": \"\\u2919\" },\n  \"&lAtail;\": { \"codepoints\": [10523], \"characters\": \"\\u291B\" },\n  \"&lat;\": { \"codepoints\": [10923], \"characters\": \"\\u2AAB\" },\n  \"&late;\": { \"codepoints\": [10925], \"characters\": \"\\u2AAD\" },\n  \"&lates;\": { \"codepoints\": [10925, 65024], \"characters\": \"\\u2AAD\\uFE00\" },\n  \"&lbarr;\": { \"codepoints\": [10508], \"characters\": \"\\u290C\" },\n  \"&lBarr;\": { \"codepoints\": [10510], \"characters\": \"\\u290E\" },\n  \"&lbbrk;\": { \"codepoints\": [10098], \"characters\": \"\\u2772\" },\n  \"&lbrace;\": { \"codepoints\": [123], \"characters\": \"\\u007B\" },\n  \"&lbrack;\": { \"codepoints\": [91], \"characters\": \"\\u005B\" },\n  \"&lbrke;\": { \"codepoints\": [10635], \"characters\": \"\\u298B\" },\n  \"&lbrksld;\": { \"codepoints\": [10639], \"characters\": \"\\u298F\" },\n  \"&lbrkslu;\": { \"codepoints\": [10637], \"characters\": \"\\u298D\" },\n  \"&Lcaron;\": { \"codepoints\": [317], \"characters\": \"\\u013D\" },\n  \"&lcaron;\": { \"codepoints\": [318], \"characters\": \"\\u013E\" },\n  \"&Lcedil;\": { \"codepoints\": [315], \"characters\": \"\\u013B\" },\n  \"&lcedil;\": { \"codepoints\": [316], \"characters\": \"\\u013C\" },\n  \"&lceil;\": { \"codepoints\": [8968], \"characters\": \"\\u2308\" },\n  \"&lcub;\": { \"codepoints\": [123], \"characters\": \"\\u007B\" },\n  \"&Lcy;\": { \"codepoints\": [1051], \"characters\": \"\\u041B\" },\n  \"&lcy;\": { \"codepoints\": [1083], \"characters\": \"\\u043B\" },\n  \"&ldca;\": { \"codepoints\": [10550], \"characters\": \"\\u2936\" },\n  \"&ldquo;\": { \"codepoints\": [8220], \"characters\": \"\\u201C\" },\n  \"&ldquor;\": { \"codepoints\": [8222], \"characters\": \"\\u201E\" },\n  \"&ldrdhar;\": { \"codepoints\": [10599], \"characters\": \"\\u2967\" },\n  \"&ldrushar;\": { \"codepoints\": [10571], \"characters\": \"\\u294B\" },\n  \"&ldsh;\": { \"codepoints\": [8626], \"characters\": \"\\u21B2\" },\n  \"&le;\": { \"codepoints\": [8804], \"characters\": \"\\u2264\" },\n  \"&lE;\": { \"codepoints\": [8806], \"characters\": \"\\u2266\" },\n  \"&LeftAngleBracket;\": { \"codepoints\": [10216], \"characters\": \"\\u27E8\" },\n  \"&LeftArrowBar;\": { \"codepoints\": [8676], \"characters\": \"\\u21E4\" },\n  \"&leftarrow;\": { \"codepoints\": [8592], \"characters\": \"\\u2190\" },\n  \"&LeftArrow;\": { \"codepoints\": [8592], \"characters\": \"\\u2190\" },\n  \"&Leftarrow;\": { \"codepoints\": [8656], \"characters\": \"\\u21D0\" },\n  \"&LeftArrowRightArrow;\": { \"codepoints\": [8646], \"characters\": \"\\u21C6\" },\n  \"&leftarrowtail;\": { \"codepoints\": [8610], \"characters\": \"\\u21A2\" },\n  \"&LeftCeiling;\": { \"codepoints\": [8968], \"characters\": \"\\u2308\" },\n  \"&LeftDoubleBracket;\": { \"codepoints\": [10214], \"characters\": \"\\u27E6\" },\n  \"&LeftDownTeeVector;\": { \"codepoints\": [10593], \"characters\": \"\\u2961\" },\n  \"&LeftDownVectorBar;\": { \"codepoints\": [10585], \"characters\": \"\\u2959\" },\n  \"&LeftDownVector;\": { \"codepoints\": [8643], \"characters\": \"\\u21C3\" },\n  \"&LeftFloor;\": { \"codepoints\": [8970], \"characters\": \"\\u230A\" },\n  \"&leftharpoondown;\": { \"codepoints\": [8637], \"characters\": \"\\u21BD\" },\n  \"&leftharpoonup;\": { \"codepoints\": [8636], \"characters\": \"\\u21BC\" },\n  \"&leftleftarrows;\": { \"codepoints\": [8647], \"characters\": \"\\u21C7\" },\n  \"&leftrightarrow;\": { \"codepoints\": [8596], \"characters\": \"\\u2194\" },\n  \"&LeftRightArrow;\": { \"codepoints\": [8596], \"characters\": \"\\u2194\" },\n  \"&Leftrightarrow;\": { \"codepoints\": [8660], \"characters\": \"\\u21D4\" },\n  \"&leftrightarrows;\": { \"codepoints\": [8646], \"characters\": \"\\u21C6\" },\n  \"&leftrightharpoons;\": { \"codepoints\": [8651], \"characters\": \"\\u21CB\" },\n  \"&leftrightsquigarrow;\": { \"codepoints\": [8621], \"characters\": \"\\u21AD\" },\n  \"&LeftRightVector;\": { \"codepoints\": [10574], \"characters\": \"\\u294E\" },\n  \"&LeftTeeArrow;\": { \"codepoints\": [8612], \"characters\": \"\\u21A4\" },\n  \"&LeftTee;\": { \"codepoints\": [8867], \"characters\": \"\\u22A3\" },\n  \"&LeftTeeVector;\": { \"codepoints\": [10586], \"characters\": \"\\u295A\" },\n  \"&leftthreetimes;\": { \"codepoints\": [8907], \"characters\": \"\\u22CB\" },\n  \"&LeftTriangleBar;\": { \"codepoints\": [10703], \"characters\": \"\\u29CF\" },\n  \"&LeftTriangle;\": { \"codepoints\": [8882], \"characters\": \"\\u22B2\" },\n  \"&LeftTriangleEqual;\": { \"codepoints\": [8884], \"characters\": \"\\u22B4\" },\n  \"&LeftUpDownVector;\": { \"codepoints\": [10577], \"characters\": \"\\u2951\" },\n  \"&LeftUpTeeVector;\": { \"codepoints\": [10592], \"characters\": \"\\u2960\" },\n  \"&LeftUpVectorBar;\": { \"codepoints\": [10584], \"characters\": \"\\u2958\" },\n  \"&LeftUpVector;\": { \"codepoints\": [8639], \"characters\": \"\\u21BF\" },\n  \"&LeftVectorBar;\": { \"codepoints\": [10578], \"characters\": \"\\u2952\" },\n  \"&LeftVector;\": { \"codepoints\": [8636], \"characters\": \"\\u21BC\" },\n  \"&lEg;\": { \"codepoints\": [10891], \"characters\": \"\\u2A8B\" },\n  \"&leg;\": { \"codepoints\": [8922], \"characters\": \"\\u22DA\" },\n  \"&leq;\": { \"codepoints\": [8804], \"characters\": \"\\u2264\" },\n  \"&leqq;\": { \"codepoints\": [8806], \"characters\": \"\\u2266\" },\n  \"&leqslant;\": { \"codepoints\": [10877], \"characters\": \"\\u2A7D\" },\n  \"&lescc;\": { \"codepoints\": [10920], \"characters\": \"\\u2AA8\" },\n  \"&les;\": { \"codepoints\": [10877], \"characters\": \"\\u2A7D\" },\n  \"&lesdot;\": { \"codepoints\": [10879], \"characters\": \"\\u2A7F\" },\n  \"&lesdoto;\": { \"codepoints\": [10881], \"characters\": \"\\u2A81\" },\n  \"&lesdotor;\": { \"codepoints\": [10883], \"characters\": \"\\u2A83\" },\n  \"&lesg;\": { \"codepoints\": [8922, 65024], \"characters\": \"\\u22DA\\uFE00\" },\n  \"&lesges;\": { \"codepoints\": [10899], \"characters\": \"\\u2A93\" },\n  \"&lessapprox;\": { \"codepoints\": [10885], \"characters\": \"\\u2A85\" },\n  \"&lessdot;\": { \"codepoints\": [8918], \"characters\": \"\\u22D6\" },\n  \"&lesseqgtr;\": { \"codepoints\": [8922], \"characters\": \"\\u22DA\" },\n  \"&lesseqqgtr;\": { \"codepoints\": [10891], \"characters\": \"\\u2A8B\" },\n  \"&LessEqualGreater;\": { \"codepoints\": [8922], \"characters\": \"\\u22DA\" },\n  \"&LessFullEqual;\": { \"codepoints\": [8806], \"characters\": \"\\u2266\" },\n  \"&LessGreater;\": { \"codepoints\": [8822], \"characters\": \"\\u2276\" },\n  \"&lessgtr;\": { \"codepoints\": [8822], \"characters\": \"\\u2276\" },\n  \"&LessLess;\": { \"codepoints\": [10913], \"characters\": \"\\u2AA1\" },\n  \"&lesssim;\": { \"codepoints\": [8818], \"characters\": \"\\u2272\" },\n  \"&LessSlantEqual;\": { \"codepoints\": [10877], \"characters\": \"\\u2A7D\" },\n  \"&LessTilde;\": { \"codepoints\": [8818], \"characters\": \"\\u2272\" },\n  \"&lfisht;\": { \"codepoints\": [10620], \"characters\": \"\\u297C\" },\n  \"&lfloor;\": { \"codepoints\": [8970], \"characters\": \"\\u230A\" },\n  \"&Lfr;\": { \"codepoints\": [120079], \"characters\": \"\\uD835\\uDD0F\" },\n  \"&lfr;\": { \"codepoints\": [120105], \"characters\": \"\\uD835\\uDD29\" },\n  \"&lg;\": { \"codepoints\": [8822], \"characters\": \"\\u2276\" },\n  \"&lgE;\": { \"codepoints\": [10897], \"characters\": \"\\u2A91\" },\n  \"&lHar;\": { \"codepoints\": [10594], \"characters\": \"\\u2962\" },\n  \"&lhard;\": { \"codepoints\": [8637], \"characters\": \"\\u21BD\" },\n  \"&lharu;\": { \"codepoints\": [8636], \"characters\": \"\\u21BC\" },\n  \"&lharul;\": { \"codepoints\": [10602], \"characters\": \"\\u296A\" },\n  \"&lhblk;\": { \"codepoints\": [9604], \"characters\": \"\\u2584\" },\n  \"&LJcy;\": { \"codepoints\": [1033], \"characters\": \"\\u0409\" },\n  \"&ljcy;\": { \"codepoints\": [1113], \"characters\": \"\\u0459\" },\n  \"&llarr;\": { \"codepoints\": [8647], \"characters\": \"\\u21C7\" },\n  \"&ll;\": { \"codepoints\": [8810], \"characters\": \"\\u226A\" },\n  \"&Ll;\": { \"codepoints\": [8920], \"characters\": \"\\u22D8\" },\n  \"&llcorner;\": { \"codepoints\": [8990], \"characters\": \"\\u231E\" },\n  \"&Lleftarrow;\": { \"codepoints\": [8666], \"characters\": \"\\u21DA\" },\n  \"&llhard;\": { \"codepoints\": [10603], \"characters\": \"\\u296B\" },\n  \"&lltri;\": { \"codepoints\": [9722], \"characters\": \"\\u25FA\" },\n  \"&Lmidot;\": { \"codepoints\": [319], \"characters\": \"\\u013F\" },\n  \"&lmidot;\": { \"codepoints\": [320], \"characters\": \"\\u0140\" },\n  \"&lmoustache;\": { \"codepoints\": [9136], \"characters\": \"\\u23B0\" },\n  \"&lmoust;\": { \"codepoints\": [9136], \"characters\": \"\\u23B0\" },\n  \"&lnap;\": { \"codepoints\": [10889], \"characters\": \"\\u2A89\" },\n  \"&lnapprox;\": { \"codepoints\": [10889], \"characters\": \"\\u2A89\" },\n  \"&lne;\": { \"codepoints\": [10887], \"characters\": \"\\u2A87\" },\n  \"&lnE;\": { \"codepoints\": [8808], \"characters\": \"\\u2268\" },\n  \"&lneq;\": { \"codepoints\": [10887], \"characters\": \"\\u2A87\" },\n  \"&lneqq;\": { \"codepoints\": [8808], \"characters\": \"\\u2268\" },\n  \"&lnsim;\": { \"codepoints\": [8934], \"characters\": \"\\u22E6\" },\n  \"&loang;\": { \"codepoints\": [10220], \"characters\": \"\\u27EC\" },\n  \"&loarr;\": { \"codepoints\": [8701], \"characters\": \"\\u21FD\" },\n  \"&lobrk;\": { \"codepoints\": [10214], \"characters\": \"\\u27E6\" },\n  \"&longleftarrow;\": { \"codepoints\": [10229], \"characters\": \"\\u27F5\" },\n  \"&LongLeftArrow;\": { \"codepoints\": [10229], \"characters\": \"\\u27F5\" },\n  \"&Longleftarrow;\": { \"codepoints\": [10232], \"characters\": \"\\u27F8\" },\n  \"&longleftrightarrow;\": { \"codepoints\": [10231], \"characters\": \"\\u27F7\" },\n  \"&LongLeftRightArrow;\": { \"codepoints\": [10231], \"characters\": \"\\u27F7\" },\n  \"&Longleftrightarrow;\": { \"codepoints\": [10234], \"characters\": \"\\u27FA\" },\n  \"&longmapsto;\": { \"codepoints\": [10236], \"characters\": \"\\u27FC\" },\n  \"&longrightarrow;\": { \"codepoints\": [10230], \"characters\": \"\\u27F6\" },\n  \"&LongRightArrow;\": { \"codepoints\": [10230], \"characters\": \"\\u27F6\" },\n  \"&Longrightarrow;\": { \"codepoints\": [10233], \"characters\": \"\\u27F9\" },\n  \"&looparrowleft;\": { \"codepoints\": [8619], \"characters\": \"\\u21AB\" },\n  \"&looparrowright;\": { \"codepoints\": [8620], \"characters\": \"\\u21AC\" },\n  \"&lopar;\": { \"codepoints\": [10629], \"characters\": \"\\u2985\" },\n  \"&Lopf;\": { \"codepoints\": [120131], \"characters\": \"\\uD835\\uDD43\" },\n  \"&lopf;\": { \"codepoints\": [120157], \"characters\": \"\\uD835\\uDD5D\" },\n  \"&loplus;\": { \"codepoints\": [10797], \"characters\": \"\\u2A2D\" },\n  \"&lotimes;\": { \"codepoints\": [10804], \"characters\": \"\\u2A34\" },\n  \"&lowast;\": { \"codepoints\": [8727], \"characters\": \"\\u2217\" },\n  \"&lowbar;\": { \"codepoints\": [95], \"characters\": \"\\u005F\" },\n  \"&LowerLeftArrow;\": { \"codepoints\": [8601], \"characters\": \"\\u2199\" },\n  \"&LowerRightArrow;\": { \"codepoints\": [8600], \"characters\": \"\\u2198\" },\n  \"&loz;\": { \"codepoints\": [9674], \"characters\": \"\\u25CA\" },\n  \"&lozenge;\": { \"codepoints\": [9674], \"characters\": \"\\u25CA\" },\n  \"&lozf;\": { \"codepoints\": [10731], \"characters\": \"\\u29EB\" },\n  \"&lpar;\": { \"codepoints\": [40], \"characters\": \"\\u0028\" },\n  \"&lparlt;\": { \"codepoints\": [10643], \"characters\": \"\\u2993\" },\n  \"&lrarr;\": { \"codepoints\": [8646], \"characters\": \"\\u21C6\" },\n  \"&lrcorner;\": { \"codepoints\": [8991], \"characters\": \"\\u231F\" },\n  \"&lrhar;\": { \"codepoints\": [8651], \"characters\": \"\\u21CB\" },\n  \"&lrhard;\": { \"codepoints\": [10605], \"characters\": \"\\u296D\" },\n  \"&lrm;\": { \"codepoints\": [8206], \"characters\": \"\\u200E\" },\n  \"&lrtri;\": { \"codepoints\": [8895], \"characters\": \"\\u22BF\" },\n  \"&lsaquo;\": { \"codepoints\": [8249], \"characters\": \"\\u2039\" },\n  \"&lscr;\": { \"codepoints\": [120001], \"characters\": \"\\uD835\\uDCC1\" },\n  \"&Lscr;\": { \"codepoints\": [8466], \"characters\": \"\\u2112\" },\n  \"&lsh;\": { \"codepoints\": [8624], \"characters\": \"\\u21B0\" },\n  \"&Lsh;\": { \"codepoints\": [8624], \"characters\": \"\\u21B0\" },\n  \"&lsim;\": { \"codepoints\": [8818], \"characters\": \"\\u2272\" },\n  \"&lsime;\": { \"codepoints\": [10893], \"characters\": \"\\u2A8D\" },\n  \"&lsimg;\": { \"codepoints\": [10895], \"characters\": \"\\u2A8F\" },\n  \"&lsqb;\": { \"codepoints\": [91], \"characters\": \"\\u005B\" },\n  \"&lsquo;\": { \"codepoints\": [8216], \"characters\": \"\\u2018\" },\n  \"&lsquor;\": { \"codepoints\": [8218], \"characters\": \"\\u201A\" },\n  \"&Lstrok;\": { \"codepoints\": [321], \"characters\": \"\\u0141\" },\n  \"&lstrok;\": { \"codepoints\": [322], \"characters\": \"\\u0142\" },\n  \"&ltcc;\": { \"codepoints\": [10918], \"characters\": \"\\u2AA6\" },\n  \"&ltcir;\": { \"codepoints\": [10873], \"characters\": \"\\u2A79\" },\n  \"&lt;\": { \"codepoints\": [60], \"characters\": \"\\u003C\" },\n  \"&lt\": { \"codepoints\": [60], \"characters\": \"\\u003C\" },\n  \"&LT;\": { \"codepoints\": [60], \"characters\": \"\\u003C\" },\n  \"&LT\": { \"codepoints\": [60], \"characters\": \"\\u003C\" },\n  \"&Lt;\": { \"codepoints\": [8810], \"characters\": \"\\u226A\" },\n  \"&ltdot;\": { \"codepoints\": [8918], \"characters\": \"\\u22D6\" },\n  \"&lthree;\": { \"codepoints\": [8907], \"characters\": \"\\u22CB\" },\n  \"&ltimes;\": { \"codepoints\": [8905], \"characters\": \"\\u22C9\" },\n  \"&ltlarr;\": { \"codepoints\": [10614], \"characters\": \"\\u2976\" },\n  \"&ltquest;\": { \"codepoints\": [10875], \"characters\": \"\\u2A7B\" },\n  \"&ltri;\": { \"codepoints\": [9667], \"characters\": \"\\u25C3\" },\n  \"&ltrie;\": { \"codepoints\": [8884], \"characters\": \"\\u22B4\" },\n  \"&ltrif;\": { \"codepoints\": [9666], \"characters\": \"\\u25C2\" },\n  \"&ltrPar;\": { \"codepoints\": [10646], \"characters\": \"\\u2996\" },\n  \"&lurdshar;\": { \"codepoints\": [10570], \"characters\": \"\\u294A\" },\n  \"&luruhar;\": { \"codepoints\": [10598], \"characters\": \"\\u2966\" },\n  \"&lvertneqq;\": { \"codepoints\": [8808, 65024], \"characters\": \"\\u2268\\uFE00\" },\n  \"&lvnE;\": { \"codepoints\": [8808, 65024], \"characters\": \"\\u2268\\uFE00\" },\n  \"&macr;\": { \"codepoints\": [175], \"characters\": \"\\u00AF\" },\n  \"&macr\": { \"codepoints\": [175], \"characters\": \"\\u00AF\" },\n  \"&male;\": { \"codepoints\": [9794], \"characters\": \"\\u2642\" },\n  \"&malt;\": { \"codepoints\": [10016], \"characters\": \"\\u2720\" },\n  \"&maltese;\": { \"codepoints\": [10016], \"characters\": \"\\u2720\" },\n  \"&Map;\": { \"codepoints\": [10501], \"characters\": \"\\u2905\" },\n  \"&map;\": { \"codepoints\": [8614], \"characters\": \"\\u21A6\" },\n  \"&mapsto;\": { \"codepoints\": [8614], \"characters\": \"\\u21A6\" },\n  \"&mapstodown;\": { \"codepoints\": [8615], \"characters\": \"\\u21A7\" },\n  \"&mapstoleft;\": { \"codepoints\": [8612], \"characters\": \"\\u21A4\" },\n  \"&mapstoup;\": { \"codepoints\": [8613], \"characters\": \"\\u21A5\" },\n  \"&marker;\": { \"codepoints\": [9646], \"characters\": \"\\u25AE\" },\n  \"&mcomma;\": { \"codepoints\": [10793], \"characters\": \"\\u2A29\" },\n  \"&Mcy;\": { \"codepoints\": [1052], \"characters\": \"\\u041C\" },\n  \"&mcy;\": { \"codepoints\": [1084], \"characters\": \"\\u043C\" },\n  \"&mdash;\": { \"codepoints\": [8212], \"characters\": \"\\u2014\" },\n  \"&mDDot;\": { \"codepoints\": [8762], \"characters\": \"\\u223A\" },\n  \"&measuredangle;\": { \"codepoints\": [8737], \"characters\": \"\\u2221\" },\n  \"&MediumSpace;\": { \"codepoints\": [8287], \"characters\": \"\\u205F\" },\n  \"&Mellintrf;\": { \"codepoints\": [8499], \"characters\": \"\\u2133\" },\n  \"&Mfr;\": { \"codepoints\": [120080], \"characters\": \"\\uD835\\uDD10\" },\n  \"&mfr;\": { \"codepoints\": [120106], \"characters\": \"\\uD835\\uDD2A\" },\n  \"&mho;\": { \"codepoints\": [8487], \"characters\": \"\\u2127\" },\n  \"&micro;\": { \"codepoints\": [181], \"characters\": \"\\u00B5\" },\n  \"&micro\": { \"codepoints\": [181], \"characters\": \"\\u00B5\" },\n  \"&midast;\": { \"codepoints\": [42], \"characters\": \"\\u002A\" },\n  \"&midcir;\": { \"codepoints\": [10992], \"characters\": \"\\u2AF0\" },\n  \"&mid;\": { \"codepoints\": [8739], \"characters\": \"\\u2223\" },\n  \"&middot;\": { \"codepoints\": [183], \"characters\": \"\\u00B7\" },\n  \"&middot\": { \"codepoints\": [183], \"characters\": \"\\u00B7\" },\n  \"&minusb;\": { \"codepoints\": [8863], \"characters\": \"\\u229F\" },\n  \"&minus;\": { \"codepoints\": [8722], \"characters\": \"\\u2212\" },\n  \"&minusd;\": { \"codepoints\": [8760], \"characters\": \"\\u2238\" },\n  \"&minusdu;\": { \"codepoints\": [10794], \"characters\": \"\\u2A2A\" },\n  \"&MinusPlus;\": { \"codepoints\": [8723], \"characters\": \"\\u2213\" },\n  \"&mlcp;\": { \"codepoints\": [10971], \"characters\": \"\\u2ADB\" },\n  \"&mldr;\": { \"codepoints\": [8230], \"characters\": \"\\u2026\" },\n  \"&mnplus;\": { \"codepoints\": [8723], \"characters\": \"\\u2213\" },\n  \"&models;\": { \"codepoints\": [8871], \"characters\": \"\\u22A7\" },\n  \"&Mopf;\": { \"codepoints\": [120132], \"characters\": \"\\uD835\\uDD44\" },\n  \"&mopf;\": { \"codepoints\": [120158], \"characters\": \"\\uD835\\uDD5E\" },\n  \"&mp;\": { \"codepoints\": [8723], \"characters\": \"\\u2213\" },\n  \"&mscr;\": { \"codepoints\": [120002], \"characters\": \"\\uD835\\uDCC2\" },\n  \"&Mscr;\": { \"codepoints\": [8499], \"characters\": \"\\u2133\" },\n  \"&mstpos;\": { \"codepoints\": [8766], \"characters\": \"\\u223E\" },\n  \"&Mu;\": { \"codepoints\": [924], \"characters\": \"\\u039C\" },\n  \"&mu;\": { \"codepoints\": [956], \"characters\": \"\\u03BC\" },\n  \"&multimap;\": { \"codepoints\": [8888], \"characters\": \"\\u22B8\" },\n  \"&mumap;\": { \"codepoints\": [8888], \"characters\": \"\\u22B8\" },\n  \"&nabla;\": { \"codepoints\": [8711], \"characters\": \"\\u2207\" },\n  \"&Nacute;\": { \"codepoints\": [323], \"characters\": \"\\u0143\" },\n  \"&nacute;\": { \"codepoints\": [324], \"characters\": \"\\u0144\" },\n  \"&nang;\": { \"codepoints\": [8736, 8402], \"characters\": \"\\u2220\\u20D2\" },\n  \"&nap;\": { \"codepoints\": [8777], \"characters\": \"\\u2249\" },\n  \"&napE;\": { \"codepoints\": [10864, 824], \"characters\": \"\\u2A70\\u0338\" },\n  \"&napid;\": { \"codepoints\": [8779, 824], \"characters\": \"\\u224B\\u0338\" },\n  \"&napos;\": { \"codepoints\": [329], \"characters\": \"\\u0149\" },\n  \"&napprox;\": { \"codepoints\": [8777], \"characters\": \"\\u2249\" },\n  \"&natural;\": { \"codepoints\": [9838], \"characters\": \"\\u266E\" },\n  \"&naturals;\": { \"codepoints\": [8469], \"characters\": \"\\u2115\" },\n  \"&natur;\": { \"codepoints\": [9838], \"characters\": \"\\u266E\" },\n  \"&nbsp;\": { \"codepoints\": [160], \"characters\": \"\\u00A0\" },\n  \"&nbsp\": { \"codepoints\": [160], \"characters\": \"\\u00A0\" },\n  \"&nbump;\": { \"codepoints\": [8782, 824], \"characters\": \"\\u224E\\u0338\" },\n  \"&nbumpe;\": { \"codepoints\": [8783, 824], \"characters\": \"\\u224F\\u0338\" },\n  \"&ncap;\": { \"codepoints\": [10819], \"characters\": \"\\u2A43\" },\n  \"&Ncaron;\": { \"codepoints\": [327], \"characters\": \"\\u0147\" },\n  \"&ncaron;\": { \"codepoints\": [328], \"characters\": \"\\u0148\" },\n  \"&Ncedil;\": { \"codepoints\": [325], \"characters\": \"\\u0145\" },\n  \"&ncedil;\": { \"codepoints\": [326], \"characters\": \"\\u0146\" },\n  \"&ncong;\": { \"codepoints\": [8775], \"characters\": \"\\u2247\" },\n  \"&ncongdot;\": { \"codepoints\": [10861, 824], \"characters\": \"\\u2A6D\\u0338\" },\n  \"&ncup;\": { \"codepoints\": [10818], \"characters\": \"\\u2A42\" },\n  \"&Ncy;\": { \"codepoints\": [1053], \"characters\": \"\\u041D\" },\n  \"&ncy;\": { \"codepoints\": [1085], \"characters\": \"\\u043D\" },\n  \"&ndash;\": { \"codepoints\": [8211], \"characters\": \"\\u2013\" },\n  \"&nearhk;\": { \"codepoints\": [10532], \"characters\": \"\\u2924\" },\n  \"&nearr;\": { \"codepoints\": [8599], \"characters\": \"\\u2197\" },\n  \"&neArr;\": { \"codepoints\": [8663], \"characters\": \"\\u21D7\" },\n  \"&nearrow;\": { \"codepoints\": [8599], \"characters\": \"\\u2197\" },\n  \"&ne;\": { \"codepoints\": [8800], \"characters\": \"\\u2260\" },\n  \"&nedot;\": { \"codepoints\": [8784, 824], \"characters\": \"\\u2250\\u0338\" },\n  \"&NegativeMediumSpace;\": { \"codepoints\": [8203], \"characters\": \"\\u200B\" },\n  \"&NegativeThickSpace;\": { \"codepoints\": [8203], \"characters\": \"\\u200B\" },\n  \"&NegativeThinSpace;\": { \"codepoints\": [8203], \"characters\": \"\\u200B\" },\n  \"&NegativeVeryThinSpace;\": { \"codepoints\": [8203], \"characters\": \"\\u200B\" },\n  \"&nequiv;\": { \"codepoints\": [8802], \"characters\": \"\\u2262\" },\n  \"&nesear;\": { \"codepoints\": [10536], \"characters\": \"\\u2928\" },\n  \"&nesim;\": { \"codepoints\": [8770, 824], \"characters\": \"\\u2242\\u0338\" },\n  \"&NestedGreaterGreater;\": { \"codepoints\": [8811], \"characters\": \"\\u226B\" },\n  \"&NestedLessLess;\": { \"codepoints\": [8810], \"characters\": \"\\u226A\" },\n  \"&NewLine;\": { \"codepoints\": [10], \"characters\": \"\\u000A\" },\n  \"&nexist;\": { \"codepoints\": [8708], \"characters\": \"\\u2204\" },\n  \"&nexists;\": { \"codepoints\": [8708], \"characters\": \"\\u2204\" },\n  \"&Nfr;\": { \"codepoints\": [120081], \"characters\": \"\\uD835\\uDD11\" },\n  \"&nfr;\": { \"codepoints\": [120107], \"characters\": \"\\uD835\\uDD2B\" },\n  \"&ngE;\": { \"codepoints\": [8807, 824], \"characters\": \"\\u2267\\u0338\" },\n  \"&nge;\": { \"codepoints\": [8817], \"characters\": \"\\u2271\" },\n  \"&ngeq;\": { \"codepoints\": [8817], \"characters\": \"\\u2271\" },\n  \"&ngeqq;\": { \"codepoints\": [8807, 824], \"characters\": \"\\u2267\\u0338\" },\n  \"&ngeqslant;\": { \"codepoints\": [10878, 824], \"characters\": \"\\u2A7E\\u0338\" },\n  \"&nges;\": { \"codepoints\": [10878, 824], \"characters\": \"\\u2A7E\\u0338\" },\n  \"&nGg;\": { \"codepoints\": [8921, 824], \"characters\": \"\\u22D9\\u0338\" },\n  \"&ngsim;\": { \"codepoints\": [8821], \"characters\": \"\\u2275\" },\n  \"&nGt;\": { \"codepoints\": [8811, 8402], \"characters\": \"\\u226B\\u20D2\" },\n  \"&ngt;\": { \"codepoints\": [8815], \"characters\": \"\\u226F\" },\n  \"&ngtr;\": { \"codepoints\": [8815], \"characters\": \"\\u226F\" },\n  \"&nGtv;\": { \"codepoints\": [8811, 824], \"characters\": \"\\u226B\\u0338\" },\n  \"&nharr;\": { \"codepoints\": [8622], \"characters\": \"\\u21AE\" },\n  \"&nhArr;\": { \"codepoints\": [8654], \"characters\": \"\\u21CE\" },\n  \"&nhpar;\": { \"codepoints\": [10994], \"characters\": \"\\u2AF2\" },\n  \"&ni;\": { \"codepoints\": [8715], \"characters\": \"\\u220B\" },\n  \"&nis;\": { \"codepoints\": [8956], \"characters\": \"\\u22FC\" },\n  \"&nisd;\": { \"codepoints\": [8954], \"characters\": \"\\u22FA\" },\n  \"&niv;\": { \"codepoints\": [8715], \"characters\": \"\\u220B\" },\n  \"&NJcy;\": { \"codepoints\": [1034], \"characters\": \"\\u040A\" },\n  \"&njcy;\": { \"codepoints\": [1114], \"characters\": \"\\u045A\" },\n  \"&nlarr;\": { \"codepoints\": [8602], \"characters\": \"\\u219A\" },\n  \"&nlArr;\": { \"codepoints\": [8653], \"characters\": \"\\u21CD\" },\n  \"&nldr;\": { \"codepoints\": [8229], \"characters\": \"\\u2025\" },\n  \"&nlE;\": { \"codepoints\": [8806, 824], \"characters\": \"\\u2266\\u0338\" },\n  \"&nle;\": { \"codepoints\": [8816], \"characters\": \"\\u2270\" },\n  \"&nleftarrow;\": { \"codepoints\": [8602], \"characters\": \"\\u219A\" },\n  \"&nLeftarrow;\": { \"codepoints\": [8653], \"characters\": \"\\u21CD\" },\n  \"&nleftrightarrow;\": { \"codepoints\": [8622], \"characters\": \"\\u21AE\" },\n  \"&nLeftrightarrow;\": { \"codepoints\": [8654], \"characters\": \"\\u21CE\" },\n  \"&nleq;\": { \"codepoints\": [8816], \"characters\": \"\\u2270\" },\n  \"&nleqq;\": { \"codepoints\": [8806, 824], \"characters\": \"\\u2266\\u0338\" },\n  \"&nleqslant;\": { \"codepoints\": [10877, 824], \"characters\": \"\\u2A7D\\u0338\" },\n  \"&nles;\": { \"codepoints\": [10877, 824], \"characters\": \"\\u2A7D\\u0338\" },\n  \"&nless;\": { \"codepoints\": [8814], \"characters\": \"\\u226E\" },\n  \"&nLl;\": { \"codepoints\": [8920, 824], \"characters\": \"\\u22D8\\u0338\" },\n  \"&nlsim;\": { \"codepoints\": [8820], \"characters\": \"\\u2274\" },\n  \"&nLt;\": { \"codepoints\": [8810, 8402], \"characters\": \"\\u226A\\u20D2\" },\n  \"&nlt;\": { \"codepoints\": [8814], \"characters\": \"\\u226E\" },\n  \"&nltri;\": { \"codepoints\": [8938], \"characters\": \"\\u22EA\" },\n  \"&nltrie;\": { \"codepoints\": [8940], \"characters\": \"\\u22EC\" },\n  \"&nLtv;\": { \"codepoints\": [8810, 824], \"characters\": \"\\u226A\\u0338\" },\n  \"&nmid;\": { \"codepoints\": [8740], \"characters\": \"\\u2224\" },\n  \"&NoBreak;\": { \"codepoints\": [8288], \"characters\": \"\\u2060\" },\n  \"&NonBreakingSpace;\": { \"codepoints\": [160], \"characters\": \"\\u00A0\" },\n  \"&nopf;\": { \"codepoints\": [120159], \"characters\": \"\\uD835\\uDD5F\" },\n  \"&Nopf;\": { \"codepoints\": [8469], \"characters\": \"\\u2115\" },\n  \"&Not;\": { \"codepoints\": [10988], \"characters\": \"\\u2AEC\" },\n  \"&not;\": { \"codepoints\": [172], \"characters\": \"\\u00AC\" },\n  \"&not\": { \"codepoints\": [172], \"characters\": \"\\u00AC\" },\n  \"&NotCongruent;\": { \"codepoints\": [8802], \"characters\": \"\\u2262\" },\n  \"&NotCupCap;\": { \"codepoints\": [8813], \"characters\": \"\\u226D\" },\n  \"&NotDoubleVerticalBar;\": { \"codepoints\": [8742], \"characters\": \"\\u2226\" },\n  \"&NotElement;\": { \"codepoints\": [8713], \"characters\": \"\\u2209\" },\n  \"&NotEqual;\": { \"codepoints\": [8800], \"characters\": \"\\u2260\" },\n  \"&NotEqualTilde;\": { \"codepoints\": [8770, 824], \"characters\": \"\\u2242\\u0338\" },\n  \"&NotExists;\": { \"codepoints\": [8708], \"characters\": \"\\u2204\" },\n  \"&NotGreater;\": { \"codepoints\": [8815], \"characters\": \"\\u226F\" },\n  \"&NotGreaterEqual;\": { \"codepoints\": [8817], \"characters\": \"\\u2271\" },\n  \"&NotGreaterFullEqual;\": { \"codepoints\": [8807, 824], \"characters\": \"\\u2267\\u0338\" },\n  \"&NotGreaterGreater;\": { \"codepoints\": [8811, 824], \"characters\": \"\\u226B\\u0338\" },\n  \"&NotGreaterLess;\": { \"codepoints\": [8825], \"characters\": \"\\u2279\" },\n  \"&NotGreaterSlantEqual;\": { \"codepoints\": [10878, 824], \"characters\": \"\\u2A7E\\u0338\" },\n  \"&NotGreaterTilde;\": { \"codepoints\": [8821], \"characters\": \"\\u2275\" },\n  \"&NotHumpDownHump;\": { \"codepoints\": [8782, 824], \"characters\": \"\\u224E\\u0338\" },\n  \"&NotHumpEqual;\": { \"codepoints\": [8783, 824], \"characters\": \"\\u224F\\u0338\" },\n  \"&notin;\": { \"codepoints\": [8713], \"characters\": \"\\u2209\" },\n  \"&notindot;\": { \"codepoints\": [8949, 824], \"characters\": \"\\u22F5\\u0338\" },\n  \"&notinE;\": { \"codepoints\": [8953, 824], \"characters\": \"\\u22F9\\u0338\" },\n  \"&notinva;\": { \"codepoints\": [8713], \"characters\": \"\\u2209\" },\n  \"&notinvb;\": { \"codepoints\": [8951], \"characters\": \"\\u22F7\" },\n  \"&notinvc;\": { \"codepoints\": [8950], \"characters\": \"\\u22F6\" },\n  \"&NotLeftTriangleBar;\": { \"codepoints\": [10703, 824], \"characters\": \"\\u29CF\\u0338\" },\n  \"&NotLeftTriangle;\": { \"codepoints\": [8938], \"characters\": \"\\u22EA\" },\n  \"&NotLeftTriangleEqual;\": { \"codepoints\": [8940], \"characters\": \"\\u22EC\" },\n  \"&NotLess;\": { \"codepoints\": [8814], \"characters\": \"\\u226E\" },\n  \"&NotLessEqual;\": { \"codepoints\": [8816], \"characters\": \"\\u2270\" },\n  \"&NotLessGreater;\": { \"codepoints\": [8824], \"characters\": \"\\u2278\" },\n  \"&NotLessLess;\": { \"codepoints\": [8810, 824], \"characters\": \"\\u226A\\u0338\" },\n  \"&NotLessSlantEqual;\": { \"codepoints\": [10877, 824], \"characters\": \"\\u2A7D\\u0338\" },\n  \"&NotLessTilde;\": { \"codepoints\": [8820], \"characters\": \"\\u2274\" },\n  \"&NotNestedGreaterGreater;\": { \"codepoints\": [10914, 824], \"characters\": \"\\u2AA2\\u0338\" },\n  \"&NotNestedLessLess;\": { \"codepoints\": [10913, 824], \"characters\": \"\\u2AA1\\u0338\" },\n  \"&notni;\": { \"codepoints\": [8716], \"characters\": \"\\u220C\" },\n  \"&notniva;\": { \"codepoints\": [8716], \"characters\": \"\\u220C\" },\n  \"&notnivb;\": { \"codepoints\": [8958], \"characters\": \"\\u22FE\" },\n  \"&notnivc;\": { \"codepoints\": [8957], \"characters\": \"\\u22FD\" },\n  \"&NotPrecedes;\": { \"codepoints\": [8832], \"characters\": \"\\u2280\" },\n  \"&NotPrecedesEqual;\": { \"codepoints\": [10927, 824], \"characters\": \"\\u2AAF\\u0338\" },\n  \"&NotPrecedesSlantEqual;\": { \"codepoints\": [8928], \"characters\": \"\\u22E0\" },\n  \"&NotReverseElement;\": { \"codepoints\": [8716], \"characters\": \"\\u220C\" },\n  \"&NotRightTriangleBar;\": { \"codepoints\": [10704, 824], \"characters\": \"\\u29D0\\u0338\" },\n  \"&NotRightTriangle;\": { \"codepoints\": [8939], \"characters\": \"\\u22EB\" },\n  \"&NotRightTriangleEqual;\": { \"codepoints\": [8941], \"characters\": \"\\u22ED\" },\n  \"&NotSquareSubset;\": { \"codepoints\": [8847, 824], \"characters\": \"\\u228F\\u0338\" },\n  \"&NotSquareSubsetEqual;\": { \"codepoints\": [8930], \"characters\": \"\\u22E2\" },\n  \"&NotSquareSuperset;\": { \"codepoints\": [8848, 824], \"characters\": \"\\u2290\\u0338\" },\n  \"&NotSquareSupersetEqual;\": { \"codepoints\": [8931], \"characters\": \"\\u22E3\" },\n  \"&NotSubset;\": { \"codepoints\": [8834, 8402], \"characters\": \"\\u2282\\u20D2\" },\n  \"&NotSubsetEqual;\": { \"codepoints\": [8840], \"characters\": \"\\u2288\" },\n  \"&NotSucceeds;\": { \"codepoints\": [8833], \"characters\": \"\\u2281\" },\n  \"&NotSucceedsEqual;\": { \"codepoints\": [10928, 824], \"characters\": \"\\u2AB0\\u0338\" },\n  \"&NotSucceedsSlantEqual;\": { \"codepoints\": [8929], \"characters\": \"\\u22E1\" },\n  \"&NotSucceedsTilde;\": { \"codepoints\": [8831, 824], \"characters\": \"\\u227F\\u0338\" },\n  \"&NotSuperset;\": { \"codepoints\": [8835, 8402], \"characters\": \"\\u2283\\u20D2\" },\n  \"&NotSupersetEqual;\": { \"codepoints\": [8841], \"characters\": \"\\u2289\" },\n  \"&NotTilde;\": { \"codepoints\": [8769], \"characters\": \"\\u2241\" },\n  \"&NotTildeEqual;\": { \"codepoints\": [8772], \"characters\": \"\\u2244\" },\n  \"&NotTildeFullEqual;\": { \"codepoints\": [8775], \"characters\": \"\\u2247\" },\n  \"&NotTildeTilde;\": { \"codepoints\": [8777], \"characters\": \"\\u2249\" },\n  \"&NotVerticalBar;\": { \"codepoints\": [8740], \"characters\": \"\\u2224\" },\n  \"&nparallel;\": { \"codepoints\": [8742], \"characters\": \"\\u2226\" },\n  \"&npar;\": { \"codepoints\": [8742], \"characters\": \"\\u2226\" },\n  \"&nparsl;\": { \"codepoints\": [11005, 8421], \"characters\": \"\\u2AFD\\u20E5\" },\n  \"&npart;\": { \"codepoints\": [8706, 824], \"characters\": \"\\u2202\\u0338\" },\n  \"&npolint;\": { \"codepoints\": [10772], \"characters\": \"\\u2A14\" },\n  \"&npr;\": { \"codepoints\": [8832], \"characters\": \"\\u2280\" },\n  \"&nprcue;\": { \"codepoints\": [8928], \"characters\": \"\\u22E0\" },\n  \"&nprec;\": { \"codepoints\": [8832], \"characters\": \"\\u2280\" },\n  \"&npreceq;\": { \"codepoints\": [10927, 824], \"characters\": \"\\u2AAF\\u0338\" },\n  \"&npre;\": { \"codepoints\": [10927, 824], \"characters\": \"\\u2AAF\\u0338\" },\n  \"&nrarrc;\": { \"codepoints\": [10547, 824], \"characters\": \"\\u2933\\u0338\" },\n  \"&nrarr;\": { \"codepoints\": [8603], \"characters\": \"\\u219B\" },\n  \"&nrArr;\": { \"codepoints\": [8655], \"characters\": \"\\u21CF\" },\n  \"&nrarrw;\": { \"codepoints\": [8605, 824], \"characters\": \"\\u219D\\u0338\" },\n  \"&nrightarrow;\": { \"codepoints\": [8603], \"characters\": \"\\u219B\" },\n  \"&nRightarrow;\": { \"codepoints\": [8655], \"characters\": \"\\u21CF\" },\n  \"&nrtri;\": { \"codepoints\": [8939], \"characters\": \"\\u22EB\" },\n  \"&nrtrie;\": { \"codepoints\": [8941], \"characters\": \"\\u22ED\" },\n  \"&nsc;\": { \"codepoints\": [8833], \"characters\": \"\\u2281\" },\n  \"&nsccue;\": { \"codepoints\": [8929], \"characters\": \"\\u22E1\" },\n  \"&nsce;\": { \"codepoints\": [10928, 824], \"characters\": \"\\u2AB0\\u0338\" },\n  \"&Nscr;\": { \"codepoints\": [119977], \"characters\": \"\\uD835\\uDCA9\" },\n  \"&nscr;\": { \"codepoints\": [120003], \"characters\": \"\\uD835\\uDCC3\" },\n  \"&nshortmid;\": { \"codepoints\": [8740], \"characters\": \"\\u2224\" },\n  \"&nshortparallel;\": { \"codepoints\": [8742], \"characters\": \"\\u2226\" },\n  \"&nsim;\": { \"codepoints\": [8769], \"characters\": \"\\u2241\" },\n  \"&nsime;\": { \"codepoints\": [8772], \"characters\": \"\\u2244\" },\n  \"&nsimeq;\": { \"codepoints\": [8772], \"characters\": \"\\u2244\" },\n  \"&nsmid;\": { \"codepoints\": [8740], \"characters\": \"\\u2224\" },\n  \"&nspar;\": { \"codepoints\": [8742], \"characters\": \"\\u2226\" },\n  \"&nsqsube;\": { \"codepoints\": [8930], \"characters\": \"\\u22E2\" },\n  \"&nsqsupe;\": { \"codepoints\": [8931], \"characters\": \"\\u22E3\" },\n  \"&nsub;\": { \"codepoints\": [8836], \"characters\": \"\\u2284\" },\n  \"&nsubE;\": { \"codepoints\": [10949, 824], \"characters\": \"\\u2AC5\\u0338\" },\n  \"&nsube;\": { \"codepoints\": [8840], \"characters\": \"\\u2288\" },\n  \"&nsubset;\": { \"codepoints\": [8834, 8402], \"characters\": \"\\u2282\\u20D2\" },\n  \"&nsubseteq;\": { \"codepoints\": [8840], \"characters\": \"\\u2288\" },\n  \"&nsubseteqq;\": { \"codepoints\": [10949, 824], \"characters\": \"\\u2AC5\\u0338\" },\n  \"&nsucc;\": { \"codepoints\": [8833], \"characters\": \"\\u2281\" },\n  \"&nsucceq;\": { \"codepoints\": [10928, 824], \"characters\": \"\\u2AB0\\u0338\" },\n  \"&nsup;\": { \"codepoints\": [8837], \"characters\": \"\\u2285\" },\n  \"&nsupE;\": { \"codepoints\": [10950, 824], \"characters\": \"\\u2AC6\\u0338\" },\n  \"&nsupe;\": { \"codepoints\": [8841], \"characters\": \"\\u2289\" },\n  \"&nsupset;\": { \"codepoints\": [8835, 8402], \"characters\": \"\\u2283\\u20D2\" },\n  \"&nsupseteq;\": { \"codepoints\": [8841], \"characters\": \"\\u2289\" },\n  \"&nsupseteqq;\": { \"codepoints\": [10950, 824], \"characters\": \"\\u2AC6\\u0338\" },\n  \"&ntgl;\": { \"codepoints\": [8825], \"characters\": \"\\u2279\" },\n  \"&Ntilde;\": { \"codepoints\": [209], \"characters\": \"\\u00D1\" },\n  \"&Ntilde\": { \"codepoints\": [209], \"characters\": \"\\u00D1\" },\n  \"&ntilde;\": { \"codepoints\": [241], \"characters\": \"\\u00F1\" },\n  \"&ntilde\": { \"codepoints\": [241], \"characters\": \"\\u00F1\" },\n  \"&ntlg;\": { \"codepoints\": [8824], \"characters\": \"\\u2278\" },\n  \"&ntriangleleft;\": { \"codepoints\": [8938], \"characters\": \"\\u22EA\" },\n  \"&ntrianglelefteq;\": { \"codepoints\": [8940], \"characters\": \"\\u22EC\" },\n  \"&ntriangleright;\": { \"codepoints\": [8939], \"characters\": \"\\u22EB\" },\n  \"&ntrianglerighteq;\": { \"codepoints\": [8941], \"characters\": \"\\u22ED\" },\n  \"&Nu;\": { \"codepoints\": [925], \"characters\": \"\\u039D\" },\n  \"&nu;\": { \"codepoints\": [957], \"characters\": \"\\u03BD\" },\n  \"&num;\": { \"codepoints\": [35], \"characters\": \"\\u0023\" },\n  \"&numero;\": { \"codepoints\": [8470], \"characters\": \"\\u2116\" },\n  \"&numsp;\": { \"codepoints\": [8199], \"characters\": \"\\u2007\" },\n  \"&nvap;\": { \"codepoints\": [8781, 8402], \"characters\": \"\\u224D\\u20D2\" },\n  \"&nvdash;\": { \"codepoints\": [8876], \"characters\": \"\\u22AC\" },\n  \"&nvDash;\": { \"codepoints\": [8877], \"characters\": \"\\u22AD\" },\n  \"&nVdash;\": { \"codepoints\": [8878], \"characters\": \"\\u22AE\" },\n  \"&nVDash;\": { \"codepoints\": [8879], \"characters\": \"\\u22AF\" },\n  \"&nvge;\": { \"codepoints\": [8805, 8402], \"characters\": \"\\u2265\\u20D2\" },\n  \"&nvgt;\": { \"codepoints\": [62, 8402], \"characters\": \"\\u003E\\u20D2\" },\n  \"&nvHarr;\": { \"codepoints\": [10500], \"characters\": \"\\u2904\" },\n  \"&nvinfin;\": { \"codepoints\": [10718], \"characters\": \"\\u29DE\" },\n  \"&nvlArr;\": { \"codepoints\": [10498], \"characters\": \"\\u2902\" },\n  \"&nvle;\": { \"codepoints\": [8804, 8402], \"characters\": \"\\u2264\\u20D2\" },\n  \"&nvlt;\": { \"codepoints\": [60, 8402], \"characters\": \"\\u003C\\u20D2\" },\n  \"&nvltrie;\": { \"codepoints\": [8884, 8402], \"characters\": \"\\u22B4\\u20D2\" },\n  \"&nvrArr;\": { \"codepoints\": [10499], \"characters\": \"\\u2903\" },\n  \"&nvrtrie;\": { \"codepoints\": [8885, 8402], \"characters\": \"\\u22B5\\u20D2\" },\n  \"&nvsim;\": { \"codepoints\": [8764, 8402], \"characters\": \"\\u223C\\u20D2\" },\n  \"&nwarhk;\": { \"codepoints\": [10531], \"characters\": \"\\u2923\" },\n  \"&nwarr;\": { \"codepoints\": [8598], \"characters\": \"\\u2196\" },\n  \"&nwArr;\": { \"codepoints\": [8662], \"characters\": \"\\u21D6\" },\n  \"&nwarrow;\": { \"codepoints\": [8598], \"characters\": \"\\u2196\" },\n  \"&nwnear;\": { \"codepoints\": [10535], \"characters\": \"\\u2927\" },\n  \"&Oacute;\": { \"codepoints\": [211], \"characters\": \"\\u00D3\" },\n  \"&Oacute\": { \"codepoints\": [211], \"characters\": \"\\u00D3\" },\n  \"&oacute;\": { \"codepoints\": [243], \"characters\": \"\\u00F3\" },\n  \"&oacute\": { \"codepoints\": [243], \"characters\": \"\\u00F3\" },\n  \"&oast;\": { \"codepoints\": [8859], \"characters\": \"\\u229B\" },\n  \"&Ocirc;\": { \"codepoints\": [212], \"characters\": \"\\u00D4\" },\n  \"&Ocirc\": { \"codepoints\": [212], \"characters\": \"\\u00D4\" },\n  \"&ocirc;\": { \"codepoints\": [244], \"characters\": \"\\u00F4\" },\n  \"&ocirc\": { \"codepoints\": [244], \"characters\": \"\\u00F4\" },\n  \"&ocir;\": { \"codepoints\": [8858], \"characters\": \"\\u229A\" },\n  \"&Ocy;\": { \"codepoints\": [1054], \"characters\": \"\\u041E\" },\n  \"&ocy;\": { \"codepoints\": [1086], \"characters\": \"\\u043E\" },\n  \"&odash;\": { \"codepoints\": [8861], \"characters\": \"\\u229D\" },\n  \"&Odblac;\": { \"codepoints\": [336], \"characters\": \"\\u0150\" },\n  \"&odblac;\": { \"codepoints\": [337], \"characters\": \"\\u0151\" },\n  \"&odiv;\": { \"codepoints\": [10808], \"characters\": \"\\u2A38\" },\n  \"&odot;\": { \"codepoints\": [8857], \"characters\": \"\\u2299\" },\n  \"&odsold;\": { \"codepoints\": [10684], \"characters\": \"\\u29BC\" },\n  \"&OElig;\": { \"codepoints\": [338], \"characters\": \"\\u0152\" },\n  \"&oelig;\": { \"codepoints\": [339], \"characters\": \"\\u0153\" },\n  \"&ofcir;\": { \"codepoints\": [10687], \"characters\": \"\\u29BF\" },\n  \"&Ofr;\": { \"codepoints\": [120082], \"characters\": \"\\uD835\\uDD12\" },\n  \"&ofr;\": { \"codepoints\": [120108], \"characters\": \"\\uD835\\uDD2C\" },\n  \"&ogon;\": { \"codepoints\": [731], \"characters\": \"\\u02DB\" },\n  \"&Ograve;\": { \"codepoints\": [210], \"characters\": \"\\u00D2\" },\n  \"&Ograve\": { \"codepoints\": [210], \"characters\": \"\\u00D2\" },\n  \"&ograve;\": { \"codepoints\": [242], \"characters\": \"\\u00F2\" },\n  \"&ograve\": { \"codepoints\": [242], \"characters\": \"\\u00F2\" },\n  \"&ogt;\": { \"codepoints\": [10689], \"characters\": \"\\u29C1\" },\n  \"&ohbar;\": { \"codepoints\": [10677], \"characters\": \"\\u29B5\" },\n  \"&ohm;\": { \"codepoints\": [937], \"characters\": \"\\u03A9\" },\n  \"&oint;\": { \"codepoints\": [8750], \"characters\": \"\\u222E\" },\n  \"&olarr;\": { \"codepoints\": [8634], \"characters\": \"\\u21BA\" },\n  \"&olcir;\": { \"codepoints\": [10686], \"characters\": \"\\u29BE\" },\n  \"&olcross;\": { \"codepoints\": [10683], \"characters\": \"\\u29BB\" },\n  \"&oline;\": { \"codepoints\": [8254], \"characters\": \"\\u203E\" },\n  \"&olt;\": { \"codepoints\": [10688], \"characters\": \"\\u29C0\" },\n  \"&Omacr;\": { \"codepoints\": [332], \"characters\": \"\\u014C\" },\n  \"&omacr;\": { \"codepoints\": [333], \"characters\": \"\\u014D\" },\n  \"&Omega;\": { \"codepoints\": [937], \"characters\": \"\\u03A9\" },\n  \"&omega;\": { \"codepoints\": [969], \"characters\": \"\\u03C9\" },\n  \"&Omicron;\": { \"codepoints\": [927], \"characters\": \"\\u039F\" },\n  \"&omicron;\": { \"codepoints\": [959], \"characters\": \"\\u03BF\" },\n  \"&omid;\": { \"codepoints\": [10678], \"characters\": \"\\u29B6\" },\n  \"&ominus;\": { \"codepoints\": [8854], \"characters\": \"\\u2296\" },\n  \"&Oopf;\": { \"codepoints\": [120134], \"characters\": \"\\uD835\\uDD46\" },\n  \"&oopf;\": { \"codepoints\": [120160], \"characters\": \"\\uD835\\uDD60\" },\n  \"&opar;\": { \"codepoints\": [10679], \"characters\": \"\\u29B7\" },\n  \"&OpenCurlyDoubleQuote;\": { \"codepoints\": [8220], \"characters\": \"\\u201C\" },\n  \"&OpenCurlyQuote;\": { \"codepoints\": [8216], \"characters\": \"\\u2018\" },\n  \"&operp;\": { \"codepoints\": [10681], \"characters\": \"\\u29B9\" },\n  \"&oplus;\": { \"codepoints\": [8853], \"characters\": \"\\u2295\" },\n  \"&orarr;\": { \"codepoints\": [8635], \"characters\": \"\\u21BB\" },\n  \"&Or;\": { \"codepoints\": [10836], \"characters\": \"\\u2A54\" },\n  \"&or;\": { \"codepoints\": [8744], \"characters\": \"\\u2228\" },\n  \"&ord;\": { \"codepoints\": [10845], \"characters\": \"\\u2A5D\" },\n  \"&order;\": { \"codepoints\": [8500], \"characters\": \"\\u2134\" },\n  \"&orderof;\": { \"codepoints\": [8500], \"characters\": \"\\u2134\" },\n  \"&ordf;\": { \"codepoints\": [170], \"characters\": \"\\u00AA\" },\n  \"&ordf\": { \"codepoints\": [170], \"characters\": \"\\u00AA\" },\n  \"&ordm;\": { \"codepoints\": [186], \"characters\": \"\\u00BA\" },\n  \"&ordm\": { \"codepoints\": [186], \"characters\": \"\\u00BA\" },\n  \"&origof;\": { \"codepoints\": [8886], \"characters\": \"\\u22B6\" },\n  \"&oror;\": { \"codepoints\": [10838], \"characters\": \"\\u2A56\" },\n  \"&orslope;\": { \"codepoints\": [10839], \"characters\": \"\\u2A57\" },\n  \"&orv;\": { \"codepoints\": [10843], \"characters\": \"\\u2A5B\" },\n  \"&oS;\": { \"codepoints\": [9416], \"characters\": \"\\u24C8\" },\n  \"&Oscr;\": { \"codepoints\": [119978], \"characters\": \"\\uD835\\uDCAA\" },\n  \"&oscr;\": { \"codepoints\": [8500], \"characters\": \"\\u2134\" },\n  \"&Oslash;\": { \"codepoints\": [216], \"characters\": \"\\u00D8\" },\n  \"&Oslash\": { \"codepoints\": [216], \"characters\": \"\\u00D8\" },\n  \"&oslash;\": { \"codepoints\": [248], \"characters\": \"\\u00F8\" },\n  \"&oslash\": { \"codepoints\": [248], \"characters\": \"\\u00F8\" },\n  \"&osol;\": { \"codepoints\": [8856], \"characters\": \"\\u2298\" },\n  \"&Otilde;\": { \"codepoints\": [213], \"characters\": \"\\u00D5\" },\n  \"&Otilde\": { \"codepoints\": [213], \"characters\": \"\\u00D5\" },\n  \"&otilde;\": { \"codepoints\": [245], \"characters\": \"\\u00F5\" },\n  \"&otilde\": { \"codepoints\": [245], \"characters\": \"\\u00F5\" },\n  \"&otimesas;\": { \"codepoints\": [10806], \"characters\": \"\\u2A36\" },\n  \"&Otimes;\": { \"codepoints\": [10807], \"characters\": \"\\u2A37\" },\n  \"&otimes;\": { \"codepoints\": [8855], \"characters\": \"\\u2297\" },\n  \"&Ouml;\": { \"codepoints\": [214], \"characters\": \"\\u00D6\" },\n  \"&Ouml\": { \"codepoints\": [214], \"characters\": \"\\u00D6\" },\n  \"&ouml;\": { \"codepoints\": [246], \"characters\": \"\\u00F6\" },\n  \"&ouml\": { \"codepoints\": [246], \"characters\": \"\\u00F6\" },\n  \"&ovbar;\": { \"codepoints\": [9021], \"characters\": \"\\u233D\" },\n  \"&OverBar;\": { \"codepoints\": [8254], \"characters\": \"\\u203E\" },\n  \"&OverBrace;\": { \"codepoints\": [9182], \"characters\": \"\\u23DE\" },\n  \"&OverBracket;\": { \"codepoints\": [9140], \"characters\": \"\\u23B4\" },\n  \"&OverParenthesis;\": { \"codepoints\": [9180], \"characters\": \"\\u23DC\" },\n  \"&para;\": { \"codepoints\": [182], \"characters\": \"\\u00B6\" },\n  \"&para\": { \"codepoints\": [182], \"characters\": \"\\u00B6\" },\n  \"&parallel;\": { \"codepoints\": [8741], \"characters\": \"\\u2225\" },\n  \"&par;\": { \"codepoints\": [8741], \"characters\": \"\\u2225\" },\n  \"&parsim;\": { \"codepoints\": [10995], \"characters\": \"\\u2AF3\" },\n  \"&parsl;\": { \"codepoints\": [11005], \"characters\": \"\\u2AFD\" },\n  \"&part;\": { \"codepoints\": [8706], \"characters\": \"\\u2202\" },\n  \"&PartialD;\": { \"codepoints\": [8706], \"characters\": \"\\u2202\" },\n  \"&Pcy;\": { \"codepoints\": [1055], \"characters\": \"\\u041F\" },\n  \"&pcy;\": { \"codepoints\": [1087], \"characters\": \"\\u043F\" },\n  \"&percnt;\": { \"codepoints\": [37], \"characters\": \"\\u0025\" },\n  \"&period;\": { \"codepoints\": [46], \"characters\": \"\\u002E\" },\n  \"&permil;\": { \"codepoints\": [8240], \"characters\": \"\\u2030\" },\n  \"&perp;\": { \"codepoints\": [8869], \"characters\": \"\\u22A5\" },\n  \"&pertenk;\": { \"codepoints\": [8241], \"characters\": \"\\u2031\" },\n  \"&Pfr;\": { \"codepoints\": [120083], \"characters\": \"\\uD835\\uDD13\" },\n  \"&pfr;\": { \"codepoints\": [120109], \"characters\": \"\\uD835\\uDD2D\" },\n  \"&Phi;\": { \"codepoints\": [934], \"characters\": \"\\u03A6\" },\n  \"&phi;\": { \"codepoints\": [966], \"characters\": \"\\u03C6\" },\n  \"&phiv;\": { \"codepoints\": [981], \"characters\": \"\\u03D5\" },\n  \"&phmmat;\": { \"codepoints\": [8499], \"characters\": \"\\u2133\" },\n  \"&phone;\": { \"codepoints\": [9742], \"characters\": \"\\u260E\" },\n  \"&Pi;\": { \"codepoints\": [928], \"characters\": \"\\u03A0\" },\n  \"&pi;\": { \"codepoints\": [960], \"characters\": \"\\u03C0\" },\n  \"&pitchfork;\": { \"codepoints\": [8916], \"characters\": \"\\u22D4\" },\n  \"&piv;\": { \"codepoints\": [982], \"characters\": \"\\u03D6\" },\n  \"&planck;\": { \"codepoints\": [8463], \"characters\": \"\\u210F\" },\n  \"&planckh;\": { \"codepoints\": [8462], \"characters\": \"\\u210E\" },\n  \"&plankv;\": { \"codepoints\": [8463], \"characters\": \"\\u210F\" },\n  \"&plusacir;\": { \"codepoints\": [10787], \"characters\": \"\\u2A23\" },\n  \"&plusb;\": { \"codepoints\": [8862], \"characters\": \"\\u229E\" },\n  \"&pluscir;\": { \"codepoints\": [10786], \"characters\": \"\\u2A22\" },\n  \"&plus;\": { \"codepoints\": [43], \"characters\": \"\\u002B\" },\n  \"&plusdo;\": { \"codepoints\": [8724], \"characters\": \"\\u2214\" },\n  \"&plusdu;\": { \"codepoints\": [10789], \"characters\": \"\\u2A25\" },\n  \"&pluse;\": { \"codepoints\": [10866], \"characters\": \"\\u2A72\" },\n  \"&PlusMinus;\": { \"codepoints\": [177], \"characters\": \"\\u00B1\" },\n  \"&plusmn;\": { \"codepoints\": [177], \"characters\": \"\\u00B1\" },\n  \"&plusmn\": { \"codepoints\": [177], \"characters\": \"\\u00B1\" },\n  \"&plussim;\": { \"codepoints\": [10790], \"characters\": \"\\u2A26\" },\n  \"&plustwo;\": { \"codepoints\": [10791], \"characters\": \"\\u2A27\" },\n  \"&pm;\": { \"codepoints\": [177], \"characters\": \"\\u00B1\" },\n  \"&Poincareplane;\": { \"codepoints\": [8460], \"characters\": \"\\u210C\" },\n  \"&pointint;\": { \"codepoints\": [10773], \"characters\": \"\\u2A15\" },\n  \"&popf;\": { \"codepoints\": [120161], \"characters\": \"\\uD835\\uDD61\" },\n  \"&Popf;\": { \"codepoints\": [8473], \"characters\": \"\\u2119\" },\n  \"&pound;\": { \"codepoints\": [163], \"characters\": \"\\u00A3\" },\n  \"&pound\": { \"codepoints\": [163], \"characters\": \"\\u00A3\" },\n  \"&prap;\": { \"codepoints\": [10935], \"characters\": \"\\u2AB7\" },\n  \"&Pr;\": { \"codepoints\": [10939], \"characters\": \"\\u2ABB\" },\n  \"&pr;\": { \"codepoints\": [8826], \"characters\": \"\\u227A\" },\n  \"&prcue;\": { \"codepoints\": [8828], \"characters\": \"\\u227C\" },\n  \"&precapprox;\": { \"codepoints\": [10935], \"characters\": \"\\u2AB7\" },\n  \"&prec;\": { \"codepoints\": [8826], \"characters\": \"\\u227A\" },\n  \"&preccurlyeq;\": { \"codepoints\": [8828], \"characters\": \"\\u227C\" },\n  \"&Precedes;\": { \"codepoints\": [8826], \"characters\": \"\\u227A\" },\n  \"&PrecedesEqual;\": { \"codepoints\": [10927], \"characters\": \"\\u2AAF\" },\n  \"&PrecedesSlantEqual;\": { \"codepoints\": [8828], \"characters\": \"\\u227C\" },\n  \"&PrecedesTilde;\": { \"codepoints\": [8830], \"characters\": \"\\u227E\" },\n  \"&preceq;\": { \"codepoints\": [10927], \"characters\": \"\\u2AAF\" },\n  \"&precnapprox;\": { \"codepoints\": [10937], \"characters\": \"\\u2AB9\" },\n  \"&precneqq;\": { \"codepoints\": [10933], \"characters\": \"\\u2AB5\" },\n  \"&precnsim;\": { \"codepoints\": [8936], \"characters\": \"\\u22E8\" },\n  \"&pre;\": { \"codepoints\": [10927], \"characters\": \"\\u2AAF\" },\n  \"&prE;\": { \"codepoints\": [10931], \"characters\": \"\\u2AB3\" },\n  \"&precsim;\": { \"codepoints\": [8830], \"characters\": \"\\u227E\" },\n  \"&prime;\": { \"codepoints\": [8242], \"characters\": \"\\u2032\" },\n  \"&Prime;\": { \"codepoints\": [8243], \"characters\": \"\\u2033\" },\n  \"&primes;\": { \"codepoints\": [8473], \"characters\": \"\\u2119\" },\n  \"&prnap;\": { \"codepoints\": [10937], \"characters\": \"\\u2AB9\" },\n  \"&prnE;\": { \"codepoints\": [10933], \"characters\": \"\\u2AB5\" },\n  \"&prnsim;\": { \"codepoints\": [8936], \"characters\": \"\\u22E8\" },\n  \"&prod;\": { \"codepoints\": [8719], \"characters\": \"\\u220F\" },\n  \"&Product;\": { \"codepoints\": [8719], \"characters\": \"\\u220F\" },\n  \"&profalar;\": { \"codepoints\": [9006], \"characters\": \"\\u232E\" },\n  \"&profline;\": { \"codepoints\": [8978], \"characters\": \"\\u2312\" },\n  \"&profsurf;\": { \"codepoints\": [8979], \"characters\": \"\\u2313\" },\n  \"&prop;\": { \"codepoints\": [8733], \"characters\": \"\\u221D\" },\n  \"&Proportional;\": { \"codepoints\": [8733], \"characters\": \"\\u221D\" },\n  \"&Proportion;\": { \"codepoints\": [8759], \"characters\": \"\\u2237\" },\n  \"&propto;\": { \"codepoints\": [8733], \"characters\": \"\\u221D\" },\n  \"&prsim;\": { \"codepoints\": [8830], \"characters\": \"\\u227E\" },\n  \"&prurel;\": { \"codepoints\": [8880], \"characters\": \"\\u22B0\" },\n  \"&Pscr;\": { \"codepoints\": [119979], \"characters\": \"\\uD835\\uDCAB\" },\n  \"&pscr;\": { \"codepoints\": [120005], \"characters\": \"\\uD835\\uDCC5\" },\n  \"&Psi;\": { \"codepoints\": [936], \"characters\": \"\\u03A8\" },\n  \"&psi;\": { \"codepoints\": [968], \"characters\": \"\\u03C8\" },\n  \"&puncsp;\": { \"codepoints\": [8200], \"characters\": \"\\u2008\" },\n  \"&Qfr;\": { \"codepoints\": [120084], \"characters\": \"\\uD835\\uDD14\" },\n  \"&qfr;\": { \"codepoints\": [120110], \"characters\": \"\\uD835\\uDD2E\" },\n  \"&qint;\": { \"codepoints\": [10764], \"characters\": \"\\u2A0C\" },\n  \"&qopf;\": { \"codepoints\": [120162], \"characters\": \"\\uD835\\uDD62\" },\n  \"&Qopf;\": { \"codepoints\": [8474], \"characters\": \"\\u211A\" },\n  \"&qprime;\": { \"codepoints\": [8279], \"characters\": \"\\u2057\" },\n  \"&Qscr;\": { \"codepoints\": [119980], \"characters\": \"\\uD835\\uDCAC\" },\n  \"&qscr;\": { \"codepoints\": [120006], \"characters\": \"\\uD835\\uDCC6\" },\n  \"&quaternions;\": { \"codepoints\": [8461], \"characters\": \"\\u210D\" },\n  \"&quatint;\": { \"codepoints\": [10774], \"characters\": \"\\u2A16\" },\n  \"&quest;\": { \"codepoints\": [63], \"characters\": \"\\u003F\" },\n  \"&questeq;\": { \"codepoints\": [8799], \"characters\": \"\\u225F\" },\n  \"&quot;\": { \"codepoints\": [34], \"characters\": \"\\u0022\" },\n  \"&quot\": { \"codepoints\": [34], \"characters\": \"\\u0022\" },\n  \"&QUOT;\": { \"codepoints\": [34], \"characters\": \"\\u0022\" },\n  \"&QUOT\": { \"codepoints\": [34], \"characters\": \"\\u0022\" },\n  \"&rAarr;\": { \"codepoints\": [8667], \"characters\": \"\\u21DB\" },\n  \"&race;\": { \"codepoints\": [8765, 817], \"characters\": \"\\u223D\\u0331\" },\n  \"&Racute;\": { \"codepoints\": [340], \"characters\": \"\\u0154\" },\n  \"&racute;\": { \"codepoints\": [341], \"characters\": \"\\u0155\" },\n  \"&radic;\": { \"codepoints\": [8730], \"characters\": \"\\u221A\" },\n  \"&raemptyv;\": { \"codepoints\": [10675], \"characters\": \"\\u29B3\" },\n  \"&rang;\": { \"codepoints\": [10217], \"characters\": \"\\u27E9\" },\n  \"&Rang;\": { \"codepoints\": [10219], \"characters\": \"\\u27EB\" },\n  \"&rangd;\": { \"codepoints\": [10642], \"characters\": \"\\u2992\" },\n  \"&range;\": { \"codepoints\": [10661], \"characters\": \"\\u29A5\" },\n  \"&rangle;\": { \"codepoints\": [10217], \"characters\": \"\\u27E9\" },\n  \"&raquo;\": { \"codepoints\": [187], \"characters\": \"\\u00BB\" },\n  \"&raquo\": { \"codepoints\": [187], \"characters\": \"\\u00BB\" },\n  \"&rarrap;\": { \"codepoints\": [10613], \"characters\": \"\\u2975\" },\n  \"&rarrb;\": { \"codepoints\": [8677], \"characters\": \"\\u21E5\" },\n  \"&rarrbfs;\": { \"codepoints\": [10528], \"characters\": \"\\u2920\" },\n  \"&rarrc;\": { \"codepoints\": [10547], \"characters\": \"\\u2933\" },\n  \"&rarr;\": { \"codepoints\": [8594], \"characters\": \"\\u2192\" },\n  \"&Rarr;\": { \"codepoints\": [8608], \"characters\": \"\\u21A0\" },\n  \"&rArr;\": { \"codepoints\": [8658], \"characters\": \"\\u21D2\" },\n  \"&rarrfs;\": { \"codepoints\": [10526], \"characters\": \"\\u291E\" },\n  \"&rarrhk;\": { \"codepoints\": [8618], \"characters\": \"\\u21AA\" },\n  \"&rarrlp;\": { \"codepoints\": [8620], \"characters\": \"\\u21AC\" },\n  \"&rarrpl;\": { \"codepoints\": [10565], \"characters\": \"\\u2945\" },\n  \"&rarrsim;\": { \"codepoints\": [10612], \"characters\": \"\\u2974\" },\n  \"&Rarrtl;\": { \"codepoints\": [10518], \"characters\": \"\\u2916\" },\n  \"&rarrtl;\": { \"codepoints\": [8611], \"characters\": \"\\u21A3\" },\n  \"&rarrw;\": { \"codepoints\": [8605], \"characters\": \"\\u219D\" },\n  \"&ratail;\": { \"codepoints\": [10522], \"characters\": \"\\u291A\" },\n  \"&rAtail;\": { \"codepoints\": [10524], \"characters\": \"\\u291C\" },\n  \"&ratio;\": { \"codepoints\": [8758], \"characters\": \"\\u2236\" },\n  \"&rationals;\": { \"codepoints\": [8474], \"characters\": \"\\u211A\" },\n  \"&rbarr;\": { \"codepoints\": [10509], \"characters\": \"\\u290D\" },\n  \"&rBarr;\": { \"codepoints\": [10511], \"characters\": \"\\u290F\" },\n  \"&RBarr;\": { \"codepoints\": [10512], \"characters\": \"\\u2910\" },\n  \"&rbbrk;\": { \"codepoints\": [10099], \"characters\": \"\\u2773\" },\n  \"&rbrace;\": { \"codepoints\": [125], \"characters\": \"\\u007D\" },\n  \"&rbrack;\": { \"codepoints\": [93], \"characters\": \"\\u005D\" },\n  \"&rbrke;\": { \"codepoints\": [10636], \"characters\": \"\\u298C\" },\n  \"&rbrksld;\": { \"codepoints\": [10638], \"characters\": \"\\u298E\" },\n  \"&rbrkslu;\": { \"codepoints\": [10640], \"characters\": \"\\u2990\" },\n  \"&Rcaron;\": { \"codepoints\": [344], \"characters\": \"\\u0158\" },\n  \"&rcaron;\": { \"codepoints\": [345], \"characters\": \"\\u0159\" },\n  \"&Rcedil;\": { \"codepoints\": [342], \"characters\": \"\\u0156\" },\n  \"&rcedil;\": { \"codepoints\": [343], \"characters\": \"\\u0157\" },\n  \"&rceil;\": { \"codepoints\": [8969], \"characters\": \"\\u2309\" },\n  \"&rcub;\": { \"codepoints\": [125], \"characters\": \"\\u007D\" },\n  \"&Rcy;\": { \"codepoints\": [1056], \"characters\": \"\\u0420\" },\n  \"&rcy;\": { \"codepoints\": [1088], \"characters\": \"\\u0440\" },\n  \"&rdca;\": { \"codepoints\": [10551], \"characters\": \"\\u2937\" },\n  \"&rdldhar;\": { \"codepoints\": [10601], \"characters\": \"\\u2969\" },\n  \"&rdquo;\": { \"codepoints\": [8221], \"characters\": \"\\u201D\" },\n  \"&rdquor;\": { \"codepoints\": [8221], \"characters\": \"\\u201D\" },\n  \"&rdsh;\": { \"codepoints\": [8627], \"characters\": \"\\u21B3\" },\n  \"&real;\": { \"codepoints\": [8476], \"characters\": \"\\u211C\" },\n  \"&realine;\": { \"codepoints\": [8475], \"characters\": \"\\u211B\" },\n  \"&realpart;\": { \"codepoints\": [8476], \"characters\": \"\\u211C\" },\n  \"&reals;\": { \"codepoints\": [8477], \"characters\": \"\\u211D\" },\n  \"&Re;\": { \"codepoints\": [8476], \"characters\": \"\\u211C\" },\n  \"&rect;\": { \"codepoints\": [9645], \"characters\": \"\\u25AD\" },\n  \"&reg;\": { \"codepoints\": [174], \"characters\": \"\\u00AE\" },\n  \"&reg\": { \"codepoints\": [174], \"characters\": \"\\u00AE\" },\n  \"&REG;\": { \"codepoints\": [174], \"characters\": \"\\u00AE\" },\n  \"&REG\": { \"codepoints\": [174], \"characters\": \"\\u00AE\" },\n  \"&ReverseElement;\": { \"codepoints\": [8715], \"characters\": \"\\u220B\" },\n  \"&ReverseEquilibrium;\": { \"codepoints\": [8651], \"characters\": \"\\u21CB\" },\n  \"&ReverseUpEquilibrium;\": { \"codepoints\": [10607], \"characters\": \"\\u296F\" },\n  \"&rfisht;\": { \"codepoints\": [10621], \"characters\": \"\\u297D\" },\n  \"&rfloor;\": { \"codepoints\": [8971], \"characters\": \"\\u230B\" },\n  \"&rfr;\": { \"codepoints\": [120111], \"characters\": \"\\uD835\\uDD2F\" },\n  \"&Rfr;\": { \"codepoints\": [8476], \"characters\": \"\\u211C\" },\n  \"&rHar;\": { \"codepoints\": [10596], \"characters\": \"\\u2964\" },\n  \"&rhard;\": { \"codepoints\": [8641], \"characters\": \"\\u21C1\" },\n  \"&rharu;\": { \"codepoints\": [8640], \"characters\": \"\\u21C0\" },\n  \"&rharul;\": { \"codepoints\": [10604], \"characters\": \"\\u296C\" },\n  \"&Rho;\": { \"codepoints\": [929], \"characters\": \"\\u03A1\" },\n  \"&rho;\": { \"codepoints\": [961], \"characters\": \"\\u03C1\" },\n  \"&rhov;\": { \"codepoints\": [1009], \"characters\": \"\\u03F1\" },\n  \"&RightAngleBracket;\": { \"codepoints\": [10217], \"characters\": \"\\u27E9\" },\n  \"&RightArrowBar;\": { \"codepoints\": [8677], \"characters\": \"\\u21E5\" },\n  \"&rightarrow;\": { \"codepoints\": [8594], \"characters\": \"\\u2192\" },\n  \"&RightArrow;\": { \"codepoints\": [8594], \"characters\": \"\\u2192\" },\n  \"&Rightarrow;\": { \"codepoints\": [8658], \"characters\": \"\\u21D2\" },\n  \"&RightArrowLeftArrow;\": { \"codepoints\": [8644], \"characters\": \"\\u21C4\" },\n  \"&rightarrowtail;\": { \"codepoints\": [8611], \"characters\": \"\\u21A3\" },\n  \"&RightCeiling;\": { \"codepoints\": [8969], \"characters\": \"\\u2309\" },\n  \"&RightDoubleBracket;\": { \"codepoints\": [10215], \"characters\": \"\\u27E7\" },\n  \"&RightDownTeeVector;\": { \"codepoints\": [10589], \"characters\": \"\\u295D\" },\n  \"&RightDownVectorBar;\": { \"codepoints\": [10581], \"characters\": \"\\u2955\" },\n  \"&RightDownVector;\": { \"codepoints\": [8642], \"characters\": \"\\u21C2\" },\n  \"&RightFloor;\": { \"codepoints\": [8971], \"characters\": \"\\u230B\" },\n  \"&rightharpoondown;\": { \"codepoints\": [8641], \"characters\": \"\\u21C1\" },\n  \"&rightharpoonup;\": { \"codepoints\": [8640], \"characters\": \"\\u21C0\" },\n  \"&rightleftarrows;\": { \"codepoints\": [8644], \"characters\": \"\\u21C4\" },\n  \"&rightleftharpoons;\": { \"codepoints\": [8652], \"characters\": \"\\u21CC\" },\n  \"&rightrightarrows;\": { \"codepoints\": [8649], \"characters\": \"\\u21C9\" },\n  \"&rightsquigarrow;\": { \"codepoints\": [8605], \"characters\": \"\\u219D\" },\n  \"&RightTeeArrow;\": { \"codepoints\": [8614], \"characters\": \"\\u21A6\" },\n  \"&RightTee;\": { \"codepoints\": [8866], \"characters\": \"\\u22A2\" },\n  \"&RightTeeVector;\": { \"codepoints\": [10587], \"characters\": \"\\u295B\" },\n  \"&rightthreetimes;\": { \"codepoints\": [8908], \"characters\": \"\\u22CC\" },\n  \"&RightTriangleBar;\": { \"codepoints\": [10704], \"characters\": \"\\u29D0\" },\n  \"&RightTriangle;\": { \"codepoints\": [8883], \"characters\": \"\\u22B3\" },\n  \"&RightTriangleEqual;\": { \"codepoints\": [8885], \"characters\": \"\\u22B5\" },\n  \"&RightUpDownVector;\": { \"codepoints\": [10575], \"characters\": \"\\u294F\" },\n  \"&RightUpTeeVector;\": { \"codepoints\": [10588], \"characters\": \"\\u295C\" },\n  \"&RightUpVectorBar;\": { \"codepoints\": [10580], \"characters\": \"\\u2954\" },\n  \"&RightUpVector;\": { \"codepoints\": [8638], \"characters\": \"\\u21BE\" },\n  \"&RightVectorBar;\": { \"codepoints\": [10579], \"characters\": \"\\u2953\" },\n  \"&RightVector;\": { \"codepoints\": [8640], \"characters\": \"\\u21C0\" },\n  \"&ring;\": { \"codepoints\": [730], \"characters\": \"\\u02DA\" },\n  \"&risingdotseq;\": { \"codepoints\": [8787], \"characters\": \"\\u2253\" },\n  \"&rlarr;\": { \"codepoints\": [8644], \"characters\": \"\\u21C4\" },\n  \"&rlhar;\": { \"codepoints\": [8652], \"characters\": \"\\u21CC\" },\n  \"&rlm;\": { \"codepoints\": [8207], \"characters\": \"\\u200F\" },\n  \"&rmoustache;\": { \"codepoints\": [9137], \"characters\": \"\\u23B1\" },\n  \"&rmoust;\": { \"codepoints\": [9137], \"characters\": \"\\u23B1\" },\n  \"&rnmid;\": { \"codepoints\": [10990], \"characters\": \"\\u2AEE\" },\n  \"&roang;\": { \"codepoints\": [10221], \"characters\": \"\\u27ED\" },\n  \"&roarr;\": { \"codepoints\": [8702], \"characters\": \"\\u21FE\" },\n  \"&robrk;\": { \"codepoints\": [10215], \"characters\": \"\\u27E7\" },\n  \"&ropar;\": { \"codepoints\": [10630], \"characters\": \"\\u2986\" },\n  \"&ropf;\": { \"codepoints\": [120163], \"characters\": \"\\uD835\\uDD63\" },\n  \"&Ropf;\": { \"codepoints\": [8477], \"characters\": \"\\u211D\" },\n  \"&roplus;\": { \"codepoints\": [10798], \"characters\": \"\\u2A2E\" },\n  \"&rotimes;\": { \"codepoints\": [10805], \"characters\": \"\\u2A35\" },\n  \"&RoundImplies;\": { \"codepoints\": [10608], \"characters\": \"\\u2970\" },\n  \"&rpar;\": { \"codepoints\": [41], \"characters\": \"\\u0029\" },\n  \"&rpargt;\": { \"codepoints\": [10644], \"characters\": \"\\u2994\" },\n  \"&rppolint;\": { \"codepoints\": [10770], \"characters\": \"\\u2A12\" },\n  \"&rrarr;\": { \"codepoints\": [8649], \"characters\": \"\\u21C9\" },\n  \"&Rrightarrow;\": { \"codepoints\": [8667], \"characters\": \"\\u21DB\" },\n  \"&rsaquo;\": { \"codepoints\": [8250], \"characters\": \"\\u203A\" },\n  \"&rscr;\": { \"codepoints\": [120007], \"characters\": \"\\uD835\\uDCC7\" },\n  \"&Rscr;\": { \"codepoints\": [8475], \"characters\": \"\\u211B\" },\n  \"&rsh;\": { \"codepoints\": [8625], \"characters\": \"\\u21B1\" },\n  \"&Rsh;\": { \"codepoints\": [8625], \"characters\": \"\\u21B1\" },\n  \"&rsqb;\": { \"codepoints\": [93], \"characters\": \"\\u005D\" },\n  \"&rsquo;\": { \"codepoints\": [8217], \"characters\": \"\\u2019\" },\n  \"&rsquor;\": { \"codepoints\": [8217], \"characters\": \"\\u2019\" },\n  \"&rthree;\": { \"codepoints\": [8908], \"characters\": \"\\u22CC\" },\n  \"&rtimes;\": { \"codepoints\": [8906], \"characters\": \"\\u22CA\" },\n  \"&rtri;\": { \"codepoints\": [9657], \"characters\": \"\\u25B9\" },\n  \"&rtrie;\": { \"codepoints\": [8885], \"characters\": \"\\u22B5\" },\n  \"&rtrif;\": { \"codepoints\": [9656], \"characters\": \"\\u25B8\" },\n  \"&rtriltri;\": { \"codepoints\": [10702], \"characters\": \"\\u29CE\" },\n  \"&RuleDelayed;\": { \"codepoints\": [10740], \"characters\": \"\\u29F4\" },\n  \"&ruluhar;\": { \"codepoints\": [10600], \"characters\": \"\\u2968\" },\n  \"&rx;\": { \"codepoints\": [8478], \"characters\": \"\\u211E\" },\n  \"&Sacute;\": { \"codepoints\": [346], \"characters\": \"\\u015A\" },\n  \"&sacute;\": { \"codepoints\": [347], \"characters\": \"\\u015B\" },\n  \"&sbquo;\": { \"codepoints\": [8218], \"characters\": \"\\u201A\" },\n  \"&scap;\": { \"codepoints\": [10936], \"characters\": \"\\u2AB8\" },\n  \"&Scaron;\": { \"codepoints\": [352], \"characters\": \"\\u0160\" },\n  \"&scaron;\": { \"codepoints\": [353], \"characters\": \"\\u0161\" },\n  \"&Sc;\": { \"codepoints\": [10940], \"characters\": \"\\u2ABC\" },\n  \"&sc;\": { \"codepoints\": [8827], \"characters\": \"\\u227B\" },\n  \"&sccue;\": { \"codepoints\": [8829], \"characters\": \"\\u227D\" },\n  \"&sce;\": { \"codepoints\": [10928], \"characters\": \"\\u2AB0\" },\n  \"&scE;\": { \"codepoints\": [10932], \"characters\": \"\\u2AB4\" },\n  \"&Scedil;\": { \"codepoints\": [350], \"characters\": \"\\u015E\" },\n  \"&scedil;\": { \"codepoints\": [351], \"characters\": \"\\u015F\" },\n  \"&Scirc;\": { \"codepoints\": [348], \"characters\": \"\\u015C\" },\n  \"&scirc;\": { \"codepoints\": [349], \"characters\": \"\\u015D\" },\n  \"&scnap;\": { \"codepoints\": [10938], \"characters\": \"\\u2ABA\" },\n  \"&scnE;\": { \"codepoints\": [10934], \"characters\": \"\\u2AB6\" },\n  \"&scnsim;\": { \"codepoints\": [8937], \"characters\": \"\\u22E9\" },\n  \"&scpolint;\": { \"codepoints\": [10771], \"characters\": \"\\u2A13\" },\n  \"&scsim;\": { \"codepoints\": [8831], \"characters\": \"\\u227F\" },\n  \"&Scy;\": { \"codepoints\": [1057], \"characters\": \"\\u0421\" },\n  \"&scy;\": { \"codepoints\": [1089], \"characters\": \"\\u0441\" },\n  \"&sdotb;\": { \"codepoints\": [8865], \"characters\": \"\\u22A1\" },\n  \"&sdot;\": { \"codepoints\": [8901], \"characters\": \"\\u22C5\" },\n  \"&sdote;\": { \"codepoints\": [10854], \"characters\": \"\\u2A66\" },\n  \"&searhk;\": { \"codepoints\": [10533], \"characters\": \"\\u2925\" },\n  \"&searr;\": { \"codepoints\": [8600], \"characters\": \"\\u2198\" },\n  \"&seArr;\": { \"codepoints\": [8664], \"characters\": \"\\u21D8\" },\n  \"&searrow;\": { \"codepoints\": [8600], \"characters\": \"\\u2198\" },\n  \"&sect;\": { \"codepoints\": [167], \"characters\": \"\\u00A7\" },\n  \"&sect\": { \"codepoints\": [167], \"characters\": \"\\u00A7\" },\n  \"&semi;\": { \"codepoints\": [59], \"characters\": \"\\u003B\" },\n  \"&seswar;\": { \"codepoints\": [10537], \"characters\": \"\\u2929\" },\n  \"&setminus;\": { \"codepoints\": [8726], \"characters\": \"\\u2216\" },\n  \"&setmn;\": { \"codepoints\": [8726], \"characters\": \"\\u2216\" },\n  \"&sext;\": { \"codepoints\": [10038], \"characters\": \"\\u2736\" },\n  \"&Sfr;\": { \"codepoints\": [120086], \"characters\": \"\\uD835\\uDD16\" },\n  \"&sfr;\": { \"codepoints\": [120112], \"characters\": \"\\uD835\\uDD30\" },\n  \"&sfrown;\": { \"codepoints\": [8994], \"characters\": \"\\u2322\" },\n  \"&sharp;\": { \"codepoints\": [9839], \"characters\": \"\\u266F\" },\n  \"&SHCHcy;\": { \"codepoints\": [1065], \"characters\": \"\\u0429\" },\n  \"&shchcy;\": { \"codepoints\": [1097], \"characters\": \"\\u0449\" },\n  \"&SHcy;\": { \"codepoints\": [1064], \"characters\": \"\\u0428\" },\n  \"&shcy;\": { \"codepoints\": [1096], \"characters\": \"\\u0448\" },\n  \"&ShortDownArrow;\": { \"codepoints\": [8595], \"characters\": \"\\u2193\" },\n  \"&ShortLeftArrow;\": { \"codepoints\": [8592], \"characters\": \"\\u2190\" },\n  \"&shortmid;\": { \"codepoints\": [8739], \"characters\": \"\\u2223\" },\n  \"&shortparallel;\": { \"codepoints\": [8741], \"characters\": \"\\u2225\" },\n  \"&ShortRightArrow;\": { \"codepoints\": [8594], \"characters\": \"\\u2192\" },\n  \"&ShortUpArrow;\": { \"codepoints\": [8593], \"characters\": \"\\u2191\" },\n  \"&shy;\": { \"codepoints\": [173], \"characters\": \"\\u00AD\" },\n  \"&shy\": { \"codepoints\": [173], \"characters\": \"\\u00AD\" },\n  \"&Sigma;\": { \"codepoints\": [931], \"characters\": \"\\u03A3\" },\n  \"&sigma;\": { \"codepoints\": [963], \"characters\": \"\\u03C3\" },\n  \"&sigmaf;\": { \"codepoints\": [962], \"characters\": \"\\u03C2\" },\n  \"&sigmav;\": { \"codepoints\": [962], \"characters\": \"\\u03C2\" },\n  \"&sim;\": { \"codepoints\": [8764], \"characters\": \"\\u223C\" },\n  \"&simdot;\": { \"codepoints\": [10858], \"characters\": \"\\u2A6A\" },\n  \"&sime;\": { \"codepoints\": [8771], \"characters\": \"\\u2243\" },\n  \"&simeq;\": { \"codepoints\": [8771], \"characters\": \"\\u2243\" },\n  \"&simg;\": { \"codepoints\": [10910], \"characters\": \"\\u2A9E\" },\n  \"&simgE;\": { \"codepoints\": [10912], \"characters\": \"\\u2AA0\" },\n  \"&siml;\": { \"codepoints\": [10909], \"characters\": \"\\u2A9D\" },\n  \"&simlE;\": { \"codepoints\": [10911], \"characters\": \"\\u2A9F\" },\n  \"&simne;\": { \"codepoints\": [8774], \"characters\": \"\\u2246\" },\n  \"&simplus;\": { \"codepoints\": [10788], \"characters\": \"\\u2A24\" },\n  \"&simrarr;\": { \"codepoints\": [10610], \"characters\": \"\\u2972\" },\n  \"&slarr;\": { \"codepoints\": [8592], \"characters\": \"\\u2190\" },\n  \"&SmallCircle;\": { \"codepoints\": [8728], \"characters\": \"\\u2218\" },\n  \"&smallsetminus;\": { \"codepoints\": [8726], \"characters\": \"\\u2216\" },\n  \"&smashp;\": { \"codepoints\": [10803], \"characters\": \"\\u2A33\" },\n  \"&smeparsl;\": { \"codepoints\": [10724], \"characters\": \"\\u29E4\" },\n  \"&smid;\": { \"codepoints\": [8739], \"characters\": \"\\u2223\" },\n  \"&smile;\": { \"codepoints\": [8995], \"characters\": \"\\u2323\" },\n  \"&smt;\": { \"codepoints\": [10922], \"characters\": \"\\u2AAA\" },\n  \"&smte;\": { \"codepoints\": [10924], \"characters\": \"\\u2AAC\" },\n  \"&smtes;\": { \"codepoints\": [10924, 65024], \"characters\": \"\\u2AAC\\uFE00\" },\n  \"&SOFTcy;\": { \"codepoints\": [1068], \"characters\": \"\\u042C\" },\n  \"&softcy;\": { \"codepoints\": [1100], \"characters\": \"\\u044C\" },\n  \"&solbar;\": { \"codepoints\": [9023], \"characters\": \"\\u233F\" },\n  \"&solb;\": { \"codepoints\": [10692], \"characters\": \"\\u29C4\" },\n  \"&sol;\": { \"codepoints\": [47], \"characters\": \"\\u002F\" },\n  \"&Sopf;\": { \"codepoints\": [120138], \"characters\": \"\\uD835\\uDD4A\" },\n  \"&sopf;\": { \"codepoints\": [120164], \"characters\": \"\\uD835\\uDD64\" },\n  \"&spades;\": { \"codepoints\": [9824], \"characters\": \"\\u2660\" },\n  \"&spadesuit;\": { \"codepoints\": [9824], \"characters\": \"\\u2660\" },\n  \"&spar;\": { \"codepoints\": [8741], \"characters\": \"\\u2225\" },\n  \"&sqcap;\": { \"codepoints\": [8851], \"characters\": \"\\u2293\" },\n  \"&sqcaps;\": { \"codepoints\": [8851, 65024], \"characters\": \"\\u2293\\uFE00\" },\n  \"&sqcup;\": { \"codepoints\": [8852], \"characters\": \"\\u2294\" },\n  \"&sqcups;\": { \"codepoints\": [8852, 65024], \"characters\": \"\\u2294\\uFE00\" },\n  \"&Sqrt;\": { \"codepoints\": [8730], \"characters\": \"\\u221A\" },\n  \"&sqsub;\": { \"codepoints\": [8847], \"characters\": \"\\u228F\" },\n  \"&sqsube;\": { \"codepoints\": [8849], \"characters\": \"\\u2291\" },\n  \"&sqsubset;\": { \"codepoints\": [8847], \"characters\": \"\\u228F\" },\n  \"&sqsubseteq;\": { \"codepoints\": [8849], \"characters\": \"\\u2291\" },\n  \"&sqsup;\": { \"codepoints\": [8848], \"characters\": \"\\u2290\" },\n  \"&sqsupe;\": { \"codepoints\": [8850], \"characters\": \"\\u2292\" },\n  \"&sqsupset;\": { \"codepoints\": [8848], \"characters\": \"\\u2290\" },\n  \"&sqsupseteq;\": { \"codepoints\": [8850], \"characters\": \"\\u2292\" },\n  \"&square;\": { \"codepoints\": [9633], \"characters\": \"\\u25A1\" },\n  \"&Square;\": { \"codepoints\": [9633], \"characters\": \"\\u25A1\" },\n  \"&SquareIntersection;\": { \"codepoints\": [8851], \"characters\": \"\\u2293\" },\n  \"&SquareSubset;\": { \"codepoints\": [8847], \"characters\": \"\\u228F\" },\n  \"&SquareSubsetEqual;\": { \"codepoints\": [8849], \"characters\": \"\\u2291\" },\n  \"&SquareSuperset;\": { \"codepoints\": [8848], \"characters\": \"\\u2290\" },\n  \"&SquareSupersetEqual;\": { \"codepoints\": [8850], \"characters\": \"\\u2292\" },\n  \"&SquareUnion;\": { \"codepoints\": [8852], \"characters\": \"\\u2294\" },\n  \"&squarf;\": { \"codepoints\": [9642], \"characters\": \"\\u25AA\" },\n  \"&squ;\": { \"codepoints\": [9633], \"characters\": \"\\u25A1\" },\n  \"&squf;\": { \"codepoints\": [9642], \"characters\": \"\\u25AA\" },\n  \"&srarr;\": { \"codepoints\": [8594], \"characters\": \"\\u2192\" },\n  \"&Sscr;\": { \"codepoints\": [119982], \"characters\": \"\\uD835\\uDCAE\" },\n  \"&sscr;\": { \"codepoints\": [120008], \"characters\": \"\\uD835\\uDCC8\" },\n  \"&ssetmn;\": { \"codepoints\": [8726], \"characters\": \"\\u2216\" },\n  \"&ssmile;\": { \"codepoints\": [8995], \"characters\": \"\\u2323\" },\n  \"&sstarf;\": { \"codepoints\": [8902], \"characters\": \"\\u22C6\" },\n  \"&Star;\": { \"codepoints\": [8902], \"characters\": \"\\u22C6\" },\n  \"&star;\": { \"codepoints\": [9734], \"characters\": \"\\u2606\" },\n  \"&starf;\": { \"codepoints\": [9733], \"characters\": \"\\u2605\" },\n  \"&straightepsilon;\": { \"codepoints\": [1013], \"characters\": \"\\u03F5\" },\n  \"&straightphi;\": { \"codepoints\": [981], \"characters\": \"\\u03D5\" },\n  \"&strns;\": { \"codepoints\": [175], \"characters\": \"\\u00AF\" },\n  \"&sub;\": { \"codepoints\": [8834], \"characters\": \"\\u2282\" },\n  \"&Sub;\": { \"codepoints\": [8912], \"characters\": \"\\u22D0\" },\n  \"&subdot;\": { \"codepoints\": [10941], \"characters\": \"\\u2ABD\" },\n  \"&subE;\": { \"codepoints\": [10949], \"characters\": \"\\u2AC5\" },\n  \"&sube;\": { \"codepoints\": [8838], \"characters\": \"\\u2286\" },\n  \"&subedot;\": { \"codepoints\": [10947], \"characters\": \"\\u2AC3\" },\n  \"&submult;\": { \"codepoints\": [10945], \"characters\": \"\\u2AC1\" },\n  \"&subnE;\": { \"codepoints\": [10955], \"characters\": \"\\u2ACB\" },\n  \"&subne;\": { \"codepoints\": [8842], \"characters\": \"\\u228A\" },\n  \"&subplus;\": { \"codepoints\": [10943], \"characters\": \"\\u2ABF\" },\n  \"&subrarr;\": { \"codepoints\": [10617], \"characters\": \"\\u2979\" },\n  \"&subset;\": { \"codepoints\": [8834], \"characters\": \"\\u2282\" },\n  \"&Subset;\": { \"codepoints\": [8912], \"characters\": \"\\u22D0\" },\n  \"&subseteq;\": { \"codepoints\": [8838], \"characters\": \"\\u2286\" },\n  \"&subseteqq;\": { \"codepoints\": [10949], \"characters\": \"\\u2AC5\" },\n  \"&SubsetEqual;\": { \"codepoints\": [8838], \"characters\": \"\\u2286\" },\n  \"&subsetneq;\": { \"codepoints\": [8842], \"characters\": \"\\u228A\" },\n  \"&subsetneqq;\": { \"codepoints\": [10955], \"characters\": \"\\u2ACB\" },\n  \"&subsim;\": { \"codepoints\": [10951], \"characters\": \"\\u2AC7\" },\n  \"&subsub;\": { \"codepoints\": [10965], \"characters\": \"\\u2AD5\" },\n  \"&subsup;\": { \"codepoints\": [10963], \"characters\": \"\\u2AD3\" },\n  \"&succapprox;\": { \"codepoints\": [10936], \"characters\": \"\\u2AB8\" },\n  \"&succ;\": { \"codepoints\": [8827], \"characters\": \"\\u227B\" },\n  \"&succcurlyeq;\": { \"codepoints\": [8829], \"characters\": \"\\u227D\" },\n  \"&Succeeds;\": { \"codepoints\": [8827], \"characters\": \"\\u227B\" },\n  \"&SucceedsEqual;\": { \"codepoints\": [10928], \"characters\": \"\\u2AB0\" },\n  \"&SucceedsSlantEqual;\": { \"codepoints\": [8829], \"characters\": \"\\u227D\" },\n  \"&SucceedsTilde;\": { \"codepoints\": [8831], \"characters\": \"\\u227F\" },\n  \"&succeq;\": { \"codepoints\": [10928], \"characters\": \"\\u2AB0\" },\n  \"&succnapprox;\": { \"codepoints\": [10938], \"characters\": \"\\u2ABA\" },\n  \"&succneqq;\": { \"codepoints\": [10934], \"characters\": \"\\u2AB6\" },\n  \"&succnsim;\": { \"codepoints\": [8937], \"characters\": \"\\u22E9\" },\n  \"&succsim;\": { \"codepoints\": [8831], \"characters\": \"\\u227F\" },\n  \"&SuchThat;\": { \"codepoints\": [8715], \"characters\": \"\\u220B\" },\n  \"&sum;\": { \"codepoints\": [8721], \"characters\": \"\\u2211\" },\n  \"&Sum;\": { \"codepoints\": [8721], \"characters\": \"\\u2211\" },\n  \"&sung;\": { \"codepoints\": [9834], \"characters\": \"\\u266A\" },\n  \"&sup1;\": { \"codepoints\": [185], \"characters\": \"\\u00B9\" },\n  \"&sup1\": { \"codepoints\": [185], \"characters\": \"\\u00B9\" },\n  \"&sup2;\": { \"codepoints\": [178], \"characters\": \"\\u00B2\" },\n  \"&sup2\": { \"codepoints\": [178], \"characters\": \"\\u00B2\" },\n  \"&sup3;\": { \"codepoints\": [179], \"characters\": \"\\u00B3\" },\n  \"&sup3\": { \"codepoints\": [179], \"characters\": \"\\u00B3\" },\n  \"&sup;\": { \"codepoints\": [8835], \"characters\": \"\\u2283\" },\n  \"&Sup;\": { \"codepoints\": [8913], \"characters\": \"\\u22D1\" },\n  \"&supdot;\": { \"codepoints\": [10942], \"characters\": \"\\u2ABE\" },\n  \"&supdsub;\": { \"codepoints\": [10968], \"characters\": \"\\u2AD8\" },\n  \"&supE;\": { \"codepoints\": [10950], \"characters\": \"\\u2AC6\" },\n  \"&supe;\": { \"codepoints\": [8839], \"characters\": \"\\u2287\" },\n  \"&supedot;\": { \"codepoints\": [10948], \"characters\": \"\\u2AC4\" },\n  \"&Superset;\": { \"codepoints\": [8835], \"characters\": \"\\u2283\" },\n  \"&SupersetEqual;\": { \"codepoints\": [8839], \"characters\": \"\\u2287\" },\n  \"&suphsol;\": { \"codepoints\": [10185], \"characters\": \"\\u27C9\" },\n  \"&suphsub;\": { \"codepoints\": [10967], \"characters\": \"\\u2AD7\" },\n  \"&suplarr;\": { \"codepoints\": [10619], \"characters\": \"\\u297B\" },\n  \"&supmult;\": { \"codepoints\": [10946], \"characters\": \"\\u2AC2\" },\n  \"&supnE;\": { \"codepoints\": [10956], \"characters\": \"\\u2ACC\" },\n  \"&supne;\": { \"codepoints\": [8843], \"characters\": \"\\u228B\" },\n  \"&supplus;\": { \"codepoints\": [10944], \"characters\": \"\\u2AC0\" },\n  \"&supset;\": { \"codepoints\": [8835], \"characters\": \"\\u2283\" },\n  \"&Supset;\": { \"codepoints\": [8913], \"characters\": \"\\u22D1\" },\n  \"&supseteq;\": { \"codepoints\": [8839], \"characters\": \"\\u2287\" },\n  \"&supseteqq;\": { \"codepoints\": [10950], \"characters\": \"\\u2AC6\" },\n  \"&supsetneq;\": { \"codepoints\": [8843], \"characters\": \"\\u228B\" },\n  \"&supsetneqq;\": { \"codepoints\": [10956], \"characters\": \"\\u2ACC\" },\n  \"&supsim;\": { \"codepoints\": [10952], \"characters\": \"\\u2AC8\" },\n  \"&supsub;\": { \"codepoints\": [10964], \"characters\": \"\\u2AD4\" },\n  \"&supsup;\": { \"codepoints\": [10966], \"characters\": \"\\u2AD6\" },\n  \"&swarhk;\": { \"codepoints\": [10534], \"characters\": \"\\u2926\" },\n  \"&swarr;\": { \"codepoints\": [8601], \"characters\": \"\\u2199\" },\n  \"&swArr;\": { \"codepoints\": [8665], \"characters\": \"\\u21D9\" },\n  \"&swarrow;\": { \"codepoints\": [8601], \"characters\": \"\\u2199\" },\n  \"&swnwar;\": { \"codepoints\": [10538], \"characters\": \"\\u292A\" },\n  \"&szlig;\": { \"codepoints\": [223], \"characters\": \"\\u00DF\" },\n  \"&szlig\": { \"codepoints\": [223], \"characters\": \"\\u00DF\" },\n  \"&Tab;\": { \"codepoints\": [9], \"characters\": \"\\u0009\" },\n  \"&target;\": { \"codepoints\": [8982], \"characters\": \"\\u2316\" },\n  \"&Tau;\": { \"codepoints\": [932], \"characters\": \"\\u03A4\" },\n  \"&tau;\": { \"codepoints\": [964], \"characters\": \"\\u03C4\" },\n  \"&tbrk;\": { \"codepoints\": [9140], \"characters\": \"\\u23B4\" },\n  \"&Tcaron;\": { \"codepoints\": [356], \"characters\": \"\\u0164\" },\n  \"&tcaron;\": { \"codepoints\": [357], \"characters\": \"\\u0165\" },\n  \"&Tcedil;\": { \"codepoints\": [354], \"characters\": \"\\u0162\" },\n  \"&tcedil;\": { \"codepoints\": [355], \"characters\": \"\\u0163\" },\n  \"&Tcy;\": { \"codepoints\": [1058], \"characters\": \"\\u0422\" },\n  \"&tcy;\": { \"codepoints\": [1090], \"characters\": \"\\u0442\" },\n  \"&tdot;\": { \"codepoints\": [8411], \"characters\": \"\\u20DB\" },\n  \"&telrec;\": { \"codepoints\": [8981], \"characters\": \"\\u2315\" },\n  \"&Tfr;\": { \"codepoints\": [120087], \"characters\": \"\\uD835\\uDD17\" },\n  \"&tfr;\": { \"codepoints\": [120113], \"characters\": \"\\uD835\\uDD31\" },\n  \"&there4;\": { \"codepoints\": [8756], \"characters\": \"\\u2234\" },\n  \"&therefore;\": { \"codepoints\": [8756], \"characters\": \"\\u2234\" },\n  \"&Therefore;\": { \"codepoints\": [8756], \"characters\": \"\\u2234\" },\n  \"&Theta;\": { \"codepoints\": [920], \"characters\": \"\\u0398\" },\n  \"&theta;\": { \"codepoints\": [952], \"characters\": \"\\u03B8\" },\n  \"&thetasym;\": { \"codepoints\": [977], \"characters\": \"\\u03D1\" },\n  \"&thetav;\": { \"codepoints\": [977], \"characters\": \"\\u03D1\" },\n  \"&thickapprox;\": { \"codepoints\": [8776], \"characters\": \"\\u2248\" },\n  \"&thicksim;\": { \"codepoints\": [8764], \"characters\": \"\\u223C\" },\n  \"&ThickSpace;\": { \"codepoints\": [8287, 8202], \"characters\": \"\\u205F\\u200A\" },\n  \"&ThinSpace;\": { \"codepoints\": [8201], \"characters\": \"\\u2009\" },\n  \"&thinsp;\": { \"codepoints\": [8201], \"characters\": \"\\u2009\" },\n  \"&thkap;\": { \"codepoints\": [8776], \"characters\": \"\\u2248\" },\n  \"&thksim;\": { \"codepoints\": [8764], \"characters\": \"\\u223C\" },\n  \"&THORN;\": { \"codepoints\": [222], \"characters\": \"\\u00DE\" },\n  \"&THORN\": { \"codepoints\": [222], \"characters\": \"\\u00DE\" },\n  \"&thorn;\": { \"codepoints\": [254], \"characters\": \"\\u00FE\" },\n  \"&thorn\": { \"codepoints\": [254], \"characters\": \"\\u00FE\" },\n  \"&tilde;\": { \"codepoints\": [732], \"characters\": \"\\u02DC\" },\n  \"&Tilde;\": { \"codepoints\": [8764], \"characters\": \"\\u223C\" },\n  \"&TildeEqual;\": { \"codepoints\": [8771], \"characters\": \"\\u2243\" },\n  \"&TildeFullEqual;\": { \"codepoints\": [8773], \"characters\": \"\\u2245\" },\n  \"&TildeTilde;\": { \"codepoints\": [8776], \"characters\": \"\\u2248\" },\n  \"&timesbar;\": { \"codepoints\": [10801], \"characters\": \"\\u2A31\" },\n  \"&timesb;\": { \"codepoints\": [8864], \"characters\": \"\\u22A0\" },\n  \"&times;\": { \"codepoints\": [215], \"characters\": \"\\u00D7\" },\n  \"&times\": { \"codepoints\": [215], \"characters\": \"\\u00D7\" },\n  \"&timesd;\": { \"codepoints\": [10800], \"characters\": \"\\u2A30\" },\n  \"&tint;\": { \"codepoints\": [8749], \"characters\": \"\\u222D\" },\n  \"&toea;\": { \"codepoints\": [10536], \"characters\": \"\\u2928\" },\n  \"&topbot;\": { \"codepoints\": [9014], \"characters\": \"\\u2336\" },\n  \"&topcir;\": { \"codepoints\": [10993], \"characters\": \"\\u2AF1\" },\n  \"&top;\": { \"codepoints\": [8868], \"characters\": \"\\u22A4\" },\n  \"&Topf;\": { \"codepoints\": [120139], \"characters\": \"\\uD835\\uDD4B\" },\n  \"&topf;\": { \"codepoints\": [120165], \"characters\": \"\\uD835\\uDD65\" },\n  \"&topfork;\": { \"codepoints\": [10970], \"characters\": \"\\u2ADA\" },\n  \"&tosa;\": { \"codepoints\": [10537], \"characters\": \"\\u2929\" },\n  \"&tprime;\": { \"codepoints\": [8244], \"characters\": \"\\u2034\" },\n  \"&trade;\": { \"codepoints\": [8482], \"characters\": \"\\u2122\" },\n  \"&TRADE;\": { \"codepoints\": [8482], \"characters\": \"\\u2122\" },\n  \"&triangle;\": { \"codepoints\": [9653], \"characters\": \"\\u25B5\" },\n  \"&triangledown;\": { \"codepoints\": [9663], \"characters\": \"\\u25BF\" },\n  \"&triangleleft;\": { \"codepoints\": [9667], \"characters\": \"\\u25C3\" },\n  \"&trianglelefteq;\": { \"codepoints\": [8884], \"characters\": \"\\u22B4\" },\n  \"&triangleq;\": { \"codepoints\": [8796], \"characters\": \"\\u225C\" },\n  \"&triangleright;\": { \"codepoints\": [9657], \"characters\": \"\\u25B9\" },\n  \"&trianglerighteq;\": { \"codepoints\": [8885], \"characters\": \"\\u22B5\" },\n  \"&tridot;\": { \"codepoints\": [9708], \"characters\": \"\\u25EC\" },\n  \"&trie;\": { \"codepoints\": [8796], \"characters\": \"\\u225C\" },\n  \"&triminus;\": { \"codepoints\": [10810], \"characters\": \"\\u2A3A\" },\n  \"&TripleDot;\": { \"codepoints\": [8411], \"characters\": \"\\u20DB\" },\n  \"&triplus;\": { \"codepoints\": [10809], \"characters\": \"\\u2A39\" },\n  \"&trisb;\": { \"codepoints\": [10701], \"characters\": \"\\u29CD\" },\n  \"&tritime;\": { \"codepoints\": [10811], \"characters\": \"\\u2A3B\" },\n  \"&trpezium;\": { \"codepoints\": [9186], \"characters\": \"\\u23E2\" },\n  \"&Tscr;\": { \"codepoints\": [119983], \"characters\": \"\\uD835\\uDCAF\" },\n  \"&tscr;\": { \"codepoints\": [120009], \"characters\": \"\\uD835\\uDCC9\" },\n  \"&TScy;\": { \"codepoints\": [1062], \"characters\": \"\\u0426\" },\n  \"&tscy;\": { \"codepoints\": [1094], \"characters\": \"\\u0446\" },\n  \"&TSHcy;\": { \"codepoints\": [1035], \"characters\": \"\\u040B\" },\n  \"&tshcy;\": { \"codepoints\": [1115], \"characters\": \"\\u045B\" },\n  \"&Tstrok;\": { \"codepoints\": [358], \"characters\": \"\\u0166\" },\n  \"&tstrok;\": { \"codepoints\": [359], \"characters\": \"\\u0167\" },\n  \"&twixt;\": { \"codepoints\": [8812], \"characters\": \"\\u226C\" },\n  \"&twoheadleftarrow;\": { \"codepoints\": [8606], \"characters\": \"\\u219E\" },\n  \"&twoheadrightarrow;\": { \"codepoints\": [8608], \"characters\": \"\\u21A0\" },\n  \"&Uacute;\": { \"codepoints\": [218], \"characters\": \"\\u00DA\" },\n  \"&Uacute\": { \"codepoints\": [218], \"characters\": \"\\u00DA\" },\n  \"&uacute;\": { \"codepoints\": [250], \"characters\": \"\\u00FA\" },\n  \"&uacute\": { \"codepoints\": [250], \"characters\": \"\\u00FA\" },\n  \"&uarr;\": { \"codepoints\": [8593], \"characters\": \"\\u2191\" },\n  \"&Uarr;\": { \"codepoints\": [8607], \"characters\": \"\\u219F\" },\n  \"&uArr;\": { \"codepoints\": [8657], \"characters\": \"\\u21D1\" },\n  \"&Uarrocir;\": { \"codepoints\": [10569], \"characters\": \"\\u2949\" },\n  \"&Ubrcy;\": { \"codepoints\": [1038], \"characters\": \"\\u040E\" },\n  \"&ubrcy;\": { \"codepoints\": [1118], \"characters\": \"\\u045E\" },\n  \"&Ubreve;\": { \"codepoints\": [364], \"characters\": \"\\u016C\" },\n  \"&ubreve;\": { \"codepoints\": [365], \"characters\": \"\\u016D\" },\n  \"&Ucirc;\": { \"codepoints\": [219], \"characters\": \"\\u00DB\" },\n  \"&Ucirc\": { \"codepoints\": [219], \"characters\": \"\\u00DB\" },\n  \"&ucirc;\": { \"codepoints\": [251], \"characters\": \"\\u00FB\" },\n  \"&ucirc\": { \"codepoints\": [251], \"characters\": \"\\u00FB\" },\n  \"&Ucy;\": { \"codepoints\": [1059], \"characters\": \"\\u0423\" },\n  \"&ucy;\": { \"codepoints\": [1091], \"characters\": \"\\u0443\" },\n  \"&udarr;\": { \"codepoints\": [8645], \"characters\": \"\\u21C5\" },\n  \"&Udblac;\": { \"codepoints\": [368], \"characters\": \"\\u0170\" },\n  \"&udblac;\": { \"codepoints\": [369], \"characters\": \"\\u0171\" },\n  \"&udhar;\": { \"codepoints\": [10606], \"characters\": \"\\u296E\" },\n  \"&ufisht;\": { \"codepoints\": [10622], \"characters\": \"\\u297E\" },\n  \"&Ufr;\": { \"codepoints\": [120088], \"characters\": \"\\uD835\\uDD18\" },\n  \"&ufr;\": { \"codepoints\": [120114], \"characters\": \"\\uD835\\uDD32\" },\n  \"&Ugrave;\": { \"codepoints\": [217], \"characters\": \"\\u00D9\" },\n  \"&Ugrave\": { \"codepoints\": [217], \"characters\": \"\\u00D9\" },\n  \"&ugrave;\": { \"codepoints\": [249], \"characters\": \"\\u00F9\" },\n  \"&ugrave\": { \"codepoints\": [249], \"characters\": \"\\u00F9\" },\n  \"&uHar;\": { \"codepoints\": [10595], \"characters\": \"\\u2963\" },\n  \"&uharl;\": { \"codepoints\": [8639], \"characters\": \"\\u21BF\" },\n  \"&uharr;\": { \"codepoints\": [8638], \"characters\": \"\\u21BE\" },\n  \"&uhblk;\": { \"codepoints\": [9600], \"characters\": \"\\u2580\" },\n  \"&ulcorn;\": { \"codepoints\": [8988], \"characters\": \"\\u231C\" },\n  \"&ulcorner;\": { \"codepoints\": [8988], \"characters\": \"\\u231C\" },\n  \"&ulcrop;\": { \"codepoints\": [8975], \"characters\": \"\\u230F\" },\n  \"&ultri;\": { \"codepoints\": [9720], \"characters\": \"\\u25F8\" },\n  \"&Umacr;\": { \"codepoints\": [362], \"characters\": \"\\u016A\" },\n  \"&umacr;\": { \"codepoints\": [363], \"characters\": \"\\u016B\" },\n  \"&uml;\": { \"codepoints\": [168], \"characters\": \"\\u00A8\" },\n  \"&uml\": { \"codepoints\": [168], \"characters\": \"\\u00A8\" },\n  \"&UnderBar;\": { \"codepoints\": [95], \"characters\": \"\\u005F\" },\n  \"&UnderBrace;\": { \"codepoints\": [9183], \"characters\": \"\\u23DF\" },\n  \"&UnderBracket;\": { \"codepoints\": [9141], \"characters\": \"\\u23B5\" },\n  \"&UnderParenthesis;\": { \"codepoints\": [9181], \"characters\": \"\\u23DD\" },\n  \"&Union;\": { \"codepoints\": [8899], \"characters\": \"\\u22C3\" },\n  \"&UnionPlus;\": { \"codepoints\": [8846], \"characters\": \"\\u228E\" },\n  \"&Uogon;\": { \"codepoints\": [370], \"characters\": \"\\u0172\" },\n  \"&uogon;\": { \"codepoints\": [371], \"characters\": \"\\u0173\" },\n  \"&Uopf;\": { \"codepoints\": [120140], \"characters\": \"\\uD835\\uDD4C\" },\n  \"&uopf;\": { \"codepoints\": [120166], \"characters\": \"\\uD835\\uDD66\" },\n  \"&UpArrowBar;\": { \"codepoints\": [10514], \"characters\": \"\\u2912\" },\n  \"&uparrow;\": { \"codepoints\": [8593], \"characters\": \"\\u2191\" },\n  \"&UpArrow;\": { \"codepoints\": [8593], \"characters\": \"\\u2191\" },\n  \"&Uparrow;\": { \"codepoints\": [8657], \"characters\": \"\\u21D1\" },\n  \"&UpArrowDownArrow;\": { \"codepoints\": [8645], \"characters\": \"\\u21C5\" },\n  \"&updownarrow;\": { \"codepoints\": [8597], \"characters\": \"\\u2195\" },\n  \"&UpDownArrow;\": { \"codepoints\": [8597], \"characters\": \"\\u2195\" },\n  \"&Updownarrow;\": { \"codepoints\": [8661], \"characters\": \"\\u21D5\" },\n  \"&UpEquilibrium;\": { \"codepoints\": [10606], \"characters\": \"\\u296E\" },\n  \"&upharpoonleft;\": { \"codepoints\": [8639], \"characters\": \"\\u21BF\" },\n  \"&upharpoonright;\": { \"codepoints\": [8638], \"characters\": \"\\u21BE\" },\n  \"&uplus;\": { \"codepoints\": [8846], \"characters\": \"\\u228E\" },\n  \"&UpperLeftArrow;\": { \"codepoints\": [8598], \"characters\": \"\\u2196\" },\n  \"&UpperRightArrow;\": { \"codepoints\": [8599], \"characters\": \"\\u2197\" },\n  \"&upsi;\": { \"codepoints\": [965], \"characters\": \"\\u03C5\" },\n  \"&Upsi;\": { \"codepoints\": [978], \"characters\": \"\\u03D2\" },\n  \"&upsih;\": { \"codepoints\": [978], \"characters\": \"\\u03D2\" },\n  \"&Upsilon;\": { \"codepoints\": [933], \"characters\": \"\\u03A5\" },\n  \"&upsilon;\": { \"codepoints\": [965], \"characters\": \"\\u03C5\" },\n  \"&UpTeeArrow;\": { \"codepoints\": [8613], \"characters\": \"\\u21A5\" },\n  \"&UpTee;\": { \"codepoints\": [8869], \"characters\": \"\\u22A5\" },\n  \"&upuparrows;\": { \"codepoints\": [8648], \"characters\": \"\\u21C8\" },\n  \"&urcorn;\": { \"codepoints\": [8989], \"characters\": \"\\u231D\" },\n  \"&urcorner;\": { \"codepoints\": [8989], \"characters\": \"\\u231D\" },\n  \"&urcrop;\": { \"codepoints\": [8974], \"characters\": \"\\u230E\" },\n  \"&Uring;\": { \"codepoints\": [366], \"characters\": \"\\u016E\" },\n  \"&uring;\": { \"codepoints\": [367], \"characters\": \"\\u016F\" },\n  \"&urtri;\": { \"codepoints\": [9721], \"characters\": \"\\u25F9\" },\n  \"&Uscr;\": { \"codepoints\": [119984], \"characters\": \"\\uD835\\uDCB0\" },\n  \"&uscr;\": { \"codepoints\": [120010], \"characters\": \"\\uD835\\uDCCA\" },\n  \"&utdot;\": { \"codepoints\": [8944], \"characters\": \"\\u22F0\" },\n  \"&Utilde;\": { \"codepoints\": [360], \"characters\": \"\\u0168\" },\n  \"&utilde;\": { \"codepoints\": [361], \"characters\": \"\\u0169\" },\n  \"&utri;\": { \"codepoints\": [9653], \"characters\": \"\\u25B5\" },\n  \"&utrif;\": { \"codepoints\": [9652], \"characters\": \"\\u25B4\" },\n  \"&uuarr;\": { \"codepoints\": [8648], \"characters\": \"\\u21C8\" },\n  \"&Uuml;\": { \"codepoints\": [220], \"characters\": \"\\u00DC\" },\n  \"&Uuml\": { \"codepoints\": [220], \"characters\": \"\\u00DC\" },\n  \"&uuml;\": { \"codepoints\": [252], \"characters\": \"\\u00FC\" },\n  \"&uuml\": { \"codepoints\": [252], \"characters\": \"\\u00FC\" },\n  \"&uwangle;\": { \"codepoints\": [10663], \"characters\": \"\\u29A7\" },\n  \"&vangrt;\": { \"codepoints\": [10652], \"characters\": \"\\u299C\" },\n  \"&varepsilon;\": { \"codepoints\": [1013], \"characters\": \"\\u03F5\" },\n  \"&varkappa;\": { \"codepoints\": [1008], \"characters\": \"\\u03F0\" },\n  \"&varnothing;\": { \"codepoints\": [8709], \"characters\": \"\\u2205\" },\n  \"&varphi;\": { \"codepoints\": [981], \"characters\": \"\\u03D5\" },\n  \"&varpi;\": { \"codepoints\": [982], \"characters\": \"\\u03D6\" },\n  \"&varpropto;\": { \"codepoints\": [8733], \"characters\": \"\\u221D\" },\n  \"&varr;\": { \"codepoints\": [8597], \"characters\": \"\\u2195\" },\n  \"&vArr;\": { \"codepoints\": [8661], \"characters\": \"\\u21D5\" },\n  \"&varrho;\": { \"codepoints\": [1009], \"characters\": \"\\u03F1\" },\n  \"&varsigma;\": { \"codepoints\": [962], \"characters\": \"\\u03C2\" },\n  \"&varsubsetneq;\": { \"codepoints\": [8842, 65024], \"characters\": \"\\u228A\\uFE00\" },\n  \"&varsubsetneqq;\": { \"codepoints\": [10955, 65024], \"characters\": \"\\u2ACB\\uFE00\" },\n  \"&varsupsetneq;\": { \"codepoints\": [8843, 65024], \"characters\": \"\\u228B\\uFE00\" },\n  \"&varsupsetneqq;\": { \"codepoints\": [10956, 65024], \"characters\": \"\\u2ACC\\uFE00\" },\n  \"&vartheta;\": { \"codepoints\": [977], \"characters\": \"\\u03D1\" },\n  \"&vartriangleleft;\": { \"codepoints\": [8882], \"characters\": \"\\u22B2\" },\n  \"&vartriangleright;\": { \"codepoints\": [8883], \"characters\": \"\\u22B3\" },\n  \"&vBar;\": { \"codepoints\": [10984], \"characters\": \"\\u2AE8\" },\n  \"&Vbar;\": { \"codepoints\": [10987], \"characters\": \"\\u2AEB\" },\n  \"&vBarv;\": { \"codepoints\": [10985], \"characters\": \"\\u2AE9\" },\n  \"&Vcy;\": { \"codepoints\": [1042], \"characters\": \"\\u0412\" },\n  \"&vcy;\": { \"codepoints\": [1074], \"characters\": \"\\u0432\" },\n  \"&vdash;\": { \"codepoints\": [8866], \"characters\": \"\\u22A2\" },\n  \"&vDash;\": { \"codepoints\": [8872], \"characters\": \"\\u22A8\" },\n  \"&Vdash;\": { \"codepoints\": [8873], \"characters\": \"\\u22A9\" },\n  \"&VDash;\": { \"codepoints\": [8875], \"characters\": \"\\u22AB\" },\n  \"&Vdashl;\": { \"codepoints\": [10982], \"characters\": \"\\u2AE6\" },\n  \"&veebar;\": { \"codepoints\": [8891], \"characters\": \"\\u22BB\" },\n  \"&vee;\": { \"codepoints\": [8744], \"characters\": \"\\u2228\" },\n  \"&Vee;\": { \"codepoints\": [8897], \"characters\": \"\\u22C1\" },\n  \"&veeeq;\": { \"codepoints\": [8794], \"characters\": \"\\u225A\" },\n  \"&vellip;\": { \"codepoints\": [8942], \"characters\": \"\\u22EE\" },\n  \"&verbar;\": { \"codepoints\": [124], \"characters\": \"\\u007C\" },\n  \"&Verbar;\": { \"codepoints\": [8214], \"characters\": \"\\u2016\" },\n  \"&vert;\": { \"codepoints\": [124], \"characters\": \"\\u007C\" },\n  \"&Vert;\": { \"codepoints\": [8214], \"characters\": \"\\u2016\" },\n  \"&VerticalBar;\": { \"codepoints\": [8739], \"characters\": \"\\u2223\" },\n  \"&VerticalLine;\": { \"codepoints\": [124], \"characters\": \"\\u007C\" },\n  \"&VerticalSeparator;\": { \"codepoints\": [10072], \"characters\": \"\\u2758\" },\n  \"&VerticalTilde;\": { \"codepoints\": [8768], \"characters\": \"\\u2240\" },\n  \"&VeryThinSpace;\": { \"codepoints\": [8202], \"characters\": \"\\u200A\" },\n  \"&Vfr;\": { \"codepoints\": [120089], \"characters\": \"\\uD835\\uDD19\" },\n  \"&vfr;\": { \"codepoints\": [120115], \"characters\": \"\\uD835\\uDD33\" },\n  \"&vltri;\": { \"codepoints\": [8882], \"characters\": \"\\u22B2\" },\n  \"&vnsub;\": { \"codepoints\": [8834, 8402], \"characters\": \"\\u2282\\u20D2\" },\n  \"&vnsup;\": { \"codepoints\": [8835, 8402], \"characters\": \"\\u2283\\u20D2\" },\n  \"&Vopf;\": { \"codepoints\": [120141], \"characters\": \"\\uD835\\uDD4D\" },\n  \"&vopf;\": { \"codepoints\": [120167], \"characters\": \"\\uD835\\uDD67\" },\n  \"&vprop;\": { \"codepoints\": [8733], \"characters\": \"\\u221D\" },\n  \"&vrtri;\": { \"codepoints\": [8883], \"characters\": \"\\u22B3\" },\n  \"&Vscr;\": { \"codepoints\": [119985], \"characters\": \"\\uD835\\uDCB1\" },\n  \"&vscr;\": { \"codepoints\": [120011], \"characters\": \"\\uD835\\uDCCB\" },\n  \"&vsubnE;\": { \"codepoints\": [10955, 65024], \"characters\": \"\\u2ACB\\uFE00\" },\n  \"&vsubne;\": { \"codepoints\": [8842, 65024], \"characters\": \"\\u228A\\uFE00\" },\n  \"&vsupnE;\": { \"codepoints\": [10956, 65024], \"characters\": \"\\u2ACC\\uFE00\" },\n  \"&vsupne;\": { \"codepoints\": [8843, 65024], \"characters\": \"\\u228B\\uFE00\" },\n  \"&Vvdash;\": { \"codepoints\": [8874], \"characters\": \"\\u22AA\" },\n  \"&vzigzag;\": { \"codepoints\": [10650], \"characters\": \"\\u299A\" },\n  \"&Wcirc;\": { \"codepoints\": [372], \"characters\": \"\\u0174\" },\n  \"&wcirc;\": { \"codepoints\": [373], \"characters\": \"\\u0175\" },\n  \"&wedbar;\": { \"codepoints\": [10847], \"characters\": \"\\u2A5F\" },\n  \"&wedge;\": { \"codepoints\": [8743], \"characters\": \"\\u2227\" },\n  \"&Wedge;\": { \"codepoints\": [8896], \"characters\": \"\\u22C0\" },\n  \"&wedgeq;\": { \"codepoints\": [8793], \"characters\": \"\\u2259\" },\n  \"&weierp;\": { \"codepoints\": [8472], \"characters\": \"\\u2118\" },\n  \"&Wfr;\": { \"codepoints\": [120090], \"characters\": \"\\uD835\\uDD1A\" },\n  \"&wfr;\": { \"codepoints\": [120116], \"characters\": \"\\uD835\\uDD34\" },\n  \"&Wopf;\": { \"codepoints\": [120142], \"characters\": \"\\uD835\\uDD4E\" },\n  \"&wopf;\": { \"codepoints\": [120168], \"characters\": \"\\uD835\\uDD68\" },\n  \"&wp;\": { \"codepoints\": [8472], \"characters\": \"\\u2118\" },\n  \"&wr;\": { \"codepoints\": [8768], \"characters\": \"\\u2240\" },\n  \"&wreath;\": { \"codepoints\": [8768], \"characters\": \"\\u2240\" },\n  \"&Wscr;\": { \"codepoints\": [119986], \"characters\": \"\\uD835\\uDCB2\" },\n  \"&wscr;\": { \"codepoints\": [120012], \"characters\": \"\\uD835\\uDCCC\" },\n  \"&xcap;\": { \"codepoints\": [8898], \"characters\": \"\\u22C2\" },\n  \"&xcirc;\": { \"codepoints\": [9711], \"characters\": \"\\u25EF\" },\n  \"&xcup;\": { \"codepoints\": [8899], \"characters\": \"\\u22C3\" },\n  \"&xdtri;\": { \"codepoints\": [9661], \"characters\": \"\\u25BD\" },\n  \"&Xfr;\": { \"codepoints\": [120091], \"characters\": \"\\uD835\\uDD1B\" },\n  \"&xfr;\": { \"codepoints\": [120117], \"characters\": \"\\uD835\\uDD35\" },\n  \"&xharr;\": { \"codepoints\": [10231], \"characters\": \"\\u27F7\" },\n  \"&xhArr;\": { \"codepoints\": [10234], \"characters\": \"\\u27FA\" },\n  \"&Xi;\": { \"codepoints\": [926], \"characters\": \"\\u039E\" },\n  \"&xi;\": { \"codepoints\": [958], \"characters\": \"\\u03BE\" },\n  \"&xlarr;\": { \"codepoints\": [10229], \"characters\": \"\\u27F5\" },\n  \"&xlArr;\": { \"codepoints\": [10232], \"characters\": \"\\u27F8\" },\n  \"&xmap;\": { \"codepoints\": [10236], \"characters\": \"\\u27FC\" },\n  \"&xnis;\": { \"codepoints\": [8955], \"characters\": \"\\u22FB\" },\n  \"&xodot;\": { \"codepoints\": [10752], \"characters\": \"\\u2A00\" },\n  \"&Xopf;\": { \"codepoints\": [120143], \"characters\": \"\\uD835\\uDD4F\" },\n  \"&xopf;\": { \"codepoints\": [120169], \"characters\": \"\\uD835\\uDD69\" },\n  \"&xoplus;\": { \"codepoints\": [10753], \"characters\": \"\\u2A01\" },\n  \"&xotime;\": { \"codepoints\": [10754], \"characters\": \"\\u2A02\" },\n  \"&xrarr;\": { \"codepoints\": [10230], \"characters\": \"\\u27F6\" },\n  \"&xrArr;\": { \"codepoints\": [10233], \"characters\": \"\\u27F9\" },\n  \"&Xscr;\": { \"codepoints\": [119987], \"characters\": \"\\uD835\\uDCB3\" },\n  \"&xscr;\": { \"codepoints\": [120013], \"characters\": \"\\uD835\\uDCCD\" },\n  \"&xsqcup;\": { \"codepoints\": [10758], \"characters\": \"\\u2A06\" },\n  \"&xuplus;\": { \"codepoints\": [10756], \"characters\": \"\\u2A04\" },\n  \"&xutri;\": { \"codepoints\": [9651], \"characters\": \"\\u25B3\" },\n  \"&xvee;\": { \"codepoints\": [8897], \"characters\": \"\\u22C1\" },\n  \"&xwedge;\": { \"codepoints\": [8896], \"characters\": \"\\u22C0\" },\n  \"&Yacute;\": { \"codepoints\": [221], \"characters\": \"\\u00DD\" },\n  \"&Yacute\": { \"codepoints\": [221], \"characters\": \"\\u00DD\" },\n  \"&yacute;\": { \"codepoints\": [253], \"characters\": \"\\u00FD\" },\n  \"&yacute\": { \"codepoints\": [253], \"characters\": \"\\u00FD\" },\n  \"&YAcy;\": { \"codepoints\": [1071], \"characters\": \"\\u042F\" },\n  \"&yacy;\": { \"codepoints\": [1103], \"characters\": \"\\u044F\" },\n  \"&Ycirc;\": { \"codepoints\": [374], \"characters\": \"\\u0176\" },\n  \"&ycirc;\": { \"codepoints\": [375], \"characters\": \"\\u0177\" },\n  \"&Ycy;\": { \"codepoints\": [1067], \"characters\": \"\\u042B\" },\n  \"&ycy;\": { \"codepoints\": [1099], \"characters\": \"\\u044B\" },\n  \"&yen;\": { \"codepoints\": [165], \"characters\": \"\\u00A5\" },\n  \"&yen\": { \"codepoints\": [165], \"characters\": \"\\u00A5\" },\n  \"&Yfr;\": { \"codepoints\": [120092], \"characters\": \"\\uD835\\uDD1C\" },\n  \"&yfr;\": { \"codepoints\": [120118], \"characters\": \"\\uD835\\uDD36\" },\n  \"&YIcy;\": { \"codepoints\": [1031], \"characters\": \"\\u0407\" },\n  \"&yicy;\": { \"codepoints\": [1111], \"characters\": \"\\u0457\" },\n  \"&Yopf;\": { \"codepoints\": [120144], \"characters\": \"\\uD835\\uDD50\" },\n  \"&yopf;\": { \"codepoints\": [120170], \"characters\": \"\\uD835\\uDD6A\" },\n  \"&Yscr;\": { \"codepoints\": [119988], \"characters\": \"\\uD835\\uDCB4\" },\n  \"&yscr;\": { \"codepoints\": [120014], \"characters\": \"\\uD835\\uDCCE\" },\n  \"&YUcy;\": { \"codepoints\": [1070], \"characters\": \"\\u042E\" },\n  \"&yucy;\": { \"codepoints\": [1102], \"characters\": \"\\u044E\" },\n  \"&yuml;\": { \"codepoints\": [255], \"characters\": \"\\u00FF\" },\n  \"&yuml\": { \"codepoints\": [255], \"characters\": \"\\u00FF\" },\n  \"&Yuml;\": { \"codepoints\": [376], \"characters\": \"\\u0178\" },\n  \"&Zacute;\": { \"codepoints\": [377], \"characters\": \"\\u0179\" },\n  \"&zacute;\": { \"codepoints\": [378], \"characters\": \"\\u017A\" },\n  \"&Zcaron;\": { \"codepoints\": [381], \"characters\": \"\\u017D\" },\n  \"&zcaron;\": { \"codepoints\": [382], \"characters\": \"\\u017E\" },\n  \"&Zcy;\": { \"codepoints\": [1047], \"characters\": \"\\u0417\" },\n  \"&zcy;\": { \"codepoints\": [1079], \"characters\": \"\\u0437\" },\n  \"&Zdot;\": { \"codepoints\": [379], \"characters\": \"\\u017B\" },\n  \"&zdot;\": { \"codepoints\": [380], \"characters\": \"\\u017C\" },\n  \"&zeetrf;\": { \"codepoints\": [8488], \"characters\": \"\\u2128\" },\n  \"&ZeroWidthSpace;\": { \"codepoints\": [8203], \"characters\": \"\\u200B\" },\n  \"&Zeta;\": { \"codepoints\": [918], \"characters\": \"\\u0396\" },\n  \"&zeta;\": { \"codepoints\": [950], \"characters\": \"\\u03B6\" },\n  \"&zfr;\": { \"codepoints\": [120119], \"characters\": \"\\uD835\\uDD37\" },\n  \"&Zfr;\": { \"codepoints\": [8488], \"characters\": \"\\u2128\" },\n  \"&ZHcy;\": { \"codepoints\": [1046], \"characters\": \"\\u0416\" },\n  \"&zhcy;\": { \"codepoints\": [1078], \"characters\": \"\\u0436\" },\n  \"&zigrarr;\": { \"codepoints\": [8669], \"characters\": \"\\u21DD\" },\n  \"&zopf;\": { \"codepoints\": [120171], \"characters\": \"\\uD835\\uDD6B\" },\n  \"&Zopf;\": { \"codepoints\": [8484], \"characters\": \"\\u2124\" },\n  \"&Zscr;\": { \"codepoints\": [119989], \"characters\": \"\\uD835\\uDCB5\" },\n  \"&zscr;\": { \"codepoints\": [120015], \"characters\": \"\\uD835\\uDCCF\" },\n  \"&zwj;\": { \"codepoints\": [8205], \"characters\": \"\\u200D\" },\n  \"&zwnj;\": { \"codepoints\": [8204], \"characters\": \"\\u200C\" }\n};\n\nvar ALPHANUMERIC = /^[a-zA-Z0-9]/;\nvar getPossibleNamedEntityStart = makeRegexMatcher(/^&[a-zA-Z0-9]/);\nvar getApparentNamedEntity = makeRegexMatcher(/^&[a-zA-Z0-9]+;/);\n\nvar getNamedEntityByFirstChar = {};\n(function () {\n  var namedEntitiesByFirstChar = {};\n  for (var ent in ENTITIES) {\n    var chr = ent.charAt(1);\n    namedEntitiesByFirstChar[chr] = (namedEntitiesByFirstChar[chr] || []);\n    namedEntitiesByFirstChar[chr].push(ent.slice(2));\n  }\n  for (var chr in namedEntitiesByFirstChar) {\n    getNamedEntityByFirstChar[chr] = makeRegexMatcher(\n      new RegExp('^&' + chr + '(?:' +\n                 namedEntitiesByFirstChar[chr].join('|') + ')'));\n  }\n})();\n\n// Run a provided \"matcher\" function but reset the current position afterwards.\n// Fatal failure of the matcher is not suppressed.\nvar peekMatcher = function (scanner, matcher) {\n  var start = scanner.pos;\n  var result = matcher(scanner);\n  scanner.pos = start;\n  return result;\n};\n\n// Returns a string like \"&amp;\" or a falsy value if no match.  Fails fatally\n// if something looks like a named entity but isn't.\nvar getNamedCharRef = function (scanner, inAttribute) {\n  // look for `&` followed by alphanumeric\n  if (! peekMatcher(scanner, getPossibleNamedEntityStart))\n    return null;\n\n  var matcher = getNamedEntityByFirstChar[scanner.rest().charAt(1)];\n  var entity = null;\n  if (matcher)\n    entity = peekMatcher(scanner, matcher);\n\n  if (entity) {\n    if (entity.slice(-1) !== ';') {\n      // Certain character references with no semi are an error, like `&lt`.\n      // In attribute values, however, this is not fatal if the next character\n      // is alphanumeric.\n      //\n      // This rule affects href attributes, for example, deeming \"/?foo=bar&ltc=abc\"\n      // to be ok but \"/?foo=bar&lt=abc\" to not be.\n      if (inAttribute && ALPHANUMERIC.test(scanner.rest().charAt(entity.length)))\n        return null;\n      scanner.fatal(\"Character reference requires semicolon: \" + entity);\n    } else {\n      scanner.pos += entity.length;\n      return entity;\n    }\n  } else {\n    // we couldn't match any real entity, so see if this is a bad entity\n    // or something we can overlook.\n    var badEntity = peekMatcher(scanner, getApparentNamedEntity);\n    if (badEntity)\n      scanner.fatal(\"Invalid character reference: \" + badEntity);\n    // `&aaaa` is ok with no semicolon\n    return null;\n  }\n};\n\n// Returns the sequence of one or two codepoints making up an entity as an array.\n// Codepoints in the array are integers and may be out of the single-char JavaScript\n// range.\nvar getCodePoints = function (namedEntity) {\n  return ENTITIES[namedEntity].codepoints;\n};\n\nvar ALLOWED_AFTER_AMP = /^[\\u0009\\u000a\\u000c <&]/;\n\nvar getCharRefNumber = makeRegexMatcher(/^(?:[xX][0-9a-fA-F]+|[0-9]+);/);\n\nvar BIG_BAD_CODEPOINTS = (function (obj) {\n  var list = [0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF,\n              0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE, 0x6FFFF,\n              0x7FFFE, 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF,\n              0xAFFFE, 0xAFFFF, 0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF,\n              0xDFFFE, 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF,\n              0x10FFFE, 0x10FFFF];\n  for (var i = 0; i < list.length; i++)\n    obj[list[i]] = true;\n\n  return obj;\n})({});\n\nvar isLegalCodepoint = function (cp) {\n  if ((cp === 0) ||\n      (cp >= 0x80 && cp <= 0x9f) ||\n      (cp >= 0xd800 && cp <= 0xdfff) ||\n      (cp >= 0x10ffff) ||\n      (cp >= 0x1 && cp <= 0x8) ||\n      (cp === 0xb) ||\n      (cp >= 0xd && cp <= 0x1f) ||\n      (cp >= 0x7f && cp <= 0x9f) ||\n      (cp >= 0xfdd0 && cp <= 0xfdef) ||\n      (cp === 0xfffe) ||\n      (cp === 0xffff) ||\n      (cp >= 0x10000 && BIG_BAD_CODEPOINTS[cp]))\n    return false;\n\n  return true;\n};\n\n// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference\n//\n// Matches a character reference if possible, including the initial `&`.\n// Fails fatally in error cases (assuming an initial `&` is matched), like a disallowed codepoint\n// number or a bad named character reference.\n//\n// `inAttribute` is truthy if we are in an attribute value.\n//\n// `allowedChar` is an optional character that,\n// if found after the initial `&`, aborts parsing silently rather than failing fatally.  In real use it is\n// either `\"`, `'`, or `>` and is supplied when parsing attribute values.  NOTE: In the current spec, the\n// value of `allowedChar` doesn't actually seem to end up mattering, but there is still some debate about\n// the right approach to ampersands.\ngetCharacterReference = HTMLTools.Parse.getCharacterReference = function (scanner, inAttribute, allowedChar) {\n  if (scanner.peek() !== '&')\n    // no ampersand\n    return null;\n\n  var afterAmp = scanner.rest().charAt(1);\n\n  if (afterAmp === '#') {\n    scanner.pos += 2;\n    // refNumber includes possible initial `x` and final semicolon\n    var refNumber = getCharRefNumber(scanner);\n    // At this point we've consumed the input, so we're committed to returning\n    // something or failing fatally.\n    if (! refNumber)\n      scanner.fatal(\"Invalid numerical character reference starting with &#\");\n    var codepoint;\n    if (refNumber.charAt(0) === 'x' || refNumber.charAt(0) === 'X') {\n      // hex\n      var hex = refNumber.slice(1, -1);\n      while (hex.charAt(0) === '0')\n        hex = hex.slice(1);\n      if (hex.length > 6)\n        scanner.fatal(\"Numerical character reference too large: 0x\" + hex);\n      codepoint = parseInt(hex || \"0\", 16);\n    } else {\n      var dec = refNumber.slice(0, -1);\n      while (dec.charAt(0) === '0')\n        dec = dec.slice(1);\n      if (dec.length > 7)\n        scanner.fatal(\"Numerical character reference too large: \" + dec);\n      codepoint = parseInt(dec || \"0\", 10);\n    }\n    if (! isLegalCodepoint(codepoint))\n      scanner.fatal(\"Illegal codepoint in numerical character reference: &#\" + refNumber);\n    return { t: 'CharRef',\n             v: '&#' + refNumber,\n             cp: [codepoint] };\n  } else if ((! afterAmp) // EOF\n             || (allowedChar && afterAmp === allowedChar)\n             || ALLOWED_AFTER_AMP.test(afterAmp)) {\n    return null;\n  } else {\n    var namedEntity = getNamedCharRef(scanner, inAttribute);\n    if (namedEntity) {\n      return { t: 'CharRef',\n               v: namedEntity,\n               cp: getCodePoints(namedEntity) };\n    } else {\n      return null;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/html-tools/charref_tests.js",
    "content": "var Scanner = HTMLTools.Scanner;\nvar getCharacterReference = HTMLTools.Parse.getCharacterReference;\n\nTinytest.add(\"html-tools - entities\", function (test) {\n  var succeed = function (input, match, codepoints) {\n    if (typeof input === 'string')\n      input = {input: input};\n\n    // match arg is optional; codepoints is never a string\n    if (typeof match !== 'string') {\n      codepoints = match;\n      match = input.input;\n    }\n\n    var scanner = new Scanner(input.input);\n    var result = getCharacterReference(scanner, input.inAttribute, input.allowedChar);\n    test.isTrue(result);\n    test.equal(scanner.pos, match.length);\n    test.equal(result, {\n      t: 'CharRef',\n      v: match,\n      cp: _.map(codepoints,\n                function (x) { return (typeof x === 'string' ?\n                                       x.charCodeAt(0) : x); })\n    });\n  };\n\n  var ignore = function (input) {\n    if (typeof input === 'string')\n      input = {input: input};\n\n    var scanner = new Scanner(input.input);\n    var result = getCharacterReference(scanner, input.inAttribute, input.allowedChar);\n    test.isFalse(result);\n    test.equal(scanner.pos, 0);\n  };\n\n  var fatal = function (input, messageContains) {\n    if (typeof input === 'string')\n      input = {input: input};\n\n    var scanner = new Scanner(input.input);\n    var error;\n    try {\n      getCharacterReference(scanner, input.inAttribute, input.allowedChar);\n    } catch (e) {\n      error = e;\n    }\n    test.isTrue(error);\n    if (error)\n      test.isTrue(messageContains && error.message.indexOf(messageContains) >= 0, error.message);\n  };\n\n  ignore('a');\n  ignore('&');\n  ignore('&&');\n  ignore('&\\t');\n  ignore('& ');\n  fatal('&#', 'Invalid numerical character reference starting with &#');\n  ignore('&a');\n  fatal('&a;', 'Invalid character reference: &a;');\n  ignore({input: '&\"', allowedChar: '\"'});\n  ignore('&\"');\n\n  succeed('&gt;', ['>']);\n  fatal('&gt', 'Character reference requires semicolon');\n  ignore('&aaa');\n  fatal('&gta', 'Character reference requires semicolon');\n  ignore({input: '&gta', inAttribute: true});\n  fatal({input: '&gt=', inAttribute: true}, 'Character reference requires semicolon: &gt');\n\n  succeed('&gt;;', '&gt;', ['>']);\n\n  fatal('&asdflkj;', 'Invalid character reference: &asdflkj;');\n  fatal('&A0asdflkj;', 'Invalid character reference: &A0asdflkj;');\n  ignore('&A0asdflkj');\n\n  succeed('&zopf;', [120171]);\n  succeed('&acE;', [8766, 819]);\n\n  succeed('&#10;', [10]);\n  fatal('&#10', 'Invalid numerical character reference starting with &#');\n  fatal('&#xg;', 'Invalid numerical character reference starting with &#');\n  fatal('&#;', 'Invalid numerical character reference starting with &#');\n  fatal('&#a;', 'Invalid numerical character reference starting with &#');\n  fatal('&#a', 'Invalid numerical character reference starting with &#');\n  fatal('&#z', 'Invalid numerical character reference starting with &#');\n  succeed('&#000000000000010;', [10]);\n  fatal('&#0001000000000010;', 'Numerical character reference too large: 1000000000010');\n  succeed('&#x00000000000000000000a;', [10]);\n  fatal('&#x000100000000000a;', 'Numerical character reference too large: 0x100000000000a');\n  succeed('&#010;', [10]);\n  succeed('&#xa;', [10]);\n  succeed('&#Xa;', [10]);\n  succeed('&#XA;', [10]);\n  succeed('&#xA;', [10]);\n\n  fatal('&#0;', 'Illegal codepoint in numerical character reference: &#0;');\n  fatal('&#x0;', 'Illegal codepoint in numerical character reference: &#x0;');\n\n  fatal('&#xb;', 'Illegal codepoint in numerical character reference: &#xb;');\n  succeed('&#xc;', [12]);\n  fatal('&#11;', 'Illegal codepoint in numerical character reference: &#11;');\n  succeed('&#12;', [12]);\n\n  fatal('&#x10ffff;', 'Illegal codepoint in numerical character reference');\n  fatal('&#x10fffe;', 'Illegal codepoint in numerical character reference');\n  succeed('&#x10fffd;', [0x10fffd]);\n\n  fatal('&#1114111;', 'Illegal codepoint in numerical character reference');\n  fatal('&#1114110;', 'Illegal codepoint in numerical character reference');\n  succeed('&#1114109;', [0x10fffd]);\n\n});\n"
  },
  {
    "path": "packages/html-tools/package.js",
    "content": "Package.describe({\n  summary: \"Standards-compliant HTML tools\",\n  version: '1.0.10'\n});\n\nPackage.onUse(function (api) {\n  api.use('htmljs');\n  api.imply('htmljs');\n\n  api.export('HTMLTools');\n\n  api.addFiles(['utils.js',\n                 'scanner.js',\n                 'charref.js',\n                 'tokenize.js',\n                 'templatetag.js',\n                 'parse.js']);\n});\n\nPackage.onTest(function (api) {\n  api.use('tinytest');\n  api.use('html-tools');\n  api.use('underscore');\n  api.use('htmljs');\n  api.use('blaze-tools'); // for `toJS`\n  api.addFiles(['charref_tests.js',\n                 'tokenize_tests.js',\n                 'parse_tests.js']);\n});\n"
  },
  {
    "path": "packages/html-tools/parse.js",
    "content": "\n// Parse a \"fragment\" of HTML, up to the end of the input or a particular\n// template tag (using the \"shouldStop\" option).\nHTMLTools.parseFragment = function (input, options) {\n  var scanner;\n  if (typeof input === 'string')\n    scanner = new Scanner(input);\n  else\n    // input can be a scanner.  We'd better not have a different\n    // value for the \"getTemplateTag\" option as when the scanner\n    // was created, because we don't do anything special to reset\n    // the value (which is attached to the scanner).\n    scanner = input;\n\n  // ```\n  // { getTemplateTag: function (scanner, templateTagPosition) {\n  //     if (templateTagPosition === HTMLTools.TEMPLATE_TAG_POSITION.ELEMENT) {\n  //       ...\n  // ```\n  if (options && options.getTemplateTag)\n    scanner.getTemplateTag = options.getTemplateTag;\n\n  // function (scanner) -> boolean\n  var shouldStop = options && options.shouldStop;\n\n  var result;\n  if (options && options.textMode) {\n    if (options.textMode === HTML.TEXTMODE.STRING) {\n      result = getRawText(scanner, null, shouldStop);\n    } else if (options.textMode === HTML.TEXTMODE.RCDATA) {\n      result = getRCData(scanner, null, shouldStop);\n    } else {\n      throw new Error(\"Unsupported textMode: \" + options.textMode);\n    }\n  } else {\n    result = getContent(scanner, shouldStop);\n  }\n  if (! scanner.isEOF()) {\n    // If we aren't at the end of the input, we either stopped at an unmatched\n    // HTML end tag or at a template tag (like `{{else}}` or `{{/if}}`).\n    // Detect the former case (stopped at an HTML end tag) and throw a good\n    // error.\n\n    var posBefore = scanner.pos;\n\n    try {\n      var endTag = getHTMLToken(scanner);\n    } catch (e) {\n      // ignore errors from getTemplateTag\n    }\n\n    // XXX we make some assumptions about shouldStop here, like that it\n    // won't tell us to stop at an HTML end tag.  Should refactor\n    // `shouldStop` into something more suitable.\n    if (endTag && endTag.t === 'Tag' && endTag.isEnd) {\n      var closeTag = endTag.n;\n      var isVoidElement = HTML.isVoidElement(closeTag);\n      scanner.fatal(\"Unexpected HTML close tag\" +\n                    (isVoidElement ?\n                     '.  <' + endTag.n + '> should have no close tag.' : ''));\n    }\n\n    scanner.pos = posBefore; // rewind, we'll continue parsing as usual\n\n    // If no \"shouldStop\" option was provided, we should have consumed the whole\n    // input.\n    if (! shouldStop)\n      scanner.fatal(\"Expected EOF\");\n  }\n\n  return result;\n};\n\n// Take a numeric Unicode code point, which may be larger than 16 bits,\n// and encode it as a JavaScript UTF-16 string.\n//\n// Adapted from\n// http://stackoverflow.com/questions/7126384/expressing-utf-16-unicode-characters-in-javascript/7126661.\ncodePointToString = HTMLTools.codePointToString = function(cp) {\n  if (cp >= 0 && cp <= 0xD7FF || cp >= 0xE000 && cp <= 0xFFFF) {\n    return String.fromCharCode(cp);\n  } else if (cp >= 0x10000 && cp <= 0x10FFFF) {\n\n    // we substract 0x10000 from cp to get a 20-bit number\n    // in the range 0..0xFFFF\n    cp -= 0x10000;\n\n    // we add 0xD800 to the number formed by the first 10 bits\n    // to give the first byte\n    var first = ((0xffc00 & cp) >> 10) + 0xD800;\n\n    // we add 0xDC00 to the number formed by the low 10 bits\n    // to give the second byte\n    var second = (0x3ff & cp) + 0xDC00;\n\n    return String.fromCharCode(first) + String.fromCharCode(second);\n  } else {\n    return '';\n  }\n};\n\ngetContent = HTMLTools.Parse.getContent = function (scanner, shouldStopFunc) {\n  var items = [];\n\n  while (! scanner.isEOF()) {\n    if (shouldStopFunc && shouldStopFunc(scanner))\n      break;\n\n    var posBefore = scanner.pos;\n    var token = getHTMLToken(scanner);\n    if (! token)\n      // tokenizer reached EOF on its own, e.g. while scanning\n      // template comments like `{{! foo}}`.\n      continue;\n\n    if (token.t === 'Doctype') {\n      scanner.fatal(\"Unexpected Doctype\");\n    } else if (token.t === 'Chars') {\n      pushOrAppendString(items, token.v);\n    } else if (token.t === 'CharRef') {\n      items.push(convertCharRef(token));\n    } else if (token.t === 'Comment') {\n      items.push(HTML.Comment(token.v));\n    } else if (token.t === 'TemplateTag') {\n      items.push(token.v);\n    } else if (token.t === 'Tag') {\n      if (token.isEnd) {\n        // Stop when we encounter an end tag at the top level.\n        // Rewind; we'll re-parse the end tag later.\n        scanner.pos = posBefore;\n        break;\n      }\n\n      var tagName = token.n;\n      // is this an element with no close tag (a BR, HR, IMG, etc.) based\n      // on its name?\n      var isVoid = HTML.isVoidElement(tagName);\n      if (token.isSelfClosing) {\n        if (! (isVoid || HTML.isKnownSVGElement(tagName) || tagName.indexOf(':') >= 0))\n          scanner.fatal('Only certain elements like BR, HR, IMG, etc. (and foreign elements like SVG) are allowed to self-close');\n      }\n\n      // result of parseAttrs may be null\n      var attrs = parseAttrs(token.attrs);\n      // arrays need to be wrapped in HTML.Attrs(...)\n      // when used to construct tags\n      if (HTML.isArray(attrs))\n        attrs = HTML.Attrs.apply(null, attrs);\n\n      var tagFunc = HTML.getTag(tagName);\n      if (isVoid || token.isSelfClosing) {\n        items.push(attrs ? tagFunc(attrs) : tagFunc());\n      } else {\n        // parse HTML tag contents.\n\n        // HTML treats a final `/` in a tag as part of an attribute, as in `<a href=/foo/>`, but the template author who writes `<circle r={{r}}/>`, say, may not be thinking about that, so generate a good error message in the \"looks like self-close\" case.\n        var looksLikeSelfClose = (scanner.input.substr(scanner.pos - 2, 2) === '/>');\n\n        var content = null;\n        if (token.n === 'textarea') {\n          if (scanner.peek() === '\\n')\n            scanner.pos++;\n          var textareaValue = getRCData(scanner, token.n, shouldStopFunc);\n          if (textareaValue) {\n            if (attrs instanceof HTML.Attrs) {\n              attrs = HTML.Attrs.apply(\n                null, attrs.value.concat([{value: textareaValue}]));\n            } else {\n              attrs = (attrs || {});\n              attrs.value = textareaValue;\n            }\n          }\n        } else if (token.n === 'script' || token.n === 'style') {\n          content = getRawText(scanner, token.n, shouldStopFunc);\n        } else {\n          content = getContent(scanner, shouldStopFunc);\n        }\n\n        var endTag = getHTMLToken(scanner);\n\n        if (! (endTag && endTag.t === 'Tag' && endTag.isEnd && endTag.n === tagName))\n          scanner.fatal('Expected \"' + tagName + '\" end tag' + (looksLikeSelfClose ? ' -- if the \"<' + token.n + ' />\" tag was supposed to self-close, try adding a space before the \"/\"' : ''));\n\n        // XXX support implied end tags in cases allowed by the spec\n\n        // make `content` into an array suitable for applying tag constructor\n        // as in `FOO.apply(null, content)`.\n        if (content == null)\n          content = [];\n        else if (! (content instanceof Array))\n          content = [content];\n\n        items.push(HTML.getTag(tagName).apply(\n          null, (attrs ? [attrs] : []).concat(content)));\n      }\n    } else {\n      scanner.fatal(\"Unknown token type: \" + token.t);\n    }\n  }\n\n  if (items.length === 0)\n    return null;\n  else if (items.length === 1)\n    return items[0];\n  else\n    return items;\n};\n\nvar pushOrAppendString = function (items, string) {\n  if (items.length &&\n      typeof items[items.length - 1] === 'string')\n    items[items.length - 1] += string;\n  else\n    items.push(string);\n};\n\n// get RCDATA to go in the lowercase (or camel case) tagName (e.g. \"textarea\")\ngetRCData = HTMLTools.Parse.getRCData = function (scanner, tagName, shouldStopFunc) {\n  var items = [];\n\n  while (! scanner.isEOF()) {\n    // break at appropriate end tag\n    if (tagName && isLookingAtEndTag(scanner, tagName))\n      break;\n\n    if (shouldStopFunc && shouldStopFunc(scanner))\n      break;\n\n    var token = getHTMLToken(scanner, 'rcdata');\n    if (! token)\n      // tokenizer reached EOF on its own, e.g. while scanning\n      // template comments like `{{! foo}}`.\n      continue;\n\n    if (token.t === 'Chars') {\n      pushOrAppendString(items, token.v);\n    } else if (token.t === 'CharRef') {\n      items.push(convertCharRef(token));\n    } else if (token.t === 'TemplateTag') {\n      items.push(token.v);\n    } else {\n      // (can't happen)\n      scanner.fatal(\"Unknown or unexpected token type: \" + token.t);\n    }\n  }\n\n  if (items.length === 0)\n    return null;\n  else if (items.length === 1)\n    return items[0];\n  else\n    return items;\n};\n\nvar getRawText = function (scanner, tagName, shouldStopFunc) {\n  var items = [];\n\n  while (! scanner.isEOF()) {\n    // break at appropriate end tag\n    if (tagName && isLookingAtEndTag(scanner, tagName))\n      break;\n\n    if (shouldStopFunc && shouldStopFunc(scanner))\n      break;\n\n    var token = getHTMLToken(scanner, 'rawtext');\n    if (! token)\n      // tokenizer reached EOF on its own, e.g. while scanning\n      // template comments like `{{! foo}}`.\n      continue;\n\n    if (token.t === 'Chars') {\n      pushOrAppendString(items, token.v);\n    } else if (token.t === 'TemplateTag') {\n      items.push(token.v);\n    } else {\n      // (can't happen)\n      scanner.fatal(\"Unknown or unexpected token type: \" + token.t);\n    }\n  }\n\n  if (items.length === 0)\n    return null;\n  else if (items.length === 1)\n    return items[0];\n  else\n    return items;\n};\n\n// Input: A token like `{ t: 'CharRef', v: '&amp;', cp: [38] }`.\n//\n// Output: A tag like `HTML.CharRef({ html: '&amp;', str: '&' })`.\nvar convertCharRef = function (token) {\n  var codePoints = token.cp;\n  var str = '';\n  for (var i = 0; i < codePoints.length; i++)\n    str += codePointToString(codePoints[i]);\n  return HTML.CharRef({ html: token.v, str: str });\n};\n\n// Input is always a dictionary (even if zero attributes) and each\n// value in the dictionary is an array of `Chars`, `CharRef`,\n// and maybe `TemplateTag` tokens.\n//\n// Output is null if there are zero attributes, and otherwise a\n// dictionary, or an array of dictionaries and template tags.\n// Each value in the dictionary is HTMLjs (e.g. a\n// string or an array of `Chars`, `CharRef`, and `TemplateTag`\n// nodes).\n//\n// An attribute value with no input tokens is represented as \"\",\n// not an empty array, in order to prop open empty attributes\n// with no template tags.\nvar parseAttrs = function (attrs) {\n  var result = null;\n\n  if (HTML.isArray(attrs)) {\n    // first element is nondynamic attrs, rest are template tags\n    var nondynamicAttrs = parseAttrs(attrs[0]);\n    if (nondynamicAttrs) {\n      result = (result || []);\n      result.push(nondynamicAttrs);\n    }\n    for (var i = 1; i < attrs.length; i++) {\n      var token = attrs[i];\n      if (token.t !== 'TemplateTag')\n        throw new Error(\"Expected TemplateTag token\");\n      result = (result || []);\n      result.push(token.v);\n    }\n    return result;\n  }\n\n  for (var k in attrs) {\n    if (! result)\n      result = {};\n\n    var inValue = attrs[k];\n    var outParts = [];\n    for (var i = 0; i < inValue.length; i++) {\n      var token = inValue[i];\n      if (token.t === 'CharRef') {\n        outParts.push(convertCharRef(token));\n      } else if (token.t === 'TemplateTag') {\n        outParts.push(token.v);\n      } else if (token.t === 'Chars') {\n        pushOrAppendString(outParts, token.v);\n      }\n    }\n\n    var outValue = (inValue.length === 0 ? '' :\n                    (outParts.length === 1 ? outParts[0] : outParts));\n    var properKey = HTMLTools.properCaseAttributeName(k);\n    result[properKey] = outValue;\n  }\n\n  return result;\n};\n"
  },
  {
    "path": "packages/html-tools/parse_tests.js",
    "content": "var Scanner = HTMLTools.Scanner;\nvar getContent = HTMLTools.Parse.getContent;\n\nvar CharRef = HTML.CharRef;\nvar Comment = HTML.Comment;\nvar TemplateTag = HTMLTools.TemplateTag;\nvar Attrs = HTML.Attrs;\n\nvar BR = HTML.BR;\nvar HR = HTML.HR;\nvar INPUT = HTML.INPUT;\nvar A = HTML.A;\nvar DIV = HTML.DIV;\nvar P = HTML.P;\nvar TEXTAREA = HTML.TEXTAREA;\nvar SCRIPT = HTML.SCRIPT;\nvar STYLE = HTML.STYLE;\n\nTinytest.add(\"html-tools - parser getContent\", function (test) {\n\n  var succeed = function (input, expected) {\n    var endPos = input.indexOf('^^^');\n    if (endPos < 0)\n      endPos = input.length;\n\n    var scanner = new Scanner(input.replace('^^^', ''));\n    var result = getContent(scanner);\n    test.equal(scanner.pos, endPos);\n    test.equal(BlazeTools.toJS(result), BlazeTools.toJS(expected));\n  };\n\n  var fatal = function (input, messageContains) {\n    var scanner = new Scanner(input);\n    var error;\n    try {\n      getContent(scanner);\n    } catch (e) {\n      error = e;\n    }\n    test.isTrue(error);\n    if (messageContains)\n      test.isTrue(messageContains && error.message.indexOf(messageContains) >= 0, error.message);\n  };\n\n\n  succeed('', null);\n  succeed('abc', 'abc');\n  succeed('abc^^^</x>', 'abc');\n  succeed('a&lt;b', ['a', CharRef({html: '&lt;', str: '<'}), 'b']);\n  succeed('<!-- x -->', Comment(' x '));\n  succeed('&acE;', CharRef({html: '&acE;', str: '\\u223e\\u0333'}));\n  succeed('&zopf;', CharRef({html: '&zopf;', str: '\\ud835\\udd6b'}));\n  succeed('&&>&g&gt;;', ['&&>&g', CharRef({html: '&gt;', str: '>'}), ';']);\n\n  // Can't have an unescaped `&` if followed by certain names like `gt`\n  fatal('&gt&');\n  // tests for other failure cases\n  fatal('<');\n\n  succeed('<br>', BR());\n  succeed('<br/>', BR());\n  fatal('<div/>', 'self-close');\n\n  succeed('<hr id=foo>', HR({id:'foo'}));\n  succeed('<hr id=&lt;foo&gt;>', HR({id:[CharRef({html:'&lt;', str:'<'}),\n                                         'foo',\n                                         CharRef({html:'&gt;', str:'>'})]}));\n  succeed('<input selected>', INPUT({selected: ''}));\n  succeed('<input selected/>', INPUT({selected: ''}));\n  succeed('<input selected />', INPUT({selected: ''}));\n  var FOO = HTML.getTag('foo');\n  succeed('<foo bar></foo>', FOO({bar: ''}));\n  succeed('<foo bar baz ></foo>', FOO({bar: '', baz: ''}));\n  succeed('<foo bar=x baz qux=y blah ></foo>',\n          FOO({bar: 'x', baz: '', qux: 'y', blah: ''}));\n  succeed('<foo bar=\"x\" baz qux=\"y\" blah ></foo>',\n          FOO({bar: 'x', baz: '', qux: 'y', blah: ''}));\n  fatal('<input bar\"baz\">');\n  fatal('<input x=\"y\"z >');\n  fatal('<input x=\\'y\\'z >');\n  succeed('<br x=&&&>', BR({x: '&&&'}));\n  succeed('<br><br><br>', [BR(), BR(), BR()]);\n  succeed('aaa<br>\\nbbb<br>\\nccc<br>', ['aaa', BR(), '\\nbbb', BR(), '\\nccc', BR()]);\n\n  succeed('<a></a>', A());\n  fatal('<');\n  fatal('<a');\n  fatal('<a>');\n  fatal('<a><');\n  fatal('<a></');\n  fatal('<a></a');\n\n  succeed('<a href=\"http://www.apple.com/\">Apple</a>',\n          A({href: \"http://www.apple.com/\"}, 'Apple'));\n\n  (function () {\n    var A = HTML.getTag('a');\n    var B = HTML.getTag('b');\n    var C = HTML.getTag('c');\n    var D = HTML.getTag('d');\n\n    succeed('<a>1<b>2<c>3<d>4</d>5</c>6</b>7</a>8',\n            [A('1', B('2', C('3', D('4'), '5'), '6'), '7'), '8']);\n  })();\n\n  fatal('<b>hello <i>there</b> world</i>');\n\n  // XXX support implied end tags in cases allowed by the spec\n  fatal('<p>');\n\n  fatal('<a>Foo</a/>');\n  fatal('<a>Foo</a b=c>');\n\n  succeed('<textarea>asdf</textarea>', TEXTAREA({value: \"asdf\"}));\n  succeed('<textarea x=y>asdf</textarea>', TEXTAREA({x: \"y\", value: \"asdf\"}));\n  succeed('<textarea><p></textarea>', TEXTAREA({value: \"<p>\"}));\n  succeed('<textarea>a&amp;b</textarea>',\n          TEXTAREA({value: [\"a\", CharRef({html: '&amp;', str: '&'}), \"b\"]}));\n  succeed('<textarea></textarea</textarea>', TEXTAREA({value: \"</textarea\"}));\n  // absorb up to one initial newline, as per HTML parsing spec\n  succeed('<textarea>\\n</textarea>', TEXTAREA());\n  succeed('<textarea>\\nasdf</textarea>', TEXTAREA({value: \"asdf\"}));\n  succeed('<textarea>\\n\\nasdf</textarea>', TEXTAREA({value: \"\\nasdf\"}));\n  succeed('<textarea>\\n\\n</textarea>', TEXTAREA({value: \"\\n\"}));\n  succeed('<textarea>\\nasdf\\n</textarea>', TEXTAREA({value: \"asdf\\n\"}));\n  succeed('<textarea><!-- --></textarea>', TEXTAREA({value: \"<!-- -->\"}));\n  succeed('<tExTaReA>asdf</TEXTarea>', TEXTAREA({value: \"asdf\"}));\n  fatal('<textarea>asdf');\n  fatal('<textarea>asdf</textarea');\n  fatal('<textarea>&davidgreenspan;</textarea>');\n  succeed('<textarea>&</textarea>', TEXTAREA({value: \"&\"}));\n  succeed('<textarea></textarea  \\n<</textarea  \\n>asdf',\n          [TEXTAREA({value: \"</textarea  \\n<\"}), \"asdf\"]);\n  // regression test for a bug that happened with textarea content\n  // handling after an element with content\n  succeed('<div>x</div><textarea></textarea>', [DIV(\"x\"), TEXTAREA()]);\n\n  // CR/LF behavior\n  succeed('<br\\r\\n x>', BR({x:''}));\n  succeed('<br\\r x>', BR({x:''}));\n  succeed('<br x=\"y\"\\r\\n>', BR({x:'y'}));\n  succeed('<br x=\"y\"\\r>', BR({x:'y'}));\n  succeed('<br x=\\r\\n\"y\">', BR({x:'y'}));\n  succeed('<br x=\\r\"y\">', BR({x:'y'}));\n  succeed('<br x\\r=\\r\"y\">', BR({x:'y'}));\n  succeed('<!--\\r\\n-->', Comment('\\n'));\n  succeed('<!--\\r-->', Comment('\\n'));\n  succeed('<textarea>a\\r\\nb\\r\\nc</textarea>', TEXTAREA({value: 'a\\nb\\nc'}));\n  succeed('<textarea>a\\rb\\rc</textarea>', TEXTAREA({value: 'a\\nb\\nc'}));\n  succeed('<br x=\"\\r\\n\\r\\n\">', BR({x:'\\n\\n'}));\n  succeed('<br x=\"\\r\\r\">', BR({x:'\\n\\n'}));\n  succeed('<br x=y\\r>', BR({x:'y'}));\n  fatal('<br x=\\r>');\n\n  succeed('<script>var x=\"<div>\";</script>',SCRIPT('var x=\"<div>\";'));\n  succeed('<script>var x=1 && 0;</script>',SCRIPT('var x=1 && 0;'));\n\n  succeed('<script>asdf</script>', SCRIPT(\"asdf\"));\n  succeed('<script x=y>asdf</script>', SCRIPT({x: \"y\"}, \"asdf\"));\n  succeed('<script><p></script>', SCRIPT(\"<p>\"));\n  succeed('<script>a&amp;b</script>', SCRIPT(\"a&amp;b\"));\n  succeed('<script></script</script>', SCRIPT(\"</script\"));\n  succeed('<script>\\n</script>', SCRIPT(\"\\n\"));\n  succeed('<script><!-- --></script>', SCRIPT(\"<!-- -->\"));\n  succeed('<sCrIpT>asdf</SCRipt>', SCRIPT(\"asdf\"));\n  fatal('<script>asdf');\n  fatal('<script>asdf</script');\n  succeed('<script>&davidgreenspan;</script>', SCRIPT(\"&davidgreenspan;\"));\n  succeed('<script>&</script>', SCRIPT(\"&\"));\n  succeed('<script></script  \\n<</script  \\n>asdf',\n          [SCRIPT(\"</script  \\n<\"), \"asdf\"]);\n\n  succeed('<style>asdf</style>', STYLE(\"asdf\"));\n  succeed('<style x=y>asdf</style>', STYLE({x: \"y\"}, \"asdf\"));\n  succeed('<style><p></style>', STYLE(\"<p>\"));\n  succeed('<style>a&amp;b</style>', STYLE(\"a&amp;b\"));\n  succeed('<style></style</style>', STYLE(\"</style\"));\n  succeed('<style>\\n</style>', STYLE(\"\\n\"));\n  succeed('<style><!-- --></style>', STYLE(\"<!-- -->\"));\n  succeed('<sTyLe>asdf</STYle>', STYLE(\"asdf\"));\n  fatal('<style>asdf');\n  fatal('<style>asdf</style');\n  succeed('<style>&davidgreenspan;</style>', STYLE(\"&davidgreenspan;\"));\n  succeed('<style>&</style>', STYLE(\"&\"));\n  succeed('<style></style  \\n<</style  \\n>asdf',\n          [STYLE(\"</style  \\n<\"), \"asdf\"]);\n});\n\nTinytest.add(\"html-tools - parseFragment\", function (test) {\n  test.equal(BlazeTools.toJS(HTMLTools.parseFragment(\"<div><p id=foo>Hello</p></div>\")),\n             BlazeTools.toJS(DIV(P({id:'foo'}, 'Hello'))));\n\n  _.each(['asdf</br>', '{{!foo}}</br>', '{{!foo}} </br>',\n          'asdf</a>', '{{!foo}}</a>', '{{!foo}} </a>'], function (badFrag) {\n            test.throws(function() {\n              HTMLTools.parseFragment(badFrag);\n            }, /Unexpected HTML close tag/);\n          });\n\n  (function () {\n    var p = HTMLTools.parseFragment('<p></p>');\n    test.equal(p.tagName, 'p');\n    test.equal(p.attrs, null);\n    test.isTrue(p instanceof HTML.Tag);\n    test.equal(p.children.length, 0);\n  })();\n\n  (function () {\n    var p = HTMLTools.parseFragment('<p>x</p>');\n    test.equal(p.tagName, 'p');\n    test.equal(p.attrs, null);\n    test.isTrue(p instanceof HTML.Tag);\n    test.equal(p.children.length, 1);\n    test.equal(p.children[0], 'x');\n  })();\n\n  (function () {\n    var p = HTMLTools.parseFragment('<p>x&#65;</p>');\n    test.equal(p.tagName, 'p');\n    test.equal(p.attrs, null);\n    test.isTrue(p instanceof HTML.Tag);\n    test.equal(p.children.length, 2);\n    test.equal(p.children[0], 'x');\n\n    test.isTrue(p.children[1] instanceof HTML.CharRef);\n    test.equal(p.children[1].html, '&#65;');\n    test.equal(p.children[1].str, 'A');\n  })();\n\n  (function () {\n    var pp = HTMLTools.parseFragment('<p>x</p><p>y</p>');\n    test.isTrue(pp instanceof Array);\n    test.equal(pp.length, 2);\n\n    test.equal(pp[0].tagName, 'p');\n    test.equal(pp[0].attrs, null);\n    test.isTrue(pp[0] instanceof HTML.Tag);\n    test.equal(pp[0].children.length, 1);\n    test.equal(pp[0].children[0], 'x');\n\n    test.equal(pp[1].tagName, 'p');\n    test.equal(pp[1].attrs, null);\n    test.isTrue(pp[1] instanceof HTML.Tag);\n    test.equal(pp[1].children.length, 1);\n    test.equal(pp[1].children[0], 'y');\n  })();\n\n  var scanner = new Scanner('asdf');\n  scanner.pos = 1;\n  test.equal(HTMLTools.parseFragment(scanner), 'sdf');\n\n  test.throws(function () {\n    var scanner = new Scanner('asdf</p>');\n    scanner.pos = 1;\n    HTMLTools.parseFragment(scanner);\n  });\n});\n\nTinytest.add(\"html-tools - getTemplateTag\", function (test) {\n\n  // match a simple tag consisting of `{{`, an optional `!`, one\n  // or more ASCII letters, spaces or html tags, and a closing `}}`.\n  var mustache = /^\\{\\{(!?[a-zA-Z 0-9</>]+)\\}\\}/;\n\n  // This implementation of `getTemplateTag` looks for \"{{\" and if it\n  // finds it, it will match the regex above or fail fatally trying.\n  // The object it returns is opaque to the tokenizer/parser and can\n  // be anything we want.\n  var getTemplateTag = function (scanner, position) {\n    if (! (scanner.peek() === '{' && // one-char peek is just an optimization\n           scanner.rest().slice(0, 2) === '{{'))\n      return null;\n\n    var match = mustache.exec(scanner.rest());\n    if (! match)\n      scanner.fatal(\"Bad mustache\");\n\n    scanner.pos += match[0].length;\n\n    if (match[1].charAt(0) === '!')\n      return null; // `{{!foo}}` is like a comment\n\n    return TemplateTag({ stuff: match[1] });\n  };\n\n\n\n  var succeed = function (input, expected) {\n    var endPos = input.indexOf('^^^');\n    if (endPos < 0)\n      endPos = input.length;\n\n    var scanner = new Scanner(input.replace('^^^', ''));\n    scanner.getTemplateTag = getTemplateTag;\n    var result;\n    try {\n      result = getContent(scanner);\n    } catch (e) {\n      result = String(e);\n    }\n    test.equal(scanner.pos, endPos);\n    test.equal(BlazeTools.toJS(result), BlazeTools.toJS(expected));\n  };\n\n  var fatal = function (input, messageContains) {\n    var scanner = new Scanner(input);\n    scanner.getTemplateTag = getTemplateTag;\n    var error;\n    try {\n      getContent(scanner);\n    } catch (e) {\n      error = e;\n    }\n    test.isTrue(error);\n    if (messageContains)\n      test.isTrue(messageContains && error.message.indexOf(messageContains) >= 0, error.message);\n  };\n\n\n  succeed('{{foo}}', TemplateTag({stuff: 'foo'}));\n\n  succeed('<a href=http://www.apple.com/>{{foo}}</a>',\n          A({href: \"http://www.apple.com/\"}, TemplateTag({stuff: 'foo'})));\n\n  // tags not parsed in comments\n  succeed('<!--{{foo}}-->', Comment(\"{{foo}}\"));\n  succeed('<!--{{foo-->', Comment(\"{{foo\"));\n\n  succeed('&am{{foo}}p;', ['&am', TemplateTag({stuff: 'foo'}), 'p;']);\n\n  // can't start a mustache and not finish it\n  fatal('{{foo');\n  fatal('<a>{{</a>');\n\n  // no mustache allowed in tag name\n  fatal('<{{a}}>');\n  fatal('<{{a}}b>');\n  fatal('<a{{b}}>');\n\n  // single curly brace is no biggie\n  succeed('a{b', 'a{b');\n  succeed('<br x={ />', BR({x:'{'}));\n  succeed('<br x={foo} />', BR({x:'{foo}'}));\n\n  succeed('<br {{x}}>', BR(Attrs(TemplateTag({stuff: 'x'}))));\n  succeed('<br {{x}} {{y}}>', BR(Attrs(TemplateTag({stuff: 'x'}),\n                                       TemplateTag({stuff: 'y'}))));\n  succeed('<br {{x}} y>', BR(Attrs({y: ''}, TemplateTag({stuff: 'x'}))));\n  fatal('<br {{x}}y>');\n  fatal('<br {{x}}=y>');\n  succeed('<br x={{y}} z>', BR({x: TemplateTag({stuff: 'y'}), z: ''}));\n  succeed('<br x=y{{z}}w>', BR({x: ['y', TemplateTag({stuff: 'z'}), 'w']}));\n  succeed('<br x=\"y{{z}}w\">', BR({x: ['y', TemplateTag({stuff: 'z'}), 'w']}));\n  succeed('<br x=\"y {{z}}{{w}} v\">', BR({x: ['y ', TemplateTag({stuff: 'z'}),\n                                             TemplateTag({stuff: 'w'}), ' v']}));\n  // Slash is parsed as part of unquoted attribute!  This is consistent with\n  // the HTML tokenization spec.  It seems odd for some inputs but is probably\n  // for cases like `<a href=http://foo.com/>` or `<a href=/foo/>`.\n  succeed('<br x={{y}}/>', BR({x: [TemplateTag({stuff: 'y'}), '/']}));\n  succeed('<br x={{z}}{{w}}>', BR({x: [TemplateTag({stuff: 'z'}),\n                                       TemplateTag({stuff: 'w'})]}));\n  fatal('<br x=\"y\"{{z}}>');\n\n  succeed('<br x=&amp;>', BR({x:CharRef({html: '&amp;', str: '&'})}));\n\n\n  // check tokenization of stache tags with spaces\n  succeed('<br {{x 1}}>', BR(Attrs(TemplateTag({stuff: 'x 1'}))));\n  succeed('<br {{x 1}} {{y 2}}>', BR(Attrs(TemplateTag({stuff: 'x 1'}),\n                                           TemplateTag({stuff: 'y 2'}))));\n  succeed('<br {{x 1}} y>', BR(Attrs({y:''}, TemplateTag({stuff: 'x 1'}))));\n  fatal('<br {{x 1}}y>');\n  fatal('<br {{x 1}}=y>');\n  succeed('<br x={{y 2}} z>', BR({x: TemplateTag({stuff: 'y 2'}), z: ''}));\n  succeed('<br x=y{{z 3}}w>', BR({x: ['y', TemplateTag({stuff: 'z 3'}), 'w']}));\n  succeed('<br x=\"y{{z 3}}w\">', BR({x: ['y', TemplateTag({stuff: 'z 3'}), 'w']}));\n  succeed('<br x=\"y {{z 3}}{{w 4}} v\">', BR({x: ['y ', TemplateTag({stuff: 'z 3'}),\n                                                 TemplateTag({stuff: 'w 4'}), ' v']}));\n  succeed('<br x={{y 2}}/>', BR({x: [TemplateTag({stuff: 'y 2'}), '/']}));\n  succeed('<br x={{z 3}}{{w 4}}>', BR({x: [TemplateTag({stuff: 'z 3'}),\n                                           TemplateTag({stuff: 'w 4'})]}));\n\n  succeed('<p></p>', P());\n\n  succeed('x{{foo}}{{bar}}y', ['x', TemplateTag({stuff: 'foo'}),\n                               TemplateTag({stuff: 'bar'}), 'y']);\n  succeed('x{{!foo}}{{!bar}}y', 'xy');\n  succeed('x{{!foo}}{{bar}}y', ['x', TemplateTag({stuff: 'bar'}), 'y']);\n  succeed('x{{foo}}{{!bar}}y', ['x', TemplateTag({stuff: 'foo'}), 'y']);\n  succeed('<div>{{!foo}}{{!bar}}</div>', DIV());\n  succeed('<div>{{!foo}}<br />{{!bar}}</div>', DIV(BR()));\n  succeed('<div> {{!foo}} {{!bar}} </div>', DIV(\"   \"));\n  succeed('<div> {{!foo}} <br /> {{!bar}}</div>', DIV(\"  \", BR(), \" \"));\n  succeed('{{! <div></div> }}', null);\n  succeed('{{!<div></div>}}', null);\n\n  succeed('', null);\n  succeed('{{!foo}}', null);\n\n  succeed('<textarea {{a}} x=1 {{b}}></textarea>',\n          TEXTAREA(Attrs({x:\"1\"}, TemplateTag({stuff: 'a'}),\n                         TemplateTag({stuff: 'b'}))));\n\n});\n"
  },
  {
    "path": "packages/html-tools/scanner.js",
    "content": "// This is a Scanner class suitable for any parser/lexer/tokenizer.\n//\n// A Scanner has an immutable source document (string) `input` and a current\n// position `pos`, an index into the string, which can be set at will.\n//\n// * `new Scanner(input)` - constructs a Scanner with source string `input`\n// * `scanner.rest()` - returns the rest of the input after `pos`\n// * `scanner.peek()` - returns the character at `pos`\n// * `scanner.isEOF()` - true if `pos` is at or beyond the end of `input`\n// * `scanner.fatal(msg)` - throw an error indicating a problem at `pos`\n\nScanner = HTMLTools.Scanner = function (input) {\n  this.input = input; // public, read-only\n  this.pos = 0; // public, read-write\n};\n\nScanner.prototype.rest = function () {\n  // Slicing a string is O(1) in modern JavaScript VMs (including old IE).\n  return this.input.slice(this.pos);\n};\n\nScanner.prototype.isEOF = function () {\n  return this.pos >= this.input.length;\n};\n\nScanner.prototype.fatal = function (msg) {\n  // despite this default, you should always provide a message!\n  msg = (msg || \"Parse error\");\n\n  var CONTEXT_AMOUNT = 20;\n\n  var input = this.input;\n  var pos = this.pos;\n  var pastInput = input.substring(pos - CONTEXT_AMOUNT - 1, pos);\n  if (pastInput.length > CONTEXT_AMOUNT)\n    pastInput = '...' + pastInput.substring(-CONTEXT_AMOUNT);\n\n  var upcomingInput = input.substring(pos, pos + CONTEXT_AMOUNT + 1);\n  if (upcomingInput.length > CONTEXT_AMOUNT)\n    upcomingInput = upcomingInput.substring(0, CONTEXT_AMOUNT) + '...';\n\n  var positionDisplay = ((pastInput + upcomingInput).replace(/\\n/g, ' ') + '\\n' +\n                         (new Array(pastInput.length + 1).join(' ')) + \"^\");\n\n  var e = new Error(msg + \"\\n\" + positionDisplay);\n\n  e.offset = pos;\n  var allPastInput = input.substring(0, pos);\n  e.line = (1 + (allPastInput.match(/\\n/g) || []).length);\n  e.col = (1 + pos - allPastInput.lastIndexOf('\\n'));\n  e.scanner = this;\n\n  throw e;\n};\n\n// Peek at the next character.\n//\n// If `isEOF`, returns an empty string.\nScanner.prototype.peek = function () {\n  return this.input.charAt(this.pos);\n};\n\n// Constructs a `getFoo` function where `foo` is specified with a regex.\n// The regex should start with `^`.  The constructed function will return\n// match group 1, if it exists and matches a non-empty string, or else\n// the entire matched string (or null if there is no match).\n//\n// A `getFoo` function tries to match and consume a foo.  If it succeeds,\n// the current position of the scanner is advanced.  If it fails, the\n// current position is not advanced and a falsy value (typically null)\n// is returned.\nmakeRegexMatcher = function (regex) {\n  return function (scanner) {\n    var match = regex.exec(scanner.rest());\n\n    if (! match)\n      return null;\n\n    scanner.pos += match[0].length;\n    return match[1] || match[0];\n  };\n};\n"
  },
  {
    "path": "packages/html-tools/templatetag.js",
    "content": "// _assign is like _.extend or the upcoming Object.assign.\n// Copy src's own, enumerable properties onto tgt and return\n// tgt.\nvar _hasOwnProperty = Object.prototype.hasOwnProperty;\nvar _assign = function (tgt, src) {\n  for (var k in src) {\n    if (_hasOwnProperty.call(src, k))\n      tgt[k] = src[k];\n  }\n  return tgt;\n};\n\n\nHTMLTools.TemplateTag = function (props) {\n  if (! (this instanceof HTMLTools.TemplateTag))\n    // called without `new`\n    return new HTMLTools.TemplateTag;\n\n  if (props)\n    _assign(this, props);\n};\n\n_assign(HTMLTools.TemplateTag.prototype, {\n  constructorName: 'HTMLTools.TemplateTag',\n  toJS: function (visitor) {\n    return visitor.generateCall(this.constructorName,\n                                _assign({}, this));\n  }\n});\n"
  },
  {
    "path": "packages/html-tools/tokenize.js",
    "content": "// Token types:\n//\n// { t: 'Doctype',\n//   v: String (entire Doctype declaration from the source),\n//   name: String,\n//   systemId: String (optional),\n//   publicId: String (optional)\n// }\n//\n// { t: 'Comment',\n//   v: String (not including \"<!--\" and \"-->\")\n// }\n//\n// { t: 'Chars',\n//   v: String (pure text like you might pass to document.createTextNode,\n//              no character references)\n// }\n//\n// { t: 'Tag',\n//   isEnd: Boolean (optional),\n//   isSelfClosing: Boolean (optional),\n//   n: String (tag name, in lowercase or camel case),\n//   attrs: dictionary of { String: [tokens] }\n//          OR [{ String: [tokens] }, TemplateTag tokens...]\n//     (only for start tags; required)\n// }\n//\n// { t: 'CharRef',\n//   v: String (entire character reference from the source, e.g. \"&amp;\"),\n//   cp: [Integer] (array of Unicode code point numbers it expands to)\n// }\n//\n// We keep around both the original form of the character reference and its\n// expansion so that subsequent processing steps have the option to\n// re-emit it (if they are generating HTML) or interpret it.  Named and\n// numerical code points may be more than 16 bits, in which case they\n// need to passed through codePointToString to make a JavaScript string.\n// Most named entities and all numeric character references are one codepoint\n// (e.g. \"&amp;\" is [38]), but a few are two codepoints.\n//\n// { t: 'TemplateTag',\n//   v: HTMLTools.TemplateTag\n// }\n\n// The HTML tokenization spec says to preprocess the input stream to replace\n// CR(LF)? with LF.  However, preprocessing `scanner` would complicate things\n// by making indexes not match the input (e.g. for error messages), so we just\n// keep in mind as we go along that an LF might be represented by CRLF or CR.\n// In most cases, it doesn't actually matter what combination of whitespace\n// characters are present (e.g. inside tags).\nvar HTML_SPACE = /^[\\f\\n\\r\\t ]/;\n\nvar convertCRLF = function (str) {\n  return str.replace(/\\r\\n?/g, '\\n');\n};\n\ngetComment = HTMLTools.Parse.getComment = function (scanner) {\n  if (scanner.rest().slice(0, 4) !== '<!--')\n    return null;\n  scanner.pos += 4;\n\n  // Valid comments are easy to parse; they end at the first `--`!\n  // Our main job is throwing errors.\n\n  var rest = scanner.rest();\n  if (rest.charAt(0) === '>' || rest.slice(0, 2) === '->')\n    scanner.fatal(\"HTML comment can't start with > or ->\");\n\n  var closePos = rest.indexOf('-->');\n  if (closePos < 0)\n    scanner.fatal(\"Unclosed HTML comment\");\n\n  var commentContents = rest.slice(0, closePos);\n  if (commentContents.slice(-1) === '-')\n    scanner.fatal(\"HTML comment must end at first `--`\");\n  if (commentContents.indexOf(\"--\") >= 0)\n    scanner.fatal(\"HTML comment cannot contain `--` anywhere\");\n  if (commentContents.indexOf('\\u0000') >= 0)\n    scanner.fatal(\"HTML comment cannot contain NULL\");\n\n  scanner.pos += closePos + 3;\n\n  return { t: 'Comment',\n           v: convertCRLF(commentContents) };\n};\n\nvar skipSpaces = function (scanner) {\n  while (HTML_SPACE.test(scanner.peek()))\n    scanner.pos++;\n};\n\nvar requireSpaces = function (scanner) {\n  if (! HTML_SPACE.test(scanner.peek()))\n    scanner.fatal(\"Expected space\");\n  skipSpaces(scanner);\n};\n\nvar getDoctypeQuotedString = function (scanner) {\n  var quote = scanner.peek();\n  if (! (quote === '\"' || quote === \"'\"))\n    scanner.fatal(\"Expected single or double quote in DOCTYPE\");\n  scanner.pos++;\n\n  if (scanner.peek() === quote)\n    // prevent a falsy return value (empty string)\n    scanner.fatal(\"Malformed DOCTYPE\");\n\n  var str = '';\n  var ch;\n  while ((ch = scanner.peek()), ch !== quote) {\n    if ((! ch) || (ch === '\\u0000') || (ch === '>'))\n      scanner.fatal(\"Malformed DOCTYPE\");\n    str += ch;\n    scanner.pos++;\n  }\n\n  scanner.pos++;\n\n  return str;\n};\n\n// See http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html#the-doctype.\n//\n// If `getDocType` sees \"<!DOCTYPE\" (case-insensitive), it will match or fail fatally.\ngetDoctype = HTMLTools.Parse.getDoctype = function (scanner) {\n  if (HTMLTools.asciiLowerCase(scanner.rest().slice(0, 9)) !== '<!doctype')\n    return null;\n  var start = scanner.pos;\n  scanner.pos += 9;\n\n  requireSpaces(scanner);\n\n  var ch = scanner.peek();\n  if ((! ch) || (ch === '>') || (ch === '\\u0000'))\n    scanner.fatal('Malformed DOCTYPE');\n  var name = ch;\n  scanner.pos++;\n\n  while ((ch = scanner.peek()), ! (HTML_SPACE.test(ch) || ch === '>')) {\n    if ((! ch) || (ch === '\\u0000'))\n      scanner.fatal('Malformed DOCTYPE');\n    name += ch;\n    scanner.pos++;\n  }\n  name = HTMLTools.asciiLowerCase(name);\n\n  // Now we're looking at a space or a `>`.\n  skipSpaces(scanner);\n\n  var systemId = null;\n  var publicId = null;\n\n  if (scanner.peek() !== '>') {\n    // Now we're essentially in the \"After DOCTYPE name state\" of the tokenizer,\n    // but we're not looking at space or `>`.\n\n    // this should be \"public\" or \"system\".\n    var publicOrSystem = HTMLTools.asciiLowerCase(scanner.rest().slice(0, 6));\n\n    if (publicOrSystem === 'system') {\n      scanner.pos += 6;\n      requireSpaces(scanner);\n      systemId = getDoctypeQuotedString(scanner);\n      skipSpaces(scanner);\n      if (scanner.peek() !== '>')\n        scanner.fatal(\"Malformed DOCTYPE\");\n    } else if (publicOrSystem === 'public') {\n      scanner.pos += 6;\n      requireSpaces(scanner);\n      publicId = getDoctypeQuotedString(scanner);\n      if (scanner.peek() !== '>') {\n        requireSpaces(scanner);\n        if (scanner.peek() !== '>') {\n          systemId = getDoctypeQuotedString(scanner);\n          skipSpaces(scanner);\n          if (scanner.peek() !== '>')\n            scanner.fatal(\"Malformed DOCTYPE\");\n        }\n      }\n    } else {\n      scanner.fatal(\"Expected PUBLIC or SYSTEM in DOCTYPE\");\n    }\n  }\n\n  // looking at `>`\n  scanner.pos++;\n  var result = { t: 'Doctype',\n                 v: scanner.input.slice(start, scanner.pos),\n                 name: name };\n\n  if (systemId)\n    result.systemId = systemId;\n  if (publicId)\n    result.publicId = publicId;\n\n  return result;\n};\n\n// The special character `{` is only allowed as the first character\n// of a Chars, so that we have a chance to detect template tags.\nvar getChars = makeRegexMatcher(/^[^&<\\u0000][^&<\\u0000{]*/);\n\nvar assertIsTemplateTag = function (x) {\n  if (! (x instanceof HTMLTools.TemplateTag))\n    throw new Error(\"Expected an instance of HTMLTools.TemplateTag\");\n  return x;\n};\n\n// Returns the next HTML token, or `null` if we reach EOF.\n//\n// Note that if we have a `getTemplateTag` function that sometimes\n// consumes characters and emits nothing (e.g. in the case of template\n// comments), we may go from not-at-EOF to at-EOF and return `null`,\n// while otherwise we always find some token to return.\ngetHTMLToken = HTMLTools.Parse.getHTMLToken = function (scanner, dataMode) {\n  var result = null;\n  if (scanner.getTemplateTag) {\n    // Try to parse a template tag by calling out to the provided\n    // `getTemplateTag` function.  If the function returns `null` but\n    // consumes characters, it must have parsed a comment or something,\n    // so we loop and try it again.  If it ever returns `null` without\n    // consuming anything, that means it didn't see anything interesting\n    // so we look for a normal token.  If it returns a truthy value,\n    // the value must be instanceof HTMLTools.TemplateTag.  We wrap it\n    // in a Special token.\n    var lastPos = scanner.pos;\n    result = scanner.getTemplateTag(\n      scanner,\n      (dataMode === 'rcdata' ? TEMPLATE_TAG_POSITION.IN_RCDATA :\n       (dataMode === 'rawtext' ? TEMPLATE_TAG_POSITION.IN_RAWTEXT :\n        TEMPLATE_TAG_POSITION.ELEMENT)));\n\n    if (result)\n      return { t: 'TemplateTag', v: assertIsTemplateTag(result) };\n    else if (scanner.pos > lastPos)\n      return null;\n  }\n\n  var chars = getChars(scanner);\n  if (chars)\n    return { t: 'Chars',\n             v: convertCRLF(chars) };\n\n  var ch = scanner.peek();\n  if (! ch)\n    return null; // EOF\n\n  if (ch === '\\u0000')\n    scanner.fatal(\"Illegal NULL character\");\n\n  if (ch === '&') {\n    if (dataMode !== 'rawtext') {\n      var charRef = getCharacterReference(scanner);\n      if (charRef)\n        return charRef;\n    }\n\n    scanner.pos++;\n    return { t: 'Chars',\n             v: '&' };\n  }\n\n  // If we're here, we're looking at `<`.\n\n  if (scanner.peek() === '<' && dataMode) {\n    // don't interpret tags\n    scanner.pos++;\n    return { t: 'Chars',\n             v: '<' };\n  }\n\n  // `getTag` will claim anything starting with `<` not followed by `!`.\n  // `getComment` takes `<!--` and getDoctype takes `<!doctype`.\n  result = (getTagToken(scanner) || getComment(scanner) || getDoctype(scanner));\n\n  if (result)\n    return result;\n\n  scanner.fatal(\"Unexpected `<!` directive.\");\n};\n\nvar getTagName = makeRegexMatcher(/^[a-zA-Z][^\\f\\n\\r\\t />{]*/);\nvar getClangle = makeRegexMatcher(/^>/);\nvar getSlash = makeRegexMatcher(/^\\//);\nvar getAttributeName = makeRegexMatcher(/^[^>/\\u0000\"'<=\\f\\n\\r\\t ][^\\f\\n\\r\\t /=>\"'<\\u0000]*/);\n\n// Try to parse `>` or `/>`, mutating `tag` to be self-closing in the latter\n// case (and failing fatally if `/` isn't followed by `>`).\n// Return tag if successful.\nvar handleEndOfTag = function (scanner, tag) {\n  if (getClangle(scanner))\n    return tag;\n\n  if (getSlash(scanner)) {\n    if (! getClangle(scanner))\n      scanner.fatal(\"Expected `>` after `/`\");\n    tag.isSelfClosing = true;\n    return tag;\n  }\n\n  return null;\n};\n\n// Scan a quoted or unquoted attribute value (omit `quote` for unquoted).\nvar getAttributeValue = function (scanner, quote) {\n  if (quote) {\n    if (scanner.peek() !== quote)\n      return null;\n    scanner.pos++;\n  }\n\n  var tokens = [];\n  var charsTokenToExtend = null;\n\n  var charRef;\n  while (true) {\n    var ch = scanner.peek();\n    var templateTag;\n    var curPos = scanner.pos;\n    if (quote && ch === quote) {\n      scanner.pos++;\n      return tokens;\n    } else if ((! quote) && (HTML_SPACE.test(ch) || ch === '>')) {\n      return tokens;\n    } else if (! ch) {\n      scanner.fatal(\"Unclosed attribute in tag\");\n    } else if (quote ? ch === '\\u0000' : ('\\u0000\"\\'<=`'.indexOf(ch) >= 0)) {\n      scanner.fatal(\"Unexpected character in attribute value\");\n    } else if (ch === '&' &&\n               (charRef = getCharacterReference(scanner, true,\n                                                quote || '>'))) {\n      tokens.push(charRef);\n      charsTokenToExtend = null;\n    } else if (scanner.getTemplateTag &&\n               ((templateTag = scanner.getTemplateTag(\n                 scanner, TEMPLATE_TAG_POSITION.IN_ATTRIBUTE)) ||\n                scanner.pos > curPos /* `{{! comment}}` */)) {\n      if (templateTag) {\n        tokens.push({t: 'TemplateTag',\n                     v: assertIsTemplateTag(templateTag)});\n        charsTokenToExtend = null;\n      }\n    } else {\n      if (! charsTokenToExtend) {\n        charsTokenToExtend = { t: 'Chars', v: '' };\n        tokens.push(charsTokenToExtend);\n      }\n      charsTokenToExtend.v += (ch === '\\r' ? '\\n' : ch);\n      scanner.pos++;\n      if (quote && ch === '\\r' && scanner.peek() === '\\n')\n        scanner.pos++;\n    }\n  }\n};\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\ngetTagToken = HTMLTools.Parse.getTagToken = function (scanner) {\n  if (! (scanner.peek() === '<' && scanner.rest().charAt(1) !== '!'))\n    return null;\n  scanner.pos++;\n\n  var tag = { t: 'Tag' };\n\n  // now looking at the character after `<`, which is not a `!`\n  if (scanner.peek() === '/') {\n    tag.isEnd = true;\n    scanner.pos++;\n  }\n\n  var tagName = getTagName(scanner);\n  if (! tagName)\n    scanner.fatal(\"Expected tag name after `<`\");\n  tag.n = HTMLTools.properCaseTagName(tagName);\n\n  if (scanner.peek() === '/' && tag.isEnd)\n    scanner.fatal(\"End tag can't have trailing slash\");\n  if (handleEndOfTag(scanner, tag))\n    return tag;\n\n  if (scanner.isEOF())\n    scanner.fatal(\"Unclosed `<`\");\n\n  if (! HTML_SPACE.test(scanner.peek()))\n    // e.g. `<a{{b}}>`\n    scanner.fatal(\"Expected space after tag name\");\n\n  // we're now in \"Before attribute name state\" of the tokenizer\n  skipSpaces(scanner);\n\n  if (scanner.peek() === '/' && tag.isEnd)\n    scanner.fatal(\"End tag can't have trailing slash\");\n  if (handleEndOfTag(scanner, tag))\n    return tag;\n\n  if (tag.isEnd)\n    scanner.fatal(\"End tag can't have attributes\");\n\n  tag.attrs = {};\n  var nondynamicAttrs = tag.attrs;\n\n  while (true) {\n    // Note: at the top of this loop, we've already skipped any spaces.\n\n    // This will be set to true if after parsing the attribute, we should\n    // require spaces (or else an end of tag, i.e. `>` or `/>`).\n    var spacesRequiredAfter = false;\n\n    // first, try for a template tag.\n    var curPos = scanner.pos;\n    var templateTag = (scanner.getTemplateTag &&\n                       scanner.getTemplateTag(\n                         scanner, TEMPLATE_TAG_POSITION.IN_START_TAG));\n    if (templateTag || (scanner.pos > curPos)) {\n      if (templateTag) {\n        if (tag.attrs === nondynamicAttrs)\n          tag.attrs = [nondynamicAttrs];\n        tag.attrs.push({ t: 'TemplateTag',\n                         v: assertIsTemplateTag(templateTag) });\n      } // else, must have scanned a `{{! comment}}`\n\n      spacesRequiredAfter = true;\n    } else {\n\n      var attributeName = getAttributeName(scanner);\n      if (! attributeName)\n        scanner.fatal(\"Expected attribute name in tag\");\n      // Throw error on `{` in attribute name.  This provides *some* error message\n      // if someone writes `<a x{{y}}>` or `<a x{{y}}=z>`.  The HTML tokenization\n      // spec doesn't say that `{` is invalid, but the DOM API (setAttribute) won't\n      // allow it, so who cares.\n      if (attributeName.indexOf('{') >= 0)\n        scanner.fatal(\"Unexpected `{` in attribute name.\");\n      attributeName = HTMLTools.properCaseAttributeName(attributeName);\n\n      if (hasOwnProperty.call(nondynamicAttrs, attributeName))\n        scanner.fatal(\"Duplicate attribute in tag: \" + attributeName);\n\n      nondynamicAttrs[attributeName] = [];\n\n      skipSpaces(scanner);\n\n      if (handleEndOfTag(scanner, tag))\n        return tag;\n\n      var ch = scanner.peek();\n      if (! ch)\n        scanner.fatal(\"Unclosed <\");\n      if ('\\u0000\"\\'<'.indexOf(ch) >= 0)\n        scanner.fatal(\"Unexpected character after attribute name in tag\");\n\n      if (ch === '=') {\n        scanner.pos++;\n\n        skipSpaces(scanner);\n\n        ch = scanner.peek();\n        if (! ch)\n          scanner.fatal(\"Unclosed <\");\n        if ('\\u0000><=`'.indexOf(ch) >= 0)\n          scanner.fatal(\"Unexpected character after = in tag\");\n\n        if ((ch === '\"') || (ch === \"'\"))\n          nondynamicAttrs[attributeName] = getAttributeValue(scanner, ch);\n        else\n          nondynamicAttrs[attributeName] = getAttributeValue(scanner);\n\n        spacesRequiredAfter = true;\n      }\n    }\n    // now we are in the \"post-attribute\" position, whether it was a template tag\n    // attribute (like `{{x}}`) or a normal one (like `x` or `x=y`).\n\n    if (handleEndOfTag(scanner, tag))\n      return tag;\n\n    if (scanner.isEOF())\n      scanner.fatal(\"Unclosed `<`\");\n\n    if (spacesRequiredAfter)\n      requireSpaces(scanner);\n    else\n      skipSpaces(scanner);\n\n    if (handleEndOfTag(scanner, tag))\n      return tag;\n  }\n};\n\nTEMPLATE_TAG_POSITION = HTMLTools.TEMPLATE_TAG_POSITION = {\n  ELEMENT: 1,\n  IN_START_TAG: 2,\n  IN_ATTRIBUTE: 3,\n  IN_RCDATA: 4,\n  IN_RAWTEXT: 5\n};\n\n// tagName must be proper case\nisLookingAtEndTag = function (scanner, tagName) {\n  var rest = scanner.rest();\n  var pos = 0; // into rest\n  var firstPart = /^<\\/([a-zA-Z]+)/.exec(rest);\n  if (firstPart &&\n      HTMLTools.properCaseTagName(firstPart[1]) === tagName) {\n    // we've seen `</foo`, now see if the end tag continues\n    pos += firstPart[0].length;\n    while (pos < rest.length && HTML_SPACE.test(rest.charAt(pos)))\n      pos++;\n    if (pos < rest.length && rest.charAt(pos) === '>')\n      return true;\n  }\n  return false;\n};\n"
  },
  {
    "path": "packages/html-tools/tokenize_tests.js",
    "content": "var Scanner = HTMLTools.Scanner;\nvar getComment = HTMLTools.Parse.getComment;\nvar getDoctype = HTMLTools.Parse.getDoctype;\nvar getHTMLToken = HTMLTools.Parse.getHTMLToken;\n\n// \"tokenize\" is not really a great operation for real use, because\n// it ignores the special content rules for tags like \"style\" and\n// \"script\".\nvar tokenize = function (input) {\n  var scanner = new Scanner(input);\n  var tokens = [];\n  while (! scanner.isEOF()) {\n    var token = getHTMLToken(scanner);\n    if (token)\n      tokens.push(token);\n  }\n\n  return tokens;\n};\n\n\nTinytest.add(\"html-tools - comments\", function (test) {\n  var succeed = function (input, content) {\n    var scanner = new Scanner(input);\n    var result = getComment(scanner);\n    test.isTrue(result);\n    test.equal(scanner.pos, content.length + 7);\n    test.equal(result, {\n      t: 'Comment',\n      v: content\n    });\n  };\n\n  var ignore = function (input) {\n    var scanner = new Scanner(input);\n    var result = getComment(scanner);;\n    test.isFalse(result);\n    test.equal(scanner.pos, 0);\n  };\n\n  var fatal = function (input, messageContains) {\n    var scanner = new Scanner(input);\n    var error;\n    try {\n      getComment(scanner);\n    } catch (e) {\n      error = e;\n    }\n    test.isTrue(error);\n    if (error)\n      test.isTrue(messageContains && error.message.indexOf(messageContains) >= 0, error.message);\n  };\n\n  test.equal(getComment(new Scanner(\"<!-- hello -->\")),\n             { t: 'Comment', v: ' hello ' });\n\n  ignore(\"<!DOCTYPE>\");\n  ignore(\"<!-a\");\n  ignore(\"<--\");\n  ignore(\"<!\");\n  ignore(\"abc\");\n  ignore(\"<a\");\n\n  fatal('<!--', 'Unclosed');\n  fatal('<!---', 'Unclosed');\n  fatal('<!----', 'Unclosed');\n  fatal('<!-- -', 'Unclosed');\n  fatal('<!-- --', 'Unclosed');\n  fatal('<!-- -- abcd', 'Unclosed');\n  fatal('<!-- ->', 'Unclosed');\n  fatal('<!-- a--b -->', 'cannot contain');\n  fatal('<!--x--->', 'must end at first');\n\n  fatal('<!-- a\\u0000b -->', 'cannot contain');\n  fatal('<!--\\u0000 x-->', 'cannot contain');\n\n  succeed('<!---->', '');\n  succeed('<!---x-->', '-x');\n  succeed('<!--x-->', 'x');\n  succeed('<!-- hello - - world -->', ' hello - - world ');\n});\n\nTinytest.add(\"html-tools - doctype\", function (test) {\n  var succeed = function (input, expectedProps) {\n    var scanner = new Scanner(input);\n    var result = getDoctype(scanner);\n    test.isTrue(result);\n    test.equal(scanner.pos, result.v.length);\n    test.equal(input.slice(0, result.v.length), result.v);\n    var actualProps = _.extend({}, result);\n    delete actualProps.t;\n    delete actualProps.v;\n    test.equal(actualProps, expectedProps);\n  };\n\n  var fatal = function (input, messageContains) {\n    var scanner = new Scanner(input);\n    var error;\n    try {\n      getDoctype(scanner);\n    } catch (e) {\n      error = e;\n    }\n    test.isTrue(error);\n    if (messageContains)\n      test.isTrue(error.message.indexOf(messageContains) >= 0, error.message);\n  };\n\n  test.equal(getDoctype(new Scanner(\"<!DOCTYPE html>x\")),\n             { t: 'Doctype',\n               v: '<!DOCTYPE html>',\n               name: 'html' });\n\n  test.equal(getDoctype(new Scanner(\"<!DOCTYPE html SYSTEM 'about:legacy-compat'>x\")),\n             { t: 'Doctype',\n               v: \"<!DOCTYPE html SYSTEM 'about:legacy-compat'>\",\n               name: 'html',\n               systemId: 'about:legacy-compat' });\n\n  test.equal(getDoctype(new Scanner(\"<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.0//EN'>x\")),\n             { t: 'Doctype',\n               v: \"<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.0//EN'>\",\n               name: 'html',\n               publicId: '-//W3C//DTD HTML 4.0//EN' });\n\n  test.equal(getDoctype(new Scanner(\"<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.0//EN' 'http://www.w3.org/TR/html4/strict.dtd'>x\")),\n             { t: 'Doctype',\n               v: \"<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.0//EN' 'http://www.w3.org/TR/html4/strict.dtd'>\",\n               name: 'html',\n               publicId: '-//W3C//DTD HTML 4.0//EN',\n               systemId: 'http://www.w3.org/TR/html4/strict.dtd' });\n\n  succeed('<!DOCTYPE html>', {name: 'html'});\n  succeed('<!DOCTYPE htML>', {name: 'html'});\n  succeed('<!DOCTYPE HTML>', {name: 'html'});\n  succeed('<!doctype html>', {name: 'html'});\n  succeed('<!doctYPE html>', {name: 'html'});\n  succeed('<!DOCTYPE html \\u000c>', {name: 'html'});\n  fatal('<!DOCTYPE', 'Expected space');\n  fatal('<!DOCTYPE ', 'Malformed DOCTYPE');\n  fatal('<!DOCTYPE  ', 'Malformed DOCTYPE');\n  fatal('<!DOCTYPE>', 'Expected space');\n  fatal('<!DOCTYPE >', 'Malformed DOCTYPE');\n  fatal('<!DOCTYPE\\u0000', 'Expected space');\n  fatal('<!DOCTYPE \\u0000', 'Malformed DOCTYPE');\n  fatal('<!DOCTYPE html\\u0000>', 'Malformed DOCTYPE');\n  fatal('<!DOCTYPE html', 'Malformed DOCTYPE');\n\n  succeed('<!DOCTYPE html SYSTEM \"about:legacy-compat\">', {name: 'html', systemId: 'about:legacy-compat'});\n  succeed('<!doctype HTML system \"about:legacy-compat\">', {name: 'html', systemId: 'about:legacy-compat'});\n  succeed(\"<!DOCTYPE html SYSTEM 'about:legacy-compat'>\", {name: 'html', systemId: 'about:legacy-compat'});\n  succeed(\"<!dOcTyPe HtMl sYsTeM 'about:legacy-compat'>\", {name: 'html', systemId: 'about:legacy-compat'});\n  succeed('<!DOCTYPE  html\\tSYSTEM\\t\"about:legacy-compat\"   \\t>', {name: 'html', systemId: 'about:legacy-compat'});\n  fatal('<!DOCTYPE html SYSTE \"about:legacy-compat\">', 'Expected PUBLIC or SYSTEM');\n  fatal('<!DOCTYPE html SYSTE', 'Expected PUBLIC or SYSTEM');\n  fatal('<!DOCTYPE html SYSTEM\"about:legacy-compat\">', 'Expected space');\n  fatal('<!DOCTYPE html SYSTEM');\n  fatal('<!DOCTYPE html SYSTEM ');\n  fatal('<!DOCTYPE html SYSTEM>');\n  fatal('<!DOCTYPE html SYSTEM >');\n  fatal('<!DOCTYPE html SYSTEM \">\">');\n  fatal('<!DOCTYPE html SYSTEM \"\\u0000about:legacy-compat\">');\n  fatal('<!DOCTYPE html SYSTEM \"about:legacy-compat\\u0000\">');\n  fatal('<!DOCTYPE html SYSTEM \"');\n  fatal('<!DOCTYPE html SYSTEM \"\">');\n  fatal('<!DOCTYPE html SYSTEM \\'');\n  fatal('<!DOCTYPE html SYSTEM\\'a\\'>');\n  fatal('<!DOCTYPE html SYSTEM about:legacy-compat>');\n\n  succeed('<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0//EN\">',\n          { name: 'html',\n            publicId: '-//W3C//DTD HTML 4.0//EN'});\n  succeed('<!DOCTYPE html PUBLIC \\'-//W3C//DTD HTML 4.0//EN\\'>',\n          { name: 'html',\n            publicId: '-//W3C//DTD HTML 4.0//EN'});\n  succeed('<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">',\n          { name: 'html',\n            publicId: '-//W3C//DTD HTML 4.0//EN',\n            systemId: 'http://www.w3.org/TR/REC-html40/strict.dtd'});\n  succeed('<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \\'http://www.w3.org/TR/REC-html40/strict.dtd\\'>',\n          { name: 'html',\n            publicId: '-//W3C//DTD HTML 4.0//EN',\n            systemId: 'http://www.w3.org/TR/REC-html40/strict.dtd'});\n  succeed('<!DOCTYPE html public \\'-//W3C//DTD HTML 4.0//EN\\' \\'http://www.w3.org/TR/REC-html40/strict.dtd\\'>',\n          { name: 'html',\n            publicId: '-//W3C//DTD HTML 4.0//EN',\n            systemId: 'http://www.w3.org/TR/REC-html40/strict.dtd'});\n  succeed('<!DOCTYPE html public \\'-//W3C//DTD HTML 4.0//EN\\'\\t\\'http://www.w3.org/TR/REC-html40/strict.dtd\\'   >',\n          { name: 'html',\n            publicId: '-//W3C//DTD HTML 4.0//EN',\n            systemId: 'http://www.w3.org/TR/REC-html40/strict.dtd'});\n  fatal('<!DOCTYPE html public \\'-//W3C//DTD HTML 4.0//EN\\' \\'http://www.w3.org/TR/REC-html40/strict.dtd\\'');\n  fatal('<!DOCTYPE html public \\'-//W3C//DTD HTML 4.0//EN\\' \\'http://www.w3.org/TR/REC-html40/strict.dtd\\'');\n  fatal('<!DOCTYPE html public \\'-//W3C//DTD HTML 4.0//EN\\' \\'http://www.w3.org/TR/REC-html40/strict.dtd');\n  fatal('<!DOCTYPE html public \\'-//W3C//DTD HTML 4.0//EN\\' \\'');\n  fatal('<!DOCTYPE html public \\'-//W3C//DTD HTML 4.0//EN\\' ');\n  fatal('<!DOCTYPE html public \\'- ');\n  fatal('<!DOCTYPE html public>');\n  fatal('<!DOCTYPE html public \"-//W3C//DTD HTML 4.0//EN\"\"http://www.w3.org/TR/REC-html40/strict.dtd\">');\n});\n\nTinytest.add(\"html-tools - tokenize\", function (test) {\n\n  var fatal = function (input, messageContains) {\n    var error;\n    try {\n      tokenize(input);\n    } catch (e) {\n      error = e;\n    }\n    test.isTrue(error);\n    if (messageContains)\n      test.isTrue(error.message.indexOf(messageContains) >= 0, error.message);\n  };\n\n\n  test.equal(tokenize(''), []);\n  test.equal(tokenize('abc'), [{t: 'Chars', v: 'abc'}]);\n  test.equal(tokenize('&'), [{t: 'Chars', v: '&'}]);\n  test.equal(tokenize('&amp;'), [{t: 'CharRef', v: '&amp;', cp: [38]}]);\n  test.equal(tokenize('ok&#32;fine'),\n             [{t: 'Chars', v: 'ok'},\n              {t: 'CharRef', v: '&#32;', cp: [32]},\n              {t: 'Chars', v: 'fine'}]);\n\n  test.equal(tokenize('a<!--b-->c'),\n             [{t: 'Chars',\n               v: 'a'},\n              {t: 'Comment',\n               v: 'b'},\n              {t: 'Chars',\n               v: 'c'}]);\n\n  test.equal(tokenize('<a>'), [{t: 'Tag', n: 'a'}]);\n\n  fatal('<');\n  fatal('<x');\n  fatal('<x ');\n  fatal('<x a');\n  fatal('<x a ');\n  fatal('<x a =');\n  fatal('<x a = ');\n  fatal('<x a = b');\n  fatal('<x a = \"b');\n  fatal('<x a = \\'b');\n  fatal('<x a = b ');\n  fatal('<x a = b /');\n  test.equal(tokenize('<x a = b />'),\n             [{t: 'Tag', n: 'x',\n               attrs: { a: [{t: 'Chars', v: 'b'}] },\n               isSelfClosing: true}]);\n\n  test.equal(tokenize('<a>X</a>'),\n             [{t: 'Tag', n: 'a'},\n              {t: 'Chars', v: 'X'},\n              {t: 'Tag', n: 'a', isEnd: true}]);\n\n  fatal('<x a a>'); // duplicate attribute value\n  test.equal(tokenize('<a b  >'),\n             [{t: 'Tag', n: 'a', attrs: { b: [] }}]);\n  fatal('< a>');\n  fatal('< /a>');\n  fatal('</ a>');\n\n  // Slash does not end an unquoted attribute, interestingly\n  test.equal(tokenize('<a b=/>'),\n             [{t: 'Tag', n: 'a', attrs: { b: [{t: 'Chars', v: '/'}] }}]);\n\n  test.equal(tokenize('<a b=\"c\" d=e f=\\'g\\' h \\t>'),\n             [{t: 'Tag', n: 'a',\n               attrs: { b: [{t: 'Chars', v: 'c'}],\n                        d: [{t: 'Chars', v: 'e'}],\n                        f: [{t: 'Chars', v: 'g'}],\n                        h: [] }}]);\n\n  fatal('</a b=\"c\" d=e f=\\'g\\' h \\t\\u0000>');\n  fatal('</a b=\"c\" d=ef=\\'g\\' h \\t>');\n  fatal('</a b=\"c\"d=e f=\\'g\\' h \\t>');\n\n  test.equal(tokenize('<a/>'), [{t: 'Tag', n: 'a', isSelfClosing: true}]);\n\n  fatal('<a/ >');\n  fatal('<a/b>');\n  fatal('<a b=c`>');\n  fatal('<a b=c<>');\n\n  test.equal(tokenize('<a# b0=\"c@\" d1=e2 f#=\\'g  \\' h \\t>'),\n             [{t: 'Tag', n: 'a#',\n               attrs: { b0: [{t: 'Chars', v: 'c@'}],\n                        d1: [{t: 'Chars', v: 'e2'}],\n                        'f#': [{t: 'Chars', v: 'g  '}],\n                        h: [] }}]);\n\n  test.equal(tokenize('<div class=\"\"></div>'),\n             [{t: 'Tag', n: 'div', attrs: { 'class': [] }},\n              {t: 'Tag', n: 'div', isEnd: true}]);\n\n  test.equal(tokenize('<div class=\"&\">'),\n             [{t: 'Tag', n: 'div', attrs: { 'class': [{t: 'Chars', v: '&'}] }}]);\n  test.equal(tokenize('<div class=&>'),\n             [{t: 'Tag', n: 'div', attrs: { 'class': [{t: 'Chars', v: '&'}] }}]);\n  test.equal(tokenize('<div class=&amp;>'),\n             [{t: 'Tag', n: 'div', attrs: { 'class': [{t: 'CharRef', v: '&amp;', cp: [38]}] }}]);\n\n  test.equal(tokenize('<div class=aa&&zopf;&acE;&bb>'),\n             [{t: 'Tag', n: 'div', attrs: { 'class': [\n               {t: 'Chars', v: 'aa&'},\n               {t: 'CharRef', v: '&zopf;', cp: [120171]},\n               {t: 'CharRef', v: '&acE;', cp: [8766, 819]},\n               {t: 'Chars', v: '&bb'}\n             ] }}]);\n\n  test.equal(tokenize('<div class=\"aa &&zopf;&acE;& bb\">'),\n             [{t: 'Tag', n: 'div', attrs: { 'class': [\n               {t: 'Chars', v: 'aa &'},\n               {t: 'CharRef', v: '&zopf;', cp: [120171]},\n               {t: 'CharRef', v: '&acE;', cp: [8766, 819]},\n               {t: 'Chars', v: '& bb'}\n             ] }}]);\n\n  test.equal(tokenize('<a b=\"\\'`<>&\">'),\n             [{t: 'Tag', n: 'a', attrs: { b: [{t: 'Chars', v: '\\'`<>&'}] }}]);\n  test.equal(tokenize('<a b=\\'\"`<>&\\'>'),\n             [{t: 'Tag', n: 'a', attrs: { b: [{t: 'Chars', v: '\"`<>&'}] }}]);\n\n  fatal('&gt');\n  fatal('&gtc');\n  test.equal(tokenize('<a b=&gtc>'),\n             [{t: 'Tag', n: 'a', attrs: { b: [{t: 'Chars', v: '&gtc' }] }}]);\n  test.equal(tokenize('<a b=\"&gtc\">'),\n             [{t: 'Tag', n: 'a', attrs: { b: [{t: 'Chars', v: '&gtc' }] }}]);\n  fatal('<a b=&gt>');\n  fatal('<a b=\"&gt\">');\n  fatal('<a b=\"&gt=\">');\n\n  fatal('<!');\n  fatal('<!x>');\n\n  fatal('<a{{b}}>');\n  fatal('<{{a}}>');\n  fatal('</a b=c>'); // end tag can't have attributes\n  fatal('</a/>'); // end tag can't be self-closing\n  fatal('</a  />');\n});\n"
  },
  {
    "path": "packages/html-tools/utils.js",
    "content": "\nHTMLTools = {};\nHTMLTools.Parse = {};\n\nvar asciiLowerCase = HTMLTools.asciiLowerCase = function (str) {\n  return str.replace(/[A-Z]/g, function (c) {\n    return String.fromCharCode(c.charCodeAt(0) + 32);\n  });\n};\n\nvar svgCamelCaseAttributes = 'attributeName attributeType baseFrequency baseProfile calcMode clipPathUnits contentScriptType contentStyleType diffuseConstant edgeMode externalResourcesRequired filterRes filterUnits glyphRef glyphRef gradientTransform gradientTransform gradientUnits gradientUnits kernelMatrix kernelUnitLength kernelUnitLength kernelUnitLength keyPoints keySplines keyTimes lengthAdjust limitingConeAngle markerHeight markerUnits markerWidth maskContentUnits maskUnits numOctaves pathLength patternContentUnits patternTransform patternUnits pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits refX refY repeatCount repeatDur requiredExtensions requiredFeatures specularConstant specularExponent specularExponent spreadMethod spreadMethod startOffset stdDeviation stitchTiles surfaceScale surfaceScale systemLanguage tableValues targetX targetY textLength textLength viewBox viewTarget xChannelSelector yChannelSelector zoomAndPan'.split(' ');\n\nvar properAttributeCaseMap = (function (map) {\n  for (var i = 0; i < svgCamelCaseAttributes.length; i++) {\n    var a = svgCamelCaseAttributes[i];\n    map[asciiLowerCase(a)] = a;\n  }\n  return map;\n})({});\n\nvar properTagCaseMap = (function (map) {\n  var knownElements = HTML.knownElementNames;\n  for (var i = 0; i < knownElements.length; i++) {\n    var a = knownElements[i];\n    map[asciiLowerCase(a)] = a;\n  }\n  return map;\n})({});\n\n// Take a tag name in any case and make it the proper case for HTML.\n//\n// Modern browsers let you embed SVG in HTML, but SVG elements are special\n// in that they have a case-sensitive DOM API (nodeName, getAttribute,\n// setAttribute).  For example, it has to be `setAttribute(\"viewBox\")`,\n// not `\"viewbox\"`.  However, the browser's HTML parser is NOT case sensitive\n// and will fix the case for you, so if you write `<svg viewbox=\"...\">`\n// you actually get a `\"viewBox\"` attribute.  Any HTML-parsing toolchain\n// must do the same.\nHTMLTools.properCaseTagName = function (name) {\n  var lowered = asciiLowerCase(name);\n  return properTagCaseMap.hasOwnProperty(lowered) ?\n    properTagCaseMap[lowered] : lowered;\n};\n\n// See docs for properCaseTagName.\nHTMLTools.properCaseAttributeName = function (name) {\n  var lowered = asciiLowerCase(name);\n  return properAttributeCaseMap.hasOwnProperty(lowered) ?\n    properAttributeCaseMap[lowered] : lowered;\n};\n"
  },
  {
    "path": "packages/htmljs/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/htmljs/README.md",
    "content": "# HTMLjs\n\nHTMLjs is a small library for expressing HTML trees with a concise\nsyntax.  It is used to render content in Blaze and to represent\ntemplates during compilation.\n\n```\nvar UL = HTML.UL, LI = HTML.LI, B = HTML.B;\n\nHTML.toHTML(\n  UL({id: 'mylist'},\n     LI({'class': 'item'}, \"Hello \", B(\"world\"), \"!\"),\n     LI({'class': 'item'}, \"Goodbye, world\")))\n```\n\n```\n<ul id=\"mylist\">\n  <li class=\"item\">Hello <b>world</b>!</li>\n  <li class=\"item\">Goodbye, world</li>\n</ul>\n```\n\nThe functions `UL`, `LI`, and `B` are constructors which\nreturn instances of `HTML.Tag`.  These tag objects can\nthen be converted to an HTML string or directly into DOM nodes.\n\nThe flexible structure of HTMLjs allows different kinds of Blaze\ndirectives to be embedded in the tree.  HTMLjs does not know about\nthese directives, which are considered \"foreign objects.\"\n\n# Built-in Types\n\nThe following types are built into HTMLjs.  Built-in methods like\n`HTML.toHTML` require a tree consisting only of these types.\n\n* __`null`, `undefined`__ - Render to nothing.\n\n* __boolean, number__ - Render to the string form of the boolean or number.\n\n* __string__ - Renders to a text node (or part of an attribute value).  All characters are safe, and no HTML injection is possible.  The string `\"<a>\"` renders `&lt;a>` in HTML, and `document.createTextNode(\"<a>\")` in DOM.\n\n* __Array__ - Renders to its elements in order.  An array may be empty.  Arrays are detected using `HTML.isArray(...)`.\n\n* __`HTML.Tag`__ - Renders to an HTML element (including start tag, contents, and end tag).\n\n* __`HTML.CharRef({html: ..., str: ...})`__ - Renders to a character reference (such as `&nbsp`) when generating HTML.\n\n* __`HTML.Comment(text)`__ - Renders to an HTML comment.\n\n* __`HTML.Raw(html)`__ - Renders to a string of HTML to include verbatim.\n\nThe `new` keyword is not required before constructors of HTML object types.\n\nAll objects and arrays should be considered immutable.  Instance properties\nare public, but they should only be read, not written.  Arrays should not\nbe spliced in place.  This convention allows for clean patterns of\nprocessing and transforming HTMLjs trees.\n\n\n## HTML.Tag\n\nAn `HTML.Tag` is created using a tag-specific constructor, like\n`HTML.P` for a `<p>` tag or `HTML.INPUT` for an `<input>` tag.  The\nresulting object is `instanceof HTML.Tag`.  (The `HTML.Tag`\nconstructor should not be called directly.)\n\nTag constructors take an optional attributes dictionary followed\nby zero or more children:\n\n```\nHTML.HR()\n\nHTML.DIV(HTML.P(\"First paragraph\"),\n         HTML.P(\"Second paragraph\"))\n\nHTML.INPUT({type: \"text\"})\n\nHTML.SPAN({'class': \"foo\"}, \"Some text\")\n```\n\n### Instance properties\n\nTags have the following properties:\n\n* `tagName` - The tag name in lowercase (or camelCase)\n* `children` - An array of children (always present)\n* `attrs` - An attributes dictionary, `null`, or an array (see below)\n\n\n### Special forms of attributes\n\nThe attributes of a Tag may be an array of dictionaries.  In order\nfor a tag constructor to recognize an array as the attributes argument,\nit must be written as `HTML.Attrs(attrs1, attrs2, ...)`, as in this\nexample:\n\n```\nvar extraAttrs = {'class': \"container\"};\n\nvar div = HTML.DIV(HTML.Attrs({id: \"main\"}, extraAttrs),\n                   \"This is the content.\");\n\ndiv.attrs // => [{id: \"main\"}, {'class': \"container\"}]\n```\n\n`HTML.Attrs` may also be used to pass a foreign object in place of\nan attributes dictionary of a tag.\n\n\n\n### Normalized Case for Tag Names\n\nThe `tagName` field is always in \"normalized case,\" which is the\nofficial case for that particular element name (usually lowercase).\nFor example, `HTML.DIV().tagName` is `\"div\"`.  For some elements\nused in inline SVG graphics, the correct case is \"camelCase.\"  For\nexample, there is an element named `clipPath`.\n\nWeb browsers have a confusing policy about case.  They perform case\nnormalization when parsing HTML, but not when creating SVG elements\nat runtime; the correct case is required.\n\nTherefore, in order to avoid ever having to normalize case at\nruntime, the policy of HTMLjs is to put the burden on the caller\nof functions like `HTML.ensureTag` -- for example, a template\nengine -- of supplying correct normalized case.\n\nBriefly put, normlized case is usually lowercase, except for certain\nelements where it is camelCase.\n\n\n### Known Elements\n\nHTMLjs comes preloaded with constructors for all \"known\" HTML and\nSVG elements.  You can use `HTML.P`, `HTML.DIV`, and so on out of\nthe box.  If you want to create a tag like `<foo>` for some reason,\nyou have to tell HTMLjs to create the `HTML.FOO` constructor for you\nusing `HTML.ensureTag` or `HTML.getTag`.\n\nHTMLjs's lists of known elements are public because they are useful to\nother packages that provide additional functions not found here, like\nfunctions for normalizing case.\n\n\n\n## Foreign objects\n\nArbitrary objects are allowed in HTMLjs trees, which is useful for\nadapting HTMLjs to a wide variety of uses.  Such objects are called\nforeign objects.\n\nThe one restriction on foreign objects is that they must be\ninstances of a class -- so-called \"constructed objects\" (see\n`HTML.isConstructedObject`) -- so that they can be distinguished\nfrom the vanilla JS objects that represent attributes dictionaries\nwhen constructing Tags.\n\nFunctions are also considered foreign objects.\n\n## HTML.getTag(tagName)\n\n* `tagName` - A string in normalized case\n\nCreates a tag constructor for `tagName`, assigns it to the `HTML`\nnamespace object, and returns it.\n\nFor example, `HTML.getTag(\"p\")` returns `HTML.P`.  `HTML.getTag(\"foo\")`\nwill create and return `HTML.FOO`.\n\nIt's very important that `tagName` be in normalized case, or else\nan incorrect tag constructor will be registered and used henceforth.\n\n\n## HTML.ensureTag(tagName)\n\n* `tagName` - A string in normalized case\n\nEnsures that a tag constructor (like `HTML.FOO`) exists for a tag\nname (like `\"foo\"`), creating it if necessary.  Like `HTML.getTag`\nbut does not return the tag constructor.\n\n\n## HTML.isTagEnsured(tagName)\n\n* `tagName` - A string in normalized case\n\nReturns whether a particular tag is guaranteed to be available on\nthe `HTML` object (under the name returned by `HTML.getSymbolName`).\n\nUseful for code generators.\n\n\n## HTML.getSymbolName(tagName)\n\n* `tagName` - A string in normalized case\n\nReturns the name of the all-caps constructor (like `\"FOO\"`) for a\ntag name in normalized case (like `\"foo\"`).\n\nIn addition to converting `tagName` to all-caps, hyphens (`-`) in\ntag names are converted to underscores (`_`).\n\nUseful for code generators.\n\n\n## HTML.knownElementNames\n\nAn array of all known HTML5 and SVG element names in normalized case.\n\n\n## HTML.knownSVGElementNames\n\nAn array of all known SVG element names in normalized case.\n\nThe `\"a\"` element is not included because it is primarily a non-SVG\nelement.\n\n\n## HTML.voidElementNames\n\nAn array of all \"void\" element names in normalized case.  Void\nelements are elements with a start tag and no end tag, such as BR,\nHR, IMG, and INPUT.\n\nThe HTML spec defines a closed class of void elements.\n\n\n## HTML.isKnownElement(tagName)\n\n* `tagName` - A string in normalized case\n\nReturns whether `tagName` is a known HTML5 or SVG element.\n\n\n## HTML.isKnownSVGElement(tagName)\n\n* `tagName` - A string in normalized case\n\nReturns whether `tagName` is the name of a known SVG element.\n\n\n## HTML.isVoidElement(tagName)\n\n* `tagName` - A string in normalized case\n\nReturns whether `tagName` is the name of a void element.\n\n\n## HTML.CharRef({html: ..., str: ...})\n\nRepresents a character reference like `&nbsp;`.\n\nA CharRef is not required for escaping special characters like `<`,\nwhich are automatically escaped by HTMLjs.  For example,\n`HTML.toHTML(\"<\")` is `\"&lt;\"`.  Also, now that browsers speak\nUnicode, non-ASCII characters typically do not need to be expressed\nas character references either.  The purpose of `CharRef` is offer\ncontrol over the generated HTML, allowing template engines to\npreserve any character references that they come across.\n\nConstructing a CharRef requires two strings, the uninterpreted\n\"HTML\" form and the interpreted \"string\" form.  Both are required\nto be present, and it is up to the caller to make sure the\ninformation is accurate.\n\nExamples of valid CharRefs:\n\n* `HTML.CharRef({html: '&amp;', str: '&'})`\n* `HTML.CharRef({html: '&nbsp;', str: '\\u00A0'})\n\nInstance properties: `.html`, `.str`\n\n\n## HTML.Comment(value)\n\n* `value` - String\n\nRepresents an HTML Comment.  For example, `HTML.Comment(\"foo\")` represents\nthe comment `<!--foo-->`.\n\nThe value string should not contain two consecutive hyphens (`--`) or start\nor end with a hyphen.  If it does, the offending hyphens will be stripped\nbefore generating HTML.\n\nInstance properties: `value`\n\n\n## HTML.Raw(value)\n\n* `value` - String\n\nRepresents HTML code to be inserted verbatim.  `value` must consist\nof a valid, complete fragment of HTML, with all tags closed and\nall required end tags present.\n\nNo security checks are performed, and no special characters are\nescaped.  `Raw` should not be used if there are other ways of\naccomplishing the same result.  HTML supplied by an application\nuser should not be rendered unless the user is trusted, and even\nthen, there could be strange results if required end tags are\nmissing.\n\nInstance properties: `value`\n\n\n## HTML.isArray(x)\n\nReturns whether `x` is considered an array for the purposes of\nHTMLjs.  An array is an object created using `[...]` or\n`new Array`.\n\nThis function is provided because there are several common ways to\ndetermine whether an object should be treated as an array in\nJavaScript.\n\n\n## HTML.isConstructedObject(x)\n\nReturns whether `x` is a \"constructed object,\" which is (loosely\nspeaking) an object that was created with `new Foo` (for some `Foo`)\nrather than with `{...}` (a vanilla object).  Vanilla objects are used\nas attribute dictionaries when constructing tags, while constructed\nobjects are used as children.\n\nFor example, in `HTML.DIV({id:\"foo\"})`, `{id:\"foo\"}` is a vanilla\nobject.  In `HTML.DIV(HTML.SPAN(\"text\"))`, the `HTML.SPAN` is a\nconstructed object.\n\nA simple constructed object can be created as follows:\n\n```\nvar Foo = function () {};\nvar x = new Foo; // x is a constructed object\n```\n\nIn particular, the test is that `x` is an object and `x.constructor`\nis set, but on a prototype of the object, not the object itself.\nThe above example works because JavaScript sets\n`Foo.prototype.constructor = Foo` when you create a function `Foo`.\n\n\n## HTML.isNully(content)\n\nReturns true if `content` is `null`, `undefined`, an empty array,\nor an array of only \"nully\" elements.\n\n\n## HTML.isValidAttributeName(name)\n\nReturns whether `name` is a valid name for an attribute of an HTML tag\nor element.  `name` must:\n\n* Start with `:`, `_`, `A-Z` or `a-z`\n* Consist only of those characters plus `-`, `.`, and `0-9`.\n\nDiscussion: The HTML spec and the DOM API (`setAttribute`) have different\ndefinitions of what characters are legal in an attribute.  The HTML\nparser is extremely permissive (allowing, for example, `<a %=%>`), while\n`setAttribute` seems to use something like the XML grammar for names (and\nthrows an error if a name is invalid, making that attribute unsettable).\nIf we knew exactly what grammar browsers used for `setAttribute`, we could\ninclude various Unicode ranges in what's legal.  For now, we allow ASCII chars\nthat are known to be valid XML, valid HTML, and settable via `setAttribute`.\n\nSee <http://www.w3.org/TR/REC-xml/#NT-Name> and\n<http://dev.w3.org/html5/markup/syntax.html#syntax-attributes>.\n\n\n## HTML.flattenAttributes(attrs)\n\nIf `attrs` is an array, the attribute dictionaries in the array are\ncombined into a single attributes dictionary, which is returned.\nAny \"nully\" attribute values (see `HTML.isNully`) are ignored in\nthe process.  If `attrs` is a single attribute dictionary, a copy\nis returned with any nully attributes removed.  If `attrs` is\nequal to null or an empty array, `null` is returned.\n\nAttribute dictionaries are combined by assigning the name/value\npairs in array order, with later values overwriting previous\nvalues.\n\n`attrs` must not contain any foreign objects.\n\n\n## HTML.toHTML(content)\n\n* `content` - any HTMLjs content\n\nReturns a string of HTML generated from `content`.\n\nFor example:\n\n```\nHTML.toHTML(HTML.HR()) // => \"<hr>\"\n```\n\nForeign objects are not allowed in `content`.  To generate HTML\ncontaining foreign objects, create a subclass of\n`HTML.ToHTMLVisitor` and override `visitObject`.\n\n\n## HTML.toText(content, textMode)\n\n* `content` - any HTMLjs content\n* `textMode` - the type of text to generate; one of\n  `HTML.TEXTMODE.STRING`, `HTML.TEXTMODE.RCDATA`, or\n  `HTML.TEXTMODE.ATTRIBUTE`\n\nGenerating HTML or DOM from HTMLjs content requires generating text\nfor attribute values and for the contents of TEXTAREA elements,\namong others.  The input content may contain strings, arrays,\nbooleans, numbers, nulls, and CharRefs.  Behavior on other types\nis undefined.\n\nThe required `textMode` argument specifies the type of text to\ngenerate:\n\n* `HTML.TEXTMODE.STRING` - a string with no special\n  escaping or encoding performed, suitable for passing to\n  `setAttribute` or `document.createTextNode`.\n* `HTML.TEXTMODE.RCDATA` - a string with `<` and `&` encoded\n  as character references (and CharRefs included in their\n  \"HTML\" form), suitable for including in a string of HTML\n* `HTML.TEXTMODE.ATTRIBUTE` - a string with `\"` and `&` encoded\n  as character references (and CharRefs included in their\n  \"HTML\" form), suitable for including in an HTML attribute\n  value surrounded by double quotes\n"
  },
  {
    "path": "packages/htmljs/html.js",
    "content": "\n\nHTML.Tag = function () {};\nHTML.Tag.prototype.tagName = ''; // this will be set per Tag subclass\nHTML.Tag.prototype.attrs = null;\nHTML.Tag.prototype.children = Object.freeze ? Object.freeze([]) : [];\nHTML.Tag.prototype.htmljsType = HTML.Tag.htmljsType = ['Tag'];\n\n// Given \"p\" create the function `HTML.P`.\nvar makeTagConstructor = function (tagName) {\n  // HTMLTag is the per-tagName constructor of a HTML.Tag subclass\n  var HTMLTag = function (/*arguments*/) {\n    // Work with or without `new`.  If not called with `new`,\n    // perform instantiation by recursively calling this constructor.\n    // We can't pass varargs, so pass no args.\n    var instance = (this instanceof HTML.Tag) ? this : new HTMLTag;\n\n    var i = 0;\n    var attrs = arguments.length && arguments[0];\n    if (attrs && (typeof attrs === 'object')) {\n      // Treat vanilla JS object as an attributes dictionary.\n      if (! HTML.isConstructedObject(attrs)) {\n        instance.attrs = attrs;\n        i++;\n      } else if (attrs instanceof HTML.Attrs) {\n        var array = attrs.value;\n        if (array.length === 1) {\n          instance.attrs = array[0];\n        } else if (array.length > 1) {\n          instance.attrs = array;\n        }\n        i++;\n      }\n    }\n\n\n    // If no children, don't create an array at all, use the prototype's\n    // (frozen, empty) array.  This way we don't create an empty array\n    // every time someone creates a tag without `new` and this constructor\n    // calls itself with no arguments (above).\n    if (i < arguments.length)\n      instance.children = SLICE.call(arguments, i);\n\n    return instance;\n  };\n  HTMLTag.prototype = new HTML.Tag;\n  HTMLTag.prototype.constructor = HTMLTag;\n  HTMLTag.prototype.tagName = tagName;\n\n  return HTMLTag;\n};\n\n// Not an HTMLjs node, but a wrapper to pass multiple attrs dictionaries\n// to a tag (for the purpose of implementing dynamic attributes).\nvar Attrs = HTML.Attrs = function (/*attrs dictionaries*/) {\n  // Work with or without `new`.  If not called with `new`,\n  // perform instantiation by recursively calling this constructor.\n  // We can't pass varargs, so pass no args.\n  var instance = (this instanceof Attrs) ? this : new Attrs;\n\n  instance.value = SLICE.call(arguments);\n\n  return instance;\n};\n\n////////////////////////////// KNOWN ELEMENTS\n\nHTML.getTag = function (tagName) {\n  var symbolName = HTML.getSymbolName(tagName);\n  if (symbolName === tagName) // all-caps tagName\n    throw new Error(\"Use the lowercase or camelCase form of '\" + tagName + \"' here\");\n\n  if (! HTML[symbolName])\n    HTML[symbolName] = makeTagConstructor(tagName);\n\n  return HTML[symbolName];\n};\n\nHTML.ensureTag = function (tagName) {\n  HTML.getTag(tagName); // don't return it\n};\n\nHTML.isTagEnsured = function (tagName) {\n  return HTML.isKnownElement(tagName);\n};\n\nHTML.getSymbolName = function (tagName) {\n  // \"foo-bar\" -> \"FOO_BAR\"\n  return tagName.toUpperCase().replace(/-/g, '_');\n};\n\nHTML.knownElementNames = 'a abbr acronym address applet area article aside audio b base basefont bdi bdo big blockquote body br button canvas caption center cite code col colgroup command data datagrid datalist dd del details dfn dir div dl dt em embed eventsource fieldset figcaption figure font footer form frame frameset h1 h2 h3 h4 h5 h6 head header hgroup hr html i iframe img input ins isindex kbd keygen label legend li link main map mark menu meta meter nav noframes noscript object ol optgroup option output p param pre progress q rp rt ruby s samp script section select small source span strike strong style sub summary sup table tbody td textarea tfoot th thead time title tr track tt u ul var video wbr'.split(' ');\n// (we add the SVG ones below)\n\nHTML.knownSVGElementNames = 'altGlyph altGlyphDef altGlyphItem animate animateColor animateMotion animateTransform circle clipPath color-profile cursor defs desc ellipse feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence filter font font-face font-face-format font-face-name font-face-src font-face-uri foreignObject g glyph glyphRef hkern image line linearGradient marker mask metadata missing-glyph path pattern polygon polyline radialGradient rect set stop style svg switch symbol text textPath title tref tspan use view vkern'.split(' ');\n// Append SVG element names to list of known element names\nHTML.knownElementNames = HTML.knownElementNames.concat(HTML.knownSVGElementNames);\n\nHTML.voidElementNames = 'area base br col command embed hr img input keygen link meta param source track wbr'.split(' ');\n\n// Speed up search through lists of known elements by creating internal \"sets\"\n// of strings.\nvar YES = {yes:true};\nvar makeSet = function (array) {\n  var set = {};\n  for (var i = 0; i < array.length; i++)\n    set[array[i]] = YES;\n  return set;\n};\nvar voidElementSet = makeSet(HTML.voidElementNames);\nvar knownElementSet = makeSet(HTML.knownElementNames);\nvar knownSVGElementSet = makeSet(HTML.knownSVGElementNames);\n\nHTML.isKnownElement = function (tagName) {\n  return knownElementSet[tagName] === YES;\n};\n\nHTML.isKnownSVGElement = function (tagName) {\n  return knownSVGElementSet[tagName] === YES;\n};\n\nHTML.isVoidElement = function (tagName) {\n  return voidElementSet[tagName] === YES;\n};\n\n\n// Ensure tags for all known elements\nfor (var i = 0; i < HTML.knownElementNames.length; i++)\n  HTML.ensureTag(HTML.knownElementNames[i]);\n\n\nvar CharRef = HTML.CharRef = function (attrs) {\n  if (! (this instanceof CharRef))\n    // called without `new`\n    return new CharRef(attrs);\n\n  if (! (attrs && attrs.html && attrs.str))\n    throw new Error(\n      \"HTML.CharRef must be constructed with ({html:..., str:...})\");\n\n  this.html = attrs.html;\n  this.str = attrs.str;\n};\nCharRef.prototype.htmljsType = CharRef.htmljsType = ['CharRef'];\n\nvar Comment = HTML.Comment = function (value) {\n  if (! (this instanceof Comment))\n    // called without `new`\n    return new Comment(value);\n\n  if (typeof value !== 'string')\n    throw new Error('HTML.Comment must be constructed with a string');\n\n  this.value = value;\n  // Kill illegal hyphens in comment value (no way to escape them in HTML)\n  this.sanitizedValue = value.replace(/^-|--+|-$/g, '');\n};\nComment.prototype.htmljsType = Comment.htmljsType = ['Comment'];\n\nvar Raw = HTML.Raw = function (value) {\n  if (! (this instanceof Raw))\n    // called without `new`\n    return new Raw(value);\n\n  if (typeof value !== 'string')\n    throw new Error('HTML.Raw must be constructed with a string');\n\n  this.value = value;\n};\nRaw.prototype.htmljsType = Raw.htmljsType = ['Raw'];\n\n\nHTML.isArray = function (x) {\n  // could change this to use the more convoluted Object.prototype.toString\n  // approach that works when objects are passed between frames, but does\n  // it matter?\n  return (x instanceof Array);\n};\n\nHTML.isConstructedObject = function (x) {\n  // Figure out if `x` is \"an instance of some class\" or just a plain\n  // object literal.  It correctly treats an object literal like\n  // `{ constructor: ... }` as an object literal.  It won't detect\n  // instances of classes that lack a `constructor` property (e.g.\n  // if you assign to a prototype when setting up the class as in:\n  // `Foo = function () { ... }; Foo.prototype = { ... }`, then\n  // `(new Foo).constructor` is `Object`, not `Foo`).\n  return (x && (typeof x === 'object') &&\n          (x.constructor !== Object) &&\n          (typeof x.constructor === 'function') &&\n          (x instanceof x.constructor));\n};\n\nHTML.isNully = function (node) {\n  if (node == null)\n    // null or undefined\n    return true;\n\n  if (HTML.isArray(node)) {\n    // is it an empty array or an array of all nully items?\n    for (var i = 0; i < node.length; i++)\n      if (! HTML.isNully(node[i]))\n        return false;\n    return true;\n  }\n\n  return false;\n};\n\nHTML.isValidAttributeName = function (name) {\n  return /^[:_A-Za-z][:_A-Za-z0-9.\\-]*/.test(name);\n};\n\n// If `attrs` is an array of attributes dictionaries, combines them\n// into one.  Removes attributes that are \"nully.\"\nHTML.flattenAttributes = function (attrs) {\n  if (! attrs)\n    return attrs;\n\n  var isArray = HTML.isArray(attrs);\n  if (isArray && attrs.length === 0)\n    return null;\n\n  var result = {};\n  for (var i = 0, N = (isArray ? attrs.length : 1); i < N; i++) {\n    var oneAttrs = (isArray ? attrs[i] : attrs);\n    if ((typeof oneAttrs !== 'object') ||\n        HTML.isConstructedObject(oneAttrs))\n      throw new Error(\"Expected plain JS object as attrs, found: \" + oneAttrs);\n    for (var name in oneAttrs) {\n      if (! HTML.isValidAttributeName(name))\n        throw new Error(\"Illegal HTML attribute name: \" + name);\n      var value = oneAttrs[name];\n      if (! HTML.isNully(value))\n        result[name] = value;\n    }\n  }\n\n  return result;\n};\n\n\n\n////////////////////////////// TOHTML\n\nHTML.toHTML = function (content) {\n  return (new HTML.ToHTMLVisitor).visit(content);\n};\n\n// Escaping modes for outputting text when generating HTML.\nHTML.TEXTMODE = {\n  STRING: 1,\n  RCDATA: 2,\n  ATTRIBUTE: 3\n};\n\n\nHTML.toText = function (content, textMode) {\n  if (! textMode)\n    throw new Error(\"textMode required for HTML.toText\");\n  if (! (textMode === HTML.TEXTMODE.STRING ||\n         textMode === HTML.TEXTMODE.RCDATA ||\n         textMode === HTML.TEXTMODE.ATTRIBUTE))\n    throw new Error(\"Unknown textMode: \" + textMode);\n\n  var visitor = new HTML.ToTextVisitor({textMode: textMode});;\n  return visitor.visit(content);\n};\n"
  },
  {
    "path": "packages/htmljs/htmljs_test.js",
    "content": "\nTinytest.add(\"htmljs - getTag\", function (test) {\n  var FOO = HTML.getTag('foo');\n  test.isTrue(HTML.FOO === FOO);\n  var x = FOO();\n\n  test.equal(x.tagName, 'foo');\n  test.isTrue(x instanceof HTML.FOO);\n  test.isTrue(x instanceof HTML.Tag);\n  test.equal(x.children, []);\n  test.equal(x.attrs, null);\n\n  test.isTrue((new FOO) instanceof HTML.FOO);\n  test.isTrue((new FOO) instanceof HTML.Tag);\n  test.isFalse((new HTML.P) instanceof HTML.FOO);\n\n  var result = HTML.ensureTag('Bar');\n  test.equal(typeof result, 'undefined');\n  var BAR = HTML.BAR;\n  test.equal(BAR().tagName, 'Bar');\n});\n\nTinytest.add(\"htmljs - construction\", function (test) {\n  var A = HTML.getTag('a');\n  var B = HTML.getTag('b');\n  var C = HTML.getTag('c');\n\n  var a = A(0, B({q:0}, C(A(B({})), 'foo')));\n  test.equal(a.tagName, 'a');\n  test.equal(a.attrs, null);\n  test.equal(a.children.length, 2);\n  test.equal(a.children[0], 0);\n  var b = a.children[1];\n  test.equal(b.tagName, 'b');\n  test.equal(b.attrs, {q:0});\n  test.equal(b.children.length, 1);\n  var c = b.children[0];\n  test.equal(c.tagName, 'c');\n  test.equal(c.attrs, null);\n  test.equal(c.children.length, 2);\n  test.equal(c.children[0].tagName, 'a');\n  test.equal(c.children[0].attrs, null);\n  test.equal(c.children[0].children.length, 1);\n  test.equal(c.children[0].children[0].tagName, 'b');\n  test.equal(c.children[0].children[0].children.length, 0);\n  test.equal(c.children[0].children[0].attrs, {});\n  test.equal(c.children[1], 'foo');\n\n  var a2 = new A({m:1}, {n:2}, B(), {o:3}, 'foo');\n  test.equal(a2.tagName, 'a');\n  test.equal(a2.attrs, {m:1});\n  test.equal(a2.children.length, 4);\n  test.equal(a2.children[0], {n:2});\n  test.equal(a2.children[1].tagName, 'b');\n  test.equal(a2.children[2], {o:3});\n  test.equal(a2.children[3], 'foo');\n\n  // tests of HTML.isConstructedObject (indirectly)\n  test.equal(A({x:1}).children.length, 0);\n  var f = function () {};\n  test.equal(A(new f).children.length, 1);\n  test.equal(A(new Date).children.length, 1);\n  test.equal(A({constructor: 'blah'}).children.length, 0);\n  test.equal(A({constructor: Object}).children.length, 0);\n\n  test.equal(HTML.toHTML(HTML.CharRef({html: '&amp;', str: '&'})), '&amp;');\n  test.throws(function () {\n    HTML.CharRef({html: '&amp;'}); // no 'str'\n  });\n});\n\nTinytest.add(\"htmljs - utils\", function (test) {\n\n  test.notEqual(\"\\u00c9\".toLowerCase(), \"\\u00c9\");\n  test.equal(HTMLTools.asciiLowerCase(\"\\u00c9\"), \"\\u00c9\");\n\n  test.equal(HTMLTools.asciiLowerCase(\"Hello There\"), \"hello there\");\n\n  test.isTrue(HTML.isVoidElement(\"br\"));\n  test.isFalse(HTML.isVoidElement(\"div\"));\n  test.isTrue(HTML.isKnownElement(\"div\"));\n\n});\n\nTinytest.add(\"htmljs - details\", function (test) {\n  test.equal(HTML.toHTML(false), \"false\");\n});\n"
  },
  {
    "path": "packages/htmljs/package.js",
    "content": "Package.describe({\n  summary: \"Small library for expressing HTML trees\",\n  version: '1.0.10'\n});\n\nPackage.onUse(function (api) {\n  api.use('deps');\n  api.export('HTML');\n\n  api.addFiles(['preamble.js',\n                 'visitors.js',\n                 'html.js']);\n});\n\nPackage.onTest(function (api) {\n  api.use('htmljs');\n  api.use('html-tools');\n  api.use('tinytest');\n  api.use('underscore');\n  api.addFiles(['htmljs_test.js']);\n});\n"
  },
  {
    "path": "packages/htmljs/preamble.js",
    "content": "HTML = {};\n\nIDENTITY = function (x) { return x; };\nSLICE = Array.prototype.slice;\n"
  },
  {
    "path": "packages/htmljs/visitors.js",
    "content": "////////////////////////////// VISITORS\n\n// _assign is like _.extend or the upcoming Object.assign.\n// Copy src's own, enumerable properties onto tgt and return\n// tgt.\nvar _hasOwnProperty = Object.prototype.hasOwnProperty;\nvar _assign = function (tgt, src) {\n  for (var k in src) {\n    if (_hasOwnProperty.call(src, k))\n      tgt[k] = src[k];\n  }\n  return tgt;\n};\n\nHTML.Visitor = function (props) {\n  _assign(this, props);\n};\n\nHTML.Visitor.def = function (options) {\n  _assign(this.prototype, options);\n};\n\nHTML.Visitor.extend = function (options) {\n  var curType = this;\n  var subType = function HTMLVisitorSubtype(/*arguments*/) {\n    HTML.Visitor.apply(this, arguments);\n  };\n  subType.prototype = new curType;\n  subType.extend = curType.extend;\n  subType.def = curType.def;\n  if (options)\n    _assign(subType.prototype, options);\n  return subType;\n};\n\nHTML.Visitor.def({\n  visit: function (content/*, ...*/) {\n    if (content == null)\n      // null or undefined.\n      return this.visitNull.apply(this, arguments);\n\n    if (typeof content === 'object') {\n      if (content.htmljsType) {\n        switch (content.htmljsType) {\n        case HTML.Tag.htmljsType:\n          return this.visitTag.apply(this, arguments);\n        case HTML.CharRef.htmljsType:\n          return this.visitCharRef.apply(this, arguments);\n        case HTML.Comment.htmljsType:\n          return this.visitComment.apply(this, arguments);\n        case HTML.Raw.htmljsType:\n          return this.visitRaw.apply(this, arguments);\n        default:\n          throw new Error(\"Unknown htmljs type: \" + content.htmljsType);\n        }\n      }\n\n      if (HTML.isArray(content))\n        return this.visitArray.apply(this, arguments);\n\n      return this.visitObject.apply(this, arguments);\n\n    } else if ((typeof content === 'string') ||\n               (typeof content === 'boolean') ||\n               (typeof content === 'number')) {\n      return this.visitPrimitive.apply(this, arguments);\n\n    } else if (typeof content === 'function') {\n      return this.visitFunction.apply(this, arguments);\n    }\n\n    throw new Error(\"Unexpected object in htmljs: \" + content);\n\n  },\n  visitNull: function (nullOrUndefined/*, ...*/) {},\n  visitPrimitive: function (stringBooleanOrNumber/*, ...*/) {},\n  visitArray: function (array/*, ...*/) {},\n  visitComment: function (comment/*, ...*/) {},\n  visitCharRef: function (charRef/*, ...*/) {},\n  visitRaw: function (raw/*, ...*/) {},\n  visitTag: function (tag/*, ...*/) {},\n  visitObject: function (obj/*, ...*/) {\n    throw new Error(\"Unexpected object in htmljs: \" + obj);\n  },\n  visitFunction: function (fn/*, ...*/) {\n    throw new Error(\"Unexpected function in htmljs: \" + fn);\n  }\n});\n\nHTML.TransformingVisitor = HTML.Visitor.extend();\nHTML.TransformingVisitor.def({\n  visitNull: IDENTITY,\n  visitPrimitive: IDENTITY,\n  visitArray: function (array/*, ...*/) {\n    var argsCopy = SLICE.call(arguments);\n    var result = array;\n    for (var i = 0; i < array.length; i++) {\n      var oldItem = array[i];\n      argsCopy[0] = oldItem;\n      var newItem = this.visit.apply(this, argsCopy);\n      if (newItem !== oldItem) {\n        // copy `array` on write\n        if (result === array)\n          result = array.slice();\n        result[i] = newItem;\n      }\n    }\n    return result;\n  },\n  visitComment: IDENTITY,\n  visitCharRef: IDENTITY,\n  visitRaw: IDENTITY,\n  visitObject: IDENTITY,\n  visitFunction: IDENTITY,\n  visitTag: function (tag/*, ...*/) {\n    var oldChildren = tag.children;\n    var argsCopy = SLICE.call(arguments);\n    argsCopy[0] = oldChildren;\n    var newChildren = this.visitChildren.apply(this, argsCopy);\n\n    var oldAttrs = tag.attrs;\n    argsCopy[0] = oldAttrs;\n    var newAttrs = this.visitAttributes.apply(this, argsCopy);\n\n    if (newAttrs === oldAttrs && newChildren === oldChildren)\n      return tag;\n\n    var newTag = HTML.getTag(tag.tagName).apply(null, newChildren);\n    newTag.attrs = newAttrs;\n    return newTag;\n  },\n  visitChildren: function (children/*, ...*/) {\n    return this.visitArray.apply(this, arguments);\n  },\n  // Transform the `.attrs` property of a tag, which may be a dictionary,\n  // an array, or in some uses, a foreign object (such as\n  // a template tag).\n  visitAttributes: function (attrs/*, ...*/) {\n    if (HTML.isArray(attrs)) {\n      var argsCopy = SLICE.call(arguments);\n      var result = attrs;\n      for (var i = 0; i < attrs.length; i++) {\n        var oldItem = attrs[i];\n        argsCopy[0] = oldItem;\n        var newItem = this.visitAttributes.apply(this, argsCopy);\n        if (newItem !== oldItem) {\n          // copy on write\n          if (result === attrs)\n            result = attrs.slice();\n          result[i] = newItem;\n        }\n      }\n      return result;\n    }\n\n    if (attrs && HTML.isConstructedObject(attrs)) {\n      throw new Error(\"The basic HTML.TransformingVisitor does not support \" +\n                      \"foreign objects in attributes.  Define a custom \" +\n                      \"visitAttributes for this case.\");\n    }\n\n    var oldAttrs = attrs;\n    var newAttrs = oldAttrs;\n    if (oldAttrs) {\n      var attrArgs = [null, null];\n      attrArgs.push.apply(attrArgs, arguments);\n      for (var k in oldAttrs) {\n        var oldValue = oldAttrs[k];\n        attrArgs[0] = k;\n        attrArgs[1] = oldValue;\n        var newValue = this.visitAttribute.apply(this, attrArgs);\n        if (newValue !== oldValue) {\n          // copy on write\n          if (newAttrs === oldAttrs)\n            newAttrs = _assign({}, oldAttrs);\n          newAttrs[k] = newValue;\n        }\n      }\n    }\n\n    return newAttrs;\n  },\n  // Transform the value of one attribute name/value in an\n  // attributes dictionary.\n  visitAttribute: function (name, value, tag/*, ...*/) {\n    var args = SLICE.call(arguments, 2);\n    args[0] = value;\n    return this.visit.apply(this, args);\n  }\n});\n\n\nHTML.ToTextVisitor = HTML.Visitor.extend();\nHTML.ToTextVisitor.def({\n  visitNull: function (nullOrUndefined) {\n    return '';\n  },\n  visitPrimitive: function (stringBooleanOrNumber) {\n    var str = String(stringBooleanOrNumber);\n    if (this.textMode === HTML.TEXTMODE.RCDATA) {\n      return str.replace(/&/g, '&amp;').replace(/</g, '&lt;');\n    } else if (this.textMode === HTML.TEXTMODE.ATTRIBUTE) {\n      // escape `&` and `\"` this time, not `&` and `<`\n      return str.replace(/&/g, '&amp;').replace(/\"/g, '&quot;');\n    } else {\n      return str;\n    }\n  },\n  visitArray: function (array) {\n    var parts = [];\n    for (var i = 0; i < array.length; i++)\n      parts.push(this.visit(array[i]));\n    return parts.join('');\n  },\n  visitComment: function (comment) {\n    throw new Error(\"Can't have a comment here\");\n  },\n  visitCharRef: function (charRef) {\n    if (this.textMode === HTML.TEXTMODE.RCDATA ||\n        this.textMode === HTML.TEXTMODE.ATTRIBUTE) {\n      return charRef.html;\n    } else {\n      return charRef.str;\n    }\n  },\n  visitRaw: function (raw) {\n    return raw.value;\n  },\n  visitTag: function (tag) {\n    // Really we should just disallow Tags here.  However, at the\n    // moment it's useful to stringify any HTML we find.  In\n    // particular, when you include a template within `{{#markdown}}`,\n    // we render the template as text, and since there's currently\n    // no way to make the template be *parsed* as text (e.g. `<template\n    // type=\"text\">`), we hackishly support HTML tags in markdown\n    // in templates by parsing them and stringifying them.\n    return this.visit(this.toHTML(tag));\n  },\n  visitObject: function (x) {\n    throw new Error(\"Unexpected object in htmljs in toText: \" + x);\n  },\n  toHTML: function (node) {\n    return HTML.toHTML(node);\n  }\n});\n\n\n\nHTML.ToHTMLVisitor = HTML.Visitor.extend();\nHTML.ToHTMLVisitor.def({\n  visitNull: function (nullOrUndefined) {\n    return '';\n  },\n  visitPrimitive: function (stringBooleanOrNumber) {\n    var str = String(stringBooleanOrNumber);\n    return str.replace(/&/g, '&amp;').replace(/</g, '&lt;');\n  },\n  visitArray: function (array) {\n    var parts = [];\n    for (var i = 0; i < array.length; i++)\n      parts.push(this.visit(array[i]));\n    return parts.join('');\n  },\n  visitComment: function (comment) {\n    return '<!--' + comment.sanitizedValue + '-->';\n  },\n  visitCharRef: function (charRef) {\n    return charRef.html;\n  },\n  visitRaw: function (raw) {\n    return raw.value;\n  },\n  visitTag: function (tag) {\n    var attrStrs = [];\n\n    var tagName = tag.tagName;\n    var children = tag.children;\n\n    var attrs = tag.attrs;\n    if (attrs) {\n      attrs = HTML.flattenAttributes(attrs);\n      for (var k in attrs) {\n        if (k === 'value' && tagName === 'textarea') {\n          children = [attrs[k], children];\n        } else {\n          var v = this.toText(attrs[k], HTML.TEXTMODE.ATTRIBUTE);\n          attrStrs.push(' ' + k + '=\"' + v + '\"');\n        }\n      }\n    }\n\n    var startTag = '<' + tagName + attrStrs.join('') + '>';\n\n    var childStrs = [];\n    var content;\n    if (tagName === 'textarea') {\n\n      for (var i = 0; i < children.length; i++)\n        childStrs.push(this.toText(children[i], HTML.TEXTMODE.RCDATA));\n\n      content = childStrs.join('');\n      if (content.slice(0, 1) === '\\n')\n        // TEXTAREA will absorb a newline, so if we see one, add\n        // another one.\n        content = '\\n' + content;\n\n    } else {\n      for (var i = 0; i < children.length; i++)\n        childStrs.push(this.visit(children[i]));\n\n      content = childStrs.join('');\n    }\n\n    var result = startTag + content;\n\n    if (children.length || ! HTML.isVoidElement(tagName)) {\n      // \"Void\" elements like BR are the only ones that don't get a close\n      // tag in HTML5.  They shouldn't have contents, either, so we could\n      // throw an error upon seeing contents here.\n      result += '</' + tagName + '>';\n    }\n\n    return result;\n  },\n  visitObject: function (x) {\n    throw new Error(\"Unexpected object in htmljs in toHTML: \" + x);\n  },\n  toText: function (node, textMode) {\n    return HTML.toText(node, textMode);\n  }\n});\n"
  },
  {
    "path": "packages/http/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/http/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/http/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/http/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"ansi-regex\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz\",\n      \"from\": \"ansi-regex@>=2.0.0 <3.0.0\"\n    },\n    \"ansi-styles\": {\n      \"version\": \"2.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz\",\n      \"from\": \"ansi-styles@>=2.2.1 <3.0.0\"\n    },\n    \"asn1\": {\n      \"version\": \"0.2.3\",\n      \"resolved\": \"https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz\",\n      \"from\": \"asn1@>=0.2.3 <0.3.0\"\n    },\n    \"assert-plus\": {\n      \"version\": \"0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz\",\n      \"from\": \"assert-plus@>=0.2.0 <0.3.0\"\n    },\n    \"async\": {\n      \"version\": \"1.5.2\",\n      \"resolved\": \"https://registry.npmjs.org/async/-/async-1.5.2.tgz\",\n      \"from\": \"async@>=1.5.2 <2.0.0\"\n    },\n    \"aws-sign2\": {\n      \"version\": \"0.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz\",\n      \"from\": \"aws-sign2@>=0.6.0 <0.7.0\"\n    },\n    \"aws4\": {\n      \"version\": \"1.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz\",\n      \"from\": \"aws4@>=1.2.1 <2.0.0\"\n    },\n    \"bl\": {\n      \"version\": \"1.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/bl/-/bl-1.1.2.tgz\",\n      \"from\": \"bl@>=1.1.2 <1.2.0\"\n    },\n    \"boom\": {\n      \"version\": \"2.10.1\",\n      \"resolved\": \"https://registry.npmjs.org/boom/-/boom-2.10.1.tgz\",\n      \"from\": \"boom@>=2.0.0 <3.0.0\"\n    },\n    \"caseless\": {\n      \"version\": \"0.11.0\",\n      \"resolved\": \"https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz\",\n      \"from\": \"caseless@>=0.11.0 <0.12.0\"\n    },\n    \"chalk\": {\n      \"version\": \"1.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz\",\n      \"from\": \"chalk@>=1.1.1 <2.0.0\"\n    },\n    \"combined-stream\": {\n      \"version\": \"1.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz\",\n      \"from\": \"combined-stream@>=1.0.5 <1.1.0\"\n    },\n    \"commander\": {\n      \"version\": \"2.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/commander/-/commander-2.9.0.tgz\",\n      \"from\": \"commander@>=2.9.0 <3.0.0\"\n    },\n    \"core-util-is\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz\",\n      \"from\": \"core-util-is@>=1.0.0 <1.1.0\"\n    },\n    \"cryptiles\": {\n      \"version\": \"2.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz\",\n      \"from\": \"cryptiles@>=2.0.0 <3.0.0\"\n    },\n    \"dashdash\": {\n      \"version\": \"1.14.0\",\n      \"resolved\": \"https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz\",\n      \"from\": \"dashdash@>=1.12.0 <2.0.0\",\n      \"dependencies\": {\n        \"assert-plus\": {\n          \"version\": \"1.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz\",\n          \"from\": \"assert-plus@>=1.0.0 <2.0.0\"\n        }\n      }\n    },\n    \"delayed-stream\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz\",\n      \"from\": \"delayed-stream@>=1.0.0 <1.1.0\"\n    },\n    \"ecc-jsbn\": {\n      \"version\": \"0.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz\",\n      \"from\": \"ecc-jsbn@>=0.1.1 <0.2.0\"\n    },\n    \"escape-string-regexp\": {\n      \"version\": \"1.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz\",\n      \"from\": \"escape-string-regexp@>=1.0.2 <2.0.0\"\n    },\n    \"extend\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/extend/-/extend-3.0.0.tgz\",\n      \"from\": \"extend@>=3.0.0 <3.1.0\"\n    },\n    \"extsprintf\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz\",\n      \"from\": \"extsprintf@1.0.2\"\n    },\n    \"forever-agent\": {\n      \"version\": \"0.6.1\",\n      \"resolved\": \"https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz\",\n      \"from\": \"forever-agent@>=0.6.1 <0.7.0\"\n    },\n    \"form-data\": {\n      \"version\": \"1.0.0-rc4\",\n      \"resolved\": \"https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz\",\n      \"from\": \"form-data@>=1.0.0-rc3 <1.1.0\"\n    },\n    \"generate-function\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz\",\n      \"from\": \"generate-function@>=2.0.0 <3.0.0\"\n    },\n    \"generate-object-property\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz\",\n      \"from\": \"generate-object-property@>=1.1.0 <2.0.0\"\n    },\n    \"getpass\": {\n      \"version\": \"0.1.6\",\n      \"resolved\": \"https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz\",\n      \"from\": \"getpass@>=0.1.1 <0.2.0\",\n      \"dependencies\": {\n        \"assert-plus\": {\n          \"version\": \"1.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz\",\n          \"from\": \"assert-plus@>=1.0.0 <2.0.0\"\n        }\n      }\n    },\n    \"graceful-readlink\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz\",\n      \"from\": \"graceful-readlink@>=1.0.0\"\n    },\n    \"har-validator\": {\n      \"version\": \"2.0.6\",\n      \"resolved\": \"https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz\",\n      \"from\": \"har-validator@>=2.0.6 <2.1.0\"\n    },\n    \"has-ansi\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz\",\n      \"from\": \"has-ansi@>=2.0.0 <3.0.0\"\n    },\n    \"hawk\": {\n      \"version\": \"3.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz\",\n      \"from\": \"hawk@>=3.1.3 <3.2.0\"\n    },\n    \"hoek\": {\n      \"version\": \"2.16.3\",\n      \"resolved\": \"https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz\",\n      \"from\": \"hoek@>=2.0.0 <3.0.0\"\n    },\n    \"http-signature\": {\n      \"version\": \"1.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz\",\n      \"from\": \"http-signature@>=1.1.0 <1.2.0\"\n    },\n    \"inherits\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\",\n      \"from\": \"inherits@>=2.0.1 <2.1.0\"\n    },\n    \"is-my-json-valid\": {\n      \"version\": \"2.13.1\",\n      \"resolved\": \"https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz\",\n      \"from\": \"is-my-json-valid@>=2.12.4 <3.0.0\"\n    },\n    \"is-property\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz\",\n      \"from\": \"is-property@>=1.0.0 <2.0.0\"\n    },\n    \"is-typedarray\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz\",\n      \"from\": \"is-typedarray@>=1.0.0 <1.1.0\"\n    },\n    \"isarray\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz\",\n      \"from\": \"isarray@>=1.0.0 <1.1.0\"\n    },\n    \"isstream\": {\n      \"version\": \"0.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz\",\n      \"from\": \"isstream@>=0.1.2 <0.2.0\"\n    },\n    \"jodid25519\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz\",\n      \"from\": \"jodid25519@>=1.0.0 <2.0.0\"\n    },\n    \"jsbn\": {\n      \"version\": \"0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz\",\n      \"from\": \"jsbn@>=0.1.0 <0.2.0\"\n    },\n    \"json-schema\": {\n      \"version\": \"0.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz\",\n      \"from\": \"json-schema@0.2.2\"\n    },\n    \"json-stringify-safe\": {\n      \"version\": \"5.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz\",\n      \"from\": \"json-stringify-safe@>=5.0.1 <5.1.0\"\n    },\n    \"jsonpointer\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz\",\n      \"from\": \"jsonpointer@2.0.0\"\n    },\n    \"jsprim\": {\n      \"version\": \"1.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/jsprim/-/jsprim-1.2.2.tgz\",\n      \"from\": \"jsprim@>=1.2.2 <2.0.0\"\n    },\n    \"mime-db\": {\n      \"version\": \"1.23.0\",\n      \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz\",\n      \"from\": \"mime-db@>=1.23.0 <1.24.0\"\n    },\n    \"mime-types\": {\n      \"version\": \"2.1.11\",\n      \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz\",\n      \"from\": \"mime-types@>=2.1.7 <2.2.0\"\n    },\n    \"node-uuid\": {\n      \"version\": \"1.4.7\",\n      \"resolved\": \"https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz\",\n      \"from\": \"node-uuid@>=1.4.7 <1.5.0\"\n    },\n    \"oauth-sign\": {\n      \"version\": \"0.8.2\",\n      \"resolved\": \"https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz\",\n      \"from\": \"oauth-sign@>=0.8.1 <0.9.0\"\n    },\n    \"pinkie\": {\n      \"version\": \"2.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz\",\n      \"from\": \"pinkie@>=2.0.0 <3.0.0\"\n    },\n    \"pinkie-promise\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz\",\n      \"from\": \"pinkie-promise@>=2.0.0 <3.0.0\"\n    },\n    \"process-nextick-args\": {\n      \"version\": \"1.0.7\",\n      \"resolved\": \"https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz\",\n      \"from\": \"process-nextick-args@>=1.0.6 <1.1.0\"\n    },\n    \"qs\": {\n      \"version\": \"6.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/qs/-/qs-6.1.0.tgz\",\n      \"from\": \"qs@>=6.1.0 <6.2.0\"\n    },\n    \"readable-stream\": {\n      \"version\": \"2.0.6\",\n      \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz\",\n      \"from\": \"readable-stream@>=2.0.5 <2.1.0\"\n    },\n    \"request\": {\n      \"version\": \"2.72.0\",\n      \"resolved\": \"https://registry.npmjs.org/request/-/request-2.72.0.tgz\",\n      \"from\": \"request@2.72.0\"\n    },\n    \"sntp\": {\n      \"version\": \"1.0.9\",\n      \"resolved\": \"https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz\",\n      \"from\": \"sntp@>=1.0.0 <2.0.0\"\n    },\n    \"sshpk\": {\n      \"version\": \"1.8.3\",\n      \"resolved\": \"https://registry.npmjs.org/sshpk/-/sshpk-1.8.3.tgz\",\n      \"from\": \"sshpk@>=1.7.0 <2.0.0\",\n      \"dependencies\": {\n        \"assert-plus\": {\n          \"version\": \"1.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz\",\n          \"from\": \"assert-plus@>=1.0.0 <2.0.0\"\n        }\n      }\n    },\n    \"string_decoder\": {\n      \"version\": \"0.10.31\",\n      \"resolved\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\",\n      \"from\": \"string_decoder@>=0.10.0 <0.11.0\"\n    },\n    \"stringstream\": {\n      \"version\": \"0.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz\",\n      \"from\": \"stringstream@>=0.0.4 <0.1.0\"\n    },\n    \"strip-ansi\": {\n      \"version\": \"3.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz\",\n      \"from\": \"strip-ansi@>=3.0.0 <4.0.0\"\n    },\n    \"supports-color\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz\",\n      \"from\": \"supports-color@>=2.0.0 <3.0.0\"\n    },\n    \"tough-cookie\": {\n      \"version\": \"2.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz\",\n      \"from\": \"tough-cookie@>=2.2.0 <2.3.0\"\n    },\n    \"tunnel-agent\": {\n      \"version\": \"0.4.3\",\n      \"resolved\": \"https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz\",\n      \"from\": \"tunnel-agent@>=0.4.1 <0.5.0\"\n    },\n    \"tweetnacl\": {\n      \"version\": \"0.13.3\",\n      \"resolved\": \"https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz\",\n      \"from\": \"tweetnacl@>=0.13.0 <0.14.0\"\n    },\n    \"util-deprecate\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz\",\n      \"from\": \"util-deprecate@>=1.0.1 <1.1.0\"\n    },\n    \"verror\": {\n      \"version\": \"1.3.6\",\n      \"resolved\": \"https://registry.npmjs.org/verror/-/verror-1.3.6.tgz\",\n      \"from\": \"verror@1.3.6\"\n    },\n    \"xtend\": {\n      \"version\": \"4.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz\",\n      \"from\": \"xtend@>=4.0.0 <5.0.0\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/http/README.md",
    "content": "# http\n\n`HTTP` provides an HTTP request API on the client and server.  To use\nthese functions, add the HTTP package to your project with `$ meteor add http`.\n\nSee the [HTTP section in the Meteor docs](http://docs.meteor.com/#http) for more details.\n\n## Direct access to npm request API\n\nOn the server, the `http` package is implemented using the\n[npm `request` module](https://www.npmjs.com/package/request).  If you'd like\ndirect access to this module, you can find it at\n`HTTPInternals.NpmModules.request.module`. Its version can be read at\n`HTTPInternals.NpmModules.request.version`.\n\nAdditionally, you can override any `request` option when using `HTTP.call` (or\n`HTTP.get`, etc) by including a `npmRequestOptions` option.\n\nThe version of `request` used may change incompatibly from version to version of\nMeteor (or we may even replace it with an entirely different implementation);\nuse at your own risk.\n"
  },
  {
    "path": "packages/http/deprecated.js",
    "content": "// The HTTP object used to be called Meteor.http.\n// XXX COMPAT WITH 0.6.4\nMeteor.http = HTTP;\n"
  },
  {
    "path": "packages/http/httpcall_client.js",
    "content": "/**\n * @summary Perform an outbound HTTP request.\n * @locus Anywhere\n * @param {String} method The [HTTP method](http://en.wikipedia.org/wiki/HTTP_method) to use, such as \"`GET`\", \"`POST`\", or \"`HEAD`\".\n * @param {String} url The URL to retrieve.\n * @param {Object} [options]\n * @param {String} options.content String to use as the HTTP request body.\n * @param {Object} options.data JSON-able object to stringify and use as the HTTP request body. Overwrites `content`.\n * @param {String} options.query Query string to go in the URL. Overwrites any query string in `url`.\n * @param {Object} options.params Dictionary of request parameters to be encoded and placed in the URL (for GETs) or request body (for POSTs).  If `content` or `data` is specified, `params` will always be placed in the URL.\n * @param {String} options.auth HTTP basic authentication string of the form `\"username:password\"`\n * @param {Object} options.headers Dictionary of strings, headers to add to the HTTP request.\n * @param {Number} options.timeout Maximum time in milliseconds to wait for the request before failing.  There is no timeout by default.\n * @param {Boolean} options.followRedirects If `true`, transparently follow HTTP redirects. Cannot be set to `false` on the client. Default `true`.\n * @param {Object} options.npmRequestOptions On the server, `HTTP.call` is implemented by using the [npm `request` module](https://www.npmjs.com/package/request). Any options in this object will be passed directly to the `request` invocation.\n * @param {Function} options.beforeSend On the client, this will be called before the request is sent to allow for more direct manipulation of the underlying XMLHttpRequest object, which will be passed as the first argument. If the callback returns `false`, the request will be not be send.\n * @param {Function} [asyncCallback] Optional callback.  If passed, the method runs asynchronously, instead of synchronously, and calls asyncCallback.  On the client, this callback is required.\n */\nHTTP.call = function(method, url, options, callback) {\n\n  ////////// Process arguments //////////\n\n  if (! callback && typeof options === \"function\") {\n    // support (method, url, callback) argument list\n    callback = options;\n    options = null;\n  }\n\n  options = options || {};\n\n  if (typeof callback !== \"function\")\n    throw new Error(\n      \"Can't make a blocking HTTP call from the client; callback required.\");\n\n  method = (method || \"\").toUpperCase();\n\n  var headers = {};\n\n  var content = options.content;\n  if (options.data) {\n    content = JSON.stringify(options.data);\n    headers['Content-Type'] = 'application/json';\n  }\n\n  var params_for_url, params_for_body;\n  if (content || method === \"GET\" || method === \"HEAD\")\n    params_for_url = options.params;\n  else\n    params_for_body = options.params;\n\n  url = URL._constructUrl(url, options.query, params_for_url);\n\n  if (options.followRedirects === false)\n    throw new Error(\"Option followRedirects:false not supported on client.\");\n\n  if (_.has(options, 'npmRequestOptions')) {\n    throw new Error(\"Option npmRequestOptions not supported on client.\");\n  }\n\n  var username, password;\n  if (options.auth) {\n    var colonLoc = options.auth.indexOf(':');\n    if (colonLoc < 0)\n      throw new Error('auth option should be of the form \"username:password\"');\n    username = options.auth.substring(0, colonLoc);\n    password = options.auth.substring(colonLoc+1);\n  }\n\n  if (params_for_body) {\n    content = URL._encodeParams(params_for_body);\n  }\n\n  _.extend(headers, options.headers || {});\n\n  ////////// Callback wrapping //////////\n\n  // wrap callback to add a 'response' property on an error, in case\n  // we have both (http 4xx/5xx error, which has a response payload)\n  callback = (function(callback) {\n    return function(error, response) {\n      if (error && response)\n        error.response = response;\n      callback(error, response);\n    };\n  })(callback);\n\n  // safety belt: only call the callback once.\n  callback = _.once(callback);\n\n\n  ////////// Kickoff! //////////\n\n  // from this point on, errors are because of something remote, not\n  // something we should check in advance. Turn exceptions into error\n  // results.\n  try {\n    // setup XHR object\n    var xhr;\n    if (typeof XMLHttpRequest !== \"undefined\")\n      xhr = new XMLHttpRequest();\n    else if (typeof ActiveXObject !== \"undefined\")\n      xhr = new ActiveXObject(\"Microsoft.XMLHttp\"); // IE6\n    else\n      throw new Error(\"Can't create XMLHttpRequest\"); // ???\n\n    xhr.open(method, url, true, username, password);\n\n    for (var k in headers)\n      xhr.setRequestHeader(k, headers[k]);\n\n\n    // setup timeout\n    var timed_out = false;\n    var timer;\n    if (options.timeout) {\n      timer = Meteor.setTimeout(function() {\n        timed_out = true;\n        xhr.abort();\n      }, options.timeout);\n    };\n\n    // callback on complete\n    xhr.onreadystatechange = function(evt) {\n      if (xhr.readyState === 4) { // COMPLETE\n        if (timer)\n          Meteor.clearTimeout(timer);\n\n        if (timed_out) {\n          callback(new Error(\"timeout\"));\n        } else if (! xhr.status) {\n          // no HTTP response\n          callback(new Error(\"network\"));\n        } else {\n\n          var response = {};\n          response.statusCode = xhr.status;\n          response.content = xhr.responseText;\n\n          response.headers = {};\n          var header_str = xhr.getAllResponseHeaders();\n\n          // https://github.com/meteor/meteor/issues/553\n          //\n          // In Firefox there is a weird issue, sometimes\n          // getAllResponseHeaders returns the empty string, but\n          // getResponseHeader returns correct results. Possibly this\n          // issue:\n          // https://bugzilla.mozilla.org/show_bug.cgi?id=608735\n          //\n          // If this happens we can't get a full list of headers, but\n          // at least get content-type so our JSON decoding happens\n          // correctly. In theory, we could try and rescue more header\n          // values with a list of common headers, but content-type is\n          // the only vital one for now.\n          if (\"\" === header_str && xhr.getResponseHeader(\"content-type\"))\n            header_str =\n            \"content-type: \" + xhr.getResponseHeader(\"content-type\");\n\n          var headers_raw = header_str.split(/\\r?\\n/);\n          _.each(headers_raw, function (h) {\n            var m = /^(.*?):(?:\\s+)(.*)$/.exec(h);\n            if (m && m.length === 3)\n              response.headers[m[1].toLowerCase()] = m[2];\n          });\n\n          populateData(response);\n\n          var error = null;\n          if (response.statusCode >= 400)\n            error = makeErrorByStatus(response.statusCode, response.content);\n\n          callback(error, response);\n        }\n      }\n    };\n\n    // Allow custom control over XHR and abort early.\n    if (options.beforeSend) {\n      // Sanity\n      var beforeSend = _.once(options.beforeSend);\n\n      // Call the callback and check to see if the request was aborted\n      if (false === beforeSend.call(null, xhr, options)) {\n        return xhr.abort();\n      }\n    }\n\n    // send it on its way\n    xhr.send(content);\n\n  } catch (err) {\n    callback(err);\n  }\n\n};\n"
  },
  {
    "path": "packages/http/httpcall_common.js",
    "content": "const MAX_LENGTH = 500; // if you change this, also change the appropriate test\n\nmakeErrorByStatus = function(statusCode, content) {\n  let message = `failed [${statusCode}]`;\n\n  if (content) {\n    const stringContent = typeof content == \"string\" ?\n      content : content.toString();\n\n    message += ' ' + truncate(stringContent.replace(/\\n/g, ' '), MAX_LENGTH);\n  }\n\n  return new Error(message);\n};\n\nfunction truncate(str, length) {\n  return str.length > length ? str.slice(0, length) + '...' : str;\n}\n\n// Fill in `response.data` if the content-type is JSON.\npopulateData = function(response) {\n  // Read Content-Type header, up to a ';' if there is one.\n  // A typical header might be \"application/json; charset=utf-8\"\n  // or just \"application/json\".\n  var contentType = (response.headers['content-type'] || ';').split(';')[0];\n\n  // Only try to parse data as JSON if server sets correct content type.\n  if (_.include(['application/json', 'text/javascript',\n      'application/javascript', 'application/x-javascript'], contentType)) {\n    try {\n      response.data = JSON.parse(response.content);\n    } catch (err) {\n      response.data = null;\n    }\n  } else {\n    response.data = null;\n  }\n};\n\nHTTP = {};\n\n/**\n * @summary Send an HTTP `GET` request. Equivalent to calling [`HTTP.call`](#http_call) with \"GET\" as the first argument.\n * @param {String} url The URL to which the request should be sent.\n * @param {Object} [callOptions] Options passed on to [`HTTP.call`](#http_call).\n * @param {Function} [asyncCallback] Callback that is called when the request is completed. Required on the client.\n * @locus Anywhere\n */\nHTTP.get = function (/* varargs */) {\n  return HTTP.call.apply(this, [\"GET\"].concat(_.toArray(arguments)));\n};\n\n/**\n * @summary Send an HTTP `POST` request. Equivalent to calling [`HTTP.call`](#http_call) with \"POST\" as the first argument.\n * @param {String} url The URL to which the request should be sent.\n * @param {Object} [callOptions] Options passed on to [`HTTP.call`](#http_call).\n * @param {Function} [asyncCallback] Callback that is called when the request is completed. Required on the client.\n * @locus Anywhere\n */\nHTTP.post = function (/* varargs */) {\n  return HTTP.call.apply(this, [\"POST\"].concat(_.toArray(arguments)));\n};\n\n/**\n * @summary Send an HTTP `PUT` request. Equivalent to calling [`HTTP.call`](#http_call) with \"PUT\" as the first argument.\n * @param {String} url The URL to which the request should be sent.\n * @param {Object} [callOptions] Options passed on to [`HTTP.call`](#http_call).\n * @param {Function} [asyncCallback] Callback that is called when the request is completed. Required on the client.\n * @locus Anywhere\n */\nHTTP.put = function (/* varargs */) {\n  return HTTP.call.apply(this, [\"PUT\"].concat(_.toArray(arguments)));\n};\n\n/**\n * @summary Send an HTTP `DELETE` request. Equivalent to calling [`HTTP.call`](#http_call) with \"DELETE\" as the first argument. (Named `del` to avoid conflict with the Javascript keyword `delete`)\n * @param {String} url The URL to which the request should be sent.\n * @param {Object} [callOptions] Options passed on to [`HTTP.call`](#http_call).\n * @param {Function} [asyncCallback] Callback that is called when the request is completed. Required on the client.\n * @locus Anywhere\n */\nHTTP.del = function (/* varargs */) {\n  return HTTP.call.apply(this, [\"DELETE\"].concat(_.toArray(arguments)));\n};\n\n/**\n * @summary Send an HTTP `PATCH` request. Equivalent to calling [`HTTP.call`](#http_call) with \"PATCH\" as the first argument.\n * @param {String} url The URL to which the request should be sent.\n * @param {Object} [callOptions] Options passed on to [`HTTP.call`](#http_call).\n * @param {Function} [asyncCallback] Callback that is called when the request is completed. Required on the client.\n * @locus Anywhere\n */\nHTTP.patch = function (/* varargs */) {\n  return HTTP.call.apply(this, [\"PATCH\"].concat(_.toArray(arguments)));\n};\n"
  },
  {
    "path": "packages/http/httpcall_server.js",
    "content": "var path = Npm.require('path');\nvar request = Npm.require('request');\nvar url_util = Npm.require('url');\n\nHTTPInternals = {\n  NpmModules: {\n    request: {\n      version: Npm.require('request/package.json').version,\n      module: request\n    }\n  }\n};\n\n// _call always runs asynchronously; HTTP.call, defined below,\n// wraps _call and runs synchronously when no callback is provided.\nvar _call = function(method, url, options, callback) {\n\n  ////////// Process arguments //////////\n\n  if (! callback && typeof options === \"function\") {\n    // support (method, url, callback) argument list\n    callback = options;\n    options = null;\n  }\n\n  options = options || {};\n\n  if (_.has(options, 'beforeSend')) {\n    throw new Error(\"Option beforeSend not supported on server.\");\n  }\n\n  method = (method || \"\").toUpperCase();\n\n  if (! /^https?:\\/\\//.test(url))\n    throw new Error(\"url must be absolute and start with http:// or https://\");\n\n  var headers = {};\n\n  var content = options.content;\n  if (options.data) {\n    content = JSON.stringify(options.data);\n    headers['Content-Type'] = 'application/json';\n  }\n\n\n  var paramsForUrl, paramsForBody;\n  if (content || method === \"GET\" || method === \"HEAD\")\n    paramsForUrl = options.params;\n  else\n    paramsForBody = options.params;\n\n  var newUrl = URL._constructUrl(url, options.query, paramsForUrl);\n\n  if (options.auth) {\n    if (options.auth.indexOf(':') < 0)\n      throw new Error('auth option should be of the form \"username:password\"');\n    headers['Authorization'] = \"Basic \"+\n      (new Buffer(options.auth, \"ascii\")).toString(\"base64\");\n  }\n\n  if (paramsForBody) {\n    content = URL._encodeParams(paramsForBody);\n    headers['Content-Type'] = \"application/x-www-form-urlencoded\";\n  }\n\n  _.extend(headers, options.headers || {});\n\n  // wrap callback to add a 'response' property on an error, in case\n  // we have both (http 4xx/5xx error, which has a response payload)\n  callback = (function(callback) {\n    return function(error, response) {\n      if (error && response)\n        error.response = response;\n      callback(error, response);\n    };\n  })(callback);\n\n  // safety belt: only call the callback once.\n  callback = _.once(callback);\n\n\n  ////////// Kickoff! //////////\n\n  // Allow users to override any request option with the npmRequestOptions\n  // option.\n  var reqOptions = _.extend({\n    url: newUrl,\n    method: method,\n    encoding: \"utf8\",\n    jar: false,\n    timeout: options.timeout,\n    body: content,\n    followRedirect: options.followRedirects,\n    // Follow redirects on non-GET requests\n    // also. (https://github.com/meteor/meteor/issues/2808)\n    followAllRedirects: options.followRedirects,\n    headers: headers\n  }, options.npmRequestOptions || {});\n\n  request(reqOptions, function(error, res, body) {\n    var response = null;\n\n    if (! error) {\n\n      response = {};\n      response.statusCode = res.statusCode;\n      response.content = body;\n      response.headers = res.headers;\n\n      populateData(response);\n\n      if (response.statusCode >= 400)\n        error = makeErrorByStatus(response.statusCode, response.content);\n    }\n\n    callback(error, response);\n\n  });\n};\n\nHTTP.call = Meteor.wrapAsync(_call);\n"
  },
  {
    "path": "packages/http/httpcall_tests.js",
    "content": "// URL prefix for tests to talk to\nvar _XHR_URL_PREFIX = \"/http_test_responder\";\n\nvar url_base = function () {\n  if (Meteor.isServer) {\n    var address = WebApp.httpServer.address();\n    return \"http://127.0.0.1:\" + address.port;\n  } else {\n    return \"\";\n  }\n};\n\nvar url_prefix = function () {\n  if (Meteor.isServer && _XHR_URL_PREFIX.indexOf(\"http\") !== 0) {\n    _XHR_URL_PREFIX = url_base() + _XHR_URL_PREFIX;\n  }\n  return _XHR_URL_PREFIX;\n};\n\n\ntestAsyncMulti(\"httpcall - basic\", [\n  function(test, expect) {\n    var basic_get = function(url, options, expected_url) {\n\n      var callback = function(error, result) {\n        test.isFalse(error);\n        if (! error) {\n          test.equal(typeof result, \"object\");\n          test.equal(result.statusCode, 200);\n\n          var data = result.data;\n\n          // allow dropping of final ? (which mobile browsers seem to do)\n          var allowed = [expected_url];\n          if (expected_url.slice(-1) === '?')\n            allowed.push(expected_url.slice(0, -1));\n\n          test.include(allowed, expected_url);\n          test.equal(data.method, \"GET\");\n        }\n      };\n\n\n      HTTP.call(\"GET\", url_prefix()+url, options, expect(callback));\n\n      if (Meteor.isServer) {\n        // test sync version\n        try {\n          var result = HTTP.call(\"GET\", url_prefix()+url, options);\n          callback(undefined, result);\n        } catch (e) {\n          callback(e, e.response);\n        }\n      }\n    };\n\n    basic_get(\"/foo\", null, \"/foo\");\n    basic_get(\"/foo?\", null, \"/foo?\");\n    basic_get(\"/foo?a=b\", null, \"/foo?a=b\");\n    basic_get(\"/foo\", {params: {fruit: \"apple\"}},\n              \"/foo?fruit=apple\");\n    basic_get(\"/foo\", {params: {fruit: \"apple\", dog: \"Spot the dog\"}},\n              \"/foo?fruit=apple&dog=Spot+the+dog\");\n    basic_get(\"/foo?\", {params: {fruit: \"apple\", dog: \"Spot the dog\"}},\n              \"/foo?fruit=apple&dog=Spot+the+dog\");\n    basic_get(\"/foo?bar\", {params: {fruit: \"apple\", dog: \"Spot the dog\"}},\n              \"/foo?bar&fruit=apple&dog=Spot+the+dog\");\n    basic_get(\"/foo?bar\", {params: {fruit: \"apple\", dog: \"Spot the dog\"},\n                           query: \"baz\"},\n              \"/foo?baz&fruit=apple&dog=Spot+the+dog\");\n    basic_get(\"/foo\", {params: {fruit: \"apple\", dog: \"Spot the dog\"},\n                       query: \"baz\"},\n              \"/foo?baz&fruit=apple&dog=Spot+the+dog\");\n    basic_get(\"/foo?\", {params: {fruit: \"apple\", dog: \"Spot the dog\"},\n                       query: \"baz\"},\n              \"/foo?baz&fruit=apple&dog=Spot+the+dog\");\n    basic_get(\"/foo?bar\", {query: \"\"}, \"/foo?\");\n    basic_get(\"/foo?bar\", {params: {fruit: \"apple\", dog: \"Spot the dog\"},\n                           query: \"\"},\n              \"/foo?fruit=apple&dog=Spot+the+dog\");\n  }]);\n\ntestAsyncMulti(\"httpcall - errors\", [\n  function(test, expect) {\n\n    // Accessing unknown server (should fail to make any connection)\n    var unknownServerCallback = function(error, result) {\n      test.isTrue(error);\n      test.isFalse(result);\n      test.isFalse(error.response);\n    };\n\n    const invalidIp = \"0.0.0.199\";\n    // This is an invalid destination IP address, and thus should always give an error.\n    // If your ISP is intercepting DNS misses and serving ads, an obviously\n    // invalid URL (http://asdf.asdf) might produce an HTTP response.\n    HTTP.call(\"GET\", `http://${invalidIp}/`, expect(unknownServerCallback));\n\n    if (Meteor.isServer) {\n      // test sync version\n      try {\n        var unknownServerResult = HTTP.call(\"GET\", `http://${invalidIp}/`);\n        unknownServerCallback(undefined, unknownServerResult);\n      } catch (e) {\n        unknownServerCallback(e, e.response);\n      }\n    }\n\n    // Server serves 500\n    var error500Callback = function(error, result) {\n      test.isTrue(error);\n      test.isTrue(error.message.indexOf(\"500\") !== -1); // message has statusCode\n      test.isTrue(error.message.indexOf(\n        error.response.content.substring(0, 10)) !== -1); // message has part of content\n\n      test.isTrue(result);\n      test.isTrue(error.response);\n      test.equal(result, error.response);\n      test.equal(error.response.statusCode, 500);\n\n      // in test_responder.js we make a very long response body, to make sure\n      // that we truncate messages. first of all, make sure we didn't make that\n      // message too short, so that we can be sure we're verifying that we truncate.\n      test.isTrue(error.response.content.length > 520);\n      test.isTrue(error.message.length < 520); // make sure we truncate.\n    };\n    HTTP.call(\"GET\", url_prefix()+\"/fail\", expect(error500Callback));\n\n    if (Meteor.isServer) {\n      // test sync version\n      try {\n        var error500Result = HTTP.call(\"GET\", url_prefix()+\"/fail\");\n        error500Callback(undefined, error500Result);\n      } catch (e) {\n        error500Callback(e, e.response);\n      }\n    }\n  }\n]);\n\ntestAsyncMulti(\"httpcall - timeout\", [\n  function(test, expect) {\n\n    // Should time out\n    var timeoutCallback = function(error, result) {\n      test.isTrue(error);\n      test.isFalse(result);\n      test.isFalse(error.response);\n    };\n    var timeoutUrl = url_prefix()+\"/slow-\"+Random.id();\n    HTTP.call(\n      \"GET\", timeoutUrl,\n      { timeout: 500 },\n      expect(timeoutCallback));\n\n    if (Meteor.isServer) {\n      // test sync version\n      try {\n        var timeoutResult = HTTP.call(\"GET\", timeoutUrl, { timeout: 500 });\n        timeoutCallback(undefined, timeoutResult);\n      } catch (e) {\n        timeoutCallback(e, e.response);\n      }\n    }\n\n    // Should not time out\n    var noTimeoutCallback = function(error, result) {\n      test.isFalse(error);\n      test.isTrue(result);\n      test.equal(result.statusCode, 200);\n      var data = result.data;\n      test.equal(data.url.substring(0, 4), \"/foo\");\n      test.equal(data.method, \"GET\");\n    };\n    var noTimeoutUrl = url_prefix()+\"/foo-\"+Random.id();\n    HTTP.call(\n      \"GET\", noTimeoutUrl,\n      { timeout: 2000 },\n      expect(noTimeoutCallback));\n\n    if (Meteor.isServer) {\n      // test sync version\n      try {\n        var noTimeoutResult = HTTP.call(\"GET\", noTimeoutUrl, { timeout: 2000 });\n        noTimeoutCallback(undefined, noTimeoutResult);\n      } catch (e) {\n        noTimeoutCallback(e, e.response);\n      }\n    }\n  }\n]);\n\ntestAsyncMulti(\"httpcall - redirect\", [\n\n  function(test, expect) {\n    // Test that we follow redirects by default\n    HTTP.call(\"GET\", url_prefix()+\"/redirect\", expect(\n      function(error, result) {\n        test.isFalse(error);\n        test.isTrue(result);\n\n        // should be redirected transparently to /foo\n        test.equal(result.statusCode, 200);\n        var data = result.data;\n        test.equal(data.url, \"/foo\");\n        test.equal(data.method, \"GET\");\n      }));\n\n    // followRedirect option; can't be false on client\n    _.each([false, true], function(followRedirects) {\n      var do_it = function(should_work) {\n        var maybe_expect = should_work ? expect : _.identity;\n        _.each([\"GET\", \"POST\"], function (method) {\n          HTTP.call(\n            method, url_prefix()+\"/redirect\",\n            {followRedirects: followRedirects},\n            maybe_expect(function(error, result) {\n              test.isFalse(error);\n              test.isTrue(result);\n\n              if (followRedirects) {\n                // should be redirected transparently to /foo\n                test.equal(result.statusCode, 200);\n                var data = result.data;\n                test.equal(data.url, \"/foo\");\n                // This is \"GET\" even when the initial request was a\n                // POST because browsers follow redirects with a GET\n                // even when the initial request was a different method.\n                test.equal(data.method, \"GET\");\n              } else {\n                // should see redirect\n                test.equal(result.statusCode, 301);\n              }\n            }));\n        });\n      };\n      if (Meteor.isClient && ! followRedirects) {\n        // not supported, should fail\n        test.throws(do_it);\n      } else {\n        do_it(true);\n      }\n    });\n  }\n\n]);\n\ntestAsyncMulti(\"httpcall - methods\", [\n\n  function(test, expect) {\n    // non-get methods\n    var test_method = function(meth, func_name) {\n      func_name = func_name || meth.toLowerCase();\n      HTTP[func_name](\n        url_prefix()+\"/foo\",\n        expect(function(error, result) {\n          test.isFalse(error);\n          test.isTrue(result);\n          test.equal(result.statusCode, 200);\n          var data = result.data;\n          test.equal(data.url, \"/foo\");\n\n          // IE <= 8 turns seems to turn POSTs with no body into\n          // GETs, inexplicably.\n          //\n          // XXX Except now it doesn't!? Not sure what changed, but\n          // these lines now break the test...\n          // if (Meteor.isClient && $.browser.msie && $.browser.version <= 8\n          //     && meth === \"POST\")\n          //   meth = \"GET\";\n\n          test.equal(data.method, meth);\n        }));\n    };\n\n    test_method(\"GET\");\n    test_method(\"POST\");\n    test_method(\"PUT\");\n    test_method(\"DELETE\", 'del');\n    test_method(\"PATCH\");\n  },\n\n  function(test, expect) {\n    // contents and data\n    HTTP.call(\n      \"POST\", url_prefix()+\"/foo\",\n      { content: \"Hello World!\" },\n      expect(function(error, result) {\n        test.isFalse(error);\n        test.isTrue(result);\n        test.equal(result.statusCode, 200);\n        var data = result.data;\n        test.equal(data.body, \"Hello World!\");\n      }));\n\n    HTTP.call(\n      \"POST\", url_prefix()+\"/data-test\",\n      { data: {greeting: \"Hello World!\"} },\n      expect(function(error, result) {\n        test.isFalse(error);\n        test.isTrue(result);\n        test.equal(result.statusCode, 200);\n        var data = result.data;\n        test.equal(data.body, {greeting: \"Hello World!\"});\n        // nb: some browsers include a charset here too.\n        test.matches(data.headers['content-type'], /^application\\/json\\b/);\n      }));\n\n    HTTP.call(\n      \"POST\", url_prefix()+\"/data-test-explicit\",\n      { data: {greeting: \"Hello World!\"},\n        headers: {'Content-Type': 'text/stupid'} },\n      expect(function(error, result) {\n        test.isFalse(error);\n        test.isTrue(result);\n        test.equal(result.statusCode, 200);\n        var data = result.data;\n        test.equal(data.body, {greeting: \"Hello World!\"});\n        // nb: some browsers include a charset here too.\n        test.matches(data.headers['content-type'], /^text\\/stupid\\b/);\n      }));\n  }\n]);\n\ntestAsyncMulti(\"httpcall - http auth\", [\n  function(test, expect) {\n    // Test basic auth\n\n    // Unfortunately, any failed auth will result in a browser\n    // password prompt.  So we don't test auth failure, only\n    // success.\n\n    // Random password breaks in Firefox, because Firefox incorrectly\n    // uses cached credentials even if we supply different ones:\n    // https://bugzilla.mozilla.org/show_bug.cgi?id=654348\n    var password = 'rocks';\n    //var password = Random.id().replace(/[^0-9a-zA-Z]/g, '');\n    HTTP.call(\n      \"GET\", url_prefix()+\"/login?\"+password,\n      { auth: \"meteor:\"+password },\n      expect(function(error, result) {\n        // should succeed\n        test.isFalse(error);\n        test.isTrue(result);\n        test.equal(result.statusCode, 200);\n        var data = result.data;\n        test.equal(data.url, \"/login?\"+password);\n      }));\n\n    // test fail on malformed username:password\n    test.throws(function() {\n      HTTP.call(\n        \"GET\", url_prefix()+\"/login?\"+password,\n        { auth: \"fooooo\" },\n        function() { throw new Error(\"can't get here\"); });\n    });\n  }\n]);\n\ntestAsyncMulti(\"httpcall - headers\", [\n  function(test, expect) {\n    HTTP.call(\n      \"GET\", url_prefix()+\"/foo-with-headers\",\n      {headers: { \"Test-header\": \"Value\",\n                  \"another\": \"Value2\" } },\n      expect(function(error, result) {\n        test.isFalse(error);\n        test.isTrue(result);\n\n        test.equal(result.statusCode, 200);\n        var data = result.data;\n        test.equal(data.url, \"/foo-with-headers\");\n        test.equal(data.method, \"GET\");\n        test.equal(data.headers['test-header'], \"Value\");\n        test.equal(data.headers['another'], \"Value2\");\n      }));\n\n    HTTP.call(\n      \"GET\", url_prefix()+\"/headers\",\n      expect(function(error, result) {\n        test.isFalse(error);\n        test.isTrue(result);\n\n        test.equal(result.statusCode, 201);\n        test.equal(result.headers['a-silly-header'], \"Tis a\");\n        test.equal(result.headers['another-silly-header'], \"Silly place.\");\n      }));\n  }\n]);\n\ntestAsyncMulti(\"httpcall - params\", [\n  function(test, expect) {\n    var do_test = function(method, url, params, opt_opts, expect_url, expect_body) {\n      var opts = {};\n      if (typeof opt_opts === \"string\") {\n        // opt_opts omitted\n        expect_body = expect_url;\n        expect_url = opt_opts;\n      } else {\n        opts = opt_opts;\n      }\n      HTTP.call(\n        method, url_prefix()+url,\n        _.extend({ params: params }, opts),\n        expect(function(error, result) {\n          test.isFalse(error);\n          test.isTrue(result);\n          test.equal(result.statusCode, 200);\n          if (method !== \"HEAD\") {\n            var data = result.data;\n            test.equal(data.method, method);\n            test.equal(data.url, expect_url);\n            test.equal(data.body, expect_body);\n          }\n      }));\n    };\n\n    do_test(\"GET\", \"/blah\", {foo:\"bar\"}, \"/blah?foo=bar\", \"\");\n    do_test(\"GET\", \"/\", {foo:\"bar\", fruit:\"apple\"}, \"/?foo=bar&fruit=apple\", \"\");\n    do_test(\"POST\", \"/\", {foo:\"bar\", fruit:\"apple\"}, \"/\", \"foo=bar&fruit=apple\");\n    do_test(\"POST\", \"/\", {foo:\"bar\", fruit:\"apple\"}, \"/\", \"foo=bar&fruit=apple\");\n    do_test(\"GET\", \"/\", {'foo!':\"bang!\"}, {}, \"/?foo%21=bang%21\", \"\");\n    do_test(\"POST\", \"/\", {'foo!':\"bang!\"}, {}, \"/\", \"foo%21=bang%21\");\n    do_test(\"POST\", \"/\", {foo:\"bar\", fruit:\"apple\"}, {\n      content: \"stuff!\"}, \"/?foo=bar&fruit=apple\", \"stuff!\");\n    do_test(\"POST\", \"/\", {foo:\"bar\", greeting:\"Hello World\"}, {\n      content: \"stuff!\"}, \"/?foo=bar&greeting=Hello+World\", \"stuff!\");\n    do_test(\"POST\", \"/foo\", {foo:\"bar\", greeting:\"Hello World\"},\n            \"/foo\", \"foo=bar&greeting=Hello+World\");\n    do_test(\"HEAD\", \"/head\", {foo:\"bar\"}, \"/head?foo=bar\", \"\");\n    do_test(\"PUT\", \"/put\", {foo:\"bar\"}, \"/put\", \"foo=bar\");\n  }\n]);\n\ntestAsyncMulti(\"httpcall - npmRequestOptions\", [\n  function (test, expect) {\n    if (Meteor.isClient) {\n      test.throws(function () {\n        HTTP.get(url_prefix() + \"/\",\n                 { npmRequestOptions: { encoding: null } },\n                 function () {});\n      });\n      return;\n    }\n\n    HTTP.get(\n      url_prefix() + \"/\",\n      { npmRequestOptions: { encoding: null } },\n      expect(function (error, result) {\n        test.isFalse(error);\n        test.isTrue(result);\n        test.equal(result.statusCode, 200);\n        test.instanceOf(result.content, Buffer);\n      })\n    );\n  }\n]);\n\nMeteor.isClient && testAsyncMulti(\"httpcall - beforeSend\", [\n  function (test, expect) {\n    var fired = false;\n    var bSend = function(xhr){\n      test.isFalse(fired);\n      fired = true;\n      test.isTrue(xhr instanceof XMLHttpRequest);\n    };\n\n    HTTP.get(url_prefix() + \"/\", {beforeSend: bSend}, expect(function () {\n      test.isTrue(fired);\n    }));\n  }\n]);\n\n\nif (Meteor.isServer) {\n  // This is testing the server's static file sending code, not the http\n  // package. It's here because it is very similar to the other tests\n  // here, even though it is testing something else.\n  //\n  // client http library mangles paths before they are requested. only\n  // run this test on the server.\n  testAsyncMulti(\"httpcall - static file serving\", [\n    function(test, expect) {\n      // Suppress error printing for this test (and for any other code that sets\n      // the x-suppress-error header).\n      WebApp.suppressConnectErrors();\n\n      var do_test = function (path, code, match) {\n        HTTP.get(\n          url_base() + path,\n          {headers: {'x-suppress-error': 'true'}},\n          expect(function(error, result) {\n            test.equal(result.statusCode, code);\n            if (match)\n              test.matches(result.content, match);\n          }));\n      };\n\n      // existing static file\n      do_test(\"/packages/local-test_http/test_static.serveme\", 200, /static file serving/);\n\n      // no such file, so return the default app HTML.\n      var getsAppHtml = [\n        // This file doesn't exist.\n        \"/nosuchfile\",\n\n        // Our static file serving doesn't process .. or its encoded version, so\n        // any of these return the app HTML.\n        \"/../nosuchfile\",\n        \"/%2e%2e/nosuchfile\",\n        \"/%2E%2E/nosuchfile\",\n        \"/%2d%2d/nosuchfile\",\n        \"/packages/http/../http/test_static.serveme\",\n        \"/packages/http/%2e%2e/http/test_static.serveme\",\n        \"/packages/http/%2E%2E/http/test_static.serveme\",\n        \"/packages/http/../../packages/http/test_static.serveme\",\n        \"/packages/http/%2e%2e/%2e%2e/packages/http/test_static.serveme\",\n        \"/packages/http/%2E%2E/%2E%2E/packages/http/test_static.serveme\",\n\n        // ... and they *definitely* shouldn't be able to escape the app bundle.\n        \"/packages/http/../../../../../../packages/http/test_static.serveme\",\n        \"/../../../../../../../../../../../bin/ls\",\n        \"/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/bin/ls\",\n        \"/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/bin/ls\"\n      ];\n\n      _.each(getsAppHtml, function (x) {\n        do_test(x, 200, /__meteor_runtime_config__ = JSON/);\n      });\n    }\n  ]);\n}\n\nMeteor.isServer && Tinytest.add(\"httpcall - npm modules\", function (test) {\n  // Make sure the version number looks like a version number. (All published\n  // request version numbers end in \".0\".)\n  test.matches(HTTPInternals.NpmModules.request.version, /^2\\.(\\d+)\\.0/);\n  test.equal(typeof(HTTPInternals.NpmModules.request.module), 'function');\n  test.isTrue(HTTPInternals.NpmModules.request.module.get);\n});\n\n// TO TEST/ADD:\n// - https\n// - cookies?\n// - human-readable error reason/cause?\n// - data parse error\n"
  },
  {
    "path": "packages/http/package.js",
    "content": "Package.describe({\n  summary: \"Make HTTP calls to remote servers\",\n  version: '1.1.7'\n});\n\nNpm.depends({\n  request: \"2.72.0\"\n});\n\nPackage.onUse(function (api) {\n  api.use([\n    'underscore',\n    'url',\n    'ecmascript'\n  ]);\n\n  api.export('HTTP');\n  api.export('HTTPInternals', 'server');\n  api.addFiles('httpcall_common.js', ['client', 'server']);\n  api.addFiles('httpcall_client.js', 'client');\n  api.addFiles('httpcall_server.js', 'server');\n  api.addFiles('deprecated.js', ['client', 'server']);\n});\n\nPackage.onTest(function (api) {\n  api.use('ecmascript');\n  api.use('webapp', 'server');\n  api.use('underscore');\n  api.use('random');\n  api.use('jquery', 'client');\n  api.use('http', ['client', 'server']);\n  api.use('tinytest');\n  api.use('test-helpers', ['client', 'server']);\n\n  api.addFiles('test_responder.js', 'server');\n  api.addFiles('httpcall_tests.js', ['client', 'server']);\n\n  api.addAssets('test_static.serveme', 'client');\n});\n"
  },
  {
    "path": "packages/http/test_responder.js",
    "content": "var TEST_RESPONDER_ROUTE = \"/http_test_responder\";\n\nvar respond = function(req, res) {\n\n  if (req.url.slice(0,5) === \"/slow\") {\n    setTimeout(function() {\n      res.statusCode = 200;\n      res.end(\"A SLOW RESPONSE\");\n    }, 5000);\n    return;\n  } else if (req.url === \"/fail\") {\n    res.statusCode = 500;\n    res.end(\"SOME SORT OF SERVER ERROR. foo\" +\n            _.times(100, function () {\n              return \"MAKE THIS LONG TO TEST THAT WE TRUNCATE\";\n            }).join(' '));\n    return;\n  } else if (req.url === \"/redirect\") {\n    res.statusCode = 301;\n    // XXX shouldn't be redirecting to a relative URL, per HTTP spec,\n    // but browsers etc. seem to tolerate it.\n    res.setHeader(\"Location\", TEST_RESPONDER_ROUTE+\"/foo\");\n    res.end(\"REDIRECT TO FOO\");\n    return;\n  } else if (req.url.slice(0,6) === \"/login\") {\n    var username = 'meteor';\n    // get password from query string\n    var password = req.url.slice(7);\n    // realm is displayed in dialog box if one pops up, avoid confusion\n    var realm = TEST_RESPONDER_ROUTE+\"/login\";\n    var validate = function(user, pass) {\n      return user === username && pass === password;\n    };\n    var connect = WebAppInternals.NpmModules.connect.module;\n    var checker = connect.basicAuth(validate, realm);\n    var success = false;\n    checker(req, res, function() {\n      success = true;\n    });\n    if (! success)\n      return;\n  } else if (req.url === \"/headers\") {\n    res.statusCode = 201;\n    res.setHeader(\"A-Silly-Header\", \"Tis a\");\n    res.setHeader(\"Another-Silly-Header\", \"Silly place.\");\n    res.end(\"A RESPONSE WITH SOME HEADERS\");\n    return;\n  }\n\n  var chunks = [];\n  req.setEncoding(\"utf8\");\n  req.on(\"data\", function(chunk) {\n    chunks.push(chunk); });\n  req.on(\"end\", function() {\n    var body = chunks.join('');\n\n    if (body.charAt(0) === '{') {\n      body = JSON.parse(body);\n    }\n\n    var response_data = {\n      method: req.method,\n      url: req.url,\n      headers: req.headers,\n      body: body\n    };\n    var response_string = \"\";\n    if (req.method !== \"HEAD\")\n      response_string = JSON.stringify(response_data);\n\n    res.statusCode = 200;\n    res.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\n    res.end(response_string);\n  });\n\n};\n\nvar run_responder = function() {\n  WebApp.connectHandlers.stack.unshift(\n    { route: TEST_RESPONDER_ROUTE, handle: respond });\n};\n\nrun_responder();\n"
  },
  {
    "path": "packages/http/test_static.serveme",
    "content": "Here is some text used by the static file serving test.\n"
  },
  {
    "path": "packages/id-map/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/id-map/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/id-map/id-map.js",
    "content": "IdMap = function (idStringify, idParse) {\n  var self = this;\n  self._map = {};\n  self._idStringify = idStringify || JSON.stringify;\n  self._idParse = idParse || JSON.parse;\n};\n\n// Some of these methods are designed to match methods on OrderedDict, since\n// (eg) ObserveMultiplex and _CachingChangeObserver use them interchangeably.\n// (Conceivably, this should be replaced with \"UnorderedDict\" with a specific\n// set of methods that overlap between the two.)\n\n_.extend(IdMap.prototype, {\n  get: function (id) {\n    var self = this;\n    var key = self._idStringify(id);\n    return self._map[key];\n  },\n  set: function (id, value) {\n    var self = this;\n    var key = self._idStringify(id);\n    self._map[key] = value;\n  },\n  remove: function (id) {\n    var self = this;\n    var key = self._idStringify(id);\n    delete self._map[key];\n  },\n  has: function (id) {\n    var self = this;\n    var key = self._idStringify(id);\n    return _.has(self._map, key);\n  },\n  empty: function () {\n    var self = this;\n    return _.isEmpty(self._map);\n  },\n  clear: function () {\n    var self = this;\n    self._map = {};\n  },\n  // Iterates over the items in the map. Return `false` to break the loop.\n  forEach: function (iterator) {\n    var self = this;\n    // don't use _.each, because we can't break out of it.\n    var keys = _.keys(self._map);\n    for (var i = 0; i < keys.length; i++) {\n      var breakIfFalse = iterator.call(null, self._map[keys[i]],\n                                       self._idParse(keys[i]));\n      if (breakIfFalse === false)\n        return;\n    }\n  },\n  size: function () {\n    var self = this;\n    return _.size(self._map);\n  },\n  setDefault: function (id, def) {\n    var self = this;\n    var key = self._idStringify(id);\n    if (_.has(self._map, key))\n      return self._map[key];\n    self._map[key] = def;\n    return def;\n  },\n  // Assumes that values are EJSON-cloneable, and that we don't need to clone\n  // IDs (ie, that nobody is going to mutate an ObjectId).\n  clone: function () {\n    var self = this;\n    var clone = new IdMap(self._idStringify, self._idParse);\n    self.forEach(function (value, id) {\n      clone.set(id, EJSON.clone(value));\n    });\n    return clone;\n  }\n});\n\n"
  },
  {
    "path": "packages/id-map/package.js",
    "content": "Package.describe({\n  summary: \"Dictionary data structure allowing non-string keys\",\n  version: '1.0.8'\n});\n\nPackage.onUse(function (api) {\n  api.export('IdMap');\n  api.use(['underscore', 'ejson']);\n  api.addFiles([ 'id-map.js' ]);\n});\n"
  },
  {
    "path": "packages/insecure/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/insecure/README.md",
    "content": "# insecure\n\nAllow almost all collection methods, such as `insert`, `update`, and `remove`, to be called from the client. This package is useful for prototyping an app without worrying about database permissions, but should be removed as soon as the app needs to restrict database access.\n\nThe `insecure` package is automatically added to every Meteor app by `meteor create`."
  },
  {
    "path": "packages/insecure/package.js",
    "content": "Package.describe({\n  summary: \"(For prototyping only) Allow all database writes from the client\",\n  version: '1.0.7'\n});\n\n// This package is empty; its presence is detected by mongo-livedata.\n"
  },
  {
    "path": "packages/jquery/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/jquery/README.md",
    "content": "# jquery\n\n[jQuery](http://jquery.com/) is a fast and concise JavaScript\nLibrary that simplifies HTML document traversing, event handling,\nanimating, and Ajax interactions for rapid web development.\n\nThe `jquery` package adds the jQuery library to the client JavaScript\nbundle. It has no effect on the server.\n\nThis package is automatically included in every new Meteor app by `meteor create`.\n\nIn addition to the `jquery` package, Meteor provides several jQuery\nplugins as separate packages. These include:\n\n* [`jquery-waypoints`](http://imakewebthings.com/jquery-waypoints/)\n"
  },
  {
    "path": "packages/jquery/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v1.11.2\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-12-17T15:27Z\n */\n\n(function( global, factory ) {\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\t\t// For CommonJS and CommonJS-like environments where a proper window is present,\n\t\t// execute the factory and get jQuery\n\t\t// For environments that do not inherently posses a window with a document\n\t\t// (such as Node.js), expose a jQuery-making factory as module.exports\n\t\t// This accentuates the need for the creation of a real window\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n}(typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Can't do this because several apps including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n// Support: Firefox 18+\n//\n\nvar deletedIds = [];\n\nvar slice = deletedIds.slice;\n\nvar concat = deletedIds.concat;\n\nvar push = deletedIds.push;\n\nvar indexOf = deletedIds.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar support = {};\n\n\n\nvar\n\tversion = \"1.11.2\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t},\n\n\t// Support: Android<4.1, IE<9\n\t// Make sure we trim BOM and NBSP\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\n\njQuery.fn = jQuery.prototype = {\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num != null ?\n\n\t\t\t// Return just the one element from the set\n\t\t\t( num < 0 ? this[ num + this.length ] : this[ num ] ) :\n\n\t\t\t// Return all the elements in a clean array\n\t\t\tslice.call( this );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\t\tret.context = this.context;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: deletedIds.sort,\n\tsplice: deletedIds.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar src, copyIsArray, copy, name, options, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\t/* jshint eqeqeq: false */\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\t// parseFloat NaNs numeric-cast false positives (null|true|false|\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\t// adding 1 corrects loss of precision from parseFloat (#15100)\n\t\treturn !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\tvar key;\n\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Handle iteration over inherited properties before own properties.\n\t\tif ( support.ownLast ) {\n\t\t\tfor ( key in obj ) {\n\t\t\t\treturn hasOwn.call( obj, key );\n\t\t\t}\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn obj + \"\";\n\t\t}\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ toString.call(obj) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && jQuery.trim( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( obj, callback, args ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = obj.length,\n\t\t\tisArray = isArraylike( obj );\n\n\t\tif ( args ) {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Support: Android<4.1, IE<9\n\ttrim: function( text ) {\n\t\treturn text == null ?\n\t\t\t\"\" :\n\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArraylike( Object(arr) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\tvar len;\n\n\t\tif ( arr ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( arr, elem, i );\n\t\t\t}\n\n\t\t\tlen = arr.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in arr && arr[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\twhile ( j < len ) {\n\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)\n\t\tif ( len !== len ) {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tisArray = isArraylike( elems ),\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar args, proxy, tmp;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\tnow: function() {\n\t\treturn +( new Date() );\n\t},\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nfunction isArraylike( obj ) {\n\tvar length = obj.length,\n\t\ttype = jQuery.type( obj );\n\n\tif ( type === \"function\" || jQuery.isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\tif ( obj.nodeType === 1 && length ) {\n\t\treturn true;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v2.2.0-pre\n * http://sizzlejs.com/\n *\n * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-12-16\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// General-purpose constants\n\tMAX_NEGATIVE = 1 << 31,\n\n\t// Instance methods\n\thasOwn = ({}).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpush_native = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf as it's faster than native\n\t// http://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\t// http://www.w3.org/TR/css3-syntax/#characters\n\tcharacterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Loosely modeled on CSS identifier characters\n\t// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")(?:\" + whitespace +\n\t\t// Operator (capture 2)\n\t\t\"*([*^$|!~]?=)\" + whitespace +\n\t\t// \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n\t\t\"*\\\\]\",\n\n\tpseudos = \":(\" + characterEncoding + \")(?:\\\\((\" +\n\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\t\t// 2. simple (capture 6)\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\t\t// 3. anything else (capture 2)\n\t\t\".*\" +\n\t\t\")\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n\trattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\trescape = /'|\\\\/g,\n\n\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\t// Support: Firefox<24\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\n\t\t\tescaped :\n\t\t\thigh < 0 ?\n\t\t\t\t// BMP codepoint\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t};\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\tpreferredDoc.childNodes\n\t);\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar match, elem, m, nodeType,\n\t\t// QSA vars\n\t\ti, groups, old, nid, newContext, newSelector;\n\n\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\n\tcontext = context || document;\n\tresults = results || [];\n\tnodeType = context.nodeType;\n\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\tif ( !seed && documentIsHTML ) {\n\n\t\t// Try to shortcut find operations when possible (e.g., not under DocumentFragment)\n\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\tif ( (m = match[1]) ) {\n\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\telem = context.getElementById( m );\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document (jQuery #6963)\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Context is not a document\n\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\treturn results;\n\n\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName ) {\n\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\treturn results;\n\t\t\t}\n\t\t}\n\n\t\t// QSA path\n\t\tif ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\t\t\tnid = old = expando;\n\t\t\tnewContext = context;\n\t\t\tnewSelector = nodeType !== 1 && selector;\n\n\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t// IE 8 doesn't work on object elements\n\t\t\tif ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\tgroups = tokenize( selector );\n\n\t\t\t\tif ( (old = context.getAttribute(\"id\")) ) {\n\t\t\t\t\tnid = old.replace( rescape, \"\\\\$&\" );\n\t\t\t\t} else {\n\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t}\n\t\t\t\tnid = \"[id='\" + nid + \"'] \";\n\n\t\t\t\ti = groups.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tgroups[i] = nid + toSelector( groups[i] );\n\t\t\t\t}\n\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;\n\t\t\t\tnewSelector = groups.join(\",\");\n\t\t\t}\n\n\t\t\tif ( newSelector ) {\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t);\n\t\t\t\t\treturn results;\n\t\t\t\t} catch(qsaError) {\n\t\t\t\t} finally {\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.removeAttribute(\"id\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {Function(string, Object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key + \" \" ] = value);\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created div and expects a boolean result\n */\nfunction assert( fn ) {\n\tvar div = document.createElement(\"div\");\n\n\ttry {\n\t\treturn !!fn( div );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// Remove from its parent by default\n\t\tif ( div.parentNode ) {\n\t\t\tdiv.parentNode.removeChild( div );\n\t\t}\n\t\t// release memory in IE\n\t\tdiv = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split(\"|\"),\n\t\ti = attrs.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\t( ~b.sourceIndex || MAX_NEGATIVE ) -\n\t\t\t( ~a.sourceIndex || MAX_NEGATIVE );\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, parent,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// If no document and documentElement is available, return\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Set our document\n\tdocument = doc;\n\tdocElem = doc.documentElement;\n\tparent = doc.defaultView;\n\n\t// Support: IE>8\n\t// If iframe document is assigned to \"document\" variable and if iframe has been reloaded,\n\t// IE will throw \"permission denied\" error when accessing \"document\" variable, see jQuery #13936\n\t// IE6-8 do not support the defaultView property so parent will be undefined\n\tif ( parent && parent !== parent.top ) {\n\t\t// IE11 does not have attachEvent, so all must suffer\n\t\tif ( parent.addEventListener ) {\n\t\t\tparent.addEventListener( \"unload\", unloadHandler, false );\n\t\t} else if ( parent.attachEvent ) {\n\t\t\tparent.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t/* Support tests\n\t---------------------------------------------------------------------- */\n\tdocumentIsHTML = !isXML( doc );\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties\n\t// (excepting IE8 booleans)\n\tsupport.attributes = assert(function( div ) {\n\t\tdiv.className = \"i\";\n\t\treturn !div.getAttribute(\"className\");\n\t});\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert(function( div ) {\n\t\tdiv.appendChild( doc.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( doc.getElementsByClassName );\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert(function( div ) {\n\t\tdocElem.appendChild( div ).id = expando;\n\t\treturn !doc.getElementsByName || !doc.getElementsByName( expando ).length;\n\t});\n\n\t// ID find and filter\n\tif ( support.getById ) {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [ m ] : [];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t} else {\n\t\t// Support: IE6/7\n\t\t// getElementById is not reliable as a find shortcut\n\t\tdelete Expr.find[\"ID\"];\n\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t} else if ( support.qsa ) {\n\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t}\n\t\t} :\n\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See http://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( div ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\f]' msallowcapture=''>\" +\n\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( div.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+\n\t\t\tif ( !div.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibing-combinator selector` fails\n\t\t\tif ( !div.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = doc.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tdiv.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( div.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tdiv.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( div ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( div, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully does not implement inclusive descendent\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\tif ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\t\t\treturn a === doc ? -1 :\n\t\t\t\tb === doc ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\treturn doc;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch (e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( (elem = results[i++]) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( (node = elem[i++]) ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[3] || match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[6] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[3] ) {\n\t\t\t\tmatch[2] = match[4] || match[5] || \"\";\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() { return true; } :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, outerCache, node, diff, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\t\t\t\t\t\t\touterCache = parent[ expando ] || (parent[ expando ] = {});\n\t\t\t\t\t\t\tcache = outerCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[0] === dirruns && cache[1];\n\t\t\t\t\t\t\tdiff = cache[0] === dirruns && cache[2];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\touterCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n\t\t\t\t\t\t\tdiff = cache[1];\n\n\t\t\t\t\t\t// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\tif ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\tinput[0] = null;\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\ttext = text.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( (tokens = []) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push({\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t});\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\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\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\t\t\t\t\t\tif ( (oldCache = outerCache[ dir ]) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\touterCache[ dir ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\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\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context !== document && context;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Keep `i` a string if there are no elements so `matchedCount` will be \"00\" below\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\tmatchedCount += i;\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !match ) {\n\t\t\tmatch = tokenize( selector );\n\t\t}\n\t\ti = match.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( match[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n\t\t// Save selector and tokenization\n\t\tcached.selector = selector;\n\t}\n\treturn cached;\n};\n\n/**\n * A low-level selection function that works with Sizzle's compiled\n *  selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n *  selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\nselect = Sizzle.select = function( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tcompiled = typeof selector === \"function\" && selector,\n\t\tmatch = !seed && tokenize( (selector = compiled.selector || selector) );\n\n\tresults = results || [];\n\n\t// Try to minimize operations if there is no seed and only one group\n\tif ( match.length === 1 ) {\n\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\ttokens = match[0] = match[0].slice( 0 );\n\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\tsupport.getById && context.nodeType === 9 && documentIsHTML &&\n\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[i];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( (seed = find(\n\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t)) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\trsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n};\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n// Support: Chrome 14-35+\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert(function( div1 ) {\n\t// Should return 1, but returns 4 (following)\n\treturn div1.compareDocumentPosition( document.createElement(\"div\") ) & 1;\n});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert(function( div ) {\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\treturn div.firstChild.getAttribute(\"href\") === \"#\" ;\n}) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert(function( div ) {\n\tdiv.innerHTML = \"<input/>\";\n\tdiv.firstChild.setAttribute( \"value\", \"\" );\n\treturn div.firstChild.getAttribute( \"value\" ) === \"\";\n}) ) {\n\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert(function( div ) {\n\treturn div.getAttribute(\"disabled\") == null;\n}) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\tnull;\n\t\t}\n\t});\n}\n\nreturn Sizzle;\n\n})( window );\n\n\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\nvar rsingleTag = (/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/);\n\n\n\nvar risSimple = /^.[^:#\\[\\.,]*$/;\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\t/* jshint -W018 */\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t});\n\n\t}\n\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t});\n\n\t}\n\n\tif ( typeof qualifier === \"string\" ) {\n\t\tif ( risSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter( qualifier, elements, not );\n\t\t}\n\n\t\tqualifier = jQuery.filter( qualifier, elements );\n\t}\n\n\treturn jQuery.grep( elements, function( elem ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;\n\t});\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\treturn elems.length === 1 && elem.nodeType === 1 ?\n\t\tjQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :\n\t\tjQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t}));\n};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar i,\n\t\t\tret = [],\n\t\t\tself = this,\n\t\t\tlen = self.length;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}) );\n\t\t}\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\t// Needed because $( selector, context ) becomes $( context ).find( selector )\n\t\tret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );\n\t\tret.selector = this.selector ? this.selector + \" \" + selector : selector;\n\t\treturn ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], false) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], true) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n});\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,\n\n\tinit = jQuery.fn.init = function( selector, context ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\n\t\t\t\t\t// scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[1],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn typeof rootjQuery.ready !== \"undefined\" ?\n\t\t\t\trootjQuery.ready( selector ) :\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.extend({\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\njQuery.fn.extend({\n\thas: function( target ) {\n\t\tvar i,\n\t\t\ttargets = jQuery( target, this ),\n\t\t\tlen = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\tpos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tfor ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {\n\t\t\t\t// Always skip document fragments\n\t\t\t\tif ( cur.nodeType < 11 && (pos ?\n\t\t\t\t\tpos.index(cur) > -1 :\n\n\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\tjQuery.find.matchesSelector(cur, selectors)) ) {\n\n\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.unique(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter(selector)\n\t\t);\n\t}\n});\n\nfunction sibling( cur, dir ) {\n\tdo {\n\t\tcur = cur[ dir ];\n\t} while ( cur && cur.nodeType !== 1 );\n\n\treturn cur;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tret = jQuery.unique( ret );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tret = ret.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\nvar rnotwhite = (/\\S+/g);\n\n\n\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n\tvar object = optionsCache[ options ] = {};\n\tjQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t});\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\t( optionsCache[ options ] || createOptions( options ) ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\tfiringLength = 0;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\t\t\t\t// action, add listener, listener list, final state\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\t\t\tvar fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n\t\t\t\t\t\t\tdeferred[ tuple[1] ](function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Keep pipe for back-compat\n\t\tpromise.pipe = promise.then;\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 3 ];\n\n\t\t\t// promise[ done | fail | progress ] = list.add\n\t\t\tpromise[ tuple[1] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(function() {\n\t\t\t\t\t// state = [ resolved | rejected ]\n\t\t\t\t\tstate = stateString;\n\n\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n\t\t\t}\n\n\t\t\t// deferred[ resolve | reject | notify ]\n\t\t\tdeferred[ tuple[0] ] = function() {\n\t\t\t\tdeferred[ tuple[0] + \"With\" ]( this === deferred ? promise : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\t\t\tdeferred[ tuple[0] + \"With\" ] = list.fireWith;\n\t\t});\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( subordinate /* , ..., subordinateN */ ) {\n\t\tvar i = 0,\n\t\t\tresolveValues = slice.call( arguments ),\n\t\t\tlength = resolveValues.length,\n\n\t\t\t// the count of uncompleted subordinates\n\t\t\tremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n\t\t\t// Update function for both resolve and progress values\n\t\t\tupdateFunc = function( i, contexts, values ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tcontexts[ i ] = this;\n\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( values === progressValues ) {\n\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n\n\t\t\t\t\t} else if ( !(--remaining) ) {\n\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tprogressValues, progressContexts, resolveContexts;\n\n\t\t// add listeners to Deferred subordinates; treat others as resolved\n\t\tif ( length > 1 ) {\n\t\t\tprogressValues = new Array( length );\n\t\t\tprogressContexts = new Array( length );\n\t\t\tresolveContexts = new Array( length );\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n\t\t\t\t\tresolveValues[ i ].promise()\n\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject )\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\n\t\t\t\t} else {\n\t\t\t\t\t--remaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we're not waiting on anything, resolve the master\n\t\tif ( !remaining ) {\n\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n\t\t}\n\n\t\treturn deferred.promise();\n\t}\n});\n\n\n// The deferred used on DOM ready\nvar readyList;\n\njQuery.fn.ready = function( fn ) {\n\t// Add the callback\n\tjQuery.ready.promise().done( fn );\n\n\treturn this;\n};\n\njQuery.extend({\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( !document.body ) {\n\t\t\treturn setTimeout( jQuery.ready );\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.triggerHandler ) {\n\t\t\tjQuery( document ).triggerHandler( \"ready\" );\n\t\t\tjQuery( document ).off( \"ready\" );\n\t\t}\n\t}\n});\n\n/**\n * Clean-up method for dom ready events\n */\nfunction detach() {\n\tif ( document.addEventListener ) {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\t\twindow.removeEventListener( \"load\", completed, false );\n\n\t} else {\n\t\tdocument.detachEvent( \"onreadystatechange\", completed );\n\t\twindow.detachEvent( \"onload\", completed );\n\t}\n}\n\n/**\n * The ready event handler and self cleanup method\n */\nfunction completed() {\n\t// readyState === \"complete\" is good enough for us to call the dom ready in oldIE\n\tif ( document.addEventListener || event.type === \"load\" || document.readyState === \"complete\" ) {\n\t\tdetach();\n\t\tjQuery.ready();\n\t}\n}\n\njQuery.ready.promise = function( obj ) {\n\tif ( !readyList ) {\n\n\t\treadyList = jQuery.Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the browser event has already occurred.\n\t\t// we once tried to use readyState \"interactive\" here, but it caused issues like the one\n\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\tsetTimeout( jQuery.ready );\n\n\t\t// Standards-based browsers support DOMContentLoaded\n\t\t} else if ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\n\n\t\t// If IE event model is used\n\t\t} else {\n\t\t\t// Ensure firing before onload, maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", completed );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", completed );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar top = false;\n\n\t\t\ttry {\n\t\t\t\ttop = window.frameElement == null && document.documentElement;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( top && top.doScroll ) {\n\t\t\t\t(function doScrollCheck() {\n\t\t\t\t\tif ( !jQuery.isReady ) {\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Use the trick by Diego Perini\n\t\t\t\t\t\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\t\t\t\t\t\ttop.doScroll(\"left\");\n\t\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t\treturn setTimeout( doScrollCheck, 50 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// detach all dom ready events\n\t\t\t\t\t\tdetach();\n\n\t\t\t\t\t\t// and execute any waiting functions\n\t\t\t\t\t\tjQuery.ready();\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t}\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n\nvar strundefined = typeof undefined;\n\n\n\n// Support: IE<9\n// Iteration over object's inherited properties before its own\nvar i;\nfor ( i in jQuery( support ) ) {\n\tbreak;\n}\nsupport.ownLast = i !== \"0\";\n\n// Note: most support tests are defined in their respective modules.\n// false until the test is run\nsupport.inlineBlockNeedsLayout = false;\n\n// Execute ASAP in case we need to set body.style.zoom\njQuery(function() {\n\t// Minified: var a,b,c,d\n\tvar val, div, body, container;\n\n\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\tif ( !body || !body.style ) {\n\t\t// Return for frameset docs that don't have a body\n\t\treturn;\n\t}\n\n\t// Setup\n\tdiv = document.createElement( \"div\" );\n\tcontainer = document.createElement( \"div\" );\n\tcontainer.style.cssText = \"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\";\n\tbody.appendChild( container ).appendChild( div );\n\n\tif ( typeof div.style.zoom !== strundefined ) {\n\t\t// Support: IE<8\n\t\t// Check if natively block-level elements act like inline-block\n\t\t// elements when setting their display to 'inline' and giving\n\t\t// them layout\n\t\tdiv.style.cssText = \"display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1\";\n\n\t\tsupport.inlineBlockNeedsLayout = val = div.offsetWidth === 3;\n\t\tif ( val ) {\n\t\t\t// Prevent IE 6 from affecting layout for positioned elements #11048\n\t\t\t// Prevent IE from shrinking the body in IE 7 mode #12869\n\t\t\t// Support: IE<8\n\t\t\tbody.style.zoom = 1;\n\t\t}\n\t}\n\n\tbody.removeChild( container );\n});\n\n\n\n\n(function() {\n\tvar div = document.createElement( \"div\" );\n\n\t// Execute the test only if not already executed in another module.\n\tif (support.deleteExpando == null) {\n\t\t// Support: IE<9\n\t\tsupport.deleteExpando = true;\n\t\ttry {\n\t\t\tdelete div.test;\n\t\t} catch( e ) {\n\t\t\tsupport.deleteExpando = false;\n\t\t}\n\t}\n\n\t// Null elements to avoid leaks in IE.\n\tdiv = null;\n})();\n\n\n/**\n * Determines whether an object can have data\n */\njQuery.acceptData = function( elem ) {\n\tvar noData = jQuery.noData[ (elem.nodeName + \" \").toLowerCase() ],\n\t\tnodeType = +elem.nodeType || 1;\n\n\t// Do not set data on non-element DOM nodes because it will not be cleared (#8335).\n\treturn nodeType !== 1 && nodeType !== 9 ?\n\t\tfalse :\n\n\t\t// Nodes accept data unless otherwise specified; rejection can be conditional\n\t\t!noData || noData !== true && elem.getAttribute(\"classid\") === noData;\n};\n\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tvar name;\n\tfor ( name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nfunction internalData( elem, name, data, pvt /* Internal Use Only */ ) {\n\tif ( !jQuery.acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar ret, thisCache,\n\t\tinternalKey = jQuery.expando,\n\n\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t// can't GC object references properly across the DOM-JS boundary\n\t\tisNode = elem.nodeType,\n\n\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t// attached directly to the object so GC can occur automatically\n\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;\n\n\t// Avoid doing any more work than we need to when trying to get data on an\n\t// object that has no data at all\n\tif ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === \"string\" ) {\n\t\treturn;\n\t}\n\n\tif ( !id ) {\n\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t// ends up in the global cache\n\t\tif ( isNode ) {\n\t\t\tid = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;\n\t\t} else {\n\t\t\tid = internalKey;\n\t\t}\n\t}\n\n\tif ( !cache[ id ] ) {\n\t\t// Avoid exposing jQuery metadata on plain JS objects when the object\n\t\t// is serialized using JSON.stringify\n\t\tcache[ id ] = isNode ? {} : { toJSON: jQuery.noop };\n\t}\n\n\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t// shallow copied over onto the existing cache\n\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\tif ( pvt ) {\n\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t} else {\n\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t}\n\t}\n\n\tthisCache = cache[ id ];\n\n\t// jQuery data() is stored in a separate object inside the object's internal data\n\t// cache in order to avoid key collisions between internal data and user-defined\n\t// data.\n\tif ( !pvt ) {\n\t\tif ( !thisCache.data ) {\n\t\t\tthisCache.data = {};\n\t\t}\n\n\t\tthisCache = thisCache.data;\n\t}\n\n\tif ( data !== undefined ) {\n\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t}\n\n\t// Check for both converted-to-camel and non-converted data property names\n\t// If a data property was specified\n\tif ( typeof name === \"string\" ) {\n\n\t\t// First Try to find as-is property data\n\t\tret = thisCache[ name ];\n\n\t\t// Test for null|undefined property data\n\t\tif ( ret == null ) {\n\n\t\t\t// Try to find the camelCased property\n\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t}\n\t} else {\n\t\tret = thisCache;\n\t}\n\n\treturn ret;\n}\n\nfunction internalRemoveData( elem, name, pvt ) {\n\tif ( !jQuery.acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar thisCache, i,\n\t\tisNode = elem.nodeType,\n\n\t\t// See jQuery.data for more information\n\t\tcache = isNode ? jQuery.cache : elem,\n\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t// If there is already no cache entry for this object, there is no\n\t// purpose in continuing\n\tif ( !cache[ id ] ) {\n\t\treturn;\n\t}\n\n\tif ( name ) {\n\n\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\tif ( thisCache ) {\n\n\t\t\t// Support array or space separated string names for data keys\n\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\tname = [ name ];\n\t\t\t\t} else {\n\n\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tname = name.split(\" \");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = name.concat( jQuery.map( name, jQuery.camelCase ) );\n\t\t\t}\n\n\t\t\ti = name.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t}\n\n\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t// and let the cache object itself get destroyed\n\t\t\tif ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t// See jQuery.data for more information\n\tif ( !pvt ) {\n\t\tdelete cache[ id ].data;\n\n\t\t// Don't destroy the parent cache unless the internal data object\n\t\t// had been the only thing left in it\n\t\tif ( !isEmptyDataObject( cache[ id ] ) ) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// Destroy the cache\n\tif ( isNode ) {\n\t\tjQuery.cleanData( [ elem ], true );\n\n\t// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)\n\t/* jshint eqeqeq: false */\n\t} else if ( support.deleteExpando || cache != cache.window ) {\n\t\t/* jshint eqeqeq: true */\n\t\tdelete cache[ id ];\n\n\t// When all else fails, null\n\t} else {\n\t\tcache[ id ] = null;\n\t}\n}\n\njQuery.extend({\n\tcache: {},\n\n\t// The following elements (space-suffixed to avoid Object.prototype collisions)\n\t// throw uncatchable exceptions if you attempt to set expando properties\n\tnoData: {\n\t\t\"applet \": true,\n\t\t\"embed \": true,\n\t\t// ...but Flash objects (which have this classid) *can* handle expandos\n\t\t\"object \": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name );\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data, true );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name, true );\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[0],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Special expections of .data basically thwart jQuery.access,\n\t\t// so implement the relevant behavior ourselves\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t// Support: IE11+\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice(5) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn arguments.length > 1 ?\n\n\t\t\t// Sets one value\n\t\t\tthis.each(function() {\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t}) :\n\n\t\t\t// Gets one value\n\t\t\t// Try to fetch any internally stored data first\n\t\t\telem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\n\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray(data) ) {\n\t\t\t\t\tqueue = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// not intended for public consumption - generates a queueHooks object, or returns the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn jQuery._data( elem, key ) || jQuery._data( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tjQuery._removeData( elem, type + \"queue\" );\n\t\t\t\tjQuery._removeData( elem, key );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = jQuery._data( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\nvar pnum = (/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/).source;\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar isHidden = function( elem, el ) {\n\t\t// isHidden might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\t\treturn jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n\t};\n\n\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlength = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( jQuery.type( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\tjQuery.access( elems, fn, i, key[i], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn chainable ?\n\t\telems :\n\n\t\t// Gets\n\t\tbulk ?\n\t\t\tfn.call( elems ) :\n\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n};\nvar rcheckableType = (/^(?:checkbox|radio)$/i);\n\n\n\n(function() {\n\t// Minified: var a,b,c\n\tvar input = document.createElement( \"input\" ),\n\t\tdiv = document.createElement( \"div\" ),\n\t\tfragment = document.createDocumentFragment();\n\n\t// Setup\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\n\t// IE strips leading whitespace when .innerHTML is used\n\tsupport.leadingWhitespace = div.firstChild.nodeType === 3;\n\n\t// Make sure that tbody elements aren't automatically inserted\n\t// IE will insert them into empty tables\n\tsupport.tbody = !div.getElementsByTagName( \"tbody\" ).length;\n\n\t// Make sure that link elements get serialized correctly by innerHTML\n\t// This requires a wrapper element in IE\n\tsupport.htmlSerialize = !!div.getElementsByTagName( \"link\" ).length;\n\n\t// Makes sure cloning an html5 element does not cause problems\n\t// Where outerHTML is undefined, this still works\n\tsupport.html5Clone =\n\t\tdocument.createElement( \"nav\" ).cloneNode( true ).outerHTML !== \"<:nav></:nav>\";\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tinput.type = \"checkbox\";\n\tinput.checked = true;\n\tfragment.appendChild( input );\n\tsupport.appendChecked = input.checked;\n\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\t// Support: IE6-IE11+\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tfragment.appendChild( div );\n\tdiv.innerHTML = \"<input type='radio' checked='checked' name='t'/>\";\n\n\t// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3\n\t// old WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE<9\n\t// Opera does not clone events (and typeof div.attachEvent === undefined).\n\t// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()\n\tsupport.noCloneEvent = true;\n\tif ( div.attachEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\n\t\tdiv.cloneNode( true ).click();\n\t}\n\n\t// Execute the test only if not already executed in another module.\n\tif (support.deleteExpando == null) {\n\t\t// Support: IE<9\n\t\tsupport.deleteExpando = true;\n\t\ttry {\n\t\t\tdelete div.test;\n\t\t} catch( e ) {\n\t\t\tsupport.deleteExpando = false;\n\t\t}\n\t}\n})();\n\n\n(function() {\n\tvar i, eventName,\n\t\tdiv = document.createElement( \"div\" );\n\n\t// Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)\n\tfor ( i in { submit: true, change: true, focusin: true }) {\n\t\teventName = \"on\" + i;\n\n\t\tif ( !(support[ i + \"Bubbles\" ] = eventName in window) ) {\n\t\t\t// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)\n\t\t\tdiv.setAttribute( eventName, \"t\" );\n\t\t\tsupport[ i + \"Bubbles\" ] = div.attributes[ eventName ].expando === false;\n\t\t}\n\t}\n\n\t// Null elements to avoid leaks in IE.\n\tdiv = null;\n})();\n\n\nvar rformElems = /^(?:input|select|textarea)$/i,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)$/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\t\tvar tmp, events, t, handleObjIn,\n\t\t\tspecial, eventHandle, handleObj,\n\t\t\thandlers, type, namespaces, origType,\n\t\t\telemData = jQuery._data( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !(events = elemData.events) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !(eventHandle = elemData.handle) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !(handlers = events[ type ]) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\t\tvar j, handleObj, tmp,\n\t\t\torigCount, t, events,\n\t\t\tspecial, handlers, type,\n\t\t\tnamespaces, origType,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[2] && new RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdelete elemData.handle;\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery._removeData( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\tvar handle, ontype, cur,\n\t\t\tbubbleType, special, tmp, i,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split(\".\") : [];\n\n\t\tcur = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf(\":\") < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === (elem.ownerDocument || document) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {\n\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && jQuery.acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&\n\t\t\t\tjQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\ttry {\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486,#12518)\n\t\t\t\t\t\t// only reproducible on winXP IE8 native, not IE9 in IE8 mode\n\t\t\t\t\t}\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, ret, handleObj, matched, j,\n\t\t\thandlerQueue = [],\n\t\t\targs = slice.call( arguments ),\n\t\t\thandlers = ( jQuery._data( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( (event.result = ret) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\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\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar sel, handleObj, matches, i,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\t/* jshint eqeqeq: false */\n\t\t\tfor ( ; cur != this; cur = cur.parentNode || this ) {\n\t\t\t\t/* jshint eqeqeq: true */\n\n\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== \"click\") ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Fix target property (#1925)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Support: Chrome 23+, Safari?\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)\n\t\tevent.metaKey = !!event.metaKey;\n\n\t\treturn fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar body, eventDoc, doc,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tfocus: {\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.focus();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t\t// If we error on focus to hidden element (#1486, #12518),\n\t\t\t\t\t\t// let .trigger() run the handlers\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\t\tclick: {\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( jQuery.nodeName( this, \"input\" ) && this.type === \"checkbox\" && this.click ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t_default: function( event ) {\n\t\t\t\treturn jQuery.nodeName( event.target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tvar name = \"on\" + type;\n\n\t\tif ( elem.detachEvent ) {\n\n\t\t\t// #8545, #7054, preventing memory leaks for custom events in IE6-8\n\t\t\t// detachEvent needed property on element, by name of that event, to properly expose it to GC\n\t\t\tif ( typeof elem[ name ] === strundefined ) {\n\t\t\t\telem[ name ] = null;\n\t\t\t}\n\n\t\t\telem.detachEvent( name, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\t\t\t\t// Support: IE < 9, Android < 4.0\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If preventDefault exists, run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// Support: IE\n\t\t// Otherwise set the returnValue property of the original event to false\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// If stopPropagation exists, run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\n\t\t// Support: IE\n\t\t// Set the cancelBubble property of the original event to true\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopImmediatePropagation ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\",\n\tpointerenter: \"pointerover\",\n\tpointerleave: \"pointerout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !jQuery._data( form, \"submitBubbles\" ) ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( form, \"submitBubbles\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Allow triggered, simulated change events (#11500)\n\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, \"changeBubbles\" ) ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( elem, \"changeBubbles\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn !rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = jQuery._data( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tjQuery._data( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = jQuery._data( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tjQuery._removeData( doc, fix );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery._data( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar type, origFn;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[0];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n});\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\t\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:null|\\d+)\"/g,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /^$|\\/(?:java|ecma)script/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,\n\n\t// We have to close these tags to support XHTML (#13200)\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\tparam: [ 1, \"<object>\", \"</object>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n\t\t// unless wrapped in a div with non-breaking characters in front of it.\n\t\t_default: support.htmlSerialize ? [ 0, \"\", \"\" ] : [ 1, \"X<div>\", \"</div>\"  ]\n\t},\n\tsafeFragment = createSafeFragment( document ),\n\tfragmentDiv = safeFragment.appendChild( document.createElement(\"div\") );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\nfunction getAll( context, tag ) {\n\tvar elems, elem,\n\t\ti = 0,\n\t\tfound = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\ttypeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\tundefined;\n\n\tif ( !found ) {\n\t\tfor ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( !tag || jQuery.nodeName( elem, tag ) ) {\n\t\t\t\tfound.push( elem );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( found, getAll( elem, tag ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], found ) :\n\t\tfound;\n}\n\n// Used in buildFragment, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( rcheckableType.test( elem.type ) ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n\n// Support: IE<8\n// Manipulating tables requires a tbody\nfunction manipulationTarget( elem, content ) {\n\treturn jQuery.nodeName( elem, \"table\" ) &&\n\t\tjQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ?\n\n\t\telem.getElementsByTagName(\"tbody\")[0] ||\n\t\t\telem.appendChild( elem.ownerDocument.createElement(\"tbody\") ) :\n\t\telem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = (jQuery.find.attr( elem, \"type\" ) !== null) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\tif ( match ) {\n\t\telem.type = match[1];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar elem,\n\t\ti = 0;\n\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\tjQuery._data( elem, \"globalEval\", !refElements || jQuery._data( refElements[i], \"globalEval\" ) );\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction fixCloneNodeIssues( src, dest ) {\n\tvar nodeName, e, data;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 copies events bound via attachEvent when using cloneNode.\n\tif ( !support.noCloneEvent && dest[ jQuery.expando ] ) {\n\t\tdata = jQuery._data( dest );\n\n\t\tfor ( e in data.events ) {\n\t\t\tjQuery.removeEvent( dest, e, data.handle );\n\t\t}\n\n\t\t// Event data gets referenced instead of copied if the expando gets copied too\n\t\tdest.removeAttribute( jQuery.expando );\n\t}\n\n\t// IE blanks contents when cloning scripts, and tries to evaluate newly-set text\n\tif ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdisableScript( dest ).text = src.text;\n\t\trestoreScript( dest );\n\n\t// IE6-10 improperly clones children of object elements using classid.\n\t// IE10 throws NoModificationAllowedError if parent is null, #12132.\n\t} else if ( nodeName === \"object\" ) {\n\t\tif ( dest.parentNode ) {\n\t\t\tdest.outerHTML = src.outerHTML;\n\t\t}\n\n\t\t// This path appears unavoidable for IE9. When cloning an object\n\t\t// element in IE9, the outerHTML strategy above is not sufficient.\n\t\t// If the src has innerHTML and the destination does not,\n\t\t// copy the src.innerHTML into the dest.innerHTML. #10324\n\t\tif ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {\n\t\t\tdest.innerHTML = src.innerHTML;\n\t\t}\n\n\t} else if ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\n\t\tdest.defaultChecked = dest.checked = src.checked;\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.defaultSelected = dest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar destElements, node, clone, i, srcElements,\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\tif ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ) {\n\t\t\tclone = elem.cloneNode( true );\n\n\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t} else {\n\t\t\tfragmentDiv.innerHTML = elem.outerHTML;\n\t\t\tfragmentDiv.removeChild( clone = fragmentDiv.firstChild );\n\t\t}\n\n\t\tif ( (!support.noCloneEvent || !support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\t// Fix all IE cloning issues\n\t\t\tfor ( i = 0; (node = srcElements[i]) != null; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tfixCloneNodeIssues( node, destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0; (node = srcElements[i]) != null; i++ ) {\n\t\t\t\t\tcloneCopyEvent( node, destElements[i] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\tdestElements = srcElements = node = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar j, elem, contains,\n\t\t\ttmp, tag, tbody, wrap,\n\t\t\tl = elems.length,\n\n\t\t\t// Ensure a safe fragment\n\t\t\tsafe = createSafeFragment( context ),\n\n\t\t\tnodes = [],\n\t\t\ti = 0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || safe.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = (rtagName.exec( elem ) || [ \"\", \"\" ])[ 1 ].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\n\t\t\t\t\ttmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, \"<$1></$2>\" ) + wrap[2];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[0];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Manually add leading whitespace removed by IE\n\t\t\t\t\tif ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tnodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\telem = tag === \"table\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\ttmp.firstChild :\n\n\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\twrap[1] === \"<table>\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\t\ttmp :\n\t\t\t\t\t\t\t\t0;\n\n\t\t\t\t\t\tj = elem && elem.childNodes.length;\n\t\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( (tbody = elem.childNodes[j]), \"tbody\" ) && !tbody.childNodes.length ) {\n\t\t\t\t\t\t\t\telem.removeChild( tbody );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Fix #12392 for WebKit and IE > 9\n\t\t\t\t\ttmp.textContent = \"\";\n\n\t\t\t\t\t// Fix #12392 for oldIE\n\t\t\t\t\twhile ( tmp.firstChild ) {\n\t\t\t\t\t\ttmp.removeChild( tmp.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remember the top-level container for proper cleanup\n\t\t\t\t\ttmp = safe.lastChild;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Fix #11356: Clear elements from fragment\n\t\tif ( tmp ) {\n\t\t\tsafe.removeChild( tmp );\n\t\t}\n\n\t\t// Reset defaultChecked for any radios and checkboxes\n\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\tif ( !support.appendChecked ) {\n\t\t\tjQuery.grep( getAll( nodes, \"input\" ), fixDefaultChecked );\n\t\t}\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( safe.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttmp = null;\n\n\t\treturn safe;\n\t},\n\n\tcleanData: function( elems, /* internal */ acceptData ) {\n\t\tvar elem, type, id, data,\n\t\t\ti = 0,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tcache = jQuery.cache,\n\t\t\tdeleteExpando = support.deleteExpando,\n\t\t\tspecial = jQuery.event.special;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( acceptData || jQuery.acceptData( elem ) ) {\n\n\t\t\t\tid = elem[ internalKey ];\n\t\t\t\tdata = id && cache[ id ];\n\n\t\t\t\tif ( data ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove cache only if it was not already removed by jQuery.event.remove\n\t\t\t\t\tif ( cache[ id ] ) {\n\n\t\t\t\t\t\tdelete cache[ id ];\n\n\t\t\t\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t\t\t\t// we must handle all of these cases\n\t\t\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\t\t\tdelete elem[ internalKey ];\n\n\t\t\t\t\t\t} else if ( typeof elem.removeAttribute !== strundefined ) {\n\t\t\t\t\t\t\telem.removeAttribute( internalKey );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\telem[ internalKey ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdeletedIds.push( id );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t});\n\t},\n\n\tafter: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t});\n\t},\n\n\tremove: function( selector, keepData /* Internal Use Only */ ) {\n\t\tvar elem,\n\t\t\telems = selector ? jQuery.filter( selector, this ) : this,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\n\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t}\n\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t}\n\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\n\t\t\t// If this is a select, ensure that it displays empty (#12336)\n\t\t\t// Support: IE<9\n\t\t\tif ( elem.options && jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\telem.options.length = 0;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map(function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tundefined;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( support.htmlSerialize || !rnoshimcache.test( value )  ) &&\n\t\t\t\t( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ (rtagName.exec( value ) || [ \"\", \"\" ])[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar arg = arguments[ 0 ];\n\n\t\t// Make the changes, replacing each context element with the new content\n\t\tthis.domManip( arguments, function( elem ) {\n\t\t\targ = this.parentNode;\n\n\t\t\tjQuery.cleanData( getAll( this ) );\n\n\t\t\tif ( arg ) {\n\t\t\t\targ.replaceChild( elem, this );\n\t\t\t}\n\t\t});\n\n\t\t// Force removal if there was no new content (e.g., from empty arguments)\n\t\treturn arg && (arg.length || arg.nodeType) ? this : this.remove();\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, callback ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = concat.apply( [], args );\n\n\t\tvar first, node, hasScripts,\n\t\t\tscripts, doc, fragment,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[0],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction ||\n\t\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\t\treturn this.each(function( index ) {\n\t\t\t\tvar self = set.eq( index );\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\targs[0] = value.call( this, index, self.html() );\n\t\t\t\t}\n\t\t\t\tself.domManip( args, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\t\thasScripts = scripts.length;\n\n\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tnode = fragment;\n\n\t\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call( this[i], node, i );\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!jQuery._data( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\t\tif ( jQuery._evalUrl ) {\n\t\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.globalEval( ( node.text || node.textContent || node.innerHTML || \"\" ).replace( rcleanScript, \"\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fix #11809: Avoid leaking memory\n\t\t\t\tfragment = first = null;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\ti = 0,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone(true);\n\t\t\tjQuery( insert[i] )[ original ]( elems );\n\n\t\t\t// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\n\nvar iframe,\n\telemdisplay = {};\n\n/**\n * Retrieve the actual display of a element\n * @param {String} name nodeName of the element\n * @param {Object} doc Document object\n */\n// Called only from within defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar style,\n\t\telem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\n\t\t// getDefaultComputedStyle might be reliably used only on attached element\n\t\tdisplay = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?\n\n\t\t\t// Use of this method is a temporary fix (more like optmization) until something better comes along,\n\t\t\t// since it was removed from specification and supported only in FF\n\t\t\tstyle.display : jQuery.css( elem[ 0 ], \"display\" );\n\n\t// We don't have any data stored on the element,\n\t// so use \"detach\" method as fast way to get rid of the element\n\telem.detach();\n\n\treturn display;\n}\n\n/**\n * Try to determine the default display value of an element\n * @param {String} nodeName\n */\nfunction defaultDisplay( nodeName ) {\n\tvar doc = document,\n\t\tdisplay = elemdisplay[ nodeName ];\n\n\tif ( !display ) {\n\t\tdisplay = actualDisplay( nodeName, doc );\n\n\t\t// If the simple way fails, read from inside an iframe\n\t\tif ( display === \"none\" || !display ) {\n\n\t\t\t// Use the already-created iframe if possible\n\t\t\tiframe = (iframe || jQuery( \"<iframe frameborder='0' width='0' height='0'/>\" )).appendTo( doc.documentElement );\n\n\t\t\t// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse\n\t\t\tdoc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;\n\n\t\t\t// Support: IE\n\t\t\tdoc.write();\n\t\t\tdoc.close();\n\n\t\t\tdisplay = actualDisplay( nodeName, doc );\n\t\t\tiframe.detach();\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn display;\n}\n\n\n(function() {\n\tvar shrinkWrapBlocksVal;\n\n\tsupport.shrinkWrapBlocks = function() {\n\t\tif ( shrinkWrapBlocksVal != null ) {\n\t\t\treturn shrinkWrapBlocksVal;\n\t\t}\n\n\t\t// Will be changed later if needed.\n\t\tshrinkWrapBlocksVal = false;\n\n\t\t// Minified: var b,c,d\n\t\tvar div, body, container;\n\n\t\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\t\tif ( !body || !body.style ) {\n\t\t\t// Test fired too early or in an unsupported environment, exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Setup\n\t\tdiv = document.createElement( \"div\" );\n\t\tcontainer = document.createElement( \"div\" );\n\t\tcontainer.style.cssText = \"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\";\n\t\tbody.appendChild( container ).appendChild( div );\n\n\t\t// Support: IE6\n\t\t// Check if elements with layout shrink-wrap their children\n\t\tif ( typeof div.style.zoom !== strundefined ) {\n\t\t\t// Reset CSS: box-sizing; display; margin; border\n\t\t\tdiv.style.cssText =\n\t\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t\t// Vendor-prefix box-sizing\n\t\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;\" +\n\t\t\t\t\"box-sizing:content-box;display:block;margin:0;border:0;\" +\n\t\t\t\t\"padding:1px;width:1px;zoom:1\";\n\t\t\tdiv.appendChild( document.createElement( \"div\" ) ).style.width = \"5px\";\n\t\t\tshrinkWrapBlocksVal = div.offsetWidth !== 3;\n\t\t}\n\n\t\tbody.removeChild( container );\n\n\t\treturn shrinkWrapBlocksVal;\n\t};\n\n})();\nvar rmargin = (/^margin/);\n\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\n\n\nvar getStyles, curCSS,\n\trposition = /^(top|right|bottom|left)$/;\n\nif ( window.getComputedStyle ) {\n\tgetStyles = function( elem ) {\n\t\t// Support: IE<=11+, Firefox<=30+ (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\tif ( elem.ownerDocument.defaultView.opener ) {\n\t\t\treturn elem.ownerDocument.defaultView.getComputedStyle( elem, null );\n\t\t}\n\n\t\treturn window.getComputedStyle( elem, null );\n\t};\n\n\tcurCSS = function( elem, name, computed ) {\n\t\tvar width, minWidth, maxWidth, ret,\n\t\t\tstyle = elem.style;\n\n\t\tcomputed = computed || getStyles( elem );\n\n\t\t// getPropertyValue is only needed for .css('filter') in IE9, see #12537\n\t\tret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;\n\n\t\tif ( computed ) {\n\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\n\t\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t\t// Chrome < 17 and Safari 5.0 uses \"computed value\" instead of \"used value\" for margin-right\n\t\t\t// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n\t\t\t// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t\t// Remember the original values\n\t\t\t\twidth = style.width;\n\t\t\t\tminWidth = style.minWidth;\n\t\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t\t// Put in the new values to get a computed value out\n\t\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\t\tret = computed.width;\n\n\t\t\t\t// Revert the changed values\n\t\t\t\tstyle.width = width;\n\t\t\t\tstyle.minWidth = minWidth;\n\t\t\t\tstyle.maxWidth = maxWidth;\n\t\t\t}\n\t\t}\n\n\t\t// Support: IE\n\t\t// IE returns zIndex value as an integer.\n\t\treturn ret === undefined ?\n\t\t\tret :\n\t\t\tret + \"\";\n\t};\n} else if ( document.documentElement.currentStyle ) {\n\tgetStyles = function( elem ) {\n\t\treturn elem.currentStyle;\n\t};\n\n\tcurCSS = function( elem, name, computed ) {\n\t\tvar left, rs, rsLeft, ret,\n\t\t\tstyle = elem.style;\n\n\t\tcomputed = computed || getStyles( elem );\n\t\tret = computed ? computed[ name ] : undefined;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && style[ name ] ) {\n\t\t\tret = style[ name ];\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\t// but not position css attributes, as those are proportional to the parent element instead\n\t\t// and we can't measure the parent instead because it might trigger a \"stacking dolls\" problem\n\t\tif ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trs = elem.runtimeStyle;\n\t\t\trsLeft = rs && rs.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\t// Support: IE\n\t\t// IE returns zIndex value as an integer.\n\t\treturn ret === undefined ?\n\t\t\tret :\n\t\t\tret + \"\" || \"auto\";\n\t};\n}\n\n\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\t// Define the hook, we'll check on the first run if it's really needed.\n\treturn {\n\t\tget: function() {\n\t\t\tvar condition = conditionFn();\n\n\t\t\tif ( condition == null ) {\n\t\t\t\t// The test was not ready at this point; screw the hook this time\n\t\t\t\t// but check again when needed next time.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( condition ) {\n\t\t\t\t// Hook not needed (or it's not possible to use it due to missing dependency),\n\t\t\t\t// remove it.\n\t\t\t\t// Since there are no other hooks for marginRight, remove the whole object.\n\t\t\t\tdelete this.get;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\n\t\t\treturn (this.get = hookFn).apply( this, arguments );\n\t\t}\n\t};\n}\n\n\n(function() {\n\t// Minified: var b,c,d,e,f,g, h,i\n\tvar div, style, a, pixelPositionVal, boxSizingReliableVal,\n\t\treliableHiddenOffsetsVal, reliableMarginRightVal;\n\n\t// Setup\n\tdiv = document.createElement( \"div\" );\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\tstyle = a && a.style;\n\n\t// Finish early in limited (non-browser) environments\n\tif ( !style ) {\n\t\treturn;\n\t}\n\n\tstyle.cssText = \"float:left;opacity:.5\";\n\n\t// Support: IE<9\n\t// Make sure that element opacity exists (as opposed to filter)\n\tsupport.opacity = style.opacity === \"0.5\";\n\n\t// Verify style float existence\n\t// (IE uses styleFloat instead of cssFloat)\n\tsupport.cssFloat = !!style.cssFloat;\n\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\t// Support: Firefox<29, Android 2.3\n\t// Vendor-prefix box-sizing\n\tsupport.boxSizing = style.boxSizing === \"\" || style.MozBoxSizing === \"\" ||\n\t\tstyle.WebkitBoxSizing === \"\";\n\n\tjQuery.extend(support, {\n\t\treliableHiddenOffsets: function() {\n\t\t\tif ( reliableHiddenOffsetsVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn reliableHiddenOffsetsVal;\n\t\t},\n\n\t\tboxSizingReliable: function() {\n\t\t\tif ( boxSizingReliableVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn boxSizingReliableVal;\n\t\t},\n\n\t\tpixelPosition: function() {\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn pixelPositionVal;\n\t\t},\n\n\t\t// Support: Android 2.3\n\t\treliableMarginRight: function() {\n\t\t\tif ( reliableMarginRightVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn reliableMarginRightVal;\n\t\t}\n\t});\n\n\tfunction computeStyleTests() {\n\t\t// Minified: var b,c,d,j\n\t\tvar div, body, container, contents;\n\n\t\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\t\tif ( !body || !body.style ) {\n\t\t\t// Test fired too early or in an unsupported environment, exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Setup\n\t\tdiv = document.createElement( \"div\" );\n\t\tcontainer = document.createElement( \"div\" );\n\t\tcontainer.style.cssText = \"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\";\n\t\tbody.appendChild( container ).appendChild( div );\n\n\t\tdiv.style.cssText =\n\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t// Vendor-prefix box-sizing\n\t\t\t\"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;\" +\n\t\t\t\"box-sizing:border-box;display:block;margin-top:1%;top:1%;\" +\n\t\t\t\"border:1px;padding:1px;width:4px;position:absolute\";\n\n\t\t// Support: IE<9\n\t\t// Assume reasonable values in the absence of getComputedStyle\n\t\tpixelPositionVal = boxSizingReliableVal = false;\n\t\treliableMarginRightVal = true;\n\n\t\t// Check for getComputedStyle so that this code is not run in IE<9.\n\t\tif ( window.getComputedStyle ) {\n\t\t\tpixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== \"1%\";\n\t\t\tboxSizingReliableVal =\n\t\t\t\t( window.getComputedStyle( div, null ) || { width: \"4px\" } ).width === \"4px\";\n\n\t\t\t// Support: Android 2.3\n\t\t\t// Div with explicit width and no margin-right incorrectly\n\t\t\t// gets computed margin-right based on width of container (#3333)\n\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\tcontents = div.appendChild( document.createElement( \"div\" ) );\n\n\t\t\t// Reset CSS: box-sizing; display; margin; border; padding\n\t\t\tcontents.style.cssText = div.style.cssText =\n\t\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t\t// Vendor-prefix box-sizing\n\t\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;\" +\n\t\t\t\t\"box-sizing:content-box;display:block;margin:0;border:0;padding:0\";\n\t\t\tcontents.style.marginRight = contents.style.width = \"0\";\n\t\t\tdiv.style.width = \"1px\";\n\n\t\t\treliableMarginRightVal =\n\t\t\t\t!parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );\n\n\t\t\tdiv.removeChild( contents );\n\t\t}\n\n\t\t// Support: IE8\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\tdiv.innerHTML = \"<table><tr><td></td><td>t</td></tr></table>\";\n\t\tcontents = div.getElementsByTagName( \"td\" );\n\t\tcontents[ 0 ].style.cssText = \"margin:0;border:0;padding:0;display:none\";\n\t\treliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;\n\t\tif ( reliableHiddenOffsetsVal ) {\n\t\t\tcontents[ 0 ].style.display = \"\";\n\t\t\tcontents[ 1 ].style.display = \"none\";\n\t\t\treliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t}\n\n})();\n\n\n// A method for quickly swapping in/out CSS properties to get correct calculations.\njQuery.swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\nvar\n\t\tralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity\\s*=\\s*([^)]*)/,\n\n\t// swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n\t// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trnumsplit = new RegExp( \"^(\" + pnum + \")(.*)$\", \"i\" ),\n\trrelNum = new RegExp( \"^([+-])=(\" + pnum + \")\", \"i\" ),\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t},\n\n\tcssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ];\n\n\n// return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n\t// shortcut for names that are not vendor prefixed\n\tif ( name in style ) {\n\t\treturn name;\n\t}\n\n\t// check for vendor prefixed names\n\tvar capName = name.charAt(0).toUpperCase() + name.slice(1),\n\t\torigName = name,\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in style ) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn origName;\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem, hidden,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t}\n\t\t} else {\n\t\t\thidden = isHidden( elem );\n\n\t\t\tif ( display && display !== \"none\" || !hidden ) {\n\t\t\t\tjQuery._data( elem, \"olddisplay\", hidden ? display : jQuery.css( elem, \"display\" ) );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of most of the elements in a second loop\n\t// to avoid the constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n\t\t\telem.style.display = show ? values[ index ] || \"\" : \"none\";\n\t\t}\n\t}\n\n\treturn elements;\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\tvar matches = rnumsplit.exec( value );\n\treturn matches ?\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\tvar i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\n\t\t// Otherwise initialize for horizontal or vertical properties\n\t\tname === \"width\" ? 1 : 0,\n\n\t\tval = 0;\n\n\tfor ( ; i < 4; i += 2 ) {\n\t\t// both box models exclude margin, so add it if we want it\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\tif ( isBorderBox ) {\n\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\tif ( extra === \"content\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// at this point, extra isn't border nor margin, so remove border\n\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t} else {\n\t\t\t// at this point, extra isn't content, so add padding\n\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// at this point, extra isn't content nor padding, so add border\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property, which is equivalent to the border-box value\n\tvar valueIsBorderBox = true,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\tstyles = getStyles( elem ),\n\t\tisBorderBox = support.boxSizing && jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\tif ( val <= 0 || val == null ) {\n\t\t// Fall back to computed then uncomputed css if necessary\n\t\tval = curCSS( elem, name, styles );\n\t\tif ( val < 0 || val == null ) {\n\t\t\tval = elem.style[ name ];\n\t\t}\n\n\t\t// Computed unit is not pixels. Stop here and return.\n\t\tif ( rnumnonpx.test(val) ) {\n\t\t\treturn val;\n\t\t}\n\n\t\t// we need the check for style in case a browser which returns unreliable values\n\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\tvalueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles\n\t\t)\n\t) + \"px\";\n}\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Don't automatically add \"px\" to these possibly-unitless properties\n\tcssNumber: {\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"flexGrow\": true,\n\t\t\"flexShrink\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"order\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style;\n\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that null and NaN values aren't set. See: #7116\n\t\t\tif ( value == null || value !== value ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,\n\t\t\t// but it would mean to define eight (for every problematic property) identical functions\n\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf(\"background\") === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n\n\t\t\t\t// Support: IE\n\t\t\t\t// Swallow errors from 'invalid' CSS values (#5509)\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar num, val, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t//convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Return, converting to number if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || jQuery.isNumeric( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t}\n});\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\t// certain elements can have dimension info if we invisibly show them\n\t\t\t\t// however, it must have a current display style that would benefit from this\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) && elem.offsetWidth === 0 ?\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t}) :\n\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar styles = extra && getStyles( elem );\n\t\t\treturn setPositiveNumber( elem, value, extra ?\n\t\t\t\taugmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra,\n\t\t\t\t\tsupport.boxSizing && jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\tstyles\n\t\t\t\t) : 0\n\t\t\t);\n\t\t}\n\t};\n});\n\nif ( !support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( 0.01 * parseFloat( RegExp.$1 ) ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\t// if value === \"\", then remove inline opacity #12685\n\t\t\tif ( ( value >= 1 || value === \"\" ) &&\n\t\t\t\t\tjQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" &&\n\t\t\t\t\tstyle.removeAttribute ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there is no filter style applied in a css rule or unset inline opacity, we are done\n\t\t\t\tif ( value === \"\" || currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" },\n\t\t\t\tcurCSS, [ elem, \"marginRight\" ] );\n\t\t}\n\t}\n);\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( !rmargin.test( prefix ) ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n});\n\njQuery.fn.extend({\n\tcss: function( name, value ) {\n\t\treturn access( this, function( elem, name, value ) {\n\t\t\tvar styles, len,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t},\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tif ( typeof state === \"boolean\" ) {\n\t\t\treturn state ? this.show() : this.hide();\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( isHidden( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t});\n\t}\n});\n\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || \"swing\";\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\tif ( tween.elem[ tween.prop ] != null &&\n\t\t\t\t(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails\n\t\t\t// so, simple values such as \"10px\" are parsed to Float.\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\t\t\t// use step hook for back compat - use cssHook if its there - use .style if its\n\t\t\t// available and use plain properties where available\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Support: IE <=9\n// Panic based approach to setting things on disconnected nodes\n\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p * Math.PI ) / 2;\n\t}\n};\n\njQuery.fx = Tween.prototype.init;\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\n\n\n\nvar\n\tfxNow, timerId,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" ),\n\trrun = /queueHooks$/,\n\tanimationPrefilters = [ defaultPrefilter ],\n\ttweeners = {\n\t\t\"*\": [ function( prop, value ) {\n\t\t\tvar tween = this.createTween( prop, value ),\n\t\t\t\ttarget = tween.cur(),\n\t\t\t\tparts = rfxnum.exec( value ),\n\t\t\t\tunit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t\t\t// Starting value computation is required for potential unit mismatches\n\t\t\t\tstart = ( jQuery.cssNumber[ prop ] || unit !== \"px\" && +target ) &&\n\t\t\t\t\trfxnum.exec( jQuery.css( tween.elem, prop ) ),\n\t\t\t\tscale = 1,\n\t\t\t\tmaxIterations = 20;\n\n\t\t\tif ( start && start[ 3 ] !== unit ) {\n\t\t\t\t// Trust units reported by jQuery.css\n\t\t\t\tunit = unit || start[ 3 ];\n\n\t\t\t\t// Make sure we update the tween properties later on\n\t\t\t\tparts = parts || [];\n\n\t\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\t\tstart = +target || 1;\n\n\t\t\t\tdo {\n\t\t\t\t\t// If previous iteration zeroed out, double until we get *something*\n\t\t\t\t\t// Use a string for doubling factor so we don't accidentally see scale as unchanged below\n\t\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t\t// Adjust and apply\n\t\t\t\t\tstart = start / scale;\n\t\t\t\t\tjQuery.style( tween.elem, prop, start + unit );\n\n\t\t\t\t// Update scale, tolerating zero or NaN from tween.cur()\n\t\t\t\t// And breaking the loop if scale is unchanged or perfect, or if we've just had enough\n\t\t\t\t} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n\t\t\t}\n\n\t\t\t// Update tween properties\n\t\t\tif ( parts ) {\n\t\t\t\tstart = tween.start = +start || +target || 0;\n\t\t\t\ttween.unit = unit;\n\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\ttween.end = parts[ 1 ] ?\n\t\t\t\t\tstart + ( parts[ 1 ] + 1 ) * parts[ 2 ] :\n\t\t\t\t\t+parts[ 2 ];\n\t\t\t}\n\n\t\t\treturn tween;\n\t\t} ]\n\t};\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout(function() {\n\t\tfxNow = undefined;\n\t});\n\treturn ( fxNow = jQuery.now() );\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\tattrs = { height: type },\n\t\ti = 0;\n\n\t// if we include width, step value is 1 to do all cssExpand values,\n\t// if we don't include width, step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth ? 1 : 0;\n\tfor ( ; i < 4 ; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\nfunction createTween( value, prop, animation ) {\n\tvar tween,\n\t\tcollection = ( tweeners[ prop ] || [] ).concat( tweeners[ \"*\" ] ),\n\t\tindex = 0,\n\t\tlength = collection.length;\n\tfor ( ; index < length; index++ ) {\n\t\tif ( (tween = collection[ index ].call( animation, prop, value )) ) {\n\n\t\t\t// we're done with this property\n\t\t\treturn tween;\n\t\t}\n\t}\n}\n\nfunction defaultPrefilter( elem, props, opts ) {\n\t/* jshint validthis: true */\n\tvar prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHidden( elem ),\n\t\tdataShow = jQuery._data( elem, \"fxshow\" );\n\n\t// handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always(function() {\n\t\t\t// doing this makes sure that the complete handler will be called\n\t\t\t// before this completes\n\t\t\tanim.always(function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t// height/width overflow pass\n\tif ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n\t\t// Make sure that nothing sneaks out\n\t\t// Record all 3 overflow attributes because IE does not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t// Test default display if display is currently \"none\"\n\t\tcheckDisplay = display === \"none\" ?\n\t\t\tjQuery._data( elem, \"olddisplay\" ) || defaultDisplay( elem.nodeName ) : display;\n\n\t\tif ( checkDisplay === \"inline\" && jQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t// inline-level elements accept inline-block;\n\t\t\t// block-level elements need to be inline with layout\n\t\t\tif ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === \"inline\" ) {\n\t\t\t\tstyle.display = \"inline-block\";\n\t\t\t} else {\n\t\t\t\tstyle.zoom = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tif ( !support.shrinkWrapBlocks() ) {\n\t\t\tanim.always(function() {\n\t\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t\t});\n\t\t}\n\t}\n\n\t// show/hide pass\n\tfor ( prop in props ) {\n\t\tvalue = props[ prop ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ prop ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\n\t\t// Any non-fx value stops us from restoring the original display value\n\t\t} else {\n\t\t\tdisplay = undefined;\n\t\t}\n\t}\n\n\tif ( !jQuery.isEmptyObject( orig ) ) {\n\t\tif ( dataShow ) {\n\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\thidden = dataShow.hidden;\n\t\t\t}\n\t\t} else {\n\t\t\tdataShow = jQuery._data( elem, \"fxshow\", {} );\n\t\t}\n\n\t\t// store state if its toggle - enables .stop().toggle() to \"reverse\"\n\t\tif ( toggle ) {\n\t\t\tdataShow.hidden = !hidden;\n\t\t}\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done(function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t});\n\t\t}\n\t\tanim.done(function() {\n\t\t\tvar prop;\n\t\t\tjQuery._removeData( elem, \"fxshow\" );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t});\n\t\tfor ( prop in orig ) {\n\t\t\ttween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t// If this is a noop like .hide().hide(), restore an overwritten display value\n\t} else if ( (display === \"none\" ? defaultDisplay( elem.nodeName ) : display) === \"inline\" ) {\n\t\tstyle.display = display;\n\t}\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar index, name, easing, value, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t// also - reusing 'index' from above because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = animationPrefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\t\t\t// don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t}),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\t\t\t\t// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ]);\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise({\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, { specialEasing: {} }, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\t\t\t\t\t// if we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// resolve when we played the last frame\n\t\t\t\t// otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length ; index++ ) {\n\t\tresult = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tjQuery.map( props, createTween, animation );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t})\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\ttweener: function( props, callback ) {\n\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.split(\" \");\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length ; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\ttweeners[ prop ] = tweeners[ prop ] || [];\n\t\t\ttweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tanimationPrefilters.unshift( callback );\n\t\t} else {\n\t\t\tanimationPrefilters.push( callback );\n\t\t}\n\t}\n});\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t};\n\n\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.fn.extend({\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n\t\t\t// animate to the value specified\n\t\t\t.end().animate({ opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || jQuery._data( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\tdata = jQuery._data( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\thooks.stop.call( this, true );\n\t\t\t}\n\n\t\t\t// look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t});\n\t}\n});\n\njQuery.each([ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n});\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\"),\n\tslideUp: genFx(\"hide\"),\n\tslideToggle: genFx(\"toggle\"),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.timers = [];\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ttimers = jQuery.timers,\n\t\ti = 0;\n\n\tfxNow = jQuery.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\t\t// Checks the timer has not already been removed\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tjQuery.timers.push( timer );\n\tif ( timer() ) {\n\t\tjQuery.fx.start();\n\t} else {\n\t\tjQuery.timers.pop();\n\t}\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.start = function() {\n\tif ( !timerId ) {\n\t\ttimerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\tclearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\t// Default speed\n\t_default: 400\n};\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// http://blindsignals.com/index.php/2009/07/jquery-delay/\njQuery.fn.delay = function( time, type ) {\n\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\ttype = type || \"fx\";\n\n\treturn this.queue( type, function( next, hooks ) {\n\t\tvar timeout = setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\tclearTimeout( timeout );\n\t\t};\n\t});\n};\n\n\n(function() {\n\t// Minified: var a,b,c,d,e\n\tvar input, div, select, a, opt;\n\n\t// Setup\n\tdiv = document.createElement( \"div\" );\n\tdiv.setAttribute( \"className\", \"t\" );\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\ta = div.getElementsByTagName(\"a\")[ 0 ];\n\n\t// First batch of tests.\n\tselect = document.createElement(\"select\");\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName(\"input\")[ 0 ];\n\n\ta.style.cssText = \"top:1px\";\n\n\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\tsupport.getSetAttribute = div.className !== \"t\";\n\n\t// Get the style information from getAttribute\n\t// (IE uses .cssText instead)\n\tsupport.style = /top/.test( a.getAttribute(\"style\") );\n\n\t// Make sure that URLs aren't manipulated\n\t// (IE normalizes it by default)\n\tsupport.hrefNormalized = a.getAttribute(\"href\") === \"/a\";\n\n\t// Check the default checkbox/radio value (\"\" on WebKit; \"on\" elsewhere)\n\tsupport.checkOn = !!input.value;\n\n\t// Make sure that a selected-by-default option has a working selected property.\n\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\tsupport.optSelected = opt.selected;\n\n\t// Tests for enctype support on a form (#6743)\n\tsupport.enctype = !!document.createElement(\"form\").enctype;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Support: IE8 only\n\t// Check if we can trust getAttribute(\"value\")\n\tinput = document.createElement( \"input\" );\n\tinput.setAttribute( \"value\", \"\" );\n\tsupport.input = input.getAttribute( \"value\" ) === \"\";\n\n\t// Check if an input maintains its value after becoming a radio\n\tinput.value = \"t\";\n\tinput.setAttribute( \"type\", \"radio\" );\n\tsupport.radioValue = input.value === \"t\";\n})();\n\n\nvar rreturn = /\\r/g;\n\njQuery.fn.extend({\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\treturn val != null ?\n\t\t\t\t\tval :\n\t\t\t\t\t// Support: IE10-11+\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\tjQuery.trim( jQuery.text( elem ) );\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\" || index < 0,\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length,\n\t\t\t\t\ti = index < 0 ?\n\t\t\t\t\t\tmax :\n\t\t\t\t\t\tone ? index : 0;\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// oldIE doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t( support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null ) &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar optionSet, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\ti = options.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\tif ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {\n\n\t\t\t\t\t\t// Support: IE6\n\t\t\t\t\t\t// When new option element is added to select box we need to\n\t\t\t\t\t\t// force reflow of newly added node in order to workaround delay\n\t\t\t\t\t\t// of initialization properties\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\toption.selected = optionSet = true;\n\n\t\t\t\t\t\t} catch ( _ ) {\n\n\t\t\t\t\t\t\t// Will be executed only in IE6\n\t\t\t\t\t\t\toption.scrollHeight;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\toption.selected = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\n\t\t\t\treturn options;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Radios and checkboxes getter/setter\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t};\n\tif ( !support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\t// Support: Webkit\n\t\t\t// \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t};\n\t}\n});\n\n\n\n\nvar nodeHook, boolHook,\n\tattrHandle = jQuery.expr.attrHandle,\n\truseDefault = /^(?:checked|selected)$/i,\n\tgetSetAttribute = support.getSetAttribute,\n\tgetSetInput = support.input;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tattr: function( elem, name, value ) {\n\t\tvar hooks, ret,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === strundefined ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\n\t\t\t} else if ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\t\t\tret = jQuery.find.attr( elem, name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret == null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name, propName,\n\t\t\ti = 0,\n\t\t\tattrNames = value && value.match( rnotwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( (name = attrNames[i++]) ) {\n\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t// Boolean attributes get special treatment (#10870)\n\t\t\t\tif ( jQuery.expr.match.bool.test( name ) ) {\n\t\t\t\t\t// Set corresponding property to false\n\t\t\t\t\tif ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t// Also clear defaultChecked/defaultSelected (if appropriate)\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] =\n\t\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\n\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to default in case type is set after value during creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Hook for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\t\t\t// IE<8 needs the *property* name\n\t\t\telem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );\n\n\t\t// Use defaultChecked and defaultSelected for oldIE\n\t\t} else {\n\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] = elem[ name ] = true;\n\t\t}\n\n\t\treturn name;\n\t}\n};\n\n// Retrieve booleans specially\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?\n\t\tfunction( elem, name, isXML ) {\n\t\t\tvar ret, handle;\n\t\t\tif ( !isXML ) {\n\t\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\t\thandle = attrHandle[ name ];\n\t\t\t\tattrHandle[ name ] = ret;\n\t\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tnull;\n\t\t\t\tattrHandle[ name ] = handle;\n\t\t\t}\n\t\t\treturn ret;\n\t\t} :\n\t\tfunction( elem, name, isXML ) {\n\t\t\tif ( !isXML ) {\n\t\t\t\treturn elem[ jQuery.camelCase( \"default-\" + name ) ] ?\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tnull;\n\t\t\t}\n\t\t};\n});\n\n// fix oldIE attroperties\nif ( !getSetInput || !getSetAttribute ) {\n\tjQuery.attrHooks.value = {\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.defaultValue = value;\n\t\t\t} else {\n\t\t\t\t// Use nodeHook if defined (#1954); otherwise setAttribute is fine\n\t\t\t\treturn nodeHook && nodeHook.set( elem, value, name );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = {\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\telem.setAttributeNode(\n\t\t\t\t\t(ret = elem.ownerDocument.createAttribute( name ))\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tret.value = value += \"\";\n\n\t\t\t// Break association with cloned elements by also using setAttribute (#9646)\n\t\t\tif ( name === \"value\" || value === elem.getAttribute( name ) ) {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n\n\t// Some attributes are constructed with empty-string values when not defined\n\tattrHandle.id = attrHandle.name = attrHandle.coords =\n\t\tfunction( elem, name, isXML ) {\n\t\t\tvar ret;\n\t\t\tif ( !isXML ) {\n\t\t\t\treturn (ret = elem.getAttributeNode( name )) && ret.value !== \"\" ?\n\t\t\t\t\tret.value :\n\t\t\t\t\tnull;\n\t\t\t}\n\t\t};\n\n\t// Fixing value retrieval on a button requires this module\n\tjQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( ret && ret.specified ) {\n\t\t\t\treturn ret.value;\n\t\t\t}\n\t\t},\n\t\tset: nodeHook.set\n\t};\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tset: function( elem, value, name ) {\n\t\t\tnodeHook.set( elem, value === \"\" ? false : value, name );\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\nif ( !support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Note: IE uppercases css property names, but if we were to .toLowerCase()\n\t\t\t// .cssText, that would destroy case senstitivity in URL's, like in \"background\"\n\t\t\treturn elem.style.cssText || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = value + \"\" );\n\t\t}\n\t};\n}\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button|object)$/i,\n\trclickable = /^(?:a|area)$/i;\n\njQuery.fn.extend({\n\tprop: function( name, value ) {\n\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\treturn hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?\n\t\t\t\tret :\n\t\t\t\t( elem[ name ] = value );\n\n\t\t} else {\n\t\t\treturn hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ?\n\t\t\t\tret :\n\t\t\t\telem[ name ];\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\t// Use proper attribute retrieval(#12072)\n\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\treturn tabindex ?\n\t\t\t\t\tparseInt( tabindex, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\t-1;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Some attributes require a special call on IE\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !support.hrefNormalized ) {\n\t// href/src property should get the full normalized URL (#10299/#12915)\n\tjQuery.each([ \"href\", \"src\" ], function( i, name ) {\n\t\tjQuery.propHooks[ name ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\treturn elem.getAttribute( name, 4 );\n\t\t\t}\n\t\t};\n\t});\n}\n\n// Support: Safari, IE9+\n// mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t};\n}\n\njQuery.each([\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n});\n\n// IE6/7 call enctype encoding\nif ( !support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n\n\n\nvar rclass = /[\\t\\r\\n\\f]/g;\n\njQuery.fn.extend({\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j, finalValue,\n\t\t\ti = 0,\n\t\t\tlen = this.length,\n\t\t\tproceed = typeof value === \"string\" && value;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( proceed ) {\n\t\t\t// The disjunction here is for better compressibility (see removeClass)\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\" \"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = jQuery.trim( cur );\n\t\t\t\t\tif ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = finalValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j, finalValue,\n\t\t\ti = 0,\n\t\t\tlen = this.length,\n\t\t\tproceed = arguments.length === 0 || typeof value === \"string\" && value;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\t\tif ( proceed ) {\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\"\"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) >= 0 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = value ? jQuery.trim( cur ) : \"\";\n\t\t\t\t\tif ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = finalValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value;\n\n\t\tif ( typeof stateVal === \"boolean\" && type === \"string\" ) {\n\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t}\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tclassNames = value.match( rnotwhite ) || [];\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space separated list\n\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( type === strundefined || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed \"false\",\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n});\n\n\n\n\n// Return jQuery for attributes-only inclusion\n\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n});\n\njQuery.fn.extend({\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n\t}\n});\n\n\nvar nonce = jQuery.now();\n\nvar rquery = (/\\?/);\n\n\n\nvar rvalidtokens = /(,)|(\\[|{)|(}|])|\"(?:[^\"\\\\\\r\\n]|\\\\[\"\\\\\\/bfnrt]|\\\\u[\\da-fA-F]{4})*\"\\s*:?|true|false|null|-?(?!0\\d)\\d+(?:\\.\\d+|)(?:[eE][+-]?\\d+|)/g;\n\njQuery.parseJSON = function( data ) {\n\t// Attempt to parse using the native JSON parser first\n\tif ( window.JSON && window.JSON.parse ) {\n\t\t// Support: Android 2.3\n\t\t// Workaround failure to string-cast null input\n\t\treturn window.JSON.parse( data + \"\" );\n\t}\n\n\tvar requireNonComma,\n\t\tdepth = null,\n\t\tstr = jQuery.trim( data + \"\" );\n\n\t// Guard against invalid (and possibly dangerous) input by ensuring that nothing remains\n\t// after removing valid tokens\n\treturn str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {\n\n\t\t// Force termination if we see a misplaced comma\n\t\tif ( requireNonComma && comma ) {\n\t\t\tdepth = 0;\n\t\t}\n\n\t\t// Perform no more replacements after returning to outermost depth\n\t\tif ( depth === 0 ) {\n\t\t\treturn token;\n\t\t}\n\n\t\t// Commas must not follow \"[\", \"{\", or \",\"\n\t\trequireNonComma = open || comma;\n\n\t\t// Determine new depth\n\t\t// array/object open (\"[\" or \"{\"): depth += true - false (increment)\n\t\t// array/object close (\"]\" or \"}\"): depth += false - true (decrement)\n\t\t// other cases (\",\" or primitive): depth += true - true (numeric cast)\n\t\tdepth += !close - !open;\n\n\t\t// Remove this token\n\t\treturn \"\";\n\t}) ) ?\n\t\t( Function( \"return \" + str ) )() :\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n};\n\n\n// Cross-browser xml parsing\njQuery.parseXML = function( data ) {\n\tvar xml, tmp;\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\ttry {\n\t\tif ( window.DOMParser ) { // Standard\n\t\t\ttmp = new DOMParser();\n\t\t\txml = tmp.parseFromString( data, \"text/xml\" );\n\t\t} else { // IE\n\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\txml.async = \"false\";\n\t\t\txml.loadXML( data );\n\t\t}\n\t} catch( e ) {\n\t\txml = undefined;\n\t}\n\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\tjQuery.error( \"Invalid XML: \" + data );\n\t}\n\treturn xml;\n};\n\n\nvar\n\t// Document location\n\tajaxLocParts,\n\tajaxLocation,\n\n\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat(\"*\");\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( (dataType = dataTypes[i++]) ) {\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType.charAt( 0 ) === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif ( typeof dataTypeOrTransport === \"string\" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t});\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar deep, key,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\n/* Handles responses to an ajax request:\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\tvar firstDataType, ct, finalDataType, type,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes;\n\n\t// Remove auto dataType and get content-type in the process\n\twhile ( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader(\"Content-Type\");\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n/* Chain conversions given the request and the original response\n * Also sets the responseXXX fields on the jqXHR instance\n */\nfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\tvar conv2, current, conv, tmp, prev,\n\t\tconverters = {},\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice();\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\tcurrent = dataTypes.shift();\n\n\t// Convert to each sequential dataType\n\twhile ( current ) {\n\n\t\tif ( s.responseFields[ current ] ) {\n\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t}\n\n\t\t// Apply the dataFilter if provided\n\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t}\n\n\t\tprev = current;\n\t\tcurrent = dataTypes.shift();\n\n\t\tif ( current ) {\n\n\t\t\t// There's only work to do if current dataType is non-auto\n\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\tcurrent = prev;\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[ \"throws\" ] ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\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\t}\n\n\treturn { state: \"success\", data: response };\n}\n\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\",\n\t\t\tjson: \"responseJSON\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\t\t\t// Response headers as string\n\t\t\tresponseHeadersString,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\n\t\t\ttransport,\n\t\t\t// Response headers\n\t\t\tresponseHeaders,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\tjQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks(\"once memory\"),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( (match = rheaders.exec( responseHeadersString )) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || ajaxLocation ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( rnotwhite ) || [ \"\" ];\n\n\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) !==\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger(\"ajaxStart\");\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\tcacheURL = s.url;\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\tcacheURL = ( s.url += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data );\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\ts.url = rts.test( cacheURL ) ?\n\n\t\t\t\t\t// If there is already a '_' parameter, set its value\n\t\t\t\t\tcacheURL.replace( rts, \"$1_=\" + nonce++ ) :\n\n\t\t\t\t\t// Otherwise add one to the end\n\t\t\t\t\tcacheURL + ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + nonce++;\n\t\t\t}\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout(function() {\n\t\t\t\t\tjqXHR.abort(\"timeout\");\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Determine if successful\n\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( isSuccess ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"Last-Modified\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"etag\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 || s.type === \"HEAD\" ) {\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tstatusText = response.state;\n\t\t\t\t\tsuccess = response.data;\n\t\t\t\t\terror = response.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger(\"ajaxStop\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t}\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t});\n\t};\n});\n\n\njQuery._evalUrl = function( url ) {\n\treturn jQuery.ajax({\n\t\turl: url,\n\t\ttype: \"GET\",\n\t\tdataType: \"script\",\n\t\tasync: false,\n\t\tglobal: false,\n\t\t\"throws\": true\n\t});\n};\n\n\njQuery.fn.extend({\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t}\n});\n\n\njQuery.expr.filters.hidden = function( elem ) {\n\t// Support: Opera <= 12.12\n\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n\treturn elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||\n\t\t(!support.reliableHiddenOffsets() &&\n\t\t\t((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n};\n\njQuery.expr.filters.visible = function( elem ) {\n\treturn !jQuery.expr.filters.hidden( elem );\n};\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, value ) {\n\t\t\t// If value is a function, invoke it and return its value\n\t\t\tvalue = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t};\n\n\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\tif ( traditional === undefined ) {\n\t\ttraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t});\n\n\t} else {\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" ).replace( r20, \"+\" );\n};\n\njQuery.fn.extend({\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map(function() {\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t})\n\t\t.filter(function() {\n\t\t\tvar type = this.type;\n\t\t\t// Use .is(\":disabled\") so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t})\n\t\t.map(function( i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val ) {\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?\n\t// Support: IE6+\n\tfunction() {\n\n\t\t// XHR cannot access local files, always use ActiveX for that case\n\t\treturn !this.isLocal &&\n\n\t\t\t// Support: IE7-8\n\t\t\t// oldIE XHR does not support non-RFC2616 methods (#13240)\n\t\t\t// See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx\n\t\t\t// and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9\n\t\t\t// Although this check for six methods instead of eight\n\t\t\t// since IE also does not support \"trace\" and \"connect\"\n\t\t\t/^(get|post|head|put|delete|options)$/i.test( this.type ) &&\n\n\t\t\tcreateStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\nvar xhrId = 0,\n\txhrCallbacks = {},\n\txhrSupported = jQuery.ajaxSettings.xhr();\n\n// Support: IE<10\n// Open requests must be manually aborted on unload (#5280)\n// See https://support.microsoft.com/kb/2856746 for more info\nif ( window.attachEvent ) {\n\twindow.attachEvent( \"onunload\", function() {\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( undefined, true );\n\t\t}\n\t});\n}\n\n// Determine support properties\nsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nxhrSupported = support.ajax = !!xhrSupported;\n\n// Create transport if the browser can provide an xhr\nif ( xhrSupported ) {\n\n\tjQuery.ajaxTransport(function( options ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !options.crossDomain || support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\t\t\t\t\tvar i,\n\t\t\t\t\t\txhr = options.xhr(),\n\t\t\t\t\t\tid = ++xhrId;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\txhr.open( options.type, options.url, options.async, options.username, options.password );\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !options.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set headers\n\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t\t// IE's ActiveXObject throws a 'Type Mismatch' exception when setting\n\t\t\t\t\t\t// request header to a null-value.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// To keep consistent with other XHR implementations, cast the value\n\t\t\t\t\t\t// to string and ignore `undefined`.\n\t\t\t\t\t\tif ( headers[ i ] !== undefined ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] + \"\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( options.hasContent && options.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\t\t\t\t\t\tvar status, statusText, responses;\n\n\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\t\t\t\t\t\t\t// Clean up\n\t\t\t\t\t\t\tdelete xhrCallbacks[ id ];\n\t\t\t\t\t\t\tcallback = undefined;\n\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\n\t\t\t\t\t\t\t// Abort manually if needed\n\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\tstatus = xhr.status;\n\n\t\t\t\t\t\t\t\t// Support: IE<10\n\t\t\t\t\t\t\t\t// Accessing binary-data responseText throws an exception\n\t\t\t\t\t\t\t\t// (#11426)\n\t\t\t\t\t\t\t\tif ( typeof xhr.responseText === \"string\" ) {\n\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\tif ( !status && options.isLocal && !options.crossDomain ) {\n\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, xhr.getAllResponseHeaders() );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( !options.async ) {\n\t\t\t\t\t\t// if we're in sync mode we fire the callback\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else if ( xhr.readyState === 4 ) {\n\t\t\t\t\t\t// (IE6 & IE7) if it's in cache and has been\n\t\t\t\t\t\t// retrieved directly we need to fire the callback\n\t\t\t\t\t\tsetTimeout( callback );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Add to the list of active xhr callbacks\n\t\t\t\t\t\txhr.onreadystatechange = xhrCallbacks[ id ] = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback( undefined, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /(?:java|ecma)script/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || jQuery(\"head\")[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement(\"script\");\n\n\t\t\t\tscript.async = true;\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( script.parentNode ) {\n\t\t\t\t\t\t\tscript.parentNode.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = null;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending\n\t\t\t\t// Use native DOM manipulation to avoid our domManip AJAX trickery\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( undefined, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" && !( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") && rjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always(function() {\n\t\t\t// Restore preexisting value\n\t\t\twindow[ callbackName ] = overwritten;\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\t\t\t\t// make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t});\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// data: string of html\n// context (optional): If specified, the fragment will be created in this context, defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\tcontext = context || document;\n\n\tvar parsed = rsingleTag.exec( data ),\n\t\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[1] ) ];\n\t}\n\n\tparsed = jQuery.buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\n\n// Keep a copy of the old load method\nvar _load = jQuery.fn.load;\n\n/**\n * Load a url into a page\n */\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, response, type,\n\t\tself = this,\n\t\toff = url.indexOf(\" \");\n\n\tif ( off >= 0 ) {\n\t\tselector = jQuery.trim( url.slice( off, url.length ) );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\n\t\t\t// if \"type\" variable is undefined, then \"GET\" method will be used\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t}).done(function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery(\"<div>\").append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t}).complete( callback && function( jqXHR, status ) {\n\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t});\n\t}\n\n\treturn this;\n};\n\n\n\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [ \"ajaxStart\", \"ajaxStop\", \"ajaxComplete\", \"ajaxError\", \"ajaxSuccess\", \"ajaxSend\" ], function( i, type ) {\n\tjQuery.fn[ type ] = function( fn ) {\n\t\treturn this.on( type, fn );\n\t};\n});\n\n\n\n\njQuery.expr.filters.animated = function( elem ) {\n\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\treturn elem === fn.elem;\n\t}).length;\n};\n\n\n\n\n\nvar docElem = window.document.documentElement;\n\n/**\n * Gets a window from an element\n */\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\njQuery.offset = {\n\tsetOffset: function( elem, options, i ) {\n\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\tcurElem = jQuery( elem ),\n\t\t\tprops = {};\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tcurOffset = curElem.offset();\n\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\tjQuery.inArray(\"auto\", [ curCSSTop, curCSSLeft ] ) > -1;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\njQuery.fn.extend({\n\toffset: function( options ) {\n\t\tif ( arguments.length ) {\n\t\t\treturn options === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each(function( i ) {\n\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t});\n\t\t}\n\n\t\tvar docElem, win,\n\t\t\tbox = { top: 0, left: 0 },\n\t\t\telem = this[ 0 ],\n\t\t\tdoc = elem && elem.ownerDocument;\n\n\t\tif ( !doc ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure it's not a disconnected DOM node\n\t\tif ( !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box;\n\t\t}\n\n\t\t// If we don't have gBCR, just use 0,0 rather than error\n\t\t// BlackBerry 5, iOS 3 (original iPhone)\n\t\tif ( typeof elem.getBoundingClientRect !== strundefined ) {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t}\n\t\twin = getWindow( doc );\n\t\treturn {\n\t\t\ttop: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),\n\t\t\tleft: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )\n\t\t};\n\t},\n\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset,\n\t\t\tparentOffset = { top: 0, left: 0 },\n\t\t\telem = this[ 0 ];\n\n\t\t// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\t\t\t// we assume that getBoundingClientRect is available when computed position is fixed\n\t\t\toffset = elem.getBoundingClientRect();\n\t\t} else {\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset.top  += jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true );\n\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true );\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true)\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || docElem;\n\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) && jQuery.css( offsetParent, \"position\" ) === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent || docElem;\n\t\t});\n\t}\n});\n\n// Create scrollLeft and scrollTop methods\njQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\twin.document.documentElement[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\ttop ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// getComputedStyle returns percent when specified for top/left/bottom/right\n// rather than make the css module depend on the offset module, we just check for it here\njQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\tcomputed = curCSS( elem, prop );\n\t\t\t\t// if curCSS returns percentage, fallback to offset\n\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\tcomputed;\n\t\t\t}\n\t\t}\n\t);\n});\n\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name }, function( defaultExtra, funcName ) {\n\t\t// margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t\t// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n\t\t\t\t\t// isn't a whole lot we can do. See pull request at this URL for discussion:\n\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n\t\t\t\t\treturn elem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest\n\t\t\t\t\t// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t});\n});\n\n\n// The number of elements contained in the matched element set\njQuery.fn.size = function() {\n\treturn this.length;\n};\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\n\n\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine( \"jquery\", [], function() {\n\t\treturn jQuery;\n\t});\n}\n\n\n\n\nvar\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$;\n\njQuery.noConflict = function( deep ) {\n\tif ( window.$ === jQuery ) {\n\t\twindow.$ = _$;\n\t}\n\n\tif ( deep && window.jQuery === jQuery ) {\n\t\twindow.jQuery = _jQuery;\n\t}\n\n\treturn jQuery;\n};\n\n// Expose jQuery and $ identifiers, even in\n// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( typeof noGlobal === strundefined ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n\n\n\nreturn jQuery;\n\n}));\n"
  },
  {
    "path": "packages/jquery/main.js",
    "content": "var global = this;\n\ntry {\n  var jQuery = require(\"jquery\");\n} catch (e) {\n  jQuery = require(\"./jquery.js\");\n}\n\n// Provide values for the exported variables of the jquery package.\nexports.$ = exports.jQuery = jQuery;\n\n// There's no stopping legacy code from referring to window.$ or\n// window.jQuery, so we have to keep defining those properties globally,\n// but at least the exports of this package will be reliable.\nglobal.$ = global.$ || jQuery;\nglobal.jQuery = global.jQuery || jQuery;\n"
  },
  {
    "path": "packages/jquery/package.js",
    "content": "Package.describe({\n  summary: \"Manipulate the DOM using CSS selectors\",\n\n  // This is actually jQuery 1.11.2, but because of people bumping the\n  // patch number instead of the wrap number, we're higher than that.\n  // In fairness, there's no way to make an RC of a new version without\n  // bumping the patch number.\n  version: '1.11.9'\n});\n\nPackage.onUse(function (api) {\n  api.use('modules');\n\n  api.mainModule('main.js', 'client');\n\n  api.export('$', 'client');\n  api.export('jQuery', 'client');\n});\n"
  },
  {
    "path": "packages/jquery-waypoints/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/jquery-waypoints/README.md",
    "content": "# jquery-waypoints\n\nThis is a wrapper package for the JQuery Waypoints library. You can use it to add callbacks that fire when the user scrolls to certain elements on a page, for example to implement table of contents highlighting.\n\nSee the [JQuery Waypoints docs](http://imakewebthings.com/jquery-waypoints/) for more details."
  },
  {
    "path": "packages/jquery-waypoints/package.js",
    "content": "Package.describe({\n  summary: \"Run a function when the user scrolls past an element\",\n  version: \"1.0.9\"\n});\n\nPackage.onUse(function (api) {\n  api.use('jquery');\n  api.use('coffeescript');\n  api.addFiles('waypoints.coffee', 'client');\n});\n"
  },
  {
    "path": "packages/jquery-waypoints/waypoints.coffee",
    "content": "###\njQuery Waypoints - v2.0.4\nCopyright (c) 2011-2014 Caleb Troughton\nDual licensed under the MIT license and GPL license.\nhttps://github.com/imakewebthings/jquery-waypoints/blob/master/licenses.txt\n###\n((root, factory) ->\n  if typeof define is 'function' and define.amd\n    define 'waypoints', ['jquery'], ($) ->\n      factory $, root\n  else\n    factory root.jQuery, root\n) this, ($, window) ->\n  $w = $ window\n\n  # Touch support feature test\n  isTouch = 'ontouchstart' in window\n\n  # Internal plugin-wide variables:\n\n  # - allWaypoints: A hash containing two hashes, one for vertical waypoints\n  #   and one for horizontal waypoints. In each hash they value is a Waypoint\n  #   instance and the key is that waypoint's unique ID.\n\n  # - contextCounter: A counter that is incremented with each instantiation\n  #   of the Context class, used in its unique ID.\n\n  # - contexts: A hash of all contexts. The value of each entry is a Context\n  #   instance and the key is that context's unique ID.\n\n  # - contextKey: The DOM element for each context keeps a reference to the\n  #   context's unique ID in the jQuery .data() object. This is the key for\n  #   that data entry.\n\n  # - resizeEvent: The namespaced resize event used by contexts.\n\n  # - scrollEvent: The namespaced scroll event used by contexts.\n\n  # - waypointCounter: A counter that is incremented with each instantiation\n  #   of the Waypoint class, used in its unique ID.\n\n  # - waypointKey: The DOM element for each waypoint keeps a reference to an\n  #   array of the unique IDs of all waypoints attached to that element. This\n  #   array is kept in the jQuery .data() object, and this is the key for\n  #   that entry.\n\n  # - wp: A variable shortcut for the waypoint method name on the $.fn object.\n  #   Using this variable just helps with minification.\n\n  # - wps: A variable shortcut for the waypoints method name on the $ object.\n  #   Using this variable just helps with minification.\n\n  allWaypoints = \n    horizontal: {}\n    vertical: {}\n  contextCounter = 1\n  contexts = {}\n  contextKey = 'waypoints-context-id'\n  resizeEvent = 'resize.waypoints'\n  scrollEvent = 'scroll.waypoints'\n  waypointCounter = 1\n  waypointKey = 'waypoints-waypoint-ids'\n  wp = 'waypoint'\n  wps = 'waypoints'\n\n  # Context: Represents a single scrolling element in which waypoints live.\n  # For most users there will only be one Context, the window, but users can\n  # use other scrollable elements as a context using the \"context\" option\n  # when creating waypoints.\n\n  # Properties:\n\n  # - $element: jQuery object containing the context element.\n\n  # - element: The raw HTMLNode of the context element.\n\n  # - didResize: A flag used in throttling the resize event.\n\n  # - didScroll: A flag used in throttling the scroll event.\n\n  # - id: A unique identifier for the context.\n\n  # - oldScroll: A hash containing...\n  #   - x: The context's last known horizontal scroll value.\n  #   - y: The context's last known vertical scroll value.\n\n  # - waypoints: A hash containing two hashes with all waypoints in the context.\n  #   Entries are in the same style as the allWaypoints hashes:\n  #   (key = waypoint.id, value = waypoint)\n  #   - horizontal: A hash of all horizontal waypoints.\n  #   - vertical: A hash of all vertical waypoints.\n\n  class Context\n    constructor: ($element) ->\n      @$element = $element\n      @element = $element[0]\n      @didResize = no\n      @didScroll = no\n      @id = 'context' + contextCounter++\n      @oldScroll =\n        x: $element.scrollLeft()\n        y: $element.scrollTop()\n      @waypoints =\n        horizontal: {}\n        vertical: {}\n      \n      # We need to keep a reference to this Context instance on the DOM node\n      # so we can look it up later based on the node.\n      @element[contextKey] = @id\n\n      # To do that look up, we need to have this instance in the global hash.\n      contexts[@id] = this\n\n      # Run scroll checks on scroll, but throttle it for performance reasons.\n      $element.bind scrollEvent, =>\n        unless @didScroll or isTouch\n          @didScroll = yes\n          scrollHandler = =>\n            @doScroll()\n            @didScroll = no\n          window.setTimeout scrollHandler, $[wps].settings.scrollThrottle\n\n      # Run a refresh on resize, but throttle it for performance reasons.\n      $element.bind resizeEvent, =>\n        unless @didResize\n          @didResize = yes\n          resizeHandler = =>\n            $[wps] 'refresh'\n            @didResize = no\n          window.setTimeout resizeHandler, $[wps].settings.resizeThrottle\n\n    # doScroll()\n\n    # Looks at the new scroll values for the context, compares them to the old\n    # scroll values, and checks to see if any waypoints should be triggered\n    # by that change.\n    doScroll: ->\n\n      # We use some hashes with common values for each axis so that we can\n      # just iterate over it rather than write the whole thing twice for\n      # each axis.\n      axes =\n        horizontal:\n          newScroll: @$element.scrollLeft()\n          oldScroll: @oldScroll.x\n          forward: 'right'\n          backward: 'left'\n        vertical:\n          newScroll: @$element.scrollTop()\n          oldScroll: @oldScroll.y\n          forward: 'down'\n          backward: 'up'\n\n      # This is a small \"hack\" for iOS, needed because scrolls in mobile\n      # Safari that start or end with the URL bar showing will cause window\n      # height changes without firing a resize event.\n      if isTouch and (!axes.vertical.oldScroll or !axes.vertical.newScroll)\n          $[wps] 'refresh'\n\n      # For each axis, check to see if any waypoints have been crossed.\n      # Also determine the direction it's being crossed and sort/reverse all\n      # crossed waypoints accordingly. And, of course, trigger the waypoints.\n      $.each axes, (aKey, axis) =>\n        triggered = []\n        isForward = axis.newScroll > axis.oldScroll\n        direction = if isForward then axis.forward else axis.backward\n        $.each @waypoints[aKey], (wKey, waypoint) ->\n          if axis.oldScroll < waypoint.offset <= axis.newScroll\n            triggered.push waypoint\n          else if axis.newScroll < waypoint.offset <= axis.oldScroll\n            triggered.push waypoint\n        triggered.sort (a, b) -> a.offset - b.offset\n        triggered.reverse() unless isForward\n        $.each triggered, (i, waypoint) ->\n          if waypoint.options.continuous or i is triggered.length - 1\n            waypoint.trigger [direction]\n\n      # Now that we're done with the check, the new scroll values become\n      # the old scroll values for the next check.\n      @oldScroll =\n        x: axes.horizontal.newScroll\n        y: axes.vertical.newScroll\n\n    # refresh()\n    # Runs through all of the waypoints in the context and recalculates\n    # their offsets (the scroll value at which the waypoint is triggered.)\n    # If a change in offset also happens to cross the context's current\n    # scroll value, the waypoint will be triggered in the appropriate direction\n    # unless prevented by the \"onlyOnScroll\" waypoint option.\n    refresh: () ->\n      isWin = $.isWindow @element\n      cOffset = @$element.offset()\n\n      # Make sure we have the most up-to-date scroll values for our context.\n      @doScroll()\n\n      # Each axis recalculation needs to know some things:\n\n      # - contextOffset: The distance between the edge of the document and\n      #   the context element.\n      \n      # - contextScroll: The scroll value of the context. However, if the\n      #   context is the window this needs to be 0 because this value only\n      #   comes into play when used in adjustment calculations for non-window\n      #   context waypoints.\n\n      # - contextDimension: Width or height of the context.\n\n      # - oldScroll: The scroll value of the context. Unlike \"contextScroll\",\n      #   this is the same no matter the type of context, and is used when\n      #   determining whether a newly added waypoint should immediately fire\n      #   on its first offset calculation.\n\n      # - forward: Direction string passed to forward waypoint triggers.\n\n      # - backward: Direction string passed to backward waypoint triggers.\n\n      # - offsetProp: Key of the .offset() object for this axis.\n      axes =\n        horizontal:\n          contextOffset: if isWin then 0 else cOffset.left\n          contextScroll: if isWin then 0 else @oldScroll.x\n          contextDimension: @$element.width()\n          oldScroll: @oldScroll.x\n          forward: 'right'\n          backward: 'left'\n          offsetProp: 'left'\n        vertical:\n          contextOffset: if isWin then 0 else cOffset.top\n          contextScroll: if isWin then 0 else @oldScroll.y\n          contextDimension: if isWin then $[wps]('viewportHeight') else \\\n            @$element.height()\n          oldScroll: @oldScroll.y\n          forward: 'down'\n          backward: 'up'\n          offsetProp: 'top'\n\n      # For each axis, run through the waypoints. Store the old offset.\n      # Recalculate the new offset. Check the difference against the context's\n      # current scroll value and trigger any crossed waypoints accordingly.\n      $.each axes, (aKey, axis) =>\n        $.each @waypoints[aKey], (i, waypoint) ->\n          adjustment = waypoint.options.offset\n          oldOffset = waypoint.offset\n          elementOffset = if $.isWindow waypoint.element then 0 else \\\n            waypoint.$element.offset()[axis.offsetProp]\n\n          # The \"offset\" waypoint option (which we call \"adjustment\" here) can\n          # be a number, percentage string, keyword string (bottom-in-view),\n          # or a function. So we deal with all of these types here.\n          if $.isFunction adjustment\n            adjustment = adjustment.apply waypoint.element\n          else if typeof adjustment is 'string'\n            adjustment = parseFloat adjustment\n            if waypoint.options.offset.indexOf('%') > -1\n              adjustment = Math.ceil(axis.contextDimension * adjustment / 100)\n\n          # We've finally calculated all the crazy little adjustments that\n          # can come from using non-window contexts and the \"offset\" option.\n          # Store the damn thing.\n          waypoint.offset = elementOffset \\\n                          - axis.contextOffset \\\n                          + axis.contextScroll \\\n                          - adjustment\n\n          # \"onlyOnScroll\" tells us to not even consider triggering waypoints\n          # during refresh, so we can eject early.\n          return if (waypoint.options.onlyOnScroll and oldOffset?) or \\\n                    !waypoint.enabled\n\n          # Case where the refresh causes a backward trigger.\n          if oldOffset isnt null and \\\n            oldOffset < axis.oldScroll <= waypoint.offset\n              waypoint.trigger [axis.backward]\n\n          # Now the forward case.\n          else if oldOffset isnt null and \\\n            oldOffset > axis.oldScroll >= waypoint.offset\n              waypoint.trigger [axis.forward]\n\n          # \"oldOffset\" values of null mean this is the first calculation of\n          # the waypoint's offset. It's a special time in a waypoint's life.\n          else if oldOffset is null and axis.oldScroll >= waypoint.offset\n            waypoint.trigger [axis.forward]\n\n    # checkEmpty()\n\n    # Looks at the waypoints hashes. If they are empty, the context removes\n    # itself from the global contexts hash.\n    checkEmpty: ->\n      if $.isEmptyObject(@waypoints.horizontal) and \\\n        $.isEmptyObject(@waypoints.vertical)\n          @$element.unbind [resizeEvent, scrollEvent].join(' ')\n          delete contexts[@id]\n\n  # Waypoint: Represents a single callback function tied to an element. An\n  # element can have multiple waypoints with multiple offsets.\n\n  # Properties:\n\n  # - $element: jQuery object containing the waypoint element.\n\n  # - element: The raw HTMLNode of the waypoint element.\n\n  # - axis: 'horizontal' || 'vertical' - The axis on which this waypoint lives.\n\n  # - callback: The function that is fired when the waypoint is triggered.\n\n  # - context: A reference to the context this waypoint belongs to.\n\n  # - enabled: Boolean indicating whether this waypoint is enabled or not.\n  #   Disabled waypoints are still returned in functions that aggregate\n  #   waypoints, but do not fire their callbacks.\n\n  # - id: A unique identifier for the waypoint.\n\n  # - offset: The scroll offset at which the waypoint should trigger.\n\n  # - options: A hash containing the various waypoint options.\n  #   See $.fn.waypoint.defaults for more information on those options.\n  class Waypoint\n    constructor: ($element, context, options) ->\n      options = $.extend {}, $.fn[wp].defaults, options\n      if options.offset is 'bottom-in-view'\n        options.offset = ->\n          contextHeight = $[wps] 'viewportHeight'\n          unless $.isWindow context.element\n            contextHeight = context.$element.height()\n          contextHeight - $(this).outerHeight()\n\n      @$element = $element\n      @element = $element[0]\n      @axis = if options.horizontal then 'horizontal' else 'vertical'\n      @callback = options.handler\n      @context = context\n      @enabled = options.enabled\n      @id = 'waypoints' + waypointCounter++\n      @offset = null\n      @options = options\n\n      # Add our new waypoint to its context.\n      context.waypoints[@axis][@id] = this\n\n      # Add it to the global hash.\n      allWaypoints[@axis][@id] = this\n\n      # Add the waypoint's id to the element's waypoint id list.\n      idList = @element[waypointKey] ? []\n      idList.push @id\n      @element[waypointKey] = idList\n    \n    # trigger(array)\n\n    # Calls the waypoint's callback function, passing to it the arguments\n    # supplied in the \"args\" array.\n    trigger: (args) ->\n      return unless @enabled\n      if @callback?\n        @callback.apply @element, args\n      if @options.triggerOnce\n        @destroy()\n\n    # disable()\n\n    # Temporarily disables a waypoint from firing its callback.\n    disable: ->\n      @enabled = false\n\n    # enable()\n\n    # Breathe life back into the waypoint.\n    enable: ->\n      @context.refresh()\n      @enabled = true\n\n    # destroy()\n\n    # Kills the waypoint for good.\n    destroy: ->\n      delete allWaypoints[@axis][@id]\n      delete @context.waypoints[@axis][@id]\n      @context.checkEmpty()\n\n    # Waypoint.getWaypointsByElement(HTMLNode)\n\n    # Returns an array of all Waypoint instances attached to the \"element\"\n    # HTMLNode. Returns an empty array if there are no attached waypoints.\n    @getWaypointsByElement: (element) ->\n      ids = element[waypointKey]\n      return [] unless ids\n      all = $.extend {}, allWaypoints.horizontal, allWaypoints.vertical\n      $.map ids, (id) ->\n        all[id]\n\n  # These methods are available on the $.fn object by using the method\n  # name as the first argument to .waypoint. Ex: $('div').waypoint('destroy')\n  methods =\n\n    # init(function, object)\n\n    # Creates a new waypoint (and if needed, a new context) using the supplied\n    # callback function and options.\n\n    # The \"f\" function and the \"options\" object are both optional, but at least\n    # one must be supplied. So acceptable signatures are:\n\n    # - .waypoint(f)\n    # - .waypoint(options)\n    # - .waypoint(f, options)\n\n    # This \"init\" method should never need to be called explicity by the user.\n    # It is the default method that is delegated to when .waypoint is called\n    # with one of the above signatures.\n\n    # Ex: $('div').waypoint(function(direction) {\n    #   // Do things\n    # }, { offset: '100%' });\n    init: (f, options) ->\n      options ?= {}\n      options.handler ?= f\n\n      @each ->\n        $this = $ this\n        contextElement = options.context ? $.fn[wp].defaults.context\n        unless $.isWindow contextElement\n          contextElement = $this.closest contextElement\n        contextElement = $ contextElement\n        context = contexts[contextElement[0][contextKey]]\n        context = new Context contextElement unless context\n        new Waypoint $this, context, options\n      $[wps] 'refresh'\n      this\n\n    # Disable, enable, and destroy all just delegate to the instance methods\n    # of the waypoints attached to the subject elements.\n    disable: -> methods._invoke.call this, 'disable'\n    enable: -> methods._invoke.call this, 'enable'\n    destroy: -> methods._invoke.call this, 'destroy'\n\n    # .waypoint('prev', string, string|HTMLNode|jQuery)\n\n    # Returns a jQuery object containing previous waypoint elements. This\n    # creates a new entry in the jQuery object stack just like jQuery's prev\n    # function. \"axis\" indicates the axis on which to traverse\n    # ('horizontal' | 'vertical') and \"selector\" indicates which context\n    # element to use. The defaults are 'vertical' and window respectively.\n    prev: (axis, selector) ->\n      methods._traverse.call this, axis, selector, (stack, index, waypoints) ->\n        stack.push waypoints[index-1] if index > 0\n\n    # .waypoint('next', string, string|HTMLNode|jQuery)\n\n    # Returns a jQuery object containing next waypoint elements. This\n    # creates a new entry in the jQuery object stack just like jQuery's next\n    # function. \"axis\" indicates the axis on which to traverse\n    # ('horizontal' | 'vertical') and \"selector\" indicates which context\n    # element to use. The defaults are 'vertical' and window respectively.\n    next: (axis, selector) ->\n      methods._traverse.call this, axis, selector, (stack, index, waypoints) ->\n        stack.push waypoints[index+1] if index < waypoints.length-1\n\n    # Internal: Aggregates waypoints on a given axis of a context, and applies\n    # a \"push\" callback for each element in the subject jQuery object. This\n    # callback builds the element array to push to the jQuery stack.\n    _traverse: (axis = 'vertical', selector = window, push) ->\n      waypoints = jQMethods.aggregate selector\n      stack = []\n      @each ->\n        index = $.inArray this, waypoints[axis]\n        push stack, index, waypoints[axis]\n      @pushStack stack\n\n    # Internal: Finds all waypoints on a given set of \"$elements\" and invokes\n    # \"method\" on each instance.\n    _invoke: (method) ->\n      this.each ->\n        waypoints = Waypoint.getWaypointsByElement this\n        $.each waypoints, (i, waypoint) ->\n          waypoint[method]()\n          true\n      this\n\n  # $.fn.waypoint. Let's just hook this guy up to our methods hash and\n  # add some trivial error reporting for bogus calls.\n  $.fn[wp] = (method, args...) ->\n    if methods[method]\n      methods[method].apply this, args\n    else if $.isFunction(method)\n      methods.init.apply this, arguments\n    else if $.isPlainObject(method)\n      methods.init.apply this, [null, method]\n    else if !method\n      $.error \"jQuery Waypoints needs a callback function or handler option.\"\n    else\n      $.error \"The #{method} method does not exist in jQuery Waypoints.\"\n\n  # The default options object for a waypoint.\n\n  # - context: string|HTMLNode|jQuery - The scrollable element that the\n  #   waypoint acts within. The waypoint will look for the closest ancestor\n  #   element that matches this selector or node.\n\n  # - continuous: Multiple waypoints may be triggered by a single scroll check.\n  #   If you would like a waypoint to only trigger if it is the last waypoint\n  #   in a scroll check, set this to false.\n\n  # - enabled: Should this waypoint start enabled (true) or disabled (false)?\n\n  # - handler: This option is not defined by default, but can be used as an\n  #   alternate way to pass the waypoint callback function, rather than as\n  #   the first argument to .waypoint.\n\n  #   Ex: $('div').waypoint({\n  #     handler: function(direction) { ... }\n  #   });\n\n  # - horizontal: Set this to true if the waypoint is, well, horizontal.\n\n  # - offset: number|string|function - Determines how far from the top (or left\n  #   if the waypoint is horizontal) of the context's viewport to trigger the\n  #   waypoint. The default of 0 means that the waypoint is triggered when the\n  #   top of the waypoint element hits the top of the window/context-element.\n  #   An offset of 50 would mean the waypoint triggers when the top of the\n  #   element is 50 pixels from the top of the window.\n\n  #   A % string is translated into a percentage of the width/height of\n  #   the context.\n\n  #   If a function is passed, that function should return a number. The \"this\"\n  #   keyword within this function will be set to the raw HTMLNode of the\n  #   waypoint element.\n\n  # - triggerOnce: If true, the waypoint will destroy itself after\n  #   first trigger.\n  $.fn[wp].defaults =\n    context: window\n    continuous: true\n    enabled: true\n    horizontal: false\n    offset: 0\n    triggerOnce: false\n    \n  # These methods are available on the $ object by using the method name as\n  # the first argument to .waypoint. Ex: $.waypoints('refresh')\n  jQMethods =\n\n    # $.waypoints('refresh')\n\n    # Forces a refresh on all contexts, recalculating all waypoint offsets.\n    # This is done automatically on waypoint addition and during resize events,\n    # but if a user does something to change the DOM, CSS, or in some way\n    # change the layout of a page and its elements, they might need to call\n    # this method manually.\n    refresh: ->\n      $.each contexts, (i, context) -> context.refresh()\n    \n    # $.waypoints('viewportHeight')\n\n    # A utility method that returns the window height, but takes into account\n    # inconsistencies that come with just using jQuery's .height() on iOS.\n    viewportHeight: ->\n      window.innerHeight ? $w.height()\n\n    # $.waypoints(['aggregate'], [contextSelector])\n\n    # Returns an object containing two HTMLNode arrays, one for each axis:\n\n    # {\n    #   horizontal: [ HTMLNode... ]\n    #   vertical: [ HTMLNode... ]\n    # }\n      \n    # This is the default method used when calling $.waypoints(). If\n    # \"contextSelector\" is not supplied, it returns all waypoints. If\n    # \"contextSelector\" is supplied it only returns waypoints for that context.\n\n    # The array of waypoint elements is returned sorted by calculated offset,\n    # the order in which they would be triggered on the page.\n    aggregate: (contextSelector) ->\n      collection = allWaypoints\n      if contextSelector\n        collection = contexts[$(contextSelector)[0][contextKey]]?.waypoints\n      return [] unless collection\n      waypoints =\n        horizontal: []\n        vertical: []\n      $.each waypoints, (axis, arr) ->\n        $.each collection[axis], (key, waypoint) ->\n          arr.push waypoint\n        arr.sort (a, b) -> a.offset - b.offset\n        waypoints[axis] = $.map arr, (waypoint) -> waypoint.element\n        waypoints[axis] = $.unique waypoints[axis]\n      waypoints\n\n    # $.waypoints('above', [string|HTMLNode|jQuery])\n\n    # Returns all vertical waypoints that lie above the current scroll position\n    # of the context specified by \"contextSelector\". If no \"contextSelector\"\n    # is supplied, it defaults to the window.\n    above: (contextSelector = window) ->\n      jQMethods._filter contextSelector, 'vertical', (context, waypoint) ->\n        waypoint.offset <= context.oldScroll.y\n\n    # $.waypoints('below', [string|HTMLNode|jQuery])\n\n    # Returns all vertical waypoints that lie below the current scroll position\n    # of the context specified by \"contextSelector\". If no \"contextSelector\"\n    # is supplied, it defaults to the window.\n    below: (contextSelector = window) ->\n      jQMethods._filter contextSelector, 'vertical', (context, waypoint) ->\n        waypoint.offset > context.oldScroll.y\n\n    # $.waypoints('left', [string|HTMLNode|jQuery])\n\n    # Returns all horizontal waypoints left of the current scroll position\n    # of the context specified by \"contextSelector\". If no \"contextSelector\"\n    # is supplied, it defaults to the window.\n    left: (contextSelector = window) ->\n      jQMethods._filter contextSelector, 'horizontal', (context, waypoint) ->\n        waypoint.offset <= context.oldScroll.x\n\n    # $.waypoints('right', [string|HTMLNode|jQuery])\n\n    # Returns all horizontal waypoints right of the current scroll position\n    # of the context specified by \"contextSelector\". If no \"contextSelector\"\n    # is supplied, it defaults to the window.\n    right: (contextSelector = window) ->\n      jQMethods._filter contextSelector, 'horizontal', (context, waypoint) ->\n        waypoint.offset > context.oldScroll.x\n\n    # $.waypoints('enable/disable/destroy')\n\n    # These methods delegate to the enable/disable/destroy instance methods \n    # for all waypoints.\n    enable: -> jQMethods._invoke 'enable'\n    disable: -> jQMethods._invoke 'disable'\n    destroy: -> jQMethods._invoke 'destroy'\n\n    # $.waypoints('extendFn', string, function)\n\n    # Extends the $.fn.waypoint method object with a new method, \"f\". This\n    # just lets other modules piggyback on the .waypoint namespace.\n    extendFn: (methodName, f) ->\n      methods[methodName] = f\n\n    # Internal: Invokes \"method\" on all waypoints.\n    _invoke: (method) ->\n      waypoints = $.extend {}, allWaypoints.vertical, allWaypoints.horizontal\n      $.each waypoints, (key, waypoint) ->\n        waypoint[method]()\n        true\n\n    # Internal: Returns an array of all HTMLNodes for each waypoint that passes\n    # the \"test\" function. Only waypoints within the \"selector\" context on the\n    # \"axis\" axis are tested. As with .aggregate, the array is sorted by\n    # calculated offset (trigger order).\n    _filter: (selector, axis, test) ->\n      context = contexts[$(selector)[0][contextKey]]\n      return [] unless context\n      waypoints = []\n      $.each context.waypoints[axis], (i, waypoint) ->\n        waypoints.push waypoint if test context, waypoint\n      waypoints.sort (a, b) -> a.offset - b.offset\n      $.map waypoints, (waypoint) -> waypoint.element\n\n  # Hook up jQMethods to the $.waypoints namespace.\n  $[wps] = (method, args...) ->\n    if jQMethods[method]\n      jQMethods[method].apply null, args\n    else\n      jQMethods.aggregate.call null, method\n\n  # Plugin-wide settings:\n\n  # - resizeThrottle: For performance reasons, the refresh performed during\n  #   resizes is throttled. This value is the rate-limit in milliseconds\n  #   between resize refreshes. For more information on throttling, check out\n  #   Ben Alman’s throttle / debounce plugin.\n  #   http://benalman.com/projects/jquery-throttle-debounce-plugin/\n\n  # - scrollThrottle: For performance reasons, checking for any crossed\n  #   waypoints during a scroll event is throttled. This value is the\n  #   rate-limit in milliseconds between scroll checks. For more information\n  #   on throttling, check out Ben Alman’s throttle / debounce plugin.\n  #   http://benalman.com/projects/jquery-throttle-debounce-plugin/\n\n  $[wps].settings =\n    resizeThrottle: 100\n    scrollThrottle: 30\n\n  # Ensure a refresh on page load. Newly loaded images often shift layout.\n  $w.load -> $[wps] 'refresh'\n"
  },
  {
    "path": "packages/jshint/.npm/plugin/lintJshint/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/jshint/.npm/plugin/lintJshint/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/jshint/.npm/plugin/lintJshint/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"jshint\": {\n      \"version\": \"2.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/jshint/-/jshint-2.7.0.tgz\",\n      \"from\": \"https://registry.npmjs.org/jshint/-/jshint-2.7.0.tgz\",\n      \"dependencies\": {\n        \"cli\": {\n          \"version\": \"0.6.6\",\n          \"resolved\": \"https://registry.npmjs.org/cli/-/cli-0.6.6.tgz\",\n          \"from\": \"https://registry.npmjs.org/cli/-/cli-0.6.6.tgz\",\n          \"dependencies\": {\n            \"glob\": {\n              \"version\": \"3.2.11\",\n              \"resolved\": \"https://registry.npmjs.org/glob/-/glob-3.2.11.tgz\",\n              \"from\": \"https://registry.npmjs.org/glob/-/glob-3.2.11.tgz\",\n              \"dependencies\": {\n                \"inherits\": {\n                  \"version\": \"2.0.1\",\n                  \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\"\n                },\n                \"minimatch\": {\n                  \"version\": \"0.3.0\",\n                  \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz\",\n                  \"dependencies\": {\n                    \"lru-cache\": {\n                      \"version\": \"2.6.1\",\n                      \"resolved\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.1.tgz\",\n                      \"from\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.1.tgz\"\n                    },\n                    \"sigmund\": {\n                      \"version\": \"1.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz\",\n                      \"from\": \"https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz\"\n                    }\n                  }\n                }\n              }\n            }\n          }\n        },\n        \"console-browserify\": {\n          \"version\": \"1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz\",\n          \"dependencies\": {\n            \"date-now\": {\n              \"version\": \"0.1.4\",\n              \"resolved\": \"https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz\",\n              \"from\": \"https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz\"\n            }\n          }\n        },\n        \"exit\": {\n          \"version\": \"0.1.2\",\n          \"resolved\": \"https://registry.npmjs.org/exit/-/exit-0.1.2.tgz\",\n          \"from\": \"https://registry.npmjs.org/exit/-/exit-0.1.2.tgz\"\n        },\n        \"htmlparser2\": {\n          \"version\": \"3.8.2\",\n          \"resolved\": \"https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.2.tgz\",\n          \"from\": \"https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.2.tgz\",\n          \"dependencies\": {\n            \"domelementtype\": {\n              \"version\": \"1.3.0\",\n              \"resolved\": \"https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz\"\n            },\n            \"domhandler\": {\n              \"version\": \"2.3.0\",\n              \"resolved\": \"https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz\"\n            },\n            \"domutils\": {\n              \"version\": \"1.5.1\",\n              \"resolved\": \"https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz\",\n              \"dependencies\": {\n                \"dom-serializer\": {\n                  \"version\": \"0.1.0\",\n                  \"resolved\": \"https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz\",\n                  \"dependencies\": {\n                    \"domelementtype\": {\n                      \"version\": \"1.1.3\",\n                      \"resolved\": \"https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz\",\n                      \"from\": \"https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz\"\n                    },\n                    \"entities\": {\n                      \"version\": \"1.1.1\",\n                      \"resolved\": \"https://registry.npmjs.org/entities/-/entities-1.1.1.tgz\",\n                      \"from\": \"https://registry.npmjs.org/entities/-/entities-1.1.1.tgz\"\n                    }\n                  }\n                }\n              }\n            },\n            \"entities\": {\n              \"version\": \"1.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/entities/-/entities-1.0.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/entities/-/entities-1.0.0.tgz\"\n            },\n            \"readable-stream\": {\n              \"version\": \"1.1.13\",\n              \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz\",\n              \"from\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz\",\n              \"dependencies\": {\n                \"core-util-is\": {\n                  \"version\": \"1.0.1\",\n                  \"resolved\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz\"\n                },\n                \"inherits\": {\n                  \"version\": \"2.0.1\",\n                  \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\"\n                },\n                \"isarray\": {\n                  \"version\": \"0.0.1\",\n                  \"resolved\": \"https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz\"\n                },\n                \"string_decoder\": {\n                  \"version\": \"0.10.31\",\n                  \"resolved\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\",\n                  \"from\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\"\n                }\n              }\n            }\n          }\n        },\n        \"lodash\": {\n          \"version\": \"3.6.0\",\n          \"resolved\": \"https://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz\"\n        },\n        \"minimatch\": {\n          \"version\": \"2.0.4\",\n          \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz\",\n          \"from\": \"https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz\",\n          \"dependencies\": {\n            \"brace-expansion\": {\n              \"version\": \"1.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz\",\n              \"dependencies\": {\n                \"balanced-match\": {\n                  \"version\": \"0.2.0\",\n                  \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz\"\n                },\n                \"concat-map\": {\n                  \"version\": \"0.0.1\",\n                  \"resolved\": \"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz\"\n                }\n              }\n            }\n          }\n        },\n        \"shelljs\": {\n          \"version\": \"0.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz\"\n        },\n        \"strip-json-comments\": {\n          \"version\": \"1.0.2\",\n          \"resolved\": \"https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.2.tgz\",\n          \"from\": \"https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.2.tgz\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/jshint/README.md",
    "content": "JSHint for Meteor\n===\n\nThis packages adds a Linter Plugin that automatically runs all your JavaScript\nsource files through the [JSHint linter](http://jshint.com/about/), correctly\npassing the global imports from the used packages.\n\nTo configure the plugin, put a `.jshintrc` file into your app's (or package's)\nroot, containing a valid JSON with the [JSHint\noptions](http://jshint.com/docs/options/).\n\n"
  },
  {
    "path": "packages/jshint/package.js",
    "content": "Package.describe({\n  name: 'jshint',\n  version: '1.0.4_1',\n  summary: 'Lint all your JavaScript files with JSHint.',\n  documentation: 'README.md'\n});\n\nPackage.registerBuildPlugin({\n  name: \"lintJshint\",\n  sources: [\n    'plugin/lint-jshint.js'\n  ],\n  npmDependencies: {\n    \"jshint\": \"2.7.0\"\n  }\n});\n\nPackage.onUse(function(api) {\n  api.use('isobuild:linter-plugin@1.0.0');\n});\n\nPackage.onTest(function(api) {\n  api.use('tinytest');\n  api.use('jshint');\n});\n"
  },
  {
    "path": "packages/jshint/plugin/lint-jshint.js",
    "content": "var util = Npm.require('util');\nvar Future = Npm.require('fibers/future');\nvar jshint = Npm.require('jshint').JSHINT;\n\nPlugin.registerLinter({\n  extensions: [\"js\"],\n  filenames: [\".jshintrc\"]\n}, function () {\n  var linter = new JsHintLinter();\n  return linter;\n});\n\nfunction JsHintLinter () {\n  // packageName -> { config (json),\n  //                  files: { [pathInPackage,arch] -> { hash, errors }}}\n  this._cacheByPackage = {};\n};\n\nvar DEFAULT_CONFIG = JSON.stringify({\n  undef: true,\n  unused: true,\n  node: true,\n  browser: true\n});\n\nJsHintLinter.prototype.processFilesForPackage = function (files, options) {\n  var self = this;\n  var globals = options.globals;\n\n  // Assumes that this method gets called once per package.\n  var packageName = files[0].getPackageName();\n  if (! self._cacheByPackage.hasOwnProperty(packageName)) {\n    self._cacheByPackage[packageName] = {\n      configString: DEFAULT_CONFIG,\n      files: {}\n    };\n  }\n  var cache = self._cacheByPackage[packageName];\n\n  var configs = files.filter(function (file) {\n    return file.getBasename() === '.jshintrc';\n  });\n  if (configs.length > 1) {\n    configs[0].error({\n      message: \"Found multiple .jshintrc files in package \" + packageName +\n        \": \" +\n        configs.map(function (c) { return c.getPathInPackage(); }).join(', ')\n    });\n    return;\n  }\n\n  if (configs.length) {\n    var newConfigString = configs[0].getContentsAsString();\n    if (cache.configString !== newConfigString) {\n      // Reset cache.\n      cache.files = {};\n      cache.configString = newConfigString;\n    }\n  } else {\n    if (cache.configString !== DEFAULT_CONFIG) {\n      // Reset cache.\n      cache.files = {};\n      cache.configString = DEFAULT_CONFIG;\n    }\n  }\n\n  try {\n    var config = JSON.parse(cache.configString);\n  } catch (err) {\n    // This should really not happen for DEFAULT_CONFIG :)\n    configs[0].error({\n      message: \"Failed to parse \" + configs[0].getPathInPackage() +\n        \": not valid JSON: \" + err.message\n    });\n    return;\n  }\n\n  // JSHint has a particular format for defining globals. `false` means that the\n  // global is not allowed to be redefined. `true` means it is allowed to be\n  // redefined. Since the passed imports are probably not great for definition,\n  // mark them as false.\n  var predefinedGlobals = {};\n  globals.forEach(function (symbol) {\n    predefinedGlobals[symbol] = false;\n  });\n\n  files.forEach(function (file) {\n    if (file.getBasename() === '.jshintrc')\n      return;\n\n    // skip files we already linted\n    var cacheKey = JSON.stringify([file.getPathInPackage(), file.getArch()]);\n    if (cache.files.hasOwnProperty(cacheKey) &&\n        cache.files[cacheKey].hash === file.getSourceHash()) {\n      reportErrors(file, cache.files[cacheKey].errors);\n      return;\n    }\n\n    var errors = [];\n    if (! jshint(file.getContentsAsString(), config, predefinedGlobals)) {\n      errors = jshint.errors;\n      reportErrors(file, errors);\n    }\n    cache.files[cacheKey] = { hash: file.getSourceHash(), errors: errors };\n  });\n\n  function reportErrors(file, errors) {\n    errors.forEach(function (error) {\n      file.error({\n        message: error.reason,\n        line: error.line,\n        column: error.character\n      });\n    });\n  }\n};\n\n"
  },
  {
    "path": "packages/jsparse/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/jsparse/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/jsparse/lexer.js",
    "content": "var regexEscape = function (str) {\n  return str.replace(/[\\][^$\\\\.*+?(){}|]/g, '\\\\$&');\n};\n\n// Adapted from source code of http://xregexp.com/plugins/#unicode\nvar unicodeCategories = {\n  Ll: \"0061-007A00B500DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F05210523052505270561-05871D00-1D2B1D6B-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7B2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2CF32D00-2D252D272D2DA641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA661A663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CA78EA791A793A7A1A7A3A7A5A7A7A7A9A7FAFB00-FB06FB13-FB17FF41-FF5A\",\n  Lm: \"02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D6A1D781D9B-1DBF2071207F2090-209C2C7C2C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A7F8A7F9A9CFAA70AADDAAF3AAF4FF70FF9EFF9F\",\n  Lo: \"00AA00BA01BB01C0-01C3029405D0-05EA05F0-05F20620-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150840-085808A008A2-08AC0904-0939093D09500958-09610972-09770979-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-0CB90CBD0CDE0CE00CE10CF10CF20D05-0D0C0D0E-0D100D12-0D3A0D3D0D4E0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC-0EDF0F000F40-0F470F49-0F6C0F88-0F8C1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA10FD-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-1BA01BAE1BAF1BBA-1BE51C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF11CF51CF62135-21382D30-2D672D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31BA31F0-31FF3400-4DB54E00-9FCCA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCAAE0-AAEAAAF2AB01-AB06AB09-AB0EAB11-AB16AB20-AB26AB28-AB2EABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC\",\n  Lt: \"01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC\",\n  Lu: \"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E05200522052405260531-055610A0-10C510C710CD1E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CED2CF2A640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA660A662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BA78DA790A792A7A0A7A2A7A4A7A6A7A8A7AAFF21-FF3A\",\n  Mc: \"0903093B093E-09400949-094C094E094F0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1BAC1BAD1BE71BEA-1BEC1BEE1BF21BF31C24-1C2B1C341C351CE11CF21CF3302E302FA823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BAAEBAAEEAAEFAAF5ABE3ABE4ABE6ABE7ABE9ABEAABEC\",\n  Mn: \"0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065F067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0859-085B08E4-08FE0900-0902093A093C0941-0948094D0951-095709620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F8D-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135D-135F1712-17141732-1734175217531772177317B417B517B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91BAB1BE61BE81BE91BED1BEF-1BF11C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1CF41DC0-1DE61DFC-1DFF20D0-20DC20E120E5-20F02CEF-2CF12D7F2DE0-2DFF302A-302D3099309AA66FA674-A67DA69FA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1AAECAAEDAAF6ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26\",\n  Nd: \"0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19D91A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19\",\n  Nl: \"16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF\",\n  Pc: \"005F203F20402054FE33FE34FE4D-FE4FFF3F\"\n};\n\nvar unicodeClass = function (abbrev) {\n  return '[' +\n    unicodeCategories[abbrev].replace(/[0-9A-F]{4}/ig, \"\\\\u$&\") + ']';\n};\n\n// See ECMA-262 spec, 3rd edition, section 7\n\n// Section 7.2\n// Match one or more characters of whitespace, excluding line terminators.\n// Do this by matching reluctantly, stopping at a non-dot (line terminator\n// or end of string) or a non-whitespace.\n// We are taking advantage of the fact that we are parsing JS from JS in\n// regexes like this by \"passing through\" the spec's definition of whitespace,\n// which is the same in regexes and the lexical grammar.\nvar rWhiteSpace = /[^\\S\\u000A\\u000D\\u2028\\u2029]+/g;\n// Section 7.3\n// Match one line terminator.  Same as (?!.)[\\s\\S] but more explicit.\nvar rLineTerminator = /[\\u000A\\u000D\\u2028\\u2029]/g;\n// Section 7.4\n// Match one multi-line comment.\n// [\\s\\S] is shorthand for any character, including newlines.\n// The *? reluctant qualifier makes this easy.\nvar rMultiLineComment = /\\/\\*[\\s\\S]*?\\*\\//g;\n// Match one single-line comment, not including the line terminator.\nvar rSingleLineComment = /\\/\\/.*/g;\n// Section 7.6\n// Match one or more characters that can start an identifier.\n// This is IdentifierStart+.\nvar rIdentifierPrefix = new RegExp(\n  \"([a-zA-Z$_]+|\\\\\\\\u[0-9a-fA-F]{4}|\" +\n    [unicodeClass('Lu'), unicodeClass('Ll'), unicodeClass('Lt'),\n     unicodeClass('Lm'), unicodeClass('Lo'), unicodeClass('Nl')].join('|') +\n    \")+\", 'g');\n// Match one or more characters that can continue an identifier.\n// This is (IdentifierPart and not IdentifierStart)+.\n// To match a full identifier, match rIdentifierPrefix, then\n// match rIdentifierMiddle followed by rIdentifierPrefix until they both fail.\nvar rIdentifierMiddle = new RegExp(\n  \"([0-9]|\" + [unicodeClass('Mn'), unicodeClass('Mc'), unicodeClass('Nd'),\n               unicodeClass('Pc')].join('|') + \")+\", 'g');\n// Section 7.7\n// Match one punctuator (except for division punctuators).\nvar rPunctuator = new RegExp(\n  regexEscape(\"{ } ( ) [ ] . ; , < > <= >= == != === !== + - * % ++ -- << >> \"+\n              \">>> & | ^ ! ~ && || ? : = += -= *= %= <<= >>= >>>= &= |= ^=\")\n  // sort from longest to shortest so that we don't match '==' for '===' and\n  // '*' for '*=', etc.\n    .split(' ').sort(function (a,b) { return b.length - a.length; })\n    .join('|'), 'g');\nvar rDivPunctuator = /\\/=?/g;\n// Section 7.8.3\nvar rHexLiteral = /0[xX][0-9a-fA-F]+(?!\\w)/g;\nvar rOctLiteral = /0[0-7]+(?!\\w)/g; // deprecated\nvar rDecLiteral =\n      /(((0|[1-9][0-9]*)(\\.[0-9]*)?)|\\.[0-9]+)([Ee][+-]?[0-9]+)?(?!\\w)/g;\n// Section 7.8.4\nvar rStringQuote = /[\"']/g;\n// Match one or more characters besides quotes, backslashes, or line ends\nvar rStringMiddle = /(?=.)[^\"'\\\\]+?((?!.)|(?=[\"'\\\\]))/g;\n// Match one escape sequence, including the backslash.\nvar rEscapeSequence =\n      /\\\\(['\"\\\\bfnrtv]|0(?![0-9])|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|(?=.)[^ux0-9])/g;\n// Match one ES5 line continuation\nvar rLineContinuation =\n      /\\\\(\\r\\n|[\\u000A\\u000D\\u2028\\u2029])/g;\n// Section 7.8.5\n// Match one regex literal, including slashes, not including flags.\n// Support unescaped '/' in character classes, per 5th ed.\n// For example: `/[/]/` will match the string `\"/\"`.\n//\n// Explanation of regex:\n// - Match `/` not followed by `/` or `*`\n// - Match one or more of any of these:\n//   - Backslash followed by one non-newline\n//   - One non-newline, not `[` or `\\` or `/`\n//   - A character class, beginning with `[` and ending with `]`.\n//     In the middle is zero or more of any of these:\n//     - Backslash followed by one non-newline\n//     - One non-newline, not `]` or `\\`\n// - Match closing `/`\nvar rRegexLiteral =\n      /\\/(?![*\\/])(\\\\.|(?=.)[^\\[\\/\\\\]|\\[(\\\\.|(?=.)[^\\]\\\\])*\\])+\\//g;\nvar rRegexFlags = /[a-zA-Z]*/g;\n\nvar rDecider =\n      /((?=.)\\s)|(\\/[\\/\\*]?)|([\\][{}();,<>=!+*%&|^~?:-]|\\.(?![0-9]))|([\\d.])|([\"'])|(.)|([\\S\\s])/g;\n\nvar keywordLookup = {\n  ' break': 'KEYWORD',\n  ' case': 'KEYWORD',\n  ' catch': 'KEYWORD',\n  ' continue': 'KEYWORD',\n  ' debugger': 'KEYWORD',\n  ' default': 'KEYWORD',\n  ' delete': 'KEYWORD',\n  ' do': 'KEYWORD',\n  ' else': 'KEYWORD',\n  ' finally': 'KEYWORD',\n  ' for': 'KEYWORD',\n  ' function': 'KEYWORD',\n  ' if': 'KEYWORD',\n  ' in': 'KEYWORD',\n  ' instanceof': 'KEYWORD',\n  ' new': 'KEYWORD',\n  ' return': 'KEYWORD',\n  ' switch': 'KEYWORD',\n  ' this': 'KEYWORD',\n  ' throw': 'KEYWORD',\n  ' try': 'KEYWORD',\n  ' typeof': 'KEYWORD',\n  ' var': 'KEYWORD',\n  ' void': 'KEYWORD',\n  ' while': 'KEYWORD',\n  ' with': 'KEYWORD',\n\n  ' false': 'BOOLEAN',\n  ' true': 'BOOLEAN',\n\n  ' null': 'NULL'\n};\n\nvar makeSet = function (array) {\n  var s = {};\n  for (var i = 0, N = array.length; i < N; i++)\n    s[array[i]] = true;\n  return s;\n};\n\nvar nonTokenTypes = makeSet('WHITESPACE COMMENT NEWLINE EOF ERROR'.split(' '));\n\nvar punctuationBeforeDivision = makeSet('] ) } ++ --'.split(' '));\nvar keywordsBeforeDivision = makeSet('this'.split(' '));\n\nvar guessIsDivisionPermittedAfterToken = function (tok) {\n  // Figure out if a '/' character should be interpreted as division\n  // rather than the start of a regular expression when it follows the\n  // token, which must be a token lexeme per isToken().\n  // The beginning of section 7 of the spec briefly\n  // explains what's going on; basically the lexical grammar can't\n  // distinguish, for example, `e/f/g` (division) from `e=/f/g`\n  // (assignment of a regular expression), among many other variations.\n  //\n  // THIS IS ONLY A HEURISTIC, though it will rarely fail.\n  // Here are the two cases I know of where help from the parser is needed:\n  //  - if (foo)\n  //        /ba/.test(\"banana\") && console.log(\"matches\");\n  //    (Close paren of a control structure before a statement starting with\n  //     a regex literal.  Starting a statement with a regex literal is\n  //     unusual, of course, because it's hard to have a side effect.)\n  //  - ++ /foo/.abc\n  //    (Prefix `++` or `--` before an expression starting with a regex\n  //     literal.  This will run but I can't see any use for it.)\n  switch (tok.type()) {\n  case \"PUNCTUATION\":\n    // few punctuators can end an expression, but e.g. `)`\n    return !! punctuationBeforeDivision[tok.text()];\n  case \"KEYWORD\":\n    // few keywords can end an expression, but e.g. `this`\n    return !! keywordsBeforeDivision[tok.text()];\n  case \"IDENTIFIER\":\n    return true;\n  default: // literal\n    return true;\n  }\n};\n\n////////// PUBLIC API\n\nvar Lexeme = function (pos, type, text) {\n  this._pos = pos;\n  this._type = type;\n  this._text = text;\n};\n\nLexeme.prototype.startPos = function () {\n  return this._pos;\n};\n\nLexeme.prototype.endPos = function () {\n  return this._pos + this._text.length;\n};\n\nLexeme.prototype.type = function () {\n  return this._type;\n};\n\nLexeme.prototype.text = function () {\n  return this._text;\n};\n\nLexeme.prototype.isToken = function () {\n  return ! nonTokenTypes[this._type];\n};\n\nLexeme.prototype.isError = function () {\n  return this._type === \"ERROR\";\n};\n\nLexeme.prototype.isEOF = function () {\n  return this._type === \"EOF\";\n};\n\nLexeme.prototype.prev = function () {\n  return this._prev;\n};\n\nLexeme.prototype.next = function () {\n  return this._next;\n};\n\nLexeme.prototype.toString = function () {\n  return this.isError() ? \"ERROR\" :\n    this.isEOF() ? \"EOF\" : \"`\" + this.text() + \"`\";\n};\n\n// Create a Lexer for the given string of JavaScript code.\n//\n// A lexer keeps a pointer `pos` into the string that is\n// advanced when you ask for the next lexeme with `next()`.\n//\n// XXXXX UPDATE DOCS\n// Properties:\n//   code: Original JavaScript code string.\n//   pos:  Current index into the string.  You can assign to it\n//           to continue lexing from a different position.  After\n//           calling next(), it is the ending index of the most\n//           recent lexeme.\n//   lastPos:  The starting index of the most recent lexeme.\n//           Equal to `pos - text.length`.\n//   text: Text of the last lexeme as a string.\n//   type: Type of the last lexeme, as returned by `next()`.\n//   divisionPermitted: Whether a '/' character should be interpreted\n//           as division rather than the start of a regular expression.\n//           This flag is set automatically during lexing based on the\n//           previous token (i.e. the most recent token lexeme), but\n//           it is technically only a heuristic.\n//           Thie flag can be read and set manually to affect the\n//           parsing of the next token.\n\nJSLexer = function (code) {\n  this.code = code;\n  this.pos = 0;\n  this.divisionPermitted = false;\n  this.lastLexeme = null;\n};\n\nJSLexer.Lexeme = Lexeme;\n\n// XXXX UPDATE DOCS\n// Return the type of the next of lexeme starting at `pos`, and advance\n// `pos` to the end of the lexeme.  The text of the lexeme is available\n// in `text`.  The text is always the substring of `code` between the\n// old and new values of `pos`.  An \"EOF\" lexeme terminates\n// the stream.  \"ERROR\" lexemes indicate a bad input string.  Out of all\n// lexemes, only \"EOF\" has empty text, and it always has empty text.\n// All others contain at least one character from the source code.\n//\n// Lexeme types:\n// Literals: BOOLEAN, NULL, REGEX, NUMBER, STRING\n// Whitespace-like: WHITESPACE, COMMENT, NEWLINE, EOF\n// Other Tokens: IDENTIFIER, KEYWORD, PUNCTUATION\n// ... and ERROR\n\nJSLexer.prototype.next = function () {\n  var self = this;\n  var code = self.code;\n  var origPos = self.pos;\n  var divisionPermitted = self.divisionPermitted;\n\n  if (origPos > code.length)\n    throw new Error(\"out of range\");\n\n  // Running regexes inside this function will move this local\n  // `pos` forward.\n  // When we commit to emitting a lexeme, we'll set self.pos\n  // based on it.\n  var pos = origPos;\n\n  // Emit a lexeme.  Always called as `return lexeme(type)`.\n  var lexeme = function (type) {\n    // If `pos` hasn't moved, we consider this an error.\n    // This means that grammar cases that only run one regex\n    // or an alternation ('||') of regexes don't need to\n    // check for failure.\n    // This also guarantees that only EOF lexemes are empty.\n    if (pos === origPos && type !== 'EOF') {\n      type = 'ERROR';\n      pos = origPos + 1;\n    }\n    self.pos = pos;\n    var lex = new JSLexer.Lexeme(origPos, type, code.substring(origPos, pos));\n    if (self.lastLexeme) {\n      self.lastLexeme._next = lex;\n      lex._prev = self.lastLexeme;\n    }\n    self.lastLexeme = lex;\n    if (lex.isToken())\n      self.divisionPermitted = guessIsDivisionPermittedAfterToken(lex);\n    return lex;\n  };\n\n  if (pos === code.length)\n    return lexeme('EOF');\n\n  // Result of the regex match in the most recent call to `run`.\n  var match = null;\n\n  // Run a regex starting from `pos`, recording the end of the matched\n  // string in `pos` and the match data in `match`.  The regex must have\n  // the 'g' (global) flag.  If it doesn't match at `pos`, set `match`\n  // to null.  The caller should expect the regex to match at `pos`, as\n  // failure is too expensive to run in a tight loop.\n  var run = function (regex) {\n    // Cause regex matching to start at `pos`.\n    regex.lastIndex = pos;\n    match = regex.exec(code);\n    // Simulate \"sticky\" matching by throwing out the match if it\n    // didn't match exactly at `pos`.  If it didn't, we may have\n    // just searched the entire string.\n    if (match && (match.index !== pos))\n      match = null;\n    // Record the end position of the match back into `pos`.\n    // Avoid an IE7 bug where lastIndex is incremented when\n    // the match has 0 length.\n    if (match && match[0].length !== 0)\n      pos = regex.lastIndex;\n    return match;\n  };\n\n  // Decide which case of the grammar we are in based on one or two\n  // characters, then roll back `pos`.\n  run(rDecider);\n  pos = origPos;\n\n  // Grammar cases\n  if (match[1]) { // \\s\n    run(rWhiteSpace);\n    return lexeme('WHITESPACE');\n  }\n  if (match[2]) { // one of //, /*, /\n    if (match[2] === '//') {\n      run(rSingleLineComment);\n      return lexeme('COMMENT');\n    }\n    if (match[2] === '/*') {\n      run(rMultiLineComment);\n      return lexeme(match ? 'COMMENT' : 'ERROR');\n    }\n    if (match[2] === '/') {\n      if (divisionPermitted) {\n        run(rDivPunctuator);\n        return lexeme('PUNCTUATION');\n      } else {\n        run(rRegexLiteral);\n        if (! match)\n          return lexeme('ERROR');\n        run(rRegexFlags);\n        return lexeme('REGEX');\n      }\n    }\n  }\n  if (match[3]) { // any other punctuation char\n    run(rPunctuator);\n    return lexeme(match ? 'PUNCTUATION' : 'ERROR');\n  }\n  if (match[4]) { // 0-9\n    run(rDecLiteral) || run(rHexLiteral) || run(rOctLiteral);\n    return lexeme(match ? 'NUMBER' : 'ERROR');\n  }\n  if (match[5]) { // \" or '\n    run(rStringQuote);\n    var quote = match[0];\n    do {\n      run(rStringMiddle) || run(rEscapeSequence) ||\n        run(rLineContinuation) || run(rStringQuote);\n    } while (match && match[0] !== quote);\n    if (! (match && match[0] === quote))\n      return lexeme('ERROR');\n    return lexeme('STRING');\n  }\n  if (match[7]) { // non-dot (line terminator)\n    run(rLineTerminator);\n    return lexeme('NEWLINE');\n  }\n  // dot (any non-line-terminator)\n  run(rIdentifierPrefix);\n  // Use non-short-circuiting bitwise OR, '|', to always try\n  // both regexes in sequence, returning false only if neither\n  // matched.\n  while ((!! run(rIdentifierMiddle)) |\n         (!! run(rIdentifierPrefix))) { /*continue*/ }\n  var word = code.substring(origPos, pos);\n  return lexeme(keywordLookup[' '+word] || 'IDENTIFIER');\n};\n\nJSLexer.prettyOffset = function (code, pos) {\n  var codeUpToPos = code.substring(0, pos);\n  var startOfLine = codeUpToPos.lastIndexOf('\\n') + 1;\n  var indexInLine = pos - startOfLine; // 0-based\n  var lineNum = codeUpToPos.replace(/[^\\n]+/g, '').length + 1; // 1-based\n  return \"line \" + lineNum + \", offset \" + indexInLine;\n};\n"
  },
  {
    "path": "packages/jsparse/package.js",
    "content": "Package.describe({\n  summary: \"Full-featured JavaScript parser\",\n  version: \"1.0.9\"\n});\n\nPackage.onUse(function (api) {\n  api.export(['JSLexer', 'JSParser', 'ParseNode']);\n  api.addFiles(['lexer.js', 'parserlib.js', 'stringify.js', 'parser.js'],\n                ['client', 'server']);\n});\n\nPackage.onTest(function (api) {\n  api.use(['tinytest', 'underscore']);\n  api.use('jsparse', 'client');\n\n  api.addFiles('parser_tests.js',\n                // Test just on client for faster running; should run\n                // identically on server.\n                'client');\n                //['client', 'server']);\n});\n"
  },
  {
    "path": "packages/jsparse/parser.js",
    "content": "///// JAVASCRIPT PARSER\n\n// What we don't support from ECMA-262 5.1:\n//  - object literal trailing comma\n//  - object literal get/set\n\nvar expecting = Parser.expecting;\n\nvar assertion = Parsers.assertion;\nvar node = Parsers.node;\nvar or = Parsers.or;\nvar and = Parsers.and;\nvar not = Parsers.not;\nvar list = Parsers.list;\nvar seq = Parsers.seq;\nvar opt = Parsers.opt;\nvar constant = Parsers.constant;\nvar mapResult = Parsers.mapResult;\n\n\nvar makeSet = function (array) {\n  var s = {};\n  for (var i = 0, N = array.length; i < N; i++)\n    s[array[i]] = true;\n  return s;\n};\n\n\nJSParser = function (code, options) {\n  this.lexer = new JSLexer(code);\n  this.oldToken = null;\n  this.newToken = null;\n  this.pos = 0;\n  this.isLineTerminatorHere = false;\n  this.includeComments = false;\n  // the last COMMENT lexeme between oldToken and newToken\n  // that we've consumed, if any.\n  this.lastCommentConsumed = null;\n\n  options = options || {};\n  // pass {tokens:'strings'} to get strings for\n  // tokens instead of token objects\n  if (options.tokens === 'strings') {\n    this.tokenFunc = function (tok) {\n      return tok.text();\n    };\n  } else {\n    this.tokenFunc = function (tok) {\n      return tok;\n    };\n  }\n\n  // pass {includeComments: true} to include comments in the AST.  For\n  // a comment to be included, it must occur where a series of\n  // statements could occur, and it must be preceded by only comments\n  // and whitespace on the same line.\n  if (options.includeComments) {\n    this.includeComments = true;\n  }\n};\n\nJSParser.prototype.consumeNewToken = function () {\n  var self = this;\n  var lexer = self.lexer;\n  self.oldToken = self.newToken;\n  self.isLineTerminatorHere = false;\n  var lex;\n  do {\n    lex = lexer.next();\n    if (lex.isError())\n      throw new Error(\"Bad token at \" +\n                      JSLexer.prettyOffset(lexer.code, lex.startPos()) +\n                      \", text `\" + lex.text() + \"`\");\n    else if (lex.type() === \"NEWLINE\")\n      self.isLineTerminatorHere = true;\n    else if (lex.type() === \"COMMENT\" && ! /^.*$/.test(lex.text()))\n      // multiline comments containing line terminators count\n      // as line terminators.\n      self.isLineTerminatorHere = true;\n  } while (! lex.isEOF() && ! lex.isToken());\n  self.newToken = lex;\n  self.pos = lex.startPos();\n  self.lastCommentConsumed = null;\n};\n\nJSParser.prototype.getParseError = function (expecting, found) {\n  var msg = (expecting ? \"Expected \" + expecting : \"Unexpected token\");\n  if (this.oldToken)\n    msg += \" after \" + this.oldToken;\n  var pos = this.pos;\n  msg += \" at \" + JSLexer.prettyOffset(this.lexer.code, pos);\n  msg += \", found \" + (found || this.newToken);\n  return new Error(msg);\n};\n\nJSParser.prototype.getSyntaxTree = function () {\n  var self = this;\n\n  self.consumeNewToken();\n\n  var NIL = new ParseNode('nil', []);\n\n  var booleanFlaggedParser = function (parserConstructFunc) {\n    return {\n      'false': parserConstructFunc(false),\n      'true': parserConstructFunc(true)\n    };\n  };\n\n  // Takes a space-separated list of either punctuation or keyword tokens\n  var lookAheadToken = function (tokens) {\n    var type = (/\\w/.test(tokens) ? 'KEYWORD' : 'PUNCTUATION');\n    var textSet = makeSet(tokens.split(' '));\n    return expecting(\n      tokens.split(' ').join(', '),\n      assertion(function (t) {\n        return (t.newToken.type() === type && textSet[t.newToken.text()]);\n      }));\n  };\n\n  var lookAheadTokenType = function (type) {\n    return expecting(type, assertion(function (t) {\n      return t.newToken.type() === type;\n    }));\n  };\n\n  // Takes a space-separated list of either punctuation or keyword tokens\n  var token = function (tokens) {\n    var type = (/\\w/.test(tokens) ? 'KEYWORD' : 'PUNCTUATION');\n    var textSet = makeSet(tokens.split(' '));\n    return new Parser(\n      tokens.split(' ').join(', '),\n      function (t) {\n        if (t.newToken.type() === type && textSet[t.newToken.text()]) {\n          t.consumeNewToken();\n          return self.tokenFunc(t.oldToken);\n        }\n        return null;\n      });\n  };\n\n  var tokenType = function (type) {\n    return new Parser(type, function (t) {\n      if (t.newToken.type() === type) {\n        t.consumeNewToken();\n        return self.tokenFunc(t.oldToken);\n      }\n      return null;\n    });\n  };\n\n  var noLineTerminatorHere = expecting(\n    'noLineTerminator', assertion(function (t) {\n      return ! t.isLineTerminatorHere;\n    }));\n\n  var nonLHSExpressionNames = makeSet(\n    'unary binary postfix ternary assignment comma'.split(' '));\n  var isExpressionLHS = function (exprNode) {\n    return ! nonLHSExpressionNames[exprNode.name];\n  };\n\n  // Like token, but marks tokens that need to defy the lexer's\n  // heuristic about whether the next '/' is a division or\n  // starts a regex.\n  var preSlashToken = function (text, divisionNotRegex) {\n    var inner = token(text);\n    return new Parser(\n      inner.expecting,\n      function (t) {\n        // temporarily set divisionPermitted,\n        // restoring it if we don't match.\n        var oldValue = t.lexer.divisionPermitted;\n        var result;\n        try {\n          t.lexer.divisionPermitted = divisionNotRegex;\n          result = inner.parse(t);\n          return result;\n        } finally {\n          if (! result)\n            t.lexer.divisionPermitted = oldValue;\n        }\n      });\n  };\n\n  // Mark some productions \"lazy\" to allow grammar circularity, i.e. accessing\n  // later parsers from earlier ones.\n  // These lazy versions will be replaced with real ones, which they will\n  // access when run.\n  var expressionMaybeNoIn = {\n    'false': Parsers.lazy(\n      'expression',\n      function () { return expressionMaybeNoIn[false]; }),\n    'true': Parsers.lazy(\n      'expression',\n      function () { return expressionMaybeNoIn[true]; })\n  };\n  var expression = expressionMaybeNoIn[false];\n\n  var assignmentExpressionMaybeNoIn = {\n    'false': Parsers.lazy(\n      'expression',\n      function () { return assignmentExpressionMaybeNoIn[false]; }),\n    'true': Parsers.lazy(\n      'expression',\n      function () { return assignmentExpressionMaybeNoIn[true]; })\n  };\n  var assignmentExpression = assignmentExpressionMaybeNoIn[false];\n\n  var functionBody = Parsers.lazy(\n    'statement', function () { return functionBody; });\n  var statement = Parsers.lazy(\n    'statement', function () { return statement; });\n  ////\n\n  var arrayLiteral =\n        node('array',\n             seq(token('['),\n                 opt(list(token(','))),\n                 or(\n                   lookAheadToken(']'),\n                   list(\n                     expecting(\n                       'expression',\n                       or(assignmentExpression,\n                          // count a peeked-at ']' as an expression\n                          // to support elisions at end, e.g.\n                          // `[1,2,3,,,,,,]`.\n                          lookAheadToken(']'))),\n                     // list seperator is one or more commas\n                     // to support elision\n                     list(token(',')))),\n                 token(']')));\n\n  // \"IdentifierName\" in ES5 allows reserved words, like in a property access\n  // or a key of an object literal.\n  // Put IDENTIFIER last so it shows up in the error message.\n  var identifierName = or(tokenType('NULL'), tokenType('BOOLEAN'),\n                          tokenType('KEYWORD'), tokenType('IDENTIFIER'));\n\n  var propertyName = expecting('propertyName', or(\n    node('idPropName', identifierName),\n    node('numPropName', tokenType('NUMBER')),\n    node('strPropName', tokenType('STRING'))));\n  var nameColonValue = expecting(\n    'propertyName',\n    node('prop', seq(propertyName, token(':'), assignmentExpression)));\n\n  // Allow trailing comma in object literal, per ES5.  Trailing comma\n  // must follow a `name:value`, that is, `{,}` is invalid.\n  //\n  // We can't just use a normal comma list(), because it will seize\n  // on the comma as a sign that the list continues.  Instead,\n  // we specify a list of either ',' or nameColonValue, using positive\n  // and negative lookAheads to constrain the sequence.  The grammar\n  // is ordered so that error messages will always say\n  // \"Expected propertyName\" or \"Expected ,\" as appropriate, not\n  // \"Expected ,\" when the look-ahead is negative or \"Expected }\".\n  var objectLiteral =\n        node('object',\n             seq(token('{'),\n                 or(lookAheadToken('}'),\n                    and(not(lookAheadToken(',')),\n                        list(or(seq(token(','),\n                                    expecting('propertyName',\n                                              not(lookAheadToken(',')))),\n                                seq(nameColonValue,\n                                    or(lookAheadToken('}'),\n                                       lookAheadToken(','))))))),\n                 expecting('propertyName', token('}'))));\n\n  var functionMaybeNameRequired = booleanFlaggedParser(\n    function (nameRequired) {\n      return seq(token('function'),\n                 (nameRequired ? tokenType('IDENTIFIER') :\n                  or(tokenType('IDENTIFIER'),\n                     and(lookAheadToken('('), constant(NIL)))),\n                 token('('),\n                 or(lookAheadToken(')'),\n                    list(tokenType('IDENTIFIER'), token(','))),\n                 token(')'),\n                 token('{'),\n                 functionBody,\n                 token('}'));\n    });\n  var functionExpression = node('functionExpr',\n                                functionMaybeNameRequired[false]);\n\n  var primaryOrFunctionExpression =\n        expecting('expression',\n                  or(node('this', token('this')),\n                     node('identifier', tokenType('IDENTIFIER')),\n                     node('number', tokenType('NUMBER')),\n                     node('boolean', tokenType('BOOLEAN')),\n                     node('null', tokenType('NULL')),\n                     node('regex', tokenType('REGEX')),\n                     node('string', tokenType('STRING')),\n                     node('parens',\n                          seq(token('('), expression, token(')'))),\n                     arrayLiteral,\n                     objectLiteral,\n                     functionExpression));\n\n\n  var dotEnding = seq(token('.'), identifierName);\n  var bracketEnding = seq(token('['), expression, token(']'));\n  var callArgs = seq(token('('),\n                     or(lookAheadToken(')'),\n                        list(assignmentExpression,\n                             token(','))),\n                     token(')'));\n\n  var newKeyword = token('new');\n\n  // This is a completely equivalent refactor of the spec's production\n  // for a LeftHandSideExpression.\n  //\n  // An lhsExpression is basically an expression that can serve as\n  // the left-hand-side of an assignment, though function calls and\n  // \"new\" invocation are included because they have the same\n  // precedence.  Actually, the spec technically allows a function\n  // call to \"return\" a valid l-value, as in `foo(bar) = baz`,\n  // though no built-in or user-specifiable call has this property\n  // (it would have to be defined by a browser or other \"host\").\n  var lhsExpression = new Parser(\n    'expression',\n    function (t) {\n      // Accumulate all initial \"new\" keywords, not yet knowing\n      // if they have a corresponding argument list later.\n      var news = [];\n      var n;\n      while ((n = newKeyword.parse(t)))\n        news.push(n);\n\n      // Read the primaryOrFunctionExpression that will be the \"core\"\n      // of this lhsExpression.  It is preceded by zero or more `new`\n      // keywords, and followed by any sequence of (...), [...],\n      // and .foo add-ons.\n      // if we have 'new' keywords, we are committed and must\n      // match an expression or error.\n      var result = primaryOrFunctionExpression.parseRequiredIf(t, news.length);\n      if (! result)\n        return null;\n\n      // Our plan of attack is to apply each dot, bracket, or call\n      // as we come across it.  Whether a call is a `new` call depends\n      // on whether there are `new` keywords we haven't used.  If so,\n      // we pop one off the stack.\n      var done = false;\n      while (! done) {\n        var r;\n        if ((r = dotEnding.parse(t))) {\n          result = new ParseNode('dot', [result].concat(r));\n        } else if ((r = bracketEnding.parse(t))) {\n          result = new ParseNode('bracket', [result].concat(r));\n        } else if ((r = callArgs.parse(t))) {\n          if (news.length)\n            result = new ParseNode('newcall', [news.pop(), result].concat(r));\n          else\n            result = new ParseNode('call', [result].concat(r));\n        } else {\n          done = true;\n        }\n      }\n\n      // There may be more `new` keywords than calls, which is how\n      // paren-less constructions (`new Date`) are parsed.  We've\n      // already handled `new foo().bar()`, now handle `new new foo().bar`.\n      while (news.length)\n        result = new ParseNode('new', [news.pop(), result]);\n\n      return result;\n    });\n\n  var postfixToken = token('++ --');\n  var postfixLookahead = lookAheadToken('++ --');\n  var postfixExpression = expecting(\n    'expression',\n    mapResult(seq(lhsExpression,\n                  opt(and(noLineTerminatorHere,\n                          postfixLookahead,\n                          postfixToken))),\n              function (v) {\n                if (v.length === 1)\n                  return v[0];\n                return new ParseNode('postfix', v);\n              }));\n\n  var unaryExpression = Parsers.unary(\n    'unary', postfixExpression,\n    or(token('delete void typeof'),\n       preSlashToken('++ -- + - ~ !', false)));\n\n  // The \"noIn\" business is all to facilitate parsing\n  // of for-in constructs, though the cases that make\n  // this required are quite obscure.\n  // The `for(var x in y)` form is allowed to take\n  // an initializer for `x` (which is only useful for\n  // its side effects, or if `y` has no properties).\n  // So an example might be:\n  // `for(var x = a().b in c);`\n  // In this example, `var x = a().b` is parsed without\n  // the `in`, which would otherwise be part of the\n  // varDecl, using varDeclNoIn.\n\n  // Our binaryExpression is the spec's LogicalORExpression,\n  // which includes all the higher-precendence operators.\n  var binaryExpressionMaybeNoIn = booleanFlaggedParser(\n    function (noIn) {\n      // high to low precedence\n      var binaryOps = [token('* / %'),\n                       token('+ -'),\n                       token('<< >> >>>'),\n                       or(token('< > <= >='),\n                          noIn ? token('instanceof') :\n                          token('instanceof in')),\n                       token('== != === !=='),\n                       token('&'),\n                       token('^'),\n                       token('|'),\n                       token('&&'),\n                       token('||')];\n      return expecting(\n        'expression',\n        Parsers.binaryLeft('binary', unaryExpression, binaryOps));\n    });\n  var binaryExpression = binaryExpressionMaybeNoIn[false];\n\n  var conditionalExpressionMaybeNoIn = booleanFlaggedParser(\n    function (noIn) {\n      return expecting(\n        'expression',\n        mapResult(\n          seq(binaryExpressionMaybeNoIn[noIn],\n              opt(seq(\n                token('?'),\n                assignmentExpression, token(':'),\n                assignmentExpressionMaybeNoIn[noIn]))),\n          function (v) {\n            if (v.length === 1)\n              return v[0];\n            return new ParseNode('ternary', v);\n          }));\n    });\n  var conditionalExpression = conditionalExpressionMaybeNoIn[false];\n\n  var assignOp = token('= *= /= %= += -= <<= >>= >>>= &= ^= |=');\n\n  assignmentExpressionMaybeNoIn = booleanFlaggedParser(\n    function (noIn) {\n      return new Parser(\n        'expression',\n        function (t) {\n          var r = conditionalExpressionMaybeNoIn[noIn].parse(t);\n          if (! r)\n            return null;\n\n          // Assignment is right-associative.\n          // Plan of attack: make a list of all the parts\n          // [expression, op, expression, op, ... expression]\n          // and then fold them up at the end.\n          var parts = [r];\n          var op;\n          while (isExpressionLHS(r) &&(op = assignOp.parse(t)))\n            parts.push(op,\n                       conditionalExpressionMaybeNoIn[noIn].parseRequired(t));\n\n          var result = parts.pop();\n          while (parts.length) {\n            op = parts.pop();\n            var lhs = parts.pop();\n            result = new ParseNode('assignment', [lhs, op, result]);\n          }\n          return result;\n        });\n    });\n  assignmentExpression = assignmentExpressionMaybeNoIn[false];\n\n  expressionMaybeNoIn = booleanFlaggedParser(\n    function (noIn) {\n      return expecting(\n        'expression',\n        mapResult(\n          list(assignmentExpressionMaybeNoIn[noIn], token(',')),\n          function (v) {\n            if (v.length === 1)\n              return v[0];\n            return new ParseNode('comma', v);\n          }));\n    });\n  expression = expressionMaybeNoIn[false];\n\n  // STATEMENTS\n\n  var comment = node('comment', new Parser(null, function (t) {\n    if (! t.includeComments)\n      return null;\n\n    // Match a COMMENT lexeme between oldToken and newToken.\n    //\n    // This is an unusual Parser because it doesn't match and consume\n    // newToken, but instead uses the next()/prev() API on lexemes.\n    // It assumes it can walk the linked list backwards from newToken\n    // (though not necessarily forwards).\n    //\n    // We start at the last comment we've visited for this\n    // oldToken/newToken pair, if any, or else oldToken, or else the\n    // beginning of the token stream.  We ignore comments that are\n    // preceded by any non-comment source code on the same line.\n    var lexeme = (t.lastCommentConsumed || t.oldToken || null);\n    if (! lexeme) {\n      // no oldToken, must be on first token.  walk backwards\n      // to start with first lexeme (which may be a comment\n      // or whitespace)\n      lexeme = t.newToken;\n      while (lexeme.prev())\n        lexeme = lexeme.prev();\n    } else {\n      // start with lexeme after last token or comment consumed\n      lexeme = lexeme.next();\n    }\n    var seenNewline = ((! t.oldToken) || t.lastCommentConsumed || false);\n    while (lexeme !== t.newToken) {\n      var type = lexeme.type();\n      if (type === \"NEWLINE\") {\n        seenNewline = true;\n      } else if (type === \"COMMENT\") {\n        t.lastCommentConsumed = lexeme;\n        if (seenNewline)\n          return lexeme;\n      }\n      lexeme = lexeme.next();\n    }\n    return null;\n  }));\n\n  var statements = list(or(comment, statement));\n\n  // implements JavaScript's semicolon \"insertion\" rules\n  var maybeSemicolon = expecting(\n    'semicolon',\n    or(token(';'),\n       and(\n         or(\n           lookAheadToken('}'),\n           lookAheadTokenType('EOF'),\n           assertion(function (t) {\n             return t.isLineTerminatorHere;\n           })),\n         constant(new ParseNode(';', [])))));\n\n  var expressionStatement = node(\n    'expressionStmnt',\n    and(\n      not(or(lookAheadToken('{'), lookAheadToken('function'))),\n      seq(expression,\n          expecting('semicolon',\n                    or(maybeSemicolon,\n                       // allow presence of colon to terminate\n                       // statement legally, for the benefit of\n                       // expressionOrLabelStatement.  Basically assume\n                       // an implicit semicolon.  This\n                       // is safe because a colon can never legally\n                       // follow a semicolon anyway.\n                       and(lookAheadToken(':'),\n                           constant(new ParseNode(';', []))))))));\n\n  // it's hard to parse statement labels, as in\n  // `foo: x = 1`, because we can't tell from the\n  // first token whether we are looking at an expression\n  // statement or a label statement.  To work around this,\n  // expressionOrLabelStatement parses the expression and\n  // then rewrites the result if it is an identifier\n  // followed by a colon.\n  var labelColonAndStatement = seq(token(':'), statement);\n  var noColon = expecting(\n    'semicolon', not(lookAheadToken(':')));\n  var expressionOrLabelStatement = new Parser(\n    null,\n    function (t) {\n      var exprStmnt = expressionStatement.parse(t);\n      if (! exprStmnt)\n        return null;\n\n      var expr = exprStmnt.children[0];\n      var maybeSemi = exprStmnt.children[1];\n      if (expr.name !== 'identifier' ||\n          ! (maybeSemi instanceof ParseNode)) {\n        // We either have a non-identifier expression or a present\n        // semicolon.  This is not a label.\n        //\n        // Fail now if we are looking at a colon, causing an\n        // error message on input like `1+1:` of the same kind\n        // you'd get without statement label parsing.\n        noColon.parseRequired(t);\n        return exprStmnt;\n      }\n\n      var rest = labelColonAndStatement.parse(t);\n      if (! rest)\n        return exprStmnt;\n\n      return new ParseNode('labelStmnt',\n                           [expr.children[0]].concat(rest));\n    });\n\n  var emptyStatement = node('emptyStmnt', token(';')); // required semicolon\n\n  var blockStatement = expecting('block', node('blockStmnt', seq(\n    token('{'), or(lookAheadToken('}'), statements),\n    token('}'))));\n\n  var varDeclMaybeNoIn = booleanFlaggedParser(function (noIn) {\n    return node(\n      'varDecl',\n      seq(tokenType('IDENTIFIER'),\n          opt(seq(token('='),\n                  assignmentExpressionMaybeNoIn[noIn]))));\n  });\n  var varDecl = varDeclMaybeNoIn[false];\n\n  var variableStatement = node(\n    'varStmnt',\n    seq(token('var'), list(varDecl, token(',')),\n        maybeSemicolon));\n\n  // A paren that may be followed by a statement\n  // beginning with a regex literal.\n  var closeParenBeforeStatement = preSlashToken(')', false);\n\n  var ifStatement = node(\n    'ifStmnt',\n    seq(token('if'), token('('), expression,\n        closeParenBeforeStatement, statement,\n        opt(seq(token('else'), statement))));\n\n  var secondThirdClauses = expecting(\n    'semicolon',\n    and(lookAheadToken(';'),\n        seq(\n          expecting('semicolon', token(';')),\n          or(and(lookAheadToken(';'),\n                 constant(NIL)),\n             expression),\n          expecting('semicolon', token(';')),\n          or(and(lookAheadToken(')'),\n                 constant(NIL)),\n             expression))));\n  var inExpr = seq(token('in'), expression);\n  var inExprExpectingSemi = expecting('semicolon',\n                                      seq(token('in'), expression));\n  var forSpec = mapResult(node(\n    'forSpec',\n    or(seq(token('var'),\n           varDeclMaybeNoIn[true],\n           expecting(\n             'commaOrIn',\n             or(inExpr,\n                seq(\n                  or(\n                    lookAheadToken(';'),\n                    seq(token(','),\n                        list(varDeclMaybeNoIn[true], token(',')))),\n                  secondThirdClauses)))),\n       // get the case where the first clause is empty out of the way.\n       // the lookAhead's return value is the empty placeholder for the\n       // missing expression.\n       seq(and(lookAheadToken(';'),\n               constant(NIL)), secondThirdClauses),\n       // custom parser the non-var case because we have to\n       // read the first expression before we know if there's\n       // an \"in\".\n       new Parser(\n         null,\n         function (t) {\n           var firstExpr = expressionMaybeNoIn[true].parse(t);\n           if (! firstExpr)\n             return null;\n           var rest = secondThirdClauses.parse(t);\n           if (! rest) {\n             // we need a left-hand-side expression for a\n             // `for (x in y)` loop.\n             if (! isExpressionLHS(firstExpr))\n               throw t.getParseError(\"semicolon\");\n             // if we don't see 'in' at this point, it's probably\n             // a missing semicolon\n             rest = inExprExpectingSemi.parseRequired(t);\n           }\n\n           return [firstExpr].concat(rest);\n         }))),\n                          function (clauses) {\n                            // There are four kinds of for-loop, and we call the\n                            // part between the parens one of forSpec, forVarSpec,\n                            // forInSpec, and forVarInSpec.  Having parsed it\n                            // already, we rewrite the node name based on how\n                            // many items came out.  forIn and forVarIn always\n                            // have 3 and 4 items respectively.  for has 5\n                            // (the optional expressions are present as nils).\n                            // forVar has 6 or more, because `for(var x;;);`\n                            // produces [`var` `x` `;` nil `;` nil].\n                            var numChildren = clauses.children.length;\n                            if (numChildren === 3)\n                              return new ParseNode('forInSpec', clauses.children);\n                            else if (numChildren === 4)\n                              return new ParseNode('forVarInSpec', clauses.children);\n                            else if (numChildren >= 6)\n                              return new ParseNode('forVarSpec', clauses.children);\n                            return clauses;\n                          });\n\n  var iterationStatement = or(\n    node('doStmnt', seq(token('do'), statement, token('while'),\n                        token('('), expression, token(')'),\n                        maybeSemicolon)),\n    node('whileStmnt', seq(token('while'), token('('), expression,\n                           closeParenBeforeStatement, statement)),\n    // semicolons must be real, not maybeSemicolons\n    node('forStmnt', seq(\n      token('for'), token('('), forSpec, closeParenBeforeStatement,\n      statement)));\n\n  var returnStatement = node(\n    'returnStmnt',\n    seq(token('return'), or(\n      and(noLineTerminatorHere, expression), constant(NIL)),\n        maybeSemicolon));\n  var continueStatement = node(\n    'continueStmnt',\n    seq(token('continue'), or(\n      and(noLineTerminatorHere, tokenType('IDENTIFIER')), constant(NIL)),\n        maybeSemicolon));\n  var breakStatement = node(\n    'breakStmnt',\n    seq(token('break'), or(\n      and(noLineTerminatorHere, tokenType('IDENTIFIER')), constant(NIL)),\n        maybeSemicolon));\n  var throwStatement = node(\n    'throwStmnt',\n    seq(token('throw'),\n        and(or(noLineTerminatorHere,\n               // If there is a line break here and more tokens after,\n               // we want to error appropriately.  `throw \\n e` should\n               // complain about the \"end of line\", not the `e`.\n               and(not(lookAheadTokenType(\"EOF\")),\n                   new Parser(null,\n                              function (t) {\n                                throw t.getParseError('expression', 'end of line');\n                              }))),\n            expression),\n        maybeSemicolon));\n\n  var withStatement = node(\n    'withStmnt',\n    seq(token('with'), token('('), expression, closeParenBeforeStatement,\n        statement));\n\n  var switchCase = node(\n    'case',\n    seq(token('case'), expression, token(':'),\n        or(lookAheadToken('}'),\n           lookAheadToken('case default'),\n           statements)));\n  var switchDefault = node(\n    'default',\n    seq(token('default'), token(':'),\n        or(lookAheadToken('}'),\n           lookAheadToken('case'),\n           statements)));\n\n  var switchStatement = node(\n    'switchStmnt',\n    seq(token('switch'), token('('), expression, token(')'),\n        token('{'),\n        or(lookAheadToken('}'),\n           lookAheadToken('default'),\n           list(switchCase)),\n        opt(seq(switchDefault,\n                opt(list(switchCase)))),\n        token('}')));\n\n  var catchFinally = expecting(\n    'catch',\n    and(lookAheadToken('catch finally'),\n        seq(\n          or(node(\n            'catch',\n            seq(token('catch'), token('('), tokenType('IDENTIFIER'),\n                token(')'), blockStatement)),\n             constant(NIL)),\n          or(node(\n            'finally',\n            seq(token('finally'), blockStatement)),\n             constant(NIL)))));\n  var tryStatement = node(\n    'tryStmnt',\n    seq(token('try'), blockStatement, catchFinally));\n  var debuggerStatement = node(\n    'debuggerStmnt', seq(token('debugger'), maybeSemicolon));\n\n  statement = expecting('statement',\n                        or(expressionOrLabelStatement,\n                           emptyStatement,\n                           blockStatement,\n                           variableStatement,\n                           ifStatement,\n                           iterationStatement,\n                           returnStatement,\n                           continueStatement,\n                           breakStatement,\n                           withStatement,\n                           switchStatement,\n                           throwStatement,\n                           tryStatement,\n                           debuggerStatement));\n\n  // PROGRAM\n\n  var functionDecl = node(\n    'functionDecl', functionMaybeNameRequired[true]);\n\n  // Look for statement before functionDecl, to catch comments in\n  // includeComments mode.  A statement can't start with 'function'\n  // anyway, so the order doesn't matter otherwise.\n  var sourceElement = or(statement, functionDecl);\n  var sourceElements = list(or(comment, sourceElement));\n\n  functionBody = expecting(\n    'functionBody', or(lookAheadToken('}'), sourceElements));\n\n  var program = node(\n    'program',\n    seq(opt(sourceElements),\n        // If not at EOF, complain \"expecting statement\"\n        expecting('statement', lookAheadTokenType(\"EOF\"))));\n\n  return program.parse(this);\n};\n"
  },
  {
    "path": "packages/jsparse/parser_tests.js",
    "content": "var parserTestOptions = { includeComments: true };\n\nvar allNodeNames = [\n  \";\",\n  \"array\",\n  \"assignment\",\n  \"binary\",\n  \"blockStmnt\",\n  \"boolean\",\n  \"bracket\",\n  \"breakStmnt\",\n  \"call\",\n  \"case\",\n  \"catch\",\n  \"comma\",\n  \"comment\",\n  \"continueStmnt\",\n  \"debuggerStmnt\",\n  \"default\",\n  \"doStmnt\",\n  \"dot\",\n  \"emptyStmnt\",\n  \"expressionStmnt\",\n  \"finally\",\n  \"forInSpec\",\n  \"forSpec\",\n  \"forStmnt\",\n  \"forVarInSpec\",\n  \"forVarSpec\",\n  \"functionDecl\",\n  \"functionExpr\",\n  \"idPropName\",\n  \"identifier\",\n  \"ifStmnt\",\n  \"labelStmnt\",\n  \"new\",\n  \"newcall\",\n  \"nil\",\n  \"null\",\n  \"numPropName\",\n  \"number\",\n  \"object\",\n  \"parens\",\n  \"postfix\",\n  \"program\",\n  \"prop\",\n  \"regex\",\n  \"returnStmnt\",\n  \"strPropName\",\n  \"string\",\n  \"switchStmnt\",\n  \"ternary\",\n  \"this\",\n  \"throwStmnt\",\n  \"tryStmnt\",\n  \"unary\",\n  \"varDecl\",\n  \"varStmnt\",\n  \"whileStmnt\",\n  \"withStmnt\"\n];\n\nvar allNodeNamesSet = {};\n_.each(allNodeNames, function (n) { allNodeNamesSet[n] = true; });\n\n\nvar makeTester = function (test) {\n  return {\n    // Parse code and make sure it matches expectedTreeString.\n    goodParse: function (code, expectedTreeString, regexTokenHints) {\n      var expectedTree = ParseNode.unstringify(expectedTreeString);\n\n      // first use lexer to collect all tokens\n      var lexer = new JSLexer(code);\n      var allTokensInOrder = [];\n      while (! lexer.next().isEOF()) {\n        var lex = lexer.lastLexeme;\n        if (lex.isError())\n          test.fail(\"Lexer error at \" + lex.startPos());\n        if (lex.isToken())\n          allTokensInOrder.push(lex);\n        if (regexTokenHints && regexTokenHints[allTokensInOrder.length])\n          lexer.divisionPermitted = false;\n      }\n\n      var parser = new JSParser(code, parserTestOptions);\n      var actualTree = parser.getSyntaxTree();\n\n      var nextTokenIndex = 0;\n      var check = function (tree) {\n        if (tree instanceof ParseNode) {\n          // This is a NODE (non-terminal).\n          var nodeName = tree.name;\n          if (! (nodeName && typeof nodeName === \"string\" &&\n                 allNodeNamesSet[nodeName] === true))\n            test.fail(\"Not a node name: \" + nodeName);\n          _.each(tree.children, check);\n        } else if (typeof tree === 'object' &&\n                   typeof tree.text === 'function') {\n          // This is a TOKEN (terminal).\n          // Make sure we are visiting every token once, in order.\n          // Make an exception for any comment lexemes present,\n          // because we couldn't know whether to include them in\n          // allTokensInOrder.\n          if (tree.type() !== \"COMMENT\") {\n            if (nextTokenIndex >= allTokensInOrder.length)\n              test.fail(\"Too many tokens: \" + (nextTokenIndex + 1));\n            var referenceToken = allTokensInOrder[nextTokenIndex++];\n            if (tree.text() !== referenceToken.text())\n              test.fail(tree.text() + \" !== \" + referenceToken.text());\n            if (tree.startPos() !== referenceToken.startPos())\n              test.fail(tree.startPos() + \" !== \" + referenceToken.startPos());\n            if (code.substring(tree.startPos(), tree.endPos()) !== tree.text())\n              test.fail(\"Didn't see \" + tree.text() + \" at \" + tree.startPos() +\n                        \" in \" + code);\n          }\n        } else {\n          test.fail(\"Unknown tree part: \" + tree);\n        }\n      };\n\n      check(actualTree);\n      if (nextTokenIndex !== allTokensInOrder.length)\n        test.fail(\"Too few tokens: \" + nextTokenIndex);\n\n      test.equal(parser.pos, code.length);\n\n      test.equal(ParseNode.stringify(actualTree),\n                 ParseNode.stringify(expectedTree), code);\n    },\n    // Takes code with part of it surrounding with backticks.\n    // Removes the two backtick characters, tries to parse the code,\n    // and then asserts that there was a tokenization-level error,\n    // with the part that was between the backticks called out as\n    // the bad token.\n    //\n    // For example, the test \"123`@`\" will try to parse \"123@\" and\n    // assert that a tokenization error occurred at '@'.\n    badToken: function (code) {\n      var constructMessage = function (pos, text) {\n        var nicePos = JSLexer.prettyOffset(code, pos);\n        return \"Bad token at \" + nicePos + \", text `\" + text + \"`\";\n      };\n      var pos = code.indexOf('`');\n      var text = code.match(/`(.*?)`/)[1];\n      code = code.replace(/`/g, '');\n\n      var parsed = false;\n      var error = null;\n      try {\n        var tree = new JSParser(code, parserTestOptions).getSyntaxTree();\n        parsed = true;\n      } catch (e) {\n        error = e;\n      }\n      test.isFalse(parsed);\n      test.isTrue(error);\n      test.equal(error.message, constructMessage(pos, text));\n    },\n    // Takes code with a backtick-quoted string embedded in it.\n    // Removes the backticks and their contents, tries to parse the code,\n    // and then asserts that there was a parse error at the location\n    // where the backtick-quoted string was embedded.  The embedded\n    // string must match whatever the error message says was \"expected\".\n    //\n    // For example, the test \"{`statement`\" will try to parse the code\n    // \"{\" and then assert that an error occured at the end of the string\n    // saying \"Expected statement\".  The test \"1 `semicolon`2\" will try\n    // to parse \"1 2\" and assert that the error \"Expected semicolon\"\n    // appeared after the space and before the 2.\n    //\n    // A second backtick-quoted string is used as the \"found\" token\n    // in the error message.\n    badParse: function (code) {\n      var constructMessage = function (whatExpected, pos, found, after) {\n        return \"Expected \" + whatExpected + (after ? \" after \" + after : \"\") +\n          \" at \" + JSLexer.prettyOffset(code, pos) + \", found \" + found;\n      };\n      var pos = code.indexOf('`');\n\n      var backticked = code.match(/`.*?`/g);\n      var whatExpected = backticked[0] && backticked[0].slice(1,-1);\n      var found = backticked[1] && backticked[1].slice(1, -1);\n      code = code.replace(/`.*?`/g, '');\n\n      var parsed = false;\n      var error = null;\n      var parser = new JSParser(code, parserTestOptions);\n      try {\n        var tree = parser.getSyntaxTree();\n        parsed = true;\n      } catch (e) {\n        error = e;\n      }\n      test.isFalse(parsed);\n      test.isTrue(error);\n      if (! parsed && error) {\n        var after = parser.oldToken;\n        found = (found || parser.newToken);\n        test.equal(error.message,\n                   constructMessage(whatExpected, pos, found, after),\n                   code);\n      }\n    }\n  };\n};\n\n\nTinytest.add(\"jsparse - basics\", function (test) {\n  var tester = makeTester(test);\n  tester.goodParse('1', \"program(expressionStmnt(number(1) ;()))\");\n  tester.goodParse('1 + 1', \"program(expressionStmnt(binary(number(1) + number(1)) ;()))\");\n  tester.goodParse('1*2+3*4', \"program(expressionStmnt(binary(binary(number(1) * number(2)) + \" +\n                \"binary(number(3) * number(4))) ;()))\");\n  tester.goodParse('1 + 1;', \"program(expressionStmnt(binary(number(1) + number(1)) ;))\");\n  tester.goodParse('1 + 1;;', \"program(expressionStmnt(binary(number(1) + number(1)) ;) emptyStmnt(;))\");\n  tester.goodParse('', \"program()\");\n  tester.goodParse('\\n', \"program()\");\n  tester.goodParse(';;;\\n\\n;\\n', \"program(emptyStmnt(;) emptyStmnt(;) emptyStmnt(;) emptyStmnt(;))\");\n  tester.goodParse('foo', \"program(expressionStmnt(identifier(foo) ;()))\");\n  tester.goodParse('foo();', \"program(expressionStmnt(call(identifier(foo) `(` `)`) ;))\");\n  tester.goodParse('var x = 3', \"program(varStmnt(var varDecl(x = number(3)) ;()))\");\n  tester.goodParse('++x;', \"program(expressionStmnt(unary(++ identifier(x)) ;))\");\n  tester.goodParse('x++;', \"program(expressionStmnt(postfix(identifier(x) ++) ;))\");\n  tester.goodParse(\n    'throw new Error',\n    \"program(throwStmnt(throw new(new identifier(Error)) ;()))\");\n  tester.goodParse(\n    'var x = function () { return 123; };',\n    'program(varStmnt(var varDecl(x = functionExpr(function nil() `(` `)` ' +\n      '{ returnStmnt(return number(123) ;) })) ;))');\n\n  tester.badParse(\"var x = `expression`\");\n  tester.badParse(\"1 `semicolon`1\");\n  tester.badParse(\"1+1`semicolon`:\");\n});\n\nTinytest.add(\"jsparse - tokenization errors\", function (test) {\n  var tester = makeTester(test);\n  tester.badToken(\"123`@`\");\n  tester.badToken(\"thisIsATestOf = `'unterminated `\\n strings'\");\n  // make sure newlines aren't quietly included in regex literals\n  tester.badToken(\"var x = `/`a\\nb/;\");\n  tester.badToken(\"var x = `/`a\\\\\\nb/;\");\n  tester.badToken(\"var x = `/`a[\\n]b/;\");\n});\n\nTinytest.add(\"jsparse - syntax forms\", function (test) {\n  var tester = makeTester(test);\n  var trials = [\n    // STATEMENTS\n    ['1',\n     'program(expressionStmnt(number(1) ;()))'],\n    ['1;;;;2',\n     'program(expressionStmnt(number(1) ;) emptyStmnt(;) emptyStmnt(;) emptyStmnt(;) ' +\n     'expressionStmnt(number(2) ;()))'],\n    ['{}',\n     'program(blockStmnt({ }))'],\n    ['{null}',\n     'program(blockStmnt({ expressionStmnt(null(null) ;()) }))'],\n    ['{\\nfoo()\\nbar();\\n}',\n     'program(blockStmnt({ expressionStmnt(call(identifier(foo) `(` `)`) ;()) ' +\n     'expressionStmnt(call(identifier(bar) `(` `)`) ;) }))'],\n    ['{{{}}}',\n     'program(blockStmnt({ blockStmnt({ blockStmnt({ }) }) }))'],\n    ['var x = y, z,\\n  a = b = c;',\n     'program(varStmnt(var varDecl(x = identifier(y)) , varDecl(z) , varDecl(a = ' +\n     'assignment(identifier(b) = identifier(c))) ;))'],\n    ['if (x === y);',\n     'program(ifStmnt(if `(` binary(identifier(x) === identifier(y)) `)` emptyStmnt(;)))'],\n    ['if (z) return',\n     'program(ifStmnt(if `(` identifier(z) `)` returnStmnt(return nil() ;())))'],\n    ['if (a) b; else c',\n     'program(ifStmnt(if `(` identifier(a) `)` expressionStmnt(identifier(b) ;) else ' +\n     'expressionStmnt(identifier(c) ;())))'],\n    ['if (n === 1) { foo(); } else if (n === 2) { bar(); } else { baz(); }',\n     'program(ifStmnt(if `(` binary(identifier(n) === number(1)) `)` blockStmnt(' +\n     '{ expressionStmnt(call(identifier(foo) `(` `)`) ;) }) else ifStmnt(' +\n     'if `(` binary(identifier(n) === number(2)) `)` blockStmnt(' +\n     '{ expressionStmnt(call(identifier(bar) `(` `)`) ;) }) else blockStmnt(' +\n     '{ expressionStmnt(call(identifier(baz) `(` `)`) ;) }))))'],\n    ['while (false);',\n     'program(whileStmnt(while `(` boolean(false) `)` emptyStmnt(;)))'],\n    ['while (/foo/.test(bar.baz)) {\\n  bar = bar.baz;\\n}',\n     'program(whileStmnt(while `(` call(dot(regex(/foo/) . test) `(` ' +\n     'dot(identifier(bar) . baz) `)`) `)` blockStmnt({ expressionStmnt(' +\n     'assignment(identifier(bar) = dot(identifier(bar) . baz)) ;) })))'],\n    ['while (false) while (false);',\n     'program(whileStmnt(while `(` boolean(false) `)` ' +\n     'whileStmnt(while `(` boolean (false) `)` emptyStmnt(;))))'],\n    ['do a; while (b);',\n     'program(doStmnt(do expressionStmnt(identifier(a) ;) while `(` identifier(b) `)` ;))'],\n    ['do { x-- } while (x);',\n     'program(doStmnt(do blockStmnt({ expressionStmnt(postfix(identifier(x) --) ;()) }) ' +\n     'while `(` identifier(x) `)` ;))'],\n    ['do a\\n while (b)\\n x++',\n     'program(doStmnt(do expressionStmnt(identifier(a) ;()) while `(` identifier(b) `)` ;()) ' +\n     'expressionStmnt(postfix(identifier(x) ++) ;()))'],\n    [\"for(;;);\",\n     \"program(forStmnt(for `(` forSpec(nil() ; nil() ; nil()) `)` emptyStmnt(;)))\"],\n    [\"for(x in y);\",\n     \"program(forStmnt(for `(` forInSpec(identifier(x) in identifier(y)) `)` emptyStmnt(;)))\"],\n    [\"for(var x in y);\",\n     \"program(forStmnt(for `(` forVarInSpec(var varDecl(x) in identifier(y)) `)` emptyStmnt(;)))\"],\n    [\"for(var x;;);\",\n     \"program(forStmnt(for `(` forVarSpec(var varDecl(x) ; nil() ; nil()) `)` emptyStmnt(;)))\"],\n    [\"for(var i=0;i<N;i++) {}\",\n     \"program(forStmnt(for `(` forVarSpec(var varDecl(i = number(0)) ; \" +\n     \"binary(identifier(i) < identifier(N)) ; postfix(identifier(i) ++)) `)` blockStmnt({ })))\"],\n    [\"for (var x=3 in y);\",\n     \"program(forStmnt(for `(` forVarInSpec(var varDecl(x = number(3)) in identifier(y)) `)` \" +\n     \"emptyStmnt(;)))\"],\n    [\"for (x.foo in y);\",\n     \"program(forStmnt(for `(` forInSpec(dot(identifier(x) . foo) in identifier(y)) `)` emptyStmnt(;)))\"],\n    [\"return\",\n     \"program(returnStmnt(return nil() ;()))\"],\n    [\"return;\",\n     \"program(returnStmnt(return nil() ;))\"],\n    [\"return null\",\n     \"program(returnStmnt(return null(null) ;()))\"],\n    [\"return null;\",\n     \"program(returnStmnt(return null(null) ;))\"],\n    [\"return\\n1+1\",\n     \"program(returnStmnt(return nil() ;()) expressionStmnt(binary(number(1) + number(1)) ;()))\"],\n    [\"return 1\\n  +1\",\n     \"program(returnStmnt(return binary(number(1) + number(1)) ;()))\"],\n    [\"continue\",\n     \"program(continueStmnt(continue nil() ;()))\"],\n    [\"continue foo\",\n     \"program(continueStmnt(continue foo ;()))\"],\n    [\"continue foo;\",\n     \"program(continueStmnt(continue foo ;))\"],\n    [\"continue\\n  foo;\",\n     \"program(continueStmnt(continue nil() ;()) expressionStmnt(identifier(foo) ;))\"],\n    [\"break\",\n     \"program(breakStmnt(break nil() ;()))\"],\n    [\"break foo\",\n     \"program(breakStmnt(break foo ;()))\"],\n    [\"break foo;\",\n     \"program(breakStmnt(break foo ;))\"],\n    [\"break\\n  foo;\",\n     \"program(breakStmnt(break nil() ;()) expressionStmnt(identifier(foo) ;))\"],\n    [\"throw e;\",\n     \"program(throwStmnt(throw identifier(e) ;))\"],\n    [\"throw e\",\n     \"program(throwStmnt(throw identifier(e) ;()))\"],\n    [\"throw new Error;\",\n     \"program(throwStmnt(throw new(new identifier(Error)) ;))\"],\n    [\"with(x);\",\n     \"program(withStmnt(with `(` identifier(x) `)` emptyStmnt(;)))\"],\n    [\"with(a=b) {}\",\n     \"program(withStmnt(with `(` assignment(identifier(a) = identifier(b)) `)` blockStmnt({ })))\"],\n    [\"switch(x) {}\",\n     \"program(switchStmnt(switch `(` identifier(x) `)` { }))\"],\n    [\"switch(x) {case 1:case 2:case 3:default:case 4:}\",\n     \"program(switchStmnt(switch `(` identifier(x) `)` { \" +\n     \"case(case number(1) :) case(case number(2) :) case(case number(3) :) \" +\n     \"default(default :) case(case number(4) :) }))\"],\n    [\"switch(x) {\\ncase 1:\\n  return\\ncase 2:\\ncase 3:\\n  throw e}\",\n     \"program(switchStmnt(switch `(` identifier(x) `)` { \" +\n     \"case(case number(1) : returnStmnt(return nil() ;())) \" +\n     \"case(case number(2) :) case(case number(3) : \" +\n     \"throwStmnt(throw identifier(e) ;())) }))\"],\n    [\"switch(x) {default:;}\",\n     \"program(switchStmnt(switch `(` identifier(x) `)` { default(default : emptyStmnt(;)) }))\"],\n    [\"try {} catch (e) {} finally {}\",\n     \"program(tryStmnt(try blockStmnt({ }) catch(catch `(` e `)` blockStmnt({ })) \" +\n     \"finally(finally blockStmnt({ }))))\"],\n    [\"try {} finally {}\",\n     \"program(tryStmnt(try blockStmnt({ }) nil() finally(finally blockStmnt({ }))))\"],\n    [\"try {} catch (e) {}\",\n     \"program(tryStmnt(try blockStmnt({ }) catch(catch `(` e `)` blockStmnt({ })) nil()))\"],\n    [\"a:;\",\n     \"program(labelStmnt(a : emptyStmnt(;)))\"],\n    [\"{x:1}\",\n     \"program(blockStmnt({ labelStmnt(x : expressionStmnt(number(1) ;())) }))\"],\n    [\"{x:y:z:1}\",\n     \"program(blockStmnt({ labelStmnt(x : labelStmnt(y : \" +\n     \"labelStmnt(z : expressionStmnt(number(1) ;())))) }))\"],\n    [\";;foo:\\nfor(;;);\",\n     \"program(emptyStmnt(;) emptyStmnt(;) labelStmnt(foo : \" +\n     \"forStmnt(for `(` forSpec(nil() ; nil() ; nil()) `)` emptyStmnt(;))))\"],\n    [\"debugger\",\n     \"program(debuggerStmnt(debugger ;()))\"],\n    [\"debugger;\",\n     \"program(debuggerStmnt(debugger ;))\"],\n    [\"function foo() {}\",\n     \"program(functionDecl(function foo `(` `)` { }))\"],\n    [\"function foo() {function bar() {}}\",\n     \"program(functionDecl(function foo `(` `)` { functionDecl(function bar `(` `)` { }) }))\"],\n    [\";;function f() {};;\",\n     \"program(emptyStmnt(;) emptyStmnt(;) functionDecl(function f `(` `)` { }) \" +\n     \"emptyStmnt(;) emptyStmnt(;))\"],\n    [\"function foo(a,b,c) {}\",\n     \"program(functionDecl(function foo `(` a , b , c `)` { }))\"],\n\n    // EXPRESSIONS\n    [\"null + this - 3 + true\",\n     \"program(expressionStmnt(binary(binary(binary(null(null) + this(this)) - \" +\n     \"number(3)) + boolean(true)) ;()))\"],\n    [\"+.5\",\n     \"program(expressionStmnt(unary(+ number(.5)) ;()))\"],\n    [\"a1a1a\",\n     \"program(expressionStmnt(identifier(a1a1a) ;()))\"],\n    [\"/abc/mig\",\n     \"program(expressionStmnt(regex(/abc/mig) ;()))\"],\n    [\"/[]/\",\n     \"program(expressionStmnt(regex(/[]/) ;()))\"],\n    [\"/[/]/\",\n     \"program(expressionStmnt(regex(/[/]/) ;()))\"],\n    [\"/[[/]/\",\n     \"program(expressionStmnt(regex(/[[/]/) ;()))\"],\n    [\"/.\\\\/[a//b]\\\\[\\\\][[\\\\d/]/\",\n     \"program(expressionStmnt(regex(/.\\\\/[a//b]\\\\[\\\\][[\\\\d/]/) ;()))\"],\n    [\"a / /b/mgi / c\",\n     \"program(expressionStmnt(binary(binary(identifier(a) / \" +\n     \"regex(/b/mgi)) / identifier(c)) ;()))\"],\n    [\"'a' + \\\"\\\" + \\\"b\\\" + '\\\\''\",\n     \"program(expressionStmnt(binary(binary(binary(string('a') + string(\\\"\\\")) + \" +\n     \"string(\\\"b\\\")) + string('\\\\'')) ;()))\"],\n    [\"_ + x0123 + $\",\n     \"program(expressionStmnt(binary(binary(identifier(_) + \" +\n     \"identifier(x0123)) + identifier($)) ;()))\"],\n    [\"if ((x = 1)) return ((1+2))*((1<<2));\",\n     \"program(ifStmnt(if `(` parens(`(` assignment(identifier(x) = number(1)) `)`) \" +\n     \"`)` returnStmnt(return binary(parens(`(` parens(`(` binary(number(1) + \" +\n     \"number(2)) `)`) `)`) * parens(`(` parens(`(` binary(number(1) << number(2)) \" +\n     \"`)`) `)`)) ;)))\"],\n    [\"[];\",\n     \"program(expressionStmnt(array([ ]) ;))\"],\n    [\"[,,,];\",\n     \"program(expressionStmnt(array([ , , , ]) ;))\"],\n    [\"[(1,2),,3];\",\n     \"program(expressionStmnt(array([ parens(`(` comma(number(1) , \" +\n     \"number(2)) `)`) , , number(3) ]) ;))\"],\n    [\"({});\",\n     \"program(expressionStmnt(parens(`(` object({ }) `)`) ;))\"],\n    [\"({1:1});\",\n     \"program(expressionStmnt(parens(`(` object({ prop(numPropName(1) : number(1)) }) `)`) ;))\"],\n    [\"({x:true});\",\n     \"program(expressionStmnt(parens(`(` object({ prop(idPropName(x) : boolean(true)) }) `)`) ;))\"],\n    [\"({'a':b, c:'d', 1:null});\",\n     \"program(expressionStmnt(parens(`(` object({ prop(strPropName('a') : \" +\n     \"identifier(b)) , prop(idPropName(c) : string('d')) , prop(numPropName(1) \" +\n     \": null(null)) }) `)`) ;))\"],\n    [\"(function () {});\",\n     \"program(expressionStmnt(parens(`(` functionExpr(function nil() `(` `)` { }) `)`) ;))\"],\n    [\"(function foo() {});\",\n     \"program(expressionStmnt(parens(`(` functionExpr(function foo `(` `)` { }) `)`) ;))\"],\n    [\"x = function () {}.y;\",\n     \"program(expressionStmnt(assignment(identifier(x) = dot(functionExpr(\" +\n     \"function nil() `(` `)` { }) . y)) ;))\"],\n    [\"(function (a) {})\",\n     \"program(expressionStmnt(parens(`(` functionExpr(function nil() \" +\n     \"`(` a `)` { }) `)`) ;()))\"],\n    [\"(function (a,b,c) {})\",\n     \"program(expressionStmnt(parens(`(` functionExpr(function nil() `(` \" +\n     \"a , b , c `)` { }) `)`) ;()))\"],\n    [\"foo.bar.baz;\",\n     \"program(expressionStmnt(dot(dot(identifier(foo) . bar) . baz) ;))\"],\n    [\"foo[bar,bar][baz].qux[1+1];\",\n     \"program(expressionStmnt(bracket(dot(bracket(bracket(identifier(foo) \" +\n     \"[ comma(identifier(bar) , identifier(bar)) ]) [ identifier(baz) ]) . qux) \" +\n     \"[ binary(number(1) + number(1)) ]) ;))\"],\n    [\"new new a.b.c[d]\",\n     \"program(expressionStmnt(new(new new(new bracket(dot(dot(identifier(a) \" +\n     \". b) . c) [ identifier(d) ]))) ;()))\"],\n    [\"new new a.b.c[d]()\",\n     \"program(expressionStmnt(new(new newcall(new \" +\n     \"bracket(dot(dot(identifier(a) . b) . c) [ identifier(d) ]) `(` `)`)) ;()))\"],\n    [\"new new a.b.c[d]()()\",\n     \"program(expressionStmnt(newcall(new newcall(new \" +\n     \"bracket(dot(dot(identifier(a) . b) . c) [ identifier(d) ]) `(` `)`) `(` `)`) ;()))\"],\n    [\"new foo(x).bar(y)\",\n     \"program(expressionStmnt(call(dot(newcall(new identifier(foo) `(` \" +\n     \"identifier(x) `)`) . bar) `(` identifier(y) `)`) ;()))\"],\n    [\"new new foo().bar\",\n     \"program(expressionStmnt(new(new dot(newcall(new identifier(foo) `(` `)`) . bar)) ;()))\"],\n    [\"delete void typeof - + ~ ! -- ++ x;\",\n     \"program(expressionStmnt(unary(delete unary(void unary(typeof unary(- unary(+ \" +\n     \"unary(~ unary(! unary(-- unary(++ identifier(x)))))))))) ;))\"],\n    [\"x++ + ++y\",\n     \"program(expressionStmnt(binary(postfix(identifier(x) ++) + \" +\n     \"unary(++ identifier(y))) ;()))\"],\n    [\"1*2+3*4\",\n     \"program(expressionStmnt(binary(binary(number(1) * number(2)) \" +\n     \"+ binary(number(3) * number(4))) ;()))\"],\n    [\"a*b/c%d+e-f<<g>>h>>>i<j>k<=l>=m instanceof n in o==p!=q===r!==s&t^u|v&&w||x\",\n     \"program(expressionStmnt(binary(binary(binary(binary(binary(binary(binary(\" +\n     \"binary(binary(binary(binary(binary(binary(binary(binary(binary(binary(binary(\" +\n     \"binary(binary(binary(binary(binary(identifier(a) * identifier(b)) / \" +\n     \"identifier(c)) % identifier(d)) + identifier(e)) - identifier(f)) << identifier(g)) \" +\n     \">> identifier(h)) >>> identifier(i)) < identifier(j)) > identifier(k)) <= \" +\n     \"identifier(l)) >= identifier(m)) instanceof identifier(n)) in identifier(o)) == \" +\n     \"identifier(p)) != identifier(q)) === identifier(r)) !== identifier(s)) & \" +\n     \"identifier(t)) ^ identifier(u)) | identifier(v)) && identifier(w)) || \" +\n     \"identifier(x)) ;()))\"],\n    [\"a||b&&c|d^e&f!==g===h!=i==j in k instanceof l>=m<=n<o<p>>>q>>r<<s-t+u%v/w*x\",\n     \"program(expressionStmnt(binary(identifier(a) || binary(identifier(b) && \" +\n     \"binary(identifier(c) | binary(identifier(d) ^ binary(identifier(e) & \" +\n     \"binary(binary(binary(binary(identifier(f) !== identifier(g)) === identifier(h)) \" +\n     \"!= identifier(i)) == binary(binary(binary(binary(binary(binary(identifier(j) in \" +\n     \"identifier(k)) instanceof identifier(l)) >= identifier(m)) <= identifier(n)) < \" +\n     \"identifier(o)) < binary(binary(binary(identifier(p) >>> identifier(q)) >> \" +\n     \"identifier(r)) << binary(binary(identifier(s) - identifier(t)) + \" +\n     \"binary(binary(binary(identifier(u) % identifier(v)) / identifier(w)) * \" +\n     \"identifier(x))))))))))) ;()))\"],\n    [\"a?b:c\",\n     \"program(expressionStmnt(ternary(identifier(a) ? identifier(b) : \" +\n     \"identifier(c)) ;()))\"],\n    [\"1==2?3=4:5=6\",\n     \"program(expressionStmnt(ternary(binary(number(1) == number(2)) ? \" +\n     \"assignment(number(3) = number(4)) : assignment(number(5) = number(6))) ;()))\"],\n    [\"a=b,c=d\",\n     \"program(expressionStmnt(comma(assignment(identifier(a) = identifier(b)) , \" +\n     \"assignment(identifier(c) = identifier(d))) ;()))\"],\n    [\"a=b=c=d\",\n     \"program(expressionStmnt(assignment(identifier(a) = assignment(identifier(b) \" +\n     \"= assignment(identifier(c) = identifier(d)))) ;()))\"],\n    [\"x[0]=x[1]=true\",\n     \"program(expressionStmnt(assignment(bracket(identifier(x) [ number(0) ]) = \" +\n     \"assignment(bracket(identifier(x) [ number(1) ]) = boolean(true))) ;()))\"],\n    [\"a*=b/=c%=d+=e-=f<<=g>>=h>>>=i&=j^=k|=l\",\n     \"program(expressionStmnt(assignment(identifier(a) *= assignment(identifier(b) \" +\n     \"/= assignment(identifier(c) %= assignment(identifier(d) += \" +\n     \"assignment(identifier(e) -= assignment(identifier(f) <<= \" +\n     \"assignment(identifier(g) >>= assignment(identifier(h) >>>= \" +\n     \"assignment(identifier(i) &= assignment(identifier(j) ^= \" +\n     \"assignment(identifier(k) |= identifier(l)))))))))))) ;()))\"],\n    [\"1;\\n\\n\\n\\n/* foo */\\n// bar\\n\", // trailing whitespace and comments\n     \"program(expressionStmnt(number(1) ;) comment(`/* foo */`) comment(`// bar`))\"],\n    // includeComments option; comments in AST\n    [\"//foo\",\n     \"program(comment(//foo))\"],\n    [\"//foo\\n\",\n     \"program(comment(//foo))\"],\n    [\"/*foo*/\",\n     \"program(comment(/*foo*/))\"],\n    [\"/*foo*/\\n\",\n     \"program(comment(/*foo*/))\"],\n    [\";\\n//foo\",\n     \"program(emptyStmnt(;) comment(//foo))\"],\n    [\";\\n/*foo*/\",\n     \"program(emptyStmnt(;) comment(/*foo*/))\"],\n    [\";\\n//foo\\n;\",\n     \"program(emptyStmnt(;) comment(//foo) emptyStmnt(;))\"],\n    [\";\\n/*foo*/\\n;\",\n     \"program(emptyStmnt(;) comment(/*foo*/) emptyStmnt(;))\"],\n    [\";\\n//foo\\n//bar\\n;\",\n     \"program(emptyStmnt(;) comment(//foo) comment(//bar) emptyStmnt(;))\"],\n    [\";\\n/*foo*/ /*bar*/\\n;\",\n     \"program(emptyStmnt(;) comment(/*foo*/) comment(/*bar*/) emptyStmnt(;))\"],\n    [\";//foo\\n//bar\\n;\",\n     \"program(emptyStmnt(;) comment(//bar) emptyStmnt(;))\"],\n    [\";/*foo*/\\n/*bar*/\\n;\",\n     \"program(emptyStmnt(;) comment(/*bar*/) emptyStmnt(;))\"],\n    [\";/*foo*//*bar*///baz\\n;\",\n     \"program(emptyStmnt(;) emptyStmnt(;))\"],\n    [\";/*foo*//*bar*///baz\",\n     \"program(emptyStmnt(;))\"],\n    [\"/*foo*//*bar*///baz\",\n     \"program(comment(/*foo*/) comment(/*bar*/) comment(//baz))\"],\n    [\"//foo\\n//bar\\nfunction aaa() {}\\nfunction bbb() {}\",\n     \"program(comment(//foo) comment(//bar) functionDecl(function aaa `(` `)` { }) \" +\n     \"functionDecl(function bbb `(` `)` { }))\"],\n    // comments don't interfere with parse\n    [\"if (true)\\n//comment\\nfoo();\",\n     \"program(ifStmnt(if `(` boolean(true) `)` \" +\n     \"expressionStmnt(call(identifier(foo) `(` `)`) ;)))\"],\n    // bare keywords allowed in property access and object literal\n    [\"foo.return();\",\n     \"program(expressionStmnt(call(dot(identifier(foo) . return) `(` `)`) ;))\"],\n    [\"foo.true();\",\n     \"program(expressionStmnt(call(dot(identifier(foo) . true) `(` `)`) ;))\"],\n    [\"foo.null();\",\n     \"program(expressionStmnt(call(dot(identifier(foo) . null) `(` `)`) ;))\"],\n    [\"({true:3})\",\n     \"program(expressionStmnt(parens(`(` object({ prop(idPropName(true) : number(3)) }) `)`) ;()))\"],\n    [\"({null:3})\",\n     \"program(expressionStmnt(parens(`(` object({ prop(idPropName(null) : number(3)) }) `)`) ;()))\"],\n    [\"({if:3})\",\n     \"program(expressionStmnt(parens(`(` object({ prop(idPropName(if) : number(3)) }) `)`) ;()))\"],\n    // ES5 line continuations in string literals\n    [\"var x = 'a\\\\\\nb\\\\\\nc';\",\n     \"program(varStmnt(var varDecl(x = string(`'a\\\\\\nb\\\\\\nc'`)) ;))\"],\n    // ES5 trailing comma in object literal\n    [\"({});\",\n     \"program(expressionStmnt(parens(`(` object({ }) `)`) ;))\"],\n    [\"({x:1});\",\n     \"program(expressionStmnt(parens(`(` object({ prop(idPropName(x) : number(1)) }) `)`) ;))\"],\n    [\"({x:1,});\",\n     \"program(expressionStmnt(parens(`(` object({ prop(idPropName(x) : number(1)) , }) `)`) ;))\"],\n    [\"({x:1,y:2});\",\n     \"program(expressionStmnt(parens(`(` object({ prop(idPropName(x) : number(1)) , \" +\n     \"prop(idPropName(y) : number(2)) }) `)`) ;))\"],\n    [\"({x:1,y:2,});\",\n     \"program(expressionStmnt(parens(`(` object({ prop(idPropName(x) : number(1)) , \" +\n     \"prop(idPropName(y) : number(2)) , }) `)`) ;))\"]\n  ];\n  _.each(trials, function (tr) {\n    tester.goodParse(tr[0], tr[1]);\n  });\n});\n\nTinytest.add(\"jsparse - bad parses\", function (test) {\n  var tester = makeTester(test);\n  // string between backticks is pulled out and becomes what's \"expected\"\n  // at that location, according to the correct error message\n  var trials = [\n    '{`statement`',\n    'if (`expression`)',\n    'if `(`else',\n    'var`varDecl`;',\n    'while (`expression`);',\n    'while`(`;',\n    'do a `semicolon`while b;',\n    'do a\\n while `(`b;',\n    '1 `semicolon`2',\n    'for (`forSpec`);',\n    'for (1\\n`semicolon`2\\n3);',\n    'continue `semicolon`1+1;',\n    'break `semicolon`1+1;',\n    'throw`expression`',\n    'throw`expression`;',\n    'throw\\n`expression`',\n    'throw\\n`expression``end of line`e',\n    'throw `expression`=;',\n    'with(`expression`);',\n    'switch(`expression`)',\n    'switch(x)`{`;',\n    'try`block`',\n    'try {}`catch`',\n    'try {} catch`(`;',\n    'try {} catch(e)`block`;',\n    '1+1`semicolon`:',\n    '{a:`statement`}',\n    'function `IDENTIFIER`() {}',\n    'foo: `statement`function foo() {}',\n    '[`expression`=',\n    '[,,`expression`=',\n    '({`propertyName`|:3})',\n    '({1:2,3`:`})',\n    '({1:2,`propertyName`',\n    'x.`IDENTIFIER`,',\n    'foo;`semicolon`:;',\n    '1;`statement`=',\n    'a+b`semicolon`=c;',\n    'for(1+1 `semicolon`in {});',\n    '`statement`=',\n    'for(;`expression`var;) {}',\n    '({`propertyName`',\n    '({`propertyName`,})',\n    '({`propertyName`:})',\n    '({x`:`})',\n    '({x:1,`propertyName`',\n    '({x:1,`propertyName`,})',\n    '({x:1`,`',\n    '({x:1,`propertyName`,y:2})',\n    '({x:1,`propertyName`,})',\n    '({x:1,y:2`,`:',\n    '({x:1,y:2,`propertyName`',\n    '({x:1,y:2,`propertyName`:',\n    '({x:1,y:2,`propertyName`,})'\n  ];\n  _.each(trials, function (tr) {\n    tester.badParse(tr);\n  });\n});\n\nTinytest.add(\"jsparse - regex division ambiguity\", function (test) {\n  var tester = makeTester(test);\n  tester.goodParse(\"if (e) /f/g;\",\n                   \"program(ifStmnt(if `(` identifier(e) `)` expressionStmnt(regex(/f/g) ;)))\",\n                   {4: true});\n  tester.goodParse(\"++/x/.y;\",\n                   \"program(expressionStmnt(unary(++ dot(regex(/x/) . y)) ;))\",\n                   {1: true});\n  tester.goodParse(\"x++/2/g;\",\n                   \"program(expressionStmnt(binary(binary(postfix(identifier(x) ++) / \" +\n                   \"number(2)) / identifier(g)) ;))\");\n  tester.goodParse(\"(1+1)/2/g;\",\n                   \"program(expressionStmnt(binary(binary(parens(`(` binary(number(1) + \" +\n                   \"number(1)) `)`) / \" +\n                   \"number(2)) / identifier(g)) ;))\");\n  tester.goodParse(\"/x/\",\n                   \"program(expressionStmnt(regex(/x/) ;()))\");\n});\n\nTinytest.add(\"jsparse - semicolon insertion\", function (test) {\n  var tester = makeTester(test);\n  // Spec section 7.9.2\n  tester.badParse(\"{ 1 `semicolon`2 } 3\");\n  tester.goodParse(\"{ 1\\n2 } 3\", \"program(blockStmnt({ expressionStmnt(number(1) \" +\n                   \";()) expressionStmnt(number(2) ;()) }) expressionStmnt(number(3) ;()))\");\n  tester.badParse(\"for (a; b\\n`semicolon`)\");\n  tester.goodParse(\"return\\na + b\",\n                   \"program(returnStmnt(return nil() ;()) \" +\n                   \"expressionStmnt(binary(identifier(a) + identifier(b)) ;()))\");\n  tester.goodParse(\"a = b\\n++c\",\n                   \"program(expressionStmnt(assignment(identifier(a) = identifier(b)) ;())\" +\n                   \"expressionStmnt(unary(++ identifier(c)) ;()))\");\n  tester.badParse(\"if (a > b)\\n`statement`else c = d\");\n  tester.goodParse(\"a = b + c\\n(d + e).print()\",\n                   \"program(expressionStmnt(assignment(identifier(a) = \" +\n                   \"binary(identifier(b) + call(dot(call(identifier(c) `(` \" +\n                   \"binary(identifier(d) + identifier(e)) `)`) . print) `(` `)`))) ;()))\");\n});\n\nTinytest.add(\"jsparse - comments\", function (test) {\n  var tester = makeTester(test);\n  // newline in multi-line comment makes it into a line break for semicolon\n  // insertion purposes\n  tester.badParse(\"1/**/`semicolon`2\");\n  tester.goodParse(\"1/*\\n*/2\",\n                   \"program(expressionStmnt(number(1) ;()) expressionStmnt(number(2) ;()))\");\n});\n\nTinytest.add(\"jsparse - initial lex error\", function (test) {\n  var doTest = function (code) {\n    // this shouldn't throw\n    var parser = new JSParser(code, parserTestOptions);\n    // this should throw\n    try {\n      parser.getSyntaxTree();\n      test.fail();\n    } catch (e) {\n      test.isTrue(/^Bad token/.test(e.message), e.message);\n    }\n  };\n\n  doTest('/');\n  doTest('@');\n});\n"
  },
  {
    "path": "packages/jsparse/parserlib.js",
    "content": "///// TOKENIZER AND PARSER COMBINATORS\n\n// XXX track line/col position, for errors and maybe token info\n\nvar isArray = function (obj) {\n  return obj && (typeof obj === 'object') && (typeof obj.length === 'number');\n};\n\nParseNode = function (name, children) {\n  this.name = name;\n  this.children = children;\n\n  if (! isArray(children))\n    throw new Error(\"Expected array in new ParseNode(\" + name + \", ...)\");\n};\n\n\nParser = function (expecting, runFunc) {\n  this.expecting = expecting;\n  this._run = runFunc;\n};\n\nParser.prototype.parse = function (t) {\n  return this._run(t);\n};\n\nParser.prototype.parseRequired = function (t) {\n  return this.parseRequiredIf(t, true);\n};\n\nParser.prototype.parseRequiredIf = function (t, required) {\n  var result = this._run(t);\n\n  if (required && ! result)\n    throw t.getParseError(this.expecting);\n\n  return result;\n};\n\nParser.expecting = function (expecting, parser) {\n  return new Parser(expecting, parser._run);\n};\n\n\n// A parser that consume()s has to succeed.\n// Similarly, a parser that fails can't have consumed.\n\nParsers = {};\n\nParsers.assertion = function (test) {\n  return new Parser(\n    null, function (t) {\n      return test(t) ? [] : null;\n    });\n};\n\nParsers.node = function (name, childrenParser) {\n  return new Parser(name, function (t) {\n    var children = childrenParser.parse(t);\n    if (! children)\n      return null;\n    if (! isArray(children))\n      children = [children];\n    return new ParseNode(name, children);\n  });\n};\n\nParsers.or = function (/*parsers*/) {\n  var args = arguments;\n  return new Parser(\n    args[args.length - 1].expecting,\n    function (t) {\n      var result;\n      for(var i = 0, N = args.length; i < N; i++) {\n        result = args[i].parse(t);\n        if (result)\n          return result;\n      }\n      return null;\n    });\n};\n\n// Parses a left-recursive expression with zero or more occurrences\n// of a binary op.  Leaves the term unwrapped if no op.  For example\n// (in a hypothetical use case):\n// `1` => \"1\"\n// `1+2` => [\"binary\", \"1\", \"+\", \"2\"]\n// `1+2+3` => [\"binary\", [\"binary\", \"1\", \"+\", \"2\"], \"+\", \"3\"]\n//\n// opParsers is an array of op parsers from high to low\n// precedence (tightest-binding first)\nParsers.binaryLeft = function (name, termParser, opParsers) {\n  var opParser;\n\n  if (opParsers.length === 1) {\n    // take single opParser out of its array\n    opParser = opParsers[0];\n  } else {\n    // pop off last opParser (non-destructively) and replace\n    // termParser with a recursive binaryLeft on the remaining\n    // ops.\n    termParser = Parsers.binaryLeft(name, termParser, opParsers.slice(0, -1));\n    opParser = opParsers[opParsers.length - 1];\n  }\n\n  return new Parser(\n    termParser.expecting,\n    function (t) {\n      var result = termParser.parse(t);\n      if (! result)\n        return null;\n\n      var op;\n      while ((op = opParser.parse(t))) {\n        result = new ParseNode(\n          name,\n          [result, op, termParser.parseRequired(t)]);\n      }\n      return result;\n    });\n};\n\nParsers.unary = function (name, termParser, opParser) {\n  var unaryList = Parsers.opt(Parsers.list(opParser));\n  return new Parser(\n    termParser.expecting,\n    function (t) {\n      var unaries = unaryList.parse(t);\n      // if we have unaries, we are committed and\n      // have to match a term or error.\n      var result = termParser.parseRequiredIf(t, unaries.length);\n      if (! result)\n        return null;\n\n      while (unaries.length)\n        result = new ParseNode(name, [unaries.pop(), result]);\n      return result;\n    });\n};\n\n// Parses a list of one or more items with a separator, listing the\n// items and separators.  (Separator is optional.)  For example:\n// `x` => [\"x\"]\n// `x,y` => [\"x\", \",\", \"y\"]\n// `x,y,z` => [\"x\", \",\", \"y\", \",\", \"z\"]\n// Unpacks.\nParsers.list = function (itemParser, sepParser) {\n  var push = function(array, newThing) {\n    if (isArray(newThing))\n      array.push.apply(array, newThing);\n    else\n      array.push(newThing);\n  };\n  return new Parser(\n    itemParser.expecting,\n    function (t) {\n      var result = [];\n      var firstItem = itemParser.parse(t);\n      if (! firstItem)\n        return null;\n      push(result, firstItem);\n\n      if (sepParser) {\n        var sep;\n        while ((sep = sepParser.parse(t))) {\n          push(result, sep);\n          push(result, itemParser.parseRequired(t));\n        }\n      } else {\n        var item;\n        while ((item = itemParser.parse(t)))\n          push(result, item);\n      }\n      return result;\n    });\n};\n\n// Unpacks arrays (nested seqs).\nParsers.seq = function (/*parsers*/) {\n  var args = arguments;\n  if (! args.length)\n    return Parsers.constant([]);\n\n  return new Parser(\n    args[0].expecting,\n    function (t) {\n      var result = [];\n      for (var i = 0, N = args.length; i < N; i++) {\n        // first item in sequence can fail, and we\n        // fail (without error); after that, error on failure\n        var r = args[i].parseRequiredIf(t, i > 0);\n        if (! r)\n          return null;\n\n        if (isArray(r)) // append array!\n          result.push.apply(result, r);\n        else\n          result.push(r);\n      }\n      return result;\n    });\n};\n\n// parsers except last must never consume\nParsers.and = function (/*parsers*/) {\n  var args = arguments;\n  if (! args.length)\n    return Parsers.constant([]);\n\n  return new Parser(\n    args[args.length - 1].expecting,\n    function (t) {\n      var result;\n      for(var i = 0, N = args.length; i < N; i++) {\n        result = args[i].parse(t);\n        if (! result)\n          return null;\n      }\n      return result;\n    });\n};\n\n// parser must not consume\nParsers.not = function (parser) {\n  return new Parser(\n    null,\n    function (t) {\n      return parser.parse(t) ? null : [];\n    });\n};\n\n// parser that looks at nothing and returns result\nParsers.constant = function (result) {\n  return new Parser(null,\n                    function (t) { return result; });\n};\n\nParsers.opt = function (parser) {\n  return Parser.expecting(\n    parser.expecting,\n    Parsers.or(parser, Parsers.seq()));\n};\n\nParsers.mapResult = function (parser, func) {\n  return new Parser(\n    parser.expecting,\n    function (t) {\n      var v = parser.parse(t);\n      return v ? func(v, t) : null;\n    });\n};\n\nParsers.lazy = function (expecting, parserFunc) {\n  var inner = null;\n  return new Parser(expecting, function (t) {\n    if (! inner)\n      inner = parserFunc();\n    return inner.parse(t);\n  });\n};\n"
  },
  {
    "path": "packages/jsparse/stringify.js",
    "content": "// The \"tree string\" format is a simple format for representing syntax trees.\n//\n// For example, the parse of `x++;` is written as:\n// \"program(expressionStmnt(postfix(identifier(x) ++) ;))\"\n//\n// A Node is written as \"name(item1 item2 item3)\", with additional whitespace\n// allowed anywhere between the name, parentheses, and items.\n//\n// Tokens don't need to be escaped unless they contain '(', ')', whitespace, or\n// backticks, or are empty.  If they do, they can be written enclosed in backticks.\n// To escape a backtick within backticks, double it.\n//\n// `stringify` generates \"canonical\" tree strings, which have no extra escaping\n// or whitespace, just one space between items in a Node.\n\n\nParseNode.prototype.stringify = function () {\n  return ParseNode.stringify(this);\n};\n\nvar backtickEscape = function (str) {\n  if (/[\\s()`]/.test(str))\n    return '`' + str.replace(/`/g, '``') + '`';\n  else if (! str)\n    return '``';\n  else\n    return str;\n};\n\nvar backtickUnescape = function (str) {\n  if (str.charAt(0) === '`') {\n    if (str.length === 1 || str.slice(-1) !== '`')\n      throw new Error(\"Mismatched ` in \" + str);\n    if (str.length === 2)\n      str = '';\n    else\n      str = str.slice(1, -1).replace(/``/g, '`');\n  }\n  return str;\n};\n\nParseNode.stringify = function (tree) {\n  if (tree instanceof ParseNode) {\n    var str = backtickEscape(tree.name);\n    str += '(';\n    var escapedChildren = [];\n    for(var i = 0, N = tree.children.length; i < N; i++)\n      escapedChildren.push(ParseNode.stringify(tree.children[i]));\n    str += escapedChildren.join(' ');\n    str += ')';\n    return str;\n  }\n\n  // Treat a token object or string as a token.\n  if (typeof tree.text === 'function')\n    tree = tree.text();\n  else if (typeof tree.text === 'string')\n    tree = tree.text;\n  return backtickEscape(String(tree));\n};\n\nParseNode.unstringify = function (str) {\n  var lexemes = str.match(/\\(|\\)|`([^`]||``)*`|`|[^\\s()`]+/g) || [];\n  var N = lexemes.length;\n  var state = {\n    i: 0,\n    getParseError: function (expecting) {\n      throw new Error(\"unstringify: Expecting \" + expecting +\", found \" +\n                      (lexemes[this.i] || \"end of string\"));\n    },\n    peek: function () { return lexemes[this.i]; },\n    advance: function () { this.i++; }\n  };\n  var paren = function (chr) {\n    return new Parser(chr, function (t) {\n      if (t.peek() !== chr)\n        return null;\n      t.advance();\n      return chr;\n    });\n  };\n  var EMPTY_STRING = [\"\"];\n  var token = new Parser('token', function (t) {\n    var txt = t.peek();\n    if (!txt || txt.charAt(0) === '(' || txt.charAt(0) === ')')\n      return null;\n\n    t.advance();\n    // can't return falsy value from successful parser\n    return backtickUnescape(txt) || EMPTY_STRING;\n  });\n\n  // Make \"item\" lazy so it can be recursive.\n  var item = Parsers.lazy('token', function () { return item; });\n\n  // Parse a single node or token.\n  item = Parsers.mapResult(\n    Parsers.seq(token,\n                Parsers.opt(Parsers.seq(\n                  paren('('), Parsers.opt(Parsers.list(item)), paren(')')))),\n    function (v) {\n      for(var i = 0, N = v.length; i < N; i++)\n        if (v[i] === EMPTY_STRING)\n          v[i] = \"\";\n\n      if (v.length === 1)\n        // token\n        return v[0];\n      // node. exclude parens\n      return new ParseNode(v[0], v.slice(2, -1));\n    });\n\n  var endOfString = new Parser(\"end of string\", function (t) {\n    return t.i === N ? [] : null;\n  });\n\n  return Parsers.seq(item, endOfString).parseRequired(state)[0];\n};\n"
  },
  {
    "path": "packages/launch-screen/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/launch-screen/README.md",
    "content": "Launch Screen package\n===\n\nA mobile-only package that provides an API for postponing when your\napp's launch screen is removed and your app is made visible. For\nexample, your app can avoid showing the user a white page while first\nrendering the UI.\n\n### Simple usage\n\n```js\n// just add the package, no special configuration required\n```\n\nWhen this package is added, the app will hold the launch screen until\nthe `body` template is rendered. If you're using iron:router in your\napp, it waits until the first route is rendered.\n\nYou can also control it manually if you want to wait on other UI\nelements to be loaded before releasing the launch screen and showing\nthe user the actual app.\n\n### Additional waiting before releasing the launch screen\n\nTo wait on more events before releasing the launch screen, call `var handle =\nLaunchScreen.hold()` in the top-level of the client code of your app, and when\nyou're ready to show the launch screen, call `handle.release()`.\n\nFor example, to wait for a template to be rendered:\n\n```javascript\n// in a client-only javascript file\nvar handle = LaunchScreen.hold();\n\nTemplate.myUI.onRendered(function () {\n  handle.release();\n});\n```\n\nYour app, or packages used in your app, can call `LaunchScreen.hold()`\nmultiple times. The launch screen will be removed once `release` has been\ncalled on all of the handles.\n"
  },
  {
    "path": "packages/launch-screen/default-behavior.js",
    "content": "// Hold launch screen on app load. This reflects the fact that Meteor\n// mobile apps that use this package always start with a launch screen\n// visible. (see XXX comment at the top of package.js for more\n// details)\nvar handle = LaunchScreen.hold();\n\nvar Template = Package.templating && Package.templating.Template;\n\nMeteor.startup(function () {\n  if (! Template) {\n    handle.release();\n  } else if (Package['iron:router']) {\n    // XXX Instead of doing this here, this code should be in\n    // iron:router directly. Note that since we're in a\n    // `Meteor.startup` block it's ok that we don't have a\n    // weak dependency on iron:router in package.js.\n    Package['iron:router'].Router.onAfterAction(function () {\n      handle.release();\n    });\n  } else {\n    Template.body.onRendered(function () {\n      handle.release();\n    });\n\n    // In case `Template.body` never gets rendered (due to some bug),\n    // hide the launch screen after 6 seconds. This matches the\n    // observed timeout that Cordova apps on Android (but not iOS)\n    // have on hiding the launch screen (even if you don't call\n    // `navigator.splashscreen.hide()`)\n    setTimeout(function () {\n      handle.release();\n    }, 6000);\n  }\n});\n"
  },
  {
    "path": "packages/launch-screen/mobile-launch-screen.js",
    "content": "// XXX This currently implements loading screens for mobile apps only,\n// but in the future can be expanded to all apps.\n\nvar holdCount = 0;\nvar alreadyHidden = false;\n\nLaunchScreen = {\n  hold: function () {\n    if (! Meteor.isCordova) {\n      return {\n        release: function () { /* noop */ }\n      };\n    }\n\n    if (alreadyHidden) {\n      throw new Error(\"Can't show launch screen once it's hidden\");\n    }\n\n    holdCount++;\n\n    var released = false;\n    var release = function () {\n      if (! Meteor.isCordova)\n        return;\n\n      if (! released) {\n        released = true;\n        holdCount--;\n        if (holdCount === 0 &&\n            typeof navigator !== 'undefined' && navigator.splashscreen) {\n          alreadyHidden = true;\n          navigator.splashscreen.hide();\n        }\n      }\n    };\n\n    // Returns a launch screen handle with a release method\n    return {\n      release: release\n    };\n  }\n};\n"
  },
  {
    "path": "packages/launch-screen/package.js",
    "content": "Package.describe({\n  // XXX We currently hard-code the \"launch-screen\" package in the\n  // build tool. If this package is in your app, we turn off the\n  // default splash screen loading behavior (this packages hides it\n  // explicitly). In the future, there should be a better interface\n  // between such packages and the build tool.\n  name: 'launch-screen',\n  summary: 'Default and customizable launch screen on mobile.',\n  version: '1.0.12'\n});\n\nCordova.depends({\n  'cordova-plugin-splashscreen': '3.2.1'\n});\n\nPackage.onUse(function(api) {\n  api.addFiles('mobile-launch-screen.js', 'web');\n  api.addFiles('default-behavior.js', 'web');\n  api.use(['blaze', 'templating'], 'web', { weak: true });\n\n  api.export('LaunchScreen');\n});\n"
  },
  {
    "path": "packages/less/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/less/.npm/plugin/compileLessBatch/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/less/.npm/plugin/compileLessBatch/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/less/.npm/plugin/compileLessBatch/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"less\": {\n      \"version\": \"2.5.0\",\n      \"resolved\": \"https://github.com/meteor/less.js/tarball/8130849eb3d7f0ecf0ca8d0af7c4207b0442e3f6\",\n      \"from\": \"https://github.com/meteor/less.js/tarball/8130849eb3d7f0ecf0ca8d0af7c4207b0442e3f6\",\n      \"dependencies\": {\n        \"errno\": {\n          \"version\": \"0.1.3\",\n          \"resolved\": \"https://registry.npmjs.org/errno/-/errno-0.1.3.tgz\",\n          \"from\": \"https://registry.npmjs.org/errno/-/errno-0.1.3.tgz\",\n          \"dependencies\": {\n            \"prr\": {\n              \"version\": \"0.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/prr/-/prr-0.0.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/prr/-/prr-0.0.0.tgz\"\n            }\n          }\n        },\n        \"graceful-fs\": {\n          \"version\": \"3.0.8\",\n          \"resolved\": \"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.8.tgz\",\n          \"from\": \"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.8.tgz\"\n        },\n        \"image-size\": {\n          \"version\": \"0.3.5\",\n          \"resolved\": \"https://registry.npmjs.org/image-size/-/image-size-0.3.5.tgz\",\n          \"from\": \"https://registry.npmjs.org/image-size/-/image-size-0.3.5.tgz\"\n        },\n        \"mime\": {\n          \"version\": \"1.3.4\",\n          \"resolved\": \"https://registry.npmjs.org/mime/-/mime-1.3.4.tgz\",\n          \"from\": \"https://registry.npmjs.org/mime/-/mime-1.3.4.tgz\"\n        },\n        \"mkdirp\": {\n          \"version\": \"0.5.1\",\n          \"resolved\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz\",\n          \"dependencies\": {\n            \"minimist\": {\n              \"version\": \"0.0.8\",\n              \"resolved\": \"https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz\",\n              \"from\": \"https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz\"\n            }\n          }\n        },\n        \"promise\": {\n          \"version\": \"6.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/promise/-/promise-6.1.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/promise/-/promise-6.1.0.tgz\",\n          \"dependencies\": {\n            \"asap\": {\n              \"version\": \"1.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/asap/-/asap-1.0.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/asap/-/asap-1.0.0.tgz\"\n            }\n          }\n        },\n        \"request\": {\n          \"version\": \"2.58.0\",\n          \"resolved\": \"https://registry.npmjs.org/request/-/request-2.58.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/request/-/request-2.58.0.tgz\",\n          \"dependencies\": {\n            \"aws-sign2\": {\n              \"version\": \"0.5.0\",\n              \"resolved\": \"https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz\"\n            },\n            \"bl\": {\n              \"version\": \"0.9.4\",\n              \"resolved\": \"https://registry.npmjs.org/bl/-/bl-0.9.4.tgz\",\n              \"from\": \"https://registry.npmjs.org/bl/-/bl-0.9.4.tgz\",\n              \"dependencies\": {\n                \"readable-stream\": {\n                  \"version\": \"1.0.33\",\n                  \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz\",\n                  \"from\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz\",\n                  \"dependencies\": {\n                    \"core-util-is\": {\n                      \"version\": \"1.0.1\",\n                      \"resolved\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz\",\n                      \"from\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz\"\n                    },\n                    \"inherits\": {\n                      \"version\": \"2.0.1\",\n                      \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\",\n                      \"from\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\"\n                    },\n                    \"isarray\": {\n                      \"version\": \"0.0.1\",\n                      \"resolved\": \"https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz\",\n                      \"from\": \"https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz\"\n                    },\n                    \"string_decoder\": {\n                      \"version\": \"0.10.31\",\n                      \"resolved\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\",\n                      \"from\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\"\n                    }\n                  }\n                }\n              }\n            },\n            \"caseless\": {\n              \"version\": \"0.10.0\",\n              \"resolved\": \"https://registry.npmjs.org/caseless/-/caseless-0.10.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/caseless/-/caseless-0.10.0.tgz\"\n            },\n            \"combined-stream\": {\n              \"version\": \"1.0.5\",\n              \"resolved\": \"https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz\",\n              \"from\": \"https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz\",\n              \"dependencies\": {\n                \"delayed-stream\": {\n                  \"version\": \"1.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz\"\n                }\n              }\n            },\n            \"extend\": {\n              \"version\": \"2.0.1\",\n              \"resolved\": \"https://registry.npmjs.org/extend/-/extend-2.0.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/extend/-/extend-2.0.1.tgz\"\n            },\n            \"forever-agent\": {\n              \"version\": \"0.6.1\",\n              \"resolved\": \"https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz\"\n            },\n            \"form-data\": {\n              \"version\": \"1.0.0-rc1\",\n              \"resolved\": \"https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc1.tgz\",\n              \"from\": \"https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc1.tgz\",\n              \"dependencies\": {\n                \"async\": {\n                  \"version\": \"1.3.0\",\n                  \"resolved\": \"https://registry.npmjs.org/async/-/async-1.3.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/async/-/async-1.3.0.tgz\"\n                },\n                \"mime-types\": {\n                  \"version\": \"2.1.3\",\n                  \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.3.tgz\",\n                  \"from\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.3.tgz\",\n                  \"dependencies\": {\n                    \"mime-db\": {\n                      \"version\": \"1.15.0\",\n                      \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.15.0.tgz\",\n                      \"from\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.15.0.tgz\"\n                    }\n                  }\n                }\n              }\n            },\n            \"har-validator\": {\n              \"version\": \"1.8.0\",\n              \"resolved\": \"https://registry.npmjs.org/har-validator/-/har-validator-1.8.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/har-validator/-/har-validator-1.8.0.tgz\",\n              \"dependencies\": {\n                \"bluebird\": {\n                  \"version\": \"2.9.33\",\n                  \"resolved\": \"https://registry.npmjs.org/bluebird/-/bluebird-2.9.33.tgz\",\n                  \"from\": \"https://registry.npmjs.org/bluebird/-/bluebird-2.9.33.tgz\"\n                },\n                \"chalk\": {\n                  \"version\": \"1.1.0\",\n                  \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-1.1.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/chalk/-/chalk-1.1.0.tgz\",\n                  \"dependencies\": {\n                    \"ansi-styles\": {\n                      \"version\": \"2.1.0\",\n                      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.1.0.tgz\",\n                      \"from\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.1.0.tgz\"\n                    },\n                    \"escape-string-regexp\": {\n                      \"version\": \"1.0.3\",\n                      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz\",\n                      \"from\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz\"\n                    },\n                    \"has-ansi\": {\n                      \"version\": \"2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz\",\n                      \"from\": \"https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz\",\n                      \"dependencies\": {\n                        \"ansi-regex\": {\n                          \"version\": \"2.0.0\",\n                          \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz\",\n                          \"from\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz\"\n                        }\n                      }\n                    },\n                    \"strip-ansi\": {\n                      \"version\": \"3.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.0.tgz\",\n                      \"from\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.0.tgz\",\n                      \"dependencies\": {\n                        \"ansi-regex\": {\n                          \"version\": \"2.0.0\",\n                          \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz\",\n                          \"from\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz\"\n                        }\n                      }\n                    },\n                    \"supports-color\": {\n                      \"version\": \"2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz\",\n                      \"from\": \"https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz\"\n                    }\n                  }\n                },\n                \"commander\": {\n                  \"version\": \"2.8.1\",\n                  \"resolved\": \"https://registry.npmjs.org/commander/-/commander-2.8.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/commander/-/commander-2.8.1.tgz\",\n                  \"dependencies\": {\n                    \"graceful-readlink\": {\n                      \"version\": \"1.0.1\",\n                      \"resolved\": \"https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz\",\n                      \"from\": \"https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz\"\n                    }\n                  }\n                },\n                \"is-my-json-valid\": {\n                  \"version\": \"2.12.0\",\n                  \"resolved\": \"https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.12.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.12.0.tgz\",\n                  \"dependencies\": {\n                    \"generate-function\": {\n                      \"version\": \"2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz\",\n                      \"from\": \"https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz\"\n                    },\n                    \"generate-object-property\": {\n                      \"version\": \"1.2.0\",\n                      \"resolved\": \"https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz\",\n                      \"from\": \"https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz\",\n                      \"dependencies\": {\n                        \"is-property\": {\n                          \"version\": \"1.0.2\",\n                          \"resolved\": \"https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz\",\n                          \"from\": \"https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz\"\n                        }\n                      }\n                    },\n                    \"jsonpointer\": {\n                      \"version\": \"1.1.0\",\n                      \"resolved\": \"https://registry.npmjs.org/jsonpointer/-/jsonpointer-1.1.0.tgz\",\n                      \"from\": \"https://registry.npmjs.org/jsonpointer/-/jsonpointer-1.1.0.tgz\"\n                    },\n                    \"xtend\": {\n                      \"version\": \"4.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz\",\n                      \"from\": \"https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz\"\n                    }\n                  }\n                }\n              }\n            },\n            \"hawk\": {\n              \"version\": \"2.3.1\",\n              \"resolved\": \"https://registry.npmjs.org/hawk/-/hawk-2.3.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/hawk/-/hawk-2.3.1.tgz\",\n              \"dependencies\": {\n                \"boom\": {\n                  \"version\": \"2.8.0\",\n                  \"resolved\": \"https://registry.npmjs.org/boom/-/boom-2.8.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/boom/-/boom-2.8.0.tgz\"\n                },\n                \"cryptiles\": {\n                  \"version\": \"2.0.4\",\n                  \"resolved\": \"https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.4.tgz\",\n                  \"from\": \"https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.4.tgz\"\n                },\n                \"hoek\": {\n                  \"version\": \"2.14.0\",\n                  \"resolved\": \"https://registry.npmjs.org/hoek/-/hoek-2.14.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/hoek/-/hoek-2.14.0.tgz\"\n                },\n                \"sntp\": {\n                  \"version\": \"1.0.9\",\n                  \"resolved\": \"https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz\",\n                  \"from\": \"https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz\"\n                }\n              }\n            },\n            \"http-signature\": {\n              \"version\": \"0.11.0\",\n              \"resolved\": \"https://registry.npmjs.org/http-signature/-/http-signature-0.11.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/http-signature/-/http-signature-0.11.0.tgz\",\n              \"dependencies\": {\n                \"asn1\": {\n                  \"version\": \"0.1.11\",\n                  \"resolved\": \"https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz\",\n                  \"from\": \"https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz\"\n                },\n                \"assert-plus\": {\n                  \"version\": \"0.1.5\",\n                  \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz\",\n                  \"from\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz\"\n                },\n                \"ctype\": {\n                  \"version\": \"0.5.3\",\n                  \"resolved\": \"https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz\",\n                  \"from\": \"https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz\"\n                }\n              }\n            },\n            \"isstream\": {\n              \"version\": \"0.1.2\",\n              \"resolved\": \"https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz\",\n              \"from\": \"https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz\"\n            },\n            \"json-stringify-safe\": {\n              \"version\": \"5.0.1\",\n              \"resolved\": \"https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz\"\n            },\n            \"mime-types\": {\n              \"version\": \"2.0.14\",\n              \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz\",\n              \"from\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz\",\n              \"dependencies\": {\n                \"mime-db\": {\n                  \"version\": \"1.12.0\",\n                  \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz\"\n                }\n              }\n            },\n            \"node-uuid\": {\n              \"version\": \"1.4.3\",\n              \"resolved\": \"https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz\",\n              \"from\": \"https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz\"\n            },\n            \"oauth-sign\": {\n              \"version\": \"0.8.0\",\n              \"resolved\": \"https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.0.tgz\"\n            },\n            \"qs\": {\n              \"version\": \"3.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/qs/-/qs-3.1.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/qs/-/qs-3.1.0.tgz\"\n            },\n            \"stringstream\": {\n              \"version\": \"0.0.4\",\n              \"resolved\": \"https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz\",\n              \"from\": \"https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz\"\n            },\n            \"tough-cookie\": {\n              \"version\": \"2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.0.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.0.0.tgz\"\n            },\n            \"tunnel-agent\": {\n              \"version\": \"0.4.1\",\n              \"resolved\": \"https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.1.tgz\"\n            }\n          }\n        },\n        \"source-map\": {\n          \"version\": \"0.4.4\",\n          \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz\",\n          \"from\": \"https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz\",\n          \"dependencies\": {\n            \"amdefine\": {\n              \"version\": \"1.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz\"\n            }\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/less/README.md",
    "content": "# Less\n\nThe Less package provides a compiler build plugin for the Meteor build tool. It\nhandles the compilation of `*.less` files to CSS.\n\n## Usage\n\nIf you want to use it in your app, just run:\n\n```bash\nmeteor add less\n```\n\nIf you want to use it for your package, add it in your package control file's\n`onUse` block:\n\n```javascript\nPackage.onUse(function (api) {\n  ...\n  api.use('less');\n  ...\n});\n```\n\n## File types\n\nThere are two different types of files recognized by this package:\n\n- Less sources (all `*.less` files that are not imports)\n- Less imports:\n  * files with the `import.less` extension: `*.import.less`\n  * files in an `imports` directory: `**/imports/**/*.less`\n  * marked as `isImport: true` in the package's `package.js` file:\n    `api.addFiles('x.less', 'client', {isImport: true})`\n\nThe source files are compiled automatically. The imports are not loaded by\nthemselves; you need to import them from one of the source files to use them.\n\nThe imports are intended to keep shared mixins and variables for your project,\nor to allow your package to provide several components which your package's\nusers can opt into one by one.\n\nEach compiled source file produces a separate CSS file.  (The\n`standard-minifier-css` package merges them into one file afterwards.)\n\n## Importing\n\nYou can use the regular `@import` syntax to import any Less files: sources or\nimports.\n\nBesides the usual way of importing files based on the relative path in the same\npackage (or app), you can also import files from other packages or apps with the\nfollowing syntax.\n\nImporting styles from a different package:\n\n```less\n@import \"{my-package:pretty-buttons}/buttons/styles.import.less\"\n\n.my-button {\n  // use the styles imported from a package\n  .pretty-button;\n}\n```\n\nImporting styles from the target app:\n\n```less\n@import \"{}/client/styles/imports/colors.less\"\n\n.my-nav {\n  // use a color from the app style pallete\n  background-color: @primary-branding-color;\n}\n```\n\nImporting styles relative to the current package/app's root:\n\n```less\n@import \"/path/to/style.import.less\";\n```\n"
  },
  {
    "path": "packages/less/less_tests.js",
    "content": "Tinytest.add(\"less - imports\", function (test) {\n  var div = document.createElement('div');\n  document.body.appendChild(div);\n\n  try {\n    var t = function (className, style) {\n      div.className = className;\n      test.equal(getStyleProperty(div, 'border-style'), style, className);\n    };\n    t('el1', 'dotted');\n    t('el2', 'dashed');\n    t('el3', 'solid');\n    t('el4', 'double');\n    t('el5', 'groove');\n    t('el6', 'inset');\n\n    // This is assigned to 'ridge' in not-included.less, which is ... not\n    // included. So that's why it should be 'none'.  (This tests that we don't\n    // process non-main files.)\n    t('el0', 'none');\n  } finally {\n    document.body.removeChild(div);\n  }\n});\n"
  },
  {
    "path": "packages/less/package.js",
    "content": "Package.describe({\n  name: 'less',\n  version: '2.6.3_1',\n  summary: 'Leaner CSS language',\n  documentation: 'README.md'\n});\n\nPackage.registerBuildPlugin({\n  name: \"compileLessBatch\",\n  use: ['caching-compiler', 'ecmascript', 'underscore'],\n  sources: [\n    'plugin/compile-less.js'\n  ],\n  npmDependencies: {\n    // Fork of 2.5.0, deleted large unused files in dist directory.\n    \"less\": \"https://github.com/meteor/less.js/tarball/8130849eb3d7f0ecf0ca8d0af7c4207b0442e3f6\"\n  }\n});\n\nPackage.onUse(function (api) {\n  api.use('isobuild:compiler-plugin@1.0.0');\n});\n\nPackage.onTest(function(api) {\n  api.use('less');\n  api.use(['tinytest', 'test-helpers']);\n  api.addFiles(['tests/top.import.less',\n                'tests/top3.import.less',\n                'tests/dir/in-dir.import.less',\n                'tests/dir/in-dir2.import.less',\n                'tests/dir/root.less',\n                'tests/dir/subdir/in-subdir.import.less']);\n\n  api.addFiles('tests/imports/not-included.less', 'client', {\n    lazy: true\n  });\n\n  api.addFiles('tests/top2.less', 'client', {isImport: true});\n\n  api.addFiles('less_tests.js', 'client');\n});\n"
  },
  {
    "path": "packages/less/plugin/compile-less.js",
    "content": "const path = Plugin.path;\nconst less = Npm.require('less');\nconst Future = Npm.require('fibers/future');\n\nPlugin.registerCompiler({\n  // *.lessimport has been deprecated since 0.7.1, but it still works. We\n  // *recommend *.import.less or the imports subdirectory instead.\n  extensions: ['less', 'lessimport'],\n  archMatching: 'web'\n}, () => new LessCompiler());\n\n// CompileResult is {css, sourceMap}.\nclass LessCompiler extends MultiFileCachingCompiler {\n  constructor() {\n    super({\n      compilerName: 'less',\n      defaultCacheSize: 1024*1024*10,\n    });\n  }\n\n  getCacheKey(inputFile) {\n    return inputFile.getSourceHash();\n  }\n\n  compileResultSize(compileResult) {\n    return compileResult.css.length +\n      this.sourceMapSize(compileResult.sourceMap);\n  }\n\n  // The heuristic is that a file is an import (ie, is not itself\n  // processed as a root) if it matches *.import.less or *.lessimport.\n  // This can be overridden in either direction via an explicit `isImport`\n  // file option in api.addFiles.\n  isRoot(inputFile) {\n    const fileOptions = inputFile.getFileOptions();\n    if (fileOptions.hasOwnProperty('isImport')) {\n      return !fileOptions.isImport;\n    }\n\n    const pathInPackage = inputFile.getPathInPackage();\n    return !(/\\.import\\.less$/.test(pathInPackage) ||\n             /\\.lessimport$/.test(pathInPackage));\n  }\n\n  compileOneFile(inputFile, allFiles) {\n    const importPlugin = new MeteorImportLessPlugin(allFiles);\n\n    const f = new Future;\n    let output;\n    try {\n      less.render(inputFile.getContentsAsBuffer().toString('utf8'), {\n        filename: this.getAbsoluteImportPath(inputFile),\n        plugins: [importPlugin],\n        // Generate a source map, and include the source files in the\n        // sourcesContent field.  (Note that source files which don't themselves\n        // produce text (eg, are entirely variable definitions) won't end up in\n        // the source map!)\n        sourceMap: { outputSourceFiles: true }\n      }, f.resolver());\n      output = f.wait();\n    } catch (e) {\n      inputFile.error({\n        message: e.message,\n        sourcePath: decodeFilePath(e.filename),\n        line: e.line,\n        column: e.column\n      });\n      return null;\n    }\n\n    if (output.map) {\n      const map = JSON.parse(output.map);\n      map.sources = map.sources.map(decodeFilePath);\n      output.map = map;\n    }\n\n    const compileResult = {css: output.css, sourceMap: output.map};\n    const referencedImportPaths = [];\n    output.imports.forEach((path) => {\n      // Some files that show up in output.imports are not actually files; for\n      // example @import url(\"...\");\n      if (allFiles.has(path)) {\n        referencedImportPaths.push(path);\n      }\n    });\n\n    return {compileResult, referencedImportPaths};\n  }\n\n  addCompileResult(inputFile, compileResult) {\n    inputFile.addStylesheet({\n      data: compileResult.css,\n      path: inputFile.getPathInPackage() + '.css',\n      sourceMap: compileResult.sourceMap\n    });\n  }\n}\n\nclass MeteorImportLessPlugin {\n  constructor(allFiles) {\n    this.allFiles = allFiles;\n    this.minVersion = [2, 5, 0];\n  }\n\n  install(less, pluginManager) {\n    pluginManager.addFileManager(\n      new MeteorImportLessFileManager(this.allFiles));\n  }\n}\n\nclass MeteorImportLessFileManager extends less.AbstractFileManager {\n  constructor(allFiles) {\n    super();\n    this.allFiles = allFiles;\n  }\n\n  // We want to be the only active FileManager, so claim to support everything.\n  supports(filename) {\n    // We shouldn't process files that start with `//` or a protocol because\n    // those are not relative to the app at all; they are probably native\n    // CSS imports\n    if (! filename.match(/^(https?:)?\\/\\//)) {\n      return true;\n    }\n\n    return false;\n  }\n\n  loadFile(filename, currentDirectory, options, environment, cb) {\n    const packageMatch = currentDirectory.match(/^(\\{[^}]*\\})/);\n    if (! packageMatch) {\n      // shouldn't happen.  all filenames less ever sees should involve this {}\n      // thing!\n      cb(new Error('file without Meteor context? ' + currentDirectory));\n      return;\n    }\n    const currentPackagePrefix = packageMatch[1];\n\n    let resolvedFilename;\n    if (filename[0] === '/') {\n      // Map `/foo/bar.less` onto `{thispackage}/foo/bar.less`\n      resolvedFilename = currentPackagePrefix + filename;\n    } else if (filename[0] === '{') {\n      resolvedFilename = filename;\n    } else {\n      resolvedFilename = path.join(currentDirectory, filename);\n    }\n\n    if (!this.allFiles.has(resolvedFilename)) {\n      cb({type: 'File', message: 'Unknown import: ' + filename});\n      return;\n    }\n    cb(null, {\n      contents: this.allFiles.get(resolvedFilename)\n        .getContentsAsBuffer().toString('utf8'),\n      filename: resolvedFilename\n    });\n  }\n}\n\nfunction decodeFilePath (filePath) {\n  const match = filePath.match(/^{(.*)}\\/(.*)$/);\n  if (! match)\n    throw new Error('Failed to decode Less path: ' + filePath);\n\n  if (match[1] === '') {\n    // app\n    return match[2];\n  }\n\n  return 'packages/' + match[1] + '/' + match[2];\n}\n"
  },
  {
    "path": "packages/less/tests/dir/in-dir.import.less",
    "content": "@el3-style: solid;\n"
  },
  {
    "path": "packages/less/tests/dir/in-dir2.import.less",
    "content": "@el4-style: double;\n"
  },
  {
    "path": "packages/less/tests/dir/root.less",
    "content": "@import \"/tests/top.import.less\";\n@import \"{local-test:less}/tests/top2.less\";\n@import \"in-dir.import.less\";\n@import \"./in-dir2.import.less\";\n@import \"subdir/in-subdir.import.less\";\n\n\n.el1 { border-style: @el1-style; }\n.el2 { border-style: @el2-style; }\n.el3 { border-style: @el3-style; }\n.el4 { border-style: @el4-style; }\n.el5 { border-style: @el5-style; }\n.el6 { border-style: @el6-style; }\n"
  },
  {
    "path": "packages/less/tests/dir/subdir/in-subdir.import.less",
    "content": "@el5-style: groove;\n"
  },
  {
    "path": "packages/less/tests/imports/not-included.less",
    "content": "/* This less file isn't included by any main file */\n.el0 { border-style: ridge; }\n"
  },
  {
    "path": "packages/less/tests/top.import.less",
    "content": "@el1-style: dotted;\n\n/* Test that package-relative imports work from within a\n * package-relative-imported file */\n@import \"/tests/top3.import.less\";\n\n// Make sure regular CSS import doesn't make the compiler explode - this was\n// a regression from 1.1.0.3 caught in QA\n@import url(\"http://hello.myfonts.net/count/2c4b9d\");\n"
  },
  {
    "path": "packages/less/tests/top2.less",
    "content": "@el2-style: dashed;\n"
  },
  {
    "path": "packages/less/tests/top3.import.less",
    "content": "@el6-style: inset;\n"
  },
  {
    "path": "packages/livedata/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/livedata/DDP.md",
    "content": "DDP Specification\n=================\n\nThe Meteor `livedata` package has been renamed to `ddp`, so this document now lives at [https://github.com/meteor/meteor/blob/devel/packages/ddp/DDP.md](https://github.com/meteor/meteor/blob/devel/packages/ddp/DDP.md)."
  },
  {
    "path": "packages/livedata/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/livedata/package.js",
    "content": "Package.describe({\n  summary: \"Moved to the 'ddp' package\",\n  version: '1.0.18'\n});\n\nPackage.onUse(function (api) {\n  api.use(\"ddp\");\n  api.imply(\"ddp\");\n\n  // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.\n  //\n  // (in particular, packages that have a weak dependency on this\n  // package, since then exported symbols live on the\n  // `Package.livedata` object)\n  api.export('DDP');\n  api.export('DDPServer', 'server');\n  api.export('LivedataTest', {testOnly: true});\n});\n"
  },
  {
    "path": "packages/localstorage/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/localstorage/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/localstorage/localstorage.js",
    "content": "// Meteor._localStorage is not an ideal name, but we can change it later.\n\n// Let's test to make sure that localStorage actually works. For example, in\n// Safari with private browsing on, window.localStorage exists but actually\n// trying to use it throws.\n// Accessing window.localStorage can also immediately throw an error in IE (#1291).\n\nvar key = '_localstorage_test_' + Random.id();\nvar retrieved;\ntry {\n  if (window.localStorage) {\n    window.localStorage.setItem(key, key);\n    retrieved = window.localStorage.getItem(key);\n    window.localStorage.removeItem(key);\n  }\n} catch (e) {\n  // ... ignore\n}\nif (key === retrieved) {\n  Meteor._localStorage = {\n    getItem: function (key) {\n      return window.localStorage.getItem(key);\n    },\n    setItem: function (key, value) {\n      window.localStorage.setItem(key, value);\n    },\n    removeItem: function (key) {\n      window.localStorage.removeItem(key);\n    }\n  };\n}\n\nif (!Meteor._localStorage) {\n  Meteor._debug(\n    \"You are running a browser with no localStorage or userData \"\n      + \"support. Logging in from one tab will not cause another \"\n      + \"tab to be logged in.\");\n\n  Meteor._localStorage = {\n    _data: {},\n\n    setItem: function (key, val) {\n      this._data[key] = val;\n    },\n    removeItem: function (key) {\n      delete this._data[key];\n    },\n    getItem: function (key) {\n      var value = this._data[key];\n      if (value === undefined)\n        return null;\n      else\n        return value;\n    }\n  };\n}\n"
  },
  {
    "path": "packages/localstorage/localstorage_tests.js",
    "content": "Tinytest.add(\"localStorage\", function (test) {\n  // Doesn't actually test preservation across reloads since that is hard.\n  // userData should do that for us so it's unlikely this wouldn't work.\n  Meteor._localStorage.setItem(\"key\", \"value\");\n  test.equal(Meteor._localStorage.getItem(\"key\"), \"value\");\n  Meteor._localStorage.removeItem(\"key\");\n  test.equal(Meteor._localStorage.getItem(\"key\"), null);\n});\n"
  },
  {
    "path": "packages/localstorage/package.js",
    "content": "Package.describe({\n  summary: \"Simulates local storage on IE 6,7 using userData\",\n  version: \"1.0.11\"\n});\n\nPackage.onUse(function (api) {\n  api.use('random', 'client');\n\n  api.addFiles('localstorage.js', 'client');\n});\n\nPackage.onTest(function (api) {\n  api.use('localstorage', 'client');\n  api.use('tinytest');\n\n  api.addFiles('localstorage_tests.js', 'client');\n});\n"
  },
  {
    "path": "packages/logging/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/logging/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/logging/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/logging/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"cli-color\": {\n      \"version\": \"0.2.3\",\n      \"resolved\": \"https://registry.npmjs.org/cli-color/-/cli-color-0.2.3.tgz\",\n      \"from\": \"https://registry.npmjs.org/cli-color/-/cli-color-0.2.3.tgz\",\n      \"dependencies\": {\n        \"es5-ext\": {\n          \"version\": \"0.9.2\",\n          \"resolved\": \"https://registry.npmjs.org/es5-ext/-/es5-ext-0.9.2.tgz\",\n          \"from\": \"https://registry.npmjs.org/es5-ext/-/es5-ext-0.9.2.tgz\"\n        },\n        \"memoizee\": {\n          \"version\": \"0.2.5\",\n          \"resolved\": \"https://registry.npmjs.org/memoizee/-/memoizee-0.2.5.tgz\",\n          \"from\": \"https://registry.npmjs.org/memoizee/-/memoizee-0.2.5.tgz\",\n          \"dependencies\": {\n            \"event-emitter\": {\n              \"version\": \"0.2.2\",\n              \"resolved\": \"https://registry.npmjs.org/event-emitter/-/event-emitter-0.2.2.tgz\",\n              \"from\": \"https://registry.npmjs.org/event-emitter/-/event-emitter-0.2.2.tgz\"\n            },\n            \"next-tick\": {\n              \"version\": \"0.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/next-tick/-/next-tick-0.1.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/next-tick/-/next-tick-0.1.0.tgz\"\n            }\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/logging/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/logging/logging.js",
    "content": "Log = function () {\n  return Log.info.apply(this, arguments);\n};\n\n/// FOR TESTING\nvar intercept = 0;\nvar interceptedLines = [];\nvar suppress = 0;\n\n// Intercept the next 'count' calls to a Log function. The actual\n// lines printed to the console can be cleared and read by calling\n// Log._intercepted().\nLog._intercept = function (count) {\n  intercept += count;\n};\n\n// Suppress the next 'count' calls to a Log function. Use this to stop\n// tests from spamming the console, especially with red errors that\n// might look like a failing test.\nLog._suppress = function (count) {\n  suppress += count;\n};\n\n// Returns intercepted lines and resets the intercept counter.\nLog._intercepted = function () {\n  var lines = interceptedLines;\n  interceptedLines = [];\n  intercept = 0;\n  return lines;\n};\n\n// Either 'json' or 'colored-text'.\n//\n// When this is set to 'json', print JSON documents that are parsed by another\n// process ('satellite' or 'meteor run'). This other process should call\n// 'Log.format' for nice output.\n//\n// When this is set to 'colored-text', call 'Log.format' before printing.\n// This should be used for logging from within satellite, since there is no\n// other process that will be reading its standard output.\nLog.outputFormat = 'json';\n\nvar LEVEL_COLORS = {\n  debug: 'green',\n  // leave info as the default color\n  warn: 'magenta',\n  error: 'red'\n};\n\nvar META_COLOR = 'blue';\n\n// XXX package\nvar RESTRICTED_KEYS = ['time', 'timeInexact', 'level', 'file', 'line',\n                        'program', 'originApp', 'satellite', 'stderr'];\n\nvar FORMATTED_KEYS = RESTRICTED_KEYS.concat(['app', 'message']);\n\nvar logInBrowser = function (obj) {\n  var str = Log.format(obj);\n\n  // XXX Some levels should be probably be sent to the server\n  var level = obj.level;\n\n  if ((typeof console !== 'undefined') && console[level]) {\n    console[level](str);\n  } else {\n    // XXX Uses of Meteor._debug should probably be replaced by Log.debug or\n    //     Log.info, and we should have another name for \"do your best to\n    //     call call console.log\".\n    Meteor._debug(str);\n  }\n};\n\n// @returns {Object: { line: Number, file: String }}\nLog._getCallerDetails = function () {\n  var getStack = function () {\n    // We do NOT use Error.prepareStackTrace here (a V8 extension that gets us a\n    // pre-parsed stack) since it's impossible to compose it with the use of\n    // Error.prepareStackTrace used on the server for source maps.\n    var err = new Error;\n    var stack = err.stack;\n    return stack;\n  };\n\n  var stack = getStack();\n\n  if (!stack) return {};\n\n  var lines = stack.split('\\n');\n\n  // looking for the first line outside the logging package (or an\n  // eval if we find that first)\n  var line;\n  for (var i = 1; i < lines.length; ++i) {\n    line = lines[i];\n    if (line.match(/^\\s*at eval \\(eval/)) {\n      return {file: \"eval\"};\n    }\n\n    if (!line.match(/packages\\/(?:local-test[:_])?logging(?:\\/|\\.js)/))\n      break;\n  }\n\n  var details = {};\n\n  // The format for FF is 'functionName@filePath:lineNumber'\n  // The format for V8 is 'functionName (packages/logging/logging.js:81)' or\n  //                      'packages/logging/logging.js:81'\n  var match = /(?:[@(]| at )([^(]+?):([0-9:]+)(?:\\)|$)/.exec(line);\n  if (!match)\n    return details;\n  // in case the matched block here is line:column\n  details.line = match[2].split(':')[0];\n\n  // Possible format: https://foo.bar.com/scripts/file.js?random=foobar\n  // XXX: if you can write the following in better way, please do it\n  // XXX: what about evals?\n  details.file = match[1].split('/').slice(-1)[0].split('?')[0];\n\n  return details;\n};\n\n_.each(['debug', 'info', 'warn', 'error'], function (level) {\n  // @param arg {String|Object}\n  Log[level] = function (arg) {\n    if (suppress) {\n      suppress--;\n      return;\n    }\n\n    var intercepted = false;\n    if (intercept) {\n      intercept--;\n      intercepted = true;\n    }\n\n    var obj = (_.isObject(arg) && !_.isRegExp(arg) && !_.isDate(arg) ) ?\n              arg : {message: new String(arg).toString() };\n\n    _.each(RESTRICTED_KEYS, function (key) {\n      if (obj[key])\n        throw new Error(\"Can't set '\" + key + \"' in log message\");\n    });\n\n    if (_.has(obj, 'message') && !_.isString(obj.message))\n      throw new Error(\"The 'message' field in log objects must be a string\");\n    if (!obj.omitCallerDetails)\n      obj = _.extend(Log._getCallerDetails(), obj);\n    obj.time = new Date();\n    obj.level = level;\n\n    // XXX allow you to enable 'debug', probably per-package\n    if (level === 'debug')\n      return;\n\n    if (intercepted) {\n      interceptedLines.push(EJSON.stringify(obj));\n    } else if (Meteor.isServer) {\n      if (Log.outputFormat === 'colored-text') {\n        console.log(Log.format(obj, {color: true}));\n      } else if (Log.outputFormat === 'json') {\n        console.log(EJSON.stringify(obj));\n      } else {\n        throw new Error(\"Unknown logging output format: \" + Log.outputFormat);\n      }\n    } else {\n      logInBrowser(obj);\n    }\n  };\n});\n\n// tries to parse line as EJSON. returns object if parse is successful, or null if not\nLog.parse = function (line) {\n  var obj = null;\n  if (line && line.charAt(0) === '{') { // might be json generated from calling 'Log'\n    try { obj = EJSON.parse(line); } catch (e) {}\n  }\n\n  // XXX should probably check fields other than 'time'\n  if (obj && obj.time && (obj.time instanceof Date))\n    return obj;\n  else\n    return null;\n};\n\n// formats a log object into colored human and machine-readable text\nLog.format = function (obj, options) {\n  obj = EJSON.clone(obj); // don't mutate the argument\n  options = options || {};\n\n  var time = obj.time;\n  if (!(time instanceof Date))\n    throw new Error(\"'time' must be a Date object\");\n  var timeInexact = obj.timeInexact;\n\n  // store fields that are in FORMATTED_KEYS since we strip them\n  var level = obj.level || 'info';\n  var file = obj.file;\n  var lineNumber = obj.line;\n  var appName = obj.app || '';\n  var originApp = obj.originApp;\n  var message = obj.message || '';\n  var program = obj.program || '';\n  var satellite = obj.satellite;\n  var stderr = obj.stderr || '';\n\n  _.each(FORMATTED_KEYS, function(key) {\n    delete obj[key];\n  });\n\n  if (!_.isEmpty(obj)) {\n    if (message) message += \" \";\n    message += EJSON.stringify(obj);\n  }\n\n  var pad2 = function(n) { return n < 10 ? '0' + n : n.toString(); };\n  var pad3 = function(n) { return n < 100 ? '0' + pad2(n) : n.toString(); };\n\n  var dateStamp = time.getFullYear().toString() +\n    pad2(time.getMonth() + 1 /*0-based*/) +\n    pad2(time.getDate());\n  var timeStamp = pad2(time.getHours()) +\n        ':' +\n        pad2(time.getMinutes()) +\n        ':' +\n        pad2(time.getSeconds()) +\n        '.' +\n        pad3(time.getMilliseconds());\n\n  // eg in San Francisco in June this will be '(-7)'\n  var utcOffsetStr = '(' + (-(new Date().getTimezoneOffset() / 60)) + ')';\n\n  var appInfo = '';\n  if (appName) appInfo += appName;\n  if (originApp && originApp !== appName) appInfo += ' via ' + originApp;\n  if (appInfo) appInfo = '[' + appInfo + '] ';\n\n  var sourceInfoParts = [];\n  if (program) sourceInfoParts.push(program);\n  if (file) sourceInfoParts.push(file);\n  if (lineNumber) sourceInfoParts.push(lineNumber);\n  var sourceInfo = _.isEmpty(sourceInfoParts) ?\n    '' : '(' + sourceInfoParts.join(':') + ') ';\n\n  if (satellite)\n    sourceInfo += ['[', satellite, ']'].join('');\n\n  var stderrIndicator = stderr ? '(STDERR) ' : '';\n\n  var metaPrefix = [\n    level.charAt(0).toUpperCase(),\n    dateStamp,\n    '-',\n    timeStamp,\n    utcOffsetStr,\n    timeInexact ? '? ' : ' ',\n    appInfo,\n    sourceInfo,\n    stderrIndicator].join('');\n\n  var prettify = function (line, color) {\n    return (options.color && Meteor.isServer && color) ?\n      require('cli-color')[color](line) : line;\n  };\n\n  return prettify(metaPrefix, options.metaColor || META_COLOR) +\n    prettify(message, LEVEL_COLORS[level]);\n};\n\n// Turn a line of text into a loggable object.\n// @param line {String}\n// @param override {Object}\nLog.objFromText = function (line, override) {\n  var obj = {message: line, level: \"info\", time: new Date(), timeInexact: true};\n  return _.extend(obj, override);\n};\n"
  },
  {
    "path": "packages/logging/logging_cordova.js",
    "content": "// Log all uncaught errors so they can be printed to the developer.\n// But since Android's adb catlog already prints the uncaught exceptions, we\n// can disable it for Android.\nif (! /Android/i.test(navigator.userAgent)) {\n  window.onerror = function (msg, url, line) {\n    // Cut off the url prefix, the meaningful part always starts at 'www/' in\n    // Cordova apps.\n    url = url.replace(/^.*?\\/www\\//, '');\n    console.log('Uncaught Error: ' + msg + ':' + line + ':' + url);\n  };\n}\n\n"
  },
  {
    "path": "packages/logging/logging_test.js",
    "content": "Tinytest.add(\"logging - _getCallerDetails\", function (test) {\n  var details = Log._getCallerDetails();\n  // Ignore this test for Opera, IE, Safari since this test would work only\n  // in Chrome and Firefox, other browsers don't give us an ability to get\n  // stacktrace.\n  if ((new Error).stack) {\n    if (Meteor.isServer) {\n      test.equal(details.file, 'tinytest.js');\n    } else {\n      // Note that we want this to work in --production too, so we need to allow\n      // for the minified filename.\n      test.matches(details.file,\n                   /^(?:tinytest\\.js|[a-f0-9]{40}\\.js)$/);\n    }\n\n    // evaled statements shouldn't crash\n    var code = \"Log._getCallerDetails().file\";\n    // Note that we want this to work in --production too, so we need to allow\n    // for the minified filename\n    test.matches(eval(code),\n                 /^(?:eval|local-test_logging\\.js|[a-f0-9]{40}\\.js)/);\n  }\n});\n\nTinytest.add(\"logging - log\", function (test) {\n  var logBothMessageAndObject = function (log, level) {\n    Log._intercept(3);\n\n    // Tests for correctness\n    log(\"message\");\n    log({property1: \"foo\", property2: \"bar\"});\n    log({message: \"mixed\", property1: \"foo\", property2: \"bar\"});\n\n    var intercepted = Log._intercepted();\n    test.equal(intercepted.length, 3);\n\n    var obj1 = EJSON.parse(intercepted[0]);\n    test.equal(obj1.message, \"message\");\n    test.equal(obj1.level, level);\n    test.instanceOf(obj1.time, Date);\n\n    var obj2 = EJSON.parse(intercepted[1]);\n    test.isFalse(obj2.message);\n    test.equal(obj2.property1, \"foo\");\n    test.equal(obj2.property2, \"bar\");\n    test.equal(obj2.level, level);\n    test.instanceOf(obj2.time, Date);\n\n    var obj3 = EJSON.parse(intercepted[2]);\n    test.equal(obj3.message, \"mixed\");\n    test.equal(obj3.property1, \"foo\");\n    test.equal(obj3.property2, \"bar\");\n    test.equal(obj3.level, level);\n    test.instanceOf(obj3.time, Date);\n\n    // Test logging falsy values, as well as single digits\n    // and some other non-stringy things\n    // In a format of testcase, expected result, name of the test.\n    var testcases = [\n          [1, \"1\", \"single digit\"],\n          [0, \"0\", \"falsy - 0\"],\n          [null, \"null\", \"falsy - null\"],\n          [undefined, \"undefined\", \"falsy - undefined\"],\n          [new Date(\"2013-06-13T01:15:16.000Z\"), new Date(\"2013-06-13T01:15:16.000Z\"), \"date\"],\n          [/[^regexp]{0,1}/g, \"/[^regexp]{0,1}/g\", \"regexp\"],\n          [true, \"true\", \"boolean - true\"],\n          [false, \"false\", \"boolean - false\"],\n          [-Infinity, \"-Infinity\", \"number - -Infinity\"]];\n\n    Log._intercept(testcases.length);\n    _.each(testcases, function (testcase) {\n      log(testcase[0]);\n    });\n\n    intercepted = Log._intercepted();\n\n    test.equal(intercepted.length, testcases.length);\n\n    _.each(testcases, function (testcase, index) {\n      var expected = testcase[1];\n      var testName = testcase[2];\n      var recieved = intercepted[index];\n      var obj = EJSON.parse(recieved);\n\n      // IE8 and old Safari don't support this date format. Skip it.\n      if (expected && expected.toString &&\n          (expected.toString() === \"NaN\" ||\n           expected.toString() === \"Invalid Date\"))\n        return;\n\n      if (_.isDate(testcase[0]))\n        obj.message = new Date(obj.message);\n      test.equal(obj.message, expected, 'Logging ' + testName);\n    });\n\n    // Tests for correct exceptions\n    Log._intercept(6);\n\n    test.throws(function () {\n      log({time: 'not the right time'});\n    });\n    test.throws(function () {\n      log({level: 'not the right level'});\n    });\n    _.each(['file', 'line', 'program', 'originApp', 'satellite'],\n      function (restrictedKey) {\n      test.throws(function () {\n        var obj = {};\n        obj[restrictedKey] = 'usage of restricted key';\n        log(obj);\n      });\n    });\n\n    // Can't pass numbers, objects, arrays, regexps or functions as message\n    var throwingTestcases = [1, NaN, {foo:\"bar\"}, [\"a\", \"r\", \"r\"], null,\n                             undefined, new Date, function () { return 42; },\n                             /[regexp]/ ];\n    Log._intercept(throwingTestcases.length);\n    _.each(throwingTestcases, function (testcase) {\n      test.throws(function () {\n        log({ message: testcase });\n      });\n    });\n\n    // Since all tests above should throw, nothing should be printed.\n    // This call will set the logging interception to the clean state as well.\n    test.equal(Log._intercepted().length, 0);\n  };\n\n  logBothMessageAndObject(Log, 'info');\n  _.each(['info', 'warn', 'error'], function (level) {\n    logBothMessageAndObject(Log[level], level);\n  });\n});\n\nTinytest.add(\"logging - parse\", function (test) {\n  test.equal(Log.parse(\"message\"), null);\n  test.equal(Log.parse('{\"foo\": \"bar\"}'), null);\n  var time = new Date;\n  test.equal(Log.parse('{\"foo\": \"bar\", \"time\": ' + EJSON.stringify(time) + '}'),\n                        { foo: \"bar\", time: time });\n  test.equal(Log.parse('{\"foo\": not json \"bar\"}'), null);\n  test.equal(Log.parse('{\"time\": \"not a date object\"}'), null);\n});\n\nTinytest.add(\"logging - format\", function (test) {\n  var time = new Date(2012, 9 - 1/*0-based*/, 8, 7, 6, 5, 4);\n  var utcOffsetStr = '(' + (-(new Date().getTimezoneOffset() / 60)) + ')';\n\n  _.each(['debug', 'info', 'warn', 'error'], function (level) {\n    test.equal(\n      Log.format({message: \"message\", time: time, level: level}),\n      level.charAt(0).toUpperCase() + \"20120908-07:06:05.004\" + utcOffsetStr + \" message\");\n\n    test.equal(\n      Log.format({message: \"message\", time: time, timeInexact: true, level: level}),\n      level.charAt(0).toUpperCase() + \"20120908-07:06:05.004\" + utcOffsetStr + \"? message\");\n\n    test.equal(\n      Log.format({foo1: \"bar1\", foo2: \"bar2\", time: time, level: level}),\n      level.charAt(0).toUpperCase() + '20120908-07:06:05.004' + utcOffsetStr + ' {\"foo1\":\"bar1\",\"foo2\":\"bar2\"}');\n\n    test.equal(\n      Log.format({message: \"message\", foo: \"bar\", time: time, level: level}),\n      level.charAt(0).toUpperCase() + '20120908-07:06:05.004' + utcOffsetStr + ' message {\"foo\":\"bar\"}');\n\n    // Has everything except stderr field\n    test.equal(\n      Log.format({message: \"message\", foo: \"bar\", time: time, level: level, file: \"app.js\", line:42, app: \"myApp\", originApp: \"proxy\", program: \"server\"}),\n      level.charAt(0).toUpperCase() + '20120908-07:06:05.004' + utcOffsetStr + ' [myApp via proxy] (server:app.js:42) message {\\\"foo\\\":\\\"bar\\\"}');\n\n    // stderr\n    test.equal(\n      Log.format({message: \"message from stderr\", time: time, level: level, stderr: true}),\n      level.charAt(0).toUpperCase() + '20120908-07:06:05.004' + utcOffsetStr + ' (STDERR) message from stderr');\n\n    // app/originApp\n    test.equal(\n      Log.format({message: \"message\", time: time, level: level, app: \"app\", originApp: \"app\"}),\n      level.charAt(0).toUpperCase() + '20120908-07:06:05.004' + utcOffsetStr + ' [app] message');\n    test.equal(\n      Log.format({message: \"message\", time: time, level: level, app: \"app\", originApp: \"proxy\"}),\n      level.charAt(0).toUpperCase() + '20120908-07:06:05.004' + utcOffsetStr + ' [app via proxy] message');\n\n    // source info\n    test.equal(\n      Log.format({message: \"message\", time: time, level: level, file: \"app.js\", line: 42, program: \"server\"}),\n      level.charAt(0).toUpperCase() + '20120908-07:06:05.004' + utcOffsetStr + ' (server:app.js:42) message');\n    test.equal(\n      Log.format({message: \"message\", time: time, level: level, file: \"app.js\", line: 42}),\n      level.charAt(0).toUpperCase() + '20120908-07:06:05.004' + utcOffsetStr + ' (app.js:42) message');\n  });\n});\n"
  },
  {
    "path": "packages/logging/package.js",
    "content": "Package.describe({\n  summary: \"Logging facility.\",\n  version: '1.0.13_1'\n});\n\nNpm.depends({\n  \"cli-color\": \"0.2.3\"\n});\n\nNpm.strip({\n  \"es5-ext\": [\"test/\"]\n});\n\nCordova.depends({\n  'cordova-plugin-console': '1.0.2'\n});\n\nPackage.onUse(function (api) {\n  api.export('Log');\n  api.use(['underscore', 'ejson', 'modules']);\n  api.addFiles('logging.js');\n  api.addFiles('logging_cordova.js', 'web.cordova');\n});\n\nPackage.onTest(function (api) {\n  api.use(['tinytest', 'underscore', 'ejson']);\n  api.use('logging', ['client', 'server']);\n  api.addFiles('logging_test.js', ['server', 'client']);\n});\n"
  },
  {
    "path": "packages/logic-solver/README.md",
    "content": "# Logic Solver\n\n## Introduction\n\nLogic Solver is a boolean satisfiability solver written in JavaScript.\nGiven a problem expressed as logical constraints on boolean\n(true/false) variables, it either provides a possible solution, or\ntells you definitively that there is no possible assignment of the\nvariables that satisfies the constraints.\n\nMany kinds of logic problems can be expressed in terms of constraints\non boolean variables, including Sudoku puzzles, scheduling problems,\nand the package dependency problem faced by package managers that\nautomatically resolve version conflicts.\n\nLogic Solver can handle complex problems with thousands of variables,\nand has some powerful features such as incremental solving and solving\nunder temporary assumptions.  It also supports small-integer sums and\ninequalities, and can minimize or maximize an integer expression.\n\nLogic Solver contains a copy of [MiniSat](http://minisat.se/), an\nindustrial-strength SAT solver, compiled from C++ to JavaScript using\n[Emscripten](http://emscripten.org).  See [About\nMiniSat](#about-minisat) for more information.\n\nLogic Solver can solve a hard Sudoku in under a second in a web browser,\nwith very clean-looking code compared to many constraint solvers.\n[**Try this demo**](http://sudoku-demo.meteor.com/)\n\n## On NPM\n\n```\nvar Logic = require('logic-solver');\n```\n\nhttps://www.npmjs.com/package/logic-solver\n\n## Table of Contents\n\n- [Introduction](#introduction)\n- [On NPM](#on-npm)\n- [Example: Dinner Guests](#example-dinner-guests)\n- [Example: Magic Squares](#example-magic-squares)\n- [Variables](#variables)\n  - [Logic.Solver#getVarNum(variableName, [noCreate])](#logicsolvergetvarnumvariablename-nocreate)\n  - [Logic.Solver#getVarName(variableNum)](#logicsolvergetvarnamevariablenum)\n- [Terms](#terms)\n  - [Logic.FALSE, Logic.TRUE](#logicfalse-logictrue)\n  - [Logic.isTerm(value)](#logicistermvalue)\n  - [Logic.isNameTerm(value)](#logicisnametermvalue)\n  - [Logic.isNumTerm(value)](#logicisnumtermvalue)\n  - [Logic.Solver#toNameTerm(term)](#logicsolvertonametermterm)\n  - [Logic.Solver#toNumTerm(term, [noCreate])](#logicsolvertonumtermterm-nocreate)\n- [Formulas](#formulas)\n  - [Logic.isFormula(value)](#logicisformulavalue)\n  - [Logic.not(operand)](#logicnotoperand)\n  - [Logic.or(operands...)](#logicoroperands)\n  - [Logic.and(operands...)](#logicandoperands)\n  - [Logic.xor(operands...)](#logicxoroperands)\n  - [Logic.implies(operand1, operand2)](#logicimpliesoperand1-operand2)\n  - [Logic.equiv(operand1, operand2)](#logicequivoperand1-operand2)\n  - [Logic.exactlyOne(operands...)](#logicexactlyoneoperands)\n  - [Logic.atMostOne(operands...)](#logicatmostoneoperands)\n- [Logic.Solver](#logicsolver)\n  - [new Logic.Solver()](#new-logicsolver)\n  - [Logic.Solver#require(args...)](#logicsolverrequireargs)\n  - [Logic.Solver#forbid(args...)](#logicsolverforbidargs)\n  - [Logic.Solver#solve()](#logicsolversolve)\n  - [Logic.Solver#solveAssuming(assumption)](#logicsolversolveassumingassumption)\n  - [Logic.disablingAssertions(func)](#logicdisablingassertionsfunc)\n- [Logic.Solution](#logicsolution)\n  - [Logic.Solution#getMap()](#logicsolutiongetmap)\n  - [Logic.Solution#getTrueVars()](#logicsolutiongettruevars)\n  - [Logic.Solution#evaluate(expression)](#logicsolutionevaluateexpression)\n  - [Logic.Solution#getFormula()](#logicsolutiongetformula)\n  - [Logic.Solution#getWeightedSum(formulas, weights)](#logicsolutiongetweightedsumformulas-weights)\n  - [Logic.Solution#ignoreUnknownVariables()](#logicsolutionignoreunknownvariables)\n- [Optimization](#optimization)\n  - [Logic.Solver#minimizeWeightedSum(solution, formulas, weights)](#logicsolverminimizeweightedsumsolution-formulas-weights)\n  - [Logic.Solver#maximizeWeightedSum(solution, formulas, weights)](#logicsolvermaximizeweightedsumsolution-formulas-weights)\n- [Bits (integers)](#bits-integers)\n  - [new Logic.Bits(formulas)](#new-logicbitsformulas)\n  - [Logic.isBits(value)](#logicisbitsvalue)\n  - [Logic.constantBits(wholeNumber)](#logicconstantbitswholenumber)\n  - [Logic.variableBits(baseName, N)](#logicvariablebitsbasename-n)\n  - [Logic.equalBits(bits1, bits2)](#logicequalbitsbits1-bits2)\n  - [Logic.lessThan(bits1, bits2)](#logiclessthanbits1-bits2)\n  - [Logic.lessThanOrEqual(bits1, bits2)](#logiclessthanorequalbits1-bits2)\n  - [Logic.greaterThan(bits1, bits2)](#logicgreaterthanbits1-bits2)\n  - [Logic.greaterThanOrEqual(bits1, bits2)](#logicgreaterthanorequalbits1-bits2)\n  - [Logic.sum(operands...)](#logicsumoperands)\n  - [Logic.weightedSum(formulas, weights)](#logicweightedsumformulas-weights)\n- [About MiniSat](#about-minisat)\n\n## Example: Dinner Guests\n\nWe are trying to decide what combination of Alice, Bob, and Charlie\nto invite over to dinner, subject to the following constraints:\n\n* Don't invite both Alice and Bob\n* Invite either Bob or Charlie\n\nSetting up these constraints in code:\n\n```js\nvar solver = new Logic.Solver();\n\nsolver.require(Logic.atMostOne(\"Alice\", \"Bob\"));\nsolver.require(Logic.or(\"Bob\", \"Charlie\"));\n```\n\nSolving now will give us one possible solution, chosen arbitrarily:\n\n```js\nvar sol1 = solver.solve();\nsol1.getTrueVars() // => [\"Bob\"]\n```\n\nLet's see what happens if we invite Alice.  By using `solveAssuming`, we\ncan look for a solution that makes an additional logical expression true\nover the ones we have required so far:\n\n```js\nvar sol2 = solver.solveAssuming(\"Alice\");\nsol2.getTrueVars() // => [\"Alice\", \"Charlie\"]\n```\n\nAha!  It seems that inviting Alice means we can't invite Bob, but then\nwe must invite Charlie!  If our reasoning is correct, it is impossible\nto invite Alice and not invite Charlie.  We can confirm this:\n\n```js\nsolver.solveAssuming(Logic.and(\"Alice\", \"-Charlie\")) // => null\n```\n\n(Note that `\"-Charlie\"` is shorthand for `Logic.not(\"Charlie\")`.)\n\nLet's write some code to list all possible solutions:\n\n```js\nvar solutions = [];\nvar curSol;\nwhile ((curSol = solver.solve())) {\n  solutions.push(curSol.getTrueVars());\n  solver.forbid(curSol.getFormula()); // forbid the current solution\n}\n\nsolutions\n// => [[\"Alice\", \"Charlie\"], [\"Charlie\"], [\"Bob\", \"Charlie\"], [\"Bob\"]]\n```\n\nAs you can see, there are four possible solutions to the original problem.\n\nAfter running the above code, all possible solutions are now\nforbidden, so the solver is in an unsatisfiable state.  Calls to\n`solver.require` and `solver.forbid` are permanent, so we cannot\nreturn to a satisfiable state, and any call to `solve` or\n`solveAssuming` henceforth will return no solution:\n\n```js\nsolver.solve() // => null\n```\n\nIt's informative to look at the clauses generated by Logic Solver during\nthis example.  In this notation, `v` is the boolean \"OR\" operator:\n\n```\n-Alice v -Bob  (at most one of Alice, Bob)\nBob v Charlie  (at least one of Bob, Charlie)\n\nAlice v -$assump1  (solve assuming Alice)\n\n$and1 v -$assump2  (solve assuming Alice and not Charlie)\nAlice v -$and1\n-Charlie v -$and1\n\n-Alice v Bob v -Charlie  (forbid [\"Alice\", \"Charlie\"])\nAlice v Bob v -Charlie   (forbid [\"Charlie\"])\nAlice v -Bob v -Charlie  (etc.)\nAlice v -Bob v Charlie\n```\n\nThese clauses are sent to MiniSat using variable numbers in place of names,\nmaking the entire problem quite compact:\n\n```\n[[-3,-4], [4,5],\n [3,-6],\n [8,-7], [3,-8], [-5,-8],\n [-3,4,-5], [3,4,-5], [3,-4,-5], [3,-4,5]]\n```\n\n## Example: Magic Squares\n\nA 3x3 \"magic square\" is an arrangement of the digits 1 through 9 into a square\nsuch that the digits in each row, column, and diagonal add up to the same number.\nHere is an example from [Wikipedia](http://en.wikipedia.org/wiki/Magic_square):\n\n```\n2 7 6\n9 5 1\n4 3 8\n```\n\nEach row, column, and three-digit diagonal adds up to 15, as you can verify.\n(There are many 3x3 magic squares, but the magic sum is always 15, because\nall the digits together add up to 45!)\n\nLet's use Logic Solver to find magic squares.  We could be fancy about\nit and write code that would generalize to NxN magic squares, but\nlet's keep it simple and name the digit locations as follows:\n\n```\nA B C\nD E F\nG H I\n```\n\nBecause each location holds an integer, we must use integer variables instead\nof boolean variables.  An integer in Logic Solver is represented as a group\nof bits, where each bit is a boolean variable, or an entire boolean formula.\nLet's create a 4-bit group of variables for each digit location:\n\n```js\nvar A = Logic.variableBits('A', 4);\nvar B = Logic.variableBits('B', 4);\nvar C = Logic.variableBits('C', 4);\nvar D = Logic.variableBits('D', 4);\nvar E = Logic.variableBits('E', 4);\nvar F = Logic.variableBits('F', 4);\nvar G = Logic.variableBits('G', 4);\nvar H = Logic.variableBits('H', 4);\nvar I = Logic.variableBits('I', 4);\n\nvar locations = [A, B, C, D, E, F, G, H, I];\n\nA.bits // => [\"A$0\", \"A$1\", \"A$2\", \"A$3\"]\n```\n\nLet's also assign the number 15, in bit form, to a variable for convenience.\n\n```js\nvar fifteen = Logic.constantBits(15);\nfifteen.bits // => [\"$T\", \"$T\", \"$T\", \"$T\"]\n```\n\nThe binary representation of 15 is \"1111\", so its bit form consists of\nfour copies of `Logic.TRUE` or `\"$T\"`.  We didn't have to know that,\nthough, because `Logic.constantBits` generated it for us.\n\nNow, we create a Solver and express our sum constraints:\n\n```js\nvar solver = new Logic.Solver();\n\n_.each([[A,B,C], [D,E,F], [G,H,I], [A,D,G], [B,E,H], [C,F,I],\n        [A,E,I], [G,E,C]],\n       function (terms) {\n         solver.require(Logic.equalBits(Logic.sum(terms), fifteen));\n       });\n```\n\nLet's see what solution we get!\n\n```js\nvar sol1 = solver.solve();\nsol1.evaluate(A) // => 3\nsol1.evaluate(B) // => 10 (uh oh)\n_.map(locations, function (loc) { return sol1.evaluate(loc); })\n// => [3, 10, 2,\n//     4,  5, 6,\n//     8,  0, 7]\n```\n\nOops, it looks like we forgot to specify that each \"digit\" is between\n1 and 9!  There is no harm done, because we have only underspecified\nthe problem.  We can continue to use the same `solver` instance.\n\nNow we add inequalities to make each location A through I hold a number\nbetween 1 and 9 inclusive, and solve again:\n\n```js\n_.each(locations, function (loc) {\n  solver.require(Logic.greaterThanOrEqual(loc, Logic.constantBits(1)));\n  solver.require(Logic.lessThanOrEqual(loc, Logic.constantBits(9)));\n});\n\nvar sol2 = solver.solve();\n_.map(locations, function (loc) { return sol2.evaluate(loc); })\n// => [8, 1, 6,\n//     3, 5, 7,\n//     4, 9, 2]\n```\n\nNow we have a proper magic square!\n\nHowever, it just so happens that we also forgot to specify that the\nnumbers be distinct.  To demonstrate that this is an important missing\nconstraint, we can use `solveAssuming` to ask for a solution where A\nand B are equal:\n\n```js\nvar sol3 = solver.solveAssuming(Logic.equalBits(A, B));\n_.map(locations, function (loc) { return sol3.evaluate(loc); })\n// => [4, 4, 7,\n//     8, 5, 2,\n//     3, 6, 6]\n```\n\nOr where A, B, and C are equal:\n\n```js\nvar sol4 = solver.solveAssuming(Logic.and(Logic.equalBits(A, B),\n                                          Logic.equalBits(B, C)));\n_.map(locations, function (loc) { return sol4.evaluate(loc); })\n// => [5, 5, 5,\n//     5, 5, 5,\n//     5, 5, 5]\n```\n\nA good way to enforce that all locations hold different digits is to\ngenerate a requirement about each pair of different locations:\n\n```js\n_.each(locations, function (loc1, i) {\n  _.each(locations, function (loc2, j) {\n    if (i !== j) {\n      solver.forbid(Logic.equalBits(loc1, loc2));\n    }\n  });\n});\n```\n\nSolving now gives us a proper magic square again:\n\n```js\nvar sol5 = solver.solve();\n_.map(locations, function (loc) { return sol5.evaluate(loc); })\n// => [6, 7, 2,\n//     1, 5, 9,\n//     8, 3, 4]\n```\n\nIf we wished to continue interrogating the solver, we could try asking\nfor a magic square with a 1 in the upper-left corner, or proceed to\nenumerate a list of magic squares.\n\nFinally, let's demonstrate that our \"integers\" are really just groups of\nboolean variables:\n\n```js\nsol5.getTrueVars()\n// => [\"A$1\", \"A$2\", \"B$0\", \"B$1\", \"B$2\", \"C$1\", \"D$0\", \"E$0\", \"E$2\",\n//     \"F$0\", \"F$3\", \"G$3\", \"H$0\", \"H$1\", \"I$2\"]\n\n_.map(A.bits, function (v) { return sol5.evaluate(v); })\n// => [false, true, true, false]\n```\n\nYou may be wondering whether it's bad that we generated 72 constraints\nas part of finding a 3x3 magic square.  While there are certainly much\nfaster ways to calculate magic squares, it is perfectly reasonable\nwhen setting up a logic problem to generate a complete set of pairwise\nconstraints over N variables.  In fact, having more constraints often\nimproves performance in real-world problems, so it is worth generating\nextra constraints even when they are technically redundant.  More\nconstraints means more deductions can be made at each step, meaning\nfewer possibilities need to be tried that ultimately won't work out.\nIn this case, it's important that when the solver assigns a digit to a\nparticular location, it immediately be able to deduce that the same\nnumber does not appear at any other location.\n\n## Variables\n\nVariable names are Strings which can contain spaces and punctuation:\n\n```js\nLogic.implies('it is raining', 'take an umbrella');\n\nLogic.exactlyOne(\"1,1\", \"1,2\", \"1,3\")\n```\n\nRestrictions: A variable name must not be empty, consist of only the\ncharacters `0` through `9`, or start with `-`.  Variable names that\nstart with `$` are reserved for internal use.\n\nYou do not need to declare or create your variables before using them\nin formulas passed to `require` and `forbid`.\n\nWhen you pass a variable name to a Solver for the first time, a\nvariable number is allocated, and that name and number become\nsynonymous for that Solver instance.  You don't need to know about\nvariable numbers to use Logic Solver, but you can always use a\nvariable number in place of a variable name in terms and formulas, in\ncase that is useful.  (It is useful internally, and would probably be\nuseful if you were to wrap Logic Solver in another library.)  Examples\nof Solver methods that may allocate new variables are `require`,\n`forbid`, `solveAssuming`, and `getVarNum`.\n\nIf you want to add a free variable to a Solver but not require\nanything about it, you can use `getVarNum` to cause the variable to be\nallocated.  It will then appear in solutions.\n\n### Methods\n\n#### Logic.Solver#getVarNum(variableName, [noCreate])\n\nReturns the variable number for a variable name, allocating a number if\nthis is the first time this Solver has seen `variableName`.\n\n###### Parameters\n\n* `variableName` - String - A valid variable name.\n* `noCreate` - Boolean - Optional.  If true, this method will return\n  0 instead of allocating a new variable number if `variableName` is new.\n\n###### Returns\n\nInteger - A positive integer variable number, or 0 if `noCreate` is true\nand there is no variable number allocated for `variableName`.\n\n#### Logic.Solver#getVarName(variableNum)\n\nReturns the variable name for a given variable number.  An error is thrown\nif `variableNum` is not an allocated variable number.\n\n###### Parameters\n\n* `variableNum` - Integer - An allocated variable number.\n\n###### Returns\n\nString - A variable name.\n\n## Terms\n\nA Term is a variable name or number, optionally negated.  To negate a\nstring Term, prefix it with `\"-\"`.  Examples of valid Terms are\n`\"foo\"`, `\"-foo\"`, `5`, and `-5`.  In other solvers and papers, you may\nsee Terms referred to as \"literals.\"\n\nThe following are equivalent:\n\n```js\nsolver.require(\"-A\");\nsolver.require(Logic.not(\"A\"));\nsolver.forbid(\"A\");\n```\n\nIn fact, `Logic.not(\"A\")` returns `\"-A\"`.  It is valid to have more\nthan one `-` in a Term (`\"---A\"`), and the meaning will be what you'd\nexpect, but `Logic.not` will never return you such a Term, so in\npractice this case does not come up.  `Logic.not(\"-A\")` returns `\"A\"`.\n\nString Terms are called NameTerms, and numeric Terms are called\nNumTerms.  You will not normally need to use numeric Terms, but if you\ndo, note that it doesn't make sense to share them across Solver\ninstances, because each Solver has its own variable numbers.  See the\n[Variables](#variables) section for more information.\n\n### Constants\n\n#### Logic.FALSE, Logic.TRUE\n\nThese Terms represent the constant boolean values false and true.  You\nmay seem them appear as the internal variables `$F` and `$T` or `1`\nand `2`, which are automatically pinned to false and true.\n\n### Methods\n\n#### Logic.isTerm(value)\n\nReturns whether `value` is a valid Term.  A valid Term is either a\nString consisting of a valid variable name preceded by zero or more\n`-` characters, or a non-zero integer.\n\n###### Parameters\n\n* `value` - Any\n\n###### Returns\n\nBoolean\n\n#### Logic.isNameTerm(value)\n\nReturns whether `value` is a valid NameTerm (a Term that is a String).\n\n###### Parameters\n\n* `value` - Any\n\n###### Returns\n\nBoolean\n\n#### Logic.isNumTerm(value)\n\nReturns whether `value` is a valid NumTerm (a Term that is a Number).\n\n###### Parameters\n\n* `value` - Any\n\n###### Returns\n\nBoolean\n\n#### Logic.Solver#toNameTerm(term)\n\nConverts a Term to a NameTerm if it isn't already.  If `term` is a\nNumTerm, the variable number is translated into a variable name.  An\nerror is thrown if the variable number is not an allocated variable\nnumber of this Solver.\n\n###### Parameters\n\n* `term` - Term - The Term to convert, which may be a NameTerm or\n  NumTerm.\n\n###### Returns\n\nNameTerm\n\n#### Logic.Solver#toNumTerm(term, [noCreate])\n\nConverts a Term to a NumTerm if it isn't already.  If `term` is a\nNameTerm, the variable name is translated into a variable number.  A\nnew variable number is allocated if the variable name has not been\nseen before by this Solver, unless you pass true for `noCreate`.\n\n###### Parameters\n\n* `term` - Term - The Term to convert, which may be a NameTerm or\n  NumTerm.\n* `noCreate` - Boolean - Optional.  If true, this method will not\n  allocate a new variable number if it encounters a new variable name,\n  but will return 0 instead.\n\n###### Returns\n\nNumTerm, or 0 (if `noCreate` is true and a new variable name is encountered)\n\n## Formulas\n\nA Formula is an object representing a boolean expression.\nConceptually, a Formula is built out of Terms and operations that\ncombine Terms.\n\nHere are some examples of Formulas:\n\n```js\n// A and B\nLogic.and(\"A\", \"B\")\n\n// If exactly one of (A, B, C) is true, then A does not equal D.\nLogic.implies(Logic.exactlyOne(\"A\", \"B\", \"C\"),\n              Logic.not(Logic.equiv(\"A\", \"D\")))\n\n// More of (x1, x2, x3) are true than (y1, y2, y3)\nvar xs = [\"x1\", \"x2\", \"x3\"];\nvar ys = [\"y1\", \"y2\", \"y3\"];\nLogic.greaterThan(Logic.sum(xs), Logic.sum(ys))\n```\n\nFormulas are immutable.  To be on the safe side, do not mutate any arrays\nyou use to create a Formula.\n\nFormulas are Solver-independent.  They can be created without a Solver,\nand although Solvers keep track of Formula objects and recognize them\n(to avoid compiling the same Formula twice), a Formula object never\nbecomes tied to one Solver object and can always be reused, as long as\nit doesn't contain any explicit variable numbers (NumTerms).\n\nA Term is not a Formula, but you can always pass a Term anywhere a Formula\nis required.\n\nFunctions such as `Logic.and` and `Logic.greaterThan` are called\nFormula constructor functions.  One thing to note about them is that\nthey do not always return Formulas, but may return Terms as well.\n`Logic.and(\"A\")`, for example, returns `\"A\"`.  Some constructor functions\ntake any number of arguments, which may be nested in arrays, so that\nthe following are equivalent:\n\n```js\nLogic.and(\"A\", \"B\", \"C\")\nLogic.and([\"A\", \"B\", \"C\"])\nLogic.and(\"A\", [[\"B\", \"C\"]], [])\n```\n\nTo use a Formula, you must tell a Solver to `require` or `forbid` it.\nOtherwise, the Formula does not take effect.\n\n```js\nvar solver = new Logic.Solver();\nsolver.require(\"A\");\n\nLogic.exactlyOne(\"A\", \"B\"); // no effect, just creates a Formula\n\nsolver.require(Logic.exactlyOne(\"A\", \"B\")); // this works\n\nvar myFormula = Logic.exactlyOne(\"A\", \"B\");\nsolver.require(myFormula); // this also works\n```\n\nYou should save and reuse Formula objects whenever possible, because\nthe Solver will recognize the Formula object and not recompile it.\nInternally, each Formula is replaced by a variable in the Solver, such\nas `$and1` for a `Logic.and`, and clauses are generated that relate\nthe variable to the operands of the Formula.  When you pass the same\nFormula object again, it is replaced by the same variable, and the\nFormula only needs to be compiled once.\n\nFormulas that operate on integers are documented in the\n[Bits](#bits-integers) section.\n\n### Methods\n\n#### Logic.isFormula(value)\n\nReturns true if `value` is a Formula object.  (A Term is not a Formula.)\n\n###### Parameters\n\n* `value` - Any\n\n###### Returns\n\nBoolean\n\n#### Logic.not(operand)\n\nRepresents a boolean expression that is true when its operand is false,\nand vice versa.\n\nWhen called on an operand that is a NameTerm, NumTerm, or Formula, returns\na value of the same kind.\n\n###### Parameters\n\n* `operand` - Formula or Term\n\n###### Returns\n\nFormula or Term (same kind as `operand`)\n\n###### Examples\n\n```js\nLogic.not(\"A\") // => \"-A\"\nLogic.not(\"-A\") // => \"A\"\nLogic.not(Logic.and(\"A\", \"B\")) // => a Formula object\n```\n\n#### Logic.or(operands...)\n\nRepresents a boolean expression that is true when at least one of its\noperands is true.\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, or Arrays\n\n###### Returns\n\nFormula or Term\n\n#### Logic.and(operands...)\n\nRepresents a boolean expression that is true when all of its operands\nare true.\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, or Arrays\n\n###### Returns\n\nFormula or Term\n\n#### Logic.xor(operands...)\n\nRepresents a boolean expression that is true when an odd number of its\noperands are true.\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, or Arrays\n\n###### Returns\n\nFormula or Term\n\n#### Logic.implies(operand1, operand2)\n\nRepresents a boolean expression that is true unless `operand1` is true and\n`operand2` is false.  In other words, if this Formula is required to be true,\nand `operand1` is true, then `operand2` must be true.\n\n###### Parameters\n\n* `operand1` - Formula or Term\n* `operand2` - Formula or Term\n\n###### Returns\n\nFormula or Term\n\n#### Logic.equiv(operand1, operand2)\n\nRepresents a boolean expression that is true when `operand1` and `operand2`\nare either both true or both false.\n\n###### Parameters\n\n* `operand1` - Formula or Term\n* `operand2` - Formula or Term\n\n###### Returns\n\nFormula or Term\n\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, or Arrays\n\n###### Returns\n\nFormula or Term\n\n#### Logic.exactlyOne(operands...)\n\nRepresents a boolean expression that is true when exactly one of its\noperands is true.\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, or Arrays\n\n###### Returns\n\nFormula or Term\n\n#### Logic.atMostOne(operands...)\n\nRepresents a boolean expression that is true when zero or one of its\noperands are true.\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, or Arrays\n\n###### Returns\n\nFormula or Term\n\n## Logic.Solver\n\nYou create a Logic.Solver with `new Logic.Solver()`.\n\nA Solver maintains a list of Formulas that must be true (or false),\nwhich you can think of as a list of constraints.  Each Solver instance\nembeds a self-contained MiniSat instance, which learns and remembers\nfacts that are derived from the constraints.  At any time, you can ask\nthe Solver for a solution that satisfies the current constraints, and\nit will either provide one (chosen arbitrarily) or report that none\nexists.  You can then continue to add more constraints and solve again.\n\nSee [Example: Dinner Guests](#example-dinner-guests) for a good\nintroduction to Solver.\n\nConstraints are only ever added, never removed.  If the current\nconstraints are not satisfiable, then `solve()` will return null, and\nadding additional constraints cannot make the problem solvable again.\nHowever, using `solveAssuming`, you can look for a solution with a\nparticular Formula temporarily in force.  If `solveAssuming` returns\nnull, there is no harm done, and you can continue to solve under other\nassumptions or add more constraints.\n\nSometimes `solve()` will take a long time!  That is to be expected.\nThe best thing to do is to try expressing the problem in a different\nway, with fewer variables, more sharing of common subexpressions, or\nmore constraints between variables so that the solver can make\nimportant deductions in fewer steps.  Also try wrapping your code in\n`Logic.disablingAssertions(function () { ... })` in case runtime type\nchecks are slowing down Formula compilation.\n\nIf you need an extra speed boost in Node, you could help me create a\nbinary npm package containing a native-compiled MiniSat.\n\n### Constructor\n\n#### new Logic.Solver()\n\n### Methods\n\n#### Logic.Solver#require(args...)\n\nRequires that the Formulas and Terms listed in `args` be true in order\nfor a solution to be valid.\n\n###### Parameters\n\n* `args...` - Zero or more Formulas, Terms, or Arrays\n\n#### Logic.Solver#forbid(args...)\n\nRequires that the Formulas and Terms listed in `args` be *false* in\norder for a solution to be valid.\n\n###### Parameters\n\n* `args...` - Zero or more Formulas, Terms, or Arrays\n\n#### Logic.Solver#solve()\n\nFinds a solution that satisfies all the constraints specified with\n`require` and `forbid`, or determines that no such solution is\npossible.  A solution is an assignment of all the variables to boolean\nvalues.\n\nTo find more than one solution, you can forbid the first solution\n(using `solver.forbid(solution.getFormula())`, and solve again.\n\nSolving is fully incremental, and each call to `solve()` has the\nbenefit of everything learned by previous calls to `solve()`.\nRe-solving with one or two new constraints is typically very fast,\nbecause no work is repeated.\n\nThere is no guarantee of which solution is found if there are more\nthan one.  However, some statements can be made about what to expect:\n\n* MiniSat starts by trying a solution where all variables are false,\n  so underconstrained variables will tend to be set to false.\n\n* Calling `solve()` repeatedly, with no intervening method calls, will\n  in practice return the same solution each time.  On the other hand,\n  if you call `solve`, then `solveAssuming`, then `solve` again, the\n  call to `solveAssuming` will affect the solution returned by the\n  second `solve`.\n\n* Logic Solver and MiniSat are deterministic, so the same series of\n  calls on a new Solver will generally produce the same results.\n  However, the results may not be stable across different versions of\n  Logic Solver.\n\n###### Returns\n\nLogic.Solution, or null if no solution is possible\n\n#### Logic.Solver#solveAssuming(assumption)\n\nLike `solve()`, but looks for a solution that additionally satisfies\n`assumption`.  This is especially useful for testing whether a new\nconstraint would make the problem unsolvable before requiring it,\nor for \"querying\" the solver about different types of solutions.\n\nNote that any solution returned by `solveAssuming` is also a valid\nsolution for `solve` to return.  If you call `solve`, then\n`solveAssuming`, then `solve` again, the second `solve` will typically\nreturn the same solution as `solveAssuming`, because the internal\nstate of the solver has been changed (even though no new permanent\nconstraints have been introduced).\n\n###### Parameters\n\n* `assumption` - Formula or Term\n\n###### Returns\n\nLogic.Solution or null\n\n#### Logic.disablingAssertions(func)\n\nCalls `func()`, disabling runtime type checks and assertions for the\nduration.  This speeds up the processing of complex Formulas,\nespecially when integers or large numbers of variables are involved,\nat the price of not validating the arguments to most function calls.\nIt doesn't affect the time spent in MiniSat.\n\n###### Parameters\n\n* `func` - Function\n\n###### Returns\n\nAny - The return value of `func()`.\n\n## Logic.Solution\n\nA Solution represents an assignment or mapping of the Solver\nvariables to true/false values.  Solution objects are returned by\n`Logic.Solver#solve` and `Logic.Solver#solveAssuming`.\n\n(Variables internal to the Solver, which start with `$` and which\nyou'd probably only encounter while poking around in internals, are\nnot considered part of the assignment.)\n\n### Methods\n\n#### Logic.Solution#getMap()\n\nReturns a complete mapping of variables to their assigned values.\n\n###### Returns\n\nObject - Dictionary whose keys are variable names and whose values are\nbooleans\n\n#### Logic.Solution#getTrueVars()\n\nReturns a list of all the variables that are assigned to true by this\nSolution.\n\n###### Returns\n\nArray of String - Names of the variables that are assigned to true\n\n#### Logic.Solution#evaluate(expression)\n\nEvaluates a Formula or Term under this Solution's\nassignment of the variables, returning a boolean value.  For example:\n\n```js\nsolution.evaluate('A')\nsolution.evaluate('-A')\nsolution.evaluate(Logic.or('A', 'B'))\nsolution.evaluate(myFormula) // Formula given to the Solver earlier\n```\n\nIf `expression` is a Bits, the result of evaluation is an integer:\n\n```js\nvar x = Logic.variableBits('x', 3); // 3-digit binary variable\nvar y = Logic.variableBits('y', 3);\nvar xySum = Logic.sum(x, y);\nvar five = Logic.constantBits(5);\n\nvar solver = new Logic.Solver;\nsolver.require(Logic.equalBits(xySum, five));\nvar solution = solver.solve();\nsolution.evaluate(x) // 2 (for example)\nsolution.evaluate(y) // 3 (for example)\nsolution.evaluate(five) // 5\n```\n\nIt is an error to try to evaluate an unknown variable or a variable that\ndid not exist at the time the Solution was created, unless you call\n`ignoreUnknownVariables()` first.\n\n###### Parameters\n\n* `expression` - Formula, Term, or Bits\n\n###### Returns\n\nBoolean or Integer\n\n#### Logic.Solution#getFormula()\n\nCreates a Formula (or Term) which can be used to require, or forbid,\nthat variables are assigned to the exact values they have in this\nSolution.\n\nTo find all solutions to a logic problem:\n\n```js\nvar solver = new Logic.Solver;\nsolver.require(Logic.or('A', 'B'));\n\nvar allSolutions = [];\nvar curSolution = null;\nwhile ((curSolution = solver.solve())) {\n  allSolutions.push(curSolution.getTrueVars());\n  solver.forbid(curSolution.getFormula());\n}\n\nallSolutions // [[\"A\"], [\"A\", \"B\"], [\"B\"]]\n```\n\nAdding a constraint and solving again in this way is quite efficient.\n\nThe Formula or Term returned may not be used with any other Solver instance\nbesides the one that produced this Solution.\n\n###### Returns\n\nFormula or Term\n\n#### Logic.Solution#getWeightedSum(formulas, weights)\n\nEquivalent to `evaluate(Logic.weightedSum(formulas, weights))`, but\nmuch faster because the addition is done using integer arithmetic,\nnot boolean logic.  Rather than constructing a Bits and evaluating it,\n`getWeightedSum` simply evaluates each of the Formulas to a boolean\nvalue and then sums the weights corresponding to the Formulas that\nevaluate to true.\n\nSee `Logic.weightedSum`.\n\n###### Parameters\n\n* `formulas` - Array of Formula or Term\n* `weights` - Array of non-negative integers, or a single non-negative integer\n\n###### Returns\n\nInteger\n\n#### Logic.Solution#ignoreUnknownVariables()\n\nCauses all evaluation by this Solution instance, from now on, to treat\nvariables that aren't part of this Solution as false instead of\nthrowing an error.  This includes unrecognized variable names and\nvariables that were created after this Solution was created.\n\nThis method cannot be undone.  Good style is to call it once when you\nfirst get the Solution object, or not at all.\n\n## Optimization\n\nLogic Solver can perform basic integer optimization, using a\ncombination of inequalities and incremental solving.  The methods in\nthis section are utilities for minimizing or maximizing the value of a\nweighted sum, which is a type of problem sometimes called\npseudo-boolean optimization.\n\nTo understand how these methods work, remember that if you have one\nsolution and want another solution to the same problem, a good\ntechnique is to forbid the current solution and then re-solve.  In a\nsimilar vein, if you have one solution and want another solution that\nyields a larger or smaller value for an integer expression, you can\nsimply express this new constraint as an inequality and re-solve.  The\nfinal wrinkle is to use `solveAssuming` to test out each inequality\nbefore requiring it, so that when the minimum or maximum value is\nfound, the solver is not put into an unsatisfiable state.  The methods\nin this section implement this technique for you.\n\nThis approach to integer optimization works surprisingly well, even when it\ntakes many iterations to achieve the optimum value of a large cost function.\nHowever, depending on the structure of your problem, it may be quite a\ntime-consuming operation.\n\n### Methods\n\n#### Logic.Solver#minimizeWeightedSum(solution, formulas, weights)\n\nFinds a Solution that minimizes the value of\n`Logic.weightedSum(formulas, weights)`, and adds a requirement that\nthis mininum value is obtained (in the sense of calling\n`Solver#require` on this Solver).\n\nTo determine this minimum value, call\n`solution.getWeightedSum(formulas, weights)` on the returned Solution.\n\nA currently valid Solution must be passed in as a starting point.\nThis starting Solution must have been obtained by calling `solve` or\n`solveAssuming` on this Solver, and in addition, being \"currently\nvalid\" means that no calls to `require` or `forbid` have been made\nsince the Solution was produced that conflict with its assignments.\n\nNote that while this method may add constraints to the Solver, the Solver\nis always in a satisfiable state both before and after this method is\ncalled.\n\n###### Parameters\n\n* `solution` - Logic.Solution - A currently valid Solution for this Solver.\n* `formulas` - Array of Formula or Term\n* `weights` - Array of non-negative integers, or a single non-negative integer\n\n###### Returns\n\nLogic.Solution - A valid Solution that achieves the minimum value of\nthe weighted sum.  It may be `solution` if no improvement on the original\nvalue of the weighted sum is possible.\n\n#### Logic.Solver#maximizeWeightedSum(solution, formulas, weights)\n\nFinds a Solution that maximizes the value of\n`Logic.weightedSum(formulas, weights)`, and adds a requirement that\nthis maximum value is obtained (in the sense of calling\n`Solver#require` on this Solver).\n\nTo determine this maximum value, call\n`solution.getWeightedSum(formulas, weights)` on the returned Solution.\n\nA currently valid Solution must be passed in as a starting point.\nThis starting Solution must have been obtained by calling `solve` or\n`solveAssuming` on this Solver, and in addition, being \"currently\nvalid\" means that no calls to `require` or `forbid` have been made\nsince the Solution was produced that conflict with its assignments.\n\nNote that while this method may add constraints to the Solver, the Solver\nis always in a satisfiable state both before and after this method is\ncalled.\n\n###### Parameters\n\n* `solution` - Logic.Solution - A currently valid Solution for this Solver.\n* `formulas` - Array of Formula or Term\n* `weights` - Array of non-negative integers, or a single non-negative integer\n\n###### Returns\n\nLogic.Solution - A valid Solution that achieves the maximum value of\nthe weighted sum.  It may be `solution` if no improvement on the original\nvalue of the weighted sum is possible.\n\n\n## Bits (integers)\n\nA Bits object represents an N-digit binary number (non-negative\ninteger) as an array of N Formulas.  That is, it has a Formula\nfor the boolean value of each bit.  The Formulas are stored in an\narray called `bits` with the least significant bit first, so `bits[0]`\nis the ones digit, `bits[1]` is the twos digit, `bits[2]` is the fours\ndigit, and so on.  (Note that this is the opposite order from how we\nusually write numbers!  It's much more convenient because the index\ninto the array is always the same as the power of two, with numbers\ngrowing to the right as they gain larger-valued digits.)\n\nYou usually don't construct a Bits using the constructor, but instead\nusing `Logic.constantBits`, `Logic.variableBits`, or an operation on\nFormulas such as `Logic.sum`.  When you create an integer variable\nusing `Logic.variableBits`, you specify the number of bits N, but in\nother cases the number of bits is calculated automatically.  For\nexample, `Logic.sum()` with no arguments returns a 0-length Bits.\n`Logic.sum('A', 'B')` returns a 2-length Bits which is the equivalent\nof `new Logic.Bits([Logic.xor('A', 'B'), Logic.and('A', 'B')])`.\n\nSee [Example: Magic Squares](#example-magic-squares) for a good example\nof using Bits.\n\nTo avoid confusion with NumTerms, there is no automatic promotion of\nintegers to Bits.  If you want to use a constant like 5, you must\ncall `Logic.constantBits(5)` to get a Bits object.\n\nThere is currently no explicit subtraction nor any negative numbers in\nLogic Solver.\n\n###### Fields\n\n* `bits` - Array of Formula or Term - Read-only.\n\n### Constructor\n\n#### new Logic.Bits(formulas)\n\nAs previously mentioned, it's more common to create a Bits object\nusing `Logic.constantBits`, `Logic.variableBits`, `Logic.sum`, or\n`Logic.weightedSum` than using this constructor.\n\n###### Parameters\n\n* `formulas` - Array of Formula or Term - Becomes the value of\n  the `bits` property of this Bits.  The array is not copied, so\n  don't mutate the original array.  Unlike many Logic Solver\n  methods, this constructor does not take a variable number\n  of arguments, but requires exactly one array.\n\n### Methods\n\n#### Logic.isBits(value)\n\nReturns true if `value` is a Bits object.\n\n###### Parameters\n\n* `value` - Any\n\n###### Returns\n\nBoolean\n\n#### Logic.constantBits(wholeNumber)\n\nCreates a constant Bits representing the given number.\n\nFor example, `Logic.constantBits(4)` is equivalent to\n`new Logic.Bits([Logic.FALSE, Logic.FALSE, Logic.TRUE])`.\n\n###### Parameters\n\n* `wholeNumber` - non-negative integer\n\n###### Returns\n\nBits\n\n#### Logic.variableBits(baseName, N)\n\nCreates a Bits representing an N-digit integer variable.\n\nFor example, `Logic.variableBits('A', 3)` is equivalent to\n`new Logic.Bits(['A$0', 'A$1', 'A$2'])`.\n\n###### Parameters\n\n* `baseName` - String\n* `N` - non-negative integer\n\n###### Returns\n\nBits\n\n#### Logic.equalBits(bits1, bits2)\n\nRepresents a boolean expression that is true when `bits1` and `bits2`\nare the same integer.\n\n###### Parameters\n\n* `bits1` - Bits\n* `bits2` - Bits\n\n###### Returns\n\nFormula or Term\n\n#### Logic.lessThan(bits1, bits2)\n\nRepresents a boolean expression that is true when `bits1` is less than\n`bits2`, interpreting each as a non-negative integer.\n\n###### Parameters\n\n* `bits1` - Bits\n* `bits2` - Bits\n\n###### Returns\n\nFormula or Term\n\n#### Logic.lessThanOrEqual(bits1, bits2)\n\nRepresents a boolean expression that is true when `bits1` is less than\nor equal to `bits2`, interpreting each as a non-negative integer.\n\n###### Parameters\n\n* `bits1` - Bits\n* `bits2` - Bits\n\n###### Returns\n\nFormula or Term\n\n#### Logic.greaterThan(bits1, bits2)\n\nRepresents a boolean expression that is true when `bits1` is greater than\n`bits2`, interpreting each as a non-negative integer.\n\n###### Parameters\n\n* `bits1` - Bits\n* `bits2` - Bits\n\n###### Returns\n\nFormula or Term\n\n#### Logic.greaterThanOrEqual(bits1, bits2)\n\nRepresents a boolean expression that is true when `bits1` is greater than\nor equal to `bits2`, interpreting each as a non-negative integer.\n\n###### Parameters\n\n* `bits1` - Bits\n* `bits2` - Bits\n\n###### Returns\n\nFormula or Term\n\n#### Logic.sum(operands...)\n\nRepresents an integer expression that is the sum of the values of all\nthe operands.  Bits are interpreted as integers, and booleans are\ninterpreted as 1 or 0.\n\nAs with Formula constructor functions that take a variable number of\narguments, the operands may be nested in arrays arbitrarily and\narbitrarily deeply.\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, Bits, or Arrays\n\n###### Returns\n\nBits\n\n#### Logic.weightedSum(formulas, weights)\n\nRepresents an integer expression that is a weighted sum of the given\nFormulas and Terms, after mapping false to 0 and true to 1.\n\nIn other words, the sum is:\n`(formulas[0] * weights[0]) + (formulas[1] * weights[1]) + ...`,\nwhere `formulas[0]` is replaced with 0 or 1 based on the boolean value\nof that Formula.\n\n`weights` may either be an array of non-negative integers, or a single\nnon-negative integer, in which case that weight is used for all formulas.\nIf `weights` is an array, it must have the same length as `formulas`.\n\n###### Parameters\n\n* `formulas` - Array of Formula or Term\n* `weights` - Array of non-negative integers, or a single non-negative integer\n\n###### Returns\n\nBits\n\n\n## About MiniSat\n\nSolving satisfiability problems (\"SAT-solving\") is notoriously\ndifficult from an algorithmic perspective, but solvers such as MiniSat\nimplement advanced techniques that have come out of years of research.\nYou can read more about MiniSat on its web page at http://minisat.se/.\n\nMiniSat accepts input in \"conjunctive normal form,\" which is a fairly\nlow-level representation of a logic problem.  Logic Solver's main job\nis to take arbitrary boolean formulas that you specify, such as\n\"exactly one of A, B, and C is true,\" and compile them into a list of\nstatements that must all be satisfied -- a conjunction of clauses --\neach of which is a simple disjunction such as: \"A or B or C.\"  \"Not A,\nor not B.\"\n\nAlthough MiniSat operates on a low-level representation of the problem\nand has no explicit knowledge of its overall structure, it is able to\nuse sophisticated techniques to derive new clauses that are implied by\nthe existing clauses.  A naive solver would try assigning values to\nsome of the variables until a conflict occurs, and then backtrack, but\nnot really learn anything from the conflict.  Even custom solvers\nwritten for a particular problem often work this way.  Solvers such as\nMiniSat, on the other hand, employ [Conflict-Driven Clause\nLearning](http://en.wikipedia.org/wiki/Conflict-Driven_Clause_Learning),\nwhich means that when they backtrack, they learn new clauses.  These\nnew clauses narrow the search space and cause subsequent trials to\nreach a conflict sooner, until the entire problem is found to be\nunsatisfiable or a valid assignment is found.\n\nIn principle, Logic Solver could be used as a clause generator for\nother SAT-solver backends besides MiniSat, or for a backend consisting\nof MiniSat compiled to native machine code instead of JavaScript.\n"
  },
  {
    "path": "packages/logic-solver/logic.js",
    "content": "Logic._MiniSat = MiniSat; // Expose for testing and poking around\n\n// import the private testers from types.js\nvar isInteger = Logic._isInteger;\nvar isFunction = Logic._isFunction;\nvar isString = Logic._isString;\nvar isArrayWhere = Logic._isArrayWhere;\nvar isFormulaOrTerm = Logic._isFormulaOrTerm;\nvar isFormulaOrTermOrBits = Logic._isFormulaOrTermOrBits;\n\nLogic._assert = function (value, tester, description) {\n  if (! tester(value)) {\n    var displayValue = (typeof value === 'string' ? JSON.stringify(value) :\n                        value);\n    throw new Error(displayValue + \" is not \" +\n                    (tester.description || description));\n  }\n};\n\n// Call this as `if (assert) assertNumArgs(...)`\nvar assertNumArgs = function (actual, expected, funcName) {\n  if (actual !== expected) {\n    throw new Error(\"Expected \" + expected + \" args in \" + funcName +\n                    \", got \" + actual);\n  }\n};\n\n// Call `assert` as: `if (assert) assert(...)`.\n// This local variable temporarily set to `null` inside\n// `Logic.disablingAssertions`.\nvar assert = Logic._assert;\n\n// Like `if (assert) assert(...)` but usable from other files in the package.\nLogic._assertIfEnabled = function (value, tester, description) {\n  if (assert) assert(value, tester, description);\n};\n\n// Disabling runtime assertions speeds up clause generation.  Assertions\n// are disabled when the local variable `assert` is null instead of\n// `Logic._assert`.\nLogic.disablingAssertions = function (f) {\n  var oldAssert = assert;\n  try {\n    assert = null;\n    return f();\n  } finally {\n    assert = oldAssert;\n  }\n};\n\n// Back-compat.\nLogic._disablingTypeChecks = Logic.disablingAssertions;\n\n////////////////////\n\n// Takes a Formula or Term, returns a Formula or Term.\n// Unlike other operators, if you give it a Term,\n// you will get a Term back (of the same type, NameTerm\n// or NumTerm).\nLogic.not = function (operand) {\n  if (assert) assert(operand, isFormulaOrTerm);\n\n  if (operand instanceof Logic.Formula) {\n    return new Logic.NotFormula(operand);\n  } else {\n    // Term\n    if (typeof operand === 'number') {\n      return -operand;\n    } else if (operand.charAt(0) === '-') {\n      return operand.slice(1);\n    } else {\n      return '-' + operand;\n    }\n  }\n};\n\nLogic.NAME_FALSE = \"$F\";\nLogic.NAME_TRUE = \"$T\";\nLogic.NUM_FALSE = 1;\nLogic.NUM_TRUE = 2;\n\nLogic.TRUE = Logic.NAME_TRUE;\nLogic.FALSE = Logic.NAME_FALSE;\n\n// Abstract base class.  Subclasses are created using _defineFormula.\nLogic.Formula = function () {};\n\nLogic._defineFormula = function (constructor, typeName, methods) {\n  if (assert) assert(constructor, isFunction);\n  if (assert) assert(typeName, isString);\n\n  constructor.prototype = new Logic.Formula();\n  constructor.prototype.type = typeName;\n  if (methods) {\n    _.extend(constructor.prototype, methods);\n  }\n};\n\n// Returns a list of Clauses that together require the Formula to be\n// true, or false (depending on isTrue; both cases must be\n// implemented).  A single Clause may also be returned.  The\n// implementation should call the termifier to convert terms and\n// formulas to NumTerms specific to a solver instance, and use them to\n// construct a Logic.Clause.\nLogic.Formula.prototype.generateClauses = function (isTrue, termifier) {\n  throw new Error(\"Cannot generate this Formula; it must be expanded\");\n};\n// All Formulas have a globally-unique id so that Solvers can track them.\n// It is assigned lazily.\nLogic.Formula._nextGuid = 1;\nLogic.Formula.prototype._guid = null;\nLogic.Formula.prototype.guid = function () {\n  if (this._guid === null) {\n    this._guid = Logic.Formula._nextGuid++;\n  }\n  return this._guid;\n};\n\n// A \"clause\" is a disjunction of terms, e.g. \"A or B or (not C)\",\n// which we write \"A v B v -C\".  Logic.Clause is mainly an internal\n// Solver data structure, which is the final result of formula\n// generation and mapping variable names to numbers, before passing\n// the clauses to MiniSat.\nLogic.Clause = function (/*formulaOrArray, ...*/) {\n  var terms = _.flatten(arguments);\n  if (assert) assert(terms, isArrayWhere(Logic.isNumTerm));\n\n  this.terms = terms; // immutable [NumTerm]\n};\n\n// Returns a new Clause with the extra term or terms appended\nLogic.Clause.prototype.append = function (/*formulaOrArray, ...*/) {\n  return new Logic.Clause(this.terms.concat(_.flatten(arguments)));\n};\n\nvar FormulaInfo = function () {\n  // We generate a variable when a Formula is used.\n  this.varName = null; // string name of variable\n  this.varNum = null; // number of variable (always positive)\n\n  // A formula variable that is used only in the positive or only\n  // in the negative doesn't need the full set of clauses that\n  // establish a bidirectional implication between the formula and the\n  // variable.  For example, in the formula `Logic.or(\"A\", \"B\")`, with the\n  // formula variable `$or1`, the full set of clauses is `A v B v\n  // -$or1; -A v $or1; -B v $or1`.  If both `$or1` and `-$or1` appear\n  // elsewhere in the set of clauses, then all three of these clauses\n  // are required.  However, somewhat surprisingly, if only `$or1` appears,\n  // then only the first is necessary.  If only `-$or1` appears, then only\n  // the second and third are necessary.\n  //\n  // Suppose the formula A v B is represented by the variable $or1,\n  // and $or1 is only used positively. It's important that A v B being\n  // false forces $or1 to be false, so that when $or1 is used it has\n  // the appropriate effect. For example, if we have the clause $or1 v\n  // C, then A v B being false should force $or1 to be false, which\n  // forces C to be true. So we generate the clause A v B v\n  // -$or1. (The implications of this clause are: If A v B is false,\n  // $or1 must be false. If $or1 is true, A v B must be true.)\n  //\n  // However, in the case where A v B is true, we don't actually\n  // need to insist that the solver set $or1 to true, as long as we\n  // are ok with relaxing the relationship between A v B and $or1\n  // and getting a \"wrong\" value for $or1 in the solution. Suppose\n  // the solver goes to work and at some point determines A v B to\n  // be true. It could set $or1 to true, satisfying all the clauses\n  // where it appears, or it could set $or1 to false, which only\n  // constrains the solution space and doesn't open up any new\n  // solutions for other variables. If the solver happens to find a\n  // solution where A v B is true and $or1 is false, we know there\n  // is a similar solution that makes all the same assignments\n  // except it assigns $or1 to true.\n  //\n  // If a formula is used only negatively, a similar argument applies\n  // but with signs flipped, and if it is used both positively and\n  // negatively, both kinds of clauses must be generated.\n  //\n  // See the mention of \"polarity\" in the MiniSat+ paper\n  // (http://minisat.se/downloads/MiniSat+.pdf).\n  //\n  // These flags are set when generation has been done for the positive\n  // case or the negative case, so that we only generate each one once.\n  this.occursPositively = false;\n  this.occursNegatively = false;\n\n  // If a Formula has been directly required or forbidden, we can\n  // replace it by TRUE or FALSE in subsequent clauses.  Track the\n  // information here.\n  this.isRequired = false;\n  this.isForbidden = false;\n};\n\n\n// The \"termifier\" interface is provided to a Formula's\n// generateClauses method, which must use it to generate Clause\n// objects.\n//\n// The reason for this approach is that it gives the Formula control\n// over the clauses returned, but it gives the Solver control over\n// Formula generation.\nLogic.Termifier = function (solver) {\n  this.solver = solver;\n};\n\n// The main entry point, the `clause` method takes a list of\n// FormulaOrTerms and converts it to a Clause containing NumTerms, *by\n// replacing Formulas with their variables*, creating the variable if\n// necessary.  For example, if an OrFormula is represented by the\n// variable `$or1`, it will be replaced by the numeric version of\n// `$or1` to make the Clause.  When the Clause is actually used, it\n// will trigger generation of the clauses that relate `$or1` to the\n// operands of the OrFormula.\nLogic.Termifier.prototype.clause = function (/*args*/) {\n  var self = this;\n  var formulas = _.flatten(arguments);\n  if (assert) assert(formulas, isArrayWhere(isFormulaOrTerm));\n\n  return new Logic.Clause(_.map(formulas, function (f) {\n    return self.term(f);\n  }));\n};\n\n// The `term` method performs the mapping from FormulaOrTerm to\n// NumTerm.  It's called by `clause` and could be called directly\n// from a Formula's generateClauses if it was useful for some\n// reason.\nLogic.Termifier.prototype.term = function (formula) {\n  return this.solver._formulaToTerm(formula);\n};\n\n// The `generate` method generates clauses for a Formula (or\n// Term).  It should be used carefully, because it works quite\n// differently from passing a Formula into `clause`, which is the\n// normal way for one Formula to refer to another.  When you use a\n// Formula in `clause`, it is replaced by the Formula's variable,\n// and the Solver handles generating the Formula's clauses once.\n// When you use `generate`, this system is bypassed, and the\n// Formula's generateClauses method is called pretty much directly,\n// returning the array of Clauses.\nLogic.Termifier.prototype.generate = function (isTrue, formula) {\n  return this.solver._generateFormula(isTrue, formula, this);\n};\n\n\nLogic.Solver = function () {\n  var self = this;\n\n  self.clauses = []; // mutable [Clause]\n  self._num2name = [null]; // no 0th var\n  self._name2num = {}; // (' '+vname) -> vnum\n\n  // true and false\n  var F = self.getVarNum(Logic.NAME_FALSE, false, true); // 1\n  var T = self.getVarNum(Logic.NAME_TRUE, false, true); // 2\n  if (F !== Logic.NUM_FALSE || T !== Logic.NUM_TRUE) {\n    throw new Error(\"Assertion failure: $T and $F have wrong numeric value\");\n  }\n  self._F_used = false;\n  self._T_used = false;\n  // It's important that these clauses are elements 0 and 1\n  // of the clauses array, so that they can optionally be stripped\n  // off.  For example, _clauseData takes advantage of this fact.\n  self.clauses.push(new Logic.Clause(-Logic.NUM_FALSE));\n  self.clauses.push(new Logic.Clause(Logic.NUM_TRUE));\n\n  self._formulaInfo = {}; // Formula guid -> FormulaInfo\n  // For generating formula variables like \"$or1\", \"$or2\", \"$and1\", \"$and2\"\n  self._nextFormulaNumByType = {}; // Formula type -> next var id\n  // Map of Formulas whose info has `false` for either\n  // `occursPositively` or `occursNegatively`\n  self._ungeneratedFormulas = {}; // varNum -> Formula\n\n  self._numClausesAddedToMiniSat = 0;\n  self._unsat = false; // once true, no solution henceforth\n  self._minisat = new MiniSat(); // this takes some time\n\n  self._termifier = new Logic.Termifier(self);\n};\n\n// Get a var number for vname, assigning it a number if it is new.\n// Setting \"noCreate\" to true causes the function to return 0 instead of\n// creating a new variable.\n// Setting \"_createInternals\" to true grants the ability to create $ variables.\nLogic.Solver.prototype.getVarNum = function (vname, noCreate, _createInternals) {\n  var key = ' '+vname;\n  if (_.has(this._name2num, key)) {\n    return this._name2num[key];\n  } else if (noCreate) {\n    return 0;\n  } else {\n    if (vname.charAt(0) === \"$\" && ! _createInternals) {\n      throw new Error(\"Only generated variable names can start with $\");\n    }\n    var vnum = this._num2name.length;\n    this._name2num[key] = vnum;\n    this._num2name.push(vname);\n    return vnum;\n  }\n};\n\nLogic.Solver.prototype.getVarName = function (vnum) {\n  if (assert) assert(vnum, isInteger);\n\n  var num2name = this._num2name;\n  if (vnum < 1 || vnum >= num2name.length) {\n    throw new Error(\"Bad variable num: \" + vnum);\n  } else {\n    return num2name[vnum];\n  }\n};\n\n// Converts a Term to a NumTerm (if it isn't already).  This is done\n// when a Formula creates Clauses for a Solver, since Clauses require\n// NumTerms.  NumTerms stay the same, while a NameTerm like \"-foo\"\n// might become (say) the number -3.  If a NameTerm names a variable\n// that doesn't exist, it is automatically created, unless noCreate\n// is passed, in which case 0 is returned instead.\nLogic.Solver.prototype.toNumTerm = function (t, noCreate) {\n  var self = this;\n\n  if (assert) assert(t, Logic.isTerm);\n\n  if (typeof t === 'number') {\n    return t;\n  } else { // string\n    var not = false;\n    while (t.charAt(0) === '-') {\n      t = t.slice(1);\n      not = ! not;\n    }\n    var n = self.getVarNum(t, noCreate);\n    if (! n) {\n      return 0; // must be the noCreate case\n    } else {\n      return (not ? -n : n);\n    }\n  }\n};\n\n// Converts a Term to a NameTerm (if it isn't already).\nLogic.Solver.prototype.toNameTerm = function (t) {\n  var self = this;\n\n  if (assert) assert(t, Logic.isTerm);\n\n  if (typeof t === 'string') {\n    // canonicalize, removing leading \"--\"\n    while (t.slice(0, 2) === '--') {\n      t = t.slice(2);\n    }\n    return t;\n  } else { // number\n    var not = false;\n    if (t < 0) {\n      not = true;\n      t = -t;\n    }\n    t = self.getVarName(t);\n    if (not) {\n      t = '-' + t;\n    }\n    return t;\n  }\n};\n\nLogic.Solver.prototype._addClause = function (cls, _extraTerms,\n                                              _useTermOverride) {\n  var self = this;\n\n  if (assert) assert(cls, Logic.isClause);\n\n  var extraTerms = null;\n  if (_extraTerms) {\n    extraTerms = _extraTerms;\n    if (assert) assert(extraTerms, isArrayWhere(Logic.isNumTerm));\n  }\n\n  var usedF = false;\n  var usedT = false;\n\n  var numRealTerms = cls.terms.length;\n  if (extraTerms) {\n    // extraTerms are added to the clause as is.  Formula variables in\n    // extraTerms do not cause Formula clause generation, which is\n    // necessary to implement Formula clause generation.\n    cls = cls.append(extraTerms);\n  }\n\n  for (var i = 0; i < cls.terms.length; i++) {\n    var t = cls.terms[i];\n    var v = (t < 0) ? -t : t;\n    if (v === Logic.NUM_FALSE) {\n      usedF = true;\n    } else if (v === Logic.NUM_TRUE) {\n      usedT = true;\n    } else if (v < 1 || v >= self._num2name.length) {\n      throw new Error(\"Bad variable number: \" + v);\n    } else if (i < numRealTerms) {\n      if (_useTermOverride) {\n        _useTermOverride(t);\n      } else {\n        self._useFormulaTerm(t);\n      }\n    }\n  }\n\n  this._F_used = (this._F_used || usedF);\n  this._T_used = (this._T_used || usedT);\n\n  this.clauses.push(cls);\n};\n\n// When we actually use a Formula variable, generate clauses for it,\n// based on whether the usage is positive or negative.  For example,\n// if the Formula `Logic.or(\"X\", \"Y\")` is represented by `$or1`, which\n// is variable number 5, then when you actually use 5 or -5 in a clause,\n// the clauses \"X v Y v -5\" (when you use 5) or \"-X v 5; -Y v 5\"\n// (when you use -5) will be generated.  The clause \"X v Y v -5\"\n// is equivalent to \"5 => X v Y\" (or -(X v Y) => -5), while the clauses\n// \"-X v 5; -Y v 5\" are equivalent to \"-5 => -X; -5 => -Y\" (or\n// \"X => 5; Y => 5\").\n\nLogic.Solver.prototype._useFormulaTerm = function (t, _addClausesOverride) {\n  var self = this;\n  if (assert) assert(t, Logic.isNumTerm);\n  var v = (t < 0) ? -t : t;\n\n  if (! _.has(self._ungeneratedFormulas, v)) {\n    return;\n  }\n\n  // using a Formula's var; maybe have to generate clauses\n  // for the Formula\n  var formula = self._ungeneratedFormulas[v];\n  var info = self._getFormulaInfo(formula);\n  var positive = t > 0;\n\n  // To avoid overflowing the JS stack, defer calls to addClause.\n  // The way we get overflows is when Formulas are deeply nested\n  // (which happens naturally when you call Logic.sum or\n  // Logic.weightedSum on a long list of terms), which causes\n  // addClause to call useFormulaTerm to call addClause, and so\n  // on.  Approach:  The outermost useFormulaTerm keeps a list\n  // of clauses to add, and then adds them in a loop using a\n  // special argument to addClause that passes a special argument\n  // to useFormulaTerm that causes those clauses to go into the\n  // list too.  Code outside of `_useFormulaTerm` and `_addClause(s)`\n  // does not have to pass these special arguments to call them.\n  var deferredAddClauses = null;\n  var addClauses;\n  if (! _addClausesOverride) {\n    deferredAddClauses = [];\n    addClauses = function (clauses, extraTerms) {\n      deferredAddClauses.push({clauses: clauses,\n                               extraTerms: extraTerms});\n    };\n  } else {\n    addClauses = _addClausesOverride;\n  }\n\n  if (positive && ! info.occursPositively) {\n    // generate clauses for the formula.\n    // Eg, if we use variable `X` which represents the formula\n    // `A v B`, add the clause `A v B v -X`.\n    // By using the extraTerms argument to addClauses, we avoid\n    // treating this as a negative occurrence of X.\n    info.occursPositively = true;\n    var clauses = self._generateFormula(true, formula);\n    addClauses(clauses, [-v]);\n  } else if ((! positive) && ! info.occursNegatively) {\n    // Eg, if we have the term `-X` where `X` represents the\n    // formula `A v B`, add the clauses `-A v X` and `-B v X`.\n    // By using the extraTerms argument to addClauses, we avoid\n    // treating this as a positive occurrence of X.\n    info.occursNegatively = true;\n    var clauses = self._generateFormula(false, formula);\n    addClauses(clauses, [v]);\n  }\n  if (info.occursPositively && info.occursNegatively) {\n    delete self._ungeneratedFormulas[v];\n  }\n\n  if (! (deferredAddClauses && deferredAddClauses.length)) {\n    return;\n  }\n\n  var useTerm = function (t) {\n    self._useFormulaTerm(t, addClauses);\n  };\n  // This is the loop that turns recursion into iteration.\n  // When addClauses calls useTerm, which calls useFormulaTerm,\n  // the nested useFormulaTerm will add any clauses to our\n  // own deferredAddClauses list.\n  while (deferredAddClauses.length) {\n    var next = deferredAddClauses.pop();\n    self._addClauses(next.clauses, next.extraTerms, useTerm);\n  }\n};\n\nLogic.Solver.prototype._addClauses = function (array, _extraTerms,\n                                               _useTermOverride) {\n  if (assert) assert(array, isArrayWhere(Logic.isClause));\n  var self = this;\n  _.each(array, function (cls) {\n    self._addClause(cls, _extraTerms, _useTermOverride);\n  });\n};\n\nLogic.Solver.prototype.require = function (/*formulaOrArray, ...*/) {\n  this._requireForbidImpl(true, _.flatten(arguments));\n};\n\nLogic.Solver.prototype.forbid = function (/*formulaOrArray, ...*/) {\n  this._requireForbidImpl(false, _.flatten(arguments));\n};\n\nLogic.Solver.prototype._requireForbidImpl = function (isRequire, formulas) {\n  var self = this;\n  if (assert) assert(formulas, isArrayWhere(isFormulaOrTerm));\n\n  _.each(formulas, function (f) {\n    if (f instanceof Logic.NotFormula) {\n      self._requireForbidImpl(!isRequire, [f.operand]);\n    } else if (f instanceof Logic.Formula) {\n      var info = self._getFormulaInfo(f);\n      if (info.varNum !== null) {\n        var sign = isRequire ? 1 : -1;\n        self._addClause(new Logic.Clause(sign*info.varNum));\n      } else {\n        self._addClauses(self._generateFormula(isRequire, f));\n      }\n      if (isRequire) {\n        info.isRequired = true;\n      } else {\n        info.isForbidden = true;\n      }\n    } else {\n      self._addClauses(self._generateFormula(isRequire, f));\n    }\n  });\n};\n\nLogic.Solver.prototype._generateFormula = function (isTrue, formula, _termifier) {\n  var self = this;\n  if (assert) assert(formula, isFormulaOrTerm);\n\n  if (formula instanceof Logic.NotFormula) {\n    return self._generateFormula(!isTrue, formula.operand);\n  } else if (formula instanceof Logic.Formula) {\n    var info = self._getFormulaInfo(formula);\n    if ((isTrue && info.isRequired) ||\n        (!isTrue && info.isForbidden)) {\n      return [];\n      } else if ((isTrue && info.isForbidden) ||\n                 (!isTrue && info.isRequired)) {\n        return [new Logic.Clause()]; // never satisfied clause\n      } else {\n        var ret = formula.generateClauses(isTrue,\n                                          _termifier || self._termifier);\n        return _.isArray(ret) ? ret : [ret];\n      }\n  } else { // Term\n    var t = self.toNumTerm(formula);\n    var sign = isTrue ? 1 : -1;\n    if (t === sign*Logic.NUM_TRUE || t === -sign*Logic.NUM_FALSE) {\n      return [];\n    } else if (t === sign*Logic.NUM_FALSE || t === -sign*Logic.NUM_TRUE) {\n      return [new Logic.Clause()]; // never satisfied clause\n    } else {\n      return [new Logic.Clause(sign*t)];\n    }\n  }\n};\n\n// Get clause data as an array of arrays of integers,\n// for testing and debugging purposes.\nLogic.Solver.prototype._clauseData = function () {\n  var clauses = _.pluck(this.clauses, 'terms');\n  if (! this._T_used) {\n    clauses.splice(1, 1);\n  }\n  if (! this._F_used) {\n    clauses.splice(0, 1);\n  }\n  return clauses;\n};\n\n// Get clause data as an array of human-readable strings,\n// for testing and debugging purposes.\n// A clause might look like \"A v -B\" (where \"v\" represents\n// and OR operator).\nLogic.Solver.prototype._clauseStrings = function () {\n  var self = this;\n  var clauseData = self._clauseData();\n  return _.map(clauseData, function (clause) {\n    return _.map(clause, function (nterm) {\n      var str = self.toNameTerm(nterm);\n      if (/\\s/.test(str)) {\n        // write name in quotes for readability.  we don't bother\n        // making this string machine-parsable in the general case.\n        var sign = '';\n        if (str.charAt(0) === '-') {\n          // temporarily remove '-'\n          sign = '-';\n          str = str.slice(1);\n        }\n        str = sign + '\"' + str + '\"';\n      }\n      return str;\n    }).join(' v ');\n  });\n};\n\nLogic.Solver.prototype._getFormulaInfo = function (formula, _noCreate) {\n  var self = this;\n  var guid = formula.guid();\n  if (! self._formulaInfo[guid]) {\n    if (_noCreate) {\n      return null;\n    }\n    self._formulaInfo[guid] = new FormulaInfo();\n  }\n  return self._formulaInfo[guid];\n};\n\n// Takes a Formula or an array of Formulas, returns a NumTerm or\n// array of NumTerms.\nLogic.Solver.prototype._formulaToTerm = function (formula) {\n  var self = this;\n\n  if (_.isArray(formula)) {\n    if (assert) assert(formula, isArrayWhere(isFormulaOrTerm));\n    return _.map(formula, _.bind(self._formulaToTerm, self));\n  } else {\n    if (assert) assert(formula, isFormulaOrTerm);\n  }\n\n  if (formula instanceof Logic.NotFormula) {\n    // shortcut that avoids creating a variable called\n    // something like \"$not1\" when you use Logic.not(formula).\n    return Logic.not(self._formulaToTerm(formula.operand));\n  } else if (formula instanceof Logic.Formula) {\n    var info = this._getFormulaInfo(formula);\n    if (info.isRequired) {\n      return Logic.NUM_TRUE;\n    } else if (info.isForbidden) {\n      return Logic.NUM_FALSE;\n    } else if (info.varNum === null) {\n      // generate a Solver-local formula variable like \"$or1\"\n      var type = formula.type;\n      if (! this._nextFormulaNumByType[type]) {\n        this._nextFormulaNumByType[type] = 1;\n      }\n      var numForVarName = this._nextFormulaNumByType[type]++;\n      info.varName = \"$\" + formula.type + numForVarName;\n      info.varNum = this.getVarNum(info.varName, false, true);\n      this._ungeneratedFormulas[info.varNum] = formula;\n    }\n    return info.varNum;\n  } else {\n    // formula is a Term\n    return self.toNumTerm(formula);\n  }\n};\n\nLogic.or = function (/*formulaOrArray, ...*/) {\n  var args = _.flatten(arguments);\n  if (args.length === 0) {\n    return Logic.FALSE;\n  } else if (args.length === 1) {\n    if (assert) assert(args[0], isFormulaOrTerm);\n    return args[0];\n  } else {\n    return new Logic.OrFormula(args);\n  }\n};\n\nLogic.OrFormula = function (operands) {\n  if (assert) assert(operands, isArrayWhere(isFormulaOrTerm));\n  this.operands = operands;\n};\n\nLogic._defineFormula(Logic.OrFormula, 'or', {\n  generateClauses: function (isTrue, t) {\n    if (isTrue) {\n      // eg A v B v C\n      return t.clause(this.operands);\n    } else {\n      // eg -A; -B; -C\n      var result = [];\n      _.each(this.operands, function (o) {\n        result.push.apply(result, t.generate(false, o));\n      });\n      return result;\n    }\n  }\n});\n\nLogic.NotFormula = function (operand) {\n  if (assert) assert(operand, isFormulaOrTerm);\n  this.operand = operand;\n};\n\n// No generation or simplification for 'not'; it is\n// simplified away by the solver itself.\nLogic._defineFormula(Logic.NotFormula, 'not');\n\nLogic.and = function (/*formulaOrArray, ...*/) {\n  var args = _.flatten(arguments);\n  if (args.length === 0) {\n    return Logic.TRUE;\n  } else if (args.length === 1) {\n    if (assert) assert(args[0], isFormulaOrTerm);\n    return args[0];\n  } else {\n    return new Logic.AndFormula(args);\n  }\n};\n\nLogic.AndFormula = function (operands) {\n  if (assert) assert(operands, isArrayWhere(isFormulaOrTerm));\n  this.operands = operands;\n};\n\nLogic._defineFormula(Logic.AndFormula, 'and', {\n  generateClauses: function (isTrue, t) {\n    if (isTrue) {\n      // eg A; B; C\n      var result = [];\n      _.each(this.operands, function (o) {\n        result.push.apply(result, t.generate(true, o));\n      });\n      return result;\n    } else {\n      // eg -A v -B v -C\n      return t.clause(_.map(this.operands, Logic.not));\n    }\n  }\n});\n\n// Group `array` into groups of N, where the last group\n// may be shorter than N.  group([a,b,c,d,e], 3) => [[a,b,c],[d,e]]\nvar group = function (array, N) {\n  var ret = [];\n  for (var i = 0; i < array.length; i += N) {\n    ret.push(array.slice(i, i+N));\n  }\n  return ret;\n};\n\nLogic.xor = function (/*formulaOrArray, ...*/) {\n  var args = _.flatten(arguments);\n  if (args.length === 0) {\n    return Logic.FALSE;\n  } else if (args.length === 1) {\n    if (assert) assert(args[0], isFormulaOrTerm);\n    return args[0];\n  } else {\n    return new Logic.XorFormula(args);\n  }\n};\n\nLogic.XorFormula = function (operands) {\n  if (assert) assert(operands, isArrayWhere(isFormulaOrTerm));\n  this.operands = operands;\n};\n\nLogic._defineFormula(Logic.XorFormula, 'xor', {\n  generateClauses: function (isTrue, t) {\n    var args = this.operands;\n    var not = Logic.not;\n    if (args.length > 3) {\n      return t.generate(\n        isTrue,\n        Logic.xor(\n          _.map(group(this.operands, 3), function (group) {\n            return Logic.xor(group);\n          })));\n    } else if (isTrue) { // args.length <= 3\n      if (args.length === 0) {\n        return t.clause(); // always fail\n      } else if (args.length === 1) {\n        return t.clause(args[0]);\n      } else if (args.length === 2) {\n        var A = args[0], B = args[1];\n        return [t.clause(A, B), // A v B\n                t.clause(not(A), not(B))]; // -A v -B\n      } else if (args.length === 3) {\n        var A = args[0], B = args[1], C = args[2];\n        return [t.clause(A, B, C), // A v B v C\n                t.clause(A, not(B), not(C)), // A v -B v -C\n                t.clause(not(A), B, not(C)), // -A v B v -C\n                t.clause(not(A), not(B), C)]; // -A v -B v C\n      }\n    } else { // !isTrue, args.length <= 3\n      if (args.length === 0) {\n        return []; // always succeed\n      } else if (args.length === 1) {\n        return t.clause(not(args[0]));\n      } else if (args.length === 2) {\n        var A = args[0], B = args[1];\n        return [t.clause(A, not(B)), // A v -B\n                t.clause(not(A), B)]; // -A v B\n      } else if (args.length === 3) {\n        var A = args[0], B = args[1], C = args[2];\n        return [t.clause(not(A), not(B), not(C)), // -A v -B v -C\n                t.clause(not(A), B, C), // -A v B v C\n                t.clause(A, not(B), C), // A v -B v C\n                t.clause(A, B, not(C))]; // A v B v -C\n      }\n    }\n  }\n});\n\nLogic.atMostOne = function (/*formulaOrArray, ...*/) {\n  var args = _.flatten(arguments);\n  if (args.length <= 1) {\n    return Logic.TRUE;\n  } else {\n    return new Logic.AtMostOneFormula(args);\n  }\n};\n\nLogic.AtMostOneFormula = function (operands) {\n  if (assert) assert(operands, isArrayWhere(isFormulaOrTerm));\n  this.operands = operands;\n};\n\nLogic._defineFormula(Logic.AtMostOneFormula, 'atMostOne', {\n  generateClauses: function (isTrue, t) {\n     var args = this.operands;\n     var not = Logic.not;\n     if (args.length <= 1) {\n       return []; // always succeed\n     } else if (args.length === 2) {\n       return t.generate(isTrue, Logic.not(Logic.and(args)));\n     } else if (isTrue && args.length === 3) {\n       // Pick any two args; at least one is false (they aren't\n       // both true).  This strategy would also work for\n       // N>3, and could provide a speed-up by having more clauses\n       // (N^2) but fewer propagation steps.  No speed-up was\n       // observed on the Sudoku test from using this strategy\n       // up to N=10.\n       var clauses = [];\n       for (var i = 0; i < args.length; i++) {\n         for (var j = i+1; j < args.length; j++) {\n           clauses.push(t.clause(not(args[i]), not(args[j])));\n         }\n       }\n       return clauses;\n     } else if ((! isTrue) && args.length === 3) {\n       var A = args[0], B = args[1], C = args[2];\n       // Pick any two args; at least one is true (they aren't\n       // both false).  This only works for N=3.\n       return [t.clause(A, B), t.clause(A, C), t.clause(B, C)];\n     } else {\n       // See the \"commander variables\" technique from:\n       // http://www.cs.cmu.edu/~wklieber/papers/2007_efficient-cnf-encoding-for-selecting-1.pdf\n       // But in short: At most one group has at least one \"true\",\n       // and each group has at most one \"true\".  Formula generation\n       // automatically generates the right implications.\n       var groups = group(args, 3);\n       var ors = _.map(groups, function (g) { return Logic.or(g); });\n       if (groups[groups.length - 1].length < 2) {\n         // Remove final group of length 1 so we don't generate\n         // no-op clauses of one sort or another\n         groups.pop();\n       }\n       var atMostOnes = _.map(groups, function (g) {\n         return Logic.atMostOne(g);\n       });\n       return t.generate(isTrue, Logic.and(Logic.atMostOne(ors), atMostOnes));\n     }\n  }\n});\n\nLogic.implies = function (A, B) {\n  if (assert) assertNumArgs(arguments.length, 2, \"Logic.implies\");\n  return new Logic.ImpliesFormula(A, B);\n};\n\nLogic.ImpliesFormula = function (A, B) {\n  if (assert) assert(A, isFormulaOrTerm);\n  if (assert) assert(B, isFormulaOrTerm);\n  if (assert) assertNumArgs(arguments.length, 2, \"Logic.implies\");\n  this.A = A;\n  this.B = B;\n};\n\nLogic._defineFormula(Logic.ImpliesFormula, 'implies', {\n  generateClauses: function (isTrue, t) {\n    return t.generate(isTrue, Logic.or(Logic.not(this.A), this.B));\n  }\n});\n\nLogic.equiv = function (A, B) {\n  if (assert) assertNumArgs(arguments.length, 2, \"Logic.equiv\");\n  return new Logic.EquivFormula(A, B);\n};\n\nLogic.EquivFormula = function (A, B) {\n  if (assert) assert(A, isFormulaOrTerm);\n  if (assert) assert(B, isFormulaOrTerm);\n  if (assert) assertNumArgs(arguments.length, 2, \"Logic.equiv\");\n  this.A = A;\n  this.B = B;\n};\n\nLogic._defineFormula(Logic.EquivFormula, 'equiv', {\n  generateClauses: function (isTrue, t) {\n    return t.generate(!isTrue, Logic.xor(this.A, this.B));\n  }\n});\n\nLogic.exactlyOne = function (/*formulaOrArray, ...*/) {\n  var args = _.flatten(arguments);\n  if (args.length === 0) {\n    return Logic.FALSE;\n  } else if (args.length === 1) {\n    if (assert) assert(args[0], isFormulaOrTerm);\n    return args[0];\n  } else {\n    return new Logic.ExactlyOneFormula(args);\n  }\n};\n\nLogic.ExactlyOneFormula = function (operands) {\n  if (assert) assert(operands, isArrayWhere(isFormulaOrTerm));\n  this.operands = operands;\n};\n\nLogic._defineFormula(Logic.ExactlyOneFormula, 'exactlyOne', {\n  generateClauses: function (isTrue, t) {\n    var args = this.operands;\n    if (args.length < 3) {\n      return t.generate(isTrue, Logic.xor(args));\n    } else {\n      return t.generate(isTrue, Logic.and(Logic.atMostOne(args),\n                                          Logic.or(args)));\n    }\n  }\n});\n\n// List of 0 or more formulas or terms, which together represent\n// a non-negative integer.  Least significant bit is first.  That is,\n// the kth array element has a place value of 2^k.\nLogic.Bits = function (formulaArray) {\n  if (assert) assert(formulaArray, isArrayWhere(isFormulaOrTerm));\n  this.bits = formulaArray; // public, immutable\n};\n\nLogic.constantBits = function (wholeNumber) {\n  if (assert) assert(wholeNumber, Logic.isWholeNumber);\n  var result = [];\n  while (wholeNumber) {\n    result.push((wholeNumber & 1) ? Logic.TRUE : Logic.FALSE);\n    wholeNumber >>>= 1;\n  }\n  return new Logic.Bits(result);\n};\n\nLogic.variableBits = function (baseName, nbits) {\n  if (assert) assert(nbits, Logic.isWholeNumber);\n  var result = [];\n  for (var i = 0; i < nbits; i++) {\n    result.push(baseName + '$' + i);\n  }\n  return new Logic.Bits(result);\n};\n\n// bits1 <= bits2\nLogic.lessThanOrEqual = function (bits1, bits2) {\n  return new Logic.LessThanOrEqualFormula(bits1, bits2);\n};\n\nLogic.LessThanOrEqualFormula = function (bits1, bits2) {\n  if (assert) assert(bits1, Logic.isBits);\n  if (assert) assert(bits2, Logic.isBits);\n  if (assert) assertNumArgs(arguments.length, 2, \"Bits comparison function\");\n  this.bits1 = bits1;\n  this.bits2 = bits2;\n};\n\nvar genLTE = function (bits1, bits2, t, notEqual) {\n  var ret = [];\n  // clone so we can mutate them in place\n  var A = bits1.bits.slice();\n  var B = bits2.bits.slice();\n  if (notEqual && ! bits2.bits.length) {\n    // can't be less than 0\n    return t.clause();\n  }\n  // if A is longer than B, the extra (high) bits\n  // must be 0.\n  while (A.length > B.length) {\n    var hi = A.pop();\n    ret.push(t.clause(Logic.not(hi)));\n  }\n  // now B.length >= A.length\n  // Let xors[i] be (A[i] xor B[i]), or just\n  // B[i] if A is too short.\n  var xors = _.map(B, function (b, i) {\n    if (i < A.length) {\n      return Logic.xor(A[i], b);\n    } else {\n      return b;\n    }\n  });\n\n  // Suppose we are comparing 3-bit numbers, requiring\n  // that ABC <= XYZ.  Here is what we require:\n  //\n  // * It is false that A=1 and X=0.\n  // * It is false that A=X, B=1, and Y=0.\n  // * It is false that A=X, B=Y, C=1, and Y=0.\n  //\n  // Translating these into clauses using DeMorgan's law:\n  //\n  // * A=0 or X=1\n  // * (A xor X) or B=0 or Y=1\n  // * (A xor X) or (B xor Y) or C=0 or Y=1\n  //\n  // Since our arguments are LSB first, in the example\n  // we would be given [C, B, A] and [Z, Y, X] as input.\n  // We iterate over the first argument starting from\n  // the right, and build up a clause by iterating over\n  // the xors from the right.\n  //\n  // If we have ABC <= VWXYZ, then we still have three clauses,\n  // but each one is prefixed with \"V or W or\", because V and W\n  // are at the end of the xors array.  This is equivalent to\n  // padding ABC with two zeros.\n\n  for (var i = A.length-1; i >= 0; i--) {\n    ret.push(t.clause(xors.slice(i+1), Logic.not(A[i]), B[i]));\n  }\n  if (notEqual) {\n    ret.push.apply(ret, t.generate(true, Logic.or(xors)));\n  }\n  return ret;\n};\n\nLogic._defineFormula(Logic.LessThanOrEqualFormula, 'lte', {\n  generateClauses: function (isTrue, t) {\n    if (isTrue) {\n      // bits1 <= bits2\n      return genLTE(this.bits1, this.bits2, t, false);\n    } else {\n      // bits2 < bits1\n      return genLTE(this.bits2, this.bits1, t, true);\n    }\n  }\n});\n\n// bits1 < bits2\nLogic.lessThan = function (bits1, bits2) {\n  return new Logic.LessThanFormula(bits1, bits2);\n};\n\nLogic.LessThanFormula = function (bits1, bits2) {\n  if (assert) assert(bits1, Logic.isBits);\n  if (assert) assert(bits2, Logic.isBits);\n  if (assert) assertNumArgs(arguments.length, 2, \"Bits comparison function\");\n  this.bits1 = bits1;\n  this.bits2 = bits2;\n};\n\nLogic._defineFormula(Logic.LessThanFormula, 'lt', {\n  generateClauses: function (isTrue, t) {\n    if (isTrue) {\n      // bits1 < bits2\n      return genLTE(this.bits1, this.bits2, t, true);\n    } else {\n      // bits2 <= bits1\n      return genLTE(this.bits2, this.bits1, t, false);\n    }\n  }\n});\n\nLogic.greaterThan = function (bits1, bits2) {\n  return Logic.lessThan(bits2, bits1);\n};\n\nLogic.greaterThanOrEqual = function (bits1, bits2) {\n  return Logic.lessThanOrEqual(bits2, bits1);\n};\n\nLogic.equalBits = function (bits1, bits2) {\n  return new Logic.EqualBitsFormula(bits1, bits2);\n};\n\nLogic.EqualBitsFormula = function (bits1, bits2) {\n  if (assert) assert(bits1, Logic.isBits);\n  if (assert) assert(bits2, Logic.isBits);\n  if (assert) assertNumArgs(arguments.length, 2, \"Logic.equalBits\");\n  this.bits1 = bits1;\n  this.bits2 = bits2;\n};\n\nLogic._defineFormula(Logic.EqualBitsFormula, 'equalBits', {\n  generateClauses: function (isTrue, t) {\n    var A = this.bits1.bits;\n    var B = this.bits2.bits;\n    var nbits = Math.max(A.length, B.length);\n    var facts = [];\n    for (var i = 0; i < nbits; i++) {\n      if (i >= A.length) {\n        facts.push(Logic.not(B[i]));\n      } else if (i >= B.length) {\n        facts.push(Logic.not(A[i]));\n      } else {\n        facts.push(Logic.equiv(A[i], B[i]));\n      }\n    }\n    return t.generate(isTrue, Logic.and(facts));\n  }\n});\n\n// Definition of full-adder and half-adder:\n//\n// A full-adder is a 3-input, 2-output gate producing the sum of its\n// inputs as a 2-bit binary number. The most significant bit is called\n// \"carry\", the least significant \"sum\". A half-adder does the same\n// thing, but has only 2 inputs (and can therefore never output a\n// \"3\").\n//\n// The half-adder sum bit is really just an XOR, and the carry bit\n// is really just an AND.  However, they get their own formula types\n// here to enhance readability of the generated clauses.\n\nLogic.HalfAdderSum = function (formula1, formula2) {\n  if (assert) assert(formula1, isFormulaOrTerm);\n  if (assert) assert(formula2, isFormulaOrTerm);\n\n  if (assert) assertNumArgs(arguments.length, 2, \"Logic.HalfAdderSum\");\n  this.a = formula1;\n  this.b = formula2;\n};\n\nLogic._defineFormula(Logic.HalfAdderSum, 'hsum', {\n  generateClauses: function (isTrue, t) {\n    return t.generate(isTrue, Logic.xor(this.a, this.b));\n  }\n});\n\nLogic.HalfAdderCarry = function (formula1, formula2) {\n  if (assert) assert(formula1, isFormulaOrTerm);\n  if (assert) assert(formula2, isFormulaOrTerm);\n  if (assert) assertNumArgs(arguments.length, 2, \"Logic.HalfAdderCarry\");\n  this.a = formula1;\n  this.b = formula2;\n};\n\nLogic._defineFormula(Logic.HalfAdderCarry, 'hcarry', {\n  generateClauses: function (isTrue, t) {\n    return t.generate(isTrue, Logic.and(this.a, this.b));\n  }\n});\n\nLogic.FullAdderSum = function (formula1, formula2, formula3) {\n  if (assert) assert(formula1, isFormulaOrTerm);\n  if (assert) assert(formula2, isFormulaOrTerm);\n  if (assert) assert(formula3, isFormulaOrTerm);\n  if (assert) assertNumArgs(arguments.length, 3, \"Logic.FullAdderSum\");\n  this.a = formula1;\n  this.b = formula2;\n  this.c = formula3;\n};\n\nLogic._defineFormula(Logic.FullAdderSum, 'fsum', {\n  generateClauses: function (isTrue, t) {\n    return t.generate(isTrue, Logic.xor(this.a, this.b, this.c));\n  }\n});\n\nLogic.FullAdderCarry = function (formula1, formula2, formula3) {\n  if (assert) assert(formula1, isFormulaOrTerm);\n  if (assert) assert(formula2, isFormulaOrTerm);\n  if (assert) assert(formula3, isFormulaOrTerm);\n  if (assert) assertNumArgs(arguments.length, 3, \"Logic.FullAdderCarry\");\n  this.a = formula1;\n  this.b = formula2;\n  this.c = formula3;\n};\n\nLogic._defineFormula(Logic.FullAdderCarry, 'fcarry', {\n  generateClauses: function (isTrue, t) {\n    return t.generate(! isTrue,\n                      Logic.atMostOne(this.a, this.b, this.c));\n  }\n});\n\n// Implements the Adder strategy from the MiniSat+ paper:\n// http://minisat.se/downloads/MiniSat+.pdf\n// \"Translating Pseudo-boolean Constraints into SAT\"\n//\n// Takes a list of list of Formulas.  The first list is bits\n// to give weight 1; the second is bits to give weight 2;\n// the third is bits to give weight 4; and so on.\n//\n// Returns an array of Logic.FormulaOrTerm.\nvar binaryWeightedSum = function (varsByWeight) {\n  if (assert) assert(varsByWeight,\n                     isArrayWhere(isArrayWhere(isFormulaOrTerm)));\n  // initialize buckets to a two-level clone of varsByWeight\n  var buckets = _.map(varsByWeight, _.clone);\n  var lowestWeight = 0; // index of the first non-empty array\n  var output = [];\n  while (lowestWeight < buckets.length) {\n    var bucket = buckets[lowestWeight];\n    if (! bucket.length) {\n      output.push(Logic.FALSE);\n      lowestWeight++;\n    } else if (bucket.length === 1) {\n      output.push(bucket[0]);\n      lowestWeight++;\n    } else if (bucket.length === 2) {\n      var sum = new Logic.HalfAdderSum(bucket[0], bucket[1]);\n      var carry = new Logic.HalfAdderCarry(bucket[0], bucket[1]);\n      bucket.length = 0;\n      bucket.push(sum);\n      pushToNth(buckets, lowestWeight+1, carry);\n    } else {\n      // Whether we take variables from the start or end of the\n      // bucket (i.e. `pop` or `shift`) determines the shape of the tree.\n      // Empirically, some logic problems are faster with `shift` (2x or so),\n      // but `pop` gives an order-of-magnitude speed-up on the Meteor Version\n      // Solver \"benchmark-tests\" suite (Slava's benchmarks based on data from\n      // Rails).  So, `pop` it is.\n      var c = bucket.pop();\n      var b = bucket.pop();\n      var a = bucket.pop();\n      var sum = new Logic.FullAdderSum(a, b, c);\n      var carry = new Logic.FullAdderCarry(a, b, c);\n      bucket.push(sum);\n      pushToNth(buckets, lowestWeight+1, carry);\n    }\n  }\n  return output;\n};\n\n// Push `newItem` onto the array at arrayOfArrays[n],\n// first ensuring that it exists by pushing empty\n// arrays onto arrayOfArrays.\nvar pushToNth = function (arrayOfArrays, n, newItem) {\n  while (n >= arrayOfArrays.length) {\n    arrayOfArrays.push([]);\n  }\n  arrayOfArrays[n].push(newItem);\n};\n\nvar checkWeightedSumArgs = function (formulas, weights) {\n  if (assert) assert(formulas, isArrayWhere(isFormulaOrTerm));\n  if (typeof weights === 'number') {\n    if (assert) assert(weights, Logic.isWholeNumber);\n  } else {\n    if (assert) assert(weights, isArrayWhere(Logic.isWholeNumber));\n    if (formulas.length !== weights.length) {\n      throw new Error(\"Formula array and weight array must be same length\" +\n                      \"; they are \" + formulas.length + \" and \" + weights.length);\n    }\n  }\n};\n\nLogic.weightedSum = function (formulas, weights) {\n  checkWeightedSumArgs(formulas, weights);\n\n  if (formulas.length === 0) {\n    return new Logic.Bits([]);\n  }\n\n  if (typeof weights === 'number') {\n    weights = _.map(formulas, function () { return weights; });\n  }\n\n  var binaryWeighted = [];\n  _.each(formulas, function (f, i) {\n    var w = weights[i];\n    var whichBit = 0;\n    while (w) {\n      if (w & 1) {\n        pushToNth(binaryWeighted, whichBit, f);\n      }\n      w >>>= 1;\n      whichBit++;\n    }\n  });\n\n  return new Logic.Bits(binaryWeightedSum(binaryWeighted));\n};\n\nLogic.sum = function (/*formulaOrBitsOrArray, ...*/) {\n  var things = _.flatten(arguments);\n  if (assert) assert(things, isArrayWhere(isFormulaOrTermOrBits));\n\n  var binaryWeighted = [];\n  _.each(things, function (x) {\n    if (x instanceof Logic.Bits) {\n      _.each(x.bits, function (b, i) {\n        pushToNth(binaryWeighted, i, b);\n      });\n    } else {\n      pushToNth(binaryWeighted, 0, x);\n    }\n  });\n\n  return new Logic.Bits(binaryWeightedSum(binaryWeighted));\n};\n\n////////////////////////////////////////\n\nLogic.Solver.prototype.solve = function (_assumpVar) {\n  var self = this;\n  if (_assumpVar !== undefined) {\n    if (! (_assumpVar >= 1)) {\n      throw new Error(\"_assumpVar must be a variable number\");\n    }\n  }\n\n  if (self._unsat) {\n    return null;\n  }\n\n  while (self._numClausesAddedToMiniSat < self.clauses.length) {\n    var i = self._numClausesAddedToMiniSat;\n    var stillSat = self._minisat.addClause(self.clauses[i].terms);\n    self._numClausesAddedToMiniSat++;\n    if (! stillSat) {\n      self._unsat = true;\n      return null;\n    }\n  }\n  self._minisat.ensureVar(this._num2name.length - 1);\n\n  var stillSat = (_assumpVar ?\n                  self._minisat.solveAssuming(_assumpVar) :\n                  self._minisat.solve());\n  if (! stillSat) {\n    if (! _assumpVar) {\n      self._unsat = true;\n    }\n    return null;\n  }\n\n  return new Logic.Solution(self, self._minisat.getSolution());\n};\n\nLogic.Solver.prototype.solveAssuming = function (formula) {\n  if (assert) assert(formula, isFormulaOrTerm);\n\n  // Wrap the formula in a formula of type Assumption, so that\n  // we always generate a var like `$assump123`, regardless\n  // of whether `formula` is a Term, a NotFormula, an already\n  // required or forbidden Formula, etc.\n  var assump = new Logic.Assumption(formula);\n  var assumpVar = this._formulaToTerm(assump);\n  if (! (typeof assumpVar === 'number' && assumpVar > 0)) {\n    throw new Error(\"Assertion failure: not a positive numeric term\");\n  }\n\n  // Generate clauses as if we used the assumption variable in a\n  // clause, in the positive.  So if we assume \"A v B\", we might get a\n  // clause like \"A v B v -$assump123\" (or actually, \"$or1 v\n  // -$assump123\"), as if we had used $assump123 in a clause.  Instead\n  // of using it in a clause, though, we temporarily assume it to be\n  // true.\n  this._useFormulaTerm(assumpVar);\n\n  var result = this.solve(assumpVar);\n  // Tell MiniSat that we will never use assumpVar again.\n  // The formula may be used again, however.  (For example, you\n  // can solve assuming a formula F, and if it works, require F.)\n  this._minisat.retireVar(assumpVar);\n\n  return result;\n};\n\nLogic.Assumption = function (formula) {\n  if (assert) assert(formula, isFormulaOrTerm);\n  this.formula = formula;\n};\n\nLogic._defineFormula(Logic.Assumption, 'assump', {\n  generateClauses: function (isTrue, t) {\n    if (isTrue) {\n      return t.clause(this.formula);\n    } else {\n      return t.clause(Logic.not(this.formula));\n    }\n  }\n});\n\nLogic.Solution = function (_solver, _assignment) {\n  var self = this;\n  self._solver = _solver;\n  self._assignment = _assignment;\n\n  // save a snapshot of which formulas have variables designated\n  // for them, but where we haven't generated clauses that constrain\n  // those variables in both the positive and the negative direction.\n  self._ungeneratedFormulas = _.clone(_solver._ungeneratedFormulas);\n\n  self._formulaValueCache = {};\n  self._termifier = new Logic.Termifier(self._solver);\n  // Normally, when a Formula uses a Termifier to generate clauses that\n  // refer to other Formulas, the Termifier replaces the Formulas with\n  // their variables.  We hijack this mechanism to replace the Formulas\n  // with their truth variables instead, leading to recursive evaluation.\n  // Note that we cache the evaluated truth values of Formulas to avoid\n  // redundant evaluation.\n  self._termifier.term = function (formula) {\n    return self.evaluate(formula) ? Logic.NUM_TRUE : Logic.NUM_FALSE;\n  };\n\n  // When true, evaluation doesn't throw errors when\n  // `evaluate` or `getWeightedSum` encounter named variables that are\n  // unknown or variables that weren't present when this Solution was\n  // generated.  Instead, the unknown variables are assumed to be false.\n  self._ignoreUnknownVariables = false;\n};\n\nLogic.Solution.prototype.ignoreUnknownVariables = function () {\n  // We only make this settable one way (false to true).\n  // Setting it back and forth would be questionable, since we keep\n  // a cache of Formula evaluations.\n  this._ignoreUnknownVariables = true;\n};\n\n// Get a map of variables to their assignments,\n// such as `{A: true, B: false, C: true}`.\n// Internal variables are excluded.\nLogic.Solution.prototype.getMap = function () {\n  var solver = this._solver;\n  var assignment = this._assignment;\n  var result = {};\n  for (var i = 1; i < assignment.length; i++) {\n    var name = solver.getVarName(i);\n    if (name && name.charAt(0) !== '$') {\n      result[name] = assignment[i];\n    }\n  }\n  return result;\n};\n\n// Get an array of variables that are assigned\n// `true` by this solution, sorted by name.\n// Internal variables are excluded.\nLogic.Solution.prototype.getTrueVars = function () {\n  var solver = this._solver;\n  var assignment = this._assignment;\n  var result = [];\n  for (var i = 1; i < assignment.length; i++) {\n    if (assignment[i]) {\n      var name = solver.getVarName(i);\n      if (name && name.charAt(0) !== '$') {\n        result.push(name);\n      }\n    }\n  }\n  result.sort();\n  return result;\n};\n\n// Get a Formula that says that the variables are assigned\n// according to this solution.  (Internal variables are\n// excluded.)  By forbidding this Formula and solving again,\n// you can see if there are other solutions.\nLogic.Solution.prototype.getFormula = function () {\n  var solver = this._solver;\n  var assignment = this._assignment;\n  var terms = [];\n  for (var i = 1; i < assignment.length; i++) {\n    var name = solver.getVarName(i);\n    if (name && name.charAt(0) !== '$') {\n      terms.push(assignment[i] ? i : -i);\n    }\n  }\n  return Logic.and(terms);\n};\n\n// Returns a boolean if the argument is a Formula (or Term), and an integer\n// if the argument is a Logic.Bits.\nLogic.Solution.prototype.evaluate = function (formulaOrBits) {\n  var self = this;\n  if (assert) assert(formulaOrBits, isFormulaOrTermOrBits);\n\n  if (formulaOrBits instanceof Logic.Bits) {\n    // Evaluate to an integer\n    var ret = 0;\n    _.each(formulaOrBits.bits, function (f, i) {\n      if (self.evaluate(f)) {\n        ret += 1 << i;\n      }\n    });\n    return ret;\n  }\n\n  var solver = self._solver;\n  var ignoreUnknownVariables = self._ignoreUnknownVariables;\n  var assignment = self._assignment;\n  var formula = formulaOrBits;\n  if (formula instanceof Logic.NotFormula) {\n    return ! self.evaluate(formula.operand);\n  } else if (formula instanceof Logic.Formula) {\n    var cachedResult = self._formulaValueCache[formula.guid()];\n    if (typeof cachedResult === 'boolean') {\n      return cachedResult;\n    } else {\n      var value;\n      var info = solver._getFormulaInfo(formula, true);\n      if (info && info.varNum && info.varNum < assignment.length &&\n          ! _.has(self._ungeneratedFormulas, info.varNum)) {\n        // as an optimization, read the value of the formula directly\n        // from a variable if the formula's clauses were completely\n        // generated at the time of solving.  (We must be careful,\n        // because if we didn't generate both the positive and the\n        // negative polarity clauses for the formula, then the formula\n        // variable is not actually constrained to have the right\n        // value.)\n        value = assignment[info.varNum];\n      } else {\n        var clauses = solver._generateFormula(true, formula, self._termifier);\n        var value = _.all(clauses, function (cls) {\n          return _.any(cls.terms, function (t) {\n            return self.evaluate(t);\n          });\n        });\n      }\n      self._formulaValueCache[formula.guid()] = value;\n      return value;\n    }\n  } else {\n    // Term; convert to numeric (possibly negative), but throw\n    // an error if the name is not found.  If `ignoreUnknownVariables`\n    // is set, return false instead.\n    var numTerm = solver.toNumTerm(formula, true);\n    if (! numTerm) {\n      if (ignoreUnknownVariables) {\n        return false;\n      } else {\n        // formula must be a NameTerm naming a variable that doesn't exist\n        var vname = String(formula).replace(/^-*/, '');\n        throw new Error(\"No such variable: \" + vname);\n      }\n    }\n    var v = numTerm;\n    var isNot = false;\n    if (numTerm < 0) {\n      v = -v;\n      isNot = true;\n    }\n    if (v < 1 || v >= assignment.length) {\n      var vname = v;\n      if (v >= 1 && v < solver._num2name.length) {\n        vname = solver._num2name[v];\n      }\n      if (ignoreUnknownVariables) {\n        return false;\n      } else {\n        throw new Error(\"Variable not part of solution: \" + vname);\n      }\n    }\n    var ret = assignment[v];\n    if (isNot) {\n      ret = ! ret;\n    }\n    return ret;\n  }\n};\n\nLogic.Solution.prototype.getWeightedSum = function (formulas, weights) {\n  checkWeightedSumArgs(formulas, weights);\n\n  var total = 0;\n  if (typeof weights === 'number') {\n    for (var i = 0; i < formulas.length; i++) {\n      total += weights * (this.evaluate(formulas[i]) ? 1 : 0);\n    }\n  } else {\n    for (var i = 0; i < formulas.length; i++) {\n      total += weights[i] * (this.evaluate(formulas[i]) ? 1 : 0);\n    }\n  }\n  return total;\n};\n"
  },
  {
    "path": "packages/logic-solver/logic_tests.js",
    "content": "\nTinytest.add(\"logic-solver - require\", function (test) {\n  var s = new Logic.Solver;\n\n  s.require('foo');\n  test.equal(s._clauseData(), [[3]]);\n  test.equal(s._clauseStrings(), [\"foo\"]);\n  s.forbid('foo');\n  test.equal(s._clauseData(), [[3], [-3]]);\n  test.equal(s._clauseStrings(), [\"foo\", \"-foo\"]);\n\n  s.require([['foo'], '-bar'], '--foo', 'foo');\n  test.equal(s._clauseData(), [[3], [-3], [3], [-4], [3], [3]]);\n  test.equal(s._clauseStrings(), [\"foo\", \"-foo\", \"foo\",\n                                  \"-bar\", \"foo\", \"foo\"]);\n});\n\nTinytest.add(\"logic-solver - _clauseStrings\", function (test) {\n  var s = new Logic.Solver;\n\n  s.require('foo');\n\n  test.equal(s._clauseStrings(), [\"foo\"]);\n  s.require('-myPackage 1.0.0');\n  test.equal(s._clauseStrings(), [\"foo\", '-\"myPackage 1.0.0\"']);\n});\n\nTinytest.add(\"logic-solver - illegal NameTerms\", function (test) {\n  var s = new Logic.Solver;\n\n  test.throws(function () {\n    s.require('');\n  });\n\n  test.throws(function () {\n    s.require('-');\n  });\n\n  test.throws(function () {\n    s.require('0');\n  });\n\n  test.throws(function () {\n    s.require('$x');\n  });\n\n  test.throws(function () {\n    s.require('-1');\n  });\n\n  test.throws(function () {\n    s.require('---123');\n  });\n});\n\nTinytest.add(\"logic-solver - toNameTerm, toNumTerm\", function (test) {\n  var s = new Logic.Solver;\n\n  test.equal(s.toNumTerm(\"foo\"), 3);\n  test.equal(s.toNumTerm(\"-foo\"), -3);\n\n  test.equal(s.toNameTerm(3), \"foo\");\n  test.equal(s.toNameTerm(-3), \"-foo\");\n\n  test.equal(s.toNameTerm(\"-----foo\"), \"-foo\");\n});\n\nvar formatLines = function (stringArray) {\n  return JSON.stringify(stringArray).replace(/\",\"/g, '\",\\n \"');\n};\n\nvar checkClauses = function (test, f, expected) {\n  check(f, Function);\n  check(expected, [String]);\n  var s = new Logic.Solver;\n  f(s);\n  test.equal(formatLines(s._clauseStrings()),\n             formatLines(expected));\n};\n\nvar runClauseTests = function (test, funcsAndExpecteds) {\n  check(funcsAndExpecteds.length % 2, 0);\n  for (var i = 0; i < funcsAndExpecteds.length; i++) {\n    var f = funcsAndExpecteds[i];\n    i++;\n    var expected = funcsAndExpecteds[i];\n    checkClauses(test, f, expected);\n  }\n};\n\nTinytest.add(\"logic-solver - bad NumTerms\", function (test) {\n  test.throws(function () {\n    var s = new Logic.Solver;\n    s.require(3);\n  });\n\n  test.throws(function () {\n    var s = new Logic.Solver;\n    s.require(-3);\n  });\n\n  test.throws(function () {\n    var s = new Logic.Solver;\n    s.require(0);\n  });\n\n  test.throws(function () {\n    var s = new Logic.Solver;\n    s.require(Logic.or(3));\n  });\n});\n\nTinytest.add(\"logic-solver - true and false\", function (test) {\n  runClauseTests(test, [\n    // Clauses that forbid $F and require $T are automatically\n    // generated as the first two clauses.  Using each of them\n    // causes the relevant clause to be included in the output.\n    function (s) {\n      s.require(Logic.or(Logic.TRUE, Logic.not(Logic.TRUE)));\n    },\n    [\"$T\", \"$T v -$T\"],\n    function (s) {\n      s.require(Logic.or(Logic.not(Logic.TRUE),\n                         Logic.not(Logic.FALSE)));\n    },\n    [\"-$F\", \"$T\", \"-$T v -$F\"],\n    // requiring or forbidding $T, $F, or the negation of one\n    // of those is optimizated.  this is helpful when formulas\n    // expand to one of these (e.g. Logic.and() => $T => []).\n    function (s) { s.require(Logic.TRUE); }, [],\n    function (s) { s.require(Logic.FALSE); }, [\"\"],\n    function (s) { s.require(Logic.not(Logic.TRUE)); }, [\"\"],\n    function (s) { s.require(Logic.not(Logic.FALSE)); }, [],\n    function (s) { s.forbid(Logic.TRUE); }, [\"\"],\n    function (s) { s.forbid(Logic.FALSE); }, [],\n    function (s) { s.forbid(Logic.not(Logic.TRUE)); }, [],\n    function (s) { s.forbid(Logic.not(Logic.FALSE)); }, [\"\"]\n  ]);\n});\n\nTinytest.add(\"logic-solver - Logic.or\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      s.require(Logic.or('A', 'B'));\n    },\n    [\"A v B\"],\n    function (s) {\n      s.require(Logic.or(['A', 'B']));\n    },\n    [\"A v B\"],\n    function (s) {\n      s.require(Logic.or(['A'], ['B']));\n    },\n    [\"A v B\"],\n    function (s) {\n      s.require('A');\n      s.require(Logic.or('-C', 'D', 3));\n    },\n    [\"A\", \"-C v D v A\"],\n    function (s) {\n      s.forbid(Logic.or('A', '-B'));\n    },\n    [\"-A\", \"B\"],\n    function (s) {\n      s.forbid(Logic.or());\n    },\n    [],\n    function (s) {\n      s.require(Logic.or());\n    },\n    [\"\"]\n  ]);\n});\n\nTinytest.add(\"logic-solver - Formula sharing\", function (test) {\n  var f = Logic.or(\"A\", \"B\");\n  var s1 = new Logic.Solver;\n  var s2 = new Logic.Solver;\n\n  s1.require(\"X\");\n  s1.require(f);\n\n  s2.forbid(f);\n\n  test.equal(s1._clauseData(), [[3], [4, 5]]);\n  test.equal(s2._clauseData(), [[-3], [-4]]);\n});\n\nTinytest.add(\"logic-solver - nested Logic.or\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      s.require(Logic.or(Logic.or(\"A\", \"B\"), Logic.or(\"C\", \"D\")));\n    },\n    [\"A v B v -$or1\", \"C v D v -$or2\", \"$or1 v $or2\"]\n  ]);\n});\n\nTinytest.add(\"logic-solver - Logic.not term\", function (test) {\n  test.equal(Logic.not(\"foo\"), \"-foo\");\n  test.equal(Logic.not(\"-foo\"), \"foo\");\n  test.equal(Logic.not(\"--foo\"), \"-foo\");\n  test.equal(Logic.not(1), -1);\n  test.equal(Logic.not(-1), 1);\n});\n\nTinytest.add(\"logic-solver - Logic.not formula\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      s.require(Logic.not(Logic.or(\"A\", \"B\")));\n    },\n    [\"-A\", \"-B\"],\n    function (s) {\n      s.forbid(Logic.not(Logic.or(\"A\", \"B\")));\n    },\n    [\"A v B\"],\n    function (s) {\n      s.require(Logic.or(Logic.not(Logic.or(\"A\", \"B\")), \"C\"));\n    },\n    [\"-A v $or1\", \"-B v $or1\", \"-$or1 v C\"]\n  ]);\n});\n\nTinytest.add(\"logic-solver - Require/forbid after formula gen\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      // Use a formula in the positive and then require it.  Requiring\n      // the formula does not regenerate its clauses, it just requires\n      // the formula's variable ($or1).\n      var f = Logic.or(\"A\", \"B\");\n      s.require(Logic.or(f, \"C\"));\n      s.require(f);\n    },\n    [\"A v B v -$or1\",\"$or1 v C\",\"$or1\"]\n  ]);\n\n  runClauseTests(test, [\n    function (s) {\n      // Use a formula in the posiive and then forbid it.\n      // Forbidding a formula that has not been used in the\n      // negative before requires generating new clauses.\n      var f = Logic.or(\"A\", \"B\");\n      s.require(Logic.or(f, \"C\"));\n      s.forbid(f);\n    },\n    [\"A v B v -$or1\",\"$or1 v C\",\"-A v $or1\",\"-B v $or1\",\"-$or1\"]\n  ]);\n\n  runClauseTests(test, [\n    function (s) {\n      // Use a formula in the negative and then forbid it.\n      var f = Logic.or(\"A\", \"B\");\n      s.require(Logic.or(Logic.not(f), \"C\"));\n      s.forbid(f);\n    },\n    [\"-A v $or1\",\"-B v $or1\",\"-$or1 v C\",\"-$or1\"]\n  ]);\n\n  runClauseTests(test, [\n    function (s) {\n      // Use a formula in the negative and then require it.\n      var f = Logic.or(\"A\", \"B\");\n      s.require(Logic.or(Logic.not(f), \"C\"));\n      s.require(f);\n    },\n    [\"-A v $or1\",\"-B v $or1\",\"-$or1 v C\",\"A v B v -$or1\",\"$or1\"]\n  ]);\n\n  runClauseTests(test, [\n    function (s) {\n      var f = Logic.or(\"A\", \"B\");\n      s.require(Logic.and(f, \"C\"));\n      s.require(f);\n    },\n    // Arguments to AND are generated in place, meaning that if `f`\n    // is used elsewhere, its clauses will be generated twice.\n    // Oh well.  It's a trade-off.  The same applies to OR when\n    // generating the false case.\n    [\"A v B\",\n     \"C\",\n     \"A v B\"]\n  ]);\n});\n\n\nTinytest.add(\"logic-solver - Logic.and\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      s.require(Logic.and('A', 'B'));\n    },\n    [\"A\", \"B\"],\n    function (s) {\n      s.require(Logic.and(['A', 'B']));\n    },\n    [\"A\", \"B\"],\n    function (s) {\n      s.require(Logic.and(['A'], ['-B'], 'C'));\n    },\n    [\"A\", \"-B\", \"C\"],\n    function (s) {\n      s.forbid(Logic.and('A', '-B', 'C'));\n    },\n    [\"-A v B v -C\"],\n    function (s) {\n      s.forbid(Logic.and());\n    },\n    [\"\"],\n    function (s) {\n      s.require(Logic.and());\n    },\n    [],\n    function (s) {\n      s.require(Logic.or(Logic.and(Logic.or(\"A\", \"B\"),\n                                   Logic.or(\"-A\", \"C\")),\n                         \"-D\"));\n    },\n    [\"A v B v -$and1\",\n     \"-A v C v -$and1\",\n     \"$and1 v -D\"],\n    function (s) {\n      s.require(Logic.or(Logic.not(Logic.and(Logic.or(\"A\", \"B\"),\n                                             Logic.or(\"-A\", \"C\"))),\n                         \"-D\"));\n    },\n    [\"-$or1 v -$or2 v $and1\",\n     \"A v $or2\",\n     \"-C v $or2\",\n     \"-A v $or1\",\n     \"-B v $or1\",\n     \"-$and1 v -D\"]\n  ]);\n});\n\nTinytest.add(\"logic-solver - Logic.xor\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      s.require(Logic.xor()); },\n    [\"\"],\n    function (s) {\n      s.forbid(Logic.xor()); },\n    [],\n    function (s) {\n      s.require(Logic.or(Logic.xor(), Logic.xor())); },\n    [\"-$F\", \"$F v $F\"],\n    function (s) {\n      s.require(Logic.xor(\"A\")); },\n    [\"A\"],\n    function (s) {\n      s.forbid(Logic.xor(\"A\")); },\n    [\"-A\"],\n    function (s) {\n      s.require(Logic.xor(\"A\", \"B\")); },\n    [\"A v B\", \"-A v -B\"],\n    function (s) {\n      s.forbid(Logic.xor(\"A\", \"B\")); },\n    [\"A v -B\", \"-A v B\"],\n    function (s) {\n      s.require(Logic.xor([\"A\", []], [\"B\"], [])); },\n    [\"A v B\", \"-A v -B\"],\n    function (s) {\n      s.require(Logic.xor(\"A\", \"B\", \"C\")); },\n    [\"A v B v C\", \"A v -B v -C\", \"-A v B v -C\", \"-A v -B v C\"],\n    function (s) {\n      s.forbid(Logic.xor(\"A\", \"B\", \"C\"));  },\n    [\"-A v -B v -C\", \"-A v B v C\", \"A v -B v C\", \"A v B v -C\"],\n    function (s) {\n      s.require(Logic.xor(\"A\", \"B\", \"C\", \"D\")); },\n    [\"A v B v C v -$xor1\",\n     \"A v -B v -C v -$xor1\",\n     \"-A v B v -C v -$xor1\",\n     \"-A v -B v C v -$xor1\",\n     \"$xor1 v D\",\n     \"-A v -B v -C v $xor1\",\n     \"-A v B v C v $xor1\",\n     \"A v -B v C v $xor1\",\n     \"A v B v -C v $xor1\",\n     \"-$xor1 v -D\"],\n    function (s) {\n      s.forbid(Logic.xor(\"A\", \"B\", \"C\", \"D\")); },\n    [\"A v B v C v -$xor1\",\n     \"A v -B v -C v -$xor1\",\n     \"-A v B v -C v -$xor1\",\n     \"-A v -B v C v -$xor1\",\n     \"$xor1 v -D\",\n     \"-A v -B v -C v $xor1\",\n     \"-A v B v C v $xor1\",\n     \"A v -B v C v $xor1\",\n     \"A v B v -C v $xor1\",\n     \"-$xor1 v D\"],\n    function (s) {\n      s.require(Logic.xor(\"A\", \"B\", \"C\", \"D\", \"E\")); },\n    [\"A v B v C v -$xor1\",\n     \"A v -B v -C v -$xor1\",\n     \"-A v B v -C v -$xor1\",\n     \"-A v -B v C v -$xor1\",\n     \"D v E v -$xor2\",\n     \"-D v -E v -$xor2\",\n     \"$xor1 v $xor2\",\n     \"-A v -B v -C v $xor1\",\n     \"-A v B v C v $xor1\",\n     \"A v -B v C v $xor1\",\n     \"A v B v -C v $xor1\",\n     \"D v -E v $xor2\",\n     \"-D v E v $xor2\",\n     \"-$xor1 v -$xor2\"],\n    function (s) {\n      s.forbid(Logic.xor(\"A\", \"B\", \"C\", \"D\", \"E\")); },\n    [\"A v B v C v -$xor1\",\n     \"A v -B v -C v -$xor1\",\n     \"-A v B v -C v -$xor1\",\n     \"-A v -B v C v -$xor1\",\n     \"D v -E v $xor2\",\n     \"-D v E v $xor2\",\n     \"$xor1 v -$xor2\",\n     \"-A v -B v -C v $xor1\",\n     \"-A v B v C v $xor1\",\n     \"A v -B v C v $xor1\",\n     \"A v B v -C v $xor1\",\n     \"D v E v -$xor2\",\n     \"-D v -E v -$xor2\",\n     \"-$xor1 v $xor2\"]\n  ]);\n});\n\nTinytest.add(\"logic-solver - require/forbid generation\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      var f = Logic.and(\"A\", \"B\");\n      s.require(Logic.or(f, \"C\"));\n      s.forbid(f);\n    },\n    [\"A v -$and1\", \"B v -$and1\", \"$and1 v C\", \"-A v -B v $and1\", \"-$and1\"],\n    function (s) {\n      var f = Logic.and(\"A\", \"B\");\n      s.require(Logic.or(Logic.not(f), \"C\"));\n      s.require(f);\n    },\n    [\"-A v -B v $and1\", \"-$and1 v C\", \"A v -$and1\", \"B v -$and1\", \"$and1\"],\n    function (s) {\n      var f = Logic.and(\"A\", \"B\");\n      s.require(f);\n      s.require(f);\n    },\n    [\"A\", \"B\"],\n    function (s) {\n      var f = Logic.and(\"A\", \"B\");\n      s.forbid(f);\n      s.forbid(f);\n    },\n    [\"-A v -B\"],\n    function (s) {\n      var f = Logic.and(\"A\", \"B\");\n      s.require(f);\n      s.forbid(f);\n      s.forbid(f);\n    },\n    [\"A\", \"B\", \"\"],\n    function (s) {\n      var f = Logic.and(\"A\", \"B\");\n      s.forbid(f);\n      s.require(f);\n      s.require(f);\n    },\n    [\"-A v -B\", \"\"],\n    function (s) {\n      var f = Logic.and(\"A\", \"B\");\n      s.require(f);\n      s.require(Logic.or(f, \"C\"));\n    },\n    [\"$T\", \"A\", \"B\", \"$T v C\"],\n    function (s) {\n      var f = Logic.and(\"A\", \"B\");\n      s.require(f);\n      s.require(Logic.or(Logic.not(f), \"C\"));\n    },\n    [\"$T\", \"A\", \"B\", \"-$T v C\"],\n    function (s) {\n      var f = Logic.and(\"A\", \"B\");\n      s.forbid(f);\n      s.require(Logic.or(Logic.not(f), \"C\"));\n    },\n    [\"-$F\", \"-A v -B\", \"-$F v C\"],\n    function (s) {\n      var f = Logic.and(\"A\", \"B\");\n      s.require(f);\n      s.forbid(f);\n      s.require(Logic.or(f, \"C\"));\n    },\n    [\"$T\", \"A\", \"B\", \"\", \"$T v C\"],\n    function (s) {\n      var f = Logic.and(\"A\", \"B\");\n      s.forbid(f);\n      s.require(f);\n      s.require(Logic.or(f, \"C\"));\n    },\n    [\"$T\", \"-A v -B\", \"\", \"$T v C\"]\n  ]);\n});\n\nTinytest.add(\"logic-solver - Logic.atMostOne\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      s.require(Logic.atMostOne()); },\n    [],\n    function (s) {\n      s.forbid(Logic.atMostOne()); },\n    [\"\"],\n    function (s) {\n      s.require(Logic.atMostOne(\"A\")); },\n    [],\n    function (s) {\n      s.forbid(Logic.atMostOne(\"A\")); },\n    [\"\"],\n    function (s) {\n      s.require(Logic.atMostOne(\"A\", \"B\")); },\n    [\"-A v -B\"],\n    function (s) {\n      s.forbid(Logic.atMostOne(\"A\", \"B\")); },\n    [\"A\", \"B\"],\n    function (s) {\n      s.require(Logic.atMostOne(\"A\", \"B\", \"C\")); },\n    [\"-A v -B\", \"-A v -C\", \"-B v -C\"],\n    function (s) {\n      s.forbid(Logic.atMostOne(\"A\", \"B\", \"C\")); },\n    [\"A v B\", \"A v C\", \"B v C\"],\n    function (s) {\n      s.require(Logic.atMostOne(\"A\", \"B\", \"C\", \"D\")); },\n    // If D is true, then all of A,B,C must be false.\n    // Two of A,B,C must be false.\n    [\"-A v $or1\",\n     \"-B v $or1\",\n     \"-C v $or1\",\n     \"-$or1 v -D\",\n     \"-A v -B\",\n     \"-A v -C\",\n     \"-B v -C\"],\n    function (s) {\n      s.forbid(Logic.atMostOne(\"A\", \"B\", \"C\", \"D\")); },\n    // If any two of A,B,C are false (lines 3,4,5), then we'll need\n    // one of A,B,C and D to be true (lines 1,2 by implication of\n    // line 6).  (This isn't the reasoning that generated the clauses,\n    // but it's one way to think of it.)\n    [\"A v B v C v $atMostOne1\",\n     \"D v $atMostOne1\",\n     \"A v B v $atMostOne2\",\n     \"A v C v $atMostOne2\",\n     \"B v C v $atMostOne2\",\n     \"-$atMostOne1 v -$atMostOne2\"],\n    function (s) {\n      s.require(Logic.atMostOne(\"A\", \"B\", \"C\", \"D\", \"E\")); },\n    [\"-A v $or1\",\n     \"-B v $or1\",\n     \"-C v $or1\",\n     \"-D v $or2\",\n     \"-E v $or2\",\n     \"-$or1 v -$or2\",\n     \"-A v -B\",\n     \"-A v -C\",\n     \"-B v -C\",\n     \"-D v -E\"],\n    function (s) {\n      s.forbid(Logic.atMostOne(\"A\", \"B\", \"C\", \"D\", \"E\")); },\n    [\"A v B v C v $atMostOne1\",\n     \"D v E v $atMostOne1\",\n     \"A v B v $atMostOne2\",\n     \"A v C v $atMostOne2\",\n     \"B v C v $atMostOne2\",\n     \"D v $atMostOne3\",\n     \"E v $atMostOne3\",\n     \"-$atMostOne1 v -$atMostOne2 v -$atMostOne3\"]\n  ]);\n});\n\nTinytest.add(\"logic-solver - Logic.implies, Logic.equiv\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      s.require(Logic.implies(\"A\", \"B\")); },\n    [\"-A v B\"],\n    function (s) {\n      s.forbid(Logic.implies(\"A\", \"B\")); },\n    [\"A\", \"-B\"],\n    function (s) {\n      s.require(Logic.or(Logic.implies(\"A\", \"B\"), \"C\")); },\n    [\"-A v B v -$implies1\", \"$implies1 v C\"],\n    function (s) {\n      s.require(Logic.or(Logic.implies(Logic.or(\"A\", \"D\"), \"B\"), \"C\")); },\n    [\"-$or1 v B v -$implies1\",\n     \"-A v $or1\",\n     \"-D v $or1\",\n     \"$implies1 v C\"],\n    function (s) {\n      s.require(Logic.equiv(\"A\", \"B\")); },\n    [\"A v -B\",\n     \"-A v B\"],\n    function (s) {\n      s.forbid(Logic.equiv(\"A\", \"B\")); },\n    [\"A v B\",\n     \"-A v -B\"],\n    function (s) {\n      s.require(Logic.equiv(Logic.or(\"A\", \"B\"),\n                           Logic.or(\"C\", \"D\"))); },\n    [\"A v B v -$or1\",\n     \"-C v $or2\",\n     \"-D v $or2\",\n     \"$or1 v -$or2\",\n     \"-A v $or1\",\n     \"-B v $or1\",\n     \"C v D v -$or2\",\n     \"-$or1 v $or2\"]\n  ]);\n});\n\nTinytest.add(\"logic-solver - Logic.exactlyOne\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      s.require(Logic.exactlyOne()); },\n    [\"\"],\n    function (s) {\n      s.forbid(Logic.exactlyOne()); },\n    [],\n    function (s) {\n      s.require(Logic.exactlyOne(\"A\")); },\n    [\"A\"],\n    function (s) {\n      s.forbid(Logic.exactlyOne(\"A\")); },\n    [\"-A\"],\n    function (s) {\n      s.require(Logic.exactlyOne(\"A\", \"B\")); },\n    [\"A v B\", \"-A v -B\"],\n    function (s) {\n      s.forbid(Logic.exactlyOne(\"A\", \"B\")); },\n    [\"A v -B\", \"-A v B\"],\n    function (s) {\n      s.require(Logic.exactlyOne(\"A\", \"B\", \"C\")); },\n    [\"-A v -B\",\n     \"-A v -C\",\n     \"-B v -C\",\n     \"A v B v C\"],\n    function (s) {\n      s.forbid(Logic.exactlyOne(\"A\", \"B\", \"C\")); },\n    [\"A v B v $atMostOne1\",\n     \"A v C v $atMostOne1\",\n     \"B v C v $atMostOne1\",\n     \"-A v $or1\",\n     \"-B v $or1\",\n     \"-C v $or1\",\n     \"-$atMostOne1 v -$or1\"]\n  ]);\n});\n\nvar equalBitFormulas = function (test, bits1, bits2) {\n  test.isTrue(bits1 instanceof Logic.Bits);\n  test.isTrue(bits2 instanceof Logic.Bits);\n  // the elements of bits1 and bits2 will have to be\n  // terms (or the same Formula objects) for this to\n  // compare by value\n  test.equal(bits1.bits, bits2.bits);\n};\n\nTinytest.add(\"logic-solver - Logic.constantBits\", function (test) {\n  equalBitFormulas(test, Logic.constantBits(0), new Logic.Bits([]));\n  equalBitFormulas(test, Logic.constantBits(1), new Logic.Bits([\"$T\"]));\n  equalBitFormulas(test, Logic.constantBits(2), new Logic.Bits([\"$F\", \"$T\"]));\n  equalBitFormulas(test, Logic.constantBits(3), new Logic.Bits([\"$T\", \"$T\"]));\n  equalBitFormulas(test, Logic.constantBits(4), new Logic.Bits([\"$F\", \"$F\", \"$T\"]));\n  equalBitFormulas(test, Logic.constantBits(5), new Logic.Bits([\"$T\", \"$F\", \"$T\"]));\n});\n\nTinytest.add(\"logic-solver - Logic.equalBits\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      s.require(Logic.equalBits(new Logic.Bits([]),\n                                new Logic.Bits([]))); },\n    [],\n    function (s) {\n      s.forbid(Logic.equalBits(new Logic.Bits([]),\n                               new Logic.Bits([]))); },\n    [\"\"],\n    function (s) {\n      s.require(Logic.equalBits(new Logic.Bits([\"A\"]),\n                                new Logic.Bits([]))); },\n    [\"-A\"],\n    function (s) {\n      s.require(Logic.equalBits(new Logic.Bits([]),\n                                new Logic.Bits([\"A\"]))); },\n    [\"-A\"],\n    function (s) {\n      s.forbid(Logic.equalBits(new Logic.Bits([\"A\"]),\n                               new Logic.Bits([]))); },\n    [\"A\"],\n    function (s) {\n      s.forbid(Logic.equalBits(new Logic.Bits([]),\n                               new Logic.Bits([\"A\"]))); },\n    [\"A\"],\n    function (s) {\n      s.require(Logic.equalBits(new Logic.Bits([\"A\", \"B\", \"C\"]),\n                                new Logic.Bits([]))); },\n    [\"-A\", \"-B\", \"-C\"],\n    function (s) {\n      s.require(Logic.equalBits(new Logic.Bits([]),\n                                new Logic.Bits([\"A\", \"B\", \"C\"]))); },\n    [\"-A\", \"-B\", \"-C\"],\n    function (s) {\n      s.forbid(Logic.equalBits(new Logic.Bits([\"A\", \"B\", \"C\"]),\n                               new Logic.Bits([]))); },\n    [\"A v B v C\"],\n    function (s) {\n      s.forbid(Logic.equalBits(new Logic.Bits([]),\n                               new Logic.Bits([\"A\", \"B\", \"C\"]))); },\n    [\"A v B v C\"],\n    function (s) {\n      s.require(Logic.equalBits(new Logic.Bits([\"A\"]),\n                                new Logic.Bits([\"B\"]))); },\n    [\"A v -B\", \"-A v B\"],\n    function (s) {\n      s.forbid(Logic.equalBits(new Logic.Bits([\"A\"]),\n                               new Logic.Bits([\"B\"]))); },\n    [\"A v B\", \"-A v -B\"],\n    function (s) {\n      s.require(Logic.equalBits(new Logic.Bits([\"A\", \"B\"]),\n                                new Logic.Bits([\"X\", \"Y\"]))); },\n    [\"A v -X\", \"-A v X\",\n     \"B v -Y\", \"-B v Y\"],\n    function (s) {\n      s.forbid(Logic.equalBits(new Logic.Bits([\"A\", \"B\"]),\n                               new Logic.Bits([\"X\", \"Y\"]))); },\n    [\"A v X v $equiv1\",\n     \"-A v -X v $equiv1\",\n     \"B v Y v $equiv2\",\n     \"-B v -Y v $equiv2\",\n     \"-$equiv1 v -$equiv2\"],\n    function (s) {\n      s.require(Logic.equalBits(new Logic.Bits([\"A\", \"B\"]),\n                                new Logic.Bits([\"X\"]))); },\n    [\"A v -X\", \"-A v X\", \"-B\"],\n    function (s) {\n      s.forbid(Logic.equalBits(new Logic.Bits([\"A\", \"B\"]),\n                               new Logic.Bits([\"X\"]))); },\n    [\"A v X v $equiv1\",\n     \"-A v -X v $equiv1\",\n     \"-$equiv1 v B\"],\n    function (s) {\n      s.require(Logic.equalBits(new Logic.Bits([\"A\"]),\n                                new Logic.Bits([\"X\", \"Y\"]))); },\n    [\"A v -X\", \"-A v X\", \"-Y\"],\n    function (s) {\n      s.forbid(Logic.equalBits(new Logic.Bits([\"A\"]),\n                               new Logic.Bits([\"X\", \"Y\"]))); },\n    [\"A v X v $equiv1\",\n     \"-A v -X v $equiv1\",\n     \"-$equiv1 v Y\"],\n    function (s) {\n      s.require(Logic.equalBits(new Logic.Bits([Logic.or(\"A\", \"B\")]),\n                                new Logic.Bits([Logic.or(\"C\", \"D\")]))); },\n    [\"A v B v -$or1\",\n     \"-C v $or2\",\n     \"-D v $or2\",\n     \"$or1 v -$or2\",\n     \"-A v $or1\",\n     \"-B v $or1\",\n     \"C v D v -$or2\",\n     \"-$or1 v $or2\"]\n  ]);\n});\n\nTinytest.add(\"logic-solver - Logic.lessThan[OrEqual]\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      s.require(Logic.lessThan(new Logic.Bits([]),\n                               new Logic.Bits([]))); },\n    [\"\"],\n    function (s) {\n      s.require(Logic.lessThanOrEqual(new Logic.Bits([]),\n                                      new Logic.Bits([]))); },\n    [],\n    function (s) {\n      s.forbid(Logic.lessThan(new Logic.Bits([]),\n                              new Logic.Bits([]))); },\n    [],\n    function (s) {\n      s.forbid(Logic.lessThanOrEqual(new Logic.Bits([]),\n                                     new Logic.Bits([]))); },\n    [\"\"],\n    function (s) {\n      s.require(Logic.lessThan(new Logic.Bits([\"A\"]),\n                               new Logic.Bits([]))); },\n    [\"\"],\n    function (s) {\n      s.require(Logic.lessThanOrEqual(new Logic.Bits([\"A\"]),\n                                      new Logic.Bits([]))); },\n    [\"-A\"],\n    function (s) {\n      s.forbid(Logic.lessThan(new Logic.Bits([\"A\"]),\n                              new Logic.Bits([]))); },\n    [],\n    function (s) {\n      s.forbid(Logic.lessThanOrEqual(new Logic.Bits([\"A\"]),\n                                     new Logic.Bits([]))); },\n    [\"A\"],\n    function (s) {\n      s.require(Logic.lessThan(new Logic.Bits([]),\n                               new Logic.Bits([\"A\"]))); },\n    [\"A\"],\n    function (s) {\n      s.require(Logic.lessThanOrEqual(new Logic.Bits([]),\n                                      new Logic.Bits([\"A\"]))); },\n    [],\n    function (s) {\n      s.forbid(Logic.lessThan(new Logic.Bits([]),\n                              new Logic.Bits([\"A\"]))); },\n    [\"-A\"],\n    function (s) {\n      s.forbid(Logic.lessThanOrEqual(new Logic.Bits([]),\n                                     new Logic.Bits([\"A\"]))); },\n    [\"\"],\n    function (s) {\n      s.require(Logic.lessThan(new Logic.Bits([\"A\"]),\n                               new Logic.Bits([\"B\"]))); },\n    [\"-A v B\",\n     \"A v B\",\n     \"-A v -B\"],\n    function (s) {\n      s.require(Logic.lessThanOrEqual(new Logic.Bits([\"A\"]),\n                                      new Logic.Bits([\"B\"]))); },\n    [\"-A v B\"],\n    function (s) {\n      s.forbid(Logic.lessThan(new Logic.Bits([\"A\"]),\n                              new Logic.Bits([\"B\"]))); },\n    [\"-B v A\"],\n    function (s) {\n      s.forbid(Logic.lessThanOrEqual(new Logic.Bits([\"A\"]),\n                                     new Logic.Bits([\"B\"]))); },\n    [\"-B v A\",\n     \"B v A\",\n     \"-B v -A\"],\n    function (s) {\n      s.require(Logic.lessThan(new Logic.Bits([\"B\", \"A\"]),\n                               new Logic.Bits([\"Y\", \"X\"]))); },\n    [\"-A v X\",\n     \"A v X v -$xor1\",\n     \"-A v -X v -$xor1\",\n     \"$xor1 v -B v Y\",\n     \"B v Y v -$xor2\",\n     \"-B v -Y v -$xor2\",\n     \"$xor2 v $xor1\"],\n    function (s) {\n      s.require(Logic.lessThanOrEqual(new Logic.Bits([\"B\", \"A\"]),\n                                      new Logic.Bits([\"Y\", \"X\"]))); },\n    [\"-A v X\",\n     \"A v X v -$xor1\",\n     \"-A v -X v -$xor1\",\n     \"$xor1 v -B v Y\"],\n    function (s) {\n      s.forbid(Logic.lessThan(new Logic.Bits([\"B\", \"A\"]),\n                              new Logic.Bits([\"Y\", \"X\"]))); },\n    [\"-X v A\",\n     \"X v A v -$xor1\",\n     \"-X v -A v -$xor1\",\n     \"$xor1 v -Y v B\"],\n    function (s) {\n      s.forbid(Logic.lessThanOrEqual(new Logic.Bits([\"B\", \"A\"]),\n                                     new Logic.Bits([\"Y\", \"X\"]))); },\n    [\"-X v A\",\n     \"X v A v -$xor1\",\n     \"-X v -A v -$xor1\",\n     \"$xor1 v -Y v B\",\n     \"Y v B v -$xor2\",\n     \"-Y v -B v -$xor2\",\n     \"$xor2 v $xor1\"],\n    function (s) {\n      s.require(Logic.lessThan(new Logic.Bits([\"A\"]),\n                               new Logic.Bits([\"Y\", \"X\"]))); },\n    [\"X v -A v Y\",\n     \"A v Y v -$xor1\",\n     \"-A v -Y v -$xor1\",\n     \"$xor1 v X\"],\n    function (s) {\n      s.require(Logic.lessThanOrEqual(new Logic.Bits([\"A\"]),\n                                      new Logic.Bits([\"Y\", \"X\"]))); },\n    [\"X v -A v Y\"],\n    function (s) {\n      s.forbid(Logic.lessThan(new Logic.Bits([\"A\"]),\n                              new Logic.Bits([\"Y\", \"X\"]))); },\n    [\"-X\",\n     \"-Y v A\"],\n    function (s) {\n      s.forbid(Logic.lessThanOrEqual(new Logic.Bits([\"A\"]),\n                                     new Logic.Bits([\"Y\", \"X\"]))); },\n    [\"-X\",\n     \"-Y v A\",\n     \"Y v A\",\n     \"-Y v -A\"],\n    function (s) {\n      s.require(Logic.lessThan(new Logic.Bits([\"B\", \"A\"]),\n                               new Logic.Bits([\"X\"]))); },\n    [\"-A\",\n     \"-B v X\",\n     \"B v X\",\n     \"-B v -X\"],\n    function (s) {\n      s.require(Logic.lessThanOrEqual(new Logic.Bits([\"B\", \"A\"]),\n                                      new Logic.Bits([\"X\"]))); },\n    [\"-A\",\n     \"-B v X\"],\n    function (s) {\n      s.forbid(Logic.lessThan(new Logic.Bits([\"B\", \"A\"]),\n                              new Logic.Bits([\"X\"]))); },\n    [\"A v -X v B\"],\n    function (s) {\n      s.forbid(Logic.lessThanOrEqual(new Logic.Bits([\"B\", \"A\"]),\n                                     new Logic.Bits([\"X\"]))); },\n    [\"A v -X v B\",\n     \"X v B v -$xor1\",\n     \"-X v -B v -$xor1\",\n     \"$xor1 v A\"],\n    function (s) {\n      s.require(Logic.lessThan(new Logic.Bits([\"C\", \"B\", \"A\"]),\n                               new Logic.Bits([\"Z\", \"Y\", \"X\"]))); },\n    [\"-A v X\",\n     \"A v X v -$xor1\",\n     \"-A v -X v -$xor1\",\n     \"$xor1 v -B v Y\",\n     \"B v Y v -$xor2\",\n     \"-B v -Y v -$xor2\",\n     \"$xor2 v $xor1 v -C v Z\",\n     \"C v Z v -$xor3\",\n     \"-C v -Z v -$xor3\",\n     \"$xor3 v $xor2 v $xor1\"],\n    function (s) {\n      s.require(Logic.lessThanOrEqual(new Logic.Bits([\"C\", \"B\", \"A\"]),\n                                      new Logic.Bits([\"Z\", \"Y\", \"X\"]))); },\n    [\"-A v X\",\n     \"A v X v -$xor1\",\n     \"-A v -X v -$xor1\",\n     \"$xor1 v -B v Y\",\n     \"B v Y v -$xor2\",\n     \"-B v -Y v -$xor2\",\n     \"$xor2 v $xor1 v -C v Z\"],\n    function (s) {\n      s.forbid(Logic.lessThan(new Logic.Bits([\"C\", \"B\", \"A\"]),\n                              new Logic.Bits([\"Z\", \"Y\", \"X\"]))); },\n    [\"-X v A\",\n     \"X v A v -$xor1\",\n     \"-X v -A v -$xor1\",\n     \"$xor1 v -Y v B\",\n     \"Y v B v -$xor2\",\n     \"-Y v -B v -$xor2\",\n     \"$xor2 v $xor1 v -Z v C\"],\n    function (s) {\n      s.forbid(Logic.lessThanOrEqual(new Logic.Bits([\"C\", \"B\", \"A\"]),\n                                     new Logic.Bits([\"Z\", \"Y\", \"X\"]))); },\n    [\"-X v A\",\n     \"X v A v -$xor1\",\n     \"-X v -A v -$xor1\",\n     \"$xor1 v -Y v B\",\n     \"Y v B v -$xor2\",\n     \"-Y v -B v -$xor2\",\n     \"$xor2 v $xor1 v -Z v C\",\n     \"Z v C v -$xor3\",\n     \"-Z v -C v -$xor3\",\n     \"$xor3 v $xor2 v $xor1\"]\n  ]);\n});\n\nTinytest.add(\"logic-solver - half/full sum/carry\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      s.require(new Logic.HalfAdderSum(\"A\", \"B\")); },\n    [\"A v B\", \"-A v -B\"],\n    function (s) {\n      s.forbid(new Logic.HalfAdderSum(\"A\", \"B\")); },\n    [\"A v -B\", \"-A v B\"],\n    function (s) {\n      s.require(Logic.or(new Logic.HalfAdderSum(\"A\", \"B\"), \"C\")); },\n    [\"A v B v -$hsum1\",\n     \"-A v -B v -$hsum1\",\n     \"$hsum1 v C\"],\n    function (s) {\n      s.require(new Logic.HalfAdderCarry(\"A\", \"B\")); },\n    [\"A\", \"B\"],\n    function (s) {\n      s.forbid(new Logic.HalfAdderCarry(\"A\", \"B\")); },\n    [\"-A v -B\"],\n    function (s) {\n      s.require(Logic.or(new Logic.HalfAdderCarry(\"A\", \"B\"), \"C\")); },\n    [\"A v -$hcarry1\",\n     \"B v -$hcarry1\",\n     \"$hcarry1 v C\"]\n  ]);\n\n  runClauseTests(test, [\n    function (s) {\n      s.require(new Logic.FullAdderSum(\"A\", \"B\", \"C\")); },\n    [\"A v B v C\",\n     \"A v -B v -C\",\n     \"-A v B v -C\",\n     \"-A v -B v C\"],\n    function (s) {\n      s.forbid(new Logic.FullAdderSum(\"A\", \"B\", \"C\")); },\n    [\"-A v -B v -C\",\n     \"-A v B v C\",\n     \"A v -B v C\",\n     \"A v B v -C\"],\n    function (s) {\n      s.require(Logic.or(new Logic.FullAdderSum(\"A\", \"B\", \"C\"), \"D\")); },\n    [\"A v B v C v -$fsum1\",\n     \"A v -B v -C v -$fsum1\",\n     \"-A v B v -C v -$fsum1\",\n     \"-A v -B v C v -$fsum1\",\n     \"$fsum1 v D\"],\n    function (s) {\n      s.require(new Logic.FullAdderCarry(\"A\", \"B\", \"C\")); },\n    [\"A v B\",\n     \"A v C\",\n     \"B v C\"],\n    function (s) {\n      s.forbid(new Logic.FullAdderCarry(\"A\", \"B\", \"C\")); },\n    [\"-A v -B\",\n     \"-A v -C\",\n     \"-B v -C\"],\n    function (s) {\n      s.require(Logic.or(new Logic.FullAdderCarry(\"A\", \"B\", \"C\"), \"D\")); },\n    [\"A v B v -$fcarry1\",\n     \"A v C v -$fcarry1\",\n     \"B v C v -$fcarry1\",\n     \"$fcarry1 v D\"]\n  ]);\n});\n\nTinytest.add(\"logic-solver - sum of terms\", function (test) {\n  runClauseTests(test, [\n    function (s) {\n      s.require(\n        // XY = A + B + C\n        Logic.equalBits(new Logic.Bits([\"Y\", \"X\"]),\n                        Logic.sum(\"A\", \"B\", \"C\")));\n    },\n    [\"-A v -B v -C v $fsum1\",\n     \"-A v B v C v $fsum1\",\n     \"A v -B v C v $fsum1\",\n     \"A v B v -C v $fsum1\",\n     \"Y v -$fsum1\",\n     \"A v B v C v -$fsum1\",\n     \"A v -B v -C v -$fsum1\",\n     \"-A v B v -C v -$fsum1\",\n     \"-A v -B v C v -$fsum1\",\n     \"-Y v $fsum1\",\n     \"-A v -B v $fcarry1\",\n     \"-A v -C v $fcarry1\",\n     \"-B v -C v $fcarry1\",\n     \"X v -$fcarry1\",\n     \"A v B v -$fcarry1\",\n     \"A v C v -$fcarry1\",\n     \"B v C v -$fcarry1\",\n     \"-X v $fcarry1\"],\n    function (s) {\n      s.require(\n        // AB + C = XYZ\n        Logic.equalBits(new Logic.Bits([\"Z\", \"Y\", \"X\"]),\n                        Logic.sum(new Logic.Bits([\"B\", \"A\"]), \"C\")));\n    },\n    [\"B v -C v $hsum1\",\n     \"-B v C v $hsum1\",\n     \"Z v -$hsum1\",\n     \"B v C v -$hsum1\",\n     \"-B v -C v -$hsum1\",\n     \"-Z v $hsum1\",\n     \"A v -$hcarry2 v $hsum2\",\n     \"-A v $hcarry2 v $hsum2\",\n     \"B v -$hcarry2\",\n     \"C v -$hcarry2\",\n     \"-B v -C v $hcarry2\",\n     \"Y v -$hsum2\",\n     \"A v $hcarry2 v -$hsum2\",\n     \"-A v -$hcarry2 v -$hsum2\",\n     \"-Y v $hsum2\",\n     \"-A v -$hcarry2 v $hcarry1\",\n     \"X v -$hcarry1\",\n     \"A v -$hcarry1\",\n     \"B v -$hcarry1\",\n     \"C v -$hcarry1\",\n     \"-X v $hcarry1\"],\n    function (s) {\n      s.require(\n        // 8X + 15Y = ZABCDE\n        Logic.equalBits(new Logic.Bits([\"E\", \"D\", \"C\", \"B\", \"A\", \"Z\"]),\n                        Logic.weightedSum([\"X\", \"Y\"], [8, 15])));\n    },\n    // C, D, and E all = Y\n    // AB = X + Y\n    // Z = 0\n    [\"E v -Y\",\n     \"-E v Y\",\n     \"D v -Y\",\n     \"-D v Y\",\n     \"C v -Y\",\n     \"-C v Y\",\n     \"X v -Y v $hsum1\",\n     \"-X v Y v $hsum1\",\n     \"B v -$hsum1\",\n     \"X v Y v -$hsum1\",\n     \"-X v -Y v -$hsum1\",\n     \"-B v $hsum1\",\n     \"-X v -Y v $hcarry1\",\n     \"A v -$hcarry1\",\n     \"X v -$hcarry1\",\n     \"Y v -$hcarry1\",\n     \"-A v $hcarry1\",\n     \"-Z\"],\n    function (s) {\n      // A + B < 2\n      s.require(Logic.lessThan(Logic.sum(\"A\", \"B\"), Logic.constantBits(2)));\n    },\n    [\"-$F\",\n     \"$T\",\n     \"-A v -B v $hcarry1\",\n     \"-$hcarry1 v $T\",\n     \"$hcarry1 v $T v -$xor1\",\n     \"-$hcarry1 v -$T v -$xor1\",\n     \"A v -$hcarry1\",\n     \"B v -$hcarry1\",\n     \"A v -B v $hsum1\",\n     \"-A v B v $hsum1\",\n     \"$xor1 v -$hsum1 v $F\",\n     \"$hsum1 v $F v -$xor2\",\n     \"-$hsum1 v -$F v -$xor2\",\n     \"A v B v -$hsum1\",\n     \"-A v -B v -$hsum1\",\n     \"$xor2 v $xor1\"]\n  ]);\n});\n\nTinytest.add(\"logic-solver - MiniSat\", function (test) {\n  var M = new Logic._MiniSat;\n  // Unique solution is (1,2,3,4) = (0,1,0,0)\n  test.isTrue(M.addClause([-4]));\n  test.isTrue(M.addClause([-1, -2]));\n  test.isTrue(M.addClause([4, -1, 2]));\n  test.isTrue(M.addClause([1, 2, 3]));\n  test.isTrue(M.addClause([1, 2, -3, 4]));\n  test.isTrue(M.addClause([1, -2, -3]));\n  test.isTrue(M.solve());\n  test.equal(M.getSolution(), [null, false, true, false, false]);\n  M.addClause([1, -2, 3, 4]);\n  test.isFalse(M.solve());\n  test.isFalse(M.addClause([4]));\n});\n\nTinytest.add(\"logic-solver - MiniSat solveAssuming\", function (test) {\n  var M = new Logic._MiniSat;\n  M.ensureVar(1);\n  test.isTrue(M.solveAssuming(1));\n  test.equal(M.getSolution(), [null, true]);\n  test.isTrue(M.solveAssuming(1));\n  test.equal(M.getSolution(), [null, true]);\n  test.isTrue(M.addClause([-1]));\n  test.isTrue(M.addClause([2, -2]));\n  test.isTrue(M.solve());\n  test.equal(M.getSolution(), [null, false, false]); // empirically\n  test.isTrue(M.solveAssuming(2));\n  test.equal(M.getSolution(), [null, false, true]);\n  test.isTrue(M.solve());\n});\n\n\nTinytest.add(\"logic-solver - simple solve\", function (test) {\n  var s = new Logic.Solver;\n  // Unique solution is (A,B,C,D) = (0,1,0,0)\n  s.require(\"-D\");\n  s.require(Logic.or(\"-A\", \"-B\"));\n  s.require(Logic.or(\"D\", \"-A\", \"B\"));\n  s.require(Logic.or(\"A\", \"B\", \"C\"));\n  s.require(Logic.or(\"A\", \"B\", \"-C\", \"D\"));\n  s.require(Logic.or(\"A\", \"-B\", \"-C\"));\n  var sol = s.solve();\n  test.equal(s._minisat._clauses.length, 8); // includes \"$T\" and \"-$F\"\n  test.isTrue(sol);\n  test.equal(sol.getMap(), {\n    A: false, B: true, C: false, D: false\n  });\n  s.require(Logic.or(\"A\", \"-B\", \"C\", \"D\"));\n  var sol2 = s.solve();\n  test.isFalse(sol2);\n  // make sure we only added the new clause\n  test.equal(s._minisat._clauses.length, 9);\n});\n\nTinytest.add(\"logic-solver - getVarNum\", function (test) {\n  var s = new Logic.Solver();\n  s.require(\"A\");\n  var a = s.getVarNum(\"A\");\n  test.isTrue(a > 0); // this also confirms it's a number\n  test.equal(s.getVarNum(\"B\", true), 0); // noCreate = true\n  var b = s.getVarNum(\"B\");\n  test.notEqual(a, b);\n  var a2 = s.getVarNum(\"A\");\n  var b2 = s.getVarNum(\"B\");\n  test.equal(a, a2);\n  test.equal(b, b2);\n});\n\n\nTinytest.add(\"logic-solver - assumptions\", function (test) {\n  var s = new Logic.Solver;\n  s.getVarNum(\"A\");\n  s.getVarNum(\"B\");\n  s.getVarNum(\"C\");\n  s.getVarNum(\"D\");\n  // MiniSat could return any assignment of the variables here,\n  // but we happen to know that it uses all-false as a starting\n  // point for search.\n  test.equal(s.solve().getMap(), { A: false, B: false, C: false, D: false });\n\n  var atLeastOne = Logic.or(\"A\", \"B\", \"C\", \"D\");\n  // which of A,B,C,D comes back true is totally arbitrary, but it's\n  // deterministic as long as we don't touch anything.\n  test.equal(s.solveAssuming(atLeastOne).getMap(),\n             { A: false, B: true, C: false, D: false });\n  test.equal(formatLines(s._clauseStrings()),\n             formatLines([\"$or1 v -$assump1\",\n                          \"A v B v C v D v -$or1\"]));\n\n  // assume the same thing again\n  test.equal(s.solveAssuming(atLeastOne).getMap(),\n             { A: false, B: true, C: false, D: false });\n  test.equal(formatLines(s._clauseStrings()),\n             formatLines([\"$or1 v -$assump1\",\n                          \"A v B v C v D v -$or1\",\n                          \"$or1 v -$assump2\"]));\n\n  var none = Logic.and(\"-A\", \"-B\", \"-C\", \"-D\");\n  test.equal(s.solveAssuming(none).getMap(),\n             { A: false, B: false, C: false, D: false });\n  test.equal(formatLines(s._clauseStrings()),\n             formatLines([\"$or1 v -$assump1\",\n                          \"A v B v C v D v -$or1\",\n                          \"$or1 v -$assump2\",\n                          \"$and1 v -$assump3\",\n                          \"-A v -$and1\",\n                          \"-B v -$and1\",\n                          \"-C v -$and1\",\n                          \"-D v -$and1\"]));\n\n  // require a formula that was previously just temporarily assumed!\n  s.require(atLeastOne);\n  test.equal(s.solve().getMap(),\n             // any one could be true\n             { A: false, B: true, C: false, D: false });\n  test.equal(formatLines(s._clauseStrings()),\n             formatLines([\"$or1 v -$assump1\",\n                          \"A v B v C v D v -$or1\",\n                          \"$or1 v -$assump2\",\n                          \"$and1 v -$assump3\",\n                          \"-A v -$and1\",\n                          \"-B v -$and1\",\n                          \"-C v -$and1\",\n                          \"-D v -$and1\",\n                          \"$or1\"]));\n\n  test.equal(s.solveAssuming(\"D\").getMap(),\n             // at least D is true; other than that, anything goes\n             { A: false, B: true, C: false, D: true });\n  test.equal(formatLines(s._clauseStrings()),\n             formatLines([\"$or1 v -$assump1\",\n                          \"A v B v C v D v -$or1\",\n                          \"$or1 v -$assump2\",\n                          \"$and1 v -$assump3\",\n                          \"-A v -$and1\",\n                          \"-B v -$and1\",\n                          \"-C v -$and1\",\n                          \"-D v -$and1\",\n                          \"$or1\",\n                          \"D v -$assump4\"]));\n\n  var sum = Logic.sum(\"A\", \"B\", \"C\", \"D\");\n  var atLeast2 = Logic.greaterThanOrEqual(sum, Logic.constantBits(2));\n  test.equal(s.solveAssuming(atLeast2).getMap(),\n             // any two or more, including D\n             { A: false, B: true, C: false, D: true });\n  s.require(atLeast2);\n  var atLeast3 = Logic.greaterThanOrEqual(sum, Logic.constantBits(3));\n  test.equal(s.solveAssuming(atLeast3).getMap(),\n             // any three or more, including D\n             { A: true, B: true, C: false, D: true });\n  s.require(atLeast3);\n  var atLeast4 = Logic.greaterThanOrEqual(sum, Logic.constantBits(4));\n  test.equal(s.solveAssuming(atLeast4).getMap(),\n             { A: true, B: true, C: true, D: true });\n\n  s.forbid(\"C\");\n  test.equal(s.solve().getMap(),\n             { A: true, B: true, C: false, D: true });\n});\n\nTinytest.add(\"logic-solver - eight queens\", function (test) {\n  var boardSquare = function (r, c) {\n    return String(r) + ',' + String(c);\n  };\n\n  Logic._disablingTypeChecks(function () {\n\n    var solver = new Logic.Solver;\n    var nums = _.range(1, 9); // 1..8\n    _.each(nums, function (x) {\n      // one per row x, one per column x\n      solver.require(Logic.exactlyOne(_.map(nums, function (y) {\n        return boardSquare(x, y);\n      })));\n      solver.require(Logic.exactlyOne(_.map(nums, function (y) {\n        return boardSquare(y, x);\n      })));\n    });\n\n    // At most one queen per diagonal.  A diagonal\n    // consists of squares whose row + column sums\n    // to a constant, or the horizontal flip of\n    // such a set of squares.\n    for (var flip = 0; flip <= 1; flip++) {\n      for (var sum = 2; sum <= 16; sum++) {\n        var vars = [];\n        for (var r = 1; r <= sum-1; r++) {\n          var c = sum - r;\n          if (flip)\n            c = 9-c;\n          if (r >= 1 && r <= 8 && c >= 1 && c <= 8) {\n            vars.push(boardSquare(r,c));\n          }\n        }\n        solver.require(Logic.atMostOne(vars));\n      }\n    }\n\n    var solution = solver.solve().getTrueVars();\n\n    // solution might be, for example,\n    // [\"16\", \"24\", \"31\", \"45\", \"58\", \"62\", \"77\", \"83\"]\n    test.equal(solution.length, 8);\n    test.isTrue(/^([1-8],[1-8] ){7}[1-8],[1-8]$/.test(solution.join(' ')));\n    var assertEightDifferent = function (transformFunc) {\n      test.equal(_.uniq(_.map(solution, transformFunc)).length, 8);\n    };\n    // queens occur in eight different rows, eight different columns\n    assertEightDifferent(function (queen) { return queen.charAt(0); });\n    assertEightDifferent(function (queen) { return queen.charAt(2); });\n    // queens' row/col have eight different sums, eight different differences\n    assertEightDifferent(function (queen) {\n      return Number(queen.charAt(0)) - Number(queen.charAt(2));\n    });\n    assertEightDifferent(function (queen) {\n      return Number(queen.charAt(0)) + Number(queen.charAt(2));\n    });\n  });\n});\n\n\nTinytest.add(\"logic-solver - Sudoku\", function (test) {\n  var v = function (row, col, value) {\n    return row + \",\" + col + \"=\" + value;\n  };\n\n  Logic._disablingTypeChecks(function () {\n    //console.profile('sudoku');\n\n    var solver = new Logic.Solver();\n\n    // All rows, columns, and digits are 0-based internally.\n    for (var x = 0; x < 9; x++) {\n      // Find the top-left of box x. For example, Box 0 has a top-left\n      // of (0,0).  Box 3 has a top-left of (3,0).\n      var boxRow = Math.floor(x/3)*3;\n      var boxCol = (x%3)*3;\n      for (var y = 0; y < 9; y++) {\n        var numberInEachSquare = [];\n        var columnHavingYInRowX = [];\n        var rowHavingYInColumnX = [];\n        var squareHavingYInBoxX = [];\n        for (var z = 0; z < 9; z++) {\n          numberInEachSquare.push(v(x,y,z));\n          columnHavingYInRowX.push(v(x,z,y));\n          rowHavingYInColumnX.push(v(z,x,y));\n          squareHavingYInBoxX.push(v(\n            boxRow + Math.floor(z/3),\n            boxCol + (z%3),\n            y));\n        }\n        solver.require(Logic.exactlyOne(numberInEachSquare));\n        solver.require(Logic.exactlyOne(columnHavingYInRowX));\n        solver.require(Logic.exactlyOne(rowHavingYInColumnX));\n        solver.require(Logic.exactlyOne(squareHavingYInBoxX));\n      }\n    }\n\n    // Input a pretty hard Sudoku from here:\n    // http://www.menneske.no/sudoku/eng/showpuzzle.html?number=6903541\n    var puzzle = [\n      \"....839..\",\n      \"1......3.\",\n      \"..4....7.\",\n      \".42.3....\",\n      \"6.......4\",\n      \"....7..1.\",\n      \".2.......\",\n      \".8...92..\",\n      \"...25...6\"\n    ];\n    for (var r = 0; r < 9; r++) {\n      var str = puzzle[r];\n      for (var c = 0; c < 9; c++) {\n        // zero-based digit\n        var digit = str.charCodeAt(c) - 49;\n        if (digit >= 0 && digit < 9) {\n          solver.require(v(r, c, digit));\n        }\n      }\n    }\n\n    var solution = solver.solve().getTrueVars();\n    var solutionString = _.map(solution, function (v) {\n      return String(Number(v.slice(-1)) + 1);\n    }).join('').match(/.{9}/g).join('\\n');\n    test.equal(solutionString, [\n      \"765483921\",\n      \"198726435\",\n      \"234915678\",\n      \"842531769\",\n      \"617892354\",\n      \"359674812\",\n      \"926147583\",\n      \"581369247\",\n      \"473258196\"\n    ].join('\\n'));\n\n    //console.profileEnd('sudoku');\n  });\n});\n\nTinytest.add(\"logic-solver - goes to eleven\", function (test) {\n  var solver = new Logic.Solver();\n  var eleven = Logic.constantBits(11);\n  var x = Logic.variableBits(\"x\", 5);\n  solver.require(Logic.lessThanOrEqual(x, eleven));\n  solver.require(Logic.lessThanOrEqual(eleven, x));\n  test.equal(solver.solve().getTrueVars().join(','), \"x$0,x$1,x$3\");\n});\n\nTinytest.add(\"logic-solver - evaluate\", function (test) {\n  var isTrue = function (x) {\n    test.isTrue(x === true); // require exact \"true\"\n  };\n  var isFalse = function (x) {\n    test.isFalse(x !== false); // require exact \"false\"\n  };\n\n  var s = new Logic.Solver();\n  s.require(\"A\", \"-B\");\n  var f = Logic.and(\"A\", \"-B\");\n  s.require(f);\n  var g = Logic.and(\"A\", \"B\");\n  s.forbid(g);\n  var h1 = Logic.xor(\"A\", \"B\");\n  var h2 = Logic.and(\"A\", \"B\");\n  s.require(Logic.or(\"$T\", h1));\n  s.require(Logic.or(\"$T\", h2));\n  var sol = s.solve();\n  isTrue(sol.evaluate(\"A\"));\n  isFalse(sol.evaluate(\"-A\"));\n  isTrue(sol.evaluate(\"--A\"));\n  isFalse(sol.evaluate(\"B\"));\n  isTrue(sol.evaluate(\"-B\"));\n  isTrue(sol.evaluate(f));\n  isFalse(sol.evaluate(g));\n  isTrue(sol.evaluate(h1));\n  isFalse(sol.evaluate(h2));\n  isFalse(sol.evaluate(Logic.not(h1)));\n  isTrue(sol.evaluate(Logic.not(h2)));\n  isTrue(sol.evaluate(Logic.exactlyOne(\"A\", \"B\")));\n  isFalse(sol.evaluate(Logic.exactlyOne(\"-A\", \"B\")));\n\n  s.require(Logic.or(\"$T\", Logic.not(h1)));\n  s.require(Logic.or(\"$T\", Logic.not(h2)));\n  isTrue(sol.evaluate(h1));\n  isFalse(sol.evaluate(h2));\n\n  test.throws(function () {\n    sol.evaluate(\"C\");\n  });\n\n  s.require(\"D\");\n  test.throws(function () {\n    sol.evaluate(\"D\");\n  });\n  test.throws(function () {\n    sol.evaluate(Logic.or(\"D\", \"$T\"));\n  });\n\n  test.equal(sol.evaluate(\n    new Logic.Bits([\"A\", \"B\", \"-A\", \"$F\", \"-B\"])), 17);\n\n  var numClauses = s.clauses.length;\n  test.equal(sol.evaluate(Logic.weightedSum([Logic.or(\"A\", \"B\"),\n                                             \"A\", \"A\", \"-B\"],\n                                            [7, 7, 7, 7])), 28);\n  test.equal(s.clauses.length, numClauses);\n});\n\nTinytest.add(\"logic-solver - toy packages\", function (test) {\n\n  var withSolver = function (func) {\n\n    var solver = new Logic.Solver();\n\n    _.each(allPackageVersions, function (versions, pkg) {\n      versions = _.map(versions, function (v) {\n        return pkg + \"@\" + v;\n      });\n      // e.g. atMostOne([\"foo@1.0.0\", \"foo@1.0.1\", \"foo@2.0.0\"])\n      solver.require(Logic.atMostOne(versions));\n      // e.g. equiv(\"foo\", or([\"foo@1.0.0\", ...]))\n      solver.require(Logic.equiv(pkg, Logic.or(versions)));\n    });\n\n    _.each(dependencies, function (depMap, packageVersion) {\n      _.each(depMap, function (compatibleVersions, package2) {\n        // e.g. implies(\"bar@1.2.4\", \"foo\")\n        solver.require(Logic.implies(packageVersion, package2));\n        // Now ban all incompatible versions of package2 if\n        // we select this packageVersion.\n        // NOTE: This is not the best way to express constraints.  It's\n        // not what we do in the real package constraint solver.\n        _.each(allPackageVersions[package2], function (v) {\n          if (! _.contains(compatibleVersions, v)) {\n            solver.require(Logic.implies(packageVersion,\n                                         Logic.not(package2 + \"@\" + v)));\n          }\n        });\n      });\n    });\n\n    var optimize = function (solver, costVectorMap) {\n      var solution = solver.solve();\n      if (! solution) {\n        return null;\n      }\n\n      var terms = [];\n      var weightVectors = [];\n      var vectorLength = null;\n      _.each(costVectorMap, function (vector, key) {\n        terms.push(key);\n        weightVectors.push(vector);\n        if (vectorLength === null) {\n          vectorLength = vector.length;\n        } else {\n          if (vectorLength !== vector.length) {\n            throw new Error(\"Uneven vector lengths: \" + vectorLength +\n                            \" and \" + vector.length);\n          }\n        }\n      });\n\n      for (var i = 0; i < vectorLength; i++) {\n        var weights = _.pluck(weightVectors, i);\n        solution = solver.minimizeWeightedSum(solution, terms, weights);\n      }\n\n      return solution;\n    };\n\n    var solve = function (optionalCosts) {\n      var solution = (optionalCosts ? optimize(solver, optionalCosts) :\n                      solver.solve());\n      if (! solution) {\n        return solution; // null\n      } else {\n        // only return variables like \"foo@1.0.0\", not \"foo\"\n        return _.filter(solution.getTrueVars(), function (v) {\n          return v.indexOf('@') >= 0;\n        });\n      }\n    };\n\n    func(solver, solve);\n  };\n\n  var allPackageVersions = {\n    'foo': ['1.0.0', '1.0.1', '2.0.0'],\n    'bar': ['1.2.3', '1.2.4', '1.2.5'],\n    'baz': ['3.0.0']\n  };\n\n  // Exact dependencies.\n  var dependencies = {\n    'bar@1.2.3': { foo: ['1.0.0'] },\n    'bar@1.2.4': { foo: ['1.0.1'] },\n    'bar@1.2.5': { foo: ['2.0.0'] },\n    'baz@3.0.0': { foo: ['1.0.0', '1.0.1'],\n                   bar: ['1.2.4', '1.2.5'] }\n  };\n\n  withSolver(function (solver, solve) {\n    // Ask for \"bar@1.2.5\", get both it and \"foo@2.0.0\"\n    solver.require(\"bar@1.2.5\");\n    test.equal(solve(), [\"bar@1.2.5\", \"foo@2.0.0\"]);\n  });\n\n  withSolver(function (solver, solve) {\n    // Ask for \"foo@1.0.1\" and *some* version of bar!\n    solver.require(\"foo@1.0.1\");\n    solver.require(\"bar\");\n    test.equal(solve(), [\"bar@1.2.4\", \"foo@1.0.1\"]);\n  });\n\n  withSolver(function (solver, solve) {\n    // Ask for versions that can't be combined\n    solver.require(\"foo@1.0.1\");\n    solver.require(\"bar@1.2.3\");\n    test.equal(solve(), null);\n  });\n\n  withSolver(function (solver, solve) {\n    // Ask for baz, automatically get versions of foo and bar\n    // such that foo satisfies bar's dependency!\n    solver.require(\"baz\");\n    test.equal(solve(), [\"bar@1.2.4\",\n                         \"baz@3.0.0\",\n                         \"foo@1.0.1\"]);\n  });\n\n  withSolver(function (solver, solve) {\n    // pick earliest versions\n    solver.require(\"foo\");\n    solver.require(\"bar\");\n    test.equal(solve({ \"foo@1.0.0\": [0],\n                       \"foo@1.0.1\": [1],\n                       \"foo@2.0.0\": [2],\n                       \"bar@1.2.3\": [0],\n                       \"bar@1.2.4\": [1],\n                       \"bar@1.2.5\": [2] }),\n               [\"bar@1.2.3\", \"foo@1.0.0\"]);\n  });\n\n  withSolver(function (solver, solve) {\n    // pick latest versions\n    solver.require(\"foo\");\n    solver.require(\"bar\");\n    test.equal(solve({ \"foo@1.0.0\": [2],\n                       \"foo@1.0.1\": [1],\n                       \"foo@2.0.0\": [0],\n                       \"bar@1.2.3\": [2],\n                       \"bar@1.2.4\": [1],\n                       \"bar@1.2.5\": [0] }),\n               [\"bar@1.2.5\", \"foo@2.0.0\"]);\n  });\n\n  withSolver(function (solver, solve) {\n    // pick earliest versions (but give solver a\n    // cost vector with extra stuff)\n    solver.require(\"foo\");\n    solver.require(\"bar\");\n    test.equal(solve({ \"foo@1.0.0\": [1, 0],\n                       \"foo@1.0.1\": [1, 1],\n                       \"foo@2.0.0\": [1, 2],\n                       \"bar@1.2.3\": [2, 0],\n                       \"bar@1.2.4\": [2, 1],\n                       \"bar@1.2.5\": [2, 2] }),\n               [\"bar@1.2.3\", \"foo@1.0.0\"]);\n  });\n\n  withSolver(function (solver, solve) {\n    // pick latest versions (but give solver a\n    // bigger vector to work with)\n    solver.require(\"foo\");\n    solver.require(\"bar\");\n    test.equal(solve({ \"foo@1.0.0\": [1, 2],\n                       \"foo@1.0.1\": [1, 1],\n                       \"foo@2.0.0\": [1, 0],\n                       \"bar@1.2.3\": [2, 2],\n                       \"bar@1.2.4\": [2, 1],\n                       \"bar@1.2.5\": [2, 0] }),\n               [\"bar@1.2.5\", \"foo@2.0.0\"]);\n  });\n\n});\n\nTinytest.add(\"logic-solver - minimize\", function (test) {\n  var s = new Logic.Solver();\n  s.require(Logic.or(\"A\", \"B\", \"C\", \"D\"));\n  // cost is equal to the number of false variables\n  var costTerms = [\"-A\", \"-B\", \"-C\", \"-D\"];\n  var costWeights = 1;\n  var solution1 = s.solve();\n  // nothing forces the cost (= the number of false variables)\n  // to be greater than 0, but MiniSat will always discover\n  // a sparser solution than (1,1,1,1) first.\n  test.isTrue(solution1.getWeightedSum(costTerms, costWeights) > 0);\n  var solution2 = s.minimizeWeightedSum(solution1, costTerms, costWeights);\n  test.isFalse(solution1 === solution2);\n  test.equal(solution2.getWeightedSum(costTerms, costWeights), 0);\n  test.equal(solution2.getTrueVars(), [\"A\", \"B\", \"C\", \"D\"]);\n});\n\nTinytest.add(\"logic-solver - maximize\", function (test) {\n  var s = new Logic.Solver();\n  // Find subset of {2, 5, 10, 11, 15} that sums to as close\n  // as possible to 19 without going over.\n  var costWeights = [2, 5, 10, 11, 15];\n  // name variables after the weights\n  var costTerms = _.map(costWeights, function (w) {\n    return \"#\"+w;\n  });\n  var ws = Logic.weightedSum(costTerms, costWeights);\n  s.require(Logic.lessThanOrEqual(ws, Logic.constantBits(19)));\n  var sol = s.solve();\n  var sol2 = s.maximizeWeightedSum(sol, costTerms, costWeights, ws);\n  test.equal(sol2.getTrueVars(), [\"#11\", \"#2\", \"#5\"]);\n});\n\nTinytest.add(\"logic-solver - weightedSum\", function (test) {\n  var s = new Logic.Solver();\n  s.require(Logic.equalBits(\n    Logic.weightedSum([\"A\", \"B\"], [1, 4]),\n    Logic.constantBits(5)));\n  var sol = s.solve();\n  test.isTrue(sol);\n  test.equal(sol.getTrueVars(), [\"A\", \"B\"]);\n});\n\nTinytest.add(\"logic-solver - type-checking\", function (test) {\n  // on by default\n  test.throws(function () {\n    Logic.or({});\n  }, /is not a Formula or Term/);\n\n  // ... but can turn it off (this shouldn't throw)\n  Logic._disablingTypeChecks(function () {\n    Logic.or({});\n  });\n});\n"
  },
  {
    "path": "packages/logic-solver/minisat.js",
    "content": "// This file is generated by the meteor/minisat repo.\n// See that repo's README for instructions for building it.\nC_MINISAT=(function(){var module={};var require=(function(){});var process={argv:[\"node\",\"minisat\"],on:(function(){}),stdout:{write:(function(str){console.log(\"MINISAT-out:\",str.replace(/\\n$/,\"\"))})},stderr:{write:(function(str){console.log(\"MINISAT-err:\",str.replace(/\\n$/,\"\"))})}};var window=0;var Module;if(!Module)Module=(typeof Module!==\"undefined\"?Module:null)||{};var moduleOverrides={};for(var key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var ENVIRONMENT_IS_NODE=typeof process===\"object\"&&typeof require===\"function\";var ENVIRONMENT_IS_WEB=typeof window===\"object\";var ENVIRONMENT_IS_WORKER=typeof importScripts===\"function\";var ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){if(!Module[\"print\"])Module[\"print\"]=function print(x){process[\"stdout\"].write(x+\"\\n\")};if(!Module[\"printErr\"])Module[\"printErr\"]=function printErr(x){process[\"stderr\"].write(x+\"\\n\")};var nodeFS=require(\"fs\");var nodePath=require(\"path\");Module[\"read\"]=function read(filename,binary){filename=nodePath[\"normalize\"](filename);var ret=nodeFS[\"readFileSync\"](filename);if(!ret&&filename!=nodePath[\"resolve\"](filename)){filename=path.join(__dirname,\"..\",\"src\",filename);ret=nodeFS[\"readFileSync\"](filename)}if(ret&&!binary)ret=ret.toString();return ret};Module[\"readBinary\"]=function readBinary(filename){return Module[\"read\"](filename,true)};Module[\"load\"]=function load(f){globalEval(read(f))};if(process[\"argv\"].length>1){Module[\"thisProgram\"]=process[\"argv\"][1].replace(/\\\\/g,\"/\")}else{Module[\"thisProgram\"]=\"unknown-program\"}Module[\"arguments\"]=process[\"argv\"].slice(2);if(typeof module!==\"undefined\"){module[\"exports\"]=Module}process[\"on\"](\"uncaughtException\",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}))}else if(ENVIRONMENT_IS_SHELL){if(!Module[\"print\"])Module[\"print\"]=print;if(typeof printErr!=\"undefined\")Module[\"printErr\"]=printErr;if(typeof read!=\"undefined\"){Module[\"read\"]=read}else{Module[\"read\"]=function read(){throw\"no read() available (jsc?)\"}}Module[\"readBinary\"]=function readBinary(f){if(typeof readbuffer===\"function\"){return new Uint8Array(readbuffer(f))}var data=read(f,\"binary\");assert(typeof data===\"object\");return data};if(typeof scriptArgs!=\"undefined\"){Module[\"arguments\"]=scriptArgs}else if(typeof arguments!=\"undefined\"){Module[\"arguments\"]=arguments}this[\"Module\"]=Module}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){Module[\"read\"]=function read(url){var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,false);xhr.send(null);return xhr.responseText};if(typeof arguments!=\"undefined\"){Module[\"arguments\"]=arguments}if(typeof console!==\"undefined\"){if(!Module[\"print\"])Module[\"print\"]=function print(x){console.log(x)};if(!Module[\"printErr\"])Module[\"printErr\"]=function printErr(x){console.log(x)}}else{var TRY_USE_DUMP=false;if(!Module[\"print\"])Module[\"print\"]=TRY_USE_DUMP&&typeof dump!==\"undefined\"?(function(x){dump(x)}):(function(x){})}if(ENVIRONMENT_IS_WEB){window[\"Module\"]=Module}else{Module[\"load\"]=importScripts}}else{throw\"Unknown runtime environment. Where are we?\"}function globalEval(x){eval.call(null,x)}if(!Module[\"load\"]&&Module[\"read\"]){Module[\"load\"]=function load(f){globalEval(Module[\"read\"](f))}}if(!Module[\"print\"]){Module[\"print\"]=(function(){})}if(!Module[\"printErr\"]){Module[\"printErr\"]=Module[\"print\"]}if(!Module[\"arguments\"]){Module[\"arguments\"]=[]}if(!Module[\"thisProgram\"]){Module[\"thisProgram\"]=\"./this.program\"}Module.print=Module[\"print\"];Module.printErr=Module[\"printErr\"];Module[\"preRun\"]=[];Module[\"postRun\"]=[];for(var key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}var Runtime={setTempRet0:(function(value){tempRet0=value}),getTempRet0:(function(){return tempRet0}),stackSave:(function(){return STACKTOP}),stackRestore:(function(stackTop){STACKTOP=stackTop}),getNativeTypeSize:(function(type){switch(type){case\"i1\":case\"i8\":return 1;case\"i16\":return 2;case\"i32\":return 4;case\"i64\":return 8;case\"float\":return 4;case\"double\":return 8;default:{if(type[type.length-1]===\"*\"){return Runtime.QUANTUM_SIZE}else if(type[0]===\"i\"){var bits=parseInt(type.substr(1));assert(bits%8===0);return bits/8}else{return 0}}}}),getNativeFieldSize:(function(type){return Math.max(Runtime.getNativeTypeSize(type),Runtime.QUANTUM_SIZE)}),STACK_ALIGN:16,getAlignSize:(function(type,size,vararg){if(!vararg&&(type==\"i64\"||type==\"double\"))return 8;if(!type)return Math.min(size,8);return Math.min(size||(type?Runtime.getNativeFieldSize(type):0),Runtime.QUANTUM_SIZE)}),dynCall:(function(sig,ptr,args){if(args&&args.length){if(!args.splice)args=Array.prototype.slice.call(args);args.splice(0,0,ptr);return Module[\"dynCall_\"+sig].apply(null,args)}else{return Module[\"dynCall_\"+sig].call(null,ptr)}}),functionPointers:[],addFunction:(function(func){for(var i=0;i<Runtime.functionPointers.length;i++){if(!Runtime.functionPointers[i]){Runtime.functionPointers[i]=func;return 2*(1+i)}}throw\"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.\"}),removeFunction:(function(index){Runtime.functionPointers[(index-2)/2]=null}),getAsmConst:(function(code,numArgs){if(!Runtime.asmConstCache)Runtime.asmConstCache={};var func=Runtime.asmConstCache[code];if(func)return func;var args=[];for(var i=0;i<numArgs;i++){args.push(String.fromCharCode(36)+i)}var source=Pointer_stringify(code);if(source[0]==='\"'){if(source.indexOf('\"',1)===source.length-1){source=source.substr(1,source.length-2)}else{abort(\"invalid EM_ASM input |\"+source+\"|. Please use EM_ASM(..code..) (no quotes) or EM_ASM({ ..code($0).. }, input) (to input values)\")}}try{var evalled=eval(\"(function(Module, FS) { return function(\"+args.join(\",\")+\"){ \"+source+\" } })\")(Module,typeof FS!==\"undefined\"?FS:null)}catch(e){Module.printErr(\"error in executing inline EM_ASM code: \"+e+\" on: \\n\\n\"+source+\"\\n\\nwith args |\"+args+\"| (make sure to use the right one out of EM_ASM, EM_ASM_ARGS, etc.)\");throw e}return Runtime.asmConstCache[code]=evalled}),warnOnce:(function(text){if(!Runtime.warnOnce.shown)Runtime.warnOnce.shown={};if(!Runtime.warnOnce.shown[text]){Runtime.warnOnce.shown[text]=1;Module.printErr(text)}}),funcWrappers:{},getFuncWrapper:(function(func,sig){assert(sig);if(!Runtime.funcWrappers[sig]){Runtime.funcWrappers[sig]={}}var sigCache=Runtime.funcWrappers[sig];if(!sigCache[func]){sigCache[func]=function dynCall_wrapper(){return Runtime.dynCall(sig,func,arguments)}}return sigCache[func]}),UTF8Processor:(function(){var buffer=[];var needed=0;this.processCChar=(function(code){code=code&255;if(buffer.length==0){if((code&128)==0){return String.fromCharCode(code)}buffer.push(code);if((code&224)==192){needed=1}else if((code&240)==224){needed=2}else{needed=3}return\"\"}if(needed){buffer.push(code);needed--;if(needed>0)return\"\"}var c1=buffer[0];var c2=buffer[1];var c3=buffer[2];var c4=buffer[3];var ret;if(buffer.length==2){ret=String.fromCharCode((c1&31)<<6|c2&63)}else if(buffer.length==3){ret=String.fromCharCode((c1&15)<<12|(c2&63)<<6|c3&63)}else{var codePoint=(c1&7)<<18|(c2&63)<<12|(c3&63)<<6|c4&63;ret=String.fromCharCode(((codePoint-65536)/1024|0)+55296,(codePoint-65536)%1024+56320)}buffer.length=0;return ret});this.processJSString=function processJSString(string){string=unescape(encodeURIComponent(string));var ret=[];for(var i=0;i<string.length;i++){ret.push(string.charCodeAt(i))}return ret}}),getCompilerSetting:(function(name){throw\"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work\"}),stackAlloc:(function(size){var ret=STACKTOP;STACKTOP=STACKTOP+size|0;STACKTOP=STACKTOP+15&-16;return ret}),staticAlloc:(function(size){var ret=STATICTOP;STATICTOP=STATICTOP+size|0;STATICTOP=STATICTOP+15&-16;return ret}),dynamicAlloc:(function(size){var ret=DYNAMICTOP;DYNAMICTOP=DYNAMICTOP+size|0;DYNAMICTOP=DYNAMICTOP+15&-16;if(DYNAMICTOP>=TOTAL_MEMORY)enlargeMemory();return ret}),alignMemory:(function(size,quantum){var ret=size=Math.ceil(size/(quantum?quantum:16))*(quantum?quantum:16);return ret}),makeBigInt:(function(low,high,unsigned){var ret=unsigned?+(low>>>0)+ +(high>>>0)*+4294967296:+(low>>>0)+ +(high|0)*+4294967296;return ret}),GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module[\"Runtime\"]=Runtime;var __THREW__=0;var ABORT=false;var EXITSTATUS=0;var undef=0;var tempValue,tempInt,tempBigInt,tempInt2,tempBigInt2,tempPair,tempBigIntI,tempBigIntR,tempBigIntS,tempBigIntP,tempBigIntD,tempDouble,tempFloat;var tempI64,tempI64b;var tempRet0,tempRet1,tempRet2,tempRet3,tempRet4,tempRet5,tempRet6,tempRet7,tempRet8,tempRet9;function assert(condition,text){if(!condition){abort(\"Assertion failed: \"+text)}}var globalScope=this;function getCFunc(ident){var func=Module[\"_\"+ident];if(!func){try{func=eval(\"_\"+ident)}catch(e){}}assert(func,\"Cannot call unknown function \"+ident+\" (perhaps LLVM optimizations or closure removed it?)\");return func}var cwrap,ccall;((function(){var JSfuncs={\"stackSave\":(function(){Runtime.stackSave()}),\"stackRestore\":(function(){Runtime.stackRestore()}),\"arrayToC\":(function(arr){var ret=Runtime.stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}),\"stringToC\":(function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=Runtime.stackAlloc((str.length<<2)+1);writeStringToMemory(str,ret)}return ret})};var toC={\"string\":JSfuncs[\"stringToC\"],\"array\":JSfuncs[\"arrayToC\"]};ccall=function ccallFunc(ident,returnType,argTypes,args){var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=Runtime.stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);if(returnType===\"string\")ret=Pointer_stringify(ret);if(stack!==0)Runtime.stackRestore(stack);return ret};var sourceRegex=/^function\\s*\\(([^)]*)\\)\\s*{\\s*([^*]*?)[\\s;]*(?:return\\s*(.*?)[;\\s]*)?}$/;function parseJSFunc(jsfunc){var parsed=jsfunc.toString().match(sourceRegex).slice(1);return{arguments:parsed[0],body:parsed[1],returnValue:parsed[2]}}var JSsource={};for(var fun in JSfuncs){if(JSfuncs.hasOwnProperty(fun)){JSsource[fun]=parseJSFunc(JSfuncs[fun])}}cwrap=function cwrap(ident,returnType,argTypes){argTypes=argTypes||[];var cfunc=getCFunc(ident);var numericArgs=argTypes.every((function(type){return type===\"number\"}));var numericRet=returnType!==\"string\";if(numericRet&&numericArgs){return cfunc}var argNames=argTypes.map((function(x,i){return\"$\"+i}));var funcstr=\"(function(\"+argNames.join(\",\")+\") {\";var nargs=argTypes.length;if(!numericArgs){funcstr+=\"var stack = \"+JSsource[\"stackSave\"].body+\";\";for(var i=0;i<nargs;i++){var arg=argNames[i],type=argTypes[i];if(type===\"number\")continue;var convertCode=JSsource[type+\"ToC\"];funcstr+=\"var \"+convertCode.arguments+\" = \"+arg+\";\";funcstr+=convertCode.body+\";\";funcstr+=arg+\"=\"+convertCode.returnValue+\";\"}}var cfuncname=parseJSFunc((function(){return cfunc})).returnValue;funcstr+=\"var ret = \"+cfuncname+\"(\"+argNames.join(\",\")+\");\";if(!numericRet){var strgfy=parseJSFunc((function(){return Pointer_stringify})).returnValue;funcstr+=\"ret = \"+strgfy+\"(ret);\"}if(!numericArgs){funcstr+=JSsource[\"stackRestore\"].body.replace(\"()\",\"(stack)\")+\";\"}funcstr+=\"return ret})\";return eval(funcstr)}}))();Module[\"cwrap\"]=cwrap;Module[\"ccall\"]=ccall;function setValue(ptr,value,type,noSafe){type=type||\"i8\";if(type.charAt(type.length-1)===\"*\")type=\"i32\";switch(type){case\"i1\":HEAP8[ptr>>0]=value;break;case\"i8\":HEAP8[ptr>>0]=value;break;case\"i16\":HEAP16[ptr>>1]=value;break;case\"i32\":HEAP32[ptr>>2]=value;break;case\"i64\":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case\"float\":HEAPF32[ptr>>2]=value;break;case\"double\":HEAPF64[ptr>>3]=value;break;default:abort(\"invalid type for setValue: \"+type)}}Module[\"setValue\"]=setValue;function getValue(ptr,type,noSafe){type=type||\"i8\";if(type.charAt(type.length-1)===\"*\")type=\"i32\";switch(type){case\"i1\":return HEAP8[ptr>>0];case\"i8\":return HEAP8[ptr>>0];case\"i16\":return HEAP16[ptr>>1];case\"i32\":return HEAP32[ptr>>2];case\"i64\":return HEAP32[ptr>>2];case\"float\":return HEAPF32[ptr>>2];case\"double\":return HEAPF64[ptr>>3];default:abort(\"invalid type for setValue: \"+type)}return null}Module[\"getValue\"]=getValue;var ALLOC_NORMAL=0;var ALLOC_STACK=1;var ALLOC_STATIC=2;var ALLOC_DYNAMIC=3;var ALLOC_NONE=4;Module[\"ALLOC_NORMAL\"]=ALLOC_NORMAL;Module[\"ALLOC_STACK\"]=ALLOC_STACK;Module[\"ALLOC_STATIC\"]=ALLOC_STATIC;Module[\"ALLOC_DYNAMIC\"]=ALLOC_DYNAMIC;Module[\"ALLOC_NONE\"]=ALLOC_NONE;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab===\"number\"){zeroinit=true;size=slab}else{zeroinit=false;size=slab.length}var singleType=typeof types===\"string\"?types:null;var ret;if(allocator==ALLOC_NONE){ret=ptr}else{ret=[_malloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][allocator===undefined?ALLOC_STATIC:allocator](Math.max(size,singleType?1:types.length))}if(zeroinit){var ptr=ret,stop;assert((ret&3)==0);stop=ret+(size&~3);for(;ptr<stop;ptr+=4){HEAP32[ptr>>2]=0}stop=ret+size;while(ptr<stop){HEAP8[ptr++>>0]=0}return ret}if(singleType===\"i8\"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i<size){var curr=slab[i];if(typeof curr===\"function\"){curr=Runtime.getFunctionIndex(curr)}type=singleType||types[i];if(type===0){i++;continue}if(type==\"i64\")type=\"i32\";setValue(ret+i,curr,type);if(previousType!==type){typeSize=Runtime.getNativeTypeSize(type);previousType=type}i+=typeSize}return ret}Module[\"allocate\"]=allocate;function Pointer_stringify(ptr,length){if(length===0||!ptr)return\"\";var hasUtf=false;var t;var i=0;while(1){t=HEAPU8[ptr+i>>0];if(t>=128)hasUtf=true;else if(t==0&&!length)break;i++;if(length&&i==length)break}if(!length)length=i;var ret=\"\";if(!hasUtf){var MAX_CHUNK=1024;var curr;while(length>0){curr=String.fromCharCode.apply(String,HEAPU8.subarray(ptr,ptr+Math.min(length,MAX_CHUNK)));ret=ret?ret+curr:curr;ptr+=MAX_CHUNK;length-=MAX_CHUNK}return ret}var utf8=new Runtime.UTF8Processor;for(i=0;i<length;i++){t=HEAPU8[ptr+i>>0];ret+=utf8.processCChar(t)}return ret}Module[\"Pointer_stringify\"]=Pointer_stringify;function UTF16ToString(ptr){var i=0;var str=\"\";while(1){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)return str;++i;str+=String.fromCharCode(codeUnit)}}Module[\"UTF16ToString\"]=UTF16ToString;function stringToUTF16(str,outPtr){for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);HEAP16[outPtr+i*2>>1]=codeUnit}HEAP16[outPtr+str.length*2>>1]=0}Module[\"stringToUTF16\"]=stringToUTF16;function UTF32ToString(ptr){var i=0;var str=\"\";while(1){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)return str;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}}Module[\"UTF32ToString\"]=UTF32ToString;function stringToUTF32(str,outPtr){var iChar=0;for(var iCodeUnit=0;iCodeUnit<str.length;++iCodeUnit){var codeUnit=str.charCodeAt(iCodeUnit);if(codeUnit>=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++iCodeUnit);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr+iChar*4>>2]=codeUnit;++iChar}HEAP32[outPtr+iChar*4>>2]=0}Module[\"stringToUTF32\"]=stringToUTF32;function demangle(func){var hasLibcxxabi=!!Module[\"___cxa_demangle\"];if(hasLibcxxabi){try{var buf=_malloc(func.length);writeStringToMemory(func.substr(1),buf);var status=_malloc(4);var ret=Module[\"___cxa_demangle\"](buf,0,0,status);if(getValue(status,\"i32\")===0&&ret){return Pointer_stringify(ret)}}catch(e){}finally{if(buf)_free(buf);if(status)_free(status);if(ret)_free(ret)}}var i=3;var basicTypes={\"v\":\"void\",\"b\":\"bool\",\"c\":\"char\",\"s\":\"short\",\"i\":\"int\",\"l\":\"long\",\"f\":\"float\",\"d\":\"double\",\"w\":\"wchar_t\",\"a\":\"signed char\",\"h\":\"unsigned char\",\"t\":\"unsigned short\",\"j\":\"unsigned int\",\"m\":\"unsigned long\",\"x\":\"long long\",\"y\":\"unsigned long long\",\"z\":\"...\"};var subs=[];var first=true;function dump(x){if(x)Module.print(x);Module.print(func);var pre=\"\";for(var a=0;a<i;a++)pre+=\" \";Module.print(pre+\"^\")}function parseNested(){i++;if(func[i]===\"K\")i++;var parts=[];while(func[i]!==\"E\"){if(func[i]===\"S\"){i++;var next=func.indexOf(\"_\",i);var num=func.substring(i,next)||0;parts.push(subs[num]||\"?\");i=next+1;continue}if(func[i]===\"C\"){parts.push(parts[parts.length-1]);i+=2;continue}var size=parseInt(func.substr(i));var pre=size.toString().length;if(!size||!pre){i--;break}var curr=func.substr(i+pre,size);parts.push(curr);subs.push(curr);i+=pre+size}i++;return parts}function parse(rawList,limit,allowVoid){limit=limit||Infinity;var ret=\"\",list=[];function flushList(){return\"(\"+list.join(\", \")+\")\"}var name;if(func[i]===\"N\"){name=parseNested().join(\"::\");limit--;if(limit===0)return rawList?[name]:name}else{if(func[i]===\"K\"||first&&func[i]===\"L\")i++;var size=parseInt(func.substr(i));if(size){var pre=size.toString().length;name=func.substr(i+pre,size);i+=pre+size}}first=false;if(func[i]===\"I\"){i++;var iList=parse(true);var iRet=parse(true,1,true);ret+=iRet[0]+\" \"+name+\"<\"+iList.join(\", \")+\">\"}else{ret=name}paramLoop:while(i<func.length&&limit-->0){var c=func[i++];if(c in basicTypes){list.push(basicTypes[c])}else{switch(c){case\"P\":list.push(parse(true,1,true)[0]+\"*\");break;case\"R\":list.push(parse(true,1,true)[0]+\"&\");break;case\"L\":{i++;var end=func.indexOf(\"E\",i);var size=end-i;list.push(func.substr(i,size));i+=size+2;break};case\"A\":{var size=parseInt(func.substr(i));i+=size.toString().length;if(func[i]!==\"_\")throw\"?\";i++;list.push(parse(true,1,true)[0]+\" [\"+size+\"]\");break};case\"E\":break paramLoop;default:ret+=\"?\"+c;break paramLoop}}}if(!allowVoid&&list.length===1&&list[0]===\"void\")list=[];if(rawList){if(ret){list.push(ret+\"?\")}return list}else{return ret+flushList()}}var parsed=func;try{if(func==\"Object._main\"||func==\"_main\"){return\"main()\"}if(typeof func===\"number\")func=Pointer_stringify(func);if(func[0]!==\"_\")return func;if(func[1]!==\"_\")return func;if(func[2]!==\"Z\")return func;switch(func[3]){case\"n\":return\"operator new()\";case\"d\":return\"operator delete()\"}parsed=parse()}catch(e){parsed+=\"?\"}if(parsed.indexOf(\"?\")>=0&&!hasLibcxxabi){Runtime.warnOnce(\"warning: a problem occurred in builtin C++ name demangling; build with  -s DEMANGLE_SUPPORT=1  to link in libcxxabi demangling\")}return parsed}function demangleAll(text){return text.replace(/__Z[\\w\\d_]+/g,(function(x){var y=demangle(x);return x===y?x:x+\" [\"+y+\"]\"}))}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return\"(no stack trace available)\"}}return err.stack.toString()}function stackTrace(){return demangleAll(jsStackTrace())}Module[\"stackTrace\"]=stackTrace;var PAGE_SIZE=4096;function alignMemoryPage(x){return x+4095&-4096}var HEAP;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var STATIC_BASE=0,STATICTOP=0,staticSealed=false;var STACK_BASE=0,STACKTOP=0,STACK_MAX=0;var DYNAMIC_BASE=0,DYNAMICTOP=0;function enlargeMemory(){abort(\"Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value \"+TOTAL_MEMORY+\", (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.\")}var TOTAL_STACK=Module[\"TOTAL_STACK\"]||5242880;var TOTAL_MEMORY=Module[\"TOTAL_MEMORY\"]||67108864;var FAST_MEMORY=Module[\"FAST_MEMORY\"]||2097152;var totalMemory=64*1024;while(totalMemory<TOTAL_MEMORY||totalMemory<2*TOTAL_STACK){if(totalMemory<16*1024*1024){totalMemory*=2}else{totalMemory+=16*1024*1024}}if(totalMemory!==TOTAL_MEMORY){Module.printErr(\"increasing TOTAL_MEMORY to \"+totalMemory+\" to be compliant with the asm.js spec\");TOTAL_MEMORY=totalMemory}assert(typeof Int32Array!==\"undefined\"&&typeof Float64Array!==\"undefined\"&&!!(new Int32Array(1))[\"subarray\"]&&!!(new Int32Array(1))[\"set\"],\"JS engine does not provide full typed array support\");var buffer=new ArrayBuffer(TOTAL_MEMORY);HEAP8=new Int8Array(buffer);HEAP16=new Int16Array(buffer);HEAP32=new Int32Array(buffer);HEAPU8=new Uint8Array(buffer);HEAPU16=new Uint16Array(buffer);HEAPU32=new Uint32Array(buffer);HEAPF32=new Float32Array(buffer);HEAPF64=new Float64Array(buffer);HEAP32[0]=255;assert(HEAPU8[0]===255&&HEAPU8[3]===0,\"Typed arrays 2 must be run on a little-endian system\");Module[\"HEAP\"]=HEAP;Module[\"buffer\"]=buffer;Module[\"HEAP8\"]=HEAP8;Module[\"HEAP16\"]=HEAP16;Module[\"HEAP32\"]=HEAP32;Module[\"HEAPU8\"]=HEAPU8;Module[\"HEAPU16\"]=HEAPU16;Module[\"HEAPU32\"]=HEAPU32;Module[\"HEAPF32\"]=HEAPF32;Module[\"HEAPF64\"]=HEAPF64;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback==\"function\"){callback();continue}var func=callback.func;if(typeof func===\"number\"){if(callback.arg===undefined){Runtime.dynCall(\"v\",func)}else{Runtime.dynCall(\"vi\",func,[callback.arg])}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module[\"preRun\"]){if(typeof Module[\"preRun\"]==\"function\")Module[\"preRun\"]=[Module[\"preRun\"]];while(Module[\"preRun\"].length){addOnPreRun(Module[\"preRun\"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){if(runtimeInitialized)return;runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__);runtimeExited=true}function postRun(){if(Module[\"postRun\"]){if(typeof Module[\"postRun\"]==\"function\")Module[\"postRun\"]=[Module[\"postRun\"]];while(Module[\"postRun\"].length){addOnPostRun(Module[\"postRun\"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}Module[\"addOnPreRun\"]=Module.addOnPreRun=addOnPreRun;function addOnInit(cb){__ATINIT__.unshift(cb)}Module[\"addOnInit\"]=Module.addOnInit=addOnInit;function addOnPreMain(cb){__ATMAIN__.unshift(cb)}Module[\"addOnPreMain\"]=Module.addOnPreMain=addOnPreMain;function addOnExit(cb){__ATEXIT__.unshift(cb)}Module[\"addOnExit\"]=Module.addOnExit=addOnExit;function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}Module[\"addOnPostRun\"]=Module.addOnPostRun=addOnPostRun;function intArrayFromString(stringy,dontAddNull,length){var ret=(new Runtime.UTF8Processor).processJSString(stringy);if(length){ret.length=length}if(!dontAddNull){ret.push(0)}return ret}Module[\"intArrayFromString\"]=intArrayFromString;function intArrayToString(array){var ret=[];for(var i=0;i<array.length;i++){var chr=array[i];if(chr>255){chr&=255}ret.push(String.fromCharCode(chr))}return ret.join(\"\")}Module[\"intArrayToString\"]=intArrayToString;function writeStringToMemory(string,buffer,dontAddNull){var array=intArrayFromString(string,dontAddNull);var i=0;while(i<array.length){var chr=array[i];HEAP8[buffer+i>>0]=chr;i=i+1}}Module[\"writeStringToMemory\"]=writeStringToMemory;function writeArrayToMemory(array,buffer){for(var i=0;i<array.length;i++){HEAP8[buffer+i>>0]=array[i]}}Module[\"writeArrayToMemory\"]=writeArrayToMemory;function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.length;i++){HEAP8[buffer+i>>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer+str.length>>0]=0}Module[\"writeAsciiToMemory\"]=writeAsciiToMemory;function unSign(value,bits,ignore){if(value>=0){return value}return bits<=32?2*Math.abs(1<<bits-1)+value:Math.pow(2,bits)+value}function reSign(value,bits,ignore){if(value<=0){return value}var half=bits<=32?Math.abs(1<<bits-1):Math.pow(2,bits-1);if(value>=half&&(bits<=32||value>half)){value=-2*half+value}return value}if(!Math[\"imul\"]||Math[\"imul\"](4294967295,5)!==-5)Math[\"imul\"]=function imul(a,b){var ah=a>>>16;var al=a&65535;var bh=b>>>16;var bl=b&65535;return al*bl+(ah*bl+al*bh<<16)|0};Math.imul=Math[\"imul\"];var Math_abs=Math.abs;var Math_cos=Math.cos;var Math_sin=Math.sin;var Math_tan=Math.tan;var Math_acos=Math.acos;var Math_asin=Math.asin;var Math_atan=Math.atan;var Math_atan2=Math.atan2;var Math_exp=Math.exp;var Math_log=Math.log;var Math_sqrt=Math.sqrt;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_pow=Math.pow;var Math_imul=Math.imul;var Math_fround=Math.fround;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module[\"monitorRunDependencies\"]){Module[\"monitorRunDependencies\"](runDependencies)}}Module[\"addRunDependency\"]=addRunDependency;function removeRunDependency(id){runDependencies--;if(Module[\"monitorRunDependencies\"]){Module[\"monitorRunDependencies\"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module[\"removeRunDependency\"]=removeRunDependency;Module[\"preloadedImages\"]={};Module[\"preloadedAudios\"]={};var memoryInitializer=null;STATIC_BASE=8;STATICTOP=STATIC_BASE+5664;__ATINIT__.push({func:(function(){__GLOBAL__I_a()})},{func:(function(){__GLOBAL__I_a127()})});allocate([78,55,77,105,110,105,115,97,116,50,48,79,117,116,79,102,77,101,109,111,114,121,69,120,99,101,112,116,105,111,110,69,0,0,0,0,0,0,0,0,88,18,0,0,8,0,0,0,78,55,77,105,110,105,115,97,116,54,79,112,116,105,111,110,69,0,0,0,0,0,0,0,88,18,0,0,56,0,0,0,10,32,32,32,32,32,32,32,32,37,115,10,0,0,0,0,0,0,0,0,80,0,0,0,1,0,0,0,2,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,200,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,1,0,0,0,78,55,77,105,110,105,115,97,116,49,48,66,111,111,108,79,112,116,105,111,110,69,0,0,128,18,0,0,176,0,0,0,80,0,0,0,0,0,0,0,32,32,45,37,115,44,32,45,110,111,45,37,115,0,0,0,40,100,101,102,97,117,108,116,58,32,37,115,41,10,0,0,111,110,0,0,0,0,0,0,111,102,102,0,0,0,0,0,110,111,45,0,0,0,0,0,0,0,0,0,64,1,0,0,1,0,0,0,4,0,0,0,2,0,0,0,2,0,0,0,78,55,77,105,110,105,115,97,116,57,73,110,116,79,112,116,105,111,110,69,0,0,0,0,128,18,0,0,40,1,0,0,80,0,0,0,0,0,0,0,32,32,45,37,45,49,50,115,32,61,32,37,45,56,115,32,91,0,0,0,0,0,0,0,105,109,105,110,0,0,0,0,37,52,100,0,0,0,0,0,32,46,46,32,0,0,0,0,105,109,97,120,0,0,0,0,93,32,40,100,101,102,97,117,108,116,58,32,37,100,41,10,0,0,0,0,0,0,0,0,69,82,82,79,82,33,32,118,97,108,117,101,32,60,37,115,62,32,105,115,32,116,111,111,32,108,97,114,103,101,32,102,111,114,32,111,112,116,105,111,110,32,34,37,115,34,46,10,0,0,0,0,0,0,0,0,69,82,82,79,82,33,32,118,97,108,117,101,32,60,37,115,62,32,105,115,32,116,111,111,32,115,109,97,108,108,32,102,111,114,32,111,112,116,105,111,110,32,34,37,115,34,46,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,118,97,114,45,100,101,99,97,121,0,0,0,0,0,0,0,84,104,101,32,118,97,114,105,97,98,108,101,32,97,99,116,105,118,105,116,121,32,100,101,99,97,121,32,102,97,99,116,111,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,99,108,97,45,100,101,99,97,121,0,0,0,0,0,0,0,84,104,101,32,99,108,97,117,115,101,32,97,99,116,105,118,105,116,121,32,100,101,99,97,121,32,102,97,99,116,111,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,110,100,45,102,114,101,113,0,0,0,0,0,0,0,0,84,104,101,32,102,114,101,113,117,101,110,99,121,32,119,105,116,104,32,119,104,105,99,104,32,116,104,101,32,100,101,99,105,115,105,111,110,32,104,101,117,114,105,115,116,105,99,32,116,114,105,101,115,32,116,111,32,99,104,111,111,115,101,32,97,32,114,97,110,100,111,109,32,118,97,114,105,97,98,108,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,110,100,45,115,101,101,100,0,0,0,0,0,0,0,0,85,115,101,100,32,98,121,32,116,104,101,32,114,97,110,100,111,109,32,118,97,114,105,97,98,108,101,32,115,101,108,101,99,116,105,111,110,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,99,99,109,105,110,45,109,111,100,101,0,0,0,0,0,0,67,111,110,116,114,111,108,115,32,99,111,110,102,108,105,99,116,32,99,108,97,117,115,101,32,109,105,110,105,109,105,122,97,116,105,111,110,32,40,48,61,110,111,110,101,44,32,49,61,98,97,115,105,99,44,32,50,61,100,101,101,112,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,112,104,97,115,101,45,115,97,118,105,110,103,0,0,0,0,67,111,110,116,114,111,108,115,32,116,104,101,32,108,101,118,101,108,32,111,102,32,112,104,97,115,101,32,115,97,118,105,110,103,32,40,48,61,110,111,110,101,44,32,49,61,108,105,109,105,116,101,100,44,32,50,61,102,117,108,108,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,110,100,45,105,110,105,116,0,0,0,0,0,0,0,0,82,97,110,100,111,109,105,122,101,32,116,104,101,32,105,110,105,116,105,97,108,32,97,99,116,105,118,105,116,121,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,108,117,98,121,0,0,0,0,85,115,101,32,116,104,101,32,76,117,98,121,32,114,101,115,116,97,114,116,32,115,101,113,117,101,110,99,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,102,105,114,115,116,0,0,84,104,101,32,98,97,115,101,32,114,101,115,116,97,114,116,32,105,110,116,101,114,118,97,108,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,105,110,99,0,0,0,0,82,101,115,116,97,114,116,32,105,110,116,101,114,118,97,108,32,105,110,99,114,101,97,115,101,32,102,97,99,116,111,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,99,45,102,114,97,99,0,84,104,101,32,102,114,97,99,116,105,111,110,32,111,102,32,119,97,115,116,101,100,32,109,101,109,111,114,121,32,97,108,108,111,119,101,100,32,98,101,102,111,114,101,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,116,114,105,103,103,101,114,101,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,109,105,110,45,108,101,97,114,110,116,115,0,0,0,0,0,77,105,110,105,109,117,109,32,108,101,97,114,110,116,32,99,108,97,117,115,101,32,108,105,109,105,116,0,0,0,0,0,0,0,0,0,192,7,0,0,5,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,124,32,37,57,100,32,124,32,37,55,100,32,37,56,100,32,37,56,100,32,124,32,37,56,100,32,37,56,100,32,37,54,46,48,102,32,124,32,37,54,46,51,102,32,37,37,32,124,10,0,0,0,0,0,0,0,124,32,32,71,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,58,32,32,32,37,49,50,100,32,98,121,116,101,115,32,61,62,32,37,49,50,100,32,98,121,116,101,115,32,32,32,32,32,32,32,32,32,32,32,32,32,124,10,0,0,0,0,0,0,0,0,78,55,77,105,110,105,115,97,116,54,83,111,108,118,101,114,69,0,0,0,0,0,0,0,88,18,0,0,168,7,0,0,60,98,111,111,108,62,0,0,10,32,32,32,32,32,32,32,32,37,115,10,0,0,0,0,60,105,110,116,51,50,62,0,69,82,82,79,82,33,32,118,97,108,117,101,32,60,37,115,62,32,105,115,32,116,111,111,32,108,97,114,103,101,32,102,111,114,32,111,112,116,105,111,110,32,34,37,115,34,46,10,0,0,0,0,0,0,0,0,69,82,82,79,82,33,32,118,97,108,117,101,32,60,37,115,62,32,105,115,32,116,111,111,32,115,109,97,108,108,32,102,111,114,32,111,112,116,105,111,110,32,34,37,115,34,46,10,0,0,0,0,0,0,0,0,67,79,82,69,0,0,0,0,60,100,111,117,98,108,101,62,0,0,0,0,0,0,0,0,0,0,0,0,168,8,0,0,1,0,0,0,8,0,0,0,3,0,0,0,3,0,0,0,78,55,77,105,110,105,115,97,116,49,50,68,111,117,98,108,101,79,112,116,105,111,110,69,0,0,0,0,0,0,0,0,128,18,0,0,136,8,0,0,80,0,0,0,0,0,0,0,32,32,45,37,45,49,50,115,32,61,32,37,45,56,115,32,37,99,37,52,46,50,103,32,46,46,32,37,52,46,50,103,37,99,32,40,100,101,102,97,117,108,116,58,32,37,103,41,10,0,0,0,0,0,0,0,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,91,32,83,101,97,114,99,104,32,83,116,97,116,105,115,116,105,99,115,32,93,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,0,124,32,67,111,110,102,108,105,99,116,115,32,124,32,32,32,32,32,32,32,32,32,32,79,82,73,71,73,78,65,76,32,32,32,32,32,32,32,32,32,124,32,32,32,32,32,32,32,32,32,32,76,69,65,82,78,84,32,32,32,32,32,32,32,32,32,32,124,32,80,114,111,103,114,101,115,115,32,124,0,124,32,32,32,32,32,32,32,32,32,32,32,124,32,32,32,32,86,97,114,115,32,32,67,108,97,117,115,101,115,32,76,105,116,101,114,97,108,115,32,124,32,32,32,32,76,105,109,105,116,32,32,67,108,97,117,115,101,115,32,76,105,116,47,67,108,32,124,32,32,32,32,32,32,32,32,32,32,124,0,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,97,115,121,109,109,0,0,0,83,104,114,105,110,107,32,99,108,97,117,115,101,115,32,98,121,32,97,115,121,109,109,101,116,114,105,99,32,98,114,97,110,99,104,105,110,103,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,99,104,101,99,107,0,0,67,104,101,99,107,32,105,102,32,97,32,99,108,97,117,115,101,32,105,115,32,97,108,114,101,97,100,121,32,105,109,112,108,105,101,100,46,32,40,99,111,115,116,108,121,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,108,105,109,0,0,0,0,80,101,114,102,111,114,109,32,118,97,114,105,97,98,108,101,32,101,108,105,109,105,110,97,116,105,111,110,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,114,111,119,0,0,0,0,65,108,108,111,119,32,97,32,118,97,114,105,97,98,108,101,32,101,108,105,109,105,110,97,116,105,111,110,32,115,116,101,112,32,116,111,32,103,114,111,119,32,98,121,32,97,32,110,117,109,98,101,114,32,111,102,32,99,108,97,117,115,101,115,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,99,108,45,108,105,109,0,0,86,97,114,105,97,98,108,101,115,32,97,114,101,32,110,111,116,32,101,108,105,109,105,110,97,116,101,100,32,105,102,32,105,116,32,112,114,111,100,117,99,101,115,32,97,32,114,101,115,111,108,118,101,110,116,32,119,105,116,104,32,97,32,108,101,110,103,116,104,32,97,98,111,118,101,32,116,104,105,115,32,108,105,109,105,116,46,32,45,49,32,109,101,97,110,115,32,110,111,32,108,105,109,105,116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,115,117,98,45,108,105,109,0,68,111,32,110,111,116,32,99,104,101,99,107,32,105,102,32,115,117,98,115,117,109,112,116,105,111,110,32,97,103,97,105,110,115,116,32,97,32,99,108,97,117,115,101,32,108,97,114,103,101,114,32,116,104,97,110,32,116,104,105,115,46,32,45,49,32,109,101,97,110,115,32,110,111,32,108,105,109,105,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,115,105,109,112,45,103,99,45,102,114,97,99,0,0,0,0,84,104,101,32,102,114,97,99,116,105,111,110,32,111,102,32,119,97,115,116,101,100,32,109,101,109,111,114,121,32,97,108,108,111,119,101,100,32,98,101,102,111,114,101,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,116,114,105,103,103,101,114,101,100,32,100,117,114,105,110,103,32,115,105,109,112,108,105,102,105,99,97,116,105,111,110,46,0,0,0,0,0,0,0,120,14,0,0,9,0,0,0,10,0,0,0,11,0,0,0,0,0,0,0,115,117,98,115,117,109,112,116,105,111,110,32,108,101,102,116,58,32,37,49,48,100,32,40,37,49,48,100,32,115,117,98,115,117,109,101,100,44,32,37,49,48,100,32,100,101,108,101,116,101,100,32,108,105,116,101,114,97,108,115,41,13,0,0,101,108,105,109,105,110,97,116,105,111,110,32,108,101,102,116,58,32,37,49,48,100,13,0,124,32,32,69,108,105,109,105,110,97,116,101,100,32,99,108,97,117,115,101,115,58,32,32,32,32,32,37,49,48,46,50,102,32,77,98,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,124,10,0,0,0,0,124,32,32,71,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,58,32,32,32,37,49,50,100,32,98,121,116,101,115,32,61,62,32,37,49,50,100,32,98,121,116,101,115,32,32,32,32,32,32,32,32,32,32,32,32,32,124,10,0,0,0,0,0,0,0,0,78,55,77,105,110,105,115,97,116,49,48,83,105,109,112,83,111,108,118,101,114,69,0,0,128,18,0,0,96,14,0,0,192,7,0,0,0,0,0,0,60,100,111,117,98,108,101,62,0,0,0,0,0,0,0,0,60,105,110,116,51,50,62,0,83,73,77,80,0,0,0,0,60,98,111,111,108,62,0,0,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,79,33,0,0,0,0,0,2,0,0,0,0,0,0,0,48,15,0,0,0,0,0,0,117,110,99,97,117,103,104,116,0,0,0,0,0,0,0,0,116,101,114,109,105,110,97,116,105,110,103,32,119,105,116,104,32,37,115,32,101,120,99,101,112,116,105,111,110,32,111,102,32,116,121,112,101,32,37,115,58,32,37,115,0,0,0,0,116,101,114,109,105,110,97,116,105,110,103,32,119,105,116,104,32,37,115,32,101,120,99,101,112,116,105,111,110,32,111,102,32,116,121,112,101,32,37,115,0,0,0,0,0,0,0,0,116,101,114,109,105,110,97,116,105,110,103,32,119,105,116,104,32,37,115,32,102,111,114,101,105,103,110,32,101,120,99,101,112,116,105,111,110,0,0,0,116,101,114,109,105,110,97,116,105,110,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,112,116,104,114,101,97,100,95,111,110,99,101,32,102,97,105,108,117,114,101,32,105,110,32,95,95,99,120,97,95,103,101,116,95,103,108,111,98,97,108,115,95,102,97,115,116,40,41,0,0,0,0,0,0,0,0,99,97,110,110,111,116,32,99,114,101,97,116,101,32,112,116,104,114,101,97,100,32,107,101,121,32,102,111,114,32,95,95,99,120,97,95,103,101,116,95,103,108,111,98,97,108,115,40,41,0,0,0,0,0,0,0,99,97,110,110,111,116,32,122,101,114,111,32,111,117,116,32,116,104,114,101,97,100,32,118,97,108,117,101,32,102,111,114,32,95,95,99,120,97,95,103,101,116,95,103,108,111,98,97,108,115,40,41,0,0,0,0,0,0,0,0,200,16,0,0,12,0,0,0,13,0,0,0,1,0,0,0,0,0,0,0,115,116,100,58,58,98,97,100,95,97,108,108,111,99,0,0,83,116,57,98,97,100,95,97,108,108,111,99,0,0,0,0,128,18,0,0,184,16,0,0,80,17,0,0,0,0,0,0,116,101,114,109,105,110,97,116,101,95,104,97,110,100,108,101,114,32,117,110,101,120,112,101,99,116,101,100,108,121,32,114,101,116,117,114,110,101,100,0,116,101,114,109,105,110,97,116,101,95,104,97,110,100,108,101,114,32,117,110,101,120,112,101,99,116,101,100,108,121,32,116,104,114,101,119,32,97,110,32,101,120,99,101,112,116,105,111,110,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,116,57,101,120,99,101,112,116,105,111,110,0,0,0,0,88,18,0,0,64,17,0,0,83,116,57,116,121,112,101,95,105,110,102,111,0,0,0,0,88,18,0,0,88,17,0,0,78,49,48,95,95,99,120,120,97,98,105,118,49,49,54,95,95,115,104,105,109,95,116,121,112,101,95,105,110,102,111,69,0,0,0,0,0,0,0,0,128,18,0,0,112,17,0,0,104,17,0,0,0,0,0,0,78,49,48,95,95,99,120,120,97,98,105,118,49,49,55,95,95,99,108,97,115,115,95,116,121,112,101,95,105,110,102,111,69,0,0,0,0,0,0,0,128,18,0,0,168,17,0,0,152,17,0,0,0,0,0,0,78,49,48,95,95,99,120,120,97,98,105,118,49,49,57,95,95,112,111,105,110,116,101,114,95,116,121,112,101,95,105,110,102,111,69,0,0,0,0,0,78,49,48,95,95,99,120,120,97,98,105,118,49,49,55,95,95,112,98,97,115,101,95,116,121,112,101,95,105,110,102,111,69,0,0,0,0,0,0,0,128,18,0,0,8,18,0,0,152,17,0,0,0,0,0,0,128,18,0,0,224,17,0,0,48,18,0,0,0,0,0,0,0,0,0,0,208,17,0,0,14,0,0,0,15,0,0,0,16,0,0,0,17,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,200,18,0,0,14,0,0,0,18,0,0,0,16,0,0,0,17,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,78,49,48,95,95,99,120,120,97,98,105,118,49,50,48,95,95,115,105,95,99,108,97,115,115,95,116,121,112,101,95,105,110,102,111,69,0,0,0,0,128,18,0,0,160,18,0,0,208,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,1,2,3,4,5,6,7,8,9,255,255,255,255,255,255,255,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,255,255,255,255,255,255,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,1,2,4,7,3,6,5,0,0,0,0,0,0,0,0,105,110,102,105,110,105,116,121,0,0,0,0,0,0,0,0,110,97,110,0,0,0,0,0,95,112,137,0,255,9,47,15,10,0,0,0,100,0,0,0,232,3,0,0,16,39,0,0,160,134,1,0,64,66,15,0,128,150,152,0,0,225,245,5],\"i8\",ALLOC_NONE,Runtime.GLOBAL_BASE);var tempDoublePtr=Runtime.alignMemory(allocate(12,\"i8\",ALLOC_STATIC),8);assert(tempDoublePtr%8==0);function copyTempFloat(ptr){HEAP8[tempDoublePtr]=HEAP8[ptr];HEAP8[tempDoublePtr+1]=HEAP8[ptr+1];HEAP8[tempDoublePtr+2]=HEAP8[ptr+2];HEAP8[tempDoublePtr+3]=HEAP8[ptr+3]}function copyTempDouble(ptr){HEAP8[tempDoublePtr]=HEAP8[ptr];HEAP8[tempDoublePtr+1]=HEAP8[ptr+1];HEAP8[tempDoublePtr+2]=HEAP8[ptr+2];HEAP8[tempDoublePtr+3]=HEAP8[ptr+3];HEAP8[tempDoublePtr+4]=HEAP8[ptr+4];HEAP8[tempDoublePtr+5]=HEAP8[ptr+5];HEAP8[tempDoublePtr+6]=HEAP8[ptr+6];HEAP8[tempDoublePtr+7]=HEAP8[ptr+7]}function _atexit(func,arg){__ATEXIT__.unshift({func:func,arg:arg})}function ___cxa_atexit(){return _atexit.apply(null,arguments)}Module[\"_i64Subtract\"]=_i64Subtract;var ___errno_state=0;function ___setErrNo(value){HEAP32[___errno_state>>2]=value;return value}var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};function _sysconf(name){switch(name){case 30:return PAGE_SIZE;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 79:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return-1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator===\"object\")return navigator[\"hardwareConcurrency\"]||1;return 1}}___setErrNo(ERRNO_CODES.EINVAL);return-1}function __ZSt18uncaught_exceptionv(){return!!__ZSt18uncaught_exceptionv.uncaught_exception}var EXCEPTIONS={last:0,caught:[],infos:{},deAdjust:(function(adjusted){if(!adjusted||EXCEPTIONS.infos[adjusted])return adjusted;for(var ptr in EXCEPTIONS.infos){var info=EXCEPTIONS.infos[ptr];if(info.adjusted===adjusted){return ptr}}return adjusted}),addRef:(function(ptr){if(!ptr)return;var info=EXCEPTIONS.infos[ptr];info.refcount++}),decRef:(function(ptr){if(!ptr)return;var info=EXCEPTIONS.infos[ptr];assert(info.refcount>0);info.refcount--;if(info.refcount===0){if(info.destructor){Runtime.dynCall(\"vi\",info.destructor,[ptr])}delete EXCEPTIONS.infos[ptr];___cxa_free_exception(ptr)}}),clearRef:(function(ptr){if(!ptr)return;var info=EXCEPTIONS.infos[ptr];info.refcount=0})};function ___resumeException(ptr){if(!EXCEPTIONS.last){EXCEPTIONS.last=ptr}EXCEPTIONS.clearRef(EXCEPTIONS.deAdjust(ptr));throw ptr+\" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.\"}function ___cxa_find_matching_catch(){var thrown=EXCEPTIONS.last;if(!thrown){return(asm[\"setTempRet0\"](0),0)|0}var info=EXCEPTIONS.infos[thrown];var throwntype=info.type;if(!throwntype){return(asm[\"setTempRet0\"](0),thrown)|0}var typeArray=Array.prototype.slice.call(arguments);var pointer=Module[\"___cxa_is_pointer_type\"](throwntype);if(!___cxa_find_matching_catch.buffer)___cxa_find_matching_catch.buffer=_malloc(4);HEAP32[___cxa_find_matching_catch.buffer>>2]=thrown;thrown=___cxa_find_matching_catch.buffer;for(var i=0;i<typeArray.length;i++){if(typeArray[i]&&Module[\"___cxa_can_catch\"](typeArray[i],throwntype,thrown)){thrown=HEAP32[thrown>>2];info.adjusted=thrown;return(asm[\"setTempRet0\"](typeArray[i]),thrown)|0}}thrown=HEAP32[thrown>>2];return(asm[\"setTempRet0\"](throwntype),thrown)|0}function ___cxa_throw(ptr,type,destructor){EXCEPTIONS.infos[ptr]={ptr:ptr,adjusted:ptr,type:type,destructor:destructor,refcount:0};EXCEPTIONS.last=ptr;if(!(\"uncaught_exception\"in __ZSt18uncaught_exceptionv)){__ZSt18uncaught_exceptionv.uncaught_exception=1}else{__ZSt18uncaught_exceptionv.uncaught_exception++}throw ptr+\" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.\"}Module[\"_memset\"]=_memset;Module[\"_bitshift64Shl\"]=_bitshift64Shl;function _abort(){Module[\"abort\"]()}var FS=undefined;var SOCKFS=undefined;function _send(fd,buf,len,flags){var sock=SOCKFS.getSocket(fd);if(!sock){___setErrNo(ERRNO_CODES.EBADF);return-1}return _write(fd,buf,len)}function _pwrite(fildes,buf,nbyte,offset){var stream=FS.getStream(fildes);if(!stream){___setErrNo(ERRNO_CODES.EBADF);return-1}try{var slab=HEAP8;return FS.write(stream,slab,buf,nbyte,offset)}catch(e){FS.handleFSError(e);return-1}}function _write(fildes,buf,nbyte){var stream=FS.getStream(fildes);if(!stream){___setErrNo(ERRNO_CODES.EBADF);return-1}try{var slab=HEAP8;return FS.write(stream,slab,buf,nbyte)}catch(e){FS.handleFSError(e);return-1}}function _fileno(stream){stream=FS.getStreamFromPtr(stream);if(!stream)return-1;return stream.fd}function _fwrite(ptr,size,nitems,stream){var bytesToWrite=nitems*size;if(bytesToWrite==0)return 0;var fd=_fileno(stream);var bytesWritten=_write(fd,ptr,bytesToWrite);if(bytesWritten==-1){var streamObj=FS.getStreamFromPtr(stream);if(streamObj)streamObj.error=true;return 0}else{return bytesWritten/size|0}}Module[\"_strlen\"]=_strlen;function __reallyNegative(x){return x<0||x===0&&1/x===-Infinity}function __formatString(format,varargs){var textIndex=format;var argIndex=0;function getNextArg(type){var ret;if(type===\"double\"){ret=(HEAP32[tempDoublePtr>>2]=HEAP32[varargs+argIndex>>2],HEAP32[tempDoublePtr+4>>2]=HEAP32[varargs+(argIndex+4)>>2],+HEAPF64[tempDoublePtr>>3])}else if(type==\"i64\"){ret=[HEAP32[varargs+argIndex>>2],HEAP32[varargs+(argIndex+4)>>2]]}else{type=\"i32\";ret=HEAP32[varargs+argIndex>>2]}argIndex+=Runtime.getNativeFieldSize(type);return ret}var ret=[];var curr,next,currArg;while(1){var startTextIndex=textIndex;curr=HEAP8[textIndex>>0];if(curr===0)break;next=HEAP8[textIndex+1>>0];if(curr==37){var flagAlwaysSigned=false;var flagLeftAlign=false;var flagAlternative=false;var flagZeroPad=false;var flagPadSign=false;flagsLoop:while(1){switch(next){case 43:flagAlwaysSigned=true;break;case 45:flagLeftAlign=true;break;case 35:flagAlternative=true;break;case 48:if(flagZeroPad){break flagsLoop}else{flagZeroPad=true;break};case 32:flagPadSign=true;break;default:break flagsLoop}textIndex++;next=HEAP8[textIndex+1>>0]}var width=0;if(next==42){width=getNextArg(\"i32\");textIndex++;next=HEAP8[textIndex+1>>0]}else{while(next>=48&&next<=57){width=width*10+(next-48);textIndex++;next=HEAP8[textIndex+1>>0]}}var precisionSet=false,precision=-1;if(next==46){precision=0;precisionSet=true;textIndex++;next=HEAP8[textIndex+1>>0];if(next==42){precision=getNextArg(\"i32\");textIndex++}else{while(1){var precisionChr=HEAP8[textIndex+1>>0];if(precisionChr<48||precisionChr>57)break;precision=precision*10+(precisionChr-48);textIndex++}}next=HEAP8[textIndex+1>>0]}if(precision<0){precision=6;precisionSet=false}var argSize;switch(String.fromCharCode(next)){case\"h\":var nextNext=HEAP8[textIndex+2>>0];if(nextNext==104){textIndex++;argSize=1}else{argSize=2}break;case\"l\":var nextNext=HEAP8[textIndex+2>>0];if(nextNext==108){textIndex++;argSize=8}else{argSize=4}break;case\"L\":case\"q\":case\"j\":argSize=8;break;case\"z\":case\"t\":case\"I\":argSize=4;break;default:argSize=null}if(argSize)textIndex++;next=HEAP8[textIndex+1>>0];switch(String.fromCharCode(next)){case\"d\":case\"i\":case\"u\":case\"o\":case\"x\":case\"X\":case\"p\":{var signed=next==100||next==105;argSize=argSize||4;var currArg=getNextArg(\"i\"+argSize*8);var origArg=currArg;var argText;if(argSize==8){currArg=Runtime.makeBigInt(currArg[0],currArg[1],next==117)}if(argSize<=4){var limit=Math.pow(256,argSize)-1;currArg=(signed?reSign:unSign)(currArg&limit,argSize*8)}var currAbsArg=Math.abs(currArg);var prefix=\"\";if(next==100||next==105){if(argSize==8&&i64Math)argText=i64Math.stringify(origArg[0],origArg[1],null);else argText=reSign(currArg,8*argSize,1).toString(10)}else if(next==117){if(argSize==8&&i64Math)argText=i64Math.stringify(origArg[0],origArg[1],true);else argText=unSign(currArg,8*argSize,1).toString(10);currArg=Math.abs(currArg)}else if(next==111){argText=(flagAlternative?\"0\":\"\")+currAbsArg.toString(8)}else if(next==120||next==88){prefix=flagAlternative&&currArg!=0?\"0x\":\"\";if(argSize==8&&i64Math){if(origArg[1]){argText=(origArg[1]>>>0).toString(16);var lower=(origArg[0]>>>0).toString(16);while(lower.length<8)lower=\"0\"+lower;argText+=lower}else{argText=(origArg[0]>>>0).toString(16)}}else if(currArg<0){currArg=-currArg;argText=(currAbsArg-1).toString(16);var buffer=[];for(var i=0;i<argText.length;i++){buffer.push((15-parseInt(argText[i],16)).toString(16))}argText=buffer.join(\"\");while(argText.length<argSize*2)argText=\"f\"+argText}else{argText=currAbsArg.toString(16)}if(next==88){prefix=prefix.toUpperCase();argText=argText.toUpperCase()}}else if(next==112){if(currAbsArg===0){argText=\"(nil)\"}else{prefix=\"0x\";argText=currAbsArg.toString(16)}}if(precisionSet){while(argText.length<precision){argText=\"0\"+argText}}if(currArg>=0){if(flagAlwaysSigned){prefix=\"+\"+prefix}else if(flagPadSign){prefix=\" \"+prefix}}if(argText.charAt(0)==\"-\"){prefix=\"-\"+prefix;argText=argText.substr(1)}while(prefix.length+argText.length<width){if(flagLeftAlign){argText+=\" \"}else{if(flagZeroPad){argText=\"0\"+argText}else{prefix=\" \"+prefix}}}argText=prefix+argText;argText.split(\"\").forEach((function(chr){ret.push(chr.charCodeAt(0))}));break};case\"f\":case\"F\":case\"e\":case\"E\":case\"g\":case\"G\":{var currArg=getNextArg(\"double\");var argText;if(isNaN(currArg)){argText=\"nan\";flagZeroPad=false}else if(!isFinite(currArg)){argText=(currArg<0?\"-\":\"\")+\"inf\";flagZeroPad=false}else{var isGeneral=false;var effectivePrecision=Math.min(precision,20);if(next==103||next==71){isGeneral=true;precision=precision||1;var exponent=parseInt(currArg.toExponential(effectivePrecision).split(\"e\")[1],10);if(precision>exponent&&exponent>=-4){next=(next==103?\"f\":\"F\").charCodeAt(0);precision-=exponent+1}else{next=(next==103?\"e\":\"E\").charCodeAt(0);precision--}effectivePrecision=Math.min(precision,20)}if(next==101||next==69){argText=currArg.toExponential(effectivePrecision);if(/[eE][-+]\\d$/.test(argText)){argText=argText.slice(0,-1)+\"0\"+argText.slice(-1)}}else if(next==102||next==70){argText=currArg.toFixed(effectivePrecision);if(currArg===0&&__reallyNegative(currArg)){argText=\"-\"+argText}}var parts=argText.split(\"e\");if(isGeneral&&!flagAlternative){while(parts[0].length>1&&parts[0].indexOf(\".\")!=-1&&(parts[0].slice(-1)==\"0\"||parts[0].slice(-1)==\".\")){parts[0]=parts[0].slice(0,-1)}}else{if(flagAlternative&&argText.indexOf(\".\")==-1)parts[0]+=\".\";while(precision>effectivePrecision++)parts[0]+=\"0\"}argText=parts[0]+(parts.length>1?\"e\"+parts[1]:\"\");if(next==69)argText=argText.toUpperCase();if(currArg>=0){if(flagAlwaysSigned){argText=\"+\"+argText}else if(flagPadSign){argText=\" \"+argText}}}while(argText.length<width){if(flagLeftAlign){argText+=\" \"}else{if(flagZeroPad&&(argText[0]==\"-\"||argText[0]==\"+\")){argText=argText[0]+\"0\"+argText.slice(1)}else{argText=(flagZeroPad?\"0\":\" \")+argText}}}if(next<97)argText=argText.toUpperCase();argText.split(\"\").forEach((function(chr){ret.push(chr.charCodeAt(0))}));break};case\"s\":{var arg=getNextArg(\"i8*\");var argLength=arg?_strlen(arg):\"(null)\".length;if(precisionSet)argLength=Math.min(argLength,precision);if(!flagLeftAlign){while(argLength<width--){ret.push(32)}}if(arg){for(var i=0;i<argLength;i++){ret.push(HEAPU8[arg++>>0])}}else{ret=ret.concat(intArrayFromString(\"(null)\".substr(0,argLength),true))}if(flagLeftAlign){while(argLength<width--){ret.push(32)}}break};case\"c\":{if(flagLeftAlign)ret.push(getNextArg(\"i8\"));while(--width>0){ret.push(32)}if(!flagLeftAlign)ret.push(getNextArg(\"i8\"));break};case\"n\":{var ptr=getNextArg(\"i32*\");HEAP32[ptr>>2]=ret.length;break};case\"%\":{ret.push(curr);break};default:{for(var i=startTextIndex;i<textIndex+2;i++){ret.push(HEAP8[i>>0])}}}textIndex+=2}else{ret.push(curr);textIndex+=1}}return ret}function _fprintf(stream,format,varargs){var result=__formatString(format,varargs);var stack=Runtime.stackSave();var ret=_fwrite(allocate(result,\"i8\",ALLOC_STACK),1,result.length,stream);Runtime.stackRestore(stack);return ret}function _printf(format,varargs){var result=__formatString(format,varargs);var string=intArrayToString(result);if(string[string.length-1]===\"\\n\")string=string.substr(0,string.length-1);Module.print(string);return result.length}function _pthread_once(ptr,func){if(!_pthread_once.seen)_pthread_once.seen={};if(ptr in _pthread_once.seen)return;Runtime.dynCall(\"v\",func);_pthread_once.seen[ptr]=1}function _fputc(c,stream){var chr=unSign(c&255);HEAP8[_fputc.ret>>0]=chr;var fd=_fileno(stream);var ret=_write(fd,_fputc.ret,1);if(ret==-1){var streamObj=FS.getStreamFromPtr(stream);if(streamObj)streamObj.error=true;return-1}else{return chr}}var PTHREAD_SPECIFIC={};function _pthread_getspecific(key){return PTHREAD_SPECIFIC[key]||0}Module[\"_i64Add\"]=_i64Add;function _fputs(s,stream){var fd=_fileno(stream);return _write(fd,s,_strlen(s))}var _stdout=allocate(1,\"i32*\",ALLOC_STATIC);function _puts(s){var result=Pointer_stringify(s);var string=result.substr(0);if(string[string.length-1]===\"\\n\")string=string.substr(0,string.length-1);Module.print(string);return result.length}function _pthread_setspecific(key,value){if(!(key in PTHREAD_SPECIFIC)){return ERRNO_CODES.EINVAL}PTHREAD_SPECIFIC[key]=value;return 0}function __exit(status){Module[\"exit\"](status)}function _exit(status){__exit(status)}var _UItoD=true;function _malloc(bytes){var ptr=Runtime.dynamicAlloc(bytes+8);return ptr+8&4294967288}Module[\"_malloc\"]=_malloc;function ___cxa_allocate_exception(size){return _malloc(size)}function _fmod(x,y){return x%y}function _fmodl(){return _fmod.apply(null,arguments)}Module[\"_bitshift64Lshr\"]=_bitshift64Lshr;function ___cxa_pure_virtual(){ABORT=true;throw\"Pure virtual function called!\"}function _time(ptr){var ret=Date.now()/1e3|0;if(ptr){HEAP32[ptr>>2]=ret}return ret}var PTHREAD_SPECIFIC_NEXT_KEY=1;function _pthread_key_create(key,destructor){if(key==0){return ERRNO_CODES.EINVAL}HEAP32[key>>2]=PTHREAD_SPECIFIC_NEXT_KEY;PTHREAD_SPECIFIC[PTHREAD_SPECIFIC_NEXT_KEY]=0;PTHREAD_SPECIFIC_NEXT_KEY++;return 0}function ___cxa_guard_acquire(variable){if(!HEAP8[variable>>0]){HEAP8[variable>>0]=1;return 1}return 0}function ___cxa_guard_release(){}function _vfprintf(s,f,va_arg){return _fprintf(s,f,HEAP32[va_arg>>2])}function ___cxa_begin_catch(ptr){__ZSt18uncaught_exceptionv.uncaught_exception--;EXCEPTIONS.caught.push(ptr);EXCEPTIONS.addRef(EXCEPTIONS.deAdjust(ptr));return ptr}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest);return dest}Module[\"_memcpy\"]=_memcpy;var _llvm_pow_f64=Math_pow;function _sbrk(bytes){var self=_sbrk;if(!self.called){DYNAMICTOP=alignMemoryPage(DYNAMICTOP);self.called=true;assert(Runtime.dynamicAlloc);self.alloc=Runtime.dynamicAlloc;Runtime.dynamicAlloc=(function(){abort(\"cannot dynamically allocate, sbrk now has control\")})}var ret=DYNAMICTOP;if(bytes!=0)self.alloc(bytes);return ret}var _fabs=Math_abs;function ___errno_location(){return ___errno_state}var _BItoD=true;function _copysign(a,b){return __reallyNegative(a)===__reallyNegative(b)?a:-a}function _copysignl(){return _copysign.apply(null,arguments)}var ___dso_handle=allocate(1,\"i32*\",ALLOC_STATIC);var _stderr=allocate(1,\"i32*\",ALLOC_STATIC);___errno_state=Runtime.staticAlloc(4);HEAP32[___errno_state>>2]=0;_fputc.ret=allocate([0],\"i8\",ALLOC_STATIC);STACK_BASE=STACKTOP=Runtime.alignMemory(STATICTOP);staticSealed=true;STACK_MAX=STACK_BASE+TOTAL_STACK;DYNAMIC_BASE=DYNAMICTOP=Runtime.alignMemory(STACK_MAX);assert(DYNAMIC_BASE<TOTAL_MEMORY,\"TOTAL_MEMORY not big enough for stack\");var ctlz_i8=allocate([8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"i8\",ALLOC_DYNAMIC);var cttz_i8=allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0],\"i8\",ALLOC_DYNAMIC);function invoke_iiii(index,a1,a2,a3){try{return Module[\"dynCall_iiii\"](index,a1,a2,a3)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;asm[\"setThrew\"](1,0)}}function invoke_viiiii(index,a1,a2,a3,a4,a5){try{Module[\"dynCall_viiiii\"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;asm[\"setThrew\"](1,0)}}function invoke_vi(index,a1){try{Module[\"dynCall_vi\"](index,a1)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;asm[\"setThrew\"](1,0)}}function invoke_vii(index,a1,a2){try{Module[\"dynCall_vii\"](index,a1,a2)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;asm[\"setThrew\"](1,0)}}function invoke_ii(index,a1){try{return Module[\"dynCall_ii\"](index,a1)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;asm[\"setThrew\"](1,0)}}function invoke_v(index){try{Module[\"dynCall_v\"](index)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;asm[\"setThrew\"](1,0)}}function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){try{Module[\"dynCall_viiiiii\"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;asm[\"setThrew\"](1,0)}}function invoke_iii(index,a1,a2){try{return Module[\"dynCall_iii\"](index,a1,a2)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;asm[\"setThrew\"](1,0)}}function invoke_viiii(index,a1,a2,a3,a4){try{Module[\"dynCall_viiii\"](index,a1,a2,a3,a4)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;asm[\"setThrew\"](1,0)}}Module.asmGlobalArg={\"Math\":Math,\"Int8Array\":Int8Array,\"Int16Array\":Int16Array,\"Int32Array\":Int32Array,\"Uint8Array\":Uint8Array,\"Uint16Array\":Uint16Array,\"Uint32Array\":Uint32Array,\"Float32Array\":Float32Array,\"Float64Array\":Float64Array};Module.asmLibraryArg={\"abort\":abort,\"assert\":assert,\"min\":Math_min,\"invoke_iiii\":invoke_iiii,\"invoke_viiiii\":invoke_viiiii,\"invoke_vi\":invoke_vi,\"invoke_vii\":invoke_vii,\"invoke_ii\":invoke_ii,\"invoke_v\":invoke_v,\"invoke_viiiiii\":invoke_viiiiii,\"invoke_iii\":invoke_iii,\"invoke_viiii\":invoke_viiii,\"_fabs\":_fabs,\"_llvm_pow_f64\":_llvm_pow_f64,\"_send\":_send,\"_fmod\":_fmod,\"___cxa_guard_acquire\":___cxa_guard_acquire,\"___setErrNo\":___setErrNo,\"_vfprintf\":_vfprintf,\"___cxa_allocate_exception\":___cxa_allocate_exception,\"___cxa_find_matching_catch\":___cxa_find_matching_catch,\"___cxa_guard_release\":___cxa_guard_release,\"_pwrite\":_pwrite,\"__reallyNegative\":__reallyNegative,\"_sbrk\":_sbrk,\"___cxa_begin_catch\":___cxa_begin_catch,\"_emscripten_memcpy_big\":_emscripten_memcpy_big,\"_fileno\":_fileno,\"___resumeException\":___resumeException,\"__ZSt18uncaught_exceptionv\":__ZSt18uncaught_exceptionv,\"_sysconf\":_sysconf,\"_pthread_getspecific\":_pthread_getspecific,\"_atexit\":_atexit,\"_pthread_once\":_pthread_once,\"_puts\":_puts,\"_printf\":_printf,\"_pthread_key_create\":_pthread_key_create,\"_write\":_write,\"___errno_location\":___errno_location,\"_pthread_setspecific\":_pthread_setspecific,\"___cxa_atexit\":___cxa_atexit,\"_copysign\":_copysign,\"_fputc\":_fputc,\"___cxa_throw\":___cxa_throw,\"__exit\":__exit,\"_copysignl\":_copysignl,\"_abort\":_abort,\"_fwrite\":_fwrite,\"_time\":_time,\"_fprintf\":_fprintf,\"__formatString\":__formatString,\"_fputs\":_fputs,\"_exit\":_exit,\"___cxa_pure_virtual\":___cxa_pure_virtual,\"_fmodl\":_fmodl,\"STACKTOP\":STACKTOP,\"STACK_MAX\":STACK_MAX,\"tempDoublePtr\":tempDoublePtr,\"ABORT\":ABORT,\"cttz_i8\":cttz_i8,\"ctlz_i8\":ctlz_i8,\"NaN\":NaN,\"Infinity\":Infinity,\"___dso_handle\":___dso_handle,\"_stderr\":_stderr};// EMSCRIPTEN_START_ASM\nvar asm=(function(global,env,buffer) {\n\"use asm\";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.tempDoublePtr|0;var l=env.ABORT|0;var m=env.cttz_i8|0;var n=env.ctlz_i8|0;var o=env.___dso_handle|0;var p=env._stderr|0;var q=0;var r=0;var s=0;var t=0;var u=+env.NaN,v=+env.Infinity;var w=0,x=0,y=0,z=0,A=0.0,B=0,C=0,D=0,E=0.0;var F=0;var G=0;var H=0;var I=0;var J=0;var K=0;var L=0;var M=0;var N=0;var O=0;var P=global.Math.floor;var Q=global.Math.abs;var R=global.Math.sqrt;var S=global.Math.pow;var T=global.Math.cos;var U=global.Math.sin;var V=global.Math.tan;var W=global.Math.acos;var X=global.Math.asin;var Y=global.Math.atan;var Z=global.Math.atan2;var _=global.Math.exp;var $=global.Math.log;var aa=global.Math.ceil;var ba=global.Math.imul;var ca=env.abort;var da=env.assert;var ea=env.min;var fa=env.invoke_iiii;var ga=env.invoke_viiiii;var ha=env.invoke_vi;var ia=env.invoke_vii;var ja=env.invoke_ii;var ka=env.invoke_v;var la=env.invoke_viiiiii;var ma=env.invoke_iii;var na=env.invoke_viiii;var oa=env._fabs;var pa=env._llvm_pow_f64;var qa=env._send;var ra=env._fmod;var sa=env.___cxa_guard_acquire;var ta=env.___setErrNo;var ua=env._vfprintf;var va=env.___cxa_allocate_exception;var wa=env.___cxa_find_matching_catch;var xa=env.___cxa_guard_release;var ya=env._pwrite;var za=env.__reallyNegative;var Aa=env._sbrk;var Ba=env.___cxa_begin_catch;var Ca=env._emscripten_memcpy_big;var Da=env._fileno;var Ea=env.___resumeException;var Fa=env.__ZSt18uncaught_exceptionv;var Ga=env._sysconf;var Ha=env._pthread_getspecific;var Ia=env._atexit;var Ja=env._pthread_once;var Ka=env._puts;var La=env._printf;var Ma=env._pthread_key_create;var Na=env._write;var Oa=env.___errno_location;var Pa=env._pthread_setspecific;var Qa=env.___cxa_atexit;var Ra=env._copysign;var Sa=env._fputc;var Ta=env.___cxa_throw;var Ua=env.__exit;var Va=env._copysignl;var Wa=env._abort;var Xa=env._fwrite;var Ya=env._time;var Za=env._fprintf;var _a=env.__formatString;var $a=env._fputs;var ab=env._exit;var bb=env.___cxa_pure_virtual;var cb=env._fmodl;var db=0.0;\n// EMSCRIPTEN_START_FUNCS\nfunction nb(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+15&-16;return b|0}function ob(){return i|0}function pb(a){a=a|0;i=a}function qb(a,b){a=a|0;b=b|0;if(!q){q=a;r=b}}function rb(b){b=b|0;a[k>>0]=a[b>>0];a[k+1>>0]=a[b+1>>0];a[k+2>>0]=a[b+2>>0];a[k+3>>0]=a[b+3>>0]}function sb(b){b=b|0;a[k>>0]=a[b>>0];a[k+1>>0]=a[b+1>>0];a[k+2>>0]=a[b+2>>0];a[k+3>>0]=a[b+3>>0];a[k+4>>0]=a[b+4>>0];a[k+5>>0]=a[b+5>>0];a[k+6>>0]=a[b+6>>0];a[k+7>>0]=a[b+7>>0]}function tb(a){a=a|0;F=a}function ub(){return F|0}function vb(a){a=a|0;Ba(a|0)|0;ud()}function wb(a){a=a|0;return}function xb(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0;h=i;c[b>>2]=112;c[b+4>>2]=d;c[b+8>>2]=e;c[b+12>>2]=f;c[b+16>>2]=g;if((a[144]|0)==0?(sa(144)|0)!=0:0){c[32]=0;c[33]=0;c[34]=0;Qa(19,128,o|0)|0;xa(144)}g=c[33]|0;if((g|0)==(c[34]|0)){f=(g>>1)+2&-2;f=(f|0)<2?2:f;if((f|0)>(2147483647-g|0)){d=va(1)|0;Ta(d|0,48,0)}e=c[32]|0;d=f+g|0;c[34]=d;d=Ud(e,d<<2)|0;c[32]=d;if((d|0)==0?(c[(Oa()|0)>>2]|0)==12:0){d=va(1)|0;Ta(d|0,48,0)}g=c[33]|0}c[33]=g+1;g=(c[32]|0)+(g<<2)|0;if(!g){i=h;return}c[g>>2]=b;i=h;return}function yb(a){a=a|0;var b=0;b=i;pd(a);i=b;return}function zb(a){a=a|0;var b=0,d=0;b=i;d=c[a>>2]|0;if(!d){i=b;return}c[a+4>>2]=0;Td(d);c[a>>2]=0;c[a+8>>2]=0;i=b;return}function Ab(a){a=a|0;var b=0;b=i;pd(a);i=b;return}function Bb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;if((a[d>>0]|0)!=45){k=0;i=e;return k|0}f=d+1|0;g=110;j=f;k=0;while(1){h=k+1|0;if((a[j>>0]|0)!=g<<24>>24){g=1;break}j=d+(k+2)|0;if((h|0)==3){g=0;f=j;break}else{g=a[264+h>>0]|0;k=h}}if(ee(f,c[b+4>>2]|0)|0){k=0;i=e;return k|0}a[b+20>>0]=g;k=1;i=e;return k|0}function Cb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;h=i;i=i+16|0;e=h;f=c[p>>2]|0;g=b+4|0;j=c[g>>2]|0;c[e>>2]=j;c[e+4>>2]=j;Za(f|0,216,e|0)|0;j=0;while(1){k=j>>>0<(32-((me(c[g>>2]|0)|0)<<1)|0)>>>0;Sa(32,f|0)|0;if(k)j=j+1|0;else break}c[e>>2]=(a[b+20>>0]|0)!=0?248:256;Za(f|0,232,e|0)|0;if(!d){i=h;return}c[e>>2]=c[b+8>>2];Za(f|0,88,e|0)|0;Sa(10,f|0)|0;i=h;return}function Db(a){a=a|0;var b=0;b=i;pd(a);i=b;return}function Eb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;i=i+16|0;h=e;g=e+8|0;if((a[d>>0]|0)!=45){n=0;i=e;return n|0}l=d+1|0;f=b+4|0;j=c[f>>2]|0;k=a[j>>0]|0;a:do if(k<<24>>24){m=0;while(1){n=m;m=m+1|0;if((a[l>>0]|0)!=k<<24>>24){b=0;break}k=a[j+m>>0]|0;l=d+(n+2)|0;if(!(k<<24>>24))break a}i=e;return b|0}while(0);if((a[l>>0]|0)!=61){n=0;i=e;return n|0}d=l+1|0;j=de(d,g,10)|0;if(!(c[g>>2]|0)){n=0;i=e;return n|0}if((j|0)>(c[b+24>>2]|0)){n=c[p>>2]|0;m=c[f>>2]|0;c[h>>2]=d;c[h+4>>2]=m;Za(n|0,416,h|0)|0;ab(1)}if((j|0)<(c[b+20>>2]|0)){n=c[p>>2]|0;m=c[f>>2]|0;c[h>>2]=d;c[h+4>>2]=m;Za(n|0,472,h|0)|0;ab(1)}c[b+28>>2]=j;n=1;i=e;return n|0}function Fb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;i=i+16|0;e=d;f=c[p>>2]|0;g=c[a+16>>2]|0;c[e>>2]=c[a+4>>2];c[e+4>>2]=g;Za(f|0,336,e|0)|0;g=c[a+20>>2]|0;if((g|0)==-2147483648)Xa(360,4,1,f|0)|0;else{c[e>>2]=g;Za(f|0,368,e|0)|0}Xa(376,4,1,f|0)|0;g=c[a+24>>2]|0;if((g|0)==2147483647)Xa(384,4,1,f|0)|0;else{c[e>>2]=g;Za(f|0,368,e|0)|0}c[e>>2]=c[a+28>>2];Za(f|0,392,e|0)|0;if(!b){i=d;return}c[e>>2]=c[a+8>>2];Za(f|0,88,e|0)|0;Sa(10,f|0)|0;i=d;return}function Gb(b){b=b|0;var d=0,e=0,f=0,g=0,j=0;g=i;c[b>>2]=1816;f=b+4|0;e=b+32|0;j=b+48|0;c[f+0>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=0;c[e+0>>2]=0;c[e+4>>2]=0;c[e+8>>2]=0;c[e+12>>2]=0;h[j>>3]=+h[75];h[b+56>>3]=+h[89];h[b+64>>3]=+h[103];h[b+72>>3]=+h[123];a[b+80>>0]=a[1364]|0;c[b+84>>2]=c[269];c[b+88>>2]=c[297];a[b+92>>0]=0;a[b+93>>0]=a[1292]|0;h[b+96>>3]=+h[204];c[b+104>>2]=c[439];c[b+108>>2]=c[359];h[b+112>>3]=+h[191];h[b+120>>3]=.3333333333333333;h[b+128>>3]=1.1;c[b+136>>2]=100;h[b+144>>3]=1.5;j=b+316|0;c[b+332>>2]=0;c[b+336>>2]=0;c[b+340>>2]=0;c[b+348>>2]=0;c[b+352>>2]=0;c[b+356>>2]=0;c[b+364>>2]=0;c[b+368>>2]=0;c[b+372>>2]=0;c[b+380>>2]=0;c[b+384>>2]=0;c[b+388>>2]=0;c[b+396>>2]=0;c[b+400>>2]=0;c[b+404>>2]=0;e=b+544|0;c[b+412>>2]=0;c[b+416>>2]=0;c[b+420>>2]=0;c[b+428>>2]=0;c[b+432>>2]=0;c[b+436>>2]=0;c[b+444>>2]=0;c[b+448>>2]=0;c[b+452>>2]=0;ke(b+152|0,0,176)|0;c[b+456>>2]=e;f=b+460|0;c[f+0>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=0;c[b+488>>2]=j;a[b+492>>0]=1;h[b+496>>3]=1.0;h[b+504>>3]=1.0;c[b+512>>2]=0;c[b+516>>2]=-1;j=b+520|0;f=b+536|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;a[f>>0]=1;f=b+540|0;c[f+0>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;gc(e,1048576);a[b+560>>0]=0;e=b+604|0;f=b+664|0;j=b+564|0;d=j+36|0;do{c[j>>2]=0;j=j+4|0}while((j|0)<(d|0));j=e+0|0;d=j+36|0;do{c[j>>2]=0;j=j+4|0}while((j|0)<(d|0));j=b+680|0;c[f+0>>2]=-1;c[f+4>>2]=-1;c[f+8>>2]=-1;c[f+12>>2]=-1;a[j>>0]=0;i=g;return}function Hb(a){a=a|0;var b=0;b=i;Ib(a);pd(a);i=b;return}function Ib(a){a=a|0;var b=0,d=0,e=0;b=i;c[a>>2]=1816;d=a+628|0;e=c[d>>2]|0;if(e){c[a+632>>2]=0;Td(e);c[d>>2]=0;c[a+636>>2]=0}d=a+616|0;e=c[d>>2]|0;if(e){c[a+620>>2]=0;Td(e);c[d>>2]=0;c[a+624>>2]=0}d=a+604|0;e=c[d>>2]|0;if(e){c[a+608>>2]=0;Td(e);c[d>>2]=0;c[a+612>>2]=0}d=a+588|0;e=c[d>>2]|0;if(e){c[a+592>>2]=0;Td(e);c[d>>2]=0;c[a+596>>2]=0}d=a+576|0;e=c[d>>2]|0;if(e){c[a+580>>2]=0;Td(e);c[d>>2]=0;c[a+584>>2]=0}d=a+564|0;e=c[d>>2]|0;if(e){c[a+568>>2]=0;Td(e);c[d>>2]=0;c[a+572>>2]=0}d=c[a+544>>2]|0;if(d)Td(d);d=a+472|0;e=c[d>>2]|0;if(e){c[a+476>>2]=0;Td(e);c[d>>2]=0;c[a+480>>2]=0}d=a+460|0;e=c[d>>2]|0;if(e){c[a+464>>2]=0;Td(e);c[d>>2]=0;c[a+468>>2]=0}hc(a+412|0);d=a+396|0;e=c[d>>2]|0;if(e){c[a+400>>2]=0;Td(e);c[d>>2]=0;c[a+404>>2]=0}d=a+380|0;e=c[d>>2]|0;if(e){c[a+384>>2]=0;Td(e);c[d>>2]=0;c[a+388>>2]=0}e=a+364|0;d=c[e>>2]|0;if(d){c[a+368>>2]=0;Td(d);c[e>>2]=0;c[a+372>>2]=0}d=a+348|0;e=c[d>>2]|0;if(e){c[a+352>>2]=0;Td(e);c[d>>2]=0;c[a+356>>2]=0}d=a+332|0;e=c[d>>2]|0;if(e){c[a+336>>2]=0;Td(e);c[d>>2]=0;c[a+340>>2]=0}d=a+316|0;e=c[d>>2]|0;if(e){c[a+320>>2]=0;Td(e);c[d>>2]=0;c[a+324>>2]=0}d=a+304|0;e=c[d>>2]|0;if(e){c[a+308>>2]=0;Td(e);c[d>>2]=0;c[a+312>>2]=0}d=a+292|0;e=c[d>>2]|0;if(e){c[a+296>>2]=0;Td(e);c[d>>2]=0;c[a+300>>2]=0}d=a+280|0;e=c[d>>2]|0;if(e){c[a+284>>2]=0;Td(e);c[d>>2]=0;c[a+288>>2]=0}d=a+268|0;e=c[d>>2]|0;if(e){c[a+272>>2]=0;Td(e);c[d>>2]=0;c[a+276>>2]=0}d=a+256|0;e=c[d>>2]|0;if(e){c[a+260>>2]=0;Td(e);c[d>>2]=0;c[a+264>>2]=0}d=a+32|0;e=c[d>>2]|0;if(e){c[a+36>>2]=0;Td(e);c[d>>2]=0;c[a+40>>2]=0}d=a+16|0;e=c[d>>2]|0;if(e){c[a+20>>2]=0;Td(e);c[d>>2]=0;c[a+24>>2]=0}e=a+4|0;d=c[e>>2]|0;if(!d){i=b;return}c[a+8>>2]=0;Td(d);c[e>>2]=0;c[a+12>>2]=0;i=b;return}function Jb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0,q=0,r=0;f=i;i=i+16|0;k=f+4|0;j=f;g=b+580|0;m=c[g>>2]|0;if((m|0)>0){o=m+ -1|0;p=c[(c[b+576>>2]|0)+(o<<2)>>2]|0;c[g>>2]=o;g=p}else{p=b+540|0;g=c[p>>2]|0;c[p>>2]=g+1}m=b+412|0;p=g<<1;c[k>>2]=p;ic(m,k);c[j>>2]=p|1;ic(m,j);k=b+332|0;m=a[544]|0;j=g+1|0;jc(k,j);a[(c[k>>2]|0)+g>>0]=m;k=b+396|0;m=b+400|0;if((c[m>>2]|0)<(j|0)){o=b+404|0;p=c[o>>2]|0;if((p|0)<(j|0)){q=g+2-p&-2;n=(p>>1)+2&-2;n=(q|0)>(n|0)?q:n;if((n|0)>(2147483647-p|0)){q=va(1)|0;Ta(q|0,48,0)}r=c[k>>2]|0;q=n+p|0;c[o>>2]=q;q=Ud(r,q<<3)|0;c[k>>2]=q;if((q|0)==0?(c[(Oa()|0)>>2]|0)==12:0){r=va(1)|0;Ta(r|0,48,0)}}o=c[m>>2]|0;if((o|0)<(j|0))do{n=(c[k>>2]|0)+(o<<3)|0;if(n){r=n;c[r>>2]=0;c[r+4>>2]=0}o=o+1|0}while((o|0)!=(j|0));c[m>>2]=j}m=(c[k>>2]|0)+(g<<3)|0;c[m>>2]=-1;c[m+4>>2]=0;m=b+316|0;if(!(a[b+93>>0]|0))l=0.0;else{r=b+72|0;l=+h[r>>3]*1389796.0;l=l- +(~~(l/2147483647.0)|0)*2147483647.0;h[r>>3]=l;l=l/2147483647.0*1.0e-5}k=b+320|0;if((c[k>>2]|0)<(j|0)){n=b+324|0;o=c[n>>2]|0;if((o|0)<(j|0)){r=g+2-o&-2;p=(o>>1)+2&-2;p=(r|0)>(p|0)?r:p;if((p|0)>(2147483647-o|0)){r=va(1)|0;Ta(r|0,48,0)}q=c[m>>2]|0;r=p+o|0;c[n>>2]=r;r=Ud(q,r<<3)|0;c[m>>2]=r;if((r|0)==0?(c[(Oa()|0)>>2]|0)==12:0){r=va(1)|0;Ta(r|0,48,0)}}p=c[k>>2]|0;if((p|0)<(j|0)){n=c[m>>2]|0;do{o=n+(p<<3)|0;if(o)h[o>>3]=0.0;p=p+1|0}while((p|0)!=(j|0))}c[k>>2]=j}h[(c[m>>2]|0)+(g<<3)>>3]=l;kc(b+588|0,g,0);kc(b+348|0,g,1);k=b+364|0;d=a[d>>0]|0;jc(k,j);a[(c[k>>2]|0)+g>>0]=d;k=b+380|0;d=b+384|0;if((c[d>>2]|0)<(j|0)){m=b+388|0;o=c[m>>2]|0;if((o|0)<(j|0)){r=g+2-o&-2;n=(o>>1)+2&-2;n=(r|0)>(n|0)?r:n;if((n|0)>(2147483647-o|0)){r=va(1)|0;Ta(r|0,48,0)}q=c[k>>2]|0;r=n+o|0;c[m>>2]=r;r=Ud(q,r)|0;c[k>>2]=r;if((r|0)==0?(c[(Oa()|0)>>2]|0)==12:0){r=va(1)|0;Ta(r|0,48,0)}}m=c[d>>2]|0;if((m|0)<(j|0))do{n=(c[k>>2]|0)+m|0;if(n)a[n>>0]=0;m=m+1|0}while((m|0)!=(j|0));c[d>>2]=j}d=b+288|0;k=c[d>>2]|0;if((k|0)<(j|0)){r=g+2-k&-2;j=(k>>1)+2&-2;j=(r|0)>(j|0)?r:j;if((j|0)>(2147483647-k|0)){r=va(1)|0;Ta(r|0,48,0)}q=b+280|0;p=c[q>>2]|0;r=j+k|0;c[d>>2]=r;r=Ud(p,r<<2)|0;c[q>>2]=r;if((r|0)==0?(c[(Oa()|0)>>2]|0)==12:0){r=va(1)|0;Ta(r|0,48,0)}}j=b+380|0;d=(c[j>>2]|0)+g|0;k=(a[d>>0]|0)==0;if(e){if(k){r=b+200|0;q=r;q=ne(c[q>>2]|0,c[q+4>>2]|0,1,0)|0;c[r>>2]=q;c[r+4>>2]=F}}else if(!k){r=b+200|0;q=r;q=ne(c[q>>2]|0,c[q+4>>2]|0,-1,-1)|0;c[r>>2]=q;c[r+4>>2]=F}a[d>>0]=e&1;e=b+460|0;if((c[b+476>>2]|0)>(g|0)?(c[(c[b+472>>2]|0)+(g<<2)>>2]|0)>-1:0){i=f;return g|0}if(!(a[(c[j>>2]|0)+g>>0]|0)){i=f;return g|0}lc(e,g);i=f;return g|0}function Kb(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;f=i;i=i+16|0;k=f+1|0;j=f;g=b+492|0;if(!(a[g>>0]|0)){s=0;i=f;return s|0}s=c[e>>2]|0;h=e+4|0;l=c[h>>2]|0;a[k+0>>0]=a[j+0>>0]|0;oc(s,l,k);l=c[h>>2]|0;a:do if((l|0)>0){k=b+332|0;j=a[528]|0;m=0;n=0;p=-2;while(1){s=c[e>>2]|0;o=c[s+(m<<2)>>2]|0;r=d[(c[k>>2]|0)+(o>>1)>>0]|0;t=r^o&1;q=t&255;u=j&255;if((o|0)==(p^1|0)?1:(q<<24>>24==j<<24>>24&(u>>>1^1)|u&2&t|0)!=0){b=1;break}t=a[536]|0;u=t&255;if((o|0)!=(p|0)?((u>>>1^1)&q<<24>>24==t<<24>>24|r&2&u|0)==0:0){c[s+(n<<2)>>2]=o;l=c[h>>2]|0;n=n+1|0}else o=p;m=m+1|0;if((m|0)<(l|0))p=o;else break a}i=f;return b|0}else{m=0;n=0}while(0);j=m-n|0;if((j|0)>0){l=l-j|0;c[h>>2]=l}if(!l){a[g>>0]=0;u=0;i=f;return u|0}else if((l|0)==1){t=c[c[e>>2]>>2]|0;s=t>>1;a[(c[b+332>>2]|0)+s>>0]=(t&1^1)&255^1;u=c[b+296>>2]|0;s=(c[b+396>>2]|0)+(s<<3)|0;c[s>>2]=-1;c[s+4>>2]=u;s=b+284|0;u=c[s>>2]|0;c[s>>2]=u+1;c[(c[b+280>>2]|0)+(u<<2)>>2]=t;u=(Mb(b)|0)==-1;a[g>>0]=u&1;i=f;return u|0}else{e=pc(b+544|0,e,0)|0;h=b+256|0;g=b+260|0;k=c[g>>2]|0;j=b+264|0;if((k|0)==(c[j>>2]|0)){l=(k>>1)+2&-2;l=(l|0)<2?2:l;if((l|0)>(2147483647-k|0)){u=va(1)|0;Ta(u|0,48,0)}t=c[h>>2]|0;u=l+k|0;c[j>>2]=u;u=Ud(t,u<<2)|0;c[h>>2]=u;if((u|0)==0?(c[(Oa()|0)>>2]|0)==12:0){u=va(1)|0;Ta(u|0,48,0)}k=c[g>>2]|0}c[g>>2]=k+1;g=(c[h>>2]|0)+(k<<2)|0;if(g)c[g>>2]=e;Nb(b,e);u=1;i=f;return u|0}return 0}function Lb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0;f=c[d>>2]|0;d=f>>1;a[(c[b+332>>2]|0)+d>>0]=(f&1^1)&255^1;g=c[b+296>>2]|0;d=(c[b+396>>2]|0)+(d<<3)|0;c[d>>2]=e;c[d+4>>2]=g;e=b+284|0;d=c[e>>2]|0;c[e>>2]=d+1;c[(c[b+280>>2]|0)+(d<<2)>>2]=f;return}function Mb(b){b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0;k=i;i=i+16|0;r=k;h=b+512|0;t=c[h>>2]|0;q=b+284|0;if((t|0)>=(c[q>>2]|0)){M=0;K=0;O=-1;N=b+184|0;I=N;L=I;L=c[L>>2]|0;I=I+4|0;I=c[I>>2]|0;I=ne(L|0,I|0,M|0,K|0)|0;L=F;J=N;c[J>>2]=I;N=N+4|0;c[N>>2]=L;N=b+520|0;L=N;J=L;J=c[J>>2]|0;L=L+4|0;L=c[L>>2]|0;K=je(J|0,L|0,M|0,K|0)|0;M=F;L=N;c[L>>2]=K;N=N+4|0;c[N>>2]=M;i=k;return O|0}o=b+280|0;j=b+428|0;g=b+412|0;l=b+332|0;m=b+544|0;n=r+4|0;e=b+396|0;p=b+296|0;f=b+456|0;z=-1;s=0;do{c[h>>2]=t+1;w=c[(c[o>>2]|0)+(t<<2)>>2]|0;if(a[(c[j>>2]|0)+w>>0]|0){u=c[g>>2]|0;t=u+(w*12|0)+4|0;y=c[t>>2]|0;if((y|0)>0){u=u+(w*12|0)|0;v=0;x=0;do{B=c[u>>2]|0;A=B+(v<<3)|0;if((c[(c[c[f>>2]>>2]|0)+(c[A>>2]<<2)>>2]&3|0)!=1){N=A;O=c[N+4>>2]|0;y=B+(x<<3)|0;c[y>>2]=c[N>>2];c[y+4>>2]=O;y=c[t>>2]|0;x=x+1|0}v=v+1|0}while((v|0)<(y|0))}else{v=0;x=0}u=v-x|0;if((u|0)>0)c[t>>2]=y-u;a[(c[j>>2]|0)+w>>0]=0}t=c[g>>2]|0;s=s+1|0;u=c[t+(w*12|0)>>2]|0;t=t+(w*12|0)+4|0;x=c[t>>2]|0;v=u+(x<<3)|0;a:do if(!x){v=u;y=u}else{w=w^1;x=(x<<3)+ -1|0;B=u;y=u;while(1){while(1){b:while(1){H=c[B+4>>2]|0;O=d[(c[l>>2]|0)+(H>>1)>>0]^H&1;J=a[528]|0;I=J&255;K=I&2;I=I>>>1^1;if((O&255)<<24>>24==J<<24>>24&I|K&O){E=19;break}A=c[B>>2]|0;E=c[m>>2]|0;G=E+(A<<2)|0;C=E+(A+1<<2)|0;D=c[C>>2]|0;if((D|0)==(w|0)){O=E+(A+2<<2)|0;D=c[O>>2]|0;c[C>>2]=D;c[O>>2]=w}C=B+8|0;c[r>>2]=A;c[n>>2]=D;if((D|0)!=(H|0)?(O=d[(c[l>>2]|0)+(D>>1)>>0]^D&1,((O&255)<<24>>24==J<<24>>24&I|K&O|0)!=0):0){E=27;break}K=c[G>>2]|0;if(K>>>0<=95){E=31;break}I=c[l>>2]|0;J=a[536]|0;H=J&255;O=H&2;H=H>>>1^1;N=2;while(1){L=G+(N<<2)+4|0;M=c[L>>2]|0;P=d[I+(M>>1)>>0]^M&1;N=N+1|0;if(!((P&255)<<24>>24==J<<24>>24&H|O&P))break;if((N|0)>=(K>>>5|0)){E=32;break b}}P=E+(A+2<<2)|0;c[P>>2]=M;c[L>>2]=w;qc((c[g>>2]|0)+((c[P>>2]^1)*12|0)|0,r);if((C|0)==(v|0))break a;else B=C}if((E|0)==19){E=0;N=B;O=c[N+4>>2]|0;P=y;c[P>>2]=c[N>>2];c[P+4>>2]=O;B=B+8|0;y=y+8|0}else if((E|0)==27){E=0;O=r;P=c[O+4>>2]|0;B=y;c[B>>2]=c[O>>2];c[B+4>>2]=P;B=C;y=y+8|0}else if((E|0)==31){J=a[536]|0;E=32}if((E|0)==32){E=y+8|0;G=r;I=c[G+4>>2]|0;H=y;c[H>>2]=c[G>>2];c[H+4>>2]=I;H=D>>1;I=D&1;G=(c[l>>2]|0)+H|0;P=d[G>>0]^I;O=J&255;if((P&255)<<24>>24==J<<24>>24&(O>>>1^1)|O&2&P)break;a[G>>0]=(I^1)&255^1;y=c[p>>2]|0;B=(c[e>>2]|0)+(H<<3)|0;c[B>>2]=A;c[B+4>>2]=y;B=c[q>>2]|0;c[q>>2]=B+1;c[(c[o>>2]|0)+(B<<2)>>2]=D;B=C;y=E}if((B|0)==(v|0))break a}c[h>>2]=c[q>>2];if(C>>>0<v>>>0){z=(u+(x-C)|0)>>>3;while(1){N=C;C=C+8|0;O=c[N+4>>2]|0;P=E;c[P>>2]=c[N>>2];c[P+4>>2]=O;if(C>>>0>=v>>>0)break;else E=E+8|0}B=B+(z+2<<3)|0;y=y+(z+2<<3)|0}else{B=C;y=E}if((B|0)==(v|0)){z=A;break}else z=A}}while(0);u=v-y|0;if((u|0)>0)c[t>>2]=(c[t>>2]|0)-(u>>3);t=c[h>>2]|0}while((t|0)<(c[q>>2]|0));N=s;L=((s|0)<0)<<31>>31;P=z;O=b+184|0;J=O;M=J;M=c[M>>2]|0;J=J+4|0;J=c[J>>2]|0;J=ne(M|0,J|0,N|0,L|0)|0;M=F;K=O;c[K>>2]=J;O=O+4|0;c[O>>2]=M;O=b+520|0;M=O;K=M;K=c[K>>2]|0;M=M+4|0;M=c[M>>2]|0;L=je(K|0,M|0,N|0,L|0)|0;N=F;M=O;c[M>>2]=L;O=O+4|0;c[O>>2]=N;i=k;return P|0}function Nb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;d=i;i=i+16|0;k=d+8|0;f=d;g=c[a+544>>2]|0;e=g+(b<<2)|0;h=g+(b+1<<2)|0;j=a+412|0;l=(c[j>>2]|0)+((c[h>>2]^1)*12|0)|0;g=g+(b+2<<2)|0;m=c[g>>2]|0;c[k>>2]=b;c[k+4>>2]=m;qc(l,k);g=(c[j>>2]|0)+((c[g>>2]^1)*12|0)|0;h=c[h>>2]|0;c[f>>2]=b;c[f+4>>2]=h;qc(g,f);if(!(c[e>>2]&4)){m=a+208|0;l=m;l=ne(c[l>>2]|0,c[l+4>>2]|0,1,0)|0;c[m>>2]=l;c[m+4>>2]=F;m=a+224|0;l=m;l=ne((c[e>>2]|0)>>>5|0,0,c[l>>2]|0,c[l+4>>2]|0)|0;c[m>>2]=l;c[m+4>>2]=F;i=d;return}else{m=a+216|0;l=m;l=ne(c[l>>2]|0,c[l+4>>2]|0,1,0)|0;c[m>>2]=l;c[m+4>>2]=F;m=a+232|0;l=m;l=ne((c[e>>2]|0)>>>5|0,0,c[l>>2]|0,c[l+4>>2]|0)|0;c[m>>2]=l;c[m+4>>2]=F;i=d;return}}function Ob(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;g=i;i=i+16|0;l=g+4|0;j=g;h=c[b+544>>2]|0;f=h+(d<<2)|0;k=c[h+(d+1<<2)>>2]^1;if(!e){c[l>>2]=k;e=b+428|0;m=c[e>>2]|0;k=m+k|0;if(!(a[k>>0]|0)){a[k>>0]=1;mc(b+444|0,l);m=c[e>>2]|0}d=c[h+(d+2<<2)>>2]^1;c[j>>2]=d;d=m+d|0;if(!(a[d>>0]|0)){a[d>>0]=1;mc(b+444|0,j)}}else{j=b+412|0;e=c[j>>2]|0;l=e+(k*12|0)|0;h=h+(d+2<<2)|0;k=e+(k*12|0)+4|0;m=c[k>>2]|0;a:do if((m|0)>0){p=c[l>>2]|0;o=0;while(1){n=o+1|0;if((c[p+(o<<3)>>2]|0)==(d|0)){n=o;break a}if((n|0)<(m|0))o=n;else break}}else n=0;while(0);m=m+ -1|0;if((n|0)<(m|0)){do{e=c[l>>2]|0;m=n;n=n+1|0;o=e+(n<<3)|0;p=c[o+4>>2]|0;m=e+(m<<3)|0;c[m>>2]=c[o>>2];c[m+4>>2]=p;m=(c[k>>2]|0)+ -1|0}while((n|0)<(m|0));e=c[j>>2]|0}c[k>>2]=m;j=c[h>>2]^1;h=e+(j*12|0)|0;j=e+(j*12|0)+4|0;k=c[j>>2]|0;b:do if((k|0)>0){e=c[h>>2]|0;m=0;while(1){l=m+1|0;if((c[e+(m<<3)>>2]|0)==(d|0)){l=m;break b}if((l|0)<(k|0))m=l;else break}}else l=0;while(0);d=k+ -1|0;if((l|0)<(d|0))do{n=c[h>>2]|0;d=l;l=l+1|0;o=n+(l<<3)|0;p=c[o+4>>2]|0;d=n+(d<<3)|0;c[d>>2]=c[o>>2];c[d+4>>2]=p;d=(c[j>>2]|0)+ -1|0}while((l|0)<(d|0));c[j>>2]=d}if(!(c[f>>2]&4)){p=b+208|0;o=p;o=ne(c[o>>2]|0,c[o+4>>2]|0,-1,-1)|0;c[p>>2]=o;c[p+4>>2]=F;p=b+224|0;o=p;o=je(c[o>>2]|0,c[o+4>>2]|0,(c[f>>2]|0)>>>5|0,0)|0;c[p>>2]=o;c[p+4>>2]=F;i=g;return}else{p=b+216|0;o=p;o=ne(c[o>>2]|0,c[o+4>>2]|0,-1,-1)|0;c[p>>2]=o;c[p+4>>2]=F;p=b+232|0;o=p;o=je(c[o>>2]|0,c[o+4>>2]|0,(c[f>>2]|0)>>>5|0,0)|0;c[p>>2]=o;c[p+4>>2]=F;i=g;return}}function Pb(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;h=i;g=b+544|0;m=c[g>>2]|0;f=m+(e<<2)|0;Ob(b,e,0);m=c[m+(e+1<<2)>>2]|0;j=m>>1;m=(d[(c[b+332>>2]|0)+j>>0]|0)^m&1;o=a[528]|0;n=o&255;if((((m&255)<<24>>24==o<<24>>24&(n>>>1^1)|n&2&m|0)!=0?(k=(c[b+396>>2]|0)+(j<<3)|0,l=c[k>>2]|0,(l|0)!=-1):0)?((c[g>>2]|0)+(l<<2)|0)==(f|0):0)c[k>>2]=-1;c[f>>2]=c[f>>2]&-4|1;n=c[(c[g>>2]|0)+(e<<2)>>2]|0;o=b+556|0;c[o>>2]=((((n>>>3&1)+(n>>>5)<<2)+4|0)>>>2)+(c[o>>2]|0);i=h;return}function Qb(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;g=c[e>>2]|0;if(g>>>0<=31){l=0;i=f;return l|0}h=c[b+332>>2]|0;j=a[528]|0;k=j&255;l=k&2;k=k>>>1^1;b=0;while(1){m=c[e+(b<<2)+4>>2]|0;m=(d[h+(m>>1)>>0]|0)^m&1;b=b+1|0;if((m&255)<<24>>24==j<<24>>24&k|l&m){g=1;e=5;break}if((b|0)>=(g>>>5|0)){g=0;e=5;break}}if((e|0)==5){i=f;return g|0}return 0}function Rb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;g=i;e=b+296|0;if((c[e>>2]|0)<=(d|0)){i=g;return}f=b+284|0;s=c[f>>2]|0;j=b+292|0;t=c[j>>2]|0;u=c[t+(d<<2)>>2]|0;if((s|0)>(u|0)){r=b+280|0;m=b+332|0;l=b+88|0;k=b+348|0;n=b+460|0;p=b+476|0;q=b+472|0;o=b+380|0;do{s=s+ -1|0;u=c[(c[r>>2]|0)+(s<<2)>>2]>>1;a[(c[m>>2]|0)+u>>0]=a[544]|0;t=c[l>>2]|0;if((t|0)<=1){if((t|0)==1?(s|0)>(c[(c[j>>2]|0)+((c[e>>2]|0)+ -1<<2)>>2]|0):0)h=7}else h=7;if((h|0)==7){h=0;a[(c[k>>2]|0)+u>>0]=c[(c[r>>2]|0)+(s<<2)>>2]&1}if(!((c[p>>2]|0)>(u|0)?(c[(c[q>>2]|0)+(u<<2)>>2]|0)>-1:0))h=11;if((h|0)==11?(h=0,(a[(c[o>>2]|0)+u>>0]|0)!=0):0)lc(n,u);t=c[j>>2]|0;u=c[t+(d<<2)>>2]|0}while((s|0)>(u|0));s=c[f>>2]|0}c[b+512>>2]=u;b=c[t+(d<<2)>>2]|0;if((s-b|0)>0)c[f>>2]=b;if(((c[e>>2]|0)-d|0)<=0){i=g;return}c[e>>2]=d;i=g;return}function Sb(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0;d=i;f=b+72|0;q=+h[f>>3]*1389796.0;q=q- +(~~(q/2147483647.0)|0)*2147483647.0;h[f>>3]=q;l=b+464|0;if(q/2147483647.0<+h[b+64>>3]?(m=c[l>>2]|0,(m|0)!=0):0){q=q*1389796.0;q=q- +(~~(q/2147483647.0)|0)*2147483647.0;h[f>>3]=q;m=c[(c[b+460>>2]|0)+(~~(+(m|0)*(q/2147483647.0))<<2)>>2]|0;o=a[(c[b+332>>2]|0)+m>>0]|0;n=a[544]|0;p=n&255;if(((p>>>1^1)&o<<24>>24==n<<24>>24|o&2&p|0)!=0?(a[(c[b+380>>2]|0)+m>>0]|0)!=0:0){p=b+176|0;o=p;o=ne(c[o>>2]|0,c[o+4>>2]|0,1,0)|0;c[p>>2]=o;c[p+4>>2]=F}}else m=-1;n=b+460|0;p=b+332|0;o=b+380|0;while(1){if(((m|0)!=-1?(r=a[(c[p>>2]|0)+m>>0]|0,j=a[544]|0,e=j&255,g=e>>>1^1,(g&r<<24>>24==j<<24>>24|r&2&e|0)!=0):0)?(a[(c[o>>2]|0)+m>>0]|0)!=0:0)break;if(!(c[l>>2]|0)){e=-2;k=17;break}m=rc(n)|0}if((k|0)==17){i=d;return e|0}l=a[(c[b+364>>2]|0)+m>>0]|0;k=l&255;if(!(g&l<<24>>24==j<<24>>24|e&2&k)){p=a[528]|0;r=p&255;r=((r>>>1^1)&l<<24>>24==p<<24>>24|k&2&r|0)!=0|m<<1;i=d;return r|0}if(!(a[b+92>>0]|0)){r=(a[(c[b+348>>2]|0)+m>>0]|0)!=0|m<<1;i=d;return r|0}else{q=+h[f>>3]*1389796.0;q=q- +(~~(q/2147483647.0)|0)*2147483647.0;h[f>>3]=q;r=q/2147483647.0<.5|m<<1;i=d;return r|0}return 0}function Tb(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0.0,U=0;j=i;i=i+16|0;p=j+8|0;t=j+4|0;n=j;m=e+4|0;k=c[m>>2]|0;l=e+8|0;if((k|0)==(c[l>>2]|0)){q=(k>>1)+2&-2;q=(q|0)<2?2:q;if((q|0)>(2147483647-k|0)){S=va(1)|0;Ta(S|0,48,0)}R=c[e>>2]|0;S=q+k|0;c[l>>2]=S;S=Ud(R,S<<2)|0;c[e>>2]=S;if((S|0)==0?(c[(Oa()|0)>>2]|0)==12:0){S=va(1)|0;Ta(S|0,48,0)}k=c[m>>2]|0}l=(c[e>>2]|0)+(k<<2)|0;if(l){c[l>>2]=0;k=c[m>>2]|0}c[m>>2]=k+1;q=b+544|0;H=b+280|0;k=b+588|0;l=b+396|0;C=b+504|0;E=b+316|0;D=b+540|0;B=b+476|0;A=b+472|0;z=b+460|0;y=b+488|0;x=b+296|0;v=b+496|0;w=b+272|0;G=b+268|0;J=-2;I=(c[b+284>>2]|0)+ -1|0;K=0;do{L=c[q>>2]|0;d=L+(d<<2)|0;M=c[d>>2]|0;if((M&4|0)!=0?(r=+h[v>>3],S=d+(M>>>5<<2)+4|0,T=r+ +g[S>>2],g[S>>2]=T,T>1.0e20):0){O=c[w>>2]|0;if((O|0)>0){N=c[G>>2]|0;M=0;do{S=L+(c[N+(M<<2)>>2]<<2)|0;S=S+((c[S>>2]|0)>>>5<<2)+4|0;g[S>>2]=+g[S>>2]*1.0e-20;M=M+1|0}while((M|0)!=(O|0))}h[v>>3]=r*1.0e-20}J=(J|0)!=-2&1;if(J>>>0<(c[d>>2]|0)>>>5>>>0)do{M=c[d+(J<<2)+4>>2]|0;c[t>>2]=M;M=M>>1;L=(c[k>>2]|0)+M|0;do if((a[L>>0]|0)==0?(c[(c[l>>2]|0)+(M<<3)+4>>2]|0)>0:0){O=c[E>>2]|0;S=O+(M<<3)|0;T=+h[C>>3]+ +h[S>>3];h[S>>3]=T;if(T>1.0e+100){P=c[D>>2]|0;if((P|0)>0){N=0;do{S=O+(N<<3)|0;h[S>>3]=+h[S>>3]*1.0e-100;N=N+1|0}while((N|0)!=(P|0))}h[C>>3]=+h[C>>3]*1.0e-100}if((c[B>>2]|0)>(M|0)?(u=c[A>>2]|0,s=c[u+(M<<2)>>2]|0,(s|0)>-1):0){N=c[z>>2]|0;O=c[N+(s<<2)>>2]|0;a:do if(!s)R=0;else{S=s;while(1){R=S;S=S+ -1>>1;Q=N+(S<<2)|0;P=c[Q>>2]|0;U=c[c[y>>2]>>2]|0;if(!(+h[U+(O<<3)>>3]>+h[U+(P<<3)>>3]))break a;c[N+(R<<2)>>2]=P;c[u+(c[Q>>2]<<2)>>2]=R;if(!S){R=0;break}}}while(0);c[N+(R<<2)>>2]=O;c[u+(O<<2)>>2]=R}a[L>>0]=1;if((c[(c[l>>2]|0)+(M<<3)+4>>2]|0)<(c[x>>2]|0)){mc(e,t);break}else{K=K+1|0;break}}while(0);J=J+1|0}while((J|0)<((c[d>>2]|0)>>>5|0));d=c[H>>2]|0;L=c[k>>2]|0;do{J=I;I=I+ -1|0;J=c[d+(J<<2)>>2]|0;N=J>>1;M=L+N|0}while((a[M>>0]|0)==0);d=c[(c[l>>2]|0)+(N<<3)>>2]|0;a[M>>0]=0;K=K+ -1|0}while((K|0)>0);c[c[e>>2]>>2]=J^1;t=b+616|0;v=c[t>>2]|0;s=b+620|0;if(!v)w=c[s>>2]|0;else{c[s>>2]=0;w=0}u=c[m>>2]|0;if((w|0)<(u|0)){y=b+624|0;x=c[y>>2]|0;if((x|0)<(u|0)){U=u+1-x&-2;w=(x>>1)+2&-2;w=(U|0)>(w|0)?U:w;if((w|0)>(2147483647-x|0)){U=va(1)|0;Ta(U|0,48,0)}U=w+x|0;c[y>>2]=U;v=Ud(v,U<<2)|0;c[t>>2]=v;if((v|0)==0?(c[(Oa()|0)>>2]|0)==12:0){U=va(1)|0;Ta(U|0,48,0)}}w=c[s>>2]|0;b:do if((w|0)<(u|0))while(1){v=v+(w<<2)|0;if(v)c[v>>2]=0;w=w+1|0;if((w|0)==(u|0))break b;v=c[t>>2]|0}while(0);c[s>>2]=u;u=c[m>>2]|0}if((u|0)>0){w=c[t>>2]|0;v=c[e>>2]|0;x=0;do{c[w+(x<<2)>>2]=c[v+(x<<2)>>2];x=x+1|0;u=c[m>>2]|0}while((x|0)<(u|0))}v=c[b+84>>2]|0;if((v|0)==1)if((u|0)>1){n=c[e>>2]|0;o=1;v=1;while(1){u=c[n+(o<<2)>>2]|0;p=c[l>>2]|0;w=c[p+(u>>1<<3)>>2]|0;c:do if((w|0)!=-1){x=(c[q>>2]|0)+(w<<2)|0;y=c[x>>2]|0;if(y>>>0>63){w=c[k>>2]|0;z=1;while(1){U=c[x+(z<<2)+4>>2]>>1;if((a[w+U>>0]|0)==0?(c[p+(U<<3)+4>>2]|0)>0:0)break;z=z+1|0;if((z|0)>=(y>>>5|0))break c}c[n+(v<<2)>>2]=u;v=v+1|0}}else{c[n+(v<<2)>>2]=u;v=v+1|0}while(0);o=o+1|0;p=c[m>>2]|0;if((o|0)>=(p|0)){n=p;break}}}else{n=u;o=1;v=1}else if((v|0)==2)if((u|0)>1){q=1;v=1;do{w=c[e>>2]|0;u=c[w+(q<<2)>>2]|0;if((c[(c[l>>2]|0)+(u>>1<<3)>>2]|0)!=-1){c[n>>2]=u;c[p+0>>2]=c[n+0>>2];if(!(Ub(b,p)|0)){u=c[e>>2]|0;w=u;u=c[u+(q<<2)>>2]|0;o=62}}else o=62;if((o|0)==62){o=0;c[w+(v<<2)>>2]=u;v=v+1|0}q=q+1|0;u=c[m>>2]|0}while((q|0)<(u|0));n=u;o=q}else{n=u;o=1;v=1}else{n=u;o=u;v=u}U=b+240|0;S=U;S=ne(c[S>>2]|0,c[S+4>>2]|0,n|0,((n|0)<0)<<31>>31|0)|0;c[U>>2]=S;c[U+4>>2]=F;o=o-v|0;if((o|0)>0){n=n-o|0;c[m>>2]=n}U=b+248|0;S=U;S=ne(c[S>>2]|0,c[S+4>>2]|0,n|0,((n|0)<0)<<31>>31|0)|0;c[U>>2]=S;c[U+4>>2]=F;if((n|0)==1)e=0;else{e=c[e>>2]|0;if((n|0)>2){b=c[l>>2]|0;m=2;o=1;do{o=(c[b+(c[e+(m<<2)>>2]>>1<<3)+4>>2]|0)>(c[b+(c[e+(o<<2)>>2]>>1<<3)+4>>2]|0)?m:o;m=m+1|0}while((m|0)<(n|0))}else o=1;S=e+(o<<2)|0;U=c[S>>2]|0;e=e+4|0;c[S>>2]=c[e>>2];c[e>>2]=U;e=c[(c[l>>2]|0)+(U>>1<<3)+4>>2]|0}c[f>>2]=e;if((c[s>>2]|0)>0)f=0;else{i=j;return}do{a[(c[k>>2]|0)+(c[(c[t>>2]|0)+(f<<2)>>2]>>1)>>0]=0;f=f+1|0}while((f|0)<(c[s>>2]|0));i=j;return}function Ub(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;e=i;n=c[d>>2]|0;l=b+396|0;q=c[l>>2]|0;k=b+544|0;s=(c[k>>2]|0)+(c[q+(n>>1<<3)>>2]<<2)|0;h=b+604|0;f=b+608|0;if(c[h>>2]|0)c[f>>2]=0;g=b+588|0;j=b+612|0;b=b+616|0;o=1;while(1){if(o>>>0<(c[s>>2]|0)>>>5>>>0){r=c[s+(o<<2)+4>>2]|0;p=r>>1;if((c[q+(p<<3)+4>>2]|0)!=0?(m=a[(c[g>>2]|0)+p>>0]|0,(m+ -1<<24>>24&255)>=2):0){s=c[f>>2]|0;t=(s|0)==(c[j>>2]|0);if(m<<24>>24==3?1:(c[q+(p<<3)>>2]|0)==-1){k=8;break}if(t){q=(s>>1)+2&-2;q=(q|0)<2?2:q;if((q|0)>(2147483647-s|0)){k=24;break}u=c[h>>2]|0;t=q+s|0;c[j>>2]=t;t=Ud(u,t<<3)|0;c[h>>2]=t;if((t|0)==0?(c[(Oa()|0)>>2]|0)==12:0){k=24;break}s=c[f>>2]|0}c[f>>2]=s+1;q=(c[h>>2]|0)+(s<<3)|0;if(q){u=q;c[u>>2]=o;c[u+4>>2]=n}c[d>>2]=r;s=c[l>>2]|0;n=r;q=s;s=(c[k>>2]|0)+(c[s+(p<<3)>>2]<<2)|0;o=0}}else{n=(c[g>>2]|0)+(n>>1)|0;if(!(a[n>>0]|0)){a[n>>0]=2;mc(b,d)}n=c[f>>2]|0;if(!n){f=1;k=34;break}u=n+ -1|0;n=c[h>>2]|0;o=c[n+(u<<3)>>2]|0;n=c[n+(u<<3)+4>>2]|0;c[d>>2]=n;q=c[l>>2]|0;s=(c[k>>2]|0)+(c[q+(n>>1<<3)>>2]<<2)|0;c[f>>2]=u}o=o+1|0}if((k|0)==8){if(t){k=(s>>1)+2&-2;k=(k|0)<2?2:k;if((k|0)>(2147483647-s|0)){u=va(1)|0;Ta(u|0,48,0)}t=c[h>>2]|0;u=k+s|0;c[j>>2]=u;u=Ud(t,u<<3)|0;c[h>>2]=u;if((u|0)==0?(c[(Oa()|0)>>2]|0)==12:0){u=va(1)|0;Ta(u|0,48,0)}s=c[f>>2]|0}j=s+1|0;c[f>>2]=j;k=(c[h>>2]|0)+(s<<3)|0;if(k){j=k;c[j>>2]=0;c[j+4>>2]=n;j=c[f>>2]|0}if((j|0)>0)k=0;else{u=0;i=e;return u|0}do{l=(c[g>>2]|0)+(c[(c[h>>2]|0)+(k<<3)+4>>2]>>1)|0;if(!(a[l>>0]|0)){a[l>>0]=3;mc(b,(c[h>>2]|0)+(k<<3)+4|0);j=c[f>>2]|0}k=k+1|0}while((k|0)<(j|0));f=0;i=e;return f|0}else if((k|0)==24)Ta(va(1)|0,48,0);else if((k|0)==34){i=e;return f|0}return 0}function Vb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;j=i;i=i+32|0;h=j+16|0;g=j+12|0;k=j+8|0;f=j;n=e+20|0;l=e+16|0;if((c[n>>2]|0)>0){m=0;do{a[(c[e>>2]|0)+(c[(c[l>>2]|0)+(m<<2)>>2]|0)>>0]=0;m=m+1|0}while((m|0)<(c[n>>2]|0))}if(c[l>>2]|0)c[n>>2]=0;m=c[d>>2]|0;c[k>>2]=m;c[g>>2]=m;c[h+0>>2]=c[g+0>>2];sc(e,h,0);l=(c[e>>2]|0)+m|0;if(!(a[l>>0]|0)){a[l>>0]=1;mc(e+16|0,k)}if(!(c[b+296>>2]|0)){i=j;return}d=m>>1;o=b+588|0;a[(c[o>>2]|0)+d>>0]=1;p=c[b+284>>2]|0;n=b+292|0;s=c[c[n>>2]>>2]|0;if((p|0)>(s|0)){k=b+280|0;l=b+396|0;m=e+16|0;b=b+544|0;do{p=p+ -1|0;r=c[(c[k>>2]|0)+(p<<2)>>2]|0;q=r>>1;if(a[(c[o>>2]|0)+q>>0]|0){s=c[l>>2]|0;t=c[s+(q<<3)>>2]|0;a:do if((t|0)==-1){r=r^1;c[f>>2]=r;c[g>>2]=r;c[h+0>>2]=c[g+0>>2];sc(e,h,0);r=(c[e>>2]|0)+r|0;if(!(a[r>>0]|0)){a[r>>0]=1;mc(m,f)}}else{r=(c[b>>2]|0)+(t<<2)|0;t=c[r>>2]|0;if(t>>>0>63){u=1;while(1){v=c[r+(u<<2)+4>>2]>>1;if((c[s+(v<<3)+4>>2]|0)>0){a[(c[o>>2]|0)+v>>0]=1;t=c[r>>2]|0}u=u+1|0;if((u|0)>=(t>>>5|0))break a;s=c[l>>2]|0}}}while(0);a[(c[o>>2]|0)+q>>0]=0;s=c[c[n>>2]>>2]|0}}while((p|0)>(s|0))}a[(c[o>>2]|0)+d>>0]=0;i=j;return}function Wb(b){b=b|0;var e=0,f=0,j=0,k=0,l=0,m=0,n=0.0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;f=i;i=i+16|0;p=f+4|0;u=f;e=b+272|0;w=c[e>>2]|0;n=+h[b+496>>3]/+(w|0);k=b+544|0;l=b+268|0;v=c[l>>2]|0;c[u>>2]=k;c[p+0>>2]=c[u+0>>2];tc(v,w,p);p=c[e>>2]|0;if((p|0)>0){m=b+332|0;o=b+396|0;q=0;v=0;do{t=c[l>>2]|0;u=c[t+(q<<2)>>2]|0;w=c[k>>2]|0;r=w+(u<<2)|0;s=c[r>>2]|0;do if(s>>>0>95){x=c[w+(u+1<<2)>>2]|0;w=x>>1;x=(d[(c[m>>2]|0)+w>>0]|0)^x&1;z=a[528]|0;y=z&255;if(((x&255)<<24>>24==z<<24>>24&(y>>>1^1)|y&2&x|0)!=0?(z=c[(c[o>>2]|0)+(w<<3)>>2]|0,(z|0)!=-1&(z|0)==(u|0)):0){j=9;break}if((q|0)>=((p|0)/2|0|0)?!(+g[r+(s>>>5<<2)+4>>2]<n):0){j=9;break}Pb(b,u)}else j=9;while(0);if((j|0)==9){j=0;c[t+(v<<2)>>2]=u;v=v+1|0}q=q+1|0;p=c[e>>2]|0}while((q|0)<(p|0))}else{q=0;v=0}j=q-v|0;if((j|0)>0)c[e>>2]=p-j;if(!(+((c[b+556>>2]|0)>>>0)>+h[b+96>>3]*+((c[b+548>>2]|0)>>>0))){i=f;return}gb[c[(c[b>>2]|0)+8>>2]&31](b);i=f;return}function Xb(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;f=i;g=e+4|0;m=c[g>>2]|0;if((m|0)>0){j=b+544|0;h=b+332|0;k=0;l=0;do{u=c[e>>2]|0;p=c[u+(k<<2)>>2]|0;m=(c[j>>2]|0)+(p<<2)|0;o=c[m>>2]|0;do if(o>>>0>31){v=c[h>>2]|0;r=a[528]|0;q=r&255;w=q&2;q=q>>>1^1;s=o>>>5;t=0;do{x=c[m+(t<<2)+4>>2]|0;x=(d[v+(x>>1)>>0]|0)^x&1;t=t+1|0;if((x&255)<<24>>24==r<<24>>24&q|w&x){n=7;break}}while((t|0)<(s|0));if((n|0)==7){n=0;Pb(b,p);break}if(o>>>0>95){n=a[536]|0;q=o>>>5;p=2;do{r=m+(p<<2)+4|0;x=c[r>>2]|0;x=(d[(c[h>>2]|0)+(x>>1)>>0]|0)^x&1;w=n&255;if((x&255)<<24>>24==n<<24>>24&(w>>>1^1)|w&2&x){c[r>>2]=c[m+(q+ -1<<2)+4>>2];o=c[m>>2]|0;if(o&8){o=o>>>5;c[m+(o+ -1<<2)+4>>2]=c[m+(o<<2)+4>>2];o=c[m>>2]|0}o=o+ -32|0;c[m>>2]=o;p=p+ -1|0}p=p+1|0;q=o>>>5}while((p|0)<(q|0));p=c[e>>2]|0;u=p;p=c[p+(k<<2)>>2]|0;n=16}else n=16}else n=16;while(0);if((n|0)==16){n=0;c[u+(l<<2)>>2]=p;l=l+1|0}k=k+1|0;m=c[g>>2]|0}while((k|0)<(m|0))}else{k=0;l=0}e=k-l|0;if((e|0)<=0){i=f;return}c[g>>2]=m-e;i=f;return}function Yb(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;g=i;i=i+16|0;e=g+4|0;h=g;c[e>>2]=0;d=e+4|0;c[d>>2]=0;f=e+8|0;c[f>>2]=0;c[h>>2]=0;j=b+540|0;n=c[j>>2]|0;if((n|0)>0){l=b+380|0;k=b+332|0;m=0;do{if((a[(c[l>>2]|0)+m>>0]|0)!=0?(p=a[(c[k>>2]|0)+m>>0]|0,q=a[544]|0,o=q&255,((o>>>1^1)&p<<24>>24==q<<24>>24|p&2&o|0)!=0):0){nc(e,h);n=c[j>>2]|0}m=m+1|0;c[h>>2]=m}while((m|0)<(n|0))}uc(b+460|0,e);b=c[e>>2]|0;if(!b){i=g;return}c[d>>2]=0;Td(b);c[e>>2]=0;c[f>>2]=0;i=g;return}function Zb(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;d=i;f=b+492|0;if((a[f>>0]|0)!=0?(Mb(b)|0)==-1:0){f=b+284|0;g=b+516|0;if((c[f>>2]|0)==(c[g>>2]|0)){s=1;i=d;return s|0}j=b+520|0;s=j;r=c[s+4>>2]|0;if((r|0)>0|(r|0)==0&(c[s>>2]|0)>>>0>0){s=1;i=d;return s|0}Xb(b,b+268|0);if(a[b+536>>0]|0){Xb(b,b+256|0);l=b+564|0;k=b+568|0;if((c[k>>2]|0)>0){n=b+588|0;m=0;do{a[(c[n>>2]|0)+(c[(c[l>>2]|0)+(m<<2)>>2]|0)>>0]=1;m=m+1|0}while((m|0)<(c[k>>2]|0))}p=c[f>>2]|0;if((p|0)>0){m=c[b+280>>2]|0;n=c[b+588>>2]|0;q=0;o=0;do{r=c[m+(q<<2)>>2]|0;if(!(a[n+(r>>1)>>0]|0)){c[m+(o<<2)>>2]=r;p=c[f>>2]|0;o=o+1|0}q=q+1|0}while((q|0)<(p|0))}else{q=0;o=0}m=q-o|0;if((m|0)>0){p=p-m|0;c[f>>2]=p}c[b+512>>2]=p;a:do if((c[k>>2]|0)>0){o=b+588|0;m=0;do{a[(c[o>>2]|0)+(c[(c[l>>2]|0)+(m<<2)>>2]|0)>>0]=0;m=m+1|0;n=c[k>>2]|0}while((m|0)<(n|0));if((n|0)>0){n=b+580|0;o=b+584|0;m=b+576|0;p=0;while(1){r=c[n>>2]|0;if((r|0)==(c[o>>2]|0)){q=(r>>1)+2&-2;q=(q|0)<2?2:q;if((q|0)>(2147483647-r|0)){e=28;break}s=c[m>>2]|0;q=q+r|0;c[o>>2]=q;q=Ud(s,q<<2)|0;c[m>>2]=q;if((q|0)==0?(c[(Oa()|0)>>2]|0)==12:0){e=28;break}r=c[n>>2]|0}else q=c[m>>2]|0;s=q+(r<<2)|0;if(s){c[s>>2]=0;r=c[n>>2]|0}c[n>>2]=r+1;s=c[l>>2]|0;c[q+(r<<2)>>2]=c[s+(p<<2)>>2];p=p+1|0;if((p|0)>=(c[k>>2]|0))break a}if((e|0)==28)Ta(va(1)|0,48,0)}else e=21}else e=21;while(0);if((e|0)==21)s=c[l>>2]|0;if(s)c[k>>2]=0}if(+((c[b+556>>2]|0)>>>0)>+h[b+96>>3]*+((c[b+548>>2]|0)>>>0))gb[c[(c[b>>2]|0)+8>>2]&31](b);Yb(b);c[g>>2]=c[f>>2];r=b+224|0;s=b+232|0;r=ne(c[s>>2]|0,c[s+4>>2]|0,c[r>>2]|0,c[r+4>>2]|0)|0;s=j;c[s>>2]=r;c[s+4>>2]=F;s=1;i=d;return s|0}a[f>>0]=0;s=0;i=d;return s|0}function _b(b,e,f){b=b|0;e=e|0;f=f|0;var j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0.0,ga=0,ha=0,ia=0,ja=0.0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0.0,ra=0,sa=0,ta=0.0;n=i;i=i+64|0;_=n;G=n+60|0;B=n+56|0;j=n+44|0;$=n+40|0;c[j>>2]=0;m=j+4|0;c[m>>2]=0;l=j+8|0;c[l>>2]=0;N=e+160|0;M=N;M=ne(c[M>>2]|0,c[M+4>>2]|0,1,0)|0;c[N>>2]=M;c[N+4>>2]=F;N=(f|0)<0;M=e+680|0;L=e+664|0;K=e+672|0;q=e+296|0;w=e+272|0;o=e+284|0;I=e+640|0;E=e+308|0;D=e+304|0;r=e+332|0;H=e+292|0;ba=e+168|0;t=e+396|0;v=e+280|0;J=e+184|0;C=e+192|0;u=e+48|0;U=e+504|0;Y=e+56|0;aa=e+496|0;ca=e+656|0;O=e+144|0;P=e+648|0;Q=e+128|0;R=e+44|0;T=e+200|0;V=e+208|0;W=e+224|0;X=e+216|0;s=e+232|0;Z=e+540|0;p=e+292|0;x=e+544|0;z=e+276|0;y=e+268|0;A=e+268|0;da=0;a:while(1){ea=N|(da|0)<(f|0);while(1){ga=Mb(e)|0;if((ga|0)!=-1)break;if(!ea){ga=41;break a}if(a[M>>0]|0){ga=41;break a}ga=L;ha=c[ga+4>>2]|0;if((ha|0)>=0?(sa=C,ra=c[sa+4>>2]|0,!(ra>>>0<ha>>>0|((ra|0)==(ha|0)?(c[sa>>2]|0)>>>0<(c[ga>>2]|0)>>>0:0))):0){ga=41;break a}ga=K;ha=c[ga+4>>2]|0;if((ha|0)>=0?(sa=J,ra=c[sa+4>>2]|0,!(ra>>>0<ha>>>0|((ra|0)==(ha|0)?(c[sa>>2]|0)>>>0<(c[ga>>2]|0)>>>0:0))):0){ga=41;break a}if((c[q>>2]|0)==0?!(Zb(e)|0):0){ga=50;break a}if(+((c[w>>2]|0)-(c[o>>2]|0)|0)>=+h[I>>3])Wb(e);while(1){ga=c[q>>2]|0;if((ga|0)>=(c[E>>2]|0)){ga=59;break}ka=c[(c[D>>2]|0)+(ga<<2)>>2]|0;ha=d[(c[r>>2]|0)+(ka>>1)>>0]|0;sa=ha^ka&1;ia=sa&255;pa=a[528]|0;ra=pa&255;if(!(ia<<24>>24==pa<<24>>24&(ra>>>1^1)|ra&2&sa)){ga=56;break}c[G>>2]=c[o>>2];nc(H,G)}if((ga|0)==56){ga=0;ra=a[536]|0;sa=ra&255;if((sa>>>1^1)&ia<<24>>24==ra<<24>>24|ha&2&sa){ga=57;break a}if((ka|0)==-2)ga=59}if((ga|0)==59){sa=ba;sa=ne(c[sa>>2]|0,c[sa+4>>2]|0,1,0)|0;ka=ba;c[ka>>2]=sa;c[ka+4>>2]=F;ka=Sb(e)|0;if((ka|0)==-2){ga=60;break a}}c[_>>2]=c[o>>2];nc(H,_);sa=ka>>1;a[(c[r>>2]|0)+sa>>0]=(ka&1^1)&255^1;ra=c[q>>2]|0;sa=(c[t>>2]|0)+(sa<<3)|0;c[sa>>2]=-1;c[sa+4>>2]=ra;sa=c[o>>2]|0;c[o>>2]=sa+1;c[(c[v>>2]|0)+(sa<<2)>>2]=ka}ra=C;ra=ne(c[ra>>2]|0,c[ra+4>>2]|0,1,0)|0;sa=C;c[sa>>2]=ra;c[sa+4>>2]=F;da=da+1|0;if(!(c[q>>2]|0)){ga=5;break}if(c[j>>2]|0)c[m>>2]=0;Tb(e,ga,j,B);Rb(e,c[B>>2]|0);if((c[m>>2]|0)==1){ra=c[c[j>>2]>>2]|0;sa=ra>>1;a[(c[r>>2]|0)+sa>>0]=(ra&1^1)&255^1;pa=c[q>>2]|0;sa=(c[t>>2]|0)+(sa<<3)|0;c[sa>>2]=-1;c[sa+4>>2]=pa;sa=c[o>>2]|0;c[o>>2]=sa+1;c[(c[v>>2]|0)+(sa<<2)>>2]=ra}else{ea=pc(x,j,1)|0;ga=c[w>>2]|0;if((ga|0)==(c[z>>2]|0)){ha=(ga>>1)+2&-2;ha=(ha|0)<2?2:ha;if((ha|0)>(2147483647-ga|0)){ga=14;break}ra=c[y>>2]|0;sa=ha+ga|0;c[z>>2]=sa;sa=Ud(ra,sa<<2)|0;c[y>>2]=sa;if((sa|0)==0?(c[(Oa()|0)>>2]|0)==12:0){ga=14;break}ga=c[w>>2]|0}c[w>>2]=ga+1;ga=(c[y>>2]|0)+(ga<<2)|0;if(ga)c[ga>>2]=ea;Nb(e,ea);ia=c[x>>2]|0;sa=ia+(ea<<2)|0;fa=+h[aa>>3];sa=sa+((c[sa>>2]|0)>>>5<<2)+4|0;ta=fa+ +g[sa>>2];g[sa>>2]=ta;if(ta>1.0e20){ha=c[w>>2]|0;if((ha|0)>0){ga=c[A>>2]|0;ka=0;do{sa=ia+(c[ga+(ka<<2)>>2]<<2)|0;sa=sa+((c[sa>>2]|0)>>>5<<2)+4|0;g[sa>>2]=+g[sa>>2]*1.0e-20;ka=ka+1|0}while((ka|0)!=(ha|0))}h[aa>>3]=fa*1.0e-20}ra=c[c[j>>2]>>2]|0;sa=ra>>1;a[(c[r>>2]|0)+sa>>0]=(ra&1^1)&255^1;pa=c[q>>2]|0;sa=(c[t>>2]|0)+(sa<<3)|0;c[sa>>2]=ea;c[sa+4>>2]=pa;sa=c[o>>2]|0;c[o>>2]=sa+1;c[(c[v>>2]|0)+(sa<<2)>>2]=ra}h[U>>3]=1.0/+h[u>>3]*+h[U>>3];h[aa>>3]=1.0/+h[Y>>3]*+h[aa>>3];sa=(c[ca>>2]|0)+ -1|0;c[ca>>2]=sa;if(sa)continue;fa=+h[O>>3]*+h[P>>3];h[P>>3]=fa;c[ca>>2]=~~fa;fa=+h[Q>>3]*+h[I>>3];h[I>>3]=fa;if((c[R>>2]|0)<=0)continue;ga=c[C>>2]|0;ea=c[T>>2]|0;oa=c[q>>2]|0;if(!oa)ha=o;else ha=c[p>>2]|0;ha=c[ha>>2]|0;na=c[V>>2]|0;ma=c[W>>2]|0;la=c[X>>2]|0;ka=s;ia=c[ka>>2]|0;ka=c[ka+4>>2]|0;ja=+(c[Z>>2]|0);qa=1.0/ja;if((oa|0)<0)ta=0.0;else{pa=0;ta=0.0;while(1){if(!pa)ra=0;else ra=c[(c[p>>2]|0)+(pa+ -1<<2)>>2]|0;if((pa|0)==(oa|0))sa=o;else sa=(c[p>>2]|0)+(pa<<2)|0;ta=ta+ +S(+qa,+(+(pa|0)))*+((c[sa>>2]|0)-ra|0);if((pa|0)==(oa|0))break;else pa=pa+1|0}}c[_>>2]=ga;c[_+4>>2]=ea-ha;c[_+8>>2]=na;c[_+12>>2]=ma;c[_+16>>2]=~~fa;c[_+20>>2]=la;sa=_+24|0;h[k>>3]=(+(ia>>>0)+4294967296.0*+(ka>>>0))/+(la|0);c[sa>>2]=c[k>>2];c[sa+4>>2]=c[k+4>>2];sa=_+32|0;h[k>>3]=ta/ja*100.0;c[sa>>2]=c[k>>2];c[sa+4>>2]=c[k+4>>2];La(1832,_|0)|0}if((ga|0)==5)a[b>>0]=a[536]|0;else if((ga|0)==14)Ta(va(1)|0,48,0);else if((ga|0)==41){fa=+(c[Z>>2]|0);ja=1.0/fa;r=c[q>>2]|0;if((r|0)<0)qa=0.0;else{q=0;qa=0.0;while(1){if(!q)s=0;else s=c[(c[p>>2]|0)+(q+ -1<<2)>>2]|0;if((q|0)==(r|0))t=o;else t=(c[p>>2]|0)+(q<<2)|0;qa=qa+ +S(+ja,+(+(q|0)))*+((c[t>>2]|0)-s|0);if((q|0)==(r|0))break;else q=q+1|0}}h[e+528>>3]=qa/fa;Rb(e,0);a[b>>0]=a[544]|0}else if((ga|0)==50)a[b>>0]=a[536]|0;else if((ga|0)==57){c[$>>2]=ka^1;sa=e+16|0;c[_+0>>2]=c[$+0>>2];Vb(e,_,sa);a[b>>0]=a[536]|0}else if((ga|0)==60)a[b>>0]=a[528]|0;b=c[j>>2]|0;if(!b){i=n;return}c[m>>2]=0;Td(b);c[j>>2]=0;c[l>>2]=0;i=n;return}function $b(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0.0,w=0,x=0,y=0,z=0.0,A=0,B=0;f=i;i=i+16|0;j=f;e=d+4|0;if(c[e>>2]|0)c[d+8>>2]=0;g=d+36|0;k=d+32|0;if((c[g>>2]|0)>0){l=d+16|0;m=0;do{a[(c[l>>2]|0)+(c[(c[k>>2]|0)+(m<<2)>>2]|0)>>0]=0;m=m+1|0}while((m|0)<(c[g>>2]|0))}if(c[k>>2]|0)c[g>>2]=0;k=d+492|0;if(!(a[k>>0]|0)){a[b>>0]=a[536]|0;i=f;return}l=d+152|0;y=l;y=ne(c[y>>2]|0,c[y+4>>2]|0,1,0)|0;c[l>>2]=y;c[l+4>>2]=F;z=+h[d+120>>3]*+(c[d+208>>2]|0);l=d+640|0;h[l>>3]=z;v=+(c[d+104>>2]|0);if(z<v)h[l>>3]=v;w=c[d+136>>2]|0;h[d+648>>3]=+(w|0);c[d+656>>2]=w;w=a[544]|0;l=d+44|0;if((c[l>>2]|0)>0){Ka(2288)|0;Ka(2368)|0;Ka(2448)|0;Ka(2528)|0;o=a[544]|0}else o=w;n=d+192|0;m=d+184|0;y=o&255;a:do if((y>>>1^1)&w<<24>>24==o<<24>>24|w&2&y){q=d+80|0;t=d+112|0;p=d+108|0;o=d+680|0;r=d+664|0;s=d+672|0;u=0;while(1){v=+h[t>>3];if(!(a[q>>0]|0))v=+S(+v,+(+(u|0)));else{y=u+1|0;if((u|0)>0){x=0;w=1;do{x=x+1|0;w=w<<1|1}while((w|0)<(y|0));y=w+ -1|0}else{x=0;y=0}if((y|0)!=(u|0)){w=u;do{A=y>>1;x=x+ -1|0;w=(w|0)%(A|0)|0;y=A+ -1|0}while((y|0)!=(w|0))}v=+S(+v,+(+(x|0)))}_b(j,d,~~(v*+(c[p>>2]|0)));w=a[j>>0]|0;if(a[o>>0]|0)break a;y=r;x=c[y+4>>2]|0;if((x|0)>=0?(A=n,B=c[A+4>>2]|0,!(B>>>0<x>>>0|((B|0)==(x|0)?(c[A>>2]|0)>>>0<(c[y>>2]|0)>>>0:0))):0)break a;y=s;x=c[y+4>>2]|0;if((x|0)>=0?(B=m,A=c[B+4>>2]|0,!(A>>>0<x>>>0|((A|0)==(x|0)?(c[B>>2]|0)>>>0<(c[y>>2]|0)>>>0:0))):0)break a;A=a[544]|0;B=A&255;if(!((B>>>1^1)&w<<24>>24==A<<24>>24|w&2&B))break;else u=u+1|0}}while(0);if((c[l>>2]|0)>0)Ka(2528)|0;A=a[528]|0;B=A&255;j=w&2;if(!((B>>>1^1)&w<<24>>24==A<<24>>24|j&B)){A=a[536]|0;B=A&255;if(((B>>>1^1)&w<<24>>24==A<<24>>24|j&B|0)!=0?(c[g>>2]|0)==0:0)a[k>>0]=0}else{g=d+540|0;jc(e,c[g>>2]|0);if((c[g>>2]|0)>0){j=d+332|0;k=0;do{a[(c[e>>2]|0)+k>>0]=a[(c[j>>2]|0)+k>>0]|0;k=k+1|0}while((k|0)<(c[g>>2]|0))}}Rb(d,0);a[b>>0]=w;i=f;return}function ac(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;f=i;h=b+412|0;vc(h);k=b+540|0;if((c[k>>2]|0)>0){j=b+544|0;g=0;do{l=g<<1;n=c[h>>2]|0;m=n+(l*12|0)+4|0;if((c[m>>2]|0)>0){p=n+(l*12|0)|0;o=0;do{s=(c[p>>2]|0)+(o<<3)|0;n=c[s>>2]|0;q=c[j>>2]|0;r=q+(n<<2)|0;if(!(c[r>>2]&16)){t=wc(e,r)|0;c[s>>2]=t;c[r>>2]=c[r>>2]|16;c[q+(n+1<<2)>>2]=t}else c[s>>2]=c[q+(n+1<<2)>>2];o=o+1|0}while((o|0)<(c[m>>2]|0));m=c[h>>2]|0}else m=n;n=l|1;l=m+(n*12|0)+4|0;if((c[l>>2]|0)>0){r=m+(n*12|0)|0;q=0;do{m=(c[r>>2]|0)+(q<<3)|0;p=c[m>>2]|0;o=c[j>>2]|0;n=o+(p<<2)|0;if(!(c[n>>2]&16)){t=wc(e,n)|0;c[m>>2]=t;c[n>>2]=c[n>>2]|16;c[o+(p+1<<2)>>2]=t}else c[m>>2]=c[o+(p+1<<2)>>2];q=q+1|0}while((q|0)<(c[l>>2]|0))}g=g+1|0}while((g|0)<(c[k>>2]|0))}g=b+284|0;if((c[g>>2]|0)>0){l=b+280|0;k=b+396|0;j=b+544|0;h=b+332|0;m=0;do{r=c[k>>2]|0;p=r+(c[(c[l>>2]|0)+(m<<2)>>2]>>1<<3)|0;q=c[p>>2]|0;do if((q|0)!=-1){t=c[j>>2]|0;s=t+(q<<2)|0;o=(c[s>>2]&16|0)==0;if(o){u=c[t+(q+1<<2)>>2]|0;n=u>>1;u=(d[(c[h>>2]|0)+n>>0]|0)^u&1;w=a[528]|0;v=w&255;if(!((u&255)<<24>>24==w<<24>>24&(v>>>1^1)|v&2&u))break;w=c[r+(n<<3)>>2]|0;if(!((w|0)!=-1&(w|0)==(q|0)))break;if(o){w=wc(e,s)|0;c[p>>2]=w;c[s>>2]=c[s>>2]|16;c[t+(q+1<<2)>>2]=w;break}}c[p>>2]=c[t+(q+1<<2)>>2]}while(0);m=m+1|0}while((m|0)<(c[g>>2]|0))}g=b+272|0;n=c[g>>2]|0;if((n|0)>0){j=b+268|0;h=b+544|0;m=c[j>>2]|0;k=0;l=0;do{p=m+(k<<2)|0;o=c[p>>2]|0;r=c[h>>2]|0;q=r+(o<<2)|0;s=c[q>>2]|0;if((s&3|0)!=1){if(!(s&16)){n=wc(e,q)|0;c[p>>2]=n;c[q>>2]=c[q>>2]|16;c[r+(o+1<<2)>>2]=n;n=c[j>>2]|0;m=n;n=c[n+(k<<2)>>2]|0}else{n=c[r+(o+1<<2)>>2]|0;c[p>>2]=n}c[m+(l<<2)>>2]=n;n=c[g>>2]|0;l=l+1|0}k=k+1|0}while((k|0)<(n|0))}else{k=0;l=0}h=k-l|0;if((h|0)>0)c[g>>2]=n-h;g=b+260|0;m=c[g>>2]|0;if((m|0)>0){h=b+256|0;b=b+544|0;l=c[h>>2]|0;j=0;k=0;do{n=l+(j<<2)|0;p=c[n>>2]|0;o=c[b>>2]|0;r=o+(p<<2)|0;q=c[r>>2]|0;if((q&3|0)!=1){if(!(q&16)){m=wc(e,r)|0;c[n>>2]=m;c[r>>2]=c[r>>2]|16;c[o+(p+1<<2)>>2]=m;m=c[h>>2]|0;l=m;m=c[m+(j<<2)>>2]|0}else{m=c[o+(p+1<<2)>>2]|0;c[n>>2]=m}c[l+(k<<2)>>2]=m;m=c[g>>2]|0;k=k+1|0}j=j+1|0}while((j|0)<(m|0))}else{j=0;k=0}e=j-k|0;if((e|0)<=0){i=f;return}c[g>>2]=m-e;i=f;return}function bc(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0;g=i;i=i+32|0;j=g;d=g+8|0;e=b+548|0;f=b+556|0;h=(c[e>>2]|0)-(c[f>>2]|0)|0;c[d+0>>2]=0;c[d+4>>2]=0;c[d+8>>2]=0;c[d+12>>2]=0;gc(d,h);h=d+16|0;a[h>>0]=0;ac(b,d);if((c[b+44>>2]|0)>1){k=c[d+4>>2]<<2;c[j>>2]=c[e>>2]<<2;c[j+4>>2]=k;La(1888,j|0)|0}a[b+560>>0]=a[h>>0]|0;h=b+544|0;j=c[h>>2]|0;if(j)Td(j);c[h>>2]=c[d>>2];c[e>>2]=c[d+4>>2];c[b+552>>2]=c[d+8>>2];c[f>>2]=c[d+12>>2];i=g;return}function cc(){var d=0,e=0,f=0;d=i;i=i+16|0;e=d;a[528]=0;a[536]=1;a[544]=2;xb(552,608,624,2136,2144);c[138]=2168;h[72]=0.0;h[73]=1.0;a[592]=0;a[593]=0;b[297]=b[e+0>>1]|0;b[298]=b[e+2>>1]|0;b[299]=b[e+4>>1]|0;h[75]=.95;xb(664,720,736,2136,2144);c[166]=2168;h[86]=0.0;h[87]=1.0;a[704]=0;a[705]=0;b[353]=b[e+0>>1]|0;b[354]=b[e+2>>1]|0;b[355]=b[e+4>>1]|0;h[89]=.999;xb(776,832,848,2136,2144);c[194]=2168;h[100]=0.0;h[101]=1.0;a[816]=1;a[817]=1;b[409]=b[e+0>>1]|0;b[410]=b[e+2>>1]|0;b[411]=b[e+4>>1]|0;h[103]=0.0;xb(936,992,1008,2136,2144);c[234]=2168;h[120]=0.0;h[121]=v;a[976]=0;a[977]=0;b[489]=b[e+0>>1]|0;b[490]=b[e+2>>1]|0;b[491]=b[e+4>>1]|0;h[123]=91648253.0;xb(1048,1080,1096,2136,2016);c[262]=280;f=1068|0;c[f>>2]=0;c[f+4>>2]=2;c[269]=2;xb(1160,1192,1208,2136,2016);c[290]=280;f=1180|0;c[f>>2]=0;c[f+4>>2]=2;c[297]=2;xb(1272,1296,1312,2136,1992);c[318]=160;a[1292]=0;xb(1344,1368,1376,2136,1992);c[336]=160;a[1364]=1;xb(1408,1440,1448,2136,2016);c[352]=280;f=1428|0;c[f>>2]=1;c[f+4>>2]=2147483647;c[359]=100;xb(1480,1536,1544,2136,2144);c[370]=2168;h[188]=1.0;h[189]=v;a[1520]=0;a[1521]=0;b[761]=b[e+0>>1]|0;b[762]=b[e+2>>1]|0;b[763]=b[e+4>>1]|0;h[191]=2.0;xb(1584,1640,1648,2136,2144);c[396]=2168;h[201]=0.0;h[202]=v;a[1624]=0;a[1625]=0;b[813]=b[e+0>>1]|0;b[814]=b[e+2>>1]|0;b[815]=b[e+4>>1]|0;h[204]=.2;xb(1728,1760,1776,2136,2016);c[432]=280;e=1748|0;c[e>>2]=0;c[e+4>>2]=2147483647;c[439]=0;i=d;return}function dc(a){a=a|0;var b=0;b=i;pd(a);i=b;return}function ec(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,q=0.0,r=0.0;e=i;i=i+16|0;j=e;g=e+8|0;if((a[d>>0]|0)!=45){o=0;i=e;return o|0}m=d+1|0;f=b+4|0;k=c[f>>2]|0;l=a[k>>0]|0;a:do if(l<<24>>24){n=0;while(1){o=n;n=n+1|0;if((a[m>>0]|0)!=l<<24>>24){b=0;break}l=a[k+n>>0]|0;m=d+(o+2)|0;if(!(l<<24>>24))break a}i=e;return b|0}while(0);if((a[m>>0]|0)!=61){o=0;i=e;return o|0}k=m+1|0;q=+ce(k,g);if(!(c[g>>2]|0)){o=0;i=e;return o|0}r=+h[b+32>>3];if(q>=r?(a[b+41>>0]|0)==0|q!=r:0){o=c[p>>2]|0;n=c[f>>2]|0;c[j>>2]=k;c[j+4>>2]=n;Za(o|0,2024,j|0)|0;ab(1)}r=+h[b+24>>3];if(q<=r?(a[b+40>>0]|0)==0|q!=r:0){o=c[p>>2]|0;n=c[f>>2]|0;c[j>>2]=k;c[j+4>>2]=n;Za(o|0,2080,j|0)|0;ab(1)}h[b+48>>3]=q;o=1;i=e;return o|0}function fc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0.0,m=0,n=0.0,o=0.0,q=0;e=i;i=i+48|0;f=e;g=c[p>>2]|0;q=c[b+16>>2]|0;m=(a[b+40>>0]|0)!=0?91:40;o=+h[b+24>>3];n=+h[b+32>>3];j=(a[b+41>>0]|0)!=0?93:41;l=+h[b+48>>3];c[f>>2]=c[b+4>>2];c[f+4>>2]=q;c[f+8>>2]=m;m=f+12|0;h[k>>3]=o;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];m=f+20|0;h[k>>3]=n;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];c[f+28>>2]=j;j=f+32|0;h[k>>3]=l;c[j>>2]=c[k>>2];c[j+4>>2]=c[k+4>>2];Za(g|0,2232,f|0)|0;if(!d){i=e;return}c[f>>2]=c[b+8>>2];Za(g|0,2e3,f|0)|0;Sa(10,g|0)|0;i=e;return}function gc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;e=a+8|0;f=c[e>>2]|0;if(f>>>0<b>>>0)h=f;else{i=d;return}while(1){if(h>>>0>=b>>>0)break;h=((h>>>3)+2+(h>>>1)&-2)+h|0;c[e>>2]=h;if(h>>>0<=f>>>0){g=4;break}}if((g|0)==4)Ta(va(1)|0,48,0);e=Ud(c[a>>2]|0,h<<2)|0;if((e|0)==0?(c[(Oa()|0)>>2]|0)==12:0)Ta(va(1)|0,48,0);c[a>>2]=e;i=d;return}function hc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0;b=i;e=a+32|0;d=c[e>>2]|0;if(d){c[a+36>>2]=0;Td(d);c[e>>2]=0;c[a+40>>2]=0}e=a+16|0;d=c[e>>2]|0;if(d){c[a+20>>2]=0;Td(d);c[e>>2]=0;c[a+24>>2]=0}e=c[a>>2]|0;if(!e){i=b;return}d=a+4|0;g=c[d>>2]|0;if((g|0)>0){f=0;do{j=e+(f*12|0)|0;h=c[j>>2]|0;if(h){c[e+(f*12|0)+4>>2]=0;Td(h);c[j>>2]=0;c[e+(f*12|0)+8>>2]=0;e=c[a>>2]|0;g=c[d>>2]|0}f=f+1|0}while((f|0)<(g|0))}c[d>>2]=0;Td(e);c[a>>2]=0;c[a+8>>2]=0;i=b;return}function ic(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;f=i;i=i+16|0;e=f+4|0;d=f;l=c[b>>2]|0;h=l+1|0;g=a+4|0;if((c[g>>2]|0)<(h|0)){k=a+8|0;j=c[k>>2]|0;if((j|0)<(h|0)){m=l+2-j&-2;l=(j>>1)+2&-2;l=(m|0)>(l|0)?m:l;if((l|0)>(2147483647-j|0)){m=va(1)|0;Ta(m|0,48,0)}n=c[a>>2]|0;m=l+j|0;c[k>>2]=m;m=Ud(n,m*12|0)|0;c[a>>2]=m;if((m|0)==0?(c[(Oa()|0)>>2]|0)==12:0){n=va(1)|0;Ta(n|0,48,0)}}k=c[g>>2]|0;if((k|0)<(h|0)){j=c[a>>2]|0;do{l=j+(k*12|0)|0;if(l){c[l>>2]=0;c[j+(k*12|0)+4>>2]=0;c[j+(k*12|0)+8>>2]=0}k=k+1|0}while((k|0)!=(h|0))}c[g>>2]=h;l=c[b>>2]|0}g=c[a>>2]|0;if(!(c[g+(l*12|0)>>2]|0)){m=l;n=a+16|0;c[d>>2]=m;c[e+0>>2]=c[d+0>>2];sc(n,e,0);i=f;return}c[g+(l*12|0)+4>>2]=0;m=c[b>>2]|0;n=a+16|0;c[d>>2]=m;c[e+0>>2]=c[d+0>>2];sc(n,e,0);i=f;return}function jc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;f=i;e=b+4|0;if((c[e>>2]|0)>=(d|0)){i=f;return}h=b+8|0;g=c[h>>2]|0;if((g|0)<(d|0)){k=d+1-g&-2;j=(g>>1)+2&-2;j=(k|0)>(j|0)?k:j;if((j|0)>(2147483647-g|0)){k=va(1)|0;Ta(k|0,48,0)}l=c[b>>2]|0;k=j+g|0;c[h>>2]=k;k=Ud(l,k)|0;c[b>>2]=k;if((k|0)==0?(c[(Oa()|0)>>2]|0)==12:0){l=va(1)|0;Ta(l|0,48,0)}}g=c[e>>2]|0;if((g|0)<(d|0)){b=c[b>>2]|0;do{h=b+g|0;if(h)a[h>>0]=0;g=g+1|0}while((g|0)!=(d|0))}c[e>>2]=d;i=f;return}function kc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;h=i;g=d+1|0;f=b+4|0;if((c[f>>2]|0)>=(g|0)){l=c[b>>2]|0;l=l+d|0;a[l>>0]=e;i=h;return}k=b+8|0;j=c[k>>2]|0;if((j|0)<(g|0)){m=d+2-j&-2;l=(j>>1)+2&-2;l=(m|0)>(l|0)?m:l;if((l|0)>(2147483647-j|0)){m=va(1)|0;Ta(m|0,48,0)}n=c[b>>2]|0;m=l+j|0;c[k>>2]=m;m=Ud(n,m)|0;c[b>>2]=m;if((m|0)==0?(c[(Oa()|0)>>2]|0)==12:0){n=va(1)|0;Ta(n|0,48,0)}}j=c[f>>2]|0;if((j|0)<(g|0))do{k=(c[b>>2]|0)+j|0;if(k)a[k>>0]=0;j=j+1|0}while((j|0)!=(g|0));c[f>>2]=g;n=c[b>>2]|0;n=n+d|0;a[n>>0]=e;i=h;return}function lc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0;d=i;i=i+16|0;g=d;c[g>>2]=b;j=a+12|0;f=b+1|0;e=a+16|0;if((c[e>>2]|0)<(f|0)){l=a+20|0;k=c[l>>2]|0;if((k|0)<(f|0)){n=b+2-k&-2;m=(k>>1)+2&-2;m=(n|0)>(m|0)?n:m;if((m|0)>(2147483647-k|0)){n=va(1)|0;Ta(n|0,48,0)}o=c[j>>2]|0;n=m+k|0;c[l>>2]=n;n=Ud(o,n<<2)|0;c[j>>2]=n;if((n|0)==0?(c[(Oa()|0)>>2]|0)==12:0){o=va(1)|0;Ta(o|0,48,0)}}k=c[e>>2]|0;if((f|0)>(k|0))ke((c[j>>2]|0)+(k<<2)|0,-1,f-k<<2|0)|0;c[e>>2]=f}c[(c[j>>2]|0)+(b<<2)>>2]=c[a+4>>2];nc(a,g);e=c[j>>2]|0;g=c[e+(b<<2)>>2]|0;b=c[a>>2]|0;f=c[b+(g<<2)>>2]|0;if(!g){n=0;o=b+(n<<2)|0;c[o>>2]=f;o=e+(f<<2)|0;c[o>>2]=n;i=d;return}a=a+28|0;while(1){j=g;g=g+ -1>>1;k=b+(g<<2)|0;l=c[k>>2]|0;o=c[c[a>>2]>>2]|0;if(!(+h[o+(f<<3)>>3]>+h[o+(l<<3)>>3])){a=14;break}c[b+(j<<2)>>2]=l;c[e+(c[k>>2]<<2)>>2]=j;if(!g){j=0;a=14;break}}if((a|0)==14){o=b+(j<<2)|0;c[o>>2]=f;o=e+(f<<2)|0;c[o>>2]=j;i=d;return}}function mc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;e=a+4|0;f=c[e>>2]|0;g=a+8|0;h=c[g>>2]|0;if((f|0)==(h|0)&(h|0)<(f+1|0)){h=(f>>1)+2&-2;h=(h|0)<2?2:h;if((h|0)>(2147483647-f|0)){h=va(1)|0;Ta(h|0,48,0)}j=c[a>>2]|0;f=h+f|0;c[g>>2]=f;f=Ud(j,f<<2)|0;c[a>>2]=f;if((f|0)==0?(c[(Oa()|0)>>2]|0)==12:0){j=va(1)|0;Ta(j|0,48,0)}}else f=c[a>>2]|0;j=c[e>>2]|0;c[e>>2]=j+1;e=f+(j<<2)|0;if(!e){i=d;return}c[e>>2]=c[b>>2];i=d;return}function nc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;e=a+4|0;f=c[e>>2]|0;g=a+8|0;h=c[g>>2]|0;if((f|0)==(h|0)&(h|0)<(f+1|0)){h=(f>>1)+2&-2;h=(h|0)<2?2:h;if((h|0)>(2147483647-f|0)){h=va(1)|0;Ta(h|0,48,0)}j=c[a>>2]|0;f=h+f|0;c[g>>2]=f;f=Ud(j,f<<2)|0;c[a>>2]=f;if((f|0)==0?(c[(Oa()|0)>>2]|0)==12:0){j=va(1)|0;Ta(j|0,48,0)}}else f=c[a>>2]|0;j=c[e>>2]|0;c[e>>2]=j+1;e=f+(j<<2)|0;if(!e){i=d;return}c[e>>2]=c[b>>2];i=d;return}function oc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;i=i+16|0;f=e+2|0;h=e+1|0;g=e;if((d|0)<16){g=d+ -1|0;if((g|0)>0)h=0;else{i=e;return}do{f=h;h=h+1|0;if((h|0)<(d|0)){k=f;j=h;do{k=(c[b+(j<<2)>>2]|0)<(c[b+(k<<2)>>2]|0)?j:k;j=j+1|0}while((j|0)!=(d|0))}else k=f;n=b+(f<<2)|0;o=c[n>>2]|0;p=b+(k<<2)|0;c[n>>2]=c[p>>2];c[p>>2]=o}while((h|0)!=(g|0));i=e;return}j=c[b+(((d|0)/2|0)<<2)>>2]|0;m=-1;n=d;while(1){do{m=m+1|0;l=b+(m<<2)|0;k=c[l>>2]|0}while((k|0)<(j|0));do{n=n+ -1|0;o=b+(n<<2)|0;p=c[o>>2]|0}while((j|0)<(p|0));if((m|0)>=(n|0))break;c[l>>2]=p;c[o>>2]=k}a[f+0>>0]=a[h+0>>0]|0;oc(b,m,f);p=d-m|0;a[f+0>>0]=a[g+0>>0]|0;oc(l,p,f);i=e;return}function pc(a,b,e){a=a|0;b=b|0;e=e|0;var f=0,h=0,j=0,k=0,l=0,m=0;f=i;k=e&1;j=d[a+16>>0]|0|k;h=b+4|0;l=((j+(c[h>>2]|0)<<2)+4|0)>>>2;m=a+4|0;gc(a,l+(c[m>>2]|0)|0);e=c[m>>2]|0;l=l+e|0;c[m>>2]=l;if(l>>>0<e>>>0)Ta(va(1)|0,48,0);a=(c[a>>2]|0)+(e<<2)|0;if(!a){i=f;return e|0}j=j<<3|k<<2;c[a>>2]=c[a>>2]&-32|j;j=c[h>>2]<<5|j;c[a>>2]=j;if((c[h>>2]|0)>0){j=c[b>>2]|0;b=0;do{c[a+(b<<2)+4>>2]=c[j+(b<<2)>>2];b=b+1|0}while((b|0)<(c[h>>2]|0));j=c[a>>2]|0}if(!(j&8)){i=f;return e|0}h=j>>>5;if(j&4){g[a+(h<<2)+4>>2]=0.0;i=f;return e|0}if(!h){h=0;j=0}else{j=0;b=0;do{j=1<<((c[a+(b<<2)+4>>2]|0)>>>1&31)|j;b=b+1|0}while((b|0)<(h|0))}c[a+(h<<2)+4>>2]=j;i=f;return e|0}function qc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;e=a+4|0;f=c[e>>2]|0;g=a+8|0;h=c[g>>2]|0;if((f|0)==(h|0)&(h|0)<(f+1|0)){h=(f>>1)+2&-2;h=(h|0)<2?2:h;if((h|0)>(2147483647-f|0)){h=va(1)|0;Ta(h|0,48,0)}j=c[a>>2]|0;f=h+f|0;c[g>>2]=f;f=Ud(j,f<<3)|0;c[a>>2]=f;if((f|0)==0?(c[(Oa()|0)>>2]|0)==12:0){j=va(1)|0;Ta(j|0,48,0)}}else f=c[a>>2]|0;j=c[e>>2]|0;c[e>>2]=j+1;e=f+(j<<3)|0;if(!e){i=d;return}g=b;h=c[g+4>>2]|0;j=e;c[j>>2]=c[g>>2];c[j+4>>2]=h;i=d;return}function rc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0;b=i;d=c[a>>2]|0;f=c[d>>2]|0;k=a+4|0;o=c[d+((c[k>>2]|0)+ -1<<2)>>2]|0;c[d>>2]=o;e=c[a+12>>2]|0;c[e+(o<<2)>>2]=0;c[e+(f<<2)>>2]=-1;o=(c[k>>2]|0)+ -1|0;c[k>>2]=o;if((o|0)<=1){i=b;return f|0}g=c[d>>2]|0;l=a+28|0;a=0;m=1;while(1){n=(a<<1)+2|0;if((n|0)<(o|0)){p=c[d+(n<<2)>>2]|0;s=c[d+(m<<2)>>2]|0;o=c[c[l>>2]>>2]|0;q=+h[o+(p<<3)>>3];r=+h[o+(s<<3)>>3];if(!(q>r)){p=s;q=r;j=6}}else{o=c[c[l>>2]>>2]|0;j=c[d+(m<<2)>>2]|0;p=j;q=+h[o+(j<<3)>>3];j=6}if((j|0)==6){j=0;n=m}if(!(q>+h[o+(g<<3)>>3]))break;c[d+(a<<2)>>2]=p;c[e+(p<<2)>>2]=a;m=n<<1|1;o=c[k>>2]|0;if((m|0)>=(o|0)){a=n;break}else a=n}c[d+(a<<2)>>2]=g;c[e+(g<<2)>>2]=a;i=b;return f|0}function sc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;k=c[d>>2]|0;d=k+1|0;g=b+4|0;if((c[g>>2]|0)>=(d|0)){i=f;return}j=b+8|0;h=c[j>>2]|0;if((h|0)<(d|0)){l=k+2-h&-2;k=(h>>1)+2&-2;k=(l|0)>(k|0)?l:k;if((k|0)>(2147483647-h|0)){l=va(1)|0;Ta(l|0,48,0)}m=c[b>>2]|0;l=k+h|0;c[j>>2]=l;l=Ud(m,l)|0;c[b>>2]=l;if((l|0)==0?(c[(Oa()|0)>>2]|0)==12:0){m=va(1)|0;Ta(m|0,48,0)}}h=c[g>>2]|0;if((h|0)<(d|0))do{a[(c[b>>2]|0)+h>>0]=e;h=h+1|0}while((h|0)!=(d|0));c[g>>2]=d;i=f;return}function tc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;e=i;i=i+16|0;h=e+8|0;f=e+4|0;j=e;if((b|0)<16){f=b+ -1|0;if((f|0)<=0){i=e;return}h=c[d>>2]|0;d=0;do{j=d;d=d+1|0;if((d|0)<(b|0)){k=c[h>>2]|0;m=j;l=d;do{n=k+(c[a+(l<<2)>>2]<<2)|0;u=c[n>>2]|0;q=u>>>5;if(u>>>0>95){o=k+(c[a+(m<<2)>>2]<<2)|0;p=(c[o>>2]|0)>>>5;if((p|0)==2)m=l;else m=+g[n+(q<<2)+4>>2]<+g[o+(p<<2)+4>>2]?l:m}l=l+1|0}while((l|0)!=(b|0))}else m=j;s=a+(j<<2)|0;t=c[s>>2]|0;u=a+(m<<2)|0;c[s>>2]=c[u>>2];c[u>>2]=t}while((d|0)!=(f|0));i=e;return}k=c[a+(((b|0)/2|0)<<2)>>2]|0;q=-1;o=b;while(1){t=q+1|0;p=a+(t<<2)|0;u=c[p>>2]|0;l=c[d>>2]|0;m=c[l>>2]|0;s=m+(u<<2)|0;r=c[s>>2]|0;q=m+(k<<2)|0;n=c[q>>2]|0;a:do if(r>>>0>95)while(1){v=n>>>5;if((v|0)!=2?!(+g[s+(r>>>5<<2)+4>>2]<+g[q+(v<<2)+4>>2]):0){q=t;break a}t=t+1|0;p=a+(t<<2)|0;u=c[p>>2]|0;s=m+(u<<2)|0;r=c[s>>2]|0;if(r>>>0<=95){q=t;break}}else q=t;while(0);o=o+ -1|0;s=a+(o<<2)|0;r=m+(k<<2)|0;b:do if(n>>>0>95)while(1){t=m+(c[s>>2]<<2)|0;v=(c[t>>2]|0)>>>5;if((v|0)!=2?!(+g[r+(n>>>5<<2)+4>>2]<+g[t+(v<<2)+4>>2]):0)break b;v=o+ -1|0;s=a+(v<<2)|0;o=v}while(0);if((q|0)>=(o|0))break;c[p>>2]=c[s>>2];c[s>>2]=u}c[f>>2]=l;c[h+0>>2]=c[f+0>>2];tc(a,q,h);v=b-q|0;c[j>>2]=l;c[h+0>>2]=c[j+0>>2];tc(p,v,h);i=e;return}function uc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0;e=i;f=a+4|0;j=c[f>>2]|0;g=c[a>>2]|0;if((j|0)>0){l=c[a+12>>2]|0;k=0;do{c[l+(c[g+(k<<2)>>2]<<2)>>2]=-1;k=k+1|0;j=c[f>>2]|0}while((k|0)<(j|0))}if(g){c[f>>2]=0;j=0}g=b+4|0;if((c[g>>2]|0)>0){k=a+12|0;j=0;do{s=(c[b>>2]|0)+(j<<2)|0;c[(c[k>>2]|0)+(c[s>>2]<<2)>>2]=j;nc(a,s);j=j+1|0}while((j|0)<(c[g>>2]|0));j=c[f>>2]|0}if((j|0)<=1){i=e;return}g=c[a>>2]|0;b=a+28|0;a=a+12|0;o=j;k=(j|0)/2|0;while(1){k=k+ -1|0;j=c[g+(k<<2)>>2]|0;m=k<<1|1;a:do if((m|0)<(o|0)){l=k;while(1){n=(l<<1)+2|0;if((n|0)<(o|0)){p=c[g+(n<<2)>>2]|0;s=c[g+(m<<2)>>2]|0;o=c[c[b>>2]>>2]|0;q=+h[o+(p<<3)>>3];r=+h[o+(s<<3)>>3];if(!(q>r)){p=s;q=r;d=16}}else{o=c[c[b>>2]>>2]|0;d=c[g+(m<<2)>>2]|0;p=d;q=+h[o+(d<<3)>>3];d=16}if((d|0)==16){d=0;n=m}if(!(q>+h[o+(j<<3)>>3]))break a;c[g+(l<<2)>>2]=p;c[(c[a>>2]|0)+(p<<2)>>2]=l;m=n<<1|1;o=c[f>>2]|0;if((m|0)>=(o|0)){l=n;break}else l=n}}else l=k;while(0);c[g+(l<<2)>>2]=j;c[(c[a>>2]|0)+(j<<2)>>2]=l;if((k|0)<=0)break;o=c[f>>2]|0}i=e;return}function vc(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;e=i;d=b+36|0;l=c[d>>2]|0;f=b+32|0;n=c[f>>2]|0;if((l|0)>0){h=b+16|0;g=b+44|0;j=0;do{k=n+(j<<2)|0;m=c[k>>2]|0;if(a[(c[h>>2]|0)+m>>0]|0){n=c[b>>2]|0;l=n+(m*12|0)+4|0;p=c[l>>2]|0;if((p|0)>0){m=n+(m*12|0)|0;n=0;o=0;do{q=c[m>>2]|0;r=q+(n<<3)|0;if((c[(c[c[g>>2]>>2]|0)+(c[r>>2]<<2)>>2]&3|0)!=1){s=r;r=c[s+4>>2]|0;p=q+(o<<3)|0;c[p>>2]=c[s>>2];c[p+4>>2]=r;p=c[l>>2]|0;o=o+1|0}n=n+1|0}while((n|0)<(p|0))}else{n=0;o=0}m=n-o|0;if((m|0)>0)c[l>>2]=p-m;a[(c[h>>2]|0)+(c[k>>2]|0)>>0]=0;l=c[d>>2]|0;n=c[f>>2]|0}j=j+1|0}while((j|0)<(l|0))}if(!n){i=e;return}c[d>>2]=0;i=e;return}function wc(a,b){a=a|0;b=b|0;var e=0,f=0,h=0,j=0,k=0;f=i;j=c[b>>2]|0;h=j>>>2&1|(d[a+16>>0]|0);j=((h+(j>>>5)<<2)+4|0)>>>2;k=a+4|0;gc(a,j+(c[k>>2]|0)|0);e=c[k>>2]|0;j=j+e|0;c[k>>2]=j;if(j>>>0<e>>>0)Ta(va(1)|0,48,0);a=(c[a>>2]|0)+(e<<2)|0;if(!a){i=f;return e|0}h=c[b>>2]&-9|h<<3;c[a>>2]=h;if((c[b>>2]|0)>>>0>31){h=0;do{c[a+(h<<2)+4>>2]=c[b+(h<<2)+4>>2];h=h+1|0}while((h|0)<((c[b>>2]|0)>>>5|0));h=c[a>>2]|0}if(!(h&8)){i=f;return e|0}j=h>>>5;b=b+(j<<2)+4|0;if(!(h&4)){c[a+(j<<2)+4>>2]=c[b>>2];i=f;return e|0}else{g[a+(j<<2)+4>>2]=+g[b>>2];i=f;return e|0}return 0}function xc(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0;d=i;i=i+16|0;g=d;Gb(b);c[b>>2]=3424;c[b+684>>2]=c[719];c[b+688>>2]=c[747];c[b+692>>2]=c[785];h[b+696>>3]=+h[411];a[b+704>>0]=a[2652]|0;a[b+705>>0]=a[2724]|0;a[b+706>>0]=a[2804]|0;a[b+707>>0]=1;c[b+708>>2]=0;c[b+712>>2]=0;c[b+716>>2]=0;c[b+720>>2]=1;a[b+724>>0]=1;e=b+732|0;k=b+544|0;c[b+760>>2]=0;c[b+764>>2]=0;c[b+768>>2]=0;c[b+776>>2]=0;c[b+780>>2]=0;c[b+784>>2]=0;c[b+792>>2]=0;c[b+796>>2]=0;c[b+800>>2]=0;j=b+804|0;c[e+0>>2]=0;c[e+4>>2]=0;c[e+8>>2]=0;c[e+12>>2]=0;c[e+16>>2]=0;c[e+20>>2]=0;c[j>>2]=k;j=b+808|0;c[j>>2]=0;c[b+812>>2]=0;c[b+816>>2]=0;e=b+824|0;c[e+0>>2]=0;c[e+4>>2]=0;c[e+8>>2]=0;c[e+12>>2]=0;c[e+16>>2]=0;c[e+20>>2]=0;c[b+852>>2]=j;Qc(b+856|0,1);j=b+868|0;e=b+892|0;c[b+920>>2]=0;c[b+924>>2]=0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;c[j+16>>2]=0;c[e+0>>2]=0;c[e+4>>2]=0;c[e+8>>2]=0;c[e+12>>2]=0;c[e+16>>2]=0;c[e+20>>2]=0;e=g+4|0;c[e>>2]=0;j=g+8|0;c[j>>2]=2;f=Ud(0,8)|0;c[g>>2]=f;if((f|0)==0?(c[(Oa()|0)>>2]|0)==12:0)Ta(va(1)|0,48,0);c[f>>2]=-2;c[e>>2]=1;a[b+560>>0]=1;c[b+928>>2]=pc(k,g,0)|0;a[b+536>>0]=0;if(!f){i=d;return}c[e>>2]=0;Td(f);c[g>>2]=0;c[j>>2]=0;i=d;return}function yc(a){a=a|0;var b=0;b=i;zc(a);pd(a);i=b;return}function zc(a){a=a|0;var b=0,d=0,e=0;b=i;c[a>>2]=3424;d=a+904|0;e=c[d>>2]|0;if(e){c[a+908>>2]=0;Td(e);c[d>>2]=0;c[a+912>>2]=0}d=a+892|0;e=c[d>>2]|0;if(e){c[a+896>>2]=0;Td(e);c[d>>2]=0;c[a+900>>2]=0}d=a+876|0;e=c[d>>2]|0;if(e){c[a+880>>2]=0;Td(e);c[d>>2]=0;c[a+884>>2]=0}d=a+856|0;e=c[d>>2]|0;if(e){c[a+860>>2]=0;Td(e);c[d>>2]=0;c[a+864>>2]=0}e=a+836|0;d=c[e>>2]|0;if(d){c[a+840>>2]=0;Td(d);c[e>>2]=0;c[a+844>>2]=0}d=a+824|0;e=c[d>>2]|0;if(e){c[a+828>>2]=0;Td(e);c[d>>2]=0;c[a+832>>2]=0}d=a+808|0;e=c[d>>2]|0;if(e){c[a+812>>2]=0;Td(e);c[d>>2]=0;c[a+816>>2]=0}Rc(a+760|0);d=a+744|0;e=c[d>>2]|0;if(e){c[a+748>>2]=0;Td(e);c[d>>2]=0;c[a+752>>2]=0}d=a+732|0;e=c[d>>2]|0;if(!e){Ib(a);i=b;return}c[a+736>>2]=0;Td(e);c[d>>2]=0;c[a+740>>2]=0;Ib(a);i=b;return}function Ac(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0;f=i;i=i+32|0;h=f+12|0;k=f+8|0;l=f+16|0;g=f+4|0;j=f;a[l>>0]=a[d>>0]|0;a[h+0>>0]=a[l+0>>0]|0;e=Jb(b,h,e)|0;c[k>>2]=e;kc(b+876|0,e,0);kc(b+904|0,e,0);if(!(a[b+724>>0]|0)){i=f;return e|0}l=b+808|0;d=e<<1;c[g>>2]=d;c[h+0>>2]=c[g+0>>2];Sc(l,h,0);c[j>>2]=d|1;c[h+0>>2]=c[j+0>>2];Sc(l,h,0);Tc(b+760|0,k);kc(b+744|0,e,0);Uc(b+824|0,e);i=f;return e|0}function Bc(b,e,f,g){b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;k=i;i=i+32|0;h=k+4|0;r=k;p=k+16|0;c[h>>2]=0;j=h+4|0;c[j>>2]=0;l=h+8|0;c[l>>2]=0;s=a[2608]|0;a[b>>0]=s;m=e+724|0;f=(d[m>>0]&(f&1)|0)!=0;if(f){u=e+308|0;x=c[u>>2]|0;if((x|0)>0){t=e+304|0;s=e+876|0;v=0;do{w=c[(c[t>>2]|0)+(v<<2)>>2]>>1;c[r>>2]=w;w=(c[s>>2]|0)+w|0;if(!(a[w>>0]|0)){a[w>>0]=1;nc(h,r);x=c[u>>2]|0}v=v+1|0}while((v|0)<(x|0))}r=(Cc(e,g)|0)&1^1;a[b>>0]=r;g=a[2608]|0}else{g=s;r=s}x=g&255;if(!((x>>>1^1)&r<<24>>24==g<<24>>24|x&2&(r&255))){if((c[e+44>>2]|0)>0)Ka(3760)|0}else{$b(p,e);r=a[p>>0]|0;a[b>>0]=r}w=a[2608]|0;x=w&255;if((((x>>>1^1)&r<<24>>24==w<<24>>24|x&2&(r&255)|0)!=0?(a[e+707>>0]|0)!=0:0)?(q=(c[e+736>>2]|0)+ -1|0,(q|0)>0):0){b=e+732|0;p=e+4|0;do{g=c[b>>2]|0;u=c[g+(q<<2)>>2]|0;v=q+ -1|0;w=c[g+(v<<2)>>2]|0;q=c[p>>2]|0;a:do if((u|0)>1){s=a[2616]|0;r=s&255;t=r&2;r=r>>>1^1;x=v;while(1){w=d[q+(w>>1)>>0]^w&1;v=u+ -1|0;if(!((w&255)<<24>>24==s<<24>>24&r|t&w))break a;u=x+ -1|0;w=c[g+(u<<2)>>2]|0;if((v|0)>1){x=u;u=v}else{x=u;u=v;o=20;break}}}else{x=v;o=20}while(0);if((o|0)==20){o=0;a[q+(w>>1)>>0]=(w&1^1)&255^1}q=x-u|0}while((q|0)>0)}if(f?(n=c[j>>2]|0,(n|0)>0):0){o=c[h>>2]|0;f=e+876|0;p=0;do{b=c[o+(p<<2)>>2]|0;a[(c[f>>2]|0)+b>>0]=0;if(a[m>>0]|0)Vc(e,b);p=p+1|0}while((p|0)<(n|0))}e=c[h>>2]|0;if(!e){i=k;return}c[j>>2]=0;Td(e);c[h>>2]=0;c[l>>2]=0;i=k;return}function Cc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0;m=i;i=i+16|0;j=m;if(!(Zb(b)|0)){H=0;i=m;return H|0}l=b+724|0;if(!(a[l>>0]|0)){H=1;i=m;return H|0}x=b+924|0;v=b+872|0;w=b+868|0;u=b+860|0;r=b+680|0;y=b+824|0;g=b+828|0;o=b+836|0;z=b+904|0;A=b+332|0;e=b+44|0;B=b+704|0;D=b+706|0;E=b+696|0;p=b+556|0;q=b+548|0;C=b+876|0;s=b+920|0;t=b+284|0;a:while(1){if(((c[x>>2]|0)<=0?(c[s>>2]|0)>=(c[t>>2]|0):0)?(c[g>>2]|0)<=0:0)break;Ic(b);G=c[v>>2]|0;H=c[w>>2]|0;F=G-H|0;if((G|0)<(H|0))F=(c[u>>2]|0)+F|0;if(!((F|0)<=0?(c[s>>2]|0)>=(c[t>>2]|0):0))n=11;if((n|0)==11?(n=0,!(Jc(b,1)|0)):0){n=12;break}H=c[g>>2]|0;if(a[r>>0]|0){n=15;break}if(!H)continue;else F=0;while(1){J=c[y>>2]|0;G=c[J>>2]|0;I=c[J+(H+ -1<<2)>>2]|0;c[J>>2]=I;H=c[o>>2]|0;c[H+(I<<2)>>2]=0;c[H+(G<<2)>>2]=-1;H=(c[g>>2]|0)+ -1|0;c[g>>2]=H;if((H|0)>1)Wc(y,0);if(a[r>>0]|0)continue a;if((a[(c[z>>2]|0)+G>>0]|0)==0?(I=a[(c[A>>2]|0)+G>>0]|0,H=a[2624]|0,J=H&255,((J>>>1^1)&I<<24>>24==H<<24>>24|I&2&J|0)!=0):0){if((c[e>>2]|0)>1&((F|0)%100|0|0)==0){c[j>>2]=c[g>>2];La(3504,j|0)|0}if(a[B>>0]|0){J=(c[C>>2]|0)+G|0;H=a[J>>0]|0;a[J>>0]=1;if(!(Lc(b,G)|0)){n=29;break a}a[(c[C>>2]|0)+G>>0]=H<<24>>24!=0&1}if((((a[D>>0]|0)!=0?(I=a[(c[A>>2]|0)+G>>0]|0,H=a[2624]|0,J=H&255,((J>>>1^1)&I<<24>>24==H<<24>>24|I&2&J|0)!=0):0)?(a[(c[C>>2]|0)+G>>0]|0)==0:0)?!(Mc(b,G)|0):0){n=35;break a}if(+((c[p>>2]|0)>>>0)>+h[E>>3]*+((c[q>>2]|0)>>>0))gb[c[(c[b>>2]|0)+8>>2]&31](b)}H=c[g>>2]|0;if(!H)continue a;else F=F+1|0}}do if((n|0)==12)a[b+492>>0]=0;else if((n|0)==15){r=c[b+824>>2]|0;if((H|0)<=0){if(!r)break}else{t=c[o>>2]|0;s=0;do{c[t+(c[r+(s<<2)>>2]<<2)>>2]=-1;s=s+1|0}while((s|0)<(c[g>>2]|0))}c[g>>2]=0}else if((n|0)==29)a[b+492>>0]=0;else if((n|0)==35)a[b+492>>0]=0;while(0);if(!d){if(+((c[p>>2]|0)>>>0)>+h[b+96>>3]*+((c[q>>2]|0)>>>0))gb[c[(c[b>>2]|0)+8>>2]&31](b)}else{d=b+744|0;p=c[d>>2]|0;if(p){c[b+748>>2]=0;Td(p);c[d>>2]=0;c[b+752>>2]=0}Xc(b+760|0,1);d=b+808|0;p=c[d>>2]|0;if(p){c[b+812>>2]=0;Td(p);c[d>>2]=0;c[b+816>>2]=0}p=b+824|0;d=c[p>>2]|0;if((c[g>>2]|0)<=0){if(d)n=48}else{n=c[o>>2]|0;o=0;do{c[n+(c[d+(o<<2)>>2]<<2)>>2]=-1;o=o+1|0}while((o|0)<(c[g>>2]|0));n=48}if((n|0)==48){c[g>>2]=0;Td(d);c[p>>2]=0;c[b+832>>2]=0}Yc(b+856|0,1);a[l>>0]=0;a[b+536>>0]=1;a[b+560>>0]=0;c[b+728>>2]=c[b+540>>2];Yb(b);gb[c[(c[b>>2]|0)+8>>2]&31](b)}if((c[e>>2]|0)>0?(f=c[b+736>>2]|0,(f|0)>0):0){h[k>>3]=+(f<<2>>>0)*9.5367431640625e-7;c[j>>2]=c[k>>2];c[j+4>>2]=c[k+4>>2];La(3528,j|0)|0}J=(a[b+492>>0]|0)!=0;i=m;return J|0}function Dc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;e=i;i=i+16|0;g=e;j=b+256|0;k=b+260|0;h=c[k>>2]|0;if((a[b+705>>0]|0)!=0?Ec(b,d)|0:0){p=1;i=e;return p|0}if(!(Kb(b,d)|0)){p=0;i=e;return p|0}if(!(a[b+724>>0]|0)){p=1;i=e;return p|0}d=c[k>>2]|0;if((d|0)!=(h+1|0)){p=1;i=e;return p|0}p=c[(c[j>>2]|0)+(d+ -1<<2)>>2]|0;c[g>>2]=p;m=(c[b+544>>2]|0)+(p<<2)|0;Zc(b+856|0,p);if((c[m>>2]|0)>>>0<=31){p=1;i=e;return p|0}l=b+760|0;k=b+808|0;j=b+744|0;h=b+924|0;d=b+824|0;n=b+840|0;b=b+836|0;o=0;do{p=m+(o<<2)+4|0;_c((c[l>>2]|0)+((c[p>>2]>>1)*12|0)|0,g);q=(c[k>>2]|0)+(c[p>>2]<<2)|0;c[q>>2]=(c[q>>2]|0)+1;a[(c[j>>2]|0)+(c[p>>2]>>1)>>0]=1;c[h>>2]=(c[h>>2]|0)+1;p=c[p>>2]>>1;if((c[n>>2]|0)>(p|0)?(f=c[(c[b>>2]|0)+(p<<2)>>2]|0,(f|0)>-1):0)Wc(d,f);o=o+1|0}while((o|0)<((c[m>>2]|0)>>>5|0));f=1;i=e;return f|0}function Ec(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;k=i;i=i+16|0;h=k+8|0;j=k+4|0;g=k;c[j>>2]=c[b+284>>2];nc(b+292|0,j);j=e+4|0;m=c[j>>2]|0;a:do if((m|0)>0){f=b+332|0;l=0;while(1){n=c[(c[e>>2]|0)+(l<<2)>>2]|0;p=d[(c[f>>2]|0)+(n>>1)>>0]|0;q=p^n&1;o=q&255;s=a[2608]|0;r=s&255;if(o<<24>>24==s<<24>>24&(r>>>1^1)|r&2&q)break;r=a[2616]|0;s=r&255;if(!((s>>>1^1)&o<<24>>24==r<<24>>24|p&2&s)){c[g>>2]=n^1;c[h+0>>2]=c[g+0>>2];Lb(b,h,-1);m=c[j>>2]|0}l=l+1|0;if((l|0)>=(m|0))break a}Rb(b,0);s=1;i=k;return s|0}while(0);s=(Mb(b)|0)!=-1;Rb(b,0);i=k;return s|0}function Fc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;i=i+16|0;g=e;f=(c[b+544>>2]|0)+(d<<2)|0;if(!(a[b+724>>0]|0)){Pb(b,d);i=e;return}if((c[f>>2]|0)>>>0<=31){Pb(b,d);i=e;return}j=b+808|0;k=b+776|0;h=b+792|0;l=0;do{m=f+(l<<2)+4|0;n=(c[j>>2]|0)+(c[m>>2]<<2)|0;c[n>>2]=(c[n>>2]|0)+ -1;Vc(b,c[m>>2]>>1);m=c[m>>2]>>1;c[g>>2]=m;m=(c[k>>2]|0)+m|0;if(!(a[m>>0]|0)){a[m>>0]=1;nc(h,g)}l=l+1|0}while((l|0)<((c[f>>2]|0)>>>5|0));Pb(b,d);i=e;return}function Gc(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;g=i;i=i+16|0;j=g+4|0;h=g;l=c[b+544>>2]|0;k=l+(e<<2)|0;Zc(b+856|0,e);if((c[k>>2]&-32|0)==64){Fc(b,e);p=c[f>>2]|0;f=c[k>>2]|0;a:do if(f>>>0>31){m=f>>>5;n=0;while(1){o=n+1|0;if((c[k+(n<<2)+4>>2]|0)==(p|0)){o=n;break a}if((o|0)<(m|0))n=o;else break}}else{m=0;o=0}while(0);n=m+ -1|0;if((o|0)<(n|0))do{f=o;o=o+1|0;c[k+(f<<2)+4>>2]=c[k+(o<<2)+4>>2];f=c[k>>2]|0;m=f>>>5;n=m+ -1|0}while((o|0)<(n|0));if(f&8){c[k+(n<<2)+4>>2]=c[k+(m<<2)+4>>2];f=c[k>>2]|0}m=f+ -32|0;c[k>>2]=m;m=m>>>5;if(!m){m=0;f=0}else{f=0;n=0;do{f=1<<((c[k+(n<<2)+4>>2]|0)>>>1&31)|f;n=n+1|0}while((n|0)<(m|0))}c[k+(m<<2)+4>>2]=f}else{Ob(b,e,1);f=c[f>>2]|0;n=c[k>>2]|0;b:do if(n>>>0>31){m=n>>>5;o=0;while(1){p=o+1|0;if((c[k+(o<<2)+4>>2]|0)==(f|0)){p=o;break b}if((p|0)<(m|0))o=p;else break}}else{m=0;p=0}while(0);o=m+ -1|0;if((p|0)<(o|0))do{n=p;p=p+1|0;c[k+(n<<2)+4>>2]=c[k+(p<<2)+4>>2];n=c[k>>2]|0;m=n>>>5;o=m+ -1|0}while((p|0)<(o|0));if(n&8){c[k+(o<<2)+4>>2]=c[k+(m<<2)+4>>2];n=c[k>>2]|0}o=n+ -32|0;c[k>>2]=o;o=o>>>5;if(!o){o=0;m=0}else{m=0;n=0;do{m=1<<((c[k+(n<<2)+4>>2]|0)>>>1&31)|m;n=n+1|0}while((n|0)<(o|0))}c[k+(o<<2)+4>>2]=m;Nb(b,e);m=f>>1;n=c[b+760>>2]|0;o=n+(m*12|0)|0;n=n+(m*12|0)+4|0;p=c[n>>2]|0;c:do if((p|0)>0){s=c[o>>2]|0;q=0;while(1){r=q+1|0;if((c[s+(q<<2)>>2]|0)==(e|0))break c;if((r|0)<(p|0))q=r;else{q=r;break}}}else q=0;while(0);p=p+ -1|0;if((q|0)<(p|0)){o=c[o>>2]|0;do{p=q;q=q+1|0;c[o+(p<<2)>>2]=c[o+(q<<2)>>2];p=(c[n>>2]|0)+ -1|0}while((q|0)<(p|0))}c[n>>2]=p;s=(c[b+808>>2]|0)+(f<<2)|0;c[s>>2]=(c[s>>2]|0)+ -1;Vc(b,m)}if((c[k>>2]&-32|0)!=32){s=1;i=g;return s|0}l=c[l+(e+1<<2)>>2]|0;k=d[(c[b+332>>2]|0)+(l>>1)>>0]|0;s=k^l&1;e=s&255;q=a[2624]|0;r=q&255;if(!(e<<24>>24==q<<24>>24&(r>>>1^1)|r&2&s)){r=a[2616]|0;s=r&255;if((s>>>1^1)&e<<24>>24==r<<24>>24|k&2&s){s=0;i=g;return s|0}}else{c[h>>2]=l;c[j+0>>2]=c[h+0>>2];Lb(b,j,-1)}s=(Mb(b)|0)==-1;i=g;return s|0}function Hc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;g=i;i=i+16|0;j=g+4|0;h=g;o=a+708|0;c[o>>2]=(c[o>>2]|0)+1;if(c[f>>2]|0)c[f+4>>2]=0;k=(c[b>>2]|0)>>>5>>>0<(c[d>>2]|0)>>>5>>>0;a=k?d:b;b=k?b:d;k=c[b>>2]|0;a:do if(k>>>0>31){d=0;b:while(1){l=c[b+(d<<2)+4>>2]|0;c:do if((l>>1|0)!=(e|0)){m=c[a>>2]|0;d:do if(m>>>0>31){n=0;while(1){o=c[a+(n<<2)+4>>2]|0;n=n+1|0;if((l^o)>>>0<2)break;if((n|0)>=(m>>>5|0))break d}if((o|0)==(l^1|0)){f=0;break b}else break c}while(0);c[j>>2]=l;mc(f,j);k=c[b>>2]|0}while(0);d=d+1|0;if((d|0)>=(k>>>5|0))break a}i=g;return f|0}while(0);d=c[a>>2]|0;if(d>>>0<=31){o=1;i=g;return o|0}j=0;do{b=c[a+(j<<2)+4>>2]|0;if((b>>1|0)!=(e|0)){c[h>>2]=b;mc(f,h);d=c[a>>2]|0}j=j+1|0}while((j|0)<(d>>>5|0));f=1;i=g;return f|0}function Ic(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;d=i;k=b+924|0;if(!(c[k>>2]|0)){i=d;return}h=b+856|0;e=b+872|0;f=b+868|0;j=b+860|0;g=b+544|0;l=0;while(1){w=c[e>>2]|0;m=c[f>>2]|0;n=w-m|0;if((w|0)<(m|0))n=(c[j>>2]|0)+n|0;if((l|0)>=(n|0))break;n=(c[g>>2]|0)+(c[(c[h>>2]|0)+(((m+l|0)%(c[j>>2]|0)|0)<<2)>>2]<<2)|0;m=c[n>>2]|0;if(!(m&3))c[n>>2]=m&-4|2;l=l+1|0}l=b+540|0;q=c[l>>2]|0;if((q|0)>0){n=b+744|0;o=b+776|0;m=b+760|0;b=b+804|0;p=0;do{if(a[(c[n>>2]|0)+p>>0]|0){r=(c[o>>2]|0)+p|0;if(a[r>>0]|0){s=c[m>>2]|0;q=s+(p*12|0)+4|0;u=c[q>>2]|0;if((u|0)>0){s=c[s+(p*12|0)>>2]|0;v=0;t=0;do{w=c[s+(v<<2)>>2]|0;if((c[(c[c[b>>2]>>2]|0)+(w<<2)>>2]&3|0)!=1){c[s+(t<<2)>>2]=w;u=c[q>>2]|0;t=t+1|0}v=v+1|0}while((v|0)<(u|0))}else{v=0;t=0}s=v-t|0;if((s|0)>0)c[q>>2]=u-s;a[r>>0]=0}r=c[m>>2]|0;q=r+(p*12|0)+4|0;t=c[q>>2]|0;if((t|0)>0){r=r+(p*12|0)|0;s=0;do{u=c[(c[r>>2]|0)+(s<<2)>>2]|0;if(!(c[(c[g>>2]|0)+(u<<2)>>2]&3)){Zc(h,u);t=(c[g>>2]|0)+(c[(c[r>>2]|0)+(s<<2)>>2]<<2)|0;c[t>>2]=c[t>>2]&-4|2;t=c[q>>2]|0}s=s+1|0}while((s|0)<(t|0))}a[(c[n>>2]|0)+p>>0]=0;q=c[l>>2]|0}p=p+1|0}while((p|0)<(q|0));l=0}else l=0;while(1){w=c[e>>2]|0;m=c[f>>2]|0;n=w-m|0;if((w|0)<(m|0))n=(c[j>>2]|0)+n|0;if((l|0)>=(n|0))break;m=(c[g>>2]|0)+(c[(c[h>>2]|0)+(((m+l|0)%(c[j>>2]|0)|0)<<2)>>2]<<2)|0;n=c[m>>2]|0;if((n&3|0)==2)c[m>>2]=n&-4;l=l+1|0}c[k>>2]=0;i=d;return}function Jc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0;e=i;i=i+16|0;m=e;x=e+12|0;g=b+856|0;l=b+872|0;q=b+868|0;j=b+860|0;u=b+680|0;f=b+920|0;h=b+284|0;t=b+280|0;r=b+544|0;s=b+928|0;o=b+44|0;n=b+776|0;v=b+692|0;p=b+804|0;k=b+760|0;C=0;F=0;D=0;a:while(1){E=c[q>>2]|0;do{A=c[l>>2]|0;B=(A|0)<(E|0);A=A-E|0;if(B)G=(c[j>>2]|0)+A|0;else G=A;if((G|0)<=0?(c[f>>2]|0)>=(c[h>>2]|0):0){f=1;j=53;break a}if(a[u>>0]|0){j=8;break a}if(B)A=(c[j>>2]|0)+A|0;if((A|0)==0?(z=c[f>>2]|0,(z|0)<(c[h>>2]|0)):0){c[f>>2]=z+1;c[(c[r>>2]|0)+((c[s>>2]|0)+1<<2)>>2]=c[(c[t>>2]|0)+(z<<2)>>2];A=(c[r>>2]|0)+(c[s>>2]<<2)|0;B=(c[A>>2]|0)>>>5;if(!B){B=0;G=0}else{G=0;E=0;do{G=1<<((c[A+(E<<2)+4>>2]|0)>>>1&31)|G;E=E+1|0}while((E|0)<(B|0))}c[A+(B<<2)+4>>2]=G;Zc(g,c[s>>2]|0);E=c[q>>2]|0}A=c[(c[g>>2]|0)+(E<<2)>>2]|0;E=E+1|0;J=c[j>>2]|0;E=(E|0)==(J|0)?0:E;c[q>>2]=E;G=c[r>>2]|0;B=G+(A<<2)|0;I=c[B>>2]|0}while((I&3|0)!=0);if(d?(c[o>>2]|0)>1:0){H=C+1|0;if(!((C|0)%1e3|0)){I=c[l>>2]|0;c[m>>2]=I-E+((I|0)<(E|0)?J:0);c[m+4>>2]=D;c[m+8>>2]=F;La(3440,m|0)|0;I=c[B>>2]|0;C=H}else C=H}E=G+(A+1<<2)|0;G=c[E>>2]>>1;if(I>>>0>63){H=c[k>>2]|0;I=I>>>5;J=1;do{P=c[B+(J<<2)+4>>2]>>1;G=(c[H+(P*12|0)+4>>2]|0)<(c[H+(G*12|0)+4>>2]|0)?P:G;J=J+1|0}while((J|0)<(I|0))}I=(c[n>>2]|0)+G|0;if(a[I>>0]|0){J=c[k>>2]|0;H=J+(G*12|0)+4|0;M=c[H>>2]|0;if((M|0)>0){J=c[J+(G*12|0)>>2]|0;L=0;K=0;do{N=c[J+(L<<2)>>2]|0;if((c[(c[c[p>>2]>>2]|0)+(N<<2)>>2]&3|0)!=1){c[J+(K<<2)>>2]=N;M=c[H>>2]|0;K=K+1|0}L=L+1|0}while((L|0)<(M|0))}else{L=0;K=0}J=L-K|0;if((J|0)>0)c[H>>2]=M-J;a[I>>0]=0}I=c[k>>2]|0;H=c[I+(G*12|0)>>2]|0;I=I+(G*12|0)+4|0;if((c[I>>2]|0)>0)J=0;else continue;while(1){N=c[B>>2]|0;if(N&3)continue a;K=c[H+(J<<2)>>2]|0;L=c[r>>2]|0;O=L+(K<<2)|0;M=c[O>>2]|0;b:do if(((!((M&3|0)!=0|(K|0)==(A|0))?(P=c[v>>2]|0,y=M>>>5,(P|0)==-1|(y|0)<(P|0)):0)?(w=N>>>5,y>>>0>=w>>>0):0)?(c[B+(w<<2)+4>>2]&~c[O+(y<<2)+4>>2]|0)==0:0){L=L+(K+1<<2)|0;do if(N>>>0>31){if(M>>>0>31){O=-2;M=0}else break b;while(1){N=c[E+(M<<2)>>2]|0;c:do if((O|0)==-2){P=0;while(1){O=c[L+(P<<2)>>2]|0;if((N|0)==(O|0)){N=-2;break c}P=P+1|0;if((N|0)==(O^1|0))break c;if(P>>>0>=y>>>0)break b}}else{P=0;while(1){if((N|0)==(c[L+(P<<2)>>2]|0)){N=O;break c}P=P+1|0;if(P>>>0>=y>>>0)break b}}while(0);M=M+1|0;if(M>>>0>=w>>>0)break;else O=N}if((N|0)==-2)break;else if((N|0)==-1)break b;c[x>>2]=N^1;c[m+0>>2]=c[x+0>>2];if(!(Gc(b,K,m)|0)){f=0;j=53;break a}F=F+1|0;J=(((N>>1|0)==(G|0))<<31>>31)+J|0;break b}while(0);Fc(b,K);D=D+1|0}while(0);J=J+1|0;if((J|0)>=(c[I>>2]|0))continue a}}if((j|0)==8){Yc(g,0);c[f>>2]=c[h>>2];P=1;i=e;return P|0}else if((j|0)==53){i=e;return f|0}return 0}function Kc(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;h=i;i=i+16|0;g=h+12|0;m=h+8|0;k=h+4|0;j=h;l=(c[b+544>>2]|0)+(f<<2)|0;if(c[l>>2]&3){r=1;i=h;return r|0}if(Qb(b,l)|0){r=1;i=h;return r|0}c[m>>2]=c[b+284>>2];nc(b+292|0,m);p=c[l>>2]|0;if(p>>>0>31){m=b+332|0;n=0;o=-2;do{q=c[l+(n<<2)+4>>2]|0;r=q>>1;if((r|0)!=(e|0)?(r=(d[(c[m>>2]|0)+r>>0]|0)^q&1,t=a[2616]|0,s=t&255,((r&255)<<24>>24==t<<24>>24&(s>>>1^1)|s&2&r|0)==0):0){c[k>>2]=q^1;c[g+0>>2]=c[k+0>>2];Lb(b,g,-1);p=c[l>>2]|0}else o=q;n=n+1|0}while((n|0)<(p>>>5|0))}else o=-2;t=(Mb(b)|0)==-1;Rb(b,0);if(!t){t=b+712|0;c[t>>2]=(c[t>>2]|0)+1;c[j>>2]=o;c[g+0>>2]=c[j+0>>2];if(!(Gc(b,f,g)|0)){t=0;i=h;return t|0}}t=1;i=h;return t|0}function Lc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;h=(c[b+776>>2]|0)+d|0;f=b+760|0;if(a[h>>0]|0){k=c[f>>2]|0;g=k+(d*12|0)+4|0;n=c[g>>2]|0;if((n|0)>0){j=b+804|0;k=c[k+(d*12|0)>>2]|0;m=0;l=0;do{o=c[k+(m<<2)>>2]|0;if((c[(c[c[j>>2]>>2]|0)+(o<<2)>>2]&3|0)!=1){c[k+(l<<2)>>2]=o;n=c[g>>2]|0;l=l+1|0}m=m+1|0}while((m|0)<(n|0))}else{m=0;l=0}j=m-l|0;if((j|0)>0)c[g>>2]=n-j;a[h>>0]=0}g=c[f>>2]|0;n=a[(c[b+332>>2]|0)+d>>0]|0;m=a[2624]|0;o=m&255;if(!((o>>>1^1)&n<<24>>24==m<<24>>24|n&2&o)){o=1;i=e;return o|0}f=g+(d*12|0)+4|0;h=c[f>>2]|0;if(!h){o=1;i=e;return o|0}a:do if((h|0)>0){g=g+(d*12|0)|0;h=0;while(1){if(!(Kc(b,d,c[(c[g>>2]|0)+(h<<2)>>2]|0)|0)){b=0;break}h=h+1|0;if((h|0)>=(c[f>>2]|0))break a}i=e;return b|0}while(0);o=Jc(b,0)|0;i=e;return o|0}function Mc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0;e=i;i=i+48|0;s=e+36|0;r=e+32|0;t=e+28|0;u=e+24|0;f=e+12|0;g=e;n=(c[b+776>>2]|0)+d|0;m=b+760|0;if(a[n>>0]|0){q=c[m>>2]|0;o=q+(d*12|0)+4|0;y=c[o>>2]|0;if((y|0)>0){p=b+804|0;q=c[q+(d*12|0)>>2]|0;w=0;v=0;do{z=c[q+(w<<2)>>2]|0;if((c[(c[c[p>>2]>>2]|0)+(z<<2)>>2]&3|0)!=1){c[q+(v<<2)>>2]=z;y=c[o>>2]|0;v=v+1|0}w=w+1|0}while((w|0)<(y|0))}else{w=0;v=0}p=w-v|0;if((p|0)>0)c[o>>2]=y-p;a[n>>0]=0}v=c[m>>2]|0;w=v+(d*12|0)|0;c[f>>2]=0;n=f+4|0;c[n>>2]=0;o=f+8|0;c[o>>2]=0;c[g>>2]=0;q=g+4|0;c[q>>2]=0;p=g+8|0;c[p>>2]=0;v=v+(d*12|0)+4|0;a:do if((c[v>>2]|0)>0){y=b+544|0;B=d<<1;A=0;do{C=(c[w>>2]|0)+(A<<2)|0;E=(c[y>>2]|0)+(c[C>>2]<<2)|0;Z=c[E>>2]|0;z=Z>>>5;b:do if(Z>>>0>31){G=0;while(1){D=G+1|0;if((c[E+(G<<2)+4>>2]|0)==(B|0)){D=G;break b}if((D|0)<(z|0))G=D;else break}}else D=0;while(0);_c((D|0)<(z|0)?f:g,C);A=A+1|0;z=c[v>>2]|0}while((A|0)<(z|0));y=c[n>>2]|0;B=(y|0)>0;if(B){C=c[q>>2]|0;K=(C|0)>0;J=b+544|0;D=c[f>>2]|0;A=c[g>>2]|0;E=b+708|0;I=b+684|0;H=b+688|0;P=0;G=0;while(1){if(K){M=D+(G<<2)|0;L=c[J>>2]|0;N=c[E>>2]|0;O=0;do{S=L+(c[M>>2]<<2)|0;U=L+(c[A+(O<<2)>>2]<<2)|0;N=N+1|0;c[E>>2]=N;Q=(c[S>>2]|0)>>>5>>>0<(c[U>>2]|0)>>>5>>>0;R=Q?U:S;U=Q?S:U;S=R+4|0;Q=U+4|0;R=c[R>>2]|0;T=R>>>5;W=T+ -1|0;U=c[U>>2]|0;c:do if(U>>>0>31){V=0;while(1){Z=c[Q+(V<<2)>>2]|0;d:do if((Z>>1|0)!=(d|0)){e:do if(R>>>0>31){Y=0;while(1){X=c[S+(Y<<2)>>2]|0;Y=Y+1|0;if((X^Z)>>>0<2)break;if((Y|0)>=(T|0))break e}if((X|0)==(Z^1|0))break c;else break d}while(0);W=W+1|0}while(0);V=V+1|0;if((V|0)>=(U>>>5|0)){x=28;break}}}else x=28;while(0);if((x|0)==28){x=0;if((P|0)>=((c[I>>2]|0)+z|0)){b=1;break a}Z=c[H>>2]|0;if((Z|0)!=-1&(W|0)>(Z|0)){b=1;break a}else P=P+1|0}O=O+1|0}while((O|0)<(C|0))}G=G+1|0;if((G|0)>=(y|0)){x=32;break}}}else{B=0;x=32}}else{y=0;B=0;x=32}while(0);f:do if((x|0)==32){a[(c[b+904>>2]|0)+d>>0]=1;z=b+380|0;A=(c[z>>2]|0)+d|0;if(a[A>>0]|0){Z=b+200|0;Y=Z;Y=ne(c[Y>>2]|0,c[Y+4>>2]|0,-1,-1)|0;c[Z>>2]=Y;c[Z+4>>2]=F}a[A>>0]=0;A=b+460|0;if(!((c[b+476>>2]|0)>(d|0)?(c[(c[b+472>>2]|0)+(d<<2)>>2]|0)>-1:0))x=36;if((x|0)==36?(a[(c[z>>2]|0)+d>>0]|0)!=0:0)lc(A,d);x=b+716|0;c[x>>2]=(c[x>>2]|0)+1;x=c[q>>2]|0;if((y|0)>(x|0)){A=b+732|0;if((x|0)>0){u=b+544|0;t=c[g>>2]|0;E=b+736|0;D=0;do{C=(c[u>>2]|0)+(c[t+(D<<2)>>2]<<2)|0;z=c[E>>2]|0;if((c[C>>2]|0)>>>0>31){G=0;H=-1;do{Z=C+(G<<2)+4|0;c[s>>2]=c[Z>>2];_c(A,s);H=(c[Z>>2]>>1|0)==(d|0)?G+z|0:H;G=G+1|0}while((G|0)<((c[C>>2]|0)>>>5|0))}else H=-1;Z=c[A>>2]|0;X=Z+(H<<2)|0;Y=c[X>>2]|0;Z=Z+(z<<2)|0;c[X>>2]=c[Z>>2];c[Z>>2]=Y;c[r>>2]=(c[C>>2]|0)>>>5;_c(A,r);D=D+1|0}while((D|0)<(x|0))}c[s>>2]=d<<1;_c(A,s);c[r>>2]=1;_c(A,r)}else{D=b+732|0;if(B){G=b+544|0;E=c[f>>2]|0;z=b+736|0;H=0;do{C=(c[G>>2]|0)+(c[E+(H<<2)>>2]<<2)|0;A=c[z>>2]|0;if((c[C>>2]|0)>>>0>31){I=0;J=-1;do{Z=C+(I<<2)+4|0;c[s>>2]=c[Z>>2];_c(D,s);J=(c[Z>>2]>>1|0)==(d|0)?I+A|0:J;I=I+1|0}while((I|0)<((c[C>>2]|0)>>>5|0))}else J=-1;Z=c[D>>2]|0;X=Z+(J<<2)|0;Y=c[X>>2]|0;Z=Z+(A<<2)|0;c[X>>2]=c[Z>>2];c[Z>>2]=Y;c[r>>2]=(c[C>>2]|0)>>>5;_c(D,r);H=H+1|0}while((H|0)<(y|0))}c[t>>2]=d<<1|1;_c(D,t);c[u>>2]=1;_c(D,u)}if((c[v>>2]|0)>0){r=0;do{Fc(b,c[(c[w>>2]|0)+(r<<2)>>2]|0);r=r+1|0}while((r|0)<(c[v>>2]|0))}r=b+628|0;g:do if(B){s=b+544|0;w=c[f>>2]|0;A=c[g>>2]|0;if((x|0)>0)v=0;else{r=0;while(1){r=r+1|0;if((r|0)>=(y|0))break g}}do{u=w+(v<<2)|0;t=0;do{Z=c[s>>2]|0;if(Hc(b,Z+(c[u>>2]<<2)|0,Z+(c[A+(t<<2)>>2]<<2)|0,d,r)|0?!(Dc(b,r)|0):0){b=0;break f}t=t+1|0}while((t|0)<(x|0));v=v+1|0}while((v|0)<(y|0))}while(0);r=c[m>>2]|0;m=r+(d*12|0)|0;s=c[m>>2]|0;if(s){c[r+(d*12|0)+4>>2]=0;Td(s);c[m>>2]=0;c[r+(d*12|0)+8>>2]=0}m=b+412|0;d=d<<1;s=c[m>>2]|0;r=s+(d*12|0)+4|0;if((c[r>>2]|0)==0?(l=s+(d*12|0)|0,k=c[l>>2]|0,(k|0)!=0):0){c[r>>2]=0;Td(k);c[l>>2]=0;c[s+(d*12|0)+8>>2]=0;s=c[m>>2]|0}k=d|1;l=s+(k*12|0)+4|0;if((c[l>>2]|0)==0?(j=s+(k*12|0)|0,h=c[j>>2]|0,(h|0)!=0):0){c[l>>2]=0;Td(h);c[j>>2]=0;c[s+(k*12|0)+8>>2]=0}b=Jc(b,0)|0;A=c[g>>2]|0}while(0);if(A){c[q>>2]=0;Td(A);c[g>>2]=0;c[p>>2]=0}g=c[f>>2]|0;if(!g){i=e;return b|0}c[n>>2]=0;Td(g);c[f>>2]=0;c[o>>2]=0;i=e;return b|0}function Nc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;e=i;if(!(a[b+724>>0]|0)){i=e;return}l=b+540|0;if((c[l>>2]|0)>0){j=b+760|0;f=b+804|0;g=b+776|0;k=b+544|0;h=0;do{n=c[j>>2]|0;m=n+(h*12|0)+4|0;p=c[m>>2]|0;if((p|0)>0){n=c[n+(h*12|0)>>2]|0;q=0;o=0;do{r=c[n+(q<<2)>>2]|0;if((c[(c[c[f>>2]>>2]|0)+(r<<2)>>2]&3|0)!=1){c[n+(o<<2)>>2]=r;p=c[m>>2]|0;o=o+1|0}q=q+1|0}while((q|0)<(p|0))}else{q=0;o=0}n=q-o|0;if((n|0)>0)c[m>>2]=p-n;a[(c[g>>2]|0)+h>>0]=0;n=c[j>>2]|0;m=n+(h*12|0)+4|0;if((c[m>>2]|0)>0){r=n+(h*12|0)|0;p=0;do{n=(c[r>>2]|0)+(p<<2)|0;o=c[n>>2]|0;q=c[k>>2]|0;s=q+(o<<2)|0;if(!(c[s>>2]&16)){t=wc(d,s)|0;c[n>>2]=t;c[s>>2]=c[s>>2]|16;c[q+(o+1<<2)>>2]=t}else c[n>>2]=c[q+(o+1<<2)>>2];p=p+1|0}while((p|0)<(c[m>>2]|0))}h=h+1|0}while((h|0)<(c[l>>2]|0))}f=b+856|0;t=c[b+872>>2]|0;g=b+868|0;m=c[g>>2]|0;k=t-m|0;if((t|0)<(m|0))k=(c[b+860>>2]|0)+k|0;a:do if((k|0)>0){h=b+860|0;j=b+544|0;while(1){l=c[(c[f>>2]|0)+(m<<2)>>2]|0;n=m+1|0;c[g>>2]=(n|0)==(c[h>>2]|0)?0:n;n=c[j>>2]|0;o=n+(l<<2)|0;m=c[o>>2]|0;if(!(m&3)){if(!(m&16)){t=wc(d,o)|0;c[o>>2]=c[o>>2]|16;c[n+(l+1<<2)>>2]=t;l=t}else l=c[n+(l+1<<2)>>2]|0;Zc(f,l)}k=k+ -1|0;if((k|0)<=0)break a;m=c[g>>2]|0}}else j=b+544|0;while(0);b=b+928|0;f=c[b>>2]|0;h=c[j>>2]|0;g=h+(f<<2)|0;if(!(c[g>>2]&16)){t=wc(d,g)|0;c[b>>2]=t;c[g>>2]=c[g>>2]|16;c[h+(f+1<<2)>>2]=t;i=e;return}else{c[b>>2]=c[h+(f+1<<2)>>2];i=e;return}}function Oc(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;h=i;i=i+32|0;l=h;d=h+8|0;e=b+544|0;f=b+548|0;g=b+556|0;j=(c[f>>2]|0)-(c[g>>2]|0)|0;c[d+0>>2]=0;c[d+4>>2]=0;c[d+8>>2]=0;c[d+12>>2]=0;gc(d,j);j=d+16|0;k=b+560|0;a[j>>0]=a[k>>0]|0;Nc(b,d);ac(b,d);if((c[b+44>>2]|0)>1){m=c[d+4>>2]<<2;c[l>>2]=c[f>>2]<<2;c[l+4>>2]=m;La(3608,l|0)|0}a[k>>0]=a[j>>0]|0;j=c[e>>2]|0;if(j)Td(j);c[e>>2]=c[d>>2];c[f>>2]=c[d+4>>2];c[b+552>>2]=c[d+8>>2];c[g>>2]=c[d+12>>2];i=h;return}function Pc(){var d=0,e=0,f=0;d=i;i=i+16|0;e=d;a[2608]=0;a[2616]=1;a[2624]=2;xb(2632,2656,2664,3744,3752);c[658]=160;a[2652]=0;xb(2704,2728,2736,3744,3752);c[676]=160;a[2724]=0;xb(2784,2808,2816,3744,3752);c[696]=160;a[2804]=1;xb(2848,2880,2888,3744,3736);c[712]=280;f=2868|0;c[f>>2]=-2147483648;c[f+4>>2]=2147483647;c[719]=0;xb(2960,2992,3e3,3744,3736);c[740]=280;f=2980|0;c[f>>2]=-1;c[f+4>>2]=2147483647;c[747]=20;xb(3112,3144,3152,3744,3736);c[778]=280;f=3132|0;c[f>>2]=-1;c[f+4>>2]=2147483647;c[785]=1e3;xb(3240,3296,3312,3744,3720);c[810]=2168;h[408]=0.0;h[409]=v;a[3280]=0;a[3281]=0;b[1641]=b[e+0>>1]|0;b[1642]=b[e+2>>1]|0;b[1643]=b[e+4>>1]|0;h[411]=.5;i=d;return}function Qc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;c[a>>2]=0;e=a+4|0;c[e>>2]=0;f=a+8|0;c[f>>2]=0;if((b|0)<=0){i=d;return}g=b+1&-2;g=(g|0)>2?g:2;c[f>>2]=g;f=Ud(0,g<<2)|0;c[a>>2]=f;if((f|0)==0?(c[(Oa()|0)>>2]|0)==12:0)Ta(va(1)|0,48,0);a=c[e>>2]|0;if((a|0)<(b|0))do{g=f+(a<<2)|0;if(g)c[g>>2]=0;a=a+1|0}while((a|0)!=(b|0));c[e>>2]=b;i=d;return}function Rc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0;b=i;e=a+32|0;d=c[e>>2]|0;if(d){c[a+36>>2]=0;Td(d);c[e>>2]=0;c[a+40>>2]=0}e=a+16|0;d=c[e>>2]|0;if(d){c[a+20>>2]=0;Td(d);c[e>>2]=0;c[a+24>>2]=0}e=c[a>>2]|0;if(!e){i=b;return}d=a+4|0;g=c[d>>2]|0;if((g|0)>0){f=0;do{j=e+(f*12|0)|0;h=c[j>>2]|0;if(h){c[e+(f*12|0)+4>>2]=0;Td(h);c[j>>2]=0;c[e+(f*12|0)+8>>2]=0;e=c[a>>2]|0;g=c[d>>2]|0}f=f+1|0}while((f|0)<(g|0))}c[d>>2]=0;Td(e);c[a>>2]=0;c[a+8>>2]=0;i=b;return}function Sc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;b=c[b>>2]|0;g=b+1|0;f=a+4|0;if((c[f>>2]|0)>=(g|0)){k=c[a>>2]|0;k=k+(b<<2)|0;c[k>>2]=d;i=e;return}h=a+8|0;k=c[h>>2]|0;if((k|0)<(g|0)){l=b+2-k&-2;j=(k>>1)+2&-2;j=(l|0)>(j|0)?l:j;if((j|0)>(2147483647-k|0)){l=va(1)|0;Ta(l|0,48,0)}m=c[a>>2]|0;l=j+k|0;c[h>>2]=l;l=Ud(m,l<<2)|0;c[a>>2]=l;if((l|0)==0?(c[(Oa()|0)>>2]|0)==12:0){m=va(1)|0;Ta(m|0,48,0)}}k=c[f>>2]|0;if((k|0)<(g|0)){h=c[a>>2]|0;do{j=h+(k<<2)|0;if(j)c[j>>2]=0;k=k+1|0}while((k|0)!=(g|0))}c[f>>2]=g;m=c[a>>2]|0;m=m+(b<<2)|0;c[m>>2]=d;i=e;return}function Tc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;k=c[d>>2]|0;g=k+1|0;f=b+4|0;if((c[f>>2]|0)<(g|0)){j=b+8|0;h=c[j>>2]|0;if((h|0)<(g|0)){l=k+2-h&-2;k=(h>>1)+2&-2;k=(l|0)>(k|0)?l:k;if((k|0)>(2147483647-h|0)){l=va(1)|0;Ta(l|0,48,0)}m=c[b>>2]|0;l=k+h|0;c[j>>2]=l;l=Ud(m,l*12|0)|0;c[b>>2]=l;if((l|0)==0?(c[(Oa()|0)>>2]|0)==12:0){m=va(1)|0;Ta(m|0,48,0)}}j=c[f>>2]|0;if((j|0)<(g|0)){h=c[b>>2]|0;do{k=h+(j*12|0)|0;if(k){c[k>>2]=0;c[h+(j*12|0)+4>>2]=0;c[h+(j*12|0)+8>>2]=0}j=j+1|0}while((j|0)!=(g|0))}c[f>>2]=g;h=c[d>>2]|0}else h=k;f=c[b>>2]|0;if(c[f+(h*12|0)>>2]|0){c[f+(h*12|0)+4>>2]=0;h=c[d>>2]|0}d=b+16|0;f=h+1|0;g=b+20|0;if((c[g>>2]|0)>=(f|0)){i=e;return}j=b+24|0;b=c[j>>2]|0;if((b|0)<(f|0)){m=h+2-b&-2;h=(b>>1)+2&-2;h=(m|0)>(h|0)?m:h;if((h|0)>(2147483647-b|0)){m=va(1)|0;Ta(m|0,48,0)}l=c[d>>2]|0;m=h+b|0;c[j>>2]=m;m=Ud(l,m)|0;c[d>>2]=m;if((m|0)==0?(c[(Oa()|0)>>2]|0)==12:0){m=va(1)|0;Ta(m|0,48,0)}}b=c[g>>2]|0;if((b|0)<(f|0))do{a[(c[d>>2]|0)+b>>0]=0;b=b+1|0}while((b|0)!=(f|0));c[g>>2]=f;i=e;return}function Uc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;d=i;i=i+16|0;g=d;c[g>>2]=b;f=a+12|0;e=b+1|0;h=a+16|0;if((c[h>>2]|0)<(e|0)){k=a+20|0;j=c[k>>2]|0;if((j|0)<(e|0)){m=b+2-j&-2;l=(j>>1)+2&-2;l=(m|0)>(l|0)?m:l;if((l|0)>(2147483647-j|0)){m=va(1)|0;Ta(m|0,48,0)}n=c[f>>2]|0;m=l+j|0;c[k>>2]=m;m=Ud(n,m<<2)|0;c[f>>2]=m;if((m|0)==0?(c[(Oa()|0)>>2]|0)==12:0){n=va(1)|0;Ta(n|0,48,0)}}j=c[h>>2]|0;if((e|0)>(j|0))ke((c[f>>2]|0)+(j<<2)|0,-1,e-j<<2|0)|0;c[h>>2]=e}c[(c[f>>2]|0)+(b<<2)>>2]=c[a+4>>2];nc(a,g);e=c[f>>2]|0;j=c[e+(b<<2)>>2]|0;b=c[a>>2]|0;f=c[b+(j<<2)>>2]|0;if(!j){m=0;n=b+(m<<2)|0;c[n>>2]=f;n=e+(f<<2)|0;c[n>>2]=m;i=d;return}a=a+28|0;g=f<<1;h=g|1;while(1){m=j;j=j+ -1>>1;l=b+(j<<2)|0;k=c[l>>2]|0;r=c[c[a>>2]>>2]|0;o=c[r+(g<<2)>>2]|0;q=c[r+(h<<2)>>2]|0;o=we(q|0,((q|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;q=F;p=k<<1;n=c[r+(p<<2)>>2]|0;p=c[r+((p|1)<<2)>>2]|0;n=we(p|0,((p|0)<0)<<31>>31|0,n|0,((n|0)<0)<<31>>31|0)|0;p=F;if(!(q>>>0<p>>>0|(q|0)==(p|0)&o>>>0<n>>>0)){a=14;break}c[b+(m<<2)>>2]=k;c[e+(c[l>>2]<<2)>>2]=m;if(!j){m=0;a=14;break}}if((a|0)==14){r=b+(m<<2)|0;c[r>>2]=f;r=e+(f<<2)|0;c[r>>2]=m;i=d;return}}function Vc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;e=i;h=b+824|0;l=(c[b+840>>2]|0)>(d|0);if(l?(c[(c[b+836>>2]|0)+(d<<2)>>2]|0)>-1:0)j=7;else j=3;do if((j|0)==3){if(a[(c[b+876>>2]|0)+d>>0]|0){i=e;return}if(a[(c[b+904>>2]|0)+d>>0]|0){i=e;return}o=a[(c[b+332>>2]|0)+d>>0]|0;n=a[2624]|0;p=n&255;if((p>>>1^1)&o<<24>>24==n<<24>>24|o&2&p)if(l){j=7;break}else break;else{i=e;return}}while(0);if((j|0)==7?(f=c[b+836>>2]|0,g=f+(d<<2)|0,k=c[g>>2]|0,(k|0)>-1):0){d=c[h>>2]|0;j=c[d+(k<<2)>>2]|0;a:do if(!k)o=0;else{l=b+852|0;m=j<<1;b=m|1;while(1){o=k;k=k+ -1>>1;p=d+(k<<2)|0;n=c[p>>2]|0;u=c[c[l>>2]>>2]|0;r=c[u+(m<<2)>>2]|0;t=c[u+(b<<2)>>2]|0;r=we(t|0,((t|0)<0)<<31>>31|0,r|0,((r|0)<0)<<31>>31|0)|0;t=F;s=n<<1;q=c[u+(s<<2)>>2]|0;s=c[u+((s|1)<<2)>>2]|0;q=we(s|0,((s|0)<0)<<31>>31|0,q|0,((q|0)<0)<<31>>31|0)|0;s=F;if(!(t>>>0<s>>>0|(t|0)==(s|0)&r>>>0<q>>>0))break a;c[d+(o<<2)>>2]=n;c[f+(c[p>>2]<<2)>>2]=o;if(!k){o=0;break}}}while(0);c[d+(o<<2)>>2]=j;c[f+(j<<2)>>2]=o;Wc(h,c[g>>2]|0);i=e;return}Uc(h,d);i=e;return}function Wc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;d=i;e=c[a>>2]|0;f=c[e+(b<<2)>>2]|0;m=b<<1|1;l=a+4|0;o=c[l>>2]|0;if((m|0)>=(o|0)){p=b;q=a+12|0;o=e+(p<<2)|0;c[o>>2]=f;q=c[q>>2]|0;q=q+(f<<2)|0;c[q>>2]=p;i=d;return}h=a+28|0;k=f<<1;j=k|1;a=a+12|0;while(1){n=(b<<1)+2|0;if((n|0)<(o|0)){p=c[e+(n<<2)>>2]|0;q=c[e+(m<<2)>>2]|0;u=p<<1;o=c[c[h>>2]>>2]|0;s=c[o+(u<<2)>>2]|0;u=c[o+((u|1)<<2)>>2]|0;s=we(u|0,((u|0)<0)<<31>>31|0,s|0,((s|0)<0)<<31>>31|0)|0;u=F;t=q<<1;r=c[o+(t<<2)>>2]|0;t=c[o+((t|1)<<2)>>2]|0;r=we(t|0,((t|0)<0)<<31>>31|0,r|0,((r|0)<0)<<31>>31|0)|0;t=F;if(!(u>>>0<t>>>0|(u|0)==(t|0)&s>>>0<r>>>0)){p=q;g=7}}else{p=c[e+(m<<2)>>2]|0;o=c[c[h>>2]>>2]|0;g=7}if((g|0)==7){g=0;n=m}r=p<<1;t=c[o+(r<<2)>>2]|0;r=c[o+((r|1)<<2)>>2]|0;t=we(r|0,((r|0)<0)<<31>>31|0,t|0,((t|0)<0)<<31>>31|0)|0;r=F;u=c[o+(k<<2)>>2]|0;s=c[o+(j<<2)>>2]|0;u=we(s|0,((s|0)<0)<<31>>31|0,u|0,((u|0)<0)<<31>>31|0)|0;s=F;if(!(r>>>0<s>>>0|(r|0)==(s|0)&t>>>0<u>>>0)){g=10;break}c[e+(b<<2)>>2]=p;c[(c[a>>2]|0)+(p<<2)>>2]=b;m=n<<1|1;o=c[l>>2]|0;if((m|0)>=(o|0)){b=n;g=10;break}else b=n}if((g|0)==10){u=e+(b<<2)|0;c[u>>2]=f;u=c[a>>2]|0;u=u+(f<<2)|0;c[u>>2]=b;i=d;return}}function Xc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0;d=i;h=c[a>>2]|0;if(h){e=a+4|0;f=c[e>>2]|0;a:do if((f|0)>0){g=0;while(1){j=h+(g*12|0)|0;k=c[j>>2]|0;if(k){c[h+(g*12|0)+4>>2]=0;Td(k);c[j>>2]=0;c[h+(g*12|0)+8>>2]=0;f=c[e>>2]|0}g=g+1|0;if((g|0)>=(f|0))break a;h=c[a>>2]|0}}while(0);c[e>>2]=0;if(b){Td(c[a>>2]|0);c[a>>2]=0;c[a+8>>2]=0}}e=a+16|0;f=c[e>>2]|0;if((f|0)!=0?(c[a+20>>2]=0,b):0){Td(f);c[e>>2]=0;c[a+24>>2]=0}f=a+32|0;e=c[f>>2]|0;if(!e){i=d;return}c[a+36>>2]=0;if(!b){i=d;return}Td(e);c[f>>2]=0;c[a+40>>2]=0;i=d;return}function Yc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;e=i;f=c[a>>2]|0;d=a+4|0;if(f){c[d>>2]=0;if(b){Td(f);c[a>>2]=0;c[a+8>>2]=0;f=0}}else f=0;if((c[d>>2]|0)>=1){h=a+16|0;c[h>>2]=0;h=a+12|0;c[h>>2]=0;i=e;return}h=a+8|0;g=c[h>>2]|0;if((g|0)<1){j=2-g&-2;b=(g>>1)+2&-2;b=(j|0)>(b|0)?j:b;if((b|0)>(2147483647-g|0)){j=va(1)|0;Ta(j|0,48,0)}j=b+g|0;c[h>>2]=j;f=Ud(f,j<<2)|0;c[a>>2]=f;if((f|0)==0?(c[(Oa()|0)>>2]|0)==12:0){j=va(1)|0;Ta(j|0,48,0)}}b=c[d>>2]|0;if((b|0)<1)while(1){g=f+(b<<2)|0;if(g)c[g>>2]=0;if(!b)break;else b=b+1|0}c[d>>2]=1;j=a+16|0;c[j>>2]=0;j=a+12|0;c[j>>2]=0;i=e;return}function Zc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+16|0;d=e;f=a+16|0;j=c[f>>2]|0;c[f>>2]=j+1;c[(c[a>>2]|0)+(j<<2)>>2]=b;j=c[f>>2]|0;b=a+4|0;h=c[b>>2]|0;if((j|0)==(h|0)){c[f>>2]=0;j=0}g=a+12|0;if((c[g>>2]|0)!=(j|0)){i=e;return}Qc(d,(h*3|0)+1>>1);l=c[g>>2]|0;m=c[b>>2]|0;if((l|0)<(m|0)){j=c[a>>2]|0;k=c[d>>2]|0;m=0;while(1){h=m+1|0;c[k+(m<<2)>>2]=c[j+(l<<2)>>2];l=l+1|0;m=c[b>>2]|0;if((l|0)>=(m|0)){k=h;break}else m=h}}else k=0;h=c[a>>2]|0;if((c[f>>2]|0)>0){j=c[d>>2]|0;l=0;while(1){c[j+(k<<2)>>2]=c[h+(l<<2)>>2];l=l+1|0;if((l|0)>=(c[f>>2]|0))break;else k=k+1|0}m=c[b>>2]|0}c[g>>2]=0;c[f>>2]=m;if(!h)f=a+8|0;else{c[b>>2]=0;Td(h);c[a>>2]=0;f=a+8|0;c[f>>2]=0}c[a>>2]=c[d>>2];l=d+4|0;c[b>>2]=c[l>>2];m=d+8|0;c[f>>2]=c[m>>2];c[d>>2]=0;c[l>>2]=0;c[m>>2]=0;i=e;return}function _c(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;e=a+4|0;f=c[e>>2]|0;g=a+8|0;h=c[g>>2]|0;if((f|0)==(h|0)&(h|0)<(f+1|0)){h=(f>>1)+2&-2;h=(h|0)<2?2:h;if((h|0)>(2147483647-f|0)){h=va(1)|0;Ta(h|0,48,0)}j=c[a>>2]|0;f=h+f|0;c[g>>2]=f;f=Ud(j,f<<2)|0;c[a>>2]=f;if((f|0)==0?(c[(Oa()|0)>>2]|0)==12:0){j=va(1)|0;Ta(j|0,48,0)}}else f=c[a>>2]|0;j=c[e>>2]|0;c[e>>2]=j+1;e=f+(j<<2)|0;if(!e){i=d;return}c[e>>2]=c[b>>2];i=d;return}function $c(){var a=0,b=0;b=i;Ka(3864)|0;a=od(936)|0;xc(a);i=b;return a|0}function ad(a){a=a|0;var b=0;b=i;if(!a){i=b;return}gb[c[(c[a>>2]|0)+4>>2]&31](a);i=b;return}function bd(){var b=0,d=0,e=0;b=i;i=i+16|0;d=b;e=od(936)|0;xc(e);c[964]=e;Cc(e,1)|0;e=c[964]|0;a[d+0>>0]=a[3840]|0;Ac(e,d,1)|0;i=b;return}function cd(b){b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d;if((c[962]|0)>=(b|0)){i=d;return}do{f=c[964]|0;a[e+0>>0]=a[3840]|0;Ac(f,e,1)|0;f=(c[962]|0)+1|0;c[962]=f}while((f|0)<(b|0));i=d;return}function dd(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;g=i;i=i+32|0;h=g+16|0;e=g+4|0;j=g;c[e>>2]=0;f=e+4|0;c[f>>2]=0;d=e+8|0;c[d>>2]=0;k=c[b>>2]|0;if(k)do{l=(k|0)<0?0-k|0:k;if((c[962]|0)<(l|0))do{m=c[964]|0;a[h+0>>0]=a[3840]|0;Ac(m,h,1)|0;m=(c[962]|0)+1|0;c[962]=m}while((m|0)<(l|0));c[j>>2]=l<<1|k>>>31;mc(e,j);b=b+4|0;k=c[b>>2]|0}while((k|0)!=0);j=c[964]|0;h=j+628|0;ld(e,h);h=Dc(j,h)|0;j=c[e>>2]|0;if(!j){i=g;return h|0}c[f>>2]=0;Td(j);c[e>>2]=0;c[d>>2]=0;i=g;return h|0}function ed(){var b=0,d=0,e=0,f=0;d=i;i=i+16|0;b=d;e=c[964]|0;f=e+664|0;c[f+0>>2]=-1;c[f+4>>2]=-1;c[f+8>>2]=-1;c[f+12>>2]=-1;if(c[e+304>>2]|0)c[e+308>>2]=0;Bc(b,e,1,0);i=d;return(a[b>>0]|0)==0|0}function fd(){return(c[(c[964]|0)+4>>2]|0)+1|0}function gd(){return c[962]|0}function hd(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;i=i+32|0;h=d+16|0;f=d+4|0;j=d;c[f>>2]=0;e=f+4|0;c[e>>2]=0;g=f+8|0;c[g>>2]=0;c[j>>2]=b<<1;mc(f,j);b=c[964]|0;j=b+664|0;c[j+0>>2]=-1;c[j+4>>2]=-1;c[j+8>>2]=-1;c[j+12>>2]=-1;ld(f,b+304|0);Bc(h,b,1,0);b=(a[h>>0]|0)==0;h=c[f>>2]|0;if(!h){i=d;return b|0}c[e>>2]=0;Td(h);c[f>>2]=0;c[g>>2]=0;i=d;return b|0}function id(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;e=b;d=c[964]|0;c[e>>2]=a<<1|1;a=d+628|0;if(c[a>>2]|0)c[d+632>>2]=0;mc(a,e);Dc(d,a)|0;i=b;return}function jd(){return c[(c[964]|0)+36>>2]|0}function kd(){return c[(c[964]|0)+32>>2]|0}function ld(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;d=i;h=c[b>>2]|0;e=b+4|0;if(!h)j=c[e>>2]|0;else{c[e>>2]=0;j=0}e=a+4|0;f=c[e>>2]|0;g=b+4|0;if((j|0)<(f|0)){k=b+8|0;j=c[k>>2]|0;if((j|0)<(f|0)){m=f+1-j&-2;l=(j>>1)+2&-2;l=(m|0)>(l|0)?m:l;if((l|0)>(2147483647-j|0)){m=va(1)|0;Ta(m|0,48,0)}m=l+j|0;c[k>>2]=m;h=Ud(h,m<<2)|0;c[b>>2]=h;if((h|0)==0?(c[(Oa()|0)>>2]|0)==12:0){m=va(1)|0;Ta(m|0,48,0)}}j=c[g>>2]|0;a:do if((j|0)<(f|0))while(1){h=h+(j<<2)|0;if(h)c[h>>2]=0;j=j+1|0;if((j|0)==(f|0))break a;h=c[b>>2]|0}while(0);c[g>>2]=f;f=c[e>>2]|0}if((f|0)<=0){i=d;return}b=c[b>>2]|0;a=c[a>>2]|0;f=0;do{c[b+(f<<2)>>2]=c[a+(f<<2)>>2];f=f+1|0}while((f|0)<(c[e>>2]|0));i=d;return}function md(a,b){a=a|0;b=b|0;var d=0;d=i;i=i+16|0;c[d>>2]=b;b=c[p>>2]|0;ua(b|0,a|0,d|0)|0;Sa(10,b|0)|0;Wa()}function nd(){var a=0,b=0;a=i;i=i+16|0;if(!(Ja(4064,3)|0)){b=Ha(c[1014]|0)|0;i=a;return b|0}else md(4072,a);return 0}function od(a){a=a|0;var b=0,d=0;b=i;a=(a|0)==0?1:a;d=Sd(a)|0;if(d){i=b;return d|0}while(1){d=vd()|0;if(!d){a=4;break}jb[d&3]();d=Sd(a)|0;if(d){a=5;break}}if((a|0)==4){d=va(4)|0;c[d>>2]=4248;Ta(d|0,4296,12)}else if((a|0)==5){i=b;return d|0}return 0}function pd(a){a=a|0;var b=0;b=i;Td(a);i=b;return}function qd(a){a=a|0;var b=0;b=i;pd(a);i=b;return}function rd(a){a=a|0;return}function sd(a){a=a|0;return 4264}function td(a){a=a|0;var b=0;b=i;i=i+16|0;jb[a&3]();md(4312,b)}function ud(){var a=0,b=0;b=nd()|0;if(((b|0)!=0?(a=c[b>>2]|0,(a|0)!=0):0)?(b=a+48|0,(c[b>>2]&-256|0)==1126902528?(c[b+4>>2]|0)==1129074247:0):0)td(c[a+12>>2]|0);b=c[968]|0;c[968]=b+0;td(b)}function vd(){var a=0;a=c[1102]|0;c[1102]=a+0;return a|0}function wd(a){a=a|0;return}function xd(a){a=a|0;return}function yd(a){a=a|0;return}function zd(a){a=a|0;return}function Ad(a){a=a|0;return}function Bd(a){a=a|0;var b=0;b=i;pd(a);i=b;return}function Cd(a){a=a|0;var b=0;b=i;pd(a);i=b;return}function Dd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;e=i;i=i+64|0;f=e;if((a|0)==(b|0)){h=1;i=e;return h|0}if(!b){h=0;i=e;return h|0}b=Hd(b,4504,4560,0)|0;if(!b){h=0;i=e;return h|0}h=f+0|0;g=h+56|0;do{c[h>>2]=0;h=h+4|0}while((h|0)<(g|0));c[f>>2]=b;c[f+8>>2]=a;c[f+12>>2]=-1;c[f+48>>2]=1;mb[c[(c[b>>2]|0)+28>>2]&3](b,f,c[d>>2]|0,1);if((c[f+24>>2]|0)!=1){h=0;i=e;return h|0}c[d>>2]=c[f+16>>2];h=1;i=e;return h|0}function Ed(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0;b=i;g=d+16|0;h=c[g>>2]|0;if(!h){c[g>>2]=e;c[d+24>>2]=f;c[d+36>>2]=1;i=b;return}if((h|0)!=(e|0)){h=d+36|0;c[h>>2]=(c[h>>2]|0)+1;c[d+24>>2]=2;a[d+54>>0]=1;i=b;return}e=d+24|0;if((c[e>>2]|0)!=2){i=b;return}c[e>>2]=f;i=b;return}function Fd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;f=i;if((c[b+8>>2]|0)!=(a|0)){i=f;return}Ed(0,b,d,e);i=f;return}function Gd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;f=i;if((a|0)==(c[b+8>>2]|0)){Ed(0,b,d,e);i=f;return}else{a=c[a+8>>2]|0;mb[c[(c[a>>2]|0)+28>>2]&3](a,b,d,e);i=f;return}}function Hd(d,e,f,g){d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;h=i;i=i+64|0;j=h;k=c[d>>2]|0;l=d+(c[k+ -8>>2]|0)|0;k=c[k+ -4>>2]|0;c[j>>2]=f;c[j+4>>2]=d;c[j+8>>2]=e;c[j+12>>2]=g;n=j+16|0;o=j+20|0;e=j+24|0;m=j+28|0;g=j+32|0;d=j+40|0;p=(k|0)==(f|0);q=n+0|0;f=q+36|0;do{c[q>>2]=0;q=q+4|0}while((q|0)<(f|0));b[n+36>>1]=0;a[n+38>>0]=0;if(p){c[j+48>>2]=1;kb[c[(c[k>>2]|0)+20>>2]&3](k,j,l,l,1,0);q=(c[e>>2]|0)==1?l:0;i=h;return q|0}fb[c[(c[k>>2]|0)+24>>2]&3](k,j,l,1,0);j=c[j+36>>2]|0;if(!j){q=(c[d>>2]|0)==1&(c[m>>2]|0)==1&(c[g>>2]|0)==1?c[o>>2]|0:0;i=h;return q|0}else if((j|0)==1){if((c[e>>2]|0)!=1?!((c[d>>2]|0)==0&(c[m>>2]|0)==1&(c[g>>2]|0)==1):0){q=0;i=h;return q|0}q=c[n>>2]|0;i=h;return q|0}else{q=0;i=h;return q|0}return 0}function Id(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0;b=i;a[d+53>>0]=1;if((c[d+4>>2]|0)!=(f|0)){i=b;return}a[d+52>>0]=1;f=d+16|0;h=c[f>>2]|0;if(!h){c[f>>2]=e;c[d+24>>2]=g;c[d+36>>2]=1;if(!((g|0)==1?(c[d+48>>2]|0)==1:0)){i=b;return}a[d+54>>0]=1;i=b;return}if((h|0)!=(e|0)){h=d+36|0;c[h>>2]=(c[h>>2]|0)+1;a[d+54>>0]=1;i=b;return}e=d+24|0;f=c[e>>2]|0;if((f|0)==2)c[e>>2]=g;else g=f;if(!((g|0)==1?(c[d+48>>2]|0)==1:0)){i=b;return}a[d+54>>0]=1;i=b;return}function Jd(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0;h=i;if((b|0)==(c[d+8>>2]|0)){if((c[d+4>>2]|0)!=(e|0)){i=h;return}j=d+28|0;if((c[j>>2]|0)==1){i=h;return}c[j>>2]=f;i=h;return}if((b|0)!=(c[d>>2]|0)){l=c[b+8>>2]|0;fb[c[(c[l>>2]|0)+24>>2]&3](l,d,e,f,g);i=h;return}if((c[d+16>>2]|0)!=(e|0)?(k=d+20|0,(c[k>>2]|0)!=(e|0)):0){c[d+32>>2]=f;f=d+44|0;if((c[f>>2]|0)==4){i=h;return}l=d+52|0;a[l>>0]=0;m=d+53|0;a[m>>0]=0;b=c[b+8>>2]|0;kb[c[(c[b>>2]|0)+20>>2]&3](b,d,e,e,1,g);if(a[m>>0]|0){if(!(a[l>>0]|0)){b=1;j=13}}else{b=0;j=13}do if((j|0)==13){c[k>>2]=e;m=d+40|0;c[m>>2]=(c[m>>2]|0)+1;if((c[d+36>>2]|0)==1?(c[d+24>>2]|0)==2:0){a[d+54>>0]=1;if(b)break}else j=16;if((j|0)==16?b:0)break;c[f>>2]=4;i=h;return}while(0);c[f>>2]=3;i=h;return}if((f|0)!=1){i=h;return}c[d+32>>2]=1;i=h;return}function Kd(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0;g=i;if((c[d+8>>2]|0)==(b|0)){if((c[d+4>>2]|0)!=(e|0)){i=g;return}d=d+28|0;if((c[d>>2]|0)==1){i=g;return}c[d>>2]=f;i=g;return}if((c[d>>2]|0)!=(b|0)){i=g;return}if((c[d+16>>2]|0)!=(e|0)?(h=d+20|0,(c[h>>2]|0)!=(e|0)):0){c[d+32>>2]=f;c[h>>2]=e;b=d+40|0;c[b>>2]=(c[b>>2]|0)+1;if((c[d+36>>2]|0)==1?(c[d+24>>2]|0)==2:0)a[d+54>>0]=1;c[d+44>>2]=4;i=g;return}if((f|0)!=1){i=g;return}c[d+32>>2]=1;i=g;return}function Ld(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0;h=i;if((a|0)==(c[b+8>>2]|0)){Id(0,b,d,e,f);i=h;return}else{a=c[a+8>>2]|0;kb[c[(c[a>>2]|0)+20>>2]&3](a,b,d,e,f,g);i=h;return}}function Md(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;g=i;if((c[b+8>>2]|0)!=(a|0)){i=g;return}Id(0,b,d,e,f);i=g;return}function Nd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=i;i=i+16|0;f=e;c[f>>2]=c[d>>2];a=eb[c[(c[a>>2]|0)+16>>2]&1](a,b,f)|0;b=a&1;if(!a){i=e;return b|0}c[d>>2]=c[f>>2];i=e;return b|0}function Od(a){a=a|0;var b=0;b=i;if(!a)a=0;else a=(Hd(a,4504,4672,0)|0)!=0;i=b;return a&1|0}function Pd(){var a=0,b=0,d=0,e=0,f=0;a=i;i=i+16|0;b=a;a=a+12|0;d=nd()|0;if(!d)md(4040,b);d=c[d>>2]|0;if(!d)md(4040,b);f=d+48|0;e=c[f>>2]|0;f=c[f+4>>2]|0;if(!((e&-256|0)==1126902528&(f|0)==1129074247)){c[b>>2]=c[970];md(4e3,b)}if((e|0)==1126902529&(f|0)==1129074247)e=c[d+44>>2]|0;else e=d+80|0;c[a>>2]=e;f=c[d>>2]|0;d=c[f+4>>2]|0;if(eb[c[(c[4432>>2]|0)+16>>2]&1](4432,f,a)|0){f=c[a>>2]|0;e=c[970]|0;f=ib[c[(c[f>>2]|0)+8>>2]&1](f)|0;c[b>>2]=e;c[b+4>>2]=d;c[b+8>>2]=f;md(3904,b)}else{c[b>>2]=c[970];c[b+4>>2]=d;md(3952,b)}}function Qd(){var a=0;a=i;i=i+16|0;if(!(Ma(4056,20)|0)){i=a;return}else md(4128,a)}function Rd(a){a=a|0;var b=0;b=i;i=i+16|0;Td(a);if(!(Pa(c[1014]|0,0)|0)){i=b;return}else md(4184,b)}function Sd(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;b=i;do if(a>>>0<245){if(a>>>0<11)a=16;else a=a+11&-8;x=a>>>3;p=c[1206]|0;w=p>>>x;if(w&3){g=(w&1^1)+x|0;f=g<<1;d=4864+(f<<2)|0;f=4864+(f+2<<2)|0;h=c[f>>2]|0;j=h+8|0;e=c[j>>2]|0;do if((d|0)!=(e|0)){if(e>>>0<(c[1210]|0)>>>0)Wa();k=e+12|0;if((c[k>>2]|0)==(h|0)){c[k>>2]=d;c[f>>2]=e;break}else Wa()}else c[1206]=p&~(1<<g);while(0);H=g<<3;c[h+4>>2]=H|3;H=h+(H|4)|0;c[H>>2]=c[H>>2]|1;H=j;i=b;return H|0}v=c[1208]|0;if(a>>>0>v>>>0){if(w){h=2<<x;h=w<<x&(h|0-h);h=(h&0-h)+ -1|0;d=h>>>12&16;h=h>>>d;j=h>>>5&8;h=h>>>j;f=h>>>2&4;h=h>>>f;g=h>>>1&2;h=h>>>g;e=h>>>1&1;e=(j|d|f|g|e)+(h>>>e)|0;h=e<<1;g=4864+(h<<2)|0;h=4864+(h+2<<2)|0;f=c[h>>2]|0;d=f+8|0;j=c[d>>2]|0;do if((g|0)!=(j|0)){if(j>>>0<(c[1210]|0)>>>0)Wa();k=j+12|0;if((c[k>>2]|0)==(f|0)){c[k>>2]=g;c[h>>2]=j;E=c[1208]|0;break}else Wa()}else{c[1206]=p&~(1<<e);E=v}while(0);H=e<<3;e=H-a|0;c[f+4>>2]=a|3;g=f+a|0;c[f+(a|4)>>2]=e|1;c[f+H>>2]=e;if(E){f=c[1211]|0;l=E>>>3;j=l<<1;h=4864+(j<<2)|0;k=c[1206]|0;l=1<<l;if(k&l){j=4864+(j+2<<2)|0;k=c[j>>2]|0;if(k>>>0<(c[1210]|0)>>>0)Wa();else{D=j;C=k}}else{c[1206]=k|l;D=4864+(j+2<<2)|0;C=h}c[D>>2]=f;c[C+12>>2]=f;c[f+8>>2]=C;c[f+12>>2]=h}c[1208]=e;c[1211]=g;H=d;i=b;return H|0}p=c[1207]|0;if(p){d=(p&0-p)+ -1|0;G=d>>>12&16;d=d>>>G;F=d>>>5&8;d=d>>>F;H=d>>>2&4;d=d>>>H;f=d>>>1&2;d=d>>>f;e=d>>>1&1;e=c[5128+((F|G|H|f|e)+(d>>>e)<<2)>>2]|0;d=(c[e+4>>2]&-8)-a|0;f=e;while(1){g=c[f+16>>2]|0;if(!g){g=c[f+20>>2]|0;if(!g)break}f=(c[g+4>>2]&-8)-a|0;H=f>>>0<d>>>0;d=H?f:d;f=g;e=H?g:e}h=c[1210]|0;if(e>>>0<h>>>0)Wa();f=e+a|0;if(e>>>0>=f>>>0)Wa();g=c[e+24>>2]|0;k=c[e+12>>2]|0;do if((k|0)==(e|0)){k=e+20|0;j=c[k>>2]|0;if(!j){k=e+16|0;j=c[k>>2]|0;if(!j){B=0;break}}while(1){l=j+20|0;m=c[l>>2]|0;if(m){j=m;k=l;continue}l=j+16|0;m=c[l>>2]|0;if(!m)break;else{j=m;k=l}}if(k>>>0<h>>>0)Wa();else{c[k>>2]=0;B=j;break}}else{j=c[e+8>>2]|0;if(j>>>0<h>>>0)Wa();h=j+12|0;if((c[h>>2]|0)!=(e|0))Wa();l=k+8|0;if((c[l>>2]|0)==(e|0)){c[h>>2]=k;c[l>>2]=j;B=k;break}else Wa()}while(0);do if(g){j=c[e+28>>2]|0;h=5128+(j<<2)|0;if((e|0)==(c[h>>2]|0)){c[h>>2]=B;if(!B){c[1207]=c[1207]&~(1<<j);break}}else{if(g>>>0<(c[1210]|0)>>>0)Wa();h=g+16|0;if((c[h>>2]|0)==(e|0))c[h>>2]=B;else c[g+20>>2]=B;if(!B)break}h=c[1210]|0;if(B>>>0<h>>>0)Wa();c[B+24>>2]=g;g=c[e+16>>2]|0;do if(g)if(g>>>0<h>>>0)Wa();else{c[B+16>>2]=g;c[g+24>>2]=B;break}while(0);g=c[e+20>>2]|0;if(g)if(g>>>0<(c[1210]|0)>>>0)Wa();else{c[B+20>>2]=g;c[g+24>>2]=B;break}}while(0);if(d>>>0<16){H=d+a|0;c[e+4>>2]=H|3;H=e+(H+4)|0;c[H>>2]=c[H>>2]|1}else{c[e+4>>2]=a|3;c[e+(a|4)>>2]=d|1;c[e+(d+a)>>2]=d;h=c[1208]|0;if(h){g=c[1211]|0;k=h>>>3;l=k<<1;h=4864+(l<<2)|0;j=c[1206]|0;k=1<<k;if(j&k){j=4864+(l+2<<2)|0;k=c[j>>2]|0;if(k>>>0<(c[1210]|0)>>>0)Wa();else{A=j;z=k}}else{c[1206]=j|k;A=4864+(l+2<<2)|0;z=h}c[A>>2]=g;c[z+12>>2]=g;c[g+8>>2]=z;c[g+12>>2]=h}c[1208]=d;c[1211]=f}H=e+8|0;i=b;return H|0}}}else if(a>>>0<=4294967231){z=a+11|0;a=z&-8;B=c[1207]|0;if(B){A=0-a|0;z=z>>>8;if(z)if(a>>>0>16777215)C=31;else{G=(z+1048320|0)>>>16&8;H=z<<G;F=(H+520192|0)>>>16&4;H=H<<F;C=(H+245760|0)>>>16&2;C=14-(F|G|C)+(H<<C>>>15)|0;C=a>>>(C+7|0)&1|C<<1}else C=0;D=c[5128+(C<<2)>>2]|0;a:do if(!D){F=0;z=0}else{if((C|0)==31)z=0;else z=25-(C>>>1)|0;F=0;E=a<<z;z=0;while(1){G=c[D+4>>2]&-8;H=G-a|0;if(H>>>0<A>>>0)if((G|0)==(a|0)){A=H;F=D;z=D;break a}else{A=H;z=D}H=c[D+20>>2]|0;D=c[D+(E>>>31<<2)+16>>2]|0;F=(H|0)==0|(H|0)==(D|0)?F:H;if(!D)break;else E=E<<1}}while(0);if((F|0)==0&(z|0)==0){H=2<<C;B=B&(H|0-H);if(!B)break;H=(B&0-B)+ -1|0;D=H>>>12&16;H=H>>>D;C=H>>>5&8;H=H>>>C;E=H>>>2&4;H=H>>>E;G=H>>>1&2;H=H>>>G;F=H>>>1&1;F=c[5128+((C|D|E|G|F)+(H>>>F)<<2)>>2]|0}if(F)while(1){H=(c[F+4>>2]&-8)-a|0;B=H>>>0<A>>>0;A=B?H:A;z=B?F:z;B=c[F+16>>2]|0;if(B){F=B;continue}F=c[F+20>>2]|0;if(!F)break}if((z|0)!=0?A>>>0<((c[1208]|0)-a|0)>>>0:0){f=c[1210]|0;if(z>>>0<f>>>0)Wa();d=z+a|0;if(z>>>0>=d>>>0)Wa();e=c[z+24>>2]|0;g=c[z+12>>2]|0;do if((g|0)==(z|0)){h=z+20|0;g=c[h>>2]|0;if(!g){h=z+16|0;g=c[h>>2]|0;if(!g){x=0;break}}while(1){j=g+20|0;k=c[j>>2]|0;if(k){g=k;h=j;continue}j=g+16|0;k=c[j>>2]|0;if(!k)break;else{g=k;h=j}}if(h>>>0<f>>>0)Wa();else{c[h>>2]=0;x=g;break}}else{h=c[z+8>>2]|0;if(h>>>0<f>>>0)Wa();j=h+12|0;if((c[j>>2]|0)!=(z|0))Wa();f=g+8|0;if((c[f>>2]|0)==(z|0)){c[j>>2]=g;c[f>>2]=h;x=g;break}else Wa()}while(0);do if(e){f=c[z+28>>2]|0;g=5128+(f<<2)|0;if((z|0)==(c[g>>2]|0)){c[g>>2]=x;if(!x){c[1207]=c[1207]&~(1<<f);break}}else{if(e>>>0<(c[1210]|0)>>>0)Wa();f=e+16|0;if((c[f>>2]|0)==(z|0))c[f>>2]=x;else c[e+20>>2]=x;if(!x)break}f=c[1210]|0;if(x>>>0<f>>>0)Wa();c[x+24>>2]=e;e=c[z+16>>2]|0;do if(e)if(e>>>0<f>>>0)Wa();else{c[x+16>>2]=e;c[e+24>>2]=x;break}while(0);e=c[z+20>>2]|0;if(e)if(e>>>0<(c[1210]|0)>>>0)Wa();else{c[x+20>>2]=e;c[e+24>>2]=x;break}}while(0);b:do if(A>>>0>=16){c[z+4>>2]=a|3;c[z+(a|4)>>2]=A|1;c[z+(A+a)>>2]=A;f=A>>>3;if(A>>>0<256){h=f<<1;e=4864+(h<<2)|0;g=c[1206]|0;f=1<<f;do if(!(g&f)){c[1206]=g|f;w=4864+(h+2<<2)|0;v=e}else{f=4864+(h+2<<2)|0;g=c[f>>2]|0;if(g>>>0>=(c[1210]|0)>>>0){w=f;v=g;break}Wa()}while(0);c[w>>2]=d;c[v+12>>2]=d;c[z+(a+8)>>2]=v;c[z+(a+12)>>2]=e;break}e=A>>>8;if(e)if(A>>>0>16777215)e=31;else{G=(e+1048320|0)>>>16&8;H=e<<G;F=(H+520192|0)>>>16&4;H=H<<F;e=(H+245760|0)>>>16&2;e=14-(F|G|e)+(H<<e>>>15)|0;e=A>>>(e+7|0)&1|e<<1}else e=0;f=5128+(e<<2)|0;c[z+(a+28)>>2]=e;c[z+(a+20)>>2]=0;c[z+(a+16)>>2]=0;g=c[1207]|0;h=1<<e;if(!(g&h)){c[1207]=g|h;c[f>>2]=d;c[z+(a+24)>>2]=f;c[z+(a+12)>>2]=d;c[z+(a+8)>>2]=d;break}h=c[f>>2]|0;if((e|0)==31)e=0;else e=25-(e>>>1)|0;c:do if((c[h+4>>2]&-8|0)!=(A|0)){e=A<<e;while(1){g=h+(e>>>31<<2)+16|0;f=c[g>>2]|0;if(!f)break;if((c[f+4>>2]&-8|0)==(A|0)){p=f;break c}else{e=e<<1;h=f}}if(g>>>0<(c[1210]|0)>>>0)Wa();else{c[g>>2]=d;c[z+(a+24)>>2]=h;c[z+(a+12)>>2]=d;c[z+(a+8)>>2]=d;break b}}else p=h;while(0);f=p+8|0;e=c[f>>2]|0;H=c[1210]|0;if(p>>>0>=H>>>0&e>>>0>=H>>>0){c[e+12>>2]=d;c[f>>2]=d;c[z+(a+8)>>2]=e;c[z+(a+12)>>2]=p;c[z+(a+24)>>2]=0;break}else Wa()}else{H=A+a|0;c[z+4>>2]=H|3;H=z+(H+4)|0;c[H>>2]=c[H>>2]|1}while(0);H=z+8|0;i=b;return H|0}}}else a=-1;while(0);p=c[1208]|0;if(p>>>0>=a>>>0){e=p-a|0;d=c[1211]|0;if(e>>>0>15){c[1211]=d+a;c[1208]=e;c[d+(a+4)>>2]=e|1;c[d+p>>2]=e;c[d+4>>2]=a|3}else{c[1208]=0;c[1211]=0;c[d+4>>2]=p|3;H=d+(p+4)|0;c[H>>2]=c[H>>2]|1}H=d+8|0;i=b;return H|0}p=c[1209]|0;if(p>>>0>a>>>0){G=p-a|0;c[1209]=G;H=c[1212]|0;c[1212]=H+a;c[H+(a+4)>>2]=G|1;c[H+4>>2]=a|3;H=H+8|0;i=b;return H|0}do if(!(c[1324]|0)){p=Ga(30)|0;if(!(p+ -1&p)){c[1326]=p;c[1325]=p;c[1327]=-1;c[1328]=-1;c[1329]=0;c[1317]=0;c[1324]=(Ya(0)|0)&-16^1431655768;break}else Wa()}while(0);x=a+48|0;p=c[1326]|0;w=a+47|0;A=p+w|0;p=0-p|0;v=A&p;if(v>>>0<=a>>>0){H=0;i=b;return H|0}z=c[1316]|0;if((z|0)!=0?(G=c[1314]|0,H=G+v|0,H>>>0<=G>>>0|H>>>0>z>>>0):0){H=0;i=b;return H|0}d:do if(!(c[1317]&4)){B=c[1212]|0;e:do if(B){z=5272|0;while(1){C=c[z>>2]|0;if(C>>>0<=B>>>0?(y=z+4|0,(C+(c[y>>2]|0)|0)>>>0>B>>>0):0)break;z=c[z+8>>2]|0;if(!z){o=181;break e}}if(z){A=A-(c[1209]|0)&p;if(A>>>0<2147483647){p=Aa(A|0)|0;if((p|0)==((c[z>>2]|0)+(c[y>>2]|0)|0)){z=A;o=190}else{z=A;o=191}}else z=0}else o=181}else o=181;while(0);do if((o|0)==181){y=Aa(0)|0;if((y|0)!=(-1|0)){A=y;z=c[1325]|0;p=z+ -1|0;if(!(p&A))z=v;else z=v-A+(p+A&0-z)|0;p=c[1314]|0;A=p+z|0;if(z>>>0>a>>>0&z>>>0<2147483647){H=c[1316]|0;if((H|0)!=0?A>>>0<=p>>>0|A>>>0>H>>>0:0){z=0;break}p=Aa(z|0)|0;if((p|0)==(y|0)){p=y;o=190}else o=191}else z=0}else z=0}while(0);f:do if((o|0)==190){if((p|0)!=(-1|0)){q=z;o=201;break d}}else if((o|0)==191){o=0-z|0;do if((p|0)!=(-1|0)&z>>>0<2147483647&x>>>0>z>>>0?(u=c[1326]|0,u=w-z+u&0-u,u>>>0<2147483647):0)if((Aa(u|0)|0)==(-1|0)){Aa(o|0)|0;z=0;break f}else{z=u+z|0;break}while(0);if((p|0)==(-1|0))z=0;else{q=z;o=201;break d}}while(0);c[1317]=c[1317]|4;o=198}else{z=0;o=198}while(0);if((((o|0)==198?v>>>0<2147483647:0)?(t=Aa(v|0)|0,s=Aa(0)|0,(t|0)!=(-1|0)&(s|0)!=(-1|0)&t>>>0<s>>>0):0)?(r=s-t|0,q=r>>>0>(a+40|0)>>>0,q):0){p=t;q=q?r:z;o=201}if((o|0)==201){r=(c[1314]|0)+q|0;c[1314]=r;if(r>>>0>(c[1315]|0)>>>0)c[1315]=r;r=c[1212]|0;g:do if(r){t=5272|0;while(1){s=c[t>>2]|0;v=t+4|0;w=c[v>>2]|0;if((p|0)==(s+w|0)){o=213;break}u=c[t+8>>2]|0;if(!u)break;else t=u}if(((o|0)==213?(c[t+12>>2]&8|0)==0:0)?r>>>0>=s>>>0&r>>>0<p>>>0:0){c[v>>2]=w+q;d=(c[1209]|0)+q|0;e=r+8|0;if(!(e&7))e=0;else e=0-e&7;H=d-e|0;c[1212]=r+e;c[1209]=H;c[r+(e+4)>>2]=H|1;c[r+(d+4)>>2]=40;c[1213]=c[1328];break}s=c[1210]|0;if(p>>>0<s>>>0){c[1210]=p;s=p}v=p+q|0;t=5272|0;while(1){if((c[t>>2]|0)==(v|0)){o=223;break}u=c[t+8>>2]|0;if(!u)break;else t=u}if((o|0)==223?(c[t+12>>2]&8|0)==0:0){c[t>>2]=p;h=t+4|0;c[h>>2]=(c[h>>2]|0)+q;h=p+8|0;if(!(h&7))h=0;else h=0-h&7;j=p+(q+8)|0;if(!(j&7))n=0;else n=0-j&7;o=p+(n+q)|0;k=h+a|0;j=p+k|0;m=o-(p+h)-a|0;c[p+(h+4)>>2]=a|3;h:do if((o|0)!=(r|0)){if((o|0)==(c[1211]|0)){H=(c[1208]|0)+m|0;c[1208]=H;c[1211]=j;c[p+(k+4)>>2]=H|1;c[p+(H+k)>>2]=H;break}r=q+4|0;u=c[p+(r+n)>>2]|0;if((u&3|0)==1){a=u&-8;t=u>>>3;i:do if(u>>>0>=256){l=c[p+((n|24)+q)>>2]|0;t=c[p+(q+12+n)>>2]|0;do if((t|0)==(o|0)){v=n|16;u=p+(r+v)|0;t=c[u>>2]|0;if(!t){u=p+(v+q)|0;t=c[u>>2]|0;if(!t){g=0;break}}while(1){w=t+20|0;v=c[w>>2]|0;if(v){t=v;u=w;continue}w=t+16|0;v=c[w>>2]|0;if(!v)break;else{t=v;u=w}}if(u>>>0<s>>>0)Wa();else{c[u>>2]=0;g=t;break}}else{u=c[p+((n|8)+q)>>2]|0;if(u>>>0<s>>>0)Wa();v=u+12|0;if((c[v>>2]|0)!=(o|0))Wa();s=t+8|0;if((c[s>>2]|0)==(o|0)){c[v>>2]=t;c[s>>2]=u;g=t;break}else Wa()}while(0);if(!l)break;s=c[p+(q+28+n)>>2]|0;t=5128+(s<<2)|0;do if((o|0)!=(c[t>>2]|0)){if(l>>>0<(c[1210]|0)>>>0)Wa();s=l+16|0;if((c[s>>2]|0)==(o|0))c[s>>2]=g;else c[l+20>>2]=g;if(!g)break i}else{c[t>>2]=g;if(g)break;c[1207]=c[1207]&~(1<<s);break i}while(0);o=c[1210]|0;if(g>>>0<o>>>0)Wa();c[g+24>>2]=l;s=n|16;l=c[p+(s+q)>>2]|0;do if(l)if(l>>>0<o>>>0)Wa();else{c[g+16>>2]=l;c[l+24>>2]=g;break}while(0);l=c[p+(r+s)>>2]|0;if(!l)break;if(l>>>0<(c[1210]|0)>>>0)Wa();else{c[g+20>>2]=l;c[l+24>>2]=g;break}}else{g=c[p+((n|8)+q)>>2]|0;r=c[p+(q+12+n)>>2]|0;u=4864+(t<<1<<2)|0;do if((g|0)!=(u|0)){if(g>>>0<s>>>0)Wa();if((c[g+12>>2]|0)==(o|0))break;Wa()}while(0);if((r|0)==(g|0)){c[1206]=c[1206]&~(1<<t);break}do if((r|0)==(u|0))l=r+8|0;else{if(r>>>0<s>>>0)Wa();s=r+8|0;if((c[s>>2]|0)==(o|0)){l=s;break}Wa()}while(0);c[g+12>>2]=r;c[l>>2]=g}while(0);o=p+((a|n)+q)|0;m=a+m|0}g=o+4|0;c[g>>2]=c[g>>2]&-2;c[p+(k+4)>>2]=m|1;c[p+(m+k)>>2]=m;g=m>>>3;if(m>>>0<256){l=g<<1;d=4864+(l<<2)|0;m=c[1206]|0;g=1<<g;do if(!(m&g)){c[1206]=m|g;f=4864+(l+2<<2)|0;e=d}else{l=4864+(l+2<<2)|0;g=c[l>>2]|0;if(g>>>0>=(c[1210]|0)>>>0){f=l;e=g;break}Wa()}while(0);c[f>>2]=j;c[e+12>>2]=j;c[p+(k+8)>>2]=e;c[p+(k+12)>>2]=d;break}e=m>>>8;do if(!e)e=0;else{if(m>>>0>16777215){e=31;break}G=(e+1048320|0)>>>16&8;H=e<<G;F=(H+520192|0)>>>16&4;H=H<<F;e=(H+245760|0)>>>16&2;e=14-(F|G|e)+(H<<e>>>15)|0;e=m>>>(e+7|0)&1|e<<1}while(0);l=5128+(e<<2)|0;c[p+(k+28)>>2]=e;c[p+(k+20)>>2]=0;c[p+(k+16)>>2]=0;g=c[1207]|0;f=1<<e;if(!(g&f)){c[1207]=g|f;c[l>>2]=j;c[p+(k+24)>>2]=l;c[p+(k+12)>>2]=j;c[p+(k+8)>>2]=j;break}f=c[l>>2]|0;if((e|0)==31)e=0;else e=25-(e>>>1)|0;j:do if((c[f+4>>2]&-8|0)!=(m|0)){e=m<<e;while(1){g=f+(e>>>31<<2)+16|0;l=c[g>>2]|0;if(!l)break;if((c[l+4>>2]&-8|0)==(m|0)){d=l;break j}else{e=e<<1;f=l}}if(g>>>0<(c[1210]|0)>>>0)Wa();else{c[g>>2]=j;c[p+(k+24)>>2]=f;c[p+(k+12)>>2]=j;c[p+(k+8)>>2]=j;break h}}else d=f;while(0);e=d+8|0;f=c[e>>2]|0;H=c[1210]|0;if(d>>>0>=H>>>0&f>>>0>=H>>>0){c[f+12>>2]=j;c[e>>2]=j;c[p+(k+8)>>2]=f;c[p+(k+12)>>2]=d;c[p+(k+24)>>2]=0;break}else Wa()}else{H=(c[1209]|0)+m|0;c[1209]=H;c[1212]=j;c[p+(k+4)>>2]=H|1}while(0);H=p+(h|8)|0;i=b;return H|0}e=5272|0;while(1){d=c[e>>2]|0;if(d>>>0<=r>>>0?(n=c[e+4>>2]|0,m=d+n|0,m>>>0>r>>>0):0)break;e=c[e+8>>2]|0}e=d+(n+ -39)|0;if(!(e&7))e=0;else e=0-e&7;d=d+(n+ -47+e)|0;d=d>>>0<(r+16|0)>>>0?r:d;e=d+8|0;f=p+8|0;if(!(f&7))f=0;else f=0-f&7;H=q+ -40-f|0;c[1212]=p+f;c[1209]=H;c[p+(f+4)>>2]=H|1;c[p+(q+ -36)>>2]=40;c[1213]=c[1328];c[d+4>>2]=27;c[e+0>>2]=c[1318];c[e+4>>2]=c[1319];c[e+8>>2]=c[1320];c[e+12>>2]=c[1321];c[1318]=p;c[1319]=q;c[1321]=0;c[1320]=e;e=d+28|0;c[e>>2]=7;if((d+32|0)>>>0<m>>>0)do{H=e;e=e+4|0;c[e>>2]=7}while((H+8|0)>>>0<m>>>0);if((d|0)!=(r|0)){d=d-r|0;e=r+(d+4)|0;c[e>>2]=c[e>>2]&-2;c[r+4>>2]=d|1;c[r+d>>2]=d;e=d>>>3;if(d>>>0<256){f=e<<1;d=4864+(f<<2)|0;g=c[1206]|0;e=1<<e;do if(!(g&e)){c[1206]=g|e;k=4864+(f+2<<2)|0;j=d}else{f=4864+(f+2<<2)|0;e=c[f>>2]|0;if(e>>>0>=(c[1210]|0)>>>0){k=f;j=e;break}Wa()}while(0);c[k>>2]=r;c[j+12>>2]=r;c[r+8>>2]=j;c[r+12>>2]=d;break}e=d>>>8;if(e)if(d>>>0>16777215)e=31;else{G=(e+1048320|0)>>>16&8;H=e<<G;F=(H+520192|0)>>>16&4;H=H<<F;e=(H+245760|0)>>>16&2;e=14-(F|G|e)+(H<<e>>>15)|0;e=d>>>(e+7|0)&1|e<<1}else e=0;j=5128+(e<<2)|0;c[r+28>>2]=e;c[r+20>>2]=0;c[r+16>>2]=0;f=c[1207]|0;g=1<<e;if(!(f&g)){c[1207]=f|g;c[j>>2]=r;c[r+24>>2]=j;c[r+12>>2]=r;c[r+8>>2]=r;break}f=c[j>>2]|0;if((e|0)==31)e=0;else e=25-(e>>>1)|0;k:do if((c[f+4>>2]&-8|0)!=(d|0)){e=d<<e;j=f;while(1){f=j+(e>>>31<<2)+16|0;g=c[f>>2]|0;if(!g)break;if((c[g+4>>2]&-8|0)==(d|0)){h=g;break k}else{e=e<<1;j=g}}if(f>>>0<(c[1210]|0)>>>0)Wa();else{c[f>>2]=r;c[r+24>>2]=j;c[r+12>>2]=r;c[r+8>>2]=r;break g}}else h=f;while(0);e=h+8|0;d=c[e>>2]|0;H=c[1210]|0;if(h>>>0>=H>>>0&d>>>0>=H>>>0){c[d+12>>2]=r;c[e>>2]=r;c[r+8>>2]=d;c[r+12>>2]=h;c[r+24>>2]=0;break}else Wa()}}else{H=c[1210]|0;if((H|0)==0|p>>>0<H>>>0)c[1210]=p;c[1318]=p;c[1319]=q;c[1321]=0;c[1215]=c[1324];c[1214]=-1;d=0;do{H=d<<1;G=4864+(H<<2)|0;c[4864+(H+3<<2)>>2]=G;c[4864+(H+2<<2)>>2]=G;d=d+1|0}while((d|0)!=32);d=p+8|0;if(!(d&7))d=0;else d=0-d&7;H=q+ -40-d|0;c[1212]=p+d;c[1209]=H;c[p+(d+4)>>2]=H|1;c[p+(q+ -36)>>2]=40;c[1213]=c[1328]}while(0);d=c[1209]|0;if(d>>>0>a>>>0){G=d-a|0;c[1209]=G;H=c[1212]|0;c[1212]=H+a;c[H+(a+4)>>2]=G|1;c[H+4>>2]=a|3;H=H+8|0;i=b;return H|0}}c[(Oa()|0)>>2]=12;H=0;i=b;return H|0}function Td(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;b=i;if(!a){i=b;return}q=a+ -8|0;r=c[1210]|0;if(q>>>0<r>>>0)Wa();n=c[a+ -4>>2]|0;m=n&3;if((m|0)==1)Wa();j=n&-8;h=a+(j+ -8)|0;do if(!(n&1)){u=c[q>>2]|0;if(!m){i=b;return}q=-8-u|0;n=a+q|0;m=u+j|0;if(n>>>0<r>>>0)Wa();if((n|0)==(c[1211]|0)){e=a+(j+ -4)|0;o=c[e>>2]|0;if((o&3|0)!=3){e=n;o=m;break}c[1208]=m;c[e>>2]=o&-2;c[a+(q+4)>>2]=m|1;c[h>>2]=m;i=b;return}t=u>>>3;if(u>>>0<256){e=c[a+(q+8)>>2]|0;o=c[a+(q+12)>>2]|0;p=4864+(t<<1<<2)|0;if((e|0)!=(p|0)){if(e>>>0<r>>>0)Wa();if((c[e+12>>2]|0)!=(n|0))Wa()}if((o|0)==(e|0)){c[1206]=c[1206]&~(1<<t);e=n;o=m;break}if((o|0)!=(p|0)){if(o>>>0<r>>>0)Wa();p=o+8|0;if((c[p>>2]|0)==(n|0))s=p;else Wa()}else s=o+8|0;c[e+12>>2]=o;c[s>>2]=e;e=n;o=m;break}s=c[a+(q+24)>>2]|0;t=c[a+(q+12)>>2]|0;do if((t|0)==(n|0)){u=a+(q+20)|0;t=c[u>>2]|0;if(!t){u=a+(q+16)|0;t=c[u>>2]|0;if(!t){p=0;break}}while(1){v=t+20|0;w=c[v>>2]|0;if(w){t=w;u=v;continue}v=t+16|0;w=c[v>>2]|0;if(!w)break;else{t=w;u=v}}if(u>>>0<r>>>0)Wa();else{c[u>>2]=0;p=t;break}}else{u=c[a+(q+8)>>2]|0;if(u>>>0<r>>>0)Wa();r=u+12|0;if((c[r>>2]|0)!=(n|0))Wa();v=t+8|0;if((c[v>>2]|0)==(n|0)){c[r>>2]=t;c[v>>2]=u;p=t;break}else Wa()}while(0);if(s){r=c[a+(q+28)>>2]|0;t=5128+(r<<2)|0;if((n|0)==(c[t>>2]|0)){c[t>>2]=p;if(!p){c[1207]=c[1207]&~(1<<r);e=n;o=m;break}}else{if(s>>>0<(c[1210]|0)>>>0)Wa();r=s+16|0;if((c[r>>2]|0)==(n|0))c[r>>2]=p;else c[s+20>>2]=p;if(!p){e=n;o=m;break}}r=c[1210]|0;if(p>>>0<r>>>0)Wa();c[p+24>>2]=s;s=c[a+(q+16)>>2]|0;do if(s)if(s>>>0<r>>>0)Wa();else{c[p+16>>2]=s;c[s+24>>2]=p;break}while(0);q=c[a+(q+20)>>2]|0;if(q)if(q>>>0<(c[1210]|0)>>>0)Wa();else{c[p+20>>2]=q;c[q+24>>2]=p;e=n;o=m;break}else{e=n;o=m}}else{e=n;o=m}}else{e=q;o=j}while(0);if(e>>>0>=h>>>0)Wa();m=a+(j+ -4)|0;n=c[m>>2]|0;if(!(n&1))Wa();if(!(n&2)){if((h|0)==(c[1212]|0)){w=(c[1209]|0)+o|0;c[1209]=w;c[1212]=e;c[e+4>>2]=w|1;if((e|0)!=(c[1211]|0)){i=b;return}c[1211]=0;c[1208]=0;i=b;return}if((h|0)==(c[1211]|0)){w=(c[1208]|0)+o|0;c[1208]=w;c[1211]=e;c[e+4>>2]=w|1;c[e+w>>2]=w;i=b;return}o=(n&-8)+o|0;m=n>>>3;do if(n>>>0>=256){l=c[a+(j+16)>>2]|0;m=c[a+(j|4)>>2]|0;do if((m|0)==(h|0)){n=a+(j+12)|0;m=c[n>>2]|0;if(!m){n=a+(j+8)|0;m=c[n>>2]|0;if(!m){k=0;break}}while(1){q=m+20|0;p=c[q>>2]|0;if(p){m=p;n=q;continue}p=m+16|0;q=c[p>>2]|0;if(!q)break;else{m=q;n=p}}if(n>>>0<(c[1210]|0)>>>0)Wa();else{c[n>>2]=0;k=m;break}}else{n=c[a+j>>2]|0;if(n>>>0<(c[1210]|0)>>>0)Wa();p=n+12|0;if((c[p>>2]|0)!=(h|0))Wa();q=m+8|0;if((c[q>>2]|0)==(h|0)){c[p>>2]=m;c[q>>2]=n;k=m;break}else Wa()}while(0);if(l){m=c[a+(j+20)>>2]|0;n=5128+(m<<2)|0;if((h|0)==(c[n>>2]|0)){c[n>>2]=k;if(!k){c[1207]=c[1207]&~(1<<m);break}}else{if(l>>>0<(c[1210]|0)>>>0)Wa();m=l+16|0;if((c[m>>2]|0)==(h|0))c[m>>2]=k;else c[l+20>>2]=k;if(!k)break}h=c[1210]|0;if(k>>>0<h>>>0)Wa();c[k+24>>2]=l;l=c[a+(j+8)>>2]|0;do if(l)if(l>>>0<h>>>0)Wa();else{c[k+16>>2]=l;c[l+24>>2]=k;break}while(0);h=c[a+(j+12)>>2]|0;if(h)if(h>>>0<(c[1210]|0)>>>0)Wa();else{c[k+20>>2]=h;c[h+24>>2]=k;break}}}else{k=c[a+j>>2]|0;j=c[a+(j|4)>>2]|0;a=4864+(m<<1<<2)|0;if((k|0)!=(a|0)){if(k>>>0<(c[1210]|0)>>>0)Wa();if((c[k+12>>2]|0)!=(h|0))Wa()}if((j|0)==(k|0)){c[1206]=c[1206]&~(1<<m);break}if((j|0)!=(a|0)){if(j>>>0<(c[1210]|0)>>>0)Wa();a=j+8|0;if((c[a>>2]|0)==(h|0))l=a;else Wa()}else l=j+8|0;c[k+12>>2]=j;c[l>>2]=k}while(0);c[e+4>>2]=o|1;c[e+o>>2]=o;if((e|0)==(c[1211]|0)){c[1208]=o;i=b;return}}else{c[m>>2]=n&-2;c[e+4>>2]=o|1;c[e+o>>2]=o}h=o>>>3;if(o>>>0<256){j=h<<1;d=4864+(j<<2)|0;k=c[1206]|0;h=1<<h;if(k&h){j=4864+(j+2<<2)|0;h=c[j>>2]|0;if(h>>>0<(c[1210]|0)>>>0)Wa();else{f=j;g=h}}else{c[1206]=k|h;f=4864+(j+2<<2)|0;g=d}c[f>>2]=e;c[g+12>>2]=e;c[e+8>>2]=g;c[e+12>>2]=d;i=b;return}f=o>>>8;if(f)if(o>>>0>16777215)f=31;else{v=(f+1048320|0)>>>16&8;w=f<<v;u=(w+520192|0)>>>16&4;w=w<<u;f=(w+245760|0)>>>16&2;f=14-(u|v|f)+(w<<f>>>15)|0;f=o>>>(f+7|0)&1|f<<1}else f=0;g=5128+(f<<2)|0;c[e+28>>2]=f;c[e+20>>2]=0;c[e+16>>2]=0;j=c[1207]|0;h=1<<f;a:do if(j&h){g=c[g>>2]|0;if((f|0)==31)f=0;else f=25-(f>>>1)|0;b:do if((c[g+4>>2]&-8|0)!=(o|0)){f=o<<f;while(1){j=g+(f>>>31<<2)+16|0;h=c[j>>2]|0;if(!h)break;if((c[h+4>>2]&-8|0)==(o|0)){d=h;break b}else{f=f<<1;g=h}}if(j>>>0<(c[1210]|0)>>>0)Wa();else{c[j>>2]=e;c[e+24>>2]=g;c[e+12>>2]=e;c[e+8>>2]=e;break a}}else d=g;while(0);g=d+8|0;f=c[g>>2]|0;w=c[1210]|0;if(d>>>0>=w>>>0&f>>>0>=w>>>0){c[f+12>>2]=e;c[g>>2]=e;c[e+8>>2]=f;c[e+12>>2]=d;c[e+24>>2]=0;break}else Wa()}else{c[1207]=j|h;c[g>>2]=e;c[e+24>>2]=g;c[e+12>>2]=e;c[e+8>>2]=e}while(0);w=(c[1214]|0)+ -1|0;c[1214]=w;if(!w)d=5280|0;else{i=b;return}while(1){d=c[d>>2]|0;if(!d)break;else d=d+8|0}c[1214]=-1;i=b;return}function Ud(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;do if(a){if(b>>>0>4294967231){c[(Oa()|0)>>2]=12;e=0;break}if(b>>>0<11)e=16;else e=b+11&-8;e=fe(a+ -8|0,e)|0;if(e){e=e+8|0;break}e=Sd(b)|0;if(!e)e=0;else{f=c[a+ -4>>2]|0;f=(f&-8)-((f&3|0)==0?8:4)|0;pe(e|0,a|0,(f>>>0<b>>>0?f:b)|0)|0;Td(a)}}else e=Sd(b)|0;while(0);i=d;return e|0}function Vd(a){a=a|0;if((a|0)==32)a=1;else a=(a+ -9|0)>>>0<5;return a&1|0}function Wd(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;j=i;if(e>>>0>36){c[(Oa()|0)>>2]=22;s=0;t=0;F=s;i=j;return t|0}k=b+4|0;l=b+100|0;do{m=c[k>>2]|0;if(m>>>0<(c[l>>2]|0)>>>0){c[k>>2]=m+1;o=d[m>>0]|0}else o=Zd(b)|0}while((Vd(o)|0)!=0);do if((o|0)==43|(o|0)==45){m=((o|0)==45)<<31>>31;n=c[k>>2]|0;if(n>>>0<(c[l>>2]|0)>>>0){c[k>>2]=n+1;o=d[n>>0]|0;break}else{o=Zd(b)|0;break}}else m=0;while(0);n=(e|0)==0;do if((e&-17|0)==0&(o|0)==48){o=c[k>>2]|0;if(o>>>0<(c[l>>2]|0)>>>0){c[k>>2]=o+1;o=d[o>>0]|0}else o=Zd(b)|0;if((o|32|0)!=120)if(n){e=8;f=46;break}else{f=32;break}e=c[k>>2]|0;if(e>>>0<(c[l>>2]|0)>>>0){c[k>>2]=e+1;o=d[e>>0]|0}else o=Zd(b)|0;if((d[o+5321>>0]|0)>15){g=(c[l>>2]|0)==0;if(!g)c[k>>2]=(c[k>>2]|0)+ -1;if(!f){Yd(b,0);s=0;t=0;F=s;i=j;return t|0}if(g){s=0;t=0;F=s;i=j;return t|0}c[k>>2]=(c[k>>2]|0)+ -1;s=0;t=0;F=s;i=j;return t|0}else{e=16;f=46}}else{e=n?10:e;if((d[o+5321>>0]|0)>>>0<e>>>0)f=32;else{if(c[l>>2]|0)c[k>>2]=(c[k>>2]|0)+ -1;Yd(b,0);c[(Oa()|0)>>2]=22;s=0;t=0;F=s;i=j;return t|0}}while(0);if((f|0)==32)if((e|0)==10){e=o+ -48|0;if(e>>>0<10){n=0;do{n=(n*10|0)+e|0;e=c[k>>2]|0;if(e>>>0<(c[l>>2]|0)>>>0){c[k>>2]=e+1;o=d[e>>0]|0}else o=Zd(b)|0;e=o+ -48|0}while(e>>>0<10&n>>>0<429496729);p=0}else{n=0;p=0}e=o+ -48|0;if(e>>>0<10){do{q=we(n|0,p|0,10,0)|0;r=F;s=((e|0)<0)<<31>>31;t=~s;if(r>>>0>t>>>0|(r|0)==(t|0)&q>>>0>~e>>>0)break;n=ne(q|0,r|0,e|0,s|0)|0;p=F;e=c[k>>2]|0;if(e>>>0<(c[l>>2]|0)>>>0){c[k>>2]=e+1;o=d[e>>0]|0}else o=Zd(b)|0;e=o+ -48|0}while(e>>>0<10&(p>>>0<429496729|(p|0)==429496729&n>>>0<2576980378));if(e>>>0<=9){e=10;f=72}}}else f=46;a:do if((f|0)==46){if(!(e+ -1&e)){f=a[5584+((e*23|0)>>>5&7)>>0]|0;r=a[o+5321>>0]|0;n=r&255;if(n>>>0<e>>>0){o=n;n=0;do{n=o|n<<f;o=c[k>>2]|0;if(o>>>0<(c[l>>2]|0)>>>0){c[k>>2]=o+1;s=d[o>>0]|0}else s=Zd(b)|0;r=a[s+5321>>0]|0;o=r&255}while(o>>>0<e>>>0&n>>>0<134217728);p=0}else{p=0;n=0;s=o}o=oe(-1,-1,f|0)|0;q=F;if((r&255)>>>0>=e>>>0|(p>>>0>q>>>0|(p|0)==(q|0)&n>>>0>o>>>0)){o=s;f=72;break}while(1){n=le(n|0,p|0,f|0)|0;p=F;n=r&255|n;r=c[k>>2]|0;if(r>>>0<(c[l>>2]|0)>>>0){c[k>>2]=r+1;s=d[r>>0]|0}else s=Zd(b)|0;r=a[s+5321>>0]|0;if((r&255)>>>0>=e>>>0|(p>>>0>q>>>0|(p|0)==(q|0)&n>>>0>o>>>0)){o=s;f=72;break a}}}r=a[o+5321>>0]|0;f=r&255;if(f>>>0<e>>>0){n=0;do{n=f+(ba(n,e)|0)|0;f=c[k>>2]|0;if(f>>>0<(c[l>>2]|0)>>>0){c[k>>2]=f+1;q=d[f>>0]|0}else q=Zd(b)|0;r=a[q+5321>>0]|0;f=r&255}while(f>>>0<e>>>0&n>>>0<119304647);p=0}else{n=0;p=0;q=o}if((r&255)>>>0<e>>>0){f=xe(-1,-1,e|0,0)|0;o=F;while(1){if(p>>>0>o>>>0|(p|0)==(o|0)&n>>>0>f>>>0){o=q;f=72;break a}s=we(n|0,p|0,e|0,0)|0;t=F;r=r&255;if(t>>>0>4294967295|(t|0)==-1&s>>>0>~r>>>0){o=q;f=72;break a}n=ne(r|0,0,s|0,t|0)|0;p=F;q=c[k>>2]|0;if(q>>>0<(c[l>>2]|0)>>>0){c[k>>2]=q+1;q=d[q>>0]|0}else q=Zd(b)|0;r=a[q+5321>>0]|0;if((r&255)>>>0>=e>>>0){o=q;f=72;break}}}else{o=q;f=72}}while(0);if((f|0)==72)if((d[o+5321>>0]|0)>>>0<e>>>0){do{f=c[k>>2]|0;if(f>>>0<(c[l>>2]|0)>>>0){c[k>>2]=f+1;f=d[f>>0]|0}else f=Zd(b)|0}while((d[f+5321>>0]|0)>>>0<e>>>0);c[(Oa()|0)>>2]=34;p=h;n=g}if(c[l>>2]|0)c[k>>2]=(c[k>>2]|0)+ -1;if(!(p>>>0<h>>>0|(p|0)==(h|0)&n>>>0<g>>>0)){if(!((g&1|0)!=0|0!=0|(m|0)!=0)){c[(Oa()|0)>>2]=34;t=ne(g|0,h|0,-1,-1)|0;s=F;F=s;i=j;return t|0}if(p>>>0>h>>>0|(p|0)==(h|0)&n>>>0>g>>>0){c[(Oa()|0)>>2]=34;s=h;t=g;F=s;i=j;return t|0}}t=((m|0)<0)<<31>>31;t=je(n^m|0,p^t|0,m|0,t|0)|0;s=F;F=s;i=j;return t|0}\n\n\n\nfunction Xd(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0,s=0,t=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,G=0.0,H=0,I=0.0,J=0.0,K=0.0,L=0.0;g=i;i=i+512|0;k=g;if(!e){e=24;j=-149}else if((e|0)==2){e=53;j=-1074}else if((e|0)==1){e=53;j=-1074}else{J=0.0;i=g;return+J}n=b+4|0;o=b+100|0;do{h=c[n>>2]|0;if(h>>>0<(c[o>>2]|0)>>>0){c[n>>2]=h+1;w=d[h>>0]|0}else w=Zd(b)|0}while((Vd(w)|0)!=0);do if((w|0)==43|(w|0)==45){h=1-(((w|0)==45&1)<<1)|0;m=c[n>>2]|0;if(m>>>0<(c[o>>2]|0)>>>0){c[n>>2]=m+1;w=d[m>>0]|0;break}else{w=Zd(b)|0;break}}else h=1;while(0);r=0;do{if((w|32|0)!=(a[5600+r>>0]|0))break;do if(r>>>0<7){m=c[n>>2]|0;if(m>>>0<(c[o>>2]|0)>>>0){c[n>>2]=m+1;w=d[m>>0]|0;break}else{w=Zd(b)|0;break}}while(0);r=r+1|0}while(r>>>0<8);do if((r|0)==3)p=23;else if((r|0)!=8){m=(f|0)!=0;if(r>>>0>3&m)if((r|0)==8)break;else{p=23;break}a:do if(!r){r=0;do{if((w|32|0)!=(a[5616+r>>0]|0))break a;do if(r>>>0<2){s=c[n>>2]|0;if(s>>>0<(c[o>>2]|0)>>>0){c[n>>2]=s+1;w=d[s>>0]|0;break}else{w=Zd(b)|0;break}}while(0);r=r+1|0}while(r>>>0<3)}while(0);if(!r){do if((w|0)==48){m=c[n>>2]|0;if(m>>>0<(c[o>>2]|0)>>>0){c[n>>2]=m+1;m=d[m>>0]|0}else m=Zd(b)|0;if((m|32|0)!=120){if(!(c[o>>2]|0)){w=48;break}c[n>>2]=(c[n>>2]|0)+ -1;w=48;break}k=c[n>>2]|0;if(k>>>0<(c[o>>2]|0)>>>0){c[n>>2]=k+1;z=d[k>>0]|0;x=0}else{z=Zd(b)|0;x=0}while(1){if((z|0)==46){p=70;break}else if((z|0)!=48){k=0;m=0;s=0;r=0;w=0;y=0;G=1.0;t=0;q=0.0;break}k=c[n>>2]|0;if(k>>>0<(c[o>>2]|0)>>>0){c[n>>2]=k+1;z=d[k>>0]|0;x=1;continue}else{z=Zd(b)|0;x=1;continue}}if((p|0)==70){k=c[n>>2]|0;if(k>>>0<(c[o>>2]|0)>>>0){c[n>>2]=k+1;z=d[k>>0]|0}else z=Zd(b)|0;if((z|0)==48){s=0;r=0;do{k=c[n>>2]|0;if(k>>>0<(c[o>>2]|0)>>>0){c[n>>2]=k+1;z=d[k>>0]|0}else z=Zd(b)|0;s=ne(s|0,r|0,-1,-1)|0;r=F}while((z|0)==48);k=0;m=0;x=1;w=1;y=0;G=1.0;t=0;q=0.0}else{k=0;m=0;s=0;r=0;w=1;y=0;G=1.0;t=0;q=0.0}}b:while(1){B=z+ -48|0;do if(B>>>0>=10){A=z|32;C=(z|0)==46;if(!((A+ -97|0)>>>0<6|C))break b;if(C)if(!w){s=m;r=k;w=1;break}else{z=46;break b}else{B=(z|0)>57?A+ -87|0:B;p=83;break}}else p=83;while(0);if((p|0)==83){p=0;do if(!((k|0)<0|(k|0)==0&m>>>0<8)){if((k|0)<0|(k|0)==0&m>>>0<14){J=G*.0625;I=J;q=q+J*+(B|0);break}if((B|0)==0|(y|0)!=0)I=G;else{y=1;I=G;q=q+G*.5}}else{I=G;t=B+(t<<4)|0}while(0);m=ne(m|0,k|0,1,0)|0;k=F;x=1;G=I}z=c[n>>2]|0;if(z>>>0<(c[o>>2]|0)>>>0){c[n>>2]=z+1;z=d[z>>0]|0;continue}else{z=Zd(b)|0;continue}}if(!x){e=(c[o>>2]|0)==0;if(!e)c[n>>2]=(c[n>>2]|0)+ -1;if(f){if(!e?(l=c[n>>2]|0,c[n>>2]=l+ -1,(w|0)!=0):0)c[n>>2]=l+ -2}else Yd(b,0);J=+(h|0)*0.0;i=g;return+J}p=(w|0)==0;l=p?m:s;p=p?k:r;if((k|0)<0|(k|0)==0&m>>>0<8)do{t=t<<4;m=ne(m|0,k|0,1,0)|0;k=F}while((k|0)<0|(k|0)==0&m>>>0<8);do if((z|32|0)==112){m=he(b,f)|0;k=F;if((m|0)==0&(k|0)==-2147483648)if(!f){Yd(b,0);J=0.0;i=g;return+J}else{if(!(c[o>>2]|0)){m=0;k=0;break}c[n>>2]=(c[n>>2]|0)+ -1;m=0;k=0;break}}else if(!(c[o>>2]|0)){m=0;k=0}else{c[n>>2]=(c[n>>2]|0)+ -1;m=0;k=0}while(0);l=le(l|0,p|0,2)|0;l=ne(l|0,F|0,-32,-1)|0;k=ne(l|0,F|0,m|0,k|0)|0;l=F;if(!t){J=+(h|0)*0.0;i=g;return+J}if((l|0)>0|(l|0)==0&k>>>0>(0-j|0)>>>0){c[(Oa()|0)>>2]=34;J=+(h|0)*1.7976931348623157e+308*1.7976931348623157e+308;i=g;return+J}H=j+ -106|0;E=((H|0)<0)<<31>>31;if((l|0)<(E|0)|(l|0)==(E|0)&k>>>0<H>>>0){c[(Oa()|0)>>2]=34;J=+(h|0)*2.2250738585072014e-308*2.2250738585072014e-308;i=g;return+J}if((t|0)>-1)do{t=t<<1;if(!(q>=.5))G=q;else{G=q+-1.0;t=t|1}q=q+G;k=ne(k|0,l|0,-1,-1)|0;l=F}while((t|0)>-1);j=je(32,0,j|0,((j|0)<0)<<31>>31|0)|0;j=ne(k|0,l|0,j|0,F|0)|0;H=F;if(0>(H|0)|0==(H|0)&e>>>0>j>>>0)if((j|0)<0){e=0;p=126}else{e=j;p=124}else p=124;if((p|0)==124)if((e|0)<53)p=126;else{j=e;G=+(h|0);I=0.0}if((p|0)==126){I=+(h|0);j=e;G=I;I=+Va(+(+_d(1.0,84-e|0)),+I)}H=(j|0)<32&q!=0.0&(t&1|0)==0;q=G*(H?0.0:q)+(I+G*+(((H&1)+t|0)>>>0))-I;if(!(q!=0.0))c[(Oa()|0)>>2]=34;J=+$d(q,k);i=g;return+J}while(0);m=j+e|0;l=0-m|0;B=0;while(1){if((w|0)==46){p=137;break}else if((w|0)!=48){D=0;C=0;A=0;break}r=c[n>>2]|0;if(r>>>0<(c[o>>2]|0)>>>0){c[n>>2]=r+1;w=d[r>>0]|0;B=1;continue}else{w=Zd(b)|0;B=1;continue}}if((p|0)==137){p=c[n>>2]|0;if(p>>>0<(c[o>>2]|0)>>>0){c[n>>2]=p+1;w=d[p>>0]|0}else w=Zd(b)|0;if((w|0)==48){D=0;C=0;do{D=ne(D|0,C|0,-1,-1)|0;C=F;p=c[n>>2]|0;if(p>>>0<(c[o>>2]|0)>>>0){c[n>>2]=p+1;w=d[p>>0]|0}else w=Zd(b)|0}while((w|0)==48);B=1;A=1}else{D=0;C=0;A=1}}c[k>>2]=0;z=w+ -48|0;E=(w|0)==46;c:do if(z>>>0<10|E){p=k+496|0;y=0;x=0;t=0;s=0;r=0;d:while(1){do if(E)if(!A){D=y;C=x;A=1}else break d;else{E=ne(y|0,x|0,1,0)|0;x=F;H=(w|0)!=48;if((s|0)>=125){if(!H){y=E;break}c[p>>2]=c[p>>2]|1;y=E;break}y=k+(s<<2)|0;if(t)z=w+ -48+((c[y>>2]|0)*10|0)|0;c[y>>2]=z;t=t+1|0;z=(t|0)==9;y=E;B=1;t=z?0:t;s=(z&1)+s|0;r=H?E:r}while(0);w=c[n>>2]|0;if(w>>>0<(c[o>>2]|0)>>>0){c[n>>2]=w+1;w=d[w>>0]|0}else w=Zd(b)|0;z=w+ -48|0;E=(w|0)==46;if(!(z>>>0<10|E)){p=160;break c}}z=(B|0)!=0;p=168}else{y=0;x=0;t=0;s=0;r=0;p=160}while(0);do if((p|0)==160){z=(A|0)==0;D=z?y:D;C=z?x:C;z=(B|0)!=0;if(!(z&(w|32|0)==101))if((w|0)>-1){p=168;break}else{p=170;break}z=he(b,f)|0;w=F;do if((z|0)==0&(w|0)==-2147483648)if(!f){Yd(b,0);J=0.0;i=g;return+J}else{if(!(c[o>>2]|0)){z=0;w=0;break}c[n>>2]=(c[n>>2]|0)+ -1;z=0;w=0;break}while(0);b=ne(z|0,w|0,D|0,C|0)|0;C=F}while(0);if((p|0)==168)if(c[o>>2]|0){c[n>>2]=(c[n>>2]|0)+ -1;if(z)b=D;else p=171}else p=170;if((p|0)==170)if(z)b=D;else p=171;if((p|0)==171){c[(Oa()|0)>>2]=22;Yd(b,0);J=0.0;i=g;return+J}n=c[k>>2]|0;if(!n){J=+(h|0)*0.0;i=g;return+J}if((b|0)==(y|0)&(C|0)==(x|0)&((x|0)<0|(x|0)==0&y>>>0<10)?e>>>0>30|(n>>>e|0)==0:0){J=+(h|0)*+(n>>>0);i=g;return+J}H=(j|0)/-2|0;E=((H|0)<0)<<31>>31;if((C|0)>(E|0)|(C|0)==(E|0)&b>>>0>H>>>0){c[(Oa()|0)>>2]=34;J=+(h|0)*1.7976931348623157e+308*1.7976931348623157e+308;i=g;return+J}H=j+ -106|0;E=((H|0)<0)<<31>>31;if((C|0)<(E|0)|(C|0)==(E|0)&b>>>0<H>>>0){c[(Oa()|0)>>2]=34;J=+(h|0)*2.2250738585072014e-308*2.2250738585072014e-308;i=g;return+J}if(t){if((t|0)<9){n=k+(s<<2)|0;o=c[n>>2]|0;do{o=o*10|0;t=t+1|0}while((t|0)!=9);c[n>>2]=o}s=s+1|0}if((r|0)<9?(r|0)<=(b|0)&(b|0)<18:0){if((b|0)==9){J=+(h|0)*+((c[k>>2]|0)>>>0);i=g;return+J}if((b|0)<9){J=+(h|0)*+((c[k>>2]|0)>>>0)/+(c[5632+(8-b<<2)>>2]|0);i=g;return+J}H=e+27+(ba(b,-3)|0)|0;n=c[k>>2]|0;if((H|0)>30|(n>>>H|0)==0){J=+(h|0)*+(n>>>0)*+(c[5632+(b+ -10<<2)>>2]|0);i=g;return+J}}n=(b|0)%9|0;if(!n){n=0;o=0}else{f=(b|0)>-1?n:n+9|0;p=c[5632+(8-f<<2)>>2]|0;if(s){r=1e9/(p|0)|0;n=0;o=0;t=0;do{D=k+(t<<2)|0;E=c[D>>2]|0;H=((E>>>0)/(p>>>0)|0)+o|0;c[D>>2]=H;o=ba((E>>>0)%(p>>>0)|0,r)|0;E=t;t=t+1|0;if((E|0)==(n|0)&(H|0)==0){n=t&127;b=b+ -9|0}}while((t|0)!=(s|0));if(o){c[k+(s<<2)>>2]=o;s=s+1|0}}else{n=0;s=0}o=0;b=9-f+b|0}e:while(1){f=k+(n<<2)|0;if((b|0)<18){do{r=0;f=s+127|0;while(1){f=f&127;p=k+(f<<2)|0;t=le(c[p>>2]|0,0,29)|0;t=ne(t|0,F|0,r|0,0)|0;r=F;if(r>>>0>0|(r|0)==0&t>>>0>1e9){H=xe(t|0,r|0,1e9,0)|0;t=ye(t|0,r|0,1e9,0)|0;r=H}else r=0;c[p>>2]=t;p=(f|0)==(n|0);if(!((f|0)!=(s+127&127|0)|p))s=(t|0)==0?f:s;if(p)break;else f=f+ -1|0}o=o+ -29|0}while((r|0)==0)}else{if((b|0)!=18)break;do{if((c[f>>2]|0)>>>0>=9007199){b=18;break e}r=0;p=s+127|0;while(1){p=p&127;t=k+(p<<2)|0;w=le(c[t>>2]|0,0,29)|0;w=ne(w|0,F|0,r|0,0)|0;r=F;if(r>>>0>0|(r|0)==0&w>>>0>1e9){H=xe(w|0,r|0,1e9,0)|0;w=ye(w|0,r|0,1e9,0)|0;r=H}else r=0;c[t>>2]=w;t=(p|0)==(n|0);if(!((p|0)!=(s+127&127|0)|t))s=(w|0)==0?p:s;if(t)break;else p=p+ -1|0}o=o+ -29|0}while((r|0)==0)}n=n+127&127;if((n|0)==(s|0)){H=s+127&127;s=k+((s+126&127)<<2)|0;c[s>>2]=c[s>>2]|c[k+(H<<2)>>2];s=H}c[k+(n<<2)>>2]=r;b=b+9|0}f:while(1){f=s+1&127;p=k+((s+127&127)<<2)|0;while(1){t=(b|0)==18;r=(b|0)>27?9:1;while(1){w=0;while(1){x=w+n&127;if((x|0)==(s|0)){w=2;break}y=c[k+(x<<2)>>2]|0;z=c[5624+(w<<2)>>2]|0;if(y>>>0<z>>>0){w=2;break}x=w+1|0;if(y>>>0>z>>>0)break;if((x|0)<2)w=x;else{w=x;break}}if((w|0)==2&t)break f;o=r+o|0;if((n|0)==(s|0))n=s;else break}t=(1<<r)+ -1|0;w=1e9>>>r;x=n;y=0;do{D=k+(n<<2)|0;E=c[D>>2]|0;H=(E>>>r)+y|0;c[D>>2]=H;y=ba(E&t,w)|0;H=(n|0)==(x|0)&(H|0)==0;n=n+1&127;b=H?b+ -9|0:b;x=H?n:x}while((n|0)!=(s|0));if(!y){n=x;continue}if((f|0)!=(x|0))break;c[p>>2]=c[p>>2]|1;n=x}c[k+(s<<2)>>2]=y;n=x;s=f}b=n&127;if((b|0)==(s|0)){c[k+(f+ -1<<2)>>2]=0;s=f}G=+((c[k+(b<<2)>>2]|0)>>>0);b=n+1&127;if((b|0)==(s|0)){s=s+1&127;c[k+(s+ -1<<2)>>2]=0}q=+(h|0);I=q*(G*1.0e9+ +((c[k+(b<<2)>>2]|0)>>>0));h=o+53|0;j=h-j|0;if((j|0)<(e|0))if((j|0)<0){e=0;b=1;p=244}else{e=j;b=1;p=243}else{b=0;p=243}if((p|0)==243)if((e|0)<53)p=244;else{G=0.0;J=0.0}if((p|0)==244){L=+Va(+(+_d(1.0,105-e|0)),+I);K=+cb(+I,+(+_d(1.0,53-e|0)));G=L;J=K;I=L+(I-K)}f=n+2&127;do if((f|0)!=(s|0)){k=c[k+(f<<2)>>2]|0;do if(k>>>0>=5e8){if(k>>>0>5e8){J=q*.75+J;break}if((n+3&127|0)==(s|0)){J=q*.5+J;break}else{J=q*.75+J;break}}else{if((k|0)==0?(n+3&127|0)==(s|0):0)break;J=q*.25+J}while(0);if((53-e|0)<=1)break;if(+cb(+J,1.0)!=0.0)break;J=J+1.0}while(0);q=I+J-G;do if((h&2147483647|0)>(-2-m|0)){if(+Q(+q)>=9007199254740992.0){b=(b|0)!=0&(e|0)==(j|0)?0:b;o=o+1|0;q=q*.5}if((o+50|0)<=(l|0)?!((b|0)!=0&J!=0.0):0)break;c[(Oa()|0)>>2]=34}while(0);L=+$d(q,o);i=g;return+L}else if((r|0)==3){e=c[n>>2]|0;if(e>>>0<(c[o>>2]|0)>>>0){c[n>>2]=e+1;e=d[e>>0]|0}else e=Zd(b)|0;if((e|0)==40)e=1;else{if(!(c[o>>2]|0)){L=u;i=g;return+L}c[n>>2]=(c[n>>2]|0)+ -1;L=u;i=g;return+L}while(1){h=c[n>>2]|0;if(h>>>0<(c[o>>2]|0)>>>0){c[n>>2]=h+1;h=d[h>>0]|0}else h=Zd(b)|0;if(!((h+ -48|0)>>>0<10|(h+ -65|0)>>>0<26)?!((h+ -97|0)>>>0<26|(h|0)==95):0)break;e=e+1|0}if((h|0)==41){L=u;i=g;return+L}h=(c[o>>2]|0)==0;if(!h)c[n>>2]=(c[n>>2]|0)+ -1;if(!m){c[(Oa()|0)>>2]=22;Yd(b,0);L=0.0;i=g;return+L}if((e|0)==0|h){L=u;i=g;return+L}do{e=e+ -1|0;c[n>>2]=(c[n>>2]|0)+ -1}while((e|0)!=0);q=u;i=g;return+q}else{if(c[o>>2]|0)c[n>>2]=(c[n>>2]|0)+ -1;c[(Oa()|0)>>2]=22;Yd(b,0);L=0.0;i=g;return+L}}while(0);if((p|0)==23){e=(c[o>>2]|0)==0;if(!e)c[n>>2]=(c[n>>2]|0)+ -1;if(!(r>>>0<4|(f|0)==0|e))do{c[n>>2]=(c[n>>2]|0)+ -1;r=r+ -1|0}while(r>>>0>3)}L=+(h|0)*v;i=g;return+L}function Yd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;c[a+104>>2]=b;f=c[a+8>>2]|0;e=c[a+4>>2]|0;g=f-e|0;c[a+108>>2]=g;if((b|0)!=0&(g|0)>(b|0)){c[a+100>>2]=e+b;i=d;return}else{c[a+100>>2]=f;i=d;return}}function Zd(b){b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;f=i;j=b+104|0;l=c[j>>2]|0;if(!((l|0)!=0?(c[b+108>>2]|0)>=(l|0):0))k=3;if((k|0)==3?(e=be(b)|0,(e|0)>=0):0){k=c[j>>2]|0;j=c[b+8>>2]|0;if((k|0)!=0?(g=c[b+4>>2]|0,h=k-(c[b+108>>2]|0)+ -1|0,(j-g|0)>(h|0)):0)c[b+100>>2]=g+h;else c[b+100>>2]=j;g=c[b+4>>2]|0;if(j){l=b+108|0;c[l>>2]=j+1-g+(c[l>>2]|0)}b=g+ -1|0;if((d[b>>0]|0|0)==(e|0)){l=e;i=f;return l|0}a[b>>0]=e;l=e;i=f;return l|0}c[b+100>>2]=0;l=-1;i=f;return l|0}function _d(a,b){a=+a;b=b|0;var d=0,e=0;d=i;if((b|0)>1023){a=a*8.98846567431158e+307;e=b+ -1023|0;if((e|0)>1023){b=b+ -2046|0;b=(b|0)>1023?1023:b;a=a*8.98846567431158e+307}else b=e}else if((b|0)<-1022){a=a*2.2250738585072014e-308;e=b+1022|0;if((e|0)<-1022){b=b+2044|0;b=(b|0)<-1022?-1022:b;a=a*2.2250738585072014e-308}else b=e}b=le(b+1023|0,0,52)|0;e=F;c[k>>2]=b;c[k+4>>2]=e;a=a*+h[k>>3];i=d;return+a}function $d(a,b){a=+a;b=b|0;var c=0;c=i;a=+_d(a,b);i=c;return+a}function ae(b){b=b|0;var d=0,e=0,f=0;e=i;f=b+74|0;d=a[f>>0]|0;a[f>>0]=d+255|d;f=b+20|0;d=b+44|0;if((c[f>>2]|0)>>>0>(c[d>>2]|0)>>>0)eb[c[b+36>>2]&1](b,0,0)|0;c[b+16>>2]=0;c[b+28>>2]=0;c[f>>2]=0;f=c[b>>2]|0;if(!(f&20)){f=c[d>>2]|0;c[b+8>>2]=f;c[b+4>>2]=f;f=0;i=e;return f|0}if(!(f&4)){f=-1;i=e;return f|0}c[b>>2]=f|32;f=-1;i=e;return f|0}function be(a){a=a|0;var b=0,e=0;b=i;i=i+16|0;e=b;if((c[a+8>>2]|0)==0?(ae(a)|0)!=0:0)a=-1;else if((eb[c[a+32>>2]&1](a,e,1)|0)==1)a=d[e>>0]|0;else a=-1;i=b;return a|0}function ce(a,b){a=a|0;b=b|0;var d=0,e=0,f=0.0,g=0,h=0;d=i;i=i+112|0;e=d;h=e+0|0;g=h+112|0;do{c[h>>2]=0;h=h+4|0}while((h|0)<(g|0));g=e+4|0;c[g>>2]=a;h=e+8|0;c[h>>2]=-1;c[e+44>>2]=a;c[e+76>>2]=-1;Yd(e,0);f=+Xd(e,1,1);e=(c[g>>2]|0)-(c[h>>2]|0)+(c[e+108>>2]|0)|0;if(!b){i=d;return+f}if(e)a=a+e|0;c[b>>2]=a;i=d;return+f}function de(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;e=i;i=i+112|0;g=e;c[g>>2]=0;f=g+4|0;c[f>>2]=a;c[g+44>>2]=a;if((a|0)<0)c[g+8>>2]=-1;else c[g+8>>2]=a+2147483647;c[g+76>>2]=-1;Yd(g,0);d=Wd(g,d,1,-2147483648,0)|0;if(!b){i=e;return d|0}c[b>>2]=a+((c[f>>2]|0)+(c[g+108>>2]|0)-(c[g+8>>2]|0));i=e;return d|0}function ee(b,c){b=b|0;c=c|0;var d=0,e=0,f=0;d=i;f=a[b>>0]|0;e=a[c>>0]|0;if(f<<24>>24==0?1:f<<24>>24!=e<<24>>24)c=f;else{do{b=b+1|0;c=c+1|0;f=a[b>>0]|0;e=a[c>>0]|0}while(!(f<<24>>24==0?1:f<<24>>24!=e<<24>>24));c=f}i=d;return(c&255)-(e&255)|0}function fe(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;d=i;f=a+4|0;e=c[f>>2]|0;l=e&-8;j=a+l|0;m=c[1210]|0;h=e&3;if(!((h|0)!=1&a>>>0>=m>>>0&a>>>0<j>>>0))Wa();g=a+(l|4)|0;p=c[g>>2]|0;if(!(p&1))Wa();if(!h){if(b>>>0<256){r=0;i=d;return r|0}if(l>>>0>=(b+4|0)>>>0?(l-b|0)>>>0<=c[1326]<<1>>>0:0){r=a;i=d;return r|0}r=0;i=d;return r|0}if(l>>>0>=b>>>0){h=l-b|0;if(h>>>0<=15){r=a;i=d;return r|0}c[f>>2]=e&1|b|2;c[a+(b+4)>>2]=h|3;c[g>>2]=c[g>>2]|1;ge(a+b|0,h);r=a;i=d;return r|0}if((j|0)==(c[1212]|0)){g=(c[1209]|0)+l|0;if(g>>>0<=b>>>0){r=0;i=d;return r|0}r=g-b|0;c[f>>2]=e&1|b|2;c[a+(b+4)>>2]=r|1;c[1212]=a+b;c[1209]=r;r=a;i=d;return r|0}if((j|0)==(c[1211]|0)){h=(c[1208]|0)+l|0;if(h>>>0<b>>>0){r=0;i=d;return r|0}g=h-b|0;if(g>>>0>15){c[f>>2]=e&1|b|2;c[a+(b+4)>>2]=g|1;c[a+h>>2]=g;e=a+(h+4)|0;c[e>>2]=c[e>>2]&-2;e=a+b|0}else{c[f>>2]=e&1|h|2;e=a+(h+4)|0;c[e>>2]=c[e>>2]|1;e=0;g=0}c[1208]=g;c[1211]=e;r=a;i=d;return r|0}if(p&2){r=0;i=d;return r|0}g=(p&-8)+l|0;if(g>>>0<b>>>0){r=0;i=d;return r|0}h=g-b|0;o=p>>>3;do if(p>>>0>=256){n=c[a+(l+24)>>2]|0;o=c[a+(l+12)>>2]|0;do if((o|0)==(j|0)){p=a+(l+20)|0;o=c[p>>2]|0;if(!o){p=a+(l+16)|0;o=c[p>>2]|0;if(!o){k=0;break}}while(1){r=o+20|0;q=c[r>>2]|0;if(q){o=q;p=r;continue}q=o+16|0;r=c[q>>2]|0;if(!r)break;else{o=r;p=q}}if(p>>>0<m>>>0)Wa();else{c[p>>2]=0;k=o;break}}else{p=c[a+(l+8)>>2]|0;if(p>>>0<m>>>0)Wa();m=p+12|0;if((c[m>>2]|0)!=(j|0))Wa();q=o+8|0;if((c[q>>2]|0)==(j|0)){c[m>>2]=o;c[q>>2]=p;k=o;break}else Wa()}while(0);if(n){m=c[a+(l+28)>>2]|0;o=5128+(m<<2)|0;if((j|0)==(c[o>>2]|0)){c[o>>2]=k;if(!k){c[1207]=c[1207]&~(1<<m);break}}else{if(n>>>0<(c[1210]|0)>>>0)Wa();m=n+16|0;if((c[m>>2]|0)==(j|0))c[m>>2]=k;else c[n+20>>2]=k;if(!k)break}j=c[1210]|0;if(k>>>0<j>>>0)Wa();c[k+24>>2]=n;m=c[a+(l+16)>>2]|0;do if(m)if(m>>>0<j>>>0)Wa();else{c[k+16>>2]=m;c[m+24>>2]=k;break}while(0);j=c[a+(l+20)>>2]|0;if(j)if(j>>>0<(c[1210]|0)>>>0)Wa();else{c[k+20>>2]=j;c[j+24>>2]=k;break}}}else{k=c[a+(l+8)>>2]|0;l=c[a+(l+12)>>2]|0;p=4864+(o<<1<<2)|0;if((k|0)!=(p|0)){if(k>>>0<m>>>0)Wa();if((c[k+12>>2]|0)!=(j|0))Wa()}if((l|0)==(k|0)){c[1206]=c[1206]&~(1<<o);break}if((l|0)!=(p|0)){if(l>>>0<m>>>0)Wa();m=l+8|0;if((c[m>>2]|0)==(j|0))n=m;else Wa()}else n=l+8|0;c[k+12>>2]=l;c[n>>2]=k}while(0);if(h>>>0<16){c[f>>2]=g|e&1|2;r=a+(g|4)|0;c[r>>2]=c[r>>2]|1;r=a;i=d;return r|0}else{c[f>>2]=e&1|b|2;c[a+(b+4)>>2]=h|3;r=a+(g|4)|0;c[r>>2]=c[r>>2]|1;ge(a+b|0,h);r=a;i=d;return r|0}return 0}function ge(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;d=i;h=a+b|0;l=c[a+4>>2]|0;do if(!(l&1)){p=c[a>>2]|0;if(!(l&3)){i=d;return}l=a+(0-p)|0;m=p+b|0;r=c[1210]|0;if(l>>>0<r>>>0)Wa();if((l|0)==(c[1211]|0)){e=a+(b+4)|0;n=c[e>>2]|0;if((n&3|0)!=3){e=l;n=m;break}c[1208]=m;c[e>>2]=n&-2;c[a+(4-p)>>2]=m|1;c[h>>2]=m;i=d;return}s=p>>>3;if(p>>>0<256){e=c[a+(8-p)>>2]|0;n=c[a+(12-p)>>2]|0;o=4864+(s<<1<<2)|0;if((e|0)!=(o|0)){if(e>>>0<r>>>0)Wa();if((c[e+12>>2]|0)!=(l|0))Wa()}if((n|0)==(e|0)){c[1206]=c[1206]&~(1<<s);e=l;n=m;break}if((n|0)!=(o|0)){if(n>>>0<r>>>0)Wa();o=n+8|0;if((c[o>>2]|0)==(l|0))q=o;else Wa()}else q=n+8|0;c[e+12>>2]=n;c[q>>2]=e;e=l;n=m;break}q=c[a+(24-p)>>2]|0;s=c[a+(12-p)>>2]|0;do if((s|0)==(l|0)){u=16-p|0;t=a+(u+4)|0;s=c[t>>2]|0;if(!s){t=a+u|0;s=c[t>>2]|0;if(!s){o=0;break}}while(1){v=s+20|0;u=c[v>>2]|0;if(u){s=u;t=v;continue}u=s+16|0;v=c[u>>2]|0;if(!v)break;else{s=v;t=u}}if(t>>>0<r>>>0)Wa();else{c[t>>2]=0;o=s;break}}else{t=c[a+(8-p)>>2]|0;if(t>>>0<r>>>0)Wa();r=t+12|0;if((c[r>>2]|0)!=(l|0))Wa();u=s+8|0;if((c[u>>2]|0)==(l|0)){c[r>>2]=s;c[u>>2]=t;o=s;break}else Wa()}while(0);if(q){s=c[a+(28-p)>>2]|0;r=5128+(s<<2)|0;if((l|0)==(c[r>>2]|0)){c[r>>2]=o;if(!o){c[1207]=c[1207]&~(1<<s);e=l;n=m;break}}else{if(q>>>0<(c[1210]|0)>>>0)Wa();r=q+16|0;if((c[r>>2]|0)==(l|0))c[r>>2]=o;else c[q+20>>2]=o;if(!o){e=l;n=m;break}}r=c[1210]|0;if(o>>>0<r>>>0)Wa();c[o+24>>2]=q;p=16-p|0;q=c[a+p>>2]|0;do if(q)if(q>>>0<r>>>0)Wa();else{c[o+16>>2]=q;c[q+24>>2]=o;break}while(0);p=c[a+(p+4)>>2]|0;if(p)if(p>>>0<(c[1210]|0)>>>0)Wa();else{c[o+20>>2]=p;c[p+24>>2]=o;e=l;n=m;break}else{e=l;n=m}}else{e=l;n=m}}else{e=a;n=b}while(0);l=c[1210]|0;if(h>>>0<l>>>0)Wa();m=a+(b+4)|0;o=c[m>>2]|0;if(!(o&2)){if((h|0)==(c[1212]|0)){v=(c[1209]|0)+n|0;c[1209]=v;c[1212]=e;c[e+4>>2]=v|1;if((e|0)!=(c[1211]|0)){i=d;return}c[1211]=0;c[1208]=0;i=d;return}if((h|0)==(c[1211]|0)){v=(c[1208]|0)+n|0;c[1208]=v;c[1211]=e;c[e+4>>2]=v|1;c[e+v>>2]=v;i=d;return}n=(o&-8)+n|0;m=o>>>3;do if(o>>>0>=256){k=c[a+(b+24)>>2]|0;o=c[a+(b+12)>>2]|0;do if((o|0)==(h|0)){o=a+(b+20)|0;m=c[o>>2]|0;if(!m){o=a+(b+16)|0;m=c[o>>2]|0;if(!m){j=0;break}}while(1){p=m+20|0;q=c[p>>2]|0;if(q){m=q;o=p;continue}q=m+16|0;p=c[q>>2]|0;if(!p)break;else{m=p;o=q}}if(o>>>0<l>>>0)Wa();else{c[o>>2]=0;j=m;break}}else{m=c[a+(b+8)>>2]|0;if(m>>>0<l>>>0)Wa();p=m+12|0;if((c[p>>2]|0)!=(h|0))Wa();l=o+8|0;if((c[l>>2]|0)==(h|0)){c[p>>2]=o;c[l>>2]=m;j=o;break}else Wa()}while(0);if(k){m=c[a+(b+28)>>2]|0;l=5128+(m<<2)|0;if((h|0)==(c[l>>2]|0)){c[l>>2]=j;if(!j){c[1207]=c[1207]&~(1<<m);break}}else{if(k>>>0<(c[1210]|0)>>>0)Wa();l=k+16|0;if((c[l>>2]|0)==(h|0))c[l>>2]=j;else c[k+20>>2]=j;if(!j)break}h=c[1210]|0;if(j>>>0<h>>>0)Wa();c[j+24>>2]=k;k=c[a+(b+16)>>2]|0;do if(k)if(k>>>0<h>>>0)Wa();else{c[j+16>>2]=k;c[k+24>>2]=j;break}while(0);h=c[a+(b+20)>>2]|0;if(h)if(h>>>0<(c[1210]|0)>>>0)Wa();else{c[j+20>>2]=h;c[h+24>>2]=j;break}}}else{j=c[a+(b+8)>>2]|0;a=c[a+(b+12)>>2]|0;b=4864+(m<<1<<2)|0;if((j|0)!=(b|0)){if(j>>>0<l>>>0)Wa();if((c[j+12>>2]|0)!=(h|0))Wa()}if((a|0)==(j|0)){c[1206]=c[1206]&~(1<<m);break}if((a|0)!=(b|0)){if(a>>>0<l>>>0)Wa();b=a+8|0;if((c[b>>2]|0)==(h|0))k=b;else Wa()}else k=a+8|0;c[j+12>>2]=a;c[k>>2]=j}while(0);c[e+4>>2]=n|1;c[e+n>>2]=n;if((e|0)==(c[1211]|0)){c[1208]=n;i=d;return}}else{c[m>>2]=o&-2;c[e+4>>2]=n|1;c[e+n>>2]=n}b=n>>>3;if(n>>>0<256){a=b<<1;h=4864+(a<<2)|0;j=c[1206]|0;b=1<<b;if(j&b){a=4864+(a+2<<2)|0;j=c[a>>2]|0;if(j>>>0<(c[1210]|0)>>>0)Wa();else{g=a;f=j}}else{c[1206]=j|b;g=4864+(a+2<<2)|0;f=h}c[g>>2]=e;c[f+12>>2]=e;c[e+8>>2]=f;c[e+12>>2]=h;i=d;return}f=n>>>8;if(f)if(n>>>0>16777215)f=31;else{u=(f+1048320|0)>>>16&8;v=f<<u;t=(v+520192|0)>>>16&4;v=v<<t;f=(v+245760|0)>>>16&2;f=14-(t|u|f)+(v<<f>>>15)|0;f=n>>>(f+7|0)&1|f<<1}else f=0;g=5128+(f<<2)|0;c[e+28>>2]=f;c[e+20>>2]=0;c[e+16>>2]=0;a=c[1207]|0;h=1<<f;if(!(a&h)){c[1207]=a|h;c[g>>2]=e;c[e+24>>2]=g;c[e+12>>2]=e;c[e+8>>2]=e;i=d;return}g=c[g>>2]|0;if((f|0)==31)f=0;else f=25-(f>>>1)|0;a:do if((c[g+4>>2]&-8|0)!=(n|0)){f=n<<f;a=g;while(1){h=a+(f>>>31<<2)+16|0;g=c[h>>2]|0;if(!g)break;if((c[g+4>>2]&-8|0)==(n|0))break a;else{f=f<<1;a=g}}if(h>>>0<(c[1210]|0)>>>0)Wa();c[h>>2]=e;c[e+24>>2]=a;c[e+12>>2]=e;c[e+8>>2]=e;i=d;return}while(0);f=g+8|0;h=c[f>>2]|0;v=c[1210]|0;if(!(g>>>0>=v>>>0&h>>>0>=v>>>0))Wa();c[h+12>>2]=e;c[f>>2]=e;c[e+8>>2]=h;c[e+12>>2]=g;c[e+24>>2]=0;i=d;return}function he(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;g=a+4|0;h=c[g>>2]|0;f=a+100|0;if(h>>>0<(c[f>>2]|0)>>>0){c[g>>2]=h+1;j=d[h>>0]|0}else j=Zd(a)|0;if((j|0)==43|(j|0)==45){k=c[g>>2]|0;h=(j|0)==45&1;if(k>>>0<(c[f>>2]|0)>>>0){c[g>>2]=k+1;j=d[k>>0]|0}else j=Zd(a)|0;if((j+ -48|0)>>>0>9&(b|0)!=0?(c[f>>2]|0)!=0:0)c[g>>2]=(c[g>>2]|0)+ -1}else h=0;if((j+ -48|0)>>>0>9){if(!(c[f>>2]|0)){j=-2147483648;k=0;F=j;i=e;return k|0}c[g>>2]=(c[g>>2]|0)+ -1;j=-2147483648;k=0;F=j;i=e;return k|0}else b=0;do{b=j+ -48+(b*10|0)|0;j=c[g>>2]|0;if(j>>>0<(c[f>>2]|0)>>>0){c[g>>2]=j+1;j=d[j>>0]|0}else j=Zd(a)|0}while((j+ -48|0)>>>0<10&(b|0)<214748364);k=((b|0)<0)<<31>>31;if((j+ -48|0)>>>0<10)do{k=we(b|0,k|0,10,0)|0;b=F;j=ne(j|0,((j|0)<0)<<31>>31|0,-48,-1)|0;b=ne(j|0,F|0,k|0,b|0)|0;k=F;j=c[g>>2]|0;if(j>>>0<(c[f>>2]|0)>>>0){c[g>>2]=j+1;j=d[j>>0]|0}else j=Zd(a)|0}while((j+ -48|0)>>>0<10&((k|0)<21474836|(k|0)==21474836&b>>>0<2061584302));if((j+ -48|0)>>>0<10)do{j=c[g>>2]|0;if(j>>>0<(c[f>>2]|0)>>>0){c[g>>2]=j+1;j=d[j>>0]|0}else j=Zd(a)|0}while((j+ -48|0)>>>0<10);if(c[f>>2]|0)c[g>>2]=(c[g>>2]|0)+ -1;g=(h|0)!=0;h=je(0,0,b|0,k|0)|0;j=g?F:k;k=g?h:b;F=j;i=e;return k|0}function ie(){}function je(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;b=b-d-(c>>>0>a>>>0|0)>>>0;return(F=b,a-c>>>0|0)|0}function ke(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=b+e|0;if((e|0)>=20){d=d&255;i=b&3;h=d|d<<8|d<<16|d<<24;g=f&~3;if(i){i=b+4-i|0;while((b|0)<(i|0)){a[b>>0]=d;b=b+1|0}}while((b|0)<(g|0)){c[b>>2]=h;b=b+4|0}}while((b|0)<(f|0)){a[b>>0]=d;b=b+1|0}return b-e|0}function le(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){F=b<<c|(a&(1<<c)-1<<32-c)>>>32-c;return a<<c}F=a<<c-32;return 0}function me(b){b=b|0;var c=0;c=b;while(a[c>>0]|0)c=c+1|0;return c-b|0}function ne(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;c=a+c>>>0;return(F=b+d+(c>>>0<a>>>0|0)>>>0,c|0)|0}function oe(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){F=b>>>c;return a>>>c|(b&(1<<c)-1)<<32-c}F=0;return b>>>c-32|0}function pe(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return Ca(b|0,d|0,e|0)|0;f=b|0;if((b&3)==(d&3)){while(b&3){if(!e)return f|0;a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function qe(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){F=b>>c;return a>>>c|(b&(1<<c)-1)<<32-c}F=(b|0)<0?-1:0;return b>>c-32|0}function re(b){b=b|0;var c=0;c=a[n+(b>>>24)>>0]|0;if((c|0)<8)return c|0;c=a[n+(b>>16&255)>>0]|0;if((c|0)<8)return c+8|0;c=a[n+(b>>8&255)>>0]|0;if((c|0)<8)return c+16|0;return(a[n+(b&255)>>0]|0)+24|0}function se(b){b=b|0;var c=0;c=a[m+(b&255)>>0]|0;if((c|0)<8)return c|0;c=a[m+(b>>8&255)>>0]|0;if((c|0)<8)return c+8|0;c=a[m+(b>>16&255)>>0]|0;if((c|0)<8)return c+16|0;return(a[m+(b>>>24)>>0]|0)+24|0}function te(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;f=a&65535;d=b&65535;c=ba(d,f)|0;e=a>>>16;d=(c>>>16)+(ba(d,e)|0)|0;b=b>>>16;a=ba(b,f)|0;return(F=(d>>>16)+(ba(b,e)|0)+(((d&65535)+a|0)>>>16)|0,d+a<<16|c&65535|0)|0}function ue(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;j=b>>31|((b|0)<0?-1:0)<<1;i=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;f=d>>31|((d|0)<0?-1:0)<<1;e=((d|0)<0?-1:0)>>31|((d|0)<0?-1:0)<<1;h=je(j^a,i^b,j,i)|0;g=F;b=f^j;a=e^i;a=je((ze(h,g,je(f^c,e^d,f,e)|0,F,0)|0)^b,F^a,b,a)|0;return a|0}function ve(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0;f=i;i=i+8|0;j=f|0;h=b>>31|((b|0)<0?-1:0)<<1;g=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;l=e>>31|((e|0)<0?-1:0)<<1;k=((e|0)<0?-1:0)>>31|((e|0)<0?-1:0)<<1;b=je(h^a,g^b,h,g)|0;a=F;ze(b,a,je(l^d,k^e,l,k)|0,F,j)|0;a=je(c[j>>2]^h,c[j+4>>2]^g,h,g)|0;b=F;i=f;return(F=b,a)|0}function we(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=a;f=c;a=te(e,f)|0;c=F;return(F=(ba(b,f)|0)+(ba(d,e)|0)+c|c&0,a|0|0)|0}function xe(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;a=ze(a,b,c,d,0)|0;return a|0}function ye(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;g=i;i=i+8|0;f=g|0;ze(a,b,d,e,f)|0;i=g;return(F=c[f+4>>2]|0,c[f>>2]|0)|0}function ze(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;h=a;j=b;i=j;l=d;g=e;k=g;if(!i){g=(f|0)!=0;if(!k){if(g){c[f>>2]=(h>>>0)%(l>>>0);c[f+4>>2]=0}k=0;m=(h>>>0)/(l>>>0)>>>0;return(F=k,m)|0}else{if(!g){l=0;m=0;return(F=l,m)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;l=0;m=0;return(F=l,m)|0}}m=(k|0)==0;do if(l){if(!m){k=(re(k|0)|0)-(re(i|0)|0)|0;if(k>>>0<=31){m=k+1|0;l=31-k|0;a=k-31>>31;j=m;b=h>>>(m>>>0)&a|i<<l;a=i>>>(m>>>0)&a;k=0;l=h<<l;break}if(!f){l=0;m=0;return(F=l,m)|0}c[f>>2]=a|0;c[f+4>>2]=j|b&0;l=0;m=0;return(F=l,m)|0}k=l-1|0;if(k&l){l=(re(l|0)|0)+33-(re(i|0)|0)|0;p=64-l|0;m=32-l|0;n=m>>31;o=l-32|0;a=o>>31;j=l;b=m-1>>31&i>>>(o>>>0)|(i<<m|h>>>(l>>>0))&a;a=a&i>>>(l>>>0);k=h<<p&n;l=(i<<p|h>>>(o>>>0))&n|h<<m&l-33>>31;break}if(f){c[f>>2]=k&h;c[f+4>>2]=0}if((l|0)==1){o=j|b&0;p=a|0|0;return(F=o,p)|0}else{p=se(l|0)|0;o=i>>>(p>>>0)|0;p=i<<32-p|h>>>(p>>>0)|0;return(F=o,p)|0}}else{if(m){if(f){c[f>>2]=(i>>>0)%(l>>>0);c[f+4>>2]=0}o=0;p=(i>>>0)/(l>>>0)>>>0;return(F=o,p)|0}if(!h){if(f){c[f>>2]=0;c[f+4>>2]=(i>>>0)%(k>>>0)}o=0;p=(i>>>0)/(k>>>0)>>>0;return(F=o,p)|0}l=k-1|0;if(!(l&k)){if(f){c[f>>2]=a|0;c[f+4>>2]=l&i|b&0}o=0;p=i>>>((se(k|0)|0)>>>0);return(F=o,p)|0}k=(re(k|0)|0)-(re(i|0)|0)|0;if(k>>>0<=30){a=k+1|0;l=31-k|0;j=a;b=i<<l|h>>>(a>>>0);a=i>>>(a>>>0);k=0;l=h<<l;break}if(!f){o=0;p=0;return(F=o,p)|0}c[f>>2]=a|0;c[f+4>>2]=j|b&0;o=0;p=0;return(F=o,p)|0}while(0);if(!j){g=l;e=0;i=0}else{h=d|0|0;g=g|e&0;e=ne(h,g,-1,-1)|0;d=F;i=0;do{m=l;l=k>>>31|l<<1;k=i|k<<1;m=b<<1|m>>>31|0;n=b>>>31|a<<1|0;je(e,d,m,n)|0;p=F;o=p>>31|((p|0)<0?-1:0)<<1;i=o&1;b=je(m,n,o&h,(((p|0)<0?-1:0)>>31|((p|0)<0?-1:0)<<1)&g)|0;a=F;j=j-1|0}while((j|0)!=0);g=l;e=0}h=0;if(f){c[f>>2]=b;c[f+4>>2]=a}o=(k|0)>>>31|(g|h)<<1|(h<<1|k>>>31)&0|e;p=(k<<1|0>>>31)&-2|i;return(F=o,p)|0}function Ae(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return eb[a&1](b|0,c|0,d|0)|0}function Be(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;fb[a&3](b|0,c|0,d|0,e|0,f|0)}function Ce(a,b){a=a|0;b=b|0;gb[a&31](b|0)}function De(a,b,c){a=a|0;b=b|0;c=c|0;hb[a&3](b|0,c|0)}function Ee(a,b){a=a|0;b=b|0;return ib[a&1](b|0)|0}function Fe(a){a=a|0;jb[a&3]()}function Ge(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;kb[a&3](b|0,c|0,d|0,e|0,f|0,g|0)}function He(a,b,c){a=a|0;b=b|0;c=c|0;return lb[a&3](b|0,c|0)|0}function Ie(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;mb[a&3](b|0,c|0,d|0,e|0)}function Je(a,b,c){a=a|0;b=b|0;c=c|0;ca(0);return 0}function Ke(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;ca(1)}function Le(a){a=a|0;ca(2)}function Me(a,b){a=a|0;b=b|0;ca(3)}function Ne(a){a=a|0;ca(4);return 0}function Oe(){ca(5)}function Pe(){bb()}function Qe(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;ca(6)}function Re(a,b){a=a|0;b=b|0;ca(7);return 0}function Se(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;ca(8)}\n\n\n\n\n// EMSCRIPTEN_END_FUNCS\n// (start of meteor/midamble.js)\n// This \"midamble\" is hacked into the output JS in a place\n// where it has access to the inner function generated\n// by Emscripten, the one that starts with \"use asm\".\n// NOTE: This doesn't work with minification on!\n/////setInnerMalloc = function (hookedMalloc) {\n/////  _malloc = hookedMalloc;\n/////};\n/////setInnerFree = function (hookedFree) {\n/////  _free = hookedFree;\n/////};\n// (end of meteor/midamble.js)\nvar eb=[Je,Dd];var fb=[Ke,Kd,Jd,Ke];var gb=[Le,wb,yb,Ab,Db,Ib,Hb,bc,dc,zc,yc,Oc,rd,qd,yd,Bd,zd,Ad,Cd,zb,Rd,Le,Le,Le,Le,Le,Le,Le,Le,Le,Le,Le];var hb=[Me,Cb,Fb,fc];var ib=[Ne,sd];var jb=[Oe,Pe,Pd,Qd];var kb=[Qe,Md,Ld,Qe];var lb=[Re,Bb,Eb,ec];var mb=[Se,Fd,Gd,Se];return{_yo:$c,_strlen:me,_retireVar:id,_bitshift64Lshr:oe,_unyo:ad,_solve:ed,_bitshift64Shl:le,_getSolution:fd,___cxa_is_pointer_type:Od,_memset:ke,_getNumVars:gd,_memcpy:pe,_getConflictClauseSize:jd,_addClause:dd,_i64Subtract:je,_createTheSolver:bd,_realloc:Ud,_i64Add:ne,_solveAssuming:hd,___cxa_can_catch:Nd,_ensureVar:cd,_getConflictClause:kd,_free:Td,_malloc:Sd,__GLOBAL__I_a:cc,__GLOBAL__I_a127:Pc,runPostSets:ie,stackAlloc:nb,stackSave:ob,stackRestore:pb,setThrew:qb,setTempRet0:tb,getTempRet0:ub,dynCall_iiii:Ae,dynCall_viiiii:Be,dynCall_vi:Ce,dynCall_vii:De,dynCall_ii:Ee,dynCall_v:Fe,dynCall_viiiiii:Ge,dynCall_iii:He,dynCall_viiii:Ie}})\n\n\n// EMSCRIPTEN_END_ASM\n(Module.asmGlobalArg,Module.asmLibraryArg,buffer);var _yo=Module[\"_yo\"]=asm[\"_yo\"];var _strlen=Module[\"_strlen\"]=asm[\"_strlen\"];var _retireVar=Module[\"_retireVar\"]=asm[\"_retireVar\"];var _bitshift64Lshr=Module[\"_bitshift64Lshr\"]=asm[\"_bitshift64Lshr\"];var _unyo=Module[\"_unyo\"]=asm[\"_unyo\"];var _solve=Module[\"_solve\"]=asm[\"_solve\"];var _bitshift64Shl=Module[\"_bitshift64Shl\"]=asm[\"_bitshift64Shl\"];var _getSolution=Module[\"_getSolution\"]=asm[\"_getSolution\"];var ___cxa_is_pointer_type=Module[\"___cxa_is_pointer_type\"]=asm[\"___cxa_is_pointer_type\"];var _memset=Module[\"_memset\"]=asm[\"_memset\"];var _getNumVars=Module[\"_getNumVars\"]=asm[\"_getNumVars\"];var _memcpy=Module[\"_memcpy\"]=asm[\"_memcpy\"];var _getConflictClauseSize=Module[\"_getConflictClauseSize\"]=asm[\"_getConflictClauseSize\"];var _addClause=Module[\"_addClause\"]=asm[\"_addClause\"];var _i64Subtract=Module[\"_i64Subtract\"]=asm[\"_i64Subtract\"];var _createTheSolver=Module[\"_createTheSolver\"]=asm[\"_createTheSolver\"];var _realloc=Module[\"_realloc\"]=asm[\"_realloc\"];var _i64Add=Module[\"_i64Add\"]=asm[\"_i64Add\"];var _solveAssuming=Module[\"_solveAssuming\"]=asm[\"_solveAssuming\"];var ___cxa_can_catch=Module[\"___cxa_can_catch\"]=asm[\"___cxa_can_catch\"];var _ensureVar=Module[\"_ensureVar\"]=asm[\"_ensureVar\"];var _getConflictClause=Module[\"_getConflictClause\"]=asm[\"_getConflictClause\"];var _free=Module[\"_free\"]=asm[\"_free\"];var _malloc=Module[\"_malloc\"]=asm[\"_malloc\"];var __GLOBAL__I_a=Module[\"__GLOBAL__I_a\"]=asm[\"__GLOBAL__I_a\"];var __GLOBAL__I_a127=Module[\"__GLOBAL__I_a127\"]=asm[\"__GLOBAL__I_a127\"];var runPostSets=Module[\"runPostSets\"]=asm[\"runPostSets\"];var dynCall_iiii=Module[\"dynCall_iiii\"]=asm[\"dynCall_iiii\"];var dynCall_viiiii=Module[\"dynCall_viiiii\"]=asm[\"dynCall_viiiii\"];var dynCall_vi=Module[\"dynCall_vi\"]=asm[\"dynCall_vi\"];var dynCall_vii=Module[\"dynCall_vii\"]=asm[\"dynCall_vii\"];var dynCall_ii=Module[\"dynCall_ii\"]=asm[\"dynCall_ii\"];var dynCall_v=Module[\"dynCall_v\"]=asm[\"dynCall_v\"];var dynCall_viiiiii=Module[\"dynCall_viiiiii\"]=asm[\"dynCall_viiiiii\"];var dynCall_iii=Module[\"dynCall_iii\"]=asm[\"dynCall_iii\"];var dynCall_viiii=Module[\"dynCall_viiii\"]=asm[\"dynCall_viiii\"];Runtime.stackAlloc=asm[\"stackAlloc\"];Runtime.stackSave=asm[\"stackSave\"];Runtime.stackRestore=asm[\"stackRestore\"];Runtime.setTempRet0=asm[\"setTempRet0\"];Runtime.getTempRet0=asm[\"getTempRet0\"];var i64Math=(function(){var goog={math:{}};goog.math.Long=(function(low,high){this.low_=low|0;this.high_=high|0});goog.math.Long.IntCache_={};goog.math.Long.fromInt=(function(value){if(-128<=value&&value<128){var cachedObj=goog.math.Long.IntCache_[value];if(cachedObj){return cachedObj}}var obj=new goog.math.Long(value|0,value<0?-1:0);if(-128<=value&&value<128){goog.math.Long.IntCache_[value]=obj}return obj});goog.math.Long.fromNumber=(function(value){if(isNaN(value)||!isFinite(value)){return goog.math.Long.ZERO}else if(value<=-goog.math.Long.TWO_PWR_63_DBL_){return goog.math.Long.MIN_VALUE}else if(value+1>=goog.math.Long.TWO_PWR_63_DBL_){return goog.math.Long.MAX_VALUE}else if(value<0){return goog.math.Long.fromNumber(-value).negate()}else{return new goog.math.Long(value%goog.math.Long.TWO_PWR_32_DBL_|0,value/goog.math.Long.TWO_PWR_32_DBL_|0)}});goog.math.Long.fromBits=(function(lowBits,highBits){return new goog.math.Long(lowBits,highBits)});goog.math.Long.fromString=(function(str,opt_radix){if(str.length==0){throw Error(\"number format error: empty string\")}var radix=opt_radix||10;if(radix<2||36<radix){throw Error(\"radix out of range: \"+radix)}if(str.charAt(0)==\"-\"){return goog.math.Long.fromString(str.substring(1),radix).negate()}else if(str.indexOf(\"-\")>=0){throw Error('number format error: interior \"-\" character: '+str)}var radixToPower=goog.math.Long.fromNumber(Math.pow(radix,8));var result=goog.math.Long.ZERO;for(var i=0;i<str.length;i+=8){var size=Math.min(8,str.length-i);var value=parseInt(str.substring(i,i+size),radix);if(size<8){var power=goog.math.Long.fromNumber(Math.pow(radix,size));result=result.multiply(power).add(goog.math.Long.fromNumber(value))}else{result=result.multiply(radixToPower);result=result.add(goog.math.Long.fromNumber(value))}}return result});goog.math.Long.TWO_PWR_16_DBL_=1<<16;goog.math.Long.TWO_PWR_24_DBL_=1<<24;goog.math.Long.TWO_PWR_32_DBL_=goog.math.Long.TWO_PWR_16_DBL_*goog.math.Long.TWO_PWR_16_DBL_;goog.math.Long.TWO_PWR_31_DBL_=goog.math.Long.TWO_PWR_32_DBL_/2;goog.math.Long.TWO_PWR_48_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_16_DBL_;goog.math.Long.TWO_PWR_64_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_32_DBL_;goog.math.Long.TWO_PWR_63_DBL_=goog.math.Long.TWO_PWR_64_DBL_/2;goog.math.Long.ZERO=goog.math.Long.fromInt(0);goog.math.Long.ONE=goog.math.Long.fromInt(1);goog.math.Long.NEG_ONE=goog.math.Long.fromInt(-1);goog.math.Long.MAX_VALUE=goog.math.Long.fromBits(4294967295|0,2147483647|0);goog.math.Long.MIN_VALUE=goog.math.Long.fromBits(0,2147483648|0);goog.math.Long.TWO_PWR_24_=goog.math.Long.fromInt(1<<24);goog.math.Long.prototype.toInt=(function(){return this.low_});goog.math.Long.prototype.toNumber=(function(){return this.high_*goog.math.Long.TWO_PWR_32_DBL_+this.getLowBitsUnsigned()});goog.math.Long.prototype.toString=(function(opt_radix){var radix=opt_radix||10;if(radix<2||36<radix){throw Error(\"radix out of range: \"+radix)}if(this.isZero()){return\"0\"}if(this.isNegative()){if(this.equals(goog.math.Long.MIN_VALUE)){var radixLong=goog.math.Long.fromNumber(radix);var div=this.div(radixLong);var rem=div.multiply(radixLong).subtract(this);return div.toString(radix)+rem.toInt().toString(radix)}else{return\"-\"+this.negate().toString(radix)}}var radixToPower=goog.math.Long.fromNumber(Math.pow(radix,6));var rem=this;var result=\"\";while(true){var remDiv=rem.div(radixToPower);var intval=rem.subtract(remDiv.multiply(radixToPower)).toInt();var digits=intval.toString(radix);rem=remDiv;if(rem.isZero()){return digits+result}else{while(digits.length<6){digits=\"0\"+digits}result=\"\"+digits+result}}});goog.math.Long.prototype.getHighBits=(function(){return this.high_});goog.math.Long.prototype.getLowBits=(function(){return this.low_});goog.math.Long.prototype.getLowBitsUnsigned=(function(){return this.low_>=0?this.low_:goog.math.Long.TWO_PWR_32_DBL_+this.low_});goog.math.Long.prototype.getNumBitsAbs=(function(){if(this.isNegative()){if(this.equals(goog.math.Long.MIN_VALUE)){return 64}else{return this.negate().getNumBitsAbs()}}else{var val=this.high_!=0?this.high_:this.low_;for(var bit=31;bit>0;bit--){if((val&1<<bit)!=0){break}}return this.high_!=0?bit+33:bit+1}});goog.math.Long.prototype.isZero=(function(){return this.high_==0&&this.low_==0});goog.math.Long.prototype.isNegative=(function(){return this.high_<0});goog.math.Long.prototype.isOdd=(function(){return(this.low_&1)==1});goog.math.Long.prototype.equals=(function(other){return this.high_==other.high_&&this.low_==other.low_});goog.math.Long.prototype.notEquals=(function(other){return this.high_!=other.high_||this.low_!=other.low_});goog.math.Long.prototype.lessThan=(function(other){return this.compare(other)<0});goog.math.Long.prototype.lessThanOrEqual=(function(other){return this.compare(other)<=0});goog.math.Long.prototype.greaterThan=(function(other){return this.compare(other)>0});goog.math.Long.prototype.greaterThanOrEqual=(function(other){return this.compare(other)>=0});goog.math.Long.prototype.compare=(function(other){if(this.equals(other)){return 0}var thisNeg=this.isNegative();var otherNeg=other.isNegative();if(thisNeg&&!otherNeg){return-1}if(!thisNeg&&otherNeg){return 1}if(this.subtract(other).isNegative()){return-1}else{return 1}});goog.math.Long.prototype.negate=(function(){if(this.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.MIN_VALUE}else{return this.not().add(goog.math.Long.ONE)}});goog.math.Long.prototype.add=(function(other){var a48=this.high_>>>16;var a32=this.high_&65535;var a16=this.low_>>>16;var a00=this.low_&65535;var b48=other.high_>>>16;var b32=other.high_&65535;var b16=other.low_>>>16;var b00=other.low_&65535;var c48=0,c32=0,c16=0,c00=0;c00+=a00+b00;c16+=c00>>>16;c00&=65535;c16+=a16+b16;c32+=c16>>>16;c16&=65535;c32+=a32+b32;c48+=c32>>>16;c32&=65535;c48+=a48+b48;c48&=65535;return goog.math.Long.fromBits(c16<<16|c00,c48<<16|c32)});goog.math.Long.prototype.subtract=(function(other){return this.add(other.negate())});goog.math.Long.prototype.multiply=(function(other){if(this.isZero()){return goog.math.Long.ZERO}else if(other.isZero()){return goog.math.Long.ZERO}if(this.equals(goog.math.Long.MIN_VALUE)){return other.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO}else if(other.equals(goog.math.Long.MIN_VALUE)){return this.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO}if(this.isNegative()){if(other.isNegative()){return this.negate().multiply(other.negate())}else{return this.negate().multiply(other).negate()}}else if(other.isNegative()){return this.multiply(other.negate()).negate()}if(this.lessThan(goog.math.Long.TWO_PWR_24_)&&other.lessThan(goog.math.Long.TWO_PWR_24_)){return goog.math.Long.fromNumber(this.toNumber()*other.toNumber())}var a48=this.high_>>>16;var a32=this.high_&65535;var a16=this.low_>>>16;var a00=this.low_&65535;var b48=other.high_>>>16;var b32=other.high_&65535;var b16=other.low_>>>16;var b00=other.low_&65535;var c48=0,c32=0,c16=0,c00=0;c00+=a00*b00;c16+=c00>>>16;c00&=65535;c16+=a16*b00;c32+=c16>>>16;c16&=65535;c16+=a00*b16;c32+=c16>>>16;c16&=65535;c32+=a32*b00;c48+=c32>>>16;c32&=65535;c32+=a16*b16;c48+=c32>>>16;c32&=65535;c32+=a00*b32;c48+=c32>>>16;c32&=65535;c48+=a48*b00+a32*b16+a16*b32+a00*b48;c48&=65535;return goog.math.Long.fromBits(c16<<16|c00,c48<<16|c32)});goog.math.Long.prototype.div=(function(other){if(other.isZero()){throw Error(\"division by zero\")}else if(this.isZero()){return goog.math.Long.ZERO}if(this.equals(goog.math.Long.MIN_VALUE)){if(other.equals(goog.math.Long.ONE)||other.equals(goog.math.Long.NEG_ONE)){return goog.math.Long.MIN_VALUE}else if(other.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.ONE}else{var halfThis=this.shiftRight(1);var approx=halfThis.div(other).shiftLeft(1);if(approx.equals(goog.math.Long.ZERO)){return other.isNegative()?goog.math.Long.ONE:goog.math.Long.NEG_ONE}else{var rem=this.subtract(other.multiply(approx));var result=approx.add(rem.div(other));return result}}}else if(other.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.ZERO}if(this.isNegative()){if(other.isNegative()){return this.negate().div(other.negate())}else{return this.negate().div(other).negate()}}else if(other.isNegative()){return this.div(other.negate()).negate()}var res=goog.math.Long.ZERO;var rem=this;while(rem.greaterThanOrEqual(other)){var approx=Math.max(1,Math.floor(rem.toNumber()/other.toNumber()));var log2=Math.ceil(Math.log(approx)/Math.LN2);var delta=log2<=48?1:Math.pow(2,log2-48);var approxRes=goog.math.Long.fromNumber(approx);var approxRem=approxRes.multiply(other);while(approxRem.isNegative()||approxRem.greaterThan(rem)){approx-=delta;approxRes=goog.math.Long.fromNumber(approx);approxRem=approxRes.multiply(other)}if(approxRes.isZero()){approxRes=goog.math.Long.ONE}res=res.add(approxRes);rem=rem.subtract(approxRem)}return res});goog.math.Long.prototype.modulo=(function(other){return this.subtract(this.div(other).multiply(other))});goog.math.Long.prototype.not=(function(){return goog.math.Long.fromBits(~this.low_,~this.high_)});goog.math.Long.prototype.and=(function(other){return goog.math.Long.fromBits(this.low_&other.low_,this.high_&other.high_)});goog.math.Long.prototype.or=(function(other){return goog.math.Long.fromBits(this.low_|other.low_,this.high_|other.high_)});goog.math.Long.prototype.xor=(function(other){return goog.math.Long.fromBits(this.low_^other.low_,this.high_^other.high_)});goog.math.Long.prototype.shiftLeft=(function(numBits){numBits&=63;if(numBits==0){return this}else{var low=this.low_;if(numBits<32){var high=this.high_;return goog.math.Long.fromBits(low<<numBits,high<<numBits|low>>>32-numBits)}else{return goog.math.Long.fromBits(0,low<<numBits-32)}}});goog.math.Long.prototype.shiftRight=(function(numBits){numBits&=63;if(numBits==0){return this}else{var high=this.high_;if(numBits<32){var low=this.low_;return goog.math.Long.fromBits(low>>>numBits|high<<32-numBits,high>>numBits)}else{return goog.math.Long.fromBits(high>>numBits-32,high>=0?0:-1)}}});goog.math.Long.prototype.shiftRightUnsigned=(function(numBits){numBits&=63;if(numBits==0){return this}else{var high=this.high_;if(numBits<32){var low=this.low_;return goog.math.Long.fromBits(low>>>numBits|high<<32-numBits,high>>>numBits)}else if(numBits==32){return goog.math.Long.fromBits(high,0)}else{return goog.math.Long.fromBits(high>>>numBits-32,0)}}});var navigator={appName:\"Modern Browser\"};var dbits;var canary=0xdeadbeefcafe;var j_lm=(canary&16777215)==15715070;function BigInteger(a,b,c){if(a!=null)if(\"number\"==typeof a)this.fromNumber(a,b,c);else if(b==null&&\"string\"!=typeof a)this.fromString(a,256);else this.fromString(a,b)}function nbi(){return new BigInteger(null)}function am1(i,x,w,j,c,n){while(--n>=0){var v=x*this[i++]+w[j]+c;c=Math.floor(v/67108864);w[j++]=v&67108863}return c}function am2(i,x,w,j,c,n){var xl=x&32767,xh=x>>15;while(--n>=0){var l=this[i]&32767;var h=this[i++]>>15;var m=xh*l+h*xl;l=xl*l+((m&32767)<<15)+w[j]+(c&1073741823);c=(l>>>30)+(m>>>15)+xh*h+(c>>>30);w[j++]=l&1073741823}return c}function am3(i,x,w,j,c,n){var xl=x&16383,xh=x>>14;while(--n>=0){var l=this[i]&16383;var h=this[i++]>>14;var m=xh*l+h*xl;l=xl*l+((m&16383)<<14)+w[j]+c;c=(l>>28)+(m>>14)+xh*h;w[j++]=l&268435455}return c}if(j_lm&&navigator.appName==\"Microsoft Internet Explorer\"){BigInteger.prototype.am=am2;dbits=30}else if(j_lm&&navigator.appName!=\"Netscape\"){BigInteger.prototype.am=am1;dbits=26}else{BigInteger.prototype.am=am3;dbits=28}BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=(1<<dbits)-1;BigInteger.prototype.DV=1<<dbits;var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP);BigInteger.prototype.F1=BI_FP-dbits;BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM=\"0123456789abcdefghijklmnopqrstuvwxyz\";var BI_RC=new Array;var rr,vv;rr=\"0\".charCodeAt(0);for(vv=0;vv<=9;++vv)BI_RC[rr++]=vv;rr=\"a\".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;rr=\"A\".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;function int2char(n){return BI_RM.charAt(n)}function intAt(s,i){var c=BI_RC[s.charCodeAt(i)];return c==null?-1:c}function bnpCopyTo(r){for(var i=this.t-1;i>=0;--i)r[i]=this[i];r.t=this.t;r.s=this.s}function bnpFromInt(x){this.t=1;this.s=x<0?-1:0;if(x>0)this[0]=x;else if(x<-1)this[0]=x+DV;else this.t=0}function nbv(i){var r=nbi();r.fromInt(i);return r}function bnpFromString(s,b){var k;if(b==16)k=4;else if(b==8)k=3;else if(b==256)k=8;else if(b==2)k=1;else if(b==32)k=5;else if(b==4)k=2;else{this.fromRadix(s,b);return}this.t=0;this.s=0;var i=s.length,mi=false,sh=0;while(--i>=0){var x=k==8?s[i]&255:intAt(s,i);if(x<0){if(s.charAt(i)==\"-\")mi=true;continue}mi=false;if(sh==0)this[this.t++]=x;else if(sh+k>this.DB){this[this.t-1]|=(x&(1<<this.DB-sh)-1)<<sh;this[this.t++]=x>>this.DB-sh}else this[this.t-1]|=x<<sh;sh+=k;if(sh>=this.DB)sh-=this.DB}if(k==8&&(s[0]&128)!=0){this.s=-1;if(sh>0)this[this.t-1]|=(1<<this.DB-sh)-1<<sh}this.clamp();if(mi)BigInteger.ZERO.subTo(this,this)}function bnpClamp(){var c=this.s&this.DM;while(this.t>0&&this[this.t-1]==c)--this.t}function bnToString(b){if(this.s<0)return\"-\"+this.negate().toString(b);var k;if(b==16)k=4;else if(b==8)k=3;else if(b==2)k=1;else if(b==32)k=5;else if(b==4)k=2;else return this.toRadix(b);var km=(1<<k)-1,d,m=false,r=\"\",i=this.t;var p=this.DB-i*this.DB%k;if(i-->0){if(p<this.DB&&(d=this[i]>>p)>0){m=true;r=int2char(d)}while(i>=0){if(p<k){d=(this[i]&(1<<p)-1)<<k-p;d|=this[--i]>>(p+=this.DB-k)}else{d=this[i]>>(p-=k)&km;if(p<=0){p+=this.DB;--i}}if(d>0)m=true;if(m)r+=int2char(d)}}return m?r:\"0\"}function bnNegate(){var r=nbi();BigInteger.ZERO.subTo(this,r);return r}function bnAbs(){return this.s<0?this.negate():this}function bnCompareTo(a){var r=this.s-a.s;if(r!=0)return r;var i=this.t;r=i-a.t;if(r!=0)return this.s<0?-r:r;while(--i>=0)if((r=this[i]-a[i])!=0)return r;return 0}function nbits(x){var r=1,t;if((t=x>>>16)!=0){x=t;r+=16}if((t=x>>8)!=0){x=t;r+=8}if((t=x>>4)!=0){x=t;r+=4}if((t=x>>2)!=0){x=t;r+=2}if((t=x>>1)!=0){x=t;r+=1}return r}function bnBitLength(){if(this.t<=0)return 0;return this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(n,r){var i;for(i=this.t-1;i>=0;--i)r[i+n]=this[i];for(i=n-1;i>=0;--i)r[i]=0;r.t=this.t+n;r.s=this.s}function bnpDRShiftTo(n,r){for(var i=n;i<this.t;++i)r[i-n]=this[i];r.t=Math.max(this.t-n,0);r.s=this.s}function bnpLShiftTo(n,r){var bs=n%this.DB;var cbs=this.DB-bs;var bm=(1<<cbs)-1;var ds=Math.floor(n/this.DB),c=this.s<<bs&this.DM,i;for(i=this.t-1;i>=0;--i){r[i+ds+1]=this[i]>>cbs|c;c=(this[i]&bm)<<bs}for(i=ds-1;i>=0;--i)r[i]=0;r[ds]=c;r.t=this.t+ds+1;r.s=this.s;r.clamp()}function bnpRShiftTo(n,r){r.s=this.s;var ds=Math.floor(n/this.DB);if(ds>=this.t){r.t=0;return}var bs=n%this.DB;var cbs=this.DB-bs;var bm=(1<<bs)-1;r[0]=this[ds]>>bs;for(var i=ds+1;i<this.t;++i){r[i-ds-1]|=(this[i]&bm)<<cbs;r[i-ds]=this[i]>>bs}if(bs>0)r[this.t-ds-1]|=(this.s&bm)<<cbs;r.t=this.t-ds;r.clamp()}function bnpSubTo(a,r){var i=0,c=0,m=Math.min(a.t,this.t);while(i<m){c+=this[i]-a[i];r[i++]=c&this.DM;c>>=this.DB}if(a.t<this.t){c-=a.s;while(i<this.t){c+=this[i];r[i++]=c&this.DM;c>>=this.DB}c+=this.s}else{c+=this.s;while(i<a.t){c-=a[i];r[i++]=c&this.DM;c>>=this.DB}c-=a.s}r.s=c<0?-1:0;if(c<-1)r[i++]=this.DV+c;else if(c>0)r[i++]=c;r.t=i;r.clamp()}function bnpMultiplyTo(a,r){var x=this.abs(),y=a.abs();var i=x.t;r.t=i+y.t;while(--i>=0)r[i]=0;for(i=0;i<y.t;++i)r[i+x.t]=x.am(0,y[i],r,i,0,x.t);r.s=0;r.clamp();if(this.s!=a.s)BigInteger.ZERO.subTo(r,r)}function bnpSquareTo(r){var x=this.abs();var i=r.t=2*x.t;while(--i>=0)r[i]=0;for(i=0;i<x.t-1;++i){var c=x.am(i,x[i],r,2*i,0,1);if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1))>=x.DV){r[i+x.t]-=x.DV;r[i+x.t+1]=1}}if(r.t>0)r[r.t-1]+=x.am(i,x[i],r,2*i,0,1);r.s=0;r.clamp()}function bnpDivRemTo(m,q,r){var pm=m.abs();if(pm.t<=0)return;var pt=this.abs();if(pt.t<pm.t){if(q!=null)q.fromInt(0);if(r!=null)this.copyTo(r);return}if(r==null)r=nbi();var y=nbi(),ts=this.s,ms=m.s;var nsh=this.DB-nbits(pm[pm.t-1]);if(nsh>0){pm.lShiftTo(nsh,y);pt.lShiftTo(nsh,r)}else{pm.copyTo(y);pt.copyTo(r)}var ys=y.t;var y0=y[ys-1];if(y0==0)return;var yt=y0*(1<<this.F1)+(ys>1?y[ys-2]>>this.F2:0);var d1=this.FV/yt,d2=(1<<this.F1)/yt,e=1<<this.F2;var i=r.t,j=i-ys,t=q==null?nbi():q;y.dlShiftTo(j,t);if(r.compareTo(t)>=0){r[r.t++]=1;r.subTo(t,r)}BigInteger.ONE.dlShiftTo(ys,t);t.subTo(y,y);while(y.t<ys)y[y.t++]=0;while(--j>=0){var qd=r[--i]==y0?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);if((r[i]+=y.am(0,qd,r,j,0,ys))<qd){y.dlShiftTo(j,t);r.subTo(t,r);while(r[i]<--qd)r.subTo(t,r)}}if(q!=null){r.drShiftTo(ys,q);if(ts!=ms)BigInteger.ZERO.subTo(q,q)}r.t=ys;r.clamp();if(nsh>0)r.rShiftTo(nsh,r);if(ts<0)BigInteger.ZERO.subTo(r,r)}function bnMod(a){var r=nbi();this.abs().divRemTo(a,null,r);if(this.s<0&&r.compareTo(BigInteger.ZERO)>0)a.subTo(r,r);return r}function Classic(m){this.m=m}function cConvert(x){if(x.s<0||x.compareTo(this.m)>=0)return x.mod(this.m);else return x}function cRevert(x){return x}function cReduce(x){x.divRemTo(this.m,null,x)}function cMulTo(x,y,r){x.multiplyTo(y,r);this.reduce(r)}function cSqrTo(x,r){x.squareTo(r);this.reduce(r)}Classic.prototype.convert=cConvert;Classic.prototype.revert=cRevert;Classic.prototype.reduce=cReduce;Classic.prototype.mulTo=cMulTo;Classic.prototype.sqrTo=cSqrTo;function bnpInvDigit(){if(this.t<1)return 0;var x=this[0];if((x&1)==0)return 0;var y=x&3;y=y*(2-(x&15)*y)&15;y=y*(2-(x&255)*y)&255;y=y*(2-((x&65535)*y&65535))&65535;y=y*(2-x*y%this.DV)%this.DV;return y>0?this.DV-y:-y}function Montgomery(m){this.m=m;this.mp=m.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<<m.DB-15)-1;this.mt2=2*m.t}function montConvert(x){var r=nbi();x.abs().dlShiftTo(this.m.t,r);r.divRemTo(this.m,null,r);if(x.s<0&&r.compareTo(BigInteger.ZERO)>0)this.m.subTo(r,r);return r}function montRevert(x){var r=nbi();x.copyTo(r);this.reduce(r);return r}function montReduce(x){while(x.t<=this.mt2)x[x.t++]=0;for(var i=0;i<this.m.t;++i){var j=x[i]&32767;var u0=j*this.mpl+((j*this.mph+(x[i]>>15)*this.mpl&this.um)<<15)&x.DM;j=i+this.m.t;x[j]+=this.m.am(0,u0,x,i,0,this.m.t);while(x[j]>=x.DV){x[j]-=x.DV;x[++j]++}}x.clamp();x.drShiftTo(this.m.t,x);if(x.compareTo(this.m)>=0)x.subTo(this.m,x)}function montSqrTo(x,r){x.squareTo(r);this.reduce(r)}function montMulTo(x,y,r){x.multiplyTo(y,r);this.reduce(r)}Montgomery.prototype.convert=montConvert;Montgomery.prototype.revert=montRevert;Montgomery.prototype.reduce=montReduce;Montgomery.prototype.mulTo=montMulTo;Montgomery.prototype.sqrTo=montSqrTo;function bnpIsEven(){return(this.t>0?this[0]&1:this.s)==0}function bnpExp(e,z){if(e>4294967295||e<1)return BigInteger.ONE;var r=nbi(),r2=nbi(),g=z.convert(this),i=nbits(e)-1;g.copyTo(r);while(--i>=0){z.sqrTo(r,r2);if((e&1<<i)>0)z.mulTo(r2,g,r);else{var t=r;r=r2;r2=t}}return z.revert(r)}function bnModPowInt(e,m){var z;if(e<256||m.isEven())z=new Classic(m);else z=new Montgomery(m);return this.exp(e,z)}BigInteger.prototype.copyTo=bnpCopyTo;BigInteger.prototype.fromInt=bnpFromInt;BigInteger.prototype.fromString=bnpFromString;BigInteger.prototype.clamp=bnpClamp;BigInteger.prototype.dlShiftTo=bnpDLShiftTo;BigInteger.prototype.drShiftTo=bnpDRShiftTo;BigInteger.prototype.lShiftTo=bnpLShiftTo;BigInteger.prototype.rShiftTo=bnpRShiftTo;BigInteger.prototype.subTo=bnpSubTo;BigInteger.prototype.multiplyTo=bnpMultiplyTo;BigInteger.prototype.squareTo=bnpSquareTo;BigInteger.prototype.divRemTo=bnpDivRemTo;BigInteger.prototype.invDigit=bnpInvDigit;BigInteger.prototype.isEven=bnpIsEven;BigInteger.prototype.exp=bnpExp;BigInteger.prototype.toString=bnToString;BigInteger.prototype.negate=bnNegate;BigInteger.prototype.abs=bnAbs;BigInteger.prototype.compareTo=bnCompareTo;BigInteger.prototype.bitLength=bnBitLength;BigInteger.prototype.mod=bnMod;BigInteger.prototype.modPowInt=bnModPowInt;BigInteger.ZERO=nbv(0);BigInteger.ONE=nbv(1);function bnpFromRadix(s,b){this.fromInt(0);if(b==null)b=10;var cs=this.chunkSize(b);var d=Math.pow(b,cs),mi=false,j=0,w=0;for(var i=0;i<s.length;++i){var x=intAt(s,i);if(x<0){if(s.charAt(i)==\"-\"&&this.signum()==0)mi=true;continue}w=b*w+x;if(++j>=cs){this.dMultiply(d);this.dAddOffset(w,0);j=0;w=0}}if(j>0){this.dMultiply(Math.pow(b,j));this.dAddOffset(w,0)}if(mi)BigInteger.ZERO.subTo(this,this)}function bnpChunkSize(r){return Math.floor(Math.LN2*this.DB/Math.log(r))}function bnSigNum(){if(this.s<0)return-1;else if(this.t<=0||this.t==1&&this[0]<=0)return 0;else return 1}function bnpDMultiply(n){this[this.t]=this.am(0,n-1,this,0,0,this.t);++this.t;this.clamp()}function bnpDAddOffset(n,w){if(n==0)return;while(this.t<=w)this[this.t++]=0;this[w]+=n;while(this[w]>=this.DV){this[w]-=this.DV;if(++w>=this.t)this[this.t++]=0;++this[w]}}function bnpToRadix(b){if(b==null)b=10;if(this.signum()==0||b<2||b>36)return\"0\";var cs=this.chunkSize(b);var a=Math.pow(b,cs);var d=nbv(a),y=nbi(),z=nbi(),r=\"\";this.divRemTo(d,y,z);while(y.signum()>0){r=(a+z.intValue()).toString(b).substr(1)+r;y.divRemTo(d,y,z)}return z.intValue().toString(b)+r}function bnIntValue(){if(this.s<0){if(this.t==1)return this[0]-this.DV;else if(this.t==0)return-1}else if(this.t==1)return this[0];else if(this.t==0)return 0;return(this[1]&(1<<32-this.DB)-1)<<this.DB|this[0]}function bnpAddTo(a,r){var i=0,c=0,m=Math.min(a.t,this.t);while(i<m){c+=this[i]+a[i];r[i++]=c&this.DM;c>>=this.DB}if(a.t<this.t){c+=a.s;while(i<this.t){c+=this[i];r[i++]=c&this.DM;c>>=this.DB}c+=this.s}else{c+=this.s;while(i<a.t){c+=a[i];r[i++]=c&this.DM;c>>=this.DB}c+=a.s}r.s=c<0?-1:0;if(c>0)r[i++]=c;else if(c<-1)r[i++]=this.DV+c;r.t=i;r.clamp()}BigInteger.prototype.fromRadix=bnpFromRadix;BigInteger.prototype.chunkSize=bnpChunkSize;BigInteger.prototype.signum=bnSigNum;BigInteger.prototype.dMultiply=bnpDMultiply;BigInteger.prototype.dAddOffset=bnpDAddOffset;BigInteger.prototype.toRadix=bnpToRadix;BigInteger.prototype.intValue=bnIntValue;BigInteger.prototype.addTo=bnpAddTo;var Wrapper={abs:(function(l,h){var x=new goog.math.Long(l,h);var ret;if(x.isNegative()){ret=x.negate()}else{ret=x}HEAP32[tempDoublePtr>>2]=ret.low_;HEAP32[tempDoublePtr+4>>2]=ret.high_}),ensureTemps:(function(){if(Wrapper.ensuredTemps)return;Wrapper.ensuredTemps=true;Wrapper.two32=new BigInteger;Wrapper.two32.fromString(\"4294967296\",10);Wrapper.two64=new BigInteger;Wrapper.two64.fromString(\"18446744073709551616\",10);Wrapper.temp1=new BigInteger;Wrapper.temp2=new BigInteger}),lh2bignum:(function(l,h){var a=new BigInteger;a.fromString(h.toString(),10);var b=new BigInteger;a.multiplyTo(Wrapper.two32,b);var c=new BigInteger;c.fromString(l.toString(),10);var d=new BigInteger;c.addTo(b,d);return d}),stringify:(function(l,h,unsigned){var ret=(new goog.math.Long(l,h)).toString();if(unsigned&&ret[0]==\"-\"){Wrapper.ensureTemps();var bignum=new BigInteger;bignum.fromString(ret,10);ret=new BigInteger;Wrapper.two64.addTo(bignum,ret);ret=ret.toString(10)}return ret}),fromString:(function(str,base,min,max,unsigned){Wrapper.ensureTemps();var bignum=new BigInteger;bignum.fromString(str,base);var bigmin=new BigInteger;bigmin.fromString(min,10);var bigmax=new BigInteger;bigmax.fromString(max,10);if(unsigned&&bignum.compareTo(BigInteger.ZERO)<0){var temp=new BigInteger;bignum.addTo(Wrapper.two64,temp);bignum=temp}var error=false;if(bignum.compareTo(bigmin)<0){bignum=bigmin;error=true}else if(bignum.compareTo(bigmax)>0){bignum=bigmax;error=true}var ret=goog.math.Long.fromString(bignum.toString());HEAP32[tempDoublePtr>>2]=ret.low_;HEAP32[tempDoublePtr+4>>2]=ret.high_;if(error)throw\"range error\"})};return Wrapper})();if(memoryInitializer){if(typeof Module[\"locateFile\"]===\"function\"){memoryInitializer=Module[\"locateFile\"](memoryInitializer)}else if(Module[\"memoryInitializerPrefixURL\"]){memoryInitializer=Module[\"memoryInitializerPrefixURL\"]+memoryInitializer}if(ENVIRONMENT_IS_NODE||ENVIRONMENT_IS_SHELL){var data=Module[\"readBinary\"](memoryInitializer);HEAPU8.set(data,STATIC_BASE)}else{addRunDependency(\"memory initializer\");Browser.asyncLoad(memoryInitializer,(function(data){HEAPU8.set(data,STATIC_BASE);removeRunDependency(\"memory initializer\")}),(function(data){throw\"could not load memory initializer \"+memoryInitializer}))}}function ExitStatus(status){this.name=\"ExitStatus\";this.message=\"Program terminated with exit(\"+status+\")\";this.status=status}ExitStatus.prototype=new Error;ExitStatus.prototype.constructor=ExitStatus;var initialStackTop;var preloadStartTime=null;var calledMain=false;dependenciesFulfilled=function runCaller(){if(!Module[\"calledRun\"]&&shouldRunNow)run();if(!Module[\"calledRun\"])dependenciesFulfilled=runCaller};Module[\"callMain\"]=Module.callMain=function callMain(args){assert(runDependencies==0,\"cannot call main when async dependencies remain! (listen on __ATMAIN__)\");assert(__ATPRERUN__.length==0,\"cannot call main when preRun functions remain to be called\");args=args||[];ensureInitRuntime();var argc=args.length+1;function pad(){for(var i=0;i<4-1;i++){argv.push(0)}}var argv=[allocate(intArrayFromString(Module[\"thisProgram\"]),\"i8\",ALLOC_NORMAL)];pad();for(var i=0;i<argc-1;i=i+1){argv.push(allocate(intArrayFromString(args[i]),\"i8\",ALLOC_NORMAL));pad()}argv.push(0);argv=allocate(argv,\"i32\",ALLOC_NORMAL);initialStackTop=STACKTOP;try{var ret=Module[\"_main\"](argc,argv,0);exit(ret)}catch(e){if(e instanceof ExitStatus){return}else if(e==\"SimulateInfiniteLoop\"){Module[\"noExitRuntime\"]=true;return}else{if(e&&typeof e===\"object\"&&e.stack)Module.printErr(\"exception thrown: \"+[e,e.stack]);throw e}}finally{calledMain=true}};function run(args){args=args||Module[\"arguments\"];if(preloadStartTime===null)preloadStartTime=Date.now();if(runDependencies>0){return}preRun();if(runDependencies>0)return;if(Module[\"calledRun\"])return;function doRun(){if(Module[\"calledRun\"])return;Module[\"calledRun\"]=true;if(ABORT)return;ensureInitRuntime();preMain();if(ENVIRONMENT_IS_WEB&&preloadStartTime!==null){Module.printErr(\"pre-main prep time: \"+(Date.now()-preloadStartTime)+\" ms\")}if(Module[\"_main\"]&&shouldRunNow){Module[\"callMain\"](args)}postRun()}if(Module[\"setStatus\"]){Module[\"setStatus\"](\"Running...\");setTimeout((function(){setTimeout((function(){Module[\"setStatus\"](\"\")}),1);doRun()}),1)}else{doRun()}}Module[\"run\"]=Module.run=run;function exit(status){if(Module[\"noExitRuntime\"]){return}ABORT=true;EXITSTATUS=status;STACKTOP=initialStackTop;exitRuntime();if(ENVIRONMENT_IS_NODE){process[\"stdout\"][\"once\"](\"drain\",(function(){process[\"exit\"](status)}));console.log(\" \");setTimeout((function(){process[\"exit\"](status)}),500)}else if(ENVIRONMENT_IS_SHELL&&typeof quit===\"function\"){quit(status)}throw new ExitStatus(status)}Module[\"exit\"]=Module.exit=exit;function abort(text){if(text){Module.print(text);Module.printErr(text)}ABORT=true;EXITSTATUS=1;var extra=\"\\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.\";throw\"abort() at \"+stackTrace()+extra}Module[\"abort\"]=Module.abort=abort;if(Module[\"preInit\"]){if(typeof Module[\"preInit\"]==\"function\")Module[\"preInit\"]=[Module[\"preInit\"]];while(Module[\"preInit\"].length>0){Module[\"preInit\"].pop()()}}var shouldRunNow=true;if(Module[\"noInitialRun\"]){shouldRunNow=false}run();var origMalloc=Module._malloc;var origFree=Module._free;var MEMSTATS={totalMemory:Module.HEAPU8.length,heapUsed:0};var MEMSTATS_DATA={pointerToSizeMap:{},getSizeOfPointer:(function(ptr){return MEMSTATS_DATA.pointerToSizeMap[ptr]})};Module.MEMSTATS=MEMSTATS;Module.MEMSTATS_DATA=MEMSTATS_DATA;var hookedMalloc=(function(size){var ptr=origMalloc(size);if(!ptr){return 0}MEMSTATS.heapUsed+=size;MEMSTATS_DATA.pointerToSizeMap[ptr]=size;return ptr});var hookedFree=(function(ptr){if(ptr){MEMSTATS.heapUsed-=MEMSTATS_DATA.getSizeOfPointer(ptr)||0;delete MEMSTATS_DATA.pointerToSizeMap[ptr]}return origFree(ptr)});Module._malloc=hookedMalloc;Module._free=hookedFree;_malloc=hookedMalloc;_free=hookedFree;var setInnerMalloc,setInnerFree;if(setInnerMalloc){setInnerMalloc(hookedMalloc);setInnerFree(hookedFree)}return module.exports});if(typeof module!==\"undefined\"){module.exports=C_MINISAT}\n\n\n\n\n"
  },
  {
    "path": "packages/logic-solver/minisat_wrapper.js",
    "content": "MiniSat = function () {\n  // A MiniSat object wraps an instance of \"native\" MiniSat.  You can\n  // have as many MiniSat objects as you want, and they are all\n  // independent.\n  //\n  // C is the \"module\" object created by Emscripten.  We wrap the\n  // output of Emscripten in a closure, so each call to C_MINISAT()\n  // actually instantiates a separate C environment, including\n  // the \"native\" heap.\n  //\n  // The methods available on `C` include the global functions we\n  // define in `logic-solver.cc`, each prefixed with `_`, and a varied\n  // assortment of helpers put there by Emscripten, some of which are\n  // documented here:\n  // http://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html\n  //\n  // See the README in the meteor/minisat repo for more notes about\n  // our build of MiniSat.\n  var C = this._C = C_MINISAT();\n\n  this._native = {\n    getStackPointer: function () {\n      return C.Runtime.stackSave();\n    },\n    setStackPointer: function (ptr) {\n      C.Runtime.stackRestore(ptr);\n    },\n    allocateBytes: function (len) {\n      return C.allocate(len, 'i8', C.ALLOC_STACK);\n    },\n    pushString: function (str) {\n      return this.allocateBytes(C.intArrayFromString(str));\n    },\n    savingStack: function (func) {\n      var SP = this.getStackPointer();\n      try {\n        return func(this, C);\n      } finally {\n        this.setStackPointer(SP);\n      }\n    }\n  };\n\n  C._createTheSolver();\n\n  // useful log for debugging and testing\n  this._clauses = [];\n};\n\n\n// Make sure MiniSat has allocated space in its model for v,\n// even if v is unused.  If we have variables A,B,C,D which\n// are numbers 1,2,3,4, for example, but we never actually use\n// C and D, calling ensureVar(4) will make MiniSat give us\n// solution values for them anyway.\nMiniSat.prototype.ensureVar = function (v) {\n  Logic._assertIfEnabled(v, Logic.isWholeNumber);\n  this._C._ensureVar(v);\n};\n\n// Add a clause, in the form of an array of Logic.NumTerms.\n// Returns true if the problem is still satisfiable\n// (as far as we know without doing more work), and false if\n// we can already tell that it is unsatisfiable.\nMiniSat.prototype.addClause = function (terms) {\n  Logic._assertIfEnabled(terms, Logic._isArrayWhere(Logic.isNumTerm));\n  this._clauses.push(terms);\n  return this._native.savingStack(function (native, C) {\n    var termsPtr = C.allocate((terms.length+1)*4, 'i32', C.ALLOC_STACK);\n    _.each(terms, function (t, i) {\n      C.setValue(termsPtr + i*4, t, 'i32');\n    });\n    C.setValue(termsPtr + terms.length*4, 0, 'i32'); // 0-terminate\n    return C._addClause(termsPtr) ? true : false;\n  });\n};\n\nMiniSat.prototype.solve = function () {\n  return this._C._solve() ? true : false;\n};\n\nMiniSat.prototype.solveAssuming = function (v) {\n  return this._C._solveAssuming(v) ? true : false;\n};\n\nMiniSat.prototype.getSolution = function () {\n  var solution = [null]; // no 0th var\n  var C = this._C;\n  var numVars = C._getNumVars();\n  var solPtr = C._getSolution();\n  for (var i = 0; i < numVars; i++) {\n    // 0 is Minisat::l_True (lifted \"true\").\n    // Internally, Minisat has three states for a variable:\n    // true, false, and undetermined.  It doesn't distinguish\n    // between \"false\" and \"undetermined\" in solutions though\n    // (I think it sets undetermined variables to false).\n    solution[i+1] = (C.getValue(solPtr+i, 'i8') === 0);\n  }\n  return solution;\n};\n\nMiniSat.prototype.retireVar = function (v) {\n  this._C._retireVar(v);\n};\n\n// The \"conflict clause\" feature of MiniSat is not what it sounds\n// like, unfortunately -- it doesn't help explain conflicts.\n// It only tells us which assumption vars are to blame for a failed\n// solveAssuming (and we only ever pass one var).\n// We keep this function around in case we discover a use for it.\nMiniSat.prototype.getConflictClause = function () {\n  var C = this._C;\n  var numTerms = C._getConflictClauseSize();\n  var clausePtr = C._getConflictClause();\n  var terms = [];\n  for (var i = 0; i < numTerms; i++) {\n    var t = C.getValue(clausePtr + i*4, 'i32');\n    var v = (t >>> 1);\n    var s = (t & 1) ? -1 : 1;\n    terms[i] = v * s;\n  }\n  return terms;\n};\n"
  },
  {
    "path": "packages/logic-solver/optimize.js",
    "content": "var getNonZeroWeightedTerms = function (costTerms, costWeights) {\n  if (typeof costWeights === 'number') {\n    return costWeights ? costTerms : [];\n  } else {\n    var terms = [];\n    for (var i = 0; i < costTerms.length; i++) {\n      if (costWeights[i]) {\n        terms.push(costTerms[i]);\n      }\n    }\n    return terms;\n  }\n};\n\n// See comments on minimizeWeightedSum and maximizeWeightedSum.\nvar minMaxWS = function (solver, solution, costTerms, costWeights, options,\n                         isMin) {\n  var curSolution = solution;\n  var curCost = curSolution.getWeightedSum(costTerms, costWeights);\n\n  var optFormula = options && options.formula;\n  var weightedSum = (optFormula || Logic.weightedSum(costTerms, costWeights));\n\n  var progress = options && options.progress;\n  var strategy = options && options.strategy;\n\n  // array of terms with non-zero weights, populated on demand\n  var nonZeroTerms = null;\n\n  if (isMin && curCost > 0) {\n    // try to skip straight to 0 cost, because if it works, it could\n    // save us some time\n    if (progress) {\n      progress('trying', 0);\n    }\n    var zeroSolution = null;\n    nonZeroTerms = getNonZeroWeightedTerms(costTerms, costWeights);\n    var zeroSolution = solver.solveAssuming(Logic.not(Logic.or(nonZeroTerms)));\n    if (zeroSolution) {\n      curSolution = zeroSolution;\n      curCost = 0;\n    }\n  }\n\n  if (isMin && strategy === 'bottom-up') {\n    for (var trialCost = 1; trialCost < curCost; trialCost++) {\n      if (progress) {\n        progress('trying', trialCost);\n      }\n      var costIsTrialCost = Logic.equalBits(\n        weightedSum, Logic.constantBits(trialCost));\n      var newSolution = solver.solveAssuming(costIsTrialCost);\n      if (newSolution) {\n        curSolution = newSolution;\n        curCost = trialCost;\n        break;\n      }\n    }\n  } else if (strategy && strategy !== 'default') {\n    throw new Error(\"Bad strategy: \" + strategy);\n  } else {\n    strategy = 'default';\n  }\n\n  if (strategy === 'default') {\n    // for minimization, count down from current cost. for maximization,\n    // count up.\n    while (isMin ? curCost > 0 : true) {\n      if (progress) {\n        progress('improving', curCost);\n      }\n      var improvement = (isMin ? Logic.lessThan : Logic.greaterThan)(\n        weightedSum, Logic.constantBits(curCost));\n      var newSolution = solver.solveAssuming(improvement);\n      if (! newSolution) {\n        break;\n      }\n      solver.require(improvement);\n      curSolution = newSolution;\n      curCost = curSolution.getWeightedSum(costTerms, costWeights);\n    }\n  }\n\n  if (isMin && curCost === 0) {\n    // express the requirement that the weighted sum be 0 in an efficient\n    // way for the solver (all terms with non-zero weights must be 0)\n    if (! nonZeroTerms) {\n      nonZeroTerms = getNonZeroWeightedTerms(costTerms, costWeights);\n    }\n    solver.forbid(nonZeroTerms);\n  } else {\n    solver.require(Logic.equalBits(weightedSum, Logic.constantBits(curCost)));\n  }\n\n  if (progress) {\n    progress('finished', curCost);\n  }\n\n  return curSolution;\n};\n\n// Minimize (or maximize) the dot product of costTerms and\n// costWeights, and further, require (as in solver.require) that the\n// value of the dot product be equal to the optimum found.  Returns a\n// valid solution where this optimum is achieved.\n//\n// `solution` must be a current valid solution as returned from\n// `solve` or `solveAssuming`.  It is used as a starting point (to\n// evaluate the current cost).\n//\n// costWeights is an array (of same length as costTerms) or a single\n// WholeNumber.\n//\n// if the caller passes options.formula, it should be the formula\n// Logic.weightedSum(costTerms, costWeights).  The optimizer will use\n// this existing formula rather than generating a new one (for\n// efficiency).  The optimizer still wants to know the terms and\n// weights, because it is more efficient for it to evaluate the\n// current cost using them directly rather than the formula.\n//\n// options.progress: a function that takes two arguments, to call at\n// particular times during optimization.  Called with arguments\n// ('improving', cost) when about to search for a way to improve on\n// `cost`, and called with arguments ('finished', cost) when the\n// optimum is reached.  There's also ('trying', cost) when a cost\n// is tried directly (which is usually done with 0 right off the bat).\n//\n// options.strategy: a string hinting how to go about the optimization.\n// the default strategy (option absent or 'default') is to work down\n// from the current cost for minimization or up from the current cost\n// for maximization, and iteratively insist that the cost be made lower\n// if possible.  For minimization, the alternate strategy 'bottom-up' is\n// available, which starts at 0 and tries ever higher costs until one\n// works.  All strategies first try and see if a cost of 0 is possible.\n\n// (\"costTerms\" is kind of a misnomer since they may be Formulas or Terms.)\nLogic.Solver.prototype.minimizeWeightedSum = function (solution, costTerms,\n                                                       costWeights, options) {\n  return minMaxWS(this, solution, costTerms, costWeights, options, true);\n};\n\nLogic.Solver.prototype.maximizeWeightedSum = function (solution, costTerms,\n                                                       costWeights, options) {\n  return minMaxWS(this, solution, costTerms, costWeights, options, false);\n};\n"
  },
  {
    "path": "packages/logic-solver/package.js",
    "content": "Package.describe({\n  summary: \"General satisfiability solver for logic problems\",\n  version: '2.0.6'\n});\n\nPackage.on_use(function (api) {\n  api.export('Logic');\n  api.use('underscore');\n  api.add_files(['minisat.js',\n                 'minisat_wrapper.js',\n                 'types.js',\n                 'logic.js',\n                 'optimize.js']);\n});\n\nPackage.on_test(function (api) {\n  api.use(['tinytest', 'check', 'underscore']);\n  api.use('logic-solver');\n\n  // logic-solver is totally meant for the client too, but not old\n  // ones like IE 8, so we have to exclude it from our automated\n  // testing.  It needs a browser released in the last year (say) so\n  // that Emscripten-compiled code runs reasonably.\n  api.add_files('logic_tests.js', 'server');\n});\n"
  },
  {
    "path": "packages/logic-solver/types.js",
    "content": "Logic = {};\n\n////////// TYPE TESTERS\n\n\n// Set the `description` property of a tester function and return the function.\nvar withDescription = function (description, tester) {\n  tester.description = description;\n  return tester;\n};\n\n// Create a function (x) => (x instanceof constructor), but possibly before\n// constructor is available.  For example, if Logic.Formula hasn't been\n// assigned yet, passing Logic for `obj` and \"Formula\" for `constructorName`\n// will still work.\nvar lazyInstanceofTester = function (description, obj, constructorName) {\n  return withDescription(description, function (x) {\n    return x instanceof obj[constructorName];\n  });\n};\n\n\n///// PUBLIC TYPE TESTERS\n\n// All variables have a name and a number.  The number is mainly used\n// internally, and it's what's given to MiniSat.  Names and numbers\n// are interchangeable, which is convenient for doing manipulation\n// of terms in a way that works before or after variable names are\n// converted to numbers.\n\n// Term: a variable name or variable number, optionally\n// negated (meaning \"boolean not\").  For example,\n// `1`, `-1`, `\"foo\"`, or `\"-foo\"`.  All variables have\n// internal numbers that start at 1, so \"foo\" might be\n// variable number 1, for example.  Any number of leading\n// \"-\" will be parsed in the string form, but we try to\n// keep it to either one or zero of them.\n\nLogic.isNumTerm = withDescription('a NumTerm (non-zero integer)',\n                                  function (x) {\n                                    // 32-bit integer, but not 0\n                                    return (x === (x | 0)) && x !== 0;\n                                  });\n\n// NameTerm must not be empty, or just `-` characters, or look like a\n// number.  Specifically, it can't be zero or more `-` followed by\n// zero or more digits.\nLogic.isNameTerm = withDescription('a NameTerm (string)',\n                                   function (x) {\n                                     return (typeof x === 'string') &&\n                                       ! /^-*[0-9]*$/.test(x);\n                                   });\n\nLogic.isTerm = withDescription('a Term (appropriate string or number)',\n                               function (x) {\n                                 return Logic.isNumTerm(x) ||\n                                   Logic.isNameTerm(x);\n                               });\n\n// WholeNumber: a non-negative integer (0 is allowed)\nLogic.isWholeNumber = withDescription('a whole number (integer >= 0)',\n                                      function (x) {\n                                        return (x === (x | 0)) && x >= 0;\n                                      });\n\nLogic.isFormula = lazyInstanceofTester('a Formula', Logic, 'Formula');\nLogic.isClause = lazyInstanceofTester('a Clause', Logic, 'Clause');\nLogic.isBits = lazyInstanceofTester('a Bits', Logic, 'Bits');\n\n///// UNDOCUMENTED TYPE TESTERS\n\nLogic._isInteger = withDescription(\n  'an integer', function (x) { return x === (x | 0); });\n\nLogic._isFunction = withDescription(\n  'a Function', function (x) { return typeof x === 'function'; });\n\nLogic._isString = withDescription(\n  'a String', function (x) { return typeof x === 'string'; });\n\nLogic._isArrayWhere = function (tester) {\n  var description = 'an array';\n  if (tester.description) {\n    description += ' of ' + tester.description;\n  }\n  return withDescription(description, function (x) {\n    if (! _.isArray(x)) {\n      return false;\n    } else {\n      for (var i = 0; i < x.length; i++) {\n        if (! tester(x[i])) {\n          return false;\n        }\n      }\n      return true;\n    }\n  });\n};\n\nLogic._isFormulaOrTerm = withDescription('a Formula or Term',\n                                         function (x) {\n                                           return Logic.isFormula(x) ||\n                                             Logic.isTerm(x);\n                                         });\n\n\nLogic._isFormulaOrTermOrBits = withDescription('a Formula, Term, or Bits',\n                                               function (x) {\n                                                 return Logic.isFormula(x) ||\n                                                   Logic.isBits(x) ||\n                                                   Logic.isTerm(x);\n                                               });\n"
  },
  {
    "path": "packages/markdown/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/markdown/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/markdown/license.txt",
    "content": "Copyright (c) 2007, John Fraser  \r\n<http://www.attacklab.net/>  \r\nAll rights reserved.\r\n\r\nOriginal Markdown copyright (c) 2004, John Gruber  \r\n<http://daringfireball.net/>  \r\nAll rights reserved.\r\n\r\nRedistribution and use in source and binary forms, with or without\r\nmodification, are permitted provided that the following conditions are\r\nmet:\r\n\r\n* Redistributions of source code must retain the above copyright notice,\r\n  this list of conditions and the following disclaimer.\r\n\r\n* Redistributions in binary form must reproduce the above copyright\r\n  notice, this list of conditions and the following disclaimer in the\r\n  documentation and/or other materials provided with the distribution.\r\n\r\n* Neither the name \"Markdown\" nor the names of its contributors may\r\n  be used to endorse or promote products derived from this software\r\n  without specific prior written permission.\r\n\r\nThis software is provided by the copyright holders and contributors \"as\r\nis\" and any express or implied warranties, including, but not limited\r\nto, the implied warranties of merchantability and fitness for a\r\nparticular purpose are disclaimed. In no event shall the copyright owner\r\nor contributors be liable for any direct, indirect, incidental, special,\r\nexemplary, or consequential damages (including, but not limited to,\r\nprocurement of substitute goods or services; loss of use, data, or\r\nprofits; or business interruption) however caused and on any theory of\r\nliability, whether in contract, strict liability, or tort (including\r\nnegligence or otherwise) arising in any way out of the use of this\r\nsoftware, even if advised of the possibility of such damage.\r\n"
  },
  {
    "path": "packages/markdown/package.js",
    "content": "// Source: https://github.com/coreyti/showdown\n\nPackage.describe({\n  summary: \"Markdown-to-HTML processor\",\n  version: \"1.0.10\"\n});\n\nPackage.onUse(function (api) {\n  api.addFiles(\"showdown.js\");\n  api.export('Showdown');\n\n  api.use(\"templating\", \"client\", {weak: true});\n  api.addFiles('template-integration.js', 'client');\n});\n\nPackage.onTest(function (api) {\n  api.use(\"blaze\", \"client\");\n});\n"
  },
  {
    "path": "packages/markdown/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//\n// METEOR CHANGE: remove \"var\" so that this isn't file-local.\nShowdown = { extensions: {} };\n\n//\n// forEach\n//\nvar forEach = Showdown.forEach = function(obj, callback) {\n\tif (typeof obj.forEach === 'function') {\n\t\tobj.forEach(callback);\n\t} else {\n\t\tvar i, len = obj.length;\n\t\tfor (i = 0; i < len; i++) {\n\t\t\tcallback(obj[i], i, obj);\n\t\t}\n\t}\n};\n\n//\n// Standard extension naming\n//\nvar stdExtName = function(s) {\n\treturn s.replace(/[_-]||\\s/g, '').toLowerCase();\n};\n\n//\n// converter\n//\n// Wraps all \"globals\" so that the only thing\n// exposed is makeHtml().\n//\nShowdown.converter = function(converter_options) {\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// Global extensions\nvar g_lang_extensions = [];\nvar g_output_modifiers = [];\n\n\n//\n// Automatic Extension Loading (node only):\n//\n\nif (typeof module !== 'undefind' && typeof exports !== 'undefined' && typeof require !== 'undefind') {\n\tvar fs = require('fs');\n\n\tif (fs) {\n\t\t// Search extensions folder\n\t\tvar extensions = fs.readdirSync((__dirname || '.')+'/extensions').filter(function(file){\n\t\t\treturn ~file.indexOf('.js');\n\t\t}).map(function(file){\n\t\t\treturn file.replace(/\\.js$/, '');\n\t\t});\n\t\t// Load extensions into Showdown namespace\n\t\tShowdown.forEach(extensions, function(ext){\n\t\t\tvar name = stdExtName(ext);\n\t\t\tShowdown.extensions[name] = require('./extensions/' + ext);\n\t\t});\n\t}\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 = {};\n\tg_titles = {};\n\tg_html_blocks = [];\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\t// 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// Run language extensions\n\tShowdown.forEach(g_lang_extensions, function(x){\n\t\ttext = _ExecuteExtension(x, text);\n\t});\n\n\t// Handle github codeblocks prior to running HashHTML so that\n\t// HTML contained within the codeblock gets escaped propertly\n\ttext = _DoGithubCodeBlocks(text);\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\t// Run output modifiers\n\tShowdown.forEach(g_output_modifiers, function(x){\n\t\ttext = _ExecuteExtension(x, text);\n\t});\n\n\treturn text;\n};\n//\n// Options:\n//\n\n// Parse extensions options into separate arrays\nif (converter_options && converter_options.extensions) {\n\n  var self = this;\n\n\t// Iterate over each plugin\n\tShowdown.forEach(converter_options.extensions, function(plugin){\n\n\t\t// Assume it's a bundled plugin if a string is given\n\t\tif (typeof plugin === 'string') {\n\t\t\tplugin = Showdown.extensions[stdExtName(plugin)];\n\t\t}\n\n\t\tif (typeof plugin === 'function') {\n\t\t\t// Iterate over each extension within that plugin\n\t\t\tShowdown.forEach(plugin(self), function(ext){\n\t\t\t\t// Sort extensions by type\n\t\t\t\tif (ext.type) {\n\t\t\t\t\tif (ext.type === 'language' || ext.type === 'lang') {\n\t\t\t\t\t\tg_lang_extensions.push(ext);\n\t\t\t\t\t} else if (ext.type === 'output' || ext.type === 'html') {\n\t\t\t\t\t\tg_output_modifiers.push(ext);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Assume language extension\n\t\t\t\t\tg_output_modifiers.push(ext);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tthrow \"Extension '\" + plugin + \"' could not be loaded.  It was either not found or is not a valid extension.\";\n\t\t}\n\t});\n}\n\n\nvar _ExecuteExtension = function(ext, text) {\n\tif (ext.regex) {\n\t\tvar re = new RegExp(ext.regex, 'g');\n\t\treturn text.replace(re, ext.replace);\n\t} else if (ext.filter) {\n\t\treturn ext.filter(text);\n\t}\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\n\t// attacklab: sentinel workarounds for lack of \\A and \\Z, safari\\khtml bug\n\ttext += \"~0\";\n\n\ttext = text.replace(/^[ ]{0,3}\\[(.+)\\]:[ \\t]*\\n?[ \\t]*<?(\\S+?)>?[ \\t]*\\n?[ \\t]*(?:(\\n*)[\"(](.+?)[\")][ \\t]*)?(?:\\n+|(?=~0))/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\t// attacklab: strip sentinel\n\ttext = text.replace(/~0/,\"\");\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|style|section|header|footer|nav|article|aside\";\n\tvar block_tags_b = \"p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside\";\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|style|section|header|footer|nav|article|aside)\\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 id=\"' + headerId(m1) + '\">' + _RunSpanGamut(m1) + \"</h1>\");});\n\n\ttext = text.replace(/^(.+)[ \\t]*\\n-+[ \\t]*\\n+/gm,\n\t\tfunction(matchFound,m1){return hashBlock('<h2 id=\"' + headerId(m1) + '\">' + _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 + ' id=\"' + headerId(m2) + '\">' + _RunSpanGamut(m2) + \"</h\" + h_level + \">\");\n\t\t});\n\n\tfunction headerId(m) {\n\t\treturn m.replace(/[^\\w]/g, '').toLowerCase();\n\t}\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 _DoGithubCodeBlocks = function(text) {\n//\n//  Process Github-style code blocks\n//  Example:\n//  ```ruby\n//  def hello_world(x)\n//    puts \"Hello, #{x}\"\n//  end\n//  ```\n//\n\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([\\s\\S]*?)\\n```/g,\n\t\tfunction(wholeMatch,m1,m2) {\n\t\t\tvar language = m1;\n\t\t\tvar codeblock = m2;\n\n\t\t\tcodeblock = _EncodeCode(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\" + (language ? \" class=\\\"\" + language + '\"' : \"\") + \">\" + codeblock + \"\\n</code></pre>\";\n\n\t\t\treturn hashBlock(codeblock);\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\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\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 = [];\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\tvar encode = [\n\t\tfunction(ch){return \"&#\"+ch.charCodeAt(0)+\";\";},\n\t\tfunction(ch){return \"&#x\"+ch.charCodeAt(0).toString(16)+\";\";},\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\n\n// export\nif (typeof module !== 'undefined') module.exports = Showdown;\n\n// stolen from AMD branch of underscore\n// AMD define happens at the end for compatibility with AMD loaders\n// that don't enforce next-turn semantics on modules.\nif (typeof define === 'function' && define.amd) {\n    define('showdown', function() {\n        return Showdown;\n    });\n}\n"
  },
  {
    "path": "packages/markdown/template-integration.js",
    "content": "if (Package.templating) {\n  var Template = Package.templating.Template;\n  var Blaze = Package.blaze.Blaze; // implied by `templating`\n  var HTML = Package.htmljs.HTML; // implied by `blaze`\n\n  Blaze.Template.registerHelper(\"markdown\", new Template('markdown', function () {\n    var view = this;\n    var content = '';\n    if (view.templateContentBlock) {\n      content = Blaze._toText(view.templateContentBlock, HTML.TEXTMODE.STRING);\n    }\n    var converter = new Showdown.converter();\n    return HTML.Raw(converter.makeHtml(content));\n  }));\n}\n"
  },
  {
    "path": "packages/meetup/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/meetup/README.md",
    "content": "# meetup\n\nAn implementation of the Meetup OAuth flow. See the [project\npage](https://www.meteor.com/accounts) on Meteor Accounts for more\ndetails."
  },
  {
    "path": "packages/meetup/meetup_client.js",
    "content": "Meetup = {};\n// Request Meetup credentials for the user\n// @param options {optional}\n// @param credentialRequestCompleteCallback {Function} Callback function to call on\n//   completion. Takes one argument, credentialToken on success, or Error on\n//   error.\nMeetup.requestCredential = function (options, credentialRequestCompleteCallback) {\n  // support both (options, callback) and (callback).\n  if (!credentialRequestCompleteCallback && typeof options === 'function') {\n    credentialRequestCompleteCallback = options;\n    options = {};\n  }\n\n  var config = ServiceConfiguration.configurations.findOne({service: 'meetup'});\n  if (!config) {\n    credentialRequestCompleteCallback && credentialRequestCompleteCallback(\n      new ServiceConfiguration.ConfigError());\n    return;\n  }\n\n  // For some reason, meetup converts underscores to spaces in the state\n  // parameter when redirecting back to the client, so we use\n  // `Random.id()` here (alphanumerics) instead of `Random.secret()`\n  // (base 64 characters).\n  var credentialToken = Random.id();\n\n  var scope = (options && options.requestPermissions) || [];\n  var flatScope = _.map(scope, encodeURIComponent).join('+');\n\n  var loginStyle = OAuth._loginStyle('meetup', config, options);\n\n  var loginUrl =\n        'https://secure.meetup.com/oauth2/authorize' +\n        '?client_id=' + config.clientId +\n        '&response_type=code' +\n        '&scope=' + flatScope +\n        '&redirect_uri=' + OAuth._redirectUri('meetup', config) +\n        '&state=' + OAuth._stateParam(loginStyle, credentialToken, options && options.redirectUrl);\n\n  // meetup box gets taller when permissions requested.\n  var height = 620;\n  if (_.without(scope, 'basic').length)\n    height += 130;\n\n  OAuth.launchLogin({\n    loginService: \"meetup\",\n    loginStyle: loginStyle,\n    loginUrl: loginUrl,\n    credentialRequestCompleteCallback: credentialRequestCompleteCallback,\n    credentialToken: credentialToken,\n    popupOptions: {width: 900, height: height}\n  });\n};\n"
  },
  {
    "path": "packages/meetup/meetup_configure.html",
    "content": "<template name=\"configureLoginServiceDialogForMeetup\">\n  <p>\n    First, you'll need to get a Meetup Client ID. Follow these steps:\n  </p>\n  <ol>\n    <li>\n      Visit <a href=\"http://www.meetup.com/meetup_api/oauth_consumers/create/\" target=\"blank\">http://www.meetup.com/meetup_api/oauth_consumers/create/</a>\n    </li>\n    <li>\n      Set the Consumer name to the name of your application.\n    </li>\n    <li>\n      Optionally set the Application Website to the URL of your\n      website.  You can leave this blank.\n    </li>\n    <li>\n      Set the <b>Redirect URI</b> to: <span class=\"url\">{{siteUrl}}</span>  (Do not append a path to this URL.)\n    </li>\n  </ol>\n</template>\n"
  },
  {
    "path": "packages/meetup/meetup_configure.js",
    "content": "Template.configureLoginServiceDialogForMeetup.helpers({\n  siteUrl: function () {\n    return Meteor.absoluteUrl();\n  }\n});\n\nTemplate.configureLoginServiceDialogForMeetup.fields = function () {\n  return [\n    {property: 'clientId', label: 'Key'},\n    {property: 'secret', label: 'Secret'}\n  ];\n};\n"
  },
  {
    "path": "packages/meetup/meetup_server.js",
    "content": "Meetup = {};\n\nOAuth.registerService('meetup', 2, null, function(query) {\n\n  var accessToken = getAccessToken(query);\n  var identity = getIdentity(accessToken);\n\n  return {\n    serviceData: {\n      id: identity.id,\n      accessToken: accessToken\n    },\n    options: {profile: {name: identity.name}}\n  };\n});\n\nvar getAccessToken = function (query) {\n  var config = ServiceConfiguration.configurations.findOne({service: 'meetup'});\n  if (!config)\n    throw new ServiceConfiguration.ConfigError();\n\n  var response;\n  try {\n    response = HTTP.post(\n      \"https://secure.meetup.com/oauth2/access\", {headers: {Accept: 'application/json'}, params: {\n        code: query.code,\n        client_id: config.clientId,\n        client_secret: OAuth.openSecret(config.secret),\n        grant_type: 'authorization_code',\n        redirect_uri: OAuth._redirectUri('meetup', config),\n        state: query.state\n      }});\n  } catch (err) {\n    throw _.extend(new Error(\"Failed to complete OAuth handshake with Meetup. \" + err.message),\n                   {response: err.response});\n  }\n\n  if (response.data.error) { // if the http response was a json object with an error attribute\n    throw new Error(\"Failed to complete OAuth handshake with Meetup. \" + response.data.error);\n  } else {\n    return response.data.access_token;\n  }\n};\n\nvar getIdentity = function (accessToken) {\n  try {\n    var response = HTTP.get(\n      \"https://api.meetup.com/2/members\",\n      {params: {member_id: 'self', access_token: accessToken}});\n    return response.data.results && response.data.results[0];\n  } catch (err) {\n    throw _.extend(new Error(\"Failed to fetch identity from Meetup. \" + err.message),\n                   {response: err.response});\n  }\n};\n\n\nMeetup.retrieveCredential = function(credentialToken, credentialSecret) {\n  return OAuth.retrieveCredential(credentialToken, credentialSecret);\n};\n"
  },
  {
    "path": "packages/meetup/package.js",
    "content": "Package.describe({\n  summary: \"Meetup OAuth flow\",\n  version: \"1.6.4\"\n});\n\nPackage.onUse(function(api) {\n  api.use('oauth2', ['client', 'server']);\n  api.use('oauth', ['client', 'server']);\n  api.use('http', ['server']);\n  api.use('templating', 'client');\n  api.use('underscore', 'client');\n  api.use('random', 'client');\n  api.use('service-configuration', ['client', 'server']);\n\n  api.export('Meetup');\n\n  api.addFiles(\n    ['meetup_configure.html', 'meetup_configure.js'],\n    'client');\n\n  api.addFiles('meetup_server.js', 'server');\n  api.addFiles('meetup_client.js', 'client');\n});\n"
  },
  {
    "path": "packages/meteor/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/meteor/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/meteor/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/meteor/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"meteor-deque\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/meteor-deque/-/meteor-deque-2.1.0.tgz\",\n      \"from\": \"https://registry.npmjs.org/meteor-deque/-/meteor-deque-2.1.0.tgz\",\n      \"dependencies\": {\n        \"double-ended-queue\": {\n          \"version\": \"2.1.0-0\",\n          \"resolved\": \"https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz\",\n          \"from\": \"https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/meteor/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/meteor/bare_test_setup.js",
    "content": "// Normally, a var should be file-local, but this file is loaded with {bare:\n// true}, so it should be readable by bare_tests.js\nvar VariableSetByBareTestSetup = 1234;\n"
  },
  {
    "path": "packages/meteor/bare_tests.js",
    "content": "Tinytest.add(\"linker - bare\", function (test) {\n  test.equal(VariableSetByBareTestSetup, 1234);\n});\n"
  },
  {
    "path": "packages/meteor/browser_environment_test.js",
    "content": "Tinytest.add(\"environment - browser basics\", function (test) {\n  test.isTrue(Meteor.isClient);\n  test.isFalse(Meteor.isServer);\n  test.isFalse(Meteor.isCordova);\n});\n"
  },
  {
    "path": "packages/meteor/client_environment.js",
    "content": "meteorEnv = __meteor_runtime_config__.meteorEnv;\n\n/**\n * @summary The Meteor namespace\n * @namespace Meteor\n */\nMeteor = {\n  /**\n   * @summary Boolean variable.  True if running in production environment.\n   * @locus Anywhere\n   * @static\n   * @type {Boolean}\n   */\n  isProduction: meteorEnv.NODE_ENV === \"production\",\n\n  /**\n   * @summary Boolean variable.  True if running in development environment.\n   * @locus Anywhere\n   * @static\n   * @type {Boolean}\n   */\n  isDevelopment: meteorEnv.NODE_ENV !== \"production\",\n\n  /**\n   * @summary Boolean variable.  True if running in client environment.\n   * @locus Anywhere\n   * @static\n   * @type {Boolean}\n   */\n  isClient: true,\n\n  /**\n   * @summary Boolean variable.  True if running in server environment.\n   * @locus Anywhere\n   * @static\n   * @type {Boolean}\n   */\n  isServer: false,\n  isCordova: false\n};\n\nif (typeof __meteor_runtime_config__ === 'object' &&\n    __meteor_runtime_config__.PUBLIC_SETTINGS) {\n  /**\n   * @summary `Meteor.settings` contains deployment-specific configuration options. You can initialize settings by passing the `--settings` option (which takes the name of a file containing JSON data) to `meteor run` or `meteor deploy`. When running your server directly (e.g. from a bundle), you instead specify settings by putting the JSON directly into the `METEOR_SETTINGS` environment variable. If the settings object contains a key named `public`, then `Meteor.settings.public` will be available on the client as well as the server.  All other properties of `Meteor.settings` are only defined on the server.  You can rely on `Meteor.settings` and `Meteor.settings.public` being defined objects (not undefined) on both client and server even if there are no settings specified.  Changes to `Meteor.settings.public` at runtime will be picked up by new client connections.\n   * @locus Anywhere\n   * @type {Object}\n   */\n  Meteor.settings = { 'public': __meteor_runtime_config__.PUBLIC_SETTINGS };\n}\n"
  },
  {
    "path": "packages/meteor/client_environment_test.js",
    "content": "Tinytest.add(\"environment - client basics\", function (test) {\n  test.isTrue(Meteor.isClient);\n  test.isFalse(Meteor.isServer);\n});\n"
  },
  {
    "path": "packages/meteor/cordova_environment.js",
    "content": "/**\n * @summary Boolean variable.  True if running in a Cordova mobile environment.\n * @type {Boolean}\n * @static\n * @locus Anywhere\n */\nMeteor.isCordova = true;\n\nMeteor.isProduction = meteorEnv.NODE_ENV === \"production\";\nMeteor.isDevelopment = meteorEnv.NODE_ENV !== \"production\";\n"
  },
  {
    "path": "packages/meteor/cordova_environment_test.js",
    "content": "Tinytest.add(\"environment - cordova basics\", function (test) {\n  test.isFalse(Meteor.isServer);\n  test.isTrue(Meteor.isClient);\n  test.isTrue(Meteor.isCordova);\n});\n\n"
  },
  {
    "path": "packages/meteor/debug.js",
    "content": "var suppress = 0;\n\n// replacement for console.log. This is a temporary API. We should\n// provide a real logging API soon (possibly just a polyfill for\n// console?)\n//\n// NOTE: this is used on the server to print the warning about\n// having autopublish enabled when you probably meant to turn it\n// off. it's not really the proper use of something called\n// _debug. the intent is for this message to go to the terminal and\n// be very visible. if you change _debug to go someplace else, etc,\n// please fix the autopublish code to do something reasonable.\n//\nMeteor._debug = function (/* arguments */) {\n  if (suppress) {\n    suppress--;\n    return;\n  }\n  if (typeof console !== 'undefined' &&\n      typeof console.log !== 'undefined') {\n    if (arguments.length == 0) { // IE Companion breaks otherwise\n      // IE10 PP4 requires at least one argument\n      console.log('');\n    } else {\n      // IE doesn't have console.log.apply, it's not a real Object.\n      // http://stackoverflow.com/questions/5538972/console-log-apply-not-working-in-ie9\n      // http://patik.com/blog/complete-cross-browser-console-log/\n      if (typeof console.log.apply === \"function\") {\n        // Most browsers\n\n        // Chrome and Safari only hyperlink URLs to source files in first argument of\n        // console.log, so try to call it with one argument if possible.\n        // Approach taken here: If all arguments are strings, join them on space.\n        // See https://github.com/meteor/meteor/pull/732#issuecomment-13975991\n        var allArgumentsOfTypeString = true;\n        for (var i = 0; i < arguments.length; i++)\n          if (typeof arguments[i] !== \"string\")\n            allArgumentsOfTypeString = false;\n\n        if (allArgumentsOfTypeString)\n          console.log.apply(console, [Array.prototype.join.call(arguments, \" \")]);\n        else\n          console.log.apply(console, arguments);\n\n      } else if (typeof Function.prototype.bind === \"function\") {\n        // IE9\n        var log = Function.prototype.bind.call(console.log, console);\n        log.apply(console, arguments);\n      } else {\n        // IE8\n        Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));\n      }\n    }\n  }\n};\n\n// Suppress the next 'count' Meteor._debug messsages. Use this to\n// stop tests from spamming the console.\n//\nMeteor._suppress_log = function (count) {\n  suppress += count;\n};\n\nMeteor._suppressed_log_expected = function () {\n  return suppress !== 0;\n};\n\n"
  },
  {
    "path": "packages/meteor/debug_test.js",
    "content": "Tinytest.add(\"core - debug\", function (test) {\n\n  // Just run a log statement and make sure it doesn't explode.\n  Meteor._suppress_log(3);\n  Meteor._debug();\n  Meteor._debug(\"test one arg\");\n  Meteor._debug(\"this\", \"is\", \"a\", \"test\");\n  test.ok();\n\n});\n"
  },
  {
    "path": "packages/meteor/dynamics_browser.js",
    "content": "// Simple implementation of dynamic scoping, for use in browsers\n\nvar nextSlot = 0;\nvar currentValues = [];\n\nMeteor.EnvironmentVariable = function () {\n  this.slot = nextSlot++;\n};\n\n_.extend(Meteor.EnvironmentVariable.prototype, {\n  get: function () {\n    return currentValues[this.slot];\n  },\n\n  getOrNullIfOutsideFiber: function () {\n    return this.get();\n  },\n\n  withValue: function (value, func) {\n    var saved = currentValues[this.slot];\n    try {\n      currentValues[this.slot] = value;\n      var ret = func();\n    } finally {\n      currentValues[this.slot] = saved;\n    }\n    return ret;\n  }\n});\n\nMeteor.bindEnvironment = function (func, onException, _this) {\n  // needed in order to be able to create closures inside func and\n  // have the closed variables not change back to their original\n  // values\n  var boundValues = _.clone(currentValues);\n\n  if (!onException || typeof(onException) === 'string') {\n    var description = onException || \"callback of async function\";\n    onException = function (error) {\n      Meteor._debug(\n        \"Exception in \" + description + \":\",\n        error && error.stack || error\n      );\n    };\n  }\n\n  return function (/* arguments */) {\n    var savedValues = currentValues;\n    try {\n      currentValues = boundValues;\n      var ret = func.apply(_this, _.toArray(arguments));\n    } catch (e) {\n      // note: callback-hook currently relies on the fact that if onException\n      // throws in the browser, the wrapped call throws.\n      onException(e);\n    } finally {\n      currentValues = savedValues;\n    }\n    return ret;\n  };\n};\n\nMeteor._nodeCodeMustBeInFiber = function () {\n  // no-op on browser\n};\n"
  },
  {
    "path": "packages/meteor/dynamics_nodejs.js",
    "content": "// Fiber-aware implementation of dynamic scoping, for use on the server\n\nvar Fiber = Npm.require('fibers');\n\nvar nextSlot = 0;\n\nMeteor._nodeCodeMustBeInFiber = function () {\n  if (!Fiber.current) {\n    throw new Error(\"Meteor code must always run within a Fiber. \" +\n                    \"Try wrapping callbacks that you pass to non-Meteor \" +\n                    \"libraries with Meteor.bindEnvironment.\");\n  }\n};\n\nMeteor.EnvironmentVariable = function () {\n  this.slot = nextSlot++;\n};\n\n_.extend(Meteor.EnvironmentVariable.prototype, {\n  get: function () {\n    Meteor._nodeCodeMustBeInFiber();\n\n    return Fiber.current._meteor_dynamics &&\n      Fiber.current._meteor_dynamics[this.slot];\n  },\n\n  // Most Meteor code ought to run inside a fiber, and the\n  // _nodeCodeMustBeInFiber assertion helps you remember to include appropriate\n  // bindEnvironment calls (which will get you the *right value* for your\n  // environment variables, on the server).\n  //\n  // In some very special cases, it's more important to run Meteor code on the\n  // server in non-Fiber contexts rather than to strongly enforce the safeguard\n  // against forgetting to use bindEnvironment. For example, using `check` in\n  // some top-level constructs like connect handlers without needing unnecessary\n  // Fibers on every request is more important that possibly failing to find the\n  // correct argumentChecker. So this function is just like get(), but it\n  // returns null rather than throwing when called from outside a Fiber. (On the\n  // client, it is identical to get().)\n  getOrNullIfOutsideFiber: function () {\n    if (!Fiber.current)\n      return null;\n    return this.get();\n  },\n\n  withValue: function (value, func) {\n    Meteor._nodeCodeMustBeInFiber();\n\n    if (!Fiber.current._meteor_dynamics)\n      Fiber.current._meteor_dynamics = [];\n    var currentValues = Fiber.current._meteor_dynamics;\n\n    var saved = currentValues[this.slot];\n    try {\n      currentValues[this.slot] = value;\n      var ret = func();\n    } finally {\n      currentValues[this.slot] = saved;\n    }\n\n    return ret;\n  }\n});\n\n// Meteor application code is always supposed to be run inside a\n// fiber. bindEnvironment ensures that the function it wraps is run from\n// inside a fiber and ensures it sees the values of Meteor environment\n// variables that are set at the time bindEnvironment is called.\n//\n// If an environment-bound function is called from outside a fiber (eg, from\n// an asynchronous callback from a non-Meteor library such as MongoDB), it'll\n// kick off a new fiber to execute the function, and returns undefined as soon\n// as that fiber returns or yields (and func's return value is ignored).\n//\n// If it's called inside a fiber, it works normally (the\n// return value of the function will be passed through, and no new\n// fiber will be created.)\n//\n// `onException` should be a function or a string.  When it is a\n// function, it is called as a callback when the bound function raises\n// an exception.  If it is a string, it should be a description of the\n// callback, and when an exception is raised a debug message will be\n// printed with the description.\nMeteor.bindEnvironment = function (func, onException, _this) {\n  Meteor._nodeCodeMustBeInFiber();\n\n  var boundValues = _.clone(Fiber.current._meteor_dynamics || []);\n\n  if (!onException || typeof(onException) === 'string') {\n    var description = onException || \"callback of async function\";\n    onException = function (error) {\n      Meteor._debug(\n        \"Exception in \" + description + \":\",\n        error && error.stack || error\n      );\n    };\n  } else if (typeof(onException) !== 'function') {\n    throw new Error('onException argument must be a function, string or undefined for Meteor.bindEnvironment().');\n  }\n\n  return function (/* arguments */) {\n    var args = _.toArray(arguments);\n\n    var runWithEnvironment = function () {\n      var savedValues = Fiber.current._meteor_dynamics;\n      try {\n        // Need to clone boundValues in case two fibers invoke this\n        // function at the same time\n        Fiber.current._meteor_dynamics = _.clone(boundValues);\n        var ret = func.apply(_this, args);\n      } catch (e) {\n        // note: callback-hook currently relies on the fact that if onException\n        // throws and you were originally calling the wrapped callback from\n        // within a Fiber, the wrapped call throws.\n        onException(e);\n      } finally {\n        Fiber.current._meteor_dynamics = savedValues;\n      }\n      return ret;\n    };\n\n    if (Fiber.current)\n      return runWithEnvironment();\n    Fiber(runWithEnvironment).run();\n  };\n};\n"
  },
  {
    "path": "packages/meteor/dynamics_test.js",
    "content": "var CurrentFoo = new Meteor.EnvironmentVariable;\n\nTinytest.add(\"environment - dynamic variables\", function (test) {\n  test.equal(CurrentFoo.get(), undefined);\n\n  CurrentFoo.withValue(17, function () {\n    test.equal(CurrentFoo.get(), 17);\n\n    CurrentFoo.withValue(22, function () {\n      test.equal(CurrentFoo.get(), 22);\n    });\n\n    test.equal(CurrentFoo.get(), 17);\n  });\n\n  test.equal(CurrentFoo.get(), undefined);\n});\n\nTinytest.add(\"environment - bindEnvironment\", function (test) {\n  var raised_f;\n\n  var f = CurrentFoo.withValue(17, function () {\n    return Meteor.bindEnvironment(function (flag) {\n      test.equal(CurrentFoo.get(), 17);\n      if (flag)\n        throw \"test\";\n      return 12;\n    }, function (e) {\n      test.equal(CurrentFoo.get(), 17);\n      raised_f = e;\n    });\n  });\n\n  var test_f = function () {\n    raised_f = null;\n\n    test.equal(f(false), 12);\n    test.equal(raised_f, null);\n\n    test.equal(f(true), undefined);\n    test.equal(raised_f, \"test\");\n  };\n\n  // At top level\n\n  test.equal(CurrentFoo.get(), undefined);\n  test_f();\n\n  // Inside a withValue\n\n  CurrentFoo.withValue(22, function () {\n    test.equal(CurrentFoo.get(), 22);\n    test_f();\n    test.equal(CurrentFoo.get(), 22);\n  });\n\n  test.equal(CurrentFoo.get(), undefined);\n\n  // Multiple environment-bound functions on the stack (in the nodejs\n  // implementation, this needs to avoid creating additional fibers)\n\n  var raised_g;\n\n  var g = CurrentFoo.withValue(99, function () {\n    return Meteor.bindEnvironment(function (flag) {\n      test.equal(CurrentFoo.get(), 99);\n\n      if (flag)\n        throw \"trial\";\n\n      test_f();\n      return 88;\n    }, function (e) {\n      test.equal(CurrentFoo.get(), 99);\n      raised_g = e;\n    });\n  });\n\n  var test_g = function () {\n    raised_g = null;\n\n    test.equal(g(false), 88);\n    test.equal(raised_g, null);\n\n    test.equal(g(true), undefined);\n    test.equal(raised_g, \"trial\");\n  };\n\n  test_g();\n\n  CurrentFoo.withValue(77, function () {\n    test.equal(CurrentFoo.get(), 77);\n    test_g();\n    test.equal(CurrentFoo.get(), 77);\n  });\n\n  test.equal(CurrentFoo.get(), undefined);\n});\n\nTinytest.addAsync(\"environment - bare bindEnvironment\",\n                  function (test, onComplete) {\n  // this will have to create a fiber in nodejs\n  CurrentFoo.withValue(68, function () {\n    var f = Meteor.bindEnvironment(function () {\n      test.equal(CurrentFoo.get(), 68);\n      onComplete();\n    }, function () {});\n\n    setTimeout(f, 0);\n  });\n});\n"
  },
  {
    "path": "packages/meteor/errors.js",
    "content": "// Makes an error subclass which properly contains a stack trace in most\n// environments. constructor can set fields on `this` (and should probably set\n// `message`, which is what gets displayed at the top of a stack trace).\n//\nMeteor.makeErrorType = function (name, constructor) {\n  var errorClass = function (/*arguments*/) {\n    // Ensure we get a proper stack trace in most Javascript environments\n    if (Error.captureStackTrace) {\n      // V8 environments (Chrome and Node.js)\n      Error.captureStackTrace(this, errorClass);\n    } else {\n      // Borrow the .stack property of a native Error object.\n      this.stack = new Error().stack;\n    }\n    // Safari magically works.\n\n    constructor.apply(this, arguments);\n\n    this.errorType = name;\n  };\n\n  Meteor._inherits(errorClass, Error);\n\n  return errorClass;\n};\n\n// This should probably be in the livedata package, but we don't want\n// to require you to use the livedata package to get it. Eventually we\n// should probably rename it to DDP.Error and put it back in the\n// 'livedata' package (which we should rename to 'ddp' also.)\n//\n// Note: The DDP server assumes that Meteor.Error EJSON-serializes as an object\n// containing 'error' and optionally 'reason' and 'details'.\n// The DDP client manually puts these into Meteor.Error objects. (We don't use\n// EJSON.addType here because the type is determined by location in the\n// protocol, not text on the wire.)\n\n/**\n * @summary This class represents a symbolic error thrown by a method.\n * @locus Anywhere\n * @class\n * @param {String} error A string code uniquely identifying this kind of error.\n * This string should be used by callers of the method to determine the\n * appropriate action to take, instead of attempting to parse the reason\n * or details fields. For example:\n *\n * ```\n * // on the server, pick a code unique to this error\n * // the reason field should be a useful debug message\n * throw new Meteor.Error(\"logged-out\", \n *   \"The user must be logged in to post a comment.\");\n *\n * // on the client\n * Meteor.call(\"methodName\", function (error) {\n *   // identify the error\n *   if (error && error.error === \"logged-out\") {\n *     // show a nice error message\n *     Session.set(\"errorMessage\", \"Please log in to post a comment.\");\n *   }\n * });\n * ```\n * \n * For legacy reasons, some built-in Meteor functions such as `check` throw\n * errors with a number in this field.\n * \n * @param {String} [reason] Optional.  A short human-readable summary of the\n * error, like 'Not Found'.\n * @param {String} [details] Optional.  Additional information about the error,\n * like a textual stack trace.\n */\nMeteor.Error = Meteor.makeErrorType(\n  \"Meteor.Error\",\n  function (error, reason, details) {\n    var self = this;\n\n    // String code uniquely identifying this kind of error.\n    self.error = error;\n\n    // Optional: A short human-readable summary of the error. Not\n    // intended to be shown to end users, just developers. (\"Not Found\",\n    // \"Internal Server Error\")\n    self.reason = reason;\n\n    // Optional: Additional information about the error, say for\n    // debugging. It might be a (textual) stack trace if the server is\n    // willing to provide one. The corresponding thing in HTTP would be\n    // the body of a 404 or 500 response. (The difference is that we\n    // never expect this to be shown to end users, only developers, so\n    // it doesn't need to be pretty.)\n    self.details = details;\n\n    // This is what gets displayed at the top of a stack trace. Current\n    // format is \"[404]\" (if no reason is set) or \"File not found [404]\"\n    if (self.reason)\n      self.message = self.reason + ' [' + self.error + ']';\n    else\n      self.message = '[' + self.error + ']';\n  });\n\n// Meteor.Error is basically data and is sent over DDP, so you should be able to\n// properly EJSON-clone it. This is especially important because if a\n// Meteor.Error is thrown through a Future, the error, reason, and details\n// properties become non-enumerable so a standard Object clone won't preserve\n// them and they will be lost from DDP.\nMeteor.Error.prototype.clone = function () {\n  var self = this;\n  return new Meteor.Error(self.error, self.reason, self.details);\n};\n"
  },
  {
    "path": "packages/meteor/fiber_helpers.js",
    "content": "var path = Npm.require('path');\nvar Fiber = Npm.require('fibers');\nvar Future = Npm.require(path.join('fibers', 'future'));\n\nMeteor._noYieldsAllowed = function (f) {\n  var savedYield = Fiber.yield;\n  Fiber.yield = function () {\n    throw new Error(\"Can't call yield in a noYieldsAllowed block!\");\n  };\n  try {\n    return f();\n  } finally {\n    Fiber.yield = savedYield;\n  }\n};\n\nMeteor._DoubleEndedQueue = Npm.require('meteor-deque');\n\n// Meteor._SynchronousQueue is a queue which runs task functions serially.\n// Tasks are assumed to be synchronous: ie, it's assumed that they are\n// done when they return.\n//\n// It has two methods:\n//   - queueTask queues a task to be run, and returns immediately.\n//   - runTask queues a task to be run, and then yields. It returns\n//     when the task finishes running.\n//\n// It's safe to call queueTask from within a task, but not runTask (unless\n// you're calling runTask from a nested Fiber).\n//\n// Somewhat inspired by async.queue, but specific to blocking tasks.\n// XXX break this out into an NPM module?\n// XXX could maybe use the npm 'schlock' module instead, which would\n//     also support multiple concurrent \"read\" tasks\n//\nMeteor._SynchronousQueue = function () {\n  var self = this;\n  // List of tasks to run (not including a currently-running task if any). Each\n  // is an object with field 'task' (the task function to run) and 'future' (the\n  // Future associated with the blocking runTask call that queued it, or null if\n  // called from queueTask).\n  self._taskHandles = new Meteor._DoubleEndedQueue();\n  // This is true if self._run() is either currently executing or scheduled to\n  // do so soon.\n  self._runningOrRunScheduled = false;\n  // During the execution of a task, this is set to the fiber used to execute\n  // that task. We use this to throw an error rather than deadlocking if the\n  // user calls runTask from within a task on the same fiber.\n  self._currentTaskFiber = undefined;\n  // This is true if we're currently draining.  While we're draining, a further\n  // drain is a noop, to prevent infinite loops.  \"drain\" is a heuristic type\n  // operation, that has a meaning like unto \"what a naive person would expect\n  // when modifying a table from an observe\"\n  self._draining = false;\n};\n\n_.extend(Meteor._SynchronousQueue.prototype, {\n  runTask: function (task) {\n    var self = this;\n\n    if (!self.safeToRunTask()) {\n      if (Fiber.current)\n        throw new Error(\"Can't runTask from another task in the same fiber\");\n      else\n        throw new Error(\"Can only call runTask in a Fiber\");\n    }\n\n    var fut = new Future;\n    var handle = {\n      task: Meteor.bindEnvironment(task, function (e) {\n        Meteor._debug(\"Exception from task:\", e && e.stack || e);\n        throw e;\n      }),\n      future: fut,\n      name: task.name\n    };\n    self._taskHandles.push(handle);\n    self._scheduleRun();\n    // Yield. We'll get back here after the task is run (and will throw if the\n    // task throws).\n    fut.wait();\n  },\n  queueTask: function (task) {\n    var self = this;\n    self._taskHandles.push({\n      task: task,\n      name: task.name\n    });\n    self._scheduleRun();\n    // No need to block.\n  },\n\n  flush: function () {\n    var self = this;\n    self.runTask(function () {});\n  },\n\n  safeToRunTask: function () {\n    var self = this;\n    return Fiber.current && self._currentTaskFiber !== Fiber.current;\n  },\n\n  drain: function () {\n    var self = this;\n    if (self._draining)\n      return;\n    if (!self.safeToRunTask())\n      return;\n    self._draining = true;\n    while (! self._taskHandles.isEmpty()) {\n      self.flush();\n    }\n    self._draining = false;\n  },\n\n  _scheduleRun: function () {\n    var self = this;\n    // Already running or scheduled? Do nothing.\n    if (self._runningOrRunScheduled)\n      return;\n\n    self._runningOrRunScheduled = true;\n    setImmediate(function () {\n      Fiber(function () {\n        self._run();\n      }).run();\n    });\n  },\n  _run: function () {\n    var self = this;\n\n    if (!self._runningOrRunScheduled)\n      throw new Error(\"expected to be _runningOrRunScheduled\");\n\n    if (self._taskHandles.isEmpty()) {\n      // Done running tasks! Don't immediately schedule another run, but\n      // allow future tasks to do so.\n      self._runningOrRunScheduled = false;\n      return;\n    }\n    var taskHandle = self._taskHandles.shift();\n\n    // Run the task.\n    self._currentTaskFiber = Fiber.current;\n    var exception = undefined;\n    try {\n      taskHandle.task();\n    } catch (err) {\n      if (taskHandle.future) {\n        // We'll throw this exception through runTask.\n        exception = err;\n      } else {\n        Meteor._debug(\"Exception in queued task: \" + (err.stack || err));\n      }\n    }\n    self._currentTaskFiber = undefined;\n\n    // Soon, run the next task, if there is any.\n    self._runningOrRunScheduled = false;\n    self._scheduleRun();\n\n    // If this was queued with runTask, let the runTask call return (throwing if\n    // the task threw).\n    if (taskHandle.future) {\n      if (exception)\n        taskHandle.future['throw'](exception);\n      else\n        taskHandle.future['return']();\n    }\n  }\n});\n\n// Sleep. Mostly used for debugging (eg, inserting latency into server\n// methods).\n//\nMeteor._sleepForMs = function (ms) {\n  var fiber = Fiber.current;\n  setTimeout(function() {\n    fiber.run();\n  }, ms);\n  Fiber.yield();\n};\n"
  },
  {
    "path": "packages/meteor/fiber_helpers_test.js",
    "content": "var Fiber = Npm.require('fibers');\n\nTinytest.add(\"fibers - synchronous queue\", function (test) {\n  var q = new Meteor._SynchronousQueue;\n  var output = [];\n  var pusher = function (n) {\n    return function () {\n      output.push(n);\n    };\n  };\n  var outputIsUpTo = function (n) {\n    test.equal(output, _.range(1, n+1));\n  };\n\n  // Queue a task. It cannot run until we yield.\n  q.queueTask(pusher(1));\n  outputIsUpTo(0);\n\n  // Run another task. After queueing it, the fiber constructed here will yield\n  // back to this outer function. No task can have run yet since the main test\n  // fiber still will not have yielded.\n  var runTask2Done = false;\n  Fiber(function () {\n    q.runTask(pusher(2));\n    runTask2Done = true;\n  }).run();\n  outputIsUpTo(0);\n  test.isFalse(runTask2Done);\n\n  // Queue a third task. Still no outer yields, so still no runs.\n  q.queueTask(function () {\n    output.push(3);\n    // This task gets queued once we actually start running functions, which\n    // isn't until the runTask(pusher(4)), so it gets queued after Task #4.\n    q.queueTask(pusher(5));\n  });\n  outputIsUpTo(0);\n  test.isFalse(runTask2Done);\n\n  // Run a task and block for it to be done. All queued tasks up to this one\n  // will now be run.\n  q.runTask(pusher(4));\n  outputIsUpTo(4);\n  test.isTrue(runTask2Done);\n\n  // Task #5 is still in the queue. Run another task synchronously.\n  q.runTask(pusher(6));\n  outputIsUpTo(6);\n\n  // Queue a task that throws. It'll write some debug output, but that's it.\n  Meteor._suppress_log(1);\n  q.queueTask(function () {\n    throw new Error(\"bla\");\n  });\n  // let it run.\n  q.runTask(pusher(7));\n  outputIsUpTo(7);\n\n  // Run a task that throws. It should throw from runTask.\n  Meteor._suppress_log(1);\n  test.throws(function () {\n    q.runTask(function () {\n      throw new Error(\"this is thrown\");\n    });\n  });\n});\n"
  },
  {
    "path": "packages/meteor/fiber_stubs_client.js",
    "content": "// This file is a partial analogue to fiber_helpers.js, which allows the client\n// to use a queue too, and also to call noYieldsAllowed.\n\n// The client has no ability to yield, so noYieldsAllowed is a noop.\n//\nMeteor._noYieldsAllowed = function (f) {\n  return f();\n};\n\n// An even simpler queue of tasks than the fiber-enabled one.  This one just\n// runs all the tasks when you call runTask or flush, synchronously.\n//\nMeteor._SynchronousQueue = function () {\n  var self = this;\n  self._tasks = [];\n  self._running = false;\n  self._runTimeout = null;\n};\n\n_.extend(Meteor._SynchronousQueue.prototype, {\n  runTask: function (task) {\n    var self = this;\n    if (!self.safeToRunTask())\n      throw new Error(\"Could not synchronously run a task from a running task\");\n    self._tasks.push(task);\n    var tasks = self._tasks;\n    self._tasks = [];\n    self._running = true;\n\n    if (self._runTimeout) {\n      // Since we're going to drain the queue, we can forget about the timeout\n      // which tries to run it.  (But if one of our tasks queues something else,\n      // the timeout will be correctly re-created.)\n      clearTimeout(self._runTimeout);\n      self._runTimeout = null;\n    }\n\n    try {\n      while (!_.isEmpty(tasks)) {\n        var t = tasks.shift();\n        try {\n          t();\n        } catch (e) {\n          if (_.isEmpty(tasks)) {\n            // this was the last task, that is, the one we're calling runTask\n            // for.\n            throw e;\n          } else {\n            Meteor._debug(\"Exception in queued task: \" + (e.stack || e));\n          }\n        }\n      }\n    } finally {\n      self._running = false;\n    }\n  },\n\n  queueTask: function (task) {\n    var self = this;\n    self._tasks.push(task);\n    // Intentionally not using Meteor.setTimeout, because it doesn't like runing\n    // in stubs for now.\n    if (!self._runTimeout) {\n      self._runTimeout = setTimeout(_.bind(self.flush, self), 0);\n    }\n  },\n\n  flush: function () {\n    var self = this;\n    self.runTask(function () {});\n  },\n\n  drain: function () {\n    var self = this;\n    if (!self.safeToRunTask())\n      return;\n    while (!_.isEmpty(self._tasks)) {\n      self.flush();\n    }\n  },\n\n  safeToRunTask: function () {\n    var self = this;\n    return !self._running;\n  }\n});\n"
  },
  {
    "path": "packages/meteor/flush-buffers-on-exit-in-windows.js",
    "content": "if (process.platform === \"win32\") {\n  /*\n   * Based on https://github.com/cowboy/node-exit\n   *\n   * Copyright (c) 2013 \"Cowboy\" Ben Alman\n   * Licensed under the MIT license.\n   */\n  var origProcessExit = process.exit.bind(process);\n  process.exit = function (exitCode) {\n    var streams = [process.stdout, process.stderr];\n    var drainCount = 0;\n    // Actually exit if all streams are drained.\n    function tryToExit() {\n      if (drainCount === streams.length) {\n        origProcessExit(exitCode);\n      }\n    }\n    streams.forEach(function(stream) {\n      // Count drained streams now, but monitor non-drained streams.\n      if (stream.bufferSize === 0) {\n        drainCount++;\n      } else {\n        stream.write('', 'utf-8', function() {\n          drainCount++;\n          tryToExit();\n        });\n      }\n      // Prevent further writing.\n      stream.write = function() {};\n    });\n    // If all streams were already drained, exit now.\n    tryToExit();\n    // In Windows, when run as a Node.js child process, a script utilizing\n    // this library might just exit with a 0 exit code, regardless. This code,\n    // despite the fact that it looks a bit crazy, appears to fix that.\n    process.on('exit', function() {\n      origProcessExit(exitCode);\n    });\n  };\n}"
  },
  {
    "path": "packages/meteor/global.js",
    "content": "global = this;\n"
  },
  {
    "path": "packages/meteor/helpers.js",
    "content": "if (Meteor.isServer)\n  var Future = Npm.require('fibers/future');\n\nif (typeof __meteor_runtime_config__ === 'object' &&\n    __meteor_runtime_config__.meteorRelease) {\n  /**\n   * @summary `Meteor.release` is a string containing the name of the [release](#meteorupdate) with which the project was built (for example, `\"1.2.3\"`). It is `undefined` if the project was built using a git checkout of Meteor.\n   * @locus Anywhere\n   * @type {String}\n   */\n  Meteor.release = __meteor_runtime_config__.meteorRelease;\n}\n\n// XXX find a better home for these? Ideally they would be _.get,\n// _.ensure, _.delete..\n\n_.extend(Meteor, {\n  // _get(a,b,c,d) returns a[b][c][d], or else undefined if a[b] or\n  // a[b][c] doesn't exist.\n  //\n  _get: function (obj /*, arguments */) {\n    for (var i = 1; i < arguments.length; i++) {\n      if (!(arguments[i] in obj))\n        return undefined;\n      obj = obj[arguments[i]];\n    }\n    return obj;\n  },\n\n  // _ensure(a,b,c,d) ensures that a[b][c][d] exists. If it does not,\n  // it is created and set to {}. Either way, it is returned.\n  //\n  _ensure: function (obj /*, arguments */) {\n    for (var i = 1; i < arguments.length; i++) {\n      var key = arguments[i];\n      if (!(key in obj))\n        obj[key] = {};\n      obj = obj[key];\n    }\n\n    return obj;\n  },\n\n  // _delete(a, b, c, d) deletes a[b][c][d], then a[b][c] unless it\n  // isn't empty, then a[b] unless it isn't empty.\n  //\n  _delete: function (obj /*, arguments */) {\n    var stack = [obj];\n    var leaf = true;\n    for (var i = 1; i < arguments.length - 1; i++) {\n      var key = arguments[i];\n      if (!(key in obj)) {\n        leaf = false;\n        break;\n      }\n      obj = obj[key];\n      if (typeof obj !== \"object\")\n        break;\n      stack.push(obj);\n    }\n\n    for (var i = stack.length - 1; i >= 0; i--) {\n      var key = arguments[i+1];\n\n      if (leaf)\n        leaf = false;\n      else\n        for (var other in stack[i][key])\n          return; // not empty -- we're done\n\n      delete stack[i][key];\n    }\n  },\n\n  // wrapAsync can wrap any function that takes some number of arguments that\n  // can't be undefined, followed by some optional arguments, where the callback\n  // is the last optional argument.\n  // e.g. fs.readFile(pathname, [callback]),\n  // fs.open(pathname, flags, [mode], [callback])\n  // For maximum effectiveness and least confusion, wrapAsync should be used on\n  // functions where the callback is the only argument of type Function.\n\n  /**\n   * @memberOf Meteor\n   * @summary Wrap a function that takes a callback function as its final parameter. The signature of the callback of the wrapped function should be `function(error, result){}`. On the server, the wrapped function can be used either synchronously (without passing a callback) or asynchronously (when a callback is passed). On the client, a callback is always required; errors will be logged if there is no callback. If a callback is provided, the environment captured when the original function was called will be restored in the callback.\n   * @locus Anywhere\n   * @param {Function} func A function that takes a callback as its final parameter\n   * @param {Object} [context] Optional `this` object against which the original function will be invoked\n   */\n  wrapAsync: function (fn, context) {\n    return function (/* arguments */) {\n      var self = context || this;\n      var newArgs = _.toArray(arguments);\n      var callback;\n\n      for (var i = newArgs.length - 1; i >= 0; --i) {\n        var arg = newArgs[i];\n        var type = typeof arg;\n        if (type !== \"undefined\") {\n          if (type === \"function\") {\n            callback = arg;\n          }\n          break;\n        }\n      }\n\n      if (! callback) {\n        if (Meteor.isClient) {\n          callback = logErr;\n        } else {\n          var fut = new Future();\n          callback = fut.resolver();\n        }\n        ++i; // Insert the callback just after arg.\n      }\n\n      newArgs[i] = Meteor.bindEnvironment(callback);\n      var result = fn.apply(self, newArgs);\n      return fut ? fut.wait() : result;\n    };\n  },\n\n  // Sets child's prototype to a new object whose prototype is parent's\n  // prototype. Used as:\n  //   Meteor._inherits(ClassB, ClassA).\n  //   _.extend(ClassB.prototype, { ... })\n  // Inspired by CoffeeScript's `extend` and Google Closure's `goog.inherits`.\n  _inherits: function (Child, Parent) {\n    // copy Parent static properties\n    for (var key in Parent) {\n      // make sure we only copy hasOwnProperty properties vs. prototype\n      // properties\n      if (_.has(Parent, key))\n        Child[key] = Parent[key];\n    }\n\n    // a middle member of prototype chain: takes the prototype from the Parent\n    var Middle = function () {\n      this.constructor = Child;\n    };\n    Middle.prototype = Parent.prototype;\n    Child.prototype = new Middle();\n    Child.__super__ = Parent.prototype;\n    return Child;\n  }\n});\n\nvar warnedAboutWrapAsync = false;\n\n/**\n * @deprecated in 0.9.3\n */\nMeteor._wrapAsync = function(fn, context) {\n  if (! warnedAboutWrapAsync) {\n    Meteor._debug(\"Meteor._wrapAsync has been renamed to Meteor.wrapAsync\");\n    warnedAboutWrapAsync = true;\n  }\n  return Meteor.wrapAsync.apply(Meteor, arguments);\n};\n\nfunction logErr(err) {\n  if (err) {\n    return Meteor._debug(\n      \"Exception in callback of async function\",\n      err.stack ? err.stack : err\n    );\n  }\n}\n"
  },
  {
    "path": "packages/meteor/helpers_test.js",
    "content": "Tinytest.add(\"environment - helpers\", function (test) {\n  /*** ensure ***/\n  var x = {};\n  var y = Meteor._ensure(x, \"a\", \"b\", \"c\");\n  test.equal(x, {a: {b: {c: {}}}});\n  test.equal(y, {});\n  y.d = 12;\n  test.equal(x, {a: {b: {c: {d: 12}}}});\n  test.equal(y, {d: 12});\n\n  y = Meteor._ensure(x, \"a\", \"b\", \"c\");\n  test.equal(x, {a: {b: {c: {d: 12}}}});\n  test.equal(y, {d: 12});\n  y.x = 13;\n  test.equal(x, {a: {b: {c: {d: 12, x: 13}}}});\n  test.equal(y, {d: 12, x: 13});\n\n  y = Meteor._ensure(x, \"a\", \"n\");\n  test.equal(x, {a: {b: {c: {d: 12, x: 13}}, n: {}}});\n  test.equal(y, {});\n  y.d = 22;\n  test.equal(x, {a: {b: {c: {d: 12, x: 13}}, n: {d: 22}}});\n  test.equal(y, {d: 22});\n\n  Meteor._ensure(x, \"a\", \"q\", \"r\")[\"s\"] = 99\n  test.equal(x, {a: {b: {c: {d: 12, x: 13}}, n: {d: 22}, q: {r: {s: 99}}}});\n\n  Meteor._ensure(x, \"b\")[\"z\"] = 44;\n  test.equal(x, {a: {b: {c: {d: 12, x: 13}}, n: {d: 22}, q: {r: {s: 99}}},\n                 b: {z: 44}});\n\n  /*** delete ***/\n\n  x = {};\n  Meteor._delete(x, \"a\", \"b\", \"c\");\n  test.equal(x, {});\n\n  x = {a: {b: {}}};\n  Meteor._delete(x, \"a\", \"b\", \"c\");\n  test.equal(x, {});\n\n  x = {a: {b: {}, n: {}}};\n  Meteor._delete(x, \"a\", \"b\", \"c\");\n  test.equal(x, {a: {n: {}}});\n\n  x = {a: {b: {}}, n: {}};\n  Meteor._delete(x, \"a\", \"b\", \"c\");\n  test.equal(x, {n: {}});\n\n  x = {a: {b: 99}};\n  Meteor._delete(x, \"a\", \"b\", \"c\");\n  test.equal(x, {});\n\n  x = {a: {b: 99}};\n  Meteor._delete(x, \"a\", \"b\", \"c\", \"d\");\n  test.equal(x, {});\n\n  x = {a: {b: 99}};\n  Meteor._delete(x, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\");\n  test.equal(x, {});\n\n  x = {a: {b: {c: {d: 99}}}, x: 12};\n  Meteor._delete(x, \"a\", \"b\", \"c\", \"d\");\n  test.equal(x, {x: 12});\n\n  x = {a: {b: {c: {d: 99}}, x: 12}};\n  Meteor._delete(x, \"a\", \"b\", \"c\", \"d\");\n  test.equal(x, {a: {x: 12}});\n\n  x = {a: 12, b: 13};\n  Meteor._delete(x, \"a\");\n  test.equal(x, {b: 13});\n\n  x = {a: 12};\n  Meteor._delete(x, \"a\");\n  test.equal(x, {});\n\n  /*** inherits ***/\n  var Parent = function () {};\n  Parent.parentStaticProp = true;\n  Parent.prototype.parentProp = true;\n\n  var Child = function () {};\n  Meteor._inherits(Child, Parent);\n\n  Child.prototype.childProp = true;\n\n  test.isTrue(Child.parentStaticProp, 'copy parent static props');\n  test.equal(Child.__super__, Parent.prototype, '__super__ is set');\n\n  var c = new Child;\n  test.isTrue(c.parentProp, 'prototype chain hooked up correctly');\n});\n\nTinytest.add(\"environment - startup\", function (test) {\n  // After startup, Meteor.startup should call the callback immediately.\n  var called = false;\n  Meteor.startup(function () {\n    called = true;\n  });\n  test.isTrue(called);\n});\n"
  },
  {
    "path": "packages/meteor/package.js",
    "content": "// All other packages automatically depend on this one\n\nPackage.describe({\n  summary: \"Core Meteor environment\",\n  version: '1.1.15_1'\n});\n\nPackage.registerBuildPlugin({\n  name: \"basicFileTypes\",\n  sources: ['plugin/basic-file-types.js']\n});\n\nNpm.depends({\n  \"meteor-deque\": \"2.1.0\"\n});\n\nPackage.onUse(function (api) {\n  api.use('underscore', ['client', 'server']);\n\n  api.use('isobuild:compiler-plugin@1.0.0');\n\n  api.export('Meteor');\n\n  api.addFiles('global.js', ['client', 'server']);\n  api.export('global');\n\n  api.addFiles('client_environment.js', 'client');\n  api.addFiles('server_environment.js', 'server');\n  // Defined by client_environment.js and server_environment.js.\n  api.export(\"meteorEnv\");\n\n  api.addFiles('cordova_environment.js', 'web.cordova');\n  api.addFiles('helpers.js', ['client', 'server']);\n  api.addFiles('setimmediate.js', ['client', 'server']);\n  api.addFiles('timers.js', ['client', 'server']);\n  api.addFiles('errors.js', ['client', 'server']);\n  api.addFiles('fiber_helpers.js', 'server');\n  api.addFiles('fiber_stubs_client.js', 'client');\n  api.addFiles('startup_client.js', ['client']);\n  api.addFiles('startup_server.js', ['server']);\n  api.addFiles('debug.js', ['client', 'server']);\n  api.addFiles('string_utils.js', ['client', 'server']);\n  api.addFiles('test_environment.js', ['client', 'server']);\n  \n  // dynamic variables, bindEnvironment\n  // XXX move into a separate package?\n  api.addFiles('dynamics_browser.js', 'client');\n  api.addFiles('dynamics_nodejs.js', 'server');\n\n  // note server before common. usually it is the other way around, but\n  // in this case server must load first.\n  api.addFiles('url_server.js', 'server');\n  api.addFiles('url_common.js', ['client', 'server']);\n\n  // People expect process.exit() to not swallow console output.\n  // On Windows, it sometimes does, so we fix it for all apps and packages\n  api.addFiles('flush-buffers-on-exit-in-windows.js', 'server');\n});\n\nPackage.onTest(function (api) {\n  api.use(['underscore', 'tinytest', 'test-helpers']);\n\n  api.addFiles('browser_environment_test.js', 'web.browser');\n  api.addFiles('client_environment_test.js', 'client');\n  api.addFiles('cordova_environment_test.js', 'web.cordova');\n  api.addFiles('server_environment_test.js', 'server');\n\n  api.addFiles('helpers_test.js', ['client', 'server']);\n  api.addFiles('dynamics_test.js', ['client', 'server']);\n\n  api.addFiles('fiber_helpers_test.js', ['server']);\n  api.addFiles('wrapasync_test.js', ['server']);\n\n  api.addFiles('url_tests.js', ['client', 'server']);\n\n  api.addFiles('timers_tests.js', ['client', 'server']);\n\n  api.addFiles('debug_test.js', 'client');\n\n  api.addFiles('bare_test_setup.js', 'client', {bare: true});\n  api.addFiles('bare_tests.js', 'client');\n});\n"
  },
  {
    "path": "packages/meteor/plugin/basic-file-types.js",
    "content": "/* \"js\" handler is now hardcoded in packages.js.. necessarily, because\n   we can't exactly define the *.js source file handler in a *.js\n   source file. */\n\nPlugin.registerCompiler({\n  extensions: ['css'],\n  archMatching: 'web'\n}, function () {\n  return new CssCompiler;\n});\n\nvar CssCompiler = function () {\n};\nCssCompiler.prototype.processFilesForTarget = function (inputFiles) {\n  inputFiles.forEach(function (inputFile) {\n    inputFile.addStylesheet({\n      data: inputFile.getContentsAsString(),\n      path: inputFile.getPathInPackage()\n    });\n  });\n};\n"
  },
  {
    "path": "packages/meteor/server_environment.js",
    "content": "meteorEnv = {\n  NODE_ENV: process.env.NODE_ENV || \"production\",\n  TEST_METADATA: process.env.TEST_METADATA || \"{}\"\n};\n\nif (typeof __meteor_runtime_config__ === \"object\") {\n  __meteor_runtime_config__.meteorEnv = meteorEnv;\n}\n\nMeteor = {\n  isProduction: meteorEnv.NODE_ENV === \"production\",\n  isDevelopment: meteorEnv.NODE_ENV !== \"production\",\n  isClient: false,\n  isServer: true,\n  isCordova: false\n};\n\nMeteor.settings = {};\n\nif (process.env.METEOR_SETTINGS) {\n  try {\n    Meteor.settings = JSON.parse(process.env.METEOR_SETTINGS);\n  } catch (e) {\n    throw new Error(\"METEOR_SETTINGS are not valid JSON: \" + process.env.METEOR_SETTINGS);\n  }\n}\n\n// Make sure that there is always a public attribute\n// to enable Meteor.settings.public on client\nif (! Meteor.settings.public) {\n    Meteor.settings.public = {};\n}\n\n// Push a subset of settings to the client.  Note that the way this\n// code is written, if the app mutates `Meteor.settings.public` on the\n// server, it also mutates\n// `__meteor_runtime_config__.PUBLIC_SETTINGS`, and the modified\n// settings will be sent to the client.\nif (typeof __meteor_runtime_config__ === \"object\") {\n  __meteor_runtime_config__.PUBLIC_SETTINGS = Meteor.settings.public;\n}\n"
  },
  {
    "path": "packages/meteor/server_environment_test.js",
    "content": "Tinytest.add(\"environment - server basics\", function (test) {\n  test.isFalse(Meteor.isClient);\n  test.isTrue(Meteor.isServer);\n  test.isFalse(Meteor.isCordova);\n});\n"
  },
  {
    "path": "packages/meteor/setimmediate.js",
    "content": "// Chooses one of three setImmediate implementations:\n//\n// * Native setImmediate (IE 10, Node 0.9+)\n//\n// * postMessage (many browsers)\n//\n// * setTimeout  (fallback)\n//\n// The postMessage implementation is based on\n// https://github.com/NobleJS/setImmediate/tree/1.0.1\n//\n// Don't use `nextTick` for Node since it runs its callbacks before\n// I/O, which is stricter than we're looking for.\n//\n// Not installed as a polyfill, as our public API is `Meteor.defer`.\n// Since we're not trying to be a polyfill, we have some\n// simplifications:\n//\n// If one invocation of a setImmediate callback pauses itself by a\n// call to alert/prompt/showModelDialog, the NobleJS polyfill\n// implementation ensured that no setImmedate callback would run until\n// the first invocation completed.  While correct per the spec, what it\n// would mean for us in practice is that any reactive updates relying\n// on Meteor.defer would be hung in the main window until the modal\n// dialog was dismissed.  Thus we only ensure that a setImmediate\n// function is called in a later event loop.\n//\n// We don't need to support using a string to be eval'ed for the\n// callback, arguments to the function, or clearImmediate.\n\n\"use strict\";\n\nvar global = this;\n\n\n// IE 10, Node >= 9.1\n\nfunction useSetImmediate() {\n  if (! global.setImmediate)\n    return null;\n  else {\n    var setImmediate = function (fn) {\n      global.setImmediate(fn);\n    };\n    setImmediate.implementation = 'setImmediate';\n    return setImmediate;\n  }\n}\n\n\n// Android 2.3.6, Chrome 26, Firefox 20, IE 8-9, iOS 5.1.1 Safari\n\nfunction usePostMessage() {\n  // The test against `importScripts` prevents this implementation\n  // from being installed inside a web worker, where\n  // `global.postMessage` means something completely different and\n  // can't be used for this purpose.\n\n  if (!global.postMessage || global.importScripts) {\n    return null;\n  }\n\n  // Avoid synchronous post message implementations.\n\n  var postMessageIsAsynchronous = true;\n  var oldOnMessage = global.onmessage;\n  global.onmessage = function () {\n      postMessageIsAsynchronous = false;\n  };\n  global.postMessage(\"\", \"*\");\n  global.onmessage = oldOnMessage;\n\n  if (! postMessageIsAsynchronous)\n    return null;\n\n  var funcIndex = 0;\n  var funcs = {};\n\n  // Installs an event handler on `global` for the `message` event: see\n  // * https://developer.mozilla.org/en/DOM/window.postMessage\n  // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages\n\n  // XXX use Random.id() here?\n  var MESSAGE_PREFIX = \"Meteor._setImmediate.\" + Math.random() + '.';\n\n  function isStringAndStartsWith(string, putativeStart) {\n    return (typeof string === \"string\" &&\n            string.substring(0, putativeStart.length) === putativeStart);\n  }\n\n  function onGlobalMessage(event) {\n    // This will catch all incoming messages (even from other\n    // windows!), so we need to try reasonably hard to avoid letting\n    // anyone else trick us into firing off. We test the origin is\n    // still this window, and that a (randomly generated)\n    // unpredictable identifying prefix is present.\n    if (event.source === global &&\n        isStringAndStartsWith(event.data, MESSAGE_PREFIX)) {\n      var index = event.data.substring(MESSAGE_PREFIX.length);\n      try {\n        if (funcs[index])\n          funcs[index]();\n      }\n      finally {\n        delete funcs[index];\n      }\n    }\n  }\n\n  if (global.addEventListener) {\n    global.addEventListener(\"message\", onGlobalMessage, false);\n  } else {\n    global.attachEvent(\"onmessage\", onGlobalMessage);\n  }\n\n  var setImmediate = function (fn) {\n    // Make `global` post a message to itself with the handle and\n    // identifying prefix, thus asynchronously invoking our\n    // onGlobalMessage listener above.\n    ++funcIndex;\n    funcs[funcIndex] = fn;\n    global.postMessage(MESSAGE_PREFIX + funcIndex, \"*\");\n  };\n  setImmediate.implementation = 'postMessage';\n  return setImmediate;\n}\n\n\nfunction useTimeout() {\n  var setImmediate = function (fn) {\n    global.setTimeout(fn, 0);\n  };\n  setImmediate.implementation = 'setTimeout';\n  return setImmediate;\n}\n\n\nMeteor._setImmediate =\n  useSetImmediate() ||\n  usePostMessage() ||\n  useTimeout();\n"
  },
  {
    "path": "packages/meteor/startup_client.js",
    "content": "var callbackQueue = [];\nvar isLoadingCompleted = false;\nvar isReady = false;\n\n// Keeps track of how many events to wait for in addition to loading completing,\n// before we're considered ready.\nvar readyHoldsCount = 0;\n\nvar holdReady =  function () {\n  readyHoldsCount++;\n}\n\nvar releaseReadyHold = function () {\n  readyHoldsCount--;\n  maybeReady();\n}\n\nvar maybeReady = function () {\n  if (isReady || !isLoadingCompleted || readyHoldsCount > 0)\n    return;\n\n  isReady = true;\n\n  // Run startup callbacks\n  while (callbackQueue.length)\n    (callbackQueue.shift())();\n\n  if (Meteor.isCordova) {\n    // Notify the WebAppLocalServer plugin that startup was completed successfully,\n    // so we can roll back faulty versions if this doesn't happen\n    WebAppLocalServer.startupDidComplete();\n  }\n};\n\nvar loadingCompleted = function () {\n  if (!isLoadingCompleted) {\n    isLoadingCompleted = true;\n    maybeReady();\n  }\n}\n\nif (Meteor.isCordova) {\n  holdReady();\n  document.addEventListener('deviceready', releaseReadyHold, false);\n}\n\nif (document.readyState === 'complete' || document.readyState === 'loaded') {\n  // Loading has completed,\n  // but allow other scripts the opportunity to hold ready\n  window.setTimeout(loadingCompleted);\n} else { // Attach event listeners to wait for loading to complete\n  if (document.addEventListener) {\n    document.addEventListener('DOMContentLoaded', loadingCompleted, false);\n    window.addEventListener('load', loadingCompleted, false);\n  } else { // Use IE event model for < IE9\n    document.attachEvent('onreadystatechange', function () {\n      if (document.readyState === \"complete\") {\n        loadingCompleted();\n      }\n    });\n    window.attachEvent('load', loadingCompleted);\n  }\n}\n\n/**\n * @summary Run code when a client or a server starts.\n * @locus Anywhere\n * @param {Function} func A function to run on startup.\n */\nMeteor.startup = function (callback) {\n  // Fix for < IE9, see http://javascript.nwbox.com/IEContentLoaded/\n  var doScroll = !document.addEventListener &&\n    document.documentElement.doScroll;\n\n  if (!doScroll || window !== top) {\n    if (isReady)\n      callback();\n    else\n      callbackQueue.push(callback);\n  } else {\n    try { doScroll('left'); }\n    catch (error) {\n      setTimeout(function () { Meteor.startup(callback); }, 50);\n      return;\n    };\n    callback();\n  }\n};\n"
  },
  {
    "path": "packages/meteor/startup_server.js",
    "content": "Meteor.startup = function (callback) {\n  if (__meteor_bootstrap__.startupHooks) {\n    __meteor_bootstrap__.startupHooks.push(callback);\n  } else {\n    // We already started up. Just call it now.\n    callback();\n  }\n};\n"
  },
  {
    "path": "packages/meteor/string_utils.js",
    "content": "// Like Perl's quotemeta: quotes all regexp metacharacters.\n// Code taken from\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\nMeteor._escapeRegExp = function (string) {\n    return String(string).replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n};\n"
  },
  {
    "path": "packages/meteor/test_environment.js",
    "content": "var TEST_METADATA_STR;\nif (Meteor.isClient) {\n  TEST_METADATA_STR = meteorEnv.TEST_METADATA;\n} else {\n  TEST_METADATA_STR = process.env.TEST_METADATA;\n}\n\nvar TEST_METADATA = JSON.parse(TEST_METADATA_STR || \"{}\");\nvar testDriverPackageName = TEST_METADATA.driverPackage;\n\n// Note that if we are in test-packages mode neither of these will be set,\n// but we will have a test driver package\nMeteor.isTest = !!TEST_METADATA.isTest;\nMeteor.isAppTest = !!TEST_METADATA.isAppTest;\nMeteor.isPackageTest = !!testDriverPackageName && !Meteor.isTest && !Meteor.isAppTest; \n\nif (typeof testDriverPackageName === \"string\") {\n  Meteor.startup(function() {\n    var testDriverPackage = Package[testDriverPackageName];\n    if (! testDriverPackage) {\n      throw new Error(\"Can't find test driver package: \" + testDriverPackageName);\n    }\n\n    // On the client, the test driver *must* define `runTests`\n    if (Meteor.isClient) {\n      if (typeof testDriverPackage.runTests !== \"function\") {\n        throw new Error(\"Test driver package \" + testDriverPackageName\n          + \" missing `runTests` export\");\n      }\n      testDriverPackage.runTests();\n    } else {\n      // The server can optionally define `start`\n      if (typeof testDriverPackage.start === \"function\") {\n        testDriverPackage.start();\n      }\n    }\n  });\n}\n"
  },
  {
    "path": "packages/meteor/timers.js",
    "content": "var withoutInvocation = function (f) {\n  if (Package.ddp) {\n    var _CurrentInvocation = Package.ddp.DDP._CurrentInvocation;\n    if (_CurrentInvocation.get() && _CurrentInvocation.get().isSimulation)\n      throw new Error(\"Can't set timers inside simulations\");\n    return function () { _CurrentInvocation.withValue(null, f); };\n  }\n  else\n    return f;\n};\n\nvar bindAndCatch = function (context, f) {\n  return Meteor.bindEnvironment(withoutInvocation(f), context);\n};\n\n_.extend(Meteor, {\n  // Meteor.setTimeout and Meteor.setInterval callbacks scheduled\n  // inside a server method are not part of the method invocation and\n  // should clear out the CurrentInvocation environment variable.\n\n  /**\n   * @memberOf Meteor\n   * @summary Call a function in the future after waiting for a specified delay.\n   * @locus Anywhere\n   * @param {Function} func The function to run\n   * @param {Number} delay Number of milliseconds to wait before calling function\n   */\n  setTimeout: function (f, duration) {\n    return setTimeout(bindAndCatch(\"setTimeout callback\", f), duration);\n  },\n\n  /**\n   * @memberOf Meteor\n   * @summary Call a function repeatedly, with a time delay between calls.\n   * @locus Anywhere\n   * @param {Function} func The function to run\n   * @param {Number} delay Number of milliseconds to wait between each function call.\n   */\n  setInterval: function (f, duration) {\n    return setInterval(bindAndCatch(\"setInterval callback\", f), duration);\n  },\n\n  /**\n   * @memberOf Meteor\n   * @summary Cancel a repeating function call scheduled by `Meteor.setInterval`.\n   * @locus Anywhere\n   * @param {Number} id The handle returned by `Meteor.setInterval`\n   */\n  clearInterval: function(x) {\n    return clearInterval(x);\n  },\n\n  /**\n   * @memberOf Meteor\n   * @summary Cancel a function call scheduled by `Meteor.setTimeout`.\n   * @locus Anywhere\n   * @param {Number} id The handle returned by `Meteor.setTimeout`\n   */\n  clearTimeout: function(x) {\n    return clearTimeout(x);\n  },\n\n  // XXX consider making this guarantee ordering of defer'd callbacks, like\n  // Tracker.afterFlush or Node's nextTick (in practice). Then tests can do:\n  //    callSomethingThatDefersSomeWork();\n  //    Meteor.defer(expect(somethingThatValidatesThatTheWorkHappened));\n\n  /**\n   * @memberOf Meteor\n   * @summary Defer execution of a function to run asynchronously in the background (similar to `Meteor.setTimeout(func, 0)`.\n   * @locus Anywhere\n   * @param {Function} func The function to run\n   */\n  defer: function (f) {\n    Meteor._setImmediate(bindAndCatch(\"defer callback\", f));\n  }\n});\n"
  },
  {
    "path": "packages/meteor/timers_tests.js",
    "content": "Tinytest.addAsync('timers - defer', function (test, onComplete) {\n  var x = 'a';\n  Meteor.defer(function () {\n    test.equal(x, 'b');\n    onComplete();\n  });\n  x = 'b';\n});\n\nTinytest.addAsync('timers - nested defer', function (test, onComplete) {\n  var x = 'a';\n  Meteor.defer(function () {\n    test.equal(x, 'b');\n    Meteor.defer(function () {\n      test.equal(x, 'c');\n      onComplete();\n    });\n    x = 'c';\n  });\n  x = 'b';\n});\n"
  },
  {
    "path": "packages/meteor/url_common.js",
    "content": "/**\n * @summary Generate an absolute URL pointing to the application. The server reads from the `ROOT_URL` environment variable to determine where it is running. This is taken care of automatically for apps deployed to Galaxy, but must be provided when using `meteor build`.\n * @locus Anywhere\n * @param {String} [path] A path to append to the root URL. Do not include a leading \"`/`\".\n * @param {Object} [options]\n * @param {Boolean} options.secure Create an HTTPS URL.\n * @param {Boolean} options.replaceLocalhost Replace localhost with 127.0.0.1. Useful for services that don't recognize localhost as a domain name.\n * @param {String} options.rootUrl Override the default ROOT_URL from the server environment. For example: \"`http://foo.example.com`\"\n */\nMeteor.absoluteUrl = function (path, options) {\n  // path is optional\n  if (!options && typeof path === 'object') {\n    options = path;\n    path = undefined;\n  }\n  // merge options with defaults\n  options = _.extend({}, Meteor.absoluteUrl.defaultOptions, options || {});\n\n  var url = options.rootUrl;\n  if (!url)\n    throw new Error(\"Must pass options.rootUrl or set ROOT_URL in the server environment\");\n\n  if (!/^http[s]?:\\/\\//i.test(url)) // url starts with 'http://' or 'https://'\n    url = 'http://' + url; // we will later fix to https if options.secure is set\n\n  if (!/\\/$/.test(url)) // url ends with '/'\n    url += '/';\n\n  if (path)\n    url += path;\n\n  // turn http to https if secure option is set, and we're not talking\n  // to localhost.\n  if (options.secure &&\n      /^http:/.test(url) && // url starts with 'http:'\n      !/http:\\/\\/localhost[:\\/]/.test(url) && // doesn't match localhost\n      !/http:\\/\\/127\\.0\\.0\\.1[:\\/]/.test(url)) // or 127.0.0.1\n    url = url.replace(/^http:/, 'https:');\n\n  if (options.replaceLocalhost)\n    url = url.replace(/^http:\\/\\/localhost([:\\/].*)/, 'http://127.0.0.1$1');\n\n  return url;\n};\n\n// allow later packages to override default options\nMeteor.absoluteUrl.defaultOptions = { };\nif (typeof __meteor_runtime_config__ === \"object\" &&\n    __meteor_runtime_config__.ROOT_URL)\n  Meteor.absoluteUrl.defaultOptions.rootUrl = __meteor_runtime_config__.ROOT_URL;\n\n\nMeteor._relativeToSiteRootUrl = function (link) {\n  if (typeof __meteor_runtime_config__ === \"object\" &&\n      link.substr(0, 1) === \"/\")\n    link = (__meteor_runtime_config__.ROOT_URL_PATH_PREFIX || \"\") + link;\n  return link;\n};\n"
  },
  {
    "path": "packages/meteor/url_server.js",
    "content": "if (process.env.ROOT_URL &&\n    typeof __meteor_runtime_config__ === \"object\") {\n  __meteor_runtime_config__.ROOT_URL = process.env.ROOT_URL;\n  if (__meteor_runtime_config__.ROOT_URL) {\n    var parsedUrl = Npm.require('url').parse(__meteor_runtime_config__.ROOT_URL);\n    // Sometimes users try to pass, eg, ROOT_URL=mydomain.com.\n    if (!parsedUrl.host) {\n      throw Error(\"$ROOT_URL, if specified, must be an URL\");\n    }\n    var pathPrefix = parsedUrl.pathname;\n    if (pathPrefix.slice(-1) === '/') {\n      // remove trailing slash (or turn \"/\" into \"\")\n      pathPrefix = pathPrefix.slice(0, -1);\n    }\n    __meteor_runtime_config__.ROOT_URL_PATH_PREFIX = pathPrefix;\n  } else {\n    __meteor_runtime_config__.ROOT_URL_PATH_PREFIX = \"\";\n  }\n}\n"
  },
  {
    "path": "packages/meteor/url_tests.js",
    "content": "Tinytest.add(\"absolute-url - basics\", function(test) {\n\n  _.each(['', 'http://'], function (prefix) {\n\n    test.equal(Meteor.absoluteUrl({rootUrl: prefix + 'asdf.com'}),\n               'http://asdf.com/');\n    test.equal(Meteor.absoluteUrl(undefined, {rootUrl: prefix + 'asdf.com'}),\n               'http://asdf.com/');\n    test.equal(Meteor.absoluteUrl(undefined, {rootUrl: prefix + 'asdf.com/'}),\n               'http://asdf.com/');\n\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: prefix + 'asdf.com/'}),\n               'http://asdf.com/foo');\n    test.equal(Meteor.absoluteUrl('/foo', {rootUrl: prefix + 'asdf.com'}),\n               'http://asdf.com//foo');\n    test.equal(Meteor.absoluteUrl('#foo', {rootUrl: prefix + 'asdf.com'}),\n               'http://asdf.com/#foo');\n\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: prefix + 'asdf.com',\n                                          secure: true}),\n               'https://asdf.com/foo');\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: 'https://asdf.com',\n                                          secure: true}),\n               'https://asdf.com/foo');\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: 'https://asdf.com',\n                                          secure: false}),\n               'https://asdf.com/foo');\n\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: prefix + 'localhost',\n                                          secure: true}),\n               'http://localhost/foo');\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: prefix + 'localhost:3000',\n                                          secure: true}),\n               'http://localhost:3000/foo');\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: 'https://localhost:3000',\n                                          secure: true}),\n               'https://localhost:3000/foo');\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: prefix + '127.0.0.1:3000',\n                                          secure: true}),\n               'http://127.0.0.1:3000/foo');\n\n    // test replaceLocalhost\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: prefix + 'localhost:3000',\n                                          replaceLocalhost: true}),\n               'http://127.0.0.1:3000/foo');\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: prefix + 'localhost',\n                                          replaceLocalhost: true}),\n               'http://127.0.0.1/foo');\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: prefix + '127.0.0.1:3000',\n                                          replaceLocalhost: true}),\n               'http://127.0.0.1:3000/foo');\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: prefix + '127.0.0.1',\n                                          replaceLocalhost: true}),\n               'http://127.0.0.1/foo');\n    // don't replace just any localhost\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: prefix + 'foo.com/localhost',\n                                          replaceLocalhost: true}),\n               'http://foo.com/localhost/foo');\n    test.equal(Meteor.absoluteUrl('foo', {rootUrl: prefix + 'foo.localhost.com',\n                                          replaceLocalhost: true}),\n               'http://foo.localhost.com/foo');\n  });\n});\n\n\nTinytest.add(\"absolute-url - environment\", function(test) {\n  // make sure our test runner set the runtime configuration, and this\n  // propagates to the client.\n  test.isTrue(/^http/.test(__meteor_runtime_config__.ROOT_URL));\n});\n"
  },
  {
    "path": "packages/meteor/wrapasync_test.js",
    "content": "var asyncFunction1 = function (x, cb) {\n  setTimeout(function () { cb(null, x); }, 5);\n};\nvar asyncFunction2 = function (x, opt, cb) {\n  if (! cb && opt instanceof Function) {\n    cb = opt;\n    opt = null;\n  }\n  asyncFunction1(x, cb);\n};\nvar asyncFunction3 = function (opt, cb) {\n  if (! cb && opt instanceof Function) {\n    cb = opt;\n    opt = null;\n  }\n  asyncFunction1(3, cb);\n};\nvar asyncFunction4 = function (cb) {\n  asyncFunction1(3, cb);\n};\n\nvar asyncFunction5 = function (cb) {\n  var self = this;\n  setTimeout(function() {\n    cb(null, self);\n  }, 5);\n}\nasyncFunction5.context = {};\n\nvar wrapped1 = Meteor.wrapAsync(asyncFunction1);\nvar wrapped2 = Meteor.wrapAsync(asyncFunction2);\nvar wrapped3 = Meteor.wrapAsync(asyncFunction3);\nvar wrapped4 = Meteor.wrapAsync(asyncFunction4);\nvar wrapped5 = Meteor.wrapAsync(\n  asyncFunction5,\n  asyncFunction5.context\n);\n\nTinytest.add(\"environment - wrapAsync sync\", function (test) {\n  // one required arg and callback\n  test.equal(wrapped1(3), 3);\n  test.equal(wrapped1(3, undefined), 3);\n  // one required arg, optional second arg, callback\n  test.equal(wrapped2(3), 3);\n  test.equal(wrapped2(3, {foo: \"bar\"}), 3);\n  test.equal(wrapped2(3, undefined, undefined), 3);\n  test.equal(wrapped2(3, {foo: \"bar\"}, undefined), 3);\n  // optional first arg, callback\n  test.equal(wrapped3(3), 3);\n  test.equal(wrapped3(3, undefined), 3);\n  test.equal(wrapped3(), 3);\n  test.equal(wrapped3(undefined), 3);\n  // only callback\n  test.equal(wrapped4(), 3);\n  test.equal(wrapped4(undefined), 3);\n  test.equal(wrapped5(), asyncFunction5.context);\n});\n\ntestAsyncMulti(\"environment - wrapAsync async\", [\n  function (test, expect) {\n    var cb = function (result) {\n      return expect(null, result);\n    };\n    // one required arg and callback\n    test.equal(wrapped1(3, cb(3)), undefined);\n    // one required arg, optional second arg, callback\n    test.equal(wrapped2(3, cb(3)), undefined);\n    test.equal(wrapped2(3, {foo: \"bar\"}, cb(3)), undefined);\n    test.equal(wrapped2(3, undefined, cb(3)), undefined);\n    // optional first arg, callback\n    test.equal(wrapped3(3, cb(3)), undefined);\n    test.equal(wrapped3(cb(3)), undefined);\n    test.equal(wrapped3(undefined, cb(3)), undefined);\n    // only callback\n    test.equal(wrapped4(cb(3)), undefined);\n  }\n]);\n\nTinytest.addAsync(\"environment - wrapAsync callback is \" +\n                  \"in fiber\", function (test, onComplete) {\n                    var cb = function (err, result) {\n                      if (Meteor.isServer) {\n                        var Fiber = Npm.require('fibers');\n                        test.isTrue(Fiber.current);\n                      }\n                      onComplete();\n                    };\n                    wrapped1(3, cb);\n                  });\n"
  },
  {
    "path": "packages/meteor-base/README.md",
    "content": "# meteor-base\n\nA default set of packages that almost every app will have. You should only remove this package if you really, really know what you are doing.\n\nIt comes with the following packages:\n\n1. [`meteor`](https://atmospherejs.com/meteor/meteor) - Super basic stuff about the programming environment, and a handler for the `css` file type.\n2. [`webapp`](https://atmospherejs.com/meteor/webapp) - The actual web server that handles connections, serves files, etc.\n3. [`underscore`](https://atmospherejs.com/meteor/underscore) - A library with lots of useful utilities that most of Meteor is built on.\n4. [`hot-code-push`](https://atmospherejs.com/meteor/hot-code-push) - Refresh the client automatically when the server has new code.\n5. [`ddp`](https://atmospherejs.com/meteor/ddp) - A protocol for communicating between the client and server. This is what enables `Meteor.methods`, `Meteor.publish`, `Meteor.subscribe`, etc.\n"
  },
  {
    "path": "packages/meteor-base/package.js",
    "content": "Package.describe({\n  name: 'meteor-base',\n  version: '1.0.4',\n  // Brief, one-line summary of the package.\n  summary: 'Packages that every Meteor app needs',\n  // By default, Meteor will default to using README.md for documentation.\n  // To avoid submitting documentation, set this field to null.\n  documentation: 'README.md'\n});\n\nPackage.onUse(function(api) {\n  api.imply([\n    // Super basic stuff about where your code is running and async utilities\n    'meteor',\n\n    // This package enables making client-server connections; currently Meteor\n    // only supports building client/server web applications so this is not\n    // removable\n    'webapp',\n\n    // Most Meteor core packages depend on Underscore right now\n    'underscore',\n\n    // The protocol and client/server libraries that Meteor uses to send data\n    'ddp',\n    'livedata', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.\n\n    // Push code changes to the client and automatically reload the page\n    'hot-code-push'\n  ]);\n});\n"
  },
  {
    "path": "packages/meteor-developer/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/meteor-developer/README.md",
    "content": "# meteor-developer\n\nAn implementation of the Meteor Developer Account OAuth flow. See the\n[project page](https://www.meteor.com/accounts) on Meteor Accounts for\nmore details."
  },
  {
    "path": "packages/meteor-developer/meteor_developer_client.js",
    "content": "// Request Meteor developer account credentials for the user\n// @param credentialRequestCompleteCallback {Function} Callback function to call on\n//   completion. Takes one argument, credentialToken on success, or Error on\n//   error.\nvar requestCredential = function (options, credentialRequestCompleteCallback) {\n  // support a callback without options\n  if (! credentialRequestCompleteCallback && typeof options === \"function\") {\n    credentialRequestCompleteCallback = options;\n    options = null;\n  }\n\n  var config = ServiceConfiguration.configurations.findOne({\n    service: 'meteor-developer'\n  });\n  if (!config) {\n    credentialRequestCompleteCallback &&\n      credentialRequestCompleteCallback(new ServiceConfiguration.ConfigError());\n    return;\n  }\n\n  var credentialToken = Random.secret();\n\n  var loginStyle = OAuth._loginStyle('meteor-developer', config, options);\n\n  var loginUrl =\n        MeteorDeveloperAccounts._server +\n        \"/oauth2/authorize?\" +\n        \"state=\" + OAuth._stateParam(loginStyle, credentialToken, options && options.redirectUrl) +\n        \"&response_type=code&\" +\n        \"client_id=\" + config.clientId;\n\n  /**\n   * @deprecated in 1.3.0\n   */\n  if (options && options.userEmail && !options.loginHint) {\n    options.loginHint = options.userEmail;\n    delete options.userEmail;\n  }\n\n  if (options && options.loginHint) {\n    loginUrl += '&user_email=' + encodeURIComponent(options.loginHint);\n  }\n\n  loginUrl += \"&redirect_uri=\" + OAuth._redirectUri('meteor-developer', config);\n\n  OAuth.launchLogin({\n    loginService: \"meteor-developer\",\n    loginStyle: loginStyle,\n    loginUrl: loginUrl,\n    credentialRequestCompleteCallback: credentialRequestCompleteCallback,\n    credentialToken: credentialToken,\n    popupOptions: {width: 470, height: 490}\n  });\n};\n\nMeteorDeveloperAccounts.requestCredential = requestCredential;\n"
  },
  {
    "path": "packages/meteor-developer/meteor_developer_common.js",
    "content": "MeteorDeveloperAccounts = {};\n\nMeteorDeveloperAccounts._server = \"https://www.meteor.com\";\n\n// Options are:\n//  - developerAccountsServer: defaults to \"https://www.meteor.com\"\nMeteorDeveloperAccounts._config = function (options) {\n  if (options.developerAccountsServer) {\n    MeteorDeveloperAccounts._server = options.developerAccountsServer;\n  }\n};\n"
  },
  {
    "path": "packages/meteor-developer/meteor_developer_configure.html",
    "content": "<template name=\"configureLoginServiceDialogForMeteorDeveloper\">\n  <p>\n    First, you'll need to get a Meteor developer account Client ID.\n    Follow these steps:\n  </p>\n  <ol>\n    <li> Visit <a href=\"https://www.meteor.com/account-settings\" target=\"_blank\">https://www.meteor.com/account-settings</a> and sign in.\n    </li>\n    <li> Click \"New app\" in the \"Meteor developer account apps\" section\n      and give your app a name.</li>\n    <li> Add\n      <span class=\"url\">\n        {{siteUrl}}_oauth/meteor-developer\n      </span>\n      as an Allowed Redirect URL.\n    </li>\n  </ol>\n</template>\n"
  },
  {
    "path": "packages/meteor-developer/meteor_developer_configure.js",
    "content": "Template.configureLoginServiceDialogForMeteorDeveloper.helpers({\n  siteUrl: function () {\n    return Meteor.absoluteUrl();\n  }\n});\n\nTemplate.configureLoginServiceDialogForMeteorDeveloper.fields = function () {\n  return [\n    {property: 'clientId', label: 'App ID'},\n    {property: 'secret', label: 'App secret'}\n  ];\n};\n"
  },
  {
    "path": "packages/meteor-developer/meteor_developer_server.js",
    "content": "OAuth.registerService(\"meteor-developer\", 2, null, function (query) {\n  var response = getTokens(query);\n  var accessToken = response.accessToken;\n  var identity = getIdentity(accessToken);\n\n  var serviceData = {\n    accessToken: OAuth.sealSecret(accessToken),\n    expiresAt: (+new Date) + (1000 * response.expiresIn)\n  };\n\n  _.extend(serviceData, identity);\n\n  // only set the token in serviceData if it's there. this ensures\n  // that we don't lose old ones (since we only get this on the first\n  // log in attempt)\n  if (response.refreshToken)\n    serviceData.refreshToken = OAuth.sealSecret(response.refreshToken);\n\n  return {\n    serviceData: serviceData,\n    options: {profile: {name: serviceData.username}}\n    // XXX use username for name until meteor accounts has a profile with a name\n  };\n});\n\n// returns an object containing:\n// - accessToken\n// - expiresIn: lifetime of token in seconds\n// - refreshToken, if this is the first authorization request and we got a\n//   refresh token from the server\nvar getTokens = function (query) {\n  var config = ServiceConfiguration.configurations.findOne({\n    service: 'meteor-developer'\n  });\n  if (!config)\n    throw new ServiceConfiguration.ConfigError();\n\n  var response;\n  try {\n    response = HTTP.post(\n      MeteorDeveloperAccounts._server + \"/oauth2/token\", {\n        params: {\n          grant_type: \"authorization_code\",\n          code: query.code,\n          client_id: config.clientId,\n          client_secret: OAuth.openSecret(config.secret),\n          redirect_uri: OAuth._redirectUri('meteor-developer', config)\n        }\n      }\n    );\n  } catch (err) {\n    throw _.extend(\n      new Error(\n        \"Failed to complete OAuth handshake with Meteor developer accounts. \"\n          + err.message\n      ),\n      {response: err.response}\n    );\n  }\n\n  if (! response.data || response.data.error) {\n    // if the http response was a json object with an error attribute\n    throw new Error(\n      \"Failed to complete OAuth handshake with Meteor developer accounts. \" +\n        (response.data ? response.data.error :\n         \"No response data\")\n    );\n  } else {\n    return {\n      accessToken: response.data.access_token,\n      refreshToken: response.data.refresh_token,\n      expiresIn: response.data.expires_in\n    };\n  }\n};\n\nvar getIdentity = function (accessToken) {\n  try {\n    return HTTP.get(\n      MeteorDeveloperAccounts._server + \"/api/v1/identity\",\n      {\n        headers: { Authorization: \"Bearer \" + accessToken }\n      }\n    ).data;\n  } catch (err) {\n    throw _.extend(\n      new Error(\"Failed to fetch identity from Meteor developer accounts. \" +\n                err.message),\n      {response: err.response}\n    );\n  }\n};\n\nMeteorDeveloperAccounts.retrieveCredential = function (credentialToken,\n                                                       credentialSecret) {\n  return OAuth.retrieveCredential(credentialToken, credentialSecret);\n};\n"
  },
  {
    "path": "packages/meteor-developer/package.js",
    "content": "Package.describe({\n  summary: \"Meteor developer accounts OAuth flow\",\n  version: \"1.1.9\"\n});\n\nPackage.onUse(function (api) {\n  api.use('oauth2', ['client', 'server']);\n  api.use('oauth', ['client', 'server']);\n  api.use('http', ['server']);\n  api.use(['underscore', 'service-configuration'], ['client', 'server']);\n  api.use(['random', 'templating'], 'client');\n\n  api.export('MeteorDeveloperAccounts');\n\n  api.addFiles('meteor_developer_common.js');\n  api.addFiles(['meteor_developer_configure.html',\n                 'meteor_developer_configure.js'], 'client');\n  api.addFiles('meteor_developer_server.js', 'server');\n  api.addFiles('meteor_developer_client.js', 'client');\n});\n"
  },
  {
    "path": "packages/meteor-platform/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/meteor-platform/README.md",
    "content": "# meteor-platform\n\nThis package used to be added to every app by `meteor create`, but is now deprecated in favor of `meteor-base` and a carefully chosen set of other packages.\n\nSee the PR here with the discussion: https://github.com/meteor/meteor/pull/4851\n\nThis package was previously known as [standard-app-packages](https://atmospherejs.com/meteor/standard-app-packages).\n"
  },
  {
    "path": "packages/meteor-platform/package.js",
    "content": "Package.describe({\n  summary: \"(Deprecated) Include a standard set of Meteor packages in your app\",\n  version: '1.2.6'\n});\n\nPackage.onUse(function(api) {\n  // The \"imply\" here means that if your app uses \"meteor-platform\", it is\n  // treated as if it also directly included all of these packages (and it gets\n  // their exports, plugins, etc).\n  //\n  // If you want, you can \"meteor remove meteor-platform\" and add some of\n  // these back in individually. We haven't tested every subset, though :)\n  api.imply([\n    // The normal \"every package uses 'meteor'\" rule only applies to packages\n    // built from a package source directory, so we make sure apps get it too.\n    // Meteor.isServer! The CSS extension handler! And so much more!\n    'meteor',\n    // A standard Meteor app is a web app. (Without this, there will be no\n    // 'main' function unless you define one yourself.)\n    'webapp',\n    // It's Log! It's better than bad, it's good!\n    'logging',\n    // Tracker.autorun and friends. What's Meteor without reactivity?\n    'tracker',\n    'deps', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.\n    // The easiest way to get a little reactivity into your app.\n    'session',\n    // DDP: Meteor's client/server protocol.\n    'ddp',\n    'livedata', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.\n    // You want to keep your data somewhere? How about MongoDB?\n    'mongo',\n    // Blaze: Reactive DOM!\n    'blaze',\n    'ui', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.\n    // A great template language!\n    'spacebars',\n    // Turn templates into views!\n    'templating',\n    // Easy type assertions? check.\n    'check',\n    // _.isUseful(true)\n    'underscore',\n    // $(\".usefulToo\")\n    'jquery',\n    // Life isn't always predictable.\n    'random',\n    // People like being able to clone objects.\n    'ejson'\n  ]);\n\n  // These are useful too!  But you don't have to see their exports\n  // unless you want to.\n  api.use([\n    // We can reload the client without messing up methods in flight.\n    'reload',\n    // And update automatically when new client code is available!\n    'autoupdate'\n  ], ['client', 'server']);\n\n  // More mobile specific implies\n  api.imply([\n    // Remove the 300ms click delay on mobile\n    'fastclick',\n    // Good defaults for the mobile status bar\n    'mobile-status-bar'\n  ], 'web.cordova');\n\n  api.imply([\n    // Launch screen configuration. Currently only on mobile but we include the\n    // no-op browser version anyway.\n    'launch-screen'\n  ], 'web');\n});\n"
  },
  {
    "path": "packages/meteor-tool/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/meteor-tool/README.md",
    "content": "# meteor-tool\n\nThis is the Meteor command-line tool. Most of the code for it is in the [tools directory](https://github.com/meteor/meteor/tree/master/tools) of the Meteor repository.\n\nThe Meteor tool also includes testing functionality and example apps for the Meteor framework.\n\nRead more about it on the [project page](https://www.meteor.com/tool)"
  },
  {
    "path": "packages/meteor-tool/package.js",
    "content": "Package.describe({\n  summary: \"The Meteor command-line tool\",\n  version: '1.3.4_1'\n});\n\nPackage.includeTool();\n"
  },
  {
    "path": "packages/meyerweb-reset/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/meyerweb-reset/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/meyerweb-reset/package.js",
    "content": "// This package is a hack to get reset.css loaded before other css\n// files. I've marked it internal because I'm not sure if we want to\n// encourage this pattern. Maybe another solution would be better.\nPackage.describe({\n  summary: \"reset.css v2.0 from http://meyerweb.com/eric/tools/css/reset/\",\n  version: \"1.0.7\"\n});\n\nPackage.onUse(function (api) {\n  api.addFiles(\"reset.css\", \"client\");\n});\n"
  },
  {
    "path": "packages/meyerweb-reset/reset.css",
    "content": "/* http://meyerweb.com/eric/tools/css/reset/\n   v2.0 | 20110126\n   License: none (public domain)\n*/\n\nhtml, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, big, cite, code,\ndel, dfn, em, img, ins, kbd, q, s, samp,\nsmall, strike, strong, sub, sup, tt, var,\nb, u, i, center,\ndl, dt, dd, ol, ul, li,\nfieldset, form, label, legend,\ntable, caption, tbody, tfoot, thead, tr, th, td,\narticle, aside, canvas, details, embed,\nfigure, figcaption, footer, header, hgroup,\nmenu, nav, output, ruby, section, summary,\ntime, mark, audio, video {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tfont-size: 100%;\n\tfont: inherit;\n\tvertical-align: baseline;\n}\n/* HTML5 display-role reset for older browsers */\narticle, aside, details, figcaption, figure,\nfooter, header, hgroup, menu, nav, section {\n\tdisplay: block;\n}\nbody {\n\tline-height: 1;\n}\nol, ul {\n\tlist-style: none;\n}\nblockquote, q {\n\tquotes: none;\n}\nblockquote:before, blockquote:after,\nq:before, q:after {\n\tcontent: '';\n\tcontent: none;\n}\ntable {\n\tborder-collapse: collapse;\n\tborder-spacing: 0;\n}\n"
  },
  {
    "path": "packages/minifier-css/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/minifier-css/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/minifier-css/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/minifier-css/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"css-parse\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz\",\n      \"from\": \"https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz\",\n      \"dependencies\": {\n        \"css\": {\n          \"version\": \"2.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/css/-/css-2.2.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/css/-/css-2.2.0.tgz\",\n          \"dependencies\": {\n            \"inherits\": {\n              \"version\": \"2.0.1\",\n              \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\"\n            },\n            \"source-map\": {\n              \"version\": \"0.1.43\",\n              \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz\",\n              \"from\": \"https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz\",\n              \"dependencies\": {\n                \"amdefine\": {\n                  \"version\": \"0.1.1\",\n                  \"resolved\": \"https://registry.npmjs.org/amdefine/-/amdefine-0.1.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/amdefine/-/amdefine-0.1.1.tgz\"\n                }\n              }\n            },\n            \"source-map-resolve\": {\n              \"version\": \"0.3.1\",\n              \"resolved\": \"https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz\",\n              \"dependencies\": {\n                \"atob\": {\n                  \"version\": \"1.1.2\",\n                  \"resolved\": \"https://registry.npmjs.org/atob/-/atob-1.1.2.tgz\",\n                  \"from\": \"https://registry.npmjs.org/atob/-/atob-1.1.2.tgz\"\n                },\n                \"resolve-url\": {\n                  \"version\": \"0.2.1\",\n                  \"resolved\": \"https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz\"\n                },\n                \"source-map-url\": {\n                  \"version\": \"0.3.0\",\n                  \"resolved\": \"https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz\"\n                }\n              }\n            },\n            \"urix\": {\n              \"version\": \"0.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/urix/-/urix-0.1.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/urix/-/urix-0.1.0.tgz\"\n            }\n          }\n        }\n      }\n    },\n    \"css-stringify\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/css-stringify/-/css-stringify-2.0.0.tgz\",\n      \"from\": \"https://registry.npmjs.org/css-stringify/-/css-stringify-2.0.0.tgz\",\n      \"dependencies\": {\n        \"css\": {\n          \"version\": \"2.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/css/-/css-2.2.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/css/-/css-2.2.0.tgz\",\n          \"dependencies\": {\n            \"inherits\": {\n              \"version\": \"2.0.1\",\n              \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\"\n            },\n            \"source-map\": {\n              \"version\": \"0.1.43\",\n              \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz\",\n              \"from\": \"https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz\",\n              \"dependencies\": {\n                \"amdefine\": {\n                  \"version\": \"0.1.1\",\n                  \"resolved\": \"https://registry.npmjs.org/amdefine/-/amdefine-0.1.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/amdefine/-/amdefine-0.1.1.tgz\"\n                }\n              }\n            },\n            \"source-map-resolve\": {\n              \"version\": \"0.3.1\",\n              \"resolved\": \"https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz\",\n              \"dependencies\": {\n                \"atob\": {\n                  \"version\": \"1.1.2\",\n                  \"resolved\": \"https://registry.npmjs.org/atob/-/atob-1.1.2.tgz\",\n                  \"from\": \"https://registry.npmjs.org/atob/-/atob-1.1.2.tgz\"\n                },\n                \"resolve-url\": {\n                  \"version\": \"0.2.1\",\n                  \"resolved\": \"https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz\"\n                },\n                \"source-map-url\": {\n                  \"version\": \"0.3.0\",\n                  \"resolved\": \"https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz\"\n                }\n              }\n            },\n            \"urix\": {\n              \"version\": \"0.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/urix/-/urix-0.1.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/urix/-/urix-0.1.0.tgz\"\n            }\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/minifier-css/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/minifier-css/minification.js",
    "content": "// http://stackoverflow.com/questions/9906794/internet-explorers-css-rules-limits\nvar LIMIT = 4095;\n\n// Stringifier based on css-stringify\nvar emit = function (str) {\n  return str.toString();\n};\n\nvar visit = function (node, last) {\n  return traverse[node.type](node, last);\n};\n\nvar mapVisit = function (nodes) {\n  var buf = \"\";\n\n  for (var i = 0, length = nodes.length; i < length; i++) {\n    buf += visit(nodes[i], i === length - 1);\n  }\n\n  return buf;\n};\n\n// returns a list of strings\nMinifyAst = function(node) {\n  // the approach is taken from BlessCSS\n\n  var newAsts = [];\n  var current = {\n    selectors: 0,\n    nodes: []\n  };\n\n  var startNewAst = function () {\n    newAsts.push({\n      type: 'stylesheet',\n      stylesheet: {\n        rules: current.nodes\n      }\n    });\n\n    current.nodes = [];\n    current.selectors = 0;\n  };\n\n  _.each(node.stylesheet.rules, function (rule) {\n    switch (rule.type) {\n      case 'rule':\n        if (current.selectors + rule.selectors.length > LIMIT) {\n          startNewAst();\n        }\n\n        current.selectors += rule.selectors.length;\n        current.nodes.push(rule);\n        break;\n      case 'comment':\n        // no-op\n        break;\n      default:\n        // nested rules\n        var nested = 0;\n        _.each(rule.rules, function (nestedRule) {\n          if (nestedRule.selectors) {\n            nested += nestedRule.selectors.length;\n          }\n        });\n\n        if (current.selectors + nested > LIMIT) {\n          startNewAst();\n        }\n\n        current.selectors += nested;\n        current.nodes.push(rule);\n        break;\n    }\n  });\n\n  // push the left-over\n  if (current.nodes.length > 0) {\n    startNewAst();\n  }\n\n  var stringifyAst = function (node) {\n    return node.stylesheet\n      .rules.map(function (rule) { return visit(rule); })\n      .join('');\n  };\n\n  return newAsts.map(stringifyAst);\n};\n\nvar traverse = {};\n\ntraverse.comment = function(node) {\n  return emit('', node.position);\n};\n\ntraverse.import = function(node) {\n  return emit('@import ' + node.import + ';', node.position);\n};\n\ntraverse.media = function(node) {\n  return emit('@media ' + node.media, node.position, true)\n    + emit('{')\n    + mapVisit(node.rules)\n    + emit('}');\n};\n\ntraverse.document = function(node) {\n  var doc = '@' + (node.vendor || '') + 'document ' + node.document;\n\n  return emit(doc, node.position, true)\n    + emit('{')\n    + mapVisit(node.rules)\n    + emit('}');\n};\n\ntraverse.charset = function(node) {\n  return emit('@charset ' + node.charset + ';', node.position);\n};\n\ntraverse.namespace = function(node) {\n  return emit('@namespace ' + node.namespace + ';', node.position);\n};\n\ntraverse.supports = function(node){\n  return emit('@supports ' + node.supports, node.position, true)\n    + emit('{')\n    + mapVisit(node.rules)\n    + emit('}');\n};\n\ntraverse.keyframes = function(node) {\n  return emit('@'\n    + (node.vendor || '')\n    + 'keyframes '\n    + node.name, node.position, true)\n    + emit('{')\n    + mapVisit(node.keyframes)\n    + emit('}');\n};\n\ntraverse.keyframe = function(node) {\n  var decls = node.declarations;\n\n  return emit(node.values.join(','), node.position, true)\n    + emit('{')\n    + mapVisit(decls)\n    + emit('}');\n};\n\ntraverse.page = function(node) {\n  var sel = node.selectors.length\n    ? node.selectors.join(', ')\n    : '';\n\n  return emit('@page ' + sel, node.position, true)\n    + emit('{')\n    + mapVisit(node.declarations)\n    + emit('}');\n};\n\ntraverse['font-face'] = function(node){\n  return emit('@font-face', node.position, true)\n    + emit('{')\n    + mapVisit(node.declarations)\n    + emit('}');\n};\n\ntraverse.rule = function(node) {\n  var decls = node.declarations;\n  if (!decls.length) return '';\n\n  var selectors = node.selectors.map(function (selector) {\n    // removes universal selectors like *.class => .class\n    // removes optional whitespace around '>' and '+'\n    return selector.replace(/\\*\\./, '.')\n                   .replace(/\\s*>\\s*/g, '>')\n                   .replace(/\\s*\\+\\s*/g, '+');\n  });\n  return emit(selectors.join(','), node.position, true)\n    + emit('{')\n    + mapVisit(decls)\n    + emit('}');\n};\n\ntraverse.declaration = function(node, last) {\n  var value = node.value;\n\n  // remove optional quotes around font name\n  if (node.property === 'font') {\n    value = value.replace(/\\'[^\\']+\\'/g, function (m) {\n      if (m.indexOf(' ') !== -1)\n        return m;\n      return m.replace(/\\'/g, '');\n    });\n    value = value.replace(/\\\"[^\\\"]+\\\"/g, function (m) {\n      if (m.indexOf(' ') !== -1)\n        return m;\n      return m.replace(/\\\"/g, '');\n    });\n  }\n  // remove url quotes if possible\n  // in case it is the last declaration, we can omit the semicolon\n  return emit(node.property + ':' + value, node.position)\n         + (last ? '' : emit(';'));\n};\n"
  },
  {
    "path": "packages/minifier-css/minifier-tests.js",
    "content": "\nTinytest.add(\"minifier-css - simple css minification\", function (test) {\n  var t = function (css, expected, desc) {\n    test.equal(CssTools.minifyCss(css), [expected], desc);\n  }\n\n  t('a \\t\\n{ color: red } \\n', 'a{color:red}', 'whitespace check');\n  t('a \\t\\n{ color: red; margin: 1; } \\n', 'a{color:red;margin:1}', 'only last one loses semicolon');\n  t('a \\t\\n{ color: red;;; margin: 1;;; } \\n', 'a{color:red;margin:1}', 'more semicolons than needed');\n  t('a , p \\t\\n{ color: red; } \\n', 'a,p{color:red}', 'multiple selectors');\n  t('body {}', '', 'removing empty rules');\n  t('*.my-class { color: #fff; }', '.my-class{color:#fff}', 'removing universal selector');\n  t('p > *.my-class { color: #fff; }', 'p>.my-class{color:#fff}', 'removing optional whitespace around \">\" in selector');\n  t('p +  *.my-class { color: #fff; }', 'p+.my-class{color:#fff}', 'removing optional whitespace around \"+\" in selector');\n  // XXX url parsing is difficult to support at the moment\n  t('a {\\n\\\n  font:12px \\'Helvetica\\',\"Arial\",\\'Nautica\\';\\n\\\n  background:url(\"/some/nice/picture.png\");\\n}',\n  'a{font:12px Helvetica,Arial,Nautica;background:url(\"/some/nice/picture.png\")}',  'removing quotes in font and url (if possible)');\n  t('/* no comments */ a { color: red; }', 'a{color:red}', 'remove comments');\n});\n"
  },
  {
    "path": "packages/minifier-css/minifier.js",
    "content": "var cssParse = Npm.require('css-parse');\nvar cssStringify = Npm.require('css-stringify');\nvar url = Npm.require('url');\nvar path = Npm.require('path');\n\nCssTools = {\n  parseCss: cssParse,\n  stringifyCss: cssStringify,\n  minifyCss: function (cssText) {\n    return CssTools.minifyCssAst(cssParse(cssText));\n  },\n  minifyCssAst: function (cssAst) {\n    return MinifyAst(cssAst);\n  },\n  mergeCssAsts: function (cssAsts, warnCb) {\n    var rulesPredicate = function (rules) {\n      if (! _.isArray(rules))\n        rules = [rules];\n      return function (node) {\n        return _.contains(rules, node.type);\n      }\n    };\n\n    // Simple concatenation of CSS files would break @import rules\n    // located in the beginning of a file. Before concatenation, pull them to\n    // the beginning of a new syntax tree so they always precede other rules.\n    var newAst = {\n      type: 'stylesheet',\n      stylesheet: { rules: [] }\n    };\n\n    _.each(cssAsts, function (ast) {\n      // Pick only the imports from the beginning of file ignoring @charset\n      // rules as every file is assumed to be in UTF-8.\n      var charsetRules = _.filter(ast.stylesheet.rules,\n                                  rulesPredicate(\"charset\"));\n\n      if (_.any(charsetRules, function (rule) {\n        // According to MDN, only 'UTF-8' and \"UTF-8\" are the correct encoding\n        // directives representing UTF-8.\n        return ! /^(['\"])UTF-8\\1$/.test(rule.charset);\n      })) {\n        warnCb(ast.filename, \"@charset rules in this file will be ignored as UTF-8 is the only encoding supported\");\n      }\n\n      ast.stylesheet.rules = _.reject(ast.stylesheet.rules,\n                                      rulesPredicate(\"charset\"));\n      var importCount = 0;\n      for (var i = 0; i < ast.stylesheet.rules.length; i++)\n        if (! rulesPredicate([\"import\", \"comment\"])(ast.stylesheet.rules[i])) {\n          importCount = i;\n          break;\n        }\n\n      CssTools.rewriteCssUrls(ast);\n\n      var imports = ast.stylesheet.rules.splice(0, importCount);\n      newAst.stylesheet.rules = newAst.stylesheet.rules.concat(imports);\n\n      // if there are imports left in the middle of file, warn user as it might\n      // be a potential bug (imports are valid only in the beginning of file).\n      if (_.any(ast.stylesheet.rules, rulesPredicate(\"import\"))) {\n        // XXX make this an error?\n        warnCb(ast.filename, \"there are some @import rules those are not taking effect as they are required to be in the beginning of the file\");\n      }\n\n    });\n\n    // Now we can put the rest of CSS rules into new AST\n    _.each(cssAsts, function (ast) {\n      newAst.stylesheet.rules =\n        newAst.stylesheet.rules.concat(ast.stylesheet.rules);\n    });\n\n    return newAst;\n  },\n\n  // We are looking for all relative urls defined with the `url()` functional\n  // notation and rewriting them to the equivalent absolute url using the\n  // `position.source` path provided by css-parse\n  // For performance reasons this function acts by side effect by modifying the\n  // given AST without doing a deep copy.\n  rewriteCssUrls: function (ast) {\n    rewriteRules(ast.stylesheet.rules);\n  }\n};\n\nif (typeof Profile !== 'undefined') {\n  _.each(['parseCss', 'stringifyCss', 'minifyCss',\n          'minifyCssAst', 'mergeCssAsts', 'rewriteCssUrls'],\n         function (funcName) {\n           CssTools[funcName] = Profile('CssTools.'+funcName,\n                                        CssTools[funcName]);\n         });\n}\n\nvar rewriteRules = function (rules) {\n  _.each(rules, function(rule, ruleIndex) {\n\n    // Recurse if there are sub-rules. An example:\n    //     @media (...) {\n    //         .rule { url(...); }\n    //     }\n    if (_.has(rule, 'rules')) {\n      rewriteRules(rule.rules);\n    }\n\n    var basePath = pathDirname(rule.position.source);\n\n    // Set the correct basePath based on how the linked asset will be served.\n    // XXX This is wrong. We are coupling the information about how files will\n    // be served by the web server to the information how they were stored\n    // originally on the filesystem in the project structure. Ideally, there\n    // should be some module that tells us precisely how each asset will be\n    // served but for now we are just assuming that everything that comes from\n    // a folder starting with \"/packages/\" is served on the same path as\n    // it was on the filesystem and everything else is served on root \"/\".\n    if (! basePath.match(/^\\/?packages\\//i))\n        basePath = \"/\";\n\n    _.each(rule.declarations, function(declaration, declarationIndex) {\n      var parts, resource, absolutePath, quotes, oldCssUrl, newCssUrl;\n      var value = declaration.value;\n\n      // Match css values containing some functional calls to `url(URI)` where\n      // URI is optionally quoted.\n      // Note that a css value can contains other elements, for instance:\n      //   background: top center url(\"background.png\") black;\n      // or even multiple url(), for instance for multiple backgrounds.\n      var cssUrlRegex = /url\\s*\\(\\s*(['\"]?)(.+?)\\1\\s*\\)/gi;\n      while (parts = cssUrlRegex.exec(value)) {\n        oldCssUrl = parts[0];\n        quotes = parts[1];\n        resource = url.parse(parts[2]);\n\n        // Rewrite relative paths to absolute paths.\n        // We don't rewrite urls starting with a protocol definition such as\n        // http, https, or data.\n        if (isRelative(resource.path) && resource.protocol === null) {\n          absolutePath = pathJoin(basePath, resource.path);\n          newCssUrl = \"url(\" + quotes + absolutePath + quotes + \")\";\n          value = value.replace(oldCssUrl, newCssUrl);\n        }\n      }\n\n      declaration.value = value;\n    });\n  });\n};\n\nvar isRelative = function(path) {\n  return path && path.charAt(0) !== '/';\n};\n\n// These are duplicates of functions in tools/files.js, because we don't have\n// a good way of exporting them into packages.\n// XXX deduplicate files.js into a package at somepoint so that we can use it\n// in core\nvar toOSPath = function (p) {\n  if (process.platform === 'win32')\n    return p.replace(/\\//g, '\\\\');\n  return p;\n}\n\nvar toStandardPath = function (p) {\n  if (process.platform === 'win32')\n    return p.replace(/\\\\/g, '/');\n  return p;\n};\n\nvar pathJoin = function (a, b) {\n  return toStandardPath(path.join(\n    toOSPath(a),\n    toOSPath(b)));\n};\n\nvar pathDirname = function (p) {\n  return toStandardPath(path.dirname(toOSPath(p)));\n};\n"
  },
  {
    "path": "packages/minifier-css/package.js",
    "content": "Package.describe({\n  summary: \"CSS minifier\",\n  version: \"1.1.12_1\"\n});\n\nNpm.depends({\n  \"css-parse\": \"2.0.0\",\n  \"css-stringify\": \"2.0.0\"\n});\n\nNpm.strip({\n  \"css-parse\": [\"test/\"],\n  \"css-stringify\": [\"test/\"]\n});\n\nPackage.onUse(function (api) {\n  api.use('underscore', 'server');\n  api.export(['CssTools']);\n  api.addFiles(['minification.js', 'minifier.js'], 'server');\n});\n\nPackage.onTest(function (api) {\n  api.use('minifier-css', 'server');\n  api.use('tinytest');\n\n  api.addFiles([\n    'minifier-tests.js',\n    'urlrewriting-tests.js'\n  ], 'server');\n});\n"
  },
  {
    "path": "packages/minifier-css/urlrewriting-tests.js",
    "content": "\nTinytest.add(\"minifier-css - url rewriting when merging\", function (test) {\n  var stylesheet = function(backgroundPath) {\n    return \"body { color: green; background: top center url(\" + backgroundPath + \") black, bottom center url(\" + backgroundPath + \"); }\"\n  };\n\n  var parseOptions = { source: null, position: true };\n\n  var t = function(relativeUrl, absoluteUrl, desc) {\n    var ast1 = CssTools.parseCss(stylesheet(relativeUrl), parseOptions);\n    var ast2 = CssTools.parseCss(stylesheet(absoluteUrl), parseOptions);\n    CssTools.rewriteCssUrls(ast1);\n\n    test.equal(CssTools.stringifyCss(ast1), CssTools.stringifyCss(ast2), desc);\n  };\n\n  parseOptions.source = 'packages/nameOfPackage/style.css';\n  t('../image.png', 'packages/image.png', 'parent directory');\n  t('./../image.png', 'packages/image.png', 'parent directory');\n  t('../nameOfPackage2/image.png', 'packages/nameOfPackage2/image.png', 'cousin directory');\n  t('../../image.png', 'image.png', 'grand parent directory');\n  t('./image.png', 'packages/nameOfPackage/image.png', 'current directory');\n  t('./child/image.png', 'packages/nameOfPackage/child/image.png', 'child directory');\n  t('child/image.png', 'packages/nameOfPackage/child/image.png', 'child directory');\n  t('/image.png', '/image.png', 'absolute url');\n  t('\"/image.png\"', '\"/image.png\"', 'double quoted url');\n  t(\"'/image.png'\", \"'/image.png'\", 'single quoted url');\n  t('\"./../image.png\"', '\"packages/image.png\"', 'quoted parent directory');\n  t('http://i.imgur.com/fBcdJIh.gif', 'http://i.imgur.com/fBcdJIh.gif', 'complete URL');\n  t('\"http://i.imgur.com/fBcdJIh.gif\"', '\"http://i.imgur.com/fBcdJIh.gif\"', 'complete quoted URL');\n  t('data:image/png;base64,iVBORw0K=', 'data:image/png;base64,iVBORw0K=', 'data URI');\n  t('http://', 'http://', 'malformed URL');\n\n  parseOptions.source = 'application/client/dir/other-style.css';\n  t('./image.png', '/image.png', 'base path is root');\n  t('./child/image.png', '/child/image.png', 'child directory from root');\n  t('child/image.png', '/child/image.png', 'child directory from root');\n  t('/image.png', '/image.png', 'absolute url');\n  t('\"/image.png\"', '\"/image.png\"', 'double quoted url');\n  t(\"'/image.png'\", \"'/image.png'\", 'single quoted url');\n  t('http://i.imgur.com/fBcdJIh.gif', 'http://i.imgur.com/fBcdJIh.gif', 'complete URL');\n  t('\"http://i.imgur.com/fBcdJIh.gif\"', '\"http://i.imgur.com/fBcdJIh.gif\"', 'complete quoted URL');\n  t('data:image/png;base64,iVBORw0K=', 'data:image/png;base64,iVBORw0K=', 'data URI');\n  t('http://', 'http://', 'malformed URL');\n\n});\n\nTinytest.add(\"minifier-css - url rewriting with media queries (ast rule recursion)\", function (test) {\n  var stylesheet = function(backgroundPath) {\n    return \"@media (min--moz-device-pixel-ratio: 1.5),\\n\\\n    (-o-min-device-pixel-ratio: 3/2),\\n\\\n    (-webkit-min-device-pixel-ratio: 1.5),\\n\\\n    (min-device-pixel-ratio: 1.5),\\n\\\n    (min-resolution: 1.5dppx) \\n\\\n    { .foobar { background-image: url(\" + backgroundPath + \"); } }\"\n  };\n\n  var parseOptions = { source: null, position: true };\n\n  var t = function(relativeUrl, absoluteUrl, desc) {\n    var ast1 = CssTools.parseCss(stylesheet(relativeUrl), parseOptions);\n    var ast2 = CssTools.parseCss(stylesheet(absoluteUrl), parseOptions);\n    CssTools.rewriteCssUrls(ast1);\n\n    test.equal(CssTools.stringifyCss(ast1), CssTools.stringifyCss(ast2), desc);\n  };\n\n  parseOptions.source = 'packages/nameOfPackage/style.css';\n  t('../image.png', 'packages/image.png', 'parent directory');\n  t('./../image.png', 'packages/image.png', 'parent directory');\n  t('../nameOfPackage2/image.png', 'packages/nameOfPackage2/image.png', 'cousin directory');\n  t('../../image.png', 'image.png', 'grand parent directory');\n  t('./image.png', 'packages/nameOfPackage/image.png', 'current directory');\n  t('./child/image.png', 'packages/nameOfPackage/child/image.png', 'child directory');\n  t('child/image.png', 'packages/nameOfPackage/child/image.png', 'child directory');\n  t('/image.png', '/image.png', 'absolute url');\n  t('\"/image.png\"', '\"/image.png\"', 'double quoted url');\n  t(\"'/image.png'\", \"'/image.png'\", 'single quoted url');\n  t('\"./../image.png\"', '\"packages/image.png\"', 'quoted parent directory');\n  t('http://i.imgur.com/fBcdJIh.gif', 'http://i.imgur.com/fBcdJIh.gif', 'complete URL');\n  t('\"http://i.imgur.com/fBcdJIh.gif\"', '\"http://i.imgur.com/fBcdJIh.gif\"', 'complete quoted URL');\n  t('data:image/png;base64,iVBORw0K=', 'data:image/png;base64,iVBORw0K=', 'data URI');\n  t('http://', 'http://', 'malformed URL');\n\n  parseOptions.source = 'application/client/dir/other-style.css';\n  t('./image.png', '/image.png', 'base path is root');\n  t('./child/image.png', '/child/image.png', 'child directory from root');\n  t('child/image.png', '/child/image.png', 'child directory from root');\n  t('/image.png', '/image.png', 'absolute url');\n  t('\"/image.png\"', '\"/image.png\"', 'double quoted url');\n  t(\"'/image.png'\", \"'/image.png'\", 'single quoted url');\n  t('http://i.imgur.com/fBcdJIh.gif', 'http://i.imgur.com/fBcdJIh.gif', 'complete URL');\n  t('\"http://i.imgur.com/fBcdJIh.gif\"', '\"http://i.imgur.com/fBcdJIh.gif\"', 'complete quoted URL');\n  t('data:image/png;base64,iVBORw0K=', 'data:image/png;base64,iVBORw0K=', 'data URI');\n  t('http://', 'http://', 'malformed URL');\n\n});\n"
  },
  {
    "path": "packages/minifier-js/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/minifier-js/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/minifier-js/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/minifier-js/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"uglify-js\": {\n      \"version\": \"2.4.20\",\n      \"resolved\": \"https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.20.tgz\",\n      \"from\": \"https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.20.tgz\",\n      \"dependencies\": {\n        \"async\": {\n          \"version\": \"0.2.10\",\n          \"resolved\": \"https://registry.npmjs.org/async/-/async-0.2.10.tgz\",\n          \"from\": \"https://registry.npmjs.org/async/-/async-0.2.10.tgz\"\n        },\n        \"source-map\": {\n          \"version\": \"0.1.34\",\n          \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz\",\n          \"from\": \"https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz\",\n          \"dependencies\": {\n            \"amdefine\": {\n              \"version\": \"0.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz\"\n            }\n          }\n        },\n        \"uglify-to-browserify\": {\n          \"version\": \"1.0.2\",\n          \"resolved\": \"https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz\",\n          \"from\": \"https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz\"\n        },\n        \"yargs\": {\n          \"version\": \"3.5.4\",\n          \"resolved\": \"https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz\",\n          \"from\": \"https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz\",\n          \"dependencies\": {\n            \"camelcase\": {\n              \"version\": \"1.0.2\",\n              \"resolved\": \"https://registry.npmjs.org/camelcase/-/camelcase-1.0.2.tgz\",\n              \"from\": \"https://registry.npmjs.org/camelcase/-/camelcase-1.0.2.tgz\"\n            },\n            \"decamelize\": {\n              \"version\": \"1.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/decamelize/-/decamelize-1.0.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/decamelize/-/decamelize-1.0.0.tgz\"\n            },\n            \"window-size\": {\n              \"version\": \"0.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz\"\n            },\n            \"wordwrap\": {\n              \"version\": \"0.0.2\",\n              \"resolved\": \"https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz\",\n              \"from\": \"https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz\"\n            }\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/minifier-js/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/minifier-js/beautify-tests.js",
    "content": "\n// The UglifyJSMinify API can also be used for beautification.  Test that it\n// behaves as expected.\n\nTinytest.add('minifier-js - uglify beautify', function (test) {\n  // See <https://github.com/mishoo/UglifyJS2#the-simple-way> and\n  // <http://lisperator.net/uglifyjs/codegen> for the API we're calling.\n  test.equal(UglifyJSMinify('one = function () { return 1; };',\n                            { fromString: true,\n                              output: { beautify: true,\n                                        indent_level: 2,\n                                        width: 80 } }).code,\n             'one = function() {\\n' +\n             '  return 1;\\n' +\n             '};');\n});\n"
  },
  {
    "path": "packages/minifier-js/minifier.js",
    "content": "UglifyJS = Npm.require('uglify-js');\nUglifyJSMinify = UglifyJS.minify;"
  },
  {
    "path": "packages/minifier-js/package.js",
    "content": "Package.describe({\n  summary: \"JavaScript minifier\",\n  version: \"1.1.12_1\"\n});\n\nNpm.depends({\n  \"uglify-js\": \"2.4.20\",\n});\n\nNpm.strip({\n  \"uglify-js\": [\"test/\"],\n});\n\nPackage.onUse(function (api) {\n  api.use('underscore', 'server');\n  api.export(['UglifyJSMinify', 'UglifyJS']);\n  api.addFiles(['minifier.js'], 'server');\n});\n\nPackage.onTest(function (api) {\n  api.use('minifier-js', 'server');\n  api.use('tinytest');\n\n  api.addFiles([\n    'beautify-tests.js',\n  ], 'server');\n});\n"
  },
  {
    "path": "packages/minimongo/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/minimongo/NOTES",
    "content": "## CORE FUNCTIONALITY THAT'S MISSING ##\n\nIn update, $pull can't take a selector like {$gt: 3} (but it can take\n{x: 3}, or {x: {$gt: 3}} -- basically, selectors that match documents\ncan be used, but selectors that are intended to match non-document\nvalues won't work.)\n\nSort does not correctly implement the Mongo behavior where only array entries\nthat match the query's selector are used as sort keys. Specifically, when\nsorting a document with sort specifier {a:1}, the document {a: [5, 10]} will\nusually have sort key 5 (the minimum is used for ascending sorts and the maximum\nfor descending sorts). But if the query's selector is {a: {$gt: 7}}, then Mongo\nwill actually use 10 as the sort key because 5 does not match.\n\nUnsupported selectors:\n - $elemMatch inside $all\n - geoqueries other than $near ($nearSphere, $geoIntersects, $geoWithin)\n\nIn MongoDB, a query with $near that matches a document which has multiple points\nmatching the key (eg, `c.find({$near: 'a'})` with the document\n`{a: [[1,1], [2, 2]]}` can return the document multiple times (perhaps not\neven consecutively). In minimongo, queries never return a document multiple\ntimes.\n\n## ON TYPES ##\n\nWe don't implement these Mongo types completely: timestamp (but date works),\nsymbol, javascript code (with or without scope), minkey/maxkey, regexp (stored\nin the database), fixed-precision integers.\n\nIf your Javascript implementation enumerates the keys of objects in a\nconsistent order, then we implement object equality and object\ncomparison in the same way that Mongo does it (defined relative to the\nkey order in the objects.) If your JS implementation doesn't keep the\nkeys of objects in order (or you choose to consider its behavior as\nundefined), then object equality and comparison is undefined in your\nmongo queries.\n\nIn update, we don't support $bit (because $bit only works on the\ninteger type, and we don't support the integer type yet.)\n\n## API ##\n\nfind() doesn't support the min and max parameters.\n\nfindAndModify isn't supported.\n\nThe aggregate functions distinct(), and group() aren't supported. Map/reduce\nisn't supported.\n\nupdate() should have a clear stance on atomicity (both in terms of\nmultiple ops on a single document, and on multi-document update mode.)\nIt just hasn't been looked at/thought about yet.\n\nIn general, the API needs tests, especially update. (On the other\nhand, the underlying selector and mutator code is quite well tested.)\n\n## OTHER STUFF ##\n\nWe ignore the 'x' and 's' flags on regular expressions.\n\n\"Natural order\" isn't very well defined.\n\nWe don't support capped collections.\n\nLittle performance optimization has been done. In particular, there are no\nindexes.\n"
  },
  {
    "path": "packages/minimongo/README.md",
    "content": "# Minimongo\n\n`minimongo` is reimplementation of (almost) the entire MongoDB API, against an\nin-memory JavaScript database. It is like a MongoDB emulator that runs inside\nyour web browser. You can insert data into it and search, sort, and update that\ndata. This is great if you like the MongoDB API (which you may already be using\non the server), need a way to store data on the client that you've fetched and\nare using to render your interface, and want to use that familiar API.\n\nMinimongo is used as a temporary data cache in the standard Meteor stack, to\nlearn more about mini-databases and what they can do, see [the project page on\nwww.meteor.com](https://www.meteor.com/mini-databases)\n\n## Internals\n\nMinimongo implements the following features, mirroring the MongoDB features:\n\n- Selectors\n- Modifiers\n- Fields projections\n- Querying with `sort` and `limit`\n- ObjectID generation\n- Geo-positional operator `$near` with GeoJSON parsing\n\nInternally, all documents are mapped in a single JS object from `_id` to the\ndocument. Besides this mapping, Minimongo doesn't implement any types of\nsecondary indexes.\n\nAlso, currently Minimongo doesn't implement any aggregation features. The full\nlist of incompatible features can be found in the NOTES file.\n\nBesides the MongoDB features, Minimongo implements the following for a better\nintegration with the Meteor stack:\n\n- `observe` and `observeChanges` APIs, notification callbacks when the result of\na query changes\n- integration with Meteor's [Tracker](https://www.meteor.com/tracker)\n- Meteor's Publish a cursor interface `_publishCursor`, that results into an\n  `observe` call\n- Meteor's interface of `pauseObservers` and `resumeObservers`, for client-side\n  caches (allow latency compensation to change multiple objects at once w/o a\n  flicker)\n- In addition to the previous point, `saveOriginals` and `retrieveOriginals` are\n  used to revert the local changes\n- additional analysis functions for Meteor's server-side Oplog Observe Driver\n(only loaded for the server-side):\n  * can this modifier change the result of this selector if the document didn't\n  match before\n  * can the sort order change after applying this modifier (for a given\n  selector)\n  * what is a combined projection for these selector, sorter and projection\n- `find` accepts a literal function instead of a selector, and a comparison\n  function for sorting\n\n\n### saveOriginals/retrieveOriginals & pauseObserver/resumeObservers\n\nThis part of the implementation is very important for a smooth Optimistic UI\nexperience (also called \"Latency Compensation\") avoiding an extra flicker.\n\nLet's review the usual Optimistic UI flow:\n\n- User triggers an interaction on the client\n- The simulation applies some mutations to the state locally\n- The RPC is fired to be executed on the server\n- After some time, the RPC returns with the result\n- After some more time, RPC returns an \"updated\" message (on DDP level), meaning\nthat all the changes from RPC have persisted\n- At this point we know, that all the actual changes from the server are synced,\n  we can throw away the simulated mutations (preserving the real changes from\n  the server)\n\nTo implement the last step, Minimongo implements the following:\n\n- When a simulation starts, `saveOriginals` is called, to take a snapshot of the\nstate before the update. Internally, it is implemented in a more efficient\ncopy-on-write style.\n- After the simulation, wait, to get all the real changes from the server.\n- When the server is done with giving us new changes, we apply all the new\nchanges and throw away all the simulated changes (with `retrieveOriginals`).\n- All massive replacements happen in between `pauseObservers` and\n  `resumeObservers` calls, so any user code (such as Blaze) sees the whole\n  change in one tick (helps to avoid the flicker).\n\n"
  },
  {
    "path": "packages/minimongo/diff.js",
    "content": "// ordered: bool.\n// old_results and new_results: collections of documents.\n//    if ordered, they are arrays.\n//    if unordered, they are IdMaps\nLocalCollection._diffQueryChanges = function (ordered, oldResults, newResults, observer, options) {\n  return DiffSequence.diffQueryChanges(ordered, oldResults, newResults, observer, options);\n};\n\nLocalCollection._diffQueryUnorderedChanges = function (oldResults, newResults, observer, options) {\n  return DiffSequence.diffQueryUnorderedChanges(oldResults, newResults, observer, options);\n};\n\n\nLocalCollection._diffQueryOrderedChanges =\n  function (oldResults, newResults, observer, options) {\n  return DiffSequence.diffQueryOrderedChanges(oldResults, newResults, observer, options);\n};\n\nLocalCollection._diffObjects = function (left, right, callbacks) {\n  return DiffSequence.diffObjects(left, right, callbacks);\n};\n"
  },
  {
    "path": "packages/minimongo/helpers.js",
    "content": "// Like _.isArray, but doesn't regard polyfilled Uint8Arrays on old browsers as\n// arrays.\n// XXX maybe this should be EJSON.isArray\nisArray = function (x) {\n  return _.isArray(x) && !EJSON.isBinary(x);\n};\n\n// XXX maybe this should be EJSON.isObject, though EJSON doesn't know about\n// RegExp\n// XXX note that _type(undefined) === 3!!!!\nisPlainObject = LocalCollection._isPlainObject = function (x) {\n  return x && LocalCollection._f._type(x) === 3;\n};\n\nisIndexable = function (x) {\n  return isArray(x) || isPlainObject(x);\n};\n\n// Returns true if this is an object with at least one key and all keys begin\n// with $.  Unless inconsistentOK is set, throws if some keys begin with $ and\n// others don't.\nisOperatorObject = function (valueSelector, inconsistentOK) {\n  if (!isPlainObject(valueSelector))\n    return false;\n\n  var theseAreOperators = undefined;\n  _.each(valueSelector, function (value, selKey) {\n    var thisIsOperator = selKey.substr(0, 1) === '$';\n    if (theseAreOperators === undefined) {\n      theseAreOperators = thisIsOperator;\n    } else if (theseAreOperators !== thisIsOperator) {\n      if (!inconsistentOK)\n        throw new Error(\"Inconsistent operator: \" +\n                        JSON.stringify(valueSelector));\n      theseAreOperators = false;\n    }\n  });\n  return !!theseAreOperators;  // {} has no operators\n};\n\n\n// string can be converted to integer\nisNumericKey = function (s) {\n  return /^[0-9]+$/.test(s);\n};\n"
  },
  {
    "path": "packages/minimongo/id_map.js",
    "content": "LocalCollection._IdMap = function () {\n  var self = this;\n  IdMap.call(self, MongoID.idStringify, MongoID.idParse);\n};\n\nMeteor._inherits(LocalCollection._IdMap, IdMap);\n\n"
  },
  {
    "path": "packages/minimongo/minimongo.js",
    "content": "// XXX type checking on selectors (graceful error if malformed)\n\n// LocalCollection: a set of documents that supports queries and modifiers.\n\n// Cursor: a specification for a particular subset of documents, w/\n// a defined order, limit, and offset.  creating a Cursor with LocalCollection.find(),\n\n// ObserveHandle: the return value of a live query.\n\nLocalCollection = function (name) {\n  var self = this;\n  self.name = name;\n  // _id -> document (also containing id)\n  self._docs = new LocalCollection._IdMap;\n\n  self._observeQueue = new Meteor._SynchronousQueue();\n\n  self.next_qid = 1; // live query id generator\n\n  // qid -> live query object. keys:\n  //  ordered: bool. ordered queries have addedBefore/movedBefore callbacks.\n  //  results: array (ordered) or object (unordered) of current results\n  //    (aliased with self._docs!)\n  //  resultsSnapshot: snapshot of results. null if not paused.\n  //  cursor: Cursor object for the query.\n  //  selector, sorter, (callbacks): functions\n  self.queries = {};\n\n  // null if not saving originals; an IdMap from id to original document value if\n  // saving originals. See comments before saveOriginals().\n  self._savedOriginals = null;\n\n  // True when observers are paused and we should not send callbacks.\n  self.paused = false;\n};\n\nMinimongo = {};\n\n// Object exported only for unit testing.\n// Use it to export private functions to test in Tinytest.\nMinimongoTest = {};\n\nMinimongoError = function (message) {\n  var e = new Error(message);\n  e.name = \"MinimongoError\";\n  return e;\n};\n\n\n// options may include sort, skip, limit, reactive\n// sort may be any of these forms:\n//     {a: 1, b: -1}\n//     [[\"a\", \"asc\"], [\"b\", \"desc\"]]\n//     [\"a\", [\"b\", \"desc\"]]\n//   (in the first form you're beholden to key enumeration order in\n//   your javascript VM)\n//\n// reactive: if given, and false, don't register with Tracker (default\n// is true)\n//\n// XXX possibly should support retrieving a subset of fields? and\n// have it be a hint (ignored on the client, when not copying the\n// doc?)\n//\n// XXX sort does not yet support subkeys ('a.b') .. fix that!\n// XXX add one more sort form: \"key\"\n// XXX tests\nLocalCollection.prototype.find = function (selector, options) {\n  // default syntax for everything is to omit the selector argument.\n  // but if selector is explicitly passed in as false or undefined, we\n  // want a selector that matches nothing.\n  if (arguments.length === 0)\n    selector = {};\n\n  return new LocalCollection.Cursor(this, selector, options);\n};\n\n// don't call this ctor directly.  use LocalCollection.find().\n\nLocalCollection.Cursor = function (collection, selector, options) {\n  var self = this;\n  if (!options) options = {};\n\n  self.collection = collection;\n  self.sorter = null;\n  self.matcher = new Minimongo.Matcher(selector);\n\n  if (LocalCollection._selectorIsId(selector)) {\n    // stash for fast path\n    self._selectorId = selector;\n  } else if (LocalCollection._selectorIsIdPerhapsAsObject(selector)) {\n    // also do the fast path for { _id: idString }\n    self._selectorId = selector._id;\n  } else {\n    self._selectorId = undefined;\n    if (self.matcher.hasGeoQuery() || options.sort) {\n      self.sorter = new Minimongo.Sorter(options.sort || [],\n                                         { matcher: self.matcher });\n    }\n  }\n\n  self.skip = options.skip;\n  self.limit = options.limit;\n  self.fields = options.fields;\n\n  self._projectionFn = LocalCollection._compileProjection(self.fields || {});\n\n  self._transform = LocalCollection.wrapTransform(options.transform);\n\n  // by default, queries register w/ Tracker when it is available.\n  if (typeof Tracker !== \"undefined\")\n    self.reactive = (options.reactive === undefined) ? true : options.reactive;\n};\n\n// Since we don't actually have a \"nextObject\" interface, there's really no\n// reason to have a \"rewind\" interface.  All it did was make multiple calls\n// to fetch/map/forEach return nothing the second time.\n// XXX COMPAT WITH 0.8.1\nLocalCollection.Cursor.prototype.rewind = function () {\n};\n\nLocalCollection.prototype.findOne = function (selector, options) {\n  if (arguments.length === 0)\n    selector = {};\n\n  // NOTE: by setting limit 1 here, we end up using very inefficient\n  // code that recomputes the whole query on each update. The upside is\n  // that when you reactively depend on a findOne you only get\n  // invalidated when the found object changes, not any object in the\n  // collection. Most findOne will be by id, which has a fast path, so\n  // this might not be a big deal. In most cases, invalidation causes\n  // the called to re-query anyway, so this should be a net performance\n  // improvement.\n  options = options || {};\n  options.limit = 1;\n\n  return this.find(selector, options).fetch()[0];\n};\n\n/**\n * @callback IterationCallback\n * @param {Object} doc\n * @param {Number} index\n */\n/**\n * @summary Call `callback` once for each matching document, sequentially and synchronously.\n * @locus Anywhere\n * @method  forEach\n * @instance\n * @memberOf Mongo.Cursor\n * @param {IterationCallback} callback Function to call. It will be called with three arguments: the document, a 0-based index, and <em>cursor</em> itself.\n * @param {Any} [thisArg] An object which will be the value of `this` inside `callback`.\n */\nLocalCollection.Cursor.prototype.forEach = function (callback, thisArg) {\n  var self = this;\n\n  var objects = self._getRawObjects({ordered: true});\n\n  if (self.reactive) {\n    self._depend({\n      addedBefore: true,\n      removed: true,\n      changed: true,\n      movedBefore: true});\n  }\n\n  _.each(objects, function (elt, i) {\n    // This doubles as a clone operation.\n    elt = self._projectionFn(elt);\n\n    if (self._transform)\n      elt = self._transform(elt);\n    callback.call(thisArg, elt, i, self);\n  });\n};\n\nLocalCollection.Cursor.prototype.getTransform = function () {\n  return this._transform;\n};\n\n/**\n * @summary Map callback over all matching documents.  Returns an Array.\n * @locus Anywhere\n * @method map\n * @instance\n * @memberOf Mongo.Cursor\n * @param {IterationCallback} callback Function to call. It will be called with three arguments: the document, a 0-based index, and <em>cursor</em> itself.\n * @param {Any} [thisArg] An object which will be the value of `this` inside `callback`.\n */\nLocalCollection.Cursor.prototype.map = function (callback, thisArg) {\n  var self = this;\n  var res = [];\n  self.forEach(function (doc, index) {\n    res.push(callback.call(thisArg, doc, index, self));\n  });\n  return res;\n};\n\n/**\n * @summary Return all matching documents as an Array.\n * @memberOf Mongo.Cursor\n * @method  fetch\n * @instance\n * @locus Anywhere\n * @returns {Object[]}\n */\nLocalCollection.Cursor.prototype.fetch = function () {\n  var self = this;\n  var res = [];\n  self.forEach(function (doc) {\n    res.push(doc);\n  });\n  return res;\n};\n\n/**\n * @summary Returns the number of documents that match a query.\n * @memberOf Mongo.Cursor\n * @method  count\n * @instance\n * @locus Anywhere\n * @returns {Number}\n */\nLocalCollection.Cursor.prototype.count = function () {\n  var self = this;\n\n  if (self.reactive)\n    self._depend({added: true, removed: true},\n                 true /* allow the observe to be unordered */);\n\n  return self._getRawObjects({ordered: true}).length;\n};\n\nLocalCollection.Cursor.prototype._publishCursor = function (sub) {\n  var self = this;\n  if (! self.collection.name)\n    throw new Error(\"Can't publish a cursor from a collection without a name.\");\n  var collection = self.collection.name;\n\n  // XXX minimongo should not depend on mongo-livedata!\n  if (! Package.mongo) {\n    throw new Error(\"Can't publish from Minimongo without the `mongo` package.\");\n  }\n\n  return Package.mongo.Mongo.Collection._publishCursor(self, sub, collection);\n};\n\nLocalCollection.Cursor.prototype._getCollectionName = function () {\n  var self = this;\n  return self.collection.name;\n};\n\nLocalCollection._observeChangesCallbacksAreOrdered = function (callbacks) {\n  if (callbacks.added && callbacks.addedBefore)\n    throw new Error(\"Please specify only one of added() and addedBefore()\");\n  return !!(callbacks.addedBefore || callbacks.movedBefore);\n};\n\nLocalCollection._observeCallbacksAreOrdered = function (callbacks) {\n  if (callbacks.addedAt && callbacks.added)\n    throw new Error(\"Please specify only one of added() and addedAt()\");\n  if (callbacks.changedAt && callbacks.changed)\n    throw new Error(\"Please specify only one of changed() and changedAt()\");\n  if (callbacks.removed && callbacks.removedAt)\n    throw new Error(\"Please specify only one of removed() and removedAt()\");\n\n  return !!(callbacks.addedAt || callbacks.movedTo || callbacks.changedAt\n            || callbacks.removedAt);\n};\n\n// the handle that comes back from observe.\nLocalCollection.ObserveHandle = function () {};\n\n// options to contain:\n//  * callbacks for observe():\n//    - addedAt (document, atIndex)\n//    - added (document)\n//    - changedAt (newDocument, oldDocument, atIndex)\n//    - changed (newDocument, oldDocument)\n//    - removedAt (document, atIndex)\n//    - removed (document)\n//    - movedTo (document, oldIndex, newIndex)\n//\n// attributes available on returned query handle:\n//  * stop(): end updates\n//  * collection: the collection this query is querying\n//\n// iff x is a returned query handle, (x instanceof\n// LocalCollection.ObserveHandle) is true\n//\n// initial results delivered through added callback\n// XXX maybe callbacks should take a list of objects, to expose transactions?\n// XXX maybe support field limiting (to limit what you're notified on)\n\n_.extend(LocalCollection.Cursor.prototype, {\n  /**\n   * @summary Watch a query.  Receive callbacks as the result set changes.\n   * @locus Anywhere\n   * @memberOf Mongo.Cursor\n   * @instance\n   * @param {Object} callbacks Functions to call to deliver the result set as it changes\n   */\n  observe: function (options) {\n    var self = this;\n    return LocalCollection._observeFromObserveChanges(self, options);\n  },\n\n  /**\n   * @summary Watch a query.  Receive callbacks as the result set changes.  Only the differences between the old and new documents are passed to the callbacks.\n   * @locus Anywhere\n   * @memberOf Mongo.Cursor\n   * @instance\n   * @param {Object} callbacks Functions to call to deliver the result set as it changes\n   */\n  observeChanges: function (options) {\n    var self = this;\n\n    var ordered = LocalCollection._observeChangesCallbacksAreOrdered(options);\n\n    // there are several places that assume you aren't combining skip/limit with\n    // unordered observe.  eg, update's EJSON.clone, and the \"there are several\"\n    // comment in _modifyAndNotify\n    // XXX allow skip/limit with unordered observe\n    if (!options._allow_unordered && !ordered && (self.skip || self.limit))\n      throw new Error(\"must use ordered observe (ie, 'addedBefore' instead of 'added') with skip or limit\");\n\n    if (self.fields && (self.fields._id === 0 || self.fields._id === false))\n      throw Error(\"You may not observe a cursor with {fields: {_id: 0}}\");\n\n    var query = {\n      dirty: false,\n      matcher: self.matcher, // not fast pathed\n      sorter: ordered && self.sorter,\n      distances: (\n        self.matcher.hasGeoQuery() && ordered && new LocalCollection._IdMap),\n      resultsSnapshot: null,\n      ordered: ordered,\n      cursor: self,\n      projectionFn: self._projectionFn\n    };\n    var qid;\n\n    // Non-reactive queries call added[Before] and then never call anything\n    // else.\n    if (self.reactive) {\n      qid = self.collection.next_qid++;\n      self.collection.queries[qid] = query;\n    }\n    query.results = self._getRawObjects({\n      ordered: ordered, distances: query.distances});\n    if (self.collection.paused)\n      query.resultsSnapshot = (ordered ? [] : new LocalCollection._IdMap);\n\n    // wrap callbacks we were passed. callbacks only fire when not paused and\n    // are never undefined\n    // Filters out blacklisted fields according to cursor's projection.\n    // XXX wrong place for this?\n\n    // furthermore, callbacks enqueue until the operation we're working on is\n    // done.\n    var wrapCallback = function (f) {\n      if (!f)\n        return function () {};\n      return function (/*args*/) {\n        var context = this;\n        var args = arguments;\n\n        if (self.collection.paused)\n          return;\n\n        self.collection._observeQueue.queueTask(function () {\n          f.apply(context, args);\n        });\n      };\n    };\n    query.added = wrapCallback(options.added);\n    query.changed = wrapCallback(options.changed);\n    query.removed = wrapCallback(options.removed);\n    if (ordered) {\n      query.addedBefore = wrapCallback(options.addedBefore);\n      query.movedBefore = wrapCallback(options.movedBefore);\n    }\n\n    if (!options._suppress_initial && !self.collection.paused) {\n      // XXX unify ordered and unordered interface\n      var each = ordered\n            ? _.bind(_.each, null, query.results)\n            : _.bind(query.results.forEach, query.results);\n      each(function (doc) {\n        var fields = EJSON.clone(doc);\n\n        delete fields._id;\n        if (ordered)\n          query.addedBefore(doc._id, self._projectionFn(fields), null);\n        query.added(doc._id, self._projectionFn(fields));\n      });\n    }\n\n    var handle = new LocalCollection.ObserveHandle;\n    _.extend(handle, {\n      collection: self.collection,\n      stop: function () {\n        if (self.reactive)\n          delete self.collection.queries[qid];\n      }\n    });\n\n    if (self.reactive && Tracker.active) {\n      // XXX in many cases, the same observe will be recreated when\n      // the current autorun is rerun.  we could save work by\n      // letting it linger across rerun and potentially get\n      // repurposed if the same observe is performed, using logic\n      // similar to that of Meteor.subscribe.\n      Tracker.onInvalidate(function () {\n        handle.stop();\n      });\n    }\n    // run the observe callbacks resulting from the initial contents\n    // before we leave the observe.\n    self.collection._observeQueue.drain();\n\n    return handle;\n  }\n});\n\n// Returns a collection of matching objects, but doesn't deep copy them.\n//\n// If ordered is set, returns a sorted array, respecting sorter, skip, and limit\n// properties of the query.  if sorter is falsey, no sort -- you get the natural\n// order.\n//\n// If ordered is not set, returns an object mapping from ID to doc (sorter, skip\n// and limit should not be set).\n//\n// If ordered is set and this cursor is a $near geoquery, then this function\n// will use an _IdMap to track each distance from the $near argument point in\n// order to use it as a sort key. If an _IdMap is passed in the 'distances'\n// argument, this function will clear it and use it for this purpose (otherwise\n// it will just create its own _IdMap). The observeChanges implementation uses\n// this to remember the distances after this function returns.\nLocalCollection.Cursor.prototype._getRawObjects = function (options) {\n  var self = this;\n  options = options || {};\n\n  // XXX use OrderedDict instead of array, and make IdMap and OrderedDict\n  // compatible\n  var results = options.ordered ? [] : new LocalCollection._IdMap;\n\n  // fast path for single ID value\n  if (self._selectorId !== undefined) {\n    // If you have non-zero skip and ask for a single id, you get\n    // nothing. This is so it matches the behavior of the '{_id: foo}'\n    // path.\n    if (self.skip)\n      return results;\n\n    var selectedDoc = self.collection._docs.get(self._selectorId);\n    if (selectedDoc) {\n      if (options.ordered)\n        results.push(selectedDoc);\n      else\n        results.set(self._selectorId, selectedDoc);\n    }\n    return results;\n  }\n\n  // slow path for arbitrary selector, sort, skip, limit\n\n  // in the observeChanges case, distances is actually part of the \"query\" (ie,\n  // live results set) object.  in other cases, distances is only used inside\n  // this function.\n  var distances;\n  if (self.matcher.hasGeoQuery() && options.ordered) {\n    if (options.distances) {\n      distances = options.distances;\n      distances.clear();\n    } else {\n      distances = new LocalCollection._IdMap();\n    }\n  }\n\n  self.collection._docs.forEach(function (doc, id) {\n    var matchResult = self.matcher.documentMatches(doc);\n    if (matchResult.result) {\n      if (options.ordered) {\n        results.push(doc);\n        if (distances && matchResult.distance !== undefined)\n          distances.set(id, matchResult.distance);\n      } else {\n        results.set(id, doc);\n      }\n    }\n    // Fast path for limited unsorted queries.\n    // XXX 'length' check here seems wrong for ordered\n    if (self.limit && !self.skip && !self.sorter &&\n        results.length === self.limit)\n      return false;  // break\n    return true;  // continue\n  });\n\n  if (!options.ordered)\n    return results;\n\n  if (self.sorter) {\n    var comparator = self.sorter.getComparator({distances: distances});\n    results.sort(comparator);\n  }\n\n  var idx_start = self.skip || 0;\n  var idx_end = self.limit ? (self.limit + idx_start) : results.length;\n  return results.slice(idx_start, idx_end);\n};\n\n// XXX Maybe we need a version of observe that just calls a callback if\n// anything changed.\nLocalCollection.Cursor.prototype._depend = function (changers, _allow_unordered) {\n  var self = this;\n\n  if (Tracker.active) {\n    var v = new Tracker.Dependency;\n    v.depend();\n    var notifyChange = _.bind(v.changed, v);\n\n    var options = {\n      _suppress_initial: true,\n      _allow_unordered: _allow_unordered\n    };\n    _.each(['added', 'changed', 'removed', 'addedBefore', 'movedBefore'],\n           function (fnName) {\n             if (changers[fnName])\n               options[fnName] = notifyChange;\n           });\n\n    // observeChanges will stop() when this computation is invalidated\n    self.observeChanges(options);\n  }\n};\n\n// XXX enforce rule that field names can't start with '$' or contain '.'\n// (real mongodb does in fact enforce this)\n// XXX possibly enforce that 'undefined' does not appear (we assume\n// this in our handling of null and $exists)\nLocalCollection.prototype.insert = function (doc, callback) {\n  var self = this;\n  doc = EJSON.clone(doc);\n\n  if (!_.has(doc, '_id')) {\n    // if you really want to use ObjectIDs, set this global.\n    // Mongo.Collection specifies its own ids and does not use this code.\n    doc._id = LocalCollection._useOID ? new MongoID.ObjectID()\n                                      : Random.id();\n  }\n  var id = doc._id;\n\n  if (self._docs.has(id))\n    throw MinimongoError(\"Duplicate _id '\" + id + \"'\");\n\n  self._saveOriginal(id, undefined);\n  self._docs.set(id, doc);\n\n  var queriesToRecompute = [];\n  // trigger live queries that match\n  for (var qid in self.queries) {\n    var query = self.queries[qid];\n    if (query.dirty) continue;\n    var matchResult = query.matcher.documentMatches(doc);\n    if (matchResult.result) {\n      if (query.distances && matchResult.distance !== undefined)\n        query.distances.set(id, matchResult.distance);\n      if (query.cursor.skip || query.cursor.limit)\n        queriesToRecompute.push(qid);\n      else\n        LocalCollection._insertInResults(query, doc);\n    }\n  }\n\n  _.each(queriesToRecompute, function (qid) {\n    if (self.queries[qid])\n      self._recomputeResults(self.queries[qid]);\n  });\n  self._observeQueue.drain();\n\n  // Defer because the caller likely doesn't expect the callback to be run\n  // immediately.\n  if (callback)\n    Meteor.defer(function () {\n      callback(null, id);\n    });\n  return id;\n};\n\n// Iterates over a subset of documents that could match selector; calls\n// f(doc, id) on each of them.  Specifically, if selector specifies\n// specific _id's, it only looks at those.  doc is *not* cloned: it is the\n// same object that is in _docs.\nLocalCollection.prototype._eachPossiblyMatchingDoc = function (selector, f) {\n  var self = this;\n  var specificIds = LocalCollection._idsMatchedBySelector(selector);\n  if (specificIds) {\n    for (var i = 0; i < specificIds.length; ++i) {\n      var id = specificIds[i];\n      var doc = self._docs.get(id);\n      if (doc) {\n        var breakIfFalse = f(doc, id);\n        if (breakIfFalse === false)\n          break;\n      }\n    }\n  } else {\n    self._docs.forEach(f);\n  }\n};\n\nLocalCollection.prototype.remove = function (selector, callback) {\n  var self = this;\n\n  // Easy special case: if we're not calling observeChanges callbacks and we're\n  // not saving originals and we got asked to remove everything, then just empty\n  // everything directly.\n  if (self.paused && !self._savedOriginals && EJSON.equals(selector, {})) {\n    var result = self._docs.size();\n    self._docs.clear();\n    _.each(self.queries, function (query) {\n      if (query.ordered) {\n        query.results = [];\n      } else {\n        query.results.clear();\n      }\n    });\n    if (callback) {\n      Meteor.defer(function () {\n        callback(null, result);\n      });\n    }\n    return result;\n  }\n\n  var matcher = new Minimongo.Matcher(selector);\n  var remove = [];\n  self._eachPossiblyMatchingDoc(selector, function (doc, id) {\n    if (matcher.documentMatches(doc).result)\n      remove.push(id);\n  });\n\n  var queriesToRecompute = [];\n  var queryRemove = [];\n  for (var i = 0; i < remove.length; i++) {\n    var removeId = remove[i];\n    var removeDoc = self._docs.get(removeId);\n    _.each(self.queries, function (query, qid) {\n      if (query.dirty) return;\n\n      if (query.matcher.documentMatches(removeDoc).result) {\n        if (query.cursor.skip || query.cursor.limit)\n          queriesToRecompute.push(qid);\n        else\n          queryRemove.push({qid: qid, doc: removeDoc});\n      }\n    });\n    self._saveOriginal(removeId, removeDoc);\n    self._docs.remove(removeId);\n  }\n\n  // run live query callbacks _after_ we've removed the documents.\n  _.each(queryRemove, function (remove) {\n    var query = self.queries[remove.qid];\n    if (query) {\n      query.distances && query.distances.remove(remove.doc._id);\n      LocalCollection._removeFromResults(query, remove.doc);\n    }\n  });\n  _.each(queriesToRecompute, function (qid) {\n    var query = self.queries[qid];\n    if (query)\n      self._recomputeResults(query);\n  });\n  self._observeQueue.drain();\n  result = remove.length;\n  if (callback)\n    Meteor.defer(function () {\n      callback(null, result);\n    });\n  return result;\n};\n\n// XXX atomicity: if multi is true, and one modification fails, do\n// we rollback the whole operation, or what?\nLocalCollection.prototype.update = function (selector, mod, options, callback) {\n  var self = this;\n  if (! callback && options instanceof Function) {\n    callback = options;\n    options = null;\n  }\n  if (!options) options = {};\n\n  var matcher = new Minimongo.Matcher(selector);\n\n  // Save the original results of any query that we might need to\n  // _recomputeResults on, because _modifyAndNotify will mutate the objects in\n  // it. (We don't need to save the original results of paused queries because\n  // they already have a resultsSnapshot and we won't be diffing in\n  // _recomputeResults.)\n  var qidToOriginalResults = {};\n  // We should only clone each document once, even if it appears in multiple queries\n  var docMap = new LocalCollection._IdMap;\n  var idsMatchedBySelector = LocalCollection._idsMatchedBySelector(selector);\n\n  _.each(self.queries, function (query, qid) {\n    if ((query.cursor.skip || query.cursor.limit) && ! self.paused) {\n      // Catch the case of a reactive `count()` on a cursor with skip\n      // or limit, which registers an unordered observe. This is a\n      // pretty rare case, so we just clone the entire result set with\n      // no optimizations for documents that appear in these result\n      // sets and other queries.\n      if (query.results instanceof LocalCollection._IdMap) {\n        qidToOriginalResults[qid] = query.results.clone();\n        return;\n      }\n\n      if (!(query.results instanceof Array)) {\n        throw new Error(\"Assertion failed: query.results not an array\");\n      }\n\n      // Clones a document to be stored in `qidToOriginalResults`\n      // because it may be modified before the new and old result sets\n      // are diffed. But if we know exactly which document IDs we're\n      // going to modify, then we only need to clone those.\n      var memoizedCloneIfNeeded = function(doc) {\n        if (docMap.has(doc._id)) {\n          return docMap.get(doc._id);\n        } else {\n          var docToMemoize;\n\n          if (idsMatchedBySelector && !_.any(idsMatchedBySelector, function(id) {\n            return EJSON.equals(id, doc._id);\n          })) {\n            docToMemoize = doc;\n          } else {\n            docToMemoize = EJSON.clone(doc);\n          }\n\n          docMap.set(doc._id, docToMemoize);\n          return docToMemoize;\n        }\n      };\n\n      qidToOriginalResults[qid] = query.results.map(memoizedCloneIfNeeded);\n    }\n  });\n  var recomputeQids = {};\n\n  var updateCount = 0;\n\n  self._eachPossiblyMatchingDoc(selector, function (doc, id) {\n    var queryResult = matcher.documentMatches(doc);\n    if (queryResult.result) {\n      // XXX Should we save the original even if mod ends up being a no-op?\n      self._saveOriginal(id, doc);\n      self._modifyAndNotify(doc, mod, recomputeQids, queryResult.arrayIndices);\n      ++updateCount;\n      if (!options.multi)\n        return false;  // break\n    }\n    return true;\n  });\n\n  _.each(recomputeQids, function (dummy, qid) {\n    var query = self.queries[qid];\n    if (query)\n      self._recomputeResults(query, qidToOriginalResults[qid]);\n  });\n  self._observeQueue.drain();\n\n  // If we are doing an upsert, and we didn't modify any documents yet, then\n  // it's time to do an insert. Figure out what document we are inserting, and\n  // generate an id for it.\n  var insertedId;\n  if (updateCount === 0 && options.upsert) {\n    var newDoc = LocalCollection._removeDollarOperators(selector);\n    LocalCollection._modify(newDoc, mod, {isInsert: true});\n    if (! newDoc._id && options.insertedId)\n      newDoc._id = options.insertedId;\n    insertedId = self.insert(newDoc);\n    updateCount = 1;\n  }\n\n  // Return the number of affected documents, or in the upsert case, an object\n  // containing the number of affected docs and the id of the doc that was\n  // inserted, if any.\n  var result;\n  if (options._returnObject) {\n    result = {\n      numberAffected: updateCount\n    };\n    if (insertedId !== undefined)\n      result.insertedId = insertedId;\n  } else {\n    result = updateCount;\n  }\n\n  if (callback)\n    Meteor.defer(function () {\n      callback(null, result);\n    });\n  return result;\n};\n\n// A convenience wrapper on update. LocalCollection.upsert(sel, mod) is\n// equivalent to LocalCollection.update(sel, mod, { upsert: true, _returnObject:\n// true }).\nLocalCollection.prototype.upsert = function (selector, mod, options, callback) {\n  var self = this;\n  if (! callback && typeof options === \"function\") {\n    callback = options;\n    options = {};\n  }\n  return self.update(selector, mod, _.extend({}, options, {\n    upsert: true,\n    _returnObject: true\n  }), callback);\n};\n\nLocalCollection.prototype._modifyAndNotify = function (\n    doc, mod, recomputeQids, arrayIndices) {\n  var self = this;\n\n  var matched_before = {};\n  for (var qid in self.queries) {\n    var query = self.queries[qid];\n    if (query.dirty) continue;\n\n    if (query.ordered) {\n      matched_before[qid] = query.matcher.documentMatches(doc).result;\n    } else {\n      // Because we don't support skip or limit (yet) in unordered queries, we\n      // can just do a direct lookup.\n      matched_before[qid] = query.results.has(doc._id);\n    }\n  }\n\n  var old_doc = EJSON.clone(doc);\n\n  LocalCollection._modify(doc, mod, {arrayIndices: arrayIndices});\n\n  for (qid in self.queries) {\n    query = self.queries[qid];\n    if (query.dirty) continue;\n\n    var before = matched_before[qid];\n    var afterMatch = query.matcher.documentMatches(doc);\n    var after = afterMatch.result;\n    if (after && query.distances && afterMatch.distance !== undefined)\n      query.distances.set(doc._id, afterMatch.distance);\n\n    if (query.cursor.skip || query.cursor.limit) {\n      // We need to recompute any query where the doc may have been in the\n      // cursor's window either before or after the update. (Note that if skip\n      // or limit is set, \"before\" and \"after\" being true do not necessarily\n      // mean that the document is in the cursor's output after skip/limit is\n      // applied... but if they are false, then the document definitely is NOT\n      // in the output. So it's safe to skip recompute if neither before or\n      // after are true.)\n      if (before || after)\n        recomputeQids[qid] = true;\n    } else if (before && !after) {\n      LocalCollection._removeFromResults(query, doc);\n    } else if (!before && after) {\n      LocalCollection._insertInResults(query, doc);\n    } else if (before && after) {\n      LocalCollection._updateInResults(query, doc, old_doc);\n    }\n  }\n};\n\n// XXX the sorted-query logic below is laughably inefficient. we'll\n// need to come up with a better datastructure for this.\n//\n// XXX the logic for observing with a skip or a limit is even more\n// laughably inefficient. we recompute the whole results every time!\n\nLocalCollection._insertInResults = function (query, doc) {\n  var fields = EJSON.clone(doc);\n  delete fields._id;\n  if (query.ordered) {\n    if (!query.sorter) {\n      query.addedBefore(doc._id, query.projectionFn(fields), null);\n      query.results.push(doc);\n    } else {\n      var i = LocalCollection._insertInSortedList(\n        query.sorter.getComparator({distances: query.distances}),\n        query.results, doc);\n      var next = query.results[i+1];\n      if (next)\n        next = next._id;\n      else\n        next = null;\n      query.addedBefore(doc._id, query.projectionFn(fields), next);\n    }\n    query.added(doc._id, query.projectionFn(fields));\n  } else {\n    query.added(doc._id, query.projectionFn(fields));\n    query.results.set(doc._id, doc);\n  }\n};\n\nLocalCollection._removeFromResults = function (query, doc) {\n  if (query.ordered) {\n    var i = LocalCollection._findInOrderedResults(query, doc);\n    query.removed(doc._id);\n    query.results.splice(i, 1);\n  } else {\n    var id = doc._id;  // in case callback mutates doc\n    query.removed(doc._id);\n    query.results.remove(id);\n  }\n};\n\nLocalCollection._updateInResults = function (query, doc, old_doc) {\n  if (!EJSON.equals(doc._id, old_doc._id))\n    throw new Error(\"Can't change a doc's _id while updating\");\n  var projectionFn = query.projectionFn;\n  var changedFields = DiffSequence.makeChangedFields(\n    projectionFn(doc), projectionFn(old_doc));\n\n  if (!query.ordered) {\n    if (!_.isEmpty(changedFields)) {\n      query.changed(doc._id, changedFields);\n      query.results.set(doc._id, doc);\n    }\n    return;\n  }\n\n  var orig_idx = LocalCollection._findInOrderedResults(query, doc);\n\n  if (!_.isEmpty(changedFields))\n    query.changed(doc._id, changedFields);\n  if (!query.sorter)\n    return;\n\n  // just take it out and put it back in again, and see if the index\n  // changes\n  query.results.splice(orig_idx, 1);\n  var new_idx = LocalCollection._insertInSortedList(\n    query.sorter.getComparator({distances: query.distances}),\n    query.results, doc);\n  if (orig_idx !== new_idx) {\n    var next = query.results[new_idx+1];\n    if (next)\n      next = next._id;\n    else\n      next = null;\n    query.movedBefore && query.movedBefore(doc._id, next);\n  }\n};\n\n// Recomputes the results of a query and runs observe callbacks for the\n// difference between the previous results and the current results (unless\n// paused). Used for skip/limit queries.\n//\n// When this is used by insert or remove, it can just use query.results for the\n// old results (and there's no need to pass in oldResults), because these\n// operations don't mutate the documents in the collection. Update needs to pass\n// in an oldResults which was deep-copied before the modifier was applied.\n//\n// oldResults is guaranteed to be ignored if the query is not paused.\nLocalCollection.prototype._recomputeResults = function (query, oldResults) {\n  var self = this;\n  if (self.paused) {\n    // There's no reason to recompute the results now as we're still paused.\n    // By flagging the query as \"dirty\", the recompute will be performed\n    // when resumeObservers is called.\n    query.dirty = true;\n    return;\n  }\n\n  if (! self.paused && ! oldResults)\n    oldResults = query.results;\n  if (query.distances)\n    query.distances.clear();\n  query.results = query.cursor._getRawObjects({\n    ordered: query.ordered, distances: query.distances});\n\n  if (! self.paused) {\n    LocalCollection._diffQueryChanges(\n      query.ordered, oldResults, query.results, query,\n      { projectionFn: query.projectionFn });\n  }\n};\n\n\nLocalCollection._findInOrderedResults = function (query, doc) {\n  if (!query.ordered)\n    throw new Error(\"Can't call _findInOrderedResults on unordered query\");\n  for (var i = 0; i < query.results.length; i++)\n    if (query.results[i] === doc)\n      return i;\n  throw Error(\"object missing from query\");\n};\n\n// This binary search puts a value between any equal values, and the first\n// lesser value.\nLocalCollection._binarySearch = function (cmp, array, value) {\n  var first = 0, rangeLength = array.length;\n\n  while (rangeLength > 0) {\n    var halfRange = Math.floor(rangeLength/2);\n    if (cmp(value, array[first + halfRange]) >= 0) {\n      first += halfRange + 1;\n      rangeLength -= halfRange + 1;\n    } else {\n      rangeLength = halfRange;\n    }\n  }\n  return first;\n};\n\nLocalCollection._insertInSortedList = function (cmp, array, value) {\n  if (array.length === 0) {\n    array.push(value);\n    return 0;\n  }\n\n  var idx = LocalCollection._binarySearch(cmp, array, value);\n  array.splice(idx, 0, value);\n  return idx;\n};\n\n// To track what documents are affected by a piece of code, call saveOriginals()\n// before it and retrieveOriginals() after it. retrieveOriginals returns an\n// object whose keys are the ids of the documents that were affected since the\n// call to saveOriginals(), and the values are equal to the document's contents\n// at the time of saveOriginals. (In the case of an inserted document, undefined\n// is the value.) You must alternate between calls to saveOriginals() and\n// retrieveOriginals().\nLocalCollection.prototype.saveOriginals = function () {\n  var self = this;\n  if (self._savedOriginals)\n    throw new Error(\"Called saveOriginals twice without retrieveOriginals\");\n  self._savedOriginals = new LocalCollection._IdMap;\n};\nLocalCollection.prototype.retrieveOriginals = function () {\n  var self = this;\n  if (!self._savedOriginals)\n    throw new Error(\"Called retrieveOriginals without saveOriginals\");\n\n  var originals = self._savedOriginals;\n  self._savedOriginals = null;\n  return originals;\n};\n\nLocalCollection.prototype._saveOriginal = function (id, doc) {\n  var self = this;\n  // Are we even trying to save originals?\n  if (!self._savedOriginals)\n    return;\n  // Have we previously mutated the original (and so 'doc' is not actually\n  // original)?  (Note the 'has' check rather than truth: we store undefined\n  // here for inserted docs!)\n  if (self._savedOriginals.has(id))\n    return;\n  self._savedOriginals.set(id, EJSON.clone(doc));\n};\n\n// Pause the observers. No callbacks from observers will fire until\n// 'resumeObservers' is called.\nLocalCollection.prototype.pauseObservers = function () {\n  // No-op if already paused.\n  if (this.paused)\n    return;\n\n  // Set the 'paused' flag such that new observer messages don't fire.\n  this.paused = true;\n\n  // Take a snapshot of the query results for each query.\n  for (var qid in this.queries) {\n    var query = this.queries[qid];\n\n    query.resultsSnapshot = EJSON.clone(query.results);\n  }\n};\n\n// Resume the observers. Observers immediately receive change\n// notifications to bring them to the current state of the\n// database. Note that this is not just replaying all the changes that\n// happened during the pause, it is a smarter 'coalesced' diff.\nLocalCollection.prototype.resumeObservers = function () {\n  var self = this;\n  // No-op if not paused.\n  if (!this.paused)\n    return;\n\n  // Unset the 'paused' flag. Make sure to do this first, otherwise\n  // observer methods won't actually fire when we trigger them.\n  this.paused = false;\n\n  for (var qid in this.queries) {\n    var query = self.queries[qid];\n    if (query.dirty) {\n      query.dirty = false;\n      // re-compute results will perform `LocalCollection._diffQueryChanges` automatically.\n      self._recomputeResults(query, query.resultsSnapshot);\n    } else {\n      // Diff the current results against the snapshot and send to observers.\n      // pass the query object for its observer callbacks.\n      LocalCollection._diffQueryChanges(\n        query.ordered, query.resultsSnapshot, query.results, query,\n        {projectionFn: query.projectionFn});\n    }\n    query.resultsSnapshot = null;\n  }\n  self._observeQueue.drain();\n};\n\n"
  },
  {
    "path": "packages/minimongo/minimongo_server_tests.js",
    "content": "Tinytest.add(\"minimongo - modifier affects selector\", function (test) {\n  function testSelectorPaths (sel, paths, desc) {\n    var matcher = new Minimongo.Matcher(sel);\n    test.equal(matcher._getPaths(), paths, desc);\n  }\n\n  testSelectorPaths({\n    foo: {\n      bar: 3,\n      baz: 42\n    }\n  }, ['foo'], \"literal\");\n\n  testSelectorPaths({\n    foo: 42,\n    bar: 33\n  }, ['foo', 'bar'], \"literal\");\n\n  testSelectorPaths({\n    foo: [ 'something' ],\n    bar: \"asdf\"\n  }, ['foo', 'bar'], \"literal\");\n\n  testSelectorPaths({\n    a: { $lt: 3 },\n    b: \"you know, literal\",\n    'path.is.complicated': { $not: { $regex: 'acme.*corp' } }\n  }, ['a', 'b', 'path.is.complicated'], \"literal + operators\");\n\n  testSelectorPaths({\n    $or: [{ 'a.b': 1 }, { 'a.b.c': { $lt: 22 } },\n     {$and: [{ 'x.d': { $ne: 5, $gte: 433 } }, { 'a.b': 234 }]}]\n  }, ['a.b', 'a.b.c', 'x.d'], 'group operators + duplicates');\n\n  // When top-level value is an object, it is treated as a literal,\n  // so when you query col.find({ a: { foo: 1, bar: 2 } })\n  // it doesn't mean you are looking for anything that has 'a.foo' to be 1 and\n  // 'a.bar' to be 2, instead you are looking for 'a' to be exatly that object\n  // with exatly that order of keys. { a: { foo: 1, bar: 2, baz: 3 } } wouldn't\n  // match it. That's why in this selector 'a' would be important key, not a.foo\n  // and a.bar.\n  testSelectorPaths({\n    a: {\n      foo: 1,\n      bar: 2\n    },\n    'b.c': {\n      literal: \"object\",\n      but: \"we still observe any changes in 'b.c'\"\n    }\n  }, ['a', 'b.c'], \"literal object\");\n\n  // Note that a and b do NOT end up in the path list, but x and y both do.\n  testSelectorPaths({\n    $or: [\n      {x: {$elemMatch: {a: 5}}},\n      {y: {$elemMatch: {b: 7}}}\n    ]\n  }, ['x', 'y'], \"$or and elemMatch\");\n\n  function testSelectorAffectedByModifier (sel, mod, yes, desc) {\n    var matcher = new Minimongo.Matcher(sel);\n    test.equal(matcher.affectedByModifier(mod), yes, desc);\n  }\n\n  function affected(sel, mod, desc) {\n    testSelectorAffectedByModifier(sel, mod, true, desc);\n  }\n  function notAffected(sel, mod, desc) {\n    testSelectorAffectedByModifier(sel, mod, false, desc);\n  }\n\n  notAffected({ foo: 0 }, { $set: { bar: 1 } }, \"simplest\");\n  affected({ foo: 0 }, { $set: { foo: 1 } }, \"simplest\");\n  affected({ foo: 0 }, { $set: { 'foo.bar': 1 } }, \"simplest\");\n  notAffected({ 'foo.bar': 0 }, { $set: { 'foo.baz': 1 } }, \"simplest\");\n  affected({ 'foo.bar': 0 }, { $set: { 'foo.1': 1 } }, \"simplest\");\n  affected({ 'foo.bar': 0 }, { $set: { 'foo.2.bar': 1 } }, \"simplest\");\n\n  notAffected({ 'foo': 0 }, { $set: { 'foobaz': 1 } }, \"correct prefix check\");\n  notAffected({ 'foobar': 0 }, { $unset: { 'foo': 1 } }, \"correct prefix check\");\n  notAffected({ 'foo.bar': 0 }, { $unset: { 'foob': 1 } }, \"correct prefix check\");\n\n  notAffected({ 'foo.Infinity.x': 0 }, { $unset: { 'foo.x': 1 } }, \"we convert integer fields correctly\");\n  notAffected({ 'foo.1e3.x': 0 }, { $unset: { 'foo.x': 1 } }, \"we convert integer fields correctly\");\n\n  affected({ 'foo.3.bar': 0 }, { $set: { 'foo.3.bar': 1 } }, \"observe for an array element\");\n\n  notAffected({ 'foo.4.bar.baz': 0 }, { $unset: { 'foo.3.bar': 1 } }, \"delicate work with numeric fields in selector\");\n  notAffected({ 'foo.4.bar.baz': 0 }, { $unset: { 'foo.bar': 1 } }, \"delicate work with numeric fields in selector\");\n  affected({ 'foo.4.bar.baz': 0 }, { $unset: { 'foo.4.bar': 1 } }, \"delicate work with numeric fields in selector\");\n  affected({ 'foo.bar.baz': 0 }, { $unset: { 'foo.3.bar': 1 } }, \"delicate work with numeric fields in selector\");\n\n  affected({ 'foo.0.bar': 0 }, { $set: { 'foo.0.0.bar': 1 } }, \"delicate work with nested arrays and selectors by indecies\");\n\n  affected({foo: {$elemMatch: {bar: 5}}}, {$set: {'foo.4.bar': 5}}, \"$elemMatch\");\n});\n\nTinytest.add(\"minimongo - selector and projection combination\", function (test) {\n  function testSelProjectionComb (sel, proj, expected, desc) {\n    var matcher = new Minimongo.Matcher(sel);\n    test.equal(matcher.combineIntoProjection(proj), expected, desc);\n  }\n\n  // Test with inclusive projection\n  testSelProjectionComb({ a: 1, b: 2 }, { b: 1, c: 1, d: 1 }, { a: true, b: true, c: true, d: true }, \"simplest incl\");\n  testSelProjectionComb({ $or: [{ a: 1234, e: {$lt: 5} }], b: 2 }, { b: 1, c: 1, d: 1 }, { a: true, b: true, c: true, d: true, e: true }, \"simplest incl, branching\");\n  testSelProjectionComb({\n    'a.b': { $lt: 3 },\n    'y.0': -1,\n    'a.c': 15\n  }, {\n    'd': 1,\n    'z': 1\n  }, {\n    'a.b': true,\n    'y': true,\n    'a.c': true,\n    'd': true,\n    'z': true\n  }, \"multikey paths in selector - incl\");\n\n  testSelProjectionComb({\n    foo: 1234,\n    $and: [{ k: -1 }, { $or: [{ b: 15 }] }]\n  }, {\n    'foo.bar': 1,\n    'foo.zzz': 1,\n    'b.asdf': 1\n  }, {\n    foo: true,\n    b: true,\n    k: true\n  }, \"multikey paths in fields - incl\");\n\n  testSelProjectionComb({\n    'a.b.c': 123,\n    'a.b.d': 321,\n    'b.c.0': 111,\n    'a.e': 12345\n  }, {\n    'a.b.z': 1,\n    'a.b.d.g': 1,\n    'c.c.c': 1\n  }, {\n    'a.b.c': true,\n    'a.b.d': true,\n    'a.b.z': true,\n    'b.c': true,\n    'a.e': true,\n    'c.c.c': true\n  }, \"multikey both paths - incl\");\n\n  testSelProjectionComb({\n    'a.b.c.d': 123,\n    'a.b1.c.d': 421,\n    'a.b.c.e': 111\n  }, {\n    'a.b': 1\n  }, {\n    'a.b': true,\n    'a.b1.c.d': true\n  }, \"shadowing one another - incl\");\n\n  testSelProjectionComb({\n    'a.b': 123,\n    'foo.bar': false\n  }, {\n    'a.b.c.d': 1,\n    'foo': 1\n  }, {\n    'a.b': true,\n    'foo': true\n  }, \"shadowing one another - incl\");\n\n  testSelProjectionComb({\n    'a.b.c': 1\n  }, {\n    'a.b.c': 1\n  }, {\n    'a.b.c': true\n  }, \"same paths - incl\");\n\n  testSelProjectionComb({\n    'x.4.y': 42,\n    'z.0.1': 33\n  }, {\n    'x.x': 1\n  }, {\n    'x.x': true,\n    'x.y': true,\n    'z': true\n  }, \"numbered keys in selector - incl\");\n\n  testSelProjectionComb({\n    'a.b.c': 42,\n    $where: function () { return true; }\n  }, {\n    'a.b': 1,\n    'z.z': 1\n  }, {}, \"$where in the selector - incl\");\n\n  testSelProjectionComb({\n    $or: [\n      {'a.b.c': 42},\n      {$where: function () { return true; } }\n    ]\n  }, {\n    'a.b': 1,\n    'z.z': 1\n  }, {}, \"$where in the selector - incl\");\n\n  // Test with exclusive projection\n  testSelProjectionComb({ a: 1, b: 2 }, { b: 0, c: 0, d: 0 }, { c: false, d: false }, \"simplest excl\");\n  testSelProjectionComb({ $or: [{ a: 1234, e: {$lt: 5} }], b: 2 }, { b: 0, c: 0, d: 0 }, { c: false, d: false }, \"simplest excl, branching\");\n  testSelProjectionComb({\n    'a.b': { $lt: 3 },\n    'y.0': -1,\n    'a.c': 15\n  }, {\n    'd': 0,\n    'z': 0\n  }, {\n    d: false,\n    z: false\n  }, \"multikey paths in selector - excl\");\n\n  testSelProjectionComb({\n    foo: 1234,\n    $and: [{ k: -1 }, { $or: [{ b: 15 }] }]\n  }, {\n    'foo.bar': 0,\n    'foo.zzz': 0,\n    'b.asdf': 0\n  }, {\n  }, \"multikey paths in fields - excl\");\n\n  testSelProjectionComb({\n    'a.b.c': 123,\n    'a.b.d': 321,\n    'b.c.0': 111,\n    'a.e': 12345\n  }, {\n    'a.b.z': 0,\n    'a.b.d.g': 0,\n    'c.c.c': 0\n  }, {\n    'a.b.z': false,\n    'c.c.c': false\n  }, \"multikey both paths - excl\");\n\n  testSelProjectionComb({\n    'a.b.c.d': 123,\n    'a.b1.c.d': 421,\n    'a.b.c.e': 111\n  }, {\n    'a.b': 0\n  }, {\n  }, \"shadowing one another - excl\");\n\n  testSelProjectionComb({\n    'a.b': 123,\n    'foo.bar': false\n  }, {\n    'a.b.c.d': 0,\n    'foo': 0\n  }, {\n  }, \"shadowing one another - excl\");\n\n  testSelProjectionComb({\n    'a.b.c': 1\n  }, {\n    'a.b.c': 0\n  }, {\n  }, \"same paths - excl\");\n\n  testSelProjectionComb({\n    'a.b': 123,\n    'a.c.d': 222,\n    'ddd': 123\n  }, {\n    'a.b': 0,\n    'a.c.e': 0,\n    'asdf': 0\n  }, {\n    'a.c.e': false,\n    'asdf': false\n  }, \"intercept the selector path - excl\");\n\n  testSelProjectionComb({\n    'a.b.c': 14\n  }, {\n    'a.b.d': 0\n  }, {\n    'a.b.d': false\n  }, \"different branches - excl\");\n\n  testSelProjectionComb({\n    'a.b.c.d': \"124\",\n    'foo.bar.baz.que': \"some value\"\n  }, {\n    'a.b.c.d.e': 0,\n    'foo.bar': 0\n  }, {\n  }, \"excl on incl paths - excl\");\n\n  testSelProjectionComb({\n    'x.4.y': 42,\n    'z.0.1': 33\n  }, {\n    'x.x': 0,\n    'x.y': 0\n  }, {\n    'x.x': false,\n  }, \"numbered keys in selector - excl\");\n\n  testSelProjectionComb({\n    'a.b.c': 42,\n    $where: function () { return true; }\n  }, {\n    'a.b': 0,\n    'z.z': 0\n  }, {}, \"$where in the selector - excl\");\n\n  testSelProjectionComb({\n    $or: [\n      {'a.b.c': 42},\n      {$where: function () { return true; } }\n    ]\n  }, {\n    'a.b': 0,\n    'z.z': 0\n  }, {}, \"$where in the selector - excl\");\n\n});\n\nTinytest.add(\"minimongo - sorter and projection combination\", function (test) {\n  function testSorterProjectionComb (sortSpec, proj, expected, desc) {\n    var sorter = new Minimongo.Sorter(sortSpec);\n    test.equal(sorter.combineIntoProjection(proj), expected, desc);\n  }\n\n  // Test with inclusive projection\n  testSorterProjectionComb({ a: 1, b: 1 }, { b: 1, c: 1, d: 1 }, { a: true, b: true, c: true, d: true }, \"simplest incl\");\n  testSorterProjectionComb({ a: 1, b: -1 }, { b: 1, c: 1, d: 1 }, { a: true, b: true, c: true, d: true }, \"simplest incl\");\n  testSorterProjectionComb({ 'a.c': 1 }, { b: 1 }, { 'a.c': true, b: true }, \"dot path incl\");\n  testSorterProjectionComb({ 'a.1.c': 1 }, { b: 1 }, { 'a.c': true, b: true }, \"dot num path incl\");\n  testSorterProjectionComb({ 'a.1.c': 1 }, { b: 1, a: 1 }, { a: true, b: true }, \"dot num path incl overlap\");\n  testSorterProjectionComb({ 'a.1.c': 1, 'a.2.b': -1 }, { b: 1 }, { 'a.c': true, 'a.b': true, b: true }, \"dot num path incl\");\n  testSorterProjectionComb({ 'a.1.c': 1, 'a.2.b': -1 }, {}, {}, \"dot num path with empty incl\");\n\n  // Test with exclusive projection\n  testSorterProjectionComb({ a: 1, b: 1 }, { b: 0, c: 0, d: 0 }, { c: false, d: false }, \"simplest excl\");\n  testSorterProjectionComb({ a: 1, b: -1 }, { b: 0, c: 0, d: 0 }, { c: false, d: false }, \"simplest excl\");\n  testSorterProjectionComb({ 'a.c': 1 }, { b: 0 }, { b: false }, \"dot path excl\");\n  testSorterProjectionComb({ 'a.1.c': 1 }, { b: 0 }, { b: false }, \"dot num path excl\");\n  testSorterProjectionComb({ 'a.1.c': 1 }, { b: 0, a: 0 }, { b: false }, \"dot num path excl overlap\");\n  testSorterProjectionComb({ 'a.1.c': 1, 'a.2.b': -1 }, { b: 0 }, { b: false }, \"dot num path excl\");\n});\n\n\n(function () {\n  // TODO: Tests for \"can selector become true by modifier\" are incomplete,\n  // absent or test the functionality of \"not ideal\" implementation (test checks\n  // that certain case always returns true as implementation is incomplete)\n  // - tests with $and/$or/$nor/$not branches (are absent)\n  // - more tests with arrays fields and numeric keys (incomplete and test \"not\n  // ideal\" implementation)\n  // - tests when numeric keys actually mean numeric keys, not array indexes\n  // (are absent)\n  // - tests with $-operators in the selector (are incomplete and test \"not\n  // ideal\" implementation)\n  //  * gives up on $-operators with non-scalar values ({$ne: {x: 1}})\n  //  * analyses $in\n  //  * analyses $nin/$ne\n  //  * analyses $gt, $gte, $lt, $lte\n  //  * gives up on a combination of $gt/$gte/$lt/$lte and $ne/$nin\n  //  * doesn't support $eq properly\n\n  var test = null; // set this global in the beginning of every test\n  // T - should return true\n  // F - should return false\n  var oneTest = function (sel, mod, expected, desc) {\n    var matcher = new Minimongo.Matcher(sel);\n    test.equal(matcher.canBecomeTrueByModifier(mod), expected, desc);\n  };\n  function T (sel, mod, desc) {\n    oneTest(sel, mod, true, desc);\n  }\n  function F (sel, mod, desc) {\n    oneTest(sel, mod, false, desc);\n  }\n\n  Tinytest.add(\"minimongo - can selector become true by modifier - literals (structured tests)\", function (t) {\n    test = t;\n\n    var selector = {\n      'a.b.c': 2,\n      'foo.bar': {\n        z: { y: 1 }\n      },\n      'foo.baz': [ {ans: 42}, \"string\", false, undefined ],\n      'empty.field': null\n    };\n\n    T(selector, {$set:{ 'a.b.c': 2 }});\n    F(selector, {$unset:{ 'a': 1 }});\n    F(selector, {$unset:{ 'a.b': 1 }});\n    F(selector, {$unset:{ 'a.b.c': 1 }});\n    T(selector, {$set:{ 'a.b': { c: 2 } }});\n    F(selector, {$set:{ 'a.b': {} }});\n    T(selector, {$set:{ 'a.b': { c: 2, x: 5 } }});\n    F(selector, {$set:{ 'a.b.c.k': 3 }});\n    F(selector, {$set:{ 'a.b.c.k': {} }});\n\n    F(selector, {$unset:{ 'foo': 1 }});\n    F(selector, {$unset:{ 'foo.bar': 1 }});\n    F(selector, {$unset:{ 'foo.bar.z': 1 }});\n    F(selector, {$unset:{ 'foo.bar.z.y': 1 }});\n    F(selector, {$set:{ 'foo.bar.x': 1 }});\n    F(selector, {$set:{ 'foo.bar': {} }});\n    F(selector, {$set:{ 'foo.bar': 3 }});\n    T(selector, {$set:{ 'foo.bar': { z: { y: 1 } } }});\n    T(selector, {$set:{ 'foo.bar.z': { y: 1 } }});\n    T(selector, {$set:{ 'foo.bar.z.y': 1 }});\n\n    F(selector, {$set:{ 'empty.field': {} }});\n    T(selector, {$set:{ 'empty': {} }});\n    T(selector, {$set:{ 'empty.field': null }});\n    T(selector, {$set:{ 'empty.field': undefined }});\n    F(selector, {$set:{ 'empty.field.a': 3 }});\n  });\n\n  Tinytest.add(\"minimongo - can selector become true by modifier - literals (adhoc tests)\", function (t) {\n    test = t;\n    T({x:1}, {$set:{x:1}}, \"simple set scalar\");\n    T({x:\"a\"}, {$set:{x:\"a\"}}, \"simple set scalar\");\n    T({x:false}, {$set:{x:false}}, \"simple set scalar\");\n    F({x:true}, {$set:{x:false}}, \"simple set scalar\");\n    F({x:2}, {$set:{x:3}}, \"simple set scalar\");\n\n    F({'foo.bar.baz': 1, x:1}, {$unset:{'foo.bar.baz': 1}, $set:{x:1}}, \"simple unset of the interesting path\");\n    F({'foo.bar.baz': 1, x:1}, {$unset:{'foo.bar': 1}, $set:{x:1}}, \"simple unset of the interesting path prefix\");\n    F({'foo.bar.baz': 1, x:1}, {$unset:{'foo': 1}, $set:{x:1}}, \"simple unset of the interesting path prefix\");\n    F({'foo.bar.baz': 1}, {$unset:{'foo.baz': 1}}, \"simple unset of the interesting path prefix\");\n    F({'foo.bar.baz': 1}, {$unset:{'foo.bar.bar': 1}}, \"simple unset of the interesting path prefix\");\n  });\n\n  Tinytest.add(\"minimongo - can selector become true by modifier - regexps\", function (t) {\n    test = t;\n\n    // Regexp\n    T({ 'foo.bar': /^[0-9]+$/i }, { $set: {'foo.bar': '01233'} }, \"set of regexp\");\n    // XXX this test should be False, should be fixed within improved implementation\n    T({ 'foo.bar': /^[0-9]+$/i, x: 1 }, { $set: {'foo.bar': '0a1233', x: 1} }, \"set of regexp\");\n    // XXX this test should be False, should be fixed within improved implementation\n    T({ 'foo.bar': /^[0-9]+$/i, x: 1 }, { $unset: {'foo.bar': 1}, $set: { x: 1 } }, \"unset of regexp\");\n    T({ 'foo.bar': /^[0-9]+$/i, x: 1 }, { $set: { x: 1 } }, \"don't touch regexp\");\n  });\n\n  Tinytest.add(\"minimongo - can selector become true by modifier - undefined/null\", function (t) {\n    test = t;\n    // Nulls / Undefined\n    T({ 'foo.bar': null }, {$set:{'foo.bar': null}}, \"set of null looking for null\");\n    T({ 'foo.bar': null }, {$set:{'foo.bar': undefined}}, \"set of undefined looking for null\");\n    T({ 'foo.bar': undefined }, {$set:{'foo.bar': null}}, \"set of null looking for undefined\");\n    T({ 'foo.bar': undefined }, {$set:{'foo.bar': undefined}}, \"set of undefined looking for undefined\");\n    T({ 'foo.bar': null }, {$set:{'foo': null}}, \"set of null of parent path looking for null\");\n    F({ 'foo.bar': null }, {$set:{'foo.bar.baz': null}}, \"set of null of different path looking for null\");\n    T({ 'foo.bar': null }, { $unset: { 'foo': 1 } }, \"unset the parent\");\n    T({ 'foo.bar': null }, { $unset: { 'foo.bar': 1 } }, \"unset tracked path\");\n    T({ 'foo.bar': null }, { $set: { 'foo': 3 } }, \"set the parent\");\n    T({ 'foo.bar': null }, { $set: { 'foo': {baz:1} } }, \"set the parent\");\n\n  });\n\n  Tinytest.add(\"minimongo - can selector become true by modifier - literals with arrays\", function (t) {\n    test = t;\n    // These tests are incomplete and in theory they all should return true as we\n    // don't support any case with numeric fields yet.\n    T({'a.1.b': 1, x:1}, {$unset:{'a.1.b': 1}, $set:{x:1}}, \"unset of array element's field with exactly the same index as selector\");\n    F({'a.2.b': 1}, {$unset:{'a.1.b': 1}}, \"unset of array element's field with different index as selector\");\n    // This is false, because if you are looking for array but in reality it is an\n    // object, it just can't get to true.\n    F({'a.2.b': 1}, {$unset:{'a.b': 1}}, \"unset of field while selector is looking for index\");\n    T({ 'foo.bar': null }, {$set:{'foo.1.bar': null}}, \"set array's element's field to null looking for null\");\n    T({ 'foo.bar': null }, {$set:{'foo.0.bar': 1, 'foo.1.bar': null}}, \"set array's element's field to null looking for null\");\n    // This is false, because there may remain other array elements that match\n    // but we modified this test as we don't support this case yet\n    T({'a.b': 1}, {$unset:{'a.1.b': 1}}, \"unset of array element's field\");\n  });\n\n  Tinytest.add(\"minimongo - can selector become true by modifier - set an object literal whose fields are selected\", function (t) {\n    test = t;\n    T({ 'a.b.c': 1 }, { $set: { 'a.b': { c: 1 } } }, \"a simple scalar selector and simple set\");\n    F({ 'a.b.c': 1 }, { $set: { 'a.b': { c: 2 } } }, \"a simple scalar selector and simple set to false\");\n    F({ 'a.b.c': 1 }, { $set: { 'a.b': { d: 1 } } }, \"a simple scalar selector and simple set a wrong literal\");\n    F({ 'a.b.c': 1 }, { $set: { 'a.b': 222 } }, \"a simple scalar selector and simple set a wrong type\");\n  });\n\n  Tinytest.add(\"minimongo - can selector become true by modifier - $-scalar selectors and simple tests\", function (t) {\n    test = t;\n    T({ 'a.b.c': { $lt: 5 } }, { $set: { 'a.b': { c: 4 } } }, \"nested $lt\");\n    F({ 'a.b.c': { $lt: 5 } }, { $set: { 'a.b': { c: 5 } } }, \"nested $lt\");\n    F({ 'a.b.c': { $lt: 5 } }, { $set: { 'a.b': { c: 6 } } }, \"nested $lt\");\n    F({ 'a.b.c': { $lt: 5 } }, { $set: { 'a.b.d': 7 } }, \"nested $lt, the change doesn't matter\");\n    F({ 'a.b.c': { $lt: 5 } }, { $set: { 'a.b': { d: 7 } } }, \"nested $lt, the key disappears\");\n    T({ 'a.b.c': { $lt: 5 } }, { $set: { 'a.b': { d: 7, c: -1 } } }, \"nested $lt\");\n    F({ a: { $lt: 10, $gt: 3 } }, { $unset: { a: 1 } }, \"unset $lt\");\n    T({ a: { $lt: 10, $gt: 3 } }, { $set: { a: 4 } }, \"set between x and y\");\n    F({ a: { $lt: 10, $gt: 3 } }, { $set: { a: 3 } }, \"set between x and y\");\n    F({ a: { $lt: 10, $gt: 3 } }, { $set: { a: 10 } }, \"set between x and y\");\n    F({ a: { $gt: 10, $lt: 3 } }, { $set: { a: 9 } }, \"impossible statement\");\n    T({ a: { $lte: 10, $gte: 3 } }, { $set: { a: 3 } }, \"set between x and y\");\n    T({ a: { $lte: 10, $gte: 3 } }, { $set: { a: 10 } }, \"set between x and y\");\n    F({ a: { $lte: 10, $gte: 3 } }, { $set: { a: -10 } }, \"set between x and y\");\n    T({ a: { $lte: 10, $gte: 3, $gt: 3, $lt: 10 } }, { $set: { a: 4 } }, \"set between x and y\");\n    F({ a: { $lte: 10, $gte: 3, $gt: 3, $lt: 10 } }, { $set: { a: 3 } }, \"set between x and y\");\n    F({ a: { $lte: 10, $gte: 3, $gt: 3, $lt: 10 } }, { $set: { a: 10 } }, \"set between x and y\");\n    F({ a: { $lte: 10, $gte: 3, $gt: 3, $lt: 10 } }, { $set: { a: Infinity } }, \"set between x and y\");\n    T({ a: { $lte: 10, $gte: 3, $gt: 3, $lt: 10 }, x: 1 }, { $set: { x: 1 } }, \"set between x and y - dummy\");\n    F({ a: { $lte: 10, $gte: 13, $gt: 3, $lt: 9 }, x: 1 }, { $set: { x: 1 } }, \"set between x and y - dummy - impossible\");\n    F({ a: { $lte: 10 } }, { $set: { a: Infinity } }, \"Infinity <= 10?\");\n    T({ a: { $lte: 10 } }, { $set: { a: -Infinity } }, \"-Infinity <= 10?\");\n    // XXX is this sufficient?\n    T({ a: { $gt: 9.99999999999999, $lt: 10 }, x: 1 }, { $set: { x: 1 } }, \"very close $gt and $lt\");\n    // XXX this test should be F, but since it is so hard to be precise in\n    // floating point math, the current implementation falls back to T\n    T({ a: { $gt: 9.999999999999999, $lt: 10 }, x: 1 }, { $set: { x: 1 } }, \"very close $gt and $lt\");\n    T({ a: { $eq: 5 } }, { $set: { a: 5 } }, \"set of $eq\");\n    T({ a: { $eq: 5 }, b: { $eq: 7 } }, { $set: { a: 5 } }, \"set of $eq with other $eq\");\n    F({ a: { $eq: 5 } }, { $set: { a: 4 } }, \"set below of $eq\");\n    F({ a: { $eq: 5 } }, { $set: { a: 6 } }, \"set above of $eq\");\n    T({ a: { $ne: 5 } }, { $unset: { a: 1 } }, \"unset of $ne\");\n    T({ a: { $ne: 5 } }, { $set: { a: 1 } }, \"set of $ne\");\n    T({ a: { $ne: \"some string\" }, x: 1 }, { $set: { x: 1 } }, \"$ne dummy\");\n    T({ a: { $ne: true }, x: 1 }, { $set: { x: 1 } }, \"$ne dummy\");\n    T({ a: { $ne: false }, x: 1 }, { $set: { x: 1 } }, \"$ne dummy\");\n    T({ a: { $ne: null }, x: 1 }, { $set: { x: 1 } }, \"$ne dummy\");\n    T({ a: { $ne: Infinity }, x: 1 }, { $set: { x: 1 } }, \"$ne dummy\");\n    T({ a: { $ne: 5 } }, { $set: { a: -10 } }, \"set of $ne\");\n    T({ a: { $in: [1, 3, 5, 7] } }, { $set: { a: 5 } }, \"$in checks\");\n    F({ a: { $in: [1, 3, 5, 7] } }, { $set: { a: -5 } }, \"$in checks\");\n    T({ a: { $in: [1, 3, 5, 7], $gt: 6 }, x: 1 }, { $set: { x: 1 } }, \"$in combination with $gt\");\n    F({ a: { $lte: 10, $gte: 3 } }, { $set: { 'a.b': -10 } }, \"sel between x and y, set its subfield\");\n    F({ b: { $in: [1, 3, 5, 7] } }, { $set: { 'b.c': 2 } }, \"sel $in, set subfield\");\n    T({ b: { $in: [1, 3, 5, 7] } }, { $set: { 'bd.c': 2, b: 3 } }, \"sel $in, set similar subfield\");\n    F({ 'b.c': { $in: [1, 3, 5, 7] } }, { $set: { b: 2 } }, \"sel subfield of set scalar\");\n    // If modifier tries to set a sub-field of a path expected to be a scalar.\n    F({ 'a.b': { $gt: 5, $lt: 7}, x: 1 }, { $set: { 'a.b.c': 3, x: 1 } }, \"set sub-field of $gt,$lt operator (scalar expected)\");\n    F({ 'a.b': { $gt: 5, $lt: 7}, x: 1 }, { $set: { x: 1 }, $unset: { 'a.b.c': 1 } }, \"unset sub-field of $gt,$lt operator (scalar expected)\");\n  });\n\n  Tinytest.add(\"minimongo - can selector become true by modifier - $-nonscalar selectors and simple tests\", function (t) {\n    test = t;\n    T({ a: { $eq: { x: 5 } } }, { $set: { 'a.x': 5 } }, \"set of $eq\");\n    // XXX this test should be F, but it is not implemented yet\n    T({ a: { $eq: { x: 5 } } }, { $set: { 'a.x': 4 } }, \"set of $eq\");\n    // XXX this test should be F, but it is not implemented yet\n    T({ a: { $eq: { x: 5 } } }, { $set: { 'a.y': 4 } }, \"set of $eq\");\n    T({ a: { $ne: { x: 5 } } }, { $set: { 'a.x': 3 } }, \"set of $ne\");\n    // XXX this test should be F, but it is not implemented yet\n    T({ a: { $ne: { x: 5 } } }, { $set: { 'a.x': 5 } }, \"set of $ne\");\n    T({ a: { $in: [{ b: 1 }, { b: 3 }] } }, { $set: { a: { b: 3 } } }, \"$in checks\");\n    // XXX this test should be F, but it is not implemented yet\n    T({ a: { $in: [{ b: 1 }, { b: 3 }] } }, { $set: { a: { v: 3 } } }, \"$in checks\");\n    T({ a: { $ne: { a: 2 } }, x: 1 }, { $set: { x: 1 } }, \"$ne dummy\");\n    // XXX this test should be F, but it is not implemented yet\n    T({ a: { $ne: { a: 2 } } }, { $set: { a: { a: 2 } } }, \"$ne object\");\n  });\n})();\n"
  },
  {
    "path": "packages/minimongo/minimongo_tests.js",
    "content": "\n// Hack to make LocalCollection generate ObjectIDs by default.\nLocalCollection._useOID = true;\n\n// assert that f is a strcmp-style comparison function that puts\n// 'values' in the provided order\n\nvar assert_ordering = function (test, f, values) {\n  for (var i = 0; i < values.length; i++) {\n    var x = f(values[i], values[i]);\n    if (x !== 0) {\n      // XXX super janky\n      test.fail({type: \"minimongo-ordering\",\n                 message: \"value doesn't order as equal to itself\",\n                 value: JSON.stringify(values[i]),\n                 should_be_zero_but_got: JSON.stringify(x)});\n    }\n    if (i + 1 < values.length) {\n      var less = values[i];\n      var more = values[i + 1];\n      var x = f(less, more);\n      if (!(x < 0)) {\n        // XXX super janky\n        test.fail({type: \"minimongo-ordering\",\n                   message: \"ordering test failed\",\n                   first: JSON.stringify(less),\n                   second: JSON.stringify(more),\n                   should_be_negative_but_got: JSON.stringify(x)});\n      }\n      x = f(more, less);\n      if (!(x > 0)) {\n        // XXX super janky\n        test.fail({type: \"minimongo-ordering\",\n                   message: \"ordering test failed\",\n                   first: JSON.stringify(less),\n                   second: JSON.stringify(more),\n                   should_be_positive_but_got: JSON.stringify(x)});\n      }\n    }\n  }\n};\n\nvar log_callbacks = function (operations) {\n  return {\n    addedAt: function (obj, idx, before) {\n      delete obj._id;\n      operations.push(EJSON.clone(['added', obj, idx, before]));\n    },\n    changedAt: function (obj, old_obj, at) {\n      delete obj._id;\n      delete old_obj._id;\n      operations.push(EJSON.clone(['changed', obj, at, old_obj]));\n    },\n    movedTo: function (obj, old_at, new_at, before) {\n      delete obj._id;\n      operations.push(EJSON.clone(['moved', obj, old_at, new_at, before]));\n    },\n    removedAt: function (old_obj, at) {\n      var id = old_obj._id;\n      delete old_obj._id;\n      operations.push(EJSON.clone(['removed', id, at, old_obj]));\n    }\n  };\n};\n\n// XXX test shared structure in all MM entrypoints\nTinytest.add(\"minimongo - basics\", function (test) {\n  var c = new LocalCollection(),\n      fluffyKitten_id,\n      count;\n\n  fluffyKitten_id = c.insert({type: \"kitten\", name: \"fluffy\"});\n  c.insert({type: \"kitten\", name: \"snookums\"});\n  c.insert({type: \"cryptographer\", name: \"alice\"});\n  c.insert({type: \"cryptographer\", name: \"bob\"});\n  c.insert({type: \"cryptographer\", name: \"cara\"});\n  test.equal(c.find().count(), 5);\n  test.equal(c.find({type: \"kitten\"}).count(), 2);\n  test.equal(c.find({type: \"cryptographer\"}).count(), 3);\n  test.length(c.find({type: \"kitten\"}).fetch(), 2);\n  test.length(c.find({type: \"cryptographer\"}).fetch(), 3);\n  test.equal(fluffyKitten_id, c.findOne({type: \"kitten\", name: \"fluffy\"})._id);\n\n  c.remove({name: \"cara\"});\n  test.equal(c.find().count(), 4);\n  test.equal(c.find({type: \"kitten\"}).count(), 2);\n  test.equal(c.find({type: \"cryptographer\"}).count(), 2);\n  test.length(c.find({type: \"kitten\"}).fetch(), 2);\n  test.length(c.find({type: \"cryptographer\"}).fetch(), 2);\n\n  count = c.update({name: \"snookums\"}, {$set: {type: \"cryptographer\"}});\n  test.equal(count, 1);\n  test.equal(c.find().count(), 4);\n  test.equal(c.find({type: \"kitten\"}).count(), 1);\n  test.equal(c.find({type: \"cryptographer\"}).count(), 3);\n  test.length(c.find({type: \"kitten\"}).fetch(), 1);\n  test.length(c.find({type: \"cryptographer\"}).fetch(), 3);\n\n  c.remove(null);\n  c.remove(false);\n  c.remove(undefined);\n  test.equal(c.find().count(), 4);\n\n  c.remove({_id: null});\n  c.remove({_id: false});\n  c.remove({_id: undefined});\n  count = c.remove();\n  test.equal(count, 0);\n  test.equal(c.find().count(), 4);\n\n  count = c.remove({});\n  test.equal(count, 4);\n  test.equal(c.find().count(), 0);\n\n  c.insert({_id: 1, name: \"strawberry\", tags: [\"fruit\", \"red\", \"squishy\"]});\n  c.insert({_id: 2, name: \"apple\", tags: [\"fruit\", \"red\", \"hard\"]});\n  c.insert({_id: 3, name: \"rose\", tags: [\"flower\", \"red\", \"squishy\"]});\n\n  test.equal(c.find({tags: \"flower\"}).count(), 1);\n  test.equal(c.find({tags: \"fruit\"}).count(), 2);\n  test.equal(c.find({tags: \"red\"}).count(), 3);\n  test.length(c.find({tags: \"flower\"}).fetch(), 1);\n  test.length(c.find({tags: \"fruit\"}).fetch(), 2);\n  test.length(c.find({tags: \"red\"}).fetch(), 3);\n\n  test.equal(c.findOne(1).name, \"strawberry\");\n  test.equal(c.findOne(2).name, \"apple\");\n  test.equal(c.findOne(3).name, \"rose\");\n  test.equal(c.findOne(4), undefined);\n  test.equal(c.findOne(\"abc\"), undefined);\n  test.equal(c.findOne(undefined), undefined);\n\n  test.equal(c.find(1).count(), 1);\n  test.equal(c.find(4).count(), 0);\n  test.equal(c.find(\"abc\").count(), 0);\n  test.equal(c.find(undefined).count(), 0);\n  test.equal(c.find().count(), 3);\n  test.equal(c.find(1, {skip: 1}).count(), 0);\n  test.equal(c.find({_id: 1}, {skip: 1}).count(), 0);\n  test.equal(c.find({}, {skip: 1}).count(), 2);\n  test.equal(c.find({}, {skip: 2}).count(), 1);\n  test.equal(c.find({}, {limit: 2}).count(), 2);\n  test.equal(c.find({}, {limit: 1}).count(), 1);\n  test.equal(c.find({}, {skip: 1, limit: 1}).count(), 1);\n  test.equal(c.find({tags: \"fruit\"}, {skip: 1}).count(), 1);\n  test.equal(c.find({tags: \"fruit\"}, {limit: 1}).count(), 1);\n  test.equal(c.find({tags: \"fruit\"}, {skip: 1, limit: 1}).count(), 1);\n  test.equal(c.find(1, {sort: ['_id','desc'], skip: 1}).count(), 0);\n  test.equal(c.find({_id: 1}, {sort: ['_id','desc'], skip: 1}).count(), 0);\n  test.equal(c.find({}, {sort: ['_id','desc'], skip: 1}).count(), 2);\n  test.equal(c.find({}, {sort: ['_id','desc'], skip: 2}).count(), 1);\n  test.equal(c.find({}, {sort: ['_id','desc'], limit: 2}).count(), 2);\n  test.equal(c.find({}, {sort: ['_id','desc'], limit: 1}).count(), 1);\n  test.equal(c.find({}, {sort: ['_id','desc'], skip: 1, limit: 1}).count(), 1);\n  test.equal(c.find({tags: \"fruit\"}, {sort: ['_id','desc'], skip: 1}).count(), 1);\n  test.equal(c.find({tags: \"fruit\"}, {sort: ['_id','desc'], limit: 1}).count(), 1);\n  test.equal(c.find({tags: \"fruit\"}, {sort: ['_id','desc'], skip: 1, limit: 1}).count(), 1);\n\n  // Regression test for #455.\n  c.insert({foo: {bar: 'baz'}});\n  test.equal(c.find({foo: {bam: 'baz'}}).count(), 0);\n  test.equal(c.find({foo: {bar: 'baz'}}).count(), 1);\n\n});\n\nTinytest.add(\"minimongo - cursors\", function (test) {\n  var c = new LocalCollection();\n  var res;\n\n  for (var i = 0; i < 20; i++)\n    c.insert({i: i});\n\n  var q = c.find();\n  test.equal(q.count(), 20);\n\n  // fetch\n  res = q.fetch();\n  test.length(res, 20);\n  for (var i = 0; i < 20; i++) {\n    test.equal(res[i].i, i);\n  }\n  // call it again, it still works\n  test.length(q.fetch(), 20);\n\n  // forEach\n  var count = 0;\n  var context = {};\n  q.forEach(function (obj, i, cursor) {\n    test.equal(obj.i, count++);\n    test.equal(obj.i, i);\n    test.isTrue(context === this);\n    test.isTrue(cursor === q);\n  }, context);\n  test.equal(count, 20);\n  // call it again, it still works\n  test.length(q.fetch(), 20);\n\n  // map\n  res = q.map(function (obj, i, cursor) {\n    test.equal(obj.i, i);\n    test.isTrue(context === this);\n    test.isTrue(cursor === q);\n    return obj.i * 2;\n  }, context);\n  test.length(res, 20);\n  for (var i = 0; i < 20; i++)\n    test.equal(res[i], i * 2);\n  // call it again, it still works\n  test.length(q.fetch(), 20);\n\n  // findOne (and no rewind first)\n  test.equal(c.findOne({i: 0}).i, 0);\n  test.equal(c.findOne({i: 1}).i, 1);\n  var id = c.findOne({i: 2})._id;\n  test.equal(c.findOne(id).i, 2);\n});\n\nTinytest.add(\"minimongo - transform\", function (test) {\n  var c = new LocalCollection;\n  c.insert({});\n  // transform functions must return objects\n  var invalidTransform = function (doc) { return doc._id; };\n  test.throws(function () {\n    c.findOne({}, {transform: invalidTransform});\n  });\n\n  // transformed documents get _id field transplanted if not present\n  var transformWithoutId = function (doc) { return _.omit(doc, '_id'); };\n  test.equal(c.findOne({}, {transform: transformWithoutId})._id,\n             c.findOne()._id);\n});\n\nTinytest.add(\"minimongo - misc\", function (test) {\n  // deepcopy\n  var a = {a: [1, 2, 3], b: \"x\", c: true, d: {x: 12, y: [12]},\n           f: null, g: new Date()};\n  var b = EJSON.clone(a);\n  test.equal(a, b);\n  test.isTrue(LocalCollection._f._equal(a, b));\n  a.a.push(4);\n  test.length(b.a, 3);\n  a.c = false;\n  test.isTrue(b.c);\n  b.d.z = 15;\n  a.d.z = 14;\n  test.equal(b.d.z, 15);\n  a.d.y.push(88);\n  test.length(b.d.y, 1);\n  test.equal(a.g, b.g);\n  b.g.setDate(b.g.getDate() + 1);\n  test.notEqual(a.g, b.g);\n\n  a = {x: function () {}};\n  b = EJSON.clone(a);\n  a.x.a = 14;\n  test.equal(b.x.a, 14); // just to document current behavior\n});\n\nTinytest.add(\"minimongo - lookup\", function (test) {\n  var lookupA = MinimongoTest.makeLookupFunction('a');\n  test.equal(lookupA({}), [{value: undefined}]);\n  test.equal(lookupA({a: 1}), [{value: 1}]);\n  test.equal(lookupA({a: [1]}), [{value: [1]}]);\n\n  var lookupAX = MinimongoTest.makeLookupFunction('a.x');\n  test.equal(lookupAX({a: {x: 1}}), [{value: 1}]);\n  test.equal(lookupAX({a: {x: [1]}}), [{value: [1]}]);\n  test.equal(lookupAX({a: 5}), [{value: undefined}]);\n  test.equal(lookupAX({a: [{x: 1}, {x: [2]}, {y: 3}]}),\n             [{value: 1, arrayIndices: [0]},\n              {value: [2], arrayIndices: [1]},\n              {value: undefined, arrayIndices: [2]}]);\n\n  var lookupA0X = MinimongoTest.makeLookupFunction('a.0.x');\n  test.equal(lookupA0X({a: [{x: 1}]}), [\n    // From interpreting '0' as \"0th array element\".\n    {value: 1, arrayIndices: [0, 'x']},\n    // From interpreting '0' as \"after branching in the array, look in the\n    // object {x:1} for a field named 0\".\n    {value: undefined, arrayIndices: [0]}]);\n  test.equal(lookupA0X({a: [{x: [1]}]}), [\n    {value: [1], arrayIndices: [0, 'x']},\n    {value: undefined, arrayIndices: [0]}]);\n  test.equal(lookupA0X({a: 5}), [{value: undefined}]);\n  test.equal(lookupA0X({a: [{x: 1}, {x: [2]}, {y: 3}]}), [\n    // From interpreting '0' as \"0th array element\".\n    {value: 1, arrayIndices: [0, 'x']},\n    // From interpreting '0' as \"after branching in the array, look in the\n    // object {x:1} for a field named 0\".\n    {value: undefined, arrayIndices: [0]},\n    {value: undefined, arrayIndices: [1]},\n    {value: undefined, arrayIndices: [2]}\n  ]);\n\n  test.equal(\n    MinimongoTest.makeLookupFunction('w.x.0.z')({\n      w: [{x: [{z: 5}]}]}), [\n        // From interpreting '0' as \"0th array element\".\n        {value: 5, arrayIndices: [0, 0, 'x']},\n        // From interpreting '0' as \"after branching in the array, look in the\n        // object {z:5} for a field named \"0\".\n        {value: undefined, arrayIndices: [0, 0]}\n      ]);\n});\n\nTinytest.add(\"minimongo - selector_compiler\", function (test) {\n  var matches = function (shouldMatch, selector, doc) {\n    var doesMatch = new Minimongo.Matcher(selector).documentMatches(doc).result;\n    if (doesMatch != shouldMatch) {\n      // XXX super janky\n      test.fail({message: \"minimongo match failure: document \" +\n                 (shouldMatch ? \"should match, but doesn't\" :\n                  \"shouldn't match, but does\"),\n                 selector: JSON.stringify(selector),\n                 document: JSON.stringify(doc)\n                });\n    }\n  };\n\n  var match = _.bind(matches, null, true);\n  var nomatch = _.bind(matches, null, false);\n\n  // XXX blog post about what I learned while writing these tests (weird\n  // mongo edge cases)\n\n  // empty selectors\n  match({}, {});\n  match({}, {a: 12});\n\n  // scalars\n  match(1, {_id: 1, a: 'foo'});\n  nomatch(1, {_id: 2, a: 'foo'});\n  match('a', {_id: 'a', a: 'foo'});\n  nomatch('a', {_id: 'b', a: 'foo'});\n\n  // safety\n  nomatch(undefined, {});\n  nomatch(undefined, {_id: 'foo'});\n  nomatch(false, {_id: 'foo'});\n  nomatch(null, {_id: 'foo'});\n  nomatch({_id: undefined}, {_id: 'foo'});\n  nomatch({_id: false}, {_id: 'foo'});\n  nomatch({_id: null}, {_id: 'foo'});\n\n  // matching one or more keys\n  nomatch({a: 12}, {});\n  match({a: 12}, {a: 12});\n  match({a: 12}, {a: 12, b: 13});\n  match({a: 12, b: 13}, {a: 12, b: 13});\n  match({a: 12, b: 13}, {a: 12, b: 13, c: 14});\n  nomatch({a: 12, b: 13, c: 14}, {a: 12, b: 13});\n  nomatch({a: 12, b: 13}, {b: 13, c: 14});\n\n  match({a: 12}, {a: [12]});\n  match({a: 12}, {a: [11, 12, 13]});\n  nomatch({a: 12}, {a: [11, 13]});\n  match({a: 12, b: 13}, {a: [11, 12, 13], b: [13, 14, 15]});\n  nomatch({a: 12, b: 13}, {a: [11, 12, 13], b: [14, 15]});\n\n  // dates\n  var date1 = new Date;\n  var date2 = new Date(date1.getTime() + 1000);\n  match({a: date1}, {a: date1});\n  nomatch({a: date1}, {a: date2});\n\n\n  // arrays\n  match({a: [1,2]}, {a: [1, 2]});\n  match({a: [1,2]}, {a: [[1, 2]]});\n  match({a: [1,2]}, {a: [[3, 4], [1, 2]]});\n  nomatch({a: [1,2]}, {a: [3, 4]});\n  nomatch({a: [1,2]}, {a: [[[1, 2]]]});\n\n  // literal documents\n  match({a: {b: 12}}, {a: {b: 12}});\n  nomatch({a: {b: 12, c: 13}}, {a: {b: 12}});\n  nomatch({a: {b: 12}}, {a: {b: 12, c: 13}});\n  match({a: {b: 12, c: 13}}, {a: {b: 12, c: 13}});\n  nomatch({a: {b: 12, c: 13}}, {a: {c: 13, b: 12}}); // tested on mongodb\n  nomatch({a: {}}, {a: {b: 12}});\n  nomatch({a: {b:12}}, {a: {}});\n  match(\n    {a: {b: 12, c: [13, true, false, 2.2, \"a\", null, {d: 14}]}},\n    {a: {b: 12, c: [13, true, false, 2.2, \"a\", null, {d: 14}]}});\n  match({a: {b: 12}}, {a: {b: 12}, k: 99});\n\n  match({a: {b: 12}}, {a: [{b: 12}]});\n  nomatch({a: {b: 12}}, {a: [[{b: 12}]]});\n  match({a: {b: 12}}, {a: [{b: 11}, {b: 12}, {b: 13}]});\n  nomatch({a: {b: 12}}, {a: [{b: 11}, {b: 12, c: 20}, {b: 13}]});\n  nomatch({a: {b: 12, c: 20}}, {a: [{b: 11}, {b: 12}, {c: 20}]});\n  match({a: {b: 12, c: 20}}, {a: [{b: 11}, {b: 12, c: 20}, {b: 13}]});\n\n  // null\n  match({a: null}, {a: null});\n  match({a: null}, {b: 12});\n  nomatch({a: null}, {a: 12});\n  match({a: null}, {a: [1, 2, null, 3]}); // tested on mongodb\n  nomatch({a: null}, {a: [1, 2, {}, 3]}); // tested on mongodb\n\n  // order comparisons: $lt, $gt, $lte, $gte\n  match({a: {$lt: 10}}, {a: 9});\n  nomatch({a: {$lt: 10}}, {a: 10});\n  nomatch({a: {$lt: 10}}, {a: 11});\n\n  match({a: {$gt: 10}}, {a: 11});\n  nomatch({a: {$gt: 10}}, {a: 10});\n  nomatch({a: {$gt: 10}}, {a: 9});\n\n  match({a: {$lte: 10}}, {a: 9});\n  match({a: {$lte: 10}}, {a: 10});\n  nomatch({a: {$lte: 10}}, {a: 11});\n\n  match({a: {$gte: 10}}, {a: 11});\n  match({a: {$gte: 10}}, {a: 10});\n  nomatch({a: {$gte: 10}}, {a: 9});\n\n  match({a: {$lt: 10}}, {a: [11, 9, 12]});\n  nomatch({a: {$lt: 10}}, {a: [11, 12]});\n\n  // (there's a full suite of ordering test elsewhere)\n  nomatch({a: {$lt: \"null\"}}, {a: null});\n  match({a: {$lt: {x: [2, 3, 4]}}}, {a: {x: [1, 3, 4]}});\n  match({a: {$gt: {x: [2, 3, 4]}}}, {a: {x: [3, 3, 4]}});\n  nomatch({a: {$gt: {x: [2, 3, 4]}}}, {a: {x: [1, 3, 4]}});\n  nomatch({a: {$gt: {x: [2, 3, 4]}}}, {a: {x: [2, 3, 4]}});\n  nomatch({a: {$lt: {x: [2, 3, 4]}}}, {a: {x: [2, 3, 4]}});\n  match({a: {$gte: {x: [2, 3, 4]}}}, {a: {x: [2, 3, 4]}});\n  match({a: {$lte: {x: [2, 3, 4]}}}, {a: {x: [2, 3, 4]}});\n\n  nomatch({a: {$gt: [2, 3]}}, {a: [1, 2]}); // tested against mongodb\n\n  // composition of two qualifiers\n  nomatch({a: {$lt: 11, $gt: 9}}, {a: 8});\n  nomatch({a: {$lt: 11, $gt: 9}}, {a: 9});\n  match({a: {$lt: 11, $gt: 9}}, {a: 10});\n  nomatch({a: {$lt: 11, $gt: 9}}, {a: 11});\n  nomatch({a: {$lt: 11, $gt: 9}}, {a: 12});\n\n  match({a: {$lt: 11, $gt: 9}}, {a: [8, 9, 10, 11, 12]});\n  match({a: {$lt: 11, $gt: 9}}, {a: [8, 9, 11, 12]}); // tested against mongodb\n\n  // $all\n  match({a: {$all: [1, 2]}}, {a: [1, 2]});\n  nomatch({a: {$all: [1, 2, 3]}}, {a: [1, 2]});\n  match({a: {$all: [1, 2]}}, {a: [3, 2, 1]});\n  match({a: {$all: [1, \"x\"]}}, {a: [3, \"x\", 1]});\n  nomatch({a: {$all: ['2']}}, {a: 2});\n  nomatch({a: {$all: [2]}}, {a: '2'});\n  match({a: {$all: [[1, 2], [1, 3]]}}, {a: [[1, 3], [1, 2], [1, 4]]});\n  nomatch({a: {$all: [[1, 2], [1, 3]]}}, {a: [[1, 4], [1, 2], [1, 4]]});\n  match({a: {$all: [2, 2]}}, {a: [2]}); // tested against mongodb\n  nomatch({a: {$all: [2, 3]}}, {a: [2, 2]});\n\n  nomatch({a: {$all: [1, 2]}}, {a: [[1, 2]]}); // tested against mongodb\n  nomatch({a: {$all: [1, 2]}}, {}); // tested against mongodb, field doesn't exist\n  nomatch({a: {$all: [1, 2]}}, {a: {foo: 'bar'}}); // tested against mongodb, field is not an object\n  nomatch({a: {$all: []}}, {a: []});\n  nomatch({a: {$all: []}}, {a: [5]});\n  match({a: {$all: [/i/, /e/i]}}, {a: [\"foo\", \"bEr\", \"biz\"]});\n  nomatch({a: {$all: [/i/, /e/i]}}, {a: [\"foo\", \"bar\", \"biz\"]});\n  match({a: {$all: [{b: 3}]}}, {a: [{b: 3}]});\n  // Members of $all other than regexps are *equality matches*, not document\n  // matches.\n  nomatch({a: {$all: [{b: 3}]}}, {a: [{b: 3, k: 4}]});\n  test.throws(function () {\n    match({a: {$all: [{$gt: 4}]}}, {});\n  });\n\n  // $exists\n  match({a: {$exists: true}}, {a: 12});\n  nomatch({a: {$exists: true}}, {b: 12});\n  nomatch({a: {$exists: false}}, {a: 12});\n  match({a: {$exists: false}}, {b: 12});\n\n  match({a: {$exists: true}}, {a: []});\n  nomatch({a: {$exists: true}}, {b: []});\n  nomatch({a: {$exists: false}}, {a: []});\n  match({a: {$exists: false}}, {b: []});\n\n  match({a: {$exists: true}}, {a: [1]});\n  nomatch({a: {$exists: true}}, {b: [1]});\n  nomatch({a: {$exists: false}}, {a: [1]});\n  match({a: {$exists: false}}, {b: [1]});\n\n  match({a: {$exists: 1}}, {a: 5});\n  match({a: {$exists: 0}}, {b: 5});\n\n  nomatch({'a.x':{$exists: false}}, {a: [{}, {x: 5}]});\n  match({'a.x':{$exists: true}}, {a: [{}, {x: 5}]});\n  match({'a.x':{$exists: true}}, {a: [{}, {x: 5}]});\n  match({'a.x':{$exists: true}}, {a: {x: []}});\n  match({'a.x':{$exists: true}}, {a: {x: null}});\n\n  // $mod\n  match({a: {$mod: [10, 1]}}, {a: 11});\n  nomatch({a: {$mod: [10, 1]}}, {a: 12});\n  match({a: {$mod: [10, 1]}}, {a: [10, 11, 12]});\n  nomatch({a: {$mod: [10, 1]}}, {a: [10, 12]});\n  _.each([\n    5,\n    [10],\n    [10, 1, 2],\n    \"foo\",\n    {bar: 1},\n    []\n  ], function (badMod) {\n    test.throws(function () {\n      match({a: {$mod: badMod}}, {a: 11});\n    });\n  });\n\n  // $eq\n  nomatch({a: {$eq: 1}}, {a: 2});\n  match({a: {$eq: 2}}, {a: 2});\n  nomatch({a: {$eq: [1]}}, {a: [2]});\n\n  match({a: {$eq: [1, 2]}}, {a: [1, 2]});\n  match({a: {$eq: 1}}, {a: [1, 2]});\n  match({a: {$eq: 2}}, {a: [1, 2]});\n  nomatch({a: {$eq: 3}}, {a: [1, 2]});\n  match({'a.b': {$eq: 1}}, {a: [{b: 1}, {b: 2}]});\n  match({'a.b': {$eq: 2}}, {a: [{b: 1}, {b: 2}]});\n  nomatch({'a.b': {$eq: 3}}, {a: [{b: 1}, {b: 2}]});\n\n  match({a: {$eq: {x: 1}}}, {a: {x: 1}});\n  nomatch({a: {$eq: {x: 1}}}, {a: {x: 2}});\n  nomatch({a: {$eq: {x: 1}}}, {a: {x: 1, y: 2}});\n\n  // $ne\n  match({a: {$ne: 1}}, {a: 2});\n  nomatch({a: {$ne: 2}}, {a: 2});\n  match({a: {$ne: [1]}}, {a: [2]});\n\n  nomatch({a: {$ne: [1, 2]}}, {a: [1, 2]}); // all tested against mongodb\n  nomatch({a: {$ne: 1}}, {a: [1, 2]});\n  nomatch({a: {$ne: 2}}, {a: [1, 2]});\n  match({a: {$ne: 3}}, {a: [1, 2]});\n  nomatch({'a.b': {$ne: 1}}, {a: [{b: 1}, {b: 2}]});\n  nomatch({'a.b': {$ne: 2}}, {a: [{b: 1}, {b: 2}]});\n  match({'a.b': {$ne: 3}}, {a: [{b: 1}, {b: 2}]});\n\n  nomatch({a: {$ne: {x: 1}}}, {a: {x: 1}});\n  match({a: {$ne: {x: 1}}}, {a: {x: 2}});\n  match({a: {$ne: {x: 1}}}, {a: {x: 1, y: 2}});\n\n  // This query means: All 'a.b' must be non-5, and some 'a.b' must be >6.\n  match({'a.b': {$ne: 5, $gt: 6}}, {a: [{b: 2}, {b: 10}]});\n  nomatch({'a.b': {$ne: 5, $gt: 6}}, {a: [{b: 2}, {b: 4}]});\n  nomatch({'a.b': {$ne: 5, $gt: 6}}, {a: [{b: 2}, {b: 5}]});\n  nomatch({'a.b': {$ne: 5, $gt: 6}}, {a: [{b: 10}, {b: 5}]});\n  // Should work the same if the branch is at the bottom.\n  match({a: {$ne: 5, $gt: 6}}, {a: [2, 10]});\n  nomatch({a: {$ne: 5, $gt: 6}}, {a: [2, 4]});\n  nomatch({a: {$ne: 5, $gt: 6}}, {a: [2, 5]});\n  nomatch({a: {$ne: 5, $gt: 6}}, {a: [10, 5]});\n\n  // $in\n  match({a: {$in: [1, 2, 3]}}, {a: 2});\n  nomatch({a: {$in: [1, 2, 3]}}, {a: 4});\n  match({a: {$in: [[1], [2], [3]]}}, {a: [2]});\n  nomatch({a: {$in: [[1], [2], [3]]}}, {a: [4]});\n  match({a: {$in: [{b: 1}, {b: 2}, {b: 3}]}}, {a: {b: 2}});\n  nomatch({a: {$in: [{b: 1}, {b: 2}, {b: 3}]}}, {a: {b: 4}});\n\n  match({a: {$in: [1, 2, 3]}}, {a: [2]}); // tested against mongodb\n  match({a: {$in: [{x: 1}, {x: 2}, {x: 3}]}}, {a: [{x: 2}]});\n  match({a: {$in: [1, 2, 3]}}, {a: [4, 2]});\n  nomatch({a: {$in: [1, 2, 3]}}, {a: [4]});\n\n  match({a: {$in: ['x', /foo/i]}}, {a: 'x'});\n  match({a: {$in: ['x', /foo/i]}}, {a: 'fOo'});\n  match({a: {$in: ['x', /foo/i]}}, {a: ['f', 'fOo']});\n  nomatch({a: {$in: ['x', /foo/i]}}, {a: ['f', 'fOx']});\n\n  match({a: {$in: [1, null]}}, {});\n  match({'a.b': {$in: [1, null]}}, {});\n  match({'a.b': {$in: [1, null]}}, {a: {}});\n  match({'a.b': {$in: [1, null]}}, {a: {b: null}});\n  nomatch({'a.b': {$in: [1, null]}}, {a: {b: 5}});\n  nomatch({'a.b': {$in: [1]}}, {a: {b: null}});\n  nomatch({'a.b': {$in: [1]}}, {a: {}});\n  nomatch({'a.b': {$in: [1, null]}}, {a: [{b: 5}]});\n  match({'a.b': {$in: [1, null]}}, {a: [{b: 5}, {}]});\n  nomatch({'a.b': {$in: [1, null]}}, {a: [{b: 5}, []]});\n  nomatch({'a.b': {$in: [1, null]}}, {a: [{b: 5}, 5]});\n\n  // $nin\n  nomatch({a: {$nin: [1, 2, 3]}}, {a: 2});\n  match({a: {$nin: [1, 2, 3]}}, {a: 4});\n  nomatch({a: {$nin: [[1], [2], [3]]}}, {a: [2]});\n  match({a: {$nin: [[1], [2], [3]]}}, {a: [4]});\n  nomatch({a: {$nin: [{b: 1}, {b: 2}, {b: 3}]}}, {a: {b: 2}});\n  match({a: {$nin: [{b: 1}, {b: 2}, {b: 3}]}}, {a: {b: 4}});\n\n  nomatch({a: {$nin: [1, 2, 3]}}, {a: [2]}); // tested against mongodb\n  nomatch({a: {$nin: [{x: 1}, {x: 2}, {x: 3}]}}, {a: [{x: 2}]});\n  nomatch({a: {$nin: [1, 2, 3]}}, {a: [4, 2]});\n  nomatch({'a.b': {$nin: [1, 2, 3]}}, {a: [{b:4}, {b:2}]});\n  match({a: {$nin: [1, 2, 3]}}, {a: [4]});\n  match({'a.b': {$nin: [1, 2, 3]}}, {a: [{b:4}]});\n\n  nomatch({a: {$nin: ['x', /foo/i]}}, {a: 'x'});\n  nomatch({a: {$nin: ['x', /foo/i]}}, {a: 'fOo'});\n  nomatch({a: {$nin: ['x', /foo/i]}}, {a: ['f', 'fOo']});\n  match({a: {$nin: ['x', /foo/i]}}, {a: ['f', 'fOx']});\n\n  nomatch({a: {$nin: [1, null]}}, {});\n  nomatch({'a.b': {$nin: [1, null]}}, {});\n  nomatch({'a.b': {$nin: [1, null]}}, {a: {}});\n  nomatch({'a.b': {$nin: [1, null]}}, {a: {b: null}});\n  match({'a.b': {$nin: [1, null]}}, {a: {b: 5}});\n  match({'a.b': {$nin: [1]}}, {a: {b: null}});\n  match({'a.b': {$nin: [1]}}, {a: {}});\n  match({'a.b': {$nin: [1, null]}}, {a: [{b: 5}]});\n  nomatch({'a.b': {$nin: [1, null]}}, {a: [{b: 5}, {}]});\n  match({'a.b': {$nin: [1, null]}}, {a: [{b: 5}, []]});\n  match({'a.b': {$nin: [1, null]}}, {a: [{b: 5}, 5]});\n\n  // $size\n  match({a: {$size: 0}}, {a: []});\n  match({a: {$size: 1}}, {a: [2]});\n  match({a: {$size: 2}}, {a: [2, 2]});\n  nomatch({a: {$size: 0}}, {a: [2]});\n  nomatch({a: {$size: 1}}, {a: []});\n  nomatch({a: {$size: 1}}, {a: [2, 2]});\n  nomatch({a: {$size: 0}}, {a: \"2\"});\n  nomatch({a: {$size: 1}}, {a: \"2\"});\n  nomatch({a: {$size: 2}}, {a: \"2\"});\n\n  nomatch({a: {$size: 2}}, {a: [[2,2]]}); // tested against mongodb\n\n  // $type\n  match({a: {$type: 1}}, {a: 1.1});\n  match({a: {$type: 1}}, {a: 1});\n  nomatch({a: {$type: 1}}, {a: \"1\"});\n  match({a: {$type: 2}}, {a: \"1\"});\n  nomatch({a: {$type: 2}}, {a: 1});\n  match({a: {$type: 3}}, {a: {}});\n  match({a: {$type: 3}}, {a: {b: 2}});\n  nomatch({a: {$type: 3}}, {a: []});\n  nomatch({a: {$type: 3}}, {a: [1]});\n  nomatch({a: {$type: 3}}, {a: null});\n  match({a: {$type: 5}}, {a: EJSON.newBinary(0)});\n  match({a: {$type: 5}}, {a: EJSON.newBinary(4)});\n  nomatch({a: {$type: 5}}, {a: []});\n  nomatch({a: {$type: 5}}, {a: [42]});\n  match({a: {$type: 7}}, {a: new MongoID.ObjectID()});\n  nomatch({a: {$type: 7}}, {a: \"1234567890abcd1234567890\"});\n  match({a: {$type: 8}}, {a: true});\n  match({a: {$type: 8}}, {a: false});\n  nomatch({a: {$type: 8}}, {a: \"true\"});\n  nomatch({a: {$type: 8}}, {a: 0});\n  nomatch({a: {$type: 8}}, {a: null});\n  nomatch({a: {$type: 8}}, {a: ''});\n  nomatch({a: {$type: 8}}, {});\n  match({a: {$type: 9}}, {a: (new Date)});\n  nomatch({a: {$type: 9}}, {a: +(new Date)});\n  match({a: {$type: 10}}, {a: null});\n  nomatch({a: {$type: 10}}, {a: false});\n  nomatch({a: {$type: 10}}, {a: ''});\n  nomatch({a: {$type: 10}}, {a: 0});\n  nomatch({a: {$type: 10}}, {});\n  match({a: {$type: 11}}, {a: /x/});\n  nomatch({a: {$type: 11}}, {a: 'x'});\n  nomatch({a: {$type: 11}}, {});\n\n  // The normal rule for {$type:4} (4 means array) is that it NOT good enough to\n  // just have an array that's the leaf that matches the path.  (An array inside\n  // that array is good, though.)\n  nomatch({a: {$type: 4}}, {a: []});\n  nomatch({a: {$type: 4}}, {a: [1]}); // tested against mongodb\n  match({a: {$type: 1}}, {a: [1]});\n  nomatch({a: {$type: 2}}, {a: [1]});\n  match({a: {$type: 1}}, {a: [\"1\", 1]});\n  match({a: {$type: 2}}, {a: [\"1\", 1]});\n  nomatch({a: {$type: 3}}, {a: [\"1\", 1]});\n  nomatch({a: {$type: 4}}, {a: [\"1\", 1]});\n  nomatch({a: {$type: 1}}, {a: [\"1\", []]});\n  match({a: {$type: 2}}, {a: [\"1\", []]});\n  match({a: {$type: 4}}, {a: [\"1\", []]}); // tested against mongodb\n  // An exception to the normal rule is that an array found via numeric index is\n  // examined itself, and its elements are not.\n  match({'a.0': {$type: 4}}, {a: [[0]]});\n  nomatch({'a.0': {$type: 1}}, {a: [[0]]});\n\n  // regular expressions\n  match({a: /a/}, {a: 'cat'});\n  nomatch({a: /a/}, {a: 'cut'});\n  nomatch({a: /a/}, {a: 'CAT'});\n  match({a: /a/i}, {a: 'CAT'});\n  match({a: /a/}, {a: ['foo', 'bar']});  // search within array...\n  nomatch({a: /,/}, {a: ['foo', 'bar']});  // but not by stringifying\n  match({a: {$regex: 'a'}}, {a: ['foo', 'bar']});\n  nomatch({a: {$regex: ','}}, {a: ['foo', 'bar']});\n  match({a: {$regex: /a/}}, {a: 'cat'});\n  nomatch({a: {$regex: /a/}}, {a: 'cut'});\n  nomatch({a: {$regex: /a/}}, {a: 'CAT'});\n  match({a: {$regex: /a/i}}, {a: 'CAT'});\n  match({a: {$regex: /a/, $options: 'i'}}, {a: 'CAT'}); // tested\n  match({a: {$regex: /a/i, $options: 'i'}}, {a: 'CAT'}); // tested\n  nomatch({a: {$regex: /a/i, $options: ''}}, {a: 'CAT'}); // tested\n  match({a: {$regex: 'a'}}, {a: 'cat'});\n  nomatch({a: {$regex: 'a'}}, {a: 'cut'});\n  nomatch({a: {$regex: 'a'}}, {a: 'CAT'});\n  match({a: {$regex: 'a', $options: 'i'}}, {a: 'CAT'});\n  match({a: {$regex: '', $options: 'i'}}, {a: 'foo'});\n  nomatch({a: {$regex: '', $options: 'i'}}, {});\n  nomatch({a: {$regex: '', $options: 'i'}}, {a: 5});\n  nomatch({a: /undefined/}, {});\n  nomatch({a: {$regex: 'undefined'}}, {});\n  nomatch({a: /xxx/}, {});\n  nomatch({a: {$regex: 'xxx'}}, {});\n\n  // GitHub issue #2817:\n  // Regexps with a global flag ('g') keep a state when tested against the same\n  // string. Selector shouldn't return different result for similar documents\n  // because of this state.\n  var reusedRegexp = /sh/ig;\n  match({a: reusedRegexp}, {a: 'Shorts'});\n  match({a: reusedRegexp}, {a: 'Shorts'});\n  match({a: reusedRegexp}, {a: 'Shorts'});\n\n  match({a: {$regex: reusedRegexp}}, {a: 'Shorts'});\n  match({a: {$regex: reusedRegexp}}, {a: 'Shorts'});\n  match({a: {$regex: reusedRegexp}}, {a: 'Shorts'});\n\n  test.throws(function () {\n    match({a: {$options: 'i'}}, {a: 12});\n  });\n\n  match({a: /a/}, {a: ['dog', 'cat']});\n  nomatch({a: /a/}, {a: ['dog', 'puppy']});\n\n  // we don't support regexps in minimongo very well (eg, there's no EJSON\n  // encoding so it won't go over the wire), but run these tests anyway\n  match({a: /a/}, {a: /a/});\n  match({a: /a/}, {a: ['x', /a/]});\n  nomatch({a: /a/}, {a: /a/i});\n  nomatch({a: /a/m}, {a: /a/});\n  nomatch({a: /a/}, {a: /b/});\n  nomatch({a: /5/}, {a: 5});\n  nomatch({a: /t/}, {a: true});\n  match({a: /m/i}, {a: ['x', 'xM']});\n\n  test.throws(function () {\n    match({a: {$regex: /a/, $options: 'x'}}, {a: 'cat'});\n  });\n  test.throws(function () {\n    match({a: {$regex: /a/, $options: 's'}}, {a: 'cat'});\n  });\n\n  // $not\n  match({x: {$not: {$gt: 7}}}, {x: 6});\n  nomatch({x: {$not: {$gt: 7}}}, {x: 8});\n  match({x: {$not: {$lt: 10, $gt: 7}}}, {x: 11});\n  nomatch({x: {$not: {$lt: 10, $gt: 7}}}, {x: 9});\n  match({x: {$not: {$lt: 10, $gt: 7}}}, {x: 6});\n\n  match({x: {$not: {$gt: 7}}}, {x: [2, 3, 4]});\n  match({'x.y': {$not: {$gt: 7}}}, {x: [{y:2}, {y:3}, {y:4}]});\n  nomatch({x: {$not: {$gt: 7}}}, {x: [2, 3, 4, 10]});\n  nomatch({'x.y': {$not: {$gt: 7}}}, {x: [{y:2}, {y:3}, {y:4}, {y:10}]});\n\n  match({x: {$not: /a/}}, {x: \"dog\"});\n  nomatch({x: {$not: /a/}}, {x: \"cat\"});\n  match({x: {$not: /a/}}, {x: [\"dog\", \"puppy\"]});\n  nomatch({x: {$not: /a/}}, {x: [\"kitten\", \"cat\"]});\n\n  // dotted keypaths: bare values\n  match({\"a.b\": 1}, {a: {b: 1}});\n  nomatch({\"a.b\": 1}, {a: {b: 2}});\n  match({\"a.b\": [1,2,3]}, {a: {b: [1,2,3]}});\n  nomatch({\"a.b\": [1,2,3]}, {a: {b: [4]}});\n  match({\"a.b\": /a/}, {a: {b: \"cat\"}});\n  nomatch({\"a.b\": /a/}, {a: {b: \"dog\"}});\n  match({\"a.b.c\": null}, {});\n  match({\"a.b.c\": null}, {a: 1});\n  match({\"a.b\": null}, {a: 1});\n  match({\"a.b.c\": null}, {a: {b: 4}});\n\n  // dotted keypaths, nulls, numeric indices, arrays\n  nomatch({\"a.b\": null}, {a: [1]});\n  match({\"a.b\": []}, {a: {b: []}});\n  var big = {a: [{b: 1}, 2, {}, {b: [3, 4]}]};\n  match({\"a.b\": 1}, big);\n  match({\"a.b\": [3, 4]}, big);\n  match({\"a.b\": 3}, big);\n  match({\"a.b\": 4}, big);\n  match({\"a.b\": null}, big);  // matches on slot 2\n  match({'a.1': 8}, {a: [7, 8, 9]});\n  nomatch({'a.1': 7}, {a: [7, 8, 9]});\n  nomatch({'a.1': null}, {a: [7, 8, 9]});\n  match({'a.1': [8, 9]}, {a: [7, [8, 9]]});\n  nomatch({'a.1': 6}, {a: [[6, 7], [8, 9]]});\n  nomatch({'a.1': 7}, {a: [[6, 7], [8, 9]]});\n  nomatch({'a.1': 8}, {a: [[6, 7], [8, 9]]});\n  nomatch({'a.1': 9}, {a: [[6, 7], [8, 9]]});\n  match({\"a.1\": 2}, {a: [0, {1: 2}, 3]});\n  match({\"a.1\": {1: 2}}, {a: [0, {1: 2}, 3]});\n  match({\"x.1.y\": 8}, {x: [7, {y: 8}, 9]});\n  // comes from trying '1' as key in the plain object\n  match({\"x.1.y\": null}, {x: [7, {y: 8}, 9]});\n  match({\"a.1.b\": 9}, {a: [7, {b: 9}, {1: {b: 'foo'}}]});\n  match({\"a.1.b\": 'foo'}, {a: [7, {b: 9}, {1: {b: 'foo'}}]});\n  match({\"a.1.b\": null}, {a: [7, {b: 9}, {1: {b: 'foo'}}]});\n  match({\"a.1.b\": 2}, {a: [1, [{b: 2}], 3]});\n  nomatch({\"a.1.b\": null}, {a: [1, [{b: 2}], 3]});\n  // this is new behavior in mongo 2.5\n  nomatch({\"a.0.b\": null}, {a: [5]});\n  match({\"a.1\": 4}, {a: [{1: 4}, 5]});\n  match({\"a.1\": 5}, {a: [{1: 4}, 5]});\n  nomatch({\"a.1\": null}, {a: [{1: 4}, 5]});\n  match({\"a.1.foo\": 4}, {a: [{1: {foo: 4}}, {foo: 5}]});\n  match({\"a.1.foo\": 5}, {a: [{1: {foo: 4}}, {foo: 5}]});\n  match({\"a.1.foo\": null}, {a: [{1: {foo: 4}}, {foo: 5}]});\n\n  // trying to access a dotted field that is undefined at some point\n  // down the chain\n  nomatch({\"a.b\": 1}, {x: 2});\n  nomatch({\"a.b.c\": 1}, {a: {x: 2}});\n  nomatch({\"a.b.c\": 1}, {a: {b: {x: 2}}});\n  nomatch({\"a.b.c\": 1}, {a: {b: 1}});\n  nomatch({\"a.b.c\": 1}, {a: {b: 0}});\n\n  // dotted keypaths: literal objects\n  match({\"a.b\": {c: 1}}, {a: {b: {c: 1}}});\n  nomatch({\"a.b\": {c: 1}}, {a: {b: {c: 2}}});\n  nomatch({\"a.b\": {c: 1}}, {a: {b: 2}});\n  match({\"a.b\": {c: 1, d: 2}}, {a: {b: {c: 1, d: 2}}});\n  nomatch({\"a.b\": {c: 1, d: 2}}, {a: {b: {c: 1, d: 1}}});\n  nomatch({\"a.b\": {c: 1, d: 2}}, {a: {b: {d: 2}}});\n\n  // dotted keypaths: $ operators\n  match({\"a.b\": {$in: [1, 2, 3]}}, {a: {b: [2]}}); // tested against mongodb\n  match({\"a.b\": {$in: [{x: 1}, {x: 2}, {x: 3}]}}, {a: {b: [{x: 2}]}});\n  match({\"a.b\": {$in: [1, 2, 3]}}, {a: {b: [4, 2]}});\n  nomatch({\"a.b\": {$in: [1, 2, 3]}}, {a: {b: [4]}});\n\n  // $or\n  test.throws(function () {\n    match({$or: []}, {});\n  });\n  test.throws(function () {\n    match({$or: [5]}, {});\n  });\n  test.throws(function () {\n    match({$or: []}, {a: 1});\n  });\n  match({$or: [{a: 1}]}, {a: 1});\n  nomatch({$or: [{b: 2}]}, {a: 1});\n  match({$or: [{a: 1}, {b: 2}]}, {a: 1});\n  nomatch({$or: [{c: 3}, {d: 4}]}, {a: 1});\n  match({$or: [{a: 1}, {b: 2}]}, {a: [1, 2, 3]});\n  nomatch({$or: [{a: 1}, {b: 2}]}, {c: [1, 2, 3]});\n  nomatch({$or: [{a: 1}, {b: 2}]}, {a: [2, 3, 4]});\n  match({$or: [{a: 1}, {a: 2}]}, {a: 1});\n  match({$or: [{a: 1}, {a: 2}], b: 2}, {a: 1, b: 2});\n  nomatch({$or: [{a: 2}, {a: 3}], b: 2}, {a: 1, b: 2});\n  nomatch({$or: [{a: 1}, {a: 2}], b: 3}, {a: 1, b: 2});\n\n  // Combining $or with equality\n  match({x: 1, $or: [{a: 1}, {b: 1}]}, {x: 1, b: 1});\n  match({$or: [{a: 1}, {b: 1}], x: 1}, {x: 1, b: 1});\n  nomatch({x: 1, $or: [{a: 1}, {b: 1}]}, {b: 1});\n  nomatch({x: 1, $or: [{a: 1}, {b: 1}]}, {x: 1});\n\n  // $or and $lt, $lte, $gt, $gte\n  match({$or: [{a: {$lte: 1}}, {a: 2}]}, {a: 1});\n  nomatch({$or: [{a: {$lt: 1}}, {a: 2}]}, {a: 1});\n  match({$or: [{a: {$gte: 1}}, {a: 2}]}, {a: 1});\n  nomatch({$or: [{a: {$gt: 1}}, {a: 2}]}, {a: 1});\n  match({$or: [{b: {$gt: 1}}, {b: {$lt: 3}}]}, {b: 2});\n  nomatch({$or: [{b: {$lt: 1}}, {b: {$gt: 3}}]}, {b: 2});\n\n  // $or and $in\n  match({$or: [{a: {$in: [1, 2, 3]}}]}, {a: 1});\n  nomatch({$or: [{a: {$in: [4, 5, 6]}}]}, {a: 1});\n  match({$or: [{a: {$in: [1, 2, 3]}}, {b: 2}]}, {a: 1});\n  match({$or: [{a: {$in: [1, 2, 3]}}, {b: 2}]}, {b: 2});\n  nomatch({$or: [{a: {$in: [1, 2, 3]}}, {b: 2}]}, {c: 3});\n  match({$or: [{a: {$in: [1, 2, 3]}}, {b: {$in: [1, 2, 3]}}]}, {b: 2});\n  nomatch({$or: [{a: {$in: [1, 2, 3]}}, {b: {$in: [4, 5, 6]}}]}, {b: 2});\n\n  // $or and $nin\n  nomatch({$or: [{a: {$nin: [1, 2, 3]}}]}, {a: 1});\n  match({$or: [{a: {$nin: [4, 5, 6]}}]}, {a: 1});\n  nomatch({$or: [{a: {$nin: [1, 2, 3]}}, {b: 2}]}, {a: 1});\n  match({$or: [{a: {$nin: [1, 2, 3]}}, {b: 2}]}, {b: 2});\n  match({$or: [{a: {$nin: [1, 2, 3]}}, {b: 2}]}, {c: 3});\n  match({$or: [{a: {$nin: [1, 2, 3]}}, {b: {$nin: [1, 2, 3]}}]}, {b: 2});\n  nomatch({$or: [{a: {$nin: [1, 2, 3]}}, {b: {$nin: [1, 2, 3]}}]}, {a: 1, b: 2});\n  match({$or: [{a: {$nin: [1, 2, 3]}}, {b: {$nin: [4, 5, 6]}}]}, {b: 2});\n\n  // $or and dot-notation\n  match({$or: [{\"a.b\": 1}, {\"a.b\": 2}]}, {a: {b: 1}});\n  match({$or: [{\"a.b\": 1}, {\"a.c\": 1}]}, {a: {b: 1}});\n  nomatch({$or: [{\"a.b\": 2}, {\"a.c\": 1}]}, {a: {b: 1}});\n\n  // $or and nested objects\n  match({$or: [{a: {b: 1, c: 2}}, {a: {b: 2, c: 1}}]}, {a: {b: 1, c: 2}});\n  nomatch({$or: [{a: {b: 1, c: 3}}, {a: {b: 2, c: 1}}]}, {a: {b: 1, c: 2}});\n\n  // $or and regexes\n  match({$or: [{a: /a/}]}, {a: \"cat\"});\n  nomatch({$or: [{a: /o/}]}, {a: \"cat\"});\n  match({$or: [{a: /a/}, {a: /o/}]}, {a: \"cat\"});\n  nomatch({$or: [{a: /i/}, {a: /o/}]}, {a: \"cat\"});\n  match({$or: [{a: /i/}, {b: /o/}]}, {a: \"cat\", b: \"dog\"});\n\n  // $or and $ne\n  match({$or: [{a: {$ne: 1}}]}, {});\n  nomatch({$or: [{a: {$ne: 1}}]}, {a: 1});\n  match({$or: [{a: {$ne: 1}}]}, {a: 2});\n  match({$or: [{a: {$ne: 1}}]}, {b: 1});\n  match({$or: [{a: {$ne: 1}}, {a: {$ne: 2}}]}, {a: 1});\n  match({$or: [{a: {$ne: 1}}, {b: {$ne: 1}}]}, {a: 1});\n  nomatch({$or: [{a: {$ne: 1}}, {b: {$ne: 2}}]}, {a: 1, b: 2});\n\n  // $or and $not\n  match({$or: [{a: {$not: {$mod: [10, 1]}}}]}, {});\n  nomatch({$or: [{a: {$not: {$mod: [10, 1]}}}]}, {a: 1});\n  match({$or: [{a: {$not: {$mod: [10, 1]}}}]}, {a: 2});\n  match({$or: [{a: {$not: {$mod: [10, 1]}}}, {a: {$not: {$mod: [10, 2]}}}]}, {a: 1});\n  nomatch({$or: [{a: {$not: {$mod: [10, 1]}}}, {a: {$mod: [10, 2]}}]}, {a: 1});\n  match({$or: [{a: {$not: {$mod: [10, 1]}}}, {a: {$mod: [10, 2]}}]}, {a: 2});\n  match({$or: [{a: {$not: {$mod: [10, 1]}}}, {a: {$mod: [10, 2]}}]}, {a: 3});\n  // this is possibly an open-ended task, so we stop here ...\n\n  // $nor\n  test.throws(function () {\n    match({$nor: []}, {});\n  });\n  test.throws(function () {\n    match({$nor: [5]}, {});\n  });\n  test.throws(function () {\n    match({$nor: []}, {a: 1});\n  });\n  nomatch({$nor: [{a: 1}]}, {a: 1});\n  match({$nor: [{b: 2}]}, {a: 1});\n  nomatch({$nor: [{a: 1}, {b: 2}]}, {a: 1});\n  match({$nor: [{c: 3}, {d: 4}]}, {a: 1});\n  nomatch({$nor: [{a: 1}, {b: 2}]}, {a: [1, 2, 3]});\n  match({$nor: [{a: 1}, {b: 2}]}, {c: [1, 2, 3]});\n  match({$nor: [{a: 1}, {b: 2}]}, {a: [2, 3, 4]});\n  nomatch({$nor: [{a: 1}, {a: 2}]}, {a: 1});\n\n  // $nor and $lt, $lte, $gt, $gte\n  nomatch({$nor: [{a: {$lte: 1}}, {a: 2}]}, {a: 1});\n  match({$nor: [{a: {$lt: 1}}, {a: 2}]}, {a: 1});\n  nomatch({$nor: [{a: {$gte: 1}}, {a: 2}]}, {a: 1});\n  match({$nor: [{a: {$gt: 1}}, {a: 2}]}, {a: 1});\n  nomatch({$nor: [{b: {$gt: 1}}, {b: {$lt: 3}}]}, {b: 2});\n  match({$nor: [{b: {$lt: 1}}, {b: {$gt: 3}}]}, {b: 2});\n\n  // $nor and $in\n  nomatch({$nor: [{a: {$in: [1, 2, 3]}}]}, {a: 1});\n  match({$nor: [{a: {$in: [4, 5, 6]}}]}, {a: 1});\n  nomatch({$nor: [{a: {$in: [1, 2, 3]}}, {b: 2}]}, {a: 1});\n  nomatch({$nor: [{a: {$in: [1, 2, 3]}}, {b: 2}]}, {b: 2});\n  match({$nor: [{a: {$in: [1, 2, 3]}}, {b: 2}]}, {c: 3});\n  nomatch({$nor: [{a: {$in: [1, 2, 3]}}, {b: {$in: [1, 2, 3]}}]}, {b: 2});\n  match({$nor: [{a: {$in: [1, 2, 3]}}, {b: {$in: [4, 5, 6]}}]}, {b: 2});\n\n  // $nor and $nin\n  match({$nor: [{a: {$nin: [1, 2, 3]}}]}, {a: 1});\n  nomatch({$nor: [{a: {$nin: [4, 5, 6]}}]}, {a: 1});\n  match({$nor: [{a: {$nin: [1, 2, 3]}}, {b: 2}]}, {a: 1});\n  nomatch({$nor: [{a: {$nin: [1, 2, 3]}}, {b: 2}]}, {b: 2});\n  nomatch({$nor: [{a: {$nin: [1, 2, 3]}}, {b: 2}]}, {c: 3});\n  nomatch({$nor: [{a: {$nin: [1, 2, 3]}}, {b: {$nin: [1, 2, 3]}}]}, {b: 2});\n  match({$nor: [{a: {$nin: [1, 2, 3]}}, {b: {$nin: [1, 2, 3]}}]}, {a: 1, b: 2});\n  nomatch({$nor: [{a: {$nin: [1, 2, 3]}}, {b: {$nin: [4, 5, 6]}}]}, {b: 2});\n\n  // $nor and dot-notation\n  nomatch({$nor: [{\"a.b\": 1}, {\"a.b\": 2}]}, {a: {b: 1}});\n  nomatch({$nor: [{\"a.b\": 1}, {\"a.c\": 1}]}, {a: {b: 1}});\n  match({$nor: [{\"a.b\": 2}, {\"a.c\": 1}]}, {a: {b: 1}});\n\n  // $nor and nested objects\n  nomatch({$nor: [{a: {b: 1, c: 2}}, {a: {b: 2, c: 1}}]}, {a: {b: 1, c: 2}});\n  match({$nor: [{a: {b: 1, c: 3}}, {a: {b: 2, c: 1}}]}, {a: {b: 1, c: 2}});\n\n  // $nor and regexes\n  nomatch({$nor: [{a: /a/}]}, {a: \"cat\"});\n  match({$nor: [{a: /o/}]}, {a: \"cat\"});\n  nomatch({$nor: [{a: /a/}, {a: /o/}]}, {a: \"cat\"});\n  match({$nor: [{a: /i/}, {a: /o/}]}, {a: \"cat\"});\n  nomatch({$nor: [{a: /i/}, {b: /o/}]}, {a: \"cat\", b: \"dog\"});\n\n  // $nor and $ne\n  nomatch({$nor: [{a: {$ne: 1}}]}, {});\n  match({$nor: [{a: {$ne: 1}}]}, {a: 1});\n  nomatch({$nor: [{a: {$ne: 1}}]}, {a: 2});\n  nomatch({$nor: [{a: {$ne: 1}}]}, {b: 1});\n  nomatch({$nor: [{a: {$ne: 1}}, {a: {$ne: 2}}]}, {a: 1});\n  nomatch({$nor: [{a: {$ne: 1}}, {b: {$ne: 1}}]}, {a: 1});\n  match({$nor: [{a: {$ne: 1}}, {b: {$ne: 2}}]}, {a: 1, b: 2});\n\n  // $nor and $not\n  nomatch({$nor: [{a: {$not: {$mod: [10, 1]}}}]}, {});\n  match({$nor: [{a: {$not: {$mod: [10, 1]}}}]}, {a: 1});\n  nomatch({$nor: [{a: {$not: {$mod: [10, 1]}}}]}, {a: 2});\n  nomatch({$nor: [{a: {$not: {$mod: [10, 1]}}}, {a: {$not: {$mod: [10, 2]}}}]}, {a: 1});\n  match({$nor: [{a: {$not: {$mod: [10, 1]}}}, {a: {$mod: [10, 2]}}]}, {a: 1});\n  nomatch({$nor: [{a: {$not: {$mod: [10, 1]}}}, {a: {$mod: [10, 2]}}]}, {a: 2});\n  nomatch({$nor: [{a: {$not: {$mod: [10, 1]}}}, {a: {$mod: [10, 2]}}]}, {a: 3});\n\n  // $and\n\n  test.throws(function () {\n    match({$and: []}, {});\n  });\n  test.throws(function () {\n    match({$and: [5]}, {});\n  });\n  test.throws(function () {\n    match({$and: []}, {a: 1});\n  });\n  match({$and: [{a: 1}]}, {a: 1});\n  nomatch({$and: [{a: 1}, {a: 2}]}, {a: 1});\n  nomatch({$and: [{a: 1}, {b: 1}]}, {a: 1});\n  match({$and: [{a: 1}, {b: 2}]}, {a: 1, b: 2});\n  nomatch({$and: [{a: 1}, {b: 1}]}, {a: 1, b: 2});\n  match({$and: [{a: 1}, {b: 2}], c: 3}, {a: 1, b: 2, c: 3});\n  nomatch({$and: [{a: 1}, {b: 2}], c: 4}, {a: 1, b: 2, c: 3});\n\n  // $and and regexes\n  match({$and: [{a: /a/}]}, {a: \"cat\"});\n  match({$and: [{a: /a/i}]}, {a: \"CAT\"});\n  nomatch({$and: [{a: /o/}]}, {a: \"cat\"});\n  nomatch({$and: [{a: /a/}, {a: /o/}]}, {a: \"cat\"});\n  match({$and: [{a: /a/}, {b: /o/}]}, {a: \"cat\", b: \"dog\"});\n  nomatch({$and: [{a: /a/}, {b: /a/}]}, {a: \"cat\", b: \"dog\"});\n\n  // $and, dot-notation, and nested objects\n  match({$and: [{\"a.b\": 1}]}, {a: {b: 1}});\n  match({$and: [{a: {b: 1}}]}, {a: {b: 1}});\n  nomatch({$and: [{\"a.b\": 2}]}, {a: {b: 1}});\n  nomatch({$and: [{\"a.c\": 1}]}, {a: {b: 1}});\n  nomatch({$and: [{\"a.b\": 1}, {\"a.b\": 2}]}, {a: {b: 1}});\n  nomatch({$and: [{\"a.b\": 1}, {a: {b: 2}}]}, {a: {b: 1}});\n  match({$and: [{\"a.b\": 1}, {\"c.d\": 2}]}, {a: {b: 1}, c: {d: 2}});\n  nomatch({$and: [{\"a.b\": 1}, {\"c.d\": 1}]}, {a: {b: 1}, c: {d: 2}});\n  match({$and: [{\"a.b\": 1}, {c: {d: 2}}]}, {a: {b: 1}, c: {d: 2}});\n  nomatch({$and: [{\"a.b\": 1}, {c: {d: 1}}]}, {a: {b: 1}, c: {d: 2}});\n  nomatch({$and: [{\"a.b\": 2}, {c: {d: 2}}]}, {a: {b: 1}, c: {d: 2}});\n  match({$and: [{a: {b: 1}}, {c: {d: 2}}]}, {a: {b: 1}, c: {d: 2}});\n  nomatch({$and: [{a: {b: 2}}, {c: {d: 2}}]}, {a: {b: 1}, c: {d: 2}});\n\n  // $and and $in\n  nomatch({$and: [{a: {$in: []}}]}, {});\n  match({$and: [{a: {$in: [1, 2, 3]}}]}, {a: 1});\n  nomatch({$and: [{a: {$in: [4, 5, 6]}}]}, {a: 1});\n  nomatch({$and: [{a: {$in: [1, 2, 3]}}, {a: {$in: [4, 5, 6]}}]}, {a: 1});\n  nomatch({$and: [{a: {$in: [1, 2, 3]}}, {b: {$in: [1, 2, 3]}}]}, {a: 1, b: 4});\n  match({$and: [{a: {$in: [1, 2, 3]}}, {b: {$in: [4, 5, 6]}}]}, {a: 1, b: 4});\n\n\n  // $and and $nin\n  match({$and: [{a: {$nin: []}}]}, {});\n  nomatch({$and: [{a: {$nin: [1, 2, 3]}}]}, {a: 1});\n  match({$and: [{a: {$nin: [4, 5, 6]}}]}, {a: 1});\n  nomatch({$and: [{a: {$nin: [1, 2, 3]}}, {a: {$nin: [4, 5, 6]}}]}, {a: 1});\n  nomatch({$and: [{a: {$nin: [1, 2, 3]}}, {b: {$nin: [1, 2, 3]}}]}, {a: 1, b: 4});\n  nomatch({$and: [{a: {$nin: [1, 2, 3]}}, {b: {$nin: [4, 5, 6]}}]}, {a: 1, b: 4});\n\n  // $and and $lt, $lte, $gt, $gte\n  match({$and: [{a: {$lt: 2}}]}, {a: 1});\n  nomatch({$and: [{a: {$lt: 1}}]}, {a: 1});\n  match({$and: [{a: {$lte: 1}}]}, {a: 1});\n  match({$and: [{a: {$gt: 0}}]}, {a: 1});\n  nomatch({$and: [{a: {$gt: 1}}]}, {a: 1});\n  match({$and: [{a: {$gte: 1}}]}, {a: 1});\n  match({$and: [{a: {$gt: 0}}, {a: {$lt: 2}}]}, {a: 1});\n  nomatch({$and: [{a: {$gt: 1}}, {a: {$lt: 2}}]}, {a: 1});\n  nomatch({$and: [{a: {$gt: 0}}, {a: {$lt: 1}}]}, {a: 1});\n  match({$and: [{a: {$gte: 1}}, {a: {$lte: 1}}]}, {a: 1});\n  nomatch({$and: [{a: {$gte: 2}}, {a: {$lte: 0}}]}, {a: 1});\n\n  // $and and $ne\n  match({$and: [{a: {$ne: 1}}]}, {});\n  nomatch({$and: [{a: {$ne: 1}}]}, {a: 1});\n  match({$and: [{a: {$ne: 1}}]}, {a: 2});\n  nomatch({$and: [{a: {$ne: 1}}, {a: {$ne: 2}}]}, {a: 2});\n  match({$and: [{a: {$ne: 1}}, {a: {$ne: 3}}]}, {a: 2});\n\n  // $and and $not\n  match({$and: [{a: {$not: {$gt: 2}}}]}, {a: 1});\n  nomatch({$and: [{a: {$not: {$lt: 2}}}]}, {a: 1});\n  match({$and: [{a: {$not: {$lt: 0}}}, {a: {$not: {$gt: 2}}}]}, {a: 1});\n  nomatch({$and: [{a: {$not: {$lt: 2}}}, {a: {$not: {$gt: 0}}}]}, {a: 1});\n\n  // $where\n  match({$where: \"this.a === 1\"}, {a: 1});\n  match({$where: \"obj.a === 1\"}, {a: 1});\n  nomatch({$where: \"this.a !== 1\"}, {a: 1});\n  nomatch({$where: \"obj.a !== 1\"}, {a: 1});\n  nomatch({$where: \"this.a === 1\", a: 2}, {a: 1});\n  match({$where: \"this.a === 1\", b: 2}, {a: 1, b: 2});\n  match({$where: \"this.a === 1 && this.b === 2\"}, {a: 1, b: 2});\n  match({$where: \"this.a instanceof Array\"}, {a: []});\n  nomatch({$where: \"this.a instanceof Array\"}, {a: 1});\n\n  // reaching into array\n  match({\"dogs.0.name\": \"Fido\"}, {dogs: [{name: \"Fido\"}, {name: \"Rex\"}]});\n  match({\"dogs.1.name\": \"Rex\"}, {dogs: [{name: \"Fido\"}, {name: \"Rex\"}]});\n  nomatch({\"dogs.1.name\": \"Fido\"}, {dogs: [{name: \"Fido\"}, {name: \"Rex\"}]});\n  match({\"room.1b\": \"bla\"}, {room: {\"1b\": \"bla\"}});\n\n  match({\"dogs.name\": \"Fido\"}, {dogs: [{name: \"Fido\"}, {name: \"Rex\"}]});\n  match({\"dogs.name\": \"Rex\"}, {dogs: [{name: \"Fido\"}, {name: \"Rex\"}]});\n  match({\"animals.dogs.name\": \"Fido\"},\n        {animals: [{dogs: [{name: \"Rover\"}]},\n                   {},\n                   {dogs: [{name: \"Fido\"}, {name: \"Rex\"}]}]});\n  match({\"animals.dogs.name\": \"Fido\"},\n        {animals: [{dogs: {name: \"Rex\"}},\n                   {dogs: {name: \"Fido\"}}]});\n  match({\"animals.dogs.name\": \"Fido\"},\n        {animals: [{dogs: [{name: \"Rover\"}]},\n                   {},\n                   {dogs: [{name: [\"Fido\"]}, {name: \"Rex\"}]}]});\n  nomatch({\"dogs.name\": \"Fido\"}, {dogs: []});\n\n  // $elemMatch\n  match({dogs: {$elemMatch: {name: /e/}}},\n        {dogs: [{name: \"Fido\"}, {name: \"Rex\"}]});\n  nomatch({dogs: {$elemMatch: {name: /a/}}},\n          {dogs: [{name: \"Fido\"}, {name: \"Rex\"}]});\n  match({dogs: {$elemMatch: {age: {$gt: 4}}}},\n        {dogs: [{name: \"Fido\", age: 5}, {name: \"Rex\", age: 3}]});\n  match({dogs: {$elemMatch: {name: \"Fido\", age: {$gt: 4}}}},\n        {dogs: [{name: \"Fido\", age: 5}, {name: \"Rex\", age: 3}]});\n  nomatch({dogs: {$elemMatch: {name: \"Fido\", age: {$gt: 5}}}},\n          {dogs: [{name: \"Fido\", age: 5}, {name: \"Rex\", age: 3}]});\n  match({dogs: {$elemMatch: {name: /i/, age: {$gt: 4}}}},\n        {dogs: [{name: \"Fido\", age: 5}, {name: \"Rex\", age: 3}]});\n  nomatch({dogs: {$elemMatch: {name: /e/, age: 5}}},\n          {dogs: [{name: \"Fido\", age: 5}, {name: \"Rex\", age: 3}]});\n  match({x: {$elemMatch: {y: 9}}}, {x: [{y: 9}]});\n  nomatch({x: {$elemMatch: {y: 9}}}, {x: [[{y: 9}]]});\n  match({x: {$elemMatch: {$gt: 5, $lt: 9}}}, {x: [8]});\n  nomatch({x: {$elemMatch: {$gt: 5, $lt: 9}}}, {x: [[8]]});\n  match({'a.x': {$elemMatch: {y: 9}}},\n        {a: [{x: []}, {x: [{y: 9}]}]});\n  nomatch({a: {$elemMatch: {x: 5}}}, {a: {x: 5}});\n  match({a: {$elemMatch: {0: {$gt: 5, $lt: 9}}}}, {a: [[6]]});\n  match({a: {$elemMatch: {'0.b': {$gt: 5, $lt: 9}}}}, {a: [[{b:6}]]});\n  match({a: {$elemMatch: {x: 1, $or: [{a: 1}, {b: 1}]}}},\n        {a: [{x: 1, b: 1}]});\n  match({a: {$elemMatch: {$or: [{a: 1}, {b: 1}], x: 1}}},\n        {a: [{x: 1, b: 1}]});\n  match({a: {$elemMatch: {$or: [{a: 1}, {b: 1}]}}},\n        {a: [{x: 1, b: 1}]});\n  match({a: {$elemMatch: {$or: [{a: 1}, {b: 1}]}}},\n        {a: [{x: 1, b: 1}]});\n  match({a: {$elemMatch: {$and: [{b: 1}, {x: 1}]}}},\n        {a: [{x: 1, b: 1}]});\n  nomatch({a: {$elemMatch: {x: 1, $or: [{a: 1}, {b: 1}]}}},\n          {a: [{b: 1}]});\n  nomatch({a: {$elemMatch: {x: 1, $or: [{a: 1}, {b: 1}]}}},\n          {a: [{x: 1}]});\n  nomatch({a: {$elemMatch: {x: 1, $or: [{a: 1}, {b: 1}]}}},\n          {a: [{x: 1}, {b: 1}]});\n\n  test.throws(function () {\n    match({a: {$elemMatch: {$gte: 1, $or: [{a: 1}, {b: 1}]}}},\n          {a: [{x: 1, b: 1}]});\n  });\n\n  test.throws(function () {\n    match({x: {$elemMatch: {$and: [{$gt: 5, $lt: 9}]}}}, {x: [8]});\n  });\n\n  // $comment\n  match({a: 5, $comment: \"asdf\"}, {a: 5});\n  nomatch({a: 6, $comment: \"asdf\"}, {a: 5});\n\n  // XXX still needs tests:\n  // - non-scalar arguments to $gt, $lt, etc\n});\n\nTinytest.add(\"minimongo - projection_compiler\", function (test) {\n  var testProjection = function (projection, tests) {\n    var projection_f = LocalCollection._compileProjection(projection);\n    var equalNonStrict = function (a, b, desc) {\n      test.isTrue(_.isEqual(a, b), desc);\n    };\n\n    _.each(tests, function (testCase) {\n      equalNonStrict(projection_f(testCase[0]), testCase[1], testCase[2]);\n    });\n  };\n\n  var testCompileProjectionThrows = function (projection, expectedError) {\n    test.throws(function () {\n      LocalCollection._compileProjection(projection);\n    }, expectedError);\n  };\n\n  testProjection({ 'foo': 1, 'bar': 1 }, [\n    [{ foo: 42, bar: \"something\", baz: \"else\" },\n     { foo: 42, bar: \"something\" },\n     \"simplest - whitelist\"],\n\n    [{ foo: { nested: 17 }, baz: {} },\n     { foo: { nested: 17 } },\n     \"nested whitelisted field\"],\n\n    [{ _id: \"uid\", bazbaz: 42 },\n     { _id: \"uid\" },\n     \"simplest whitelist - preserve _id\"]\n  ]);\n\n  testProjection({ 'foo': 0, 'bar': 0 }, [\n    [{ foo: 42, bar: \"something\", baz: \"else\" },\n     { baz: \"else\" },\n     \"simplest - blacklist\"],\n\n    [{ foo: { nested: 17 }, baz: { foo: \"something\" } },\n     { baz: { foo: \"something\" } },\n     \"nested blacklisted field\"],\n\n    [{ _id: \"uid\", bazbaz: 42 },\n     { _id: \"uid\", bazbaz: 42 },\n     \"simplest blacklist - preserve _id\"]\n  ]);\n\n  testProjection({ _id: 0, foo: 1 }, [\n    [{ foo: 42, bar: 33, _id: \"uid\" },\n     { foo: 42 },\n     \"whitelist - _id blacklisted\"]\n  ]);\n\n  testProjection({ _id: 0, foo: 0 }, [\n    [{ foo: 42, bar: 33, _id: \"uid\" },\n     { bar: 33 },\n     \"blacklist - _id blacklisted\"]\n  ]);\n\n  testProjection({ 'foo.bar.baz': 1 }, [\n    [{ foo: { meh: \"fur\", bar: { baz: 42 }, tr: 1 }, bar: 33, baz: 'trolololo' },\n     { foo: { bar: { baz: 42 } } },\n     \"whitelist nested\"],\n\n    // Behavior of this test is looked up in actual mongo\n    [{ foo: { meh: \"fur\", bar: \"nope\", tr: 1 }, bar: 33, baz: 'trolololo' },\n     { foo: {} },\n     \"whitelist nested - path not found in doc, different type\"],\n\n    // Behavior of this test is looked up in actual mongo\n    [{ foo: { meh: \"fur\", bar: [], tr: 1 }, bar: 33, baz: 'trolololo' },\n     { foo: { bar: [] } },\n     \"whitelist nested - path not found in doc\"]\n  ]);\n\n  testProjection({ 'hope.humanity': 0, 'hope.people': 0 }, [\n    [{ hope: { humanity: \"lost\", people: 'broken', candies: 'long live!' } },\n     { hope: { candies: 'long live!' } },\n     \"blacklist nested\"],\n\n    [{ hope: \"new\" },\n     { hope: \"new\" },\n     \"blacklist nested - path not found in doc\"]\n  ]);\n\n  testProjection({ _id: 1 }, [\n    [{ _id: 42, x: 1, y: { z: \"2\" } },\n     { _id: 42 },\n     \"_id whitelisted\"],\n    [{ _id: 33 },\n     { _id: 33 },\n     \"_id whitelisted, _id only\"],\n    [{ x: 1 },\n     {},\n     \"_id whitelisted, no _id\"]\n  ]);\n\n  testProjection({ _id: 0 }, [\n    [{ _id: 42, x: 1, y: { z: \"2\" } },\n     { x: 1, y: { z: \"2\" } },\n     \"_id blacklisted\"],\n    [{ _id: 33 },\n     {},\n     \"_id blacklisted, _id only\"],\n    [{ x: 1 },\n     { x: 1 },\n     \"_id blacklisted, no _id\"]\n  ]);\n\n  testProjection({}, [\n    [{ a: 1, b: 2, c: \"3\" },\n     { a: 1, b: 2, c: \"3\" },\n     \"empty projection\"]\n  ]);\n\n  testCompileProjectionThrows(\n    { 'inc': 1, 'excl': 0 },\n    \"You cannot currently mix including and excluding fields\");\n  testCompileProjectionThrows(\n    { _id: 1, a: 0 },\n    \"You cannot currently mix including and excluding fields\");\n\n  testCompileProjectionThrows(\n    { 'a': 1, 'a.b': 1 },\n    \"using both of them may trigger unexpected behavior\");\n  testCompileProjectionThrows(\n    { 'a.b.c': 1, 'a.b': 1, 'a': 1 },\n    \"using both of them may trigger unexpected behavior\");\n\n  testCompileProjectionThrows(\"some string\", \"fields option must be an object\");\n});\n\nTinytest.add(\"minimongo - fetch with fields\", function (test) {\n  var c = new LocalCollection();\n  _.times(30, function (i) {\n    c.insert({\n      something: Random.id(),\n      anything: {\n        foo: \"bar\",\n        cool: \"hot\"\n      },\n      nothing: i,\n      i: i\n    });\n  });\n\n  // Test just a regular fetch with some projection\n  var fetchResults = c.find({}, { fields: {\n    'something': 1,\n    'anything.foo': 1\n  } }).fetch();\n\n  test.isTrue(_.all(fetchResults, function (x) {\n    return x &&\n           x.something &&\n           x.anything &&\n           x.anything.foo &&\n           x.anything.foo === \"bar\" &&\n           !_.has(x, 'nothing') &&\n           !_.has(x.anything, 'cool');\n  }));\n\n  // Test with a selector, even field used in the selector is excluded in the\n  // projection\n  fetchResults = c.find({\n    nothing: { $gte: 5 }\n  }, {\n    fields: { nothing: 0 }\n  }).fetch();\n\n  test.isTrue(_.all(fetchResults, function (x) {\n    return x &&\n           x.something &&\n           x.anything &&\n           x.anything.foo === \"bar\" &&\n           x.anything.cool === \"hot\" &&\n           !_.has(x, 'nothing') &&\n           x.i &&\n           x.i >= 5;\n  }));\n\n  test.isTrue(fetchResults.length === 25);\n\n  // Test that we can sort, based on field excluded from the projection, use\n  // skip and limit as well!\n  // following find will get indexes [10..20) sorted by nothing\n  fetchResults = c.find({}, {\n    sort: {\n      nothing: 1\n    },\n    limit: 10,\n    skip: 10,\n    fields: {\n      i: 1,\n      something: 1\n    }\n  }).fetch();\n\n  test.isTrue(_.all(fetchResults, function (x) {\n    return x &&\n           x.something &&\n           x.i >= 10 && x.i < 20;\n  }));\n\n  _.each(fetchResults, function (x, i, arr) {\n    if (!i) return;\n    test.isTrue(x.i === arr[i-1].i + 1);\n  });\n\n  // Temporary unsupported operators\n  // queries are taken from MongoDB docs examples\n  test.throws(function () {\n    c.find({}, { fields: { 'grades.$': 1 } });\n  });\n  test.throws(function () {\n    c.find({}, { fields: { grades: { $elemMatch: { mean: 70 } } } });\n  });\n  test.throws(function () {\n    c.find({}, { fields: { grades: { $slice: [20, 10] } } });\n  });\n});\n\nTinytest.add(\"minimongo - fetch with projection, subarrays\", function (test) {\n  // Apparently projection of type 'foo.bar.x' for\n  // { foo: [ { bar: { x: 42 } }, { bar: { x: 3 } } ] }\n  // should return exactly this object. More precisely, arrays are considered as\n  // sets and are queried separately and then merged back to result set\n  var c = new LocalCollection();\n\n  // Insert a test object with two set fields\n  c.insert({\n    setA: [{\n      fieldA: 42,\n      fieldB: 33\n    }, {\n      fieldA: \"the good\",\n      fieldB: \"the bad\",\n      fieldC: \"the ugly\"\n    }],\n    setB: [{\n      anotherA: { },\n      anotherB: \"meh\"\n    }, {\n      anotherA: 1234,\n      anotherB: 431\n    }]\n  });\n\n  var equalNonStrict = function (a, b, desc) {\n    test.isTrue(_.isEqual(a, b), desc);\n  };\n\n  var testForProjection = function (projection, expected) {\n    var fetched = c.find({}, { fields: projection }).fetch()[0];\n    equalNonStrict(fetched, expected, \"failed sub-set projection: \" +\n                                      JSON.stringify(projection));\n  };\n\n  testForProjection({ 'setA.fieldA': 1, 'setB.anotherB': 1, _id: 0 },\n                    {\n                      setA: [{ fieldA: 42 }, { fieldA: \"the good\" }],\n                      setB: [{ anotherB: \"meh\" }, { anotherB: 431 }]\n                    });\n\n  testForProjection({ 'setA.fieldA': 0, 'setB.anotherA': 0, _id: 0 },\n                    {\n                      setA: [{fieldB:33}, {fieldB:\"the bad\",fieldC:\"the ugly\"}],\n                      setB: [{ anotherB: \"meh\" }, { anotherB: 431 }]\n                    });\n\n  c.remove({});\n  c.insert({a:[[{b:1,c:2},{b:2,c:4}],{b:3,c:5},[{b:4, c:9}]]});\n\n  testForProjection({ 'a.b': 1, _id: 0 },\n                    {a: [ [ { b: 1 }, { b: 2 } ], { b: 3 }, [ { b: 4 } ] ] });\n  testForProjection({ 'a.b': 0, _id: 0 },\n                    {a: [ [ { c: 2 }, { c: 4 } ], { c: 5 }, [ { c: 9 } ] ] });\n});\n\nTinytest.add(\"minimongo - fetch with projection, deep copy\", function (test) {\n  // Compiled fields projection defines the contract: returned document doesn't\n  // retain anything from the passed argument.\n  var doc = {\n    a: { x: 42 },\n    b: {\n      y: { z: 33 }\n    },\n    c: \"asdf\"\n  };\n\n  var fields = {\n    'a': 1,\n    'b.y': 1\n  };\n\n  var projectionFn = LocalCollection._compileProjection(fields);\n  var filteredDoc = projectionFn(doc);\n  doc.a.x++;\n  doc.b.y.z--;\n  test.equal(filteredDoc.a.x, 42, \"projection returning deep copy - including\");\n  test.equal(filteredDoc.b.y.z, 33, \"projection returning deep copy - including\");\n\n  fields = { c: 0 };\n  projectionFn = LocalCollection._compileProjection(fields);\n  filteredDoc = projectionFn(doc);\n\n  doc.a.x = 5;\n  test.equal(filteredDoc.a.x, 43, \"projection returning deep copy - excluding\");\n});\n\nTinytest.add(\"minimongo - observe ordered with projection\", function (test) {\n  // These tests are copy-paste from \"minimongo -observe ordered\",\n  // slightly modified to test projection\n  var operations = [];\n  var cbs = log_callbacks(operations);\n  var handle;\n\n  var c = new LocalCollection();\n  handle = c.find({}, {sort: {a: 1}, fields: { a: 1 }}).observe(cbs);\n  test.isTrue(handle.collection === c);\n\n  c.insert({_id: 'foo', a:1, b:2});\n  test.equal(operations.shift(), ['added', {a:1}, 0, null]);\n  c.update({a:1}, {$set: {a: 2, b: 1}});\n  test.equal(operations.shift(), ['changed', {a:2}, 0, {a:1}]);\n  c.insert({_id: 'bar', a:10, c: 33});\n  test.equal(operations.shift(), ['added', {a:10}, 1, null]);\n  c.update({}, {$inc: {a: 1}}, {multi: true});\n  c.update({}, {$inc: {c: 1}}, {multi: true});\n  test.equal(operations.shift(), ['changed', {a:3}, 0, {a:2}]);\n  test.equal(operations.shift(), ['changed', {a:11}, 1, {a:10}]);\n  c.update({a:11}, {a:1, b:44});\n  test.equal(operations.shift(), ['changed', {a:1}, 1, {a:11}]);\n  test.equal(operations.shift(), ['moved', {a:1}, 1, 0, 'foo']);\n  c.remove({a:2});\n  test.equal(operations.shift(), undefined);\n  c.remove({a:3});\n  test.equal(operations.shift(), ['removed', 'foo', 1, {a:3}]);\n\n  // test stop\n  handle.stop();\n  var idA2 = Random.id();\n  c.insert({_id: idA2, a:2});\n  test.equal(operations.shift(), undefined);\n\n  var cursor = c.find({}, {fields: {a: 1, _id: 0}});\n  test.throws(function () {\n    cursor.observeChanges({added: function () {}});\n  });\n  test.throws(function () {\n    cursor.observe({added: function () {}});\n  });\n\n  // test initial inserts (and backwards sort)\n  handle = c.find({}, {sort: {a: -1}, fields: { a: 1 } }).observe(cbs);\n  test.equal(operations.shift(), ['added', {a:2}, 0, null]);\n  test.equal(operations.shift(), ['added', {a:1}, 1, null]);\n  handle.stop();\n\n  // test _suppress_initial\n  handle = c.find({}, {sort: {a: -1}, fields: { a: 1 }}).observe(_.extend(cbs, {_suppress_initial: true}));\n  test.equal(operations.shift(), undefined);\n  c.insert({a:100, b: { foo: \"bar\" }});\n  test.equal(operations.shift(), ['added', {a:100}, 0, idA2]);\n  handle.stop();\n\n  // test skip and limit.\n  c.remove({});\n  handle = c.find({}, {sort: {a: 1}, skip: 1, limit: 2, fields: { 'blacklisted': 0 }}).observe(cbs);\n  test.equal(operations.shift(), undefined);\n  c.insert({a:1, blacklisted:1324});\n  test.equal(operations.shift(), undefined);\n  c.insert({_id: 'foo', a:2, blacklisted:[\"something\"]});\n  test.equal(operations.shift(), ['added', {a:2}, 0, null]);\n  c.insert({a:3, blacklisted: { 2: 3 }});\n  test.equal(operations.shift(), ['added', {a:3}, 1, null]);\n  c.insert({a:4, blacklisted: 6});\n  test.equal(operations.shift(), undefined);\n  c.update({a:1}, {a:0, blacklisted:4444});\n  test.equal(operations.shift(), undefined);\n  c.update({a:0}, {a:5, blacklisted:11111});\n  test.equal(operations.shift(), ['removed', 'foo', 0, {a:2}]);\n  test.equal(operations.shift(), ['added', {a:4}, 1, null]);\n  c.update({a:3}, {a:3.5, blacklisted:333.4444});\n  test.equal(operations.shift(), ['changed', {a:3.5}, 0, {a:3}]);\n  handle.stop();\n\n  // test _no_indices\n\n  c.remove({});\n  handle = c.find({}, {sort: {a: 1}, fields: { a: 1 }}).observe(_.extend(cbs, {_no_indices: true}));\n  c.insert({_id: 'foo', a:1, zoo: \"crazy\"});\n  test.equal(operations.shift(), ['added', {a:1}, -1, null]);\n  c.update({a:1}, {$set: {a: 2, foobar: \"player\"}});\n  test.equal(operations.shift(), ['changed', {a:2}, -1, {a:1}]);\n  c.insert({a:10, b:123.45});\n  test.equal(operations.shift(), ['added', {a:10}, -1, null]);\n  c.update({}, {$inc: {a: 1, b:2}}, {multi: true});\n  test.equal(operations.shift(), ['changed', {a:3}, -1, {a:2}]);\n  test.equal(operations.shift(), ['changed', {a:11}, -1, {a:10}]);\n  c.update({a:11, b:125.45}, {a:1, b:444});\n  test.equal(operations.shift(), ['changed', {a:1}, -1, {a:11}]);\n  test.equal(operations.shift(), ['moved', {a:1}, -1, -1, 'foo']);\n  c.remove({a:2});\n  test.equal(operations.shift(), undefined);\n  c.remove({a:3});\n  test.equal(operations.shift(), ['removed', 'foo', -1, {a:3}]);\n  handle.stop();\n});\n\n\nTinytest.add(\"minimongo - ordering\", function (test) {\n  var shortBinary = EJSON.newBinary(1);\n  shortBinary[0] = 128;\n  var longBinary1 = EJSON.newBinary(2);\n  longBinary1[1] = 42;\n  var longBinary2 = EJSON.newBinary(2);\n  longBinary2[1] = 50;\n\n  var date1 = new Date;\n  var date2 = new Date(date1.getTime() + 1000);\n\n  // value ordering\n  assert_ordering(test, LocalCollection._f._cmp, [\n    null,\n    1, 2.2, 3,\n    \"03\", \"1\", \"11\", \"2\", \"a\", \"aaa\",\n    {}, {a: 2}, {a: 3}, {a: 3, b: 4}, {b: 4}, {b: 4, a: 3},\n    {b: {}}, {b: [1, 2, 3]}, {b: [1, 2, 4]},\n    [], [1, 2], [1, 2, 3], [1, 2, 4], [1, 2, \"4\"], [1, 2, [4]],\n    shortBinary, longBinary1, longBinary2,\n    new MongoID.ObjectID(\"1234567890abcd1234567890\"),\n    new MongoID.ObjectID(\"abcd1234567890abcd123456\"),\n    false, true,\n    date1, date2\n  ]);\n\n  // document ordering under a sort specification\n  var verify = function (sorts, docs) {\n    _.each(_.isArray(sorts) ? sorts : [sorts], function (sort) {\n      var sorter = new Minimongo.Sorter(sort);\n      assert_ordering(test, sorter.getComparator(), docs);\n    });\n  };\n\n  // note: [] doesn't sort with \"arrays\", it sorts as \"undefined\". the position\n  // of arrays in _typeorder only matters for things like $lt. (This behavior\n  // verified with MongoDB 2.2.1.) We don't define the relative order of {a: []}\n  // and {c: 1} is undefined (MongoDB does seem to care but it's not clear how\n  // or why).\n  verify([{\"a\" : 1}, [\"a\"], [[\"a\", \"asc\"]]],\n         [{a: []}, {a: 1}, {a: {}}, {a: true}]);\n  verify([{\"a\" : 1}, [\"a\"], [[\"a\", \"asc\"]]],\n         [{c: 1}, {a: 1}, {a: {}}, {a: true}]);\n  verify([{\"a\" : -1}, [[\"a\", \"desc\"]]],\n         [{a: true}, {a: {}}, {a: 1}, {c: 1}]);\n  verify([{\"a\" : -1}, [[\"a\", \"desc\"]]],\n         [{a: true}, {a: {}}, {a: 1}, {a: []}]);\n\n  verify([{\"a\" : 1, \"b\": -1}, [\"a\", [\"b\", \"desc\"]],\n          [[\"a\", \"asc\"], [\"b\", \"desc\"]]],\n         [{c: 1}, {a: 1, b: 3}, {a: 1, b: 2}, {a: 2, b: 0}]);\n\n  verify([{\"a\" : 1, \"b\": 1}, [\"a\", \"b\"],\n          [[\"a\", \"asc\"], [\"b\", \"asc\"]]],\n         [{c: 1}, {a: 1, b: 2}, {a: 1, b: 3}, {a: 2, b: 0}]);\n\n  test.throws(function () {\n    new Minimongo.Sorter(\"a\");\n  });\n\n  test.throws(function () {\n    new Minimongo.Sorter(123);\n  });\n\n  // We don't support $natural:1 (since we don't actually have Mongo's on-disk\n  // ordering available!)\n  test.throws(function () {\n    new Minimongo.Sorter({$natural: 1});\n  });\n\n  // No sort spec implies everything equal.\n  test.equal(new Minimongo.Sorter({}).getComparator()({a:1}, {a:2}), 0);\n\n  // All sorts of array edge cases!\n  // Increasing sort sorts by the smallest element it finds; 1 < 2.\n  verify({a: 1}, [\n    {a: [1, 10, 20]},\n    {a: [5, 2, 99]}\n  ]);\n  // Decreasing sorts by largest it finds; 99 > 20.\n  verify({a: -1}, [\n    {a: [5, 2, 99]},\n    {a: [1, 10, 20]}\n  ]);\n  // Can also sort by specific array indices.\n  verify({'a.1': 1}, [\n    {a: [5, 2, 99]},\n    {a: [1, 10, 20]}\n  ]);\n  // We do NOT expand sub-arrays, so the minimum in the second doc is 5, not\n  // -20. (Numbers always sort before arrays.)\n  verify({a: 1}, [\n    {a: [1, [10, 15], 20]},\n    {a: [5, [-5, -20], 18]}\n  ]);\n  // The maximum in each of these is the array, since arrays are \"greater\" than\n  // numbers. And [10, 15] is greater than [-5, -20].\n  verify({a: -1}, [\n    {a: [1, [10, 15], 20]},\n    {a: [5, [-5, -20], 18]}\n  ]);\n  // 'a.0' here ONLY means \"first element of a\", not \"first element of something\n  // found in a\", so it CANNOT find the 10 or -5.\n  verify({'a.0': 1}, [\n    {a: [1, [10, 15], 20]},\n    {a: [5, [-5, -20], 18]}\n  ]);\n  verify({'a.0': -1}, [\n    {a: [5, [-5, -20], 18]},\n    {a: [1, [10, 15], 20]}\n  ]);\n  // Similarly, this is just comparing [-5,-20] to [10, 15].\n  verify({'a.1': 1}, [\n    {a: [5, [-5, -20], 18]},\n    {a: [1, [10, 15], 20]}\n  ]);\n  verify({'a.1': -1}, [\n    {a: [1, [10, 15], 20]},\n    {a: [5, [-5, -20], 18]}\n  ]);\n  // Here we are just comparing [10,15] directly to [19,3] (and NOT also\n  // iterating over the numbers; this is implemented by setting dontIterate in\n  // makeLookupFunction).  So [10,15]<[19,3] even though 3 is the smallest\n  // number you can find there.\n  verify({'a.1': 1}, [\n    {a: [1, [10, 15], 20]},\n    {a: [5, [19, 3], 18]}\n  ]);\n  verify({'a.1': -1}, [\n    {a: [5, [19, 3], 18]},\n    {a: [1, [10, 15], 20]}\n  ]);\n  // Minimal elements are 1 and 5.\n  verify({a: 1}, [\n    {a: [1, [10, 15], 20]},\n    {a: [5, [19, 3], 18]}\n  ]);\n  // Maximal elements are [19,3] and [10,15] (because arrays sort higher than\n  // numbers), even though there's a 20 floating around.\n  verify({a: -1}, [\n    {a: [5, [19, 3], 18]},\n    {a: [1, [10, 15], 20]}\n  ]);\n  // Maximal elements are [10,15] and [3,19].  [10,15] is bigger even though 19\n  // is the biggest number in them, because array comparison is lexicographic.\n  verify({a: -1}, [\n    {a: [1, [10, 15], 20]},\n    {a: [5, [3, 19], 18]}\n  ]);\n\n  // (0,4) < (0,5), so they go in this order.  It's not correct to consider\n  // (0,3) as a sort key for the second document because they come from\n  // different a-branches.\n  verify({'a.x': 1, 'a.y': 1}, [\n    {a: [{x: 0, y: 4}]},\n    {a: [{x: 0, y: 5}, {x: 1, y: 3}]}\n  ]);\n\n  verify({'a.0.s': 1}, [\n    {a: [ {s: 1} ]},\n    {a: [ {s: 2} ]}\n  ]);\n});\n\nTinytest.add(\"minimongo - sort\", function (test) {\n  var c = new LocalCollection();\n  for (var i = 0; i < 50; i++)\n    for (var j = 0; j < 2; j++)\n      c.insert({a: i, b: j, _id: i + \"_\" + j});\n\n  test.equal(\n    c.find({a: {$gt: 10}}, {sort: {b: -1, a: 1}, limit: 5}).fetch(), [\n      {a: 11, b: 1, _id: \"11_1\"},\n      {a: 12, b: 1, _id: \"12_1\"},\n      {a: 13, b: 1, _id: \"13_1\"},\n      {a: 14, b: 1, _id: \"14_1\"},\n      {a: 15, b: 1, _id: \"15_1\"}]);\n\n  test.equal(\n    c.find({a: {$gt: 10}}, {sort: {b: -1, a: 1}, skip: 3, limit: 5}).fetch(), [\n      {a: 14, b: 1, _id: \"14_1\"},\n      {a: 15, b: 1, _id: \"15_1\"},\n      {a: 16, b: 1, _id: \"16_1\"},\n      {a: 17, b: 1, _id: \"17_1\"},\n      {a: 18, b: 1, _id: \"18_1\"}]);\n\n  test.equal(\n    c.find({a: {$gte: 20}}, {sort: {a: 1, b: -1}, skip: 50, limit: 5}).fetch(), [\n      {a: 45, b: 1, _id: \"45_1\"},\n      {a: 45, b: 0, _id: \"45_0\"},\n      {a: 46, b: 1, _id: \"46_1\"},\n      {a: 46, b: 0, _id: \"46_0\"},\n      {a: 47, b: 1, _id: \"47_1\"}]);\n});\n\nTinytest.add(\"minimongo - subkey sort\", function (test) {\n  var c = new LocalCollection();\n\n  // normal case\n  c.insert({a: {b: 2}});\n  c.insert({a: {b: 1}});\n  c.insert({a: {b: 3}});\n  test.equal(\n    _.pluck(c.find({}, {sort: {'a.b': -1}}).fetch(), 'a'),\n    [{b: 3}, {b: 2}, {b: 1}]);\n\n  // isn't an object\n  c.insert({a: 1});\n  test.equal(\n    _.pluck(c.find({}, {sort: {'a.b': 1}}).fetch(), 'a'),\n    [1, {b: 1}, {b: 2}, {b: 3}]);\n\n  // complex object\n  c.insert({a: {b: {c: 1}}});\n  test.equal(\n    _.pluck(c.find({}, {sort: {'a.b': -1}}).fetch(), 'a'),\n    [{b: {c: 1}}, {b: 3}, {b: 2}, {b: 1}, 1]);\n\n  // no such top level prop\n  c.insert({c: 1});\n  test.equal(\n    _.pluck(c.find({}, {sort: {'a.b': -1}}).fetch(), 'a'),\n    [{b: {c: 1}}, {b: 3}, {b: 2}, {b: 1}, 1, undefined]);\n\n  // no such mid level prop. just test that it doesn't throw.\n  test.equal(c.find({}, {sort: {'a.nope.c': -1}}).count(), 6);\n});\n\nTinytest.add(\"minimongo - array sort\", function (test) {\n  var c = new LocalCollection();\n\n  // \"up\" and \"down\" are the indices that the docs should have when sorted\n  // ascending and descending by \"a.x\" respectively. They are not reverses of\n  // each other: when sorting ascending, you use the minimum value you can find\n  // in the document, and when sorting descending, you use the maximum value you\n  // can find. So [1, 4] shows up in the 1 slot when sorting ascending and the 4\n  // slot when sorting descending.\n  //\n  // Similarly, \"selected\" is the index that the doc should have in the query\n  // that sorts ascending on \"a.x\" and selects {'a.x': {$gt: 1}}. In this case,\n  // the 1 in [1, 4] may not be used as a sort key.\n  c.insert({up: 1, down: 1, selected: 2, a: {x: [1, 4]}});\n  c.insert({up: 2, down: 2, selected: 0, a: [{x: [2]}, {x: 3}]});\n  c.insert({up: 0, down: 4,              a: {x: 0}});\n  c.insert({up: 3, down: 3, selected: 1, a: {x: 2.5}});\n  c.insert({up: 4, down: 0, selected: 3, a: {x: 5}});\n\n  // Test that the the documents in \"cursor\" contain values with the name\n  // \"field\" running from 0 to the max value of that name in the collection.\n  var testCursorMatchesField = function (cursor, field) {\n    var fieldValues = [];\n    c.find().forEach(function (doc) {\n      if (_.has(doc, field))\n        fieldValues.push(doc[field]);\n    });\n    test.equal(_.pluck(cursor.fetch(), field),\n               _.range(_.max(fieldValues) + 1));\n  };\n\n  testCursorMatchesField(c.find({}, {sort: {'a.x': 1}}), 'up');\n  testCursorMatchesField(c.find({}, {sort: {'a.x': -1}}), 'down');\n  testCursorMatchesField(c.find({'a.x': {$gt: 1}}, {sort: {'a.x': 1}}),\n                         'selected');\n});\n\nTinytest.add(\"minimongo - sort keys\", function (test) {\n  var keyListToObject = function (keyList) {\n    var obj = {};\n    _.each(keyList, function (key) {\n      obj[EJSON.stringify(key)] = true;\n    });\n    return obj;\n  };\n\n  var testKeys = function (sortSpec, doc, expectedKeyList) {\n    var expectedKeys = keyListToObject(expectedKeyList);\n    var sorter = new Minimongo.Sorter(sortSpec);\n\n    var actualKeyList = [];\n    sorter._generateKeysFromDoc(doc, function (key) {\n      actualKeyList.push(key);\n    });\n    var actualKeys = keyListToObject(actualKeyList);\n    test.equal(actualKeys, expectedKeys);\n  };\n\n  var testParallelError = function (sortSpec, doc) {\n    var sorter = new Minimongo.Sorter(sortSpec);\n    test.throws(function () {\n      sorter._generateKeysFromDoc(doc, function (){});\n    }, /parallel arrays/);\n  };\n\n  // Just non-array fields.\n  testKeys({'a.x': 1, 'a.y': 1},\n           {a: {x: 0, y: 5}},\n           [[0,5]]);\n\n  // Ensure that we don't get [0,3] and [1,5].\n  testKeys({'a.x': 1, 'a.y': 1},\n           {a: [{x: 0, y: 5}, {x: 1, y: 3}]},\n           [[0,5], [1,3]]);\n\n  // Ensure we can combine \"array fields\" with \"non-array fields\".\n  testKeys({'a.x': 1, 'a.y': 1, b: -1},\n           {a: [{x: 0, y: 5}, {x: 1, y: 3}], b: 42},\n           [[0,5,42], [1,3,42]]);\n  testKeys({b: -1, 'a.x': 1, 'a.y': 1},\n           {a: [{x: 0, y: 5}, {x: 1, y: 3}], b: 42},\n           [[42,0,5], [42,1,3]]);\n  testKeys({'a.x': 1, b: -1, 'a.y': 1},\n           {a: [{x: 0, y: 5}, {x: 1, y: 3}], b: 42},\n           [[0,42,5], [1,42,3]]);\n  testKeys({a: 1, b: 1},\n           {a: [1, 2, 3], b: 42},\n           [[1,42], [2,42], [3,42]]);\n\n  // Don't support multiple arrays at the same level.\n  testParallelError({a: 1, b: 1},\n                    {a: [1, 2, 3], b: [42]});\n\n  // We are MORE STRICT than Mongo here; Mongo supports this!\n  // XXX support this too  #NestedArraySort\n  testParallelError({'a.x': 1, 'a.y': 1},\n                    {a: [{x: 1, y: [2, 3]},\n                         {x: 2, y: [4, 5]}]});\n});\n\nTinytest.add(\"minimongo - sort key filter\", function (test) {\n  var testOrder = function (sortSpec, selector, doc1, doc2) {\n    var matcher = new Minimongo.Matcher(selector);\n    var sorter = new Minimongo.Sorter(sortSpec, {matcher: matcher});\n    var comparator = sorter.getComparator();\n    var comparison = comparator(doc1, doc2);\n    test.isTrue(comparison < 0);\n  };\n\n  testOrder({'a.x': 1}, {'a.x': {$gt: 1}},\n            {a: {x: 3}},\n            {a: {x: [1, 4]}});\n  testOrder({'a.x': 1}, {'a.x': {$gt: 0}},\n            {a: {x: [1, 4]}},\n            {a: {x: 3}});\n\n  var keyCompatible = function (sortSpec, selector, key, compatible) {\n    var matcher = new Minimongo.Matcher(selector);\n    var sorter = new Minimongo.Sorter(sortSpec, {matcher: matcher});\n    var actual = sorter._keyCompatibleWithSelector(key);\n    test.equal(actual, compatible);\n  };\n\n  keyCompatible({a: 1}, {a: 5}, [5], true);\n  keyCompatible({a: 1}, {a: 5}, [8], false);\n  keyCompatible({a: 1}, {a: {x: 5}}, [{x: 5}], true);\n  keyCompatible({a: 1}, {a: {x: 5}}, [{x: 5, y: 9}], false);\n  keyCompatible({'a.x': 1}, {a: {x: 5}}, [5], true);\n  // To confirm this:\n  //   > db.x.insert({_id: \"q\", a: [{x:1}, {x:5}], b: 2})\n  //   > db.x.insert({_id: \"w\", a: [{x:5}, {x:10}], b: 1})\n  //   > db.x.find({}).sort({'a.x': 1, b: 1})\n  //   { \"_id\" : \"q\", \"a\" : [  {  \"x\" : 1 },  {  \"x\" : 5 } ], \"b\" : 2 }\n  //   { \"_id\" : \"w\", \"a\" : [  {  \"x\" : 5 },  {  \"x\" : 10 } ], \"b\" : 1 }\n  //   > db.x.find({a: {x:5}}).sort({'a.x': 1, b: 1})\n  //   { \"_id\" : \"q\", \"a\" : [  {  \"x\" : 1 },  {  \"x\" : 5 } ], \"b\" : 2 }\n  //   { \"_id\" : \"w\", \"a\" : [  {  \"x\" : 5 },  {  \"x\" : 10 } ], \"b\" : 1 }\n  //   > db.x.find({'a.x': 5}).sort({'a.x': 1, b: 1})\n  //   { \"_id\" : \"w\", \"a\" : [  {  \"x\" : 5 },  {  \"x\" : 10 } ], \"b\" : 1 }\n  //   { \"_id\" : \"q\", \"a\" : [  {  \"x\" : 1 },  {  \"x\" : 5 } ], \"b\" : 2 }\n  // ie, only the last one manages to trigger the key compatibility code,\n  // not the previous one.  (The \"b\" sort is necessary because when the key\n  // compatibility code *does* kick in, both documents only end up with \"5\"\n  // for the first field as their only sort key, and we need to differentiate\n  // somehow...)\n  keyCompatible({'a.x': 1}, {a: {x: 5}}, [1], true);\n  keyCompatible({'a.x': 1}, {'a.x': 5}, [5], true);\n  keyCompatible({'a.x': 1}, {'a.x': 5}, [1], false);\n\n  // Regex key check.\n  keyCompatible({a: 1}, {a: /^foo+/}, ['foo'], true);\n  keyCompatible({a: 1}, {a: /^foo+/}, ['foooo'], true);\n  keyCompatible({a: 1}, {a: /^foo+/}, ['foooobar'], true);\n  keyCompatible({a: 1}, {a: /^foo+/}, ['afoooo'], false);\n  keyCompatible({a: 1}, {a: /^foo+/}, [''], false);\n  keyCompatible({a: 1}, {a: {$regex: \"^foo+\"}}, ['foo'], true);\n  keyCompatible({a: 1}, {a: {$regex: \"^foo+\"}}, ['foooo'], true);\n  keyCompatible({a: 1}, {a: {$regex: \"^foo+\"}}, ['foooobar'], true);\n  keyCompatible({a: 1}, {a: {$regex: \"^foo+\"}}, ['afoooo'], false);\n  keyCompatible({a: 1}, {a: {$regex: \"^foo+\"}}, [''], false);\n\n  keyCompatible({a: 1}, {a: /^foo+/i}, ['foo'], true);\n  // Key compatibility check appears to be turned off for regexps with flags.\n  keyCompatible({a: 1}, {a: /^foo+/i}, ['bar'], true);\n  keyCompatible({a: 1}, {a: /^foo+/m}, ['bar'], true);\n  keyCompatible({a: 1}, {a: {$regex: \"^foo+\", $options: \"i\"}}, ['bar'], true);\n  keyCompatible({a: 1}, {a: {$regex: \"^foo+\", $options: \"m\"}}, ['bar'], true);\n\n  // Multiple keys!\n  keyCompatible({a: 1, b: 1, c: 1},\n                {a: {$gt: 5}, c: {$lt: 3}}, [6, \"bla\", 2], true);\n  keyCompatible({a: 1, b: 1, c: 1},\n                {a: {$gt: 5}, c: {$lt: 3}}, [6, \"bla\", 4], false);\n  keyCompatible({a: 1, b: 1, c: 1},\n                {a: {$gt: 5}, c: {$lt: 3}}, [3, \"bla\", 1], false);\n  // No filtering is done (ie, all keys are compatible) if the first key isn't\n  // constrained.\n  keyCompatible({a: 1, b: 1, c: 1},\n                {c: {$lt: 3}}, [3, \"bla\", 4], true);\n});\n\nTinytest.add(\"minimongo - sort function\", function (test) {\n  var c = new LocalCollection();\n\n  c.insert({a: 1});\n  c.insert({a: 10});\n  c.insert({a: 5});\n  c.insert({a: 7});\n  c.insert({a: 2});\n  c.insert({a: 4});\n  c.insert({a: 3});\n\n  var sortFunction = function (doc1, doc2) {\n    return doc2.a - doc1.a;\n  };\n\n  test.equal(c.find({}, {sort: sortFunction}).fetch(), c.find({}).fetch().sort(sortFunction));\n  test.notEqual(c.find({}).fetch(), c.find({}).fetch().sort(sortFunction));\n  test.equal(c.find({}, {sort: {a: -1}}).fetch(), c.find({}).fetch().sort(sortFunction));\n});\n\nTinytest.add(\"minimongo - binary search\", function (test) {\n  var forwardCmp = function (a, b) {\n    return a - b;\n  };\n\n  var backwardCmp = function (a, b) {\n    return -1 * forwardCmp(a, b);\n  };\n\n  var checkSearch = function (cmp, array, value, expected, message) {\n    var actual = LocalCollection._binarySearch(cmp, array, value);\n    if (expected != actual) {\n      test.fail({type: \"minimongo-binary-search\",\n                 message: message + \" : Expected index \" + expected +\n                 \" but had \" + actual\n      });\n    }\n  };\n\n  var checkSearchForward = function (array, value, expected, message) {\n    checkSearch(forwardCmp, array, value, expected, message);\n  };\n  var checkSearchBackward = function (array, value, expected, message) {\n    checkSearch(backwardCmp, array, value, expected, message);\n  };\n\n  checkSearchForward([1, 2, 5, 7], 4, 2, \"Inner insert\");\n  checkSearchForward([1, 2, 3, 4], 3, 3, \"Inner insert, equal value\");\n  checkSearchForward([1, 2, 5], 4, 2, \"Inner insert, odd length\");\n  checkSearchForward([1, 3, 5, 6], 9, 4, \"End insert\");\n  checkSearchForward([1, 3, 5, 6], 0, 0, \"Beginning insert\");\n  checkSearchForward([1], 0, 0, \"Single array, less than.\");\n  checkSearchForward([1], 1, 1, \"Single array, equal.\");\n  checkSearchForward([1], 2, 1, \"Single array, greater than.\");\n  checkSearchForward([], 1, 0, \"Empty array\");\n  checkSearchForward([1, 1, 1, 2, 2, 2, 2], 1, 3, \"Highly degenerate array, lower\");\n  checkSearchForward([1, 1, 1, 2, 2, 2, 2], 2, 7, \"Highly degenerate array, upper\");\n  checkSearchForward([2, 2, 2, 2, 2, 2, 2], 1, 0, \"Highly degenerate array, lower\");\n  checkSearchForward([2, 2, 2, 2, 2, 2, 2], 2, 7, \"Highly degenerate array, equal\");\n  checkSearchForward([2, 2, 2, 2, 2, 2, 2], 3, 7, \"Highly degenerate array, upper\");\n\n  checkSearchBackward([7, 5, 2, 1], 4, 2, \"Backward: Inner insert\");\n  checkSearchBackward([4, 3, 2, 1], 3, 2, \"Backward: Inner insert, equal value\");\n  checkSearchBackward([5, 2, 1], 4, 1, \"Backward: Inner insert, odd length\");\n  checkSearchBackward([6, 5, 3, 1], 9, 0, \"Backward: Beginning insert\");\n  checkSearchBackward([6, 5, 3, 1], 0, 4, \"Backward: End insert\");\n  checkSearchBackward([1], 0, 1, \"Backward: Single array, less than.\");\n  checkSearchBackward([1], 1, 1, \"Backward: Single array, equal.\");\n  checkSearchBackward([1], 2, 0, \"Backward: Single array, greater than.\");\n  checkSearchBackward([], 1, 0, \"Backward: Empty array\");\n  checkSearchBackward([2, 2, 2, 2, 1, 1, 1], 1, 7, \"Backward: Degenerate array, lower\");\n  checkSearchBackward([2, 2, 2, 2, 1, 1, 1], 2, 4, \"Backward: Degenerate array, upper\");\n  checkSearchBackward([2, 2, 2, 2, 2, 2, 2], 1, 7, \"Backward: Highly degenerate array, upper\");\n  checkSearchBackward([2, 2, 2, 2, 2, 2, 2], 2, 7, \"Backward: Highly degenerate array, upper\");\n  checkSearchBackward([2, 2, 2, 2, 2, 2, 2], 3, 0, \"Backward: Highly degenerate array, upper\");\n});\n\nTinytest.add(\"minimongo - modify\", function (test) {\n  var modifyWithQuery = function (doc, query, mod, expected) {\n    var coll = new LocalCollection;\n    coll.insert(doc);\n    // The query is relevant for 'a.$.b'.\n    coll.update(query, mod);\n    var actual = coll.findOne();\n    delete actual._id;  // added by insert\n    test.equal(actual, expected, EJSON.stringify({input: doc, mod: mod}));\n  };\n  var modify = function (doc, mod, expected) {\n    modifyWithQuery(doc, {}, mod, expected);\n  };\n  var exceptionWithQuery = function (doc, query, mod) {\n    var coll = new LocalCollection;\n    coll.insert(doc);\n    test.throws(function () {\n      coll.update(query, mod);\n    });\n  };\n  var exception = function (doc, mod) {\n    exceptionWithQuery(doc, {}, mod);\n  };\n\n  var upsert = function (query, mod, expected) {\n    var coll = new LocalCollection;\n    \n    var result = coll.upsert(query, mod);\n    \n    var actual = coll.findOne();\n    \n    if (expected._id) {\n      test.equal(result.insertedId, expected._id);\n    }\n    else {\n      delete actual._id;\n    }\n    \n    test.equal(actual, expected);\n  };\n  \n  // document replacement\n  modify({}, {}, {});\n  modify({a: 12}, {}, {}); // tested against mongodb\n  modify({a: 12}, {a: 13}, {a:13});\n  modify({a: 12, b: 99}, {a: 13}, {a:13});\n  exception({a: 12}, {a: 13, $set: {b: 13}});\n  exception({a: 12}, {$set: {b: 13}, a: 13});\n\n  // keys\n  modify({}, {$set: {'a': 12}}, {a: 12});\n  modify({}, {$set: {'a.b': 12}}, {a: {b: 12}});\n  modify({}, {$set: {'a.b.c': 12}}, {a: {b: {c: 12}}});\n  modify({a: {d: 99}}, {$set: {'a.b.c': 12}}, {a: {d: 99, b: {c: 12}}});\n  modify({}, {$set: {'a.b.3.c': 12}}, {a: {b: {3: {c: 12}}}});\n  modify({a: {b: []}}, {$set: {'a.b.3.c': 12}}, {\n    a: {b: [null, null, null, {c: 12}]}});\n  exception({a: [null, null, null]}, {$set: {'a.1.b': 12}});\n  exception({a: [null, 1, null]}, {$set: {'a.1.b': 12}});\n  exception({a: [null, \"x\", null]}, {$set: {'a.1.b': 12}});\n  exception({a: [null, [], null]}, {$set: {'a.1.b': 12}});\n  modify({a: [null, null, null]}, {$set: {'a.3.b': 12}}, {\n    a: [null, null, null, {b: 12}]});\n  exception({a: []}, {$set: {'a.b': 12}});\n  exception({a: 12}, {$set: {'a.b': 99}}); // tested on mongo\n  exception({a: 'x'}, {$set: {'a.b': 99}});\n  exception({a: true}, {$set: {'a.b': 99}});\n  exception({a: null}, {$set: {'a.b': 99}});\n  modify({a: {}}, {$set: {'a.3': 12}}, {a: {'3': 12}});\n  modify({a: []}, {$set: {'a.3': 12}}, {a: [null, null, null, 12]});\n  exception({}, {$set: {'': 12}}); // tested on mongo\n  exception({}, {$set: {'.': 12}}); // tested on mongo\n  exception({}, {$set: {'a.': 12}}); // tested on mongo\n  exception({}, {$set: {'. ': 12}}); // tested on mongo\n  exception({}, {$inc: {'... ': 12}}); // tested on mongo\n  exception({}, {$set: {'a..b': 12}}); // tested on mongo\n  modify({a: [1,2,3]}, {$set: {'a.01': 99}}, {a: [1, 99, 3]});\n  modify({a: [1,{a: 98},3]}, {$set: {'a.01.b': 99}}, {a: [1,{a:98, b: 99},3]});\n  modify({}, {$set: {'2.a.b': 12}}, {'2': {'a': {'b': 12}}}); // tested\n  exception({x: []}, {$set: {'x.2..a': 99}});\n  modify({x: [null, null]}, {$set: {'x.2.a': 1}}, {x: [null, null, {a: 1}]});\n  exception({x: [null, null]}, {$set: {'x.1.a': 1}});\n\n  // a.$.b\n  modifyWithQuery({a: [{x: 2}, {x: 4}]}, {'a.x': 4}, {$set: {'a.$.z': 9}},\n                  {a: [{x: 2}, {x: 4, z: 9}]});\n  exception({a: [{x: 2}, {x: 4}]}, {$set: {'a.$.z': 9}});\n  exceptionWithQuery({a: [{x: 2}, {x: 4}], b: 5}, {b: 5}, {$set: {'a.$.z': 9}});\n  // can't have two $\n  exceptionWithQuery({a: [{x: [2]}]}, {'a.x': 2}, {$set: {'a.$.x.$': 9}});\n  modifyWithQuery({a: [5, 6, 7]}, {a: 6}, {$set: {'a.$': 9}}, {a: [5, 9, 7]});\n  modifyWithQuery({a: [{b: [{c: 9}, {c: 10}]}, {b: {c: 11}}]}, {'a.b.c': 10},\n                  {$unset: {'a.$.b': 1}}, {a: [{}, {b: {c: 11}}]});\n  modifyWithQuery({a: [{b: [{c: 9}, {c: 10}]}, {b: {c: 11}}]}, {'a.b.c': 11},\n                  {$unset: {'a.$.b': 1}},\n                  {a: [{b: [{c: 9}, {c: 10}]}, {}]});\n  modifyWithQuery({a: [1]}, {'a.0': 1}, {$set: {'a.$': 5}}, {a: [5]});\n  modifyWithQuery({a: [9]}, {a: {$mod: [2, 1]}}, {$set: {'a.$': 5}}, {a: [5]});\n  // Negatives don't set '$'.\n  exceptionWithQuery({a: [1]}, {$not: {a: 2}}, {$set: {'a.$': 5}});\n  exceptionWithQuery({a: [1]}, {'a.0': {$ne: 2}}, {$set: {'a.$': 5}});\n  // One $or clause works.\n  modifyWithQuery({a: [{x: 2}, {x: 4}]},\n                  {$or: [{'a.x': 4}]}, {$set: {'a.$.z': 9}},\n                  {a: [{x: 2}, {x: 4, z: 9}]});\n  // More $or clauses throw.\n  exceptionWithQuery({a: [{x: 2}, {x: 4}]},\n                     {$or: [{'a.x': 4}, {'a.x': 4}]},\n                     {$set: {'a.$.z': 9}});\n  // $and uses the last one.\n  modifyWithQuery({a: [{x: 1}, {x: 3}]},\n                  {$and: [{'a.x': 1}, {'a.x': 3}]},\n                  {$set: {'a.$.x': 5}},\n                  {a: [{x: 1}, {x: 5}]});\n  modifyWithQuery({a: [{x: 1}, {x: 3}]},\n                  {$and: [{'a.x': 3}, {'a.x': 1}]},\n                  {$set: {'a.$.x': 5}},\n                  {a: [{x: 5}, {x: 3}]});\n  // Same goes for the implicit AND of a document selector.\n  modifyWithQuery({a: [{x: 1}, {y: 3}]},\n                  {'a.x': 1, 'a.y': 3},\n                  {$set: {'a.$.z': 5}},\n                  {a: [{x: 1}, {y: 3, z: 5}]});\n  // with $near, make sure it finds the closest one\n  modifyWithQuery({a: [{b: [1,1]},\n                       {b: [ [3,3], [4,4] ]},\n                       {b: [9,9]}]},\n                  {'a.b': {$near: [5, 5]}},\n                  {$set: {'a.$.b': 'k'}},\n                  {a: [{b: [1,1]}, {b: 'k'}, {b: [9,9]}]});\n  modifyWithQuery({a: [{x: 1}, {y: 1}, {x: 1, y: 1}]},\n                  {a: {$elemMatch: {x: 1, y: 1}}},\n                  {$set: {'a.$.x': 2}},\n                  {a: [{x: 1}, {y: 1}, {x: 2, y: 1}]});\n  modifyWithQuery({a: [{b: [{x: 1}, {y: 1}, {x: 1, y: 1}]}]},\n                  {'a.b': {$elemMatch: {x: 1, y: 1}}},\n                  {$set: {'a.$.b': 3}},\n                  {a: [{b: 3}]});\n\n  // $inc\n  modify({a: 1, b: 2}, {$inc: {a: 10}}, {a: 11, b: 2});\n  modify({a: 1, b: 2}, {$inc: {c: 10}}, {a: 1, b: 2, c: 10});\n  exception({a: 1}, {$inc: {a: '10'}});\n  exception({a: 1}, {$inc: {a: true}});\n  exception({a: 1}, {$inc: {a: [10]}});\n  exception({a: '1'}, {$inc: {a: 10}});\n  exception({a: [1]}, {$inc: {a: 10}});\n  exception({a: {}}, {$inc: {a: 10}});\n  exception({a: false}, {$inc: {a: 10}});\n  exception({a: null}, {$inc: {a: 10}});\n  modify({a: [1, 2]}, {$inc: {'a.1': 10}}, {a: [1, 12]});\n  modify({a: [1, 2]}, {$inc: {'a.2': 10}}, {a: [1, 2, 10]});\n  modify({a: [1, 2]}, {$inc: {'a.3': 10}}, {a: [1, 2, null, 10]});\n  modify({a: {b: 2}}, {$inc: {'a.b': 10}}, {a: {b: 12}});\n  modify({a: {b: 2}}, {$inc: {'a.c': 10}}, {a: {b: 2, c: 10}});\n  exception({}, {$inc: {_id: 1}});\n\n  // $set\n  modify({a: 1, b: 2}, {$set: {a: 10}}, {a: 10, b: 2});\n  modify({a: 1, b: 2}, {$set: {c: 10}}, {a: 1, b: 2, c: 10});\n  modify({a: 1, b: 2}, {$set: {a: {c: 10}}}, {a: {c: 10}, b: 2});\n  modify({a: [1, 2], b: 2}, {$set: {a: [3, 4]}}, {a: [3, 4], b: 2});\n  modify({a: [1, 2, 3], b: 2}, {$set: {'a.1': [3, 4]}},\n         {a: [1, [3, 4], 3], b:2});\n  modify({a: [1], b: 2}, {$set: {'a.1': 9}}, {a: [1, 9], b: 2});\n  modify({a: [1], b: 2}, {$set: {'a.2': 9}}, {a: [1, null, 9], b: 2});\n  modify({a: {b: 1}}, {$set: {'a.c': 9}}, {a: {b: 1, c: 9}});\n  modify({}, {$set: {'x._id': 4}}, {x: {_id: 4}});\n  exception({}, {$set: {_id: 4}});\n  exception({_id: 4}, {$set: {_id: 4}});  // even not-changing _id is bad\n\n  // $unset\n  modify({}, {$unset: {a: 1}}, {});\n  modify({a: 1}, {$unset: {a: 1}}, {});\n  modify({a: 1, b: 2}, {$unset: {a: 1}}, {b: 2});\n  modify({a: 1, b: 2}, {$unset: {a: 0}}, {b: 2});\n  modify({a: 1, b: 2}, {$unset: {a: false}}, {b: 2});\n  modify({a: 1, b: 2}, {$unset: {a: null}}, {b: 2});\n  modify({a: 1, b: 2}, {$unset: {a: [1]}}, {b: 2});\n  modify({a: 1, b: 2}, {$unset: {a: {}}}, {b: 2});\n  modify({a: {b: 2, c: 3}}, {$unset: {'a.b': 1}}, {a: {c: 3}});\n  modify({a: [1, 2, 3]}, {$unset: {'a.1': 1}}, {a: [1, null, 3]}); // tested\n  modify({a: [1, 2, 3]}, {$unset: {'a.2': 1}}, {a: [1, 2, null]}); // tested\n  modify({a: [1, 2, 3]}, {$unset: {'a.x': 1}}, {a: [1, 2, 3]}); // tested\n  modify({a: {b: 1}}, {$unset: {'a.b.c.d': 1}}, {a: {b: 1}});\n  modify({a: {b: 1}}, {$unset: {'a.x.c.d': 1}}, {a: {b: 1}});\n  modify({a: {b: {c: 1}}}, {$unset: {'a.b.c': 1}}, {a: {b: {}}});\n  exception({}, {$unset: {_id: 1}});\n\n  // $push\n  modify({}, {$push: {a: 1}}, {a: [1]});\n  modify({a: []}, {$push: {a: 1}}, {a: [1]});\n  modify({a: [1]}, {$push: {a: 2}}, {a: [1, 2]});\n  exception({a: true}, {$push: {a: 1}});\n  modify({a: [1]}, {$push: {a: [2]}}, {a: [1, [2]]});\n  modify({a: []}, {$push: {'a.1': 99}}, {a: [null, [99]]}); // tested\n  modify({a: {}}, {$push: {'a.x': 99}}, {a: {x: [99]}});\n  modify({}, {$push: {a: {$each: [1, 2, 3]}}},\n         {a: [1, 2, 3]});\n  modify({a: []}, {$push: {a: {$each: [1, 2, 3]}}},\n         {a: [1, 2, 3]});\n  modify({a: [true]}, {$push: {a: {$each: [1, 2, 3]}}},\n         {a: [true, 1, 2, 3]});\n  // No positive numbers for $slice\n  exception({}, {$push: {a: {$each: [], $slice: 5}}});\n  modify({a: [true]}, {$push: {a: {$each: [1, 2, 3], $slice: -2}}},\n         {a: [2, 3]});\n  modify({a: [false, true]}, {$push: {a: {$each: [1], $slice: -2}}},\n         {a: [true, 1]});\n  modify(\n    {a: [{x: 3}, {x: 1}]},\n    {$push: {a: {\n      $each: [{x: 4}, {x: 2}],\n      $slice: -2,\n      $sort: {x: 1}\n    }}},\n    {a: [{x: 3}, {x: 4}]});\n  modify({}, {$push: {a: {$each: [1, 2, 3], $slice: 0}}}, {a: []});\n  modify({a: [1, 2]}, {$push: {a: {$each: [1, 2, 3], $slice: 0}}}, {a: []});\n  // $push with $position modifier\n  // No negative number for $position\n  exception({a: []}, {$push: {a: {$each: [0], $position: -1}}});\n  modify({a: [1, 2]}, {$push: {a: {$each: [0], $position: 0}}},\n    {a: [0, 1, 2]});\n  modify({a: [1, 2]}, {$push: {a: {$each: [-1, 0], $position: 0}}},\n    {a: [-1, 0, 1, 2]});\n  modify({a: [1, 3]}, {$push: {a: {$each: [2], $position: 1}}}, {a: [1, 2, 3]});\n  modify({a: [1, 4]}, {$push: {a: {$each: [2, 3], $position: 1}}},\n    {a: [1, 2, 3, 4]});\n  modify({a: [1, 2]}, {$push: {a: {$each: [3], $position: 3}}}, {a: [1, 2, 3]});\n  modify({a: [1, 2]}, {$push: {a: {$each: [3], $position: 99}}},\n    {a: [1, 2, 3]});\n  modify({a: [1, 2]}, {$push: {a: {$each: [3], $position: 99, $slice: -2}}},\n    {a: [2, 3]});\n  modify(\n    {a: [{x: 1}, {x: 2}]},\n    {$push: {a: {$each: [{x: 3}], $position: 0, $sort: {x: 1}, $slice: -3}}},\n    {a: [{x: 1}, {x: 2}, {x: 3}]}\n  );\n  modify(\n    {a: [{x: 1}, {x: 2}]},\n    {$push: {a: {$each: [{x: 3}], $position: 0, $sort: {x: 1}, $slice: 0}}},\n    {a: []}\n  );\n\n\n  // $pushAll\n  modify({}, {$pushAll: {a: [1]}}, {a: [1]});\n  modify({a: []}, {$pushAll: {a: [1]}}, {a: [1]});\n  modify({a: [1]}, {$pushAll: {a: [2]}}, {a: [1, 2]});\n  modify({}, {$pushAll: {a: [1, 2]}}, {a: [1, 2]});\n  modify({a: []}, {$pushAll: {a: [1, 2]}}, {a: [1, 2]});\n  modify({a: [1]}, {$pushAll: {a: [2, 3]}}, {a: [1, 2, 3]});\n  modify({}, {$pushAll: {a: []}}, {a: []});\n  modify({a: []}, {$pushAll: {a: []}}, {a: []});\n  modify({a: [1]}, {$pushAll: {a: []}}, {a: [1]});\n  exception({a: true}, {$pushAll: {a: [1]}});\n  exception({a: []}, {$pushAll: {a: 1}});\n  modify({a: []}, {$pushAll: {'a.1': [99]}}, {a: [null, [99]]});\n  modify({a: []}, {$pushAll: {'a.1': []}}, {a: [null, []]});\n  modify({a: {}}, {$pushAll: {'a.x': [99]}}, {a: {x: [99]}});\n  modify({a: {}}, {$pushAll: {'a.x': []}}, {a: {x: []}});\n\n  // $addToSet\n  modify({}, {$addToSet: {a: 1}}, {a: [1]});\n  modify({a: []}, {$addToSet: {a: 1}}, {a: [1]});\n  modify({a: [1]}, {$addToSet: {a: 2}}, {a: [1, 2]});\n  modify({a: [1, 2]}, {$addToSet: {a: 1}}, {a: [1, 2]});\n  modify({a: [1, 2]}, {$addToSet: {a: 2}}, {a: [1, 2]});\n  modify({a: [1, 2]}, {$addToSet: {a: 3}}, {a: [1, 2, 3]});\n  exception({a: true}, {$addToSet: {a: 1}});\n  modify({a: [1]}, {$addToSet: {a: [2]}}, {a: [1, [2]]});\n  modify({}, {$addToSet: {a: {x: 1}}}, {a: [{x: 1}]});\n  modify({a: [{x: 1}]}, {$addToSet: {a: {x: 1}}}, {a: [{x: 1}]});\n  modify({a: [{x: 1}]}, {$addToSet: {a: {x: 2}}}, {a: [{x: 1}, {x: 2}]});\n  modify({a: [{x: 1, y: 2}]}, {$addToSet: {a: {x: 1, y: 2}}},\n         {a: [{x: 1, y: 2}]});\n  modify({a: [{x: 1, y: 2}]}, {$addToSet: {a: {y: 2, x: 1}}},\n         {a: [{x: 1, y: 2}, {y: 2, x: 1}]});\n  modify({a: [1, 2]}, {$addToSet: {a: {$each: [3, 1, 4]}}}, {a: [1, 2, 3, 4]});\n  modify({a: [1, 2]}, {$addToSet: {a: {$each: [3, 1, 4], b: 12}}},\n         {a: [1, 2, 3, 4]}); // tested\n  modify({a: [1, 2]}, {$addToSet: {a: {b: 12, $each: [3, 1, 4]}}},\n         {a: [1, 2, {b: 12, $each: [3, 1, 4]}]}); // tested\n  modify({}, {$addToSet: {a: {$each: []}}}, {a: []});\n  modify({}, {$addToSet: {a: {$each: [1]}}}, {a: [1]});\n  modify({a: []}, {$addToSet: {'a.1': 99}}, {a: [null, [99]]});\n  modify({a: {}}, {$addToSet: {'a.x': 99}}, {a: {x: [99]}});\n\n  // $pop\n  modify({}, {$pop: {a: 1}}, {}); // tested\n  modify({}, {$pop: {a: -1}}, {}); // tested\n  modify({a: []}, {$pop: {a: 1}}, {a: []});\n  modify({a: []}, {$pop: {a: -1}}, {a: []});\n  modify({a: [1, 2, 3]}, {$pop: {a: 1}}, {a: [1, 2]});\n  modify({a: [1, 2, 3]}, {$pop: {a: 10}}, {a: [1, 2]});\n  modify({a: [1, 2, 3]}, {$pop: {a: .001}}, {a: [1, 2]});\n  modify({a: [1, 2, 3]}, {$pop: {a: 0}}, {a: [1, 2]});\n  modify({a: [1, 2, 3]}, {$pop: {a: \"stuff\"}}, {a: [1, 2]});\n  modify({a: [1, 2, 3]}, {$pop: {a: -1}}, {a: [2, 3]});\n  modify({a: [1, 2, 3]}, {$pop: {a: -10}}, {a: [2, 3]});\n  modify({a: [1, 2, 3]}, {$pop: {a: -.001}}, {a: [2, 3]});\n  exception({a: true}, {$pop: {a: 1}});\n  exception({a: true}, {$pop: {a: -1}});\n  modify({a: []}, {$pop: {'a.1': 1}}, {a: []}); // tested\n  modify({a: [1, [2, 3], 4]}, {$pop: {'a.1': 1}}, {a: [1, [2], 4]});\n  modify({a: {}}, {$pop: {'a.x': 1}}, {a: {}}); // tested\n  modify({a: {x: [2, 3]}}, {$pop: {'a.x': 1}}, {a: {x: [2]}});\n\n  // $pull\n  modify({}, {$pull: {a: 1}}, {});\n  modify({}, {$pull: {'a.x': 1}}, {});\n  modify({a: {}}, {$pull: {'a.x': 1}}, {a: {}});\n  exception({a: true}, {$pull: {a: 1}});\n  modify({a: [2, 1, 2]}, {$pull: {a: 1}}, {a: [2, 2]});\n  modify({a: [2, 1, 2]}, {$pull: {a: 2}}, {a: [1]});\n  modify({a: [2, 1, 2]}, {$pull: {a: 3}}, {a: [2, 1, 2]});\n  modify({a: [1, null, 2, null]}, {$pull: {a: null}}, {a: [1, 2]});\n  modify({a: []}, {$pull: {a: 3}}, {a: []});\n  modify({a: [[2], [2, 1], [3]]}, {$pull: {a: [2, 1]}},\n         {a: [[2], [3]]}); // tested\n  modify({a: [{b: 1, c: 2}, {b: 2, c: 2}]}, {$pull: {a: {b: 1}}},\n         {a: [{b: 2, c: 2}]});\n  modify({a: [{b: 1, c: 2}, {b: 2, c: 2}]}, {$pull: {a: {c: 2}}},\n         {a: []});\n  // XXX implement this functionality!\n  // probably same refactoring as $elemMatch?\n  // modify({a: [1, 2, 3, 4]}, {$pull: {$gt: 2}}, {a: [1,2]}); fails!\n\n  // $pullAll\n  modify({}, {$pullAll: {a: [1]}}, {});\n  modify({a: [1, 2, 3]}, {$pullAll: {a: []}}, {a: [1, 2, 3]});\n  modify({a: [1, 2, 3]}, {$pullAll: {a: [2]}}, {a: [1, 3]});\n  modify({a: [1, 2, 3]}, {$pullAll: {a: [2, 1]}}, {a: [3]});\n  modify({a: [1, 2, 3]}, {$pullAll: {a: [1, 2]}}, {a: [3]});\n  modify({}, {$pullAll: {'a.b.c': [2]}}, {});\n  exception({a: true}, {$pullAll: {a: [1]}});\n  exception({a: [1, 2, 3]}, {$pullAll: {a: 1}});\n  modify({x: [{a: 1}, {a: 1, b: 2}]}, {$pullAll: {x: [{a: 1}]}},\n         {x: [{a: 1, b: 2}]});\n\n  // $rename\n  modify({}, {$rename: {a: 'b'}}, {});\n  modify({a: [12]}, {$rename: {a: 'b'}}, {b: [12]});\n  modify({a: {b: 12}}, {$rename: {a: 'c'}}, {c: {b: 12}});\n  modify({a: {b: 12}}, {$rename: {'a.b': 'a.c'}}, {a: {c: 12}});\n  modify({a: {b: 12}}, {$rename: {'a.b': 'x'}}, {a: {}, x: 12}); // tested\n  modify({a: {b: 12}}, {$rename: {'a.b': 'q.r'}}, {a: {}, q: {r: 12}});\n  modify({a: {b: 12}}, {$rename: {'a.b': 'q.2.r'}}, {a: {}, q: {2: {r: 12}}});\n  modify({a: {b: 12}, q: {}}, {$rename: {'a.b': 'q.2.r'}},\n         {a: {}, q: {2: {r: 12}}});\n  exception({a: {b: 12}, q: []}, {$rename: {'a.b': 'q.2'}}); // tested\n  exception({a: {b: 12}, q: []}, {$rename: {'a.b': 'q.2.r'}}); // tested\n  // These strange MongoDB behaviors throw.\n  // modify({a: {b: 12}, q: []}, {$rename: {'q.1': 'x'}},\n  //        {a: {b: 12}, x: []}); // tested\n  // modify({a: {b: 12}, q: []}, {$rename: {'q.1.j': 'x'}},\n  //        {a: {b: 12}, x: []}); // tested\n  exception({}, {$rename: {'a': 'a'}});\n  exception({}, {$rename: {'a.b': 'a.b'}});\n  modify({a: 12, b: 13}, {$rename: {a: 'b'}}, {b: 12});\n\n  // $setOnInsert\n  modify({a: 0}, {$setOnInsert: {a: 12}}, {a: 0});\n  upsert({a: 12}, {$setOnInsert: {b: 12}}, {a: 12, b: 12});\n  upsert({a: 12}, {$setOnInsert: {_id: 'test'}}, {_id: 'test', a: 12});\n  \n  exception({}, {$set: {_id: 'bad'}});\n  \n  // $bit\n  // unimplemented\n\n  // XXX test case sensitivity of modops\n  // XXX for each (most) modop, test that it performs a deep copy\n});\n\n// XXX test update() (selecting docs, multi, upsert..)\n\nTinytest.add(\"minimongo - observe ordered\", function (test) {\n  var operations = [];\n  var cbs = log_callbacks(operations);\n  var handle;\n\n  var c = new LocalCollection();\n  handle = c.find({}, {sort: {a: 1}}).observe(cbs);\n  test.isTrue(handle.collection === c);\n\n  c.insert({_id: 'foo', a:1});\n  test.equal(operations.shift(), ['added', {a:1}, 0, null]);\n  c.update({a:1}, {$set: {a: 2}});\n  test.equal(operations.shift(), ['changed', {a:2}, 0, {a:1}]);\n  c.insert({a:10});\n  test.equal(operations.shift(), ['added', {a:10}, 1, null]);\n  c.update({}, {$inc: {a: 1}}, {multi: true});\n  test.equal(operations.shift(), ['changed', {a:3}, 0, {a:2}]);\n  test.equal(operations.shift(), ['changed', {a:11}, 1, {a:10}]);\n  c.update({a:11}, {a:1});\n  test.equal(operations.shift(), ['changed', {a:1}, 1, {a:11}]);\n  test.equal(operations.shift(), ['moved', {a:1}, 1, 0, 'foo']);\n  c.remove({a:2});\n  test.equal(operations.shift(), undefined);\n  c.remove({a:3});\n  test.equal(operations.shift(), ['removed', 'foo', 1, {a:3}]);\n\n  // test stop\n  handle.stop();\n  var idA2 = Random.id();\n  c.insert({_id: idA2, a:2});\n  test.equal(operations.shift(), undefined);\n\n  // test initial inserts (and backwards sort)\n  handle = c.find({}, {sort: {a: -1}}).observe(cbs);\n  test.equal(operations.shift(), ['added', {a:2}, 0, null]);\n  test.equal(operations.shift(), ['added', {a:1}, 1, null]);\n  handle.stop();\n\n  // test _suppress_initial\n  handle = c.find({}, {sort: {a: -1}}).observe(_.extend({\n    _suppress_initial: true}, cbs));\n  test.equal(operations.shift(), undefined);\n  c.insert({a:100});\n  test.equal(operations.shift(), ['added', {a:100}, 0, idA2]);\n  handle.stop();\n\n  // test skip and limit.\n  c.remove({});\n  handle = c.find({}, {sort: {a: 1}, skip: 1, limit: 2}).observe(cbs);\n  test.equal(operations.shift(), undefined);\n  c.insert({a:1});\n  test.equal(operations.shift(), undefined);\n  c.insert({_id: 'foo', a:2});\n  test.equal(operations.shift(), ['added', {a:2}, 0, null]);\n  c.insert({a:3});\n  test.equal(operations.shift(), ['added', {a:3}, 1, null]);\n  c.insert({a:4});\n  test.equal(operations.shift(), undefined);\n  c.update({a:1}, {a:0});\n  test.equal(operations.shift(), undefined);\n  c.update({a:0}, {a:5});\n  test.equal(operations.shift(), ['removed', 'foo', 0, {a:2}]);\n  test.equal(operations.shift(), ['added', {a:4}, 1, null]);\n  c.update({a:3}, {a:3.5});\n  test.equal(operations.shift(), ['changed', {a:3.5}, 0, {a:3}]);\n  handle.stop();\n\n  // test observe limit with pre-existing docs\n  c.remove({});\n  c.insert({a: 1});\n  c.insert({_id: 'two', a: 2});\n  c.insert({a: 3});\n  handle = c.find({}, {sort: {a: 1}, limit: 2}).observe(cbs);\n  test.equal(operations.shift(), ['added', {a:1}, 0, null]);\n  test.equal(operations.shift(), ['added', {a:2}, 1, null]);\n  test.equal(operations.shift(), undefined);\n  c.remove({a: 2});\n  test.equal(operations.shift(), ['removed', 'two', 1, {a:2}]);\n  test.equal(operations.shift(), ['added', {a:3}, 1, null]);\n  test.equal(operations.shift(), undefined);\n  handle.stop();\n\n  // test _no_indices\n\n  c.remove({});\n  handle = c.find({}, {sort: {a: 1}}).observe(_.extend(cbs, {_no_indices: true}));\n  c.insert({_id: 'foo', a:1});\n  test.equal(operations.shift(), ['added', {a:1}, -1, null]);\n  c.update({a:1}, {$set: {a: 2}});\n  test.equal(operations.shift(), ['changed', {a:2}, -1, {a:1}]);\n  c.insert({a:10});\n  test.equal(operations.shift(), ['added', {a:10}, -1, null]);\n  c.update({}, {$inc: {a: 1}}, {multi: true});\n  test.equal(operations.shift(), ['changed', {a:3}, -1, {a:2}]);\n  test.equal(operations.shift(), ['changed', {a:11}, -1, {a:10}]);\n  c.update({a:11}, {a:1});\n  test.equal(operations.shift(), ['changed', {a:1}, -1, {a:11}]);\n  test.equal(operations.shift(), ['moved', {a:1}, -1, -1, 'foo']);\n  c.remove({a:2});\n  test.equal(operations.shift(), undefined);\n  c.remove({a:3});\n  test.equal(operations.shift(), ['removed', 'foo', -1, {a:3}]);\n  handle.stop();\n});\n\n_.each([true, false], function (ordered) {\n  Tinytest.add(\"minimongo - observe ordered: \" + ordered, function (test) {\n    var c = new LocalCollection();\n\n    var ev = \"\";\n    var makecb = function (tag) {\n      var ret = {};\n      _.each([\"added\", \"changed\", \"removed\"], function (fn) {\n        var fnName = ordered ? fn + \"At\" : fn;\n        ret[fnName] = function (doc) {\n          ev = (ev + fn.substr(0, 1) + tag + doc._id + \"_\");\n        };\n      });\n      return ret;\n    };\n    var expect = function (x) {\n      test.equal(ev, x);\n      ev = \"\";\n    };\n\n    c.insert({_id: 1, name: \"strawberry\", tags: [\"fruit\", \"red\", \"squishy\"]});\n    c.insert({_id: 2, name: \"apple\", tags: [\"fruit\", \"red\", \"hard\"]});\n    c.insert({_id: 3, name: \"rose\", tags: [\"flower\", \"red\", \"squishy\"]});\n\n    // This should work equally well for ordered and unordered observations\n    // (because the callbacks don't look at indices and there's no 'moved'\n    // callback).\n    var handle = c.find({tags: \"flower\"}).observe(makecb('a'));\n    expect(\"aa3_\");\n    c.update({name: \"rose\"}, {$set: {tags: [\"bloom\", \"red\", \"squishy\"]}});\n    expect(\"ra3_\");\n    c.update({name: \"rose\"}, {$set: {tags: [\"flower\", \"red\", \"squishy\"]}});\n    expect(\"aa3_\");\n    c.update({name: \"rose\"}, {$set: {food: false}});\n    expect(\"ca3_\");\n    c.remove({});\n    expect(\"ra3_\");\n    c.insert({_id: 4, name: \"daisy\", tags: [\"flower\"]});\n    expect(\"aa4_\");\n    handle.stop();\n    // After calling stop, no more callbacks are called.\n    c.insert({_id: 5, name: \"iris\", tags: [\"flower\"]});\n    expect(\"\");\n\n    // Test that observing a lookup by ID works.\n    handle = c.find(4).observe(makecb('b'));\n    expect('ab4_');\n    c.update(4, {$set: {eek: 5}});\n    expect('cb4_');\n    handle.stop();\n\n    // Test observe with reactive: false.\n    handle = c.find({tags: \"flower\"}, {reactive: false}).observe(makecb('c'));\n    expect('ac4_ac5_');\n    // This insert shouldn't trigger a callback because it's not reactive.\n    c.insert({_id: 6, name: \"river\", tags: [\"flower\"]});\n    expect('');\n    handle.stop();\n  });\n});\n\n\nTinytest.add(\"minimongo - saveOriginals\", function (test) {\n  // set up some data\n  var c = new LocalCollection(),\n      count;\n  c.insert({_id: 'foo', x: 'untouched'});\n  c.insert({_id: 'bar', x: 'updateme'});\n  c.insert({_id: 'baz', x: 'updateme'});\n  c.insert({_id: 'quux', y: 'removeme'});\n  c.insert({_id: 'whoa', y: 'removeme'});\n\n  // Save originals and make some changes.\n  c.saveOriginals();\n  c.insert({_id: \"hooray\", z: 'insertme'});\n  c.remove({y: 'removeme'});\n  count = c.update({x: 'updateme'}, {$set: {z: 5}}, {multi: true});\n  c.update('bar', {$set: {k: 7}});  // update same doc twice\n\n  // Verify returned count is correct\n  test.equal(count, 2);\n\n  // Verify the originals.\n  var originals = c.retrieveOriginals();\n  var affected = ['bar', 'baz', 'quux', 'whoa', 'hooray'];\n  test.equal(originals.size(), _.size(affected));\n  _.each(affected, function (id) {\n    test.isTrue(originals.has(id));\n  });\n  test.equal(originals.get('bar'), {_id: 'bar', x: 'updateme'});\n  test.equal(originals.get('baz'), {_id: 'baz', x: 'updateme'});\n  test.equal(originals.get('quux'), {_id: 'quux', y: 'removeme'});\n  test.equal(originals.get('whoa'), {_id: 'whoa', y: 'removeme'});\n  test.equal(originals.get('hooray'), undefined);\n\n  // Verify that changes actually occured.\n  test.equal(c.find().count(), 4);\n  test.equal(c.findOne('foo'), {_id: 'foo', x: 'untouched'});\n  test.equal(c.findOne('bar'), {_id: 'bar', x: 'updateme', z: 5, k: 7});\n  test.equal(c.findOne('baz'), {_id: 'baz', x: 'updateme', z: 5});\n  test.equal(c.findOne('hooray'), {_id: 'hooray', z: 'insertme'});\n\n  // The next call doesn't get the same originals again.\n  c.saveOriginals();\n  originals = c.retrieveOriginals();\n  test.isTrue(originals);\n  test.isTrue(originals.empty());\n\n  // Insert and remove a document during the period.\n  c.saveOriginals();\n  c.insert({_id: 'temp', q: 8});\n  c.remove('temp');\n  originals = c.retrieveOriginals();\n  test.equal(originals.size(), 1);\n  test.isTrue(originals.has('temp'));\n  test.equal(originals.get('temp'), undefined);\n});\n\nTinytest.add(\"minimongo - saveOriginals errors\", function (test) {\n  var c = new LocalCollection();\n  // Can't call retrieve before save.\n  test.throws(function () { c.retrieveOriginals(); });\n  c.saveOriginals();\n  // Can't call save twice.\n  test.throws(function () { c.saveOriginals(); });\n});\n\nTinytest.add(\"minimongo - objectid transformation\", function (test) {\n  var testId = function (item) {\n    test.equal(item, MongoID.idParse(MongoID.idStringify(item)));\n  };\n  var randomOid = new MongoID.ObjectID();\n  testId(randomOid);\n  testId(\"FOO\");\n  testId(\"ffffffffffff\");\n  testId(\"0987654321abcdef09876543\");\n  testId(new MongoID.ObjectID());\n  testId(\"--a string\");\n\n  test.equal(\"ffffffffffff\", MongoID.idParse(MongoID.idStringify(\"ffffffffffff\")));\n});\n\n\nTinytest.add(\"minimongo - objectid\", function (test) {\n  var randomOid = new MongoID.ObjectID();\n  var anotherRandomOid = new MongoID.ObjectID();\n  test.notEqual(randomOid, anotherRandomOid);\n  test.throws(function() { new MongoID.ObjectID(\"qqqqqqqqqqqqqqqqqqqqqqqq\");});\n  test.throws(function() { new MongoID.ObjectID(\"ABCDEF\"); });\n  test.equal(randomOid, new MongoID.ObjectID(randomOid.valueOf()));\n});\n\nTinytest.add(\"minimongo - pause\", function (test) {\n  var operations = [];\n  var cbs = log_callbacks(operations);\n\n  var c = new LocalCollection();\n  var h = c.find({}).observe(cbs);\n\n  // remove and add cancel out.\n  c.insert({_id: 1, a: 1});\n  test.equal(operations.shift(), ['added', {a:1}, 0, null]);\n\n  c.pauseObservers();\n\n  c.remove({_id: 1});\n  test.length(operations, 0);\n  c.insert({_id: 1, a: 1});\n  test.length(operations, 0);\n\n  c.resumeObservers();\n  test.length(operations, 0);\n\n\n  // two modifications become one\n  c.pauseObservers();\n\n  c.update({_id: 1}, {a: 2});\n  c.update({_id: 1}, {a: 3});\n\n  c.resumeObservers();\n  test.equal(operations.shift(), ['changed', {a:3}, 0, {a:1}]);\n  test.length(operations, 0);\n\n  // test special case for remove({})\n  c.pauseObservers();\n  test.equal(c.remove({}), 1);\n  test.length(operations, 0);\n  c.resumeObservers();\n  test.equal(operations.shift(), ['removed', 1, 0, {a:3}]);\n  test.length(operations, 0);\n\n  h.stop();\n});\n\nTinytest.add(\"minimongo - ids matched by selector\", function (test) {\n  var check = function (selector, ids) {\n    var idsFromSelector = LocalCollection._idsMatchedBySelector(selector);\n    // XXX normalize order, in a way that also works for ObjectIDs?\n    test.equal(idsFromSelector, ids);\n  };\n  check(\"foo\", [\"foo\"]);\n  check({_id: \"foo\"}, [\"foo\"]);\n  var oid1 = new MongoID.ObjectID();\n  check(oid1, [oid1]);\n  check({_id: oid1}, [oid1]);\n  check({_id: \"foo\", x: 42}, [\"foo\"]);\n  check({}, null);\n  check({_id: {$in: [\"foo\", oid1]}}, [\"foo\", oid1]);\n  check({_id: {$ne: \"foo\"}}, null);\n  // not actually valid, but works for now...\n  check({$and: [\"foo\"]}, [\"foo\"]);\n  check({$and: [{x: 42}, {_id: oid1}]}, [oid1]);\n  check({$and: [{x: 42}, {_id: {$in: [oid1]}}]}, [oid1]);\n});\n\nTinytest.add(\"minimongo - reactive stop\", function (test) {\n  var coll = new LocalCollection();\n  coll.insert({_id: 'A'});\n  coll.insert({_id: 'B'});\n  coll.insert({_id: 'C'});\n\n  var addBefore = function (str, newChar, before) {\n    var idx = str.indexOf(before);\n    if (idx === -1)\n      return str + newChar;\n    return str.slice(0, idx) + newChar + str.slice(idx);\n  };\n\n  var x, y;\n  var sortOrder = ReactiveVar(1);\n\n  var c = Tracker.autorun(function () {\n    var q = coll.find({}, {sort: {_id: sortOrder.get()}});\n    x = \"\";\n    q.observe({ addedAt: function (doc, atIndex, before) {\n      x = addBefore(x, doc._id, before);\n    }});\n    y = \"\";\n    q.observeChanges({ addedBefore: function (id, fields, before) {\n      y = addBefore(y, id, before);\n    }});\n  });\n\n  test.equal(x, \"ABC\");\n  test.equal(y, \"ABC\");\n\n  sortOrder.set(-1);\n  test.equal(x, \"ABC\");\n  test.equal(y, \"ABC\");\n  Tracker.flush();\n  test.equal(x, \"CBA\");\n  test.equal(y, \"CBA\");\n\n  coll.insert({_id: 'D'});\n  coll.insert({_id: 'E'});\n  test.equal(x, \"EDCBA\");\n  test.equal(y, \"EDCBA\");\n\n  c.stop();\n  // stopping kills the observes immediately\n  coll.insert({_id: 'F'});\n  test.equal(x, \"EDCBA\");\n  test.equal(y, \"EDCBA\");\n});\n\nTinytest.add(\"minimongo - immediate invalidate\", function (test) {\n  var coll = new LocalCollection();\n  coll.insert({_id: 'A'});\n\n  // This has two separate findOnes.  findOne() uses skip/limit, which means\n  // that its response to an update() call involves a recompute. We used to have\n  // a bug where we would first calculate all the calls that need to be\n  // recomputed, then recompute them one by one, without checking to see if the\n  // callbacks from recomputing one query stopped the second query, which\n  // crashed.\n  var c = Tracker.autorun(function () {\n    coll.findOne('A');\n    coll.findOne('A');\n  });\n\n  coll.update('A', {$set: {x: 42}});\n\n  c.stop();\n});\n\n\nTinytest.add(\"minimongo - count on cursor with limit\", function(test){\n  var coll = new LocalCollection(), count;\n\n  coll.insert({_id: 'A'});\n  coll.insert({_id: 'B'});\n  coll.insert({_id: 'C'});\n  coll.insert({_id: 'D'});\n\n  var c = Tracker.autorun(function (c) {\n    var cursor = coll.find({_id: {$exists: true}}, {sort: {_id: 1}, limit: 3});\n    count = cursor.count();\n  });\n\n  test.equal(count, 3);\n\n  coll.remove('A'); // still 3 in the collection\n  Tracker.flush();\n  test.equal(count, 3);\n\n  coll.remove('B'); // expect count now 2\n  Tracker.flush();\n  test.equal(count, 2);\n\n\n  coll.insert({_id: 'A'}); // now 3 again\n  Tracker.flush();\n  test.equal(count, 3);\n\n  coll.insert({_id: 'B'}); // now 4 entries, but count should be 3 still\n  Tracker.flush();\n  test.equal(count, 3);\n\n  c.stop();\n});\n\nTinytest.add(\"minimongo - reactive count with cached cursor\", function (test) {\n  var coll = new LocalCollection;\n  var cursor = coll.find({});\n  var firstAutorunCount, secondAutorunCount;\n  Tracker.autorun(function(){\n    firstAutorunCount = cursor.count();\n  });\n  Tracker.autorun(function(){\n    secondAutorunCount = coll.find({}).count();\n  });\n  test.equal(firstAutorunCount, 0);\n  test.equal(secondAutorunCount, 0);\n  coll.insert({i: 1});\n  coll.insert({i: 2});\n  coll.insert({i: 3});\n  Tracker.flush();\n  test.equal(firstAutorunCount, 3);\n  test.equal(secondAutorunCount, 3);\n});\n\nTinytest.add(\"minimongo - $near operator tests\", function (test) {\n  var coll = new LocalCollection();\n  coll.insert({ rest: { loc: [2, 3] } });\n  coll.insert({ rest: { loc: [-3, 3] } });\n  coll.insert({ rest: { loc: [5, 5] } });\n\n  test.equal(coll.find({ 'rest.loc': { $near: [0, 0], $maxDistance: 30 } }).count(), 3);\n  test.equal(coll.find({ 'rest.loc': { $near: [0, 0], $maxDistance: 4 } }).count(), 1);\n  var points = coll.find({ 'rest.loc': { $near: [0, 0], $maxDistance: 6 } }).fetch();\n  _.each(points, function (point, i, points) {\n    test.isTrue(!i || distance([0, 0], point.rest.loc) >= distance([0, 0], points[i - 1].rest.loc));\n  });\n\n  function distance(a, b) {\n    var x = a[0] - b[0];\n    var y = a[1] - b[1];\n    return Math.sqrt(x * x + y * y);\n  }\n\n  // GeoJSON tests\n  coll = new LocalCollection();\n  var data = [{ \"category\" : \"BURGLARY\", \"descript\" : \"BURGLARY OF STORE, FORCIBLE ENTRY\", \"address\" : \"100 Block of 10TH ST\", \"location\" : { \"type\" : \"Point\", \"coordinates\" : [  -122.415449723856,  37.7749518087273 ] } },\n    { \"category\" : \"WEAPON LAWS\", \"descript\" : \"POSS OF PROHIBITED WEAPON\", \"address\" : \"900 Block of MINNA ST\", \"location\" : { \"type\" : \"Point\", \"coordinates\" : [  -122.415386041221,  37.7747879744156 ] } },\n    { \"category\" : \"LARCENY/THEFT\", \"descript\" : \"GRAND THEFT OF PROPERTY\", \"address\" : \"900 Block of MINNA ST\", \"location\" : { \"type\" : \"Point\", \"coordinates\" : [  -122.41538270191,  37.774683628213 ] } },\n    { \"category\" : \"LARCENY/THEFT\", \"descript\" : \"PETTY THEFT FROM LOCKED AUTO\", \"address\" : \"900 Block of MINNA ST\", \"location\" : { \"type\" : \"Point\", \"coordinates\" : [  -122.415396041221,  37.7747879744156 ] } },\n    { \"category\" : \"OTHER OFFENSES\", \"descript\" : \"POSSESSION OF BURGLARY TOOLS\", \"address\" : \"900 Block of MINNA ST\", \"location\" : { \"type\" : \"Point\", \"coordinates\" : [  -122.415386041221,  37.7747879734156 ] } }\n  ];\n\n  _.each(data, function (x, i) { coll.insert(_.extend(x, { x: i })); });\n\n  var close15 = coll.find({ location: { $near: {\n    $geometry: { type: \"Point\",\n                 coordinates: [-122.4154282, 37.7746115] },\n    $maxDistance: 15 } } }).fetch();\n  test.length(close15, 1);\n  test.equal(close15[0].descript, \"GRAND THEFT OF PROPERTY\");\n\n  var close20 = coll.find({ location: { $near: {\n    $geometry: { type: \"Point\",\n                 coordinates: [-122.4154282, 37.7746115] },\n    $maxDistance: 20 } } }).fetch();\n  test.length(close20, 4);\n  test.equal(close20[0].descript, \"GRAND THEFT OF PROPERTY\");\n  test.equal(close20[1].descript, \"PETTY THEFT FROM LOCKED AUTO\");\n  test.equal(close20[2].descript, \"POSSESSION OF BURGLARY TOOLS\");\n  test.equal(close20[3].descript, \"POSS OF PROHIBITED WEAPON\");\n\n  // Any combinations of $near with $or/$and/$nor/$not should throw an error\n  test.throws(function () {\n    coll.find({ location: {\n      $not: {\n        $near: {\n          $geometry: {\n            type: \"Point\",\n            coordinates: [-122.4154282, 37.7746115]\n          }, $maxDistance: 20 } } } });\n  });\n  test.throws(function () {\n    coll.find({\n      $and: [ { location: { $near: { $geometry: { type: \"Point\", coordinates: [-122.4154282, 37.7746115] }, $maxDistance: 20 }}},\n              { x: 0 }]\n    });\n  });\n  test.throws(function () {\n    coll.find({\n      $or: [ { location: { $near: { $geometry: { type: \"Point\", coordinates: [-122.4154282, 37.7746115] }, $maxDistance: 20 }}},\n             { x: 0 }]\n    });\n  });\n  test.throws(function () {\n    coll.find({\n      $nor: [ { location: { $near: { $geometry: { type: \"Point\", coordinates: [-122.4154282, 37.7746115] }, $maxDistance: 1 }}},\n              { x: 0 }]\n    });\n  });\n  test.throws(function () {\n    coll.find({\n      $and: [{\n        $and: [{\n          location: {\n            $near: {\n              $geometry: {\n                type: \"Point\",\n                coordinates: [-122.4154282, 37.7746115]\n              },\n              $maxDistance: 1\n            }\n          }\n        }]\n      }]\n    });\n  });\n\n  // array tests\n  coll = new LocalCollection();\n  coll.insert({\n    _id: \"x\",\n    k: 9,\n    a: [\n      {b: [\n        [100, 100],\n        [1,  1]]},\n      {b: [150,  150]}]});\n  coll.insert({\n    _id: \"y\",\n    k: 9,\n    a: {b: [5, 5]}});\n  var testNear = function (near, md, expected) {\n    test.equal(\n      _.pluck(\n        coll.find({'a.b': {$near: near, $maxDistance: md}}).fetch(), '_id'),\n      expected);\n  };\n  testNear([149, 149], 4, ['x']);\n  testNear([149, 149], 1000, ['x', 'y']);\n  // It's important that we figure out that 'x' is closer than 'y' to [2,2] even\n  // though the first within-1000 point in 'x' (ie, [100,100]) is farther than\n  // 'y'.\n  testNear([2, 2], 1000, ['x', 'y']);\n\n  // Ensure that distance is used as a tie-breaker for sort.\n  test.equal(\n    _.pluck(coll.find({'a.b': {$near: [1, 1]}}, {sort: {k: 1}}).fetch(), '_id'),\n    ['x', 'y']);\n  test.equal(\n    _.pluck(coll.find({'a.b': {$near: [5, 5]}}, {sort: {k: 1}}).fetch(), '_id'),\n    ['y', 'x']);\n\n  var operations = [];\n  var cbs = log_callbacks(operations);\n  var handle = coll.find({'a.b': {$near: [7,7]}}).observe(cbs);\n\n  test.length(operations, 2);\n  test.equal(operations.shift(), ['added', {k:9, a:{b:[5,5]}}, 0, null]);\n  test.equal(operations.shift(),\n             ['added', {k: 9, a:[{b:[[100,100],[1,1]]},{b:[150,150]}]},\n              1, null]);\n  // This needs to be inserted in the MIDDLE of the two existing ones.\n  coll.insert({a: {b: [3,3]}});\n  test.length(operations, 1);\n  test.equal(operations.shift(), ['added', {a: {b: [3, 3]}}, 1, 'x']);\n\n  handle.stop();\n});\n\n// Regression test for #4377. Previously, \"replace\" updates didn't clone the\n// argument.\nTinytest.add(\"minimongo - update should clone\", function (test) {\n  var x = [];\n  var coll = new LocalCollection;\n  var id = coll.insert({});\n  coll.update(id, {x: x});\n  x.push(1);\n  test.equal(coll.findOne(id), {_id: id, x: []});\n});\n\n// See #2275.\nTinytest.add(\"minimongo - fetch in observe\", function (test) {\n  var coll = new LocalCollection;\n  var callbackInvoked = false;\n  var observe = coll.find().observeChanges({\n    added: function (id, fields) {\n      callbackInvoked = true;\n      test.equal(fields, {foo: 1});\n      var doc = coll.findOne({foo: 1});\n      test.isTrue(doc);\n      test.equal(doc.foo, 1);\n    }\n  });\n  test.isFalse(callbackInvoked);\n  var computation = Tracker.autorun(function (computation) {\n    if (computation.firstRun) {\n      coll.insert({foo: 1});\n    }\n  });\n  test.isTrue(callbackInvoked);\n  observe.stop();\n  computation.stop();\n});\n\n// See #2254\nTinytest.add(\"minimongo - fine-grained reactivity of observe with fields projection\", function (test) {\n  var X = new LocalCollection;\n  var id = \"asdf\";\n  X.insert({_id: id, foo: {bar: 123}});\n\n  var callbackInvoked = false;\n  var obs = X.find(id, {fields: {'foo.bar': 1}}).observeChanges({\n    changed: function (id, fields) {\n      callbackInvoked = true;\n    }\n  });\n\n  test.isFalse(callbackInvoked);\n  X.update(id, {$set: {'foo.baz': 456}});\n  test.isFalse(callbackInvoked);\n\n  obs.stop();\n});\nTinytest.add(\"minimongo - fine-grained reactivity of query with fields projection\", function (test) {\n  var X = new LocalCollection;\n  var id = \"asdf\";\n  X.insert({_id: id, foo: {bar: 123}});\n\n  var callbackInvoked = false;\n  var computation = Tracker.autorun(function () {\n    callbackInvoked = true;\n    return X.findOne(id, { fields: { 'foo.bar': 1 } });\n  });\n  test.isTrue(callbackInvoked);\n  callbackInvoked = false;\n  X.update(id, {$set: {'foo.baz': 456}});\n  test.isFalse(callbackInvoked);\n  X.update(id, {$set: {'foo.bar': 124}});\n  Tracker.flush();\n  test.isTrue(callbackInvoked);\n\n  computation.stop();\n});\n\n// Tests that the logic in `LocalCollection.prototype.update`\n// correctly deals with count() on a cursor with skip or limit (since\n// then the result set is an IdMap, not an array)\nTinytest.add(\"minimongo - reactive skip/limit count while updating\", function(test) {\n  var X = new LocalCollection;\n  var count = -1;\n\n  var c = Tracker.autorun(function() {\n    count = X.find({}, {skip: 1, limit: 1}).count();\n  });\n\n  test.equal(count, 0);\n\n  X.insert({});\n  Tracker.flush({_throwFirstError: true});\n  test.equal(count, 0);\n\n  X.insert({});\n  Tracker.flush({_throwFirstError: true});\n  test.equal(count, 1);\n\n  X.update({}, {$set: {foo: 1}});\n  Tracker.flush({_throwFirstError: true});\n  test.equal(count, 1);\n\n  // Make sure a second update also works\n  X.update({}, {$set: {foo: 2}});\n  Tracker.flush({_throwFirstError: true});\n  test.equal(count, 1);\n\n  c.stop();\n});\n"
  },
  {
    "path": "packages/minimongo/modify.js",
    "content": "// XXX need a strategy for passing the binding of $ into this\n// function, from the compiled selector\n//\n// maybe just {key.up.to.just.before.dollarsign: array_index}\n//\n// XXX atomicity: if one modification fails, do we roll back the whole\n// change?\n//\n// options:\n//   - isInsert is set when _modify is being called to compute the document to\n//     insert as part of an upsert operation. We use this primarily to figure\n//     out when to set the fields in $setOnInsert, if present.\nLocalCollection._modify = function (doc, mod, options) {\n  options = options || {};\n  if (!isPlainObject(mod))\n    throw MinimongoError(\"Modifier must be an object\");\n\n  // Make sure the caller can't mutate our data structures.\n  mod = EJSON.clone(mod);\n\n  var isModifier = isOperatorObject(mod);\n\n  var newDoc;\n\n  if (!isModifier) {\n    if (mod._id && !EJSON.equals(doc._id, mod._id))\n      throw MinimongoError(\"Cannot change the _id of a document\");\n\n    // replace the whole document\n    for (var k in mod) {\n      if (/\\./.test(k))\n        throw MinimongoError(\n          \"When replacing document, field name may not contain '.'\");\n    }\n    newDoc = mod;\n  } else {\n    // apply modifiers to the doc.\n    newDoc = EJSON.clone(doc);\n\n    _.each(mod, function (operand, op) {\n      var modFunc = MODIFIERS[op];\n      // Treat $setOnInsert as $set if this is an insert.\n      if (options.isInsert && op === '$setOnInsert')\n        modFunc = MODIFIERS['$set'];\n      if (!modFunc)\n        throw MinimongoError(\"Invalid modifier specified \" + op);\n      _.each(operand, function (arg, keypath) {\n        if (keypath === '') {\n          throw MinimongoError(\"An empty update path is not valid.\");\n        }\n\n        if (keypath === '_id' && op !== '$setOnInsert') {\n          throw MinimongoError(\"Mod on _id not allowed\");\n        }\n\n        var keyparts = keypath.split('.');\n\n        if (! _.all(keyparts, _.identity)) {\n          throw MinimongoError(\n            \"The update path '\" + keypath +\n              \"' contains an empty field name, which is not allowed.\");\n        }\n\n        var noCreate = _.has(NO_CREATE_MODIFIERS, op);\n        var forbidArray = (op === \"$rename\");\n        var target = findModTarget(newDoc, keyparts, {\n          noCreate: NO_CREATE_MODIFIERS[op],\n          forbidArray: (op === \"$rename\"),\n          arrayIndices: options.arrayIndices\n        });\n        var field = keyparts.pop();\n        modFunc(target, field, arg, keypath, newDoc);\n      });\n    });\n  }\n\n  // move new document into place.\n  _.each(_.keys(doc), function (k) {\n    // Note: this used to be for (var k in doc) however, this does not\n    // work right in Opera. Deleting from a doc while iterating over it\n    // would sometimes cause opera to skip some keys.\n    if (k !== '_id')\n      delete doc[k];\n  });\n  _.each(newDoc, function (v, k) {\n    doc[k] = v;\n  });\n};\n\n// for a.b.c.2.d.e, keyparts should be ['a', 'b', 'c', '2', 'd', 'e'],\n// and then you would operate on the 'e' property of the returned\n// object.\n//\n// if options.noCreate is falsey, creates intermediate levels of\n// structure as necessary, like mkdir -p (and raises an exception if\n// that would mean giving a non-numeric property to an array.) if\n// options.noCreate is true, return undefined instead.\n//\n// may modify the last element of keyparts to signal to the caller that it needs\n// to use a different value to index into the returned object (for example,\n// ['a', '01'] -> ['a', 1]).\n//\n// if forbidArray is true, return null if the keypath goes through an array.\n//\n// if options.arrayIndices is set, use its first element for the (first) '$' in\n// the path.\nvar findModTarget = function (doc, keyparts, options) {\n  options = options || {};\n  var usedArrayIndex = false;\n  for (var i = 0; i < keyparts.length; i++) {\n    var last = (i === keyparts.length - 1);\n    var keypart = keyparts[i];\n    var indexable = isIndexable(doc);\n    if (!indexable) {\n      if (options.noCreate)\n        return undefined;\n      var e = MinimongoError(\n        \"cannot use the part '\" + keypart + \"' to traverse \" + doc);\n      e.setPropertyError = true;\n      throw e;\n    }\n    if (doc instanceof Array) {\n      if (options.forbidArray)\n        return null;\n      if (keypart === '$') {\n        if (usedArrayIndex)\n          throw MinimongoError(\"Too many positional (i.e. '$') elements\");\n        if (!options.arrayIndices || !options.arrayIndices.length) {\n          throw MinimongoError(\"The positional operator did not find the \" +\n                               \"match needed from the query\");\n        }\n        keypart = options.arrayIndices[0];\n        usedArrayIndex = true;\n      } else if (isNumericKey(keypart)) {\n        keypart = parseInt(keypart);\n      } else {\n        if (options.noCreate)\n          return undefined;\n        throw MinimongoError(\n          \"can't append to array using string field name [\"\n                    + keypart + \"]\");\n      }\n      if (last)\n        // handle 'a.01'\n        keyparts[i] = keypart;\n      if (options.noCreate && keypart >= doc.length)\n        return undefined;\n      while (doc.length < keypart)\n        doc.push(null);\n      if (!last) {\n        if (doc.length === keypart)\n          doc.push({});\n        else if (typeof doc[keypart] !== \"object\")\n          throw MinimongoError(\"can't modify field '\" + keyparts[i + 1] +\n                      \"' of list value \" + JSON.stringify(doc[keypart]));\n      }\n    } else {\n      if (keypart.length && keypart.substr(0, 1) === '$')\n        throw MinimongoError(\"can't set field named \" + keypart);\n      if (!(keypart in doc)) {\n        if (options.noCreate)\n          return undefined;\n        if (!last)\n          doc[keypart] = {};\n      }\n    }\n\n    if (last)\n      return doc;\n    doc = doc[keypart];\n  }\n\n  // notreached\n};\n\nvar NO_CREATE_MODIFIERS = {\n  $unset: true,\n  $pop: true,\n  $rename: true,\n  $pull: true,\n  $pullAll: true\n};\n\nvar MODIFIERS = {\n  $inc: function (target, field, arg) {\n    if (typeof arg !== \"number\")\n      throw MinimongoError(\"Modifier $inc allowed for numbers only\");\n    if (field in target) {\n      if (typeof target[field] !== \"number\")\n        throw MinimongoError(\"Cannot apply $inc modifier to non-number\");\n      target[field] += arg;\n    } else {\n      target[field] = arg;\n    }\n  },\n  $set: function (target, field, arg) {\n    if (!_.isObject(target)) { // not an array or an object\n      var e = MinimongoError(\"Cannot set property on non-object field\");\n      e.setPropertyError = true;\n      throw e;\n    }\n    if (target === null) {\n      var e = MinimongoError(\"Cannot set property on null\");\n      e.setPropertyError = true;\n      throw e;\n    }\n    target[field] = arg;\n  },\n  $setOnInsert: function (target, field, arg) {\n    // converted to `$set` in `_modify`\n  },\n  $unset: function (target, field, arg) {\n    if (target !== undefined) {\n      if (target instanceof Array) {\n        if (field in target)\n          target[field] = null;\n      } else\n        delete target[field];\n    }\n  },\n  $push: function (target, field, arg) {\n    if (target[field] === undefined)\n      target[field] = [];\n    if (!(target[field] instanceof Array))\n      throw MinimongoError(\"Cannot apply $push modifier to non-array\");\n\n    if (!(arg && arg.$each)) {\n      // Simple mode: not $each\n      target[field].push(arg);\n      return;\n    }\n\n    // Fancy mode: $each (and maybe $slice and $sort and $position)\n    var toPush = arg.$each;\n    if (!(toPush instanceof Array))\n      throw MinimongoError(\"$each must be an array\");\n\n    // Parse $position\n    var position = undefined;\n    if ('$position' in arg) {\n      if (typeof arg.$position !== \"number\")\n        throw MinimongoError(\"$position must be a numeric value\");\n      // XXX should check to make sure integer\n      if (arg.$position < 0)\n        throw MinimongoError(\"$position in $push must be zero or positive\");\n      position = arg.$position;\n    }\n\n    // Parse $slice.\n    var slice = undefined;\n    if ('$slice' in arg) {\n      if (typeof arg.$slice !== \"number\")\n        throw MinimongoError(\"$slice must be a numeric value\");\n      // XXX should check to make sure integer\n      if (arg.$slice > 0)\n        throw MinimongoError(\"$slice in $push must be zero or negative\");\n      slice = arg.$slice;\n    }\n\n    // Parse $sort.\n    var sortFunction = undefined;\n    if (arg.$sort) {\n      if (slice === undefined)\n        throw MinimongoError(\"$sort requires $slice to be present\");\n      // XXX this allows us to use a $sort whose value is an array, but that's\n      // actually an extension of the Node driver, so it won't work\n      // server-side. Could be confusing!\n      // XXX is it correct that we don't do geo-stuff here?\n      sortFunction = new Minimongo.Sorter(arg.$sort).getComparator();\n      for (var i = 0; i < toPush.length; i++) {\n        if (LocalCollection._f._type(toPush[i]) !== 3) {\n          throw MinimongoError(\"$push like modifiers using $sort \" +\n                      \"require all elements to be objects\");\n        }\n      }\n    }\n\n    // Actually push.\n    if (position === undefined) {\n      for (var j = 0; j < toPush.length; j++)\n        target[field].push(toPush[j]);\n    } else {\n      var spliceArguments = [position, 0];\n      for (var j = 0; j < toPush.length; j++)\n        spliceArguments.push(toPush[j]);\n      Array.prototype.splice.apply(target[field], spliceArguments);\n    }\n\n    // Actually sort.\n    if (sortFunction)\n      target[field].sort(sortFunction);\n\n    // Actually slice.\n    if (slice !== undefined) {\n      if (slice === 0)\n        target[field] = [];  // differs from Array.slice!\n      else\n        target[field] = target[field].slice(slice);\n    }\n  },\n  $pushAll: function (target, field, arg) {\n    if (!(typeof arg === \"object\" && arg instanceof Array))\n      throw MinimongoError(\"Modifier $pushAll/pullAll allowed for arrays only\");\n    var x = target[field];\n    if (x === undefined)\n      target[field] = arg;\n    else if (!(x instanceof Array))\n      throw MinimongoError(\"Cannot apply $pushAll modifier to non-array\");\n    else {\n      for (var i = 0; i < arg.length; i++)\n        x.push(arg[i]);\n    }\n  },\n  $addToSet: function (target, field, arg) {\n    var isEach = false;\n    if (typeof arg === \"object\") {\n      //check if first key is '$each'\n      for (var k in arg) {\n        if (k === \"$each\")\n          isEach = true;\n        break;\n      }\n    }\n    var values = isEach ? arg[\"$each\"] : [arg];\n    var x = target[field];\n    if (x === undefined)\n      target[field] = values;\n    else if (!(x instanceof Array))\n      throw MinimongoError(\"Cannot apply $addToSet modifier to non-array\");\n    else {\n      _.each(values, function (value) {\n        for (var i = 0; i < x.length; i++)\n          if (LocalCollection._f._equal(value, x[i]))\n            return;\n        x.push(value);\n      });\n    }\n  },\n  $pop: function (target, field, arg) {\n    if (target === undefined)\n      return;\n    var x = target[field];\n    if (x === undefined)\n      return;\n    else if (!(x instanceof Array))\n      throw MinimongoError(\"Cannot apply $pop modifier to non-array\");\n    else {\n      if (typeof arg === 'number' && arg < 0)\n        x.splice(0, 1);\n      else\n        x.pop();\n    }\n  },\n  $pull: function (target, field, arg) {\n    if (target === undefined)\n      return;\n    var x = target[field];\n    if (x === undefined)\n      return;\n    else if (!(x instanceof Array))\n      throw MinimongoError(\"Cannot apply $pull/pullAll modifier to non-array\");\n    else {\n      var out = [];\n      if (arg != null && typeof arg === \"object\" && !(arg instanceof Array)) {\n        // XXX would be much nicer to compile this once, rather than\n        // for each document we modify.. but usually we're not\n        // modifying that many documents, so we'll let it slide for\n        // now\n\n        // XXX Minimongo.Matcher isn't up for the job, because we need\n        // to permit stuff like {$pull: {a: {$gt: 4}}}.. something\n        // like {$gt: 4} is not normally a complete selector.\n        // same issue as $elemMatch possibly?\n        var matcher = new Minimongo.Matcher(arg);\n        for (var i = 0; i < x.length; i++)\n          if (!matcher.documentMatches(x[i]).result)\n            out.push(x[i]);\n      } else {\n        for (var i = 0; i < x.length; i++)\n          if (!LocalCollection._f._equal(x[i], arg))\n            out.push(x[i]);\n      }\n      target[field] = out;\n    }\n  },\n  $pullAll: function (target, field, arg) {\n    if (!(typeof arg === \"object\" && arg instanceof Array))\n      throw MinimongoError(\"Modifier $pushAll/pullAll allowed for arrays only\");\n    if (target === undefined)\n      return;\n    var x = target[field];\n    if (x === undefined)\n      return;\n    else if (!(x instanceof Array))\n      throw MinimongoError(\"Cannot apply $pull/pullAll modifier to non-array\");\n    else {\n      var out = [];\n      for (var i = 0; i < x.length; i++) {\n        var exclude = false;\n        for (var j = 0; j < arg.length; j++) {\n          if (LocalCollection._f._equal(x[i], arg[j])) {\n            exclude = true;\n            break;\n          }\n        }\n        if (!exclude)\n          out.push(x[i]);\n      }\n      target[field] = out;\n    }\n  },\n  $rename: function (target, field, arg, keypath, doc) {\n    if (keypath === arg)\n      // no idea why mongo has this restriction..\n      throw MinimongoError(\"$rename source must differ from target\");\n    if (target === null)\n      throw MinimongoError(\"$rename source field invalid\");\n    if (typeof arg !== \"string\")\n      throw MinimongoError(\"$rename target must be a string\");\n    if (target === undefined)\n      return;\n    var v = target[field];\n    delete target[field];\n\n    var keyparts = arg.split('.');\n    var target2 = findModTarget(doc, keyparts, {forbidArray: true});\n    if (target2 === null)\n      throw MinimongoError(\"$rename target field invalid\");\n    var field2 = keyparts.pop();\n    target2[field2] = v;\n  },\n  $bit: function (target, field, arg) {\n    // XXX mongo only supports $bit on integers, and we only support\n    // native javascript numbers (doubles) so far, so we can't support $bit\n    throw MinimongoError(\"$bit is not supported\");\n  }\n};\n"
  },
  {
    "path": "packages/minimongo/objectid.js",
    "content": "// Is this selector just shorthand for lookup by _id?\nLocalCollection._selectorIsId = function (selector) {\n  return (typeof selector === \"string\") ||\n    (typeof selector === \"number\") ||\n    selector instanceof MongoID.ObjectID;\n};\n\n// Is the selector just lookup by _id (shorthand or not)?\nLocalCollection._selectorIsIdPerhapsAsObject = function (selector) {\n  return LocalCollection._selectorIsId(selector) ||\n    (selector && typeof selector === \"object\" &&\n     selector._id && LocalCollection._selectorIsId(selector._id) &&\n     _.size(selector) === 1);\n};\n\n// If this is a selector which explicitly constrains the match by ID to a finite\n// number of documents, returns a list of their IDs.  Otherwise returns\n// null. Note that the selector may have other restrictions so it may not even\n// match those document!  We care about $in and $and since those are generated\n// access-controlled update and remove.\nLocalCollection._idsMatchedBySelector = function (selector) {\n  // Is the selector just an ID?\n  if (LocalCollection._selectorIsId(selector))\n    return [selector];\n  if (!selector)\n    return null;\n\n  // Do we have an _id clause?\n  if (_.has(selector, '_id')) {\n    // Is the _id clause just an ID?\n    if (LocalCollection._selectorIsId(selector._id))\n      return [selector._id];\n    // Is the _id clause {_id: {$in: [\"x\", \"y\", \"z\"]}}?\n    if (selector._id && selector._id.$in\n        && _.isArray(selector._id.$in)\n        && !_.isEmpty(selector._id.$in)\n        && _.all(selector._id.$in, LocalCollection._selectorIsId)) {\n      return selector._id.$in;\n    }\n    return null;\n  }\n\n  // If this is a top-level $and, and any of the clauses constrain their\n  // documents, then the whole selector is constrained by any one clause's\n  // constraint. (Well, by their intersection, but that seems unlikely.)\n  if (selector.$and && _.isArray(selector.$and)) {\n    for (var i = 0; i < selector.$and.length; ++i) {\n      var subIds = LocalCollection._idsMatchedBySelector(selector.$and[i]);\n      if (subIds)\n        return subIds;\n    }\n  }\n\n  return null;\n};\n\n\n"
  },
  {
    "path": "packages/minimongo/observe.js",
    "content": "// XXX maybe move these into another ObserveHelpers package or something\n\n// _CachingChangeObserver is an object which receives observeChanges callbacks\n// and keeps a cache of the current cursor state up to date in self.docs. Users\n// of this class should read the docs field but not modify it. You should pass\n// the \"applyChange\" field as the callbacks to the underlying observeChanges\n// call. Optionally, you can specify your own observeChanges callbacks which are\n// invoked immediately before the docs field is updated; this object is made\n// available as `this` to those callbacks.\nLocalCollection._CachingChangeObserver = function (options) {\n  var self = this;\n  options = options || {};\n\n  var orderedFromCallbacks = options.callbacks &&\n        LocalCollection._observeChangesCallbacksAreOrdered(options.callbacks);\n  if (_.has(options, 'ordered')) {\n    self.ordered = options.ordered;\n    if (options.callbacks && options.ordered !== orderedFromCallbacks)\n      throw Error(\"ordered option doesn't match callbacks\");\n  } else if (options.callbacks) {\n    self.ordered = orderedFromCallbacks;\n  } else {\n    throw Error(\"must provide ordered or callbacks\");\n  }\n  var callbacks = options.callbacks || {};\n\n  if (self.ordered) {\n    self.docs = new OrderedDict(MongoID.idStringify);\n    self.applyChange = {\n      addedBefore: function (id, fields, before) {\n        var doc = EJSON.clone(fields);\n        doc._id = id;\n        callbacks.addedBefore && callbacks.addedBefore.call(\n          self, id, fields, before);\n        // This line triggers if we provide added with movedBefore.\n        callbacks.added && callbacks.added.call(self, id, fields);\n        // XXX could `before` be a falsy ID?  Technically\n        // idStringify seems to allow for them -- though\n        // OrderedDict won't call stringify on a falsy arg.\n        self.docs.putBefore(id, doc, before || null);\n      },\n      movedBefore: function (id, before) {\n        var doc = self.docs.get(id);\n        callbacks.movedBefore && callbacks.movedBefore.call(self, id, before);\n        self.docs.moveBefore(id, before || null);\n      }\n    };\n  } else {\n    self.docs = new LocalCollection._IdMap;\n    self.applyChange = {\n      added: function (id, fields) {\n        var doc = EJSON.clone(fields);\n        callbacks.added && callbacks.added.call(self, id, fields);\n        doc._id = id;\n        self.docs.set(id,  doc);\n      }\n    };\n  }\n\n  // The methods in _IdMap and OrderedDict used by these callbacks are\n  // identical.\n  self.applyChange.changed = function (id, fields) {\n    var doc = self.docs.get(id);\n    if (!doc)\n      throw new Error(\"Unknown id for changed: \" + id);\n    callbacks.changed && callbacks.changed.call(\n      self, id, EJSON.clone(fields));\n    DiffSequence.applyChanges(doc, fields);\n  };\n  self.applyChange.removed = function (id) {\n    callbacks.removed && callbacks.removed.call(self, id);\n    self.docs.remove(id);\n  };\n};\n\nLocalCollection._observeFromObserveChanges = function (cursor, observeCallbacks) {\n  var transform = cursor.getTransform() || function (doc) {return doc;};\n  var suppressed = !!observeCallbacks._suppress_initial;\n\n  var observeChangesCallbacks;\n  if (LocalCollection._observeCallbacksAreOrdered(observeCallbacks)) {\n    // The \"_no_indices\" option sets all index arguments to -1 and skips the\n    // linear scans required to generate them.  This lets observers that don't\n    // need absolute indices benefit from the other features of this API --\n    // relative order, transforms, and applyChanges -- without the speed hit.\n    var indices = !observeCallbacks._no_indices;\n    observeChangesCallbacks = {\n      addedBefore: function (id, fields, before) {\n        var self = this;\n        if (suppressed || !(observeCallbacks.addedAt || observeCallbacks.added))\n          return;\n        var doc = transform(_.extend(fields, {_id: id}));\n        if (observeCallbacks.addedAt) {\n          var index = indices\n                ? (before ? self.docs.indexOf(before) : self.docs.size()) : -1;\n          observeCallbacks.addedAt(doc, index, before);\n        } else {\n          observeCallbacks.added(doc);\n        }\n      },\n      changed: function (id, fields) {\n        var self = this;\n        if (!(observeCallbacks.changedAt || observeCallbacks.changed))\n          return;\n        var doc = EJSON.clone(self.docs.get(id));\n        if (!doc)\n          throw new Error(\"Unknown id for changed: \" + id);\n        var oldDoc = transform(EJSON.clone(doc));\n        DiffSequence.applyChanges(doc, fields);\n        doc = transform(doc);\n        if (observeCallbacks.changedAt) {\n          var index = indices ? self.docs.indexOf(id) : -1;\n          observeCallbacks.changedAt(doc, oldDoc, index);\n        } else {\n          observeCallbacks.changed(doc, oldDoc);\n        }\n      },\n      movedBefore: function (id, before) {\n        var self = this;\n        if (!observeCallbacks.movedTo)\n          return;\n        var from = indices ? self.docs.indexOf(id) : -1;\n\n        var to = indices\n              ? (before ? self.docs.indexOf(before) : self.docs.size()) : -1;\n        // When not moving backwards, adjust for the fact that removing the\n        // document slides everything back one slot.\n        if (to > from)\n          --to;\n        observeCallbacks.movedTo(transform(EJSON.clone(self.docs.get(id))),\n                                 from, to, before || null);\n      },\n      removed: function (id) {\n        var self = this;\n        if (!(observeCallbacks.removedAt || observeCallbacks.removed))\n          return;\n        // technically maybe there should be an EJSON.clone here, but it's about\n        // to be removed from self.docs!\n        var doc = transform(self.docs.get(id));\n        if (observeCallbacks.removedAt) {\n          var index = indices ? self.docs.indexOf(id) : -1;\n          observeCallbacks.removedAt(doc, index);\n        } else {\n          observeCallbacks.removed(doc);\n        }\n      }\n    };\n  } else {\n    observeChangesCallbacks = {\n      added: function (id, fields) {\n        if (!suppressed && observeCallbacks.added) {\n          var doc = _.extend(fields, {_id:  id});\n          observeCallbacks.added(transform(doc));\n        }\n      },\n      changed: function (id, fields) {\n        var self = this;\n        if (observeCallbacks.changed) {\n          var oldDoc = self.docs.get(id);\n          var doc = EJSON.clone(oldDoc);\n          DiffSequence.applyChanges(doc, fields);\n          observeCallbacks.changed(transform(doc),\n                                   transform(EJSON.clone(oldDoc)));\n        }\n      },\n      removed: function (id) {\n        var self = this;\n        if (observeCallbacks.removed) {\n          observeCallbacks.removed(transform(self.docs.get(id)));\n        }\n      }\n    };\n  }\n\n  var changeObserver = new LocalCollection._CachingChangeObserver(\n    {callbacks: observeChangesCallbacks});\n  var handle = cursor.observeChanges(changeObserver.applyChange);\n  suppressed = false;\n\n  return handle;\n};\n"
  },
  {
    "path": "packages/minimongo/package.js",
    "content": "Package.describe({\n  summary: \"Meteor's client-side datastore: a port of MongoDB to Javascript\",\n  version: '1.0.17'\n});\n\nPackage.onUse(function (api) {\n  api.export('LocalCollection');\n  api.export('Minimongo');\n  api.export('MinimongoTest', { testOnly: true });\n  api.use(['underscore', 'ejson', 'id-map', 'ordered-dict', 'tracker',\n           'mongo-id', 'random', 'diff-sequence']);\n  // This package is used for geo-location queries such as $near\n  api.use('geojson-utils');\n  // This package is used to get diff results on arrays and objects\n  api.use('diff-sequence');\n\n  api.addFiles([\n    'minimongo.js',\n    'wrap_transform.js',\n    'helpers.js',\n    'selector.js',\n    'sort.js',\n    'projection.js',\n    'modify.js',\n    'diff.js',\n    'id_map.js',\n    'observe.js',\n    'objectid.js'\n  ]);\n\n  // Functionality used only by oplog tailing on the server side\n  api.addFiles([\n    'selector_projection.js',\n    'selector_modifier.js',\n    'sorter_projection.js'\n  ], 'server');\n});\n\nPackage.onTest(function (api) {\n  api.use('minimongo', ['client', 'server']);\n  api.use('test-helpers', 'client');\n  api.use(['tinytest', 'underscore', 'ejson', 'ordered-dict',\n           'random', 'tracker', 'reactive-var', 'mongo-id']);\n  api.addFiles('minimongo_tests.js', 'client');\n  api.addFiles('wrap_transform_tests.js');\n  api.addFiles('minimongo_server_tests.js', 'server');\n});\n"
  },
  {
    "path": "packages/minimongo/projection.js",
    "content": "// Knows how to compile a fields projection to a predicate function.\n// @returns - Function: a closure that filters out an object according to the\n//            fields projection rules:\n//            @param obj - Object: MongoDB-styled document\n//            @returns - Object: a document with the fields filtered out\n//                       according to projection rules. Doesn't retain subfields\n//                       of passed argument.\nLocalCollection._compileProjection = function (fields) {\n  LocalCollection._checkSupportedProjection(fields);\n\n  var _idProjection = _.isUndefined(fields._id) ? true : fields._id;\n  var details = projectionDetails(fields);\n\n  // returns transformed doc according to ruleTree\n  var transform = function (doc, ruleTree) {\n    // Special case for \"sets\"\n    if (_.isArray(doc))\n      return _.map(doc, function (subdoc) { return transform(subdoc, ruleTree); });\n\n    var res = details.including ? {} : EJSON.clone(doc);\n    _.each(ruleTree, function (rule, key) {\n      if (!_.has(doc, key))\n        return;\n      if (_.isObject(rule)) {\n        // For sub-objects/subsets we branch\n        if (_.isObject(doc[key]))\n          res[key] = transform(doc[key], rule);\n        // Otherwise we don't even touch this subfield\n      } else if (details.including)\n        res[key] = EJSON.clone(doc[key]);\n      else\n        delete res[key];\n    });\n\n    return res;\n  };\n\n  return function (obj) {\n    var res = transform(obj, details.tree);\n\n    if (_idProjection && _.has(obj, '_id'))\n      res._id = obj._id;\n    if (!_idProjection && _.has(res, '_id'))\n      delete res._id;\n    return res;\n  };\n};\n\n// Traverses the keys of passed projection and constructs a tree where all\n// leaves are either all True or all False\n// @returns Object:\n//  - tree - Object - tree representation of keys involved in projection\n//  (exception for '_id' as it is a special case handled separately)\n//  - including - Boolean - \"take only certain fields\" type of projection\nprojectionDetails = function (fields) {\n  // Find the non-_id keys (_id is handled specially because it is included unless\n  // explicitly excluded). Sort the keys, so that our code to detect overlaps\n  // like 'foo' and 'foo.bar' can assume that 'foo' comes first.\n  var fieldsKeys = _.keys(fields).sort();\n\n  // If _id is the only field in the projection, do not remove it, since it is\n  // required to determine if this is an exclusion or exclusion. Also keep an\n  // inclusive _id, since inclusive _id follows the normal rules about mixing\n  // inclusive and exclusive fields. If _id is not the only field in the\n  // projection and is exclusive, remove it so it can be handled later by a\n  // special case, since exclusive _id is always allowed.\n  if (fieldsKeys.length > 0 &&\n      !(fieldsKeys.length === 1 && fieldsKeys[0] === '_id') &&\n      !(_.contains(fieldsKeys, '_id') && fields['_id']))\n    fieldsKeys = _.reject(fieldsKeys, function (key) { return key === '_id'; });\n\n  var including = null; // Unknown\n\n  _.each(fieldsKeys, function (keyPath) {\n    var rule = !!fields[keyPath];\n    if (including === null)\n      including = rule;\n    if (including !== rule)\n      // This error message is copied from MongoDB shell\n      throw MinimongoError(\"You cannot currently mix including and excluding fields.\");\n  });\n\n\n  var projectionRulesTree = pathsToTree(\n    fieldsKeys,\n    function (path) { return including; },\n    function (node, path, fullPath) {\n      // Check passed projection fields' keys: If you have two rules such as\n      // 'foo.bar' and 'foo.bar.baz', then the result becomes ambiguous. If\n      // that happens, there is a probability you are doing something wrong,\n      // framework should notify you about such mistake earlier on cursor\n      // compilation step than later during runtime.  Note, that real mongo\n      // doesn't do anything about it and the later rule appears in projection\n      // project, more priority it takes.\n      //\n      // Example, assume following in mongo shell:\n      // > db.coll.insert({ a: { b: 23, c: 44 } })\n      // > db.coll.find({}, { 'a': 1, 'a.b': 1 })\n      // { \"_id\" : ObjectId(\"520bfe456024608e8ef24af3\"), \"a\" : { \"b\" : 23 } }\n      // > db.coll.find({}, { 'a.b': 1, 'a': 1 })\n      // { \"_id\" : ObjectId(\"520bfe456024608e8ef24af3\"), \"a\" : { \"b\" : 23, \"c\" : 44 } }\n      //\n      // Note, how second time the return set of keys is different.\n\n      var currentPath = fullPath;\n      var anotherPath = path;\n      throw MinimongoError(\"both \" + currentPath + \" and \" + anotherPath +\n                           \" found in fields option, using both of them may trigger \" +\n                           \"unexpected behavior. Did you mean to use only one of them?\");\n    });\n\n  return {\n    tree: projectionRulesTree,\n    including: including\n  };\n};\n\n// paths - Array: list of mongo style paths\n// newLeafFn - Function: of form function(path) should return a scalar value to\n//                       put into list created for that path\n// conflictFn - Function: of form function(node, path, fullPath) is called\n//                        when building a tree path for 'fullPath' node on\n//                        'path' was already a leaf with a value. Must return a\n//                        conflict resolution.\n// initial tree - Optional Object: starting tree.\n// @returns - Object: tree represented as a set of nested objects\npathsToTree = function (paths, newLeafFn, conflictFn, tree) {\n  tree = tree || {};\n  _.each(paths, function (keyPath) {\n    var treePos = tree;\n    var pathArr = keyPath.split('.');\n\n    // use _.all just for iteration with break\n    var success = _.all(pathArr.slice(0, -1), function (key, idx) {\n      if (!_.has(treePos, key))\n        treePos[key] = {};\n      else if (!_.isObject(treePos[key])) {\n        treePos[key] = conflictFn(treePos[key],\n                                  pathArr.slice(0, idx + 1).join('.'),\n                                  keyPath);\n        // break out of loop if we are failing for this path\n        if (!_.isObject(treePos[key]))\n          return false;\n      }\n\n      treePos = treePos[key];\n      return true;\n    });\n\n    if (success) {\n      var lastKey = _.last(pathArr);\n      if (!_.has(treePos, lastKey))\n        treePos[lastKey] = newLeafFn(keyPath);\n      else\n        treePos[lastKey] = conflictFn(treePos[lastKey], keyPath, keyPath);\n    }\n  });\n\n  return tree;\n};\n\nLocalCollection._checkSupportedProjection = function (fields) {\n  if (!_.isObject(fields) || _.isArray(fields))\n    throw MinimongoError(\"fields option must be an object\");\n\n  _.each(fields, function (val, keyPath) {\n    if (_.contains(keyPath.split('.'), '$'))\n      throw MinimongoError(\"Minimongo doesn't support $ operator in projections yet.\");\n    if (typeof val === 'object' && _.intersection(['$elemMatch', '$meta', '$slice'], _.keys(val)).length > 0)\n      throw MinimongoError(\"Minimongo doesn't support operators in projections yet.\");\n    if (_.indexOf([1, 0, true, false], val) === -1)\n      throw MinimongoError(\"Projection values should be one of 1, 0, true, or false\");\n  });\n};\n"
  },
  {
    "path": "packages/minimongo/selector.js",
    "content": "// The minimongo selector compiler!\n\n// Terminology:\n//  - a \"selector\" is the EJSON object representing a selector\n//  - a \"matcher\" is its compiled form (whether a full Minimongo.Matcher\n//    object or one of the component lambdas that matches parts of it)\n//  - a \"result object\" is an object with a \"result\" field and maybe\n//    distance and arrayIndices.\n//  - a \"branched value\" is an object with a \"value\" field and maybe\n//    \"dontIterate\" and \"arrayIndices\".\n//  - a \"document\" is a top-level object that can be stored in a collection.\n//  - a \"lookup function\" is a function that takes in a document and returns\n//    an array of \"branched values\".\n//  - a \"branched matcher\" maps from an array of branched values to a result\n//    object.\n//  - an \"element matcher\" maps from a single value to a bool.\n\n// Main entry point.\n//   var matcher = new Minimongo.Matcher({a: {$gt: 5}});\n//   if (matcher.documentMatches({a: 7})) ...\nMinimongo.Matcher = function (selector) {\n  var self = this;\n  // A set (object mapping string -> *) of all of the document paths looked\n  // at by the selector. Also includes the empty string if it may look at any\n  // path (eg, $where).\n  self._paths = {};\n  // Set to true if compilation finds a $near.\n  self._hasGeoQuery = false;\n  // Set to true if compilation finds a $where.\n  self._hasWhere = false;\n  // Set to false if compilation finds anything other than a simple equality or\n  // one or more of '$gt', '$gte', '$lt', '$lte', '$ne', '$in', '$nin' used with\n  // scalars as operands.\n  self._isSimple = true;\n  // Set to a dummy document which always matches this Matcher. Or set to null\n  // if such document is too hard to find.\n  self._matchingDocument = undefined;\n  // A clone of the original selector. It may just be a function if the user\n  // passed in a function; otherwise is definitely an object (eg, IDs are\n  // translated into {_id: ID} first. Used by canBecomeTrueByModifier and\n  // Sorter._useWithMatcher.\n  self._selector = null;\n  self._docMatcher = self._compileSelector(selector);\n};\n\n_.extend(Minimongo.Matcher.prototype, {\n  documentMatches: function (doc) {\n    if (!doc || typeof doc !== \"object\") {\n      throw Error(\"documentMatches needs a document\");\n    }\n    return this._docMatcher(doc);\n  },\n  hasGeoQuery: function () {\n    return this._hasGeoQuery;\n  },\n  hasWhere: function () {\n    return this._hasWhere;\n  },\n  isSimple: function () {\n    return this._isSimple;\n  },\n\n  // Given a selector, return a function that takes one argument, a\n  // document. It returns a result object.\n  _compileSelector: function (selector) {\n    var self = this;\n    // you can pass a literal function instead of a selector\n    if (selector instanceof Function) {\n      self._isSimple = false;\n      self._selector = selector;\n      self._recordPathUsed('');\n      return function (doc) {\n        return {result: !!selector.call(doc)};\n      };\n    }\n\n    // shorthand -- scalars match _id\n    if (LocalCollection._selectorIsId(selector)) {\n      self._selector = {_id: selector};\n      self._recordPathUsed('_id');\n      return function (doc) {\n        return {result: EJSON.equals(doc._id, selector)};\n      };\n    }\n\n    // protect against dangerous selectors.  falsey and {_id: falsey} are both\n    // likely programmer error, and not what you want, particularly for\n    // destructive operations.\n    if (!selector || (('_id' in selector) && !selector._id)) {\n      self._isSimple = false;\n      return nothingMatcher;\n    }\n\n    // Top level can't be an array or true or binary.\n    if (typeof(selector) === 'boolean' || isArray(selector) ||\n        EJSON.isBinary(selector))\n      throw new Error(\"Invalid selector: \" + selector);\n\n    self._selector = EJSON.clone(selector);\n    return compileDocumentSelector(selector, self, {isRoot: true});\n  },\n  _recordPathUsed: function (path) {\n    this._paths[path] = true;\n  },\n  // Returns a list of key paths the given selector is looking for. It includes\n  // the empty string if there is a $where.\n  _getPaths: function () {\n    return _.keys(this._paths);\n  }\n});\n\n\n// Takes in a selector that could match a full document (eg, the original\n// selector). Returns a function mapping document->result object.\n//\n// matcher is the Matcher object we are compiling.\n//\n// If this is the root document selector (ie, not wrapped in $and or the like),\n// then isRoot is true. (This is used by $near.)\nvar compileDocumentSelector = function (docSelector, matcher, options) {\n  options = options || {};\n  var docMatchers = [];\n  _.each(docSelector, function (subSelector, key) {\n    if (key.substr(0, 1) === '$') {\n      // Outer operators are either logical operators (they recurse back into\n      // this function), or $where.\n      if (!_.has(LOGICAL_OPERATORS, key))\n        throw new Error(\"Unrecognized logical operator: \" + key);\n      matcher._isSimple = false;\n      docMatchers.push(LOGICAL_OPERATORS[key](subSelector, matcher,\n                                              options.inElemMatch));\n    } else {\n      // Record this path, but only if we aren't in an elemMatcher, since in an\n      // elemMatch this is a path inside an object in an array, not in the doc\n      // root.\n      if (!options.inElemMatch)\n        matcher._recordPathUsed(key);\n      var lookUpByIndex = makeLookupFunction(key);\n      var valueMatcher =\n        compileValueSelector(subSelector, matcher, options.isRoot);\n      docMatchers.push(function (doc) {\n        var branchValues = lookUpByIndex(doc);\n        return valueMatcher(branchValues);\n      });\n    }\n  });\n\n  return andDocumentMatchers(docMatchers);\n};\n\n// Takes in a selector that could match a key-indexed value in a document; eg,\n// {$gt: 5, $lt: 9}, or a regular expression, or any non-expression object (to\n// indicate equality).  Returns a branched matcher: a function mapping\n// [branched value]->result object.\nvar compileValueSelector = function (valueSelector, matcher, isRoot) {\n  if (valueSelector instanceof RegExp) {\n    matcher._isSimple = false;\n    return convertElementMatcherToBranchedMatcher(\n      regexpElementMatcher(valueSelector));\n  } else if (isOperatorObject(valueSelector)) {\n    return operatorBranchedMatcher(valueSelector, matcher, isRoot);\n  } else {\n    return convertElementMatcherToBranchedMatcher(\n      equalityElementMatcher(valueSelector));\n  }\n};\n\n// Given an element matcher (which evaluates a single value), returns a branched\n// value (which evaluates the element matcher on all the branches and returns a\n// more structured return value possibly including arrayIndices).\nvar convertElementMatcherToBranchedMatcher = function (\n    elementMatcher, options) {\n  options = options || {};\n  return function (branches) {\n    var expanded = branches;\n    if (!options.dontExpandLeafArrays) {\n      expanded = expandArraysInBranches(\n        branches, options.dontIncludeLeafArrays);\n    }\n    var ret = {};\n    ret.result = _.any(expanded, function (element) {\n      var matched = elementMatcher(element.value);\n\n      // Special case for $elemMatch: it means \"true, and use this as an array\n      // index if I didn't already have one\".\n      if (typeof matched === 'number') {\n        // XXX This code dates from when we only stored a single array index\n        // (for the outermost array). Should we be also including deeper array\n        // indices from the $elemMatch match?\n        if (!element.arrayIndices)\n          element.arrayIndices = [matched];\n        matched = true;\n      }\n\n      // If some element matched, and it's tagged with array indices, include\n      // those indices in our result object.\n      if (matched && element.arrayIndices)\n        ret.arrayIndices = element.arrayIndices;\n\n      return matched;\n    });\n    return ret;\n  };\n};\n\n// Takes a RegExp object and returns an element matcher.\nregexpElementMatcher = function (regexp) {\n  return function (value) {\n    if (value instanceof RegExp) {\n      // Comparing two regexps means seeing if the regexps are identical\n      // (really!). Underscore knows how.\n      return _.isEqual(value, regexp);\n    }\n    // Regexps only work against strings.\n    if (typeof value !== 'string')\n      return false;\n\n    // Reset regexp's state to avoid inconsistent matching for objects with the\n    // same value on consecutive calls of regexp.test. This happens only if the\n    // regexp has the 'g' flag. Also note that ES6 introduces a new flag 'y' for\n    // which we should *not* change the lastIndex but MongoDB doesn't support\n    // either of these flags.\n    regexp.lastIndex = 0;\n\n    return regexp.test(value);\n  };\n};\n\n// Takes something that is not an operator object and returns an element matcher\n// for equality with that thing.\nequalityElementMatcher = function (elementSelector) {\n  if (isOperatorObject(elementSelector))\n    throw Error(\"Can't create equalityValueSelector for operator object\");\n\n  // Special-case: null and undefined are equal (if you got undefined in there\n  // somewhere, or if you got it due to some branch being non-existent in the\n  // weird special case), even though they aren't with EJSON.equals.\n  if (elementSelector == null) {  // undefined or null\n    return function (value) {\n      return value == null;  // undefined or null\n    };\n  }\n\n  return function (value) {\n    return LocalCollection._f._equal(elementSelector, value);\n  };\n};\n\n// Takes an operator object (an object with $ keys) and returns a branched\n// matcher for it.\nvar operatorBranchedMatcher = function (valueSelector, matcher, isRoot) {\n  // Each valueSelector works separately on the various branches.  So one\n  // operator can match one branch and another can match another branch.  This\n  // is OK.\n\n  var operatorMatchers = [];\n  _.each(valueSelector, function (operand, operator) {\n    var simpleRange = _.contains(['$lt', '$lte', '$gt', '$gte'], operator) &&\n      _.isNumber(operand);\n    var simpleEquality = _.contains(['$ne', '$eq'], operator) && !_.isObject(operand);\n    var simpleInclusion = _.contains(['$in', '$nin'], operator) &&\n      _.isArray(operand) && !_.any(operand, _.isObject);\n\n    if (! (simpleRange || simpleInclusion || simpleEquality)) {\n      matcher._isSimple = false;\n    }\n\n    if (_.has(VALUE_OPERATORS, operator)) {\n      operatorMatchers.push(\n        VALUE_OPERATORS[operator](operand, valueSelector, matcher, isRoot));\n    } else if (_.has(ELEMENT_OPERATORS, operator)) {\n      var options = ELEMENT_OPERATORS[operator];\n      operatorMatchers.push(\n        convertElementMatcherToBranchedMatcher(\n          options.compileElementSelector(\n            operand, valueSelector, matcher),\n          options));\n    } else {\n      throw new Error(\"Unrecognized operator: \" + operator);\n    }\n  });\n\n  return andBranchedMatchers(operatorMatchers);\n};\n\nvar compileArrayOfDocumentSelectors = function (\n    selectors, matcher, inElemMatch) {\n  if (!isArray(selectors) || _.isEmpty(selectors))\n    throw Error(\"$and/$or/$nor must be nonempty array\");\n  return _.map(selectors, function (subSelector) {\n    if (!isPlainObject(subSelector))\n      throw Error(\"$or/$and/$nor entries need to be full objects\");\n    return compileDocumentSelector(\n      subSelector, matcher, {inElemMatch: inElemMatch});\n  });\n};\n\n// Operators that appear at the top level of a document selector.\nvar LOGICAL_OPERATORS = {\n  $and: function (subSelector, matcher, inElemMatch) {\n    var matchers = compileArrayOfDocumentSelectors(\n      subSelector, matcher, inElemMatch);\n    return andDocumentMatchers(matchers);\n  },\n\n  $or: function (subSelector, matcher, inElemMatch) {\n    var matchers = compileArrayOfDocumentSelectors(\n      subSelector, matcher, inElemMatch);\n\n    // Special case: if there is only one matcher, use it directly, *preserving*\n    // any arrayIndices it returns.\n    if (matchers.length === 1)\n      return matchers[0];\n\n    return function (doc) {\n      var result = _.any(matchers, function (f) {\n        return f(doc).result;\n      });\n      // $or does NOT set arrayIndices when it has multiple\n      // sub-expressions. (Tested against MongoDB.)\n      return {result: result};\n    };\n  },\n\n  $nor: function (subSelector, matcher, inElemMatch) {\n    var matchers = compileArrayOfDocumentSelectors(\n      subSelector, matcher, inElemMatch);\n    return function (doc) {\n      var result = _.all(matchers, function (f) {\n        return !f(doc).result;\n      });\n      // Never set arrayIndices, because we only match if nothing in particular\n      // \"matched\" (and because this is consistent with MongoDB).\n      return {result: result};\n    };\n  },\n\n  $where: function (selectorValue, matcher) {\n    // Record that *any* path may be used.\n    matcher._recordPathUsed('');\n    matcher._hasWhere = true;\n    if (!(selectorValue instanceof Function)) {\n      // XXX MongoDB seems to have more complex logic to decide where or or not\n      // to add \"return\"; not sure exactly what it is.\n      selectorValue = Function(\"obj\", \"return \" + selectorValue);\n    }\n    return function (doc) {\n      // We make the document available as both `this` and `obj`.\n      // XXX not sure what we should do if this throws\n      return {result: selectorValue.call(doc, doc)};\n    };\n  },\n\n  // This is just used as a comment in the query (in MongoDB, it also ends up in\n  // query logs); it has no effect on the actual selection.\n  $comment: function () {\n    return function () {\n      return {result: true};\n    };\n  }\n};\n\n// Returns a branched matcher that matches iff the given matcher does not.\n// Note that this implicitly \"deMorganizes\" the wrapped function.  ie, it\n// means that ALL branch values need to fail to match innerBranchedMatcher.\nvar invertBranchedMatcher = function (branchedMatcher) {\n  return function (branchValues) {\n    var invertMe = branchedMatcher(branchValues);\n    // We explicitly choose to strip arrayIndices here: it doesn't make sense to\n    // say \"update the array element that does not match something\", at least\n    // in mongo-land.\n    return {result: !invertMe.result};\n  };\n};\n\n// Operators that (unlike LOGICAL_OPERATORS) pertain to individual paths in a\n// document, but (unlike ELEMENT_OPERATORS) do not have a simple definition as\n// \"match each branched value independently and combine with\n// convertElementMatcherToBranchedMatcher\".\nvar VALUE_OPERATORS = {\n  $eq: function (operand) {\n    return convertElementMatcherToBranchedMatcher(\n      equalityElementMatcher(operand));\n  },\n  $not: function (operand, valueSelector, matcher) {\n    return invertBranchedMatcher(compileValueSelector(operand, matcher));\n  },\n  $ne: function (operand) {\n    return invertBranchedMatcher(convertElementMatcherToBranchedMatcher(\n      equalityElementMatcher(operand)));\n  },\n  $nin: function (operand) {\n    return invertBranchedMatcher(convertElementMatcherToBranchedMatcher(\n      ELEMENT_OPERATORS.$in.compileElementSelector(operand)));\n  },\n  $exists: function (operand) {\n    var exists = convertElementMatcherToBranchedMatcher(function (value) {\n      return value !== undefined;\n    });\n    return operand ? exists : invertBranchedMatcher(exists);\n  },\n  // $options just provides options for $regex; its logic is inside $regex\n  $options: function (operand, valueSelector) {\n    if (!_.has(valueSelector, '$regex'))\n      throw Error(\"$options needs a $regex\");\n    return everythingMatcher;\n  },\n  // $maxDistance is basically an argument to $near\n  $maxDistance: function (operand, valueSelector) {\n    if (!valueSelector.$near)\n      throw Error(\"$maxDistance needs a $near\");\n    return everythingMatcher;\n  },\n  $all: function (operand, valueSelector, matcher) {\n    if (!isArray(operand))\n      throw Error(\"$all requires array\");\n    // Not sure why, but this seems to be what MongoDB does.\n    if (_.isEmpty(operand))\n      return nothingMatcher;\n\n    var branchedMatchers = [];\n    _.each(operand, function (criterion) {\n      // XXX handle $all/$elemMatch combination\n      if (isOperatorObject(criterion))\n        throw Error(\"no $ expressions in $all\");\n      // This is always a regexp or equality selector.\n      branchedMatchers.push(compileValueSelector(criterion, matcher));\n    });\n    // andBranchedMatchers does NOT require all selectors to return true on the\n    // SAME branch.\n    return andBranchedMatchers(branchedMatchers);\n  },\n  $near: function (operand, valueSelector, matcher, isRoot) {\n    if (!isRoot)\n      throw Error(\"$near can't be inside another $ operator\");\n    matcher._hasGeoQuery = true;\n\n    // There are two kinds of geodata in MongoDB: coordinate pairs and\n    // GeoJSON. They use different distance metrics, too. GeoJSON queries are\n    // marked with a $geometry property.\n\n    var maxDistance, point, distance;\n    if (isPlainObject(operand) && _.has(operand, '$geometry')) {\n      // GeoJSON \"2dsphere\" mode.\n      maxDistance = operand.$maxDistance;\n      point = operand.$geometry;\n      distance = function (value) {\n        // XXX: for now, we don't calculate the actual distance between, say,\n        // polygon and circle. If people care about this use-case it will get\n        // a priority.\n        if (!value || !value.type)\n          return null;\n        if (value.type === \"Point\") {\n          return GeoJSON.pointDistance(point, value);\n        } else {\n          return GeoJSON.geometryWithinRadius(value, point, maxDistance)\n            ? 0 : maxDistance + 1;\n        }\n      };\n    } else {\n      maxDistance = valueSelector.$maxDistance;\n      if (!isArray(operand) && !isPlainObject(operand))\n        throw Error(\"$near argument must be coordinate pair or GeoJSON\");\n      point = pointToArray(operand);\n      distance = function (value) {\n        if (!isArray(value) && !isPlainObject(value))\n          return null;\n        return distanceCoordinatePairs(point, value);\n      };\n    }\n\n    return function (branchedValues) {\n      // There might be multiple points in the document that match the given\n      // field. Only one of them needs to be within $maxDistance, but we need to\n      // evaluate all of them and use the nearest one for the implicit sort\n      // specifier. (That's why we can't just use ELEMENT_OPERATORS here.)\n      //\n      // Note: This differs from MongoDB's implementation, where a document will\n      // actually show up *multiple times* in the result set, with one entry for\n      // each within-$maxDistance branching point.\n      branchedValues = expandArraysInBranches(branchedValues);\n      var result = {result: false};\n      _.each(branchedValues, function (branch) {\n        var curDistance = distance(branch.value);\n        // Skip branches that aren't real points or are too far away.\n        if (curDistance === null || curDistance > maxDistance)\n          return;\n        // Skip anything that's a tie.\n        if (result.distance !== undefined && result.distance <= curDistance)\n          return;\n        result.result = true;\n        result.distance = curDistance;\n        if (!branch.arrayIndices)\n          delete result.arrayIndices;\n        else\n          result.arrayIndices = branch.arrayIndices;\n      });\n      return result;\n    };\n  }\n};\n\n// Helpers for $near.\nvar distanceCoordinatePairs = function (a, b) {\n  a = pointToArray(a);\n  b = pointToArray(b);\n  var x = a[0] - b[0];\n  var y = a[1] - b[1];\n  if (_.isNaN(x) || _.isNaN(y))\n    return null;\n  return Math.sqrt(x * x + y * y);\n};\n// Makes sure we get 2 elements array and assume the first one to be x and\n// the second one to y no matter what user passes.\n// In case user passes { lon: x, lat: y } returns [x, y]\nvar pointToArray = function (point) {\n  return _.map(point, _.identity);\n};\n\n// Helper for $lt/$gt/$lte/$gte.\nvar makeInequality = function (cmpValueComparator) {\n  return {\n    compileElementSelector: function (operand) {\n      // Arrays never compare false with non-arrays for any inequality.\n      // XXX This was behavior we observed in pre-release MongoDB 2.5, but\n      //     it seems to have been reverted.\n      //     See https://jira.mongodb.org/browse/SERVER-11444\n      if (isArray(operand)) {\n        return function () {\n          return false;\n        };\n      }\n\n      // Special case: consider undefined and null the same (so true with\n      // $gte/$lte).\n      if (operand === undefined)\n        operand = null;\n\n      var operandType = LocalCollection._f._type(operand);\n\n      return function (value) {\n        if (value === undefined)\n          value = null;\n        // Comparisons are never true among things of different type (except\n        // null vs undefined).\n        if (LocalCollection._f._type(value) !== operandType)\n          return false;\n        return cmpValueComparator(LocalCollection._f._cmp(value, operand));\n      };\n    }\n  };\n};\n\n// Each element selector contains:\n//  - compileElementSelector, a function with args:\n//    - operand - the \"right hand side\" of the operator\n//    - valueSelector - the \"context\" for the operator (so that $regex can find\n//      $options)\n//    - matcher - the Matcher this is going into (so that $elemMatch can compile\n//      more things)\n//    returning a function mapping a single value to bool.\n//  - dontExpandLeafArrays, a bool which prevents expandArraysInBranches from\n//    being called\n//  - dontIncludeLeafArrays, a bool which causes an argument to be passed to\n//    expandArraysInBranches if it is called\nELEMENT_OPERATORS = {\n  $lt: makeInequality(function (cmpValue) {\n    return cmpValue < 0;\n  }),\n  $gt: makeInequality(function (cmpValue) {\n    return cmpValue > 0;\n  }),\n  $lte: makeInequality(function (cmpValue) {\n    return cmpValue <= 0;\n  }),\n  $gte: makeInequality(function (cmpValue) {\n    return cmpValue >= 0;\n  }),\n  $mod: {\n    compileElementSelector: function (operand) {\n      if (!(isArray(operand) && operand.length === 2\n            && typeof(operand[0]) === 'number'\n            && typeof(operand[1]) === 'number')) {\n        throw Error(\"argument to $mod must be an array of two numbers\");\n      }\n      // XXX could require to be ints or round or something\n      var divisor = operand[0];\n      var remainder = operand[1];\n      return function (value) {\n        return typeof value === 'number' && value % divisor === remainder;\n      };\n    }\n  },\n  $in: {\n    compileElementSelector: function (operand) {\n      if (!isArray(operand))\n        throw Error(\"$in needs an array\");\n\n      var elementMatchers = [];\n      _.each(operand, function (option) {\n        if (option instanceof RegExp)\n          elementMatchers.push(regexpElementMatcher(option));\n        else if (isOperatorObject(option))\n          throw Error(\"cannot nest $ under $in\");\n        else\n          elementMatchers.push(equalityElementMatcher(option));\n      });\n\n      return function (value) {\n        // Allow {a: {$in: [null]}} to match when 'a' does not exist.\n        if (value === undefined)\n          value = null;\n        return _.any(elementMatchers, function (e) {\n          return e(value);\n        });\n      };\n    }\n  },\n  $size: {\n    // {a: [[5, 5]]} must match {a: {$size: 1}} but not {a: {$size: 2}}, so we\n    // don't want to consider the element [5,5] in the leaf array [[5,5]] as a\n    // possible value.\n    dontExpandLeafArrays: true,\n    compileElementSelector: function (operand) {\n      if (typeof operand === 'string') {\n        // Don't ask me why, but by experimentation, this seems to be what Mongo\n        // does.\n        operand = 0;\n      } else if (typeof operand !== 'number') {\n        throw Error(\"$size needs a number\");\n      }\n      return function (value) {\n        return isArray(value) && value.length === operand;\n      };\n    }\n  },\n  $type: {\n    // {a: [5]} must not match {a: {$type: 4}} (4 means array), but it should\n    // match {a: {$type: 1}} (1 means number), and {a: [[5]]} must match {$a:\n    // {$type: 4}}. Thus, when we see a leaf array, we *should* expand it but\n    // should *not* include it itself.\n    dontIncludeLeafArrays: true,\n    compileElementSelector: function (operand) {\n      if (typeof operand !== 'number')\n        throw Error(\"$type needs a number\");\n      return function (value) {\n        return value !== undefined\n          && LocalCollection._f._type(value) === operand;\n      };\n    }\n  },\n  $regex: {\n    compileElementSelector: function (operand, valueSelector) {\n      if (!(typeof operand === 'string' || operand instanceof RegExp))\n        throw Error(\"$regex has to be a string or RegExp\");\n\n      var regexp;\n      if (valueSelector.$options !== undefined) {\n        // Options passed in $options (even the empty string) always overrides\n        // options in the RegExp object itself. (See also\n        // Mongo.Collection._rewriteSelector.)\n\n        // Be clear that we only support the JS-supported options, not extended\n        // ones (eg, Mongo supports x and s). Ideally we would implement x and s\n        // by transforming the regexp, but not today...\n        if (/[^gim]/.test(valueSelector.$options))\n          throw new Error(\"Only the i, m, and g regexp options are supported\");\n\n        var regexSource = operand instanceof RegExp ? operand.source : operand;\n        regexp = new RegExp(regexSource, valueSelector.$options);\n      } else if (operand instanceof RegExp) {\n        regexp = operand;\n      } else {\n        regexp = new RegExp(operand);\n      }\n      return regexpElementMatcher(regexp);\n    }\n  },\n  $elemMatch: {\n    dontExpandLeafArrays: true,\n    compileElementSelector: function (operand, valueSelector, matcher) {\n      if (!isPlainObject(operand))\n        throw Error(\"$elemMatch need an object\");\n\n      var subMatcher, isDocMatcher;\n      if (isOperatorObject(_.omit(operand, _.keys(LOGICAL_OPERATORS)), true)) {\n        subMatcher = compileValueSelector(operand, matcher);\n        isDocMatcher = false;\n      } else {\n        // This is NOT the same as compileValueSelector(operand), and not just\n        // because of the slightly different calling convention.\n        // {$elemMatch: {x: 3}} means \"an element has a field x:3\", not\n        // \"consists only of a field x:3\". Also, regexps and sub-$ are allowed.\n        subMatcher = compileDocumentSelector(operand, matcher,\n                                             {inElemMatch: true});\n        isDocMatcher = true;\n      }\n\n      return function (value) {\n        if (!isArray(value))\n          return false;\n        for (var i = 0; i < value.length; ++i) {\n          var arrayElement = value[i];\n          var arg;\n          if (isDocMatcher) {\n            // We can only match {$elemMatch: {b: 3}} against objects.\n            // (We can also match against arrays, if there's numeric indices,\n            // eg {$elemMatch: {'0.b': 3}} or {$elemMatch: {0: 3}}.)\n            if (!isPlainObject(arrayElement) && !isArray(arrayElement))\n              return false;\n            arg = arrayElement;\n          } else {\n            // dontIterate ensures that {a: {$elemMatch: {$gt: 5}}} matches\n            // {a: [8]} but not {a: [[8]]}\n            arg = [{value: arrayElement, dontIterate: true}];\n          }\n          // XXX support $near in $elemMatch by propagating $distance?\n          if (subMatcher(arg).result)\n            return i;   // specially understood to mean \"use as arrayIndices\"\n        }\n        return false;\n      };\n    }\n  }\n};\n\n// makeLookupFunction(key) returns a lookup function.\n//\n// A lookup function takes in a document and returns an array of matching\n// branches.  If no arrays are found while looking up the key, this array will\n// have exactly one branches (possibly 'undefined', if some segment of the key\n// was not found).\n//\n// If arrays are found in the middle, this can have more than one element, since\n// we \"branch\". When we \"branch\", if there are more key segments to look up,\n// then we only pursue branches that are plain objects (not arrays or scalars).\n// This means we can actually end up with no branches!\n//\n// We do *NOT* branch on arrays that are found at the end (ie, at the last\n// dotted member of the key). We just return that array; if you want to\n// effectively \"branch\" over the array's values, post-process the lookup\n// function with expandArraysInBranches.\n//\n// Each branch is an object with keys:\n//  - value: the value at the branch\n//  - dontIterate: an optional bool; if true, it means that 'value' is an array\n//    that expandArraysInBranches should NOT expand. This specifically happens\n//    when there is a numeric index in the key, and ensures the\n//    perhaps-surprising MongoDB behavior where {'a.0': 5} does NOT\n//    match {a: [[5]]}.\n//  - arrayIndices: if any array indexing was done during lookup (either due to\n//    explicit numeric indices or implicit branching), this will be an array of\n//    the array indices used, from outermost to innermost; it is falsey or\n//    absent if no array index is used. If an explicit numeric index is used,\n//    the index will be followed in arrayIndices by the string 'x'.\n//\n//    Note: arrayIndices is used for two purposes. First, it is used to\n//    implement the '$' modifier feature, which only ever looks at its first\n//    element.\n//\n//    Second, it is used for sort key generation, which needs to be able to tell\n//    the difference between different paths. Moreover, it needs to\n//    differentiate between explicit and implicit branching, which is why\n//    there's the somewhat hacky 'x' entry: this means that explicit and\n//    implicit array lookups will have different full arrayIndices paths. (That\n//    code only requires that different paths have different arrayIndices; it\n//    doesn't actually \"parse\" arrayIndices. As an alternative, arrayIndices\n//    could contain objects with flags like \"implicit\", but I think that only\n//    makes the code surrounding them more complex.)\n//\n//    (By the way, this field ends up getting passed around a lot without\n//    cloning, so never mutate any arrayIndices field/var in this package!)\n//\n//\n// At the top level, you may only pass in a plain object or array.\n//\n// See the test 'minimongo - lookup' for some examples of what lookup functions\n// return.\nmakeLookupFunction = function (key, options) {\n  options = options || {};\n  var parts = key.split('.');\n  var firstPart = parts.length ? parts[0] : '';\n  var firstPartIsNumeric = isNumericKey(firstPart);\n  var nextPartIsNumeric = parts.length >= 2 && isNumericKey(parts[1]);\n  var lookupRest;\n  if (parts.length > 1) {\n    lookupRest = makeLookupFunction(parts.slice(1).join('.'));\n  }\n\n  var omitUnnecessaryFields = function (retVal) {\n    if (!retVal.dontIterate)\n      delete retVal.dontIterate;\n    if (retVal.arrayIndices && !retVal.arrayIndices.length)\n      delete retVal.arrayIndices;\n    return retVal;\n  };\n\n  // Doc will always be a plain object or an array.\n  // apply an explicit numeric index, an array.\n  return function (doc, arrayIndices) {\n    if (!arrayIndices)\n      arrayIndices = [];\n\n    if (isArray(doc)) {\n      // If we're being asked to do an invalid lookup into an array (non-integer\n      // or out-of-bounds), return no results (which is different from returning\n      // a single undefined result, in that `null` equality checks won't match).\n      if (!(firstPartIsNumeric && firstPart < doc.length))\n        return [];\n\n      // Remember that we used this array index. Include an 'x' to indicate that\n      // the previous index came from being considered as an explicit array\n      // index (not branching).\n      arrayIndices = arrayIndices.concat(+firstPart, 'x');\n    }\n\n    // Do our first lookup.\n    var firstLevel = doc[firstPart];\n\n    // If there is no deeper to dig, return what we found.\n    //\n    // If what we found is an array, most value selectors will choose to treat\n    // the elements of the array as matchable values in their own right, but\n    // that's done outside of the lookup function. (Exceptions to this are $size\n    // and stuff relating to $elemMatch.  eg, {a: {$size: 2}} does not match {a:\n    // [[1, 2]]}.)\n    //\n    // That said, if we just did an *explicit* array lookup (on doc) to find\n    // firstLevel, and firstLevel is an array too, we do NOT want value\n    // selectors to iterate over it.  eg, {'a.0': 5} does not match {a: [[5]]}.\n    // So in that case, we mark the return value as \"don't iterate\".\n    if (!lookupRest) {\n      return [omitUnnecessaryFields({\n        value: firstLevel,\n        dontIterate: isArray(doc) && isArray(firstLevel),\n        arrayIndices: arrayIndices})];\n    }\n\n    // We need to dig deeper.  But if we can't, because what we've found is not\n    // an array or plain object, we're done. If we just did a numeric index into\n    // an array, we return nothing here (this is a change in Mongo 2.5 from\n    // Mongo 2.4, where {'a.0.b': null} stopped matching {a: [5]}). Otherwise,\n    // return a single `undefined` (which can, for example, match via equality\n    // with `null`).\n    if (!isIndexable(firstLevel)) {\n      if (isArray(doc))\n        return [];\n      return [omitUnnecessaryFields({value: undefined,\n                                      arrayIndices: arrayIndices})];\n    }\n\n    var result = [];\n    var appendToResult = function (more) {\n      Array.prototype.push.apply(result, more);\n    };\n\n    // Dig deeper: look up the rest of the parts on whatever we've found.\n    // (lookupRest is smart enough to not try to do invalid lookups into\n    // firstLevel if it's an array.)\n    appendToResult(lookupRest(firstLevel, arrayIndices));\n\n    // If we found an array, then in *addition* to potentially treating the next\n    // part as a literal integer lookup, we should also \"branch\": try to look up\n    // the rest of the parts on each array element in parallel.\n    //\n    // In this case, we *only* dig deeper into array elements that are plain\n    // objects. (Recall that we only got this far if we have further to dig.)\n    // This makes sense: we certainly don't dig deeper into non-indexable\n    // objects. And it would be weird to dig into an array: it's simpler to have\n    // a rule that explicit integer indexes only apply to an outer array, not to\n    // an array you find after a branching search.\n    //\n    // In the special case of a numeric part in a *sort selector* (not a query\n    // selector), we skip the branching: we ONLY allow the numeric part to mean\n    // \"look up this index\" in that case, not \"also look up this index in all\n    // the elements of the array\".\n    if (isArray(firstLevel) && !(nextPartIsNumeric && options.forSort)) {\n      _.each(firstLevel, function (branch, arrayIndex) {\n        if (isPlainObject(branch)) {\n          appendToResult(lookupRest(\n            branch,\n            arrayIndices.concat(arrayIndex)));\n        }\n      });\n    }\n\n    return result;\n  };\n};\nMinimongoTest.makeLookupFunction = makeLookupFunction;\n\nexpandArraysInBranches = function (branches, skipTheArrays) {\n  var branchesOut = [];\n  _.each(branches, function (branch) {\n    var thisIsArray = isArray(branch.value);\n    // We include the branch itself, *UNLESS* we it's an array that we're going\n    // to iterate and we're told to skip arrays.  (That's right, we include some\n    // arrays even skipTheArrays is true: these are arrays that were found via\n    // explicit numerical indices.)\n    if (!(skipTheArrays && thisIsArray && !branch.dontIterate)) {\n      branchesOut.push({\n        value: branch.value,\n        arrayIndices: branch.arrayIndices\n      });\n    }\n    if (thisIsArray && !branch.dontIterate) {\n      _.each(branch.value, function (leaf, i) {\n        branchesOut.push({\n          value: leaf,\n          arrayIndices: (branch.arrayIndices || []).concat(i)\n        });\n      });\n    }\n  });\n  return branchesOut;\n};\n\nvar nothingMatcher = function (docOrBranchedValues) {\n  return {result: false};\n};\n\nvar everythingMatcher = function (docOrBranchedValues) {\n  return {result: true};\n};\n\n\n// NB: We are cheating and using this function to implement \"AND\" for both\n// \"document matchers\" and \"branched matchers\". They both return result objects\n// but the argument is different: for the former it's a whole doc, whereas for\n// the latter it's an array of \"branched values\".\nvar andSomeMatchers = function (subMatchers) {\n  if (subMatchers.length === 0)\n    return everythingMatcher;\n  if (subMatchers.length === 1)\n    return subMatchers[0];\n\n  return function (docOrBranches) {\n    var ret = {};\n    ret.result = _.all(subMatchers, function (f) {\n      var subResult = f(docOrBranches);\n      // Copy a 'distance' number out of the first sub-matcher that has\n      // one. Yes, this means that if there are multiple $near fields in a\n      // query, something arbitrary happens; this appears to be consistent with\n      // Mongo.\n      if (subResult.result && subResult.distance !== undefined\n          && ret.distance === undefined) {\n        ret.distance = subResult.distance;\n      }\n      // Similarly, propagate arrayIndices from sub-matchers... but to match\n      // MongoDB behavior, this time the *last* sub-matcher with arrayIndices\n      // wins.\n      if (subResult.result && subResult.arrayIndices) {\n        ret.arrayIndices = subResult.arrayIndices;\n      }\n      return subResult.result;\n    });\n\n    // If we didn't actually match, forget any extra metadata we came up with.\n    if (!ret.result) {\n      delete ret.distance;\n      delete ret.arrayIndices;\n    }\n    return ret;\n  };\n};\n\nvar andDocumentMatchers = andSomeMatchers;\nvar andBranchedMatchers = andSomeMatchers;\n\n\n// helpers used by compiled selector code\nLocalCollection._f = {\n  // XXX for _all and _in, consider building 'inquery' at compile time..\n\n  _type: function (v) {\n    if (typeof v === \"number\")\n      return 1;\n    if (typeof v === \"string\")\n      return 2;\n    if (typeof v === \"boolean\")\n      return 8;\n    if (isArray(v))\n      return 4;\n    if (v === null)\n      return 10;\n    if (v instanceof RegExp)\n      // note that typeof(/x/) === \"object\"\n      return 11;\n    if (typeof v === \"function\")\n      return 13;\n    if (v instanceof Date)\n      return 9;\n    if (EJSON.isBinary(v))\n      return 5;\n    if (v instanceof MongoID.ObjectID)\n      return 7;\n    return 3; // object\n\n    // XXX support some/all of these:\n    // 14, symbol\n    // 15, javascript code with scope\n    // 16, 18: 32-bit/64-bit integer\n    // 17, timestamp\n    // 255, minkey\n    // 127, maxkey\n  },\n\n  // deep equality test: use for literal document and array matches\n  _equal: function (a, b) {\n    return EJSON.equals(a, b, {keyOrderSensitive: true});\n  },\n\n  // maps a type code to a value that can be used to sort values of\n  // different types\n  _typeorder: function (t) {\n    // http://www.mongodb.org/display/DOCS/What+is+the+Compare+Order+for+BSON+Types\n    // XXX what is the correct sort position for Javascript code?\n    // ('100' in the matrix below)\n    // XXX minkey/maxkey\n    return [-1,  // (not a type)\n            1,   // number\n            2,   // string\n            3,   // object\n            4,   // array\n            5,   // binary\n            -1,  // deprecated\n            6,   // ObjectID\n            7,   // bool\n            8,   // Date\n            0,   // null\n            9,   // RegExp\n            -1,  // deprecated\n            100, // JS code\n            2,   // deprecated (symbol)\n            100, // JS code\n            1,   // 32-bit int\n            8,   // Mongo timestamp\n            1    // 64-bit int\n           ][t];\n  },\n\n  // compare two values of unknown type according to BSON ordering\n  // semantics. (as an extension, consider 'undefined' to be less than\n  // any other value.) return negative if a is less, positive if b is\n  // less, or 0 if equal\n  _cmp: function (a, b) {\n    if (a === undefined)\n      return b === undefined ? 0 : -1;\n    if (b === undefined)\n      return 1;\n    var ta = LocalCollection._f._type(a);\n    var tb = LocalCollection._f._type(b);\n    var oa = LocalCollection._f._typeorder(ta);\n    var ob = LocalCollection._f._typeorder(tb);\n    if (oa !== ob)\n      return oa < ob ? -1 : 1;\n    if (ta !== tb)\n      // XXX need to implement this if we implement Symbol or integers, or\n      // Timestamp\n      throw Error(\"Missing type coercion logic in _cmp\");\n    if (ta === 7) { // ObjectID\n      // Convert to string.\n      ta = tb = 2;\n      a = a.toHexString();\n      b = b.toHexString();\n    }\n    if (ta === 9) { // Date\n      // Convert to millis.\n      ta = tb = 1;\n      a = a.getTime();\n      b = b.getTime();\n    }\n\n    if (ta === 1) // double\n      return a - b;\n    if (tb === 2) // string\n      return a < b ? -1 : (a === b ? 0 : 1);\n    if (ta === 3) { // Object\n      // this could be much more efficient in the expected case ...\n      var to_array = function (obj) {\n        var ret = [];\n        for (var key in obj) {\n          ret.push(key);\n          ret.push(obj[key]);\n        }\n        return ret;\n      };\n      return LocalCollection._f._cmp(to_array(a), to_array(b));\n    }\n    if (ta === 4) { // Array\n      for (var i = 0; ; i++) {\n        if (i === a.length)\n          return (i === b.length) ? 0 : -1;\n        if (i === b.length)\n          return 1;\n        var s = LocalCollection._f._cmp(a[i], b[i]);\n        if (s !== 0)\n          return s;\n      }\n    }\n    if (ta === 5) { // binary\n      // Surprisingly, a small binary blob is always less than a large one in\n      // Mongo.\n      if (a.length !== b.length)\n        return a.length - b.length;\n      for (i = 0; i < a.length; i++) {\n        if (a[i] < b[i])\n          return -1;\n        if (a[i] > b[i])\n          return 1;\n      }\n      return 0;\n    }\n    if (ta === 8) { // boolean\n      if (a) return b ? 0 : 1;\n      return b ? -1 : 0;\n    }\n    if (ta === 10) // null\n      return 0;\n    if (ta === 11) // regexp\n      throw Error(\"Sorting not supported on regular expression\"); // XXX\n    // 13: javascript code\n    // 14: symbol\n    // 15: javascript code with scope\n    // 16: 32-bit integer\n    // 17: timestamp\n    // 18: 64-bit integer\n    // 255: minkey\n    // 127: maxkey\n    if (ta === 13) // javascript code\n      throw Error(\"Sorting not supported on Javascript code\"); // XXX\n    throw Error(\"Unknown type to sort\");\n  }\n};\n\n// Oddball function used by upsert.\nLocalCollection._removeDollarOperators = function (selector) {\n  var selectorDoc = {};\n  for (var k in selector)\n    if (k.substr(0, 1) !== '$')\n      selectorDoc[k] = selector[k];\n  return selectorDoc;\n};\n"
  },
  {
    "path": "packages/minimongo/selector_modifier.js",
    "content": "// Returns true if the modifier applied to some document may change the result\n// of matching the document by selector\n// The modifier is always in a form of Object:\n//  - $set\n//    - 'a.b.22.z': value\n//    - 'foo.bar': 42\n//  - $unset\n//    - 'abc.d': 1\nMinimongo.Matcher.prototype.affectedByModifier = function (modifier) {\n  var self = this;\n  // safe check for $set/$unset being objects\n  modifier = _.extend({ $set: {}, $unset: {} }, modifier);\n  var modifiedPaths = _.keys(modifier.$set).concat(_.keys(modifier.$unset));\n  var meaningfulPaths = self._getPaths();\n\n  return _.any(modifiedPaths, function (path) {\n    var mod = path.split('.');\n    return _.any(meaningfulPaths, function (meaningfulPath) {\n      var sel = meaningfulPath.split('.');\n      var i = 0, j = 0;\n\n      while (i < sel.length && j < mod.length) {\n        if (isNumericKey(sel[i]) && isNumericKey(mod[j])) {\n          // foo.4.bar selector affected by foo.4 modifier\n          // foo.3.bar selector unaffected by foo.4 modifier\n          if (sel[i] === mod[j])\n            i++, j++;\n          else\n            return false;\n        } else if (isNumericKey(sel[i])) {\n          // foo.4.bar selector unaffected by foo.bar modifier\n          return false;\n        } else if (isNumericKey(mod[j])) {\n          j++;\n        } else if (sel[i] === mod[j])\n          i++, j++;\n        else\n          return false;\n      }\n\n      // One is a prefix of another, taking numeric fields into account\n      return true;\n    });\n  });\n};\n\n// Minimongo.Sorter gets a similar method, which delegates to a Matcher it made\n// for this exact purpose.\nMinimongo.Sorter.prototype.affectedByModifier = function (modifier) {\n  var self = this;\n  return self._selectorForAffectedByModifier.affectedByModifier(modifier);\n};\n\n// @param modifier - Object: MongoDB-styled modifier with `$set`s and `$unsets`\n//                           only. (assumed to come from oplog)\n// @returns - Boolean: if after applying the modifier, selector can start\n//                     accepting the modified value.\n// NOTE: assumes that document affected by modifier didn't match this Matcher\n// before, so if modifier can't convince selector in a positive change it would\n// stay 'false'.\n// Currently doesn't support $-operators and numeric indices precisely.\nMinimongo.Matcher.prototype.canBecomeTrueByModifier = function (modifier) {\n  var self = this;\n  if (!this.affectedByModifier(modifier))\n    return false;\n\n  modifier = _.extend({$set:{}, $unset:{}}, modifier);\n  var modifierPaths = _.keys(modifier.$set).concat(_.keys(modifier.$unset));\n\n  if (!self.isSimple())\n    return true;\n\n  if (_.any(self._getPaths(), pathHasNumericKeys) ||\n      _.any(modifierPaths, pathHasNumericKeys))\n    return true;\n\n  // check if there is a $set or $unset that indicates something is an\n  // object rather than a scalar in the actual object where we saw $-operator\n  // NOTE: it is correct since we allow only scalars in $-operators\n  // Example: for selector {'a.b': {$gt: 5}} the modifier {'a.b.c':7} would\n  // definitely set the result to false as 'a.b' appears to be an object.\n  var expectedScalarIsObject = _.any(self._selector, function (sel, path) {\n    if (! isOperatorObject(sel))\n      return false;\n    return _.any(modifierPaths, function (modifierPath) {\n      return startsWith(modifierPath, path + '.');\n    });\n  });\n\n  if (expectedScalarIsObject)\n    return false;\n\n  // See if we can apply the modifier on the ideally matching object. If it\n  // still matches the selector, then the modifier could have turned the real\n  // object in the database into something matching.\n  var matchingDocument = EJSON.clone(self.matchingDocument());\n\n  // The selector is too complex, anything can happen.\n  if (matchingDocument === null)\n    return true;\n\n  try {\n    LocalCollection._modify(matchingDocument, modifier);\n  } catch (e) {\n    // Couldn't set a property on a field which is a scalar or null in the\n    // selector.\n    // Example:\n    // real document: { 'a.b': 3 }\n    // selector: { 'a': 12 }\n    // converted selector (ideal document): { 'a': 12 }\n    // modifier: { $set: { 'a.b': 4 } }\n    // We don't know what real document was like but from the error raised by\n    // $set on a scalar field we can reason that the structure of real document\n    // is completely different.\n    if (e.name === \"MinimongoError\" && e.setPropertyError)\n      return false;\n    throw e;\n  }\n\n  return self.documentMatches(matchingDocument).result;\n};\n\n// Returns an object that would match the selector if possible or null if the\n// selector is too complex for us to analyze\n// { 'a.b': { ans: 42 }, 'foo.bar': null, 'foo.baz': \"something\" }\n// => { a: { b: { ans: 42 } }, foo: { bar: null, baz: \"something\" } }\nMinimongo.Matcher.prototype.matchingDocument = function () {\n  var self = this;\n\n  // check if it was computed before\n  if (self._matchingDocument !== undefined)\n    return self._matchingDocument;\n\n  // If the analysis of this selector is too hard for our implementation\n  // fallback to \"YES\"\n  var fallback = false;\n  self._matchingDocument = pathsToTree(self._getPaths(),\n    function (path) {\n      var valueSelector = self._selector[path];\n      if (isOperatorObject(valueSelector)) {\n        // if there is a strict equality, there is a good\n        // chance we can use one of those as \"matching\"\n        // dummy value\n        if (valueSelector.$eq) {\n          return valueSelector.$eq;\n        } else if (valueSelector.$in) {\n          var matcher = new Minimongo.Matcher({ placeholder: valueSelector });\n\n          // Return anything from $in that matches the whole selector for this\n          // path. If nothing matches, returns `undefined` as nothing can make\n          // this selector into `true`.\n          return _.find(valueSelector.$in, function (x) {\n            return matcher.documentMatches({ placeholder: x }).result;\n          });\n        } else if (onlyContainsKeys(valueSelector, ['$gt', '$gte', '$lt', '$lte'])) {\n          var lowerBound = -Infinity, upperBound = Infinity;\n          _.each(['$lte', '$lt'], function (op) {\n            if (_.has(valueSelector, op) && valueSelector[op] < upperBound)\n              upperBound = valueSelector[op];\n          });\n          _.each(['$gte', '$gt'], function (op) {\n            if (_.has(valueSelector, op) && valueSelector[op] > lowerBound)\n              lowerBound = valueSelector[op];\n          });\n\n          var middle = (lowerBound + upperBound) / 2;\n          var matcher = new Minimongo.Matcher({ placeholder: valueSelector });\n          if (!matcher.documentMatches({ placeholder: middle }).result &&\n              (middle === lowerBound || middle === upperBound))\n            fallback = true;\n\n          return middle;\n        } else if (onlyContainsKeys(valueSelector, ['$nin', '$ne'])) {\n          // Since self._isSimple makes sure $nin and $ne are not combined with\n          // objects or arrays, we can confidently return an empty object as it\n          // never matches any scalar.\n          return {};\n        } else {\n          fallback = true;\n        }\n      }\n      return self._selector[path];\n    },\n    _.identity /*conflict resolution is no resolution*/);\n\n  if (fallback)\n    self._matchingDocument = null;\n\n  return self._matchingDocument;\n};\n\nvar getPaths = function (sel) {\n  return _.keys(new Minimongo.Matcher(sel)._paths);\n  return _.chain(sel).map(function (v, k) {\n    // we don't know how to handle $where because it can be anything\n    if (k === \"$where\")\n      return ''; // matches everything\n    // we branch from $or/$and/$nor operator\n    if (_.contains(['$or', '$and', '$nor'], k))\n      return _.map(v, getPaths);\n    // the value is a literal or some comparison operator\n    return k;\n  }).flatten().uniq().value();\n};\n\n// A helper to ensure object has only certain keys\nvar onlyContainsKeys = function (obj, keys) {\n  return _.all(obj, function (v, k) {\n    return _.contains(keys, k);\n  });\n};\n\nvar pathHasNumericKeys = function (path) {\n  return _.any(path.split('.'), isNumericKey);\n}\n\n// XXX from Underscore.String (http://epeli.github.com/underscore.string/)\nvar startsWith = function(str, starts) {\n  return str.length >= starts.length &&\n    str.substring(0, starts.length) === starts;\n};\n"
  },
  {
    "path": "packages/minimongo/selector_projection.js",
    "content": "// Knows how to combine a mongo selector and a fields projection to a new fields\n// projection taking into account active fields from the passed selector.\n// @returns Object - projection object (same as fields option of mongo cursor)\nMinimongo.Matcher.prototype.combineIntoProjection = function (projection) {\n  var self = this;\n  var selectorPaths = Minimongo._pathsElidingNumericKeys(self._getPaths());\n\n  // Special case for $where operator in the selector - projection should depend\n  // on all fields of the document. getSelectorPaths returns a list of paths\n  // selector depends on. If one of the paths is '' (empty string) representing\n  // the root or the whole document, complete projection should be returned.\n  if (_.contains(selectorPaths, ''))\n    return {};\n\n  return combineImportantPathsIntoProjection(selectorPaths, projection);\n};\n\nMinimongo._pathsElidingNumericKeys = function (paths) {\n  var self = this;\n  return _.map(paths, function (path) {\n    return _.reject(path.split('.'), isNumericKey).join('.');\n  });\n};\n\ncombineImportantPathsIntoProjection = function (paths, projection) {\n  var prjDetails = projectionDetails(projection);\n  var tree = prjDetails.tree;\n  var mergedProjection = {};\n\n  // merge the paths to include\n  tree = pathsToTree(paths,\n                     function (path) { return true; },\n                     function (node, path, fullPath) { return true; },\n                     tree);\n  mergedProjection = treeToPaths(tree);\n  if (prjDetails.including) {\n    // both selector and projection are pointing on fields to include\n    // so we can just return the merged tree\n    return mergedProjection;\n  } else {\n    // selector is pointing at fields to include\n    // projection is pointing at fields to exclude\n    // make sure we don't exclude important paths\n    var mergedExclProjection = {};\n    _.each(mergedProjection, function (incl, path) {\n      if (!incl)\n        mergedExclProjection[path] = false;\n    });\n\n    return mergedExclProjection;\n  }\n};\n\n// Returns a set of key paths similar to\n// { 'foo.bar': 1, 'a.b.c': 1 }\nvar treeToPaths = function (tree, prefix) {\n  prefix = prefix || '';\n  var result = {};\n\n  _.each(tree, function (val, key) {\n    if (_.isObject(val))\n      _.extend(result, treeToPaths(val, prefix + key + '.'));\n    else\n      result[prefix + key] = val;\n  });\n\n  return result;\n};\n\n"
  },
  {
    "path": "packages/minimongo/sort.js",
    "content": "// Give a sort spec, which can be in any of these forms:\n//   {\"key1\": 1, \"key2\": -1}\n//   [[\"key1\", \"asc\"], [\"key2\", \"desc\"]]\n//   [\"key1\", [\"key2\", \"desc\"]]\n//\n// (.. with the first form being dependent on the key enumeration\n// behavior of your javascript VM, which usually does what you mean in\n// this case if the key names don't look like integers ..)\n//\n// return a function that takes two objects, and returns -1 if the\n// first object comes first in order, 1 if the second object comes\n// first, or 0 if neither object comes before the other.\n\nMinimongo.Sorter = function (spec, options) {\n  var self = this;\n  options = options || {};\n\n  self._sortSpecParts = [];\n  self._sortFunction = null;\n\n  var addSpecPart = function (path, ascending) {\n    if (!path)\n      throw Error(\"sort keys must be non-empty\");\n    if (path.charAt(0) === '$')\n      throw Error(\"unsupported sort key: \" + path);\n    self._sortSpecParts.push({\n      path: path,\n      lookup: makeLookupFunction(path, {forSort: true}),\n      ascending: ascending\n    });\n  };\n\n  if (spec instanceof Array) {\n    for (var i = 0; i < spec.length; i++) {\n      if (typeof spec[i] === \"string\") {\n        addSpecPart(spec[i], true);\n      } else {\n        addSpecPart(spec[i][0], spec[i][1] !== \"desc\");\n      }\n    }\n  } else if (typeof spec === \"object\") {\n    _.each(spec, function (value, key) {\n      addSpecPart(key, value >= 0);\n    });\n  } else if (typeof spec === \"function\") {\n    self._sortFunction = spec;\n  } else {\n    throw Error(\"Bad sort specification: \" + JSON.stringify(spec));\n  }\n\n  // If a function is specified for sorting, we skip the rest.\n  if (self._sortFunction)\n    return;\n\n  // To implement affectedByModifier, we piggy-back on top of Matcher's\n  // affectedByModifier code; we create a selector that is affected by the same\n  // modifiers as this sort order. This is only implemented on the server.\n  if (self.affectedByModifier) {\n    var selector = {};\n    _.each(self._sortSpecParts, function (spec) {\n      selector[spec.path] = 1;\n    });\n    self._selectorForAffectedByModifier = new Minimongo.Matcher(selector);\n  }\n\n  self._keyComparator = composeComparators(\n    _.map(self._sortSpecParts, function (spec, i) {\n      return self._keyFieldComparator(i);\n    }));\n\n  // If you specify a matcher for this Sorter, _keyFilter may be set to a\n  // function which selects whether or not a given \"sort key\" (tuple of values\n  // for the different sort spec fields) is compatible with the selector.\n  self._keyFilter = null;\n  options.matcher && self._useWithMatcher(options.matcher);\n};\n\n// In addition to these methods, sorter_project.js defines combineIntoProjection\n// on the server only.\n_.extend(Minimongo.Sorter.prototype, {\n  getComparator: function (options) {\n    var self = this;\n\n    // If we have no distances, just use the comparator from the source\n    // specification (which defaults to \"everything is equal\".\n    if (!options || !options.distances) {\n      return self._getBaseComparator();\n    }\n\n    var distances = options.distances;\n\n    // Return a comparator which first tries the sort specification, and if that\n    // says \"it's equal\", breaks ties using $near distances.\n    return composeComparators([self._getBaseComparator(), function (a, b) {\n      if (!distances.has(a._id))\n        throw Error(\"Missing distance for \" + a._id);\n      if (!distances.has(b._id))\n        throw Error(\"Missing distance for \" + b._id);\n      return distances.get(a._id) - distances.get(b._id);\n    }]);\n  },\n\n  _getPaths: function () {\n    var self = this;\n    return _.pluck(self._sortSpecParts, 'path');\n  },\n\n  // Finds the minimum key from the doc, according to the sort specs.  (We say\n  // \"minimum\" here but this is with respect to the sort spec, so \"descending\"\n  // sort fields mean we're finding the max for that field.)\n  //\n  // Note that this is NOT \"find the minimum value of the first field, the\n  // minimum value of the second field, etc\"... it's \"choose the\n  // lexicographically minimum value of the key vector, allowing only keys which\n  // you can find along the same paths\".  ie, for a doc {a: [{x: 0, y: 5}, {x:\n  // 1, y: 3}]} with sort spec {'a.x': 1, 'a.y': 1}, the only keys are [0,5] and\n  // [1,3], and the minimum key is [0,5]; notably, [0,3] is NOT a key.\n  _getMinKeyFromDoc: function (doc) {\n    var self = this;\n    var minKey = null;\n\n    self._generateKeysFromDoc(doc, function (key) {\n      if (!self._keyCompatibleWithSelector(key))\n        return;\n\n      if (minKey === null) {\n        minKey = key;\n        return;\n      }\n      if (self._compareKeys(key, minKey) < 0) {\n        minKey = key;\n      }\n    });\n\n    // This could happen if our key filter somehow filters out all the keys even\n    // though somehow the selector matches.\n    if (minKey === null)\n      throw Error(\"sort selector found no keys in doc?\");\n    return minKey;\n  },\n\n  _keyCompatibleWithSelector: function (key) {\n    var self = this;\n    return !self._keyFilter || self._keyFilter(key);\n  },\n\n  // Iterates over each possible \"key\" from doc (ie, over each branch), calling\n  // 'cb' with the key.\n  _generateKeysFromDoc: function (doc, cb) {\n    var self = this;\n\n    if (self._sortSpecParts.length === 0)\n      throw new Error(\"can't generate keys without a spec\");\n\n    // maps index -> ({'' -> value} or {path -> value})\n    var valuesByIndexAndPath = [];\n\n    var pathFromIndices = function (indices) {\n      return indices.join(',') + ',';\n    };\n\n    var knownPaths = null;\n\n    _.each(self._sortSpecParts, function (spec, whichField) {\n      // Expand any leaf arrays that we find, and ignore those arrays\n      // themselves.  (We never sort based on an array itself.)\n      var branches = expandArraysInBranches(spec.lookup(doc), true);\n\n      // If there are no values for a key (eg, key goes to an empty array),\n      // pretend we found one null value.\n      if (!branches.length)\n        branches = [{value: null}];\n\n      var usedPaths = false;\n      valuesByIndexAndPath[whichField] = {};\n      _.each(branches, function (branch) {\n        if (!branch.arrayIndices) {\n          // If there are no array indices for a branch, then it must be the\n          // only branch, because the only thing that produces multiple branches\n          // is the use of arrays.\n          if (branches.length > 1)\n            throw Error(\"multiple branches but no array used?\");\n          valuesByIndexAndPath[whichField][''] = branch.value;\n          return;\n        }\n\n        usedPaths = true;\n        var path = pathFromIndices(branch.arrayIndices);\n        if (_.has(valuesByIndexAndPath[whichField], path))\n          throw Error(\"duplicate path: \" + path);\n        valuesByIndexAndPath[whichField][path] = branch.value;\n\n        // If two sort fields both go into arrays, they have to go into the\n        // exact same arrays and we have to find the same paths.  This is\n        // roughly the same condition that makes MongoDB throw this strange\n        // error message.  eg, the main thing is that if sort spec is {a: 1,\n        // b:1} then a and b cannot both be arrays.\n        //\n        // (In MongoDB it seems to be OK to have {a: 1, 'a.x.y': 1} where 'a'\n        // and 'a.x.y' are both arrays, but we don't allow this for now.\n        // #NestedArraySort\n        // XXX achieve full compatibility here\n        if (knownPaths && !_.has(knownPaths, path)) {\n          throw Error(\"cannot index parallel arrays\");\n        }\n      });\n\n      if (knownPaths) {\n        // Similarly to above, paths must match everywhere, unless this is a\n        // non-array field.\n        if (!_.has(valuesByIndexAndPath[whichField], '') &&\n            _.size(knownPaths) !== _.size(valuesByIndexAndPath[whichField])) {\n          throw Error(\"cannot index parallel arrays!\");\n        }\n      } else if (usedPaths) {\n        knownPaths = {};\n        _.each(valuesByIndexAndPath[whichField], function (x, path) {\n          knownPaths[path] = true;\n        });\n      }\n    });\n\n    if (!knownPaths) {\n      // Easy case: no use of arrays.\n      var soleKey = _.map(valuesByIndexAndPath, function (values) {\n        if (!_.has(values, ''))\n          throw Error(\"no value in sole key case?\");\n        return values[''];\n      });\n      cb(soleKey);\n      return;\n    }\n\n    _.each(knownPaths, function (x, path) {\n      var key = _.map(valuesByIndexAndPath, function (values) {\n        if (_.has(values, ''))\n          return values[''];\n        if (!_.has(values, path))\n          throw Error(\"missing path?\");\n        return values[path];\n      });\n      cb(key);\n    });\n  },\n\n  // Takes in two keys: arrays whose lengths match the number of spec\n  // parts. Returns negative, 0, or positive based on using the sort spec to\n  // compare fields.\n  _compareKeys: function (key1, key2) {\n    var self = this;\n    if (key1.length !== self._sortSpecParts.length ||\n        key2.length !== self._sortSpecParts.length) {\n      throw Error(\"Key has wrong length\");\n    }\n\n    return self._keyComparator(key1, key2);\n  },\n\n  // Given an index 'i', returns a comparator that compares two key arrays based\n  // on field 'i'.\n  _keyFieldComparator: function (i) {\n    var self = this;\n    var invert = !self._sortSpecParts[i].ascending;\n    return function (key1, key2) {\n      var compare = LocalCollection._f._cmp(key1[i], key2[i]);\n      if (invert)\n        compare = -compare;\n      return compare;\n    };\n  },\n\n  // Returns a comparator that represents the sort specification (but not\n  // including a possible geoquery distance tie-breaker).\n  _getBaseComparator: function () {\n    var self = this;\n\n    if (self._sortFunction)\n      return self._sortFunction;\n\n    // If we're only sorting on geoquery distance and no specs, just say\n    // everything is equal.\n    if (!self._sortSpecParts.length) {\n      return function (doc1, doc2) {\n        return 0;\n      };\n    }\n\n    return function (doc1, doc2) {\n      var key1 = self._getMinKeyFromDoc(doc1);\n      var key2 = self._getMinKeyFromDoc(doc2);\n      return self._compareKeys(key1, key2);\n    };\n  },\n\n  // In MongoDB, if you have documents\n  //    {_id: 'x', a: [1, 10]} and\n  //    {_id: 'y', a: [5, 15]},\n  // then C.find({}, {sort: {a: 1}}) puts x before y (1 comes before 5).\n  // But  C.find({a: {$gt: 3}}, {sort: {a: 1}}) puts y before x (1 does not\n  // match the selector, and 5 comes before 10).\n  //\n  // The way this works is pretty subtle!  For example, if the documents\n  // are instead {_id: 'x', a: [{x: 1}, {x: 10}]}) and\n  //             {_id: 'y', a: [{x: 5}, {x: 15}]}),\n  // then C.find({'a.x': {$gt: 3}}, {sort: {'a.x': 1}}) and\n  //      C.find({a: {$elemMatch: {x: {$gt: 3}}}}, {sort: {'a.x': 1}})\n  // both follow this rule (y before x).  (ie, you do have to apply this\n  // through $elemMatch.)\n  //\n  // So if you pass a matcher to this sorter's constructor, we will attempt to\n  // skip sort keys that don't match the selector. The logic here is pretty\n  // subtle and undocumented; we've gotten as close as we can figure out based\n  // on our understanding of Mongo's behavior.\n  _useWithMatcher: function (matcher) {\n    var self = this;\n\n    if (self._keyFilter)\n      throw Error(\"called _useWithMatcher twice?\");\n\n    // If we are only sorting by distance, then we're not going to bother to\n    // build a key filter.\n    // XXX figure out how geoqueries interact with this stuff\n    if (_.isEmpty(self._sortSpecParts))\n      return;\n\n    var selector = matcher._selector;\n\n    // If the user just passed a literal function to find(), then we can't get a\n    // key filter from it.\n    if (selector instanceof Function)\n      return;\n\n    var constraintsByPath = {};\n    _.each(self._sortSpecParts, function (spec, i) {\n      constraintsByPath[spec.path] = [];\n    });\n\n    _.each(selector, function (subSelector, key) {\n      // XXX support $and and $or\n\n      var constraints = constraintsByPath[key];\n      if (!constraints)\n        return;\n\n      // XXX it looks like the real MongoDB implementation isn't \"does the\n      // regexp match\" but \"does the value fall into a range named by the\n      // literal prefix of the regexp\", ie \"foo\" in /^foo(bar|baz)+/  But\n      // \"does the regexp match\" is a good approximation.\n      if (subSelector instanceof RegExp) {\n        // As far as we can tell, using either of the options that both we and\n        // MongoDB support ('i' and 'm') disables use of the key filter. This\n        // makes sense: MongoDB mostly appears to be calculating ranges of an\n        // index to use, which means it only cares about regexps that match\n        // one range (with a literal prefix), and both 'i' and 'm' prevent the\n        // literal prefix of the regexp from actually meaning one range.\n        if (subSelector.ignoreCase || subSelector.multiline)\n          return;\n        constraints.push(regexpElementMatcher(subSelector));\n        return;\n      }\n\n      if (isOperatorObject(subSelector)) {\n        _.each(subSelector, function (operand, operator) {\n          if (_.contains(['$lt', '$lte', '$gt', '$gte'], operator)) {\n            // XXX this depends on us knowing that these operators don't use any\n            // of the arguments to compileElementSelector other than operand.\n            constraints.push(\n              ELEMENT_OPERATORS[operator].compileElementSelector(operand));\n          }\n\n          // See comments in the RegExp block above.\n          if (operator === '$regex' && !subSelector.$options) {\n            constraints.push(\n              ELEMENT_OPERATORS.$regex.compileElementSelector(\n                operand, subSelector));\n          }\n\n          // XXX support {$exists: true}, $mod, $type, $in, $elemMatch\n        });\n        return;\n      }\n\n      // OK, it's an equality thing.\n      constraints.push(equalityElementMatcher(subSelector));\n    });\n\n    // It appears that the first sort field is treated differently from the\n    // others; we shouldn't create a key filter unless the first sort field is\n    // restricted, though after that point we can restrict the other sort fields\n    // or not as we wish.\n    if (_.isEmpty(constraintsByPath[self._sortSpecParts[0].path]))\n      return;\n\n    self._keyFilter = function (key) {\n      return _.all(self._sortSpecParts, function (specPart, index) {\n        return _.all(constraintsByPath[specPart.path], function (f) {\n          return f(key[index]);\n        });\n      });\n    };\n  }\n});\n\n// Given an array of comparators\n// (functions (a,b)->(negative or positive or zero)), returns a single\n// comparator which uses each comparator in order and returns the first\n// non-zero value.\nvar composeComparators = function (comparatorArray) {\n  return function (a, b) {\n    for (var i = 0; i < comparatorArray.length; ++i) {\n      var compare = comparatorArray[i](a, b);\n      if (compare !== 0)\n        return compare;\n    }\n    return 0;\n  };\n};\n"
  },
  {
    "path": "packages/minimongo/sorter_projection.js",
    "content": "Minimongo.Sorter.prototype.combineIntoProjection = function (projection) {\n  var self = this;\n  var specPaths = Minimongo._pathsElidingNumericKeys(self._getPaths());\n  return combineImportantPathsIntoProjection(specPaths, projection);\n};\n"
  },
  {
    "path": "packages/minimongo/wrap_transform.js",
    "content": "// Wrap a transform function to return objects that have the _id field\n// of the untransformed document. This ensures that subsystems such as\n// the observe-sequence package that call `observe` can keep track of\n// the documents identities.\n//\n// - Require that it returns objects\n// - If the return value has an _id field, verify that it matches the\n//   original _id field\n// - If the return value doesn't have an _id field, add it back.\nLocalCollection.wrapTransform = function (transform) {\n  if (! transform)\n    return null;\n\n  // No need to doubly-wrap transforms.\n  if (transform.__wrappedTransform__)\n    return transform;\n\n  var wrapped = function (doc) {\n    if (!_.has(doc, '_id')) {\n      // XXX do we ever have a transform on the oplog's collection? because that\n      // collection has no _id.\n      throw new Error(\"can only transform documents with _id\");\n    }\n\n    var id = doc._id;\n    // XXX consider making tracker a weak dependency and checking Package.tracker here\n    var transformed = Tracker.nonreactive(function () {\n      return transform(doc);\n    });\n\n    if (!isPlainObject(transformed)) {\n      throw new Error(\"transform must return object\");\n    }\n\n    if (_.has(transformed, '_id')) {\n      if (!EJSON.equals(transformed._id, id)) {\n        throw new Error(\"transformed document can't have different _id\");\n      }\n    } else {\n      transformed._id = id;\n    }\n    return transformed;\n  };\n  wrapped.__wrappedTransform__ = true;\n  return wrapped;\n};\n"
  },
  {
    "path": "packages/minimongo/wrap_transform_tests.js",
    "content": "Tinytest.add(\"minimongo - wrapTransform\", function (test) {\n  var wrap = LocalCollection.wrapTransform;\n\n  // Transforming no function gives falsey.\n  test.isFalse(wrap(undefined));\n  test.isFalse(wrap(null));\n\n  // It's OK if you don't change the ID.\n  var validTransform = function (doc) {\n    delete doc.x;\n    doc.y = 42;\n    doc.z = function () { return 43; };\n    return doc;\n  };\n  var transformed = wrap(validTransform)({_id: \"asdf\", x: 54});\n  test.equal(_.keys(transformed), ['_id', 'y', 'z']);\n  test.equal(transformed.y, 42);\n  test.equal(transformed.z(), 43);\n\n  // Ensure that ObjectIDs work (even if the _ids in question are not ===-equal)\n  var oid1 = new MongoID.ObjectID();\n  var oid2 = new MongoID.ObjectID(oid1.toHexString());\n  test.equal(wrap(function () {return {_id: oid2};})({_id: oid1}),\n             {_id: oid2});\n\n  // transform functions must return objects\n  var invalidObjects = [\n    \"asdf\", new MongoID.ObjectID(), false, null, true,\n    27, [123], /adsf/, new Date, function () {}, undefined\n  ];\n  _.each(invalidObjects, function (invalidObject) {\n    var wrapped = wrap(function () { return invalidObject; });\n    test.throws(function () {\n      wrapped({_id: \"asdf\"});\n    });\n  }, /transform must return object/);\n\n  // transform functions may not change _ids\n  var wrapped = wrap(function (doc) { doc._id = 'x'; return doc; });\n  test.throws(function () {\n    wrapped({_id: 'y'});\n  }, /can't have different _id/);\n\n  // transform functions may remove _ids\n  test.equal({_id: 'a', x: 2},\n             wrap(function (d) {delete d._id; return d;})({_id: 'a', x: 2}));\n\n  // test that wrapped transform functions are nonreactive\n  var unwrapped = function (doc) {\n    test.isFalse(Tracker.active);\n    return doc;\n  };\n  var handle = Tracker.autorun(function () {\n    test.isTrue(Tracker.active);\n    wrap(unwrapped)({_id: \"xxx\"});\n  });\n  handle.stop();\n});\n"
  },
  {
    "path": "packages/mobile-experience/README.md",
    "content": "# mobile-experience\n\nA set of Cordova/PhoneGap-specific packages that set some good defaults when building for mobile. These packages only activate when you are building a native Android or iOS app.\n\n1. [fastclick](https://atmospherejs.com/meteor/fastclick) - avoid the 300ms touch delay\n2. [mobile-status-bar](https://atmospherejs.com/meteor/mobile-status-bar) - avoid the status bar information covering up your app content\n3. [launch-screen](https://atmospherejs.com/meteor/launch-screen) - cover the app with a launch image so that people don’t have to see things loading\n"
  },
  {
    "path": "packages/mobile-experience/package.js",
    "content": "Package.describe({\n  name: 'mobile-experience',\n  version: '1.0.4',\n  // Brief, one-line summary of the package.\n  summary: 'Packages for a great mobile user experience',\n  // By default, Meteor will default to using README.md for documentation.\n  // To avoid submitting documentation, set this field to null.\n  documentation: 'README.md'\n});\n\nPackage.onUse(function(api) {\n  api.imply([\n    // Fastclick: remove the 300 ms click event lag in mobile browsers\n    \"fastclick\",\n\n    // A nicer appearance for the status bar in PhoneGap/Cordova apps\n    \"mobile-status-bar\"\n  ], \"web.cordova\");\n\n  api.imply([\n    // Show a nice splash image while your PhoneGap/Cordova app's UI is loading.\n    // Doesn't do anything without Cordova, but we include it everywhere so you\n    // don't need a ton of if statements around your LaunchScreen calls.\n    \"launch-screen\"\n  ]);\n});\n"
  },
  {
    "path": "packages/mobile-status-bar/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/mobile-status-bar/README.md",
    "content": "# mobile-status-bar\n\nThis package allows you to customize the status bar on Meteor\nPhonegap/Cordova apps.\n\nRight now it just exposes the standard `cordova-plugin-statusbar` plugin for\nPhonegap/Cordova with some defaults. For the extensive documentation see the\noriginal [plugin\nrepo](https://github.com/apache/cordova-plugin-statusbar/blob/master/doc/index.md).\n\nYou can set status bar preferences in your [`mobile-config.js` file](http://docs.meteor.com/#mobileconfigjs) like this:\n\n```\nApp.setPreference('StatusBarOverlaysWebView', 'false');\nApp.setPreference('StatusBarBackgroundColor', '#000000');\n```"
  },
  {
    "path": "packages/mobile-status-bar/package.js",
    "content": "Package.describe({\n  summary: \"Good defaults for the mobile status bar\",\n  version: \"1.0.12\"\n});\n\nCordova.depends({\n  'cordova-plugin-statusbar': '2.1.2'\n});\n"
  },
  {
    "path": "packages/modules/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/modules/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/modules/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"acorn\": {\n      \"version\": \"3.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-3.2.0.tgz\",\n      \"from\": \"acorn@>=3.2.0 <3.3.0\"\n    },\n    \"ast-types\": {\n      \"version\": \"0.8.16\",\n      \"resolved\": \"https://registry.npmjs.org/ast-types/-/ast-types-0.8.16.tgz\",\n      \"from\": \"ast-types@>=0.8.16 <0.9.0\"\n    },\n    \"magic-string\": {\n      \"version\": \"0.15.1\",\n      \"resolved\": \"https://registry.npmjs.org/magic-string/-/magic-string-0.15.1.tgz\",\n      \"from\": \"magic-string@>=0.15.0 <0.16.0\"\n    },\n    \"reify\": {\n      \"version\": \"0.3.4\",\n      \"resolved\": \"https://registry.npmjs.org/reify/-/reify-0.3.4.tgz\",\n      \"from\": \"reify@0.3.4\"\n    },\n    \"vlq\": {\n      \"version\": \"0.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/vlq/-/vlq-0.2.1.tgz\",\n      \"from\": \"vlq@>=0.2.1 <0.3.0\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/modules/README.md",
    "content": "# Using JavaScript modules in Meteor\r\n\r\nES2015 module support for Meteor\r\n\r\nRead more at http://docs.meteor.com/#/full/modules"
  },
  {
    "path": "packages/modules/buffer.js",
    "content": "try {\n  Buffer = global.Buffer || require(\"buffer\").Buffer;\n} catch (noBuffer) {}\n"
  },
  {
    "path": "packages/modules/client.js",
    "content": "require(\"./install-packages.js\");\nrequire(\"./stubs.js\");\nrequire(\"./buffer.js\");\nrequire(\"./process.js\");\nrequire(\"reify/lib/runtime\").enable(module.constructor);\n\nexports.addStyles = require(\"./css\").addStyles;\n"
  },
  {
    "path": "packages/modules/css.js",
    "content": "var doc = document;\nvar head = doc.getElementsByTagName(\"head\").item(0);\n\nexports.addStyles = function (css) {\n  var style = doc.createElement(\"style\");\n\n  style.setAttribute(\"type\", \"text/css\");\n\n  // https://msdn.microsoft.com/en-us/library/ms535871(v=vs.85).aspx\n  var internetExplorerSheetObject =\n    style.sheet || // Edge/IE11.\n    style.styleSheet; // Older IEs.\n\n  if (internetExplorerSheetObject) {\n    internetExplorerSheetObject.cssText = css;\n  } else {\n    style.appendChild(doc.createTextNode(css));\n  }\n\n  return head.appendChild(style);\n};\n"
  },
  {
    "path": "packages/modules/install-packages.js",
    "content": "function install(name, mainModule) {\n  var meteorDir = {};\n\n  // Given a package name <name>, install a stub module in the\n  // /node_modules/meteor directory called <name>.js, so that\n  // require.resolve(\"meteor/<name>\") will always return\n  // /node_modules/meteor/<name>.js instead of something like\n  // /node_modules/meteor/<name>/index.js, in the rare but possible event\n  // that the package contains a file called index.js (#6590).\n\n  if (mainModule) {\n    meteorDir[name + \".js\"] = [mainModule, function (require, e, module) {\n      module.exports = require(mainModule);\n    }];\n  } else {\n    // back compat with old Meteor packages\n    meteorDir[name + \".js\"] = function (r, e, module) {\n      module.exports = Package[name];\n    };\n  }\n\n  meteorInstall({\n    node_modules: {\n      meteor: meteorDir\n    }\n  });\n}\n\n// This file will be modified during computeJsOutputFilesMap to include\n// install(<name>) calls for every Meteor package.\n"
  },
  {
    "path": "packages/modules/package.js",
    "content": "Package.describe({\n  name: \"modules\",\n  version: \"0.6.4\",\n  summary: \"CommonJS module system\",\n  documentation: \"README.md\"\n});\n\nNpm.depends({\n  reify: \"0.3.4\"\n});\n\nPackage.onUse(function(api) {\n  api.use(\"underscore\");\n  api.use(\"modules-runtime\");\n  api.mainModule(\"client.js\", \"client\");\n  api.mainModule(\"server.js\", \"server\");\n  api.export(\"meteorInstall\");\n  api.export(\"Buffer\");\n  api.export(\"process\");\n});\n"
  },
  {
    "path": "packages/modules/process.js",
    "content": "try {\n  // The application can run `npm install process` to provide its own\n  // process stub; otherwise this module will provide a partial stub.\n  process = global.process || require(\"process\");\n} catch (noProcess) {\n  process = {};\n}\n\nif (Meteor.isServer) {\n  // Make require(\"process\") work on the server in all versions of Node.\n  meteorInstall({\n    node_modules: {\n      \"process.js\": function (r, e, module) {\n        module.exports = process;\n      }\n    }\n  });\n} else {\n  process.platform = \"browser\";\n  process.nextTick = process.nextTick || Meteor._setImmediate;\n}\n\nif (typeof process.env !== \"object\") {\n  process.env = {};\n}\n\n_.extend(process.env, meteorEnv);\n"
  },
  {
    "path": "packages/modules/server.js",
    "content": "require(\"./install-packages.js\");\nrequire(\"./buffer.js\");\nrequire(\"./process.js\");\nrequire(\"reify/lib/runtime\").enable(module.constructor);\n"
  },
  {
    "path": "packages/modules/stubs.js",
    "content": "try {\n  // When meteor-node-stubs is installed in the application's root\n  // node_modules directory, requiring it here installs aliases for stubs\n  // for all Node built-in modules, such as fs, util, and http.\n  require(\"meteor-node-stubs\");\n} catch (noStubs) {}\n"
  },
  {
    "path": "packages/modules-runtime/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/modules-runtime/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/modules-runtime/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"install\": {\n      \"version\": \"0.8.1\",\n      \"resolved\": \"https://registry.npmjs.org/install/-/install-0.8.1.tgz\",\n      \"from\": \"install@0.8.1\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/modules-runtime/README.md",
    "content": "## modules-runtime\n\nThis package implements the `meteorInstall` function that is used and\nre-exported by the `modules` package. Do not depend directly on this\npackage (unless you know what you're doing); depend instead on the\n`modules` package.\n"
  },
  {
    "path": "packages/modules-runtime/modules-runtime-tests.js",
    "content": "Tinytest.add('modules', function (test) {\n  test.equal(typeof meteorInstall, \"function\");\n  var require = meteorInstall();\n  test.equal(typeof require, \"function\");\n});\n"
  },
  {
    "path": "packages/modules-runtime/modules-runtime.js",
    "content": "var options = {};\nvar hasOwn = options.hasOwnProperty;\n\n// RegExp matching strings that don't start with a `.` or a `/`.\nvar topLevelIdPattern = /^[^./]/;\n\n// This function will be called whenever a module identifier that hasn't\n// been installed is required. For backwards compatibility, and so that we\n// can require binary dependencies on the server, we implement the\n// fallback in terms of Npm.require.\noptions.fallback = function (id, parentId, error) {\n  // For simplicity, we honor only top-level module identifiers here.\n  // We could try to honor relative and absolute module identifiers by\n  // somehow combining `id` with `dir`, but we'd have to be really careful\n  // that the resulting modules were located in a known directory (not\n  // some arbitrary location on the file system), and we only really need\n  // the fallback for dependencies installed in node_modules directories.\n  if (topLevelIdPattern.test(id)) {\n    if (typeof Npm === \"object\" &&\n        typeof Npm.require === \"function\") {\n      return Npm.require(id);\n    }\n  }\n\n  throw error;\n};\n\noptions.fallback.resolve = function (id, parentId, error) {\n  if (Meteor.isServer &&\n      topLevelIdPattern.test(id)) {\n    // Allow any top-level identifier to resolve to itself on the server,\n    // so that options.fallback can have a chance to handle it.\n    return id;\n  }\n\n  throw error;\n};\n\nmeteorInstall = makeInstaller(options);\nvar Mp = meteorInstall.Module.prototype;\n\nif (Meteor.isServer) {\n  Mp.useNode = function () {\n    if (typeof npmRequire !== \"function\") {\n      // Can't use Node if npmRequire is not defined.\n      return false;\n    }\n\n    var parts = this.id.split(\"/\");\n    var start = 0;\n    if (parts[start] === \"\") ++start;\n    if (parts[start] === \"node_modules\" &&\n        parts[start + 1] === \"meteor\") {\n      start += 2;\n    }\n\n    if (parts.indexOf(\"node_modules\", start) < 0) {\n      // Don't try to use Node for modules that aren't in node_modules\n      // directories.\n      return false;\n    }\n\n    try {\n      npmRequire.resolve(this.id);\n    } catch (e) {\n      return false;\n    }\n\n    this.exports = npmRequire(this.id);\n\n    return true;\n  };\n}\n"
  },
  {
    "path": "packages/modules-runtime/package.js",
    "content": "Package.describe({\n  name: \"modules-runtime\",\n  version: \"0.6.4_1\",\n  summary: \"CommonJS module system\",\n  git: \"https://github.com/benjamn/install\",\n  documentation: \"README.md\"\n});\n\nNpm.depends({\n  install: \"0.8.1\"\n});\n\nPackage.onUse(function(api) {\n  api.addFiles(\".npm/package/node_modules/install/install.js\", [\n    \"client\",\n    \"server\"\n  ], {\n    bare: true\n  });\n\n  api.addFiles(\"modules-runtime.js\");\n  api.export(\"meteorInstall\");\n});\n\nPackage.onTest(function(api) {\n  api.use(\"tinytest\");\n  api.use(\"modules\"); // Test modules-runtime via modules.\n  api.addFiles(\"modules-runtime-tests.js\");\n});\n"
  },
  {
    "path": "packages/mongo/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/mongo/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/mongo/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/mongo/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"mongodb-uri\": {\n      \"version\": \"0.9.7\",\n      \"resolved\": \"https://registry.npmjs.org/mongodb-uri/-/mongodb-uri-0.9.7.tgz\",\n      \"from\": \"https://registry.npmjs.org/mongodb-uri/-/mongodb-uri-0.9.7.tgz\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/mongo/README.md",
    "content": "# mongo\n\nThe `mongo` package is a [full stack database\ndriver](https://www.meteor.com/full-stack-db-drivers) that provides\nseveral paramount pieces of functionality to work with MongoDB in\nMeteor:\n\n- an efficient [Livequery][livequery] implementation providing real-time\n  updates from the database by consuming the MongoDB replication log\n- a fall-back Livequery implementation for cases when the replication log is not\n  available, implemented by polling the database\n- DDP RPC end-points for updating the data from clients connected over the wire\n- Serialization and deserialization of updates to the DDP format\n\nTo learn more about Livequery, see the [project page on\nwww.meteor.com][livequery].\n\n[livequery]: https://www.meteor.com/livequery\n\n## Direct access to npm mongodb API\n\nOn the server, the `mongo` package is implemented using the\n[npm `mongodb` module](https://www.npmjs.com/package/mongodb).  If you'd like\ndirect access to this module, you can find it at\n`MongoInternals.NpmModules.mongodb.module`. Its version can be read at\n`MongoInternals.NpmModules.mongodb.version`.\n\nAdditionally, you can call `c.rawCollection()` or `c.rawDatabase()` on any\n`Mongo.Collection` to get the object from the npm `mongodb` module corresponding\nto the collection or database.  This is documented at\nhttp://mongodb.github.io/node-mongodb-native/\n\nThe version of `mongo` used may change incompatibly from version to version of\nMeteor (or we may even replace it with an entirely different implementation);\nuse at your own risk.\n"
  },
  {
    "path": "packages/mongo/allow_tests.js",
    "content": "if (Meteor.isServer) {\n  // Set up allow/deny rules for test collections\n\n  var allowCollections = {};\n\n  // We create the collections in the publisher (instead of using a method or\n  // something) because if we made them with a method, we'd need to follow the\n  // method with some subscribes, and it's possible that the method call would\n  // be delayed by a wait method and the subscribe messages would be sent before\n  // it and fail due to the collection not yet existing. So we are very hacky\n  // and use a publish.\n  Meteor.publish(\"allowTests\", function (nonce, idGeneration) {\n    check(nonce, String);\n    check(idGeneration, String);\n    var cursors = [];\n    var needToConfigure = undefined;\n\n    // helper for defining a collection. we are careful to create just one\n    // Mongo.Collection even if the sub body is rerun, by caching them.\n    var defineCollection = function(name, insecure, transform) {\n      var fullName = name + idGeneration + nonce;\n\n      var collection;\n      if (_.has(allowCollections, fullName)) {\n        collection = allowCollections[fullName];\n        if (needToConfigure === true)\n          throw new Error(\"collections inconsistently exist\");\n        needToConfigure = false;\n      } else {\n        collection = new Mongo.Collection(\n          fullName, {idGeneration: idGeneration, transform: transform});\n        allowCollections[fullName] = collection;\n        if (needToConfigure === false)\n          throw new Error(\"collections inconsistently don't exist\");\n        needToConfigure = true;\n        collection._insecure = insecure;\n        var m = {};\n        m[\"clear-collection-\" + fullName] = function() {\n          collection.remove({});\n        };\n        Meteor.methods(m);\n      }\n\n      cursors.push(collection.find());\n      return collection;\n    };\n\n    var insecureCollection = defineCollection(\n      \"collection-insecure\", true /*insecure*/);\n    // totally locked down collection\n    var lockedDownCollection = defineCollection(\n      \"collection-locked-down\", false /*insecure*/);\n    // restricted collection with same allowed modifications, both with and\n    // without the `insecure` package\n    var restrictedCollectionDefaultSecure = defineCollection(\n      \"collection-restrictedDefaultSecure\", false /*insecure*/);\n    var restrictedCollectionDefaultInsecure = defineCollection(\n      \"collection-restrictedDefaultInsecure\", true /*insecure*/);\n    var restrictedCollectionForUpdateOptionsTest = defineCollection(\n      \"collection-restrictedForUpdateOptionsTest\", true /*insecure*/);\n    var restrictedCollectionForPartialAllowTest = defineCollection(\n      \"collection-restrictedForPartialAllowTest\", true /*insecure*/);\n    var restrictedCollectionForPartialDenyTest = defineCollection(\n      \"collection-restrictedForPartialDenyTest\", true /*insecure*/);\n    var restrictedCollectionForFetchTest = defineCollection(\n      \"collection-restrictedForFetchTest\", true /*insecure*/);\n    var restrictedCollectionForFetchAllTest = defineCollection(\n      \"collection-restrictedForFetchAllTest\", true /*insecure*/);\n    var restrictedCollectionWithTransform = defineCollection(\n      \"withTransform\", false, function (doc) {\n        return doc.a;\n      });\n    var restrictedCollectionForInvalidTransformTest = defineCollection(\n      \"collection-restrictedForInvalidTransform\", false /*insecure*/);\n    var restrictedCollectionForClientIdTest = defineCollection(\n      \"collection-restrictedForClientIdTest\", false /*insecure*/);\n\n    if (needToConfigure) {\n      restrictedCollectionWithTransform.allow({\n        insert: function (userId, doc) {\n          return doc.foo === \"foo\";\n        },\n        update: function (userId, doc) {\n          return doc.foo === \"foo\";\n        },\n        remove: function (userId, doc) {\n          return doc.bar === \"bar\";\n        }\n      });\n      restrictedCollectionWithTransform.allow({\n        // transform: null means that doc here is the top level, not the 'a'\n        // element.\n        transform: null,\n        insert: function (userId, doc) {\n          return !!doc.topLevelField;\n        },\n        update: function (userId, doc) {\n          return !!doc.topLevelField;\n        }\n      });\n      restrictedCollectionForInvalidTransformTest.allow({\n        // transform must return an object which is not a mongo id\n        transform: function (doc) { return doc._id; },\n        insert: function () { return true; }\n      });\n      restrictedCollectionForClientIdTest.allow({\n        // This test just requires the collection to trigger the restricted\n        // case.\n        insert: function () { return true; }\n      });\n\n      // two calls to allow to verify that either validator is sufficient.\n      var allows = [{\n        insert: function(userId, doc) {\n          return doc.canInsert;\n        },\n        update: function(userId, doc) {\n          return doc.canUpdate;\n        },\n        remove: function (userId, doc) {\n          return doc.canRemove;\n        }\n      }, {\n        insert: function(userId, doc) {\n          return doc.canInsert2;\n        },\n        update: function(userId, doc, fields, modifier) {\n          return -1 !== _.indexOf(fields, 'canUpdate2');\n        },\n        remove: function(userId, doc) {\n          return doc.canRemove2;\n        }\n      }];\n\n      // two calls to deny to verify that either one blocks the change.\n      var denies = [{\n        insert: function(userId, doc) {\n          return doc.cantInsert;\n        },\n        remove: function (userId, doc) {\n          return doc.cantRemove;\n        }\n      }, {\n        insert: function(userId, doc) {\n          // Don't allow explicit ID to be set by the client.\n          return _.has(doc, '_id');\n        },\n        update: function(userId, doc, fields, modifier) {\n          return -1 !== _.indexOf(fields, 'verySecret');\n        }\n      }];\n\n      _.each([\n        restrictedCollectionDefaultSecure,\n        restrictedCollectionDefaultInsecure,\n        restrictedCollectionForUpdateOptionsTest\n      ], function (collection) {\n        _.each(allows, function (allow) {\n          collection.allow(allow);\n        });\n        _.each(denies, function (deny) {\n          collection.deny(deny);\n        });\n      });\n\n      // just restrict one operation so that we can verify that others\n      // fail\n      restrictedCollectionForPartialAllowTest.allow({\n        insert: function() {}\n      });\n      restrictedCollectionForPartialDenyTest.deny({\n        insert: function() {}\n      });\n\n      // verify that we only fetch the fields specified - we should\n      // be fetching just field1, field2, and field3.\n      restrictedCollectionForFetchTest.allow({\n        insert: function() { return true; },\n        update: function(userId, doc) {\n          // throw fields in doc so that we can inspect them in test\n          throw new Meteor.Error(\n            999, \"Test: Fields in doc: \" + _.keys(doc).sort().join(','));\n        },\n        remove: function(userId, doc) {\n          // throw fields in doc so that we can inspect them in test\n          throw new Meteor.Error(\n            999, \"Test: Fields in doc: \" + _.keys(doc).sort().join(','));\n        },\n        fetch: ['field1']\n      });\n      restrictedCollectionForFetchTest.allow({\n        fetch: ['field2']\n      });\n      restrictedCollectionForFetchTest.deny({\n        fetch: ['field3']\n      });\n\n      // verify that not passing fetch to one of the calls to allow\n      // causes all fields to be fetched\n      restrictedCollectionForFetchAllTest.allow({\n        insert: function() { return true; },\n        update: function(userId, doc) {\n          // throw fields in doc so that we can inspect them in test\n          throw new Meteor.Error(\n            999, \"Test: Fields in doc: \" + _.keys(doc).sort().join(','));\n        },\n        remove: function(userId, doc) {\n          // throw fields in doc so that we can inspect them in test\n          throw new Meteor.Error(\n            999, \"Test: Fields in doc: \" + _.keys(doc).sort().join(','));\n        },\n        fetch: ['field1']\n      });\n      restrictedCollectionForFetchAllTest.allow({\n        update: function() { return true; }\n      });\n    }\n\n    return cursors;\n  });\n}\n\nif (Meteor.isClient) {\n  _.each(['STRING', 'MONGO'], function (idGeneration) {\n    // Set up a bunch of test collections... on the client! They match the ones\n    // created by setUpAllowTestsCollections.\n\n    var nonce = Random.id();\n    // Tell the server to make, configure, and publish a set of collections unique\n    // to our test run. Since the method does not unblock, this will complete\n    // running on the server before anything else happens.\n    Meteor.subscribe('allowTests', nonce, idGeneration);\n\n    // helper for defining a collection, subscribing to it, and defining\n    // a method to clear it\n    var defineCollection = function(name, transform) {\n      var fullName = name + idGeneration + nonce;\n      var collection = new Mongo.Collection(\n        fullName, {idGeneration: idGeneration, transform: transform});\n\n      collection.callClearMethod = function (callback) {\n        Meteor.call(\"clear-collection-\" + fullName, callback);\n      };\n      collection.unnoncedName = name + idGeneration;\n      return collection;\n    };\n\n    // totally insecure collection\n    var insecureCollection = defineCollection(\"collection-insecure\");\n\n    // totally locked down collection\n    var lockedDownCollection = defineCollection(\"collection-locked-down\");\n\n    // restricted collection with same allowed modifications, both with and\n    // without the `insecure` package\n    var restrictedCollectionDefaultSecure = defineCollection(\n      \"collection-restrictedDefaultSecure\");\n    var restrictedCollectionDefaultInsecure = defineCollection(\n      \"collection-restrictedDefaultInsecure\");\n    var restrictedCollectionForUpdateOptionsTest = defineCollection(\n      \"collection-restrictedForUpdateOptionsTest\");\n    var restrictedCollectionForPartialAllowTest = defineCollection(\n      \"collection-restrictedForPartialAllowTest\");\n    var restrictedCollectionForPartialDenyTest = defineCollection(\n      \"collection-restrictedForPartialDenyTest\");\n    var restrictedCollectionForFetchTest = defineCollection(\n      \"collection-restrictedForFetchTest\");\n    var restrictedCollectionForFetchAllTest = defineCollection(\n      \"collection-restrictedForFetchAllTest\");\n    var restrictedCollectionWithTransform = defineCollection(\n      \"withTransform\", function (doc) {\n        return doc.a;\n      });\n    var restrictedCollectionForInvalidTransformTest = defineCollection(\n      \"collection-restrictedForInvalidTransform\");\n    var restrictedCollectionForClientIdTest = defineCollection(\n      \"collection-restrictedForClientIdTest\");\n\n    // test that if allow is called once then the collection is\n    // restricted, and that other mutations aren't allowed\n    testAsyncMulti(\"collection - partial allow, \" + idGeneration, [\n      function (test, expect) {\n        restrictedCollectionForPartialAllowTest.update(\n          'foo', {$set: {updated: true}}, expect(function (err, res) {\n            test.equal(err.error, 403);\n          }));\n      }\n    ]);\n\n    // test that if deny is called once then the collection is\n    // restricted, and that other mutations aren't allowed\n    testAsyncMulti(\"collection - partial deny, \" + idGeneration, [\n      function (test, expect) {\n        restrictedCollectionForPartialDenyTest.update(\n          'foo', {$set: {updated: true}}, expect(function (err, res) {\n            test.equal(err.error, 403);\n          }));\n      }\n    ]);\n\n\n    // test that we only fetch the fields specified\n    testAsyncMulti(\"collection - fetch, \" + idGeneration, [\n      function (test, expect) {\n        var fetchId = restrictedCollectionForFetchTest.insert(\n          {field1: 1, field2: 1, field3: 1, field4: 1});\n        var fetchAllId = restrictedCollectionForFetchAllTest.insert(\n          {field1: 1, field2: 1, field3: 1, field4: 1});\n        restrictedCollectionForFetchTest.update(\n          fetchId, {$set: {updated: true}}, expect(function (err, res) {\n            test.equal(err.reason,\n                       \"Test: Fields in doc: _id,field1,field2,field3\");\n          }));\n        restrictedCollectionForFetchTest.remove(\n          fetchId, expect(function (err, res) {\n            test.equal(err.reason,\n                       \"Test: Fields in doc: _id,field1,field2,field3\");\n          }));\n\n        restrictedCollectionForFetchAllTest.update(\n          fetchAllId, {$set: {updated: true}}, expect(function (err, res) {\n            test.equal(err.reason,\n                       \"Test: Fields in doc: _id,field1,field2,field3,field4\");\n          }));\n        restrictedCollectionForFetchAllTest.remove(\n          fetchAllId, expect(function (err, res) {\n            test.equal(err.reason,\n                       \"Test: Fields in doc: _id,field1,field2,field3,field4\");\n          }));\n      }\n    ]);\n\n    (function(){\n      testAsyncMulti(\"collection - restricted factories \" + idGeneration, [\n        function (test, expect) {\n          restrictedCollectionWithTransform.callClearMethod(expect(function () {\n            test.equal(restrictedCollectionWithTransform.find().count(), 0);\n          }));\n        },\n        function (test, expect) {\n          var self = this;\n          restrictedCollectionWithTransform.insert({\n            a: {foo: \"foo\", bar: \"bar\", baz: \"baz\"}\n          }, expect(function (e, res) {\n            test.isFalse(e);\n            test.isTrue(res);\n            self.item1 = res;\n          }));\n          restrictedCollectionWithTransform.insert({\n            a: {foo: \"foo\", bar: \"quux\", baz: \"quux\"},\n            b: \"potato\"\n          }, expect(function (e, res) {\n            test.isFalse(e);\n            test.isTrue(res);\n            self.item2 = res;\n          }));\n          restrictedCollectionWithTransform.insert({\n            a: {foo: \"adsfadf\", bar: \"quux\", baz: \"quux\"},\n            b: \"potato\"\n          }, expect(function (e, res) {\n            test.isTrue(e);\n          }));\n          restrictedCollectionWithTransform.insert({\n            a: {foo: \"bar\"},\n            topLevelField: true\n          }, expect(function (e, res) {\n            test.isFalse(e);\n            test.isTrue(res);\n            self.item3 = res;\n          }));\n        },\n        function (test, expect) {\n          var self = this;\n          // This should work, because there is an update allow for things with\n          // topLevelField.\n          restrictedCollectionWithTransform.update(\n            self.item3, { $set: { xxx: true } }, expect(function (e, res) {\n              test.isFalse(e);\n              test.equal(1, res);\n            }));\n        },\n        function (test, expect) {\n          var self = this;\n          test.equal(\n            restrictedCollectionWithTransform.findOne(self.item1),\n            {_id: self.item1, foo: \"foo\", bar: \"bar\", baz: \"baz\"});\n          restrictedCollectionWithTransform.remove(\n            self.item1, expect(function (e, res) {\n              test.isFalse(e);\n            }));\n          restrictedCollectionWithTransform.remove(\n            self.item2, expect(function (e, res) {\n              test.isTrue(e);\n            }));\n        }\n      ]);\n    })();\n\n    testAsyncMulti(\"collection - insecure, \" + idGeneration, [\n      function (test, expect) {\n        insecureCollection.callClearMethod(expect(function () {\n          test.equal(insecureCollection.find().count(), 0);\n        }));\n      },\n      function (test, expect) {\n        var id = insecureCollection.insert({foo: 'bar'}, expect(function(err, res) {\n          test.equal(res, id);\n          test.equal(insecureCollection.find(id).count(), 1);\n          test.equal(insecureCollection.findOne(id).foo, 'bar');\n        }));\n        test.equal(insecureCollection.find(id).count(), 1);\n        test.equal(insecureCollection.findOne(id).foo, 'bar');\n      }\n    ]);\n\n    testAsyncMulti(\"collection - locked down, \" + idGeneration, [\n      function (test, expect) {\n        lockedDownCollection.callClearMethod(expect(function() {\n          test.equal(lockedDownCollection.find().count(), 0);\n        }));\n      },\n      function (test, expect) {\n        lockedDownCollection.insert({foo: 'bar'}, expect(function (err, res) {\n          test.equal(err.error, 403);\n          test.equal(lockedDownCollection.find().count(), 0);\n        }));\n      }\n    ]);\n\n    (function () {\n      var collection = restrictedCollectionForUpdateOptionsTest;\n      var id1, id2;\n      testAsyncMulti(\"collection - update options, \" + idGeneration, [\n        // init\n        function (test, expect) {\n          collection.callClearMethod(expect(function () {\n            test.equal(collection.find().count(), 0);\n          }));\n        },\n        // put a few objects\n        function (test, expect) {\n          var doc = {canInsert: true, canUpdate: true};\n          id1 = collection.insert(doc);\n          id2 = collection.insert(doc);\n          collection.insert(doc);\n          collection.insert(doc, expect(function (err, res) {\n            test.isFalse(err);\n            test.equal(collection.find().count(), 4);\n          }));\n        },\n        // update by id\n        function (test, expect) {\n          collection.update(\n            id1,\n            {$set: {updated: true}},\n            expect(function (err, res) {\n              test.isFalse(err);\n              test.equal(res, 1);\n              test.equal(collection.find({updated: true}).count(), 1);\n            }));\n        },\n        // update by id in an object\n        function (test, expect) {\n          collection.update(\n            {_id: id2},\n            {$set: {updated: true}},\n            expect(function (err, res) {\n              test.isFalse(err);\n              test.equal(res, 1);\n              test.equal(collection.find({updated: true}).count(), 2);\n            }));\n        },\n        // update with replacement operator not allowed, and has nice error.\n        function (test, expect) {\n          collection.update(\n            {_id: id2},\n            {_id: id2, updated: true},\n            expect(function (err, res) {\n              test.equal(err.error, 403);\n              test.matches(err.reason, /In a restricted/);\n              // unchanged\n              test.equal(collection.find({updated: true}).count(), 2);\n            }));\n        },\n        // upsert not allowed, and has nice error.\n        function (test, expect) {\n          collection.update(\n            {_id: id2},\n            {$set: { upserted: true }},\n            { upsert: true },\n            expect(function (err, res) {\n              test.equal(err.error, 403);\n              test.matches(err.reason, /in a restricted/);\n              test.equal(collection.find({ upserted: true }).count(), 0);\n            }));\n        },\n        // update with rename operator not allowed, and has nice error.\n        function (test, expect) {\n          collection.update(\n            {_id: id2},\n            {$rename: {updated: 'asdf'}},\n            expect(function (err, res) {\n              test.equal(err.error, 403);\n              test.matches(err.reason, /not allowed/);\n              // unchanged\n              test.equal(collection.find({updated: true}).count(), 2);\n            }));\n        },\n        // update method with a non-ID selector is not allowed\n        function (test, expect) {\n          // We shouldn't even send the method...\n          test.throws(function () {\n            collection.update(\n              {updated: {$exists: false}},\n              {$set: {updated: true}});\n          });\n          // ... but if we did, the server would reject it too.\n          Meteor.call(\n            '/' + collection._name + '/update',\n            {updated: {$exists: false}},\n            {$set: {updated: true}},\n            expect(function (err, res) {\n              test.equal(err.error, 403);\n              // unchanged\n              test.equal(collection.find({updated: true}).count(), 2);\n            }));\n        },\n        // make sure it doesn't think that {_id: 'foo', something: else} is ok.\n        function (test, expect) {\n          test.throws(function () {\n            collection.update(\n              {_id: id1, updated: {$exists: false}},\n              {$set: {updated: true}});\n          });\n        },\n        // remove method with a non-ID selector is not allowed\n        function (test, expect) {\n          // We shouldn't even send the method...\n          test.throws(function () {\n            collection.remove({updated: true});\n          });\n          // ... but if we did, the server would reject it too.\n          Meteor.call(\n            '/' + collection._name + '/remove',\n            {updated: true},\n            expect(function (err, res) {\n              test.equal(err.error, 403);\n              // unchanged\n              test.equal(collection.find({updated: true}).count(), 2);\n            }));\n        }\n      ]);\n    }) ();\n\n    _.each(\n      [restrictedCollectionDefaultInsecure, restrictedCollectionDefaultSecure],\n      function(collection) {\n        var canUpdateId, canRemoveId;\n\n        testAsyncMulti(\"collection - \" + collection.unnoncedName, [\n          // init\n          function (test, expect) {\n            collection.callClearMethod(expect(function () {\n              test.equal(collection.find().count(), 0);\n            }));\n          },\n\n          // insert with no allows passing. request is denied.\n          function (test, expect) {\n            collection.insert(\n              {},\n              expect(function (err, res) {\n                test.equal(err.error, 403);\n                test.equal(collection.find().count(), 0);\n              }));\n          },\n          // insert with one allow and one deny. denied.\n          function (test, expect) {\n            collection.insert(\n              {canInsert: true, cantInsert: true},\n              expect(function (err, res) {\n                test.equal(err.error, 403);\n                test.equal(collection.find().count(), 0);\n              }));\n          },\n          // insert with one allow and other deny. denied.\n          function (test, expect) {\n            collection.insert(\n              {canInsert: true, _id: Random.id()},\n              expect(function (err, res) {\n                test.equal(err.error, 403);\n                test.equal(collection.find().count(), 0);\n              }));\n          },\n          // insert one allow passes. allowed.\n          function (test, expect) {\n            collection.insert(\n              {canInsert: true},\n              expect(function (err, res) {\n                test.isFalse(err);\n                test.equal(collection.find().count(), 1);\n              }));\n          },\n          // insert other allow passes. allowed.\n          // includes canUpdate for later.\n          function (test, expect) {\n            canUpdateId = collection.insert(\n              {canInsert2: true, canUpdate: true},\n              expect(function (err, res) {\n                test.isFalse(err);\n                test.equal(collection.find().count(), 2);\n              }));\n          },\n          // yet a third insert executes. this one has canRemove and\n          // cantRemove set for later.\n          function (test, expect) {\n            canRemoveId = collection.insert(\n              {canInsert: true, canRemove: true, cantRemove: true},\n              expect(function (err, res) {\n                test.isFalse(err);\n                test.equal(collection.find().count(), 3);\n              }));\n          },\n\n          // can't update with a non-operator mutation\n          function (test, expect) {\n            collection.update(\n              canUpdateId, {newObject: 1},\n              expect(function (err, res) {\n                test.equal(err.error, 403);\n                test.equal(collection.find().count(), 3);\n              }));\n          },\n\n          // updating dotted fields works as if we are changing their\n          // top part\n          function (test, expect) {\n            collection.update(\n              canUpdateId, {$set: {\"dotted.field\": 1}},\n              expect(function (err, res) {\n                test.isFalse(err);\n                test.equal(res, 1);\n                test.equal(collection.findOne(canUpdateId).dotted.field, 1);\n              }));\n          },\n          function (test, expect) {\n            collection.update(\n              canUpdateId, {$set: {\"verySecret.field\": 1}},\n              expect(function (err, res) {\n                test.equal(err.error, 403);\n                test.equal(collection.find({verySecret: {$exists: true}}).count(), 0);\n              }));\n          },\n\n          // update doesn't do anything if no docs match\n          function (test, expect) {\n            collection.update(\n              \"doesn't exist\",\n              {$set: {updated: true}},\n              expect(function (err, res) {\n                test.isFalse(err);\n                test.equal(res, 0);\n                // nothing has changed\n                test.equal(collection.find().count(), 3);\n                test.equal(collection.find({updated: true}).count(), 0);\n              }));\n          },\n          // update fails when access is denied trying to set `verySecret`\n          function (test, expect) {\n            collection.update(\n              canUpdateId, {$set: {verySecret: true}},\n              expect(function (err, res) {\n                test.equal(err.error, 403);\n                // nothing has changed\n                test.equal(collection.find().count(), 3);\n                test.equal(collection.find({updated: true}).count(), 0);\n              }));\n          },\n          // update fails when trying to set two fields, one of which is\n          // `verySecret`\n          function (test, expect) {\n            collection.update(\n              canUpdateId, {$set: {updated: true, verySecret: true}},\n              expect(function (err, res) {\n                test.equal(err.error, 403);\n                // nothing has changed\n                test.equal(collection.find().count(), 3);\n                test.equal(collection.find({updated: true}).count(), 0);\n              }));\n          },\n          // update fails when trying to modify docs that don't\n          // have `canUpdate` set\n          function (test, expect) {\n            collection.update(\n              canRemoveId,\n              {$set: {updated: true}},\n              expect(function (err, res) {\n                test.equal(err.error, 403);\n                // nothing has changed\n                test.equal(collection.find().count(), 3);\n                test.equal(collection.find({updated: true}).count(), 0);\n              }));\n          },\n          // update executes when it should\n          function (test, expect) {\n            collection.update(\n              canUpdateId,\n              {$set: {updated: true}},\n              expect(function (err, res) {\n                test.isFalse(err);\n                test.equal(res, 1);\n                test.equal(collection.find({updated: true}).count(), 1);\n              }));\n          },\n\n          // remove fails when trying to modify a doc with no `canRemove` set\n          function (test, expect) {\n            collection.remove(canUpdateId,\n                              expect(function (err, res) {\n              test.equal(err.error, 403);\n              // nothing has changed\n              test.equal(collection.find().count(), 3);\n            }));\n          },\n          // remove fails when trying to modify an doc with `cantRemove`\n          // set\n          function (test, expect) {\n            collection.remove(canRemoveId,\n                              expect(function (err, res) {\n              test.equal(err.error, 403);\n              // nothing has changed\n              test.equal(collection.find().count(), 3);\n            }));\n          },\n\n          // update the doc to remove cantRemove.\n          function (test, expect) {\n            collection.update(\n              canRemoveId,\n              {$set: {cantRemove: false, canUpdate2: true}},\n              expect(function (err, res) {\n                test.isFalse(err);\n                test.equal(res, 1);\n                test.equal(collection.find({cantRemove: true}).count(), 0);\n              }));\n          },\n\n          // now remove can remove it.\n          function (test, expect) {\n            collection.remove(canRemoveId,\n                              expect(function (err, res) {\n              test.isFalse(err);\n              test.equal(res, 1);\n              // successfully removed\n              test.equal(collection.find().count(), 2);\n            }));\n          },\n\n          // try to remove a doc that doesn't exist. see we remove no docs.\n          function (test, expect) {\n            collection.remove('some-random-id-that-never-matches',\n                              expect(function (err, res) {\n              test.isFalse(err);\n              test.equal(res, 0);\n              // nothing removed\n              test.equal(collection.find().count(), 2);\n            }));\n          },\n\n          // methods can still bypass restrictions\n          function (test, expect) {\n            collection.callClearMethod(\n              expect(function (err, res) {\n                test.isFalse(err);\n                // successfully removed\n                test.equal(collection.find().count(), 0);\n            }));\n          }\n        ]);\n      });\n    testAsyncMulti(\n      \"collection - allow/deny transform must return object, \" + idGeneration,\n      [function (test, expect) {\n        restrictedCollectionForInvalidTransformTest.insert({}, expect(function (err, res) {\n          test.isTrue(err);\n        }));\n      }]);\n    testAsyncMulti(\n      \"collection - restricted collection allows client-side id, \" + idGeneration,\n      [function (test, expect) {\n        var self = this;\n        self.id = Random.id();\n        restrictedCollectionForClientIdTest.insert({_id: self.id}, expect(function (err, res) {\n          test.isFalse(err);\n          test.equal(res, self.id);\n          test.equal(restrictedCollectionForClientIdTest.findOne(self.id),\n                     {_id: self.id});\n        }));\n      }]);\n  });  // end idGeneration loop\n}  // end if isClient\n\n\n\n// A few simple server-only tests which don't need to coordinate collections\n// with the client..\nif (Meteor.isServer) {\n  Tinytest.add(\"collection - allow and deny validate options\", function (test) {\n    var collection = new Mongo.Collection(null);\n\n    test.throws(function () {\n      collection.allow({invalidOption: true});\n    });\n    test.throws(function () {\n      collection.deny({invalidOption: true});\n    });\n\n    _.each(['insert', 'update', 'remove', 'fetch'], function (key) {\n      var options = {};\n      options[key] = true;\n      test.throws(function () {\n        collection.allow(options);\n      });\n      test.throws(function () {\n        collection.deny(options);\n      });\n    });\n\n    _.each(['insert', 'update', 'remove'], function (key) {\n      var options = {};\n      options[key] = false;\n      test.throws(function () {\n        collection.allow(options);\n      });\n      test.throws(function () {\n        collection.deny(options);\n      });\n    });\n\n    _.each(['insert', 'update', 'remove'], function (key) {\n      var options = {};\n      options[key] = undefined;\n      test.throws(function () {\n        collection.allow(options);\n      });\n      test.throws(function () {\n        collection.deny(options);\n      });\n    });\n\n    _.each(['insert', 'update', 'remove'], function (key) {\n      var options = {};\n      options[key] = ['an array']; // this should be a function, not an array\n      test.throws(function () {\n        collection.allow(options);\n      });\n      test.throws(function () {\n        collection.deny(options);\n      });\n    });\n\n    test.throws(function () {\n      collection.allow({fetch: function () {}}); // this should be an array\n    });\n  });\n\n  Tinytest.add(\"collection - calling allow restricts\", function (test) {\n    var collection = new Mongo.Collection(null);\n    test.equal(collection._restricted, false);\n    collection.allow({\n      insert: function() {}\n    });\n    test.equal(collection._restricted, true);\n  });\n\n  Tinytest.add(\"collection - global insecure\", function (test) {\n    // note: This test alters the global insecure status, by sneakily hacking\n    // the global Package object!\n    var insecurePackage = Package.insecure;\n\n    Package.insecure = {};\n    var collection = new Mongo.Collection(null);\n    test.equal(collection._isInsecure(), true);\n\n    Package.insecure = undefined;\n    test.equal(collection._isInsecure(), false);\n\n    delete Package.insecure;\n    test.equal(collection._isInsecure(), false);\n\n    collection._insecure = true;\n    test.equal(collection._isInsecure(), true);\n\n    if (insecurePackage)\n      Package.insecure = insecurePackage;\n    else\n      delete Package.insecure;\n  });\n}\n"
  },
  {
    "path": "packages/mongo/collection.js",
    "content": "// options.connection, if given, is a LivedataClient or LivedataServer\n// XXX presently there is no way to destroy/clean up a Collection\n\n/**\n * @summary Namespace for MongoDB-related items\n * @namespace\n */\nMongo = {};\n\n/**\n * @summary Constructor for a Collection\n * @locus Anywhere\n * @instancename collection\n * @class\n * @param {String} name The name of the collection.  If null, creates an unmanaged (unsynchronized) local collection.\n * @param {Object} [options]\n * @param {Object} options.connection The server connection that will manage this collection. Uses the default connection if not specified.  Pass the return value of calling [`DDP.connect`](#ddp_connect) to specify a different server. Pass `null` to specify no connection. Unmanaged (`name` is null) collections cannot specify a connection.\n * @param {String} options.idGeneration The method of generating the `_id` fields of new documents in this collection.  Possible values:\n\n - **`'STRING'`**: random strings\n - **`'MONGO'`**:  random [`Mongo.ObjectID`](#mongo_object_id) values\n\nThe default id generation technique is `'STRING'`.\n * @param {Function} options.transform An optional transformation function. Documents will be passed through this function before being returned from `fetch` or `findOne`, and before being passed to callbacks of `observe`, `map`, `forEach`, `allow`, and `deny`. Transforms are *not* applied for the callbacks of `observeChanges` or to cursors returned from publish functions.\n * @param {Boolean} options.defineMutationMethods Set to `false` to skip setting up the mutation methods that enable insert/update/remove from client code. Default `true`.\n */\nMongo.Collection = function (name, options) {\n  var self = this;\n  if (! (self instanceof Mongo.Collection))\n    throw new Error('use \"new\" to construct a Mongo.Collection');\n\n  if (!name && (name !== null)) {\n    Meteor._debug(\"Warning: creating anonymous collection. It will not be \" +\n                  \"saved or synchronized over the network. (Pass null for \" +\n                  \"the collection name to turn off this warning.)\");\n    name = null;\n  }\n\n  if (name !== null && typeof name !== \"string\") {\n    throw new Error(\n      \"First argument to new Mongo.Collection must be a string or null\");\n  }\n\n  if (options && options.methods) {\n    // Backwards compatibility hack with original signature (which passed\n    // \"connection\" directly instead of in options. (Connections must have a \"methods\"\n    // method.)\n    // XXX remove before 1.0\n    options = {connection: options};\n  }\n  // Backwards compatibility: \"connection\" used to be called \"manager\".\n  if (options && options.manager && !options.connection) {\n    options.connection = options.manager;\n  }\n  options = _.extend({\n    connection: undefined,\n    idGeneration: 'STRING',\n    transform: null,\n    _driver: undefined,\n    _preventAutopublish: false\n  }, options);\n\n  switch (options.idGeneration) {\n  case 'MONGO':\n    self._makeNewID = function () {\n      var src = name\n            ? DDP.randomStream('/collection/' + name)\n            : Random.insecure;\n      return new Mongo.ObjectID(src.hexString(24));\n    };\n    break;\n  case 'STRING':\n  default:\n    self._makeNewID = function () {\n      var src = name\n            ? DDP.randomStream('/collection/' + name)\n            : Random.insecure;\n      return src.id();\n    };\n    break;\n  }\n\n  self._transform = LocalCollection.wrapTransform(options.transform);\n\n  if (! name || options.connection === null)\n    // note: nameless collections never have a connection\n    self._connection = null;\n  else if (options.connection)\n    self._connection = options.connection;\n  else if (Meteor.isClient)\n    self._connection = Meteor.connection;\n  else\n    self._connection = Meteor.server;\n\n  if (!options._driver) {\n    // XXX This check assumes that webapp is loaded so that Meteor.server !==\n    // null. We should fully support the case of \"want to use a Mongo-backed\n    // collection from Node code without webapp\", but we don't yet.\n    // #MeteorServerNull\n    if (name && self._connection === Meteor.server &&\n        typeof MongoInternals !== \"undefined\" &&\n        MongoInternals.defaultRemoteCollectionDriver) {\n      options._driver = MongoInternals.defaultRemoteCollectionDriver();\n    } else {\n      options._driver = LocalCollectionDriver;\n    }\n  }\n\n  self._collection = options._driver.open(name, self._connection);\n  self._name = name;\n  self._driver = options._driver;\n\n  if (self._connection && self._connection.registerStore) {\n    // OK, we're going to be a slave, replicating some remote\n    // database, except possibly with some temporary divergence while\n    // we have unacknowledged RPC's.\n    var ok = self._connection.registerStore(name, {\n      // Called at the beginning of a batch of updates. batchSize is the number\n      // of update calls to expect.\n      //\n      // XXX This interface is pretty janky. reset probably ought to go back to\n      // being its own function, and callers shouldn't have to calculate\n      // batchSize. The optimization of not calling pause/remove should be\n      // delayed until later: the first call to update() should buffer its\n      // message, and then we can either directly apply it at endUpdate time if\n      // it was the only update, or do pauseObservers/apply/apply at the next\n      // update() if there's another one.\n      beginUpdate: function (batchSize, reset) {\n        // pause observers so users don't see flicker when updating several\n        // objects at once (including the post-reconnect reset-and-reapply\n        // stage), and so that a re-sorting of a query can take advantage of the\n        // full _diffQuery moved calculation instead of applying change one at a\n        // time.\n        if (batchSize > 1 || reset)\n          self._collection.pauseObservers();\n\n        if (reset)\n          self._collection.remove({});\n      },\n\n      // Apply an update.\n      // XXX better specify this interface (not in terms of a wire message)?\n      update: function (msg) {\n        var mongoId = MongoID.idParse(msg.id);\n        var doc = self._collection.findOne(mongoId);\n\n        // Is this a \"replace the whole doc\" message coming from the quiescence\n        // of method writes to an object? (Note that 'undefined' is a valid\n        // value meaning \"remove it\".)\n        if (msg.msg === 'replace') {\n          var replace = msg.replace;\n          if (!replace) {\n            if (doc)\n              self._collection.remove(mongoId);\n          } else if (!doc) {\n            self._collection.insert(replace);\n          } else {\n            // XXX check that replace has no $ ops\n            self._collection.update(mongoId, replace);\n          }\n          return;\n        } else if (msg.msg === 'added') {\n          if (doc) {\n            throw new Error(\"Expected not to find a document already present for an add\");\n          }\n          self._collection.insert(_.extend({_id: mongoId}, msg.fields));\n        } else if (msg.msg === 'removed') {\n          if (!doc)\n            throw new Error(\"Expected to find a document already present for removed\");\n          self._collection.remove(mongoId);\n        } else if (msg.msg === 'changed') {\n          if (!doc)\n            throw new Error(\"Expected to find a document to change\");\n          if (!_.isEmpty(msg.fields)) {\n            var modifier = {};\n            _.each(msg.fields, function (value, key) {\n              if (value === undefined) {\n                if (!modifier.$unset)\n                  modifier.$unset = {};\n                modifier.$unset[key] = 1;\n              } else {\n                if (!modifier.$set)\n                  modifier.$set = {};\n                modifier.$set[key] = value;\n              }\n            });\n            self._collection.update(mongoId, modifier);\n          }\n        } else {\n          throw new Error(\"I don't know how to deal with this message\");\n        }\n\n      },\n\n      // Called at the end of a batch of updates.\n      endUpdate: function () {\n        self._collection.resumeObservers();\n      },\n\n      // Called around method stub invocations to capture the original versions\n      // of modified documents.\n      saveOriginals: function () {\n        self._collection.saveOriginals();\n      },\n      retrieveOriginals: function () {\n        return self._collection.retrieveOriginals();\n      },\n\n      // Used to preserve current versions of documents across a store reset.\n      getDoc: function(id) {\n        return self.findOne(id);\n      },\n\n      // To be able to get back to the collection from the store.\n      _getCollection: function () {\n        return self;\n      }\n    });\n\n    if (!ok) {\n      const message = `There is already a collection named \"${name}\"`;\n      if (options._suppressSameNameError === true) {\n        // XXX In theory we do not have to throw when `ok` is falsy. The store is already defined\n        // for this collection name, but this will simply be another reference to it and everything\n        // should work. However, we have historically thrown an error here, so for now we will\n        // skip the error only when `_suppressSameNameError` is `true`, allowing people to opt in\n        // and give this some real world testing.\n        console.warn ? console.warn(message) : console.log(message);\n      } else {\n        throw new Error(message);\n      }\n    }\n  }\n\n  // XXX don't define these until allow or deny is actually used for this\n  // collection. Could be hard if the security rules are only defined on the\n  // server.\n  if (options.defineMutationMethods !== false) {\n    try {\n      self._defineMutationMethods({ useExisting: (options._suppressSameNameError === true) });\n    } catch (error) {\n      // Throw a more understandable error on the server for same collection name\n      if (error.message === `A method named '/${name}/insert' is already defined`)\n        throw new Error(`There is already a collection named \"${name}\"`);\n      throw error;\n    }\n  }\n\n  // autopublish\n  if (Package.autopublish && !options._preventAutopublish && self._connection\n      && self._connection.publish) {\n    self._connection.publish(null, function () {\n      return self.find();\n    }, {is_auto: true});\n  }\n};\n\n///\n/// Main collection API\n///\n\n\n_.extend(Mongo.Collection.prototype, {\n\n  _getFindSelector: function (args) {\n    if (args.length == 0)\n      return {};\n    else\n      return args[0];\n  },\n\n  _getFindOptions: function (args) {\n    var self = this;\n    if (args.length < 2) {\n      return { transform: self._transform };\n    } else {\n      check(args[1], Match.Optional(Match.ObjectIncluding({\n        fields: Match.Optional(Match.OneOf(Object, undefined)),\n        sort: Match.Optional(Match.OneOf(Object, Array, Function, undefined)),\n        limit: Match.Optional(Match.OneOf(Number, undefined)),\n        skip: Match.Optional(Match.OneOf(Number, undefined))\n     })));\n\n      return _.extend({\n        transform: self._transform\n      }, args[1]);\n    }\n  },\n\n  /**\n   * @summary Find the documents in a collection that match the selector.\n   * @locus Anywhere\n   * @method find\n   * @memberOf Mongo.Collection\n   * @instance\n   * @param {MongoSelector} [selector] A query describing the documents to find\n   * @param {Object} [options]\n   * @param {MongoSortSpecifier} options.sort Sort order (default: natural order)\n   * @param {Number} options.skip Number of results to skip at the beginning\n   * @param {Number} options.limit Maximum number of results to return\n   * @param {MongoFieldSpecifier} options.fields Dictionary of fields to return or exclude.\n   * @param {Boolean} options.reactive (Client only) Default `true`; pass `false` to disable reactivity\n   * @param {Function} options.transform Overrides `transform` on the  [`Collection`](#collections) for this cursor.  Pass `null` to disable transformation.\n   * @param {Boolean} options.disableOplog (Server only) Pass true to disable oplog-tailing on this query. This affects the way server processes calls to `observe` on this query. Disabling the oplog can be useful when working with data that updates in large batches.\n   * @param {Number} options.pollingIntervalMs (Server only) How often to poll this query when observing on the server. In milliseconds. Defaults to 10 seconds.\n   * @param {Number} options.pollingThrottleMs (Server only) Minimum time to allow between re-polling. Increasing this will save CPU and mongo load at the expense of slower updates to users. Decreasing this is not recommended. In milliseconds. Defaults to 50 milliseconds.\n   * @returns {Mongo.Cursor}\n   */\n  find: function (/* selector, options */) {\n    // Collection.find() (return all docs) behaves differently\n    // from Collection.find(undefined) (return 0 docs).  so be\n    // careful about the length of arguments.\n    var self = this;\n    var argArray = _.toArray(arguments);\n    return self._collection.find(self._getFindSelector(argArray),\n                                 self._getFindOptions(argArray));\n  },\n\n  /**\n   * @summary Finds the first document that matches the selector, as ordered by sort and skip options.\n   * @locus Anywhere\n   * @method findOne\n   * @memberOf Mongo.Collection\n   * @instance\n   * @param {MongoSelector} [selector] A query describing the documents to find\n   * @param {Object} [options]\n   * @param {MongoSortSpecifier} options.sort Sort order (default: natural order)\n   * @param {Number} options.skip Number of results to skip at the beginning\n   * @param {MongoFieldSpecifier} options.fields Dictionary of fields to return or exclude.\n   * @param {Boolean} options.reactive (Client only) Default true; pass false to disable reactivity\n   * @param {Function} options.transform Overrides `transform` on the [`Collection`](#collections) for this cursor.  Pass `null` to disable transformation.\n   * @returns {Object}\n   */\n  findOne: function (/* selector, options */) {\n    var self = this;\n    var argArray = _.toArray(arguments);\n    return self._collection.findOne(self._getFindSelector(argArray),\n                                    self._getFindOptions(argArray));\n  }\n\n});\n\nMongo.Collection._publishCursor = function (cursor, sub, collection) {\n  var observeHandle = cursor.observeChanges({\n    added: function (id, fields) {\n      sub.added(collection, id, fields);\n    },\n    changed: function (id, fields) {\n      sub.changed(collection, id, fields);\n    },\n    removed: function (id) {\n      sub.removed(collection, id);\n    }\n  });\n\n  // We don't call sub.ready() here: it gets called in livedata_server, after\n  // possibly calling _publishCursor on multiple returned cursors.\n\n  // register stop callback (expects lambda w/ no args).\n  sub.onStop(function () {observeHandle.stop();});\n\n  // return the observeHandle in case it needs to be stopped early\n  return observeHandle;\n};\n\n// protect against dangerous selectors.  falsey and {_id: falsey} are both\n// likely programmer error, and not what you want, particularly for destructive\n// operations.  JS regexps don't serialize over DDP but can be trivially\n// replaced by $regex.\nMongo.Collection._rewriteSelector = function (selector) {\n  // shorthand -- scalars match _id\n  if (LocalCollection._selectorIsId(selector))\n    selector = {_id: selector};\n\n  if (_.isArray(selector)) {\n    // This is consistent with the Mongo console itself; if we don't do this\n    // check passing an empty array ends up selecting all items\n    throw new Error(\"Mongo selector can't be an array.\");\n  }\n\n  if (!selector || (('_id' in selector) && !selector._id))\n    // can't match anything\n    return {_id: Random.id()};\n\n  var ret = {};\n  _.each(selector, function (value, key) {\n    // Mongo supports both {field: /foo/} and {field: {$regex: /foo/}}\n    if (value instanceof RegExp) {\n      ret[key] = convertRegexpToMongoSelector(value);\n    } else if (value && value.$regex instanceof RegExp) {\n      ret[key] = convertRegexpToMongoSelector(value.$regex);\n      // if value is {$regex: /foo/, $options: ...} then $options\n      // override the ones set on $regex.\n      if (value.$options !== undefined)\n        ret[key].$options = value.$options;\n    }\n    else if (_.contains(['$or','$and','$nor'], key)) {\n      // Translate lower levels of $and/$or/$nor\n      ret[key] = _.map(value, function (v) {\n        return Mongo.Collection._rewriteSelector(v);\n      });\n    } else {\n      ret[key] = value;\n    }\n  });\n  return ret;\n};\n\n// convert a JS RegExp object to a Mongo {$regex: ..., $options: ...}\n// selector\nfunction convertRegexpToMongoSelector(regexp) {\n  check(regexp, RegExp); // safety belt\n\n  var selector = {$regex: regexp.source};\n  var regexOptions = '';\n  // JS RegExp objects support 'i', 'm', and 'g'. Mongo regex $options\n  // support 'i', 'm', 'x', and 's'. So we support 'i' and 'm' here.\n  if (regexp.ignoreCase)\n    regexOptions += 'i';\n  if (regexp.multiline)\n    regexOptions += 'm';\n  if (regexOptions)\n    selector.$options = regexOptions;\n\n  return selector;\n};\n\n// 'insert' immediately returns the inserted document's new _id.\n// The others return values immediately if you are in a stub, an in-memory\n// unmanaged collection, or a mongo-backed collection and you don't pass a\n// callback. 'update' and 'remove' return the number of affected\n// documents. 'upsert' returns an object with keys 'numberAffected' and, if an\n// insert happened, 'insertedId'.\n//\n// Otherwise, the semantics are exactly like other methods: they take\n// a callback as an optional last argument; if no callback is\n// provided, they block until the operation is complete, and throw an\n// exception if it fails; if a callback is provided, then they don't\n// necessarily block, and they call the callback when they finish with error and\n// result arguments.  (The insert method provides the document ID as its result;\n// update and remove provide the number of affected docs as the result; upsert\n// provides an object with numberAffected and maybe insertedId.)\n//\n// On the client, blocking is impossible, so if a callback\n// isn't provided, they just return immediately and any error\n// information is lost.\n//\n// There's one more tweak. On the client, if you don't provide a\n// callback, then if there is an error, a message will be logged with\n// Meteor._debug.\n//\n// The intent (though this is actually determined by the underlying\n// drivers) is that the operations should be done synchronously, not\n// generating their result until the database has acknowledged\n// them. In the future maybe we should provide a flag to turn this\n// off.\n\n/**\n * @summary Insert a document in the collection.  Returns its unique _id.\n * @locus Anywhere\n * @method  insert\n * @memberOf Mongo.Collection\n * @instance\n * @param {Object} doc The document to insert. May not yet have an _id attribute, in which case Meteor will generate one for you.\n * @param {Function} [callback] Optional.  If present, called with an error object as the first argument and, if no error, the _id as the second.\n */\nMongo.Collection.prototype.insert = function insert(doc, callback) {\n  // Make sure we were passed a document to insert\n  if (!doc) {\n    throw new Error(\"insert requires an argument\");\n  }\n\n  // Shallow-copy the document and possibly generate an ID\n  doc = _.extend({}, doc);\n\n  if ('_id' in doc) {\n    if (!doc._id || !(typeof doc._id === 'string'\n          || doc._id instanceof Mongo.ObjectID)) {\n      throw new Error(\"Meteor requires document _id fields to be non-empty strings or ObjectIDs\");\n    }\n  } else {\n    let generateId = true;\n\n    // Don't generate the id if we're the client and the 'outermost' call\n    // This optimization saves us passing both the randomSeed and the id\n    // Passing both is redundant.\n    if (this._isRemoteCollection()) {\n      const enclosing = DDP._CurrentInvocation.get();\n      if (!enclosing) {\n        generateId = false;\n      }\n    }\n\n    if (generateId) {\n      doc._id = this._makeNewID();\n    }\n  }\n\n  // On inserts, always return the id that we generated; on all other\n  // operations, just return the result from the collection.\n  var chooseReturnValueFromCollectionResult = function (result) {\n    if (doc._id) {\n      return doc._id;\n    }\n\n    // XXX what is this for??\n    // It's some iteraction between the callback to _callMutatorMethod and\n    // the return value conversion\n    doc._id = result;\n\n    return result;\n  };\n\n  const wrappedCallback = wrapCallback(\n    callback, chooseReturnValueFromCollectionResult);\n\n  if (this._isRemoteCollection()) {\n    const result = this._callMutatorMethod(\"insert\", [doc], wrappedCallback);\n    return chooseReturnValueFromCollectionResult(result);\n  }\n\n  // it's my collection.  descend into the collection object\n  // and propagate any exception.\n  try {\n    // If the user provided a callback and the collection implements this\n    // operation asynchronously, then queryRet will be undefined, and the\n    // result will be returned through the callback instead.\n    const result = this._collection.insert(doc, wrappedCallback);\n    return chooseReturnValueFromCollectionResult(result);\n  } catch (e) {\n    if (callback) {\n      callback(e);\n      return null;\n    }\n    throw e;\n  }\n}\n\n/**\n * @summary Modify one or more documents in the collection. Returns the number of affected documents.\n * @locus Anywhere\n * @method update\n * @memberOf Mongo.Collection\n * @instance\n * @param {MongoSelector} selector Specifies which documents to modify\n * @param {MongoModifier} modifier Specifies how to modify the documents\n * @param {Object} [options]\n * @param {Boolean} options.multi True to modify all matching documents; false to only modify one of the matching documents (the default).\n * @param {Boolean} options.upsert True to insert a document if no matching documents are found.\n * @param {Function} [callback] Optional.  If present, called with an error object as the first argument and, if no error, the number of affected documents as the second.\n */\nMongo.Collection.prototype.update = function update(selector, modifier, ...optionsAndCallback) {\n  const callback = popCallbackFromArgs(optionsAndCallback);\n\n  selector = Mongo.Collection._rewriteSelector(selector);\n\n  // We've already popped off the callback, so we are left with an array\n  // of one or zero items\n  const options = _.clone(optionsAndCallback[0]) || {};\n  if (options && options.upsert) {\n    // set `insertedId` if absent.  `insertedId` is a Meteor extension.\n    if (options.insertedId) {\n      if (!(typeof options.insertedId === 'string'\n            || options.insertedId instanceof Mongo.ObjectID))\n        throw new Error(\"insertedId must be string or ObjectID\");\n    } else if (! selector._id) {\n      options.insertedId = this._makeNewID();\n    }\n  }\n\n  const wrappedCallback = wrapCallback(callback);\n\n  if (this._isRemoteCollection()) {\n    const args = [\n      selector,\n      modifier,\n      options\n    ];\n\n    return this._callMutatorMethod(\"update\", args, wrappedCallback);\n  }\n\n  // it's my collection.  descend into the collection object\n  // and propagate any exception.\n  try {\n    // If the user provided a callback and the collection implements this\n    // operation asynchronously, then queryRet will be undefined, and the\n    // result will be returned through the callback instead.\n    return this._collection.update(\n      selector, modifier, options, wrappedCallback);\n  } catch (e) {\n    if (callback) {\n      callback(e);\n      return null;\n    }\n    throw e;\n  }\n}\n\n/**\n * @summary Remove documents from the collection\n * @locus Anywhere\n * @method remove\n * @memberOf Mongo.Collection\n * @instance\n * @param {MongoSelector} selector Specifies which documents to remove\n * @param {Function} [callback] Optional.  If present, called with an error object as its argument.\n */\nMongo.Collection.prototype.remove = function remove(selector, callback) {\n  selector = Mongo.Collection._rewriteSelector(selector);\n\n  const wrappedCallback = wrapCallback(callback);\n\n  if (this._isRemoteCollection()) {\n    return this._callMutatorMethod(\"remove\", [selector], wrappedCallback);\n  }\n\n  // it's my collection.  descend into the collection object\n  // and propagate any exception.\n  try {\n    // If the user provided a callback and the collection implements this\n    // operation asynchronously, then queryRet will be undefined, and the\n    // result will be returned through the callback instead.\n    return this._collection.remove(selector, wrappedCallback);\n  } catch (e) {\n    if (callback) {\n      callback(e);\n      return null;\n    }\n    throw e;\n  }\n};\n\n// Determine if this collection is simply a minimongo representation of a real\n// database on another server\nMongo.Collection.prototype._isRemoteCollection = function _isRemoteCollection() {\n  // XXX see #MeteorServerNull\n  return this._connection && this._connection !== Meteor.server;\n}\n\n// Convert the callback to not return a result if there is an error\nfunction wrapCallback(callback, convertResult) {\n  if (!callback) {\n    return;\n  }\n\n  // If no convert function was passed in, just use a \"blank function\"\n  convertResult = convertResult || _.identity;\n\n  return (error, result) => {\n    callback(error, ! error && convertResult(result));\n  };\n}\n\n/**\n * @summary Modify one or more documents in the collection, or insert one if no matching documents were found. Returns an object with keys `numberAffected` (the number of documents modified)  and `insertedId` (the unique _id of the document that was inserted, if any).\n * @locus Anywhere\n * @param {MongoSelector} selector Specifies which documents to modify\n * @param {MongoModifier} modifier Specifies how to modify the documents\n * @param {Object} [options]\n * @param {Boolean} options.multi True to modify all matching documents; false to only modify one of the matching documents (the default).\n * @param {Function} [callback] Optional.  If present, called with an error object as the first argument and, if no error, the number of affected documents as the second.\n */\nMongo.Collection.prototype.upsert = function upsert(\n    selector, modifier, options, callback) {\n  if (! callback && typeof options === \"function\") {\n    callback = options;\n    options = {};\n  }\n\n  const updateOptions = _.extend({}, options, {\n    _returnObject: true,\n    upsert: true\n  });\n\n  return this.update(selector, modifier, updateOptions, callback);\n};\n\n// We'll actually design an index API later. For now, we just pass through to\n// Mongo's, but make it synchronous.\nMongo.Collection.prototype._ensureIndex = function (index, options) {\n  var self = this;\n  if (!self._collection._ensureIndex)\n    throw new Error(\"Can only call _ensureIndex on server collections\");\n  self._collection._ensureIndex(index, options);\n};\nMongo.Collection.prototype._dropIndex = function (index) {\n  var self = this;\n  if (!self._collection._dropIndex)\n    throw new Error(\"Can only call _dropIndex on server collections\");\n  self._collection._dropIndex(index);\n};\nMongo.Collection.prototype._dropCollection = function () {\n  var self = this;\n  if (!self._collection.dropCollection)\n    throw new Error(\"Can only call _dropCollection on server collections\");\n  self._collection.dropCollection();\n};\nMongo.Collection.prototype._createCappedCollection = function (byteSize, maxDocuments) {\n  var self = this;\n  if (!self._collection._createCappedCollection)\n    throw new Error(\"Can only call _createCappedCollection on server collections\");\n  self._collection._createCappedCollection(byteSize, maxDocuments);\n};\n\n/**\n * @summary Returns the [`Collection`](http://mongodb.github.io/node-mongodb-native/1.4/api-generated/collection.html) object corresponding to this collection from the [npm `mongodb` driver module](https://www.npmjs.com/package/mongodb) which is wrapped by `Mongo.Collection`.\n * @locus Server\n */\nMongo.Collection.prototype.rawCollection = function () {\n  var self = this;\n  if (! self._collection.rawCollection) {\n    throw new Error(\"Can only call rawCollection on server collections\");\n  }\n  return self._collection.rawCollection();\n};\n\n/**\n * @summary Returns the [`Db`](http://mongodb.github.io/node-mongodb-native/1.4/api-generated/db.html) object corresponding to this collection's database connection from the [npm `mongodb` driver module](https://www.npmjs.com/package/mongodb) which is wrapped by `Mongo.Collection`.\n * @locus Server\n */\nMongo.Collection.prototype.rawDatabase = function () {\n  var self = this;\n  if (! (self._driver.mongo && self._driver.mongo.db)) {\n    throw new Error(\"Can only call rawDatabase on server collections\");\n  }\n  return self._driver.mongo.db;\n};\n\n\n/**\n * @summary Create a Mongo-style `ObjectID`.  If you don't specify a `hexString`, the `ObjectID` will generated randomly (not using MongoDB's ID construction rules).\n * @locus Anywhere\n * @class\n * @param {String} [hexString] Optional.  The 24-character hexadecimal contents of the ObjectID to create\n */\nMongo.ObjectID = MongoID.ObjectID;\n\n/**\n * @summary To create a cursor, use find. To access the documents in a cursor, use forEach, map, or fetch.\n * @class\n * @instanceName cursor\n */\nMongo.Cursor = LocalCollection.Cursor;\n\n/**\n * @deprecated in 0.9.1\n */\nMongo.Collection.Cursor = Mongo.Cursor;\n\n/**\n * @deprecated in 0.9.1\n */\nMongo.Collection.ObjectID = Mongo.ObjectID;\n\n/**\n * @deprecated in 0.9.1\n */\nMeteor.Collection = Mongo.Collection;\n\n// Allow deny stuff is now in the allow-deny package\n_.extend(Meteor.Collection.prototype, AllowDeny.CollectionPrototype);\n\nfunction popCallbackFromArgs(args) {\n  // Pull off any callback (or perhaps a 'callback' variable that was passed\n  // in undefined, like how 'upsert' does it).\n  if (args.length &&\n      (args[args.length - 1] === undefined ||\n       args[args.length - 1] instanceof Function)) {\n    return args.pop();\n  }\n}\n"
  },
  {
    "path": "packages/mongo/collection_tests.js",
    "content": "Tinytest.add(\n  'collection - call Mongo.Collection without new',\n  function (test) {\n    test.throws(\n      function () {\n        Mongo.Collection(null);\n      },\n      /use \"new\" to construct a Mongo\\.Collection/\n    );\n  }\n);\n\nTinytest.add('collection - call new Mongo.Collection multiple times',\n  function (test) {\n    var collectionName = 'multiple_times_1_' + test.id;\n    new Mongo.Collection(collectionName);\n\n    test.throws(\n      function () {\n        new Mongo.Collection(collectionName);\n      },\n      /There is already a collection named/\n    );\n  }\n);\n\nTinytest.add('collection - call new Mongo.Collection multiple times with _suppressSameNameError=true',\n  function (test) {\n    var collectionName = 'multiple_times_2_' + test.id;\n    new Mongo.Collection(collectionName);\n\n    try {\n      new Mongo.Collection(collectionName, {_suppressSameNameError: true});\n      test.ok();\n    } catch (error) {\n      console.log(error);\n      test.fail('Expected new Mongo.Collection not to throw an error when called twice with the same name');\n    }\n  }\n);\n\nTinytest.add('collection - call new Mongo.Collection with defineMutationMethods=false',\n  function (test) {\n    var handlerPropName = Meteor.isClient ? '_methodHandlers' : 'method_handlers';\n\n    var methodCollectionName = 'hasmethods' + test.id;\n    var hasmethods = new Mongo.Collection(methodCollectionName);\n    test.equal(typeof hasmethods._connection[handlerPropName]['/' + methodCollectionName + '/insert'], 'function');\n\n    var noMethodCollectionName = 'nomethods' + test.id;\n    var nomethods = new Mongo.Collection(noMethodCollectionName, {defineMutationMethods: false});\n    test.equal(nomethods._connection[handlerPropName]['/' + noMethodCollectionName + '/insert'], undefined);\n  }\n);\n\nTinytest.add('collection - call find with sort function',\n  function (test) {\n    var initialize = function (collection) {\n      collection.insert({a: 2});\n      collection.insert({a: 3});\n      collection.insert({a: 1});\n    };\n\n    var sorter = function (a, b) {\n      return a.a - b.a;\n    }\n\n    var getSorted = function (collection) {\n      return collection.find({}, {sort: sorter}).map(function (doc) { return doc.a; });\n    };\n\n    var collectionName = 'sort' + test.id;\n    var localCollection = new Mongo.Collection(null);\n    var namedCollection = new Mongo.Collection(collectionName, {connection: null});\n\n    initialize(localCollection);\n    test.equal(getSorted(localCollection), [1, 2, 3]);\n\n    initialize(namedCollection);\n    test.equal(getSorted(namedCollection), [1, 2, 3]);\n  }\n);\n\nTinytest.add('collection - call native find with sort function',\n  function (test) {\n    var collectionName = 'sortNative' + test.id;\n    var nativeCollection = new Mongo.Collection(collectionName);\n\n    if (Meteor.isServer) {\n      test.throws(\n        function () {\n          nativeCollection.find({}, {sort: function(){}}).map(function (doc) { return doc.a; })\n        },\n        /Illegal sort clause/\n      );\n    }\n  }\n);\n"
  },
  {
    "path": "packages/mongo/doc_fetcher.js",
    "content": "var Fiber = Npm.require('fibers');\nvar Future = Npm.require('fibers/future');\n\nDocFetcher = function (mongoConnection) {\n  var self = this;\n  self._mongoConnection = mongoConnection;\n  // Map from cache key -> [callback]\n  self._callbacksForCacheKey = {};\n};\n\n_.extend(DocFetcher.prototype, {\n  // Fetches document \"id\" from collectionName, returning it or null if not\n  // found.\n  //\n  // If you make multiple calls to fetch() with the same cacheKey (a string),\n  // DocFetcher may assume that they all return the same document. (It does\n  // not check to see if collectionName/id match.)\n  //\n  // You may assume that callback is never called synchronously (and in fact\n  // OplogObserveDriver does so).\n  fetch: function (collectionName, id, cacheKey, callback) {\n    var self = this;\n\n    check(collectionName, String);\n    // id is some sort of scalar\n    check(cacheKey, String);\n\n    // If there's already an in-progress fetch for this cache key, yield until\n    // it's done and return whatever it returns.\n    if (_.has(self._callbacksForCacheKey, cacheKey)) {\n      self._callbacksForCacheKey[cacheKey].push(callback);\n      return;\n    }\n\n    var callbacks = self._callbacksForCacheKey[cacheKey] = [callback];\n\n    Fiber(function () {\n      try {\n        var doc = self._mongoConnection.findOne(\n          collectionName, {_id: id}) || null;\n        // Return doc to all relevant callbacks. Note that this array can\n        // continue to grow during callback excecution.\n        while (!_.isEmpty(callbacks)) {\n          // Clone the document so that the various calls to fetch don't return\n          // objects that are intertwingled with each other. Clone before\n          // popping the future, so that if clone throws, the error gets passed\n          // to the next callback.\n          var clonedDoc = EJSON.clone(doc);\n          callbacks.pop()(null, clonedDoc);\n        }\n      } catch (e) {\n        while (!_.isEmpty(callbacks)) {\n          callbacks.pop()(e);\n        }\n      } finally {\n        // XXX consider keeping the doc around for a period of time before\n        // removing from the cache\n        delete self._callbacksForCacheKey[cacheKey];\n      }\n    }).run();\n  }\n});\n\nMongoTest.DocFetcher = DocFetcher;\n"
  },
  {
    "path": "packages/mongo/doc_fetcher_tests.js",
    "content": "var Fiber = Npm.require('fibers');\nvar Future = Npm.require('fibers/future');\n\ntestAsyncMulti(\"mongo-livedata - doc fetcher\", [\n  function (test, expect) {\n    var self = this;\n    var collName = \"docfetcher-\" + Random.id();\n    var collection = new Mongo.Collection(collName);\n    var id1 = collection.insert({x: 1});\n    var id2 = collection.insert({y: 2});\n\n    var fetcher = new MongoTest.DocFetcher(\n      MongoInternals.defaultRemoteCollectionDriver().mongo);\n\n    // Test basic operation.\n    fetcher.fetch(collName, id1, Random.id(), expect(null, {_id: id1, x: 1}));\n    fetcher.fetch(collName, \"nonexistent!\", Random.id(), expect(null, null));\n\n    var fetched = false;\n    var cacheKey = Random.id();\n    var expected = {_id: id2, y: 2};\n    fetcher.fetch(collName, id2, cacheKey, expect(function (e, d) {\n      fetched = true;\n      test.isFalse(e);\n      test.equal(d, expected);\n    }));\n    // The fetcher yields.\n    test.isFalse(fetched);\n\n    // Now ask for another document with the same cache key. Because a fetch for\n    // that cache key is in flight, we will get the other fetch's document, not\n    // this random document.\n    fetcher.fetch(collName, Random.id(), cacheKey, expect(function (e, d) {\n      test.isFalse(e);\n      test.equal(d, expected);\n    }));\n  }\n]);\n"
  },
  {
    "path": "packages/mongo/local_collection_driver.js",
    "content": "LocalCollectionDriver = function () {\n  var self = this;\n  self.noConnCollections = {};\n};\n\nvar ensureCollection = function (name, collections) {\n  if (!(name in collections))\n    collections[name] = new LocalCollection(name);\n  return collections[name];\n};\n\n_.extend(LocalCollectionDriver.prototype, {\n  open: function (name, conn) {\n    var self = this;\n    if (!name)\n      return new LocalCollection;\n    if (! conn) {\n      return ensureCollection(name, self.noConnCollections);\n    }\n    if (! conn._mongo_livedata_collections)\n      conn._mongo_livedata_collections = {};\n    // XXX is there a way to keep track of a connection's collections without\n    // dangling it off the connection object?\n    return ensureCollection(name, conn._mongo_livedata_collections);\n  }\n});\n\n// singleton\nLocalCollectionDriver = new LocalCollectionDriver;\n"
  },
  {
    "path": "packages/mongo/mongo_driver.js",
    "content": "/**\n * Provide a synchronous Collection API using fibers, backed by\n * MongoDB.  This is only for use on the server, and mostly identical\n * to the client API.\n *\n * NOTE: the public API methods must be run within a fiber. If you call\n * these outside of a fiber they will explode!\n */\n\nvar path = Npm.require('path');\nvar MongoDB = NpmModuleMongodb;\nvar Fiber = Npm.require('fibers');\nvar Future = Npm.require(path.join('fibers', 'future'));\n\nMongoInternals = {};\nMongoTest = {};\n\nMongoInternals.NpmModules = {\n  mongodb: {\n    version: NpmModuleMongodbVersion,\n    module: MongoDB\n  }\n};\n\n// Older version of what is now available via\n// MongoInternals.NpmModules.mongodb.module.  It was never documented, but\n// people do use it.\n// XXX COMPAT WITH 1.0.3.2\nMongoInternals.NpmModule = MongoDB;\n\n// This is used to add or remove EJSON from the beginning of everything nested\n// inside an EJSON custom type. It should only be called on pure JSON!\nvar replaceNames = function (filter, thing) {\n  if (typeof thing === \"object\") {\n    if (_.isArray(thing)) {\n      return _.map(thing, _.bind(replaceNames, null, filter));\n    }\n    var ret = {};\n    _.each(thing, function (value, key) {\n      ret[filter(key)] = replaceNames(filter, value);\n    });\n    return ret;\n  }\n  return thing;\n};\n\n// Ensure that EJSON.clone keeps a Timestamp as a Timestamp (instead of just\n// doing a structural clone).\n// XXX how ok is this? what if there are multiple copies of MongoDB loaded?\nMongoDB.Timestamp.prototype.clone = function () {\n  // Timestamps should be immutable.\n  return this;\n};\n\nvar makeMongoLegal = function (name) { return \"EJSON\" + name; };\nvar unmakeMongoLegal = function (name) { return name.substr(5); };\n\nvar replaceMongoAtomWithMeteor = function (document) {\n  if (document instanceof MongoDB.Binary) {\n    var buffer = document.value(true);\n    return new Uint8Array(buffer);\n  }\n  if (document instanceof MongoDB.ObjectID) {\n    return new Mongo.ObjectID(document.toHexString());\n  }\n  if (document[\"EJSON$type\"] && document[\"EJSON$value\"]\n      && _.size(document) === 2) {\n    return EJSON.fromJSONValue(replaceNames(unmakeMongoLegal, document));\n  }\n  if (document instanceof MongoDB.Timestamp) {\n    // For now, the Meteor representation of a Mongo timestamp type (not a date!\n    // this is a weird internal thing used in the oplog!) is the same as the\n    // Mongo representation. We need to do this explicitly or else we would do a\n    // structural clone and lose the prototype.\n    return document;\n  }\n  return undefined;\n};\n\nvar replaceMeteorAtomWithMongo = function (document) {\n  if (EJSON.isBinary(document)) {\n    // This does more copies than we'd like, but is necessary because\n    // MongoDB.BSON only looks like it takes a Uint8Array (and doesn't actually\n    // serialize it correctly).\n    return new MongoDB.Binary(new Buffer(document));\n  }\n  if (document instanceof Mongo.ObjectID) {\n    return new MongoDB.ObjectID(document.toHexString());\n  }\n  if (document instanceof MongoDB.Timestamp) {\n    // For now, the Meteor representation of a Mongo timestamp type (not a date!\n    // this is a weird internal thing used in the oplog!) is the same as the\n    // Mongo representation. We need to do this explicitly or else we would do a\n    // structural clone and lose the prototype.\n    return document;\n  }\n  if (EJSON._isCustomType(document)) {\n    return replaceNames(makeMongoLegal, EJSON.toJSONValue(document));\n  }\n  // It is not ordinarily possible to stick dollar-sign keys into mongo\n  // so we don't bother checking for things that need escaping at this time.\n  return undefined;\n};\n\nvar replaceTypes = function (document, atomTransformer) {\n  if (typeof document !== 'object' || document === null)\n    return document;\n\n  var replacedTopLevelAtom = atomTransformer(document);\n  if (replacedTopLevelAtom !== undefined)\n    return replacedTopLevelAtom;\n\n  var ret = document;\n  _.each(document, function (val, key) {\n    var valReplaced = replaceTypes(val, atomTransformer);\n    if (val !== valReplaced) {\n      // Lazy clone. Shallow copy.\n      if (ret === document)\n        ret = _.clone(document);\n      ret[key] = valReplaced;\n    }\n  });\n  return ret;\n};\n\n\nMongoConnection = function (url, options) {\n  var self = this;\n  options = options || {};\n  self._observeMultiplexers = {};\n  self._onFailoverHook = new Hook;\n\n  var mongoOptions = {db: {safe: true}, server: {}, replSet: {}};\n\n  // Set autoReconnect to true, unless passed on the URL. Why someone\n  // would want to set autoReconnect to false, I'm not really sure, but\n  // keeping this for backwards compatibility for now.\n  if (!(/[\\?&]auto_?[rR]econnect=/.test(url))) {\n    mongoOptions.server.auto_reconnect = true;\n  }\n\n  // Disable the native parser by default, unless specifically enabled\n  // in the mongo URL.\n  // - The native driver can cause errors which normally would be\n  //   thrown, caught, and handled into segfaults that take down the\n  //   whole app.\n  // - Binary modules don't yet work when you bundle and move the bundle\n  //   to a different platform (aka deploy)\n  // We should revisit this after binary npm module support lands.\n  if (!(/[\\?&]native_?[pP]arser=/.test(url))) {\n    mongoOptions.db.native_parser = false;\n  }\n\n  // XXX maybe we should have a better way of allowing users to configure the\n  // underlying Mongo driver\n  if (_.has(options, 'poolSize')) {\n    // If we just set this for \"server\", replSet will override it. If we just\n    // set it for replSet, it will be ignored if we're not using a replSet.\n    mongoOptions.server.poolSize = options.poolSize;\n    mongoOptions.replSet.poolSize = options.poolSize;\n  }\n\n  self.db = null;\n  // We keep track of the ReplSet's primary, so that we can trigger hooks when\n  // it changes.  The Node driver's joined callback seems to fire way too\n  // often, which is why we need to track it ourselves.\n  self._primary = null;\n  self._oplogHandle = null;\n  self._docFetcher = null;\n\n\n  var connectFuture = new Future;\n  MongoDB.connect(\n    url,\n    mongoOptions,\n    Meteor.bindEnvironment(\n      function (err, db) {\n        if (err) {\n          throw err;\n        }\n\n        // First, figure out what the current primary is, if any.\n        if (db.serverConfig._state.master)\n          self._primary = db.serverConfig._state.master.name;\n        db.serverConfig.on(\n          'joined', Meteor.bindEnvironment(function (kind, doc) {\n            if (kind === 'primary') {\n              if (doc.primary !== self._primary) {\n                self._primary = doc.primary;\n                self._onFailoverHook.each(function (callback) {\n                  callback();\n                  return true;\n                });\n              }\n            } else if (doc.me === self._primary) {\n              // The thing we thought was primary is now something other than\n              // primary.  Forget that we thought it was primary.  (This means\n              // that if a server stops being primary and then starts being\n              // primary again without another server becoming primary in the\n              // middle, we'll correctly count it as a failover.)\n              self._primary = null;\n            }\n          }));\n\n        // Allow the constructor to return.\n        connectFuture['return'](db);\n      },\n      connectFuture.resolver()  // onException\n    )\n  );\n\n  // Wait for the connection to be successful; throws on failure.\n  self.db = connectFuture.wait();\n\n  if (options.oplogUrl && ! Package['disable-oplog']) {\n    self._oplogHandle = new OplogHandle(options.oplogUrl, self.db.databaseName);\n    self._docFetcher = new DocFetcher(self);\n  }\n};\n\nMongoConnection.prototype.close = function() {\n  var self = this;\n\n  if (! self.db)\n    throw Error(\"close called before Connection created?\");\n\n  // XXX probably untested\n  var oplogHandle = self._oplogHandle;\n  self._oplogHandle = null;\n  if (oplogHandle)\n    oplogHandle.stop();\n\n  // Use Future.wrap so that errors get thrown. This happens to\n  // work even outside a fiber since the 'close' method is not\n  // actually asynchronous.\n  Future.wrap(_.bind(self.db.close, self.db))(true).wait();\n};\n\n// Returns the Mongo Collection object; may yield.\nMongoConnection.prototype.rawCollection = function (collectionName) {\n  var self = this;\n\n  if (! self.db)\n    throw Error(\"rawCollection called before Connection created?\");\n\n  var future = new Future;\n  self.db.collection(collectionName, future.resolver());\n  return future.wait();\n};\n\nMongoConnection.prototype._createCappedCollection = function (\n    collectionName, byteSize, maxDocuments) {\n  var self = this;\n\n  if (! self.db)\n    throw Error(\"_createCappedCollection called before Connection created?\");\n\n  var future = new Future();\n  self.db.createCollection(\n    collectionName,\n    { capped: true, size: byteSize, max: maxDocuments },\n    future.resolver());\n  future.wait();\n};\n\n// This should be called synchronously with a write, to create a\n// transaction on the current write fence, if any. After we can read\n// the write, and after observers have been notified (or at least,\n// after the observer notifiers have added themselves to the write\n// fence), you should call 'committed()' on the object returned.\nMongoConnection.prototype._maybeBeginWrite = function () {\n  var self = this;\n  var fence = DDPServer._CurrentWriteFence.get();\n  if (fence)\n    return fence.beginWrite();\n  else\n    return {committed: function () {}};\n};\n\n// Internal interface: adds a callback which is called when the Mongo primary\n// changes. Returns a stop handle.\nMongoConnection.prototype._onFailover = function (callback) {\n  return this._onFailoverHook.register(callback);\n};\n\n\n//////////// Public API //////////\n\n// The write methods block until the database has confirmed the write (it may\n// not be replicated or stable on disk, but one server has confirmed it) if no\n// callback is provided. If a callback is provided, then they call the callback\n// when the write is confirmed. They return nothing on success, and raise an\n// exception on failure.\n//\n// After making a write (with insert, update, remove), observers are\n// notified asynchronously. If you want to receive a callback once all\n// of the observer notifications have landed for your write, do the\n// writes inside a write fence (set DDPServer._CurrentWriteFence to a new\n// _WriteFence, and then set a callback on the write fence.)\n//\n// Since our execution environment is single-threaded, this is\n// well-defined -- a write \"has been made\" if it's returned, and an\n// observer \"has been notified\" if its callback has returned.\n\nvar writeCallback = function (write, refresh, callback) {\n  return function (err, result) {\n    if (! err) {\n      // XXX We don't have to run this on error, right?\n      try {\n        refresh();\n      } catch (refreshErr) {\n        if (callback) {\n          callback(refreshErr);\n          return;\n        } else {\n          throw refreshErr;\n        }\n      }\n    }\n    write.committed();\n    if (callback)\n      callback(err, result);\n    else if (err)\n      throw err;\n  };\n};\n\nvar bindEnvironmentForWrite = function (callback) {\n  return Meteor.bindEnvironment(callback, \"Mongo write\");\n};\n\nMongoConnection.prototype._insert = function (collection_name, document,\n                                              callback) {\n  var self = this;\n\n  var sendError = function (e) {\n    if (callback)\n      return callback(e);\n    throw e;\n  };\n\n  if (collection_name === \"___meteor_failure_test_collection\") {\n    var e = new Error(\"Failure test\");\n    e.expected = true;\n    sendError(e);\n    return;\n  }\n\n  if (!(LocalCollection._isPlainObject(document) &&\n        !EJSON._isCustomType(document))) {\n    sendError(new Error(\n      \"Only plain objects may be inserted into MongoDB\"));\n    return;\n  }\n\n  var write = self._maybeBeginWrite();\n  var refresh = function () {\n    Meteor.refresh({collection: collection_name, id: document._id });\n  };\n  callback = bindEnvironmentForWrite(writeCallback(write, refresh, callback));\n  try {\n    var collection = self.rawCollection(collection_name);\n    collection.insert(replaceTypes(document, replaceMeteorAtomWithMongo),\n                      {safe: true}, callback);\n  } catch (e) {\n    write.committed();\n    throw e;\n  }\n};\n\n// Cause queries that may be affected by the selector to poll in this write\n// fence.\nMongoConnection.prototype._refresh = function (collectionName, selector) {\n  var self = this;\n  var refreshKey = {collection: collectionName};\n  // If we know which documents we're removing, don't poll queries that are\n  // specific to other documents. (Note that multiple notifications here should\n  // not cause multiple polls, since all our listener is doing is enqueueing a\n  // poll.)\n  var specificIds = LocalCollection._idsMatchedBySelector(selector);\n  if (specificIds) {\n    _.each(specificIds, function (id) {\n      Meteor.refresh(_.extend({id: id}, refreshKey));\n    });\n  } else {\n    Meteor.refresh(refreshKey);\n  }\n};\n\nMongoConnection.prototype._remove = function (collection_name, selector,\n                                              callback) {\n  var self = this;\n\n  if (collection_name === \"___meteor_failure_test_collection\") {\n    var e = new Error(\"Failure test\");\n    e.expected = true;\n    if (callback)\n      return callback(e);\n    else\n      throw e;\n  }\n\n  var write = self._maybeBeginWrite();\n  var refresh = function () {\n    self._refresh(collection_name, selector);\n  };\n  callback = bindEnvironmentForWrite(writeCallback(write, refresh, callback));\n\n  try {\n    var collection = self.rawCollection(collection_name);\n    collection.remove(replaceTypes(selector, replaceMeteorAtomWithMongo),\n                      {safe: true}, callback);\n  } catch (e) {\n    write.committed();\n    throw e;\n  }\n};\n\nMongoConnection.prototype._dropCollection = function (collectionName, cb) {\n  var self = this;\n\n  var write = self._maybeBeginWrite();\n  var refresh = function () {\n    Meteor.refresh({collection: collectionName, id: null,\n                    dropCollection: true});\n  };\n  cb = bindEnvironmentForWrite(writeCallback(write, refresh, cb));\n\n  try {\n    var collection = self.rawCollection(collectionName);\n    collection.drop(cb);\n  } catch (e) {\n    write.committed();\n    throw e;\n  }\n};\n\n// For testing only.  Slightly better than `c.rawDatabase().dropDatabase()`\n// because it lets the test's fence wait for it to be complete.\nMongoConnection.prototype._dropDatabase = function (cb) {\n  var self = this;\n\n  var write = self._maybeBeginWrite();\n  var refresh = function () {\n    Meteor.refresh({ dropDatabase: true });\n  };\n  cb = bindEnvironmentForWrite(writeCallback(write, refresh, cb));\n\n  try {\n    self.db.dropDatabase(cb);\n  } catch (e) {\n    write.committed();\n    throw e;\n  }\n};\n\nMongoConnection.prototype._update = function (collection_name, selector, mod,\n                                              options, callback) {\n  var self = this;\n\n  if (! callback && options instanceof Function) {\n    callback = options;\n    options = null;\n  }\n\n  if (collection_name === \"___meteor_failure_test_collection\") {\n    var e = new Error(\"Failure test\");\n    e.expected = true;\n    if (callback)\n      return callback(e);\n    else\n      throw e;\n  }\n\n  // explicit safety check. null and undefined can crash the mongo\n  // driver. Although the node driver and minimongo do 'support'\n  // non-object modifier in that they don't crash, they are not\n  // meaningful operations and do not do anything. Defensively throw an\n  // error here.\n  if (!mod || typeof mod !== 'object')\n    throw new Error(\"Invalid modifier. Modifier must be an object.\");\n\n  if (!(LocalCollection._isPlainObject(mod) &&\n        !EJSON._isCustomType(mod))) {\n    throw new Error(\n      \"Only plain objects may be used as replacement\" +\n        \" documents in MongoDB\");\n    return;\n  }\n\n  if (!options) options = {};\n\n  var write = self._maybeBeginWrite();\n  var refresh = function () {\n    self._refresh(collection_name, selector);\n  };\n  callback = writeCallback(write, refresh, callback);\n  try {\n    var collection = self.rawCollection(collection_name);\n    var mongoOpts = {safe: true};\n    // explictly enumerate options that minimongo supports\n    if (options.upsert) mongoOpts.upsert = true;\n    if (options.multi) mongoOpts.multi = true;\n    // Lets you get a more more full result from MongoDB. Use with caution:\n    // might not work with C.upsert (as opposed to C.update({upsert:true}) or\n    // with simulated upsert.\n    if (options.fullResult) mongoOpts.fullResult = true;\n\n    var mongoSelector = replaceTypes(selector, replaceMeteorAtomWithMongo);\n    var mongoMod = replaceTypes(mod, replaceMeteorAtomWithMongo);\n\n    var isModify = isModificationMod(mongoMod);\n    var knownId = selector._id || mod._id;\n\n    if (options._forbidReplace && ! isModify) {\n      var e = new Error(\"Invalid modifier. Replacements are forbidden.\");\n      if (callback) {\n        return callback(e);\n      } else {\n        throw e;\n      }\n    }\n\n    if (options.upsert && (! knownId) && options.insertedId) {\n      // XXX If we know we're using Mongo 2.6 (and this isn't a replacement)\n      //     we should be able to just use $setOnInsert instead of this\n      //     simulated upsert thing. (We can't use $setOnInsert with\n      //     replacements because there's nowhere to write it, and $setOnInsert\n      //     can't set _id on Mongo 2.4.)\n      //\n      //     Also, in the future we could do a real upsert for the mongo id\n      //     generation case, if the the node mongo driver gives us back the id\n      //     of the upserted doc (which our current version does not).\n      //\n      //     For more context, see\n      //     https://github.com/meteor/meteor/issues/2278#issuecomment-64252706\n      simulateUpsertWithInsertedId(\n        collection, mongoSelector, mongoMod,\n        isModify, options,\n        // This callback does not need to be bindEnvironment'ed because\n        // simulateUpsertWithInsertedId() wraps it and then passes it through\n        // bindEnvironmentForWrite.\n        function (err, result) {\n          // If we got here via a upsert() call, then options._returnObject will\n          // be set and we should return the whole object. Otherwise, we should\n          // just return the number of affected docs to match the mongo API.\n          if (result && ! options._returnObject)\n            callback(err, result.numberAffected);\n          else\n            callback(err, result);\n        }\n      );\n    } else {\n      collection.update(\n        mongoSelector, mongoMod, mongoOpts,\n        bindEnvironmentForWrite(function (err, result, extra) {\n          if (! err) {\n            if (result && options._returnObject) {\n              result = { numberAffected: result };\n              // If this was an upsert() call, and we ended up\n              // inserting a new doc and we know its id, then\n              // return that id as well.\n              if (options.upsert && knownId &&\n                  ! extra.updatedExisting)\n                result.insertedId = knownId;\n            }\n          }\n          callback(err, result);\n        }));\n    }\n  } catch (e) {\n    write.committed();\n    throw e;\n  }\n};\n\nvar isModificationMod = function (mod) {\n  var isReplace = false;\n  var isModify = false;\n  for (var k in mod) {\n    if (k.substr(0, 1) === '$') {\n      isModify = true;\n    } else {\n      isReplace = true;\n    }\n  }\n  if (isModify && isReplace) {\n    throw new Error(\n      \"Update parameter cannot have both modifier and non-modifier fields.\");\n  }\n  return isModify;\n};\n\nvar NUM_OPTIMISTIC_TRIES = 3;\n\n// exposed for testing\nMongoConnection._isCannotChangeIdError = function (err) {\n  // First check for what this error looked like in Mongo 2.4.  Either of these\n  // checks should work, but just to be safe...\n  if (err.code === 13596)\n    return true;\n  if (err.err.indexOf(\"cannot change _id of a document\") === 0)\n    return true;\n\n  // Now look for what it looks like in Mongo 2.6.  We don't use the error code\n  // here, because the error code we observed it producing (16837) appears to be\n  // a far more generic error code based on examining the source.\n  if (err.err.indexOf(\"The _id field cannot be changed\") === 0)\n    return true;\n\n  return false;\n};\n\nvar simulateUpsertWithInsertedId = function (collection, selector, mod,\n                                             isModify, options, callback) {\n  // STRATEGY:  First try doing a plain update.  If it affected 0 documents,\n  // then without affecting the database, we know we should probably do an\n  // insert.  We then do a *conditional* insert that will fail in the case\n  // of a race condition.  This conditional insert is actually an\n  // upsert-replace with an _id, which will never successfully update an\n  // existing document.  If this upsert fails with an error saying it\n  // couldn't change an existing _id, then we know an intervening write has\n  // caused the query to match something.  We go back to step one and repeat.\n  // Like all \"optimistic write\" schemes, we rely on the fact that it's\n  // unlikely our writes will continue to be interfered with under normal\n  // circumstances (though sufficiently heavy contention with writers\n  // disagreeing on the existence of an object will cause writes to fail\n  // in theory).\n\n  var newDoc;\n  // Run this code up front so that it fails fast if someone uses\n  // a Mongo update operator we don't support.\n  if (isModify) {\n    // We've already run replaceTypes/replaceMeteorAtomWithMongo on\n    // selector and mod.  We assume it doesn't matter, as far as\n    // the behavior of modifiers is concerned, whether `_modify`\n    // is run on EJSON or on mongo-converted EJSON.\n    var selectorDoc = LocalCollection._removeDollarOperators(selector);\n\n    newDoc = selectorDoc;\n\n    // Convert dotted keys into objects. (Resolves issue #4522).\n    _.each(newDoc, function (value, key) {\n      var trail = key.split(\".\");\n\n      if (trail.length > 1) {\n        //Key is dotted. Convert it into an object.\n        delete newDoc[key];\n\n        var obj = newDoc,\n            leaf = trail.pop();\n\n        // XXX It is not quite certain what should be done if there are clashing\n        // keys on the trail of the dotted key. For now we will just override it\n        // It wouldn't be a very sane query in the first place, but should look\n        // up what mongo does in this case.\n\n        while ((key = trail.shift())) {\n          if (typeof obj[key] !== \"object\") {\n            obj[key] = {};\n          }\n\n          obj = obj[key];\n        }\n\n        obj[leaf] = value;\n      }\n    });\n\n    LocalCollection._modify(newDoc, mod, {isInsert: true});\n  } else {\n    newDoc = mod;\n  }\n\n  var insertedId = options.insertedId; // must exist\n  var mongoOptsForUpdate = {\n    safe: true,\n    multi: options.multi\n  };\n  var mongoOptsForInsert = {\n    safe: true,\n    upsert: true\n  };\n\n  var tries = NUM_OPTIMISTIC_TRIES;\n\n  var doUpdate = function () {\n    tries--;\n    if (! tries) {\n      callback(new Error(\"Upsert failed after \" + NUM_OPTIMISTIC_TRIES + \" tries.\"));\n    } else {\n      collection.update(selector, mod, mongoOptsForUpdate,\n                        bindEnvironmentForWrite(function (err, result) {\n                          if (err)\n                            callback(err);\n                          else if (result)\n                            callback(null, {\n                              numberAffected: result\n                            });\n                          else\n                            doConditionalInsert();\n                        }));\n    }\n  };\n\n  var doConditionalInsert = function () {\n    var replacementWithId = _.extend(\n      replaceTypes({_id: insertedId}, replaceMeteorAtomWithMongo),\n      newDoc);\n    collection.update(selector, replacementWithId, mongoOptsForInsert,\n                      bindEnvironmentForWrite(function (err, result) {\n                        if (err) {\n                          // figure out if this is a\n                          // \"cannot change _id of document\" error, and\n                          // if so, try doUpdate() again, up to 3 times.\n                          if (MongoConnection._isCannotChangeIdError(err)) {\n                            doUpdate();\n                          } else {\n                            callback(err);\n                          }\n                        } else {\n                          callback(null, {\n                            numberAffected: result,\n                            insertedId: insertedId\n                          });\n                        }\n                      }));\n  };\n\n  doUpdate();\n};\n\n_.each([\"insert\", \"update\", \"remove\", \"dropCollection\", \"dropDatabase\"], function (method) {\n  MongoConnection.prototype[method] = function (/* arguments */) {\n    var self = this;\n    return Meteor.wrapAsync(self[\"_\" + method]).apply(self, arguments);\n  };\n});\n\n// XXX MongoConnection.upsert() does not return the id of the inserted document\n// unless you set it explicitly in the selector or modifier (as a replacement\n// doc).\nMongoConnection.prototype.upsert = function (collectionName, selector, mod,\n                                             options, callback) {\n  var self = this;\n  if (typeof options === \"function\" && ! callback) {\n    callback = options;\n    options = {};\n  }\n\n  return self.update(collectionName, selector, mod,\n                     _.extend({}, options, {\n                       upsert: true,\n                       _returnObject: true\n                     }), callback);\n};\n\nMongoConnection.prototype.find = function (collectionName, selector, options) {\n  var self = this;\n\n  if (arguments.length === 1)\n    selector = {};\n\n  return new Cursor(\n    self, new CursorDescription(collectionName, selector, options));\n};\n\nMongoConnection.prototype.findOne = function (collection_name, selector,\n                                              options) {\n  var self = this;\n  if (arguments.length === 1)\n    selector = {};\n\n  options = options || {};\n  options.limit = 1;\n  return self.find(collection_name, selector, options).fetch()[0];\n};\n\n// We'll actually design an index API later. For now, we just pass through to\n// Mongo's, but make it synchronous.\nMongoConnection.prototype._ensureIndex = function (collectionName, index,\n                                                   options) {\n  var self = this;\n\n  // We expect this function to be called at startup, not from within a method,\n  // so we don't interact with the write fence.\n  var collection = self.rawCollection(collectionName);\n  var future = new Future;\n  var indexName = collection.ensureIndex(index, options, future.resolver());\n  future.wait();\n};\nMongoConnection.prototype._dropIndex = function (collectionName, index) {\n  var self = this;\n\n  // This function is only used by test code, not within a method, so we don't\n  // interact with the write fence.\n  var collection = self.rawCollection(collectionName);\n  var future = new Future;\n  var indexName = collection.dropIndex(index, future.resolver());\n  future.wait();\n};\n\n// CURSORS\n\n// There are several classes which relate to cursors:\n//\n// CursorDescription represents the arguments used to construct a cursor:\n// collectionName, selector, and (find) options.  Because it is used as a key\n// for cursor de-dup, everything in it should either be JSON-stringifiable or\n// not affect observeChanges output (eg, options.transform functions are not\n// stringifiable but do not affect observeChanges).\n//\n// SynchronousCursor is a wrapper around a MongoDB cursor\n// which includes fully-synchronous versions of forEach, etc.\n//\n// Cursor is the cursor object returned from find(), which implements the\n// documented Mongo.Collection cursor API.  It wraps a CursorDescription and a\n// SynchronousCursor (lazily: it doesn't contact Mongo until you call a method\n// like fetch or forEach on it).\n//\n// ObserveHandle is the \"observe handle\" returned from observeChanges. It has a\n// reference to an ObserveMultiplexer.\n//\n// ObserveMultiplexer allows multiple identical ObserveHandles to be driven by a\n// single observe driver.\n//\n// There are two \"observe drivers\" which drive ObserveMultiplexers:\n//   - PollingObserveDriver caches the results of a query and reruns it when\n//     necessary.\n//   - OplogObserveDriver follows the Mongo operation log to directly observe\n//     database changes.\n// Both implementations follow the same simple interface: when you create them,\n// they start sending observeChanges callbacks (and a ready() invocation) to\n// their ObserveMultiplexer, and you stop them by calling their stop() method.\n\nCursorDescription = function (collectionName, selector, options) {\n  var self = this;\n  self.collectionName = collectionName;\n  self.selector = Mongo.Collection._rewriteSelector(selector);\n  self.options = options || {};\n};\n\nCursor = function (mongo, cursorDescription) {\n  var self = this;\n\n  self._mongo = mongo;\n  self._cursorDescription = cursorDescription;\n  self._synchronousCursor = null;\n};\n\n_.each(['forEach', 'map', 'fetch', 'count'], function (method) {\n  Cursor.prototype[method] = function () {\n    var self = this;\n\n    // You can only observe a tailable cursor.\n    if (self._cursorDescription.options.tailable)\n      throw new Error(\"Cannot call \" + method + \" on a tailable cursor\");\n\n    if (!self._synchronousCursor) {\n      self._synchronousCursor = self._mongo._createSynchronousCursor(\n        self._cursorDescription, {\n          // Make sure that the \"self\" argument to forEach/map callbacks is the\n          // Cursor, not the SynchronousCursor.\n          selfForIteration: self,\n          useTransform: true\n        });\n    }\n\n    return self._synchronousCursor[method].apply(\n      self._synchronousCursor, arguments);\n  };\n});\n\n// Since we don't actually have a \"nextObject\" interface, there's really no\n// reason to have a \"rewind\" interface.  All it did was make multiple calls\n// to fetch/map/forEach return nothing the second time.\n// XXX COMPAT WITH 0.8.1\nCursor.prototype.rewind = function () {\n};\n\nCursor.prototype.getTransform = function () {\n  return this._cursorDescription.options.transform;\n};\n\n// When you call Meteor.publish() with a function that returns a Cursor, we need\n// to transmute it into the equivalent subscription.  This is the function that\n// does that.\n\nCursor.prototype._publishCursor = function (sub) {\n  var self = this;\n  var collection = self._cursorDescription.collectionName;\n  return Mongo.Collection._publishCursor(self, sub, collection);\n};\n\n// Used to guarantee that publish functions return at most one cursor per\n// collection. Private, because we might later have cursors that include\n// documents from multiple collections somehow.\nCursor.prototype._getCollectionName = function () {\n  var self = this;\n  return self._cursorDescription.collectionName;\n}\n\nCursor.prototype.observe = function (callbacks) {\n  var self = this;\n  return LocalCollection._observeFromObserveChanges(self, callbacks);\n};\n\nCursor.prototype.observeChanges = function (callbacks) {\n  var self = this;\n  var ordered = LocalCollection._observeChangesCallbacksAreOrdered(callbacks);\n  return self._mongo._observeChanges(\n    self._cursorDescription, ordered, callbacks);\n};\n\nMongoConnection.prototype._createSynchronousCursor = function(\n    cursorDescription, options) {\n  var self = this;\n  options = _.pick(options || {}, 'selfForIteration', 'useTransform');\n\n  var collection = self.rawCollection(cursorDescription.collectionName);\n  var cursorOptions = cursorDescription.options;\n  var mongoOptions = {\n    sort: cursorOptions.sort,\n    limit: cursorOptions.limit,\n    skip: cursorOptions.skip\n  };\n\n  // Do we want a tailable cursor (which only works on capped collections)?\n  if (cursorOptions.tailable) {\n    // We want a tailable cursor...\n    mongoOptions.tailable = true;\n    // ... and for the server to wait a bit if any getMore has no data (rather\n    // than making us put the relevant sleeps in the client)...\n    mongoOptions.awaitdata = true;\n    // ... and to keep querying the server indefinitely rather than just 5 times\n    // if there's no more data.\n    mongoOptions.numberOfRetries = -1;\n    // And if this is on the oplog collection and the cursor specifies a 'ts',\n    // then set the undocumented oplog replay flag, which does a special scan to\n    // find the first document (instead of creating an index on ts). This is a\n    // very hard-coded Mongo flag which only works on the oplog collection and\n    // only works with the ts field.\n    if (cursorDescription.collectionName === OPLOG_COLLECTION &&\n        cursorDescription.selector.ts) {\n      mongoOptions.oplogReplay = true;\n    }\n  }\n\n  var dbCursor = collection.find(\n    replaceTypes(cursorDescription.selector, replaceMeteorAtomWithMongo),\n    cursorOptions.fields, mongoOptions);\n\n  return new SynchronousCursor(dbCursor, cursorDescription, options);\n};\n\nvar SynchronousCursor = function (dbCursor, cursorDescription, options) {\n  var self = this;\n  options = _.pick(options || {}, 'selfForIteration', 'useTransform');\n\n  self._dbCursor = dbCursor;\n  self._cursorDescription = cursorDescription;\n  // The \"self\" argument passed to forEach/map callbacks. If we're wrapped\n  // inside a user-visible Cursor, we want to provide the outer cursor!\n  self._selfForIteration = options.selfForIteration || self;\n  if (options.useTransform && cursorDescription.options.transform) {\n    self._transform = LocalCollection.wrapTransform(\n      cursorDescription.options.transform);\n  } else {\n    self._transform = null;\n  }\n\n  // Need to specify that the callback is the first argument to nextObject,\n  // since otherwise when we try to call it with no args the driver will\n  // interpret \"undefined\" first arg as an options hash and crash.\n  self._synchronousNextObject = Future.wrap(\n    dbCursor.nextObject.bind(dbCursor), 0);\n  self._synchronousCount = Future.wrap(dbCursor.count.bind(dbCursor));\n  self._visitedIds = new LocalCollection._IdMap;\n};\n\n_.extend(SynchronousCursor.prototype, {\n  _nextObject: function () {\n    var self = this;\n\n    while (true) {\n      var doc = self._synchronousNextObject().wait();\n\n      if (!doc) return null;\n      doc = replaceTypes(doc, replaceMongoAtomWithMeteor);\n\n      if (!self._cursorDescription.options.tailable && _.has(doc, '_id')) {\n        // Did Mongo give us duplicate documents in the same cursor? If so,\n        // ignore this one. (Do this before the transform, since transform might\n        // return some unrelated value.) We don't do this for tailable cursors,\n        // because we want to maintain O(1) memory usage. And if there isn't _id\n        // for some reason (maybe it's the oplog), then we don't do this either.\n        // (Be careful to do this for falsey but existing _id, though.)\n        if (self._visitedIds.has(doc._id)) continue;\n        self._visitedIds.set(doc._id, true);\n      }\n\n      if (self._transform)\n        doc = self._transform(doc);\n\n      return doc;\n    }\n  },\n\n  forEach: function (callback, thisArg) {\n    var self = this;\n\n    // Get back to the beginning.\n    self._rewind();\n\n    // We implement the loop ourself instead of using self._dbCursor.each,\n    // because \"each\" will call its callback outside of a fiber which makes it\n    // much more complex to make this function synchronous.\n    var index = 0;\n    while (true) {\n      var doc = self._nextObject();\n      if (!doc) return;\n      callback.call(thisArg, doc, index++, self._selfForIteration);\n    }\n  },\n\n  // XXX Allow overlapping callback executions if callback yields.\n  map: function (callback, thisArg) {\n    var self = this;\n    var res = [];\n    self.forEach(function (doc, index) {\n      res.push(callback.call(thisArg, doc, index, self._selfForIteration));\n    });\n    return res;\n  },\n\n  _rewind: function () {\n    var self = this;\n\n    // known to be synchronous\n    self._dbCursor.rewind();\n\n    self._visitedIds = new LocalCollection._IdMap;\n  },\n\n  // Mostly usable for tailable cursors.\n  close: function () {\n    var self = this;\n\n    self._dbCursor.close();\n  },\n\n  fetch: function () {\n    var self = this;\n    return self.map(_.identity);\n  },\n\n  count: function () {\n    var self = this;\n    return self._synchronousCount().wait();\n  },\n\n  // This method is NOT wrapped in Cursor.\n  getRawObjects: function (ordered) {\n    var self = this;\n    if (ordered) {\n      return self.fetch();\n    } else {\n      var results = new LocalCollection._IdMap;\n      self.forEach(function (doc) {\n        results.set(doc._id, doc);\n      });\n      return results;\n    }\n  }\n});\n\nMongoConnection.prototype.tail = function (cursorDescription, docCallback) {\n  var self = this;\n  if (!cursorDescription.options.tailable)\n    throw new Error(\"Can only tail a tailable cursor\");\n\n  var cursor = self._createSynchronousCursor(cursorDescription);\n\n  var stopped = false;\n  var lastTS = undefined;\n  var loop = function () {\n    while (true) {\n      if (stopped)\n        return;\n      try {\n        var doc = cursor._nextObject();\n      } catch (err) {\n        // There's no good way to figure out if this was actually an error\n        // from Mongo. Ah well. But either way, we need to retry the cursor\n        // (unless the failure was because the observe got stopped).\n        doc = null;\n      }\n      // Since cursor._nextObject can yield, we need to check again to see if\n      // we've been stopped before calling the callback.\n      if (stopped)\n        return;\n      if (doc) {\n        // If a tailable cursor contains a \"ts\" field, use it to recreate the\n        // cursor on error. (\"ts\" is a standard that Mongo uses internally for\n        // the oplog, and there's a special flag that lets you do binary search\n        // on it instead of needing to use an index.)\n        lastTS = doc.ts;\n        docCallback(doc);\n      } else {\n        var newSelector = _.clone(cursorDescription.selector);\n        if (lastTS) {\n          newSelector.ts = {$gt: lastTS};\n        }\n        cursor = self._createSynchronousCursor(new CursorDescription(\n          cursorDescription.collectionName,\n          newSelector,\n          cursorDescription.options));\n        // Mongo failover takes many seconds.  Retry in a bit.  (Without this\n        // setTimeout, we peg the CPU at 100% and never notice the actual\n        // failover.\n        Meteor.setTimeout(loop, 100);\n        break;\n      }\n    }\n  };\n\n  Meteor.defer(loop);\n\n  return {\n    stop: function () {\n      stopped = true;\n      cursor.close();\n    }\n  };\n};\n\nMongoConnection.prototype._observeChanges = function (\n    cursorDescription, ordered, callbacks) {\n  var self = this;\n\n  if (cursorDescription.options.tailable) {\n    return self._observeChangesTailable(cursorDescription, ordered, callbacks);\n  }\n\n  // You may not filter out _id when observing changes, because the id is a core\n  // part of the observeChanges API.\n  if (cursorDescription.options.fields &&\n      (cursorDescription.options.fields._id === 0 ||\n       cursorDescription.options.fields._id === false)) {\n    throw Error(\"You may not observe a cursor with {fields: {_id: 0}}\");\n  }\n\n  var observeKey = JSON.stringify(\n    _.extend({ordered: ordered}, cursorDescription));\n\n  var multiplexer, observeDriver;\n  var firstHandle = false;\n\n  // Find a matching ObserveMultiplexer, or create a new one. This next block is\n  // guaranteed to not yield (and it doesn't call anything that can observe a\n  // new query), so no other calls to this function can interleave with it.\n  Meteor._noYieldsAllowed(function () {\n    if (_.has(self._observeMultiplexers, observeKey)) {\n      multiplexer = self._observeMultiplexers[observeKey];\n    } else {\n      firstHandle = true;\n      // Create a new ObserveMultiplexer.\n      multiplexer = new ObserveMultiplexer({\n        ordered: ordered,\n        onStop: function () {\n          delete self._observeMultiplexers[observeKey];\n          observeDriver.stop();\n        }\n      });\n      self._observeMultiplexers[observeKey] = multiplexer;\n    }\n  });\n\n  var observeHandle = new ObserveHandle(multiplexer, callbacks);\n\n  if (firstHandle) {\n    var matcher, sorter;\n    var canUseOplog = _.all([\n      function () {\n        // At a bare minimum, using the oplog requires us to have an oplog, to\n        // want unordered callbacks, and to not want a callback on the polls\n        // that won't happen.\n        return self._oplogHandle && !ordered &&\n          !callbacks._testOnlyPollCallback;\n      }, function () {\n        // We need to be able to compile the selector. Fall back to polling for\n        // some newfangled $selector that minimongo doesn't support yet.\n        try {\n          matcher = new Minimongo.Matcher(cursorDescription.selector);\n          return true;\n        } catch (e) {\n          // XXX make all compilation errors MinimongoError or something\n          //     so that this doesn't ignore unrelated exceptions\n          return false;\n        }\n      }, function () {\n        // ... and the selector itself needs to support oplog.\n        return OplogObserveDriver.cursorSupported(cursorDescription, matcher);\n      }, function () {\n        // And we need to be able to compile the sort, if any.  eg, can't be\n        // {$natural: 1}.\n        if (!cursorDescription.options.sort)\n          return true;\n        try {\n          sorter = new Minimongo.Sorter(cursorDescription.options.sort,\n                                        { matcher: matcher });\n          return true;\n        } catch (e) {\n          // XXX make all compilation errors MinimongoError or something\n          //     so that this doesn't ignore unrelated exceptions\n          return false;\n        }\n      }], function (f) { return f(); });  // invoke each function\n\n    var driverClass = canUseOplog ? OplogObserveDriver : PollingObserveDriver;\n    observeDriver = new driverClass({\n      cursorDescription: cursorDescription,\n      mongoHandle: self,\n      multiplexer: multiplexer,\n      ordered: ordered,\n      matcher: matcher,  // ignored by polling\n      sorter: sorter,  // ignored by polling\n      _testOnlyPollCallback: callbacks._testOnlyPollCallback\n    });\n\n    // This field is only set for use in tests.\n    multiplexer._observeDriver = observeDriver;\n  }\n\n  // Blocks until the initial adds have been sent.\n  multiplexer.addHandleAndSendInitialAdds(observeHandle);\n\n  return observeHandle;\n};\n\n// Listen for the invalidation messages that will trigger us to poll the\n// database for changes. If this selector specifies specific IDs, specify them\n// here, so that updates to different specific IDs don't cause us to poll.\n// listenCallback is the same kind of (notification, complete) callback passed\n// to InvalidationCrossbar.listen.\n\nlistenAll = function (cursorDescription, listenCallback) {\n  var listeners = [];\n  forEachTrigger(cursorDescription, function (trigger) {\n    listeners.push(DDPServer._InvalidationCrossbar.listen(\n      trigger, listenCallback));\n  });\n\n  return {\n    stop: function () {\n      _.each(listeners, function (listener) {\n        listener.stop();\n      });\n    }\n  };\n};\n\nforEachTrigger = function (cursorDescription, triggerCallback) {\n  var key = {collection: cursorDescription.collectionName};\n  var specificIds = LocalCollection._idsMatchedBySelector(\n    cursorDescription.selector);\n  if (specificIds) {\n    _.each(specificIds, function (id) {\n      triggerCallback(_.extend({id: id}, key));\n    });\n    triggerCallback(_.extend({dropCollection: true, id: null}, key));\n  } else {\n    triggerCallback(key);\n  }\n  // Everyone cares about the database being dropped.\n  triggerCallback({ dropDatabase: true });\n};\n\n// observeChanges for tailable cursors on capped collections.\n//\n// Some differences from normal cursors:\n//   - Will never produce anything other than 'added' or 'addedBefore'. If you\n//     do update a document that has already been produced, this will not notice\n//     it.\n//   - If you disconnect and reconnect from Mongo, it will essentially restart\n//     the query, which will lead to duplicate results. This is pretty bad,\n//     but if you include a field called 'ts' which is inserted as\n//     new MongoInternals.MongoTimestamp(0, 0) (which is initialized to the\n//     current Mongo-style timestamp), we'll be able to find the place to\n//     restart properly. (This field is specifically understood by Mongo with an\n//     optimization which allows it to find the right place to start without\n//     an index on ts. It's how the oplog works.)\n//   - No callbacks are triggered synchronously with the call (there's no\n//     differentiation between \"initial data\" and \"later changes\"; everything\n//     that matches the query gets sent asynchronously).\n//   - De-duplication is not implemented.\n//   - Does not yet interact with the write fence. Probably, this should work by\n//     ignoring removes (which don't work on capped collections) and updates\n//     (which don't affect tailable cursors), and just keeping track of the ID\n//     of the inserted object, and closing the write fence once you get to that\n//     ID (or timestamp?).  This doesn't work well if the document doesn't match\n//     the query, though.  On the other hand, the write fence can close\n//     immediately if it does not match the query. So if we trust minimongo\n//     enough to accurately evaluate the query against the write fence, we\n//     should be able to do this...  Of course, minimongo doesn't even support\n//     Mongo Timestamps yet.\nMongoConnection.prototype._observeChangesTailable = function (\n    cursorDescription, ordered, callbacks) {\n  var self = this;\n\n  // Tailable cursors only ever call added/addedBefore callbacks, so it's an\n  // error if you didn't provide them.\n  if ((ordered && !callbacks.addedBefore) ||\n      (!ordered && !callbacks.added)) {\n    throw new Error(\"Can't observe an \" + (ordered ? \"ordered\" : \"unordered\")\n                    + \" tailable cursor without a \"\n                    + (ordered ? \"addedBefore\" : \"added\") + \" callback\");\n  }\n\n  return self.tail(cursorDescription, function (doc) {\n    var id = doc._id;\n    delete doc._id;\n    // The ts is an implementation detail. Hide it.\n    delete doc.ts;\n    if (ordered) {\n      callbacks.addedBefore(id, doc, null);\n    } else {\n      callbacks.added(id, doc);\n    }\n  });\n};\n\n// XXX We probably need to find a better way to expose this. Right now\n// it's only used by tests, but in fact you need it in normal\n// operation to interact with capped collections.\nMongoInternals.MongoTimestamp = MongoDB.Timestamp;\n\nMongoInternals.Connection = MongoConnection;\n"
  },
  {
    "path": "packages/mongo/mongo_livedata_tests.js",
    "content": "// This is a magic collection that fails its writes on the server when\n// the selector (or inserted document) contains fail: true.\n\nvar TRANSFORMS = {};\n\n// We keep track of the collections, so we can refer to them by name\nvar COLLECTIONS = {};\n\nif (Meteor.isServer) {\n  Meteor.methods({\n    createInsecureCollection: function (name, options) {\n      check(name, String);\n      check(options, Match.Optional({\n        transformName: Match.Optional(String),\n        idGeneration: Match.Optional(String)\n      }));\n\n      if (options && options.transformName) {\n        options.transform = TRANSFORMS[options.transformName];\n      }\n      var c = new Mongo.Collection(name, options);\n      COLLECTIONS[name] = c;\n      c._insecure = true;\n      Meteor.publish('c-' + name, function () {\n        return c.find();\n      });\n    },\n    dropInsecureCollection: function(name) {\n      var c = COLLECTIONS[name];\n      c._dropCollection();\n    }\n  });\n}\n\n// We store the generated id, keyed by collection, for each insert\n// This is so we can test the stub and the server generate the same id\nvar INSERTED_IDS = {};\n\nMeteor.methods({\n  insertObjects: function (collectionName, doc, count) {\n    var c = COLLECTIONS[collectionName];\n    var ids = [];\n    for (var i = 0; i < count; i++) {\n      var id = c.insert(doc);\n      INSERTED_IDS[collectionName] = (INSERTED_IDS[collectionName] || []).concat([id]);\n      ids.push(id);\n    }\n    return ids;\n  },\n  upsertObject: function (collectionName, selector, modifier) {\n    var c = COLLECTIONS[collectionName];\n    return c.upsert(selector, modifier);\n  },\n  doMeteorCall: function (name /*, arguments */) {\n    var args = Array.prototype.slice.call(arguments);\n\n    return Meteor.call.apply(null, args);\n  }\n});\n\nvar runInFence = function (f) {\n  if (Meteor.isClient) {\n    f();\n  } else {\n    var fence = new DDPServer._WriteFence;\n    DDPServer._CurrentWriteFence.withValue(fence, f);\n    fence.armAndWait();\n  }\n};\n\n// Helpers for upsert tests\n\nvar stripId = function (obj) {\n  delete obj._id;\n};\n\nvar compareResults = function (test, skipIds, actual, expected) {\n  if (skipIds) {\n    _.map(actual, stripId);\n    _.map(expected, stripId);\n  }\n  // (technically should ignore order in comparison)\n  test.equal(actual, expected);\n};\n\nvar upsert = function (coll, useUpdate, query, mod, options, callback) {\n  if (! callback && typeof options === \"function\") {\n    callback = options;\n    options = {};\n  }\n\n  if (useUpdate) {\n    if (callback)\n      return coll.update(query, mod,\n                         _.extend({ upsert: true }, options),\n                         function (err, result) {\n                           callback(err, ! err && {\n                             numberAffected: result\n                           });\n                         });\n    return {\n      numberAffected: coll.update(query, mod,\n                                  _.extend({ upsert: true }, options))\n    };\n  } else {\n    return coll.upsert(query, mod, options, callback);\n  }\n};\n\nvar upsertTestMethod = \"livedata_upsert_test_method\";\nvar upsertTestMethodColl;\n\n// This is the implementation of the upsert test method on both the client and\n// the server. On the client, we get a test object. On the server, we just throw\n// errors if something doesn't go according to plan, and when the client\n// receives those errors it will cause the test to fail.\n//\n// Client-side exceptions in here will NOT cause the test to fail! Because it's\n// a stub, those exceptions will get caught and logged.\nvar upsertTestMethodImpl = function (coll, useUpdate, test) {\n  coll.remove({});\n  var result1 = upsert(coll, useUpdate, { foo: \"bar\" }, { foo: \"bar\" });\n\n  if (! test) {\n    test = {\n      equal: function (a, b) {\n        if (! EJSON.equals(a, b))\n          throw new Error(\"Not equal: \" +\n                          JSON.stringify(a) + \", \" + JSON.stringify(b));\n      },\n      isTrue: function (a) {\n        if (! a)\n          throw new Error(\"Not truthy: \" + JSON.stringify(a));\n      },\n      isFalse: function (a) {\n        if (a)\n          throw new Error(\"Not falsey: \" + JSON.stringify(a));\n      }\n    };\n  }\n\n  // if we don't test this, then testing result1.numberAffected will throw,\n  // which will get caught and logged and the whole test will pass!\n  test.isTrue(result1);\n\n  test.equal(result1.numberAffected, 1);\n  if (! useUpdate)\n    test.isTrue(result1.insertedId);\n  var fooId = result1.insertedId;\n  var obj = coll.findOne({ foo: \"bar\" });\n  test.isTrue(obj);\n  if (! useUpdate)\n    test.equal(obj._id, result1.insertedId);\n  var result2 = upsert(coll, useUpdate, { _id: fooId },\n                       { $set: { foo: \"baz \" } });\n  test.isTrue(result2);\n  test.equal(result2.numberAffected, 1);\n  test.isFalse(result2.insertedId);\n};\n\nif (Meteor.isServer) {\n  var m = {};\n  m[upsertTestMethod] = function (run, useUpdate, options) {\n    check(run, String);\n    check(useUpdate, Boolean);\n    upsertTestMethodColl = new Mongo.Collection(upsertTestMethod + \"_collection_\" + run, options);\n    upsertTestMethodImpl(upsertTestMethodColl, useUpdate);\n  };\n  Meteor.methods(m);\n}\n\nMeteor._FailureTestCollection =\n  new Mongo.Collection(\"___meteor_failure_test_collection\");\n\n// For test \"document with a custom type\"\nvar Dog = function (name, color, actions) {\n  var self = this;\n  self.color = color;\n  self.name = name;\n  self.actions = actions || [{name: \"wag\"}, {name: \"swim\"}];\n};\n_.extend(Dog.prototype, {\n  getName: function () { return this.name;},\n  getColor: function () { return this.name;},\n  equals: function (other) { return other.name === this.name &&\n                             other.color === this.color &&\n                             EJSON.equals(other.actions, this.actions);},\n  toJSONValue: function () { return {color: this.color, name: this.name, actions: this.actions};},\n  typeName: function () { return \"dog\"; },\n  clone: function () { return new Dog(this.name, this.color); },\n  speak: function () { return \"woof\"; }\n});\nEJSON.addType(\"dog\", function (o) { return new Dog(o.name, o.color, o.actions);});\n\n\n// Parameterize tests.\n_.each( ['STRING', 'MONGO'], function(idGeneration) {\n\nvar collectionOptions = { idGeneration: idGeneration};\n\ntestAsyncMulti(\"mongo-livedata - database error reporting. \" + idGeneration, [\n  function (test, expect) {\n    var ftc = Meteor._FailureTestCollection;\n\n    var exception = function (err, res) {\n      test.instanceOf(err, Error);\n    };\n\n    _.each([\"insert\", \"remove\", \"update\"], function (op) {\n      var arg = (op === \"insert\" ? {} : 'bla');\n      var arg2 = {};\n\n      var callOp = function (callback) {\n        if (op === \"update\") {\n          ftc[op](arg, arg2, callback);\n        } else {\n          ftc[op](arg, callback);\n        }\n      };\n\n      if (Meteor.isServer) {\n        test.throws(function () {\n          callOp();\n        });\n\n        callOp(expect(exception));\n      }\n\n      if (Meteor.isClient) {\n        callOp(expect(exception));\n\n        // This would log to console in normal operation.\n        Meteor._suppress_log(1);\n        callOp();\n      }\n    });\n  }\n]);\n\n\nTinytest.addAsync(\"mongo-livedata - basics, \" + idGeneration, function (test, onComplete) {\n  var run = test.runId();\n  var coll, coll2;\n  if (Meteor.isClient) {\n    coll = new Mongo.Collection(null, collectionOptions) ; // local, unmanaged\n    coll2 = new Mongo.Collection(null, collectionOptions); // local, unmanaged\n  } else {\n    coll = new Mongo.Collection(\"livedata_test_collection_\"+run, collectionOptions);\n    coll2 = new Mongo.Collection(\"livedata_test_collection_2_\"+run, collectionOptions);\n  }\n\n  var log = '';\n  var obs = coll.find({run: run}, {sort: [\"x\"]}).observe({\n    addedAt: function (doc, before_index, before) {\n      log += 'a(' + doc.x + ',' + before_index + ',' + before + ')';\n    },\n    changedAt: function (new_doc, old_doc, at_index) {\n      log += 'c(' + new_doc.x + ',' + at_index + ',' + old_doc.x + ')';\n    },\n    movedTo: function (doc, old_index, new_index) {\n      log += 'm(' + doc.x + ',' + old_index + ',' + new_index + ')';\n    },\n    removedAt: function (doc, at_index) {\n      log += 'r(' + doc.x + ',' + at_index + ')';\n    }\n  });\n\n  var captureObserve = function (f) {\n    if (Meteor.isClient) {\n      f();\n    } else {\n      var fence = new DDPServer._WriteFence;\n      DDPServer._CurrentWriteFence.withValue(fence, f);\n      fence.armAndWait();\n    }\n\n    var ret = log;\n    log = '';\n    return ret;\n  };\n\n  var expectObserve = function (expected, f) {\n    if (!(expected instanceof Array))\n      expected = [expected];\n\n    test.include(expected, captureObserve(f));\n  };\n\n  test.equal(coll.find({run: run}).count(), 0);\n  test.equal(coll.findOne(\"abc\"), undefined);\n  test.equal(coll.findOne({run: run}), undefined);\n\n  expectObserve('a(1,0,null)', function () {\n    var id = coll.insert({run: run, x: 1});\n    test.equal(coll.find({run: run}).count(), 1);\n    test.equal(coll.findOne(id).x, 1);\n    test.equal(coll.findOne({run: run}).x, 1);\n  });\n\n  expectObserve('a(4,1,null)', function () {\n    var id2 = coll.insert({run: run, x: 4});\n    test.equal(coll.find({run: run}).count(), 2);\n    test.equal(coll.find({_id: id2}).count(), 1);\n    test.equal(coll.findOne(id2).x, 4);\n  });\n\n  test.equal(coll.findOne({run: run}, {sort: [\"x\"], skip: 0}).x, 1);\n  test.equal(coll.findOne({run: run}, {sort: [\"x\"], skip: 1}).x, 4);\n  test.equal(coll.findOne({run: run}, {sort: {x: -1}, skip: 0}).x, 4);\n  test.equal(coll.findOne({run: run}, {sort: {x: -1}, skip: 1}).x, 1);\n\n\n  var cur = coll.find({run: run}, {sort: [\"x\"]});\n  var total = 0;\n  var index = 0;\n  var context = {};\n  cur.forEach(function (doc, i, cursor) {\n    test.equal(i, index++);\n    test.isTrue(cursor === cur);\n    test.isTrue(context === this);\n    total *= 10;\n    if (Meteor.isServer) {\n      // Verify that the callbacks from forEach run sequentially and that\n      // forEach waits for them to complete (issue# 321). If they do not run\n      // sequentially, then the second callback could execute during the first\n      // callback's sleep sleep and the *= 10 will occur before the += 1, then\n      // total (at test.equal time) will be 5. If forEach does not wait for the\n      // callbacks to complete, then total (at test.equal time) will be 0.\n      Meteor._sleepForMs(5);\n    }\n    total += doc.x;\n    // verify the meteor environment is set up here\n    coll2.insert({total:total});\n  }, context);\n  test.equal(total, 14);\n\n  index = 0;\n  test.equal(cur.map(function (doc, i, cursor) {\n    // XXX we could theoretically make map run its iterations in parallel or\n    // something which would make this fail\n    test.equal(i, index++);\n    test.isTrue(cursor === cur);\n    test.isTrue(context === this);\n    return doc.x * 2;\n  }, context), [2, 8]);\n\n  test.equal(_.pluck(coll.find({run: run}, {sort: {x: -1}}).fetch(), \"x\"),\n             [4, 1]);\n\n  expectObserve('', function () {\n    var count = coll.update({run: run, x: -1}, {$inc: {x: 2}}, {multi: true});\n    test.equal(count, 0);\n  });\n\n  expectObserve('c(3,0,1)c(6,1,4)', function () {\n    var count = coll.update({run: run}, {$inc: {x: 2}}, {multi: true});\n    test.equal(count, 2);\n    test.equal(_.pluck(coll.find({run: run}, {sort: {x: -1}}).fetch(), \"x\"),\n               [6, 3]);\n  });\n\n  expectObserve(['c(13,0,3)m(13,0,1)', 'm(6,1,0)c(13,1,3)',\n                 'c(13,0,3)m(6,1,0)', 'm(3,0,1)c(13,1,3)'], function () {\n    coll.update({run: run, x: 3}, {$inc: {x: 10}}, {multi: true});\n    test.equal(_.pluck(coll.find({run: run}, {sort: {x: -1}}).fetch(), \"x\"),\n               [13, 6]);\n  });\n\n  expectObserve('r(13,1)', function () {\n    var count = coll.remove({run: run, x: {$gt: 10}});\n    test.equal(count, 1);\n    test.equal(coll.find({run: run}).count(), 1);\n  });\n\n  expectObserve('r(6,0)', function () {\n    coll.remove({run: run});\n    test.equal(coll.find({run: run}).count(), 0);\n  });\n\n  expectObserve('', function () {\n    var count = coll.remove({run: run});\n    test.equal(count, 0);\n    test.equal(coll.find({run: run}).count(), 0);\n  });\n\n  obs.stop();\n  onComplete();\n});\n\nTinytest.addAsync(\"mongo-livedata - fuzz test, \" + idGeneration, function(test, onComplete) {\n\n  var run = Random.id();\n  var coll;\n  if (Meteor.isClient) {\n    coll = new Mongo.Collection(null, collectionOptions); // local, unmanaged\n  } else {\n    coll = new Mongo.Collection(\"livedata_test_collection_\"+run, collectionOptions);\n  }\n\n  // fuzz test of observe(), especially the server-side diffing\n  var actual = [];\n  var correct = [];\n  var counters = {add: 0, change: 0, move: 0, remove: 0};\n\n  var obs = coll.find({run: run}, {sort: [\"x\"]}).observe({\n    addedAt: function (doc, before_index) {\n      counters.add++;\n      actual.splice(before_index, 0, doc.x);\n    },\n    changedAt: function (new_doc, old_doc, at_index) {\n      counters.change++;\n      test.equal(actual[at_index], old_doc.x);\n      actual[at_index] = new_doc.x;\n    },\n    movedTo: function (doc, old_index, new_index) {\n      counters.move++;\n      test.equal(actual[old_index], doc.x);\n      actual.splice(old_index, 1);\n      actual.splice(new_index, 0, doc.x);\n    },\n    removedAt: function (doc, at_index) {\n      counters.remove++;\n      test.equal(actual[at_index], doc.x);\n      actual.splice(at_index, 1);\n    }\n  });\n\n  if (Meteor.isServer) {\n    // For now, has to be polling (not oplog) because it is ordered observe.\n    test.isTrue(obs._multiplexer._observeDriver._suspendPolling);\n  }\n\n  var step = 0;\n\n  // Use non-deterministic randomness so we can have a shorter fuzz\n  // test (fewer iterations).  For deterministic (fully seeded)\n  // randomness, remove the call to Random.fraction().\n  var seededRandom = new SeededRandom(\"foobard\" + Random.fraction());\n  // Random integer in [0,n)\n  var rnd = function (n) {\n    return seededRandom.nextIntBetween(0, n-1);\n  };\n\n  var finishObserve = function (f) {\n    if (Meteor.isClient) {\n      f();\n    } else {\n      var fence = new DDPServer._WriteFence;\n      DDPServer._CurrentWriteFence.withValue(fence, f);\n      fence.armAndWait();\n    }\n  };\n\n  var doStep = function () {\n    if (step++ === 5) { // run N random tests\n      obs.stop();\n      onComplete();\n      return;\n    }\n\n    var max_counters = _.clone(counters);\n\n    finishObserve(function () {\n      if (Meteor.isServer)\n        obs._multiplexer._observeDriver._suspendPolling();\n\n      // Do a batch of 1-10 operations\n      var batch_count = rnd(10) + 1;\n      for (var i = 0; i < batch_count; i++) {\n        // 25% add, 25% remove, 25% change in place, 25% change and move\n        var op = rnd(4);\n        var which = rnd(correct.length);\n        if (op === 0 || step < 2 || !correct.length) {\n          // Add\n          var x = rnd(1000000);\n          coll.insert({run: run, x: x});\n          correct.push(x);\n          max_counters.add++;\n        } else if (op === 1 || op === 2) {\n          var x = correct[which];\n          if (op === 1)\n            // Small change, not likely to cause a move\n            var val = x + (rnd(2) ? -1 : 1);\n          else\n            // Large change, likely to cause a move\n            var val = rnd(1000000);\n          coll.update({run: run, x: x}, {$set: {x: val}});\n          correct[which] = val;\n          max_counters.change++;\n          max_counters.move++;\n        } else {\n          coll.remove({run: run, x: correct[which]});\n          correct.splice(which, 1);\n          max_counters.remove++;\n        }\n      }\n      if (Meteor.isServer)\n        obs._multiplexer._observeDriver._resumePolling();\n\n    });\n\n    // Did we actually deliver messages that mutated the array in the\n    // right way?\n    correct.sort(function (a,b) {return a-b;});\n    test.equal(actual, correct);\n\n    // Did we limit ourselves to one 'moved' message per change,\n    // rather than O(results) moved messages?\n    _.each(max_counters, function (v, k) {\n      test.isTrue(max_counters[k] >= counters[k], k);\n    });\n\n    Meteor.defer(doStep);\n  };\n\n  doStep();\n\n});\n\nTinytest.addAsync(\"mongo-livedata - scribbling, \" + idGeneration, function (test, onComplete) {\n  var run = test.runId();\n  var coll;\n  if (Meteor.isClient) {\n    coll = new Mongo.Collection(null, collectionOptions); // local, unmanaged\n  } else {\n    coll = new Mongo.Collection(\"livedata_test_collection_\"+run, collectionOptions);\n  }\n\n  var numAddeds = 0;\n  var handle = coll.find({run: run}).observe({\n    addedAt: function (o) {\n      // test that we can scribble on the object we get back from Mongo without\n      // breaking anything.  The worst possible scribble is messing with _id.\n      delete o._id;\n      numAddeds++;\n    }\n  });\n  _.each([123, 456, 789], function (abc) {\n    runInFence(function () {\n      coll.insert({run: run, abc: abc});\n    });\n  });\n  handle.stop();\n  // will be 6 (1+2+3) if we broke diffing!\n  test.equal(numAddeds, 3);\n\n  onComplete();\n});\n\nTinytest.addAsync(\"mongo-livedata - stop handle in callback, \" + idGeneration, function (test, onComplete) {\n  var run = Random.id();\n  var coll;\n  if (Meteor.isClient) {\n    coll = new Mongo.Collection(null, collectionOptions); // local, unmanaged\n  } else {\n    coll = new Mongo.Collection(\"stopHandleInCallback-\"+run, collectionOptions);\n  }\n\n  var output = [];\n\n  var handle = coll.find().observe({\n    added: function (doc) {\n      output.push({added: doc._id});\n    },\n    changed: function (newDoc) {\n      output.push('changed');\n      handle.stop();\n    }\n  });\n\n  test.equal(output, []);\n\n  // Insert a document. Observe that the added callback is called.\n  var docId;\n  runInFence(function () {\n    docId = coll.insert({foo: 42});\n  });\n  test.length(output, 1);\n  test.equal(output.shift(), {added: docId});\n\n  // Update it. Observe that the changed callback is called. This should also\n  // stop the observation.\n  runInFence(function() {\n    coll.update(docId, {$set: {bar: 10}});\n  });\n  test.length(output, 1);\n  test.equal(output.shift(), 'changed');\n\n  // Update again. This shouldn't call the callback because we stopped the\n  // observation.\n  runInFence(function() {\n    coll.update(docId, {$set: {baz: 40}});\n  });\n  test.length(output, 0);\n\n  test.equal(coll.find().count(), 1);\n  test.equal(coll.findOne(docId),\n             {_id: docId, foo: 42, bar: 10, baz: 40});\n\n  onComplete();\n});\n\n// This behavior isn't great, but it beats deadlock.\nif (Meteor.isServer) {\n  Tinytest.addAsync(\"mongo-livedata - recursive observe throws, \" + idGeneration, function (test, onComplete) {\n    var run = test.runId();\n    var coll = new Mongo.Collection(\"observeInCallback-\"+run, collectionOptions);\n\n    var callbackCalled = false;\n    var handle = coll.find({}).observe({\n      added: function (newDoc) {\n        callbackCalled = true;\n        test.throws(function () {\n          coll.find({}).observe();\n        });\n      }\n    });\n    test.isFalse(callbackCalled);\n    // Insert a document. Observe that the added callback is called.\n    runInFence(function () {\n      coll.insert({foo: 42});\n    });\n    test.isTrue(callbackCalled);\n\n    handle.stop();\n\n    onComplete();\n  });\n\n  Tinytest.addAsync(\"mongo-livedata - cursor dedup, \" + idGeneration, function (test, onComplete) {\n    var run = test.runId();\n    var coll = new Mongo.Collection(\"cursorDedup-\"+run, collectionOptions);\n\n    var observer = function (noAdded) {\n      var output = [];\n      var callbacks = {\n        changed: function (newDoc) {\n          output.push({changed: newDoc._id});\n        }\n      };\n      if (!noAdded) {\n        callbacks.added = function (doc) {\n          output.push({added: doc._id});\n        };\n      }\n      var handle = coll.find({foo: 22}).observe(callbacks);\n      return {output: output, handle: handle};\n    };\n\n    // Insert a doc and start observing.\n    var docId1 = coll.insert({foo: 22});\n    var o1 = observer();\n    // Initial add.\n    test.length(o1.output, 1);\n    test.equal(o1.output.shift(), {added: docId1});\n\n    // Insert another doc (blocking until observes have fired).\n    var docId2;\n    runInFence(function () {\n      docId2 = coll.insert({foo: 22, bar: 5});\n    });\n    // Observed add.\n    test.length(o1.output, 1);\n    test.equal(o1.output.shift(), {added: docId2});\n\n    // Second identical observe.\n    var o2 = observer();\n    // Initial adds.\n    test.length(o2.output, 2);\n    test.include([docId1, docId2], o2.output[0].added);\n    test.include([docId1, docId2], o2.output[1].added);\n    test.notEqual(o2.output[0].added, o2.output[1].added);\n    o2.output.length = 0;\n    // Original observe not affected.\n    test.length(o1.output, 0);\n\n    // White-box test: both observes should share an ObserveMultiplexer.\n    var observeMultiplexer = o1.handle._multiplexer;\n    test.isTrue(observeMultiplexer);\n    test.isTrue(observeMultiplexer === o2.handle._multiplexer);\n\n    // Update. Both observes fire.\n    runInFence(function () {\n      coll.update(docId1, {$set: {x: 'y'}});\n    });\n    test.length(o1.output, 1);\n    test.length(o2.output, 1);\n    test.equal(o1.output.shift(), {changed: docId1});\n    test.equal(o2.output.shift(), {changed: docId1});\n\n    // Stop first handle. Second handle still around.\n    o1.handle.stop();\n    test.length(o1.output, 0);\n    test.length(o2.output, 0);\n\n    // Another update. Just the second handle should fire.\n    runInFence(function () {\n      coll.update(docId2, {$set: {z: 'y'}});\n    });\n    test.length(o1.output, 0);\n    test.length(o2.output, 1);\n    test.equal(o2.output.shift(), {changed: docId2});\n\n    // Stop second handle. Nothing should happen, but the multiplexer should\n    // be stopped.\n    test.isTrue(observeMultiplexer._handles);  // This will change.\n    o2.handle.stop();\n    test.length(o1.output, 0);\n    test.length(o2.output, 0);\n    // White-box: ObserveMultiplexer has nulled its _handles so you can't\n    // accidentally join to it.\n    test.isNull(observeMultiplexer._handles);\n\n    // Start yet another handle on the same query.\n    var o3 = observer();\n    // Initial adds.\n    test.length(o3.output, 2);\n    test.include([docId1, docId2], o3.output[0].added);\n    test.include([docId1, docId2], o3.output[1].added);\n    test.notEqual(o3.output[0].added, o3.output[1].added);\n    // Old observers not called.\n    test.length(o1.output, 0);\n    test.length(o2.output, 0);\n    // White-box: Different ObserveMultiplexer.\n    test.isTrue(observeMultiplexer !== o3.handle._multiplexer);\n\n    // Start another handle with no added callback. Regression test for #589.\n    var o4 = observer(true);\n\n    o3.handle.stop();\n    o4.handle.stop();\n\n    onComplete();\n  });\n\n  Tinytest.addAsync(\"mongo-livedata - async server-side insert, \" + idGeneration, function (test, onComplete) {\n    // Tests that insert returns before the callback runs. Relies on the fact\n    // that mongo does not run the callback before spinning off the event loop.\n    var cname = Random.id();\n    var coll = new Mongo.Collection(cname);\n    var doc = { foo: \"bar\" };\n    var x = 0;\n    coll.insert(doc, function (err, result) {\n      test.equal(err, null);\n      test.equal(x, 1);\n      onComplete();\n    });\n    x++;\n  });\n\n  Tinytest.addAsync(\"mongo-livedata - async server-side update, \" + idGeneration, function (test, onComplete) {\n    // Tests that update returns before the callback runs.\n    var cname = Random.id();\n    var coll = new Mongo.Collection(cname);\n    var doc = { foo: \"bar\" };\n    var x = 0;\n    var id = coll.insert(doc);\n    coll.update(id, { $set: { foo: \"baz\" } }, function (err, result) {\n      test.equal(err, null);\n      test.equal(result, 1);\n      test.equal(x, 1);\n      onComplete();\n    });\n    x++;\n  });\n\n  Tinytest.addAsync(\"mongo-livedata - async server-side remove, \" + idGeneration, function (test, onComplete) {\n    // Tests that remove returns before the callback runs.\n    var cname = Random.id();\n    var coll = new Mongo.Collection(cname);\n    var doc = { foo: \"bar\" };\n    var x = 0;\n    var id = coll.insert(doc);\n    coll.remove(id, function (err, result) {\n      test.equal(err, null);\n      test.isFalse(coll.findOne(id));\n      test.equal(x, 1);\n      onComplete();\n    });\n    x++;\n  });\n\n  // compares arrays a and b w/o looking at order\n  var setsEqual = function (a, b) {\n    a = _.map(a, EJSON.stringify);\n    b = _.map(b, EJSON.stringify);\n    return _.isEmpty(_.difference(a, b)) && _.isEmpty(_.difference(b, a));\n  };\n\n  // This test mainly checks the correctness of oplog code dealing with limited\n  // queries. Compitablity with poll-diff is added as well.\n  Tinytest.addAsync(\"mongo-livedata - observe sorted, limited \" + idGeneration, function (test, onComplete) {\n    var run = test.runId();\n    var coll = new Mongo.Collection(\"observeLimit-\"+run, collectionOptions);\n\n    var observer = function () {\n      var state = {};\n      var output = [];\n      var callbacks = {\n        changed: function (newDoc) {\n          output.push({changed: newDoc._id});\n          state[newDoc._id] = newDoc;\n        },\n        added: function (newDoc) {\n          output.push({added: newDoc._id});\n          state[newDoc._id] = newDoc;\n        },\n        removed: function (oldDoc) {\n          output.push({removed: oldDoc._id});\n          delete state[oldDoc._id];\n        }\n      };\n      var handle = coll.find({foo: 22},\n                             {sort: {bar: 1}, limit: 3}).observe(callbacks);\n\n      return {output: output, handle: handle, state: state};\n    };\n    var clearOutput = function (o) { o.output.splice(0, o.output.length); };\n\n    var ins = function (doc) {\n      var id; runInFence(function () { id = coll.insert(doc); });\n      return id;\n    };\n    var rem = function (sel) { runInFence(function () { coll.remove(sel); }); };\n    var upd = function (sel, mod, opt) {\n      runInFence(function () {\n        coll.update(sel, mod, opt);\n      });\n    };\n    // tests '_id' subfields for all documents in oplog buffer\n    var testOplogBufferIds = function (ids) {\n      if (!usesOplog)\n        return;\n      var bufferIds = [];\n      o.handle._multiplexer._observeDriver._unpublishedBuffer.forEach(function (x, id) {\n        bufferIds.push(id);\n      });\n\n      test.isTrue(setsEqual(ids, bufferIds), \"expected: \" + ids + \"; got: \" + bufferIds);\n    };\n    var testSafeAppendToBufferFlag = function (expected) {\n      if (!usesOplog)\n        return;\n      test.equal(o.handle._multiplexer._observeDriver._safeAppendToBuffer,\n                 expected);\n    };\n\n    // We'll describe our state as follows.  5:1 means \"the document with\n    // _id=docId1 and bar=5\".  We list documents as\n    //   [ currently published | in the buffer ] outside the buffer\n    // If safeToAppendToBuffer is true, we'll say ]! instead.\n\n    // Insert a doc and start observing.\n    var docId1 = ins({foo: 22, bar: 5});\n    waitUntilOplogCaughtUp();\n\n    // State: [ 5:1 | ]!\n    var o = observer();\n    var usesOplog = o.handle._multiplexer._observeDriver._usesOplog;\n    // Initial add.\n    test.length(o.output, 1);\n    test.equal(o.output.shift(), {added: docId1});\n    testSafeAppendToBufferFlag(true);\n\n    // Insert another doc (blocking until observes have fired).\n    // State: [ 5:1 6:2 | ]!\n    var docId2 = ins({foo: 22, bar: 6});\n    // Observed add.\n    test.length(o.output, 1);\n    test.equal(o.output.shift(), {added: docId2});\n    testSafeAppendToBufferFlag(true);\n\n    var docId3 = ins({ foo: 22, bar: 3 });\n    // State: [ 3:3 5:1 6:2 | ]!\n    test.length(o.output, 1);\n    test.equal(o.output.shift(), {added: docId3});\n    testSafeAppendToBufferFlag(true);\n\n    // Add a non-matching document\n    ins({ foo: 13 });\n    // It shouldn't be added\n    test.length(o.output, 0);\n\n    // Add something that matches but is too big to fit in\n    var docId4 = ins({ foo: 22, bar: 7 });\n    // State: [ 3:3 5:1 6:2 | 7:4 ]!\n    // It shouldn't be added but should end up in the buffer.\n    test.length(o.output, 0);\n    testOplogBufferIds([docId4]);\n    testSafeAppendToBufferFlag(true);\n\n    // Let's add something small enough to fit in\n    var docId5 = ins({ foo: 22, bar: -1 });\n    // State: [ -1:5 3:3 5:1 | 6:2 7:4 ]!\n    // We should get an added and a removed events\n    test.length(o.output, 2);\n    // doc 2 was removed from the published set as it is too big to be in\n    test.isTrue(setsEqual(o.output, [{added: docId5}, {removed: docId2}]));\n    clearOutput(o);\n    testOplogBufferIds([docId2, docId4]);\n    testSafeAppendToBufferFlag(true);\n\n    // Now remove something and that doc 2 should be right back\n    rem(docId5);\n    // State: [ 3:3 5:1 6:2 | 7:4 ]!\n    test.length(o.output, 2);\n    test.isTrue(setsEqual(o.output, [{removed: docId5}, {added: docId2}]));\n    clearOutput(o);\n    testOplogBufferIds([docId4]);\n    testSafeAppendToBufferFlag(true);\n\n    // Add some negative numbers overflowing the buffer.\n    // New documents will take the published place, [3 5 6] will take the buffer\n    // and 7 will be outside of the buffer in MongoDB.\n    var docId6 = ins({ foo: 22, bar: -1 });\n    var docId7 = ins({ foo: 22, bar: -2 });\n    var docId8 = ins({ foo: 22, bar: -3 });\n    // State: [ -3:8 -2:7 -1:6 | 3:3 5:1 6:2 ] 7:4\n    test.length(o.output, 6);\n    var expected = [{added: docId6}, {removed: docId2},\n                    {added: docId7}, {removed: docId1},\n                    {added: docId8}, {removed: docId3}];\n    test.isTrue(setsEqual(o.output, expected));\n    clearOutput(o);\n    testOplogBufferIds([docId1, docId2, docId3]);\n    testSafeAppendToBufferFlag(false);\n\n    // If we update first 3 docs (increment them by 20), it would be\n    // interesting.\n    upd({ bar: { $lt: 0 }}, { $inc: { bar: 20 } }, { multi: true });\n    // State: [ 3:3 5:1 6:2 | ] 7:4 17:8 18:7 19:6\n    //   which triggers re-poll leaving us at\n    // State: [ 3:3 5:1 6:2 | 7:4 17:8 18:7 ] 19:6\n\n    // The updated documents can't find their place in published and they can't\n    // be buffered as we are not aware of the situation outside of the buffer.\n    // But since our buffer becomes empty, it will be refilled partially with\n    // updated documents.\n    test.length(o.output, 6);\n    var expectedRemoves = [{removed: docId6},\n                           {removed: docId7},\n                           {removed: docId8}];\n    var expectedAdds = [{added: docId3},\n                        {added: docId1},\n                        {added: docId2}];\n\n    test.isTrue(setsEqual(o.output, expectedAdds.concat(expectedRemoves)));\n    clearOutput(o);\n    testOplogBufferIds([docId4, docId7, docId8]);\n    testSafeAppendToBufferFlag(false);\n\n    // Remove first 4 docs (3, 1, 2, 4) forcing buffer to become empty and\n    // schedule a repoll.\n    rem({ bar: { $lt: 10 } });\n    // State: [ 17:8 18:7 19:6 | ]!\n\n    // XXX the oplog code analyzes the events one by one: one remove after\n    // another. Poll-n-diff code, on the other side, analyzes the batch action\n    // of multiple remove. Because of that difference, expected outputs differ.\n    if (usesOplog) {\n      var expectedRemoves = [{removed: docId3}, {removed: docId1},\n                             {removed: docId2}, {removed: docId4}];\n      var expectedAdds = [{added: docId4}, {added: docId8},\n                          {added: docId7}, {added: docId6}];\n\n      test.length(o.output, 8);\n    } else {\n      var expectedRemoves = [{removed: docId3}, {removed: docId1},\n                             {removed: docId2}];\n      var expectedAdds = [{added: docId8}, {added: docId7}, {added: docId6}];\n\n      test.length(o.output, 6);\n    }\n\n    test.isTrue(setsEqual(o.output, expectedAdds.concat(expectedRemoves)));\n    clearOutput(o);\n    testOplogBufferIds([]);\n    testSafeAppendToBufferFlag(true);\n\n    var docId9 = ins({ foo: 22, bar: 21 });\n    var docId10 = ins({ foo: 22, bar: 31 });\n    var docId11 = ins({ foo: 22, bar: 41 });\n    var docId12 = ins({ foo: 22, bar: 51 });\n    // State: [ 17:8 18:7 19:6 | 21:9 31:10 41:11 ] 51:12\n\n    testOplogBufferIds([docId9, docId10, docId11]);\n    testSafeAppendToBufferFlag(false);\n    test.length(o.output, 0);\n    upd({ bar: { $lt: 20 } }, { $inc: { bar: 5 } }, { multi: true });\n    // State: [ 21:9 22:8 23:7 | 24:6 31:10 41:11 ] 51:12\n    test.length(o.output, 4);\n    test.isTrue(setsEqual(o.output, [{removed: docId6},\n                                     {added: docId9},\n                                     {changed: docId7},\n                                     {changed: docId8}]));\n    clearOutput(o);\n    testOplogBufferIds([docId6, docId10, docId11]);\n    testSafeAppendToBufferFlag(false);\n\n    rem(docId9);\n    // State: [ 22:8 23:7 24:6 | 31:10 41:11 ] 51:12\n    test.length(o.output, 2);\n    test.isTrue(setsEqual(o.output, [{removed: docId9}, {added: docId6}]));\n    clearOutput(o);\n    testOplogBufferIds([docId10, docId11]);\n    testSafeAppendToBufferFlag(false);\n\n    upd({ bar: { $gt: 25 } }, { $inc: { bar: -7.5 } }, { multi: true });\n    // State: [ 22:8 23:7 23.5:10 | 24:6 ] 33.5:11 43.5:12\n    // 33.5 doesn't update in-place in buffer, because it the driver is not sure\n    // it can do it: because the buffer does not have the safe append flag set,\n    // for all it knows there is a different doc which is less than 33.5.\n    test.length(o.output, 2);\n    test.isTrue(setsEqual(o.output, [{removed: docId6}, {added: docId10}]));\n    clearOutput(o);\n    testOplogBufferIds([docId6]);\n    testSafeAppendToBufferFlag(false);\n\n    // Force buffer objects to be moved into published set so we can check them\n    rem(docId7);\n    rem(docId8);\n    rem(docId10);\n    // State: [ 24:6 | ] 33.5:11 43.5:12\n    //    triggers repoll\n    // State: [ 24:6 33.5:11 43.5:12 | ]!\n    test.length(o.output, 6);\n    test.isTrue(setsEqual(o.output, [{removed: docId7}, {removed: docId8},\n                                     {removed: docId10}, {added: docId6},\n                                     {added: docId11}, {added: docId12}]));\n\n    test.length(_.keys(o.state), 3);\n    test.equal(o.state[docId6], { _id: docId6, foo: 22, bar: 24 });\n    test.equal(o.state[docId11], { _id: docId11, foo: 22, bar: 33.5 });\n    test.equal(o.state[docId12], { _id: docId12, foo: 22, bar: 43.5 });\n    clearOutput(o);\n    testOplogBufferIds([]);\n    testSafeAppendToBufferFlag(true);\n\n    var docId13 = ins({ foo: 22, bar: 50 });\n    var docId14 = ins({ foo: 22, bar: 51 });\n    var docId15 = ins({ foo: 22, bar: 52 });\n    var docId16 = ins({ foo: 22, bar: 53 });\n    // State: [ 24:6 33.5:11 43.5:12 | 50:13 51:14 52:15 ] 53:16\n    test.length(o.output, 0);\n    testOplogBufferIds([docId13, docId14, docId15]);\n    testSafeAppendToBufferFlag(false);\n\n    // Update something that's outside the buffer to be in the buffer, writing\n    // only to the sort key.\n    upd(docId16, {$set: {bar: 10}});\n    // State: [ 10:16 24:6 33.5:11 | 43.5:12 50:13 51:14 ] 52:15\n    test.length(o.output, 2);\n    test.isTrue(setsEqual(o.output, [{removed: docId12}, {added: docId16}]));\n    clearOutput(o);\n    testOplogBufferIds([docId12, docId13, docId14]);\n    testSafeAppendToBufferFlag(false);\n\n    o.handle.stop();\n    onComplete();\n  });\n\n  Tinytest.addAsync(\"mongo-livedata - observe sorted, limited, sort fields \" + idGeneration, function (test, onComplete) {\n    var run = test.runId();\n    var coll = new Mongo.Collection(\"observeLimit-\"+run, collectionOptions);\n\n    var observer = function () {\n      var state = {};\n      var output = [];\n      var callbacks = {\n        changed: function (newDoc) {\n          output.push({changed: newDoc._id});\n          state[newDoc._id] = newDoc;\n        },\n        added: function (newDoc) {\n          output.push({added: newDoc._id});\n          state[newDoc._id] = newDoc;\n        },\n        removed: function (oldDoc) {\n          output.push({removed: oldDoc._id});\n          delete state[oldDoc._id];\n        }\n      };\n      var handle = coll.find({}, {sort: {x: 1},\n                                  limit: 2,\n                                  fields: {y: 1}}).observe(callbacks);\n\n      return {output: output, handle: handle, state: state};\n    };\n    var clearOutput = function (o) { o.output.splice(0, o.output.length); };\n    var ins = function (doc) {\n      var id; runInFence(function () { id = coll.insert(doc); });\n      return id;\n    };\n    var rem = function (id) {\n      runInFence(function () { coll.remove(id); });\n    };\n\n    var o = observer();\n\n    var docId1 = ins({ x: 1, y: 1222 });\n    var docId2 = ins({ x: 5, y: 5222 });\n\n    test.length(o.output, 2);\n    test.equal(o.output, [{added: docId1}, {added: docId2}]);\n    clearOutput(o);\n\n    var docId3 = ins({ x: 7, y: 7222 });\n    test.length(o.output, 0);\n\n    var docId4 = ins({ x: -1, y: -1222 });\n\n    // Becomes [docId4 docId1 | docId2 docId3]\n    test.length(o.output, 2);\n    test.isTrue(setsEqual(o.output, [{added: docId4}, {removed: docId2}]));\n\n    test.equal(_.size(o.state), 2);\n    test.equal(o.state[docId4], {_id: docId4, y: -1222});\n    test.equal(o.state[docId1], {_id: docId1, y: 1222});\n    clearOutput(o);\n\n    rem(docId2);\n    // Becomes [docId4 docId1 | docId3]\n    test.length(o.output, 0);\n\n    rem(docId4);\n    // Becomes [docId1 docId3]\n    test.length(o.output, 2);\n    test.isTrue(setsEqual(o.output, [{added: docId3}, {removed: docId4}]));\n\n    test.equal(_.size(o.state), 2);\n    test.equal(o.state[docId3], {_id: docId3, y: 7222});\n    test.equal(o.state[docId1], {_id: docId1, y: 1222});\n    clearOutput(o);\n\n    onComplete();\n  });\n\n  Tinytest.addAsync(\"mongo-livedata - observe sorted, limited, big initial set\" + idGeneration, function (test, onComplete) {\n    var run = test.runId();\n    var coll = new Mongo.Collection(\"observeLimit-\"+run, collectionOptions);\n\n    var observer = function () {\n      var state = {};\n      var output = [];\n      var callbacks = {\n        changed: function (newDoc) {\n          output.push({changed: newDoc._id});\n          state[newDoc._id] = newDoc;\n        },\n        added: function (newDoc) {\n          output.push({added: newDoc._id});\n          state[newDoc._id] = newDoc;\n        },\n        removed: function (oldDoc) {\n          output.push({removed: oldDoc._id});\n          delete state[oldDoc._id];\n        }\n      };\n      var handle = coll.find({}, {sort: {x: 1, y: 1}, limit: 3})\n                    .observe(callbacks);\n\n      return {output: output, handle: handle, state: state};\n    };\n    var clearOutput = function (o) { o.output.splice(0, o.output.length); };\n    var ins = function (doc) {\n      var id; runInFence(function () { id = coll.insert(doc); });\n      return id;\n    };\n    var rem = function (id) {\n      runInFence(function () { coll.remove(id); });\n    };\n    // tests '_id' subfields for all documents in oplog buffer\n    var testOplogBufferIds = function (ids) {\n      var bufferIds = [];\n      o.handle._multiplexer._observeDriver._unpublishedBuffer.forEach(function (x, id) {\n        bufferIds.push(id);\n      });\n\n      test.isTrue(setsEqual(ids, bufferIds), \"expected: \" + ids + \"; got: \" + bufferIds);\n    };\n    var testSafeAppendToBufferFlag = function (expected) {\n      if (expected)\n        test.isTrue(o.handle._multiplexer._observeDriver._safeAppendToBuffer);\n      else\n        test.isFalse(o.handle._multiplexer._observeDriver._safeAppendToBuffer);\n    };\n\n    var ids = {};\n    _.each([2, 4, 1, 3, 5, 5, 9, 1, 3, 2, 5], function (x, i) {\n      ids[i] = ins({ x: x, y: i });\n    });\n\n    // Ensure that we are past all the 'i' entries before we run the query, so\n    // that we get the expected phase transitions.\n    waitUntilOplogCaughtUp();\n\n    var o = observer();\n    var usesOplog = o.handle._multiplexer._observeDriver._usesOplog;\n    //  x: [1 1 2 | 2 3 3] 4 5 5 5  9\n    // id: [2 7 0 | 9 3 8] 1 4 5 10 6\n\n    test.length(o.output, 3);\n    test.isTrue(setsEqual([{added: ids[2]}, {added: ids[7]}, {added: ids[0]}], o.output));\n    usesOplog && testOplogBufferIds([ids[9], ids[3], ids[8]]);\n    usesOplog && testSafeAppendToBufferFlag(false);\n    clearOutput(o);\n\n    rem(ids[0]);\n    //  x: [1 1 2 | 3 3] 4 5 5 5  9\n    // id: [2 7 9 | 3 8] 1 4 5 10 6\n    test.length(o.output, 2);\n    test.isTrue(setsEqual([{removed: ids[0]}, {added: ids[9]}], o.output));\n    usesOplog && testOplogBufferIds([ids[3], ids[8]]);\n    usesOplog && testSafeAppendToBufferFlag(false);\n    clearOutput(o);\n\n    rem(ids[7]);\n    //  x: [1 2 3 | 3] 4 5 5 5  9\n    // id: [2 9 3 | 8] 1 4 5 10 6\n    test.length(o.output, 2);\n    test.isTrue(setsEqual([{removed: ids[7]}, {added: ids[3]}], o.output));\n    usesOplog && testOplogBufferIds([ids[8]]);\n    usesOplog && testSafeAppendToBufferFlag(false);\n    clearOutput(o);\n\n    rem(ids[3]);\n    //  x: [1 2 3 | 4 5 5] 5  9\n    // id: [2 9 8 | 1 4 5] 10 6\n    test.length(o.output, 2);\n    test.isTrue(setsEqual([{removed: ids[3]}, {added: ids[8]}], o.output));\n    usesOplog && testOplogBufferIds([ids[1], ids[4], ids[5]]);\n    usesOplog && testSafeAppendToBufferFlag(false);\n    clearOutput(o);\n\n    rem({ x: {$lt: 4} });\n    //  x: [4 5 5 | 5  9]\n    // id: [1 4 5 | 10 6]\n    test.length(o.output, 6);\n    test.isTrue(setsEqual([{removed: ids[2]}, {removed: ids[9]}, {removed: ids[8]},\n                           {added: ids[5]}, {added: ids[4]}, {added: ids[1]}], o.output));\n    usesOplog && testOplogBufferIds([ids[10], ids[6]]);\n    usesOplog && testSafeAppendToBufferFlag(true);\n    clearOutput(o);\n\n\n    onComplete();\n  });\n}\n\n\ntestAsyncMulti('mongo-livedata - empty documents, ' + idGeneration, [\n  function (test, expect) {\n    this.collectionName = Random.id();\n    if (Meteor.isClient) {\n      Meteor.call('createInsecureCollection', this.collectionName);\n      Meteor.subscribe('c-' + this.collectionName, expect());\n    }\n  }, function (test, expect) {\n    var coll = new Mongo.Collection(this.collectionName, collectionOptions);\n\n    coll.insert({}, expect(function (err, id) {\n      test.isFalse(err);\n      test.isTrue(id);\n      var cursor = coll.find();\n      test.equal(cursor.count(), 1);\n    }));\n  }\n]);\n\n// Regression test for #2413.\ntestAsyncMulti('mongo-livedata - upsert without callback, ' + idGeneration, [\n  function (test, expect) {\n    this.collectionName = Random.id();\n    if (Meteor.isClient) {\n      Meteor.call('createInsecureCollection', this.collectionName);\n      Meteor.subscribe('c-' + this.collectionName, expect());\n    }\n  }, function (test, expect) {\n    var coll = new Mongo.Collection(this.collectionName, collectionOptions);\n\n    // No callback!  Before fixing #2413, this method never returned and\n    // so no future DDP methods worked either.\n    coll.upsert('foo', {bar: 1});\n    // Do something else on the same method and expect it to actually work.\n    // (If the bug comes back, this will 'async batch timeout'.)\n    coll.insert({}, expect(function(){}));\n  }\n]);\n\n// See https://github.com/meteor/meteor/issues/594.\ntestAsyncMulti('mongo-livedata - document with length, ' + idGeneration, [\n  function (test, expect) {\n    this.collectionName = Random.id();\n    if (Meteor.isClient) {\n      Meteor.call('createInsecureCollection', this.collectionName, collectionOptions);\n      Meteor.subscribe('c-' + this.collectionName, expect());\n    }\n  }, function (test, expect) {\n    var self = this;\n    var coll = self.coll = new Mongo.Collection(self.collectionName, collectionOptions);\n\n    coll.insert({foo: 'x', length: 0}, expect(function (err, id) {\n      test.isFalse(err);\n      test.isTrue(id);\n      self.docId = id;\n      test.equal(coll.findOne(self.docId),\n                 {_id: self.docId, foo: 'x', length: 0});\n    }));\n  },\n  function (test, expect) {\n    var self = this;\n    var coll = self.coll;\n    coll.update(self.docId, {$set: {length: 5}}, expect(function (err) {\n      test.isFalse(err);\n      test.equal(coll.findOne(self.docId),\n                 {_id: self.docId, foo: 'x', length: 5});\n    }));\n  }\n]);\n\ntestAsyncMulti('mongo-livedata - document with a date, ' + idGeneration, [\n  function (test, expect) {\n    this.collectionName = Random.id();\n    if (Meteor.isClient) {\n      Meteor.call('createInsecureCollection', this.collectionName, collectionOptions);\n      Meteor.subscribe('c-' + this.collectionName, expect());\n    }\n  }, function (test, expect) {\n\n    var coll = new Mongo.Collection(this.collectionName, collectionOptions);\n    var docId;\n    coll.insert({d: new Date(1356152390004)}, expect(function (err, id) {\n      test.isFalse(err);\n      test.isTrue(id);\n      docId = id;\n      var cursor = coll.find();\n      test.equal(cursor.count(), 1);\n      test.equal(coll.findOne().d.getFullYear(), 2012);\n    }));\n  }\n]);\n\ntestAsyncMulti('mongo-livedata - document goes through a transform, ' + idGeneration, [\n  function (test, expect) {\n    var self = this;\n    var seconds = function (doc) {\n      doc.seconds = function () {return doc.d.getSeconds();};\n      return doc;\n    };\n    TRANSFORMS[\"seconds\"] = seconds;\n    self.collectionOptions = {\n      idGeneration: idGeneration,\n      transform: seconds,\n      transformName: \"seconds\"\n    };\n    this.collectionName = Random.id();\n    if (Meteor.isClient) {\n      Meteor.call('createInsecureCollection', this.collectionName, collectionOptions);\n      Meteor.subscribe('c-' + this.collectionName, expect());\n    }\n  }, function (test, expect) {\n    var self = this;\n    self.coll = new Mongo.Collection(self.collectionName, self.collectionOptions);\n    var obs;\n    var expectAdd = expect(function (doc) {\n      test.equal(doc.seconds(), 50);\n    });\n    var expectRemove = expect(function (doc) {\n      test.equal(doc.seconds(), 50);\n      obs.stop();\n    });\n    self.coll.insert({d: new Date(1356152390004)}, expect(function (err, id) {\n      test.isFalse(err);\n      test.isTrue(id);\n      var cursor = self.coll.find();\n      obs = cursor.observe({\n        added: expectAdd,\n        removed: expectRemove\n      });\n      test.equal(cursor.count(), 1);\n      test.equal(cursor.fetch()[0].seconds(), 50);\n      test.equal(self.coll.findOne().seconds(), 50);\n      test.equal(self.coll.findOne({}, {transform: null}).seconds, undefined);\n      test.equal(self.coll.findOne({}, {\n        transform: function (doc) {return {seconds: doc.d.getSeconds()};}\n      }).seconds, 50);\n      self.coll.remove(id);\n    }));\n  },\n  function (test, expect) {\n    var self = this;\n    self.coll.insert({d: new Date(1356152390004)}, expect(function (err, id) {\n      test.isFalse(err);\n      test.isTrue(id);\n      self.id1 = id;\n    }));\n    self.coll.insert({d: new Date(1356152391004)}, expect(function (err, id) {\n      test.isFalse(err);\n      test.isTrue(id);\n      self.id2 = id;\n    }));\n  }\n]);\n\ntestAsyncMulti('mongo-livedata - transform sets _id if not present, ' + idGeneration, [\n  function (test, expect) {\n    var self = this;\n    var justId = function (doc) {\n      return _.omit(doc, '_id');\n    };\n    TRANSFORMS[\"justId\"] = justId;\n    var collectionOptions = {\n      idGeneration: idGeneration,\n      transform: justId,\n      transformName: \"justId\"\n    };\n    this.collectionName = Random.id();\n    if (Meteor.isClient) {\n      Meteor.call('createInsecureCollection', this.collectionName, collectionOptions);\n      Meteor.subscribe('c-' + this.collectionName, expect());\n    }\n  }, function (test, expect) {\n    var self = this;\n    self.coll = new Mongo.Collection(this.collectionName, collectionOptions);\n    self.coll.insert({}, expect(function (err, id) {\n      test.isFalse(err);\n      test.isTrue(id);\n      test.equal(self.coll.findOne()._id, id);\n    }));\n  }\n]);\n\nvar bin = Base64.decode(\n  \"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyBy\" +\n    \"ZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJv\" +\n    \"bSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhl\" +\n    \"IG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdo\" +\n    \"dCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdl\" +\n    \"bmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9y\" +\n    \"dCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=\");\n\ntestAsyncMulti('mongo-livedata - document with binary data, ' + idGeneration, [\n  function (test, expect) {\n    // XXX probably shouldn't use EJSON's private test symbols\n    this.collectionName = Random.id();\n    if (Meteor.isClient) {\n      Meteor.call('createInsecureCollection', this.collectionName, collectionOptions);\n      Meteor.subscribe('c-' + this.collectionName, expect());\n    }\n  }, function (test, expect) {\n    var coll = new Mongo.Collection(this.collectionName, collectionOptions);\n    var docId;\n    coll.insert({b: bin}, expect(function (err, id) {\n      test.isFalse(err);\n      test.isTrue(id);\n      docId = id;\n      var cursor = coll.find();\n      test.equal(cursor.count(), 1);\n      var inColl = coll.findOne();\n      test.isTrue(EJSON.isBinary(inColl.b));\n      test.equal(inColl.b, bin);\n    }));\n  }\n]);\n\ntestAsyncMulti('mongo-livedata - document with a custom type, ' + idGeneration, [\n  function (test, expect) {\n    this.collectionName = Random.id();\n    if (Meteor.isClient) {\n      Meteor.call('createInsecureCollection', this.collectionName, collectionOptions);\n      Meteor.subscribe('c-' + this.collectionName, expect());\n    }\n  }, function (test, expect) {\n    var self = this;\n    self.coll = new Mongo.Collection(this.collectionName, collectionOptions);\n    var docId;\n    // Dog is implemented at the top of the file, outside of the idGeneration\n    // loop (so that we only call EJSON.addType once).\n    var d = new Dog(\"reginald\", \"purple\");\n    self.coll.insert({d: d}, expect(function (err, id) {\n      test.isFalse(err);\n      test.isTrue(id);\n      docId = id;\n      self.docId = docId;\n      var cursor = self.coll.find();\n      test.equal(cursor.count(), 1);\n      var inColl = self.coll.findOne();\n      test.isTrue(inColl);\n      inColl && test.equal(inColl.d.speak(), \"woof\");\n    }));\n  }, function (test, expect) {\n    var self = this;\n    self.coll.insert(new Dog(\"rover\", \"orange\"), expect(function (err, id) {\n      test.isTrue(err);\n      test.isFalse(id);\n    }));\n  }, function (test, expect) {\n    var self = this;\n    self.coll.update(\n      self.docId, new Dog(\"rover\", \"orange\"), expect(function (err) {\n        test.isTrue(err);\n      }));\n  }\n]);\n\nif (Meteor.isServer) {\n  Tinytest.addAsync(\"mongo-livedata - update return values, \" + idGeneration, function (test, onComplete) {\n    var run = test.runId();\n    var coll = new Mongo.Collection(\"livedata_update_result_\"+run, collectionOptions);\n\n    coll.insert({ foo: \"bar\" });\n    coll.insert({ foo: \"baz\" });\n    test.equal(coll.update({}, { $set: { foo: \"qux\" } }, { multi: true }),\n               2);\n    coll.update({}, { $set: { foo: \"quux\" } }, { multi: true }, function (err, result) {\n      test.isFalse(err);\n      test.equal(result, 2);\n      onComplete();\n    });\n  });\n\n  Tinytest.addAsync(\"mongo-livedata - remove return values, \" + idGeneration, function (test, onComplete) {\n    var run = test.runId();\n    var coll = new Mongo.Collection(\"livedata_update_result_\"+run, collectionOptions);\n\n    coll.insert({ foo: \"bar\" });\n    coll.insert({ foo: \"baz\" });\n    test.equal(coll.remove({}), 2);\n    coll.insert({ foo: \"bar\" });\n    coll.insert({ foo: \"baz\" });\n    coll.remove({}, function (err, result) {\n      test.isFalse(err);\n      test.equal(result, 2);\n      onComplete();\n    });\n  });\n\n\n  Tinytest.addAsync(\"mongo-livedata - id-based invalidation, \" + idGeneration, function (test, onComplete) {\n    var run = test.runId();\n    var coll = new Mongo.Collection(\"livedata_invalidation_collection_\"+run, collectionOptions);\n\n    coll.allow({\n      update: function () {return true;},\n      remove: function () {return true;}\n    });\n\n    var id1 = coll.insert({x: 42, is1: true});\n    var id2 = coll.insert({x: 50, is2: true});\n\n    var polls = {};\n    var handlesToStop = [];\n    var observe = function (name, query) {\n      var handle = coll.find(query).observeChanges({\n        // Make sure that we only poll on invalidation, not due to time, and\n        // keep track of when we do. Note: this option disables the use of\n        // oplogs (which admittedly is somewhat irrelevant to this feature).\n        _testOnlyPollCallback: function () {\n          polls[name] = (name in polls ? polls[name] + 1 : 1);\n        }\n      });\n      handlesToStop.push(handle);\n    };\n\n    observe(\"all\", {});\n    observe(\"id1Direct\", id1);\n    observe(\"id1InQuery\", {_id: id1, z: null});\n    observe(\"id2Direct\", id2);\n    observe(\"id2InQuery\", {_id: id2, z: null});\n    observe(\"bothIds\", {_id: {$in: [id1, id2]}});\n\n    var resetPollsAndRunInFence = function (f) {\n      polls = {};\n      runInFence(f);\n    };\n\n    // Update id1 directly. This should poll all but the \"id2\" queries. \"all\"\n    // and \"bothIds\" increment by 2 because they are looking at both.\n    resetPollsAndRunInFence(function () {\n      coll.update(id1, {$inc: {x: 1}});\n    });\n    test.equal(\n      polls,\n      {all: 1, id1Direct: 1, id1InQuery: 1, bothIds: 1});\n\n    // Update id2 using a funny query. This should poll all but the \"id1\"\n    // queries.\n    resetPollsAndRunInFence(function () {\n      coll.update({_id: id2, q: null}, {$inc: {x: 1}});\n    });\n    test.equal(\n      polls,\n      {all: 1, id2Direct: 1, id2InQuery: 1, bothIds: 1});\n\n    // Update both using a $in query. Should poll each of them exactly once.\n    resetPollsAndRunInFence(function () {\n      coll.update({_id: {$in: [id1, id2]}, q: null}, {$inc: {x: 1}});\n    });\n    test.equal(\n      polls,\n      {all: 1, id1Direct: 1, id1InQuery: 1, id2Direct: 1, id2InQuery: 1,\n       bothIds: 1});\n\n    _.each(handlesToStop, function (h) {h.stop();});\n    onComplete();\n  });\n\n  Tinytest.add(\"mongo-livedata - upsert error parse, \" + idGeneration, function (test) {\n    var run = test.runId();\n    var coll = new Mongo.Collection(\"livedata_upsert_errorparse_collection_\"+run, collectionOptions);\n\n    coll.insert({_id: 'foobar'});\n    var err;\n    try {\n      coll.update({_id: 'foobar'}, {_id: 'cowbar'});\n    } catch (e) {\n      err = e;\n    }\n    test.isTrue(err);\n    test.isTrue(MongoInternals.Connection._isCannotChangeIdError(err));\n\n    try {\n      coll.insert({_id: 'foobar'});\n    } catch (e) {\n      err = e;\n    }\n    test.isTrue(err);\n    // duplicate id error is not same as change id error\n    test.isFalse(MongoInternals.Connection._isCannotChangeIdError(err));\n  });\n\n} // end Meteor.isServer\n\n// This test is duplicated below (with some changes) for async upserts that go\n// over the network.\n_.each(Meteor.isServer ? [true, false] : [true], function (minimongo) {\n  _.each([true, false], function (useUpdate) {\n    _.each([true, false], function (useDirectCollection) {\n      Tinytest.add(\"mongo-livedata - \" + (useUpdate ? \"update \" : \"\") + \"upsert\" + (minimongo ? \" minimongo\" : \"\") + (useDirectCollection ? \" direct collection \" : \"\") + \", \" + idGeneration, function (test) {\n        var run = test.runId();\n        var options = collectionOptions;\n        // We don't get ids back when we use update() to upsert, or when we are\n        // directly calling MongoConnection.upsert().\n        var skipIds = useUpdate || (! minimongo && useDirectCollection);\n        if (minimongo)\n          options = _.extend({}, collectionOptions, { connection: null });\n        var coll = new Mongo.Collection(\n          \"livedata_upsert_collection_\"+run+\n            (useUpdate ? \"_update_\" : \"\") +\n            (minimongo ? \"_minimongo_\" : \"\") +\n            (useDirectCollection ? \"_direct_\" : \"\") + \"\",\n          options\n        );\n        if (useDirectCollection)\n          coll = coll._collection;\n\n        var result1 = upsert(coll, useUpdate, {foo: 'bar'}, {foo: 'bar'});\n        test.equal(result1.numberAffected, 1);\n        if (! skipIds)\n          test.isTrue(result1.insertedId);\n        compareResults(test, skipIds, coll.find().fetch(), [{foo: 'bar', _id: result1.insertedId}]);\n\n        var result2 = upsert(coll, useUpdate, {foo: 'bar'}, {foo: 'baz'});\n        test.equal(result2.numberAffected, 1);\n        if (! skipIds)\n          test.isFalse(result2.insertedId);\n        compareResults(test, skipIds, coll.find().fetch(), [{foo: 'baz', _id: result1.insertedId}]);\n\n        coll.remove({});\n\n        // Test values that require transformation to go into Mongo:\n\n        var t1 = new Mongo.ObjectID();\n        var t2 = new Mongo.ObjectID();\n        var result3 = upsert(coll, useUpdate, {foo: t1}, {foo: t1});\n        test.equal(result3.numberAffected, 1);\n        if (! skipIds)\n          test.isTrue(result3.insertedId);\n        compareResults(test, skipIds, coll.find().fetch(), [{foo: t1, _id: result3.insertedId}]);\n\n        var result4 = upsert(coll, useUpdate, {foo: t1}, {foo: t2});\n        test.equal(result2.numberAffected, 1);\n        if (! skipIds)\n          test.isFalse(result2.insertedId);\n        compareResults(test, skipIds, coll.find().fetch(), [{foo: t2, _id: result3.insertedId}]);\n\n        coll.remove({});\n\n        // Test modification by upsert\n\n        var result5 = upsert(coll, useUpdate, {name: 'David'}, {$set: {foo: 1}});\n        test.equal(result5.numberAffected, 1);\n        if (! skipIds)\n          test.isTrue(result5.insertedId);\n        var davidId = result5.insertedId;\n        compareResults(test, skipIds, coll.find().fetch(), [{name: 'David', foo: 1, _id: davidId}]);\n\n        test.throws(function () {\n          // test that bad modifier fails fast\n          upsert(coll, useUpdate, {name: 'David'}, {$blah: {foo: 2}});\n        });\n\n\n        var result6 = upsert(coll, useUpdate, {name: 'David'}, {$set: {foo: 2}});\n        test.equal(result6.numberAffected, 1);\n        if (! skipIds)\n          test.isFalse(result6.insertedId);\n        compareResults(test, skipIds, coll.find().fetch(), [{name: 'David', foo: 2,\n                                                               _id: result5.insertedId}]);\n\n        var emilyId = coll.insert({name: 'Emily', foo: 2});\n        compareResults(test, skipIds, coll.find().fetch(), [{name: 'David', foo: 2, _id: davidId},\n                                                              {name: 'Emily', foo: 2, _id: emilyId}]);\n\n        // multi update by upsert\n        var result7 = upsert(coll, useUpdate, {foo: 2},\n                             {$set: {bar: 7},\n                              $setOnInsert: {name: 'Fred', foo: 2}},\n                             {multi: true});\n        test.equal(result7.numberAffected, 2);\n        if (! skipIds)\n          test.isFalse(result7.insertedId);\n        compareResults(test, skipIds, coll.find().fetch(), [{name: 'David', foo: 2, bar: 7, _id: davidId},\n                                                              {name: 'Emily', foo: 2, bar: 7, _id: emilyId}]);\n\n        // insert by multi upsert\n        var result8 = upsert(coll, useUpdate, {foo: 3},\n                             {$set: {bar: 7},\n                              $setOnInsert: {name: 'Fred', foo: 2}},\n                             {multi: true});\n        test.equal(result8.numberAffected, 1);\n        if (! skipIds)\n          test.isTrue(result8.insertedId);\n        var fredId = result8.insertedId;\n        compareResults(test, skipIds, coll.find().fetch(),\n                       [{name: 'David', foo: 2, bar: 7, _id: davidId},\n                        {name: 'Emily', foo: 2, bar: 7, _id: emilyId},\n                        {name: 'Fred', foo: 2, bar: 7, _id: fredId}]);\n\n        // test `insertedId` option\n        var result9 = upsert(coll, useUpdate, {name: 'Steve'},\n                             {name: 'Steve'},\n                             {insertedId: 'steve'});\n        test.equal(result9.numberAffected, 1);\n        if (! skipIds)\n          test.equal(result9.insertedId, 'steve');\n        compareResults(test, skipIds, coll.find().fetch(),\n                       [{name: 'David', foo: 2, bar: 7, _id: davidId},\n                        {name: 'Emily', foo: 2, bar: 7, _id: emilyId},\n                        {name: 'Fred', foo: 2, bar: 7, _id: fredId},\n                        {name: 'Steve', _id: 'steve'}]);\n        test.isTrue(coll.findOne('steve'));\n        test.isFalse(coll.findOne('fred'));\n\n        // Test $ operator in selectors.\n\n        var result10 = upsert(coll, useUpdate,\n                              {$or: [{name: 'David'}, {name: 'Emily'}]},\n                              {$set: {foo: 3}}, {multi: true});\n        test.equal(result10.numberAffected, 2);\n        if (! skipIds)\n          test.isFalse(result10.insertedId);\n        compareResults(test, skipIds,\n                       [coll.findOne({name: 'David'}), coll.findOne({name: 'Emily'})],\n                       [{name: 'David', foo: 3, bar: 7, _id: davidId},\n                        {name: 'Emily', foo: 3, bar: 7, _id: emilyId}]\n                      );\n\n        var result11 = upsert(\n          coll, useUpdate,\n          {\n            name: 'Charlie',\n            $or: [{ foo: 2}, { bar: 7 }]\n          },\n          { $set: { foo: 3 } }\n        );\n        test.equal(result11.numberAffected, 1);\n        if (! skipIds)\n          test.isTrue(result11.insertedId);\n        var charlieId = result11.insertedId;\n        compareResults(test, skipIds,\n                       coll.find({ name: 'Charlie' }).fetch(),\n                       [{name: 'Charlie', foo: 3, _id: charlieId}]);\n      });\n    });\n  });\n});\n\nvar asyncUpsertTestName = function (useNetwork, useDirectCollection,\n                                    useUpdate, idGeneration) {\n  return \"mongo-livedata - async \" +\n    (useUpdate ? \"update \" : \"\") +\n    \"upsert \" +\n    (useNetwork ? \"over network \" : \"\") +\n    (useDirectCollection ? \", direct collection \" : \"\") +\n    idGeneration;\n};\n\n// This is a duplicate of the test above, with some changes to make it work for\n// callback style. On the client, we test server-backed and in-memory\n// collections, and run the tests for both the Mongo.Collection and the\n// LocalCollection. On the server, we test mongo-backed collections, for both\n// the Mongo.Collection and the MongoConnection.\n//\n// XXX Rewrite with testAsyncMulti, that would simplify things a lot!\n_.each(Meteor.isServer ? [false] : [true, false], function (useNetwork) {\n  _.each(useNetwork ? [false] : [true, false], function (useDirectCollection) {\n    _.each([true, false], function (useUpdate) {\n      Tinytest.addAsync(asyncUpsertTestName(useNetwork, useDirectCollection, useUpdate, idGeneration), function (test, onComplete) {\n        var coll;\n        var run = test.runId();\n        var collName = \"livedata_upsert_collection_\"+run+\n              (useUpdate ? \"_update_\" : \"\") +\n              (useNetwork ? \"_network_\" : \"\") +\n              (useDirectCollection ? \"_direct_\" : \"\");\n\n        var next0 = function () {\n          // Test starts here.\n          upsert(coll, useUpdate, {_id: 'foo'}, {_id: 'foo', foo: 'bar'}, next1);\n        };\n\n        if (useNetwork) {\n          Meteor.call(\"createInsecureCollection\", collName, collectionOptions);\n          coll = new Mongo.Collection(collName, collectionOptions);\n          Meteor.subscribe(\"c-\" + collName, next0);\n        } else {\n          var opts = _.clone(collectionOptions);\n          if (Meteor.isClient)\n            opts.connection = null;\n          coll = new Mongo.Collection(collName, opts);\n          if (useDirectCollection)\n            coll = coll._collection;\n        }\n\n        var result1;\n        var next1 = function (err, result) {\n          result1 = result;\n          test.equal(result1.numberAffected, 1);\n          if (! useUpdate) {\n            test.isTrue(result1.insertedId);\n            test.equal(result1.insertedId, 'foo');\n          }\n          compareResults(test, useUpdate, coll.find().fetch(), [{foo: 'bar', _id: 'foo'}]);\n          upsert(coll, useUpdate, {_id: 'foo'}, {foo: 'baz'}, next2);\n        };\n\n        if (! useNetwork) {\n          next0();\n        }\n\n        var t1, t2, result2;\n        var next2 = function (err, result) {\n          result2 = result;\n          test.equal(result2.numberAffected, 1);\n          if (! useUpdate)\n            test.isFalse(result2.insertedId);\n          compareResults(test, useUpdate, coll.find().fetch(), [{foo: 'baz', _id: result1.insertedId}]);\n          coll.remove({_id: 'foo'});\n          compareResults(test, useUpdate, coll.find().fetch(), []);\n\n          // Test values that require transformation to go into Mongo:\n\n          t1 = new Mongo.ObjectID();\n          t2 = new Mongo.ObjectID();\n          upsert(coll, useUpdate, {_id: t1}, {_id: t1, foo: 'bar'}, next3);\n        };\n\n        var result3;\n        var next3 = function (err, result) {\n          result3 = result;\n          test.equal(result3.numberAffected, 1);\n          if (! useUpdate) {\n            test.isTrue(result3.insertedId);\n            test.equal(t1, result3.insertedId);\n          }\n          compareResults(test, useUpdate, coll.find().fetch(), [{_id: t1, foo: 'bar'}]);\n\n          upsert(coll, useUpdate, {_id: t1}, {foo: t2}, next4);\n        };\n\n        var next4 = function (err, result4) {\n          test.equal(result2.numberAffected, 1);\n          if (! useUpdate)\n            test.isFalse(result2.insertedId);\n          compareResults(test, useUpdate, coll.find().fetch(), [{foo: t2, _id: result3.insertedId}]);\n\n          coll.remove({_id: t1});\n\n          // Test modification by upsert\n          upsert(coll, useUpdate, {_id: 'David'}, {$set: {foo: 1}}, next5);\n        };\n\n        var result5;\n        var next5 = function (err, result) {\n          result5 = result;\n          test.equal(result5.numberAffected, 1);\n          if (! useUpdate) {\n            test.isTrue(result5.insertedId);\n            test.equal(result5.insertedId, 'David');\n          }\n          var davidId = result5.insertedId;\n          compareResults(test, useUpdate, coll.find().fetch(), [{foo: 1, _id: davidId}]);\n\n          if (! Meteor.isClient && useDirectCollection) {\n            // test that bad modifier fails\n            // The stub throws an exception about the invalid modifier, which\n            // livedata logs (so we suppress it).\n            Meteor._suppress_log(1);\n            upsert(coll, useUpdate, {_id: 'David'}, {$blah: {foo: 2}}, function (err) {\n              if (! (Meteor.isClient && useDirectCollection))\n                test.isTrue(err);\n              upsert(coll, useUpdate, {_id: 'David'}, {$set: {foo: 2}}, next6);\n            });\n          } else {\n            // XXX skip this test for now for LocalCollection; the fact that\n            // we're in a nested sequence of callbacks means we're inside a\n            // Meteor.defer, which means the exception just gets\n            // logged. Something should be done about this at some point?  Maybe\n            // LocalCollection callbacks don't really have to be deferred.\n            upsert(coll, useUpdate, {_id: 'David'}, {$set: {foo: 2}}, next6);\n          }\n        };\n\n        var result6;\n        var next6 = function (err, result) {\n          result6 = result;\n          test.equal(result6.numberAffected, 1);\n          if (! useUpdate)\n            test.isFalse(result6.insertedId);\n          compareResults(test, useUpdate, coll.find().fetch(), [{_id: 'David', foo: 2}]);\n\n          var emilyId = coll.insert({_id: 'Emily', foo: 2});\n          compareResults(test, useUpdate, coll.find().fetch(), [{_id: 'David', foo: 2},\n                                                                {_id: 'Emily', foo: 2}]);\n\n          // multi update by upsert.\n          // We can't actually update multiple documents since we have to do it by\n          // id, but at least make sure the multi flag doesn't mess anything up.\n          upsert(coll, useUpdate, {_id: 'Emily'},\n                 {$set: {bar: 7},\n                  $setOnInsert: {name: 'Fred', foo: 2}},\n                 {multi: true}, next7);\n        };\n\n        var result7;\n        var next7 = function (err, result) {\n          result7 = result;\n          test.equal(result7.numberAffected, 1);\n          if (! useUpdate)\n            test.isFalse(result7.insertedId);\n          compareResults(test, useUpdate, coll.find().fetch(), [{_id: 'David', foo: 2},\n                                                                {_id: 'Emily', foo: 2, bar: 7}]);\n\n          // insert by multi upsert\n          upsert(coll, useUpdate, {_id: 'Fred'},\n                 {$set: {bar: 7},\n                  $setOnInsert: {name: 'Fred', foo: 2}},\n                 {multi: true}, next8);\n\n        };\n\n        var result8;\n        var next8 = function (err, result) {\n          result8 = result;\n\n          test.equal(result8.numberAffected, 1);\n          if (! useUpdate) {\n            test.isTrue(result8.insertedId);\n            test.equal(result8.insertedId, 'Fred');\n          }\n          var fredId = result8.insertedId;\n          compareResults(test, useUpdate,  coll.find().fetch(),\n                         [{_id: 'David', foo: 2},\n                          {_id: 'Emily', foo: 2, bar: 7},\n                          {name: 'Fred', foo: 2, bar: 7, _id: fredId}]);\n          onComplete();\n        };\n      });\n    });\n  });\n});\n\nif (Meteor.isClient) {\n  Tinytest.addAsync(\"mongo-livedata - async update/remove return values over network \" + idGeneration, function (test, onComplete) {\n    var coll;\n    var run = test.runId();\n    var collName = \"livedata_upsert_collection_\"+run;\n    Meteor.call(\"createInsecureCollection\", collName, collectionOptions);\n    coll = new Mongo.Collection(collName, collectionOptions);\n    Meteor.subscribe(\"c-\" + collName, function () {\n      coll.insert({ _id: \"foo\" });\n      coll.insert({ _id: \"bar\" });\n      coll.update({ _id: \"foo\" }, { $set: { foo: 1 } }, { multi: true }, function (err, result) {\n        test.isFalse(err);\n        test.equal(result, 1);\n        coll.update({ _id: \"foo\" }, { _id: \"foo\", foo: 2 }, function (err, result) {\n          test.isFalse(err);\n          test.equal(result, 1);\n          coll.update({ _id: \"baz\" }, { $set: { foo: 1 } }, function (err, result) {\n            test.isFalse(err);\n            test.equal(result, 0);\n            coll.remove({ _id: \"foo\" }, function (err, result) {\n              test.equal(result, 1);\n              coll.remove({ _id: \"baz\" }, function (err, result) {\n                test.equal(result, 0);\n                onComplete();\n              });\n            });\n          });\n        });\n      });\n    });\n  });\n}\n\n// Runs a method and its stub which do some upserts. The method throws an error\n// if we don't get the right return values.\nif (Meteor.isClient) {\n  _.each([true, false], function (useUpdate) {\n    Tinytest.addAsync(\"mongo-livedata - \" + (useUpdate ? \"update \" : \"\") + \"upsert in method, \" + idGeneration, function (test, onComplete) {\n      var run = test.runId();\n      upsertTestMethodColl = new Mongo.Collection(upsertTestMethod + \"_collection_\" + run, collectionOptions);\n      var m = {};\n      delete Meteor.connection._methodHandlers[upsertTestMethod];\n      m[upsertTestMethod] = function (run, useUpdate, options) {\n        upsertTestMethodImpl(upsertTestMethodColl, useUpdate, test);\n      };\n      Meteor.methods(m);\n      Meteor.call(upsertTestMethod, run, useUpdate, collectionOptions, function (err, result) {\n        test.isFalse(err);\n        onComplete();\n      });\n    });\n  });\n}\n\n_.each(Meteor.isServer ? [true, false] : [true], function (minimongo) {\n  _.each([true, false], function (useUpdate) {\n    Tinytest.add(\"mongo-livedata - \" + (useUpdate ? \"update \" : \"\") + \"upsert by id\" + (minimongo ? \" minimongo\" : \"\") + \", \" + idGeneration, function (test) {\n      var run = test.runId();\n      var options = collectionOptions;\n      if (minimongo)\n        options = _.extend({}, collectionOptions, { connection: null });\n      var coll = new Mongo.Collection(\"livedata_upsert_by_id_collection_\"+run, options);\n\n      var ret;\n      ret = upsert(coll, useUpdate, {_id: 'foo'}, {$set: {x: 1}});\n      test.equal(ret.numberAffected, 1);\n      if (! useUpdate)\n        test.equal(ret.insertedId, 'foo');\n      compareResults(test, useUpdate, coll.find().fetch(),\n                     [{_id: 'foo', x: 1}]);\n\n      ret = upsert(coll, useUpdate, {_id: 'foo'}, {$set: {x: 2}});\n      test.equal(ret.numberAffected, 1);\n      if (! useUpdate)\n        test.isFalse(ret.insertedId);\n      compareResults(test, useUpdate, coll.find().fetch(),\n                     [{_id: 'foo', x: 2}]);\n\n      ret = upsert(coll, useUpdate, {_id: 'bar'}, {$set: {x: 1}});\n      test.equal(ret.numberAffected, 1);\n      if (! useUpdate)\n        test.equal(ret.insertedId, 'bar');\n      compareResults(test, useUpdate, coll.find().fetch(),\n                     [{_id: 'foo', x: 2},\n                      {_id: 'bar', x: 1}]);\n\n      coll.remove({});\n      ret = upsert(coll, useUpdate, {_id: 'traq'}, {x: 1});\n\n      test.equal(ret.numberAffected, 1);\n      var myId = ret.insertedId;\n      if (useUpdate) {\n        myId = coll.findOne()._id;\n      }\n      // Starting with Mongo 2.6, upsert with entire document takes _id from the\n      // query, so the above upsert actually does an insert with _id traq\n      // instead of a random _id.  Whenever we are using our simulated upsert,\n      // we have this behavior (whether running against Mongo 2.4 or 2.6).\n      // https://jira.mongodb.org/browse/SERVER-5289\n      test.equal(myId, 'traq');\n      compareResults(test, useUpdate, coll.find().fetch(),\n                     [{x: 1, _id: 'traq'}]);\n\n      // this time, insert as _id 'traz'\n      ret = upsert(coll, useUpdate, {_id: 'traz'}, {_id: 'traz', x: 2});\n      test.equal(ret.numberAffected, 1);\n      if (! useUpdate)\n        test.equal(ret.insertedId, 'traz');\n      compareResults(test, useUpdate, coll.find().fetch(),\n                     [{x: 1, _id: 'traq'},\n                      {x: 2, _id: 'traz'}]);\n\n      // now update _id 'traz'\n      ret = upsert(coll, useUpdate, {_id: 'traz'}, {x: 3});\n      test.equal(ret.numberAffected, 1);\n      test.isFalse(ret.insertedId);\n      compareResults(test, useUpdate, coll.find().fetch(),\n                     [{x: 1, _id: 'traq'},\n                      {x: 3, _id: 'traz'}]);\n\n      // now update, passing _id (which is ok as long as it's the same)\n      ret = upsert(coll, useUpdate, {_id: 'traz'}, {_id: 'traz', x: 4});\n      test.equal(ret.numberAffected, 1);\n      test.isFalse(ret.insertedId);\n      compareResults(test, useUpdate, coll.find().fetch(),\n                     [{x: 1, _id: 'traq'},\n                      {x: 4, _id: 'traz'}]);\n\n    });\n  });\n});\n\n});  // end idGeneration parametrization\n\nTinytest.add('mongo-livedata - rewrite selector', function (test) {\n  test.equal(Mongo.Collection._rewriteSelector({x: /^o+B/im}),\n             {x: {$regex: '^o+B', $options: 'im'}});\n  test.equal(Mongo.Collection._rewriteSelector({x: {$regex: /^o+B/im}}),\n             {x: {$regex: '^o+B', $options: 'im'}});\n  test.equal(Mongo.Collection._rewriteSelector({x: /^o+B/}),\n             {x: {$regex: '^o+B'}});\n  test.equal(Mongo.Collection._rewriteSelector({x: {$regex: /^o+B/}}),\n             {x: {$regex: '^o+B'}});\n  test.equal(Mongo.Collection._rewriteSelector('foo'),\n             {_id: 'foo'});\n\n  test.equal(\n    Mongo.Collection._rewriteSelector(\n      {'$or': [\n        {x: /^o/},\n        {y: /^p/},\n        {z: 'q'},\n        {w: {$regex: /^r/}}\n      ]}\n    ),\n    {'$or': [\n      {x: {$regex: '^o'}},\n      {y: {$regex: '^p'}},\n      {z: 'q'},\n      {w: {$regex: '^r'}}\n    ]}\n  );\n\n  test.equal(\n    Mongo.Collection._rewriteSelector(\n      {'$or': [\n        {'$and': [\n          {x: /^a/i},\n          {y: /^b/},\n          {z: {$regex: /^c/i}},\n          {w: {$regex: '^[abc]', $options: 'i'}}, // make sure we don't break vanilla selectors\n          {v: {$regex: /O/, $options: 'i'}}, // $options should override the ones on the RegExp object\n          {u: {$regex: /O/m, $options: 'i'}} // $options should override the ones on the RegExp object\n        ]},\n        {'$nor': [\n          {s: /^d/},\n          {t: /^e/i},\n          {u: {$regex: /^f/i}},\n          // even empty string overrides built-in flags\n          {v: {$regex: /^g/i, $options: ''}}\n        ]}\n      ]}\n    ),\n    {'$or': [\n      {'$and': [\n        {x: {$regex: '^a', $options: 'i'}},\n        {y: {$regex: '^b'}},\n        {z: {$regex: '^c', $options: 'i'}},\n        {w: {$regex: '^[abc]', $options: 'i'}},\n        {v: {$regex: 'O', $options: 'i'}},\n        {u: {$regex: 'O', $options: 'i'}}\n      ]},\n      {'$nor': [\n        {s: {$regex: '^d'}},\n        {t: {$regex: '^e', $options: 'i'}},\n        {u: {$regex: '^f', $options: 'i'}},\n        {v: {$regex: '^g', $options: ''}}\n      ]}\n    ]}\n  );\n\n  var oid = new Mongo.ObjectID();\n  test.equal(Mongo.Collection._rewriteSelector(oid),\n             {_id: oid});\n});\n\ntestAsyncMulti('mongo-livedata - specified _id', [\n  function (test, expect) {\n    this.collectionName = Random.id();\n    if (Meteor.isClient) {\n      Meteor.call('createInsecureCollection', this.collectionName);\n      Meteor.subscribe('c-' + this.collectionName, expect());\n    }\n  }, function (test, expect) {\n    var expectError = expect(function (err, result) {\n      test.isTrue(err);\n      var doc = coll.findOne();\n      test.equal(doc.name, \"foo\");\n    });\n    var coll = new Mongo.Collection(this.collectionName);\n    coll.insert({_id: \"foo\", name: \"foo\"}, expect(function (err1, id) {\n      test.equal(id, \"foo\");\n      var doc = coll.findOne();\n      test.equal(doc._id, \"foo\");\n      Meteor._suppress_log(1);\n      coll.insert({_id: \"foo\", name: \"bar\"}, expectError);\n    }));\n  }\n]);\n\n\n// Consistent id generation tests\nfunction collectionInsert (test, expect, coll, index) {\n  var clientSideId = coll.insert({name: \"foo\"}, expect(function (err1, id) {\n    test.equal(id, clientSideId);\n    var o = coll.findOne(id);\n    test.isTrue(_.isObject(o));\n    test.equal(o.name, 'foo');\n  }));\n};\n\nfunction collectionUpsert (test, expect, coll, index) {\n  var upsertId = '123456' + index;\n\n  coll.upsert(upsertId, {$set: {name: \"foo\"}}, expect(function (err1, result) {\n    test.equal(result.insertedId, upsertId);\n    test.equal(result.numberAffected, 1);\n\n    var o = coll.findOne(upsertId);\n    test.isTrue(_.isObject(o));\n    test.equal(o.name, 'foo');\n  }));\n};\n\nfunction collectionUpsertExisting (test, expect, coll, index) {\n  var clientSideId = coll.insert({name: \"foo\"}, expect(function (err1, id) {\n    test.equal(id, clientSideId);\n\n    var o = coll.findOne(id);\n    test.isTrue(_.isObject(o));\n    // We're not testing sequencing/visibility rules here, so skip this check\n    // test.equal(o.name, 'foo');\n  }));\n\n  coll.upsert(clientSideId, {$set: {name: \"bar\"}}, expect(function (err1, result) {\n    test.equal(result.insertedId, clientSideId);\n    test.equal(result.numberAffected, 1);\n\n    var o = coll.findOne(clientSideId);\n    test.isTrue(_.isObject(o));\n    test.equal(o.name, 'bar');\n  }));\n};\n\nfunction functionCallsInsert (test, expect, coll, index) {\n  Meteor.call(\"insertObjects\", coll._name, {name: \"foo\"}, 1, expect(function (err1, ids) {\n    test.notEqual((INSERTED_IDS[coll._name] || []).length, 0);\n    var stubId = INSERTED_IDS[coll._name][index];\n\n    test.equal(ids.length, 1);\n    test.equal(ids[0], stubId);\n\n    var o = coll.findOne(stubId);\n    test.isTrue(_.isObject(o));\n    test.equal(o.name, 'foo');\n  }));\n};\n\nfunction functionCallsUpsert (test, expect, coll, index) {\n  var upsertId = '123456' + index;\n  Meteor.call(\"upsertObject\", coll._name, upsertId, {$set:{name: \"foo\"}}, expect(function (err1, result) {\n    test.equal(result.insertedId, upsertId);\n    test.equal(result.numberAffected, 1);\n\n    var o = coll.findOne(upsertId);\n    test.isTrue(_.isObject(o));\n    test.equal(o.name, 'foo');\n  }));\n};\n\nfunction functionCallsUpsertExisting (test, expect, coll, index) {\n  var id = coll.insert({name: \"foo\"});\n\n  var o = coll.findOne(id);\n  test.notEqual(null, o);\n  test.equal(o.name, 'foo');\n\n  Meteor.call(\"upsertObject\", coll._name, id, {$set:{name: \"bar\"}}, expect(function (err1, result) {\n    test.equal(result.numberAffected, 1);\n    test.equal(result.insertedId, undefined);\n\n    var o = coll.findOne(id);\n    test.isTrue(_.isObject(o));\n    test.equal(o.name, 'bar');\n  }));\n};\n\nfunction functionCalls3Inserts (test, expect, coll, index) {\n  Meteor.call(\"insertObjects\", coll._name, {name: \"foo\"}, 3, expect(function (err1, ids) {\n    test.notEqual((INSERTED_IDS[coll._name] || []).length, 0);\n    test.equal(ids.length, 3);\n\n    for (var i = 0; i < 3; i++) {\n      var stubId = INSERTED_IDS[coll._name][(3 * index) + i];\n      test.equal(ids[i], stubId);\n\n      var o = coll.findOne(stubId);\n      test.isTrue(_.isObject(o));\n      test.equal(o.name, 'foo');\n    }\n  }));\n};\n\nfunction functionChainInsert (test, expect, coll, index) {\n  Meteor.call(\"doMeteorCall\", \"insertObjects\", coll._name, {name: \"foo\"}, 1, expect(function (err1, ids) {\n    test.notEqual((INSERTED_IDS[coll._name] || []).length, 0);\n    var stubId = INSERTED_IDS[coll._name][index];\n\n    test.equal(ids.length, 1);\n    test.equal(ids[0], stubId);\n\n    var o = coll.findOne(stubId);\n    test.isTrue(_.isObject(o));\n    test.equal(o.name, 'foo');\n  }));\n};\n\nfunction functionChain2Insert (test, expect, coll, index) {\n  Meteor.call(\"doMeteorCall\", \"doMeteorCall\", \"insertObjects\", coll._name, {name: \"foo\"}, 1, expect(function (err1, ids) {\n    test.notEqual((INSERTED_IDS[coll._name] || []).length, 0);\n    var stubId = INSERTED_IDS[coll._name][index];\n\n    test.equal(ids.length, 1);\n    test.equal(ids[0], stubId);\n\n    var o = coll.findOne(stubId);\n    test.isTrue(_.isObject(o));\n    test.equal(o.name, 'foo');\n  }));\n};\n\nfunction functionChain2Upsert (test, expect, coll, index) {\n  var upsertId = '123456' + index;\n  Meteor.call(\"doMeteorCall\", \"doMeteorCall\", \"upsertObject\", coll._name, upsertId, {$set:{name: \"foo\"}}, expect(function (err1, result) {\n    test.equal(result.insertedId, upsertId);\n    test.equal(result.numberAffected, 1);\n\n    var o = coll.findOne(upsertId);\n    test.isTrue(_.isObject(o));\n    test.equal(o.name, 'foo');\n  }));\n};\n\n_.each( {collectionInsert: collectionInsert,\n         collectionUpsert: collectionUpsert,\n         functionCallsInsert: functionCallsInsert,\n         functionCallsUpsert: functionCallsUpsert,\n         functionCallsUpsertExisting: functionCallsUpsertExisting,\n         functionCalls3Insert: functionCalls3Inserts,\n         functionChainInsert: functionChainInsert,\n         functionChain2Insert: functionChain2Insert,\n         functionChain2Upsert: functionChain2Upsert}, function (fn, name) {\n_.each( [1, 3], function (repetitions) {\n_.each( [1, 3], function (collectionCount) {\n_.each( ['STRING', 'MONGO'], function (idGeneration) {\n\n  testAsyncMulti('mongo-livedata - consistent _id generation ' + name + ', ' + repetitions + ' repetitions on ' + collectionCount + ' collections, idGeneration=' + idGeneration, [ function (test, expect) {\n    var collectionOptions = { idGeneration: idGeneration };\n\n    var cleanups = this.cleanups = [];\n    this.collections = _.times(collectionCount, function () {\n      var collectionName = \"consistentid_\" + Random.id();\n      if (Meteor.isClient) {\n        Meteor.call('createInsecureCollection', collectionName, collectionOptions);\n        Meteor.subscribe('c-' + collectionName, expect());\n        cleanups.push(function (expect) { Meteor.call('dropInsecureCollection', collectionName, expect(function () {})); });\n      }\n\n      var collection = new Mongo.Collection(collectionName, collectionOptions);\n      if (Meteor.isServer) {\n        cleanups.push(function () { collection._dropCollection(); });\n      }\n      COLLECTIONS[collectionName] = collection;\n      return collection;\n    });\n  }, function (test, expect) {\n    // now run the actual test\n    for (var i = 0; i < repetitions; i++) {\n      for (var j = 0; j < collectionCount; j++) {\n        fn(test, expect, this.collections[j], i);\n      }\n    }\n  }, function (test, expect) {\n    // Run any registered cleanup functions (e.g. to drop collections)\n    _.each(this.cleanups, function(cleanup) {\n      cleanup(expect);\n    });\n  }]);\n\n});\n});\n});\n});\n\n\n\ntestAsyncMulti('mongo-livedata - empty string _id', [\n  function (test, expect) {\n    var self = this;\n    self.collectionName = Random.id();\n    if (Meteor.isClient) {\n      Meteor.call('createInsecureCollection', self.collectionName);\n      Meteor.subscribe('c-' + self.collectionName, expect());\n    }\n    self.coll = new Mongo.Collection(self.collectionName);\n    try {\n      self.coll.insert({_id: \"\", f: \"foo\"});\n      test.fail(\"Insert with an empty _id should fail\");\n    } catch (e) {\n      // ok\n    }\n    self.coll.insert({_id: \"realid\", f: \"bar\"}, expect(function (err, res) {\n      test.equal(res, \"realid\");\n    }));\n  },\n  function (test, expect) {\n    var self = this;\n    var docs = self.coll.find().fetch();\n    test.equal(docs, [{_id: \"realid\", f: \"bar\"}]);\n  },\n  function (test, expect) {\n    var self = this;\n    if (Meteor.isServer) {\n      self.coll._collection.insert({_id: \"\", f: \"baz\"});\n      test.equal(self.coll.find().fetch().length, 2);\n    }\n  }\n]);\n\n\nif (Meteor.isServer) {\n\n  testAsyncMulti(\"mongo-livedata - minimongo on server to server connection\", [\n    function (test, expect) {\n      var self = this;\n      Meteor._debug(\"connection setup\");\n      self.id = Random.id();\n      var C = self.C = new Mongo.Collection(\"ServerMinimongo_\" + self.id);\n      C.allow({\n        insert: function () {return true;},\n        update: function () {return true;},\n        remove: function () {return true;}\n      });\n      C.insert({a: 0, b: 1});\n      C.insert({a: 0, b: 2});\n      C.insert({a: 1, b: 3});\n      Meteor.publish(self.id, function () {\n        return C.find({a: 0});\n      });\n\n      self.conn = DDP.connect(Meteor.absoluteUrl());\n      pollUntil(expect, function () {\n        return self.conn.status().connected;\n      }, 10000);\n    },\n\n    function (test, expect) {\n      var self = this;\n      if (self.conn.status().connected) {\n        self.miniC = new Mongo.Collection(\"ServerMinimongo_\" + self.id, {\n          connection: self.conn\n        });\n        var exp = expect(function (err) {\n          test.isFalse(err);\n        });\n        self.conn.subscribe(self.id, {\n          onError: exp,\n          onReady: exp\n        });\n      }\n    },\n\n    function (test, expect) {\n      var self = this;\n      if (self.miniC) {\n        var contents = self.miniC.find().fetch();\n        test.equal(contents.length, 2);\n        test.equal(contents[0].a, 0);\n      }\n    },\n\n    function (test, expect) {\n      var self = this;\n      if (!self.miniC)\n        return;\n      self.miniC.insert({a:0, b:3});\n      var contents = self.miniC.find({b:3}).fetch();\n      test.equal(contents.length, 1);\n      test.equal(contents[0].a, 0);\n    }\n  ]);\n\n  testAsyncMulti(\"mongo-livedata - minimongo observe on server\", [\n    function (test, expect) {\n      var self = this;\n      self.id = Random.id();\n      self.C = new Mongo.Collection(\"ServerMinimongoObserve_\" + self.id);\n      self.events = [];\n\n      Meteor.publish(self.id, function () {\n        return self.C.find();\n      });\n\n      self.conn = DDP.connect(Meteor.absoluteUrl());\n      pollUntil(expect, function () {\n        return self.conn.status().connected;\n      }, 10000);\n    },\n\n    function (test, expect) {\n      var self = this;\n      if (self.conn.status().connected) {\n        self.miniC = new Mongo.Collection(\"ServerMinimongoObserve_\" + self.id, {\n          connection: self.conn\n        });\n        var exp = expect(function (err) {\n          test.isFalse(err);\n        });\n        self.conn.subscribe(self.id, {\n          onError: exp,\n          onReady: exp\n        });\n      }\n    },\n\n    function (test, expect) {\n      var self = this;\n      if (self.miniC) {\n        self.obs = self.miniC.find().observeChanges({\n          added: function (id, fields) {\n            self.events.push({evt: \"a\", id: id});\n            Meteor._sleepForMs(200);\n            self.events.push({evt: \"b\", id: id});\n          }\n        });\n        self.one = self.C.insert({});\n        self.two = self.C.insert({});\n        pollUntil(expect, function () {\n          return self.events.length === 4;\n        }, 10000);\n      }\n    },\n\n    function (test, expect) {\n      var self = this;\n      if (self.miniC) {\n        test.equal(self.events, [\n          {evt: \"a\", id: self.one},\n          {evt: \"b\", id: self.one},\n          {evt: \"a\", id: self.two},\n          {evt: \"b\", id: self.two}\n        ]);\n      }\n      self.obs && self.obs.stop();\n    }\n  ]);\n}\n\nTinytest.addAsync(\"mongo-livedata - local collections with different connections\", function (test, onComplete) {\n  var cname = Random.id();\n  var cname2 = Random.id();\n  var coll1 = new Mongo.Collection(cname);\n  var doc = { foo: \"bar\" };\n  var coll2 = new Mongo.Collection(cname2, { connection: null });\n  coll2.insert(doc, function (err, id) {\n    test.equal(coll1.find(doc).count(), 0);\n    test.equal(coll2.find(doc).count(), 1);\n    onComplete();\n  });\n});\n\nTinytest.addAsync(\"mongo-livedata - local collection with null connection, w/ callback\", function (test, onComplete) {\n  var cname = Random.id();\n  var coll1 = new Mongo.Collection(cname, { connection: null });\n  var doc = { foo: \"bar\" };\n  var docId = coll1.insert(doc, function (err, id) {\n    test.equal(docId, id);\n    test.equal(coll1.findOne(doc)._id, id);\n    onComplete();\n  });\n});\n\nTinytest.addAsync(\"mongo-livedata - local collection with null connection, w/o callback\", function (test, onComplete) {\n  var cname = Random.id();\n  var coll1 = new Mongo.Collection(cname, { connection: null });\n  var doc = { foo: \"bar\" };\n  var docId = coll1.insert(doc);\n  test.equal(coll1.findOne(doc)._id, docId);\n  onComplete();\n});\n\ntestAsyncMulti(\"mongo-livedata - update handles $push with $each correctly\", [\n  function (test, expect) {\n    var self = this;\n    var collectionName = Random.id();\n    if (Meteor.isClient) {\n      Meteor.call('createInsecureCollection', collectionName);\n      Meteor.subscribe('c-' + collectionName, expect());\n    }\n\n    self.collection = new Mongo.Collection(collectionName);\n\n    self.id = self.collection.insert(\n      {name: 'jens', elements: ['X', 'Y']}, expect(function (err, res) {\n        test.isFalse(err);\n        test.equal(self.id, res);\n        }));\n  },\n  function (test, expect) {\n    var self = this;\n    self.collection.update(self.id, {\n      $push: {\n        elements: {\n          $each: ['A', 'B', 'C'],\n          $slice: -4\n        }}}, expect(function (err, res) {\n          test.isFalse(err);\n          test.equal(\n            self.collection.findOne(self.id),\n            {_id: self.id, name: 'jens', elements: ['Y', 'A', 'B', 'C']});\n        }));\n  }\n]);\n\nif (Meteor.isServer) {\n  Tinytest.add(\"mongo-livedata - upsert handles $push with $each correctly\", function (test) {\n    var collection = new Mongo.Collection(Random.id());\n\n    var result = collection.upsert(\n      {name: 'jens'},\n      {$push: {\n        elements: {\n          $each: ['A', 'B', 'C'],\n          $slice: -4\n        }}});\n\n    test.equal(collection.findOne(result.insertedId),\n               {_id: result.insertedId,\n                name: 'jens',\n                elements: ['A', 'B', 'C']});\n\n    var id = collection.insert({name: \"david\", elements: ['X', 'Y']});\n    result = collection.upsert(\n      {name: 'david'},\n      {$push: {\n        elements: {\n          $each: ['A', 'B', 'C'],\n          $slice: -4\n        }}});\n\n    test.equal(collection.findOne(id),\n               {_id: id,\n                name: 'david',\n                elements: ['Y', 'A', 'B', 'C']});\n  });\n\n  Tinytest.add(\"mongo-livedata - upsert handles dotted selectors corrrectly\", function (test) {\n    var collection = new Mongo.Collection(Random.id());\n\n    var result1 = collection.upsert({\n      \"subdocument.a\": 1\n    }, {\n      $set: {message: \"upsert 1\"}\n    });\n\n    test.equal(collection.findOne(result1.insertedId),{\n      _id: result1.insertedId,\n      subdocument: {a: 1},\n      message: \"upsert 1\"\n    });\n\n    var result2 = collection.upsert({\n      \"subdocument.a\": 1\n    }, {\n      $set: {message: \"upsert 2\"}\n    });\n\n    test.equal(result2, {numberAffected: 1});\n\n    test.equal(collection.findOne(result1.insertedId),{\n      _id: result1.insertedId,\n      subdocument: {a: 1},\n      message: \"upsert 2\"\n    });\n\n    var result3 = collection.upsert({\n      \"subdocument.a.b\": 1,\n      \"subdocument.c\": 2\n    }, {\n      $set: {message: \"upsert3\"}\n    });\n\n    test.equal(collection.findOne(result3.insertedId),{\n      _id: result3.insertedId,\n      subdocument: {a: {b: 1}, c: 2},\n      message: \"upsert3\"\n    });\n\n    var result4 = collection.upsert({\n      \"subdocument.a\": 4\n    }, {\n      $set: {\"subdocument.a\": \"upsert 4\"}\n    });\n\n    test.equal(collection.findOne(result4.insertedId), {\n      _id: result4.insertedId,\n      subdocument: {a: \"upsert 4\"}\n    });\n\n    var result5 = collection.upsert({\n      \"subdocument.a\": \"upsert 4\"\n    }, {\n      $set: {\"subdocument.a\": \"upsert 5\"}\n    });\n\n    test.equal(result5, {numberAffected: 1});\n\n    test.equal(collection.findOne(result4.insertedId), {\n      _id: result4.insertedId,\n      subdocument: {a: \"upsert 5\"}\n    });\n\n    var result6 = collection.upsert({\n      \"subdocument.a\": \"upsert 5\"\n    }, {\n      $set: {\"subdocument\": \"upsert 6\"}\n    });\n\n    test.equal(result6, {numberAffected: 1});\n\n    test.equal(collection.findOne(result4.insertedId), {\n      _id: result4.insertedId,\n      subdocument: \"upsert 6\"\n    });\n\n    var result7 = collection.upsert({\n      \"subdocument.a.b\": 7\n    }, {\n      $set: {\n        \"subdocument.a.c\": \"upsert7\"\n      }\n    });\n\n    test.equal(collection.findOne(result7.insertedId), {\n      _id: result7.insertedId,\n      subdocument: {\n        a: {b: 7, c: \"upsert7\"}\n      }\n    });\n\n    var result8 = collection.upsert({\n      \"subdocument.a.b\": 7\n    }, {\n      $set: {\n        \"subdocument.a.c\": \"upsert8\"\n      }\n    });\n\n    test.equal(result8, {numberAffected: 1});\n\n    test.equal(collection.findOne(result7.insertedId), {\n      _id: result7.insertedId,\n      subdocument: {\n        a: {b: 7, c: \"upsert8\"}\n      }\n    });\n\n    var result9 = collection.upsert({\n      \"subdocument.a.b\": 7\n    }, {\n      $set: {\n        \"subdocument.a.b\": \"upsert9\"\n      }\n    });\n\n    test.equal(result9, {numberAffected: 1});\n\n    test.equal(collection.findOne(result7.insertedId), {\n      _id: result7.insertedId,\n      subdocument: {\n        a: {b: \"upsert9\", c: \"upsert8\"}\n      }\n    });\n\n  });\n}\n\n// This is a VERY white-box test.\nMeteor.isServer && Tinytest.add(\"mongo-livedata - oplog - _disableOplog\", function (test) {\n  var collName = Random.id();\n  var coll = new Mongo.Collection(collName);\n  if (MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle) {\n    var observeWithOplog = coll.find({x: 5})\n          .observeChanges({added: function () {}});\n    test.isTrue(observeWithOplog._multiplexer._observeDriver._usesOplog);\n    observeWithOplog.stop();\n  }\n  var observeWithoutOplog = coll.find({x: 6}, {_disableOplog: true})\n        .observeChanges({added: function () {}});\n  test.isFalse(observeWithoutOplog._multiplexer._observeDriver._usesOplog);\n  observeWithoutOplog.stop();\n});\n\nMeteor.isServer && Tinytest.add(\"mongo-livedata - oplog - include selector fields\", function (test) {\n  var collName = \"includeSelector\" + Random.id();\n  var coll = new Mongo.Collection(collName);\n\n  var docId = coll.insert({a: 1, b: [3, 2], c: 'foo'});\n  test.isTrue(docId);\n\n  // Wait until we've processed the insert oplog entry. (If the insert shows up\n  // during the observeChanges, the bug in question is not consistently\n  // reproduced.) We don't have to do this for polling observe (eg\n  // --disable-oplog).\n  waitUntilOplogCaughtUp();\n\n  var output = [];\n  var handle = coll.find({a: 1, b: 2}, {fields: {c: 1}}).observeChanges({\n    added: function (id, fields) {\n      output.push(['added', id, fields]);\n    },\n    changed: function (id, fields) {\n      output.push(['changed', id, fields]);\n    },\n    removed: function (id) {\n      output.push(['removed', id]);\n    }\n  });\n  // Initially should match the document.\n  test.length(output, 1);\n  test.equal(output.shift(), ['added', docId, {c: 'foo'}]);\n\n  // Update in such a way that, if we only knew about the published field 'c'\n  // and the changed field 'b' (but not the field 'a'), we would think it didn't\n  // match any more.  (This is a regression test for a bug that existed because\n  // we used to not use the shared projection in the initial query.)\n  runInFence(function () {\n    coll.update(docId, {$set: {'b.0': 2, c: 'bar'}});\n  });\n  test.length(output, 1);\n  test.equal(output.shift(), ['changed', docId, {c: 'bar'}]);\n\n  handle.stop();\n});\n\nMeteor.isServer && Tinytest.add(\"mongo-livedata - oplog - transform\", function (test) {\n  var collName = \"oplogTransform\" + Random.id();\n  var coll = new Mongo.Collection(collName);\n\n  var docId = coll.insert({a: 25, x: {x: 5, y: 9}});\n  test.isTrue(docId);\n\n  // Wait until we've processed the insert oplog entry. (If the insert shows up\n  // during the observeChanges, the bug in question is not consistently\n  // reproduced.) We don't have to do this for polling observe (eg\n  // --disable-oplog).\n  waitUntilOplogCaughtUp();\n\n  var cursor = coll.find({}, {transform: function (doc) {\n    return doc.x;\n  }});\n\n  var changesOutput = [];\n  var changesHandle = cursor.observeChanges({\n    added: function (id, fields) {\n      changesOutput.push(['added', fields]);\n    }\n  });\n  // We should get untransformed fields via observeChanges.\n  test.length(changesOutput, 1);\n  test.equal(changesOutput.shift(), ['added', {a: 25, x: {x: 5, y: 9}}]);\n  changesHandle.stop();\n\n  var transformedOutput = [];\n  var transformedHandle = cursor.observe({\n    added: function (doc) {\n      transformedOutput.push(['added', doc]);\n    }\n  });\n  test.length(transformedOutput, 1);\n  test.equal(transformedOutput.shift(), ['added', {x: 5, y: 9}]);\n  transformedHandle.stop();\n});\n\n\nMeteor.isServer && Tinytest.add(\"mongo-livedata - oplog - drop collection/db\", function (test) {\n  // This test uses a random database, so it can be dropped without affecting\n  // anything else.\n  var mongodbUri = Npm.require('mongodb-uri');\n  var parsedUri = mongodbUri.parse(process.env.MONGO_URL);\n  parsedUri.database = 'dropDB' + Random.id();\n  var driver = new MongoInternals.RemoteCollectionDriver(\n    mongodbUri.format(parsedUri), {\n      oplogUrl: process.env.MONGO_OPLOG_URL\n    }\n  );\n\n  var collName = \"dropCollection\" + Random.id();\n  var coll = new Mongo.Collection(collName, { _driver: driver });\n\n  var doc1Id = coll.insert({a: 'foo', c: 1});\n  var doc2Id = coll.insert({b: 'bar'});\n  var doc3Id = coll.insert({a: 'foo', c: 2});\n  var tmp;\n\n  var output = [];\n  var handle = coll.find({a: 'foo'}).observeChanges({\n    added: function (id, fields) {\n      output.push(['added', id, fields]);\n    },\n    changed: function (id) {\n      output.push(['changed']);\n    },\n    removed: function (id) {\n      output.push(['removed', id]);\n    }\n  });\n  test.length(output, 2);\n  // make order consistent\n  if (output.length === 2 && output[0][1] === doc3Id) {\n    tmp = output[0];\n    output[0] = output[1];\n    output[1] = tmp;\n  }\n  test.equal(output.shift(), ['added', doc1Id, {a: 'foo', c: 1}]);\n  test.equal(output.shift(), ['added', doc3Id, {a: 'foo', c: 2}]);\n\n  // Wait until we've processed the insert oplog entry, so that we are in a\n  // steady state (and we don't see the dropped docs because we are FETCHING).\n  waitUntilOplogCaughtUp();\n\n  // Drop the collection. Should remove all docs.\n  runInFence(function () {\n    coll._dropCollection();\n  });\n\n  test.length(output, 2);\n  // make order consistent\n  if (output.length === 2 && output[0][1] === doc3Id) {\n    tmp = output[0];\n    output[0] = output[1];\n    output[1] = tmp;\n  }\n  test.equal(output.shift(), ['removed', doc1Id]);\n  test.equal(output.shift(), ['removed', doc3Id]);\n\n  // Put something back in.\n  var doc4Id;\n  runInFence(function () {\n    doc4Id = coll.insert({a: 'foo', c: 3});\n  });\n\n  test.length(output, 1);\n  test.equal(output.shift(), ['added', doc4Id, {a: 'foo', c: 3}]);\n\n  // XXX: this was intermittently failing for unknown reasons.\n  // Now drop the database. Should remove all docs again.\n  // runInFence(function () {\n  //   driver.mongo.dropDatabase();\n  // });\n  //\n  // test.length(output, 1);\n  // test.equal(output.shift(), ['removed', doc4Id]);\n\n  handle.stop();\n  driver.mongo.close();\n});\n\nvar TestCustomType = function (head, tail) {\n  // use different field names on the object than in JSON, to ensure we are\n  // actually treating this as an opaque object.\n  this.myHead = head;\n  this.myTail = tail;\n};\n_.extend(TestCustomType.prototype, {\n  clone: function () {\n    return new TestCustomType(this.myHead, this.myTail);\n  },\n  equals: function (other) {\n    return other instanceof TestCustomType\n      && EJSON.equals(this.myHead, other.myHead)\n      && EJSON.equals(this.myTail, other.myTail);\n  },\n  typeName: function () {\n    return 'someCustomType';\n  },\n  toJSONValue: function () {\n    return {head: this.myHead, tail: this.myTail};\n  }\n});\n\nEJSON.addType('someCustomType', function (json) {\n  return new TestCustomType(json.head, json.tail);\n});\n\ntestAsyncMulti(\"mongo-livedata - oplog - update EJSON\", [\n  function (test, expect) {\n    var self = this;\n    var collectionName = \"ejson\" + Random.id();\n    if (Meteor.isClient) {\n      Meteor.call('createInsecureCollection', collectionName);\n      Meteor.subscribe('c-' + collectionName, expect());\n    }\n\n    self.collection = new Mongo.Collection(collectionName);\n    self.date = new Date;\n    self.objId = new Mongo.ObjectID;\n\n    self.id = self.collection.insert(\n      {d: self.date, oi: self.objId,\n       custom: new TestCustomType('a', 'b')},\n      expect(function (err, res) {\n        test.isFalse(err);\n        test.equal(self.id, res);\n      }));\n  },\n  function (test, expect) {\n    var self = this;\n    self.changes = [];\n    self.handle = self.collection.find({}).observeChanges({\n      added: function (id, fields) {\n        self.changes.push(['a', id, fields]);\n      },\n      changed: function (id, fields) {\n        self.changes.push(['c', id, fields]);\n      },\n      removed: function (id) {\n        self.changes.push(['r', id]);\n      }\n    });\n    test.length(self.changes, 1);\n    test.equal(self.changes.shift(),\n               ['a', self.id,\n                {d: self.date, oi: self.objId,\n                 custom: new TestCustomType('a', 'b')}]);\n\n    // First, replace the entire custom object.\n    // (runInFence is useful for the server, using expect() is useful for the\n    // client)\n    runInFence(function () {\n      self.collection.update(\n        self.id, {$set: {custom: new TestCustomType('a', 'c')}},\n        expect(function (err) {\n          test.isFalse(err);\n        }));\n    });\n  },\n  function (test, expect) {\n    var self = this;\n    test.length(self.changes, 1);\n    test.equal(self.changes.shift(),\n               ['c', self.id, {custom: new TestCustomType('a', 'c')}]);\n\n    // Now, sneakily replace just a piece of it. Meteor won't do this, but\n    // perhaps you are accessing Mongo directly.\n    runInFence(function () {\n      self.collection.update(\n        self.id, {$set: {'custom.EJSON$value.EJSONtail': 'd'}},\n      expect(function (err) {\n        test.isFalse(err);\n      }));\n    });\n  },\n  function (test, expect) {\n    var self = this;\n    test.length(self.changes, 1);\n    test.equal(self.changes.shift(),\n               ['c', self.id, {custom: new TestCustomType('a', 'd')}]);\n\n    // Update a date and an ObjectID too.\n    self.date2 = new Date(self.date.valueOf() + 1000);\n    self.objId2 = new Mongo.ObjectID;\n    runInFence(function () {\n      self.collection.update(\n        self.id, {$set: {d: self.date2, oi: self.objId2}},\n      expect(function (err) {\n        test.isFalse(err);\n      }));\n    });\n  },\n  function (test, expect) {\n    var self = this;\n    test.length(self.changes, 1);\n    test.equal(self.changes.shift(),\n               ['c', self.id, {d: self.date2, oi: self.objId2}]);\n\n    self.handle.stop();\n  }\n]);\n\n\nvar waitUntilOplogCaughtUp = function () {\n  var oplogHandle =\n        MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle;\n  if (oplogHandle)\n    oplogHandle.waitUntilCaughtUp();\n};\n\n\nMeteor.isServer && Tinytest.add(\"mongo-livedata - cursor dedup stop\", function (test) {\n  var coll = new Mongo.Collection(Random.id());\n  _.times(100, function () {\n    coll.insert({foo: 'baz'});\n  });\n  var handler = coll.find({}).observeChanges({\n    added: function (id) {\n      coll.update(id, {$set: {foo: 'bar'}});\n    }\n  });\n  handler.stop();\n  // Previously, this would print\n  //    Exception in queued task: TypeError: Object.keys called on non-object\n  // Unfortunately, this test didn't fail before the bugfix, but it at least\n  // would print the error and no longer does.\n  // See https://github.com/meteor/meteor/issues/2070\n});\n\ntestAsyncMulti(\"mongo-livedata - undefined find options\", [\n  function (test, expect) {\n    var self = this;\n    self.collName = Random.id();\n    if (Meteor.isClient) {\n      Meteor.call(\"createInsecureCollection\", self.collName);\n      Meteor.subscribe(\"c-\" + self.collName, expect());\n    }\n  },\n  function (test, expect) {\n    var self = this;\n    self.coll = new Mongo.Collection(self.collName);\n    self.doc = { foo: 1, bar: 2, _id: \"foobar\" };\n    self.coll.insert(self.doc, expect(function (err, id) {\n      test.isFalse(err);\n    }));\n  },\n  function (test, expect) {\n    var self = this;\n    var result = self.coll.findOne({ foo: 1 }, {\n      fields: undefined,\n      sort: undefined,\n      limit: undefined,\n      skip: undefined\n    });\n    test.equal(result, self.doc);\n  }\n]);\n\n// Regression test for #2274.\nMeteor.isServer && testAsyncMulti(\"mongo-livedata - observe limit bug\", [\n  function (test, expect) {\n    var self = this;\n    self.coll = new Mongo.Collection(Random.id());\n    var state = {};\n    var callbacks = {\n      changed: function (newDoc) {\n        state[newDoc._id] = newDoc;\n      },\n      added: function (newDoc) {\n        state[newDoc._id] = newDoc;\n      },\n      removed: function (oldDoc) {\n        delete state[oldDoc._id];\n      }\n    };\n    self.observe = self.coll.find(\n      {}, {limit: 1, sort: {sortField: -1}}).observe(callbacks);\n\n    // Insert some documents.\n    runInFence(function () {\n      self.id0 = self.coll.insert({sortField: 0, toDelete: true});\n      self.id1 = self.coll.insert({sortField: 1, toDelete: true});\n      self.id2 = self.coll.insert({sortField: 2, toDelete: true});\n    });\n    test.equal(_.keys(state), [self.id2]);\n\n    // Mutate the one in the unpublished buffer and the one below the\n    // buffer. Before the fix for #2274, this left the observe state machine in\n    // a broken state where the buffer was empty but it wasn't try to re-fill\n    // it.\n    runInFence(function () {\n      self.coll.update({_id: {$ne: self.id2}},\n                       {$set: {toDelete: false}},\n                       {multi: 1});\n    });\n    test.equal(_.keys(state), [self.id2]);\n\n    // Now remove the one published document. This should slide up id1 from the\n    // buffer, but this didn't work before the #2274 fix.\n    runInFence(function () {\n      self.coll.remove({toDelete: true});\n    });\n    test.equal(_.keys(state), [self.id1]);\n  }\n]);\n\nMeteor.isServer && testAsyncMulti(\"mongo-livedata - update with replace forbidden\", [\n  function (test, expect) {\n    var c = new Mongo.Collection(Random.id());\n\n    var id = c.insert({ foo: \"bar\" });\n\n    c.update(id, { foo2: \"bar2\" });\n    test.equal(c.findOne(id), { _id: id, foo2: \"bar2\" });\n\n    test.throws(function () {\n      c.update(id, { foo3: \"bar3\" }, { _forbidReplace: true });\n    }, \"Replacements are forbidden\");\n    test.equal(c.findOne(id), { _id: id, foo2: \"bar2\" });\n\n    test.throws(function () {\n      c.update(id, { foo3: \"bar3\", $set: { blah: 1 } });\n    }, \"cannot have both modifier and non-modifier fields\");\n    test.equal(c.findOne(id), { _id: id, foo2: \"bar2\" });\n  }\n]);\n\nMeteor.isServer && Tinytest.add(\n  \"mongo-livedata - connection failure throws\",\n  function (test) {\n    test.throws(function () {\n      new MongoInternals.Connection('mongodb://this-does-not-exist.test/asdf');\n    });\n  }\n);\n\nMeteor.isServer && Tinytest.add(\"mongo-livedata - npm modules\", function (test) {\n  // Make sure the version number looks like a version number.\n  test.matches(MongoInternals.NpmModules.mongodb.version, /^1\\.(\\d+)\\.(\\d+)/);\n  test.equal(typeof(MongoInternals.NpmModules.mongodb.module), 'function');\n  test.equal(typeof(MongoInternals.NpmModules.mongodb.module.connect),\n             'function');\n  test.equal(typeof(MongoInternals.NpmModules.mongodb.module.ObjectID),\n             'function');\n\n  var c = new Mongo.Collection(Random.id());\n  var rawCollection = c.rawCollection();\n  test.isTrue(rawCollection);\n  test.isTrue(rawCollection.findAndModify);\n  var rawDb = c.rawDatabase();\n  test.isTrue(rawDb);\n  test.isTrue(rawDb.admin);\n});\n\nif (Meteor.isServer) {\n  Tinytest.add(\"mongo-livedata - update/remove don't accept an array as a selector #4804\", function (test) {\n    var collection = new Mongo.Collection(Random.id());\n\n    _.times(10, function () {\n      collection.insert({ data: \"Hello\" });\n    });\n\n    test.equal(collection.find().count(), 10);\n\n    // Test several array-related selectors\n    _.each([[], [1, 2, 3], [{}]], function (selector) {\n      test.throws(function () {\n        collection.remove(selector);\n      });\n\n      test.throws(function () {\n        collection.update(selector, {$set: 5});\n      });\n    });\n\n    test.equal(collection.find().count(), 10);\n  });\n}\n\n// This is a regression test for https://github.com/meteor/meteor/issues/4839.\n// Prior to fixing the issue (but after applying\n// https://github.com/meteor/meteor/pull/4694), doing a Mongo write from a\n// timeout that ran after a method body (invoked via the client) would throw an\n// error \"fence has already activated -- too late to add a callback\" and not\n// properly call the Mongo write's callback.  In this test:\n//  - The client invokes a method (fenceOnBeforeFireError1) which\n//    - Starts an observe on a query\n//    - Creates a timeout (which shares a write fence with the method)\n//    - Lets the method return (firing the write fence)\n//  - The timeout runs and does a Mongo write. This write is inside a write\n//    fence (because timeouts preserve the fence, see dcd26415) but the write\n//    fence already fired.\n//  - The Mongo write's callback confirms that there is no error. This was\n//    not the case before fixing the bug!  (Note that the observe was necessary\n//    for the error to occur, because the error was thrown from the observe's\n//    crossbar listener callback).  It puts the confirmation into a Future.\n//  - The client invokes another method which reads the confirmation from\n//    the future. (Well, the invocation happened earlier but the use of the\n//    Future sequences it so that the confirmation only gets read at this point.)\nif (Meteor.isClient) {\n  testAsyncMulti(\"mongo-livedata - fence onBeforeFire error\", [\n    function (test, expect) {\n      var self = this;\n      self.nonce = Random.id();\n      Meteor.call('fenceOnBeforeFireError1', self.nonce, expect(function (err) {\n        test.isFalse(err);\n      }));\n    },\n    function (test, expect) {\n      var self = this;\n      Meteor.call('fenceOnBeforeFireError2', self.nonce, expect(\n        function (err, success) {\n          test.isFalse(err);\n          test.isTrue(success);\n        }\n      ));\n    }\n  ]);\n} else {\n  var fenceOnBeforeFireErrorCollection = new Mongo.Collection(\"FOBFE\");\n  var Future = Npm.require('fibers/future');\n  var futuresByNonce = {};\n  Meteor.methods({\n    fenceOnBeforeFireError1: function (nonce) {\n      futuresByNonce[nonce] = new Future;\n      var observe = fenceOnBeforeFireErrorCollection.find({nonce: nonce})\n            .observeChanges({added: function (){}});\n      Meteor.setTimeout(function () {\n        fenceOnBeforeFireErrorCollection.insert(\n          {nonce: nonce},\n          function (err, result) {\n            var success = !err && result;\n            futuresByNonce[nonce].return(success);\n            observe.stop();\n          }\n        );\n      }, 10);\n    },\n    fenceOnBeforeFireError2: function (nonce) {\n      try {\n        return futuresByNonce[nonce].wait();\n      } finally {\n        delete futuresByNonce[nonce];\n      }\n    }\n  });\n}\n"
  },
  {
    "path": "packages/mongo/observe_changes_tests.js",
    "content": "var makeCollection = function () {\n  if (Meteor.isServer)\n    return new Mongo.Collection(Random.id());\n  else\n    return new Mongo.Collection(null);\n};\n\n_.each ([{added:'added', forceOrdered: true},\n         {added:'added', forceOrdered: false},\n         {added: 'addedBefore', forceOrdered: false}], function (options) {\n           var added = options.added;\n           var forceOrdered = options.forceOrdered;\n  Tinytest.addAsync(\"observeChanges - single id - basics \"\n                    + added\n                    + (forceOrdered ? \" force ordered\" : \"\"),\n                    function (test, onComplete) {\n    var c = makeCollection();\n    var counter = 0;\n    var callbacks = [added, \"changed\", \"removed\"];\n    if (forceOrdered)\n      callbacks.push(\"movedBefore\");\n    withCallbackLogger(test,\n                       callbacks,\n                       Meteor.isServer,\n                       function (logger) {\n    var barid = c.insert({thing: \"stuff\"});\n    var fooid = c.insert({noodles: \"good\", bacon: \"bad\", apples: \"ok\"});\n\n    var handle = c.find(fooid).observeChanges(logger);\n    if (added === 'added')\n      logger.expectResult(added, [fooid, {noodles: \"good\", bacon: \"bad\",apples: \"ok\"}]);\n    else\n      logger.expectResult(added,\n                          [fooid, {noodles: \"good\", bacon: \"bad\", apples: \"ok\"}, null]);\n    c.update(fooid, {noodles: \"alright\", potatoes: \"tasty\", apples: \"ok\"});\n    logger.expectResult(\"changed\",\n                        [fooid, {noodles: \"alright\", potatoes: \"tasty\", bacon: undefined}]);\n\n    c.remove(fooid);\n    logger.expectResult(\"removed\", [fooid]);\n\n    c.remove(barid);\n\n    c.insert({noodles: \"good\", bacon: \"bad\", apples: \"ok\"});\n    logger.expectNoResult();\n    handle.stop();\n\n    var badCursor = c.find({}, {fields: {noodles: 1, _id: false}});\n    test.throws(function () {\n      badCursor.observeChanges(logger);\n    });\n\n    onComplete();\n    });\n  });\n});\n\nTinytest.addAsync(\"observeChanges - callback isolation\", function (test, onComplete) {\n  var c = makeCollection();\n  withCallbackLogger(test, [\"added\", \"changed\", \"removed\"], Meteor.isServer, function (logger) {\n    var handles = [];\n    var cursor = c.find();\n    handles.push(cursor.observeChanges(logger));\n    // fields-tampering observer\n    handles.push(cursor.observeChanges({\n      added: function(id, fields) {\n        fields.apples = 'green';\n      },\n      changed: function(id, fields) {\n        fields.apples = 'green';\n      },\n    }));\n\n    var fooid = c.insert({apples: \"ok\"});\n    logger.expectResult(\"added\", [fooid, {apples: \"ok\"}]);\n\n    c.update(fooid, {apples: \"not ok\"})\n    logger.expectResult(\"changed\", [fooid, {apples: \"not ok\"}]);\n\n    test.equal(c.findOne(fooid).apples, \"not ok\");\n\n    _.each(handles, function(handle) { handle.stop(); });\n    onComplete();\n  });\n\n});\n\nTinytest.addAsync(\"observeChanges - single id - initial adds\", function (test, onComplete) {\n  var c = makeCollection();\n  withCallbackLogger(test, [\"added\", \"changed\", \"removed\"], Meteor.isServer, function (logger) {\n  var fooid = c.insert({noodles: \"good\", bacon: \"bad\", apples: \"ok\"});\n  var handle = c.find(fooid).observeChanges(logger);\n  logger.expectResult(\"added\", [fooid, {noodles: \"good\", bacon: \"bad\", apples: \"ok\"}]);\n  logger.expectNoResult();\n  handle.stop();\n  onComplete();\n  });\n});\n\n\n\nTinytest.addAsync(\"observeChanges - unordered - initial adds\", function (test, onComplete) {\n  var c = makeCollection();\n  withCallbackLogger(test, [\"added\", \"changed\", \"removed\"], Meteor.isServer, function (logger) {\n  var fooid = c.insert({noodles: \"good\", bacon: \"bad\", apples: \"ok\"});\n  var barid = c.insert({noodles: \"good\", bacon: \"weird\", apples: \"ok\"});\n  var handle = c.find().observeChanges(logger);\n  logger.expectResultUnordered([\n    {callback: \"added\",\n     args: [fooid, {noodles: \"good\", bacon: \"bad\", apples: \"ok\"}]},\n    {callback: \"added\",\n     args: [barid, {noodles: \"good\", bacon: \"weird\", apples: \"ok\"}]}\n  ]);\n  logger.expectNoResult();\n  handle.stop();\n  onComplete();\n  });\n});\n\nTinytest.addAsync(\"observeChanges - unordered - basics\", function (test, onComplete) {\n  var c = makeCollection();\n  withCallbackLogger(test, [\"added\", \"changed\", \"removed\"], Meteor.isServer, function (logger) {\n  var handle = c.find().observeChanges(logger);\n  var barid = c.insert({thing: \"stuff\"});\n  logger.expectResultOnly(\"added\", [barid, {thing: \"stuff\"}]);\n\n  var fooid = c.insert({noodles: \"good\", bacon: \"bad\", apples: \"ok\"});\n\n  logger.expectResultOnly(\"added\", [fooid, {noodles: \"good\", bacon: \"bad\", apples: \"ok\"}]);\n\n  c.update(fooid, {noodles: \"alright\", potatoes: \"tasty\", apples: \"ok\"});\n  c.update(fooid, {noodles: \"alright\", potatoes: \"tasty\", apples: \"ok\"});\n  logger.expectResultOnly(\"changed\",\n                      [fooid, {noodles: \"alright\", potatoes: \"tasty\", bacon: undefined}]);\n  c.remove(fooid);\n  logger.expectResultOnly(\"removed\", [fooid]);\n  c.remove(barid);\n  logger.expectResultOnly(\"removed\", [barid]);\n\n  fooid = c.insert({noodles: \"good\", bacon: \"bad\", apples: \"ok\"});\n\n  logger.expectResult(\"added\", [fooid, {noodles: \"good\", bacon: \"bad\", apples: \"ok\"}]);\n  logger.expectNoResult();\n  handle.stop();\n  onComplete();\n  });\n});\n\nif (Meteor.isServer) {\n  Tinytest.addAsync(\"observeChanges - unordered - specific fields\", function (test, onComplete) {\n    var c = makeCollection();\n    withCallbackLogger(test, [\"added\", \"changed\", \"removed\"], Meteor.isServer, function (logger) {\n      var handle = c.find({}, {fields:{noodles: 1, bacon: 1}}).observeChanges(logger);\n      var barid = c.insert({thing: \"stuff\"});\n      logger.expectResultOnly(\"added\", [barid, {}]);\n\n      var fooid = c.insert({noodles: \"good\", bacon: \"bad\", apples: \"ok\"});\n\n      logger.expectResultOnly(\"added\", [fooid, {noodles: \"good\", bacon: \"bad\"}]);\n\n      c.update(fooid, {noodles: \"alright\", potatoes: \"tasty\", apples: \"ok\"});\n      logger.expectResultOnly(\"changed\",\n                              [fooid, {noodles: \"alright\", bacon: undefined}]);\n      c.update(fooid, {noodles: \"alright\", potatoes: \"meh\", apples: \"ok\"});\n      c.remove(fooid);\n      logger.expectResultOnly(\"removed\", [fooid]);\n      c.remove(barid);\n      logger.expectResultOnly(\"removed\", [barid]);\n\n      fooid = c.insert({noodles: \"good\", bacon: \"bad\"});\n\n      logger.expectResult(\"added\", [fooid, {noodles: \"good\", bacon: \"bad\"}]);\n      logger.expectNoResult();\n      handle.stop();\n      onComplete();\n    });\n  });\n\n  Tinytest.addAsync(\"observeChanges - unordered - specific fields + selector on excluded fields\", function (test, onComplete) {\n    var c = makeCollection();\n    withCallbackLogger(test, [\"added\", \"changed\", \"removed\"], Meteor.isServer, function (logger) {\n      var handle = c.find({ mac: 1, cheese: 2 },\n                          {fields:{noodles: 1, bacon: 1, eggs: 1}}).observeChanges(logger);\n      var barid = c.insert({thing: \"stuff\", mac: 1, cheese: 2});\n      logger.expectResultOnly(\"added\", [barid, {}]);\n\n      var fooid = c.insert({noodles: \"good\", bacon: \"bad\", apples: \"ok\", mac: 1, cheese: 2});\n\n      logger.expectResultOnly(\"added\", [fooid, {noodles: \"good\", bacon: \"bad\"}]);\n\n      c.update(fooid, {noodles: \"alright\", potatoes: \"tasty\", apples: \"ok\", mac: 1, cheese: 2});\n      logger.expectResultOnly(\"changed\",\n                              [fooid, {noodles: \"alright\", bacon: undefined}]);\n\n      // Doesn't get update event, since modifies only hidden fields\n      c.update(fooid, {noodles: \"alright\", potatoes: \"meh\", apples: \"ok\", mac: 1, cheese: 2});\n      logger.expectNoResult();\n\n      c.remove(fooid);\n      logger.expectResultOnly(\"removed\", [fooid]);\n      c.remove(barid);\n      logger.expectResultOnly(\"removed\", [barid]);\n\n      fooid = c.insert({noodles: \"good\", bacon: \"bad\", mac: 1, cheese: 2});\n\n      logger.expectResult(\"added\", [fooid, {noodles: \"good\", bacon: \"bad\"}]);\n      logger.expectNoResult();\n      handle.stop();\n      onComplete();\n    });\n  });\n}\n\nTinytest.addAsync(\"observeChanges - unordered - specific fields + modify on excluded fields\", function (test, onComplete) {\n  var c = makeCollection();\n  withCallbackLogger(test, [\"added\", \"changed\", \"removed\"], Meteor.isServer, function (logger) {\n    var handle = c.find({ mac: 1, cheese: 2 },\n                        {fields:{noodles: 1, bacon: 1, eggs: 1}}).observeChanges(logger);\n    var fooid = c.insert({noodles: \"good\", bacon: \"bad\", apples: \"ok\", mac: 1, cheese: 2});\n\n    logger.expectResultOnly(\"added\", [fooid, {noodles: \"good\", bacon: \"bad\"}]);\n\n\n    // Noodles go into shadow, mac appears as eggs\n    c.update(fooid, {$rename: { noodles: 'shadow', apples: 'eggs' }});\n    logger.expectResultOnly(\"changed\",\n                            [fooid, {eggs:\"ok\", noodles: undefined}]);\n\n    c.remove(fooid);\n    logger.expectResultOnly(\"removed\", [fooid]);\n    logger.expectNoResult();\n    handle.stop();\n    onComplete();\n  });\n});\n\nTinytest.addAsync(\n  \"observeChanges - unordered - unset parent of observed field\",\n  function (test, onComplete) {\n    var c = makeCollection();\n    withCallbackLogger(\n      test, ['added', 'changed', 'removed'], Meteor.isServer,\n      function (logger) {\n        var handle = c.find({}, {fields: {'type.name': 1}}).observeChanges(logger);\n        var id = c.insert({ type: { name: 'foobar' } });\n        logger.expectResultOnly('added', [id, { type: { name: 'foobar' } }]);\n\n        c.update(id, { $unset: { type: 1 } });\n        test.equal(c.find().fetch(), [{ _id: id }]);\n        logger.expectResultOnly('changed', [id, { type: undefined }]);\n\n        handle.stop();\n        onComplete();\n      }\n    );\n  }\n);\n\n\n\nTinytest.addAsync(\"observeChanges - unordered - enters and exits result set through change\", function (test, onComplete) {\n  var c = makeCollection();\n  withCallbackLogger(test, [\"added\", \"changed\", \"removed\"], Meteor.isServer, function (logger) {\n  var handle = c.find({noodles: \"good\"}).observeChanges(logger);\n  var barid = c.insert({thing: \"stuff\"});\n\n  var fooid = c.insert({noodles: \"good\", bacon: \"bad\", apples: \"ok\"});\n  logger.expectResultOnly(\"added\", [fooid, {noodles: \"good\", bacon: \"bad\", apples: \"ok\"}]);\n\n  c.update(fooid, {noodles: \"alright\", potatoes: \"tasty\", apples: \"ok\"});\n  logger.expectResultOnly(\"removed\",\n                      [fooid]);\n  c.remove(fooid);\n  c.remove(barid);\n\n  fooid = c.insert({noodles: \"ok\", bacon: \"bad\", apples: \"ok\"});\n  c.update(fooid, {noodles: \"good\", potatoes: \"tasty\", apples: \"ok\"});\n  logger.expectResult(\"added\", [fooid, {noodles: \"good\", potatoes: \"tasty\", apples: \"ok\"}]);\n  logger.expectNoResult();\n  handle.stop();\n  onComplete();\n  });\n});\n\n\nif (Meteor.isServer) {\n  testAsyncMulti(\"observeChanges - tailable\", [\n    function (test, expect) {\n      var self = this;\n      var collName = \"cap_\" + Random.id();\n      var coll = new Mongo.Collection(collName);\n      coll._createCappedCollection(1000000);\n      self.xs = [];\n      self.expects = [];\n      self.insert = function (fields) {\n        coll.insert(_.extend({ts: new MongoInternals.MongoTimestamp(0, 0)},\n                             fields));\n      };\n\n      // Tailable observe shouldn't show things that are in the initial\n      // contents.\n      self.insert({x: 1});\n      // Wait for one added call before going to the next test function.\n      self.expects.push(expect());\n\n      var cursor = coll.find({y: {$ne: 7}}, {tailable: true});\n      self.handle = cursor.observeChanges({\n        added: function (id, fields) {\n          self.xs.push(fields.x);\n          test.notEqual(self.expects.length, 0);\n          self.expects.pop()();\n        },\n        changed: function () {\n          test.fail({unexpected: \"changed\"});\n        },\n        removed: function () {\n          test.fail({unexpected: \"removed\"});\n        }\n      });\n\n      // Nothing happens synchronously.\n      test.equal(self.xs, []);\n    },\n    function (test, expect) {\n      var self = this;\n      // The cursors sees the first element.\n      test.equal(self.xs, [1]);\n      self.xs = [];\n\n      self.insert({x: 2, y: 3});\n      self.insert({x: 3, y: 7});  // filtered out by the query\n      self.insert({x: 4});\n      // Expect two added calls to happen.\n      self.expects = [expect(), expect()];\n    },\n    function (test, expect) {\n      var self = this;\n      test.equal(self.xs, [2, 4]);\n      self.xs = [];\n      self.handle.stop();\n\n      self.insert({x: 5});\n      // XXX This timeout isn't perfect but it's pretty hard to prove that an\n      // event WON'T happen without something like a write fence.\n      Meteor.setTimeout(expect(), 1000);\n    },\n    function (test, expect) {\n      var self = this;\n      test.equal(self.xs, []);\n    }\n  ]);\n}\n\n\ntestAsyncMulti(\"observeChanges - bad query\", [\n  function (test, expect) {\n    var c = makeCollection();\n    var observeThrows = function () {\n      test.throws(function () {\n        c.find({__id: {$in: null}}).observeChanges({\n          added: function () {\n            test.fail(\"added shouldn't be called\");\n          }\n        });\n      }, '$in needs an array');\n    };\n\n    if (Meteor.isClient) {\n      observeThrows();\n      return;\n    }\n\n    // Test that if two copies of the same bad observeChanges run in parallel\n    // and are de-duped, both observeChanges calls will throw.\n    var Fiber = Npm.require('fibers');\n    var Future = Npm.require('fibers/future');\n    var f1 = new Future;\n    var f2 = new Future;\n    Fiber(function () {\n      // The observeChanges call in here will yield when we talk to mongod,\n      // which will allow the second Fiber to start and observe a duplicate\n      // query.\n      observeThrows();\n      f1['return']();\n    }).run();\n    Fiber(function () {\n      test.isFalse(f1.isResolved());  // first observe hasn't thrown yet\n      observeThrows();\n      f2['return']();\n    }).run();\n    f1.wait();\n    f2.wait();\n  }\n]);\n"
  },
  {
    "path": "packages/mongo/observe_multiplex.js",
    "content": "var Future = Npm.require('fibers/future');\n\nObserveMultiplexer = function (options) {\n  var self = this;\n\n  if (!options || !_.has(options, 'ordered'))\n    throw Error(\"must specified ordered\");\n\n  Package.facts && Package.facts.Facts.incrementServerFact(\n    \"mongo-livedata\", \"observe-multiplexers\", 1);\n\n  self._ordered = options.ordered;\n  self._onStop = options.onStop || function () {};\n  self._queue = new Meteor._SynchronousQueue();\n  self._handles = {};\n  self._readyFuture = new Future;\n  self._cache = new LocalCollection._CachingChangeObserver({\n    ordered: options.ordered});\n  // Number of addHandleAndSendInitialAdds tasks scheduled but not yet\n  // running. removeHandle uses this to know if it's time to call the onStop\n  // callback.\n  self._addHandleTasksScheduledButNotPerformed = 0;\n\n  _.each(self.callbackNames(), function (callbackName) {\n    self[callbackName] = function (/* ... */) {\n      self._applyCallback(callbackName, _.toArray(arguments));\n    };\n  });\n};\n\n_.extend(ObserveMultiplexer.prototype, {\n  addHandleAndSendInitialAdds: function (handle) {\n    var self = this;\n\n    // Check this before calling runTask (even though runTask does the same\n    // check) so that we don't leak an ObserveMultiplexer on error by\n    // incrementing _addHandleTasksScheduledButNotPerformed and never\n    // decrementing it.\n    if (!self._queue.safeToRunTask())\n      throw new Error(\n        \"Can't call observeChanges from an observe callback on the same query\");\n    ++self._addHandleTasksScheduledButNotPerformed;\n\n    Package.facts && Package.facts.Facts.incrementServerFact(\n      \"mongo-livedata\", \"observe-handles\", 1);\n\n    self._queue.runTask(function () {\n      self._handles[handle._id] = handle;\n      // Send out whatever adds we have so far (whether or not we the\n      // multiplexer is ready).\n      self._sendAdds(handle);\n      --self._addHandleTasksScheduledButNotPerformed;\n    });\n    // *outside* the task, since otherwise we'd deadlock\n    self._readyFuture.wait();\n  },\n\n  // Remove an observe handle. If it was the last observe handle, call the\n  // onStop callback; you cannot add any more observe handles after this.\n  //\n  // This is not synchronized with polls and handle additions: this means that\n  // you can safely call it from within an observe callback, but it also means\n  // that we have to be careful when we iterate over _handles.\n  removeHandle: function (id) {\n    var self = this;\n\n    // This should not be possible: you can only call removeHandle by having\n    // access to the ObserveHandle, which isn't returned to user code until the\n    // multiplex is ready.\n    if (!self._ready())\n      throw new Error(\"Can't remove handles until the multiplex is ready\");\n\n    delete self._handles[id];\n\n    Package.facts && Package.facts.Facts.incrementServerFact(\n      \"mongo-livedata\", \"observe-handles\", -1);\n\n    if (_.isEmpty(self._handles) &&\n        self._addHandleTasksScheduledButNotPerformed === 0) {\n      self._stop();\n    }\n  },\n  _stop: function (options) {\n    var self = this;\n    options = options || {};\n\n    // It shouldn't be possible for us to stop when all our handles still\n    // haven't been returned from observeChanges!\n    if (! self._ready() && ! options.fromQueryError)\n      throw Error(\"surprising _stop: not ready\");\n\n    // Call stop callback (which kills the underlying process which sends us\n    // callbacks and removes us from the connection's dictionary).\n    self._onStop();\n    Package.facts && Package.facts.Facts.incrementServerFact(\n      \"mongo-livedata\", \"observe-multiplexers\", -1);\n\n    // Cause future addHandleAndSendInitialAdds calls to throw (but the onStop\n    // callback should make our connection forget about us).\n    self._handles = null;\n  },\n\n  // Allows all addHandleAndSendInitialAdds calls to return, once all preceding\n  // adds have been processed. Does not block.\n  ready: function () {\n    var self = this;\n    self._queue.queueTask(function () {\n      if (self._ready())\n        throw Error(\"can't make ObserveMultiplex ready twice!\");\n      self._readyFuture.return();\n    });\n  },\n\n  // If trying to execute the query results in an error, call this. This is\n  // intended for permanent errors, not transient network errors that could be\n  // fixed. It should only be called before ready(), because if you called ready\n  // that meant that you managed to run the query once. It will stop this\n  // ObserveMultiplex and cause addHandleAndSendInitialAdds calls (and thus\n  // observeChanges calls) to throw the error.\n  queryError: function (err) {\n    var self = this;\n    self._queue.runTask(function () {\n      if (self._ready())\n        throw Error(\"can't claim query has an error after it worked!\");\n      self._stop({fromQueryError: true});\n      self._readyFuture.throw(err);\n    });\n  },\n\n  // Calls \"cb\" once the effects of all \"ready\", \"addHandleAndSendInitialAdds\"\n  // and observe callbacks which came before this call have been propagated to\n  // all handles. \"ready\" must have already been called on this multiplexer.\n  onFlush: function (cb) {\n    var self = this;\n    self._queue.queueTask(function () {\n      if (!self._ready())\n        throw Error(\"only call onFlush on a multiplexer that will be ready\");\n      cb();\n    });\n  },\n  callbackNames: function () {\n    var self = this;\n    if (self._ordered)\n      return [\"addedBefore\", \"changed\", \"movedBefore\", \"removed\"];\n    else\n      return [\"added\", \"changed\", \"removed\"];\n  },\n  _ready: function () {\n    return this._readyFuture.isResolved();\n  },\n  _applyCallback: function (callbackName, args) {\n    var self = this;\n    self._queue.queueTask(function () {\n      // If we stopped in the meantime, do nothing.\n      if (!self._handles)\n        return;\n\n      // First, apply the change to the cache.\n      // XXX We could make applyChange callbacks promise not to hang on to any\n      // state from their arguments (assuming that their supplied callbacks\n      // don't) and skip this clone. Currently 'changed' hangs on to state\n      // though.\n      self._cache.applyChange[callbackName].apply(null, EJSON.clone(args));\n\n      // If we haven't finished the initial adds, then we should only be getting\n      // adds.\n      if (!self._ready() &&\n          (callbackName !== 'added' && callbackName !== 'addedBefore')) {\n        throw new Error(\"Got \" + callbackName + \" during initial adds\");\n      }\n\n      // Now multiplex the callbacks out to all observe handles. It's OK if\n      // these calls yield; since we're inside a task, no other use of our queue\n      // can continue until these are done. (But we do have to be careful to not\n      // use a handle that got removed, because removeHandle does not use the\n      // queue; thus, we iterate over an array of keys that we control.)\n      _.each(_.keys(self._handles), function (handleId) {\n        var handle = self._handles && self._handles[handleId];\n        if (!handle)\n          return;\n        var callback = handle['_' + callbackName];\n        // clone arguments so that callbacks can mutate their arguments\n        callback && callback.apply(null, EJSON.clone(args));\n      });\n    });\n  },\n\n  // Sends initial adds to a handle. It should only be called from within a task\n  // (the task that is processing the addHandleAndSendInitialAdds call). It\n  // synchronously invokes the handle's added or addedBefore; there's no need to\n  // flush the queue afterwards to ensure that the callbacks get out.\n  _sendAdds: function (handle) {\n    var self = this;\n    if (self._queue.safeToRunTask())\n      throw Error(\"_sendAdds may only be called from within a task!\");\n    var add = self._ordered ? handle._addedBefore : handle._added;\n    if (!add)\n      return;\n    // note: docs may be an _IdMap or an OrderedDict\n    self._cache.docs.forEach(function (doc, id) {\n      if (!_.has(self._handles, handle._id))\n        throw Error(\"handle got removed before sending initial adds!\");\n      var fields = EJSON.clone(doc);\n      delete fields._id;\n      if (self._ordered)\n        add(id, fields, null); // we're going in order, so add at end\n      else\n        add(id, fields);\n    });\n  }\n});\n\n\nvar nextObserveHandleId = 1;\nObserveHandle = function (multiplexer, callbacks) {\n  var self = this;\n  // The end user is only supposed to call stop().  The other fields are\n  // accessible to the multiplexer, though.\n  self._multiplexer = multiplexer;\n  _.each(multiplexer.callbackNames(), function (name) {\n    if (callbacks[name]) {\n      self['_' + name] = callbacks[name];\n    } else if (name === \"addedBefore\" && callbacks.added) {\n      // Special case: if you specify \"added\" and \"movedBefore\", you get an\n      // ordered observe where for some reason you don't get ordering data on\n      // the adds.  I dunno, we wrote tests for it, there must have been a\n      // reason.\n      self._addedBefore = function (id, fields, before) {\n        callbacks.added(id, fields);\n      };\n    }\n  });\n  self._stopped = false;\n  self._id = nextObserveHandleId++;\n};\nObserveHandle.prototype.stop = function () {\n  var self = this;\n  if (self._stopped)\n    return;\n  self._stopped = true;\n  self._multiplexer.removeHandle(self._id);\n};\n"
  },
  {
    "path": "packages/mongo/oplog_observe_driver.js",
    "content": "var Fiber = Npm.require('fibers');\nvar Future = Npm.require('fibers/future');\n\nvar PHASE = {\n  QUERYING: \"QUERYING\",\n  FETCHING: \"FETCHING\",\n  STEADY: \"STEADY\"\n};\n\n// Exception thrown by _needToPollQuery which unrolls the stack up to the\n// enclosing call to finishIfNeedToPollQuery.\nvar SwitchedToQuery = function () {};\nvar finishIfNeedToPollQuery = function (f) {\n  return function () {\n    try {\n      f.apply(this, arguments);\n    } catch (e) {\n      if (!(e instanceof SwitchedToQuery))\n        throw e;\n    }\n  };\n};\n\nvar currentId = 0;\n\n// OplogObserveDriver is an alternative to PollingObserveDriver which follows\n// the Mongo operation log instead of just re-polling the query. It obeys the\n// same simple interface: constructing it starts sending observeChanges\n// callbacks (and a ready() invocation) to the ObserveMultiplexer, and you stop\n// it by calling the stop() method.\nOplogObserveDriver = function (options) {\n  var self = this;\n  self._usesOplog = true;  // tests look at this\n\n  self._id = currentId;\n  currentId++;\n\n  self._cursorDescription = options.cursorDescription;\n  self._mongoHandle = options.mongoHandle;\n  self._multiplexer = options.multiplexer;\n\n  if (options.ordered) {\n    throw Error(\"OplogObserveDriver only supports unordered observeChanges\");\n  }\n\n  var sorter = options.sorter;\n  // We don't support $near and other geo-queries so it's OK to initialize the\n  // comparator only once in the constructor.\n  var comparator = sorter && sorter.getComparator();\n\n  if (options.cursorDescription.options.limit) {\n    // There are several properties ordered driver implements:\n    // - _limit is a positive number\n    // - _comparator is a function-comparator by which the query is ordered\n    // - _unpublishedBuffer is non-null Min/Max Heap,\n    //                      the empty buffer in STEADY phase implies that the\n    //                      everything that matches the queries selector fits\n    //                      into published set.\n    // - _published - Min Heap (also implements IdMap methods)\n\n    var heapOptions = { IdMap: LocalCollection._IdMap };\n    self._limit = self._cursorDescription.options.limit;\n    self._comparator = comparator;\n    self._sorter = sorter;\n    self._unpublishedBuffer = new MinMaxHeap(comparator, heapOptions);\n    // We need something that can find Max value in addition to IdMap interface\n    self._published = new MaxHeap(comparator, heapOptions);\n  } else {\n    self._limit = 0;\n    self._comparator = null;\n    self._sorter = null;\n    self._unpublishedBuffer = null;\n    self._published = new LocalCollection._IdMap;\n  }\n\n  // Indicates if it is safe to insert a new document at the end of the buffer\n  // for this query. i.e. it is known that there are no documents matching the\n  // selector those are not in published or buffer.\n  self._safeAppendToBuffer = false;\n\n  self._stopped = false;\n  self._stopHandles = [];\n\n  Package.facts && Package.facts.Facts.incrementServerFact(\n    \"mongo-livedata\", \"observe-drivers-oplog\", 1);\n\n  self._registerPhaseChange(PHASE.QUERYING);\n\n  var selector = self._cursorDescription.selector;\n  self._matcher = options.matcher;\n  var projection = self._cursorDescription.options.fields || {};\n  self._projectionFn = LocalCollection._compileProjection(projection);\n  // Projection function, result of combining important fields for selector and\n  // existing fields projection\n  self._sharedProjection = self._matcher.combineIntoProjection(projection);\n  if (sorter)\n    self._sharedProjection = sorter.combineIntoProjection(self._sharedProjection);\n  self._sharedProjectionFn = LocalCollection._compileProjection(\n    self._sharedProjection);\n\n  self._needToFetch = new LocalCollection._IdMap;\n  self._currentlyFetching = null;\n  self._fetchGeneration = 0;\n\n  self._requeryWhenDoneThisQuery = false;\n  self._writesToCommitWhenWeReachSteady = [];\n\n  // If the oplog handle tells us that it skipped some entries (because it got\n  // behind, say), re-poll.\n  self._stopHandles.push(self._mongoHandle._oplogHandle.onSkippedEntries(\n    finishIfNeedToPollQuery(function () {\n      self._needToPollQuery();\n    })\n  ));\n\n  forEachTrigger(self._cursorDescription, function (trigger) {\n    self._stopHandles.push(self._mongoHandle._oplogHandle.onOplogEntry(\n      trigger, function (notification) {\n        Meteor._noYieldsAllowed(finishIfNeedToPollQuery(function () {\n          var op = notification.op;\n          if (notification.dropCollection || notification.dropDatabase) {\n            // Note: this call is not allowed to block on anything (especially\n            // on waiting for oplog entries to catch up) because that will block\n            // onOplogEntry!\n            self._needToPollQuery();\n          } else {\n            // All other operators should be handled depending on phase\n            if (self._phase === PHASE.QUERYING)\n              self._handleOplogEntryQuerying(op);\n            else\n              self._handleOplogEntrySteadyOrFetching(op);\n          }\n        }));\n      }\n    ));\n  });\n\n  // XXX ordering w.r.t. everything else?\n  self._stopHandles.push(listenAll(\n    self._cursorDescription, function (notification) {\n      // If we're not in a pre-fire write fence, we don't have to do anything.\n      var fence = DDPServer._CurrentWriteFence.get();\n      if (!fence || fence.fired)\n        return;\n\n      if (fence._oplogObserveDrivers) {\n        fence._oplogObserveDrivers[self._id] = self;\n        return;\n      }\n\n      fence._oplogObserveDrivers = {};\n      fence._oplogObserveDrivers[self._id] = self;\n\n      fence.onBeforeFire(function () {\n        var drivers = fence._oplogObserveDrivers;\n        delete fence._oplogObserveDrivers;\n\n        // This fence cannot fire until we've caught up to \"this point\" in the\n        // oplog, and all observers made it back to the steady state.\n        self._mongoHandle._oplogHandle.waitUntilCaughtUp();\n\n        _.each(drivers, function (driver) {\n          if (driver._stopped)\n            return;\n\n          var write = fence.beginWrite();\n          if (driver._phase === PHASE.STEADY) {\n            // Make sure that all of the callbacks have made it through the\n            // multiplexer and been delivered to ObserveHandles before committing\n            // writes.\n            driver._multiplexer.onFlush(function () {\n              write.committed();\n            });\n          } else {\n            driver._writesToCommitWhenWeReachSteady.push(write);\n          }\n        });\n      });\n    }\n  ));\n\n  // When Mongo fails over, we need to repoll the query, in case we processed an\n  // oplog entry that got rolled back.\n  self._stopHandles.push(self._mongoHandle._onFailover(finishIfNeedToPollQuery(\n    function () {\n      self._needToPollQuery();\n    })));\n\n  // Give _observeChanges a chance to add the new ObserveHandle to our\n  // multiplexer, so that the added calls get streamed.\n  Meteor.defer(finishIfNeedToPollQuery(function () {\n    self._runInitialQuery();\n  }));\n};\n\n_.extend(OplogObserveDriver.prototype, {\n  _addPublished: function (id, doc) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      var fields = _.clone(doc);\n      delete fields._id;\n      self._published.set(id, self._sharedProjectionFn(doc));\n      self._multiplexer.added(id, self._projectionFn(fields));\n\n      // After adding this document, the published set might be overflowed\n      // (exceeding capacity specified by limit). If so, push the maximum\n      // element to the buffer, we might want to save it in memory to reduce the\n      // amount of Mongo lookups in the future.\n      if (self._limit && self._published.size() > self._limit) {\n        // XXX in theory the size of published is no more than limit+1\n        if (self._published.size() !== self._limit + 1) {\n          throw new Error(\"After adding to published, \" +\n                          (self._published.size() - self._limit) +\n                          \" documents are overflowing the set\");\n        }\n\n        var overflowingDocId = self._published.maxElementId();\n        var overflowingDoc = self._published.get(overflowingDocId);\n\n        if (EJSON.equals(overflowingDocId, id)) {\n          throw new Error(\"The document just added is overflowing the published set\");\n        }\n\n        self._published.remove(overflowingDocId);\n        self._multiplexer.removed(overflowingDocId);\n        self._addBuffered(overflowingDocId, overflowingDoc);\n      }\n    });\n  },\n  _removePublished: function (id) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._published.remove(id);\n      self._multiplexer.removed(id);\n      if (! self._limit || self._published.size() === self._limit)\n        return;\n\n      if (self._published.size() > self._limit)\n        throw Error(\"self._published got too big\");\n\n      // OK, we are publishing less than the limit. Maybe we should look in the\n      // buffer to find the next element past what we were publishing before.\n\n      if (!self._unpublishedBuffer.empty()) {\n        // There's something in the buffer; move the first thing in it to\n        // _published.\n        var newDocId = self._unpublishedBuffer.minElementId();\n        var newDoc = self._unpublishedBuffer.get(newDocId);\n        self._removeBuffered(newDocId);\n        self._addPublished(newDocId, newDoc);\n        return;\n      }\n\n      // There's nothing in the buffer.  This could mean one of a few things.\n\n      // (a) We could be in the middle of re-running the query (specifically, we\n      // could be in _publishNewResults). In that case, _unpublishedBuffer is\n      // empty because we clear it at the beginning of _publishNewResults. In\n      // this case, our caller already knows the entire answer to the query and\n      // we don't need to do anything fancy here.  Just return.\n      if (self._phase === PHASE.QUERYING)\n        return;\n\n      // (b) We're pretty confident that the union of _published and\n      // _unpublishedBuffer contain all documents that match selector. Because\n      // _unpublishedBuffer is empty, that means we're confident that _published\n      // contains all documents that match selector. So we have nothing to do.\n      if (self._safeAppendToBuffer)\n        return;\n\n      // (c) Maybe there are other documents out there that should be in our\n      // buffer. But in that case, when we emptied _unpublishedBuffer in\n      // _removeBuffered, we should have called _needToPollQuery, which will\n      // either put something in _unpublishedBuffer or set _safeAppendToBuffer\n      // (or both), and it will put us in QUERYING for that whole time. So in\n      // fact, we shouldn't be able to get here.\n\n      throw new Error(\"Buffer inexplicably empty\");\n    });\n  },\n  _changePublished: function (id, oldDoc, newDoc) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._published.set(id, self._sharedProjectionFn(newDoc));\n      var projectedNew = self._projectionFn(newDoc);\n      var projectedOld = self._projectionFn(oldDoc);\n      var changed = DiffSequence.makeChangedFields(\n        projectedNew, projectedOld);\n      if (!_.isEmpty(changed))\n        self._multiplexer.changed(id, changed);\n    });\n  },\n  _addBuffered: function (id, doc) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._unpublishedBuffer.set(id, self._sharedProjectionFn(doc));\n\n      // If something is overflowing the buffer, we just remove it from cache\n      if (self._unpublishedBuffer.size() > self._limit) {\n        var maxBufferedId = self._unpublishedBuffer.maxElementId();\n\n        self._unpublishedBuffer.remove(maxBufferedId);\n\n        // Since something matching is removed from cache (both published set and\n        // buffer), set flag to false\n        self._safeAppendToBuffer = false;\n      }\n    });\n  },\n  // Is called either to remove the doc completely from matching set or to move\n  // it to the published set later.\n  _removeBuffered: function (id) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._unpublishedBuffer.remove(id);\n      // To keep the contract \"buffer is never empty in STEADY phase unless the\n      // everything matching fits into published\" true, we poll everything as\n      // soon as we see the buffer becoming empty.\n      if (! self._unpublishedBuffer.size() && ! self._safeAppendToBuffer)\n        self._needToPollQuery();\n    });\n  },\n  // Called when a document has joined the \"Matching\" results set.\n  // Takes responsibility of keeping _unpublishedBuffer in sync with _published\n  // and the effect of limit enforced.\n  _addMatching: function (doc) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      var id = doc._id;\n      if (self._published.has(id))\n        throw Error(\"tried to add something already published \" + id);\n      if (self._limit && self._unpublishedBuffer.has(id))\n        throw Error(\"tried to add something already existed in buffer \" + id);\n\n      var limit = self._limit;\n      var comparator = self._comparator;\n      var maxPublished = (limit && self._published.size() > 0) ?\n        self._published.get(self._published.maxElementId()) : null;\n      var maxBuffered = (limit && self._unpublishedBuffer.size() > 0)\n        ? self._unpublishedBuffer.get(self._unpublishedBuffer.maxElementId())\n        : null;\n      // The query is unlimited or didn't publish enough documents yet or the\n      // new document would fit into published set pushing the maximum element\n      // out, then we need to publish the doc.\n      var toPublish = ! limit || self._published.size() < limit ||\n        comparator(doc, maxPublished) < 0;\n\n      // Otherwise we might need to buffer it (only in case of limited query).\n      // Buffering is allowed if the buffer is not filled up yet and all\n      // matching docs are either in the published set or in the buffer.\n      var canAppendToBuffer = !toPublish && self._safeAppendToBuffer &&\n        self._unpublishedBuffer.size() < limit;\n\n      // Or if it is small enough to be safely inserted to the middle or the\n      // beginning of the buffer.\n      var canInsertIntoBuffer = !toPublish && maxBuffered &&\n        comparator(doc, maxBuffered) <= 0;\n\n      var toBuffer = canAppendToBuffer || canInsertIntoBuffer;\n\n      if (toPublish) {\n        self._addPublished(id, doc);\n      } else if (toBuffer) {\n        self._addBuffered(id, doc);\n      } else {\n        // dropping it and not saving to the cache\n        self._safeAppendToBuffer = false;\n      }\n    });\n  },\n  // Called when a document leaves the \"Matching\" results set.\n  // Takes responsibility of keeping _unpublishedBuffer in sync with _published\n  // and the effect of limit enforced.\n  _removeMatching: function (id) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      if (! self._published.has(id) && ! self._limit)\n        throw Error(\"tried to remove something matching but not cached \" + id);\n\n      if (self._published.has(id)) {\n        self._removePublished(id);\n      } else if (self._unpublishedBuffer.has(id)) {\n        self._removeBuffered(id);\n      }\n    });\n  },\n  _handleDoc: function (id, newDoc) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      var matchesNow = newDoc && self._matcher.documentMatches(newDoc).result;\n\n      var publishedBefore = self._published.has(id);\n      var bufferedBefore = self._limit && self._unpublishedBuffer.has(id);\n      var cachedBefore = publishedBefore || bufferedBefore;\n\n      if (matchesNow && !cachedBefore) {\n        self._addMatching(newDoc);\n      } else if (cachedBefore && !matchesNow) {\n        self._removeMatching(id);\n      } else if (cachedBefore && matchesNow) {\n        var oldDoc = self._published.get(id);\n        var comparator = self._comparator;\n        var minBuffered = self._limit && self._unpublishedBuffer.size() &&\n          self._unpublishedBuffer.get(self._unpublishedBuffer.minElementId());\n\n        if (publishedBefore) {\n          // Unlimited case where the document stays in published once it\n          // matches or the case when we don't have enough matching docs to\n          // publish or the changed but matching doc will stay in published\n          // anyways.\n          //\n          // XXX: We rely on the emptiness of buffer. Be sure to maintain the\n          // fact that buffer can't be empty if there are matching documents not\n          // published. Notably, we don't want to schedule repoll and continue\n          // relying on this property.\n          var staysInPublished = ! self._limit ||\n            self._unpublishedBuffer.size() === 0 ||\n            comparator(newDoc, minBuffered) <= 0;\n\n          if (staysInPublished) {\n            self._changePublished(id, oldDoc, newDoc);\n          } else {\n            // after the change doc doesn't stay in the published, remove it\n            self._removePublished(id);\n            // but it can move into buffered now, check it\n            var maxBuffered = self._unpublishedBuffer.get(\n              self._unpublishedBuffer.maxElementId());\n\n            var toBuffer = self._safeAppendToBuffer ||\n                  (maxBuffered && comparator(newDoc, maxBuffered) <= 0);\n\n            if (toBuffer) {\n              self._addBuffered(id, newDoc);\n            } else {\n              // Throw away from both published set and buffer\n              self._safeAppendToBuffer = false;\n            }\n          }\n        } else if (bufferedBefore) {\n          oldDoc = self._unpublishedBuffer.get(id);\n          // remove the old version manually instead of using _removeBuffered so\n          // we don't trigger the querying immediately.  if we end this block\n          // with the buffer empty, we will need to trigger the query poll\n          // manually too.\n          self._unpublishedBuffer.remove(id);\n\n          var maxPublished = self._published.get(\n            self._published.maxElementId());\n          var maxBuffered = self._unpublishedBuffer.size() &&\n                self._unpublishedBuffer.get(\n                  self._unpublishedBuffer.maxElementId());\n\n          // the buffered doc was updated, it could move to published\n          var toPublish = comparator(newDoc, maxPublished) < 0;\n\n          // or stays in buffer even after the change\n          var staysInBuffer = (! toPublish && self._safeAppendToBuffer) ||\n                (!toPublish && maxBuffered &&\n                 comparator(newDoc, maxBuffered) <= 0);\n\n          if (toPublish) {\n            self._addPublished(id, newDoc);\n          } else if (staysInBuffer) {\n            // stays in buffer but changes\n            self._unpublishedBuffer.set(id, newDoc);\n          } else {\n            // Throw away from both published set and buffer\n            self._safeAppendToBuffer = false;\n            // Normally this check would have been done in _removeBuffered but\n            // we didn't use it, so we need to do it ourself now.\n            if (! self._unpublishedBuffer.size()) {\n              self._needToPollQuery();\n            }\n          }\n        } else {\n          throw new Error(\"cachedBefore implies either of publishedBefore or bufferedBefore is true.\");\n        }\n      }\n    });\n  },\n  _fetchModifiedDocuments: function () {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._registerPhaseChange(PHASE.FETCHING);\n      // Defer, because nothing called from the oplog entry handler may yield,\n      // but fetch() yields.\n      Meteor.defer(finishIfNeedToPollQuery(function () {\n        while (!self._stopped && !self._needToFetch.empty()) {\n          if (self._phase === PHASE.QUERYING) {\n            // While fetching, we decided to go into QUERYING mode, and then we\n            // saw another oplog entry, so _needToFetch is not empty. But we\n            // shouldn't fetch these documents until AFTER the query is done.\n            break;\n          }\n\n          // Being in steady phase here would be surprising.\n          if (self._phase !== PHASE.FETCHING)\n            throw new Error(\"phase in fetchModifiedDocuments: \" + self._phase);\n\n          self._currentlyFetching = self._needToFetch;\n          var thisGeneration = ++self._fetchGeneration;\n          self._needToFetch = new LocalCollection._IdMap;\n          var waiting = 0;\n          var fut = new Future;\n          // This loop is safe, because _currentlyFetching will not be updated\n          // during this loop (in fact, it is never mutated).\n          self._currentlyFetching.forEach(function (cacheKey, id) {\n            waiting++;\n            self._mongoHandle._docFetcher.fetch(\n              self._cursorDescription.collectionName, id, cacheKey,\n              finishIfNeedToPollQuery(function (err, doc) {\n                try {\n                  if (err) {\n                    Meteor._debug(\"Got exception while fetching documents: \" +\n                                  err);\n                    // If we get an error from the fetcher (eg, trouble\n                    // connecting to Mongo), let's just abandon the fetch phase\n                    // altogether and fall back to polling. It's not like we're\n                    // getting live updates anyway.\n                    if (self._phase !== PHASE.QUERYING) {\n                      self._needToPollQuery();\n                    }\n                  } else if (!self._stopped && self._phase === PHASE.FETCHING\n                             && self._fetchGeneration === thisGeneration) {\n                    // We re-check the generation in case we've had an explicit\n                    // _pollQuery call (eg, in another fiber) which should\n                    // effectively cancel this round of fetches.  (_pollQuery\n                    // increments the generation.)\n                    self._handleDoc(id, doc);\n                  }\n                } finally {\n                  waiting--;\n                  // Because fetch() never calls its callback synchronously,\n                  // this is safe (ie, we won't call fut.return() before the\n                  // forEach is done).\n                  if (waiting === 0)\n                    fut.return();\n                }\n              }));\n          });\n          fut.wait();\n          // Exit now if we've had a _pollQuery call (here or in another fiber).\n          if (self._phase === PHASE.QUERYING)\n            return;\n          self._currentlyFetching = null;\n        }\n        // We're done fetching, so we can be steady, unless we've had a\n        // _pollQuery call (here or in another fiber).\n        if (self._phase !== PHASE.QUERYING)\n          self._beSteady();\n      }));\n    });\n  },\n  _beSteady: function () {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._registerPhaseChange(PHASE.STEADY);\n      var writes = self._writesToCommitWhenWeReachSteady;\n      self._writesToCommitWhenWeReachSteady = [];\n      self._multiplexer.onFlush(function () {\n        _.each(writes, function (w) {\n          w.committed();\n        });\n      });\n    });\n  },\n  _handleOplogEntryQuerying: function (op) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._needToFetch.set(idForOp(op), op.ts.toString());\n    });\n  },\n  _handleOplogEntrySteadyOrFetching: function (op) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      var id = idForOp(op);\n      // If we're already fetching this one, or about to, we can't optimize;\n      // make sure that we fetch it again if necessary.\n      if (self._phase === PHASE.FETCHING &&\n          ((self._currentlyFetching && self._currentlyFetching.has(id)) ||\n           self._needToFetch.has(id))) {\n        self._needToFetch.set(id, op.ts.toString());\n        return;\n      }\n\n      if (op.op === 'd') {\n        if (self._published.has(id) ||\n            (self._limit && self._unpublishedBuffer.has(id)))\n          self._removeMatching(id);\n      } else if (op.op === 'i') {\n        if (self._published.has(id))\n          throw new Error(\"insert found for already-existing ID in published\");\n        if (self._unpublishedBuffer && self._unpublishedBuffer.has(id))\n          throw new Error(\"insert found for already-existing ID in buffer\");\n\n        // XXX what if selector yields?  for now it can't but later it could\n        // have $where\n        if (self._matcher.documentMatches(op.o).result)\n          self._addMatching(op.o);\n      } else if (op.op === 'u') {\n        // Is this a modifier ($set/$unset, which may require us to poll the\n        // database to figure out if the whole document matches the selector) or\n        // a replacement (in which case we can just directly re-evaluate the\n        // selector)?\n        var isReplace = !_.has(op.o, '$set') && !_.has(op.o, '$unset');\n        // If this modifier modifies something inside an EJSON custom type (ie,\n        // anything with EJSON$), then we can't try to use\n        // LocalCollection._modify, since that just mutates the EJSON encoding,\n        // not the actual object.\n        var canDirectlyModifyDoc =\n          !isReplace && modifierCanBeDirectlyApplied(op.o);\n\n        var publishedBefore = self._published.has(id);\n        var bufferedBefore = self._limit && self._unpublishedBuffer.has(id);\n\n        if (isReplace) {\n          self._handleDoc(id, _.extend({_id: id}, op.o));\n        } else if ((publishedBefore || bufferedBefore) &&\n                   canDirectlyModifyDoc) {\n          // Oh great, we actually know what the document is, so we can apply\n          // this directly.\n          var newDoc = self._published.has(id)\n            ? self._published.get(id) : self._unpublishedBuffer.get(id);\n          newDoc = EJSON.clone(newDoc);\n\n          newDoc._id = id;\n          try {\n            LocalCollection._modify(newDoc, op.o);\n          } catch (e) {\n            if (e.name !== \"MinimongoError\")\n              throw e;\n            // We didn't understand the modifier.  Re-fetch.\n            self._needToFetch.set(id, op.ts.toString());\n            if (self._phase === PHASE.STEADY) {\n              self._fetchModifiedDocuments();\n            }\n            return;\n          }\n          self._handleDoc(id, self._sharedProjectionFn(newDoc));\n        } else if (!canDirectlyModifyDoc ||\n                   self._matcher.canBecomeTrueByModifier(op.o) ||\n                   (self._sorter && self._sorter.affectedByModifier(op.o))) {\n          self._needToFetch.set(id, op.ts.toString());\n          if (self._phase === PHASE.STEADY)\n            self._fetchModifiedDocuments();\n        }\n      } else {\n        throw Error(\"XXX SURPRISING OPERATION: \" + op);\n      }\n    });\n  },\n  // Yields!\n  _runInitialQuery: function () {\n    var self = this;\n    if (self._stopped)\n      throw new Error(\"oplog stopped surprisingly early\");\n\n    self._runQuery({initial: true});  // yields\n\n    if (self._stopped)\n      return;  // can happen on queryError\n\n    // Allow observeChanges calls to return. (After this, it's possible for\n    // stop() to be called.)\n    self._multiplexer.ready();\n\n    self._doneQuerying();  // yields\n  },\n\n  // In various circumstances, we may just want to stop processing the oplog and\n  // re-run the initial query, just as if we were a PollingObserveDriver.\n  //\n  // This function may not block, because it is called from an oplog entry\n  // handler.\n  //\n  // XXX We should call this when we detect that we've been in FETCHING for \"too\n  // long\".\n  //\n  // XXX We should call this when we detect Mongo failover (since that might\n  // mean that some of the oplog entries we have processed have been rolled\n  // back). The Node Mongo driver is in the middle of a bunch of huge\n  // refactorings, including the way that it notifies you when primary\n  // changes. Will put off implementing this until driver 1.4 is out.\n  _pollQuery: function () {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      if (self._stopped)\n        return;\n\n      // Yay, we get to forget about all the things we thought we had to fetch.\n      self._needToFetch = new LocalCollection._IdMap;\n      self._currentlyFetching = null;\n      ++self._fetchGeneration;  // ignore any in-flight fetches\n      self._registerPhaseChange(PHASE.QUERYING);\n\n      // Defer so that we don't yield.  We don't need finishIfNeedToPollQuery\n      // here because SwitchedToQuery is not thrown in QUERYING mode.\n      Meteor.defer(function () {\n        self._runQuery();\n        self._doneQuerying();\n      });\n    });\n  },\n\n  // Yields!\n  _runQuery: function (options) {\n    var self = this;\n    options = options || {};\n    var newResults, newBuffer;\n\n    // This while loop is just to retry failures.\n    while (true) {\n      // If we've been stopped, we don't have to run anything any more.\n      if (self._stopped)\n        return;\n\n      newResults = new LocalCollection._IdMap;\n      newBuffer = new LocalCollection._IdMap;\n\n      // Query 2x documents as the half excluded from the original query will go\n      // into unpublished buffer to reduce additional Mongo lookups in cases\n      // when documents are removed from the published set and need a\n      // replacement.\n      // XXX needs more thought on non-zero skip\n      // XXX 2 is a \"magic number\" meaning there is an extra chunk of docs for\n      // buffer if such is needed.\n      var cursor = self._cursorForQuery({ limit: self._limit * 2 });\n      try {\n        cursor.forEach(function (doc, i) {  // yields\n          if (!self._limit || i < self._limit)\n            newResults.set(doc._id, doc);\n          else\n            newBuffer.set(doc._id, doc);\n        });\n        break;\n      } catch (e) {\n        if (options.initial && typeof(e.code) === 'number') {\n          // This is an error document sent to us by mongod, not a connection\n          // error generated by the client. And we've never seen this query work\n          // successfully. Probably it's a bad selector or something, so we\n          // should NOT retry. Instead, we should halt the observe (which ends\n          // up calling `stop` on us).\n          self._multiplexer.queryError(e);\n          return;\n        }\n\n        // During failover (eg) if we get an exception we should log and retry\n        // instead of crashing.\n        Meteor._debug(\"Got exception while polling query: \" + e);\n        Meteor._sleepForMs(100);\n      }\n    }\n\n    if (self._stopped)\n      return;\n\n    self._publishNewResults(newResults, newBuffer);\n  },\n\n  // Transitions to QUERYING and runs another query, or (if already in QUERYING)\n  // ensures that we will query again later.\n  //\n  // This function may not block, because it is called from an oplog entry\n  // handler. However, if we were not already in the QUERYING phase, it throws\n  // an exception that is caught by the closest surrounding\n  // finishIfNeedToPollQuery call; this ensures that we don't continue running\n  // close that was designed for another phase inside PHASE.QUERYING.\n  //\n  // (It's also necessary whenever logic in this file yields to check that other\n  // phases haven't put us into QUERYING mode, though; eg,\n  // _fetchModifiedDocuments does this.)\n  _needToPollQuery: function () {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      if (self._stopped)\n        return;\n\n      // If we're not already in the middle of a query, we can query now\n      // (possibly pausing FETCHING).\n      if (self._phase !== PHASE.QUERYING) {\n        self._pollQuery();\n        throw new SwitchedToQuery;\n      }\n\n      // We're currently in QUERYING. Set a flag to ensure that we run another\n      // query when we're done.\n      self._requeryWhenDoneThisQuery = true;\n    });\n  },\n\n  // Yields!\n  _doneQuerying: function () {\n    var self = this;\n\n    if (self._stopped)\n      return;\n    self._mongoHandle._oplogHandle.waitUntilCaughtUp();  // yields\n    if (self._stopped)\n      return;\n    if (self._phase !== PHASE.QUERYING)\n      throw Error(\"Phase unexpectedly \" + self._phase);\n\n    Meteor._noYieldsAllowed(function () {\n      if (self._requeryWhenDoneThisQuery) {\n        self._requeryWhenDoneThisQuery = false;\n        self._pollQuery();\n      } else if (self._needToFetch.empty()) {\n        self._beSteady();\n      } else {\n        self._fetchModifiedDocuments();\n      }\n    });\n  },\n\n  _cursorForQuery: function (optionsOverwrite) {\n    var self = this;\n    return Meteor._noYieldsAllowed(function () {\n      // The query we run is almost the same as the cursor we are observing,\n      // with a few changes. We need to read all the fields that are relevant to\n      // the selector, not just the fields we are going to publish (that's the\n      // \"shared\" projection). And we don't want to apply any transform in the\n      // cursor, because observeChanges shouldn't use the transform.\n      var options = _.clone(self._cursorDescription.options);\n\n      // Allow the caller to modify the options. Useful to specify different\n      // skip and limit values.\n      _.extend(options, optionsOverwrite);\n\n      options.fields = self._sharedProjection;\n      delete options.transform;\n      // We are NOT deep cloning fields or selector here, which should be OK.\n      var description = new CursorDescription(\n        self._cursorDescription.collectionName,\n        self._cursorDescription.selector,\n        options);\n      return new Cursor(self._mongoHandle, description);\n    });\n  },\n\n\n  // Replace self._published with newResults (both are IdMaps), invoking observe\n  // callbacks on the multiplexer.\n  // Replace self._unpublishedBuffer with newBuffer.\n  //\n  // XXX This is very similar to LocalCollection._diffQueryUnorderedChanges. We\n  // should really: (a) Unify IdMap and OrderedDict into Unordered/OrderedDict\n  // (b) Rewrite diff.js to use these classes instead of arrays and objects.\n  _publishNewResults: function (newResults, newBuffer) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n\n      // If the query is limited and there is a buffer, shut down so it doesn't\n      // stay in a way.\n      if (self._limit) {\n        self._unpublishedBuffer.clear();\n      }\n\n      // First remove anything that's gone. Be careful not to modify\n      // self._published while iterating over it.\n      var idsToRemove = [];\n      self._published.forEach(function (doc, id) {\n        if (!newResults.has(id))\n          idsToRemove.push(id);\n      });\n      _.each(idsToRemove, function (id) {\n        self._removePublished(id);\n      });\n\n      // Now do adds and changes.\n      // If self has a buffer and limit, the new fetched result will be\n      // limited correctly as the query has sort specifier.\n      newResults.forEach(function (doc, id) {\n        self._handleDoc(id, doc);\n      });\n\n      // Sanity-check that everything we tried to put into _published ended up\n      // there.\n      // XXX if this is slow, remove it later\n      if (self._published.size() !== newResults.size()) {\n        throw Error(\n          \"The Mongo server and the Meteor query disagree on how \" +\n            \"many documents match your query. Maybe it is hitting a Mongo \" +\n            \"edge case? The query is: \" +\n            EJSON.stringify(self._cursorDescription.selector));\n      }\n      self._published.forEach(function (doc, id) {\n        if (!newResults.has(id))\n          throw Error(\"_published has a doc that newResults doesn't; \" + id);\n      });\n\n      // Finally, replace the buffer\n      newBuffer.forEach(function (doc, id) {\n        self._addBuffered(id, doc);\n      });\n\n      self._safeAppendToBuffer = newBuffer.size() < self._limit;\n    });\n  },\n\n  // This stop function is invoked from the onStop of the ObserveMultiplexer, so\n  // it shouldn't actually be possible to call it until the multiplexer is\n  // ready.\n  //\n  // It's important to check self._stopped after every call in this file that\n  // can yield!\n  stop: function () {\n    var self = this;\n    if (self._stopped)\n      return;\n    self._stopped = true;\n    _.each(self._stopHandles, function (handle) {\n      handle.stop();\n    });\n\n    // Note: we *don't* use multiplexer.onFlush here because this stop\n    // callback is actually invoked by the multiplexer itself when it has\n    // determined that there are no handles left. So nothing is actually going\n    // to get flushed (and it's probably not valid to call methods on the\n    // dying multiplexer).\n    _.each(self._writesToCommitWhenWeReachSteady, function (w) {\n      w.committed();  // maybe yields?\n    });\n    self._writesToCommitWhenWeReachSteady = null;\n\n    // Proactively drop references to potentially big things.\n    self._published = null;\n    self._unpublishedBuffer = null;\n    self._needToFetch = null;\n    self._currentlyFetching = null;\n    self._oplogEntryHandle = null;\n    self._listenersHandle = null;\n\n    Package.facts && Package.facts.Facts.incrementServerFact(\n      \"mongo-livedata\", \"observe-drivers-oplog\", -1);\n  },\n\n  _registerPhaseChange: function (phase) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      var now = new Date;\n\n      if (self._phase) {\n        var timeDiff = now - self._phaseStartTime;\n        Package.facts && Package.facts.Facts.incrementServerFact(\n          \"mongo-livedata\", \"time-spent-in-\" + self._phase + \"-phase\", timeDiff);\n      }\n\n      self._phase = phase;\n      self._phaseStartTime = now;\n    });\n  }\n});\n\n// Does our oplog tailing code support this cursor? For now, we are being very\n// conservative and allowing only simple queries with simple options.\n// (This is a \"static method\".)\nOplogObserveDriver.cursorSupported = function (cursorDescription, matcher) {\n  // First, check the options.\n  var options = cursorDescription.options;\n\n  // Did the user say no explicitly?\n  // underscored version of the option is COMPAT with 1.2\n  if (options.disableOplog || options._disableOplog)\n    return false;\n\n  // skip is not supported: to support it we would need to keep track of all\n  // \"skipped\" documents or at least their ids.\n  // limit w/o a sort specifier is not supported: current implementation needs a\n  // deterministic way to order documents.\n  if (options.skip || (options.limit && !options.sort)) return false;\n\n  // If a fields projection option is given check if it is supported by\n  // minimongo (some operators are not supported).\n  if (options.fields) {\n    try {\n      LocalCollection._checkSupportedProjection(options.fields);\n    } catch (e) {\n      if (e.name === \"MinimongoError\")\n        return false;\n      else\n        throw e;\n    }\n  }\n\n  // We don't allow the following selectors:\n  //   - $where (not confident that we provide the same JS environment\n  //             as Mongo, and can yield!)\n  //   - $near (has \"interesting\" properties in MongoDB, like the possibility\n  //            of returning an ID multiple times, though even polling maybe\n  //            have a bug there)\n  //           XXX: once we support it, we would need to think more on how we\n  //           initialize the comparators when we create the driver.\n  return !matcher.hasWhere() && !matcher.hasGeoQuery();\n};\n\nvar modifierCanBeDirectlyApplied = function (modifier) {\n  return _.all(modifier, function (fields, operation) {\n    return _.all(fields, function (value, field) {\n      return !/EJSON\\$/.test(field);\n    });\n  });\n};\n\nMongoInternals.OplogObserveDriver = OplogObserveDriver;\n"
  },
  {
    "path": "packages/mongo/oplog_tailing.js",
    "content": "var Future = Npm.require('fibers/future');\n\nOPLOG_COLLECTION = 'oplog.rs';\n\nvar TOO_FAR_BEHIND = process.env.METEOR_OPLOG_TOO_FAR_BEHIND || 2000;\n\nvar showTS = function (ts) {\n  return \"Timestamp(\" + ts.getHighBits() + \", \" + ts.getLowBits() + \")\";\n};\n\nidForOp = function (op) {\n  if (op.op === 'd')\n    return op.o._id;\n  else if (op.op === 'i')\n    return op.o._id;\n  else if (op.op === 'u')\n    return op.o2._id;\n  else if (op.op === 'c')\n    throw Error(\"Operator 'c' doesn't supply an object with id: \" +\n                EJSON.stringify(op));\n  else\n    throw Error(\"Unknown op: \" + EJSON.stringify(op));\n};\n\nOplogHandle = function (oplogUrl, dbName) {\n  var self = this;\n  self._oplogUrl = oplogUrl;\n  self._dbName = dbName;\n\n  self._oplogLastEntryConnection = null;\n  self._oplogTailConnection = null;\n  self._stopped = false;\n  self._tailHandle = null;\n  self._readyFuture = new Future();\n  self._crossbar = new DDPServer._Crossbar({\n    factPackage: \"mongo-livedata\", factName: \"oplog-watchers\"\n  });\n  self._baseOplogSelector = {\n    ns: new RegExp('^' + Meteor._escapeRegExp(self._dbName) + '\\\\.'),\n    $or: [\n      { op: {$in: ['i', 'u', 'd']} },\n      // drop collection\n      { op: 'c', 'o.drop': { $exists: true } },\n      { op: 'c', 'o.dropDatabase': 1 },\n    ]\n  };\n\n  // Data structures to support waitUntilCaughtUp(). Each oplog entry has a\n  // MongoTimestamp object on it (which is not the same as a Date --- it's a\n  // combination of time and an incrementing counter; see\n  // http://docs.mongodb.org/manual/reference/bson-types/#timestamps).\n  //\n  // _catchingUpFutures is an array of {ts: MongoTimestamp, future: Future}\n  // objects, sorted by ascending timestamp. _lastProcessedTS is the\n  // MongoTimestamp of the last oplog entry we've processed.\n  //\n  // Each time we call waitUntilCaughtUp, we take a peek at the final oplog\n  // entry in the db.  If we've already processed it (ie, it is not greater than\n  // _lastProcessedTS), waitUntilCaughtUp immediately returns. Otherwise,\n  // waitUntilCaughtUp makes a new Future and inserts it along with the final\n  // timestamp entry that it read, into _catchingUpFutures. waitUntilCaughtUp\n  // then waits on that future, which is resolved once _lastProcessedTS is\n  // incremented to be past its timestamp by the worker fiber.\n  //\n  // XXX use a priority queue or something else that's faster than an array\n  self._catchingUpFutures = [];\n  self._lastProcessedTS = null;\n\n  self._onSkippedEntriesHook = new Hook({\n    debugPrintExceptions: \"onSkippedEntries callback\"\n  });\n\n  self._entryQueue = new Meteor._DoubleEndedQueue();\n  self._workerActive = false;\n\n  self._startTailing();\n};\n\n_.extend(OplogHandle.prototype, {\n  stop: function () {\n    var self = this;\n    if (self._stopped)\n      return;\n    self._stopped = true;\n    if (self._tailHandle)\n      self._tailHandle.stop();\n    // XXX should close connections too\n  },\n  onOplogEntry: function (trigger, callback) {\n    var self = this;\n    if (self._stopped)\n      throw new Error(\"Called onOplogEntry on stopped handle!\");\n\n    // Calling onOplogEntry requires us to wait for the tailing to be ready.\n    self._readyFuture.wait();\n\n    var originalCallback = callback;\n    callback = Meteor.bindEnvironment(function (notification) {\n      // XXX can we avoid this clone by making oplog.js careful?\n      originalCallback(EJSON.clone(notification));\n    }, function (err) {\n      Meteor._debug(\"Error in oplog callback\", err.stack);\n    });\n    var listenHandle = self._crossbar.listen(trigger, callback);\n    return {\n      stop: function () {\n        listenHandle.stop();\n      }\n    };\n  },\n  // Register a callback to be invoked any time we skip oplog entries (eg,\n  // because we are too far behind).\n  onSkippedEntries: function (callback) {\n    var self = this;\n    if (self._stopped)\n      throw new Error(\"Called onSkippedEntries on stopped handle!\");\n    return self._onSkippedEntriesHook.register(callback);\n  },\n  // Calls `callback` once the oplog has been processed up to a point that is\n  // roughly \"now\": specifically, once we've processed all ops that are\n  // currently visible.\n  // XXX become convinced that this is actually safe even if oplogConnection\n  // is some kind of pool\n  waitUntilCaughtUp: function () {\n    var self = this;\n    if (self._stopped)\n      throw new Error(\"Called waitUntilCaughtUp on stopped handle!\");\n\n    // Calling waitUntilCaughtUp requries us to wait for the oplog connection to\n    // be ready.\n    self._readyFuture.wait();\n\n    while (!self._stopped) {\n      // We need to make the selector at least as restrictive as the actual\n      // tailing selector (ie, we need to specify the DB name) or else we might\n      // find a TS that won't show up in the actual tail stream.\n      try {\n        var lastEntry = self._oplogLastEntryConnection.findOne(\n          OPLOG_COLLECTION, self._baseOplogSelector,\n          {fields: {ts: 1}, sort: {$natural: -1}});\n        break;\n      } catch (e) {\n        // During failover (eg) if we get an exception we should log and retry\n        // instead of crashing.\n        Meteor._debug(\"Got exception while reading last entry: \" + e);\n        Meteor._sleepForMs(100);\n      }\n    }\n\n    if (self._stopped)\n      return;\n\n    if (!lastEntry) {\n      // Really, nothing in the oplog? Well, we've processed everything.\n      return;\n    }\n\n    var ts = lastEntry.ts;\n    if (!ts)\n      throw Error(\"oplog entry without ts: \" + EJSON.stringify(lastEntry));\n\n    if (self._lastProcessedTS && ts.lessThanOrEqual(self._lastProcessedTS)) {\n      // We've already caught up to here.\n      return;\n    }\n\n\n    // Insert the future into our list. Almost always, this will be at the end,\n    // but it's conceivable that if we fail over from one primary to another,\n    // the oplog entries we see will go backwards.\n    var insertAfter = self._catchingUpFutures.length;\n    while (insertAfter - 1 > 0\n           && self._catchingUpFutures[insertAfter - 1].ts.greaterThan(ts)) {\n      insertAfter--;\n    }\n    var f = new Future;\n    self._catchingUpFutures.splice(insertAfter, 0, {ts: ts, future: f});\n    f.wait();\n  },\n  _startTailing: function () {\n    var self = this;\n    // First, make sure that we're talking to the local database.\n    var mongodbUri = Npm.require('mongodb-uri');\n    if (mongodbUri.parse(self._oplogUrl).database !== 'local') {\n      throw Error(\"$MONGO_OPLOG_URL must be set to the 'local' database of \" +\n                  \"a Mongo replica set\");\n    }\n\n    // We make two separate connections to Mongo. The Node Mongo driver\n    // implements a naive round-robin connection pool: each \"connection\" is a\n    // pool of several (5 by default) TCP connections, and each request is\n    // rotated through the pools. Tailable cursor queries block on the server\n    // until there is some data to return (or until a few seconds have\n    // passed). So if the connection pool used for tailing cursors is the same\n    // pool used for other queries, the other queries will be delayed by seconds\n    // 1/5 of the time.\n    //\n    // The tail connection will only ever be running a single tail command, so\n    // it only needs to make one underlying TCP connection.\n    self._oplogTailConnection = new MongoConnection(\n      self._oplogUrl, {poolSize: 1});\n    // XXX better docs, but: it's to get monotonic results\n    // XXX is it safe to say \"if there's an in flight query, just use its\n    //     results\"? I don't think so but should consider that\n    self._oplogLastEntryConnection = new MongoConnection(\n      self._oplogUrl, {poolSize: 1});\n\n    // Now, make sure that there actually is a repl set here. If not, oplog\n    // tailing won't ever find anything!\n    var f = new Future;\n    self._oplogLastEntryConnection.db.admin().command(\n      { ismaster: 1 }, f.resolver());\n    var isMasterDoc = f.wait();\n    if (!(isMasterDoc && isMasterDoc.documents && isMasterDoc.documents[0] &&\n          isMasterDoc.documents[0].setName)) {\n      throw Error(\"$MONGO_OPLOG_URL must be set to the 'local' database of \" +\n                  \"a Mongo replica set\");\n    }\n\n    // Find the last oplog entry.\n    var lastOplogEntry = self._oplogLastEntryConnection.findOne(\n      OPLOG_COLLECTION, {}, {sort: {$natural: -1}, fields: {ts: 1}});\n\n    var oplogSelector = _.clone(self._baseOplogSelector);\n    if (lastOplogEntry) {\n      // Start after the last entry that currently exists.\n      oplogSelector.ts = {$gt: lastOplogEntry.ts};\n      // If there are any calls to callWhenProcessedLatest before any other\n      // oplog entries show up, allow callWhenProcessedLatest to call its\n      // callback immediately.\n      self._lastProcessedTS = lastOplogEntry.ts;\n    }\n\n    var cursorDescription = new CursorDescription(\n      OPLOG_COLLECTION, oplogSelector, {tailable: true});\n\n    self._tailHandle = self._oplogTailConnection.tail(\n      cursorDescription, function (doc) {\n        self._entryQueue.push(doc);\n        self._maybeStartWorker();\n      }\n    );\n    self._readyFuture.return();\n  },\n\n  _maybeStartWorker: function () {\n    var self = this;\n    if (self._workerActive)\n      return;\n    self._workerActive = true;\n    Meteor.defer(function () {\n      try {\n        while (! self._stopped && ! self._entryQueue.isEmpty()) {\n          // Are we too far behind? Just tell our observers that they need to\n          // repoll, and drop our queue.\n          if (self._entryQueue.length > TOO_FAR_BEHIND) {\n            var lastEntry = self._entryQueue.pop();\n            self._entryQueue.clear();\n\n            self._onSkippedEntriesHook.each(function (callback) {\n              callback();\n              return true;\n            });\n\n            // Free any waitUntilCaughtUp() calls that were waiting for us to\n            // pass something that we just skipped.\n            self._setLastProcessedTS(lastEntry.ts);\n            continue;\n          }\n\n          var doc = self._entryQueue.shift();\n\n          if (!(doc.ns && doc.ns.length > self._dbName.length + 1 &&\n                doc.ns.substr(0, self._dbName.length + 1) ===\n                (self._dbName + '.'))) {\n            throw new Error(\"Unexpected ns\");\n          }\n\n          var trigger = {collection: doc.ns.substr(self._dbName.length + 1),\n                         dropCollection: false,\n                         dropDatabase: false,\n                         op: doc};\n\n          // Is it a special command and the collection name is hidden somewhere\n          // in operator?\n          if (trigger.collection === \"$cmd\") {\n            if (doc.o.dropDatabase) {\n              delete trigger.collection;\n              trigger.dropDatabase = true;\n            } else if (_.has(doc.o, 'drop')) {\n              trigger.collection = doc.o.drop;\n              trigger.dropCollection = true;\n              trigger.id = null;\n            } else {\n              throw Error(\"Unknown command \" + JSON.stringify(doc));\n            }\n          } else {\n            // All other ops have an id.\n            trigger.id = idForOp(doc);\n          }\n\n          self._crossbar.fire(trigger);\n\n          // Now that we've processed this operation, process pending\n          // sequencers.\n          if (!doc.ts)\n            throw Error(\"oplog entry without ts: \" + EJSON.stringify(doc));\n          self._setLastProcessedTS(doc.ts);\n        }\n      } finally {\n        self._workerActive = false;\n      }\n    });\n  },\n  _setLastProcessedTS: function (ts) {\n    var self = this;\n    self._lastProcessedTS = ts;\n    while (!_.isEmpty(self._catchingUpFutures)\n           && self._catchingUpFutures[0].ts.lessThanOrEqual(\n             self._lastProcessedTS)) {\n      var sequencer = self._catchingUpFutures.shift();\n      sequencer.future.return();\n    }\n  }\n});\n"
  },
  {
    "path": "packages/mongo/oplog_tests.js",
    "content": "var OplogCollection = new Mongo.Collection(\"oplog-\" + Random.id());\n\nTinytest.add(\"mongo-livedata - oplog - cursorSupported\", function (test) {\n  var oplogEnabled =\n        !!MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle;\n\n  var supported = function (expected, selector, options) {\n    var cursor = OplogCollection.find(selector, options);\n    var handle = cursor.observeChanges({added: function () {}});\n    // If there's no oplog at all, we shouldn't ever use it.\n    if (!oplogEnabled)\n      expected = false;\n    test.equal(!!handle._multiplexer._observeDriver._usesOplog, expected);\n    handle.stop();\n  };\n\n  supported(true, \"asdf\");\n  supported(true, 1234);\n  supported(true, new Mongo.ObjectID());\n\n  supported(true, {_id: \"asdf\"});\n  supported(true, {_id: 1234});\n  supported(true, {_id: new Mongo.ObjectID()});\n\n  supported(true, {foo: \"asdf\",\n                   bar: 1234,\n                   baz: new Mongo.ObjectID(),\n                   eeney: true,\n                   miney: false,\n                   moe: null});\n\n  supported(true, {});\n\n  supported(true, {$and: [{foo: \"asdf\"}, {bar: \"baz\"}]});\n  supported(true, {foo: {x: 1}});\n  supported(true, {foo: {$gt: 1}});\n  supported(true, {foo: [1, 2, 3]});\n\n  // No $where.\n  supported(false, {$where: \"xxx\"});\n  supported(false, {$and: [{foo: \"adsf\"}, {$where: \"xxx\"}]});\n  // No geoqueries.\n  supported(false, {x: {$near: [1,1]}});\n  // Nothing Minimongo doesn't understand.  (Minimongo happens to fail to\n  // implement $elemMatch inside $all which MongoDB supports.)\n  supported(false, {x: {$all: [{$elemMatch: {y: 2}}]}});\n\n  supported(true, {}, { sort: {x:1} });\n  supported(true, {}, { sort: {x:1}, limit: 5 });\n  supported(false, {}, { sort: {$natural:1}, limit: 5 });\n  supported(false, {}, { limit: 5 });\n  supported(false, {}, { skip: 2, limit: 5 });\n  supported(false, {}, { skip: 2 });\n});\n\nprocess.env.MONGO_OPLOG_URL && testAsyncMulti(\n  \"mongo-livedata - oplog - entry skipping\", [\n    function (test, expect) {\n      var self = this;\n      self.collectionName = Random.id();\n      self.collection = new Mongo.Collection(self.collectionName);\n      self.collection._ensureIndex({species: 1});\n\n      // Fill collection with lots of irrelevant objects (red cats) and some\n      // relevant ones (blue dogs).\n      self.IRRELEVANT_SIZE = 15000;\n      self.RELEVANT_SIZE = 10;\n      var docs = [];\n      var i;\n      for (i = 0; i < self.IRRELEVANT_SIZE; ++i) {\n        docs.push({\n          name: \"cat \" + i,\n          species: 'cat',\n          color: 'red'\n        });\n      }\n      for (i = 0; i < self.RELEVANT_SIZE; ++i) {\n        docs.push({\n          name: \"dog \" + i,\n          species: 'dog',\n          color: 'blue'\n        });\n      }\n      // XXX implement bulk insert #1255\n      var rawCollection = self.collection.rawCollection();\n      rawCollection.insert(docs, Meteor.bindEnvironment(expect(function (err) {\n        test.isFalse(err);\n      })));\n    },\n    function (test, expect) {\n      var self = this;\n\n      test.equal(self.collection.find().count(),\n                 self.IRRELEVANT_SIZE + self.RELEVANT_SIZE);\n\n      var blueDog5Id = null;\n      var gotSpot = false;\n\n      // Watch for blue dogs.\n      self.subHandle =\n        self.collection.find({species: 'dog', color: 'blue'}).observeChanges({\n          added: function (id, fields) {\n            if (fields.name === 'dog 5')\n              blueDog5Id = id;\n          },\n          changed: function (id, fields) {\n            if (EJSON.equals(id, blueDog5Id) && fields.name === 'spot')\n              gotSpot = true;\n          }\n        });\n      test.isTrue(self.subHandle._multiplexer._observeDriver._usesOplog);\n      test.isTrue(blueDog5Id);\n      test.isFalse(gotSpot);\n\n      self.skipped = false;\n      self.skipHandle =\n        MongoInternals.defaultRemoteCollectionDriver().mongo\n        ._oplogHandle.onSkippedEntries(function () {\n          self.skipped = true;\n        });\n\n      // Dye all the cats blue. This adds lots of oplog mentries that look like\n      // they might in theory be relevant (since they say \"something you didn't\n      // know about is now blue\", and who knows, maybe it's a dog) which puts\n      // the OplogObserveDriver into FETCHING mode, which performs poorly.\n      self.collection.update({species: 'cat'},\n                             {$set: {color: 'blue'}},\n                             {multi: true});\n      self.collection.update(blueDog5Id, {$set: {name: 'spot'}});\n\n      // We ought to see the spot change soon!  It's important to keep this\n      // timeout relatively small (ie, small enough that if we set\n      // $METEOR_OPLOG_TOO_FAR_BEHIND to something enormous, say 200000, that\n      // the test fails).\n      pollUntil(expect, function () {\n        return gotSpot;\n      }, 2000);\n    },\n    function (test, expect) {\n      var self = this;\n      test.isTrue(self.skipped);\n\n      self.skipHandle.stop();\n      self.subHandle.stop();\n      self.collection.remove({});\n    }\n  ]\n);\n"
  },
  {
    "path": "packages/mongo/package.js",
    "content": "// XXX We should revisit how we factor MongoDB support into (1) the\n// server-side node.js driver [which you might use independently of\n// livedata, after all], (2) minimongo [ditto], and (3) Collection,\n// which is the class that glues the two of them to Livedata, but also\n// is generally the \"public interface for newbies\" to Mongo in the\n// Meteor universe. We want to allow the components to be used\n// independently, but we don't want to overwhelm the user with\n// minutiae.\n\nPackage.describe({\n  summary: \"Adaptor for using MongoDB and Minimongo over DDP\",\n  version: '1.1.9_1'\n});\n\nNpm.depends({\n  \"mongodb-uri\": \"0.9.7\"\n});\n\nNpm.strip({\n  mongodb: [\"test/\"]\n});\n\nPackage.onUse(function (api) {\n  api.use('npm-mongo', 'server');\n  api.use('allow-deny');\n\n  api.use([\n    'random',\n    'ejson',\n    'underscore',\n    'minimongo',\n    'ddp',\n    'tracker',\n    'diff-sequence',\n    'mongo-id',\n    'check',\n    'ecmascript'\n  ]);\n\n  // Binary Heap data structure is used to optimize oplog observe driver\n  // performance.\n  api.use('binary-heap', 'server');\n\n  // Allow us to detect 'insecure'.\n  api.use('insecure', {weak: true});\n\n  // Allow us to detect 'autopublish', and publish collections if it's loaded.\n  api.use('autopublish', 'server', {weak: true});\n\n  // Allow us to detect 'disable-oplog', which turns off oplog tailing for your\n  // app even if it's configured in the environment. (This package will be\n  // probably be removed before 1.0.)\n  api.use('disable-oplog', 'server', {weak: true});\n\n  // defaultRemoteCollectionDriver gets its deployConfig from something that is\n  // (for questionable reasons) initialized by the webapp package.\n  api.use('webapp', 'server', {weak: true});\n\n  // If the facts package is loaded, publish some statistics.\n  api.use('facts', 'server', {weak: true});\n\n  api.use('callback-hook', 'server');\n\n  // Stuff that should be exposed via a real API, but we haven't yet.\n  api.export('MongoInternals', 'server');\n  // For tests only.\n  api.export('MongoTest', 'server', {testOnly: true});\n  api.export(\"Mongo\");\n\n  api.addFiles(['mongo_driver.js', 'oplog_tailing.js',\n                 'observe_multiplex.js', 'doc_fetcher.js',\n                 'polling_observe_driver.js','oplog_observe_driver.js'],\n                'server');\n  api.addFiles('local_collection_driver.js', ['client', 'server']);\n  api.addFiles('remote_collection_driver.js', 'server');\n  api.addFiles('collection.js', ['client', 'server']);\n});\n\nPackage.onTest(function (api) {\n  api.use('mongo');\n  api.use('check');\n  api.use(['tinytest', 'underscore', 'test-helpers', 'ejson', 'random',\n           'ddp', 'base64']);\n  // XXX test order dependency: the allow_tests \"partial allow\" test\n  // fails if it is run before mongo_livedata_tests.\n  api.addFiles('mongo_livedata_tests.js', ['client', 'server']);\n  api.addFiles('allow_tests.js', ['client', 'server']);\n  api.addFiles('collection_tests.js', ['client', 'server']);\n  api.addFiles('observe_changes_tests.js', ['client', 'server']);\n  api.addFiles('oplog_tests.js', 'server');\n  api.addFiles('doc_fetcher_tests.js', 'server');\n});\n"
  },
  {
    "path": "packages/mongo/polling_observe_driver.js",
    "content": "PollingObserveDriver = function (options) {\n  var self = this;\n\n  self._cursorDescription = options.cursorDescription;\n  self._mongoHandle = options.mongoHandle;\n  self._ordered = options.ordered;\n  self._multiplexer = options.multiplexer;\n  self._stopCallbacks = [];\n  self._stopped = false;\n\n  self._synchronousCursor = self._mongoHandle._createSynchronousCursor(\n    self._cursorDescription);\n\n  // previous results snapshot.  on each poll cycle, diffs against\n  // results drives the callbacks.\n  self._results = null;\n\n  // The number of _pollMongo calls that have been added to self._taskQueue but\n  // have not started running. Used to make sure we never schedule more than one\n  // _pollMongo (other than possibly the one that is currently running). It's\n  // also used by _suspendPolling to pretend there's a poll scheduled. Usually,\n  // it's either 0 (for \"no polls scheduled other than maybe one currently\n  // running\") or 1 (for \"a poll scheduled that isn't running yet\"), but it can\n  // also be 2 if incremented by _suspendPolling.\n  self._pollsScheduledButNotStarted = 0;\n  self._pendingWrites = []; // people to notify when polling completes\n\n  // Make sure to create a separately throttled function for each\n  // PollingObserveDriver object.\n  self._ensurePollIsScheduled = _.throttle(\n    self._unthrottledEnsurePollIsScheduled,\n    self._cursorDescription.options.pollingThrottleMs || 50 /* ms */);\n\n  // XXX figure out if we still need a queue\n  self._taskQueue = new Meteor._SynchronousQueue();\n\n  var listenersHandle = listenAll(\n    self._cursorDescription, function (notification) {\n      // When someone does a transaction that might affect us, schedule a poll\n      // of the database. If that transaction happens inside of a write fence,\n      // block the fence until we've polled and notified observers.\n      var fence = DDPServer._CurrentWriteFence.get();\n      if (fence)\n        self._pendingWrites.push(fence.beginWrite());\n      // Ensure a poll is scheduled... but if we already know that one is,\n      // don't hit the throttled _ensurePollIsScheduled function (which might\n      // lead to us calling it unnecessarily in <pollingThrottleMs> ms).\n      if (self._pollsScheduledButNotStarted === 0)\n        self._ensurePollIsScheduled();\n    }\n  );\n  self._stopCallbacks.push(function () { listenersHandle.stop(); });\n\n  // every once and a while, poll even if we don't think we're dirty, for\n  // eventual consistency with database writes from outside the Meteor\n  // universe.\n  //\n  // For testing, there's an undocumented callback argument to observeChanges\n  // which disables time-based polling and gets called at the beginning of each\n  // poll.\n  if (options._testOnlyPollCallback) {\n    self._testOnlyPollCallback = options._testOnlyPollCallback;\n  } else {\n    var pollingInterval =\n          self._cursorDescription.options.pollingIntervalMs ||\n          self._cursorDescription.options._pollingInterval || // COMPAT with 1.2\n          10 * 1000;\n    var intervalHandle = Meteor.setInterval(\n      _.bind(self._ensurePollIsScheduled, self), pollingInterval);\n    self._stopCallbacks.push(function () {\n      Meteor.clearInterval(intervalHandle);\n    });\n  }\n\n  // Make sure we actually poll soon!\n  self._unthrottledEnsurePollIsScheduled();\n\n  Package.facts && Package.facts.Facts.incrementServerFact(\n    \"mongo-livedata\", \"observe-drivers-polling\", 1);\n};\n\n_.extend(PollingObserveDriver.prototype, {\n  // This is always called through _.throttle (except once at startup).\n  _unthrottledEnsurePollIsScheduled: function () {\n    var self = this;\n    if (self._pollsScheduledButNotStarted > 0)\n      return;\n    ++self._pollsScheduledButNotStarted;\n    self._taskQueue.queueTask(function () {\n      self._pollMongo();\n    });\n  },\n\n  // test-only interface for controlling polling.\n  //\n  // _suspendPolling blocks until any currently running and scheduled polls are\n  // done, and prevents any further polls from being scheduled. (new\n  // ObserveHandles can be added and receive their initial added callbacks,\n  // though.)\n  //\n  // _resumePolling immediately polls, and allows further polls to occur.\n  _suspendPolling: function() {\n    var self = this;\n    // Pretend that there's another poll scheduled (which will prevent\n    // _ensurePollIsScheduled from queueing any more polls).\n    ++self._pollsScheduledButNotStarted;\n    // Now block until all currently running or scheduled polls are done.\n    self._taskQueue.runTask(function() {});\n\n    // Confirm that there is only one \"poll\" (the fake one we're pretending to\n    // have) scheduled.\n    if (self._pollsScheduledButNotStarted !== 1)\n      throw new Error(\"_pollsScheduledButNotStarted is \" +\n                      self._pollsScheduledButNotStarted);\n  },\n  _resumePolling: function() {\n    var self = this;\n    // We should be in the same state as in the end of _suspendPolling.\n    if (self._pollsScheduledButNotStarted !== 1)\n      throw new Error(\"_pollsScheduledButNotStarted is \" +\n                      self._pollsScheduledButNotStarted);\n    // Run a poll synchronously (which will counteract the\n    // ++_pollsScheduledButNotStarted from _suspendPolling).\n    self._taskQueue.runTask(function () {\n      self._pollMongo();\n    });\n  },\n\n  _pollMongo: function () {\n    var self = this;\n    --self._pollsScheduledButNotStarted;\n\n    if (self._stopped)\n      return;\n\n    var first = false;\n    var oldResults = self._results;\n    if (!oldResults) {\n      first = true;\n      // XXX maybe use OrderedDict instead?\n      oldResults = self._ordered ? [] : new LocalCollection._IdMap;\n    }\n\n    self._testOnlyPollCallback && self._testOnlyPollCallback();\n\n    // Save the list of pending writes which this round will commit.\n    var writesForCycle = self._pendingWrites;\n    self._pendingWrites = [];\n\n    // Get the new query results. (This yields.)\n    try {\n      var newResults = self._synchronousCursor.getRawObjects(self._ordered);\n    } catch (e) {\n      if (first && typeof(e.code) === 'number') {\n        // This is an error document sent to us by mongod, not a connection\n        // error generated by the client. And we've never seen this query work\n        // successfully. Probably it's a bad selector or something, so we should\n        // NOT retry. Instead, we should halt the observe (which ends up calling\n        // `stop` on us).\n        self._multiplexer.queryError(\n          new Error(\n            \"Exception while polling query \" +\n              JSON.stringify(self._cursorDescription) + \": \" + e.message));\n        return;\n      }\n\n      // getRawObjects can throw if we're having trouble talking to the\n      // database.  That's fine --- we will repoll later anyway. But we should\n      // make sure not to lose track of this cycle's writes.\n      // (It also can throw if there's just something invalid about this query;\n      // unfortunately the ObserveDriver API doesn't provide a good way to\n      // \"cancel\" the observe from the inside in this case.\n      Array.prototype.push.apply(self._pendingWrites, writesForCycle);\n      Meteor._debug(\"Exception while polling query \" +\n                    JSON.stringify(self._cursorDescription) + \": \" + e.stack);\n      return;\n    }\n\n    // Run diffs.\n    if (!self._stopped) {\n      LocalCollection._diffQueryChanges(\n        self._ordered, oldResults, newResults, self._multiplexer);\n    }\n\n    // Signals the multiplexer to allow all observeChanges calls that share this\n    // multiplexer to return. (This happens asynchronously, via the\n    // multiplexer's queue.)\n    if (first)\n      self._multiplexer.ready();\n\n    // Replace self._results atomically.  (This assignment is what makes `first`\n    // stay through on the next cycle, so we've waited until after we've\n    // committed to ready-ing the multiplexer.)\n    self._results = newResults;\n\n    // Once the ObserveMultiplexer has processed everything we've done in this\n    // round, mark all the writes which existed before this call as\n    // commmitted. (If new writes have shown up in the meantime, there'll\n    // already be another _pollMongo task scheduled.)\n    self._multiplexer.onFlush(function () {\n      _.each(writesForCycle, function (w) {\n        w.committed();\n      });\n    });\n  },\n\n  stop: function () {\n    var self = this;\n    self._stopped = true;\n    _.each(self._stopCallbacks, function (c) { c(); });\n    // Release any write fences that are waiting on us.\n    _.each(self._pendingWrites, function (w) {\n      w.committed();\n    });\n    Package.facts && Package.facts.Facts.incrementServerFact(\n      \"mongo-livedata\", \"observe-drivers-polling\", -1);\n  }\n});\n"
  },
  {
    "path": "packages/mongo/remote_collection_driver.js",
    "content": "MongoInternals.RemoteCollectionDriver = function (\n  mongo_url, options) {\n  var self = this;\n  self.mongo = new MongoConnection(mongo_url, options);\n};\n\n_.extend(MongoInternals.RemoteCollectionDriver.prototype, {\n  open: function (name) {\n    var self = this;\n    var ret = {};\n    _.each(\n      ['find', 'findOne', 'insert', 'update', 'upsert',\n       'remove', '_ensureIndex', '_dropIndex', '_createCappedCollection',\n       'dropCollection', 'rawCollection'],\n      function (m) {\n        ret[m] = _.bind(self.mongo[m], self.mongo, name);\n      });\n    return ret;\n  }\n});\n\n\n// Create the singleton RemoteCollectionDriver only on demand, so we\n// only require Mongo configuration if it's actually used (eg, not if\n// you're only trying to receive data from a remote DDP server.)\nMongoInternals.defaultRemoteCollectionDriver = _.once(function () {\n  var connectionOptions = {};\n\n  var mongoUrl = process.env.MONGO_URL;\n\n  if (process.env.MONGO_OPLOG_URL) {\n    connectionOptions.oplogUrl = process.env.MONGO_OPLOG_URL;\n  }\n\n  if (! mongoUrl)\n    throw new Error(\"MONGO_URL must be set in environment\");\n\n  return new MongoInternals.RemoteCollectionDriver(mongoUrl, connectionOptions);\n});\n"
  },
  {
    "path": "packages/mongo-id/id.js",
    "content": "MongoID = {};\n\nMongoID._looksLikeObjectID = function (str) {\n  return str.length === 24 && str.match(/^[0-9a-f]*$/);\n};\n\nMongoID.ObjectID = function (hexString) {\n  //random-based impl of Mongo ObjectID\n  var self = this;\n  if (hexString) {\n    hexString = hexString.toLowerCase();\n    if (!MongoID._looksLikeObjectID(hexString)) {\n      throw new Error(\"Invalid hexadecimal string for creating an ObjectID\");\n    }\n    // meant to work with _.isEqual(), which relies on structural equality\n    self._str = hexString;\n  } else {\n    self._str = Random.hexString(24);\n  }\n};\n\nMongoID.ObjectID.prototype.toString = function () {\n  var self = this;\n  return \"ObjectID(\\\"\" + self._str + \"\\\")\";\n};\n\nMongoID.ObjectID.prototype.equals = function (other) {\n  var self = this;\n  return other instanceof MongoID.ObjectID &&\n    self.valueOf() === other.valueOf();\n};\n\nMongoID.ObjectID.prototype.clone = function () {\n  var self = this;\n  return new MongoID.ObjectID(self._str);\n};\n\nMongoID.ObjectID.prototype.typeName = function() {\n  return \"oid\";\n};\n\nMongoID.ObjectID.prototype.getTimestamp = function() {\n  var self = this;\n  return parseInt(self._str.substr(0, 8), 16);\n};\n\nMongoID.ObjectID.prototype.valueOf =\n    MongoID.ObjectID.prototype.toJSONValue =\n    MongoID.ObjectID.prototype.toHexString =\n    function () { return this._str; };\n\nEJSON.addType(\"oid\",  function (str) {\n  return new MongoID.ObjectID(str);\n});\n\nMongoID.idStringify = function (id) {\n  if (id instanceof MongoID.ObjectID) {\n    return id.valueOf();\n  } else if (typeof id === 'string') {\n    if (id === \"\") {\n      return id;\n    } else if (id.substr(0, 1) === \"-\" || // escape previously dashed strings\n               id.substr(0, 1) === \"~\" || // escape escaped numbers, true, false\n               MongoID._looksLikeObjectID(id) || // escape object-id-form strings\n               id.substr(0, 1) === '{') { // escape object-form strings, for maybe implementing later\n      return \"-\" + id;\n    } else {\n      return id; // other strings go through unchanged.\n    }\n  } else if (id === undefined) {\n    return '-';\n  } else if (typeof id === 'object' && id !== null) {\n    throw new Error(\"Meteor does not currently support objects other than ObjectID as ids\");\n  } else { // Numbers, true, false, null\n    return \"~\" + JSON.stringify(id);\n  }\n};\n\n\nMongoID.idParse = function (id) {\n  if (id === \"\") {\n    return id;\n  } else if (id === '-') {\n    return undefined;\n  } else if (id.substr(0, 1) === '-') {\n    return id.substr(1);\n  } else if (id.substr(0, 1) === '~') {\n    return JSON.parse(id.substr(1));\n  } else if (MongoID._looksLikeObjectID(id)) {\n    return new MongoID.ObjectID(id);\n  } else {\n    return id;\n  }\n};\n\n"
  },
  {
    "path": "packages/mongo-id/package.js",
    "content": "Package.describe({\n  summary: \"JS simulation of MongoDB ObjectIDs\",\n  version: '1.0.5',\n  documentation: null\n});\n\nPackage.onUse(function (api) {\n  api.export('MongoID');\n  api.use(['ejson', 'id-map', 'random']);\n  api.addFiles([\n    'id.js'\n  ]);\n});\n"
  },
  {
    "path": "packages/mongo-livedata/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/mongo-livedata/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/mongo-livedata/package.js",
    "content": "Package.describe({\n  summary: \"Moved to the 'mongo' package\",\n  version: '1.0.12'\n});\n\nPackage.onUse(function (api) {\n  api.imply(\"mongo\");\n});\n"
  },
  {
    "path": "packages/non-core/README",
    "content": "As of Meteor 0.9.0, Meteor supports packages with OS-specific builds (such as\npackages that use binary npm modules). This allows you to deploy apps from one\nplatform to another, as long as the package has already published to the package\nserver in the appropriate target architecture.\n\nHowever, this only works if the package can be loaded from the server at all; it\ndoes not work if the package is only available as local source code in your app,\nor in the main meteor tree if you're running meteor from a git checkout.\n\nSpecifically, this means that packages *in the Meteor core* which have\nOS-specific dependencies will prevent apps from being deployed, if meteor is\nbeing run from the git checkout. To simplify this, we're taking the OS-specific\ndependencies of core packages and moving them to these packages, which are *NOT*\nin \"the core\". In order to run meteor from a checkout, these packages must be\nalready published to the server.  Fortunately, they won't change very\nfrequently.\n"
  },
  {
    "path": "packages/non-core/jquery-history/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/non-core/jquery-history/history.adapter.jquery.js",
    "content": "/**\n * History.js jQuery Adapter\n * @author Benjamin Arthur Lupton <contact@balupton.com>\n * @copyright 2010-2011 Benjamin Arthur Lupton <contact@balupton.com>\n * @license New BSD License <http://creativecommons.org/licenses/BSD/>\n */\n\n// Closure\n(function(window,undefined){\n\t\"use strict\";\n\n\t// Localise Globals\n\tvar\n\t\tHistory = window.History = window.History||{},\n\t\tjQuery = window.jQuery;\n\n\t// Check Existence\n\tif ( typeof History.Adapter !== 'undefined' ) {\n\t\tthrow new Error('History.js Adapter has already been loaded...');\n\t}\n\n\t// Add the Adapter\n\tHistory.Adapter = {\n\t\t/**\n\t\t * History.Adapter.bind(el,event,callback)\n\t\t * @param {Element|string} el\n\t\t * @param {string} event - custom and standard events\n\t\t * @param {function} callback\n\t\t * @return {void}\n\t\t */\n\t\tbind: function(el,event,callback){\n\t\t\tjQuery(el).bind(event,callback);\n\t\t},\n\n\t\t/**\n\t\t * History.Adapter.trigger(el,event)\n\t\t * @param {Element|string} el\n\t\t * @param {string} event - custom and standard events\n\t\t * @param {Object=} extra - a object of extra event data (optional)\n\t\t * @return {void}\n\t\t */\n\t\ttrigger: function(el,event,extra){\n\t\t\tjQuery(el).trigger(event,extra);\n\t\t},\n\n\t\t/**\n\t\t * History.Adapter.extractEventData(key,event,extra)\n\t\t * @param {string} key - key for the event data to extract\n\t\t * @param {string} event - custom and standard events\n\t\t * @param {Object=} extra - a object of extra event data (optional)\n\t\t * @return {mixed}\n\t\t */\n\t\textractEventData: function(key,event,extra){\n\t\t\t// jQuery Native then jQuery Custom\n\t\t\tvar result = (event && event.originalEvent && event.originalEvent[key]) || (extra && extra[key]) || undefined;\n\n\t\t\t// Return\n\t\t\treturn result;\n\t\t},\n\n\t\t/**\n\t\t * History.Adapter.onDomLoad(callback)\n\t\t * @param {function} callback\n\t\t * @return {void}\n\t\t */\n\t\tonDomLoad: function(callback) {\n\t\t\tjQuery(callback);\n\t\t}\n\t};\n\n\t// Try and Initialise History\n\tif ( typeof History.init !== 'undefined' ) {\n\t\tHistory.init();\n\t}\n\n})(window);\n\n"
  },
  {
    "path": "packages/non-core/jquery-history/history.html4.js",
    "content": "/**\n * History.js HTML4 Support\n * Depends on the HTML5 Support\n * @author Benjamin Arthur Lupton <contact@balupton.com>\n * @copyright 2010-2011 Benjamin Arthur Lupton <contact@balupton.com>\n * @license New BSD License <http://creativecommons.org/licenses/BSD/>\n */\n\n(function(window,undefined){\n\t\"use strict\";\n\n\t// ========================================================================\n\t// Initialise\n\n\t// Localise Globals\n\tvar\n\t\tdocument = window.document, // Make sure we are using the correct document\n\t\tsetTimeout = window.setTimeout||setTimeout,\n\t\tclearTimeout = window.clearTimeout||clearTimeout,\n\t\tsetInterval = window.setInterval||setInterval,\n\t\tHistory = window.History = window.History||{}; // Public History Object\n\n\t// Check Existence\n\tif ( typeof History.initHtml4 !== 'undefined' ) {\n\t\tthrow new Error('History.js HTML4 Support has already been loaded...');\n\t}\n\n\n\t// ========================================================================\n\t// Initialise HTML4 Support\n\n\t// Initialise HTML4 Support\n\tHistory.initHtml4 = function(){\n\t\t// Initialise\n\t\tif ( typeof History.initHtml4.initialized !== 'undefined' ) {\n\t\t\t// Already Loaded\n\t\t\treturn false;\n\t\t}\n\t\telse {\n\t\t\tHistory.initHtml4.initialized = true;\n\t\t}\n\n\n\t\t// ====================================================================\n\t\t// Properties\n\n\t\t/**\n\t\t * History.enabled\n\t\t * Is History enabled?\n\t\t */\n\t\tHistory.enabled = true;\n\n\n\t\t// ====================================================================\n\t\t// Hash Storage\n\n\t\t/**\n\t\t * History.savedHashes\n\t\t * Store the hashes in an array\n\t\t */\n\t\tHistory.savedHashes = [];\n\n\t\t/**\n\t\t * History.isLastHash(newHash)\n\t\t * Checks if the hash is the last hash\n\t\t * @param {string} newHash\n\t\t * @return {boolean} true\n\t\t */\n\t\tHistory.isLastHash = function(newHash){\n\t\t\t// Prepare\n\t\t\tvar oldHash = History.getHashByIndex(),\n\t\t\t\tisLast;\n\n\t\t\t// Check\n\t\t\tisLast = newHash === oldHash;\n\n\t\t\t// Return isLast\n\t\t\treturn isLast;\n\t\t};\n\n\t\t/**\n\t\t * History.saveHash(newHash)\n\t\t * Push a Hash\n\t\t * @param {string} newHash\n\t\t * @return {boolean} true\n\t\t */\n\t\tHistory.saveHash = function(newHash){\n\t\t\t// Check Hash\n\t\t\tif ( History.isLastHash(newHash) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Push the Hash\n\t\t\tHistory.savedHashes.push(newHash);\n\n\t\t\t// Return true\n\t\t\treturn true;\n\t\t};\n\n\t\t/**\n\t\t * History.getHashByIndex()\n\t\t * Gets a hash by the index\n\t\t * @param {integer} index\n\t\t * @return {string}\n\t\t */\n\t\tHistory.getHashByIndex = function(index){\n\t\t\t// Prepare\n\t\t\tvar hash = null;\n\n\t\t\t// Handle\n\t\t\tif ( typeof index === 'undefined' ) {\n\t\t\t\t// Get the last inserted\n\t\t\t\thash = History.savedHashes[History.savedHashes.length-1];\n\t\t\t}\n\t\t\telse if ( index < 0 ) {\n\t\t\t\t// Get from the end\n\t\t\t\thash = History.savedHashes[History.savedHashes.length+index];\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Get from the beginning\n\t\t\t\thash = History.savedHashes[index];\n\t\t\t}\n\n\t\t\t// Return hash\n\t\t\treturn hash;\n\t\t};\n\n\n\t\t// ====================================================================\n\t\t// Discarded States\n\n\t\t/**\n\t\t * History.discardedHashes\n\t\t * A hashed array of discarded hashes\n\t\t */\n\t\tHistory.discardedHashes = {};\n\n\t\t/**\n\t\t * History.discardedStates\n\t\t * A hashed array of discarded states\n\t\t */\n\t\tHistory.discardedStates = {};\n\n\t\t/**\n\t\t * History.discardState(State)\n\t\t * Discards the state by ignoring it through History\n\t\t * @param {object} State\n\t\t * @return {true}\n\t\t */\n\t\tHistory.discardState = function(discardedState,forwardState,backState){\n\t\t\t//History.debug('History.discardState', arguments);\n\t\t\t// Prepare\n\t\t\tvar discardedStateHash = History.getHashByState(discardedState),\n\t\t\t\tdiscardObject;\n\n\t\t\t// Create Discard Object\n\t\t\tdiscardObject = {\n\t\t\t\t'discardedState': discardedState,\n\t\t\t\t'backState': backState,\n\t\t\t\t'forwardState': forwardState\n\t\t\t};\n\n\t\t\t// Add to DiscardedStates\n\t\t\tHistory.discardedStates[discardedStateHash] = discardObject;\n\n\t\t\t// Return true\n\t\t\treturn true;\n\t\t};\n\n\t\t/**\n\t\t * History.discardHash(hash)\n\t\t * Discards the hash by ignoring it through History\n\t\t * @param {string} hash\n\t\t * @return {true}\n\t\t */\n\t\tHistory.discardHash = function(discardedHash,forwardState,backState){\n\t\t\t//History.debug('History.discardState', arguments);\n\t\t\t// Create Discard Object\n\t\t\tvar discardObject = {\n\t\t\t\t'discardedHash': discardedHash,\n\t\t\t\t'backState': backState,\n\t\t\t\t'forwardState': forwardState\n\t\t\t};\n\n\t\t\t// Add to discardedHash\n\t\t\tHistory.discardedHashes[discardedHash] = discardObject;\n\n\t\t\t// Return true\n\t\t\treturn true;\n\t\t};\n\n\t\t/**\n\t\t * History.discardState(State)\n\t\t * Checks to see if the state is discarded\n\t\t * @param {object} State\n\t\t * @return {bool}\n\t\t */\n\t\tHistory.discardedState = function(State){\n\t\t\t// Prepare\n\t\t\tvar StateHash = History.getHashByState(State),\n\t\t\t\tdiscarded;\n\n\t\t\t// Check\n\t\t\tdiscarded = History.discardedStates[StateHash]||false;\n\n\t\t\t// Return true\n\t\t\treturn discarded;\n\t\t};\n\n\t\t/**\n\t\t * History.discardedHash(hash)\n\t\t * Checks to see if the state is discarded\n\t\t * @param {string} State\n\t\t * @return {bool}\n\t\t */\n\t\tHistory.discardedHash = function(hash){\n\t\t\t// Check\n\t\t\tvar discarded = History.discardedHashes[hash]||false;\n\n\t\t\t// Return true\n\t\t\treturn discarded;\n\t\t};\n\n\t\t/**\n\t\t * History.recycleState(State)\n\t\t * Allows a discarded state to be used again\n\t\t * @param {object} data\n\t\t * @param {string} title\n\t\t * @param {string} url\n\t\t * @return {true}\n\t\t */\n\t\tHistory.recycleState = function(State){\n\t\t\t//History.debug('History.recycleState', arguments);\n\t\t\t// Prepare\n\t\t\tvar StateHash = History.getHashByState(State);\n\n\t\t\t// Remove from DiscardedStates\n\t\t\tif ( History.discardedState(State) ) {\n\t\t\t\tdelete History.discardedStates[StateHash];\n\t\t\t}\n\n\t\t\t// Return true\n\t\t\treturn true;\n\t\t};\n\n\n\t\t// ====================================================================\n\t\t// HTML4 HashChange Support\n\n\t\tif ( History.emulated.hashChange ) {\n\t\t\t/*\n\t\t\t * We must emulate the HTML4 HashChange Support by manually checking for hash changes\n\t\t\t */\n\n\t\t\t/**\n\t\t\t * History.hashChangeInit()\n\t\t\t * Init the HashChange Emulation\n\t\t\t */\n\t\t\tHistory.hashChangeInit = function(){\n\t\t\t\t// Define our Checker Function\n\t\t\t\tHistory.checkerFunction = null;\n\n\t\t\t\t// Define some variables that will help in our checker function\n\t\t\t\tvar lastDocumentHash = '',\n\t\t\t\t\tiframeId, iframe,\n\t\t\t\t\tlastIframeHash, checkerRunning;\n\n\t\t\t\t// Handle depending on the browser\n\t\t\t\tif ( History.isInternetExplorer() ) {\n\t\t\t\t\t// IE6 and IE7\n\t\t\t\t\t// We need to use an iframe to emulate the back and forward buttons\n\n\t\t\t\t\t// Create iFrame\n\t\t\t\t\tiframeId = 'historyjs-iframe';\n\t\t\t\t\tiframe = document.createElement('iframe');\n\n\t\t\t\t\t// Adjust iFarme\n\t\t\t\t\tiframe.setAttribute('id', iframeId);\n\t\t\t\t\tiframe.style.display = 'none';\n\n\t\t\t\t\t// Append iFrame\n\t\t\t\t\tdocument.body.appendChild(iframe);\n\n\t\t\t\t\t// Create initial history entry\n\t\t\t\t\tiframe.contentWindow.document.open();\n\t\t\t\t\tiframe.contentWindow.document.close();\n\n\t\t\t\t\t// Define some variables that will help in our checker function\n\t\t\t\t\tlastIframeHash = '';\n\t\t\t\t\tcheckerRunning = false;\n\n\t\t\t\t\t// Define the checker function\n\t\t\t\t\tHistory.checkerFunction = function(){\n\t\t\t\t\t\t// Check Running\n\t\t\t\t\t\tif ( checkerRunning ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Update Running\n\t\t\t\t\t\tcheckerRunning = true;\n\n\t\t\t\t\t\t// Fetch\n\t\t\t\t\t\tvar documentHash = History.getHash()||'',\n\t\t\t\t\t\t\tiframeHash = History.unescapeHash(iframe.contentWindow.document.location.hash)||'';\n\n\t\t\t\t\t\t// The Document Hash has changed (application caused)\n\t\t\t\t\t\tif ( documentHash !== lastDocumentHash ) {\n\t\t\t\t\t\t\t// Equalise\n\t\t\t\t\t\t\tlastDocumentHash = documentHash;\n\n\t\t\t\t\t\t\t// Create a history entry in the iframe\n\t\t\t\t\t\t\tif ( iframeHash !== documentHash ) {\n\t\t\t\t\t\t\t\t//History.debug('hashchange.checker: iframe hash change', 'documentHash (new):', documentHash, 'iframeHash (old):', iframeHash);\n\n\t\t\t\t\t\t\t\t// Equalise\n\t\t\t\t\t\t\t\tlastIframeHash = iframeHash = documentHash;\n\n\t\t\t\t\t\t\t\t// Create History Entry\n\t\t\t\t\t\t\t\tiframe.contentWindow.document.open();\n\t\t\t\t\t\t\t\tiframe.contentWindow.document.close();\n\n\t\t\t\t\t\t\t\t// Update the iframe's hash\n\t\t\t\t\t\t\t\tiframe.contentWindow.document.location.hash = History.escapeHash(documentHash);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Trigger Hashchange Event\n\t\t\t\t\t\t\tHistory.Adapter.trigger(window,'hashchange');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// The iFrame Hash has changed (back button caused)\n\t\t\t\t\t\telse if ( iframeHash !== lastIframeHash ) {\n\t\t\t\t\t\t\t//History.debug('hashchange.checker: iframe hash out of sync', 'iframeHash (new):', iframeHash, 'documentHash (old):', documentHash);\n\n\t\t\t\t\t\t\t// Equalise\n\t\t\t\t\t\t\tlastIframeHash = iframeHash;\n\n\t\t\t\t\t\t\t// Update the Hash\n\t\t\t\t\t\t\tHistory.setHash(iframeHash,false);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Reset Running\n\t\t\t\t\t\tcheckerRunning = false;\n\n\t\t\t\t\t\t// Return true\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// We are not IE\n\t\t\t\t\t// Firefox 1 or 2, Opera\n\n\t\t\t\t\t// Define the checker function\n\t\t\t\t\tHistory.checkerFunction = function(){\n\t\t\t\t\t\t// Prepare\n\t\t\t\t\t\tvar documentHash = History.getHash();\n\n\t\t\t\t\t\t// The Document Hash has changed (application caused)\n\t\t\t\t\t\tif ( documentHash !== lastDocumentHash ) {\n\t\t\t\t\t\t\t// Equalise\n\t\t\t\t\t\t\tlastDocumentHash = documentHash;\n\n\t\t\t\t\t\t\t// Trigger Hashchange Event\n\t\t\t\t\t\t\tHistory.Adapter.trigger(window,'hashchange');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Return true\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Apply the checker function\n\t\t\t\tHistory.intervalList.push(setInterval(History.checkerFunction, History.options.hashChangeInterval));\n\n\t\t\t\t// Done\n\t\t\t\treturn true;\n\t\t\t}; // History.hashChangeInit\n\n\t\t\t// Bind hashChangeInit\n\t\t\tHistory.Adapter.onDomLoad(History.hashChangeInit);\n\n\t\t} // History.emulated.hashChange\n\n\n\t\t// ====================================================================\n\t\t// HTML5 State Support\n\n\t\t// Non-Native pushState Implementation\n\t\tif ( History.emulated.pushState ) {\n\t\t\t/*\n\t\t\t * We must emulate the HTML5 State Management by using HTML4 HashChange\n\t\t\t */\n\n\t\t\t/**\n\t\t\t * History.onHashChange(event)\n\t\t\t * Trigger HTML5's window.onpopstate via HTML4 HashChange Support\n\t\t\t */\n\t\t\tHistory.onHashChange = function(event){\n\t\t\t\t//History.debug('History.onHashChange', arguments);\n\n\t\t\t\t// Prepare\n\t\t\t\tvar currentUrl = ((event && event.newURL) || document.location.href),\n\t\t\t\t\tcurrentHash = History.getHashByUrl(currentUrl),\n\t\t\t\t\tcurrentState = null,\n\t\t\t\t\tcurrentStateHash = null,\n\t\t\t\t\tcurrentStateHashExits = null,\n\t\t\t\t\tdiscardObject;\n\n\t\t\t\t// Check if we are the same state\n\t\t\t\tif ( History.isLastHash(currentHash) ) {\n\t\t\t\t\t// There has been no change (just the page's hash has finally propagated)\n\t\t\t\t\t//History.debug('History.onHashChange: no change');\n\t\t\t\t\tHistory.busy(false);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Reset the double check\n\t\t\t\tHistory.doubleCheckComplete();\n\n\t\t\t\t// Store our location for use in detecting back/forward direction\n\t\t\t\tHistory.saveHash(currentHash);\n\n\t\t\t\t// Expand Hash\n\t\t\t\tif ( currentHash && History.isTraditionalAnchor(currentHash) ) {\n\t\t\t\t\t//History.debug('History.onHashChange: traditional anchor', currentHash);\n\t\t\t\t\t// Traditional Anchor Hash\n\t\t\t\t\tHistory.Adapter.trigger(window,'anchorchange');\n\t\t\t\t\tHistory.busy(false);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Create State\n\t\t\t\tcurrentState = History.extractState(History.getFullUrl(currentHash||document.location.href,false),true);\n\n\t\t\t\t// Check if we are the same state\n\t\t\t\tif ( History.isLastSavedState(currentState) ) {\n\t\t\t\t\t//History.debug('History.onHashChange: no change');\n\t\t\t\t\t// There has been no change (just the page's hash has finally propagated)\n\t\t\t\t\tHistory.busy(false);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Create the state Hash\n\t\t\t\tcurrentStateHash = History.getHashByState(currentState);\n\n\t\t\t\t// Check if we are DiscardedState\n\t\t\t\tdiscardObject = History.discardedState(currentState);\n\t\t\t\tif ( discardObject ) {\n\t\t\t\t\t// Ignore this state as it has been discarded and go back to the state before it\n\t\t\t\t\tif ( History.getHashByIndex(-2) === History.getHashByState(discardObject.forwardState) ) {\n\t\t\t\t\t\t// We are going backwards\n\t\t\t\t\t\t//History.debug('History.onHashChange: go backwards');\n\t\t\t\t\t\tHistory.back(false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We are going forwards\n\t\t\t\t\t\t//History.debug('History.onHashChange: go forwards');\n\t\t\t\t\t\tHistory.forward(false);\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Push the new HTML5 State\n\t\t\t\t//History.debug('History.onHashChange: success hashchange');\n\t\t\t\tHistory.pushState(currentState.data,currentState.title,currentState.url,false);\n\n\t\t\t\t// End onHashChange closure\n\t\t\t\treturn true;\n\t\t\t};\n\t\t\tHistory.Adapter.bind(window,'hashchange',History.onHashChange);\n\n\t\t\t/**\n\t\t\t * History.pushState(data,title,url)\n\t\t\t * Add a new State to the history object, become it, and trigger onpopstate\n\t\t\t * We have to trigger for HTML4 compatibility\n\t\t\t * @param {object} data\n\t\t\t * @param {string} title\n\t\t\t * @param {string} url\n\t\t\t * @return {true}\n\t\t\t */\n\t\t\tHistory.pushState = function(data,title,url,queue){\n\t\t\t\t//History.debug('History.pushState: called', arguments);\n\n\t\t\t\t// Check the State\n\t\t\t\tif ( History.getHashByUrl(url) ) {\n\t\t\t\t\tthrow new Error('History.js does not support states with fragement-identifiers (hashes/anchors).');\n\t\t\t\t}\n\n\t\t\t\t// Handle Queueing\n\t\t\t\tif ( queue !== false && History.busy() ) {\n\t\t\t\t\t// Wait + Push to Queue\n\t\t\t\t\t//History.debug('History.pushState: we must wait', arguments);\n\t\t\t\t\tHistory.pushQueue({\n\t\t\t\t\t\tscope: History,\n\t\t\t\t\t\tcallback: History.pushState,\n\t\t\t\t\t\targs: arguments,\n\t\t\t\t\t\tqueue: queue\n\t\t\t\t\t});\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Make Busy\n\t\t\t\tHistory.busy(true);\n\n\t\t\t\t// Fetch the State Object\n\t\t\t\tvar newState = History.createStateObject(data,title,url),\n\t\t\t\t\tnewStateHash = History.getHashByState(newState),\n\t\t\t\t\toldState = History.getState(false),\n\t\t\t\t\toldStateHash = History.getHashByState(oldState),\n\t\t\t\t\thtml4Hash = History.getHash();\n\n\t\t\t\t// Store the newState\n\t\t\t\tHistory.storeState(newState);\n\t\t\t\tHistory.expectedStateId = newState.id;\n\n\t\t\t\t// Recycle the State\n\t\t\t\tHistory.recycleState(newState);\n\n\t\t\t\t// Force update of the title\n\t\t\t\tHistory.setTitle(newState);\n\n\t\t\t\t// Check if we are the same State\n\t\t\t\tif ( newStateHash === oldStateHash ) {\n\t\t\t\t\t//History.debug('History.pushState: no change', newStateHash);\n\t\t\t\t\tHistory.busy(false);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Update HTML4 Hash\n\t\t\t\tif ( newStateHash !== html4Hash && newStateHash !== History.getShortUrl(document.location.href) ) {\n\t\t\t\t\t//History.debug('History.pushState: update hash', newStateHash, html4Hash);\n\t\t\t\t\tHistory.setHash(newStateHash,false);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Update HTML5 State\n\t\t\t\tHistory.saveState(newState);\n\n\t\t\t\t// Fire HTML5 Event\n\t\t\t\t//History.debug('History.pushState: trigger popstate');\n\t\t\t\tHistory.Adapter.trigger(window,'statechange');\n\t\t\t\tHistory.busy(false);\n\n\t\t\t\t// End pushState closure\n\t\t\t\treturn true;\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * History.replaceState(data,title,url)\n\t\t\t * Replace the State and trigger onpopstate\n\t\t\t * We have to trigger for HTML4 compatibility\n\t\t\t * @param {object} data\n\t\t\t * @param {string} title\n\t\t\t * @param {string} url\n\t\t\t * @return {true}\n\t\t\t */\n\t\t\tHistory.replaceState = function(data,title,url,queue){\n\t\t\t\t//History.debug('History.replaceState: called', arguments);\n\n\t\t\t\t// Check the State\n\t\t\t\tif ( History.getHashByUrl(url) ) {\n\t\t\t\t\tthrow new Error('History.js does not support states with fragement-identifiers (hashes/anchors).');\n\t\t\t\t}\n\n\t\t\t\t// Handle Queueing\n\t\t\t\tif ( queue !== false && History.busy() ) {\n\t\t\t\t\t// Wait + Push to Queue\n\t\t\t\t\t//History.debug('History.replaceState: we must wait', arguments);\n\t\t\t\t\tHistory.pushQueue({\n\t\t\t\t\t\tscope: History,\n\t\t\t\t\t\tcallback: History.replaceState,\n\t\t\t\t\t\targs: arguments,\n\t\t\t\t\t\tqueue: queue\n\t\t\t\t\t});\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Make Busy\n\t\t\t\tHistory.busy(true);\n\n\t\t\t\t// Fetch the State Objects\n\t\t\t\tvar newState        = History.createStateObject(data,title,url),\n\t\t\t\t\toldState        = History.getState(false),\n\t\t\t\t\tpreviousState   = History.getStateByIndex(-2);\n\n\t\t\t\t// Discard Old State\n\t\t\t\tHistory.discardState(oldState,newState,previousState);\n\n\t\t\t\t// Alias to PushState\n\t\t\t\tHistory.pushState(newState.data,newState.title,newState.url,false);\n\n\t\t\t\t// End replaceState closure\n\t\t\t\treturn true;\n\t\t\t};\n\n\t\t} // History.emulated.pushState\n\n\n\n\t\t// ====================================================================\n\t\t// Initialise\n\n\t\t// Non-Native pushState Implementation\n\t\tif ( History.emulated.pushState ) {\n\t\t\t/**\n\t\t\t * Ensure initial state is handled correctly\n\t\t\t */\n\t\t\tif ( History.getHash() && !History.emulated.hashChange ) {\n\t\t\t\tHistory.Adapter.onDomLoad(function(){\n\t\t\t\t\tHistory.Adapter.trigger(window,'hashchange');\n\t\t\t\t});\n\t\t\t}\n\n\t\t} // History.emulated.pushState\n\n\t}; // History.initHtml4\n\n\t// Try and Initialise History\n\tif ( typeof History.init !== 'undefined' ) {\n\t\tHistory.init();\n\t}\n\n})(window);\n"
  },
  {
    "path": "packages/non-core/jquery-history/history.js",
    "content": "/**\n * History.js Core\n * @author Benjamin Arthur Lupton <contact@balupton.com>\n * @copyright 2010-2011 Benjamin Arthur Lupton <contact@balupton.com>\n * @license New BSD License <http://creativecommons.org/licenses/BSD/>\n */\n\n(function(window,undefined){\n\t\"use strict\";\n\n\t// ========================================================================\n\t// Initialise\n\n\t// Localise Globals\n\tvar\n\t\tconsole = window.console||undefined, // Prevent a JSLint complain\n\t\tdocument = window.document, // Make sure we are using the correct document\n\t\tnavigator = window.navigator, // Make sure we are using the correct navigator\n\t\tsessionStorage = window.sessionStorage||false, // sessionStorage\n\t\tsetTimeout = window.setTimeout,\n\t\tclearTimeout = window.clearTimeout,\n\t\tsetInterval = window.setInterval,\n\t\tclearInterval = window.clearInterval,\n\t\tJSON = window.JSON,\n\t\talert = window.alert,\n\t\tHistory = window.History = window.History||{}, // Public History Object\n\t\thistory = window.history; // Old History Object\n\n\t// MooTools Compatibility\n\tJSON.stringify = JSON.stringify||JSON.encode;\n\tJSON.parse = JSON.parse||JSON.decode;\n\n\t// Check Existence\n\tif ( typeof History.init !== 'undefined' ) {\n\t\tthrow new Error('History.js Core has already been loaded...');\n\t}\n\n\t// Initialise History\n\tHistory.init = function(){\n\t\t// Check Load Status of Adapter\n\t\tif ( typeof History.Adapter === 'undefined' ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check Load Status of Core\n\t\tif ( typeof History.initCore !== 'undefined' ) {\n\t\t\tHistory.initCore();\n\t\t}\n\n\t\t// Check Load Status of HTML4 Support\n\t\tif ( typeof History.initHtml4 !== 'undefined' ) {\n\t\t\tHistory.initHtml4();\n\t\t}\n\n\t\t// Return true\n\t\treturn true;\n\t};\n\n\n\t// ========================================================================\n\t// Initialise Core\n\n\t// Initialise Core\n\tHistory.initCore = function(){\n\t\t// Initialise\n\t\tif ( typeof History.initCore.initialized !== 'undefined' ) {\n\t\t\t// Already Loaded\n\t\t\treturn false;\n\t\t}\n\t\telse {\n\t\t\tHistory.initCore.initialized = true;\n\t\t}\n\n\n\t\t// ====================================================================\n\t\t// Options\n\n\t\t/**\n\t\t * History.options\n\t\t * Configurable options\n\t\t */\n\t\tHistory.options = History.options||{};\n\n\t\t/**\n\t\t * History.options.hashChangeInterval\n\t\t * How long should the interval be before hashchange checks\n\t\t */\n\t\tHistory.options.hashChangeInterval = History.options.hashChangeInterval || 100;\n\n\t\t/**\n\t\t * History.options.safariPollInterval\n\t\t * How long should the interval be before safari poll checks\n\t\t */\n\t\tHistory.options.safariPollInterval = History.options.safariPollInterval || 500;\n\n\t\t/**\n\t\t * History.options.doubleCheckInterval\n\t\t * How long should the interval be before we perform a double check\n\t\t */\n\t\tHistory.options.doubleCheckInterval = History.options.doubleCheckInterval || 500;\n\n\t\t/**\n\t\t * History.options.storeInterval\n\t\t * How long should we wait between store calls\n\t\t */\n\t\tHistory.options.storeInterval = History.options.storeInterval || 1000;\n\n\t\t/**\n\t\t * History.options.busyDelay\n\t\t * How long should we wait between busy events\n\t\t */\n\t\tHistory.options.busyDelay = History.options.busyDelay || 250;\n\n\t\t/**\n\t\t * History.options.debug\n\t\t * If true will enable debug messages to be logged\n\t\t */\n\t\tHistory.options.debug = History.options.debug || false;\n\n\t\t/**\n\t\t * History.options.initialTitle\n\t\t * What is the title of the initial state\n\t\t */\n\t\tHistory.options.initialTitle = History.options.initialTitle || document.title;\n\n\n\t\t// ====================================================================\n\t\t// Interval record\n\n\t\t/**\n\t\t * History.intervalList\n\t\t * List of intervals set, to be cleared when document is unloaded.\n\t\t */\n\t\tHistory.intervalList = [];\n\n\t\t/**\n\t\t * History.clearAllIntervals\n\t\t * Clears all setInterval instances.\n\t\t */\n\t\tHistory.clearAllIntervals = function(){\n\t\t\tvar i, il = History.intervalList;\n\t\t\tif (typeof il !== \"undefined\" && il !== null) {\n\t\t\t\tfor (i = 0; i < il.length; i++) {\n\t\t\t\t\tclearInterval(il[i]);\n\t\t\t\t}\n\t\t\t\tHistory.intervalList = null;\n\t\t\t}\n\t\t};\n\n\n\t\t// ====================================================================\n\t\t// Debug\n\n\t\t/**\n\t\t * History.debug(message,...)\n\t\t * Logs the passed arguments if debug enabled\n\t\t */\n\t\tHistory.debug = function(){\n\t\t\tif ( (History.options.debug||false) ) {\n\t\t\t\tHistory.log.apply(History,arguments);\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * History.log(message,...)\n\t\t * Logs the passed arguments\n\t\t */\n\t\tHistory.log = function(){\n\t\t\t// Prepare\n\t\t\tvar\n\t\t\t\tconsoleExists = !(typeof console === 'undefined' || typeof console.log === 'undefined' || typeof console.log.apply === 'undefined'),\n\t\t\t\ttextarea = document.getElementById('log'),\n\t\t\t\tmessage,\n\t\t\t\ti,n,\n\t\t\t\targs,arg\n\t\t\t\t;\n\n\t\t\t// Write to Console\n\t\t\tif ( consoleExists ) {\n\t\t\t\targs = Array.prototype.slice.call(arguments);\n\t\t\t\tmessage = args.shift();\n\t\t\t\tif ( typeof console.debug !== 'undefined' ) {\n\t\t\t\t\tconsole.debug.apply(console,[message,args]);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tconsole.log.apply(console,[message,args]);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tmessage = (\"\\n\"+arguments[0]+\"\\n\");\n\t\t\t}\n\n\t\t\t// Write to log\n\t\t\tfor ( i=1,n=arguments.length; i<n; ++i ) {\n\t\t\t\targ = arguments[i];\n\t\t\t\tif ( typeof arg === 'object' && typeof JSON !== 'undefined' ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\targ = JSON.stringify(arg);\n\t\t\t\t\t}\n\t\t\t\t\tcatch ( Exception ) {\n\t\t\t\t\t\t// Recursive Object\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tmessage += \"\\n\"+arg+\"\\n\";\n\t\t\t}\n\n\t\t\t// Textarea\n\t\t\tif ( textarea ) {\n\t\t\t\ttextarea.value += message+\"\\n-----\\n\";\n\t\t\t\ttextarea.scrollTop = textarea.scrollHeight - textarea.clientHeight;\n\t\t\t}\n\t\t\t// No Textarea, No Console\n\t\t\telse if ( !consoleExists ) {\n\t\t\t\talert(message);\n\t\t\t}\n\n\t\t\t// Return true\n\t\t\treturn true;\n\t\t};\n\n\n\t\t// ====================================================================\n\t\t// Emulated Status\n\n\t\t/**\n\t\t * History.getInternetExplorerMajorVersion()\n\t\t * Get's the major version of Internet Explorer\n\t\t * @return {integer}\n\t\t * @license Public Domain\n\t\t * @author Benjamin Arthur Lupton <contact@balupton.com>\n\t\t * @author James Padolsey <https://gist.github.com/527683>\n\t\t */\n\t\tHistory.getInternetExplorerMajorVersion = function(){\n\t\t\tvar result = History.getInternetExplorerMajorVersion.cached =\n\t\t\t\t\t(typeof History.getInternetExplorerMajorVersion.cached !== 'undefined')\n\t\t\t\t?\tHistory.getInternetExplorerMajorVersion.cached\n\t\t\t\t:\t(function(){\n\t\t\t\t\t\tvar v = 3,\n\t\t\t\t\t\t\t\tdiv = document.createElement('div'),\n\t\t\t\t\t\t\t\tall = div.getElementsByTagName('i');\n\t\t\t\t\t\twhile ( (div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->') && all[0] ) {}\n\t\t\t\t\t\treturn (v > 4) ? v : false;\n\t\t\t\t\t})()\n\t\t\t\t;\n\t\t\treturn result;\n\t\t};\n\n\t\t/**\n\t\t * History.isInternetExplorer()\n\t\t * Are we using Internet Explorer?\n\t\t * @return {boolean}\n\t\t * @license Public Domain\n\t\t * @author Benjamin Arthur Lupton <contact@balupton.com>\n\t\t */\n\t\tHistory.isInternetExplorer = function(){\n\t\t\tvar result =\n\t\t\t\tHistory.isInternetExplorer.cached =\n\t\t\t\t(typeof History.isInternetExplorer.cached !== 'undefined')\n\t\t\t\t\t?\tHistory.isInternetExplorer.cached\n\t\t\t\t\t:\tBoolean(History.getInternetExplorerMajorVersion())\n\t\t\t\t;\n\t\t\treturn result;\n\t\t};\n\n\t\t/**\n\t\t * History.emulated\n\t\t * Which features require emulating?\n\t\t */\n\t\tHistory.emulated = {\n\t\t\tpushState: !Boolean(\n\t\t\t\twindow.history && window.history.pushState && window.history.replaceState\n\t\t\t\t&& !(\n\t\t\t\t\t(/ Mobile\\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i).test(navigator.userAgent) /* disable for versions of iOS before version 4.3 (8F190) */\n\t\t\t\t\t|| (/AppleWebKit\\/5([0-2]|3[0-2])/i).test(navigator.userAgent) /* disable for the mercury iOS browser, or at least older versions of the webkit engine */\n\t\t\t\t)\n\t\t\t),\n\t\t\thashChange: Boolean(\n\t\t\t\t!(('onhashchange' in window) || ('onhashchange' in document))\n\t\t\t\t||\n\t\t\t\t(History.isInternetExplorer() && History.getInternetExplorerMajorVersion() < 8)\n\t\t\t)\n\t\t};\n\n\t\t/**\n\t\t * History.enabled\n\t\t * Is History enabled?\n\t\t */\n\t\tHistory.enabled = !History.emulated.pushState;\n\n\t\t/**\n\t\t * History.bugs\n\t\t * Which bugs are present\n\t\t */\n\t\tHistory.bugs = {\n\t\t\t/**\n\t\t\t * Safari 5 and Safari iOS 4 fail to return to the correct state once a hash is replaced by a `replaceState` call\n\t\t\t * https://bugs.webkit.org/show_bug.cgi?id=56249\n\t\t\t */\n\t\t\tsetHash: Boolean(!History.emulated.pushState && navigator.vendor === 'Apple Computer, Inc.' && /AppleWebKit\\/5([0-2]|3[0-3])/.test(navigator.userAgent)),\n\n\t\t\t/**\n\t\t\t * Safari 5 and Safari iOS 4 sometimes fail to apply the state change under busy conditions\n\t\t\t * https://bugs.webkit.org/show_bug.cgi?id=42940\n\t\t\t */\n\t\t\tsafariPoll: Boolean(!History.emulated.pushState && navigator.vendor === 'Apple Computer, Inc.' && /AppleWebKit\\/5([0-2]|3[0-3])/.test(navigator.userAgent)),\n\n\t\t\t/**\n\t\t\t * MSIE 6 and 7 sometimes do not apply a hash even it was told to (requiring a second call to the apply function)\n\t\t\t */\n\t\t\tieDoubleCheck: Boolean(History.isInternetExplorer() && History.getInternetExplorerMajorVersion() < 8),\n\n\t\t\t/**\n\t\t\t * MSIE 6 requires the entire hash to be encoded for the hashes to trigger the onHashChange event\n\t\t\t */\n\t\t\thashEscape: Boolean(History.isInternetExplorer() && History.getInternetExplorerMajorVersion() < 7)\n\t\t};\n\n\t\t/**\n\t\t * History.isEmptyObject(obj)\n\t\t * Checks to see if the Object is Empty\n\t\t * @param {Object} obj\n\t\t * @return {boolean}\n\t\t */\n\t\tHistory.isEmptyObject = function(obj) {\n\t\t\tfor ( var name in obj ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\t/**\n\t\t * History.cloneObject(obj)\n\t\t * Clones a object and eliminate all references to the original contexts\n\t\t * @param {Object} obj\n\t\t * @return {Object}\n\t\t */\n\t\tHistory.cloneObject = function(obj) {\n\t\t\tvar hash,newObj;\n\t\t\tif ( obj ) {\n\t\t\t\thash = JSON.stringify(obj);\n\t\t\t\tnewObj = JSON.parse(hash);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tnewObj = {};\n\t\t\t}\n\t\t\treturn newObj;\n\t\t};\n\n\n\t\t// ====================================================================\n\t\t// URL Helpers\n\n\t\t/**\n\t\t * History.getRootUrl()\n\t\t * Turns \"http://mysite.com/dir/page.html?asd\" into \"http://mysite.com\"\n\t\t * @return {String} rootUrl\n\t\t */\n\t\tHistory.getRootUrl = function(){\n\t\t\t// Create\n\t\t\tvar rootUrl = document.location.protocol+'//'+(document.location.hostname||document.location.host);\n\t\t\tif ( document.location.port||false ) {\n\t\t\t\trootUrl += ':'+document.location.port;\n\t\t\t}\n\t\t\trootUrl += '/';\n\n\t\t\t// Return\n\t\t\treturn rootUrl;\n\t\t};\n\n\t\t/**\n\t\t * History.getBaseHref()\n\t\t * Fetches the `href` attribute of the `<base href=\"...\">` element if it exists\n\t\t * @return {String} baseHref\n\t\t */\n\t\tHistory.getBaseHref = function(){\n\t\t\t// Create\n\t\t\tvar\n\t\t\t\tbaseElements = document.getElementsByTagName('base'),\n\t\t\t\tbaseElement = null,\n\t\t\t\tbaseHref = '';\n\n\t\t\t// Test for Base Element\n\t\t\tif ( baseElements.length === 1 ) {\n\t\t\t\t// Prepare for Base Element\n\t\t\t\tbaseElement = baseElements[0];\n\t\t\t\tbaseHref = baseElement.href.replace(/[^\\/]+$/,'');\n\t\t\t}\n\n\t\t\t// Adjust trailing slash\n\t\t\tbaseHref = baseHref.replace(/\\/+$/,'');\n\t\t\tif ( baseHref ) baseHref += '/';\n\n\t\t\t// Return\n\t\t\treturn baseHref;\n\t\t};\n\n\t\t/**\n\t\t * History.getBaseUrl()\n\t\t * Fetches the baseHref or basePageUrl or rootUrl (whichever one exists first)\n\t\t * @return {String} baseUrl\n\t\t */\n\t\tHistory.getBaseUrl = function(){\n\t\t\t// Create\n\t\t\tvar baseUrl = History.getBaseHref()||History.getBasePageUrl()||History.getRootUrl();\n\n\t\t\t// Return\n\t\t\treturn baseUrl;\n\t\t};\n\n\t\t/**\n\t\t * History.getPageUrl()\n\t\t * Fetches the URL of the current page\n\t\t * @return {String} pageUrl\n\t\t */\n\t\tHistory.getPageUrl = function(){\n\t\t\t// Fetch\n\t\t\tvar\n\t\t\t\tState = History.getState(false,false),\n\t\t\t\tstateUrl = (State||{}).url||document.location.href,\n\t\t\t\tpageUrl;\n\n\t\t\t// Create\n\t\t\tpageUrl = stateUrl.replace(/\\/+$/,'').replace(/[^\\/]+$/,function(part,index,string){\n\t\t\t\treturn (/\\./).test(part) ? part : part+'/';\n\t\t\t});\n\n\t\t\t// Return\n\t\t\treturn pageUrl;\n\t\t};\n\n\t\t/**\n\t\t * History.getBasePageUrl()\n\t\t * Fetches the Url of the directory of the current page\n\t\t * @return {String} basePageUrl\n\t\t */\n\t\tHistory.getBasePageUrl = function(){\n\t\t\t// Create\n\t\t\tvar basePageUrl = document.location.href.replace(/[#\\?].*/,'').replace(/[^\\/]+$/,function(part,index,string){\n\t\t\t\treturn (/[^\\/]$/).test(part) ? '' : part;\n\t\t\t}).replace(/\\/+$/,'')+'/';\n\n\t\t\t// Return\n\t\t\treturn basePageUrl;\n\t\t};\n\n\t\t/**\n\t\t * History.getFullUrl(url)\n\t\t * Ensures that we have an absolute URL and not a relative URL\n\t\t * @param {string} url\n\t\t * @param {Boolean} allowBaseHref\n\t\t * @return {string} fullUrl\n\t\t */\n\t\tHistory.getFullUrl = function(url,allowBaseHref){\n\t\t\t// Prepare\n\t\t\tvar fullUrl = url, firstChar = url.substring(0,1);\n\t\t\tallowBaseHref = (typeof allowBaseHref === 'undefined') ? true : allowBaseHref;\n\n\t\t\t// Check\n\t\t\tif ( /[a-z]+\\:\\/\\//.test(url) ) {\n\t\t\t\t// Full URL\n\t\t\t}\n\t\t\telse if ( firstChar === '/' ) {\n\t\t\t\t// Root URL\n\t\t\t\tfullUrl = History.getRootUrl()+url.replace(/^\\/+/,'');\n\t\t\t}\n\t\t\telse if ( firstChar === '#' ) {\n\t\t\t\t// Anchor URL\n\t\t\t\tfullUrl = History.getPageUrl().replace(/#.*/,'')+url;\n\t\t\t}\n\t\t\telse if ( firstChar === '?' ) {\n\t\t\t\t// Query URL\n\t\t\t\tfullUrl = History.getPageUrl().replace(/[\\?#].*/,'')+url;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Relative URL\n\t\t\t\tif ( allowBaseHref ) {\n\t\t\t\t\tfullUrl = History.getBaseUrl()+url.replace(/^(\\.\\/)+/,'');\n\t\t\t\t} else {\n\t\t\t\t\tfullUrl = History.getBasePageUrl()+url.replace(/^(\\.\\/)+/,'');\n\t\t\t\t}\n\t\t\t\t// We have an if condition above as we do not want hashes\n\t\t\t\t// which are relative to the baseHref in our URLs\n\t\t\t\t// as if the baseHref changes, then all our bookmarks\n\t\t\t\t// would now point to different locations\n\t\t\t\t// whereas the basePageUrl will always stay the same\n\t\t\t}\n\n\t\t\t// Return\n\t\t\treturn fullUrl.replace(/\\#$/,'');\n\t\t};\n\n\t\t/**\n\t\t * History.getShortUrl(url)\n\t\t * Ensures that we have a relative URL and not a absolute URL\n\t\t * @param {string} url\n\t\t * @return {string} url\n\t\t */\n\t\tHistory.getShortUrl = function(url){\n\t\t\t// Prepare\n\t\t\tvar shortUrl = url, baseUrl = History.getBaseUrl(), rootUrl = History.getRootUrl();\n\n\t\t\t// Trim baseUrl\n\t\t\tif ( History.emulated.pushState ) {\n\t\t\t\t// We are in a if statement as when pushState is not emulated\n\t\t\t\t// The actual url these short urls are relative to can change\n\t\t\t\t// So within the same session, we the url may end up somewhere different\n\t\t\t\tshortUrl = shortUrl.replace(baseUrl,'');\n\t\t\t}\n\n\t\t\t// Trim rootUrl\n\t\t\tshortUrl = shortUrl.replace(rootUrl,'/');\n\n\t\t\t// Ensure we can still detect it as a state\n\t\t\tif ( History.isTraditionalAnchor(shortUrl) ) {\n\t\t\t\tshortUrl = './'+shortUrl;\n\t\t\t}\n\n\t\t\t// Clean It\n\t\t\tshortUrl = shortUrl.replace(/^(\\.\\/)+/g,'./').replace(/\\#$/,'');\n\n\t\t\t// Return\n\t\t\treturn shortUrl;\n\t\t};\n\n\n\t\t// ====================================================================\n\t\t// State Storage\n\n\t\t/**\n\t\t * History.store\n\t\t * The store for all session specific data\n\t\t */\n\t\tHistory.store = {};\n\n\t\t/**\n\t\t * History.idToState\n\t\t * 1-1: State ID to State Object\n\t\t */\n\t\tHistory.idToState = History.idToState||{};\n\n\t\t/**\n\t\t * History.stateToId\n\t\t * 1-1: State String to State ID\n\t\t */\n\t\tHistory.stateToId = History.stateToId||{};\n\n\t\t/**\n\t\t * History.urlToId\n\t\t * 1-1: State URL to State ID\n\t\t */\n\t\tHistory.urlToId = History.urlToId||{};\n\n\t\t/**\n\t\t * History.storedStates\n\t\t * Store the states in an array\n\t\t */\n\t\tHistory.storedStates = History.storedStates||[];\n\n\t\t/**\n\t\t * History.savedStates\n\t\t * Saved the states in an array\n\t\t */\n\t\tHistory.savedStates = History.savedStates||[];\n\n\t\t/**\n\t\t * History.noramlizeStore()\n\t\t * Noramlize the store by adding necessary values\n\t\t */\n\t\tHistory.normalizeStore = function(){\n\t\t\tHistory.store.idToState = History.store.idToState||{};\n\t\t\tHistory.store.urlToId = History.store.urlToId||{};\n\t\t\tHistory.store.stateToId = History.store.stateToId||{};\n\t\t};\n\n\t\t/**\n\t\t * History.getState()\n\t\t * Get an object containing the data, title and url of the current state\n\t\t * @param {Boolean} friendly\n\t\t * @param {Boolean} create\n\t\t * @return {Object} State\n\t\t */\n\t\tHistory.getState = function(friendly,create){\n\t\t\t// Prepare\n\t\t\tif ( typeof friendly === 'undefined' ) { friendly = true; }\n\t\t\tif ( typeof create === 'undefined' ) { create = true; }\n\n\t\t\t// Fetch\n\t\t\tvar State = History.getLastSavedState();\n\n\t\t\t// Create\n\t\t\tif ( !State && create ) {\n\t\t\t\tState = History.createStateObject();\n\t\t\t}\n\n\t\t\t// Adjust\n\t\t\tif ( friendly ) {\n\t\t\t\tState = History.cloneObject(State);\n\t\t\t\tState.url = State.cleanUrl||State.url;\n\t\t\t}\n\n\t\t\t// Return\n\t\t\treturn State;\n\t\t};\n\n\t\t/**\n\t\t * History.getIdByState(State)\n\t\t * Gets a ID for a State\n\t\t * @param {State} newState\n\t\t * @return {String} id\n\t\t */\n\t\tHistory.getIdByState = function(newState){\n\n\t\t\t// Fetch ID\n\t\t\tvar id = History.extractId(newState.url),\n\t\t\t\tstr;\n\t\t\t\n\t\t\tif ( !id ) {\n\t\t\t\t// Find ID via State String\n\t\t\t\tstr = History.getStateString(newState);\n\t\t\t\tif ( typeof History.stateToId[str] !== 'undefined' ) {\n\t\t\t\t\tid = History.stateToId[str];\n\t\t\t\t}\n\t\t\t\telse if ( typeof History.store.stateToId[str] !== 'undefined' ) {\n\t\t\t\t\tid = History.store.stateToId[str];\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Generate a new ID\n\t\t\t\t\twhile ( true ) {\n\t\t\t\t\t\tid = (new Date()).getTime() + String(Math.random()).replace(/\\D/g,'');\n\t\t\t\t\t\tif ( typeof History.idToState[id] === 'undefined' && typeof History.store.idToState[id] === 'undefined' ) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply the new State to the ID\n\t\t\t\t\tHistory.stateToId[str] = id;\n\t\t\t\t\tHistory.idToState[id] = newState;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Return ID\n\t\t\treturn id;\n\t\t};\n\n\t\t/**\n\t\t * History.normalizeState(State)\n\t\t * Expands a State Object\n\t\t * @param {object} State\n\t\t * @return {object}\n\t\t */\n\t\tHistory.normalizeState = function(oldState){\n\t\t\t// Variables\n\t\t\tvar newState, dataNotEmpty;\n\n\t\t\t// Prepare\n\t\t\tif ( !oldState || (typeof oldState !== 'object') ) {\n\t\t\t\toldState = {};\n\t\t\t}\n\n\t\t\t// Check\n\t\t\tif ( typeof oldState.normalized !== 'undefined' ) {\n\t\t\t\treturn oldState;\n\t\t\t}\n\n\t\t\t// Adjust\n\t\t\tif ( !oldState.data || (typeof oldState.data !== 'object') ) {\n\t\t\t\toldState.data = {};\n\t\t\t}\n\n\t\t\t// ----------------------------------------------------------------\n\n\t\t\t// Create\n\t\t\tnewState = {};\n\t\t\tnewState.normalized = true;\n\t\t\tnewState.title = oldState.title||'';\n\t\t\tnewState.url = History.getFullUrl(History.unescapeString(oldState.url||document.location.href));\n\t\t\tnewState.hash = History.getShortUrl(newState.url);\n\t\t\tnewState.data = History.cloneObject(oldState.data);\n\n\t\t\t// Fetch ID\n\t\t\tnewState.id = History.getIdByState(newState);\n\n\t\t\t// ----------------------------------------------------------------\n\n\t\t\t// Clean the URL\n\t\t\tnewState.cleanUrl = newState.url.replace(/\\??\\&_suid.*/,'');\n\t\t\tnewState.url = newState.cleanUrl;\n\n\t\t\t// Check to see if we have more than just a url\n\t\t\tdataNotEmpty = !History.isEmptyObject(newState.data);\n\n\t\t\t// Apply\n\t\t\tif ( newState.title || dataNotEmpty ) {\n\t\t\t\t// Add ID to Hash\n\t\t\t\tnewState.hash = History.getShortUrl(newState.url).replace(/\\??\\&_suid.*/,'');\n\t\t\t\tif ( !/\\?/.test(newState.hash) ) {\n\t\t\t\t\tnewState.hash += '?';\n\t\t\t\t}\n\t\t\t\tnewState.hash += '&_suid='+newState.id;\n\t\t\t}\n\n\t\t\t// Create the Hashed URL\n\t\t\tnewState.hashedUrl = History.getFullUrl(newState.hash);\n\n\t\t\t// ----------------------------------------------------------------\n\n\t\t\t// Update the URL if we have a duplicate\n\t\t\tif ( (History.emulated.pushState || History.bugs.safariPoll) && History.hasUrlDuplicate(newState) ) {\n\t\t\t\tnewState.url = newState.hashedUrl;\n\t\t\t}\n\n\t\t\t// ----------------------------------------------------------------\n\n\t\t\t// Return\n\t\t\treturn newState;\n\t\t};\n\n\t\t/**\n\t\t * History.createStateObject(data,title,url)\n\t\t * Creates a object based on the data, title and url state params\n\t\t * @param {object} data\n\t\t * @param {string} title\n\t\t * @param {string} url\n\t\t * @return {object}\n\t\t */\n\t\tHistory.createStateObject = function(data,title,url){\n\t\t\t// Hashify\n\t\t\tvar State = {\n\t\t\t\t'data': data,\n\t\t\t\t'title': title,\n\t\t\t\t'url': url\n\t\t\t};\n\n\t\t\t// Expand the State\n\t\t\tState = History.normalizeState(State);\n\n\t\t\t// Return object\n\t\t\treturn State;\n\t\t};\n\n\t\t/**\n\t\t * History.getStateById(id)\n\t\t * Get a state by it's UID\n\t\t * @param {String} id\n\t\t */\n\t\tHistory.getStateById = function(id){\n\t\t\t// Prepare\n\t\t\tid = String(id);\n\n\t\t\t// Retrieve\n\t\t\tvar State = History.idToState[id] || History.store.idToState[id] || undefined;\n\n\t\t\t// Return State\n\t\t\treturn State;\n\t\t};\n\n\t\t/**\n\t\t * Get a State's String\n\t\t * @param {State} passedState\n\t\t */\n\t\tHistory.getStateString = function(passedState){\n\t\t\t// Prepare\n\t\t\tvar State, cleanedState, str;\n\n\t\t\t// Fetch\n\t\t\tState = History.normalizeState(passedState);\n\n\t\t\t// Clean\n\t\t\tcleanedState = {\n\t\t\t\tdata: State.data,\n\t\t\t\ttitle: passedState.title,\n\t\t\t\turl: passedState.url\n\t\t\t};\n\n\t\t\t// Fetch\n\t\t\tstr = JSON.stringify(cleanedState);\n\n\t\t\t// Return\n\t\t\treturn str;\n\t\t};\n\n\t\t/**\n\t\t * Get a State's ID\n\t\t * @param {State} passedState\n\t\t * @return {String} id\n\t\t */\n\t\tHistory.getStateId = function(passedState){\n\t\t\t// Prepare\n\t\t\tvar State, id;\n\t\t\t\n\t\t\t// Fetch\n\t\t\tState = History.normalizeState(passedState);\n\n\t\t\t// Fetch\n\t\t\tid = State.id;\n\n\t\t\t// Return\n\t\t\treturn id;\n\t\t};\n\n\t\t/**\n\t\t * History.getHashByState(State)\n\t\t * Creates a Hash for the State Object\n\t\t * @param {State} passedState\n\t\t * @return {String} hash\n\t\t */\n\t\tHistory.getHashByState = function(passedState){\n\t\t\t// Prepare\n\t\t\tvar State, hash;\n\t\t\t\n\t\t\t// Fetch\n\t\t\tState = History.normalizeState(passedState);\n\n\t\t\t// Hash\n\t\t\thash = State.hash;\n\n\t\t\t// Return\n\t\t\treturn hash;\n\t\t};\n\n\t\t/**\n\t\t * History.extractId(url_or_hash)\n\t\t * Get a State ID by it's URL or Hash\n\t\t * @param {string} url_or_hash\n\t\t * @return {string} id\n\t\t */\n\t\tHistory.extractId = function ( url_or_hash ) {\n\t\t\t// Prepare\n\t\t\tvar id,parts,url;\n\n\t\t\t// Extract\n\t\t\tparts = /(.*)\\&_suid=([0-9]+)$/.exec(url_or_hash);\n\t\t\turl = parts ? (parts[1]||url_or_hash) : url_or_hash;\n\t\t\tid = parts ? String(parts[2]||'') : '';\n\n\t\t\t// Return\n\t\t\treturn id||false;\n\t\t};\n\n\t\t/**\n\t\t * History.isTraditionalAnchor\n\t\t * Checks to see if the url is a traditional anchor or not\n\t\t * @param {String} url_or_hash\n\t\t * @return {Boolean}\n\t\t */\n\t\tHistory.isTraditionalAnchor = function(url_or_hash){\n\t\t\t// Check\n\t\t\tvar isTraditional = !(/[\\/\\?\\.]/.test(url_or_hash));\n\n\t\t\t// Return\n\t\t\treturn isTraditional;\n\t\t};\n\n\t\t/**\n\t\t * History.extractState\n\t\t * Get a State by it's URL or Hash\n\t\t * @param {String} url_or_hash\n\t\t * @return {State|null}\n\t\t */\n\t\tHistory.extractState = function(url_or_hash,create){\n\t\t\t// Prepare\n\t\t\tvar State = null, id, url;\n\t\t\tcreate = create||false;\n\n\t\t\t// Fetch SUID\n\t\t\tid = History.extractId(url_or_hash);\n\t\t\tif ( id ) {\n\t\t\t\tState = History.getStateById(id);\n\t\t\t}\n\n\t\t\t// Fetch SUID returned no State\n\t\t\tif ( !State ) {\n\t\t\t\t// Fetch URL\n\t\t\t\turl = History.getFullUrl(url_or_hash);\n\n\t\t\t\t// Check URL\n\t\t\t\tid = History.getIdByUrl(url)||false;\n\t\t\t\tif ( id ) {\n\t\t\t\t\tState = History.getStateById(id);\n\t\t\t\t}\n\n\t\t\t\t// Create State\n\t\t\t\tif ( !State && create && !History.isTraditionalAnchor(url_or_hash) ) {\n\t\t\t\t\tState = History.createStateObject(null,null,url);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Return\n\t\t\treturn State;\n\t\t};\n\n\t\t/**\n\t\t * History.getIdByUrl()\n\t\t * Get a State ID by a State URL\n\t\t */\n\t\tHistory.getIdByUrl = function(url){\n\t\t\t// Fetch\n\t\t\tvar id = History.urlToId[url] || History.store.urlToId[url] || undefined;\n\n\t\t\t// Return\n\t\t\treturn id;\n\t\t};\n\n\t\t/**\n\t\t * History.getLastSavedState()\n\t\t * Get an object containing the data, title and url of the current state\n\t\t * @return {Object} State\n\t\t */\n\t\tHistory.getLastSavedState = function(){\n\t\t\treturn History.savedStates[History.savedStates.length-1]||undefined;\n\t\t};\n\n\t\t/**\n\t\t * History.getLastStoredState()\n\t\t * Get an object containing the data, title and url of the current state\n\t\t * @return {Object} State\n\t\t */\n\t\tHistory.getLastStoredState = function(){\n\t\t\treturn History.storedStates[History.storedStates.length-1]||undefined;\n\t\t};\n\n\t\t/**\n\t\t * History.hasUrlDuplicate\n\t\t * Checks if a Url will have a url conflict\n\t\t * @param {Object} newState\n\t\t * @return {Boolean} hasDuplicate\n\t\t */\n\t\tHistory.hasUrlDuplicate = function(newState) {\n\t\t\t// Prepare\n\t\t\tvar hasDuplicate = false,\n\t\t\t\toldState;\n\n\t\t\t// Fetch\n\t\t\toldState = History.extractState(newState.url);\n\n\t\t\t// Check\n\t\t\thasDuplicate = oldState && oldState.id !== newState.id;\n\n\t\t\t// Return\n\t\t\treturn hasDuplicate;\n\t\t};\n\n\t\t/**\n\t\t * History.storeState\n\t\t * Store a State\n\t\t * @param {Object} newState\n\t\t * @return {Object} newState\n\t\t */\n\t\tHistory.storeState = function(newState){\n\t\t\t// Store the State\n\t\t\tHistory.urlToId[newState.url] = newState.id;\n\n\t\t\t// Push the State\n\t\t\tHistory.storedStates.push(History.cloneObject(newState));\n\n\t\t\t// Return newState\n\t\t\treturn newState;\n\t\t};\n\n\t\t/**\n\t\t * History.isLastSavedState(newState)\n\t\t * Tests to see if the state is the last state\n\t\t * @param {Object} newState\n\t\t * @return {boolean} isLast\n\t\t */\n\t\tHistory.isLastSavedState = function(newState){\n\t\t\t// Prepare\n\t\t\tvar isLast = false,\n\t\t\t\tnewId, oldState, oldId;\n\n\t\t\t// Check\n\t\t\tif ( History.savedStates.length ) {\n\t\t\t\tnewId = newState.id;\n\t\t\t\toldState = History.getLastSavedState();\n\t\t\t\toldId = oldState.id;\n\n\t\t\t\t// Check\n\t\t\t\tisLast = (newId === oldId);\n\t\t\t}\n\n\t\t\t// Return\n\t\t\treturn isLast;\n\t\t};\n\n\t\t/**\n\t\t * History.saveState\n\t\t * Push a State\n\t\t * @param {Object} newState\n\t\t * @return {boolean} changed\n\t\t */\n\t\tHistory.saveState = function(newState){\n\t\t\t// Check Hash\n\t\t\tif ( History.isLastSavedState(newState) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Push the State\n\t\t\tHistory.savedStates.push(History.cloneObject(newState));\n\n\t\t\t// Return true\n\t\t\treturn true;\n\t\t};\n\n\t\t/**\n\t\t * History.getStateByIndex()\n\t\t * Gets a state by the index\n\t\t * @param {integer} index\n\t\t * @return {Object}\n\t\t */\n\t\tHistory.getStateByIndex = function(index){\n\t\t\t// Prepare\n\t\t\tvar State = null;\n\n\t\t\t// Handle\n\t\t\tif ( typeof index === 'undefined' ) {\n\t\t\t\t// Get the last inserted\n\t\t\t\tState = History.savedStates[History.savedStates.length-1];\n\t\t\t}\n\t\t\telse if ( index < 0 ) {\n\t\t\t\t// Get from the end\n\t\t\t\tState = History.savedStates[History.savedStates.length+index];\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Get from the beginning\n\t\t\t\tState = History.savedStates[index];\n\t\t\t}\n\n\t\t\t// Return State\n\t\t\treturn State;\n\t\t};\n\n\n\t\t// ====================================================================\n\t\t// Hash Helpers\n\n\t\t/**\n\t\t * History.getHash()\n\t\t * Gets the current document hash\n\t\t * @return {string}\n\t\t */\n\t\tHistory.getHash = function(){\n\t\t\tvar hash = History.unescapeHash(document.location.hash);\n\t\t\treturn hash;\n\t\t};\n\n\t\t/**\n\t\t * History.unescapeString()\n\t\t * Unescape a string\n\t\t * @param {String} str\n\t\t * @return {string}\n\t\t */\n\t\tHistory.unescapeString = function(str){\n\t\t\t// Prepare\n\t\t\tvar result = str,\n\t\t\t\ttmp;\n\n\t\t\t// Unescape hash\n\t\t\twhile ( true ) {\n\t\t\t\ttmp = window.unescape(result);\n\t\t\t\tif ( tmp === result ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tresult = tmp;\n\t\t\t}\n\n\t\t\t// Return result\n\t\t\treturn result;\n\t\t};\n\n\t\t/**\n\t\t * History.unescapeHash()\n\t\t * normalize and Unescape a Hash\n\t\t * @param {String} hash\n\t\t * @return {string}\n\t\t */\n\t\tHistory.unescapeHash = function(hash){\n\t\t\t// Prepare\n\t\t\tvar result = History.normalizeHash(hash);\n\n\t\t\t// Unescape hash\n\t\t\tresult = History.unescapeString(result);\n\n\t\t\t// Return result\n\t\t\treturn result;\n\t\t};\n\n\t\t/**\n\t\t * History.normalizeHash()\n\t\t * normalize a hash across browsers\n\t\t * @return {string}\n\t\t */\n\t\tHistory.normalizeHash = function(hash){\n\t\t\t// Prepare\n\t\t\tvar result = hash.replace(/[^#]*#/,'').replace(/#.*/, '');\n\n\t\t\t// Return result\n\t\t\treturn result;\n\t\t};\n\n\t\t/**\n\t\t * History.setHash(hash)\n\t\t * Sets the document hash\n\t\t * @param {string} hash\n\t\t * @return {History}\n\t\t */\n\t\tHistory.setHash = function(hash,queue){\n\t\t\t// Prepare\n\t\t\tvar adjustedHash, State, pageUrl;\n\n\t\t\t// Handle Queueing\n\t\t\tif ( queue !== false && History.busy() ) {\n\t\t\t\t// Wait + Push to Queue\n\t\t\t\t//History.debug('History.setHash: we must wait', arguments);\n\t\t\t\tHistory.pushQueue({\n\t\t\t\t\tscope: History,\n\t\t\t\t\tcallback: History.setHash,\n\t\t\t\t\targs: arguments,\n\t\t\t\t\tqueue: queue\n\t\t\t\t});\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Log\n\t\t\t//History.debug('History.setHash: called',hash);\n\n\t\t\t// Prepare\n\t\t\tadjustedHash = History.escapeHash(hash);\n\n\t\t\t// Make Busy + Continue\n\t\t\tHistory.busy(true);\n\n\t\t\t// Check if hash is a state\n\t\t\tState = History.extractState(hash,true);\n\t\t\tif ( State && !History.emulated.pushState ) {\n\t\t\t\t// Hash is a state so skip the setHash\n\t\t\t\t//History.debug('History.setHash: Hash is a state so skipping the hash set with a direct pushState call',arguments);\n\n\t\t\t\t// PushState\n\t\t\t\tHistory.pushState(State.data,State.title,State.url,false);\n\t\t\t}\n\t\t\telse if ( document.location.hash !== adjustedHash ) {\n\t\t\t\t// Hash is a proper hash, so apply it\n\n\t\t\t\t// Handle browser bugs\n\t\t\t\tif ( History.bugs.setHash ) {\n\t\t\t\t\t// Fix Safari Bug https://bugs.webkit.org/show_bug.cgi?id=56249\n\n\t\t\t\t\t// Fetch the base page\n\t\t\t\t\tpageUrl = History.getPageUrl();\n\n\t\t\t\t\t// Safari hash apply\n\t\t\t\t\tHistory.pushState(null,null,pageUrl+'#'+adjustedHash,false);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Normal hash apply\n\t\t\t\t\tdocument.location.hash = adjustedHash;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Chain\n\t\t\treturn History;\n\t\t};\n\n\t\t/**\n\t\t * History.escape()\n\t\t * normalize and Escape a Hash\n\t\t * @return {string}\n\t\t */\n\t\tHistory.escapeHash = function(hash){\n\t\t\t// Prepare\n\t\t\tvar result = History.normalizeHash(hash);\n\n\t\t\t// Escape hash\n\t\t\tresult = window.escape(result);\n\n\t\t\t// IE6 Escape Bug\n\t\t\tif ( !History.bugs.hashEscape ) {\n\t\t\t\t// Restore common parts\n\t\t\t\tresult = result\n\t\t\t\t\t.replace(/\\%21/g,'!')\n\t\t\t\t\t.replace(/\\%26/g,'&')\n\t\t\t\t\t.replace(/\\%3D/g,'=')\n\t\t\t\t\t.replace(/\\%3F/g,'?');\n\t\t\t}\n\n\t\t\t// Return result\n\t\t\treturn result;\n\t\t};\n\n\t\t/**\n\t\t * History.getHashByUrl(url)\n\t\t * Extracts the Hash from a URL\n\t\t * @param {string} url\n\t\t * @return {string} url\n\t\t */\n\t\tHistory.getHashByUrl = function(url){\n\t\t\t// Extract the hash\n\t\t\tvar hash = String(url)\n\t\t\t\t.replace(/([^#]*)#?([^#]*)#?(.*)/, '$2')\n\t\t\t\t;\n\n\t\t\t// Unescape hash\n\t\t\thash = History.unescapeHash(hash);\n\n\t\t\t// Return hash\n\t\t\treturn hash;\n\t\t};\n\n\t\t/**\n\t\t * History.setTitle(title)\n\t\t * Applies the title to the document\n\t\t * @param {State} newState\n\t\t * @return {Boolean}\n\t\t */\n\t\tHistory.setTitle = function(newState){\n\t\t\t// Prepare\n\t\t\tvar title = newState.title,\n\t\t\t\tfirstState;\n\n\t\t\t// Initial\n\t\t\tif ( !title ) {\n\t\t\t\tfirstState = History.getStateByIndex(0);\n\t\t\t\tif ( firstState && firstState.url === newState.url ) {\n\t\t\t\t\ttitle = firstState.title||History.options.initialTitle;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply\n\t\t\ttry {\n\t\t\t\tdocument.getElementsByTagName('title')[0].innerHTML = title.replace('<','&lt;').replace('>','&gt;').replace(' & ',' &amp; ');\n\t\t\t}\n\t\t\tcatch ( Exception ) { }\n\t\t\tdocument.title = title;\n\n\t\t\t// Chain\n\t\t\treturn History;\n\t\t};\n\n\n\t\t// ====================================================================\n\t\t// Queueing\n\n\t\t/**\n\t\t * History.queues\n\t\t * The list of queues to use\n\t\t * First In, First Out\n\t\t */\n\t\tHistory.queues = [];\n\n\t\t/**\n\t\t * History.busy(value)\n\t\t * @param {boolean} value [optional]\n\t\t * @return {boolean} busy\n\t\t */\n\t\tHistory.busy = function(value){\n\t\t\t// Apply\n\t\t\tif ( typeof value !== 'undefined' ) {\n\t\t\t\t//History.debug('History.busy: changing ['+(History.busy.flag||false)+'] to ['+(value||false)+']', History.queues.length);\n\t\t\t\tHistory.busy.flag = value;\n\t\t\t}\n\t\t\t// Default\n\t\t\telse if ( typeof History.busy.flag === 'undefined' ) {\n\t\t\t\tHistory.busy.flag = false;\n\t\t\t}\n\n\t\t\t// Queue\n\t\t\tif ( !History.busy.flag ) {\n\t\t\t\t// Execute the next item in the queue\n\t\t\t\tclearTimeout(History.busy.timeout);\n\t\t\t\tvar fireNext = function(){\n\t\t\t\t\tvar i, queue, item;\n\t\t\t\t\tif ( History.busy.flag ) return;\n\t\t\t\t\tfor ( i=History.queues.length-1; i >= 0; --i ) {\n\t\t\t\t\t\tqueue = History.queues[i];\n\t\t\t\t\t\tif ( queue.length === 0 ) continue;\n\t\t\t\t\t\titem = queue.shift();\n\t\t\t\t\t\tHistory.fireQueueItem(item);\n\t\t\t\t\t\tHistory.busy.timeout = setTimeout(fireNext,History.options.busyDelay);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tHistory.busy.timeout = setTimeout(fireNext,History.options.busyDelay);\n\t\t\t}\n\n\t\t\t// Return\n\t\t\treturn History.busy.flag;\n\t\t};\n\n\t\t/**\n\t\t * History.busy.flag\n\t\t */\n\t\tHistory.busy.flag = false;\n\n\t\t/**\n\t\t * History.fireQueueItem(item)\n\t\t * Fire a Queue Item\n\t\t * @param {Object} item\n\t\t * @return {Mixed} result\n\t\t */\n\t\tHistory.fireQueueItem = function(item){\n\t\t\treturn item.callback.apply(item.scope||History,item.args||[]);\n\t\t};\n\n\t\t/**\n\t\t * History.pushQueue(callback,args)\n\t\t * Add an item to the queue\n\t\t * @param {Object} item [scope,callback,args,queue]\n\t\t */\n\t\tHistory.pushQueue = function(item){\n\t\t\t// Prepare the queue\n\t\t\tHistory.queues[item.queue||0] = History.queues[item.queue||0]||[];\n\n\t\t\t// Add to the queue\n\t\t\tHistory.queues[item.queue||0].push(item);\n\n\t\t\t// Chain\n\t\t\treturn History;\n\t\t};\n\n\t\t/**\n\t\t * History.queue (item,queue), (func,queue), (func), (item)\n\t\t * Either firs the item now if not busy, or adds it to the queue\n\t\t */\n\t\tHistory.queue = function(item,queue){\n\t\t\t// Prepare\n\t\t\tif ( typeof item === 'function' ) {\n\t\t\t\titem = {\n\t\t\t\t\tcallback: item\n\t\t\t\t};\n\t\t\t}\n\t\t\tif ( typeof queue !== 'undefined' ) {\n\t\t\t\titem.queue = queue;\n\t\t\t}\n\n\t\t\t// Handle\n\t\t\tif ( History.busy() ) {\n\t\t\t\tHistory.pushQueue(item);\n\t\t\t} else {\n\t\t\t\tHistory.fireQueueItem(item);\n\t\t\t}\n\n\t\t\t// Chain\n\t\t\treturn History;\n\t\t};\n\n\t\t/**\n\t\t * History.clearQueue()\n\t\t * Clears the Queue\n\t\t */\n\t\tHistory.clearQueue = function(){\n\t\t\tHistory.busy.flag = false;\n\t\t\tHistory.queues = [];\n\t\t\treturn History;\n\t\t};\n\n\n\t\t// ====================================================================\n\t\t// IE Bug Fix\n\n\t\t/**\n\t\t * History.stateChanged\n\t\t * States whether or not the state has changed since the last double check was initialised\n\t\t */\n\t\tHistory.stateChanged = false;\n\n\t\t/**\n\t\t * History.doubleChecker\n\t\t * Contains the timeout used for the double checks\n\t\t */\n\t\tHistory.doubleChecker = false;\n\n\t\t/**\n\t\t * History.doubleCheckComplete()\n\t\t * Complete a double check\n\t\t * @return {History}\n\t\t */\n\t\tHistory.doubleCheckComplete = function(){\n\t\t\t// Update\n\t\t\tHistory.stateChanged = true;\n\n\t\t\t// Clear\n\t\t\tHistory.doubleCheckClear();\n\n\t\t\t// Chain\n\t\t\treturn History;\n\t\t};\n\n\t\t/**\n\t\t * History.doubleCheckClear()\n\t\t * Clear a double check\n\t\t * @return {History}\n\t\t */\n\t\tHistory.doubleCheckClear = function(){\n\t\t\t// Clear\n\t\t\tif ( History.doubleChecker ) {\n\t\t\t\tclearTimeout(History.doubleChecker);\n\t\t\t\tHistory.doubleChecker = false;\n\t\t\t}\n\n\t\t\t// Chain\n\t\t\treturn History;\n\t\t};\n\n\t\t/**\n\t\t * History.doubleCheck()\n\t\t * Create a double check\n\t\t * @return {History}\n\t\t */\n\t\tHistory.doubleCheck = function(tryAgain){\n\t\t\t// Reset\n\t\t\tHistory.stateChanged = false;\n\t\t\tHistory.doubleCheckClear();\n\n\t\t\t// Fix IE6,IE7 bug where calling history.back or history.forward does not actually change the hash (whereas doing it manually does)\n\t\t\t// Fix Safari 5 bug where sometimes the state does not change: https://bugs.webkit.org/show_bug.cgi?id=42940\n\t\t\tif ( History.bugs.ieDoubleCheck ) {\n\t\t\t\t// Apply Check\n\t\t\t\tHistory.doubleChecker = setTimeout(\n\t\t\t\t\tfunction(){\n\t\t\t\t\t\tHistory.doubleCheckClear();\n\t\t\t\t\t\tif ( !History.stateChanged ) {\n\t\t\t\t\t\t\t//History.debug('History.doubleCheck: State has not yet changed, trying again', arguments);\n\t\t\t\t\t\t\t// Re-Attempt\n\t\t\t\t\t\t\ttryAgain();\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t},\n\t\t\t\t\tHistory.options.doubleCheckInterval\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Chain\n\t\t\treturn History;\n\t\t};\n\n\n\t\t// ====================================================================\n\t\t// Safari Bug Fix\n\n\t\t/**\n\t\t * History.safariStatePoll()\n\t\t * Poll the current state\n\t\t * @return {History}\n\t\t */\n\t\tHistory.safariStatePoll = function(){\n\t\t\t// Poll the URL\n\n\t\t\t// Get the Last State which has the new URL\n\t\t\tvar\n\t\t\t\turlState = History.extractState(document.location.href),\n\t\t\t\tnewState;\n\n\t\t\t// Check for a difference\n\t\t\tif ( !History.isLastSavedState(urlState) ) {\n\t\t\t\tnewState = urlState;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Check if we have a state with that url\n\t\t\t// If not create it\n\t\t\tif ( !newState ) {\n\t\t\t\t//History.debug('History.safariStatePoll: new');\n\t\t\t\tnewState = History.createStateObject();\n\t\t\t}\n\n\t\t\t// Apply the New State\n\t\t\t//History.debug('History.safariStatePoll: trigger');\n\t\t\tHistory.Adapter.trigger(window,'popstate');\n\n\t\t\t// Chain\n\t\t\treturn History;\n\t\t};\n\n\n\t\t// ====================================================================\n\t\t// State Aliases\n\n\t\t/**\n\t\t * History.back(queue)\n\t\t * Send the browser history back one item\n\t\t * @param {Integer} queue [optional]\n\t\t */\n\t\tHistory.back = function(queue){\n\t\t\t//History.debug('History.back: called', arguments);\n\n\t\t\t// Handle Queueing\n\t\t\tif ( queue !== false && History.busy() ) {\n\t\t\t\t// Wait + Push to Queue\n\t\t\t\t//History.debug('History.back: we must wait', arguments);\n\t\t\t\tHistory.pushQueue({\n\t\t\t\t\tscope: History,\n\t\t\t\t\tcallback: History.back,\n\t\t\t\t\targs: arguments,\n\t\t\t\t\tqueue: queue\n\t\t\t\t});\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Make Busy + Continue\n\t\t\tHistory.busy(true);\n\n\t\t\t// Fix certain browser bugs that prevent the state from changing\n\t\t\tHistory.doubleCheck(function(){\n\t\t\t\tHistory.back(false);\n\t\t\t});\n\n\t\t\t// Go back\n\t\t\thistory.go(-1);\n\n\t\t\t// End back closure\n\t\t\treturn true;\n\t\t};\n\n\t\t/**\n\t\t * History.forward(queue)\n\t\t * Send the browser history forward one item\n\t\t * @param {Integer} queue [optional]\n\t\t */\n\t\tHistory.forward = function(queue){\n\t\t\t//History.debug('History.forward: called', arguments);\n\n\t\t\t// Handle Queueing\n\t\t\tif ( queue !== false && History.busy() ) {\n\t\t\t\t// Wait + Push to Queue\n\t\t\t\t//History.debug('History.forward: we must wait', arguments);\n\t\t\t\tHistory.pushQueue({\n\t\t\t\t\tscope: History,\n\t\t\t\t\tcallback: History.forward,\n\t\t\t\t\targs: arguments,\n\t\t\t\t\tqueue: queue\n\t\t\t\t});\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Make Busy + Continue\n\t\t\tHistory.busy(true);\n\n\t\t\t// Fix certain browser bugs that prevent the state from changing\n\t\t\tHistory.doubleCheck(function(){\n\t\t\t\tHistory.forward(false);\n\t\t\t});\n\n\t\t\t// Go forward\n\t\t\thistory.go(1);\n\n\t\t\t// End forward closure\n\t\t\treturn true;\n\t\t};\n\n\t\t/**\n\t\t * History.go(index,queue)\n\t\t * Send the browser history back or forward index times\n\t\t * @param {Integer} queue [optional]\n\t\t */\n\t\tHistory.go = function(index,queue){\n\t\t\t//History.debug('History.go: called', arguments);\n\n\t\t\t// Prepare\n\t\t\tvar i;\n\n\t\t\t// Handle\n\t\t\tif ( index > 0 ) {\n\t\t\t\t// Forward\n\t\t\t\tfor ( i=1; i<=index; ++i ) {\n\t\t\t\t\tHistory.forward(queue);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( index < 0 ) {\n\t\t\t\t// Backward\n\t\t\t\tfor ( i=-1; i>=index; --i ) {\n\t\t\t\t\tHistory.back(queue);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new Error('History.go: History.go requires a positive or negative integer passed.');\n\t\t\t}\n\n\t\t\t// Chain\n\t\t\treturn History;\n\t\t};\n\n\n\t\t// ====================================================================\n\t\t// HTML5 State Support\n\n\t\t// Non-Native pushState Implementation\n\t\tif ( History.emulated.pushState ) {\n\t\t\t/*\n\t\t\t * Provide Skeleton for HTML4 Browsers\n\t\t\t */\n\n\t\t\t// Prepare\n\t\t\tvar emptyFunction = function(){};\n\t\t\tHistory.pushState = History.pushState||emptyFunction;\n\t\t\tHistory.replaceState = History.replaceState||emptyFunction;\n\t\t} // History.emulated.pushState\n\n\t\t// Native pushState Implementation\n\t\telse {\n\t\t\t/*\n\t\t\t * Use native HTML5 History API Implementation\n\t\t\t */\n\n\t\t\t/**\n\t\t\t * History.onPopState(event,extra)\n\t\t\t * Refresh the Current State\n\t\t\t */\n\t\t\tHistory.onPopState = function(event,extra){\n\t\t\t\t// Prepare\n\t\t\t\tvar stateId = false, newState = false, currentHash, currentState;\n\n\t\t\t\t// Reset the double check\n\t\t\t\tHistory.doubleCheckComplete();\n\n\t\t\t\t// Check for a Hash, and handle apporiatly\n\t\t\t\tcurrentHash\t= History.getHash();\n\t\t\t\tif ( currentHash ) {\n\t\t\t\t\t// Expand Hash\n\t\t\t\t\tcurrentState = History.extractState(currentHash||document.location.href,true);\n\t\t\t\t\tif ( currentState ) {\n\t\t\t\t\t\t// We were able to parse it, it must be a State!\n\t\t\t\t\t\t// Let's forward to replaceState\n\t\t\t\t\t\t//History.debug('History.onPopState: state anchor', currentHash, currentState);\n\t\t\t\t\t\tHistory.replaceState(currentState.data, currentState.title, currentState.url, false);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\t// Traditional Anchor\n\t\t\t\t\t\t//History.debug('History.onPopState: traditional anchor', currentHash);\n\t\t\t\t\t\tHistory.Adapter.trigger(window,'anchorchange');\n\t\t\t\t\t\tHistory.busy(false);\n\t\t\t\t\t}\n\n\t\t\t\t\t// We don't care for hashes\n\t\t\t\t\tHistory.expectedStateId = false;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Ensure\n\t\t\t\tstateId = History.Adapter.extractEventData('state',event,extra) || false;\n\n\t\t\t\t// Fetch State\n\t\t\t\tif ( stateId ) {\n\t\t\t\t\t// Vanilla: Back/forward button was used\n\t\t\t\t\tnewState = History.getStateById(stateId);\n\t\t\t\t}\n\t\t\t\telse if ( History.expectedStateId ) {\n\t\t\t\t\t// Vanilla: A new state was pushed, and popstate was called manually\n\t\t\t\t\tnewState = History.getStateById(History.expectedStateId);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Initial State\n\t\t\t\t\tnewState = History.extractState(document.location.href);\n\t\t\t\t}\n\n\t\t\t\t// The State did not exist in our store\n\t\t\t\tif ( !newState ) {\n\t\t\t\t\t// Regenerate the State\n\t\t\t\t\tnewState = History.createStateObject(null,null,document.location.href);\n\t\t\t\t}\n\n\t\t\t\t// Clean\n\t\t\t\tHistory.expectedStateId = false;\n\n\t\t\t\t// Check if we are the same state\n\t\t\t\tif ( History.isLastSavedState(newState) ) {\n\t\t\t\t\t// There has been no change (just the page's hash has finally propagated)\n\t\t\t\t\t//History.debug('History.onPopState: no change', newState, History.savedStates);\n\t\t\t\t\tHistory.busy(false);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Store the State\n\t\t\t\tHistory.storeState(newState);\n\t\t\t\tHistory.saveState(newState);\n\n\t\t\t\t// Force update of the title\n\t\t\t\tHistory.setTitle(newState);\n\n\t\t\t\t// Fire Our Event\n\t\t\t\tHistory.Adapter.trigger(window,'statechange');\n\t\t\t\tHistory.busy(false);\n\n\t\t\t\t// Return true\n\t\t\t\treturn true;\n\t\t\t};\n\t\t\tHistory.Adapter.bind(window,'popstate',History.onPopState);\n\n\t\t\t/**\n\t\t\t * History.pushState(data,title,url)\n\t\t\t * Add a new State to the history object, become it, and trigger onpopstate\n\t\t\t * We have to trigger for HTML4 compatibility\n\t\t\t * @param {object} data\n\t\t\t * @param {string} title\n\t\t\t * @param {string} url\n\t\t\t * @return {true}\n\t\t\t */\n\t\t\tHistory.pushState = function(data,title,url,queue){\n\t\t\t\t//History.debug('History.pushState: called', arguments);\n\n\t\t\t\t// Check the State\n\t\t\t\tif ( History.getHashByUrl(url) && History.emulated.pushState ) {\n\t\t\t\t\tthrow new Error('History.js does not support states with fragement-identifiers (hashes/anchors).');\n\t\t\t\t}\n\n\t\t\t\t// Handle Queueing\n\t\t\t\tif ( queue !== false && History.busy() ) {\n\t\t\t\t\t// Wait + Push to Queue\n\t\t\t\t\t//History.debug('History.pushState: we must wait', arguments);\n\t\t\t\t\tHistory.pushQueue({\n\t\t\t\t\t\tscope: History,\n\t\t\t\t\t\tcallback: History.pushState,\n\t\t\t\t\t\targs: arguments,\n\t\t\t\t\t\tqueue: queue\n\t\t\t\t\t});\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Make Busy + Continue\n\t\t\t\tHistory.busy(true);\n\n\t\t\t\t// Create the newState\n\t\t\t\tvar newState = History.createStateObject(data,title,url);\n\n\t\t\t\t// Check it\n\t\t\t\tif ( History.isLastSavedState(newState) ) {\n\t\t\t\t\t// Won't be a change\n\t\t\t\t\tHistory.busy(false);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Store the newState\n\t\t\t\t\tHistory.storeState(newState);\n\t\t\t\t\tHistory.expectedStateId = newState.id;\n\n\t\t\t\t\t// Push the newState\n\t\t\t\t\thistory.pushState(newState.id,newState.title,newState.url);\n\n\t\t\t\t\t// Fire HTML5 Event\n\t\t\t\t\tHistory.Adapter.trigger(window,'popstate');\n\t\t\t\t}\n\n\t\t\t\t// End pushState closure\n\t\t\t\treturn true;\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * History.replaceState(data,title,url)\n\t\t\t * Replace the State and trigger onpopstate\n\t\t\t * We have to trigger for HTML4 compatibility\n\t\t\t * @param {object} data\n\t\t\t * @param {string} title\n\t\t\t * @param {string} url\n\t\t\t * @return {true}\n\t\t\t */\n\t\t\tHistory.replaceState = function(data,title,url,queue){\n\t\t\t\t//History.debug('History.replaceState: called', arguments);\n\n\t\t\t\t// Check the State\n\t\t\t\tif ( History.getHashByUrl(url) && History.emulated.pushState ) {\n\t\t\t\t\tthrow new Error('History.js does not support states with fragement-identifiers (hashes/anchors).');\n\t\t\t\t}\n\n\t\t\t\t// Handle Queueing\n\t\t\t\tif ( queue !== false && History.busy() ) {\n\t\t\t\t\t// Wait + Push to Queue\n\t\t\t\t\t//History.debug('History.replaceState: we must wait', arguments);\n\t\t\t\t\tHistory.pushQueue({\n\t\t\t\t\t\tscope: History,\n\t\t\t\t\t\tcallback: History.replaceState,\n\t\t\t\t\t\targs: arguments,\n\t\t\t\t\t\tqueue: queue\n\t\t\t\t\t});\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Make Busy + Continue\n\t\t\t\tHistory.busy(true);\n\n\t\t\t\t// Create the newState\n\t\t\t\tvar newState = History.createStateObject(data,title,url);\n\n\t\t\t\t// Check it\n\t\t\t\tif ( History.isLastSavedState(newState) ) {\n\t\t\t\t\t// Won't be a change\n\t\t\t\t\tHistory.busy(false);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Store the newState\n\t\t\t\t\tHistory.storeState(newState);\n\t\t\t\t\tHistory.expectedStateId = newState.id;\n\n\t\t\t\t\t// Push the newState\n\t\t\t\t\thistory.replaceState(newState.id,newState.title,newState.url);\n\n\t\t\t\t\t// Fire HTML5 Event\n\t\t\t\t\tHistory.Adapter.trigger(window,'popstate');\n\t\t\t\t}\n\n\t\t\t\t// End replaceState closure\n\t\t\t\treturn true;\n\t\t\t};\n\n\t\t} // !History.emulated.pushState\n\n\n\t\t// ====================================================================\n\t\t// Initialise\n\n\t\t/**\n\t\t * Load the Store\n\t\t */\n\t\tif ( sessionStorage ) {\n\t\t\t// Fetch\n\t\t\ttry {\n\t\t\t\tHistory.store = JSON.parse(sessionStorage.getItem('History.store'))||{};\n\t\t\t}\n\t\t\tcatch ( err ) {\n\t\t\t\tHistory.store = {};\n\t\t\t}\n\n\t\t\t// Normalize\n\t\t\tHistory.normalizeStore();\n\t\t}\n\t\telse {\n\t\t\t// Default Load\n\t\t\tHistory.store = {};\n\t\t\tHistory.normalizeStore();\n\t\t}\n\n\t\t/**\n\t\t * Clear Intervals on exit to prevent memory leaks\n\t\t */\n\t\tHistory.Adapter.bind(window,\"beforeunload\",History.clearAllIntervals);\n\t\tHistory.Adapter.bind(window,\"unload\",History.clearAllIntervals);\n\n\t\t/**\n\t\t * Create the initial State\n\t\t */\n\t\tHistory.saveState(History.storeState(History.extractState(document.location.href,true)));\n\n\t\t/**\n\t\t * Bind for Saving Store\n\t\t */\n\t\tif ( sessionStorage ) {\n\t\t\t// When the page is closed\n\t\t\tHistory.onUnload = function(){\n\t\t\t\t// Prepare\n\t\t\t\tvar\tcurrentStore, item;\n\n\t\t\t\t// Fetch\n\t\t\t\ttry {\n\t\t\t\t\tcurrentStore = JSON.parse(sessionStorage.getItem('History.store'))||{};\n\t\t\t\t}\n\t\t\t\tcatch ( err ) {\n\t\t\t\t\tcurrentStore = {};\n\t\t\t\t}\n\n\t\t\t\t// Ensure\n\t\t\t\tcurrentStore.idToState = currentStore.idToState || {};\n\t\t\t\tcurrentStore.urlToId = currentStore.urlToId || {};\n\t\t\t\tcurrentStore.stateToId = currentStore.stateToId || {};\n\n\t\t\t\t// Sync\n\t\t\t\tfor ( item in History.idToState ) {\n\t\t\t\t\tif ( !History.idToState.hasOwnProperty(item) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tcurrentStore.idToState[item] = History.idToState[item];\n\t\t\t\t}\n\t\t\t\tfor ( item in History.urlToId ) {\n\t\t\t\t\tif ( !History.urlToId.hasOwnProperty(item) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tcurrentStore.urlToId[item] = History.urlToId[item];\n\t\t\t\t}\n\t\t\t\tfor ( item in History.stateToId ) {\n\t\t\t\t\tif ( !History.stateToId.hasOwnProperty(item) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tcurrentStore.stateToId[item] = History.stateToId[item];\n\t\t\t\t}\n\n\t\t\t\t// Update\n\t\t\t\tHistory.store = currentStore;\n\t\t\t\tHistory.normalizeStore();\n\n\t\t\t\t// Store\n\t\t\t\tsessionStorage.setItem('History.store',JSON.stringify(currentStore));\n\t\t\t};\n\n\t\t\t// For Internet Explorer\n\t\t\tHistory.intervalList.push(setInterval(History.onUnload,History.options.storeInterval));\n\t\t\t\n\t\t\t// For Other Browsers\n\t\t\tHistory.Adapter.bind(window,'beforeunload',History.onUnload);\n\t\t\tHistory.Adapter.bind(window,'unload',History.onUnload);\n\t\t\t\n\t\t\t// Both are enabled for consistency\n\t\t}\n\n\t\t// Non-Native pushState Implementation\n\t\tif ( !History.emulated.pushState ) {\n\t\t\t// Be aware, the following is only for native pushState implementations\n\t\t\t// If you are wanting to include something for all browsers\n\t\t\t// Then include it above this if block\n\n\t\t\t/**\n\t\t\t * Setup Safari Fix\n\t\t\t */\n\t\t\tif ( History.bugs.safariPoll ) {\n\t\t\t\tHistory.intervalList.push(setInterval(History.safariStatePoll, History.options.safariPollInterval));\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Ensure Cross Browser Compatibility\n\t\t\t */\n\t\t\tif ( navigator.vendor === 'Apple Computer, Inc.' || (navigator.appCodeName||'') === 'Mozilla' ) {\n\t\t\t\t/**\n\t\t\t\t * Fix Safari HashChange Issue\n\t\t\t\t */\n\n\t\t\t\t// Setup Alias\n\t\t\t\tHistory.Adapter.bind(window,'hashchange',function(){\n\t\t\t\t\tHistory.Adapter.trigger(window,'popstate');\n\t\t\t\t});\n\n\t\t\t\t// Initialise Alias\n\t\t\t\tif ( History.getHash() ) {\n\t\t\t\t\tHistory.Adapter.onDomLoad(function(){\n\t\t\t\t\t\tHistory.Adapter.trigger(window,'hashchange');\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t} // !History.emulated.pushState\n\n\n\t}; // History.initCore\n\n\t// Try and Initialise History\n\tHistory.init();\n\n})(window);\n"
  },
  {
    "path": "packages/non-core/jquery-history/package.js",
    "content": "Package.describe({\n  name: \"jquery-history\",\n  summary: \"Deprecated package for HTML5 pushState\",\n  version: \"1.0.2\"\n});\n\nPackage.onUse(function (api) {\n  api.versionsFrom('1.0');\n  api.use('json', 'client');\n  api.use('jquery', 'client');\n  api.addFiles(['history.adapter.jquery.js',\n                 'history.html4.js',\n                 'history.js'],\n                'client');\n});\n"
  },
  {
    "path": "packages/non-core/jquery-layout/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/non-core/jquery-layout/jquery.layout.js",
    "content": "/**\r\n * @preserve\r\n * jquery.layout 1.3.0 - Release Candidate 30.79\r\n * $Date: 2013-01-12 08:00:00 (Sat, 12 Jan 2013) $\r\n * $Rev: 303007 $\r\n *\r\n * Copyright (c) 2012 \r\n *   Fabrizio Balliano (http://www.fabrizioballiano.net)\r\n *   Kevin Dalman (http://allpro.net)\r\n *\r\n * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)\r\n * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.\r\n *\r\n * Changelog: http://layout.jquery-dev.net/changelog.cfm#1.3.0.rc30.79\r\n *\r\n * Docs: http://layout.jquery-dev.net/documentation.html\r\n * Tips: http://layout.jquery-dev.net/tips.html\r\n * Help: http://groups.google.com/group/jquery-ui-layout\r\n */\r\n\r\n/* JavaDoc Info: http://code.google.com/closure/compiler/docs/js-for-compiler.html\r\n * {!Object}\tnon-nullable type (never NULL)\r\n * {?string}\tnullable type (sometimes NULL) - default for {Object}\r\n * {number=}\toptional parameter\r\n * {*}\t\t\tALL types\r\n */\r\n/*\tTODO for jQ 2.0 \r\n *\tchange .andSelf() to .addBack()\r\n *\t$.fn.disableSelection won't work\r\n */\r\n\r\n// NOTE: For best readability, view with a fixed-width font and tabs equal to 4-chars\r\n\r\n;(function ($) {\r\n\r\n// alias Math methods - used a lot!\r\nvar\tmin\t\t= Math.min\r\n,\tmax\t\t= Math.max\r\n,\tround\t= Math.floor\r\n\r\n,\tisStr\t=  function (v) { return $.type(v) === \"string\"; }\r\n\r\n\t/**\r\n\t* @param {!Object}\t\t\tInstance\r\n\t* @param {Array.<string>}\ta_fn\r\n\t*/\r\n,\trunPluginCallbacks = function (Instance, a_fn) {\r\n\t\tif ($.isArray(a_fn))\r\n\t\t\tfor (var i=0, c=a_fn.length; i<c; i++) {\r\n\t\t\t\tvar fn = a_fn[i];\r\n\t\t\t\ttry {\r\n\t\t\t\t\tif (isStr(fn)) // 'name' of a function\r\n\t\t\t\t\t\tfn = eval(fn);\r\n\t\t\t\t\tif ($.isFunction(fn))\r\n\t\t\t\t\t\tg(fn)( Instance );\r\n\t\t\t\t} catch (ex) {}\r\n\t\t\t}\r\n\t\tfunction g (f) { return f; }; // compiler hack\r\n\t}\r\n;\r\n\r\n/*\r\n *\tGENERIC $.layout METHODS - used by all layouts\r\n */\r\n$.layout = {\r\n\r\n\tversion:\t\"1.3.rc30.79\"\r\n,\trevision:\t0.033007 // 1.3.0 final = 1.0300 - major(n+).minor(nn)+patch(nn+)\r\n\r\n\t// $.layout.browser REPLACES $.browser\r\n,\tbrowser:\t{} // set below\r\n\r\n\t// *PREDEFINED* EFFECTS & DEFAULTS \r\n\t// MUST list effect here - OR MUST set an fxSettings option (can be an empty hash: {})\r\n,\teffects: {\r\n\r\n\t//\tPane Open/Close Animations\r\n\t\tslide: {\r\n\t\t\tall:\t{ duration:  \"fast\"\t} // eg: duration: 1000, easing: \"easeOutBounce\"\r\n\t\t,\tnorth:\t{ direction: \"up\"\t}\r\n\t\t,\tsouth:\t{ direction: \"down\"\t}\r\n\t\t,\teast:\t{ direction: \"right\"}\r\n\t\t,\twest:\t{ direction: \"left\"\t}\r\n\t\t}\r\n\t,\tdrop: {\r\n\t\t\tall:\t{ duration:  \"slow\"\t}\r\n\t\t,\tnorth:\t{ direction: \"up\"\t}\r\n\t\t,\tsouth:\t{ direction: \"down\"\t}\r\n\t\t,\teast:\t{ direction: \"right\"}\r\n\t\t,\twest:\t{ direction: \"left\"\t}\r\n\t\t}\r\n\t,\tscale: {\r\n\t\t\tall:\t{ duration:\t\"fast\"\t}\r\n\t\t}\r\n\t//\tthese are not recommended, but can be used\r\n\t,\tblind:\t\t{}\r\n\t,\tclip:\t\t{}\r\n\t,\texplode:\t{}\r\n\t,\tfade:\t\t{}\r\n\t,\tfold:\t\t{}\r\n\t,\tpuff:\t\t{}\r\n\r\n\t//\tPane Resize Animations\r\n\t,\tsize: {\r\n\t\t\tall:\t{ easing:\t\"swing\"\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// INTERNAL CONFIG DATA - DO NOT CHANGE THIS!\r\n,\tconfig: {\r\n\t\toptionRootKeys:\t\"effects,panes,north,south,west,east,center\".split(\",\")\r\n\t,\tallPanes:\t\t\"north,south,west,east,center\".split(\",\")\r\n\t,\tborderPanes:\t\"north,south,west,east\".split(\",\")\r\n\t,\toppositeEdge: {\r\n\t\t\tnorth:\t\"south\"\r\n\t\t,\tsouth:\t\"north\"\r\n\t\t,\teast: \t\"west\"\r\n\t\t,\twest: \t\"east\"\r\n\t\t}\r\n\t//\toffscreen data\r\n\t,\toffscreenCSS:\t{ left: \"-99999px\", right: \"auto\" } // used by hide/close if useOffscreenClose=true\r\n\t,\toffscreenReset:\t\"offscreenReset\" // key used for data\r\n\t//\tCSS used in multiple places\r\n\t,\thidden:\t\t{ visibility: \"hidden\" }\r\n\t,\tvisible:\t{ visibility: \"visible\" }\r\n\t//\tlayout element settings\r\n\t,\tresizers: {\r\n\t\t\tcssReq: {\r\n\t\t\t\tposition: \t\"absolute\"\r\n\t\t\t,\tpadding: \t0\r\n\t\t\t,\tmargin: \t0\r\n\t\t\t,\tfontSize:\t\"1px\"\r\n\t\t\t,\ttextAlign:\t\"left\"\t// to counter-act \"center\" alignment!\r\n\t\t\t,\toverflow: \t\"hidden\" // prevent toggler-button from overflowing\r\n\t\t\t//\tSEE $.layout.defaults.zIndexes.resizer_normal\r\n\t\t\t}\r\n\t\t,\tcssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true\r\n\t\t\t\tbackground: \"#DDD\"\r\n\t\t\t,\tborder:\t\t\"none\"\r\n\t\t\t}\r\n\t\t}\r\n\t,\ttogglers: {\r\n\t\t\tcssReq: {\r\n\t\t\t\tposition: \t\"absolute\"\r\n\t\t\t,\tdisplay: \t\"block\"\r\n\t\t\t,\tpadding: \t0\r\n\t\t\t,\tmargin: \t0\r\n\t\t\t,\toverflow:\t\"hidden\"\r\n\t\t\t,\ttextAlign:\t\"center\"\r\n\t\t\t,\tfontSize:\t\"1px\"\r\n\t\t\t,\tcursor: \t\"pointer\"\r\n\t\t\t,\tzIndex: \t1\r\n\t\t\t}\r\n\t\t,\tcssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true\r\n\t\t\t\tbackground: \"#AAA\"\r\n\t\t\t}\r\n\t\t}\r\n\t,\tcontent: {\r\n\t\t\tcssReq: {\r\n\t\t\t\tposition:\t\"relative\" /* contain floated or positioned elements */\r\n\t\t\t}\r\n\t\t,\tcssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true\r\n\t\t\t\toverflow:\t\"auto\"\r\n\t\t\t,\tpadding:\t\"10px\"\r\n\t\t\t}\r\n\t\t,\tcssDemoPane: { // DEMO CSS - REMOVE scrolling from 'pane' when it has a content-div\r\n\t\t\t\toverflow:\t\"hidden\"\r\n\t\t\t,\tpadding:\t0\r\n\t\t\t}\r\n\t\t}\r\n\t,\tpanes: { // defaults for ALL panes - overridden by 'per-pane settings' below\r\n\t\t\tcssReq: {\r\n\t\t\t\tposition: \t\"absolute\"\r\n\t\t\t,\tmargin:\t\t0\r\n\t\t\t//\t$.layout.defaults.zIndexes.pane_normal\r\n\t\t\t}\r\n\t\t,\tcssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true\r\n\t\t\t\tpadding:\t\"10px\"\r\n\t\t\t,\tbackground:\t\"#FFF\"\r\n\t\t\t,\tborder:\t\t\"1px solid #BBB\"\r\n\t\t\t,\toverflow:\t\"auto\"\r\n\t\t\t}\r\n\t\t}\r\n\t,\tnorth: {\r\n\t\t\tside:\t\t\t\"top\"\r\n\t\t,\tsizeType:\t\t\"Height\"\r\n\t\t,\tdir:\t\t\t\"horz\"\r\n\t\t,\tcssReq: {\r\n\t\t\t\ttop: \t\t0\r\n\t\t\t,\tbottom: \t\"auto\"\r\n\t\t\t,\tleft: \t\t0\r\n\t\t\t,\tright: \t\t0\r\n\t\t\t,\twidth: \t\t\"auto\"\r\n\t\t\t//\theight: \tDYNAMIC\r\n\t\t\t}\r\n\t\t}\r\n\t,\tsouth: {\r\n\t\t\tside:\t\t\t\"bottom\"\r\n\t\t,\tsizeType:\t\t\"Height\"\r\n\t\t,\tdir:\t\t\t\"horz\"\r\n\t\t,\tcssReq: {\r\n\t\t\t\ttop: \t\t\"auto\"\r\n\t\t\t,\tbottom: \t0\r\n\t\t\t,\tleft: \t\t0\r\n\t\t\t,\tright: \t\t0\r\n\t\t\t,\twidth: \t\t\"auto\"\r\n\t\t\t//\theight: \tDYNAMIC\r\n\t\t\t}\r\n\t\t}\r\n\t,\teast: {\r\n\t\t\tside:\t\t\t\"right\"\r\n\t\t,\tsizeType:\t\t\"Width\"\r\n\t\t,\tdir:\t\t\t\"vert\"\r\n\t\t,\tcssReq: {\r\n\t\t\t\tleft: \t\t\"auto\"\r\n\t\t\t,\tright: \t\t0\r\n\t\t\t,\ttop: \t\t\"auto\" // DYNAMIC\r\n\t\t\t,\tbottom: \t\"auto\" // DYNAMIC\r\n\t\t\t,\theight: \t\"auto\"\r\n\t\t\t//\twidth: \t\tDYNAMIC\r\n\t\t\t}\r\n\t\t}\r\n\t,\twest: {\r\n\t\t\tside:\t\t\t\"left\"\r\n\t\t,\tsizeType:\t\t\"Width\"\r\n\t\t,\tdir:\t\t\t\"vert\"\r\n\t\t,\tcssReq: {\r\n\t\t\t\tleft: \t\t0\r\n\t\t\t,\tright: \t\t\"auto\"\r\n\t\t\t,\ttop: \t\t\"auto\" // DYNAMIC\r\n\t\t\t,\tbottom: \t\"auto\" // DYNAMIC\r\n\t\t\t,\theight: \t\"auto\"\r\n\t\t\t//\twidth: \t\tDYNAMIC\r\n\t\t\t}\r\n\t\t}\r\n\t,\tcenter: {\r\n\t\t\tdir:\t\t\t\"center\"\r\n\t\t,\tcssReq: {\r\n\t\t\t\tleft: \t\t\"auto\" // DYNAMIC\r\n\t\t\t,\tright: \t\t\"auto\" // DYNAMIC\r\n\t\t\t,\ttop: \t\t\"auto\" // DYNAMIC\r\n\t\t\t,\tbottom: \t\"auto\" // DYNAMIC\r\n\t\t\t,\theight: \t\"auto\"\r\n\t\t\t,\twidth: \t\t\"auto\"\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// CALLBACK FUNCTION NAMESPACE - used to store reusable callback functions\r\n,\tcallbacks: {}\r\n\r\n,\tgetParentPaneElem: function (el) {\r\n\t\t// must pass either a container or pane element\r\n\t\tvar $el = $(el)\r\n\t\t,\tlayout = $el.data(\"layout\") || $el.data(\"parentLayout\");\r\n\t\tif (layout) {\r\n\t\t\tvar $cont = layout.container;\r\n\t\t\t// see if this container is directly-nested inside an outer-pane\r\n\t\t\tif ($cont.data(\"layoutPane\")) return $cont;\r\n\t\t\tvar $pane = $cont.closest(\".\"+ $.layout.defaults.panes.paneClass);\r\n\t\t\t// if a pane was found, return it\r\n\t\t\tif ($pane.data(\"layoutPane\")) return $pane;\r\n\t\t}\r\n\t\treturn null;\r\n\t}\r\n\r\n,\tgetParentPaneInstance: function (el) {\r\n\t\t// must pass either a container or pane element\r\n\t\tvar $pane = $.layout.getParentPaneElem(el);\r\n\t\treturn $pane ? $pane.data(\"layoutPane\") : null;\r\n\t}\r\n\r\n,\tgetParentLayoutInstance: function (el) {\r\n\t\t// must pass either a container or pane element\r\n\t\tvar $pane = $.layout.getParentPaneElem(el);\r\n\t\treturn $pane ? $pane.data(\"parentLayout\") : null;\r\n\t}\r\n\r\n,\tgetEventObject: function (evt) {\r\n\t\treturn typeof evt === \"object\" && evt.stopPropagation ? evt : null;\r\n\t}\r\n,\tparsePaneName: function (evt_or_pane) {\r\n\t\tvar evt = $.layout.getEventObject( evt_or_pane )\r\n\t\t,\tpane = evt_or_pane;\r\n\t\tif (evt) {\r\n\t\t\t// ALWAYS stop propagation of events triggered in Layout!\r\n\t\t\tevt.stopPropagation();\r\n\t\t\tpane = $(this).data(\"layoutEdge\");\r\n\t\t}\r\n\t\tif (pane && !/^(west|east|north|south|center)$/.test(pane)) {\r\n\t\t\t$.layout.msg('LAYOUT ERROR - Invalid pane-name: \"'+ pane +'\"');\r\n\t\t\tpane = \"error\";\r\n\t\t}\r\n\t\treturn pane;\r\n\t}\r\n\r\n\r\n\t// LAYOUT-PLUGIN REGISTRATION\r\n\t// more plugins can added beyond this default list\r\n,\tplugins: {\r\n\t\tdraggable:\t\t!!$.fn.draggable // resizing\r\n\t,\teffects: {\r\n\t\t\tcore:\t\t!!$.effects\t\t// animimations (specific effects tested by initOptions)\r\n\t\t,\tslide:\t\t$.effects && ($.effects.slide || ($.effects.effect && $.effects.effect.slide)) // default effect\r\n\t\t}\r\n\t}\r\n\r\n//\tarrays of plugin or other methods to be triggered for events in *each layout* - will be passed 'Instance'\r\n,\tonCreate:\t[]\t// runs when layout is just starting to be created - right after options are set\r\n,\tonLoad:\t\t[]\t// runs after layout container and global events init, but before initPanes is called\r\n,\tonReady:\t[]\t// runs after initialization *completes* - ie, after initPanes completes successfully\r\n,\tonDestroy:\t[]\t// runs after layout is destroyed\r\n,\tonUnload:\t[]\t// runs after layout is destroyed OR when page unloads\r\n,\tafterOpen:\t[]\t// runs after setAsOpen() completes\r\n,\tafterClose:\t[]\t// runs after setAsClosed() completes\r\n\r\n\t/*\r\n\t*\tGENERIC UTILITY METHODS\r\n\t*/\r\n\r\n\t// calculate and return the scrollbar width, as an integer\r\n,\tscrollbarWidth:\t\tfunction () { return window.scrollbarWidth  || $.layout.getScrollbarSize('width'); }\r\n,\tscrollbarHeight:\tfunction () { return window.scrollbarHeight || $.layout.getScrollbarSize('height'); }\r\n,\tgetScrollbarSize:\tfunction (dim) {\r\n\t\tvar $c\t= $('<div style=\"position: absolute; top: -10000px; left: -10000px; width: 100px; height: 100px; overflow: scroll;\"></div>').appendTo(\"body\");\r\n\t\tvar d\t= { width: $c.css(\"width\") - $c[0].clientWidth, height: $c.height() - $c[0].clientHeight };\r\n\t\t$c.remove();\r\n\t\twindow.scrollbarWidth\t= d.width;\r\n\t\twindow.scrollbarHeight\t= d.height;\r\n\t\treturn dim.match(/^(width|height)$/) ? d[dim] : d;\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* Returns hash container 'display' and 'visibility'\r\n\t*\r\n\t* @see\t$.swap() - swaps CSS, runs callback, resets CSS\r\n\t* @param  {!Object}\t\t$E\t\t\t\tjQuery element\r\n\t* @param  {boolean=}\t[force=false]\tRun even if display != none\r\n\t* @return {!Object}\t\t\t\t\t\tReturns current style props, if applicable\r\n\t*/\r\n,\tshowInvisibly: function ($E, force) {\r\n\t\tif ($E && $E.length && (force || $E.css(\"display\") === \"none\")) { // only if not *already hidden*\r\n\t\t\tvar s = $E[0].style\r\n\t\t\t\t// save ONLY the 'style' props because that is what we must restore\r\n\t\t\t,\tCSS = { display: s.display || '', visibility: s.visibility || '' };\r\n\t\t\t// show element 'invisibly' so can be measured\r\n\t\t\t$E.css({ display: \"block\", visibility: \"hidden\" });\r\n\t\t\treturn CSS;\r\n\t\t}\r\n\t\treturn {};\r\n\t}\r\n\r\n\t/**\r\n\t* Returns data for setting size of an element (container or a pane).\r\n\t*\r\n\t* @see  _create(), onWindowResize() for container, plus others for pane\r\n\t* @return JSON  Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc\r\n\t*/\r\n,\tgetElementDimensions: function ($E, inset) {\r\n\t\tvar\r\n\t\t//\tdimensions hash - start with current data IF passed\r\n\t\t\td\t= { css: {}, inset: {} }\r\n\t\t,\tx\t= d.css\t\t\t// CSS hash\r\n\t\t,\ti\t= { bottom: 0 }\t// TEMP insets (bottom = complier hack)\r\n\t\t,\tN\t= $.layout.cssNum\r\n\t\t,\toff = $E.offset()\r\n\t\t,\tb, p, ei\t\t\t// TEMP border, padding\r\n\t\t;\r\n\t\td.offsetLeft = off.left;\r\n\t\td.offsetTop  = off.top;\r\n\r\n\t\tif (!inset) inset = {}; // simplify logic below\r\n\r\n\t\t$.each(\"Left,Right,Top,Bottom\".split(\",\"), function (idx, e) { // e = edge\r\n\t\t\tb = x[\"border\" + e] = $.layout.borderWidth($E, e);\r\n\t\t\tp = x[\"padding\"+ e] = $.layout.cssNum($E, \"padding\"+e);\r\n\t\t\tei = e.toLowerCase();\r\n\t\t\td.inset[ei] = inset[ei] >= 0 ? inset[ei] : p; // any missing insetX value = paddingX\r\n\t\t\ti[ei] = d.inset[ei] + b; // total offset of content from outer side\r\n\t\t});\r\n\r\n\t\tx.width\t\t= $E.width();\r\n\t\tx.height\t= $E.height();\r\n\t\tx.top\t\t= N($E,\"top\",true);\r\n\t\tx.bottom\t= N($E,\"bottom\",true);\r\n\t\tx.left\t\t= N($E,\"left\",true);\r\n\t\tx.right\t\t= N($E,\"right\",true);\r\n\r\n\t\td.outerWidth\t= $E.outerWidth();\r\n\t\td.outerHeight\t= $E.outerHeight();\r\n\t\t// calc the TRUE inner-dimensions, even in quirks-mode!\r\n\t\td.innerWidth\t= max(0, d.outerWidth  - i.left - i.right);\r\n\t\td.innerHeight\t= max(0, d.outerHeight - i.top  - i.bottom);\r\n\t\t// layoutWidth/Height is used in calcs for manual resizing\r\n\t\t// layoutW/H only differs from innerW/H when in quirks-mode - then is like outerW/H\r\n\t\td.layoutWidth\t= $E.innerWidth();\r\n\t\td.layoutHeight\t= $E.innerHeight();\r\n\r\n\t\t//if ($E.prop('tagName') === 'BODY') { debugData( d, $E.prop('tagName') ); } // DEBUG\r\n\r\n\t\t//d.visible\t= $E.is(\":visible\");// && x.width > 0 && x.height > 0;\r\n\r\n\t\treturn d;\r\n\t}\r\n\r\n,\tgetElementStyles: function ($E, list) {\r\n\t\tvar\r\n\t\t\tCSS\t= {}\r\n\t\t,\tstyle\t= $E[0].style\r\n\t\t,\tprops\t= list.split(\",\")\r\n\t\t,\tsides\t= \"Top,Bottom,Left,Right\".split(\",\")\r\n\t\t,\tattrs\t= \"Color,Style,Width\".split(\",\")\r\n\t\t,\tp, s, a, i, j, k\r\n\t\t;\r\n\t\tfor (i=0; i < props.length; i++) {\r\n\t\t\tp = props[i];\r\n\t\t\tif (p.match(/(border|padding|margin)$/))\r\n\t\t\t\tfor (j=0; j < 4; j++) {\r\n\t\t\t\t\ts = sides[j];\r\n\t\t\t\t\tif (p === \"border\")\r\n\t\t\t\t\t\tfor (k=0; k < 3; k++) {\r\n\t\t\t\t\t\t\ta = attrs[k];\r\n\t\t\t\t\t\t\tCSS[p+s+a] = style[p+s+a];\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tCSS[p+s] = style[p+s];\r\n\t\t\t\t}\r\n\t\t\telse\r\n\t\t\t\tCSS[p] = style[p];\r\n\t\t};\r\n\t\treturn CSS\r\n\t}\r\n\r\n\t/**\r\n\t* Return the innerWidth for the current browser/doctype\r\n\t*\r\n\t* @see  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()\r\n\t* @param  {Array.<Object>}\t$E  Must pass a jQuery object - first element is processed\r\n\t* @param  {number=}\t\t\touterWidth (optional) Can pass a width, allowing calculations BEFORE element is resized\r\n\t* @return {number}\t\t\tReturns the innerWidth of the elem by subtracting padding and borders\r\n\t*/\r\n,\tcssWidth: function ($E, outerWidth) {\r\n\t\t// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed\r\n\t\tif (outerWidth <= 0) return 0;\r\n\r\n\t\tvar bs\t= !$.layout.browser.boxModel ? \"border-box\" : $.support.boxSizing ? $E.css(\"boxSizing\") : \"content-box\"\r\n\t\t,\tb\t= $.layout.borderWidth\r\n\t\t,\tn\t= $.layout.cssNum\r\n\t\t,\tW\t= outerWidth\r\n\t\t;\r\n\t\t// strip border and/or padding from outerWidth to get CSS Width\r\n\t\tif (bs !== \"border-box\")\r\n\t\t\tW -= (b($E, \"Left\") + b($E, \"Right\"));\r\n\t\tif (bs === \"content-box\")\r\n\t\t\tW -= (n($E, \"paddingLeft\") + n($E, \"paddingRight\"));\r\n\t\treturn max(0,W);\r\n\t}\r\n\r\n\t/**\r\n\t* Return the innerHeight for the current browser/doctype\r\n\t*\r\n\t* @see  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()\r\n\t* @param  {Array.<Object>}\t$E  Must pass a jQuery object - first element is processed\r\n\t* @param  {number=}\t\t\touterHeight  (optional) Can pass a width, allowing calculations BEFORE element is resized\r\n\t* @return {number}\t\t\tReturns the innerHeight of the elem by subtracting padding and borders\r\n\t*/\r\n,\tcssHeight: function ($E, outerHeight) {\r\n\t\t// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed\r\n\t\tif (outerHeight <= 0) return 0;\r\n\r\n\t\tvar bs\t= !$.layout.browser.boxModel ? \"border-box\" : $.support.boxSizing ? $E.css(\"boxSizing\") : \"content-box\"\r\n\t\t,\tb\t= $.layout.borderWidth\r\n\t\t,\tn\t= $.layout.cssNum\r\n\t\t,\tH\t= outerHeight\r\n\t\t;\r\n\t\t// strip border and/or padding from outerHeight to get CSS Height\r\n\t\tif (bs !== \"border-box\")\r\n\t\t\tH -= (b($E, \"Top\") + b($E, \"Bottom\"));\r\n\t\tif (bs === \"content-box\")\r\n\t\t\tH -= (n($E, \"paddingTop\") + n($E, \"paddingBottom\"));\r\n\t\treturn max(0,H);\r\n\t}\r\n\r\n\t/**\r\n\t* Returns the 'current CSS numeric value' for a CSS property - 0 if property does not exist\r\n\t*\r\n\t* @see  Called by many methods\r\n\t* @param {Array.<Object>}\t$E\t\t\t\t\tMust pass a jQuery object - first element is processed\r\n\t* @param {string}\t\t\tprop\t\t\t\tThe name of the CSS property, eg: top, width, etc.\r\n\t* @param {boolean=}\t\t\t[allowAuto=false]\ttrue = return 'auto' if that is value; false = return 0\r\n\t* @return {(string|number)}\t\t\t\t\t\tUsually used to get an integer value for position (top, left) or size (height, width)\r\n\t*/\r\n,\tcssNum: function ($E, prop, allowAuto) {\r\n\t\tif (!$E.jquery) $E = $($E);\r\n\t\tvar CSS = $.layout.showInvisibly($E)\r\n\t\t,\tp\t= $.css($E[0], prop, true)\r\n\t\t,\tv\t= allowAuto && p==\"auto\" ? p : Math.round(parseFloat(p) || 0);\r\n\t\t$E.css( CSS ); // RESET\r\n\t\treturn v;\r\n\t}\r\n\r\n,\tborderWidth: function (el, side) {\r\n\t\tif (el.jquery) el = el[0];\r\n\t\tvar b = \"border\"+ side.substr(0,1).toUpperCase() + side.substr(1); // left => Left\r\n\t\treturn $.css(el, b+\"Style\", true) === \"none\" ? 0 : Math.round(parseFloat($.css(el, b+\"Width\", true)) || 0);\r\n\t}\r\n\r\n\t/**\r\n\t* Mouse-tracking utility - FUTURE REFERENCE\r\n\t*\r\n\t* init: if (!window.mouse) {\r\n\t*\t\t\twindow.mouse = { x: 0, y: 0 };\r\n\t*\t\t\t$(document).mousemove( $.layout.trackMouse );\r\n\t*\t\t}\r\n\t*\r\n\t* @param {Object}\t\tevt\r\n\t*\r\n,\ttrackMouse: function (evt) {\r\n\t\twindow.mouse = { x: evt.clientX, y: evt.clientY };\r\n\t}\r\n\t*/\r\n\r\n\t/**\r\n\t* SUBROUTINE for preventPrematureSlideClose option\r\n\t*\r\n\t* @param {Object}\t\tevt\r\n\t* @param {Object=}\t\tel\r\n\t*/\r\n,\tisMouseOverElem: function (evt, el) {\r\n\t\tvar\r\n\t\t\t$E\t= $(el || this)\r\n\t\t,\td\t= $E.offset()\r\n\t\t,\tT\t= d.top\r\n\t\t,\tL\t= d.left\r\n\t\t,\tR\t= L + $E.outerWidth()\r\n\t\t,\tB\t= T + $E.outerHeight()\r\n\t\t,\tx\t= evt.pageX\t// evt.clientX ?\r\n\t\t,\ty\t= evt.pageY\t// evt.clientY ?\r\n\t\t;\r\n\t\t// if X & Y are < 0, probably means is over an open SELECT\r\n\t\treturn ($.layout.browser.msie && x < 0 && y < 0) || ((x >= L && x <= R) && (y >= T && y <= B));\r\n\t}\r\n\r\n\t/**\r\n\t* Message/Logging Utility\r\n\t*\r\n\t* @example $.layout.msg(\"My message\");\t\t\t\t// log text\r\n\t* @example $.layout.msg(\"My message\", true);\t\t// alert text\r\n\t* @example $.layout.msg({ foo: \"bar\" }, \"Title\");\t// log hash-data, with custom title\r\n\t* @example $.layout.msg({ foo: \"bar\" }, true, \"Title\", { sort: false }); -OR-\r\n\t* @example $.layout.msg({ foo: \"bar\" }, \"Title\", { sort: false, display: true }); // alert hash-data\r\n\t*\r\n\t* @param {(Object|string)}\t\t\tinfo\t\t\tString message OR Hash/Array\r\n\t* @param {(Boolean|string|Object)=}\t[popup=false]\tTrue means alert-box - can be skipped\r\n\t* @param {(Object|string)=}\t\t\t[debugTitle=\"\"]\tTitle for Hash data - can be skipped\r\n\t* @param {Object=}\t\t\t\t\t[debugOpts]\t\tExtra options for debug output\r\n\t*/\r\n,\tmsg: function (info, popup, debugTitle, debugOpts) {\r\n\t\tif ($.isPlainObject(info) && window.debugData) {\r\n\t\t\tif (typeof popup === \"string\") {\r\n\t\t\t\tdebugOpts\t= debugTitle;\r\n\t\t\t\tdebugTitle\t= popup;\r\n\t\t\t}\r\n\t\t\telse if (typeof debugTitle === \"object\") {\r\n\t\t\t\tdebugOpts\t= debugTitle;\r\n\t\t\t\tdebugTitle\t= null;\r\n\t\t\t}\r\n\t\t\tvar t = debugTitle || \"log( <object> )\"\r\n\t\t\t,\to = $.extend({ sort: false, returnHTML: false, display: false }, debugOpts);\r\n\t\t\tif (popup === true || o.display)\r\n\t\t\t\tdebugData( info, t, o );\r\n\t\t\telse if (window.console)\r\n\t\t\t\tconsole.log(debugData( info, t, o ));\r\n\t\t}\r\n\t\telse if (popup)\r\n\t\t\talert(info);\r\n\t\telse if (window.console)\r\n\t\t\tconsole.log(info);\r\n\t\telse {\r\n\t\t\tvar id\t= \"#layoutLogger\"\r\n\t\t\t,\t$l = $(id);\r\n\t\t\tif (!$l.length)\r\n\t\t\t\t$l = createLog();\r\n\t\t\t$l.children(\"ul\").append('<li style=\"padding: 4px 10px; margin: 0; border-top: 1px solid #CCC;\">'+ info.replace(/\\</g,\"&lt;\").replace(/\\>/g,\"&gt;\") +'</li>');\r\n\t\t}\r\n\r\n\t\tfunction createLog () {\r\n\t\t\tvar pos = $.support.fixedPosition ? 'fixed' : 'absolute'\r\n\t\t\t,\t$e = $('<div id=\"layoutLogger\" style=\"position: '+ pos +'; top: 5px; z-index: 999999; max-width: 25%; overflow: hidden; border: 1px solid #000; border-radius: 5px; background: #FBFBFB; box-shadow: 0 2px 10px rgba(0,0,0,0.3);\">'\r\n\t\t\t\t+\t'<div style=\"font-size: 13px; font-weight: bold; padding: 5px 10px; background: #F6F6F6; border-radius: 5px 5px 0 0; cursor: move;\">'\r\n\t\t\t\t+\t'<span style=\"float: right; padding-left: 7px; cursor: pointer;\" title=\"Remove Console\" onclick=\"$(this).closest(\\'#layoutLogger\\').remove()\">X</span>Layout console.log</div>'\r\n\t\t\t\t+\t'<ul style=\"font-size: 13px; font-weight: none; list-style: none; margin: 0; padding: 0 0 2px;\"></ul>'\r\n\t\t\t\t+ '</div>'\r\n\t\t\t\t).appendTo(\"body\");\r\n\t\t\t$e.css('left', $(window).width() - $e.outerWidth() - 5)\r\n\t\t\tif ($.ui.draggable) $e.draggable({ handle: ':first-child' });\r\n\t\t\treturn $e;\r\n\t\t};\r\n\t}\r\n\r\n};\r\n\r\n\r\n/*\r\n *\t$.layout.browser REPLACES removed $.browser, with extra data\r\n *\tParsing code here adapted from jQuery 1.8 $.browse\r\n */\r\nvar u = navigator.userAgent.toLowerCase()\r\n,\tm = /(chrome)[ \\/]([\\w.]+)/.exec( u )\r\n\t||\t/(webkit)[ \\/]([\\w.]+)/.exec( u )\r\n\t||\t/(opera)(?:.*version|)[ \\/]([\\w.]+)/.exec( u )\r\n\t||\t/(msie) ([\\w.]+)/.exec( u )\r\n\t||\tu.indexOf(\"compatible\") < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec( u )\r\n\t||\t[]\r\n,\tb = m[1] || \"\"\r\n,\tv = m[2] || 0\r\n,\tie = b === \"msie\"\r\n;\r\n$.layout.browser = {\r\n\tversion:\tv\r\n,\tsafari:\t\tb === \"webkit\"\t// webkit (NOT chrome) = safari\r\n,\twebkit:\t\tb === \"chrome\"\t// chrome = webkit\r\n,\tmsie:\t\tie\r\n,\tisIE6:\t\tie && v == 6\r\n\t// ONLY IE reverts to old box-model - update for older jQ onReady\r\n,\tboxModel:\t!ie || $.support.boxModel !== false\r\n};\r\nif (b) $.layout.browser[b] = true; // set CURRENT browser\r\n/*\tOLD versions of jQuery only set $.support.boxModel after page is loaded\r\n *\tso if this is IE, use support.boxModel to test for quirks-mode (ONLY IE changes boxModel) */\r\nif (ie) $(function(){ $.layout.browser.boxModel = $.support.boxModel; });\r\n\r\n\r\n// DEFAULT OPTIONS\r\n$.layout.defaults = {\r\n/*\r\n *\tLAYOUT & LAYOUT-CONTAINER OPTIONS\r\n *\t- none of these options are applicable to individual panes\r\n */\r\n\tname:\t\t\t\t\t\t\"\"\t\t\t// Not required, but useful for buttons and used for the state-cookie\r\n,\tcontainerClass:\t\t\t\t\"ui-layout-container\" // layout-container element\r\n,\tinset:\t\t\t\t\t\tnull\t\t// custom container-inset values (override padding)\r\n,\tscrollToBookmarkOnLoad:\t\ttrue\t\t// after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark)\r\n,\tresizeWithWindow:\t\t\ttrue\t\t// bind thisLayout.resizeAll() to the window.resize event\r\n,\tresizeWithWindowDelay:\t\t200\t\t\t// delay calling resizeAll because makes window resizing very jerky\r\n,\tresizeWithWindowMaxDelay:\t0\t\t\t// 0 = none - force resize every XX ms while window is being resized\r\n,\tmaskPanesEarly:\t\t\t\tfalse\t\t// true = create pane-masks on resizer.mouseDown instead of waiting for resizer.dragstart\r\n,\tonresizeall_start:\t\t\tnull\t\t// CALLBACK when resizeAll() STARTS\t- NOT pane-specific\r\n,\tonresizeall_end:\t\t\tnull\t\t// CALLBACK when resizeAll() ENDS\t- NOT pane-specific\r\n,\tonload_start:\t\t\t\tnull\t\t// CALLBACK when Layout inits - after options initialized, but before elements\r\n,\tonload_end:\t\t\t\t\tnull\t\t// CALLBACK when Layout inits - after EVERYTHING has been initialized\r\n,\tonunload_start:\t\t\t\tnull\t\t// CALLBACK when Layout is destroyed OR onWindowUnload\r\n,\tonunload_end:\t\t\t\tnull\t\t// CALLBACK when Layout is destroyed OR onWindowUnload\r\n,\tinitPanes:\t\t\t\t\ttrue\t\t// false = DO NOT initialize the panes onLoad - will init later\r\n,\tshowErrorMessages:\t\t\ttrue\t\t// enables fatal error messages to warn developers of common errors\r\n,\tshowDebugMessages:\t\t\tfalse\t\t// display console-and-alert debug msgs - IF this Layout version _has_ debugging code!\r\n//\tChanging this zIndex value will cause other zIndex values to automatically change\r\n,\tzIndex:\t\t\t\t\t\tnull\t\t// the PANE zIndex - resizers and masks will be +1\r\n//\tDO NOT CHANGE the zIndex values below unless you clearly understand their relationships\r\n,\tzIndexes: {\t\t\t\t\t\t\t\t// set _default_ z-index values here...\r\n\t\tpane_normal:\t\t\t0\t\t\t// normal z-index for panes\r\n\t,\tcontent_mask:\t\t\t1\t\t\t// applied to overlays used to mask content INSIDE panes during resizing\r\n\t,\tresizer_normal:\t\t\t2\t\t\t// normal z-index for resizer-bars\r\n\t,\tpane_sliding:\t\t\t100\t\t\t// applied to *BOTH* the pane and its resizer when a pane is 'slid open'\r\n\t,\tpane_animate:\t\t\t1000\t\t// applied to the pane when being animated - not applied to the resizer\r\n\t,\tresizer_drag:\t\t\t10000\t\t// applied to the CLONED resizer-bar when being 'dragged'\r\n\t}\r\n,\terrors: {\r\n\t\tpane:\t\t\t\t\t\"pane\"\t\t// description of \"layout pane element\" - used only in error messages\r\n\t,\tselector:\t\t\t\t\"selector\"\t// description of \"jQuery-selector\" - used only in error messages\r\n\t,\taddButtonError:\t\t\t\"Error Adding Button\\nInvalid \"\r\n\t,\tcontainerMissing:\t\t\"UI Layout Initialization Error\\nThe specified layout-container does not exist.\"\r\n\t,\tcenterPaneMissing:\t\t\"UI Layout Initialization Error\\nThe center-pane element does not exist.\\nThe center-pane is a required element.\"\r\n\t,\tnoContainerHeight:\t\t\"UI Layout Initialization Warning\\nThe layout-container \\\"CONTAINER\\\" has no height.\\nTherefore the layout is 0-height and hence 'invisible'!\"\r\n\t,\tcallbackError:\t\t\t\"UI Layout Callback Error\\nThe EVENT callback is not a valid function.\"\r\n\t}\r\n/*\r\n *\tPANE DEFAULT SETTINGS\r\n *\t- settings under the 'panes' key become the default settings for *all panes*\r\n *\t- ALL pane-options can also be set specifically for each panes, which will override these 'default values'\r\n */\r\n,\tpanes: { // default options for 'all panes' - will be overridden by 'per-pane settings'\r\n\t\tapplyDemoStyles: \t\tfalse\t\t// NOTE: renamed from applyDefaultStyles for clarity\r\n\t,\tclosable:\t\t\t\ttrue\t\t// pane can open & close\r\n\t,\tresizable:\t\t\t\ttrue\t\t// when open, pane can be resized \r\n\t,\tslidable:\t\t\t\ttrue\t\t// when closed, pane can 'slide open' over other panes - closes on mouse-out\r\n\t,\tinitClosed:\t\t\t\tfalse\t\t// true = init pane as 'closed'\r\n\t,\tinitHidden: \t\t\tfalse \t\t// true = init pane as 'hidden' - no resizer-bar/spacing\r\n\t//\tSELECTORS\r\n\t//,\tpaneSelector:\t\t\t\"\"\t\t\t// MUST be pane-specific - jQuery selector for pane\r\n\t,\tcontentSelector:\t\t\".ui-layout-content\" // INNER div/element to auto-size so only it scrolls, not the entire pane!\r\n\t,\tcontentIgnoreSelector:\t\".ui-layout-ignore\"\t// element(s) to 'ignore' when measuring 'content'\r\n\t,\tfindNestedContent:\t\tfalse\t\t// true = $P.find(contentSelector), false = $P.children(contentSelector)\r\n\t//\tGENERIC ROOT-CLASSES - for auto-generated classNames\r\n\t,\tpaneClass:\t\t\t\t\"ui-layout-pane\"\t// Layout Pane\r\n\t,\tresizerClass:\t\t\t\"ui-layout-resizer\"\t// Resizer Bar\r\n\t,\ttogglerClass:\t\t\t\"ui-layout-toggler\"\t// Toggler Button\r\n\t,\tbuttonClass:\t\t\t\"ui-layout-button\"\t// CUSTOM Buttons\t- eg: '[ui-layout-button]-toggle/-open/-close/-pin'\r\n\t//\tELEMENT SIZE & SPACING\r\n\t//,\tsize:\t\t\t\t\t100\t\t\t// MUST be pane-specific -initial size of pane\r\n\t,\tminSize:\t\t\t\t0\t\t\t// when manually resizing a pane\r\n\t,\tmaxSize:\t\t\t\t0\t\t\t// ditto, 0 = no limit\r\n\t,\tspacing_open:\t\t\t6\t\t\t// space between pane and adjacent panes - when pane is 'open'\r\n\t,\tspacing_closed:\t\t\t6\t\t\t// ditto - when pane is 'closed'\r\n\t,\ttogglerLength_open:\t\t50\t\t\t// Length = WIDTH of toggler button on north/south sides - HEIGHT on east/west sides\r\n\t,\ttogglerLength_closed: \t50\t\t\t// 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden'\r\n\t,\ttogglerAlign_open:\t\t\"center\"\t// top/left, bottom/right, center, OR...\r\n\t,\ttogglerAlign_closed:\t\"center\"\t// 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right\r\n\t,\ttogglerContent_open:\t\"\"\t\t\t// text or HTML to put INSIDE the toggler\r\n\t,\ttogglerContent_closed:\t\"\"\t\t\t// ditto\r\n\t//\tRESIZING OPTIONS\r\n\t,\tresizerDblClickToggle:\ttrue\t\t// \r\n\t,\tautoResize:\t\t\t\ttrue\t\t// IF size is 'auto' or a percentage, then recalc 'pixel size' whenever the layout resizes\r\n\t,\tautoReopen:\t\t\t\ttrue\t\t// IF a pane was auto-closed due to noRoom, reopen it when there is room? False = leave it closed\r\n\t,\tresizerDragOpacity:\t\t1\t\t\t// option for ui.draggable\r\n\t//,\tresizerCursor:\t\t\t\"\"\t\t\t// MUST be pane-specific - cursor when over resizer-bar\r\n\t,\tmaskContents:\t\t\tfalse\t\t// true = add DIV-mask over-or-inside this pane so can 'drag' over IFRAMES\r\n\t,\tmaskObjects:\t\t\tfalse\t\t// true = add IFRAME-mask over-or-inside this pane to cover objects/applets - content-mask will overlay this mask\r\n\t,\tmaskZindex:\t\t\t\tnull\t\t// will override zIndexes.content_mask if specified - not applicable to iframe-panes\r\n\t,\tresizingGrid:\t\t\tfalse\t\t// grid size that the resizers will snap-to during resizing, eg: [20,20]\r\n\t,\tlivePaneResizing:\t\tfalse\t\t// true = LIVE Resizing as resizer is dragged\r\n\t,\tliveContentResizing:\tfalse\t\t// true = re-measure header/footer heights as resizer is dragged\r\n\t,\tliveResizingTolerance:\t1\t\t\t// how many px change before pane resizes, to control performance\r\n\t//\tSLIDING OPTIONS\r\n\t,\tsliderCursor:\t\t\t\"pointer\"\t// cursor when resizer-bar will trigger 'sliding'\r\n\t,\tslideTrigger_open:\t\t\"click\"\t\t// click, dblclick, mouseenter\r\n\t,\tslideTrigger_close:\t\t\"mouseleave\"// click, mouseleave\r\n\t,\tslideDelay_open:\t\t300\t\t\t// applies only for mouseenter event - 0 = instant open\r\n\t,\tslideDelay_close:\t\t300\t\t\t// applies only for mouseleave event (300ms is the minimum!)\r\n\t,\thideTogglerOnSlide:\t\tfalse\t\t// when pane is slid-open, should the toggler show?\r\n\t,\tpreventQuickSlideClose:\t$.layout.browser.webkit // Chrome triggers slideClosed as it is opening\r\n\t,\tpreventPrematureSlideClose: false\t// handle incorrect mouseleave trigger, like when over a SELECT-list in IE\r\n\t//\tPANE-SPECIFIC TIPS & MESSAGES\r\n\t,\ttips: {\r\n\t\t\tOpen:\t\t\t\t\"Open\"\t\t// eg: \"Open Pane\"\r\n\t\t,\tClose:\t\t\t\t\"Close\"\r\n\t\t,\tResize:\t\t\t\t\"Resize\"\r\n\t\t,\tSlide:\t\t\t\t\"Slide Open\"\r\n\t\t,\tPin:\t\t\t\t\"Pin\"\r\n\t\t,\tUnpin:\t\t\t\t\"Un-Pin\"\r\n\t\t,\tnoRoomToOpen:\t\t\"Not enough room to show this panel.\"\t// alert if user tries to open a pane that cannot\r\n\t\t,\tminSizeWarning:\t\t\"Panel has reached its minimum size\"\t// displays in browser statusbar\r\n\t\t,\tmaxSizeWarning:\t\t\"Panel has reached its maximum size\"\t// ditto\r\n\t\t}\r\n\t//\tHOT-KEYS & MISC\r\n\t,\tshowOverflowOnHover:\tfalse\t\t// will bind allowOverflow() utility to pane.onMouseOver\r\n\t,\tenableCursorHotkey:\t\ttrue\t\t// enabled 'cursor' hotkeys\r\n\t//,\tcustomHotkey:\t\t\t\"\"\t\t\t// MUST be pane-specific - EITHER a charCode OR a character\r\n\t,\tcustomHotkeyModifier:\t\"SHIFT\"\t\t// either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT'\r\n\t//\tPANE ANIMATION\r\n\t//\tNOTE: fxSss_open, fxSss_close & fxSss_size options (eg: fxName_open) are auto-generated if not passed\r\n\t,\tfxName:\t\t\t\t\t\"slide\" \t// ('none' or blank), slide, drop, scale -- only relevant to 'open' & 'close', NOT 'size'\r\n\t,\tfxSpeed:\t\t\t\tnull\t\t// slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration\r\n\t,\tfxSettings:\t\t\t\t{}\t\t\t// can be passed, eg: { easing: \"easeOutBounce\", duration: 1500 }\r\n\t,\tfxOpacityFix:\t\t\ttrue\t\t// tries to fix opacity in IE to restore anti-aliasing after animation\r\n\t,\tanimatePaneSizing:\t\tfalse\t\t// true = animate resizing after dragging resizer-bar OR sizePane() is called\r\n\t/*  NOTE: Action-specific FX options are auto-generated from the options above if not specifically set:\r\n\t\tfxName_open:\t\t\t\"slide\"\t\t// 'Open' pane animation\r\n\t\tfnName_close:\t\t\t\"slide\"\t\t// 'Close' pane animation\r\n\t\tfxName_size:\t\t\t\"slide\"\t\t// 'Size' pane animation - when animatePaneSizing = true\r\n\t\tfxSpeed_open:\t\t\tnull\r\n\t\tfxSpeed_close:\t\t\tnull\r\n\t\tfxSpeed_size:\t\t\tnull\r\n\t\tfxSettings_open:\t\t{}\r\n\t\tfxSettings_close:\t\t{}\r\n\t\tfxSettings_size:\t\t{}\r\n\t*/\r\n\t//\tCHILD/NESTED LAYOUTS\r\n\t,\tchildren:\t\t\t\tnull\t\t// Layout-options for nested/child layout - even {} is valid as options\r\n\t,\tcontainerSelector:\t\t''\t\t\t// if child is NOT 'directly nested', a selector to find it/them (can have more than one child layout!)\r\n\t,\tinitChildren:\t\t\ttrue\t\t// true = child layout will be created as soon as _this_ layout completes initialization\r\n\t,\tdestroyChildren:\t\ttrue\t\t// true = destroy child-layout if this pane is destroyed\r\n\t,\tresizeChildren:\t\t\ttrue\t\t// true = trigger child-layout.resizeAll() when this pane is resized\r\n\t//\tEVENT TRIGGERING\r\n\t,\ttriggerEventsOnLoad:\tfalse\t\t// true = trigger onopen OR onclose callbacks when layout initializes\r\n\t,\ttriggerEventsDuringLiveResize: true\t// true = trigger onresize callback REPEATEDLY if livePaneResizing==true\r\n\t//\tPANE CALLBACKS\r\n\t,\tonshow_start:\t\t\tnull\t\t// CALLBACK when pane STARTS to Show\t- BEFORE onopen/onhide_start\r\n\t,\tonshow_end:\t\t\t\tnull\t\t// CALLBACK when pane ENDS being Shown\t- AFTER  onopen/onhide_end\r\n\t,\tonhide_start:\t\t\tnull\t\t// CALLBACK when pane STARTS to Close\t- BEFORE onclose_start\r\n\t,\tonhide_end:\t\t\t\tnull\t\t// CALLBACK when pane ENDS being Closed\t- AFTER  onclose_end\r\n\t,\tonopen_start:\t\t\tnull\t\t// CALLBACK when pane STARTS to Open\r\n\t,\tonopen_end:\t\t\t\tnull\t\t// CALLBACK when pane ENDS being Opened\r\n\t,\tonclose_start:\t\t\tnull\t\t// CALLBACK when pane STARTS to Close\r\n\t,\tonclose_end:\t\t\tnull\t\t// CALLBACK when pane ENDS being Closed\r\n\t,\tonresize_start:\t\t\tnull\t\t// CALLBACK when pane STARTS being Resized ***FOR ANY REASON***\r\n\t,\tonresize_end:\t\t\tnull\t\t// CALLBACK when pane ENDS being Resized ***FOR ANY REASON***\r\n\t,\tonsizecontent_start:\tnull\t\t// CALLBACK when sizing of content-element STARTS\r\n\t,\tonsizecontent_end:\t\tnull\t\t// CALLBACK when sizing of content-element ENDS\r\n\t,\tonswap_start:\t\t\tnull\t\t// CALLBACK when pane STARTS to Swap\r\n\t,\tonswap_end:\t\t\t\tnull\t\t// CALLBACK when pane ENDS being Swapped\r\n\t,\tondrag_start:\t\t\tnull\t\t// CALLBACK when pane STARTS being ***MANUALLY*** Resized\r\n\t,\tondrag_end:\t\t\t\tnull\t\t// CALLBACK when pane ENDS being ***MANUALLY*** Resized\r\n\t}\r\n/*\r\n *\tPANE-SPECIFIC SETTINGS\r\n *\t- options listed below MUST be specified per-pane - they CANNOT be set under 'panes'\r\n *\t- all options under the 'panes' key can also be set specifically for any pane\r\n *\t- most options under the 'panes' key apply only to 'border-panes' - NOT the the center-pane\r\n */\r\n,\tnorth: {\r\n\t\tpaneSelector:\t\t\t\".ui-layout-north\"\r\n\t,\tsize:\t\t\t\t\t\"auto\"\t\t// eg: \"auto\", \"30%\", .30, 200\r\n\t,\tresizerCursor:\t\t\t\"n-resize\"\t// custom = url(myCursor.cur)\r\n\t,\tcustomHotkey:\t\t\t\"\"\t\t\t// EITHER a charCode (43) OR a character (\"o\")\r\n\t}\r\n,\tsouth: {\r\n\t\tpaneSelector:\t\t\t\".ui-layout-south\"\r\n\t,\tsize:\t\t\t\t\t\"auto\"\r\n\t,\tresizerCursor:\t\t\t\"s-resize\"\r\n\t,\tcustomHotkey:\t\t\t\"\"\r\n\t}\r\n,\teast: {\r\n\t\tpaneSelector:\t\t\t\".ui-layout-east\"\r\n\t,\tsize:\t\t\t\t\t200\r\n\t,\tresizerCursor:\t\t\t\"e-resize\"\r\n\t,\tcustomHotkey:\t\t\t\"\"\r\n\t}\r\n,\twest: {\r\n\t\tpaneSelector:\t\t\t\".ui-layout-west\"\r\n\t,\tsize:\t\t\t\t\t200\r\n\t,\tresizerCursor:\t\t\t\"w-resize\"\r\n\t,\tcustomHotkey:\t\t\t\"\"\r\n\t}\r\n,\tcenter: {\r\n\t\tpaneSelector:\t\t\t\".ui-layout-center\"\r\n\t,\tminWidth:\t\t\t\t0\r\n\t,\tminHeight:\t\t\t\t0\r\n\t}\r\n};\r\n\r\n$.layout.optionsMap = {\r\n\t// layout/global options - NOT pane-options\r\n\tlayout: (\"name,instanceKey,stateManagement,effects,inset,zIndexes,errors,\"\r\n\t+\t\"zIndex,scrollToBookmarkOnLoad,showErrorMessages,maskPanesEarly,\"\r\n\t+\t\"outset,resizeWithWindow,resizeWithWindowDelay,resizeWithWindowMaxDelay,\"\r\n\t+\t\"onresizeall,onresizeall_start,onresizeall_end,onload,onload_start,onload_end,onunload,onunload_start,onunload_end\").split(\",\")\r\n//\tborderPanes: [ ALL options that are NOT specified as 'layout' ]\r\n\t// default.panes options that apply to the center-pane (most options apply _only_ to border-panes)\r\n,\tcenter: (\"paneClass,contentSelector,contentIgnoreSelector,findNestedContent,applyDemoStyles,triggerEventsOnLoad,\"\r\n\t+\t\"showOverflowOnHover,maskContents,maskObjects,liveContentResizing,\"\r\n\t+\t\"containerSelector,children,initChildren,resizeChildren,destroyChildren,\"\r\n\t+\t\"onresize,onresize_start,onresize_end,onsizecontent,onsizecontent_start,onsizecontent_end\").split(\",\")\r\n\t// options that MUST be specifically set 'per-pane' - CANNOT set in the panes (defaults) key\r\n,\tnoDefault: (\"paneSelector,resizerCursor,customHotkey\").split(\",\")\r\n};\r\n\r\n/**\r\n * Processes options passed in converts flat-format data into subkey (JSON) format\r\n * In flat-format, subkeys are _currently_ separated with 2 underscores, like north__optName\r\n * Plugins may also call this method so they can transform their own data\r\n *\r\n * @param  {!Object}\thash\t\t\tData/options passed by user - may be a single level or nested levels\r\n * @param  {boolean=}\t[addKeys=false]\tShould the primary layout.options keys be added if they do not exist?\r\n * @return {Object}\t\t\t\t\t\tReturns hash of minWidth & minHeight\r\n */\r\n$.layout.transformData = function (hash, addKeys) {\r\n\tvar\tjson = addKeys ? { panes: {}, center: {} } : {} // init return object\r\n\t,\tbranch, optKey, keys, key, val, i, c;\r\n\r\n\tif (typeof hash !== \"object\") return json; // no options passed\r\n\r\n\t// convert all 'flat-keys' to 'sub-key' format\r\n\tfor (optKey in hash) {\r\n\t\tbranch\t= json;\r\n\t\tval\t\t= hash[ optKey ];\r\n\t\tkeys\t= optKey.split(\"__\"); // eg: west__size or north__fxSettings__duration\r\n\t\tc\t\t= keys.length - 1;\r\n\t\t// convert underscore-delimited to subkeys\r\n\t\tfor (i=0; i <= c; i++) {\r\n\t\t\tkey = keys[i];\r\n\t\t\tif (i === c) {\t// last key = value\r\n\t\t\t\tif ($.isPlainObject( val ))\r\n\t\t\t\t\tbranch[key] = $.layout.transformData( val ); // RECURSE\r\n\t\t\t\telse\r\n\t\t\t\t\tbranch[key] = val;\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tif (!branch[key])\r\n\t\t\t\t\tbranch[key] = {}; // create the subkey\r\n\t\t\t\t// recurse to sub-key for next loop - if not done\r\n\t\t\t\tbranch = branch[key];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn json;\r\n};\r\n\r\n// INTERNAL CONFIG DATA - DO NOT CHANGE THIS!\r\n$.layout.backwardCompatibility = {\r\n\t// data used by renameOldOptions()\r\n\tmap: {\r\n\t//\tOLD Option Name:\t\t\tNEW Option Name\r\n\t\tapplyDefaultStyles:\t\t\t\"applyDemoStyles\"\r\n\t//\tCHILD/NESTED LAYOUTS\r\n\t,\tchildOptions:\t\t\t\t\"children\"\r\n\t,\tinitChildLayout:\t\t\t\"initChildren\"\r\n\t,\tdestroyChildLayout:\t\t\t\"destroyChildren\"\r\n\t,\tresizeChildLayout:\t\t\t\"resizeChildren\"\r\n\t,\tresizeNestedLayout:\t\t\t\"resizeChildren\"\r\n\t//\tMISC Options\r\n\t,\tresizeWhileDragging:\t\t\"livePaneResizing\"\r\n\t,\tresizeContentWhileDragging:\t\"liveContentResizing\"\r\n\t,\ttriggerEventsWhileDragging:\t\"triggerEventsDuringLiveResize\"\r\n\t,\tmaskIframesOnResize:\t\t\"maskContents\"\r\n\t//\tSTATE MANAGEMENT\r\n\t,\tuseStateCookie:\t\t\t\t\"stateManagement.enabled\"\r\n\t,\t\"cookie.autoLoad\":\t\t\t\"stateManagement.autoLoad\"\r\n\t,\t\"cookie.autoSave\":\t\t\t\"stateManagement.autoSave\"\r\n\t,\t\"cookie.keys\":\t\t\t\t\"stateManagement.stateKeys\"\r\n\t,\t\"cookie.name\":\t\t\t\t\"stateManagement.cookie.name\"\r\n\t,\t\"cookie.domain\":\t\t\t\"stateManagement.cookie.domain\"\r\n\t,\t\"cookie.path\":\t\t\t\t\"stateManagement.cookie.path\"\r\n\t,\t\"cookie.expires\":\t\t\t\"stateManagement.cookie.expires\"\r\n\t,\t\"cookie.secure\":\t\t\t\"stateManagement.cookie.secure\"\r\n\t//\tOLD Language options\r\n\t,\tnoRoomToOpenTip:\t\t\t\"tips.noRoomToOpen\"\r\n\t,\ttogglerTip_open:\t\t\t\"tips.Close\"\t// open   = Close\r\n\t,\ttogglerTip_closed:\t\t\t\"tips.Open\"\t\t// closed = Open\r\n\t,\tresizerTip:\t\t\t\t\t\"tips.Resize\"\r\n\t,\tsliderTip:\t\t\t\t\t\"tips.Slide\"\r\n\t}\r\n\r\n/**\r\n* @param {Object}\topts\r\n*/\r\n,\trenameOptions: function (opts) {\r\n\t\tvar map = $.layout.backwardCompatibility.map\r\n\t\t,\toldData, newData, value\r\n\t\t;\r\n\t\tfor (var itemPath in map) {\r\n\t\t\toldData\t= getBranch( itemPath );\r\n\t\t\tvalue\t= oldData.branch[ oldData.key ];\r\n\t\t\tif (value !== undefined) {\r\n\t\t\t\tnewData = getBranch( map[itemPath], true );\r\n\t\t\t\tnewData.branch[ newData.key ] = value;\r\n\t\t\t\tdelete oldData.branch[ oldData.key ];\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t* @param {string}\tpath\r\n\t\t* @param {boolean=}\t[create=false]\tCreate path if does not exist\r\n\t\t*/\r\n\t\tfunction getBranch (path, create) {\r\n\t\t\tvar a = path.split(\".\") // split keys into array\r\n\t\t\t,\tc = a.length - 1\r\n\t\t\t,\tD = { branch: opts, key: a[c] } // init branch at top & set key (last item)\r\n\t\t\t,\ti = 0, k, undef;\r\n\t\t\tfor (; i<c; i++) { // skip the last key (data)\r\n\t\t\t\tk = a[i];\r\n\t\t\t\tif (D.branch[ k ] == undefined) { // child-key does not exist\r\n\t\t\t\t\tif (create) {\r\n\t\t\t\t\t\tD.branch = D.branch[ k ] = {}; // create child-branch\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse // can't go any farther\r\n\t\t\t\t\t\tD.branch = {}; // branch is undefined\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t\tD.branch = D.branch[ k ]; // get child-branch\r\n\t\t\t}\r\n\t\t\treturn D;\r\n\t\t};\r\n\t}\r\n\r\n/**\r\n* @param {Object}\topts\r\n*/\r\n,\trenameAllOptions: function (opts) {\r\n\t\tvar ren = $.layout.backwardCompatibility.renameOptions;\r\n\t\t// rename root (layout) options\r\n\t\tren( opts );\r\n\t\t// rename 'defaults' to 'panes'\r\n\t\tif (opts.defaults) {\r\n\t\t\tif (typeof opts.panes !== \"object\")\r\n\t\t\t\topts.panes = {};\r\n\t\t\t$.extend(true, opts.panes, opts.defaults);\r\n\t\t\tdelete opts.defaults;\r\n\t\t}\r\n\t\t// rename options in the the options.panes key\r\n\t\tif (opts.panes) ren( opts.panes );\r\n\t\t// rename options inside *each pane key*, eg: options.west\r\n\t\t$.each($.layout.config.allPanes, function (i, pane) {\r\n\t\t\tif (opts[pane]) ren( opts[pane] );\r\n\t\t});\t\r\n\t\treturn opts;\r\n\t}\r\n};\r\n\r\n\r\n\r\n\r\n/*\t============================================================\r\n *\tBEGIN WIDGET: $( selector ).layout( {options} );\r\n *\t============================================================\r\n */\r\n$.fn.layout = function (opts) {\r\n\tvar\r\n\r\n\t// local aliases to global data\r\n\tbrowser\t= $.layout.browser\r\n,\t_c\t\t= $.layout.config\r\n\r\n\t// local aliases to utlity methods\r\n,\tcssW\t= $.layout.cssWidth\r\n,\tcssH\t= $.layout.cssHeight\r\n,\telDims\t= $.layout.getElementDimensions\r\n,\tstyles\t= $.layout.getElementStyles\r\n,\tevtObj\t= $.layout.getEventObject\r\n,\tevtPane\t= $.layout.parsePaneName\r\n\r\n/**\r\n * options - populated by initOptions()\r\n */\r\n,\toptions = $.extend(true, {}, $.layout.defaults)\r\n,\teffects\t= options.effects = $.extend(true, {}, $.layout.effects)\r\n\r\n/**\r\n * layout-state object\r\n */\r\n,\tstate = {\r\n\t\t// generate unique ID to use for event.namespace so can unbind only events added by 'this layout'\r\n\t\tid:\t\t\t\t\"layout\"+ $.now()\t// code uses alias: sID\r\n\t,\tinitialized:\tfalse\r\n\t,\tpaneResizing:\tfalse\r\n\t,\tpanesSliding:\t{}\r\n\t,\tcontainer:\t{ \t// list all keys referenced in code to avoid compiler error msgs\r\n\t\t\tinnerWidth:\t\t0\r\n\t\t,\tinnerHeight:\t0\r\n\t\t,\touterWidth:\t\t0\r\n\t\t,\touterHeight:\t0\r\n\t\t,\tlayoutWidth:\t0\r\n\t\t,\tlayoutHeight:\t0\r\n\t\t}\r\n\t,\tnorth:\t\t{ childIdx: 0 }\r\n\t,\tsouth:\t\t{ childIdx: 0 }\r\n\t,\teast:\t\t{ childIdx: 0 }\r\n\t,\twest:\t\t{ childIdx: 0 }\r\n\t,\tcenter:\t\t{ childIdx: 0 }\r\n\t}\r\n\r\n/**\r\n * parent/child-layout pointers\r\n */\r\n//,\thasParentLayout\t= false\t- exists ONLY inside Instance so can be set externally\r\n,\tchildren = {\r\n\t\tnorth:\t\tnull\r\n\t,\tsouth:\t\tnull\r\n\t,\teast:\t\tnull\r\n\t,\twest:\t\tnull\r\n\t,\tcenter:\t\tnull\r\n\t}\r\n\r\n/*\r\n * ###########################\r\n *  INTERNAL HELPER FUNCTIONS\r\n * ###########################\r\n */\r\n\r\n\t/**\r\n\t* Manages all internal timers\r\n\t*/\r\n,\ttimer = {\r\n\t\tdata:\t{}\r\n\t,\tset:\tfunction (s, fn, ms) { timer.clear(s); timer.data[s] = setTimeout(fn, ms); }\r\n\t,\tclear:\tfunction (s) { var t=timer.data; if (t[s]) {clearTimeout(t[s]); delete t[s];} }\r\n\t}\r\n\r\n\t/**\r\n\t* Alert or console.log a message - IF option is enabled.\r\n\t*\r\n\t* @param {(string|!Object)}\tmsg\t\t\t\tMessage (or debug-data) to display\r\n\t* @param {boolean=}\t\t\t[popup=false]\tTrue by default, means 'alert', false means use console.log\r\n\t* @param {boolean=}\t\t\t[debug=false]\tTrue means is a widget debugging message\r\n\t*/\r\n,\t_log = function (msg, popup, debug) {\r\n\t\tvar o = options;\r\n\t\tif ((o.showErrorMessages && !debug) || (debug && o.showDebugMessages))\r\n\t\t\t$.layout.msg( o.name +' / '+ msg, (popup !== false) );\r\n\t\treturn false;\r\n\t}\r\n\r\n\t/**\r\n\t* Executes a Callback function after a trigger event, like resize, open or close\r\n\t*\r\n\t* @param {string}\t\t\t\tevtName\t\t\t\t\tName of the layout callback, eg \"onresize_start\"\r\n\t* @param {(string|boolean)=}\t[pane=\"\"]\t\t\t\tThis is passed only so we can pass the 'pane object' to the callback\r\n\t* @param {(string|boolean)=}\t[skipBoundEvents=false]\tTrue = do not run events bound to the elements - only the callbacks set in options\r\n\t*/\r\n,\t_runCallbacks = function (evtName, pane, skipBoundEvents) {\r\n\t\tvar\thasPane\t= pane && isStr(pane)\r\n\t\t,\ts\t\t= hasPane ? state[pane] : state\r\n\t\t,\to\t\t= hasPane ? options[pane] : options\r\n\t\t,\tlName\t= options.name\r\n\t\t\t// names like onopen and onopen_end separate are interchangeable in options...\r\n\t\t,\tlng\t\t= evtName + (evtName.match(/_/) ? \"\" : \"_end\")\r\n\t\t,\tshrt\t= lng.match(/_end$/) ? lng.substr(0, lng.length - 4) : \"\"\r\n\t\t,\tfn\t\t= o[lng] || o[shrt]\r\n\t\t,\tretVal\t= \"NC\" // NC = No Callback\r\n\t\t,\targs\t= []\r\n\t\t,\t$P\r\n\t\t;\r\n\t\tif ( !hasPane && $.type(pane) === 'boolean' ) {\r\n\t\t\tskipBoundEvents = pane; // allow pane param to be skipped for Layout callback\r\n\t\t\tpane = \"\";\r\n\t\t}\r\n\r\n\t\t// first trigger the callback set in the options\r\n\t\tif (fn) {\r\n\t\t\ttry {\r\n\t\t\t\t// convert function name (string) to function object\r\n\t\t\t\tif (isStr( fn )) {\r\n\t\t\t\t\tif (fn.match(/,/)) {\r\n\t\t\t\t\t\t// function name cannot contain a comma, \r\n\t\t\t\t\t\t// so must be a function name AND a parameter to pass\r\n\t\t\t\t\t\targs = fn.split(\",\")\r\n\t\t\t\t\t\t,\tfn = eval(args[0]);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse // just the name of an external function?\r\n\t\t\t\t\t\tfn = eval(fn);\r\n\t\t\t\t}\r\n\t\t\t\t// execute the callback, if exists\r\n\t\t\t\tif ($.isFunction( fn )) {\r\n\t\t\t\t\tif (args.length)\r\n\t\t\t\t\t\tretVal = g(fn)(args[1]); // pass the argument parsed from 'list'\r\n\t\t\t\t\telse if ( hasPane )\r\n\t\t\t\t\t\t// pass data: pane-name, pane-element, pane-state, pane-options, and layout-name\r\n\t\t\t\t\t\tretVal = g(fn)( pane, $Ps[pane], s, o, lName );\r\n\t\t\t\t\telse // must be a layout/container callback - pass suitable info\r\n\t\t\t\t\t\tretVal = g(fn)( Instance, s, o, lName );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tcatch (ex) {\r\n\t\t\t\t_log( options.errors.callbackError.replace(/EVENT/, $.trim((pane || \"\") +\" \"+ lng)), false );\r\n\t\t\t\tif ($.type(ex) === 'string' && string.length)\r\n\t\t\t\t\t_log('Exception:  '+ ex, false );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// trigger additional events bound directly to the pane\r\n\t\tif (!skipBoundEvents && retVal !== false) {\r\n\t\t\tif ( hasPane ) { // PANE events can be bound to each pane-elements\r\n\t\t\t\t$P\t= $Ps[pane];\r\n\t\t\t\to\t= options[pane];\r\n\t\t\t\ts\t= state[pane];\r\n\t\t\t\t$P.triggerHandler('layoutpane'+ lng, [ pane, $P, s, o, lName ]);\r\n\t\t\t\tif (shrt)\r\n\t\t\t\t\t$P.triggerHandler('layoutpane'+ shrt, [ pane, $P, s, o, lName ]);\r\n\t\t\t}\r\n\t\t\telse { // LAYOUT events can be bound to the container-element\r\n\t\t\t\t$N.triggerHandler('layout'+ lng, [ Instance, s, o, lName ]);\r\n\t\t\t\tif (shrt)\r\n\t\t\t\t\t$N.triggerHandler('layout'+ shrt, [ Instance, s, o, lName ]);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// ALWAYS resizeChildren after an onresize_end event - even during initialization\r\n\t\t// IGNORE onsizecontent_end event because causes child-layouts to resize TWICE\r\n\t\tif (hasPane && evtName === \"onresize_end\") // BAD: || evtName === \"onsizecontent_end\"\r\n\t\t\tresizeChildren(pane+\"\", true); // compiler hack -force string\r\n\r\n\t\treturn retVal;\r\n\r\n\t\tfunction g (f) { return f; }; // compiler hack\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* cure iframe display issues in IE & other browsers\r\n\t*/\r\n,\t_fixIframe = function (pane) {\r\n\t\tif (browser.mozilla) return; // skip FireFox - it auto-refreshes iframes onShow\r\n\t\tvar $P = $Ps[pane];\r\n\t\t// if the 'pane' is an iframe, do it\r\n\t\tif (state[pane].tagName === \"IFRAME\")\r\n\t\t\t$P.css(_c.hidden).css(_c.visible); \r\n\t\telse // ditto for any iframes INSIDE the pane\r\n\t\t\t$P.find('IFRAME').css(_c.hidden).css(_c.visible);\r\n\t}\r\n\r\n\t/**\r\n\t* @param  {string}\t\tpane\t\tCan accept ONLY a 'pane' (east, west, etc)\r\n\t* @param  {number=}\t\touterSize\t(optional) Can pass a width, allowing calculations BEFORE element is resized\r\n\t* @return {number}\t\tReturns the innerHeight/Width of el by subtracting padding and borders\r\n\t*/\r\n,\tcssSize = function (pane, outerSize) {\r\n\t\tvar fn = _c[pane].dir==\"horz\" ? cssH : cssW;\r\n\t\treturn fn($Ps[pane], outerSize);\r\n\t}\r\n\r\n\t/**\r\n\t* @param  {string}\t\tpane\t\tCan accept ONLY a 'pane' (east, west, etc)\r\n\t* @return {Object}\t\tReturns hash of minWidth & minHeight\r\n\t*/\r\n,\tcssMinDims = function (pane) {\r\n\t\t// minWidth/Height means CSS width/height = 1px\r\n\t\tvar\t$P\t= $Ps[pane]\r\n\t\t,\tdir\t= _c[pane].dir\r\n\t\t,\td\t= {\r\n\t\t\t\tminWidth:\t1001 - cssW($P, 1000)\r\n\t\t\t,\tminHeight:\t1001 - cssH($P, 1000)\r\n\t\t\t}\r\n\t\t;\r\n\t\tif (dir === \"horz\") d.minSize = d.minHeight;\r\n\t\tif (dir === \"vert\") d.minSize = d.minWidth;\r\n\t\treturn d;\r\n\t}\r\n\r\n\t// TODO: see if these methods can be made more useful...\r\n\t// TODO: *maybe* return cssW/H from these so caller can use this info\r\n\r\n\t/**\r\n\t* @param {(string|!Object)}\t\tel\r\n\t* @param {number=}\t\t\t\touterWidth\r\n\t* @param {boolean=}\t\t\t\t[autoHide=false]\r\n\t*/\r\n,\tsetOuterWidth = function (el, outerWidth, autoHide) {\r\n\t\tvar $E = el, w;\r\n\t\tif (isStr(el)) $E = $Ps[el]; // west\r\n\t\telse if (!el.jquery) $E = $(el);\r\n\t\tw = cssW($E, outerWidth);\r\n\t\t$E.css({ width: w });\r\n\t\tif (w > 0) {\r\n\t\t\tif (autoHide && $E.data('autoHidden') && $E.innerHeight() > 0) {\r\n\t\t\t\t$E.show().data('autoHidden', false);\r\n\t\t\t\tif (!browser.mozilla) // FireFox refreshes iframes - IE does not\r\n\t\t\t\t\t// make hidden, then visible to 'refresh' display after animation\r\n\t\t\t\t\t$E.css(_c.hidden).css(_c.visible);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if (autoHide && !$E.data('autoHidden'))\r\n\t\t\t$E.hide().data('autoHidden', true);\r\n\t}\r\n\r\n\t/**\r\n\t* @param {(string|!Object)}\t\tel\r\n\t* @param {number=}\t\t\t\touterHeight\r\n\t* @param {boolean=}\t\t\t\t[autoHide=false]\r\n\t*/\r\n,\tsetOuterHeight = function (el, outerHeight, autoHide) {\r\n\t\tvar $E = el, h;\r\n\t\tif (isStr(el)) $E = $Ps[el]; // west\r\n\t\telse if (!el.jquery) $E = $(el);\r\n\t\th = cssH($E, outerHeight);\r\n\t\t$E.css({ height: h, visibility: \"visible\" }); // may have been 'hidden' by sizeContent\r\n\t\tif (h > 0 && $E.innerWidth() > 0) {\r\n\t\t\tif (autoHide && $E.data('autoHidden')) {\r\n\t\t\t\t$E.show().data('autoHidden', false);\r\n\t\t\t\tif (!browser.mozilla) // FireFox refreshes iframes - IE does not\r\n\t\t\t\t\t$E.css(_c.hidden).css(_c.visible);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if (autoHide && !$E.data('autoHidden'))\r\n\t\t\t$E.hide().data('autoHidden', true);\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* Converts any 'size' params to a pixel/integer size, if not already\r\n\t* If 'auto' or a decimal/percentage is passed as 'size', a pixel-size is calculated\r\n\t*\r\n\t/**\r\n\t* @param  {string}\t\t\t\tpane\r\n\t* @param  {(string|number)=}\tsize\r\n\t* @param  {string=}\t\t\t\t[dir]\r\n\t* @return {number}\r\n\t*/\r\n,\t_parseSize = function (pane, size, dir) {\r\n\t\tif (!dir) dir = _c[pane].dir;\r\n\r\n\t\tif (isStr(size) && size.match(/%/))\r\n\t\t\tsize = (size === '100%') ? -1 : parseInt(size, 10) / 100; // convert % to decimal\r\n\r\n\t\tif (size === 0)\r\n\t\t\treturn 0;\r\n\t\telse if (size >= 1)\r\n\t\t\treturn parseInt(size, 10);\r\n\r\n\t\tvar o = options, avail = 0;\r\n\t\tif (dir==\"horz\") // north or south or center.minHeight\r\n\t\t\tavail = sC.innerHeight - ($Ps.north ? o.north.spacing_open : 0) - ($Ps.south ? o.south.spacing_open : 0);\r\n\t\telse if (dir==\"vert\") // east or west or center.minWidth\r\n\t\t\tavail = sC.innerWidth - ($Ps.west ? o.west.spacing_open : 0) - ($Ps.east ? o.east.spacing_open : 0);\r\n\r\n\t\tif (size === -1) // -1 == 100%\r\n\t\t\treturn avail;\r\n\t\telse if (size > 0) // percentage, eg: .25\r\n\t\t\treturn round(avail * size);\r\n\t\telse if (pane==\"center\")\r\n\t\t\treturn 0;\r\n\t\telse { // size < 0 || size=='auto' || size==Missing || size==Invalid\r\n\t\t\t// auto-size the pane\r\n\t\t\tvar\tdim\t= (dir === \"horz\" ? \"height\" : \"width\")\r\n\t\t\t,\t$P\t= $Ps[pane]\r\n\t\t\t,\t$C\t= dim === 'height' ? $Cs[pane] : false\r\n\t\t\t,\tvis\t= $.layout.showInvisibly($P) // show pane invisibly if hidden\r\n\t\t\t,\tszP\t= $P.css(dim) // SAVE current pane size\r\n\t\t\t,\tszC\t= $C ? $C.css(dim) : 0 // SAVE current content size\r\n\t\t\t;\r\n\t\t\t$P.css(dim, \"auto\");\r\n\t\t\tif ($C) $C.css(dim, \"auto\");\r\n\t\t\tsize = (dim === \"height\") ? $P.outerHeight() : $P.outerWidth(); // MEASURE\r\n\t\t\t$P.css(dim, szP).css(vis); // RESET size & visibility\r\n\t\t\tif ($C) $C.css(dim, szC);\r\n\t\t\treturn size;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t* Calculates current 'size' (outer-width or outer-height) of a border-pane - optionally with 'pane-spacing' added\r\n\t*\r\n\t* @param  {(string|!Object)}\tpane\r\n\t* @param  {boolean=}\t\t\t[inclSpace=false]\r\n\t* @return {number}\t\t\t\tReturns EITHER Width for east/west panes OR Height for north/south panes\r\n\t*/\r\n,\tgetPaneSize = function (pane, inclSpace) {\r\n\t\tvar \r\n\t\t\t$P\t= $Ps[pane]\r\n\t\t,\to\t= options[pane]\r\n\t\t,\ts\t= state[pane]\r\n\t\t,\toSp\t= (inclSpace ? o.spacing_open : 0)\r\n\t\t,\tcSp\t= (inclSpace ? o.spacing_closed : 0)\r\n\t\t;\r\n\t\tif (!$P || s.isHidden)\r\n\t\t\treturn 0;\r\n\t\telse if (s.isClosed || (s.isSliding && inclSpace))\r\n\t\t\treturn cSp;\r\n\t\telse if (_c[pane].dir === \"horz\")\r\n\t\t\treturn $P.outerHeight() + oSp;\r\n\t\telse // dir === \"vert\"\r\n\t\t\treturn $P.outerWidth() + oSp;\r\n\t}\r\n\r\n\t/**\r\n\t* Calculate min/max pane dimensions and limits for resizing\r\n\t*\r\n\t* @param  {string}\t\tpane\r\n\t* @param  {boolean=}\t[slide=false]\r\n\t*/\r\n,\tsetSizeLimits = function (pane, slide) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar \r\n\t\t\to\t\t\t\t= options[pane]\r\n\t\t,\ts\t\t\t\t= state[pane]\r\n\t\t,\tc\t\t\t\t= _c[pane]\r\n\t\t,\tdir\t\t\t\t= c.dir\r\n\t\t,\ttype\t\t\t= c.sizeType.toLowerCase()\r\n\t\t,\tisSliding\t\t= (slide != undefined ? slide : s.isSliding) // only open() passes 'slide' param\r\n\t\t,\t$P\t\t\t\t= $Ps[pane]\r\n\t\t,\tpaneSpacing\t\t= o.spacing_open\r\n\t\t//\tmeasure the pane on the *opposite side* from this pane\r\n\t\t,\taltPane\t\t\t= _c.oppositeEdge[pane]\r\n\t\t,\taltS\t\t\t= state[altPane]\r\n\t\t,\t$altP\t\t\t= $Ps[altPane]\r\n\t\t,\taltPaneSize\t\t= (!$altP || altS.isVisible===false || altS.isSliding ? 0 : (dir==\"horz\" ? $altP.outerHeight() : $altP.outerWidth()))\r\n\t\t,\taltPaneSpacing\t= ((!$altP || altS.isHidden ? 0 : options[altPane][ altS.isClosed !== false ? \"spacing_closed\" : \"spacing_open\" ]) || 0)\r\n\t\t//\tlimitSize prevents this pane from 'overlapping' opposite pane\r\n\t\t,\tcontainerSize\t= (dir==\"horz\" ? sC.innerHeight : sC.innerWidth)\r\n\t\t,\tminCenterDims\t= cssMinDims(\"center\")\r\n\t\t,\tminCenterSize\t= dir==\"horz\" ? max(options.center.minHeight, minCenterDims.minHeight) : max(options.center.minWidth, minCenterDims.minWidth)\r\n\t\t//\tif pane is 'sliding', then ignore center and alt-pane sizes - because 'overlays' them\r\n\t\t,\tlimitSize\t\t= (containerSize - paneSpacing - (isSliding ? 0 : (_parseSize(\"center\", minCenterSize, dir) + altPaneSize + altPaneSpacing)))\r\n\t\t,\tminSize\t\t\t= s.minSize = max( _parseSize(pane, o.minSize), cssMinDims(pane).minSize )\r\n\t\t,\tmaxSize\t\t\t= s.maxSize = min( (o.maxSize ? _parseSize(pane, o.maxSize) : 100000), limitSize )\r\n\t\t,\tr\t\t\t\t= s.resizerPosition = {} // used to set resizing limits\r\n\t\t,\ttop\t\t\t\t= sC.inset.top\r\n\t\t,\tleft\t\t\t= sC.inset.left\r\n\t\t,\tW\t\t\t\t= sC.innerWidth\r\n\t\t,\tH\t\t\t\t= sC.innerHeight\r\n\t\t,\trW\t\t\t\t= o.spacing_open // subtract resizer-width to get top/left position for south/east\r\n\t\t;\r\n\t\tswitch (pane) {\r\n\t\t\tcase \"north\":\tr.min = top + minSize;\r\n\t\t\t\t\t\t\tr.max = top + maxSize;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\tcase \"west\":\tr.min = left + minSize;\r\n\t\t\t\t\t\t\tr.max = left + maxSize;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\tcase \"south\":\tr.min = top + H - maxSize - rW;\r\n\t\t\t\t\t\t\tr.max = top + H - minSize - rW;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\tcase \"east\":\tr.min = left + W - maxSize - rW;\r\n\t\t\t\t\t\t\tr.max = left + W - minSize - rW;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t};\r\n\t}\r\n\r\n\t/**\r\n\t* Returns data for setting the size/position of center pane. Also used to set Height for east/west panes\r\n\t*\r\n\t* @return JSON  Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height\r\n\t*/\r\n,\tcalcNewCenterPaneDims = function () {\r\n\t\tvar d = {\r\n\t\t\ttop:\tgetPaneSize(\"north\", true) // true = include 'spacing' value for pane\r\n\t\t,\tbottom:\tgetPaneSize(\"south\", true)\r\n\t\t,\tleft:\tgetPaneSize(\"west\", true)\r\n\t\t,\tright:\tgetPaneSize(\"east\", true)\r\n\t\t,\twidth:\t0\r\n\t\t,\theight:\t0\r\n\t\t};\r\n\r\n\t\t// NOTE: sC = state.container\r\n\t\t// calc center-pane outer dimensions\r\n\t\td.width\t\t= sC.innerWidth - d.left - d.right;  // outerWidth\r\n\t\td.height\t= sC.innerHeight - d.bottom - d.top; // outerHeight\r\n\t\t// add the 'container border/padding' to get final positions relative to the container\r\n\t\td.top\t\t+= sC.inset.top;\r\n\t\td.bottom\t+= sC.inset.bottom;\r\n\t\td.left\t\t+= sC.inset.left;\r\n\t\td.right\t\t+= sC.inset.right;\r\n\r\n\t\treturn d;\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* @param {!Object}\t\tel\r\n\t* @param {boolean=}\t\t[allStates=false]\r\n\t*/\r\n,\tgetHoverClasses = function (el, allStates) {\r\n\t\tvar\r\n\t\t\t$El\t\t= $(el)\r\n\t\t,\ttype\t= $El.data(\"layoutRole\")\r\n\t\t,\tpane\t= $El.data(\"layoutEdge\")\r\n\t\t,\to\t\t= options[pane]\r\n\t\t,\troot\t= o[type +\"Class\"]\r\n\t\t,\t_pane\t= \"-\"+ pane // eg: \"-west\"\r\n\t\t,\t_open\t= \"-open\"\r\n\t\t,\t_closed\t= \"-closed\"\r\n\t\t,\t_slide\t= \"-sliding\"\r\n\t\t,\t_hover\t= \"-hover \" // NOTE the trailing space\r\n\t\t,\t_state\t= $El.hasClass(root+_closed) ? _closed : _open\r\n\t\t,\t_alt\t= _state === _closed ? _open : _closed\r\n\t\t,\tclasses = (root+_hover) + (root+_pane+_hover) + (root+_state+_hover) + (root+_pane+_state+_hover)\r\n\t\t;\r\n\t\tif (allStates) // when 'removing' classes, also remove alternate-state classes\r\n\t\t\tclasses += (root+_alt+_hover) + (root+_pane+_alt+_hover);\r\n\r\n\t\tif (type==\"resizer\" && $El.hasClass(root+_slide))\r\n\t\t\tclasses += (root+_slide+_hover) + (root+_pane+_slide+_hover);\r\n\r\n\t\treturn $.trim(classes);\r\n\t}\r\n,\taddHover\t= function (evt, el) {\r\n\t\tvar $E = $(el || this);\r\n\t\tif (evt && $E.data(\"layoutRole\") === \"toggler\")\r\n\t\t\tevt.stopPropagation(); // prevent triggering 'slide' on Resizer-bar\r\n\t\t$E.addClass( getHoverClasses($E) );\r\n\t}\r\n,\tremoveHover\t= function (evt, el) {\r\n\t\tvar $E = $(el || this);\r\n\t\t$E.removeClass( getHoverClasses($E, true) );\r\n\t}\r\n\r\n,\tonResizerEnter\t= function (evt) { // ALSO called by toggler.mouseenter\r\n\t\tvar pane\t= $(this).data(\"layoutEdge\")\r\n\t\t,\ts\t\t= state[pane]\r\n\t\t;\r\n\t\t// ignore closed-panes and mouse moving back & forth over resizer!\r\n\t\t// also ignore if ANY pane is currently resizing\r\n\t\tif ( s.isClosed || s.isResizing || state.paneResizing ) return;\r\n\r\n\t\tif ($.fn.disableSelection)\r\n\t\t\t$(\"body\").disableSelection();\r\n\t\tif (options.maskPanesEarly)\r\n\t\t\tshowMasks( pane, { resizing: true });\r\n\t}\r\n,\tonResizerLeave\t= function (evt, el) {\r\n\t\tvar\te\t\t= el || this // el is only passed when called by the timer\r\n\t\t,\tpane\t= $(e).data(\"layoutEdge\")\r\n\t\t,\tname\t= pane +\"ResizerLeave\"\r\n\t\t;\r\n\t\ttimer.clear(pane+\"_openSlider\"); // cancel slideOpen timer, if set\r\n\t\ttimer.clear(name); // cancel enableSelection timer - may re/set below\r\n\t\t// this method calls itself on a timer because it needs to allow\r\n\t\t// enough time for dragging to kick-in and set the isResizing flag\r\n\t\t// dragging has a 100ms delay set, so this delay must be >100\r\n\t\tif (!el) // 1st call - mouseleave event\r\n\t\t\ttimer.set(name, function(){ onResizerLeave(evt, e); }, 200);\r\n\t\t// if user is resizing, then dragStop will enableSelection(), so can skip it here\r\n\t\telse if ( !state.paneResizing ) { // 2nd call - by timer\r\n\t\t\tif ($.fn.enableSelection)\r\n\t\t\t\t$(\"body\").enableSelection();\r\n\t\t\tif (options.maskPanesEarly)\r\n\t\t\t\thideMasks();\r\n\t\t}\r\n\t}\r\n\r\n/*\r\n * ###########################\r\n *   INITIALIZATION METHODS\r\n * ###########################\r\n */\r\n\r\n\t/**\r\n\t* Initialize the layout - called automatically whenever an instance of layout is created\r\n\t*\r\n\t* @see  none - triggered onInit\r\n\t* @return  mixed\ttrue = fully initialized | false = panes not initialized (yet) | 'cancel' = abort\r\n\t*/\r\n,\t_create = function () {\r\n\t\t// initialize config/options\r\n\t\tinitOptions();\r\n\t\tvar o = options\r\n\t\t,\ts = state;\r\n\r\n\t\t// TEMP state so isInitialized returns true during init process\r\n\t\ts.creatingLayout = true;\r\n\r\n\t\t// init plugins for this layout, if there are any (eg: stateManagement)\r\n\t\trunPluginCallbacks( Instance, $.layout.onCreate );\r\n\r\n\t\t// options & state have been initialized, so now run beforeLoad callback\r\n\t\t// onload will CANCEL layout creation if it returns false\r\n\t\tif (false === _runCallbacks(\"onload_start\"))\r\n\t\t\treturn 'cancel';\r\n\r\n\t\t// initialize the container element\r\n\t\t_initContainer();\r\n\r\n\t\t// bind hotkey function - keyDown - if required\r\n\t\tinitHotkeys();\r\n\r\n\t\t// bind window.onunload\r\n\t\t$(window).bind(\"unload.\"+ sID, unload);\r\n\r\n\t\t// init plugins for this layout, if there are any (eg: customButtons)\r\n\t\trunPluginCallbacks( Instance, $.layout.onLoad );\r\n\r\n\t\t// if layout elements are hidden, then layout WILL NOT complete initialization!\r\n\t\t// initLayoutElements will set initialized=true and run the onload callback IF successful\r\n\t\tif (o.initPanes) _initLayoutElements();\r\n\r\n\t\tdelete s.creatingLayout;\r\n\r\n\t\treturn state.initialized;\r\n\t}\r\n\r\n\t/**\r\n\t* Initialize the layout IF not already\r\n\t*\r\n\t* @see  All methods in Instance run this test\r\n\t* @return  boolean\ttrue = layoutElements have been initialized | false = panes are not initialized (yet)\r\n\t*/\r\n,\tisInitialized = function () {\r\n\t\tif (state.initialized || state.creatingLayout) return true;\t// already initialized\r\n\t\telse return _initLayoutElements();\t// try to init panes NOW\r\n\t}\r\n\r\n\t/**\r\n\t* Initialize the layout - called automatically whenever an instance of layout is created\r\n\t*\r\n\t* @see  _create() & isInitialized\r\n\t* @param {boolean=}\t\t[retry=false]\t// indicates this is a 2nd try\r\n\t* @return  An object pointer to the instance created\r\n\t*/\r\n,\t_initLayoutElements = function (retry) {\r\n\t\t// initialize config/options\r\n\t\tvar o = options;\r\n\t\t// CANNOT init panes inside a hidden container!\r\n\t\tif (!$N.is(\":visible\")) {\r\n\t\t\t// handle Chrome bug where popup window 'has no height'\r\n\t\t\t// if layout is BODY element, try again in 50ms\r\n\t\t\t// SEE: http://layout.jquery-dev.net/samples/test_popup_window.html\r\n\t\t\tif ( !retry && browser.webkit && $N[0].tagName === \"BODY\" )\r\n\t\t\t\tsetTimeout(function(){ _initLayoutElements(true); }, 50);\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// a center pane is required, so make sure it exists\r\n\t\tif (!getPane(\"center\").length) {\r\n\t\t\treturn _log( o.errors.centerPaneMissing );\r\n\t\t}\r\n\r\n\t\t// TEMP state so isInitialized returns true during init process\r\n\t\tstate.creatingLayout = true;\r\n\r\n\t\t// update Container dims\r\n\t\t$.extend(sC, elDims( $N, o.inset )); // passing inset means DO NOT include insetX values\r\n\r\n\t\t// initialize all layout elements\r\n\t\tinitPanes();\t// size & position panes - calls initHandles() - which calls initResizable()\r\n\r\n\t\tif (o.scrollToBookmarkOnLoad) {\r\n\t\t\tvar l = self.location;\r\n\t\t\tif (l.hash) l.replace( l.hash ); // scrollTo Bookmark\r\n\t\t}\r\n\r\n\t\t// check to see if this layout 'nested' inside a pane\r\n\t\tif (Instance.hasParentLayout)\r\n\t\t\to.resizeWithWindow = false;\r\n\t\t// bind resizeAll() for 'this layout instance' to window.resize event\r\n\t\telse if (o.resizeWithWindow)\r\n\t\t\t$(window).bind(\"resize.\"+ sID, windowResize);\r\n\r\n\t\tdelete state.creatingLayout;\r\n\t\tstate.initialized = true;\r\n\r\n\t\t// init plugins for this layout, if there are any\r\n\t\trunPluginCallbacks( Instance, $.layout.onReady );\r\n\r\n\t\t// now run the onload callback, if exists\r\n\t\t_runCallbacks(\"onload_end\");\r\n\r\n\t\treturn true; // elements initialized successfully\r\n\t}\r\n\r\n\t/**\r\n\t* Initialize nested layouts for a specific pane - can optionally pass layout-options\r\n\t*\r\n\t* @param {(string|Object)}\tevt_or_pane\tThe pane being opened, ie: north, south, east, or west\r\n\t* @param {Object=}\t\t\t[opts]\t\tLayout-options - if passed, will OVERRRIDE options[pane].children\r\n\t* @return  An object pointer to the layout instance created - or null\r\n\t*/\r\n,\tcreateChildren = function (evt_or_pane, opts) {\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane)\r\n\t\t,\t$P\t= $Ps[pane]\r\n\t\t;\r\n\t\tif (!$P) return;\r\n\t\tvar\t$C\t= $Cs[pane]\r\n\t\t,\ts\t= state[pane]\r\n\t\t,\to\t= options[pane]\r\n\t\t,\tsm\t= options.stateManagement || {}\r\n\t\t,\tcos = opts ? (o.children = opts) : o.children\r\n\t\t;\r\n\t\tif ( $.isPlainObject( cos ) )\r\n\t\t\tcos = [ cos ]; // convert a hash to a 1-elem array\r\n\t\telse if (!cos || !$.isArray( cos ))\r\n\t\t\treturn;\r\n\r\n\t\t$.each( cos, function (idx, co) {\r\n\t\t\tif ( !$.isPlainObject( co ) ) return;\r\n\r\n\t\t\t// determine which element is supposed to be the 'child container'\r\n\t\t\t// if pane has a 'containerSelector' OR a 'content-div', use those instead of the pane\r\n\t\t\tvar $containers = co.containerSelector ? $P.find( co.containerSelector ) : ($C || $P);\r\n\r\n\t\t\t$containers.each(function(){\r\n\t\t\t\tvar $cont\t= $(this)\r\n\t\t\t\t,\tchild\t= $cont.data(\"layout\") //\tsee if a child-layout ALREADY exists on this element\r\n\t\t\t\t;\r\n\t\t\t\t// if no layout exists, but children are set, try to create the layout now\r\n\t\t\t\tif (!child) {\r\n\t\t\t\t\t// TODO: see about moving this to the stateManagement plugin, as a method\r\n\t\t\t\t\t// set a unique child-instance key for this layout, if not already set\r\n\t\t\t\t\tsetInstanceKey({ container: $cont, options: co }, s );\r\n\t\t\t\t\t// If THIS layout has a hash in stateManagement.autoLoad,\r\n\t\t\t\t\t// then see if it also contains state-data for this child-layout\r\n\t\t\t\t\t// If so, copy the stateData to child.options.stateManagement.autoLoad\r\n\t\t\t\t\tif ( sm.includeChildren && state.stateData[pane] ) {\r\n\t\t\t\t\t\t//\tTHIS layout's state was cached when its state was loaded\r\n\t\t\t\t\t\tvar\tpaneChildren = state.stateData[pane].children || {}\r\n\t\t\t\t\t\t,\tchildState\t= paneChildren[ co.instanceKey ]\r\n\t\t\t\t\t\t,\tco_sm\t\t= co.stateManagement || (co.stateManagement = { autoLoad: true })\r\n\t\t\t\t\t\t;\r\n\t\t\t\t\t\t// COPY the stateData into the autoLoad key\r\n\t\t\t\t\t\tif ( co_sm.autoLoad === true && childState ) {\r\n\t\t\t\t\t\t\tco_sm.autoSave\t\t\t= false; // disable autoSave because saving handled by parent-layout\r\n\t\t\t\t\t\t\tco_sm.includeChildren\t= true;  // cascade option - FOR NOW\r\n\t\t\t\t\t\t\tco_sm.autoLoad = $.extend(true, {}, childState); // COPY the state-hash\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// create the layout\r\n\t\t\t\t\tchild = $cont.layout( co );\r\n\r\n\t\t\t\t\t// if successful, update data\r\n\t\t\t\t\tif (child) {\r\n\t\t\t\t\t\t// add the child and update all layout-pointers\r\n\t\t\t\t\t\t// MAY have already been done by child-layout calling parent.refreshChildren()\r\n\t\t\t\t\t\trefreshChildren( pane, child );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t});\r\n\t}\r\n\r\n,\tsetInstanceKey = function (child, parentPaneState) {\r\n\t\t// create a named key for use in state and instance branches\r\n\t\tvar\t$c\t= child.container\r\n\t\t,\to\t= child.options\r\n\t\t,\tsm\t= o.stateManagement\r\n\t\t,\tkey\t= o.instanceKey || $c.data(\"layoutInstanceKey\")\r\n\t\t;\r\n\t\tif (!key) key = (sm && sm.cookie ? sm.cookie.name : '') || o.name; // look for a name/key\r\n\t\tif (!key) key = \"layout\"+ (++parentPaneState.childIdx);\t// if no name/key found, generate one\r\n\t\telse key = key.replace(/[^\\w-]/gi, '_').replace(/_{2,}/g, '_');\t // ensure is valid as a hash key\r\n\t\to.instanceKey = key;\r\n\t\t$c.data(\"layoutInstanceKey\", key); // useful if layout is destroyed and then recreated\r\n\t\treturn key;\r\n\t}\r\n\r\n\t/**\r\n\t* @param {string}\t\tpane\t\tThe pane being opened, ie: north, south, east, or west\r\n\t* @param {Object=}\t\tnewChild\tNew child-layout Instance to add to this pane\r\n\t*/\r\n,\trefreshChildren = function (pane, newChild) {\r\n\t\tvar\t$P\t= $Ps[pane]\r\n\t\t,\tpC\t= children[pane]\r\n\t\t,\ts\t= state[pane]\r\n\t\t,\to\r\n\t\t;\r\n\t\t// check for destroy()ed layouts and update the child pointers & arrays\r\n\t\tif ($.isPlainObject( pC )) {\r\n\t\t\t$.each( pC, function (key, child) {\r\n\t\t\t\tif (child.destroyed) delete pC[key]\r\n\t\t\t});\r\n\t\t\t// if no more children, remove the children hash\r\n\t\t\tif ($.isEmptyObject( pC ))\r\n\t\t\t\tpC = children[pane] = null; // clear children hash\r\n\t\t}\r\n\r\n\t\t// see if there is a directly-nested layout inside this pane\r\n\t\t// if there is, then there can be only ONE child-layout, so check that...\r\n\t\tif (!newChild && !pC) {\r\n\t\t\tnewChild = $P.data(\"layout\");\r\n\t\t}\r\n\r\n\t\t// if a newChild instance was passed, add it to children[pane]\r\n\t\tif (newChild) {\r\n\t\t\t// update child.state\r\n\t\t\tnewChild.hasParentLayout = true; // set parent-flag in child\r\n\t\t\t// instanceKey is a key-name used in both state and children\r\n\t\t\to = newChild.options;\r\n\t\t\t// set a unique child-instance key for this layout, if not already set\r\n\t\t\tsetInstanceKey( newChild, s );\r\n\t\t\t// add pointer to pane.children hash\r\n\t\t\tif (!pC) pC = children[pane] = {}; // create an empty children hash\r\n\t\t\tpC[ o.instanceKey ] = newChild.container.data(\"layout\"); // add childLayout instance\r\n\t\t}\r\n\r\n\t\t// ALWAYS refresh the pane.children alias, even if null\r\n\t\tInstance[pane].children = children[pane];\r\n\r\n\t\t// if newChild was NOT passed - see if there is a child layout NOW\r\n\t\tif (!newChild) {\r\n\t\t\tcreateChildren(pane); // MAY create a child and re-call this method\r\n\t\t}\r\n\t}\r\n\r\n,\twindowResize = function () {\r\n\t\tvar\to = options\r\n\t\t,\tdelay = Number(o.resizeWithWindowDelay);\r\n\t\tif (delay < 10) delay = 100; // MUST have a delay!\r\n\t\t// resizing uses a delay-loop because the resize event fires repeatly - except in FF, but delay anyway\r\n\t\ttimer.clear(\"winResize\"); // if already running\r\n\t\ttimer.set(\"winResize\", function(){\r\n\t\t\ttimer.clear(\"winResize\");\r\n\t\t\ttimer.clear(\"winResizeRepeater\");\r\n\t\t\tvar dims = elDims( $N, o.inset );\r\n\t\t\t// only trigger resizeAll() if container has changed size\r\n\t\t\tif (dims.innerWidth !== sC.innerWidth || dims.innerHeight !== sC.innerHeight)\r\n\t\t\t\tresizeAll();\r\n\t\t}, delay);\r\n\t\t// ALSO set fixed-delay timer, if not already running\r\n\t\tif (!timer.data[\"winResizeRepeater\"]) setWindowResizeRepeater();\r\n\t}\r\n\r\n,\tsetWindowResizeRepeater = function () {\r\n\t\tvar delay = Number(options.resizeWithWindowMaxDelay);\r\n\t\tif (delay > 0)\r\n\t\t\ttimer.set(\"winResizeRepeater\", function(){ setWindowResizeRepeater(); resizeAll(); }, delay);\r\n\t}\r\n\r\n,\tunload = function () {\r\n\t\tvar o = options;\r\n\r\n\t\t_runCallbacks(\"onunload_start\");\r\n\r\n\t\t// trigger plugin callabacks for this layout (eg: stateManagement)\r\n\t\trunPluginCallbacks( Instance, $.layout.onUnload );\r\n\r\n\t\t_runCallbacks(\"onunload_end\");\r\n\t}\r\n\r\n\t/**\r\n\t* Validate and initialize container CSS and events\r\n\t*\r\n\t* @see  _create()\r\n\t*/\r\n,\t_initContainer = function () {\r\n\t\tvar\r\n\t\t\tN\t\t= $N[0]\t\r\n\t\t,\t$H\t\t= $(\"html\")\r\n\t\t,\ttag\t\t= sC.tagName = N.tagName\r\n\t\t,\tid\t\t= sC.id = N.id\r\n\t\t,\tcls\t\t= sC.className = N.className\r\n\t\t,\to\t\t= options\r\n\t\t,\tname\t= o.name\r\n\t\t,\tprops\t= \"position,margin,padding,border\"\r\n\t\t,\tcss\t\t= \"layoutCSS\"\r\n\t\t,\tCSS\t\t= {}\r\n\t\t,\thid\t\t= \"hidden\" // used A LOT!\r\n\t\t//\tsee if this container is a 'pane' inside an outer-layout\r\n\t\t,\tparent\t= $N.data(\"parentLayout\")\t// parent-layout Instance\r\n\t\t,\tpane\t= $N.data(\"layoutEdge\")\t\t// pane-name in parent-layout\r\n\t\t,\tisChild\t= parent && pane\r\n\t\t,\tnum\t\t= $.layout.cssNum\r\n\t\t,\t$parent, n\r\n\t\t;\r\n\t\t// sC = state.container\r\n\t\tsC.selector = $N.selector.split(\".slice\")[0];\r\n\t\tsC.ref\t\t= (o.name ? o.name +' layout / ' : '') + tag + (id ? \"#\"+id : cls ? '.['+cls+']' : ''); // used in messages\r\n\t\tsC.isBody\t= (tag === \"BODY\");\r\n\r\n\t\t// try to find a parent-layout\r\n\t\tif (!isChild && !sC.isBody) {\r\n\t\t\t$parent = $N.closest(\".\"+ $.layout.defaults.panes.paneClass);\r\n\t\t\tparent\t= $parent.data(\"parentLayout\");\r\n\t\t\tpane\t= $parent.data(\"layoutEdge\");\r\n\t\t\tisChild\t= parent && pane;\r\n\t\t}\r\n\r\n\t\t$N\t.data({\r\n\t\t\t\tlayout: Instance\r\n\t\t\t,\tlayoutContainer: sID // FLAG to indicate this is a layout-container - contains unique internal ID\r\n\t\t\t})\r\n\t\t\t.addClass(o.containerClass)\r\n\t\t;\r\n\t\tvar layoutMethods = {\r\n\t\t\tdestroy:\t''\r\n\t\t,\tinitPanes:\t''\r\n\t\t,\tresizeAll:\t'resizeAll'\r\n\t\t,\tresize:\t\t'resizeAll'\r\n\t\t};\r\n\t\t// loop hash and bind all methods - include layoutID namespacing\r\n\t\tfor (name in layoutMethods) {\r\n\t\t\t$N.bind(\"layout\"+ name.toLowerCase() +\".\"+ sID, Instance[ layoutMethods[name] || name ]);\r\n\t\t}\r\n\r\n\t\t// if this container is another layout's 'pane', then set child/parent pointers\r\n\t\tif (isChild) {\r\n\t\t\t// update parent flag\r\n\t\t\tInstance.hasParentLayout = true;\r\n\t\t\t// set pointers to THIS child-layout (Instance) in parent-layout\r\n\t\t\tparent.refreshChildren( pane, Instance );\r\n\t\t}\r\n\r\n\t\t// SAVE original container CSS for use in destroy()\r\n\t\tif (!$N.data(css)) {\r\n\t\t\t// handle props like overflow different for BODY & HTML - has 'system default' values\r\n\t\t\tif (sC.isBody) {\r\n\t\t\t\t// SAVE <BODY> CSS\r\n\t\t\t\t$N.data(css, $.extend( styles($N, props), {\r\n\t\t\t\t\theight:\t\t$N.css(\"height\")\r\n\t\t\t\t,\toverflow:\t$N.css(\"overflow\")\r\n\t\t\t\t,\toverflowX:\t$N.css(\"overflowX\")\r\n\t\t\t\t,\toverflowY:\t$N.css(\"overflowY\")\r\n\t\t\t\t}));\r\n\t\t\t\t// ALSO SAVE <HTML> CSS\r\n\t\t\t\t$H.data(css, $.extend( styles($H, 'padding'), {\r\n\t\t\t\t\theight:\t\t\"auto\" // FF would return a fixed px-size!\r\n\t\t\t\t,\toverflow:\t$H.css(\"overflow\")\r\n\t\t\t\t,\toverflowX:\t$H.css(\"overflowX\")\r\n\t\t\t\t,\toverflowY:\t$H.css(\"overflowY\")\r\n\t\t\t\t}));\r\n\t\t\t}\r\n\t\t\telse // handle props normally for non-body elements\r\n\t\t\t\t$N.data(css, styles($N, props+\",top,bottom,left,right,width,height,overflow,overflowX,overflowY\") );\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\t// common container CSS\r\n\t\t\tCSS = {\r\n\t\t\t\toverflow:\thid\r\n\t\t\t,\toverflowX:\thid\r\n\t\t\t,\toverflowY:\thid\r\n\t\t\t};\r\n\t\t\t$N.css( CSS );\r\n\r\n\t\t\tif (o.inset && !$.isPlainObject(o.inset)) {\r\n\t\t\t\t// can specify a single number for equal outset all-around\r\n\t\t\t\tn = parseInt(o.inset, 10) || 0\r\n\t\t\t\to.inset = {\r\n\t\t\t\t\ttop:\tn\r\n\t\t\t\t,\tbottom:\tn\r\n\t\t\t\t,\tleft:\tn\r\n\t\t\t\t,\tright:\tn\r\n\t\t\t\t};\r\n\t\t\t}\r\n\r\n\t\t\t// format html & body if this is a full page layout\r\n\t\t\tif (sC.isBody) {\r\n\t\t\t\t// if HTML has padding, use this as an outer-spacing around BODY\r\n\t\t\t\tif (!o.outset) {\r\n\t\t\t\t\t// use padding from parent-elem (HTML) as outset\r\n\t\t\t\t\to.outset = {\r\n\t\t\t\t\t\ttop:\tnum($H, \"paddingTop\")\r\n\t\t\t\t\t,\tbottom:\tnum($H, \"paddingBottom\")\r\n\t\t\t\t\t,\tleft:\tnum($H, \"paddingLeft\")\r\n\t\t\t\t\t,\tright:\tnum($H, \"paddingRight\")\r\n\t\t\t\t\t};\r\n\t\t\t\t}\r\n\t\t\t\telse if (!$.isPlainObject(o.outset)) {\r\n\t\t\t\t\t// can specify a single number for equal outset all-around\r\n\t\t\t\t\tn = parseInt(o.outset, 10) || 0\r\n\t\t\t\t\to.outset = {\r\n\t\t\t\t\t\ttop:\tn\r\n\t\t\t\t\t,\tbottom:\tn\r\n\t\t\t\t\t,\tleft:\tn\r\n\t\t\t\t\t,\tright:\tn\r\n\t\t\t\t\t};\r\n\t\t\t\t}\r\n\t\t\t\t// HTML\r\n\t\t\t\t$H.css( CSS ).css({\r\n\t\t\t\t\theight:\t\t\"100%\"\r\n\t\t\t\t,\tborder:\t\t\"none\"\t// no border or padding allowed when using height = 100%\r\n\t\t\t\t,\tpadding:\t0\t\t// ditto\r\n\t\t\t\t,\tmargin:\t\t0\r\n\t\t\t\t});\r\n\t\t\t\t// BODY\r\n\t\t\t\tif (browser.isIE6) {\r\n\t\t\t\t\t// IE6 CANNOT use the trick of setting absolute positioning on all 4 sides - must have 'height'\r\n\t\t\t\t\t$N.css({\r\n\t\t\t\t\t\twidth:\t\t\"100%\"\r\n\t\t\t\t\t,\theight:\t\t\"100%\"\r\n\t\t\t\t\t,\tborder:\t\t\"none\"\t// no border or padding allowed when using height = 100%\r\n\t\t\t\t\t,\tpadding:\t0\t\t// ditto\r\n\t\t\t\t\t,\tmargin:\t\t0\r\n\t\t\t\t\t,\tposition:\t\"relative\"\r\n\t\t\t\t\t});\r\n\t\t\t\t\t// convert body padding to an inset option - the border cannot be measured in IE6!\r\n\t\t\t\t\tif (!o.inset) o.inset = elDims( $N ).inset;\r\n\t\t\t\t}\r\n\t\t\t\telse { // use absolute positioning for BODY to allow borders & padding without overflow\r\n\t\t\t\t\t$N.css({\r\n\t\t\t\t\t\twidth:\t\t\"auto\"\r\n\t\t\t\t\t,\theight:\t\t\"auto\"\r\n\t\t\t\t\t,\tmargin:\t\t0\r\n\t\t\t\t\t,\tposition:\t\"absolute\"\t// allows for border and padding on BODY\r\n\t\t\t\t\t});\r\n\t\t\t\t\t// apply edge-positioning created above\r\n\t\t\t\t\t$N.css( o.outset );\r\n\t\t\t\t}\r\n\t\t\t\t// set current layout-container dimensions\r\n\t\t\t\t$.extend(sC, elDims( $N, o.inset )); // passing inset means DO NOT include insetX values\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\t// container MUST have 'position'\r\n\t\t\t\tvar\tp = $N.css(\"position\");\r\n\t\t\t\tif (!p || !p.match(/(fixed|absolute|relative)/))\r\n\t\t\t\t\t$N.css(\"position\",\"relative\");\r\n\r\n\t\t\t\t// set current layout-container dimensions\r\n\t\t\t\tif ( $N.is(\":visible\") ) {\r\n\t\t\t\t\t$.extend(sC, elDims( $N, o.inset )); // passing inset means DO NOT change insetX (padding) values\r\n\t\t\t\t\tif (sC.innerHeight < 1) // container has no 'height' - warn developer\r\n\t\t\t\t\t\t_log( o.errors.noContainerHeight.replace(/CONTAINER/, sC.ref) );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// if container has min-width/height, then enable scrollbar(s)\r\n\t\t\tif ( num($N, \"minWidth\")  ) $N.parent().css(\"overflowX\",\"auto\");\r\n\t\t\tif ( num($N, \"minHeight\") ) $N.parent().css(\"overflowY\",\"auto\");\r\n\r\n\t\t} catch (ex) {}\r\n\t}\r\n\r\n\t/**\r\n\t* Bind layout hotkeys - if options enabled\r\n\t*\r\n\t* @see  _create() and addPane()\r\n\t* @param {string=}\t[panes=\"\"]\tThe edge(s) to process\r\n\t*/\r\n,\tinitHotkeys = function (panes) {\r\n\t\tpanes = panes ? panes.split(\",\") : _c.borderPanes;\r\n\t\t// bind keyDown to capture hotkeys, if option enabled for ANY pane\r\n\t\t$.each(panes, function (i, pane) {\r\n\t\t\tvar o = options[pane];\r\n\t\t\tif (o.enableCursorHotkey || o.customHotkey) {\r\n\t\t\t\t$(document).bind(\"keydown.\"+ sID, keyDown); // only need to bind this ONCE\r\n\t\t\t\treturn false; // BREAK - binding was done\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t* Build final OPTIONS data\r\n\t*\r\n\t* @see  _create()\r\n\t*/\r\n,\tinitOptions = function () {\r\n\t\tvar data, d, pane, key, val, i, c, o;\r\n\r\n\t\t// reprocess user's layout-options to have correct options sub-key structure\r\n\t\topts = $.layout.transformData( opts, true ); // panes = default subkey\r\n\r\n\t\t// auto-rename old options for backward compatibility\r\n\t\topts = $.layout.backwardCompatibility.renameAllOptions( opts );\r\n\r\n\t\t// if user-options has 'panes' key (pane-defaults), clean it...\r\n\t\tif (!$.isEmptyObject(opts.panes)) {\r\n\t\t\t// REMOVE any pane-defaults that MUST be set per-pane\r\n\t\t\tdata = $.layout.optionsMap.noDefault;\r\n\t\t\tfor (i=0, c=data.length; i<c; i++) {\r\n\t\t\t\tkey = data[i];\r\n\t\t\t\tdelete opts.panes[key]; // OK if does not exist\r\n\t\t\t}\r\n\t\t\t// REMOVE any layout-options specified under opts.panes\r\n\t\t\tdata = $.layout.optionsMap.layout;\r\n\t\t\tfor (i=0, c=data.length; i<c; i++) {\r\n\t\t\t\tkey = data[i];\r\n\t\t\t\tdelete opts.panes[key]; // OK if does not exist\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// MOVE any NON-layout-options from opts-root to opts.panes\r\n\t\tdata = $.layout.optionsMap.layout;\r\n\t\tvar rootKeys = $.layout.config.optionRootKeys;\r\n\t\tfor (key in opts) {\r\n\t\t\tval = opts[key];\r\n\t\t\tif ($.inArray(key, rootKeys) < 0 && $.inArray(key, data) < 0) {\r\n\t\t\t\tif (!opts.panes[key])\r\n\t\t\t\t\topts.panes[key] = $.isPlainObject(val) ? $.extend(true, {}, val) : val;\r\n\t\t\t\tdelete opts[key]\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// START by updating ALL options from opts\r\n\t\t$.extend(true, options, opts);\r\n\r\n\t\t// CREATE final options (and config) for EACH pane\r\n\t\t$.each(_c.allPanes, function (i, pane) {\r\n\r\n\t\t\t// apply 'pane-defaults' to CONFIG.[PANE]\r\n\t\t\t_c[pane] = $.extend(true, {}, _c.panes, _c[pane]);\r\n\r\n\t\t\td = options.panes;\r\n\t\t\to = options[pane];\r\n\r\n\t\t\t// center-pane uses SOME keys in defaults.panes branch\r\n\t\t\tif (pane === 'center') {\r\n\t\t\t\t// ONLY copy keys from opts.panes listed in: $.layout.optionsMap.center\r\n\t\t\t\tdata = $.layout.optionsMap.center;\t\t// list of 'center-pane keys'\r\n\t\t\t\tfor (i=0, c=data.length; i<c; i++) {\t// loop the list...\r\n\t\t\t\t\tkey = data[i];\r\n\t\t\t\t\t// only need to use pane-default if pane-specific value not set\r\n\t\t\t\t\tif (!opts.center[key] && (opts.panes[key] || !o[key]))\r\n\t\t\t\t\t\to[key] = d[key]; // pane-default\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\t// border-panes use ALL keys in defaults.panes branch\r\n\t\t\t\to = options[pane] = $.extend(true, {}, d, o); // re-apply pane-specific opts AFTER pane-defaults\r\n\t\t\t\tcreateFxOptions( pane );\r\n\t\t\t\t// ensure all border-pane-specific base-classes exist\r\n\t\t\t\tif (!o.resizerClass)\to.resizerClass\t= \"ui-layout-resizer\";\r\n\t\t\t\tif (!o.togglerClass)\to.togglerClass\t= \"ui-layout-toggler\";\r\n\t\t\t}\r\n\t\t\t// ensure we have base pane-class (ALL panes)\r\n\t\t\tif (!o.paneClass) o.paneClass = \"ui-layout-pane\";\r\n\t\t});\r\n\r\n\t\t// update options.zIndexes if a zIndex-option specified\r\n\t\tvar zo\t= opts.zIndex\r\n\t\t,\tz\t= options.zIndexes;\r\n\t\tif (zo > 0) {\r\n\t\t\tz.pane_normal\t\t= zo;\r\n\t\t\tz.content_mask\t\t= max(zo+1, z.content_mask);\t// MIN = +1\r\n\t\t\tz.resizer_normal\t= max(zo+2, z.resizer_normal);\t// MIN = +2\r\n\t\t}\r\n\r\n\t\t// DELETE 'panes' key now that we are done - values were copied to EACH pane\r\n\t\tdelete options.panes;\r\n\r\n\r\n\t\tfunction createFxOptions ( pane ) {\r\n\t\t\tvar\to = options[pane]\r\n\t\t\t,\td = options.panes;\r\n\t\t\t// ensure fxSettings key to avoid errors\r\n\t\t\tif (!o.fxSettings) o.fxSettings = {};\r\n\t\t\tif (!d.fxSettings) d.fxSettings = {};\r\n\r\n\t\t\t$.each([\"_open\",\"_close\",\"_size\"], function (i,n) { \r\n\t\t\t\tvar\r\n\t\t\t\t\tsName\t\t= \"fxName\"+ n\r\n\t\t\t\t,\tsSpeed\t\t= \"fxSpeed\"+ n\r\n\t\t\t\t,\tsSettings\t= \"fxSettings\"+ n\r\n\t\t\t\t\t// recalculate fxName according to specificity rules\r\n\t\t\t\t,\tfxName = o[sName] =\r\n\t\t\t\t\t\to[sName]\t// options.west.fxName_open\r\n\t\t\t\t\t||\td[sName]\t// options.panes.fxName_open\r\n\t\t\t\t\t||\to.fxName\t// options.west.fxName\r\n\t\t\t\t\t||\td.fxName\t// options.panes.fxName\r\n\t\t\t\t\t||\t\"none\"\t\t// MEANS $.layout.defaults.panes.fxName == \"\" || false || null || 0\r\n\t\t\t\t,\tfxExists\t= $.effects && ($.effects[fxName] || ($.effects.effect && $.effects.effect[fxName]))\r\n\t\t\t\t;\r\n\t\t\t\t// validate fxName to ensure is valid effect - MUST have effect-config data in options.effects\r\n\t\t\t\tif (fxName === \"none\" || !options.effects[fxName] || !fxExists)\r\n\t\t\t\t\tfxName = o[sName] = \"none\"; // effect not loaded OR unrecognized fxName\r\n\r\n\t\t\t\t// set vars for effects subkeys to simplify logic\r\n\t\t\t\tvar\tfx\t\t= options.effects[fxName] || {}\t// effects.slide\r\n\t\t\t\t,\tfx_all\t= fx.all\t|| null\t\t\t\t// effects.slide.all\r\n\t\t\t\t,\tfx_pane\t= fx[pane]\t|| null\t\t\t\t// effects.slide.west\r\n\t\t\t\t;\r\n\t\t\t\t// create fxSpeed[_open|_close|_size]\r\n\t\t\t\to[sSpeed] =\r\n\t\t\t\t\to[sSpeed]\t\t\t\t// options.west.fxSpeed_open\r\n\t\t\t\t||\td[sSpeed]\t\t\t\t// options.west.fxSpeed_open\r\n\t\t\t\t||\to.fxSpeed\t\t\t\t// options.west.fxSpeed\r\n\t\t\t\t||\td.fxSpeed\t\t\t\t// options.panes.fxSpeed\r\n\t\t\t\t||\tnull\t\t\t\t\t// DEFAULT - let fxSetting.duration control speed\r\n\t\t\t\t;\r\n\t\t\t\t// create fxSettings[_open|_close|_size]\r\n\t\t\t\to[sSettings] = $.extend(\r\n\t\t\t\t\ttrue\r\n\t\t\t\t,\t{}\r\n\t\t\t\t,\tfx_all\t\t\t\t\t// effects.slide.all\r\n\t\t\t\t,\tfx_pane\t\t\t\t\t// effects.slide.west\r\n\t\t\t\t,\td.fxSettings\t\t\t// options.panes.fxSettings\r\n\t\t\t\t,\to.fxSettings\t\t\t// options.west.fxSettings\r\n\t\t\t\t,\td[sSettings]\t\t\t// options.panes.fxSettings_open\r\n\t\t\t\t,\to[sSettings]\t\t\t// options.west.fxSettings_open\r\n\t\t\t\t);\r\n\t\t\t});\r\n\r\n\t\t\t// DONE creating action-specific-settings for this pane,\r\n\t\t\t// so DELETE generic options - are no longer meaningful\r\n\t\t\tdelete o.fxName;\r\n\t\t\tdelete o.fxSpeed;\r\n\t\t\tdelete o.fxSettings;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t* Initialize module objects, styling, size and position for all panes\r\n\t*\r\n\t* @see  _initElements()\r\n\t* @param {string}\tpane\t\tThe pane to process\r\n\t*/\r\n,\tgetPane = function (pane) {\r\n\t\tvar sel = options[pane].paneSelector\r\n\t\tif (sel.substr(0,1)===\"#\") // ID selector\r\n\t\t\t// NOTE: elements selected 'by ID' DO NOT have to be 'children'\r\n\t\t\treturn $N.find(sel).eq(0);\r\n\t\telse { // class or other selector\r\n\t\t\tvar $P = $N.children(sel).eq(0);\r\n\t\t\t// look for the pane nested inside a 'form' element\r\n\t\t\treturn $P.length ? $P : $N.children(\"form:first\").children(sel).eq(0);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t* @param {Object=}\t\tevt\r\n\t*/\r\n,\tinitPanes = function (evt) {\r\n\t\t// stopPropagation if called by trigger(\"layoutinitpanes\") - use evtPane utility \r\n\t\tevtPane(evt);\r\n\r\n\t\t// NOTE: do north & south FIRST so we can measure their height - do center LAST\r\n\t\t$.each(_c.allPanes, function (idx, pane) {\r\n\t\t\taddPane( pane, true );\r\n\t\t});\r\n\r\n\t\t// init the pane-handles NOW in case we have to hide or close the pane below\r\n\t\tinitHandles();\r\n\r\n\t\t// now that all panes have been initialized and initially-sized,\r\n\t\t// make sure there is really enough space available for each pane\r\n\t\t$.each(_c.borderPanes, function (i, pane) {\r\n\t\t\tif ($Ps[pane] && state[pane].isVisible) { // pane is OPEN\r\n\t\t\t\tsetSizeLimits(pane);\r\n\t\t\t\tmakePaneFit(pane); // pane may be Closed, Hidden or Resized by makePaneFit()\r\n\t\t\t}\r\n\t\t});\r\n\t\t// size center-pane AGAIN in case we 'closed' a border-pane in loop above\r\n\t\tsizeMidPanes(\"center\");\r\n\r\n\t\t//\tChrome/Webkit sometimes fires callbacks BEFORE it completes resizing!\r\n\t\t//\tBefore RC30.3, there was a 10ms delay here, but that caused layout \r\n\t\t//\tto load asynchrously, which is BAD, so try skipping delay for now\r\n\r\n\t\t// process pane contents and callbacks, and init/resize child-layout if exists\r\n\t\t$.each(_c.allPanes, function (idx, pane) {\r\n\t\t\tafterInitPane(pane);\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t* Add a pane to the layout - subroutine of initPanes()\r\n\t*\r\n\t* @see  initPanes()\r\n\t* @param {string}\tpane\t\t\tThe pane to process\r\n\t* @param {boolean=}\t[force=false]\tSize content after init\r\n\t*/\r\n,\taddPane = function (pane, force) {\r\n\t\tif (!force && !isInitialized()) return;\r\n\t\tvar\r\n\t\t\to\t\t= options[pane]\r\n\t\t,\ts\t\t= state[pane]\r\n\t\t,\tc\t\t= _c[pane]\r\n\t\t,\tdir\t\t= c.dir\r\n\t\t,\tfx\t\t= s.fx\r\n\t\t,\tspacing\t= o.spacing_open || 0\r\n\t\t,\tisCenter = (pane === \"center\")\r\n\t\t,\tCSS\t\t= {}\r\n\t\t,\t$P\t\t= $Ps[pane]\r\n\t\t,\tsize, minSize, maxSize, child\r\n\t\t;\r\n\t\t// if pane-pointer already exists, remove the old one first\r\n\t\tif ($P)\r\n\t\t\tremovePane( pane, false, true, false );\r\n\t\telse\r\n\t\t\t$Cs[pane] = false; // init\r\n\r\n\t\t$P = $Ps[pane] = getPane(pane);\r\n\t\tif (!$P.length) {\r\n\t\t\t$Ps[pane] = false; // logic\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// SAVE original Pane CSS\r\n\t\tif (!$P.data(\"layoutCSS\")) {\r\n\t\t\tvar props = \"position,top,left,bottom,right,width,height,overflow,zIndex,display,backgroundColor,padding,margin,border\";\r\n\t\t\t$P.data(\"layoutCSS\", styles($P, props));\r\n\t\t}\r\n\r\n\t\t// create alias for pane data in Instance - initHandles will add more\r\n\t\tInstance[pane] = {\r\n\t\t\tname:\t\tpane\r\n\t\t,\tpane:\t\t$Ps[pane]\r\n\t\t,\tcontent:\t$Cs[pane]\r\n\t\t,\toptions:\toptions[pane]\r\n\t\t,\tstate:\t\tstate[pane]\r\n\t\t,\tchildren:\tchildren[pane]\r\n\t\t};\r\n\r\n\t\t// add classes, attributes & events\r\n\t\t$P\t.data({\r\n\t\t\t\tparentLayout:\tInstance\t\t// pointer to Layout Instance\r\n\t\t\t,\tlayoutPane:\t\tInstance[pane]\t// NEW pointer to pane-alias-object\r\n\t\t\t,\tlayoutEdge:\t\tpane\r\n\t\t\t,\tlayoutRole:\t\t\"pane\"\r\n\t\t\t})\r\n\t\t\t.css(c.cssReq).css(\"zIndex\", options.zIndexes.pane_normal)\r\n\t\t\t.css(o.applyDemoStyles ? c.cssDemo : {}) // demo styles\r\n\t\t\t.addClass( o.paneClass +\" \"+ o.paneClass+\"-\"+pane ) // default = \"ui-layout-pane ui-layout-pane-west\" - may be a dupe of 'paneSelector'\r\n\t\t\t.bind(\"mouseenter.\"+ sID, addHover )\r\n\t\t\t.bind(\"mouseleave.\"+ sID, removeHover )\r\n\t\t\t;\r\n\t\tvar paneMethods = {\r\n\t\t\t\thide:\t\t\t\t''\r\n\t\t\t,\tshow:\t\t\t\t''\r\n\t\t\t,\ttoggle:\t\t\t\t''\r\n\t\t\t,\tclose:\t\t\t\t''\r\n\t\t\t,\topen:\t\t\t\t''\r\n\t\t\t,\tslideOpen:\t\t\t''\r\n\t\t\t,\tslideClose:\t\t\t''\r\n\t\t\t,\tslideToggle:\t\t''\r\n\t\t\t,\tsize:\t\t\t\t'sizePane'\r\n\t\t\t,\tsizePane:\t\t\t'sizePane'\r\n\t\t\t,\tsizeContent:\t\t''\r\n\t\t\t,\tsizeHandles:\t\t''\r\n\t\t\t,\tenableClosable:\t\t''\r\n\t\t\t,\tdisableClosable:\t''\r\n\t\t\t,\tenableSlideable:\t''\r\n\t\t\t,\tdisableSlideable:\t''\r\n\t\t\t,\tenableResizable:\t''\r\n\t\t\t,\tdisableResizable:\t''\r\n\t\t\t,\tswapPanes:\t\t\t'swapPanes'\r\n\t\t\t,\tswap:\t\t\t\t'swapPanes'\r\n\t\t\t,\tmove:\t\t\t\t'swapPanes'\r\n\t\t\t,\tremovePane:\t\t\t'removePane'\r\n\t\t\t,\tremove:\t\t\t\t'removePane'\r\n\t\t\t,\tcreateChildren:\t\t''\r\n\t\t\t,\tresizeChildren:\t\t''\r\n\t\t\t,\tresizeAll:\t\t\t'resizeAll'\r\n\t\t\t,\tresizeLayout:\t\t'resizeAll'\r\n\t\t\t}\r\n\t\t,\tname;\r\n\t\t// loop hash and bind all methods - include layoutID namespacing\r\n\t\tfor (name in paneMethods) {\r\n\t\t\t$P.bind(\"layoutpane\"+ name.toLowerCase() +\".\"+ sID, Instance[ paneMethods[name] || name ]);\r\n\t\t}\r\n\r\n\t\t// see if this pane has a 'scrolling-content element'\r\n\t\tinitContent(pane, false); // false = do NOT sizeContent() - called later\r\n\r\n\t\tif (!isCenter) {\r\n\t\t\t// call _parseSize AFTER applying pane classes & styles - but before making visible (if hidden)\r\n\t\t\t// if o.size is auto or not valid, then MEASURE the pane and use that as its 'size'\r\n\t\t\tsize\t= s.size = _parseSize(pane, o.size);\r\n\t\t\tminSize\t= _parseSize(pane,o.minSize) || 1;\r\n\t\t\tmaxSize\t= _parseSize(pane,o.maxSize) || 100000;\r\n\t\t\tif (size > 0) size = max(min(size, maxSize), minSize);\r\n\t\t\ts.autoResize = o.autoResize; // used with percentage sizes\r\n\r\n\t\t\t// state for border-panes\r\n\t\t\ts.isClosed  = false; // true = pane is closed\r\n\t\t\ts.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes\r\n\t\t\ts.isResizing= false; // true = pane is in process of being resized\r\n\t\t\ts.isHidden\t= false; // true = pane is hidden - no spacing, resizer or toggler is visible!\r\n\r\n\t\t\t// array for 'pin buttons' whose classNames are auto-updated on pane-open/-close\r\n\t\t\tif (!s.pins) s.pins = [];\r\n\t\t}\r\n\t\t//\tstates common to ALL panes\r\n\t\ts.tagName\t= $P[0].tagName;\r\n\t\ts.edge\t\t= pane;\t\t// useful if pane is (or about to be) 'swapped' - easy find out where it is (or is going)\r\n\t\ts.noRoom\t= false;\t// true = pane 'automatically' hidden due to insufficient room - will unhide automatically\r\n\t\ts.isVisible\t= true;\t\t// false = pane is invisible - closed OR hidden - simplify logic\r\n\r\n\t\t// init pane positioning\r\n\t\tsetPanePosition( pane );\r\n\r\n\t\t// if pane is not visible, \r\n\t\tif (dir === \"horz\") // north or south pane\r\n\t\t\tCSS.height = cssH($P, size);\r\n\t\telse if (dir === \"vert\") // east or west pane\r\n\t\t\tCSS.width = cssW($P, size);\r\n\t\t//else if (isCenter) {}\r\n\r\n\t\t$P.css(CSS); // apply size -- top, bottom & height will be set by sizeMidPanes\r\n\t\tif (dir != \"horz\") sizeMidPanes(pane, true); // true = skipCallback\r\n\r\n\t\t// if manually adding a pane AFTER layout initialization, then...\r\n\t\tif (state.initialized) {\r\n\t\t\tinitHandles( pane );\r\n\t\t\tinitHotkeys( pane );\r\n\t\t}\r\n\r\n\t\t// close or hide the pane if specified in settings\r\n\t\tif (o.initClosed && o.closable && !o.initHidden)\r\n\t\t\tclose(pane, true, true); // true, true = force, noAnimation\r\n\t\telse if (o.initHidden || o.initClosed)\r\n\t\t\thide(pane); // will be completely invisible - no resizer or spacing\r\n\t\telse if (!s.noRoom)\r\n\t\t\t// make the pane visible - in case was initially hidden\r\n\t\t\t$P.css(\"display\",\"block\");\r\n\t\t// ELSE setAsOpen() - called later by initHandles()\r\n\r\n\t\t// RESET visibility now - pane will appear IF display:block\r\n\t\t$P.css(\"visibility\",\"visible\");\r\n\r\n\t\t// check option for auto-handling of pop-ups & drop-downs\r\n\t\tif (o.showOverflowOnHover)\r\n\t\t\t$P.hover( allowOverflow, resetOverflow );\r\n\r\n\t\t// if manually adding a pane AFTER layout initialization, then...\r\n\t\tif (state.initialized) {\r\n\t\t\tafterInitPane( pane );\r\n\t\t}\r\n\t}\r\n\r\n,\tafterInitPane = function (pane) {\r\n\t\tvar\t$P\t= $Ps[pane]\r\n\t\t,\ts\t= state[pane]\r\n\t\t,\to\t= options[pane]\r\n\t\t;\r\n\t\tif (!$P) return;\r\n\r\n\t\t// see if there is a directly-nested layout inside this pane\r\n\t\tif ($P.data(\"layout\"))\r\n\t\t\trefreshChildren( pane, $P.data(\"layout\") );\r\n\r\n\t\t// process pane contents and callbacks, and init/resize child-layout if exists\r\n\t\tif (s.isVisible) { // pane is OPEN\r\n\t\t\tif (state.initialized) // this pane was added AFTER layout was created\r\n\t\t\t\tresizeAll(); // will also sizeContent\r\n\t\t\telse\r\n\t\t\t\tsizeContent(pane);\r\n\r\n\t\t\tif (o.triggerEventsOnLoad)\r\n\t\t\t\t_runCallbacks(\"onresize_end\", pane);\r\n\t\t\telse // automatic if onresize called, otherwise call it specifically\r\n\t\t\t\t// resize child - IF inner-layout already exists (created before this layout)\r\n\t\t\t\tresizeChildren(pane, true); // a previously existing childLayout\r\n\t\t}\r\n\r\n\t\t// init childLayouts - even if pane is not visible\r\n\t\tif (o.initChildren && o.children)\r\n\t\t\tcreateChildren(pane);\r\n\t}\r\n\r\n\t/**\r\n\t* @param {string=}\tpanes\t\tThe pane(s) to process\r\n\t*/\r\n,\tsetPanePosition = function (panes) {\r\n\t\tpanes = panes ? panes.split(\",\") : _c.borderPanes;\r\n\r\n\t\t// create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV\r\n\t\t$.each(panes, function (i, pane) {\r\n\t\t\tvar $P\t= $Ps[pane]\r\n\t\t\t,\t$R\t= $Rs[pane]\r\n\t\t\t,\to\t= options[pane]\r\n\t\t\t,\ts\t= state[pane]\r\n\t\t\t,\tside =  _c[pane].side\r\n\t\t\t,\tCSS\t= {}\r\n\t\t\t;\r\n\t\t\tif (!$P) return; // pane does not exist - skip\r\n\r\n\t\t\t// set css-position to account for container borders & padding\r\n\t\t\tswitch (pane) {\r\n\t\t\t\tcase \"north\": \tCSS.top \t= sC.inset.top;\r\n\t\t\t\t\t\t\t\tCSS.left \t= sC.inset.left;\r\n\t\t\t\t\t\t\t\tCSS.right\t= sC.inset.right;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"south\": \tCSS.bottom\t= sC.inset.bottom;\r\n\t\t\t\t\t\t\t\tCSS.left \t= sC.inset.left;\r\n\t\t\t\t\t\t\t\tCSS.right \t= sC.inset.right;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"west\": \tCSS.left \t= sC.inset.left; // top, bottom & height set by sizeMidPanes()\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"east\": \tCSS.right \t= sC.inset.right; // ditto\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\tcase \"center\":\t// top, left, width & height set by sizeMidPanes()\r\n\t\t\t}\r\n\t\t\t// apply position\r\n\t\t\t$P.css(CSS); \r\n\r\n\t\t\t// update resizer position\r\n\t\t\tif ($R && s.isClosed)\r\n\t\t\t\t$R.css(side, sC.inset[side]);\r\n\t\t\telse if ($R && !s.isHidden)\r\n\t\t\t\t$R.css(side, sC.inset[side] + getPaneSize(pane));\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t* Initialize module objects, styling, size and position for all resize bars and toggler buttons\r\n\t*\r\n\t* @see  _create()\r\n\t* @param {string=}\t[panes=\"\"]\tThe edge(s) to process\r\n\t*/\r\n,\tinitHandles = function (panes) {\r\n\t\tpanes = panes ? panes.split(\",\") : _c.borderPanes;\r\n\r\n\t\t// create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV\r\n\t\t$.each(panes, function (i, pane) {\r\n\t\t\tvar $P\t\t= $Ps[pane];\r\n\t\t\t$Rs[pane]\t= false; // INIT\r\n\t\t\t$Ts[pane]\t= false;\r\n\t\t\tif (!$P) return; // pane does not exist - skip\r\n\r\n\t\t\tvar\to\t\t= options[pane]\r\n\t\t\t,\ts\t\t= state[pane]\r\n\t\t\t,\tc\t\t= _c[pane]\r\n\t\t\t,\tpaneId\t= o.paneSelector.substr(0,1) === \"#\" ? o.paneSelector.substr(1) : \"\"\r\n\t\t\t,\trClass\t= o.resizerClass\r\n\t\t\t,\ttClass\t= o.togglerClass\r\n\t\t\t,\tspacing\t= (s.isVisible ? o.spacing_open : o.spacing_closed)\r\n\t\t\t,\t_pane\t= \"-\"+ pane // used for classNames\r\n\t\t\t,\t_state\t= (s.isVisible ? \"-open\" : \"-closed\") // used for classNames\r\n\t\t\t,\tI\t\t= Instance[pane]\r\n\t\t\t\t// INIT RESIZER BAR\r\n\t\t\t,\t$R\t\t= I.resizer = $Rs[pane] = $(\"<div></div>\")\r\n\t\t\t\t// INIT TOGGLER BUTTON\r\n\t\t\t,\t$T\t\t= I.toggler = (o.closable ? $Ts[pane] = $(\"<div></div>\") : false)\r\n\t\t\t;\r\n\r\n\t\t\t//if (s.isVisible && o.resizable) ... handled by initResizable\r\n\t\t\tif (!s.isVisible && o.slidable)\r\n\t\t\t\t$R.attr(\"title\", o.tips.Slide).css(\"cursor\", o.sliderCursor);\r\n\r\n\t\t\t$R\t// if paneSelector is an ID, then create a matching ID for the resizer, eg: \"#paneLeft\" => \"paneLeft-resizer\"\r\n\t\t\t\t.attr(\"id\", paneId ? paneId +\"-resizer\" : \"\" )\r\n\t\t\t\t.data({\r\n\t\t\t\t\tparentLayout:\tInstance\r\n\t\t\t\t,\tlayoutPane:\t\tInstance[pane]\t// NEW pointer to pane-alias-object\r\n\t\t\t\t,\tlayoutEdge:\t\tpane\r\n\t\t\t\t,\tlayoutRole:\t\t\"resizer\"\r\n\t\t\t\t})\r\n\t\t\t\t.css(_c.resizers.cssReq).css(\"zIndex\", options.zIndexes.resizer_normal)\r\n\t\t\t\t.css(o.applyDemoStyles ? _c.resizers.cssDemo : {}) // add demo styles\r\n\t\t\t\t.addClass(rClass +\" \"+ rClass+_pane)\r\n\t\t\t\t.hover(addHover, removeHover) // ALWAYS add hover-classes, even if resizing is not enabled - handle with CSS instead\r\n\t\t\t\t.hover(onResizerEnter, onResizerLeave) // ALWAYS NEED resizer.mouseleave to balance toggler.mouseenter\r\n\t\t\t\t.appendTo($N) // append DIV to container\r\n\t\t\t;\r\n\t\t\tif (o.resizerDblClickToggle)\r\n\t\t\t\t$R.bind(\"dblclick.\"+ sID, toggle );\r\n\r\n\t\t\tif ($T) {\r\n\t\t\t\t$T\t// if paneSelector is an ID, then create a matching ID for the resizer, eg: \"#paneLeft\" => \"#paneLeft-toggler\"\r\n\t\t\t\t\t.attr(\"id\", paneId ? paneId +\"-toggler\" : \"\" )\r\n\t\t\t\t\t.data({\r\n\t\t\t\t\t\tparentLayout:\tInstance\r\n\t\t\t\t\t,\tlayoutPane:\t\tInstance[pane]\t// NEW pointer to pane-alias-object\r\n\t\t\t\t\t,\tlayoutEdge:\t\tpane\r\n\t\t\t\t\t,\tlayoutRole:\t\t\"toggler\"\r\n\t\t\t\t\t})\r\n\t\t\t\t\t.css(_c.togglers.cssReq) // add base/required styles\r\n\t\t\t\t\t.css(o.applyDemoStyles ? _c.togglers.cssDemo : {}) // add demo styles\r\n\t\t\t\t\t.addClass(tClass +\" \"+ tClass+_pane)\r\n\t\t\t\t\t.hover(addHover, removeHover) // ALWAYS add hover-classes, even if toggling is not enabled - handle with CSS instead\r\n\t\t\t\t\t.bind(\"mouseenter\", onResizerEnter) // NEED toggler.mouseenter because mouseenter MAY NOT fire on resizer\r\n\t\t\t\t\t.appendTo($R) // append SPAN to resizer DIV\r\n\t\t\t\t;\r\n\t\t\t\t// ADD INNER-SPANS TO TOGGLER\r\n\t\t\t\tif (o.togglerContent_open) // ui-layout-open\r\n\t\t\t\t\t$(\"<span>\"+ o.togglerContent_open +\"</span>\")\r\n\t\t\t\t\t\t.data({\r\n\t\t\t\t\t\t\tlayoutEdge:\t\tpane\r\n\t\t\t\t\t\t,\tlayoutRole:\t\t\"togglerContent\"\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t\t.data(\"layoutRole\", \"togglerContent\")\r\n\t\t\t\t\t\t.data(\"layoutEdge\", pane)\r\n\t\t\t\t\t\t.addClass(\"content content-open\")\r\n\t\t\t\t\t\t.css(\"display\",\"none\")\r\n\t\t\t\t\t\t.appendTo( $T )\r\n\t\t\t\t\t\t//.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-open instead!\r\n\t\t\t\t\t;\r\n\t\t\t\tif (o.togglerContent_closed) // ui-layout-closed\r\n\t\t\t\t\t$(\"<span>\"+ o.togglerContent_closed +\"</span>\")\r\n\t\t\t\t\t\t.data({\r\n\t\t\t\t\t\t\tlayoutEdge:\t\tpane\r\n\t\t\t\t\t\t,\tlayoutRole:\t\t\"togglerContent\"\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t\t.addClass(\"content content-closed\")\r\n\t\t\t\t\t\t.css(\"display\",\"none\")\r\n\t\t\t\t\t\t.appendTo( $T )\r\n\t\t\t\t\t\t//.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-closed instead!\r\n\t\t\t\t\t;\r\n\t\t\t\t// ADD TOGGLER.click/.hover\r\n\t\t\t\tenableClosable(pane);\r\n\t\t\t}\r\n\r\n\t\t\t// add Draggable events\r\n\t\t\tinitResizable(pane);\r\n\r\n\t\t\t// ADD CLASSNAMES & SLIDE-BINDINGS - eg: class=\"resizer resizer-west resizer-open\"\r\n\t\t\tif (s.isVisible)\r\n\t\t\t\tsetAsOpen(pane);\t// onOpen will be called, but NOT onResize\r\n\t\t\telse {\r\n\t\t\t\tsetAsClosed(pane);\t// onClose will be called\r\n\t\t\t\tbindStartSlidingEvents(pane, true); // will enable events IF option is set\r\n\t\t\t}\r\n\r\n\t\t});\r\n\r\n\t\t// SET ALL HANDLE DIMENSIONS\r\n\t\tsizeHandles();\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* Initialize scrolling ui-layout-content div - if exists\r\n\t*\r\n\t* @see  initPane() - or externally after an Ajax injection\r\n\t* @param {string}\tpane\t\t\tThe pane to process\r\n\t* @param {boolean=}\t[resize=true]\tSize content after init\r\n\t*/\r\n,\tinitContent = function (pane, resize) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar \r\n\t\t\to\t= options[pane]\r\n\t\t,\tsel\t= o.contentSelector\r\n\t\t,\tI\t= Instance[pane]\r\n\t\t,\t$P\t= $Ps[pane]\r\n\t\t,\t$C\r\n\t\t;\r\n\t\tif (sel) $C = I.content = $Cs[pane] = (o.findNestedContent)\r\n\t\t\t? $P.find(sel).eq(0) // match 1-element only\r\n\t\t\t: $P.children(sel).eq(0)\r\n\t\t;\r\n\t\tif ($C && $C.length) {\r\n\t\t\t$C.data(\"layoutRole\", \"content\");\r\n\t\t\t// SAVE original Content CSS\r\n\t\t\tif (!$C.data(\"layoutCSS\"))\r\n\t\t\t\t$C.data(\"layoutCSS\", styles($C, \"height\"));\r\n\t\t\t$C.css( _c.content.cssReq );\r\n\t\t\tif (o.applyDemoStyles) {\r\n\t\t\t\t$C.css( _c.content.cssDemo ); // add padding & overflow: auto to content-div\r\n\t\t\t\t$P.css( _c.content.cssDemoPane ); // REMOVE padding/scrolling from pane\r\n\t\t\t}\r\n\t\t\t// ensure no vertical scrollbar on pane - will mess up measurements\r\n\t\t\tif ($P.css(\"overflowX\").match(/(scroll|auto)/)) {\r\n\t\t\t\t$P.css(\"overflow\", \"hidden\");\r\n\t\t\t}\r\n\t\t\tstate[pane].content = {}; // init content state\r\n\t\t\tif (resize !== false) sizeContent(pane);\r\n\t\t\t// sizeContent() is called AFTER init of all elements\r\n\t\t}\r\n\t\telse\r\n\t\t\tI.content = $Cs[pane] = false;\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* Add resize-bars to all panes that specify it in options\r\n\t* -dependancy: $.fn.resizable - will skip if not found\r\n\t*\r\n\t* @see  _create()\r\n\t* @param {string=}\t[panes=\"\"]\tThe edge(s) to process\r\n\t*/\r\n,\tinitResizable = function (panes) {\r\n\t\tvar\tdraggingAvailable = $.layout.plugins.draggable\r\n\t\t,\tside // set in start()\r\n\t\t;\r\n\t\tpanes = panes ? panes.split(\",\") : _c.borderPanes;\r\n\r\n\t\t$.each(panes, function (idx, pane) {\r\n\t\t\tvar o = options[pane];\r\n\t\t\tif (!draggingAvailable || !$Ps[pane] || !o.resizable) {\r\n\t\t\t\to.resizable = false;\r\n\t\t\t\treturn true; // skip to next\r\n\t\t\t}\r\n\r\n\t\t\tvar s\t\t= state[pane]\r\n\t\t\t,\tz\t\t= options.zIndexes\r\n\t\t\t,\tc\t\t= _c[pane]\r\n\t\t\t,\tside\t= c.dir==\"horz\" ? \"top\" : \"left\"\r\n\t\t\t,\t$P \t\t= $Ps[pane]\r\n\t\t\t,\t$R\t\t= $Rs[pane]\r\n\t\t\t,\tbase\t= o.resizerClass\r\n\t\t\t,\tlastPos\t= 0 // used when live-resizing\r\n\t\t\t,\tr, live // set in start because may change\r\n\t\t\t//\t'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process\r\n\t\t\t,\tresizerClass\t\t= base+\"-drag\"\t\t\t\t// resizer-drag\r\n\t\t\t,\tresizerPaneClass\t= base+\"-\"+pane+\"-drag\"\t\t// resizer-north-drag\r\n\t\t\t//\t'helper' class is applied to the CLONED resizer-bar while it is being dragged\r\n\t\t\t,\thelperClass\t\t\t= base+\"-dragging\"\t\t\t// resizer-dragging\r\n\t\t\t,\thelperPaneClass\t\t= base+\"-\"+pane+\"-dragging\" // resizer-north-dragging\r\n\t\t\t,\thelperLimitClass\t= base+\"-dragging-limit\"\t// resizer-drag\r\n\t\t\t,\thelperPaneLimitClass = base+\"-\"+pane+\"-dragging-limit\"\t// resizer-north-drag\r\n\t\t\t,\thelperClassesSet\t= false \t\t\t\t\t// logic var\r\n\t\t\t;\r\n\r\n\t\t\tif (!s.isClosed)\r\n\t\t\t\t$R.attr(\"title\", o.tips.Resize)\r\n\t\t\t\t  .css(\"cursor\", o.resizerCursor); // n-resize, s-resize, etc\r\n\r\n\t\t\t$R.draggable({\r\n\t\t\t\tcontainment:\t$N[0] // limit resizing to layout container\r\n\t\t\t,\taxis:\t\t\t(c.dir==\"horz\" ? \"y\" : \"x\") // limit resizing to horz or vert axis\r\n\t\t\t,\tdelay:\t\t\t0\r\n\t\t\t,\tdistance:\t\t1\r\n\t\t\t,\tgrid:\t\t\to.resizingGrid\r\n\t\t\t//\tbasic format for helper - style it using class: .ui-draggable-dragging\r\n\t\t\t,\thelper:\t\t\t\"clone\"\r\n\t\t\t,\topacity:\t\to.resizerDragOpacity\r\n\t\t\t,\taddClasses:\t\tfalse // avoid ui-state-disabled class when disabled\r\n\t\t\t//,\tiframeFix:\t\to.draggableIframeFix // TODO: consider using when bug is fixed\r\n\t\t\t,\tzIndex:\t\t\tz.resizer_drag\r\n\r\n\t\t\t,\tstart: function (e, ui) {\r\n\t\t\t\t\t// REFRESH options & state pointers in case we used swapPanes\r\n\t\t\t\t\to = options[pane];\r\n\t\t\t\t\ts = state[pane];\r\n\t\t\t\t\t// re-read options\r\n\t\t\t\t\tlive = o.livePaneResizing;\r\n\r\n\t\t\t\t\t// ondrag_start callback - will CANCEL hide if returns false\r\n\t\t\t\t\t// TODO: dragging CANNOT be cancelled like this, so see if there is a way?\r\n\t\t\t\t\tif (false === _runCallbacks(\"ondrag_start\", pane)) return false;\r\n\r\n\t\t\t\t\ts.isResizing\t\t= true; // prevent pane from closing while resizing\r\n\t\t\t\t\tstate.paneResizing\t= pane; // easy to see if ANY pane is resizing\r\n\t\t\t\t\ttimer.clear(pane+\"_closeSlider\"); // just in case already triggered\r\n\r\n\t\t\t\t\t// SET RESIZER LIMITS - used in drag()\r\n\t\t\t\t\tsetSizeLimits(pane); // update pane/resizer state\r\n\t\t\t\t\tr = s.resizerPosition;\r\n\t\t\t\t\tlastPos = ui.position[ side ]\r\n\r\n\t\t\t\t\t$R.addClass( resizerClass +\" \"+ resizerPaneClass ); // add drag classes\r\n\t\t\t\t\thelperClassesSet = false; // reset logic var - see drag()\r\n\r\n\t\t\t\t\t// DISABLE TEXT SELECTION (probably already done by resizer.mouseOver)\r\n\t\t\t\t\t$('body').disableSelection(); \r\n\r\n\t\t\t\t\t// MASK PANES CONTAINING IFRAMES, APPLETS OR OTHER TROUBLESOME ELEMENTS\r\n\t\t\t\t\tshowMasks( pane, { resizing: true });\r\n\t\t\t\t}\r\n\r\n\t\t\t,\tdrag: function (e, ui) {\r\n\t\t\t\t\tif (!helperClassesSet) { // can only add classes after clone has been added to the DOM\r\n\t\t\t\t\t\t//$(\".ui-draggable-dragging\")\r\n\t\t\t\t\t\tui.helper\r\n\t\t\t\t\t\t\t.addClass( helperClass +\" \"+ helperPaneClass ) // add helper classes\r\n\t\t\t\t\t\t\t.css({ right: \"auto\", bottom: \"auto\" })\t// fix dir=\"rtl\" issue\r\n\t\t\t\t\t\t\t.children().css(\"visibility\",\"hidden\")\t// hide toggler inside dragged resizer-bar\r\n\t\t\t\t\t\t;\r\n\t\t\t\t\t\thelperClassesSet = true;\r\n\t\t\t\t\t\t// draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane!\r\n\t\t\t\t\t\tif (s.isSliding) $Ps[pane].css(\"zIndex\", z.pane_sliding);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// CONTAIN RESIZER-BAR TO RESIZING LIMITS\r\n\t\t\t\t\tvar limit = 0;\r\n\t\t\t\t\tif (ui.position[side] < r.min) {\r\n\t\t\t\t\t\tui.position[side] = r.min;\r\n\t\t\t\t\t\tlimit = -1;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if (ui.position[side] > r.max) {\r\n\t\t\t\t\t\tui.position[side] = r.max;\r\n\t\t\t\t\t\tlimit = 1;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// ADD/REMOVE dragging-limit CLASS\r\n\t\t\t\t\tif (limit) {\r\n\t\t\t\t\t\tui.helper.addClass( helperLimitClass +\" \"+ helperPaneLimitClass ); // at dragging-limit\r\n\t\t\t\t\t\twindow.defaultStatus = (limit>0 && pane.match(/(north|west)/)) || (limit<0 && pane.match(/(south|east)/)) ? o.tips.maxSizeWarning : o.tips.minSizeWarning;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tui.helper.removeClass( helperLimitClass +\" \"+ helperPaneLimitClass ); // not at dragging-limit\r\n\t\t\t\t\t\twindow.defaultStatus = \"\";\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// DYNAMICALLY RESIZE PANES IF OPTION ENABLED\r\n\t\t\t\t\t// won't trigger unless resizer has actually moved!\r\n\t\t\t\t\tif (live && Math.abs(ui.position[side] - lastPos) >= o.liveResizingTolerance) {\r\n\t\t\t\t\t\tlastPos = ui.position[side];\r\n\t\t\t\t\t\tresizePanes(e, ui, pane)\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t,\tstop: function (e, ui) {\r\n\t\t\t\t\t$('body').enableSelection(); // RE-ENABLE TEXT SELECTION\r\n\t\t\t\t\twindow.defaultStatus = \"\"; // clear 'resizing limit' message from statusbar\r\n\t\t\t\t\t$R.removeClass( resizerClass +\" \"+ resizerPaneClass ); // remove drag classes from Resizer\r\n\t\t\t\t\ts.isResizing\t\t= false;\r\n\t\t\t\t\tstate.paneResizing\t= false; // easy to see if ANY pane is resizing\r\n\t\t\t\t\tresizePanes(e, ui, pane, true); // true = resizingDone\r\n\t\t\t\t}\r\n\r\n\t\t\t});\r\n\t\t});\r\n\r\n\t\t/**\r\n\t\t* resizePanes\r\n\t\t*\r\n\t\t* Sub-routine called from stop() - and drag() if livePaneResizing\r\n\t\t*\r\n\t\t* @param {!Object}\t\tevt\r\n\t\t* @param {!Object}\t\tui\r\n\t\t* @param {string}\t\tpane\r\n\t\t* @param {boolean=}\t\t[resizingDone=false]\r\n\t\t*/\r\n\t\tvar resizePanes = function (evt, ui, pane, resizingDone) {\r\n\t\t\tvar\tdragPos\t= ui.position\r\n\t\t\t,\tc\t\t= _c[pane]\r\n\t\t\t,\to\t\t= options[pane]\r\n\t\t\t,\ts\t\t= state[pane]\r\n\t\t\t,\tresizerPos\r\n\t\t\t;\r\n\t\t\tswitch (pane) {\r\n\t\t\t\tcase \"north\":\tresizerPos = dragPos.top; break;\r\n\t\t\t\tcase \"west\":\tresizerPos = dragPos.left; break;\r\n\t\t\t\tcase \"south\":\tresizerPos = sC.layoutHeight - dragPos.top  - o.spacing_open; break;\r\n\t\t\t\tcase \"east\":\tresizerPos = sC.layoutWidth  - dragPos.left - o.spacing_open; break;\r\n\t\t\t};\r\n\t\t\t// remove container margin from resizer position to get the pane size\r\n\t\t\tvar newSize = resizerPos - sC.inset[c.side];\r\n\r\n\t\t\t// Disable OR Resize Mask(s) created in drag.start\r\n\t\t\tif (!resizingDone) {\r\n\t\t\t\t// ensure we meet liveResizingTolerance criteria\r\n\t\t\t\tif (Math.abs(newSize - s.size) < o.liveResizingTolerance)\r\n\t\t\t\t\treturn; // SKIP resize this time\r\n\t\t\t\t// resize the pane\r\n\t\t\t\tmanualSizePane(pane, newSize, false, true); // true = noAnimation\r\n\t\t\t\tsizeMasks(); // resize all visible masks\r\n\t\t\t}\r\n\t\t\telse { // resizingDone\r\n\t\t\t\t// ondrag_end callback\r\n\t\t\t\tif (false !== _runCallbacks(\"ondrag_end\", pane))\r\n\t\t\t\t\tmanualSizePane(pane, newSize, false, true); // true = noAnimation\r\n\t\t\t\thideMasks(true); // true = force hiding all masks even if one is 'sliding'\r\n\t\t\t\tif (s.isSliding) // RE-SHOW 'object-masks' so objects won't show through sliding pane\r\n\t\t\t\t\tshowMasks( pane, { resizing: true });\r\n\t\t\t}\r\n\t\t};\r\n\t}\r\n\r\n\t/**\r\n\t*\tsizeMask\r\n\t*\r\n\t*\tNeeded to overlay a DIV over an IFRAME-pane because mask CANNOT be *inside* the pane\r\n\t*\tCalled when mask created, and during livePaneResizing\r\n\t*/\r\n,\tsizeMask = function () {\r\n\t\tvar $M\t\t= $(this)\r\n\t\t,\tpane\t= $M.data(\"layoutMask\") // eg: \"west\"\r\n\t\t,\ts\t\t= state[pane]\r\n\t\t;\r\n\t\t// only masks over an IFRAME-pane need manual resizing\r\n\t\tif (s.tagName == \"IFRAME\" && s.isVisible) // no need to mask closed/hidden panes\r\n\t\t\t$M.css({\r\n\t\t\t\ttop:\ts.offsetTop\r\n\t\t\t,\tleft:\ts.offsetLeft\r\n\t\t\t,\twidth:\ts.outerWidth\r\n\t\t\t,\theight:\ts.outerHeight\r\n\t\t\t});\r\n\t\t/* ALT Method...\r\n\t\tvar $P = $Ps[pane];\r\n\t\t$M.css( $P.position() ).css({ width: $P[0].offsetWidth, height: $P[0].offsetHeight });\r\n\t\t*/\r\n\t}\r\n,\tsizeMasks = function () {\r\n\t\t$Ms.each( sizeMask ); // resize all 'visible' masks\r\n\t}\r\n\r\n\t/**\r\n\t* @param {string}\tpane\t\tThe pane being resized, animated or isSliding\r\n\t* @param {Object=}\t[args]\t\t(optional) Options: which masks to apply, and to which panes\r\n\t*/\r\n,\tshowMasks = function (pane, args) {\r\n\t\tvar\tc\t\t= _c[pane]\r\n\t\t,\tpanes\t=  [\"center\"]\r\n\t\t,\tz\t\t= options.zIndexes\r\n\t\t,\ta\t\t= $.extend({\r\n\t\t\t\t\t\tobjectsOnly:\tfalse\r\n\t\t\t\t\t,\tanimation:\t\tfalse\r\n\t\t\t\t\t,\tresizing:\t\ttrue\r\n\t\t\t\t\t,\tsliding:\t\tstate[pane].isSliding\r\n\t\t\t\t\t},\targs )\r\n\t\t,\to, s\r\n\t\t;\r\n\t\tif (a.resizing)\r\n\t\t\tpanes.push( pane );\r\n\t\tif (a.sliding)\r\n\t\t\tpanes.push( _c.oppositeEdge[pane] ); // ADD the oppositeEdge-pane\r\n\r\n\t\tif (c.dir === \"horz\") {\r\n\t\t\tpanes.push(\"west\");\r\n\t\t\tpanes.push(\"east\");\r\n\t\t}\r\n\r\n\t\t$.each(panes, function(i,p){\r\n\t\t\ts = state[p];\r\n\t\t\to = options[p];\r\n\t\t\tif (s.isVisible && ( o.maskObjects || (!a.objectsOnly && o.maskContents) )) {\r\n\t\t\t\tgetMasks(p).each(function(){\r\n\t\t\t\t\tsizeMask.call(this);\r\n\t\t\t\t\tthis.style.zIndex = s.isSliding ? z.pane_sliding+1 : z.pane_normal+1\r\n\t\t\t\t\tthis.style.display = \"block\";\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t* @param {boolean=}\tforce\t\tHide masks even if a pane is sliding\r\n\t*/\r\n,\thideMasks = function (force) {\r\n\t\t// ensure no pane is resizing - could be a timing issue\r\n\t\tif (force || !state.paneResizing) {\r\n\t\t\t$Ms.hide(); // hide ALL masks\r\n\t\t}\r\n\t\t// if ANY pane is sliding, then DO NOT remove masks from panes with maskObjects enabled\r\n\t\telse if (!force && !$.isEmptyObject( state.panesSliding )) {\r\n\t\t\tvar\ti = $Ms.length - 1\r\n\t\t\t,\tp, $M;\r\n\t\t\tfor (; i >= 0; i--) {\r\n\t\t\t\t$M\t= $Ms.eq(i);\r\n\t\t\t\tp\t= $M.data(\"layoutMask\");\r\n\t\t\t\tif (!options[p].maskObjects) {\r\n\t\t\t\t\t$M.hide();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t* @param {string}\tpane\r\n\t*/\r\n,\tgetMasks = function (pane) {\r\n\t\tvar $Masks\t= $([])\r\n\t\t,\t$M, i = 0, c = $Ms.length\r\n\t\t;\r\n\t\tfor (; i<c; i++) {\r\n\t\t\t$M = $Ms.eq(i);\r\n\t\t\tif ($M.data(\"layoutMask\") === pane)\r\n\t\t\t\t$Masks = $Masks.add( $M );\r\n\t\t}\r\n\t\tif ($Masks.length)\r\n\t\t\treturn $Masks;\r\n\t\telse\r\n\t\t\treturn createMasks(pane);\r\n\t}\r\n\r\n\t/**\r\n\t* createMasks\r\n\t*\r\n\t* Generates both DIV (ALWAYS used) and IFRAME (optional) elements as masks\r\n\t* An IFRAME mask is created *under* the DIV when maskObjects=true, because a DIV cannot mask an applet\r\n\t*\r\n\t* @param {string}\tpane\r\n\t*/\r\n,\tcreateMasks = function (pane) {\r\n\t\tvar\r\n\t\t\t$P\t\t= $Ps[pane]\r\n\t\t,\ts\t\t= state[pane]\r\n\t\t,\to\t\t= options[pane]\r\n\t\t,\tz\t\t= options.zIndexes\r\n\t\t//,\tobjMask\t= o.maskObjects && s.tagName != \"IFRAME\" // check for option\r\n\t\t,\t$Masks\t= $([])\r\n\t\t,\tisIframe, el, $M, css, i\r\n\t\t;\r\n\t\tif (!o.maskContents && !o.maskObjects) return $Masks;\r\n\t\t// if o.maskObjects=true, then loop TWICE to create BOTH kinds of mask, else only create a DIV\r\n\t\tfor (i=0; i < (o.maskObjects ? 2 : 1); i++) {\r\n\t\t\tisIframe = o.maskObjects && i==0;\r\n\t\t\tel = document.createElement( isIframe ? \"iframe\" : \"div\" );\r\n\t\t\t$M = $(el).data(\"layoutMask\", pane); // add data to relate mask to pane\r\n\t\t\tel.className = \"ui-layout-mask ui-layout-mask-\"+ pane; // for user styling\r\n\t\t\tcss = el.style;\r\n\t\t\t// styles common to both DIVs and IFRAMES\r\n\t\t\tcss.display\t\t= \"block\";\r\n\t\t\tcss.position\t= \"absolute\";\r\n\t\t\tcss.background\t= \"#FFF\";\r\n\t\t\tif (isIframe) { // IFRAME-only props\r\n\t\t\t\tel.frameborder = 0;\r\n\t\t\t\tel.src\t\t= \"about:blank\";\r\n\t\t\t\t//el.allowTransparency = true; - for IE, but breaks masking ability!\r\n\t\t\t\tcss.opacity\t= 0;\r\n\t\t\t\tcss.filter\t= \"Alpha(Opacity='0')\";\r\n\t\t\t\tcss.border\t= 0;\r\n\t\t\t}\r\n\t\t\t// if pane is an IFRAME, then must mask the pane itself\r\n\t\t\tif (s.tagName == \"IFRAME\") {\r\n\t\t\t\t// NOTE sizing done by a subroutine so can be called during live-resizing\r\n\t\t\t\tcss.zIndex\t= z.pane_normal+1; // 1-higher than pane\r\n\t\t\t\t$N.append( el ); // append to LAYOUT CONTAINER\r\n\t\t\t}\r\n\t\t\t// otherwise put masks *inside the pane* to mask its contents\r\n\t\t\telse {\r\n\t\t\t\t$M.addClass(\"ui-layout-mask-inside-pane\");\r\n\t\t\t\tcss.zIndex\t= o.maskZindex || z.content_mask; // usually 1, but customizable\r\n\t\t\t\tcss.top\t\t= 0;\r\n\t\t\t\tcss.left\t= 0;\r\n\t\t\t\tcss.width\t= \"100%\";\r\n\t\t\t\tcss.height\t= \"100%\";\r\n\t\t\t\t$P.append( el ); // append INSIDE pane element\r\n\t\t\t}\r\n\t\t\t// add to return object\r\n\t\t\t$Masks = $Masks.add( el );\r\n\t\t\t// add Mask to cached array so can be resized & reused\r\n\t\t\t$Ms = $Ms.add( el );\r\n\t\t}\r\n\t\treturn $Masks;\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* Destroy this layout and reset all elements\r\n\t*\r\n\t* @param {boolean=}\t[destroyChildren=false]\t\tDestory Child-Layouts first?\r\n\t*/\r\n,\tdestroy = function (evt_or_destroyChildren, destroyChildren) {\r\n\t\t// UNBIND layout events and remove global object\r\n\t\t$(window).unbind(\".\"+ sID);\t\t// resize & unload\r\n\t\t$(document).unbind(\".\"+ sID);\t// keyDown (hotkeys)\r\n\r\n\t\tif (typeof evt_or_destroyChildren === \"object\")\r\n\t\t\t// stopPropagation if called by trigger(\"layoutdestroy\") - use evtPane utility \r\n\t\t\tevtPane(evt_or_destroyChildren);\r\n\t\telse // no event, so transfer 1st param to destroyChildren param\r\n\t\t\tdestroyChildren = evt_or_destroyChildren;\r\n\r\n\t\t// need to look for parent layout BEFORE we remove the container data, else skips a level\r\n\t\t//var parentPane = Instance.hasParentLayout ? $.layout.getParentPaneInstance( $N ) : null;\r\n\r\n\t\t// reset layout-container\r\n\t\t$N\t.clearQueue()\r\n\t\t\t.removeData(\"layout\")\r\n\t\t\t.removeData(\"layoutContainer\")\r\n\t\t\t.removeClass(options.containerClass)\r\n\t\t\t.unbind(\".\"+ sID) // remove ALL Layout events\r\n\t\t;\r\n\r\n\t\t// remove all mask elements that have been created\r\n\t\t$Ms.remove();\r\n\r\n\t\t// loop all panes to remove layout classes, attributes and bindings\r\n\t\t$.each(_c.allPanes, function (i, pane) {\r\n\t\t\tremovePane( pane, false, true, destroyChildren ); // true = skipResize\r\n\t\t});\r\n\r\n\t\t// do NOT reset container CSS if is a 'pane' (or 'content') in an outer-layout - ie, THIS layout is 'nested'\r\n\t\tvar css = \"layoutCSS\";\r\n\t\tif ($N.data(css) && !$N.data(\"layoutRole\")) // RESET CSS\r\n\t\t\t$N.css( $N.data(css) ).removeData(css);\r\n\r\n\t\t// for full-page layouts, also reset the <HTML> CSS\r\n\t\tif (sC.tagName === \"BODY\" && ($N = $(\"html\")).data(css)) // RESET <HTML> CSS\r\n\t\t\t$N.css( $N.data(css) ).removeData(css);\r\n\r\n\t\t// trigger plugins for this layout, if there are any\r\n\t\trunPluginCallbacks( Instance, $.layout.onDestroy );\r\n\r\n\t\t// trigger state-management and onunload callback\r\n\t\tunload();\r\n\r\n\t\t// clear the Instance of everything except for container & options (so could recreate)\r\n\t\t// RE-CREATE: myLayout = myLayout.container.layout( myLayout.options );\r\n\t\tfor (var n in Instance)\r\n\t\t\tif (!n.match(/^(container|options)$/)) delete Instance[ n ];\r\n\t\t// add a 'destroyed' flag to make it easy to check\r\n\t\tInstance.destroyed = true;\r\n\r\n\t\t// if this is a child layout, CLEAR the child-pointer in the parent\r\n\t\t/* for now the pointer REMAINS, but with only container, options and destroyed keys\r\n\t\tif (parentPane) {\r\n\t\t\tvar layout\t= parentPane.pane.data(\"parentLayout\")\r\n\t\t\t,\tkey\t\t= layout.options.instanceKey || 'error';\r\n\t\t\t// THIS SYNTAX MAY BE WRONG!\r\n\t\t\tparentPane.children[key] = layout.children[ parentPane.name ].children[key] = null;\r\n\t\t}\r\n\t\t*/\r\n\r\n\t\treturn Instance; // for coding convenience\r\n\t}\r\n\r\n\t/**\r\n\t* Remove a pane from the layout - subroutine of destroy()\r\n\t*\r\n\t* @see  destroy()\r\n\t* @param {(string|Object)}\tevt_or_pane\t\t\tThe pane to process\r\n\t* @param {boolean=}\t\t\t[remove=false]\t\tRemove the DOM element?\r\n\t* @param {boolean=}\t\t\t[skipResize=false]\tSkip calling resizeAll()?\r\n\t* @param {boolean=}\t\t\t[destroyChild=true]\tDestroy Child-layouts? If not passed, obeys options setting\r\n\t*/\r\n,\tremovePane = function (evt_or_pane, remove, skipResize, destroyChild) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane)\r\n\t\t,\t$P\t= $Ps[pane]\r\n\t\t,\t$C\t= $Cs[pane]\r\n\t\t,\t$R\t= $Rs[pane]\r\n\t\t,\t$T\t= $Ts[pane]\r\n\t\t;\r\n\t\t// NOTE: elements can still exist even after remove()\r\n\t\t//\t\tso check for missing data(), which is cleared by removed()\r\n\t\tif ($P && $.isEmptyObject( $P.data() )) $P = false;\r\n\t\tif ($C && $.isEmptyObject( $C.data() )) $C = false;\r\n\t\tif ($R && $.isEmptyObject( $R.data() )) $R = false;\r\n\t\tif ($T && $.isEmptyObject( $T.data() )) $T = false;\r\n\r\n\t\tif ($P) $P.stop(true, true);\r\n\r\n\t\tvar\to\t= options[pane]\r\n\t\t,\ts\t= state[pane]\r\n\t\t,\td\t= \"layout\"\r\n\t\t,\tcss\t= \"layoutCSS\"\r\n\t\t,\tpC\t= children[pane]\r\n\t\t,\thasChildren\t= $.isPlainObject( pC ) && !$.isEmptyObject( pC )\r\n\t\t,\tdestroy\t\t= destroyChild !== undefined ? destroyChild : o.destroyChildren\r\n\t\t;\r\n\t\t// FIRST destroy the child-layout(s)\r\n\t\tif (hasChildren && destroy) {\r\n\t\t\t$.each( pC, function (key, child) {\r\n\t\t\t\tif (!child.destroyed)\r\n\t\t\t\t\tchild.destroy(true);// tell child-layout to destroy ALL its child-layouts too\r\n\t\t\t\tif (child.destroyed)\t// destroy was successful\r\n\t\t\t\t\tdelete pC[key];\r\n\t\t\t});\r\n\t\t\t// if no more children, remove the children hash\r\n\t\t\tif ($.isEmptyObject( pC )) {\r\n\t\t\t\tpC = children[pane] = null; // clear children hash\r\n\t\t\t\thasChildren = false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Note: can't 'remove' a pane element with non-destroyed children\r\n\t\tif ($P && remove && !hasChildren)\r\n\t\t\t$P.remove(); // remove the pane-element and everything inside it\r\n\t\telse if ($P && $P[0]) {\r\n\t\t\t//\tcreate list of ALL pane-classes that need to be removed\r\n\t\t\tvar\troot\t= o.paneClass // default=\"ui-layout-pane\"\r\n\t\t\t,\tpRoot\t= root +\"-\"+ pane // eg: \"ui-layout-pane-west\"\r\n\t\t\t,\t_open\t= \"-open\"\r\n\t\t\t,\t_sliding= \"-sliding\"\r\n\t\t\t,\t_closed\t= \"-closed\"\r\n\t\t\t,\tclasses\t= [\troot, root+_open, root+_closed, root+_sliding,\t\t// generic classes\r\n\t\t\t\t\t\t\tpRoot, pRoot+_open, pRoot+_closed, pRoot+_sliding ]\t// pane-specific classes\r\n\t\t\t;\r\n\t\t\t$.merge(classes, getHoverClasses($P, true)); // ADD hover-classes\r\n\t\t\t// remove all Layout classes from pane-element\r\n\t\t\t$P\t.removeClass( classes.join(\" \") ) // remove ALL pane-classes\r\n\t\t\t\t.removeData(\"parentLayout\")\r\n\t\t\t\t.removeData(\"layoutPane\")\r\n\t\t\t\t.removeData(\"layoutRole\")\r\n\t\t\t\t.removeData(\"layoutEdge\")\r\n\t\t\t\t.removeData(\"autoHidden\")\t// in case set\r\n\t\t\t\t.unbind(\".\"+ sID) // remove ALL Layout events\r\n\t\t\t\t// TODO: remove these extra unbind commands when jQuery is fixed\r\n\t\t\t\t//.unbind(\"mouseenter\"+ sID)\r\n\t\t\t\t//.unbind(\"mouseleave\"+ sID)\r\n\t\t\t;\r\n\t\t\t// do NOT reset CSS if this pane/content is STILL the container of a nested layout!\r\n\t\t\t// the nested layout will reset its 'container' CSS when/if it is destroyed\r\n\t\t\tif (hasChildren && $C) {\r\n\t\t\t\t// a content-div may not have a specific width, so give it one to contain the Layout\r\n\t\t\t\t$C.width( $C.width() );\r\n\t\t\t\t$.each( pC, function (key, child) {\r\n\t\t\t\t\tchild.resizeAll(); // resize the Layout\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t\telse if ($C)\r\n\t\t\t\t$C.css( $C.data(css) ).removeData(css).removeData(\"layoutRole\");\r\n\t\t\t// remove pane AFTER content in case there was a nested layout\r\n\t\t\tif (!$P.data(d))\r\n\t\t\t\t$P.css( $P.data(css) ).removeData(css);\r\n\t\t}\r\n\r\n\t\t// REMOVE pane resizer and toggler elements\r\n\t\tif ($T) $T.remove();\r\n\t\tif ($R) $R.remove();\r\n\r\n\t\t// CLEAR all pointers and state data\r\n\t\tInstance[pane] = $Ps[pane] = $Cs[pane] = $Rs[pane] = $Ts[pane] = false;\r\n\t\ts = { removed: true };\r\n\r\n\t\tif (!skipResize)\r\n\t\t\tresizeAll();\r\n\t}\r\n\r\n\r\n/*\r\n * ###########################\r\n *\t   ACTION METHODS\r\n * ###########################\r\n */\r\n\r\n\t/**\r\n\t* @param {string}\tpane\r\n\t*/\r\n,\t_hidePane = function (pane) {\r\n\t\tvar $P\t= $Ps[pane]\r\n\t\t,\to\t= options[pane]\r\n\t\t,\ts\t= $P[0].style\r\n\t\t;\r\n\t\tif (o.useOffscreenClose) {\r\n\t\t\tif (!$P.data(_c.offscreenReset))\r\n\t\t\t\t$P.data(_c.offscreenReset, { left: s.left, right: s.right });\r\n\t\t\t$P.css( _c.offscreenCSS );\r\n\t\t}\r\n\t\telse\r\n\t\t\t$P.hide().removeData(_c.offscreenReset);\r\n\t}\r\n\r\n\t/**\r\n\t* @param {string}\tpane\r\n\t*/\r\n,\t_showPane = function (pane) {\r\n\t\tvar $P\t= $Ps[pane]\r\n\t\t,\to\t= options[pane]\r\n\t\t,\toff\t= _c.offscreenCSS\r\n\t\t,\told\t= $P.data(_c.offscreenReset)\r\n\t\t,\ts\t= $P[0].style\r\n\t\t;\r\n\t\t$P\t.show() // ALWAYS show, just in case\r\n\t\t\t.removeData(_c.offscreenReset);\r\n\t\tif (o.useOffscreenClose && old) {\r\n\t\t\tif (s.left == off.left)\r\n\t\t\t\ts.left = old.left;\r\n\t\t\tif (s.right == off.right)\r\n\t\t\t\ts.right = old.right;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* Completely 'hides' a pane, including its spacing - as if it does not exist\r\n\t* The pane is not actually 'removed' from the source, so can use 'show' to un-hide it\r\n\t*\r\n\t* @param {(string|Object)}\tevt_or_pane\t\t\tThe pane being hidden, ie: north, south, east, or west\r\n\t* @param {boolean=}\t\t\t[noAnimation=false]\t\r\n\t*/\r\n,\thide = function (evt_or_pane, noAnimation) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane)\r\n\t\t,\to\t= options[pane]\r\n\t\t,\ts\t= state[pane]\r\n\t\t,\t$P\t= $Ps[pane]\r\n\t\t,\t$R\t= $Rs[pane]\r\n\t\t;\r\n\t\tif (!$P || s.isHidden) return; // pane does not exist OR is already hidden\r\n\r\n\t\t// onhide_start callback - will CANCEL hide if returns false\r\n\t\tif (state.initialized && false === _runCallbacks(\"onhide_start\", pane)) return;\r\n\r\n\t\ts.isSliding = false; // just in case\r\n\t\tdelete state.panesSliding[pane];\r\n\r\n\t\t// now hide the elements\r\n\t\tif ($R) $R.hide(); // hide resizer-bar\r\n\t\tif (!state.initialized || s.isClosed) {\r\n\t\t\ts.isClosed = true; // to trigger open-animation on show()\r\n\t\t\ts.isHidden  = true;\r\n\t\t\ts.isVisible = false;\r\n\t\t\tif (!state.initialized)\r\n\t\t\t\t_hidePane(pane); // no animation when loading page\r\n\t\t\tsizeMidPanes(_c[pane].dir === \"horz\" ? \"\" : \"center\");\r\n\t\t\tif (state.initialized || o.triggerEventsOnLoad)\r\n\t\t\t\t_runCallbacks(\"onhide_end\", pane);\r\n\t\t}\r\n\t\telse {\r\n\t\t\ts.isHiding = true; // used by onclose\r\n\t\t\tclose(pane, false, noAnimation); // adjust all panes to fit\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t* Show a hidden pane - show as 'closed' by default unless openPane = true\r\n\t*\r\n\t* @param {(string|Object)}\tevt_or_pane\t\t\tThe pane being opened, ie: north, south, east, or west\r\n\t* @param {boolean=}\t\t\t[openPane=false]\r\n\t* @param {boolean=}\t\t\t[noAnimation=false]\r\n\t* @param {boolean=}\t\t\t[noAlert=false]\r\n\t*/\r\n,\tshow = function (evt_or_pane, openPane, noAnimation, noAlert) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane)\r\n\t\t,\to\t= options[pane]\r\n\t\t,\ts\t= state[pane]\r\n\t\t,\t$P\t= $Ps[pane]\r\n\t\t,\t$R\t= $Rs[pane]\r\n\t\t;\r\n\t\tif (!$P || !s.isHidden) return; // pane does not exist OR is not hidden\r\n\r\n\t\t// onshow_start callback - will CANCEL show if returns false\r\n\t\tif (false === _runCallbacks(\"onshow_start\", pane)) return;\r\n\r\n\t\ts.isShowing = true; // used by onopen/onclose\r\n\t\t//s.isHidden  = false; - will be set by open/close - if not cancelled\r\n\t\ts.isSliding = false; // just in case\r\n\t\tdelete state.panesSliding[pane];\r\n\r\n\t\t// now show the elements\r\n\t\t//if ($R) $R.show(); - will be shown by open/close\r\n\t\tif (openPane === false)\r\n\t\t\tclose(pane, true); // true = force\r\n\t\telse\r\n\t\t\topen(pane, false, noAnimation, noAlert); // adjust all panes to fit\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* Toggles a pane open/closed by calling either open or close\r\n\t*\r\n\t* @param {(string|Object)}\tevt_or_pane\t\tThe pane being toggled, ie: north, south, east, or west\r\n\t* @param {boolean=}\t\t\t[slide=false]\r\n\t*/\r\n,\ttoggle = function (evt_or_pane, slide) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tevt\t\t= evtObj(evt_or_pane)\r\n\t\t,\tpane\t= evtPane.call(this, evt_or_pane)\r\n\t\t,\ts\t\t= state[pane]\r\n\t\t;\r\n\t\tif (evt) // called from to $R.dblclick OR triggerPaneEvent\r\n\t\t\tevt.stopImmediatePropagation();\r\n\t\tif (s.isHidden)\r\n\t\t\tshow(pane); // will call 'open' after unhiding it\r\n\t\telse if (s.isClosed)\r\n\t\t\topen(pane, !!slide);\r\n\t\telse\r\n\t\t\tclose(pane);\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* Utility method used during init or other auto-processes\r\n\t*\r\n\t* @param {string}\tpane   The pane being closed\r\n\t* @param {boolean=}\t[setHandles=false]\r\n\t*/\r\n,\t_closePane = function (pane, setHandles) {\r\n\t\tvar\r\n\t\t\t$P\t= $Ps[pane]\r\n\t\t,\ts\t= state[pane]\r\n\t\t;\r\n\t\t_hidePane(pane);\r\n\t\ts.isClosed = true;\r\n\t\ts.isVisible = false;\r\n\t\tif (setHandles) setAsClosed(pane);\r\n\t}\r\n\r\n\t/**\r\n\t* Close the specified pane (animation optional), and resize all other panes as needed\r\n\t*\r\n\t* @param {(string|Object)}\tevt_or_pane\t\t\tThe pane being closed, ie: north, south, east, or west\r\n\t* @param {boolean=}\t\t\t[force=false]\r\n\t* @param {boolean=}\t\t\t[noAnimation=false]\r\n\t* @param {boolean=}\t\t\t[skipCallback=false]\r\n\t*/\r\n,\tclose = function (evt_or_pane, force, noAnimation, skipCallback) {\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane);\r\n\t\t// if pane has been initialized, but NOT the complete layout, close pane instantly\r\n\t\tif (!state.initialized && $Ps[pane]) {\r\n\t\t\t_closePane(pane, true); // INIT pane as closed\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (!isInitialized()) return;\r\n\r\n\t\tvar\r\n\t\t\t$P\t= $Ps[pane]\r\n\t\t,\t$R\t= $Rs[pane]\r\n\t\t,\t$T\t= $Ts[pane]\r\n\t\t,\to\t= options[pane]\r\n\t\t,\ts\t= state[pane]\r\n\t\t,\tc\t= _c[pane]\r\n\t\t,\tdoFX, isShowing, isHiding, wasSliding;\r\n\r\n\t\t// QUEUE in case another action/animation is in progress\r\n\t\t$N.queue(function( queueNext ){\r\n\r\n\t\t\tif ( !$P\r\n\t\t\t||\t(!o.closable && !s.isShowing && !s.isHiding)\t// invalid request // (!o.resizable && !o.closable) ???\r\n\t\t\t||\t(!force && s.isClosed && !s.isShowing)\t\t\t// already closed\r\n\t\t\t) return queueNext();\r\n\r\n\t\t\t// onclose_start callback - will CANCEL hide if returns false\r\n\t\t\t// SKIP if just 'showing' a hidden pane as 'closed'\r\n\t\t\tvar abort = !s.isShowing && false === _runCallbacks(\"onclose_start\", pane);\r\n\r\n\t\t\t// transfer logic vars to temp vars\r\n\t\t\tisShowing\t= s.isShowing;\r\n\t\t\tisHiding\t= s.isHiding;\r\n\t\t\twasSliding\t= s.isSliding;\r\n\t\t\t// now clear the logic vars (REQUIRED before aborting)\r\n\t\t\tdelete s.isShowing;\r\n\t\t\tdelete s.isHiding;\r\n\r\n\t\t\tif (abort) return queueNext();\r\n\r\n\t\t\tdoFX\t\t= !noAnimation && !s.isClosed && (o.fxName_close != \"none\");\r\n\t\t\ts.isMoving\t= true;\r\n\t\t\ts.isClosed\t= true;\r\n\t\t\ts.isVisible\t= false;\r\n\t\t\t// update isHidden BEFORE sizing panes\r\n\t\t\tif (isHiding) s.isHidden = true;\r\n\t\t\telse if (isShowing) s.isHidden = false;\r\n\r\n\t\t\tif (s.isSliding) // pane is being closed, so UNBIND trigger events\r\n\t\t\t\tbindStopSlidingEvents(pane, false); // will set isSliding=false\r\n\t\t\telse // resize panes adjacent to this one\r\n\t\t\t\tsizeMidPanes(_c[pane].dir === \"horz\" ? \"\" : \"center\", false); // false = NOT skipCallback\r\n\r\n\t\t\t// if this pane has a resizer bar, move it NOW - before animation\r\n\t\t\tsetAsClosed(pane);\r\n\r\n\t\t\t// CLOSE THE PANE\r\n\t\t\tif (doFX) { // animate the close\r\n\t\t\t\tlockPaneForFX(pane, true);\t// need to set left/top so animation will work\r\n\t\t\t\t$P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () {\r\n\t\t\t\t\tlockPaneForFX(pane, false); // undo\r\n\t\t\t\t\tif (s.isClosed) close_2();\r\n\t\t\t\t\tqueueNext();\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t\telse { // hide the pane without animation\r\n\t\t\t\t_hidePane(pane);\r\n\t\t\t\tclose_2();\r\n\t\t\t\tqueueNext();\r\n\t\t\t};\r\n\t\t});\r\n\r\n\t\t// SUBROUTINE\r\n\t\tfunction close_2 () {\r\n\t\t\ts.isMoving\t= false;\r\n\t\t\tbindStartSlidingEvents(pane, true); // will enable if o.slidable = true\r\n\r\n\t\t\t// if opposite-pane was autoClosed, see if it can be autoOpened now\r\n\t\t\tvar altPane = _c.oppositeEdge[pane];\r\n\t\t\tif (state[ altPane ].noRoom) {\r\n\t\t\t\tsetSizeLimits( altPane );\r\n\t\t\t\tmakePaneFit( altPane );\r\n\t\t\t}\r\n\r\n\t\t\tif (!skipCallback && (state.initialized || o.triggerEventsOnLoad)) {\r\n\t\t\t\t// onclose callback - UNLESS just 'showing' a hidden pane as 'closed'\r\n\t\t\t\tif (!isShowing)\t_runCallbacks(\"onclose_end\", pane);\r\n\t\t\t\t// onhide OR onshow callback\r\n\t\t\t\tif (isShowing)\t_runCallbacks(\"onshow_end\", pane);\r\n\t\t\t\tif (isHiding)\t_runCallbacks(\"onhide_end\", pane);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t* @param {string}\tpane\tThe pane just closed, ie: north, south, east, or west\r\n\t*/\r\n,\tsetAsClosed = function (pane) {\r\n\t\tif (!$Rs[pane]) return; // handles not initialized yet!\r\n\t\tvar\r\n\t\t\t$P\t\t= $Ps[pane]\r\n\t\t,\t$R\t\t= $Rs[pane]\r\n\t\t,\t$T\t\t= $Ts[pane]\r\n\t\t,\to\t\t= options[pane]\r\n\t\t,\ts\t\t= state[pane]\r\n\t\t,\tside\t= _c[pane].side\r\n\t\t,\trClass\t= o.resizerClass\r\n\t\t,\ttClass\t= o.togglerClass\r\n\t\t,\t_pane\t= \"-\"+ pane // used for classNames\r\n\t\t,\t_open\t= \"-open\"\r\n\t\t,\t_sliding= \"-sliding\"\r\n\t\t,\t_closed\t= \"-closed\"\r\n\t\t;\r\n\t\t$R\r\n\t\t\t.css(side, sC.inset[side]) // move the resizer\r\n\t\t\t.removeClass( rClass+_open +\" \"+ rClass+_pane+_open )\r\n\t\t\t.removeClass( rClass+_sliding +\" \"+ rClass+_pane+_sliding )\r\n\t\t\t.addClass( rClass+_closed +\" \"+ rClass+_pane+_closed )\r\n\t\t;\r\n\t\t// DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvents?\r\n\t\tif (o.resizable && $.layout.plugins.draggable)\r\n\t\t\t$R\r\n\t\t\t\t.draggable(\"disable\")\r\n\t\t\t\t.removeClass(\"ui-state-disabled\") // do NOT apply disabled styling - not suitable here\r\n\t\t\t\t.css(\"cursor\", \"default\")\r\n\t\t\t\t.attr(\"title\",\"\")\r\n\t\t\t;\r\n\r\n\t\t// if pane has a toggler button, adjust that too\r\n\t\tif ($T) {\r\n\t\t\t$T\r\n\t\t\t\t.removeClass( tClass+_open +\" \"+ tClass+_pane+_open )\r\n\t\t\t\t.addClass( tClass+_closed +\" \"+ tClass+_pane+_closed )\r\n\t\t\t\t.attr(\"title\", o.tips.Open) // may be blank\r\n\t\t\t;\r\n\t\t\t// toggler-content - if exists\r\n\t\t\t$T.children(\".content-open\").hide();\r\n\t\t\t$T.children(\".content-closed\").css(\"display\",\"block\");\r\n\t\t}\r\n\r\n\t\t// sync any 'pin buttons'\r\n\t\tsyncPinBtns(pane, false);\r\n\r\n\t\tif (state.initialized) {\r\n\t\t\t// resize 'length' and position togglers for adjacent panes\r\n\t\t\tsizeHandles();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t* Open the specified pane (animation optional), and resize all other panes as needed\r\n\t*\r\n\t* @param {(string|Object)}\tevt_or_pane\t\t\tThe pane being opened, ie: north, south, east, or west\r\n\t* @param {boolean=}\t\t\t[slide=false]\r\n\t* @param {boolean=}\t\t\t[noAnimation=false]\r\n\t* @param {boolean=}\t\t\t[noAlert=false]\r\n\t*/\r\n,\topen = function (evt_or_pane, slide, noAnimation, noAlert) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane)\r\n\t\t,\t$P\t= $Ps[pane]\r\n\t\t,\t$R\t= $Rs[pane]\r\n\t\t,\t$T\t= $Ts[pane]\r\n\t\t,\to\t= options[pane]\r\n\t\t,\ts\t= state[pane]\r\n\t\t,\tc\t= _c[pane]\r\n\t\t,\tdoFX, isShowing\r\n\t\t;\r\n\t\t// QUEUE in case another action/animation is in progress\r\n\t\t$N.queue(function( queueNext ){\r\n\r\n\t\t\tif ( !$P\r\n\t\t\t||\t(!o.resizable && !o.closable && !s.isShowing)\t// invalid request\r\n\t\t\t||\t(s.isVisible && !s.isSliding)\t\t\t\t\t// already open\r\n\t\t\t) return queueNext();\r\n\r\n\t\t\t// pane can ALSO be unhidden by just calling show(), so handle this scenario\r\n\t\t\tif (s.isHidden && !s.isShowing) {\r\n\t\t\t\tqueueNext(); // call before show() because it needs the queue free\r\n\t\t\t\tshow(pane, true);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tif (s.autoResize && s.size != o.size) // resize pane to original size set in options\r\n\t\t\t\tsizePane(pane, o.size, true, true, true); // true=skipCallback/noAnimation/forceResize\r\n\t\t\telse\r\n\t\t\t\t// make sure there is enough space available to open the pane\r\n\t\t\t\tsetSizeLimits(pane, slide);\r\n\r\n\t\t\t// onopen_start callback - will CANCEL open if returns false\r\n\t\t\tvar cbReturn = _runCallbacks(\"onopen_start\", pane);\r\n\r\n\t\t\tif (cbReturn === \"abort\")\r\n\t\t\t\treturn queueNext();\r\n\r\n\t\t\t// update pane-state again in case options were changed in onopen_start\r\n\t\t\tif (cbReturn !== \"NC\") // NC = \"No Callback\"\r\n\t\t\t\tsetSizeLimits(pane, slide);\r\n\r\n\t\t\tif (s.minSize > s.maxSize) { // INSUFFICIENT ROOM FOR PANE TO OPEN!\r\n\t\t\t\tsyncPinBtns(pane, false); // make sure pin-buttons are reset\r\n\t\t\t\tif (!noAlert && o.tips.noRoomToOpen)\r\n\t\t\t\t\talert(o.tips.noRoomToOpen);\r\n\t\t\t\treturn queueNext(); // ABORT\r\n\t\t\t}\r\n\r\n\t\t\tif (slide) // START Sliding - will set isSliding=true\r\n\t\t\t\tbindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane\r\n\t\t\telse if (s.isSliding) // PIN PANE (stop sliding) - open pane 'normally' instead\r\n\t\t\t\tbindStopSlidingEvents(pane, false); // UNBIND trigger events - will set isSliding=false\r\n\t\t\telse if (o.slidable)\r\n\t\t\t\tbindStartSlidingEvents(pane, false); // UNBIND trigger events\r\n\r\n\t\t\ts.noRoom = false; // will be reset by makePaneFit if 'noRoom'\r\n\t\t\tmakePaneFit(pane);\r\n\r\n\t\t\t// transfer logic var to temp var\r\n\t\t\tisShowing = s.isShowing;\r\n\t\t\t// now clear the logic var\r\n\t\t\tdelete s.isShowing;\r\n\r\n\t\t\tdoFX\t\t= !noAnimation && s.isClosed && (o.fxName_open != \"none\");\r\n\t\t\ts.isMoving\t= true;\r\n\t\t\ts.isVisible\t= true;\r\n\t\t\ts.isClosed\t= false;\r\n\t\t\t// update isHidden BEFORE sizing panes - WHY??? Old?\r\n\t\t\tif (isShowing) s.isHidden = false;\r\n\r\n\t\t\tif (doFX) { // ANIMATE\r\n\t\t\t\t// mask adjacent panes with objects\r\n\t\t\t\tlockPaneForFX(pane, true);\t// need to set left/top so animation will work\r\n\t\t\t\t\t$P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() {\r\n\t\t\t\t\tlockPaneForFX(pane, false); // undo\r\n\t\t\t\t\tif (s.isVisible) open_2(); // continue\r\n\t\t\t\t\tqueueNext();\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t\telse { // no animation\r\n\t\t\t\t_showPane(pane);// just show pane and...\r\n\t\t\t\topen_2();\t\t// continue\r\n\t\t\t\tqueueNext();\r\n\t\t\t};\r\n\t\t});\r\n\r\n\t\t// SUBROUTINE\r\n\t\tfunction open_2 () {\r\n\t\t\ts.isMoving\t= false;\r\n\r\n\t\t\t// cure iframe display issues\r\n\t\t\t_fixIframe(pane);\r\n\r\n\t\t\t// NOTE: if isSliding, then other panes are NOT 'resized'\r\n\t\t\tif (!s.isSliding) { // resize all panes adjacent to this one\r\n\t\t\t\tsizeMidPanes(_c[pane].dir==\"vert\" ? \"center\" : \"\", false); // false = NOT skipCallback\r\n\t\t\t}\r\n\r\n\t\t\t// set classes, position handles and execute callbacks...\r\n\t\t\tsetAsOpen(pane);\r\n\t\t};\r\n\t\r\n\t}\r\n\r\n\t/**\r\n\t* @param {string}\tpane\t\tThe pane just opened, ie: north, south, east, or west\r\n\t* @param {boolean=}\t[skipCallback=false]\r\n\t*/\r\n,\tsetAsOpen = function (pane, skipCallback) {\r\n\t\tvar \r\n\t\t\t$P\t\t= $Ps[pane]\r\n\t\t,\t$R\t\t= $Rs[pane]\r\n\t\t,\t$T\t\t= $Ts[pane]\r\n\t\t,\to\t\t= options[pane]\r\n\t\t,\ts\t\t= state[pane]\r\n\t\t,\tside\t= _c[pane].side\r\n\t\t,\trClass\t= o.resizerClass\r\n\t\t,\ttClass\t= o.togglerClass\r\n\t\t,\t_pane\t= \"-\"+ pane // used for classNames\r\n\t\t,\t_open\t= \"-open\"\r\n\t\t,\t_closed\t= \"-closed\"\r\n\t\t,\t_sliding= \"-sliding\"\r\n\t\t;\r\n\t\t$R\r\n\t\t\t.css(side, sC.inset[side] + getPaneSize(pane)) // move the resizer\r\n\t\t\t.removeClass( rClass+_closed +\" \"+ rClass+_pane+_closed )\r\n\t\t\t.addClass( rClass+_open +\" \"+ rClass+_pane+_open )\r\n\t\t;\r\n\t\tif (s.isSliding)\r\n\t\t\t$R.addClass( rClass+_sliding +\" \"+ rClass+_pane+_sliding )\r\n\t\telse // in case 'was sliding'\r\n\t\t\t$R.removeClass( rClass+_sliding +\" \"+ rClass+_pane+_sliding )\r\n\r\n\t\tremoveHover( 0, $R ); // remove hover classes\r\n\t\tif (o.resizable && $.layout.plugins.draggable)\r\n\t\t\t$R\t.draggable(\"enable\")\r\n\t\t\t\t.css(\"cursor\", o.resizerCursor)\r\n\t\t\t\t.attr(\"title\", o.tips.Resize);\r\n\t\telse if (!s.isSliding)\r\n\t\t\t$R.css(\"cursor\", \"default\"); // n-resize, s-resize, etc\r\n\r\n\t\t// if pane also has a toggler button, adjust that too\r\n\t\tif ($T) {\r\n\t\t\t$T\t.removeClass( tClass+_closed +\" \"+ tClass+_pane+_closed )\r\n\t\t\t\t.addClass( tClass+_open +\" \"+ tClass+_pane+_open )\r\n\t\t\t\t.attr(\"title\", o.tips.Close); // may be blank\r\n\t\t\tremoveHover( 0, $T ); // remove hover classes\r\n\t\t\t// toggler-content - if exists\r\n\t\t\t$T.children(\".content-closed\").hide();\r\n\t\t\t$T.children(\".content-open\").css(\"display\",\"block\");\r\n\t\t}\r\n\r\n\t\t// sync any 'pin buttons'\r\n\t\tsyncPinBtns(pane, !s.isSliding);\r\n\r\n\t\t// update pane-state dimensions - BEFORE resizing content\r\n\t\t$.extend(s, elDims($P));\r\n\r\n\t\tif (state.initialized) {\r\n\t\t\t// resize resizer & toggler sizes for all panes\r\n\t\t\tsizeHandles();\r\n\t\t\t// resize content every time pane opens - to be sure\r\n\t\t\tsizeContent(pane, true); // true = remeasure headers/footers, even if 'pane.isMoving'\r\n\t\t}\r\n\r\n\t\tif (!skipCallback && (state.initialized || o.triggerEventsOnLoad) && $P.is(\":visible\")) {\r\n\t\t\t// onopen callback\r\n\t\t\t_runCallbacks(\"onopen_end\", pane);\r\n\t\t\t// onshow callback - TODO: should this be here?\r\n\t\t\tif (s.isShowing) _runCallbacks(\"onshow_end\", pane);\r\n\r\n\t\t\t// ALSO call onresize because layout-size *may* have changed while pane was closed\r\n\t\t\tif (state.initialized)\r\n\t\t\t\t_runCallbacks(\"onresize_end\", pane);\r\n\t\t}\r\n\r\n\t\t// TODO: Somehow sizePane(\"north\") is being called after this point???\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* slideOpen / slideClose / slideToggle\r\n\t*\r\n\t* Pass-though methods for sliding\r\n\t*/\r\n,\tslideOpen = function (evt_or_pane) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tevt\t\t= evtObj(evt_or_pane)\r\n\t\t,\tpane\t= evtPane.call(this, evt_or_pane)\r\n\t\t,\ts\t\t= state[pane]\r\n\t\t,\tdelay\t= options[pane].slideDelay_open\r\n\t\t;\r\n\t\t// prevent event from triggering on NEW resizer binding created below\r\n\t\tif (evt) evt.stopImmediatePropagation();\r\n\r\n\t\tif (s.isClosed && evt && evt.type === \"mouseenter\" && delay > 0)\r\n\t\t\t// trigger = mouseenter - use a delay\r\n\t\t\ttimer.set(pane+\"_openSlider\", open_NOW, delay);\r\n\t\telse\r\n\t\t\topen_NOW(); // will unbind events if is already open\r\n\r\n\t\t/**\r\n\t\t* SUBROUTINE for timed open\r\n\t\t*/\r\n\t\tfunction open_NOW () {\r\n\t\t\tif (!s.isClosed) // skip if no longer closed!\r\n\t\t\t\tbindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane\r\n\t\t\telse if (!s.isMoving)\r\n\t\t\t\topen(pane, true); // true = slide - open() will handle binding\r\n\t\t};\r\n\t}\r\n\r\n,\tslideClose = function (evt_or_pane) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tevt\t\t= evtObj(evt_or_pane)\r\n\t\t,\tpane\t= evtPane.call(this, evt_or_pane)\r\n\t\t,\to\t\t= options[pane]\r\n\t\t,\ts\t\t= state[pane]\r\n\t\t,\tdelay\t= s.isMoving ? 1000 : 300 // MINIMUM delay - option may override\r\n\t\t;\r\n\t\tif (s.isClosed || s.isResizing)\r\n\t\t\treturn; // skip if already closed OR in process of resizing\r\n\t\telse if (o.slideTrigger_close === \"click\")\r\n\t\t\tclose_NOW(); // close immediately onClick\r\n\t\telse if (o.preventQuickSlideClose && s.isMoving)\r\n\t\t\treturn; // handle Chrome quick-close on slide-open\r\n\t\telse if (o.preventPrematureSlideClose && evt && $.layout.isMouseOverElem(evt, $Ps[pane]))\r\n\t\t\treturn; // handle incorrect mouseleave trigger, like when over a SELECT-list in IE\r\n\t\telse if (evt) // trigger = mouseleave - use a delay\r\n\t\t\t// 1 sec delay if 'opening', else .3 sec\r\n\t\t\ttimer.set(pane+\"_closeSlider\", close_NOW, max(o.slideDelay_close, delay));\r\n\t\telse // called programically\r\n\t\t\tclose_NOW();\r\n\r\n\t\t/**\r\n\t\t* SUBROUTINE for timed close\r\n\t\t*/\r\n\t\tfunction close_NOW () {\r\n\t\t\tif (s.isClosed) // skip 'close' if already closed!\r\n\t\t\t\tbindStopSlidingEvents(pane, false); // UNBIND trigger events - TODO: is this needed here?\r\n\t\t\telse if (!s.isMoving)\r\n\t\t\t\tclose(pane); // close will handle unbinding\r\n\t\t};\r\n\t}\r\n\r\n\t/**\r\n\t* @param {(string|Object)}\tevt_or_pane\t\tThe pane being opened, ie: north, south, east, or west\r\n\t*/\r\n,\tslideToggle = function (evt_or_pane) {\r\n\t\tvar pane = evtPane.call(this, evt_or_pane);\r\n\t\ttoggle(pane, true);\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* Must set left/top on East/South panes so animation will work properly\r\n\t*\r\n\t* @param {string}\tpane\tThe pane to lock, 'east' or 'south' - any other is ignored!\r\n\t* @param {boolean}\tdoLock  true = set left/top, false = remove\r\n\t*/\r\n,\tlockPaneForFX = function (pane, doLock) {\r\n\t\tvar $P\t= $Ps[pane]\r\n\t\t,\ts\t= state[pane]\r\n\t\t,\to\t= options[pane]\r\n\t\t,\tz\t= options.zIndexes\r\n\t\t;\r\n\t\tif (doLock) {\r\n\t\t\tshowMasks( pane, { animation: true, objectsOnly: true });\r\n\t\t\t$P.css({ zIndex: z.pane_animate }); // overlay all elements during animation\r\n\t\t\tif (pane==\"south\")\r\n\t\t\t\t$P.css({ top: sC.inset.top + sC.innerHeight - $P.outerHeight() });\r\n\t\t\telse if (pane==\"east\")\r\n\t\t\t\t$P.css({ left: sC.inset.left + sC.innerWidth - $P.outerWidth() });\r\n\t\t}\r\n\t\telse { // animation DONE - RESET CSS\r\n\t\t\thideMasks();\r\n\t\t\t$P.css({ zIndex: (s.isSliding ? z.pane_sliding : z.pane_normal) });\r\n\t\t\tif (pane==\"south\")\r\n\t\t\t\t$P.css({ top: \"auto\" });\r\n\t\t\t// if pane is positioned 'off-screen', then DO NOT screw with it!\r\n\t\t\telse if (pane==\"east\" && !$P.css(\"left\").match(/\\-99999/))\r\n\t\t\t\t$P.css({ left: \"auto\" });\r\n\t\t\t// fix anti-aliasing in IE - only needed for animations that change opacity\r\n\t\t\tif (browser.msie && o.fxOpacityFix && o.fxName_open != \"slide\" && $P.css(\"filter\") && $P.css(\"opacity\") == 1)\r\n\t\t\t\t$P[0].style.removeAttribute('filter');\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger\r\n\t*\r\n\t* @see  open(), close()\r\n\t* @param {string}\tpane\tThe pane to enable/disable, 'north', 'south', etc.\r\n\t* @param {boolean}\tenable\tEnable or Disable sliding?\r\n\t*/\r\n,\tbindStartSlidingEvents = function (pane, enable) {\r\n\t\tvar o\t\t= options[pane]\r\n\t\t,\t$P\t\t= $Ps[pane]\r\n\t\t,\t$R\t\t= $Rs[pane]\r\n\t\t,\tevtName\t= o.slideTrigger_open.toLowerCase()\r\n\t\t;\r\n\t\tif (!$R || (enable && !o.slidable)) return;\r\n\r\n\t\t// make sure we have a valid event\r\n\t\tif (evtName.match(/mouseover/))\r\n\t\t\tevtName = o.slideTrigger_open = \"mouseenter\";\r\n\t\telse if (!evtName.match(/(click|dblclick|mouseenter)/)) \r\n\t\t\tevtName = o.slideTrigger_open = \"click\";\r\n\r\n\t\t// must remove double-click-toggle when using dblclick-slide\r\n\t\tif (o.resizerDblClickToggle && evtName.match(/click/)) {\r\n\t\t\t$R[enable ? \"unbind\" : \"bind\"]('dblclick.'+ sID, toggle)\r\n\t\t}\r\n\r\n\t\t$R\r\n\t\t\t// add or remove event\r\n\t\t\t[enable ? \"bind\" : \"unbind\"](evtName +'.'+ sID, slideOpen)\r\n\t\t\t// set the appropriate cursor & title/tip\r\n\t\t\t.css(\"cursor\", enable ? o.sliderCursor : \"default\")\r\n\t\t\t.attr(\"title\", enable ? o.tips.Slide : \"\")\r\n\t\t;\r\n\t}\r\n\r\n\t/**\r\n\t* Add or remove 'mouseleave' events to 'slide close' when pane is 'sliding' open or closed\r\n\t* Also increases zIndex when pane is sliding open\r\n\t* See bindStartSlidingEvents for code to control 'slide open'\r\n\t*\r\n\t* @see  slideOpen(), slideClose()\r\n\t* @param {string}\tpane\tThe pane to process, 'north', 'south', etc.\r\n\t* @param {boolean}\tenable\tEnable or Disable events?\r\n\t*/\r\n,\tbindStopSlidingEvents = function (pane, enable) {\r\n\t\tvar\to\t\t= options[pane]\r\n\t\t,\ts\t\t= state[pane]\r\n\t\t,\tc\t\t= _c[pane]\r\n\t\t,\tz\t\t= options.zIndexes\r\n\t\t,\tevtName\t= o.slideTrigger_close.toLowerCase()\r\n\t\t,\taction\t= (enable ? \"bind\" : \"unbind\")\r\n\t\t,\t$P\t\t= $Ps[pane]\r\n\t\t,\t$R\t\t= $Rs[pane]\r\n\t\t;\r\n\t\ttimer.clear(pane+\"_closeSlider\"); // just in case\r\n\r\n\t\tif (enable) {\r\n\t\t\ts.isSliding = true;\r\n\t\t\tstate.panesSliding[pane] = true;\r\n\t\t\t// remove 'slideOpen' event from resizer\r\n\t\t\t// ALSO will raise the zIndex of the pane & resizer\r\n\t\t\tbindStartSlidingEvents(pane, false);\r\n\t\t}\r\n\t\telse {\r\n\t\t\ts.isSliding = false;\r\n\t\t\tdelete state.panesSliding[pane];\r\n\t\t}\r\n\r\n\t\t// RE/SET zIndex - increases when pane is sliding-open, resets to normal when not\r\n\t\t$P.css(\"zIndex\", enable ? z.pane_sliding : z.pane_normal);\r\n\t\t$R.css(\"zIndex\", enable ? z.pane_sliding+2 : z.resizer_normal); // NOTE: mask = pane_sliding+1\r\n\r\n\t\t// make sure we have a valid event\r\n\t\tif (!evtName.match(/(click|mouseleave)/))\r\n\t\t\tevtName = o.slideTrigger_close = \"mouseleave\"; // also catches 'mouseout'\r\n\r\n\t\t// add/remove slide triggers\r\n\t\t$R[action](evtName, slideClose); // base event on resize\r\n\t\t// need extra events for mouseleave\r\n\t\tif (evtName === \"mouseleave\") {\r\n\t\t\t// also close on pane.mouseleave\r\n\t\t\t$P[action](\"mouseleave.\"+ sID, slideClose);\r\n\t\t\t// cancel timer when mouse moves between 'pane' and 'resizer'\r\n\t\t\t$R[action](\"mouseenter.\"+ sID, cancelMouseOut);\r\n\t\t\t$P[action](\"mouseenter.\"+ sID, cancelMouseOut);\r\n\t\t}\r\n\r\n\t\tif (!enable)\r\n\t\t\ttimer.clear(pane+\"_closeSlider\");\r\n\t\telse if (evtName === \"click\" && !o.resizable) {\r\n\t\t\t// IF pane is not resizable (which already has a cursor and tip) \r\n\t\t\t// then set the a cursor & title/tip on resizer when sliding\r\n\t\t\t$R.css(\"cursor\", enable ? o.sliderCursor : \"default\");\r\n\t\t\t$R.attr(\"title\", enable ? o.tips.Close : \"\"); // use Toggler-tip, eg: \"Close Pane\"\r\n\t\t}\r\n\r\n\t\t// SUBROUTINE for mouseleave timer clearing\r\n\t\tfunction cancelMouseOut (evt) {\r\n\t\t\ttimer.clear(pane+\"_closeSlider\");\r\n\t\t\tevt.stopPropagation();\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* Hides/closes a pane if there is insufficient room - reverses this when there is room again\r\n\t* MUST have already called setSizeLimits() before calling this method\r\n\t*\r\n\t* @param {string}\tpane\t\t\t\t\tThe pane being resized\r\n\t* @param {boolean=}\t[isOpening=false]\t\tCalled from onOpen?\r\n\t* @param {boolean=}\t[skipCallback=false]\tShould the onresize callback be run?\r\n\t* @param {boolean=}\t[force=false]\r\n\t*/\r\n,\tmakePaneFit = function (pane, isOpening, skipCallback, force) {\r\n\t\tvar\to\t= options[pane]\r\n\t\t,\ts\t= state[pane]\r\n\t\t,\tc\t= _c[pane]\r\n\t\t,\t$P\t= $Ps[pane]\r\n\t\t,\t$R\t= $Rs[pane]\r\n\t\t,\tisSidePane \t= c.dir===\"vert\"\r\n\t\t,\thasRoom\t\t= false\r\n\t\t;\r\n\t\t// special handling for center & east/west panes\r\n\t\tif (pane === \"center\" || (isSidePane && s.noVerticalRoom)) {\r\n\t\t\t// see if there is enough room to display the pane\r\n\t\t\t// ERROR: hasRoom = s.minHeight <= s.maxHeight && (isSidePane || s.minWidth <= s.maxWidth);\r\n\t\t\thasRoom = (s.maxHeight >= 0);\r\n\t\t\tif (hasRoom && s.noRoom) { // previously hidden due to noRoom, so show now\r\n\t\t\t\t_showPane(pane);\r\n\t\t\t\tif ($R) $R.show();\r\n\t\t\t\ts.isVisible = true;\r\n\t\t\t\ts.noRoom = false;\r\n\t\t\t\tif (isSidePane) s.noVerticalRoom = false;\r\n\t\t\t\t_fixIframe(pane);\r\n\t\t\t}\r\n\t\t\telse if (!hasRoom && !s.noRoom) { // not currently hidden, so hide now\r\n\t\t\t\t_hidePane(pane);\r\n\t\t\t\tif ($R) $R.hide();\r\n\t\t\t\ts.isVisible = false;\r\n\t\t\t\ts.noRoom = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// see if there is enough room to fit the border-pane\r\n\t\tif (pane === \"center\") {\r\n\t\t\t// ignore center in this block\r\n\t\t}\r\n\t\telse if (s.minSize <= s.maxSize) { // pane CAN fit\r\n\t\t\thasRoom = true;\r\n\t\t\tif (s.size > s.maxSize) // pane is too big - shrink it\r\n\t\t\t\tsizePane(pane, s.maxSize, skipCallback, true, force); // true = noAnimation\r\n\t\t\telse if (s.size < s.minSize) // pane is too small - enlarge it\r\n\t\t\t\tsizePane(pane, s.minSize, skipCallback, true, force); // true = noAnimation\r\n\t\t\t// need s.isVisible because new pseudoClose method keeps pane visible, but off-screen\r\n\t\t\telse if ($R && s.isVisible && $P.is(\":visible\")) {\r\n\t\t\t\t// make sure resizer-bar is positioned correctly\r\n\t\t\t\t// handles situation where nested layout was 'hidden' when initialized\r\n\t\t\t\tvar\tpos = s.size + sC.inset[c.side];\r\n\t\t\t\tif ($.layout.cssNum( $R, c.side ) != pos) $R.css( c.side, pos );\r\n\t\t\t}\r\n\r\n\t\t\t// if was previously hidden due to noRoom, then RESET because NOW there is room\r\n\t\t\tif (s.noRoom) {\r\n\t\t\t\t// s.noRoom state will be set by open or show\r\n\t\t\t\tif (s.wasOpen && o.closable) {\r\n\t\t\t\t\tif (o.autoReopen)\r\n\t\t\t\t\t\topen(pane, false, true, true); // true = noAnimation, true = noAlert\r\n\t\t\t\t\telse // leave the pane closed, so just update state\r\n\t\t\t\t\t\ts.noRoom = false;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t\tshow(pane, s.wasOpen, true, true); // true = noAnimation, true = noAlert\r\n\t\t\t}\r\n\t\t}\r\n\t\telse { // !hasRoom - pane CANNOT fit\r\n\t\t\tif (!s.noRoom) { // pane not set as noRoom yet, so hide or close it now...\r\n\t\t\t\ts.noRoom = true; // update state\r\n\t\t\t\ts.wasOpen = !s.isClosed && !s.isSliding;\r\n\t\t\t\tif (s.isClosed){} // SKIP\r\n\t\t\t\telse if (o.closable) // 'close' if possible\r\n\t\t\t\t\tclose(pane, true, true); // true = force, true = noAnimation\r\n\t\t\t\telse // 'hide' pane if cannot just be closed\r\n\t\t\t\t\thide(pane, true); // true = noAnimation\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* manualSizePane is an exposed flow-through method allowing extra code when pane is 'manually resized'\r\n\t*\r\n\t* @param {(string|Object)}\tevt_or_pane\t\t\t\tThe pane being resized\r\n\t* @param {number}\t\t\tsize\t\t\t\t\tThe *desired* new size for this pane - will be validated\r\n\t* @param {boolean=}\t\t\t[skipCallback=false]\tShould the onresize callback be run?\r\n\t* @param {boolean=}\t\t\t[noAnimation=false]\r\n\t* @param {boolean=}\t\t\t[force=false]\t\t\tForce resizing even if does not seem necessary\r\n\t*/\r\n,\tmanualSizePane = function (evt_or_pane, size, skipCallback, noAnimation, force) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane)\r\n\t\t,\to\t= options[pane]\r\n\t\t,\ts\t= state[pane]\r\n\t\t//\tif resizing callbacks have been delayed and resizing is now DONE, force resizing to complete...\r\n\t\t,\tforceResize = force || (o.livePaneResizing && !s.isResizing)\r\n\t\t;\r\n\t\t// ANY call to manualSizePane disables autoResize - ie, percentage sizing\r\n\t\ts.autoResize = false;\r\n\t\t// flow-through...\r\n\t\tsizePane(pane, size, skipCallback, noAnimation, forceResize); // will animate resize if option enabled\r\n\t}\r\n\r\n\t/**\r\n\t* sizePane is called only by internal methods whenever a pane needs to be resized\r\n\t*\r\n\t* @param {(string|Object)}\tevt_or_pane\t\t\t\tThe pane being resized\r\n\t* @param {number}\t\t\tsize\t\t\t\t\tThe *desired* new size for this pane - will be validated\r\n\t* @param {boolean=}\t\t\t[skipCallback=false]\tShould the onresize callback be run?\r\n\t* @param {boolean=}\t\t\t[noAnimation=false]\r\n\t* @param {boolean=}\t\t\t[force=false]\t\t\tForce resizing even if does not seem necessary\r\n\t*/\r\n,\tsizePane = function (evt_or_pane, size, skipCallback, noAnimation, force) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tpane\t= evtPane.call(this, evt_or_pane) // probably NEVER called from event?\r\n\t\t,\to\t\t= options[pane]\r\n\t\t,\ts\t\t= state[pane]\r\n\t\t,\t$P\t\t= $Ps[pane]\r\n\t\t,\t$R\t\t= $Rs[pane]\r\n\t\t,\tside\t= _c[pane].side\r\n\t\t,\tdimName\t= _c[pane].sizeType.toLowerCase()\r\n\t\t,\tskipResizeWhileDragging = s.isResizing && !o.triggerEventsDuringLiveResize\r\n\t\t,\tdoFX\t= noAnimation !== true && o.animatePaneSizing\r\n\t\t,\toldSize, newSize\r\n\t\t;\r\n\t\t// QUEUE in case another action/animation is in progress\r\n\t\t$N.queue(function( queueNext ){\r\n\t\t\t// calculate 'current' min/max sizes\r\n\t\t\tsetSizeLimits(pane); // update pane-state\r\n\t\t\toldSize = s.size;\r\n\t\t\tsize = _parseSize(pane, size); // handle percentages & auto\r\n\t\t\tsize = max(size, _parseSize(pane, o.minSize));\r\n\t\t\tsize = min(size, s.maxSize);\r\n\t\t\tif (size < s.minSize) { // not enough room for pane!\r\n\t\t\t\tqueueNext(); // call before makePaneFit() because it needs the queue free\r\n\t\t\t\tmakePaneFit(pane, false, skipCallback);\t// will hide or close pane\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// IF newSize is same as oldSize, then nothing to do - abort\r\n\t\t\tif (!force && size === oldSize)\r\n\t\t\t\treturn queueNext();\r\n\r\n\t\t\ts.newSize = size;\r\n\r\n\t\t\t// onresize_start callback CANNOT cancel resizing because this would break the layout!\r\n\t\t\tif (!skipCallback && state.initialized && s.isVisible)\r\n\t\t\t\t_runCallbacks(\"onresize_start\", pane);\r\n\r\n\t\t\t// resize the pane, and make sure its visible\r\n\t\t\tnewSize = cssSize(pane, size);\r\n\r\n\t\t\tif (doFX && $P.is(\":visible\")) { // ANIMATE\r\n\t\t\t\tvar fx\t\t= $.layout.effects.size[pane] || $.layout.effects.size.all\r\n\t\t\t\t,\teasing\t= o.fxSettings_size.easing || fx.easing\r\n\t\t\t\t,\tz\t\t= options.zIndexes\r\n\t\t\t\t,\tprops\t= {};\r\n\t\t\t\tprops[ dimName ] = newSize +'px';\r\n\t\t\t\ts.isMoving = true;\r\n\t\t\t\t// overlay all elements during animation\r\n\t\t\t\t$P.css({ zIndex: z.pane_animate })\r\n\t\t\t\t  .show().animate( props, o.fxSpeed_size, easing, function(){\r\n\t\t\t\t\t// reset zIndex after animation\r\n\t\t\t\t\t$P.css({ zIndex: (s.isSliding ? z.pane_sliding : z.pane_normal) });\r\n\t\t\t\t\ts.isMoving = false;\r\n\t\t\t\t\tdelete s.newSize;\r\n\t\t\t\t\tsizePane_2(); // continue\r\n\t\t\t\t\tqueueNext();\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t\telse { // no animation\r\n\t\t\t\t$P.css( dimName, newSize );\t// resize pane\r\n\t\t\t\tdelete s.newSize;\r\n\t\t\t\t// if pane is visible, then \r\n\t\t\t\tif ($P.is(\":visible\"))\r\n\t\t\t\t\tsizePane_2(); // continue\r\n\t\t\t\telse {\r\n\t\t\t\t\t// pane is NOT VISIBLE, so just update state data...\r\n\t\t\t\t\t// when pane is *next opened*, it will have the new size\r\n\t\t\t\t\ts.size = size;\t\t\t\t// update state.size\r\n\t\t\t\t\t$.extend(s, elDims($P));\t// update state dimensions\r\n\t\t\t\t}\r\n\t\t\t\tqueueNext();\r\n\t\t\t};\r\n\r\n\t\t});\r\n\r\n\t\t// SUBROUTINE\r\n\t\tfunction sizePane_2 () {\r\n\t\t\t/*\tPanes are sometimes not sized precisely in some browsers!?\r\n\t\t\t *\tThis code will resize the pane up to 3 times to nudge the pane to the correct size\r\n\t\t\t */\r\n\t\t\tvar\tactual\t= dimName==='width' ? $P.outerWidth() : $P.outerHeight()\r\n\t\t\t,\ttries\t= [{\r\n\t\t\t\t\t\t   \tpane:\t\tpane\r\n\t\t\t\t\t\t,\tcount:\t\t1\r\n\t\t\t\t\t\t,\ttarget:\t\tsize\r\n\t\t\t\t\t\t,\tactual:\t\tactual\r\n\t\t\t\t\t\t,\tcorrect:\t(size === actual)\r\n\t\t\t\t\t\t,\tattempt:\tsize\r\n\t\t\t\t\t\t,\tcssSize:\tnewSize\r\n\t\t\t\t\t\t}]\r\n\t\t\t,\tlastTry = tries[0]\r\n\t\t\t,\tthisTry\t= {}\r\n\t\t\t,\tmsg\t\t= 'Inaccurate size after resizing the '+ pane +'-pane.'\r\n\t\t\t;\r\n\t\t\twhile ( !lastTry.correct ) {\r\n\t\t\t\tthisTry = { pane: pane, count: lastTry.count+1, target: size };\r\n\r\n\t\t\t\tif (lastTry.actual > size)\r\n\t\t\t\t\tthisTry.attempt = max(0, lastTry.attempt - (lastTry.actual - size));\r\n\t\t\t\telse // lastTry.actual < size\r\n\t\t\t\t\tthisTry.attempt = max(0, lastTry.attempt + (size - lastTry.actual));\r\n\r\n\t\t\t\tthisTry.cssSize = cssSize(pane, thisTry.attempt);\r\n\t\t\t\t$P.css( dimName, thisTry.cssSize );\r\n\r\n\t\t\t\tthisTry.actual\t= dimName=='width' ? $P.outerWidth() : $P.outerHeight();\r\n\t\t\t\tthisTry.correct\t= (size === thisTry.actual);\r\n\r\n\t\t\t\t// log attempts and alert the user of this *non-fatal error* (if showDebugMessages)\r\n\t\t\t\tif ( tries.length === 1) {\r\n\t\t\t\t\t_log(msg, false, true);\r\n\t\t\t\t\t_log(lastTry, false, true);\r\n\t\t\t\t}\r\n\t\t\t\t_log(thisTry, false, true);\r\n\t\t\t\t// after 4 tries, is as close as its gonna get!\r\n\t\t\t\tif (tries.length > 3) break;\r\n\r\n\t\t\t\ttries.push( thisTry );\r\n\t\t\t\tlastTry = tries[ tries.length - 1 ];\r\n\t\t\t}\r\n\t\t\t// END TESTING CODE\r\n\r\n\t\t\t// update pane-state dimensions\r\n\t\t\ts.size\t= size;\r\n\t\t\t$.extend(s, elDims($P));\r\n\r\n\t\t\tif (s.isVisible && $P.is(\":visible\")) {\r\n\t\t\t\t// reposition the resizer-bar\r\n\t\t\t\tif ($R) $R.css( side, size + sC.inset[side] );\r\n\t\t\t\t// resize the content-div\r\n\t\t\t\tsizeContent(pane);\r\n\t\t\t}\r\n\r\n\t\t\tif (!skipCallback && !skipResizeWhileDragging && state.initialized && s.isVisible)\r\n\t\t\t\t_runCallbacks(\"onresize_end\", pane);\r\n\r\n\t\t\t// resize all the adjacent panes, and adjust their toggler buttons\r\n\t\t\t// when skipCallback passed, it means the controlling method will handle 'other panes'\r\n\t\t\tif (!skipCallback) {\r\n\t\t\t\t// also no callback if live-resize is in progress and NOT triggerEventsDuringLiveResize\r\n\t\t\t\tif (!s.isSliding) sizeMidPanes(_c[pane].dir==\"horz\" ? \"\" : \"center\", skipResizeWhileDragging, force);\r\n\t\t\t\tsizeHandles();\r\n\t\t\t}\r\n\r\n\t\t\t// if opposite-pane was autoClosed, see if it can be autoOpened now\r\n\t\t\tvar altPane = _c.oppositeEdge[pane];\r\n\t\t\tif (size < oldSize && state[ altPane ].noRoom) {\r\n\t\t\t\tsetSizeLimits( altPane );\r\n\t\t\t\tmakePaneFit( altPane, false, skipCallback );\r\n\t\t\t}\r\n\r\n\t\t\t// DEBUG - ALERT user/developer so they know there was a sizing problem\r\n\t\t\tif (tries.length > 1)\r\n\t\t\t\t_log(msg +'\\nSee the Error Console for details.', true, true);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t* @see  initPanes(), sizePane(), \tresizeAll(), open(), close(), hide()\r\n\t* @param {(Array.<string>|string)}\tpanes\t\t\t\t\tThe pane(s) being resized, comma-delmited string\r\n\t* @param {boolean=}\t\t\t\t\t[skipCallback=false]\tShould the onresize callback be run?\r\n\t* @param {boolean=}\t\t\t\t\t[force=false]\r\n\t*/\r\n,\tsizeMidPanes = function (panes, skipCallback, force) {\r\n\t\tpanes = (panes ? panes : \"east,west,center\").split(\",\");\r\n\r\n\t\t$.each(panes, function (i, pane) {\r\n\t\t\tif (!$Ps[pane]) return; // NO PANE - skip\r\n\t\t\tvar \r\n\t\t\t\to\t\t= options[pane]\r\n\t\t\t,\ts\t\t= state[pane]\r\n\t\t\t,\t$P\t\t= $Ps[pane]\r\n\t\t\t,\t$R\t\t= $Rs[pane]\r\n\t\t\t,\tisCenter= (pane==\"center\")\r\n\t\t\t,\thasRoom\t= true\r\n\t\t\t,\tCSS\t\t= {}\r\n\t\t\t//\tif pane is not visible, show it invisibly NOW rather than for *each call* in this script\r\n\t\t\t,\tvisCSS\t= $.layout.showInvisibly($P)\r\n\r\n\t\t\t,\tnewCenter\t= calcNewCenterPaneDims()\r\n\t\t\t;\r\n\r\n\t\t\t// update pane-state dimensions\r\n\t\t\t$.extend(s, elDims($P));\r\n\r\n\t\t\tif (pane === \"center\") {\r\n\t\t\t\tif (!force && s.isVisible && newCenter.width === s.outerWidth && newCenter.height === s.outerHeight) {\r\n\t\t\t\t\t$P.css(visCSS);\r\n\t\t\t\t\treturn true; // SKIP - pane already the correct size\r\n\t\t\t\t}\r\n\t\t\t\t// set state for makePaneFit() logic\r\n\t\t\t\t$.extend(s, cssMinDims(pane), {\r\n\t\t\t\t\tmaxWidth:\tnewCenter.width\r\n\t\t\t\t,\tmaxHeight:\tnewCenter.height\r\n\t\t\t\t});\r\n\t\t\t\tCSS = newCenter;\r\n\t\t\t\ts.newWidth\t= CSS.width;\r\n\t\t\t\ts.newHeight\t= CSS.height;\r\n\t\t\t\t// convert OUTER width/height to CSS width/height \r\n\t\t\t\tCSS.width\t= cssW($P, CSS.width);\r\n\t\t\t\t// NEW - allow pane to extend 'below' visible area rather than hide it\r\n\t\t\t\tCSS.height\t= cssH($P, CSS.height);\r\n\t\t\t\thasRoom\t\t= CSS.width >= 0 && CSS.height >= 0; // height >= 0 = ALWAYS TRUE NOW\r\n\r\n\t\t\t\t// during layout init, try to shrink east/west panes to make room for center\r\n\t\t\t\tif (!state.initialized && o.minWidth > newCenter.width) {\r\n\t\t\t\t\tvar\r\n\t\t\t\t\t\treqPx\t= o.minWidth - s.outerWidth\r\n\t\t\t\t\t,\tminE\t= options.east.minSize || 0\r\n\t\t\t\t\t,\tminW\t= options.west.minSize || 0\r\n\t\t\t\t\t,\tsizeE\t= state.east.size\r\n\t\t\t\t\t,\tsizeW\t= state.west.size\r\n\t\t\t\t\t,\tnewE\t= sizeE\r\n\t\t\t\t\t,\tnewW\t= sizeW\r\n\t\t\t\t\t;\r\n\t\t\t\t\tif (reqPx > 0 && state.east.isVisible && sizeE > minE) {\r\n\t\t\t\t\t\tnewE = max( sizeE-minE, sizeE-reqPx );\r\n\t\t\t\t\t\treqPx -= sizeE-newE;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (reqPx > 0 && state.west.isVisible && sizeW > minW) {\r\n\t\t\t\t\t\tnewW = max( sizeW-minW, sizeW-reqPx );\r\n\t\t\t\t\t\treqPx -= sizeW-newW;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// IF we found enough extra space, then resize the border panes as calculated\r\n\t\t\t\t\tif (reqPx === 0) {\r\n\t\t\t\t\t\tif (sizeE && sizeE != minE)\r\n\t\t\t\t\t\t\tsizePane('east', newE, true, true, force); // true = skipCallback/noAnimation - initPanes will handle when done\r\n\t\t\t\t\t\tif (sizeW && sizeW != minW)\r\n\t\t\t\t\t\t\tsizePane('west', newW, true, true, force); // true = skipCallback/noAnimation\r\n\t\t\t\t\t\t// now start over!\r\n\t\t\t\t\t\tsizeMidPanes('center', skipCallback, force);\r\n\t\t\t\t\t\t$P.css(visCSS);\r\n\t\t\t\t\t\treturn; // abort this loop\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse { // for east and west, set only the height, which is same as center height\r\n\t\t\t\t// set state.min/maxWidth/Height for makePaneFit() logic\r\n\t\t\t\tif (s.isVisible && !s.noVerticalRoom)\r\n\t\t\t\t\t$.extend(s, elDims($P), cssMinDims(pane))\r\n\t\t\t\tif (!force && !s.noVerticalRoom && newCenter.height === s.outerHeight) {\r\n\t\t\t\t\t$P.css(visCSS);\r\n\t\t\t\t\treturn true; // SKIP - pane already the correct size\r\n\t\t\t\t}\r\n\t\t\t\t// east/west have same top, bottom & height as center\r\n\t\t\t\tCSS.top\t\t= newCenter.top;\r\n\t\t\t\tCSS.bottom\t= newCenter.bottom;\r\n\t\t\t\ts.newSize\t= newCenter.height\r\n\t\t\t\t// NEW - allow pane to extend 'below' visible area rather than hide it\r\n\t\t\t\tCSS.height\t= cssH($P, newCenter.height);\r\n\t\t\t\ts.maxHeight\t= CSS.height;\r\n\t\t\t\thasRoom\t\t= (s.maxHeight >= 0); // ALWAYS TRUE NOW\r\n\t\t\t\tif (!hasRoom) s.noVerticalRoom = true; // makePaneFit() logic\r\n\t\t\t}\r\n\r\n\t\t\tif (hasRoom) {\r\n\t\t\t\t// resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized\r\n\t\t\t\tif (!skipCallback && state.initialized)\r\n\t\t\t\t\t_runCallbacks(\"onresize_start\", pane);\r\n\r\n\t\t\t\t$P.css(CSS); // apply the CSS to pane\r\n\t\t\t\tif (pane !== \"center\")\r\n\t\t\t\t\tsizeHandles(pane); // also update resizer length\r\n\t\t\t\tif (s.noRoom && !s.isClosed && !s.isHidden)\r\n\t\t\t\t\tmakePaneFit(pane); // will re-open/show auto-closed/hidden pane\r\n\t\t\t\tif (s.isVisible) {\r\n\t\t\t\t\t$.extend(s, elDims($P)); // update pane dimensions\r\n\t\t\t\t\tif (state.initialized) sizeContent(pane); // also resize the contents, if exists\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (!s.noRoom && s.isVisible) // no room for pane\r\n\t\t\t\tmakePaneFit(pane); // will hide or close pane\r\n\r\n\t\t\t// reset visibility, if necessary\r\n\t\t\t$P.css(visCSS);\r\n\r\n\t\t\tdelete s.newSize;\r\n\t\t\tdelete s.newWidth;\r\n\t\t\tdelete s.newHeight;\r\n\r\n\t\t\tif (!s.isVisible)\r\n\t\t\t\treturn true; // DONE - next pane\r\n\r\n\t\t\t/*\r\n\t\t\t* Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes\r\n\t\t\t* Normally these panes have only 'left' & 'right' positions so pane auto-sizes\r\n\t\t\t* ALSO required when pane is an IFRAME because will NOT default to 'full width'\r\n\t\t\t*\tTODO: Can I use width:100% for a north/south iframe?\r\n\t\t\t*\tTODO: Sounds like a job for $P.outerWidth( sC.innerWidth ) SETTER METHOD\r\n\t\t\t*/\r\n\t\t\tif (pane === \"center\") { // finished processing midPanes\r\n\t\t\t\tvar fix = browser.isIE6 || !browser.boxModel;\r\n\t\t\t\tif ($Ps.north && (fix || state.north.tagName==\"IFRAME\")) \r\n\t\t\t\t\t$Ps.north.css(\"width\", cssW($Ps.north, sC.innerWidth));\r\n\t\t\t\tif ($Ps.south && (fix || state.south.tagName==\"IFRAME\"))\r\n\t\t\t\t\t$Ps.south.css(\"width\", cssW($Ps.south, sC.innerWidth));\r\n\t\t\t}\r\n\r\n\t\t\t// resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized\r\n\t\t\tif (!skipCallback && state.initialized)\r\n\t\t\t\t_runCallbacks(\"onresize_end\", pane);\r\n\t\t});\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* @see  window.onresize(), callbacks or custom code\r\n\t* @param {(Object|boolean)=}\tevt_or_refresh\tIf 'true', then also reset pane-positioning\r\n\t*/\r\n,\tresizeAll = function (evt_or_refresh) {\r\n\t\tvar\toldW\t= sC.innerWidth\r\n\t\t,\toldH\t= sC.innerHeight\r\n\t\t;\r\n\t\t// stopPropagation if called by trigger(\"layoutdestroy\") - use evtPane utility \r\n\t\tevtPane(evt_or_refresh);\r\n\r\n\t\t// cannot size layout when 'container' is hidden or collapsed\r\n\t\tif (!$N.is(\":visible\")) return;\r\n\r\n\t\tif (!state.initialized) {\r\n\t\t\t_initLayoutElements();\r\n\t\t\treturn; // no need to resize since we just initialized!\r\n\t\t}\r\n\r\n\t\tif (evt_or_refresh === true && $.isPlainObject(options.outset)) {\r\n\t\t\t// update container CSS in case outset option has changed\r\n\t\t\t$N.css( options.outset );\r\n\t\t}\r\n\t\t// UPDATE container dimensions\r\n\t\t$.extend(sC, elDims( $N, options.inset ));\r\n\t\tif (!sC.outerHeight) return;\r\n\r\n\t\t// if 'true' passed, refresh pane & handle positioning too\r\n\t\tif (evt_or_refresh === true) {\r\n\t\t\tsetPanePosition();\r\n\t\t}\r\n\r\n\t\t// onresizeall_start will CANCEL resizing if returns false\r\n\t\t// state.container has already been set, so user can access this info for calcuations\r\n\t\tif (false === _runCallbacks(\"onresizeall_start\")) return false;\r\n\r\n\t\tvar\t// see if container is now 'smaller' than before\r\n\t\t\tshrunkH\t= (sC.innerHeight < oldH)\r\n\t\t,\tshrunkW\t= (sC.innerWidth < oldW)\r\n\t\t,\t$P, o, s\r\n\t\t;\r\n\t\t// NOTE special order for sizing: S-N-E-W\r\n\t\t$.each([\"south\",\"north\",\"east\",\"west\"], function (i, pane) {\r\n\t\t\tif (!$Ps[pane]) return; // no pane - SKIP\r\n\t\t\to = options[pane];\r\n\t\t\ts = state[pane];\r\n\t\t\tif (s.autoResize && s.size != o.size) // resize pane to original size set in options\r\n\t\t\t\tsizePane(pane, o.size, true, true, true); // true=skipCallback/noAnimation/forceResize\r\n\t\t\telse {\r\n\t\t\t\tsetSizeLimits(pane);\r\n\t\t\t\tmakePaneFit(pane, false, true, true); // true=skipCallback/forceResize\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tsizeMidPanes(\"\", true, true); // true=skipCallback/forceResize\r\n\t\tsizeHandles(); // reposition the toggler elements\r\n\r\n\t\t// trigger all individual pane callbacks AFTER layout has finished resizing\r\n\t\t$.each(_c.allPanes, function (i, pane) {\r\n\t\t\t$P = $Ps[pane];\r\n\t\t\tif (!$P) return; // SKIP\r\n\t\t\tif (state[pane].isVisible) // undefined for non-existent panes\r\n\t\t\t\t_runCallbacks(\"onresize_end\", pane); // callback - if exists\r\n\t\t});\r\n\r\n\t\t_runCallbacks(\"onresizeall_end\");\r\n\t\t//_triggerLayoutEvent(pane, 'resizeall');\r\n\t}\r\n\r\n\t/**\r\n\t* Whenever a pane resizes or opens that has a nested layout, trigger resizeAll\r\n\t*\r\n\t* @param {(string|Object)}\tevt_or_pane\t\tThe pane just resized or opened\r\n\t*/\r\n,\tresizeChildren = function (evt_or_pane, skipRefresh) {\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane);\r\n\r\n\t\tif (!options[pane].resizeChildren) return;\r\n\r\n\t\t// ensure the pane-children are up-to-date\r\n\t\tif (!skipRefresh) refreshChildren( pane );\r\n\t\tvar pC = children[pane];\r\n\t\tif ($.isPlainObject( pC )) {\r\n\t\t\t// resize one or more children\r\n\t\t\t$.each( pC, function (key, child) {\r\n\t\t\t\tif (!child.destroyed) child.resizeAll();\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t* IF pane has a content-div, then resize all elements inside pane to fit pane-height\r\n\t*\r\n\t* @param {(string|Object)}\tevt_or_panes\t\tThe pane(s) being resized\r\n\t* @param {boolean=}\t\t\t[remeasure=false]\tShould the content (header/footer) be remeasured?\r\n\t*/\r\n,\tsizeContent = function (evt_or_panes, remeasure) {\r\n\t\tif (!isInitialized()) return;\r\n\r\n\t\tvar panes = evtPane.call(this, evt_or_panes);\r\n\t\tpanes = panes ? panes.split(\",\") : _c.allPanes;\r\n\r\n\t\t$.each(panes, function (idx, pane) {\r\n\t\t\tvar\r\n\t\t\t\t$P\t= $Ps[pane]\r\n\t\t\t,\t$C\t= $Cs[pane]\r\n\t\t\t,\to\t= options[pane]\r\n\t\t\t,\ts\t= state[pane]\r\n\t\t\t,\tm\t= s.content // m = measurements\r\n\t\t\t;\r\n\t\t\tif (!$P || !$C || !$P.is(\":visible\")) return true; // NOT VISIBLE - skip\r\n\r\n\t\t\t// if content-element was REMOVED, update OR remove the pointer\r\n\t\t\tif (!$C.length) {\r\n\t\t\t\tinitContent(pane, false);\t// false = do NOT sizeContent() - already there!\r\n\t\t\t\tif (!$C) return;\t\t\t// no replacement element found - pointer have been removed\r\n\t\t\t}\r\n\r\n\t\t\t// onsizecontent_start will CANCEL resizing if returns false\r\n\t\t\tif (false === _runCallbacks(\"onsizecontent_start\", pane)) return;\r\n\r\n\t\t\t// skip re-measuring offsets if live-resizing\r\n\t\t\tif ((!s.isMoving && !s.isResizing) || o.liveContentResizing || remeasure || m.top == undefined) {\r\n\t\t\t\t_measure();\r\n\t\t\t\t// if any footers are below pane-bottom, they may not measure correctly,\r\n\t\t\t\t// so allow pane overflow and re-measure\r\n\t\t\t\tif (m.hiddenFooters > 0 && $P.css(\"overflow\") === \"hidden\") {\r\n\t\t\t\t\t$P.css(\"overflow\", \"visible\");\r\n\t\t\t\t\t_measure(); // remeasure while overflowing\r\n\t\t\t\t\t$P.css(\"overflow\", \"hidden\");\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// NOTE: spaceAbove/Below *includes* the pane paddingTop/Bottom, but not pane.borders\r\n\t\t\tvar newH = s.innerHeight - (m.spaceAbove - s.css.paddingTop) - (m.spaceBelow - s.css.paddingBottom);\r\n\r\n\t\t\tif (!$C.is(\":visible\") || m.height != newH) {\r\n\t\t\t\t// size the Content element to fit new pane-size - will autoHide if not enough room\r\n\t\t\t\tsetOuterHeight($C, newH, true); // true=autoHide\r\n\t\t\t\tm.height = newH; // save new height\r\n\t\t\t};\r\n\r\n\t\t\tif (state.initialized)\r\n\t\t\t\t_runCallbacks(\"onsizecontent_end\", pane);\r\n\r\n\t\t\tfunction _below ($E) {\r\n\t\t\t\treturn max(s.css.paddingBottom, (parseInt($E.css(\"marginBottom\"), 10) || 0));\r\n\t\t\t};\r\n\r\n\t\t\tfunction _measure () {\r\n\t\t\t\tvar\r\n\t\t\t\t\tignore\t= options[pane].contentIgnoreSelector\r\n\t\t\t\t,\t$Fs\t\t= $C.nextAll().not(\".ui-layout-mask\").not(ignore || \":lt(0)\") // not :lt(0) = ALL\r\n\t\t\t\t,\t$Fs_vis\t= $Fs.filter(':visible')\r\n\t\t\t\t,\t$F\t\t= $Fs_vis.filter(':last')\r\n\t\t\t\t;\r\n\t\t\t\tm = {\r\n\t\t\t\t\ttop:\t\t\t$C[0].offsetTop\r\n\t\t\t\t,\theight:\t\t\t$C.outerHeight()\r\n\t\t\t\t,\tnumFooters:\t\t$Fs.length\r\n\t\t\t\t,\thiddenFooters:\t$Fs.length - $Fs_vis.length\r\n\t\t\t\t,\tspaceBelow:\t\t0 // correct if no content footer ($E)\r\n\t\t\t\t}\r\n\t\t\t\t\tm.spaceAbove\t= m.top; // just for state - not used in calc\r\n\t\t\t\t\tm.bottom\t\t= m.top + m.height;\r\n\t\t\t\tif ($F.length)\r\n\t\t\t\t\t//spaceBelow = (LastFooter.top + LastFooter.height) [footerBottom] - Content.bottom + max(LastFooter.marginBottom, pane.paddingBotom)\r\n\t\t\t\t\tm.spaceBelow = ($F[0].offsetTop + $F.outerHeight()) - m.bottom + _below($F);\r\n\t\t\t\telse // no footer - check marginBottom on Content element itself\r\n\t\t\t\t\tm.spaceBelow = _below($C);\r\n\t\t\t};\r\n\t\t});\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary\r\n\t*\r\n\t* @see  initHandles(), open(), close(), resizeAll()\r\n\t* @param {(string|Object)=}\t\tevt_or_panes\tThe pane(s) being resized\r\n\t*/\r\n,\tsizeHandles = function (evt_or_panes) {\r\n\t\tvar panes = evtPane.call(this, evt_or_panes)\r\n\t\tpanes = panes ? panes.split(\",\") : _c.borderPanes;\r\n\r\n\t\t$.each(panes, function (i, pane) {\r\n\t\t\tvar \r\n\t\t\t\to\t= options[pane]\r\n\t\t\t,\ts\t= state[pane]\r\n\t\t\t,\t$P\t= $Ps[pane]\r\n\t\t\t,\t$R\t= $Rs[pane]\r\n\t\t\t,\t$T\t= $Ts[pane]\r\n\t\t\t,\t$TC\r\n\t\t\t;\r\n\t\t\tif (!$P || !$R) return;\r\n\r\n\t\t\tvar\r\n\t\t\t\tdir\t\t\t= _c[pane].dir\r\n\t\t\t,\t_state\t\t= (s.isClosed ? \"_closed\" : \"_open\")\r\n\t\t\t,\tspacing\t\t= o[\"spacing\"+ _state]\r\n\t\t\t,\ttogAlign\t= o[\"togglerAlign\"+ _state]\r\n\t\t\t,\ttogLen\t\t= o[\"togglerLength\"+ _state]\r\n\t\t\t,\tpaneLen\r\n\t\t\t,\tleft\r\n\t\t\t,\toffset\r\n\t\t\t,\tCSS = {}\r\n\t\t\t;\r\n\r\n\t\t\tif (spacing === 0) {\r\n\t\t\t\t$R.hide();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\telse if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason\r\n\t\t\t\t$R.show(); // in case was previously hidden\r\n\r\n\t\t\t// Resizer Bar is ALWAYS same width/height of pane it is attached to\r\n\t\t\tif (dir === \"horz\") { // north/south\r\n\t\t\t\t//paneLen = $P.outerWidth(); // s.outerWidth || \r\n\t\t\t\tpaneLen = sC.innerWidth; // handle offscreen-panes\r\n\t\t\t\ts.resizerLength = paneLen;\r\n\t\t\t\tleft = $.layout.cssNum($P, \"left\")\r\n\t\t\t\t$R.css({\r\n\t\t\t\t\twidth:\tcssW($R, paneLen) // account for borders & padding\r\n\t\t\t\t,\theight:\tcssH($R, spacing) // ditto\r\n\t\t\t\t,\tleft:\tleft > -9999 ? left : sC.inset.left // handle offscreen-panes\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t\telse { // east/west\r\n\t\t\t\tpaneLen = $P.outerHeight(); // s.outerHeight || \r\n\t\t\t\ts.resizerLength = paneLen;\r\n\t\t\t\t$R.css({\r\n\t\t\t\t\theight:\tcssH($R, paneLen) // account for borders & padding\r\n\t\t\t\t,\twidth:\tcssW($R, spacing) // ditto\r\n\t\t\t\t,\ttop:\tsC.inset.top + getPaneSize(\"north\", true) // TODO: what if no North pane?\r\n\t\t\t\t//,\ttop:\t$.layout.cssNum($Ps[\"center\"], \"top\")\r\n\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t\t// remove hover classes\r\n\t\t\tremoveHover( o, $R );\r\n\r\n\t\t\tif ($T) {\r\n\t\t\t\tif (togLen === 0 || (s.isSliding && o.hideTogglerOnSlide)) {\r\n\t\t\t\t\t$T.hide(); // always HIDE the toggler when 'sliding'\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t\t$T.show(); // in case was previously hidden\r\n\r\n\t\t\t\tif (!(togLen > 0) || togLen === \"100%\" || togLen > paneLen) {\r\n\t\t\t\t\ttogLen = paneLen;\r\n\t\t\t\t\toffset = 0;\r\n\t\t\t\t}\r\n\t\t\t\telse { // calculate 'offset' based on options.PANE.togglerAlign_open/closed\r\n\t\t\t\t\tif (isStr(togAlign)) {\r\n\t\t\t\t\t\tswitch (togAlign) {\r\n\t\t\t\t\t\t\tcase \"top\":\r\n\t\t\t\t\t\t\tcase \"left\":\toffset = 0;\r\n\t\t\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\tcase \"bottom\":\r\n\t\t\t\t\t\t\tcase \"right\":\toffset = paneLen - togLen;\r\n\t\t\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\tcase \"middle\":\r\n\t\t\t\t\t\t\tcase \"center\":\r\n\t\t\t\t\t\t\tdefault:\t\toffset = round((paneLen - togLen) / 2); // 'default' catches typos\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse { // togAlign = number\r\n\t\t\t\t\t\tvar x = parseInt(togAlign, 10); //\r\n\t\t\t\t\t\tif (togAlign >= 0) offset = x;\r\n\t\t\t\t\t\telse offset = paneLen - togLen + x; // NOTE: x is negative!\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (dir === \"horz\") { // north/south\r\n\t\t\t\t\tvar width = cssW($T, togLen);\r\n\t\t\t\t\t$T.css({\r\n\t\t\t\t\t\twidth:\twidth  // account for borders & padding\r\n\t\t\t\t\t,\theight:\tcssH($T, spacing) // ditto\r\n\t\t\t\t\t,\tleft:\toffset // TODO: VERIFY that toggler  positions correctly for ALL values\r\n\t\t\t\t\t,\ttop:\t0\r\n\t\t\t\t\t});\r\n\t\t\t\t\t// CENTER the toggler content SPAN\r\n\t\t\t\t\t$T.children(\".content\").each(function(){\r\n\t\t\t\t\t\t$TC = $(this);\r\n\t\t\t\t\t\t$TC.css(\"marginLeft\", round((width-$TC.outerWidth())/2)); // could be negative\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t\telse { // east/west\r\n\t\t\t\t\tvar height = cssH($T, togLen);\r\n\t\t\t\t\t$T.css({\r\n\t\t\t\t\t\theight:\theight // account for borders & padding\r\n\t\t\t\t\t,\twidth:\tcssW($T, spacing) // ditto\r\n\t\t\t\t\t,\ttop:\toffset // POSITION the toggler\r\n\t\t\t\t\t,\tleft:\t0\r\n\t\t\t\t\t});\r\n\t\t\t\t\t// CENTER the toggler content SPAN\r\n\t\t\t\t\t$T.children(\".content\").each(function(){\r\n\t\t\t\t\t\t$TC = $(this);\r\n\t\t\t\t\t\t$TC.css(\"marginTop\", round((height-$TC.outerHeight())/2)); // could be negative\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// remove ALL hover classes\r\n\t\t\t\tremoveHover( 0, $T );\r\n\t\t\t}\r\n\r\n\t\t\t// DONE measuring and sizing this resizer/toggler, so can be 'hidden' now\r\n\t\t\tif (!state.initialized && (o.initHidden || s.isHidden)) {\r\n\t\t\t\t$R.hide();\r\n\t\t\t\tif ($T) $T.hide();\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* @param {(string|Object)}\tevt_or_pane\r\n\t*/\r\n,\tenableClosable = function (evt_or_pane) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane)\r\n\t\t,\t$T\t= $Ts[pane]\r\n\t\t,\to\t= options[pane]\r\n\t\t;\r\n\t\tif (!$T) return;\r\n\t\to.closable = true;\r\n\t\t$T\t.bind(\"click.\"+ sID, function(evt){ evt.stopPropagation(); toggle(pane); })\r\n\t\t\t.css(\"visibility\", \"visible\")\r\n\t\t\t.css(\"cursor\", \"pointer\")\r\n\t\t\t.attr(\"title\", state[pane].isClosed ? o.tips.Open : o.tips.Close) // may be blank\r\n\t\t\t.show();\r\n\t}\r\n\t/**\r\n\t* @param {(string|Object)}\tevt_or_pane\r\n\t* @param {boolean=}\t\t\t[hide=false]\r\n\t*/\r\n,\tdisableClosable = function (evt_or_pane, hide) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane)\r\n\t\t,\t$T\t= $Ts[pane]\r\n\t\t;\r\n\t\tif (!$T) return;\r\n\t\toptions[pane].closable = false;\r\n\t\t// is closable is disable, then pane MUST be open!\r\n\t\tif (state[pane].isClosed) open(pane, false, true);\r\n\t\t$T\t.unbind(\".\"+ sID)\r\n\t\t\t.css(\"visibility\", hide ? \"hidden\" : \"visible\") // instead of hide(), which creates logic issues\r\n\t\t\t.css(\"cursor\", \"default\")\r\n\t\t\t.attr(\"title\", \"\");\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* @param {(string|Object)}\tevt_or_pane\r\n\t*/\r\n,\tenableSlidable = function (evt_or_pane) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane)\r\n\t\t,\t$R\t= $Rs[pane]\r\n\t\t;\r\n\t\tif (!$R || !$R.data('draggable')) return;\r\n\t\toptions[pane].slidable = true; \r\n\t\tif (state[pane].isClosed)\r\n\t\t\tbindStartSlidingEvents(pane, true);\r\n\t}\r\n\t/**\r\n\t* @param {(string|Object)}\tevt_or_pane\r\n\t*/\r\n,\tdisableSlidable = function (evt_or_pane) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane)\r\n\t\t,\t$R\t= $Rs[pane]\r\n\t\t;\r\n\t\tif (!$R) return;\r\n\t\toptions[pane].slidable = false; \r\n\t\tif (state[pane].isSliding)\r\n\t\t\tclose(pane, false, true);\r\n\t\telse {\r\n\t\t\tbindStartSlidingEvents(pane, false);\r\n\t\t\t$R\t.css(\"cursor\", \"default\")\r\n\t\t\t\t.attr(\"title\", \"\");\r\n\t\t\tremoveHover(null, $R[0]); // in case currently hovered\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* @param {(string|Object)}\tevt_or_pane\r\n\t*/\r\n,\tenableResizable = function (evt_or_pane) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane)\r\n\t\t,\t$R\t= $Rs[pane]\r\n\t\t,\to\t= options[pane]\r\n\t\t;\r\n\t\tif (!$R || !$R.data('draggable')) return;\r\n\t\to.resizable = true; \r\n\t\t$R.draggable(\"enable\");\r\n\t\tif (!state[pane].isClosed)\r\n\t\t\t$R\t.css(\"cursor\", o.resizerCursor)\r\n\t\t\t \t.attr(\"title\", o.tips.Resize);\r\n\t}\r\n\t/**\r\n\t* @param {(string|Object)}\tevt_or_pane\r\n\t*/\r\n,\tdisableResizable = function (evt_or_pane) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar\tpane = evtPane.call(this, evt_or_pane)\r\n\t\t,\t$R\t= $Rs[pane]\r\n\t\t;\r\n\t\tif (!$R || !$R.data('draggable')) return;\r\n\t\toptions[pane].resizable = false; \r\n\t\t$R\t.draggable(\"disable\")\r\n\t\t\t.css(\"cursor\", \"default\")\r\n\t\t\t.attr(\"title\", \"\");\r\n\t\tremoveHover(null, $R[0]); // in case currently hovered\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* Move a pane from source-side (eg, west) to target-side (eg, east)\r\n\t* If pane exists on target-side, move that to source-side, ie, 'swap' the panes\r\n\t*\r\n\t* @param {(string|Object)}\tevt_or_pane1\tThe pane/edge being swapped\r\n\t* @param {string}\t\t\tpane2\t\t\tditto\r\n\t*/\r\n,\tswapPanes = function (evt_or_pane1, pane2) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tvar pane1 = evtPane.call(this, evt_or_pane1);\r\n\t\t// change state.edge NOW so callbacks can know where pane is headed...\r\n\t\tstate[pane1].edge = pane2;\r\n\t\tstate[pane2].edge = pane1;\r\n\t\t// run these even if NOT state.initialized\r\n\t\tif (false === _runCallbacks(\"onswap_start\", pane1)\r\n\t\t ||\tfalse === _runCallbacks(\"onswap_start\", pane2)\r\n\t\t) {\r\n\t\t\tstate[pane1].edge = pane1; // reset\r\n\t\t\tstate[pane2].edge = pane2;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar\r\n\t\t\toPane1\t= copy( pane1 )\r\n\t\t,\toPane2\t= copy( pane2 )\r\n\t\t,\tsizes\t= {}\r\n\t\t;\r\n\t\tsizes[pane1] = oPane1 ? oPane1.state.size : 0;\r\n\t\tsizes[pane2] = oPane2 ? oPane2.state.size : 0;\r\n\r\n\t\t// clear pointers & state\r\n\t\t$Ps[pane1] = false; \r\n\t\t$Ps[pane2] = false;\r\n\t\tstate[pane1] = {};\r\n\t\tstate[pane2] = {};\r\n\t\t\r\n\t\t// ALWAYS remove the resizer & toggler elements\r\n\t\tif ($Ts[pane1]) $Ts[pane1].remove();\r\n\t\tif ($Ts[pane2]) $Ts[pane2].remove();\r\n\t\tif ($Rs[pane1]) $Rs[pane1].remove();\r\n\t\tif ($Rs[pane2]) $Rs[pane2].remove();\r\n\t\t$Rs[pane1] = $Rs[pane2] = $Ts[pane1] = $Ts[pane2] = false;\r\n\r\n\t\t// transfer element pointers and data to NEW Layout keys\r\n\t\tmove( oPane1, pane2 );\r\n\t\tmove( oPane2, pane1 );\r\n\r\n\t\t// cleanup objects\r\n\t\toPane1 = oPane2 = sizes = null;\r\n\r\n\t\t// make panes 'visible' again\r\n\t\tif ($Ps[pane1]) $Ps[pane1].css(_c.visible);\r\n\t\tif ($Ps[pane2]) $Ps[pane2].css(_c.visible);\r\n\r\n\t\t// fix any size discrepancies caused by swap\r\n\t\tresizeAll();\r\n\r\n\t\t// run these even if NOT state.initialized\r\n\t\t_runCallbacks(\"onswap_end\", pane1);\r\n\t\t_runCallbacks(\"onswap_end\", pane2);\r\n\r\n\t\treturn;\r\n\r\n\t\tfunction copy (n) { // n = pane\r\n\t\t\tvar\r\n\t\t\t\t$P\t= $Ps[n]\r\n\t\t\t,\t$C\t= $Cs[n]\r\n\t\t\t;\r\n\t\t\treturn !$P ? false : {\r\n\t\t\t\tpane:\t\tn\r\n\t\t\t,\tP:\t\t\t$P ? $P[0] : false\r\n\t\t\t,\tC:\t\t\t$C ? $C[0] : false\r\n\t\t\t,\tstate:\t\t$.extend(true, {}, state[n])\r\n\t\t\t,\toptions:\t$.extend(true, {}, options[n])\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tfunction move (oPane, pane) {\r\n\t\t\tif (!oPane) return;\r\n\t\t\tvar\r\n\t\t\t\tP\t\t= oPane.P\r\n\t\t\t,\tC\t\t= oPane.C\r\n\t\t\t,\toldPane = oPane.pane\r\n\t\t\t,\tc\t\t= _c[pane]\r\n\t\t\t//\tsave pane-options that should be retained\r\n\t\t\t,\ts\t\t= $.extend(true, {}, state[pane])\r\n\t\t\t,\to\t\t= options[pane]\r\n\t\t\t//\tRETAIN side-specific FX Settings - more below\r\n\t\t\t,\tfx\t\t= { resizerCursor: o.resizerCursor }\r\n\t\t\t,\tre, size, pos\r\n\t\t\t;\r\n\t\t\t$.each(\"fxName,fxSpeed,fxSettings\".split(\",\"), function (i, k) {\r\n\t\t\t\tfx[k +\"_open\"]  = o[k +\"_open\"];\r\n\t\t\t\tfx[k +\"_close\"] = o[k +\"_close\"];\r\n\t\t\t\tfx[k +\"_size\"]  = o[k +\"_size\"];\r\n\t\t\t});\r\n\r\n\t\t\t// update object pointers and attributes\r\n\t\t\t$Ps[pane] = $(P)\r\n\t\t\t\t.data({\r\n\t\t\t\t\tlayoutPane:\t\tInstance[pane]\t// NEW pointer to pane-alias-object\r\n\t\t\t\t,\tlayoutEdge:\t\tpane\r\n\t\t\t\t})\r\n\t\t\t\t.css(_c.hidden)\r\n\t\t\t\t.css(c.cssReq)\r\n\t\t\t;\r\n\t\t\t$Cs[pane] = C ? $(C) : false;\r\n\r\n\t\t\t// set options and state\r\n\t\t\toptions[pane]\t= $.extend(true, {}, oPane.options, fx);\r\n\t\t\tstate[pane]\t\t= $.extend(true, {}, oPane.state);\r\n\r\n\t\t\t// change classNames on the pane, eg: ui-layout-pane-east ==> ui-layout-pane-west\r\n\t\t\tre = new RegExp(o.paneClass +\"-\"+ oldPane, \"g\");\r\n\t\t\tP.className = P.className.replace(re, o.paneClass +\"-\"+ pane);\r\n\r\n\t\t\t// ALWAYS regenerate the resizer & toggler elements\r\n\t\t\tinitHandles(pane); // create the required resizer & toggler\r\n\r\n\t\t\t// if moving to different orientation, then keep 'target' pane size\r\n\t\t\tif (c.dir != _c[oldPane].dir) {\r\n\t\t\t\tsize = sizes[pane] || 0;\r\n\t\t\t\tsetSizeLimits(pane); // update pane-state\r\n\t\t\t\tsize = max(size, state[pane].minSize);\r\n\t\t\t\t// use manualSizePane to disable autoResize - not useful after panes are swapped\r\n\t\t\t\tmanualSizePane(pane, size, true, true); // true/true = skipCallback/noAnimation\r\n\t\t\t}\r\n\t\t\telse // move the resizer here\r\n\t\t\t\t$Rs[pane].css(c.side, sC.inset[c.side] + (state[pane].isVisible ? getPaneSize(pane) : 0));\r\n\r\n\r\n\t\t\t// ADD CLASSNAMES & SLIDE-BINDINGS\r\n\t\t\tif (oPane.state.isVisible && !s.isVisible)\r\n\t\t\t\tsetAsOpen(pane, true); // true = skipCallback\r\n\t\t\telse {\r\n\t\t\t\tsetAsClosed(pane);\r\n\t\t\t\tbindStartSlidingEvents(pane, true); // will enable events IF option is set\r\n\t\t\t}\r\n\r\n\t\t\t// DESTROY the object\r\n\t\t\toPane = null;\r\n\t\t};\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* INTERNAL method to sync pin-buttons when pane is opened or closed\r\n\t* Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes\r\n\t*\r\n\t* @see  open(), setAsOpen(), setAsClosed()\r\n\t* @param {string}\tpane   These are the params returned to callbacks by layout()\r\n\t* @param {boolean}\tdoPin  True means set the pin 'down', False means 'up'\r\n\t*/\r\n,\tsyncPinBtns = function (pane, doPin) {\r\n\t\tif ($.layout.plugins.buttons)\r\n\t\t\t$.each(state[pane].pins, function (i, selector) {\r\n\t\t\t\t$.layout.buttons.setPinState(Instance, $(selector), pane, doPin);\r\n\t\t\t});\r\n\t}\r\n\r\n;\t// END var DECLARATIONS\r\n\r\n\t/**\r\n\t* Capture keys when enableCursorHotkey - toggle pane if hotkey pressed\r\n\t*\r\n\t* @see  document.keydown()\r\n\t*/\r\n\tfunction keyDown (evt) {\r\n\t\tif (!evt) return true;\r\n\t\tvar code = evt.keyCode;\r\n\t\tif (code < 33) return true; // ignore special keys: ENTER, TAB, etc\r\n\r\n\t\tvar\r\n\t\t\tPANE = {\r\n\t\t\t\t38: \"north\" // Up Cursor\t- $.ui.keyCode.UP\r\n\t\t\t,\t40: \"south\" // Down Cursor\t- $.ui.keyCode.DOWN\r\n\t\t\t,\t37: \"west\"  // Left Cursor\t- $.ui.keyCode.LEFT\r\n\t\t\t,\t39: \"east\"  // Right Cursor\t- $.ui.keyCode.RIGHT\r\n\t\t\t}\r\n\t\t,\tALT\t\t= evt.altKey // no worky!\r\n\t\t,\tSHIFT\t= evt.shiftKey\r\n\t\t,\tCTRL\t= evt.ctrlKey\r\n\t\t,\tCURSOR\t= (CTRL && code >= 37 && code <= 40)\r\n\t\t,\to, k, m, pane\r\n\t\t;\r\n\r\n\t\tif (CURSOR && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey\r\n\t\t\tpane = PANE[code];\r\n\t\telse if (CTRL || SHIFT) // check to see if this matches a custom-hotkey\r\n\t\t\t$.each(_c.borderPanes, function (i, p) { // loop each pane to check its hotkey\r\n\t\t\t\to = options[p];\r\n\t\t\t\tk = o.customHotkey;\r\n\t\t\t\tm = o.customHotkeyModifier; // if missing or invalid, treated as \"CTRL+SHIFT\"\r\n\t\t\t\tif ((SHIFT && m==\"SHIFT\") || (CTRL && m==\"CTRL\") || (CTRL && SHIFT)) { // Modifier matches\r\n\t\t\t\t\tif (k && code === (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches\r\n\t\t\t\t\t\tpane = p;\r\n\t\t\t\t\t\treturn false; // BREAK\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t// validate pane\r\n\t\tif (!pane || !$Ps[pane] || !options[pane].closable || state[pane].isHidden)\r\n\t\t\treturn true;\r\n\r\n\t\ttoggle(pane);\r\n\r\n\t\tevt.stopPropagation();\r\n\t\tevt.returnValue = false; // CANCEL key\r\n\t\treturn false;\r\n\t};\r\n\r\n\r\n/*\r\n * ######################################\r\n *\tUTILITY METHODS\r\n *\tcalled externally or by initButtons\r\n * ######################################\r\n */\r\n\r\n\t/**\r\n\t* Change/reset a pane overflow setting & zIndex to allow popups/drop-downs to work\r\n\t*\r\n\t* @param {Object=}   [el]\t(optional) Can also be 'bound' to a click, mouseOver, or other event\r\n\t*/\r\n\tfunction allowOverflow (el) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tif (this && this.tagName) el = this; // BOUND to element\r\n\t\tvar $P;\r\n\t\tif (isStr(el))\r\n\t\t\t$P = $Ps[el];\r\n\t\telse if ($(el).data(\"layoutRole\"))\r\n\t\t\t$P = $(el);\r\n\t\telse\r\n\t\t\t$(el).parents().each(function(){\r\n\t\t\t\tif ($(this).data(\"layoutRole\")) {\r\n\t\t\t\t\t$P = $(this);\r\n\t\t\t\t\treturn false; // BREAK\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\tif (!$P || !$P.length) return; // INVALID\r\n\r\n\t\tvar\r\n\t\t\tpane\t= $P.data(\"layoutEdge\")\r\n\t\t,\ts\t\t= state[pane]\r\n\t\t;\r\n\r\n\t\t// if pane is already raised, then reset it before doing it again!\r\n\t\t// this would happen if allowOverflow is attached to BOTH the pane and an element \r\n\t\tif (s.cssSaved)\r\n\t\t\tresetOverflow(pane); // reset previous CSS before continuing\r\n\r\n\t\t// if pane is raised by sliding or resizing, or its closed, then abort\r\n\t\tif (s.isSliding || s.isResizing || s.isClosed) {\r\n\t\t\ts.cssSaved = false;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar\r\n\t\t\tnewCSS\t= { zIndex: (options.zIndexes.resizer_normal + 1) }\r\n\t\t,\tcurCSS\t= {}\r\n\t\t,\tof\t\t= $P.css(\"overflow\")\r\n\t\t,\tofX\t\t= $P.css(\"overflowX\")\r\n\t\t,\tofY\t\t= $P.css(\"overflowY\")\r\n\t\t;\r\n\t\t// determine which, if any, overflow settings need to be changed\r\n\t\tif (of != \"visible\") {\r\n\t\t\tcurCSS.overflow = of;\r\n\t\t\tnewCSS.overflow = \"visible\";\r\n\t\t}\r\n\t\tif (ofX && !ofX.match(/(visible|auto)/)) {\r\n\t\t\tcurCSS.overflowX = ofX;\r\n\t\t\tnewCSS.overflowX = \"visible\";\r\n\t\t}\r\n\t\tif (ofY && !ofY.match(/(visible|auto)/)) {\r\n\t\t\tcurCSS.overflowY = ofX;\r\n\t\t\tnewCSS.overflowY = \"visible\";\r\n\t\t}\r\n\r\n\t\t// save the current overflow settings - even if blank!\r\n\t\ts.cssSaved = curCSS;\r\n\r\n\t\t// apply new CSS to raise zIndex and, if necessary, make overflow 'visible'\r\n\t\t$P.css( newCSS );\r\n\r\n\t\t// make sure the zIndex of all other panes is normal\r\n\t\t$.each(_c.allPanes, function(i, p) {\r\n\t\t\tif (p != pane) resetOverflow(p);\r\n\t\t});\r\n\r\n\t};\r\n\t/**\r\n\t* @param {Object=}   [el]\t(optional) Can also be 'bound' to a click, mouseOver, or other event\r\n\t*/\r\n\tfunction resetOverflow (el) {\r\n\t\tif (!isInitialized()) return;\r\n\t\tif (this && this.tagName) el = this; // BOUND to element\r\n\t\tvar $P;\r\n\t\tif (isStr(el))\r\n\t\t\t$P = $Ps[el];\r\n\t\telse if ($(el).data(\"layoutRole\"))\r\n\t\t\t$P = $(el);\r\n\t\telse\r\n\t\t\t$(el).parents().each(function(){\r\n\t\t\t\tif ($(this).data(\"layoutRole\")) {\r\n\t\t\t\t\t$P = $(this);\r\n\t\t\t\t\treturn false; // BREAK\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\tif (!$P || !$P.length) return; // INVALID\r\n\r\n\t\tvar\r\n\t\t\tpane\t= $P.data(\"layoutEdge\")\r\n\t\t,\ts\t\t= state[pane]\r\n\t\t,\tCSS\t\t= s.cssSaved || {}\r\n\t\t;\r\n\t\t// reset the zIndex\r\n\t\tif (!s.isSliding && !s.isResizing)\r\n\t\t\t$P.css(\"zIndex\", options.zIndexes.pane_normal);\r\n\r\n\t\t// reset Overflow - if necessary\r\n\t\t$P.css( CSS );\r\n\r\n\t\t// clear var\r\n\t\ts.cssSaved = false;\r\n\t};\r\n\r\n/*\r\n * #####################\r\n * CREATE/RETURN LAYOUT\r\n * #####################\r\n */\r\n\r\n\t// validate that container exists\r\n\tvar $N = $(this).eq(0); // FIRST matching Container element\r\n\tif (!$N.length) {\r\n\t\treturn _log( options.errors.containerMissing );\r\n\t};\r\n\r\n\t// Users retrieve Instance of a layout with: $N.layout() OR $N.data(\"layout\")\r\n\t// return the Instance-pointer if layout has already been initialized\r\n\tif ($N.data(\"layoutContainer\") && $N.data(\"layout\"))\r\n\t\treturn $N.data(\"layout\"); // cached pointer\r\n\r\n\t// init global vars\r\n\tvar \r\n\t\t$Ps\t= {}\t// Panes x5\t\t- set in initPanes()\r\n\t,\t$Cs\t= {}\t// Content x5\t- set in initPanes()\r\n\t,\t$Rs\t= {}\t// Resizers x4\t- set in initHandles()\r\n\t,\t$Ts\t= {}\t// Togglers x4\t- set in initHandles()\r\n\t,\t$Ms\t= $([])\t// Masks - up to 2 masks per pane (IFRAME + DIV)\r\n\t//\taliases for code brevity\r\n\t,\tsC\t= state.container // alias for easy access to 'container dimensions'\r\n\t,\tsID\t= state.id // alias for unique layout ID/namespace - eg: \"layout435\"\r\n\t;\r\n\r\n\t// create Instance object to expose data & option Properties, and primary action Methods\r\n\tvar Instance = {\r\n\t//\tlayout data\r\n\t\toptions:\t\t\toptions\t\t\t// property - options hash\r\n\t,\tstate:\t\t\t\tstate\t\t\t// property - dimensions hash\r\n\t//\tobject pointers\r\n\t,\tcontainer:\t\t\t$N\t\t\t\t// property - object pointers for layout container\r\n\t,\tpanes:\t\t\t\t$Ps\t\t\t\t// property - object pointers for ALL Panes: panes.north, panes.center\r\n\t,\tcontents:\t\t\t$Cs\t\t\t\t// property - object pointers for ALL Content: contents.north, contents.center\r\n\t,\tresizers:\t\t\t$Rs\t\t\t\t// property - object pointers for ALL Resizers, eg: resizers.north\r\n\t,\ttogglers:\t\t\t$Ts\t\t\t\t// property - object pointers for ALL Togglers, eg: togglers.north\r\n\t//\tborder-pane open/close\r\n\t,\thide:\t\t\t\thide\t\t\t// method - ditto\r\n\t,\tshow:\t\t\t\tshow\t\t\t// method - ditto\r\n\t,\ttoggle:\t\t\t\ttoggle\t\t\t// method - pass a 'pane' (\"north\", \"west\", etc)\r\n\t,\topen:\t\t\t\topen\t\t\t// method - ditto\r\n\t,\tclose:\t\t\t\tclose\t\t\t// method - ditto\r\n\t,\tslideOpen:\t\t\tslideOpen\t\t// method - ditto\r\n\t,\tslideClose:\t\t\tslideClose\t\t// method - ditto\r\n\t,\tslideToggle:\t\tslideToggle\t\t// method - ditto\r\n\t//\tpane actions\r\n\t,\tsetSizeLimits:\t\tsetSizeLimits\t// method - pass a 'pane' - update state min/max data\r\n\t,\t_sizePane:\t\t\tsizePane\t\t// method -intended for user by plugins only!\r\n\t,\tsizePane:\t\t\tmanualSizePane\t// method - pass a 'pane' AND an 'outer-size' in pixels or percent, or 'auto'\r\n\t,\tsizeContent:\t\tsizeContent\t\t// method - pass a 'pane'\r\n\t,\tswapPanes:\t\t\tswapPanes\t\t// method - pass TWO 'panes' - will swap them\r\n\t,\tshowMasks:\t\t\tshowMasks\t\t// method - pass a 'pane' OR list of panes - default = all panes with mask option set\r\n\t,\thideMasks:\t\t\thideMasks\t\t// method - ditto'\r\n\t//\tpane element methods\r\n\t,\tinitContent:\t\tinitContent\t\t// method - ditto\r\n\t,\taddPane:\t\t\taddPane\t\t\t// method - pass a 'pane'\r\n\t,\tremovePane:\t\t\tremovePane\t\t// method - pass a 'pane' to remove from layout, add 'true' to delete the pane-elem\r\n\t,\tcreateChildren:\t\tcreateChildren\t// method - pass a 'pane' and (optional) layout-options (OVERRIDES options[pane].children\r\n\t,\trefreshChildren:\trefreshChildren\t// method - pass a 'pane' and a layout-instance\r\n\t//\tspecial pane option setting\r\n\t,\tenableClosable:\t\tenableClosable\t// method - pass a 'pane'\r\n\t,\tdisableClosable:\tdisableClosable\t// method - ditto\r\n\t,\tenableSlidable:\t\tenableSlidable\t// method - ditto\r\n\t,\tdisableSlidable:\tdisableSlidable\t// method - ditto\r\n\t,\tenableResizable:\tenableResizable\t// method - ditto\r\n\t,\tdisableResizable:\tdisableResizable// method - ditto\r\n\t//\tutility methods for panes\r\n\t,\tallowOverflow:\t\tallowOverflow\t// utility - pass calling element (this)\r\n\t,\tresetOverflow:\t\tresetOverflow\t// utility - ditto\r\n\t//\tlayout control\r\n\t,\tdestroy:\t\t\tdestroy\t\t\t// method - no parameters\r\n\t,\tinitPanes:\t\t\tisInitialized\t// method - no parameters\r\n\t,\tresizeAll:\t\t\tresizeAll\t\t// method - no parameters\r\n\t//\tcallback triggering\r\n\t,\trunCallbacks:\t\t_runCallbacks\t// method - pass evtName & pane (if a pane-event), eg: trigger(\"onopen\", \"west\")\r\n\t//\talias collections of options, state and children - created in addPane and extended elsewhere\r\n\t,\thasParentLayout:\tfalse\t\t\t// set by initContainer()\r\n\t,\tchildren:\t\t\tchildren\t\t// pointers to child-layouts, eg: Instance.children.west.layoutName\r\n\t,\tnorth:\t\t\t\tfalse\t\t\t// alias group: { name: pane, pane: $Ps[pane], options: options[pane], state: state[pane], children: children[pane] }\r\n\t,\tsouth:\t\t\t\tfalse\t\t\t// ditto\r\n\t,\twest:\t\t\t\tfalse\t\t\t// ditto\r\n\t,\teast:\t\t\t\tfalse\t\t\t// ditto\r\n\t,\tcenter:\t\t\t\tfalse\t\t\t// ditto\r\n\t};\r\n\r\n\t// create the border layout NOW\r\n\tif (_create() === 'cancel') // onload_start callback returned false to CANCEL layout creation\r\n\t\treturn null;\r\n\telse // true OR false -- if layout-elements did NOT init (hidden or do not exist), can auto-init later\r\n\t\treturn Instance; // return the Instance object\r\n\r\n}\r\n\r\n\r\n})( jQuery );\r\n// END Layout - keep internal vars internal!\r\n\r\n\r\n\r\n// START Plugins - shared wrapper, no global vars\r\n(function ($) {\r\n\r\n\r\n/**\r\n * jquery.layout.state 1.0\r\n * $Date: 2011-07-16 08:00:00 (Sat, 16 July 2011) $\r\n *\r\n * Copyright (c) 2012 \r\n *   Kevin Dalman (http://allpro.net)\r\n *\r\n * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)\r\n * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.\r\n *\r\n * @requires: UI Layout 1.3.0.rc30.1 or higher\r\n * @requires: $.ui.cookie (above)\r\n *\r\n * @see: http://groups.google.com/group/jquery-ui-layout\r\n */\r\n/*\r\n *\tState-management options stored in options.stateManagement, which includes a .cookie hash\r\n *\tDefault options saves ALL KEYS for ALL PANES, ie: pane.size, pane.isClosed, pane.isHidden\r\n *\r\n *\t// STATE/COOKIE OPTIONS\r\n *\t@example $(el).layout({\r\n\t\t\t\tstateManagement: {\r\n\t\t\t\t\tenabled:\ttrue\r\n\t\t\t\t,\tstateKeys:\t\"east.size,west.size,east.isClosed,west.isClosed\"\r\n\t\t\t\t,\tcookie:\t\t{ name: \"appLayout\", path: \"/\" }\r\n\t\t\t\t}\r\n\t\t\t})\r\n *\t@example $(el).layout({ stateManagement__enabled: true }) // enable auto-state-management using cookies\r\n *\t@example $(el).layout({ stateManagement__cookie: { name: \"appLayout\", path: \"/\" } })\r\n *\t@example $(el).layout({ stateManagement__cookie__name: \"appLayout\", stateManagement__cookie__path: \"/\" })\r\n *\r\n *\t// STATE/COOKIE METHODS\r\n *\t@example myLayout.saveCookie( \"west.isClosed,north.size,south.isHidden\", {expires: 7} );\r\n *\t@example myLayout.loadCookie();\r\n *\t@example myLayout.deleteCookie();\r\n *\t@example var JSON = myLayout.readState();\t// CURRENT Layout State\r\n *\t@example var JSON = myLayout.readCookie();\t// SAVED Layout State (from cookie)\r\n *\t@example var JSON = myLayout.state.stateData;\t// LAST LOADED Layout State (cookie saved in layout.state hash)\r\n *\r\n *\tCUSTOM STATE-MANAGEMENT (eg, saved in a database)\r\n *\t@example var JSON = myLayout.readState( \"west.isClosed,north.size,south.isHidden\" );\r\n *\t@example myLayout.loadState( JSON );\r\n */\r\n\r\n/**\r\n *\tUI COOKIE UTILITY\r\n *\r\n *\tA $.cookie OR $.ui.cookie namespace *should be standard*, but until then...\r\n *\tThis creates $.ui.cookie so Layout does not need the cookie.jquery.js plugin\r\n *\tNOTE: This utility is REQUIRED by the layout.state plugin\r\n *\r\n *\tCookie methods in Layout are created as part of State Management \r\n */\r\nif (!$.ui) $.ui = {};\r\n$.ui.cookie = {\r\n\r\n\t// cookieEnabled is not in DOM specs, but DOES works in all browsers,including IE6\r\n\tacceptsCookies: !!navigator.cookieEnabled\r\n\r\n,\tread: function (name) {\r\n\t\tvar\tc\t\t= document.cookie\r\n\t\t,\tcs\t\t= c ? c.split(';') : []\r\n\t\t,\tpair\t// loop var\r\n\t\t;\r\n\t\tfor (var i=0, n=cs.length; i < n; i++) {\r\n\t\t\tpair = $.trim(cs[i]).split('='); // name=value pair\r\n\t\t\tif (pair[0] == name) // found the layout cookie\r\n\t\t\t\treturn decodeURIComponent(pair[1]);\r\n\t\t}\r\n\t\treturn null;\r\n\t}\r\n\r\n,\twrite: function (name, val, cookieOpts) {\r\n\t\tvar\tparams\t= \"\"\r\n\t\t,\tdate\t= \"\"\r\n\t\t,\tclear\t= false\r\n\t\t,\to\t\t= cookieOpts || {}\r\n\t\t,\tx\t\t= o.expires  || null\r\n\t\t,\tt\t\t= $.type(x)\r\n\t\t;\r\n\t\tif (t === \"date\")\r\n\t\t\tdate = x;\r\n\t\telse if (t === \"string\" && x > 0) {\r\n\t\t\tx = parseInt(x,10);\r\n\t\t\tt = \"number\";\r\n\t\t}\r\n\t\tif (t === \"number\") {\r\n\t\t\tdate = new Date();\r\n\t\t\tif (x > 0)\r\n\t\t\t\tdate.setDate(date.getDate() + x);\r\n\t\t\telse {\r\n\t\t\t\tdate.setFullYear(1970);\r\n\t\t\t\tclear = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (date)\t\tparams += \";expires=\"+ date.toUTCString();\r\n\t\tif (o.path)\t\tparams += \";path=\"+ o.path;\r\n\t\tif (o.domain)\tparams += \";domain=\"+ o.domain;\r\n\t\tif (o.secure)\tparams += \";secure\";\r\n\t\tdocument.cookie = name +\"=\"+ (clear ? \"\" : encodeURIComponent( val )) + params; // write or clear cookie\r\n\t}\r\n\r\n,\tclear: function (name) {\r\n\t\t$.ui.cookie.write(name, \"\", {expires: -1});\r\n\t}\r\n\r\n};\r\n// if cookie.jquery.js is not loaded, create an alias to replicate it\r\n// this may be useful to other plugins or code dependent on that plugin\r\nif (!$.cookie) $.cookie = function (k, v, o) {\r\n\tvar C = $.ui.cookie;\r\n\tif (v === null)\r\n\t\tC.clear(k);\r\n\telse if (v === undefined)\r\n\t\treturn C.read(k);\r\n\telse\r\n\t\tC.write(k, v, o);\r\n};\r\n\r\n\r\n// tell Layout that the state plugin is available\r\n$.layout.plugins.stateManagement = true;\r\n\r\n//\tAdd State-Management options to layout.defaults\r\n$.layout.config.optionRootKeys.push(\"stateManagement\");\r\n$.layout.defaults.stateManagement = {\r\n\tenabled:\t\tfalse\t// true = enable state-management, even if not using cookies\r\n,\tautoSave:\t\ttrue\t// Save a state-cookie when page exits?\r\n,\tautoLoad:\t\ttrue\t// Load the state-cookie when Layout inits?\r\n,\tanimateLoad:\ttrue\t// animate panes when loading state into an active layout\r\n,\tincludeChildren: true\t// recurse into child layouts to include their state as well\r\n\t// List state-data to save - must be pane-specific\r\n,\tstateKeys:\t\"north.size,south.size,east.size,west.size,\"+\r\n\t\t\t\t\"north.isClosed,south.isClosed,east.isClosed,west.isClosed,\"+\r\n\t\t\t\t\"north.isHidden,south.isHidden,east.isHidden,west.isHidden\"\r\n,\tcookie: {\r\n\t\tname:\t\"\"\t// If not specified, will use Layout.name, else just \"Layout\"\r\n\t,\tdomain:\t\"\"\t// blank = current domain\r\n\t,\tpath:\t\"\"\t// blank = current page, \"/\" = entire website\r\n\t,\texpires: \"\"\t// 'days' to keep cookie - leave blank for 'session cookie'\r\n\t,\tsecure:\tfalse\r\n\t}\r\n};\r\n// Set stateManagement as a layout-option, NOT a pane-option\r\n$.layout.optionsMap.layout.push(\"stateManagement\");\r\n\r\n/*\r\n *\tState Management methods\r\n */\r\n$.layout.state = {\r\n\r\n\t/**\r\n\t * Get the current layout state and save it to a cookie\r\n\t *\r\n\t * myLayout.saveCookie( keys, cookieOpts )\r\n\t *\r\n\t * @param {Object}\t\t\tinst\r\n\t * @param {(string|Array)=}\tkeys\r\n\t * @param {Object=}\t\t\tcookieOpts\r\n\t */\r\n\tsaveCookie: function (inst, keys, cookieOpts) {\r\n\t\tvar o\t= inst.options\r\n\t\t,\tsm\t= o.stateManagement\r\n\t\t,\toC\t= $.extend(true, {}, sm.cookie, cookieOpts || null)\r\n\t\t,\tdata = inst.state.stateData = inst.readState( keys || sm.stateKeys ) // read current panes-state\r\n\t\t;\r\n\t\t$.ui.cookie.write( oC.name || o.name || \"Layout\", $.layout.state.encodeJSON(data), oC );\r\n\t\treturn $.extend(true, {}, data); // return COPY of state.stateData data\r\n\t}\r\n\r\n\t/**\r\n\t * Remove the state cookie\r\n\t *\r\n\t * @param {Object}\tinst\r\n\t */\r\n,\tdeleteCookie: function (inst) {\r\n\t\tvar o = inst.options;\r\n\t\t$.ui.cookie.clear( o.stateManagement.cookie.name || o.name || \"Layout\" );\r\n\t}\r\n\r\n\t/**\r\n\t * Read & return data from the cookie - as JSON\r\n\t *\r\n\t * @param {Object}\tinst\r\n\t */\r\n,\treadCookie: function (inst) {\r\n\t\tvar o = inst.options;\r\n\t\tvar c = $.ui.cookie.read( o.stateManagement.cookie.name || o.name || \"Layout\" );\r\n\t\t// convert cookie string back to a hash and return it\r\n\t\treturn c ? $.layout.state.decodeJSON(c) : {};\r\n\t}\r\n\r\n\t/**\r\n\t * Get data from the cookie and USE IT to loadState\r\n\t *\r\n\t * @param {Object}\tinst\r\n\t */\r\n,\tloadCookie: function (inst) {\r\n\t\tvar c = $.layout.state.readCookie(inst); // READ the cookie\r\n\t\tif (c) {\r\n\t\t\tinst.state.stateData = $.extend(true, {}, c); // SET state.stateData\r\n\t\t\tinst.loadState(c); // LOAD the retrieved state\r\n\t\t}\r\n\t\treturn c;\r\n\t}\r\n\r\n\t/**\r\n\t * Update layout options from the cookie, if one exists\r\n\t *\r\n\t * @param {Object}\t\tinst\r\n\t * @param {Object=}\t\tstateData\r\n\t * @param {boolean=}\tanimate\r\n\t */\r\n,\tloadState: function (inst, data, opts) {\r\n\t\tif (!$.isPlainObject( data ) || $.isEmptyObject( data )) return;\r\n\r\n\t\t// normalize data & cache in the state object\r\n\t\tdata = inst.state.stateData = $.layout.transformData( data ); // panes = default subkey\r\n\r\n\t\t// add missing/default state-restore options\r\n\t\tvar smo = inst.options.stateManagement;\r\n\t\topts = $.extend({\r\n\t\t\tanimateLoad:\t\tfalse //smo.animateLoad\r\n\t\t,\tincludeChildren:\tsmo.includeChildren\r\n\t\t}, opts );\r\n\r\n\t\tif (!inst.state.initialized) {\r\n\t\t\t/*\r\n\t\t\t *\tlayout NOT initialized, so just update its options\r\n\t\t\t */\r\n\t\t\t// MUST remove pane.children keys before applying to options\r\n\t\t\t// use a copy so we don't remove keys from original data\r\n\t\t\tvar o = $.extend(true, {}, data);\r\n\t\t\t//delete o.center; // center has no state-data - only children\r\n\t\t\t$.each($.layout.config.allPanes, function (idx, pane) {\r\n\t\t\t\tif (o[pane]) delete o[pane].children;\t\t   \r\n\t\t\t });\r\n\t\t\t// update CURRENT layout-options with saved state data\r\n\t\t\t$.extend(true, inst.options, o);\r\n\t\t}\r\n\t\telse {\r\n\t\t\t/*\r\n\t\t\t *\tlayout already initialized, so modify layout's configuration\r\n\t\t\t */\r\n\t\t\tvar noAnimate = !opts.animateLoad\r\n\t\t\t,\to, c, h, state, open\r\n\t\t\t;\r\n\t\t\t$.each($.layout.config.borderPanes, function (idx, pane) {\r\n\t\t\t\to = data[ pane ];\r\n\t\t\t\tif (!$.isPlainObject( o )) return; // no key, skip pane\r\n\r\n\t\t\t\ts\t= o.size;\r\n\t\t\t\tc\t= o.initClosed;\r\n\t\t\t\th\t= o.initHidden;\r\n\t\t\t\tar\t= o.autoResize\r\n\t\t\t\tstate\t= inst.state[pane];\r\n\t\t\t\topen\t= state.isVisible;\r\n\r\n\t\t\t\t// reset autoResize\r\n\t\t\t\tif (ar)\r\n\t\t\t\t\tstate.autoResize = ar;\r\n\t\t\t\t// resize BEFORE opening\r\n\t\t\t\tif (!open)\r\n\t\t\t\t\tinst._sizePane(pane, s, false, false, false); // false=skipCallback/noAnimation/forceResize\r\n\t\t\t\t// open/close as necessary - DO NOT CHANGE THIS ORDER!\r\n\t\t\t\tif (h === true)\t\t\tinst.hide(pane, noAnimate);\r\n\t\t\t\telse if (c === true)\tinst.close(pane, false, noAnimate);\r\n\t\t\t\telse if (c === false)\tinst.open (pane, false, noAnimate);\r\n\t\t\t\telse if (h === false)\tinst.show (pane, false, noAnimate);\r\n\t\t\t\t// resize AFTER any other actions\r\n\t\t\t\tif (open)\r\n\t\t\t\t\tinst._sizePane(pane, s, false, false, noAnimate); // animate resize if option passed\r\n\t\t\t});\r\n\r\n\t\t\t/*\r\n\t\t\t *\tRECURSE INTO CHILD-LAYOUTS\r\n\t\t\t */\r\n\t\t\tif (opts.includeChildren) {\r\n\t\t\t\tvar paneStateChildren, childState;\r\n\t\t\t\t$.each(inst.children, function (pane, paneChildren) {\r\n\t\t\t\t\tpaneStateChildren = data[pane] ? data[pane].children : 0;\r\n\t\t\t\t\tif (paneStateChildren && paneChildren) {\r\n\t\t\t\t\t\t$.each(paneChildren, function (stateKey, child) {\r\n\t\t\t\t\t\t\tchildState = paneStateChildren[stateKey];\r\n\t\t\t\t\t\t\tif (child && childState)\r\n\t\t\t\t\t\t\t\tchild.loadState( childState );\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Get the *current layout state* and return it as a hash\r\n\t *\r\n\t * @param {Object=}\t\tinst\t// Layout instance to get state for\r\n\t * @param {object=}\t\t[opts]\t// State-Managements override options\r\n\t */\r\n,\treadState: function (inst, opts) {\r\n\t\t// backward compatility\r\n\t\tif ($.type(opts) === 'string') opts = { keys: opts };\r\n\t\tif (!opts) opts = {};\r\n\t\tvar\tsm\t\t= inst.options.stateManagement\r\n\t\t,\tic\t\t= opts.includeChildren\r\n\t\t,\trecurse\t= ic !== undefined ? ic : sm.includeChildren\r\n\t\t,\tkeys\t= opts.stateKeys || sm.stateKeys\r\n\t\t,\talt\t\t= { isClosed: 'initClosed', isHidden: 'initHidden' }\r\n\t\t,\tstate\t= inst.state\r\n\t\t,\tpanes\t= $.layout.config.allPanes\r\n\t\t,\tdata\t= {}\r\n\t\t,\tpair, pane, key, val\r\n\t\t,\tps, pC, child, array, count, branch\r\n\t\t;\r\n\t\tif ($.isArray(keys)) keys = keys.join(\",\");\r\n\t\t// convert keys to an array and change delimiters from '__' to '.'\r\n\t\tkeys = keys.replace(/__/g, \".\").split(',');\r\n\t\t// loop keys and create a data hash\r\n\t\tfor (var i=0, n=keys.length; i < n; i++) {\r\n\t\t\tpair = keys[i].split(\".\");\r\n\t\t\tpane = pair[0];\r\n\t\t\tkey  = pair[1];\r\n\t\t\tif ($.inArray(pane, panes) < 0) continue; // bad pane!\r\n\t\t\tval = state[ pane ][ key ];\r\n\t\t\tif (val == undefined) continue;\r\n\t\t\tif (key==\"isClosed\" && state[pane][\"isSliding\"])\r\n\t\t\t\tval = true; // if sliding, then *really* isClosed\r\n\t\t\t( data[pane] || (data[pane]={}) )[ alt[key] ? alt[key] : key ] = val;\r\n\t\t}\r\n\r\n\t\t// recurse into the child-layouts for each pane\r\n\t\tif (recurse) {\r\n\t\t\t$.each(panes, function (idx, pane) {\r\n\t\t\t\tpC = inst.children[pane];\r\n\t\t\t\tps = state.stateData[pane];\r\n\t\t\t\tif ($.isPlainObject( pC ) && !$.isEmptyObject( pC )) {\r\n\t\t\t\t\t// ensure a key exists for this 'pane', eg: branch = data.center\r\n\t\t\t\t\tbranch = data[pane] || (data[pane] = {});\r\n\t\t\t\t\tif (!branch.children) branch.children = {};\r\n\t\t\t\t\t$.each( pC, function (key, child) {\r\n\t\t\t\t\t\t// ONLY read state from an initialize layout\r\n\t\t\t\t\t\tif ( child.state.initialized )\r\n\t\t\t\t\t\t\tbranch.children[ key ] = $.layout.state.readState( child );\r\n\t\t\t\t\t\t// if we have PREVIOUS (onLoad) state for this child-layout, KEEP IT!\r\n\t\t\t\t\t\telse if ( ps && ps.children && ps.children[ key ] ) {\r\n\t\t\t\t\t\t\tbranch.children[ key ] = $.extend(true, {}, ps.children[ key ] );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\treturn data;\r\n\t}\r\n\r\n\t/**\r\n\t *\tStringify a JSON hash so can save in a cookie or db-field\r\n\t */\r\n,\tencodeJSON: function (JSON) {\r\n\t\treturn parse(JSON);\r\n\t\tfunction parse (h) {\r\n\t\t\tvar D=[], i=0, k, v, t // k = key, v = value\r\n\t\t\t,\ta = $.isArray(h)\r\n\t\t\t;\r\n\t\t\tfor (k in h) {\r\n\t\t\t\tv = h[k];\r\n\t\t\t\tt = typeof v;\r\n\t\t\t\tif (t == 'string')\t\t// STRING - add quotes\r\n\t\t\t\t\tv = '\"'+ v +'\"';\r\n\t\t\t\telse if (t == 'object')\t// SUB-KEY - recurse into it\r\n\t\t\t\t\tv = parse(v);\r\n\t\t\t\tD[i++] = (!a ? '\"'+ k +'\":' : '') + v;\r\n\t\t\t}\r\n\t\t\treturn (a ? '[' : '{') + D.join(',') + (a ? ']' : '}');\r\n\t\t};\r\n\t}\r\n\r\n\t/**\r\n\t *\tConvert stringified JSON back to a hash object\r\n\t *\t@see\t\t$.parseJSON(), adding in jQuery 1.4.1\r\n\t */\r\n,\tdecodeJSON: function (str) {\r\n\t\ttry { return $.parseJSON ? $.parseJSON(str) : window[\"eval\"](\"(\"+ str +\")\") || {}; }\r\n\t\tcatch (e) { return {}; }\r\n\t}\r\n\r\n\r\n,\t_create: function (inst) {\r\n\t\tvar _\t= $.layout.state\r\n\t\t,\to\t= inst.options\r\n\t\t,\tsm\t= o.stateManagement\r\n\t\t;\r\n\t\t//\tADD State-Management plugin methods to inst\r\n\t\t $.extend( inst, {\r\n\t\t//\treadCookie - update options from cookie - returns hash of cookie data\r\n\t\t\treadCookie:\t\tfunction () { return _.readCookie(inst); }\r\n\t\t//\tdeleteCookie\r\n\t\t,\tdeleteCookie:\tfunction () { _.deleteCookie(inst); }\r\n\t\t//\tsaveCookie - optionally pass keys-list and cookie-options (hash)\r\n\t\t,\tsaveCookie:\t\tfunction (keys, cookieOpts) { return _.saveCookie(inst, keys, cookieOpts); }\r\n\t\t//\tloadCookie - readCookie and use to loadState() - returns hash of cookie data\r\n\t\t,\tloadCookie:\t\tfunction () { return _.loadCookie(inst); }\r\n\t\t//\tloadState - pass a hash of state to use to update options\r\n\t\t,\tloadState:\t\tfunction (stateData, opts) { _.loadState(inst, stateData, opts); }\r\n\t\t//\treadState - returns hash of current layout-state\r\n\t\t,\treadState:\t\tfunction (keys) { return _.readState(inst, keys); }\r\n\t\t//\tadd JSON utility methods too...\r\n\t\t,\tencodeJSON:\t\t_.encodeJSON\r\n\t\t,\tdecodeJSON:\t\t_.decodeJSON\r\n\t\t});\r\n\r\n\t\t// init state.stateData key, even if plugin is initially disabled\r\n\t\tinst.state.stateData = {};\r\n\r\n\t\t// autoLoad MUST BE one of: data-array, data-hash, callback-function, or TRUE\r\n\t\tif ( !sm.autoLoad ) return;\r\n\r\n\t\t//\tWhen state-data exists in the autoLoad key USE IT,\r\n\t\t//\teven if stateManagement.enabled == false\r\n\t\tif ($.isPlainObject( sm.autoLoad )) {\r\n\t\t\tif (!$.isEmptyObject( sm.autoLoad )) {\r\n\t\t\t\tinst.loadState( sm.autoLoad );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( sm.enabled ) {\r\n\t\t\t// update the options from cookie or callback\r\n\t\t\t// if options is a function, call it to get stateData\r\n\t\t\tif ($.isFunction( sm.autoLoad )) {\r\n\t\t\t\tvar d = {};\r\n\t\t\t\ttry {\r\n\t\t\t\t\td = sm.autoLoad( inst, inst.state, inst.options, inst.options.name || '' ); // try to get data from fn\r\n\t\t\t\t} catch (e) {}\r\n\t\t\t\tif (d && $.isPlainObject( d ) && !$.isEmptyObject( d ))\r\n\t\t\t\t\tinst.loadState(d);\r\n\t\t\t}\r\n\t\t\telse // any other truthy value will trigger loadCookie\r\n\t\t\t\tinst.loadCookie();\r\n\t\t}\r\n\t}\r\n\r\n,\t_unload: function (inst) {\r\n\t\tvar sm = inst.options.stateManagement;\r\n\t\tif (sm.enabled && sm.autoSave) {\r\n\t\t\t// if options is a function, call it to save the stateData\r\n\t\t\tif ($.isFunction( sm.autoSave )) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tsm.autoSave( inst, inst.state, inst.options, inst.options.name || '' ); // try to get data from fn\r\n\t\t\t\t} catch (e) {}\r\n\t\t\t}\r\n\t\t\telse // any truthy value will trigger saveCookie\r\n\t\t\t\tinst.saveCookie();\r\n\t\t}\r\n\t}\r\n\r\n};\r\n\r\n// add state initialization method to Layout's onCreate array of functions\r\n$.layout.onCreate.push( $.layout.state._create );\r\n$.layout.onUnload.push( $.layout.state._unload );\r\n\r\n\r\n\r\n\r\n/**\r\n * jquery.layout.buttons 1.0\r\n * $Date: 2011-07-16 08:00:00 (Sat, 16 July 2011) $\r\n *\r\n * Copyright (c) 2012 \r\n *   Kevin Dalman (http://allpro.net)\r\n *\r\n * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)\r\n * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.\r\n *\r\n * @requires: UI Layout 1.3.0.rc30.1 or higher\r\n *\r\n * @see: http://groups.google.com/group/jquery-ui-layout\r\n *\r\n * Docs: [ to come ]\r\n * Tips: [ to come ]\r\n */\r\n\r\n// tell Layout that the state plugin is available\r\n$.layout.plugins.buttons = true;\r\n\r\n//\tAdd buttons options to layout.defaults\r\n$.layout.defaults.autoBindCustomButtons = false;\r\n// Specify autoBindCustomButtons as a layout-option, NOT a pane-option\r\n$.layout.optionsMap.layout.push(\"autoBindCustomButtons\");\r\n\r\n/*\r\n *\tButton methods\r\n */\r\n$.layout.buttons = {\r\n\r\n\t/**\r\n\t* Searches for .ui-layout-button-xxx elements and auto-binds them as layout-buttons\r\n\t*\r\n\t* @see  _create()\r\n\t*\r\n\t* @param  {Object}\t\tinst\tLayout Instance object\r\n\t*/\r\n\tinit: function (inst) {\r\n\t\tvar pre\t\t= \"ui-layout-button-\"\r\n\t\t,\tlayout\t= inst.options.name || \"\"\r\n\t\t,\tname;\r\n\t\t$.each(\"toggle,open,close,pin,toggle-slide,open-slide\".split(\",\"), function (i, action) {\r\n\t\t\t$.each($.layout.config.borderPanes, function (ii, pane) {\r\n\t\t\t\t$(\".\"+pre+action+\"-\"+pane).each(function(){\r\n\t\t\t\t\t// if button was previously 'bound', data.layoutName was set, but is blank if layout has no 'name'\r\n\t\t\t\t\tname = $(this).data(\"layoutName\") || $(this).attr(\"layoutName\");\r\n\t\t\t\t\tif (name == undefined || name === layout)\r\n\t\t\t\t\t\tinst.bindButton(this, action, pane);\r\n\t\t\t\t});\r\n\t\t\t});\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t* Helper function to validate params received by addButton utilities\r\n\t*\r\n\t* Two classes are added to the element, based on the buttonClass...\r\n\t* The type of button is appended to create the 2nd className:\r\n\t*  - ui-layout-button-pin\t\t// action btnClass\r\n\t*  - ui-layout-button-pin-west\t// action btnClass + pane\r\n\t*  - ui-layout-button-toggle\r\n\t*  - ui-layout-button-open\r\n\t*  - ui-layout-button-close\r\n\t*\r\n\t* @param {Object}\t\t\tinst\t\tLayout Instance object\r\n\t* @param {(string|!Object)}\tselector\tjQuery selector (or element) for button, eg: \".ui-layout-north .toggle-button\"\r\n\t* @param {string}   \t\tpane \t\tName of the pane the button is for: 'north', 'south', etc.\r\n\t*\r\n\t* @return {Array.<Object>}\tIf both params valid, the element matching 'selector' in a jQuery wrapper - otherwise returns null\r\n\t*/\r\n,\tget: function (inst, selector, pane, action) {\r\n\t\tvar $E\t= $(selector)\r\n\t\t,\to\t= inst.options\r\n\t\t,\terr\t= o.errors.addButtonError\r\n\t\t;\r\n\t\tif (!$E.length) { // element not found\r\n\t\t\t$.layout.msg(err +\" \"+ o.errors.selector +\": \"+ selector, true);\r\n\t\t}\r\n\t\telse if ($.inArray(pane, $.layout.config.borderPanes) < 0) { // invalid 'pane' sepecified\r\n\t\t\t$.layout.msg(err +\" \"+ o.errors.pane +\": \"+ pane, true);\r\n\t\t\t$E = $(\"\");  // NO BUTTON\r\n\t\t}\r\n\t\telse { // VALID\r\n\t\t\tvar btn = o[pane].buttonClass +\"-\"+ action;\r\n\t\t\t$E\t.addClass( btn +\" \"+ btn +\"-\"+ pane )\r\n\t\t\t\t.data(\"layoutName\", o.name); // add layout identifier - even if blank!\r\n\t\t}\r\n\t\treturn $E;\r\n\t}\r\n\r\n\r\n\t/**\r\n\t* NEW syntax for binding layout-buttons - will eventually replace addToggle, addOpen, etc.\r\n\t*\r\n\t* @param {Object}\t\t\tinst\t\tLayout Instance object\r\n\t* @param {(string|!Object)}\tselector\tjQuery selector (or element) for button, eg: \".ui-layout-north .toggle-button\"\r\n\t* @param {string}\t\t\taction\r\n\t* @param {string}\t\t\tpane\r\n\t*/\r\n,\tbind: function (inst, selector, action, pane) {\r\n\t\tvar _ = $.layout.buttons;\r\n\t\tswitch (action.toLowerCase()) {\r\n\t\t\tcase \"toggle\":\t\t\t_.addToggle\t(inst, selector, pane); break;\t\r\n\t\t\tcase \"open\":\t\t\t_.addOpen\t(inst, selector, pane); break;\r\n\t\t\tcase \"close\":\t\t\t_.addClose\t(inst, selector, pane); break;\r\n\t\t\tcase \"pin\":\t\t\t\t_.addPin\t(inst, selector, pane); break;\r\n\t\t\tcase \"toggle-slide\":\t_.addToggle\t(inst, selector, pane, true); break;\t\r\n\t\t\tcase \"open-slide\":\t\t_.addOpen\t(inst, selector, pane, true); break;\r\n\t\t}\r\n\t\treturn inst;\r\n\t}\r\n\r\n\t/**\r\n\t* Add a custom Toggler button for a pane\r\n\t*\r\n\t* @param {Object}\t\t\tinst\t\tLayout Instance object\r\n\t* @param {(string|!Object)}\tselector\tjQuery selector (or element) for button, eg: \".ui-layout-north .toggle-button\"\r\n\t* @param {string}  \t\t\tpane \t\tName of the pane the button is for: 'north', 'south', etc.\r\n\t* @param {boolean=}\t\t\tslide \t\ttrue = slide-open, false = pin-open\r\n\t*/\r\n,\taddToggle: function (inst, selector, pane, slide) {\r\n\t\t$.layout.buttons.get(inst, selector, pane, \"toggle\")\r\n\t\t\t.click(function(evt){\r\n\t\t\t\tinst.toggle(pane, !!slide);\r\n\t\t\t\tevt.stopPropagation();\r\n\t\t\t});\r\n\t\treturn inst;\r\n\t}\r\n\r\n\t/**\r\n\t* Add a custom Open button for a pane\r\n\t*\r\n\t* @param {Object}\t\t\tinst\t\tLayout Instance object\r\n\t* @param {(string|!Object)}\tselector\tjQuery selector (or element) for button, eg: \".ui-layout-north .toggle-button\"\r\n\t* @param {string}\t\t\tpane \t\tName of the pane the button is for: 'north', 'south', etc.\r\n\t* @param {boolean=}\t\t\tslide \t\ttrue = slide-open, false = pin-open\r\n\t*/\r\n,\taddOpen: function (inst, selector, pane, slide) {\r\n\t\t$.layout.buttons.get(inst, selector, pane, \"open\")\r\n\t\t\t.attr(\"title\", inst.options[pane].tips.Open)\r\n\t\t\t.click(function (evt) {\r\n\t\t\t\tinst.open(pane, !!slide);\r\n\t\t\t\tevt.stopPropagation();\r\n\t\t\t});\r\n\t\treturn inst;\r\n\t}\r\n\r\n\t/**\r\n\t* Add a custom Close button for a pane\r\n\t*\r\n\t* @param {Object}\t\t\tinst\t\tLayout Instance object\r\n\t* @param {(string|!Object)}\tselector\tjQuery selector (or element) for button, eg: \".ui-layout-north .toggle-button\"\r\n\t* @param {string}   \t\tpane \t\tName of the pane the button is for: 'north', 'south', etc.\r\n\t*/\r\n,\taddClose: function (inst, selector, pane) {\r\n\t\t$.layout.buttons.get(inst, selector, pane, \"close\")\r\n\t\t\t.attr(\"title\", inst.options[pane].tips.Close)\r\n\t\t\t.click(function (evt) {\r\n\t\t\t\tinst.close(pane);\r\n\t\t\t\tevt.stopPropagation();\r\n\t\t\t});\r\n\t\treturn inst;\r\n\t}\r\n\r\n\t/**\r\n\t* Add a custom Pin button for a pane\r\n\t*\r\n\t* Four classes are added to the element, based on the paneClass for the associated pane...\r\n\t* Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin:\r\n\t*  - ui-layout-pane-pin\r\n\t*  - ui-layout-pane-west-pin\r\n\t*  - ui-layout-pane-pin-up\r\n\t*  - ui-layout-pane-west-pin-up\r\n\t*\r\n\t* @param {Object}\t\t\tinst\t\tLayout Instance object\r\n\t* @param {(string|!Object)}\tselector\tjQuery selector (or element) for button, eg: \".ui-layout-north .toggle-button\"\r\n\t* @param {string}   \t\tpane \t\tName of the pane the pin is for: 'north', 'south', etc.\r\n\t*/\r\n,\taddPin: function (inst, selector, pane) {\r\n\t\tvar\t_\t= $.layout.buttons\r\n\t\t,\t$E\t= _.get(inst, selector, pane, \"pin\");\r\n\t\tif ($E.length) {\r\n\t\t\tvar s = inst.state[pane];\r\n\t\t\t$E.click(function (evt) {\r\n\t\t\t\t_.setPinState(inst, $(this), pane, (s.isSliding || s.isClosed));\r\n\t\t\t\tif (s.isSliding || s.isClosed) inst.open( pane ); // change from sliding to open\r\n\t\t\t\telse inst.close( pane ); // slide-closed\r\n\t\t\t\tevt.stopPropagation();\r\n\t\t\t});\r\n\t\t\t// add up/down pin attributes and classes\r\n\t\t\t_.setPinState(inst, $E, pane, (!s.isClosed && !s.isSliding));\r\n\t\t\t// add this pin to the pane data so we can 'sync it' automatically\r\n\t\t\t// PANE.pins key is an array so we can store multiple pins for each pane\r\n\t\t\ts.pins.push( selector ); // just save the selector string\r\n\t\t}\r\n\t\treturn inst;\r\n\t}\r\n\r\n\t/**\r\n\t* Change the class of the pin button to make it look 'up' or 'down'\r\n\t*\r\n\t* @see  addPin(), syncPins()\r\n\t*\r\n\t* @param {Object}\t\t\tinst\tLayout Instance object\r\n\t* @param {Array.<Object>}\t$Pin\tThe pin-span element in a jQuery wrapper\r\n\t* @param {string}\t\t\tpane\tThese are the params returned to callbacks by layout()\r\n\t* @param {boolean}\t\t\tdoPin\ttrue = set the pin 'down', false = set it 'up'\r\n\t*/\r\n,\tsetPinState: function (inst, $Pin, pane, doPin) {\r\n\t\tvar updown = $Pin.attr(\"pin\");\r\n\t\tif (updown && doPin === (updown==\"down\")) return; // already in correct state\r\n\t\tvar\r\n\t\t\to\t\t= inst.options[pane]\r\n\t\t,\tpin\t\t= o.buttonClass +\"-pin\"\r\n\t\t,\tside\t= pin +\"-\"+ pane\r\n\t\t,\tUP\t\t= pin +\"-up \"+\tside +\"-up\"\r\n\t\t,\tDN\t\t= pin +\"-down \"+side +\"-down\"\r\n\t\t;\r\n\t\t$Pin\r\n\t\t\t.attr(\"pin\", doPin ? \"down\" : \"up\") // logic\r\n\t\t\t.attr(\"title\", doPin ? o.tips.Unpin : o.tips.Pin)\r\n\t\t\t.removeClass( doPin ? UP : DN ) \r\n\t\t\t.addClass( doPin ? DN : UP ) \r\n\t\t;\r\n\t}\r\n\r\n\t/**\r\n\t* INTERNAL function to sync 'pin buttons' when pane is opened or closed\r\n\t* Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes\r\n\t*\r\n\t* @see  open(), close()\r\n\t*\r\n\t* @param {Object}\t\t\tinst\tLayout Instance object\r\n\t* @param {string}\tpane\tThese are the params returned to callbacks by layout()\r\n\t* @param {boolean}\tdoPin\tTrue means set the pin 'down', False means 'up'\r\n\t*/\r\n,\tsyncPinBtns: function (inst, pane, doPin) {\r\n\t\t// REAL METHOD IS _INSIDE_ LAYOUT - THIS IS HERE JUST FOR REFERENCE\r\n\t\t$.each(inst.state[pane].pins, function (i, selector) {\r\n\t\t\t$.layout.buttons.setPinState(inst, $(selector), pane, doPin);\r\n\t\t});\r\n\t}\r\n\r\n\r\n,\t_load: function (inst) {\r\n\t\tvar\t_\t= $.layout.buttons;\r\n\t\t// ADD Button methods to Layout Instance\r\n\t\t// Note: sel = jQuery Selector string\r\n\t\t$.extend( inst, {\r\n\t\t\tbindButton:\t\tfunction (sel, action, pane) { return _.bind(inst, sel, action, pane); }\r\n\t\t//\tDEPRECATED METHODS\r\n\t\t,\taddToggleBtn:\tfunction (sel, pane, slide) { return _.addToggle(inst, sel, pane, slide); }\r\n\t\t,\taddOpenBtn:\t\tfunction (sel, pane, slide) { return _.addOpen(inst, sel, pane, slide); }\r\n\t\t,\taddCloseBtn:\tfunction (sel, pane) { return _.addClose(inst, sel, pane); }\r\n\t\t,\taddPinBtn:\t\tfunction (sel, pane) { return _.addPin(inst, sel, pane); }\r\n\t\t});\r\n\r\n\t\t// init state array to hold pin-buttons\r\n\t\tfor (var i=0; i<4; i++) {\r\n\t\t\tvar pane = $.layout.config.borderPanes[i];\r\n\t\t\tinst.state[pane].pins = [];\r\n\t\t}\r\n\r\n\t\t// auto-init buttons onLoad if option is enabled\r\n\t\tif ( inst.options.autoBindCustomButtons )\r\n\t\t\t_.init(inst);\r\n\t}\r\n\r\n,\t_unload: function (inst) {\r\n\t\t// TODO: unbind all buttons???\r\n\t}\r\n\r\n};\r\n\r\n// add initialization method to Layout's onLoad array of functions\r\n$.layout.onLoad.push(  $.layout.buttons._load );\r\n//$.layout.onUnload.push( $.layout.buttons._unload );\r\n\r\n\r\n\r\n/**\r\n * jquery.layout.browserZoom 1.0\r\n * $Date: 2011-12-29 08:00:00 (Thu, 29 Dec 2011) $\r\n *\r\n * Copyright (c) 2012 \r\n *   Kevin Dalman (http://allpro.net)\r\n *\r\n * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)\r\n * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.\r\n *\r\n * @requires: UI Layout 1.3.0.rc30.1 or higher\r\n *\r\n * @see: http://groups.google.com/group/jquery-ui-layout\r\n *\r\n * TODO: Extend logic to handle other problematic zooming in browsers\r\n * TODO: Add hotkey/mousewheel bindings to _instantly_ respond to these zoom event\r\n */\r\n\r\n// tell Layout that the plugin is available\r\n$.layout.plugins.browserZoom = true;\r\n\r\n$.layout.defaults.browserZoomCheckInterval = 1000;\r\n$.layout.optionsMap.layout.push(\"browserZoomCheckInterval\");\r\n\r\n/*\r\n *\tbrowserZoom methods\r\n */\r\n$.layout.browserZoom = {\r\n\r\n\t_init: function (inst) {\r\n\t\t// abort if browser does not need this check\r\n\t\tif ($.layout.browserZoom.ratio() !== false)\r\n\t\t\t$.layout.browserZoom._setTimer(inst);\r\n\t}\r\n\r\n,\t_setTimer: function (inst) {\r\n\t\t// abort if layout destroyed or browser does not need this check\r\n\t\tif (inst.destroyed) return;\r\n\t\tvar o\t= inst.options\r\n\t\t,\ts\t= inst.state\r\n\t\t//\tdon't need check if inst has parentLayout, but check occassionally in case parent destroyed!\r\n\t\t//\tMINIMUM 100ms interval, for performance\r\n\t\t,\tms\t= inst.hasParentLayout ?  5000 : Math.max( o.browserZoomCheckInterval, 100 )\r\n\t\t;\r\n\t\t// set the timer\r\n\t\tsetTimeout(function(){\r\n\t\t\tif (inst.destroyed || !o.resizeWithWindow) return;\r\n\t\t\tvar d = $.layout.browserZoom.ratio();\r\n\t\t\tif (d !== s.browserZoom) {\r\n\t\t\t\ts.browserZoom = d;\r\n\t\t\t\tinst.resizeAll();\r\n\t\t\t}\r\n\t\t\t// set a NEW timeout\r\n\t\t\t$.layout.browserZoom._setTimer(inst);\r\n\t\t}\r\n\t\t,\tms );\r\n\t}\r\n\r\n,\tratio: function () {\r\n\t\tvar w\t= window\r\n\t\t,\ts\t= screen\r\n\t\t,\td\t= document\r\n\t\t,\tdE\t= d.documentElement || d.body\r\n\t\t,\tb\t= $.layout.browser\r\n\t\t,\tv\t= b.version\r\n\t\t,\tr, sW, cW\r\n\t\t;\r\n\t\t// we can ignore all browsers that fire window.resize event onZoom\r\n\t\tif ((b.msie && v > 8)\r\n\t\t||\t!b.msie\r\n\t\t) return false; // don't need to track zoom\r\n\r\n\t\tif (s.deviceXDPI && s.systemXDPI) // syntax compiler hack\r\n\t\t\treturn calc(s.deviceXDPI, s.systemXDPI);\r\n\t\t// everything below is just for future reference!\r\n\t\tif (b.webkit && (r = d.body.getBoundingClientRect))\r\n\t\t\treturn calc((r.left - r.right), d.body.offsetWidth);\r\n\t\tif (b.webkit && (sW = w.outerWidth))\r\n\t\t\treturn calc(sW, w.innerWidth);\r\n\t\tif ((sW = s.width) && (cW = dE.clientWidth))\r\n\t\t\treturn calc(sW, cW);\r\n\t\treturn false; // no match, so cannot - or don't need to - track zoom\r\n\r\n\t\tfunction calc (x,y) { return (parseInt(x,10) / parseInt(y,10) * 100).toFixed(); }\r\n\t}\r\n\r\n};\r\n// add initialization method to Layout's onLoad array of functions\r\n$.layout.onReady.push( $.layout.browserZoom._init );\r\n\r\n\r\n})( jQuery );\n"
  },
  {
    "path": "packages/non-core/jquery-layout/package.js",
    "content": "// XXX should probably nudge people toward the CSS Flexible Box Model\n// flexie, rather than this\n\nPackage.describe({\n  name: \"jquery-layout\",\n  summary: \"Deprecated package for JS layout\",\n  version: \"1.0.3\"\n});\n\nPackage.onUse(function (api) {\n  api.versionsFrom(\"1.0\");\n  api.use('jquery');\n  api.addFiles('jquery.layout.js', 'client');\n});\n"
  },
  {
    "path": "packages/non-core/npm-bcrypt/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/non-core/npm-bcrypt/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/non-core/npm-bcrypt/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/non-core/npm-bcrypt/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"bcrypt\": {\n      \"version\": \"0.8.6\",\n      \"resolved\": \"https://registry.npmjs.org/bcrypt/-/bcrypt-0.8.6.tgz\",\n      \"from\": \"bcrypt@0.8.6\",\n      \"dependencies\": {\n        \"bindings\": {\n          \"version\": \"1.2.1\",\n          \"resolved\": \"https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz\",\n          \"from\": \"bindings@1.2.1\"\n        },\n        \"nan\": {\n          \"version\": \"2.2.1\",\n          \"resolved\": \"https://registry.npmjs.org/nan/-/nan-2.2.1.tgz\",\n          \"from\": \"nan@2.2.1\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/non-core/npm-bcrypt/.versions",
    "content": "meteor@1.1.14-rc.0\nnpm-bcrypt@0.8.5\nunderscore@1.0.8-rc.0\n"
  },
  {
    "path": "packages/non-core/npm-bcrypt/package.js",
    "content": "Package.describe({\n  summary: \"Wrapper around the bcrypt npm package\",\n  version: '0.8.6_1',\n  documentation: null\n});\n\nNpm.depends({\n  bcrypt: '0.8.6'\n});\n\nPackage.onUse(function (api) {\n  api.export('NpmModuleBcrypt', 'server');\n  api.addFiles('wrapper.js', 'server');\n});\n"
  },
  {
    "path": "packages/non-core/npm-bcrypt/wrapper.js",
    "content": "NpmModuleBcrypt = Npm.require('bcrypt');\n"
  },
  {
    "path": "packages/non-core/npm-node-aes-gcm/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/non-core/npm-node-aes-gcm/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/non-core/npm-node-aes-gcm/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/non-core/npm-node-aes-gcm/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"node-aes-gcm\": {\n      \"version\": \"0.1.5\",\n      \"resolved\": \"https://registry.npmjs.org/node-aes-gcm/-/node-aes-gcm-0.1.5.tgz\",\n      \"from\": \"node-aes-gcm@0.1.5\",\n      \"dependencies\": {\n        \"nan\": {\n          \"version\": \"1.9.0\",\n          \"resolved\": \"https://registry.npmjs.org/nan/-/nan-1.9.0.tgz\",\n          \"from\": \"nan@>=1.7.0 <2.0.0\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/non-core/npm-node-aes-gcm/.versions",
    "content": "meteor@1.1.15\nnpm-node-aes-gcm@0.1.5_1\nunderscore@1.0.9\n"
  },
  {
    "path": "packages/non-core/npm-node-aes-gcm/README.md",
    "content": "## Using this package on Windows\n\nThis package uses the [node-aes-gcm](https://github.com/xorbit/node-aes-gcm) NPM module, which requires you to have OpenSSL installed on your system to run. To install OpenSSL on Windows, use one of the binaries on [this page](http://slproweb.com/products/Win32OpenSSL.html). Don't forget to install the Visual Studio 2008 redistributables if you don't have them yet.\n"
  },
  {
    "path": "packages/non-core/npm-node-aes-gcm/package.js",
    "content": "Package.describe({\n  summary: \"Wrapper around the node-aes-gcm npm package\",\n  version: '0.1.5_1',\n  documentation: null\n});\n\nNpm.depends({\n  'node-aes-gcm': '0.1.5'\n});\n\nPackage.onUse(function (api) {\n  api.export('NpmModuleNodeAesGcm', 'server');\n  api.addFiles('wrapper.js', 'server');\n});\n"
  },
  {
    "path": "packages/non-core/npm-node-aes-gcm/wrapper.js",
    "content": "try {\n  NpmModuleNodeAesGcm = Npm.require('node-aes-gcm');\n} catch (err) {\n  if (process.platform === \"win32\" &&\n    err.message.match(/specified module could not be found/)) {\n    // the user probably doesn't have OpenSSL installed.\n    throw new Error(\n\"Couldn't load the package 'npm-node-aes-gcm'. This is probably because you \" +\n\"don't have OpenSSL installed. See the README for details and directions: \" +\n\"https://github.com/meteor/meteor/blob/devel/packages/non-core/npm-node-aes-gcm/README.md\");\n  } else {\n    throw err;\n  }\n}"
  },
  {
    "path": "packages/npm-mongo/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/npm-mongo/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/npm-mongo/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"mongodb\": {\n      \"version\": \"1.4.39\",\n      \"resolved\": \"https://github.com/meteor/node-mongodb-native/tarball/9c7441e87fbec059dc0b70bbb70734404b994d71\",\n      \"from\": \"https://github.com/meteor/node-mongodb-native/tarball/9c7441e87fbec059dc0b70bbb70734404b994d71\",\n      \"dependencies\": {\n        \"bson\": {\n          \"version\": \"0.2.18\",\n          \"resolved\": \"https://github.com/meteor/js-bson/tarball/0103b53\",\n          \"from\": \"https://github.com/meteor/js-bson/tarball/0103b53\",\n          \"dependencies\": {\n            \"nan\": {\n              \"version\": \"1.5.1\",\n              \"resolved\": \"https://registry.npmjs.org/nan/-/nan-1.5.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/nan/-/nan-1.5.1.tgz\"\n            }\n          }\n        },\n        \"readable-stream\": {\n          \"version\": \"2.0.6\",\n          \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz\",\n          \"from\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz\",\n          \"dependencies\": {\n            \"core-util-is\": {\n              \"version\": \"1.0.2\",\n              \"resolved\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz\",\n              \"from\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz\"\n            },\n            \"inherits\": {\n              \"version\": \"2.0.1\",\n              \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\"\n            },\n            \"isarray\": {\n              \"version\": \"1.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz\"\n            },\n            \"process-nextick-args\": {\n              \"version\": \"1.0.6\",\n              \"resolved\": \"https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz\",\n              \"from\": \"https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz\"\n            },\n            \"string_decoder\": {\n              \"version\": \"0.10.31\",\n              \"resolved\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\",\n              \"from\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\"\n            },\n            \"util-deprecate\": {\n              \"version\": \"1.0.2\",\n              \"resolved\": \"https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz\",\n              \"from\": \"https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz\"\n            }\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/npm-mongo/package.js",
    "content": "// This has been moved out of the `mongo` package so it can be used by the tool\n// via isopacket, without having to also load ddp-server.\n\nPackage.describe({\n  summary: \"Wrapper around the mongo npm package\",\n  version: '1.4.44_1',\n  documentation: null\n});\n\nNpm.depends({\n  // 1.4.32 (and bson 0.2.18) with optional native dependencies (bson native\n  // piece and kerberos) ripped out, which means we don't have to do the\n  // publish-for-arch dance every time we make a Meteor release.\n  // XXX move the npm dependency into a non-core versioned package and allow\n  //     it to use C++ bson\n  mongodb: \"https://github.com/meteor/node-mongodb-native/tarball/9c7441e87fbec059dc0b70bbb70734404b994d71\"\n});\n\nPackage.onUse(function (api) {\n  api.export(['NpmModuleMongodb', 'NpmModuleMongodbVersion'], 'server');\n  api.addFiles('wrapper.js', 'server');\n});\n"
  },
  {
    "path": "packages/npm-mongo/wrapper.js",
    "content": "NpmModuleMongodb = Npm.require('mongodb');\nNpmModuleMongodbVersion = Npm.require('mongodb/package.json').version;\n"
  },
  {
    "path": "packages/oauth/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/oauth/README.md",
    "content": "# oauth\n\nCommon functionality for OAuth clients. See the [project\npage](https://www.meteor.com/accounts) on Meteor Accounts for more\ndetails."
  },
  {
    "path": "packages/oauth/deprecated.js",
    "content": "// XXX COMPAT WITH 0.8.0\n\nOauth = OAuth;\n"
  },
  {
    "path": "packages/oauth/end_of_popup_response.html",
    "content": "<html>\n<body>\n  <p id=\"completedText\" style=\"display:none;\">\n    Login completed. <a href=\"#\" id=\"loginCompleted\">\n      Click here</a> to close this window.\n  </p>\n\n  <div id=\"config\" style=\"display:none;\">##CONFIG##</div>\n  <script type=\"text/javascript\" src=\"/packages/oauth/end_of_popup_response.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "packages/oauth/end_of_popup_response.js",
    "content": "(function () {\n\n  var config = JSON.parse(document.getElementById(\"config\").innerHTML);\n\n  if (config.setCredentialToken) {\n    var credentialToken = config.credentialToken;\n    var credentialSecret = config.credentialSecret;\n\n    if (config.isCordova) {\n      var credentialString = JSON.stringify({\n        credentialToken: credentialToken,\n        credentialSecret: credentialSecret\n      });\n\n      window.location.hash = credentialString;\n    }\n\n    if (window.opener && window.opener.Package &&\n          window.opener.Package.oauth) {\n      window.opener.Package.oauth.OAuth._handleCredentialSecret(\n        credentialToken, credentialSecret);\n    } else {\n      try {\n        localStorage[config.storagePrefix + credentialToken] = credentialSecret;\n      } catch (err) {\n        // We can't do much else, but at least close the popup instead\n        // of having it hang around on a blank page.\n      }\n    }\n  }\n\n  if (! config.isCordova) {\n    document.getElementById(\"completedText\").style.display = \"block\";\n    document.getElementById(\"loginCompleted\").onclick = function(){ window.close(); };\n    window.close();\n  }\n})();\n"
  },
  {
    "path": "packages/oauth/end_of_redirect_response.html",
    "content": "<html>\n<body>\n  <div id=\"config\" style=\"display:none;\">##CONFIG##</div>\n  <script type=\"text/javascript\" src=\"/packages/oauth/end_of_redirect_response.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "packages/oauth/end_of_redirect_response.js",
    "content": "(function () {\n\n  var config = JSON.parse(document.getElementById(\"config\").innerHTML);\n\n  if (config.setCredentialToken) {\n    sessionStorage[config.storagePrefix + config.credentialToken] =\n    config.credentialSecret;\n  }\n\n  window.location = config.redirectUrl;\n\n})();\n"
  },
  {
    "path": "packages/oauth/oauth_browser.js",
    "content": "// Browser specific code for the OAuth package.\n\n// Open a popup window, centered on the screen, and call a callback when it\n// closes.\n//\n// @param url {String} url to show\n// @param callback {Function} Callback function to call on completion. Takes no\n//   arguments.\n// @param dimensions {optional Object(width, height)} The dimensions of\n//   the popup. If not passed defaults to something sane.\nOAuth.showPopup = function (url, callback, dimensions) {\n  // default dimensions that worked well for facebook and google\n  var popup = openCenteredPopup(\n    url,\n    (dimensions && dimensions.width) || 650,\n    (dimensions && dimensions.height) || 331\n  );\n\n  var checkPopupOpen = setInterval(function() {\n    try {\n      // Fix for #328 - added a second test criteria (popup.closed === undefined)\n      // to humour this Android quirk:\n      // http://code.google.com/p/android/issues/detail?id=21061\n      var popupClosed = popup.closed || popup.closed === undefined;\n    } catch (e) {\n      // For some unknown reason, IE9 (and others?) sometimes (when\n      // the popup closes too quickly?) throws \"SCRIPT16386: No such\n      // interface supported\" when trying to read 'popup.closed'. Try\n      // again in 100ms.\n      return;\n    }\n\n    if (popupClosed) {\n      clearInterval(checkPopupOpen);\n      callback();\n    }\n  }, 100);\n};\n\nvar openCenteredPopup = function(url, width, height) {\n  var screenX = typeof window.screenX !== 'undefined'\n        ? window.screenX : window.screenLeft;\n  var screenY = typeof window.screenY !== 'undefined'\n        ? window.screenY : window.screenTop;\n  var outerWidth = typeof window.outerWidth !== 'undefined'\n        ? window.outerWidth : document.body.clientWidth;\n  var outerHeight = typeof window.outerHeight !== 'undefined'\n        ? window.outerHeight : (document.body.clientHeight - 22);\n  // XXX what is the 22?\n\n  // Use `outerWidth - width` and `outerHeight - height` for help in\n  // positioning the popup centered relative to the current window\n  var left = screenX + (outerWidth - width) / 2;\n  var top = screenY + (outerHeight - height) / 2;\n  var features = ('width=' + width + ',height=' + height +\n                  ',left=' + left + ',top=' + top + ',scrollbars=yes');\n\n  var newwindow = window.open(url, 'Login', features);\n\n  if (typeof newwindow === 'undefined') {\n    // blocked by a popup blocker maybe?\n    var err = new Error(\"The login popup was blocked by the browser\");\n    err.attemptedUrl = url;\n    throw err;\n  }\n\n  if (newwindow.focus)\n    newwindow.focus();\n  \n  return newwindow;\n};"
  },
  {
    "path": "packages/oauth/oauth_client.js",
    "content": "// credentialToken -> credentialSecret. You must provide both the\n// credentialToken and the credentialSecret to retrieve an access token from\n// the _pendingCredentials collection.\nvar credentialSecrets = {};\n\nOAuth = {};\n\nOAuth.showPopup = function (url, callback, dimensions) {\n  throw new Error(\"OAuth.showPopup must be implemented on this arch.\");\n};\n\n// Determine the login style (popup or redirect) for this login flow.\n//\n//\nOAuth._loginStyle = function (service, config, options) {\n\n  if (Meteor.isCordova) {\n    return \"popup\";\n  }\n\n  var loginStyle = (options && options.loginStyle) || config.loginStyle || 'popup';\n\n  if (! _.contains([\"popup\", \"redirect\"], loginStyle))\n    throw new Error(\"Invalid login style: \" + loginStyle);\n\n  // If we don't have session storage (for example, Safari in private\n  // mode), the redirect login flow won't work, so fallback to the\n  // popup style.\n  if (loginStyle === 'redirect') {\n    try {\n      sessionStorage.setItem('Meteor.oauth.test', 'test');\n      sessionStorage.removeItem('Meteor.oauth.test');\n    } catch (e) {\n      loginStyle = 'popup';\n    }\n  }\n\n  return loginStyle;\n};\n\nOAuth._stateParam = function (loginStyle, credentialToken, redirectUrl) {\n  var state = {\n    loginStyle: loginStyle,\n    credentialToken: credentialToken,\n    isCordova: Meteor.isCordova\n  };\n\n  if (loginStyle === 'redirect')\n    state.redirectUrl = redirectUrl || ('' + window.location);\n\n  // Encode base64 as not all login services URI-encode the state\n  // parameter when they pass it back to us.\n  // Use the 'base64' package here because 'btoa' isn't supported in IE8/9.\n  return Base64.encode(JSON.stringify(state));\n};\n\n\n// At the beginning of the redirect login flow, before we redirect to\n// the login service, save the credential token for this login attempt\n// in the reload migration data.\n//\nOAuth.saveDataForRedirect = function (loginService, credentialToken) {\n  Reload._onMigrate('oauth', function () {\n    return [true, {loginService: loginService, credentialToken: credentialToken}];\n  });\n  Reload._migrate(null, {immediateMigration: true});\n};\n\n// At the end of the redirect login flow, when we've redirected back\n// to the application, retrieve the credentialToken and (if the login\n// was successful) the credentialSecret.\n//\n// Called at application startup.  Returns null if this is normal\n// application startup and we weren't just redirected at the end of\n// the login flow.\n//\nOAuth.getDataAfterRedirect = function () {\n  var migrationData = Reload._migrationData('oauth');\n\n  if (! (migrationData && migrationData.credentialToken))\n    return null;\n\n  var credentialToken = migrationData.credentialToken;\n  var key = OAuth._storageTokenPrefix + credentialToken;\n  var credentialSecret;\n  try {\n    credentialSecret = sessionStorage.getItem(key);\n    sessionStorage.removeItem(key);\n  } catch (e) {\n    Meteor._debug('error retrieving credentialSecret', e);\n  }\n  return {\n    loginService: migrationData.loginService,\n    credentialToken: credentialToken,\n    credentialSecret: credentialSecret\n  };\n};\n\n// Launch an OAuth login flow.  For the popup login style, show the\n// popup.  For the redirect login style, save the credential token for\n// this login attempt in the reload migration data, and redirect to\n// the service for the login.\n//\n// options:\n//  loginService: \"facebook\", \"google\", etc.\n//  loginStyle: \"popup\" or \"redirect\"\n//  loginUrl: The URL at the login service provider to start the OAuth flow.\n//  credentialRequestCompleteCallback: for the popup flow, call when the popup\n//    is closed and we have the credential from the login service.\n//  credentialToken: our identifier for this login flow.\n//\nOAuth.launchLogin = function (options) {\n  if (! options.loginService)\n    throw new Error('loginService required');\n  if (options.loginStyle === 'popup') {\n    OAuth.showPopup(\n      options.loginUrl,\n      _.bind(options.credentialRequestCompleteCallback, null, options.credentialToken),\n      options.popupOptions);\n  } else if (options.loginStyle === 'redirect') {\n    OAuth.saveDataForRedirect(options.loginService, options.credentialToken);\n    window.location = options.loginUrl;\n  } else {\n    throw new Error('invalid login style');\n  }\n};\n\n// XXX COMPAT WITH 0.7.0.1\n// Private interface but probably used by many oauth clients in atmosphere.\nOAuth.initiateLogin = function (credentialToken, url, callback, dimensions) {\n  OAuth.showPopup(\n    url,\n    _.bind(callback, null, credentialToken),\n    dimensions\n  );\n};\n\n// Called by the popup when the OAuth flow is completed, right before\n// the popup closes.\nOAuth._handleCredentialSecret = function (credentialToken, secret) {\n  check(credentialToken, String);\n  check(secret, String);\n  if (! _.has(credentialSecrets,credentialToken)) {\n    credentialSecrets[credentialToken] = secret;\n  } else {\n    throw new Error(\"Duplicate credential token from OAuth login\");\n  }\n};\n\n// Used by accounts-oauth, which needs both a credentialToken and the\n// corresponding to credential secret to call the `login` method over DDP.\nOAuth._retrieveCredentialSecret = function (credentialToken) {\n  // First check the secrets collected by OAuth._handleCredentialSecret,\n  // then check localStorage. This matches what we do in\n  // end_of_login_response.html.\n  var secret = credentialSecrets[credentialToken];\n  if (! secret) {\n    var localStorageKey = OAuth._storageTokenPrefix + credentialToken;\n    secret = Meteor._localStorage.getItem(localStorageKey);\n    Meteor._localStorage.removeItem(localStorageKey);\n  } else {\n    delete credentialSecrets[credentialToken];\n  }\n  return secret;\n};\n"
  },
  {
    "path": "packages/oauth/oauth_common.js",
    "content": "OAuth._storageTokenPrefix = \"Meteor.oauth.credentialSecret-\";\n\nOAuth._redirectUri = function (serviceName, config, params, absoluteUrlOptions) {\n  // XXX COMPAT WITH 0.9.0\n  // The redirect URI used to have a \"?close\" query argument.  We\n  // detect whether we need to be backwards compatible by checking for\n  // the absence of the `loginStyle` field, which wasn't used in the\n  // code which had the \"?close\" argument.\n  // This logic is duplicated in the tool so that the tool can do OAuth\n  // flow with <= 0.9.0 servers (tools/auth.js).\n  var query = config.loginStyle ? null : \"close\";\n\n  // Clone because we're going to mutate 'params'. The 'cordova' and\n  // 'android' parameters are only used for picking the host of the\n  // redirect URL, and not actually included in the redirect URL itself.\n  var isCordova = false;\n  var isAndroid = false;\n  if (params) {\n    params = _.clone(params);\n    isCordova = params.cordova;\n    isAndroid = params.android;\n    delete params.cordova;\n    delete params.android;\n    if (_.isEmpty(params)) {\n      params = undefined;\n    }\n  }\n\n  if (Meteor.isServer && isCordova) {\n    var rootUrl = process.env.MOBILE_ROOT_URL ||\n          __meteor_runtime_config__.ROOT_URL;\n\n    if (isAndroid) {\n      // Match the replace that we do in cordova boilerplate\n      // (boilerplate-generator package).\n      // XXX Maybe we should put this in a separate package or something\n      // that is used here and by boilerplate-generator? Or maybe\n      // `Meteor.absoluteUrl` should know how to do this?\n      var url = Npm.require(\"url\");\n      var parsedRootUrl = url.parse(rootUrl);\n      if (parsedRootUrl.hostname === \"localhost\") {\n        parsedRootUrl.hostname = \"10.0.2.2\";\n        delete parsedRootUrl.host;\n      }\n      rootUrl = url.format(parsedRootUrl);\n    }\n\n    absoluteUrlOptions = _.extend({}, absoluteUrlOptions, {\n      // For Cordova clients, redirect to the special Cordova root url\n      // (likely a local IP in development mode).\n      rootUrl: rootUrl\n    });\n  }\n\n  return URL._constructUrl(\n    Meteor.absoluteUrl('_oauth/' + serviceName, absoluteUrlOptions),\n    query,\n    params);\n};\n"
  },
  {
    "path": "packages/oauth/oauth_cordova.js",
    "content": "// Cordova specific code for the OAuth package.\n\n// Open a popup window, centered on the screen, and call a callback when it\n// closes.\n//\n// @param url {String} url to show\n// @param callback {Function} Callback function to call on completion. Takes no\n//   arguments.\n// @param dimensions {optional Object(width, height)} The dimensions of\n//   the popup. If not passed defaults to something sane.\nOAuth.showPopup = function (url, callback, dimensions) {\n  var fail = function (err) {\n    Meteor._debug(\"Error from OAuth popup: \" + JSON.stringify(err));\n  };\n\n  // When running on an android device, we sometimes see the\n  // `pageLoaded` callback fire twice for the final page in the OAuth\n  // popup, even though the page only loads once. This is maybe an\n  // Android bug or maybe something intentional about how onPageFinished\n  // works that we don't understand and isn't well-documented.\n  var oauthFinished = false;\n\n  var pageLoaded = function (event) {\n    if (oauthFinished) {\n      return;\n    }\n\n    if (event.url.indexOf(Meteor.absoluteUrl('_oauth')) === 0) {\n      var splitUrl = event.url.split(\"#\");\n      var hashFragment = splitUrl[1];\n\n      if (! hashFragment) {\n        throw new Error(\"No hash fragment in OAuth popup?\");\n      }\n\n      var credentials = JSON.parse(decodeURIComponent(hashFragment));\n      OAuth._handleCredentialSecret(credentials.credentialToken,\n                                    credentials.credentialSecret);\n\n      oauthFinished = true;\n\n      // On iOS, this seems to prevent \"Warning: Attempt to dismiss from\n      // view controller <MainViewController: ...> while a presentation\n      // or dismiss is in progress\". My guess is that the last\n      // navigation of the OAuth popup is still in progress while we try\n      // to close the popup. See\n      // https://issues.apache.org/jira/browse/CB-2285.\n      //\n      // XXX Can we make this timeout smaller?\n      setTimeout(function () {\n        popup.close();\n        callback();\n      }, 100);\n    }\n  };\n\n  var onExit = function () {\n    popup.removeEventListener('loadstop', pageLoaded);\n    popup.removeEventListener('loaderror', fail);\n    popup.removeEventListener('exit', onExit);\n  };\n\n  var popup = window.open(url, '_blank', 'location=yes,hidden=yes');\n  popup.addEventListener('loadstop', pageLoaded);\n  popup.addEventListener('loaderror', fail);\n  popup.addEventListener('exit', onExit);\n  popup.show();\n\n};\n"
  },
  {
    "path": "packages/oauth/oauth_server.js",
    "content": "var Fiber = Npm.require('fibers');\nvar url = Npm.require('url');\n\nOAuth = {};\nOAuthTest = {};\n\nRoutePolicy.declare('/_oauth/', 'network');\n\nvar registeredServices = {};\n\n// Internal: Maps from service version to handler function. The\n// 'oauth1' and 'oauth2' packages manipulate this directly to register\n// for callbacks.\nOAuth._requestHandlers = {};\n\n\n// Register a handler for an OAuth service. The handler will be called\n// when we get an incoming http request on /_oauth/{serviceName}. This\n// handler should use that information to fetch data about the user\n// logging in.\n//\n// @param name {String} e.g. \"google\", \"facebook\"\n// @param version {Number} OAuth version (1 or 2)\n// @param urls   For OAuth1 only, specify the service's urls\n// @param handleOauthRequest {Function(oauthBinding|query)}\n//   - (For OAuth1 only) oauthBinding {OAuth1Binding} bound to the appropriate provider\n//   - (For OAuth2 only) query {Object} parameters passed in query string\n//   - return value is:\n//     - {serviceData:, (optional options:)} where serviceData should end\n//       up in the user's services[name] field\n//     - `null` if the user declined to give permissions\n//\nOAuth.registerService = function (name, version, urls, handleOauthRequest) {\n  if (registeredServices[name])\n    throw new Error(\"Already registered the \" + name + \" OAuth service\");\n\n  registeredServices[name] = {\n    serviceName: name,\n    version: version,\n    urls: urls,\n    handleOauthRequest: handleOauthRequest\n  };\n};\n\n// For test cleanup.\nOAuthTest.unregisterService = function (name) {\n  delete registeredServices[name];\n};\n\n\nOAuth.retrieveCredential = function(credentialToken, credentialSecret) {\n  return OAuth._retrievePendingCredential(credentialToken, credentialSecret);\n};\n\n\n// The state parameter is normally generated on the client using\n// `btoa`, but for tests we need a version that runs on the server.\n//\nOAuth._generateState = function (loginStyle, credentialToken, redirectUrl) {\n  return new Buffer(JSON.stringify({\n    loginStyle: loginStyle,\n    credentialToken: credentialToken,\n    redirectUrl: redirectUrl})).toString('base64');\n};\n\nOAuth._stateFromQuery = function (query) {\n  var string;\n  try {\n    string = new Buffer(query.state, 'base64').toString('binary');\n  } catch (e) {\n    Log.warn('Unable to base64 decode state from OAuth query: ' + query.state);\n    throw e;\n  }\n\n  try {\n    return JSON.parse(string);\n  } catch (e) {\n    Log.warn('Unable to parse state from OAuth query: ' + string);\n    throw e;\n  }\n};\n\nOAuth._loginStyleFromQuery = function (query) {\n  var style;\n  // For backwards-compatibility for older clients, catch any errors\n  // that result from parsing the state parameter. If we can't parse it,\n  // set login style to popup by default.\n  try {\n    style = OAuth._stateFromQuery(query).loginStyle;\n  } catch (err) {\n    style = \"popup\";\n  }\n  if (style !== \"popup\" && style !== \"redirect\") {\n    throw new Error(\"Unrecognized login style: \" + style);\n  }\n  return style;\n};\n\nOAuth._credentialTokenFromQuery = function (query) {\n  var state;\n  // For backwards-compatibility for older clients, catch any errors\n  // that result from parsing the state parameter. If we can't parse it,\n  // assume that the state parameter's value is the credential token, as\n  // it used to be for older clients.\n  try {\n    state = OAuth._stateFromQuery(query);\n  } catch (err) {\n    return query.state;\n  }\n  return state.credentialToken;\n};\n\nOAuth._isCordovaFromQuery = function (query) {\n  try {\n    return !! OAuth._stateFromQuery(query).isCordova;\n  } catch (err) {\n    // For backwards-compatibility for older clients, catch any errors\n    // that result from parsing the state parameter. If we can't parse\n    // it, assume that we are not on Cordova, since older Meteor didn't\n    // do Cordova.\n    return false;\n  }\n};\n\n// Checks if the `redirectUrl` matches the app host.\n// We export this function so that developers can override this\n// behavior to allow apps from external domains to login using the\n// redirect OAuth flow.\nOAuth._checkRedirectUrlOrigin = function (redirectUrl) {\n  var appHost = Meteor.absoluteUrl();\n  var appHostReplacedLocalhost = Meteor.absoluteUrl(undefined, {\n    replaceLocalhost: true\n  });\n  return (\n    redirectUrl.substr(0, appHost.length) !== appHost &&\n    redirectUrl.substr(0, appHostReplacedLocalhost.length) !== appHostReplacedLocalhost\n  );\n};\n\n\n// Listen to incoming OAuth http requests\nWebApp.connectHandlers.use(function(req, res, next) {\n  // Need to create a Fiber since we're using synchronous http calls and nothing\n  // else is wrapping this in a fiber automatically\n  Fiber(function () {\n    middleware(req, res, next);\n  }).run();\n});\n\nvar middleware = function (req, res, next) {\n  // Make sure to catch any exceptions because otherwise we'd crash\n  // the runner\n  try {\n    var serviceName = oauthServiceName(req);\n    if (!serviceName) {\n      // not an oauth request. pass to next middleware.\n      next();\n      return;\n    }\n\n    var service = registeredServices[serviceName];\n\n    // Skip everything if there's no service set by the oauth middleware\n    if (!service)\n      throw new Error(\"Unexpected OAuth service \" + serviceName);\n\n    // Make sure we're configured\n    ensureConfigured(serviceName);\n\n    var handler = OAuth._requestHandlers[service.version];\n    if (!handler)\n      throw new Error(\"Unexpected OAuth version \" + service.version);\n    handler(service, req.query, res);\n  } catch (err) {\n    // if we got thrown an error, save it off, it will get passed to\n    // the appropriate login call (if any) and reported there.\n    //\n    // The other option would be to display it in the popup tab that\n    // is still open at this point, ignoring the 'close' or 'redirect'\n    // we were passed. But then the developer wouldn't be able to\n    // style the error or react to it in any way.\n    if (req.query.state && err instanceof Error) {\n      try { // catch any exceptions to avoid crashing runner\n        OAuth._storePendingCredential(OAuth._credentialTokenFromQuery(req.query), err);\n      } catch (err) {\n        // Ignore the error and just give up. If we failed to store the\n        // error, then the login will just fail with a generic error.\n        Log.warn(\"Error in OAuth Server while storing pending login result.\\n\" +\n                 err.stack || err.message);\n      }\n    }\n\n    // close the popup. because nobody likes them just hanging\n    // there.  when someone sees this multiple times they might\n    // think to check server logs (we hope?)\n    // Catch errors because any exception here will crash the runner.\n    try {\n      OAuth._endOfLoginResponse(res, {\n        query: req.query,\n        loginStyle: OAuth._loginStyleFromQuery(req.query),\n        error: err\n      });\n    } catch (err) {\n      Log.warn(\"Error generating end of login response\\n\" +\n               (err && (err.stack || err.message)));\n    }\n  }\n};\n\nOAuthTest.middleware = middleware;\n\n// Handle /_oauth/* paths and extract the service name.\n//\n// @returns {String|null} e.g. \"facebook\", or null if this isn't an\n// oauth request\nvar oauthServiceName = function (req) {\n  // req.url will be \"/_oauth/<service name>\" with an optional \"?close\".\n  var i = req.url.indexOf('?');\n  var barePath;\n  if (i === -1)\n    barePath = req.url;\n  else\n    barePath = req.url.substring(0, i);\n  var splitPath = barePath.split('/');\n\n  // Any non-oauth request will continue down the default\n  // middlewares.\n  if (splitPath[1] !== '_oauth')\n    return null;\n\n  // Find service based on url\n  var serviceName = splitPath[2];\n  return serviceName;\n};\n\n// Make sure we're configured\nvar ensureConfigured = function(serviceName) {\n  if (!ServiceConfiguration.configurations.findOne({service: serviceName})) {\n    throw new ServiceConfiguration.ConfigError();\n  }\n};\n\nvar isSafe = function (value) {\n  // This matches strings generated by `Random.secret` and\n  // `Random.id`.\n  return typeof value === \"string\" &&\n    /^[a-zA-Z0-9\\-_]+$/.test(value);\n};\n\n// Internal: used by the oauth1 and oauth2 packages\nOAuth._renderOauthResults = function(res, query, credentialSecret) {\n  // For tests, we support the `only_credential_secret_for_test`\n  // parameter, which just returns the credential secret without any\n  // surrounding HTML. (The test needs to be able to easily grab the\n  // secret and use it to log in.)\n  //\n  // XXX only_credential_secret_for_test could be useful for other\n  // things beside tests, like command-line clients. We should give it a\n  // real name and serve the credential secret in JSON.\n\n  if (query.only_credential_secret_for_test) {\n    res.writeHead(200, {'Content-Type': 'text/html'});\n    res.end(credentialSecret, 'utf-8');\n  } else {\n    var details = {\n      query: query,\n      loginStyle: OAuth._loginStyleFromQuery(query)\n    };\n    if (query.error) {\n      details.error = query.error;\n    } else {\n      var token = OAuth._credentialTokenFromQuery(query);\n      var secret = credentialSecret;\n      if (token && secret &&\n          isSafe(token) && isSafe(secret)) {\n        details.credentials = { token: token, secret: secret};\n      } else {\n        details.error = \"invalid_credential_token_or_secret\";\n      }\n    }\n\n    OAuth._endOfLoginResponse(res, details);\n  }\n};\n\n// This \"template\" (not a real Spacebars template, just an HTML file\n// with some ##PLACEHOLDER##s) communicates the credential secret back\n// to the main window and then closes the popup.\nOAuth._endOfPopupResponseTemplate = Assets.getText(\n  \"end_of_popup_response.html\");\n\nOAuth._endOfRedirectResponseTemplate = Assets.getText(\n  \"end_of_redirect_response.html\");\n\n// Renders the end of login response template into some HTML and JavaScript\n// that closes the popup or redirects at the end of the OAuth flow.\n//\n// options are:\n//   - loginStyle (\"popup\" or \"redirect\")\n//   - setCredentialToken (boolean)\n//   - credentialToken\n//   - credentialSecret\n//   - redirectUrl\n//   - isCordova (boolean)\n//\nvar renderEndOfLoginResponse = function (options) {\n  // It would be nice to use Blaze here, but it's a little tricky\n  // because our mustaches would be inside a <script> tag, and Blaze\n  // would treat the <script> tag contents as text (e.g. encode '&' as\n  // '&amp;'). So we just do a simple replace.\n\n  var escape = function (s) {\n    if (s) {\n      return s.replace(/&/g, \"&amp;\").\n        replace(/</g, \"&lt;\").\n        replace(/>/g, \"&gt;\").\n        replace(/\\\"/g, \"&quot;\").\n        replace(/\\'/g, \"&#x27;\").\n        replace(/\\//g, \"&#x2F;\");\n    } else {\n      return s;\n    }\n  };\n\n  // Escape everything just to be safe (we've already checked that some\n  // of this data -- the token and secret -- are safe).\n  var config = {\n    setCredentialToken: !! options.setCredentialToken,\n    credentialToken: escape(options.credentialToken),\n    credentialSecret: escape(options.credentialSecret),\n    storagePrefix: escape(OAuth._storageTokenPrefix),\n    redirectUrl: escape(options.redirectUrl),\n    isCordova: !! options.isCordova\n  };\n\n  var template;\n  if (options.loginStyle === 'popup') {\n    template = OAuth._endOfPopupResponseTemplate;\n  } else if (options.loginStyle === 'redirect') {\n    template = OAuth._endOfRedirectResponseTemplate;\n  } else {\n    throw new Error('invalid loginStyle: ' + options.loginStyle);\n  }\n\n  var result = template.replace(/##CONFIG##/, JSON.stringify(config));\n\n  return \"<!DOCTYPE html>\\n\" + result;\n};\n\n// Writes an HTTP response to the popup window at the end of an OAuth\n// login flow. At this point, if the user has successfully authenticated\n// to the OAuth server and authorized this app, we communicate the\n// credentialToken and credentialSecret to the main window. The main\n// window must provide both these values to the DDP `login` method to\n// authenticate its DDP connection. After communicating these vaues to\n// the main window, we close the popup.\n//\n// We export this function so that developers can override this\n// behavior, which is particularly useful in, for example, some mobile\n// environments where popups and/or `window.opener` don't work. For\n// example, an app could override `OAuth._endOfPopupResponse` to put the\n// credential token and credential secret in the popup URL for the main\n// window to read them there instead of using `window.opener`. If you\n// override this function, you take responsibility for writing to the\n// request and calling `res.end()` to complete the request.\n//\n// Arguments:\n//   - res: the HTTP response object\n//   - details:\n//      - query: the query string on the HTTP request\n//      - credentials: { token: *, secret: * }. If present, this field\n//        indicates that the login was successful. Return these values\n//        to the client, who can use them to log in over DDP. If\n//        present, the values have been checked against a limited\n//        character set and are safe to include in HTML.\n//      - error: if present, a string or Error indicating an error that\n//        occurred during the login. This can come from the client and\n//        so shouldn't be trusted for security decisions or included in\n//        the response without sanitizing it first. Only one of `error`\n//        or `credentials` should be set.\nOAuth._endOfLoginResponse = function (res, details) {\n  res.writeHead(200, {'Content-Type': 'text/html'});\n\n  var redirectUrl;\n  if (details.loginStyle === 'redirect') {\n    redirectUrl = OAuth._stateFromQuery(details.query).redirectUrl;\n    var appHost = Meteor.absoluteUrl();\n    if (OAuth._checkRedirectUrlOrigin(redirectUrl)) {\n      details.error = \"redirectUrl (\" + redirectUrl +\n        \") is not on the same host as the app (\" + appHost + \")\";\n      redirectUrl = appHost;\n    }\n  }\n\n  var isCordova = OAuth._isCordovaFromQuery(details.query);\n\n  if (details.error) {\n    Log.warn(\"Error in OAuth Server: \" +\n             (details.error instanceof Error ?\n              details.error.message : details.error));\n    res.end(renderEndOfLoginResponse({\n      loginStyle: details.loginStyle,\n      setCredentialToken: false,\n      redirectUrl: redirectUrl,\n      isCordova: isCordova\n    }), \"utf-8\");\n    return;\n  }\n\n  // If we have a credentialSecret, report it back to the parent\n  // window, with the corresponding credentialToken. The parent window\n  // uses the credentialToken and credentialSecret to log in over DDP.\n  res.end(renderEndOfLoginResponse({\n    loginStyle: details.loginStyle,\n    setCredentialToken: true,\n    credentialToken: details.credentials.token,\n    credentialSecret: details.credentials.secret,\n    redirectUrl: redirectUrl,\n    isCordova: isCordova\n  }), \"utf-8\");\n};\n\n\nvar OAuthEncryption = Package[\"oauth-encryption\"] && Package[\"oauth-encryption\"].OAuthEncryption;\n\nvar usingOAuthEncryption = function () {\n  return OAuthEncryption && OAuthEncryption.keyIsLoaded();\n};\n\n// Encrypt sensitive service data such as access tokens if the\n// \"oauth-encryption\" package is loaded and the oauth secret key has\n// been specified.  Returns the unencrypted plaintext otherwise.\n//\n// The user id is not specified because the user isn't known yet at\n// this point in the oauth authentication process.  After the oauth\n// authentication process completes the encrypted service data fields\n// will be re-encrypted with the user id included before inserting the\n// service data into the user document.\n//\nOAuth.sealSecret = function (plaintext) {\n  if (usingOAuthEncryption())\n    return OAuthEncryption.seal(plaintext);\n  else\n    return plaintext;\n}\n\n// Unencrypt a service data field, if the \"oauth-encryption\"\n// package is loaded and the field is encrypted.\n//\n// Throws an error if the \"oauth-encryption\" package is loaded and the\n// field is encrypted, but the oauth secret key hasn't been specified.\n//\nOAuth.openSecret = function (maybeSecret, userId) {\n  if (!Package[\"oauth-encryption\"] || !OAuthEncryption.isSealed(maybeSecret))\n    return maybeSecret;\n\n  return OAuthEncryption.open(maybeSecret, userId);\n};\n\n// Unencrypt fields in the service data object.\n//\nOAuth.openSecrets = function (serviceData, userId) {\n  var result = {};\n  _.each(_.keys(serviceData), function (key) {\n    result[key] = OAuth.openSecret(serviceData[key], userId);\n  });\n  return result;\n};\n"
  },
  {
    "path": "packages/oauth/oauth_tests.js",
    "content": "Tinytest.add(\"oauth - pendingCredential handles Errors\", function (test) {\n  var credentialToken = Random.id();\n\n  var testError = new Error(\"This is a test error\");\n  testError.stack = 'test stack';\n  OAuth._storePendingCredential(credentialToken, testError);\n\n  // Test that the result for the token is the expected error\n  var result = OAuth._retrievePendingCredential(credentialToken);\n  test.instanceOf(result, Error);\n  test.equal(result.message, testError.message);\n  test.equal(result.stack, testError.stack);\n});\n\nTinytest.add(\"oauth - pendingCredential handles Meteor.Errors\", function (test) {\n  var credentialToken = Random.id();\n\n  var testError = new Meteor.Error(401, \"This is a test error\");\n  testError.stack = 'test stack';\n  OAuth._storePendingCredential(credentialToken, testError);\n\n  // Test that the result for the token is the expected error\n  var result = OAuth._retrievePendingCredential(credentialToken);\n  test.instanceOf(result, Meteor.Error);\n  test.equal(result.error, testError.error);\n  test.equal(result.message, testError.message);\n  test.equal(result.reason, testError.reason);\n  test.equal(result.stack, testError.stack);\n  test.isUndefined(result.meteorError);\n});\n\nTinytest.add(\"oauth - null, undefined key for pendingCredential\", function (test) {\n  var cred = Random.id();\n  test.throws(function () {\n    OAuth._storePendingCredential(null, cred);\n  });\n  test.throws(function () {\n    OAuth._storePendingCredential(undefined, cred);\n  });\n});\n\nTinytest.add(\"oauth - pendingCredential handles duplicate key\", function (test) {\n  var key = Random.id();\n  var cred = Random.id();\n  OAuth._storePendingCredential(key, cred);\n  var newCred = Random.id();\n  OAuth._storePendingCredential(key, newCred);\n  test.equal(OAuth._retrievePendingCredential(key), newCred);\n});\n\nTinytest.add(\n  \"oauth - pendingCredential requires credential secret\",\n  function (test) {\n    var key = Random.id();\n    var cred = Random.id();\n    var secret = Random.id();\n    OAuth._storePendingCredential(key, cred, secret);\n    test.equal(OAuth._retrievePendingCredential(key), undefined);\n    test.equal(OAuth._retrievePendingCredential(key, secret), cred);\n  }\n);\n"
  },
  {
    "path": "packages/oauth/package.js",
    "content": "Package.describe({\n  summary: \"Common code for OAuth-based services\",\n  version: \"1.1.11\"\n});\n\nPackage.onUse(function (api) {\n  api.use('check');\n  api.use('underscore');\n\n  api.use('routepolicy', 'server');\n  api.use('webapp', 'server');\n  api.use('mongo', 'server');\n\n  api.use('reload', 'client');\n  api.use('base64', 'client');\n\n  api.use(['service-configuration', 'logging'], 'server');\n\n  api.use('oauth-encryption', 'server', {weak: true});\n\n  api.use('localstorage');\n  api.use('url');\n\n  api.export('OAuth');\n  api.export('OAuthTest', 'server', {testOnly: true});\n\n  api.addFiles('oauth_client.js', 'web');\n  api.addFiles('oauth_browser.js', 'web.browser');\n  api.addFiles('oauth_cordova.js', 'web.cordova');\n  api.addFiles('oauth_server.js', 'server');\n  api.addFiles('pending_credentials.js', 'server');\n\n  api.addAssets([\n    'end_of_popup_response.html',\n    'end_of_redirect_response.html'\n  ], 'server');\n\n  api.addAssets([\n    'end_of_popup_response.js',\n    'end_of_redirect_response.js'\n  ], 'client');\n\n  api.addFiles('oauth_common.js');\n\n  // XXX COMPAT WITH 0.8.0\n  api.export('Oauth');\n  api.addFiles('deprecated.js', ['client', 'server']);\n});\n\n\nPackage.onTest(function (api) {\n  api.use('tinytest');\n  api.use('random');\n  api.use('service-configuration', 'server');\n  api.use('oauth', 'server');\n  api.addFiles(\"oauth_tests.js\", 'server');\n});\n\nCordova.depends({\n  'cordova-plugin-inappbrowser': '1.3.0'\n});\n"
  },
  {
    "path": "packages/oauth/pending_credentials.js",
    "content": "//\n// When an oauth request is made, Meteor receives oauth credentials\n// in one browser tab, and temporarily persists them while that\n// tab is closed, then retrieves them in the browser tab that\n// initiated the credential request.\n//\n// _pendingCredentials is the storage mechanism used to share the\n// credential between the 2 tabs\n//\n\n\n// Collection containing pending credentials of oauth credential requests\n// Has key, credential, and createdAt fields.\nOAuth._pendingCredentials = new Mongo.Collection(\n  \"meteor_oauth_pendingCredentials\", {\n    _preventAutopublish: true\n  });\n\nOAuth._pendingCredentials._ensureIndex('key', {unique: 1});\nOAuth._pendingCredentials._ensureIndex('credentialSecret');\nOAuth._pendingCredentials._ensureIndex('createdAt');\n\n\n\n// Periodically clear old entries that were never retrieved\nvar _cleanStaleResults = function() {\n  // Remove credentials older than 1 minute\n  var timeCutoff = new Date();\n  timeCutoff.setMinutes(timeCutoff.getMinutes() - 1);\n  OAuth._pendingCredentials.remove({ createdAt: { $lt: timeCutoff } });\n};\nvar _cleanupHandle = Meteor.setInterval(_cleanStaleResults, 60 * 1000);\n\n\n// Stores the key and credential in the _pendingCredentials collection.\n// Will throw an exception if `key` is not a string.\n//\n// @param key {string}\n// @param credential {Object}   The credential to store\n// @param credentialSecret {string} A secret that must be presented in\n//   addition to the `key` to retrieve the credential\n//\nOAuth._storePendingCredential = function (key, credential, credentialSecret) {\n  check(key, String);\n  check(credentialSecret, Match.Optional(String));\n\n  if (credential instanceof Error) {\n    credential = storableError(credential);\n  } else {\n    credential = OAuth.sealSecret(credential);\n  }\n\n  // We do an upsert here instead of an insert in case the user happens\n  // to somehow send the same `state` parameter twice during an OAuth\n  // login; we don't want a duplicate key error.\n  OAuth._pendingCredentials.upsert({\n    key: key\n  }, {\n    key: key,\n    credential: credential,\n    credentialSecret: credentialSecret || null,\n    createdAt: new Date()\n  });\n};\n\n\n// Retrieves and removes a credential from the _pendingCredentials collection\n//\n// @param key {string}\n// @param credentialSecret {string}\n//\nOAuth._retrievePendingCredential = function (key, credentialSecret) {\n  check(key, String);\n\n  var pendingCredential = OAuth._pendingCredentials.findOne({\n    key: key,\n    credentialSecret: credentialSecret || null\n  });\n  if (pendingCredential) {\n    OAuth._pendingCredentials.remove({ _id: pendingCredential._id });\n    if (pendingCredential.credential.error)\n      return recreateError(pendingCredential.credential.error);\n    else\n      return OAuth.openSecret(pendingCredential.credential);\n  } else {\n    return undefined;\n  }\n};\n\n\n// Convert an Error into an object that can be stored in mongo\n// Note: A Meteor.Error is reconstructed as a Meteor.Error\n// All other error classes are reconstructed as a plain Error.\nvar storableError = function(error) {\n  var plainObject = {};\n  Object.getOwnPropertyNames(error).forEach(function(key) {\n    plainObject[key] = error[key];\n  });\n\n  // Keep track of whether it's a Meteor.Error\n  if(error instanceof Meteor.Error) {\n    plainObject['meteorError'] = true;\n  }\n\n  return { error: plainObject };\n};\n\n// Create an error from the error format stored in mongo\nvar recreateError = function(errorDoc) {\n  var error;\n\n  if (errorDoc.meteorError) {\n    error = new Meteor.Error();\n    delete errorDoc.meteorError;\n  } else {\n    error = new Error();\n  }\n\n  Object.getOwnPropertyNames(errorDoc).forEach(function(key) {\n    error[key] = errorDoc[key];\n  });\n\n  return error;\n};\n"
  },
  {
    "path": "packages/oauth-encryption/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/oauth-encryption/README.md",
    "content": "# oauth-encryption\n\nEncrypts sensitive login secrets stored in the database such as a\nlogin service's application secret key and users' access tokens.\n\nRead more at http://docs.meteor.com/#/full/oauthencryption"
  },
  {
    "path": "packages/oauth-encryption/encrypt.js",
    "content": "var crypto = Npm.require(\"crypto\");\n// XXX We hope to be able to use the `crypto` module exclusively when\n// Node supports GCM in version 0.11.\nvar gcm = NpmModuleNodeAesGcm;\n\nOAuthEncryption = {};\n\nvar gcmKey = null;\n\n\n// Node leniently ignores non-base64 characters when parsing a base64\n// string, but we want to provide a more informative error message if\n// the developer doesn't use base64 encoding.\n//\n// Note that an empty string is valid base64 (denoting 0 bytes).\n//\n// Exported for the convenience of tests.\n//\nOAuthEncryption._isBase64 = function (str) {\n  return _.isString(str) && /^[A-Za-z0-9\\+\\/]*\\={0,2}$/.test(str);\n};\n\n\n// Loads the OAuth secret key, which must be 16 bytes in length\n// encoded in base64.\n//\n// The key may be `null` which reverts to having no key (mainly used\n// by tests).\n//\nOAuthEncryption.loadKey = function (key) {\n  if (key === null) {\n    gcmKey = null;\n    return;\n  }\n\n  if (! OAuthEncryption._isBase64(key))\n    throw new Error(\"The OAuth encryption key must be encoded in base64\");\n\n  var buf = new Buffer(key, \"base64\");\n\n  if (buf.length !== 16)\n    throw new Error(\"The OAuth encryption AES-128-GCM key must be 16 bytes in length\");\n\n  gcmKey = buf;\n};\n\n\n// Encrypt `data`, which may be any EJSON-compatible object, using the\n// previously loaded OAuth secret key.\n//\n// The `userId` argument is optional. The data is encrypted as { data:\n// *, userId: * }. When the result of `seal` is passed to `open`, the\n// same user id must be supplied, which prevents user specific\n// credentials such as access tokens from being used by a different\n// user.\n//\n// We would actually like the user id to be AAD (additional\n// authenticated data), but the node crypto API does not currently have\n// support for specifying AAD.\n//\nOAuthEncryption.seal = function (data, userId) {\n  if (! gcmKey) {\n    throw new Error(\"No OAuth encryption key loaded\");\n  }\n\n  var plaintext = new Buffer(EJSON.stringify({\n    data: data,\n    userId: userId\n  }));\n  var iv = crypto.randomBytes(12);\n  var result = gcm.encrypt(gcmKey, iv, plaintext, new Buffer([]) /* aad */);\n  return {\n    iv: iv.toString(\"base64\"),\n    ciphertext: result.ciphertext.toString(\"base64\"),\n    algorithm: \"aes-128-gcm\",\n    authTag: result.auth_tag.toString(\"base64\")\n  };\n};\n\n// Decrypt the passed ciphertext (as returned from `seal`) using the\n// previously loaded OAuth secret key.\n//\n// `userId` must match the user id passed to `seal`: if the user id\n// wasn't specified, it must not be specified here, if it was\n// specified, it must be the same user id.\n//\n// To prevent an attacker from breaking the encryption key by\n// observing the result of sending manipulated ciphertexts, `open`\n// throws \"decryption unsuccessful\" on any error.\nOAuthEncryption.open = function (ciphertext, userId) {\n  if (! gcmKey)\n    throw new Error(\"No OAuth encryption key loaded\");\n\n  try {\n    if (ciphertext.algorithm !== \"aes-128-gcm\") {\n      throw new Error();\n    }\n\n    var result = gcm.decrypt(\n      gcmKey,\n      new Buffer(ciphertext.iv, \"base64\"),\n      new Buffer(ciphertext.ciphertext, \"base64\"),\n      new Buffer([]), /* aad */\n      new Buffer(ciphertext.authTag, \"base64\")\n    );\n\n    if (! result.auth_ok) {\n      throw new Error();\n    }\n\n    var err;\n    var data;\n\n    try {\n      data = EJSON.parse(result.plaintext.toString());\n    } catch (e) {\n      err = new Error();\n    }\n\n    if (data.userId !== userId) {\n      err = new Error();\n    }\n\n    if (err) {\n      throw err;\n    } else {\n      return data.data;\n    }\n  } catch (e) {\n    throw new Error(\"decryption failed\");\n  }\n};\n\n\nOAuthEncryption.isSealed = function (maybeCipherText) {\n  return maybeCipherText &&\n    OAuthEncryption._isBase64(maybeCipherText.iv) &&\n    OAuthEncryption._isBase64(maybeCipherText.ciphertext) &&\n    OAuthEncryption._isBase64(maybeCipherText.authTag) &&\n    _.isString(maybeCipherText.algorithm);\n};\n\n\nOAuthEncryption.keyIsLoaded = function () {\n  return !! gcmKey;\n};\n"
  },
  {
    "path": "packages/oauth-encryption/encrypt_tests.js",
    "content": "Tinytest.add(\"oauth-encryption - loadKey\", function (test) {\n  test.throws(\n    function () {\n      OAuthEncryption.loadKey(\"my encryption key\");\n    },\n    \"The OAuth encryption key must be encoded in base64\"\n  );\n\n  test.throws(\n    function () {\n      OAuthEncryption.loadKey(new Buffer([1, 2, 3, 4, 5]).toString(\"base64\"));\n    },\n    \"The OAuth encryption AES-128-GCM key must be 16 bytes in length\"\n  );\n\n  OAuthEncryption.loadKey(\n    new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]).\n    toString(\"base64\")\n  );\n\n  OAuthEncryption.loadKey(null);\n});\n\nTinytest.add(\"oauth-encryption - seal\", function (test) {\n  OAuthEncryption.loadKey(\n    new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]).\n    toString(\"base64\")\n  );\n\n  var ciphertext = OAuthEncryption.seal({a: 1, b: 2});\n  test.isTrue(new Buffer(ciphertext.iv, \"base64\").length === 12);\n  test.isTrue(OAuthEncryption._isBase64(ciphertext.ciphertext));\n  test.isTrue(ciphertext.algorithm === \"aes-128-gcm\");\n  test.isTrue(OAuthEncryption._isBase64(ciphertext.authTag));\n\n  OAuthEncryption.loadKey(null);\n});\n\nTinytest.add(\"oauth-encryption - open successful\", function (test) {\n  OAuthEncryption.loadKey(\n    new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]).\n    toString(\"base64\")\n  );\n  var userId = \"rH6rNSWd2hBTfkwcc\";\n  var ciphertext = OAuthEncryption.seal({a: 1, b: 2}, userId);\n\n  var decrypted = OAuthEncryption.open(ciphertext, userId);\n  test.equal(decrypted, {a: 1, b: 2});\n\n  OAuthEncryption.loadKey(null);\n});\n\nTinytest.add(\"oauth-encryption - open with wrong key\", function (test) {\n  OAuthEncryption.loadKey(\n    new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]).\n    toString(\"base64\")\n  );\n  var userId = \"rH6rNSWd2hBTfkwcc\";\n  var ciphertext = OAuthEncryption.seal({a: 1, b: 2}, userId);\n\n  OAuthEncryption.loadKey(\n    new Buffer([9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]).\n    toString(\"base64\")\n  );\n  test.throws(\n    function () {\n      OAuthEncryption.open(ciphertext, userId);\n    },\n    \"decryption failed\"\n  );\n\n  OAuthEncryption.loadKey(null);\n});\n\nTinytest.add(\"oauth-encryption - open with wrong userId\", function (test) {\n  OAuthEncryption.loadKey(\n    new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]).\n    toString(\"base64\")\n  );\n  var userId = \"rH6rNSWd2hBTfkwcc\";\n  var ciphertext = OAuthEncryption.seal({a: 1, b: 2}, userId);\n\n  var differentUser = \"3FPxY2mBNeBpigm86\";\n  test.throws(\n    function () {\n      OAuthEncryption.open(ciphertext, differentUser);\n    },\n    \"decryption failed\"\n  );\n\n  OAuthEncryption.loadKey(null);\n});\n\nTinytest.add(\"oauth-encryption - seal and open with no userId\", function (test) {\n  OAuthEncryption.loadKey(\n    new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]).\n    toString(\"base64\")\n  );\n  var ciphertext = OAuthEncryption.seal({a: 1, b: 2});\n  var decrypted = OAuthEncryption.open(ciphertext);\n  test.equal(decrypted, {a: 1, b: 2});\n});\n\nTinytest.add(\"oauth-encryption - open modified ciphertext\", function (test) {\n  OAuthEncryption.loadKey(\n    new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]).\n    toString(\"base64\")\n  );\n  var ciphertext = OAuthEncryption.seal({a: 1, b: 2});\n\n  var b = new Buffer(ciphertext.ciphertext, \"base64\");\n  b[0] = b[0] ^ 1;\n  ciphertext.ciphertext = b.toString(\"base64\");\n\n  test.throws(\n    function () {\n      OAuthEncryption.open(ciphertext);\n    },\n    \"decryption failed\"\n  );\n});\n\n\nTinytest.add(\"oauth-encryption - isSealed\", function (test) {\n  OAuthEncryption.loadKey(\n    new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]).\n    toString(\"base64\")\n  );\n  var userId = \"rH6rNSWd2hBTfkwcc\";\n  var ciphertext = OAuthEncryption.seal({a: 1, b: 2}, userId);\n  test.isTrue(OAuthEncryption.isSealed(ciphertext));\n\n  test.isFalse(OAuthEncryption.isSealed(\"abcdef\"));\n  test.isFalse(OAuthEncryption.isSealed({a: 1, b: 2}));\n\n  OAuthEncryption.loadKey(null);\n});\n\nTinytest.add(\"oauth-encryption - keyIsLoaded\", function (test) {\n  OAuthEncryption.loadKey(null);\n  test.isFalse(OAuthEncryption.keyIsLoaded());\n\n  OAuthEncryption.loadKey(\n    new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]).\n    toString(\"base64\")\n  );\n  test.isTrue(OAuthEncryption.keyIsLoaded());\n\n  OAuthEncryption.loadKey(null);\n});\n"
  },
  {
    "path": "packages/oauth-encryption/package.js",
    "content": "Package.describe({\n  summary: \"Encrypt account secrets stored in the database\",\n  version: '1.0.12'\n});\n\nPackage.onUse(function (api) {\n  api.use(\"npm-node-aes-gcm@=0.1.5_1\");\n\n  api.export(\"OAuthEncryption\", [\"server\"]);\n  api.use([\n    \"underscore\",\n    \"ejson\"\n  ]);\n  api.addFiles(\"encrypt.js\", [\"server\"]);\n});\n\nPackage.onTest(function (api) {\n  api.use(\"tinytest\");\n  api.use(\"oauth-encryption\");\n  api.addFiles(\"encrypt_tests.js\", [\"server\"]);\n});\n"
  },
  {
    "path": "packages/oauth1/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/oauth1/README.md",
    "content": "# oauth1\n\nCommon functionality for OAuth 1 clients. See the [project\npage](https://www.meteor.com/accounts) on Meteor Accounts for more\ndetails."
  },
  {
    "path": "packages/oauth1/oauth1_binding.js",
    "content": "var crypto = Npm.require(\"crypto\");\nvar querystring = Npm.require(\"querystring\");\nvar urlModule = Npm.require(\"url\");\n\n// An OAuth1 wrapper around http calls which helps get tokens and\n// takes care of HTTP headers\n//\n// @param config {Object}\n//   - consumerKey (String): oauth consumer key\n//   - secret (String): oauth consumer secret\n// @param urls {Object}\n//   - requestToken (String): url\n//   - authorize (String): url\n//   - accessToken (String): url\n//   - authenticate (String): url\nOAuth1Binding = function(config, urls) {\n  this._config = config;\n  this._urls = urls;\n};\n\nOAuth1Binding.prototype.prepareRequestToken = function(callbackUrl) {\n  var self = this;\n\n  var headers = self._buildHeader({\n    oauth_callback: callbackUrl\n  });\n\n  var response = self._call('POST', self._urls.requestToken, headers);\n  var tokens = querystring.parse(response.content);\n\n  if (! tokens.oauth_callback_confirmed)\n    throw _.extend(new Error(\"oauth_callback_confirmed false when requesting oauth1 token\"),\n                             {response: response});\n\n  self.requestToken = tokens.oauth_token;\n  self.requestTokenSecret = tokens.oauth_token_secret;\n};\n\nOAuth1Binding.prototype.prepareAccessToken = function(query, requestTokenSecret) {\n  var self = this;\n\n  // support implementations that use request token secrets. This is\n  // read by self._call.\n  //\n  // XXX make it a param to call, not something stashed on self? It's\n  // kinda confusing right now, everything except this is passed as\n  // arguments, but this is stored.\n  if (requestTokenSecret)\n    self.accessTokenSecret = requestTokenSecret;\n\n  var headers = self._buildHeader({\n    oauth_token: query.oauth_token,\n    oauth_verifier: query.oauth_verifier\n  });\n\n  var response = self._call('POST', self._urls.accessToken, headers);\n  var tokens = querystring.parse(response.content);\n\n  if (! tokens.oauth_token || ! tokens.oauth_token_secret) {\n    var error = new Error(\"missing oauth token or secret\");\n    // We provide response only if no token is available, we do not want to leak any tokens\n    if (! tokens.oauth_token && ! tokens.oauth_token_secret) {\n      _.extend(error, {response: response});\n    }\n    throw error;\n  }\n\n  self.accessToken = tokens.oauth_token;\n  self.accessTokenSecret = tokens.oauth_token_secret;\n};\n\nOAuth1Binding.prototype.call = function(method, url, params, callback) {\n  var self = this;\n\n  var headers = self._buildHeader({\n    oauth_token: self.accessToken\n  });\n\n  if(! params) {\n    params = {};\n  }\n\n  return self._call(method, url, headers, params, callback);\n};\n\nOAuth1Binding.prototype.get = function(url, params, callback) {\n  return this.call('GET', url, params, callback);\n};\n\nOAuth1Binding.prototype.post = function(url, params, callback) {\n  return this.call('POST', url, params, callback);\n};\n\nOAuth1Binding.prototype._buildHeader = function(headers) {\n  var self = this;\n  return _.extend({\n    oauth_consumer_key: self._config.consumerKey,\n    oauth_nonce: Random.secret().replace(/\\W/g, ''),\n    oauth_signature_method: 'HMAC-SHA1',\n    oauth_timestamp: (new Date().valueOf()/1000).toFixed().toString(),\n    oauth_version: '1.0'\n  }, headers);\n};\n\nOAuth1Binding.prototype._getSignature = function(method, url, rawHeaders, accessTokenSecret, params) {\n  var self = this;\n  var headers = self._encodeHeader(_.extend({}, rawHeaders, params));\n\n  var parameters = _.map(headers, function(val, key) {\n    return key + '=' + val;\n  }).sort().join('&');\n\n  var signatureBase = [\n    method,\n    self._encodeString(url),\n    self._encodeString(parameters)\n  ].join('&');\n\n  var secret = OAuth.openSecret(self._config.secret);\n\n  var signingKey = self._encodeString(secret) + '&';\n  if (accessTokenSecret)\n    signingKey += self._encodeString(accessTokenSecret);\n\n  return crypto.createHmac('SHA1', signingKey).update(signatureBase).digest('base64');\n};\n\nOAuth1Binding.prototype._call = function(method, url, headers, params, callback) {\n  var self = this;\n\n  // all URLs to be functions to support parameters/customization\n  if(typeof url === \"function\") {\n    url = url(self);\n  }\n\n  headers = headers || {};\n  params = params || {};\n\n  // Extract all query string parameters from the provided URL\n  var parsedUrl = urlModule.parse(url, true);\n  // Merge them in a way that params given to the method call have precedence\n  params = _.extend({}, parsedUrl.query, params);\n\n  // Reconstruct the URL back without any query string parameters\n  // (they are now in params)\n  parsedUrl.query = {};\n  parsedUrl.search = '';\n  url = urlModule.format(parsedUrl);\n\n  // Get the signature\n  headers.oauth_signature =\n    self._getSignature(method, url, headers, self.accessTokenSecret, params);\n\n  // Make a authorization string according to oauth1 spec\n  var authString = self._getAuthHeaderString(headers);\n\n  // Make signed request\n  try {\n    var response = HTTP.call(method, url, {\n      params: params,\n      headers: {\n        Authorization: authString\n      }\n    }, callback && function (error, response) {\n      if (! error) {\n        response.nonce = headers.oauth_nonce;\n      }\n      callback(error, response);\n    });\n    // We store nonce so that JWTs can be validated\n    if (response)\n      response.nonce = headers.oauth_nonce;\n    return response;\n  } catch (err) {\n    throw _.extend(new Error(\"Failed to send OAuth1 request to \" + url + \". \" + err.message),\n                   {response: err.response});\n  }\n};\n\nOAuth1Binding.prototype._encodeHeader = function(header) {\n  var self = this;\n  return _.reduce(header, function(memo, val, key) {\n    memo[self._encodeString(key)] = self._encodeString(val);\n    return memo;\n  }, {});\n};\n\nOAuth1Binding.prototype._encodeString = function(str) {\n  return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\\*/g, \"%2A\");\n};\n\nOAuth1Binding.prototype._getAuthHeaderString = function(headers) {\n  var self = this;\n  return 'OAuth ' +  _.map(headers, function(val, key) {\n    return self._encodeString(key) + '=\"' + self._encodeString(val) + '\"';\n  }).sort().join(', ');\n};\n"
  },
  {
    "path": "packages/oauth1/oauth1_pending_request_tokens.js",
    "content": "//\n// _pendingRequestTokens are request tokens that have been received\n// but not yet fully authorized (processed).\n//\n// During the oauth1 authorization process, the Meteor App opens\n// a pop-up, requests a request token from the oauth1 service, and\n// redirects the browser to the oauth1 service for the user\n// to grant authorization.  The user is then returned to the\n// Meteor Apps' callback url and the request token is verified.\n//\n// When Meteor Apps run on multiple servers, it's possible that\n// 2 different servers may be used to generate the request token\n// and to verify it in the callback once the user has authorized.\n//\n// For this reason, the _pendingRequestTokens are stored in the database\n// so they can be shared across Meteor App servers.\n//\n// XXX This code is fairly similar to oauth/pending_credentials.js --\n// maybe we can combine them somehow.\n\n// Collection containing pending request tokens\n// Has key, requestToken, requestTokenSecret, and createdAt fields.\nOAuth._pendingRequestTokens = new Mongo.Collection(\n  \"meteor_oauth_pendingRequestTokens\", {\n    _preventAutopublish: true\n  });\n\nOAuth._pendingRequestTokens._ensureIndex('key', {unique: 1});\nOAuth._pendingRequestTokens._ensureIndex('createdAt');\n\n\n\n// Periodically clear old entries that never got completed\nvar _cleanStaleResults = function() {\n  // Remove request tokens older than 5 minute\n  var timeCutoff = new Date();\n  timeCutoff.setMinutes(timeCutoff.getMinutes() - 5);\n  OAuth._pendingRequestTokens.remove({ createdAt: { $lt: timeCutoff } });\n};\nvar _cleanupHandle = Meteor.setInterval(_cleanStaleResults, 60 * 1000);\n\n\n// Stores the key and request token in the _pendingRequestTokens collection.\n// Will throw an exception if `key` is not a string.\n//\n// @param key {string}\n// @param requestToken {string}\n// @param requestTokenSecret {string}\n//\nOAuth._storeRequestToken = function (key, requestToken, requestTokenSecret) {\n  check(key, String);\n\n  // We do an upsert here instead of an insert in case the user happens\n  // to somehow send the same `state` parameter twice during an OAuth\n  // login; we don't want a duplicate key error.\n  OAuth._pendingRequestTokens.upsert({\n    key: key\n  }, {\n    key: key,\n    requestToken: OAuth.sealSecret(requestToken),\n    requestTokenSecret: OAuth.sealSecret(requestTokenSecret),\n    createdAt: new Date()\n  });\n};\n\n\n// Retrieves and removes a request token from the _pendingRequestTokens collection\n// Returns an object containing requestToken and requestTokenSecret properties\n//\n// @param key {string}\n//\nOAuth._retrieveRequestToken = function (key) {\n  check(key, String);\n\n  var pendingRequestToken = OAuth._pendingRequestTokens.findOne({ key: key });\n  if (pendingRequestToken) {\n    OAuth._pendingRequestTokens.remove({ _id: pendingRequestToken._id });\n    return {\n      requestToken: OAuth.openSecret(pendingRequestToken.requestToken),\n      requestTokenSecret: OAuth.openSecret(\n        pendingRequestToken.requestTokenSecret)\n    };\n  } else {\n    return undefined;\n  }\n};\n"
  },
  {
    "path": "packages/oauth1/oauth1_server.js",
    "content": "var url = Npm.require(\"url\");\n\n// connect middleware\nOAuth._requestHandlers['1'] = function (service, query, res) {\n  var config = ServiceConfiguration.configurations.findOne({service: service.serviceName});\n  if (! config) {\n    throw new ServiceConfiguration.ConfigError(service.serviceName);\n  }\n\n  var urls = service.urls;\n  var oauthBinding = new OAuth1Binding(config, urls);\n\n  var credentialSecret;\n\n  if (query.requestTokenAndRedirect) {\n    // step 1 - get and store a request token\n    var callbackUrl = OAuth._redirectUri(service.serviceName, config, {\n      state: query.state,\n      cordova: (query.cordova === \"true\"),\n      android: (query.android === \"true\")\n    });\n\n    // Get a request token to start auth process\n    oauthBinding.prepareRequestToken(callbackUrl);\n\n    // Keep track of request token so we can verify it on the next step\n    OAuth._storeRequestToken(\n      OAuth._credentialTokenFromQuery(query),\n      oauthBinding.requestToken,\n      oauthBinding.requestTokenSecret);\n\n    // support for scope/name parameters\n    var redirectUrl = undefined;\n    if(typeof urls.authenticate === \"function\") {\n      redirectUrl = urls.authenticate(oauthBinding, {\n        query: query\n      });\n    } else {\n      // Parse the URL to support additional query parameters in urls.authenticate\n      var redirectUrlObj = url.parse(urls.authenticate, true);\n      redirectUrlObj.query = redirectUrlObj.query || {};\n      redirectUrlObj.query.oauth_token = oauthBinding.requestToken;\n      redirectUrlObj.search = '';\n      // Reconstruct the URL back with provided query parameters merged with oauth_token\n      redirectUrl = url.format(redirectUrlObj);\n    }\n\n    // redirect to provider login, which will redirect back to \"step 2\" below\n\n    res.writeHead(302, {'Location': redirectUrl});\n    res.end();\n  } else {\n    // step 2, redirected from provider login - store the result\n    // and close the window to allow the login handler to proceed\n\n    // Get the user's request token so we can verify it and clear it\n    var requestTokenInfo = OAuth._retrieveRequestToken(\n      OAuth._credentialTokenFromQuery(query));\n\n    if (! requestTokenInfo) {\n      throw new Error(\"Unable to retrieve request token\");\n    }\n\n    // Verify user authorized access and the oauth_token matches\n    // the requestToken from previous step\n    if (query.oauth_token && query.oauth_token === requestTokenInfo.requestToken) {\n\n      // Prepare the login results before returning.  This way the\n      // subsequent call to the `login` method will be immediate.\n\n      // Get the access token for signing requests\n      oauthBinding.prepareAccessToken(query, requestTokenInfo.requestTokenSecret);\n\n      // Run service-specific handler.\n      var oauthResult = service.handleOauthRequest(\n        oauthBinding, { query: query });\n\n      var credentialToken = OAuth._credentialTokenFromQuery(query);\n      credentialSecret = Random.secret();\n\n      // Store the login result so it can be retrieved in another\n      // browser tab by the result handler\n      OAuth._storePendingCredential(credentialToken, {\n        serviceName: service.serviceName,\n        serviceData: oauthResult.serviceData,\n        options: oauthResult.options\n      }, credentialSecret);\n    }\n\n    // Either close the window, redirect, or render nothing\n    // if all else fails\n    OAuth._renderOauthResults(res, query, credentialSecret);\n  }\n};\n"
  },
  {
    "path": "packages/oauth1/oauth1_tests.js",
    "content": "var testPendingCredential = function (test) {\n  var http = Npm.require('http');\n  var twitterfooId = Random.id();\n  var twitterfooName = 'nickname' + Random.id();\n  var twitterfooAccessToken = Random.id();\n  var twitterfooAccessTokenSecret = Random.id();\n  var twitterOption1 = Random.id();\n  var credentialToken = Random.id();\n  var serviceName = Random.id();\n\n  var urls = {\n    requestToken: \"https://example.com/oauth/request_token\",\n    authorize: \"https://example.com/oauth/authorize\",\n    accessToken: \"https://example.com/oauth/access_token\",\n    authenticate: \"https://example.com/oauth/authenticate\"\n  };\n\n  OAuth1Binding.prototype.prepareRequestToken = function() {};\n  OAuth1Binding.prototype.prepareAccessToken = function() {\n    this.accessToken = twitterfooAccessToken;\n    this.accessTokenSecret = twitterfooAccessTokenSecret;\n  };\n\n  ServiceConfiguration.configurations.insert({service: serviceName});\n\n  try {\n    // register a fake login service\n    OAuth.registerService(serviceName, 1, urls, function (query) {\n      return {\n        serviceData: {\n          id: twitterfooId,\n          screenName: twitterfooName,\n          accessToken: OAuth.sealSecret(twitterfooAccessToken),\n          accessTokenSecret: OAuth.sealSecret(twitterfooAccessTokenSecret)\n        },\n        options: {\n          option1: twitterOption1\n        }\n      };\n    });\n\n    // simulate logging in using twitterfoo\n    Oauth._storeRequestToken(credentialToken, twitterfooAccessToken);\n\n    var req = {\n      method: \"POST\",\n      url: \"/_oauth/\" + serviceName,\n      query: {\n        state: OAuth._generateState('popup', credentialToken),\n        oauth_token: twitterfooAccessToken,\n        only_credential_secret_for_test: 1\n      }\n    };\n    var res = new http.ServerResponse(req);\n    var write = res.write;\n    var end = res.write;\n    var respData = \"\";\n    res.write = function (data, encoding, callback) {\n      respData += data;\n      return write.apply(this, arguments);\n    };\n    res.end = function (data) {\n      respData += data;\n      return end.apply(this, arguments);\n    };\n    OAuthTest.middleware(req, res);\n    var credentialSecret = respData;\n\n    // Test that the result for the token is available\n    var result = OAuth._retrievePendingCredential(credentialToken,\n                                                  credentialSecret);\n    var serviceData = OAuth.openSecrets(result.serviceData);\n    test.equal(result.serviceName, serviceName);\n    test.equal(serviceData.id, twitterfooId);\n    test.equal(serviceData.screenName, twitterfooName);\n    test.equal(serviceData.accessToken, twitterfooAccessToken);\n    test.equal(serviceData.accessTokenSecret, twitterfooAccessTokenSecret);\n    test.equal(result.options.option1, twitterOption1);\n\n    // Test that pending credential is removed after being retrieved\n    result = OAuth._retrievePendingCredential(credentialToken);\n    test.isUndefined(result);\n\n  } finally {\n    OAuthTest.unregisterService(serviceName);\n  }\n};\n\nTinytest.add(\"oauth1 - pendingCredential is stored and can be retrieved (without oauth encryption)\", function (test) {\n  OAuthEncryption.loadKey(null);\n  testPendingCredential(test);\n});\n\nTinytest.add(\"oauth1 - pendingCredential is stored and can be retrieved (with oauth encryption)\", function (test) {\n  try {\n    OAuthEncryption.loadKey(new Buffer([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]).toString(\"base64\"));\n    testPendingCredential(test);\n  } finally {\n    OAuthEncryption.loadKey(null);\n  }\n});\n\nTinytest.add(\"oauth1 - duplicate key for request token\", function (test) {\n  var key = Random.id();\n  var token = Random.id();\n  var secret = Random.id();\n  OAuth._storeRequestToken(key, token, secret);\n  var newToken = Random.id();\n  var newSecret = Random.id();\n  OAuth._storeRequestToken(key, newToken, newSecret);\n  var result = OAuth._retrieveRequestToken(key);\n  test.equal(result.requestToken, newToken);\n  test.equal(result.requestTokenSecret, newSecret);\n});\n\nTinytest.add(\"oauth1 - null, undefined key for request token\", function (test) {\n  var token = Random.id();\n  var secret = Random.id();\n  test.throws(function () {\n    OAuth._storeRequestToken(null, token, secret);\n  });\n  test.throws(function () {\n    OAuth._storeRequestToken(undefined, token, secret);\n  });\n});\n"
  },
  {
    "path": "packages/oauth1/package.js",
    "content": "Package.describe({\n  summary: \"Common code for OAuth1-based login services\",\n  version: \"1.1.10\"\n});\n\nPackage.onUse(function (api) {\n  api.use('random');\n  api.use('service-configuration', ['client', 'server']);\n  api.use('oauth', ['client', 'server']);\n  api.use([\n    'underscore',\n    'check',\n    'http'\n  ], 'server');\n\n  api.use('mongo');\n\n  api.export('OAuth1Binding', 'server');\n  api.export('OAuth1Test', 'server', {testOnly: true});\n\n  api.addFiles('oauth1_binding.js', 'server');\n  api.addFiles('oauth1_server.js', 'server');\n  api.addFiles('oauth1_pending_request_tokens.js', 'server');\n});\n\nPackage.onTest(function (api) {\n  api.use('tinytest');\n  api.use('random');\n  api.use('service-configuration', 'server');\n  api.use('oauth-encryption', 'server');\n  api.use('oauth1', 'server');\n  api.use('oauth', 'server');\n  api.addFiles(\"oauth1_tests.js\", 'server');\n});\n"
  },
  {
    "path": "packages/oauth2/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/oauth2/README.md",
    "content": "# oauth2\n\nCommon functionality for OAuth 2 clients. See the [project\npage](https://www.meteor.com/accounts) on Meteor Accounts for more\ndetails.\n"
  },
  {
    "path": "packages/oauth2/oauth2_server.js",
    "content": "// connect middleware\nOAuth._requestHandlers['2'] = function (service, query, res) {\n  // check if user authorized access\n  if (!query.error) {\n    // Prepare the login results before returning.\n\n    // Run service-specific handler.\n    var oauthResult = service.handleOauthRequest(query);\n    var credentialSecret = Random.secret();\n\n    var credentialToken = OAuth._credentialTokenFromQuery(query);\n\n    // Store the login result so it can be retrieved in another\n    // browser tab by the result handler\n    OAuth._storePendingCredential(credentialToken, {\n      serviceName: service.serviceName,\n      serviceData: oauthResult.serviceData,\n      options: oauthResult.options\n    }, credentialSecret);\n  }\n\n  // Either close the window, redirect, or render nothing\n  // if all else fails\n  OAuth._renderOauthResults(res, query, credentialSecret);\n};\n"
  },
  {
    "path": "packages/oauth2/oauth2_tests.js",
    "content": "var testPendingCredential = function (test) {\n  var http = Npm.require('http');\n  var foobookId = Random.id();\n  var foobookOption1 = Random.id();\n  var credentialToken = Random.id();\n  var serviceName = Random.id();\n\n  ServiceConfiguration.configurations.insert({service: serviceName});\n\n  try {\n    // register a fake login service\n    OAuth.registerService(serviceName, 2, null, function (query) {\n      return {\n        serviceData: {\n          id: foobookId,\n          secretStuff: OAuth.sealSecret(\"confidential\")\n        },\n        options: {option1: foobookOption1}\n      };\n    });\n\n    // simulate logging in using foobook\n    var req = {method: \"POST\",\n               url: \"/_oauth/\" + serviceName,\n               query: {\n                 state: OAuth._generateState('popup', credentialToken),\n                 close: 1,\n                 only_credential_secret_for_test: 1\n               }};\n    var res = new http.ServerResponse(req);\n    var write = res.write;\n    var end = res.write;\n    var respData = \"\";\n    res.write = function (data, encoding, callback) {\n      respData += data;\n      return write.apply(this, arguments);\n    };\n    res.end = function (data) {\n      respData += data;\n      return end.apply(this, arguments);\n    };\n\n    OAuthTest.middleware(req, res);\n    var credentialSecret = respData;\n\n    // Test that the result for the token is available\n    var result = OAuth._retrievePendingCredential(credentialToken,\n                                                  credentialSecret);\n    var serviceData = OAuth.openSecrets(result.serviceData);\n    test.equal(result.serviceName, serviceName);\n    test.equal(serviceData.id, foobookId);\n    test.equal(serviceData.secretStuff, 'confidential');\n    test.equal(result.options.option1, foobookOption1);\n\n    // Test that pending credential is removed after being retrieved\n    result = OAuth._retrievePendingCredential(credentialToken);\n    test.isUndefined(result);\n\n  } finally {\n    OAuthTest.unregisterService(serviceName);\n  }\n};\n\nTinytest.add(\"oauth2 - pendingCredential is stored and can be retrieved (without oauth encryption)\", function (test) {\n  OAuthEncryption.loadKey(null);\n  testPendingCredential(test);\n});\n\nTinytest.add(\"oauth2 - pendingCredential is stored and can be retrieved (with oauth encryption)\", function (test) {\n  try {\n    OAuthEncryption.loadKey(new Buffer([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]).toString(\"base64\"));\n    testPendingCredential(test);\n  } finally {\n    OAuthEncryption.loadKey(null);\n  }\n});\n"
  },
  {
    "path": "packages/oauth2/package.js",
    "content": "Package.describe({\n  summary: \"Common code for OAuth2-based login services\",\n  version: \"1.1.10\"\n});\n\nPackage.onUse(function (api) {\n  api.use([\n    'random'\n  ], 'server');\n\n  api.use([\n    'oauth',\n    'service-configuration'\n  ], ['client', 'server']);\n\n  api.addFiles('oauth2_server.js', 'server');\n});\n\nPackage.onTest(function (api) {\n  api.use([\n    'tinytest',\n    'random',\n    'oauth2',\n    'oauth',\n    'service-configuration',\n    'oauth-encryption'\n  ], 'server');\n\n  api.addFiles(\"oauth2_tests.js\", 'server');\n});\n"
  },
  {
    "path": "packages/observe-sequence/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/observe-sequence/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/observe-sequence/observe_sequence.js",
    "content": "var warn = function () {\n  if (ObserveSequence._suppressWarnings) {\n    ObserveSequence._suppressWarnings--;\n  } else {\n    if (typeof console !== 'undefined' && console.warn)\n      console.warn.apply(console, arguments);\n\n    ObserveSequence._loggedWarnings++;\n  }\n};\n\nvar idStringify = MongoID.idStringify;\nvar idParse = MongoID.idParse;\n\nObserveSequence = {\n  _suppressWarnings: 0,\n  _loggedWarnings: 0,\n\n  // A mechanism similar to cursor.observe which receives a reactive\n  // function returning a sequence type and firing appropriate callbacks\n  // when the value changes.\n  //\n  // @param sequenceFunc {Function} a reactive function returning a\n  //     sequence type. The currently supported sequence types are:\n  //     Array, Cursor, and null.\n  //\n  // @param callbacks {Object} similar to a specific subset of\n  //     callbacks passed to `cursor.observe`\n  //     (http://docs.meteor.com/#observe), with minor variations to\n  //     support the fact that not all sequences contain objects with\n  //     _id fields.  Specifically:\n  //\n  //     * addedAt(id, item, atIndex, beforeId)\n  //     * changedAt(id, newItem, oldItem, atIndex)\n  //     * removedAt(id, oldItem, atIndex)\n  //     * movedTo(id, item, fromIndex, toIndex, beforeId)\n  //\n  // @returns {Object(stop: Function)} call 'stop' on the return value\n  //     to stop observing this sequence function.\n  //\n  // We don't make any assumptions about our ability to compare sequence\n  // elements (ie, we don't assume EJSON.equals works; maybe there is extra\n  // state/random methods on the objects) so unlike cursor.observe, we may\n  // sometimes call changedAt() when nothing actually changed.\n  // XXX consider if we *can* make the stronger assumption and avoid\n  //     no-op changedAt calls (in some cases?)\n  //\n  // XXX currently only supports the callbacks used by our\n  // implementation of {{#each}}, but this can be expanded.\n  //\n  // XXX #each doesn't use the indices (though we'll eventually need\n  // a way to get them when we support `@index`), but calling\n  // `cursor.observe` causes the index to be calculated on every\n  // callback using a linear scan (unless you turn it off by passing\n  // `_no_indices`).  Any way to avoid calculating indices on a pure\n  // cursor observe like we used to?\n  observe: function (sequenceFunc, callbacks) {\n    var lastSeq = null;\n    var activeObserveHandle = null;\n\n    // 'lastSeqArray' contains the previous value of the sequence\n    // we're observing. It is an array of objects with '_id' and\n    // 'item' fields.  'item' is the element in the array, or the\n    // document in the cursor.\n    //\n    // '_id' is whichever of the following is relevant, unless it has\n    // already appeared -- in which case it's randomly generated.\n    //\n    // * if 'item' is an object:\n    //   * an '_id' field, if present\n    //   * otherwise, the index in the array\n    //\n    // * if 'item' is a number or string, use that value\n    //\n    // XXX this can be generalized by allowing {{#each}} to accept a\n    // general 'key' argument which could be a function, a dotted\n    // field name, or the special @index value.\n    var lastSeqArray = []; // elements are objects of form {_id, item}\n    var computation = Tracker.autorun(function () {\n      var seq = sequenceFunc();\n\n      Tracker.nonreactive(function () {\n        var seqArray; // same structure as `lastSeqArray` above.\n\n        if (activeObserveHandle) {\n          // If we were previously observing a cursor, replace lastSeqArray with\n          // more up-to-date information.  Then stop the old observe.\n          lastSeqArray = _.map(lastSeq.fetch(), function (doc) {\n            return {_id: doc._id, item: doc};\n          });\n          activeObserveHandle.stop();\n          activeObserveHandle = null;\n        }\n\n        if (!seq) {\n          seqArray = seqChangedToEmpty(lastSeqArray, callbacks);\n        } else if (seq instanceof Array) {\n          seqArray = seqChangedToArray(lastSeqArray, seq, callbacks);\n        } else if (isStoreCursor(seq)) {\n          var result /* [seqArray, activeObserveHandle] */ =\n                seqChangedToCursor(lastSeqArray, seq, callbacks);\n          seqArray = result[0];\n          activeObserveHandle = result[1];\n        } else {\n          throw badSequenceError();\n        }\n\n        diffArray(lastSeqArray, seqArray, callbacks);\n        lastSeq = seq;\n        lastSeqArray = seqArray;\n      });\n    });\n\n    return {\n      stop: function () {\n        computation.stop();\n        if (activeObserveHandle)\n          activeObserveHandle.stop();\n      }\n    };\n  },\n\n  // Fetch the items of `seq` into an array, where `seq` is of one of the\n  // sequence types accepted by `observe`.  If `seq` is a cursor, a\n  // dependency is established.\n  fetch: function (seq) {\n    if (!seq) {\n      return [];\n    } else if (seq instanceof Array) {\n      return seq;\n    } else if (isStoreCursor(seq)) {\n      return seq.fetch();\n    } else {\n      throw badSequenceError();\n    }\n  }\n};\n\nvar badSequenceError = function () {\n  return new Error(\"{{#each}} currently only accepts \" +\n                   \"arrays, cursors or falsey values.\");\n};\n\nvar isStoreCursor = function (cursor) {\n  return cursor && _.isObject(cursor) &&\n    _.isFunction(cursor.observe) && _.isFunction(cursor.fetch);\n};\n\n// Calculates the differences between `lastSeqArray` and\n// `seqArray` and calls appropriate functions from `callbacks`.\n// Reuses Minimongo's diff algorithm implementation.\nvar diffArray = function (lastSeqArray, seqArray, callbacks) {\n  var diffFn = Package['diff-sequence'].DiffSequence.diffQueryOrderedChanges;\n  var oldIdObjects = [];\n  var newIdObjects = [];\n  var posOld = {}; // maps from idStringify'd ids\n  var posNew = {}; // ditto\n  var posCur = {};\n  var lengthCur = lastSeqArray.length;\n\n  _.each(seqArray, function (doc, i) {\n    newIdObjects.push({_id: doc._id});\n    posNew[idStringify(doc._id)] = i;\n  });\n  _.each(lastSeqArray, function (doc, i) {\n    oldIdObjects.push({_id: doc._id});\n    posOld[idStringify(doc._id)] = i;\n    posCur[idStringify(doc._id)] = i;\n  });\n\n  // Arrays can contain arbitrary objects. We don't diff the\n  // objects. Instead we always fire 'changedAt' callback on every\n  // object. The consumer of `observe-sequence` should deal with\n  // it appropriately.\n  diffFn(oldIdObjects, newIdObjects, {\n    addedBefore: function (id, doc, before) {\n      var position = before ? posCur[idStringify(before)] : lengthCur;\n\n      if (before) {\n        // If not adding at the end, we need to update indexes.\n        // XXX this can still be improved greatly!\n        _.each(posCur, function (pos, id) {\n          if (pos >= position)\n            posCur[id]++;\n        });\n      }\n\n      lengthCur++;\n      posCur[idStringify(id)] = position;\n\n      callbacks.addedAt(\n        id,\n        seqArray[posNew[idStringify(id)]].item,\n        position,\n        before);\n    },\n    movedBefore: function (id, before) {\n      if (id === before)\n        return;\n\n      var oldPosition = posCur[idStringify(id)];\n      var newPosition = before ? posCur[idStringify(before)] : lengthCur;\n\n      // Moving the item forward. The new element is losing one position as it\n      // was removed from the old position before being inserted at the new\n      // position.\n      // Ex.:   0  *1*  2   3   4\n      //        0   2   3  *1*  4\n      // The original issued callback is \"1\" before \"4\".\n      // The position of \"1\" is 1, the position of \"4\" is 4.\n      // The generated move is (1) -> (3)\n      if (newPosition > oldPosition) {\n        newPosition--;\n      }\n\n      // Fix up the positions of elements between the old and the new positions\n      // of the moved element.\n      //\n      // There are two cases:\n      //   1. The element is moved forward. Then all the positions in between\n      //   are moved back.\n      //   2. The element is moved back. Then the positions in between *and* the\n      //   element that is currently standing on the moved element's future\n      //   position are moved forward.\n      _.each(posCur, function (elCurPosition, id) {\n        if (oldPosition < elCurPosition && elCurPosition < newPosition)\n          posCur[id]--;\n        else if (newPosition <= elCurPosition && elCurPosition < oldPosition)\n          posCur[id]++;\n      });\n\n      // Finally, update the position of the moved element.\n      posCur[idStringify(id)] = newPosition;\n\n      callbacks.movedTo(\n        id,\n        seqArray[posNew[idStringify(id)]].item,\n        oldPosition,\n        newPosition,\n        before);\n    },\n    removed: function (id) {\n      var prevPosition = posCur[idStringify(id)];\n\n      _.each(posCur, function (pos, id) {\n        if (pos >= prevPosition)\n          posCur[id]--;\n      });\n\n      delete posCur[idStringify(id)];\n      lengthCur--;\n\n      callbacks.removedAt(\n        id,\n        lastSeqArray[posOld[idStringify(id)]].item,\n        prevPosition);\n    }\n  });\n\n  _.each(posNew, function (pos, idString) {\n    var id = idParse(idString);\n    if (_.has(posOld, idString)) {\n      // specifically for primitive types, compare equality before\n      // firing the 'changedAt' callback. otherwise, always fire it\n      // because doing a deep EJSON comparison is not guaranteed to\n      // work (an array can contain arbitrary objects, and 'transform'\n      // can be used on cursors). also, deep diffing is not\n      // necessarily the most efficient (if only a specific subfield\n      // of the object is later accessed).\n      var newItem = seqArray[pos].item;\n      var oldItem = lastSeqArray[posOld[idString]].item;\n\n      if (typeof newItem === 'object' || newItem !== oldItem)\n          callbacks.changedAt(id, newItem, oldItem, pos);\n      }\n  });\n};\n\nseqChangedToEmpty = function (lastSeqArray, callbacks) {\n  return [];\n};\n\nseqChangedToArray = function (lastSeqArray, array, callbacks) {\n  var idsUsed = {};\n  var seqArray = _.map(array, function (item, index) {\n    var id;\n    if (typeof item === 'string') {\n      // ensure not empty, since other layers (eg DomRange) assume this as well\n      id = \"-\" + item;\n    } else if (typeof item === 'number' ||\n               typeof item === 'boolean' ||\n               item === undefined) {\n      id = item;\n    } else if (typeof item === 'object') {\n      id = (item && ('_id' in item)) ? item._id : index;\n    } else {\n      throw new Error(\"{{#each}} doesn't support arrays with \" +\n                      \"elements of type \" + typeof item);\n    }\n\n    var idString = idStringify(id);\n    if (idsUsed[idString]) {\n      if (typeof item === 'object' && '_id' in item)\n        warn(\"duplicate id \" + id + \" in\", array);\n      id = Random.id();\n    } else {\n      idsUsed[idString] = true;\n    }\n\n    return { _id: id, item: item };\n  });\n\n  return seqArray;\n};\n\nseqChangedToCursor = function (lastSeqArray, cursor, callbacks) {\n  var initial = true; // are we observing initial data from cursor?\n  var seqArray = [];\n\n  var observeHandle = cursor.observe({\n    addedAt: function (document, atIndex, before) {\n      if (initial) {\n        // keep track of initial data so that we can diff once\n        // we exit `observe`.\n        if (before !== null)\n          throw new Error(\"Expected initial data from observe in order\");\n        seqArray.push({ _id: document._id, item: document });\n      } else {\n        callbacks.addedAt(document._id, document, atIndex, before);\n      }\n    },\n    changedAt: function (newDocument, oldDocument, atIndex) {\n      callbacks.changedAt(newDocument._id, newDocument, oldDocument,\n                          atIndex);\n    },\n    removedAt: function (oldDocument, atIndex) {\n      callbacks.removedAt(oldDocument._id, oldDocument, atIndex);\n    },\n    movedTo: function (document, fromIndex, toIndex, before) {\n      callbacks.movedTo(\n        document._id, document, fromIndex, toIndex, before);\n    }\n  });\n  initial = false;\n\n  return [seqArray, observeHandle];\n};\n"
  },
  {
    "path": "packages/observe-sequence/observe_sequence_tests.js",
    "content": "// Run a function named `run` which modifies a sequence. While it\n// executes, observe changes to the sequence and accumulate them in an\n// array, canonicalizing as necessary. Then make sure the results are\n// the same as passed in `expectedCallbacks`. In items in\n// `expectedCallbacks`, allow for special values of the form {NOT:\n// \"foo\"}, which match anything other than \"foo\".\n//\n// @param test {Object} as passed to Tinytest.add\n// @param sequenceFunc {Function(): sequence type}\n// @param run {Function()} modify the sequence or cause sequenceFunc\n//     to be recomupted\n// @param expectedCallbacks {Array}\n//     elements are objects eg {addedAt: [array of arguments]}\n// @param numExpectedWarnings {Number}\nrunOneObserveSequenceTestCase = function (test, sequenceFunc,\n                                          run, expectedCallbacks,\n                                          numExpectedWarnings) {\n  if (numExpectedWarnings)\n    ObserveSequence._suppressWarnings += numExpectedWarnings;\n\n  var firedCallbacks = [];\n  var handle = ObserveSequence.observe(sequenceFunc, {\n    addedAt: function () {\n      firedCallbacks.push({addedAt: _.toArray(arguments)});\n    },\n    changedAt: function () {\n      var obj = {changedAt: _.toArray(arguments)};\n\n      // Browsers are inconsistent about the order in which 'changedAt'\n      // callbacks fire. To ensure consistent behavior of these tests,\n      // we can't simply push `obj` at the end of `firedCallbacks` as\n      // we do for the other callbacks. Instead, we use insertion sort\n      // to place `obj` in a canonical position within the chunk of\n      // contiguously recently fired 'changedAt' callbacks.\n      for (var i = firedCallbacks.length; i > 0; i--) {\n\n        var compareTo = firedCallbacks[i - 1];\n        if (!compareTo.changedAt)\n          break;\n\n        if (EJSON.stringify(compareTo, {canonical: true}) <\n            EJSON.stringify(obj, {canonical: true}))\n          break;\n      }\n\n      firedCallbacks.splice(i, 0, obj);\n    },\n    removedAt: function () {\n      firedCallbacks.push({removedAt: _.toArray(arguments)});\n    },\n    movedTo: function () {\n      firedCallbacks.push({movedTo: _.toArray(arguments)});\n    }\n  });\n\n  run();\n  Tracker.flush();\n  handle.stop();\n\n  test.equal(ObserveSequence._suppressWarnings, 0);\n  test.equal(ObserveSequence._loggedWarnings, 0);\n  ObserveSequence._loggedWarnings = 0;\n\n  // any expected argument this is `{NOT: \"foo\"}`, should match any\n  // corresponding value in the fired callbacks other than \"foo\". so,\n  // assert non-equality and then replace the appropriate entries in\n  // the 'firedCallbacks' array with `{NOT: \"foo\"}` before calling\n  // `test.equal` below.\n  var commonLength = Math.min(firedCallbacks.length, expectedCallbacks.length);\n  for (var i = 0; i < commonLength; i++) {\n    var callback = expectedCallbacks[i];\n    if (_.keys(callback).length !== 1)\n      throw new Error(\"Callbacks should be objects with one key, eg `addedAt`\");\n    var callbackName = _.keys(callback)[0];\n    var args = _.values(callback)[0];\n    _.each(args, function (arg, argIndex) {\n      if (arg && typeof arg === 'object' &&\n          'NOT' in arg &&\n          firedCallbacks[i][callbackName]) {\n        test.notEqual(firedCallbacks[i][callbackName][argIndex],\n                      arg.NOT, \"Should be NOT \" + arg.NOT);\n        firedCallbacks[i][callbackName][argIndex] = arg;\n      }\n    });\n  }\n\n  var compress = function (str) {\n    return str.replace(/\\[\\n\\s*/gm, \"[\").replace(/\\{\\n\\s*/gm, \"{\").\n      replace(/\\n\\s*\\]/gm, \"]\").replace(/\\n\\s*\\}/gm, \"}\");\n  };\n\n  test.equal(compress(EJSON.stringify(firedCallbacks, {canonical: true, indent: true})),\n             compress(EJSON.stringify(expectedCallbacks, {canonical: true, indent: true})));\n};\n\nTinytest.add('observe-sequence - initial data for all sequence types', function (test) {\n  runOneObserveSequenceTestCase(test, function () {\n    return null;\n  }, function () {}, []);\n\n  runOneObserveSequenceTestCase(test, function () {\n    return [];\n  }, function () {}, []);\n\n  runOneObserveSequenceTestCase(test, function () {\n    return [{foo: 1}, {bar: 2}];\n  }, function () {}, [\n    {addedAt: [0, {foo: 1}, 0, null]},\n    {addedAt: [1, {bar: 2}, 1, null]}\n  ]);\n\n  runOneObserveSequenceTestCase(test, function () {\n    return [{_id: \"13\", foo: 1}, {_id: \"37\", bar: 2}];\n  }, function () {}, [\n    {addedAt: [\"13\", {_id: \"13\", foo: 1}, 0, null]},\n    {addedAt: [\"37\", {_id: \"37\", bar: 2}, 1, null]}\n  ]);\n\n  runOneObserveSequenceTestCase(test, function () {\n    var coll = new Mongo.Collection(null);\n    coll.insert({_id: \"13\", foo: 1});\n    coll.insert({_id: \"37\", bar: 2});\n    var cursor = coll.find({}, {sort: {_id: 1}});\n    return cursor;\n  }, function () {}, [\n    {addedAt: [\"13\", {_id: \"13\", foo: 1}, 0, null]},\n    {addedAt: [\"37\", {_id: \"37\", bar: 2}, 1, null]}\n  ]);\n\n  // shouldn't break on array with duplicate _id's, and the ids sent\n  // in the callbacks should be distinct\n  runOneObserveSequenceTestCase(test, function () {\n    return [\n      {_id: \"13\", foo: 1},\n      {_id: \"13\", foo: 2}\n    ];\n  }, function () {}, [\n    {addedAt: [\"13\", {_id: \"13\", foo: 1}, 0, null]},\n    {addedAt: [{NOT: \"13\"}, {_id: \"13\", foo: 2}, 1, null]}\n  ], /*numExpectedWarnings = */1);\n});\n\nTinytest.add('observe-sequence - array to other array', function (test) {\n  var dep = new Tracker.Dependency;\n  var seq = [{_id: \"13\", foo: 1}, {_id: \"37\", bar: 2}];\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    seq = [{_id: \"13\", foo: 1}, {_id: \"38\", bar: 2}];\n    dep.changed();\n  }, [\n    {addedAt: [\"13\", {_id: \"13\", foo: 1}, 0, null]},\n    {addedAt: [\"37\", {_id: \"37\", bar: 2}, 1, null]},\n    {removedAt: [\"37\", {_id: \"37\", bar: 2}, 1]},\n    {addedAt: [\"38\", {_id: \"38\", bar: 2}, 1, null]},\n    {changedAt: [\"13\", {_id: \"13\", foo: 1}, {_id: \"13\", foo: 1}, 0]}\n  ]);\n});\n\nTinytest.add('observe-sequence - array to other array, strings', function (test) {\n  var dep = new Tracker.Dependency;\n  var seq = [\"A\", \"B\"];\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    seq = [\"B\", \"C\"];\n    dep.changed();\n  }, [\n    {addedAt: [\"-A\", \"A\", 0, null]},\n    {addedAt: [\"-B\", \"B\", 1, null]},\n    {removedAt: [\"-A\", \"A\", 0]},\n    {addedAt: [\"-C\", \"C\", 1, null]}\n  ]);\n});\n\nTinytest.add('observe-sequence - array to other array, objects without ids', function (test) {\n  var dep = new Tracker.Dependency;\n  var seq = [{foo: 1}, {bar: 2}];\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    seq = [{foo: 2}];\n    dep.changed();\n  }, [\n    {addedAt: [0, {foo: 1}, 0, null]},\n    {addedAt: [1, {bar: 2}, 1, null]},\n    {removedAt: [1, {bar: 2}, 1]},\n    {changedAt: [0, {foo: 2}, {foo: 1}, 0]}\n  ]);\n});\n\nTinytest.add('observe-sequence - array to other array, changes', function (test) {\n  var dep = new Tracker.Dependency;\n  var seq = [{_id: \"13\", foo: 1}, {_id: \"37\", bar: 2}, {_id: \"42\", baz: 42}];\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    seq = [{_id: \"13\", foo: 1}, {_id: \"38\", bar: 2}, {_id: \"42\", baz: 43}];\n    dep.changed();\n  }, [\n    {addedAt: [\"13\", {_id: \"13\", foo: 1}, 0, null]},\n    {addedAt: [\"37\", {_id: \"37\", bar: 2}, 1, null]},\n    {addedAt: [\"42\", {_id: \"42\", baz: 42}, 2, null]},\n    {removedAt: [\"37\", {_id: \"37\", bar: 2}, 1]},\n    {addedAt: [\"38\", {_id: \"38\", bar: 2}, 1, \"42\"]},\n    // change fires for all elements, because we don't diff the actual\n    // objects.\n    {changedAt: [\"13\", {_id: \"13\", foo: 1}, {_id: \"13\", foo: 1}, 0]},\n    {changedAt: [\"42\", {_id: \"42\", baz: 43}, {_id: \"42\", baz: 42}, 2]}\n  ]);\n});\n\nTinytest.add('observe-sequence - array to other array, movedTo', function (test) {\n  var dep = new Tracker.Dependency;\n  var seq = [{_id: \"13\", foo: 1}, {_id: \"37\", bar: 2}, {_id: \"42\", baz: 42}, {_id: \"43\", baz: 43}];\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    seq = [{_id: \"43\", baz: 43}, {_id: \"37\", bar: 2}, {_id: \"42\", baz: 42}, {_id: \"13\", foo: 1}];\n    dep.changed();\n  }, [\n    {addedAt: [\"13\", {_id: \"13\", foo: 1}, 0, null]},\n    {addedAt: [\"37\", {_id: \"37\", bar: 2}, 1, null]},\n    {addedAt: [\"42\", {_id: \"42\", baz: 42}, 2, null]},\n    {addedAt: [\"43\", {_id: \"43\", baz: 43}, 3, null]},\n\n    {movedTo: [\"43\", {_id: \"43\", baz: 43}, 3, 1, \"37\"]},\n    {movedTo: [\"13\", {_id: \"13\", foo: 1}, 0, 3, null]},\n\n    {changedAt: [\"13\", {_id: \"13\", foo: 1}, {_id: \"13\", foo: 1}, 3]},\n    {changedAt: [\"37\", {_id: \"37\", bar: 2}, {_id: \"37\", bar: 2}, 1]},\n    {changedAt: [\"42\", {_id: \"42\", baz: 42}, {_id: \"42\", baz: 42}, 2]},\n    {changedAt: [\"43\", {_id: \"43\", baz: 43}, {_id: \"43\", baz: 43}, 0]}\n  ]);\n});\n\nTinytest.add('observe-sequence - array to other array, movedTo the end', function (test) {\n  var dep = new Tracker.Dependency;\n  var seq = [{_id: \"0\"}, {_id: \"1\"}, {_id: \"2\"}, {_id: \"3\"}];\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    seq = [{_id: \"0\"}, {_id: \"2\"}, {_id: \"3\"}, {_id: \"1\"}];\n    dep.changed();\n  }, [\n    {addedAt: [\"0\", {_id: \"0\"}, 0, null]},\n    {addedAt: [\"1\", {_id: \"1\"}, 1, null]},\n    {addedAt: [\"2\", {_id: \"2\"}, 2, null]},\n    {addedAt: [\"3\", {_id: \"3\"}, 3, null]},\n\n    {movedTo: [\"1\", {_id: \"1\"}, 1, 3, null]},\n    {changedAt: [\"0\", {_id: \"0\"}, {_id: \"0\"}, 0]},\n    {changedAt: [\"1\", {_id: \"1\"}, {_id: \"1\"}, 3]},\n    {changedAt: [\"2\", {_id: \"2\"}, {_id: \"2\"}, 1]},\n    {changedAt: [\"3\", {_id: \"3\"}, {_id: \"3\"}, 2]}\n  ]);\n});\n\nTinytest.add('observe-sequence - array to other array, movedTo later position but not the latest #2845', function (test) {\n  var dep = new Tracker.Dependency;\n  var seq = [{_id: \"0\"}, {_id: \"1\"}, {_id: \"2\"}, {_id: \"3\"}];\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    seq = [{_id: \"1\"}, {_id: \"2\"}, {_id: \"0\"}, {_id: \"3\"}];\n    dep.changed();\n  }, [\n    {addedAt: [\"0\", {_id: \"0\"}, 0, null]},\n    {addedAt: [\"1\", {_id: \"1\"}, 1, null]},\n    {addedAt: [\"2\", {_id: \"2\"}, 2, null]},\n    {addedAt: [\"3\", {_id: \"3\"}, 3, null]},\n\n    {movedTo: [\"0\", {_id: \"0\"}, 0, 2, \"3\"]},\n\n    {changedAt: [\"0\", {_id: \"0\"}, {_id: \"0\"}, 2]},\n    {changedAt: [\"1\", {_id: \"1\"}, {_id: \"1\"}, 0]},\n    {changedAt: [\"2\", {_id: \"2\"}, {_id: \"2\"}, 1]},\n    {changedAt: [\"3\", {_id: \"3\"}, {_id: \"3\"}, 3]}\n  ]);\n});\n\nTinytest.add('observe-sequence - array to other array, movedTo earlier position but not the first', function (test) {\n  var dep = new Tracker.Dependency;\n  var seq = [{_id: \"0\"}, {_id: \"1\"}, {_id: \"2\"}, {_id: \"3\"}, {_id: \"4\"}];\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    seq = [{_id: \"0\"}, {_id: \"4\"}, {_id: \"1\"}, {_id: \"2\"}, {_id: \"3\"}];\n    dep.changed();\n  }, [\n    {addedAt: [\"0\", {_id: \"0\"}, 0, null]},\n    {addedAt: [\"1\", {_id: \"1\"}, 1, null]},\n    {addedAt: [\"2\", {_id: \"2\"}, 2, null]},\n    {addedAt: [\"3\", {_id: \"3\"}, 3, null]},\n    {addedAt: [\"4\", {_id: \"4\"}, 4, null]},\n\n    {movedTo: [\"4\", {_id: \"4\"}, 4, 1, \"1\"]},\n\n    {changedAt: [\"0\", {_id: \"0\"}, {_id: \"0\"}, 0]},\n    {changedAt: [\"1\", {_id: \"1\"}, {_id: \"1\"}, 2]},\n    {changedAt: [\"2\", {_id: \"2\"}, {_id: \"2\"}, 3]},\n    {changedAt: [\"3\", {_id: \"3\"}, {_id: \"3\"}, 4]},\n    {changedAt: [\"4\", {_id: \"4\"}, {_id: \"4\"}, 1]}\n  ]);\n});\n\nTinytest.add('observe-sequence - array to null', function (test) {\n  var dep = new Tracker.Dependency;\n  var seq = [{_id: \"13\", foo: 1}, {_id: \"37\", bar: 2}];\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    seq = null;\n    dep.changed();\n  }, [\n    {addedAt: [\"13\", {_id: \"13\", foo: 1}, 0, null]},\n    {addedAt: [\"37\", {_id: \"37\", bar: 2}, 1, null]},\n    {removedAt: [\"13\", {_id: \"13\", foo: 1}, 0]},\n    {removedAt: [\"37\", {_id: \"37\", bar: 2}, 0]}\n  ]);\n});\n\nTinytest.add('observe-sequence - array to cursor', function (test) {\n  var dep = new Tracker.Dependency;\n  var seq = [{_id: \"13\", foo: 1}, {_id: \"37\", bar: 2}];\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    var coll = new Mongo.Collection(null);\n    coll.insert({_id: \"13\", foo: 1});\n    coll.insert({_id: \"38\", bar: 2});\n    var cursor = coll.find({}, {sort: {_id: 1}});\n    seq = cursor;\n    dep.changed();\n  }, [\n    {addedAt: [\"13\", {_id: \"13\", foo: 1}, 0, null]},\n    {addedAt: [\"37\", {_id: \"37\", bar: 2}, 1, null]},\n    {removedAt: [\"37\", {_id: \"37\", bar: 2}, 1]},\n    {addedAt: [\"38\", {_id: \"38\", bar: 2}, 1, null]},\n    {changedAt: [\"13\", {_id: \"13\", foo: 1}, {_id: \"13\", foo: 1}, 0]}\n  ]);\n});\n\n\nTinytest.add('observe-sequence - cursor to null', function (test) {\n  var dep = new Tracker.Dependency;\n  var coll = new Mongo.Collection(null);\n  coll.insert({_id: \"13\", foo: 1});\n  coll.insert({_id: \"37\", bar: 2});\n  var cursor = coll.find({}, {sort: {_id: 1}});\n  var seq = cursor;\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    seq = null;\n    dep.changed();\n  }, [\n    {addedAt: [\"13\", {_id: \"13\", foo: 1}, 0, null]},\n    {addedAt: [\"37\", {_id: \"37\", bar: 2}, 1, null]},\n    {removedAt: [\"13\", {_id: \"13\", foo: 1}, 0]},\n    {removedAt: [\"37\", {_id: \"37\", bar: 2}, 0]}\n  ]);\n});\n\nTinytest.add('observe-sequence - cursor to array', function (test) {\n  var dep = new Tracker.Dependency;\n  var coll = new Mongo.Collection(null);\n  coll.insert({_id: \"13\", foo: 1});\n  var cursor = coll.find({}, {sort: {_id: 1}});\n  var seq = cursor;\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    coll.insert({_id: \"37\", bar: 2});\n    seq = [{_id: \"13\", foo: 1}, {_id: \"38\", bar: 2}];\n    dep.changed();\n  }, [\n    {addedAt: [\"13\", {_id: \"13\", foo: 1}, 0, null]},\n    {addedAt: [\"37\", {_id: \"37\", bar: 2}, 1, null]},\n    {removedAt: [\"37\", {_id: \"37\", bar: 2}, 1]},\n    {addedAt: [\"38\", {_id: \"38\", bar: 2}, 1, null]},\n    {changedAt: [\"13\", {_id: \"13\", foo: 1}, {_id: \"13\", foo: 1}, 0]}\n  ]);\n});\n\nTinytest.add('observe-sequence - cursor', function (test) {\n  var coll = new Mongo.Collection(null);\n  coll.insert({_id: \"13\", rank: 1});\n  var cursor = coll.find({}, {sort: {rank: 1}});\n  var seq = cursor;\n\n  runOneObserveSequenceTestCase(test, function () {\n    return seq;\n  }, function () {\n    coll.insert({_id: \"37\", rank: 2});\n    coll.insert({_id: \"77\", rank: 3});\n    coll.remove({_id: \"37\"});                           // should fire a 'removedAt' callback\n    coll.insert({_id: \"11\", rank: 0});                  // should fire an 'addedAt' callback\n    coll.update({_id: \"13\"}, {$set: {updated: true}});  // should fire an 'changedAt' callback\n    coll.update({_id: \"77\"}, {$set: {rank: -1}});       // should fire 'changedAt' and 'movedTo' callback\n  }, [\n    // this case must not fire spurious calls as the array to array\n    // case does. otherwise, the entire power of cursors is lost in\n    // blaze.\n    {addedAt: [\"13\", {_id: \"13\", rank: 1}, 0, null]},\n    {addedAt: [\"37\", {_id: \"37\", rank: 2}, 1, null]},\n    {addedAt: [\"77\", {_id: \"77\", rank: 3}, 2, null]},\n    {removedAt: [\"37\", {_id: \"37\", rank: 2}, 1]},\n    {addedAt: [\"11\", {_id: \"11\", rank: 0}, 0, \"13\"]},\n    {changedAt: [\"13\", {_id: \"13\", rank: 1, updated: true}, {_id: \"13\", rank: 1}, 1]},\n    {changedAt: [\"77\", {_id: \"77\", rank: -1}, {_id: \"77\", rank: 3}, 2]},\n    {movedTo: [\"77\", {_id: \"77\", rank: -1}, 2, 0, \"11\"]}\n  ]);\n});\n\nTinytest.add('observe-sequence - cursor to other cursor', function (test) {\n  var dep = new Tracker.Dependency;\n  var coll = new Mongo.Collection(null);\n  coll.insert({_id: \"13\", foo: 1});\n  var cursor = coll.find({}, {sort: {_id: 1}});\n  var seq = cursor;\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    coll.insert({_id: \"37\", bar: 2});\n\n    var newColl = new Mongo.Collection(null);\n    newColl.insert({_id: \"13\", foo: 1});\n    newColl.insert({_id: \"38\", bar: 2});\n    var newCursor = newColl.find({}, {sort: {_id: 1}});\n    seq = newCursor;\n    dep.changed();\n  }, [\n    {addedAt: [\"13\", {_id: \"13\", foo: 1}, 0, null]},\n    {addedAt: [\"37\", {_id: \"37\", bar: 2}, 1, null]},\n    {removedAt: [\"37\", {_id: \"37\", bar: 2}, 1]},\n    {addedAt: [\"38\", {_id: \"38\", bar: 2}, 1, null]},\n    {changedAt: [\"13\", {_id: \"13\", foo: 1}, {_id: \"13\", foo: 1}, 0]}\n  ]);\n});\n\nTinytest.add('observe-sequence - cursor to other cursor with transform', function (test) {\n  var dep = new Tracker.Dependency;\n  var transform = function(doc) {\n    return _.extend({idCopy: doc._id}, doc);\n  };\n\n  var coll = new Mongo.Collection(null, {transform: transform});\n  coll.insert({_id: \"13\", foo: 1});\n  var cursor = coll.find({}, {sort: {_id: 1}});\n  var seq = cursor;\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    coll.insert({_id: \"37\", bar: 2});\n\n    var newColl = new Mongo.Collection(null, {transform: transform});\n    newColl.insert({_id: \"13\", foo: 1});\n    newColl.insert({_id: \"38\", bar: 2});\n    var newCursor = newColl.find({}, {sort: {_id: 1}});\n    seq = newCursor;\n    dep.changed();\n  }, [\n    {addedAt: [\"13\", {_id: \"13\", foo: 1, idCopy: \"13\"}, 0, null]},\n    {addedAt: [\"37\", {_id: \"37\", bar: 2, idCopy: \"37\"}, 1, null]},\n    {removedAt: [\"37\", {_id: \"37\", bar: 2, idCopy: \"37\"}, 1]},\n    {addedAt: [\"38\", {_id: \"38\", bar: 2, idCopy: \"38\"}, 1, null]},\n    {changedAt: [\"13\", {_id: \"13\", foo: 1, idCopy: \"13\"}, {_id: \"13\", foo: 1, idCopy: \"13\"}, 0]}\n  ]);\n});\n\nTinytest.add('observe-sequence - cursor to same cursor', function (test) {\n  var coll = new Mongo.Collection(null);\n  coll.insert({_id: \"13\", rank: 1});\n  var cursor = coll.find({}, {sort: {rank: 1}});\n  var seq = cursor;\n  var dep = new Tracker.Dependency;\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    coll.insert({_id: \"24\", rank: 2});\n    dep.changed();\n    Tracker.flush();\n    coll.insert({_id: \"78\", rank: 3});\n  }, [\n    {addedAt: [\"13\", {_id: \"13\", rank: 1}, 0, null]},\n    {addedAt: [\"24\", {_id: \"24\", rank: 2}, 1, null]},\n    // even if the cursor changes to the same cursor, we do a diff,\n    // which leads to these 'changedAt' events.\n    {changedAt: [\"13\", {_id: \"13\", rank: 1}, {_id: \"13\", rank: 1}, 0]},\n    {changedAt: [\"24\", {_id: \"24\", rank: 2}, {_id: \"24\", rank: 2}, 1]},\n    {addedAt: [\"78\", {_id: \"78\", rank: 3}, 2, null]}\n  ]);\n});\n\nTinytest.add('observe-sequence - string arrays', function (test) {\n  var seq = ['A', 'B'];\n  var dep = new Tracker.Dependency;\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    seq = ['B', 'C'];\n    dep.changed();\n  }, [\n    {addedAt: ['-A', 'A', 0, null]},\n    {addedAt: ['-B', 'B', 1, null]},\n    {removedAt: ['-A', 'A', 0]},\n    {addedAt: ['-C', 'C', 1, null]}\n  ]);\n});\n\nTinytest.add('observe-sequence - number arrays', function (test) {\n  var seq = [1, 1, 2];\n  var dep = new Tracker.Dependency;\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    seq = [1, 3, 2, 3];\n    dep.changed();\n  }, [\n    {addedAt: [1, 1, 0, null]},\n    {addedAt: [{NOT: 1}, 1, 1, null]},\n    {addedAt: [2, 2, 2, null]},\n    {removedAt: [{NOT: 1}, 1, 1]},\n    {addedAt: [3, 3, 1, 2]},\n    {addedAt: [{NOT: 3}, 3, 3, null]}\n  ]);\n});\n\nTinytest.add('observe-sequence - number arrays, _id:0 correctly handled, no duplicate ids warning #4049', function (test) {\n  var seq = _.map(_.range(3), function (i) { return { _id: i}; });\n  var dep = new Tracker.Dependency;\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    // There was a bug before fixing #4049 that 0 wouldn't be handled well as an\n    // _id. An expression like `(item && item._id) || index` would incorrectly\n    // return '2' for the last item because the _id is falsy (although it is not\n    // undefined, but 0!).\n    seq = _.map([1, 2, 0], function (i) { return { _id: i}; });\n    dep.changed();\n  }, [\n    {addedAt: [0, {_id: 0}, 0, null]},\n    {addedAt: [1, {_id: 1}, 1, null]},\n    {addedAt: [2, {_id: 2}, 2, null]},\n    {movedTo: [0, {_id: 0}, 0, 2, null]},\n    {changedAt: [0, {_id: 0}, {_id: 0}, 2]},\n    {changedAt: [1, {_id: 1}, {_id: 1}, 0]},\n    {changedAt: [2, {_id: 2}, {_id: 2}, 1]}\n  ]);\n});\n\nTinytest.add('observe-sequence - cursor to other cursor, same collection', function (test) {\n  var dep = new Tracker.Dependency;\n  var coll = new Mongo.Collection(null);\n  coll.insert({_id: \"13\", foo: 1});\n  coll.insert({_id: \"37\", foo: 2});\n  var cursor = coll.find({foo: 1});\n  var seq = cursor;\n\n  runOneObserveSequenceTestCase(test, function () {\n    dep.depend();\n    return seq;\n  }, function () {\n    var newCursor = coll.find({foo: 2});\n    seq = newCursor;\n    dep.changed();\n    Tracker.flush();\n    coll.insert({_id: \"38\", foo: 1});\n    coll.insert({_id: \"39\", foo: 2});\n  }, [\n    {addedAt: [\"13\", {_id: \"13\", foo: 1}, 0, null]},\n    {removedAt: [\"13\", {_id: \"13\", foo: 1}, 0]},\n    {addedAt: [\"37\", {_id: \"37\", foo: 2}, 0, null]},\n    {addedAt: [\"39\", {_id: \"39\", foo: 2}, 1, null]}\n  ]);\n});\n"
  },
  {
    "path": "packages/observe-sequence/package.js",
    "content": "Package.describe({\n  summary: \"Observe changes to various sequence types such as arrays, cursors and objects\",\n  version: \"1.0.12\"\n});\n\nPackage.onUse(function (api) {\n  api.use('tracker');\n  api.use('mongo-id');  // for idStringify\n  api.use('diff-sequence');\n  api.use('underscore');\n  api.use('random');\n  api.export('ObserveSequence');\n  api.addFiles(['observe_sequence.js']);\n});\n\nPackage.onTest(function (api) {\n  api.use([\n    'tinytest',\n    'observe-sequence',\n    'underscore',\n    'ejson',\n    'tracker',\n    'mongo'\n  ]);\n\n  api.addFiles(['observe_sequence_tests.js'], 'client');\n});\n"
  },
  {
    "path": "packages/ordered-dict/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/ordered-dict/ordered_dict.js",
    "content": "// This file defines an ordered dictionary abstraction that is useful for\n// maintaining a dataset backed by observeChanges.  It supports ordering items\n// by specifying the item they now come before.\n\n// The implementation is a dictionary that contains nodes of a doubly-linked\n// list as its values.\n\n// constructs a new element struct\n// next and prev are whole elements, not keys.\nvar element = function (key, value, next, prev) {\n  return {\n    key: key,\n    value: value,\n    next: next,\n    prev: prev\n  };\n};\nOrderedDict = function (/* ... */) {\n  var self = this;\n  self._dict = {};\n  self._first = null;\n  self._last = null;\n  self._size = 0;\n  var args = _.toArray(arguments);\n  self._stringify = function (x) { return x; };\n  if (typeof args[0] === 'function')\n    self._stringify = args.shift();\n  _.each(args, function (kv) {\n    self.putBefore(kv[0], kv[1], null);\n  });\n};\n\n_.extend(OrderedDict.prototype, {\n  // the \"prefix keys with a space\" thing comes from here\n  // https://github.com/documentcloud/underscore/issues/376#issuecomment-2815649\n  _k: function (key) { return \" \" + this._stringify(key); },\n\n  empty: function () {\n    var self = this;\n    return !self._first;\n  },\n  size: function () {\n    var self = this;\n    return self._size;\n  },\n  _linkEltIn: function (elt) {\n    var self = this;\n    if (!elt.next) {\n      elt.prev = self._last;\n      if (self._last)\n        self._last.next = elt;\n      self._last = elt;\n    } else {\n      elt.prev = elt.next.prev;\n      elt.next.prev = elt;\n      if (elt.prev)\n        elt.prev.next = elt;\n    }\n    if (self._first === null || self._first === elt.next)\n      self._first = elt;\n  },\n  _linkEltOut: function (elt) {\n    var self = this;\n    if (elt.next)\n      elt.next.prev = elt.prev;\n    if (elt.prev)\n      elt.prev.next = elt.next;\n    if (elt === self._last)\n      self._last = elt.prev;\n    if (elt === self._first)\n      self._first = elt.next;\n  },\n  putBefore: function (key, item, before) {\n    var self = this;\n    if (self._dict[self._k(key)])\n      throw new Error(\"Item \" + key + \" already present in OrderedDict\");\n    var elt = before ?\n          element(key, item, self._dict[self._k(before)]) :\n          element(key, item, null);\n    if (elt.next === undefined)\n      throw new Error(\"could not find item to put this one before\");\n    self._linkEltIn(elt);\n    self._dict[self._k(key)] = elt;\n    self._size++;\n  },\n  append: function (key, item) {\n    var self = this;\n    self.putBefore(key, item, null);\n  },\n  remove: function (key) {\n    var self = this;\n    var elt = self._dict[self._k(key)];\n    if (elt === undefined)\n      throw new Error(\"Item \" + key + \" not present in OrderedDict\");\n    self._linkEltOut(elt);\n    self._size--;\n    delete self._dict[self._k(key)];\n    return elt.value;\n  },\n  get: function (key) {\n    var self = this;\n    if (self.has(key))\n        return self._dict[self._k(key)].value;\n    return undefined;\n  },\n  has: function (key) {\n    var self = this;\n    return _.has(self._dict, self._k(key));\n  },\n  // Iterate through the items in this dictionary in order, calling\n  // iter(value, key, index) on each one.\n\n  // Stops whenever iter returns OrderedDict.BREAK, or after the last element.\n  forEach: function (iter) {\n    var self = this;\n    var i = 0;\n    var elt = self._first;\n    while (elt !== null) {\n      var b = iter(elt.value, elt.key, i);\n      if (b === OrderedDict.BREAK)\n        return;\n      elt = elt.next;\n      i++;\n    }\n  },\n  first: function () {\n    var self = this;\n    if (self.empty())\n      return undefined;\n    return self._first.key;\n  },\n  firstValue: function () {\n    var self = this;\n    if (self.empty())\n      return undefined;\n    return self._first.value;\n  },\n  last: function () {\n    var self = this;\n    if (self.empty())\n      return undefined;\n    return self._last.key;\n  },\n  lastValue: function () {\n    var self = this;\n    if (self.empty())\n      return undefined;\n    return self._last.value;\n  },\n  prev: function (key) {\n    var self = this;\n    if (self.has(key)) {\n      var elt = self._dict[self._k(key)];\n      if (elt.prev)\n        return elt.prev.key;\n    }\n    return null;\n  },\n  next: function (key) {\n    var self = this;\n    if (self.has(key)) {\n      var elt = self._dict[self._k(key)];\n      if (elt.next)\n        return elt.next.key;\n    }\n    return null;\n  },\n  moveBefore: function (key, before) {\n    var self = this;\n    var elt = self._dict[self._k(key)];\n    var eltBefore = before ? self._dict[self._k(before)] : null;\n    if (elt === undefined)\n      throw new Error(\"Item to move is not present\");\n    if (eltBefore === undefined) {\n      throw new Error(\"Could not find element to move this one before\");\n    }\n    if (eltBefore === elt.next) // no moving necessary\n      return;\n    // remove from its old place\n    self._linkEltOut(elt);\n    // patch into its new place\n    elt.next = eltBefore;\n    self._linkEltIn(elt);\n  },\n  // Linear, sadly.\n  indexOf: function (key) {\n    var self = this;\n    var ret = null;\n    self.forEach(function (v, k, i) {\n      if (self._k(k) === self._k(key)) {\n        ret = i;\n        return OrderedDict.BREAK;\n      }\n      return undefined;\n    });\n    return ret;\n  },\n  _checkRep: function () {\n    var self = this;\n    _.each(self._dict, function (k, v) {\n      if (v.next === v)\n        throw new Error(\"Next is a loop\");\n      if (v.prev === v)\n        throw new Error(\"Prev is a loop\");\n    });\n  }\n\n});\nOrderedDict.BREAK = {\"break\": true};\n"
  },
  {
    "path": "packages/ordered-dict/package.js",
    "content": "Package.describe({\n  summary: \"Ordered traversable dictionary with a mutable ordering\",\n  version: '1.0.8',\n  documentation: null\n});\n\nPackage.onUse(function (api) {\n  api.use('underscore');\n  api.export('OrderedDict');\n  api.addFiles('ordered_dict.js', ['client', 'server']);\n});\n"
  },
  {
    "path": "packages/package-stats-opt-out/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/package-stats-opt-out/README.md",
    "content": "# package-stats-opt-out\n\nOpt out of sending statistics about which packages your app is using.\n\nRead more about the Meteor packaging system on the Isobuild [project\npage](https://www.meteor.com/isobuild)."
  },
  {
    "path": "packages/package-stats-opt-out/package.js",
    "content": "Package.describe({\n  summary: \"Opt out of sending package stats\",\n  version: '1.0.7'\n});\n\nPackage.onUse(function (api) {\n  // Empty. This package's presence tells the meteor tool to stop\n  // sending package stats.\n});\n"
  },
  {
    "path": "packages/package-version-parser/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/package-version-parser/README.md",
    "content": "This is an internal Meteor package.\n"
  },
  {
    "path": "packages/package-version-parser/package-version-parser-tests.js",
    "content": "var currentTest = null;\n\nTinytest.add(\"package-version-parser - validatePackageName\", function (test) {\n  var badName = function (packageName, messageExpect) {\n    test.throws(function () {\n      try {\n        PackageVersion.validatePackageName(packageName);\n      } catch (e) {\n        if (! e.versionParserError) {\n          test.fail(e.message);\n        }\n        throw e;\n      }\n    }, messageExpect);\n  };\n\n  PackageVersion.validatePackageName('a');\n  PackageVersion.validatePackageName('a-b');\n  PackageVersion.validatePackageName('a.b');\n\n  badName(\"$foo\", /can only contain/);\n  badName(\"\", /must contain a lowercase/);\n  badName(\"foo$bar\", /can only contain/);\n  badName(\"Foo\", /can only contain/);\n  badName(\"a b\", /can only contain/);\n  badName(\".foo\", /may not begin with a dot/);\n  badName(\"foo.\", /may not end with a dot/);\n  badName(\"foo..bar\", /not contain two consecutive dots/);\n  badName(\"-x\", /not begin with a hyphen/);\n  badName(\"--x\", /not begin with a hyphen/);\n  badName(\"0.0\", /must contain/);\n  badName(\":a\", /start or end with a colon/);\n  badName(\"a:\", /start or end with a colon/);\n\n  // these are ok\n  PackageVersion.validatePackageName('x-');\n  PackageVersion.validatePackageName('x--y');\n  PackageVersion.validatePackageName('x--');\n});\n\nTinytest.add(\"package-version-parser - parse\", function (test) {\n  test.isTrue(new PackageVersion(\"1.2.3\") instanceof PackageVersion);\n\n  var throws = function (v, re) {\n    test.throws(function () {\n      new PackageVersion(v);\n    }, re);\n  };\n  var formatPV = function (pv) {\n    pv = JSON.parse(JSON.stringify(pv));\n    delete pv._semverParsed;\n    return (JSON.stringify(pv)\n            .replace(/,(?=\"prerelease\"|\"raw\")/g, ',\\n')\n            .replace(/,/g, ', ')\n            .replace(/\"(\\w+)\":/g, '$1: ')\n            .replace(\"{\", \"{\\n\")\n            .replace(\"}\", \"\\n}\"));\n  };\n  var equal = function (pv1, pv2) {\n    test.equal(formatPV(pv1), formatPV(pv2));\n  };\n\n  equal(new PackageVersion(\"1.2.3-rc.5_1+12345\"), {\n    major: 1, minor: 2, patch: 3,\n    prerelease: [\"rc\", 5], wrapNum: 1, build: [\"12345\"],\n    raw: \"1.2.3-rc.5_1+12345\", version: \"1.2.3-rc.5_1\",\n    semver: \"1.2.3-rc.5+12345\"\n  });\n\n  equal(PackageVersion.parse(\"1.2.3-rc.5_1+12345\"), {\n    major: 1, minor: 2, patch: 3,\n    prerelease: [\"rc\", 5], wrapNum: 1, build: [\"12345\"],\n    raw: \"1.2.3-rc.5_1+12345\", version: \"1.2.3-rc.5_1\",\n    semver: \"1.2.3-rc.5+12345\"\n  });\n\n  equal(new PackageVersion(\"1.2.3\"), {\n    major: 1, minor: 2, patch: 3,\n    prerelease: [], wrapNum: 0, build: [],\n    raw: \"1.2.3\", version: \"1.2.3\", semver: \"1.2.3\"\n  });\n  throws(\"1.2\", /must look like semver/);\n  throws(\"1\", /must look like semver/);\n  equal(new PackageVersion(\"1.0.0-rc.1\"), {\n    major: 1, minor: 0, patch: 0,\n    prerelease: [\"rc\", 1], wrapNum: 0, build: [],\n    raw: \"1.0.0-rc.1\", version: \"1.0.0-rc.1\", semver: \"1.0.0-rc.1\"\n  });\n  throws(\"1.0.0-.\", /must look like semver/);\n  throws(\"1.0.0-rc.\", /must look like semver/);\n  throws(\"1.0.0-01\", /must look like semver/);\n  equal(new PackageVersion(\"1.2.3-1-1\"), {\n    major: 1, minor: 2, patch: 3,\n    prerelease: [\"1-1\"], wrapNum: 0, build: [],\n    raw: \"1.2.3-1-1\", version: \"1.2.3-1-1\", semver: \"1.2.3-1-1\"\n  });\n  equal(new PackageVersion(\"1.2.3_4\"), {\n    major: 1, minor: 2, patch: 3,\n    prerelease: [], wrapNum: 4, build: [],\n    raw: \"1.2.3_4\", version: \"1.2.3_4\", semver: \"1.2.3\"\n  });\n  throws(\"1.2.3_4_5\", /have two _/);\n  throws(\"1.2.3_0\", /must not have a leading zero/);\n  throws(\"1.2.3_01\", /must not have a leading zero/);\n  throws(\"1.2.3_a\", /must contain only digits/);\n  // (prerelease must go *before* the wrap num)\n  throws(\"1.2.3_a-rc.1\", /must contain only digits/);\n  equal(new PackageVersion(\"1.2.3-4_5\"), {\n    major: 1, minor: 2, patch: 3,\n    prerelease: [4], wrapNum: 5, build: [],\n    raw: \"1.2.3-4_5\", version: \"1.2.3-4_5\", semver: \"1.2.3-4\"\n  });\n  equal(new PackageVersion(\"1.2.3-rc.1_7+8.9-10.c\"), {\n    major: 1, minor: 2, patch: 3,\n    prerelease: [\"rc\", 1], wrapNum: 7, build: [\"8\", \"9-10\", \"c\"],\n    raw: \"1.2.3-rc.1_7+8.9-10.c\", version: \"1.2.3-rc.1_7\",\n    semver: \"1.2.3-rc.1+8.9-10.c\"\n  });\n  throws(\"1.2.3+4+5\", /have two \\+/);\n  equal(new PackageVersion(\"1.2.3+x\"), {\n    major: 1, minor: 2, patch: 3,\n    prerelease: [], wrapNum: 0, build: [\"x\"],\n    raw: \"1.2.3+x\", version: \"1.2.3\", semver: \"1.2.3+x\"\n  });\n  throws(\"1.2.3+x_1\", /must look like semver/);\n  equal(new PackageVersion(\"1.2.3_1+x\"), {\n    major: 1, minor: 2, patch: 3,\n    prerelease: [], wrapNum: 1, build: [\"x\"],\n    raw: \"1.2.3_1+x\", version: \"1.2.3_1\", semver: \"1.2.3+x\"\n  });\n\n  throws(\"v1.0.0\", /must look like semver/);\n});\n\nTinytest.add(\"package-version-parser - constraints - parsePackageConstraint\", function (test) {\n  test.isTrue(PackageVersion.parsePackageConstraint(\"foo\") instanceof\n              PackageVersion.PackageConstraint);\n\n  test.equal(PackageVersion.parsePackageConstraint(\"foo@1.2.3\"),\n             { package: \"foo\", constraintString: \"1.2.3\",\n               versionConstraint: {\n                 raw: \"1.2.3\",\n                 alternatives: [{type: \"compatible-with\",\n                                 versionString: \"1.2.3\"}] } });\n\n  test.equal(PackageVersion.parsePackageConstraint(\"foo\"),\n             { package: \"foo\", constraintString: \"\",\n               versionConstraint: {\n                 raw: \"\",\n                 alternatives: [{type: \"any-reasonable\",\n                                 versionString: null}] } });\n\n  test.equal(PackageVersion.parsePackageConstraint(\"foo@1.0.0 || =2.0.0\"),\n             { package: \"foo\", constraintString: \"1.0.0 || =2.0.0\",\n               versionConstraint: {\n                 raw: \"1.0.0 || =2.0.0\",\n                 alternatives: [{type: \"compatible-with\",\n                                 versionString: \"1.0.0\"},\n                                {type: \"exactly\",\n                                 versionString: \"2.0.0\"}] } });\n\n  test.equal(new PackageVersion.PackageConstraint(\"foo@1.0.0 || =2.0.0\"),\n             PackageVersion.parsePackageConstraint(\"foo@1.0.0 || =2.0.0\"));\n\n  test.equal(PackageVersion.parsePackageConstraint(\"foo\", null),\n             PackageVersion.parsePackageConstraint(\"foo\"));\n\n  test.equal(PackageVersion.parsePackageConstraint(\"foo\", \"\"),\n             PackageVersion.parsePackageConstraint(\"foo\"));\n\n  test.equal(PackageVersion.parsePackageConstraint(\"foo\", \"1.0.0\"),\n             PackageVersion.parsePackageConstraint(\"foo@1.0.0\"));\n\n  test.equal(PackageVersion.parsePackageConstraint(\"foo\", \"=1.0.0\"),\n             PackageVersion.parsePackageConstraint(\"foo@=1.0.0\"));\n\n  test.throws(function () {\n    PackageVersion.parsePackageConstraint(\"\", \"1.0.0\");\n  });\n  test.throws(function () {\n    PackageVersion.parsePackageConstraint(\"foo@1.0.0\", \"1.0.0\");\n  });\n  test.throws(function () {\n    PackageVersion.parsePackageConstraint(\"foo@\", \"1.0.0\");\n  });\n  test.throws(function () {\n    PackageVersion.parsePackageConstraint(\"foo@\");\n  }, /leave off the @/);\n  test.throws(function () {\n    PackageVersion.parsePackageConstraint(\"foo@\", \"\");\n  });\n  test.throws(function () {\n    PackageVersion.parsePackageConstraint(\"a@b@c\");\n  });\n  test.throws(function () {\n    PackageVersion.parsePackageConstraint(\"foo@||\");\n  }, /Invalid constraint string: \\|\\|/);\n  test.throws(function () {\n    PackageVersion.parsePackageConstraint(\"foo@=||=\");\n  }, /Empty string is not a valid version/);\n\n  test.equal(new PackageVersion.PackageConstraint(\n    \"foo\", new PackageVersion.VersionConstraint(null)),\n             { package: \"foo\", constraintString: \"\",\n               versionConstraint: {\n                 raw: \"\",\n                 alternatives: [{type: \"any-reasonable\",\n                                 versionString: null}] } });\n\n  test.equal(PackageVersion.parsePackageConstraint(\n    \"foo\", PackageVersion.parseVersionConstraint(\"1.0.0 || =2.0.0\")),\n             { package: \"foo\", constraintString: \"1.0.0 || =2.0.0\",\n               versionConstraint: {\n                 raw: \"1.0.0 || =2.0.0\",\n                 alternatives: [{type: \"compatible-with\",\n                                 versionString: \"1.0.0\"},\n                                {type: \"exactly\",\n                                 versionString: \"2.0.0\"}] } });\n\n  test.equal(PackageVersion.parseVersionConstraint(null),\n             {raw: \"\", alternatives: [{type: \"any-reasonable\",\n                                       versionString: null}]});\n  test.equal(PackageVersion.parseVersionConstraint(\"\"),\n             {raw: \"\", alternatives: [{type: \"any-reasonable\",\n                                       versionString: null}]});\n\n  test.equal(PackageVersion.parsePackageConstraint(\"foo\").toString(),\n             \"foo\");\n  test.equal(PackageVersion.parsePackageConstraint(\"foo\", null).toString(),\n             \"foo\");\n  test.equal(PackageVersion.parsePackageConstraint(\"foo@1.0.0\").toString(),\n             \"foo@1.0.0\");\n  test.equal(PackageVersion.parsePackageConstraint(\n    \"foo@=1.0.0 || 2.0.0\").toString(), \"foo@=1.0.0 || 2.0.0\");\n});\n\nvar t = function (pConstraintString, expected, descr) {\n  var constraintString = pConstraintString.replace(/^.*?(@|$)/, '');\n  var versionConstraint = {\n    raw: constraintString,\n    alternatives: expected.alternatives\n  };\n  currentTest.equal(\n    PackageVersion.parsePackageConstraint(pConstraintString),\n    {\n      package: expected.package,\n      constraintString: constraintString,\n      versionConstraint: {\n        raw: constraintString,\n        alternatives: expected.alternatives\n      }\n    },\n    descr);\n};\n\nvar FAIL = function (versionString, errorExpect) {\n  currentTest.throws(function () {\n    PackageVersion.parsePackageConstraint(versionString);\n  }, errorExpect);\n};\n\nTinytest.add(\"package-version-parser - constraints - any-reasonable\", function (test) {\n  currentTest = test;\n\n  t(\"foo\", { package: \"foo\", alternatives: [{\n        versionString: null, type: \"any-reasonable\" } ]});\n  t(\"foo-1234\", { package: \"foo-1234\", alternatives: [{\n        versionString: null, type: \"any-reasonable\" } ]});\n  FAIL(\"bad_name\");\n});\n\nTinytest.add(\"package-version-parser - constraints - compatible version, compatible-with\", function (test) {\n  currentTest = test;\n\n  t(\"foo@1.2.3\", { package: \"foo\", alternatives: [{\n        versionString: \"1.2.3\", type: \"compatible-with\" } ]});\n  t(\"foo-1233@1.2.3\", { package: \"foo-1233\", alternatives: [{\n        versionString: \"1.2.3\", type: \"compatible-with\" } ]});\n  t(\"foo-bar@3.2.1\", { package: \"foo-bar\", alternatives: [{\n        versionString: \"3.2.1\", type: \"compatible-with\" } ]});\n  FAIL(\"42@0.2.0\");\n  FAIL(\"foo@1.2.3.4\");\n  FAIL(\"foo@1.4\");\n  FAIL(\"foo@1\");\n  FAIL(\"foo@\");\n  FAIL(\"foo@@\");\n  FAIL(\"foo@x.y.z\");\n  FAIL(\"foo@<1.2\");\n  FAIL(\"foo<1.2\");\n  FAIL(\"foo@1.2.3_abc\");\n  FAIL(\"foo@1.2.3+1234_1\");\n  FAIL(\"foo@1.2.3_1-rc1\");\n  FAIL(\"foo-1233@1.2.3_0\", /must not have a leading zero/);\n  FAIL(\"foo-1233@1.2.3_a\", /must contain only digits/);\n  FAIL(\"foo-1233@1.2.3_\", /wrap number must follow/);\n  FAIL(\"foo-1233@1.2.3_0123\");\n\n  t(\"foo@1.2.3_1\", { package: \"foo\", alternatives: [{\n       versionString: \"1.2.3_1\", type: \"compatible-with\" } ]});\n  t(\"foo-bar@3.2.1-rc0_123\", { package: \"foo-bar\", alternatives: [{\n       versionString: \"3.2.1-rc0_123\", type: \"compatible-with\" } ]});\n  t(\"foo-1233@1.2.3_5+1234\", { package: \"foo-1233\", alternatives: [{\n       versionString: \"1.2.3_5+1234\", type: \"compatible-with\" } ]});\n  t(\"foo\", { package: \"foo\", alternatives: [{\n       versionString: null, type: \"any-reasonable\" } ]});\n});\n\nTinytest.add(\"package-version-parser - constraints - compatible version, exactly\", function (test) {\n  currentTest = test;\n\n  t(\"foo@=1.2.3\", { package: \"foo\", alternatives: [\n         { versionString: \"1.2.3\", type: \"exactly\" } ]});\n  t(\"foo-bar@=3.2.1\", { package: \"foo-bar\", alternatives: [{\n      versionString: \"3.2.1\", type: \"exactly\" } ]});\n  t(\"foo@=1.2.3_1\", { package: \"foo\", alternatives: [{\n       versionString: \"1.2.3_1\", type: \"exactly\" } ]});\n  t(\"foo-bar@=3.2.1_34\", { package: \"foo-bar\", alternatives: [{\n       versionString: \"3.2.1_34\", type: \"exactly\" } ]});\n\n  FAIL(\"42@=0.2.0\");\n  FAIL(\"foo@=1.2.3.4\");\n  FAIL(\"foo@=1.4\");\n  FAIL(\"foo@=1\");\n  FAIL(\"foo@@=\");\n  FAIL(\"foo@=@\");\n  FAIL(\"foo@=x.y.z\");\n  FAIL(\"foo@=<1.2\");\n  FAIL(\"foo@<=1.2\");\n  FAIL(\"foo<=1.2\");\n  FAIL(\"foo@=1.2.3_rc0\");\n\n  // We no longer support @>=.\n  FAIL(\"foo@>=1.2.3\");\n  FAIL(\"foo-bar@>=3.2.1\");\n  FAIL(\"42@>=0.2.0\");\n  FAIL(\"foo@>=1.2.3.4\");\n  FAIL(\"foo@>=1.4\");\n  FAIL(\"foo@>=1\");\n  FAIL(\"foo@@>=\");\n  FAIL(\"foo@>=@\");\n  FAIL(\"foo@>=x.y.z\");\n  FAIL(\"foo@=>12.3.11\");\n});\n\n\nTinytest.add(\"package-version-parser - constraints - or\", function (test) {\n  currentTest = test;\n\n  t(\"foo@1.0.0 || 2.0.0 || 3.0.0 || =4.0.0-rc1\",\n    { package: \"foo\", alternatives:\n      [{ versionString: \"1.0.0\", type: \"compatible-with\"},\n       { versionString: \"2.0.0\", type: \"compatible-with\"},\n       { versionString: \"3.0.0\", type: \"compatible-with\"},\n       { versionString: \"4.0.0-rc1\", type: \"exactly\"}]\n   });\n  t(\"foo@1.0.0|| 2.0.0||3.0.0    ||     =4.0.0-rc1\",\n    { package: \"foo\", alternatives:\n      [{ versionString: \"1.0.0\", type: \"compatible-with\"},\n       { versionString: \"2.0.0\", type: \"compatible-with\"},\n       { versionString: \"3.0.0\", type: \"compatible-with\"},\n       { versionString: \"4.0.0-rc1\", type: \"exactly\"}]\n   });\n  t(\"foo-bar@=3.2.1 || 1.0.0\",\n    { package: \"foo-bar\", alternatives:\n      [{ versionString: \"3.2.1\", type: \"exactly\"},\n       { versionString: \"1.0.0\", type: \"compatible-with\"}]\n   });\n  t(\"foo@=1.2.3_1 || 1.2.4\",\n    { package: \"foo\", alternatives:\n      [{ versionString: \"1.2.3_1\", type: \"exactly\"},\n       { versionString: \"1.2.4\", type: \"compatible-with\"}]\n   });\n  t(\"foo-bar@=3.2.1_34 || =3.2.1-rc1\",\n    { package: \"foo-bar\", alternatives:\n      [{ versionString: \"3.2.1_34\", type: \"exactly\"},\n       { versionString: \"3.2.1-rc1\", type: \"exactly\"}]\n    });\n\n  FAIL(\"foo@1.0.0 1.0.0\");\n  FAIL(\"foo@1.0.0 | 1.0.0\");\n  FAIL(\"foo || bar\");\n  FAIL(\"foo@1.0.0-rc|1.0.0\");\n\n  // This is the current implementation, but is arguably not great.\n  FAIL(\"foo@1.0.0 \"); // trailing space\n});\n\nTinytest.add(\n  \"package-version-parser - less than, compare, version magnitude\",\n  function (test) {\n    var compare = function (v1, v2, expected) {\n      if (expected === '<') {\n        test.isTrue(PackageVersion.lessThan(v1, v2));\n        test.isTrue(PackageVersion.versionMagnitude(v1) < PackageVersion.versionMagnitude(v2));\n        test.isTrue(PackageVersion.compare(v1, v2) < 0);\n      } else if (expected === '=') {\n        test.isFalse(PackageVersion.lessThan(v1, v2));\n        test.isFalse(PackageVersion.lessThan(v2, v1));\n        test.isTrue(PackageVersion.versionMagnitude(v1) === PackageVersion.versionMagnitude(v2));\n        test.isTrue(PackageVersion.compare(v1, v2) === 0);\n      } else if (expected === '>') {\n        test.isTrue(PackageVersion.lessThan(v2, v1));\n        test.isTrue(PackageVersion.versionMagnitude(v1) > PackageVersion.versionMagnitude(v2));\n        test.isTrue(PackageVersion.compare(v1, v2) > 0);\n      } else {\n        throw new Error(\"expected should be '<', '=' or '>'\");\n      }\n    };\n\n    compare(\"1.0.0\", \"1.2.0\", \"<\");\n    compare(\"1.0.0_50\", \"1.0.1\", \"<\");\n    compare(\"1.0.0_50\", \"1.2.0\", \"<\");\n    compare(\"1.0.0_1\", \"1.0.0_2\", \"<\");\n    compare(\"1.0.0_2\", \"1.0.0_10\", \"<\"); // verify that we compare _N \"wrap numbers\" as numbers, not strings\n    compare(\"1.0.0\", \"1.0.0_2\", \"<\");\n    compare(\"1.99.0_99\", \"3.0.0_2\", \"<\");\n    compare(\"1.99.0\", \"2.0.0\", \"<\");\n    compare(\"1.0.0_5\", \"1.0.0_2\", \">\");\n    compare(\"1.0.0_99\", \"1.2.0\", \"<\");\n    compare(\"1.0.0_99\", \"1.0.1\", \"<\");\n    compare(\"1.0.0_1\", \"1.0.0_2\", \"<\");\n    compare(\"1.0.0\", \"1.0.0_2\", \"<\");\n    compare(\"1.99.0_99\", \"3.0.0_2\", \"<\");\n\n    compare(\"1.0.0_5\", \"1.0.0_2\", \">\");\n    compare(\"1.0.0\", \"1.0.0\", \"=\");\n    compare(\"1.0.0_5\", \"1.0.0_5\", \"=\");\n    compare(\"1.2.0\", \"1.0.0\", \">\");\n    compare(\"1.0.1\", \"1.0.0_5\", \">\");\n\n    // Rule 11 from http://semver.org\n    compare(\"0.99.99\", \"1.0.0-alpha.1\", \"<\");\n    compare(\"1.0.0-alpha\", \"1.0.0-alpha.1\", \"<\");\n    compare(\"1.0.0-alpha.1\", \"1.0.0-alpha.beta\", \"<\");\n    compare(\"1.0.0-alpha.beta\", \"1.0.0-beta\", \"<\");\n    compare(\"1.0.0-beta\", \"1.0.0-beta.2\", \"<\");\n    compare(\"1.0.0-beta.2\", \"1.0.0-beta.11\", \"<\");\n    compare(\"1.0.0-beta.11\", \"1.0.0-rc.1\", \"<\");\n    compare(\"1.0.0-rc.1\", \"1.0.0\", \"<\");\n\n    // dashes are allowed in prerelease parts\n    compare(\"1.0.0--alpha\", \"1.0.0-alpha\", \"<\");\n    compare(\"1.0.0-a-lpha\", \"1.0.0-alpha\", \"<\");\n    // test single character prerelease parts\n    compare(\"1.0.0-r.1\", \"1.0.0\", \"<\");\n    // test the edges of `versionMagnitude`\n    compare(\"1.0.0-zzzzzzzzzzzz\", \"1.0.0\", \"<\");\n    // prerelease parts can contain digits and non-digits\n    compare(\"1.0.0-r1\", \"1.0.0-rc\", \"<\");\n\n    // Our broken implementation of Rule 11 (see [*] above the\n    // declaration of PackageVersion.versionMagnitude). Maybe one day\n    // we'll fix it, in which case replace \"===\" with \">\"\n    test.isTrue(PackageVersion.versionMagnitude(\"1.0.0-beta.0\") ===\n                PackageVersion.versionMagnitude(\"1.0.0-bear.0\"));\n\n  });\n\nTinytest.add(\"package-version-parser - Invalid in 0.9.2\", function (test) {\n  // Note that invalidFirstFormatConstraint assumes that the initial version\n  // passed in has been previously checked to be valid in 0.9.3.\n\n  // These are invalid in 0.9.2, but valid in 0.9.3 and above.\n  var invalidVersions =\n    [\"1.0.0_1\", \"1.0.0 || 2.0.0\", \"1.0.0-rc1_1\",\n     \"3.4.0-rc1 || =1.0.0\"];\n  _.each(invalidVersions, function (v) {\n    test.isTrue(PackageVersion.invalidFirstFormatConstraint(v));\n  });\n\n  // These are all valid in 0.9.2.\n  var validVersions =\n    [\"1.0.0\", \"2.0.0-rc1\", \"=2.5.0\"];\n  _.each(validVersions, function (v) {\n    test.isFalse(PackageVersion.invalidFirstFormatConstraint(v));\n  });\n});\n\nTinytest.add(\"package-version-parser - sort\", function (test) {\n  var versions = [\"1.0.0\", \"1.0.0-rc.0\", \"1.0.10\", \"1.0.2\"];\n  versions.sort(PackageVersion.compare);\n  test.equal(versions, [\"1.0.0-rc.0\", \"1.0.0\", \"1.0.2\", \"1.0.10\"]);\n});\n"
  },
  {
    "path": "packages/package-version-parser/package-version-parser.js",
    "content": "// This file is in tools/packaging/package-version-parser.js and is symlinked to\n// packages/package-version-parser/package-version-parser.js. It's part of both\n// the tool and the package!  We don't use an isopacket for it because it used\n// to be required as part of building isopackets (though that may no longer be\n// true).\nvar inTool = typeof Package === 'undefined';\n\n\nvar semver = inTool ?\n  require ('../../dev_bundle/lib/node_modules/semver') : SemVer410;\nvar __ = inTool ? require('../../dev_bundle/lib/node_modules/underscore') : _;\n\n// Takes in a meteor version string, for example 1.2.3-rc.5_1+12345.\n//\n// Returns an object composed of the following:\n//  * major (integer >= 0)\n//  * minor (integer >= 0)\n//  * patch (integer >= 0)\n//  * prerelease (Array of Number-or-String, possibly empty)\n//  * wrapNum (integer >= 0)\n//  * build (Array of String, possibly empty)\n//  * raw (String), the raw meteor version string\n//  * version (String), canonical meteor version without build ID\n//  * semver (String), canonical semver version with build ID but no wrap num\n//\n// The input string \"1.2.3-rc.5_1+12345\" has a (major, minor, patch) of\n// (1, 2, 3), a prerelease of [\"rc\", 5], a wrapNum of 1, a build of\n// [\"12345\"], a raw of \"1.2.3-rc.5_1+12345\", a version of\n// \"1.2.3-rc.5_1\", and a semver of \"1.2.3-rc.5+12345\".\n//\n// Throws if the version string is invalid in any way.\n//\n// You can write `PV.parse(\"1.2.3\")` as an alternative to `new PV(\"1.2.3\")`\nvar PV = function (versionString) {\n  if (! (typeof versionString === 'string')) {\n    throw new Error(\"Invalid PackageVersion argument: \" + versionString);\n  }\n  if (! versionString) {\n    throwVersionParserError(\"Empty string is not a valid version\");\n  }\n\n  // The buildID (\"+foo\" suffix) is part of semver, but split it off\n  // because it comes after the wrapNum.  The wrapNum (\"_123\" suffix)\n  // is a Meteor extension to semver.\n  var plusSplit = versionString.split('+');\n  var wrapSplit = plusSplit[0].split('_');\n  var wrapNum = 0;\n\n  if (plusSplit.length > 2) {\n    throwVersionParserError(\"Can't have two + in version: \" + versionString);\n  }\n  if (wrapSplit.length > 2) {\n    throwVersionParserError(\"Can't have two _ in version: \" + versionString);\n  }\n  if (wrapSplit.length > 1) {\n    wrapNum = wrapSplit[1];\n    if (! wrapNum) {\n      throwVersionParserError(\"A wrap number must follow _\");\n    } else if (!/^\\d+$/.test(wrapNum)) {\n      throwVersionParserError(\n        \"The wrap number (after _) must contain only digits, so \" +\n          versionString + \" is invalid.\");\n    } else if (wrapNum[0] === \"0\") {\n      throwVersionParserError(\n        \"The wrap number (after _) must not have a leading zero, so \" +\n          versionString + \" is invalid.\");\n    }\n    wrapNum = parseInt(wrapNum, 10);\n  }\n\n  // semverPart is everything but the wrapNum, so for \"1.0.0_2+xyz\",\n  // it is \"1.0.0+xyz\".\n  var semverPart = wrapSplit[0];\n  if (plusSplit.length > 1) {\n    semverPart += \"+\" + plusSplit[1];\n  }\n\n  // NPM's semver spec supports things like 'v1.0.0' and considers them valid,\n  // but we don't. Everything before the + or - should be of the x.x.x form.\n  if (! /^\\d+\\.\\d+\\.\\d+(\\+|-|$)/.test(semverPart)) {\n    throwVersionParserError(\n      \"Version string must look like semver (eg '1.2.3'), not '\"\n        + versionString + \"'.\");\n  };\n\n  var semverParse = semver.parse(semverPart);\n  if (! semverParse) {\n    throwVersionParserError(\n      \"Version string must look like semver (eg '1.2.3'), not '\"\n        + semverPart + \"'.\");\n  }\n\n  this.major = semverParse.major; // Number\n  this.minor = semverParse.minor; // Number\n  this.patch = semverParse.patch; // Number\n  this.prerelease = semverParse.prerelease; // [OneOf(Number, String)]\n  this.wrapNum = wrapNum; // Number\n  this.build = semverParse.build; // [String]\n  this.raw = versionString; // the entire version string\n  // `.version` is everything but the build ID (\"+foo\"), and it\n  // has been run through semver's canonicalization, ie \"cleaned\"\n  // (for whatever that's worth)\n  this.version = semverParse.version + (wrapNum ? '_' + wrapNum : '');\n  // everything but the wrapnum (\"_123\")\n  this.semver = semverParse.version + (\n    semverParse.build.length ? '+' + semverParse.build.join('.') : '');\n\n  this._semverParsed = null; // populate lazily\n};\n\nPV.parse = function (versionString) {\n  return new PV(versionString);\n};\n\nif (inTool) {\n  module.exports = PV;\n} else {\n  PackageVersion = PV;\n}\n\n// Converts a meteor version into a large floating point number, which\n// is (more or less [*]) unique to that version. Satisfies the\n// following guarantee: If PV.lessThan(v1, v2) then\n// PV.versionMagnitude(v1) < PV.versionMagnitude(v2) [*]\n//\n// [* XXX!] We don't quite satisfy the uniqueness and comparison properties in\n// these cases:\n// 1. If any of the version parts are greater than 100 (pretty unlikely?)\n// 2. If we're dealing with a prerelease version, we only look at the\n//    first two characters of each prerelease part. So, \"1.0.0-beta\" and\n//    \"1.0.0-bear\" will have the same magnitude.\n// 3. If we're dealing with a prerelease version with more than two parts, eg\n//    \"1.0.0-rc.0.1\". In this comparison may fail since we'd get to the limit\n//    of JavaScript floating point precision.\n//\n// If we wanted to fix this, we'd make this function return a BigFloat\n// instead of a vanilla JavaScript number. That will make the\n// constraint solver slower (by how much?), and would require some\n// careful thought.\n// (Or it could just return some sort of tuple, and ensure that\n// the cost functions that consume this can deal with tuples...)\nPV.versionMagnitude = function (versionString) {\n  var v = PV.parse(versionString);\n\n  return v.major * 100 * 100 +\n    v.minor * 100 +\n    v.patch +\n    v.wrapNum / 100 +\n    prereleaseIdentifierToFraction(v.prerelease) / 100 / 100;\n};\n\n// Accepts an array, eg [\"rc\", 2, 3]. Returns a number in the range\n// (-1, 0].  An empty array returns 0. A non-empty string returns a\n// number that is \"as large\" as the its precedence.\nvar prereleaseIdentifierToFraction = function (prerelease) {\n  if (prerelease.length === 0)\n    return 0;\n\n  return __.reduce(prerelease, function (memo, part, index) {\n    var digit;\n    if (typeof part === 'number') {\n      digit = part+1;\n    } else if (typeof part === 'string') {\n      var VALID_CHARACTERS =\n            \"-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\n      var validCharToNumber = function (ch) {\n        var result = VALID_CHARACTERS.indexOf(ch);\n        if (result === -1)\n          throw new Error(\"Unexpected character in prerelease identifier: \" + ch);\n        else\n          return result;\n      };\n\n      digit = 101 + // Numeric parts always have lower precedence than non-numeric parts.\n        validCharToNumber(part[0]) * VALID_CHARACTERS.length +\n        (part[1] ? validCharToNumber(part[1]) : 0);\n    } else {\n      throw new Error(\"Unexpected prerelease identifier part: \" + part + \" of type \" + typeof part);\n    }\n\n    // 4100 > 101 + VALID_CHARACTERS.length *\n    // VALID_CHARACTERS.length. And there's a test to verify this\n    // (\"test the edges of `versionMagnitude`\")\n    return memo + digit / Math.pow(4100, index+1);\n  }, -1);\n};\n\n// Takes in two meteor versions. Returns true if the first one is less than the second.\n// Versions are strings or PackageVersion objects.\nPV.lessThan = function (versionOne, versionTwo) {\n  return PV.compare(versionOne, versionTwo) < 0;\n};\n\n// Given a string version, returns its major version (the first section of the\n// semver), as an integer. Two versions are compatible if they have the same\n// version number.\n//\n// versionString: valid meteor version string.\nPV.majorVersion = function (versionString) {\n  return PV.parse(versionString).major;\n};\n\n// Takes in two meteor versions. Returns 0 if equal, a positive number if v1\n// is greater, a negative number if v2 is greater.\n// Versions are strings or PackageVersion objects.\nPV.compare = function (versionOne, versionTwo) {\n  var v1 = versionOne;\n  if (typeof v1 === 'string') {\n    v1 = PV.parse(v1);\n  }\n  var v2 = versionTwo;\n  if (typeof v2 === 'string') {\n    v2 = PV.parse(v2);\n  }\n\n  // If the semver parts are different, use the semver library to compare,\n  // ignoring wrap numbers.  (The semver library will ignore the build ID\n  // per the semver spec.)\n  if (v1.semver !== v2.semver) {\n    if (! v1._semverParsed) {\n      v1._semverParsed = new semver(v1.semver);\n    }\n    if (! v2._semverParsed) {\n      v2._semverParsed = new semver(v2.semver);\n    }\n    return semver.compare(v1._semverParsed, v2._semverParsed);\n  } else {\n    // If the semver components are equal, then the one with the smaller wrap\n    // numbers is smaller.\n    return v1.wrapNum - v2.wrapNum;\n  }\n};\n\n// Conceptually we have three types of constraints:\n// 1. \"compatible-with\" - A@x.y.z - constraints package A to version x.y.z or\n//    higher, as long as the version is backwards compatible with x.y.z.\n//    \"pick A compatible with x.y.z\"\n//    It is the default type.\n// 2. \"exactly\" - A@=x.y.z - constraints package A only to version x.y.z and\n//    nothing else.\n//    \"pick A exactly at x.y.z\"\n// 3. \"any-reasonable\" - \"A\"\n//    Basically, this means any version of A ... other than ones that have\n//    dashes in the version (ie, are prerelease) ... unless the prerelease\n//    version has been explicitly selected (which at this stage in the game\n//    means they are mentioned in a top-level constraint in the top-level\n//    call to the resolver).\nvar parseSimpleConstraint = function (constraintString) {\n  if (! constraintString) {\n    throw new Error(\"Non-empty string required\");\n  }\n\n  var type, versionString;\n\n  if (constraintString.charAt(0) === '=') {\n    type = \"exactly\";\n    versionString = constraintString.substr(1);\n  } else {\n    type = \"compatible-with\";\n    versionString = constraintString;\n  }\n\n  // This will throw if the version string is invalid.\n  PV.getValidServerVersion(versionString);\n\n  return { type: type, versionString: versionString };\n};\n\n\n// Check to see if the versionString that we pass in is a valid meteor version.\n//\n// Returns a valid meteor version string that can be included in the\n// server. That means that it has everything EXCEPT the build id. Throws if the\n// entered string was invalid.\nPV.getValidServerVersion = function (meteorVersionString) {\n  return PV.parse(meteorVersionString).version;\n};\n\nPV.VersionConstraint = function (vConstraintString) {\n  var alternatives;\n  // If there is no version string (\"\" or null), then our only\n  // constraint is any-reasonable.\n  if (! vConstraintString) {\n    // .versionString === null is relied on in the tool\n    alternatives =\n      [ { type: \"any-reasonable\", versionString: null } ];\n    vConstraintString = \"\";\n  } else {\n    // Parse out the versionString.\n    var parts = vConstraintString.split(/ *\\|\\| */);\n    alternatives = __.map(parts, function (alt) {\n      if (! alt) {\n        throwVersionParserError(\"Invalid constraint string: \" +\n                                vConstraintString);\n      }\n      return parseSimpleConstraint(alt);\n    });\n  }\n\n  this.raw = vConstraintString;\n  this.alternatives = alternatives;\n};\n\nPV.parseVersionConstraint = function (constraintString) {\n  return new PV.VersionConstraint(constraintString);\n};\n\n// A PackageConstraint consists of a package name and a version constraint.\n// Call either with args (package, versionConstraintString) or\n// (packageConstraintString), or (package, versionConstraint).\n// That is, (\"foo\", \"1.2.3\") or (\"foo@1.2.3\"), or (\"foo\", vc) where vc\n// is instanceof PV.VersionConstraint.\nPV.PackageConstraint = function (part1, part2) {\n  if ((typeof part1 !== \"string\") ||\n      (part2 && (typeof part2 !== \"string\") &&\n       ! (part2 instanceof PV.VersionConstraint))) {\n    throw new Error(\"constraintString must be a string\");\n  }\n\n  var packageName, versionConstraint, vConstraintString;\n  if (part2) {\n    packageName = part1;\n    if (part2 instanceof PV.VersionConstraint) {\n      versionConstraint = part2;\n    } else {\n      vConstraintString = part2;\n    }\n  } else if (part1.indexOf(\"@\") >= 0) {\n    // Shave off last part after @, with \"a@b@c\" becoming [\"a@b\", \"c\"].\n    // Validating the package name will catch extra @.\n    var parts = part1.match(/^(.*)@([^@]*)$/).slice(1);\n    packageName = parts[0];\n    vConstraintString = parts[1];\n    if (! vConstraintString) {\n      throwVersionParserError(\n        \"Version constraint for package '\" + packageName +\n          \"' cannot be empty; leave off the @ if you don't want to constrain \" +\n          \"the version.\");\n    }\n  } else {\n    packageName = part1;\n    vConstraintString = \"\";\n  }\n\n  PV.validatePackageName(packageName);\n  if (versionConstraint) {\n    vConstraintString = versionConstraint.raw;\n  } else {\n    versionConstraint = PV.parseVersionConstraint(vConstraintString);\n  }\n\n  this.package = packageName;\n  this.constraintString = vConstraintString;\n  this.versionConstraint = versionConstraint;\n};\n\nPV.PackageConstraint.prototype.toString = function () {\n  var ret = this.package;\n  if (this.constraintString) {\n    ret += \"@\" + this.constraintString;\n  }\n  return ret;\n};\n\n// Structure of a parsed constraint:\n//\n// /*PV.PackageConstraint*/\n// { package: String,\n//   constraintString: String,\n//   versionConstraint: /*PV.VersionConstraint*/ {\n//     raw: String,\n//     alternatives: [{versionString: String|null,\n//                     type: String}]}}\nPV.parsePackageConstraint = function (part1, part2) {\n  return new PV.PackageConstraint(part1, part2);\n};\n\nPV.validatePackageName = function (packageName, options) {\n  options = options || {};\n\n  var badChar = packageName.match(/[^a-z0-9:.\\-]/);\n  if (badChar) {\n    if (options.detailedColonExplanation) {\n      throwVersionParserError(\n        \"Bad character in package name: \" + JSON.stringify(badChar[0]) +\n          \".\\n\\nPackage names can only contain lowercase ASCII alphanumerics, \" +\n          \"dash, or dot.\\nIf you plan to publish a package, it must be \" +\n          \"prefixed with your\\nMeteor Developer Account username and a colon.\");\n    }\n    throwVersionParserError(\n      \"Package names can only contain lowercase ASCII alphanumerics, dash, \" +\n        \"dot, or colon, not \" + JSON.stringify(badChar[0]) + \".\");\n  }\n  if (!/[a-z]/.test(packageName)) {\n    throwVersionParserError(\"Package name must contain a lowercase ASCII letter: \"\n                            + JSON.stringify(packageName));\n  }\n  if (packageName[0] === '.') {\n    throwVersionParserError(\"Package name may not begin with a dot: \"\n                            + JSON.stringify(packageName));\n  }\n  if (packageName.slice(-1) === '.') {\n    throwVersionParserError(\"Package name may not end with a dot: \"\n                            + JSON.stringify(packageName));\n  }\n\n  if (packageName.slice(-1) === '.') {\n    throwVersionParserError(\"Package names may not end with a dot: \" +\n                            JSON.stringify(packageName));\n  }\n  if (packageName.indexOf('..') >= 0) {\n    throwVersionParserError(\"Package names may not contain two consecutive dots: \" +\n                            JSON.stringify(packageName));\n  }\n  if (packageName[0] === '-') {\n    throwVersionParserError(\"Package names may not begin with a hyphen: \" +\n                            JSON.stringify(packageName));\n  }\n  // (There is already a package ending with a `-` and one with two consecutive `-`\n  // in troposphere, though they both look like typos.)\n\n  if (packageName[0] === \":\" || __.last(packageName) === \":\") {\n    throwVersionParserError(\"Package names may not start or end with a colon: \" +\n                            JSON.stringify(packageName));\n  }\n};\n\nvar throwVersionParserError = function (message) {\n  var e = new Error(message);\n  e.versionParserError = true;\n  throw e;\n};\n\n// Return true if the version constraint was invalid prior to 0.9.3\n// (adding _ and || support)\n//\n// NOTE: this is not used on the client yet. This package is used by the\n// package server to determine what is valid.\nPV.invalidFirstFormatConstraint = function (validConstraint) {\n  if (!validConstraint) return false;\n  // We can check this easily right now, because we introduced some new\n  // characters. Anything with those characters is invalid prior to\n  // 0.9.3. XXX: If we ever have to go through these, we should write a more\n  // complicated regex.\n  return (/_/.test(validConstraint) ||\n          /\\|/.test(validConstraint));\n};\n\n// Remove a suffix like \"+foo\" if present.\nPV.removeBuildID = function (versionString) {\n  return versionString.replace(/\\+.*$/, '');\n};\n"
  },
  {
    "path": "packages/package-version-parser/package.js",
    "content": "Package.describe({\n  summary: \"Parses Meteor Smart Package version strings\",\n  version: \"3.0.9\"\n});\n\nPackage.onUse(function (api) {\n  api.export('PackageVersion');\n  api.use('underscore');\n  api.addFiles(['semver410.js',\n                'package-version-parser.js']);\n});\n\nPackage.onTest(function (api) {\n  api.use('package-version-parser');\n  api.use(['tinytest', 'underscore']);\n  api.addFiles('package-version-parser-tests.js', 'server');\n});\n"
  },
  {
    "path": "packages/package-version-parser/semver410.js",
    "content": "// <METEOR>\n// Fool the module system detection code below so that it doesn't\n// do anything special.\nvar exports = SemVer, module = {}, define = {};\n// Create a package-private variable.  Can't use SemVer because\n// of the code that says `function SemVer(...)` below (implicitly\n// declaring a var).  Can't use \"semver\" because that's a var in\n// package-version-parser.js.\nSemVer410 = SemVer;\n// </METEOR>\n\n// export the class if we are in a Node-like system.\nif (typeof module === 'object' && module.exports === exports)\n  exports = module.exports = SemVer;\n\n// The debug function is excluded entirely from the minified version.\n/* nomin */ var debug;\n/* nomin */ if (typeof process === 'object' &&\n    /* nomin */ process.env &&\n    /* nomin */ process.env.NODE_DEBUG &&\n    /* nomin */ /\\bsemver\\b/i.test(process.env.NODE_DEBUG))\n  /* nomin */ debug = function() {\n    /* nomin */ var args = Array.prototype.slice.call(arguments, 0);\n    /* nomin */ args.unshift('SEMVER');\n    /* nomin */ console.log.apply(console, args);\n    /* nomin */ };\n/* nomin */ else\n  /* nomin */ debug = function() {};\n\n// Note: this is the semver.org version of the spec that it implements\n// Not necessarily the package version of this code.\nexports.SEMVER_SPEC_VERSION = '2.0.0';\n\n// The actual regexps go on exports.re\nvar re = exports.re = [];\nvar src = exports.src = [];\nvar R = 0;\n\n// The following Regular Expressions can be used for tokenizing,\n// validating, and parsing SemVer version strings.\n\n// ## Numeric Identifier\n// A single `0`, or a non-zero digit followed by zero or more digits.\n\nvar NUMERICIDENTIFIER = R++;\nsrc[NUMERICIDENTIFIER] = '0|[1-9]\\\\d*';\nvar NUMERICIDENTIFIERLOOSE = R++;\nsrc[NUMERICIDENTIFIERLOOSE] = '[0-9]+';\n\n\n// ## Non-numeric Identifier\n// Zero or more digits, followed by a letter or hyphen, and then zero or\n// more letters, digits, or hyphens.\n\nvar NONNUMERICIDENTIFIER = R++;\nsrc[NONNUMERICIDENTIFIER] = '\\\\d*[a-zA-Z-][a-zA-Z0-9-]*';\n\n\n// ## Main Version\n// Three dot-separated numeric identifiers.\n\nvar MAINVERSION = R++;\nsrc[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\\\.' +\n                   '(' + src[NUMERICIDENTIFIER] + ')\\\\.' +\n                   '(' + src[NUMERICIDENTIFIER] + ')';\n\nvar MAINVERSIONLOOSE = R++;\nsrc[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\\\.' +\n                        '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\\\.' +\n                        '(' + src[NUMERICIDENTIFIERLOOSE] + ')';\n\n// ## Pre-release Version Identifier\n// A numeric identifier, or a non-numeric identifier.\n\nvar PRERELEASEIDENTIFIER = R++;\nsrc[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] +\n                            '|' + src[NONNUMERICIDENTIFIER] + ')';\n\nvar PRERELEASEIDENTIFIERLOOSE = R++;\nsrc[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] +\n                                 '|' + src[NONNUMERICIDENTIFIER] + ')';\n\n\n// ## Pre-release Version\n// Hyphen, followed by one or more dot-separated pre-release version\n// identifiers.\n\nvar PRERELEASE = R++;\nsrc[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] +\n                  '(?:\\\\.' + src[PRERELEASEIDENTIFIER] + ')*))';\n\nvar PRERELEASELOOSE = R++;\nsrc[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] +\n                       '(?:\\\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))';\n\n// ## Build Metadata Identifier\n// Any combination of digits, letters, or hyphens.\n\nvar BUILDIDENTIFIER = R++;\nsrc[BUILDIDENTIFIER] = '[0-9A-Za-z-]+';\n\n// ## Build Metadata\n// Plus sign, followed by one or more period-separated build metadata\n// identifiers.\n\nvar BUILD = R++;\nsrc[BUILD] = '(?:\\\\+(' + src[BUILDIDENTIFIER] +\n             '(?:\\\\.' + src[BUILDIDENTIFIER] + ')*))';\n\n\n// ## Full Version String\n// A main version, followed optionally by a pre-release version and\n// build metadata.\n\n// Note that the only major, minor, patch, and pre-release sections of\n// the version string are capturing groups.  The build metadata is not a\n// capturing group, because it should not ever be used in version\n// comparison.\n\nvar FULL = R++;\nvar FULLPLAIN = 'v?' + src[MAINVERSION] +\n                src[PRERELEASE] + '?' +\n                src[BUILD] + '?';\n\nsrc[FULL] = '^' + FULLPLAIN + '$';\n\n// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.\n// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty\n// common in the npm registry.\nvar LOOSEPLAIN = '[v=\\\\s]*' + src[MAINVERSIONLOOSE] +\n                 src[PRERELEASELOOSE] + '?' +\n                 src[BUILD] + '?';\n\nvar LOOSE = R++;\nsrc[LOOSE] = '^' + LOOSEPLAIN + '$';\n\nvar GTLT = R++;\nsrc[GTLT] = '((?:<|>)?=?)';\n\n// Something like \"2.*\" or \"1.2.x\".\n// Note that \"x.x\" is a valid xRange identifer, meaning \"any version\"\n// Only the first item is strictly required.\nvar XRANGEIDENTIFIERLOOSE = R++;\nsrc[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\\\*';\nvar XRANGEIDENTIFIER = R++;\nsrc[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\\\*';\n\nvar XRANGEPLAIN = R++;\nsrc[XRANGEPLAIN] = '[v=\\\\s]*(' + src[XRANGEIDENTIFIER] + ')' +\n                   '(?:\\\\.(' + src[XRANGEIDENTIFIER] + ')' +\n                   '(?:\\\\.(' + src[XRANGEIDENTIFIER] + ')' +\n                   '(?:' + src[PRERELEASE] + ')?' +\n                   src[BUILD] + '?' +\n                   ')?)?';\n\nvar XRANGEPLAINLOOSE = R++;\nsrc[XRANGEPLAINLOOSE] = '[v=\\\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' +\n                        '(?:\\\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +\n                        '(?:\\\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +\n                        '(?:' + src[PRERELEASELOOSE] + ')?' +\n                        src[BUILD] + '?' +\n                        ')?)?';\n\nvar XRANGE = R++;\nsrc[XRANGE] = '^' + src[GTLT] + '\\\\s*' + src[XRANGEPLAIN] + '$';\nvar XRANGELOOSE = R++;\nsrc[XRANGELOOSE] = '^' + src[GTLT] + '\\\\s*' + src[XRANGEPLAINLOOSE] + '$';\n\n// Tilde ranges.\n// Meaning is \"reasonably at or greater than\"\nvar LONETILDE = R++;\nsrc[LONETILDE] = '(?:~>?)';\n\nvar TILDETRIM = R++;\nsrc[TILDETRIM] = '(\\\\s*)' + src[LONETILDE] + '\\\\s+';\nre[TILDETRIM] = new RegExp(src[TILDETRIM], 'g');\nvar tildeTrimReplace = '$1~';\n\nvar TILDE = R++;\nsrc[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$';\nvar TILDELOOSE = R++;\nsrc[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$';\n\n// Caret ranges.\n// Meaning is \"at least and backwards compatible with\"\nvar LONECARET = R++;\nsrc[LONECARET] = '(?:\\\\^)';\n\nvar CARETTRIM = R++;\nsrc[CARETTRIM] = '(\\\\s*)' + src[LONECARET] + '\\\\s+';\nre[CARETTRIM] = new RegExp(src[CARETTRIM], 'g');\nvar caretTrimReplace = '$1^';\n\nvar CARET = R++;\nsrc[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$';\nvar CARETLOOSE = R++;\nsrc[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$';\n\n// A simple gt/lt/eq thing, or just \"\" to indicate \"any version\"\nvar COMPARATORLOOSE = R++;\nsrc[COMPARATORLOOSE] = '^' + src[GTLT] + '\\\\s*(' + LOOSEPLAIN + ')$|^$';\nvar COMPARATOR = R++;\nsrc[COMPARATOR] = '^' + src[GTLT] + '\\\\s*(' + FULLPLAIN + ')$|^$';\n\n\n// An expression to strip any whitespace between the gtlt and the thing\n// it modifies, so that `> 1.2.3` ==> `>1.2.3`\nvar COMPARATORTRIM = R++;\nsrc[COMPARATORTRIM] = '(\\\\s*)' + src[GTLT] +\n                      '\\\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')';\n\n// this one has to use the /g flag\nre[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g');\nvar comparatorTrimReplace = '$1$2$3';\n\n\n// Something like `1.2.3 - 1.2.4`\n// Note that these all use the loose form, because they'll be\n// checked against either the strict or loose comparator form\n// later.\nvar HYPHENRANGE = R++;\nsrc[HYPHENRANGE] = '^\\\\s*(' + src[XRANGEPLAIN] + ')' +\n                   '\\\\s+-\\\\s+' +\n                   '(' + src[XRANGEPLAIN] + ')' +\n                   '\\\\s*$';\n\nvar HYPHENRANGELOOSE = R++;\nsrc[HYPHENRANGELOOSE] = '^\\\\s*(' + src[XRANGEPLAINLOOSE] + ')' +\n                        '\\\\s+-\\\\s+' +\n                        '(' + src[XRANGEPLAINLOOSE] + ')' +\n                        '\\\\s*$';\n\n// Star ranges basically just allow anything at all.\nvar STAR = R++;\nsrc[STAR] = '(<|>)?=?\\\\s*\\\\*';\n\n// Compile to actual regexp objects.\n// All are flag-free, unless they were created above with a flag.\nfor (var i = 0; i < R; i++) {\n  debug(i, src[i]);\n  if (!re[i])\n    re[i] = new RegExp(src[i]);\n}\n\nexports.parse = parse;\nfunction parse(version, loose) {\n  var r = loose ? re[LOOSE] : re[FULL];\n  return (r.test(version)) ? new SemVer(version, loose) : null;\n}\n\nexports.valid = valid;\nfunction valid(version, loose) {\n  var v = parse(version, loose);\n  return v ? v.version : null;\n}\n\n\nexports.clean = clean;\nfunction clean(version, loose) {\n  var s = parse(version.trim().replace(/^[=v]+/, ''), loose);\n  return s ? s.version : null;\n}\n\nexports.SemVer = SemVer;\n\nfunction SemVer(version, loose) {\n  if (version instanceof SemVer) {\n    if (version.loose === loose)\n      return version;\n    else\n      version = version.version;\n  } else if (typeof version !== 'string') {\n    throw new TypeError('Invalid Version: ' + version);\n  }\n\n  if (!(this instanceof SemVer))\n    return new SemVer(version, loose);\n\n  debug('SemVer', version, loose);\n  this.loose = loose;\n  var m = version.trim().match(loose ? re[LOOSE] : re[FULL]);\n\n  if (!m)\n    throw new TypeError('Invalid Version: ' + version);\n\n  this.raw = version;\n\n  // these are actually numbers\n  this.major = +m[1];\n  this.minor = +m[2];\n  this.patch = +m[3];\n\n  // numberify any prerelease numeric ids\n  if (!m[4])\n    this.prerelease = [];\n  else\n    this.prerelease = m[4].split('.').map(function(id) {\n      return (/^[0-9]+$/.test(id)) ? +id : id;\n    });\n\n  this.build = m[5] ? m[5].split('.') : [];\n  this.format();\n}\n\nSemVer.prototype.format = function() {\n  this.version = this.major + '.' + this.minor + '.' + this.patch;\n  if (this.prerelease.length)\n    this.version += '-' + this.prerelease.join('.');\n  return this.version;\n};\n\nSemVer.prototype.inspect = function() {\n  return '<SemVer \"' + this + '\">';\n};\n\nSemVer.prototype.toString = function() {\n  return this.version;\n};\n\nSemVer.prototype.compare = function(other) {\n  debug('SemVer.compare', this.version, this.loose, other);\n  if (!(other instanceof SemVer))\n    other = new SemVer(other, this.loose);\n\n  return this.compareMain(other) || this.comparePre(other);\n};\n\nSemVer.prototype.compareMain = function(other) {\n  if (!(other instanceof SemVer))\n    other = new SemVer(other, this.loose);\n\n  return compareIdentifiers(this.major, other.major) ||\n         compareIdentifiers(this.minor, other.minor) ||\n         compareIdentifiers(this.patch, other.patch);\n};\n\nSemVer.prototype.comparePre = function(other) {\n  if (!(other instanceof SemVer))\n    other = new SemVer(other, this.loose);\n\n  // NOT having a prerelease is > having one\n  if (this.prerelease.length && !other.prerelease.length)\n    return -1;\n  else if (!this.prerelease.length && other.prerelease.length)\n    return 1;\n  else if (!this.prerelease.length && !other.prerelease.length)\n    return 0;\n\n  var i = 0;\n  do {\n    var a = this.prerelease[i];\n    var b = other.prerelease[i];\n    debug('prerelease compare', i, a, b);\n    if (a === undefined && b === undefined)\n      return 0;\n    else if (b === undefined)\n      return 1;\n    else if (a === undefined)\n      return -1;\n    else if (a === b)\n      continue;\n    else\n      return compareIdentifiers(a, b);\n  } while (++i);\n};\n\n// preminor will bump the version up to the next minor release, and immediately\n// down to pre-release. premajor and prepatch work the same way.\nSemVer.prototype.inc = function(release, identifier) {\n  switch (release) {\n    case 'premajor':\n      this.prerelease.length = 0;\n      this.patch = 0;\n      this.minor = 0;\n      this.major++;\n      this.inc('pre', identifier);\n      break;\n    case 'preminor':\n      this.prerelease.length = 0;\n      this.patch = 0;\n      this.minor++;\n      this.inc('pre', identifier);\n      break;\n    case 'prepatch':\n      // If this is already a prerelease, it will bump to the next version\n      // drop any prereleases that might already exist, since they are not\n      // relevant at this point.\n      this.prerelease.length = 0;\n      this.inc('patch', identifier);\n      this.inc('pre', identifier);\n      break;\n    // If the input is a non-prerelease version, this acts the same as\n    // prepatch.\n    case 'prerelease':\n      if (this.prerelease.length === 0)\n        this.inc('patch', identifier);\n      this.inc('pre', identifier);\n      break;\n\n    case 'major':\n      // If this is a pre-major version, bump up to the same major version.\n      // Otherwise increment major.\n      // 1.0.0-5 bumps to 1.0.0\n      // 1.1.0 bumps to 2.0.0\n      if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0)\n        this.major++;\n      this.minor = 0;\n      this.patch = 0;\n      this.prerelease = [];\n      break;\n    case 'minor':\n      // If this is a pre-minor version, bump up to the same minor version.\n      // Otherwise increment minor.\n      // 1.2.0-5 bumps to 1.2.0\n      // 1.2.1 bumps to 1.3.0\n      if (this.patch !== 0 || this.prerelease.length === 0)\n        this.minor++;\n      this.patch = 0;\n      this.prerelease = [];\n      break;\n    case 'patch':\n      // If this is not a pre-release version, it will increment the patch.\n      // If it is a pre-release it will bump up to the same patch version.\n      // 1.2.0-5 patches to 1.2.0\n      // 1.2.0 patches to 1.2.1\n      if (this.prerelease.length === 0)\n        this.patch++;\n      this.prerelease = [];\n      break;\n    // This probably shouldn't be used publicly.\n    // 1.0.0 \"pre\" would become 1.0.0-0 which is the wrong direction.\n    case 'pre':\n      if (this.prerelease.length === 0)\n        this.prerelease = [0];\n      else {\n        var i = this.prerelease.length;\n        while (--i >= 0) {\n          if (typeof this.prerelease[i] === 'number') {\n            this.prerelease[i]++;\n            i = -2;\n          }\n        }\n        if (i === -1) // didn't increment anything\n          this.prerelease.push(0);\n      }\n      if (identifier) {\n        // 1.2.0-beta.1 bumps to 1.2.0-beta.2,\n        // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0\n        if (this.prerelease[0] === identifier) {\n          if (isNaN(this.prerelease[1]))\n            this.prerelease = [identifier, 0];\n        } else\n          this.prerelease = [identifier, 0];\n      }\n      break;\n\n    default:\n      throw new Error('invalid increment argument: ' + release);\n  }\n  this.format();\n  return this;\n};\n\nexports.inc = inc;\nfunction inc(version, release, loose, identifier) {\n  if (typeof(loose) === 'string') {\n    identifier = loose;\n    loose = undefined;\n  }\n\n  try {\n    return new SemVer(version, loose).inc(release, identifier).version;\n  } catch (er) {\n    return null;\n  }\n}\n\nexports.compareIdentifiers = compareIdentifiers;\n\nvar numeric = /^[0-9]+$/;\nfunction compareIdentifiers(a, b) {\n  var anum = numeric.test(a);\n  var bnum = numeric.test(b);\n\n  if (anum && bnum) {\n    a = +a;\n    b = +b;\n  }\n\n  return (anum && !bnum) ? -1 :\n         (bnum && !anum) ? 1 :\n         a < b ? -1 :\n         a > b ? 1 :\n         0;\n}\n\nexports.rcompareIdentifiers = rcompareIdentifiers;\nfunction rcompareIdentifiers(a, b) {\n  return compareIdentifiers(b, a);\n}\n\nexports.compare = compare;\nfunction compare(a, b, loose) {\n  return new SemVer(a, loose).compare(b);\n}\n\nexports.compareLoose = compareLoose;\nfunction compareLoose(a, b) {\n  return compare(a, b, true);\n}\n\nexports.rcompare = rcompare;\nfunction rcompare(a, b, loose) {\n  return compare(b, a, loose);\n}\n\nexports.sort = sort;\nfunction sort(list, loose) {\n  return list.sort(function(a, b) {\n    return exports.compare(a, b, loose);\n  });\n}\n\nexports.rsort = rsort;\nfunction rsort(list, loose) {\n  return list.sort(function(a, b) {\n    return exports.rcompare(a, b, loose);\n  });\n}\n\nexports.gt = gt;\nfunction gt(a, b, loose) {\n  return compare(a, b, loose) > 0;\n}\n\nexports.lt = lt;\nfunction lt(a, b, loose) {\n  return compare(a, b, loose) < 0;\n}\n\nexports.eq = eq;\nfunction eq(a, b, loose) {\n  return compare(a, b, loose) === 0;\n}\n\nexports.neq = neq;\nfunction neq(a, b, loose) {\n  return compare(a, b, loose) !== 0;\n}\n\nexports.gte = gte;\nfunction gte(a, b, loose) {\n  return compare(a, b, loose) >= 0;\n}\n\nexports.lte = lte;\nfunction lte(a, b, loose) {\n  return compare(a, b, loose) <= 0;\n}\n\nexports.cmp = cmp;\nfunction cmp(a, op, b, loose) {\n  var ret;\n  switch (op) {\n    case '===':\n      if (typeof a === 'object') a = a.version;\n      if (typeof b === 'object') b = b.version;\n      ret = a === b;\n      break;\n    case '!==':\n      if (typeof a === 'object') a = a.version;\n      if (typeof b === 'object') b = b.version;\n      ret = a !== b;\n      break;\n    case '': case '=': case '==': ret = eq(a, b, loose); break;\n    case '!=': ret = neq(a, b, loose); break;\n    case '>': ret = gt(a, b, loose); break;\n    case '>=': ret = gte(a, b, loose); break;\n    case '<': ret = lt(a, b, loose); break;\n    case '<=': ret = lte(a, b, loose); break;\n    default: throw new TypeError('Invalid operator: ' + op);\n  }\n  return ret;\n}\n\nexports.Comparator = Comparator;\nfunction Comparator(comp, loose) {\n  if (comp instanceof Comparator) {\n    if (comp.loose === loose)\n      return comp;\n    else\n      comp = comp.value;\n  }\n\n  if (!(this instanceof Comparator))\n    return new Comparator(comp, loose);\n\n  debug('comparator', comp, loose);\n  this.loose = loose;\n  this.parse(comp);\n\n  if (this.semver === ANY)\n    this.value = '';\n  else\n    this.value = this.operator + this.semver.version;\n\n  debug('comp', this);\n}\n\nvar ANY = {};\nComparator.prototype.parse = function(comp) {\n  var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR];\n  var m = comp.match(r);\n\n  if (!m)\n    throw new TypeError('Invalid comparator: ' + comp);\n\n  this.operator = m[1];\n  if (this.operator === '=')\n    this.operator = '';\n\n  // if it literally is just '>' or '' then allow anything.\n  if (!m[2])\n    this.semver = ANY;\n  else\n    this.semver = new SemVer(m[2], this.loose);\n};\n\nComparator.prototype.inspect = function() {\n  return '<SemVer Comparator \"' + this + '\">';\n};\n\nComparator.prototype.toString = function() {\n  return this.value;\n};\n\nComparator.prototype.test = function(version) {\n  debug('Comparator.test', version, this.loose);\n\n  if (this.semver === ANY)\n    return true;\n\n  if (typeof version === 'string')\n    version = new SemVer(version, this.loose);\n\n  return cmp(version, this.operator, this.semver, this.loose);\n};\n\n\nexports.Range = Range;\nfunction Range(range, loose) {\n  if ((range instanceof Range) && range.loose === loose)\n    return range;\n\n  if (!(this instanceof Range))\n    return new Range(range, loose);\n\n  this.loose = loose;\n\n  // First, split based on boolean or ||\n  this.raw = range;\n  this.set = range.split(/\\s*\\|\\|\\s*/).map(function(range) {\n    return this.parseRange(range.trim());\n  }, this).filter(function(c) {\n    // throw out any that are not relevant for whatever reason\n    return c.length;\n  });\n\n  if (!this.set.length) {\n    throw new TypeError('Invalid SemVer Range: ' + range);\n  }\n\n  this.format();\n}\n\nRange.prototype.inspect = function() {\n  return '<SemVer Range \"' + this.range + '\">';\n};\n\nRange.prototype.format = function() {\n  this.range = this.set.map(function(comps) {\n    return comps.join(' ').trim();\n  }).join('||').trim();\n  return this.range;\n};\n\nRange.prototype.toString = function() {\n  return this.range;\n};\n\nRange.prototype.parseRange = function(range) {\n  var loose = this.loose;\n  range = range.trim();\n  debug('range', range, loose);\n  // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`\n  var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE];\n  range = range.replace(hr, hyphenReplace);\n  debug('hyphen replace', range);\n  // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`\n  range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace);\n  debug('comparator trim', range, re[COMPARATORTRIM]);\n\n  // `~ 1.2.3` => `~1.2.3`\n  range = range.replace(re[TILDETRIM], tildeTrimReplace);\n\n  // `^ 1.2.3` => `^1.2.3`\n  range = range.replace(re[CARETTRIM], caretTrimReplace);\n\n  // normalize spaces\n  range = range.split(/\\s+/).join(' ');\n\n  // At this point, the range is completely trimmed and\n  // ready to be split into comparators.\n\n  var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR];\n  var set = range.split(' ').map(function(comp) {\n    return parseComparator(comp, loose);\n  }).join(' ').split(/\\s+/);\n  if (this.loose) {\n    // in loose mode, throw out any that are not valid comparators\n    set = set.filter(function(comp) {\n      return !!comp.match(compRe);\n    });\n  }\n  set = set.map(function(comp) {\n    return new Comparator(comp, loose);\n  });\n\n  return set;\n};\n\n// Mostly just for testing and legacy API reasons\nexports.toComparators = toComparators;\nfunction toComparators(range, loose) {\n  return new Range(range, loose).set.map(function(comp) {\n    return comp.map(function(c) {\n      return c.value;\n    }).join(' ').trim().split(' ');\n  });\n}\n\n// comprised of xranges, tildes, stars, and gtlt's at this point.\n// already replaced the hyphen ranges\n// turn into a set of JUST comparators.\nfunction parseComparator(comp, loose) {\n  debug('comp', comp);\n  comp = replaceCarets(comp, loose);\n  debug('caret', comp);\n  comp = replaceTildes(comp, loose);\n  debug('tildes', comp);\n  comp = replaceXRanges(comp, loose);\n  debug('xrange', comp);\n  comp = replaceStars(comp, loose);\n  debug('stars', comp);\n  return comp;\n}\n\nfunction isX(id) {\n  return !id || id.toLowerCase() === 'x' || id === '*';\n}\n\n// ~, ~> --> * (any, kinda silly)\n// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0\n// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0\n// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0\n// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0\n// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0\nfunction replaceTildes(comp, loose) {\n  return comp.trim().split(/\\s+/).map(function(comp) {\n    return replaceTilde(comp, loose);\n  }).join(' ');\n}\n\nfunction replaceTilde(comp, loose) {\n  var r = loose ? re[TILDELOOSE] : re[TILDE];\n  return comp.replace(r, function(_, M, m, p, pr) {\n    debug('tilde', comp, _, M, m, p, pr);\n    var ret;\n\n    if (isX(M))\n      ret = '';\n    else if (isX(m))\n      ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';\n    else if (isX(p))\n      // ~1.2 == >=1.2.0- <1.3.0-\n      ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';\n    else if (pr) {\n      debug('replaceTilde pr', pr);\n      if (pr.charAt(0) !== '-')\n        pr = '-' + pr;\n      ret = '>=' + M + '.' + m + '.' + p + pr +\n            ' <' + M + '.' + (+m + 1) + '.0';\n    } else\n      // ~1.2.3 == >=1.2.3 <1.3.0\n      ret = '>=' + M + '.' + m + '.' + p +\n            ' <' + M + '.' + (+m + 1) + '.0';\n\n    debug('tilde return', ret);\n    return ret;\n  });\n}\n\n// ^ --> * (any, kinda silly)\n// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0\n// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0\n// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0\n// ^1.2.3 --> >=1.2.3 <2.0.0\n// ^1.2.0 --> >=1.2.0 <2.0.0\nfunction replaceCarets(comp, loose) {\n  return comp.trim().split(/\\s+/).map(function(comp) {\n    return replaceCaret(comp, loose);\n  }).join(' ');\n}\n\nfunction replaceCaret(comp, loose) {\n  debug('caret', comp, loose);\n  var r = loose ? re[CARETLOOSE] : re[CARET];\n  return comp.replace(r, function(_, M, m, p, pr) {\n    debug('caret', comp, _, M, m, p, pr);\n    var ret;\n\n    if (isX(M))\n      ret = '';\n    else if (isX(m))\n      ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';\n    else if (isX(p)) {\n      if (M === '0')\n        ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';\n      else\n        ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0';\n    } else if (pr) {\n      debug('replaceCaret pr', pr);\n      if (pr.charAt(0) !== '-')\n        pr = '-' + pr;\n      if (M === '0') {\n        if (m === '0')\n          ret = '>=' + M + '.' + m + '.' + p + pr +\n                ' <' + M + '.' + m + '.' + (+p + 1);\n        else\n          ret = '>=' + M + '.' + m + '.' + p + pr +\n                ' <' + M + '.' + (+m + 1) + '.0';\n      } else\n        ret = '>=' + M + '.' + m + '.' + p + pr +\n              ' <' + (+M + 1) + '.0.0';\n    } else {\n      debug('no pr');\n      if (M === '0') {\n        if (m === '0')\n          ret = '>=' + M + '.' + m + '.' + p +\n                ' <' + M + '.' + m + '.' + (+p + 1);\n        else\n          ret = '>=' + M + '.' + m + '.' + p +\n                ' <' + M + '.' + (+m + 1) + '.0';\n      } else\n        ret = '>=' + M + '.' + m + '.' + p +\n              ' <' + (+M + 1) + '.0.0';\n    }\n\n    debug('caret return', ret);\n    return ret;\n  });\n}\n\nfunction replaceXRanges(comp, loose) {\n  debug('replaceXRanges', comp, loose);\n  return comp.split(/\\s+/).map(function(comp) {\n    return replaceXRange(comp, loose);\n  }).join(' ');\n}\n\nfunction replaceXRange(comp, loose) {\n  comp = comp.trim();\n  var r = loose ? re[XRANGELOOSE] : re[XRANGE];\n  return comp.replace(r, function(ret, gtlt, M, m, p, pr) {\n    debug('xRange', comp, ret, gtlt, M, m, p, pr);\n    var xM = isX(M);\n    var xm = xM || isX(m);\n    var xp = xm || isX(p);\n    var anyX = xp;\n\n    if (gtlt === '=' && anyX)\n      gtlt = '';\n\n    if (xM) {\n      if (gtlt === '>' || gtlt === '<') {\n        // nothing is allowed\n        ret = '<0.0.0';\n      } else {\n        // nothing is forbidden\n        ret = '*';\n      }\n    } else if (gtlt && anyX) {\n      // replace X with 0\n      if (xm)\n        m = 0;\n      if (xp)\n        p = 0;\n\n      if (gtlt === '>') {\n        // >1 => >=2.0.0\n        // >1.2 => >=1.3.0\n        // >1.2.3 => >= 1.2.4\n        gtlt = '>=';\n        if (xm) {\n          M = +M + 1;\n          m = 0;\n          p = 0;\n        } else if (xp) {\n          m = +m + 1;\n          p = 0;\n        }\n      } else if (gtlt === '<=') {\n        // <=0.7.x is actually <0.8.0, since any 0.7.x should\n        // pass.  Similarly, <=7.x is actually <8.0.0, etc.\n        gtlt = '<'\n        if (xm)\n          M = +M + 1\n        else\n          m = +m + 1\n      }\n\n      ret = gtlt + M + '.' + m + '.' + p;\n    } else if (xm) {\n      ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';\n    } else if (xp) {\n      ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';\n    }\n\n    debug('xRange return', ret);\n\n    return ret;\n  });\n}\n\n// Because * is AND-ed with everything else in the comparator,\n// and '' means \"any version\", just remove the *s entirely.\nfunction replaceStars(comp, loose) {\n  debug('replaceStars', comp, loose);\n  // Looseness is ignored here.  star is always as loose as it gets!\n  return comp.trim().replace(re[STAR], '');\n}\n\n// This function is passed to string.replace(re[HYPHENRANGE])\n// M, m, patch, prerelease, build\n// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5\n// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do\n// 1.2 - 3.4 => >=1.2.0 <3.5.0\nfunction hyphenReplace($0,\n                       from, fM, fm, fp, fpr, fb,\n                       to, tM, tm, tp, tpr, tb) {\n\n  if (isX(fM))\n    from = '';\n  else if (isX(fm))\n    from = '>=' + fM + '.0.0';\n  else if (isX(fp))\n    from = '>=' + fM + '.' + fm + '.0';\n  else\n    from = '>=' + from;\n\n  if (isX(tM))\n    to = '';\n  else if (isX(tm))\n    to = '<' + (+tM + 1) + '.0.0';\n  else if (isX(tp))\n    to = '<' + tM + '.' + (+tm + 1) + '.0';\n  else if (tpr)\n    to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr;\n  else\n    to = '<=' + to;\n\n  return (from + ' ' + to).trim();\n}\n\n\n// if ANY of the sets match ALL of its comparators, then pass\nRange.prototype.test = function(version) {\n  if (!version)\n    return false;\n\n  if (typeof version === 'string')\n    version = new SemVer(version, this.loose);\n\n  for (var i = 0; i < this.set.length; i++) {\n    if (testSet(this.set[i], version))\n      return true;\n  }\n  return false;\n};\n\nfunction testSet(set, version) {\n  for (var i = 0; i < set.length; i++) {\n    if (!set[i].test(version))\n      return false;\n  }\n\n  if (version.prerelease.length) {\n    // Find the set of versions that are allowed to have prereleases\n    // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0\n    // That should allow `1.2.3-pr.2` to pass.\n    // However, `1.2.4-alpha.notready` should NOT be allowed,\n    // even though it's within the range set by the comparators.\n    for (var i = 0; i < set.length; i++) {\n      debug(set[i].semver);\n      if (set[i].semver === ANY)\n        return true;\n\n      if (set[i].semver.prerelease.length > 0) {\n        var allowed = set[i].semver;\n        if (allowed.major === version.major &&\n            allowed.minor === version.minor &&\n            allowed.patch === version.patch)\n          return true;\n      }\n    }\n\n    // Version has a -pre, but it's not one of the ones we like.\n    return false;\n  }\n\n  return true;\n}\n\nexports.satisfies = satisfies;\nfunction satisfies(version, range, loose) {\n  try {\n    range = new Range(range, loose);\n  } catch (er) {\n    return false;\n  }\n  return range.test(version);\n}\n\nexports.maxSatisfying = maxSatisfying;\nfunction maxSatisfying(versions, range, loose) {\n  return versions.filter(function(version) {\n    return satisfies(version, range, loose);\n  }).sort(function(a, b) {\n    return rcompare(a, b, loose);\n  })[0] || null;\n}\n\nexports.validRange = validRange;\nfunction validRange(range, loose) {\n  try {\n    // Return '*' instead of '' so that truthiness works.\n    // This will throw if it's invalid anyway\n    return new Range(range, loose).range || '*';\n  } catch (er) {\n    return null;\n  }\n}\n\n// Determine if version is less than all the versions possible in the range\nexports.ltr = ltr;\nfunction ltr(version, range, loose) {\n  return outside(version, range, '<', loose);\n}\n\n// Determine if version is greater than all the versions possible in the range.\nexports.gtr = gtr;\nfunction gtr(version, range, loose) {\n  return outside(version, range, '>', loose);\n}\n\nexports.outside = outside;\nfunction outside(version, range, hilo, loose) {\n  version = new SemVer(version, loose);\n  range = new Range(range, loose);\n\n  var gtfn, ltefn, ltfn, comp, ecomp;\n  switch (hilo) {\n    case '>':\n      gtfn = gt;\n      ltefn = lte;\n      ltfn = lt;\n      comp = '>';\n      ecomp = '>=';\n      break;\n    case '<':\n      gtfn = lt;\n      ltefn = gte;\n      ltfn = gt;\n      comp = '<';\n      ecomp = '<=';\n      break;\n    default:\n      throw new TypeError('Must provide a hilo val of \"<\" or \">\"');\n  }\n\n  // If it satisifes the range it is not outside\n  if (satisfies(version, range, loose)) {\n    return false;\n  }\n\n  // From now on, variable terms are as if we're in \"gtr\" mode.\n  // but note that everything is flipped for the \"ltr\" function.\n\n  for (var i = 0; i < range.set.length; ++i) {\n    var comparators = range.set[i];\n\n    var high = null;\n    var low = null;\n\n    comparators.forEach(function(comparator) {\n      high = high || comparator;\n      low = low || comparator;\n      if (gtfn(comparator.semver, high.semver, loose)) {\n        high = comparator;\n      } else if (ltfn(comparator.semver, low.semver, loose)) {\n        low = comparator;\n      }\n    });\n\n    // If the edge version comparator has a operator then our version\n    // isn't outside it\n    if (high.operator === comp || high.operator === ecomp) {\n      return false;\n    }\n\n    // If the lowest version comparator has an operator and our version\n    // is less than it then it isn't higher than the range\n    if ((!low.operator || low.operator === comp) &&\n        ltefn(version, low.semver)) {\n      return false;\n    } else if (low.operator === ecomp && ltfn(version, low.semver)) {\n      return false;\n    }\n  }\n  return true;\n}\n\n// Use the define() function if we're in AMD land\nif (typeof define === 'function' && define.amd)\n  define(exports);\n"
  },
  {
    "path": "packages/preserve-inputs/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/preserve-inputs/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/preserve-inputs/deprecated.js",
    "content": "console.log(\"The 'preserve-inputs' package is now unnecessary and deprecated.\");\n"
  },
  {
    "path": "packages/preserve-inputs/package.js",
    "content": "Package.describe({\n  summary: \"Deprecated package (now empty)\",\n  version: \"1.0.10\"\n});\n\nPackage.onUse(function (api) {\n  api.addFiles('deprecated.js', 'server');\n});\n"
  },
  {
    "path": "packages/promise/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/promise/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/promise/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"meteor-promise\": {\n      \"version\": \"0.7.2\",\n      \"from\": \"meteor-promise@0.7.2\"\n    },\n    \"promise\": {\n      \"version\": \"7.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/promise/-/promise-7.1.1.tgz\",\n      \"from\": \"promise@7.1.1\",\n      \"dependencies\": {\n        \"asap\": {\n          \"version\": \"2.0.3\",\n          \"resolved\": \"https://registry.npmjs.org/asap/-/asap-2.0.3.tgz\",\n          \"from\": \"asap@>=2.0.3 <2.1.0\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/promise/README.md",
    "content": "# promise [![Build Status](https://travis-ci.org/meteor/promise.svg)](https://travis-ci.org/meteor/promise)\nECMAScript 2015 Promise polyfill with Fiber support\n\nThe static methods `Promise.async` and `Promise.await` implement the\nrelaxed `async` and `await` functions proposed in this talk: [Why Fibers\nMake Sense For Meteor](http://benjamn.github.io/goto2015-talk).\n"
  },
  {
    "path": "packages/promise/client.js",
    "content": "require(\"meteor-promise\").makeCompatible(\n  exports.Promise = require(\"./common.js\").Promise\n);\n"
  },
  {
    "path": "packages/promise/common.js",
    "content": "var global = this;\n\nif (typeof global.Promise === \"function\") {\n  exports.Promise = global.Promise;\n} else {\n  exports.Promise = require(\"promise/lib/es6-extensions\");\n}\n\nexports.Promise.prototype.done = function (onFulfilled, onRejected) {\n  var self = this;\n\n  if (arguments.length > 0) {\n    self = this.then.apply(this, arguments);\n  }\n\n  self.then(null, function (err) {\n    Meteor._setImmediate(function () {\n      throw err;\n    });\n  });\n};\n"
  },
  {
    "path": "packages/promise/package.js",
    "content": "Package.describe({\n  name: \"promise\",\n  version: \"0.7.2_1\",\n  summary: \"ECMAScript 2015 Promise polyfill with Fiber support\",\n  git: \"https://github.com/meteor/promise\",\n  documentation: \"README.md\"\n});\n\nNpm.depends({\n  \"meteor-promise\": \"0.7.2\",\n  \"promise\": \"7.1.1\"\n});\n\nPackage.onUse(function(api) {\n  api.use(\"modules\");\n  api.mainModule(\"client.js\", \"client\");\n  api.mainModule(\"server.js\", \"server\");\n  api.export(\"Promise\");\n});\n\nPackage.onTest(function(api) {\n  api.use(\"modules\");\n  api.use(\"tinytest\");\n  api.use(\"promise\");\n  api.addFiles(\"promise-tests.js\");\n});\n"
  },
  {
    "path": "packages/promise/promise-tests.js",
    "content": "Tinytest.addAsync(\"meteor-promise - sanity\", function (test, done) {\n  var expectedError = new Error(\"expected\");\n  Promise.resolve(\"working\").then(function (result) {\n    test.equal(result, \"working\");\n    throw expectedError;\n  }).catch(function (error) {\n    test.equal(error, expectedError);\n    if (Meteor.isServer) {\n      var Fiber = require(\"fibers\");\n      // Make sure the Promise polyfill runs callbacks in a Fiber.\n      test.instanceOf(Fiber.current, Fiber);\n    }\n  }).then(done, function (error) {\n    test.exception(error);\n  });\n});\n"
  },
  {
    "path": "packages/promise/server.js",
    "content": "require(\"meteor-promise\").makeCompatible(\n  exports.Promise = require(\"./common.js\").Promise,\n  // Allow every Promise callback to run in a Fiber drawn from a pool of\n  // reusable Fibers.\n  require(\"fibers\")\n);\n"
  },
  {
    "path": "packages/random/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/random/README.md",
    "content": "# random\n\nThe `random` package provides several functions for generating random\nnumbers. It uses a cryptographically strong pseudorandom number generator when\npossible, but falls back to a weaker random number generator when\ncryptographically strong randomness is not available (on older browsers or on\nservers that don't have enough entropy to seed the cryptographically strong\ngenerator).\n\n- `Random.id([n])` - Returns a unique identifier, such as `\"Jjwjg6gouWLXhMGKW\"`, that is\nlikely to be unique in the whole world. The optional argument `n`\nspecifies the length of the identifier in characters and defaults to 17.\n\n- `Random.secret([n])` - Returns a random string of printable characters with 6 bits of\nentropy per character. The optional argument `n` specifies the length of\nthe secret string and defaults to 43 characters, or 256 bits of\nentropy. Use `Random.secret` for security-critical secrets that are\nintended for machine, rather than human, consumption.\n\n- `Random.fraction()` - Returns a number between 0 and 1, like `Math.random`.\n\n- `Random.choice(arrayOrString)` - Returns a random element of the given array or string.\n\n- `Random.hexString(n)` - Returns a random string of `n` hexadecimal digits."
  },
  {
    "path": "packages/random/deprecated.js",
    "content": "// Before this package existed, we used to use this Meteor.uuid()\n// implementing the RFC 4122 v4 UUID. It is no longer documented\n// and will go away.\n// XXX COMPAT WITH 0.5.6\nMeteor.uuid = function () {\n  var HEX_DIGITS = \"0123456789abcdef\";\n  var s = [];\n  for (var i = 0; i < 36; i++) {\n    s[i] = Random.choice(HEX_DIGITS);\n  }\n  s[14] = \"4\";\n  s[19] = HEX_DIGITS.substr((parseInt(s[19],16) & 0x3) | 0x8, 1);\n  s[8] = s[13] = s[18] = s[23] = \"-\";\n\n  var uuid = s.join(\"\");\n  return uuid;\n};\n"
  },
  {
    "path": "packages/random/package.js",
    "content": "Package.describe({\n  summary: \"Random number generator and utilities\",\n  version: '1.0.10'\n});\n\nPackage.onUse(function (api) {\n  api.use('underscore');\n  api.use('ecmascript');\n  api.export('Random');\n  api.addFiles('random.js');\n  api.addFiles('deprecated.js');\n});\n\nPackage.onTest(function(api) {\n  api.use('random');\n  api.use('ecmascript');\n  api.use('tinytest');\n  api.addFiles('random_tests.js', ['client', 'server']);\n});\n"
  },
  {
    "path": "packages/random/random.js",
    "content": "// We use cryptographically strong PRNGs (crypto.getRandomBytes() on the server,\n// window.crypto.getRandomValues() in the browser) when available. If these\n// PRNGs fail, we fall back to the Alea PRNG, which is not cryptographically\n// strong, and we seed it with various sources such as the date, Math.random,\n// and window size on the client.  When using crypto.getRandomValues(), our\n// primitive is hexString(), from which we construct fraction(). When using\n// window.crypto.getRandomValues() or alea, the primitive is fraction and we use\n// that to construct hex string.\n\nif (Meteor.isServer)\n  var nodeCrypto = Npm.require('crypto');\n\n// see http://baagoe.org/en/wiki/Better_random_numbers_for_javascript\n// for a full discussion and Alea implementation.\nvar Alea = function () {\n  function Mash() {\n    var n = 0xefc8249d;\n\n    var mash = function(data) {\n      data = data.toString();\n      for (var i = 0; i < data.length; i++) {\n        n += data.charCodeAt(i);\n        var h = 0.02519603282416938 * n;\n        n = h >>> 0;\n        h -= n;\n        h *= n;\n        n = h >>> 0;\n        h -= n;\n        n += h * 0x100000000; // 2^32\n      }\n      return (n >>> 0) * 2.3283064365386963e-10; // 2^-32\n    };\n\n    mash.version = 'Mash 0.9';\n    return mash;\n  }\n\n  return (function (args) {\n    var s0 = 0;\n    var s1 = 0;\n    var s2 = 0;\n    var c = 1;\n\n    if (args.length == 0) {\n      args = [+new Date];\n    }\n    var mash = Mash();\n    s0 = mash(' ');\n    s1 = mash(' ');\n    s2 = mash(' ');\n\n    for (var i = 0; i < args.length; i++) {\n      s0 -= mash(args[i]);\n      if (s0 < 0) {\n        s0 += 1;\n      }\n      s1 -= mash(args[i]);\n      if (s1 < 0) {\n        s1 += 1;\n      }\n      s2 -= mash(args[i]);\n      if (s2 < 0) {\n        s2 += 1;\n      }\n    }\n    mash = null;\n\n    var random = function() {\n      var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32\n      s0 = s1;\n      s1 = s2;\n      return s2 = t - (c = t | 0);\n    };\n    random.uint32 = function() {\n      return random() * 0x100000000; // 2^32\n    };\n    random.fract53 = function() {\n      return random() +\n        (random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53\n    };\n    random.version = 'Alea 0.9';\n    random.args = args;\n    return random;\n\n  } (Array.prototype.slice.call(arguments)));\n};\n\nvar UNMISTAKABLE_CHARS = \"23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz\";\nvar BASE64_CHARS = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\" +\n  \"0123456789-_\";\n\n// `type` is one of `RandomGenerator.Type` as defined below.\n//\n// options:\n// - seeds: (required, only for RandomGenerator.Type.ALEA) an array\n//   whose items will be `toString`ed and used as the seed to the Alea\n//   algorithm\nvar RandomGenerator = function (type, options) {\n  var self = this;\n  self.type = type;\n\n  if (!RandomGenerator.Type[type]) {\n    throw new Error(\"Unknown random generator type: \" + type);\n  }\n\n  if (type === RandomGenerator.Type.ALEA) {\n    if (!options.seeds) {\n      throw new Error(\"No seeds were provided for Alea PRNG\");\n    }\n    self.alea = Alea.apply(null, options.seeds);\n  }\n};\n\n// Types of PRNGs supported by the `RandomGenerator` class\nRandomGenerator.Type = {\n  // Use Node's built-in `crypto.getRandomBytes` (cryptographically\n  // secure but not seedable, runs only on the server). Reverts to\n  // `crypto.getPseudoRandomBytes` in the extremely uncommon case that\n  // there isn't enough entropy yet\n  NODE_CRYPTO: \"NODE_CRYPTO\",\n\n  // Use non-IE browser's built-in `window.crypto.getRandomValues`\n  // (cryptographically secure but not seedable, runs only in the\n  // browser).\n  BROWSER_CRYPTO: \"BROWSER_CRYPTO\",\n\n  // Use the *fast*, seedaable and not cryptographically secure\n  // Alea algorithm\n  ALEA: \"ALEA\",\n};\n\n/**\n * @name Random.fraction\n * @summary Return a number between 0 and 1, like `Math.random`.\n * @locus Anywhere\n */\nRandomGenerator.prototype.fraction = function () {\n  var self = this;\n  if (self.type === RandomGenerator.Type.ALEA) {\n    return self.alea();\n  } else if (self.type === RandomGenerator.Type.NODE_CRYPTO) {\n    var numerator = parseInt(self.hexString(8), 16);\n    return numerator * 2.3283064365386963e-10; // 2^-32\n  } else if (self.type === RandomGenerator.Type.BROWSER_CRYPTO) {\n    var array = new Uint32Array(1);\n    window.crypto.getRandomValues(array);\n    return array[0] * 2.3283064365386963e-10; // 2^-32\n  } else {\n    throw new Error('Unknown random generator type: ' + self.type);\n  }\n};\n\n/**\n * @name Random.hexString\n * @summary Return a random string of `n` hexadecimal digits.\n * @locus Anywhere\n * @param {Number} n Length of the string\n */\nRandomGenerator.prototype.hexString = function (digits) {\n  var self = this;\n  if (self.type === RandomGenerator.Type.NODE_CRYPTO) {\n    var numBytes = Math.ceil(digits / 2);\n    var bytes;\n    // Try to get cryptographically strong randomness. Fall back to\n    // non-cryptographically strong if not available.\n    try {\n      bytes = nodeCrypto.randomBytes(numBytes);\n    } catch (e) {\n      // XXX should re-throw any error except insufficient entropy\n      bytes = nodeCrypto.pseudoRandomBytes(numBytes);\n    }\n    var result = bytes.toString(\"hex\");\n    // If the number of digits is odd, we'll have generated an extra 4 bits\n    // of randomness, so we need to trim the last digit.\n    return result.substring(0, digits);\n  } else {\n    return this._randomString(digits, \"0123456789abcdef\");\n  }\n};\n\nRandomGenerator.prototype._randomString = function (charsCount,\n                                                    alphabet) {\n  var self = this;\n  var digits = [];\n  for (var i = 0; i < charsCount; i++) {\n    digits[i] = self.choice(alphabet);\n  }\n  return digits.join(\"\");\n};\n\n/**\n * @name Random.id\n * @summary Return a unique identifier, such as `\"Jjwjg6gouWLXhMGKW\"`, that is\n * likely to be unique in the whole world.\n * @locus Anywhere\n * @param {Number} [n] Optional length of the identifier in characters\n *   (defaults to 17)\n */\nRandomGenerator.prototype.id = function (charsCount) {\n  var self = this;\n  // 17 characters is around 96 bits of entropy, which is the amount of\n  // state in the Alea PRNG.\n  if (charsCount === undefined)\n    charsCount = 17;\n\n  return self._randomString(charsCount, UNMISTAKABLE_CHARS);\n};\n\n/**\n * @name Random.secret\n * @summary Return a random string of printable characters with 6 bits of\n * entropy per character. Use `Random.secret` for security-critical secrets\n * that are intended for machine, rather than human, consumption.\n * @locus Anywhere\n * @param {Number} [n] Optional length of the secret string (defaults to 43\n *   characters, or 256 bits of entropy)\n */\nRandomGenerator.prototype.secret = function (charsCount) {\n  var self = this;\n  // Default to 256 bits of entropy, or 43 characters at 6 bits per\n  // character.\n  if (charsCount === undefined)\n    charsCount = 43;\n  return self._randomString(charsCount, BASE64_CHARS);\n};\n\n/**\n * @name Random.choice\n * @summary Return a random element of the given array or string.\n * @locus Anywhere\n * @param {Array|String} arrayOrString Array or string to choose from\n */\nRandomGenerator.prototype.choice = function (arrayOrString) {\n  var index = Math.floor(this.fraction() * arrayOrString.length);\n  if (typeof arrayOrString === \"string\")\n    return arrayOrString.substr(index, 1);\n  else\n    return arrayOrString[index];\n};\n\n// instantiate RNG.  Heuristically collect entropy from various sources when a\n// cryptographic PRNG isn't available.\n\n// client sources\nvar height = (typeof window !== 'undefined' && window.innerHeight) ||\n      (typeof document !== 'undefined'\n       && document.documentElement\n       && document.documentElement.clientHeight) ||\n      (typeof document !== 'undefined'\n       && document.body\n       && document.body.clientHeight) ||\n      1;\n\nvar width = (typeof window !== 'undefined' && window.innerWidth) ||\n      (typeof document !== 'undefined'\n       && document.documentElement\n       && document.documentElement.clientWidth) ||\n      (typeof document !== 'undefined'\n       && document.body\n       && document.body.clientWidth) ||\n      1;\n\nvar agent = (typeof navigator !== 'undefined' && navigator.userAgent) || \"\";\n\nfunction createAleaGeneratorWithGeneratedSeed() {\n  return new RandomGenerator(\n    RandomGenerator.Type.ALEA,\n    {seeds: [new Date, height, width, agent, Math.random()]});\n};\n\nif (Meteor.isServer) {\n  Random = new RandomGenerator(RandomGenerator.Type.NODE_CRYPTO);\n} else {\n  if (typeof window !== \"undefined\" && window.crypto &&\n      window.crypto.getRandomValues) {\n    Random = new RandomGenerator(RandomGenerator.Type.BROWSER_CRYPTO);\n  } else {\n    // On IE 10 and below, there's no browser crypto API\n    // available. Fall back to Alea\n    //\n    // XXX looks like at the moment, we use Alea in IE 11 as well,\n    // which has `window.msCrypto` instead of `window.crypto`.\n    Random = createAleaGeneratorWithGeneratedSeed();\n  }\n}\n\n// Create a non-cryptographically secure PRNG with a given seed (using\n// the Alea algorithm)\nRandom.createWithSeeds = function (...seeds) {\n  if (seeds.length === 0) {\n    throw new Error(\"No seeds were provided\");\n  }\n  return new RandomGenerator(RandomGenerator.Type.ALEA, {seeds: seeds});\n};\n\n// Used like `Random`, but much faster and not cryptographically\n// secure\nRandom.insecure = createAleaGeneratorWithGeneratedSeed();\n"
  },
  {
    "path": "packages/random/random_tests.js",
    "content": "Tinytest.add('random', function (test) {\n  // Deterministic with a specified seed, which should generate the\n  // same sequence in all environments.\n  //\n  // For repeatable unit test failures using deterministic random\n  // number sequences it's fine if a new Meteor release changes the\n  // algorithm being used and it starts generating a different\n  // sequence for a seed, as long as the sequence is consistent for\n  // a particular release.\n  var random = Random.createWithSeeds(0);\n  test.equal(random.id(), \"cp9hWvhg8GSvuZ9os\");\n  test.equal(random.id(), \"3f3k6Xo7rrHCifQhR\");\n  test.equal(random.id(), \"shxDnjWWmnKPEoLhM\");\n  test.equal(random.id(), \"6QTjB8C5SEqhmz4ni\");\n});\n\n// node crypto and window.crypto.getRandomValues() don't let us specify a seed,\n// but at least test that the output is in the right format.\nTinytest.add('random - format', function (test) {\n  var idLen = 17;\n  test.equal(Random.id().length, idLen);\n  test.equal(Random.id(29).length, 29);\n  var numDigits = 9;\n  var hexStr = Random.hexString(numDigits);\n  test.equal(hexStr.length, numDigits);\n  parseInt(hexStr, 16); // should not throw\n  var frac = Random.fraction();\n  test.isTrue(frac < 1.0);\n  test.isTrue(frac >= 0.0);\n\n  test.equal(Random.secret().length, 43);\n  test.equal(Random.secret(13).length, 13);\n});\n\nTinytest.add('random - Alea is last resort', function (test) {\n  if (Meteor.isServer) {\n    test.isTrue(Random.alea === undefined);\n  }\n  if (Meteor.isClient) {\n    var useGetRandomValues = !!(typeof window !== \"undefined\" &&\n        window.crypto && window.crypto.getRandomValues);\n    test.equal(Random.alea === undefined, useGetRandomValues);\n  }\n});\n\nTinytest.add('random - createWithSeeds requires parameters', function (test) {\n  test.throws(function () {\n    Random.createWithSeeds();\n  });\n});\n"
  },
  {
    "path": "packages/rate-limit/README.md",
    "content": "# Rate Limit\n===\nA Rate Limiter is a general rate limiting object that stores rules and\ndetermines whether inputs are allowed based on the rules. There is also a\ngeneral structure of Rules which contain all the internal state of a rule.\n\nRate limiters analyze a series of \"inputs\" (which are POJOs) by running them\nagainst a set of \"rules.\" Rules specify which inputs they match by running\nconfigurable \"matcher\" functions on keys in the input object. A `check` method\nreturns whether this input should be allowed, the time until the rate limit is\nreset and the number of calls remaining for this input. The count of processed\ninputs are kept in a dictionary of counters stored inside each rule, keyed by\na unique string composed of the input that matched to the rule.\n\n### Rule Structure\n\nEach rule is composed of an `id`, an options object that contains the `\nintervalTime` in milliseconds after which the rule is reset and\n`numRequestsAllowed` in the specified interval time, a dictionary of `matchers`\nwhose keys are searched for in the input to determine if there is a match. If\nthe values match, then the rule's counters are incremented. Values can be\nobjects or they can be functions that return a boolean of whether the\nprovided input matches. For example, if we only want to match all even ids,\nplus any other fields, we could have a rule that included a key-value pair as\nfollows:\n\n```javascript\n{\n  ...\n  id: function (id) {\n    return id % 2 === 0;\n  },\n  ...\n}\n```\nA rule is only said to apply to a given input if every key in the matcher\nmatches to the input values. There is also a dictionary of `counters` that\nstore the current state of inputs and number of times they've been passed to\nthe rate limiter. Each rule defines a domain of keys and values that it\napplies to, and we want to have a unique way of recording each input provided\nto the Rate Limiter that matches to the rule. Say a rule inspects a methodName\nproperty and a username property. We want to count how many times each user\ncalled a certain method and restrict them to a certain number of calls per\nuser defined time frame. So we generate a unique string key (to be used as\nkeys in a counters object) to represent each specific methodName + user\ncombination. Since this rule applies to multiple user, we need to concatenate\nthe differnet input key names with their values. For example, if we had a rule\nwith matchers as such:\n\n```javascript\n{\n  username: function(username)  {\n    return true;\n  },\n  methodName: 'hello'\n}\n```\nand we were passed an input as follows:\n\n```\n{\n  username: 'meteor'\n  methodName: 'hello'\n}\n```\nThe key generated would be 'usernamemeteormethodNamehello'. This is guaranteed\nto be unique for this username+methodName combination. These keys are cleared\nevery time the intervalTime is passed, at which point we delete the current\ndictionary of counters we store. Every time a rule matches to an input, we\ndetermine the unique key string and check if it's counters have exceeded the\nallowed amounts, returning an error to the user letting them know that a rate\nlimit has been reached."
  },
  {
    "path": "packages/rate-limit/package.js",
    "content": "Package.describe({\n  name: 'rate-limit',\n  version: '1.0.5',\n  // Brief, one-line summary of the package.\n  summary: 'An algorithm for rate limiting anything',\n  // URL to the Git repository containing the source code for this package.\n  git: '',\n  // By default, Meteor will default to using README.md for documentation.\n  // To avoid submitting documentation, set this field to null.\n  documentation: 'README.md'\n});\n\nPackage.onUse(function(api) {\n  api.use('underscore');\n  api.use('random');\n  api.addFiles('rate-limit.js');\n  api.export(\"RateLimiter\");\n});\n\nPackage.onTest(function(api) {\n  api.use('test-helpers', ['client', 'server']);\n  api.use('underscore');\n  api.use('random');\n  api.use('ddp-rate-limiter');\n  api.use('tinytest');\n  api.use('rate-limit');\n  api.use('ddp-common');\n  api.addFiles('rate-limit-tests.js');\n});\n"
  },
  {
    "path": "packages/rate-limit/rate-limit-tests.js",
    "content": "// These tests were written before rate-limit was factored outside of DDP Rate\n// Limiter and thus are structured with DDP method invocations in mind. These\n// rules still test abstract rate limit package behavior. The tests currently\n// implemented are:\n// * Empty rule set on RateLimiter construction\n// * Multiple inputs, only 1 that matches rule and reaches rate limit\n// * Multiple inputs, 1 hits rate limit, wait for reset, after which inputs\n//   allowed\n// * 2 rules, 3 inputs where 2/3 match 1 rule and thus hit rate limit. Second\n//   input matches another rule and hits rate limit while 3rd rule not rate\n//   limited\n// * One rule affected by two inputs still throws\n// * Global rule triggers on any invocation after reaching limit\n// * Fuzzy rule matching triggers rate limit only when input has more keys than\n//   rule\n// * matchRule tests that have various levels of similarity in input and rule\n// * generateKeyString tests for various matches creating appropriate string\n//\n// XXX These tests should be refactored to use Tinytest.add instead of\n// testAsyncMulti as they're all on the server. Any future tests should be\n// written that way.\nTinytest.add('rate limit tests - Check empty constructor creation',\n  function (test) {\n    r = new RateLimiter();\n    test.equal(r.rules, {});\n});\n\nTinytest.add('rate limit tests - Check single rule with multiple ' +\n  'invocations, only 1 that matches',\n  function (test) {\n    r = new RateLimiter();\n    var userIdOne = 1;\n    var restrictJustUserIdOneRule = {\n      userId: userIdOne,\n      IPAddr: null,\n      method: null\n    };\n\n    r.addRule(restrictJustUserIdOneRule, 1, 1000);\n    var connectionHandle = createTempConnectionHandle(123, '127.0.0.1');\n    var methodInvc1 = createTempMethodInvocation(userIdOne, connectionHandle,\n      'login');\n    var methodInvc2 = createTempMethodInvocation(2, connectionHandle,\n      'login');\n    for (var i = 0; i < 2; i++) {\n      r.increment(methodInvc1);\n      r.increment(methodInvc2);\n    }\n    test.equal(r.check(methodInvc1).allowed, false);\n    test.equal(r.check(methodInvc2).allowed, true);\n  });\n\ntestAsyncMulti(\"rate limit tests - Run multiple invocations and wait for one\" +\n  \" to reset\", [\n  function (test, expect) {\n    var self = this;\n    self.r = new RateLimiter();\n    self.userIdOne = 1;\n    self.userIdTwo = 2;\n    self.restrictJustUserIdOneRule = {\n      userId: self.userIdOne,\n      IPAddr: null,\n      method: null\n    };\n    self.r.addRule(self.restrictJustUserIdOneRule, 1, 1000);\n    self.connectionHandle = createTempConnectionHandle(123, '127.0.0.1')\n    self.methodInvc1 = createTempMethodInvocation(self.userIdOne,\n      self.connectionHandle, 'login');\n    self.methodInvc2 = createTempMethodInvocation(self.userIdTwo,\n      self.connectionHandle, 'login');\n    for (var i = 0; i < 2; i++) {\n      self.r.increment(self.methodInvc1);\n      self.r.increment(self.methodInvc2);\n    }\n    test.equal(self.r.check(self.methodInvc1).allowed, false);\n    test.equal(self.r.check(self.methodInvc2).allowed, true);\n    Meteor.setTimeout(expect(function () {}), 1000);\n  },\n  function (test, expect) {\n    var self = this;\n    for (var i = 0; i < 100; i++) {\n      self.r.increment(self.methodInvc2);\n    }\n\n    test.equal(self.r.check(self.methodInvc1).allowed, true);\n    test.equal(self.r.check(self.methodInvc2).allowed, true);\n  }\n]);\n\nTinytest.add('rate limit tests - Check two rules that affect same methodInvc' +\n  ' still throw',\n  function (test) {\n    r = new RateLimiter();\n    var loginMethodRule = {\n      userId: null,\n      IPAddr: null,\n      method: 'login'\n    };\n    var onlyLimitEvenUserIdRule = {\n      userId: function (userId) {\n        return userId % 2 === 0\n      },\n      IPAddr: null,\n      method: null\n    };\n    r.addRule(loginMethodRule, 10, 100);\n    r.addRule(onlyLimitEvenUserIdRule, 4, 100);\n\n    var connectionHandle = createTempConnectionHandle(1234, '127.0.0.1');\n    var methodInvc1 = createTempMethodInvocation(1, connectionHandle,\n      'login');\n    var methodInvc2 = createTempMethodInvocation(2, connectionHandle,\n      'login');\n    var methodInvc3 = createTempMethodInvocation(3, connectionHandle,\n      'test');\n\n    for (var i = 0; i < 5; i++) {\n      r.increment(methodInvc1);\n      r.increment(methodInvc2);\n      r.increment(methodInvc3);\n    };\n\n    // After for loop runs, we only have 10 runs, so that's under the limit\n    test.equal(r.check(methodInvc1).allowed, true);\n    // However, this triggers userId rule since this userId is even\n    test.equal(r.check(methodInvc2).allowed, false);\n    test.equal(r.check(methodInvc2).allowed, false);\n\n    // Running one more test causes it to be false, since we're at 11 now.\n    r.increment(methodInvc1);\n    test.equal(r.check(methodInvc1).allowed, false);\n    // 3rd Method Invocation isn't affected by either rules.\n    test.equal(r.check(methodInvc3).allowed, true);\n\n  });\n\nTinytest.add('rate limit tests - Check one rule affected by two different ' +\n  'invocations',\n  function (test) {\n    r = new RateLimiter();\n    var loginMethodRule = {\n      userId: null,\n      IPAddr: null,\n      method: 'login'\n    }\n    r.addRule(loginMethodRule, 10, 10000);\n\n    var connectionHandle = createTempConnectionHandle(1234, '127.0.0.1');\n    var methodInvc1 = createTempMethodInvocation(1, connectionHandle,\n      'login');\n    var methodInvc2 = createTempMethodInvocation(2, connectionHandle,\n      'login');\n\n    for (var i = 0; i < 5; i++) {\n      r.increment(methodInvc1);\n      r.increment(methodInvc2);\n    }\n    // This throws us over the limit since both increment the login rule\n    // counter\n    r.increment(methodInvc1);\n\n    test.equal(r.check(methodInvc1).allowed, false);\n    test.equal(r.check(methodInvc2).allowed, false);\n  });\n\nTinytest.add(\"rate limit tests - add global rule\", function (test) {\n  r = new RateLimiter();\n  var globalRule = {\n    userId: null,\n    IPAddr: null,\n    method: null\n  }\n  r.addRule(globalRule, 1, 10000);\n\n  var connectionHandle = createTempConnectionHandle(1234, '127.0.0.1');\n  var connectionHandle2 = createTempConnectionHandle(1234, '127.0.0.2');\n\n  var methodInvc1 = createTempMethodInvocation(1, connectionHandle,\n    'login');\n  var methodInvc2 = createTempMethodInvocation(2, connectionHandle2,\n    'test');\n  var methodInvc3 = createTempMethodInvocation(3, connectionHandle,\n    'user-accounts');\n\n  // First invocation, all methods would still be allowed.\n  r.increment(methodInvc2);\n  test.equal(r.check(methodInvc1).allowed, true);\n  test.equal(r.check(methodInvc2).allowed, true);\n  test.equal(r.check(methodInvc3).allowed, true);\n  // Second invocation, everything has reached common rate limit\n  r.increment(methodInvc3);\n  test.equal(r.check(methodInvc1).allowed, false);\n  test.equal(r.check(methodInvc2).allowed, false);\n  test.equal(r.check(methodInvc3).allowed, false);\n});\n\nTinytest.add('rate limit tests - Fuzzy rule match does not trigger rate limit',\n  function (test) {\n    r = new RateLimiter();\n    var rule = {\n      a: function (inp) {\n        return inp % 3 == 0\n      },\n      b: 5,\n      c: \"hi\",\n    }\n    r.addRule(rule, 1, 10000);\n    var input = {\n      a: 3,\n      b: 5\n    }\n    for (var i = 0; i < 5; i++) {\n      r.increment(input);\n    }\n    test.equal(r.check(input).allowed, true);\n    var matchingInput = {\n      a: 3,\n      b: 5,\n      c: \"hi\",\n      d: 1\n    }\n    r.increment(matchingInput);\n    r.increment(matchingInput);\n    // Past limit so should be false\n    test.equal(r.check(matchingInput).allowed, false);\n\n    // Add secondary rule and check that longer time is returned when multiple\n    // rules limits are hit\n    var newRule = {\n      a: function (inp) {\n        return inp % 3 == 0\n      },\n      b: 5,\n      c: \"hi\",\n      d: 1\n    }\n    r.addRule(newRule, 1, 10);\n    // First rule should still throw while second rule will trigger as well,\n    // causing us to return longer time to reset to user\n    r.increment(matchingInput);\n    r.increment(matchingInput);\n    test.equal(r.check(matchingInput).timeToReset > 50, true);\n  }\n);\n\n\n/****** Test Our Helper Methods *****/\n\nTinytest.add(\"rate limit tests - test matchRule method\", function (test) {\n  r = new RateLimiter();\n  var globalRule = {\n    userId: null,\n    IPAddr: null,\n    type: null,\n    name: null\n  }\n  var globalRuleId = r.addRule(globalRule);\n\n  var rateLimiterInput = {\n    userId: 1023,\n    IPAddr: \"127.0.0.1\",\n    type: 'sub',\n    name: 'getSubLists'\n  };\n\n  test.equal(r.rules[globalRuleId].match(rateLimiterInput), true);\n\n  var oneNotNullRule = {\n    userId: 102,\n    IPAddr: null,\n    type: null,\n    name: null\n  }\n\n  var oneNotNullId = r.addRule(oneNotNullRule);\n  test.equal(r.rules[oneNotNullId].match(rateLimiterInput), false);\n\n  oneNotNullRule.userId = 1023;\n  test.equal(r.rules[oneNotNullId].match(rateLimiterInput), true);\n\n  var notCompleteInput = {\n    userId: 102,\n    IPAddr: '127.0.0.1'\n  };\n  test.equal(r.rules[globalRuleId].match(notCompleteInput), true);\n  test.equal(r.rules[oneNotNullId].match(notCompleteInput), false);\n});\n\nTinytest.add('rate limit tests - test generateMethodKey string',\n  function (test) {\n    r = new RateLimiter();\n    var globalRule = {\n      userId: null,\n      IPAddr: null,\n      type: null,\n      name: null\n    }\n    var globalRuleId = r.addRule(globalRule);\n\n    var rateLimiterInput = {\n      userId: 1023,\n      IPAddr: \"127.0.0.1\",\n      type: 'sub',\n      name: 'getSubLists'\n    };\n\n    test.equal(r.rules[globalRuleId]._generateKeyString(rateLimiterInput), \"\");\n    globalRule.userId = 1023;\n\n    test.equal(r.rules[globalRuleId]._generateKeyString(rateLimiterInput),\n      \"userId1023\");\n\n    var ruleWithFuncs = {\n      userId: function (input) {\n        return input % 2 === 0\n      },\n      IPAddr: null,\n      type: null\n    };\n    var funcRuleId = r.addRule(ruleWithFuncs);\n    test.equal(r.rules[funcRuleId]._generateKeyString(rateLimiterInput), \"\");\n    rateLimiterInput.userId = 1024;\n    test.equal(r.rules[funcRuleId]._generateKeyString(rateLimiterInput),\n      \"userId1024\");\n\n    var multipleRules = ruleWithFuncs;\n    multipleRules.IPAddr = '127.0.0.1';\n    var multipleRuleId = r.addRule(multipleRules);\n    test.equal(r.rules[multipleRuleId]._generateKeyString(rateLimiterInput),\n      \"userId1024IPAddr127.0.0.1\")\n  }\n);\n\nfunction createTempConnectionHandle(id, clientIP) {\n  return {\n    id: id,\n    close: function () {\n      self.close();\n    },\n    onClose: function (fn) {\n      var cb = Meteor.bindEnvironment(fn, \"connection onClose callback\");\n      if (self.inQueue) {\n        self._closeCallbacks.push(cb);\n      } else {\n        // if we're already closed, call the callback.\n        Meteor.defer(cb);\n      }\n    },\n    clientAddress: clientIP,\n    httpHeaders: null\n  };\n}\n\nfunction createTempMethodInvocation(userId, connectionHandle, methodName) {\n  var methodInv = new DDPCommon.MethodInvocation({\n    isSimulation: false,\n    userId: userId,\n    setUserId: null,\n    unblock: false,\n    connection: connectionHandle,\n    randomSeed: 1234\n  });\n  methodInv.method = methodName;\n  return methodInv;\n}"
  },
  {
    "path": "packages/rate-limit/rate-limit.js",
    "content": "// Default time interval (in milliseconds) to reset rate limit counters\nvar DEFAULT_INTERVAL_TIME_IN_MILLISECONDS = 1000;\n// Default number of events allowed per time interval\nvar DEFAULT_REQUESTS_PER_INTERVAL = 10;\n\n// A rule is defined by an options object that contains two fields,\n// `numRequestsAllowed` which is the number of events allowed per interval, and\n// an `intervalTime` which is the amount of time in milliseconds before the\n// rate limit restarts its internal counters, and by a matchers object. A\n// matchers object is a POJO that contains a set of keys with values that\n// define the entire set of inputs that match for each key. The values can\n// either be null (optional), a primitive or a function that returns a boolean\n// of whether the provided input's value matches for this key.\n//\n// Rules are uniquely assigned an `id` and they store a dictionary of counters,\n// which are records used to keep track of inputs that match the rule. If a\n// counter reaches the `numRequestsAllowed` within a given `intervalTime`, a\n// rate limit is reached and future inputs that map to that counter will\n// result in errors being returned to the client.\nvar Rule = function (options, matchers) {\n  var self = this;\n\n  self.id = Random.id();\n\n  self.options = options;\n\n  self._matchers = matchers;\n\n  self._lastResetTime = new Date().getTime();\n\n  // Dictionary of input keys to counters\n  self.counters = {};\n};\n\n_.extend(Rule.prototype, {\n  // Determine if this rule applies to the given input by comparing all\n  // rule.matchers. If the match fails, search short circuits instead of\n  // iterating through all matchers.\n  match: function (input) {\n    var self = this;\n    var ruleMatches = true;\n    return _.every(self._matchers, function (matcher, key) {\n      if (matcher !== null) {\n        if (!(_.has(input,key))) {\n          return false;\n        } else {\n          if (typeof matcher === 'function') {\n            if (!(matcher(input[key]))) {\n              return false;\n            }\n          } else {\n            if (matcher !== input[key]) {\n              return false;\n            }\n          }\n        }\n      }\n      return true;\n    });\n  },\n\n  // Generates unique key string for provided input by concatenating all the\n  // keys in the matcher with the corresponding values in the input.\n  // Only called if rule matches input.\n  _generateKeyString: function (input) {\n    var self = this;\n    var returnString = \"\";\n    _.each(self._matchers, function (matcher, key) {\n      if (matcher !== null) {\n        if (typeof matcher === 'function') {\n          if (matcher(input[key])) {\n            returnString += key + input[key];\n          }\n        } else {\n          returnString += key + input[key];\n        }\n      }\n    });\n    return returnString;\n  },\n\n  // Applies the provided input and returns the key string, time since counters\n  // were last reset and time to next reset.\n  apply: function (input) {\n    var self = this;\n    var keyString = self._generateKeyString(input);\n    var timeSinceLastReset = new Date().getTime() - self._lastResetTime;\n    var timeToNextReset = self.options.intervalTime - timeSinceLastReset;\n    return {\n      key: keyString,\n      timeSinceLastReset: timeSinceLastReset,\n      timeToNextReset: timeToNextReset\n    };\n  },\n  // Reset counter dictionary for this specific rule. Called once the\n  // timeSinceLastReset has exceeded the intervalTime. _lastResetTime is\n  // set to be the current time in milliseconds.\n  resetCounter: function () {\n    var self = this;\n\n    // Delete the old counters dictionary to allow for garbage collection\n    self.counters = {};\n    self._lastResetTime = new Date().getTime();\n  }\n});\n\n// Initialize rules to be an empty dictionary.\nRateLimiter = function () {\n  var self = this;\n\n  // Dictionary of all rules associated with this RateLimiter, keyed by their\n  // id. Each rule object stores the rule pattern, number of events allowed,\n  // last reset time and the rule reset interval in milliseconds.\n  self.rules = {};\n};\n\n/**\n * Checks if this input has exceeded any rate limits.\n * @param  {object} input dictionary containing key-value pairs of attributes\n * that match to rules\n * @return {object} Returns object of following structure\n * { 'allowed': boolean - is this input allowed\n *   'timeToReset': integer | Infinity - returns time until counters are reset\n *                   in milliseconds\n *   'numInvocationsLeft': integer | Infinity - returns number of calls left\n *   before limit is reached\n * }\n * If multiple rules match, the least number of invocations left is returned.\n * If the rate limit has been reached, the longest timeToReset is returned.\n */\nRateLimiter.prototype.check = function (input) {\n  var self = this;\n  var reply = {\n    allowed: true,\n    timeToReset: 0,\n    numInvocationsLeft: Infinity\n  };\n\n  var matchedRules = self._findAllMatchingRules(input);\n  _.each(matchedRules, function (rule) {\n    var ruleResult = rule.apply(input);\n    var numInvocations = rule.counters[ruleResult.key];\n\n    if (ruleResult.timeToNextReset < 0) {\n      // Reset all the counters since the rule has reset\n      rule.resetCounter();\n      ruleResult.timeSinceLastReset = new Date().getTime() -\n        rule._lastResetTime;\n      ruleResult.timeToNextReset = rule.options.intervalTime;\n      numInvocations = 0;\n    }\n\n    if (numInvocations > rule.options.numRequestsAllowed) {\n      // Only update timeToReset if the new time would be longer than the\n      // previously set time. This is to ensure that if this input triggers\n      // multiple rules, we return the longest period of time until they can\n      // successfully make another call\n      if (reply.timeToReset < ruleResult.timeToNextReset) {\n        reply.timeToReset = ruleResult.timeToNextReset;\n      };\n      reply.allowed = false;\n      reply.numInvocationsLeft = 0;\n    } else {\n      // If this is an allowed attempt and we haven't failed on any of the\n      // other rules that match, update the reply field.\n      if (rule.options.numRequestsAllowed - numInvocations <\n        reply.numInvocationsLeft && reply.allowed) {\n        reply.timeToReset = ruleResult.timeToNextReset;\n        reply.numInvocationsLeft = rule.options.numRequestsAllowed -\n          numInvocations;\n      }\n    }\n  });\n  return reply;\n};\n\n/**\n * Adds a rule to dictionary of rules that are checked against on every call.\n * Only inputs that pass all of the rules will be allowed. Returns unique rule\n * id that can be passed to `removeRule`.\n * @param {object} rule    Input dictionary defining certain attributes and\n * rules associated with them.\n * Each attribute's value can either be a value, a function or null. All\n * functions must return a boolean of whether the input is matched by that\n * attribute's rule or not\n * @param {integer} numRequestsAllowed Optional. Number of events allowed per\n * interval. Default = 10.\n * @param {integer} intervalTime Optional. Number of milliseconds before\n * rule's counters are reset. Default = 1000.\n * @return {string} Returns unique rule id\n */\nRateLimiter.prototype.addRule = function (rule, numRequestsAllowed,\n  intervalTime) {\n  var self = this;\n\n  var options = {\n    numRequestsAllowed: numRequestsAllowed || DEFAULT_REQUESTS_PER_INTERVAL,\n    intervalTime: intervalTime || DEFAULT_INTERVAL_TIME_IN_MILLISECONDS\n  };\n\n  var newRule = new Rule(options, rule);\n  this.rules[newRule.id] = newRule;\n  return newRule.id;\n};\n\n/**\n * Increment counters in every rule that match to this input\n * @param  {object} input Dictionary object containing attributes that may\n * match to rules\n */\nRateLimiter.prototype.increment = function (input) {\n  var self = this;\n\n  // Only increment rule counters that match this input\n  var matchedRules = self._findAllMatchingRules(input);\n  _.each(matchedRules, function (rule) {\n    var ruleResult = rule.apply(input);\n\n    if (ruleResult.timeSinceLastReset > rule.options.intervalTime) {\n      // Reset all the counters since the rule has reset\n      rule.resetCounter();\n    }\n\n    // Check whether the key exists, incrementing it if so or otherwise\n    // adding the key and setting its value to 1\n    if (_.has(rule.counters, ruleResult.key))\n      rule.counters[ruleResult.key]++;\n    else\n      rule.counters[ruleResult.key] = 1;\n  });\n};\n\n// Returns an array of all rules that apply to provided input\nRateLimiter.prototype._findAllMatchingRules = function (input) {\n  var self = this;\n\n  return _.filter(self.rules, function(rule) {\n    return rule.match(input);\n  });\n};\n/**\n * Provides a mechanism to remove rules from the rate limiter. Returns boolean\n * about success.\n * @param  {string} id Rule id returned from #addRule\n * @return {boolean} Returns true if rule was found and deleted, else false.\n */\nRateLimiter.prototype.removeRule = function (id) {\n  var self = this;\n  if (self.rules[id]) {\n    delete self.rules[id];\n    return true;\n  } else {\n    return false;\n  }\n};\n"
  },
  {
    "path": "packages/reactive-dict/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/reactive-dict/README.md",
    "content": "# reactive-dict\n\nThis package provide `ReactiveDict`, a general-purpose reactive\ndatatype for use with\n[tracker](https://atmospherejs.com/meteor/tracker). It provides all of\nthe functionality of the `Session` object documented in the [main\nMeteor docs](https://docs.meteor.com/#session), such as reactive\n`get`, `set`, and `equals` functions.\n\nIf you provide a name to its constructor, its contents will be saved across Hot\nCode Push client code updates.\n\nExample usage:\n\n```js\nvar dict = new ReactiveDict('myDict');\ndict.set(\"weather\", \"cloudy\");\nTracker.autorun(function () { console.log(\"now \" + dict.get(\"weather\")); });\n// now cloudy\ndict.set(\"weather\", \"sunny\");\n// now sunny\n```\n\nFor more information, see the [Tracker project\npage](https://www.meteor.com/tracker).\n\n## Future work\n\nUnify with [reactive-var](https://atmospherejs.com/meteor/reactive-var).\n"
  },
  {
    "path": "packages/reactive-dict/migration.js",
    "content": "ReactiveDict._migratedDictData = {}; // name -> data\nReactiveDict._dictsToMigrate = {}; // name -> ReactiveDict\n\nReactiveDict._loadMigratedDict = function (dictName) {\n  if (_.has(ReactiveDict._migratedDictData, dictName))\n    return ReactiveDict._migratedDictData[dictName];\n\n  return null;\n};\n\nReactiveDict._registerDictForMigrate = function (dictName, dict) {\n  if (_.has(ReactiveDict._dictsToMigrate, dictName))\n    throw new Error(\"Duplicate ReactiveDict name: \" + dictName);\n\n  ReactiveDict._dictsToMigrate[dictName] = dict;\n};\n\nif (Meteor.isClient && Package.reload) {\n  // Put old migrated data into ReactiveDict._migratedDictData,\n  // where it can be accessed by ReactiveDict._loadMigratedDict.\n  var migrationData = Package.reload.Reload._migrationData('reactive-dict');\n  if (migrationData && migrationData.dicts)\n    ReactiveDict._migratedDictData = migrationData.dicts;\n\n  // On migration, assemble the data from all the dicts that have been\n  // registered.\n  Package.reload.Reload._onMigrate('reactive-dict', function () {\n    var dictsToMigrate = ReactiveDict._dictsToMigrate;\n    var dataToMigrate = {};\n\n    for (var dictName in dictsToMigrate)\n      dataToMigrate[dictName] = dictsToMigrate[dictName]._getMigrationData();\n\n    return [true, {dicts: dataToMigrate}];\n  });\n}\n"
  },
  {
    "path": "packages/reactive-dict/package.js",
    "content": "Package.describe({\n  summary: \"Reactive dictionary\",\n  version: '1.1.8'\n});\n\nPackage.onUse(function (api) {\n  api.use(['underscore', 'tracker', 'ejson', 'ecmascript']);\n  // If we are loading mongo-livedata, let you store ObjectIDs in it.\n  api.use('mongo', {weak: true});\n  api.export('ReactiveDict');\n  api.addFiles('reactive-dict.js');\n  api.addFiles('migration.js');\n});\n\nPackage.onTest(function (api) {\n  api.use('tinytest');\n  api.use('reactive-dict');\n  api.use('tracker');\n  api.use('underscore');\n  api.addFiles('reactive-dict-tests.js');\n});\n"
  },
  {
    "path": "packages/reactive-dict/reactive-dict-tests.js",
    "content": "Tinytest.add('ReactiveDict - set to undefined', function (test) {\n  var dict = new ReactiveDict;\n  dict.set('foo', undefined);\n  test.equal(_.keys(dict.all()), ['foo']);\n  dict.setDefault('foo', 'bar');\n  test.equal(dict.get('foo'), undefined);\n});\n\nTinytest.add('ReactiveDict - setDefault', function (test) {\n  var dict = new ReactiveDict;\n  dict.set('A', 'blah');\n  dict.set('B', undefined);\n  dict.setDefault('A', 'default');\n  dict.setDefault('B', 'default');\n  dict.setDefault('C', 'default');\n  dict.setDefault('D', undefined);\n  test.equal(dict.all(), {A: 'blah', B: undefined,\n                          C: 'default', D: undefined});\n\n  dict = new ReactiveDict;\n  dict.set('A', 'blah');\n  dict.set('B', undefined);\n  dict.setDefault({\n    A: 'default',\n    B: 'defualt',\n    C: 'default',\n    D: undefined\n  });\n  test.equal(dict.all(), {A: 'blah', B: undefined,\n                          C: 'default', D: undefined});\n});\n\nTinytest.add('ReactiveDict - all() works', function (test) {\n  var all = {}, dict = new ReactiveDict;\n  Tracker.autorun(function() {\n    all = dict.all();\n  });\n\n  test.equal(all, {});\n\n  dict.set('foo', 'bar');\n  Tracker.flush();\n  test.equal(all, {foo: 'bar'});\n\n  dict.set('blah', undefined);\n  Tracker.flush();\n  test.equal(all, {foo: 'bar', blah: undefined});\n});\n\n\nTinytest.add('ReactiveDict - clear() works', function (test) {\n  var dict = new ReactiveDict;\n  dict.set('foo', 'bar');\n\n  // Clear should not throw an error now\n  // See issue #5530\n  dict.clear();\n\n  dict.set('foo', 'bar');\n\n  var val, equals, equalsUndefined, all;\n  Tracker.autorun(function() {\n    val = dict.get('foo');\n  });\n  Tracker.autorun(function() {\n    equals = dict.equals('foo', 'bar');\n  });\n  Tracker.autorun(function() {\n    equalsUndefined = dict.equals('foo', undefined);\n  });\n  Tracker.autorun(function() {\n    all = dict.all();\n  });\n\n  test.equal(val, 'bar');\n  test.equal(equals, true);\n  test.equal(equalsUndefined, false);\n  test.equal(all, {foo: 'bar'});\n\n  dict.clear();\n  Tracker.flush();\n  test.isUndefined(val);\n  test.equal(equals, false);\n  test.equal(equalsUndefined, true);\n  test.equal(all, {});\n});\n\nTinytest.add('ReactiveDict - delete(key) works', function (test) {\n  var dict = new ReactiveDict;\n  dict.set('foo', 'bar');\n  dict.set('bar', 'foo');\n\n  dict.set('baz', 123);\n  test.equal(dict.delete('baz'), true);\n  test.equal(dict.delete('baz'), false);\n\n  var val, equals, equalsUndefined, all;\n\n  Tracker.autorun(function() {\n    val = dict.get('foo');\n  });\n  Tracker.autorun(function() {\n    equals = dict.equals('foo', 'bar');\n  });\n  Tracker.autorun(function() {\n    equalsUndefined = dict.equals('foo', undefined);\n  });\n  Tracker.autorun(function() {\n    all = dict.all();\n  });\n\n  test.equal(val, 'bar');\n  test.equal(equals, true);\n  test.equal(equalsUndefined, false);\n  test.equal(all, {foo: 'bar', bar: 'foo'});\n\n  var didRemove = dict.delete('foo');\n  test.equal(didRemove, true);\n\n  Tracker.flush();\n\n  test.isUndefined(val);\n  test.equal(equals, false);\n  test.equal(equalsUndefined, true);\n  test.equal(all, {bar: 'foo'});\n\n  didRemove = dict.delete('barfoobar');\n  test.equal(didRemove, false);\n});\n"
  },
  {
    "path": "packages/reactive-dict/reactive-dict.js",
    "content": "// XXX come up with a serialization method which canonicalizes object key\n// order, which would allow us to use objects as values for equals.\nvar stringify = function (value) {\n  if (value === undefined)\n    return 'undefined';\n  return EJSON.stringify(value);\n};\nvar parse = function (serialized) {\n  if (serialized === undefined || serialized === 'undefined')\n    return undefined;\n  return EJSON.parse(serialized);\n};\n\nvar changed = function (v) {\n  v && v.changed();\n};\n\n// XXX COMPAT WITH 0.9.1 : accept migrationData instead of dictName\nReactiveDict = function (dictName) {\n  // this.keys: key -> value\n  if (dictName) {\n    if (typeof dictName === 'string') {\n      // the normal case, argument is a string name.\n      // _registerDictForMigrate will throw an error on duplicate name.\n      ReactiveDict._registerDictForMigrate(dictName, this);\n      this.keys = ReactiveDict._loadMigratedDict(dictName) || {};\n      this.name = dictName;\n    } else if (typeof dictName === 'object') {\n      // back-compat case: dictName is actually migrationData\n      this.keys = dictName;\n    } else {\n      throw new Error(\"Invalid ReactiveDict argument: \" + dictName);\n    }\n  } else {\n    // no name given; no migration will be performed\n    this.keys = {};\n  }\n\n  this.allDeps = new Tracker.Dependency;\n  this.keyDeps = {}; // key -> Dependency\n  this.keyValueDeps = {}; // key -> Dependency\n};\n\n_.extend(ReactiveDict.prototype, {\n  // set() began as a key/value method, but we are now overloading it\n  // to take an object of key/value pairs, similar to backbone\n  // http://backbonejs.org/#Model-set\n\n  set: function (keyOrObject, value) {\n    var self = this;\n\n    if ((typeof keyOrObject === 'object') && (value === undefined)) {\n      // Called as `dict.set({...})`\n      self._setObject(keyOrObject);\n      return;\n    }\n    // the input isn't an object, so it must be a key\n    // and we resume with the rest of the function\n    var key = keyOrObject;\n\n    value = stringify(value);\n\n    var keyExisted = _.has(self.keys, key);\n    var oldSerializedValue = keyExisted ? self.keys[key] : 'undefined';\n    var isNewValue = (value !== oldSerializedValue);\n\n    self.keys[key] = value;\n\n    if (isNewValue || !keyExisted) {\n      self.allDeps.changed();\n    }\n\n    if (isNewValue) {\n      changed(self.keyDeps[key]);\n      if (self.keyValueDeps[key]) {\n        changed(self.keyValueDeps[key][oldSerializedValue]);\n        changed(self.keyValueDeps[key][value]);\n      }\n    }\n  },\n\n  setDefault: function (keyOrObject, value) {\n    var self = this;\n\n    if ((typeof keyOrObject === 'object') && (value === undefined)) {\n      // Called as `dict.setDefault({...})`\n      self._setDefaultObject(keyOrObject);\n      return;\n    }\n    // the input isn't an object, so it must be a key\n    // and we resume with the rest of the function\n    var key = keyOrObject;\n\n    if (! _.has(self.keys, key)) {\n      self.set(key, value);\n    }\n  },\n\n  get: function (key) {\n    var self = this;\n    self._ensureKey(key);\n    self.keyDeps[key].depend();\n    return parse(self.keys[key]);\n  },\n\n  equals: function (key, value) {\n    var self = this;\n\n    // Mongo.ObjectID is in the 'mongo' package\n    var ObjectID = null;\n    if (Package.mongo) {\n      ObjectID = Package.mongo.Mongo.ObjectID;\n    }\n\n    // We don't allow objects (or arrays that might include objects) for\n    // .equals, because JSON.stringify doesn't canonicalize object key\n    // order. (We can make equals have the right return value by parsing the\n    // current value and using EJSON.equals, but we won't have a canonical\n    // element of keyValueDeps[key] to store the dependency.) You can still use\n    // \"EJSON.equals(reactiveDict.get(key), value)\".\n    //\n    // XXX we could allow arrays as long as we recursively check that there\n    // are no objects\n    if (typeof value !== 'string' &&\n        typeof value !== 'number' &&\n        typeof value !== 'boolean' &&\n        typeof value !== 'undefined' &&\n        !(value instanceof Date) &&\n        !(ObjectID && value instanceof ObjectID) &&\n        value !== null) {\n      throw new Error(\"ReactiveDict.equals: value must be scalar\");\n    }\n    var serializedValue = stringify(value);\n\n    if (Tracker.active) {\n      self._ensureKey(key);\n\n      if (! _.has(self.keyValueDeps[key], serializedValue))\n        self.keyValueDeps[key][serializedValue] = new Tracker.Dependency;\n\n      var isNew = self.keyValueDeps[key][serializedValue].depend();\n      if (isNew) {\n        Tracker.onInvalidate(function () {\n          // clean up [key][serializedValue] if it's now empty, so we don't\n          // use O(n) memory for n = values seen ever\n          if (! self.keyValueDeps[key][serializedValue].hasDependents())\n            delete self.keyValueDeps[key][serializedValue];\n        });\n      }\n    }\n\n    var oldValue = undefined;\n    if (_.has(self.keys, key)) oldValue = parse(self.keys[key]);\n    return EJSON.equals(oldValue, value);\n  },\n\n  all: function() {\n    this.allDeps.depend();\n    var ret = {};\n    _.each(this.keys, function(value, key) {\n      ret[key] = parse(value);\n    });\n    return ret;\n  },\n\n  clear: function() {\n    var self = this;\n\n    var oldKeys = self.keys;\n    self.keys = {};\n\n    self.allDeps.changed();\n\n    _.each(oldKeys, function(value, key) {\n      changed(self.keyDeps[key]);\n      if (self.keyValueDeps[key]) {\n        changed(self.keyValueDeps[key][value]);\n        changed(self.keyValueDeps[key]['undefined']);\n      }\n    });\n\n  },\n\n  delete: function(key) {\n    var self = this;\n    var didRemove = false;\n\n    if (_.has(self.keys, key)) {\n      var oldValue = self.keys[key];\n      delete self.keys[key];\n      changed(self.keyDeps[key]);\n      if (self.keyValueDeps[key]) {\n        changed(self.keyValueDeps[key][oldValue]);\n        changed(self.keyValueDeps[key]['undefined']);\n      }\n      self.allDeps.changed();\n      didRemove = true;\n    }\n\n    return didRemove;\n  },\n\n  _setObject: function (object) {\n    var self = this;\n\n    _.each(object, function (value, key){\n      self.set(key, value);\n    });\n  },\n\n  _setDefaultObject: function (object) {\n    var self = this;\n\n    _.each(object, function (value, key){\n      self.setDefault(key, value);\n    });\n  },\n\n  _ensureKey: function (key) {\n    var self = this;\n    if (!(key in self.keyDeps)) {\n      self.keyDeps[key] = new Tracker.Dependency;\n      self.keyValueDeps[key] = {};\n    }\n  },\n\n  // Get a JSON value that can be passed to the constructor to\n  // create a new ReactiveDict with the same contents as this one\n  _getMigrationData: function () {\n    // XXX sanitize and make sure it's JSONible?\n    return this.keys;\n  }\n});\n"
  },
  {
    "path": "packages/reactive-var/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/reactive-var/README.md",
    "content": "# reactive-var\n\nThis package provide `ReactiveVar`, a general-purpose reactive\ndatatype for use with\n[tracker](https://atmospherejs.com/meteor/tracker). `ReactiveVar` is\ndocumented on the [main\nMeteor docs page](https://docs.meteor.com/#reactivevar_pkg).\n\n## Future work\n\nUnify with [reactive-dict](https://atmospherejs.com/meteor/reactive-dict).\n"
  },
  {
    "path": "packages/reactive-var/package.js",
    "content": "Package.describe({\n  summary: \"Reactive variable\",\n  version: '1.0.10'\n});\n\nPackage.onUse(function (api) {\n  api.export('ReactiveVar');\n\n  api.use('tracker');\n\n  api.addFiles('reactive-var.js');\n});\n"
  },
  {
    "path": "packages/reactive-var/reactive-var.js",
    "content": "/*\n * ## [new] ReactiveVar(initialValue, [equalsFunc])\n *\n * A ReactiveVar holds a single value that can be get and set,\n * such that calling `set` will invalidate any Computations that\n * called `get`, according to the usual contract for reactive\n * data sources.\n *\n * A ReactiveVar is much like a Session variable -- compare `foo.get()`\n * to `Session.get(\"foo\")` -- but it doesn't have a global name and isn't\n * automatically migrated across hot code pushes.  Also, while Session\n * variables can only hold JSON or EJSON, ReactiveVars can hold any value.\n *\n * An important property of ReactiveVars, which is sometimes the reason\n * to use one, is that setting the value to the same value as before has\n * no effect, meaning ReactiveVars can be used to absorb extra\n * invalidations that wouldn't serve a purpose.  However, by default,\n * ReactiveVars are extremely conservative about what changes they\n * absorb.  Calling `set` with an object argument will *always* trigger\n * invalidations, because even if the new value is `===` the old value,\n * the object may have been mutated.  You can change the default behavior\n * by passing a function of two arguments, `oldValue` and `newValue`,\n * to the constructor as `equalsFunc`.\n *\n * This class is extremely basic right now, but the idea is to evolve\n * it into the ReactiveVar of Geoff's Lickable Forms proposal.\n */\n\n/**\n * @class \n * @instanceName reactiveVar\n * @summary Constructor for a ReactiveVar, which represents a single reactive variable.\n * @locus Client\n * @param {Any} initialValue The initial value to set.  `equalsFunc` is ignored when setting the initial value.\n * @param {Function} [equalsFunc] Optional.  A function of two arguments, called on the old value and the new value whenever the ReactiveVar is set.  If it returns true, no set is performed.  If omitted, the default `equalsFunc` returns true if its arguments are `===` and are of type number, boolean, string, undefined, or null.\n */\nReactiveVar = function (initialValue, equalsFunc) {\n  if (! (this instanceof ReactiveVar))\n    // called without `new`\n    return new ReactiveVar(initialValue, equalsFunc);\n\n  this.curValue = initialValue;\n  this.equalsFunc = equalsFunc;\n  this.dep = new Tracker.Dependency;\n};\n\nReactiveVar._isEqual = function (oldValue, newValue) {\n  var a = oldValue, b = newValue;\n  // Two values are \"equal\" here if they are `===` and are\n  // number, boolean, string, undefined, or null.\n  if (a !== b)\n    return false;\n  else\n    return ((!a) || (typeof a === 'number') || (typeof a === 'boolean') ||\n            (typeof a === 'string'));\n};\n\n/**\n * @summary Returns the current value of the ReactiveVar, establishing a reactive dependency.\n * @locus Client\n */\nReactiveVar.prototype.get = function () {\n  if (Tracker.active)\n    this.dep.depend();\n\n  return this.curValue;\n};\n\n/**\n * @summary Sets the current value of the ReactiveVar, invalidating the Computations that called `get` if `newValue` is different from the old value.\n * @locus Client\n * @param {Any} newValue\n */\nReactiveVar.prototype.set = function (newValue) {\n  var oldValue = this.curValue;\n\n  if ((this.equalsFunc || ReactiveVar._isEqual)(oldValue, newValue))\n    // value is same as last time\n    return;\n\n  this.curValue = newValue;\n  this.dep.changed();\n};\n\nReactiveVar.prototype.toString = function () {\n  return 'ReactiveVar{' + this.get() + '}';\n};\n\nReactiveVar.prototype._numListeners = function() {\n  // Tests want to know.\n  // Accesses a private field of Tracker.Dependency.\n  var count = 0;\n  for (var id in this.dep._dependentsById)\n    count++;\n  return count;\n};\n"
  },
  {
    "path": "packages/reload/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/reload/README.md",
    "content": "# reload\n\nThe `reload` package handles the process of *migrating* an app:\nserializing the app's state, then shutting down and restarting the app\n(for example, to load updated client code or to move the client\nsession from one JavaScript virtual machine to another), and finally\nrestoring its state.\n\nPackages that want to participate in the migration process register\nwith `reload`. They can make the migration process wait until they are\nready and include whatever state they may possess in the serialization\nand deserialization process.\n\n`reload` is part of the [Webapp](https://www.meteor.com/webapp) project.\n"
  },
  {
    "path": "packages/reload/deprecated.js",
    "content": "// Reload functionality used to live on Meteor._reload. Be nice and try not to\n// break code that uses it, even though it's internal.\n// XXX COMPAT WITH 0.6.4\nMeteor._reload = {\n  onMigrate: Reload._onMigrate,\n  migrationData: Reload._migrationData,\n  reload: Reload._reload\n};\n"
  },
  {
    "path": "packages/reload/package.js",
    "content": "Package.describe({\n  summary: \"Reload the page while preserving application state.\",\n  version: '1.1.10'\n});\n\nPackage.onUse(function (api) {\n  api.use(['underscore', 'ecmascript-runtime'], 'client');\n  api.export('Reload', 'client');\n  api.addFiles('reload.js', 'client');\n  api.addFiles('deprecated.js', 'client');\n});\n\nPackage.onTest(function (api) {\n  api.use(['tinytest', 'reload'], 'client');\n  api.addFiles('reload_tests.js', 'client');\n});\n"
  },
  {
    "path": "packages/reload/reload.js",
    "content": "/**\n * This code does _NOT_ support hot (session-restoring) reloads on\n * IE6,7. It only works on browsers with sessionStorage support.\n *\n * There are a couple approaches to add IE6,7 support:\n *\n * - use IE's \"userData\" mechanism in combination with window.name.\n * This mostly works, however the problem is that it can not get to the\n * data until after DOMReady. This is a problem for us since this API\n * relies on the data being ready before API users run. We could\n * refactor using Meteor.startup in all API users, but that might slow\n * page loads as we couldn't start the stream until after DOMReady.\n * Here are some resources on this approach:\n * https://github.com/hugeinc/USTORE.js\n * http://thudjs.tumblr.com/post/419577524/localstorage-userdata\n * http://www.javascriptkit.com/javatutors/domstorage2.shtml\n *\n * - POST the data to the server, and have the server send it back on\n * page load. This is nice because it sidesteps all the local storage\n * compatibility issues, however it is kinda tricky. We can use a unique\n * token in the URL, then get rid of it with HTML5 pushstate, but that\n * only works on pushstate browsers.\n *\n * This will all need to be reworked entirely when we add server-side\n * HTML rendering. In that case, the server will need to have access to\n * the client's session to render properly.\n */\n\n// XXX when making this API public, also expose a flag for the app\n// developer to know whether a hot code push is happening. This is\n// useful for apps using `window.onbeforeunload`. See\n// https://github.com/meteor/meteor/pull/657\n\nReload = {};\n\nvar KEY_NAME = 'Meteor_Reload';\n\nvar old_data = {};\n// read in old data at startup.\nvar old_json;\n\n// This logic for sessionStorage detection is based on browserstate/history.js\nvar safeSessionStorage = null;\ntry {\n  // This throws a SecurityError on Chrome if cookies & localStorage are\n  // explicitly disabled\n  //\n  // On Firefox with dom.storage.enabled set to false, sessionStorage is null\n  //\n  // We can't even do (typeof sessionStorage) on Chrome, it throws.  So we rely\n  // on the throw if sessionStorage == null; the alternative is browser\n  // detection, but this seems better.\n  safeSessionStorage = window.sessionStorage;\n\n  // Check we can actually use it\n  if (safeSessionStorage) {\n    safeSessionStorage.setItem('__dummy__', '1');\n    safeSessionStorage.removeItem('__dummy__');\n  } else {\n    // Be consistently null, for safety\n    safeSessionStorage = null;\n  }\n} catch(e) {\n  // Expected on chrome with strict security, or if sessionStorage not supported\n  safeSessionStorage = null;\n}\n\n// Exported for test.\nReload._getData = function () {\n  return safeSessionStorage && safeSessionStorage.getItem(KEY_NAME);\n};\n\nif (safeSessionStorage) {\n  old_json = Reload._getData();\n  safeSessionStorage.removeItem(KEY_NAME);\n} else {\n  // Unsupported browser (IE 6,7) or locked down security settings.\n  // No session resumption.\n  // Meteor._debug(\"XXX UNSUPPORTED BROWSER/SETTINGS\");\n}\n\nif (!old_json) old_json = '{}';\nvar old_parsed = {};\ntry {\n  old_parsed = JSON.parse(old_json);\n  if (typeof old_parsed !== \"object\") {\n    Meteor._debug(\"Got bad data on reload. Ignoring.\");\n    old_parsed = {};\n  }\n} catch (err) {\n  Meteor._debug(\"Got invalid JSON on reload. Ignoring.\");\n}\n\nif (old_parsed.reload && typeof old_parsed.data === \"object\") {\n  // Meteor._debug(\"Restoring reload data.\");\n  old_data = old_parsed.data;\n}\n\n\nvar providers = [];\n\n////////// External API //////////\n\n// Packages that support migration should register themselves by calling\n// this function. When it's time to migrate, callback will be called\n// with one argument, the \"retry function,\" and an optional 'option'\n// argument (containing a key 'immediateMigration'). If the package\n// is ready to migrate, it should return [true, data], where data is\n// its migration data, an arbitrary JSON value (or [true] if it has\n// no migration data this time). If the package needs more time\n// before it is ready to migrate, it should return false. Then, once\n// it is ready to migrating again, it should call the retry\n// function. The retry function will return immediately, but will\n// schedule the migration to be retried, meaning that every package\n// will be polled once again for its migration data. If they are all\n// ready this time, then the migration will happen. name must be set if there\n// is migration data. If 'immediateMigration' is set in the options\n// argument, then it doesn't matter whether the package is ready to\n// migrate or not; the reload will happen immediately without waiting\n// (used for OAuth redirect login).\n//\nReload._onMigrate = function (name, callback) {\n  if (!callback) {\n    // name not provided, so first arg is callback.\n    callback = name;\n    name = undefined;\n  }\n  providers.push({name: name, callback: callback});\n};\n\n// Called by packages when they start up.\n// Returns the object that was saved, or undefined if none saved.\n//\nReload._migrationData = function (name) {\n  return old_data[name];\n};\n\n// Options are the same as for `Reload._migrate`.\nvar pollProviders = function (tryReload, options) {\n  tryReload = tryReload || function () {};\n  options = options || {};\n\n  var migrationData = {};\n  var remaining = _.clone(providers);\n  var allReady = true;\n  while (remaining.length) {\n    var p = remaining.shift();\n    var status = p.callback(tryReload, options);\n    if (!status[0])\n      allReady = false;\n    if (status.length > 1 && p.name)\n      migrationData[p.name] = status[1];\n  };\n  if (allReady || options.immediateMigration)\n    return migrationData;\n  else\n    return null;\n};\n\n// Options are:\n//  - immediateMigration: true if the page will be reloaded immediately\n//    regardless of whether packages report that they are ready or not.\nReload._migrate = function (tryReload, options) {\n  // Make sure each package is ready to go, and collect their\n  // migration data\n  var migrationData = pollProviders(tryReload, options);\n  if (migrationData === null)\n    return false; // not ready yet..\n\n  try {\n    // Persist the migration data\n    var json = JSON.stringify({\n      data: migrationData, reload: true\n    });\n  } catch (err) {\n    Meteor._debug(\"Couldn't serialize data for migration\", migrationData);\n    throw err;\n  }\n\n  if (safeSessionStorage) {\n    try {\n      safeSessionStorage.setItem(KEY_NAME, json);\n    } catch (err) {\n      // We should have already checked this, but just log - don't throw\n      Meteor._debug(\"Couldn't save data for migration to sessionStorage\", err);\n    }\n  } else {\n    Meteor._debug(\"Browser does not support sessionStorage. Not saving migration state.\");\n  }\n\n  return true;\n};\n\n// Allows tests to isolate the list of providers.\nReload._withFreshProvidersForTest = function (f) {\n  var originalProviders = _.clone(providers);\n  providers = [];\n  try {\n    f();\n  } finally {\n    providers = originalProviders;\n  }\n};\n\n// Migrating reload: reload this page (presumably to pick up a new\n// version of the code or assets), but save the program state and\n// migrate it over. This function returns immediately. The reload\n// will happen at some point in the future once all of the packages\n// are ready to migrate.\n//\nvar reloading = false;\nReload._reload = function (options) {\n  options = options || {};\n\n  if (reloading)\n    return;\n  reloading = true;\n\n  var tryReload = function () { _.defer(function () {\n    if (Reload._migrate(tryReload, options)) {\n      // We'd like to make the browser reload the page using location.replace()\n      // instead of location.reload(), because this avoids validating assets\n      // with the server if we still have a valid cached copy. This doesn't work\n      // when the location contains a hash however, because that wouldn't reload\n      // the page and just scroll to the hash location instead.\n      if (window.location.hash || window.location.href.endsWith(\"#\")) {\n        window.location.reload();\n      } else {\n        window.location.replace(window.location.href);\n      }\n    }\n  }); };\n\n  tryReload();\n};\n"
  },
  {
    "path": "packages/reload/reload_tests.js",
    "content": "Tinytest.add(\"reload - migrate\", function (test) {\n  Reload._withFreshProvidersForTest(function () {\n    var ready = false;\n\n    Reload._onMigrate(\"reload test data 1\", function (tryReload, options) {\n      return [ready, { foo: \"bar\" }];\n    });\n\n    Reload._onMigrate(\"reload test data 2\", function (tryReload, options) {\n      return [true, { baz: \"bar\" }];\n    });\n\n    // When one provider returns false, no migration data should be stored.\n    test.isFalse(Reload._migrate(function () { }));\n    test.isFalse(Reload._getData());\n\n    // If an immediate migration is happening, then it shouldn't matter if\n    // one provider returns false.\n    test.isTrue(Reload._migrate(function () { }, { immediateMigration: true }));\n    var data = JSON.parse(Reload._getData());\n    test.equal(data.data[\"reload test data 1\"], { foo: \"bar\" });\n    test.equal(data.data[\"reload test data 2\"], { baz: \"bar\" });\n    test.equal(data.reload, true);\n\n    // Now all providers are ready.\n    ready = true;\n    test.isTrue(Reload._migrate(function () { }));\n\n    data = JSON.parse(Reload._getData());\n    test.equal(data.data[\"reload test data 1\"], { foo: \"bar\" });\n    test.equal(data.data[\"reload test data 2\"], { baz: \"bar\" });\n    test.equal(data.reload, true);\n  });\n});\n"
  },
  {
    "path": "packages/reload-safetybelt/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/reload-safetybelt/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/reload-safetybelt/package.js",
    "content": "Package.describe({\n  summary: \"Reload safety belt for multi-server deployments\",\n  version: '1.0.10'\n});\n\nPackage.onUse(function (api) {\n  api.use(\"webapp\", \"server\");\n  api.addFiles(\"reload-safety-belt.js\", \"server\");\n  api.addAssets(\"safetybelt.js\", \"server\");\n});\n\nPackage.onTest(function (api) {\n  api.addAssets(\"safetybelt.js\", \"server\");\n  api.use([\"reload-safetybelt\", \"tinytest\", \"http\", \"webapp\", \"underscore\"]);\n  api.addFiles(\"reload-safety-belt-tests.js\", \"server\");\n});\n"
  },
  {
    "path": "packages/reload-safetybelt/reload-safety-belt-tests.js",
    "content": "var script = Assets.getText(\"safetybelt.js\");\n\nTinytest.add(\"reload-safetybelt - safety belt is added\", function (test) {\n  test.isTrue(_.some(\n    WebAppInternals.additionalStaticJs,\n    function (js, pathname) {\n      return js === script;\n    }\n  ));\n});\n"
  },
  {
    "path": "packages/reload-safetybelt/reload-safety-belt.js",
    "content": "// The reload safetybelt is some js that will be loaded after everything else in\n// the HTML.  In some multi-server deployments, when you update, you have a\n// chance of hitting an old server for the HTML and the new server for the JS or\n// CSS.  This prevents you from displaying the page in that case, and instead\n// reloads it, presumably all on the new version now.\nWebAppInternals.addStaticJs(Assets.getText(\"safetybelt.js\"));\n"
  },
  {
    "path": "packages/reload-safetybelt/safetybelt.js",
    "content": "if (typeof Package === 'undefined' ||\n    ! Package.webapp ||\n    ! Package.webapp.WebApp ||\n    ! Package.webapp.WebApp._isCssLoaded()) {\n  document.location.reload();\n}\n"
  },
  {
    "path": "packages/retry/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/retry/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/retry/package.js",
    "content": "Package.describe({\n  summary: \"Retry logic with exponential backoff\",\n  version: '1.0.8'\n});\n\nPackage.onUse(function (api) {\n  api.use(['underscore', 'random'], ['client', 'server']);\n  api.export('Retry');\n  api.addFiles('retry.js', ['client', 'server']);\n});\n"
  },
  {
    "path": "packages/retry/retry.js",
    "content": "// Retry logic with an exponential backoff.\n//\n// options:\n//  baseTimeout: time for initial reconnect attempt (ms).\n//  exponent: exponential factor to increase timeout each attempt.\n//  maxTimeout: maximum time between retries (ms).\n//  minCount: how many times to reconnect \"instantly\".\n//  minTimeout: time to wait for the first `minCount` retries (ms).\n//  fuzz: factor to randomize retry times by (to avoid retry storms).\n\nRetry = function (options) {\n  var self = this;\n  _.extend(self, _.defaults(_.clone(options || {}), {\n    baseTimeout: 1000, // 1 second\n    exponent: 2.2,\n    // The default is high-ish to ensure a server can recover from a\n    // failure caused by load.\n    maxTimeout: 5 * 60000, // 5 minutes\n    minTimeout: 10,\n    minCount: 2,\n    fuzz: 0.5 // +- 25%\n  }));\n  self.retryTimer = null;\n};\n\n_.extend(Retry.prototype, {\n\n  // Reset a pending retry, if any.\n  clear: function () {\n    var self = this;\n    if (self.retryTimer)\n      clearTimeout(self.retryTimer);\n    self.retryTimer = null;\n  },\n\n  // Calculate how long to wait in milliseconds to retry, based on the\n  // `count` of which retry this is.\n  _timeout: function (count) {\n    var self = this;\n\n    if (count < self.minCount)\n      return self.minTimeout;\n\n    var timeout = Math.min(\n      self.maxTimeout,\n      self.baseTimeout * Math.pow(self.exponent, count));\n    // fuzz the timeout randomly, to avoid reconnect storms when a\n    // server goes down.\n    timeout = timeout * ((Random.fraction() * self.fuzz) +\n                         (1 - self.fuzz/2));\n    return timeout;\n  },\n\n  // Call `fn` after a delay, based on the `count` of which retry this is.\n  retryLater: function (count, fn) {\n    var self = this;\n    var timeout = self._timeout(count);\n    if (self.retryTimer)\n      clearTimeout(self.retryTimer);\n    self.retryTimer = Meteor.setTimeout(fn, timeout);\n    return timeout;\n  }\n\n});\n"
  },
  {
    "path": "packages/routepolicy/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/routepolicy/README.md",
    "content": "# RoutePolicy\n\nRoutePolicy, part of [Webapp](https://www.meteor.com/webapp), is a\nlow-level API for declaring the offline access semantics that apply to\nportions of the app's URL space. This is information is necessary when\ngenerating HTML5 Appcache manifests.\n\nFor example, [DDP](https://www.meteor.com/ddp) uses sockjs to emulate\nwebsockets when they are not available. sockjs emulates websockets\nusing HTTP long polling, and it uses URLs under `/sockjs` to perform\nthis long polling. So the [ddp](https://atmospherejs.com/meteor/ddp)\npackage uses RoutePolicy to declare that the `/sockjs` route is of\ntype \"network\" and should always be fetched live from the Internet and\nnever included in the appcache.\n\nFor more information, see the comments in the source.\n"
  },
  {
    "path": "packages/routepolicy/package.js",
    "content": "Package.describe({\n  summary: \"route policy declarations\",\n  version: '1.0.11'\n});\n\nPackage.onUse(function (api) {\n  api.use('underscore', 'server');\n  // Resolve circular dependency with webapp. We can only use WebApp via\n  // Package.webapp and only after initial load.\n  api.use('webapp', 'server', {unordered: true});\n  api.export('RoutePolicy', 'server');\n  api.export('RoutePolicyTest', 'server', {testOnly: true});\n  api.addFiles('routepolicy.js', 'server');\n});\n\nPackage.onTest(function (api) {\n  api.use(['routepolicy', 'tinytest']);\n  api.addFiles(['routepolicy_tests.js'], 'server');\n});\n"
  },
  {
    "path": "packages/routepolicy/routepolicy.js",
    "content": "// In addition to listing specific files to be cached, the browser\n// application cache manifest allows URLs to be designated as NETWORK\n// (always fetched from the Internet) and FALLBACK (which we use to\n// serve app HTML on arbitrary URLs).\n//\n// The limitation of the manifest file format is that the designations\n// are by prefix only: if \"/foo\" is declared NETWORK then \"/foobar\"\n// will also be treated as a network route.\n//\n// RoutePolicy is a low-level API for declaring the route type of URL prefixes:\n//\n// \"network\": for network routes that should not conflict with static\n// resources.  (For example, if \"/sockjs/\" is a network route, we\n// shouldn't have \"/sockjs/red-sock.jpg\" as a static resource).\n//\n// \"static-online\": for static resources which should not be cached in\n// the app cache.  This is implemented by also adding them to the\n// NETWORK section (as otherwise the browser would receive app HTML\n// for them because of the FALLBACK section), but static-online routes\n// don't need to be checked for conflict with static resources.\n\n// The route policy is a singleton in a running application, but we\n// can't unit test the real singleton because messing with the real\n// routes would break tinytest... so allow policy instances to be\n// constructed for testing.\n\nRoutePolicyTest = {};\n\nvar RoutePolicyConstructor = RoutePolicyTest.Constructor = function () {\n  var self = this;\n  self.urlPrefixTypes = {};\n};\n\n_.extend(RoutePolicyConstructor.prototype, {\n\n  urlPrefixMatches: function (urlPrefix, url) {\n    return url.substr(0, urlPrefix.length) === urlPrefix;\n  },\n\n  checkType: function (type) {\n    if (! _.contains(['network', 'static-online'], type))\n      return 'the route type must be \"network\" or \"static-online\"';\n    return null;\n  },\n\n  checkUrlPrefix: function (urlPrefix, type) {\n    var self = this;\n\n    if (urlPrefix.charAt(0) !== '/')\n      return 'a route URL prefix must begin with a slash';\n\n    if (urlPrefix === '/')\n      return 'a route URL prefix cannot be /';\n\n    var existingType = self.urlPrefixTypes[urlPrefix];\n    if (existingType && existingType !== type)\n      return 'the route URL prefix ' + urlPrefix + ' has already been declared to be of type ' + existingType;\n\n    return null;\n  },\n\n  checkForConflictWithStatic: function (urlPrefix, type, _testManifest) {\n    var self = this;\n    if (type === 'static-online')\n      return null;\n    if (!Package.webapp || !Package.webapp.WebApp\n        || !Package.webapp.WebApp.clientPrograms\n        || !Package.webapp.WebApp.clientPrograms[Package.webapp.WebApp.defaultArch].manifest) {\n      // Hack: If we don't have a manifest, deal with it\n      // gracefully. This lets us load livedata into a nodejs\n      // environment that doesn't have a HTTP server (eg, a\n      // command-line tool).\n      return null;\n    }\n    var manifest = _testManifest ||\n      Package.webapp.WebApp.clientPrograms[Package.webapp.WebApp.defaultArch].manifest;\n    var conflict = _.find(manifest, function (resource) {\n      return (resource.type === 'static' &&\n              resource.where === 'client' &&\n              self.urlPrefixMatches(urlPrefix, resource.url));\n    });\n    if (conflict)\n      return ('static resource ' + conflict.url + ' conflicts with ' +\n              type + ' route ' + urlPrefix);\n    else\n      return null;\n  },\n\n  declare: function (urlPrefix, type) {\n    var self = this;\n    var problem = self.checkType(type) ||\n                  self.checkUrlPrefix(urlPrefix, type) ||\n                  self.checkForConflictWithStatic(urlPrefix, type);\n    if (problem)\n      throw new Error(problem);\n    // TODO overlapping prefixes, e.g. /foo/ and /foo/bar/\n    self.urlPrefixTypes[urlPrefix] = type;\n  },\n\n  isValidUrl: function (url) {\n    return url.charAt(0) === '/';\n  },\n\n  classify: function (url) {\n    var self = this;\n    if (url.charAt(0) !== '/')\n      throw new Error('url must be a relative URL: ' + url);\n    var prefix = _.find(_.keys(self.urlPrefixTypes), function (_prefix) {\n      return self.urlPrefixMatches(_prefix, url);\n    });\n    if (prefix)\n      return self.urlPrefixTypes[prefix];\n    else\n      return null;\n  },\n\n  urlPrefixesFor: function (type) {\n    var self = this;\n    var prefixes = [];\n    _.each(self.urlPrefixTypes, function (_type, _prefix) {\n      if (_type === type)\n        prefixes.push(_prefix);\n    });\n    return prefixes.sort();\n  }\n});\n\nRoutePolicy = new RoutePolicyConstructor();\n"
  },
  {
    "path": "packages/routepolicy/routepolicy_tests.js",
    "content": "Tinytest.add(\"routepolicy - declare\", function (test) {\n  var policy = new RoutePolicyTest.Constructor();\n\n  policy.declare('/sockjs/', 'network');\n  policy.declare('/bigphoto.jpg', 'static-online');\n  policy.declare('/anotherphoto.png', 'static-online');\n\n  test.equal(policy.classify('/'), null);\n  test.equal(policy.classify('/foo'), null);\n  test.equal(policy.classify('/sockjs'), null);\n\n  test.equal(policy.classify('/sockjs/'), 'network');\n  test.equal(policy.classify('/sockjs/foo'), 'network');\n\n  test.equal(policy.classify('/bigphoto.jpg'), 'static-online');\n  test.equal(policy.classify('/bigphoto.jpg.orig'), 'static-online');\n\n  test.equal(policy.urlPrefixesFor('network'), ['/sockjs/']);\n  test.equal(\n    policy.urlPrefixesFor('static-online'),\n    ['/anotherphoto.png', '/bigphoto.jpg']\n  );\n});\n\nTinytest.add(\"routepolicy - static conflicts\", function (test) {\n  var manifest = [\n    {\n      \"path\": \"static/sockjs/socks-are-comfy.jpg\",\n      \"type\": \"static\",\n      \"where\": \"client\",\n      \"url\": \"/sockjs/socks-are-comfy.jpg\"\n    },\n    {\n      \"path\": \"static/bigphoto.jpg\",\n      \"type\": \"static\",\n      \"where\": \"client\",\n      \"url\": \"/bigphoto.jpg\"\n    }\n  ];\n  var policy = new RoutePolicyTest.Constructor();\n\n  test.equal(\n    policy.checkForConflictWithStatic('/sockjs/', 'network', manifest),\n    \"static resource /sockjs/socks-are-comfy.jpg conflicts with network route /sockjs/\"\n  );\n\n  test.equal(\n    policy.checkForConflictWithStatic('/bigphoto.jpg', 'static-online', manifest),\n    null\n  );\n});\n\nTinytest.add(\"routepolicy - checkUrlPrefix\", function (test) {\n  var policy = new RoutePolicyTest.Constructor();\n  policy.declare('/sockjs/', 'network');\n\n  test.equal(\n    policy.checkUrlPrefix('foo/bar', 'network'),\n    \"a route URL prefix must begin with a slash\"\n  );\n\n  test.equal(\n    policy.checkUrlPrefix('/', 'network'),\n    \"a route URL prefix cannot be /\"\n  );\n\n  test.equal(\n    policy.checkUrlPrefix('/sockjs/', 'static-online'),\n    \"the route URL prefix /sockjs/ has already been declared to be of type network\"\n  );\n});\n"
  },
  {
    "path": "packages/service-configuration/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/service-configuration/README.md",
    "content": "# service-configuration\n\nConfigure login services. Example:\n\n```\nServiceConfiguration.configurations.upsert(\n  { service: \"weibo\" },\n  { $set: { clientId: \"1292962797\", secret: \"75a730b58f5691de5522789070c319bc\" } }\n);\n```\n\nRead more in the [Meteor\ndocs](http://docs.meteor.com/#meteor_loginwithexternalservice) and the\nMeteor Accounts [project page](https://www.meteor.com/accounts).\n"
  },
  {
    "path": "packages/service-configuration/package.js",
    "content": "Package.describe({\n  summary: \"Manage the configuration for third-party services\",\n  version: \"1.0.10\"\n});\n\nPackage.onUse(function(api) {\n  api.use('accounts-base', ['client', 'server']);\n  api.use('mongo', ['client', 'server']);\n  api.export('ServiceConfiguration');\n  api.addFiles('service_configuration_common.js', ['client', 'server']);\n  api.addFiles('service_configuration_server.js', 'server');\n});\n"
  },
  {
    "path": "packages/service-configuration/service_configuration_common.js",
    "content": "if (typeof ServiceConfiguration === 'undefined') {\n  ServiceConfiguration = {};\n}\n\n\n// Table containing documents with configuration options for each\n// login service\nServiceConfiguration.configurations = new Mongo.Collection(\n  \"meteor_accounts_loginServiceConfiguration\", {\n    _preventAutopublish: true,\n    connection: Meteor.isClient ? Accounts.connection : Meteor.connection\n  });\n// Leave this collection open in insecure mode. In theory, someone could\n// hijack your oauth connect requests to a different endpoint or appId,\n// but you did ask for 'insecure'. The advantage is that it is much\n// easier to write a configuration wizard that works only in insecure\n// mode.\n\n\n// Thrown when trying to use a login service which is not configured\nServiceConfiguration.ConfigError = function (serviceName) {\n  if (Meteor.isClient && !Accounts.loginServicesConfigured()) {\n    this.message = \"Login service configuration not yet loaded\";\n  } else if (serviceName) {\n    this.message = \"Service \" + serviceName + \" not configured\";\n  } else {\n    this.message = \"Service not configured\";\n  }\n};\nServiceConfiguration.ConfigError.prototype = new Error();\nServiceConfiguration.ConfigError.prototype.name = 'ServiceConfiguration.ConfigError';\n"
  },
  {
    "path": "packages/service-configuration/service_configuration_server.js",
    "content": "// Only one configuration should ever exist for each service.\n// A unique index helps avoid various race conditions which could\n// otherwise lead to an inconsistent database state (when there are multiple\n// configurations for a single service, which configuration is correct?)\ntry {\n    ServiceConfiguration.configurations._ensureIndex(\n        { \"service\": 1 },\n        { unique: true }\n    );\n} catch (err) {\n    console.error(\n        \"The service-configuration package persists configuration in the \" +\n        \"meteor_accounts_loginServiceConfiguration collection in MongoDB. As \" +\n        \"each service should have exactly one configuration, Meteor \" +\n        \"automatically creates a MongoDB index with a unique constraint on the \" +\n        \" meteor_accounts_loginServiceConfiguration collection. The \" +\n        \"_ensureIndex command which creates that index is failing.\\n\\n\" +\n        \"Meteor versions before 1.0.4 did not create this index. If you recently \" +\n        \"upgraded and are seeing this error message for the first time, please \" +\n        \"check your meteor_accounts_loginServiceConfiguration collection for \" +\n        \"multiple configuration entries for the same service and delete \" +\n        \"configuration entries until there is no more than one configuration \" +\n        \"entry per service.\\n\\n\" +\n        \"If the meteor_accounts_loginServiceConfiguration collection looks \" +\n        \"fine, the _ensureIndex command is failing for some other reason.\\n\\n\" +\n        \"For more information on this history of this issue, please see \" +\n        \"https://github.com/meteor/meteor/pull/3514.\\n\"\n    );\n    throw err;\n}\n"
  },
  {
    "path": "packages/session/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/session/README.md",
    "content": "# session\n\nThis package provide `Session`. `Session` is a special\n[ReactiveDict](https://atmospherejs.com/meteor/reactive-dict) whose\ncontents are preserved across Hot Code Push. It's usually used to\nstore the current state of the user interface, for example, the\ncurrently selected row in a table, ora flag indicating if a dialog box\nis open.\n\nFull documentation of `Session` can be found on the [main Meteor docs\npage](https://docs.meteor.com/#session).\n\n## Future work\n\nUnify with [reactive-dict](https://atmospherejs.com/meteor/reactive-dict).\n"
  },
  {
    "path": "packages/session/package.js",
    "content": "Package.describe({\n  summary: \"Session variable\",\n  version: '1.1.6'\n});\n\nPackage.onUse(function (api) {\n  api.use(['underscore', 'reactive-dict', 'ejson'], 'client');\n\n  // Session can work with or without reload, but if reload is present\n  // it should load first so we can detect it at startup and populate\n  // the session.\n  api.use('reload', 'client', {weak: true});\n\n  api.export('Session', 'client');\n  api.addFiles('session.js', 'client');\n});\n\nPackage.onTest(function (api) {\n  api.use('tinytest');\n  api.use('session', 'client');\n  api.use('tracker');\n  api.use('mongo');\n  api.addFiles('session_tests.js', 'client');\n});\n"
  },
  {
    "path": "packages/session/session.js",
    "content": "Session = new ReactiveDict('session');\n\n// Documentation here is really awkward because the methods are defined\n// elsewhere\n\n/**\n * @memberOf Session\n * @method set\n * @summary Set a variable in the session. Notify any listeners that the value\n * has changed (eg: redraw templates, and rerun any\n * [`Tracker.autorun`](#tracker_autorun) computations, that called\n * [`Session.get`](#session_get) on this `key`.)\n * @locus Client\n * @param {String} key The key to set, eg, `selectedItem`\n * @param {EJSONable | undefined} value The new value for `key`\n */\n\n/**\n * @memberOf Session\n * @method setDefault\n * @summary Set a variable in the session if it hasn't been set before.\n * Otherwise works exactly the same as [`Session.set`](#session_set).\n * @locus Client\n * @param {String} key The key to set, eg, `selectedItem`\n * @param {EJSONable | undefined} value The new value for `key`\n */\n\n/**\n * @memberOf Session\n * @method get\n * @summary Get the value of a session variable. If inside a [reactive\n * computation](#reactivity), invalidate the computation the next time the\n * value of the variable is changed by [`Session.set`](#session_set). This\n * returns a clone of the session value, so if it's an object or an array,\n * mutating the returned value has no effect on the value stored in the\n * session.\n * @locus Client\n * @param {String} key The name of the session variable to return\n */\n\n/**\n * @memberOf Session\n * @method equals\n * @summary Test if a session variable is equal to a value. If inside a\n * [reactive computation](#reactivity), invalidate the computation the next\n * time the variable changes to or from the value.\n * @locus Client\n * @param {String} key The name of the session variable to test\n * @param {String | Number | Boolean | null | undefined} value The value to\n * test against\n */\n"
  },
  {
    "path": "packages/session/session_tests.js",
    "content": "Tinytest.add('session - setDefault', function (test) {\n  Session.setDefault('def', \"argyle\");\n  test.equal(Session.get('def'), \"argyle\");\n  Session.set('def', \"noodle\");\n  test.equal(Session.get('def'), \"noodle\");\n  Session.set('nondef', \"potato\");\n  test.equal(Session.get('nondef'), \"potato\");\n  Session.setDefault('nondef', \"eggs\");\n  test.equal(Session.get('nondef'), \"potato\");\n  // This is so the test passes the next time, after hot code push.  I know it\n  // doesn't return it to the completely untouched state, but we don't have\n  // Session.clear() yet.  When we do, this should be that.\n  delete Session.keys['def'];\n  delete Session.keys['nondef'];\n});\n\nTinytest.add('session - get/set/equals types', function (test) {\n  test.equal(Session.get('u'), undefined);\n  test.isTrue(Session.equals('u', undefined));\n  test.isFalse(Session.equals('u', null));\n  test.isFalse(Session.equals('u', 0));\n  test.isFalse(Session.equals('u', ''));\n\n  Session.set('u', undefined);\n  test.equal(Session.get('u'), undefined);\n  test.isTrue(Session.equals('u', undefined));\n  test.isFalse(Session.equals('u', null));\n  test.isFalse(Session.equals('u', 0));\n  test.isFalse(Session.equals('u', ''));\n  test.isFalse(Session.equals('u', 'undefined'));\n  test.isFalse(Session.equals('u', 'null'));\n\n  Session.set('n', null);\n  test.equal(Session.get('n'), null);\n  test.isFalse(Session.equals('n', undefined));\n  test.isTrue(Session.equals('n', null));\n  test.isFalse(Session.equals('n', 0));\n  test.isFalse(Session.equals('n', ''));\n  test.isFalse(Session.equals('n', 'undefined'));\n  test.isFalse(Session.equals('n', 'null'));\n\n  Session.set('t', true);\n  test.equal(Session.get('t'), true);\n  test.isTrue(Session.equals('t', true));\n  test.isFalse(Session.equals('t', false));\n  test.isFalse(Session.equals('t', 1));\n  test.isFalse(Session.equals('t', 'true'));\n\n  Session.set('f', false);\n  test.equal(Session.get('f'), false);\n  test.isFalse(Session.equals('f', true));\n  test.isTrue(Session.equals('f', false));\n  test.isFalse(Session.equals('f', 1));\n  test.isFalse(Session.equals('f', 'false'));\n\n  Session.set('num', 0);\n  test.equal(Session.get('num'), 0);\n  test.isTrue(Session.equals('num', 0));\n  test.isFalse(Session.equals('num', false));\n  test.isFalse(Session.equals('num', '0'));\n  test.isFalse(Session.equals('num', 1));\n\n  Session.set('str', 'true');\n  test.equal(Session.get('str'), 'true');\n  test.isTrue(Session.equals('str', 'true'));\n  test.isFalse(Session.equals('str', true));\n\n  Session.set('arr', [1, 2, {a: 1, b: [5, 6]}]);\n  test.equal(Session.get('arr'), [1, 2, {b: [5, 6], a: 1}]);\n  test.isFalse(Session.equals('arr', 1));\n  test.isFalse(Session.equals('arr', '[1,2,{\"a\":1,\"b\":[5,6]}]'));\n  test.throws(function () {\n    Session.equals('arr', [1, 2, {a: 1, b: [5, 6]}]);\n  });\n\n  Session.set('obj', {a: 1, b: [5, 6]});\n  test.equal(Session.get('obj'), {b: [5, 6], a: 1});\n  test.isFalse(Session.equals('obj', 1));\n  test.isFalse(Session.equals('obj', '{\"a\":1,\"b\":[5,6]}'));\n  test.throws(function() { Session.equals('obj', {a: 1, b: [5, 6]}); });\n\n\n  Session.set('date', new Date(1234));\n  test.equal(Session.get('date'), new Date(1234));\n  test.isFalse(Session.equals('date', new Date(3455)));\n  test.isTrue(Session.equals('date', new Date(1234)));\n\n  Session.set('oid', new Mongo.ObjectID('ffffffffffffffffffffffff'));\n  test.equal(Session.get('oid'),  new Mongo.ObjectID('ffffffffffffffffffffffff'));\n  test.isFalse(Session.equals('oid',  new Mongo.ObjectID('fffffffffffffffffffffffa')));\n  test.isTrue(Session.equals('oid', new Mongo.ObjectID('ffffffffffffffffffffffff')));\n});\n\nTinytest.add('session - objects are cloned', function (test) {\n  Session.set('frozen-array', [1, 2, 3]);\n  Session.get('frozen-array')[1] = 42;\n  test.equal(Session.get('frozen-array'), [1, 2, 3]);\n\n  Session.set('frozen-object', {a: 1, b: 2});\n  Session.get('frozen-object').a = 43;\n  test.equal(Session.get('frozen-object'), {a: 1, b: 2});\n});\n\nTinytest.add('session - context invalidation for get', function (test) {\n  var xGetExecutions = 0;\n  Tracker.autorun(function () {\n    ++xGetExecutions;\n    Session.get('x');\n  });\n  test.equal(xGetExecutions, 1);\n  Session.set('x', 1);\n  // Invalidation shouldn't happen until flush time.\n  test.equal(xGetExecutions, 1);\n  Tracker.flush();\n  test.equal(xGetExecutions, 2);\n  // Setting to the same value doesn't re-run.\n  Session.set('x', 1);\n  Tracker.flush();\n  test.equal(xGetExecutions, 2);\n  Session.set('x', '1');\n  Tracker.flush();\n  test.equal(xGetExecutions, 3);\n});\n\nTinytest.add('session - context invalidation for equals', function (test) {\n  var xEqualsExecutions = 0;\n  Tracker.autorun(function () {\n    ++xEqualsExecutions;\n    Session.equals('x', 5);\n  });\n  test.equal(xEqualsExecutions, 1);\n  Session.set('x', 1);\n  Tracker.flush();\n  // Changing undefined -> 1 shouldn't affect equals(5).\n  test.equal(xEqualsExecutions, 1);\n  Session.set('x', 5);\n  // Invalidation shouldn't happen until flush time.\n  test.equal(xEqualsExecutions, 1);\n  Tracker.flush();\n  test.equal(xEqualsExecutions, 2);\n  Session.set('x', 5);\n  Tracker.flush();\n  // Setting to the same value doesn't re-run.\n  test.equal(xEqualsExecutions, 2);\n  Session.set('x', '5');\n  test.equal(xEqualsExecutions, 2);\n  Tracker.flush();\n  test.equal(xEqualsExecutions, 3);\n  Session.set('x', 5);\n  test.equal(xEqualsExecutions, 3);\n  Tracker.flush();\n  test.equal(xEqualsExecutions, 4);\n});\n\nTinytest.add(\n  'session - context invalidation for equals with undefined',\n  function (test) {\n    // Make sure the special casing for equals undefined works.\n    var yEqualsExecutions = 0;\n    Tracker.autorun(function () {\n      ++yEqualsExecutions;\n      Session.equals('y', undefined);\n    });\n    test.equal(yEqualsExecutions, 1);\n    Session.set('y', undefined);\n    Tracker.flush();\n    test.equal(yEqualsExecutions, 1);\n    Session.set('y', 5);\n    test.equal(yEqualsExecutions, 1);\n    Tracker.flush();\n    test.equal(yEqualsExecutions, 2);\n    Session.set('y', 3);\n    Tracker.flush();\n    test.equal(yEqualsExecutions, 2);\n    Session.set('y', 'undefined');\n    Tracker.flush();\n    test.equal(yEqualsExecutions, 2);\n    Session.set('y', undefined);\n    test.equal(yEqualsExecutions, 2);\n    Tracker.flush();\n    test.equal(yEqualsExecutions, 3);\n  });\n\nTinytest.add('session - parse an object of key/value pairs', function (test) {\n  Session._setObject({fruit: 'apple', vegetable: 'potato'});\n\n  test.equal(Session.get('fruit'), 'apple');\n  test.equal(Session.get('vegetable'), 'potato');\n\n  delete Session.keys['fruit'];\n  delete Session.keys['vegetable'];\n});\n"
  },
  {
    "path": "packages/sha/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/sha/README.md",
    "content": "An implementation of the [SHA256](https://en.wikipedia.org/wiki/SHA-2) secure hash function, available in all environments.\n\n## Usage\n\n`SHA256(string)`\n\n## Example\n\n`SHA256('meteor')`\n\n> \"647d177cca8601046a3cb39e12f55bec5790bfcbc42199dd5fcf063200fac1d0\"\n"
  },
  {
    "path": "packages/sha/package.js",
    "content": "Package.describe({\n  version: '1.0.8',\n  summary: 'SHA256 implementation',\n  git: 'https://github.com/meteor/meteor'\n});\n\nPackage.onUse(function (api) {\n  api.export('SHA256');\n  api.addFiles('sha256.js');\n});\n"
  },
  {
    "path": "packages/sha/sha256.js",
    "content": "/// METEOR WRAPPER\n//\nSHA256 = (function () {\n\n\n/**\n*\n*  Secure Hash Algorithm (SHA256)\n*  http://www.webtoolkit.info/javascript-sha256.html\n*  http://anmar.eu.org/projects/jssha2/\n*\n*  Original code by Angel Marin, Paul Johnston.\n*\n**/\n\nfunction SHA256(s){\n\n\tvar chrsz   = 8;\n\tvar hexcase = 0;\n\n\tfunction safe_add (x, y) {\n\t\tvar lsw = (x & 0xFFFF) + (y & 0xFFFF);\n\t\tvar msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n\t\treturn (msw << 16) | (lsw & 0xFFFF);\n\t}\n\n\tfunction S (X, n) { return ( X >>> n ) | (X << (32 - n)); }\n\tfunction R (X, n) { return ( X >>> n ); }\n\tfunction Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); }\n\tfunction Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); }\n\tfunction Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); }\n\tfunction Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); }\n\tfunction Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); }\n\tfunction Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); }\n\n\tfunction core_sha256 (m, l) {\n\t\tvar K = new Array(0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2);\n\t\tvar HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);\n\t\tvar W = new Array(64);\n\t\tvar a, b, c, d, e, f, g, h, i, j;\n\t\tvar T1, T2;\n\n\t\tm[l >> 5] |= 0x80 << (24 - l % 32);\n\t\tm[((l + 64 >> 9) << 4) + 15] = l;\n\n\t\tfor ( var i = 0; i<m.length; i+=16 ) {\n\t\t\ta = HASH[0];\n\t\t\tb = HASH[1];\n\t\t\tc = HASH[2];\n\t\t\td = HASH[3];\n\t\t\te = HASH[4];\n\t\t\tf = HASH[5];\n\t\t\tg = HASH[6];\n\t\t\th = HASH[7];\n\n\t\t\tfor ( var j = 0; j<64; j++) {\n\t\t\t\tif (j < 16) W[j] = m[j + i];\n\t\t\t\telse W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);\n\n\t\t\t\tT1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);\n\t\t\t\tT2 = safe_add(Sigma0256(a), Maj(a, b, c));\n\n\t\t\t\th = g;\n\t\t\t\tg = f;\n\t\t\t\tf = e;\n\t\t\t\te = safe_add(d, T1);\n\t\t\t\td = c;\n\t\t\t\tc = b;\n\t\t\t\tb = a;\n\t\t\t\ta = safe_add(T1, T2);\n\t\t\t}\n\n\t\t\tHASH[0] = safe_add(a, HASH[0]);\n\t\t\tHASH[1] = safe_add(b, HASH[1]);\n\t\t\tHASH[2] = safe_add(c, HASH[2]);\n\t\t\tHASH[3] = safe_add(d, HASH[3]);\n\t\t\tHASH[4] = safe_add(e, HASH[4]);\n\t\t\tHASH[5] = safe_add(f, HASH[5]);\n\t\t\tHASH[6] = safe_add(g, HASH[6]);\n\t\t\tHASH[7] = safe_add(h, HASH[7]);\n\t\t}\n\t\treturn HASH;\n\t}\n\n\tfunction str2binb (str) {\n\t\tvar bin = Array();\n\t\tvar mask = (1 << chrsz) - 1;\n\t\tfor(var i = 0; i < str.length * chrsz; i += chrsz) {\n\t\t\tbin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);\n\t\t}\n\t\treturn bin;\n\t}\n\n\tfunction Utf8Encode(string) {\n\t\t// METEOR change:\n\t\t// The webtoolkit.info version of this code added this\n\t\t// Utf8Encode function (which does seem necessary for dealing\n\t\t// with arbitrary Unicode), but the following line seems\n\t\t// problematic:\n\t\t//\n\t\t// string = string.replace(/\\r\\n/g,\"\\n\");\n\t\tvar utftext = \"\";\n\n\t\tfor (var n = 0; n < string.length; n++) {\n\n\t\t\tvar c = string.charCodeAt(n);\n\n\t\t\tif (c < 128) {\n\t\t\t\tutftext += String.fromCharCode(c);\n\t\t\t}\n\t\t\telse if((c > 127) && (c < 2048)) {\n\t\t\t\tutftext += String.fromCharCode((c >> 6) | 192);\n\t\t\t\tutftext += String.fromCharCode((c & 63) | 128);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tutftext += String.fromCharCode((c >> 12) | 224);\n\t\t\t\tutftext += String.fromCharCode(((c >> 6) & 63) | 128);\n\t\t\t\tutftext += String.fromCharCode((c & 63) | 128);\n\t\t\t}\n\n\t\t}\n\n\t\treturn utftext;\n\t}\n\n\tfunction binb2hex (binarray) {\n\t\tvar hex_tab = hexcase ? \"0123456789ABCDEF\" : \"0123456789abcdef\";\n\t\tvar str = \"\";\n\t\tfor(var i = 0; i < binarray.length * 4; i++) {\n\t\t\tstr += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +\n\t\t\thex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);\n\t\t}\n\t\treturn str;\n\t}\n\n\ts = Utf8Encode(s);\n\treturn binb2hex(core_sha256(str2binb(s), s.length * chrsz));\n\n}\n\n/// METEOR WRAPPER\nreturn SHA256;\n})();\n"
  },
  {
    "path": "packages/showdown/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/showdown/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/showdown/package.js",
    "content": "Package.describe({\n  summary: \"Moved to the 'markdown' package\",\n  version: '1.0.8'\n});\n\nPackage.onUse(function (api) {\n  api.imply(\"markdown\");\n});\n"
  },
  {
    "path": "packages/spacebars/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/spacebars/README.md",
    "content": "# Spacebars\n\nSpacebars is a Meteor template language inspired by\n[Handlebars](http://handlebarsjs.com/).  It shares some of the spirit and syntax\nof Handlebars, but it has been tailored to produce reactive Meteor templates\nwhen compiled.\n\n\nRead more at http://docs.meteor.com/packages/spacebars.html\n"
  },
  {
    "path": "packages/spacebars/package.js",
    "content": "Package.describe({\n  summary: \"Handlebars-like template language for Meteor\",\n  version: '1.0.12'\n});\n\n// For more, see package `spacebars-compiler`, which is used by\n// the build plugin and not shipped to the client unless you\n// ask for it by name.\n//\n// The Spacebars build plugin is in package `templating`.\n//\n// Additional tests are in `spacebars-tests`.\n\nPackage.onUse(function (api) {\n  api.export('Spacebars');\n\n  api.use('htmljs');\n  api.use('tracker');\n  api.use('blaze');\n  api.use('observe-sequence');\n  api.use('underscore');\n  api.addFiles(['spacebars-runtime.js']);\n});\n"
  },
  {
    "path": "packages/spacebars/spacebars-runtime.js",
    "content": "Spacebars = {};\n\nvar tripleEquals = function (a, b) { return a === b; };\n\nSpacebars.include = function (templateOrFunction, contentFunc, elseFunc) {\n  if (! templateOrFunction)\n    return null;\n\n  if (typeof templateOrFunction !== 'function') {\n    var template = templateOrFunction;\n    if (! Blaze.isTemplate(template))\n      throw new Error(\"Expected template or null, found: \" + template);\n    var view = templateOrFunction.constructView(contentFunc, elseFunc);\n    view.__startsNewLexicalScope = true;\n    return view;\n  }\n\n  var templateVar = Blaze.ReactiveVar(null, tripleEquals);\n  var view = Blaze.View('Spacebars.include', function () {\n    var template = templateVar.get();\n    if (template === null)\n      return null;\n\n    if (! Blaze.isTemplate(template))\n      throw new Error(\"Expected template or null, found: \" + template);\n\n    return template.constructView(contentFunc, elseFunc);\n  });\n  view.__templateVar = templateVar;\n  view.onViewCreated(function () {\n    this.autorun(function () {\n      templateVar.set(templateOrFunction());\n    });\n  });\n  view.__startsNewLexicalScope = true;\n\n  return view;\n};\n\n// Executes `{{foo bar baz}}` when called on `(foo, bar, baz)`.\n// If `bar` and `baz` are functions, they are called before\n// `foo` is called on them.\n//\n// This is the shared part of Spacebars.mustache and\n// Spacebars.attrMustache, which differ in how they post-process the\n// result.\nSpacebars.mustacheImpl = function (value/*, args*/) {\n  var args = arguments;\n  // if we have any arguments (pos or kw), add an options argument\n  // if there isn't one.\n  if (args.length > 1) {\n    var kw = args[args.length - 1];\n    if (! (kw instanceof Spacebars.kw)) {\n      kw = Spacebars.kw();\n      // clone arguments into an actual array, then push\n      // the empty kw object.\n      args = Array.prototype.slice.call(arguments);\n      args.push(kw);\n    } else {\n      // For each keyword arg, call it if it's a function\n      var newHash = {};\n      for (var k in kw.hash) {\n        var v = kw.hash[k];\n        newHash[k] = (typeof v === 'function' ? v() : v);\n      }\n      args[args.length - 1] = Spacebars.kw(newHash);\n    }\n  }\n\n  return Spacebars.call.apply(null, args);\n};\n\nSpacebars.mustache = function (value/*, args*/) {\n  var result = Spacebars.mustacheImpl.apply(null, arguments);\n\n  if (result instanceof Spacebars.SafeString)\n    return HTML.Raw(result.toString());\n  else\n    // map `null`, `undefined`, and `false` to null, which is important\n    // so that attributes with nully values are considered absent.\n    // stringify anything else (e.g. strings, booleans, numbers including 0).\n    return (result == null || result === false) ? null : String(result);\n};\n\nSpacebars.attrMustache = function (value/*, args*/) {\n  var result = Spacebars.mustacheImpl.apply(null, arguments);\n\n  if (result == null || result === '') {\n    return null;\n  } else if (typeof result === 'object') {\n    return result;\n  } else if (typeof result === 'string' && HTML.isValidAttributeName(result)) {\n    var obj = {};\n    obj[result] = '';\n    return obj;\n  } else {\n    throw new Error(\"Expected valid attribute name, '', null, or object\");\n  }\n};\n\nSpacebars.dataMustache = function (value/*, args*/) {\n  var result = Spacebars.mustacheImpl.apply(null, arguments);\n\n  return result;\n};\n\n// Idempotently wrap in `HTML.Raw`.\n//\n// Called on the return value from `Spacebars.mustache` in case the\n// template uses triple-stache (`{{{foo bar baz}}}`).\nSpacebars.makeRaw = function (value) {\n  if (value == null) // null or undefined\n    return null;\n  else if (value instanceof HTML.Raw)\n    return value;\n  else\n    return HTML.Raw(value);\n};\n\n// If `value` is a function, evaluate its `args` (by calling them, if they\n// are functions), and then call it on them. Otherwise, return `value`.\n//\n// If `value` is not a function and is not null, then this method will assert\n// that there are no args. We check for null before asserting because a user\n// may write a template like {{user.fullNameWithPrefix 'Mr.'}}, where the\n// function will be null until data is ready.\nSpacebars.call = function (value/*, args*/) {\n  if (typeof value === 'function') {\n    // Evaluate arguments by calling them if they are functions.\n    var newArgs = [];\n    for (var i = 1; i < arguments.length; i++) {\n      var arg = arguments[i];\n      newArgs[i-1] = (typeof arg === 'function' ? arg() : arg);\n    }\n\n    return value.apply(null, newArgs);\n  } else {\n    if (value != null && arguments.length > 1) {\n      throw new Error(\"Can't call non-function: \" + value);\n    }\n    return value;\n  }\n};\n\n// Call this as `Spacebars.kw({ ... })`.  The return value\n// is `instanceof Spacebars.kw`.\nSpacebars.kw = function (hash) {\n  if (! (this instanceof Spacebars.kw))\n    // called without new; call with new\n    return new Spacebars.kw(hash);\n\n  this.hash = hash || {};\n};\n\n// Call this as `Spacebars.SafeString(\"some HTML\")`.  The return value\n// is `instanceof Spacebars.SafeString` (and `instanceof Handlebars.SafeString).\nSpacebars.SafeString = function (html) {\n  if (! (this instanceof Spacebars.SafeString))\n    // called without new; call with new\n    return new Spacebars.SafeString(html);\n\n  return new Handlebars.SafeString(html);\n};\nSpacebars.SafeString.prototype = Handlebars.SafeString.prototype;\n\n// `Spacebars.dot(foo, \"bar\", \"baz\")` performs a special kind\n// of `foo.bar.baz` that allows safe indexing of `null` and\n// indexing of functions (which calls the function).  If the\n// result is a function, it is always a bound function (e.g.\n// a wrapped version of `baz` that always uses `foo.bar` as\n// `this`).\n//\n// In `Spacebars.dot(foo, \"bar\")`, `foo` is assumed to be either\n// a non-function value or a \"fully-bound\" function wrapping a value,\n// where fully-bound means it takes no arguments and ignores `this`.\n//\n// `Spacebars.dot(foo, \"bar\")` performs the following steps:\n//\n// * If `foo` is falsy, return `foo`.\n//\n// * If `foo` is a function, call it (set `foo` to `foo()`).\n//\n// * If `foo` is falsy now, return `foo`.\n//\n// * Return `foo.bar`, binding it to `foo` if it's a function.\nSpacebars.dot = function (value, id1/*, id2, ...*/) {\n  if (arguments.length > 2) {\n    // Note: doing this recursively is probably less efficient than\n    // doing it in an iterative loop.\n    var argsForRecurse = [];\n    argsForRecurse.push(Spacebars.dot(value, id1));\n    argsForRecurse.push.apply(argsForRecurse,\n                              Array.prototype.slice.call(arguments, 2));\n    return Spacebars.dot.apply(null, argsForRecurse);\n  }\n\n  if (typeof value === 'function')\n    value = value();\n\n  if (! value)\n    return value; // falsy, don't index, pass through\n\n  var result = value[id1];\n  if (typeof result !== 'function')\n    return result;\n  // `value[id1]` (or `value()[id1]`) is a function.\n  // Bind it so that when called, `value` will be placed in `this`.\n  return function (/*arguments*/) {\n    return result.apply(value, arguments);\n  };\n};\n\n// Spacebars.With implements the conditional logic of rendering\n// the `{{else}}` block if the argument is falsy.  It combines\n// a Blaze.If with a Blaze.With (the latter only in the truthy\n// case, since the else block is evaluated without entering\n// a new data context).\nSpacebars.With = function (argFunc, contentFunc, elseFunc) {\n  var argVar = new Blaze.ReactiveVar;\n  var view = Blaze.View('Spacebars_with', function () {\n    return Blaze.If(function () { return argVar.get(); },\n                    function () { return Blaze.With(function () {\n                      return argVar.get(); }, contentFunc); },\n                    elseFunc);\n  });\n  view.onViewCreated(function () {\n    this.autorun(function () {\n      argVar.set(argFunc());\n\n      // This is a hack so that autoruns inside the body\n      // of the #with get stopped sooner.  It reaches inside\n      // our ReactiveVar to access its dep.\n\n      Tracker.onInvalidate(function () {\n        argVar.dep.changed();\n      });\n\n      // Take the case of `{{#with A}}{{B}}{{/with}}`.  The goal\n      // is to not re-render `B` if `A` changes to become falsy\n      // and `B` is simultaneously invalidated.\n      //\n      // A series of autoruns are involved:\n      //\n      // 1. This autorun (argument to Spacebars.With)\n      // 2. Argument to Blaze.If\n      // 3. Blaze.If view re-render\n      // 4. Argument to Blaze.With\n      // 5. The template tag `{{B}}`\n      //\n      // When (3) is invalidated, it immediately stops (4) and (5)\n      // because of a Tracker.onInvalidate built into materializeView.\n      // (When a View's render method is invalidated, it immediately\n      // tears down all the subviews, via a Tracker.onInvalidate much\n      // like this one.\n      //\n      // Suppose `A` changes to become falsy, and `B` changes at the\n      // same time (i.e. without an intervening flush).\n      // Without the code above, this happens:\n      //\n      // - (1) and (5) are invalidated.\n      // - (1) runs, invalidating (2) and (4).\n      // - (5) runs.\n      // - (2) runs, invalidating (3), stopping (4) and (5).\n      //\n      // With the code above:\n      //\n      // - (1) and (5) are invalidated, invalidating (2) and (4).\n      // - (1) runs.\n      // - (2) runs, invalidating (3), stopping (4) and (5).\n      //\n      // If the re-run of (5) is originally enqueued before (1), all\n      // bets are off, but typically that doesn't seem to be the\n      // case.  Anyway, doing this is always better than not doing it,\n      // because it might save a bunch of DOM from being updated\n      // needlessly.\n    });\n  });\n\n  return view;\n};\n\n// XXX COMPAT WITH 0.9.0\nSpacebars.TemplateWith = Blaze._TemplateWith;\n"
  },
  {
    "path": "packages/spacebars-compiler/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/spacebars-compiler/README.md",
    "content": "# spacebars-compiler\n\nThe Spacebars compiler that is invoked at build time to compile\ntemplates to JavaScript.\n\nWhile this code is not normally ever shipped to the client, it can be\nused at runtime on the server or the client by using the\n`SpacebarsCompiler` symbol from this package.\n\nThe `spacebars` package, in contrast, contains the `Spacebars` symbol\nand the Spacebars runtime, which is shipped to the client as part of\nthe app.\n\nRead more about Spacebars, Blaze, and Meteor templating on the Blaze\n[project page](https://www.meteor.com/blaze).\n"
  },
  {
    "path": "packages/spacebars-compiler/codegen.js",
    "content": "// ============================================================\n// Code-generation of template tags\n\n// The `CodeGen` class currently has no instance state, but in theory\n// it could be useful to track per-function state, like whether we\n// need to emit `var self = this` or not.\nvar CodeGen = SpacebarsCompiler.CodeGen = function () {};\n\nvar builtInBlockHelpers = SpacebarsCompiler._builtInBlockHelpers = {\n  'if': 'Blaze.If',\n  'unless': 'Blaze.Unless',\n  'with': 'Spacebars.With',\n  'each': 'Blaze.Each',\n  'let': 'Blaze.Let'\n};\n\n\n// Mapping of \"macros\" which, when preceded by `Template.`, expand\n// to special code rather than following the lookup rules for dotted\n// symbols.\nvar builtInTemplateMacros = {\n  // `view` is a local variable defined in the generated render\n  // function for the template in which `Template.contentBlock` or\n  // `Template.elseBlock` is invoked.\n  'contentBlock': 'view.templateContentBlock',\n  'elseBlock': 'view.templateElseBlock',\n\n  // Confusingly, this makes `{{> Template.dynamic}}` an alias\n  // for `{{> __dynamic}}`, where \"__dynamic\" is the template that\n  // implements the dynamic template feature.\n  'dynamic': 'Template.__dynamic',\n\n  'subscriptionsReady': 'view.templateInstance().subscriptionsReady()'\n};\n\nvar additionalReservedNames = [\"body\", \"toString\", \"instance\",  \"constructor\",\n  \"toString\", \"toLocaleString\", \"valueOf\", \"hasOwnProperty\", \"isPrototypeOf\",\n  \"propertyIsEnumerable\", \"__defineGetter__\", \"__lookupGetter__\",\n  \"__defineSetter__\", \"__lookupSetter__\", \"__proto__\", \"dynamic\",\n  \"registerHelper\", \"currentData\", \"parentData\"];\n\n// A \"reserved name\" can't be used as a <template> name.  This\n// function is used by the template file scanner.\n//\n// Note that the runtime imposes additional restrictions, for example\n// banning the name \"body\" and names of built-in object properties\n// like \"toString\".\nSpacebarsCompiler.isReservedName = function (name) {\n  return builtInBlockHelpers.hasOwnProperty(name) ||\n    builtInTemplateMacros.hasOwnProperty(name) ||\n    _.indexOf(additionalReservedNames, name) > -1;\n};\n\nvar makeObjectLiteral = function (obj) {\n  var parts = [];\n  for (var k in obj)\n    parts.push(BlazeTools.toObjectLiteralKey(k) + ': ' + obj[k]);\n  return '{' + parts.join(', ') + '}';\n};\n\n_.extend(CodeGen.prototype, {\n  codeGenTemplateTag: function (tag) {\n    var self = this;\n    if (tag.position === HTMLTools.TEMPLATE_TAG_POSITION.IN_START_TAG) {\n      // Special dynamic attributes: `<div {{attrs}}>...`\n      // only `tag.type === 'DOUBLE'` allowed (by earlier validation)\n      return BlazeTools.EmitCode('function () { return ' +\n          self.codeGenMustache(tag.path, tag.args, 'attrMustache')\n          + '; }');\n    } else {\n      if (tag.type === 'DOUBLE' || tag.type === 'TRIPLE') {\n        var code = self.codeGenMustache(tag.path, tag.args);\n        if (tag.type === 'TRIPLE') {\n          code = 'Spacebars.makeRaw(' + code + ')';\n        }\n        if (tag.position !== HTMLTools.TEMPLATE_TAG_POSITION.IN_ATTRIBUTE) {\n          // Reactive attributes are already wrapped in a function,\n          // and there's no fine-grained reactivity.\n          // Anywhere else, we need to create a View.\n          code = 'Blaze.View(' +\n            BlazeTools.toJSLiteral('lookup:' + tag.path.join('.')) + ', ' +\n            'function () { return ' + code + '; })';\n        }\n        return BlazeTools.EmitCode(code);\n      } else if (tag.type === 'INCLUSION' || tag.type === 'BLOCKOPEN') {\n        var path = tag.path;\n        var args = tag.args;\n\n        if (tag.type === 'BLOCKOPEN' &&\n            builtInBlockHelpers.hasOwnProperty(path[0])) {\n          // if, unless, with, each.\n          //\n          // If someone tries to do `{{> if}}`, we don't\n          // get here, but an error is thrown when we try to codegen the path.\n\n          // Note: If we caught these errors earlier, while scanning, we'd be able to\n          // provide nice line numbers.\n          if (path.length > 1)\n            throw new Error(\"Unexpected dotted path beginning with \" + path[0]);\n          if (! args.length)\n            throw new Error(\"#\" + path[0] + \" requires an argument\");\n\n          var dataCode = null;\n          // #each has a special treatment as it features two different forms:\n          // - {{#each people}}\n          // - {{#each person in people}}\n          if (path[0] === 'each' && args.length >= 2 && args[1][0] === 'PATH' &&\n              args[1][1].length && args[1][1][0] === 'in') {\n            // minimum conditions are met for each-in.  now validate this\n            // isn't some weird case.\n            var eachUsage = \"Use either {{#each items}} or \" +\n                  \"{{#each item in items}} form of #each.\";\n            var inArg = args[1];\n            if (! (args.length >= 3 && inArg[1].length === 1)) {\n              // we don't have at least 3 space-separated parts after #each, or\n              // inArg doesn't look like ['PATH',['in']]\n              throw new Error(\"Malformed #each. \" + eachUsage);\n            }\n            // split out the variable name and sequence arguments\n            var variableArg = args[0];\n            if (! (variableArg[0] === \"PATH\" && variableArg[1].length === 1 &&\n                   variableArg[1][0].replace(/\\./g, ''))) {\n              throw new Error(\"Bad variable name in #each\");\n            }\n            var variable = variableArg[1][0];\n            dataCode = 'function () { return { _sequence: ' +\n              self.codeGenInclusionData(args.slice(2)) +\n              ', _variable: ' + BlazeTools.toJSLiteral(variable) + ' }; }';\n          } else if (path[0] === 'let') {\n            var dataProps = {};\n            _.each(args, function (arg) {\n              if (arg.length !== 3) {\n                // not a keyword arg (x=y)\n                throw new Error(\"Incorrect form of #let\");\n              }\n              var argKey = arg[2];\n              dataProps[argKey] =\n                'function () { return Spacebars.call(' +\n                self.codeGenArgValue(arg) + '); }';\n            });\n            dataCode = makeObjectLiteral(dataProps);\n          }\n\n          if (! dataCode) {\n            // `args` must exist (tag.args.length > 0)\n            dataCode = self.codeGenInclusionDataFunc(args) || 'null';\n          }\n\n          // `content` must exist\n          var contentBlock = (('content' in tag) ?\n                              self.codeGenBlock(tag.content) : null);\n          // `elseContent` may not exist\n          var elseContentBlock = (('elseContent' in tag) ?\n                                  self.codeGenBlock(tag.elseContent) : null);\n\n          var callArgs = [dataCode, contentBlock];\n          if (elseContentBlock)\n            callArgs.push(elseContentBlock);\n\n          return BlazeTools.EmitCode(\n            builtInBlockHelpers[path[0]] + '(' + callArgs.join(', ') + ')');\n\n        } else {\n          var compCode = self.codeGenPath(path, {lookupTemplate: true});\n          if (path.length > 1) {\n            // capture reactivity\n            compCode = 'function () { return Spacebars.call(' + compCode +\n              '); }';\n          }\n\n          var dataCode = self.codeGenInclusionDataFunc(tag.args);\n          var content = (('content' in tag) ?\n                         self.codeGenBlock(tag.content) : null);\n          var elseContent = (('elseContent' in tag) ?\n                             self.codeGenBlock(tag.elseContent) : null);\n\n          var includeArgs = [compCode];\n          if (content) {\n            includeArgs.push(content);\n            if (elseContent)\n              includeArgs.push(elseContent);\n          }\n\n          var includeCode =\n                'Spacebars.include(' + includeArgs.join(', ') + ')';\n\n          // calling convention compat -- set the data context around the\n          // entire inclusion, so that if the name of the inclusion is\n          // a helper function, it gets the data context in `this`.\n          // This makes for a pretty confusing calling convention --\n          // In `{{#foo bar}}`, `foo` is evaluated in the context of `bar`\n          // -- but it's what we shipped for 0.8.0.  The rationale is that\n          // `{{#foo bar}}` is sugar for `{{#with bar}}{{#foo}}...`.\n          if (dataCode) {\n            includeCode =\n              'Blaze._TemplateWith(' + dataCode + ', function () { return ' +\n              includeCode + '; })';\n          }\n\n          // XXX BACK COMPAT - UI is the old name, Template is the new\n          if ((path[0] === 'UI' || path[0] === 'Template') &&\n              (path[1] === 'contentBlock' || path[1] === 'elseBlock')) {\n            // Call contentBlock and elseBlock in the appropriate scope\n            includeCode = 'Blaze._InOuterTemplateScope(view, function () { return '\n              + includeCode + '; })';\n          }\n\n          return BlazeTools.EmitCode(includeCode);\n        }\n      } else if (tag.type === 'ESCAPE') {\n        return tag.value;\n      } else {\n        // Can't get here; TemplateTag validation should catch any\n        // inappropriate tag types that might come out of the parser.\n        throw new Error(\"Unexpected template tag type: \" + tag.type);\n      }\n    }\n  },\n\n  // `path` is an array of at least one string.\n  //\n  // If `path.length > 1`, the generated code may be reactive\n  // (i.e. it may invalidate the current computation).\n  //\n  // No code is generated to call the result if it's a function.\n  //\n  // Options:\n  //\n  // - lookupTemplate {Boolean} If true, generated code also looks in\n  //   the list of templates. (After helpers, before data context).\n  //   Used when generating code for `{{> foo}}` or `{{#foo}}`. Only\n  //   used for non-dotted paths.\n  codeGenPath: function (path, opts) {\n    if (builtInBlockHelpers.hasOwnProperty(path[0]))\n      throw new Error(\"Can't use the built-in '\" + path[0] + \"' here\");\n    // Let `{{#if Template.contentBlock}}` check whether this template was\n    // invoked via inclusion or as a block helper, in addition to supporting\n    // `{{> Template.contentBlock}}`.\n    // XXX BACK COMPAT - UI is the old name, Template is the new\n    if (path.length >= 2 &&\n        (path[0] === 'UI' || path[0] === 'Template')\n        && builtInTemplateMacros.hasOwnProperty(path[1])) {\n      if (path.length > 2)\n        throw new Error(\"Unexpected dotted path beginning with \" +\n                        path[0] + '.' + path[1]);\n      return builtInTemplateMacros[path[1]];\n    }\n\n    var firstPathItem = BlazeTools.toJSLiteral(path[0]);\n    var lookupMethod = 'lookup';\n    if (opts && opts.lookupTemplate && path.length === 1)\n      lookupMethod = 'lookupTemplate';\n    var code = 'view.' + lookupMethod + '(' + firstPathItem + ')';\n\n    if (path.length > 1) {\n      code = 'Spacebars.dot(' + code + ', ' +\n        _.map(path.slice(1), BlazeTools.toJSLiteral).join(', ') + ')';\n    }\n\n    return code;\n  },\n\n  // Generates code for an `[argType, argValue]` argument spec,\n  // ignoring the third element (keyword argument name) if present.\n  //\n  // The resulting code may be reactive (in the case of a PATH of\n  // more than one element) and is not wrapped in a closure.\n  codeGenArgValue: function (arg) {\n    var self = this;\n\n    var argType = arg[0];\n    var argValue = arg[1];\n\n    var argCode;\n    switch (argType) {\n    case 'STRING':\n    case 'NUMBER':\n    case 'BOOLEAN':\n    case 'NULL':\n      argCode = BlazeTools.toJSLiteral(argValue);\n      break;\n    case 'PATH':\n      argCode = self.codeGenPath(argValue);\n      break;\n    case 'EXPR':\n      // The format of EXPR is ['EXPR', { type: 'EXPR', path: [...], args: { ... } }]\n      argCode = self.codeGenMustache(argValue.path, argValue.args, 'dataMustache');\n      break;\n    default:\n      // can't get here\n      throw new Error(\"Unexpected arg type: \" + argType);\n    }\n\n    return argCode;\n  },\n\n  // Generates a call to `Spacebars.fooMustache` on evaluated arguments.\n  // The resulting code has no function literals and must be wrapped in\n  // one for fine-grained reactivity.\n  codeGenMustache: function (path, args, mustacheType) {\n    var self = this;\n\n    var nameCode = self.codeGenPath(path);\n    var argCode = self.codeGenMustacheArgs(args);\n    var mustache = (mustacheType || 'mustache');\n\n    return 'Spacebars.' + mustache + '(' + nameCode +\n      (argCode ? ', ' + argCode.join(', ') : '') + ')';\n  },\n\n  // returns: array of source strings, or null if no\n  // args at all.\n  codeGenMustacheArgs: function (tagArgs) {\n    var self = this;\n\n    var kwArgs = null; // source -> source\n    var args = null; // [source]\n\n    // tagArgs may be null\n    _.each(tagArgs, function (arg) {\n      var argCode = self.codeGenArgValue(arg);\n\n      if (arg.length > 2) {\n        // keyword argument (represented as [type, value, name])\n        kwArgs = (kwArgs || {});\n        kwArgs[arg[2]] = argCode;\n      } else {\n        // positional argument\n        args = (args || []);\n        args.push(argCode);\n      }\n    });\n\n    // put kwArgs in options dictionary at end of args\n    if (kwArgs) {\n      args = (args || []);\n      args.push('Spacebars.kw(' + makeObjectLiteral(kwArgs) + ')');\n    }\n\n    return args;\n  },\n\n  codeGenBlock: function (content) {\n    return SpacebarsCompiler.codeGen(content);\n  },\n\n  codeGenInclusionData: function (args) {\n    var self = this;\n\n    if (! args.length) {\n      // e.g. `{{#foo}}`\n      return null;\n    } else if (args[0].length === 3) {\n      // keyword arguments only, e.g. `{{> point x=1 y=2}}`\n      var dataProps = {};\n      _.each(args, function (arg) {\n        var argKey = arg[2];\n        dataProps[argKey] = 'Spacebars.call(' + self.codeGenArgValue(arg) + ')';\n      });\n      return makeObjectLiteral(dataProps);\n    } else if (args[0][0] !== 'PATH') {\n      // literal first argument, e.g. `{{> foo \"blah\"}}`\n      //\n      // tag validation has confirmed, in this case, that there is only\n      // one argument (`args.length === 1`)\n      return self.codeGenArgValue(args[0]);\n    } else if (args.length === 1) {\n      // one argument, must be a PATH\n      return 'Spacebars.call(' + self.codeGenPath(args[0][1]) + ')';\n    } else {\n      // Multiple positional arguments; treat them as a nested\n      // \"data mustache\"\n      return self.codeGenMustache(args[0][1], args.slice(1),\n                                  'dataMustache');\n    }\n\n  },\n\n  codeGenInclusionDataFunc: function (args) {\n    var self = this;\n    var dataCode = self.codeGenInclusionData(args);\n    if (dataCode) {\n      return 'function () { return ' + dataCode + '; }';\n    } else {\n      return null;\n    }\n  }\n\n});\n"
  },
  {
    "path": "packages/spacebars-compiler/compile_tests.js",
    "content": "Tinytest.add(\"spacebars-compiler - compiler output\", function (test) {\n\n  var run = function (input, expected) {\n    if (expected.fail) {\n      var expectedMessage = expected.fail;\n      // test for error starting with expectedMessage\n      var msg = '';\n      test.throws(function () {\n        try {\n          SpacebarsCompiler.compile(input, {isTemplate: true});\n        } catch (e) {\n          msg = e.message;\n          throw e;\n        }\n      });\n      test.equal(msg.slice(0, expectedMessage.length),\n                 expectedMessage);\n    } else {\n      var output = SpacebarsCompiler.compile(input, {isTemplate: true});\n      var postProcess = function (string) {\n        // remove initial and trailing parens\n        string = string.replace(/^\\(([\\S\\s]*)\\)$/, '$1');\n        if (! (Package['minifier-js'] && Package['minifier-js'].UglifyJSMinify)) {\n          // these tests work a lot better with access to beautification,\n          // but let's at least do some sort of test without it.\n          // These regexes may have to be adjusted if new tests are added.\n\n          // Remove single-line comments, including line nums from build system.\n          string = string.replace(/\\/\\/.*$/mg, '');\n          string = string.replace(/\\s+/g, ''); // kill whitespace\n        }\n        return string;\n      };\n      // compare using Function .toString()!\n      test._stringEqual(\n        postProcess(output.toString()),\n        postProcess(\n          SpacebarsCompiler._beautify('(' + expected.toString() + ')')),\n        input);\n    }\n  };\n\n  coffee.runCompilerOutputTests(run);\n});\n\ncoffee = {\n  runCompilerOutputTests: null // implemented in compiler_output_tests.coffee\n};\n\n\nTinytest.add(\"spacebars-compiler - compiler errors\", function (test) {\n\n  var getError = function (input) {\n    try {\n      SpacebarsCompiler.compile(input);\n    } catch (e) {\n      return e.message;\n    }\n    test.fail(\"Didn't throw an error: \" + input);\n    return '';\n  };\n\n  var assertStartsWith = function (a, b) {\n    test.equal(a.substring(0, b.length), b);\n  };\n\n  var isError = function (input, errorStart) {\n    assertStartsWith(getError(input), errorStart);\n  };\n\n  isError(\"<input></input>\",\n          \"Unexpected HTML close tag.  <input> should have no close tag.\");\n  isError(\"{{#each foo}}<input></input>{{/foo}}\",\n          \"Unexpected HTML close tag.  <input> should have no close tag.\");\n\n  isError(\"{{#if}}{{/if}}\", \"#if requires an argument\");\n  isError(\"{{#with}}{{/with}}\", \"#with requires an argument\");\n  isError(\"{{#each}}{{/each}}\", \"#each requires an argument\");\n  isError(\"{{#unless}}{{/unless}}\", \"#unless requires an argument\");\n\n  isError(\"{{0 0}}\", \"Expected IDENTIFIER\");\n\n  isError(\"{{> foo 0 0}}\",\n          \"First argument must be a function\");\n  isError(\"{{> foo 0 x=0}}\",\n          \"First argument must be a function\");\n  isError(\"{{#foo 0 0}}{{/foo}}\",\n          \"First argument must be a function\");\n  isError(\"{{#foo 0 x=0}}{{/foo}}\",\n          \"First argument must be a function\");\n\n  _.each(['asdf</br>', '{{!foo}}</br>', '{{!foo}} </br>',\n          'asdf</a>', '{{!foo}}</a>', '{{!foo}} </a>'], function (badFrag) {\n            isError(badFrag, \"Unexpected HTML close tag\");\n          });\n\n  isError(\"{{#let myHelper}}{{/let}}\", \"Incorrect form of #let\");\n  isError(\"{{#each foo in.in bar}}{{/each}}\", \"Malformed #each\");\n  isError(\"{{#each foo.bar in baz}}{{/each}}\", \"Bad variable name in #each\");\n  isError(\"{{#each ../foo in baz}}{{/each}}\", \"Bad variable name in #each\");\n  isError(\"{{#each 3 in baz}}{{/each}}\", \"Bad variable name in #each\");\n\n  // errors using `{{> React}}`\n  isError(\"{{> React component=emptyComponent}}\",\n          \"{{> React}} must be used in a container element\");\n  isError(\"<div>{{#if include}}{{> React component=emptyComponent}}{{/if}}</div>\",\n          \"{{> React}} must be used in a container element\");\n  isError(\"<div><div>Sibling</div>{{> React component=emptyComponent}}</div>\",\n          \"{{> React}} must be used as the only child in a container element\");\n  isError(\"<div>Sibling{{> React component=emptyComponent}}</div>\",\n          \"{{> React}} must be used as the only child in a container element\");\n  isError(\"<div>{{#if sibling}}Sibling{{/if}}{{> React component=emptyComponent}}</div>\",\n          \"{{> React}} must be used as the only child in a container element\");\n});\n"
  },
  {
    "path": "packages/spacebars-compiler/compiler.js",
    "content": "\nSpacebarsCompiler.parse = function (input) {\n\n  var tree = HTMLTools.parseFragment(\n    input,\n    { getTemplateTag: TemplateTag.parseCompleteTag });\n\n  return tree;\n};\n\nSpacebarsCompiler.compile = function (input, options) {\n  var tree = SpacebarsCompiler.parse(input);\n  return SpacebarsCompiler.codeGen(tree, options);\n};\n\nSpacebarsCompiler._TemplateTagReplacer = HTML.TransformingVisitor.extend();\nSpacebarsCompiler._TemplateTagReplacer.def({\n  visitObject: function (x) {\n    if (x instanceof HTMLTools.TemplateTag) {\n\n      // Make sure all TemplateTags in attributes have the right\n      // `.position` set on them.  This is a bit of a hack\n      // (we shouldn't be mutating that here), but it allows\n      // cleaner codegen of \"synthetic\" attributes like TEXTAREA's\n      // \"value\", where the template tags were originally not\n      // in an attribute.\n      if (this.inAttributeValue)\n        x.position = HTMLTools.TEMPLATE_TAG_POSITION.IN_ATTRIBUTE;\n\n      return this.codegen.codeGenTemplateTag(x);\n    }\n\n    return HTML.TransformingVisitor.prototype.visitObject.call(this, x);\n  },\n  visitAttributes: function (attrs) {\n    if (attrs instanceof HTMLTools.TemplateTag)\n      return this.codegen.codeGenTemplateTag(attrs);\n\n    // call super (e.g. for case where `attrs` is an array)\n    return HTML.TransformingVisitor.prototype.visitAttributes.call(this, attrs);\n  },\n  visitAttribute: function (name, value, tag) {\n    this.inAttributeValue = true;\n    var result = this.visit(value);\n    this.inAttributeValue = false;\n\n    if (result !== value) {\n      // some template tags must have been replaced, because otherwise\n      // we try to keep things `===` when transforming.  Wrap the code\n      // in a function as per the rules.  You can't have\n      // `{id: Blaze.View(...)}` as an attributes dict because the View\n      // would be rendered more than once; you need to wrap it in a function\n      // so that it's a different View each time.\n      return BlazeTools.EmitCode(this.codegen.codeGenBlock(result));\n    }\n    return result;\n  }\n});\n\nSpacebarsCompiler.codeGen = function (parseTree, options) {\n  // is this a template, rather than a block passed to\n  // a block helper, say\n  var isTemplate = (options && options.isTemplate);\n  var isBody = (options && options.isBody);\n  var sourceName = (options && options.sourceName);\n\n  var tree = parseTree;\n\n  // The flags `isTemplate` and `isBody` are kind of a hack.\n  if (isTemplate || isBody) {\n    // optimizing fragments would require being smarter about whether we are\n    // in a TEXTAREA, say.\n    tree = SpacebarsCompiler.optimize(tree);\n  }\n\n  // throws an error if using `{{> React}}` with siblings\n  new ReactComponentSiblingForbidder({sourceName: sourceName})\n    .visit(tree);\n\n  var codegen = new SpacebarsCompiler.CodeGen;\n  tree = (new SpacebarsCompiler._TemplateTagReplacer(\n    {codegen: codegen})).visit(tree);\n\n  var code = '(function () { ';\n  if (isTemplate || isBody) {\n    code += 'var view = this; ';\n  }\n  code += 'return ';\n  code += BlazeTools.toJS(tree);\n  code += '; })';\n\n  code = SpacebarsCompiler._beautify(code);\n\n  return code;\n};\n\nSpacebarsCompiler._beautify = function (code) {\n  if (Package['minifier-js'] && Package['minifier-js'].UglifyJSMinify) {\n    var result = Package['minifier-js'].UglifyJSMinify(\n      code,\n      { fromString: true,\n        mangle: false,\n        compress: false,\n        output: { beautify: true,\n                  indent_level: 2,\n                  width: 80 } });\n    var output = result.code;\n    // Uglify interprets our expression as a statement and may add a semicolon.\n    // Strip trailing semicolon.\n    output = output.replace(/;$/, '');\n    return output;\n  } else {\n    // don't actually beautify; no UglifyJS\n    return code;\n  }\n};\n"
  },
  {
    "path": "packages/spacebars-compiler/compiler_output_tests.coffee",
    "content": "coffee.runCompilerOutputTests = (run) ->\n  run \"abc\",\n  \"\"\"\n  function () {\n    var view = this;\n    return \"abc\";\n  }\n  \"\"\"\n\n  run \"{{foo}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze.View(\"lookup:foo\", function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    });\n  }\n  \"\"\"\n\n  run \"{{foo bar}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze.View(\"lookup:foo\", function() {\n      return Spacebars.mustache(view.lookup(\"foo\"),\n                                view.lookup(\"bar\"));\n    });\n  }\n  \"\"\"\n\n  run \"{{foo x=bar}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze.View(\"lookup:foo\", function() {\n      return Spacebars.mustache(view.lookup(\"foo\"), Spacebars.kw({\n        x: view.lookup(\"bar\")\n      }));\n    });\n  }\n  \"\"\"\n\n  run \"{{foo.bar baz}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze.View(\"lookup:foo.bar\", function() {\n      return Spacebars.mustache(Spacebars.dot(\n               view.lookup(\"foo\"), \"bar\"),\n               view.lookup(\"baz\"));\n    });\n  }\n  \"\"\"\n\n  run \"{{foo.bar (baz qux)}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze.View(\"lookup:foo.bar\", function() {\n      return Spacebars.mustache(Spacebars.dot(\n               view.lookup(\"foo\"), \"bar\"),\n               Spacebars.dataMustache(view.lookup(\"baz\"), view.lookup(\"qux\")));\n    });\n  }\n  \"\"\"\n\n\n  run \"{{foo bar.baz}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze.View(\"lookup:foo\", function() {\n      return Spacebars.mustache(view.lookup(\"foo\"),\n             Spacebars.dot(view.lookup(\"bar\"), \"baz\"));\n    });\n  }\n  \"\"\"\n\n  run \"{{foo x=bar.baz}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze.View(\"lookup:foo\", function() {\n      return Spacebars.mustache(view.lookup(\"foo\"), Spacebars.kw({\n        x: Spacebars.dot(view.lookup(\"bar\"), \"baz\")\n      }));\n    });\n  }\n  \"\"\"\n\n  run \"{{#foo}}abc{{/foo}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Spacebars.include(view.lookupTemplate(\"foo\"), (function() {\n      return \"abc\";\n    }));\n  }\n  \"\"\"\n\n  run \"{{#if cond}}aaa{{else}}bbb{{/if}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze.If(function () {\n      return Spacebars.call(view.lookup(\"cond\"));\n    }, (function() {\n      return \"aaa\";\n    }), (function() {\n      return \"bbb\";\n    }));\n  }\n  \"\"\"\n\n  run \"{{!-- --}}{{#if cond}}aaa{{!\\n}}{{else}}{{!}}bbb{{!-- --}}{{/if}}{{!}}\",\n  \"\"\"\nfunction() {\n  var view = this;\n  return Blaze.If(function () {\n    return Spacebars.call(view.lookup(\"cond\"));\n  }, (function() {\n    return \"aaa\";\n  }), (function() {\n    return \"bbb\";\n  }));\n}\n  \"\"\"\n\n  run \"{{> foo bar}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze._TemplateWith(function() {\n      return Spacebars.call(view.lookup(\"bar\"));\n    }, function() {\n      return Spacebars.include(view.lookupTemplate(\"foo\"));\n    });\n  }\n  \"\"\"\n\n  run \"{{> foo x=bar}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze._TemplateWith(function() {\n      return {\n        x: Spacebars.call(view.lookup(\"bar\"))\n      };\n    }, function() {\n      return Spacebars.include(view.lookupTemplate(\"foo\"));\n    });\n  }\n\n  \"\"\"\n\n  run \"{{> foo bar.baz}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze._TemplateWith(function() {\n      return Spacebars.call(Spacebars.dot(view.lookup(\"bar\"), \"baz\"));\n    }, function() {\n      return Spacebars.include(view.lookupTemplate(\"foo\"));\n    });\n  }\n  \"\"\"\n\n  run \"{{> foo x=bar.baz}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze._TemplateWith(function() {\n      return {\n        x: Spacebars.call(Spacebars.dot(view.lookup(\"bar\"), \"baz\"))\n      };\n    }, function() {\n      return Spacebars.include(view.lookupTemplate(\"foo\"));\n    });\n  }\n  \"\"\"\n\n  run \"{{> foo bar baz}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze._TemplateWith(function() {\n      return Spacebars.dataMustache(view.lookup(\"bar\"), view.lookup(\"baz\"));\n    }, function() {\n      return Spacebars.include(view.lookupTemplate(\"foo\"));\n    });\n  }\n\n  \"\"\"\n\n  run \"{{#foo bar baz}}aaa{{/foo}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze._TemplateWith(function() {\n      return Spacebars.dataMustache(view.lookup(\"bar\"), view.lookup(\"baz\"));\n    }, function() {\n      return Spacebars.include(view.lookupTemplate(\"foo\"), (function() {\n        return \"aaa\";\n      }));\n    });\n  }\n  \"\"\"\n\n  run \"{{#foo p.q r.s}}aaa{{/foo}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return Blaze._TemplateWith(function() {\n      return Spacebars.dataMustache(Spacebars.dot(view.lookup(\"p\"), \"q\"), Spacebars.dot(view.lookup(\"r\"), \"s\"));\n    }, function() {\n      return Spacebars.include(view.lookupTemplate(\"foo\"), (function() {\n        return \"aaa\";\n      }));\n    });\n  }\n  \"\"\"\n\n  run \"<a {{b}}></a>\",\n  \"\"\"\n  function() {\n    var view = this;\n    return HTML.A(HTML.Attrs(function() {\n      return Spacebars.attrMustache(view.lookup(\"b\"));\n    }));\n  }\n  \"\"\"\n\n  run \"<a {{b}} c=d{{e}}f></a>\",\n  \"\"\"\n  function() {\n    var view = this;\n    return HTML.A(HTML.Attrs({\n      c: (function() { return [\n        \"d\",\n        Spacebars.mustache(view.lookup(\"e\")),\n        \"f\" ]; })\n    }, function() {\n      return Spacebars.attrMustache(view.lookup(\"b\"));\n    }));\n  }\n  \"\"\"\n\n  run \"<asdf>{{foo}}</asdf>\",\n  \"\"\"\n  function() {\n    var view = this;\n    return HTML.getTag(\"asdf\")(Blaze.View(\"lookup:foo\", function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }));\n  }\n  \"\"\"\n\n  run \"<textarea>{{foo}}</textarea>\",\n  \"\"\"\n  function() {\n    var view = this;\n    return HTML.TEXTAREA({value: (function () {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }) });\n  }\n  \"\"\"\n\n  run \"<textarea>{{{{|{{|foo}}</textarea>\",\n  \"\"\"\n  function() {\n    var view = this;\n    return HTML.TEXTAREA({value: (function () {\n      return [ \"{{{{\", \"{{\", \"foo}}\" ];\n    }) });\n  }\n  \"\"\"\n\n  run \"{{|foo}}\",\n  \"\"\"\n  function() {\n    var view = this;\n    return [ \"{{\", \"foo}}\" ];\n  }\n  \"\"\"\n\n  run \"<a b={{{|></a>\",\n  \"\"\"\n  function() {\n    var view = this;\n    return HTML.A({\n      b: (function () {\n        return \"{{{\";\n      })\n    });\n  }\n  \"\"\"\n"
  },
  {
    "path": "packages/spacebars-compiler/optimizer.js",
    "content": "// Optimize parts of an HTMLjs tree into raw HTML strings when they don't\n// contain template tags.\n\nvar constant = function (value) {\n  return function () { return value; };\n};\n\nvar OPTIMIZABLE = {\n  NONE: 0,\n  PARTS: 1,\n  FULL: 2\n};\n\n// We can only turn content into an HTML string if it contains no template\n// tags and no \"tricky\" HTML tags.  If we can optimize the entire content\n// into a string, we return OPTIMIZABLE.FULL.  If the we are given an\n// unoptimizable node, we return OPTIMIZABLE.NONE.  If we are given a tree\n// that contains an unoptimizable node somewhere, we return OPTIMIZABLE.PARTS.\n//\n// For example, we always create SVG elements programmatically, since SVG\n// doesn't have innerHTML.  If we are given an SVG element, we return NONE.\n// However, if we are given a big tree that contains SVG somewhere, we\n// return PARTS so that the optimizer can descend into the tree and optimize\n// other parts of it.\nvar CanOptimizeVisitor = HTML.Visitor.extend();\nCanOptimizeVisitor.def({\n  visitNull: constant(OPTIMIZABLE.FULL),\n  visitPrimitive: constant(OPTIMIZABLE.FULL),\n  visitComment: constant(OPTIMIZABLE.FULL),\n  visitCharRef: constant(OPTIMIZABLE.FULL),\n  visitRaw: constant(OPTIMIZABLE.FULL),\n  visitObject: constant(OPTIMIZABLE.NONE),\n  visitFunction: constant(OPTIMIZABLE.NONE),\n  visitArray: function (x) {\n    for (var i = 0; i < x.length; i++)\n      if (this.visit(x[i]) !== OPTIMIZABLE.FULL)\n        return OPTIMIZABLE.PARTS;\n    return OPTIMIZABLE.FULL;\n  },\n  visitTag: function (tag) {\n    var tagName = tag.tagName;\n    if (tagName === 'textarea') {\n      // optimizing into a TEXTAREA's RCDATA would require being a little\n      // more clever.\n      return OPTIMIZABLE.NONE;\n    } else if (tagName === 'script') {\n      // script tags don't work when rendered from strings\n      return OPTIMIZABLE.NONE;\n    } else if (! (HTML.isKnownElement(tagName) &&\n                  ! HTML.isKnownSVGElement(tagName))) {\n      // foreign elements like SVG can't be stringified for innerHTML.\n      return OPTIMIZABLE.NONE;\n    } else if (tagName === 'table') {\n      // Avoid ever producing HTML containing `<table><tr>...`, because the\n      // browser will insert a TBODY.  If we just `createElement(\"table\")` and\n      // `createElement(\"tr\")`, on the other hand, no TBODY is necessary\n      // (assuming IE 8+).\n      return OPTIMIZABLE.NONE;\n    }\n\n    var children = tag.children;\n    for (var i = 0; i < children.length; i++)\n      if (this.visit(children[i]) !== OPTIMIZABLE.FULL)\n        return OPTIMIZABLE.PARTS;\n\n    if (this.visitAttributes(tag.attrs) !== OPTIMIZABLE.FULL)\n      return OPTIMIZABLE.PARTS;\n\n    return OPTIMIZABLE.FULL;\n  },\n  visitAttributes: function (attrs) {\n    if (attrs) {\n      var isArray = HTML.isArray(attrs);\n      for (var i = 0; i < (isArray ? attrs.length : 1); i++) {\n        var a = (isArray ? attrs[i] : attrs);\n        if ((typeof a !== 'object') || (a instanceof HTMLTools.TemplateTag))\n          return OPTIMIZABLE.PARTS;\n        for (var k in a)\n          if (this.visit(a[k]) !== OPTIMIZABLE.FULL)\n            return OPTIMIZABLE.PARTS;\n      }\n    }\n    return OPTIMIZABLE.FULL;\n  }\n});\n\nvar getOptimizability = function (content) {\n  return (new CanOptimizeVisitor).visit(content);\n};\n\nvar toRaw = function (x) {\n  return HTML.Raw(HTML.toHTML(x));\n};\n\nvar TreeTransformer = HTML.TransformingVisitor.extend();\nTreeTransformer.def({\n  visitAttributes: function (attrs/*, ...*/) {\n    // pass template tags through by default\n    if (attrs instanceof HTMLTools.TemplateTag)\n      return attrs;\n\n    return HTML.TransformingVisitor.prototype.visitAttributes.apply(\n      this, arguments);\n  }\n});\n\n// Replace parts of the HTMLjs tree that have no template tags (or\n// tricky HTML tags) with HTML.Raw objects containing raw HTML.\nvar OptimizingVisitor = TreeTransformer.extend();\nOptimizingVisitor.def({\n  visitNull: toRaw,\n  visitPrimitive: toRaw,\n  visitComment: toRaw,\n  visitCharRef: toRaw,\n  visitArray: function (array) {\n    var optimizability = getOptimizability(array);\n    if (optimizability === OPTIMIZABLE.FULL) {\n      return toRaw(array);\n    } else if (optimizability === OPTIMIZABLE.PARTS) {\n      return TreeTransformer.prototype.visitArray.call(this, array);\n    } else {\n      return array;\n    }\n  },\n  visitTag: function (tag) {\n    var optimizability = getOptimizability(tag);\n    if (optimizability === OPTIMIZABLE.FULL) {\n      return toRaw(tag);\n    } else if (optimizability === OPTIMIZABLE.PARTS) {\n      return TreeTransformer.prototype.visitTag.call(this, tag);\n    } else {\n      return tag;\n    }\n  },\n  visitChildren: function (children) {\n    // don't optimize the children array into a Raw object!\n    return TreeTransformer.prototype.visitArray.call(this, children);\n  },\n  visitAttributes: function (attrs) {\n    return attrs;\n  }\n});\n\n// Combine consecutive HTML.Raws.  Remove empty ones.\nvar RawCompactingVisitor = TreeTransformer.extend();\nRawCompactingVisitor.def({\n  visitArray: function (array) {\n    var result = [];\n    for (var i = 0; i < array.length; i++) {\n      var item = array[i];\n      if ((item instanceof HTML.Raw) &&\n          ((! item.value) ||\n           (result.length &&\n            (result[result.length - 1] instanceof HTML.Raw)))) {\n        // two cases: item is an empty Raw, or previous item is\n        // a Raw as well.  In the latter case, replace the previous\n        // Raw with a longer one that includes the new Raw.\n        if (item.value) {\n          result[result.length - 1] = HTML.Raw(\n            result[result.length - 1].value + item.value);\n        }\n      } else {\n        result.push(item);\n      }\n    }\n    return result;\n  }\n});\n\n// Replace pointless Raws like `HTMl.Raw('foo')` that contain no special\n// characters with simple strings.\nvar RawReplacingVisitor = TreeTransformer.extend();\nRawReplacingVisitor.def({\n  visitRaw: function (raw) {\n    var html = raw.value;\n    if (html.indexOf('&') < 0 && html.indexOf('<') < 0) {\n      return html;\n    } else {\n      return raw;\n    }\n  }\n});\n\nSpacebarsCompiler.optimize = function (tree) {\n  tree = (new OptimizingVisitor).visit(tree);\n  tree = (new RawCompactingVisitor).visit(tree);\n  tree = (new RawReplacingVisitor).visit(tree);\n  return tree;\n};\n"
  },
  {
    "path": "packages/spacebars-compiler/package.js",
    "content": "Package.describe({\n  summary: \"Compiler for Spacebars template language\",\n  version: '1.0.12'\n});\n\nPackage.onUse(function (api) {\n  api.export('SpacebarsCompiler');\n\n  api.use('htmljs');\n  api.use('html-tools');\n  api.use('blaze-tools');\n\n  api.use('underscore');\n  // The templating plugin will pull in minifier-js, so that generated code will\n  // be beautified. But it's a weak dependency so that eg boilerplate-generator\n  // doesn't pull in the minifier.\n  api.use('minifier-js', ['server'], { weak: true });\n  api.addFiles(['templatetag.js',\n                 'optimizer.js',\n                 'react.js',\n                 'codegen.js',\n                 'compiler.js']);\n});\n\nPackage.onTest(function (api) {\n  api.use([\n    'underscore',\n    'spacebars-compiler',\n    'tinytest',\n    'blaze-tools',\n    'coffeescript',\n    'spacebars',\n    'blaze'\n  ]);\n  api.addFiles('spacebars_tests.js');\n  api.addFiles('compile_tests.js');\n  api.addFiles('compiler_output_tests.coffee');\n});\n"
  },
  {
    "path": "packages/spacebars-compiler/react.js",
    "content": "// A visitor to ensure that React components included via the `{{>\n// React}}` template defined in the react-template-helper package are\n// the only child in their parent component. Otherwise `React.render`\n// would eliminate all of their sibling nodes.\n//\n// It's a little strange that this logic is in spacebars-compiler if\n// it's only relevant to a specific package but there's no way to have\n// a package hook into a build plugin.\nReactComponentSiblingForbidder = HTML.Visitor.extend();\nReactComponentSiblingForbidder.def({\n  visitArray: function (array, parentTag) {\n    for (var i = 0; i < array.length; i++) {\n      this.visit(array[i], parentTag);\n    }\n  },\n  visitObject: function (obj, parentTag) {\n    if (obj.type === \"INCLUSION\" && obj.path.length === 1 && obj.path[0] === \"React\") {\n      if (!parentTag) {\n        throw new Error(\n          \"{{> React}} must be used in a container element\"\n            + (this.sourceName ? (\" in \" + this.sourceName) : \"\")\n               + \". Learn more at https://github.com/meteor/meteor/wiki/React-components-must-be-the-only-thing-in-their-wrapper-element\");\n      }\n\n      var numSiblings = 0;\n      for (var i = 0; i < parentTag.children.length; i++) {\n        var child = parentTag.children[i];\n        if (child !== obj && !(typeof child === \"string\" && child.match(/^\\s*$/))) {\n          numSiblings++;\n        }\n      }\n\n      if (numSiblings > 0) {\n        throw new Error(\n          \"{{> React}} must be used as the only child in a container element\"\n            + (this.sourceName ? (\" in \" + this.sourceName) : \"\")\n               + \". Learn more at https://github.com/meteor/meteor/wiki/React-components-must-be-the-only-thing-in-their-wrapper-element\");\n      }\n    }\n  },\n  visitTag: function (tag) {\n    this.visitArray(tag.children, tag /*parentTag*/);\n  }\n});\n"
  },
  {
    "path": "packages/spacebars-compiler/spacebars_tests.js",
    "content": "Tinytest.add(\"spacebars-compiler - stache tags\", function (test) {\n\n  var run = function (input, expected) {\n    if (typeof expected === \"string\") {\n      // test for error starting with string `expected`\n      var msg = '';\n      test.throws(function () {\n        try {\n          SpacebarsCompiler.TemplateTag.parse(input);\n        } catch (e) {\n          msg = e.message;\n          throw e;\n        }\n      });\n      test.equal(msg.slice(0, expected.length), expected);\n    } else {\n      var result = SpacebarsCompiler.TemplateTag.parse(input);\n      test.equal(result, expected);\n    }\n  };\n\n  run('{{foo}}', {type: 'DOUBLE', path: ['foo'], args: []});\n  run('{{foo3}}', {type: 'DOUBLE', path: ['foo3'], args: []});\n  run('{{{foo}}}', {type: 'TRIPLE', path: ['foo'], args: []});\n  run('{{{foo}}', \"Expected `}}}`\");\n  run('{{{foo', \"Expected\");\n  run('{{foo', \"Expected\");\n  run('{{ {foo}}}', \"Unknown stache tag\");\n  run('{{{{foo}}}}', \"Unknown stache tag\");\n  run('{{{>foo}}}', \"Unknown stache tag\");\n  run('{{>>foo}}', \"Unknown stache tag\");\n  run('{{! asdf }}', {type: 'COMMENT', value: ' asdf '});\n  run('{{ ! asdf }}', {type: 'COMMENT', value: ' asdf '});\n  run('{{ ! asdf }asdf', \"Unclosed\");\n  run('{{!-- asdf --}}', {type: 'BLOCKCOMMENT', value: ' asdf '});\n  run('{{ !-- asdf -- }}', {type: 'BLOCKCOMMENT', value: ' asdf '});\n  run('{{ !-- {{asdf}} -- }}', {type: 'BLOCKCOMMENT', value: ' {{asdf}} '});\n  run('{{ !-- {{as--df}} --}}', {type: 'BLOCKCOMMENT', value: ' {{as--df}} '});\n  run('{{ !-- asdf }asdf', \"Unclosed\");\n  run('{{ !-- asdf --}asdf', \"Unclosed\");\n  run('{{else}}', {type: 'ELSE'});\n  run('{{ else }}', {type: 'ELSE'});\n  run('{{else x}}', \"Expected\");\n  run('{{else_x}}', {type: 'DOUBLE', path: ['else_x'], args: []});\n  run('{{/if}}', {type: 'BLOCKCLOSE', path: ['if']});\n  run('{{ / if }}', {type: 'BLOCKCLOSE', path: ['if']});\n  run('{{/if x}}', \"Expected\");\n  run('{{#if}}', {type: 'BLOCKOPEN', path: ['if'], args: []});\n  run('{{ # if }}', {type: 'BLOCKOPEN', path: ['if'], args: []});\n  run('{{#if_3}}', {type: 'BLOCKOPEN', path: ['if_3'], args: []});\n  run('{{>x}}', {type: 'INCLUSION', path: ['x'], args: []});\n  run('{{ > x }}', {type: 'INCLUSION', path: ['x'], args: []});\n  run('{{>x_3}}', {type: 'INCLUSION', path: ['x_3'], args: []});\n\n\n\n  run('{{foo 3}}', {type: 'DOUBLE', path: ['foo'], args: [['NUMBER', 3]]});\n  run('{{ foo  3 }}', {type: 'DOUBLE', path: ['foo'], args: [['NUMBER', 3]]});\n  run('{{#foo 3}}', {type: 'BLOCKOPEN', path: ['foo'], args: [['NUMBER', 3]]});\n  run('{{ # foo  3 }}', {type: 'BLOCKOPEN', path: ['foo'],\n                         args: [['NUMBER', 3]]});\n  run('{{>foo 3}}', {type: 'INCLUSION', path: ['foo'], args: [['NUMBER', 3]]});\n  run('{{ > foo  3 }}', {type: 'INCLUSION', path: ['foo'],\n                         args: [['NUMBER', 3]]});\n  run('{{{foo 3}}}', {type: 'TRIPLE', path: ['foo'], args: [['NUMBER', 3]]});\n\n  run('{{foo bar ./foo foo/bar a.b.c baz=qux x3=.}}',\n      {type: 'DOUBLE', path: ['foo'],\n       args: [['PATH', ['bar']],\n              ['PATH', ['.', 'foo']],\n              ['PATH', ['foo', 'bar']],\n              ['PATH', ['a', 'b', 'c']],\n              ['PATH', ['qux'], 'baz'],\n              ['PATH', ['.'], 'x3']]});\n\n  // nested expressions\n  run('{{helper (subhelper ./arg) arg.sub (args.passedHelper)}}', {\n    type: 'DOUBLE', path: ['helper'],\n    args: [\n      [\n        'EXPR', {\n          type: \"EXPR\", path: [\"subhelper\"],\n          args: [[\"PATH\", [\".\", \"arg\"]]]\n        }\n      ], [\n        \"PATH\", [\"arg\", \"sub\"]\n      ], [\n        \"EXPR\", {\n          type: \"EXPR\",\n          path: [\"args\", \"passedHelper\"],\n          args: []\n        }\n      ]\n    ]\n  });\n  run('{{helper (h arg}}', \"Expected `)`\");\n  run('{{helper (h arg))}}', \"Expected\");\n  run('{{helper ) h arg}}', \"Expected\");\n  run('{{(dyn) arg}}', \"Expected ID\");\n\n  run('{{{x 0.3 [0].[3] .4 ./[4]}}}',\n      {type: 'TRIPLE', path: ['x'],\n       args: [['NUMBER', 0.3],\n              ['PATH', ['0', '3']],\n              ['NUMBER', .4],\n              ['PATH', ['.', '4']]]});\n\n  run('{{# foo this this.x null z=null}}',\n      {type: 'BLOCKOPEN', path: ['foo'],\n       args: [['PATH', ['.']],\n              ['PATH', ['.', 'x']],\n              ['NULL', null],\n              ['NULL', null, 'z']]});\n\n  run('{{./foo 3}}', {type: 'DOUBLE', path: ['.', 'foo'], args: [['NUMBER', 3]]});\n  run('{{this/foo 3}}', {type: 'DOUBLE', path: ['.', 'foo'], args: [['NUMBER', 3]]});\n  run('{{../foo 3}}', {type: 'DOUBLE', path: ['..', 'foo'], args: [['NUMBER', 3]]});\n  run('{{../../foo 3}}', {type: 'DOUBLE', path: ['...', 'foo'], args: [['NUMBER', 3]]});\n\n  run('{{foo x/..}}', \"Expected\");\n  run('{{foo x/.}}', \"Expected\");\n\n  run('{{#a.b.c}}', {type: 'BLOCKOPEN', path: ['a', 'b', 'c'],\n                     args: []});\n  run('{{> a.b.c}}', {type: 'INCLUSION', path: ['a', 'b', 'c'],\n                      args: []});\n\n  run('{{foo.[]/[]}}', {type: 'DOUBLE', path: ['foo', '', ''],\n                        args: []});\n  run('{{x foo.[=]}}', {type: 'DOUBLE', path: ['x'],\n                        args: [['PATH', ['foo', '=']]]});\n  run('{{[].foo}}', \"Path can't start with empty string\");\n\n  run('{{foo null}}', {type: 'DOUBLE', path: ['foo'],\n                       args: [['NULL', null]]});\n  run('{{foo false}}', {type: 'DOUBLE', path: ['foo'],\n                       args: [['BOOLEAN', false]]});\n  run('{{foo true}}', {type: 'DOUBLE', path: ['foo'],\n                       args: [['BOOLEAN', true]]});\n  run('{{foo \"bar\"}}', {type: 'DOUBLE', path: ['foo'],\n                        args: [['STRING', 'bar']]});\n  run(\"{{foo 'bar'}}\", {type: 'DOUBLE', path: ['foo'],\n                        args: [['STRING', 'bar']]});\n\n  run('{{foo -1 -2}}', {type: 'DOUBLE', path: ['foo'],\n                        args: [['NUMBER', -1], ['NUMBER', -2]]});\n\n  run('{{x \"\\'\"}}', {type: 'DOUBLE', path: ['x'], args: [['STRING', \"'\"]]});\n  run('{{x \\'\"\\'}}', {type: 'DOUBLE', path: ['x'], args: [['STRING', '\"']]});\n\n  run('{{> foo x=1 y=2}}',\n      {type: 'INCLUSION', path: ['foo'],\n       args: [['NUMBER', 1, 'x'],\n              ['NUMBER', 2, 'y']]});\n  // spaces around '=' are fine\n  run('{{> foo x = 1 y = 2}}',\n      {type: 'INCLUSION', path: ['foo'],\n       args: [['NUMBER', 1, 'x'],\n              ['NUMBER', 2, 'y']]});\n  run('{{> foo with-dashes=1 another-one=2}}',\n      {type: 'INCLUSION', path: ['foo'],\n       args: [['NUMBER', 1, 'with-dashes'],\n              ['NUMBER', 2, 'another-one']]});\n  run('{{> foo 1=\"keyword can start with a number\"}}',\n      {type: 'INCLUSION', path: ['foo'],\n       args: [['STRING', 'keyword can start with a number', '1']]});\n  run('{{> foo disallow-dashes-in-posarg}}',\n      \"Expected\");\n  run('{{> foo disallow-#=1}}',\n      \"Expected\");\n  run('{{> foo disallow->=1}}',\n      \"Expected\");\n  run('{{> foo disallow-{=1}}',\n      \"Expected\");\n  run('{{> foo disallow-(=1}}',\n      \"Expected\");\n  run('{{> foo disallow-}=1}}',\n      \"Expected\");\n  run('{{> foo disallow-)=1}}',\n      \"Expected\");\n  run('{{> foo x=1 y=2 z}}',\n      \"Can't have a non-keyword argument\");\n\n  run('{{true.foo}}', \"Can't use\");\n  run('{{foo.this}}', \"Can only use\");\n  run('{{./this}}', \"Can only use\");\n  run('{{../this}}', \"Can only use\");\n\n  run('{{foo \"=\"}}', {type: 'DOUBLE', path: ['foo'],\n                        args: [['STRING', '=']]});\n\n  run('{{| asdf', { type: 'ESCAPE', value: '{{' });\n  run('{{{| asdf', { type: 'ESCAPE', value: '{{{' });\n  run('{{{{| asdf', { type: 'ESCAPE', value: '{{{{' });\n});\n\n\nTinytest.add(\"spacebars-compiler - Spacebars.dot\", function (test) {\n  test.equal(Spacebars.dot(null, 'foo'), null);\n  test.equal(Spacebars.dot('foo', 'foo'), undefined);\n  test.equal(Spacebars.dot({x:1}, 'x'), 1);\n  test.equal(Spacebars.dot(\n    {x:1, y: function () { return this.x+1; }}, 'y')(), 2);\n  test.equal(Spacebars.dot(\n    function () {\n      return {x:1, y: function () { return this.x+1; }};\n    }, 'y')(), 2);\n\n  var m = 1;\n  var mget = function () {\n    return {\n      answer: m,\n      getAnswer: function () {\n        return this.answer;\n      }\n    };\n  };\n  var mgetDotAnswer = Spacebars.dot(mget, 'answer');\n  test.equal(mgetDotAnswer, 1);\n\n  m = 3;\n  var mgetDotGetAnswer = Spacebars.dot(mget, 'getAnswer');\n  test.equal(mgetDotGetAnswer(), 3);\n  m = 4;\n  test.equal(mgetDotGetAnswer(), 3);\n\n  var closet = {\n    mget: mget,\n    mget2: function () {\n      return this.mget();\n    }\n  };\n\n  m = 5;\n  var f1 = Spacebars.dot(closet, 'mget', 'answer');\n  m = 6;\n  var f2 = Spacebars.dot(closet, 'mget2', 'answer');\n  test.equal(f2, 6);\n  m = 8;\n  var f3 = Spacebars.dot(closet, 'mget2', 'getAnswer');\n  m = 9;\n  test.equal(f3(), 8);\n\n  test.equal(Spacebars.dot(0, 'abc', 'def'), 0);\n  test.equal(Spacebars.dot(function () { return null; }, 'abc', 'def'), null);\n  test.equal(Spacebars.dot(function () { return 0; }, 'abc', 'def'), 0);\n\n  // test that in `foo.bar`, `bar` may be a function that takes arguments.\n  test.equal(Spacebars.dot(\n    { one: 1, inc: function (x) { return this.one + x; } }, 'inc')(6), 7);\n  test.equal(Spacebars.dot(\n    function () {\n      return { one: 1, inc: function (x) { return this.one + x; } };\n    }, 'inc')(8), 9);\n\n});\n\n//////////////////////////////////////////////////\n\nTinytest.add(\"spacebars-compiler - parse\", function (test) {\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('{{foo}}')),\n             'SpacebarsCompiler.TemplateTag({type: \"DOUBLE\", path: [\"foo\"]})');\n\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('{{!foo}}')), 'null');\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('x{{!foo}}y')), '\"xy\"');\n\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('{{!--foo--}}')), 'null');\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('x{{!--foo--}}y')), '\"xy\"');\n\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('{{#foo}}x{{/foo}}')),\n             'SpacebarsCompiler.TemplateTag({type: \"BLOCKOPEN\", path: [\"foo\"], content: \"x\"})');\n\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('{{#foo}}{{#bar}}{{/bar}}{{/foo}}')),\n             'SpacebarsCompiler.TemplateTag({type: \"BLOCKOPEN\", path: [\"foo\"], content: SpacebarsCompiler.TemplateTag({type: \"BLOCKOPEN\", path: [\"bar\"]})})');\n\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('<div>hello</div> {{#foo}}<div>{{#bar}}world{{/bar}}</div>{{/foo}}')),\n             '[HTML.DIV(\"hello\"), \" \", SpacebarsCompiler.TemplateTag({type: \"BLOCKOPEN\", path: [\"foo\"], content: HTML.DIV(SpacebarsCompiler.TemplateTag({type: \"BLOCKOPEN\", path: [\"bar\"], content: \"world\"}))})]');\n\n\n  test.throws(function () {\n    SpacebarsCompiler.parse('<a {{{x}}}></a>');\n  });\n  test.throws(function () {\n    SpacebarsCompiler.parse('<a {{#if x}}{{/if}}></a>');\n  });\n  test.throws(function () {\n    SpacebarsCompiler.parse('<a {{k}}={[v}}></a>');\n  });\n  test.throws(function () {\n    SpacebarsCompiler.parse('<a x{{y}}></a>');\n  });\n  test.throws(function () {\n    SpacebarsCompiler.parse('<a x{{y}}=z></a>');\n  });\n  test.throws(function () {\n    SpacebarsCompiler.parse('<a {{> x}}></a>');\n  });\n\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('<a {{! x--}} b=c{{! x}} {{! x}}></a>')),\n             'HTML.A({b: \"c\"})');\n\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('<a {{!-- x--}} b=c{{ !-- x --}} {{!-- x -- }}></a>')),\n             'HTML.A({b: \"c\"})');\n\n  // currently, if there are only comments, the attribute is truthy.  This is\n  // because comments are stripped during tokenization.  If we include\n  // comments in the token stream, these cases will become falsy for selected.\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('<input selected={{!foo}}>')),\n             'HTML.INPUT({selected: \"\"})');\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('<input selected={{!foo}}{{!bar}}>')),\n             'HTML.INPUT({selected: \"\"})');\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('<input selected={{!--foo--}}>')),\n    'HTML.INPUT({selected: \"\"})');\n  test.equal(BlazeTools.toJS(SpacebarsCompiler.parse('<input selected={{!--foo--}}{{!--bar--}}>')),\n    'HTML.INPUT({selected: \"\"})');\n\n});\n"
  },
  {
    "path": "packages/spacebars-compiler/templatetag.js",
    "content": "SpacebarsCompiler = {};\n\n// A TemplateTag is the result of parsing a single `{{...}}` tag.\n//\n// The `.type` of a TemplateTag is one of:\n//\n// - `\"DOUBLE\"` - `{{foo}}`\n// - `\"TRIPLE\"` - `{{{foo}}}`\n// - `\"EXPR\"` - `(foo)`\n// - `\"COMMENT\"` - `{{! foo}}`\n// - `\"BLOCKCOMMENT\" - `{{!-- foo--}}`\n// - `\"INCLUSION\"` - `{{> foo}}`\n// - `\"BLOCKOPEN\"` - `{{#foo}}`\n// - `\"BLOCKCLOSE\"` - `{{/foo}}`\n// - `\"ELSE\"` - `{{else}}`\n// - `\"ESCAPE\"` - `{{|`, `{{{|`, `{{{{|` and so on\n//\n// Besides `type`, the mandatory properties of a TemplateTag are:\n//\n// - `path` - An array of one or more strings.  The path of `{{foo.bar}}`\n//   is `[\"foo\", \"bar\"]`.  Applies to DOUBLE, TRIPLE, INCLUSION, BLOCKOPEN,\n//   and BLOCKCLOSE.\n//\n// - `args` - An array of zero or more argument specs.  An argument spec\n//   is a two or three element array, consisting of a type, value, and\n//   optional keyword name.  For example, the `args` of `{{foo \"bar\" x=3}}`\n//   are `[[\"STRING\", \"bar\"], [\"NUMBER\", 3, \"x\"]]`.  Applies to DOUBLE,\n//   TRIPLE, INCLUSION, and BLOCKOPEN.\n//\n// - `value` - A string of the comment's text. Applies to COMMENT and\n//   BLOCKCOMMENT.\n//\n// These additional are typically set during parsing:\n//\n// - `position` - The HTMLTools.TEMPLATE_TAG_POSITION specifying at what sort\n//   of site the TemplateTag was encountered (e.g. at element level or as\n//   part of an attribute value). Its absence implies\n//   TEMPLATE_TAG_POSITION.ELEMENT.\n//\n// - `content` and `elseContent` - When a BLOCKOPEN tag's contents are\n//   parsed, they are put here.  `elseContent` will only be present if\n//   an `{{else}}` was found.\n\nvar TEMPLATE_TAG_POSITION = HTMLTools.TEMPLATE_TAG_POSITION;\n\nTemplateTag = SpacebarsCompiler.TemplateTag = function () {\n  HTMLTools.TemplateTag.apply(this, arguments);\n};\nTemplateTag.prototype = new HTMLTools.TemplateTag;\nTemplateTag.prototype.constructorName = 'SpacebarsCompiler.TemplateTag';\n\nvar makeStacheTagStartRegex = function (r) {\n  return new RegExp(r.source + /(?![{>!#/])/.source,\n                    r.ignoreCase ? 'i' : '');\n};\n\n// \"starts\" regexes are used to see what type of template\n// tag the parser is looking at.  They must match a non-empty\n// result, but not the interesting part of the tag.\nvar starts = {\n  ESCAPE: /^\\{\\{(?=\\{*\\|)/,\n  ELSE: makeStacheTagStartRegex(/^\\{\\{\\s*else(?=[\\s}])/i),\n  DOUBLE: makeStacheTagStartRegex(/^\\{\\{\\s*(?!\\s)/),\n  TRIPLE: makeStacheTagStartRegex(/^\\{\\{\\{\\s*(?!\\s)/),\n  BLOCKCOMMENT: makeStacheTagStartRegex(/^\\{\\{\\s*!--/),\n  COMMENT: makeStacheTagStartRegex(/^\\{\\{\\s*!/),\n  INCLUSION: makeStacheTagStartRegex(/^\\{\\{\\s*>\\s*(?!\\s)/),\n  BLOCKOPEN: makeStacheTagStartRegex(/^\\{\\{\\s*#\\s*(?!\\s)/),\n  BLOCKCLOSE: makeStacheTagStartRegex(/^\\{\\{\\s*\\/\\s*(?!\\s)/)\n};\n\nvar ends = {\n  DOUBLE: /^\\s*\\}\\}/,\n  TRIPLE: /^\\s*\\}\\}\\}/,\n  EXPR: /^\\s*\\)/\n};\n\nvar endsString = {\n  DOUBLE: '}}',\n  TRIPLE: '}}}',\n  EXPR: ')'\n};\n\n// Parse a tag from the provided scanner or string.  If the input\n// doesn't start with `{{`, returns null.  Otherwise, either succeeds\n// and returns a SpacebarsCompiler.TemplateTag, or throws an error (using\n// `scanner.fatal` if a scanner is provided).\nTemplateTag.parse = function (scannerOrString) {\n  var scanner = scannerOrString;\n  if (typeof scanner === 'string')\n    scanner = new HTMLTools.Scanner(scannerOrString);\n\n  if (! (scanner.peek() === '{' &&\n         (scanner.rest()).slice(0, 2) === '{{'))\n    return null;\n\n  var run = function (regex) {\n    // regex is assumed to start with `^`\n    var result = regex.exec(scanner.rest());\n    if (! result)\n      return null;\n    var ret = result[0];\n    scanner.pos += ret.length;\n    return ret;\n  };\n\n  var advance = function (amount) {\n    scanner.pos += amount;\n  };\n\n  var scanIdentifier = function (isFirstInPath) {\n    var id = BlazeTools.parseExtendedIdentifierName(scanner);\n    if (! id) {\n      expected('IDENTIFIER');\n    }\n    if (isFirstInPath &&\n        (id === 'null' || id === 'true' || id === 'false'))\n      scanner.fatal(\"Can't use null, true, or false, as an identifier at start of path\");\n\n    return id;\n  };\n\n  var scanPath = function () {\n    var segments = [];\n\n    // handle initial `.`, `..`, `./`, `../`, `../..`, `../../`, etc\n    var dots;\n    if ((dots = run(/^[\\.\\/]+/))) {\n      var ancestorStr = '.'; // eg `../../..` maps to `....`\n      var endsWithSlash = /\\/$/.test(dots);\n\n      if (endsWithSlash)\n        dots = dots.slice(0, -1);\n\n      _.each(dots.split('/'), function(dotClause, index) {\n        if (index === 0) {\n          if (dotClause !== '.' && dotClause !== '..')\n            expected(\"`.`, `..`, `./` or `../`\");\n        } else {\n          if (dotClause !== '..')\n            expected(\"`..` or `../`\");\n        }\n\n        if (dotClause === '..')\n          ancestorStr += '.';\n      });\n\n      segments.push(ancestorStr);\n\n      if (!endsWithSlash)\n        return segments;\n    }\n\n    while (true) {\n      // scan a path segment\n\n      if (run(/^\\[/)) {\n        var seg = run(/^[\\s\\S]*?\\]/);\n        if (! seg)\n          error(\"Unterminated path segment\");\n        seg = seg.slice(0, -1);\n        if (! seg && ! segments.length)\n          error(\"Path can't start with empty string\");\n        segments.push(seg);\n      } else {\n        var id = scanIdentifier(! segments.length);\n        if (id === 'this') {\n          if (! segments.length) {\n            // initial `this`\n            segments.push('.');\n          } else {\n            error(\"Can only use `this` at the beginning of a path.\\nInstead of `foo.this` or `../this`, just write `foo` or `..`.\");\n          }\n        } else {\n          segments.push(id);\n        }\n      }\n\n      var sep = run(/^[\\.\\/]/);\n      if (! sep)\n        break;\n    }\n\n    return segments;\n  };\n\n  // scan the keyword portion of a keyword argument\n  // (the \"foo\" portion in \"foo=bar\").\n  // Result is either the keyword matched, or null\n  // if we're not at a keyword argument position.\n  var scanArgKeyword = function () {\n    var match = /^([^\\{\\}\\(\\)\\>#=\\s\"'\\[\\]]+)\\s*=\\s*/.exec(scanner.rest());\n    if (match) {\n      scanner.pos += match[0].length;\n      return match[1];\n    } else {\n      return null;\n    }\n  };\n\n  // scan an argument; succeeds or errors.\n  // Result is an array of two or three items:\n  // type , value, and (indicating a keyword argument)\n  // keyword name.\n  var scanArg = function () {\n    var keyword = scanArgKeyword(); // null if not parsing a kwarg\n    var value = scanArgValue();\n    return keyword ? value.concat(keyword) : value;\n  };\n\n  // scan an argument value (for keyword or positional arguments);\n  // succeeds or errors.  Result is an array of type, value.\n  var scanArgValue = function () {\n    var startPos = scanner.pos;\n    var result;\n    if ((result = BlazeTools.parseNumber(scanner))) {\n      return ['NUMBER', result.value];\n    } else if ((result = BlazeTools.parseStringLiteral(scanner))) {\n      return ['STRING', result.value];\n    } else if (/^[\\.\\[]/.test(scanner.peek())) {\n      return ['PATH', scanPath()];\n    } else if (run(/^\\(/)) {\n      return ['EXPR', scanExpr('EXPR')];\n    } else if ((result = BlazeTools.parseExtendedIdentifierName(scanner))) {\n      var id = result;\n      if (id === 'null') {\n        return ['NULL', null];\n      } else if (id === 'true' || id === 'false') {\n        return ['BOOLEAN', id === 'true'];\n      } else {\n        scanner.pos = startPos; // unconsume `id`\n        return ['PATH', scanPath()];\n      }\n    } else {\n      expected('identifier, number, string, boolean, null, or a sub expression enclosed in \"(\", \")\"');\n    }\n  };\n\n  var scanExpr = function (type) {\n    var endType = type;\n    if (type === 'INCLUSION' || type === 'BLOCKOPEN')\n      endType = 'DOUBLE';\n\n    var tag = new TemplateTag;\n    tag.type = type;\n    tag.path = scanPath();\n    tag.args = [];\n    var foundKwArg = false;\n    while (true) {\n      run(/^\\s*/);\n      if (run(ends[endType]))\n        break;\n      else if (/^[})]/.test(scanner.peek())) {\n        expected('`' + endsString[endType] + '`');\n      }\n      var newArg = scanArg();\n      if (newArg.length === 3) {\n        foundKwArg = true;\n      } else {\n        if (foundKwArg)\n          error(\"Can't have a non-keyword argument after a keyword argument\");\n      }\n      tag.args.push(newArg);\n\n      // expect a whitespace or a closing ')' or '}'\n      if (run(/^(?=[\\s})])/) !== '')\n        expected('space');\n    }\n\n    return tag;\n  };\n\n  var type;\n\n  var error = function (msg) {\n    scanner.fatal(msg);\n  };\n\n  var expected = function (what) {\n    error('Expected ' + what);\n  };\n\n  // must do ESCAPE first, immediately followed by ELSE\n  // order of others doesn't matter\n  if (run(starts.ESCAPE)) type = 'ESCAPE';\n  else if (run(starts.ELSE)) type = 'ELSE';\n  else if (run(starts.DOUBLE)) type = 'DOUBLE';\n  else if (run(starts.TRIPLE)) type = 'TRIPLE';\n  else if (run(starts.BLOCKCOMMENT)) type = 'BLOCKCOMMENT';\n  else if (run(starts.COMMENT)) type = 'COMMENT';\n  else if (run(starts.INCLUSION)) type = 'INCLUSION';\n  else if (run(starts.BLOCKOPEN)) type = 'BLOCKOPEN';\n  else if (run(starts.BLOCKCLOSE)) type = 'BLOCKCLOSE';\n  else\n    error('Unknown stache tag');\n\n  var tag = new TemplateTag;\n  tag.type = type;\n\n  if (type === 'BLOCKCOMMENT') {\n    var result = run(/^[\\s\\S]*?--\\s*?\\}\\}/);\n    if (! result)\n      error(\"Unclosed block comment\");\n    tag.value = result.slice(0, result.lastIndexOf('--'));\n  } else if (type === 'COMMENT') {\n    var result = run(/^[\\s\\S]*?\\}\\}/);\n    if (! result)\n      error(\"Unclosed comment\");\n    tag.value = result.slice(0, -2);\n  } else if (type === 'BLOCKCLOSE') {\n    tag.path = scanPath();\n    if (! run(ends.DOUBLE))\n      expected('`}}`');\n  } else if (type === 'ELSE') {\n    if (! run(ends.DOUBLE))\n      expected('`}}`');\n  } else if (type === 'ESCAPE') {\n    var result = run(/^\\{*\\|/);\n    tag.value = '{{' + result.slice(0, -1);\n  } else {\n    // DOUBLE, TRIPLE, BLOCKOPEN, INCLUSION\n    tag = scanExpr(type);\n  }\n\n  return tag;\n};\n\n// Returns a SpacebarsCompiler.TemplateTag parsed from `scanner`, leaving scanner\n// at its original position.\n//\n// An error will still be thrown if there is not a valid template tag at\n// the current position.\nTemplateTag.peek = function (scanner) {\n  var startPos = scanner.pos;\n  var result = TemplateTag.parse(scanner);\n  scanner.pos = startPos;\n  return result;\n};\n\n// Like `TemplateTag.parse`, but in the case of blocks, parse the complete\n// `{{#foo}}...{{/foo}}` with `content` and possible `elseContent`, rather\n// than just the BLOCKOPEN tag.\n//\n// In addition:\n//\n// - Throws an error if `{{else}}` or `{{/foo}}` tag is encountered.\n//\n// - Returns `null` for a COMMENT.  (This case is distinguishable from\n//   parsing no tag by the fact that the scanner is advanced.)\n//\n// - Takes an HTMLTools.TEMPLATE_TAG_POSITION `position` and sets it as the\n//   TemplateTag's `.position` property.\n//\n// - Validates the tag's well-formedness and legality at in its position.\nTemplateTag.parseCompleteTag = function (scannerOrString, position) {\n  var scanner = scannerOrString;\n  if (typeof scanner === 'string')\n    scanner = new HTMLTools.Scanner(scannerOrString);\n\n  var startPos = scanner.pos; // for error messages\n  var result = TemplateTag.parse(scannerOrString);\n  if (! result)\n    return result;\n\n  if (result.type === 'BLOCKCOMMENT')\n    return null;\n\n  if (result.type === 'COMMENT')\n    return null;\n\n  if (result.type === 'ELSE')\n    scanner.fatal(\"Unexpected {{else}}\");\n\n  if (result.type === 'BLOCKCLOSE')\n    scanner.fatal(\"Unexpected closing template tag\");\n\n  position = (position || TEMPLATE_TAG_POSITION.ELEMENT);\n  if (position !== TEMPLATE_TAG_POSITION.ELEMENT)\n    result.position = position;\n\n  if (result.type === 'BLOCKOPEN') {\n    // parse block contents\n\n    // Construct a string version of `.path` for comparing start and\n    // end tags.  For example, `foo/[0]` was parsed into `[\"foo\", \"0\"]`\n    // and now becomes `foo,0`.  This form may also show up in error\n    // messages.\n    var blockName = result.path.join(',');\n\n    var textMode = null;\n      if (blockName === 'markdown' ||\n          position === TEMPLATE_TAG_POSITION.IN_RAWTEXT) {\n        textMode = HTML.TEXTMODE.STRING;\n      } else if (position === TEMPLATE_TAG_POSITION.IN_RCDATA ||\n                 position === TEMPLATE_TAG_POSITION.IN_ATTRIBUTE) {\n        textMode = HTML.TEXTMODE.RCDATA;\n      }\n      var parserOptions = {\n        getTemplateTag: TemplateTag.parseCompleteTag,\n        shouldStop: isAtBlockCloseOrElse,\n        textMode: textMode\n      };\n    result.content = HTMLTools.parseFragment(scanner, parserOptions);\n\n    if (scanner.rest().slice(0, 2) !== '{{')\n      scanner.fatal(\"Expected {{else}} or block close for \" + blockName);\n\n    var lastPos = scanner.pos; // save for error messages\n    var tmplTag = TemplateTag.parse(scanner); // {{else}} or {{/foo}}\n\n    if (tmplTag.type === 'ELSE') {\n      // parse {{else}} and content up to close tag\n      result.elseContent = HTMLTools.parseFragment(scanner, parserOptions);\n\n      if (scanner.rest().slice(0, 2) !== '{{')\n        scanner.fatal(\"Expected block close for \" + blockName);\n\n      lastPos = scanner.pos;\n      tmplTag = TemplateTag.parse(scanner);\n    }\n\n    if (tmplTag.type === 'BLOCKCLOSE') {\n      var blockName2 = tmplTag.path.join(',');\n      if (blockName !== blockName2) {\n        scanner.pos = lastPos;\n        scanner.fatal('Expected tag to close ' + blockName + ', found ' +\n                      blockName2);\n      }\n    } else {\n      scanner.pos = lastPos;\n      scanner.fatal('Expected tag to close ' + blockName + ', found ' +\n                    tmplTag.type);\n    }\n  }\n\n  var finalPos = scanner.pos;\n  scanner.pos = startPos;\n  validateTag(result, scanner);\n  scanner.pos = finalPos;\n\n  return result;\n};\n\nvar isAtBlockCloseOrElse = function (scanner) {\n  // Detect `{{else}}` or `{{/foo}}`.\n  //\n  // We do as much work ourselves before deferring to `TemplateTag.peek`,\n  // for efficiency (we're called for every input token) and to be\n  // less obtrusive, because `TemplateTag.peek` will throw an error if it\n  // sees `{{` followed by a malformed tag.\n  var rest, type;\n  return (scanner.peek() === '{' &&\n          (rest = scanner.rest()).slice(0, 2) === '{{' &&\n          /^\\{\\{\\s*(\\/|else\\b)/.test(rest) &&\n          (type = TemplateTag.peek(scanner).type) &&\n          (type === 'BLOCKCLOSE' || type === 'ELSE'));\n};\n\n// Validate that `templateTag` is correctly formed and legal for its\n// HTML position.  Use `scanner` to report errors. On success, does\n// nothing.\nvar validateTag = function (ttag, scanner) {\n\n  if (ttag.type === 'INCLUSION' || ttag.type === 'BLOCKOPEN') {\n    var args = ttag.args;\n    if (ttag.path[0] === 'each' && args[1] && args[1][0] === 'PATH' &&\n        args[1][1][0] === 'in') {\n      // For slightly better error messages, we detect the each-in case\n      // here in order not to complain if the user writes `{{#each 3 in x}}`\n      // that \"3 is not a function\"\n    } else {\n      if (args.length > 1 && args[0].length === 2 && args[0][0] !== 'PATH') {\n        // we have a positional argument that is not a PATH followed by\n        // other arguments\n        scanner.fatal(\"First argument must be a function, to be called on \" +\n                      \"the rest of the arguments; found \" + args[0][0]);\n      }\n    }\n  }\n\n  var position = ttag.position || TEMPLATE_TAG_POSITION.ELEMENT;\n  if (position === TEMPLATE_TAG_POSITION.IN_ATTRIBUTE) {\n    if (ttag.type === 'DOUBLE' || ttag.type === 'ESCAPE') {\n      return;\n    } else if (ttag.type === 'BLOCKOPEN') {\n      var path = ttag.path;\n      var path0 = path[0];\n      if (! (path.length === 1 && (path0 === 'if' ||\n                                   path0 === 'unless' ||\n                                   path0 === 'with' ||\n                                   path0 === 'each'))) {\n        scanner.fatal(\"Custom block helpers are not allowed in an HTML attribute, only built-in ones like #each and #if\");\n      }\n    } else {\n      scanner.fatal(ttag.type + \" template tag is not allowed in an HTML attribute\");\n    }\n  } else if (position === TEMPLATE_TAG_POSITION.IN_START_TAG) {\n    if (! (ttag.type === 'DOUBLE')) {\n      scanner.fatal(\"Reactive HTML attributes must either have a constant name or consist of a single {{helper}} providing a dictionary of names and values.  A template tag of type \" + ttag.type + \" is not allowed here.\");\n    }\n    if (scanner.peek() === '=') {\n      scanner.fatal(\"Template tags are not allowed in attribute names, only in attribute values or in the form of a single {{helper}} that evaluates to a dictionary of name=value pairs.\");\n    }\n  }\n\n};\n"
  },
  {
    "path": "packages/spacebars-tests/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/spacebars-tests/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/spacebars-tests/assets/markdown_basic.html",
    "content": "<p><i>hi</i>\n/each}}</p>\n\n<p><b><i>hi</i></b>\n<b>/each}}</b></p>\n\n<ul>\n<li><i>hi</i></li>\n<li><p>/each}}</p></li>\n<li><p><b><i>hi</i></b></p></li>\n<li><b>/each}}</b></li>\n</ul>\n\n<p>some paragraph to fix showdown's four space parsing below.</p>\n\n<pre><code>&lt;i&gt;hi&lt;/i&gt;\n/each}}\n\n&lt;b&gt;&lt;i&gt;hi&lt;/i&gt;&lt;/b&gt;\n&lt;b&gt;/each}}&lt;/b&gt;\n</code></pre>\n\n<p>&amp;gt</p>\n\n<ul>\n<li>&amp;gt</li>\n</ul>\n\n<p><code>&amp;gt</code></p>\n\n<pre><code>&amp;gt\n</code></pre>\n\n<p>&gt;</p>\n\n<ul>\n<li>&gt;</li>\n</ul>\n\n<p><code>&amp;gt;</code></p>\n\n<pre><code>&amp;gt;\n</code></pre>\n\n<p><code>&lt;i&gt;hi&lt;/i&gt;</code>\n<code>/each}}</code></p>\n\n<p><code>&lt;b&gt;&lt;i&gt;hi&lt;/i&gt;&lt;/b&gt;</code>\n<code>&lt;b&gt;/each}}</code></p>\n"
  },
  {
    "path": "packages/spacebars-tests/assets/markdown_each1.html",
    "content": "<p><b></b></p>\n\n<ul>\n<li></li>\n<li><b></b></li>\n</ul>\n\n<p>some paragraph to fix showdown's four space parsing below.</p>\n\n<pre><code>&lt;b&gt;&lt;/b&gt;\n</code></pre>\n\n<p>``</p>\n\n<p><code>&lt;b&gt;&lt;/b&gt;</code></p>\n"
  },
  {
    "path": "packages/spacebars-tests/assets/markdown_each2.html",
    "content": "<p>item</p>\n\n<p><b>item</b></p>\n\n<ul>\n<li><p>item</p></li>\n<li><p><b>item</b></p></li>\n</ul>\n\n<p>some paragraph to fix showdown's four space parsing below.</p>\n\n<pre><code>item\n\n&lt;b&gt;item&lt;/b&gt;\n</code></pre>\n\n<p><code>item</code></p>\n\n<p><code>&lt;b&gt;item&lt;/b&gt;</code></p>\n"
  },
  {
    "path": "packages/spacebars-tests/assets/markdown_if1.html",
    "content": "<p>false</p>\n\n<p><b>false</b></p>\n\n<ul>\n<li><p>false</p></li>\n<li><p><b>false</b></p></li>\n</ul>\n\n<p>some paragraph to fix showdown's four space parsing below.</p>\n\n<pre><code>false\n\n&lt;b&gt;false&lt;/b&gt;\n</code></pre>\n\n<p><code>false</code></p>\n\n<p><code>&lt;b&gt;false&lt;/b&gt;</code></p>\n"
  },
  {
    "path": "packages/spacebars-tests/assets/markdown_if2.html",
    "content": "<p>true</p>\n\n<p><b>true</b></p>\n\n<ul>\n<li><p>true</p></li>\n<li><p><b>true</b></p></li>\n</ul>\n\n<p>some paragraph to fix showdown's four space parsing below.</p>\n\n<pre><code>true\n\n&lt;b&gt;true&lt;/b&gt;\n</code></pre>\n\n<p><code>true</code></p>\n\n<p><code>&lt;b&gt;true&lt;/b&gt;</code></p>\n"
  },
  {
    "path": "packages/spacebars-tests/old_templates.js",
    "content": "// This file contains templates compiled with a pre-0.9.0 version of\n// spacebars-compiler. We run the entire suite of tests as we had on\n// 0.9.0 against these compiled template. The test suits is found\n// in old_templates_tests.js\n//\n// Why? Packages are published in built form. With Meteor 0.9.1, we\n// didn't bump the major version of the 'templating' package (which\n// would force packages that define templates to publish new versions\n// of their package). Instead, we decided to keep backcompat with the\n// old Blaze runtime APIs.\n//\n// If these tests ever break in the future, and backcompat is too hard\n// to achieve (or undesirable), we can simply bump the major version\n// of the 'templating' package, and get rid of these tests.\nTemplate.__define__(\"old_spacebars_template_test_aaa\", (function() {\n  var view = this;\n  return \"aaa\";\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_bbb\", (function() {\n  var view = this;\n  return \"bbb\";\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_bracketed_this\", (function() {\n  var view = this;\n  return [ \"[\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\".\"));\n  }), \"]\" ];\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_span_this\", (function() {\n  var view = this;\n  return HTML.SPAN(Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\".\"));\n  }));\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_content\", (function() {\n  var view = this;\n  return Blaze.InOuterTemplateScope(view, function() {\n    return Spacebars.include(function() {\n      return Spacebars.call(view.templateContentBlock);\n    });\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_elsecontent\", (function() {\n  var view = this;\n  return Blaze.InOuterTemplateScope(view, function() {\n    return Spacebars.include(function() {\n      return Spacebars.call(view.templateElseBlock);\n    });\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_iftemplate\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"condition\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.InOuterTemplateScope(view, function() {\n      return Spacebars.include(function() {\n        return Spacebars.call(view.templateContentBlock);\n      });\n    }), \"\\n  \" ];\n  }, function() {\n    return [ \"\\n    \", Blaze.InOuterTemplateScope(view, function() {\n      return Spacebars.include(function() {\n        return Spacebars.call(view.templateElseBlock);\n      });\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_simple_helper\", (function() {\n  var view = this;\n  return Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"foo\"), view.lookup(\"bar\"));\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_dynamic_template\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"foo\"));\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_interpolate_attribute\", (function() {\n  var view = this;\n  return HTML.DIV({\n    \"class\": function() {\n      return [ \"aaa\", Spacebars.mustache(view.lookup(\"foo\"), view.lookup(\"bar\")), \"zzz\" ];\n    }\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_dynamic_attrs\", (function() {\n  var view = this;\n  return HTML.SPAN(HTML.Attrs(function() {\n    return Spacebars.attrMustache(view.lookup(\"attrsObj\"));\n  }, function() {\n    return Spacebars.attrMustache(view.lookup(\"singleAttr\"));\n  }, function() {\n    return Spacebars.attrMustache(view.lookup(\"nonexistent\"));\n  }), \"hi\");\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_triple\", (function() {\n  var view = this;\n  return Blaze.View(function() {\n    return Spacebars.makeRaw(Spacebars.mustache(view.lookup(\"html\")));\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_triple2\", (function() {\n  var view = this;\n  return [ \"x\", Blaze.View(function() {\n    return Spacebars.makeRaw(Spacebars.mustache(view.lookup(\"html\")));\n  }), Blaze.View(function() {\n    return Spacebars.makeRaw(Spacebars.mustache(view.lookup(\"html2\")));\n  }), Blaze.View(function() {\n    return Spacebars.makeRaw(Spacebars.mustache(view.lookup(\"html3\")));\n  }), \"y\" ];\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_inclusion_args\", (function() {\n  var view = this;\n  return Spacebars.TemplateWith(function() {\n    return Spacebars.call(view.lookup(\"bar\"));\n  }, function() {\n    return Spacebars.include(view.lookupTemplate(\"foo\"));\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_inclusion_args2\", (function() {\n  var view = this;\n  return Spacebars.TemplateWith(function() {\n    return Spacebars.dataMustache(view.lookup(\"bar\"), Spacebars.kw({\n      q: view.lookup(\"baz\")\n    }));\n  }, function() {\n    return Spacebars.include(view.lookupTemplate(\"foo\"));\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_inclusion_dotted_args\", (function() {\n  var view = this;\n  return Spacebars.TemplateWith(function() {\n    return Spacebars.call(Spacebars.dot(view.lookup(\"bar\"), \"baz\"));\n  }, function() {\n    return Spacebars.include(view.lookupTemplate(\"foo\"));\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_inclusion_slashed_args\", (function() {\n  var view = this;\n  return Spacebars.TemplateWith(function() {\n    return Spacebars.call(Spacebars.dot(view.lookup(\"bar\"), \"baz\"));\n  }, function() {\n    return Spacebars.include(view.lookupTemplate(\"foo\"));\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_block_helper\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"foo\"), function() {\n    return \"\\n    bar\\n  \";\n  }, function() {\n    return \"\\n    baz\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_block_helper_function_one_string_arg\", (function() {\n  var view = this;\n  return Spacebars.TemplateWith(function() {\n    return \"bar\";\n  }, function() {\n    return Spacebars.include(view.lookupTemplate(\"foo\"), function() {\n      return \"\\n    content\\n  \";\n    });\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_block_helper_function_one_helper_arg\", (function() {\n  var view = this;\n  return Spacebars.TemplateWith(function() {\n    return Spacebars.call(view.lookup(\"bar\"));\n  }, function() {\n    return Spacebars.include(view.lookupTemplate(\"foo\"), function() {\n      return \"\\n    content\\n  \";\n    });\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_block_helper_component_one_helper_arg\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"bar\"));\n  }, function() {\n    return \"\\n    content\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_block_helper_component_three_helper_args\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return Spacebars.dataMustache(view.lookup(\"equals\"), view.lookup(\"bar_or_baz\"), \"bar\");\n  }, function() {\n    return \"\\n    content\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_block_helper_dotted_arg\", (function() {\n  var view = this;\n  return Spacebars.TemplateWith(function() {\n    return Spacebars.dataMustache(Spacebars.dot(view.lookup(\"bar\"), \"baz\"), view.lookup(\"qux\"));\n  }, function() {\n    return Spacebars.include(view.lookupTemplate(\"foo\"), function() {\n      return null;\n    });\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_nested_content\", (function() {\n  var view = this;\n  return Spacebars.TemplateWith(function() {\n    return {\n      condition: Spacebars.call(view.lookup(\"flag\"))\n    };\n  }, function() {\n    return Spacebars.include(view.lookupTemplate(\"old_spacebars_template_test_iftemplate\"), function() {\n      return \"\\n    hello\\n  \";\n    }, function() {\n      return \"\\n    world\\n  \";\n    });\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_iftemplate2\", (function() {\n  var view = this;\n  return Spacebars.TemplateWith(function() {\n    return {\n      condition: Spacebars.call(view.lookup(\"flag\"))\n    };\n  }, function() {\n    return Spacebars.include(view.lookupTemplate(\"old_spacebars_template_test_iftemplate\"), function() {\n      return [ \"\\n    \", Blaze.InOuterTemplateScope(view, function() {\n        return Spacebars.include(function() {\n          return Spacebars.call(view.templateContentBlock);\n        });\n      }), \"\\n  \" ];\n    }, function() {\n      return [ \"\\n    \", Blaze.InOuterTemplateScope(view, function() {\n        return Spacebars.include(function() {\n          return Spacebars.call(view.templateElseBlock);\n        });\n      }), \"\\n  \" ];\n    });\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_nested_content2\", (function() {\n  var view = this;\n  return Spacebars.TemplateWith(function() {\n    return {\n      flag: Spacebars.call(view.lookup(\"x\"))\n    };\n  }, function() {\n    return Spacebars.include(view.lookupTemplate(\"old_spacebars_template_test_iftemplate2\"), function() {\n      return \"\\n    hello\\n  \";\n    }, function() {\n      return \"\\n    world\\n  \";\n    });\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_if\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"foo\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"bar\"));\n    }), \"\\n  \" ];\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"baz\"));\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_if_in_with\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"foo\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"bar\"));\n    }), \"\\n    \", Blaze.If(function() {\n      return true;\n    }, function() {\n      return [ \"\\n      \", Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\"bar\"));\n      }), \"\\n    \" ];\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_each\", (function() {\n  var view = this;\n  return Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"items\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"text\"));\n    }), \"\\n  \" ];\n  }, function() {\n    return \"\\n    else-clause\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_dots\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"foo\"));\n  }, function() {\n    return [ \"\\n    A\\n    \", Spacebars.With(function() {\n      return Spacebars.call(view.lookup(\"bar\"));\n    }, function() {\n      return [ \"\\n      B\\n      \\n      \", Blaze.If(function() {\n        return true;\n      }, function() {\n        return [ \"\\n        C\\n        \", Blaze.Each(function() {\n          return Spacebars.call(view.lookup(\"items\"));\n        }, function() {\n          return [ \"\\n          D\\n          \\n          \", Spacebars.include(view.lookupTemplate(\"old_spacebars_template_test_dots_subtemplate\")), \"\\n          \", Spacebars.TemplateWith(function() {\n            return Spacebars.call(view.lookup(\"..\"));\n          }, function() {\n            return Spacebars.include(view.lookupTemplate(\"old_spacebars_template_test_dots_subtemplate\"));\n          }), \"\\n        \" ];\n        }), \"\\n      \" ];\n      }), \"\\n    \" ];\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_dots_subtemplate\", (function() {\n  var view = this;\n  return [ \"TITLE\\n  1\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"title\"));\n  }), \"\\n  2\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\".\"), \"title\"));\n  }), \"\\n  3\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"..\"), \"title\"));\n  }), \"\\n  4\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"...\"), \"title\"));\n  }), \"\\n\\n  GETTITLE\\n  5\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"getTitle\"), view.lookup(\".\"));\n  }), \"\\n  6\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"getTitle\"), view.lookup(\"..\"));\n  }), \"\\n  7\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"getTitle\"), view.lookup(\"...\"));\n  }) ];\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_select_tag\", (function() {\n  var view = this;\n  return HTML.SELECT(\"\\n    \", Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"optgroups\"));\n  }, function() {\n    return [ \"\\n      \", HTML.OPTGROUP({\n      label: function() {\n        return Spacebars.mustache(view.lookup(\"label\"));\n      }\n    }, \"\\n        \", Blaze.Each(function() {\n      return Spacebars.call(view.lookup(\"options\"));\n    }, function() {\n      return [ \"\\n          \", HTML.OPTION(HTML.Attrs({\n        value: function() {\n          return Spacebars.mustache(view.lookup(\"value\"));\n        }\n      }, function() {\n        return Spacebars.attrMustache(view.lookup(\"selectedAttr\"));\n      }), Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\"label\"));\n      })), \"\\n        \" ];\n    }), \"\\n      \"), \"\\n    \" ];\n  }), \"\\n  \");\n}));\n\nTemplate.__define__(\"old_test_template_issue770\", (function() {\n  var view = this;\n  return [ Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"value1\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\".\"));\n    }), \"\\n  \" ];\n  }, function() {\n    return \"\\n    xxx\\n  \";\n  }), \"\\n\\n  \", Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"value2\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\".\"));\n    }), \"\\n  \" ];\n  }, function() {\n    return \"\\n    xxx\\n  \";\n  }), \"\\n\\n  \", Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"value1\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\".\"));\n    }), \"\\n  \" ];\n  }), \"\\n\\n  \", Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"value2\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\".\"));\n    }), \"\\n  \" ];\n  }) ];\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_tricky_attrs\", (function() {\n  var view = this;\n  return [ HTML.INPUT({\n    type: function() {\n      return Spacebars.mustache(view.lookup(\"theType\"));\n    }\n  }), HTML.INPUT({\n    type: \"checkbox\",\n    \"class\": function() {\n      return Spacebars.mustache(view.lookup(\"theClass\"));\n    }\n  }) ];\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_no_data\", (function() {\n  var view = this;\n  return [ Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\".\"), \"foo\"));\n  }), Blaze.Unless(function() {\n    return Spacebars.call(Spacebars.dot(view.lookup(\".\"), \"bar\"));\n  }, function() {\n    return \"asdf\";\n  }) ];\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_textarea\", (function() {\n  var view = this;\n  return HTML.TEXTAREA({\n    value: function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_textarea2\", (function() {\n  var view = this;\n  return HTML.TEXTAREA({\n    value: function() {\n      return Blaze.If(function() {\n        return Spacebars.call(view.lookup(\"foo\"));\n      }, function() {\n        return \"</not a tag>\";\n      }, function() {\n        return \"<also not a tag>\";\n      });\n    }\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_textarea3\", (function() {\n  var view = this;\n  return HTML.TEXTAREA({\n    id: \"myTextarea\",\n    value: function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_textarea_each\", (function() {\n  var view = this;\n  return HTML.TEXTAREA({\n    value: function() {\n      return Blaze.Each(function() {\n        return Spacebars.call(view.lookup(\"foo\"));\n      }, function() {\n        return [ \"<not a tag \", Blaze.View(function() {\n          return Spacebars.mustache(view.lookup(\".\"));\n        }), \" \" ];\n      }, function() {\n        return \"<>\";\n      });\n    }\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_defer_in_rendered\", (function() {\n  var view = this;\n  return Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"items\"));\n  }, function() {\n    return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"old_spacebars_template_test_defer_in_rendered_subtemplate\")), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_defer_in_rendered_subtemplate\", (function() {\n  var view = this;\n  return \"\";\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_with_someData\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"someData\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }), \" \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"bar\"));\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_each_stops\", (function() {\n  var view = this;\n  return Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"items\"));\n  }, function() {\n    return \"\\n    x\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_block_helpers_in_attribute\", (function() {\n  var view = this;\n  return HTML.DIV({\n    \"class\": function() {\n      return Blaze.Each(function() {\n        return Spacebars.call(view.lookup(\"classes\"));\n      }, function() {\n        return Blaze.If(function() {\n          return Spacebars.dataMustache(view.lookup(\"startsLowerCase\"), view.lookup(\"name\"));\n        }, function() {\n          return [ Blaze.View(function() {\n            return Spacebars.mustache(view.lookup(\"name\"));\n          }), \" \" ];\n        });\n      }, function() {\n        return \"none\";\n      });\n    }\n  }, \"Smurf\");\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_block_helpers_in_attribute_2\", (function() {\n  var view = this;\n  return HTML.INPUT({\n    value: function() {\n      return Blaze.If(function() {\n        return Spacebars.call(view.lookup(\"foo\"));\n      }, function() {\n        return '\"';\n      }, function() {\n        return [ \"&\", HTML.CharRef({\n          html: \"&lt;\",\n          str: \"<\"\n        }), \"></x>\" ];\n      });\n    }\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_constant_each_argument\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"someData\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.Each(function() {\n      return Spacebars.call(view.lookup(\"anArray\"));\n    }, function() {\n      return [ \"\\n      \", Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\"justReturn\"), view.lookup(\".\"));\n      }), \"\\n    \" ];\n    }), \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\".\"));\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_markdown_basic\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"obj\"));\n  }, function() {\n    return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"markdown\"), function() {\n      return [ \"\\n\", Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\"hi\"));\n      }), \"\\n/each}}\\n\\n<b>\", Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\"hi\"));\n      }), \"</b>\\n<b>/each}}</b>\\n\\n* \", Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\"hi\"));\n      }), \"\\n* /each}}\\n\\n* <b>\", Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\"hi\"));\n      }), \"</b>\\n* <b>/each}}</b>\\n\\nsome paragraph to fix showdown's four space parsing below.\\n\\n    \", Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\"hi\"));\n      }), \"\\n    /each}}\\n\\n    <b>\", Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\"hi\"));\n      }), \"</b>\\n    <b>/each}}</b>\\n\\n&gt\\n\\n* &gt\\n\\n`&gt`\\n\\n    &gt\\n\\n&gt;\\n\\n* &gt;\\n\\n`&gt;`\\n\\n    &gt;\\n\\n`\", Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\"hi\"));\n      }), \"`\\n`/each}}`\\n\\n`<b>\", Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\"hi\"));\n      }), \"</b>`\\n`<b>/each}}`\\n\\n    \" ];\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_markdown_if\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"markdown\"), function() {\n    return [ \"\\n\\n\", Blaze.If(function() {\n      return Spacebars.call(view.lookup(\"cond\"));\n    }, function() {\n      return \"true\";\n    }, function() {\n      return \"false\";\n    }), \"\\n\\n<b>\", Blaze.If(function() {\n      return Spacebars.call(view.lookup(\"cond\"));\n    }, function() {\n      return \"true\";\n    }, function() {\n      return \"false\";\n    }), \"</b>\\n\\n* \", Blaze.If(function() {\n      return Spacebars.call(view.lookup(\"cond\"));\n    }, function() {\n      return \"true\";\n    }, function() {\n      return \"false\";\n    }), \"\\n\\n* <b>\", Blaze.If(function() {\n      return Spacebars.call(view.lookup(\"cond\"));\n    }, function() {\n      return \"true\";\n    }, function() {\n      return \"false\";\n    }), \"</b>\\n\\nsome paragraph to fix showdown's four space parsing below.\\n\\n    \", Blaze.If(function() {\n      return Spacebars.call(view.lookup(\"cond\"));\n    }, function() {\n      return \"true\";\n    }, function() {\n      return \"false\";\n    }), \"\\n\\n    <b>\", Blaze.If(function() {\n      return Spacebars.call(view.lookup(\"cond\"));\n    }, function() {\n      return \"true\";\n    }, function() {\n      return \"false\";\n    }), \"</b>\\n\\n`\", Blaze.If(function() {\n      return Spacebars.call(view.lookup(\"cond\"));\n    }, function() {\n      return \"true\";\n    }, function() {\n      return \"false\";\n    }), \"`\\n\\n`<b>\", Blaze.If(function() {\n      return Spacebars.call(view.lookup(\"cond\"));\n    }, function() {\n      return \"true\";\n    }, function() {\n      return \"false\";\n    }), \"</b>`\\n\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_markdown_each\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"markdown\"), function() {\n    return [ \"\\n\\n\", Blaze.Each(function() {\n      return Spacebars.call(view.lookup(\"seq\"));\n    }, function() {\n      return Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\".\"));\n      });\n    }), \"\\n\\n<b>\", Blaze.Each(function() {\n      return Spacebars.call(view.lookup(\"seq\"));\n    }, function() {\n      return Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\".\"));\n      });\n    }), \"</b>\\n\\n* \", Blaze.Each(function() {\n      return Spacebars.call(view.lookup(\"seq\"));\n    }, function() {\n      return Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\".\"));\n      });\n    }), \"\\n\\n* <b>\", Blaze.Each(function() {\n      return Spacebars.call(view.lookup(\"seq\"));\n    }, function() {\n      return Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\".\"));\n      });\n    }), \"</b>\\n\\nsome paragraph to fix showdown's four space parsing below.\\n\\n    \", Blaze.Each(function() {\n      return Spacebars.call(view.lookup(\"seq\"));\n    }, function() {\n      return Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\".\"));\n      });\n    }), \"\\n\\n    <b>\", Blaze.Each(function() {\n      return Spacebars.call(view.lookup(\"seq\"));\n    }, function() {\n      return Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\".\"));\n      });\n    }), \"</b>\\n\\n`\", Blaze.Each(function() {\n      return Spacebars.call(view.lookup(\"seq\"));\n    }, function() {\n      return Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\".\"));\n      });\n    }), \"`\\n\\n`<b>\", Blaze.Each(function() {\n      return Spacebars.call(view.lookup(\"seq\"));\n    }, function() {\n      return Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\".\"));\n      });\n    }), \"</b>`\\n\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_markdown_inclusion\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"markdown\"), function() {\n    return [ \"\\n\", Spacebars.include(view.lookupTemplate(\"old_spacebars_template_test_markdown_inclusion_subtmpl\")), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_markdown_inclusion_subtmpl\", (function() {\n  var view = this;\n  return HTML.SPAN(Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"foo\"));\n  }, function() {\n    return [ \"Foo is \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }), \".\" ];\n  }));\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_markdown_block_helpers\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"markdown\"), function() {\n    return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"old_spacebars_template_test_just_content\"), function() {\n      return \"\\nHi there!\\n    \";\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_just_content\", (function() {\n  var view = this;\n  return Blaze.InOuterTemplateScope(view, function() {\n    return Spacebars.include(function() {\n      return Spacebars.call(view.templateContentBlock);\n    });\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_simple_helpers_are_isolated\", (function() {\n  var view = this;\n  return Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"foo\"));\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_attr_helpers_are_isolated\", (function() {\n  var view = this;\n  return HTML.P({\n    attr: function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_attr_object_helpers_are_isolated\", (function() {\n  var view = this;\n  return HTML.P(HTML.Attrs(function() {\n    return Spacebars.attrMustache(view.lookup(\"attrs\"));\n  }));\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_inclusion_helpers_are_isolated\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"foo\"));\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_inclusion_helpers_are_isolated_subtemplate\", (function() {\n  var view = this;\n  return \"\";\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_nully_attributes0\", (function() {\n  var view = this;\n  return HTML.Raw('<input type=\"checkbox\" checked=\"\" stuff=\"\">');\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_nully_attributes1\", (function() {\n  var view = this;\n  return HTML.INPUT({\n    type: \"checkbox\",\n    checked: function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    },\n    stuff: function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_nully_attributes2\", (function() {\n  var view = this;\n  return HTML.INPUT({\n    type: \"checkbox\",\n    checked: function() {\n      return [ Spacebars.mustache(view.lookup(\"foo\")), Spacebars.mustache(view.lookup(\"bar\")) ];\n    },\n    stuff: function() {\n      return [ Spacebars.mustache(view.lookup(\"foo\")), Spacebars.mustache(view.lookup(\"bar\")) ];\n    }\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_nully_attributes3\", (function() {\n  var view = this;\n  return HTML.INPUT({\n    type: \"checkbox\",\n    checked: function() {\n      return Blaze.If(function() {\n        return Spacebars.call(view.lookup(\"foo\"));\n      }, function() {\n        return null;\n      });\n    },\n    stuff: function() {\n      return Blaze.If(function() {\n        return Spacebars.call(view.lookup(\"foo\"));\n      }, function() {\n        return null;\n      });\n    }\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_double\", (function() {\n  var view = this;\n  return Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"foo\"));\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_inclusion_lookup\", (function() {\n  var view = this;\n  return [ Spacebars.include(view.lookupTemplate(\"old_spacebars_template_test_inclusion_lookup_subtmpl\")), \"\\n  \", Spacebars.include(view.lookupTemplate(\"dataContextSubtmpl\")) ];\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_inclusion_lookup_subtmpl\", (function() {\n  var view = this;\n  return \"This is the template.\";\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_inclusion_lookup_subtmpl2\", (function() {\n  var view = this;\n  return \"This is generated by a helper with the same name.\";\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_inclusion_lookup_subtmpl3\", (function() {\n  var view = this;\n  return \"This is a template passed in the data context.\";\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_content_context\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"foo\"));\n  }, function() {\n    return [ \"\\n    \", Spacebars.With(function() {\n      return Spacebars.call(view.lookup(\"bar\"));\n    }, function() {\n      return [ \"\\n      \", Spacebars.TemplateWith(function() {\n        return {\n          condition: Spacebars.call(view.lookup(\"cond\"))\n        };\n      }, function() {\n        return Spacebars.include(view.lookupTemplate(\"old_spacebars_template_test_iftemplate\"), function() {\n          return [ \"\\n        \", Blaze.View(function() {\n            return Spacebars.mustache(view.lookup(\"firstLetter\"));\n          }), Blaze.View(function() {\n            return Spacebars.mustache(Spacebars.dot(view.lookup(\"..\"), \"secondLetter\"));\n          }), \"\\n      \" ];\n        }, function() {\n          return [ \"\\n        \", Blaze.View(function() {\n            return Spacebars.mustache(Spacebars.dot(view.lookup(\"..\"), \"firstLetter\"));\n          }), Blaze.View(function() {\n            return Spacebars.mustache(view.lookup(\"secondLetter\"));\n          }), \"\\n      \" ];\n        });\n      }), \"\\n    \" ];\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_control_input\", (function() {\n  var view = this;\n  return HTML.INPUT({\n    type: function() {\n      return Spacebars.mustache(view.lookup(\"type\"));\n    },\n    value: function() {\n      return Spacebars.mustache(view.lookup(\"value\"));\n    }\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_control_textarea\", (function() {\n  var view = this;\n  return HTML.TEXTAREA({\n    value: function() {\n      return Spacebars.mustache(view.lookup(\"value\"));\n    }\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_control_select\", (function() {\n  var view = this;\n  return HTML.SELECT(\"\\n    \", Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"options\"));\n  }, function() {\n    return [ \"\\n      \", HTML.OPTION({\n      selected: function() {\n        return Spacebars.mustache(view.lookup(\"selected\"));\n      }\n    }, Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\".\"));\n    })), \"\\n    \" ];\n  }), \"\\n  \");\n}));\n\nTemplate.__define__(\"old_spacebars_test_control_radio\", (function() {\n  var view = this;\n  return [ \"Band:\\n\\n  \", Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"bands\"));\n  }, function() {\n    return [ \"\\n    \", HTML.INPUT({\n      name: \"bands\",\n      type: \"radio\",\n      value: function() {\n        return Spacebars.mustache(view.lookup(\".\"));\n      },\n      checked: function() {\n        return Spacebars.mustache(view.lookup(\"isChecked\"));\n      }\n    }), \"\\n  \" ];\n  }), \"\\n\\n  \", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"band\"));\n  }) ];\n}));\n\nTemplate.__define__(\"old_spacebars_test_control_checkbox\", (function() {\n  var view = this;\n  return Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"labels\"));\n  }, function() {\n    return [ \"\\n    \", HTML.INPUT({\n      type: \"checkbox\",\n      value: function() {\n        return Spacebars.mustache(view.lookup(\".\"));\n      },\n      checked: function() {\n        return Spacebars.mustache(view.lookup(\"isChecked\"));\n      }\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_nonexistent_template\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"this_template_lives_in_outer_space\"));\n}));\n\nTemplate.__define__(\"old_spacebars_test_if_helper\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"foo\"));\n  }, function() {\n    return \"\\n    true\\n  \";\n  }, function() {\n    return \"\\n    false\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_block_helper_function\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"foo\"), function() {\n    return \"\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_onetwo\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"showOne\"));\n  }, function() {\n    return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"one\")), \"\\n  \" ];\n  }, function() {\n    return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"two\")), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_onetwo_attribute\", (function() {\n  var view = this;\n  return HTML.BR({\n    \"data-stuff\": function() {\n      return Blaze.If(function() {\n        return Spacebars.call(view.lookup(\"showOne\"));\n      }, function() {\n        return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"one\")), \"\\n  \" ];\n      }, function() {\n        return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"two\")), \"\\n  \" ];\n      });\n    }\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_with1\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"options\"));\n  }, function() {\n    return \"\\n    one\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_with2\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"options\"));\n  }, function() {\n    return \"\\n    two\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_each1\", (function() {\n  var view = this;\n  return Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"options\"));\n  }, function() {\n    return \"\\n    one\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_each2\", (function() {\n  var view = this;\n  return Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"options\"));\n  }, function() {\n    return \"\\n    two\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_with_each1\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"options\"));\n  }, function() {\n    return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_helpers_stop_with_each3\")), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_with_each2\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"options\"));\n  }, function() {\n    return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_helpers_stop_with_each3\")), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_with_each3\", (function() {\n  var view = this;\n  return Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\".\"));\n  }, function() {\n    return \"\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_if1\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"options\"));\n  }, function() {\n    return \"\\n    one\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_if2\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"options\"));\n  }, function() {\n    return \"\\n    two\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_inclusion1\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"options\"));\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_inclusion2\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"options\"));\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_inclusion3\", (function() {\n  var view = this;\n  return \"blah\";\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_with_callbacks1\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"options\"));\n  }, function() {\n    return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_helpers_stop_with_callbacks3\")), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_with_callbacks2\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"options\"));\n  }, function() {\n    return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_helpers_stop_with_callbacks3\")), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_with_callbacks3\", (function() {\n  var view = this;\n  return \"blah\";\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_unless1\", (function() {\n  var view = this;\n  return Blaze.Unless(function() {\n    return Spacebars.call(view.lookup(\"options\"));\n  }, function() {\n    return \"\\n    one\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_stop_unless2\", (function() {\n  var view = this;\n  return Blaze.Unless(function() {\n    return Spacebars.call(view.lookup(\"options\"));\n  }, function() {\n    return \"\\n    two\\n  \";\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_no_data_context\", (function() {\n  var view = this;\n  return [ HTML.Raw(\"<button></button>\\n  \"), Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"foo\"));\n  }) ];\n}));\n\nTemplate.__define__(\"old_spacebars_test_falsy_with\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"obj\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"greekLetter\"));\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_dont_leak\", (function() {\n  var view = this;\n  return Spacebars.TemplateWith(function() {\n    return {\n      foo: Spacebars.call(\"correct\")\n    };\n  }, function() {\n    return Spacebars.include(view.lookupTemplate(\"old_spacebars_test_helpers_dont_leak2\"));\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_helpers_dont_leak2\", (function() {\n  var view = this;\n  return [ Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"foo\"));\n  }), Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"bar\"));\n  }), \" \", Spacebars.include(view.lookupTemplate(\"old_spacebars_template_test_content\"), function() {\n    return Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"bonus\"));\n    });\n  }) ];\n}));\n\nTemplate.__define__(\"old_spacebars_test_event_returns_false\", (function() {\n  var view = this;\n  return HTML.Raw('<a href=\"#bad-url\" id=\"spacebars_test_event_returns_false_link\">click me</a>');\n}));\n\nTemplate.__define__(\"old_spacebars_test_event_selectors1\", (function() {\n  var view = this;\n  return HTML.DIV(Spacebars.include(view.lookupTemplate(\"old_spacebars_test_event_selectors2\")));\n}));\n\nTemplate.__define__(\"old_spacebars_test_event_selectors2\", (function() {\n  var view = this;\n  return HTML.Raw('<p class=\"p1\">Not it</p>\\n  <div><p class=\"p2\">It</p></div>');\n}));\n\nTemplate.__define__(\"old_spacebars_test_event_selectors_capturing1\", (function() {\n  var view = this;\n  return HTML.DIV(Spacebars.include(view.lookupTemplate(\"old_spacebars_test_event_selectors_capturing2\")));\n}));\n\nTemplate.__define__(\"old_spacebars_test_event_selectors_capturing2\", (function() {\n  var view = this;\n  return HTML.Raw('<video class=\"video1\">\\n    <source id=\"mp4\" src=\"http://media.w3.org/2010/05/sintel/trailer.mp4\" type=\"video/mp4\">\\n  </video>\\n  <div>\\n    <video class=\"video2\">\\n      <source id=\"mp4\" src=\"http://media.w3.org/2010/05/sintel/trailer.mp4\" type=\"video/mp4\">\\n    </video>\\n  </div>');\n}));\n\nTemplate.__define__(\"old_spacebars_test_tables1\", (function() {\n  var view = this;\n  return HTML.TABLE(HTML.TR(HTML.TD(\"Foo\")));\n}));\n\nTemplate.__define__(\"old_spacebars_test_tables2\", (function() {\n  var view = this;\n  return HTML.TABLE(HTML.TR(HTML.TD(Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"foo\"));\n  }))));\n}));\n\nTemplate.__define__(\"old_spacebars_test_jquery_events\", (function() {\n  var view = this;\n  return HTML.Raw('<button type=\"button\">button</button>');\n}));\n\nTemplate.__define__(\"old_spacebars_test_tohtml_basic\", (function() {\n  var view = this;\n  return Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"foo\"));\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_tohtml_if\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return true;\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_tohtml_with\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"foo\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\".\"));\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_tohtml_each\", (function() {\n  var view = this;\n  return Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"foos\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\".\"));\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_tohtml_include_with\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"old_spacebars_test_tohtml_with\"));\n}));\n\nTemplate.__define__(\"old_spacebars_test_tohtml_include_each\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"old_spacebars_test_tohtml_each\"));\n}));\n\nTemplate.__define__(\"old_spacebars_test_block_comment\", (function() {\n  var view = this;\n  return \"\\n  \";\n}));\n\nTemplate.__define__(\"old_spacebars_test_with_mutated_data_context\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"foo\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"value\"));\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_url_attribute\", (function() {\n  var view = this;\n  return [ HTML.A({\n    href: function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }\n  }), \"\\n  \", HTML.A({\n    href: function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }\n  }), \"\\n  \", HTML.FORM({\n    action: function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }\n  }), \"\\n  \", HTML.IMG({\n    src: function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }\n  }), \"\\n  \", HTML.INPUT({\n    value: function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }\n  }) ];\n}));\n\nTemplate.__define__(\"old_spacebars_test_event_handler_cleanup\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"foo\"));\n  }, function() {\n    return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_event_handler_cleanup_sub\")), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_event_handler_cleanup_sub\", (function() {\n  var view = this;\n  return HTML.Raw(\"<div></div>\");\n}));\n\nTemplate.__define__(\"old_spacebars_test_data_context_for_event_handler_in_if\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return {\n      foo: Spacebars.call(\"bar\")\n    };\n  }, function() {\n    return [ \"\\n    \", Blaze.If(function() {\n      return true;\n    }, function() {\n      return [ \"\\n      \", HTML.SPAN(\"Click me!\"), \"\\n    \" ];\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_each_with_autorun_insert\", (function() {\n  var view = this;\n  return Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"items\"));\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"name\"));\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_ui_hooks\", (function() {\n  var view = this;\n  return HTML.DIV({\n    \"class\": \"test-ui-hooks\"\n  }, \"\\n    \", Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"items\"));\n  }, function() {\n    return [ \"\\n      \", HTML.DIV({\n      \"class\": \"item\"\n    }, Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"_id\"));\n    })), \"\\n    \" ];\n  }), \"\\n  \");\n}));\n\nTemplate.__define__(\"old_spacebars_test_ui_hooks_nested\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"foo\"));\n  }, function() {\n    return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_ui_hooks_nested_sub\")), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_ui_hooks_nested_sub\", (function() {\n  var view = this;\n  return HTML.DIV(\"\\n    \", Spacebars.With(function() {\n    return true;\n  }, function() {\n    return [ \"\\n      \", HTML.P(\"hello\"), \"\\n    \" ];\n  }), \"\\n  \");\n}));\n\nTemplate.__define__(\"old_spacebars_test_template_instance_helper\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return true;\n  }, function() {\n    return Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    });\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_with_cleanup\", (function() {\n  var view = this;\n  return HTML.DIV({\n    \"class\": \"test-with-cleanup\"\n  }, \"\\n    \", Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"foo\"));\n  }, function() {\n    return [ \"\\n      \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\".\"));\n    }), \"\\n    \" ];\n  }), \"\\n  \");\n}));\n\nTemplate.__define__(\"old_spacebars_test_template_parent_data_helper\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return \"parent\";\n  }, function() {\n    return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_template_parent_data_helper_child\")), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_template_parent_data_helper_child\", (function() {\n  var view = this;\n  return Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"a\"));\n  }, function() {\n    return [ \"\\n    \", Spacebars.With(function() {\n      return Spacebars.call(view.lookup(\"b\"));\n    }, function() {\n      return [ \"\\n      \", Blaze.If(function() {\n        return Spacebars.call(view.lookup(\"c\"));\n      }, function() {\n        return [ \"\\n        \", Spacebars.With(function() {\n          return \"d\";\n        }, function() {\n          return [ \"\\n          \", Blaze.View(function() {\n            return Spacebars.mustache(view.lookup(\"foo\"));\n          }), \"\\n        \" ];\n        }), \"\\n      \" ];\n      }), \"\\n    \" ];\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_svg_anchor\", (function() {\n  var view = this;\n  return HTML.SVG(\"\\n    \", HTML.A({\n    \"xlink:href\": \"http://www.example.com\"\n  }, \"Foo\"), \"\\n  \");\n}));\n\nTemplate.__define__(\"old_spacebars_test_template_created_rendered_destroyed_each\", (function() {\n  var view = this;\n  return Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"items\"));\n  }, function() {\n    return [ \"\\n    \", HTML.DIV(Spacebars.TemplateWith(function() {\n      return Spacebars.call(view.lookup(\"_id\"));\n    }, function() {\n      return Spacebars.include(view.lookupTemplate(\"old_spacebars_test_template_created_rendered_destroyed_each_sub\"));\n    })), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_template_created_rendered_destroyed_each_sub\", (function() {\n  var view = this;\n  return Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\".\"));\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_ui_getElementData\", (function() {\n  var view = this;\n  return HTML.Raw(\"<span></span>\");\n}));\n\nTemplate.__define__(\"old_spacebars_test_ui_render\", (function() {\n  var view = this;\n  return HTML.SPAN(Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"greeting\"));\n  }), \" \", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"r\"));\n  }));\n}));\n\nTemplate.__define__(\"old_spacebars_test_parent_removal\", (function() {\n  var view = this;\n  return HTML.DIV({\n    \"class\": \"a\"\n  }, \"\\n    \", HTML.DIV({\n    \"class\": \"b\"\n  }, \"\\n      \", HTML.DIV({\n    \"class\": \"toremove\"\n  }, \"\\n        \", HTML.DIV({\n    \"class\": \"c\"\n  }, \"\\n          \", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"A\"), 1);\n  }), \"\\n          \", Blaze.View(function() {\n    return Spacebars.makeRaw(Spacebars.mustache(view.lookup(\"A\"), 2));\n  }), \"\\n          \", Spacebars.With(function() {\n    return Spacebars.dataMustache(view.lookup(\"A\"), 3);\n  }, function() {\n    return [ \"\\n            \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"A\"), 4);\n    }), \"\\n            \", Spacebars.With(function() {\n      return Spacebars.dataMustache(view.lookup(\"A\"), 5);\n    }, function() {\n      return [ \"\\n              \", Blaze.View(function() {\n        return Spacebars.mustache(view.lookup(\"A\"), 6);\n      }), \"\\n            \" ];\n    }), \"\\n          \" ];\n  }), \"\\n          \", Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"B\"));\n  }, function() {\n    return [ \"\\n            \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"A\"), 7);\n    }), \"\\n          \" ];\n  }), \"\\n          \", Blaze.If(function() {\n    return Spacebars.dataMustache(view.lookup(\"A\"), 8);\n  }, function() {\n    return [ \"\\n            \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"A\"), 9);\n    }), \"\\n          \" ];\n  }, function() {\n    return [ \"\\n            \", Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"A\"), \"a\");\n    }), \"\\n          \" ];\n  }), \"\\n        \"), \"\\n      \"), \"\\n    \"), \"\\n  \");\n}));\n\nTemplate.__define__(\"old_spacebars_test_focus_blur_outer\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"cond\"));\n  }, function() {\n    return [ \"\\n    a \", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_focus_blur_inner\")), \"\\n  \" ];\n  }, function() {\n    return [ \"\\n    b \", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_focus_blur_inner\")), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_focus_blur_inner\", (function() {\n  var view = this;\n  return HTML.Raw('<input type=\"text\">');\n}));\n\nTemplate.__define__(\"old_spacebars_test_event_cleanup_on_destroyed_outer\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"cond\"));\n  }, function() {\n    return [ \"\\n    \", HTML.DIV(\"a \", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_event_cleanup_on_destroyed_inner\"))), \"\\n  \" ];\n  }, function() {\n    return [ \"\\n    \", HTML.DIV(\"b \", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_event_cleanup_on_destroyed_inner\"))), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_event_cleanup_on_destroyed_inner\", (function() {\n  var view = this;\n  return HTML.Raw(\"<span>foo</span>\");\n}));\n\nTemplate.__define__(\"old_spacebars_test_isolated_lookup_inclusion\", (function() {\n  var view = this;\n  return \"x\";\n}));\n\nTemplate.__define__(\"old_spacebars_test_isolated_lookup1\", (function() {\n  var view = this;\n  return [ Spacebars.include(view.lookupTemplate(\"foo\")), \"--\", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_isolated_lookup_inclusion\")) ];\n}));\n\nTemplate.__define__(\"old_spacebars_test_isolated_lookup2\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"foo\"));\n  }, function() {\n    return [ \"\\n    \", Spacebars.With(function() {\n      return {\n        z: Spacebars.call(1)\n      };\n    }, function() {\n      return [ \"\\n      \", Spacebars.include(view.lookupTemplate(\"..\")), \"--\", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_isolated_lookup_inclusion\")), \"\\n    \" ];\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_isolated_lookup3\", (function() {\n  var view = this;\n  return [ Spacebars.include(view.lookupTemplate(\"bar\")), \"--\", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_isolated_lookup_inclusion\")) ];\n}));\n\nTemplate.__define__(\"old_spacebars_test_current_view_in_event\", (function() {\n  var view = this;\n  return HTML.SPAN(Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\".\"));\n  }));\n}));\n\nTemplate.__define__(\"old_spacebars_test_textarea_attrs\", (function() {\n  var view = this;\n  return HTML.TEXTAREA(HTML.Attrs(function() {\n    return Spacebars.attrMustache(view.lookup(\"attrs\"));\n  }));\n}));\n\nTemplate.__define__(\"old_spacebars_test_textarea_attrs_contents\", (function() {\n  var view = this;\n  return HTML.TEXTAREA(HTML.Attrs(function() {\n    return Spacebars.attrMustache(view.lookup(\"attrs\"));\n  }, {\n    value: function() {\n      return [ \"Hello \", Spacebars.mustache(view.lookup(\"name\")) ];\n    }\n  }));\n}));\n\nTemplate.__define__(\"old_spacebars_test_textarea_attrs_array_contents\", (function() {\n  var view = this;\n  return HTML.TEXTAREA(HTML.Attrs({\n    \"class\": \"bar\"\n  }, function() {\n    return Spacebars.attrMustache(view.lookup(\"attrs\"));\n  }, {\n    value: function() {\n      return [ \"Hello \", Spacebars.mustache(view.lookup(\"name\")) ];\n    }\n  }));\n}));\n\nTemplate.__define__(\"old_spacebars_test_autorun\", (function() {\n  var view = this;\n  return Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"show\"));\n  }, function() {\n    return [ \"\\n    \", Spacebars.include(view.lookupTemplate(\"old_spacebars_test_autorun_inner\")), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_autorun_inner\", (function() {\n  var view = this;\n  return \"Hello\";\n}));\n\nTemplate.__define__(\"old_spacebars_test_contentBlock_arg\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"old_spacebars_test_contentBlock_arg_inner\"), function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(Spacebars.dot(view.lookup(\".\"), \"bar\"));\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_test_contentBlock_arg_inner\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return {\n      foo: Spacebars.call(\"AAA\"),\n      bar: Spacebars.call(\"BBB\")\n    };\n  }, function() {\n    return [ \"\\n    \", Blaze.View(function() {\n      return Spacebars.mustache(Spacebars.dot(view.lookup(\".\"), \"foo\"));\n    }), \" \", Blaze.InOuterTemplateScope(view, function() {\n      return Spacebars.TemplateWith(function() {\n        return Spacebars.call(view.lookup(\".\"));\n      }, function() {\n        return Spacebars.include(function() {\n          return Spacebars.call(view.templateContentBlock);\n        });\n      });\n    }), \"\\n  \" ];\n  });\n}));\n\nTemplate.__define__(\"old_spacebars_template_test_input_field_to_same_value\", (function() {\n  var view = this;\n  return HTML.INPUT({\n    type: \"text\",\n    value: function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }\n  });\n}));\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n\nTemplate.__define__(\"old_test_assembly_a0\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"test_assembly_a1\"));\n}));\n\nTemplate.__define__(\"old_test_assembly_a1\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"test_assembly_a2\"));\n}));\n\nTemplate.__define__(\"old_test_assembly_a2\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"test_assembly_a3\"));\n}));\n\nTemplate.__define__(\"old_test_assembly_a3\", (function() {\n  var view = this;\n  return \"Hi\";\n}));\n\nTemplate.__define__(\"old_test_assembly_b0\", (function() {\n  var view = this;\n  return Spacebars.include(view.lookupTemplate(\"test_assembly_b1\"));\n}));\n\nTemplate.__define__(\"old_test_assembly_b1\", (function() {\n  var view = this;\n  return [ \"x\", Blaze.If(function() {\n    return Spacebars.call(view.lookup(\"stuff\"));\n  }, function() {\n    return \"y\";\n  }), Spacebars.include(view.lookupTemplate(\"test_assembly_b2\")) ];\n}));\n\nTemplate.__define__(\"old_test_assembly_b2\", (function() {\n  var view = this;\n  return \"hi\";\n}));\n\nTemplate.__define__(\"old_test_table_b0\", (function() {\n  var view = this;\n  return HTML.TABLE(\"\\n    \", HTML.TBODY(\"\\n      \", Spacebars.include(view.lookupTemplate(\"test_table_b1\")), \"\\n      \", Spacebars.include(view.lookupTemplate(\"test_table_b1\")), \"\\n      \", Spacebars.include(view.lookupTemplate(\"test_table_b1\")), \"\\n    \"), \"\\n  \");\n}));\n\nTemplate.__define__(\"old_test_table_b1\", (function() {\n  var view = this;\n  return HTML.TR(\"\\n    \", Spacebars.include(view.lookupTemplate(\"test_table_b2\")), \"\\n  \");\n}));\n\nTemplate.__define__(\"old_test_table_b2\", (function() {\n  var view = this;\n  return HTML.TD(\"\\n    \", Spacebars.include(view.lookupTemplate(\"test_table_b3\")), \"\\n  \");\n}));\n\nTemplate.__define__(\"old_test_table_b3\", (function() {\n  var view = this;\n  return \"Foo.\";\n}));\n\nTemplate.__define__(\"old_test_table_each\", (function() {\n  var view = this;\n  return HTML.TABLE(\"\\n    \", HTML.TBODY(\"\\n      \", Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"foo\"));\n  }, function() {\n    return [ \"\\n        \", HTML.TR(HTML.TD(Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"bar\"));\n    }))), \"\\n      \" ];\n  }), \"\\n    \"), \"\\n  \");\n}));\n\nTemplate.__define__(\"old_test_event_data_with\", (function() {\n  var view = this;\n  return HTML.DIV(\"\\n  xxx\\n  \", Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"TWO\"));\n  }, function() {\n    return [ \"\\n    \", HTML.DIV(\"\\n      xxx\\n      \", Spacebars.With(function() {\n      return Spacebars.call(view.lookup(\"THREE\"));\n    }, function() {\n      return [ \"\\n        \", HTML.DIV(\"\\n          xxx\\n        \"), \"\\n      \" ];\n    }), \"\\n    \"), \"\\n  \" ];\n  }), \"\\n\");\n}));\n\nTemplate.__define__(\"old_test_capture_events\", (function() {\n  var view = this;\n  return HTML.Raw('<video class=\"video1\">\\n    <source id=\"mp4\" src=\"\" type=\"video/mp4\">\\n  </video>\\n  <video class=\"video2\">\\n    <source id=\"mp4\" src=\"\" type=\"video/mp4\">\\n  </video>\\n  <video class=\"video2\">\\n    <source id=\"mp4\" src=\"\" type=\"video/mp4\">\\n  </video>');\n}));\n\nTemplate.__define__(\"old_test_safestring_a\", (function() {\n  var view = this;\n  return [ Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"foo\"));\n  }), \" \", Blaze.View(function() {\n    return Spacebars.makeRaw(Spacebars.mustache(view.lookup(\"foo\")));\n  }), \" \", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"bar\"));\n  }), \" \", Blaze.View(function() {\n    return Spacebars.makeRaw(Spacebars.mustache(view.lookup(\"bar\")));\n  }), \"\\n  \", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"fooprop\"));\n  }), \" \", Blaze.View(function() {\n    return Spacebars.makeRaw(Spacebars.mustache(view.lookup(\"fooprop\")));\n  }), \" \", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"barprop\"));\n  }), \" \", Blaze.View(function() {\n    return Spacebars.makeRaw(Spacebars.mustache(view.lookup(\"barprop\")));\n  }) ];\n}));\n\nTemplate.__define__(\"old_test_helpers_a\", (function() {\n  var view = this;\n  return [ \"platypus=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"platypus\"));\n  }), \"\\n  watermelon=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"watermelon\"));\n  }), \"\\n  daisy=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"daisy\"));\n  }), \"\\n  tree=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"tree\"));\n  }), \"\\n  warthog=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"warthog\"));\n  }) ];\n}));\n\nTemplate.__define__(\"old_test_helpers_b\", (function() {\n  var view = this;\n  return [ \"unknown=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"unknown\"));\n  }), \"\\n  zero=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"zero\"));\n  }) ];\n}));\n\nTemplate.__define__(\"old_test_helpers_c\", (function() {\n  var view = this;\n  return [ \"platypus.X=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"platypus\"), \"X\"));\n  }), \"\\n  watermelon.X=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"watermelon\"), \"X\"));\n  }), \"\\n  daisy.X=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"daisy\"), \"X\"));\n  }), \"\\n  tree.X=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"tree\"), \"X\"));\n  }), \"\\n  warthog.X=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"warthog\"), \"X\"));\n  }), \"\\n  getNull.X=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"getNull\"), \"X\"));\n  }), \"\\n  getUndefined.X=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"getUndefined\"), \"X\"));\n  }), \"\\n  getUndefined.X.Y=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"getUndefined\"), \"X\", \"Y\"));\n  }) ];\n}));\n\nTemplate.__define__(\"old_test_helpers_d\", (function() {\n  var view = this;\n  return [ \"daisygetter=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"daisygetter\"));\n  }), \"\\n  thisTest=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"thisTest\"));\n  }), \"\\n  \", Spacebars.With(function() {\n    return Spacebars.call(view.lookup(\"fancy\"));\n  }, function() {\n    return [ \"\\n    ../thisTest=\", Blaze.View(function() {\n      return Spacebars.mustache(Spacebars.dot(view.lookup(\"..\"), \"thisTest\"));\n    }), \"\\n  \" ];\n  }), \"\\n  \", Spacebars.With(function() {\n    return \"foo\";\n  }, function() {\n    return [ \"\\n    ../fancy.currentFruit=\", Blaze.View(function() {\n      return Spacebars.mustache(Spacebars.dot(view.lookup(\"..\"), \"fancy\", \"currentFruit\"));\n    }), \"\\n  \" ];\n  }) ];\n}));\n\nTemplate.__define__(\"old_test_helpers_e\", (function() {\n  var view = this;\n  return [ \"fancy.foo=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"fancy\"), \"foo\"));\n  }), \"\\n  fancy.apple.banana=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"fancy\"), \"apple\", \"banana\"));\n  }), \"\\n  fancy.currentFruit=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"fancy\"), \"currentFruit\"));\n  }), \"\\n  fancy.currentCountry.name=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"fancy\"), \"currentCountry\", \"name\"));\n  }), \"\\n  fancy.currentCountry.population=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"fancy\"), \"currentCountry\", \"population\"));\n  }), \"\\n  fancy.currentCountry.unicorns=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"fancy\"), \"currentCountry\", \"unicorns\"));\n  }) ];\n}));\n\nTemplate.__define__(\"old_test_helpers_f\", (function() {\n  var view = this;\n  return [ \"fancyhelper.foo=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"fancyhelper\"), \"foo\"));\n  }), \"\\n  fancyhelper.apple.banana=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"fancyhelper\"), \"apple\", \"banana\"));\n  }), \"\\n  fancyhelper.currentFruit=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentFruit\"));\n  }), \"\\n  fancyhelper.currentCountry.name=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentCountry\", \"name\"));\n  }), \"\\n  fancyhelper.currentCountry.population=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentCountry\", \"population\"));\n  }), \"\\n  fancyhelper.currentCountry.unicorns=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentCountry\", \"unicorns\"));\n  }) ];\n}));\n\nTemplate.__define__(\"old_test_helpers_g\", (function() {\n  var view = this;\n  return [ \"platypus=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"platypus\"));\n  }), \"\\n  this.platypus=\", Blaze.View(function() {\n    return Spacebars.mustache(Spacebars.dot(view.lookup(\".\"), \"platypus\"));\n  }) ];\n}));\n\nTemplate.__define__(\"old_test_helpers_h\", (function() {\n  var view = this;\n  return [ \"(methodListFour 6 7 8 9=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"methodListFour\"), 6, 7, 8, 9);\n  }), \")\\n  (methodListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"methodListFour\"), view.lookup(\"platypus\"), view.lookup(\"thisTest\"), Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentFruit\"), Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentCountry\", \"unicorns\"));\n  }), \")\\n  (methodListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns a=platypus b=thisTest c=fancyhelper.currentFruit d=fancyhelper.currentCountry.unicorns=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"methodListFour\"), view.lookup(\"platypus\"), view.lookup(\"thisTest\"), Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentFruit\"), Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentCountry\", \"unicorns\"), Spacebars.kw({\n      a: view.lookup(\"platypus\"),\n      b: view.lookup(\"thisTest\"),\n      c: Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentFruit\"),\n      d: Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentCountry\", \"unicorns\")\n    }));\n  }), \")\\n  (helperListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"helperListFour\"), view.lookup(\"platypus\"), view.lookup(\"thisTest\"), Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentFruit\"), Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentCountry\", \"unicorns\"));\n  }), \")\\n  (helperListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns a=platypus b=thisTest c=fancyhelper.currentFruit d=fancyhelper.currentCountry.unicorns=\", Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"helperListFour\"), view.lookup(\"platypus\"), view.lookup(\"thisTest\"), Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentFruit\"), Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentCountry\", \"unicorns\"), Spacebars.kw({\n      a: view.lookup(\"platypus\"),\n      b: view.lookup(\"thisTest\"),\n      c: Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentFruit\"),\n      d: Spacebars.dot(view.lookup(\"fancyhelper\"), \"currentCountry\", \"unicorns\")\n    }));\n  }), \")\" ];\n}));\n\nTemplate.__define__(\"old_test_render_a\", (function() {\n  var view = this;\n  return [ Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"foo\"));\n  }), HTML.Raw(\"<br><hr>\") ];\n}));\n\nTemplate.__define__(\"old_test_render_b\", (function() {\n  var view = this;\n  return Spacebars.With(function() {\n    return 200;\n  }, function() {\n    return [ Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\"foo\"));\n    }), HTML.BR(), HTML.HR() ];\n  });\n}));\n\nTemplate.__define__(\"old_test_render_c\", (function() {\n  var view = this;\n  return HTML.Raw(\"<br><hr>\");\n}));\n\nTemplate.__define__(\"old_test_template_arg_a\", (function() {\n  var view = this;\n  return HTML.Raw(\"<b>Foo</b> <i>Bar</i> <u>Baz</u>\");\n}));\n\nTemplate.__define__(\"old_test_template_helpers_a\", (function() {\n  var view = this;\n  return [ Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"foo\"));\n  }), Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"bar\"));\n  }), Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"baz\"));\n  }) ];\n}));\n\nTemplate.__define__(\"old_test_template_helpers_b\", (function() {\n  var view = this;\n  return [ Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"name\"));\n  }), Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"arity\"));\n  }), Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"toString\"));\n  }), Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"length\"));\n  }), Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"var\"));\n  }) ];\n}));\n\nTemplate.__define__(\"old_test_template_helpers_c\", (function() {\n  var view = this;\n  return [ Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"name\"));\n  }), Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"arity\"));\n  }), Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"length\"));\n  }), Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"var\"));\n  }), \"x\" ];\n}));\n\nTemplate.__define__(\"old_test_template_events_a\", (function() {\n  var view = this;\n  return HTML.Raw(\"<b>foo</b><u>bar</u><i>baz</i>\");\n}));\n\nTemplate.__define__(\"old_test_template_events_b\", (function() {\n  var view = this;\n  return HTML.Raw(\"<b>foo</b><u>bar</u><i>baz</i>\");\n}));\n\nTemplate.__define__(\"old_test_template_events_c\", (function() {\n  var view = this;\n  return HTML.Raw(\"<b>foo</b><u>bar</u><i>baz</i>\");\n}));\n\nTemplate.__define__(\"old_test_type_casting\", (function() {\n  var view = this;\n  return Blaze.View(function() {\n    return Spacebars.mustache(view.lookup(\"testTypeCasting\"), \"true\", \"false\", true, false, 0, 1, -1, 10, -10);\n  });\n}));\n\nTemplate.__define__(\"old_test_template_issue801\", (function() {\n  var view = this;\n  return Blaze.Each(function() {\n    return Spacebars.call(view.lookup(\"values\"));\n  }, function() {\n    return Blaze.View(function() {\n      return Spacebars.mustache(view.lookup(\".\"));\n    });\n  });\n}));\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n"
  },
  {
    "path": "packages/spacebars-tests/old_templates_tests.js",
    "content": "//\n// This file is used to ensure old built templates still work with the\n// new Blaze APIs. More in a comment at the top of old_templates.js\n//\n\nvar divRendersTo = function (test, div, html) {\n  Tracker.flush({_throwFirstError: true});\n  var actual = canonicalizeHtml(div.innerHTML);\n  test.equal(actual, html);\n};\n\nvar nodesToArray = function (array) {\n  // Starting in underscore 1.4, _.toArray does not work right on a node\n  // list in IE8. This is a workaround to support IE8.\n  return _.map(array, _.identity);\n};\n\nTinytest.add(\"spacebars-tests - old - template_tests - simple helper\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_simple_helper;\n  var R = ReactiveVar(1);\n  tmpl.foo = function (x) {\n    return x + R.get();\n  };\n  tmpl.bar = function () {\n    return 123;\n  };\n  var div = renderToDiv(tmpl);\n\n  test.equal(canonicalizeHtml(div.innerHTML), \"124\");\n  R.set(2);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"125\");\n\n  // Test that `{{foo bar}}` throws if `foo` is missing or not a function.\n  tmpl.foo = 3;\n  test.throws(function () {\n    renderToDiv(tmpl);\n  }, /Can't call non-function/);\n\n  delete tmpl.foo;\n  test.throws(function () {\n    renderToDiv(tmpl);\n  }, /No such function/);\n\n  tmpl.foo = function () {};\n  // doesn't throw\n  div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), '');\n\n  // now \"foo\" is a function in the data context\n  delete tmpl.foo;\n\n  R = ReactiveVar(1);\n  div = renderToDiv(tmpl, { foo: function (x) {\n    return x + R.get();\n  } });\n  test.equal(canonicalizeHtml(div.innerHTML), \"124\");\n  R.set(2);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"125\");\n\n  test.throws(function () {\n    renderToDiv(tmpl, {foo: 3});\n  }, /Can't call non-function/);\n\n  test.throws(function () {\n    renderToDiv(tmpl, {foo: null});\n  }, /No such function/);\n\n  test.throws(function () {\n    renderToDiv(tmpl, {});\n  }, /No such function/);\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - dynamic template\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_dynamic_template;\n  var aaa = Template.old_spacebars_template_test_aaa;\n  var bbb = Template.old_spacebars_template_test_bbb;\n  var R = ReactiveVar(\"aaa\");\n  tmpl.foo = function () {\n    return R.get() === 'aaa' ? aaa : bbb;\n  };\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"aaa\");\n\n  R.set('bbb');\n  Tracker.flush();\n\n  test.equal(canonicalizeHtml(div.innerHTML), \"bbb\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - interpolate attribute\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_interpolate_attribute;\n  tmpl.foo = function (x) {\n    return x+1;\n  };\n  tmpl.bar = function () {\n    return 123;\n  };\n  var div = renderToDiv(tmpl);\n\n  test.equal($(div).find('div')[0].className, \"aaa124zzz\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - dynamic attrs\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_dynamic_attrs;\n\n  var R2 = ReactiveVar({x: \"X\"});\n  var R3 = ReactiveVar('selected');\n  tmpl.attrsObj = function () { return R2.get(); };\n  tmpl.singleAttr = function () { return R3.get(); };\n\n  var div = renderToDiv(tmpl);\n  var span = $(div).find('span')[0];\n  test.equal(span.innerHTML, 'hi');\n  test.isTrue(span.hasAttribute('selected'));\n  test.equal(span.getAttribute('x'), 'X');\n\n  R2.set({y: \"Y\", z: \"Z\"});\n  R3.set('');\n  Tracker.flush();\n  test.equal(canonicalizeHtml(span.innerHTML), 'hi');\n  test.isFalse(span.hasAttribute('selected'));\n  test.isFalse(span.hasAttribute('x'));\n  test.equal(span.getAttribute('y'), 'Y');\n  test.equal(span.getAttribute('z'), 'Z');\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - triple\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_triple;\n\n  var R = ReactiveVar('<span class=\"hi\">blah</span>');\n  tmpl.html = function () { return R.get(); };\n\n  var div = renderToDiv(tmpl);\n  var elems = $(div).find(\"> *\");\n  test.equal(elems.length, 1);\n  test.equal(elems[0].nodeName, 'SPAN');\n  var span = elems[0];\n  test.equal(span.className, 'hi');\n  test.equal(span.innerHTML, 'blah');\n\n  R.set('asdf');\n  Tracker.flush();\n  elems = $(div).find(\"> *\");\n  test.equal(elems.length, 0);\n  test.equal(canonicalizeHtml(div.innerHTML), 'asdf');\n\n  R.set('<span class=\"hi\">blah</span>');\n  Tracker.flush();\n  elems = $(div).find(\"> *\");\n  test.equal(elems.length, 1);\n  test.equal(elems[0].nodeName, 'SPAN');\n  span = elems[0];\n  test.equal(span.className, 'hi');\n  test.equal(canonicalizeHtml(span.innerHTML), 'blah');\n\n  var tmpl = Template.old_spacebars_template_test_triple2;\n  tmpl.html = function () {};\n  tmpl.html2 = function () { return null; };\n  // no tmpl.html3\n  div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'xy');\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - inclusion args\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_inclusion_args;\n\n  var R = ReactiveVar(Template.old_spacebars_template_test_aaa);\n  tmpl.foo = function () { return R.get(); };\n\n  var div = renderToDiv(tmpl);\n  // `{{> foo bar}}`, with `foo` resolving to Template.aaa,\n  // which consists of \"aaa\"\n  test.equal(canonicalizeHtml(div.innerHTML), 'aaa');\n  R.set(Template.old_spacebars_template_test_bbb);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'bbb');\n\n  ////// Ok, now `foo` *is* Template.aaa\n  tmpl.foo = Template.old_spacebars_template_test_aaa;\n  div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'aaa');\n\n  ////// Ok, now `foo` is a template that takes an argument; bar is a string.\n  tmpl.foo = Template.old_spacebars_template_test_bracketed_this;\n  tmpl.bar = 'david';\n  div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), '[david]');\n\n  ////// Now `foo` is a template that takes an arg; bar is a function.\n  tmpl.foo = Template.old_spacebars_template_test_span_this;\n  R = ReactiveVar('david');\n  tmpl.bar = function () { return R.get(); };\n  div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>david</span>');\n  var span1 = div.querySelector('span');\n  R.set('avi');\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>avi</span>');\n  var span2 = div.querySelector('span');\n  test.isTrue(span1 === span2);\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - inclusion args 2\", function (test) {\n  // `{{> foo bar q=baz}}`\n  var tmpl = Template.old_spacebars_template_test_inclusion_args2;\n\n  tmpl.foo = Template.old_spacebars_template_test_span_this;\n  tmpl.bar = function (options) {\n    return options.hash.q;\n  };\n\n  var R = ReactiveVar('david!');\n  tmpl.baz = function () { return R.get().slice(0,5); };\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>david</span>');\n  var span1 = div.querySelector('span');\n  R.set('brillo');\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>brill</span>');\n  var span2 = div.querySelector('span');\n  test.isTrue(span1 === span2);\n});\n\n// maybe use created callback on the template instead of this?\nvar extendTemplateWithInit = function (template, initFunc) {\n  var tmpl = new Template(template.viewName+'-extended', template.renderFunction);\n  tmpl.constructView = function (/*args*/) {\n    var view = Template.prototype.constructView.apply(this, arguments);\n    initFunc(view);\n    return view;\n  };\n  return tmpl;\n};\n\nTinytest.add(\"spacebars-tests - old - template_tests - inclusion dotted args\", function (test) {\n  // `{{> foo bar.baz}}`\n  var tmpl = Template.old_spacebars_template_test_inclusion_dotted_args;\n\n  var initCount = 0;\n  tmpl.foo = extendTemplateWithInit(\n    Template.old_spacebars_template_test_bracketed_this,\n    function () { initCount++; });\n\n  var R = ReactiveVar('david');\n  tmpl.bar = function () {\n    // make sure `this` is bound correctly\n    return { baz: this.symbol + R.get() };\n  };\n\n  var div = renderToDiv(tmpl, {symbol:'%'});\n  test.equal(initCount, 1);\n  test.equal(canonicalizeHtml(div.innerHTML), '[%david]');\n\n  R.set('avi');\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), '[%avi]');\n  // check that invalidating the argument to `foo` doesn't require\n  // creating a new `foo`.\n  test.equal(initCount, 1);\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - inclusion slashed args\", function (test) {\n  // `{{> foo bar/baz}}`\n  var tmpl = Template.old_spacebars_template_test_inclusion_dotted_args;\n\n  var initCount = 0;\n  tmpl.foo = extendTemplateWithInit(\n    Template.old_spacebars_template_test_bracketed_this,\n    function () { initCount++; });\n  var R = ReactiveVar('david');\n  tmpl.bar = function () {\n    // make sure `this` is bound correctly\n    return { baz: this.symbol + R.get() };\n  };\n\n  var div = renderToDiv(tmpl, {symbol:'%'});\n  test.equal(initCount, 1);\n  test.equal(canonicalizeHtml(div.innerHTML), '[%david]');\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - block helper\", function (test) {\n  // test the case where `foo` is a calculated template that changes\n  // reactively.\n  // `{{#foo}}bar{{else}}baz{{/foo}}`\n  var tmpl = Template.old_spacebars_template_test_block_helper;\n  var R = ReactiveVar(Template.old_spacebars_template_test_content);\n  tmpl.foo = function () {\n    return R.get();\n  };\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"bar\");\n\n  R.set(Template.old_spacebars_template_test_elsecontent);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"baz\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - block helper function with one string arg\", function (test) {\n  // `{{#foo \"bar\"}}content{{/foo}}`\n  var tmpl = Template.old_spacebars_template_test_block_helper_function_one_string_arg;\n  tmpl.foo = function () {\n    if (String(this) === \"bar\")\n      return Template.old_spacebars_template_test_content;\n    else\n      return null;\n  };\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"content\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - block helper function with one helper arg\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_block_helper_function_one_helper_arg;\n  var R = ReactiveVar(\"bar\");\n  tmpl.bar = function () { return R.get(); };\n  tmpl.foo = function () {\n    if (String(this) === \"bar\")\n      return Template.old_spacebars_template_test_content;\n    else\n      return null;\n  };\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"content\");\n\n  R.set(\"baz\");\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - block helper component with one helper arg\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_block_helper_component_one_helper_arg;\n  var R = ReactiveVar(true);\n  tmpl.bar = function () { return R.get(); };\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"content\");\n\n  R.set(false);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - block helper component with three helper args\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_block_helper_component_three_helper_args;\n  var R = ReactiveVar(\"bar\");\n  tmpl.bar_or_baz = function () {\n    return R.get();\n  };\n  tmpl.equals = function (x, y) {\n    return x === y;\n  };\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"content\");\n\n  R.set(\"baz\");\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - block helper with dotted arg\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_block_helper_dotted_arg;\n  var R1 = ReactiveVar(1);\n  var R2 = ReactiveVar(10);\n  var R3 = ReactiveVar(100);\n\n  var initCount = 0;\n  tmpl.foo = extendTemplateWithInit(\n    Template.old_spacebars_template_test_bracketed_this,\n    function () { initCount++; });\n  tmpl.bar = function () {\n    return {\n      r1: R1.get(),\n      baz: function (r3) {\n        return this.r1 + R2.get() + r3;\n      }\n    };\n  };\n  tmpl.qux = function () { return R3.get(); };\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"[111]\");\n  test.equal(initCount, 1);\n\n  R1.set(2);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"[112]\");\n  test.equal(initCount, 1);\n\n  R2.set(20);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"[122]\");\n  test.equal(initCount, 1);\n\n  R3.set(200);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"[222]\");\n  test.equal(initCount, 1);\n\n  R2.set(30);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"[232]\");\n  test.equal(initCount, 1);\n\n  R1.set(3);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"[233]\");\n  test.equal(initCount, 1);\n\n  R3.set(300);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"[333]\");\n  test.equal(initCount, 1);\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - nested content\", function (test) {\n  // Test that `{{> UI.contentBlock}}` in an `{{#if}}` works.\n\n  // ```\n  // <template name=\"spacebars_template_test_iftemplate\">\n  //   {{#if condition}}\n  //     {{> UI.contentBlock}}\n  //   {{else}}\n  //     {{> UI.elseBlock}}\n  //   {{/if}}\n  // </template>\n  // ```\n\n  // ```\n  //  {{#spacebars_template_test_iftemplate flag}}\n  //    hello\n  //  {{else}}\n  //    world\n  //  {{/spacebars_template_test_iftemplate}}\n  // ```\n\n  var tmpl = Template.old_spacebars_template_test_nested_content;\n  var R = ReactiveVar(true);\n  tmpl.flag = function () {\n    return R.get();\n  };\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'hello');\n  R.set(false);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'world');\n  R.set(true);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'hello');\n\n  // Also test that `{{> UI.contentBlock}}` in a custom block helper works.\n  tmpl = Template.old_spacebars_template_test_nested_content2;\n  R = ReactiveVar(true);\n  tmpl.x = function () {\n    return R.get();\n  };\n  div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'hello');\n  R.set(false);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'world');\n  R.set(true);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'hello');\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - if\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_if;\n  var R = ReactiveVar(true);\n  tmpl.foo = function () {\n    return R.get();\n  };\n  tmpl.bar = 1;\n  tmpl.baz = 2;\n\n  var div = renderToDiv(tmpl);\n  var rendersTo = function (html) { divRendersTo(test, div, html); };\n\n  rendersTo(\"1\");\n  R.set(false);\n  rendersTo(\"2\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - if in with\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_if_in_with;\n  tmpl.foo = {bar: \"bar\"};\n\n  var div = renderToDiv(tmpl);\n  divRendersTo(test, div, \"bar bar\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - each on cursor\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_each;\n  var coll = new Mongo.Collection(null);\n  tmpl.items = function () {\n    return coll.find({}, {sort: {pos: 1}});\n  };\n\n  var div = renderToDiv(tmpl);\n  var rendersTo = function (html) { divRendersTo(test, div, html); };\n\n  rendersTo(\"else-clause\");\n  coll.insert({text: \"one\", pos: 1});\n  rendersTo(\"one\");\n  coll.insert({text: \"two\", pos: 2});\n  rendersTo(\"one two\");\n  coll.update({text: \"two\"}, {$set: {text: \"three\"}});\n  rendersTo(\"one three\");\n  coll.update({text: \"three\"}, {$set: {pos: 0}});\n  rendersTo(\"three one\");\n  coll.remove({});\n  rendersTo(\"else-clause\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - each on array\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_each;\n  var R = new ReactiveVar([]);\n  tmpl.items = function () {\n    return R.get();\n  };\n  tmpl.text = function () {\n    return this;\n  };\n\n  var div = renderToDiv(tmpl);\n  var rendersTo = function (html) { divRendersTo(test, div, html); };\n\n  rendersTo(\"else-clause\");\n  R.set([\"\"]);\n  rendersTo(\"\");\n  R.set([\"x\", \"\", \"toString\"]);\n  rendersTo(\"x toString\");\n  R.set([\"toString\"]);\n  rendersTo(\"toString\");\n  R.set([]);\n  rendersTo(\"else-clause\");\n  R.set([0, 1, 2]);\n  rendersTo(\"0 1 2\");\n  R.set([]);\n  rendersTo(\"else-clause\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - ..\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_dots;\n  Template.old_spacebars_template_test_dots_subtemplate.getTitle = function (from) {\n    return from.title;\n  };\n\n  tmpl.foo = {title: \"foo\"};\n  tmpl.foo.bar = {title: \"bar\"};\n  tmpl.foo.bar.items = [{title: \"item\"}];\n  var div = renderToDiv(tmpl);\n\n  test.equal(canonicalizeHtml(div.innerHTML), [\n    \"A\", \"B\", \"C\", \"D\",\n    // {{> spacebars_template_test_dots_subtemplate}}\n    \"TITLE\", \"1item\", \"2item\", \"3bar\", \"4foo\", \"GETTITLE\", \"5item\", \"6bar\", \"7foo\",\n    // {{> spacebars_template_test_dots_subtemplate ..}}\n    \"TITLE\", \"1bar\", \"2bar\", \"3item\", \"4bar\", \"GETTITLE\", \"5bar\", \"6item\", \"7bar\"].join(\" \"));\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - select tags\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_select_tag;\n\n  // {label: (string)}\n  var optgroups = new Mongo.Collection(null);\n\n  // {optgroup: (id), value: (string), selected: (boolean), label: (string)}\n  var options = new Mongo.Collection(null);\n\n  tmpl.optgroups = function () { return optgroups.find(); };\n  tmpl.options = function () { return options.find({optgroup: this._id}); };\n  tmpl.selectedAttr = function () { return this.selected ? {selected: true} : {}; };\n\n  var div = renderToDiv(tmpl);\n  var selectEl = $(div).find('select')[0];\n\n  // returns canonicalized contents of `div` in the form eg\n  // [\"<select>\", \"</select>\"]. strip out selected attributes -- we\n  // verify correctness by observing the `selected` property\n  var divContent = function () {\n    return canonicalizeHtml(\n      div.innerHTML.replace(/selected=\"[^\"]*\"/g, '').replace(/selected/g, ''))\n          .replace(/\\>\\s*\\</g, '>\\n<')\n          .split('\\n');\n  };\n\n  test.equal(divContent(), [\"<select>\", \"</select>\"]);\n\n  var optgroup1 = optgroups.insert({label: \"one\"});\n  var optgroup2 = optgroups.insert({label: \"two\"});\n  test.equal(divContent(), [\n    '<select>',\n    '<optgroup label=\"one\">',\n    '</optgroup>',\n    '<optgroup label=\"two\">',\n    '</optgroup>',\n    '</select>'\n  ]);\n\n  options.insert({optgroup: optgroup1, value: \"value1\", selected: false, label: \"label1\"});\n  options.insert({optgroup: optgroup1, value: \"value2\", selected: true, label: \"label2\"});\n  test.equal(divContent(), [\n    '<select>',\n    '<optgroup label=\"one\">',\n    '<option value=\"value1\">label1</option>',\n    '<option value=\"value2\">label2</option>',\n    '</optgroup>',\n    '<optgroup label=\"two\">',\n    '</optgroup>',\n    '</select>'\n  ]);\n  test.equal(selectEl.value, \"value2\");\n  test.equal($(selectEl).find('option')[0].selected, false);\n  test.equal($(selectEl).find('option')[1].selected, true);\n\n  // swap selection\n  options.update({value: \"value1\"}, {$set: {selected: true}});\n  options.update({value: \"value2\"}, {$set: {selected: false}});\n  Tracker.flush();\n\n  test.equal(divContent(), [\n    '<select>',\n    '<optgroup label=\"one\">',\n    '<option value=\"value1\">label1</option>',\n    '<option value=\"value2\">label2</option>',\n    '</optgroup>',\n    '<optgroup label=\"two\">',\n    '</optgroup>',\n    '</select>'\n  ]);\n  test.equal(selectEl.value, \"value1\");\n  test.equal($(selectEl).find('option')[0].selected, true);\n  test.equal($(selectEl).find('option')[1].selected, false);\n\n  // change value and label\n  options.update({value: \"value1\"}, {$set: {value: \"value1.0\"}});\n  options.update({value: \"value2\"}, {$set: {label: \"label2.0\"}});\n  Tracker.flush();\n\n  test.equal(divContent(), [\n    '<select>',\n    '<optgroup label=\"one\">',\n    '<option value=\"value1.0\">label1</option>',\n    '<option value=\"value2\">label2.0</option>',\n    '</optgroup>',\n    '<optgroup label=\"two\">',\n    '</optgroup>',\n    '</select>'\n  ]);\n  test.equal(selectEl.value, \"value1.0\");\n  test.equal($(selectEl).find('option')[0].selected, true);\n  test.equal($(selectEl).find('option')[1].selected, false);\n\n  // unselect and then select both options. normally, the second is\n  // selected (since it got selected later). then switch to <select\n  // multiple=\"\">. both should be selected.\n  options.update({}, {$set: {selected: false}}, {multi: true});\n  Tracker.flush();\n  options.update({}, {$set: {selected: true}}, {multi: true});\n  Tracker.flush();\n  test.equal($(selectEl).find('option')[0].selected, false);\n  test.equal($(selectEl).find('option')[1].selected, true);\n\n  selectEl.multiple = true; // allow multiple selection\n  options.update({}, {$set: {selected: false}}, {multi: true});\n  Tracker.flush();\n  options.update({}, {$set: {selected: true}}, {multi: true});\n  window.avital = true;\n  Tracker.flush();\n  test.equal($(selectEl).find('option')[0].selected, true);\n  test.equal($(selectEl).find('option')[1].selected, true);\n});\n\nTinytest.add('spacebars-tests - old - template_tests - {{#with}} falsy; issue #770', function (test) {\n  Template.old_test_template_issue770.value1 = function () { return \"abc\"; };\n  Template.old_test_template_issue770.value2 = function () { return false; };\n  var div = renderToDiv(Template.old_test_template_issue770);\n  test.equal(canonicalizeHtml(div.innerHTML),\n             \"abc xxx abc\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - tricky attrs\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_tricky_attrs;\n  tmpl.theType = function () { return 'text'; };\n  var R = ReactiveVar('foo');\n  tmpl.theClass = function () { return R.get(); };\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML).slice(0, 30),\n             '<input type=\"text\"><input class=\"foo\" type=\"checkbox\">'.slice(0, 30));\n\n  R.set('bar');\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML),\n             '<input type=\"text\"><input class=\"bar\" type=\"checkbox\">');\n\n});\n\nTinytest.add('spacebars-tests - old - template_tests - no data context', function (test) {\n  var tmpl = Template.old_spacebars_template_test_no_data;\n\n  // failure is if an exception is thrown here\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'asdf');\n});\n\nTinytest.add('spacebars-tests - old - template_tests - textarea', function (test) {\n  var tmpl = Template.old_spacebars_template_test_textarea;\n\n  var R = ReactiveVar('hello');\n\n  tmpl.foo = function () {\n    return R.get();\n  };\n\n  var div = renderToDiv(tmpl);\n  var textarea = div.querySelector('textarea');\n  test.equal(textarea.value, 'hello');\n\n  R.set('world');\n  Tracker.flush();\n  test.equal(textarea.value, 'world');\n\n});\n\nTinytest.add('spacebars-tests - old - template_tests - textarea 2', function (test) {\n  var tmpl = Template.old_spacebars_template_test_textarea2;\n\n  var R = ReactiveVar(true);\n\n  tmpl.foo = function () {\n    return R.get();\n  };\n\n  var div = renderToDiv(tmpl);\n  var textarea = div.querySelector('textarea');\n  test.equal(textarea.value, '</not a tag>');\n\n  R.set(false);\n  Tracker.flush();\n  test.equal(textarea.value, '<also not a tag>');\n\n  R.set(true);\n  Tracker.flush();\n  test.equal(textarea.value, '</not a tag>');\n\n});\n\nTinytest.add('spacebars-tests - old - template_tests - textarea 3', function (test) {\n  var tmpl = Template.old_spacebars_template_test_textarea3;\n\n  var R = ReactiveVar('hello');\n\n  tmpl.foo = function () {\n    return R.get();\n  };\n\n  var div = renderToDiv(tmpl);\n  var textarea = div.querySelector('textarea');\n  test.equal(textarea.id, 'myTextarea');\n  test.equal(textarea.value, 'hello');\n\n  R.set('world');\n  Tracker.flush();\n  test.equal(textarea.value, 'world');\n\n});\n\nTinytest.add('spacebars-tests - old - template_tests - textarea each', function (test) {\n  var tmpl = Template.old_spacebars_template_test_textarea_each;\n\n  var R = ReactiveVar(['APPLE', 'BANANA']);\n\n  tmpl.foo = function () {\n    return R.get();\n  };\n\n  var div = renderToDiv(tmpl);\n  var textarea = div.querySelector('textarea');\n  test.equal(textarea.value, '<not a tag APPLE <not a tag BANANA ');\n\n  R.set([]);\n  Tracker.flush();\n  test.equal(textarea.value, '<>');\n\n  R.set(['CUCUMBER']);\n  Tracker.flush();\n  test.equal(textarea.value, '<not a tag CUCUMBER ');\n\n});\n\ntestAsyncMulti('spacebars-tests - old - template_tests - rendered template is DOM in rendered callbacks', [\n  function (test, expect) {\n    var tmpl = Template.old_spacebars_template_test_aaa;\n    tmpl.rendered = expect(function () {\n      test.equal(canonicalizeHtml(div.innerHTML), \"aaa\");\n    });\n    var div = renderToDiv(tmpl);\n    Tracker.flush();\n  }\n]);\n\n// Test that in:\n//\n// ```\n// {{#with someData}}\n//   {{foo}} {{bar}}\n// {{/with}}\n// ```\n//\n// ... we run `someData` once even if `foo` re-renders.\nTinytest.add('spacebars-tests - old - template_tests - with someData', function (test) {\n  var tmpl = Template.old_spacebars_template_test_with_someData;\n\n  var foo = ReactiveVar('AAA');\n  var someDataRuns = 0;\n\n  tmpl.someData = function () {\n    someDataRuns++;\n    return {};\n  };\n  tmpl.foo = function () {\n    return foo.get();\n  };\n  tmpl.bar = function () {\n    return 'YO';\n  };\n\n  var div = renderToDiv(tmpl);\n\n  test.equal(someDataRuns, 1);\n  test.equal(canonicalizeHtml(div.innerHTML), 'AAA YO');\n\n  foo.set('BBB');\n  Tracker.flush();\n  test.equal(someDataRuns, 1);\n  test.equal(canonicalizeHtml(div.innerHTML), 'BBB YO');\n\n  foo.set('CCC');\n  Tracker.flush();\n  test.equal(someDataRuns, 1);\n  test.equal(canonicalizeHtml(div.innerHTML), 'CCC YO');\n});\n\nTinytest.add('spacebars-tests - old - template_tests - #each stops when rendered element is removed', function (test) {\n  var tmpl = Template.old_spacebars_template_test_each_stops;\n  var coll = new Mongo.Collection(null);\n  coll.insert({});\n  tmpl.items = function () { return coll.find(); };\n\n  var div = renderToDiv(tmpl);\n  divRendersTo(test, div, 'x');\n\n  // trigger #each component destroyed\n  $(div).remove();\n\n  // insert another document. cursor should no longer be observed so\n  // should have no effect.\n  coll.insert({});\n  divRendersTo(test, div, 'x');\n});\n\nTinytest.add('spacebars-tests - old - template_tests - block helpers in attribute', function (test) {\n  var tmpl = Template.old_spacebars_template_test_block_helpers_in_attribute;\n\n  var coll = new Mongo.Collection(null);\n  tmpl.classes = function () {\n    return coll.find({}, {sort: {name: 1}});\n  };\n  tmpl.startsLowerCase = function (name) {\n    return /^[a-z]/.test(name);\n  };\n  coll.insert({name: 'David'});\n  coll.insert({name: 'noodle'});\n  coll.insert({name: 'donut'});\n  coll.insert({name: 'frankfurter'});\n  coll.insert({name: 'Steve'});\n\n  var containerDiv = renderToDiv(tmpl);\n  var div = containerDiv.querySelector('div');\n\n  var shouldBe = function (className) {\n    Tracker.flush();\n    test.equal(div.innerHTML, \"Smurf\");\n    test.equal(div.className, className);\n    var result = canonicalizeHtml(containerDiv.innerHTML);\n    if (result === '<div>Smurf</div>')\n      result = '<div class=\"\">Smurf</div>'; // e.g. IE 9 and 10\n    test.equal(result, '<div class=\"' + className + '\">Smurf</div>');\n  };\n\n  shouldBe('donut frankfurter noodle');\n  coll.remove({name: 'frankfurter'}); // (it was kind of a mouthful)\n  shouldBe('donut noodle');\n  coll.remove({name: 'donut'});\n  shouldBe('noodle');\n  coll.remove({name: 'noodle'});\n  shouldBe(''); // 'David' and 'Steve' appear in the #each but fail the #if\n  coll.remove({});\n  shouldBe('none'); // now the `{{else}}` case kicks in\n  coll.insert({name: 'bubblegum'});\n  shouldBe('bubblegum');\n});\n\nTinytest.add('spacebars-tests - old - template_tests - block helpers in attribute 2', function (test) {\n  var tmpl = Template.old_spacebars_template_test_block_helpers_in_attribute_2;\n\n  var R = ReactiveVar(true);\n\n  tmpl.foo = function () { return R.get(); };\n\n  var div = renderToDiv(tmpl);\n  var input = div.querySelector('input');\n\n  test.equal(input.value, '\"');\n  R.set(false);\n  Tracker.flush();\n  test.equal(input.value, '&<></x>');\n});\n\n\n// Test that if the argument to #each is a constant, it doesn't establish a\n// dependency on the data context, so when the context changes, items of\n// the #each are not \"changed\" and helpers do not rerun.\nTinytest.add('spacebars-tests - old - template_tests - constant #each argument', function (test) {\n  var tmpl = Template.old_spacebars_template_test_constant_each_argument;\n\n  var justReturnRuns = 0; // how many times `justReturn` is called\n  var R = ReactiveVar(1);\n\n  tmpl.someData = function () {\n    return R.get();\n  };\n  tmpl.anArray = ['foo', 'bar'];\n  tmpl.justReturn = function (x) {\n    justReturnRuns++;\n    return String(x);\n  };\n\n  var div = renderToDiv(tmpl);\n\n  test.equal(justReturnRuns, 2);\n  test.equal(canonicalizeHtml(div.innerHTML).replace(/\\s+/g, ' '),\n             'foo bar 1');\n\n  R.set(2);\n  Tracker.flush();\n\n  test.equal(justReturnRuns, 2); // still 2, no new runs!\n  test.equal(canonicalizeHtml(div.innerHTML).replace(/\\s+/g, ' '),\n             'foo bar 2');\n});\n\nTinytest.addAsync('spacebars-tests - old - template_tests - #markdown - basic', function (test, onComplete) {\n  var tmpl = Template.old_spacebars_template_test_markdown_basic;\n  tmpl.obj = {snippet: \"<i>hi</i>\"};\n  tmpl.hi = function () {\n    return this.snippet;\n  };\n  var div = renderToDiv(tmpl);\n\n  Meteor.call(\"getAsset\", \"markdown_basic.html\", function (err, html) {\n    test.isFalse(err);\n    test.equal(canonicalizeHtml(div.innerHTML),\n               canonicalizeHtml(html));\n    onComplete();\n  });\n});\n\ntestAsyncMulti('spacebars-tests - old - template_tests - #markdown - if', [\n  function (test, expect) {\n    var self = this;\n    Meteor.call(\"getAsset\", \"markdown_if1.html\", expect(function (err, html) {\n      test.isFalse(err);\n      self.html1 = html;\n    }));\n    Meteor.call(\"getAsset\", \"markdown_if2.html\", expect(function (err, html) {\n      test.isFalse(err);\n      self.html2 = html;\n    }));\n  },\n\n  function (test, expect) {\n    var self = this;\n    var tmpl = Template.old_spacebars_template_test_markdown_if;\n    var R = new ReactiveVar(false);\n    tmpl.cond = function () { return R.get(); };\n\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), canonicalizeHtml(self.html1));\n    R.set(true);\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), canonicalizeHtml(self.html2));\n  }\n]);\n\ntestAsyncMulti('spacebars-tests - old - template_tests - #markdown - each', [\n  function (test, expect) {\n    var self = this;\n    Meteor.call(\"getAsset\", \"markdown_each1.html\", expect(function (err, html) {\n      test.isFalse(err);\n      self.html1 = html;\n    }));\n    Meteor.call(\"getAsset\", \"markdown_each2.html\", expect(function (err, html) {\n      test.isFalse(err);\n      self.html2 = html;\n    }));\n  },\n\n  function (test, expect) {\n    var self = this;\n    var tmpl = Template.old_spacebars_template_test_markdown_each;\n    var R = new ReactiveVar([]);\n    tmpl.seq = function () { return R.get(); };\n\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), canonicalizeHtml(self.html1));\n\n    R.set([\"item\"]);\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), canonicalizeHtml(self.html2));\n  }\n]);\n\nTinytest.add('spacebars-tests - old - template_tests - #markdown - inclusion', function (test) {\n  var tmpl = Template.old_spacebars_template_test_markdown_inclusion;\n  var subtmpl = Template.old_spacebars_template_test_markdown_inclusion_subtmpl;\n  subtmpl.foo = \"bar\";\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"<p><span>Foo is bar.</span></p>\");\n});\n\nTinytest.add('spacebars-tests - old - template_tests - #markdown - block helpers', function (test) {\n  var tmpl = Template.old_spacebars_template_test_markdown_block_helpers;\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"<p>Hi there!</p>\");\n});\n\n// Test that when a simple helper re-runs due to a dependency changing\n// but the return value is the same, the DOM text node is not\n// re-rendered.\nTinytest.add('spacebars-tests - old - template_tests - simple helpers are isolated', function (test) {\n  var runs = [{\n    helper: function () { return \"foo\"; },\n    nodeValue: \"foo\"\n  }, {\n    helper: function () { return new Spacebars.SafeString(\"bar\"); },\n    nodeValue: \"bar\"\n  }];\n\n  _.each(runs, function (run) {\n    var tmpl = Template.old_spacebars_template_test_simple_helpers_are_isolated;\n    var dep = new Tracker.Dependency;\n    tmpl.foo = function () {\n      dep.depend();\n      return run.helper();\n    };\n    var div = renderToDiv(tmpl);\n    var fooTextNode = _.find(div.childNodes, function (node) {\n      return node.nodeValue === run.nodeValue;\n    });\n\n    test.isTrue(fooTextNode);\n\n    dep.changed();\n    Tracker.flush();\n    var newFooTextNode = _.find(div.childNodes, function (node) {\n      return node.nodeValue === run.nodeValue;\n    });\n\n    test.equal(fooTextNode, newFooTextNode);\n  });\n});\n\n// Test that when a helper in an element attribute re-runs due to a\n// dependency changing but the return value is the same, the attribute\n// value is not set.\nTinytest.add('spacebars-tests - old - template_tests - attribute helpers are isolated', function (test) {\n  var tmpl = Template.old_spacebars_template_test_attr_helpers_are_isolated;\n  var dep = new Tracker.Dependency;\n  tmpl.foo = function () {\n    dep.depend();\n    return \"foo\";\n  };\n  var div = renderToDiv(tmpl);\n  var pElement = div.querySelector('p');\n\n  test.equal(pElement.getAttribute('attr'), 'foo');\n\n  // set the attribute to something else, afterwards check that it\n  // hasn't been updated back to the correct value.\n  pElement.setAttribute('attr', 'not-foo');\n  dep.changed();\n  Tracker.flush();\n  test.equal(pElement.getAttribute('attr'), 'not-foo');\n});\n\n// A helper can return an object with a set of element attributes via\n// `<p {{attrs}}>`. When it re-runs due to a dependency changing the\n// value for a given attribute might stay the same. Test that the\n// attribute is not set on the DOM element.\nTinytest.add('spacebars-tests - old - template_tests - attribute object helpers are isolated', function (test) {\n  var tmpl = Template.old_spacebars_template_test_attr_object_helpers_are_isolated;\n  var dep = new Tracker.Dependency;\n  tmpl.attrs = function () {\n    dep.depend();\n    return {foo: \"bar\"};\n  };\n  var div = renderToDiv(tmpl);\n  var pElement = div.querySelector('p');\n\n  test.equal(pElement.getAttribute('foo'), 'bar');\n\n  // set the attribute to something else, afterwards check that it\n  // hasn't been updated back to the correct value.\n  pElement.setAttribute('foo', 'not-bar');\n  dep.changed();\n  Tracker.flush();\n  test.equal(pElement.getAttribute('foo'), 'not-bar');\n});\n\n// Test that when a helper in an inclusion directive (`{{> foo }}`)\n// re-runs due to a dependency changing but the return value is the\n// same, the template is not re-rendered.\n//\n// Also, verify that an error is thrown if the return value from such\n// a helper is not a component.\nTinytest.add('spacebars-tests - old - template_tests - inclusion helpers are isolated', function (test) {\n  var tmpl = Template.old_spacebars_template_test_inclusion_helpers_are_isolated;\n  var dep = new Tracker.Dependency;\n  var subtmpl = Template.old_spacebars_template_test_inclusion_helpers_are_isolated_subtemplate;\n  // make a copy so we can set \"rendered\" without mutating the original\n  var subtmplCopy = new Template(subtmpl.viewName, subtmpl.renderFunction);\n\n  var R = new ReactiveVar(subtmplCopy);\n  tmpl.foo = function () {\n    dep.depend();\n    return R.get();\n  };\n\n  var div = renderToDiv(tmpl);\n    subtmplCopy.rendered = function () {\n    test.fail(\"shouldn't re-render when same value returned from helper\");\n  };\n\n  dep.changed();\n  Tracker.flush({_throwFirstError: true}); // `subtmplCopy.rendered` not called\n\n  R.set(null);\n  Tracker.flush({_throwFirstError: true}); // no error thrown\n\n  R.set(\"neither a component nor null\");\n\n  test.throws(function () {\n    Tracker.flush({_throwFirstError: true});\n  }, /Expected template or null/);\n});\n\nTinytest.add('spacebars-tests - old - template_tests - nully attributes', function (test) {\n  var tmpls = {\n    0: Template.old_spacebars_template_test_nully_attributes0,\n    1: Template.old_spacebars_template_test_nully_attributes1,\n    2: Template.old_spacebars_template_test_nully_attributes2,\n    3: Template.old_spacebars_template_test_nully_attributes3,\n    4: Template.old_spacebars_template_test_nully_attributes4,\n    5: Template.old_spacebars_template_test_nully_attributes5,\n    6: Template.old_spacebars_template_test_nully_attributes6\n  };\n\n  var run = function (whichTemplate, data, expectTrue) {\n    var div = renderToDiv(tmpls[whichTemplate], data);\n    var input = div.querySelector('input');\n    var descr = JSON.stringify([whichTemplate, data, expectTrue]);\n    if (expectTrue) {\n      test.isTrue(input.checked, descr);\n      test.equal(typeof input.getAttribute('stuff'), 'string', descr);\n    } else {\n      test.isFalse(input.checked);\n      test.equal(JSON.stringify(input.getAttribute('stuff')), 'null', descr);\n    }\n\n    var html = Blaze.toHTML(Blaze.With(data, function () {\n      return tmpls[whichTemplate];\n    }));\n\n    test.equal(/ checked=\"[^\"]*\"/.test(html), !! expectTrue);\n    test.equal(/ stuff=\"[^\"]*\"/.test(html), !! expectTrue);\n  };\n\n  run(0, {}, true);\n\n  var truthies = [true, ''];\n  var falsies = [false, null, undefined];\n\n  _.each(truthies, function (x) {\n    run(1, {foo: x}, true);\n  });\n  _.each(falsies, function (x) {\n    run(1, {foo: x}, false);\n  });\n\n  _.each(truthies, function (x) {\n    _.each(truthies, function (y) {\n      run(2, {foo: x, bar: y}, true);\n    });\n    _.each(falsies, function (y) {\n      run(2, {foo: x, bar: y}, true);\n    });\n  });\n  _.each(falsies, function (x) {\n    _.each(truthies, function (y) {\n      run(2, {foo: x, bar: y}, true);\n    });\n    _.each(falsies, function (y) {\n      run(2, {foo: x, bar: y}, false);\n    });\n  });\n\n  run(3, {foo: true}, false);\n  run(3, {foo: false}, false);\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - double\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_double;\n\n  var run = function (foo, expectedResult) {\n    tmpl.foo = foo;\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), expectedResult);\n  };\n\n  run('asdf', 'asdf');\n  run(1.23, '1.23');\n  run(0, '0');\n  run(true, 'true');\n  run(false, '');\n  run(null, '');\n  run(undefined, '');\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - inclusion lookup order\", function (test) {\n  // test that {{> foo}} looks for a helper named 'foo', then a\n  // template named 'foo', then a 'foo' field in the data context.\n  var tmpl = Template.old_spacebars_template_test_inclusion_lookup;\n  var tmplData = function () {\n    return {\n      // shouldn't have an effect since we define a helper with the\n      // same name.\n      old_spacebars_template_test_inclusion_lookup_subtmpl: Template.\n        old_spacebars_template_test_inclusion_lookup_subtmpl3,\n      dataContextSubtmpl: Template.\n        old_spacebars_template_test_inclusion_lookup_subtmpl3};\n  };\n\n  tmpl.old_spacebars_template_test_inclusion_lookup_subtmpl =\n    Template.old_spacebars_template_test_inclusion_lookup_subtmpl2;\n\n  test.equal(canonicalizeHtml(renderToDiv(tmpl, tmplData).innerHTML),\n    [\"This is generated by a helper with the same name.\",\n     \"This is a template passed in the data context.\"].join(' '));\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - content context\", function (test) {\n  var tmpl = Template.old_spacebars_template_test_content_context;\n  var R = ReactiveVar(true);\n  tmpl.foo = {\n    firstLetter: 'F',\n    secondLetter: 'O',\n    bar: {\n      cond: function () { return R.get(); },\n      firstLetter: 'B',\n      secondLetter: 'A'\n    }\n  };\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'BO');\n  R.set(false);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'FA');\n});\n\n_.each(['textarea', 'text', 'password', 'submit', 'button',\n        'reset', 'select', 'hidden'], function (type) {\n  Tinytest.add(\"spacebars-tests - old - template_tests - controls - \" + type, function(test) {\n    var R = ReactiveVar({x:\"test\"});\n    var R2 = ReactiveVar(\"\");\n    var tmpl;\n\n    if (type === 'select') {\n      tmpl = Template.old_spacebars_test_control_select;\n      tmpl.options = ['This is a test', 'This is a fridge',\n                      'This is a frog', 'This is a new frog', 'foobar',\n                      'This is a photograph', 'This is a monkey',\n                      'This is a donkey'];\n      tmpl.selected = function () {\n        R2.get();  // Re-render when R2 is changed, even though it\n                   // doesn't affect HTML.\n        return ('This is a ' + R.get().x) === this.toString();\n      };\n    } else if (type === 'textarea') {\n      tmpl = Template.old_spacebars_test_control_textarea;\n      tmpl.value = function () {\n        R2.get();  // Re-render when R2 is changed, even though it\n                   // doesn't affect HTML.\n        return 'This is a ' + R.get().x;\n      };\n    } else {\n      tmpl = Template.old_spacebars_test_control_input;\n      tmpl.value = function () {\n        R2.get();  // Re-render when R2 is changed, even though it\n                   // doesn't affect HTML.\n        return 'This is a ' + R.get().x;\n      };\n      tmpl.type = type;\n    };\n\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n    var canFocus = (type !== 'hidden');\n\n    // find first element child, ignoring any marker nodes\n    var input = div.firstChild;\n    while (input.nodeType !== 1)\n      input = input.nextSibling;\n\n    if (type === 'textarea' || type === 'select') {\n      test.equal(input.nodeName, type.toUpperCase());\n    } else {\n      test.equal(input.nodeName, 'INPUT');\n      test.equal(input.type, type);\n    }\n    test.equal(DomUtils.getElementValue(input), \"This is a test\");\n\n    // value updates reactively\n    R.set({x:\"fridge\"});\n    Tracker.flush();\n    test.equal(DomUtils.getElementValue(input), \"This is a fridge\");\n\n    if (canFocus) {\n      // ...if focused, it still updates but focus isn't lost.\n      focusElement(input);\n      DomUtils.setElementValue(input, \"something else\");\n      R.set({x:\"frog\"});\n\n      Tracker.flush();\n      test.equal(DomUtils.getElementValue(input), \"This is a frog\");\n      test.equal(document.activeElement, input);\n    }\n\n    // Setting a value (similar to user typing) should prevent value from being\n    // reverted if the div is re-rendered but the rendered value (ie, R) does\n    // not change.\n    DomUtils.setElementValue(input, \"foobar\");\n    R2.set(\"change\");\n    Tracker.flush();\n    test.equal(DomUtils.getElementValue(input), \"foobar\");\n\n    // ... but if the actual rendered value changes, that should take effect.\n    R.set({x:\"photograph\"});\n    Tracker.flush();\n    test.equal(DomUtils.getElementValue(input), \"This is a photograph\");\n\n    document.body.removeChild(div);\n  });\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - radio\", function(test) {\n  var R = ReactiveVar(\"\");\n  var R2 = ReactiveVar(\"\");\n  var change_buf = [];\n  var tmpl = Template.old_spacebars_test_control_radio;\n  tmpl.bands = [\"AM\", \"FM\", \"XM\"];\n  tmpl.isChecked = function () {\n    return R.get() === this.toString();\n  };\n  tmpl.band = function () {\n    return R.get();\n  };\n  tmpl.events({\n    'change input': function (event) {\n      var btn = event.target;\n      var band = btn.value;\n      change_buf.push(band);\n      R.set(band);\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n  document.body.appendChild(div);\n\n  // get the three buttons; they should not change identities!\n  var btns = nodesToArray(div.getElementsByTagName(\"INPUT\"));\n  var text = function () {\n    var text = div.innerText || div.textContent;\n    return text.replace(/[ \\n\\r]+/g, \" \");\n  };\n\n  test.equal(_.pluck(btns, 'checked'), [false, false, false]);\n  test.equal(text(), \"Band: \");\n\n  clickIt(btns[0]);\n  test.equal(change_buf, ['AM']);\n  change_buf.length = 0;\n  Tracker.flush();\n  test.equal(_.pluck(btns, 'checked'), [true, false, false]);\n  test.equal(text(), \"Band: AM\");\n\n  R2.set(\"change\");\n  Tracker.flush();\n  test.length(change_buf, 0);\n  test.equal(_.pluck(btns, 'checked'), [true, false, false]);\n  test.equal(text(), \"Band: AM\");\n\n  clickIt(btns[1]);\n  test.equal(change_buf, ['FM']);\n  change_buf.length = 0;\n  Tracker.flush();\n  test.equal(_.pluck(btns, 'checked'), [false, true, false]);\n  test.equal(text(), \"Band: FM\");\n\n  clickIt(btns[2]);\n  test.equal(change_buf, ['XM']);\n  change_buf.length = 0;\n  Tracker.flush();\n  test.equal(_.pluck(btns, 'checked'), [false, false, true]);\n  test.equal(text(), \"Band: XM\");\n\n  clickIt(btns[1]);\n  test.equal(change_buf, ['FM']);\n  change_buf.length = 0;\n  Tracker.flush();\n  test.equal(_.pluck(btns, 'checked'), [false, true, false]);\n  test.equal(text(), \"Band: FM\");\n\n  document.body.removeChild(div);\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - checkbox\", function(test) {\n  var tmpl = Template.old_spacebars_test_control_checkbox;\n  tmpl.labels = [\"Foo\", \"Bar\", \"Baz\"];\n  var Rs = {};\n  _.each(tmpl.labels, function (label) {\n    Rs[label] = ReactiveVar(false);\n  });\n  tmpl.isChecked = function () {\n    return Rs[this.toString()].get();\n  };\n  var changeBuf = [];\n\n  var div = renderToDiv(tmpl);\n  document.body.appendChild(div);\n\n  var boxes = nodesToArray(div.getElementsByTagName(\"INPUT\"));\n\n  test.equal(_.pluck(boxes, 'checked'), [false, false, false]);\n\n  // Re-render with first one checked.\n  Rs.Foo.set(true);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [true, false, false]);\n\n  // Re-render with first one unchecked again.\n  Rs.Foo.set(false);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [false, false, false]);\n\n  // User clicks the second one.\n  clickElement(boxes[1]);\n  test.equal(_.pluck(boxes, 'checked'), [false, true, false]);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [false, true, false]);\n\n  // Re-render with third one checked. Second one should stay checked because\n  // it's a user update!\n  Rs.Baz.set(true);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [false, true, true]);\n\n  // User turns second and third off.\n  clickElement(boxes[1]);\n  clickElement(boxes[2]);\n  test.equal(_.pluck(boxes, 'checked'), [false, false, false]);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [false, false, false]);\n\n  // Re-render with first one checked. Third should stay off because it's a user\n  // update!\n  Rs.Foo.set(true);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [true, false, false]);\n\n  // Re-render with first one unchecked. Third should still stay off.\n  Rs.Foo.set(false);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [false, false, false]);\n\n  document.body.removeChild(div);\n});\n\nTinytest.add('spacebars-tests - old - template_tests - unfound template', function (test) {\n  test.throws(function () {\n    renderToDiv(Template.old_spacebars_test_nonexistent_template);\n  }, /No such template/);\n});\n\nTinytest.add('spacebars-tests - old - template_tests - helper passed to #if called exactly once when invalidated', function (test) {\n  var tmpl = Template.old_spacebars_test_if_helper;\n\n  var count = 0;\n  var d = new Tracker.Dependency;\n  tmpl.foo = function () {\n    d.depend();\n    count++;\n    return foo;\n  };\n\n  foo = false;\n  var div = renderToDiv(tmpl);\n  divRendersTo(test, div, \"false\");\n  test.equal(count, 1);\n\n  foo = true;\n  d.changed();\n  divRendersTo(test, div, \"true\");\n  test.equal(count, 2);\n});\n\nTinytest.add('spacebars-tests - old - template_tests - custom block helper functions called exactly once when invalidated', function (test) {\n  var tmpl = Template.old_spacebars_test_block_helper_function;\n\n  var count = 0;\n  var d = new Tracker.Dependency;\n  tmpl.foo = function () {\n    d.depend();\n    count++;\n    return Template.old_spacebars_template_test_aaa;\n  };\n\n  foo = false;\n  renderToDiv(tmpl);\n  Tracker.flush();\n  test.equal(count, 1);\n\n  foo = true;\n  d.changed();\n  Tracker.flush();\n  test.equal(count, 2);\n});\n\nvar runOneTwoTest = function (test, subTemplateName, optionsData) {\n  _.each([Template.old_spacebars_test_helpers_stop_onetwo,\n          Template.old_spacebars_test_helpers_stop_onetwo_attribute],\n         function (tmpl) {\n\n           tmpl.one = Template[subTemplateName + '1'];\n           tmpl.two = Template[subTemplateName + '2'];\n\n           var buf = '';\n\n           var showOne = ReactiveVar(true);\n           var dummy = ReactiveVar(0);\n\n           tmpl.showOne = function () { return showOne.get(); };\n           tmpl.one.options = function () {\n             var x = dummy.get();\n             buf += '1';\n             if (optionsData)\n               return optionsData[x];\n             else\n               return ['something'];\n           };\n           tmpl.two.options = function () {\n             var x = dummy.get();\n             buf += '2';\n             if (optionsData)\n               return optionsData[x];\n             else\n               return ['something'];\n           };\n\n           var div = renderToDiv(tmpl);\n           Tracker.flush();\n           test.equal(buf, '1');\n\n           showOne.set(false);\n           dummy.set(1);\n           Tracker.flush();\n           test.equal(buf, '12');\n\n           showOne.set(true);\n           dummy.set(2);\n           Tracker.flush();\n           test.equal(buf, '121');\n\n           // clean up the div\n           $(div).remove();\n           test.equal(showOne._numListeners(), 0);\n           test.equal(dummy._numListeners(), 0);\n         });\n};\n\nTinytest.add('spacebars-tests - old - template_tests - with stops without re-running helper', function (test) {\n  runOneTwoTest(test, 'old_spacebars_test_helpers_stop_with');\n});\n\nTinytest.add('spacebars-tests - old - template_tests - each stops without re-running helper', function (test) {\n  runOneTwoTest(test, 'old_spacebars_test_helpers_stop_each');\n});\n\nTinytest.add('spacebars-tests - old - template_tests - each inside with stops without re-running helper', function (test) {\n  runOneTwoTest(test, 'old_spacebars_test_helpers_stop_with_each');\n});\n\nTinytest.add('spacebars-tests - old - template_tests - if stops without re-running helper', function (test) {\n  runOneTwoTest(test, 'old_spacebars_test_helpers_stop_if', ['a', 'b', 'a']);\n});\n\nTinytest.add('spacebars-tests - old - template_tests - unless stops without re-running helper', function (test) {\n  runOneTwoTest(test, 'old_spacebars_test_helpers_stop_unless', ['a', 'b', 'a']);\n});\n\nTinytest.add('spacebars-tests - old - template_tests - inclusion stops without re-running function', function (test) {\n  var t = Template.old_spacebars_test_helpers_stop_inclusion3;\n  runOneTwoTest(test, 'old_spacebars_test_helpers_stop_inclusion', [t, t, t]);\n});\n\nTinytest.add('spacebars-tests - old - template_tests - template with callbacks inside with stops without recalculating data', function (test) {\n  var tmpl = Template.old_spacebars_test_helpers_stop_with_callbacks3;\n  tmpl.created = function () {};\n  tmpl.rendered = function () {};\n  tmpl.destroyed = function () {};\n  runOneTwoTest(test, 'old_spacebars_test_helpers_stop_with_callbacks');\n});\n\nTinytest.add('spacebars-tests - old - template_tests - no data context is seen as an empty object', function (test) {\n  var tmpl = Template.old_spacebars_test_no_data_context;\n\n  var dataInHelper = 'UNSET';\n  var dataInRendered = 'UNSET';\n  var dataInCreated = 'UNSET';\n  var dataInDestroyed = 'UNSET';\n  var dataInEvent = 'UNSET';\n\n  tmpl.foo = function () {\n    dataInHelper = this;\n  };\n  tmpl.created = function () {\n    dataInCreated = this.data;\n  };\n  tmpl.rendered = function () {\n    dataInRendered = this.data;\n  };\n  tmpl.destroyed = function () {\n    dataInDestroyed = this.data;\n  };\n  tmpl.events({\n    'click': function () {\n      dataInEvent = this;\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n  document.body.appendChild(div);\n  clickElement(div.querySelector('button'));\n  Tracker.flush(); // rendered gets called afterFlush\n  $(div).remove();\n\n  test.isFalse(dataInHelper === window);\n  test.equal(dataInHelper, {});\n  test.equal(dataInCreated, null);\n  test.equal(dataInRendered, null);\n  test.equal(dataInDestroyed, null);\n  test.isFalse(dataInEvent === window);\n  test.equal(dataInEvent, {});\n});\n\nTinytest.add('spacebars-tests - old - template_tests - falsy with', function (test) {\n  var tmpl = Template.old_spacebars_test_falsy_with;\n  var R = ReactiveVar(null);\n  tmpl.obj = function () { return R.get(); };\n\n  var div = renderToDiv(tmpl);\n  divRendersTo(test, div, \"\");\n\n  R.set({greekLetter: 'alpha'});\n  divRendersTo(test, div, \"alpha\");\n\n  R.set(null);\n  divRendersTo(test, div, \"\");\n\n  R.set({greekLetter: 'alpha'});\n  divRendersTo(test, div, \"alpha\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - helpers don't leak\", function (test) {\n  var tmpl = Template.old_spacebars_test_helpers_dont_leak;\n  tmpl.foo = \"wrong\";\n  tmpl.bar = function () { return \"WRONG\"; };\n\n  // Also test that custom block helpers (implemented as templates) do NOT\n  // interfere with helper lookup in the current template\n  Template.old_spacebars_test_helpers_dont_leak2.bonus =\n    function () { return 'BONUS'; };\n\n  var div = renderToDiv(tmpl);\n  divRendersTo(test, div, \"correct BONUS\");\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - event handler returns false\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_event_returns_false;\n    var elemId = \"spacebars_test_event_returns_false_link\";\n    tmpl.events({\n      'click a': function (evt) { return false; }\n    });\n\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n    clickIt(document.getElementById(elemId));\n    // NOTE: This failure can stick across test runs!  Try\n    // removing '#bad-url' from the location bar and run\n    // the tests again. :)\n    test.isFalse(/#bad-url/.test(window.location.hash));\n    document.body.removeChild(div);\n  }\n);\n\n// Make sure that if you bind an event on \"div p\", for example,\n// both the div and the p need to be in the template.  jQuery's\n// `$(elem).find(...)` works this way, but the browser's\n// querySelector doesn't.\nTinytest.add(\n  \"spacebars-tests - old - template_tests - event map selector scope\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_event_selectors1;\n    var tmpl2 = Template.old_spacebars_test_event_selectors2;\n    var buf = [];\n    tmpl2.events({\n      'click div p': function (evt) { buf.push(evt.currentTarget.className); }\n    });\n\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n    test.equal(buf.join(), '');\n    clickIt(div.querySelector('.p1'));\n    test.equal(buf.join(), '');\n    clickIt(div.querySelector('.p2'));\n    test.equal(buf.join(), 'p2');\n    document.body.removeChild(div);\n  }\n);\n\nif (document.addEventListener) {\n  // see note about non-bubbling events in the \"capuring events\"\n  // templating test for why we use the VIDEO tag.  (It would be\n  // nice to get rid of the network dependency, though.)\n  // We skip this test in IE 8.\n  Tinytest.add(\n    \"spacebars-tests - old - template_tests - event map selector scope (capturing)\",\n    function (test) {\n      var tmpl = Template.old_spacebars_test_event_selectors_capturing1;\n      var tmpl2 = Template.old_spacebars_test_event_selectors_capturing2;\n      var buf = [];\n      tmpl2.events({\n        'play div video': function (evt) { buf.push(evt.currentTarget.className); }\n      });\n\n      var div = renderToDiv(tmpl);\n      document.body.appendChild(div);\n      test.equal(buf.join(), '');\n      simulateEvent(div.querySelector(\".video1\"),\n                    \"play\", {}, {bubbles: false});\n      test.equal(buf.join(), '');\n      simulateEvent(div.querySelector(\".video2\"),\n                    \"play\", {}, {bubbles: false});\n      test.equal(buf.join(), 'video2');\n      document.body.removeChild(div);\n    }\n  );\n}\n\nTinytest.add(\"spacebars-tests - old - template_tests - tables\", function (test) {\n  var tmpl1 = Template.old_spacebars_test_tables1;\n\n  var div = renderToDiv(tmpl1);\n  test.equal(_.pluck(div.querySelectorAll('*'), 'tagName'),\n             ['TABLE', 'TR', 'TD']);\n  divRendersTo(test, div, '<table><tr><td>Foo</td></tr></table>');\n\n  var tmpl2 = Template.old_spacebars_test_tables2;\n  tmpl2.foo = 'Foo';\n  div = renderToDiv(tmpl2);\n  test.equal(_.pluck(div.querySelectorAll('*'), 'tagName'),\n             ['TABLE', 'TR', 'TD']);\n  divRendersTo(test, div, '<table><tr><td>Foo</td></tr></table>');\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - jQuery.trigger extraParameters are passed to the event callback\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_jquery_events;\n    var captured = false;\n    var args = [\"param1\", \"param2\", {option: 1}, 1, 2, 3];\n\n    tmpl.events({\n      'someCustomEvent': function (event, template) {\n        var i;\n        for (i=0; i<args.length; i++) {\n          // expect the arguments to be just after template\n          test.equal(arguments[i+2], args[i]);\n        }\n        captured = true;\n      }\n    });\n\n    tmpl.rendered = function () {\n      $(this.find('button')).trigger('someCustomEvent', args);\n    };\n\n    renderToDiv(tmpl);\n    Tracker.flush();\n    test.equal(captured, true);\n  }\n);\n\nTinytest.add(\"spacebars-tests - old - template_tests - toHTML\", function (test) {\n  // run once, verifying that autoruns are stopped\n  var once = function (tmplToRender, tmplForHelper, helper, val) {\n    var count = 0;\n    var R = new ReactiveVar;\n    var getR = function () {\n      count++;\n      return R.get();\n    };\n\n    R.set(val);\n    tmplForHelper[helper] = getR;\n    test.equal(canonicalizeHtml(Blaze.toHTML(tmplToRender)), \"bar\");\n    test.equal(count, 1);\n    R.set(\"\");\n    Tracker.flush();\n    test.equal(count, 1); // all autoruns stopped\n  };\n\n  once(Template.old_spacebars_test_tohtml_basic,\n       Template.old_spacebars_test_tohtml_basic, \"foo\", \"bar\");\n  once(Template.old_spacebars_test_tohtml_if,\n       Template.old_spacebars_test_tohtml_if, \"foo\", \"bar\");\n  once(Template.old_spacebars_test_tohtml_with,\n       Template.old_spacebars_test_tohtml_with, \"foo\", \"bar\");\n  once(Template.old_spacebars_test_tohtml_each,\n       Template.old_spacebars_test_tohtml_each, \"foos\", [\"bar\"]);\n\n  once(Template.old_spacebars_test_tohtml_include_with,\n       Template.old_spacebars_test_tohtml_with, \"foo\", \"bar\");\n  once(Template.old_spacebars_test_tohtml_include_each,\n       Template.old_spacebars_test_tohtml_each, \"foos\", [\"bar\"]);\n});\n\nTinytest.add(\"spacebars-tests - old - template_tests - block comments should not be displayed\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_block_comment;\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), '');\n  }\n);\n\n// Originally reported at https://github.com/meteor/meteor/issues/2046\nTinytest.add(\"spacebars-tests - old - template_tests - {{#with}} with mutated data context\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_with_mutated_data_context;\n    var foo = {value: 0};\n    var dep = new Tracker.Dependency;\n    tmpl.foo = function () {\n      dep.depend();\n      return foo;\n    };\n\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), '0');\n\n    foo.value = 1;\n    dep.changed();\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), '1');\n  });\n\nTinytest.add(\"spacebars-tests - old - template_tests - event handlers get cleaned up when template is removed\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_event_handler_cleanup;\n    var subtmpl = Template.old_spacebars_test_event_handler_cleanup_sub;\n\n    var rv = new ReactiveVar(true);\n    tmpl.foo = function () {\n      return rv.get();\n    };\n\n    subtmpl.events({\n      \"click/mouseover\": function () { }\n    });\n\n    var div = renderToDiv(tmpl);\n\n    test.equal(div.$blaze_events[\"click\"].handlers.length, 1);\n    test.equal(div.$blaze_events[\"mouseover\"].handlers.length, 1);\n\n    rv.set(false);\n    Tracker.flush();\n\n    test.equal(div.$blaze_events[\"click\"].handlers.length, 0);\n    test.equal(div.$blaze_events[\"mouseover\"].handlers.length, 0);\n  }\n);\n\n// This test makes sure that Blaze correctly finds the controller\n// heirarchy surrounding an element that itself doesn't have a\n// controller.\nTinytest.add(\n  \"spacebars-tests - old - template_tests - data context in event handlers on elements inside {{#if}}\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_data_context_for_event_handler_in_if;\n    var data = null;\n    tmpl.events({\n      'click span': function () {\n        data = this;\n      }\n    });\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n    clickIt(div.querySelector('span'));\n    test.equal(data, {foo: \"bar\"});\n    document.body.removeChild(div);\n  });\n\n// https://github.com/meteor/meteor/issues/2156\nTinytest.add(\n  \"spacebars-tests - old - template_tests - each with inserts inside autorun\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_each_with_autorun_insert;\n    var coll = new Mongo.Collection(null);\n    var rv = new ReactiveVar;\n\n    tmpl.items = function () {\n      return coll.find();\n    };\n\n    var div = renderToDiv(tmpl);\n\n    Tracker.autorun(function () {\n      if (rv.get()) {\n        coll.insert({ name: rv.get() });\n      }\n    });\n\n    rv.set(\"foo1\");\n    Tracker.flush();\n    var firstId = coll.findOne()._id;\n\n    rv.set(\"foo2\");\n    Tracker.flush();\n\n    test.equal(canonicalizeHtml(div.innerHTML), \"foo1 foo2\");\n\n    coll.update(firstId, { $set: { name: \"foo3\" } });\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"foo3 foo2\");\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - ui hooks\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_ui_hooks;\n    var rv = new ReactiveVar([]);\n    tmpl.items = function () {\n      return rv.get();\n    };\n\n    var div = renderToDiv(tmpl);\n\n    var hooks = [];\n    var container = div.querySelector(\".test-ui-hooks\");\n\n    // Before we attach the ui hooks, put two items in the DOM.\n    var origVal = [{ _id: 'foo1' }, { _id: 'foo2' }];\n    rv.set(origVal);\n    Tracker.flush();\n\n    container._uihooks = {\n      insertElement: function (n, next) {\n        hooks.push(\"insert\");\n\n        // check that the element hasn't actually been added yet\n        test.isTrue((! n.parentNode) ||\n                    n.parentNode.nodeType === 11 /*DOCUMENT_FRAGMENT_NODE*/);\n      },\n      removeElement: function (n) {\n        hooks.push(\"remove\");\n        // check that the element hasn't actually been removed yet\n        test.isTrue(n.parentNode === container);\n      },\n      moveElement: function (n, next) {\n        hooks.push(\"move\");\n        // check that the element hasn't actually been moved yet\n        test.isFalse(n.nextNode === next);\n      }\n    };\n\n    var testDomUnchanged = function () {\n      var items = div.querySelectorAll(\".item\");\n      test.equal(items.length, 2);\n      test.equal(canonicalizeHtml(items[0].innerHTML), \"foo1\");\n      test.equal(canonicalizeHtml(items[1].innerHTML), \"foo2\");\n    };\n\n    var newVal = _.clone(origVal);\n    newVal.push({ _id: 'foo3' });\n    rv.set(newVal);\n    Tracker.flush();\n    test.equal(hooks, ['insert']);\n    testDomUnchanged();\n\n    newVal.reverse();\n    rv.set(newVal);\n    Tracker.flush();\n    test.equal(hooks, ['insert', 'move']);\n    testDomUnchanged();\n\n    newVal = [origVal[0]];\n    rv.set(newVal);\n    Tracker.flush();\n    test.equal(hooks, ['insert', 'move', 'remove']);\n    testDomUnchanged();\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - ui hooks - nested domranges\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_ui_hooks_nested;\n    var rv = new ReactiveVar(true);\n\n    tmpl.foo = function () {\n      return rv.get();\n    };\n\n    var subtmpl = Template.old_spacebars_test_ui_hooks_nested_sub;\n    var uiHookCalled = false;\n    subtmpl.rendered = function () {\n      this.firstNode.parentNode._uihooks = {\n        removeElement: function (node) {\n          uiHookCalled = true;\n        }\n      };\n    };\n\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n    Tracker.flush();\n\n    var htmlBeforeRemove = canonicalizeHtml(div.innerHTML);\n    rv.set(false);\n    Tracker.flush();\n    test.isTrue(uiHookCalled);\n    var htmlAfterRemove = canonicalizeHtml(div.innerHTML);\n    test.equal(htmlBeforeRemove, htmlAfterRemove);\n    document.body.removeChild(div);\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - Template.instance from helper\",\n  function (test) {\n    // Set a property on the template instance; check that it's still\n    // there from a helper.\n\n    var tmpl = Template.old_spacebars_test_template_instance_helper;\n    var value = Random.id();\n    var instanceFromHelper;\n\n    tmpl.created = function () {\n      this.value = value;\n    };\n    tmpl.foo = function () {\n      instanceFromHelper = Template.instance();\n    };\n\n    var div = renderToDiv(tmpl);\n    test.equal(instanceFromHelper.value, value);\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - Template.instance from helper, \" +\n    \"template instance is kept up-to-date\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_template_instance_helper;\n    var rv = new ReactiveVar(\"\");\n    var instanceFromHelper;\n\n    tmpl.foo = function () {\n      return Template.instance().data;\n    };\n\n    var div = renderToDiv(tmpl, function () { return rv.get(); });\n    rv.set(\"first\");\n    divRendersTo(test, div, \"first\");\n\n    rv.set(\"second\");\n    Tracker.flush();\n    divRendersTo(test, div, \"second\");\n\n    // Template.instance() returns null when no template instance\n    test.isTrue(Template.instance() === null);\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - {{#with}} autorun is cleaned up\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_with_cleanup;\n    var rv = new ReactiveVar(\"\");\n    var helperCalled = false;\n    tmpl.foo = function () {\n      helperCalled = true;\n      return rv.get();\n    };\n\n    var div = renderToDiv(tmpl);\n    rv.set(\"first\");\n    Tracker.flush();\n    test.equal(helperCalled, true);\n\n    helperCalled = false;\n    $(div).find(\".test-with-cleanup\").remove();\n\n    rv.set(\"second\");\n    Tracker.flush();\n    test.equal(helperCalled, false);\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - UI.parentData from helpers\",\n  function (test) {\n    var childTmpl = Template.old_spacebars_test_template_parent_data_helper_child;\n    var parentTmpl = Template.old_spacebars_test_template_parent_data_helper;\n\n    var height = new ReactiveVar(0);\n    var bar = new ReactiveVar(\"bar\");\n\n    childTmpl.a = [\"a\"];\n    childTmpl.b = function () { return bar.get(); };\n    childTmpl.c = [\"c\"];\n\n    childTmpl.foo = function () {\n      var a = Template.parentData(height.get());\n      var b = UI._parentData(height.get()); // back-compat\n      test.equal(a, b);\n      return a;\n    };\n\n    var div = renderToDiv(parentTmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), \"d\");\n\n    height.set(1);\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"bar\");\n\n    // Test UI.parentData() reactivity\n\n    bar.set(\"baz\");\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"baz\");\n\n    height.set(2);\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"a\");\n\n    height.set(3);\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"parent\");\n  }\n);\n\nTinytest.add(\n  \"spacebars - old - SVG <a> elements\",\n  function (test) {\n    if (! document.createElementNS) {\n      // IE 8\n      return;\n    }\n\n    var tmpl = Template.old_spacebars_test_svg_anchor;\n    var div = renderToDiv(tmpl);\n\n    var anchNamespace = $(div).find(\"a\").get(0).namespaceURI;\n    test.equal(anchNamespace, \"http://www.w3.org/2000/svg\");\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - created/rendered/destroyed by each\",\n  function (test) {\n    var outerTmpl =\n          Template.old_spacebars_test_template_created_rendered_destroyed_each;\n    var innerTmpl =\n          Template.old_spacebars_test_template_created_rendered_destroyed_each_sub;\n\n    var buf = '';\n\n    innerTmpl.created = function () { buf += 'C' + String(this.data).toLowerCase(); };\n    innerTmpl.rendered = function () { buf += 'R' + String(this.data).toLowerCase(); };\n    innerTmpl.destroyed = function () { buf += 'D' + String(this.data).toLowerCase(); };\n\n    var R = ReactiveVar([{_id: 'A'}]);\n\n    outerTmpl.items = function () {\n      return R.get();\n    };\n\n    var div = renderToDiv(outerTmpl);\n    divRendersTo(test, div, '<div>A</div>');\n    test.equal(buf, 'CaRa');\n\n    R.set([{_id: 'B'}]);\n    divRendersTo(test, div, '<div>B</div>');\n    test.equal(buf, 'CaRaDaCbRb');\n\n    R.set([{_id: 'C'}]);\n    divRendersTo(test, div, '<div>C</div>');\n    test.equal(buf, 'CaRaDaCbRbDbCcRc');\n\n    $(div).remove();\n    test.equal(buf, 'CaRaDaCbRbDbCcRcDc');\n  });\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - UI.render/UI.remove\",\n  function (test) {\n    var div = document.createElement(\"DIV\");\n    document.body.appendChild(div);\n\n    var created = false, rendered = false, destroyed = false;\n    var R = ReactiveVar('aaa');\n\n    var tmpl = Template.old_spacebars_test_ui_render;\n    tmpl.greeting = function () { return this.greeting || 'Hello'; };\n    tmpl.r = function () { return R.get(); };\n    tmpl.created = function () { created = true; };\n    tmpl.rendered = function () { rendered = true; };\n    tmpl.destroyed = function () { destroyed = true; };\n\n    test.equal([created, rendered, destroyed], [false, false, false]);\n\n    var renderedTmpl = UI.render(tmpl, div);\n    test.equal([created, rendered, destroyed], [true, false, false]);\n\n    // Flush now. We fire the rendered callback in an afterFlush block,\n    // to ensure that the DOM is completely updated.\n    Tracker.flush();\n    test.equal([created, rendered, destroyed], [true, true, false]);\n\n    var otherDiv = document.createElement(\"DIV\");\n    // can run a second time without throwing\n    var x = UI.render(tmpl, otherDiv);\n    // note: we'll have clean up `x` below\n\n    var renderedTmpl2 = UI.renderWithData(\n      tmpl, {greeting: 'Bye'}, div);\n    test.equal(canonicalizeHtml(div.innerHTML),\n               \"<span>Hello aaa</span><span>Bye aaa</span>\");\n    R.set('bbb');\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML),\n               \"<span>Hello bbb</span><span>Bye bbb</span>\");\n    test.equal([created, rendered, destroyed], [true, true, false]);\n    test.equal(R._numListeners(), 3);\n    UI.remove(renderedTmpl);\n    UI.remove(renderedTmpl); // test that double-remove doesn't throw\n    UI.remove(renderedTmpl2);\n    UI.remove(x);\n    test.equal([created, rendered, destroyed], [true, true, true]);\n    test.equal(R._numListeners(), 0);\n    test.equal(canonicalizeHtml(div.innerHTML), \"\");\n  });\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - UI.render fails on jQuery objects\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_ui_render;\n    test.throws(function () {\n      UI.render(tmpl, $('body'));\n    }, /'parentElement' must be a DOM node/);\n    test.throws(function () {\n      UI.render(tmpl, document.body, $('body'));\n    }, /'nextNode' must be a DOM node/);\n  });\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - UI.getElementData\",\n  function (test) {\n    var div = document.createElement(\"DIV\");\n    var tmpl = Template.old_spacebars_test_ui_getElementData;\n    UI.renderWithData(tmpl, {foo: \"bar\"}, div);\n\n    var span = div.querySelector('SPAN');\n    test.isTrue(span);\n    test.equal(UI.getElementData(span), {foo: \"bar\"});\n    test.equal(Blaze.getData(span), {foo: \"bar\"});\n  });\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - autorun cleanup\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_parent_removal;\n\n    var Acalls = '';\n    var A = ReactiveVar('hi');\n    tmpl.A = function (chr) {\n      Acalls += chr;\n      return A.get();\n    };\n    var Bcalls = 0;\n    var B = ReactiveVar(['one', 'two']);\n    tmpl.B = function () {\n      Bcalls++;\n      return B.get();\n    };\n\n    // Assert how many times A and B were accessed (since last time)\n    // and how many autoruns are listening to them.\n    var assertCallsAndListeners =\n          function (a_calls, b_calls, a_listeners, b_listeners) {\n            test.equal('A calls: ' + Acalls.length,\n                       'A calls: ' + a_calls,\n                       Acalls);\n            test.equal('B calls: ' + Bcalls,\n                       'B calls: ' + b_calls);\n            test.equal('A listeners: ' + A._numListeners(),\n                       'A listeners: ' + a_listeners);\n            test.equal('B listeners: ' + B._numListeners(),\n                       'B listeners: ' + b_listeners);\n            Acalls = '';\n            Bcalls = 0;\n          };\n\n    var div = renderToDiv(tmpl);\n    assertCallsAndListeners(10, 1, 10, 1);\n    A.set('');\n    Tracker.flush();\n    // Confirm that #4, #5, #6, and #9 are not re-run.\n    // #a is newly run, for a total of 10 - 4 + 1 = 7,\n    assertCallsAndListeners(7, 0, 7, 1);\n    A.set('hi');\n    Tracker.flush();\n    assertCallsAndListeners(10, 0, 10, 1);\n\n    // Now see that removing the DOM with jQuery, below\n    // the level of the entire template, stops everything.\n    $(div.querySelector('.toremove')).remove();\n    assertCallsAndListeners(0, 0, 0, 0);\n  });\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - focus/blur with clean-up\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_focus_blur_outer;\n    var cond = ReactiveVar(true);\n    tmpl.cond = function () {\n      return cond.get();\n    };\n    var buf = [];\n    Template.old_spacebars_test_focus_blur_inner.events({\n      'focus input': function () {\n        buf.push('FOCUS');\n      },\n      'blur input': function () {\n        buf.push('BLUR');\n      }\n    });\n\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n\n    // check basic focus and blur to make sure\n    // everything is sane\n    test.equal(div.querySelectorAll('input').length, 1);\n    var input;\n    focusElement(input = div.querySelector('input'));\n    // We don't get focus events when the Chrome Dev Tools are focused,\n    // unfortunately, as of Chrome 35.  I think this is a regression in\n    // Chrome 34.  So, the goal is to work whether or not focus is\n    // \"borken,\" where \"working\" means always failing if DOMBackend isn't\n    // correctly unbinding the old event handlers when we switch the IF,\n    // and always passing if it is.  To cause the problem in DOMBackend,\n    // delete the '**' argument to jQuery#off in\n    // DOMBackend.Events.undelegateEvents.  The only compromise we are\n    // making here is that if some unrelated bug in Blaze makes\n    // focus/blur not work, the failure might be masked while the Dev\n    // Tools are open.\n    var borken = false;\n    if (buf.length === 0 && document.activeElement === input) {\n      test.ok({note:\"You might need to defocus the Chrome Dev Tools to get a more accurate run of this test!\"});\n      borken = true;\n      $(input).trigger('focus');\n    }\n    test.equal(buf.join(), 'FOCUS');\n    blurElement(div.querySelector('input'));\n    if (buf.length === 1)\n      $(input).trigger('blur');\n    test.equal(buf.join(), 'FOCUS,BLUR');\n\n    // now switch the IF and check again.  The failure mode\n    // we observed was that DOMBackend would not correctly\n    // unbind the old event listener at the jQuery level,\n    // so the old event listener would fire and cause an\n    // exception inside Blaze (\"Must be attached\" in\n    // DOMRange#containsElement), which would show up in\n    // the console and cause our handler not to fire.\n    cond.set(false);\n    buf.length = 0;\n    Tracker.flush();\n    test.equal(div.querySelectorAll('input').length, 1);\n    focusElement(input = div.querySelector('input'));\n    if (borken)\n      $(input).trigger('focus');\n    test.equal(buf.join(), 'FOCUS');\n    blurElement(div.querySelector('input'));\n    if (! borken)\n      test.equal(buf.join(), 'FOCUS,BLUR');\n\n    document.body.removeChild(div);\n  });\n\n// We used to remove event handlers on DOMRange detached, but when\n// tearing down a view, we don't \"detach\" all the DOMRanges recursively.\n// Mainly, we destroy the View.  Destroying a View should remove its\n// event listeners.  (In practice, however, it's hard to think of\n// consequences to not removing event handlers on removed DOM nodes,\n// which will probably be GCed anyway.)\nTinytest.add(\n  \"spacebars-tests - old - template_tests - event cleanup on destroyed\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_event_cleanup_on_destroyed_outer;\n    var cond = ReactiveVar(true);\n    tmpl.cond = function () {\n      return cond.get();\n    };\n\n    Template.old_spacebars_test_event_cleanup_on_destroyed_inner.events({\n      'click span': function () {}});\n\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n\n    var eventDiv = div.querySelector('div');\n    test.equal(eventDiv.$blaze_events.click.handlers.length, 1);\n\n    cond.set(false);\n    Tracker.flush();\n    test.equal(eventDiv.$blaze_events.click.handlers.length, 0);\n\n    document.body.removeChild(div);\n  });\n\n_.each([1, 2, 3], function (n) {\n  Tinytest.add(\n    \"spacebars-tests - old - template_tests - lookup is isolated \" + n,\n    function (test) {\n      var buf = \"\";\n      var inclusion = Template.old_spacebars_test_isolated_lookup_inclusion;\n      inclusion.created = function () { buf += 'C'; };\n      inclusion.destroyed = function () { buf += 'D'; };\n\n      var tmpl = Template['old_spacebars_test_isolated_lookup' + n];\n      var R = ReactiveVar(Template.old_spacebars_template_test_aaa);\n\n      tmpl.bar = function () {\n        return R.get();\n      };\n\n      var div = renderToDiv(\n        tmpl,\n        function () {\n          return { foo: R.get() };\n        });\n\n      test.equal(canonicalizeHtml(div.innerHTML), 'aaa--x');\n      test.equal(buf, 'C');\n      R.set(Template.old_spacebars_template_test_bbb);\n      Tracker.flush();\n      test.equal(canonicalizeHtml(div.innerHTML), 'bbb--x');\n      test.equal(buf, 'C');\n    }\n  );\n});\n\nTinytest.add('spacebars-tests - old - template_tests - current view in event handler', function (test) {\n  var tmpl = Template.old_spacebars_test_current_view_in_event;\n\n  var currentView;\n  var currentData;\n\n  tmpl.events({\n    'click span': function () {\n      currentView = Blaze.getView();\n      currentData = Blaze.getData();\n    }\n  });\n\n  var div = renderToDiv(tmpl, 'blah');\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>blah</span>');\n  document.body.appendChild(div);\n  clickElement(div.querySelector('span'));\n  $(div).remove();\n\n  test.isTrue(currentView);\n  test.equal(currentData, 'blah');\n});\n\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - textarea attrs\", function (test) {\n    var tmplNoContents = {\n      tmpl: Template.old_spacebars_test_textarea_attrs,\n      hasTextAreaContents: false\n    };\n    var tmplWithContents = {\n      tmpl: Template.old_spacebars_test_textarea_attrs_contents,\n      hasTextAreaContents: true\n    };\n    var tmplWithContentsAndMoreAttrs = {\n      tmpl: Template.old_spacebars_test_textarea_attrs_array_contents,\n      hasTextAreaContents: true\n    };\n\n    _.each(\n      [tmplNoContents, tmplWithContents,\n       tmplWithContentsAndMoreAttrs],\n      function (tmplInfo) {\n\n        var id = new ReactiveVar(\"textarea-\" + Random.id());\n        var name = new ReactiveVar(\"one\");\n        var attrs = new ReactiveVar({\n          id: \"textarea-\" + Random.id()\n        });\n\n        var div = renderToDiv(tmplInfo.tmpl, {\n          attrs: function () {\n            return attrs.get();\n          },\n          name: function () {\n            return name.get();\n          }\n        });\n\n        // Check that the id and value attribute are as we expect.\n        // We can't check div.innerHTML because Chrome at least doesn't\n        // appear to put textarea value attributes in innerHTML.\n        var textarea = div.querySelector(\"textarea\");\n        test.equal(textarea.id, attrs.get().id);\n        test.equal(\n          textarea.value, tmplInfo.hasTextAreaContents ? \"Hello one\" : \"\");\n        // One of the templates has a separate attribute in addition to\n        // an attributes dictionary.\n        if (tmplInfo === tmplWithContentsAndMoreAttrs) {\n          test.equal($(textarea).attr(\"class\"), \"bar\");\n        }\n\n        // Change the id, check that the attribute updates reactively.\n        attrs.set({ id: \"textarea-\" + Random.id() });\n        Tracker.flush();\n        test.equal(textarea.id, attrs.get().id);\n\n        // Change the name variable, check that the textarea value\n        // updates reactively.\n        name.set(\"two\");\n        Tracker.flush();\n        test.equal(\n          textarea.value, tmplInfo.hasTextAreaContents ? \"Hello two\" : \"\");\n\n        if (tmplInfo === tmplWithContentsAndMoreAttrs) {\n          test.equal($(textarea).attr(\"class\"), \"bar\");\n        }\n\n      });\n\n  });\n\nTinytest.add(\n  \"spacebars-tests - old - template_tests - this.autorun\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_autorun;\n    var tmplInner = Template.old_spacebars_test_autorun_inner;\n\n    // Keep track of the value of `Template.instance()` inside the\n    // autorun each time it runs.\n    var autorunTemplateInstances = [];\n    var actualTemplateInstance;\n    var returnedComputation;\n    var computationArg;\n\n    var show = new ReactiveVar(true);\n    var rv = new ReactiveVar(\"foo\");\n\n    tmplInner.created = function () {\n      actualTemplateInstance = this;\n      returnedComputation = this.autorun(function (c) {\n        computationArg = c;\n        rv.get();\n        autorunTemplateInstances.push(Template.instance());\n      });\n    };\n\n    tmpl.helpers({\n      show: function () {\n        return show.get();\n      }\n    });\n\n    var div = renderToDiv(tmpl);\n    test.equal(autorunTemplateInstances.length, 1);\n    test.equal(autorunTemplateInstances[0], actualTemplateInstance);\n\n    // Test that the autorun returned a computation and received a\n    // computation as an argument.\n    test.isTrue(returnedComputation instanceof Tracker.Computation);\n    test.equal(returnedComputation, computationArg);\n\n    // Make sure the autorun re-runs when `rv` changes, and that it has\n    // the correct current view.\n    rv.set(\"bar\");\n    Tracker.flush();\n    test.equal(autorunTemplateInstances.length, 2);\n    test.equal(autorunTemplateInstances[1], actualTemplateInstance);\n\n    // If the inner template is destroyed, the autorun should be stopped.\n    show.set(false);\n    Tracker.flush();\n    rv.set(\"baz\");\n    Tracker.flush();\n\n    test.equal(autorunTemplateInstances.length, 2);\n    test.equal(rv._numListeners(), 0);\n  }\n);\n\n// Test that argument in {{> UI.contentBlock arg}} is evaluated in\n// the proper data context.\nTinytest.add(\n  \"spacebars-tests - old - template_tests - contentBlock argument\",\n  function (test) {\n    var tmpl = Template.old_spacebars_test_contentBlock_arg;\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), 'AAA BBB');\n  });\n\n// Test that when Blaze sets an input field to the same value,\n// we don't lose the insertion point position.\nTinytest.add(\n  \"spacebars-tests - old - template_tests - input field to same value\",\n  function (test) {\n    var tmpl = Template.old_spacebars_template_test_input_field_to_same_value;\n    var R = ReactiveVar(\"BLAH\");\n    tmpl.foo = function () { return R.get(); };\n    var div = renderToDiv(tmpl);\n\n    document.body.appendChild(div);\n\n    var input = div.querySelector('input');\n    test.equal(input.value, \"BLAH\");\n\n    var setSelection = function (startEnd) {\n      startEnd = startEnd.split(' ');\n      if (typeof input.selectionStart === 'number') {\n        // all but IE < 9\n        input.selectionStart = startEnd[0];\n        input.selectionEnd = startEnd[1];\n      } else {\n        // IE 8\n        input.focus();\n        var r = input.createTextRange();\n        // move the start and end of the range to the beginning\n        // of the input field\n        r.moveStart('textedit', -1);\n        r.moveEnd('textedit', -1);\n        // move the start and end a certain number of characters\n        // (relative to their current position)\n        r.moveEnd('character', startEnd[1]);\n        r.moveStart('character', startEnd[0]);\n        r.select();\n      }\n    };\n    var getSelection = function () {\n      if (typeof input.selectionStart === 'number') {\n        // all but IE < 9\n        return input.selectionStart + \" \" + input.selectionEnd;\n      } else {\n        // IE 8\n        input.focus();\n        var r = document.selection.createRange();\n        var fullText = input.value;\n        var start, end;\n        if (r.text) {\n          // one or more characters are selected.\n          // this is kind of hacky!  Relies on fullText\n          // not having duplicate letters, for example.\n          start = fullText.indexOf(r.text);\n          end = start + r.text.length;\n        } else {\n          r.moveStart('textedit', -1);\n          start = end = r.text.length;\n        }\n        return start + \" \" + end;\n      }\n    };\n\n    setSelection(\"2 3\");\n    test.equal(getSelection(), \"2 3\");\n    // At this point, we COULD confirm that setting input.value to\n    // the same thing as before (\"BLAH\") loses the insertion\n    // point (per browser behavior).  However, it doesn't on Firefox.\n    // So we set it to something different, which verifies that our\n    // test machinery is correct.\n    input.value = \"BLAN\";\n    // test that insertion point is lost\n    var selectionAfterSet = getSelection();\n    if (selectionAfterSet !== \"0 0\") // IE 8\n      test.equal(getSelection(), \"4 4\");\n\n    // now make the input say \"BLAH\" but the AttributeHandler\n    // says \"OTHER\" (so we can make it do the no-op update)\n    R.set(\"OTHER\");\n    Tracker.flush();\n    test.equal(input.value, \"OTHER\");\n    input.value = \"BLAH\";\n    setSelection(\"2 2\");\n\n    R.set(\"BLAH\");\n    Tracker.flush();\n    test.equal(input.value, \"BLAH\");\n    // test that didn't lose insertion point!\n    test.equal(getSelection(), \"2 2\");\n\n    // clean up after ourselves\n    document.body.removeChild(div);\n  }\n);\n"
  },
  {
    "path": "packages/spacebars-tests/package.js",
    "content": "Package.describe({\n  summary: \"Additional tests for Spacebars\",\n  version: '1.0.8'\n});\n\n// These tests are in a separate package to avoid a circular dependency\n// between the `spacebars` and `templating` packages.\nPackage.onTest(function (api) {\n  api.use([\n    'es5-shim',\n    'underscore',\n    'spacebars',\n    'tinytest',\n    'jquery',\n    'test-helpers',\n    'reactive-var',\n    'showdown',\n    'minimongo',\n    'tracker',\n    'mongo',\n    'random',\n    'blaze',\n    'session'\n  ]);\n\n  api.use('templating', 'client');\n  api.addFiles([\n    'template_tests.html',\n    'template_tests.js',\n    'templating_tests.html',\n    'templating_tests.js',\n\n    'old_templates.js', // backcompat for packages built with old Blaze APIs.\n    'old_templates_tests.js'\n  ], 'client');\n\n  api.addFiles('template_tests_server.js', 'server');\n\n  api.addAssets([\n    'assets/markdown_basic.html',\n    'assets/markdown_if1.html',\n    'assets/markdown_if2.html',\n    'assets/markdown_each1.html',\n    'assets/markdown_each2.html'\n  ], 'server');\n});\n"
  },
  {
    "path": "packages/spacebars-tests/template_tests.html",
    "content": "\n<!-- convenient templates to use in different tests -->\n<template name=\"spacebars_template_test_aaa\">\n  aaa\n</template>\n\n<template name=\"spacebars_template_test_bbb\">\n  bbb\n</template>\n\n<template name=\"spacebars_template_test_bracketed_this\">\n  [{{this}}]\n</template>\n\n<template name=\"spacebars_template_test_span_this\">\n  <span>{{this}}</span>\n</template>\n\n<template name=\"spacebars_template_test_content\">\n  {{> Template.contentBlock}}\n</template>\n\n<template name=\"spacebars_template_test_elsecontent\">\n  {{> Template.elseBlock}}\n</template>\n\n<template name=\"spacebars_template_test_iftemplate\">\n  {{#if condition}}\n    {{> Template.contentBlock}}\n  {{else}}\n    {{> Template.elseBlock}}\n  {{/if}}\n</template>\n\n<template name=\"spacebars_template_test_bracketed_foo\">\n  [{{foo}}]\n</template>\n\n<!-- -->\n\n\n\n<template name=\"spacebars_template_test_simple_helper\">\n  {{foo bar}}\n</template>\n\n<template name=\"spacebars_template_test_member_helper\">\n  {{user.prefixName 'Mr.'}}\n</template>\n\n<template name=\"spacebars_template_test_dynamic_template\">\n  {{> foo}}\n</template>\n\n<template name=\"spacebars_template_test_interpolate_attribute\">\n  <div class=\"aaa{{foo bar}}zzz\"></div>\n</template>\n\n<template name=\"spacebars_template_test_dynamic_attrs\">\n  <span {{attrsObj}} {{singleAttr}} {{nonexistent}}>hi</span>\n</template>\n\n<template name=\"spacebars_template_test_triple\">\n  {{{html}}}\n</template>\n\n<template name=\"spacebars_template_test_triple2\">\n  x{{{html}}}{{{html2}}}{{{html3}}}y\n</template>\n\n<template name=\"spacebars_template_test_inclusion_args\">\n  {{> foo bar}}\n</template>\n\n<template name=\"spacebars_template_test_inclusion_args2\">\n  {{> foo bar q=baz}}\n</template>\n\n<template name=\"spacebars_template_test_inclusion_dotted_args\">\n  {{> foo bar.baz}}\n</template>\n\n<template name=\"spacebars_template_test_inclusion_slashed_args\">\n  {{> foo bar/baz}}\n</template>\n\n<template name=\"spacebars_template_test_block_helper\">\n  {{#foo}}\n    bar\n  {{else}}\n    baz\n  {{/foo}}\n</template>\n\n<template name=\"spacebars_template_test_block_helper_function_one_string_arg\">\n  {{#foo \"bar\"}}\n    content\n  {{/foo}}\n</template>\n\n<template name=\"spacebars_template_test_block_helper_function_one_helper_arg\">\n  {{#foo bar}}\n    content\n  {{/foo}}\n</template>\n\n<template name=\"spacebars_template_test_block_helper_component_one_helper_arg\">\n  {{#if bar}}\n    content\n  {{/if}}\n</template>\n\n<template name=\"spacebars_template_test_block_helper_component_three_helper_args\">\n  {{#if equals bar_or_baz \"bar\"}}\n    content\n  {{/if}}\n</template>\n\n<template name=\"spacebars_template_test_block_helper_dotted_arg\">\n  {{#foo bar.baz qux}}{{/foo}}\n</template>\n\n<template name=\"spacebars_template_test_nested_content\">\n  {{#spacebars_template_test_iftemplate condition=flag}}\n    hello\n  {{else}}\n    world\n  {{/spacebars_template_test_iftemplate}}\n</template>\n\n<template name=\"spacebars_template_test_iftemplate2\">\n  {{#spacebars_template_test_iftemplate condition=flag}}\n    {{> Template.contentBlock}}\n  {{else}}\n    {{> Template.elseBlock}}\n  {{/spacebars_template_test_iftemplate}}\n</template>\n\n<template name=\"spacebars_template_test_nested_content2\">\n  {{#spacebars_template_test_iftemplate2 flag=x}}\n    hello\n  {{else}}\n    world\n  {{/spacebars_template_test_iftemplate2}}\n</template>\n\n<template name=\"spacebars_template_test_if\">\n  {{#if foo}}\n    {{bar}}\n  {{else}}\n    {{baz}}\n  {{/if}}\n</template>\n\n<template name=\"spacebars_template_test_if_in_with\">\n  {{#with foo}}\n    {{bar}}\n    {{#if true}}\n      {{bar}}\n    {{/if}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_each\">\n  {{#each items}}\n    {{text}}\n  {{else}}\n    else-clause\n  {{/each}}\n</template>\n\n<template name=\"spacebars_template_test_dots\">\n  {{#with foo}}\n    A\n    {{#with bar}}\n      B\n      {{! #if shouldn't add a data context }}\n      {{#if true}}\n        C\n        {{#each items}}\n          D\n          {{! inclusion should only add a data context if passed explicitly }}\n          {{> spacebars_template_test_dots_subtemplate}}\n          {{> spacebars_template_test_dots_subtemplate ..}}\n        {{/each}}\n      {{/if}}\n    {{/with}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_dots_subtemplate\">\n  TITLE\n  1{{title}}\n  2{{./title}}\n  3{{../title}}\n  4{{../../title}}\n\n  GETTITLE\n  5{{getTitle .}}\n  6{{getTitle ..}}\n  7{{getTitle ../..}}\n</template>\n\n<template name=\"spacebars_template_test_select_tag\">\n  <select>\n    {{#each optgroups}}\n      <optgroup label={{label}}>\n        {{#each options}}\n          <option value={{value}} {{selectedAttr}}>{{label}}</option>\n        {{/each}}\n      </optgroup>\n    {{/each}}\n  </select>\n</template>\n\n<!-- Test for issue #770 - falsy value for with. -->\n<template name=\"test_template_issue770\">\n  {{# with value1}}\n    {{this}}\n  {{else}}\n    xxx\n  {{/with}}\n\n  {{# with value2}}\n    {{this}}\n  {{else}}\n    xxx\n  {{/with}}\n\n  {{# with value1}}\n    {{this}}\n  {{/with}}\n\n  {{# with value2}}\n    {{this}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_tricky_attrs\">\n  <input type={{theType}}><input type=checkbox class={{theClass}}>\n</template>\n\n<template name=\"spacebars_template_test_no_data\">\n  {{this.foo}}{{#unless this.bar}}asdf{{/unless}}\n</template>\n\n<template name=\"spacebars_template_test_textarea\">\n  <textarea>{{foo}}</textarea>\n</template>\n\n<template name=\"spacebars_template_test_textarea2\">\n  <textarea>{{#if foo}}</not a tag>{{else}}<also not a tag>{{/if}}</textarea>\n</template>\n\n<template name=\"spacebars_template_test_textarea3\">\n  <textarea id=\"myTextarea\">{{foo}}</textarea>\n</template>\n\n<template name=\"spacebars_template_test_textarea_each\">\n  <textarea>{{#each foo}}<not a tag {{.}} {{else}}<>{{/each}}</textarea>\n</template>\n\n<template name=\"spacebars_template_test_defer_in_rendered\">\n  {{#each items}}\n    {{> spacebars_template_test_defer_in_rendered_subtemplate}}\n  {{/each}}\n</template>\n\n<template name=\"spacebars_template_test_defer_in_rendered_subtemplate\">\n  {{! see rendered callback }}\n</template>\n\n<template name=\"spacebars_template_test_with_someData\">\n  {{#with someData}}\n    {{foo}} {{bar}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_each_stops\">\n  {{#each items}}\n    x\n  {{/each}}\n</template>\n\n<template name=\"spacebars_template_test_block_helpers_in_attribute\">\n  <div class=\"{{#each classes}}{{#if startsLowerCase name}}{{name}} {{/if}}{{else}}none{{/each}}\">Smurf</div>\n</template>\n\n<template name=\"spacebars_template_test_block_helpers_in_attribute_2\">\n  <input value=\"{{#if foo}}\"{{else}}&&lt;></x>{{/if}}\">\n</template>\n\n<template name=\"spacebars_template_test_constant_each_argument\">\n  {{#with someData}}\n    {{#each anArray}}\n      {{justReturn this}}\n    {{/each}}\n    {{this}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_markdown_basic\">\n  {{#with obj}}\n    {{#markdown}}\n{{hi}}\n/each}}\n\n<b>{{hi}}</b>\n<b>/each}}</b>\n\n* {{hi}}\n* /each}}\n\n* <b>{{hi}}</b>\n* <b>/each}}</b>\n\nsome paragraph to fix showdown's four space parsing below.\n\n    {{hi}}\n    /each}}\n\n    <b>{{hi}}</b>\n    <b>/each}}</b>\n\n&gt\n\n* &gt\n\n`&gt`\n\n    &gt\n\n&gt;\n\n* &gt;\n\n`&gt;`\n\n    &gt;\n\n`{{hi}}`\n`/each}}`\n\n`<b>{{hi}}</b>`\n`<b>/each}}`\n\n    {{/markdown}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_markdown_if\">\n  {{#markdown}}\n\n{{#if cond}}true{{else}}false{{/if}}\n\n<b>{{#if cond}}true{{else}}false{{/if}}</b>\n\n* {{#if cond}}true{{else}}false{{/if}}\n\n* <b>{{#if cond}}true{{else}}false{{/if}}</b>\n\nsome paragraph to fix showdown's four space parsing below.\n\n    {{#if cond}}true{{else}}false{{/if}}\n\n    <b>{{#if cond}}true{{else}}false{{/if}}</b>\n\n`{{#if cond}}true{{else}}false{{/if}}`\n\n`<b>{{#if cond}}true{{else}}false{{/if}}</b>`\n\n  {{/markdown}}\n</template>\n\n<template name=\"spacebars_template_test_markdown_each\">\n  {{#markdown}}\n\n{{#each seq}}{{.}}{{/each}}\n\n<b>{{#each seq}}{{.}}{{/each}}</b>\n\n* {{#each seq}}{{.}}{{/each}}\n\n* <b>{{#each seq}}{{.}}{{/each}}</b>\n\nsome paragraph to fix showdown's four space parsing below.\n\n    {{#each seq}}{{.}}{{/each}}\n\n    <b>{{#each seq}}{{.}}{{/each}}</b>\n\n`{{#each seq}}{{.}}{{/each}}`\n\n`<b>{{#each seq}}{{.}}{{/each}}</b>`\n\n  {{/markdown}}\n</template>\n\n<template name=\"spacebars_template_test_markdown_inclusion\">\n  {{#markdown}}\n{{> spacebars_template_test_markdown_inclusion_subtmpl}}\n  {{/markdown}}\n</template>\n\n<template name=\"spacebars_template_test_markdown_inclusion_subtmpl\">\n  <span>{{#if foo}}Foo is {{foo}}.{{/if}}</span>\n</template>\n\n<template name=\"spacebars_template_test_markdown_block_helpers\">\n  {{#markdown}}\n    {{#spacebars_template_test_just_content}}\nHi there!\n    {{/spacebars_template_test_just_content}}\n  {{/markdown}}\n</template>\n\n<template name=\"spacebars_template_test_just_content\">\n  {{> Template.contentBlock}}\n</template>\n\n<template name=\"spacebars_template_test_simple_helpers_are_isolated\">\n  {{foo}}\n</template>\n\n<template name=\"spacebars_template_test_attr_helpers_are_isolated\">\n  <p attr={{foo}}></p>\n</template>\n\n<template name=\"spacebars_template_test_attr_object_helpers_are_isolated\">\n  <p {{attrs}}></p>\n</template>\n\n<template name=\"spacebars_template_test_inclusion_helpers_are_isolated\">\n  {{> foo}}\n</template>\n\n<template name=\"spacebars_template_test_inclusion_helpers_are_isolated_subtemplate\">\n</template>\n\n<template name=\"spacebars_template_test_nully_attributes0\">\n  <input type=\"checkbox\" checked=\"\" stuff=\"\">\n</template>\n\n<template name=\"spacebars_template_test_nully_attributes1\">\n  <input type=\"checkbox\" checked={{foo}} stuff={{foo}}>\n</template>\n\n<template name=\"spacebars_template_test_nully_attributes2\">\n  <input type=\"checkbox\" checked={{foo}}{{bar}} stuff={{foo}}{{bar}}>\n</template>\n\n<template name=\"spacebars_template_test_nully_attributes3\">\n  <input type=\"checkbox\" checked={{#if foo}}{{/if}} stuff={{#if foo}}{{/if}}>\n</template>\n\n<template name=\"spacebars_template_test_double\">\n  {{foo}}\n</template>\n\n<template name=\"spacebars_template_test_inclusion_lookup\">\n  {{> spacebars_template_test_inclusion_lookup_subtmpl}}\n  {{> dataContextSubtmpl}}\n</template>\n\n<template name=\"spacebars_template_test_inclusion_lookup_subtmpl\">\n  This is the template.\n</template>\n\n<template name=\"spacebars_template_test_inclusion_lookup_subtmpl2\">\n  This is generated by a helper with the same name.\n</template>\n\n<template name=\"spacebars_template_test_inclusion_lookup_subtmpl3\">\n  This is a template passed in the data context.\n</template>\n\n<template name=\"spacebars_template_test_content_context\">\n  {{#with foo}}\n    {{#with bar}}\n      {{#spacebars_template_test_iftemplate condition=cond}}\n        {{firstLetter}}{{../secondLetter}}\n      {{else}}\n        {{../firstLetter}}{{secondLetter}}\n      {{/spacebars_template_test_iftemplate}}\n    {{/with}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_test_control_input\">\n  <input type={{type}} value={{value}}>\n</template>\n\n<template name=\"spacebars_test_control_textarea\">\n  <textarea>{{value}}</textarea>\n</template>\n\n<template name=\"spacebars_test_control_select\">\n  <select>\n    {{#each options}}\n      <option selected={{selected}}>{{.}}</option>\n    {{/each}}\n  </select>\n</template>\n\n<template name=\"spacebars_test_control_radio\">\n  Band:\n\n  {{#each bands}}\n    <input name=\"bands\" type=\"radio\" value={{.}} checked={{isChecked}} />\n  {{/each}}\n\n  {{band}}\n</template>\n\n<template name=\"spacebars_test_control_checkbox\">\n  {{#each labels}}\n    <input type=\"checkbox\" value={{.}} checked={{isChecked}} />\n  {{/each}}\n</template>\n\n<template name=\"spacebars_test_nonexistent_template\">\n  {{> this_template_lives_in_outer_space}}\n</template>\n\n<template name=\"spacebars_test_if_helper\">\n  {{#if foo}}\n    true\n  {{else}}\n    false\n  {{/if}}\n</template>\n\n<template name=\"spacebars_test_block_helper_function\">\n  {{#foo}}\n  {{/foo}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_onetwo\">\n  {{#if showOne}}\n    {{> one}}\n  {{else}}\n    {{> two}}\n  {{/if}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_onetwo_attribute\">\n  <br data-stuff=\n  {{#if showOne}}\n    {{> one}}\n  {{else}}\n    {{> two}}\n  {{/if}}>\n</template>\n\n<template name=\"spacebars_test_helpers_stop_with1\">\n  {{#with options}}\n    one\n  {{/with}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_with2\">\n  {{#with options}}\n    two\n  {{/with}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_each1\">\n  {{#each options}}\n    one\n  {{/each}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_each2\">\n  {{#each options}}\n    two\n  {{/each}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_with_each1\">\n  {{#with options}}\n    {{> spacebars_test_helpers_stop_with_each3}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_with_each2\">\n  {{#with options}}\n    {{> spacebars_test_helpers_stop_with_each3}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_with_each3\">\n  {{#each this}}\n  {{/each}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_if1\">\n  {{#if options}}\n    one\n  {{/if}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_if2\">\n  {{#if options}}\n    two\n  {{/if}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_inclusion1\">\n  {{> options}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_inclusion2\">\n  {{> options}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_inclusion3\">\n  blah\n</template>\n\n<template name=\"spacebars_test_helpers_stop_with_callbacks1\">\n  {{#with options}}\n    {{> spacebars_test_helpers_stop_with_callbacks3}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_with_callbacks2\">\n  {{#with options}}\n    {{> spacebars_test_helpers_stop_with_callbacks3}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_with_callbacks3\">\n  blah\n</template>\n\n<template name=\"spacebars_test_helpers_stop_unless1\">\n  {{#unless options}}\n    one\n  {{/unless}}\n</template>\n\n<template name=\"spacebars_test_helpers_stop_unless2\">\n  {{#unless options}}\n    two\n  {{/unless}}\n</template>\n\n<template name=\"spacebars_test_no_data_context\">\n  <button></button>\n  {{foo}}\n</template>\n\n<template name=\"spacebars_test_falsy_with\">\n  {{#with obj}}\n    {{greekLetter}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_test_helpers_dont_leak\">\n  {{> spacebars_test_helpers_dont_leak2 foo=\"correct\"}}\n</template>\n\n<template name=\"spacebars_test_helpers_dont_leak2\">\n  {{foo}}{{bar}} {{#spacebars_template_test_content}}{{bonus}}{{/spacebars_template_test_content}}\n</template>\n\n<template name=\"spacebars_test_event_returns_false\">\n  <a href=\"#bad-url\" id=\"spacebars_test_event_returns_false_link\">click me</a>\n</template>\n\n<template name=\"spacebars_test_event_selectors1\">\n  <div>{{> spacebars_test_event_selectors2}}</div>\n</template>\n\n<template name=\"spacebars_test_event_selectors2\">\n  <p class=\"p1\">Not it</p>\n  <div><p class=\"p2\">It</p></div>\n</template>\n\n<template name=\"spacebars_test_event_selectors_capturing1\">\n  <div>{{> spacebars_test_event_selectors_capturing2}}</div>\n</template>\n\n<template name=\"spacebars_test_event_selectors_capturing2\">\n  <video class='video1'>\n    <source id='mp4'\n      src=\"http://media.w3.org/2010/05/sintel/trailer.mp4\"\n      type='video/mp4'>\n  </video>\n  <div>\n    <video class='video2'>\n      <source id='mp4'\n        src=\"http://media.w3.org/2010/05/sintel/trailer.mp4\"\n        type='video/mp4'>\n    </video>\n  </div>\n</template>\n\n<template name=\"spacebars_test_tables1\">\n  <table><tr><td>Foo</td></tr></table>\n</template>\n\n<template name=\"spacebars_test_tables2\">\n  <table><tr><td>{{foo}}</td></tr></table>\n</template>\n\n<template name=\"spacebars_test_jquery_events\">\n  <button type=\"button\">button</button>\n</template>\n\n<template name=\"spacebars_test_tohtml_basic\">\n  {{foo}}\n</template>\n\n<template name=\"spacebars_test_tohtml_if\">\n  {{#if true}}\n    {{foo}}\n  {{/if}}\n</template>\n\n<template name=\"spacebars_test_tohtml_with\">\n  {{#with foo}}\n    {{.}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_test_tohtml_each\">\n  {{#each foos}}\n    {{.}}\n  {{/each}}\n</template>\n\n<template name=\"spacebars_test_tohtml_include_with\">\n  {{> spacebars_test_tohtml_with}}\n</template>\n\n<template name=\"spacebars_test_tohtml_include_each\">\n  {{> spacebars_test_tohtml_each}}\n</template>\n\n<template name=\"spacebars_test_block_comment\">\n  {{!-- foo --}}\n  {{!--\n    {{bar}}\n  --}}\n</template>\n\n<template name=\"spacebars_test_with_mutated_data_context\">\n  {{#with foo}}\n    {{value}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_test_url_attribute\">\n  <a href=\"{{foo}}\"></a>\n  <a hReF=\"{{foo}}\"></a>\n  <form action=\"{{foo}}\"></form>\n  <img src=\"{{foo}}\" />\n  <input value=\"{{foo}}\" />\n</template>\n\n<template name=\"spacebars_test_event_handler_cleanup\">\n  {{#if foo}}\n    {{>spacebars_test_event_handler_cleanup_sub}}\n  {{/if}}\n</template>\n\n<template name=\"spacebars_test_event_handler_cleanup_sub\">\n  <div></div>\n</template>\n\n<template name=\"spacebars_test_data_context_for_event_handler_in_if\">\n  {{#with foo=\"bar\"}}\n    {{#if true}}\n      <span>Click me!</span>\n    {{/if}}\n  {{/with}}\n</template>\n\n\n<template name=\"spacebars_test_each_with_autorun_insert\">\n  {{#each items}}\n    {{name}}\n  {{/each}}\n</template>\n\n<template name=\"spacebars_test_ui_hooks\">\n  <div class=\"test-ui-hooks\">\n    {{#each items}}\n      <div class=\"item\">{{_id}}</div>\n    {{/each}}\n  </div>\n</template>\n\n<template name=\"spacebars_test_ui_hooks_nested\">\n  {{#if foo}}\n    {{> spacebars_test_ui_hooks_nested_sub}}\n  {{/if}}\n</template>\n\n<template name=\"spacebars_test_ui_hooks_nested_sub\">\n  <div>\n    {{#with true}}\n      <p>hello</p>\n    {{/with}}\n  </div>\n</template>\n\n<template name=\"spacebars_test_template_instance_helper\">\n  {{#with true}}{{foo}}{{/with}}\n</template>\n\n<template name=\"spacebars_test_with_cleanup\">\n  <div class=\"test-with-cleanup\">\n    {{#with foo}}\n      {{this}}\n    {{/with}}\n  </div>\n</template>\n\n<template name=\"spacebars_test_template_parent_data_helper\">\n  {{#with \"parent\"}}\n    {{> spacebars_test_template_parent_data_helper_child}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_test_template_parent_data_helper_child\">\n  {{#each a}}\n    {{#with b}}\n      {{#if c}}\n        {{#with \"d\"}}\n          {{foo}}\n        {{/with}}\n      {{/if}}\n    {{/with}}\n  {{/each}}\n</template>\n\n<template name=\"spacebars_test_svg_anchor\">\n  <svg>\n    <a xlink:href=\"http://www.example.com\">Foo</a>\n  </svg>\n</template>\n\n<template name=\"spacebars_test_template_created_rendered_destroyed_each\">\n  {{#each items}}\n    <div>{{> spacebars_test_template_created_rendered_destroyed_each_sub _id}}</div>\n  {{/each}}\n</template>\n\n<template name=\"spacebars_test_template_created_rendered_destroyed_each_sub\">\n  {{.}}\n</template>\n\n<template name=\"spacebars_test_ui_getElementData\">\n  <span></span>\n</template>\n\n<template name=\"spacebars_test_ui_render\">\n  <span>{{greeting}} {{r}}</span>\n</template>\n\n<template name=\"spacebars_test_parent_removal\">\n  <div class=\"a\">\n    <div class=\"b\">\n      <div class=\"toremove\">\n        <div class=\"c\">\n          {{A 1}}\n          {{{A 2}}}\n          {{#with A 3}}\n            {{A 4}}\n            {{#with A 5}}\n              {{A 6}}\n            {{/with}}\n          {{/with}}\n          {{#each B}}\n            {{A 7}}\n          {{/each}}\n          {{#if A 8}}\n            {{A 9}}\n          {{else}}\n            {{A 'a'}}\n          {{/if}}\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n\n<template name=\"spacebars_test_focus_blur_outer\">\n  {{#if cond}}\n    a {{> spacebars_test_focus_blur_inner}}\n  {{else}}\n    b {{> spacebars_test_focus_blur_inner}}\n  {{/if}}\n</template>\n\n<template name=\"spacebars_test_focus_blur_inner\">\n  <input type=\"text\">\n</template>\n\n<template name=\"spacebars_test_event_cleanup_on_destroyed_outer\">\n  {{#if cond}}\n    <div>a {{> spacebars_test_event_cleanup_on_destroyed_inner}}</div>\n  {{else}}\n    <div>b {{> spacebars_test_event_cleanup_on_destroyed_inner}}</div>\n  {{/if}}\n</template>\n\n<template name=\"spacebars_test_event_cleanup_on_destroyed_inner\">\n  <span>foo</span>\n</template>\n\n<template name=\"spacebars_test_isolated_lookup_inclusion\">\n  x\n</template>\n\n<template name=\"spacebars_test_isolated_lookup1\">\n  {{> foo}}--{{> spacebars_test_isolated_lookup_inclusion}}\n</template>\n\n<template name=\"spacebars_test_isolated_lookup2\">\n  {{#with foo}}\n    {{#with z=1}}\n      {{> ..}}--{{> spacebars_test_isolated_lookup_inclusion}}\n    {{/with}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_test_isolated_lookup3\">\n  {{> bar}}--{{> spacebars_test_isolated_lookup_inclusion}}\n</template>\n\n<template name=\"spacebars_test_current_view_in_event\">\n  <span>{{.}}</span>\n</template>\n\n<template name=\"spacebars_test_textarea_attrs\">\n  <textarea {{attrs}}></textarea>\n</template>\n\n<template name=\"spacebars_test_textarea_attrs_contents\">\n  <textarea {{attrs}}>Hello {{name}}</textarea>\n</template>\n\n<template name=\"spacebars_test_textarea_attrs_array_contents\">\n  <textarea {{attrs}} class=\"bar\">Hello {{name}}</textarea>\n</template>\n\n<template name=\"spacebars_test_autorun\">\n  {{#if show}}\n    {{>spacebars_test_autorun_inner}}\n  {{/if}}\n</template>\n\n<template name=\"spacebars_test_autorun_inner\">\n  Hello\n</template>\n\n<template name=\"spacebars_test_contentBlock_arg\">\n  {{#spacebars_test_contentBlock_arg_inner}}\n    {{this.bar}}\n  {{/spacebars_test_contentBlock_arg_inner}}\n</template>\n\n<template name=\"spacebars_test_contentBlock_arg_inner\">\n  {{#with foo=\"AAA\" bar=\"BBB\"}}\n    {{this.foo}} {{> Template.contentBlock this}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_input_field_to_same_value\">\n  <input type=\"text\" value={{foo}}>\n</template>\n\n<template name=\"spacebars_template_test_content_backcompat\">\n  {{#spacebars_template_test_iftemplate_backcompat condition=flag}}\n    hello\n  {{else}}\n    world\n  {{/spacebars_template_test_iftemplate_backcompat}}\n</template>\n\n<template name=\"spacebars_template_test_iftemplate_backcompat\">\n  {{#if condition}}\n    {{> UI.contentBlock}}\n  {{else}}\n    {{> UI.elseBlock}}\n  {{/if}}\n</template>\n\n<template name=\"spacebars_template_test_content_context_backcompat\">\n  {{#with foo}}\n    {{#with bar}}\n      {{#spacebars_template_test_iftemplate_backcompat condition=cond}}\n        {{firstLetter}}{{../secondLetter}}\n      {{else}}\n        {{../firstLetter}}{{secondLetter}}\n      {{/spacebars_template_test_iftemplate_backcompat}}\n    {{/with}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_falsy_helper\">\n  foo:{{foo}} GLOBAL_ZERO:{{GLOBAL_ZERO}}\n</template>\n\n<template name=\"spacebars_template_test_oldstyle_helpers\">\n  {{foo}}\n</template>\n\n<!-- issue meteor/meteor #3130 -->\n<template name=\"spacebars_template_test_with_data_remove\">\n  <b>some data - {{foo}}</b>\n</template>\n\n<template name=\"spacebars_template_test_inclusion_with_data_remove\">\n  <span>\n    {{> spacebars_template_test_inclusion_with_data_remove_inner \"stuff\"}}\n  </span>\n</template>\n\n<template name=\"spacebars_template_test_inclusion_with_data_remove_inner\">\n  <b>{{.}}</b>\n</template>\n\n<!-- issue meteor/meteor #3540 -->\n<template name=\"spacebars_template_test_template_instance_wrapper_outer\">\n  {{#spacebars_template_test_template_instance_wrapper_wrapper}}\n    {{thisShouldOutputHello}}\n  {{/spacebars_template_test_template_instance_wrapper_wrapper}}\n  {{thisShouldOutputHello}}\n</template>\n\n<template name=\"spacebars_template_test_template_instance_wrapper_wrapper\">\n  {{> Template.contentBlock}}\n</template>\n\n<template name=\"spacebars_template_test_template_level_subscriptions\">\n  {{#if Template.subscriptionsReady}}\n    ready!\n  {{/if}}\n  {{Template.subscriptionsReady}}\n</template>\n\n<template name=\"spacebars_template_test_template_level_subs_resubscribe\">\n  {{#if ifArg}}\n    {{subscribingHelper1}}\n  {{else}}\n    {{subscribingHelper2}}\n  {{/if}}\n</template>\n\n<template name=\"spacebars_template_test_old_each_data_context\">\n  {{#each items}}\n    <div>{{text}}</div>\n  {{/each}}\n</template>\n\n<template name=\"spacebars_template_test_new_each_data_context\">\n  {{#with dataContext}}\n    {{#each item in items}}\n      <div>{{item.text}} -- {{toplevel}}</div>\n    {{/each}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_new_each_data_context_subexpr\">\n  {{#with dataContext}}\n    {{#each item in (items)}}\n      <div>{{item.text}} -- {{toplevel}}</div>\n    {{/each}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_new_each_lookup_top_level\">\n  {{#with dataContext}}\n    {{#each item in letter_a}}\n      {{#spacebars_template_test_new_each_lookup_block_helper}}\n        <div>\n          {{item}}\n        </div>\n      {{/spacebars_template_test_new_each_lookup_block_helper}}\n    {{/each}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_new_each_lookup_block_helper\">\n  {{#with subcontext}}\n    {{#each item in letter_b}}\n      {{> Template.contentBlock}}\n    {{/each}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_let_bindings\">\n  {{#with dataContext}}\n    {{#let alias=helper anotherVarFromContext=\"override\"}}\n      <div>{{alias}} -- {{helper}} -- {{varFromContext}} -- {{anotherVarFromContext}}</div>\n    {{/let}}\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_each_index\">\n  {{#each things}}\n    <span>{{@index}} - {{num}}</span>\n  {{/each}}\n</template>\n\n<template name=\"spacebars_template_test_nested_exprs\">\n  {{add (add 1 2) 3}}\n</template>\n\n<template name=\"spacebars_template_test_nested_subexprs\">\n  {{capitalize (firstWord generateSentence)}}\n</template>\n\n<template name=\"spacebars_template_test_exprs_keyword_callable\">\n  {{stuff}} {{another}}\n</template>\n\n<template name=\"spacebars_template_test_exprs_keyword\">\n  {{> spacebars_template_test_exprs_keyword_callable stuff=(capitalize name) another=(capitalize \"mello\")}}\n</template>\n\n<template name=\"spacebars_template_test_with_rerender\">\n  <input type=\"text\" class=\"foo\">\n  {{#with y=x}}\n    <span class=\"bar\">{{y}}</span>\n  {{/with}}\n</template>\n\n<template name=\"spacebars_template_test_let_rerender\">\n  <input type=\"text\" class=\"foo\">\n  {{#let y=x}}\n    <span class=\"bar\">{{y}}</span>\n  {{/let}}\n</template>\n\n<template name=\"spacebars_template_test_each_multiarg\">\n  {{#each helper arg}}\n    <div>{{this}}</div>\n  {{/each}}\n</template>\n\n<template name=\"spacebars_template_test_lexical_leakage\">\n  {{#each list}}\n    <div><span>{{@index}}</span>{{> spacebars_template_test_get_index}}</div>\n  {{/each}}\n</template>\n\n<template name=\"spacebars_template_test_get_index\">\n  <span>{{@index}}</span>\n</template>\n\n<template name=\"spacebars_template_test_each_in_multi_args\">\n  {{#each item in helper list}}\n    <div>{{item}}</div>\n  {{/each}}\n</template>\n"
  },
  {
    "path": "packages/spacebars-tests/template_tests.js",
    "content": "var divRendersTo = function (test, div, html) {\n  Tracker.flush({_throwFirstError: true});\n  var actual = canonicalizeHtml(div.innerHTML);\n  test.equal(actual, html);\n};\n\nvar nodesToArray = function (array) {\n  // Starting in underscore 1.4, _.toArray does not work right on a node\n  // list in IE8. This is a workaround to support IE8.\n  return _.map(array, _.identity);\n};\n\n// maybe use created callback on the template instead of this?\nvar extendTemplateWithInit = function (template, initFunc) {\n  var tmpl = new Template(template.viewName+'-extended', template.renderFunction);\n  tmpl.constructView = function (/*args*/) {\n    var view = Template.prototype.constructView.apply(this, arguments);\n    initFunc(view);\n    return view;\n  };\n  return tmpl;\n};\n\n// Make a \"clone\" of origTemplate (but not its helpers)\nvar copyTemplate = function (origTemplate) {\n  return new Template(origTemplate.viewName, origTemplate.renderFunction);\n};\n\nTinytest.add(\"spacebars-tests - template_tests - simple helper\", function (test) {\n  var baseTmpl = Template.spacebars_template_test_simple_helper;\n  var tmpl1 = copyTemplate(baseTmpl);\n  var R = ReactiveVar(1);\n  tmpl1.helpers({\n    foo: function (x) {\n      return x + R.get();\n    },\n    bar: function () {\n      return 123;\n    }\n  });\n  var div = renderToDiv(tmpl1);\n\n  test.equal(canonicalizeHtml(div.innerHTML), \"124\");\n  R.set(2);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"125\");\n\n  // Test that `{{foo bar}}` throws if `foo` is missing or not a function.\n  var tmpl2 = copyTemplate(baseTmpl);\n  tmpl2.helpers({foo: 3});\n  test.throws(function () {\n    renderToDiv(tmpl2);\n  }, /Can't call non-function/);\n\n  var tmpl3 = copyTemplate(baseTmpl);\n  test.throws(function () {\n    renderToDiv(tmpl3);\n  }, /No such function/);\n\n  var tmpl4 = copyTemplate(baseTmpl);\n  tmpl4.helpers({foo: function () {}});\n  // doesn't throw\n  div = renderToDiv(tmpl4);\n  test.equal(canonicalizeHtml(div.innerHTML), '');\n\n  // now make \"foo\" is a function in the data context\n  var tmpl5 = copyTemplate(baseTmpl);\n  tmpl5.helpers({\n    bar: function () {\n      return 123;\n    }\n  });\n\n  R = ReactiveVar(1);\n  div = renderToDiv(tmpl5, { foo: function (x) {\n    return x + R.get();\n  } });\n  test.equal(canonicalizeHtml(div.innerHTML), \"124\");\n  R.set(2);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"125\");\n\n  test.throws(function () {\n    renderToDiv(tmpl5, {foo: 3});\n  }, /Can't call non-function/);\n\n  test.throws(function () {\n    renderToDiv(tmpl5, {foo: null});\n  }, /No such function/);\n\n  test.throws(function () {\n    renderToDiv(tmpl5, {});\n  }, /No such function/);\n});\n\nTinytest.add(\"spacebars-tests - template_tests - member helper\", function (test) {\n  var baseTmpl = Template.spacebars_template_test_member_helper;\n\n  // Test that returning function member of a data object can be used as a\n  // a helper within a template, in this case, {{user.prefixName 'Mr.'}}\n  var tmpl1 = copyTemplate(baseTmpl);\n  var name = ReactiveVar('foo');\n  tmpl1.helpers({\n    user: function() {\n      return {\n        prefixName: function(prefix) {\n          return prefix + ' ' + name.get();\n        },\n      };\n    },\n  });\n  var div = renderToDiv(tmpl1);\n  test.equal(canonicalizeHtml(div.innerHTML), 'Mr. foo');\n  name.set('bar');\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'Mr. bar');\n\n  // Test that `{{user.prefixName 'Mr.'}}` returns nothing if `user` is not\n  // not a function or is completely missing from helpers.\n  var tmpl2 = copyTemplate(baseTmpl);\n  tmpl2.helpers({user: 3});\n  div = renderToDiv(tmpl2);\n  test.equal(canonicalizeHtml(div.innerHTML), '');\n\n  var tmpl3 = copyTemplate(baseTmpl);\n  div = renderToDiv(tmpl3);\n  test.equal(canonicalizeHtml(div.innerHTML), '');\n\n  // Test that `{{user.prefixName 'Mr.'}}` returns nothing if the `user`\n  // returns null. Before fixing Meteor issue #5441, this test would throw.\n  var tmpl4 = copyTemplate(baseTmpl);\n  tmpl4.helpers({user: function () {}});\n  div = renderToDiv(tmpl4);\n  test.equal(canonicalizeHtml(div.innerHTML), '');\n\n  // One more test, similar to the above, but where `user` is not null but\n  // `user.prefixName` is. This test was also broken prior to the fix.\n  var tmpl4 = copyTemplate(baseTmpl);\n  tmpl4.helpers({user: function () { return {prefixName: null}; }});\n  div = renderToDiv(tmpl4);\n  test.equal(canonicalizeHtml(div.innerHTML), '');\n});\n\nTinytest.add(\"spacebars-tests - template_tests - dynamic template\", function (test) {\n  var tmpl = Template.spacebars_template_test_dynamic_template;\n  var aaa = Template.spacebars_template_test_aaa;\n  var bbb = Template.spacebars_template_test_bbb;\n  var R = ReactiveVar(\"aaa\");\n  tmpl.helpers({foo: function () {\n    return R.get() === 'aaa' ? aaa : bbb;\n  }});\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"aaa\");\n\n  R.set('bbb');\n  Tracker.flush();\n\n  test.equal(canonicalizeHtml(div.innerHTML), \"bbb\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - interpolate attribute\", function (test) {\n  var tmpl = Template.spacebars_template_test_interpolate_attribute;\n  tmpl.helpers({\n    foo: function (x) {\n      return x+1;\n    },\n    bar: function () {\n      return 123;\n    }\n  });\n  var div = renderToDiv(tmpl);\n\n  test.equal($(div).find('div')[0].className, \"aaa124zzz\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - dynamic attrs\", function (test) {\n  var tmpl = Template.spacebars_template_test_dynamic_attrs;\n\n  var R2 = ReactiveVar({x: \"X\"});\n  var R3 = ReactiveVar('selected');\n  tmpl.helpers({\n    attrsObj: function () { return R2.get(); },\n    singleAttr: function () { return R3.get(); }\n  });\n\n  var div = renderToDiv(tmpl);\n  var span = $(div).find('span')[0];\n  test.equal(span.innerHTML, 'hi');\n  test.isTrue(span.hasAttribute('selected'));\n  test.equal(span.getAttribute('x'), 'X');\n\n  R2.set({y: \"Y\", z: \"Z\"});\n  R3.set('');\n  Tracker.flush();\n  test.equal(canonicalizeHtml(span.innerHTML), 'hi');\n  test.isFalse(span.hasAttribute('selected'));\n  test.isFalse(span.hasAttribute('x'));\n  test.equal(span.getAttribute('y'), 'Y');\n  test.equal(span.getAttribute('z'), 'Z');\n});\n\nTinytest.add(\"spacebars-tests - template_tests - triple\", function (test) {\n  var tmpl = Template.spacebars_template_test_triple;\n\n  var R = ReactiveVar('<span class=\"hi\">blah</span>');\n  tmpl.helpers({\n    html: function () { return R.get(); }\n  });\n\n  var div = renderToDiv(tmpl);\n  var elems = $(div).find(\"> *\");\n  test.equal(elems.length, 1);\n  test.equal(elems[0].nodeName, 'SPAN');\n  var span = elems[0];\n  test.equal(span.className, 'hi');\n  test.equal(span.innerHTML, 'blah');\n\n  R.set('asdf');\n  Tracker.flush();\n  elems = $(div).find(\"> *\");\n  test.equal(elems.length, 0);\n  test.equal(canonicalizeHtml(div.innerHTML), 'asdf');\n\n  R.set('<span class=\"hi\">blah</span>');\n  Tracker.flush();\n  elems = $(div).find(\"> *\");\n  test.equal(elems.length, 1);\n  test.equal(elems[0].nodeName, 'SPAN');\n  span = elems[0];\n  test.equal(span.className, 'hi');\n  test.equal(canonicalizeHtml(span.innerHTML), 'blah');\n\n  var tmpl = Template.spacebars_template_test_triple2;\n  tmpl.helpers({\n    html: function () {},\n    html2: function () { return null; }\n  });\n  // no tmpl.html3\n  div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'xy');\n});\n\nTinytest.add(\"spacebars-tests - template_tests - inclusion args\", function (test) {\n  var tmpl = Template.spacebars_template_test_inclusion_args;\n\n  var R = ReactiveVar(Template.spacebars_template_test_aaa);\n  tmpl.helpers({foo: function () { return R.get(); }});\n\n  var div = renderToDiv(tmpl);\n  // `{{> foo bar}}`, with `foo` resolving to Template.aaa,\n  // which consists of \"aaa\"\n  test.equal(canonicalizeHtml(div.innerHTML), 'aaa');\n  R.set(Template.spacebars_template_test_bbb);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'bbb');\n\n  ////// Ok, now `foo` *is* Template.aaa\n  tmpl.helpers({foo: Template.spacebars_template_test_aaa});\n  div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'aaa');\n\n  ////// Ok, now `foo` is a template that takes an argument; bar is a string.\n  tmpl.helpers({\n    foo: Template.spacebars_template_test_bracketed_this,\n    bar: 'david'\n  });\n  div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), '[david]');\n\n  ////// Now `foo` is a template that takes an arg; bar is a function.\n  tmpl.helpers({foo: Template.spacebars_template_test_span_this});\n  R = ReactiveVar('david');\n  tmpl.helpers({bar: function () { return R.get(); }});\n  div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>david</span>');\n  var span1 = div.querySelector('span');\n  R.set('avi');\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>avi</span>');\n  var span2 = div.querySelector('span');\n  test.isTrue(span1 === span2);\n});\n\nTinytest.add(\"spacebars-tests - template_tests - inclusion args 2\", function (test) {\n  // `{{> foo bar q=baz}}`\n  var tmpl = Template.spacebars_template_test_inclusion_args2;\n\n  tmpl.helpers({\n    foo: Template.spacebars_template_test_span_this,\n    bar: function (options) {\n      return options.hash.q;\n    }\n  });\n\n  var R = ReactiveVar('david!');\n  tmpl.helpers({ baz: function () { return R.get().slice(0,5); } });\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>david</span>');\n  var span1 = div.querySelector('span');\n  R.set('brillo');\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>brill</span>');\n  var span2 = div.querySelector('span');\n  test.isTrue(span1 === span2);\n});\n\nTinytest.add(\"spacebars-tests - template_tests - inclusion dotted args\", function (test) {\n  // `{{> foo bar.baz}}`\n  var tmpl = Template.spacebars_template_test_inclusion_dotted_args;\n\n  var initCount = 0;\n  tmpl.helpers({\n    foo: extendTemplateWithInit(\n      Template.spacebars_template_test_bracketed_this,\n      function () { initCount++; })\n  });\n\n  var R = ReactiveVar('david');\n  tmpl.helpers({\n    bar: function () {\n      // make sure `this` is bound correctly\n      return { baz: this.symbol + R.get() };\n    }\n  });\n\n  var div = renderToDiv(tmpl, {symbol:'%'});\n  test.equal(initCount, 1);\n  test.equal(canonicalizeHtml(div.innerHTML), '[%david]');\n\n  R.set('avi');\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), '[%avi]');\n  // check that invalidating the argument to `foo` doesn't require\n  // creating a new `foo`.\n  test.equal(initCount, 1);\n});\n\nTinytest.add(\"spacebars-tests - template_tests - inclusion slashed args\", function (test) {\n  // `{{> foo bar/baz}}`\n  var tmpl = Template.spacebars_template_test_inclusion_dotted_args;\n\n  var initCount = 0;\n  tmpl.helpers({foo: extendTemplateWithInit(\n    Template.spacebars_template_test_bracketed_this,\n    function () { initCount++; }) });\n  var R = ReactiveVar('david');\n  tmpl.helpers({bar: function () {\n    // make sure `this` is bound correctly\n    return { baz: this.symbol + R.get() };\n  }});\n\n  var div = renderToDiv(tmpl, {symbol:'%'});\n  test.equal(initCount, 1);\n  test.equal(canonicalizeHtml(div.innerHTML), '[%david]');\n});\n\nTinytest.add(\"spacebars-tests - template_tests - block helper\", function (test) {\n  // test the case where `foo` is a calculated template that changes\n  // reactively.\n  // `{{#foo}}bar{{else}}baz{{/foo}}`\n  var tmpl = Template.spacebars_template_test_block_helper;\n  var R = ReactiveVar(Template.spacebars_template_test_content);\n  tmpl.helpers({foo: function () {\n    return R.get();\n  }});\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"bar\");\n\n  R.set(Template.spacebars_template_test_elsecontent);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"baz\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - block helper function with one string arg\", function (test) {\n  // `{{#foo \"bar\"}}content{{/foo}}`\n  var tmpl = Template.spacebars_template_test_block_helper_function_one_string_arg;\n  tmpl.helpers({foo: function () {\n    if (String(this) === \"bar\")\n      return Template.spacebars_template_test_content;\n    else\n      return null;\n  }});\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"content\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - block helper function with one helper arg\", function (test) {\n  var tmpl = Template.spacebars_template_test_block_helper_function_one_helper_arg;\n  var R = ReactiveVar(\"bar\");\n  tmpl.helpers({\n    bar: function () { return R.get(); },\n    foo: function () {\n      if (String(this) === \"bar\")\n        return Template.spacebars_template_test_content;\n      else\n        return null;\n    }\n  });\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"content\");\n\n  R.set(\"baz\");\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - block helper component with one helper arg\", function (test) {\n  var tmpl = Template.spacebars_template_test_block_helper_component_one_helper_arg;\n  var R = ReactiveVar(true);\n  tmpl.helpers({bar: function () { return R.get(); }});\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"content\");\n\n  R.set(false);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - block helper component with three helper args\", function (test) {\n  var tmpl = Template.spacebars_template_test_block_helper_component_three_helper_args;\n  var R = ReactiveVar(\"bar\");\n  tmpl.helpers({\n    bar_or_baz: function () {\n      return R.get();\n    },\n    equals: function (x, y) {\n      return x === y;\n    }\n  });\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"content\");\n\n  R.set(\"baz\");\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - block helper with dotted arg\", function (test) {\n  var tmpl = Template.spacebars_template_test_block_helper_dotted_arg;\n  var R1 = ReactiveVar(1);\n  var R2 = ReactiveVar(10);\n  var R3 = ReactiveVar(100);\n\n  var initCount = 0;\n  tmpl.helpers({\n    foo: extendTemplateWithInit(\n      Template.spacebars_template_test_bracketed_this,\n      function () { initCount++; }),\n\n    bar: function () {\n      return {\n        r1: R1.get(),\n        baz: function (r3) {\n          return this.r1 + R2.get() + r3;\n        }\n      };\n    },\n    qux: function () { return R3.get(); }\n  });\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"[111]\");\n  test.equal(initCount, 1);\n\n  R1.set(2);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"[112]\");\n  test.equal(initCount, 1);\n\n  R2.set(20);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"[122]\");\n  test.equal(initCount, 1);\n\n  R3.set(200);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"[222]\");\n  test.equal(initCount, 1);\n\n  R2.set(30);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"[232]\");\n  test.equal(initCount, 1);\n\n  R1.set(3);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"[233]\");\n  test.equal(initCount, 1);\n\n  R3.set(300);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"[333]\");\n  test.equal(initCount, 1);\n});\n\nTinytest.add(\"spacebars-tests - template_tests - nested content\", function (test) {\n  // Test that `{{> Template.contentBlock}}` in an `{{#if}}` works.\n\n  // ```\n  // <template name=\"spacebars_template_test_iftemplate\">\n  //   {{#if condition}}\n  //     {{> Template.contentBlock}}\n  //   {{else}}\n  //     {{> Template.elseBlock}}\n  //   {{/if}}\n  // </template>\n  // ```\n\n  // ```\n  //  {{#spacebars_template_test_iftemplate flag}}\n  //    hello\n  //  {{else}}\n  //    world\n  //  {{/spacebars_template_test_iftemplate}}\n  // ```\n\n  var tmpl = Template.spacebars_template_test_nested_content;\n  var R = ReactiveVar(true);\n  tmpl.helpers({\n    flag: function () {\n      return R.get();\n    }\n  });\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'hello');\n  R.set(false);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'world');\n  R.set(true);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'hello');\n\n  // Also test that `{{> Template.contentBlock}}` in a custom block helper works.\n  tmpl = Template.spacebars_template_test_nested_content2;\n  R = ReactiveVar(true);\n  tmpl.helpers({\n    x: function () {\n      return R.get();\n    }\n  });\n  div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'hello');\n  R.set(false);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'world');\n  R.set(true);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'hello');\n});\n\nTinytest.add(\"spacebars-tests - template_tests - if\", function (test) {\n  var tmpl = Template.spacebars_template_test_if;\n  var R = ReactiveVar(true);\n  tmpl.helpers({\n    foo: function () {\n      return R.get();\n    },\n    bar: 1,\n    baz: 2\n  });\n\n  var div = renderToDiv(tmpl);\n  var rendersTo = function (html) { divRendersTo(test, div, html); };\n\n  rendersTo(\"1\");\n  R.set(false);\n  rendersTo(\"2\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - if in with\", function (test) {\n  var tmpl = Template.spacebars_template_test_if_in_with;\n  tmpl.helpers({foo: {bar: \"bar\"}});\n\n  var div = renderToDiv(tmpl);\n  divRendersTo(test, div, \"bar bar\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - each on cursor\", function (test) {\n  var tmpl = Template.spacebars_template_test_each;\n  var coll = new Mongo.Collection(null);\n  tmpl.helpers({\n    items: function () {\n      return coll.find({}, {sort: {pos: 1}});\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n  var rendersTo = function (html) { divRendersTo(test, div, html); };\n\n  rendersTo(\"else-clause\");\n  coll.insert({text: \"one\", pos: 1});\n  rendersTo(\"one\");\n  coll.insert({text: \"two\", pos: 2});\n  rendersTo(\"one two\");\n  coll.update({text: \"two\"}, {$set: {text: \"three\"}});\n  rendersTo(\"one three\");\n  coll.update({text: \"three\"}, {$set: {pos: 0}});\n  rendersTo(\"three one\");\n  coll.remove({});\n  rendersTo(\"else-clause\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - each on array\", function (test) {\n  var tmpl = Template.spacebars_template_test_each;\n  var R = new ReactiveVar([]);\n  tmpl.helpers({\n    items: function () {\n      return R.get();\n    },\n    text: function () {\n      return this;\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n  var rendersTo = function (html) { divRendersTo(test, div, html); };\n\n  rendersTo(\"else-clause\");\n  R.set([\"\"]);\n  rendersTo(\"\");\n  R.set([\"x\", \"\", \"toString\"]);\n  rendersTo(\"x toString\");\n  R.set([\"toString\"]);\n  rendersTo(\"toString\");\n  R.set([]);\n  rendersTo(\"else-clause\");\n  R.set([0, 1, 2]);\n  rendersTo(\"0 1 2\");\n  R.set([]);\n  rendersTo(\"else-clause\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - ..\", function (test) {\n  var tmpl = Template.spacebars_template_test_dots;\n\n  Template.spacebars_template_test_dots_subtemplate.helpers({\n    getTitle: function (from) {\n      return from.title;\n    }\n  });\n\n  tmpl.helpers({\n    foo: {\n      title: \"foo\",\n      bar: {title: \"bar\",\n            items: [{title: \"item\"}]}\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n\n  test.equal(canonicalizeHtml(div.innerHTML), [\n    \"A\", \"B\", \"C\", \"D\",\n    // {{> spacebars_template_test_dots_subtemplate}}\n    \"TITLE\", \"1item\", \"2item\", \"3bar\", \"4foo\", \"GETTITLE\", \"5item\", \"6bar\", \"7foo\",\n    // {{> spacebars_template_test_dots_subtemplate ..}}\n    \"TITLE\", \"1bar\", \"2bar\", \"3item\", \"4bar\", \"GETTITLE\", \"5bar\", \"6item\", \"7bar\"].join(\" \"));\n});\n\nTinytest.add(\"spacebars-tests - template_tests - select tags\", function (test) {\n  var tmpl = Template.spacebars_template_test_select_tag;\n\n  // {label: (string)}\n  var optgroups = new Mongo.Collection(null);\n\n  // {optgroup: (id), value: (string), selected: (boolean), label: (string)}\n  var options = new Mongo.Collection(null);\n\n  tmpl.helpers({\n    optgroups: function () { return optgroups.find(); },\n    options: function () { return options.find({optgroup: this._id}); },\n    selectedAttr: function () { return this.selected ? {selected: true} : {}; }\n  });\n\n  var div = renderToDiv(tmpl);\n  var selectEl = $(div).find('select')[0];\n\n  // returns canonicalized contents of `div` in the form eg\n  // [\"<select>\", \"</select>\"]. strip out selected attributes -- we\n  // verify correctness by observing the `selected` property\n  var divContent = function () {\n    return canonicalizeHtml(\n      div.innerHTML.replace(/selected=\"[^\"]*\"/g, '').replace(/selected/g, ''))\n          .replace(/\\>\\s*\\</g, '>\\n<')\n          .split('\\n');\n  };\n\n  test.equal(divContent(), [\"<select>\", \"</select>\"]);\n\n  var optgroup1 = optgroups.insert({label: \"one\"});\n  var optgroup2 = optgroups.insert({label: \"two\"});\n  test.equal(divContent(), [\n    '<select>',\n    '<optgroup label=\"one\">',\n    '</optgroup>',\n    '<optgroup label=\"two\">',\n    '</optgroup>',\n    '</select>'\n  ]);\n\n  options.insert({optgroup: optgroup1, value: \"value1\", selected: false, label: \"label1\"});\n  options.insert({optgroup: optgroup1, value: \"value2\", selected: true, label: \"label2\"});\n  test.equal(divContent(), [\n    '<select>',\n    '<optgroup label=\"one\">',\n    '<option value=\"value1\">label1</option>',\n    '<option value=\"value2\">label2</option>',\n    '</optgroup>',\n    '<optgroup label=\"two\">',\n    '</optgroup>',\n    '</select>'\n  ]);\n  test.equal(selectEl.value, \"value2\");\n  test.equal($(selectEl).find('option')[0].selected, false);\n  test.equal($(selectEl).find('option')[1].selected, true);\n\n  // swap selection\n  options.update({value: \"value1\"}, {$set: {selected: true}});\n  options.update({value: \"value2\"}, {$set: {selected: false}});\n  Tracker.flush();\n\n  test.equal(divContent(), [\n    '<select>',\n    '<optgroup label=\"one\">',\n    '<option value=\"value1\">label1</option>',\n    '<option value=\"value2\">label2</option>',\n    '</optgroup>',\n    '<optgroup label=\"two\">',\n    '</optgroup>',\n    '</select>'\n  ]);\n  test.equal(selectEl.value, \"value1\");\n  test.equal($(selectEl).find('option')[0].selected, true);\n  test.equal($(selectEl).find('option')[1].selected, false);\n\n  // change value and label\n  options.update({value: \"value1\"}, {$set: {value: \"value1.0\"}});\n  options.update({value: \"value2\"}, {$set: {label: \"label2.0\"}});\n  Tracker.flush();\n\n  test.equal(divContent(), [\n    '<select>',\n    '<optgroup label=\"one\">',\n    '<option value=\"value1.0\">label1</option>',\n    '<option value=\"value2\">label2.0</option>',\n    '</optgroup>',\n    '<optgroup label=\"two\">',\n    '</optgroup>',\n    '</select>'\n  ]);\n  test.equal(selectEl.value, \"value1.0\");\n  test.equal($(selectEl).find('option')[0].selected, true);\n  test.equal($(selectEl).find('option')[1].selected, false);\n\n  // unselect and then select both options. normally, the second is\n  // selected (since it got selected later). then switch to <select\n  // multiple=\"\">. both should be selected.\n  options.update({}, {$set: {selected: false}}, {multi: true});\n  Tracker.flush();\n  options.update({}, {$set: {selected: true}}, {multi: true});\n  Tracker.flush();\n  test.equal($(selectEl).find('option')[0].selected, false);\n  test.equal($(selectEl).find('option')[1].selected, true);\n\n  selectEl.multiple = true; // allow multiple selection\n  options.update({}, {$set: {selected: false}}, {multi: true});\n  Tracker.flush();\n  options.update({}, {$set: {selected: true}}, {multi: true});\n  Tracker.flush();\n  test.equal($(selectEl).find('option')[0].selected, true);\n  test.equal($(selectEl).find('option')[1].selected, true);\n});\n\nTinytest.add('spacebars-tests - template_tests - {{#with}} falsy; issue #770', function (test) {\n  Template.test_template_issue770.helpers({\n    value1: function () { return \"abc\"; },\n    value2: function () { return false; }\n  });\n  var div = renderToDiv(Template.test_template_issue770);\n  test.equal(canonicalizeHtml(div.innerHTML),\n             \"abc xxx abc\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - tricky attrs\", function (test) {\n  var tmpl = Template.spacebars_template_test_tricky_attrs;\n  var R = ReactiveVar('foo');\n  tmpl.helpers({\n    theType: function () { return 'text'; },\n    theClass: function () { return R.get(); }\n  });\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML).slice(0, 30),\n             '<input type=\"text\"><input class=\"foo\" type=\"checkbox\">'.slice(0, 30));\n\n  R.set('bar');\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML),\n             '<input type=\"text\"><input class=\"bar\" type=\"checkbox\">');\n\n});\n\nTinytest.add('spacebars-tests - template_tests - no data context', function (test) {\n  var tmpl = Template.spacebars_template_test_no_data;\n\n  // failure is if an exception is thrown here\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'asdf');\n});\n\nTinytest.add('spacebars-tests - template_tests - textarea', function (test) {\n  var tmpl = Template.spacebars_template_test_textarea;\n\n  var R = ReactiveVar('hello');\n\n  tmpl.helpers({foo: function () {\n    return R.get();\n  }});\n\n  var div = renderToDiv(tmpl);\n  var textarea = div.querySelector('textarea');\n  test.equal(textarea.value, 'hello');\n\n  R.set('world');\n  Tracker.flush();\n  test.equal(textarea.value, 'world');\n\n});\n\nTinytest.add('spacebars-tests - template_tests - textarea 2', function (test) {\n  var tmpl = Template.spacebars_template_test_textarea2;\n\n  var R = ReactiveVar(true);\n\n  tmpl.helpers({foo: function () {\n    return R.get();\n  }});\n\n  var div = renderToDiv(tmpl);\n  var textarea = div.querySelector('textarea');\n  test.equal(textarea.value, '</not a tag>');\n\n  R.set(false);\n  Tracker.flush();\n  test.equal(textarea.value, '<also not a tag>');\n\n  R.set(true);\n  Tracker.flush();\n  test.equal(textarea.value, '</not a tag>');\n});\n\nTinytest.add('spacebars-tests - template_tests - textarea 3', function (test) {\n  var tmpl = Template.spacebars_template_test_textarea3;\n\n  var R = ReactiveVar('hello');\n\n  tmpl.helpers({foo: function () {\n    return R.get();\n  }});\n\n  var div = renderToDiv(tmpl);\n  var textarea = div.querySelector('textarea');\n  test.equal(textarea.id, 'myTextarea');\n  test.equal(textarea.value, 'hello');\n\n  R.set('world');\n  Tracker.flush();\n  test.equal(textarea.value, 'world');\n\n});\n\nTinytest.add('spacebars-tests - template_tests - textarea each', function (test) {\n  var tmpl = Template.spacebars_template_test_textarea_each;\n\n  var R = ReactiveVar(['APPLE', 'BANANA']);\n\n  tmpl.helpers({foo: function () {\n    return R.get();\n  }});\n\n  var div = renderToDiv(tmpl);\n  var textarea = div.querySelector('textarea');\n  test.equal(textarea.value, '<not a tag APPLE <not a tag BANANA ');\n\n  R.set([]);\n  Tracker.flush();\n  test.equal(textarea.value, '<>');\n\n  R.set(['CUCUMBER']);\n  Tracker.flush();\n  test.equal(textarea.value, '<not a tag CUCUMBER ');\n\n});\n\n// Ensure that one can call `Meteor.defer` within a rendered callback\n// triggered by a document insertion that happend in a method stub.\n//\n// Why do we have this test? Because you generally can't call\n// `Meteor.defer` inside a method stub (see\n// packages/meteor/timers.js).  This test verifies that rendered\n// callbacks don't fire synchronously as part of a method stub.\ntestAsyncMulti('spacebars-tests - template_tests - defer in rendered callbacks', [function (test, expect) {\n  var tmpl = Template.spacebars_template_test_defer_in_rendered;\n  var coll = new Mongo.Collection(null);\n\n  Meteor.methods({\n    spacebarsTestInsertEmptyObject: function () {\n      // cause a new instance of `subtmpl` to be placed in the\n      // DOM. verify that it's not fired directly within a method\n      // stub, in which `Meteor.defer` is not allowed.\n      coll.insert({});\n    }\n  });\n\n  tmpl.helpers({\n    items: function () {\n      return coll.find();\n    }\n  });\n\n  var subtmpl = Template.spacebars_template_test_defer_in_rendered_subtemplate;\n\n  subtmpl.rendered = expect(function () {\n    // will throw if called in a method stub\n    Meteor.defer(function () {});\n  });\n\n  var div = renderToDiv(tmpl);\n\n  // not defined on the server, but it's fine since the stub does\n  // the relevant work\n  Meteor._suppress_log(1);\n  Meteor.call(\"spacebarsTestInsertEmptyObject\");\n}]);\n\ntestAsyncMulti('spacebars-tests - template_tests - rendered template is DOM in rendered callbacks', [\n  function (test, expect) {\n    var tmpl = Template.spacebars_template_test_aaa;\n    tmpl.rendered = expect(function () {\n      test.equal(canonicalizeHtml(div.innerHTML), \"aaa\");\n    });\n    var div = renderToDiv(tmpl);\n    Tracker.flush();\n  }\n]);\n\n// Test that in:\n//\n// ```\n// {{#with someData}}\n//   {{foo}} {{bar}}\n// {{/with}}\n// ```\n//\n// ... we run `someData` once even if `foo` re-renders.\nTinytest.add('spacebars-tests - template_tests - with someData', function (test) {\n  var tmpl = Template.spacebars_template_test_with_someData;\n\n  var foo = ReactiveVar('AAA');\n  var someDataRuns = 0;\n\n  tmpl.helpers({\n    someData: function () {\n      someDataRuns++;\n      return {};\n    },\n    foo: function () {\n      return foo.get();\n    },\n    bar: function () {\n      return 'YO';\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n\n  test.equal(someDataRuns, 1);\n  test.equal(canonicalizeHtml(div.innerHTML), 'AAA YO');\n\n  foo.set('BBB');\n  Tracker.flush();\n  test.equal(someDataRuns, 1);\n  test.equal(canonicalizeHtml(div.innerHTML), 'BBB YO');\n\n  foo.set('CCC');\n  Tracker.flush();\n  test.equal(someDataRuns, 1);\n  test.equal(canonicalizeHtml(div.innerHTML), 'CCC YO');\n});\n\nTinytest.add('spacebars-tests - template_tests - #each stops when rendered element is removed', function (test) {\n  var tmpl = Template.spacebars_template_test_each_stops;\n  var coll = new Mongo.Collection(null);\n  coll.insert({});\n  tmpl.helpers({items: function () { return coll.find(); }});\n\n  var div = renderToDiv(tmpl);\n  divRendersTo(test, div, 'x');\n\n  // trigger #each component destroyed\n  $(div).remove();\n\n  // insert another document. cursor should no longer be observed so\n  // should have no effect.\n  coll.insert({});\n  divRendersTo(test, div, 'x');\n});\n\nTinytest.add('spacebars-tests - template_tests - block helpers in attribute', function (test) {\n  var tmpl = Template.spacebars_template_test_block_helpers_in_attribute;\n\n  var coll = new Mongo.Collection(null);\n  tmpl.helpers({\n    classes: function () {\n    return coll.find({}, {sort: {name: 1}});\n    },\n    startsLowerCase: function (name) {\n      return /^[a-z]/.test(name);\n    }\n  });\n  coll.insert({name: 'David'});\n  coll.insert({name: 'noodle'});\n  coll.insert({name: 'donut'});\n  coll.insert({name: 'frankfurter'});\n  coll.insert({name: 'Steve'});\n\n  var containerDiv = renderToDiv(tmpl);\n  var div = containerDiv.querySelector('div');\n\n  var shouldBe = function (className) {\n    Tracker.flush();\n    test.equal(div.innerHTML, \"Smurf\");\n    test.equal(div.className, className);\n    var result = canonicalizeHtml(containerDiv.innerHTML);\n    if (result === '<div>Smurf</div>')\n      result = '<div class=\"\">Smurf</div>'; // e.g. IE 9 and 10\n    test.equal(result, '<div class=\"' + className + '\">Smurf</div>');\n  };\n\n  shouldBe('donut frankfurter noodle');\n  coll.remove({name: 'frankfurter'}); // (it was kind of a mouthful)\n  shouldBe('donut noodle');\n  coll.remove({name: 'donut'});\n  shouldBe('noodle');\n  coll.remove({name: 'noodle'});\n  shouldBe(''); // 'David' and 'Steve' appear in the #each but fail the #if\n  coll.remove({});\n  shouldBe('none'); // now the `{{else}}` case kicks in\n  coll.insert({name: 'bubblegum'});\n  shouldBe('bubblegum');\n});\n\nTinytest.add('spacebars-tests - template_tests - block helpers in attribute 2', function (test) {\n  var tmpl = Template.spacebars_template_test_block_helpers_in_attribute_2;\n\n  var R = ReactiveVar(true);\n\n  tmpl.helpers({foo: function () { return R.get(); }});\n\n  var div = renderToDiv(tmpl);\n  var input = div.querySelector('input');\n\n  test.equal(input.value, '\"');\n  R.set(false);\n  Tracker.flush();\n  test.equal(input.value, '&<></x>');\n});\n\n\n// Test that if the argument to #each is a constant, it doesn't establish a\n// dependency on the data context, so when the context changes, items of\n// the #each are not \"changed\" and helpers do not rerun.\nTinytest.add('spacebars-tests - template_tests - constant #each argument', function (test) {\n  var tmpl = Template.spacebars_template_test_constant_each_argument;\n\n  var justReturnRuns = 0; // how many times `justReturn` is called\n  var R = ReactiveVar(1);\n\n  tmpl.helpers({\n    someData: function () {\n      return R.get();\n    },\n    anArray: ['foo', 'bar'],\n    justReturn: function (x) {\n      justReturnRuns++;\n      return String(x);\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n\n  test.equal(justReturnRuns, 2);\n  test.equal(canonicalizeHtml(div.innerHTML).replace(/\\s+/g, ' '),\n             'foo bar 1');\n\n  R.set(2);\n  Tracker.flush();\n\n  test.equal(justReturnRuns, 2); // still 2, no new runs!\n  test.equal(canonicalizeHtml(div.innerHTML).replace(/\\s+/g, ' '),\n             'foo bar 2');\n});\n\nTinytest.addAsync('spacebars-tests - template_tests - #markdown - basic', function (test, onComplete) {\n  var tmpl = Template.spacebars_template_test_markdown_basic;\n  tmpl.helpers({\n    obj: {snippet: \"<i>hi</i>\"},\n    hi: function () {\n      return this.snippet;\n    }\n  });\n  var div = renderToDiv(tmpl);\n\n  Meteor.call(\"getAsset\", \"markdown_basic.html\", function (err, html) {\n    test.isFalse(err);\n    test.equal(canonicalizeHtml(div.innerHTML),\n               canonicalizeHtml(html));\n    onComplete();\n  });\n});\n\ntestAsyncMulti('spacebars-tests - template_tests - #markdown - if', [\n  function (test, expect) {\n    var self = this;\n    Meteor.call(\"getAsset\", \"markdown_if1.html\", expect(function (err, html) {\n      test.isFalse(err);\n      self.html1 = html;\n    }));\n    Meteor.call(\"getAsset\", \"markdown_if2.html\", expect(function (err, html) {\n      test.isFalse(err);\n      self.html2 = html;\n    }));\n  },\n\n  function (test, expect) {\n    var self = this;\n    var tmpl = Template.spacebars_template_test_markdown_if;\n    var R = new ReactiveVar(false);\n    tmpl.helpers({cond: function () { return R.get(); }});\n\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), canonicalizeHtml(self.html1));\n    R.set(true);\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), canonicalizeHtml(self.html2));\n  }\n]);\n\ntestAsyncMulti('spacebars-tests - template_tests - #markdown - each', [\n  function (test, expect) {\n    var self = this;\n    Meteor.call(\"getAsset\", \"markdown_each1.html\", expect(function (err, html) {\n      test.isFalse(err);\n      self.html1 = html;\n    }));\n    Meteor.call(\"getAsset\", \"markdown_each2.html\", expect(function (err, html) {\n      test.isFalse(err);\n      self.html2 = html;\n    }));\n  },\n\n  function (test, expect) {\n    var self = this;\n    var tmpl = Template.spacebars_template_test_markdown_each;\n    var R = new ReactiveVar([]);\n    tmpl.helpers({seq: function () { return R.get(); }});\n\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), canonicalizeHtml(self.html1));\n\n    R.set([\"item\"]);\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), canonicalizeHtml(self.html2));\n  }\n]);\n\nTinytest.add('spacebars-tests - template_tests - #markdown - inclusion', function (test) {\n  var tmpl = Template.spacebars_template_test_markdown_inclusion;\n  var subtmpl = Template.spacebars_template_test_markdown_inclusion_subtmpl;\n  subtmpl.helpers({foo: \"bar\"});\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"<p><span>Foo is bar.</span></p>\");\n});\n\nTinytest.add('spacebars-tests - template_tests - #markdown - block helpers', function (test) {\n  var tmpl = Template.spacebars_template_test_markdown_block_helpers;\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"<p>Hi there!</p>\");\n});\n\n// Test that when a simple helper re-runs due to a dependency changing\n// but the return value is the same, the DOM text node is not\n// re-rendered.\nTinytest.add('spacebars-tests - template_tests - simple helpers are isolated', function (test) {\n  var runs = [{\n    helper: function () { return \"foo\"; },\n    nodeValue: \"foo\"\n  }, {\n    helper: function () { return new Spacebars.SafeString(\"bar\"); },\n    nodeValue: \"bar\"\n  }];\n\n  _.each(runs, function (run) {\n    var tmpl = Template.spacebars_template_test_simple_helpers_are_isolated;\n    var dep = new Tracker.Dependency;\n    tmpl.helpers({foo: function () {\n      dep.depend();\n      return run.helper();\n    }});\n    var div = renderToDiv(tmpl);\n    var fooTextNode = _.find(div.childNodes, function (node) {\n      return node.nodeValue === run.nodeValue;\n    });\n\n    test.isTrue(fooTextNode);\n\n    dep.changed();\n    Tracker.flush();\n    var newFooTextNode = _.find(div.childNodes, function (node) {\n      return node.nodeValue === run.nodeValue;\n    });\n\n    test.equal(fooTextNode, newFooTextNode);\n  });\n});\n\n// Test that when a helper in an element attribute re-runs due to a\n// dependency changing but the return value is the same, the attribute\n// value is not set.\nTinytest.add('spacebars-tests - template_tests - attribute helpers are isolated', function (test) {\n  var tmpl = Template.spacebars_template_test_attr_helpers_are_isolated;\n  var dep = new Tracker.Dependency;\n  tmpl.helpers({foo: function () {\n    dep.depend();\n    return \"foo\";\n  }});\n  var div = renderToDiv(tmpl);\n  var pElement = div.querySelector('p');\n\n  test.equal(pElement.getAttribute('attr'), 'foo');\n\n  // set the attribute to something else, afterwards check that it\n  // hasn't been updated back to the correct value.\n  pElement.setAttribute('attr', 'not-foo');\n  dep.changed();\n  Tracker.flush();\n  test.equal(pElement.getAttribute('attr'), 'not-foo');\n});\n\n// A helper can return an object with a set of element attributes via\n// `<p {{attrs}}>`. When it re-runs due to a dependency changing the\n// value for a given attribute might stay the same. Test that the\n// attribute is not set on the DOM element.\nTinytest.add('spacebars-tests - template_tests - attribute object helpers are isolated', function (test) {\n  var tmpl = Template.spacebars_template_test_attr_object_helpers_are_isolated;\n  var dep = new Tracker.Dependency;\n  tmpl.helpers({attrs: function () {\n    dep.depend();\n    return {foo: \"bar\"};\n  }});\n  var div = renderToDiv(tmpl);\n  var pElement = div.querySelector('p');\n\n  test.equal(pElement.getAttribute('foo'), 'bar');\n\n  // set the attribute to something else, afterwards check that it\n  // hasn't been updated back to the correct value.\n  pElement.setAttribute('foo', 'not-bar');\n  dep.changed();\n  Tracker.flush();\n  test.equal(pElement.getAttribute('foo'), 'not-bar');\n});\n\n// Test that when a helper in an inclusion directive (`{{> foo }}`)\n// re-runs due to a dependency changing but the return value is the\n// same, the template is not re-rendered.\n//\n// Also, verify that an error is thrown if the return value from such\n// a helper is not a component.\nTinytest.add('spacebars-tests - template_tests - inclusion helpers are isolated', function (test) {\n  var tmpl = Template.spacebars_template_test_inclusion_helpers_are_isolated;\n  var dep = new Tracker.Dependency;\n  var subtmpl = Template.spacebars_template_test_inclusion_helpers_are_isolated_subtemplate;\n  // make a copy so we can set \"rendered\" without mutating the original\n  var subtmplCopy = copyTemplate(subtmpl);\n\n  var R = new ReactiveVar(subtmplCopy);\n  tmpl.helpers({foo: function () {\n    dep.depend();\n    return R.get();\n  }});\n\n  var div = renderToDiv(tmpl);\n  subtmplCopy.rendered = function () {\n    test.fail(\"shouldn't re-render when same value returned from helper\");\n  };\n  subtmplCopy.onRendered(function () {\n    test.fail(\"shouldn't re-render when same value returned from helper\");\n  });\n\n  dep.changed();\n  Tracker.flush({_throwFirstError: true}); // `subtmplCopy.rendered` not called\n\n  R.set(null);\n  Tracker.flush({_throwFirstError: true}); // no error thrown\n\n  R.set(\"neither a component nor null\");\n\n  test.throws(function () {\n    Tracker.flush({_throwFirstError: true});\n  }, /Expected template or null/);\n});\n\nTinytest.add('spacebars-tests - template_tests - nully attributes', function (test) {\n  var tmpls = {\n    0: Template.spacebars_template_test_nully_attributes0,\n    1: Template.spacebars_template_test_nully_attributes1,\n    2: Template.spacebars_template_test_nully_attributes2,\n    3: Template.spacebars_template_test_nully_attributes3,\n    4: Template.spacebars_template_test_nully_attributes4,\n    5: Template.spacebars_template_test_nully_attributes5,\n    6: Template.spacebars_template_test_nully_attributes6\n  };\n\n  var run = function (whichTemplate, data, expectTrue) {\n    var div = renderToDiv(tmpls[whichTemplate], data);\n    var input = div.querySelector('input');\n    var descr = JSON.stringify([whichTemplate, data, expectTrue]);\n    if (expectTrue) {\n      test.isTrue(input.checked, descr);\n      test.equal(typeof input.getAttribute('stuff'), 'string', descr);\n    } else {\n      test.isFalse(input.checked);\n      test.equal(JSON.stringify(input.getAttribute('stuff')), 'null', descr);\n    }\n\n    var html = Blaze.toHTML(Blaze.With(data, function () {\n      return tmpls[whichTemplate];\n    }));\n\n    test.equal(/ checked=\"[^\"]*\"/.test(html), !! expectTrue);\n    test.equal(/ stuff=\"[^\"]*\"/.test(html), !! expectTrue);\n  };\n\n  run(0, {}, true);\n\n  var truthies = [true, ''];\n  var falsies = [false, null, undefined];\n\n  _.each(truthies, function (x) {\n    run(1, {foo: x}, true);\n  });\n  _.each(falsies, function (x) {\n    run(1, {foo: x}, false);\n  });\n\n  _.each(truthies, function (x) {\n    _.each(truthies, function (y) {\n      run(2, {foo: x, bar: y}, true);\n    });\n    _.each(falsies, function (y) {\n      run(2, {foo: x, bar: y}, true);\n    });\n  });\n  _.each(falsies, function (x) {\n    _.each(truthies, function (y) {\n      run(2, {foo: x, bar: y}, true);\n    });\n    _.each(falsies, function (y) {\n      run(2, {foo: x, bar: y}, false);\n    });\n  });\n\n  run(3, {foo: true}, false);\n  run(3, {foo: false}, false);\n});\n\nTinytest.add(\"spacebars-tests - template_tests - double\", function (test) {\n  var tmpl = Template.spacebars_template_test_double;\n\n  var run = function (foo, expectedResult) {\n    tmpl.helpers({foo: foo});\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), expectedResult);\n  };\n\n  run('asdf', 'asdf');\n  run(1.23, '1.23');\n  run(0, '0');\n  run(true, 'true');\n  run(false, '');\n  run(null, '');\n  run(undefined, '');\n});\n\nTinytest.add(\"spacebars-tests - template_tests - inclusion lookup order\", function (test) {\n  // test that {{> foo}} looks for a helper named 'foo', then a\n  // template named 'foo', then a 'foo' field in the data context.\n  var tmpl = Template.spacebars_template_test_inclusion_lookup;\n  var tmplData = function () {\n    return {\n      // shouldn't have an effect since we define a helper with the\n      // same name.\n      spacebars_template_test_inclusion_lookup_subtmpl: Template.\n        spacebars_template_test_inclusion_lookup_subtmpl3,\n      dataContextSubtmpl: Template.\n        spacebars_template_test_inclusion_lookup_subtmpl3};\n  };\n\n  tmpl.helpers({\n    spacebars_template_test_inclusion_lookup_subtmpl:\n    Template.spacebars_template_test_inclusion_lookup_subtmpl2\n  });\n\n  test.equal(canonicalizeHtml(renderToDiv(tmpl, tmplData).innerHTML),\n    [\"This is generated by a helper with the same name.\",\n     \"This is a template passed in the data context.\"].join(' '));\n});\n\nTinytest.add(\"spacebars-tests - template_tests - content context\", function (test) {\n  var tmpl = Template.spacebars_template_test_content_context;\n  var R = ReactiveVar(true);\n  tmpl.helpers({foo: {\n    firstLetter: 'F',\n    secondLetter: 'O',\n    bar: {\n      cond: function () { return R.get(); },\n      firstLetter: 'B',\n      secondLetter: 'A'\n    }\n  }});\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'BO');\n  R.set(false);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'FA');\n});\n\n_.each(['textarea', 'text', 'password', 'submit', 'button',\n        'reset', 'select', 'hidden'], function (type) {\n  Tinytest.add(\"spacebars-tests - template_tests - controls - \" + type, function(test) {\n    var R = ReactiveVar({x:\"test\"});\n    var R2 = ReactiveVar(\"\");\n    var tmpl;\n\n    if (type === 'select') {\n      tmpl = Template.spacebars_test_control_select;\n      tmpl.helpers({\n        options: ['This is a test', 'This is a fridge',\n                  'This is a frog', 'This is a new frog', 'foobar',\n                  'This is a photograph', 'This is a monkey',\n                  'This is a donkey'],\n        selected: function () {\n          R2.get();  // Re-render when R2 is changed, even though it\n          // doesn't affect HTML.\n          return ('This is a ' + R.get().x) === this.toString();\n        }\n      });\n    } else if (type === 'textarea') {\n      tmpl = Template.spacebars_test_control_textarea;\n      tmpl.helpers({\n        value: function () {\n          R2.get();  // Re-render when R2 is changed, even though it\n          // doesn't affect HTML.\n          return 'This is a ' + R.get().x;\n        }\n      });\n    } else {\n      tmpl = Template.spacebars_test_control_input;\n      tmpl.helpers({\n        value: function () {\n          R2.get();  // Re-render when R2 is changed, even though it\n          // doesn't affect HTML.\n          return 'This is a ' + R.get().x;\n        },\n        type: type\n      });\n    }\n\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n    var canFocus = (type !== 'hidden');\n\n    // find first element child, ignoring any marker nodes\n    var input = div.firstChild;\n    while (input.nodeType !== 1)\n      input = input.nextSibling;\n\n    if (type === 'textarea' || type === 'select') {\n      test.equal(input.nodeName, type.toUpperCase());\n    } else {\n      test.equal(input.nodeName, 'INPUT');\n      test.equal(input.type, type);\n    }\n    test.equal(DomUtils.getElementValue(input), \"This is a test\");\n\n    // value updates reactively\n    R.set({x:\"fridge\"});\n    Tracker.flush();\n    test.equal(DomUtils.getElementValue(input), \"This is a fridge\");\n\n    if (canFocus) {\n      // ...if focused, it still updates but focus isn't lost.\n      focusElement(input);\n      DomUtils.setElementValue(input, \"something else\");\n      R.set({x:\"frog\"});\n\n      Tracker.flush();\n      test.equal(DomUtils.getElementValue(input), \"This is a frog\");\n      test.equal(document.activeElement, input);\n    }\n\n    // Setting a value (similar to user typing) should prevent value from being\n    // reverted if the div is re-rendered but the rendered value (ie, R) does\n    // not change.\n    DomUtils.setElementValue(input, \"foobar\");\n    R2.set(\"change\");\n    Tracker.flush();\n    test.equal(DomUtils.getElementValue(input), \"foobar\");\n\n    // ... but if the actual rendered value changes, that should take effect.\n    R.set({x:\"photograph\"});\n    Tracker.flush();\n    test.equal(DomUtils.getElementValue(input), \"This is a photograph\");\n\n    document.body.removeChild(div);\n  });\n});\n\nTinytest.add(\"spacebars-tests - template_tests - radio\", function(test) {\n  var R = ReactiveVar(\"\");\n  var R2 = ReactiveVar(\"\");\n  var change_buf = [];\n  var tmpl = Template.spacebars_test_control_radio;\n  tmpl.helpers({\n    bands: [\"AM\", \"FM\", \"XM\"],\n    isChecked: function () {\n      return R.get() === this.toString();\n    },\n    band: function () {\n      return R.get();\n    }\n  });\n  tmpl.events({\n    'change input': function (event) {\n      var btn = event.target;\n      var band = btn.value;\n      change_buf.push(band);\n      R.set(band);\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n  document.body.appendChild(div);\n\n  // get the three buttons; they should not change identities!\n  var btns = nodesToArray(div.getElementsByTagName(\"INPUT\"));\n  var text = function () {\n    var text = div.innerText || div.textContent;\n    return text.replace(/[ \\n\\r]+/g, \" \");\n  };\n\n  test.equal(_.pluck(btns, 'checked'), [false, false, false]);\n  test.equal(text(), \"Band: \");\n\n  clickIt(btns[0]);\n  test.equal(change_buf, ['AM']);\n  change_buf.length = 0;\n  Tracker.flush();\n  test.equal(_.pluck(btns, 'checked'), [true, false, false]);\n  test.equal(text(), \"Band: AM\");\n\n  R2.set(\"change\");\n  Tracker.flush();\n  test.length(change_buf, 0);\n  test.equal(_.pluck(btns, 'checked'), [true, false, false]);\n  test.equal(text(), \"Band: AM\");\n\n  clickIt(btns[1]);\n  test.equal(change_buf, ['FM']);\n  change_buf.length = 0;\n  Tracker.flush();\n  test.equal(_.pluck(btns, 'checked'), [false, true, false]);\n  test.equal(text(), \"Band: FM\");\n\n  clickIt(btns[2]);\n  test.equal(change_buf, ['XM']);\n  change_buf.length = 0;\n  Tracker.flush();\n  test.equal(_.pluck(btns, 'checked'), [false, false, true]);\n  test.equal(text(), \"Band: XM\");\n\n  clickIt(btns[1]);\n  test.equal(change_buf, ['FM']);\n  change_buf.length = 0;\n  Tracker.flush();\n  test.equal(_.pluck(btns, 'checked'), [false, true, false]);\n  test.equal(text(), \"Band: FM\");\n\n  document.body.removeChild(div);\n});\n\nTinytest.add(\"spacebars-tests - template_tests - checkbox\", function(test) {\n  var tmpl = Template.spacebars_test_control_checkbox;\n  var labels = [\"Foo\", \"Bar\", \"Baz\"];\n  var Rs = {};\n  _.each(labels, function (label) {\n    Rs[label] = ReactiveVar(false);\n  });\n  tmpl.helpers({\n    labels: labels,\n    isChecked: function () {\n      return Rs[this.toString()].get();\n    }\n  });\n  var changeBuf = [];\n\n  var div = renderToDiv(tmpl);\n  document.body.appendChild(div);\n\n  var boxes = nodesToArray(div.getElementsByTagName(\"INPUT\"));\n\n  test.equal(_.pluck(boxes, 'checked'), [false, false, false]);\n\n  // Re-render with first one checked.\n  Rs.Foo.set(true);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [true, false, false]);\n\n  // Re-render with first one unchecked again.\n  Rs.Foo.set(false);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [false, false, false]);\n\n  // User clicks the second one.\n  clickElement(boxes[1]);\n  test.equal(_.pluck(boxes, 'checked'), [false, true, false]);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [false, true, false]);\n\n  // Re-render with third one checked. Second one should stay checked because\n  // it's a user update!\n  Rs.Baz.set(true);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [false, true, true]);\n\n  // User turns second and third off.\n  clickElement(boxes[1]);\n  clickElement(boxes[2]);\n  test.equal(_.pluck(boxes, 'checked'), [false, false, false]);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [false, false, false]);\n\n  // Re-render with first one checked. Third should stay off because it's a user\n  // update!\n  Rs.Foo.set(true);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [true, false, false]);\n\n  // Re-render with first one unchecked. Third should still stay off.\n  Rs.Foo.set(false);\n  Tracker.flush();\n  test.equal(_.pluck(boxes, 'checked'), [false, false, false]);\n\n  document.body.removeChild(div);\n});\n\nTinytest.add('spacebars-tests - template_tests - unfound template', function (test) {\n  test.throws(function () {\n    renderToDiv(Template.spacebars_test_nonexistent_template);\n  }, /No such template/);\n});\n\nTinytest.add('spacebars-tests - template_tests - helper passed to #if called exactly once when invalidated', function (test) {\n  var tmpl = Template.spacebars_test_if_helper;\n\n  var foo;\n  var count = 0;\n  var d = new Tracker.Dependency;\n  tmpl.helpers({foo: function () {\n    d.depend();\n    count++;\n    return foo;\n  }});\n\n  foo = false;\n  var div = renderToDiv(tmpl);\n  divRendersTo(test, div, \"false\");\n  test.equal(count, 1);\n\n  foo = true;\n  d.changed();\n  divRendersTo(test, div, \"true\");\n  test.equal(count, 2);\n});\n\nTinytest.add('spacebars-tests - template_tests - custom block helper functions called exactly once when invalidated', function (test) {\n  var tmpl = Template.spacebars_test_block_helper_function;\n\n  var foo;\n  var count = 0;\n  var d = new Tracker.Dependency;\n  tmpl.helpers({foo: function () {\n    d.depend();\n    count++;\n    return Template.spacebars_template_test_aaa;\n  }});\n\n  foo = false;\n  renderToDiv(tmpl);\n  Tracker.flush();\n  test.equal(count, 1);\n\n  foo = true;\n  d.changed();\n  Tracker.flush();\n  test.equal(count, 2);\n});\n\nvar runOneTwoTest = function (test, subTemplateName, optionsData) {\n  _.each([Template.spacebars_test_helpers_stop_onetwo,\n          Template.spacebars_test_helpers_stop_onetwo_attribute],\n         function (tmpl) {\n\n           var sub1 = Template[subTemplateName + '1'];\n           var sub2 = Template[subTemplateName + '2'];\n\n           tmpl.helpers({\n             one: sub1,\n             two: sub2\n           });\n\n           var buf = '';\n\n           var showOne = ReactiveVar(true);\n           var dummy = ReactiveVar(0);\n\n           tmpl.helpers({showOne: function () { return showOne.get(); }});\n           sub1.helpers({options: function () {\n             var x = dummy.get();\n             buf += '1';\n             if (optionsData)\n               return optionsData[x];\n             else\n               return ['something'];\n           }});\n           sub2.helpers({options: function () {\n             var x = dummy.get();\n             buf += '2';\n             if (optionsData)\n               return optionsData[x];\n             else\n               return ['something'];\n           }});\n\n           var div = renderToDiv(tmpl);\n           Tracker.flush();\n           test.equal(buf, '1');\n\n           showOne.set(false);\n           dummy.set(1);\n           Tracker.flush();\n           test.equal(buf, '12');\n\n           showOne.set(true);\n           dummy.set(2);\n           Tracker.flush();\n           test.equal(buf, '121');\n\n           // clean up the div\n           $(div).remove();\n           test.equal(showOne._numListeners(), 0);\n           test.equal(dummy._numListeners(), 0);\n         });\n};\n\nTinytest.add('spacebars-tests - template_tests - with stops without re-running helper', function (test) {\n  runOneTwoTest(test, 'spacebars_test_helpers_stop_with');\n});\n\nTinytest.add('spacebars-tests - template_tests - each stops without re-running helper', function (test) {\n  runOneTwoTest(test, 'spacebars_test_helpers_stop_each');\n});\n\nTinytest.add('spacebars-tests - template_tests - each inside with stops without re-running helper', function (test) {\n  runOneTwoTest(test, 'spacebars_test_helpers_stop_with_each');\n});\n\nTinytest.add('spacebars-tests - template_tests - if stops without re-running helper', function (test) {\n  runOneTwoTest(test, 'spacebars_test_helpers_stop_if', ['a', 'b', 'a']);\n});\n\nTinytest.add('spacebars-tests - template_tests - unless stops without re-running helper', function (test) {\n  runOneTwoTest(test, 'spacebars_test_helpers_stop_unless', ['a', 'b', 'a']);\n});\n\nTinytest.add('spacebars-tests - template_tests - inclusion stops without re-running function', function (test) {\n  var t = Template.spacebars_test_helpers_stop_inclusion3;\n  runOneTwoTest(test, 'spacebars_test_helpers_stop_inclusion', [t, t, t]);\n});\n\nTinytest.add('spacebars-tests - template_tests - template with callbacks inside with stops without recalculating data', function (test) {\n  var tmpl = Template.spacebars_test_helpers_stop_with_callbacks3;\n  tmpl.created = function () {};\n  tmpl.rendered = function () {};\n  tmpl.destroyed = function () {};\n  runOneTwoTest(test, 'spacebars_test_helpers_stop_with_callbacks');\n});\n\nTinytest.add('spacebars-tests - template_tests - no data context is seen as an empty object', function (test) {\n  var tmpl = Template.spacebars_test_no_data_context;\n\n  var dataInHelper = 'UNSET';\n  var dataInRendered = 'UNSET';\n  var dataInCreated = 'UNSET';\n  var dataInDestroyed = 'UNSET';\n  var dataInEvent = 'UNSET';\n\n  tmpl.helpers({foo: function () {\n    dataInHelper = this;\n  }});\n  tmpl.created = function () {\n    dataInCreated = this.data;\n  };\n  tmpl.rendered = function () {\n    dataInRendered = this.data;\n  };\n  tmpl.destroyed = function () {\n    dataInDestroyed = this.data;\n  };\n  tmpl.events({\n    'click': function () {\n      dataInEvent = this;\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n  document.body.appendChild(div);\n  clickElement(div.querySelector('button'));\n  Tracker.flush(); // rendered gets called afterFlush\n  $(div).remove();\n\n  test.isFalse(dataInHelper === window);\n  test.equal(dataInHelper, {});\n  test.equal(dataInCreated, null);\n  test.equal(dataInRendered, null);\n  test.equal(dataInDestroyed, null);\n  test.isFalse(dataInEvent === window);\n  test.equal(dataInEvent, {});\n});\n\nTinytest.add('spacebars-tests - template_tests - falsy with', function (test) {\n  var tmpl = Template.spacebars_test_falsy_with;\n  var R = ReactiveVar(null);\n  tmpl.helpers({obj: function () { return R.get(); }});\n\n  var div = renderToDiv(tmpl);\n  divRendersTo(test, div, \"\");\n\n  R.set({greekLetter: 'alpha'});\n  divRendersTo(test, div, \"alpha\");\n\n  R.set(null);\n  divRendersTo(test, div, \"\");\n\n  R.set({greekLetter: 'alpha'});\n  divRendersTo(test, div, \"alpha\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - helpers don't leak\", function (test) {\n  var tmpl = Template.spacebars_test_helpers_dont_leak;\n  tmpl.foo = \"wrong\";\n  tmpl.bar = function () { return \"WRONG\"; };\n\n  // Also test that custom block helpers (implemented as templates) do NOT\n  // interfere with helper lookup in the current template\n  Template.spacebars_test_helpers_dont_leak2.helpers({\n    bonus: function () { return 'BONUS'; }});\n\n  var div = renderToDiv(tmpl);\n  divRendersTo(test, div, \"correct BONUS\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - event handler returns false\",\n  function (test) {\n    var tmpl = Template.spacebars_test_event_returns_false;\n    var elemId = \"spacebars_test_event_returns_false_link\";\n    tmpl.events({\n      'click a': function (evt) { return false; }\n    });\n\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n    clickIt(document.getElementById(elemId));\n    // NOTE: This failure can stick across test runs!  Try\n    // removing '#bad-url' from the location bar and run\n    // the tests again. :)\n    test.isFalse(/#bad-url/.test(window.location.hash));\n    document.body.removeChild(div);\n  }\n);\n\n// Make sure that if you bind an event on \"div p\", for example,\n// both the div and the p need to be in the template.  jQuery's\n// `$(elem).find(...)` works this way, but the browser's\n// querySelector doesn't.\nTinytest.add(\n  \"spacebars-tests - template_tests - event map selector scope\",\n  function (test) {\n    var tmpl = Template.spacebars_test_event_selectors1;\n    var tmpl2 = Template.spacebars_test_event_selectors2;\n    var buf = [];\n    tmpl2.events({\n      'click div p': function (evt) { buf.push(evt.currentTarget.className); }\n    });\n\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n    test.equal(buf.join(), '');\n    clickIt(div.querySelector('.p1'));\n    test.equal(buf.join(), '');\n    clickIt(div.querySelector('.p2'));\n    test.equal(buf.join(), 'p2');\n    document.body.removeChild(div);\n  }\n);\n\nif (document.addEventListener) {\n  // see note about non-bubbling events in the \"capuring events\"\n  // templating test for why we use the VIDEO tag.  (It would be\n  // nice to get rid of the network dependency, though.)\n  // We skip this test in IE 8.\n  Tinytest.add(\n    \"spacebars-tests - template_tests - event map selector scope (capturing)\",\n    function (test) {\n      var tmpl = Template.spacebars_test_event_selectors_capturing1;\n      var tmpl2 = Template.spacebars_test_event_selectors_capturing2;\n      var buf = [];\n      tmpl2.events({\n        'play div video': function (evt) { buf.push(evt.currentTarget.className); }\n      });\n\n      var div = renderToDiv(tmpl);\n      document.body.appendChild(div);\n      test.equal(buf.join(), '');\n      simulateEvent(div.querySelector(\".video1\"),\n                    \"play\", {}, {bubbles: false});\n      test.equal(buf.join(), '');\n      simulateEvent(div.querySelector(\".video2\"),\n                    \"play\", {}, {bubbles: false});\n      test.equal(buf.join(), 'video2');\n      document.body.removeChild(div);\n    }\n  );\n}\n\nTinytest.add(\"spacebars-tests - template_tests - tables\", function (test) {\n  var tmpl1 = Template.spacebars_test_tables1;\n\n  var div = renderToDiv(tmpl1);\n  test.equal(_.pluck(div.querySelectorAll('*'), 'tagName'),\n             ['TABLE', 'TR', 'TD']);\n  divRendersTo(test, div, '<table><tr><td>Foo</td></tr></table>');\n\n  var tmpl2 = Template.spacebars_test_tables2;\n  tmpl2.helpers({foo: 'Foo'});\n  div = renderToDiv(tmpl2);\n  test.equal(_.pluck(div.querySelectorAll('*'), 'tagName'),\n             ['TABLE', 'TR', 'TD']);\n  divRendersTo(test, div, '<table><tr><td>Foo</td></tr></table>');\n});\n\nTinytest.add(\"spacebars-tests - template_tests - jQuery.trigger extraParameters are passed to the event callback\",\n  function (test) {\n    var tmpl = Template.spacebars_test_jquery_events;\n    var captured = false;\n    var args = [\"param1\", \"param2\", {option: 1}, 1, 2, 3];\n\n    tmpl.events({\n      'someCustomEvent': function (event, template) {\n        var i;\n        for (i=0; i<args.length; i++) {\n          // expect the arguments to be just after template\n          test.equal(arguments[i+2], args[i]);\n        }\n        captured = true;\n      }\n    });\n\n    tmpl.rendered = function () {\n      $(this.find('button')).trigger('someCustomEvent', args);\n    };\n\n    renderToDiv(tmpl);\n    Tracker.flush();\n    test.equal(captured, true);\n  }\n);\n\nTinytest.add(\"spacebars-tests - template_tests - toHTML\", function (test) {\n  // run once, verifying that autoruns are stopped\n  var once = function (tmplToRender, tmplForHelper, helper, val) {\n    var count = 0;\n    var R = new ReactiveVar;\n    var getR = function () {\n      count++;\n      return R.get();\n    };\n\n    R.set(val);\n    var helpers = {};\n    helpers[helper] = getR;\n    tmplForHelper.helpers(helpers);\n    test.equal(canonicalizeHtml(Blaze.toHTML(tmplToRender)), \"bar\");\n    test.equal(count, 1);\n    R.set(\"\");\n    Tracker.flush();\n    test.equal(count, 1); // all autoruns stopped\n  };\n\n  once(Template.spacebars_test_tohtml_basic,\n       Template.spacebars_test_tohtml_basic, \"foo\", \"bar\");\n  once(Template.spacebars_test_tohtml_if,\n       Template.spacebars_test_tohtml_if, \"foo\", \"bar\");\n  once(Template.spacebars_test_tohtml_with,\n       Template.spacebars_test_tohtml_with, \"foo\", \"bar\");\n  once(Template.spacebars_test_tohtml_each,\n       Template.spacebars_test_tohtml_each, \"foos\", [\"bar\"]);\n\n  once(Template.spacebars_test_tohtml_include_with,\n       Template.spacebars_test_tohtml_with, \"foo\", \"bar\");\n  once(Template.spacebars_test_tohtml_include_each,\n       Template.spacebars_test_tohtml_each, \"foos\", [\"bar\"]);\n});\n\nTinytest.add(\"spacebars-tests - template_tests - block comments should not be displayed\",\n  function (test) {\n    var tmpl = Template.spacebars_test_block_comment;\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), '');\n  }\n);\n\n// Originally reported at https://github.com/meteor/meteor/issues/2046\nTinytest.add(\"spacebars-tests - template_tests - {{#with}} with mutated data context\",\n  function (test) {\n    var tmpl = Template.spacebars_test_with_mutated_data_context;\n    var foo = {value: 0};\n    var dep = new Tracker.Dependency;\n    tmpl.helpers({foo: function () {\n      dep.depend();\n      return foo;\n    }});\n\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), '0');\n\n    foo.value = 1;\n    dep.changed();\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), '1');\n  });\n\nTinytest.add(\"spacebars-tests - template_tests - javascript scheme urls\",\n  function (test) {\n    var tmpl = Template.spacebars_test_url_attribute;\n    var sessionKey = \"foo-\" + Random.id();\n    tmpl.helpers({foo: function () {\n      return Session.get(sessionKey);\n    }});\n\n    var numUrlAttrs = 4;\n    var div = renderToDiv(tmpl);\n\n    // [tag name, attr name, is a url attribute]\n    var attrsList = [[\"A\", \"href\", true], [\"FORM\", \"action\", true],\n                     [\"IMG\", \"src\", true], [\"INPUT\", \"value\", false]];\n\n    var checkAttrs = function (url, isJavascriptProtocol) {\n      if (isJavascriptProtocol) {\n        Meteor._suppress_log(numUrlAttrs);\n      }\n      Session.set(sessionKey, url);\n      Tracker.flush();\n      _.each(\n        attrsList,\n        function (attrInfo) {\n          var normalizedUrl;\n          var elem = document.createElement(attrInfo[0]);\n          try {\n            elem[attrInfo[1]] = url;\n          } catch (err) {\n            // IE throws an exception if you set an img src to a\n            // javascript: URL. Blaze can't override this behavior;\n            // whether you've called Blaze._javascriptUrlsAllowed() or not,\n            // you won't be able to set a javascript: URL in an img\n            // src. So we only test img tags in other browsers.\n            if (attrInfo[0] === \"IMG\") {\n              return;\n            }\n            throw err;\n          }\n          document.body.appendChild(elem);\n          normalizedUrl = elem[attrInfo[1]];\n          document.body.removeChild(elem);\n\n          _.each(\n            div.getElementsByTagName(attrInfo[0]),\n            function (elem) {\n              test.equal(\n                elem[attrInfo[1]],\n                isJavascriptProtocol && attrInfo[2] ? \"\" : normalizedUrl\n              );\n            }\n          );\n        }\n      );\n    };\n\n    test.equal(Blaze._javascriptUrlsAllowed(), false);\n    checkAttrs(\"http://www.meteor.com\", false);\n    checkAttrs(\"javascript:alert(1)\", true);\n    checkAttrs(\"jAvAsCrIpT:alert(1)\", true);\n    checkAttrs(\"    javascript:alert(1)\", true);\n    Blaze._allowJavascriptUrls();\n    test.equal(Blaze._javascriptUrlsAllowed(), true);\n    checkAttrs(\"http://www.meteor.com\", false);\n    checkAttrs(\"javascript:alert(1)\", false);\n    checkAttrs(\"jAvAsCrIpT:alert(1)\", false);\n    checkAttrs(\"    javascript:alert(1)\", false);\n  }\n);\n\nTinytest.add(\"spacebars-tests - template_tests - event handlers get cleaned up when template is removed\",\n  function (test) {\n    var tmpl = Template.spacebars_test_event_handler_cleanup;\n    var subtmpl = Template.spacebars_test_event_handler_cleanup_sub;\n\n    var rv = new ReactiveVar(true);\n    tmpl.helpers({foo: function () {\n      return rv.get();\n    }});\n\n    subtmpl.events({\n      \"click/mouseover\": function () { }\n    });\n\n    var div = renderToDiv(tmpl);\n\n    test.equal(div.$blaze_events[\"click\"].handlers.length, 1);\n    test.equal(div.$blaze_events[\"mouseover\"].handlers.length, 1);\n\n    rv.set(false);\n    Tracker.flush();\n\n    test.equal(div.$blaze_events[\"click\"].handlers.length, 0);\n    test.equal(div.$blaze_events[\"mouseover\"].handlers.length, 0);\n  }\n);\n\n// This test makes sure that Blaze correctly finds the controller\n// heirarchy surrounding an element that itself doesn't have a\n// controller.\nTinytest.add(\n  \"spacebars-tests - template_tests - data context in event handlers on elements inside {{#if}}\",\n  function (test) {\n    var tmpl = Template.spacebars_test_data_context_for_event_handler_in_if;\n    var data = null;\n    tmpl.events({\n      'click span': function () {\n        data = this;\n      }\n    });\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n    clickIt(div.querySelector('span'));\n    test.equal(data, {foo: \"bar\"});\n    document.body.removeChild(div);\n  });\n\n// https://github.com/meteor/meteor/issues/2156\nTinytest.add(\n  \"spacebars-tests - template_tests - each with inserts inside autorun\",\n  function (test) {\n    var tmpl = Template.spacebars_test_each_with_autorun_insert;\n    var coll = new Mongo.Collection(null);\n    var rv = new ReactiveVar;\n\n    tmpl.helpers({items: function () {\n      return coll.find();\n    }});\n\n    var div = renderToDiv(tmpl);\n\n    Tracker.autorun(function () {\n      if (rv.get()) {\n        coll.insert({ name: rv.get() });\n      }\n    });\n\n    rv.set(\"foo1\");\n    Tracker.flush();\n    var firstId = coll.findOne()._id;\n\n    rv.set(\"foo2\");\n    Tracker.flush();\n\n    test.equal(canonicalizeHtml(div.innerHTML), \"foo1 foo2\");\n\n    coll.update(firstId, { $set: { name: \"foo3\" } });\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"foo3 foo2\");\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - template_tests - ui hooks\",\n  function (test) {\n    var tmpl = Template.spacebars_test_ui_hooks;\n    var rv = new ReactiveVar([]);\n    tmpl.helpers({items: function () {\n      return rv.get();\n    }});\n\n    var div = renderToDiv(tmpl);\n\n    var hooks = [];\n    var container = div.querySelector(\".test-ui-hooks\");\n\n    // Before we attach the ui hooks, put two items in the DOM.\n    var origVal = [{ _id: 'foo1' }, { _id: 'foo2' }];\n    rv.set(origVal);\n    Tracker.flush();\n\n    container._uihooks = {\n      insertElement: function (n, next) {\n        hooks.push(\"insert\");\n\n        // check that the element hasn't actually been added yet\n        test.isTrue((! n.parentNode) ||\n                    n.parentNode.nodeType === 11 /*DOCUMENT_FRAGMENT_NODE*/);\n      },\n      removeElement: function (n) {\n        hooks.push(\"remove\");\n        // check that the element hasn't actually been removed yet\n        test.isTrue(n.parentNode === container);\n      },\n      moveElement: function (n, next) {\n        hooks.push(\"move\");\n        // check that the element hasn't actually been moved yet\n        test.isFalse(n.nextNode === next);\n      }\n    };\n\n    var testDomUnchanged = function () {\n      var items = div.querySelectorAll(\".item\");\n      test.equal(items.length, 2);\n      test.equal(canonicalizeHtml(items[0].innerHTML), \"foo1\");\n      test.equal(canonicalizeHtml(items[1].innerHTML), \"foo2\");\n    };\n\n    var newVal = _.clone(origVal);\n    newVal.push({ _id: 'foo3' });\n    rv.set(newVal);\n    Tracker.flush();\n    test.equal(hooks, ['insert']);\n    testDomUnchanged();\n\n    newVal.reverse();\n    rv.set(newVal);\n    Tracker.flush();\n    test.equal(hooks, ['insert', 'move']);\n    testDomUnchanged();\n\n    newVal = [origVal[0]];\n    rv.set(newVal);\n    Tracker.flush();\n    test.equal(hooks, ['insert', 'move', 'remove']);\n    testDomUnchanged();\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - template_tests - ui hooks - nested domranges\",\n  function (test) {\n    var tmpl = Template.spacebars_test_ui_hooks_nested;\n    var rv = new ReactiveVar(true);\n\n    tmpl.helpers({foo: function () {\n      return rv.get();\n    }});\n\n    var subtmpl = Template.spacebars_test_ui_hooks_nested_sub;\n    var uiHookCalled = false;\n    subtmpl.rendered = function () {\n      this.firstNode.parentNode._uihooks = {\n        removeElement: function (node) {\n          uiHookCalled = true;\n        }\n      };\n    };\n\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n    Tracker.flush();\n\n    var htmlBeforeRemove = canonicalizeHtml(div.innerHTML);\n    rv.set(false);\n    Tracker.flush();\n    test.isTrue(uiHookCalled);\n    var htmlAfterRemove = canonicalizeHtml(div.innerHTML);\n    test.equal(htmlBeforeRemove, htmlAfterRemove);\n    document.body.removeChild(div);\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - template_tests - Template.instance from helper\",\n  function (test) {\n    // Set a property on the template instance; check that it's still\n    // there from a helper.\n\n    var tmpl = Template.spacebars_test_template_instance_helper;\n    var value = Random.id();\n    var instanceFromHelper;\n\n    tmpl.created = function () {\n      this.value = value;\n    };\n    tmpl.helpers({foo: function () {\n      instanceFromHelper = Template.instance();\n    }});\n\n    var div = renderToDiv(tmpl);\n    test.equal(instanceFromHelper.value, value);\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - template_tests - Template.instance from helper, \" +\n    \"template instance is kept up-to-date\",\n  function (test) {\n    var tmpl = Template.spacebars_test_template_instance_helper;\n    var rv = new ReactiveVar(\"\");\n    var instanceFromHelper;\n\n    tmpl.helpers({foo: function () {\n      return Template.instance().data;\n    }});\n\n    var div = renderToDiv(tmpl, function () { return rv.get(); });\n    rv.set(\"first\");\n    divRendersTo(test, div, \"first\");\n\n    rv.set(\"second\");\n    Tracker.flush();\n    divRendersTo(test, div, \"second\");\n\n    // Template.instance() returns null when no template instance\n    test.isTrue(Template.instance() === null);\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - template_tests - {{#with}} autorun is cleaned up\",\n  function (test) {\n    var tmpl = Template.spacebars_test_with_cleanup;\n    var rv = new ReactiveVar(\"\");\n    var helperCalled = false;\n    tmpl.helpers({foo: function () {\n      helperCalled = true;\n      return rv.get();\n    }});\n\n    var div = renderToDiv(tmpl);\n    rv.set(\"first\");\n    Tracker.flush();\n    test.equal(helperCalled, true);\n\n    helperCalled = false;\n    $(div).find(\".test-with-cleanup\").remove();\n\n    rv.set(\"second\");\n    Tracker.flush();\n    test.equal(helperCalled, false);\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - template_tests - Template.parentData from helpers\",\n  function (test) {\n    var childTmpl = Template.spacebars_test_template_parent_data_helper_child;\n    var parentTmpl = Template.spacebars_test_template_parent_data_helper;\n\n    var height = new ReactiveVar(0);\n    var bar = new ReactiveVar(\"bar\");\n\n    childTmpl.helpers({\n      a: [\"a\"],\n      b: function () { return bar.get(); },\n      c: [\"c\"],\n      foo: function () {\n        var a = Template.parentData(height.get());\n        var b = UI._parentData(height.get()); // back-compat\n        test.equal(a, b);\n        return a;\n      }\n    });\n\n    var div = renderToDiv(parentTmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), \"d\");\n\n    height.set(1);\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"bar\");\n\n    // Test Template.parentData() reactivity\n\n    bar.set(\"baz\");\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"baz\");\n\n    height.set(2);\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"a\");\n\n    height.set(3);\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"parent\");\n\n    // Test that calling Template.parentData() without any arguments is the same as Template.parentData(1)\n\n    height.set(null);\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"baz\");\n  }\n);\n\nTinytest.add(\n  \"spacebars - SVG <a> elements\",\n  function (test) {\n    if (! document.createElementNS) {\n      // IE 8\n      return;\n    }\n\n    var tmpl = Template.spacebars_test_svg_anchor;\n    var div = renderToDiv(tmpl);\n\n    var anchNamespace = $(div).find(\"a\").get(0).namespaceURI;\n    test.equal(anchNamespace, \"http://www.w3.org/2000/svg\");\n  }\n);\n\nTinytest.add(\n  \"spacebars-tests - template_tests - created/rendered/destroyed by each\",\n  function (test) {\n    var outerTmpl =\n          Template.spacebars_test_template_created_rendered_destroyed_each;\n    var innerTmpl =\n          Template.spacebars_test_template_created_rendered_destroyed_each_sub;\n\n    var buf = '';\n\n    innerTmpl.created = function () { buf += 'C' + String(this.data).toLowerCase(); };\n    innerTmpl.rendered = function () { buf += 'R' + String(this.data).toLowerCase(); };\n    innerTmpl.destroyed = function () { buf += 'D' + String(this.data).toLowerCase(); };\n\n    var R = ReactiveVar([{_id: 'A'}]);\n\n    outerTmpl.helpers({items: function () {\n      return R.get();\n    }});\n\n    var div = renderToDiv(outerTmpl);\n    divRendersTo(test, div, '<div>A</div>');\n    test.equal(buf, 'CaRa');\n\n    R.set([{_id: 'B'}]);\n    divRendersTo(test, div, '<div>B</div>');\n    test.equal(buf, 'CaRaDaCbRb');\n\n    R.set([{_id: 'C'}]);\n    divRendersTo(test, div, '<div>C</div>');\n    test.equal(buf, 'CaRaDaCbRbDbCcRc');\n\n    $(div).remove();\n    test.equal(buf, 'CaRaDaCbRbDbCcRcDc');\n  });\n\nTinytest.add(\n  \"spacebars-tests - template_tests - Blaze.render/Blaze.remove\",\n  function (test) {\n    var div = document.createElement(\"DIV\");\n    document.body.appendChild(div);\n\n    var created = false, rendered = false, destroyed = false;\n    var R = ReactiveVar('aaa');\n\n    var tmpl = Template.spacebars_test_ui_render;\n    tmpl.helpers({\n      greeting: function () { return this.greeting || 'Hello'; },\n      r: function () { return R.get(); }\n    });\n    tmpl.created = function () { created = true; };\n    tmpl.rendered = function () { rendered = true; };\n    tmpl.destroyed = function () { destroyed = true; };\n\n    test.equal([created, rendered, destroyed], [false, false, false]);\n\n    var renderedTmpl = Blaze.render(tmpl, div);\n    test.equal([created, rendered, destroyed], [true, false, false]);\n\n    // Flush now. We fire the rendered callback in an afterFlush block,\n    // to ensure that the DOM is completely updated.\n    Tracker.flush();\n    test.equal([created, rendered, destroyed], [true, true, false]);\n\n    var otherDiv = document.createElement(\"DIV\");\n    // can run a second time without throwing\n    var x = Blaze.render(tmpl, otherDiv);\n    // note: we'll have clean up `x` below\n\n    var renderedTmpl2 = Blaze.renderWithData(\n      tmpl, {greeting: 'Bye'}, div);\n    test.equal(canonicalizeHtml(div.innerHTML),\n               \"<span>Hello aaa</span><span>Bye aaa</span>\");\n    R.set('bbb');\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML),\n               \"<span>Hello bbb</span><span>Bye bbb</span>\");\n    test.equal([created, rendered, destroyed], [true, true, false]);\n    test.equal(R._numListeners(), 3);\n    Blaze.remove(renderedTmpl);\n    Blaze.remove(renderedTmpl); // test that double-remove doesn't throw\n    Blaze.remove(renderedTmpl2);\n    Blaze.remove(x);\n    test.equal([created, rendered, destroyed], [true, true, true]);\n    test.equal(R._numListeners(), 0);\n    test.equal(canonicalizeHtml(div.innerHTML), \"\");\n  });\n\nTinytest.add(\n  \"spacebars-tests - template_tests - Blaze.render fails on jQuery objects\",\n  function (test) {\n    var tmpl = Template.spacebars_test_ui_render;\n    test.throws(function () {\n      Blaze.render(tmpl, $('body'));\n    }, /'parentElement' must be a DOM node/);\n    test.throws(function () {\n      Blaze.render(tmpl, document.body, $('body'));\n    }, /'nextNode' must be a DOM node/);\n  });\n\nTinytest.add(\n  \"spacebars-tests - template_tests - UI.getElementData\",\n  function (test) {\n    var div = document.createElement(\"DIV\");\n    var tmpl = Template.spacebars_test_ui_getElementData;\n    Blaze.renderWithData(tmpl, {foo: \"bar\"}, div);\n\n    var span = div.querySelector('SPAN');\n    test.isTrue(span);\n    test.equal(UI.getElementData(span), {foo: \"bar\"});\n    test.equal(Blaze.getData(span), {foo: \"bar\"});\n  });\n\nTinytest.add(\n  \"spacebars-tests - template_tests - autorun cleanup\",\n  function (test) {\n    var tmpl = Template.spacebars_test_parent_removal;\n\n    var Acalls = '';\n    var A = ReactiveVar('hi');\n    tmpl.helpers({A: function (chr) {\n      Acalls += chr;\n      return A.get();\n    }});\n    var Bcalls = 0;\n    var B = ReactiveVar(['one', 'two']);\n    tmpl.helpers({B: function () {\n      Bcalls++;\n      return B.get();\n    }});\n\n    // Assert how many times A and B were accessed (since last time)\n    // and how many autoruns are listening to them.\n    var assertCallsAndListeners =\n          function (a_calls, b_calls, a_listeners, b_listeners) {\n            test.equal('A calls: ' + Acalls.length,\n                       'A calls: ' + a_calls,\n                       Acalls);\n            test.equal('B calls: ' + Bcalls,\n                       'B calls: ' + b_calls);\n            test.equal('A listeners: ' + A._numListeners(),\n                       'A listeners: ' + a_listeners);\n            test.equal('B listeners: ' + B._numListeners(),\n                       'B listeners: ' + b_listeners);\n            Acalls = '';\n            Bcalls = 0;\n          };\n\n    var div = renderToDiv(tmpl);\n    assertCallsAndListeners(10, 1, 10, 1);\n    A.set('');\n    Tracker.flush();\n    // Confirm that #4, #5, #6, and #9 are not re-run.\n    // #a is newly run, for a total of 10 - 4 + 1 = 7,\n    assertCallsAndListeners(7, 0, 7, 1);\n    A.set('hi');\n    Tracker.flush();\n    assertCallsAndListeners(10, 0, 10, 1);\n\n    // Now see that removing the DOM with jQuery, below\n    // the level of the entire template, stops everything.\n    $(div.querySelector('.toremove')).remove();\n    assertCallsAndListeners(0, 0, 0, 0);\n  });\n\nTinytest.add(\n  \"spacebars-tests - template_tests - focus/blur with clean-up\",\n  function (test) {\n    var tmpl = Template.spacebars_test_focus_blur_outer;\n    var cond = ReactiveVar(true);\n    tmpl.helpers({cond: function () {\n      return cond.get();\n    }});\n    var buf = [];\n    Template.spacebars_test_focus_blur_inner.events({\n      'focus input': function () {\n        buf.push('FOCUS');\n      },\n      'blur input': function () {\n        buf.push('BLUR');\n      }\n    });\n\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n\n    // check basic focus and blur to make sure\n    // everything is sane\n    test.equal(div.querySelectorAll('input').length, 1);\n    var input;\n    focusElement(input = div.querySelector('input'));\n    // We don't get focus events when the Chrome Dev Tools are focused,\n    // unfortunately, as of Chrome 35.  I think this is a regression in\n    // Chrome 34.  So, the goal is to work whether or not focus is\n    // \"borken,\" where \"working\" means always failing if DOMBackend isn't\n    // correctly unbinding the old event handlers when we switch the IF,\n    // and always passing if it is.  To cause the problem in DOMBackend,\n    // delete the '**' argument to jQuery#off in\n    // DOMBackend.Events.undelegateEvents.  The only compromise we are\n    // making here is that if some unrelated bug in Blaze makes\n    // focus/blur not work, the failure might be masked while the Dev\n    // Tools are open.\n    var borken = false;\n    if (buf.length === 0 && document.activeElement === input) {\n      test.ok({note:\"You might need to defocus the Chrome Dev Tools to get a more accurate run of this test!\"});\n      borken = true;\n      $(input).trigger('focus');\n    }\n    test.equal(buf.join(), 'FOCUS');\n    blurElement(div.querySelector('input'));\n    if (buf.length === 1)\n      $(input).trigger('blur');\n    test.equal(buf.join(), 'FOCUS,BLUR');\n\n    // now switch the IF and check again.  The failure mode\n    // we observed was that DOMBackend would not correctly\n    // unbind the old event listener at the jQuery level,\n    // so the old event listener would fire and cause an\n    // exception inside Blaze (\"Must be attached\" in\n    // DOMRange#containsElement), which would show up in\n    // the console and cause our handler not to fire.\n    cond.set(false);\n    buf.length = 0;\n    Tracker.flush();\n    test.equal(div.querySelectorAll('input').length, 1);\n    focusElement(input = div.querySelector('input'));\n    if (borken)\n      $(input).trigger('focus');\n    test.equal(buf.join(), 'FOCUS');\n    blurElement(div.querySelector('input'));\n    if (! borken)\n      test.equal(buf.join(), 'FOCUS,BLUR');\n\n    document.body.removeChild(div);\n  });\n\n// We used to remove event handlers on DOMRange detached, but when\n// tearing down a view, we don't \"detach\" all the DOMRanges recursively.\n// Mainly, we destroy the View.  Destroying a View should remove its\n// event listeners.  (In practice, however, it's hard to think of\n// consequences to not removing event handlers on removed DOM nodes,\n// which will probably be GCed anyway.)\nTinytest.add(\n  \"spacebars-tests - template_tests - event cleanup on destroyed\",\n  function (test) {\n    var tmpl = Template.spacebars_test_event_cleanup_on_destroyed_outer;\n    var cond = ReactiveVar(true);\n    tmpl.helpers({cond: function () {\n      return cond.get();\n    }});\n\n    Template.spacebars_test_event_cleanup_on_destroyed_inner.events({\n      'click span': function () {}});\n\n    var div = renderToDiv(tmpl);\n    document.body.appendChild(div);\n\n    var eventDiv = div.querySelector('div');\n    test.equal(eventDiv.$blaze_events.click.handlers.length, 1);\n\n    cond.set(false);\n    Tracker.flush();\n    test.equal(eventDiv.$blaze_events.click.handlers.length, 0);\n\n    document.body.removeChild(div);\n  });\n\n_.each([1, 2, 3], function (n) {\n  Tinytest.add(\n    \"spacebars-tests - template_tests - lookup is isolated \" + n,\n    function (test) {\n      var buf = \"\";\n      var inclusion = Template.spacebars_test_isolated_lookup_inclusion;\n      inclusion.created = function () { buf += 'C'; };\n      inclusion.destroyed = function () { buf += 'D'; };\n\n      var tmpl = Template['spacebars_test_isolated_lookup' + n];\n      var R = ReactiveVar(Template.spacebars_template_test_aaa);\n\n      tmpl.helpers({bar: function () {\n        return R.get();\n      }});\n\n      var div = renderToDiv(\n        tmpl,\n        function () {\n          return { foo: R.get() };\n        });\n\n      test.equal(canonicalizeHtml(div.innerHTML), 'aaa--x');\n      test.equal(buf, 'C');\n      R.set(Template.spacebars_template_test_bbb);\n      Tracker.flush();\n      test.equal(canonicalizeHtml(div.innerHTML), 'bbb--x');\n      test.equal(buf, 'C');\n    }\n  );\n});\n\nTinytest.add('spacebars-tests - template_tests - current view in event handler', function (test) {\n  var tmpl = Template.spacebars_test_current_view_in_event;\n\n  var currentView;\n  var currentData;\n\n  tmpl.events({\n    'click span': function () {\n      currentView = Blaze.getView();\n      currentData = Blaze.getData();\n    }\n  });\n\n  var div = renderToDiv(tmpl, 'blah');\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>blah</span>');\n  document.body.appendChild(div);\n  clickElement(div.querySelector('span'));\n  $(div).remove();\n\n  test.isTrue(currentView);\n  test.equal(currentData, 'blah');\n});\n\n\nTinytest.add('spacebars-tests - template_tests - helper invalidates self', function (test) {\n  var tmpl = Template.spacebars_template_test_bracketed_foo;\n\n  var count = new ReactiveVar(0);\n\n  tmpl.helpers({\n    // It's unusual for a helper to have side effects, but it's possible\n    // and people do it.  Regression test for #4097.\n    foo: function () {\n      // Make count odd and return it.\n      var c = count.get();\n      if ((c % 2) === 0) {\n        count.set(c+1);\n      }\n      return c;\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n  divRendersTo(test, div, '[1]');\n  count.set(2);\n  divRendersTo(test, div, '[3]');\n});\n\nTinytest.add(\n  \"spacebars-tests - template_tests - textarea attrs\", function (test) {\n    var tmplNoContents = {\n      tmpl: Template.spacebars_test_textarea_attrs,\n      hasTextAreaContents: false\n    };\n    var tmplWithContents = {\n      tmpl: Template.spacebars_test_textarea_attrs_contents,\n      hasTextAreaContents: true\n    };\n    var tmplWithContentsAndMoreAttrs = {\n      tmpl: Template.spacebars_test_textarea_attrs_array_contents,\n      hasTextAreaContents: true\n    };\n\n    _.each(\n      [tmplNoContents, tmplWithContents,\n       tmplWithContentsAndMoreAttrs],\n      function (tmplInfo) {\n\n        var id = new ReactiveVar(\"textarea-\" + Random.id());\n        var name = new ReactiveVar(\"one\");\n        var attrs = new ReactiveVar({\n          id: \"textarea-\" + Random.id()\n        });\n\n        var div = renderToDiv(tmplInfo.tmpl, {\n          attrs: function () {\n            return attrs.get();\n          },\n          name: function () {\n            return name.get();\n          }\n        });\n\n        // Check that the id and value attribute are as we expect.\n        // We can't check div.innerHTML because Chrome at least doesn't\n        // appear to put textarea value attributes in innerHTML.\n        var textarea = div.querySelector(\"textarea\");\n        test.equal(textarea.id, attrs.get().id);\n        test.equal(\n          textarea.value, tmplInfo.hasTextAreaContents ? \"Hello one\" : \"\");\n        // One of the templates has a separate attribute in addition to\n        // an attributes dictionary.\n        if (tmplInfo === tmplWithContentsAndMoreAttrs) {\n          test.equal($(textarea).attr(\"class\"), \"bar\");\n        }\n\n        // Change the id, check that the attribute updates reactively.\n        attrs.set({ id: \"textarea-\" + Random.id() });\n        Tracker.flush();\n        test.equal(textarea.id, attrs.get().id);\n\n        // Change the name variable, check that the textarea value\n        // updates reactively.\n        name.set(\"two\");\n        Tracker.flush();\n        test.equal(\n          textarea.value, tmplInfo.hasTextAreaContents ? \"Hello two\" : \"\");\n\n        if (tmplInfo === tmplWithContentsAndMoreAttrs) {\n          test.equal($(textarea).attr(\"class\"), \"bar\");\n        }\n\n      });\n\n  });\n\nTinytest.add(\n  \"spacebars-tests - template_tests - this.autorun\",\n  function (test) {\n    var tmpl = Template.spacebars_test_autorun;\n    var tmplInner = Template.spacebars_test_autorun_inner;\n\n    // Keep track of the value of `Template.instance()` inside the\n    // autorun each time it runs.\n    var autorunTemplateInstances = [];\n    var actualTemplateInstance;\n    var returnedComputation;\n    var computationArg;\n\n    var show = new ReactiveVar(true);\n    var rv = new ReactiveVar(\"foo\");\n\n    tmplInner.created = function () {\n      actualTemplateInstance = this;\n      returnedComputation = this.autorun(function (c) {\n        computationArg = c;\n        rv.get();\n        autorunTemplateInstances.push(Template.instance());\n      });\n    };\n\n    tmpl.helpers({\n      show: function () {\n        return show.get();\n      }\n    });\n\n    var div = renderToDiv(tmpl);\n    test.equal(autorunTemplateInstances.length, 1);\n    test.equal(autorunTemplateInstances[0], actualTemplateInstance);\n\n    // Test that the autorun returned a computation and received a\n    // computation as an argument.\n    test.isTrue(returnedComputation instanceof Tracker.Computation);\n    test.equal(returnedComputation, computationArg);\n\n    // Make sure the autorun re-runs when `rv` changes, and that it has\n    // the correct current view.\n    rv.set(\"bar\");\n    Tracker.flush();\n    test.equal(autorunTemplateInstances.length, 2);\n    test.equal(autorunTemplateInstances[1], actualTemplateInstance);\n\n    // If the inner template is destroyed, the autorun should be stopped.\n    show.set(false);\n    Tracker.flush();\n    rv.set(\"baz\");\n    Tracker.flush();\n\n    test.equal(autorunTemplateInstances.length, 2);\n    test.equal(rv._numListeners(), 0);\n  }\n);\n\n// Test that argument in {{> Template.contentBlock arg}} is evaluated in\n// the proper data context.\nTinytest.add(\n  \"spacebars-tests - template_tests - contentBlock argument\",\n  function (test) {\n    var tmpl = Template.spacebars_test_contentBlock_arg;\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), 'AAA BBB');\n  });\n\n// Test that when Blaze sets an input field to the same value,\n// we don't lose the insertion point position.\nTinytest.add(\n  \"spacebars-tests - template_tests - input field to same value\",\n  function (test) {\n    var tmpl = Template.spacebars_template_test_input_field_to_same_value;\n    var R = ReactiveVar(\"BLAH\");\n    tmpl.helpers({foo: function () { return R.get(); }});\n    var div = renderToDiv(tmpl);\n\n    document.body.appendChild(div);\n\n    var input = div.querySelector('input');\n    test.equal(input.value, \"BLAH\");\n\n    var setSelection = function (startEnd) {\n      startEnd = startEnd.split(' ');\n      if (typeof input.selectionStart === 'number') {\n        // all but IE < 9\n        input.selectionStart = startEnd[0];\n        input.selectionEnd = startEnd[1];\n      } else {\n        // IE 8\n        input.focus();\n        var r = input.createTextRange();\n        // move the start and end of the range to the beginning\n        // of the input field\n        r.moveStart('textedit', -1);\n        r.moveEnd('textedit', -1);\n        // move the start and end a certain number of characters\n        // (relative to their current position)\n        r.moveEnd('character', startEnd[1]);\n        r.moveStart('character', startEnd[0]);\n        r.select();\n      }\n    };\n    var getSelection = function () {\n      if (typeof input.selectionStart === 'number') {\n        // all but IE < 9\n        return input.selectionStart + \" \" + input.selectionEnd;\n      } else {\n        // IE 8\n        input.focus();\n        var r = document.selection.createRange();\n        var fullText = input.value;\n        var start, end;\n        if (r.text) {\n          // one or more characters are selected.\n          // this is kind of hacky!  Relies on fullText\n          // not having duplicate letters, for example.\n          start = fullText.indexOf(r.text);\n          end = start + r.text.length;\n        } else {\n          r.moveStart('textedit', -1);\n          start = end = r.text.length;\n        }\n        return start + \" \" + end;\n      }\n    };\n\n    setSelection(\"2 3\");\n    test.equal(getSelection(), \"2 3\");\n    // At this point, we COULD confirm that setting input.value to\n    // the same thing as before (\"BLAH\") loses the insertion\n    // point (per browser behavior).  However, it doesn't on Firefox.\n    // So we set it to something different, which verifies that our\n    // test machinery is correct.\n    input.value = \"BLAN\";\n    // test that insertion point is lost\n    var selectionAfterSet = getSelection();\n    if (selectionAfterSet !== \"0 0\") // IE 8\n      test.equal(getSelection(), \"4 4\");\n\n    // now make the input say \"BLAH\" but the AttributeHandler\n    // says \"OTHER\" (so we can make it do the no-op update)\n    R.set(\"OTHER\");\n    Tracker.flush();\n    test.equal(input.value, \"OTHER\");\n    input.value = \"BLAH\";\n    setSelection(\"2 2\");\n\n    R.set(\"BLAH\");\n    Tracker.flush();\n    test.equal(input.value, \"BLAH\");\n    // test that didn't lose insertion point!\n    test.equal(getSelection(), \"2 2\");\n\n    // clean up after ourselves\n    document.body.removeChild(div);\n  }\n);\n\nTinytest.add(\"spacebars-tests - template_tests - contentBlock back-compat\", function (test) {\n  // adapted from another test, but this time make sure `UI.contentBlock`\n  // and `UI.elseBlock` correctly behave as `Template.contentBlock`\n  // and `Template.elseBlock`.\n\n  var tmpl = Template.spacebars_template_test_content_backcompat;\n  var R = ReactiveVar(true);\n  tmpl.helpers({flag: function () {\n    return R.get();\n  }});\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'hello');\n  R.set(false);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'world');\n  R.set(true);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'hello');\n});\n\n// For completeness (of coverage), make sure the code that calls\n// `Template.contentBlock` in the correct scope also causes\n// the old `UI.contentBlock` to be called in the correct scope.\nTinytest.add(\"spacebars-tests - template_tests - content context back-compat\", function (test) {\n  var tmpl = Template.spacebars_template_test_content_context_backcompat;\n  var R = ReactiveVar(true);\n  tmpl.helpers({foo: {\n    firstLetter: 'F',\n    secondLetter: 'O',\n    bar: {\n      cond: function () { return R.get(); },\n      firstLetter: 'B',\n      secondLetter: 'A'\n    }\n  }});\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'BO');\n  R.set(false);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), 'FA');\n});\n\nTinytest.add(\"spacebars-tests - template_tests - falsy helper\", function (test) {\n  var tmpl = Template.spacebars_template_test_falsy_helper;\n  tmpl.helpers({foo: 0});\n  Template.registerHelper('GLOBAL_ZERO', 0);\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'foo:0 GLOBAL_ZERO:0');\n});\n\nTinytest.add(\"spacebars-tests - template_tests - old-style helpers\", function (test) {\n  var tmpl = Template.spacebars_template_test_oldstyle_helpers;\n  tmpl._NOWARN_OLDSTYLE_HELPERS = true;\n\n  // Test old-style helper\n  tmpl.foo = 'hello';\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'hello');\n\n  // Test that replacing a helper still works (i.e. we don't cache them).\n  // We can change this behavior if we need to, but it is more breaking\n  // to do so.  It breaks some unit tests, for example.\n  tmpl.foo = 'world';\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), 'world');\n\n  // Test that you can delete an old-style helper with `delete`.\n  // As with the previous case, we can break this functionality, but\n  // we should do it intentionally.\n  delete tmpl.foo;\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), '');\n});\n\nTinytest.add(\"spacebars-tests - template_tests - with data remove (#3130)\", function (test) {\n  var tmpl = Template.spacebars_template_test_with_data_remove;\n\n  var div = document.createElement(\"DIV\");\n  var theWith = Blaze.renderWithData(tmpl, { foo: 3130 }, div);\n  test.equal(canonicalizeHtml(div.innerHTML), '<b>some data - 3130</b>');\n  var view = Blaze.getView(div.querySelector('b'));\n  test.isFalse(theWith.isDestroyed);\n  Blaze.remove(view);\n  test.isTrue(theWith.isDestroyed);\n  test.equal(div.innerHTML, \"\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - inclusion with data remove (#3130)\", function (test) {\n  var tmpl = Template.spacebars_template_test_inclusion_with_data_remove;\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), '<span><b>stuff</b></span>');\n  var view = Blaze.getView(div.querySelector('b'));\n  var parentView = view.parentView;\n  test.isTrue(parentView.__isTemplateWith);\n  test.isFalse(parentView.isDestroyed);\n  Blaze.remove(view);\n  test.isTrue(parentView.isDestroyed);\n  test.equal(canonicalizeHtml(div.innerHTML), \"<span></span>\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - custom block helper doesn't break Template.instance() (#3540)\", function (test) {\n  var tmpl = Template.spacebars_template_test_template_instance_wrapper_outer;\n\n  tmpl.helpers({\n    thisShouldOutputHello: function () {\n      return Template.instance().customProp;\n    }\n  });\n\n  tmpl.created = function () {\n    this.customProp = \"hello\";\n  };\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"hello hello\");\n});\n\ntestAsyncMulti(\"spacebars-tests - template_tests - template-level subscriptions\", [\n  function (test, expect) {\n    var tmpl = Template.spacebars_template_test_template_level_subscriptions;\n    var tmplInstance;\n    var div;\n\n    // Make sure the subscriptions stop when the template is destroyed\n    var stopCallback = expect();\n    var stopCallback2 = expect();\n\n    var futureId = Random.id();\n\n    // Make sure the HTML is what we expect when one subscription is ready\n    var checkOneReady = expect(function () {\n      test.equal(canonicalizeHtml(div.innerHTML), \"\");\n      Meteor.call('makeTemplateSubReady', futureId);\n    });\n\n    // Make sure the HTML is what we expect when both subscriptions are ready\n    var checkBothReady = expect(function () {\n      test.equal(canonicalizeHtml(div.innerHTML), \"ready! true\");\n\n      // This will call the template's destroyed callback\n      Blaze.remove(tmplInstance.view);\n    });\n\n    var subscriptionsFinished = 0;\n\n    // Manually use the subscribe ready callback to make sure the template is\n    // doing the right thing\n    var subscribeCallback = expect(function () {\n      subscriptionsFinished++;\n\n      if (subscriptionsFinished === 1) {\n        // We need to use Tracker.afterFlush here and Tracker.flush doesn't work\n        // because we need to wait for the other callback to fire (the one that\n        // makes ready return true) _and_ we need the UI to rerender\n        Tracker.afterFlush(checkOneReady);\n      }\n\n      if (subscriptionsFinished === 2) {\n        Tracker.afterFlush(checkBothReady);\n      }\n    });\n\n    tmpl.onCreated(function () {\n      var subHandle = this.subscribe(\"templateSub\", subscribeCallback);\n      var subHandle2 = this.subscribe(\"templateSub\", futureId, {\n        onReady: subscribeCallback,\n        connection: Meteor.connection\n      });\n\n      subHandle.stop = stopCallback;\n      subHandle2.stop = stopCallback2;\n\n      tmplInstance = this;\n    });\n\n    // Insertion point\n    div = renderToDiv(tmpl);\n\n    // To start, there is no content because the template isn't ready\n    test.equal(canonicalizeHtml(div.innerHTML), \"\");\n  }\n]);\n\ntestAsyncMulti(\"spacebars-tests - template_tests - template-level subscriptions don't resubscribe unnecessarily\", [\n  function (test, expect) {\n    var tmpl = Template.spacebars_template_test_template_level_subs_resubscribe;\n    var subHandle;\n    var trueThenFalse = new ReactiveVar(true);\n\n    tmpl.helpers({\n      ifArg: function () {\n        return trueThenFalse.get();\n      },\n      subscribingHelper1: expect(function () {\n        subHandle = Template.instance().subscribe(\"templateSub\");\n      }),\n      subscribingHelper2: expect(function () {\n        var subHandle2 = Template.instance().subscribe(\"templateSub\");\n        test.isTrue(subHandle.subscriptionId === subHandle2.subscriptionId);\n\n        // Make sure we didn't add two subscription handles to our internal list\n        test.equal(_.keys(Template.instance()._subscriptionHandles).length, 1);\n      })\n    });\n\n    renderToDiv(tmpl);\n    Tracker.flush();\n    trueThenFalse.set(false);\n  }\n]);\n\nTinytest.add(\"spacebars-tests - template_tests - old #each sets data context\", function (test) {\n  var tmpl = Template.spacebars_template_test_old_each_data_context;\n  tmpl.helpers({\n    items: [{text:\"a\"}, {text:\"b\"}]\n  });\n\n  var div = document.createElement(\"DIV\");\n  var theWith = Blaze.render(tmpl, div);\n  test.equal(canonicalizeHtml(div.innerHTML), '<div>a</div><div>b</div>');\n  var view = Blaze.getView(div.querySelector('div'));\n  Blaze.remove(view);\n});\n\nTinytest.add(\"spacebars-tests - template_tests - new #each extends data context\", function (test) {\n  var tmpl = Template.spacebars_template_test_new_each_data_context;\n  tmpl.helpers({\n    dataContext: function () {\n      return {\n        items: [{text:\"a\"}, {text:\"b\"}],\n        toplevel: \"XYZ\"\n      };\n    }\n  });\n\n  var div = document.createElement(\"DIV\");\n  var theWith = Blaze.render(tmpl, div);\n  test.equal(canonicalizeHtml(div.innerHTML), '<div>a -- XYZ</div><div>b -- XYZ</div>');\n  var view = Blaze.getView(div.querySelector('div'));\n  Blaze.remove(view);\n});\n\n// Same as above, but now the argument to each in has a subexpression\nTinytest.add(\"spacebars-tests - template_tests - new #each with subexpression (#5137)\", function (test) {\n  var tmpl = Template.spacebars_template_test_new_each_data_context_subexpr;\n  tmpl.helpers({\n    dataContext: function () {\n      return {\n        items: [{text:\"a\"}, {text:\"b\"}],\n        toplevel: \"XYZ\"\n      };\n    }\n  });\n\n  var div = document.createElement(\"DIV\");\n  var theWith = Blaze.render(tmpl, div);\n  test.equal(canonicalizeHtml(div.innerHTML), '<div>a -- XYZ</div><div>b -- XYZ</div>');\n  var view = Blaze.getView(div.querySelector('div'));\n  Blaze.remove(view);\n});\n\nTinytest.add(\"spacebars-tests - template_tests - new #each binding lookup is scoped to the template\", function (test) {\n  var tmpl = Template.spacebars_template_test_new_each_lookup_top_level;\n  tmpl.helpers({\n    dataContext: function () {\n      return {\n        letter_a: [\"a\"],\n        subcontext: {\n          letter_b: [\"b\"]\n        }\n      };\n    }\n  });\n\n  var div = document.createElement(\"DIV\");\n  var theWith = Blaze.render(tmpl, div);\n  test.equal(canonicalizeHtml(div.innerHTML), '<div>a</div>');\n  var view = Blaze.getView(div.querySelector('div'));\n  Blaze.remove(view);\n});\n\nTinytest.add(\"spacebars-tests - template_tests - let bindings\", function (test) {\n  var tmpl = Template.spacebars_template_test_let_bindings;\n\n  var v = new ReactiveVar(\"var\");\n  tmpl.helpers({\n    dataContext: function () {\n      return {\n        varFromContext: \"from context\",\n        anotherVarFromContext: \"another var from context\"\n      };\n    },\n    helper: function () {\n      return v.get();\n    }\n  });\n\n  var div = document.createElement(\"DIV\");\n  var theWith = Blaze.render(tmpl, div);\n  test.equal(canonicalizeHtml(div.innerHTML), '<div>var -- var -- from context -- override</div>');\n\n  v.set(\"new var\");\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), '<div>new var -- new var -- from context -- override</div>');\n\n  var view = Blaze.getView(div.querySelector('div'));\n  Blaze.remove(view);\n});\n\nTinytest.add(\"spacebars-tests - template_tests - #each @index\", function (test) {\n  var tmpl = Template.spacebars_template_test_each_index;\n\n  var c = new Mongo.Collection();\n  c.insert({ num: 2 });\n  c.insert({ num: 4 });\n  tmpl.helpers({\n    things: function () {\n      return c.find({}, {sort:{num: 1}});\n    }\n  });\n\n  var div = document.createElement(\"DIV\");\n  var theEach = Blaze.render(tmpl, div);\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>0 - 2</span><span>1 - 4</span>');\n\n  c.insert({ num: 1 });\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>0 - 1</span><span>1 - 2</span><span>2 - 4</span>');\n\n  var three = c.insert({ num: 3 });\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>0 - 1</span><span>1 - 2</span><span>2 - 3</span><span>3 - 4</span>');\n\n  c.update(three, { num: 0 });\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>0 - 0</span><span>1 - 1</span><span>2 - 2</span><span>3 - 4</span>');\n\n  c.remove(three);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), '<span>0 - 1</span><span>1 - 2</span><span>2 - 4</span>');\n\n  var view = Blaze.getView(div.querySelector('span'));\n  Blaze.remove(view);\n});\n\nTinytest.add(\"spacebars-tests - template_tests - nested expressions\", function (test) {\n  var tmpl = Template.spacebars_template_test_nested_exprs;\n\n  tmpl.helpers({\n    add: function (a, b) {\n      return a + b;\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"6\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - nested sub-expressions\", function (test) {\n  var tmpl = Template.spacebars_template_test_nested_subexprs;\n\n  var sentence = new ReactiveVar(\"can't even imagine a world without Light\");\n  tmpl.helpers({\n    capitalize: function (str) {\n      return str.charAt(0).toUpperCase() + str.substring(1);\n    },\n    firstWord: function (sentence) {\n      return sentence.split(' ')[0];\n    },\n    generateSentence: function () {\n      return sentence.get();\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"Can't\");\n\n  sentence.set(\"that would be quite dark\");\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"That\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - expressions as keyword args\", function (test) {\n  var tmpl = Template.spacebars_template_test_exprs_keyword;\n\n  var name = new ReactiveVar(\"light\");\n  tmpl.helpers({\n    capitalize: function (str) {\n      return str.charAt(0).toUpperCase() + str.substring(1);\n    },\n    name: function () {\n      return name.get();\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"Light Mello\");\n\n  name.set(\"misa\");\n  Tracker.flush();\n  test.equal(canonicalizeHtml(div.innerHTML), \"Misa Mello\");\n});\n\nvar testDoesntRerender = function (test, which) {\n  var tmpl = ({\n    \"WITH\": Template.spacebars_template_test_with_rerender,\n    \"LET\": Template.spacebars_template_test_let_rerender\n  })[which];\n\n  var x = new ReactiveVar(\"aaa\");\n  tmpl.helpers({\n    x: function () {\n      return x.get();\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n  var input = div.querySelector('input.foo');\n  var span = div.querySelector('span.bar');\n  test.isTrue(input && input.className === 'foo');\n  test.isTrue(span && span.className === 'bar');\n  test.equal(canonicalizeHtml(span.innerHTML), 'aaa');\n\n  x.set('bbb');\n  Tracker.flush();\n  // make sure the input and span are still the same, but the new\n  // value of x is reflected\n  var input2 = div.querySelector('input.foo');\n  var span2 = div.querySelector('span.bar');\n  test.isTrue(input2 === input, 'input');\n  test.isTrue(span2 === span, 'span');\n  test.equal(canonicalizeHtml(span2.innerHTML), 'bbb');\n};\n\n\nTinytest.add(\"spacebars-tests - template_tests - #with doesn't re-render template\", function (test) {\n  testDoesntRerender(test, \"WITH\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - #let doesn't re-render template\", function (test) {\n  testDoesntRerender(test, \"LET\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - #each takes multiple arguments\", function (test) {\n  var tmpl = Template.spacebars_template_test_each_multiarg;\n  tmpl.helpers({\n    arg: ['a', 'b', 'c'],\n    helper: function (x) { return x; }\n  });\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"<div>a</div><div>b</div><div>c</div>\");\n});\n\nTinytest.add(\"spacebars-tests - template_tests - lexical scope doesn't leak\", function (test) {\n  // make sure '@index' doesn't leak into subtemplates\n  var tmpl = Template.spacebars_template_test_lexical_leakage;\n  tmpl.helpers({\n    list: ['a', 'b', 'c']\n  });\n\n  test.throws(function () {\n    var div = renderToDiv(tmpl);\n  }, /Unsupported directive/);\n});\n\n// PR #5138\nTinytest.add(\"spacebars-tests - template_tests - multiple arguments in each-in\", function (test) {\n  var tmpl = Template.spacebars_template_test_each_in_multi_args;\n  tmpl.helpers({\n    list: ['a', 'b', 'c'],\n    helper: function (list) {\n      return list.reverse();\n    }\n  });\n\n  var div = renderToDiv(tmpl);\n  test.equal(canonicalizeHtml(div.innerHTML), \"<div>c</div><div>b</div><div>a</div>\");\n});\n"
  },
  {
    "path": "packages/spacebars-tests/template_tests_server.js",
    "content": "var path = Npm.require(\"path\");\nvar Future = Npm.require('fibers/future');\n\nMeteor.methods({\n  getAsset: function (filename) {\n    return Assets.getText(path.join(\"assets\", filename));\n  }\n});\n\nvar templateSubFutures = {};\nMeteor.publish(\"templateSub\", function (futureId) {\n  var self = this;\n  Meteor.defer(function () {  // because subs are blocking\n    if (futureId) {\n      var f = new Future();\n      templateSubFutures[futureId] = f;\n      f.wait();\n      delete templateSubFutures[futureId];\n    }\n\n    self.ready();\n  });\n});\nMeteor.methods({\n  makeTemplateSubReady: function (futureId) {\n    templateSubFutures[futureId].return();\n  }\n});\n"
  },
  {
    "path": "packages/spacebars-tests/templating_tests.html",
    "content": "<template name=\"test_assembly_a0\">\n  {{> test_assembly_a1}}\n</template>\n\n<template name=\"test_assembly_a1\">\n  {{> test_assembly_a2}}\n</template>\n\n<template name=\"test_assembly_a2\">\n  {{> test_assembly_a3}}\n</template>\n\n<template name=\"test_assembly_a3\">\n  Hi\n</template>\n\n\n\n<template name=\"test_assembly_b0\">\n  {{> test_assembly_b1}}\n</template>\n\n<template name=\"test_assembly_b1\">\n  x{{#if stuff}}y{{/if}}{{> test_assembly_b2}}\n</template>\n\n<template name=\"test_assembly_b2\">\n  hi\n</template>\n\n\n\n<template name=\"test_table_b0\">\n  <table>\n    <tbody>\n      {{> test_table_b1}}\n      {{> test_table_b1}}\n      {{> test_table_b1}}\n    </tbody>\n  </table>\n</template>\n\n<template name=\"test_table_b1\">\n  <tr>\n    {{> test_table_b2}}\n  </tr>\n</template>\n\n<template name=\"test_table_b2\">\n  <td>\n    {{> test_table_b3}}\n  </td>\n</template>\n\n<template name=\"test_table_b3\">\n  Foo.\n</template>\n\n\n<template name=\"test_table_each\">\n  <table>\n    <tbody>\n      {{#each foo}}\n        <tr><td>{{bar}}</td></tr>\n      {{/each}}\n    </tbody>\n  </table>\n</template>\n\n<template name=\"test_event_data_with\">\n<div>\n  xxx\n  {{#with TWO}}\n    <div>\n      xxx\n      {{#with THREE}}\n        <div>\n          xxx\n        </div>\n      {{/with}}\n    </div>\n  {{/with}}\n</div>\n</template>\n\n<template name=\"test_capture_events\">\n  <video class='video1'>\n    <source id='mp4'\n      src=\"\"\n      type='video/mp4'>\n  </video>\n  <video class='video2'>\n    <source id='mp4'\n      src=\"\"\n      type='video/mp4'>\n  </video>\n  <video class='video2'>\n    <source id='mp4'\n      src=\"\"\n      type='video/mp4'>\n  </video>\n</template>\n\n<template name=\"test_safestring_a\">\n  {{foo}} {{{foo}}} {{bar}} {{{bar}}}\n  {{fooprop}} {{{fooprop}}} {{barprop}} {{{barprop}}}\n</template>\n\n<template name=\"test_helpers_a\">\n  platypus={{platypus}}\n  watermelon={{watermelon}}\n  daisy={{daisy}}\n  tree={{tree}}\n  warthog={{warthog}}\n</template>\n\n<template name=\"test_helpers_b\">\n  unknown={{unknown}}\n  zero={{zero}}\n</template>\n\n<template name=\"test_helpers_c\">\n  platypus.X={{platypus.X}}\n  watermelon.X={{watermelon.X}}\n  daisy.X={{daisy.X}}\n  tree.X={{tree.X}}\n  warthog.X={{warthog.X}}\n  getNull.X={{getNull.X}}\n  getUndefined.X={{getUndefined.X}}\n  getUndefined.X.Y={{getUndefined.X.Y}}\n</template>\n\n<template name=\"test_helpers_d\">\n  daisygetter={{daisygetter}}\n  thisTest={{thisTest}}\n  {{#with fancy}}\n    ../thisTest={{../thisTest}}\n  {{/with}}\n  {{#with \"foo\"}}\n    ../fancy.currentFruit={{../fancy.currentFruit}}\n  {{/with}}\n</template>\n\n<template name=\"test_helpers_e\">\n  fancy.foo={{fancy.foo}}\n  fancy.apple.banana={{fancy.apple.banana}}\n  fancy.currentFruit={{fancy.currentFruit}}\n  fancy.currentCountry.name={{fancy.currentCountry.name}}\n  fancy.currentCountry.population={{fancy.currentCountry.population}}\n  fancy.currentCountry.unicorns={{fancy.currentCountry.unicorns}}\n</template>\n\n<template name=\"test_helpers_f\">\n  fancyhelper.foo={{fancyhelper.foo}}\n  fancyhelper.apple.banana={{fancyhelper.apple.banana}}\n  fancyhelper.currentFruit={{fancyhelper.currentFruit}}\n  fancyhelper.currentCountry.name={{fancyhelper.currentCountry.name}}\n  fancyhelper.currentCountry.population={{fancyhelper.currentCountry.population}}\n  fancyhelper.currentCountry.unicorns={{fancyhelper.currentCountry.unicorns}}\n</template>\n\n<template name=\"test_helpers_g\">\n  platypus={{platypus}}\n  this.platypus={{this.platypus}}\n</template>\n\n<template name=\"test_helpers_h\">\n  (methodListFour 6 7 8 9={{methodListFour 6 7 8 9}})\n  (methodListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns={{methodListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns}})\n  (methodListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns a=platypus b=thisTest c=fancyhelper.currentFruit d=fancyhelper.currentCountry.unicorns={{methodListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns a=platypus b=thisTest c=fancyhelper.currentFruit d=fancyhelper.currentCountry.unicorns}})\n  (helperListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns={{helperListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns}})\n  (helperListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns a=platypus b=thisTest c=fancyhelper.currentFruit d=fancyhelper.currentCountry.unicorns={{helperListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns a=platypus b=thisTest c=fancyhelper.currentFruit d=fancyhelper.currentCountry.unicorns}})\n</template>\n\n<template name=\"test_render_a\">\n  {{foo}}<br><hr>\n</template>\n\n<template name=\"test_render_b\">\n  {{#with 200}}{{foo}}<br><hr>{{/with}}\n</template>\n\n<template name=\"test_render_c\">\n  <br><hr>\n</template>\n\n<template name=\"test_template_arg_a\">\n  <b>Foo</b> <i>Bar</i> <u>Baz</u>\n</template>\n\n<template name=\"test_template_helpers_a\">\n  {{foo}}{{bar}}{{baz}}\n</template>\n\n<template name=\"test_template_helpers_b\">\n  {{name}}{{arity}}{{toString}}{{length}}{{var}}\n</template>\n\n<template name=\"test_template_helpers_c\">\n  {{name}}{{arity}}{{length}}{{var}}x\n</template>\n\n<template name=\"test_template_events_a\">\n  <b>foo</b><u>bar</u><i>baz</i>\n</template>\n\n<template name=\"test_template_events_b\">\n  <b>foo</b><u>bar</u><i>baz</i>\n</template>\n\n<template name=\"test_template_events_c\">\n  <b>foo</b><u>bar</u><i>baz</i>\n</template>\n\n<!-- Test for Issue 617 - Type casting for helpers -->\n<template name=\"test_type_casting\">\n{{testTypeCasting 'true' 'false' true false 0 1 -1 10 -10}}\n</template>\n\n<!-- Test for issue #801 - Each handling of falsy values eg. [1, 2, null, undefined] -->\n<template name=\"test_template_issue801\">\n{{#each values}}{{this}}{{/each}}\n</template>\n\n"
  },
  {
    "path": "packages/spacebars-tests/templating_tests.js",
    "content": "\n// for events to bubble an element needs to be in the DOM.\n// @return {Function} call this for cleanup\nvar addToBody = function (el) {\n  el.style.display = \"none\";\n  document.body.appendChild(el);\n  return function () {\n    document.body.removeChild(el);\n  };\n};\n\n\nTinytest.add(\"spacebars-tests - templating_tests - assembly\", function (test) {\n\n  // Test for a bug that made it to production -- after a replacement,\n  // we need to also check the newly replaced node for replacements\n  var div = renderToDiv(Template.test_assembly_a0);\n  test.equal(canonicalizeHtml(div.innerHTML),\n               \"Hi\");\n\n  // Another production bug -- we must use LiveRange to replace the\n  // placeholder, or risk breaking other LiveRanges\n  Session.set(\"stuff\", true); // XXX bad form to use Session in a test?\n  Template.test_assembly_b1.helpers({\n    stuff: function () {\n      return Session.get(\"stuff\");\n    }\n  });\n  var onscreen = renderToDiv(Template.test_assembly_b0);\n  test.equal(canonicalizeHtml(onscreen.innerHTML), \"xyhi\");\n  Session.set(\"stuff\", false);\n  Tracker.flush();\n  test.equal(canonicalizeHtml(onscreen.innerHTML), \"xhi\");\n  Tracker.flush();\n});\n\n// Test that if a template throws an error, then pending_partials is\n// cleaned up properly (that template rendering doesn't break..)\n\n\n\n\n\n\nTinytest.add(\"spacebars-tests - templating_tests - table assembly\", function(test) {\n  var childWithTag = function(node, tag) {\n    return _.find(node.childNodes, function(n) {\n      return n.nodeName === tag;\n    });\n  };\n\n  // The table.rows test would fail when TR/TD tags are stripped due\n  // to improper html-to-fragment\n  var table = childWithTag(renderToDiv(Template.test_table_b0), \"TABLE\");\n  test.equal(table.rows.length, 3);\n\n  var c = new LocalCollection();\n  c.insert({bar:'a'});\n  c.insert({bar:'b'});\n  c.insert({bar:'c'});\n  var onscreen = renderToDiv(Template.test_table_each, {foo: c.find()});\n  table = childWithTag(onscreen, \"TABLE\");\n\n  test.equal(table.rows.length, 3, table.parentNode.innerHTML);\n  var tds = onscreen.getElementsByTagName(\"TD\");\n  test.equal(tds.length, 3);\n  test.equal(canonicalizeHtml(tds[0].innerHTML), \"a\");\n  test.equal(canonicalizeHtml(tds[1].innerHTML), \"b\");\n  test.equal(canonicalizeHtml(tds[2].innerHTML), \"c\");\n\n  Tracker.flush();\n});\n\nTinytest.add(\"spacebars-tests - templating_tests - event handler this\", function(test) {\n\n  Template.test_event_data_with.helpers({\n    ONE: {str: \"one\"},\n    TWO: {str: \"two\"},\n    THREE: {str: \"three\"}\n  });\n\n  Template.test_event_data_with.events({\n    'click': function(event, template) {\n      test.isTrue(this.str);\n      test.equal(template.data.str, \"one\");\n      event_buf.push(this.str);\n    }\n  });\n\n  var event_buf = [];\n  var containerDiv = renderToDiv(Template.test_event_data_with, {str: \"one\"});\n  var cleanupDiv = addToBody(containerDiv);\n\n  var divs = containerDiv.getElementsByTagName(\"div\");\n  test.equal(3, divs.length);\n\n  clickElement(divs[0]);\n  test.equal(event_buf, ['one']);\n  event_buf.length = 0;\n\n  clickElement(divs[1]);\n  test.equal(event_buf, ['two']);\n  event_buf.length = 0;\n\n  clickElement(divs[2]);\n  test.equal(event_buf, ['three']);\n  event_buf.length = 0;\n\n  cleanupDiv();\n  Tracker.flush();\n});\n\n\nif (document.addEventListener) {\n  // Only run this test on browsers with support for event\n  // capturing. A more detailed analysis can be found at\n  // https://www.meteor.com/blog/2013/09/06/browser-events-bubbling-capturing-and-delegation\n\n  // This is related to issue at https://gist.github.com/mquandalle/8157017\n  // Tests two situations related to events that can only be captured, not bubbled:\n  // 1. Event should only fire the handler that matches the selector given\n  // 2. Event should work on every element in the selector and not just the first element\n  // This test isn't written against mouseenter because it is synthesized by jQuery,\n  // the bug also happened with the play event\n  Tinytest.add(\"spacebars-tests - templating_tests - capturing events\", function (test) {\n    var video1Played = 0,\n        video2Played = 0;\n\n    Template.test_capture_events.events({\n      'play .video1': function () {\n        video1Played++;\n      },\n      'play .video2': function () {\n        video2Played++;\n      }\n    });\n\n    // add to body or else events don't actually fire\n    var containerDiv = renderToDiv(Template.test_capture_events);\n    var cleanupDiv = addToBody(containerDiv);\n\n    var checkAndResetEvents = function(video1, video2) {\n      test.equal(video1Played, video1);\n      test.equal(video2Played, video2);\n\n      video1Played = 0;\n      video2Played = 0;\n    };\n\n    simulateEvent($(containerDiv).find(\".video1\").get(0),\n                  \"play\", {}, {bubbles: false});\n    checkAndResetEvents(1, 0);\n\n    simulateEvent($(containerDiv).find(\".video2\").get(0),\n                  \"play\", {}, {bubbles: false});\n    checkAndResetEvents(0, 1);\n\n    simulateEvent($(containerDiv).find(\".video2\").get(1),\n                  \"play\", {}, {bubbles: false});\n    checkAndResetEvents(0, 1);\n\n    // clean up DOM\n    cleanupDiv();\n    Tracker.flush();\n  });\n}\n\nTinytest.add(\"spacebars-tests - templating_tests - safestring\", function(test) {\n\n  Template.test_safestring_a.helpers({\n    foo: function() {\n      return \"<br>\";\n    },\n    bar: function() {\n      return new Spacebars.SafeString(\"<hr>\");\n    }\n  });\n\n  var obj = {fooprop: \"<br>\",\n             barprop: new Spacebars.SafeString(\"<hr>\")};\n  var html = canonicalizeHtml(\n    renderToDiv(Template.test_safestring_a, obj).innerHTML);\n\n  test.equal(html,\n             \"&lt;br&gt;<br><hr><hr>\"+\n             \"&lt;br&gt;<br><hr><hr>\");\n\n});\n\nTinytest.add(\"spacebars-tests - templating_tests - helpers and dots\", function(test) {\n  Template.registerHelper(\"platypus\", function() {\n    return \"eggs\";\n  });\n  Template.registerHelper(\"watermelon\", function() {\n    return \"seeds\";\n  });\n\n  Template.registerHelper(\"daisygetter\", function() {\n    return this.daisy;\n  });\n\n  // XXX for debugging\n  Template.registerHelper(\"debugger\", function() {\n    debugger;\n  });\n\n  var getFancyObject = function() {\n    return {\n      foo: 'bar',\n      apple: {banana: 'smoothie'},\n      currentFruit: function() {\n        return 'guava';\n      },\n      currentCountry: function() {\n        return {name: 'Iceland',\n                _pop: 321007,\n                population: function() {\n                  return this._pop;\n                },\n                unicorns: 0, // falsy value\n                daisyGetter: function() {\n                  return this.daisy;\n                }\n               };\n      }\n    };\n  };\n\n  Template.registerHelper(\"fancyhelper\", getFancyObject);\n\n  Template.test_helpers_a.helpers({\n    platypus: 'bill',\n    warthog: function() {\n      return 'snout';\n    }\n  });\n\n  var listFour = function(a, b, c, d, options) {\n    test.isTrue(options instanceof Spacebars.kw);\n    var keywordArgs = _.map(_.keys(options.hash), function(k) {\n      var val = options.hash[k];\n      return k+':'+val;\n    });\n    return [a, b, c, d].concat(keywordArgs).join(' ');\n  };\n\n  var dataObj = {\n    zero: 0,\n    platypus: 'weird',\n    watermelon: 'rind',\n    daisy: 'petal',\n    tree: function() { return 'leaf'; },\n    thisTest: function() { return this.tree(); },\n    getNull: function() { return null; },\n    getUndefined: function () { return; },\n    fancy: getFancyObject(),\n    methodListFour: listFour\n  };\n\n  var html;\n  html = canonicalizeHtml(\n    renderToDiv(Template.test_helpers_a, dataObj).innerHTML);\n  test.equal(html.match(/\\S+/g), [\n    'platypus=bill', // helpers on Template object take first priority\n    'watermelon=seeds', // global helpers take second priority\n    'daisy=petal', // unshadowed object property\n    'tree=leaf', // function object property\n    'warthog=snout' // function Template property\n  ]);\n\n  html = canonicalizeHtml(\n    renderToDiv(Template.test_helpers_b, dataObj).innerHTML);\n  test.equal(html.match(/\\S+/g), [\n    // unknown properties silently fail\n    'unknown=',\n    // falsy property comes through\n    'zero=0'\n  ]);\n\n  html = canonicalizeHtml(\n    renderToDiv(Template.test_helpers_c, dataObj).innerHTML);\n  test.equal(html.match(/\\S+/g), [\n    // property gets are supposed to silently fail\n    'platypus.X=',\n    'watermelon.X=',\n    'daisy.X=',\n    'tree.X=',\n    'warthog.X=',\n    'getNull.X=',\n    'getUndefined.X=',\n    'getUndefined.X.Y='\n  ]);\n\n  html = canonicalizeHtml(\n    renderToDiv(Template.test_helpers_d, dataObj).innerHTML);\n  test.equal(html.match(/\\S+/g), [\n    // helpers should get current data context in `this`\n    'daisygetter=petal',\n    // object methods should get object in `this`\n    'thisTest=leaf',\n    // nesting inside {{#with fancy}} shouldn't affect\n    // method\n    '../thisTest=leaf',\n    // combine .. and .\n    '../fancy.currentFruit=guava'\n  ]);\n\n  html = canonicalizeHtml(\n    renderToDiv(Template.test_helpers_e, dataObj).innerHTML);\n  test.equal(html.match(/\\S+/g), [\n    'fancy.foo=bar',\n    'fancy.apple.banana=smoothie',\n    'fancy.currentFruit=guava',\n    'fancy.currentCountry.name=Iceland',\n    'fancy.currentCountry.population=321007',\n    'fancy.currentCountry.unicorns=0'\n  ]);\n\n  html = canonicalizeHtml(\n    renderToDiv(Template.test_helpers_f, dataObj).innerHTML);\n  test.equal(html.match(/\\S+/g), [\n    'fancyhelper.foo=bar',\n    'fancyhelper.apple.banana=smoothie',\n    'fancyhelper.currentFruit=guava',\n    'fancyhelper.currentCountry.name=Iceland',\n    'fancyhelper.currentCountry.population=321007',\n    'fancyhelper.currentCountry.unicorns=0'\n  ]);\n\n  // test significance of 'this', which prevents helper from\n  // shadowing property\n  html = canonicalizeHtml(\n    renderToDiv(Template.test_helpers_g, dataObj).innerHTML);\n  test.equal(html.match(/\\S+/g), [\n    'platypus=eggs',\n    'this.platypus=weird'\n  ]);\n\n  // test interpretation of arguments\n\n  Template.test_helpers_h.helpers({helperListFour: listFour});\n\n  html = canonicalizeHtml(\n    renderToDiv(Template.test_helpers_h, dataObj).innerHTML);\n  var trials =\n        html.match(/\\(.*?\\)/g);\n  test.equal(trials[0],\n             '(methodListFour 6 7 8 9=6 7 8 9)');\n  test.equal(trials[1],\n             '(methodListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns=eggs leaf guava 0)');\n  test.equal(trials[2],\n             '(methodListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns a=platypus b=thisTest c=fancyhelper.currentFruit d=fancyhelper.currentCountry.unicorns=eggs leaf guava 0 a:eggs b:leaf c:guava d:0)');\n  test.equal(trials[3],\n             '(helperListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns=eggs leaf guava 0)');\n  test.equal(trials[4],\n             '(helperListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns a=platypus b=thisTest c=fancyhelper.currentFruit d=fancyhelper.currentCountry.unicorns=eggs leaf guava 0 a:eggs b:leaf c:guava d:0)');\n  test.equal(trials.length, 5);\n\n});\n\n\nTinytest.add(\"spacebars-tests - templating_tests - rendered template\", function(test) {\n  var R = ReactiveVar('foo');\n  Template.test_render_a.helpers({\n    foo: function() {\n      R.get();\n      return this.x + 1;\n    }\n  });\n\n  var div = renderToDiv(Template.test_render_a, {x: 123});\n  test.equal($(div).text().match(/\\S+/)[0], \"124\");\n\n  var br1 = div.getElementsByTagName('br')[0];\n  var hr1 = div.getElementsByTagName('hr')[0];\n  test.isTrue(br1);\n  test.isTrue(hr1);\n\n  R.set('bar');\n  Tracker.flush();\n  var br2 = div.getElementsByTagName('br')[0];\n  var hr2 = div.getElementsByTagName('hr')[0];\n  test.isTrue(br2);\n  test.isTrue(br1 === br2);\n  test.isTrue(hr2);\n  test.isTrue(hr1 === hr2);\n\n  Tracker.flush();\n\n  /////\n\n  R = ReactiveVar('foo');\n\n  Template.test_render_b.helpers({foo: function() {\n    R.get();\n    return (+this) + 1;\n  }});\n\n  div = renderToDiv(Template.test_render_b, {x: 123});\n  test.equal($(div).text().match(/\\S+/)[0], \"201\");\n\n  var br1 = div.getElementsByTagName('br')[0];\n  var hr1 = div.getElementsByTagName('hr')[0];\n  test.isTrue(br1);\n  test.isTrue(hr1);\n\n  R.set('bar');\n  Tracker.flush();\n  var br2 = div.getElementsByTagName('br')[0];\n  var hr2 = div.getElementsByTagName('hr')[0];\n  test.isTrue(br2);\n  test.isTrue(br1 === br2);\n  test.isTrue(hr2);\n  test.isTrue(hr1 === hr2);\n\n  Tracker.flush();\n\n});\n\nTinytest.add(\"spacebars-tests - templating_tests - template arg\", function (test) {\n  Template.test_template_arg_a.events({\n    click: function (event, template) {\n      template.firstNode.innerHTML = 'Hello';\n      template.lastNode.innerHTML = 'World';\n      template.find('i').innerHTML =\n        (template.findAll('*').length)+\"-element\";\n      template.lastNode.innerHTML += ' (the secret is '+\n        template.secret+')';\n    }\n  });\n\n  Template.test_template_arg_a.created = function() {\n    var self = this;\n    test.isFalse(self.firstNode);\n    test.isFalse(self.lastNode);\n    test.throws(function () { return self.find(\"*\"); });\n    test.throws(function () { return self.findAll(\"*\"); });\n  };\n\n  Template.test_template_arg_a.rendered = function () {\n    var template = this;\n    template.firstNode.innerHTML = 'Greetings';\n    template.lastNode.innerHTML = 'Line';\n    template.find('i').innerHTML =\n      (template.findAll('b').length)+\"-bold\";\n    template.secret = \"strawberry \"+template.data.food;\n  };\n\n  Template.test_template_arg_a.destroyed = function() {\n    var self = this;\n    test.isFalse(self.firstNode);\n    test.isFalse(self.lastNode);\n    test.throws(function () { return self.find(\"*\"); });\n    test.throws(function () { return self.findAll(\"*\"); });\n  };\n\n  var div = renderToDiv(Template.test_template_arg_a, {food: \"pie\"});\n  var cleanupDiv = addToBody(div);\n  Tracker.flush(); // cause `rendered` to be called\n  test.equal($(div).text(), \"Greetings 1-bold Line\");\n  clickElement(div.querySelector('i'));\n  test.equal($(div).text(), \"Hello 3-element World (the secret is strawberry pie)\");\n\n  cleanupDiv();\n  Tracker.flush();\n});\n\nTinytest.add(\"spacebars-tests - templating_tests - helpers\", function (test) {\n  var tmpl = Template.test_template_helpers_a;\n\n  tmpl._NOWARN_OLDSTYLE_HELPERS = true;\n  tmpl.foo = 'z';\n  tmpl.helpers({bar: 'b'});\n  // helpers(...) takes precendence of assigned helper\n  tmpl.helpers({foo: 'a', baz: function() { return 'c'; }});\n\n  var div = renderToDiv(tmpl);\n  test.equal($(div).text().match(/\\S+/)[0], 'abc');\n  Tracker.flush();\n\n  tmpl = Template.test_template_helpers_b;\n\n  tmpl.helpers({\n    'name': 'A',\n    'arity': 'B',\n    'toString': 'C',\n    'length': 4,\n    'var': 'D'\n  });\n\n  div = renderToDiv(tmpl);\n  var txt = $(div).text();\n  txt = txt.replace('[object Object]', 'X'); // IE 8\n  txt = txt.match(/\\S+/)[0];\n  test.isTrue(txt.match(/^AB[CX]4D$/));\n  // We don't make helpers with names like toString work in IE 8.\n  test.expect_fail();\n  test.equal(txt, 'ABC4D');\n  Tracker.flush();\n\n  // test that helpers don't \"leak\"\n  tmpl = Template.test_template_helpers_c;\n  div = renderToDiv(tmpl);\n  test.equal($(div).text(), 'x');\n  Tracker.flush();\n});\n\nTinytest.add(\"spacebars-tests - templating_tests - events\", function (test) {\n  var tmpl = Template.test_template_events_a;\n\n  var buf = [];\n\n  // old style\n  tmpl.events = {\n    'click b': function () { buf.push('b'); }\n  };\n\n  var div = renderToDiv(tmpl);\n  var cleanupDiv = addToBody(div);\n  clickElement($(div).find('b')[0]);\n  test.equal(buf, ['b']);\n  cleanupDiv();\n  Tracker.flush();\n\n  ///\n\n  tmpl = Template.test_template_events_b;\n  buf = [];\n  // new style\n  tmpl.events({\n    'click u': function () { buf.push('u'); }\n  });\n  tmpl.events({\n    'click i': function () { buf.push('i'); }\n  });\n\n  div = renderToDiv(tmpl);\n  cleanupDiv = addToBody(div);\n  clickElement($(div).find('u')[0]);\n  clickElement($(div).find('i')[0]);\n  test.equal(buf, ['u', 'i']);\n  cleanupDiv();\n  Tracker.flush();\n\n  //Test for identical callbacks for issue #650\n  tmpl = Template.test_template_events_c;\n  buf = [];\n  tmpl.events({\n    'click u': function () { buf.push('a'); }\n  });\n  tmpl.events({\n    'click u': function () { buf.push('b'); }\n  });\n\n  div = renderToDiv(tmpl);\n  cleanupDiv = addToBody(div);\n  clickElement($(div).find('u')[0]);\n  test.equal(buf.length, 2);\n  test.isTrue(_.contains(buf, 'a'));\n  test.isTrue(_.contains(buf, 'b'));\n  cleanupDiv();\n  Tracker.flush();\n});\n\n\nTinytest.add('spacebars-tests - templating_tests - helper typecast Issue #617', function (test) {\n\n  Template.registerHelper('testTypeCasting', function (/*arguments*/) {\n    // Return a string representing the arguments passed to this\n    // function, including types. eg:\n    // (1, true) -> \"[number,1][boolean,true]\"\n    return _.reduce(_.toArray(arguments), function (memo, arg) {\n      if (typeof arg === 'object')\n        return memo + \"[object]\";\n      return memo + \"[\" + typeof arg + \",\" + arg + \"]\";\n    }, \"\");\n    return x;\n  });\n\n  var div = renderToDiv(Template.test_type_casting);\n  var result = canonicalizeHtml(div.innerHTML);\n  test.equal(\n    result,\n    // This corresponds to entries in templating_tests.html.\n    // true/faslse\n    \"[string,true][string,false][boolean,true][boolean,false]\" +\n      // numbers\n      \"[number,0][number,1][number,-1][number,10][number,-10]\" +\n      // handlebars 'options' argument. appended to args of all helpers.\n      \"[object]\");\n});\n\nTinytest.add('spacebars-tests - templating_tests - each falsy Issue #801', function (test) {\n  //Minor test for issue #801 (#each over array containing nulls)\n  Template.test_template_issue801.helpers({\n    values: function() { return [0,1,2,null,undefined,false]; }});\n  var div = renderToDiv(Template.test_template_issue801);\n  test.equal(canonicalizeHtml(div.innerHTML), \"012\");\n});\n\nTinytest.add('spacebars-tests - templating_tests - duplicate template error', function (test) {\n  Template.__checkName(\"test_duplicate_template\");\n  Template.test_duplicate_template = new Template(\n    \"dup\", function () { return null; });\n\n  test.throws(function () {\n    Template.__checkName(\"test_duplicate_template\");\n  });\n});\n\nTinytest.add('spacebars-tests - templating_tests - reserved template name error', function (test) {\n\n  _.each('length __proto__ prototype name body currentData instance'.split(' '),\n         function (name) {\n           test.throws(function () {\n             Template.__checkName(name);\n           }, /This template name is reserved: /);\n         });\n});\n"
  },
  {
    "path": "packages/spiderable/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/spiderable/README.md",
    "content": "# spiderable\n\n`spiderable` is part of [Webapp](https://www.meteor.com/webapp). It's one possible way to allow web search engines to index a Meteor application. It uses the [AJAX Crawling specification](https://developers.google.com/webmasters/ajax-crawling/) published by Google to serve HTML to compatible spiders (Google, Bing, Yandex, and more).\n\nWhen a spider requests an HTML snapshot of a page the Meteor server runs the client half of the application inside [phantomjs](http://phantomjs.org/), a headless browser, and returns the full HTML generated by the client code.\n\nIn order to have links between multiple pages on a site visible to spiders, apps must use real links (eg `<a href=\"/about\">`) rather than simply re-rendering portions of the page when an element is clicked. Apps should render their content based on the URL of the page and can use [HTML5 pushState](https://developer.mozilla.org/en-US/docs/DOM/Manipulating_the_browser_history) to alter the URL on the client without triggering a page reload. See the [Todos example](http://meteor.com/examples/todos) for a demonstration.\n\nWhen running your page, `spiderable` will wait for all publications to be ready. Make sure that all of your [`publish functions`](#meteor_publish) either return a cursor (or an array of cursors), or eventually call [`this.ready()`](#publish_ready). Otherwise, the `phantomjs` executions will fail.\n\n## Notes\n\nIf you deploy your application with `meteor bundle`, you must install `phantomjs` ([http://phantomjs.org](http://phantomjs.org/)) somewhere in your `$PATH`. If you use `meteor deploy` this is already taken care of.\n"
  },
  {
    "path": "packages/spiderable/package.js",
    "content": "Package.describe({\n  summary: \"Makes the application crawlable to web spiders\",\n  version: \"1.0.13\"\n});\n\nPackage.onUse(function (api) {\n  api.use('webapp', 'server');\n  api.use(['ddp', 'tracker'], 'client');\n  api.use(['callback-hook'], 'client');\n  api.use(['templating'], 'client');\n  api.use(['underscore'], ['client', 'server']);\n\n  api.export('Spiderable');\n\n  api.addFiles('spiderable.html', 'client');\n  api.addFiles('spiderable.js', ['client', 'server']);\n  api.addFiles('spiderable_server.js', 'server');\n  api.addFiles('spiderable_client.js', 'client');\n\n  api.addAssets('phantom_script.js', 'server');\n});\n\nPackage.onTest(function (api) {\n  api.use(['spiderable', 'tinytest', 'underscore', 'ddp']);\n  api.addFiles('spiderable_client_tests.js', 'client');\n  api.addFiles('spiderable_server_tests.js', 'server');\n});\n"
  },
  {
    "path": "packages/spiderable/phantom_script.js",
    "content": "// 'url' is assigned to in a statement before this.\nvar page = require('webpage').create();\n\nvar isReady = function () {\n  return page.evaluate(function () {\n    if (typeof Meteor === 'undefined'\n        || Meteor.status === undefined\n        || !Meteor.status().connected) {\n      return false;\n    }\n    if (typeof Package === 'undefined'\n        || Package.spiderable === undefined\n        || Package.spiderable.Spiderable === undefined) {\n      return false;\n    }\n    return Package.spiderable.Spiderable.isReady();\n  });\n};\n\nvar dumpPageContent = function () {\n  var out = page.content;\n  out = out.replace(/<script[^>]+>(.|\\n|\\r)*?<\\/script\\s*>/ig, '');\n  out = out.replace('<meta name=\"fragment\" content=\"!\">', '');\n  console.log(out);\n};\n\npage.open(url, function(status) {\n  if (status === 'fail')\n    phantom.exit();\n});\n\nsetInterval(function() {\n  if (isReady()) {\n    dumpPageContent();\n    phantom.exit();\n  }\n}, 100);\n"
  },
  {
    "path": "packages/spiderable/spiderable.html",
    "content": "<head><meta name=\"fragment\" content=\"!\"></head>\n"
  },
  {
    "path": "packages/spiderable/spiderable.js",
    "content": "Spiderable = {};\n\n"
  },
  {
    "path": "packages/spiderable/spiderable_client.js",
    "content": "// We want to provide a deteriministic indicator of when the page is 'done'\n// This is non-trivial: e.g. an infinite stream of tweets is never done.\n//\n// We do this instead:\n//   We are done sometime after all initial subscriptions are ready\n//   Initial subscriptions are those started in the top-level script execution,\n//   or from a Meteor.startup callback when Meteor.startup is called in\n//   top-level script execution.\n//\n// Note that we don't guarantee that we won't wait longer than we have to;\n// extra subscriptions may be made, and extra data past the minimum may be\n// received.\n//\n// We set this 'started' flag as Package.spiderable.Spiderable._initialSubscriptionsStarted\n// This is used by our phantomjs to determine when the subscriptions are started;\n// it then polls until all subscriptions are ready.\n\nSpiderable._initialSubscriptionsStarted = false;\n\nSpiderable._onReadyHook = new Hook({\n  debugPrintExceptions: \"Spiderable.addReadyCondition callback\"\n});\n\n// register a new onReady hook for validation\nSpiderable.addReadyCondition = function (fn) {\n  return Spiderable._onReadyHook.register(fn);\n};\n\n//\n// register default hooks\n\n// top level code ready\nSpiderable.addReadyCondition(function () {\n  // subs & top level code (startup) completed\n  return Spiderable._initialSubscriptionsStarted;\n})\nvar startupCallbacksDone = function () {\n  Spiderable._initialSubscriptionsStarted = true;\n};\n// This extra indirection is how we get called last\nvar topLevelCodeDone = function () {\n  // We'd like to use Meteor.startup here I think, but docs/behaviour of that is wrong\n  Meteor._setImmediate(function () { startupCallbacksDone(); });\n};\nMeteor.startup(function () { topLevelCodeDone(); });\n\n// all ddp subs ready\nSpiderable.addReadyCondition(function () {\n  Tracker.flush();\n  return DDP._allSubscriptionsReady();\n})\n\n// run all hooks and return true if they all pass\nSpiderable.isReady = function () {\n  var isReady = true;\n  Spiderable._onReadyHook.each(function (callback) {\n    if (callback()) {\n      return true; // next callback\n    } else {\n      isReady = false;\n      return false; // stop immediately\n    }\n  });\n  return isReady;\n};\n\n"
  },
  {
    "path": "packages/spiderable/spiderable_client_tests.js",
    "content": "Tinytest.add(\"spiderable - default hooks registered\", function (test, expect) {\n  test.equal(\n    _.keys(Spiderable._onReadyHook.callbacks).length,\n    2\n  );\n});\n\nTinytest.add(\"spiderable - is not ready while initial subscriptions aren't started\", function (test, expect) {\n  var original = Spiderable._initialSubscriptionsStarted;\n\n  Spiderable._initialSubscriptionsStarted = false;\n  test.isFalse(Spiderable.isReady());\n\n  Spiderable._initialSubscriptionsStarted = original;\n});\n\nTinytest.add(\"spiderable - is not ready while DDP Subscriptions aren't ready\", function (test, expect) {\n  var original = DDP._allSubscriptionsReady;\n\n  Spiderable._initialSubscriptionsStarted = true;\n  DDP._allSubscriptionsReady = function () { return false; };\n\n  test.isFalse(Spiderable.isReady());\n\n  // restore original\n  DDP._allSubscriptionsReady = original;\n});\n\nTinytest.add(\"spiderable - default hooks can ready\", function (test, expect) {\n  var original = DDP._allSubscriptionsReady;\n\n  Spiderable._initialSubscriptionsStarted = true;\n  DDP._allSubscriptionsReady = function () { return true; };\n\n  test.isTrue(Spiderable.isReady());\n\n  // restore original\n  DDP._allSubscriptionsReady = original;\n});\n\nTinytest.add(\"spiderable - is not ready with a custom hook\", function (test, expect) {\n  var callbacks = {}\n  test.equal(\n    _.keys(Spiderable._onReadyHook.callbacks).length,\n    2\n  );\n\n  //clear all/default callbacks\n  _.each(Spiderable._onReadyHook.callbacks, function (value,key,list) {\n    callbacks[key] = value;\n    delete list[key];\n  });\n  test.equal(\n    _.keys(Spiderable._onReadyHook.callbacks).length,\n    0\n  );\n\n\n  // actually test not ready\n  Spiderable.addReadyCondition(function () { return false; });\n  test.isFalse(Spiderable.isReady());\n\n\n  // clear new callback\n  _.each(Spiderable._onReadyHook.callbacks, function (value,key,list) {\n    delete list[key];\n  });\n  test.equal(\n    _.keys(Spiderable._onReadyHook.callbacks).length,\n    0\n  );\n\n  // restore callbacks\n  _.each(callbacks, function (value,key,list) {\n    Spiderable._onReadyHook.callbacks[key] = value;\n  });\n  test.equal(\n    _.keys(Spiderable._onReadyHook.callbacks).length,\n    2\n  );\n});\n\nTinytest.add(\"spiderable - is ready with a custom hook\", function (test, expect) {\n  var callbacks = {}\n  test.equal(\n    _.keys(Spiderable._onReadyHook.callbacks).length,\n    2\n  );\n\n  //clear all callbacks\n  _.each(Spiderable._onReadyHook.callbacks, function (value,key,list) {\n    callbacks[key] = value;\n    delete list[key];\n  });\n  test.equal(\n    _.keys(Spiderable._onReadyHook.callbacks).length,\n    0\n  );\n\n\n  // actually test ready\n  Spiderable.addReadyCondition(function () { return true; });\n  test.isTrue(Spiderable.isReady());\n\n\n  // clear new callback\n  _.each(Spiderable._onReadyHook.callbacks, function (value,key,list) {\n    delete list[key];\n  });\n  test.equal(\n    _.keys(Spiderable._onReadyHook.callbacks).length,\n    0\n  );\n\n  // restore callbacks\n  _.each(callbacks, function (value,key,list) {\n    Spiderable._onReadyHook.callbacks[key] = value;\n  });\n  test.equal(\n    _.keys(Spiderable._onReadyHook.callbacks).length,\n    2\n  );\n});\n"
  },
  {
    "path": "packages/spiderable/spiderable_server.js",
    "content": "var fs = Npm.require('fs');\nvar child_process = Npm.require('child_process');\nvar querystring = Npm.require('querystring');\nvar urlParser = Npm.require('url');\n\n// list of bot user agents that we want to serve statically, but do\n// not obey the _escaped_fragment_ protocol. The page is served\n// statically to any client whos user agent matches any of these\n// regexps. Users may modify this array.\n//\n// An original goal with the spiderable package was to avoid doing\n// user-agent based tests. But the reality is not enough bots support\n// the _escaped_fragment_ protocol, so we need to hardcode a list\n// here. I shed a silent tear.\nSpiderable.userAgentRegExps = [\n  /^facebookexternalhit/i,\n  /^Facebot/,\n  /^linkedinbot/i,\n  /^twitterbot/i,\n  /^slackbot-linkexpanding/i\n];\n\n// how long to let phantomjs run before we kill it (and send down the\n// regular page instead). Users may modify this number.\nSpiderable.requestTimeoutMs = 15*1000;\n// maximum size of result HTML. node's default is 200k which is too\n// small for our docs.\nvar MAX_BUFFER = 5*1024*1024; // 5MB\n\n// Exported for tests.\nSpiderable._urlForPhantom = function (siteAbsoluteUrl, requestUrl) {\n  // reassembling url without escaped fragment if exists\n  var parsedUrl = urlParser.parse(requestUrl);\n  var parsedQuery = querystring.parse(parsedUrl.query);\n  var escapedFragment = parsedQuery['_escaped_fragment_'];\n  delete parsedQuery['_escaped_fragment_'];\n\n  var parsedAbsoluteUrl = urlParser.parse(siteAbsoluteUrl);\n  // If the ROOT_URL contains a path, Meteor strips that path off of the\n  // request's URL before we see it. So we concatenate the pathname from\n  // the request's URL with the root URL's pathname to get the full\n  // pathname.\n  if (parsedUrl.pathname.charAt(0) === \"/\") {\n    parsedUrl.pathname = parsedUrl.pathname.substring(1);\n  }\n  parsedAbsoluteUrl.pathname = urlParser.resolve(parsedAbsoluteUrl.pathname,\n                                                 parsedUrl.pathname);\n  parsedAbsoluteUrl.query = parsedQuery;\n  // `url.format` will only use `query` if `search` is absent\n  parsedAbsoluteUrl.search = null;\n\n  if (escapedFragment !== undefined && escapedFragment !== null && escapedFragment.length > 0) {\n    parsedAbsoluteUrl.hash = '!' + decodeURIComponent(escapedFragment);\n  }\n\n  return urlParser.format(parsedAbsoluteUrl);\n};\n\nvar PHANTOM_SCRIPT = Assets.getText(\"phantom_script.js\");\n\nWebApp.connectHandlers.use(function (req, res, next) {\n  // _escaped_fragment_ comes from Google's AJAX crawling spec:\n  // https://developers.google.com/webmasters/ajax-crawling/docs/specification\n  if (/\\?.*_escaped_fragment_=/.test(req.url) ||\n      _.any(Spiderable.userAgentRegExps, function (re) {\n        return re.test(req.headers['user-agent']); })) {\n\n    var url = Spiderable._urlForPhantom(Meteor.absoluteUrl(), req.url);\n\n    // This string is going to be put into a bash script, so it's important\n    // that 'url' (which comes from the network) can neither exploit phantomjs\n    // or the bash script. JSON stringification should prevent it from\n    // exploiting phantomjs, and since the output of JSON.stringify shouldn't\n    // be able to contain newlines, it should be unable to exploit bash as\n    // well.\n    var phantomScript = \"var url = \" + JSON.stringify(url) + \";\" +\n          PHANTOM_SCRIPT;\n\n    // Allow override of phantomjs args via env var\n    // We use one env var to try to keep env-var explosion under control.\n    // We're not going to document this unless it is actually needed;\n    // (if you find yourself needing this please let us know the use case!)\n    var phantomJsArgs = process.env.METEOR_PKG_SPIDERABLE_PHANTOMJS_ARGS || '';\n\n    // Default image loading to off (we don't need images)\n    if (phantomJsArgs.indexOf(\"--load-images=\") === -1) {\n      phantomJsArgs += \" --load-images=no\";\n    }\n\n    // POODLE means SSLv3 is being turned off everywhere.\n    // phantomjs currently defaults to SSLv3, and won't use TLS.\n    // Use --ssl-protocol to set the default to TLSv1\n    // (another option would be 'any', but really, we want to say >= TLSv1)\n    // More info: https://groups.google.com/forum/#!topic/meteor-core/uZhT3AHwpsI\n    if (phantomJsArgs.indexOf(\"--ssl-protocol=\") === -1) {\n      phantomJsArgs += \" --ssl-protocol=TLSv1\";\n    }\n\n    // Run phantomjs.\n    //\n    // Use '/dev/stdin' to avoid writing to a temporary file. We can't\n    // just omit the file, as PhantomJS takes that to mean 'use a\n    // REPL' and exits as soon as stdin closes.\n    //\n    // However, Node 0.8 broke the ability to open /dev/stdin in the\n    // subprocess, so we can't just write our string to the process's stdin\n    // directly; see https://gist.github.com/3751746 for the gory details. We\n    // work around this with a bash heredoc. (We previous used a \"cat |\"\n    // instead, but that meant we couldn't use exec and had to manage several\n    // processes.)\n    child_process.execFile(\n      '/usr/bin/env',\n      ['bash', '-c',\n       (\"exec phantomjs \" + phantomJsArgs + \" /dev/stdin <<'END'\\n\" +\n        phantomScript + \"END\\n\")],\n      {timeout: Spiderable.requestTimeoutMs, maxBuffer: MAX_BUFFER},\n      function (error, stdout, stderr) {\n        if (!error && /<html/i.test(stdout)) {\n          res.writeHead(200, {'Content-Type': 'text/html; charset=UTF-8'});\n          res.end(stdout);\n        } else {\n          // phantomjs failed. Don't send the error, instead send the\n          // normal page.\n          if (error && error.code === 127)\n            Meteor._debug(\"spiderable: phantomjs not installed. Download and install from http://phantomjs.org/\");\n          else\n            Meteor._debug(\"spiderable: phantomjs failed at \" + url + \":\", error, \"\\nstderr:\", stderr, \"\\nstdout:\", stdout);\n\n          next();\n        }\n      });\n  } else {\n    next();\n  }\n});\n"
  },
  {
    "path": "packages/spiderable/spiderable_server_tests.js",
    "content": "var url = Npm.require(\"url\");\n\nTinytest.add(\"spiderable - phantom url generation\", function (test, expect) {\n  var absUrl = \"http://example.com\";\n  _.each([\n    // Requests resulting from `<meta name=\"fragment\" content=\"!\">`\n    // will have an `_escaped_fragment_` which is present but blank,\n    // which we want to represent as having no hash fragment\n    // parameter.  (Note this means we cannot distinguish between `/`\n    // and `/#!`).\n    {\n      requestUrl: \"/?_escaped_fragment_=\",\n      expected: \"/\"\n    },\n    // Test that a nonempty fragment is tunneled through to the generated URL\n    {\n      requestUrl: \"/?_escaped_fragment_=1\",\n      expected: \"/#!1\"\n    },\n    // Test decoding the encoded escaped fragment.\n    {\n      requestUrl: \"/?_escaped_fragment_=abc%3D123%26def%3D456\",\n      expected: \"/#!abc=123&def=456\"\n    },\n    // Test that query strings are preserved\n    {\n      requestUrl: \"/?_escaped_fragment_=1&foo=bar\",\n      expected: \"/?foo=bar#!1\"\n    },\n    {\n      requestUrl: \"/?foo=bar&_escaped_fragment_=1\",\n      expected: \"/?foo=bar#!1\"\n    },\n    // Test that paths are preserved\n    {\n      requestUrl: \"/foo/bar?_escaped_fragment_=1\",\n      expected: \"/foo/bar#!1\"\n    },\n    {\n      requestUrl: \"/foo/bar?_escaped_fragment_=1&foo=bar\",\n      expected: \"/foo/bar?foo=bar#!1\"\n    },\n    // Test with a path on the site's absolute url\n    {\n      requestUrl: \"/foo/bar?_escaped_fragment_=1\",\n      expected: \"/foo/bar#!1\",\n      absUrl: \"http://example.com/foo\"\n    },\n    {\n      requestUrl: \"/bar?_escaped_fragment_=1\",\n      expected: \"/bar#!1\",\n      absUrl: \"http://example.com/foo\"\n    }\n  ], function (testCase) {\n    testCase.absUrl = testCase.absUrl || absUrl;\n\n    test.equal(\n      Spiderable._urlForPhantom(absUrl, testCase.requestUrl),\n      absUrl + testCase.expected\n    );\n  });\n});\n"
  },
  {
    "path": "packages/srp/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/srp/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/srp/biginteger.js",
    "content": "/// METEOR WRAPPER\nBigInteger = (function () {\n\n\n/// BEGIN jsbn.js\n\n/*\n * Copyright (c) 2003-2005  Tom Wu\n * All Rights Reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS-IS\" AND WITHOUT WARRANTY OF ANY KIND, \n * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY \n * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  \n *\n * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,\n * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER\n * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF\n * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT\n * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n *\n * In addition, the following condition applies:\n *\n * All redistributions must retain an intact copy of this copyright notice\n * and disclaimer.\n */\n\n// Basic JavaScript BN library - subset useful for RSA encryption.\n\n// Bits per digit\nvar dbits;\n\n// JavaScript engine analysis\nvar canary = 0xdeadbeefcafe;\nvar j_lm = ((canary&0xffffff)==0xefcafe);\n\n// (public) Constructor\nfunction BigInteger(a,b,c) {\n  if(a != null)\n    if(\"number\" == typeof a) this.fromNumber(a,b,c);\n    else if(b == null && \"string\" != typeof a) this.fromString(a,256);\n    else this.fromString(a,b);\n}\n\n// return new, unset BigInteger\nfunction nbi() { return new BigInteger(null); }\n\n// am: Compute w_j += (x*this_i), propagate carries,\n// c is initial carry, returns final carry.\n// c < 3*dvalue, x < 2*dvalue, this_i < dvalue\n// We need to select the fastest one that works in this environment.\n\n// am1: use a single mult and divide to get the high bits,\n// max digit bits should be 26 because\n// max internal value = 2*dvalue^2-2*dvalue (< 2^53)\nfunction am1(i,x,w,j,c,n) {\n  while(--n >= 0) {\n    var v = x*this[i++]+w[j]+c;\n    c = Math.floor(v/0x4000000);\n    w[j++] = v&0x3ffffff;\n  }\n  return c;\n}\n// am2 avoids a big mult-and-extract completely.\n// Max digit bits should be <= 30 because we do bitwise ops\n// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)\nfunction am2(i,x,w,j,c,n) {\n  var xl = x&0x7fff, xh = x>>15;\n  while(--n >= 0) {\n    var l = this[i]&0x7fff;\n    var h = this[i++]>>15;\n    var m = xh*l+h*xl;\n    l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);\n    c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);\n    w[j++] = l&0x3fffffff;\n  }\n  return c;\n}\n// Alternately, set max digit bits to 28 since some\n// browsers slow down when dealing with 32-bit numbers.\nfunction am3(i,x,w,j,c,n) {\n  var xl = x&0x3fff, xh = x>>14;\n  while(--n >= 0) {\n    var l = this[i]&0x3fff;\n    var h = this[i++]>>14;\n    var m = xh*l+h*xl;\n    l = xl*l+((m&0x3fff)<<14)+w[j]+c;\n    c = (l>>28)+(m>>14)+xh*h;\n    w[j++] = l&0xfffffff;\n  }\n  return c;\n}\n\n/* XXX METEOR XXX\nif(j_lm && (navigator.appName == \"Microsoft Internet Explorer\")) {\n  BigInteger.prototype.am = am2;\n  dbits = 30;\n}\nelse if(j_lm && (navigator.appName != \"Netscape\")) {\n  BigInteger.prototype.am = am1;\n  dbits = 26;\n}\nelse \n*/\n\n{ // Mozilla/Netscape seems to prefer am3\n  BigInteger.prototype.am = am3;\n  dbits = 28;\n}\n\nBigInteger.prototype.DB = dbits;\nBigInteger.prototype.DM = ((1<<dbits)-1);\nBigInteger.prototype.DV = (1<<dbits);\n\nvar BI_FP = 52;\nBigInteger.prototype.FV = Math.pow(2,BI_FP);\nBigInteger.prototype.F1 = BI_FP-dbits;\nBigInteger.prototype.F2 = 2*dbits-BI_FP;\n\n// Digit conversions\nvar BI_RM = \"0123456789abcdefghijklmnopqrstuvwxyz\";\nvar BI_RC = new Array();\nvar rr,vv;\nrr = \"0\".charCodeAt(0);\nfor(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;\nrr = \"a\".charCodeAt(0);\nfor(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;\nrr = \"A\".charCodeAt(0);\nfor(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;\n\nfunction int2char(n) { return BI_RM.charAt(n); }\nfunction intAt(s,i) {\n  var c = BI_RC[s.charCodeAt(i)];\n  return (c==null)?-1:c;\n}\n\n// (protected) copy this to r\nfunction bnpCopyTo(r) {\n  for(var i = this.t-1; i >= 0; --i) r[i] = this[i];\n  r.t = this.t;\n  r.s = this.s;\n}\n\n// (protected) set from integer value x, -DV <= x < DV\nfunction bnpFromInt(x) {\n  this.t = 1;\n  this.s = (x<0)?-1:0;\n  if(x > 0) this[0] = x;\n  else if(x < -1) this[0] = x+DV;\n  else this.t = 0;\n}\n\n// return bigint initialized to value\nfunction nbv(i) { var r = nbi(); r.fromInt(i); return r; }\n\n// (protected) set from string and radix\nfunction bnpFromString(s,b) {\n  var k;\n  if(b == 16) k = 4;\n  else if(b == 8) k = 3;\n  else if(b == 256) k = 8; // byte array\n  else if(b == 2) k = 1;\n  else if(b == 32) k = 5;\n  else if(b == 4) k = 2;\n  else { this.fromRadix(s,b); return; }\n  this.t = 0;\n  this.s = 0;\n  var i = s.length, mi = false, sh = 0;\n  while(--i >= 0) {\n    var x = (k==8)?s[i]&0xff:intAt(s,i);\n    if(x < 0) {\n      if(s.charAt(i) == \"-\") mi = true;\n      continue;\n    }\n    mi = false;\n    if(sh == 0)\n      this[this.t++] = x;\n    else if(sh+k > this.DB) {\n      this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;\n      this[this.t++] = (x>>(this.DB-sh));\n    }\n    else\n      this[this.t-1] |= x<<sh;\n    sh += k;\n    if(sh >= this.DB) sh -= this.DB;\n  }\n  if(k == 8 && (s[0]&0x80) != 0) {\n    this.s = -1;\n    if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;\n  }\n  this.clamp();\n  if(mi) BigInteger.ZERO.subTo(this,this);\n}\n\n// (protected) clamp off excess high words\nfunction bnpClamp() {\n  var c = this.s&this.DM;\n  while(this.t > 0 && this[this.t-1] == c) --this.t;\n}\n\n// (public) return string representation in given radix\nfunction bnToString(b) {\n  if(this.s < 0) return \"-\"+this.negate().toString(b);\n  var k;\n  if(b == 16) k = 4;\n  else if(b == 8) k = 3;\n  else if(b == 2) k = 1;\n  else if(b == 32) k = 5;\n  else if(b == 4) k = 2;\n  else return this.toRadix(b);\n  var km = (1<<k)-1, d, m = false, r = \"\", i = this.t;\n  var p = this.DB-(i*this.DB)%k;\n  if(i-- > 0) {\n    if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }\n    while(i >= 0) {\n      if(p < k) {\n        d = (this[i]&((1<<p)-1))<<(k-p);\n        d |= this[--i]>>(p+=this.DB-k);\n      }\n      else {\n        d = (this[i]>>(p-=k))&km;\n        if(p <= 0) { p += this.DB; --i; }\n      }\n      if(d > 0) m = true;\n      if(m) r += int2char(d);\n    }\n  }\n  return m?r:\"0\";\n}\n\n// (public) -this\nfunction bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }\n\n// (public) |this|\nfunction bnAbs() { return (this.s<0)?this.negate():this; }\n\n// (public) return + if this > a, - if this < a, 0 if equal\nfunction bnCompareTo(a) {\n  var r = this.s-a.s;\n  if(r != 0) return r;\n  var i = this.t;\n  r = i-a.t;\n  if(r != 0) return r;\n  while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;\n  return 0;\n}\n\n// returns bit length of the integer x\nfunction nbits(x) {\n  var r = 1, t;\n  if((t=x>>>16) != 0) { x = t; r += 16; }\n  if((t=x>>8) != 0) { x = t; r += 8; }\n  if((t=x>>4) != 0) { x = t; r += 4; }\n  if((t=x>>2) != 0) { x = t; r += 2; }\n  if((t=x>>1) != 0) { x = t; r += 1; }\n  return r;\n}\n\n// (public) return the number of bits in \"this\"\nfunction bnBitLength() {\n  if(this.t <= 0) return 0;\n  return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));\n}\n\n// (protected) r = this << n*DB\nfunction bnpDLShiftTo(n,r) {\n  var i;\n  for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];\n  for(i = n-1; i >= 0; --i) r[i] = 0;\n  r.t = this.t+n;\n  r.s = this.s;\n}\n\n// (protected) r = this >> n*DB\nfunction bnpDRShiftTo(n,r) {\n  for(var i = n; i < this.t; ++i) r[i-n] = this[i];\n  r.t = Math.max(this.t-n,0);\n  r.s = this.s;\n}\n\n// (protected) r = this << n\nfunction bnpLShiftTo(n,r) {\n  var bs = n%this.DB;\n  var cbs = this.DB-bs;\n  var bm = (1<<cbs)-1;\n  var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;\n  for(i = this.t-1; i >= 0; --i) {\n    r[i+ds+1] = (this[i]>>cbs)|c;\n    c = (this[i]&bm)<<bs;\n  }\n  for(i = ds-1; i >= 0; --i) r[i] = 0;\n  r[ds] = c;\n  r.t = this.t+ds+1;\n  r.s = this.s;\n  r.clamp();\n}\n\n// (protected) r = this >> n\nfunction bnpRShiftTo(n,r) {\n  r.s = this.s;\n  var ds = Math.floor(n/this.DB);\n  if(ds >= this.t) { r.t = 0; return; }\n  var bs = n%this.DB;\n  var cbs = this.DB-bs;\n  var bm = (1<<bs)-1;\n  r[0] = this[ds]>>bs;\n  for(var i = ds+1; i < this.t; ++i) {\n    r[i-ds-1] |= (this[i]&bm)<<cbs;\n    r[i-ds] = this[i]>>bs;\n  }\n  if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;\n  r.t = this.t-ds;\n  r.clamp();\n}\n\n// (protected) r = this - a\nfunction bnpSubTo(a,r) {\n  var i = 0, c = 0, m = Math.min(a.t,this.t);\n  while(i < m) {\n    c += this[i]-a[i];\n    r[i++] = c&this.DM;\n    c >>= this.DB;\n  }\n  if(a.t < this.t) {\n    c -= a.s;\n    while(i < this.t) {\n      c += this[i];\n      r[i++] = c&this.DM;\n      c >>= this.DB;\n    }\n    c += this.s;\n  }\n  else {\n    c += this.s;\n    while(i < a.t) {\n      c -= a[i];\n      r[i++] = c&this.DM;\n      c >>= this.DB;\n    }\n    c -= a.s;\n  }\n  r.s = (c<0)?-1:0;\n  if(c < -1) r[i++] = this.DV+c;\n  else if(c > 0) r[i++] = c;\n  r.t = i;\n  r.clamp();\n}\n\n// (protected) r = this * a, r != this,a (HAC 14.12)\n// \"this\" should be the larger one if appropriate.\nfunction bnpMultiplyTo(a,r) {\n  var x = this.abs(), y = a.abs();\n  var i = x.t;\n  r.t = i+y.t;\n  while(--i >= 0) r[i] = 0;\n  for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);\n  r.s = 0;\n  r.clamp();\n  if(this.s != a.s) BigInteger.ZERO.subTo(r,r);\n}\n\n// (protected) r = this^2, r != this (HAC 14.16)\nfunction bnpSquareTo(r) {\n  var x = this.abs();\n  var i = r.t = 2*x.t;\n  while(--i >= 0) r[i] = 0;\n  for(i = 0; i < x.t-1; ++i) {\n    var c = x.am(i,x[i],r,2*i,0,1);\n    if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {\n      r[i+x.t] -= x.DV;\n      r[i+x.t+1] = 1;\n    }\n  }\n  if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);\n  r.s = 0;\n  r.clamp();\n}\n\n// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)\n// r != q, this != m.  q or r may be null.\nfunction bnpDivRemTo(m,q,r) {\n  var pm = m.abs();\n  if(pm.t <= 0) return;\n  var pt = this.abs();\n  if(pt.t < pm.t) {\n    if(q != null) q.fromInt(0);\n    if(r != null) this.copyTo(r);\n    return;\n  }\n  if(r == null) r = nbi();\n  var y = nbi(), ts = this.s, ms = m.s;\n  var nsh = this.DB-nbits(pm[pm.t-1]);\t// normalize modulus\n  if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }\n  else { pm.copyTo(y); pt.copyTo(r); }\n  var ys = y.t;\n  var y0 = y[ys-1];\n  if(y0 == 0) return;\n  var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);\n  var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;\n  var i = r.t, j = i-ys, t = (q==null)?nbi():q;\n  y.dlShiftTo(j,t);\n  if(r.compareTo(t) >= 0) {\n    r[r.t++] = 1;\n    r.subTo(t,r);\n  }\n  BigInteger.ONE.dlShiftTo(ys,t);\n  t.subTo(y,y);\t// \"negative\" y so we can replace sub with am later\n  while(y.t < ys) y[y.t++] = 0;\n  while(--j >= 0) {\n    // Estimate quotient digit\n    var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);\n    if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) {\t// Try it out\n      y.dlShiftTo(j,t);\n      r.subTo(t,r);\n      while(r[i] < --qd) r.subTo(t,r);\n    }\n  }\n  if(q != null) {\n    r.drShiftTo(ys,q);\n    if(ts != ms) BigInteger.ZERO.subTo(q,q);\n  }\n  r.t = ys;\n  r.clamp();\n  if(nsh > 0) r.rShiftTo(nsh,r);\t// Denormalize remainder\n  if(ts < 0) BigInteger.ZERO.subTo(r,r);\n}\n\n// (public) this mod a\nfunction bnMod(a) {\n  var r = nbi();\n  this.abs().divRemTo(a,null,r);\n  if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);\n  return r;\n}\n\n// Modular reduction using \"classic\" algorithm\nfunction Classic(m) { this.m = m; }\nfunction cConvert(x) {\n  if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);\n  else return x;\n}\nfunction cRevert(x) { return x; }\nfunction cReduce(x) { x.divRemTo(this.m,null,x); }\nfunction cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }\nfunction cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }\n\nClassic.prototype.convert = cConvert;\nClassic.prototype.revert = cRevert;\nClassic.prototype.reduce = cReduce;\nClassic.prototype.mulTo = cMulTo;\nClassic.prototype.sqrTo = cSqrTo;\n\n// (protected) return \"-1/this % 2^DB\"; useful for Mont. reduction\n// justification:\n//         xy == 1 (mod m)\n//         xy =  1+km\n//   xy(2-xy) = (1+km)(1-km)\n// x[y(2-xy)] = 1-k^2m^2\n// x[y(2-xy)] == 1 (mod m^2)\n// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2\n// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.\n// JS multiply \"overflows\" differently from C/C++, so care is needed here.\nfunction bnpInvDigit() {\n  if(this.t < 1) return 0;\n  var x = this[0];\n  if((x&1) == 0) return 0;\n  var y = x&3;\t\t// y == 1/x mod 2^2\n  y = (y*(2-(x&0xf)*y))&0xf;\t// y == 1/x mod 2^4\n  y = (y*(2-(x&0xff)*y))&0xff;\t// y == 1/x mod 2^8\n  y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;\t// y == 1/x mod 2^16\n  // last step - calculate inverse mod DV directly;\n  // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints\n  y = (y*(2-x*y%this.DV))%this.DV;\t\t// y == 1/x mod 2^dbits\n  // we really want the negative inverse, and -DV < y < DV\n  return (y>0)?this.DV-y:-y;\n}\n\n// Montgomery reduction\nfunction Montgomery(m) {\n  this.m = m;\n  this.mp = m.invDigit();\n  this.mpl = this.mp&0x7fff;\n  this.mph = this.mp>>15;\n  this.um = (1<<(m.DB-15))-1;\n  this.mt2 = 2*m.t;\n}\n\n// xR mod m\nfunction montConvert(x) {\n  var r = nbi();\n  x.abs().dlShiftTo(this.m.t,r);\n  r.divRemTo(this.m,null,r);\n  if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);\n  return r;\n}\n\n// x/R mod m\nfunction montRevert(x) {\n  var r = nbi();\n  x.copyTo(r);\n  this.reduce(r);\n  return r;\n}\n\n// x = x/R mod m (HAC 14.32)\nfunction montReduce(x) {\n  while(x.t <= this.mt2)\t// pad x so am has enough room later\n    x[x.t++] = 0;\n  for(var i = 0; i < this.m.t; ++i) {\n    // faster way of calculating u0 = x[i]*mp mod DV\n    var j = x[i]&0x7fff;\n    var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;\n    // use am to combine the multiply-shift-add into one call\n    j = i+this.m.t;\n    x[j] += this.m.am(0,u0,x,i,0,this.m.t);\n    // propagate carry\n    while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }\n  }\n  x.clamp();\n  x.drShiftTo(this.m.t,x);\n  if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);\n}\n\n// r = \"x^2/R mod m\"; x != r\nfunction montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }\n\n// r = \"xy/R mod m\"; x,y != r\nfunction montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }\n\nMontgomery.prototype.convert = montConvert;\nMontgomery.prototype.revert = montRevert;\nMontgomery.prototype.reduce = montReduce;\nMontgomery.prototype.mulTo = montMulTo;\nMontgomery.prototype.sqrTo = montSqrTo;\n\n// (protected) true iff this is even\nfunction bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }\n\n// (protected) this^e, e < 2^32, doing sqr and mul with \"r\" (HAC 14.79)\nfunction bnpExp(e,z) {\n  if(e > 0xffffffff || e < 1) return BigInteger.ONE;\n  var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;\n  g.copyTo(r);\n  while(--i >= 0) {\n    z.sqrTo(r,r2);\n    if((e&(1<<i)) > 0) z.mulTo(r2,g,r);\n    else { var t = r; r = r2; r2 = t; }\n  }\n  return z.revert(r);\n}\n\n// (public) this^e % m, 0 <= e < 2^32\nfunction bnModPowInt(e,m) {\n  var z;\n  if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);\n  return this.exp(e,z);\n}\n\n// protected\nBigInteger.prototype.copyTo = bnpCopyTo;\nBigInteger.prototype.fromInt = bnpFromInt;\nBigInteger.prototype.fromString = bnpFromString;\nBigInteger.prototype.clamp = bnpClamp;\nBigInteger.prototype.dlShiftTo = bnpDLShiftTo;\nBigInteger.prototype.drShiftTo = bnpDRShiftTo;\nBigInteger.prototype.lShiftTo = bnpLShiftTo;\nBigInteger.prototype.rShiftTo = bnpRShiftTo;\nBigInteger.prototype.subTo = bnpSubTo;\nBigInteger.prototype.multiplyTo = bnpMultiplyTo;\nBigInteger.prototype.squareTo = bnpSquareTo;\nBigInteger.prototype.divRemTo = bnpDivRemTo;\nBigInteger.prototype.invDigit = bnpInvDigit;\nBigInteger.prototype.isEven = bnpIsEven;\nBigInteger.prototype.exp = bnpExp;\n\n// public\nBigInteger.prototype.toString = bnToString;\nBigInteger.prototype.negate = bnNegate;\nBigInteger.prototype.abs = bnAbs;\nBigInteger.prototype.compareTo = bnCompareTo;\nBigInteger.prototype.bitLength = bnBitLength;\nBigInteger.prototype.mod = bnMod;\nBigInteger.prototype.modPowInt = bnModPowInt;\n\n// \"constants\"\nBigInteger.ZERO = nbv(0);\nBigInteger.ONE = nbv(1);\n\n\n/// BEGIN jsbn2.js\n\n/*\n * Copyright (c) 2003-2005  Tom Wu\n * All Rights Reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS-IS\" AND WITHOUT WARRANTY OF ANY KIND, \n * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY \n * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  \n *\n * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,\n * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER\n * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF\n * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT\n * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n *\n * In addition, the following condition applies:\n *\n * All redistributions must retain an intact copy of this copyright notice\n * and disclaimer.\n */\n\n// Extended JavaScript BN functions, required for RSA private ops.\n\n// (public)\nfunction bnClone() { var r = nbi(); this.copyTo(r); return r; }\n\n// (public) return value as integer\nfunction bnIntValue() {\n  if(this.s < 0) {\n    if(this.t == 1) return this[0]-this.DV;\n    else if(this.t == 0) return -1;\n  }\n  else if(this.t == 1) return this[0];\n  else if(this.t == 0) return 0;\n  // assumes 16 < DB < 32\n  return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];\n}\n\n// (public) return value as byte\nfunction bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }\n\n// (public) return value as short (assumes DB>=16)\nfunction bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }\n\n// (protected) return x s.t. r^x < DV\nfunction bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }\n\n// (public) 0 if this == 0, 1 if this > 0\nfunction bnSigNum() {\n  if(this.s < 0) return -1;\n  else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;\n  else return 1;\n}\n\n// (protected) convert to radix string\nfunction bnpToRadix(b) {\n  if(b == null) b = 10;\n  if(this.signum() == 0 || b < 2 || b > 36) return \"0\";\n  var cs = this.chunkSize(b);\n  var a = Math.pow(b,cs);\n  var d = nbv(a), y = nbi(), z = nbi(), r = \"\";\n  this.divRemTo(d,y,z);\n  while(y.signum() > 0) {\n    r = (a+z.intValue()).toString(b).substr(1) + r;\n    y.divRemTo(d,y,z);\n  }\n  return z.intValue().toString(b) + r;\n}\n\n// (protected) convert from radix string\nfunction bnpFromRadix(s,b) {\n  this.fromInt(0);\n  if(b == null) b = 10;\n  var cs = this.chunkSize(b);\n  var d = Math.pow(b,cs), mi = false, j = 0, w = 0;\n  for(var i = 0; i < s.length; ++i) {\n    var x = intAt(s,i);\n    if(x < 0) {\n      if(s.charAt(i) == \"-\" && this.signum() == 0) mi = true;\n      continue;\n    }\n    w = b*w+x;\n    if(++j >= cs) {\n      this.dMultiply(d);\n      this.dAddOffset(w,0);\n      j = 0;\n      w = 0;\n    }\n  }\n  if(j > 0) {\n    this.dMultiply(Math.pow(b,j));\n    this.dAddOffset(w,0);\n  }\n  if(mi) BigInteger.ZERO.subTo(this,this);\n}\n\n// (protected) alternate constructor\nfunction bnpFromNumber(a,b,c) {\n  if(\"number\" == typeof b) {\n    // new BigInteger(int,int,RNG)\n    if(a < 2) this.fromInt(1);\n    else {\n      this.fromNumber(a,c);\n      if(!this.testBit(a-1))\t// force MSB set\n        this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);\n      if(this.isEven()) this.dAddOffset(1,0); // force odd\n      while(!this.isProbablePrime(b)) {\n        this.dAddOffset(2,0);\n        if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);\n      }\n    }\n  }\n  else {\n    // new BigInteger(int,RNG)\n    var x = new Array(), t = a&7;\n    x.length = (a>>3)+1;\n    b.nextBytes(x);\n    if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;\n    this.fromString(x,256);\n  }\n}\n\n// (public) convert to bigendian byte array\nfunction bnToByteArray() {\n  var i = this.t, r = new Array();\n  r[0] = this.s;\n  var p = this.DB-(i*this.DB)%8, d, k = 0;\n  if(i-- > 0) {\n    if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)\n      r[k++] = d|(this.s<<(this.DB-p));\n    while(i >= 0) {\n      if(p < 8) {\n        d = (this[i]&((1<<p)-1))<<(8-p);\n        d |= this[--i]>>(p+=this.DB-8);\n      }\n      else {\n        d = (this[i]>>(p-=8))&0xff;\n        if(p <= 0) { p += this.DB; --i; }\n      }\n      if((d&0x80) != 0) d |= -256;\n      if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;\n      if(k > 0 || d != this.s) r[k++] = d;\n    }\n  }\n  return r;\n}\n\nfunction bnEquals(a) { return(this.compareTo(a)==0); }\nfunction bnMin(a) { return(this.compareTo(a)<0)?this:a; }\nfunction bnMax(a) { return(this.compareTo(a)>0)?this:a; }\n\n// (protected) r = this op a (bitwise)\nfunction bnpBitwiseTo(a,op,r) {\n  var i, f, m = Math.min(a.t,this.t);\n  for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);\n  if(a.t < this.t) {\n    f = a.s&this.DM;\n    for(i = m; i < this.t; ++i) r[i] = op(this[i],f);\n    r.t = this.t;\n  }\n  else {\n    f = this.s&this.DM;\n    for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);\n    r.t = a.t;\n  }\n  r.s = op(this.s,a.s);\n  r.clamp();\n}\n\n// (public) this & a\nfunction op_and(x,y) { return x&y; }\nfunction bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }\n\n// (public) this | a\nfunction op_or(x,y) { return x|y; }\nfunction bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }\n\n// (public) this ^ a\nfunction op_xor(x,y) { return x^y; }\nfunction bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }\n\n// (public) this & ~a\nfunction op_andnot(x,y) { return x&~y; }\nfunction bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }\n\n// (public) ~this\nfunction bnNot() {\n  var r = nbi();\n  for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];\n  r.t = this.t;\n  r.s = ~this.s;\n  return r;\n}\n\n// (public) this << n\nfunction bnShiftLeft(n) {\n  var r = nbi();\n  if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);\n  return r;\n}\n\n// (public) this >> n\nfunction bnShiftRight(n) {\n  var r = nbi();\n  if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);\n  return r;\n}\n\n// return index of lowest 1-bit in x, x < 2^31\nfunction lbit(x) {\n  if(x == 0) return -1;\n  var r = 0;\n  if((x&0xffff) == 0) { x >>= 16; r += 16; }\n  if((x&0xff) == 0) { x >>= 8; r += 8; }\n  if((x&0xf) == 0) { x >>= 4; r += 4; }\n  if((x&3) == 0) { x >>= 2; r += 2; }\n  if((x&1) == 0) ++r;\n  return r;\n}\n\n// (public) returns index of lowest 1-bit (or -1 if none)\nfunction bnGetLowestSetBit() {\n  for(var i = 0; i < this.t; ++i)\n    if(this[i] != 0) return i*this.DB+lbit(this[i]);\n  if(this.s < 0) return this.t*this.DB;\n  return -1;\n}\n\n// return number of 1 bits in x\nfunction cbit(x) {\n  var r = 0;\n  while(x != 0) { x &= x-1; ++r; }\n  return r;\n}\n\n// (public) return number of set bits\nfunction bnBitCount() {\n  var r = 0, x = this.s&this.DM;\n  for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);\n  return r;\n}\n\n// (public) true iff nth bit is set\nfunction bnTestBit(n) {\n  var j = Math.floor(n/this.DB);\n  if(j >= this.t) return(this.s!=0);\n  return((this[j]&(1<<(n%this.DB)))!=0);\n}\n\n// (protected) this op (1<<n)\nfunction bnpChangeBit(n,op) {\n  var r = BigInteger.ONE.shiftLeft(n);\n  this.bitwiseTo(r,op,r);\n  return r;\n}\n\n// (public) this | (1<<n)\nfunction bnSetBit(n) { return this.changeBit(n,op_or); }\n\n// (public) this & ~(1<<n)\nfunction bnClearBit(n) { return this.changeBit(n,op_andnot); }\n\n// (public) this ^ (1<<n)\nfunction bnFlipBit(n) { return this.changeBit(n,op_xor); }\n\n// (protected) r = this + a\nfunction bnpAddTo(a,r) {\n  var i = 0, c = 0, m = Math.min(a.t,this.t);\n  while(i < m) {\n    c += this[i]+a[i];\n    r[i++] = c&this.DM;\n    c >>= this.DB;\n  }\n  if(a.t < this.t) {\n    c += a.s;\n    while(i < this.t) {\n      c += this[i];\n      r[i++] = c&this.DM;\n      c >>= this.DB;\n    }\n    c += this.s;\n  }\n  else {\n    c += this.s;\n    while(i < a.t) {\n      c += a[i];\n      r[i++] = c&this.DM;\n      c >>= this.DB;\n    }\n    c += a.s;\n  }\n  r.s = (c<0)?-1:0;\n  if(c > 0) r[i++] = c;\n  else if(c < -1) r[i++] = this.DV+c;\n  r.t = i;\n  r.clamp();\n}\n\n// (public) this + a\nfunction bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }\n\n// (public) this - a\nfunction bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }\n\n// (public) this * a\nfunction bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }\n\n// (public) this / a\nfunction bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }\n\n// (public) this % a\nfunction bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }\n\n// (public) [this/a,this%a]\nfunction bnDivideAndRemainder(a) {\n  var q = nbi(), r = nbi();\n  this.divRemTo(a,q,r);\n  return new Array(q,r);\n}\n\n// (protected) this *= n, this >= 0, 1 < n < DV\nfunction bnpDMultiply(n) {\n  this[this.t] = this.am(0,n-1,this,0,0,this.t);\n  ++this.t;\n  this.clamp();\n}\n\n// (protected) this += n << w words, this >= 0\nfunction bnpDAddOffset(n,w) {\n  while(this.t <= w) this[this.t++] = 0;\n  this[w] += n;\n  while(this[w] >= this.DV) {\n    this[w] -= this.DV;\n    if(++w >= this.t) this[this.t++] = 0;\n    ++this[w];\n  }\n}\n\n// A \"null\" reducer\nfunction NullExp() {}\nfunction nNop(x) { return x; }\nfunction nMulTo(x,y,r) { x.multiplyTo(y,r); }\nfunction nSqrTo(x,r) { x.squareTo(r); }\n\nNullExp.prototype.convert = nNop;\nNullExp.prototype.revert = nNop;\nNullExp.prototype.mulTo = nMulTo;\nNullExp.prototype.sqrTo = nSqrTo;\n\n// (public) this^e\nfunction bnPow(e) { return this.exp(e,new NullExp()); }\n\n// (protected) r = lower n words of \"this * a\", a.t <= n\n// \"this\" should be the larger one if appropriate.\nfunction bnpMultiplyLowerTo(a,n,r) {\n  var i = Math.min(this.t+a.t,n);\n  r.s = 0; // assumes a,this >= 0\n  r.t = i;\n  while(i > 0) r[--i] = 0;\n  var j;\n  for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);\n  for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);\n  r.clamp();\n}\n\n// (protected) r = \"this * a\" without lower n words, n > 0\n// \"this\" should be the larger one if appropriate.\nfunction bnpMultiplyUpperTo(a,n,r) {\n  --n;\n  var i = r.t = this.t+a.t-n;\n  r.s = 0; // assumes a,this >= 0\n  while(--i >= 0) r[i] = 0;\n  for(i = Math.max(n-this.t,0); i < a.t; ++i)\n    r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);\n  r.clamp();\n  r.drShiftTo(1,r);\n}\n\n// Barrett modular reduction\nfunction Barrett(m) {\n  // setup Barrett\n  this.r2 = nbi();\n  this.q3 = nbi();\n  BigInteger.ONE.dlShiftTo(2*m.t,this.r2);\n  this.mu = this.r2.divide(m);\n  this.m = m;\n}\n\nfunction barrettConvert(x) {\n  if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);\n  else if(x.compareTo(this.m) < 0) return x;\n  else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }\n}\n\nfunction barrettRevert(x) { return x; }\n\n// x = x mod m (HAC 14.42)\nfunction barrettReduce(x) {\n  x.drShiftTo(this.m.t-1,this.r2);\n  if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }\n  this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);\n  this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);\n  while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);\n  x.subTo(this.r2,x);\n  while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);\n}\n\n// r = x^2 mod m; x != r\nfunction barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }\n\n// r = x*y mod m; x,y != r\nfunction barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }\n\nBarrett.prototype.convert = barrettConvert;\nBarrett.prototype.revert = barrettRevert;\nBarrett.prototype.reduce = barrettReduce;\nBarrett.prototype.mulTo = barrettMulTo;\nBarrett.prototype.sqrTo = barrettSqrTo;\n\n// (public) this^e % m (HAC 14.85)\nfunction bnModPow(e,m) {\n  var i = e.bitLength(), k, r = nbv(1), z;\n  if(i <= 0) return r;\n  else if(i < 18) k = 1;\n  else if(i < 48) k = 3;\n  else if(i < 144) k = 4;\n  else if(i < 768) k = 5;\n  else k = 6;\n  if(i < 8)\n    z = new Classic(m);\n  else if(m.isEven())\n    z = new Barrett(m);\n  else\n    z = new Montgomery(m);\n\n  // precomputation\n  var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;\n  g[1] = z.convert(this);\n  if(k > 1) {\n    var g2 = nbi();\n    z.sqrTo(g[1],g2);\n    while(n <= km) {\n      g[n] = nbi();\n      z.mulTo(g2,g[n-2],g[n]);\n      n += 2;\n    }\n  }\n\n  var j = e.t-1, w, is1 = true, r2 = nbi(), t;\n  i = nbits(e[j])-1;\n  while(j >= 0) {\n    if(i >= k1) w = (e[j]>>(i-k1))&km;\n    else {\n      w = (e[j]&((1<<(i+1))-1))<<(k1-i);\n      if(j > 0) w |= e[j-1]>>(this.DB+i-k1);\n    }\n\n    n = k;\n    while((w&1) == 0) { w >>= 1; --n; }\n    if((i -= n) < 0) { i += this.DB; --j; }\n    if(is1) {\t// ret == 1, don't bother squaring or multiplying it\n      g[w].copyTo(r);\n      is1 = false;\n    }\n    else {\n      while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }\n      if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }\n      z.mulTo(r2,g[w],r);\n    }\n\n    while(j >= 0 && (e[j]&(1<<i)) == 0) {\n      z.sqrTo(r,r2); t = r; r = r2; r2 = t;\n      if(--i < 0) { i = this.DB-1; --j; }\n    }\n  }\n  return z.revert(r);\n}\n\n// (public) gcd(this,a) (HAC 14.54)\nfunction bnGCD(a) {\n  var x = (this.s<0)?this.negate():this.clone();\n  var y = (a.s<0)?a.negate():a.clone();\n  if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }\n  var i = x.getLowestSetBit(), g = y.getLowestSetBit();\n  if(g < 0) return x;\n  if(i < g) g = i;\n  if(g > 0) {\n    x.rShiftTo(g,x);\n    y.rShiftTo(g,y);\n  }\n  while(x.signum() > 0) {\n    if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);\n    if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);\n    if(x.compareTo(y) >= 0) {\n      x.subTo(y,x);\n      x.rShiftTo(1,x);\n    }\n    else {\n      y.subTo(x,y);\n      y.rShiftTo(1,y);\n    }\n  }\n  if(g > 0) y.lShiftTo(g,y);\n  return y;\n}\n\n// (protected) this % n, n < 2^26\nfunction bnpModInt(n) {\n  if(n <= 0) return 0;\n  var d = this.DV%n, r = (this.s<0)?n-1:0;\n  if(this.t > 0)\n    if(d == 0) r = this[0]%n;\n    else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;\n  return r;\n}\n\n// (public) 1/this % m (HAC 14.61)\nfunction bnModInverse(m) {\n  var ac = m.isEven();\n  if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;\n  var u = m.clone(), v = this.clone();\n  var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);\n  while(u.signum() != 0) {\n    while(u.isEven()) {\n      u.rShiftTo(1,u);\n      if(ac) {\n        if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }\n        a.rShiftTo(1,a);\n      }\n      else if(!b.isEven()) b.subTo(m,b);\n      b.rShiftTo(1,b);\n    }\n    while(v.isEven()) {\n      v.rShiftTo(1,v);\n      if(ac) {\n        if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }\n        c.rShiftTo(1,c);\n      }\n      else if(!d.isEven()) d.subTo(m,d);\n      d.rShiftTo(1,d);\n    }\n    if(u.compareTo(v) >= 0) {\n      u.subTo(v,u);\n      if(ac) a.subTo(c,a);\n      b.subTo(d,b);\n    }\n    else {\n      v.subTo(u,v);\n      if(ac) c.subTo(a,c);\n      d.subTo(b,d);\n    }\n  }\n  if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;\n  if(d.compareTo(m) >= 0) return d.subtract(m);\n  if(d.signum() < 0) d.addTo(m,d); else return d;\n  if(d.signum() < 0) return d.add(m); else return d;\n}\n\nvar lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509];\nvar lplim = (1<<26)/lowprimes[lowprimes.length-1];\n\n// (public) test primality with certainty >= 1-.5^t\nfunction bnIsProbablePrime(t) {\n  var i, x = this.abs();\n  if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {\n    for(i = 0; i < lowprimes.length; ++i)\n      if(x[0] == lowprimes[i]) return true;\n    return false;\n  }\n  if(x.isEven()) return false;\n  i = 1;\n  while(i < lowprimes.length) {\n    var m = lowprimes[i], j = i+1;\n    while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];\n    m = x.modInt(m);\n    while(i < j) if(m%lowprimes[i++] == 0) return false;\n  }\n  return x.millerRabin(t);\n}\n\n// (protected) true if probably prime (HAC 4.24, Miller-Rabin)\nfunction bnpMillerRabin(t) {\n  var n1 = this.subtract(BigInteger.ONE);\n  var k = n1.getLowestSetBit();\n  if(k <= 0) return false;\n  var r = n1.shiftRight(k);\n  t = (t+1)>>1;\n  if(t > lowprimes.length) t = lowprimes.length;\n  var a = nbi();\n  for(var i = 0; i < t; ++i) {\n    a.fromInt(lowprimes[i]);\n    var y = a.modPow(r,this);\n    if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {\n      var j = 1;\n      while(j++ < k && y.compareTo(n1) != 0) {\n        y = y.modPowInt(2,this);\n        if(y.compareTo(BigInteger.ONE) == 0) return false;\n      }\n      if(y.compareTo(n1) != 0) return false;\n    }\n  }\n  return true;\n}\n\n// protected\nBigInteger.prototype.chunkSize = bnpChunkSize;\nBigInteger.prototype.toRadix = bnpToRadix;\nBigInteger.prototype.fromRadix = bnpFromRadix;\nBigInteger.prototype.fromNumber = bnpFromNumber;\nBigInteger.prototype.bitwiseTo = bnpBitwiseTo;\nBigInteger.prototype.changeBit = bnpChangeBit;\nBigInteger.prototype.addTo = bnpAddTo;\nBigInteger.prototype.dMultiply = bnpDMultiply;\nBigInteger.prototype.dAddOffset = bnpDAddOffset;\nBigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;\nBigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;\nBigInteger.prototype.modInt = bnpModInt;\nBigInteger.prototype.millerRabin = bnpMillerRabin;\n\n// public\nBigInteger.prototype.clone = bnClone;\nBigInteger.prototype.intValue = bnIntValue;\nBigInteger.prototype.byteValue = bnByteValue;\nBigInteger.prototype.shortValue = bnShortValue;\nBigInteger.prototype.signum = bnSigNum;\nBigInteger.prototype.toByteArray = bnToByteArray;\nBigInteger.prototype.equals = bnEquals;\nBigInteger.prototype.min = bnMin;\nBigInteger.prototype.max = bnMax;\nBigInteger.prototype.and = bnAnd;\nBigInteger.prototype.or = bnOr;\nBigInteger.prototype.xor = bnXor;\nBigInteger.prototype.andNot = bnAndNot;\nBigInteger.prototype.not = bnNot;\nBigInteger.prototype.shiftLeft = bnShiftLeft;\nBigInteger.prototype.shiftRight = bnShiftRight;\nBigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;\nBigInteger.prototype.bitCount = bnBitCount;\nBigInteger.prototype.testBit = bnTestBit;\nBigInteger.prototype.setBit = bnSetBit;\nBigInteger.prototype.clearBit = bnClearBit;\nBigInteger.prototype.flipBit = bnFlipBit;\nBigInteger.prototype.add = bnAdd;\nBigInteger.prototype.subtract = bnSubtract;\nBigInteger.prototype.multiply = bnMultiply;\nBigInteger.prototype.divide = bnDivide;\nBigInteger.prototype.remainder = bnRemainder;\nBigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;\nBigInteger.prototype.modPow = bnModPow;\nBigInteger.prototype.modInverse = bnModInverse;\nBigInteger.prototype.pow = bnPow;\nBigInteger.prototype.gcd = bnGCD;\nBigInteger.prototype.isProbablePrime = bnIsProbablePrime;\n\n// BigInteger interfaces not implemented in jsbn:\n\n// BigInteger(int signum, byte[] magnitude)\n// double doubleValue()\n// float floatValue()\n// int hashCode()\n// long longValue()\n// static BigInteger valueOf(long val)\n\n/// METEOR WRAPPER\nreturn BigInteger;\n})();\n"
  },
  {
    "path": "packages/srp/package.js",
    "content": "// XXX COMPAT WITH 0.8.3\n// This package is replaced by the use of bcrypt in accounts-password,\n// but we are leaving in some of the code to allow existing user\n// databases to be upgraded from SRP to bcrypt.\n\nPackage.describe({\n  summary: \"Library for Secure Remote Password (SRP) exchanges\",\n  version: \"1.0.9\"\n});\n\nPackage.onUse(function (api) {\n  api.use(['random', 'check', 'sha'], ['client', 'server']);\n  api.use('underscore');\n  api.export('SRP');\n  api.addFiles(['biginteger.js', 'srp.js'],\n                ['client', 'server']);\n});\n\nPackage.onTest(function (api) {\n  api.use('tinytest');\n  api.use('srp', ['client', 'server']);\n  api.use('underscore');\n  api.addFiles(['srp_tests.js'], ['client', 'server']);\n});\n"
  },
  {
    "path": "packages/srp/srp.js",
    "content": "// This package contains just enough of the original SRP code to\n// support the backwards-compatibility upgrade path.\n//\n// An SRP (and possibly also accounts-srp) package should eventually be\n// available in Atmosphere so that users can continue to use SRP if they\n// want to.\n\nSRP = {};\n\n/**\n * Generate a new SRP verifier. Password is the plaintext password.\n *\n * options is optional and can include:\n * - identity: String. The SRP username to user. Mostly this is passed\n *   in for testing.  Random UUID if not provided.\n * - hashedIdentityAndPassword: combined identity and password, already hashed, for the SRP to bcrypt upgrade path.\n * - salt: String. A salt to use.  Mostly this is passed in for\n *   testing.  Random UUID if not provided.\n * - SRP parameters (see _defaults and paramsFromOptions below)\n */\nSRP.generateVerifier = function (password, options) {\n  var params = paramsFromOptions(options);\n\n  var salt = (options && options.salt) || Random.secret();\n\n  var identity;\n  var hashedIdentityAndPassword = options && options.hashedIdentityAndPassword;\n  if (!hashedIdentityAndPassword) {\n    identity = (options && options.identity) || Random.secret();\n    hashedIdentityAndPassword = params.hash(identity + \":\" + password);\n  }\n\n  var x = params.hash(salt + hashedIdentityAndPassword);\n  var xi = new BigInteger(x, 16);\n  var v = params.g.modPow(xi, params.N);\n\n  return {\n    identity: identity,\n    salt: salt,\n    verifier: v.toString(16)\n  };\n};\n\n// For use with check().\nSRP.matchVerifier = {\n  identity: String,\n  salt: String,\n  verifier: String\n};\n\n\n/**\n * Default parameter values for SRP.\n *\n */\nvar _defaults = {\n  hash: function (x) { return SHA256(x).toLowerCase(); },\n  N: new BigInteger(\"EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3\", 16),\n  g: new BigInteger(\"2\")\n};\n_defaults.k = new BigInteger(\n  _defaults.hash(\n    _defaults.N.toString(16) +\n      _defaults.g.toString(16)),\n  16);\n\n/**\n * Process an options hash to create SRP parameters.\n *\n * Options can include:\n * - hash: Function. Defaults to SHA256.\n * - N: String or BigInteger. Defaults to 1024 bit value from RFC 5054\n * - g: String or BigInteger. Defaults to 2.\n * - k: String or BigInteger. Defaults to hash(N, g)\n */\nvar paramsFromOptions = function (options) {\n  if (!options) // fast path\n    return _defaults;\n\n  var ret = _.extend({}, _defaults);\n\n  _.each(['N', 'g', 'k'], function (p) {\n    if (options[p]) {\n      if (typeof options[p] === \"string\")\n        ret[p] = new BigInteger(options[p], 16);\n      else if (options[p] instanceof BigInteger)\n        ret[p] = options[p];\n      else\n        throw new Error(\"Invalid parameter: \" + p);\n    }\n  });\n\n  if (options.hash)\n    ret.hash = function (x) { return options.hash(x).toLowerCase(); };\n\n  if (!options.k && (options.N || options.g || options.hash)) {\n    ret.k = ret.hash(ret.N.toString(16) + ret.g.toString(16));\n  }\n\n  return ret;\n};\n"
  },
  {
    "path": "packages/srp/srp_tests.js",
    "content": "Tinytest.add(\"srp - fixed values\", function(test) {\n  // Test exact values outputted by `generateVerifier`. We have to be very\n  // careful about changing the SRP code, because changes could render\n  // people's existing user database unusable. This test is\n  // intentionally brittle to catch change that could affect the\n  // validity of user passwords.\n\n  var identity = \"b73d9af9-4e74-4ce0-879c-484828b08436\";\n  var salt = \"85f8b9d3-744a-487d-8982-a50e4c9f552a\";\n  var password = \"95109251-3d8a-4777-bdec-44ffe8d86dfb\";\n  var a = \"dc99c646fa4cb7c24314bb6f4ca2d391297acd0dacb0430a13bbf1e37dcf8071\";\n  var b = \"cf878e00c9f2b6aa48a10f66df9706e64fef2ca399f396d65f5b0a27cb8ae237\";\n\n  var verifier = SRP.generateVerifier(\n    password, {identity: identity, salt: salt});\n  test.equal(verifier.identity, identity);\n  test.equal(verifier.salt, salt);\n  test.equal(verifier.verifier, \"56778b720d20b2e306f04e47180fb94335b88a6052808483acb0e85612606f9f1d8d5a3c6b85e0c7bfec7f08c07bdfbd0d40b032f517871dd8afd045b0f24e2edc05ccdc47b19f35d2eb9f7670521a38c1b358fcee63f052a1aedbb1282d3b92c7a554f8523f3379c2fbc6885be8227fbd426ad6960c3839809f8c94d80a6c51\");\n});\n"
  },
  {
    "path": "packages/standard-app-packages/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/standard-app-packages/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/standard-app-packages/package.js",
    "content": "Package.describe({\n  summary: \"Moved to meteor-platform\",\n  version: '1.0.9'\n});\n\nPackage.onUse(function (api) {\n  api.imply(\"meteor-platform\");\n});\n"
  },
  {
    "path": "packages/standard-minifier-css/.npm/plugin/minifyStd/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/standard-minifier-css/.npm/plugin/minifyStd/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/standard-minifier-css/.npm/plugin/minifyStd/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"source-map\": {\n      \"version\": \"0.4.2\",\n      \"dependencies\": {\n        \"amdefine\": {\n          \"version\": \"0.1.1\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/standard-minifier-css/.npm/plugin/minifyStdCSS/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/standard-minifier-css/.npm/plugin/minifyStdCSS/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/standard-minifier-css/.npm/plugin/minifyStdCSS/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"source-map\": {\n      \"version\": \"0.5.3\",\n      \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.5.3.tgz\",\n      \"from\": \"https://registry.npmjs.org/source-map/-/source-map-0.5.3.tgz\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/standard-minifier-css/README.md",
    "content": "Standard Minifier for CSS\n===\n\nThis package provides a minifier plugin used for Meteor apps by default.\n\nThe CSS minifier mostly reduces amount of white-space parsing CSS with\nParseCSS."
  },
  {
    "path": "packages/standard-minifier-css/package.js",
    "content": "Package.describe({\n  name: 'standard-minifier-css',\n  version: '1.0.7_1',\n  summary: 'Standard css minifier used with Meteor apps by default.',\n  documentation: 'README.md'\n});\n\nPackage.registerBuildPlugin({\n  name: \"minifyStdCSS\",\n  use: [\n    'minifier-css'\n  ],\n  npmDependencies: {\n    \"source-map\": \"0.5.3\"\n  },\n  sources: [\n    'plugin/minify-css.js'\n  ]\n});\n\nPackage.onUse(function(api) {\n  api.use('isobuild:minifier-plugin@1.0.0');\n});\n\nPackage.onTest(function(api) {\n});\n"
  },
  {
    "path": "packages/standard-minifier-css/plugin/minify-css.js",
    "content": "var sourcemap = Npm.require('source-map');\n\nPlugin.registerMinifier({\n  extensions: [\"css\"]\n}, function () {\n  var minifier = new CssToolsMinifier();\n  return minifier;\n});\n\nfunction CssToolsMinifier () {};\n\nCssToolsMinifier.prototype.processFilesForBundle = function (files, options) {\n  var mode = options.minifyMode;\n\n  if (! files.length) return;\n\n  var merged = mergeCss(files);\n\n  if (mode === 'development') {\n    files[0].addStylesheet({\n      data: merged.code,\n      sourceMap: merged.sourceMap,\n      path: 'merged-stylesheets.css'\n    });\n    return;\n  }\n\n  var minifiedFiles = CssTools.minifyCss(merged.code);\n\n  if (files.length) {\n    minifiedFiles.forEach(function (minified) {\n      files[0].addStylesheet({\n        data: minified\n      });\n    });\n  }\n};\n\n// Lints CSS files and merges them into one file, fixing up source maps and\n// pulling any @import directives up to the top since the CSS spec does not\n// allow them to appear in the middle of a file.\nvar mergeCss = Profile(\"mergeCss\", function (css) {\n  // Filenames passed to AST manipulator mapped to their original files\n  var originals = {};\n\n  var cssAsts = css.map(function (file) {\n    var filename = file.getPathInBundle();\n    originals[filename] = file;\n    try {\n      var parseOptions = { source: filename, position: true };\n      var ast = CssTools.parseCss(file.getContentsAsString(), parseOptions);\n      ast.filename = filename;\n    } catch (e) {\n      if (e.reason) {\n        file.error({\n          message: e.reason,\n          line: e.line,\n          column: e.column\n        });\n      } else {\n        // Just in case it's not the normal error the library makes.\n        file.error({message: e.message});\n      }\n\n      return { type: \"stylesheet\", stylesheet: { rules: [] },\n        filename: filename };\n    }\n\n    return ast;\n  });\n\n  var warnCb = function (filename, msg) {\n    // XXX make this a buildmessage.warning call rather than a random log.\n    //     this API would be like buildmessage.error, but wouldn't cause\n    //     the build to fail.\n    console.log(filename + ': warn: ' + msg);\n  };\n\n  var mergedCssAst = CssTools.mergeCssAsts(cssAsts, warnCb);\n\n  // Overwrite the CSS files list with the new concatenated file\n  var stringifiedCss = CssTools.stringifyCss(mergedCssAst, {\n    sourcemap: true,\n    // don't try to read the referenced sourcemaps from the input\n    inputSourcemaps: false\n  });\n\n  if (! stringifiedCss.code) {\n    return { code: '' };\n  }\n\n  // Add the contents of the input files to the source map of the new file\n  stringifiedCss.map.sourcesContent =\n    stringifiedCss.map.sources.map(function (filename) {\n      return originals[filename].getContentsAsString();\n    });\n\n  var newMap;\n\n  Profile.time(\"composing source maps\", function () {\n    // If any input files had source maps, apply them.\n    // Ex.: less -> css source map should be composed with css -> css source map\n    newMap = sourcemap.SourceMapGenerator.fromSourceMap(\n      new sourcemap.SourceMapConsumer(stringifiedCss.map));\n\n    Object.keys(originals).forEach(function (name) {\n      var file = originals[name];\n      if (! file.getSourceMap())\n        return;\n      try {\n        newMap.applySourceMap(\n          new sourcemap.SourceMapConsumer(file.getSourceMap()), name);\n      } catch (err) {\n        // If we can't apply the source map, silently drop it.\n        //\n        // XXX This is here because there are some less files that\n        // produce source maps that throw when consumed. We should\n        // figure out exactly why and fix it, but this will do for now.\n      }\n    });\n  });\n\n  return {\n    code: stringifiedCss.code,\n    sourceMap: newMap.toString()\n  };\n});\n"
  },
  {
    "path": "packages/standard-minifier-js/.npm/plugin/minifyStd/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/standard-minifier-js/.npm/plugin/minifyStd/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/standard-minifier-js/.npm/plugin/minifyStd/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"source-map\": {\n      \"version\": \"0.4.2\",\n      \"dependencies\": {\n        \"amdefine\": {\n          \"version\": \"0.1.1\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/standard-minifier-js/README.md",
    "content": "Standard Minifier for JS\n===\n\nThis package provides a minifier plugin used for Meteor apps by default.\n\nThe JS minifier uses UglifyJS2. The options include name-mangling and other\ncommonly used options."
  },
  {
    "path": "packages/standard-minifier-js/package.js",
    "content": "Package.describe({\n  name: 'standard-minifier-js',\n  version: '1.0.7_1',\n  summary: 'Standard javascript minifiers used with Meteor apps by default.',\n  documentation: 'README.md'\n});\n\nPackage.registerBuildPlugin({\n  name: \"minifyStdJS\",\n  use: [\n    'minifier-js'\n  ],\n  sources: [\n    'plugin/minify-js.js'\n  ]\n});\n\nPackage.onUse(function(api) {\n  api.use('isobuild:minifier-plugin@1.0.0');\n});\n\nPackage.onTest(function(api) {\n});\n"
  },
  {
    "path": "packages/standard-minifier-js/plugin/minify-js.js",
    "content": "Plugin.registerMinifier({\n  extensions: [\"js\"]\n}, function () {\n  var minifier = new UglifyJSMinifier();\n  return minifier;\n});\n\nfunction UglifyJSMinifier () {};\n\nUglifyJSMinifier.prototype.processFilesForBundle = function (files, options) {\n  var mode = options.minifyMode;\n\n  // don't minify anything for development\n  if (mode === 'development') {\n    files.forEach(function (file) {\n      file.addJavaScript({\n        data: file.getContentsAsBuffer(),\n        sourceMap: file.getSourceMap(),\n        path: file.getPathInBundle()\n      });\n    });\n    return;\n  }\n\n  var minifyOptions = {\n    fromString: true,\n    compress: {\n      drop_debugger: false,\n      unused: false,\n      dead_code: false\n    }\n  };\n\n  var allJs = '';\n  files.forEach(function (file) {\n    // Don't reminify *.min.js.\n    if (/\\.min\\.js$/.test(file.getPathInBundle())) {\n      allJs += file.getContentsAsString();\n    } else {\n      allJs += UglifyJSMinify(file.getContentsAsString(), minifyOptions).code;\n    }\n    allJs += '\\n\\n';\n\n    Plugin.nudge();\n  });\n\n  if (files.length) {\n    files[0].addJavaScript({ data: allJs });\n  }\n};\n\n\n"
  },
  {
    "path": "packages/standard-minifiers/README.md",
    "content": "Standard Minifiers\n===\n\nThis package includes the JS and CSS standard minifiers in your Meteor project."
  },
  {
    "path": "packages/standard-minifiers/package.js",
    "content": "Package.describe({\n  name: 'standard-minifiers',\n  version: '1.0.6',\n  summary: 'Standard minifiers used with Meteor apps by default.',\n  documentation: 'README.md'\n});\n\nPackage.onUse(function(api) {\n  api.imply(['standard-minifier-css','standard-minifier-js']);\n});\n\nPackage.onTest(function(api) {});\n"
  },
  {
    "path": "packages/startup/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/startup/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/startup/package.js",
    "content": "Package.describe({\n  summary: \"Deprecated package (now empty)\",\n  version: \"1.0.7\"\n});\n\nPackage.onUse(function (api) {\n  // Deprecated -- Meteor.startup has been folded into the main\n  // 'meteor' package for now, because it seems reasonable to expect\n  // that Meteor.startup would always be available without having to\n  // include a special package.\n});\n"
  },
  {
    "path": "packages/static-html/README.md",
    "content": "# static-html\n\nEssentially, an alternative to the `templating` package that doesn't compile Blaze templates. Mostly useful if you want to use Angular or React as your view layer and just want to get some static HTML content on your page as a render target for your view framework.\n\nThis build plugin parses all of the `.html` files in your app and looks for top-level tags:\n\n- `<head>` - appended to the `head` section of your HTML\n- `<body>` - appended to the `body` section of your HTML\n\nAttributes are supported on the `<body>` tag, but not on `<head>`.\n"
  },
  {
    "path": "packages/static-html/package.js",
    "content": "Package.describe({\n  version: '1.0.10_1',\n  // Brief, one-line summary of the package.\n  summary: 'Define static page content in .html files',\n  git: 'https://github.com/meteor/meteor',\n  // By default, Meteor will default to using README.md for documentation.\n  // To avoid submitting documentation, set this field to null.\n  documentation: 'README.md'\n});\n\nPackage.registerBuildPlugin({\n  name: \"compileStaticHtmlBatch\",\n  use: [\n    'caching-html-compiler',\n    'ecmascript',\n    'templating-tools',\n    'underscore'\n  ],\n  sources: [\n    'static-html.js'\n  ]\n});\n\nPackage.onUse(function(api) {\n  api.use('isobuild:compiler-plugin@1.0.0');\n\n  // Body attributes are compiled to code that uses Meteor.startup\n  api.imply('meteor', 'client');\n});\n"
  },
  {
    "path": "packages/static-html/static-html.js",
    "content": "Plugin.registerCompiler({\n  extensions: ['html'],\n  archMatching: 'web',\n  isTemplate: true\n}, () => new CachingHtmlCompiler(\"static-html\", TemplatingTools.scanHtmlForTags, compileTagsToStaticHtml));\n\n// Same API as TutorialTools.compileTagsWithSpacebars, but instead of compiling\n// with Spacebars, it just returns static HTML\nfunction compileTagsToStaticHtml(tags) {\n  var handler = new StaticHtmlTagHandler();\n\n  tags.forEach((tag) => {\n    handler.addTagToResults(tag);\n  });\n\n  return handler.getResults();\n};\n\nclass StaticHtmlTagHandler {\n  constructor() {\n    this.results = {\n      head: '',\n      body: '',\n      js: '',\n      bodyAttrs: {}\n    };\n  }\n\n  getResults() {\n    return this.results;\n  }\n\n  addTagToResults(tag) {\n    this.tag = tag;\n\n    // do we have 1 or more attributes?\n    const hasAttribs = ! _.isEmpty(this.tag.attribs);\n\n    if (this.tag.tagName === \"head\") {\n      if (hasAttribs) {\n        this.throwCompileError(\"Attributes on <head> not supported\");\n      }\n\n      this.results.head += this.tag.contents;\n      return;\n    }\n\n\n    // <body> or <template>\n\n    try {\n      if (this.tag.tagName === \"body\") {\n        this.addBodyAttrs(this.tag.attribs);\n\n        // We may be one of many `<body>` tags.\n        this.results.body += this.tag.contents;\n      } else {\n        this.throwCompileError(\"Expected <head> or <body> tag\", this.tag.tagStartIndex);\n      }\n    } catch (e) {\n      if (e.scanner) {\n        // The error came from Spacebars\n        this.throwCompileError(e.message, this.tag.contentsStartIndex + e.offset);\n      } else {\n        throw e;\n      }\n    }\n  }\n\n  addBodyAttrs(attrs) {\n    Object.keys(attrs).forEach((attr) => {\n      const val = attrs[attr];\n\n      // This check is for conflicting body attributes in the same file;\n      // we check across multiple files in caching-html-compiler using the\n      // attributes on results.bodyAttrs\n      if (this.results.bodyAttrs.hasOwnProperty(attr) && this.results.bodyAttrs[attr] !== val) {\n        this.throwCompileError(\n          `<body> declarations have conflicting values for the '${attr}' attribute.`);\n      }\n\n      this.results.bodyAttrs[attr] = val;\n    });\n  }\n\n  throwCompileError(message, overrideIndex) {\n    TemplatingTools.throwCompileError(this.tag, message, overrideIndex);\n  }\n}\n\n"
  },
  {
    "path": "packages/stylus/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/stylus/.npm/plugin/compileStylus/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/stylus/.npm/plugin/compileStylus/README",
    "content": "This directory and the files immediately inside it are automatically generated   \nwhen you change this package's NPM dependencies. Commit the files in this    \ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control   \nso that others run the same versions of sub-dependencies.    \n   \nYou should NOT check in the node_modules directory that Meteor automatically   \ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/stylus/.npm/plugin/compileStylus/npm-shrinkwrap.json",
    "content": "{    \n  \"dependencies\": {    \n    \"nib\": {   \n      \"version\": \"1.0.2\",    \n      \"dependencies\": {    \n        \"stylus\": {    \n          \"version\": \"0.37.0\",   \n          \"dependencies\": {    \n            \"cssom\": {   \n              \"version\": \"0.2.5\"   \n            },   \n            \"mkdirp\": {    \n              \"version\": \"0.3.5\"   \n            },   \n            \"debug\": {   \n              \"version\": \"0.7.4\"   \n            },   \n            \"sax\": {   \n              \"version\": \"0.5.8\"   \n            }    \n          }    \n        }    \n      }    \n    },   \n    \"stylus\": {    \n      \"version\": \"0.46.3\",   \n      \"dependencies\": {    \n        \"css-parse\": {   \n          \"version\": \"1.7.0\"   \n        },   \n        \"mkdirp\": {    \n          \"version\": \"0.3.5\"   \n        },   \n        \"debug\": {   \n          \"version\": \"1.0.1\",    \n          \"dependencies\": {    \n            \"ms\": {    \n              \"version\": \"0.6.2\"   \n            }    \n          }    \n        },   \n        \"sax\": {   \n          \"version\": \"0.5.8\"   \n        },   \n        \"glob\": {    \n          \"version\": \"3.2.11\",   \n          \"dependencies\": {    \n            \"inherits\": {    \n              \"version\": \"2.0.1\"   \n            },   \n            \"minimatch\": {   \n              \"version\": \"0.3.0\",    \n              \"dependencies\": {    \n                \"lru-cache\": {   \n                  \"version\": \"2.5.0\"   \n                },   \n                \"sigmund\": {   \n                  \"version\": \"1.0.0\"   \n                }    \n              }    \n            }    \n          }    \n        }    \n      }    \n    }    \n  }    \n}\n"
  },
  {
    "path": "packages/stylus/.npm/plugin/compileStylusBatch/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/stylus/.npm/plugin/compileStylusBatch/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/stylus/.npm/plugin/compileStylusBatch/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"nib\": {\n      \"version\": \"1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/nib/-/nib-1.1.0.tgz\",\n      \"from\": \"https://registry.npmjs.org/nib/-/nib-1.1.0.tgz\",\n      \"dependencies\": {\n        \"stylus\": {\n          \"version\": \"0.49.3\",\n          \"resolved\": \"https://registry.npmjs.org/stylus/-/stylus-0.49.3.tgz\",\n          \"from\": \"https://registry.npmjs.org/stylus/-/stylus-0.49.3.tgz\",\n          \"dependencies\": {\n            \"css-parse\": {\n              \"version\": \"1.7.0\",\n              \"resolved\": \"https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz\"\n            },\n            \"debug\": {\n              \"version\": \"2.2.0\",\n              \"resolved\": \"https://registry.npmjs.org/debug/-/debug-2.2.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/debug/-/debug-2.2.0.tgz\",\n              \"dependencies\": {\n                \"ms\": {\n                  \"version\": \"0.7.1\",\n                  \"resolved\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\"\n                }\n              }\n            },\n            \"glob\": {\n              \"version\": \"3.2.11\",\n              \"resolved\": \"https://registry.npmjs.org/glob/-/glob-3.2.11.tgz\",\n              \"from\": \"https://registry.npmjs.org/glob/-/glob-3.2.11.tgz\",\n              \"dependencies\": {\n                \"inherits\": {\n                  \"version\": \"2.0.1\",\n                  \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\"\n                },\n                \"minimatch\": {\n                  \"version\": \"0.3.0\",\n                  \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz\",\n                  \"dependencies\": {\n                    \"lru-cache\": {\n                      \"version\": \"2.6.5\",\n                      \"resolved\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz\",\n                      \"from\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz\"\n                    },\n                    \"sigmund\": {\n                      \"version\": \"1.0.1\",\n                      \"resolved\": \"https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz\",\n                      \"from\": \"https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz\"\n                    }\n                  }\n                }\n              }\n            },\n            \"mkdirp\": {\n              \"version\": \"0.3.5\",\n              \"resolved\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz\",\n              \"from\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz\"\n            },\n            \"sax\": {\n              \"version\": \"0.5.8\",\n              \"resolved\": \"https://registry.npmjs.org/sax/-/sax-0.5.8.tgz\",\n              \"from\": \"https://registry.npmjs.org/sax/-/sax-0.5.8.tgz\"\n            },\n            \"source-map\": {\n              \"version\": \"0.1.43\",\n              \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz\",\n              \"from\": \"https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz\",\n              \"dependencies\": {\n                \"amdefine\": {\n                  \"version\": \"0.1.1\",\n                  \"resolved\": \"https://registry.npmjs.org/amdefine/-/amdefine-0.1.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/amdefine/-/amdefine-0.1.1.tgz\"\n                }\n              }\n            }\n          }\n        }\n      }\n    },\n    \"stylus\": {\n      \"version\": \"0.51.1\",\n      \"resolved\": \"https://github.com/meteor/stylus/tarball/d4352c9cb4056faf238e6bd9f9f2172472b67c5b\",\n      \"from\": \"https://github.com/meteor/stylus/tarball/d4352c9cb4056faf238e6bd9f9f2172472b67c5b\",\n      \"dependencies\": {\n        \"css-parse\": {\n          \"version\": \"1.7.0\",\n          \"resolved\": \"https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz\"\n        },\n        \"debug\": {\n          \"version\": \"2.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/debug/-/debug-2.2.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/debug/-/debug-2.2.0.tgz\",\n          \"dependencies\": {\n            \"ms\": {\n              \"version\": \"0.7.1\",\n              \"resolved\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\"\n            }\n          }\n        },\n        \"glob\": {\n          \"version\": \"3.2.11\",\n          \"resolved\": \"https://registry.npmjs.org/glob/-/glob-3.2.11.tgz\",\n          \"from\": \"https://registry.npmjs.org/glob/-/glob-3.2.11.tgz\",\n          \"dependencies\": {\n            \"inherits\": {\n              \"version\": \"2.0.1\",\n              \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\"\n            },\n            \"minimatch\": {\n              \"version\": \"0.3.0\",\n              \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz\",\n              \"dependencies\": {\n                \"lru-cache\": {\n                  \"version\": \"2.6.5\",\n                  \"resolved\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz\",\n                  \"from\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz\"\n                },\n                \"sigmund\": {\n                  \"version\": \"1.0.1\",\n                  \"resolved\": \"https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz\"\n                }\n              }\n            }\n          }\n        },\n        \"mkdirp\": {\n          \"version\": \"0.5.1\",\n          \"resolved\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz\",\n          \"dependencies\": {\n            \"minimist\": {\n              \"version\": \"0.0.8\",\n              \"resolved\": \"https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz\",\n              \"from\": \"https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz\"\n            }\n          }\n        },\n        \"sax\": {\n          \"version\": \"0.5.8\",\n          \"resolved\": \"https://registry.npmjs.org/sax/-/sax-0.5.8.tgz\",\n          \"from\": \"https://registry.npmjs.org/sax/-/sax-0.5.8.tgz\"\n        },\n        \"source-map\": {\n          \"version\": \"0.1.43\",\n          \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz\",\n          \"from\": \"https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz\",\n          \"dependencies\": {\n            \"amdefine\": {\n              \"version\": \"1.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz\"\n            }\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/stylus/README.md",
    "content": "# stylus\n\n[Stylus](http://learnboost.github.com/stylus/) is a CSS pre-processor with a\nsimple syntax and expressive dynamic behavior. It allows for more compact\nstylesheets and helps reduce code duplication in CSS files.\n\nWith the `stylus` package installed, `.main.styl` files in your application are\nautomatically compiled to CSS and the results are included in the client CSS\nbundle.\n\nThe `stylus` package also includes `nib` support. Add `@import 'nib'` to your\n`.main.styl` files to enable cross-browser mixins such as `linear-gradient` and\n`border-radius`.\n\nIf you want to `@import` a file, give it the extension `.import.styl`\nto prevent Meteor from processing it independently.\n\nSee <http://tj.github.io/nib/> for documentation of the nib extensions of Stylus.\n\n\n## Usage\n\nThe package processes all `.styl` files, treating `.styl` as entry points\nand all files with extension `.import.styl` or a file in under an `imports`\nfolder as an import.\n\nAlso, if a file is added in a package, a special `isImport: true` option can be\npassed to mark it as an import: `api.add('styles.styl', 'client', {isImport: true})`.\n\nExample:\n\nA component stylus file, importable, but not an entry-point:\n\n```stylus\n// app/components/my-component/styles.import.styl\n$primary-color = #A7A7A7\n.my-component\n  input\n    border 1px solid\n  textarea\n    color $primary-color\n```\n\nThe main app entry point for the styles, `app.styl`:\n\n```stylus\n// app/app.styl\n@import './components/my-component/styles.import'\n\n// ... rest of app styles\n```\n\n\n## Cross-packages imports\n\nThis package allows apps to import Stylus styles from packages and vice-versa.\nThe import syntax from importing files from other packages is curly braces:\n\n```javasciprt\n// in procoder:fancy-buttons package's package.js file\n...\napi.add('styles/buttons.styl', 'client', {isImport: true});\n...\n```\n\n```stylus\n// app.styl\n// import styles from a package\n@import '{procoder:fancy-buttons}/styles/buttons.styl'\n\n// use imported styles in our code\n.my-buttons\n  @extend .fancy-buttons\n  color: white\n```\n\nTo import a file from the app, leave the content of curly braces empty:\n\n```stylus\n// packages/my-package/generic-buttons.styl\n// import the base styles from app\n@import '{}/client/imports/colors.styl'\n\n// use the colors from app in this component\n.generic-buttons\n  background-color: $app-base-color\n```\n\n\n## Limitations\n\nSince this package uses custom code for `@import`s, some of the import syntax is\nnot supported at the moment:\n\n- globbing: `@import './folder/*'`\n- importing `index.styl`: `@import ./folder/` - should automatically load\n  `./folder/index.styl`\n\n"
  },
  {
    "path": "packages/stylus/package.js",
    "content": "Package.describe({\n  summary: 'Expressive, dynamic, robust CSS',\n  version: \"2.512.3_1\"\n});\n\nPackage.registerBuildPlugin({\n  name: 'compileStylusBatch',\n  use: ['ecmascript', 'caching-compiler'],\n  sources: [\n    'plugin/compile-stylus.js'\n  ],\n  npmDependencies: {\n    stylus: \"https://github.com/meteor/stylus/tarball/d4352c9cb4056faf238e6bd9f9f2172472b67c5b\", // fork of 0.51.1\n    nib: \"1.1.0\"\n  }\n});\n\nPackage.onUse(function (api) {\n  api.use('isobuild:compiler-plugin@1.0.0');\n});\n\nPackage.onTest(function (api) {\n  api.use(['tinytest', 'stylus', 'test-helpers', 'templating']);\n  api.addFiles([\n    'stylus_tests.html',\n    'stylus_tests.styl',\n    'stylus_tests.import.styl',\n    'stylus_tests.js'\n  ],'client');\n});\n"
  },
  {
    "path": "packages/stylus/plugin/compile-stylus.js",
    "content": "const stylus = Npm.require('stylus');\nconst nib = Npm.require('nib');\nconst Future = Npm.require('fibers/future');\nconst fs = Plugin.fs;\nconst path = Plugin.path;\n\nPlugin.registerCompiler({\n  extensions: ['styl'],\n  archMatching: 'web'\n}, () => new StylusCompiler());\n\n// CompileResult is {css, sourceMap}.\nclass StylusCompiler extends MultiFileCachingCompiler {\n  constructor() {\n    super({\n      compilerName: 'stylus',\n      defaultCacheSize: 1024*1024*10,\n    });\n  }\n\n  getCacheKey(inputFile) {\n    return inputFile.getSourceHash();\n  }\n\n  compileResultSize(compileResult) {\n    return compileResult.css.length +\n      this.sourceMapSize(compileResult.sourceMap);\n  }\n\n  // The heuristic is that a file is an import (ie, is not itself\n  // processed as a root) if it matches *.import.styl.  This can be\n  // overridden in either direction via an explicit `isImport` file option\n  // in api.addFiles.\n  isRoot(inputFile) {\n    const fileOptions = inputFile.getFileOptions();\n    if (fileOptions.hasOwnProperty('isImport')) {\n      return !fileOptions.isImport;\n    }\n\n    const pathInPackage = inputFile.getPathInPackage();\n    return ! /\\.import\\.styl$/.test(pathInPackage);\n  }\n\n  compileOneFile(inputFile, allFiles) {\n    const referencedImportPaths = [];\n\n    function parseImportPath(filePath, importerDir) {\n      if (! filePath) {\n        throw new Error('filePath is undefined');\n      }\n      if (filePath === inputFile.getPathInPackage()) {\n        return {\n          packageName: inputFile.getPackageName() || '',\n          pathInPackage: inputFile.getPathInPackage()\n        };\n      }\n      if (! filePath.match(/^\\{.*\\}\\//)) {\n        if (! importerDir) {\n          return { packageName: inputFile.getPackageName() || '',\n                   pathInPackage: filePath };\n        }\n\n        // relative path in the same package\n        const parsedImporter = parseImportPath(importerDir, null);\n\n        // resolve path if it is absolute or relative\n        const importPath =\n          (filePath[0] === '/') ? filePath :\n            path.join(parsedImporter.pathInPackage, filePath);\n\n        return {\n          packageName: parsedImporter.packageName,\n          pathInPackage: importPath\n        };\n      }\n\n      const match = /^\\{(.*)\\}\\/(.*)$/.exec(filePath);\n      if (! match) { return null; }\n\n      const [ignored, packageName, pathInPackage] = match;\n      return {packageName, pathInPackage};\n    }\n    function absoluteImportPath(parsed) {\n      return '{' + parsed.packageName + '}/' + parsed.pathInPackage;\n    }\n\n    const importer = {\n      find(importPath, paths) {\n        const parsed = parseImportPath(importPath, paths[paths.length - 1]);\n        if (! parsed) { return null; }\n\n        if (importPath[0] !== '{') {\n          // if it is not a custom syntax path, it could be a lookup in a folder\n          for (let i = paths.length - 1; i >= 0; i--) {\n            const joined = path.join(paths[i], importPath);\n            if (statOrNull(joined)) {\n              return [joined];\n            }\n          }\n        }\n\n        const absolutePath = absoluteImportPath(parsed);\n\n        if (! allFiles.has(absolutePath)) {\n          return null;\n        }\n\n        return [absolutePath];\n      },\n      readFile(filePath) {\n        const isAbsolute = filePath[0] === '/';\n        const isNib =\n                filePath.indexOf('/node_modules/nib/lib/nib/') !== -1;\n        const isStylusBuiltIn =\n                filePath.indexOf('/node_modules/stylus/lib/') !== -1;\n\n        if (isAbsolute || isNib || isStylusBuiltIn) {\n          // absolute path? let the default implementation handle this\n          return fs.readFileSync(filePath, 'utf8');\n        }\n\n        const parsed = parseImportPath(filePath);\n        const absolutePath = absoluteImportPath(parsed);\n\n        referencedImportPaths.push(absolutePath);\n\n        if (! allFiles.has(absolutePath)) {\n          throw new Error(\n            `Cannot read file ${absolutePath} for ${inputFile.getDisplayPath()}`\n          );\n        }\n\n        return allFiles.get(absolutePath).getContentsAsString();\n      }\n    };\n\n    function processSourcemap(sourcemap) {\n      delete sourcemap.file;\n      sourcemap.sourcesContent = sourcemap.sources.map(importer.readFile);\n      sourcemap.sources = sourcemap.sources.map((filePath) => {\n        const parsed = parseImportPath(filePath);\n        if (!parsed.packageName)\n          return parsed.pathInPackage;\n        return 'packages/' + parsed.packageName + '/' + parsed.pathInPackage;\n      });\n\n      return sourcemap;\n    }\n\n    const f = new Future;\n\n    const style = stylus(inputFile.getContentsAsString())\n            .use(nib())\n            .set('filename', inputFile.getPathInPackage())\n            .set('sourcemap', { inline: false, comment: false })\n            .set('cache', false)\n            .set('importer', importer);\n\n    style.render(f.resolver());\n    let css;\n    try {\n      css = f.wait();\n    } catch (e) {\n      inputFile.error({\n        message: 'Stylus compiler error: ' + e.message\n      });\n      return null;\n    }\n    const sourceMap = processSourcemap(style.sourcemap);\n    return {referencedImportPaths, compileResult: {css, sourceMap}};\n  }\n\n  addCompileResult(inputFile, {css, sourceMap}) {\n    inputFile.addStylesheet({\n      path: inputFile.getPathInPackage() + '.css',\n      data: css,\n      sourceMap: sourceMap\n    });\n  }\n}\n\nfunction statOrNull(path) {\n  try {\n    return fs.statSync(path);\n  } catch (e) {\n    return null;\n  }\n}\n"
  },
  {
    "path": "packages/stylus/stylus_tests.html",
    "content": "<template name=\"stylus_test_presence\">\n  <p class=\"stylus-dashy-left-border\"></p>\n</template>\n\n<template name=\"stylus_test_import\">\n  <p class=\"stylus-import-dashy-border stylus-overwrite-color\"></p>\n</template>\n\n"
  },
  {
    "path": "packages/stylus/stylus_tests.import.styl",
    "content": "// Variable used in stylus_test.styl\nimportDashy = dashed\n\n.stylus-overwrite-color\n  font-size: 20px !important\n"
  },
  {
    "path": "packages/stylus/stylus_tests.js",
    "content": "\nTinytest.add(\"stylus - presence\", function(test) {\n\n  var div = document.createElement('div');\n  Blaze.render(Template.stylus_test_presence, div);\n  div.style.display = 'block';\n  document.body.appendChild(div);\n\n  var p = div.querySelector('p');\n  var leftBorder = getStyleProperty(p, 'border-left-style');\n  test.equal(leftBorder, \"dashed\");\n\n  document.body.removeChild(div);\n});\n\nTinytest.add(\"stylus - @import\", function(test) {\n  var div = document.createElement('div');\n  Blaze.render(Template.stylus_test_import, div);\n  div.style.display = 'block';\n  document.body.appendChild(div);\n\n  var p = div.querySelector('p');\n  test.equal(getStyleProperty(p, 'font-size'), \"20px\");\n  test.equal(getStyleProperty(p, 'border-left-style'), \"dashed\");\n\n  document.body.removeChild(div);\n});\n"
  },
  {
    "path": "packages/stylus/stylus_tests.styl",
    "content": "@import \"stylus_tests.import.styl\"\n\n#stylus-tests\n  zoom: 1\n\ndashy = dashed\n\n.stylus-dashy-left-border\n  border-left: 1px dashy black\n\n.stylus-overwrite-size\n  // This property is overwritten in stylus_test.import.styl\n  font-size: 10px\n\n.stylus-import-dashy-border\n  border-left: 1px importDashy black\n"
  },
  {
    "path": "packages/templating/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/templating/README.md",
    "content": "# templating\n\nCompiles Blaze templates defined in `.html` files. Also automatically includes Blaze on the client.\n\nThis build plugin parses all of the HTML files in your app and looks for three top-level tags:\n\n- `<head>` - appended to the `head` section of your HTML\n- `<body>` - appended to the `body` section of your HTML\n- `<template name=\"templateName\">` - compiled into a Blaze template, which can be included with `{{> templateName}} or referenced in JS code with `Template.templateName`.\n\nFor more details, see the [Meteor docs about\ntemplating](http://docs.meteor.com/#/full/livehtmltemplates) and the Blaze\n[project page](https://www.meteor.com/blaze).\n"
  },
  {
    "path": "packages/templating/dynamic.html",
    "content": "<!-- Expects the data context to have a `template` property (the name of\nthe template to render) and an optional `data` property. If the `data`\nproperty is not specified, then the parent data context will be used\ninstead. Uses the __dynamicWithDataContext template below to actually\nrender the template. -->\n<template name=\"__dynamic\">\n  {{checkContext}}\n  {{#if dataContextPresent}}\n    {{# __dynamicWithDataContext}}{{> Template.contentBlock}}{{/__dynamicWithDataContext}}\n  {{else}}\n    {{! if there was no explicit 'data' argument, use the parent context}}\n    {{# __dynamicWithDataContext template=template data=..}}{{> Template.contentBlock}}{{/__dynamicWithDataContext}}\n  {{/if}}\n</template>\n\n<!-- Expects the data context to have a `template` property (the name of\nthe template to render) and a `data` property, which can be falsey. -->\n<template name=\"__dynamicWithDataContext\">\n  {{#with chooseTemplate template}}\n    {{!-- The .. is evaluated inside {{#with ../data}} --}}\n    {{# .. ../data}}{{> Template.contentBlock}}{{/ ..}}\n  {{/with}}\n</template>\n"
  },
  {
    "path": "packages/templating/dynamic.js",
    "content": "var Template = Blaze.Template;\n\n/**\n * @isTemplate true\n * @memberOf Template\n * @function dynamic\n * @summary Choose a template to include dynamically, by name.\n * @locus Templates\n * @param {String} template The name of the template to include.\n * @param {Object} [data] Optional. The data context in which to include the\n * template.\n */\n\nTemplate.__dynamicWithDataContext.helpers({\n  chooseTemplate: function (name) {\n    return Blaze._getTemplate(name, function () {\n      return Template.instance();\n    });\n  }\n});\n\nTemplate.__dynamic.helpers({\n  dataContextPresent: function () {\n    return _.has(this, \"data\");\n  },\n  checkContext: function () {\n    if (! _.has(this, \"template\")) {\n      throw new Error(\"Must specify name in the 'template' argument \" +\n                      \"to {{> Template.dynamic}}.\");\n    }\n\n    _.each(this, function (v, k) {\n      if (k !== \"template\" && k !== \"data\") {\n        throw new Error(\"Invalid argument to {{> Template.dynamic}}: \" +\n                        k);\n      }\n    });\n  }\n});\n"
  },
  {
    "path": "packages/templating/dynamic_tests.html",
    "content": "<template name=\"ui_dynamic_test\">\n  {{> Template.dynamic template=templateName data=templateData}}\n</template>\n\n<template name=\"ui_dynamic_test_no_data\">\n  {{> Template.dynamic template=templateName}}\n</template>\n\n<template name=\"ui_dynamic_test_inherited_data\">\n  {{#with context}}\n    {{> Template.dynamic template=templateName}}\n  {{else}}\n    {{> Template.dynamic template=templateName}}\n  {{/with}}\n</template>\n\n<template name=\"ui_dynamic_test_sub\">\n  test{{foo}}\n</template>\n\n<template name=\"ui_dynamic_test_contentblock\">\n  {{#Template.dynamic template=templateName data=templateData}}contentBlock{{/Template.dynamic}}\n</template>\n\n<template name=\"ui_dynamic_test_contentblock_no_data\">\n  {{# Template.dynamic template=templateName}}contentBlock{{/Template.dynamic}}\n</template>\n\n<template name=\"ui_dynamic_test_sub_contentblock\">\n  test{{foo}}{{>Template.contentBlock}}\n</template>\n\n<template name=\"ui_dynamic_test_falsey_inner_context\">\n  {{#with foo=\"bar\"}}\n    {{> Template.dynamic template=templateName data=context}}\n  {{/with}}\n</template>\n\n<template name=\"ui_dynamic_test_bad_args0\">\n  {{> Template.dynamic}}\n</template>\n\n<template name=\"ui_dynamic_test_bad_args1\">\n  {{> Template.dynamic foo=\"bar\"}}\n</template>\n\n<template name=\"ui_dynamic_test_bad_args2\">\n  {{> Template.dynamic template=\"ui_dynamic_test_sub\" foo=\"bar\"}}\n</template>\n\n<template name=\"ui_dynamic_test_falsey_context\">\n  {{> Template.dynamic template=\"ui_dynamic_test_falsey_context_sub\"}}\n</template>\n\n<template name=\"ui_dynamic_test_falsey_context_sub\">\n  {{foo}}\n</template>\n\n<template name=\"ui_dynamic_backcompat\">\n  {{> UI.dynamic template=templateName data=templateData}}\n</template>\n"
  },
  {
    "path": "packages/templating/dynamic_tests.js",
    "content": "Tinytest.add(\n  \"spacebars - ui-dynamic-template - render template dynamically\", function (test, expect) {\n    var tmpl = Template.ui_dynamic_test;\n\n    var nameVar = new ReactiveVar;\n    var dataVar = new ReactiveVar;\n    tmpl.helpers({\n      templateName: function () {\n        return nameVar.get();\n      },\n      templateData: function () {\n        return dataVar.get();\n      }\n    });\n\n    // No template chosen\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), \"\");\n\n    // Choose the \"ui-dynamic-test-sub\" template, with no data context\n    // passed in.\n    nameVar.set(\"ui_dynamic_test_sub\");\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"test\");\n\n    // Set a data context.\n    dataVar.set({ foo: \"bar\" });\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"testbar\");\n  });\n\n// Same test as above, but the {{> Template.dynamic}} inclusion has no\n// `dataContext` argument.\nTinytest.add(\n  \"spacebars - ui-dynamic-template - render template dynamically, no data context\",\n  function (test, expect) {\n    var tmpl = Template.ui_dynamic_test_no_data;\n\n    var nameVar = new ReactiveVar;\n    tmpl.helpers({\n      templateName: function () {\n        return nameVar.get();\n      }\n    });\n\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), \"\");\n\n    nameVar.set(\"ui_dynamic_test_sub\");\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"test\");\n  });\n\n\nTinytest.add(\n  \"spacebars - ui-dynamic-template - render template \" +\n    \"dynamically, data context gets inherited\",\n  function (test, expect) {\n    var tmpl = Template.ui_dynamic_test_inherited_data;\n\n    var nameVar = new ReactiveVar();\n    var dataVar = new ReactiveVar();\n    tmpl.helpers({\n      templateName: function () {\n        return nameVar.get();\n      },\n      context: function () {\n        return dataVar.get();\n      }\n    });\n\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), \"\");\n\n    nameVar.set(\"ui_dynamic_test_sub\");\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"test\");\n\n    // Set the top-level template's data context; this should be\n    // inherited by the dynamically-chosen template, since the {{>\n    // Template.dynamic}} inclusion didn't include a data argument.\n    dataVar.set({ foo: \"bar\" });\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"testbar\");\n  }\n);\n\nTinytest.add(\n  \"spacebars - ui-dynamic-template - render template dynamically with contentBlock\", function (test, expect) {\n    var tmpl = Template.ui_dynamic_test_contentblock;\n\n    var nameVar = new ReactiveVar;\n    var dataVar = new ReactiveVar;\n    tmpl.helpers({\n      templateName: function () {\n        return nameVar.get();\n      },\n      templateData: function () {\n        return dataVar.get();\n      }\n    });\n\n    // No template chosen\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), \"\");\n\n    // Choose the \"ui-dynamic-test-sub\" template, with no data context\n    // passed in.\n    nameVar.set(\"ui_dynamic_test_sub_contentblock\");\n    Tracker.flush({_throwFirstError: true});\n    test.equal(canonicalizeHtml(div.innerHTML), \"testcontentBlock\");\n\n    // Set a data context.\n    dataVar.set({ foo: \"bar\" });\n    Tracker.flush({_throwFirstError: true});\n    test.equal(canonicalizeHtml(div.innerHTML), \"testbarcontentBlock\");\n  });\n\n// Same test as above, but the {{> Template.dynamic}} inclusion has no\n// `dataContext` argument.\nTinytest.add(\n  \"spacebars - ui-dynamic-template - render template dynamically with contentBlock, no data context\",\n  function (test, expect) {\n    var tmpl = Template.ui_dynamic_test_contentblock_no_data;\n\n    var nameVar = new ReactiveVar;\n    tmpl.helpers({\n      templateName: function () {\n        return nameVar.get();\n      }\n    });\n\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), \"\");\n\n    nameVar.set(\"ui_dynamic_test_sub_contentblock\");\n    Tracker.flush({_throwFirstError: true});\n    test.equal(canonicalizeHtml(div.innerHTML), \"testcontentBlock\");\n  });\n\nTinytest.add(\n  \"spacebars - ui-dynamic-template - render template \" +\n    \"dynamically, data context does not get inherited if \" +\n    \"falsey context is passed in\",\n  function (test, expect) {\n    var tmpl = Template.ui_dynamic_test_falsey_inner_context;\n\n    var nameVar = new ReactiveVar();\n    var dataVar = new ReactiveVar();\n    tmpl.helpers({\n      templateName: function () {\n        return nameVar.get();\n      },\n      context: function () {\n        return dataVar.get();\n      }\n    });\n\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), \"\");\n\n    nameVar.set(\"ui_dynamic_test_sub\");\n    Tracker.flush();\n    // Even though the data context is falsey, we DON'T expect the\n    // subtemplate to inherit the data context from the parent template.\n    test.equal(canonicalizeHtml(div.innerHTML), \"test\");\n  }\n);\n\nTinytest.add(\n  \"spacebars - ui-dynamic-template - render template \" +\n    \"dynamically, bad arguments\",\n  function (test, expect) {\n    var tmplPrefix = \"ui_dynamic_test_bad_args\";\n    var errors = [\n      \"Must specify 'template' as an argument\",\n      \"Must specify 'template' as an argument\",\n      \"Invalid argument to {{> Template.dynamic}}\"\n    ];\n\n    for (var i = 0; i < 3; i++) {\n      var tmpl = Template[tmplPrefix + i];\n      test.throws(function () {\n        Blaze._throwNextException = true;\n        var div = renderToDiv(tmpl);\n      });\n    }\n  }\n);\n\nTinytest.add(\n  \"spacebars - ui-dynamic-template - render template \" +\n    \"dynamically, falsey context\",\n  function (test, expect) {\n    var tmpl = Template.ui_dynamic_test_falsey_context;\n    var subtmpl = Template.ui_dynamic_test_falsey_context_sub;\n\n    var subtmplContext;\n    subtmpl.helpers({foo: function () {\n      subtmplContext = this;\n    }});\n    var div = renderToDiv(tmpl);\n\n    // Because `this` can only be an object, Blaze normalizes falsey\n    // data contexts to {}.\n    test.equal(subtmplContext, {});\n  }\n);\n\nTinytest.add(\n  \"spacebars - ui-dynamic-template - back-compat\", function (test, expect) {\n    var tmpl = Template.ui_dynamic_backcompat;\n\n    var nameVar = new ReactiveVar;\n    var dataVar = new ReactiveVar;\n    tmpl.helpers({\n      templateName: function () {\n        return nameVar.get();\n      },\n      templateData: function () {\n        return dataVar.get();\n      }\n    });\n\n    // No template chosen\n    var div = renderToDiv(tmpl);\n    test.equal(canonicalizeHtml(div.innerHTML), \"\");\n\n    // Choose the \"ui-dynamic-test-sub\" template, with no data context\n    // passed in.\n    nameVar.set(\"ui_dynamic_test_sub\");\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"test\");\n\n    // Set a data context.\n    dataVar.set({ foo: \"bar\" });\n    Tracker.flush();\n    test.equal(canonicalizeHtml(div.innerHTML), \"testbar\");\n  });\n"
  },
  {
    "path": "packages/templating/package.js",
    "content": "Package.describe({\n  summary: \"Allows templates to be defined in .html files\",\n  version: '1.1.12_1'\n});\n\n// Today, this package is closely intertwined with Handlebars, meaning\n// that other templating systems will need to duplicate this logic. In\n// the future, perhaps we should have the concept of a template system\n// registry and a default templating system, ideally per-package.\n\nPackage.registerBuildPlugin({\n  name: \"compileTemplatesBatch\",\n  // minifier-js is a weak dependency of spacebars-compiler; adding it here\n  // ensures that the output is minified.  (Having it as a weak dependency means\n  // that we don't ship uglify etc with built apps just because\n  // boilerplate-generator uses spacebars-compiler.)\n  // XXX maybe uglify should be applied by this plugin instead of via magic\n  // weak dependency.\n  use: [\n    'caching-html-compiler',\n    'ecmascript',\n    'templating-tools'\n  ],\n  sources: [\n    'plugin/compile-templates.js'\n  ]\n});\n\n// This onUse describes the *runtime* implications of using this package.\nPackage.onUse(function (api) {\n  // XXX would like to do the following only when the first html file\n  // is encountered\n\n  api.addFiles('templating.js', 'client');\n  api.export('Template', 'client');\n\n  api.use('underscore'); // only the subset in packages/blaze/microscore.js\n\n  api.use('isobuild:compiler-plugin@1.0.0');\n\n  // html_scanner.js emits client code that calls Meteor.startup and\n  // Blaze, so anybody using templating (eg apps) need to implicitly use\n  // 'meteor' and 'blaze'.\n  api.use(['blaze', 'spacebars']);\n  api.imply(['meteor', 'blaze', 'spacebars'], 'client');\n\n  api.addFiles(['dynamic.html', 'dynamic.js'], 'client');\n});\n"
  },
  {
    "path": "packages/templating/plugin/compile-templates.js",
    "content": "Plugin.registerCompiler({\n  extensions: ['html'],\n  archMatching: 'web',\n  isTemplate: true\n}, () => new CachingHtmlCompiler(\n  \"templating\",\n  TemplatingTools.scanHtmlForTags,\n  TemplatingTools.compileTagsWithSpacebars\n));\n"
  },
  {
    "path": "packages/templating/templating.js",
    "content": "\n// Packages and apps add templates on to this object.\n\n/**\n * @summary The class for defining templates\n * @class\n * @instanceName Template.myTemplate\n */\nTemplate = Blaze.Template;\n\nvar RESERVED_TEMPLATE_NAMES = \"__proto__ name\".split(\" \");\n\n// Check for duplicate template names and illegal names that won't work.\nTemplate.__checkName = function (name) {\n  // Some names can't be used for Templates. These include:\n  //  - Properties Blaze sets on the Template object.\n  //  - Properties that some browsers don't let the code to set.\n  //    These are specified in RESERVED_TEMPLATE_NAMES.\n  if (name in Template || _.contains(RESERVED_TEMPLATE_NAMES, name)) {\n    if ((Template[name] instanceof Template) && name !== \"body\")\n      throw new Error(\"There are multiple templates named '\" + name + \"'. Each template needs a unique name.\");\n    throw new Error(\"This template name is reserved: \" + name);\n  }\n};\n\n// XXX COMPAT WITH 0.8.3\nTemplate.__define__ = function (name, renderFunc) {\n  Template.__checkName(name);\n  Template[name] = new Template(\"Template.\" + name, renderFunc);\n  // Exempt packages built pre-0.9.0 from warnings about using old\n  // helper syntax, because we can.  It's not very useful to get a\n  // warning about someone else's code (like a package on Atmosphere),\n  // and this should at least put a bit of a dent in number of warnings\n  // that come from packages that haven't been updated lately.\n  Template[name]._NOWARN_OLDSTYLE_HELPERS = true;\n};\n\n// Define a template `Template.body` that renders its\n// `contentRenderFuncs`.  `<body>` tags (of which there may be\n// multiple) will have their contents added to it.\n\n/**\n * @summary The [template object](#templates_api) representing your `<body>`\n * tag.\n * @locus Client\n */\nTemplate.body = new Template('body', function () {\n  var view = this;\n  return _.map(Template.body.contentRenderFuncs, function (func) {\n    return func.apply(view);\n  });\n});\nTemplate.body.contentRenderFuncs = []; // array of Blaze.Views\nTemplate.body.view = null;\n\nTemplate.body.addContent = function (renderFunc) {\n  Template.body.contentRenderFuncs.push(renderFunc);\n};\n\n// This function does not use `this` and so it may be called\n// as `Meteor.startup(Template.body.renderIntoDocument)`.\nTemplate.body.renderToDocument = function () {\n  // Only do it once.\n  if (Template.body.view)\n    return;\n\n  var view = Blaze.render(Template.body, document.body);\n  Template.body.view = view;\n};\n\n// XXX COMPAT WITH 0.9.0\nUI.body = Template.body;\n\n// XXX COMPAT WITH 0.9.0\n// (<body> tags in packages built with 0.9.0)\nTemplate.__body__ = Template.body;\nTemplate.__body__.__contentParts = Template.body.contentViews;\nTemplate.__body__.__instantiate = Template.body.renderToDocument;\n"
  },
  {
    "path": "packages/templating-tools/README.md",
    "content": "# templating-tools\n\nHas some conveniently abstracted functions that are used together with the `caching-html-compiler` package to implement different template compilers:\n\n1. `templating`\n2. `static-html`\n\nThese functions contain some code shared between the above build plugins, and if you are building your own build plugin they can be useful too. But they aren't guaranteed to be helpful for every use case, so you should carefully decide if they are appropriate for your package.\n\n---------\n\n### TemplatingTools.scanHtmlForTags(options)\n\nScan an HTML file for top-level tags as specified by `options.tagNames`, and return an array of `Tag` objects. See more about `Tag` objects below.\n\n#### Options\n\n1. `sourceName` the name of the input file, used when throwing errors.\n2. `contents` the contents of the input file, these are parsed to find the top-level tags\n3. `tagNames` the top-level tags to look for in the HTML.\n\n#### Example\n\n```js\nconst tags = scanHtmlForTags({\n  sourceName: inputPath,\n  contents: contents,\n  tagNames: [\"body\", \"head\", \"template\"]\n});\n```\n\n### TemplatingTools.compileTagsWithSpacebars(tags)\n\nTransform an array of tags into a result object of the following form:\n\n```js\n{\n  js: String,\n  body: \"\",\n  head: String,\n  bodyAttrs: {\n    [attrName]: String\n  }\n}\n```\n\n1. The contents of every `<template>` and `<body>` tag will be compiled into JavaScript with `spacebars-compiler`, and the code appended to the `js` field of the result.\n2. The contents of every `<head>` tag will be concatenated into the `head` field of the result.\n3. Any attributes found on `<body>` tags will be added to the `bodyAtts` field of the result.\n4. Every `<template>` tag is required to have a `name` attribute, and no other attributes.\n5. The `<head>` tag is not allowed to have any attributes.\n\n### TemplatingTools.CompileError\n\nThis error is thrown when a compilation error happens. If you catch it, look for the following fields, which are set by `TemplatingTools.throwCompileError`:\n\n1. `message` The error message to show to the user.\n2. `file` The filename where the error occured.\n3. `line` The line number where the error occured.\n\n### TemplatingTools.throwCompileError(tag, message, [overrideIndex])\n\nThrow a `TemplatingTools.CompileError` with the right properties. Handles generating the line number of the error for you.\n\n#### Arguments\n\n1. `tag` the Tag object in which this compile error occured. The fields on this object are used to populate fields on the resulting error.\n2. `message` the error message, will be displayed to the user.\n3. `overrideIndex` optional - if provided will be used to determine the line number of the error; otherwise the index of the start of the tag will be used.\n\n### Tag object\n\nThe `scanHtml` and `compileTagsWithSpacebars` functions communicate via an array of Tag objects, which have the following form:\n\n```js\n{\n  // Name of the tag - \"body\", \"head\", \"template\", etc\n  tagName: String,\n  \n  // Attributes on the tag\n  attribs: { [attrName]: String },\n  \n  // Contents of the tag\n  contents: String,\n  \n  // Starting index of the opening tag in the source file\n  // (used to throw informative errors)\n  tagStartIndex: Number,\n  \n  // Starting index of the contents of the tag in the source file\n  // (used to throw informative errors)\n  contentsStartIndex: Number,\n  \n  // The contents of the entire source file, should be used only to\n  // throw informative errors (for example, this can be used to\n  // determine the line number for an error)\n  fileContents: String,\n  \n  // The file name of the initial source file, used to throw errors\n  sourceName: String\n};\n```\n"
  },
  {
    "path": "packages/templating-tools/code-generation.js",
    "content": "TemplatingTools.generateTemplateJS =\nfunction generateTemplateJS(name, renderFuncCode) {\n  const nameLiteral = JSON.stringify(name);\n  const templateDotNameLiteral = JSON.stringify(`Template.${name}`);\n\n  return `\nTemplate.__checkName(${nameLiteral});\nTemplate[${nameLiteral}] = new Template(${templateDotNameLiteral}, ${renderFuncCode});\n`;\n}\n\nTemplatingTools.generateBodyJS =\nfunction generateBodyJS(renderFuncCode) {\n  return `\nTemplate.body.addContent(${renderFuncCode});\nMeteor.startup(Template.body.renderToDocument);\n`;\n}\n"
  },
  {
    "path": "packages/templating-tools/compile-tags-with-spacebars.js",
    "content": "TemplatingTools.compileTagsWithSpacebars = function compileTagsWithSpacebars(tags) {\n  var handler = new SpacebarsTagCompiler();\n\n  tags.forEach((tag) => {\n    handler.addTagToResults(tag);\n  });\n\n  return handler.getResults();\n};\n\nclass SpacebarsTagCompiler {\n  constructor() {\n    this.results = {\n      head: '',\n      body: '',\n      js: '',\n      bodyAttrs: {}\n    };\n  }\n\n  getResults() {\n    return this.results;\n  }\n\n  addTagToResults(tag) {\n    this.tag = tag;\n\n    // do we have 1 or more attributes?\n    const hasAttribs = ! _.isEmpty(this.tag.attribs);\n\n    if (this.tag.tagName === \"head\") {\n      if (hasAttribs) {\n        this.throwCompileError(\"Attributes on <head> not supported\");\n      }\n\n      this.results.head += this.tag.contents;\n      return;\n    }\n\n\n    // <body> or <template>\n\n    try {\n      if (this.tag.tagName === \"template\") {\n        const name = this.tag.attribs.name;\n\n        if (! name) {\n          this.throwCompileError(\"Template has no 'name' attribute\");\n        }\n\n        if (SpacebarsCompiler.isReservedName(name)) {\n          this.throwCompileError(`Template can't be named \"${name}\"`);\n        }\n\n        const renderFuncCode = SpacebarsCompiler.compile(this.tag.contents, {\n          isTemplate: true,\n          sourceName: `Template \"${name}\"`\n        });\n\n        this.results.js += TemplatingTools.generateTemplateJS(\n          name, renderFuncCode);\n      } else if (this.tag.tagName === \"body\") {\n        this.addBodyAttrs(this.tag.attribs);\n\n        const renderFuncCode = SpacebarsCompiler.compile(this.tag.contents, {\n          isBody: true,\n          sourceName: \"<body>\"\n        });\n\n        // We may be one of many `<body>` tags.\n        this.results.js += TemplatingTools.generateBodyJS(renderFuncCode);\n      } else {\n        this.throwCompileError(\"Expected <template>, <head>, or <body> tag in template file\", tagStartIndex);\n      }\n    } catch (e) {\n      if (e.scanner) {\n        // The error came from Spacebars\n        this.throwCompileError(e.message, this.tag.contentsStartIndex + e.offset);\n      } else {\n        throw e;\n      }\n    }\n  }\n\n  addBodyAttrs(attrs) {\n    Object.keys(attrs).forEach((attr) => {\n      const val = attrs[attr];\n\n      // This check is for conflicting body attributes in the same file;\n      // we check across multiple files in caching-html-compiler using the\n      // attributes on results.bodyAttrs\n      if (this.results.bodyAttrs.hasOwnProperty(attr) && this.results.bodyAttrs[attr] !== val) {\n        this.throwCompileError(\n          `<body> declarations have conflicting values for the '${attr}' attribute.`);\n      }\n\n      this.results.bodyAttrs[attr] = val;\n    });\n  }\n\n  throwCompileError(message, overrideIndex) {\n    TemplatingTools.throwCompileError(this.tag, message, overrideIndex);\n  }\n}\n"
  },
  {
    "path": "packages/templating-tools/html-scanner-tests.js",
    "content": "Tinytest.add(\"templating-tools - html scanner\", function (test) {\n  var testInString = function(actualStr, wantedContents) {\n    if (actualStr.indexOf(wantedContents) >= 0)\n      test.ok();\n    else\n      test.fail(\"Expected \"+JSON.stringify(wantedContents)+\n                \" in \"+JSON.stringify(actualStr));\n  };\n\n  var checkError = function(f, msgText, lineNum) {\n    try {\n      f();\n    } catch (e) {\n      if (! e instanceof TemplatingTools.CompileError) {\n        throw e;\n      }\n\n      if (e.line === lineNum)\n        test.ok();\n      else\n        test.fail(\"Error should have been on line \" + lineNum + \", not \" +\n                  e.line);\n      testInString(e.message, msgText);\n      return;\n    }\n    test.fail(\"Parse error didn't throw exception\");\n  };\n\n  // returns the appropriate code to put content in the body,\n  // where content is something simple like the string \"Hello\"\n  // (passed in as a source string including the quotes).\n  var simpleBody = function (content) {\n    return \"\\nTemplate.body.addContent((function() {\\n  var view = this;\\n  return \" + content + \";\\n}));\\nMeteor.startup(Template.body.renderToDocument);\\n\";\n  };\n\n  // arguments are quoted strings like '\"hello\"'\n  var simpleTemplate = function (templateName, content) {\n    // '\"hello\"' into '\"Template.hello\"'\n    var viewName = templateName.slice(0, 1) + 'Template.' + templateName.slice(1);\n\n    return '\\nTemplate.__checkName(' + templateName + ');\\nTemplate[' + templateName +\n      '] = new Template(' + viewName +\n      ', (function() {\\n  var view = this;\\n  return ' + content + ';\\n}));\\n';\n  };\n\n  var checkResults = function(results, expectJs, expectHead, expectBodyAttrs) {\n    test.equal(results.body, '');\n    test.equal(results.js, expectJs || '');\n    test.equal(results.head, expectHead || '');\n    test.equal(results.bodyAttrs, expectBodyAttrs || {});\n  };\n\n  function scanForTest(contents) {\n    const tags = TemplatingTools.scanHtmlForTags({\n      sourceName: \"\",\n      contents: contents,\n      tagNames: [\"body\", \"head\", \"template\"]\n    });\n\n    return TemplatingTools.compileTagsWithSpacebars(tags);\n  }\n\n  checkError(function() {\n    return scanForTest(\"asdf\");\n  }, \"Expected one of: <body>, <head>, <template>\", 1);\n\n  // body all on one line\n  checkResults(\n    scanForTest(\"<body>Hello</body>\"),\n    simpleBody('\"Hello\"'));\n\n  // multi-line body, contents trimmed\n  checkResults(\n    scanForTest(\"\\n\\n\\n<body>\\n\\nHello\\n\\n</body>\\n\\n\\n\"),\n    simpleBody('\"Hello\"'));\n\n  // same as previous, but with various HTML comments\n  checkResults(\n    scanForTest(\"\\n<!--\\n\\nfoo\\n-->\\n<!-- -->\\n\"+\n                      \"<body>\\n\\nHello\\n\\n</body>\\n\\n<!----\\n>\\n\\n\"),\n    simpleBody('\"Hello\"'));\n\n  // head and body\n  checkResults(\n    scanForTest(\"<head>\\n<title>Hello</title>\\n</head>\\n\\n<body>World</body>\\n\\n\"),\n    simpleBody('\"World\"'),\n    \"<title>Hello</title>\");\n\n  // head and body with tag whitespace\n  checkResults(\n    scanForTest(\"<head\\n>\\n<title>Hello</title>\\n</head  >\\n\\n<body>World</body\\n\\n>\\n\\n\"),\n    simpleBody('\"World\"'),\n    \"<title>Hello</title>\");\n\n  // head, body, and template\n  checkResults(\n    scanForTest(\"<head>\\n<title>Hello</title>\\n</head>\\n\\n<body>World</body>\\n\\n\"+\n                      '<template name=\"favoritefood\">\\n  pizza\\n</template>\\n'),\n    simpleBody('\"World\"') + simpleTemplate('\"favoritefood\"', '\"pizza\"'),\n    \"<title>Hello</title>\");\n\n  // one-line template\n  checkResults(\n    scanForTest('<template name=\"favoritefood\">pizza</template>'),\n    simpleTemplate('\"favoritefood\"', '\"pizza\"'));\n\n  // template with other attributes\n  checkResults(\n    scanForTest('<template foo=\"bar\" name=\"favoritefood\" baz=\"qux\">'+\n                      'pizza</template>'),\n    simpleTemplate('\"favoritefood\"', '\"pizza\"'));\n\n  // whitespace around '=' in attributes and at end of tag\n  checkResults(\n    scanForTest('<template foo = \"bar\" name  =\"favoritefood\" baz= \"qux\"  >'+\n                      'pizza</template\\n\\n>'),\n    simpleTemplate('\"favoritefood\"', '\"pizza\"'));\n\n  // whitespace around template name\n  checkResults(\n    scanForTest('<template name=\" favoritefood  \">pizza</template>'),\n    simpleTemplate('\"favoritefood\"', '\"pizza\"'));\n\n  // single quotes around template name\n  checkResults(\n    scanForTest('<template name=\\'the \"cool\" template\\'>'+\n                      'pizza</template>'),\n    simpleTemplate('\"the \\\\\"cool\\\\\" template\"', '\"pizza\"'));\n\n  checkResults(scanForTest('<body foo=\"bar\">\\n  Hello\\n</body>'), simpleBody('\"Hello\"'), \"\", {foo: \"bar\"});\n\n  // error cases; exact line numbers are not critical, these just reflect\n  // the current implementation\n\n  // unclosed body (error mentions body)\n  checkError(function() {\n    return scanForTest(\"\\n\\n<body>\\n  Hello\\n</body\");\n  }, \"body\", 3);\n\n  // bad open tag\n  checkError(function() {\n    return scanForTest(\"\\n\\n\\n<bodyd>\\n  Hello\\n</body>\");\n  }, \"Expected one of: <body>, <head>, <template>\", 4);\n  checkError(function() {\n    return scanForTest(\"\\n\\n\\n\\n<body foo=>\\n  Hello\\n</body>\");\n  }, \"error in tag\", 5);\n\n  // unclosed tag\n  checkError(function() {\n    return scanForTest(\"\\n<body>Hello\");\n  }, \"nclosed\", 2);\n\n  // unnamed template\n  checkError(function() {\n    return scanForTest(\n      \"\\n\\n<template>Hi</template>\\n\\n<template>Hi</template>\");\n  }, \"name\", 3);\n\n  // helpful doctype message\n  checkError(function() {\n    return scanForTest(\n      '<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" '+\n        '\"http://www.w3.org/TR/html4/strict.dtd\">'+\n        '\\n\\n<head>\\n</head>');\n  }, \"DOCTYPE\", 1);\n\n  // lowercase basic doctype\n  checkError(function() {\n    return scanForTest(\n      '<!doctype html>');\n  }, \"DOCTYPE\", 1);\n\n  // attributes on head not supported\n  checkError(function() {\n    return scanForTest('<head foo=\"bar\">\\n  Hello\\n</head>');\n  }, \"<head>\", 1);\n\n  // can't mismatch quotes\n  checkError(function() {\n    return scanForTest('<template name=\"foo\\'>'+\n                             'pizza</template>');\n  }, \"error in tag\", 1);\n\n  // unexpected <html> at top level\n  checkError(function() {\n    return scanForTest('\\n<html>\\n</html>');\n  }, \"Expected one of: <body>, <head>, <template>\", 2);\n\n});\n"
  },
  {
    "path": "packages/templating-tools/html-scanner.js",
    "content": "TemplatingTools.scanHtmlForTags = function scanHtmlForTags(options) {\n  const scan = new HtmlScan(options);\n  return scan.getTags();\n};\n\n/**\n * Scan an HTML file for top-level tags and extract their contents. Pass them to\n * a tag handler (an object with a handleTag method)\n *\n * This is a primitive, regex-based scanner.  It scans \n * top-level tags, which are allowed to have attributes,\n * and ignores top-level HTML comments.\n */\nclass HtmlScan {\n  /**\n   * Initialize and run a scan of a single file\n   * @param  {String} sourceName The filename, used in errors only\n   * @param  {String} contents   The contents of the file\n   * @param  {String[]} tagNames An array of tag names that are accepted at the\n   * top level. If any other tag is encountered, an error is thrown.\n   */\n  constructor({\n        sourceName,\n        contents,\n        tagNames\n      }) {\n    this.sourceName = sourceName;\n    this.contents = contents;\n    this.tagNames = tagNames;\n\n    this.rest = contents;\n    this.index = 0;\n\n    this.tags = [];\n\n    tagNameRegex = this.tagNames.join(\"|\");\n    const openTagRegex = new RegExp(`^((<(${tagNameRegex})\\\\b)|(<!--)|(<!DOCTYPE|{{!)|$)`, \"i\");\n\n    while (this.rest) {\n      // skip whitespace first (for better line numbers)\n      this.advance(this.rest.match(/^\\s*/)[0].length);\n\n      const match = openTagRegex.exec(this.rest);\n\n      if (! match) {\n        this.throwCompileError(`Expected one of: <${this.tagNames.join('>, <')}>`);\n      }\n\n      const matchToken = match[1];\n      const matchTokenTagName =  match[3];\n      const matchTokenComment = match[4];\n      const matchTokenUnsupported = match[5];\n\n      const tagStartIndex = this.index;\n      this.advance(match.index + match[0].length);\n\n      if (! matchToken) {\n        break; // matched $ (end of file)\n      }\n\n      if (matchTokenComment === '<!--') {\n        // top-level HTML comment\n        const commentEnd = /--\\s*>/.exec(this.rest);\n        if (! commentEnd)\n          this.throwCompileError(\"unclosed HTML comment in template file\");\n        this.advance(commentEnd.index + commentEnd[0].length);\n        continue;\n      }\n\n      if (matchTokenUnsupported) {\n        switch (matchTokenUnsupported.toLowerCase()) {\n        case '<!doctype':\n          this.throwCompileError(\n            \"Can't set DOCTYPE here.  (Meteor sets <!DOCTYPE html> for you)\");\n        case '{{!':\n          this.throwCompileError(\n            \"Can't use '{{! }}' outside a template.  Use '<!-- -->'.\");\n        }\n\n        this.throwCompileError();\n      }\n\n      // otherwise, a <tag>\n      const tagName = matchTokenTagName.toLowerCase();\n      const tagAttribs = {}; // bare name -> value dict\n      const tagPartRegex = /^\\s*((([a-zA-Z0-9:_-]+)\\s*=\\s*([\"'])(.*?)\\4)|(>))/;\n\n      // read attributes\n      let attr;\n      while ((attr = tagPartRegex.exec(this.rest))) {\n        const attrToken = attr[1];\n        const attrKey = attr[3];\n        let attrValue = attr[5];\n        this.advance(attr.index + attr[0].length);\n\n        if (attrToken === '>') {\n          break;\n        }\n\n        // XXX we don't HTML unescape the attribute value\n        // (e.g. to allow \"abcd&quot;efg\") or protect against\n        // collisions with methods of tagAttribs (e.g. for\n        // a property named toString)\n        attrValue = attrValue.match(/^\\s*([\\s\\S]*?)\\s*$/)[1]; // trim\n        tagAttribs[attrKey] = attrValue;\n      }\n\n      if (! attr) { // didn't end on '>'\n        this.throwCompileError(\"Parse error in tag\");\n      }\n\n      // find </tag>\n      const end = (new RegExp('</'+tagName+'\\\\s*>', 'i')).exec(this.rest);\n      if (! end) {\n        this.throwCompileError(\"unclosed <\"+tagName+\">\");\n      }\n\n      const tagContents = this.rest.slice(0, end.index);\n      const contentsStartIndex = this.index;\n\n      // trim the tag contents.\n      // this is a courtesy and is also relied on by some unit tests.\n      var m = tagContents.match(/^([ \\t\\r\\n]*)([\\s\\S]*?)[ \\t\\r\\n]*$/);\n      const trimmedContentsStartIndex = contentsStartIndex + m[1].length;\n      const trimmedTagContents = m[2];\n\n      const tag = {\n        tagName: tagName,\n        attribs: tagAttribs,\n        contents: trimmedTagContents,\n        contentsStartIndex: trimmedContentsStartIndex,\n        tagStartIndex: tagStartIndex,\n        fileContents: this.contents,\n        sourceName: this.sourceName\n      };\n\n      // save the tag\n      this.tags.push(tag);\n\n      // advance afterwards, so that line numbers in errors are correct\n      this.advance(end.index + end[0].length);\n    }\n  }\n\n  /**\n   * Advance the parser\n   * @param  {Number} amount The amount of characters to advance\n   */\n  advance(amount) {\n    this.rest = this.rest.substring(amount);\n    this.index += amount;\n  }\n\n  throwCompileError(msg, overrideIndex) {\n    const finalIndex = (typeof overrideIndex === 'number' ? overrideIndex : this.index);\n\n    const err = new TemplatingTools.CompileError();\n    err.message = msg || \"bad formatting in template file\";\n    err.file = this.sourceName;\n    err.line = this.contents.substring(0, finalIndex).split('\\n').length;\n\n    throw err;\n  }\n\n  throwBodyAttrsError(msg) {\n    this.parseError(msg);\n  }\n\n  getTags() {\n    return this.tags;\n  }\n}\n"
  },
  {
    "path": "packages/templating-tools/package.js",
    "content": "Package.describe({\n  name: 'templating-tools',\n  version: '1.0.4',\n  // Brief, one-line summary of the package.\n  summary: 'Tools to scan HTML and compile tags when building a templating package',\n  // URL to the Git repository containing the source code for this package.\n  git: 'https://github.com/meteor/meteor',\n  // By default, Meteor will default to using README.md for documentation.\n  // To avoid submitting documentation, set this field to null.\n  documentation: 'README.md'\n});\n\nPackage.onUse(function(api) {\n  api.use([\n    'underscore',\n    'ecmascript',\n    'spacebars-compiler',\n\n    // minifier-js is a weak dependency of spacebars-compiler; adding it here\n    // ensures that the output is minified.  (Having it as a weak dependency means\n    // that we don't ship uglify etc with built apps just because\n    // boilerplate-generator uses spacebars-compiler.)\n    // XXX maybe uglify should be applied by this plugin instead of via magic\n    // weak dependency.\n    'minifier-js'\n  ]);\n\n  api.addFiles([\n    'templating-tools.js',\n    'html-scanner.js',\n    'compile-tags-with-spacebars.js',\n    'throw-compile-error.js',\n    'code-generation.js'\n  ]);\n\n  api.export('TemplatingTools');\n});\n\nPackage.onTest(function(api) {\n  api.use([\n    'tinytest',\n    'templating-tools',\n    'ecmascript'\n  ]);\n\n  api.addFiles('html-scanner-tests.js', 'server');\n});\n"
  },
  {
    "path": "packages/templating-tools/templating-tools.js",
    "content": "TemplatingTools = {\n  // This type of error should be thrown during compilation\n  CompileError: class CompileError {}\n};\n"
  },
  {
    "path": "packages/templating-tools/throw-compile-error.js",
    "content": "TemplatingTools.throwCompileError =\nfunction throwCompileError(tag, message, overrideIndex) {\n  const finalIndex = (typeof overrideIndex === 'number' ?\n    overrideIndex : tag.tagStartIndex);\n\n  const err = new TemplatingTools.CompileError();\n  err.message = message || \"bad formatting in template file\";\n  err.file = tag.sourceName;\n  err.line = tag.fileContents.substring(0, finalIndex).split('\\n').length;\n  throw err;\n}\n"
  },
  {
    "path": "packages/test-helpers/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/test-helpers/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/test-helpers/async_multi.js",
    "content": "// This depends on tinytest, so it's a little weird to put it in\n// test-helpers, but it'll do for now.\n\n// Provides the testAsyncMulti helper, which creates an async test\n// (using Tinytest.addAsync) that tracks parallel and sequential\n// asynchronous calls.  Specifically, the two features it provides\n// are:\n// 1) Executing an array of functions sequentially when those functions\n//    contain async calls.\n// 2) Keeping track of when callbacks are outstanding, via \"expect\".\n//\n// To use, pass an array of functions that take arguments (test, expect).\n// (There is no onComplete callback; completion is determined automatically.)\n// Expect takes a callback closure and wraps it, returning a new callback closure,\n// and making a note that there is a callback oustanding.  Pass this returned closure\n// to async functions as the callback, and the machinery in the wrapper will\n// record the fact that the callback has been called.\n//\n// A second form of expect takes data arguments to test for.\n// Essentially, expect(\"foo\", \"bar\") is equivalent to:\n// expect(function(arg1, arg2) { test.equal([arg1, arg2], [\"foo\", \"bar\"]); }).\n//\n// You cannot \"nest\" expect or call it from a callback!  Even if you have a chain\n// of callbacks, you need to call expect at the \"top level\" (synchronously)\n// but the callback you wrap has to be the last/innermost one.  This sometimes\n// leads to some code contortions and should probably be fixed.\n\n// Example: (at top level of test file)\n//\n// testAsyncMulti(\"test name\", [\n//   function(test, expect) {\n//     ... tests here\n//     Meteor.defer(expect(function() {\n//       ... tests here\n//     }));\n//\n//     call_something_async('foo', 'bar', expect('baz')); // implicit callback\n//\n//   },\n//   function(test, expect) {\n//     ... more tests\n//   }\n// ]);\n\nvar ExpectationManager = function (test, onComplete) {\n  var self = this;\n\n  self.test = test;\n  self.onComplete = onComplete;\n  self.closed = false;\n  self.dead = false;\n  self.outstanding = 0;\n};\n\n_.extend(ExpectationManager.prototype, {\n  expect: function (/* arguments */) {\n    var self = this;\n\n    if (typeof arguments[0] === \"function\")\n      var expected = arguments[0];\n    else\n      var expected = _.toArray(arguments);\n\n    if (self.closed)\n      throw new Error(\"Too late to add more expectations to the test\");\n    self.outstanding++;\n\n    return function (/* arguments */) {\n      if (self.dead)\n        return;\n\n      if (typeof expected === \"function\") {\n        try {\n          expected.apply({}, arguments);\n        } catch (e) {\n          if (self.cancel())\n            self.test.exception(e);\n        }\n      } else {\n        self.test.equal(_.toArray(arguments), expected);\n      }\n\n      self.outstanding--;\n      self._check_complete();\n    };\n  },\n\n  done: function () {\n    var self = this;\n    self.closed = true;\n    self._check_complete();\n  },\n\n  cancel: function () {\n    var self = this;\n    if (! self.dead) {\n      self.dead = true;\n      return true;\n    }\n    return false;\n  },\n\n  _check_complete: function () {\n    var self = this;\n    if (!self.outstanding && self.closed && !self.dead) {\n      self.dead = true;\n      self.onComplete();\n    }\n  }\n});\n\ntestAsyncMulti = function (name, funcs) {\n  // XXX Tests on remote browsers are _slow_. We need a better solution.\n  var timeout = 180000;\n\n  Tinytest.addAsync(name, function (test, onComplete) {\n    var remaining = _.clone(funcs);\n    var context = {};\n    var i = 0;\n\n    var runNext = function () {\n      var func = remaining.shift();\n      if (!func) {\n        delete test.extraDetails.asyncBlock;\n        onComplete();\n      }\n      else {\n        var em = new ExpectationManager(test, function () {\n          Meteor.clearTimeout(timer);\n          runNext();\n        });\n\n        var timer = Meteor.setTimeout(function () {\n          if (em.cancel()) {\n            test.fail({type: \"timeout\", message: \"Async batch timed out\"});\n            onComplete();\n          }\n          return;\n        }, timeout);\n\n        test.extraDetails.asyncBlock = i++;\n        try {\n          func.apply(context, [test, _.bind(em.expect, em)]);\n        } catch (exception) {\n          if (em.cancel())\n            test.exception(exception);\n          Meteor.clearTimeout(timer);\n          // Because we called test.exception, we're not to call onComplete.\n          return;\n        }\n        em.done();\n      }\n    };\n\n    runNext();\n  });\n};\n\n// Call `fn` periodically until it returns true.  If it does, call\n// `success`.  If it doesn't before the timeout, call `failed`.\nsimplePoll = function (fn, success, failed, timeout, step) {\n  timeout = timeout || 10000;\n  step = step || 100;\n  var start = (new Date()).valueOf();\n  var helper = function () {\n    if (fn()) {\n      success();\n      return;\n    }\n    if (start + timeout < (new Date()).valueOf()) {\n      failed();\n      return;\n    }\n    Meteor.setTimeout(helper, step);\n  };\n  helper();\n};\n\npollUntil = function (expect, f, timeout, step, noFail) {\n  noFail = noFail || false;\n  step = step || 100;\n  var expectation = expect(true);\n  simplePoll(\n    f,\n    function () { expectation(true) },\n    function () { expectation(noFail) },\n    timeout,\n    step\n  );\n};\n"
  },
  {
    "path": "packages/test-helpers/callback_logger.js",
    "content": "// This file allows you to write tests that expect certain callbacks to be\n// called in certain orders, or optionally in groups where the order does not\n// matter.  It can be set up in either a synchronous manner, so that each\n// callback must have already occured before you call expectResult & its ilk, or\n// in an asynchronous manner, so that the logger yields and waits a reasonable\n// timeout for the callback.  Because we're using Node Fibers to yield & start\n// ourselves, the asynchronous version is only available on the server.\n\nvar Fiber = Meteor.isServer ? Npm.require('fibers') : null;\n\nvar TIMEOUT = 1000;\n\n// Run the given function, passing it a correctly-set-up callback logger as an\n// argument.  If we're meant to be running asynchronously, the function gets its\n// own Fiber.\n\nwithCallbackLogger = function (test, callbackNames, async, fun) {\n  var logger = new CallbackLogger(test, callbackNames);\n  if (async) {\n    if (!Fiber)\n      throw new Error(\"Fiber is not available\");\n    logger.fiber = Fiber(_.bind(fun, null, logger));\n    logger.fiber.run();\n  } else {\n    fun(logger);\n  }\n};\n\nvar CallbackLogger = function (test, callbackNames) {\n  var self = this;\n  self._log = [];\n  self._test = test;\n  self._yielded = false;\n  _.each(callbackNames, function (callbackName) {\n    self[callbackName] = function () {\n      var args = _.toArray(arguments);\n      self._log.push({callback: callbackName, args: args});\n      if (self.fiber) {\n        setTimeout(function () {\n          if (self._yielded)\n            self.fiber.run(callbackName);\n        }, 0);\n      }\n    };\n  });\n};\n\nCallbackLogger.prototype._yield = function (arg) {\n  var self = this;\n  self._yielded = true;\n  var y = Fiber.yield(arg);\n  self._yielded = false;\n  return y;\n};\n\nCallbackLogger.prototype.expectResult = function (callbackName, args) {\n  var self = this;\n  self._waitForLengthOrTimeout(1);\n  if (_.isEmpty(self._log)) {\n    self._test.fail([\"Expected callback \" + callbackName + \" got none\"]);\n    return;\n  }\n  var result = self._log.shift();\n  self._test.equal(result.callback, callbackName);\n  self._test.equal(result.args, args);\n};\n\nCallbackLogger.prototype.expectResultOnly = function (callbackName, args) {\n  var self = this;\n  self.expectResult(callbackName, args);\n  self._expectNoResultImpl();\n}\n\nCallbackLogger.prototype._waitForLengthOrTimeout = function (len) {\n  var self = this;\n  if (self.fiber) {\n    var timeLeft = TIMEOUT;\n    var startTime = new Date();\n    var handle = setTimeout(function () {\n      self.fiber.run(handle);\n    }, TIMEOUT);\n    while (self._log.length < len) {\n      if (self._yield() === handle) {\n        break;\n      }\n    }\n    clearTimeout(handle);\n  }\n};\n\nCallbackLogger.prototype.expectResultUnordered = function (list) {\n  var self = this;\n\n  self._waitForLengthOrTimeout(list.length);\n\n  list = _.clone(list); // shallow copy.\n  var i = list.length;\n  while (i > 0) {\n    var found = false;\n    var dequeued = self._log.shift();\n    for (var j = 0; j < list.length; j++) {\n      if (_.isEqual(list[j], dequeued)) {\n        list.splice(j, 1);\n        found = true;\n        break;\n      }\n    }\n    if (!found)\n      self._test.fail([\"Found unexpected result: \" + JSON.stringify(dequeued)]);\n    i--;\n  }\n};\n\nCallbackLogger.prototype._expectNoResultImpl = function () {\n  var self = this;\n  self._test.length(self._log, 0);\n};\n\nCallbackLogger.prototype.expectNoResult = function () {\n  var self = this;\n  if (self.fiber) {\n    var handle = setTimeout(function () {\n      self.fiber.run(handle);\n    }, TIMEOUT);\n    var foo = self._yield();\n    while (_.isEmpty(self._log) && foo !== handle) {\n      foo = self._yield();\n    }\n    clearTimeout(handle);\n  }\n  self._expectNoResultImpl();\n};\n"
  },
  {
    "path": "packages/test-helpers/canonicalize_html.js",
    "content": "canonicalizeHtml = function(html) {\n  var h = html;\n  // kill IE-specific comments inserted by DomRange\n  h = h.replace(/<!--IE-->/g, '');\n  h = h.replace(/<!---->/g, '');\n  // ignore exact text of comments\n  h = h.replace(/<!--.*?-->/g, '<!---->');\n  // make all tags lowercase\n  h = h.replace(/<\\/?(\\w+)/g, function(m) {\n    return m.toLowerCase(); });\n  // replace whitespace sequences with spaces\n  h = h.replace(/\\s+/g, ' ');\n  // Trim leading and trailing whitespace\n  h = h.replace(/^\\s+|\\s+$/g, '');\n  // remove whitespace before and after tags\n  h = h.replace(/\\s*(<\\/?\\w.*?>)\\s*/g, function (m, tag) {\n    return tag; });\n  // make tag attributes uniform\n  h = h.replace(/<(\\w+)\\s+(.*?)\\s*>/g, function(m, tagName, attrs) {\n    // Drop expando property used by Sizzle (part of jQuery) which leaks into\n    // attributes in IE8. Note that its value always contains spaces.\n    attrs = attrs.replace(/sizcache[0-9]+=\"[^\"]*\"/g, ' ');\n    // Similarly for expando properties used by jQuery to track data.\n    attrs = attrs.replace(/jQuery[0-9]+=\"[0-9]+\"/g, ' ');\n    // Similarly for expando properties used to DOMBackend to keep\n    // track of callbacks to fire when an element is removed\n    attrs = attrs.replace(/\\$blaze_teardown_callbacks=\"[^\"]*\"/g, ' ');\n    // And by DOMRange to keep track of the element's DOMRange\n    attrs = attrs.replace(/\\$blaze_range=\"[^\"]*\"/g, ' ');\n\n    attrs = attrs.replace(/\\s*=\\s*/g, '=');\n    attrs = attrs.replace(/^\\s+/g, '');\n    attrs = attrs.replace(/\\s+$/g, '');\n    attrs = attrs.replace(/\\s+/g, ' ');\n    // quote unquoted attribute values, as in `type=checkbox`.  This\n    // will do the wrong thing if there's an `=` in an attribute value.\n    attrs = attrs.replace(/(\\w)=([^'\" >/]+)/g, '$1=\"$2\"');\n\n    // for the purpose of splitting attributes in a string like 'a=\"b\"\n    // c=\"d\"', assume they are separated by a single space and values\n    // are double- or single-quoted, but allow for spaces inside the\n    // quotes.  Split on space following quote.\n    var attrList = attrs.replace(/(\\w)='([^']*)' /g, \"$1='$2'\\u0000\");\n    attrList = attrList.replace(/(\\w)=\"([^\"]*)\" /g, '$1=\"$2\"\\u0000');\n    attrList = attrList.split(\"\\u0000\");\n    // put attributes in alphabetical order\n    attrList.sort();\n\n    var tagContents = [tagName];\n\n    for(var i=0; i<attrList.length; i++) {\n      // If there were no attrs, attrList could be `[\"\"]`,\n      // so skip falsy values.\n      if (! attrList[i])\n        continue;\n      var a = attrList[i].split('=');\n\n      // In IE8, attributes whose value is \"\" appear\n      // without the '=' sign altogether.\n      if (a.length < 2)\n        a.push(\"\");\n\n      var key = a[0];\n      // Drop another expando property used by Sizzle.\n      if (key === 'sizset')\n        continue;\n      var value = a[1];\n\n      // make sure the attribute is doubled-quoted\n      if (value.charAt(0) === '\"') {\n        // Do nothing\n      } else {\n        if (value.charAt(0) !== \"'\") {\n          // attribute is unquoted. should be unreachable because of\n          // regex above.\n          value = '\"' + value + '\"';\n        } else {\n          // attribute is single-quoted. make it double-quoted.\n          value = value.replace(/\\\"/g, \"&quot;\");\n        }\n        value = value.replace(/[\"'`]/g, '\"');\n      }\n\n      // Encode quotes and double quotes in the attribute.\n      var attr = value.slice(1, -1);\n      attr = attr.replace(/\\\"/g, \"&quot;\");\n      attr = attr.replace(/\\'/g, \"&quot;\");\n      value = '\"' + attr + '\"';\n\n      // Ensure that styles do not end with a semicolon.\n      if (key === 'style') {\n        value = value.replace(/;\\\"$/, '\"');\n      }\n\n      tagContents.push(key+'='+value);\n    }\n    return '<'+tagContents.join(' ')+'>';\n  });\n  return h;\n};\n"
  },
  {
    "path": "packages/test-helpers/connection.js",
    "content": "// Establish a connection from the server to the server, and wait\n// until the client side of the connection has received the session\n// id.  On success call `succeeded` with two arguments, the client\n// side connection and the server side connection handle.  Call `failed` on\n// failure.\nmakeTestConnection = function (test, succeeded, failed) {\n  // The connection from the client side.\n  var clientConn;\n\n  // Track incoming connections server side until we know which one is\n  // ours.\n  var serverConns = {};\n\n  // Add incoming connections to `serverConns`.\n  var onConnectionHandle = Meteor.onConnection(function (serverConn) {\n    test.isTrue(_.isString(serverConn.id), \"connection handle id exists and is a string\");\n    if (serverConns[serverConn.id]) {\n      test.fail(\"onConnection callback called multiple times for same session id\");\n      failed();\n    } else {\n      serverConns[serverConn.id] = serverConn;\n    }\n  });\n\n  // We've succeeded when we get the session id on the client side.\n  var onClientSessionId = function (sessionId) {\n    test.isTrue(clientConn.status().connected);\n    var serverConn = serverConns[sessionId];\n    if (! serverConn) {\n      test.fail(\"No onConnection received server side for connected client\");\n      failed();\n    } else {\n      onConnectionHandle.stop();\n      succeeded(clientConn, serverConn);\n    }\n  };\n\n  // Connect and wait until the connection receives its session id.\n  // Disable retries so that when the connection is closed we don't\n  // automatically keep reconnecting on the client side.\n  clientConn = DDP.connect(Meteor.absoluteUrl(), {retry: false});\n  simplePoll(\n    function () {\n      return clientConn._lastSessionId;\n    },\n    function () {\n      onClientSessionId(clientConn._lastSessionId);\n    },\n    function () {\n      test.fail(\"client side of connection did not receive a session id\");\n      failed();\n    }\n  );\n};\n"
  },
  {
    "path": "packages/test-helpers/current_style.js",
    "content": "// Cross-browser implementation of getting the computed style of an element.\ngetStyleProperty = function(n, prop) {\n  if (n.currentStyle) {\n    // camelCase it for IE\n    return n.currentStyle[prop.replace(\n      /-([a-z])/g,\n      function(x,y) { return y.toUpperCase(); })];\n  } else {\n    return window.getComputedStyle(n, null).getPropertyValue(prop);\n  }\n};\n"
  },
  {
    "path": "packages/test-helpers/domutils.js",
    "content": "var testDiv = document.createElement(\"div\");\ntestDiv.innerHTML = \"   <link/><table></table><select><!----></select>\";\n// Need to wrap in a div rather than directly creating SELECT to avoid\n// *another* IE bug.\nvar testSelectDiv = document.createElement(\"div\");\ntestSelectDiv.innerHTML = \"<select><option selected>Foo</option></select>\";\ntestSelectDiv.firstChild.setAttribute(\"name\", \"myname\");\n\n// Tests that, if true, indicate browser quirks present.\nvar quirks = {\n  // IE loses initial whitespace when setting innerHTML.\n  leadingWhitespaceKilled: (testDiv.firstChild.nodeType !== 3),\n\n  // IE may insert an empty tbody tag in a table.\n  tbodyInsertion: testDiv.getElementsByTagName(\"tbody\").length > 0,\n\n  // IE loses some tags in some environments (requiring extra wrapper).\n  tagsLost: testDiv.getElementsByTagName(\"link\").length === 0,\n\n  // IE <= 9 loses HTML comments in <select> and <option> tags.\n  commentsLost: (! testDiv.getElementsByTagName(\"select\")[0].firstChild),\n\n  selectValueMustBeFromAttribute: (testSelectDiv.firstChild.value !== \"Foo\"),\n\n  // In IE7, setAttribute('name', foo) doesn't show up in rendered HTML.\n  // (In FF3, outerHTML is undefined, but it doesn't have this quirk.)\n  mustSetNameInCreateElement: (\n    testSelectDiv.firstChild.outerHTML &&\n      testSelectDiv.firstChild.outerHTML.indexOf(\"myname\") === -1)\n};\n\nDomUtils = {};\n\nDomUtils.setElementValue = function (node, value) {\n  // Try to assign the value.\n  node.value = value;\n  if (node.value === value || node.nodeName !== 'SELECT')\n    return;\n\n  // IE (all versions) appears to only let you assign SELECT values which\n  // match valid OPTION values... and moreover, the OPTION value must be\n  // explicitly given as an attribute, not just as the text. So we hunt for\n  // the OPTION and select it.\n  var options = $(node).find('option');\n  for (var i = 0; i < options.length; ++i) {\n    if (DomUtils.getElementValue(options[i]) === value) {\n      options[i].selected = true;\n      return;\n    }\n  }\n};\n\n// Gets the value of an element, portably across browsers. There's a special\n// case for SELECT elements in IE.\nDomUtils.getElementValue = function (node) {\n  if (!quirks.selectValueMustBeFromAttribute)\n    return node.value;\n\n  if (node.nodeName === 'OPTION') {\n    // Inspired by jQuery.valHooks.option.get.\n    var val = node.attributes.value;\n    return !val || val.specified ? node.value : node.text;\n  } else if (node.nodeName === 'SELECT') {\n    if (node.selectedIndex < 0)\n      return null;\n    return DomUtils.getElementValue(node.options[node.selectedIndex]);\n  } else {\n    return node.value;\n  }\n};\n"
  },
  {
    "path": "packages/test-helpers/event_simulation.js",
    "content": "// possible options:\n// bubbles: A boolean indicating whether the event should bubble up through\n//  the event chain or not. (default is true)\nsimulateEvent = function (node, event, args, options) {\n  node = (node instanceof $ ? node[0] : node);\n\n  var bubbles = (options && \"bubbles\" in options) ? options.bubbles : true;\n\n  if (document.createEvent) {\n    var e = document.createEvent(\"Event\");\n    e.initEvent(event, bubbles, true);\n    _.extend(e, args);\n    node.dispatchEvent(e);\n  } else {\n    var e = document.createEventObject();\n    _.extend(e, args);\n    node.fireEvent(\"on\" + event, e);\n  }\n};\n\nfocusElement = function(elem) {\n  // This sequence is for benefit of IE 8 and 9;\n  // test there before changing.\n  window.focus();\n  elem.focus();\n  elem.focus();\n\n  // focus() should set document.activeElement\n  if (document.activeElement !== elem)\n    throw new Error(\"focus() didn't set activeElement\");\n};\n\nblurElement = function(elem) {\n  elem.blur();\n  if (document.activeElement === elem)\n    throw new Error(\"blur() didn't affect activeElement\");\n};\n\nclickElement = function(elem) {\n  if (elem.click)\n    elem.click(); // supported by form controls cross-browser; most native way\n  else\n    simulateEvent(elem, 'click');\n};\n\nvar inDocument = function (elem) {\n  while ((elem = elem.parentNode)) {\n    if (elem == document) {\n      return true;\n    }\n  }\n  return false;\n};\n\nclickIt = function (elem) {\n  if (!inDocument(elem))\n    throw new Error(\"Can't click on elements without first adding them to the document\");\n\n  // jQuery's bubbling change event polyfill for IE 8 seems\n  // to require that the element in question have focus when\n  // it receives a simulated click.\n  if (elem.focus)\n    elem.focus();\n  clickElement(elem);\n};\n\n"
  },
  {
    "path": "packages/test-helpers/package.js",
    "content": "Package.describe({\n  summary: \"Utility functions for tests\",\n  version: '1.0.10'\n});\n\nPackage.onUse(function (api) {\n  api.use(['underscore', 'tracker', 'ejson', 'tinytest', 'random', 'blaze']);\n  api.use(['jquery'], 'client');\n\n  // XXX for connection.js. Not sure this really belongs in\n  // test-helpers. It probably would be better off in livedata. But it's\n  // unclear how to put it in livedata so that it can both be used by\n  // other package tests and not included in the non-test bundle. One\n  // idea would be to make a new separate package 'ddp-test-helpers' or\n  // the like.\n  api.use('ddp');\n\n\n  api.export([\n    'pollUntil', 'try_all_permutations',\n    'SeededRandom', 'clickElement', 'blurElement',\n    'focusElement', 'simulateEvent', 'getStyleProperty', 'canonicalizeHtml',\n    'renderToDiv', 'clickIt',\n    'withCallbackLogger', 'testAsyncMulti', 'simplePoll',\n    'makeTestConnection', 'DomUtils']);\n\n  api.addFiles('try_all_permutations.js');\n  api.addFiles('async_multi.js');\n  api.addFiles('event_simulation.js');\n  api.addFiles('seeded_random.js');\n  api.addFiles('canonicalize_html.js');\n  api.addFiles('render_div.js');\n  api.addFiles('current_style.js');\n  api.addFiles('callback_logger.js');\n  api.addFiles('domutils.js', 'client');\n  api.addFiles('connection.js', 'server');\n});\n\nPackage.onTest(function (api) {\n  api.use('tinytest');\n  api.use(['test-helpers', 'underscore']);\n  api.addFiles('try_all_permutations_test.js', 'client');\n  api.addFiles('seeded_random_test.js');\n});\n"
  },
  {
    "path": "packages/test-helpers/render_div.js",
    "content": "renderToDiv = function (template, optData) {\n  var div = document.createElement(\"DIV\");\n  if (optData == null) {\n    Blaze.render(template, div);\n  } else {\n    Blaze.renderWithData(template, optData, div);\n  }\n  return div;\n};\n"
  },
  {
    "path": "packages/test-helpers/seeded_random.js",
    "content": "SeededRandom = function(seed) { // seed may be a string or any type\n  if (! (this instanceof SeededRandom))\n    return new SeededRandom(seed);\n\n  seed = seed || \"seed\";\n  this.gen = Random.createWithSeeds(seed).alea; // from random.js\n};\nSeededRandom.prototype.next = function() {\n  return this.gen();\n};\nSeededRandom.prototype.nextBoolean = function() {\n  return this.next() >= 0.5;\n};\nSeededRandom.prototype.nextIntBetween = function(min, max) {\n  // inclusive of min and max\n  return Math.floor(this.next() * (max-min+1)) + min;\n};\nSeededRandom.prototype.nextIdentifier = function(optLen) {\n  var letters = [];\n  var len = (typeof optLen === \"number\" ? optLen : 12);\n  for(var i=0; i<len; i++)\n    letters.push(String.fromCharCode(this.nextIntBetween(97, 122)));\n  var x;\n  return letters.join('');\n};\nSeededRandom.prototype.nextChoice = function(list) {\n  return list[this.nextIntBetween(0, list.length-1)];\n};\n"
  },
  {
    "path": "packages/test-helpers/seeded_random_test.js",
    "content": "// XXX SECTION: Meta tests\n\nTinytest.add(\"test-helpers - seeded_random\", function (test) {\n  // Test that two seeded PRNGs with the same seed produce the same values.\n  var seed = \"I'm a seed\";\n  var sr1 = new SeededRandom(seed);\n  var sr2 = new SeededRandom(seed);\n  var sr1vals = [];\n  var sr2vals = [];\n  for (var i = 0; i < 100; i++) {\n    sr1vals.push(sr1.next());\n    sr2vals.push(sr2.next());\n  }\n  test.equal(sr1vals, sr2vals);\n});\n"
  },
  {
    "path": "packages/test-helpers/try_all_permutations.js",
    "content": "// Given some functions, run them in every possible order.\n//\n// In simplest usage, takes one argument, an array of functions. Run\n// those functions in every possible order. Or, if the first element\n// of the array is an integer N, with the remaining elements being\n// functions (N <= the number of functions), run every permutation of\n// N functions from the array.\n//\n// Eg:\n// try_all_permutations([A, B, C])\n// => runs A, B, C; A, C, B; B, A, C; B, C, A; C, A, B; C, B, A\n// (semicolons for clarity only)\n//\n// try_all_permutations([2, A, B, C])\n// => runs A, B; A, C; B, A; B, C; C, A; C, B\n//\n// If more than one argument A_1, A_2 ... A_n is passed, each should\n// be an array as described above. Compute the possible orderings O_1,\n// O_2 ... O_n per above, and run the Cartesian product of the\n// sets. (Except that unlike a proper Cartesian product, a set with\n// zero elements will simply be ignored.)\n//\n// Eg:\n// try_all_permutations([X], [A, B], [Y])\n// => runs X, A, B, Y; X, B, A, Y\n// try_all_permutations([X], [A, B], [], [Y])\n// => same\n//\n// If a function is passed instead of an array, it will be treated as\n// an array with one argument. In other words, these are the same:\n// try_all_permutations([X], [A, B], [Y])\n// try_all_permutations(X, [A, B], Y)\n\ntry_all_permutations = function () {\n  var args = Array.prototype.slice.call(arguments);\n\n  var current_set = 0;\n  var chosen = [];\n\n  var expand_next_set = function () {\n    if (current_set === args.length) {\n      _.each(chosen, function (f) { f(); });\n    } else {\n      var set = args[current_set];\n      if (typeof set === \"function\")\n        set = [set];\n\n      current_set++;\n      if (typeof set[0] === \"number\")\n        pick(set[0], set.slice(1));\n      else\n        pick(set.length, set);\n      current_set--;\n    }\n  };\n\n  var pick = function (how_many, remaining) {\n    if (how_many === 0)\n      expand_next_set();\n    else {\n      for (var i = 0; i < remaining.length; i++) {\n        chosen.push(remaining[i]);\n        pick(how_many - 1,\n             remaining.slice(0, i).concat(remaining.slice(i + 1)));\n        chosen.pop();\n      }\n    }\n  };\n\n  expand_next_set();\n};\n"
  },
  {
    "path": "packages/test-helpers/try_all_permutations_test.js",
    "content": "// XXX SECTION: Meta tests\n\nTinytest.add(\"test-helpers - try_all_permutations\", function (test) {\n  // Have a good test of try_all_permutations, because it would suck\n  // if try_all_permutations didn't actually run anything and so none\n  // of our other tests actually did any testing.\n\n  var out = \"\";\n  try_all_permutations(\n    function () {out += \":\";},\n    [\n      function () {out += \"A\";},\n      function () {out += \"B\";},\n      function () {out += \"C\";}\n    ],\n    function () {out += \".\";}\n  );\n\n  test.equal(out, \":ABC.:ACB.:BAC.:BCA.:CAB.:CBA.\");\n\n  out = \"\";\n  try_all_permutations(\n    [function () {out += \":\";}],\n    [\n      2,\n      function () {out += \"A\";},\n      function () {out += \"B\";},\n      function () {out += \"C\";}\n    ],\n    [],\n    [\n      0,\n      function () {out += \"X\";},\n      function () {out += \"Y\";}\n    ],\n    function () {out += \".\";}\n  );\n\n  test.equal(out, \":AB.:AC.:BA.:BC.:CA.:CB.\");\n\n  out = \"\";\n  try_all_permutations(\n    [\n      2,\n      function () {out += \"A\";},\n      function () {out += \"B\";},\n      function () {out += \"C\";},\n      function () {out += \"D\";}\n    ],\n    [\n      function () {out += \"X\";},\n      function () {out += \"Y\";}\n    ],\n    function () {out += \".\";}\n  );\n  test.equal(out, \"ABXY.ABYX.ACXY.ACYX.ADXY.ADYX.BAXY.BAYX.BCXY.BCYX.BDXY.BDYX.CAXY.CAYX.CBXY.CBYX.CDXY.CDYX.DAXY.DAYX.DBXY.DBYX.DCXY.DCYX.\");\n\n  var examine = function (n) {\n    var fs = [];\n    var seq = \"\";\n    var seen = {};\n\n    for (var i = 0; i < n; i++)\n      fs.push(_.bind(function (x) { seq += x + \"_\"; }, null, i));\n    try_all_permutations(\n      function () {seq = \"\";},\n      fs,\n      function () {\n        if (seq in seen)\n          throw new Error(\"duplicate permutation\");\n        seen[seq] = true;\n      }\n    );\n\n    var expected_count = 1;\n    for (var i = n; i >= 1; i--)\n      expected_count *= i;\n    test.equal(_.keys(seen).length, expected_count);\n  };\n\n  for (var i = 1; i <= 5; i++)\n    examine(i);\n\n  try_all_permutations();\n});\n"
  },
  {
    "path": "packages/test-in-browser/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/test-in-browser/autoupdate.js",
    "content": "// autoupdate normally won't reload on server-only changes, but when\n// running tests in the browser it's nice to have server changes cause\n// the tests to reload.  Setting the auto update version to a\n// different value when the server restarts accomplishes this.\n\nif (Package.autoupdate)\n  Package.autoupdate.Autoupdate.autoupdateVersion = Random.id();\n"
  },
  {
    "path": "packages/test-in-browser/diff_match_patch_uncompressed.js",
    "content": "/**\n * Diff Match and Patch\n *\n * Copyright 2006 Google Inc.\n * http://code.google.com/p/google-diff-match-patch/\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 * @fileoverview Computes the difference between two texts to create a patch.\n * Applies the patch onto another text, allowing for errors.\n * @author fraser@google.com (Neil Fraser)\n */\n\n/**\n * Class containing the diff, match and patch methods.\n * @constructor\n */\nfunction diff_match_patch() {\n\n  // Defaults.\n  // Redefine these in your program to override the defaults.\n\n  // Number of seconds to map a diff before giving up (0 for infinity).\n  this.Diff_Timeout = 1.0;\n  // Cost of an empty edit operation in terms of edit characters.\n  this.Diff_EditCost = 4;\n  // At what point is no match declared (0.0 = perfection, 1.0 = very loose).\n  this.Match_Threshold = 0.5;\n  // How far to search for a match (0 = exact location, 1000+ = broad match).\n  // A match this many characters away from the expected location will add\n  // 1.0 to the score (0.0 is a perfect match).\n  this.Match_Distance = 1000;\n  // When deleting a large block of text (over ~64 characters), how close do\n  // the contents have to be to match the expected contents. (0.0 = perfection,\n  // 1.0 = very loose).  Note that Match_Threshold controls how closely the\n  // end points of a delete need to match.\n  this.Patch_DeleteThreshold = 0.5;\n  // Chunk size for context length.\n  this.Patch_Margin = 4;\n\n  // The number of bits in an int.\n  this.Match_MaxBits = 32;\n}\n\n\n//  DIFF FUNCTIONS\n\n\n/**\n * The data structure representing a diff is an array of tuples:\n * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]\n * which means: delete 'Hello', add 'Goodbye' and keep ' world.'\n */\nvar DIFF_DELETE = -1;\nvar DIFF_INSERT = 1;\nvar DIFF_EQUAL = 0;\n\n/** @typedef {{0: number, 1: string}} */\ndiff_match_patch.Diff;\n\n\n/**\n * Find the differences between two texts.  Simplifies the problem by stripping\n * any common prefix or suffix off the texts before diffing.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {boolean=} opt_checklines Optional speedup flag. If present and false,\n *     then don't run a line-level diff first to identify the changed areas.\n *     Defaults to true, which does a faster, slightly less optimal diff.\n * @param {number} opt_deadline Optional time when the diff should be complete\n *     by.  Used internally for recursive calls.  Users should set DiffTimeout\n *     instead.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_main = function(text1, text2, opt_checklines,\n    opt_deadline) {\n  // Set a deadline by which time the diff must be complete.\n  if (typeof opt_deadline == 'undefined') {\n    if (this.Diff_Timeout <= 0) {\n      opt_deadline = Number.MAX_VALUE;\n    } else {\n      opt_deadline = (new Date).getTime() + this.Diff_Timeout * 1000;\n    }\n  }\n  var deadline = opt_deadline;\n\n  // Check for null inputs.\n  if (text1 == null || text2 == null) {\n    throw new Error('Null input. (diff_main)');\n  }\n\n  // Check for equality (speedup).\n  if (text1 == text2) {\n    if (text1) {\n      return [[DIFF_EQUAL, text1]];\n    }\n    return [];\n  }\n\n  if (typeof opt_checklines == 'undefined') {\n    opt_checklines = true;\n  }\n  var checklines = opt_checklines;\n\n  // Trim off common prefix (speedup).\n  var commonlength = this.diff_commonPrefix(text1, text2);\n  var commonprefix = text1.substring(0, commonlength);\n  text1 = text1.substring(commonlength);\n  text2 = text2.substring(commonlength);\n\n  // Trim off common suffix (speedup).\n  commonlength = this.diff_commonSuffix(text1, text2);\n  var commonsuffix = text1.substring(text1.length - commonlength);\n  text1 = text1.substring(0, text1.length - commonlength);\n  text2 = text2.substring(0, text2.length - commonlength);\n\n  // Compute the diff on the middle block.\n  var diffs = this.diff_compute_(text1, text2, checklines, deadline);\n\n  // Restore the prefix and suffix.\n  if (commonprefix) {\n    diffs.unshift([DIFF_EQUAL, commonprefix]);\n  }\n  if (commonsuffix) {\n    diffs.push([DIFF_EQUAL, commonsuffix]);\n  }\n  this.diff_cleanupMerge(diffs);\n  return diffs;\n};\n\n\n/**\n * Find the differences between two texts.  Assumes that the texts do not\n * have any common prefix or suffix.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {boolean} checklines Speedup flag.  If false, then don't run a\n *     line-level diff first to identify the changed areas.\n *     If true, then run a faster, slightly less optimal diff.\n * @param {number} deadline Time when the diff should be complete by.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @private\n */\ndiff_match_patch.prototype.diff_compute_ = function(text1, text2, checklines,\n    deadline) {\n  var diffs;\n\n  if (!text1) {\n    // Just add some text (speedup).\n    return [[DIFF_INSERT, text2]];\n  }\n\n  if (!text2) {\n    // Just delete some text (speedup).\n    return [[DIFF_DELETE, text1]];\n  }\n\n  var longtext = text1.length > text2.length ? text1 : text2;\n  var shorttext = text1.length > text2.length ? text2 : text1;\n  var i = longtext.indexOf(shorttext);\n  if (i != -1) {\n    // Shorter text is inside the longer text (speedup).\n    diffs = [[DIFF_INSERT, longtext.substring(0, i)],\n             [DIFF_EQUAL, shorttext],\n             [DIFF_INSERT, longtext.substring(i + shorttext.length)]];\n    // Swap insertions for deletions if diff is reversed.\n    if (text1.length > text2.length) {\n      diffs[0][0] = diffs[2][0] = DIFF_DELETE;\n    }\n    return diffs;\n  }\n\n  if (shorttext.length == 1) {\n    // Single character string.\n    // After the previous speedup, the character can't be an equality.\n    return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];\n  }\n\n  // Check to see if the problem can be split in two.\n  var hm = this.diff_halfMatch_(text1, text2);\n  if (hm) {\n    // A half-match was found, sort out the return data.\n    var text1_a = hm[0];\n    var text1_b = hm[1];\n    var text2_a = hm[2];\n    var text2_b = hm[3];\n    var mid_common = hm[4];\n    // Send both pairs off for separate processing.\n    var diffs_a = this.diff_main(text1_a, text2_a, checklines, deadline);\n    var diffs_b = this.diff_main(text1_b, text2_b, checklines, deadline);\n    // Merge the results.\n    return diffs_a.concat([[DIFF_EQUAL, mid_common]], diffs_b);\n  }\n\n  if (checklines && text1.length > 100 && text2.length > 100) {\n    return this.diff_lineMode_(text1, text2, deadline);\n  }\n\n  return this.diff_bisect_(text1, text2, deadline);\n};\n\n\n/**\n * Do a quick line-level diff on both strings, then rediff the parts for\n * greater accuracy.\n * This speedup can produce non-minimal diffs.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {number} deadline Time when the diff should be complete by.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @private\n */\ndiff_match_patch.prototype.diff_lineMode_ = function(text1, text2, deadline) {\n  // Scan the text on a line-by-line basis first.\n  var a = this.diff_linesToChars_(text1, text2);\n  text1 = a.chars1;\n  text2 = a.chars2;\n  var linearray = a.lineArray;\n\n  var diffs = this.diff_main(text1, text2, false, deadline);\n\n  // Convert the diff back to original text.\n  this.diff_charsToLines_(diffs, linearray);\n  // Eliminate freak matches (e.g. blank lines)\n  this.diff_cleanupSemantic(diffs);\n\n  // Rediff any replacement blocks, this time character-by-character.\n  // Add a dummy entry at the end.\n  diffs.push([DIFF_EQUAL, '']);\n  var pointer = 0;\n  var count_delete = 0;\n  var count_insert = 0;\n  var text_delete = '';\n  var text_insert = '';\n  while (pointer < diffs.length) {\n    switch (diffs[pointer][0]) {\n      case DIFF_INSERT:\n        count_insert++;\n        text_insert += diffs[pointer][1];\n        break;\n      case DIFF_DELETE:\n        count_delete++;\n        text_delete += diffs[pointer][1];\n        break;\n      case DIFF_EQUAL:\n        // Upon reaching an equality, check for prior redundancies.\n        if (count_delete >= 1 && count_insert >= 1) {\n          // Delete the offending records and add the merged ones.\n          diffs.splice(pointer - count_delete - count_insert,\n                       count_delete + count_insert);\n          pointer = pointer - count_delete - count_insert;\n          var a = this.diff_main(text_delete, text_insert, false, deadline);\n          for (var j = a.length - 1; j >= 0; j--) {\n            diffs.splice(pointer, 0, a[j]);\n          }\n          pointer = pointer + a.length;\n        }\n        count_insert = 0;\n        count_delete = 0;\n        text_delete = '';\n        text_insert = '';\n        break;\n    }\n    pointer++;\n  }\n  diffs.pop();  // Remove the dummy entry at the end.\n\n  return diffs;\n};\n\n\n/**\n * Find the 'middle snake' of a diff, split the problem in two\n * and return the recursively constructed diff.\n * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {number} deadline Time at which to bail if not yet complete.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @private\n */\ndiff_match_patch.prototype.diff_bisect_ = function(text1, text2, deadline) {\n  // Cache the text lengths to prevent multiple calls.\n  var text1_length = text1.length;\n  var text2_length = text2.length;\n  var max_d = Math.ceil((text1_length + text2_length) / 2);\n  var v_offset = max_d;\n  var v_length = 2 * max_d;\n  var v1 = new Array(v_length);\n  var v2 = new Array(v_length);\n  // Setting all elements to -1 is faster in Chrome & Firefox than mixing\n  // integers and undefined.\n  for (var x = 0; x < v_length; x++) {\n    v1[x] = -1;\n    v2[x] = -1;\n  }\n  v1[v_offset + 1] = 0;\n  v2[v_offset + 1] = 0;\n  var delta = text1_length - text2_length;\n  // If the total number of characters is odd, then the front path will collide\n  // with the reverse path.\n  var front = (delta % 2 != 0);\n  // Offsets for start and end of k loop.\n  // Prevents mapping of space beyond the grid.\n  var k1start = 0;\n  var k1end = 0;\n  var k2start = 0;\n  var k2end = 0;\n  for (var d = 0; d < max_d; d++) {\n    // Bail out if deadline is reached.\n    if ((new Date()).getTime() > deadline) {\n      break;\n    }\n\n    // Walk the front path one step.\n    for (var k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {\n      var k1_offset = v_offset + k1;\n      var x1;\n      if (k1 == -d || (k1 != d && v1[k1_offset - 1] < v1[k1_offset + 1])) {\n        x1 = v1[k1_offset + 1];\n      } else {\n        x1 = v1[k1_offset - 1] + 1;\n      }\n      var y1 = x1 - k1;\n      while (x1 < text1_length && y1 < text2_length &&\n             text1.charAt(x1) == text2.charAt(y1)) {\n        x1++;\n        y1++;\n      }\n      v1[k1_offset] = x1;\n      if (x1 > text1_length) {\n        // Ran off the right of the graph.\n        k1end += 2;\n      } else if (y1 > text2_length) {\n        // Ran off the bottom of the graph.\n        k1start += 2;\n      } else if (front) {\n        var k2_offset = v_offset + delta - k1;\n        if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] != -1) {\n          // Mirror x2 onto top-left coordinate system.\n          var x2 = text1_length - v2[k2_offset];\n          if (x1 >= x2) {\n            // Overlap detected.\n            return this.diff_bisectSplit_(text1, text2, x1, y1, deadline);\n          }\n        }\n      }\n    }\n\n    // Walk the reverse path one step.\n    for (var k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {\n      var k2_offset = v_offset + k2;\n      var x2;\n      if (k2 == -d || (k2 != d && v2[k2_offset - 1] < v2[k2_offset + 1])) {\n        x2 = v2[k2_offset + 1];\n      } else {\n        x2 = v2[k2_offset - 1] + 1;\n      }\n      var y2 = x2 - k2;\n      while (x2 < text1_length && y2 < text2_length &&\n             text1.charAt(text1_length - x2 - 1) ==\n             text2.charAt(text2_length - y2 - 1)) {\n        x2++;\n        y2++;\n      }\n      v2[k2_offset] = x2;\n      if (x2 > text1_length) {\n        // Ran off the left of the graph.\n        k2end += 2;\n      } else if (y2 > text2_length) {\n        // Ran off the top of the graph.\n        k2start += 2;\n      } else if (!front) {\n        var k1_offset = v_offset + delta - k2;\n        if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] != -1) {\n          var x1 = v1[k1_offset];\n          var y1 = v_offset + x1 - k1_offset;\n          // Mirror x2 onto top-left coordinate system.\n          x2 = text1_length - x2;\n          if (x1 >= x2) {\n            // Overlap detected.\n            return this.diff_bisectSplit_(text1, text2, x1, y1, deadline);\n          }\n        }\n      }\n    }\n  }\n  // Diff took too long and hit the deadline or\n  // number of diffs equals number of characters, no commonality at all.\n  return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];\n};\n\n\n/**\n * Given the location of the 'middle snake', split the diff in two parts\n * and recurse.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {number} x Index of split point in text1.\n * @param {number} y Index of split point in text2.\n * @param {number} deadline Time at which to bail if not yet complete.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @private\n */\ndiff_match_patch.prototype.diff_bisectSplit_ = function(text1, text2, x, y,\n    deadline) {\n  var text1a = text1.substring(0, x);\n  var text2a = text2.substring(0, y);\n  var text1b = text1.substring(x);\n  var text2b = text2.substring(y);\n\n  // Compute both diffs serially.\n  var diffs = this.diff_main(text1a, text2a, false, deadline);\n  var diffsb = this.diff_main(text1b, text2b, false, deadline);\n\n  return diffs.concat(diffsb);\n};\n\n\n/**\n * Split two texts into an array of strings.  Reduce the texts to a string of\n * hashes where each Unicode character represents one line.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}\n *     An object containing the encoded text1, the encoded text2 and\n *     the array of unique strings.\n *     The zeroth element of the array of unique strings is intentionally blank.\n * @private\n */\ndiff_match_patch.prototype.diff_linesToChars_ = function(text1, text2) {\n  var lineArray = [];  // e.g. lineArray[4] == 'Hello\\n'\n  var lineHash = {};   // e.g. lineHash['Hello\\n'] == 4\n\n  // '\\x00' is a valid character, but various debuggers don't like it.\n  // So we'll insert a junk entry to avoid generating a null character.\n  lineArray[0] = '';\n\n  /**\n   * Split a text into an array of strings.  Reduce the texts to a string of\n   * hashes where each Unicode character represents one line.\n   * Modifies linearray and linehash through being a closure.\n   * @param {string} text String to encode.\n   * @return {string} Encoded string.\n   * @private\n   */\n  function diff_linesToCharsMunge_(text) {\n    var chars = '';\n    // Walk the text, pulling out a substring for each line.\n    // text.split('\\n') would would temporarily double our memory footprint.\n    // Modifying text would create many large strings to garbage collect.\n    var lineStart = 0;\n    var lineEnd = -1;\n    // Keeping our own length variable is faster than looking it up.\n    var lineArrayLength = lineArray.length;\n    while (lineEnd < text.length - 1) {\n      lineEnd = text.indexOf('\\n', lineStart);\n      if (lineEnd == -1) {\n        lineEnd = text.length - 1;\n      }\n      var line = text.substring(lineStart, lineEnd + 1);\n      lineStart = lineEnd + 1;\n\n      if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) :\n          (lineHash[line] !== undefined)) {\n        chars += String.fromCharCode(lineHash[line]);\n      } else {\n        chars += String.fromCharCode(lineArrayLength);\n        lineHash[line] = lineArrayLength;\n        lineArray[lineArrayLength++] = line;\n      }\n    }\n    return chars;\n  }\n\n  var chars1 = diff_linesToCharsMunge_(text1);\n  var chars2 = diff_linesToCharsMunge_(text2);\n  return {chars1: chars1, chars2: chars2, lineArray: lineArray};\n};\n\n\n/**\n * Rehydrate the text in a diff from a string of line hashes to real lines of\n * text.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @param {!Array.<string>} lineArray Array of unique strings.\n * @private\n */\ndiff_match_patch.prototype.diff_charsToLines_ = function(diffs, lineArray) {\n  for (var x = 0; x < diffs.length; x++) {\n    var chars = diffs[x][1];\n    var text = [];\n    for (var y = 0; y < chars.length; y++) {\n      text[y] = lineArray[chars.charCodeAt(y)];\n    }\n    diffs[x][1] = text.join('');\n  }\n};\n\n\n/**\n * Determine the common prefix of two strings.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {number} The number of characters common to the start of each\n *     string.\n */\ndiff_match_patch.prototype.diff_commonPrefix = function(text1, text2) {\n  // Quick check for common null cases.\n  if (!text1 || !text2 || text1.charAt(0) != text2.charAt(0)) {\n    return 0;\n  }\n  // Binary search.\n  // Performance analysis: http://neil.fraser.name/news/2007/10/09/\n  var pointermin = 0;\n  var pointermax = Math.min(text1.length, text2.length);\n  var pointermid = pointermax;\n  var pointerstart = 0;\n  while (pointermin < pointermid) {\n    if (text1.substring(pointerstart, pointermid) ==\n        text2.substring(pointerstart, pointermid)) {\n      pointermin = pointermid;\n      pointerstart = pointermin;\n    } else {\n      pointermax = pointermid;\n    }\n    pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);\n  }\n  return pointermid;\n};\n\n\n/**\n * Determine the common suffix of two strings.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {number} The number of characters common to the end of each string.\n */\ndiff_match_patch.prototype.diff_commonSuffix = function(text1, text2) {\n  // Quick check for common null cases.\n  if (!text1 || !text2 ||\n      text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)) {\n    return 0;\n  }\n  // Binary search.\n  // Performance analysis: http://neil.fraser.name/news/2007/10/09/\n  var pointermin = 0;\n  var pointermax = Math.min(text1.length, text2.length);\n  var pointermid = pointermax;\n  var pointerend = 0;\n  while (pointermin < pointermid) {\n    if (text1.substring(text1.length - pointermid, text1.length - pointerend) ==\n        text2.substring(text2.length - pointermid, text2.length - pointerend)) {\n      pointermin = pointermid;\n      pointerend = pointermin;\n    } else {\n      pointermax = pointermid;\n    }\n    pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);\n  }\n  return pointermid;\n};\n\n\n/**\n * Determine if the suffix of one string is the prefix of another.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {number} The number of characters common to the end of the first\n *     string and the start of the second string.\n * @private\n */\ndiff_match_patch.prototype.diff_commonOverlap_ = function(text1, text2) {\n  // Cache the text lengths to prevent multiple calls.\n  var text1_length = text1.length;\n  var text2_length = text2.length;\n  // Eliminate the null case.\n  if (text1_length == 0 || text2_length == 0) {\n    return 0;\n  }\n  // Truncate the longer string.\n  if (text1_length > text2_length) {\n    text1 = text1.substring(text1_length - text2_length);\n  } else if (text1_length < text2_length) {\n    text2 = text2.substring(0, text1_length);\n  }\n  var text_length = Math.min(text1_length, text2_length);\n  // Quick check for the worst case.\n  if (text1 == text2) {\n    return text_length;\n  }\n\n  // Start by looking for a single character match\n  // and increase length until no match is found.\n  // Performance analysis: http://neil.fraser.name/news/2010/11/04/\n  var best = 0;\n  var length = 1;\n  while (true) {\n    var pattern = text1.substring(text_length - length);\n    var found = text2.indexOf(pattern);\n    if (found == -1) {\n      return best;\n    }\n    length += found;\n    if (found == 0 || text1.substring(text_length - length) ==\n        text2.substring(0, length)) {\n      best = length;\n      length++;\n    }\n  }\n};\n\n\n/**\n * Do the two texts share a substring which is at least half the length of the\n * longer text?\n * This speedup can produce non-minimal diffs.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {Array.<string>} Five element Array, containing the prefix of\n *     text1, the suffix of text1, the prefix of text2, the suffix of\n *     text2 and the common middle.  Or null if there was no match.\n * @private\n */\ndiff_match_patch.prototype.diff_halfMatch_ = function(text1, text2) {\n  if (this.Diff_Timeout <= 0) {\n    // Don't risk returning a non-optimal diff if we have unlimited time.\n    return null;\n  }\n  var longtext = text1.length > text2.length ? text1 : text2;\n  var shorttext = text1.length > text2.length ? text2 : text1;\n  if (longtext.length < 4 || shorttext.length * 2 < longtext.length) {\n    return null;  // Pointless.\n  }\n  var dmp = this;  // 'this' becomes 'window' in a closure.\n\n  /**\n   * Does a substring of shorttext exist within longtext such that the substring\n   * is at least half the length of longtext?\n   * Closure, but does not reference any external variables.\n   * @param {string} longtext Longer string.\n   * @param {string} shorttext Shorter string.\n   * @param {number} i Start index of quarter length substring within longtext.\n   * @return {Array.<string>} Five element Array, containing the prefix of\n   *     longtext, the suffix of longtext, the prefix of shorttext, the suffix\n   *     of shorttext and the common middle.  Or null if there was no match.\n   * @private\n   */\n  function diff_halfMatchI_(longtext, shorttext, i) {\n    // Start with a 1/4 length substring at position i as a seed.\n    var seed = longtext.substring(i, i + Math.floor(longtext.length / 4));\n    var j = -1;\n    var best_common = '';\n    var best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b;\n    while ((j = shorttext.indexOf(seed, j + 1)) != -1) {\n      var prefixLength = dmp.diff_commonPrefix(longtext.substring(i),\n                                               shorttext.substring(j));\n      var suffixLength = dmp.diff_commonSuffix(longtext.substring(0, i),\n                                               shorttext.substring(0, j));\n      if (best_common.length < suffixLength + prefixLength) {\n        best_common = shorttext.substring(j - suffixLength, j) +\n            shorttext.substring(j, j + prefixLength);\n        best_longtext_a = longtext.substring(0, i - suffixLength);\n        best_longtext_b = longtext.substring(i + prefixLength);\n        best_shorttext_a = shorttext.substring(0, j - suffixLength);\n        best_shorttext_b = shorttext.substring(j + prefixLength);\n      }\n    }\n    if (best_common.length * 2 >= longtext.length) {\n      return [best_longtext_a, best_longtext_b,\n              best_shorttext_a, best_shorttext_b, best_common];\n    } else {\n      return null;\n    }\n  }\n\n  // First check if the second quarter is the seed for a half-match.\n  var hm1 = diff_halfMatchI_(longtext, shorttext,\n                             Math.ceil(longtext.length / 4));\n  // Check again based on the third quarter.\n  var hm2 = diff_halfMatchI_(longtext, shorttext,\n                             Math.ceil(longtext.length / 2));\n  var hm;\n  if (!hm1 && !hm2) {\n    return null;\n  } else if (!hm2) {\n    hm = hm1;\n  } else if (!hm1) {\n    hm = hm2;\n  } else {\n    // Both matched.  Select the longest.\n    hm = hm1[4].length > hm2[4].length ? hm1 : hm2;\n  }\n\n  // A half-match was found, sort out the return data.\n  var text1_a, text1_b, text2_a, text2_b;\n  if (text1.length > text2.length) {\n    text1_a = hm[0];\n    text1_b = hm[1];\n    text2_a = hm[2];\n    text2_b = hm[3];\n  } else {\n    text2_a = hm[0];\n    text2_b = hm[1];\n    text1_a = hm[2];\n    text1_b = hm[3];\n  }\n  var mid_common = hm[4];\n  return [text1_a, text1_b, text2_a, text2_b, mid_common];\n};\n\n\n/**\n * Reduce the number of edits by eliminating semantically trivial equalities.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_cleanupSemantic = function(diffs) {\n  var changes = false;\n  var equalities = [];  // Stack of indices where equalities are found.\n  var equalitiesLength = 0;  // Keeping our own length var is faster in JS.\n  /** @type {?string} */\n  var lastequality = null;\n  // Always equal to diffs[equalities[equalitiesLength - 1]][1]\n  var pointer = 0;  // Index of current position.\n  // Number of characters that changed prior to the equality.\n  var length_insertions1 = 0;\n  var length_deletions1 = 0;\n  // Number of characters that changed after the equality.\n  var length_insertions2 = 0;\n  var length_deletions2 = 0;\n  while (pointer < diffs.length) {\n    if (diffs[pointer][0] == DIFF_EQUAL) {  // Equality found.\n      equalities[equalitiesLength++] = pointer;\n      length_insertions1 = length_insertions2;\n      length_deletions1 = length_deletions2;\n      length_insertions2 = 0;\n      length_deletions2 = 0;\n      lastequality = diffs[pointer][1];\n    } else {  // An insertion or deletion.\n      if (diffs[pointer][0] == DIFF_INSERT) {\n        length_insertions2 += diffs[pointer][1].length;\n      } else {\n        length_deletions2 += diffs[pointer][1].length;\n      }\n      // Eliminate an equality that is smaller or equal to the edits on both\n      // sides of it.\n      if (lastequality && (lastequality.length <=\n          Math.max(length_insertions1, length_deletions1)) &&\n          (lastequality.length <= Math.max(length_insertions2,\n                                           length_deletions2))) {\n        // Duplicate record.\n        diffs.splice(equalities[equalitiesLength - 1], 0,\n                     [DIFF_DELETE, lastequality]);\n        // Change second copy to insert.\n        diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;\n        // Throw away the equality we just deleted.\n        equalitiesLength--;\n        // Throw away the previous equality (it needs to be reevaluated).\n        equalitiesLength--;\n        pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;\n        length_insertions1 = 0;  // Reset the counters.\n        length_deletions1 = 0;\n        length_insertions2 = 0;\n        length_deletions2 = 0;\n        lastequality = null;\n        changes = true;\n      }\n    }\n    pointer++;\n  }\n\n  // Normalize the diff.\n  if (changes) {\n    this.diff_cleanupMerge(diffs);\n  }\n  this.diff_cleanupSemanticLossless(diffs);\n\n  // Find any overlaps between deletions and insertions.\n  // e.g: <del>abcxxx</del><ins>xxxdef</ins>\n  //   -> <del>abc</del>xxx<ins>def</ins>\n  // e.g: <del>xxxabc</del><ins>defxxx</ins>\n  //   -> <ins>def</ins>xxx<del>abc</del>\n  // Only extract an overlap if it is as big as the edit ahead or behind it.\n  pointer = 1;\n  while (pointer < diffs.length) {\n    if (diffs[pointer - 1][0] == DIFF_DELETE &&\n        diffs[pointer][0] == DIFF_INSERT) {\n      var deletion = diffs[pointer - 1][1];\n      var insertion = diffs[pointer][1];\n      var overlap_length1 = this.diff_commonOverlap_(deletion, insertion);\n      var overlap_length2 = this.diff_commonOverlap_(insertion, deletion);\n      if (overlap_length1 >= overlap_length2) {\n        if (overlap_length1 >= deletion.length / 2 ||\n            overlap_length1 >= insertion.length / 2) {\n          // Overlap found.  Insert an equality and trim the surrounding edits.\n          diffs.splice(pointer, 0,\n              [DIFF_EQUAL, insertion.substring(0, overlap_length1)]);\n          diffs[pointer - 1][1] =\n              deletion.substring(0, deletion.length - overlap_length1);\n          diffs[pointer + 1][1] = insertion.substring(overlap_length1);\n          pointer++;\n        }\n      } else {\n        if (overlap_length2 >= deletion.length / 2 ||\n            overlap_length2 >= insertion.length / 2) {\n          // Reverse overlap found.\n          // Insert an equality and swap and trim the surrounding edits.\n          diffs.splice(pointer, 0,\n              [DIFF_EQUAL, deletion.substring(0, overlap_length2)]);\n          diffs[pointer - 1][0] = DIFF_INSERT;\n          diffs[pointer - 1][1] =\n              insertion.substring(0, insertion.length - overlap_length2);\n          diffs[pointer + 1][0] = DIFF_DELETE;\n          diffs[pointer + 1][1] =\n              deletion.substring(overlap_length2);\n          pointer++;\n        }\n      }\n      pointer++;\n    }\n    pointer++;\n  }\n};\n\n\n/**\n * Look for single edits surrounded on both sides by equalities\n * which can be shifted sideways to align the edit to a word boundary.\n * e.g: The c<ins>at c</ins>ame. -> The <ins>cat </ins>came.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_cleanupSemanticLossless = function(diffs) {\n  /**\n   * Given two strings, compute a score representing whether the internal\n   * boundary falls on logical boundaries.\n   * Scores range from 6 (best) to 0 (worst).\n   * Closure, but does not reference any external variables.\n   * @param {string} one First string.\n   * @param {string} two Second string.\n   * @return {number} The score.\n   * @private\n   */\n  function diff_cleanupSemanticScore_(one, two) {\n    if (!one || !two) {\n      // Edges are the best.\n      return 6;\n    }\n\n    // Each port of this function behaves slightly differently due to\n    // subtle differences in each language's definition of things like\n    // 'whitespace'.  Since this function's purpose is largely cosmetic,\n    // the choice has been made to use each language's native features\n    // rather than force total conformity.\n    var char1 = one.charAt(one.length - 1);\n    var char2 = two.charAt(0);\n    var nonAlphaNumeric1 = char1.match(diff_match_patch.nonAlphaNumericRegex_);\n    var nonAlphaNumeric2 = char2.match(diff_match_patch.nonAlphaNumericRegex_);\n    var whitespace1 = nonAlphaNumeric1 &&\n        char1.match(diff_match_patch.whitespaceRegex_);\n    var whitespace2 = nonAlphaNumeric2 &&\n        char2.match(diff_match_patch.whitespaceRegex_);\n    var lineBreak1 = whitespace1 &&\n        char1.match(diff_match_patch.linebreakRegex_);\n    var lineBreak2 = whitespace2 &&\n        char2.match(diff_match_patch.linebreakRegex_);\n    var blankLine1 = lineBreak1 &&\n        one.match(diff_match_patch.blanklineEndRegex_);\n    var blankLine2 = lineBreak2 &&\n        two.match(diff_match_patch.blanklineStartRegex_);\n\n    if (blankLine1 || blankLine2) {\n      // Five points for blank lines.\n      return 5;\n    } else if (lineBreak1 || lineBreak2) {\n      // Four points for line breaks.\n      return 4;\n    } else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) {\n      // Three points for end of sentences.\n      return 3;\n    } else if (whitespace1 || whitespace2) {\n      // Two points for whitespace.\n      return 2;\n    } else if (nonAlphaNumeric1 || nonAlphaNumeric2) {\n      // One point for non-alphanumeric.\n      return 1;\n    }\n    return 0;\n  }\n\n  var pointer = 1;\n  // Intentionally ignore the first and last element (don't need checking).\n  while (pointer < diffs.length - 1) {\n    if (diffs[pointer - 1][0] == DIFF_EQUAL &&\n        diffs[pointer + 1][0] == DIFF_EQUAL) {\n      // This is a single edit surrounded by equalities.\n      var equality1 = diffs[pointer - 1][1];\n      var edit = diffs[pointer][1];\n      var equality2 = diffs[pointer + 1][1];\n\n      // First, shift the edit as far left as possible.\n      var commonOffset = this.diff_commonSuffix(equality1, edit);\n      if (commonOffset) {\n        var commonString = edit.substring(edit.length - commonOffset);\n        equality1 = equality1.substring(0, equality1.length - commonOffset);\n        edit = commonString + edit.substring(0, edit.length - commonOffset);\n        equality2 = commonString + equality2;\n      }\n\n      // Second, step character by character right, looking for the best fit.\n      var bestEquality1 = equality1;\n      var bestEdit = edit;\n      var bestEquality2 = equality2;\n      var bestScore = diff_cleanupSemanticScore_(equality1, edit) +\n          diff_cleanupSemanticScore_(edit, equality2);\n      while (edit.charAt(0) === equality2.charAt(0)) {\n        equality1 += edit.charAt(0);\n        edit = edit.substring(1) + equality2.charAt(0);\n        equality2 = equality2.substring(1);\n        var score = diff_cleanupSemanticScore_(equality1, edit) +\n            diff_cleanupSemanticScore_(edit, equality2);\n        // The >= encourages trailing rather than leading whitespace on edits.\n        if (score >= bestScore) {\n          bestScore = score;\n          bestEquality1 = equality1;\n          bestEdit = edit;\n          bestEquality2 = equality2;\n        }\n      }\n\n      if (diffs[pointer - 1][1] != bestEquality1) {\n        // We have an improvement, save it back to the diff.\n        if (bestEquality1) {\n          diffs[pointer - 1][1] = bestEquality1;\n        } else {\n          diffs.splice(pointer - 1, 1);\n          pointer--;\n        }\n        diffs[pointer][1] = bestEdit;\n        if (bestEquality2) {\n          diffs[pointer + 1][1] = bestEquality2;\n        } else {\n          diffs.splice(pointer + 1, 1);\n          pointer--;\n        }\n      }\n    }\n    pointer++;\n  }\n};\n\n// Define some regex patterns for matching boundaries.\ndiff_match_patch.nonAlphaNumericRegex_ = /[^a-zA-Z0-9]/;\ndiff_match_patch.whitespaceRegex_ = /\\s/;\ndiff_match_patch.linebreakRegex_ = /[\\r\\n]/;\ndiff_match_patch.blanklineEndRegex_ = /\\n\\r?\\n$/;\ndiff_match_patch.blanklineStartRegex_ = /^\\r?\\n\\r?\\n/;\n\n/**\n * Reduce the number of edits by eliminating operationally trivial equalities.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_cleanupEfficiency = function(diffs) {\n  var changes = false;\n  var equalities = [];  // Stack of indices where equalities are found.\n  var equalitiesLength = 0;  // Keeping our own length var is faster in JS.\n  /** @type {?string} */\n  var lastequality = null;\n  // Always equal to diffs[equalities[equalitiesLength - 1]][1]\n  var pointer = 0;  // Index of current position.\n  // Is there an insertion operation before the last equality.\n  var pre_ins = false;\n  // Is there a deletion operation before the last equality.\n  var pre_del = false;\n  // Is there an insertion operation after the last equality.\n  var post_ins = false;\n  // Is there a deletion operation after the last equality.\n  var post_del = false;\n  while (pointer < diffs.length) {\n    if (diffs[pointer][0] == DIFF_EQUAL) {  // Equality found.\n      if (diffs[pointer][1].length < this.Diff_EditCost &&\n          (post_ins || post_del)) {\n        // Candidate found.\n        equalities[equalitiesLength++] = pointer;\n        pre_ins = post_ins;\n        pre_del = post_del;\n        lastequality = diffs[pointer][1];\n      } else {\n        // Not a candidate, and can never become one.\n        equalitiesLength = 0;\n        lastequality = null;\n      }\n      post_ins = post_del = false;\n    } else {  // An insertion or deletion.\n      if (diffs[pointer][0] == DIFF_DELETE) {\n        post_del = true;\n      } else {\n        post_ins = true;\n      }\n      /*\n       * Five types to be split:\n       * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>\n       * <ins>A</ins>X<ins>C</ins><del>D</del>\n       * <ins>A</ins><del>B</del>X<ins>C</ins>\n       * <ins>A</del>X<ins>C</ins><del>D</del>\n       * <ins>A</ins><del>B</del>X<del>C</del>\n       */\n      if (lastequality && ((pre_ins && pre_del && post_ins && post_del) ||\n                           ((lastequality.length < this.Diff_EditCost / 2) &&\n                            (pre_ins + pre_del + post_ins + post_del) == 3))) {\n        // Duplicate record.\n        diffs.splice(equalities[equalitiesLength - 1], 0,\n                     [DIFF_DELETE, lastequality]);\n        // Change second copy to insert.\n        diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;\n        equalitiesLength--;  // Throw away the equality we just deleted;\n        lastequality = null;\n        if (pre_ins && pre_del) {\n          // No changes made which could affect previous entry, keep going.\n          post_ins = post_del = true;\n          equalitiesLength = 0;\n        } else {\n          equalitiesLength--;  // Throw away the previous equality.\n          pointer = equalitiesLength > 0 ?\n              equalities[equalitiesLength - 1] : -1;\n          post_ins = post_del = false;\n        }\n        changes = true;\n      }\n    }\n    pointer++;\n  }\n\n  if (changes) {\n    this.diff_cleanupMerge(diffs);\n  }\n};\n\n\n/**\n * Reorder and merge like edit sections.  Merge equalities.\n * Any edit section can move as long as it doesn't cross an equality.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_cleanupMerge = function(diffs) {\n  diffs.push([DIFF_EQUAL, '']);  // Add a dummy entry at the end.\n  var pointer = 0;\n  var count_delete = 0;\n  var count_insert = 0;\n  var text_delete = '';\n  var text_insert = '';\n  var commonlength;\n  while (pointer < diffs.length) {\n    switch (diffs[pointer][0]) {\n      case DIFF_INSERT:\n        count_insert++;\n        text_insert += diffs[pointer][1];\n        pointer++;\n        break;\n      case DIFF_DELETE:\n        count_delete++;\n        text_delete += diffs[pointer][1];\n        pointer++;\n        break;\n      case DIFF_EQUAL:\n        // Upon reaching an equality, check for prior redundancies.\n        if (count_delete + count_insert > 1) {\n          if (count_delete !== 0 && count_insert !== 0) {\n            // Factor out any common prefixies.\n            commonlength = this.diff_commonPrefix(text_insert, text_delete);\n            if (commonlength !== 0) {\n              if ((pointer - count_delete - count_insert) > 0 &&\n                  diffs[pointer - count_delete - count_insert - 1][0] ==\n                  DIFF_EQUAL) {\n                diffs[pointer - count_delete - count_insert - 1][1] +=\n                    text_insert.substring(0, commonlength);\n              } else {\n                diffs.splice(0, 0, [DIFF_EQUAL,\n                                    text_insert.substring(0, commonlength)]);\n                pointer++;\n              }\n              text_insert = text_insert.substring(commonlength);\n              text_delete = text_delete.substring(commonlength);\n            }\n            // Factor out any common suffixies.\n            commonlength = this.diff_commonSuffix(text_insert, text_delete);\n            if (commonlength !== 0) {\n              diffs[pointer][1] = text_insert.substring(text_insert.length -\n                  commonlength) + diffs[pointer][1];\n              text_insert = text_insert.substring(0, text_insert.length -\n                  commonlength);\n              text_delete = text_delete.substring(0, text_delete.length -\n                  commonlength);\n            }\n          }\n          // Delete the offending records and add the merged ones.\n          if (count_delete === 0) {\n            diffs.splice(pointer - count_insert,\n                count_delete + count_insert, [DIFF_INSERT, text_insert]);\n          } else if (count_insert === 0) {\n            diffs.splice(pointer - count_delete,\n                count_delete + count_insert, [DIFF_DELETE, text_delete]);\n          } else {\n            diffs.splice(pointer - count_delete - count_insert,\n                count_delete + count_insert, [DIFF_DELETE, text_delete],\n                [DIFF_INSERT, text_insert]);\n          }\n          pointer = pointer - count_delete - count_insert +\n                    (count_delete ? 1 : 0) + (count_insert ? 1 : 0) + 1;\n        } else if (pointer !== 0 && diffs[pointer - 1][0] == DIFF_EQUAL) {\n          // Merge this equality with the previous one.\n          diffs[pointer - 1][1] += diffs[pointer][1];\n          diffs.splice(pointer, 1);\n        } else {\n          pointer++;\n        }\n        count_insert = 0;\n        count_delete = 0;\n        text_delete = '';\n        text_insert = '';\n        break;\n    }\n  }\n  if (diffs[diffs.length - 1][1] === '') {\n    diffs.pop();  // Remove the dummy entry at the end.\n  }\n\n  // Second pass: look for single edits surrounded on both sides by equalities\n  // which can be shifted sideways to eliminate an equality.\n  // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC\n  var changes = false;\n  pointer = 1;\n  // Intentionally ignore the first and last element (don't need checking).\n  while (pointer < diffs.length - 1) {\n    if (diffs[pointer - 1][0] == DIFF_EQUAL &&\n        diffs[pointer + 1][0] == DIFF_EQUAL) {\n      // This is a single edit surrounded by equalities.\n      if (diffs[pointer][1].substring(diffs[pointer][1].length -\n          diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) {\n        // Shift the edit over the previous equality.\n        diffs[pointer][1] = diffs[pointer - 1][1] +\n            diffs[pointer][1].substring(0, diffs[pointer][1].length -\n                                        diffs[pointer - 1][1].length);\n        diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];\n        diffs.splice(pointer - 1, 1);\n        changes = true;\n      } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) ==\n          diffs[pointer + 1][1]) {\n        // Shift the edit over the next equality.\n        diffs[pointer - 1][1] += diffs[pointer + 1][1];\n        diffs[pointer][1] =\n            diffs[pointer][1].substring(diffs[pointer + 1][1].length) +\n            diffs[pointer + 1][1];\n        diffs.splice(pointer + 1, 1);\n        changes = true;\n      }\n    }\n    pointer++;\n  }\n  // If shifts were made, the diff needs reordering and another shift sweep.\n  if (changes) {\n    this.diff_cleanupMerge(diffs);\n  }\n};\n\n\n/**\n * loc is a location in text1, compute and return the equivalent location in\n * text2.\n * e.g. 'The cat' vs 'The big cat', 1->1, 5->8\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @param {number} loc Location within text1.\n * @return {number} Location within text2.\n */\ndiff_match_patch.prototype.diff_xIndex = function(diffs, loc) {\n  var chars1 = 0;\n  var chars2 = 0;\n  var last_chars1 = 0;\n  var last_chars2 = 0;\n  var x;\n  for (x = 0; x < diffs.length; x++) {\n    if (diffs[x][0] !== DIFF_INSERT) {  // Equality or deletion.\n      chars1 += diffs[x][1].length;\n    }\n    if (diffs[x][0] !== DIFF_DELETE) {  // Equality or insertion.\n      chars2 += diffs[x][1].length;\n    }\n    if (chars1 > loc) {  // Overshot the location.\n      break;\n    }\n    last_chars1 = chars1;\n    last_chars2 = chars2;\n  }\n  // Was the location was deleted?\n  if (diffs.length != x && diffs[x][0] === DIFF_DELETE) {\n    return last_chars2;\n  }\n  // Add the remaining character length.\n  return last_chars2 + (loc - last_chars1);\n};\n\n\n/**\n * Convert a diff array into a pretty HTML report.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {string} HTML representation.\n */\ndiff_match_patch.prototype.diff_prettyHtml = function(diffs) {\n  var html = [];\n  var pattern_amp = /&/g;\n  var pattern_lt = /</g;\n  var pattern_gt = />/g;\n  var pattern_para = /\\n/g;\n  for (var x = 0; x < diffs.length; x++) {\n    var op = diffs[x][0];    // Operation (insert, delete, equal)\n    var data = diffs[x][1];  // Text of change.\n    var text = data.replace(pattern_amp, '&amp;').replace(pattern_lt, '&lt;')\n        .replace(pattern_gt, '&gt;').replace(pattern_para, '&para;<br>');\n    switch (op) {\n      case DIFF_INSERT:\n        html[x] = '<ins style=\"background:#e6ffe6;\">' + text + '</ins>';\n        break;\n      case DIFF_DELETE:\n        html[x] = '<del style=\"background:#ffe6e6;\">' + text + '</del>';\n        break;\n      case DIFF_EQUAL:\n        html[x] = '<span>' + text + '</span>';\n        break;\n    }\n  }\n  return html.join('');\n};\n\n\n/**\n * Compute and return the source text (all equalities and deletions).\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {string} Source text.\n */\ndiff_match_patch.prototype.diff_text1 = function(diffs) {\n  var text = [];\n  for (var x = 0; x < diffs.length; x++) {\n    if (diffs[x][0] !== DIFF_INSERT) {\n      text[x] = diffs[x][1];\n    }\n  }\n  return text.join('');\n};\n\n\n/**\n * Compute and return the destination text (all equalities and insertions).\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {string} Destination text.\n */\ndiff_match_patch.prototype.diff_text2 = function(diffs) {\n  var text = [];\n  for (var x = 0; x < diffs.length; x++) {\n    if (diffs[x][0] !== DIFF_DELETE) {\n      text[x] = diffs[x][1];\n    }\n  }\n  return text.join('');\n};\n\n\n/**\n * Compute the Levenshtein distance; the number of inserted, deleted or\n * substituted characters.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {number} Number of changes.\n */\ndiff_match_patch.prototype.diff_levenshtein = function(diffs) {\n  var levenshtein = 0;\n  var insertions = 0;\n  var deletions = 0;\n  for (var x = 0; x < diffs.length; x++) {\n    var op = diffs[x][0];\n    var data = diffs[x][1];\n    switch (op) {\n      case DIFF_INSERT:\n        insertions += data.length;\n        break;\n      case DIFF_DELETE:\n        deletions += data.length;\n        break;\n      case DIFF_EQUAL:\n        // A deletion and an insertion is one substitution.\n        levenshtein += Math.max(insertions, deletions);\n        insertions = 0;\n        deletions = 0;\n        break;\n    }\n  }\n  levenshtein += Math.max(insertions, deletions);\n  return levenshtein;\n};\n\n\n/**\n * Crush the diff into an encoded string which describes the operations\n * required to transform text1 into text2.\n * E.g. =3\\t-2\\t+ing  -> Keep 3 chars, delete 2 chars, insert 'ing'.\n * Operations are tab-separated.  Inserted text is escaped using %xx notation.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {string} Delta text.\n */\ndiff_match_patch.prototype.diff_toDelta = function(diffs) {\n  var text = [];\n  for (var x = 0; x < diffs.length; x++) {\n    switch (diffs[x][0]) {\n      case DIFF_INSERT:\n        text[x] = '+' + encodeURI(diffs[x][1]);\n        break;\n      case DIFF_DELETE:\n        text[x] = '-' + diffs[x][1].length;\n        break;\n      case DIFF_EQUAL:\n        text[x] = '=' + diffs[x][1].length;\n        break;\n    }\n  }\n  return text.join('\\t').replace(/%20/g, ' ');\n};\n\n\n/**\n * Given the original text1, and an encoded string which describes the\n * operations required to transform text1 into text2, compute the full diff.\n * @param {string} text1 Source string for the diff.\n * @param {string} delta Delta text.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @throws {!Error} If invalid input.\n */\ndiff_match_patch.prototype.diff_fromDelta = function(text1, delta) {\n  var diffs = [];\n  var diffsLength = 0;  // Keeping our own length var is faster in JS.\n  var pointer = 0;  // Cursor in text1\n  var tokens = delta.split(/\\t/g);\n  for (var x = 0; x < tokens.length; x++) {\n    // Each token begins with a one character parameter which specifies the\n    // operation of this token (delete, insert, equality).\n    var param = tokens[x].substring(1);\n    switch (tokens[x].charAt(0)) {\n      case '+':\n        try {\n          diffs[diffsLength++] = [DIFF_INSERT, decodeURI(param)];\n        } catch (ex) {\n          // Malformed URI sequence.\n          throw new Error('Illegal escape in diff_fromDelta: ' + param);\n        }\n        break;\n      case '-':\n        // Fall through.\n      case '=':\n        var n = parseInt(param, 10);\n        if (isNaN(n) || n < 0) {\n          throw new Error('Invalid number in diff_fromDelta: ' + param);\n        }\n        var text = text1.substring(pointer, pointer += n);\n        if (tokens[x].charAt(0) == '=') {\n          diffs[diffsLength++] = [DIFF_EQUAL, text];\n        } else {\n          diffs[diffsLength++] = [DIFF_DELETE, text];\n        }\n        break;\n      default:\n        // Blank tokens are ok (from a trailing \\t).\n        // Anything else is an error.\n        if (tokens[x]) {\n          throw new Error('Invalid diff operation in diff_fromDelta: ' +\n                          tokens[x]);\n        }\n    }\n  }\n  if (pointer != text1.length) {\n    throw new Error('Delta length (' + pointer +\n        ') does not equal source text length (' + text1.length + ').');\n  }\n  return diffs;\n};\n\n\n//  MATCH FUNCTIONS\n\n\n/**\n * Locate the best instance of 'pattern' in 'text' near 'loc'.\n * @param {string} text The text to search.\n * @param {string} pattern The pattern to search for.\n * @param {number} loc The location to search around.\n * @return {number} Best match index or -1.\n */\ndiff_match_patch.prototype.match_main = function(text, pattern, loc) {\n  // Check for null inputs.\n  if (text == null || pattern == null || loc == null) {\n    throw new Error('Null input. (match_main)');\n  }\n\n  loc = Math.max(0, Math.min(loc, text.length));\n  if (text == pattern) {\n    // Shortcut (potentially not guaranteed by the algorithm)\n    return 0;\n  } else if (!text.length) {\n    // Nothing to match.\n    return -1;\n  } else if (text.substring(loc, loc + pattern.length) == pattern) {\n    // Perfect match at the perfect spot!  (Includes case of null pattern)\n    return loc;\n  } else {\n    // Do a fuzzy compare.\n    return this.match_bitap_(text, pattern, loc);\n  }\n};\n\n\n/**\n * Locate the best instance of 'pattern' in 'text' near 'loc' using the\n * Bitap algorithm.\n * @param {string} text The text to search.\n * @param {string} pattern The pattern to search for.\n * @param {number} loc The location to search around.\n * @return {number} Best match index or -1.\n * @private\n */\ndiff_match_patch.prototype.match_bitap_ = function(text, pattern, loc) {\n  if (pattern.length > this.Match_MaxBits) {\n    throw new Error('Pattern too long for this browser.');\n  }\n\n  // Initialise the alphabet.\n  var s = this.match_alphabet_(pattern);\n\n  var dmp = this;  // 'this' becomes 'window' in a closure.\n\n  /**\n   * Compute and return the score for a match with e errors and x location.\n   * Accesses loc and pattern through being a closure.\n   * @param {number} e Number of errors in match.\n   * @param {number} x Location of match.\n   * @return {number} Overall score for match (0.0 = good, 1.0 = bad).\n   * @private\n   */\n  function match_bitapScore_(e, x) {\n    var accuracy = e / pattern.length;\n    var proximity = Math.abs(loc - x);\n    if (!dmp.Match_Distance) {\n      // Dodge divide by zero error.\n      return proximity ? 1.0 : accuracy;\n    }\n    return accuracy + (proximity / dmp.Match_Distance);\n  }\n\n  // Highest score beyond which we give up.\n  var score_threshold = this.Match_Threshold;\n  // Is there a nearby exact match? (speedup)\n  var best_loc = text.indexOf(pattern, loc);\n  if (best_loc != -1) {\n    score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold);\n    // What about in the other direction? (speedup)\n    best_loc = text.lastIndexOf(pattern, loc + pattern.length);\n    if (best_loc != -1) {\n      score_threshold =\n          Math.min(match_bitapScore_(0, best_loc), score_threshold);\n    }\n  }\n\n  // Initialise the bit arrays.\n  var matchmask = 1 << (pattern.length - 1);\n  best_loc = -1;\n\n  var bin_min, bin_mid;\n  var bin_max = pattern.length + text.length;\n  var last_rd;\n  for (var d = 0; d < pattern.length; d++) {\n    // Scan for the best match; each iteration allows for one more error.\n    // Run a binary search to determine how far from 'loc' we can stray at this\n    // error level.\n    bin_min = 0;\n    bin_mid = bin_max;\n    while (bin_min < bin_mid) {\n      if (match_bitapScore_(d, loc + bin_mid) <= score_threshold) {\n        bin_min = bin_mid;\n      } else {\n        bin_max = bin_mid;\n      }\n      bin_mid = Math.floor((bin_max - bin_min) / 2 + bin_min);\n    }\n    // Use the result from this iteration as the maximum for the next.\n    bin_max = bin_mid;\n    var start = Math.max(1, loc - bin_mid + 1);\n    var finish = Math.min(loc + bin_mid, text.length) + pattern.length;\n\n    var rd = Array(finish + 2);\n    rd[finish + 1] = (1 << d) - 1;\n    for (var j = finish; j >= start; j--) {\n      // The alphabet (s) is a sparse hash, so the following line generates\n      // warnings.\n      var charMatch = s[text.charAt(j - 1)];\n      if (d === 0) {  // First pass: exact match.\n        rd[j] = ((rd[j + 1] << 1) | 1) & charMatch;\n      } else {  // Subsequent passes: fuzzy match.\n        rd[j] = (((rd[j + 1] << 1) | 1) & charMatch) |\n                (((last_rd[j + 1] | last_rd[j]) << 1) | 1) |\n                last_rd[j + 1];\n      }\n      if (rd[j] & matchmask) {\n        var score = match_bitapScore_(d, j - 1);\n        // This match will almost certainly be better than any existing match.\n        // But check anyway.\n        if (score <= score_threshold) {\n          // Told you so.\n          score_threshold = score;\n          best_loc = j - 1;\n          if (best_loc > loc) {\n            // When passing loc, don't exceed our current distance from loc.\n            start = Math.max(1, 2 * loc - best_loc);\n          } else {\n            // Already passed loc, downhill from here on in.\n            break;\n          }\n        }\n      }\n    }\n    // No hope for a (better) match at greater error levels.\n    if (match_bitapScore_(d + 1, loc) > score_threshold) {\n      break;\n    }\n    last_rd = rd;\n  }\n  return best_loc;\n};\n\n\n/**\n * Initialise the alphabet for the Bitap algorithm.\n * @param {string} pattern The text to encode.\n * @return {!Object} Hash of character locations.\n * @private\n */\ndiff_match_patch.prototype.match_alphabet_ = function(pattern) {\n  var s = {};\n  for (var i = 0; i < pattern.length; i++) {\n    s[pattern.charAt(i)] = 0;\n  }\n  for (var i = 0; i < pattern.length; i++) {\n    s[pattern.charAt(i)] |= 1 << (pattern.length - i - 1);\n  }\n  return s;\n};\n\n\n//  PATCH FUNCTIONS\n\n\n/**\n * Increase the context until it is unique,\n * but don't let the pattern expand beyond Match_MaxBits.\n * @param {!diff_match_patch.patch_obj} patch The patch to grow.\n * @param {string} text Source text.\n * @private\n */\ndiff_match_patch.prototype.patch_addContext_ = function(patch, text) {\n  if (text.length == 0) {\n    return;\n  }\n  var pattern = text.substring(patch.start2, patch.start2 + patch.length1);\n  var padding = 0;\n\n  // Look for the first and last matches of pattern in text.  If two different\n  // matches are found, increase the pattern length.\n  while (text.indexOf(pattern) != text.lastIndexOf(pattern) &&\n         pattern.length < this.Match_MaxBits - this.Patch_Margin -\n         this.Patch_Margin) {\n    padding += this.Patch_Margin;\n    pattern = text.substring(patch.start2 - padding,\n                             patch.start2 + patch.length1 + padding);\n  }\n  // Add one chunk for good luck.\n  padding += this.Patch_Margin;\n\n  // Add the prefix.\n  var prefix = text.substring(patch.start2 - padding, patch.start2);\n  if (prefix) {\n    patch.diffs.unshift([DIFF_EQUAL, prefix]);\n  }\n  // Add the suffix.\n  var suffix = text.substring(patch.start2 + patch.length1,\n                              patch.start2 + patch.length1 + padding);\n  if (suffix) {\n    patch.diffs.push([DIFF_EQUAL, suffix]);\n  }\n\n  // Roll back the start points.\n  patch.start1 -= prefix.length;\n  patch.start2 -= prefix.length;\n  // Extend the lengths.\n  patch.length1 += prefix.length + suffix.length;\n  patch.length2 += prefix.length + suffix.length;\n};\n\n\n/**\n * Compute a list of patches to turn text1 into text2.\n * Use diffs if provided, otherwise compute it ourselves.\n * There are four ways to call this function, depending on what data is\n * available to the caller:\n * Method 1:\n * a = text1, b = text2\n * Method 2:\n * a = diffs\n * Method 3 (optimal):\n * a = text1, b = diffs\n * Method 4 (deprecated, use method 3):\n * a = text1, b = text2, c = diffs\n *\n * @param {string|!Array.<!diff_match_patch.Diff>} a text1 (methods 1,3,4) or\n * Array of diff tuples for text1 to text2 (method 2).\n * @param {string|!Array.<!diff_match_patch.Diff>} opt_b text2 (methods 1,4) or\n * Array of diff tuples for text1 to text2 (method 3) or undefined (method 2).\n * @param {string|!Array.<!diff_match_patch.Diff>} opt_c Array of diff tuples\n * for text1 to text2 (method 4) or undefined (methods 1,2,3).\n * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.\n */\ndiff_match_patch.prototype.patch_make = function(a, opt_b, opt_c) {\n  var text1, diffs;\n  if (typeof a == 'string' && typeof opt_b == 'string' &&\n      typeof opt_c == 'undefined') {\n    // Method 1: text1, text2\n    // Compute diffs from text1 and text2.\n    text1 = /** @type {string} */(a);\n    diffs = this.diff_main(text1, /** @type {string} */(opt_b), true);\n    if (diffs.length > 2) {\n      this.diff_cleanupSemantic(diffs);\n      this.diff_cleanupEfficiency(diffs);\n    }\n  } else if (a && typeof a == 'object' && typeof opt_b == 'undefined' &&\n      typeof opt_c == 'undefined') {\n    // Method 2: diffs\n    // Compute text1 from diffs.\n    diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(a);\n    text1 = this.diff_text1(diffs);\n  } else if (typeof a == 'string' && opt_b && typeof opt_b == 'object' &&\n      typeof opt_c == 'undefined') {\n    // Method 3: text1, diffs\n    text1 = /** @type {string} */(a);\n    diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(opt_b);\n  } else if (typeof a == 'string' && typeof opt_b == 'string' &&\n      opt_c && typeof opt_c == 'object') {\n    // Method 4: text1, text2, diffs\n    // text2 is not used.\n    text1 = /** @type {string} */(a);\n    diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(opt_c);\n  } else {\n    throw new Error('Unknown call format to patch_make.');\n  }\n\n  if (diffs.length === 0) {\n    return [];  // Get rid of the null case.\n  }\n  var patches = [];\n  var patch = new diff_match_patch.patch_obj();\n  var patchDiffLength = 0;  // Keeping our own length var is faster in JS.\n  var char_count1 = 0;  // Number of characters into the text1 string.\n  var char_count2 = 0;  // Number of characters into the text2 string.\n  // Start with text1 (prepatch_text) and apply the diffs until we arrive at\n  // text2 (postpatch_text).  We recreate the patches one by one to determine\n  // context info.\n  var prepatch_text = text1;\n  var postpatch_text = text1;\n  for (var x = 0; x < diffs.length; x++) {\n    var diff_type = diffs[x][0];\n    var diff_text = diffs[x][1];\n\n    if (!patchDiffLength && diff_type !== DIFF_EQUAL) {\n      // A new patch starts here.\n      patch.start1 = char_count1;\n      patch.start2 = char_count2;\n    }\n\n    switch (diff_type) {\n      case DIFF_INSERT:\n        patch.diffs[patchDiffLength++] = diffs[x];\n        patch.length2 += diff_text.length;\n        postpatch_text = postpatch_text.substring(0, char_count2) + diff_text +\n                         postpatch_text.substring(char_count2);\n        break;\n      case DIFF_DELETE:\n        patch.length1 += diff_text.length;\n        patch.diffs[patchDiffLength++] = diffs[x];\n        postpatch_text = postpatch_text.substring(0, char_count2) +\n                         postpatch_text.substring(char_count2 +\n                             diff_text.length);\n        break;\n      case DIFF_EQUAL:\n        if (diff_text.length <= 2 * this.Patch_Margin &&\n            patchDiffLength && diffs.length != x + 1) {\n          // Small equality inside a patch.\n          patch.diffs[patchDiffLength++] = diffs[x];\n          patch.length1 += diff_text.length;\n          patch.length2 += diff_text.length;\n        } else if (diff_text.length >= 2 * this.Patch_Margin) {\n          // Time for a new patch.\n          if (patchDiffLength) {\n            this.patch_addContext_(patch, prepatch_text);\n            patches.push(patch);\n            patch = new diff_match_patch.patch_obj();\n            patchDiffLength = 0;\n            // Unlike Unidiff, our patch lists have a rolling context.\n            // http://code.google.com/p/google-diff-match-patch/wiki/Unidiff\n            // Update prepatch text & pos to reflect the application of the\n            // just completed patch.\n            prepatch_text = postpatch_text;\n            char_count1 = char_count2;\n          }\n        }\n        break;\n    }\n\n    // Update the current character count.\n    if (diff_type !== DIFF_INSERT) {\n      char_count1 += diff_text.length;\n    }\n    if (diff_type !== DIFF_DELETE) {\n      char_count2 += diff_text.length;\n    }\n  }\n  // Pick up the leftover patch if not empty.\n  if (patchDiffLength) {\n    this.patch_addContext_(patch, prepatch_text);\n    patches.push(patch);\n  }\n\n  return patches;\n};\n\n\n/**\n * Given an array of patches, return another array that is identical.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.\n */\ndiff_match_patch.prototype.patch_deepCopy = function(patches) {\n  // Making deep copies is hard in JavaScript.\n  var patchesCopy = [];\n  for (var x = 0; x < patches.length; x++) {\n    var patch = patches[x];\n    var patchCopy = new diff_match_patch.patch_obj();\n    patchCopy.diffs = [];\n    for (var y = 0; y < patch.diffs.length; y++) {\n      patchCopy.diffs[y] = patch.diffs[y].slice();\n    }\n    patchCopy.start1 = patch.start1;\n    patchCopy.start2 = patch.start2;\n    patchCopy.length1 = patch.length1;\n    patchCopy.length2 = patch.length2;\n    patchesCopy[x] = patchCopy;\n  }\n  return patchesCopy;\n};\n\n\n/**\n * Merge a set of patches onto the text.  Return a patched text, as well\n * as a list of true/false values indicating which patches were applied.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n * @param {string} text Old text.\n * @return {!Array.<string|!Array.<boolean>>} Two element Array, containing the\n *      new text and an array of boolean values.\n */\ndiff_match_patch.prototype.patch_apply = function(patches, text) {\n  if (patches.length == 0) {\n    return [text, []];\n  }\n\n  // Deep copy the patches so that no changes are made to originals.\n  patches = this.patch_deepCopy(patches);\n\n  var nullPadding = this.patch_addPadding(patches);\n  text = nullPadding + text + nullPadding;\n\n  this.patch_splitMax(patches);\n  // delta keeps track of the offset between the expected and actual location\n  // of the previous patch.  If there are patches expected at positions 10 and\n  // 20, but the first patch was found at 12, delta is 2 and the second patch\n  // has an effective expected position of 22.\n  var delta = 0;\n  var results = [];\n  for (var x = 0; x < patches.length; x++) {\n    var expected_loc = patches[x].start2 + delta;\n    var text1 = this.diff_text1(patches[x].diffs);\n    var start_loc;\n    var end_loc = -1;\n    if (text1.length > this.Match_MaxBits) {\n      // patch_splitMax will only provide an oversized pattern in the case of\n      // a monster delete.\n      start_loc = this.match_main(text, text1.substring(0, this.Match_MaxBits),\n                                  expected_loc);\n      if (start_loc != -1) {\n        end_loc = this.match_main(text,\n            text1.substring(text1.length - this.Match_MaxBits),\n            expected_loc + text1.length - this.Match_MaxBits);\n        if (end_loc == -1 || start_loc >= end_loc) {\n          // Can't find valid trailing context.  Drop this patch.\n          start_loc = -1;\n        }\n      }\n    } else {\n      start_loc = this.match_main(text, text1, expected_loc);\n    }\n    if (start_loc == -1) {\n      // No match found.  :(\n      results[x] = false;\n      // Subtract the delta for this failed patch from subsequent patches.\n      delta -= patches[x].length2 - patches[x].length1;\n    } else {\n      // Found a match.  :)\n      results[x] = true;\n      delta = start_loc - expected_loc;\n      var text2;\n      if (end_loc == -1) {\n        text2 = text.substring(start_loc, start_loc + text1.length);\n      } else {\n        text2 = text.substring(start_loc, end_loc + this.Match_MaxBits);\n      }\n      if (text1 == text2) {\n        // Perfect match, just shove the replacement text in.\n        text = text.substring(0, start_loc) +\n               this.diff_text2(patches[x].diffs) +\n               text.substring(start_loc + text1.length);\n      } else {\n        // Imperfect match.  Run a diff to get a framework of equivalent\n        // indices.\n        var diffs = this.diff_main(text1, text2, false);\n        if (text1.length > this.Match_MaxBits &&\n            this.diff_levenshtein(diffs) / text1.length >\n            this.Patch_DeleteThreshold) {\n          // The end points match, but the content is unacceptably bad.\n          results[x] = false;\n        } else {\n          this.diff_cleanupSemanticLossless(diffs);\n          var index1 = 0;\n          var index2;\n          for (var y = 0; y < patches[x].diffs.length; y++) {\n            var mod = patches[x].diffs[y];\n            if (mod[0] !== DIFF_EQUAL) {\n              index2 = this.diff_xIndex(diffs, index1);\n            }\n            if (mod[0] === DIFF_INSERT) {  // Insertion\n              text = text.substring(0, start_loc + index2) + mod[1] +\n                     text.substring(start_loc + index2);\n            } else if (mod[0] === DIFF_DELETE) {  // Deletion\n              text = text.substring(0, start_loc + index2) +\n                     text.substring(start_loc + this.diff_xIndex(diffs,\n                         index1 + mod[1].length));\n            }\n            if (mod[0] !== DIFF_DELETE) {\n              index1 += mod[1].length;\n            }\n          }\n        }\n      }\n    }\n  }\n  // Strip the padding off.\n  text = text.substring(nullPadding.length, text.length - nullPadding.length);\n  return [text, results];\n};\n\n\n/**\n * Add some padding on text start and end so that edges can match something.\n * Intended to be called only from within patch_apply.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n * @return {string} The padding string added to each side.\n */\ndiff_match_patch.prototype.patch_addPadding = function(patches) {\n  var paddingLength = this.Patch_Margin;\n  var nullPadding = '';\n  for (var x = 1; x <= paddingLength; x++) {\n    nullPadding += String.fromCharCode(x);\n  }\n\n  // Bump all the patches forward.\n  for (var x = 0; x < patches.length; x++) {\n    patches[x].start1 += paddingLength;\n    patches[x].start2 += paddingLength;\n  }\n\n  // Add some padding on start of first diff.\n  var patch = patches[0];\n  var diffs = patch.diffs;\n  if (diffs.length == 0 || diffs[0][0] != DIFF_EQUAL) {\n    // Add nullPadding equality.\n    diffs.unshift([DIFF_EQUAL, nullPadding]);\n    patch.start1 -= paddingLength;  // Should be 0.\n    patch.start2 -= paddingLength;  // Should be 0.\n    patch.length1 += paddingLength;\n    patch.length2 += paddingLength;\n  } else if (paddingLength > diffs[0][1].length) {\n    // Grow first equality.\n    var extraLength = paddingLength - diffs[0][1].length;\n    diffs[0][1] = nullPadding.substring(diffs[0][1].length) + diffs[0][1];\n    patch.start1 -= extraLength;\n    patch.start2 -= extraLength;\n    patch.length1 += extraLength;\n    patch.length2 += extraLength;\n  }\n\n  // Add some padding on end of last diff.\n  patch = patches[patches.length - 1];\n  diffs = patch.diffs;\n  if (diffs.length == 0 || diffs[diffs.length - 1][0] != DIFF_EQUAL) {\n    // Add nullPadding equality.\n    diffs.push([DIFF_EQUAL, nullPadding]);\n    patch.length1 += paddingLength;\n    patch.length2 += paddingLength;\n  } else if (paddingLength > diffs[diffs.length - 1][1].length) {\n    // Grow last equality.\n    var extraLength = paddingLength - diffs[diffs.length - 1][1].length;\n    diffs[diffs.length - 1][1] += nullPadding.substring(0, extraLength);\n    patch.length1 += extraLength;\n    patch.length2 += extraLength;\n  }\n\n  return nullPadding;\n};\n\n\n/**\n * Look through the patches and break up any which are longer than the maximum\n * limit of the match algorithm.\n * Intended to be called only from within patch_apply.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n */\ndiff_match_patch.prototype.patch_splitMax = function(patches) {\n  var patch_size = this.Match_MaxBits;\n  for (var x = 0; x < patches.length; x++) {\n    if (patches[x].length1 <= patch_size) {\n      continue;\n    }\n    var bigpatch = patches[x];\n    // Remove the big old patch.\n    patches.splice(x--, 1);\n    var start1 = bigpatch.start1;\n    var start2 = bigpatch.start2;\n    var precontext = '';\n    while (bigpatch.diffs.length !== 0) {\n      // Create one of several smaller patches.\n      var patch = new diff_match_patch.patch_obj();\n      var empty = true;\n      patch.start1 = start1 - precontext.length;\n      patch.start2 = start2 - precontext.length;\n      if (precontext !== '') {\n        patch.length1 = patch.length2 = precontext.length;\n        patch.diffs.push([DIFF_EQUAL, precontext]);\n      }\n      while (bigpatch.diffs.length !== 0 &&\n             patch.length1 < patch_size - this.Patch_Margin) {\n        var diff_type = bigpatch.diffs[0][0];\n        var diff_text = bigpatch.diffs[0][1];\n        if (diff_type === DIFF_INSERT) {\n          // Insertions are harmless.\n          patch.length2 += diff_text.length;\n          start2 += diff_text.length;\n          patch.diffs.push(bigpatch.diffs.shift());\n          empty = false;\n        } else if (diff_type === DIFF_DELETE && patch.diffs.length == 1 &&\n                   patch.diffs[0][0] == DIFF_EQUAL &&\n                   diff_text.length > 2 * patch_size) {\n          // This is a large deletion.  Let it pass in one chunk.\n          patch.length1 += diff_text.length;\n          start1 += diff_text.length;\n          empty = false;\n          patch.diffs.push([diff_type, diff_text]);\n          bigpatch.diffs.shift();\n        } else {\n          // Deletion or equality.  Only take as much as we can stomach.\n          diff_text = diff_text.substring(0,\n              patch_size - patch.length1 - this.Patch_Margin);\n          patch.length1 += diff_text.length;\n          start1 += diff_text.length;\n          if (diff_type === DIFF_EQUAL) {\n            patch.length2 += diff_text.length;\n            start2 += diff_text.length;\n          } else {\n            empty = false;\n          }\n          patch.diffs.push([diff_type, diff_text]);\n          if (diff_text == bigpatch.diffs[0][1]) {\n            bigpatch.diffs.shift();\n          } else {\n            bigpatch.diffs[0][1] =\n                bigpatch.diffs[0][1].substring(diff_text.length);\n          }\n        }\n      }\n      // Compute the head context for the next patch.\n      precontext = this.diff_text2(patch.diffs);\n      precontext =\n          precontext.substring(precontext.length - this.Patch_Margin);\n      // Append the end context for this patch.\n      var postcontext = this.diff_text1(bigpatch.diffs)\n                            .substring(0, this.Patch_Margin);\n      if (postcontext !== '') {\n        patch.length1 += postcontext.length;\n        patch.length2 += postcontext.length;\n        if (patch.diffs.length !== 0 &&\n            patch.diffs[patch.diffs.length - 1][0] === DIFF_EQUAL) {\n          patch.diffs[patch.diffs.length - 1][1] += postcontext;\n        } else {\n          patch.diffs.push([DIFF_EQUAL, postcontext]);\n        }\n      }\n      if (!empty) {\n        patches.splice(++x, 0, patch);\n      }\n    }\n  }\n};\n\n\n/**\n * Take a list of patches and return a textual representation.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n * @return {string} Text representation of patches.\n */\ndiff_match_patch.prototype.patch_toText = function(patches) {\n  var text = [];\n  for (var x = 0; x < patches.length; x++) {\n    text[x] = patches[x];\n  }\n  return text.join('');\n};\n\n\n/**\n * Parse a textual representation of patches and return a list of Patch objects.\n * @param {string} textline Text representation of patches.\n * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.\n * @throws {!Error} If invalid input.\n */\ndiff_match_patch.prototype.patch_fromText = function(textline) {\n  var patches = [];\n  if (!textline) {\n    return patches;\n  }\n  var text = textline.split('\\n');\n  var textPointer = 0;\n  var patchHeader = /^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$/;\n  while (textPointer < text.length) {\n    var m = text[textPointer].match(patchHeader);\n    if (!m) {\n      throw new Error('Invalid patch string: ' + text[textPointer]);\n    }\n    var patch = new diff_match_patch.patch_obj();\n    patches.push(patch);\n    patch.start1 = parseInt(m[1], 10);\n    if (m[2] === '') {\n      patch.start1--;\n      patch.length1 = 1;\n    } else if (m[2] == '0') {\n      patch.length1 = 0;\n    } else {\n      patch.start1--;\n      patch.length1 = parseInt(m[2], 10);\n    }\n\n    patch.start2 = parseInt(m[3], 10);\n    if (m[4] === '') {\n      patch.start2--;\n      patch.length2 = 1;\n    } else if (m[4] == '0') {\n      patch.length2 = 0;\n    } else {\n      patch.start2--;\n      patch.length2 = parseInt(m[4], 10);\n    }\n    textPointer++;\n\n    while (textPointer < text.length) {\n      var sign = text[textPointer].charAt(0);\n      try {\n        var line = decodeURI(text[textPointer].substring(1));\n      } catch (ex) {\n        // Malformed URI sequence.\n        throw new Error('Illegal escape in patch_fromText: ' + line);\n      }\n      if (sign == '-') {\n        // Deletion.\n        patch.diffs.push([DIFF_DELETE, line]);\n      } else if (sign == '+') {\n        // Insertion.\n        patch.diffs.push([DIFF_INSERT, line]);\n      } else if (sign == ' ') {\n        // Minor equality.\n        patch.diffs.push([DIFF_EQUAL, line]);\n      } else if (sign == '@') {\n        // Start of next patch.\n        break;\n      } else if (sign === '') {\n        // Blank line?  Whatever.\n      } else {\n        // WTF?\n        throw new Error('Invalid patch mode \"' + sign + '\" in: ' + line);\n      }\n      textPointer++;\n    }\n  }\n  return patches;\n};\n\n\n/**\n * Class representing one patch operation.\n * @constructor\n */\ndiff_match_patch.patch_obj = function() {\n  /** @type {!Array.<!diff_match_patch.Diff>} */\n  this.diffs = [];\n  /** @type {?number} */\n  this.start1 = null;\n  /** @type {?number} */\n  this.start2 = null;\n  /** @type {number} */\n  this.length1 = 0;\n  /** @type {number} */\n  this.length2 = 0;\n};\n\n\n/**\n * Emmulate GNU diff's format.\n * Header: @@ -382,8 +481,9 @@\n * Indicies are printed as 1-based, not 0-based.\n * @return {string} The GNU diff string.\n */\ndiff_match_patch.patch_obj.prototype.toString = function() {\n  var coords1, coords2;\n  if (this.length1 === 0) {\n    coords1 = this.start1 + ',0';\n  } else if (this.length1 == 1) {\n    coords1 = this.start1 + 1;\n  } else {\n    coords1 = (this.start1 + 1) + ',' + this.length1;\n  }\n  if (this.length2 === 0) {\n    coords2 = this.start2 + ',0';\n  } else if (this.length2 == 1) {\n    coords2 = this.start2 + 1;\n  } else {\n    coords2 = (this.start2 + 1) + ',' + this.length2;\n  }\n  var text = ['@@ -' + coords1 + ' +' + coords2 + ' @@\\n'];\n  var op;\n  // Escape the body of the patch with %xx notation.\n  for (var x = 0; x < this.diffs.length; x++) {\n    switch (this.diffs[x][0]) {\n      case DIFF_INSERT:\n        op = '+';\n        break;\n      case DIFF_DELETE:\n        op = '-';\n        break;\n      case DIFF_EQUAL:\n        op = ' ';\n        break;\n    }\n    text[x + 1] = op + encodeURI(this.diffs[x][1]) + '\\n';\n  }\n  return text.join('').replace(/%20/g, ' ');\n};\n\n\n// Export these global variables so that they survive Google's JS compiler.\n// In a browser, 'this' will be 'window'.\n// Users of node.js should 'require' the uncompressed version since Google's\n// JS compiler may break the following exports for non-browser environments.\nthis['diff_match_patch'] = diff_match_patch;\nthis['DIFF_DELETE'] = DIFF_DELETE;\nthis['DIFF_INSERT'] = DIFF_INSERT;\nthis['DIFF_EQUAL'] = DIFF_EQUAL;\n"
  },
  {
    "path": "packages/test-in-browser/driver.css",
    "content": "body {\n    padding-top: 60px;\n    padding-bottom: 40px;\n}\n\n#testProgressBar {\n    margin-top: 10px;\n    position: relative;\n}\n\n.header {\n  font-family: Arial, sans-serif;\n  font-size: 24px;\n  padding-bottom: 4px;\n}\n\n.header.in-progress {\n  color: #ccc;\n}\n\n.header.pass {\n  color: #090; /* green */\n}\n\n.header.fail {\n  color: #900; /* red */\n  font-weight: bold;\n}\n\n.header .time {\n  color: #666;\n  font-size: 14px;\n}\n\n.test_table {\n  font-family: Arial, sans-serif;\n  font-size: 16px;\n}\n\n.test_table .group {\n  border-left: 1px solid #ddd;\n}\n\n.test_table .group .group {\n  margin-left: 20px;\n}\n\n.test_table .test {\n  margin-left: 20px;\n}\n\n.test_table .testname {\n  margin-left: 200px;\n  line-height: 24px;\n  vertical-align: middle;\n  text-decoration: underline;\n  cursor: pointer;\n}\n\n.test_table .groupname {\n  font-weight: bold;\n  background: #ddd;\n  padding-left: 5px;\n  line-height: 24px;\n  vertical-align: middle;\n  font-size: 16px;\n}\n\n.test_table .event {\n  margin-left: 20px;\n  font-size: 14px;\n  border-left: 2px solid #def;\n  padding: 4px;\n  position: relative;\n}\n\n.test_table .test .testrow { position: relative; overflow: hidden; /*hasLayout*/ }\n\n.test_table .running .testname { color: #66c; /* blue */ }\n.test_table .failed .testname { color: #900; /* red */ }\n.test_table .succeeded .testname { color: #090; /* green */ }\n\n.test_table .teststatus {\n  position: absolute;\n  height: 100%;\n  width: 100px;\n  left: 0px;\n  top: 0;\n  text-align: center;\n  line-height: 24px;\n  vertical-align: middle;\n}\n\n.test_table .testtime {\n  position: absolute;\n  height: 100%;\n  width: 75px;\n  margin-right: 5px;\n  left: 100px;\n  top: 0;\n  text-align: right;\n  line-height: 24px;\n  vertical-align: middle;\n  font-size: 14px;\n  color: #666;\n}\n\n.test_table .succeeded .teststatus { color: #090; /* green */  background: #cfc; }\n.test_table .failed .teststatus { color: #900; /* red */  background: #fcc; }\n.test_table .running .teststatus { color: #ccc; }\n\n.test_table .event .expected_fail { color: #600; }\n.test_table .event .fail { color: #d00; }\n.test_table .event .exception { color: #d00; }\n.test_table .event .nodata { color: #ccc; font-style: italic; }\n\n.test_table .event .xtimes, .test_table .event .failkey { font-weight: bold; }\n\n.test_table .event .debug {\n    display: none;\n}\n\n.test_table .event:hover .debug {\n    display: inline;\n    color: gray;\n    text-decoration: underline;\n    cursor: pointer;\n}\n\n.in-progress {\n    position: absolute;\n    left: 10px;\n    z-index: 2;\n}\n\n.string_equal {\n  line-height: 1.2;\n  margin-left: 30px;\n}\n.string_equal ins {\n  text-decoration: none;\n}\n.string_equal_expected ins {\n  background: #ed0;\n}\n.string_equal_actual ins {\n  color: #d00;\n  background: #fcc;\n}\n\n#current-client-test {\n  color: #ccc;\n  margin-right: 15px;\n}"
  },
  {
    "path": "packages/test-in-browser/driver.html",
    "content": "<template name=\"testInBrowserBody\">\n  <div class=\"container-fluid\">\n  {{> navBars}}\n  {{> failedTests}}\n  {{> testTable}}\n  </div>\n</template>\n\n<template name=\"navBars\">\n  <div class=\"navbar navbar-fixed-top navbar-inverse\">\n    <div class=\"navbar-inner\">\n      <div class=\"row-fluid\">\n        <div class=\"span3\"><a class=\"brand\" href=\"#\">\n          &nbsp;\n          {{#if running}}\n            Testing in progress...\n          {{else}}\n            {{#if passed}}\n              All tests pass!\n            {{else}}\n              There are failures.\n            {{/if}}\n          {{/if}}\n        </a></div>\n        <div class=\"span2\">\n          {{#unless running}}\n            <p class=\"navbar-text\">{{total_test_time}} ms</p>\n          {{/unless}}\n        </div>\n        <div class=\"span6\">\n          {{> progressBar}}\n        </div>\n        <div class=\"span1\"></div>\n      </div>\n    </div>\n  </div>\n  {{> groupNav}}\n</template>\n\n<template name=\"progressBar\">\n  <div id=\"testProgressBar\" class=\"progress {{barOuterClass}}\">\n    <span class=\"in-progress\">Passed {{passedCount}} of {{totalCount}}</span>\n    <div class=\"bar bar-danger\" style=\"width: {{percentFail}}%;\"></div>\n    <div class=\"bar {{barInnerClass}}\" style=\"width: {{percentPass}}%;\"></div>\n  </div>\n</template>\n\n<template name=\"groupNav\">\n  <div class=\"navbar navbar-fixed-bottom navbar-inverse\">\n    <div class=\"navbar-inner\">\n      <ul class=\"nav\">\n      {{#each groupPaths}}\n        <li class=\"navbar-text\">&nbsp;-&nbsp;</li>\n        <li><a class=\"group\" href=\"#\">{{name}}</a></li>\n      {{/each}}\n      </ul>\n      <form class=\"navbar-form pull-right\">\n        <span id=\"current-client-test\"></span>\n        <a class=\"btn rerun\">\n          {{#if rerunScheduled}}\n          <i class=\"icon-time\"></i>\n          Rerun scheduled...\n          {{else}}\n          <i class=\"icon-repeat\"></i>\n          Rerun\n          {{/if}}\n        </a>\n      </form>\n      &nbsp;\n    </div>\n  </div>\n</template>\n\n<template name=\"failedTests\">\n  <div class=\"row-fluid\"><div class=\"span12\">\n  <ul class=\"failedTests\">\n    {{#each failedTests}}\n      <li>{{this}}</li>\n    {{/each}}\n  </ul>\n  </div></div>\n</template>\n\n<template name=\"testTable\">\n  <div class=\"row-fluid\"><div class=\"span12\">\n  <div class=\"test_table\">\n    {{#each testdata}}\n      {{> test_group thisWithDep}}\n    {{/each}}\n  </div>\n  </div></div>\n</template>\n\n<template name=\"test_group\">\n  <div class=\"group\">\n    <div class=\"groupname\"><a>{{name}}</a></div>\n    {{#each tests}}\n      {{> test thisWithDep}}\n    {{/each}}\n    {{#each groups}}\n      {{> test_group thisWithDep}}\n    {{/each}}\n  </div>\n</template>\n\n<template name=\"test\">\n  <div class=\"test {{test_class}}\">\n    <div class=\"testrow\">\n      <div class=\"teststatus\">\n        {{test_status_display}}\n      </div>\n      <div class=\"testtime\">\n        {{test_time_display}}\n      </div>\n      <div class=\"testname\">\n        {{#if server}}S:{{else}}C:{{/if}}\n        {{name}}\n      </div>\n    </div>\n    {{#if expanded}}\n      {{#each eventsArray}}\n        {{> event}}\n      {{else}}\n        <div class=\"event\"><div class=\"nodata\">(no data)</div></div>\n      {{/each}}\n    {{/if}}\n  </div>\n</template>\n\n<template name=\"event\">\n  <div class=\"event\">\n    <div class=\"{{type}}\">\n      <span>\n      - {{type}}\n      {{#if times}}\n        <span class=\"xtimes\">({{times}} times)</span>\n      {{/if}}\n      {{#with get_details}}\n        {{#if this}}\n          {{!\n            `type` can be any of the following or a\n            custom assertion type\n\n            * assert_equal\n            * instanceOf\n            * throws\n            * true\n            * null\n            * undefined\n            * NaN\n            * include\n            * length\n          }}\n          {{#if type}}&mdash; {{type}}{{/if}}\n          {{#each details}}\n            - <span class=\"failkey\">{{key}}</span> {{val}}\n          {{/each}}\n        {{/if}}\n        {{#if stack}}<pre>{{stack}}</pre>{{/if}}\n      {{/with}}\n      {{#if is_debuggable}}\n        <span class=\"debug\">[Debug]</span>\n      {{/if}}\n      </span>\n    </div>\n  </div>\n</template>\n"
  },
  {
    "path": "packages/test-in-browser/driver.js",
    "content": "////\n//// Setup\n////\n\n\n// dependency for the count of tests running/passed/failed, etc. drives\n// the navbar and the like.\nvar countDep = new Tracker.Dependency;\n// things that change on countDep\nvar running = true;\nvar totalCount = 0;\nvar passedCount = 0;\nvar failedCount = 0;\nvar failedTests = [];\n\n// Dependency for when a new top level group is added. Each group and\n// each test have their own dependency objects.\nvar topLevelGroupsDep = new Tracker.Dependency;\n\n// An array of top-level groups.\n//\n// Each group is an object with:\n// - name: string\n// - path: array of strings (names of parent groups)\n// - parent: parent group object (back reference)\n// - dep: Tracker.Dependency object for this group. fires when new tests added.\n// - groups: list of sub-groups\n// - tests: list of tests in this group\n//\n// Each test is an object with:\n// - name: string\n// - parent: parent group object (back reference)\n// - server: boolean\n// - fullName: string\n// - dep: Tracker.Dependency object for this test. fires when the test completes.\nvar resultTree = [];\n\n\nSession.setDefault(\"groupPath\", [\"tinytest\"]);\nSession.set(\"rerunScheduled\", false);\n\n// This function is exported. It's called on client startup by the\n// bundle generated by `meteor test` or `meteor test-packages`.\nrunTests = function () {\n  document.body.innerHTML = \"\";\n  document.head.title = \"Tests\";\n\n  Blaze.render(Template.testInBrowserBody, document.body);\n\n  Tracker.flush();\n  Tinytest._runTestsEverywhere(reportResults, function () {\n    running = false;\n    Meteor.onTestsComplete && Meteor.onTestsComplete();\n    countDep.changed();\n    Tracker.flush();\n\n    Meteor.connection._unsubscribeAll();\n  }, Session.get(\"groupPath\"));\n\n};\n\n\n////\n//// Take incoming results and drive resultsTree\n////\n\n// report a series of events in a single test, or just the existence of\n// that test if no events. this is the entry point for test results to\n// this module.\nvar reportResults = function(results) {\n  var test = _findTestForResults(results);\n\n  // Tolerate repeated reports: first undo the effect of any previous report\n  var status = _testStatus(test);\n  if (status === \"failed\") {\n    failedCount--;\n    countDep.changed();\n  } else if (status === \"succeeded\") {\n    passedCount--;\n    countDep.changed();\n  }\n\n  // Now process the current report\n  if (_.isArray(results.events)) {\n    // append events, if present\n    Array.prototype.push.apply((test.events || (test.events = [])),\n                               results.events);\n    // sort and de-duplicate, based on sequence number\n    test.events.sort(function (a, b) {\n      return a.sequence - b.sequence;\n    });\n    var out = [];\n    _.each(test.events, function (e) {\n      if (out.length === 0 || out[out.length - 1].sequence !== e.sequence)\n        out.push(e);\n    });\n    test.events = out;\n  }\n  status = _testStatus(test);\n  if (status === \"failed\") {\n    failedCount++;\n    // Expand a failed test (but only set this if the user hasn't clicked on the\n    // test name yet).\n    if (test.expanded === undefined)\n      test.expanded = true;\n    if (!_.contains(failedTests, test.fullName))\n      failedTests.push(test.fullName);\n\n    countDep.changed();\n    test.dep.changed();\n  } else if (status === \"succeeded\") {\n    passedCount++;\n    countDep.changed();\n    test.dep.changed();\n  } else if (test.expanded) {\n    // re-render the test if new results come in and the test is\n    // currently expanded.\n    test.dep.changed();\n  }\n};\n\n// forget all of the events for a particular test\nvar forgetEvents = function (results) {\n  var test = _findTestForResults(results);\n  var status = _testStatus(test);\n  if (status === \"failed\") {\n    failedCount--;\n    countDep.changed();\n  } else if (status === \"succeeded\") {\n    passedCount--;\n    countDep.changed();\n  }\n  delete test.events;\n  test.dep.changed();\n};\n\n// given a 'results' as delivered via reportResults, find the\n// corresponding leaf object in resultTree, creating one if it doesn't\n// exist. it will be an object with attributes 'name', 'parent', and\n// possibly 'events'.\nvar _findTestForResults = function (results) {\n  var groupPath = results.groupPath; // array\n  if ((! _.isArray(groupPath)) || (groupPath.length < 1)) {\n    throw new Error(\"Test must be part of a group\");\n  }\n\n  var group;\n  var i = 0;\n  _.each(groupPath, function(gname) {\n    var array = (group ? (group.groups || (group.groups = []))\n                 : resultTree);\n    var newGroup = _.find(array, function(g) { return g.name === gname; });\n    if (! newGroup) {\n      newGroup = {\n        name: gname,\n        parent: (group || null),\n        path: groupPath.slice(0, i+1),\n        dep: new Tracker.Dependency\n      }; // create group\n      array.push(newGroup);\n\n      if (group)\n        group.dep.changed();\n      else\n        topLevelGroupsDep.changed();\n    }\n    group = newGroup;\n    i++;\n  });\n\n  var testName = results.test;\n  var server = !!results.server;\n  var test = _.find(group.tests || (group.tests = []),\n                    function(t) { return t.name === testName &&\n                                  t.server === server; });\n  if (! test) {\n    // create test\n    var nameParts = _.clone(groupPath);\n    nameParts.push(testName);\n    var fullName = nameParts.join(' - ');\n    test = {\n      name: testName,\n      parent: group,\n      server: server,\n      fullName: fullName,\n      dep: new Tracker.Dependency\n    };\n    group.tests.push(test);\n    group.dep.changed();\n    totalCount++;\n    countDep.changed();\n  }\n\n  return test;\n};\n\n\n\n////\n//// Helpers on test objects\n////\n\nvar _testTime = function(t) {\n  if (t.events && t.events.length > 0) {\n    var lastEvent = _.last(t.events);\n    if (lastEvent.type === \"finish\") {\n      if ((typeof lastEvent.timeMs) === \"number\") {\n        return lastEvent.timeMs;\n      }\n    }\n  }\n  return null;\n};\n\nvar _testStatus = function(t) {\n  var events = t.events || [];\n  if (_.find(events, function(x) { return x.type === \"exception\"; })) {\n    // \"exception\" should be last event, except race conditions on the\n    // server can make this not the case.  Technically we can't tell\n    // if the test is still running at this point, but it can only\n    // result in FAIL.\n    return \"failed\";\n  } else if (events.length == 0 || (_.last(events).type != \"finish\")) {\n    return \"running\";\n  } else if (_.any(events, function(e) {\n    return e.type == \"fail\" || e.type == \"exception\"; })) {\n    return \"failed\";\n  } else {\n    return \"succeeded\";\n  }\n};\n\n\n\n////\n//// Templates\n////\n\n//// Template - navBars\n\nTemplate.navBars.helpers({\n  running: function() {\n    countDep.depend();\n    return running;\n  },\n  passed: function() {\n    countDep.depend();\n    return failedCount === 0;\n  },\n  total_test_time: function() {\n    countDep.depend();\n\n    // walk whole tree to get all tests\n    var walk = function (groups) {\n      var total = 0;\n\n      _.each(groups || [], function (group) {\n        _.each(group.tests || [], function (t) {\n          total += _testTime(t);\n        });\n\n        total += walk(group.groups);\n      });\n\n      return total;\n    };\n\n    return walk(resultTree);\n  }\n});\n\n\n//// Template - progressBar\n\nTemplate.progressBar.helpers({\n  running: function () {\n    countDep.depend();\n    return running;\n  },\n  percentPass: function () {\n    countDep.depend();\n    if (totalCount === 0)\n      return 0;\n    return 100*passedCount/totalCount;\n  },\n  totalCount: function () {\n    countDep.depend();\n    return totalCount;\n  },\n  passedCount: function () {\n    countDep.depend();\n    return passedCount;\n  },\n  percentFail: function () {\n    countDep.depend();\n    if (totalCount === 0)\n      return 0;\n    return 100*failedCount/totalCount;\n  },\n  anyFail: function () {\n    countDep.depend();\n    return failedCount > 0;\n  },\n  barOuterClass: function () {\n    countDep.depend();\n    return running ? 'progress-striped' : '';\n  },\n  barInnerClass: function () {\n    countDep.depend();\n    return (failedCount > 0 ?\n            'bar-warning' : 'bar-success');\n  }\n});\n\n//// Template - groupNav\n\nvar changeToPath = function (path) {\n  Session.set(\"groupPath\", path);\n  Session.set(\"rerunScheduled\", true);\n  // pretend there's just been a hot code push\n  // so we run the tests completely fresh.\n  Reload._reload();\n};\n\nTemplate.groupNav.helpers({\n  groupPaths: function () {\n    var groupPath = Session.get(\"groupPath\");\n    var ret = [];\n    for (var i = 1; i <= groupPath.length; i++) {\n      ret.push({path: groupPath.slice(0,i), name: groupPath[i-1]});\n    }\n    return ret;\n  },\n  rerunScheduled: function () {\n    return Session.get(\"rerunScheduled\");\n  }\n});\n\nTemplate.groupNav.events({\n  'click .group': function () {\n    changeToPath(this.path);\n  },\n  'click .rerun': function () {\n    Session.set(\"rerunScheduled\", true);\n    Reload._reload();\n  }\n});\n\nTemplate.groupNav.onRendered(function () {\n  Tinytest._onCurrentClientTest = function (name) {\n    name = (name ? 'C: '+name : '');\n    // Set the DOM directly so that it's immediate and we\n    // don't wait for Tracker to flush.\n    var span = document.getElementById('current-client-test');\n    if (span) {\n      span.innerHTML = '';\n      span.appendChild(document.createTextNode(name));\n    }\n  };\n});\n\n\n//// Template - failedTests\n\nTemplate.failedTests.helpers({\n  failedTests: function() {\n    countDep.depend();\n    return failedTests;\n  }\n});\n\n//// Template - testTable\n\nTemplate.testTable.helpers({\n  testdata: function () {\n    topLevelGroupsDep.depend();\n    return resultTree;\n  },\n  thisWithDep: function () {\n    this.dep.depend();\n    return this;\n  }\n});\n\n//// Template - test_group\n\nTemplate.test_group.helpers({\n  thisWithDep: function () {\n    this.dep.depend();\n    return this;\n  }\n});\n\nTemplate.test_group.events({\n  'click .groupname': function (evt) {\n    changeToPath(this.path);\n    // prevent enclosing groups from also triggering on\n    // same groupname.  It would be cleaner to think of\n    // this as each group only listening to its *own*\n    // groupname, but currently it listens to all of them.\n    evt.stopImmediatePropagation();\n  }\n});\n\n\n//// Template - test\n\nTemplate.test.helpers({\n  test_status_display: function() {\n    var status = _testStatus(this);\n    if (status == \"failed\") {\n      return \"FAIL\";\n    } else if (status == \"succeeded\") {\n      return \"PASS\";\n    } else {\n      return \"waiting...\";\n    }\n  },\n\n  test_time_display: function() {\n    var time = _testTime(this);\n    return (typeof time === \"number\") ? time + \" ms\" : \"\";\n  },\n\n  test_class: function() {\n    var events = this.events || [];\n    var classes = [_testStatus(this)];\n\n    if (this.expanded) {\n      classes.push(\"expanded\");\n    } else {\n      classes.push(\"collapsed\");\n    }\n\n    return classes.join(' ');\n  },\n\n  eventsArray: function() {\n    var events = _.filter(this.events, function(e) {\n      return e.type != \"finish\";\n    });\n\n    var partitionBy = function(seq, func) {\n      var result = [];\n      var lastValue = {};\n      _.each(seq, function(x) {\n        var newValue = func(x);\n        if (newValue === lastValue) {\n          result[result.length-1].push(x);\n        } else {\n          lastValue = newValue;\n          result.push([x]);\n        }\n      });\n      return result;\n    };\n\n    var dupLists = partitionBy(\n      _.map(events, function(e) {\n        // XXX XXX We need something better than stringify!\n        // stringify([undefined]) === \"[null]\"\n        e = _.clone(e);\n        delete e.sequence;\n        return {obj: e, str: JSON.stringify(e)};\n      }), function(x) { return x.str; });\n\n    return _.map(dupLists, function(L) {\n      var obj = L[0].obj;\n      return (L.length > 1) ? _.extend({times: L.length}, obj) : obj;\n    });\n  }\n});\n\nTemplate.test.events({\n  'click .testname': function () {\n    this.expanded = ! this.expanded;\n    this.dep.changed();\n  }\n});\n\n\n//// Template - event\n\nTemplate.event.events({\n  'click .debug': function () {\n    // the way we manage groupPath, shortName, cookies, etc, is really\n    // messy. needs to be aggressively refactored.\n    forgetEvents({groupPath: this.cookie.groupPath,\n                  test: this.cookie.shortName});\n    Tinytest._debugTest(this.cookie, reportResults);\n  }\n});\n\n// e.g. doDiff('abc', 'bcd') => [[-1, 'a'], [0, 'bc'], [1, 'd']]\nvar doDiff = function (str1, str2) {\n  var D = new diff_match_patch();\n  var pieces = D.diff_main(str1, str2, false);\n  D.diff_cleanupSemantic(pieces);\n  return pieces;\n};\n\nTemplate.event.helpers({\n  get_details: function() {\n\n    var details = this.details;\n\n    if (! details) {\n      return null;\n    } else {\n\n      var type = details.type;\n      var stack = details.stack;\n\n      details = _.clone(details);\n      delete details.type;\n      delete details.stack;\n\n      var prepare = function(details) {\n        if (type === 'string_equal') {\n          var diff = doDiff(details.actual,\n                            details.expected);\n        }\n\n        return _.compact(_.map(details, function(val, key) {\n\n          // make test._stringEqual results print nicely,\n          // in particular for multiline strings\n          if (type === 'string_equal' &&\n              (key === 'actual' || key === 'expected')) {\n            var html = '<pre class=\"string_equal string_equal_'+key+'\">';\n            _.each(diff, function (piece) {\n              var which = piece[0];\n              var text = piece[1];\n              if (which === 0 ||\n                  which === (key === 'actual' ? -1 : 1)) {\n                var htmlBit = Blaze._escape(text).replace(\n                    /\\n/g, '<br>');\n                if (which !== 0)\n                  htmlBit = '<ins>' + htmlBit + '</ins>';\n                html += htmlBit;\n              }\n            });\n            html += '</pre>';\n            val = new Spacebars.SafeString(html);\n          }\n\n          // You can end up with a an undefined value, e.g. using\n          // isNull without providing a message attribute: isNull(1).\n          // No need to display those.\n          if (!_.isUndefined(val)) {\n            return {\n              key: key,\n              val: val\n            };\n          } else {\n            return undefined;\n          }\n        }));\n      };\n\n      return {\n        type: type,\n        stack: stack,\n        details: prepare(details)\n      };\n    }\n  },\n\n  is_debuggable: function() {\n    return !!this.cookie;\n  }\n});\n"
  },
  {
    "path": "packages/test-in-browser/package.js",
    "content": "Package.describe({\n  summary: \"Run tests interactively in the browser\",\n  version: '1.0.12',\n  documentation: null\n});\n\nPackage.onUse(function (api) {\n  // XXX this should go away, and there should be a clean interface\n  // that tinytest and the driver both implement?\n  api.use('tinytest');\n  api.use('bootstrap@1.0.1');\n  api.use('underscore');\n\n  api.use('session');\n  api.use('reload');\n  api.use('jquery');\n\n  api.use(['webapp', 'blaze', 'templating', 'spacebars',\n           'ddp', 'tracker'], 'client');\n\n  api.addFiles('diff_match_patch_uncompressed.js', 'client');\n\n  api.addFiles([\n    'driver.html',\n    'driver.js',\n    'driver.css'\n  ], \"client\");\n\n  api.use('autoupdate', 'server', {weak: true});\n  api.use('random', 'server');\n  api.addFiles('autoupdate.js', 'server');\n\n  api.export('runTests');\n});\n"
  },
  {
    "path": "packages/test-in-console/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/test-in-console/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/test-in-console/driver.js",
    "content": "// Global flag for phantomjs (or other browser) to eval to see if we're done.\nDONE = false;\n// Failure count for phantomjs exit code\nFAILURES = null;\n\nTEST_STATUS = {\n  DONE: false,\n  FAILURES: null\n};\n\n// xUnit format uses XML output\nvar XML_CHAR_MAP = {\n  '<': '&lt;',\n  '>': '&gt;',\n  '&': '&amp;',\n  '\"': '&quot;',\n  \"'\": '&apos;'\n};\n\n// Escapes a string for insertion into XML\nvar escapeXml = function (s) {\n  return s.replace(/[<>&\"']/g, function (c) {\n    return XML_CHAR_MAP[c];\n  });\n}\n\n// Returns a human name for a test\nvar getName = function (result) {\n  return (result.server ? \"S: \" : \"C: \") +\n    result.groupPath.join(\" - \") + \" - \" + result.test;\n};\n\n// Calls console.log, but returns silently if console.log is not available\nvar log = function (/*arguments*/) {\n  if (typeof console !== 'undefined') {\n    console.log.apply(console, arguments);\n  }\n};\n\nvar MAGIC_PREFIX = '##_meteor_magic##';\n// Write output so that other tools can read it\n// Output is sent to console.log, prefixed with the magic prefix and then the facility\n// By grepping for the prefix, other tools can get the 'special' output\nvar logMagic = function (facility, s) {\n  log(MAGIC_PREFIX + facility + ': ' + s);\n};\n\n// Logs xUnit output, if xunit output is enabled\n// This uses logMagic with a facility of xunit\nvar xunit = function (s) {\n  if (xunitEnabled) {\n    logMagic('xunit', s);\n  }\n};\n\nvar passed = 0;\nvar failed = 0;\nvar expected = 0;\nvar resultSet = {};\nvar toReport = [];\n\nvar hrefPath = document.location.href.split(\"/\");\nvar platform = decodeURIComponent(hrefPath.length && hrefPath[hrefPath.length - 1]);\nif (!platform)\n  platform = \"local\";\n\n// We enable xUnit output when platform is xunit\nvar xunitEnabled = (platform == 'xunit');\n\nvar doReport = Meteor &&\n      Meteor.settings &&\n      Meteor.settings.public &&\n      Meteor.settings.public.runId;\nvar report = function (name, last) {\n  if (doReport) {\n    var data = {\n      run_id: Meteor.settings.public.runId,\n      testPath: resultSet[name].testPath,\n      status: resultSet[name].status,\n      platform: platform,\n      server: resultSet[name].server,\n      fullName: name.substr(3)\n    };\n    if ((data.status === \"FAIL\" || data.status === \"EXPECTED\") &&\n        !_.isEmpty(resultSet[name].events)) {\n      // only send events when bad things happen\n      data.events = resultSet[name].events;\n    }\n    if (last)\n      data.end = new Date();\n    else\n      data.start = new Date();\n    toReport.push(EJSON.toJSONValue(data));\n  }\n};\nvar sendReports = function (callback) {\n  var reports = toReport;\n  if (!callback)\n    callback = function () {};\n  toReport = [];\n  if (doReport)\n    Meteor.call(\"report\", reports, callback);\n  else\n    callback();\n};\n\nrunTests = function () {\n  setTimeout(sendReports, 500);\n  setInterval(sendReports, 2000);\n\n  Tinytest._runTestsEverywhere(\n    function (results) {\n      var name = getName(results);\n      if (!_.has(resultSet, name)) {\n        var testPath = EJSON.clone(results.groupPath);\n        testPath.push(results.test);\n        resultSet[name] = {\n          name: name,\n          status: \"PENDING\",\n          events: [],\n          server: !!results.server,\n          testPath: testPath,\n          test: results.test\n        };\n        report(name, false);\n      }\n      // Loop through events, and record status for each test\n      // Also log result if test has finished\n      _.each(results.events, function (event) {\n        resultSet[name].events.push(event);\n        switch (event.type) {\n        case \"ok\":\n          break;\n        case \"expected_fail\":\n          if (resultSet[name].status !== \"FAIL\")\n            resultSet[name].status = \"EXPECTED\";\n          break;\n        case \"exception\":\n          log(name, \":\", \"!!!!!!!!! FAIL !!!!!!!!!!!\");\n          if (event.details && event.details.stack)\n            log(event.details.stack);\n          else\n            log(\"Test failed with exception\");\n          failed++;\n          break;\n        case \"finish\":\n          switch (resultSet[name].status) {\n          case \"OK\":\n            break;\n          case \"PENDING\":\n            resultSet[name].status = \"OK\";\n            report(name, true);\n            log(name, \":\", \"OK\");\n            passed++;\n            break;\n          case \"EXPECTED\":\n            report(name, true);\n            log(name, \":\", \"EXPECTED FAILURE\");\n            expected++;\n            break;\n          case \"FAIL\":\n            failed++;\n            report(name, true);\n            log(name, \":\", \"!!!!!!!!! FAIL !!!!!!!!!!!\");\n            log(JSON.stringify(resultSet[name].info));\n            break;\n          default:\n            log(name, \": unknown state for the test to be in\");\n          }\n          break;\n        default:\n          resultSet[name].status = \"FAIL\";\n          resultSet[name].info = results;\n          break;\n        }\n      });\n    },\n\n    // After test completion, log a quick summary\n    function () {\n      if (failed > 0) {\n        log(\"~~~~~~~ THERE ARE FAILURES ~~~~~~~\");\n      }\n      log(\"passed/expected/failed/total\", passed, \"/\", expected, \"/\", failed, \"/\", _.size(resultSet));\n      sendReports(function () {\n        if (doReport) {\n          log(\"Waiting 3s for any last reports to get sent out\");\n          setTimeout(function () {\n            TEST_STATUS.FAILURES = FAILURES = failed;\n            TEST_STATUS.DONE = DONE = true;\n          }, 3000);\n        } else {\n          TEST_STATUS.FAILURES = FAILURES = failed;\n          TEST_STATUS.DONE = DONE = true;\n        }\n      });\n\n      // Also log xUnit output\n      xunit('<testsuite errors=\"\" failures=\"\" name=\"meteor\" skips=\"\" tests=\"\" time=\"\">');\n      _.each(resultSet, function (result, name) {\n        var classname = result.testPath.join('.').replace(/ /g, '-') + (result.server ? \"-server\" : \"-client\");\n        var name = result.test.replace(/ /g, '-') + (result.server ? \"-server\" : \"-client\");\n        var time = \"\";\n        var error = \"\";\n        _.each(result.events, function (event) {\n          switch (event.type) {\n            case \"finish\":\n              var timeMs = event.timeMs;\n              if (timeMs !== undefined) {\n                time = (timeMs / 1000) + \"\";\n              }\n              break;\n            case \"exception\":\n              var details = event.details || {};\n              error = (details.message || '?') + \" filename=\" + (details.filename || '?') + \" line=\" + (details.line || '?');\n              break;\n          }\n        });\n        switch (result.status) {\n          case \"FAIL\":\n            error = error || '?';\n            break;\n          case \"EXPECTED\":\n            error = null;\n            break;\n        }\n\n        xunit('<testcase classname=\"' + escapeXml(classname) + '\" name=\"' + escapeXml(name) + '\" time=\"' + time + '\">');\n        if (error) {\n          xunit('  <failure message=\"test failure\">' + escapeXml(error) + '</failure>');\n        }\n        xunit('</testcase>');\n      });\n      xunit('</testsuite>');\n      logMagic('state', 'done');\n    },\n    [\"tinytest\"]);\n}\n"
  },
  {
    "path": "packages/test-in-console/package.js",
    "content": "Package.describe({\n  summary: \"Run tests noninteractively, with results going to the console.\",\n  version: '1.0.12'\n});\n\nPackage.onUse(function (api) {\n\n  api.use(['tinytest', 'underscore', 'random', 'ejson', 'check']);\n  api.use('http', 'server');\n\n  api.export('TEST_STATUS', 'client');\n\n  api.addFiles(['driver.js'], \"client\");\n  api.addFiles(['reporter.js'], \"server\");\n\n  // This is to be run by phantomjs, not as part of normal package code.\n  api.addAssets('runner.js', 'server');\n\n  api.export('runTests');\n});\n"
  },
  {
    "path": "packages/test-in-console/reporter.js",
    "content": "// A hacky way to extract the phantom runner script from the package.\nif (process.env.WRITE_RUNNER_JS) {\n  Npm.require('fs').writeFileSync(\n    process.env.WRITE_RUNNER_JS, new Buffer(Assets.getBinary('runner.js')));\n}\n\nvar url =  null;\nif (Meteor.settings &&\n    Meteor.settings.public &&\n    Meteor.settings.public.runId &&\n    Meteor.settings.public.reportTo) {\n  url = Meteor.settings.public.reportTo +\n      \"/report/\" +\n      Meteor.settings.public.runId;\n}\n\nMeteor.methods({\n  report: function (reports) {\n    // XXX Could do a more precise validation here; reports are complex!\n    check(reports, [Object]);\n    if (url) {\n      HTTP.post(url, {\n        data: reports\n      });\n    }\n    return null;\n  }\n});\n\n// provide some notification we're started. This is to allow use\n// in automated scripts with `meteor run --once` which does not\n// print when the proxy is listening.\nMeteor.startup(function () {\n  Meteor._debug(\"test-in-console listening\");\n});\n"
  },
  {
    "path": "packages/test-in-console/run.sh",
    "content": "#!/usr/bin/env bash\n\ncd \"`dirname \"$0\"`\"\ncd ../..\nexport METEOR_HOME=`pwd`\n\nexport PATH=$METEOR_HOME:$PATH\n# synchronously get the dev bundle and NPM modules if they're not there.\n./meteor --get-ready || exit 1\n\nexport URL='http://localhost:4096/'\n\nexec 3< <(meteor test-packages --driver-package test-in-console -p 4096 --exclude $TEST_PACKAGES_EXCLUDE)\nEXEC_PID=$!\n\nsed '/test-in-console listening$/q' <&3\nphantomjs $METEOR_HOME/packages/test-in-console/runner.js\nSTATUS=$?\n\npkill -TERM -P $EXEC_PID\nexit $STATUS\n"
  },
  {
    "path": "packages/test-in-console/runner.js",
    "content": "var page = require('webpage').create();\nvar system = require('system');\nvar platform = system.args[1] || \"local\";\nconsole.log(\"Running Meteor tests in PhantomJS... \" + system.env.URL);\npage.onConsoleMessage = function (message) {\n  console.log(message);\n};\npage.open(system.env.URL + platform);\nsetInterval(function () {\n  var done = page.evaluate(function () {\n    if (typeof TEST_STATUS !== 'undefined')\n      return TEST_STATUS.DONE;\n    return typeof DONE !== 'undefined' && DONE;\n  });\n  if (done) {\n    var failures = page.evaluate(function () {\n      if (typeof TEST_STATUS !== 'undefined')\n        return TEST_STATUS.FAILURES;\n      if (typeof FAILURES === 'undefined') {\n        return 1;\n      }\n      return 0;\n    });\n    phantom.exit(failures ? 1 : 0);\n  }\n}, 500);\n"
  },
  {
    "path": "packages/test-server-tests-in-console-once/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/test-server-tests-in-console-once/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/test-server-tests-in-console-once/package.js",
    "content": "Package.describe({\n  summary: \"Run server tests noninteractively, with results going to the console.\",\n  version: '1.0.10'\n});\n\nPackage.onUse(function (api) {\n  api.use(['tinytest', 'underscore', 'ejson'], 'server');\n\n  api.addFiles(['server.js'], \"server\");\n});\n"
  },
  {
    "path": "packages/test-server-tests-in-console-once/server.js",
    "content": "var passed = 0;\nvar failed = 0;\nvar expected = 0;\nvar resultSet = {};\n\nvar getName = function (result) {\n  return result.groupPath.join(\" - \") + \" - \" + result.test;\n};\n\nMeteor.startup(function () {\n  console.log(\"running server-side tests\");\n  Tinytest._runTests(function (results) {\n    var name = getName(results);\n    if (!_.has(resultSet, name)) {\n      var testPath = EJSON.clone(results.groupPath);\n      testPath.push(results.test);\n      resultSet[name] = {\n        name: name,\n        status: \"PENDING\",\n        events: [],\n        testPath: testPath\n      };\n    }\n    _.each(results.events, function (event) {\n      resultSet[name].events.push(event);\n      switch (event.type) {\n      case \"ok\":\n        break;\n      case \"expected_fail\":\n        if (resultSet[name].status !== \"FAIL\")\n          resultSet[name].status = \"EXPECTED\";\n        break;\n      case \"exception\":\n        console.log(name, \":\", \"!!!!!!!!! FAIL !!!!!!!!!!!\");\n        if (event.details && event.details.stack)\n          console.log(event.details.stack);\n        else\n          console.log(\"Test failed with exception\");\n        failed++;\n        break;\n      case \"finish\":\n        switch (resultSet[name].status) {\n        case \"OK\":\n          break;\n        case \"PENDING\":\n          resultSet[name].status = \"OK\";\n          console.log(name, \":\", \"OK\");\n          passed++;\n          break;\n        case \"EXPECTED\":\n          console.log(name, \":\", \"EXPECTED FAILURE\");\n          expected++;\n          break;\n        case \"FAIL\":\n          failed++;\n          console.log(name, \":\", \"!!!!!!!!! FAIL !!!!!!!!!!!\");\n          console.log(JSON.stringify(resultSet[name].info));\n          break;\n        default:\n          console.log(name, \": unknown state for the test to be in\");\n        }\n        break;\n      default:\n        resultSet[name].status = \"FAIL\";\n        resultSet[name].info = results;\n        break;\n      }\n    });\n  }, function () {\n    console.log(\"passed/expected/failed/total\",\n                passed, \"/\", expected, \"/\", failed, \"/\", _.size(resultSet));\n    if (failed > 0) {\n      console.log(\"TESTS FAILED\");\n    } else {\n      console.log(\"ALL TESTS PASSED\");\n    }\n    process.exit(failed ? 1 : 0);\n  });\n});\n"
  },
  {
    "path": "packages/tinytest/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/tinytest/README.md",
    "content": "# TinyTest\n\nAfter reading this, you'll know:\n\n1. What Tinytest is used for.\n1. How to include tests in your package.\n1. How to structure your test file(s).\n1. When to use synchronous or asynchronous tests.\n1. How to run your tests.\n1. What assertions and utility methods are available to you.\n\n## What is Tinytest?\n\nTinytest is the official Meteor package test runner.\n\nIt's used to test *local* packages. You cannot test non-local packages (for example packages you have included using `meteor add some:package-name`) unless you clone their repos and make them available locally. The assumption is, of course, that you are testing packages under development.\n\nTinytest is specifically designed for *unit testing*. From [wikipedia](https://en.wikipedia.org/wiki/Unit_testing):\n\n> ... Intuitively, one can view a unit as the smallest testable part of an application. In procedural programming, a unit could be an entire module, but it is more commonly an individual function or procedure. In object-oriented programming, a unit is often an entire interface, such as a class, but could be an individual method.\n\n> ... Ideally, each test case is independent from the others. Substitutes such as method stubs, mock objects, fakes, and test harnesses can be used to assist testing a module in isolation.\n\nThe object of a unit test is to prove functionality you have written. It is not to prove third-party or other package or library code which may form a part of your codebase. This may require that you head up your tests with *stubs, mocks/spies* or *fakes* which satisfy the demands of your code, but are non-functional (or have limited functionality). Alternatively, instead of placing the stubs in your test file, you could put them into a separate `stubs.js` file, which you `api.addFiles`, or even create and add a stubs package which you then `api.use`.\n\nFrom [martinfowler.com](http://www.martinfowler.com/articles/mocksArentStubs.html):\n\n> Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).\n\n> Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.\n\n> Mocks [are] objects pre-programmed with expectations which form a specification of the calls they are expected to receive.\n\nFor a comprehensive way of including spies, stubs and other fun stuff, check out [practicalmeteor:munit](https://atmospherejs.com/practicalmeteor/munit) and [smithy:describe](https://atmospherejs.com/smithy/describe), both of which wrap a host of useful functionality around Tinytest, including the more widely used `describe ... it ... expect` syntax. This README covers standard Tinytest, so you should refer to the documentation for those if you prefer their syntax and functionality.\n\n## Adding Tinytest to Your Package\n\nTinytest is included through configuration in the `package.js` file using `Package.onTest()`.\n\n```javascript\n// Define test section\nPackage.onTest(function(api) {\n  // We will need the following packages to run our tests.\n  // Note that we also need to include the package to be tested (myname:mypackage).\n  api.use(['tinytest', 'underscore', 'ecmascript', 'myname:mypackage']);\n  // In v1.2 test-packages no longer include any packages globally.\n  // You may need to make some exports global for your tests to run, for example:\n  api.imply('underscore');\n  // This file contains the tests we want to run (these will run on the client and the server)\n  api.addFiles('tests.js');\n  // You can add as many test files as you want and choose where they are to run:\n  api.addFiles('server-tests.js', 'server');\n  // and these only run on the client:\n  api.addFiles('client-tests.js', 'client');\n});\n```\n\n## Structuring the Test File\n\nThe test file is normally written in Javascript/ES5 (but may be anything if the appropriate transpiler is included with `api.use('some-transpiler');` within `Package.onTest`). Examples in this README assume ES2015, for which you will have to include an `api.use('ecmascript');` line in your `Package.onTest`.\n\n> *Note that currently the `package.js` file itself is processed as Javascript/ES5. This cannot be changed.*\n\nA \"test\" contains the code you want to test, plus zero or more *assertions* wrapped within a `Tinytest.add` or `Tinytest.addAsync` callback. The `name` of the test is specified in the `add` or `addAsync` call. An assertion is a call to a method used to verify an actual result (or some property of an actual result) vs an expected result. For example, \"is the result === 1?\", or \"is the result a JavaScript `Number`?\".\n\nIf a test has no assertions it is assumed to pass unless an exception is caught. However, it is more usual to explicitly specify assertions.\n\nIn any single test all assertions must pass for the test as a whole to pass.\n\nThe `name` of the test may also be used to generate a hierarchical (grouped) result page. Hierarchical levels are split using \" - \" as a separator in the name. The name of the package should be at the head of the `name`:\n\n    'mypackage - functional tests - test 1'\n    'mypackage - functional tests - test 2'\n    'mypackage - performance tests - test 1'\n    'mypackage - performance tests - test 2'\n\nWould be good `name`s to use for reporting test results in a hierarchy.\n\nMultiple test files may be included in `package.js`. They will be processed in the order declared. However, test results are presented in the order in which they appear in their groupings. The pass/fail status of tests is updated in order, including waiting for *asynchronous* tests to complete.\n\n## Synchronous and Asynchronous Tests\n\nTests may be *synchronous* or *asynchronous*.\n\nA synchronous test is one in which the flow of code *does not* need to wait for the result of an external action to be made available through an on-completion callback.\n\nConversely, an asynchronous test is one in which the flow of code *does* need to wait for the result of an external action to be made available through an on-completion callback.\n\nSynchronous tests are more common, but asynchronous tests are useful occasionally. With the introduction of Meteor Promises (promises running in fibers), we can now successfully write synchronous tests containing asynchronous code. However, examples of this usage are outside the scope of this section of the README.\n\n### Synchronous Tests\n\n```javascript\nTinytest.add(name, function(test) {\n  // test body\n});\n```\n\nES6/2015 (recommended):\n\n```javascript\nTinytest.add(name, (test) => {\n  // test body\n});\n```\n\n### Asynchronous Tests\n\n```javascript\nTinytest.addAsync(name, function(test, onComplete) {\n  someAsyncRequest(function(error, result) {\n    // test body\n    onComplete(); // invoke when async function completes.\n  }\n});\n```\n\nES6/2015 (recommended):\n\n```javascript\nTinytest.addAsync(name, (test, onComplete) => {\n  someAsyncRequest((error, result) => {\n    // test body\n    onComplete(); // invoke when async function completes.\n  }\n});\n```\n\n## Executing the Tests\n\nTests are executed by running the (development) application with the `test-packages` command. By default, all packages are tested, but specific packages can be tested by specifying them by name.\n\n`meteor test-packages` runs tests on all (local) packages in the app.\n\n`meteor test-packages her:package his:package` runs tests only on `her:package` and `his:package`.\n\nThe results are presented on the browser (port 3000) as usual. When run as shown, the file watcher runs, so code may be edited and the tests will be re-run automatically. If this is undesirable, you may add the `--run-once` switch.\n\n## Assertions\n\nThe `test` object in the above callbacks is used to add assertions to the test.\n\n```javascript\nTinytest.add('mypackage - basic tests', (test) => {\n\n  // Get the result from our function under test.\n  const result = myFunction(1);\n\n  // Do the test ... calling myFunction with 1 should return 2.\n  test.equal(result, 2);\n});\n```\n\nTests may include multiple assertions. The total number of successes and failures for each test are reported.\n\n### Assertions with optional fail messages\n\nAn optional `message` may be added to the assertions which will change a failure report from `fail - <failure-test>` to `fail - <failure-test> - message <optional message>`\n\n#### equal\n\n`test.equal(actual, expected[, message[, not]]);`\n\n`not` is a boolean (`true`/`false`) parameter which may be used to switch the sense (`equal` becomes `notEqual`). Used internally by `notEqual`. **Don't use it in your tests - it just makes your code harder to grok.**\n\nCompares by type and value, so 2 is not equal to \"2\", for example. Is a better choice for checking something is strictly `true` or `false` than `test.isTrue` or `test.isFalse` (see below).\n\n#### notEqual\n\n`test.notEqual(actual, expected[, message]);`\n\nInternally, calls `equal` with the `not` flag set to `true`.\n\n#### matches\n\n`test.matches(actual, regexp[, message]);`\n\nChecks `regexp.test(actual)`\n\n#### notMatches\n\n`test.notMatches(actual, regexp[, message]);`\n\nChecks `!regexp.test(actual)`\n\n#### isTrue\n\n`test.isTrue(actual[, message]);`\n\nChecks that `actual` is truthy (does not check type is `Boolean`).\n\n#### isFalse\n\n`test.isFalse(actual[, message]);`\n\nChecks that `actual` is falsey (does not check type is `Boolean`).\n\n#### isNull\n\n`test.isNull(actual[, message]);`\n\nChecks `actual === null`\n\n#### isNotNull\n\n`test.isNotNull(actual[, message]);`\n\nChecks `!(actual === null)`\n\n#### isUndefined\n\n`test.isUndefined(actual[, message]);`\n\nChecks `actual === undefined`\n\n#### isNotUndefined\n\n`test.isNotUndefined(actual[, message]);`\n\nChecks `!(actual === undefined)`\n\n#### isNaN\n\n`test.isNaN(actual[, message]);`\n\nChecks `isNaN(actual)`\n\n#### isNotNaN\n\n`test.isNotNaN(actual[, message]);`\n\nChecks `!(isNaN(actual))`\n\n#### length\n\n`test.length(obj, expected_length[, message]);`\n\nChecks `obj.length === expected_length`\n\n#### instanceOf\n\n`test.instanceOf(obj, klass[, message]);`\n\nChecks `obj instanceof klass`\n\n#### notInstanceOf\n\n`test.notInstanceOf(obj, klass[, message]);`\n\nChecks `!(obj instanceof klass)`\n\n#### include\n\n`test.include(haystack, needle[, message[, not]]);`\n\n`haystack` may be an `array`, `object` or `string`. Correspondingly, `needle` may be an `element` (simple elements only), `key` (method or property name) or `substring`.\n\n`not` is a boolean (`true`/`false`) parameter which may be used to switch the sense (`include` becomes `notInclude`). Used internally by `notInclude`. **Don't use it in your tests - it just makes your code harder to grok.**\n\n#### notInclude\n\n`test.notInclude(haystack, needle[,message]);`\n\nInternally, calls `include` with the `not` flag set to `true`.\n\n#### _stringEqual\n\n`test._stringEqual: function (actual, expected[, message]);`\n\nEXPERIMENTAL way to compare two strings that results in a nicer display in the test runner, e.g. for multiline strings.\n\n### Assertions without optional fail messages\n\n`test.throws(func, expected);`\n\n`expected` can be:\n\n- `undefined`: accept any exception.\n- `string`: pass if the string is a substring of the exception message.\n- `regexp`: pass if the exception message passes the regexp.\n- `function`: call the function as a predicate with the exception.\n\nNote: Node's `assert.throws` also accepts a constructor to test whether the error is of the expected class.  But since JavaScript can't distinguish between constructors and plain functions and Node's `assert.throws` also accepts a predicate function, if the error fails the `instanceof` test with the constructor then the constructor is then treated as a predicate and called (!)\n\nThe upshot is, if you want to test whether an error is of a particular class, use a predicate function.\n\n## Utility Methods\n\n#### runId\n\n`test.runId();`\n\nReturns a unique string id for this test (for example 'ZmXxMPyoWGFy5wEiB').\n\n#### exception\n\n`test.exception(exception);`\n\n**Should only be used with asynchronous tests**\n\nCall this to fail the test with an exception that occurs inside asynchronous callbacks in tests. If you call this function, you should make sure that:\n\n- the test doesn't call its callback (onComplete function).\n- the test function doesn't directly raise an exception.\n\n#### expect_fail\n\n`test.expect_fail();`\n\nMay be used to change a fail to a qualified pass. The test is counted as a pass, but clicking on it reveals that the underlying test failed:\n\n    - expected_fail — assert_equal - expected xxx - actual yyy - not\n\n\n"
  },
  {
    "path": "packages/tinytest/model.js",
    "content": "Meteor._ServerTestResultsSubscription = 'tinytest_results_subscription';\nMeteor._ServerTestResultsCollection = 'tinytest_results_collection';\n"
  },
  {
    "path": "packages/tinytest/package.js",
    "content": "Package.describe({\n  summary: \"Tiny testing framework\",\n  version: '1.0.11'\n});\n\nPackage.onUse(function (api) {\n  api.use([\n    'ejson',\n    'underscore',\n    'random',\n    'ddp',\n    'mongo',\n    'check'\n  ]);\n\n  api.addFiles('tinytest.js');\n  api.addFiles('model.js');\n  api.addFiles('tinytest_client.js', 'client');\n  api.addFiles('tinytest_server.js', 'server');\n\n  api.export('Tinytest');\n});\n"
  },
  {
    "path": "packages/tinytest/tinytest.js",
    "content": "var Future;\nif (Meteor.isServer)\n  Future = Npm.require('fibers/future');\n\n/******************************************************************************/\n/* TestCaseResults                                                            */\n/******************************************************************************/\n\nTestCaseResults = function (test_case, onEvent, onException, stop_at_offset) {\n  var self = this;\n  self.test_case = test_case;\n  self.onEvent = onEvent;\n  self.expecting_failure = false;\n  self.current_fail_count = 0;\n  self.stop_at_offset = stop_at_offset;\n  self.onException = onException;\n  self.id = Random.id();\n  self.extraDetails = {};\n};\n\n_.extend(TestCaseResults.prototype, {\n  ok: function (doc) {\n    var self = this;\n    var ok = {type: \"ok\"};\n    if (doc)\n      ok.details = doc;\n    if (self.expecting_failure) {\n      ok.details = ok.details || {};\n      ok.details[\"was_expecting_failure\"] = true;\n      self.expecting_failure = false;\n    }\n    self.onEvent(ok);\n  },\n\n  expect_fail: function () {\n    var self = this;\n    self.expecting_failure = true;\n  },\n\n  fail: function (doc) {\n    var self = this;\n\n    if (typeof doc === \"string\") {\n      // Some very old code still tries to call fail() with a\n      // string. Don't do this!\n      doc = { type: \"fail\", message: doc };\n    }\n\n    doc = _.extend({}, doc, self.extraDetails);\n\n    if (self.stop_at_offset === 0) {\n      if (Meteor.isClient) {\n        // Only supported on the browser for now..\n        var now = (+new Date);\n        debugger;\n        if ((+new Date) - now < 100)\n          alert(\"To use this feature, first enable your browser's debugger.\");\n      }\n      self.stop_at_offset = null;\n    }\n    if (self.stop_at_offset)\n      self.stop_at_offset--;\n\n    // Get filename and line number of failure if we're using v8 (Chrome or\n    // Node).\n    if (Error.captureStackTrace) {\n      var savedPrepareStackTrace = Error.prepareStackTrace;\n      Error.prepareStackTrace = function(_, stack){ return stack; };\n      var err = new Error;\n      Error.captureStackTrace(err);\n      var stack = err.stack;\n      Error.prepareStackTrace = savedPrepareStackTrace;\n      for (var i = stack.length - 1; i >= 0; --i) {\n        var frame = stack[i];\n        // Heuristic: use the OUTERMOST line which is in a :tests.js\n        // file (this is less likely to be a test helper function).\n        if (frame.getFileName().match(/:tests\\.js/)) {\n          doc.filename = frame.getFileName();\n          doc.line = frame.getLineNumber();\n          break;\n        }\n      }\n    }\n\n    self.onEvent({\n        type: (self.expecting_failure ? \"expected_fail\" : \"fail\"),\n        details: doc,\n        cookie: {name: self.test_case.name, offset: self.current_fail_count,\n                 groupPath: self.test_case.groupPath,\n                 shortName: self.test_case.shortName}\n    });\n    self.expecting_failure = false;\n    self.current_fail_count++;\n  },\n\n  // Call this to fail the test with an exception. Use this to record\n  // exceptions that occur inside asynchronous callbacks in tests.\n  //\n  // It should only be used with asynchronous tests, and if you call\n  // this function, you should make sure that (1) the test doesn't\n  // call its callback (onComplete function); (2) the test function\n  // doesn't directly raise an exception.\n  exception: function (exception) {\n    this.onException(exception);\n  },\n\n  // returns a unique ID for this test run, for convenience use by\n  // your tests\n  runId: function () {\n    return this.id;\n  },\n\n  // === Following patterned after http://vowsjs.org/#reference ===\n\n  // XXX eliminate 'message' and 'not' arguments\n  equal: function (actual, expected, message, not) {\n\n    if ((! not) && (typeof actual === 'string') &&\n        (typeof expected === 'string')) {\n      this._stringEqual(actual, expected, message);\n      return;\n    }\n\n    /* If expected is a DOM node, do a literal '===' comparison with\n     * actual. Otherwise do a deep comparison, as implemented by _.isEqual.\n     */\n\n    var matched;\n    // XXX remove cruft specific to liverange\n    if (typeof expected === \"object\" && expected && expected.nodeType) {\n      matched = expected === actual;\n      expected = \"[Node]\";\n      actual = \"[Unknown]\";\n    } else if (typeof Uint8Array !== 'undefined' && expected instanceof Uint8Array) {\n      // I have no idea why but _.isEqual on Chrome horks completely on Uint8Arrays.\n      // and the symptom is the chrome renderer taking up an entire CPU and freezing\n      // your web page, but not pausing anywhere in _.isEqual.  I don't understand it\n      // but we fall back to a manual comparison\n      if (!(actual instanceof Uint8Array))\n        this.fail({type: \"assert_equal\", message: \"found object is not a typed array\",\n                   expected: \"A typed array\", actual: actual.constructor.toString()});\n      if (expected.length !== actual.length)\n        this.fail({type: \"assert_equal\", message: \"lengths of typed arrays do not match\",\n                   expected: expected.length, actual: actual.length});\n      for (var i = 0; i < expected.length; i++) {\n        this.equal(actual[i], expected[i]);\n      }\n    } else {\n      matched = EJSON.equals(expected, actual);\n    }\n\n    if (matched === !!not) {\n      this.fail({type: \"assert_equal\", message: message,\n                 expected: JSON.stringify(expected), actual: JSON.stringify(actual), not: !!not});\n    } else\n      this.ok();\n  },\n\n  notEqual: function (actual, expected, message) {\n    this.equal(actual, expected, message, true);\n  },\n\n  instanceOf: function (obj, klass, message) {\n    if (obj instanceof klass)\n      this.ok();\n    else\n      this.fail({type: \"instanceOf\", message: message, not: false}); // XXX what other data?\n  },\n\n  notInstanceOf: function (obj, klass, message) {\n    if (obj instanceof klass)\n      this.fail({type: \"instanceOf\", message: message, not: true}); // XXX what other data?\n    else\n      this.ok();\n  },\n\n  matches: function (actual, regexp, message) {\n    if (regexp.test(actual))\n      this.ok();\n    else\n      this.fail({type: \"matches\", message: message,\n                 actual: actual, regexp: regexp.toString(), not: false});\n  },\n\n  notMatches: function (actual, regexp, message) {\n    if (regexp.test(actual))\n      this.fail({type: \"matches\", message: message,\n                 actual: actual, regexp: regexp.toString(), not: true});\n    else\n      this.ok();\n  },\n\n  // expected can be:\n  //  undefined: accept any exception.\n  //  string: pass if the string is a substring of the exception message.\n  //  regexp: pass if the exception message passes the regexp.\n  //  function: call the function as a predicate with the exception.\n  //\n  // Note: Node's assert.throws also accepts a constructor to test\n  // whether the error is of the expected class.  But since\n  // JavaScript can't distinguish between constructors and plain\n  // functions and Node's assert.throws also accepts a predicate\n  // function, if the error fails the instanceof test with the\n  // constructor then the constructor is then treated as a predicate\n  // and called (!)\n  //\n  // The upshot is, if you want to test whether an error is of a\n  // particular class, use a predicate function.\n  //\n  throws: function (f, expected) {\n    var actual, predicate;\n\n    if (expected === undefined)\n      predicate = function (actual) {\n        return true;\n      };\n    else if (_.isString(expected))\n      predicate = function (actual) {\n        return _.isString(actual.message) &&\n               actual.message.indexOf(expected) !== -1;\n      };\n    else if (expected instanceof RegExp)\n      predicate = function (actual) {\n        return expected.test(actual.message);\n      };\n    else if (typeof expected === 'function')\n      predicate = expected;\n    else\n      throw new Error('expected should be a string, regexp, or predicate function');\n\n    try {\n      f();\n    } catch (exception) {\n      actual = exception;\n    }\n\n    if (actual && predicate(actual))\n      this.ok();\n    else\n      this.fail({\n        type: \"throws\",\n        message: actual ?\n          \"wrong error thrown: \" + actual.message :\n          \"did not throw an error as expected\"\n      });\n  },\n\n  isTrue: function (v, msg) {\n    if (v)\n      this.ok();\n    else\n      this.fail({type: \"true\", message: msg, not: false});\n  },\n\n  isFalse: function (v, msg) {\n    if (v)\n      this.fail({type: \"true\", message: msg, not: true});\n    else\n      this.ok();\n  },\n\n  isNull: function (v, msg) {\n    if (v === null)\n      this.ok();\n    else\n      this.fail({type: \"null\", message: msg, not: false});\n  },\n\n  isNotNull: function (v, msg) {\n    if (v === null)\n      this.fail({type: \"null\", message: msg, not: true});\n    else\n      this.ok();\n  },\n\n  isUndefined: function (v, msg) {\n    if (v === undefined)\n      this.ok();\n    else\n      this.fail({type: \"undefined\", message: msg, not: false});\n  },\n\n  isNotUndefined: function (v, msg) {\n    if (v === undefined)\n      this.fail({type: \"undefined\", message: msg, not: true});\n    else\n      this.ok();\n  },\n\n  isNaN: function (v, msg) {\n    if (isNaN(v))\n      this.ok();\n    else\n      this.fail({type: \"NaN\", message: msg, not: false});\n  },\n\n  isNotNaN: function (v, msg) {\n    if (isNaN(v))\n      this.fail({type: \"NaN\", message: msg, not: true});\n    else\n      this.ok();\n  },\n\n  include: function (s, v, message, not) {\n    var pass = false;\n    if (s instanceof Array)\n      pass = _.any(s, function(it) {return _.isEqual(v, it);});\n    else if (typeof s === \"object\")\n      pass = v in s;\n    else if (typeof s === \"string\")\n      if (s.indexOf(v) > -1) {\n        pass = true;\n      }\n    else\n      /* fail -- not something that contains other things */;\n    if (pass === ! not)\n      this.ok();\n    else {\n      this.fail({type: \"include\", message: message,\n                 sequence: s, should_contain_value: v, not: !!not});\n    }\n  },\n\n  notInclude: function (s, v, message) {\n    this.include(s, v, message, true);\n  },\n\n  // XXX should change to lengthOf to match vowsjs\n  length: function (obj, expected_length, msg) {\n    if (obj.length === expected_length)\n      this.ok();\n    else\n      this.fail({type: \"length\", expected: expected_length,\n                 actual: obj.length, message: msg});\n  },\n\n  // EXPERIMENTAL way to compare two strings that results in\n  // a nicer display in the test runner, e.g. for multiline\n  // strings\n  _stringEqual: function (actual, expected, message) {\n    if (actual !== expected) {\n      this.fail({type: \"string_equal\",\n                 message: message,\n                 expected: expected,\n                 actual: actual});\n    } else {\n      this.ok();\n    }\n  }\n\n\n});\n\n/******************************************************************************/\n/* TestCase                                                                   */\n/******************************************************************************/\n\nTestCase = function (name, func) {\n  var self = this;\n  self.name = name;\n  self.func = func;\n\n  var nameParts = _.map(name.split(\" - \"), function(s) {\n    return s.replace(/^\\s*|\\s*$/g, \"\"); // trim\n  });\n  self.shortName = nameParts.pop();\n  nameParts.unshift(\"tinytest\");\n  self.groupPath = nameParts;\n};\n\n_.extend(TestCase.prototype, {\n  // Run the test asynchronously, delivering results via onEvent;\n  // then call onComplete() on success, or else onException(e) if the\n  // test raised (or voluntarily reported) an exception.\n  run: function (onEvent, onComplete, onException, stop_at_offset) {\n    var self = this;\n\n    var completed = false;\n    var markComplete = function () {\n      if (completed) {\n        Meteor._debug(\"*** Test error -- test '\" + self.name +\n                      \"' returned multiple times.\");\n        return false;\n      }\n      completed = true;\n      return true;\n    };\n\n    var wrappedOnEvent = function (e) {\n      // If this trace prints, it means you ran some test.* function after the\n      // test finished! Another symptom will be that the test will display as\n      // \"waiting\" even when it counts as passed or failed.\n      if (completed)\n        console.trace(\"event after complete!\");\n      return onEvent(e);\n    };\n\n    var results = new TestCaseResults(self, wrappedOnEvent,\n                                      function (e) {\n                                        if (markComplete())\n                                          onException(e);\n                                      }, stop_at_offset);\n\n    Meteor.defer(function () {\n      try {\n        self.func(results, function () {\n          if (markComplete())\n            onComplete();\n        });\n      } catch (e) {\n        if (markComplete())\n          onException(e);\n      }\n    });\n  }\n});\n\n/******************************************************************************/\n/* TestManager                                                                */\n/******************************************************************************/\n\nTestManager = function () {\n  var self = this;\n  self.tests = {};\n  self.ordered_tests = [];\n  self.testQueue = Meteor.isServer && new Meteor._SynchronousQueue();\n};\n\nif (Meteor.isServer && process.env.TINYTEST_FILTER) {\n  __meteor_runtime_config__.tinytestFilter = process.env.TINYTEST_FILTER;\n}\n\n_.extend(TestManager.prototype, {\n  addCase: function (test) {\n    var self = this;\n    if (test.name in self.tests)\n      throw new Error(\n        \"Every test needs a unique name, but there are two tests named '\" +\n          test.name + \"'\");\n    if (__meteor_runtime_config__.tinytestFilter &&\n        test.name.indexOf(__meteor_runtime_config__.tinytestFilter) === -1) {\n      return;\n    }\n    self.tests[test.name] = test;\n    self.ordered_tests.push(test);\n  },\n\n  createRun: function (onReport, pathPrefix) {\n    var self = this;\n    return new TestRun(self, onReport, pathPrefix);\n  }\n});\n\n// singleton\nTestManager = new TestManager;\n\n/******************************************************************************/\n/* TestRun                                                                    */\n/******************************************************************************/\n\nTestRun = function (manager, onReport, pathPrefix) {\n  var self = this;\n  self.manager = manager;\n  self.onReport = onReport;\n  self.next_sequence_number = 0;\n  self._pathPrefix = pathPrefix || [];\n  _.each(self.manager.ordered_tests, function (test) {\n    if (self._prefixMatch(test.groupPath))\n      self._report(test);\n  });\n};\n\n_.extend(TestRun.prototype, {\n\n  _prefixMatch: function (testPath) {\n    var self = this;\n    for (var i = 0; i < self._pathPrefix.length; i++) {\n      if (!testPath[i] || self._pathPrefix[i] !== testPath[i]) {\n        return false;\n      }\n    }\n    return true;\n  },\n\n  _runTest: function (test, onComplete, stop_at_offset) {\n    var self = this;\n\n    var startTime = (+new Date);\n\n    test.run(function (event) {\n      /* onEvent */\n      // Ignore result callbacks if the test has already been reported\n      // as timed out.\n      if (test.timedOut)\n        return;\n      self._report(test, event);\n    }, function () {\n      /* onComplete */\n      if (test.timedOut)\n        return;\n      var totalTime = (+new Date) - startTime;\n      self._report(test, {type: \"finish\", timeMs: totalTime});\n      onComplete();\n    }, function (exception) {\n      /* onException */\n      if (test.timedOut)\n        return;\n\n      // XXX you want the \"name\" and \"message\" fields on the\n      // exception, to start with..\n      self._report(test, {\n        type: \"exception\",\n        details: {\n          message: exception.message, // XXX empty???\n          stack: exception.stack // XXX portability\n        }\n      });\n\n      onComplete();\n    }, stop_at_offset);\n  },\n\n  // Run a single test.  On the server, ensure that only one test runs\n  // at a time, even with multiple clients submitting tests.  However,\n  // time out the test after three minutes to avoid locking up the\n  // server if a test fails to complete.\n  //\n  _runOne: function (test, onComplete, stop_at_offset) {\n    var self = this;\n\n    if (! self._prefixMatch(test.groupPath)) {\n      onComplete && onComplete();\n      return;\n    }\n\n    if (Meteor.isServer) {\n      // On the server, ensure that only one test runs at a time, even\n      // with multiple clients.\n      self.manager.testQueue.queueTask(function () {\n        // The future resolves when the test completes or times out.\n        var future = new Future();\n        Meteor.setTimeout(\n          function () {\n            if (future.isResolved())\n              // If the future has resolved the test has completed.\n              return;\n            test.timedOut = true;\n            self._report(test, {\n              type: \"exception\",\n              details: {\n                message: \"test timed out\"\n              }\n            });\n            future['return']();\n          },\n          3 * 60 * 1000  // 3 minutes\n        );\n        self._runTest(test, function () {\n          // The test can complete after it has timed out (it might\n          // just be slow), so only resolve the future if the test\n          // hasn't timed out.\n          if (! future.isResolved())\n            future['return']();\n        }, stop_at_offset);\n        // Wait for the test to complete or time out.\n        future.wait();\n        onComplete && onComplete();\n      });\n    } else {\n      // client\n      self._runTest(test, function () {\n        onComplete && onComplete();\n      }, stop_at_offset);\n    }\n  },\n\n  run: function (onComplete) {\n    var self = this;\n    var tests = _.clone(self.manager.ordered_tests);\n    var reportCurrent = function (name) {\n      if (Meteor.isClient)\n        Tinytest._onCurrentClientTest(name);\n    };\n\n    var runNext = function () {\n      if (tests.length) {\n        var t = tests.shift();\n        reportCurrent(t.name);\n        self._runOne(t, runNext);\n      } else {\n        reportCurrent(null);\n        onComplete && onComplete();\n      }\n    };\n\n    runNext();\n  },\n\n  // An alternative to run(). Given the 'cookie' attribute of a\n  // failure record, try to rerun that particular test up to that\n  // failure, and then open the debugger.\n  debug: function (cookie, onComplete) {\n    var self = this;\n    var test = self.manager.tests[cookie.name];\n    if (!test)\n      throw new Error(\"No such test '\" + cookie.name + \"'\");\n    self._runOne(test, onComplete, cookie.offset);\n  },\n\n  _report: function (test, event) {\n    var self = this;\n    if (event)\n      var events = [_.extend({sequence: self.next_sequence_number++}, event)];\n    else\n      var events = [];\n    self.onReport({\n      groupPath: test.groupPath,\n      test: test.shortName,\n      events: events\n    });\n  }\n});\n\n/******************************************************************************/\n/* Public API                                                                 */\n/******************************************************************************/\n\nTinytest = {};\n\nTinytest.addAsync = function (name, func) {\n  TestManager.addCase(new TestCase(name, func));\n};\n\nTinytest.add = function (name, func) {\n  Tinytest.addAsync(name, function (test, onComplete) {\n    func(test);\n    onComplete();\n  });\n};\n\n// Run every test, asynchronously. Runs the test in the current\n// process only (if called on the server, runs the tests on the\n// server, and likewise for the client.) Report results via\n// onReport. Call onComplete when it's done.\n//\nTinytest._runTests = function (onReport, onComplete, pathPrefix) {\n  var testRun = TestManager.createRun(onReport, pathPrefix);\n  testRun.run(onComplete);\n};\n\n// Run just one test case, and stop the debugger at a particular\n// error, all as indicated by 'cookie', which will have come from a\n// failure event output by _runTests.\n//\nTinytest._debugTest = function (cookie, onReport, onComplete) {\n  var testRun = TestManager.createRun(onReport);\n  testRun.debug(cookie, onComplete);\n};\n\n// Replace this callback to get called when we run a client test,\n// and then called with `null` when the client tests are\n// done.  This is used to provide a live display of the current\n// running client test on the test results page.\nTinytest._onCurrentClientTest = function (name) {};\n\nTinytest._TestCaseResults = TestCaseResults;\nTinytest._TestCase = TestCase;\nTinytest._TestManager = TestManager;\nTinytest._TestRun = TestRun;\n"
  },
  {
    "path": "packages/tinytest/tinytest_client.js",
    "content": "// Like Tinytest._runTests, but runs the tests on both the client and\n// the server. Sets a 'server' flag on test results that came from the\n// server.\n//\n// Options:\n//   serial     if true, will not run tests in parallel.  Currently this means\n//              running the server tests before running the client tests.\n//              Default is currently true (serial operation), but we will likely\n//              change this to false in future.\nTinytest._runTestsEverywhere = function (onReport, onComplete, pathPrefix, options) {\n  var runId = Random.id();\n  var localComplete = false;\n  var localStarted = false;\n  var remoteComplete = false;\n  var done = false;\n\n  options = _.extend({\n    serial: true\n  }, options);\n  var serial = !!options.serial;\n\n  var maybeDone = function () {\n    if (!done && localComplete && remoteComplete) {\n      done = true;\n      onComplete && onComplete();\n    }\n    if (serial && remoteComplete && !localStarted) {\n      startLocalTests();\n    }\n  };\n\n  var startLocalTests = function() {\n    localStarted = true;\n    Tinytest._runTests(onReport, function () {\n      localComplete = true;\n      maybeDone();\n    }, pathPrefix);\n  };\n\n  var handle;\n\n  Meteor.connection.registerStore(Meteor._ServerTestResultsCollection, {\n    update: function (msg) {\n      // We only should call _runTestsEverywhere once per client-page-load, so\n      // we really only should see one runId here.\n      if (msg.id !== runId)\n        return;\n      // This will only work for added & changed messages.\n      // hope that is all you get.\n      _.each(msg.fields, function (report, key) {\n        // Skip the 'complete' report (deal with it last)\n        if (key === 'complete') {\n          return;\n        }\n        _.each(report.events, function (event) {\n          delete event.cookie; // can't debug a server test on the client..\n        });\n        report.server = true;\n        onReport(report);\n      });\n      // Now that we've processed all the other messages,\n      // check if we have the 'complete' message\n      if (msg.fields && _.has(msg.fields, 'complete')) {\n        remoteComplete = true;\n        handle.stop();\n        Meteor.call('tinytest/clearResults', runId);\n        maybeDone();\n      }\n    }\n  });\n\n  handle = Meteor.subscribe(Meteor._ServerTestResultsSubscription, runId);\n\n  Meteor.call('tinytest/run', runId, pathPrefix, function (error, result) {\n    if (error)\n      // XXX better report error\n      throw new Error(\"Test server returned an error\");\n  });\n\n  if (!serial) {\n    startLocalTests();\n  }\n};\n"
  },
  {
    "path": "packages/tinytest/tinytest_server.js",
    "content": "var Fiber = Npm.require('fibers');\nvar handlesForRun = {};\nvar reportsForRun = {};\n\nMeteor.publish(Meteor._ServerTestResultsSubscription, function (runId) {\n  check(runId, String);\n  var self = this;\n  if (!_.has(handlesForRun, runId))\n    handlesForRun[runId] = [self];\n  else\n    handlesForRun[runId].push(self);\n  self.onStop(function () {\n    handlesForRun[runId] = _.without(handlesForRun[runId], self);\n  });\n  if (_.has(reportsForRun, runId)) {\n    self.added(Meteor._ServerTestResultsCollection, runId,\n               reportsForRun[runId]);\n  } else {\n    self.added(Meteor._ServerTestResultsCollection, runId, {});\n  }\n  self.ready();\n});\n\nMeteor.methods({\n  'tinytest/run': function (runId, pathPrefix) {\n    check(runId, String);\n    check(pathPrefix, Match.Optional([String]));\n    this.unblock();\n\n    reportsForRun[runId] = {};\n\n    var addReport = function (key, report) {\n      var fields = {};\n      fields[key] = report;\n      _.each(handlesForRun[runId], function (handle) {\n        handle.changed(Meteor._ServerTestResultsCollection, runId, fields);\n      });\n      // Save for future subscriptions.\n      reportsForRun[runId][key] = report;\n    };\n\n    var onReport = function (report) {\n      if (! Fiber.current) {\n        Meteor._debug(\"Trying to report a test not in a fiber! \"+\n                      \"You probably forgot to wrap a callback in bindEnvironment.\");\n        console.trace();\n      }\n      var dummyKey = Random.id();\n      addReport(dummyKey, report);\n    };\n\n    var onComplete = function() {\n      // We send an object for current and future compatibility,\n      // though we could get away with just sending { complete: true }\n      var report = { done: true };\n      var key = 'complete';\n      addReport(key, report);\n    };\n\n    Tinytest._runTests(onReport, onComplete, pathPrefix);\n  },\n  'tinytest/clearResults': function (runId) {\n    check(runId, String);\n    _.each(handlesForRun[runId], function (handle) {\n      // XXX this doesn't actually notify the client that it has been\n      // unsubscribed.\n      handle.stop();\n    });\n    delete handlesForRun[runId];\n    delete reportsForRun[runId];\n  }\n});\n"
  },
  {
    "path": "packages/tinytest-harness/README.md",
    "content": ""
  },
  {
    "path": "packages/tinytest-harness/package.js",
    "content": "Package.describe({\n  name: 'tinytest-harness',\n  version: '0.0.4',\n  summary: 'In development, lets your app define Tinytests, run them and see results',\n  documentation: null\n});\n\nPackage.onUse(function(api) {\n  // XXX this needs to change. We'll probably have `testOnly` a la\n  // `debugOnly`.\n  if (global.testCommandMetadata) {\n    api.imply('tinytest');\n    api.imply('test-helpers');\n    api.imply('test-in-browser');\n\n    api.use('test-in-browser');\n\n    api.export('runTests');\n  }\n});\n"
  },
  {
    "path": "packages/tracker/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/tracker/README.md",
    "content": "# Meteor Tracker\n\nMeteor Tracker is an incredibly tiny (~1k) but incredibly powerful\nlibrary for **transparent reactive programming** in JavaScript. (It\nwas previously called Deps.)\n\nTracker gives you much of the power of a full-blown\n[Functional Reactive Programming](http://en.wikipedia.org/wiki/Functional_reactive_programming) (FRP) system without requiring you to rewrite your program as a FRP data flow graph. Combined with Tracker-aware libraries, this lets you build complex event-driven programs without writing a lot of boilerplate event-handling code.\n\nTracker is essentially a simple _convention_, or interface, that lets reactive data sources (like your database) talk to reactive data consumers (such as a live-updating HTML templating library) without the application code in between having to be involved. Since the convention is very simple, it is quick and easy for library authors to make their libraries Tracker-aware, so that they can participate in Tracker reactivity.\n\nThis README has a short introduction to Tracker. For a complete guide\nto Tracker, consult the thorough and informative [Tracker\nManual](https://github.com/meteor/meteor/wiki/Tracker-Manual), which\nis five times longer than the Tracker source code itself. You can also browse the API reference on the [main Meteor docs page](http://docs.meteor.com/#tracker).\n\n## Example\n\nTake this ordinary JavaScript function:\n\n```javascript\nvar currentTemperatureFahrenheit = function () {\n  return currentTemperatureCelsius() * 9/5 + 32;\n};\n\n```\n\nWe can call it for its value (assuming there's a `currentTemperatureCelsius` function):\n\n```\n> currentTemperatureFahrenheit()\n71.8\n```\n\nBut, if the `currentTemperatureCelsius` function is Tracker-aware (or even if it's not, but as long it reads the current temperature ultimately from some Tracker-aware data source), then we can also call `currentTemperatureFahrenheit` _reactively_:\n\n```\n> var handle = Tracker.autorun(function () {\n  console.log(\"The current temperature is\", currentTemperatureFahrenheit(),\n              \"F\");\n  });\nThe current temperature is 71.8 F       (printed immediately)\nThe current temperature is 71.9 F       (printed a few minutes later)\n> handle.stop();                        (stop temperature changes from printing)\n\n```\n\nThe function passed to `Tracker.autorun` is called once immediately, and then it's called again whenever there are any changes to any of the _reactive data sources_ that it referenced. To make this work, `currentTemperatureCelsius` just needs to register with Tracker as a reactive data source when it's called, which takes only a few lines of code.\n\nOr, instead of calling `Tracker.autorun` ourselves, we might use `currentTemperatureFahrenheit` in a [Blaze](https://www.meteor.com/blaze) template:\n\n```handlebars\n<!-- In demo.html -->\n<template name=\"demo\">\n  The current temperature is {{currentTemp}} degrees Fahrenheit.\n  {{#if belowFreezing}}\n    That's below freezing!\n  {{/if}}\n</templates>\n```\n\n```javascript\n// In demo.js\nTemplate.demo.helpers({\n  currentTemp: function () {\n    return currentTemperatureFahrenheit();\n  },\n  belowFreezing: function () {\n    return currentTemperatureFahrenheit() < 32.0;\n  }\n});\n```\n\nWhen this template is shown, the temperature shown on the screen will update live as the weather changes. The \"below freezing\" message will appear when the temperature dips below freezing, and disappear when it rises above freezing, all without having to write any additiona logic. Blaze makes this work simply by calling `Tracker.autorun` around its calls out to our helper functions.\n\n\nWhat does it look like on the other side, for package authors that are creating new reactive data sources? Here's what the implementation of `currentTemperatureCelsius` might look like (supposing you had an object `Thermometer`, with methods `read` and `onChange`):\n\n```javascript\nvar temperatureDep = new Tracker.Dependency;\n\nvar currentTemperatureCelsius = function () {\n  temperatureDep.depend();\n  return Thermometer.read();\n};\n\nThermometer.onChange(function () {\n  temperatureDep.changed();\n});\n```\n\nAs you can see, it only takes a few lines of code to make `Thermometer` Tracker-aware so that it can participate in transparent reactivity.\n\nIt's easy for a library to detect if Tracker is available, and cooperate with it if so (by making the appropriate `depend` and `changed` calls, which have virtually no overhead except when called in a reactive context), and function normally if not. So adding Tracker support doesn't break compatibility with existing users of a library, and the support doesn't have any performance impact if it's not used. (The impact when it *is* used is small as well.)\n\n## Tracker-aware libraries from the Meteor Project\n\nThe Meteor project provides a variety of Tracker-aware libraries:\n\n- [Blaze](https://www.meteor.com/blaze) is a reactive templating/DOM update library designed to work well with Tracker.\n\n- [Minimongo](https://www.meteor.com/mini-databases) is a Tracker-aware reimplementation of the MongoDB API in JavaScript, very useful for storing and querying client-side data. We also have a [\"full stack database driver\"](https://www.meteor.com/full-stack-db-drivers) for Mongo that replicates data from a real server-side MongoDB database into Minimongo.\n\n- [reactive-dict](https://atmospherejs.com/meteor/reactive-dict), and\n[reactive-var](https://atmospherejs.com/meteor/reactive-var) provide\nsome fundamental reactive data\ntypes. [session](https://atmospherejs.com/meteor/session) provides a\n`ReactiveDict` whose contents persist across hot updates to an app's\ncode.\n\n- Other Meteor core packages are generally Tracker-aware wherever it\n  makes sense. For example, the current connection status is reactive\n  in Meteor's [DDP](https://www.meteor.com/ddp) implementation, and\n  the currently logged in user is reactive in [Meteor\n  Accounts](https://www.meteor.com/accounts) system.\n\n## Future directions\n\nIdeas for future work include:\n\n- Unifying [reactive-dict](https://atmospherejs.com/meteor/reactive-dict) and\n[reactive-var](https://atmospherejs.com/meteor/reactive-var), so that instead of making a `ReactiveDict` you can simply put an object into a `ReactiveVar`\n- Providing a contract for _settable_ reactive values, to make it easier to build bidirectionally bound forms. There is some discussion of this [here](https://meteor.hackpad.com/Lickable-Forms-and-Components-6CVspZsVwJY).\n- Making it possible to control invalidation order, for example by specifying that if autorun B was created inside autorun A, then if both A and B are invalidated and eligible to be rerun, then A will rerun before B. It is easy to construct theoretical situations where this would be valuable, but situations where this makes a difference in real apps seem to be surprisingly rare.\n\nAlso as described on the project pages for [Mini databases](https://www.meteor.com/mini-databases) and [Full stack database drivers](https://www.meteor.com/full-stack-db-drivers), the Meteor project intends to eventually sponsor development of Tracker-aware libraries that emulate other server-side databases besides Mongo.\n"
  },
  {
    "path": "packages/tracker/deprecated.js",
    "content": "// Deprecated functions.\n\n// These functions used to be on the Meteor object (and worked slightly\n// differently).\n// XXX COMPAT WITH 0.5.7\nMeteor.flush = Tracker.flush;\nMeteor.autorun = Tracker.autorun;\n\n// We used to require a special \"autosubscribe\" call to reactively subscribe to\n// things. Now, it works with autorun.\n// XXX COMPAT WITH 0.5.4\nMeteor.autosubscribe = Tracker.autorun;\n\n// This Tracker API briefly existed in 0.5.8 and 0.5.9\n// XXX COMPAT WITH 0.5.9\nTracker.depend = function (d) {\n  return d.depend();\n};\n\nDeps = Tracker;\n"
  },
  {
    "path": "packages/tracker/package.js",
    "content": "Package.describe({\n  summary: \"Dependency tracker to allow reactive callbacks\",\n  version: '1.0.14'\n});\n\nPackage.onUse(function (api) {\n  api.export('Tracker');\n  api.export('Deps');\n  api.addFiles('tracker.js');\n  api.addFiles('deprecated.js');\n});\n\nPackage.onTest(function (api) {\n  api.use('tinytest');\n  api.use('test-helpers');\n  api.use('tracker');\n  api.addFiles('tracker_tests.js', 'client');\n});\n"
  },
  {
    "path": "packages/tracker/tracker.js",
    "content": "/////////////////////////////////////////////////////\n// Package docs at http://docs.meteor.com/#tracker //\n/////////////////////////////////////////////////////\n\n/**\n * @namespace Tracker\n * @summary The namespace for Tracker-related methods.\n */\nTracker = {};\n\n// http://docs.meteor.com/#tracker_active\n\n/**\n * @summary True if there is a current computation, meaning that dependencies on reactive data sources will be tracked and potentially cause the current computation to be rerun.\n * @locus Client\n * @type {Boolean}\n */\nTracker.active = false;\n\n// http://docs.meteor.com/#tracker_currentcomputation\n\n/**\n * @summary The current computation, or `null` if there isn't one.  The current computation is the [`Tracker.Computation`](#tracker_computation) object created by the innermost active call to `Tracker.autorun`, and it's the computation that gains dependencies when reactive data sources are accessed.\n * @locus Client\n * @type {Tracker.Computation}\n */\nTracker.currentComputation = null;\n\n// References to all computations created within the Tracker by id.\n// Keeping these references on an underscore property gives more control to\n// tooling and packages extending Tracker without increasing the API surface.\n// These can used to monkey-patch computations, their functions, use\n// computation ids for tracking, etc.\nTracker._computations = {};\n\nvar setCurrentComputation = function (c) {\n  Tracker.currentComputation = c;\n  Tracker.active = !! c;\n};\n\nvar _debugFunc = function () {\n  // We want this code to work without Meteor, and also without\n  // \"console\" (which is technically non-standard and may be missing\n  // on some browser we come across, like it was on IE 7).\n  //\n  // Lazy evaluation because `Meteor` does not exist right away.(??)\n  return (typeof Meteor !== \"undefined\" ? Meteor._debug :\n          ((typeof console !== \"undefined\") && console.error ?\n           function () { console.error.apply(console, arguments); } :\n           function () {}));\n};\n\nvar _maybeSuppressMoreLogs = function (messagesLength) {\n  // Sometimes when running tests, we intentionally suppress logs on expected\n  // printed errors. Since the current implementation of _throwOrLog can log\n  // multiple separate log messages, suppress all of them if at least one suppress\n  // is expected as we still want them to count as one.\n  if (typeof Meteor !== \"undefined\") {\n    if (Meteor._suppressed_log_expected()) {\n      Meteor._suppress_log(messagesLength - 1);\n    }\n  }\n};\n\nvar _throwOrLog = function (from, e) {\n  if (throwFirstError) {\n    throw e;\n  } else {\n    var printArgs = [\"Exception from Tracker \" + from + \" function:\"];\n    if (e.stack && e.message && e.name) {\n      var idx = e.stack.indexOf(e.message);\n      if (idx < 0 || idx > e.name.length + 2) { // check for \"Error: \"\n        // message is not part of the stack\n        var message = e.name + \": \" + e.message;\n        printArgs.push(message);\n      }\n    }\n    printArgs.push(e.stack);\n    _maybeSuppressMoreLogs(printArgs.length);\n\n    for (var i = 0; i < printArgs.length; i++) {\n      _debugFunc()(printArgs[i]);\n    }\n  }\n};\n\n// Takes a function `f`, and wraps it in a `Meteor._noYieldsAllowed`\n// block if we are running on the server. On the client, returns the\n// original function (since `Meteor._noYieldsAllowed` is a\n// no-op). This has the benefit of not adding an unnecessary stack\n// frame on the client.\nvar withNoYieldsAllowed = function (f) {\n  if ((typeof Meteor === 'undefined') || Meteor.isClient) {\n    return f;\n  } else {\n    return function () {\n      var args = arguments;\n      Meteor._noYieldsAllowed(function () {\n        f.apply(null, args);\n      });\n    };\n  }\n};\n\nvar nextId = 1;\n// computations whose callbacks we should call at flush time\nvar pendingComputations = [];\n// `true` if a Tracker.flush is scheduled, or if we are in Tracker.flush now\nvar willFlush = false;\n// `true` if we are in Tracker.flush now\nvar inFlush = false;\n// `true` if we are computing a computation now, either first time\n// or recompute.  This matches Tracker.active unless we are inside\n// Tracker.nonreactive, which nullfies currentComputation even though\n// an enclosing computation may still be running.\nvar inCompute = false;\n// `true` if the `_throwFirstError` option was passed in to the call\n// to Tracker.flush that we are in. When set, throw rather than log the\n// first error encountered while flushing. Before throwing the error,\n// finish flushing (from a finally block), logging any subsequent\n// errors.\nvar throwFirstError = false;\n\nvar afterFlushCallbacks = [];\n\nvar requireFlush = function () {\n  if (! willFlush) {\n    // We want this code to work without Meteor, see debugFunc above\n    if (typeof Meteor !== \"undefined\")\n      Meteor._setImmediate(Tracker._runFlush);\n    else\n      setTimeout(Tracker._runFlush, 0);\n    willFlush = true;\n  }\n};\n\n// Tracker.Computation constructor is visible but private\n// (throws an error if you try to call it)\nvar constructingComputation = false;\n\n//\n// http://docs.meteor.com/#tracker_computation\n\n/**\n * @summary A Computation object represents code that is repeatedly rerun\n * in response to\n * reactive data changes. Computations don't have return values; they just\n * perform actions, such as rerendering a template on the screen. Computations\n * are created using Tracker.autorun. Use stop to prevent further rerunning of a\n * computation.\n * @instancename computation\n */\nTracker.Computation = function (f, parent, onError) {\n  if (! constructingComputation)\n    throw new Error(\n      \"Tracker.Computation constructor is private; use Tracker.autorun\");\n  constructingComputation = false;\n\n  var self = this;\n\n  // http://docs.meteor.com/#computation_stopped\n\n  /**\n   * @summary True if this computation has been stopped.\n   * @locus Client\n   * @memberOf Tracker.Computation\n   * @instance\n   * @name  stopped\n   */\n  self.stopped = false;\n\n  // http://docs.meteor.com/#computation_invalidated\n\n  /**\n   * @summary True if this computation has been invalidated (and not yet rerun), or if it has been stopped.\n   * @locus Client\n   * @memberOf Tracker.Computation\n   * @instance\n   * @name  invalidated\n   * @type {Boolean}\n   */\n  self.invalidated = false;\n\n  // http://docs.meteor.com/#computation_firstrun\n\n  /**\n   * @summary True during the initial run of the computation at the time `Tracker.autorun` is called, and false on subsequent reruns and at other times.\n   * @locus Client\n   * @memberOf Tracker.Computation\n   * @instance\n   * @name  firstRun\n   * @type {Boolean}\n   */\n  self.firstRun = true;\n\n  self._id = nextId++;\n  self._onInvalidateCallbacks = [];\n  self._onStopCallbacks = [];\n  // the plan is at some point to use the parent relation\n  // to constrain the order that computations are processed\n  self._parent = parent;\n  self._func = f;\n  self._onError = onError;\n  self._recomputing = false;\n\n  // Register the computation within the global Tracker.\n  Tracker._computations[self._id] = self;\n\n  var errored = true;\n  try {\n    self._compute();\n    errored = false;\n  } finally {\n    self.firstRun = false;\n    if (errored)\n      self.stop();\n  }\n};\n\n// http://docs.meteor.com/#computation_oninvalidate\n\n/**\n * @summary Registers `callback` to run when this computation is next invalidated, or runs it immediately if the computation is already invalidated.  The callback is run exactly once and not upon future invalidations unless `onInvalidate` is called again after the computation becomes valid again.\n * @locus Client\n * @param {Function} callback Function to be called on invalidation. Receives one argument, the computation that was invalidated.\n */\nTracker.Computation.prototype.onInvalidate = function (f) {\n  var self = this;\n\n  if (typeof f !== 'function')\n    throw new Error(\"onInvalidate requires a function\");\n\n  if (self.invalidated) {\n    Tracker.nonreactive(function () {\n      withNoYieldsAllowed(f)(self);\n    });\n  } else {\n    self._onInvalidateCallbacks.push(f);\n  }\n};\n\n/**\n * @summary Registers `callback` to run when this computation is stopped, or runs it immediately if the computation is already stopped.  The callback is run after any `onInvalidate` callbacks.\n * @locus Client\n * @param {Function} callback Function to be called on stop. Receives one argument, the computation that was stopped.\n */\nTracker.Computation.prototype.onStop = function (f) {\n  var self = this;\n\n  if (typeof f !== 'function')\n    throw new Error(\"onStop requires a function\");\n\n  if (self.stopped) {\n    Tracker.nonreactive(function () {\n      withNoYieldsAllowed(f)(self);\n    });\n  } else {\n    self._onStopCallbacks.push(f);\n  }\n};\n\n// http://docs.meteor.com/#computation_invalidate\n\n/**\n * @summary Invalidates this computation so that it will be rerun.\n * @locus Client\n */\nTracker.Computation.prototype.invalidate = function () {\n  var self = this;\n  if (! self.invalidated) {\n    // if we're currently in _recompute(), don't enqueue\n    // ourselves, since we'll rerun immediately anyway.\n    if (! self._recomputing && ! self.stopped) {\n      requireFlush();\n      pendingComputations.push(this);\n    }\n\n    self.invalidated = true;\n\n    // callbacks can't add callbacks, because\n    // self.invalidated === true.\n    for(var i = 0, f; f = self._onInvalidateCallbacks[i]; i++) {\n      Tracker.nonreactive(function () {\n        withNoYieldsAllowed(f)(self);\n      });\n    }\n    self._onInvalidateCallbacks = [];\n  }\n};\n\n// http://docs.meteor.com/#computation_stop\n\n/**\n * @summary Prevents this computation from rerunning.\n * @locus Client\n */\nTracker.Computation.prototype.stop = function () {\n  var self = this;\n\n  if (! self.stopped) {\n    self.stopped = true;\n    self.invalidate();\n    // Unregister from global Tracker.\n    delete Tracker._computations[self._id];\n    for(var i = 0, f; f = self._onStopCallbacks[i]; i++) {\n      Tracker.nonreactive(function () {\n        withNoYieldsAllowed(f)(self);\n      });\n    }\n    self._onStopCallbacks = [];\n  }\n};\n\nTracker.Computation.prototype._compute = function () {\n  var self = this;\n  self.invalidated = false;\n\n  var previous = Tracker.currentComputation;\n  setCurrentComputation(self);\n  var previousInCompute = inCompute;\n  inCompute = true;\n  try {\n    withNoYieldsAllowed(self._func)(self);\n  } finally {\n    setCurrentComputation(previous);\n    inCompute = previousInCompute;\n  }\n};\n\nTracker.Computation.prototype._needsRecompute = function () {\n  var self = this;\n  return self.invalidated && ! self.stopped;\n};\n\nTracker.Computation.prototype._recompute = function () {\n  var self = this;\n\n  self._recomputing = true;\n  try {\n    if (self._needsRecompute()) {\n      try {\n        self._compute();\n      } catch (e) {\n        if (self._onError) {\n          self._onError(e);\n        } else {\n          _throwOrLog(\"recompute\", e);\n        }\n      }\n    }\n  } finally {\n    self._recomputing = false;\n  }\n};\n\n/**\n * @summary Process the reactive updates for this computation immediately\n * and ensure that the computation is rerun. The computation is rerun only\n * if it is invalidated.\n * @locus Client\n */\nTracker.Computation.prototype.flush = function () {\n  var self = this;\n\n  if (self._recomputing)\n    return;\n\n  self._recompute();\n};\n\n/**\n * @summary Causes the function inside this computation to run and\n * synchronously process all reactive updtes.\n * @locus Client\n */\nTracker.Computation.prototype.run = function () {\n  var self = this;\n  self.invalidate();\n  self.flush();\n};\n\n//\n// http://docs.meteor.com/#tracker_dependency\n\n/**\n * @summary A Dependency represents an atomic unit of reactive data that a\n * computation might depend on. Reactive data sources such as Session or\n * Minimongo internally create different Dependency objects for different\n * pieces of data, each of which may be depended on by multiple computations.\n * When the data changes, the computations are invalidated.\n * @class\n * @instanceName dependency\n */\nTracker.Dependency = function () {\n  this._dependentsById = {};\n};\n\n// http://docs.meteor.com/#dependency_depend\n//\n// Adds `computation` to this set if it is not already\n// present.  Returns true if `computation` is a new member of the set.\n// If no argument, defaults to currentComputation, or does nothing\n// if there is no currentComputation.\n\n/**\n * @summary Declares that the current computation (or `fromComputation` if given) depends on `dependency`.  The computation will be invalidated the next time `dependency` changes.\n\nIf there is no current computation and `depend()` is called with no arguments, it does nothing and returns false.\n\nReturns true if the computation is a new dependent of `dependency` rather than an existing one.\n * @locus Client\n * @param {Tracker.Computation} [fromComputation] An optional computation declared to depend on `dependency` instead of the current computation.\n * @returns {Boolean}\n */\nTracker.Dependency.prototype.depend = function (computation) {\n  if (! computation) {\n    if (! Tracker.active)\n      return false;\n\n    computation = Tracker.currentComputation;\n  }\n  var self = this;\n  var id = computation._id;\n  if (! (id in self._dependentsById)) {\n    self._dependentsById[id] = computation;\n    computation.onInvalidate(function () {\n      delete self._dependentsById[id];\n    });\n    return true;\n  }\n  return false;\n};\n\n// http://docs.meteor.com/#dependency_changed\n\n/**\n * @summary Invalidate all dependent computations immediately and remove them as dependents.\n * @locus Client\n */\nTracker.Dependency.prototype.changed = function () {\n  var self = this;\n  for (var id in self._dependentsById)\n    self._dependentsById[id].invalidate();\n};\n\n// http://docs.meteor.com/#dependency_hasdependents\n\n/**\n * @summary True if this Dependency has one or more dependent Computations, which would be invalidated if this Dependency were to change.\n * @locus Client\n * @returns {Boolean}\n */\nTracker.Dependency.prototype.hasDependents = function () {\n  var self = this;\n  for(var id in self._dependentsById)\n    return true;\n  return false;\n};\n\n// http://docs.meteor.com/#tracker_flush\n\n/**\n * @summary Process all reactive updates immediately and ensure that all invalidated computations are rerun.\n * @locus Client\n */\nTracker.flush = function (options) {\n  Tracker._runFlush({ finishSynchronously: true,\n                      throwFirstError: options && options._throwFirstError });\n};\n\n// Run all pending computations and afterFlush callbacks.  If we were not called\n// directly via Tracker.flush, this may return before they're all done to allow\n// the event loop to run a little before continuing.\nTracker._runFlush = function (options) {\n  // XXX What part of the comment below is still true? (We no longer\n  // have Spark)\n  //\n  // Nested flush could plausibly happen if, say, a flush causes\n  // DOM mutation, which causes a \"blur\" event, which runs an\n  // app event handler that calls Tracker.flush.  At the moment\n  // Spark blocks event handlers during DOM mutation anyway,\n  // because the LiveRange tree isn't valid.  And we don't have\n  // any useful notion of a nested flush.\n  //\n  // https://app.asana.com/0/159908330244/385138233856\n  if (inFlush)\n    throw new Error(\"Can't call Tracker.flush while flushing\");\n\n  if (inCompute)\n    throw new Error(\"Can't flush inside Tracker.autorun\");\n\n  options = options || {};\n\n  inFlush = true;\n  willFlush = true;\n  throwFirstError = !! options.throwFirstError;\n\n  var recomputedCount = 0;\n  var finishedTry = false;\n  try {\n    while (pendingComputations.length ||\n           afterFlushCallbacks.length) {\n\n      // recompute all pending computations\n      while (pendingComputations.length) {\n        var comp = pendingComputations.shift();\n        comp._recompute();\n        if (comp._needsRecompute()) {\n          pendingComputations.unshift(comp);\n        }\n\n        if (! options.finishSynchronously && ++recomputedCount > 1000) {\n          finishedTry = true;\n          return;\n        }\n      }\n\n      if (afterFlushCallbacks.length) {\n        // call one afterFlush callback, which may\n        // invalidate more computations\n        var func = afterFlushCallbacks.shift();\n        try {\n          func();\n        } catch (e) {\n          _throwOrLog(\"afterFlush\", e);\n        }\n      }\n    }\n    finishedTry = true;\n  } finally {\n    if (! finishedTry) {\n      // we're erroring due to throwFirstError being true.\n      inFlush = false; // needed before calling `Tracker.flush()` again\n      // finish flushing\n      Tracker._runFlush({\n        finishSynchronously: options.finishSynchronously,\n        throwFirstError: false\n      });\n    }\n    willFlush = false;\n    inFlush = false;\n    if (pendingComputations.length || afterFlushCallbacks.length) {\n      // We're yielding because we ran a bunch of computations and we aren't\n      // required to finish synchronously, so we'd like to give the event loop a\n      // chance. We should flush again soon.\n      if (options.finishSynchronously) {\n        throw new Error(\"still have more to do?\");  // shouldn't happen\n      }\n      setTimeout(requireFlush, 10);\n    }\n  }\n};\n\n// http://docs.meteor.com/#tracker_autorun\n//\n// Run f(). Record its dependencies. Rerun it whenever the\n// dependencies change.\n//\n// Returns a new Computation, which is also passed to f.\n//\n// Links the computation to the current computation\n// so that it is stopped if the current computation is invalidated.\n\n/**\n * @callback Tracker.ComputationFunction\n * @param {Tracker.Computation}\n */\n/**\n * @summary Run a function now and rerun it later whenever its dependencies\n * change. Returns a Computation object that can be used to stop or observe the\n * rerunning.\n * @locus Client\n * @param {Tracker.ComputationFunction} runFunc The function to run. It receives\n * one argument: the Computation object that will be returned.\n * @param {Object} [options]\n * @param {Function} options.onError Optional. The function to run when an error\n * happens in the Computation. The only argument it recieves is the Error\n * thrown. Defaults to the error being logged to the console.\n * @returns {Tracker.Computation}\n */\nTracker.autorun = function (f, options) {\n  if (typeof f !== 'function')\n    throw new Error('Tracker.autorun requires a function argument');\n\n  options = options || {};\n\n  constructingComputation = true;\n  var c = new Tracker.Computation(\n    f, Tracker.currentComputation, options.onError);\n\n  if (Tracker.active)\n    Tracker.onInvalidate(function () {\n      c.stop();\n    });\n\n  return c;\n};\n\n// http://docs.meteor.com/#tracker_nonreactive\n//\n// Run `f` with no current computation, returning the return value\n// of `f`.  Used to turn off reactivity for the duration of `f`,\n// so that reactive data sources accessed by `f` will not result in any\n// computations being invalidated.\n\n/**\n * @summary Run a function without tracking dependencies.\n * @locus Client\n * @param {Function} func A function to call immediately.\n */\nTracker.nonreactive = function (f) {\n  var previous = Tracker.currentComputation;\n  setCurrentComputation(null);\n  try {\n    return f();\n  } finally {\n    setCurrentComputation(previous);\n  }\n};\n\n// http://docs.meteor.com/#tracker_oninvalidate\n\n/**\n * @summary Registers a new [`onInvalidate`](#computation_oninvalidate) callback on the current computation (which must exist), to be called immediately when the current computation is invalidated or stopped.\n * @locus Client\n * @param {Function} callback A callback function that will be invoked as `func(c)`, where `c` is the computation on which the callback is registered.\n */\nTracker.onInvalidate = function (f) {\n  if (! Tracker.active)\n    throw new Error(\"Tracker.onInvalidate requires a currentComputation\");\n\n  Tracker.currentComputation.onInvalidate(f);\n};\n\n// http://docs.meteor.com/#tracker_afterflush\n\n/**\n * @summary Schedules a function to be called during the next flush, or later in the current flush if one is in progress, after all invalidated computations have been rerun.  The function will be run once and not on subsequent flushes unless `afterFlush` is called again.\n * @locus Client\n * @param {Function} callback A function to call at flush time.\n */\nTracker.afterFlush = function (f) {\n  afterFlushCallbacks.push(f);\n  requireFlush();\n};\n"
  },
  {
    "path": "packages/tracker/tracker_tests.js",
    "content": "Tinytest.add('tracker - run', function (test) {\n  var d = new Tracker.Dependency;\n  var x = 0;\n  var handle = Tracker.autorun(function (handle) {\n    d.depend();\n    ++x;\n  });\n  test.equal(x, 1);\n  Tracker.flush();\n  test.equal(x, 1);\n  d.changed();\n  test.equal(x, 1);\n  Tracker.flush();\n  test.equal(x, 2);\n  d.changed();\n  test.equal(x, 2);\n  Tracker.flush();\n  test.equal(x, 3);\n  d.changed();\n  // Prevent the function from running further.\n  handle.stop();\n  Tracker.flush();\n  test.equal(x, 3);\n  d.changed();\n  Tracker.flush();\n  test.equal(x, 3);\n\n  Tracker.autorun(function (internalHandle) {\n    d.depend();\n    ++x;\n    if (x == 6)\n      internalHandle.stop();\n  });\n  test.equal(x, 4);\n  d.changed();\n  Tracker.flush();\n  test.equal(x, 5);\n  d.changed();\n  // Increment to 6 and stop.\n  Tracker.flush();\n  test.equal(x, 6);\n  d.changed();\n  Tracker.flush();\n  // Still 6!\n  test.equal(x, 6);\n\n  test.throws(function () {\n    Tracker.autorun();\n  });\n  test.throws(function () {\n    Tracker.autorun({});\n  });\n});\n\nTinytest.add(\"tracker - nested run\", function (test) {\n  var a = new Tracker.Dependency;\n  var b = new Tracker.Dependency;\n  var c = new Tracker.Dependency;\n  var d = new Tracker.Dependency;\n  var e = new Tracker.Dependency;\n  var f = new Tracker.Dependency;\n\n  var buf = \"\";\n\n  var c1 = Tracker.autorun(function () {\n    a.depend();\n    buf += 'a';\n    Tracker.autorun(function () {\n      b.depend();\n      buf += 'b';\n      Tracker.autorun(function () {\n        c.depend();\n        buf += 'c';\n        var c2 = Tracker.autorun(function () {\n          d.depend();\n          buf += 'd';\n          Tracker.autorun(function () {\n            e.depend();\n            buf += 'e';\n            Tracker.autorun(function () {\n              f.depend();\n              buf += 'f';\n            });\n          });\n          Tracker.onInvalidate(function () {\n            // only run once\n            c2.stop();\n          });\n        });\n      });\n    });\n    Tracker.onInvalidate(function (c1) {\n      c1.stop();\n    });\n  });\n\n  var expect = function (str) {\n    test.equal(buf, str);\n    buf = \"\";\n  };\n\n  expect('abcdef');\n\n  b.changed();\n  expect(''); // didn't flush yet\n  Tracker.flush();\n  expect('bcdef');\n\n  c.changed();\n  Tracker.flush();\n  expect('cdef');\n\n  var changeAndExpect = function (v, str) {\n    v.changed();\n    Tracker.flush();\n    expect(str);\n  };\n\n  // should cause running\n  changeAndExpect(e, 'ef');\n  changeAndExpect(f, 'f');\n  // invalidate inner context\n  changeAndExpect(d, '');\n  // no more running!\n  changeAndExpect(e, '');\n  changeAndExpect(f, '');\n  // rerun C\n  changeAndExpect(c, 'cdef');\n  changeAndExpect(e, 'ef');\n  changeAndExpect(f, 'f');\n  // rerun B\n  changeAndExpect(b, 'bcdef');\n  changeAndExpect(e, 'ef');\n  changeAndExpect(f, 'f');\n  // kill A\n  a.changed();\n  changeAndExpect(f, '');\n  changeAndExpect(e, '');\n  changeAndExpect(d, '');\n  changeAndExpect(c, '');\n  changeAndExpect(b, '');\n  changeAndExpect(a, '');\n\n  test.isFalse(a.hasDependents());\n  test.isFalse(b.hasDependents());\n  test.isFalse(c.hasDependents());\n  test.isFalse(d.hasDependents());\n  test.isFalse(e.hasDependents());\n  test.isFalse(f.hasDependents());\n});\n\nTinytest.add(\"tracker - flush\", function (test) {\n\n  var buf = \"\";\n\n  var c1 = Tracker.autorun(function (c) {\n    buf += 'a';\n    // invalidate first time\n    if (c.firstRun)\n      c.invalidate();\n  });\n\n  test.equal(buf, 'a');\n  Tracker.flush();\n  test.equal(buf, 'aa');\n  Tracker.flush();\n  test.equal(buf, 'aa');\n  c1.stop();\n  Tracker.flush();\n  test.equal(buf, 'aa');\n\n  //////\n\n  buf = \"\";\n\n  var c2 = Tracker.autorun(function (c) {\n    buf += 'a';\n    // invalidate first time\n    if (c.firstRun)\n      c.invalidate();\n\n    Tracker.onInvalidate(function () {\n      buf += \"*\";\n    });\n  });\n\n  test.equal(buf, 'a*');\n  Tracker.flush();\n  test.equal(buf, 'a*a');\n  c2.stop();\n  test.equal(buf, 'a*a*');\n  Tracker.flush();\n  test.equal(buf, 'a*a*');\n\n  /////\n  // Can flush a diferent run from a run;\n  // no current computation in afterFlush\n\n  buf = \"\";\n\n  var c3 = Tracker.autorun(function (c) {\n    buf += 'a';\n    // invalidate first time\n    if (c.firstRun)\n      c.invalidate();\n    Tracker.afterFlush(function () {\n      buf += (Tracker.active ? \"1\" : \"0\");\n    });\n  });\n\n  Tracker.afterFlush(function () {\n    buf += 'c';\n  });\n\n  var c4 = Tracker.autorun(function (c) {\n    c4 = c;\n    buf += 'b';\n  });\n\n  Tracker.flush();\n  test.equal(buf, 'aba0c0');\n  c3.stop();\n  c4.stop();\n  Tracker.flush();\n\n  // cases where flush throws\n\n  var ran = false;\n  Tracker.afterFlush(function (arg) {\n    ran = true;\n    test.equal(typeof arg, 'undefined');\n    test.throws(function () {\n      Tracker.flush(); // illegal nested flush\n    });\n  });\n\n  Tracker.flush();\n  test.isTrue(ran);\n\n  test.throws(function () {\n    Tracker.autorun(function () {\n      Tracker.flush(); // illegal to flush from a computation\n    });\n  });\n\n  test.throws(function () {\n    Tracker.autorun(function () {\n      Tracker.autorun(function () {});\n      Tracker.flush();\n    });\n  });\n});\n\nTinytest.add(\"tracker - lifecycle\", function (test) {\n\n  test.isFalse(Tracker.active);\n  test.equal(null, Tracker.currentComputation);\n\n  var runCount = 0;\n  var firstRun = true;\n  var buf = [];\n  var cbId = 1;\n  var makeCb = function () {\n    var id = cbId++;\n    return function () {\n      buf.push(id);\n    };\n  };\n\n  var shouldStop = false;\n\n  var c1 = Tracker.autorun(function (c) {\n    test.isTrue(Tracker.active);\n    test.equal(c, Tracker.currentComputation);\n    test.equal(c.stopped, false);\n    test.equal(c.invalidated, false);\n      test.equal(c.firstRun, firstRun);\n\n    Tracker.onInvalidate(makeCb()); // 1, 6, ...\n    Tracker.afterFlush(makeCb()); // 2, 7, ...\n\n    Tracker.autorun(function (x) {\n      x.stop();\n      c.onInvalidate(makeCb()); // 3, 8, ...\n\n      Tracker.onInvalidate(makeCb()); // 4, 9, ...\n      Tracker.afterFlush(makeCb()); // 5, 10, ...\n    });\n    runCount++;\n\n    if (shouldStop)\n      c.stop();\n  });\n\n  firstRun = false;\n\n  test.equal(runCount, 1);\n\n  test.equal(buf, [4]);\n  c1.invalidate();\n  test.equal(runCount, 1);\n  test.equal(c1.invalidated, true);\n  test.equal(c1.stopped, false);\n  test.equal(buf, [4, 1, 3]);\n\n  Tracker.flush();\n\n  test.equal(runCount, 2);\n  test.equal(c1.invalidated, false);\n  test.equal(buf, [4, 1, 3, 9, 2, 5, 7, 10]);\n\n  // test self-stop\n  buf.length = 0;\n  shouldStop = true;\n  c1.invalidate();\n  test.equal(buf, [6, 8]);\n  Tracker.flush();\n  test.equal(buf, [6, 8, 14, 11, 13, 12, 15]);\n\n});\n\nTinytest.add(\"tracker - onInvalidate\", function (test) {\n  var buf = \"\";\n\n  var c1 = Tracker.autorun(function () {\n    buf += \"*\";\n  });\n\n  var append = function (x, expectedComputation) {\n    return function (givenComputation) {\n      test.isFalse(Tracker.active);\n      test.equal(givenComputation, expectedComputation || c1);\n      buf += x;\n    };\n  };\n\n  c1.onStop(append('s'));\n\n  c1.onInvalidate(append('a'));\n  c1.onInvalidate(append('b'));\n  test.equal(buf, '*');\n  Tracker.autorun(function (me) {\n    Tracker.onInvalidate(append('z', me));\n    me.stop();\n    test.equal(buf, '*z');\n    c1.invalidate();\n  });\n  test.equal(buf, '*zab');\n  c1.onInvalidate(append('c'));\n  c1.onInvalidate(append('d'));\n  test.equal(buf, '*zabcd');\n  Tracker.flush();\n  test.equal(buf, '*zabcd*');\n\n  // afterFlush ordering\n  buf = '';\n  c1.onInvalidate(append('a'));\n  c1.onInvalidate(append('b'));\n  Tracker.afterFlush(function () {\n    append('x')(c1);\n    c1.onInvalidate(append('c'));\n    c1.invalidate();\n    Tracker.afterFlush(function () {\n      append('y')(c1);\n      c1.onInvalidate(append('d'));\n      c1.invalidate();\n    });\n  });\n  Tracker.afterFlush(function () {\n    append('z')(c1);\n    c1.onInvalidate(append('e'));\n    c1.invalidate();\n  });\n\n  test.equal(buf, '');\n  Tracker.flush();\n  test.equal(buf, 'xabc*ze*yd*');\n\n  buf = \"\";\n  c1.onInvalidate(append('m'));\n  Tracker.flush();\n  test.equal(buf, '');\n  c1.stop();\n  test.equal(buf, 'ms');  // s is from onStop\n  Tracker.flush();\n  test.equal(buf, 'ms');\n  c1.onStop(append('S'));\n  test.equal(buf, 'msS');\n});\n\nTinytest.add('tracker - invalidate at flush time', function (test) {\n  // Test this sentence of the docs: Functions are guaranteed to be\n  // called at a time when there are no invalidated computations that\n  // need rerunning.\n\n  var buf = [];\n\n  Tracker.afterFlush(function () {\n    buf.push('C');\n  });\n\n  // When c1 is invalidated, it invalidates c2, then stops.\n  var c1 = Tracker.autorun(function (c) {\n    if (! c.firstRun) {\n      buf.push('A');\n      c2.invalidate();\n      c.stop();\n    }\n  });\n\n  var c2 = Tracker.autorun(function (c) {\n    if (! c.firstRun) {\n      buf.push('B');\n      c.stop();\n    }\n  });\n\n  // Invalidate c1.  If all goes well, the re-running of\n  // c2 should happen before the afterFlush.\n  c1.invalidate();\n  Tracker.flush();\n\n  test.equal(buf.join(''), 'ABC');\n\n});\n\nTinytest.add('tracker - throwFirstError', function (test) {\n  var d = new Tracker.Dependency;\n  Tracker.autorun(function (c) {\n    d.depend();\n\n    if (!c.firstRun)\n      throw new Error(\"foo\");\n  });\n\n  d.changed();\n  // doesn't throw; logs instead.\n  Meteor._suppress_log(1);\n  Tracker.flush();\n\n  d.changed();\n  test.throws(function () {\n    Tracker.flush({_throwFirstError: true});\n  }, /foo/);\n});\n\nTinytest.addAsync('tracker - no infinite recomputation', function (test, onComplete) {\n  var reran = false;\n  var c = Tracker.autorun(function (c) {\n    if (! c.firstRun)\n      reran = true;\n    c.invalidate();\n  });\n  test.isFalse(reran);\n  Meteor.setTimeout(function () {\n    c.stop();\n    Tracker.afterFlush(function () {\n      test.isTrue(reran);\n      test.isTrue(c.stopped);\n      onComplete();\n    });\n  }, 100);\n});\n\nTinytest.add('tracker - Tracker.flush finishes', function (test) {\n  // Currently, _runFlush will \"yield\" every 1000 computations... unless run in\n  // Tracker.flush. So this test validates that Tracker.flush is capable of\n  // running 2000 computations. Which isn't quite the same as infinity, but it's\n  // getting there.\n  var n = 0;\n  var c = Tracker.autorun(function (c) {\n    if (++n < 2000) {\n      c.invalidate();\n    }\n  });\n  test.equal(n, 1);\n  Tracker.flush();\n  test.equal(n, 2000);\n});\n\ntestAsyncMulti('tracker - Tracker.autorun, onError option', [function (test, expect) {\n  var d = new Tracker.Dependency;\n  var c = Tracker.autorun(function (c) {\n    d.depend();\n\n    if (! c.firstRun)\n      throw new Error(\"foo\");\n  }, {\n    onError: expect(function (err) {\n      test.equal(err.message, \"foo\");\n    })\n  });\n\n  d.changed();\n  Tracker.flush();\n}]);\n\nTinytest.add('computation - #flush', function (test) {\n  var i = 0, j = 0, d = new Tracker.Dependency;\n  var c1 = Tracker.autorun(function () {\n    d.depend();\n    i = i + 1;\n  });\n  var c2 = Tracker.autorun(function () {\n    d.depend();\n    j = j + 1;\n  });\n  test.equal(i,1);\n  test.equal(j,1);\n\n  d.changed();\n  c1.flush();\n  test.equal(i, 2);\n  test.equal(j, 1);\n\n  Tracker.flush();\n  test.equal(i, 2);\n  test.equal(j, 2);\n});\n\nTinytest.add('computation - #run', function (test) {\n  var i = 0, d = new Tracker.Dependency, d2 = new Tracker.Dependency;\n  var computation = Tracker.autorun(function (c) {\n    d.depend();\n    i = i + 1;\n    //when #run() is called, this dependency should be picked up\n    if (i>=2 && i<4) { d2.depend(); }\n  });\n  test.equal(i,1);\n  computation.run();\n  test.equal(i,2);\n\n  d.changed(); Tracker.flush();\n  test.equal(i,3);\n\n  //we expect to depend on d2 at this point\n  d2.changed(); Tracker.flush();\n  test.equal(i,4);\n\n  //we no longer depend on d2, only d\n  d2.changed(); Tracker.flush();\n  test.equal(i,4);\n  d.changed(); Tracker.flush();\n  test.equal(i,5);\n});\n"
  },
  {
    "path": "packages/twitter/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/twitter/README.md",
    "content": "# twitter\n\nAn implementation of the Twitter OAuth flow. See the [project\npage](https://www.meteor.com/accounts) on Meteor Accounts for more\ndetails."
  },
  {
    "path": "packages/twitter/package.js",
    "content": "Package.describe({\n  summary: \"Twitter OAuth flow\",\n  version: '1.1.11'\n});\n\nPackage.onUse(function(api) {\n  api.use('http', ['client', 'server']);\n  api.use('templating', 'client');\n  api.use('oauth1', ['client', 'server']);\n  api.use('oauth', ['client', 'server']);\n  api.use('random', 'client');\n  api.use('underscore', 'server');\n  api.use('service-configuration', ['client', 'server']);\n\n  api.export('Twitter');\n\n  api.addFiles(\n    ['twitter_configure.html', 'twitter_configure.js'],\n    'client');\n\n  api.addFiles('twitter_server.js', 'server');\n  api.addFiles('twitter_client.js', 'client');\n});\n"
  },
  {
    "path": "packages/twitter/twitter_client.js",
    "content": "Twitter = {};\n\n// Request Twitter credentials for the user\n// @param options {optional}  XXX support options.requestPermissions\n// @param credentialRequestCompleteCallback {Function} Callback function to call on\n//   completion. Takes one argument, credentialToken on success, or Error on\n//   error.\nTwitter.requestCredential = function (options, credentialRequestCompleteCallback) {\n  // support both (options, callback) and (callback).\n  if (!credentialRequestCompleteCallback && typeof options === 'function') {\n    credentialRequestCompleteCallback = options;\n    options = {};\n  }\n\n  var config = ServiceConfiguration.configurations.findOne({service: 'twitter'});\n  if (!config) {\n    credentialRequestCompleteCallback && credentialRequestCompleteCallback(\n      new ServiceConfiguration.ConfigError());\n    return;\n  }\n\n  var credentialToken = Random.secret();\n  // We need to keep credentialToken across the next two 'steps' so we're adding\n  // a credentialToken parameter to the url and the callback url that we'll be returned\n  // to by oauth provider\n\n  var loginStyle = OAuth._loginStyle('twitter', config, options);\n\n  // url to app, enters \"step 1\" as described in\n  // packages/accounts-oauth1-helper/oauth1_server.js\n  var loginPath = '_oauth/twitter/?requestTokenAndRedirect=true'\n        + '&state=' + OAuth._stateParam(loginStyle, credentialToken, options && options.redirectUrl);\n\n  if (Meteor.isCordova) {\n    loginPath = loginPath + \"&cordova=true\";\n    if (/Android/i.test(navigator.userAgent)) {\n      loginPath = loginPath + \"&android=true\";\n    }\n  }\n\n  // Handle force login (request the user to enter their credentials)\n  if (options && options.force_login) {\n    loginPath += \"&force_login=true\";\n  }\n\n  var loginUrl = Meteor.absoluteUrl(loginPath);\n\n  OAuth.launchLogin({\n    loginService: \"twitter\",\n    loginStyle: loginStyle,\n    loginUrl: loginUrl,\n    credentialRequestCompleteCallback: credentialRequestCompleteCallback,\n    credentialToken: credentialToken\n  });\n};\n"
  },
  {
    "path": "packages/twitter/twitter_configure.html",
    "content": "<template name=\"configureLoginServiceDialogForTwitter\">\n  <p>\n    First, you'll need to register your app on Twitter. Follow these steps:\n  </p>\n  <ol>\n    <li>\n      Visit <a href=\"https://dev.twitter.com/apps/new\" target=\"_blank\">https://dev.twitter.com/apps/new</a>\n    </li>\n    <li>\n      Set Website to: <span class=\"url\">{{siteUrl}}</span>\n    </li>\n    <li>\n      Set Callback URL to: <span class=\"url\">{{siteUrl}}_oauth/twitter</span>\n    </li>\n    <li>\n      Select \"Create your Twitter application\".\n    </li>\n    <li>\n      On the Settings tab, enable \"Allow this application to be used to Sign in with Twitter\" and click\n      \"Update settings\".\n    </li>\n    <li>\n      Switch to the \"Keys and Access Tokens\" tab.\n    </li>\n  </ol>\n</template>\n"
  },
  {
    "path": "packages/twitter/twitter_configure.js",
    "content": "Template.configureLoginServiceDialogForTwitter.helpers({\n  siteUrl: function () {\n  // Twitter doesn't recognize localhost as a domain name\n    return Meteor.absoluteUrl({replaceLocalhost: true});\n  }\n});\n\nTemplate.configureLoginServiceDialogForTwitter.fields = function () {\n  return [\n    {property: 'consumerKey', label: 'API key'},\n    {property: 'secret', label: 'API secret'}\n  ];\n};\n"
  },
  {
    "path": "packages/twitter/twitter_server.js",
    "content": "Twitter = {};\n\nvar urls = {\n  requestToken: \"https://api.twitter.com/oauth/request_token\",\n  authorize: \"https://api.twitter.com/oauth/authorize\",\n  accessToken: \"https://api.twitter.com/oauth/access_token\",\n  authenticate: \"https://api.twitter.com/oauth/authenticate\"\n};\n\n\n// https://dev.twitter.com/docs/api/1.1/get/account/verify_credentials\nTwitter.whitelistedFields = ['profile_image_url', 'profile_image_url_https', 'lang', 'email'];\n\nOAuth.registerService('twitter', 1, urls, function(oauthBinding) {\n  var identity = oauthBinding.get('https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true').data;\n\n  var serviceData = {\n    id: identity.id_str,\n    screenName: identity.screen_name,\n    accessToken: OAuth.sealSecret(oauthBinding.accessToken),\n    accessTokenSecret: OAuth.sealSecret(oauthBinding.accessTokenSecret)\n  };\n\n  // include helpful fields from twitter\n  var fields = _.pick(identity, Twitter.whitelistedFields);\n  _.extend(serviceData, fields);\n\n  return {\n    serviceData: serviceData,\n    options: {\n      profile: {\n        name: identity.name\n      }\n    }\n  };\n});\n\n\nTwitter.retrieveCredential = function(credentialToken, credentialSecret) {\n  return OAuth.retrieveCredential(credentialToken, credentialSecret);\n};\n"
  },
  {
    "path": "packages/ui/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/ui/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/ui/package.js",
    "content": "Package.describe({\n  summary: \"Deprecated: Use the 'blaze' package\",\n  version: '1.0.11'\n});\n\nPackage.onUse(function (api) {\n  api.use('blaze');\n  api.imply('blaze');\n\n  // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.\n  //\n  // (in particular, packages that have a weak dependency on this\n  // package, since then exported symbols live on the\n  // `Package.ui` object)\n  api.export(['Blaze', 'UI', 'Handlebars']);\n});\n"
  },
  {
    "path": "packages/underscore/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/underscore/README.md",
    "content": "# underscore\n\nUnderscore.js is a popular library that provides various utility functions to\nsimplify processing arrays, objects and functions.\n\nTo learn more about underscore, see\n[the underscore project site](http://underscorejs.org/).\n\n"
  },
  {
    "path": "packages/underscore/package.js",
    "content": "Package.describe({\n  summary: \"Collection of small helpers: _.map, _.each, ...\",\n  version: '1.0.9'\n});\n\nPackage.onUse(function (api) {\n  // Like all packages, we have an implicit depedency on the 'meteor'\n  // package, which provides such things as the *.js file handler. Use\n  // an undocumented API to allow 'meteor' to alter us even though we\n  // depend on it. This is necessary since 'meteor' depends on us. One\n  // day we will avoid this problem by refactor, but for now this is a\n  // practical and expedient solution.\n  //\n  // XXX Now the *.js handler is intrinsic rather than coming from the\n  // 'meteor' package and we could remove this (if we provided a way\n  // to let the package opt to not depend on 'meteor'.) We could even\n  // remove unordered dependency support, though I think it's worth keeping\n  // around for now to keep the possibility of dependency\n  // configuration alive in the codebase.\n  api.use('meteor', {unordered: true});\n\n  api.export('_');\n\n  // NOTE: we patch _.each and various other functions that polymorphically take\n  // objects, arrays, and array-like objects (such as the querySelectorAll\n  // return value, document.images, and 'arguments') such that objects with a\n  // numeric length field whose constructor === Object are still treated as\n  // objects, not as arrays.  Search for looksLikeArray.\n  api.addFiles(['pre.js', 'underscore.js', 'post.js']);\n});\n\n\nPackage.onTest(function (api) {\n  // Also turn off the strong 'meteor' dependency in the test slice\n  api.use('meteor', {unordered: true});\n});\n"
  },
  {
    "path": "packages/underscore/post.js",
    "content": "// This exports object was created in pre.js.  Now copy the `_` object from it\n// into the package-scope variable `_`, which will get exported.\n_ = exports._;\n"
  },
  {
    "path": "packages/underscore/pre.js",
    "content": "// Define an object named exports. This will cause underscore.js to put `_` as a\n// field on it, instead of in the global namespace.  See also post.js.\nexports = {};\n"
  },
  {
    "path": "packages/underscore/underscore.js",
    "content": "//     Underscore.js 1.5.2\n//     http://underscorejs.org\n//     (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\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 `exports` 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\n    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.5.2';\n\n  // Collection Functions\n  // --------------------\n\n  // METEOR CHANGE: Define _isArguments instead of depending on\n  // _.isArguments which is defined using each. In looksLikeArray\n  // (which each depends on), we then use _isArguments instead of\n  // _.isArguments.\n  var _isArguments = function (obj) {\n    return toString.call(obj) === '[object Arguments]';\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 && hasOwnProperty.call(obj, 'callee') && typeof obj.callee === 'function');\n    };\n  }\n\n  // METEOR CHANGE: _.each({length: 5}) should be treated like an object, not an\n  // array. This looksLikeArray function is introduced by Meteor, and replaces\n  // all instances of `obj.length === +obj.length`.\n  // https://github.com/meteor/meteor/issues/594\n  // https://github.com/jashkenas/underscore/issues/770\n  var looksLikeArray = function (obj) {\n    return (obj.length === +obj.length\n            // _.isArguments not yet necessarily defined here\n            && (_isArguments(obj) || obj.constructor !== Object));\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 (looksLikeArray(obj)) {\n      for (var i = 0, length = obj.length; i < length; i++) {\n        if (iterator.call(context, obj[i], i, obj) === breaker) return;\n      }\n    } else {\n      var keys = _.keys(obj);\n      for (var i = 0, length = keys.length; i < length; i++) {\n        if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;\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.push(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 (!looksLikeArray(obj)) {\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.push(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 ? void 0 : [];\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 [WebKit Bug 80797](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, using the modern version of the \n  // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).\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  // Sample **n** random values from an array.\n  // If **n** is not specified, returns a single random element from the array.\n  // The internal `guard` argument allows it to work with `map`.\n  _.sample = function(obj, n, guard) {\n    if (arguments.length < 2 || guard) {\n      return obj[_.random(obj.length - 1)];\n    }\n    return _.shuffle(obj).slice(0, Math.max(0, n));\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;\n    }), 'value');\n  };\n\n  // An internal function used for aggregate \"group by\" operations.\n  var group = function(behavior) {\n    return function(obj, value, context) {\n      var result = {};\n      var iterator = value == null ? _.identity : lookupIterator(value);\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\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 = group(function(result, key, value) {\n    (_.has(result, key) ? result[key] : (result[key] = [])).push(value);\n  });\n\n  // Indexes the object's values by a criterion, similar to `groupBy`, but for\n  // when you know that your index values will be unique.\n  _.indexBy = group(function(result, key, value) {\n    result[key] = value;\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 = group(function(result, key) {\n    _.has(result, key) ? result[key]++ : result[key] = 1;\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 create a real, live array from anything iterable.\n  _.toArray = function(obj) {\n    if (!obj) return [];\n    if (_.isArray(obj)) return slice.call(obj);\n    if (looksLikeArray(obj)) 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 (looksLikeArray(obj)) ? 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 ? array[0] : slice.call(array, 0, n);\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 array[array.length - 1];\n    } else {\n      return slice.call(array, Math.max(array.length - n, 0));\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    if (shallow && _.every(input, _.isArray)) {\n      return concat.apply(output, input);\n    }\n    each(input, function(value) {\n      if (_.isArray(value) || _.isArguments(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  // Flatten out an array, either recursively (by default), or just one level.\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(_.flatten(arguments, true));\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 length = _.max(_.pluck(arguments, \"length\").concat(0));\n    var results = new Array(length);\n    for (var i = 0; i < length; i++) {\n      results[i] = _.pluck(arguments, '' + 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, length = list.length; i < length; 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, length = array.length;\n    if (isSorted) {\n      if (typeof isSorted == 'number') {\n        i = (isSorted < 0 ? Math.max(0, length + 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 < length; 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 length = Math.max(Math.ceil((stop - start) / step), 0);\n    var idx = 0;\n    var range = new Array(length);\n\n    while(idx < length) {\n      range[idx++] = start;\n      start += step;\n    }\n\n    return range;\n  };\n\n  // Function (ahem) Functions\n  // ------------------\n\n  // Reusable constructor function for prototype setting.\n  var ctor = function(){};\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    var args, bound;\n    if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));\n    if (!_.isFunction(func)) throw new TypeError;\n    args = slice.call(arguments, 2);\n    return bound = function() {\n      if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));\n      ctor.prototype = func.prototype;\n      var self = new ctor;\n      ctor.prototype = null;\n      var result = func.apply(self, args.concat(slice.call(arguments)));\n      if (Object(result) === result) return result;\n      return self;\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) throw new Error(\"bindAll must be passed function names\");\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. Normally, the throttled function will run\n  // as much as it can, without ever going more than once per `wait` duration;\n  // but if you'd like to disable the execution on the leading edge, pass\n  // `{leading: false}`. To disable execution on the trailing edge, ditto.\n  _.throttle = function(func, wait, options) {\n    var context, args, result;\n    var timeout = null;\n    var previous = 0;\n    options || (options = {});\n    var later = function() {\n      previous = options.leading === false ? 0 : new Date;\n      timeout = null;\n      result = func.apply(context, args);\n    };\n    return function() {\n      var now = new Date;\n      if (!previous && options.leading === false) previous = now;\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 && options.trailing !== false) {\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, args, context, timestamp, result;\n    return function() {\n      context = this;\n      args = arguments;\n      timestamp = new Date();\n      var later = function() {\n        var last = (new Date()) - timestamp;\n        if (last < wait) {\n          timeout = setTimeout(later, wait - last);\n        } else {\n          timeout = null;\n          if (!immediate) result = func.apply(context, args);\n        }\n      };\n      var callNow = immediate && !timeout;\n      if (!timeout) {\n        timeout = setTimeout(later, wait);\n      }\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    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.push(key);\n    return keys;\n  };\n\n  // Retrieve the values of an object's properties.\n  _.values = function(obj) {\n    var keys = _.keys(obj);\n    var length = keys.length;\n    var values = new Array(length);\n    for (var i = 0; i < length; i++) {\n      values[i] = obj[keys[i]];\n    }\n    return values;\n  };\n\n  // Convert an object into a list of `[key, value]` pairs.\n  _.pairs = function(obj) {\n    var keys = _.keys(obj);\n    var length = keys.length;\n    var pairs = new Array(length);\n    for (var i = 0; i < length; i++) {\n      pairs[i] = [keys[i], obj[keys[i]]];\n    }\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    var keys = _.keys(obj);\n    for (var i = 0, length = keys.length; i < length; i++) {\n      result[obj[keys[i]]] = keys[i];\n    }\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] === void 0) 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    // 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    // 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      // 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(Math.max(0, 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    }\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 with the\n  // `object` as context; otherwise, return it.\n  _.result = function(object, property) {\n    if (object == null) return void 0;\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"
  },
  {
    "path": "packages/underscore-tests/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/underscore-tests/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/underscore-tests/each_test.js",
    "content": "Tinytest.add(\"underscore-tests - each\", function (test) {\n  // arrays\n  _.each([42], function (val, index) {\n    test.equal(index, 0);\n    test.equal(val, 42);\n  });\n\n  // objects with 'length' field aren't treated as arrays\n  _.each({length: 42}, function (val, key) {\n    test.equal(key, 'length');\n    test.equal(val, 42);\n  });\n\n  // The special 'arguments' variable is treated as an\n  // array\n  (function () {\n    _.each(arguments, function (val, index) {\n      test.equal(index, 0);\n      test.equal(val, 42);\n    });\n  })(42);\n\n  // An object with a 'callee' field isn't treated as arguments\n  _.each({callee: 42}, function (val, key) {\n    test.equal(key, 'callee');\n    test.equal(val, 42);\n  });\n\n  // An object with a 'callee' field isn't treated as arguments\n  _.each({length: 4, callee: 42}, function (val, key) {\n    if (key === 'callee')\n      test.equal(val, 42);\n    else if (key === 'length')\n      test.equal(val, 4);\n    else\n      test.fail({message: 'unexpected key: ' + key});\n  });\n\n\n  // NOTE: An object with a numberic 'length' field *and* a function\n  // 'callee' field will be treated as an array in IE. This may or may\n  // not be fixable, but isn't a big deal since: (1) 'callee' is a\n  // pretty rare key, and (2) JSON objects can't have functions\n  // anyways, which is the main use-case for _.each.\n});\n"
  },
  {
    "path": "packages/underscore-tests/package.js",
    "content": "Package.describe({\n  // These tests can't be directly in the underscore packages since\n  // Tinytest depends on underscore\n  summary: \"Tests for the underscore package\",\n  version: '1.0.8'\n});\n\nPackage.onTest(function (api) {\n  api.use(['tinytest', 'underscore']);\n  api.addFiles('each_test.js');\n});\n"
  },
  {
    "path": "packages/url/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/url/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/url/package.js",
    "content": "Package.describe({\n  summary: \"Utility code for constructing URLs\",\n  version: \"1.0.10\"\n});\n\nPackage.onUse(function(api) {\n  api.export('URL');\n  api.use('underscore', ['client', 'server']);\n  api.addFiles('url_common.js', ['client', 'server']);\n  api.addFiles('url_client.js', 'client');\n  api.addFiles('url_server.js', 'server');\n});\n\n// tests are in the http package\n"
  },
  {
    "path": "packages/url/url_client.js",
    "content": "URL._constructUrl = function (url, query, params) {\n  var query_match = /^(.*?)(\\?.*)?$/.exec(url);\n  return buildUrl(query_match[1], query_match[2], query, params);\n};\n"
  },
  {
    "path": "packages/url/url_common.js",
    "content": "URL = {};\n\nvar encodeString = function(str) {\n  return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\\*/g, \"%2A\");\n};\n\n\nURL._encodeParams = function(params) {\n  var buf = [];\n  _.each(params, function(value, key) {\n    if (buf.length)\n      buf.push('&');\n    buf.push(encodeString(key), '=', encodeString(value));\n  });\n  return buf.join('').replace(/%20/g, '+');\n};\n\n\nbuildUrl = function(before_qmark, from_qmark, opt_query, opt_params) {\n  var url_without_query = before_qmark;\n  var query = from_qmark ? from_qmark.slice(1) : null;\n\n  if (typeof opt_query === \"string\")\n    query = String(opt_query);\n\n  if (opt_params) {\n    query = query || \"\";\n    var prms = URL._encodeParams(opt_params);\n    if (query && prms)\n      query += '&';\n    query += prms;\n  }\n\n  var url = url_without_query;\n  if (query !== null)\n    url += (\"?\"+query);\n\n  return url;\n};\n"
  },
  {
    "path": "packages/url/url_server.js",
    "content": "var url_util = Npm.require('url');\n\nURL._constructUrl = function (url, query, params) {\n  var url_parts = url_util.parse(url);\n  return buildUrl(\n    url_parts.protocol + \"//\" + url_parts.host + url_parts.pathname,\n    url_parts.search, query, params);\n};\n"
  },
  {
    "path": "packages/webapp/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/webapp/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/webapp/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/webapp/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"connect\": {\n      \"version\": \"2.30.2\",\n      \"resolved\": \"https://registry.npmjs.org/connect/-/connect-2.30.2.tgz\",\n      \"from\": \"https://registry.npmjs.org/connect/-/connect-2.30.2.tgz\",\n      \"dependencies\": {\n        \"basic-auth-connect\": {\n          \"version\": \"1.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz\"\n        },\n        \"body-parser\": {\n          \"version\": \"1.13.3\",\n          \"resolved\": \"https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz\",\n          \"from\": \"https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz\",\n          \"dependencies\": {\n            \"iconv-lite\": {\n              \"version\": \"0.4.11\",\n              \"resolved\": \"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz\",\n              \"from\": \"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz\"\n            },\n            \"on-finished\": {\n              \"version\": \"2.3.0\",\n              \"resolved\": \"https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz\",\n              \"dependencies\": {\n                \"ee-first\": {\n                  \"version\": \"1.1.1\",\n                  \"resolved\": \"https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz\"\n                }\n              }\n            },\n            \"raw-body\": {\n              \"version\": \"2.1.5\",\n              \"resolved\": \"https://registry.npmjs.org/raw-body/-/raw-body-2.1.5.tgz\",\n              \"from\": \"https://registry.npmjs.org/raw-body/-/raw-body-2.1.5.tgz\",\n              \"dependencies\": {\n                \"bytes\": {\n                  \"version\": \"2.2.0\",\n                  \"resolved\": \"https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz\"\n                },\n                \"iconv-lite\": {\n                  \"version\": \"0.4.13\",\n                  \"resolved\": \"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz\",\n                  \"from\": \"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz\"\n                },\n                \"unpipe\": {\n                  \"version\": \"1.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz\"\n                }\n              }\n            }\n          }\n        },\n        \"bytes\": {\n          \"version\": \"2.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz\"\n        },\n        \"compression\": {\n          \"version\": \"1.5.2\",\n          \"resolved\": \"https://registry.npmjs.org/compression/-/compression-1.5.2.tgz\",\n          \"from\": \"https://registry.npmjs.org/compression/-/compression-1.5.2.tgz\",\n          \"dependencies\": {\n            \"accepts\": {\n              \"version\": \"1.2.13\",\n              \"resolved\": \"https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz\",\n              \"from\": \"https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz\",\n              \"dependencies\": {\n                \"mime-types\": {\n                  \"version\": \"2.1.9\",\n                  \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz\",\n                  \"from\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz\",\n                  \"dependencies\": {\n                    \"mime-db\": {\n                      \"version\": \"1.21.0\",\n                      \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz\",\n                      \"from\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz\"\n                    }\n                  }\n                },\n                \"negotiator\": {\n                  \"version\": \"0.5.3\",\n                  \"resolved\": \"https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz\",\n                  \"from\": \"https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz\"\n                }\n              }\n            },\n            \"compressible\": {\n              \"version\": \"2.0.6\",\n              \"resolved\": \"https://registry.npmjs.org/compressible/-/compressible-2.0.6.tgz\",\n              \"from\": \"https://registry.npmjs.org/compressible/-/compressible-2.0.6.tgz\",\n              \"dependencies\": {\n                \"mime-db\": {\n                  \"version\": \"1.21.0\",\n                  \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz\"\n                }\n              }\n            },\n            \"vary\": {\n              \"version\": \"1.0.1\",\n              \"resolved\": \"https://registry.npmjs.org/vary/-/vary-1.0.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/vary/-/vary-1.0.1.tgz\"\n            }\n          }\n        },\n        \"connect-timeout\": {\n          \"version\": \"1.6.2\",\n          \"resolved\": \"https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz\",\n          \"from\": \"https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz\",\n          \"dependencies\": {\n            \"ms\": {\n              \"version\": \"0.7.1\",\n              \"resolved\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\"\n            }\n          }\n        },\n        \"content-type\": {\n          \"version\": \"1.0.1\",\n          \"resolved\": \"https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz\"\n        },\n        \"cookie\": {\n          \"version\": \"0.1.3\",\n          \"resolved\": \"https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz\",\n          \"from\": \"https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz\"\n        },\n        \"cookie-parser\": {\n          \"version\": \"1.3.5\",\n          \"resolved\": \"https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz\",\n          \"from\": \"https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz\"\n        },\n        \"cookie-signature\": {\n          \"version\": \"1.0.6\",\n          \"resolved\": \"https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz\",\n          \"from\": \"https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz\"\n        },\n        \"csurf\": {\n          \"version\": \"1.8.3\",\n          \"resolved\": \"https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz\",\n          \"from\": \"https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz\",\n          \"dependencies\": {\n            \"csrf\": {\n              \"version\": \"3.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/csrf/-/csrf-3.0.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/csrf/-/csrf-3.0.0.tgz\",\n              \"dependencies\": {\n                \"base64-url\": {\n                  \"version\": \"1.2.1\",\n                  \"resolved\": \"https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz\"\n                },\n                \"rndm\": {\n                  \"version\": \"1.1.1\",\n                  \"resolved\": \"https://registry.npmjs.org/rndm/-/rndm-1.1.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/rndm/-/rndm-1.1.1.tgz\"\n                },\n                \"scmp\": {\n                  \"version\": \"1.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/scmp/-/scmp-1.0.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/scmp/-/scmp-1.0.0.tgz\"\n                },\n                \"uid-safe\": {\n                  \"version\": \"2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz\"\n                }\n              }\n            }\n          }\n        },\n        \"debug\": {\n          \"version\": \"2.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/debug/-/debug-2.2.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/debug/-/debug-2.2.0.tgz\",\n          \"dependencies\": {\n            \"ms\": {\n              \"version\": \"0.7.1\",\n              \"resolved\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\"\n            }\n          }\n        },\n        \"depd\": {\n          \"version\": \"1.0.1\",\n          \"resolved\": \"https://registry.npmjs.org/depd/-/depd-1.0.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/depd/-/depd-1.0.1.tgz\"\n        },\n        \"errorhandler\": {\n          \"version\": \"1.4.2\",\n          \"resolved\": \"https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.2.tgz\",\n          \"from\": \"https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.2.tgz\",\n          \"dependencies\": {\n            \"accepts\": {\n              \"version\": \"1.2.13\",\n              \"resolved\": \"https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz\",\n              \"from\": \"https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz\",\n              \"dependencies\": {\n                \"mime-types\": {\n                  \"version\": \"2.1.9\",\n                  \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz\",\n                  \"from\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz\",\n                  \"dependencies\": {\n                    \"mime-db\": {\n                      \"version\": \"1.21.0\",\n                      \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz\",\n                      \"from\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz\"\n                    }\n                  }\n                },\n                \"negotiator\": {\n                  \"version\": \"0.5.3\",\n                  \"resolved\": \"https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz\",\n                  \"from\": \"https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz\"\n                }\n              }\n            },\n            \"escape-html\": {\n              \"version\": \"1.0.2\",\n              \"resolved\": \"https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz\",\n              \"from\": \"https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz\"\n            }\n          }\n        },\n        \"express-session\": {\n          \"version\": \"1.11.3\",\n          \"resolved\": \"https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz\",\n          \"from\": \"https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz\",\n          \"dependencies\": {\n            \"crc\": {\n              \"version\": \"3.3.0\",\n              \"resolved\": \"https://registry.npmjs.org/crc/-/crc-3.3.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/crc/-/crc-3.3.0.tgz\"\n            },\n            \"uid-safe\": {\n              \"version\": \"2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz\",\n              \"dependencies\": {\n                \"base64-url\": {\n                  \"version\": \"1.2.1\",\n                  \"resolved\": \"https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz\"\n                }\n              }\n            }\n          }\n        },\n        \"finalhandler\": {\n          \"version\": \"0.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz\",\n          \"dependencies\": {\n            \"escape-html\": {\n              \"version\": \"1.0.2\",\n              \"resolved\": \"https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz\",\n              \"from\": \"https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz\"\n            },\n            \"on-finished\": {\n              \"version\": \"2.3.0\",\n              \"resolved\": \"https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz\",\n              \"dependencies\": {\n                \"ee-first\": {\n                  \"version\": \"1.1.1\",\n                  \"resolved\": \"https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz\"\n                }\n              }\n            },\n            \"unpipe\": {\n              \"version\": \"1.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz\"\n            }\n          }\n        },\n        \"fresh\": {\n          \"version\": \"0.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz\"\n        },\n        \"http-errors\": {\n          \"version\": \"1.3.1\",\n          \"resolved\": \"https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz\",\n          \"dependencies\": {\n            \"inherits\": {\n              \"version\": \"2.0.1\",\n              \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\"\n            },\n            \"statuses\": {\n              \"version\": \"1.2.1\",\n              \"resolved\": \"https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz\"\n            }\n          }\n        },\n        \"method-override\": {\n          \"version\": \"2.3.5\",\n          \"resolved\": \"https://registry.npmjs.org/method-override/-/method-override-2.3.5.tgz\",\n          \"from\": \"https://registry.npmjs.org/method-override/-/method-override-2.3.5.tgz\",\n          \"dependencies\": {\n            \"methods\": {\n              \"version\": \"1.1.1\",\n              \"resolved\": \"https://registry.npmjs.org/methods/-/methods-1.1.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/methods/-/methods-1.1.1.tgz\"\n            },\n            \"vary\": {\n              \"version\": \"1.0.1\",\n              \"resolved\": \"https://registry.npmjs.org/vary/-/vary-1.0.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/vary/-/vary-1.0.1.tgz\"\n            }\n          }\n        },\n        \"morgan\": {\n          \"version\": \"1.6.1\",\n          \"resolved\": \"https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz\",\n          \"dependencies\": {\n            \"basic-auth\": {\n              \"version\": \"1.0.3\",\n              \"resolved\": \"https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.3.tgz\",\n              \"from\": \"https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.3.tgz\"\n            },\n            \"on-finished\": {\n              \"version\": \"2.3.0\",\n              \"resolved\": \"https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz\",\n              \"dependencies\": {\n                \"ee-first\": {\n                  \"version\": \"1.1.1\",\n                  \"resolved\": \"https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz\"\n                }\n              }\n            }\n          }\n        },\n        \"multiparty\": {\n          \"version\": \"3.3.2\",\n          \"resolved\": \"https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz\",\n          \"from\": \"https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz\",\n          \"dependencies\": {\n            \"readable-stream\": {\n              \"version\": \"1.1.13\",\n              \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz\",\n              \"from\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz\",\n              \"dependencies\": {\n                \"core-util-is\": {\n                  \"version\": \"1.0.2\",\n                  \"resolved\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz\",\n                  \"from\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz\"\n                },\n                \"inherits\": {\n                  \"version\": \"2.0.1\",\n                  \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\"\n                },\n                \"isarray\": {\n                  \"version\": \"0.0.1\",\n                  \"resolved\": \"https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz\",\n                  \"from\": \"https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz\"\n                },\n                \"string_decoder\": {\n                  \"version\": \"0.10.31\",\n                  \"resolved\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\",\n                  \"from\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\"\n                }\n              }\n            },\n            \"stream-counter\": {\n              \"version\": \"0.2.0\",\n              \"resolved\": \"https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz\"\n            }\n          }\n        },\n        \"on-headers\": {\n          \"version\": \"1.0.1\",\n          \"resolved\": \"https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz\"\n        },\n        \"pause\": {\n          \"version\": \"0.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/pause/-/pause-0.1.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/pause/-/pause-0.1.0.tgz\"\n        },\n        \"qs\": {\n          \"version\": \"4.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/qs/-/qs-4.0.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/qs/-/qs-4.0.0.tgz\"\n        },\n        \"response-time\": {\n          \"version\": \"2.3.1\",\n          \"resolved\": \"https://registry.npmjs.org/response-time/-/response-time-2.3.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/response-time/-/response-time-2.3.1.tgz\"\n        },\n        \"serve-favicon\": {\n          \"version\": \"2.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.0.tgz\",\n          \"dependencies\": {\n            \"etag\": {\n              \"version\": \"1.7.0\",\n              \"resolved\": \"https://registry.npmjs.org/etag/-/etag-1.7.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/etag/-/etag-1.7.0.tgz\"\n            },\n            \"ms\": {\n              \"version\": \"0.7.1\",\n              \"resolved\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\"\n            }\n          }\n        },\n        \"serve-index\": {\n          \"version\": \"1.7.2\",\n          \"resolved\": \"https://registry.npmjs.org/serve-index/-/serve-index-1.7.2.tgz\",\n          \"from\": \"https://registry.npmjs.org/serve-index/-/serve-index-1.7.2.tgz\",\n          \"dependencies\": {\n            \"accepts\": {\n              \"version\": \"1.2.13\",\n              \"resolved\": \"https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz\",\n              \"from\": \"https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz\",\n              \"dependencies\": {\n                \"negotiator\": {\n                  \"version\": \"0.5.3\",\n                  \"resolved\": \"https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz\",\n                  \"from\": \"https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz\"\n                }\n              }\n            },\n            \"batch\": {\n              \"version\": \"0.5.2\",\n              \"resolved\": \"https://registry.npmjs.org/batch/-/batch-0.5.2.tgz\",\n              \"from\": \"https://registry.npmjs.org/batch/-/batch-0.5.2.tgz\"\n            },\n            \"escape-html\": {\n              \"version\": \"1.0.2\",\n              \"resolved\": \"https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz\",\n              \"from\": \"https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz\"\n            },\n            \"mime-types\": {\n              \"version\": \"2.1.9\",\n              \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz\",\n              \"from\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz\",\n              \"dependencies\": {\n                \"mime-db\": {\n                  \"version\": \"1.21.0\",\n                  \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz\"\n                }\n              }\n            }\n          }\n        },\n        \"serve-static\": {\n          \"version\": \"1.10.0\",\n          \"resolved\": \"https://registry.npmjs.org/serve-static/-/serve-static-1.10.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/serve-static/-/serve-static-1.10.0.tgz\",\n          \"dependencies\": {\n            \"escape-html\": {\n              \"version\": \"1.0.2\",\n              \"resolved\": \"https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz\",\n              \"from\": \"https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz\"\n            }\n          }\n        },\n        \"type-is\": {\n          \"version\": \"1.6.10\",\n          \"resolved\": \"https://registry.npmjs.org/type-is/-/type-is-1.6.10.tgz\",\n          \"from\": \"https://registry.npmjs.org/type-is/-/type-is-1.6.10.tgz\",\n          \"dependencies\": {\n            \"media-typer\": {\n              \"version\": \"0.3.0\",\n              \"resolved\": \"https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz\",\n              \"from\": \"https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz\"\n            },\n            \"mime-types\": {\n              \"version\": \"2.1.9\",\n              \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz\",\n              \"from\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz\",\n              \"dependencies\": {\n                \"mime-db\": {\n                  \"version\": \"1.21.0\",\n                  \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz\",\n                  \"from\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz\"\n                }\n              }\n            }\n          }\n        },\n        \"utils-merge\": {\n          \"version\": \"1.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz\"\n        },\n        \"vhost\": {\n          \"version\": \"3.0.2\",\n          \"resolved\": \"https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz\",\n          \"from\": \"https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz\"\n        }\n      }\n    },\n    \"parseurl\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz\",\n      \"from\": \"https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz\"\n    },\n    \"send\": {\n      \"version\": \"0.13.0\",\n      \"resolved\": \"https://registry.npmjs.org/send/-/send-0.13.0.tgz\",\n      \"from\": \"https://registry.npmjs.org/send/-/send-0.13.0.tgz\",\n      \"dependencies\": {\n        \"debug\": {\n          \"version\": \"2.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/debug/-/debug-2.2.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/debug/-/debug-2.2.0.tgz\"\n        },\n        \"depd\": {\n          \"version\": \"1.0.1\",\n          \"resolved\": \"https://registry.npmjs.org/depd/-/depd-1.0.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/depd/-/depd-1.0.1.tgz\"\n        },\n        \"destroy\": {\n          \"version\": \"1.0.3\",\n          \"resolved\": \"https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz\",\n          \"from\": \"https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz\"\n        },\n        \"escape-html\": {\n          \"version\": \"1.0.2\",\n          \"resolved\": \"https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz\",\n          \"from\": \"https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz\"\n        },\n        \"etag\": {\n          \"version\": \"1.7.0\",\n          \"resolved\": \"https://registry.npmjs.org/etag/-/etag-1.7.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/etag/-/etag-1.7.0.tgz\"\n        },\n        \"fresh\": {\n          \"version\": \"0.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz\"\n        },\n        \"http-errors\": {\n          \"version\": \"1.3.1\",\n          \"resolved\": \"https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz\",\n          \"dependencies\": {\n            \"inherits\": {\n              \"version\": \"2.0.1\",\n              \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\"\n            }\n          }\n        },\n        \"mime\": {\n          \"version\": \"1.3.4\",\n          \"resolved\": \"https://registry.npmjs.org/mime/-/mime-1.3.4.tgz\",\n          \"from\": \"https://registry.npmjs.org/mime/-/mime-1.3.4.tgz\"\n        },\n        \"ms\": {\n          \"version\": \"0.7.1\",\n          \"resolved\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\"\n        },\n        \"on-finished\": {\n          \"version\": \"2.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz\",\n          \"from\": \"https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz\",\n          \"dependencies\": {\n            \"ee-first\": {\n              \"version\": \"1.1.1\",\n              \"resolved\": \"https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz\",\n              \"from\": \"https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz\"\n            }\n          }\n        },\n        \"range-parser\": {\n          \"version\": \"1.0.3\",\n          \"resolved\": \"https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz\",\n          \"from\": \"https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz\"\n        },\n        \"statuses\": {\n          \"version\": \"1.2.1\",\n          \"resolved\": \"https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz\"\n        }\n      }\n    },\n    \"useragent\": {\n      \"version\": \"2.0.7\",\n      \"resolved\": \"https://registry.npmjs.org/useragent/-/useragent-2.0.7.tgz\",\n      \"from\": \"https://registry.npmjs.org/useragent/-/useragent-2.0.7.tgz\",\n      \"dependencies\": {\n        \"lru-cache\": {\n          \"version\": \"2.2.4\",\n          \"resolved\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz\",\n          \"from\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/webapp/README.md",
    "content": "# webapp\n\nThe `webapp` package contains the core functionality that makes a\nMeteor project into a web application. It is a \"value added HTTP\nserver\" that includes not just a web server, but also advanced app\nserving functionality like over-the-air mobile app updates and HTML5\nAppcache support. For more information, see the [Webapp project\npage](https://www.meteor.com/webapp).\n\n\n## Direct access to connect mongodb API\n\nThe `webapp` package is implemented using the\n[npm `connect` module](https://www.npmjs.com/package/connect).  `webapp` exposes\nthe connect API for handling requests through `Webapp.connectHandlers`.  See\nhttps://docs.meteor.com/#/full/webapp for more details\n\nIf you'd like direct access to the connect module (for example, to use one of\nthe middleware handlers that it defines), you can find it at\n`WebAppInternals.NpmModules.connect.module`. Its version can be read at\n`WebAppInternals.NpmModules.connect.version`.\n\nThe version of `connect` used may change incompatibly from version to version of\nMeteor (or we may even replace it with an entirely different implementation);\nuse at your own risk.\n"
  },
  {
    "path": "packages/webapp/package.js",
    "content": "Package.describe({\n  summary: \"Serves a Meteor app over HTTP\",\n  version: '1.2.9_1'\n});\n\nNpm.depends({connect: \"2.30.2\",\n             parseurl: \"1.3.0\",\n             send: \"0.13.0\",\n             useragent: \"2.0.7\"});\n\nNpm.strip({\n  multiparty: [\"test/\"],\n  useragent: [\"test/\"]\n});\n\nCordova.depends({\n  'cordova-plugin-whitelist': '1.2.1',\n  'cordova-plugin-wkwebview-engine': '1.0.2',\n  'cordova-plugin-meteor-webapp': '1.3.0'\n});\n\nPackage.onUse(function (api) {\n  api.use('ecmascript');\n  api.use(['logging', 'underscore', 'routepolicy', 'boilerplate-generator',\n           'webapp-hashing'], 'server');\n  api.use(['underscore'], 'client');\n\n  // At response serving time, webapp uses browser-policy if it is loaded. If\n  // browser-policy is loaded, then it must be loaded after webapp\n  // (browser-policy depends on webapp). So we don't explicitly depend in any\n  // way on browser-policy here, but we use it when it is loaded, and it can be\n  // loaded after webapp.\n  api.export(['WebApp', 'main', 'WebAppInternals'], 'server');\n  api.export(['WebApp'], 'client');\n  api.addFiles('webapp_server.js', 'server');\n  api.addFiles('webapp_client.js', 'client');\n  api.addFiles('webapp_cordova.js', 'web.cordova');\n});\n\nPackage.onTest(function (api) {\n  api.use(['tinytest', 'webapp', 'http', 'underscore']);\n  api.addFiles('webapp_tests.js', 'server');\n  api.addFiles('webapp_client_tests.js', 'client');\n});\n"
  },
  {
    "path": "packages/webapp/webapp_client.js",
    "content": "WebApp = {\n\n  _isCssLoaded: function () {\n    if (document.styleSheets.length === 0)\n      return true;\n\n    return _.find(document.styleSheets, function (sheet) {\n      if (sheet.cssText && !sheet.cssRules) // IE8\n        return !sheet.cssText.match(/meteor-css-not-found-error/);\n      return !_.find(sheet.cssRules, function (rule) {\n        return rule.selectorText === '.meteor-css-not-found-error';\n      });\n    });\n  }\n};\n"
  },
  {
    "path": "packages/webapp/webapp_client_tests.js",
    "content": "// Regression test for #3730\nTinytest.add(\"webapp - runtime config\", function (test) {\n  test.equal(__meteor_runtime_config__.WEBAPP_TEST_A, '<p>foo</p>');\n  test.equal(__meteor_runtime_config__.WEBAPP_TEST_B, '</script>');\n});\n"
  },
  {
    "path": "packages/webapp/webapp_cordova.js",
    "content": "Meteor.startup(() => {\n  WebAppLocalServer.onError((error) => {\n    console.error(error);\n  });\n});\n"
  },
  {
    "path": "packages/webapp/webapp_server.js",
    "content": "////////// Requires //////////\n\nvar fs = Npm.require(\"fs\");\nvar http = Npm.require(\"http\");\nvar os = Npm.require(\"os\");\nvar path = Npm.require(\"path\");\nvar url = Npm.require(\"url\");\nvar crypto = Npm.require(\"crypto\");\n\nvar connect = Npm.require('connect');\nvar parseurl = Npm.require('parseurl');\nvar useragent = Npm.require('useragent');\nvar send = Npm.require('send');\n\nvar Future = Npm.require('fibers/future');\nvar Fiber = Npm.require('fibers');\n\nvar SHORT_SOCKET_TIMEOUT = 5*1000;\nvar LONG_SOCKET_TIMEOUT = 120*1000;\n\nWebApp = {};\nWebAppInternals = {};\n\nWebAppInternals.NpmModules = {\n  connect: {\n    version: Npm.require('connect/package.json').version,\n    module: connect\n  }\n};\n\nWebApp.defaultArch = 'web.browser';\n\n// XXX maps archs to manifests\nWebApp.clientPrograms = {};\n\n// XXX maps archs to program path on filesystem\nvar archPath = {};\n\nvar bundledJsCssUrlRewriteHook;\n\nvar sha1 = function (contents) {\n  var hash = crypto.createHash('sha1');\n  hash.update(contents);\n  return hash.digest('hex');\n};\n\nvar readUtf8FileSync = function (filename) {\n  return Meteor.wrapAsync(fs.readFile)(filename, 'utf8');\n};\n\n// #BrowserIdentification\n//\n// We have multiple places that want to identify the browser: the\n// unsupported browser page, the appcache package, and, eventually\n// delivering browser polyfills only as needed.\n//\n// To avoid detecting the browser in multiple places ad-hoc, we create a\n// Meteor \"browser\" object. It uses but does not expose the npm\n// useragent module (we could choose a different mechanism to identify\n// the browser in the future if we wanted to).  The browser object\n// contains\n//\n// * `name`: the name of the browser in camel case\n// * `major`, `minor`, `patch`: integers describing the browser version\n//\n// Also here is an early version of a Meteor `request` object, intended\n// to be a high-level description of the request without exposing\n// details of connect's low-level `req`.  Currently it contains:\n//\n// * `browser`: browser identification object described above\n// * `url`: parsed url, including parsed query params\n//\n// As a temporary hack there is a `categorizeRequest` function on WebApp which\n// converts a connect `req` to a Meteor `request`. This can go away once smart\n// packages such as appcache are being passed a `request` object directly when\n// they serve content.\n//\n// This allows `request` to be used uniformly: it is passed to the html\n// attributes hook, and the appcache package can use it when deciding\n// whether to generate a 404 for the manifest.\n//\n// Real routing / server side rendering will probably refactor this\n// heavily.\n\n\n// e.g. \"Mobile Safari\" => \"mobileSafari\"\nvar camelCase = function (name) {\n  var parts = name.split(' ');\n  parts[0] = parts[0].toLowerCase();\n  for (var i = 1;  i < parts.length;  ++i) {\n    parts[i] = parts[i].charAt(0).toUpperCase() + parts[i].substr(1);\n  }\n  return parts.join('');\n};\n\nvar identifyBrowser = function (userAgentString) {\n  var userAgent = useragent.lookup(userAgentString);\n  return {\n    name: camelCase(userAgent.family),\n    major: +userAgent.major,\n    minor: +userAgent.minor,\n    patch: +userAgent.patch\n  };\n};\n\n// XXX Refactor as part of implementing real routing.\nWebAppInternals.identifyBrowser = identifyBrowser;\n\nWebApp.categorizeRequest = function (req) {\n  return _.extend({\n    browser: identifyBrowser(req.headers['user-agent']),\n    url: url.parse(req.url, true)\n  }, _.pick(req, 'dynamicHead', 'dynamicBody'));\n};\n\n// HTML attribute hooks: functions to be called to determine any attributes to\n// be added to the '<html>' tag. Each function is passed a 'request' object (see\n// #BrowserIdentification) and should return null or object.\nvar htmlAttributeHooks = [];\nvar getHtmlAttributes = function (request) {\n  var combinedAttributes  = {};\n  _.each(htmlAttributeHooks || [], function (hook) {\n    var attributes = hook(request);\n    if (attributes === null)\n      return;\n    if (typeof attributes !== 'object')\n      throw Error(\"HTML attribute hook must return null or object\");\n    _.extend(combinedAttributes, attributes);\n  });\n  return combinedAttributes;\n};\nWebApp.addHtmlAttributeHook = function (hook) {\n  htmlAttributeHooks.push(hook);\n};\n\n// Serve app HTML for this URL?\nvar appUrl = function (url) {\n  if (url === '/favicon.ico' || url === '/robots.txt')\n    return false;\n\n  // NOTE: app.manifest is not a web standard like favicon.ico and\n  // robots.txt. It is a file name we have chosen to use for HTML5\n  // appcache URLs. It is included here to prevent using an appcache\n  // then removing it from poisoning an app permanently. Eventually,\n  // once we have server side routing, this won't be needed as\n  // unknown URLs with return a 404 automatically.\n  if (url === '/app.manifest')\n    return false;\n\n  // Avoid serving app HTML for declared routes such as /sockjs/.\n  if (RoutePolicy.classify(url))\n    return false;\n\n  // we currently return app HTML on all URLs by default\n  return true;\n};\n\n\n// We need to calculate the client hash after all packages have loaded\n// to give them a chance to populate __meteor_runtime_config__.\n//\n// Calculating the hash during startup means that packages can only\n// populate __meteor_runtime_config__ during load, not during startup.\n//\n// Calculating instead it at the beginning of main after all startup\n// hooks had run would allow packages to also populate\n// __meteor_runtime_config__ during startup, but that's too late for\n// autoupdate because it needs to have the client hash at startup to\n// insert the auto update version itself into\n// __meteor_runtime_config__ to get it to the client.\n//\n// An alternative would be to give autoupdate a \"post-start,\n// pre-listen\" hook to allow it to insert the auto update version at\n// the right moment.\n\nMeteor.startup(function () {\n  var calculateClientHash = WebAppHashing.calculateClientHash;\n  WebApp.clientHash = function (archName) {\n    archName = archName || WebApp.defaultArch;\n    return calculateClientHash(WebApp.clientPrograms[archName].manifest);\n  };\n\n  WebApp.calculateClientHashRefreshable = function (archName) {\n    archName = archName || WebApp.defaultArch;\n    return calculateClientHash(WebApp.clientPrograms[archName].manifest,\n      function (name) {\n        return name === \"css\";\n      });\n  };\n  WebApp.calculateClientHashNonRefreshable = function (archName) {\n    archName = archName || WebApp.defaultArch;\n    return calculateClientHash(WebApp.clientPrograms[archName].manifest,\n      function (name) {\n        return name !== \"css\";\n      });\n  };\n  WebApp.calculateClientHashCordova = function () {\n    var archName = 'web.cordova';\n    if (! WebApp.clientPrograms[archName])\n      return 'none';\n\n    return calculateClientHash(\n      WebApp.clientPrograms[archName].manifest, null, _.pick(\n        __meteor_runtime_config__, 'PUBLIC_SETTINGS'));\n  };\n});\n\n\n\n// When we have a request pending, we want the socket timeout to be long, to\n// give ourselves a while to serve it, and to allow sockjs long polls to\n// complete.  On the other hand, we want to close idle sockets relatively\n// quickly, so that we can shut down relatively promptly but cleanly, without\n// cutting off anyone's response.\nWebApp._timeoutAdjustmentRequestCallback = function (req, res) {\n  // this is really just req.socket.setTimeout(LONG_SOCKET_TIMEOUT);\n  req.setTimeout(LONG_SOCKET_TIMEOUT);\n  // Insert our new finish listener to run BEFORE the existing one which removes\n  // the response from the socket.\n  var finishListeners = res.listeners('finish');\n  // XXX Apparently in Node 0.12 this event is now called 'prefinish'.\n  // https://github.com/joyent/node/commit/7c9b6070\n  res.removeAllListeners('finish');\n  res.on('finish', function () {\n    res.setTimeout(SHORT_SOCKET_TIMEOUT);\n  });\n  _.each(finishListeners, function (l) { res.on('finish', l); });\n};\n\n\n// Will be updated by main before we listen.\n// Map from client arch to boilerplate object.\n// Boilerplate object has:\n//   - func: XXX\n//   - baseData: XXX\nvar boilerplateByArch = {};\n\n// Given a request (as returned from `categorizeRequest`), return the\n// boilerplate HTML to serve for that request.\n//\n// If a previous connect middleware has rendered content for the head or body,\n// returns the boilerplate with that content patched in otherwise\n// memoizes on HTML attributes (used by, eg, appcache) and whether inline \n// scripts are currently allowed.\n// XXX so far this function is always called with arch === 'web.browser'\nvar memoizedBoilerplate = {};\nvar getBoilerplate = function (request, arch) {\n  var useMemoized = ! (request.dynamicHead || request.dynamicBody);\n  var htmlAttributes = getHtmlAttributes(request);\n  \n  if (useMemoized) {\n    // The only thing that changes from request to request (unless extra \n    // content is added to the head or body) are the HTML attributes \n    // (used by, eg, appcache) and whether inline scripts are allowed, so we \n    // can memoize based on that.\n    var memHash = JSON.stringify({\n      inlineScriptsAllowed: inlineScriptsAllowed,\n      htmlAttributes: htmlAttributes,\n      arch: arch\n    });\n\n    if (! memoizedBoilerplate[memHash]) {\n      memoizedBoilerplate[memHash] = boilerplateByArch[arch].toHTML({\n        htmlAttributes: htmlAttributes\n      });\n    }\n    return memoizedBoilerplate[memHash];\n  }\n  \n  var boilerplateOptions = _.extend({ \n    htmlAttributes: htmlAttributes \n  }, _.pick(request, 'dynamicHead', 'dynamicBody'));\n  \n  return boilerplateByArch[arch].toHTML(boilerplateOptions);\n};\n\nWebAppInternals.generateBoilerplateInstance = function (arch,\n                                                        manifest,\n                                                        additionalOptions) {\n  additionalOptions = additionalOptions || {};\n\n  var runtimeConfig = _.extend(\n    _.clone(__meteor_runtime_config__),\n    additionalOptions.runtimeConfigOverrides || {}\n  );\n\n  var jsCssUrlRewriteHook = bundledJsCssUrlRewriteHook || function (url) {\n    var bundledPrefix =\n       __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || '';\n    return bundledPrefix + url;\n  };\n\n  return new Boilerplate(arch, manifest,\n    _.extend({\n      pathMapper: function (itemPath) {\n        return path.join(archPath[arch], itemPath); },\n      baseDataExtension: {\n        additionalStaticJs: _.map(\n          additionalStaticJs || [],\n          function (contents, pathname) {\n            return {\n              pathname: pathname,\n              contents: contents\n            };\n          }\n        ),\n        // Convert to a JSON string, then get rid of most weird characters, then\n        // wrap in double quotes. (The outermost JSON.stringify really ought to\n        // just be \"wrap in double quotes\" but we use it to be safe.) This might\n        // end up inside a <script> tag so we need to be careful to not include\n        // \"</script>\", but normal {{spacebars}} escaping escapes too much! See\n        // https://github.com/meteor/meteor/issues/3730\n        meteorRuntimeConfig: JSON.stringify(\n          encodeURIComponent(JSON.stringify(runtimeConfig))),\n        rootUrlPathPrefix: __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || '',\n        bundledJsCssUrlRewriteHook: jsCssUrlRewriteHook,\n        inlineScriptsAllowed: WebAppInternals.inlineScriptsAllowed(),\n        inline: additionalOptions.inline\n      }\n    }, additionalOptions)\n  );\n};\n\n// A mapping from url path to \"info\". Where \"info\" has the following fields:\n// - type: the type of file to be served\n// - cacheable: optionally, whether the file should be cached or not\n// - sourceMapUrl: optionally, the url of the source map\n//\n// Info also contains one of the following:\n// - content: the stringified content that should be served at this path\n// - absolutePath: the absolute path on disk to the file\n\nvar staticFiles;\n\n// Serve static files from the manifest or added with\n// `addStaticJs`. Exported for tests.\nWebAppInternals.staticFilesMiddleware = function (staticFiles, req, res, next) {\n  if ('GET' != req.method && 'HEAD' != req.method && 'OPTIONS' != req.method) {\n    next();\n    return;\n  }\n  var pathname = parseurl(req).pathname;\n  try {\n    pathname = decodeURIComponent(pathname);\n  } catch (e) {\n    next();\n    return;\n  }\n\n  var serveStaticJs = function (s) {\n    res.writeHead(200, {\n      'Content-type': 'application/javascript; charset=UTF-8'\n    });\n    res.write(s);\n    res.end();\n  };\n\n  if (pathname === \"/meteor_runtime_config.js\" &&\n      ! WebAppInternals.inlineScriptsAllowed()) {\n    serveStaticJs(\"__meteor_runtime_config__ = \" +\n                  JSON.stringify(__meteor_runtime_config__) + \";\");\n    return;\n  } else if (_.has(additionalStaticJs, pathname) &&\n              ! WebAppInternals.inlineScriptsAllowed()) {\n    serveStaticJs(additionalStaticJs[pathname]);\n    return;\n  }\n\n  if (!_.has(staticFiles, pathname)) {\n    next();\n    return;\n  }\n\n  // We don't need to call pause because, unlike 'static', once we call into\n  // 'send' and yield to the event loop, we never call another handler with\n  // 'next'.\n\n  var info = staticFiles[pathname];\n\n  // Cacheable files are files that should never change. Typically\n  // named by their hash (eg meteor bundled js and css files).\n  // We cache them ~forever (1yr).\n  var maxAge = info.cacheable\n        ? 1000 * 60 * 60 * 24 * 365\n        : 0;\n\n  // Set the X-SourceMap header, which current Chrome, FireFox, and Safari\n  // understand.  (The SourceMap header is slightly more spec-correct but FF\n  // doesn't understand it.)\n  //\n  // You may also need to enable source maps in Chrome: open dev tools, click\n  // the gear in the bottom right corner, and select \"enable source maps\".\n  if (info.sourceMapUrl) {\n    res.setHeader('X-SourceMap',\n                  __meteor_runtime_config__.ROOT_URL_PATH_PREFIX +\n                  info.sourceMapUrl);\n  }\n\n  if (info.type === \"js\") {\n    res.setHeader(\"Content-Type\", \"application/javascript; charset=UTF-8\");\n  } else if (info.type === \"css\") {\n    res.setHeader(\"Content-Type\", \"text/css; charset=UTF-8\");\n  } else if (info.type === \"json\") {\n    res.setHeader(\"Content-Type\", \"application/json; charset=UTF-8\");\n  }\n\n  if (info.hash) {\n    res.setHeader('ETag', '\"' + info.hash + '\"');\n  }\n\n  if (info.content) {\n    res.write(info.content);\n    res.end();\n  } else {\n    send(req, info.absolutePath, {\n        maxage: maxAge,\n        dotfiles: 'allow', // if we specified a dotfile in the manifest, serve it\n        lastModified: false // don't set last-modified based on the file date\n      }).on('error', function (err) {\n        Log.error(\"Error serving static file \" + err);\n        res.writeHead(500);\n        res.end();\n      })\n      .on('directory', function () {\n        Log.error(\"Unexpected directory \" + info.absolutePath);\n        res.writeHead(500);\n        res.end();\n      })\n      .pipe(res);\n  }\n};\n\nvar getUrlPrefixForArch = function (arch) {\n  // XXX we rely on the fact that arch names don't contain slashes\n  // in that case we would need to uri escape it\n\n  // We add '__' to the beginning of non-standard archs to \"scope\" the url\n  // to Meteor internals.\n  return arch === WebApp.defaultArch ?\n    '' : '/' + '__' + arch.replace(/^web\\./, '');\n};\n\n// parse port to see if its a Windows Server style named pipe. If so, return as-is (String), otherwise return as Int\nWebAppInternals.parsePort = function (port) {\n  if( /\\\\\\\\?.+\\\\pipe\\\\?.+/.test(port) ) {\n    return port;\n  }\n\n  return parseInt(port);\n};\n\nvar runWebAppServer = function () {\n  var shuttingDown = false;\n  var syncQueue = new Meteor._SynchronousQueue();\n\n  var getItemPathname = function (itemUrl) {\n    return decodeURIComponent(url.parse(itemUrl).pathname);\n  };\n\n  WebAppInternals.reloadClientPrograms = function () {\n    syncQueue.runTask(function() {\n      staticFiles = {};\n      var generateClientProgram = function (clientPath, arch) {\n        // read the control for the client we'll be serving up\n        var clientJsonPath = path.join(__meteor_bootstrap__.serverDir,\n                                   clientPath);\n        var clientDir = path.dirname(clientJsonPath);\n        var clientJson = JSON.parse(readUtf8FileSync(clientJsonPath));\n        if (clientJson.format !== \"web-program-pre1\")\n          throw new Error(\"Unsupported format for client assets: \" +\n                          JSON.stringify(clientJson.format));\n\n        if (! clientJsonPath || ! clientDir || ! clientJson)\n          throw new Error(\"Client config file not parsed.\");\n\n        var urlPrefix = getUrlPrefixForArch(arch);\n\n        var manifest = clientJson.manifest;\n        _.each(manifest, function (item) {\n          if (item.url && item.where === \"client\") {\n            staticFiles[urlPrefix + getItemPathname(item.url)] = {\n              absolutePath: path.join(clientDir, item.path),\n              cacheable: item.cacheable,\n              hash: item.hash,\n              // Link from source to its map\n              sourceMapUrl: item.sourceMapUrl,\n              type: item.type\n            };\n\n            if (item.sourceMap) {\n              // Serve the source map too, under the specified URL. We assume all\n              // source maps are cacheable.\n              staticFiles[urlPrefix + getItemPathname(item.sourceMapUrl)] = {\n                absolutePath: path.join(clientDir, item.sourceMap),\n                cacheable: true\n              };\n            }\n          }\n        });\n\n        var program = {\n          format: \"web-program-pre1\",\n          manifest: manifest,\n          version: WebAppHashing.calculateClientHash(manifest, null, _.pick(\n            __meteor_runtime_config__, 'PUBLIC_SETTINGS')),\n          cordovaCompatibilityVersions: clientJson.cordovaCompatibilityVersions,\n          PUBLIC_SETTINGS: __meteor_runtime_config__.PUBLIC_SETTINGS\n        };\n\n        WebApp.clientPrograms[arch] = program;\n\n        // Serve the program as a string at /foo/<arch>/manifest.json\n        // XXX change manifest.json -> program.json\n        staticFiles[urlPrefix + getItemPathname('/manifest.json')] = {\n          content: JSON.stringify(program),\n          cacheable: false,\n          hash: program.version,\n          type: \"json\"\n        };\n      };\n\n      try {\n        var clientPaths = __meteor_bootstrap__.configJson.clientPaths;\n        _.each(clientPaths, function (clientPath, arch) {\n          archPath[arch] = path.dirname(clientPath);\n          generateClientProgram(clientPath, arch);\n        });\n\n        // Exported for tests.\n        WebAppInternals.staticFiles = staticFiles;\n      } catch (e) {\n        Log.error(\"Error reloading the client program: \" + e.stack);\n        process.exit(1);\n      }\n    });\n  };\n\n  WebAppInternals.generateBoilerplate = function () {\n    // This boilerplate will be served to the mobile devices when used with\n    // Meteor/Cordova for the Hot-Code Push and since the file will be served by\n    // the device's server, it is important to set the DDP url to the actual\n    // Meteor server accepting DDP connections and not the device's file server.\n    var defaultOptionsForArch = {\n      'web.cordova': {\n        runtimeConfigOverrides: {\n          // XXX We use absoluteUrl() here so that we serve https://\n          // URLs to cordova clients if force-ssl is in use. If we were\n          // to use __meteor_runtime_config__.ROOT_URL instead of\n          // absoluteUrl(), then Cordova clients would immediately get a\n          // HCP setting their DDP_DEFAULT_CONNECTION_URL to\n          // http://example.meteor.com. This breaks the app, because\n          // force-ssl doesn't serve CORS headers on 302\n          // redirects. (Plus it's undesirable to have clients\n          // connecting to http://example.meteor.com when force-ssl is\n          // in use.)\n          DDP_DEFAULT_CONNECTION_URL: process.env.MOBILE_DDP_URL ||\n            Meteor.absoluteUrl(),\n          ROOT_URL: process.env.MOBILE_ROOT_URL ||\n            Meteor.absoluteUrl()\n        }\n      }\n    };\n\n    syncQueue.runTask(function() {\n      _.each(WebApp.clientPrograms, function (program, archName) {\n        boilerplateByArch[archName] =\n          WebAppInternals.generateBoilerplateInstance(\n            archName, program.manifest,\n            defaultOptionsForArch[archName]);\n      });\n\n      // Clear the memoized boilerplate cache.\n      memoizedBoilerplate = {};\n\n      // Configure CSS injection for the default arch\n      // XXX implement the CSS injection for all archs?\n      WebAppInternals.refreshableAssets = {\n        allCss: boilerplateByArch[WebApp.defaultArch].baseData.css\n      };\n    });\n  };\n\n  WebAppInternals.reloadClientPrograms();\n\n  // webserver\n  var app = connect();\n\n  // Auto-compress any json, javascript, or text.\n  app.use(connect.compress());\n\n  // Packages and apps can add handlers that run before any other Meteor\n  // handlers via WebApp.rawConnectHandlers.\n  var rawConnectHandlers = connect();\n  app.use(rawConnectHandlers);\n\n  // We're not a proxy; reject (without crashing) attempts to treat us like\n  // one. (See #1212.)\n  app.use(function(req, res, next) {\n    if (RoutePolicy.isValidUrl(req.url)) {\n      next();\n      return;\n    }\n    res.writeHead(400);\n    res.write(\"Not a proxy\");\n    res.end();\n  });\n\n  // Strip off the path prefix, if it exists.\n  app.use(function (request, response, next) {\n    var pathPrefix = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX;\n    var url = Npm.require('url').parse(request.url);\n    var pathname = url.pathname;\n    // check if the path in the url starts with the path prefix (and the part\n    // after the path prefix must start with a / if it exists.)\n    if (pathPrefix && pathname.substring(0, pathPrefix.length) === pathPrefix &&\n       (pathname.length == pathPrefix.length\n        || pathname.substring(pathPrefix.length, pathPrefix.length + 1) === \"/\")) {\n      request.url = request.url.substring(pathPrefix.length);\n      next();\n    } else if (pathname === \"/favicon.ico\" || pathname === \"/robots.txt\") {\n      next();\n    } else if (pathPrefix) {\n      response.writeHead(404);\n      response.write(\"Unknown path\");\n      response.end();\n    } else {\n      next();\n    }\n  });\n\n  // Parse the query string into res.query. Used by oauth_server, but it's\n  // generally pretty handy..\n  app.use(connect.query());\n\n  // Serve static files from the manifest.\n  // This is inspired by the 'static' middleware.\n  app.use(function (req, res, next) {\n    Fiber(function () {\n     WebAppInternals.staticFilesMiddleware(staticFiles, req, res, next);\n    }).run();\n  });\n\n  // Packages and apps can add handlers to this via WebApp.connectHandlers.\n  // They are inserted before our default handler.\n  var packageAndAppHandlers = connect();\n  app.use(packageAndAppHandlers);\n\n  var suppressConnectErrors = false;\n  // connect knows it is an error handler because it has 4 arguments instead of\n  // 3. go figure.  (It is not smart enough to find such a thing if it's hidden\n  // inside packageAndAppHandlers.)\n  app.use(function (err, req, res, next) {\n    if (!err || !suppressConnectErrors || !req.headers['x-suppress-error']) {\n      next(err);\n      return;\n    }\n    res.writeHead(err.status, { 'Content-Type': 'text/plain' });\n    res.end(\"An error message\");\n  });\n\n  app.use(function (req, res, next) {\n    Fiber(function () {\n      if (!appUrl(req.url))\n        return next();\n\n      var headers = {\n        'Content-Type': 'text/html; charset=utf-8'\n      };\n      if (shuttingDown)\n        headers['Connection'] = 'Close';\n\n      var request = WebApp.categorizeRequest(req);\n\n      if (request.url.query && request.url.query['meteor_css_resource']) {\n        // In this case, we're requesting a CSS resource in the meteor-specific\n        // way, but we don't have it.  Serve a static css file that indicates that\n        // we didn't have it, so we can detect that and refresh.  Make sure\n        // that any proxies or CDNs don't cache this error!  (Normally proxies\n        // or CDNs are smart enough not to cache error pages, but in order to\n        // make this hack work, we need to return the CSS file as a 200, which\n        // would otherwise be cached.)\n        headers['Content-Type'] = 'text/css; charset=utf-8';\n        headers['Cache-Control'] = 'no-cache';\n        res.writeHead(200, headers);\n        res.write(\".meteor-css-not-found-error { width: 0px;}\");\n        res.end();\n        return undefined;\n      }\n\n      if (request.url.query && request.url.query['meteor_js_resource']) {\n        // Similarly, we're requesting a JS resource that we don't have.\n        // Serve an uncached 404. (We can't use the same hack we use for CSS,\n        // because actually acting on that hack requires us to have the JS\n        // already!)\n        headers['Cache-Control'] = 'no-cache';\n        res.writeHead(404, headers);\n        res.end(\"404 Not Found\");\n        return undefined;\n      }\n\n      if (request.url.query && request.url.query['meteor_dont_serve_index']) {\n        // When downloading files during a Cordova hot code push, we need\n        // to detect if a file is not available instead of inadvertently\n        // downloading the default index page.\n        // So similar to the situation above, we serve an uncached 404.\n        headers['Cache-Control'] = 'no-cache';\n        res.writeHead(404, headers);\n        res.end(\"404 Not Found\");\n        return undefined;\n      }\n\n      // /packages/asdfsad ... /__cordova/dafsdf.js\n      var pathname = parseurl(req).pathname;\n      var archKey = pathname.split('/')[1];\n      var archKeyCleaned = 'web.' + archKey.replace(/^__/, '');\n\n      if (!/^__/.test(archKey) || !_.has(archPath, archKeyCleaned)) {\n        archKey = WebApp.defaultArch;\n      } else {\n        archKey = archKeyCleaned;\n      }\n\n      var boilerplate;\n      try {\n        boilerplate = getBoilerplate(request, archKey);\n      } catch (e) {\n        Log.error(\"Error running template: \" + e.stack);\n        res.writeHead(500, headers);\n        res.end();\n        return undefined;\n      }\n\n      var statusCode = res.statusCode ? res.statusCode : 200;\n      res.writeHead(statusCode, headers);\n      res.write(boilerplate);\n      res.end();\n      return undefined;\n    }).run();\n  });\n\n  // Return 404 by default, if no other handlers serve this URL.\n  app.use(function (req, res) {\n    res.writeHead(404);\n    res.end();\n  });\n\n\n  var httpServer = http.createServer(app);\n  var onListeningCallbacks = [];\n\n  // After 5 seconds w/o data on a socket, kill it.  On the other hand, if\n  // there's an outstanding request, give it a higher timeout instead (to avoid\n  // killing long-polling requests)\n  httpServer.setTimeout(SHORT_SOCKET_TIMEOUT);\n\n  // Do this here, and then also in livedata/stream_server.js, because\n  // stream_server.js kills all the current request handlers when installing its\n  // own.\n  httpServer.on('request', WebApp._timeoutAdjustmentRequestCallback);\n\n\n  // start up app\n  _.extend(WebApp, {\n    connectHandlers: packageAndAppHandlers,\n    rawConnectHandlers: rawConnectHandlers,\n    httpServer: httpServer,\n    // For testing.\n    suppressConnectErrors: function () {\n      suppressConnectErrors = true;\n    },\n    onListening: function (f) {\n      if (onListeningCallbacks)\n        onListeningCallbacks.push(f);\n      else\n        f();\n    }\n  });\n\n  // Let the rest of the packages (and Meteor.startup hooks) insert connect\n  // middlewares and update __meteor_runtime_config__, then keep going to set up\n  // actually serving HTML.\n  main = function (argv) {\n    WebAppInternals.generateBoilerplate();\n\n    // only start listening after all the startup code has run.\n    var localPort = WebAppInternals.parsePort(process.env.PORT) || 0;\n    var host = process.env.BIND_IP;\n    var localIp = host || '0.0.0.0';\n    httpServer.listen(localPort, localIp, Meteor.bindEnvironment(function() {\n      if (process.env.METEOR_PRINT_ON_LISTEN)\n        console.log(\"LISTENING\"); // must match run-app.js\n\n      var callbacks = onListeningCallbacks;\n      onListeningCallbacks = null;\n      _.each(callbacks, function (x) { x(); });\n\n    }, function (e) {\n      console.error(\"Error listening:\", e);\n      console.error(e && e.stack);\n    }));\n\n    return 'DAEMON';\n  };\n};\n\n\nrunWebAppServer();\n\n\nvar inlineScriptsAllowed = true;\n\nWebAppInternals.inlineScriptsAllowed = function () {\n  return inlineScriptsAllowed;\n};\n\nWebAppInternals.setInlineScriptsAllowed = function (value) {\n  inlineScriptsAllowed = value;\n  WebAppInternals.generateBoilerplate();\n};\n\n\nWebAppInternals.setBundledJsCssUrlRewriteHook = function (hookFn) {\n  bundledJsCssUrlRewriteHook = hookFn;\n  WebAppInternals.generateBoilerplate();\n};\n\nWebAppInternals.setBundledJsCssPrefix = function (prefix) {\n  var self = this;\n  self.setBundledJsCssUrlRewriteHook(\n    function (url) {\n      return prefix + url;\n  });\n};\n\n// Packages can call `WebAppInternals.addStaticJs` to specify static\n// JavaScript to be included in the app. This static JS will be inlined,\n// unless inline scripts have been disabled, in which case it will be\n// served under `/<sha1 of contents>`.\nvar additionalStaticJs = {};\nWebAppInternals.addStaticJs = function (contents) {\n  additionalStaticJs[\"/\" + sha1(contents) + \".js\"] = contents;\n};\n\n// Exported for tests\nWebAppInternals.getBoilerplate = getBoilerplate;\nWebAppInternals.additionalStaticJs = additionalStaticJs;\n"
  },
  {
    "path": "packages/webapp/webapp_tests.js",
    "content": "var url = Npm.require(\"url\");\nvar crypto = Npm.require(\"crypto\");\nvar http = Npm.require(\"http\");\n\nvar additionalScript = \"(function () { var foo = 1; })\";\nWebAppInternals.addStaticJs(additionalScript);\nvar hash = crypto.createHash('sha1');\nhash.update(additionalScript);\nvar additionalScriptPathname = hash.digest('hex') + \".js\";\n\n// Mock the 'res' object that gets passed to connect handlers. This mock\n// just records any utf8 data written to the response and returns it\n// when you call `mockResponse.getBody()`.\nvar MockResponse = function () {\n  this.buffer = \"\";\n  this.statusCode = null;\n};\n\nMockResponse.prototype.writeHead = function (statusCode) {\n  this.statusCode = statusCode;\n};\n\nMockResponse.prototype.setHeader = function (name, value) {\n  // nothing\n};\n\nMockResponse.prototype.write = function (data, encoding) {\n  if (! encoding || encoding === \"utf8\") {\n    this.buffer = this.buffer + data;\n  }\n};\n\nMockResponse.prototype.end = function (data, encoding) {\n  if (! encoding || encoding === \"utf8\") {\n    if (data) {\n      this.buffer = this.buffer + data;\n    }\n  }\n};\n\nMockResponse.prototype.getBody = function () {\n  return this.buffer;\n};\n\n\n\nTinytest.add(\"webapp - content-type header\", function (test) {\n  var cssResource = _.find(\n    _.keys(WebAppInternals.staticFiles),\n    function (url) {\n      return WebAppInternals.staticFiles[url].type === \"css\";\n    }\n  );\n  var jsResource = _.find(\n    _.keys(WebAppInternals.staticFiles),\n    function (url) {\n      return WebAppInternals.staticFiles[url].type === \"js\";\n    }\n  );\n\n  var resp = HTTP.get(url.resolve(Meteor.absoluteUrl(), cssResource));\n  test.equal(resp.headers[\"content-type\"].toLowerCase(),\n             \"text/css; charset=utf-8\");\n  resp = HTTP.get(url.resolve(Meteor.absoluteUrl(), jsResource));\n  test.equal(resp.headers[\"content-type\"].toLowerCase(),\n             \"application/javascript; charset=utf-8\");\n});\n\nTinytest.add(\"webapp - additional static javascript\", function (test) {\n  var origInlineScriptsAllowed = WebAppInternals.inlineScriptsAllowed();\n\n  var staticFilesOpts = {\n    staticFiles: {},\n    clientDir: \"/\"\n  };\n\n  // It's okay to set this global state because we're not going to yield\n  // before settng it back to what it was originally.\n  WebAppInternals.setInlineScriptsAllowed(true);\n\n  Meteor._noYieldsAllowed(function () {\n    var boilerplate = WebAppInternals.getBoilerplate({\n      browser: \"doesn't-matter\",\n      url: \"also-doesnt-matter\"\n    }, \"web.browser\");\n\n    // When inline scripts are allowed, the script should be inlined.\n    test.isTrue(boilerplate.indexOf(additionalScript) !== -1);\n\n    // And the script should not be served as its own separate resource,\n    // meaning that the static file handler should pass on this request.\n    var res = new MockResponse();\n    var req = new http.IncomingMessage();\n    req.headers = {};\n    req.method = \"GET\";\n    req.url = \"/\" + additionalScriptPathname;\n    var nextCalled = false;\n    WebAppInternals.staticFilesMiddleware(\n      staticFilesOpts, req, res, function () {\n        nextCalled = true;\n      });\n    test.isTrue(nextCalled);\n  });\n\n  // When inline scripts are disallowed, the script body should not be\n  // inlined, and the script should be included in a <script src=\"..\">\n  // tag.\n  WebAppInternals.setInlineScriptsAllowed(false);\n\n  Meteor._noYieldsAllowed(function () {\n    var boilerplate = WebAppInternals.getBoilerplate({\n      browser: \"doesn't-matter\",\n      url: \"also-doesnt-matter\"\n    }, \"web.browser\");\n\n    // The script contents itself should not be present; the pathname\n    // where the script is served should be.\n    test.isTrue(boilerplate.indexOf(additionalScript) === -1);\n    test.isTrue(boilerplate.indexOf(additionalScriptPathname) !== -1);\n\n    // And the static file handler should serve the script at that pathname.\n    var res = new MockResponse();\n    var req = new http.IncomingMessage();\n    req.headers = {};\n    req.method = \"GET\";\n    req.url = \"/\" + additionalScriptPathname;\n    WebAppInternals.staticFilesMiddleware(staticFilesOpts, req, res,\n                                     function () { });\n    var resBody = res.getBody();\n    test.isTrue(resBody.indexOf(additionalScript) !== -1);\n    test.equal(res.statusCode, 200);\n  });\n\n  WebAppInternals.setInlineScriptsAllowed(origInlineScriptsAllowed);\n});\n\n// Regression test: `generateBoilerplateInstance` should not change\n// `__meteor_runtime_config__`.\nTinytest.add(\"webapp - generating boilerplate should not change runtime config\", function (test) {\n  // Set a dummy key in the runtime config served in the\n  // boilerplate. Test that the dummy key appears in the boilerplate,\n  // but not in __meteor_runtime_config__ after generating the\n  // boilerplate.\n\n  test.isFalse(__meteor_runtime_config__.WEBAPP_TEST_KEY);\n\n  var boilerplate = WebAppInternals.generateBoilerplateInstance(\n    \"web.browser\",\n    {}, // empty manifest\n    { runtimeConfigOverrides: { WEBAPP_TEST_KEY: true } }\n  );\n\n  var boilerplateHtml = boilerplate.toHTML();\n  test.isFalse(boilerplateHtml.indexOf(\"WEBAPP_TEST_KEY\") === -1);\n\n  test.isFalse(__meteor_runtime_config__.WEBAPP_TEST_KEY);\n});\n\n// Support 'named pipes' (strings) as ports for support of Windows Server / Azure deployments\nTinytest.add(\"webapp - port should be parsed as int unless it is a named pipe\", function(test){\n  // Named pipes on Windows Server follow the format: \\\\.\\pipe\\{randomstring} or \\\\{servername}\\pipe\\{randomstring}\n  var namedPipe = \"\\\\\\\\.\\\\pipe\\\\b27429e9-61e3-4c12-8bfe-950fa3295f74\";\n  var namedPipeServer = \"\\\\\\\\SERVERNAME-1234\\\\pipe\\\\6e157e98-faef-49e4-a0cf-241037223308\";\n\n  test.equal(WebAppInternals.parsePort(namedPipe),\n      \"\\\\\\\\.\\\\pipe\\\\b27429e9-61e3-4c12-8bfe-950fa3295f74\");\n  test.equal(WebAppInternals.parsePort(namedPipeServer),\n      \"\\\\\\\\SERVERNAME-1234\\\\pipe\\\\6e157e98-faef-49e4-a0cf-241037223308\");\n  test.equal(WebAppInternals.parsePort(8080),\n      8080);\n  test.equal(WebAppInternals.parsePort(\"8080\"),\n      8080);\n  test.equal(WebAppInternals.parsePort(\"8080abc\"), // ensure strangely formatted ports still work for backwards compatibility\n      8080);\n});\n\n__meteor_runtime_config__.WEBAPP_TEST_A = '<p>foo</p>';\n__meteor_runtime_config__.WEBAPP_TEST_B = '</script>';\n\n\nTinytest.add(\"webapp - npm modules\", function (test) {\n  // Make sure the version number looks like a version number.\n  test.matches(WebAppInternals.NpmModules.connect.version, /^2\\.(\\d+)\\.(\\d+)/);\n  test.equal(typeof(WebAppInternals.NpmModules.connect.module), 'function');\n  test.equal(typeof(WebAppInternals.NpmModules.connect.module.basicAuth),\n             'function');\n});\n"
  },
  {
    "path": "packages/webapp-hashing/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/webapp-hashing/README.md",
    "content": "# webapp-hashing\n\nThis package knows how to hash together all of the elements in a\nclient resource manifest to produce a build ID that can be used to\ndetermine if a client has the latest code, or if it needs to be\nupdated. It is used internally by\n[webapp](https://atmospherejs.com/meteor/webapp).\n"
  },
  {
    "path": "packages/webapp-hashing/package.js",
    "content": "Package.describe({\n  summary: \"Used internally by WebApp. Knows how to hash programs from manifests.\",\n  version: \"1.0.9\"\n});\n\nPackage.onUse(function(api) {\n  api.use('ecmascript');\n  api.use('underscore', 'server');\n  api.addFiles('webapp-hashing.js', 'server');\n  api.export('WebAppHashing');\n});\n\nPackage.onTest(function(api) {\n  api.use('tinytest');\n  api.use('webapp-hashing');\n});\n"
  },
  {
    "path": "packages/webapp-hashing/webapp-hashing.js",
    "content": "var crypto = Npm.require(\"crypto\");\n\nWebAppHashing = {};\n\n// Calculate a hash of all the client resources downloaded by the\n// browser, including the application HTML, runtime config, code, and\n// static files.\n//\n// This hash *must* change if any resources seen by the browser\n// change, and ideally *doesn't* change for any server-only changes\n// (but the second is a performance enhancement, not a hard\n// requirement).\n\nWebAppHashing.calculateClientHash =\n  function (manifest, includeFilter, runtimeConfigOverride) {\n  var hash = crypto.createHash('sha1');\n\n  // Omit the old hashed client values in the new hash. These may be\n  // modified in the new boilerplate.\n  var runtimeCfg = _.omit(__meteor_runtime_config__,\n    ['autoupdateVersion', 'autoupdateVersionRefreshable',\n     'autoupdateVersionCordova']);\n\n  if (runtimeConfigOverride) {\n    runtimeCfg = runtimeConfigOverride;\n  }\n\n  hash.update(JSON.stringify(runtimeCfg, 'utf8'));\n\n  _.each(manifest, function (resource) {\n      if ((! includeFilter || includeFilter(resource.type)) &&\n          (resource.where === 'client' || resource.where === 'internal')) {\n      hash.update(resource.path);\n      hash.update(resource.hash);\n    }\n  });\n  return hash.digest('hex');\n};\n\nWebAppHashing.calculateCordovaCompatibilityHash =\n  function(platformVersion, pluginVersions) {\n  const hash = crypto.createHash('sha1');\n\n  hash.update(platformVersion);\n\n  // Sort plugins first so iteration order doesn't affect the hash\n  const plugins = Object.keys(pluginVersions).sort();\n  for (let plugin of plugins) {\n    const version = pluginVersions[plugin];\n    hash.update(plugin);\n    hash.update(version);\n  }\n\n  return hash.digest('hex');\n};\n"
  },
  {
    "path": "packages/weibo/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/weibo/README.md",
    "content": "# weibo\n\nAn implementation of the Weibo OAuth flow. See the [project\npage](https://www.meteor.com/accounts) on Meteor Accounts for more\ndetails."
  },
  {
    "path": "packages/weibo/package.js",
    "content": "Package.describe({\n  summary: \"Weibo OAuth flow\",\n  version: '1.1.8'\n});\n\nPackage.onUse(function(api) {\n  api.use('oauth2', ['client', 'server']);\n  api.use('oauth', ['client', 'server']);\n  api.use('http', ['server']);\n  api.use('templating', 'client');\n  api.use('random', 'client');\n  api.use('service-configuration', ['client', 'server']);\n\n  api.export('Weibo');\n\n  api.addFiles(\n    ['weibo_configure.html', 'weibo_configure.js'],\n    'client');\n\n  api.addFiles('weibo_server.js', 'server');\n  api.addFiles('weibo_client.js', 'client');\n});\n"
  },
  {
    "path": "packages/weibo/weibo_client.js",
    "content": "Weibo = {};\n\n// Request Weibo credentials for the user\n// @param options {optional}\n// @param credentialRequestCompleteCallback {Function} Callback function to call on\n//   completion. Takes one argument, credentialToken on success, or Error on\n//   error.\nWeibo.requestCredential = function (options, credentialRequestCompleteCallback) {\n  // support both (options, callback) and (callback).\n  if (!credentialRequestCompleteCallback && typeof options === 'function') {\n    credentialRequestCompleteCallback = options;\n    options = {};\n  }\n\n  var config = ServiceConfiguration.configurations.findOne({service: 'weibo'});\n  if (!config) {\n    credentialRequestCompleteCallback && credentialRequestCompleteCallback(\n      new ServiceConfiguration.ConfigError());\n    return;\n  }\n\n  var credentialToken = Random.secret();\n\n  var loginStyle = OAuth._loginStyle('weibo', config, options);\n\n  // XXX need to support configuring access_type and scope\n  var loginUrl =\n        'https://api.weibo.com/oauth2/authorize' +\n        '?response_type=code' +\n        '&client_id=' + config.clientId +\n        '&redirect_uri=' + OAuth._redirectUri('weibo', config, null, {replaceLocalhost: true}) +\n        '&state=' + OAuth._stateParam(loginStyle, credentialToken, options && options.redirectUrl);\n\n  OAuth.launchLogin({\n    loginService: \"weibo\",\n    loginStyle: loginStyle,\n    loginUrl: loginUrl,\n    credentialRequestCompleteCallback: credentialRequestCompleteCallback,\n    credentialToken: credentialToken\n  });\n};\n"
  },
  {
    "path": "packages/weibo/weibo_configure.html",
    "content": "<template name=\"configureLoginServiceDialogForWeibo\">\n  <p>\n    First, you'll need to register your app on Weibo. Follow these steps:\n  </p>\n  <ol>\n    <li>\n      Visit <a href=\"http://open.weibo.com/development\" target=\"_blank\">http://open.weibo.com/development</a> (Google Chrome's automatic translation works well here)\n    </li>\n    <li>\n      Click the orange \"立即创建微连接\" button\n    </li>\n    <li>\n      Select the third option, APP / 网页应用 (Web Applications)\n    </li>\n    <li>\n      Complete the registration process. An email confirmation will be send. No SMS confirmation required.\n    </li>\n    <li>\n      Open 应用信息 (Application) -> 高级信息 (Advanced Information)\n    </li>\n    <li>\n      Set OAuth2.0 授权回调页 (authorized callback page) to: <span class=\"url\">{{siteUrl}}_oauth/weibo</span>\n    </li>\n  </ol>\n</template>\n"
  },
  {
    "path": "packages/weibo/weibo_configure.js",
    "content": "Template.configureLoginServiceDialogForWeibo.helpers({\n  siteUrl: function () {\n    // Weibo doesn't recognize localhost as a domain\n    return Meteor.absoluteUrl({replaceLocalhost: true});\n  }\n});\n\nTemplate.configureLoginServiceDialogForWeibo.fields = function () {\n  return [\n    {property: 'clientId', label: 'App Key'},\n    {property: 'secret', label: 'App Secret'}\n  ];\n};\n"
  },
  {
    "path": "packages/weibo/weibo_server.js",
    "content": "Weibo = {};\n\nOAuth.registerService('weibo', 2, null, function(query) {\n\n  var response = getTokenResponse(query);\n  var uid = parseInt(response.uid, 10);\n\n  // different parts of weibo's api seem to expect numbers, or strings\n  // for uid. let's make sure they're both the same.\n  if (response.uid !== uid + \"\")\n    throw new Error(\"Expected 'uid' to parse to an integer: \" + JSON.stringify(response));\n\n  var identity = getIdentity(response.access_token, uid);\n\n  return {\n    serviceData: {\n      // We used to store this as a string, so keep it this way rather than\n      // add complexity to Account.updateOrCreateUserFromExternalService or\n      // force a database migration\n      id: uid + \"\",\n      accessToken: response.access_token,\n      screenName: identity.screen_name,\n      expiresAt: (+new Date) + (1000 * response.expires_in)\n    },\n    options: {profile: {name: identity.screen_name}}\n  };\n});\n\n// return an object containining:\n// - uid\n// - access_token\n// - expires_in: lifetime of this token in seconds (5 years(!) right now)\nvar getTokenResponse = function (query) {\n  var config = ServiceConfiguration.configurations.findOne({service: 'weibo'});\n  if (!config)\n    throw new ServiceConfiguration.ConfigError();\n\n  var response;\n  try {\n    response = HTTP.post(\n      \"https://api.weibo.com/oauth2/access_token\", {params: {\n        code: query.code,\n        client_id: config.clientId,\n        client_secret: OAuth.openSecret(config.secret),\n        redirect_uri: OAuth._redirectUri('weibo', config, null, {replaceLocalhost: true}),\n        grant_type: 'authorization_code'\n      }});\n  } catch (err) {\n    throw _.extend(new Error(\"Failed to complete OAuth handshake with Weibo. \" + err.message),\n                   {response: err.response});\n  }\n\n  // result.headers[\"content-type\"] is 'text/plain;charset=UTF-8', so\n  // the http package doesn't automatically populate result.data\n  response.data = JSON.parse(response.content);\n\n  if (response.data.error) { // if the http response was a json object with an error attribute\n    throw new Error(\"Failed to complete OAuth handshake with Weibo. \" + response.data.error);\n  } else {\n    return response.data;\n  }\n};\n\nvar getIdentity = function (accessToken, userId) {\n  try {\n    return HTTP.get(\n      \"https://api.weibo.com/2/users/show.json\",\n      {params: {access_token: accessToken, uid: userId}}).data;\n  } catch (err) {\n    throw _.extend(new Error(\"Failed to fetch identity from Weibo. \" + err.message),\n                   {response: err.response});\n  }\n};\n\nWeibo.retrieveCredential = function(credentialToken, credentialSecret) {\n  return OAuth.retrieveCredential(credentialToken, credentialSecret);\n};\n"
  },
  {
    "path": "packages/xmlbuilder/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "packages/xmlbuilder/.npm/package/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "packages/xmlbuilder/.npm/package/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "packages/xmlbuilder/.npm/package/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"xmlbuilder\": {\n      \"version\": \"2.4.4\",\n      \"resolved\": \"https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.4.4.tgz\",\n      \"from\": \"https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.4.4.tgz\",\n      \"dependencies\": {\n        \"lodash-node\": {\n          \"version\": \"2.4.1\",\n          \"resolved\": \"https://registry.npmjs.org/lodash-node/-/lodash-node-2.4.1.tgz\",\n          \"from\": \"https://registry.npmjs.org/lodash-node/-/lodash-node-2.4.1.tgz\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/xmlbuilder/README.md",
    "content": "This is an internal Meteor package."
  },
  {
    "path": "packages/xmlbuilder/package.js",
    "content": "Package.describe({\n  summary: \"An XML builder for node.js similar to java-xmlbuilder.\",\n  version: '2.4.12_1'\n});\n\nNpm.depends({\n  'xmlbuilder': '2.4.4'  // XXX next time we update this to X.Y.Z,\n                         // make the version above be X.Y.Z_0 so we\n                         // don't accidentally unsync version numbers\n});\n\nPackage.onUse(function (api) {\n  api.addFiles(['xmlbuilder.js'], 'server');\n\n  api.export('XmlBuilder', 'server');\n});\n"
  },
  {
    "path": "packages/xmlbuilder/xmlbuilder.js",
    "content": "XmlBuilder = Npm.require('xmlbuilder');\n\n"
  },
  {
    "path": "scripts/admin/banners-oldcore.json",
    "content": "{ \"track\": \"METEOR-CORE\",\n  \"banners\": [\n    {\n      \"versions\": [\"0.9.0-rc10\", \"0.9.0-rc11\", \"0.9.0-rc12\"],\n      \"banner\": {\n        \"text\": \"=> Meteor 0.9.0 is now out! Upgrade to it with:\\n     `meteor update --release METEOR@0.9.0`\\n   Thanks for helping test the release candidates!\"\n       }\n    }\n  ]\n}\n"
  },
  {
    "path": "scripts/admin/banners.json",
    "content": "{ \"track\": \"METEOR\",\n  \"banners\": [{\n    \"versions\": [\"0.9.0\", \"0.9.0.1\", \"0.9.1\", \"0.9.1.1\", \"0.9.2\",\n                 \"0.9.2.1\", \"0.9.2.2\", \"0.9.3\", \"0.9.3.1\", \"0.9.4\", \"1.0\",\n                 \"1.0.1\", \"1.0.2\", \"1.0.2.1\", \"1.0.3\", \"1.0.3.1\", \"1.0.3.2\",\n                 \"1.0.4\", \"1.0.4.1\", \"1.0.4.2\", \"1.0.5\", \"1.1\", \"1.1.0.1\",\n                 \"1.1.0.2\", \"1.1.0.3\", \"1.2\", \"1.2.0.1\", \"1.2.0.2\", \"1.2.1\"],\n    \"banner\": {\n      \"text\": \"=> Meteor 1.3: ES2015 modules, npm integration, app testing, mobile\\n   improvements, and more.\\n\\n   This release is being downloaded in the background. Update your app to\\n   Meteor 1.3 by running 'meteor update'.\"\n    }\n  }, {\n    \"versions\": [\"1.3\", \"1.3.1\", \"1.3.2\", \"1.3.2.1\", \"1.3.2.2\", \"1.3.2.3\",\n                 \"1.3.2.4\", \"1.3.3\", \"1.3.3.1\"],\n    \"banner\": {\n      \"text\": \"=> Meteor 1.3.4: npm@3.9.6, .babelrc support, improved import declarations,\\n   DDP update batching, and more: https://github.com/meteor/meteor/blob/master/History.md#v134\\n\\n   This release is being downloaded in the background. Update your app to\\n   Meteor 1.3.4 by running 'meteor update'.\"\n    }\n  }]\n}\n"
  },
  {
    "path": "scripts/admin/bump-all-version-numbers.js",
    "content": "// run as node scripts/admin/bump-all-version-numbers.js <packageNames>\n\nvar fs = require(\"fs\");\nvar _ = require(\"../../packages/underscore/underscore.js\")._;\n\nvar packageNames = _.rest(process.argv, 2);\n\n_.each(packageNames, function (name) {\n  // name = \"packages/\" + name + \"/package.js\";\n\n  var content = fs.readFileSync(name, {encoding: \"utf-8\"});\n\n  match = content.match(/\\d+\\.\\d+\\.\\d+-winr.\\d+/);\n  if (match) {\n    var versionNumber = match[0];\n    var s = versionNumber.split(\".\");\n    s[3] = (parseInt(s[3], 10) + 1);\n    var incremented = s.join(\".\");\n\n    content = content.replace(versionNumber, incremented);\n    console.log(match[0], match[1], incremented);\n    fs.writeFileSync(name, content);\n  }\n});\n"
  },
  {
    "path": "scripts/admin/check-package-dependencies.rb",
    "content": "#! /usr/bin/env ruby\n\n# This script takes two arguments:\n# 1. The name of an export - ex. EJSON\n# 2. The name of a package - ex. ejson\n# It makes sure that if the export appears somewhere in package source code, the\n# name of the package appears somewhere in package.js for that package.\n\nroot = File.join(File.dirname(__FILE__), \"..\", \"..\");\n\nDir.chdir(root)\n\nfile_list = `git grep -lw '#{ARGV[0]}' packages/`.lines\npackage_list = file_list.map do |filename|\n  filename.split(\"/\")[1]\nend\n\npackage_list = package_list.uniq\n\npackage_list.each do |p|\n  unless File.open(\"packages/#{p}/package.js\").read.include? ARGV[1]\n    puts \"'#{ARGV[0]}' appears in #{p} but '#{ARGV[1]}' not in package.js. Files:\"\n    puts `git grep '#{ARGV[0]}' packages/#{p}/`\n    puts \"\"\n  end\nend\n"
  },
  {
    "path": "scripts/admin/copy-bootstrap-tarballs-from-jenkins.sh",
    "content": "#!/usr/bin/env bash\n\n# Requires awscli to be installed and an appropriate ~/.aws/config.\n# Usage:\n#    scripts/admin/copy-bootstrap-tarballs-from-jenkins.sh BUILDNUMBER\n# where BUILDNUMBER is the small integer Jenkins build number.\n\nset -e\nset -u\n\ncd \"`dirname \"$0\"`\"\n\nTARGET=\"s3://com.meteor.static/packages-bootstrap/\"\n\nif [ $# -ne 1 ]; then\n    echo \"usage: $0 jenkins-build-number\" 1>&2\n    exit 1\nfi\n\n# bootstrap-tarballs--${METEOR_RELEASE}--${BUILD_ID}--${BUILD_NUMBER}--${GIT_COMMIT}\nDIRNAME=$(aws s3 ls s3://com.meteor.jenkins/ | perl -nle 'print $1 if m!(bootstrap-tarballs--.+--.+--'$1'--.+)/!')\nRELEASE=$(echo $DIRNAME | perl -pe 's/^bootstrap-tarballs--(.+)--.+--.+--.+$/$1/')\n\nif [ -z \"$DIRNAME\" ]; then\n    echo \"build not found\" 1>&2\n    exit 1\nfi\n\necho \"Found build $DIRNAME\"\n\n\ntrap \"echo Found surprising number of tarballs.\" EXIT\n# Check to make sure the proper number of each kind of file is there.\naws s3 ls \"s3://com.meteor.jenkins/$DIRNAME/\" | \\\n  perl -nle 'if (/\\.tar\\.gz/) { ++$TAR } else { die \"something weird\" }  END { exit !($TAR == 4) }'\n\ntrap - EXIT\n\necho Copying to \"$TARGET\"\naws s3 cp --acl public-read --recursive \"s3://com.meteor.jenkins/$DIRNAME/\" \"$TARGET$RELEASE\"\n"
  },
  {
    "path": "scripts/admin/copy-dev-bundle-from-jenkins.sh",
    "content": "#!/usr/bin/env bash\n\n# Requires awscli to be installed and an appropriate ~/.aws/config.\n# Usage:\n#    scripts/admin/copy-dev-bundle-from-jenkins.sh [--prod] BUILDNUMBER\n# where BUILDNUMBER is the small integer Jenkins build number.\n\nset -e\nset -u\n\ncd \"`dirname \"$0\"`\"\n\narg=$1\n\nTARGET=\"s3://com.meteor.static/test/\"\nTEST=no\nif [ $# -ge 1 -a ${arg} = '--prod' ]; then\n    shift\n    arg=$1\n    TARGET=\"s3://com.meteor.static/\"\nelse\n    TEST=yes\nfi\n\nif [ $# -ne 1 ]; then\n    echo \"usage: $0 [--prod] jenkins-build-number\" 1>&2\n    exit 1\nfi\n\nDIRNAME=$(aws s3 ls s3://com.meteor.jenkins/ | perl -nle 'print $1 if m!(dev-bundle-.+--'${arg}'--.+)/!')\n\nif [ -z \"$DIRNAME\" ]; then\n    echo \"build not found\" 1>&2\n    exit 1\nfi\n\necho Found build $DIRNAME\n\ntrap \"echo Found surprising number of tarballs.\" EXIT\n# Check to make sure the proper number of each kind of file is there.\naws s3 ls s3://com.meteor.jenkins/$DIRNAME/ | \\\n  perl -nle 'if (/\\.tar\\.gz/) { ++$TAR } else { die \"something weird\" }  END { exit !($TAR == 4) }'\n\ntrap - EXIT\n\n# This awful perl line means \"print everything after the last whitespace\".\nfor FILE in $(aws s3 ls s3://com.meteor.jenkins/$DIRNAME/ | perl -nla -e 'print $F[-1]'); do\n  if aws s3 ls $TARGET$FILE >/dev/null; then\n    echo \"$TARGET$FILE already exists (maybe from another branch?)\"\n    exit 1\n  fi\ndone\n\necho Copying to $TARGET\naws s3 cp --acl public-read --recursive s3://com.meteor.jenkins/$DIRNAME/ $TARGET\n"
  },
  {
    "path": "scripts/admin/copy-windows-installer-from-jenkins.sh",
    "content": "#!/usr/bin/env bash\n\n# Run this script on Mac/Linux, not on Windows\n# Requires awscli to be installed and an appropriate ~/.aws/config.\n# Usage:\n#    scripts/admin/copy-windows-installer-from-jenkins.sh BUILDNUMBER\n# where BUILDNUMBER is the small integer Jenkins build number.\n\nset -e\nset -u\n\ncd \"$(dirname \"$0\")\"\n\nTARGET=\"s3://meteor-windows/installers/\"\n\nif [ $# -ne 1 ]; then\n    echo \"usage: $0 jenkins-build-number\" 1>&2\n    exit 1\nfi\n\n# installer-windows--${METEOR_RELEASE}--${BUILD_ID}--${BUILD_NUMBER}--${GIT_COMMIT}\nDIRNAME=$(aws s3 ls s3://com.meteor.jenkins/ | perl -nle 'print $1 if m!(installer-windows--.+--.+--'$1'--.+)/!')\nRELEASE=$(echo $DIRNAME | perl -pe 's/^installer-windows--(.+)--.+--.+--.+$/$1/')\n\nif [ -z \"$DIRNAME\" ]; then\n    echo \"build not found\" 1>&2\n    exit 1\nfi\n\necho Found build \"$DIRNAME\"\n\n# aws s3 ls returns 0 when it lists nothing\nif [[ $(aws s3 ls \"s3://com.meteor.jenkins/$DIRNAME/InstallMeteor.exe\" | wc -l) == 0 ]]; then\n  echo \"InstallMeteor.exe wasn't found in $DIRNAME, did Jenkins job fail?\"\n  exit 1\nfi\n\naws s3 cp --acl public-read --recursive \"s3://com.meteor.jenkins/$DIRNAME/\" \"$TARGET$RELEASE/\"\n\n"
  },
  {
    "path": "scripts/admin/eslint/.eslintrc",
    "content": "{\n  \"parser\": \"babel-eslint\",\n  \"env\": {\n    \"browser\": true,\n    \"node\": true\n  },\n  \"ecmaFeatures\": {\n    \"arrowFunctions\": true,\n    \"blockBindings\": true,\n    \"classes\": true,\n    \"defaultParams\": true,\n    \"destructuring\": true,\n    \"forOf\": true,\n    \"generators\": false,\n    \"modules\": true,\n    \"objectLiteralComputedProperties\": true,\n    \"objectLiteralDuplicateProperties\": false,\n    \"objectLiteralShorthandMethods\": true,\n    \"objectLiteralShorthandProperties\": true,\n    \"spread\": true,\n    \"superInFunctions\": true,\n    \"templateStrings\": true,\n    \"jsx\": true\n  },\n  \"rules\": {\n/**\n * Strict mode\n */\n    // babel inserts \"use strict\"; for us\n    // http://eslint.org/docs/rules/strict\n    \"strict\": [2, \"never\"],\n\n/**\n * ES6\n */\n    \"no-var\": 2,                     // http://eslint.org/docs/rules/no-var\n\n/**\n * Variables\n */\n    \"no-shadow\": 2,                  // http://eslint.org/docs/rules/no-shadow\n    \"no-shadow-restricted-names\": 2, // http://eslint.org/docs/rules/no-shadow-restricted-names\n    \"no-unused-vars\": [2, {          // http://eslint.org/docs/rules/no-unused-vars\n      \"vars\": \"local\",\n      \"args\": \"after-used\"\n    }],\n    \"no-use-before-define\": [2, \"nofunc\"],       // http://eslint.org/docs/rules/no-use-before-define\n\n/**\n * Possible errors\n */\n    \"comma-dangle\": [1, \"always-multiline\"],    // http://eslint.org/docs/rules/comma-dangle\n    \"no-cond-assign\": [2, \"always\"], // http://eslint.org/docs/rules/no-cond-assign\n    \"no-console\": 1,                 // http://eslint.org/docs/rules/no-console\n    \"no-debugger\": 1,                // http://eslint.org/docs/rules/no-debugger\n    \"no-alert\": 1,                   // http://eslint.org/docs/rules/no-alert\n    \"no-constant-condition\": 1,      // http://eslint.org/docs/rules/no-constant-condition\n    \"no-dupe-keys\": 2,               // http://eslint.org/docs/rules/no-dupe-keys\n    \"no-duplicate-case\": 2,          // http://eslint.org/docs/rules/no-duplicate-case\n    \"no-empty\": 2,                   // http://eslint.org/docs/rules/no-empty\n    \"no-ex-assign\": 2,               // http://eslint.org/docs/rules/no-ex-assign\n    \"no-extra-boolean-cast\": 0,      // http://eslint.org/docs/rules/no-extra-boolean-cast\n    \"no-extra-semi\": 2,              // http://eslint.org/docs/rules/no-extra-semi\n    \"no-func-assign\": 2,             // http://eslint.org/docs/rules/no-func-assign\n    \"no-inner-declarations\": 2,      // http://eslint.org/docs/rules/no-inner-declarations\n    \"no-invalid-regexp\": 2,          // http://eslint.org/docs/rules/no-invalid-regexp\n    \"no-irregular-whitespace\": 2,    // http://eslint.org/docs/rules/no-irregular-whitespace\n    \"no-obj-calls\": 2,               // http://eslint.org/docs/rules/no-obj-calls\n    \"no-reserved-keys\": 2,           // http://eslint.org/docs/rules/no-reserved-keys\n    \"no-sparse-arrays\": 2,           // http://eslint.org/docs/rules/no-sparse-arrays\n    \"no-unreachable\": 2,             // http://eslint.org/docs/rules/no-unreachable\n    \"use-isnan\": 2,                  // http://eslint.org/docs/rules/use-isnan\n    \"block-scoped-var\": 0,           // http://eslint.org/docs/rules/block-scoped-var\n\n/**\n * Best practices\n */\n    \"consistent-return\": 2,          // http://eslint.org/docs/rules/consistent-return\n    \"curly\": [2, \"multi-line\"],      // http://eslint.org/docs/rules/curly\n    \"default-case\": 2,               // http://eslint.org/docs/rules/default-case\n    \"dot-notation\": [2, {            // http://eslint.org/docs/rules/dot-notation\n      \"allowKeywords\": true\n    }],\n    \"eqeqeq\": 2,                     // http://eslint.org/docs/rules/eqeqeq\n    \"guard-for-in\": 2,               // http://eslint.org/docs/rules/guard-for-in\n    \"no-caller\": 2,                  // http://eslint.org/docs/rules/no-caller\n    \"no-else-return\": 2,             // http://eslint.org/docs/rules/no-else-return\n    \"no-eq-null\": 2,                 // http://eslint.org/docs/rules/no-eq-null\n    \"no-eval\": 2,                    // http://eslint.org/docs/rules/no-eval\n    \"no-extend-native\": 2,           // http://eslint.org/docs/rules/no-extend-native\n    \"no-extra-bind\": 2,              // http://eslint.org/docs/rules/no-extra-bind\n    \"no-fallthrough\": 2,             // http://eslint.org/docs/rules/no-fallthrough\n    \"no-floating-decimal\": 2,        // http://eslint.org/docs/rules/no-floating-decimal\n    \"no-implied-eval\": 2,            // http://eslint.org/docs/rules/no-implied-eval\n    \"no-lone-blocks\": 2,             // http://eslint.org/docs/rules/no-lone-blocks\n    \"no-loop-func\": 2,               // http://eslint.org/docs/rules/no-loop-func\n    \"no-multi-str\": 2,               // http://eslint.org/docs/rules/no-multi-str\n    \"no-native-reassign\": 2,         // http://eslint.org/docs/rules/no-native-reassign\n    \"no-new\": 2,                     // http://eslint.org/docs/rules/no-new\n    \"no-new-func\": 2,                // http://eslint.org/docs/rules/no-new-func\n    \"no-new-wrappers\": 2,            // http://eslint.org/docs/rules/no-new-wrappers\n    \"no-octal\": 2,                   // http://eslint.org/docs/rules/no-octal\n    \"no-octal-escape\": 2,            // http://eslint.org/docs/rules/no-octal-escape\n    \"no-param-reassign\": 2,          // http://eslint.org/docs/rules/no-param-reassign\n    \"no-proto\": 2,                   // http://eslint.org/docs/rules/no-proto\n    \"no-redeclare\": 2,               // http://eslint.org/docs/rules/no-redeclare\n    \"no-return-assign\": 2,           // http://eslint.org/docs/rules/no-return-assign\n    \"no-script-url\": 2,              // http://eslint.org/docs/rules/no-script-url\n    \"no-self-compare\": 2,            // http://eslint.org/docs/rules/no-self-compare\n    \"no-sequences\": 2,               // http://eslint.org/docs/rules/no-sequences\n    \"no-throw-literal\": 2,           // http://eslint.org/docs/rules/no-throw-literal\n    \"no-with\": 2,                    // http://eslint.org/docs/rules/no-with\n    \"radix\": 2,                      // http://eslint.org/docs/rules/radix\n    \"vars-on-top\": 2,                // http://eslint.org/docs/rules/vars-on-top\n    \"wrap-iife\": [2, \"any\"],         // http://eslint.org/docs/rules/wrap-iife\n    \"yoda\": 2,                       // http://eslint.org/docs/rules/yoda\n    \"max-len\": [2, 80, 2],           // http://eslint.org/docs/rules/max-len\n\n/**\n * Style\n */\n    \"indent\": [2, 2],                // http://eslint.org/docs/rules/indent\n    \"brace-style\": [2,               // http://eslint.org/docs/rules/brace-style\n      \"1tbs\", {\n      \"allowSingleLine\": true\n    }],\n    \"quotes\": [\n      2, \"single\", \"avoid-escape\"    // http://eslint.org/docs/rules/quotes\n    ],\n    \"camelcase\": [2, {               // http://eslint.org/docs/rules/camelcase\n      \"properties\": \"never\"\n    }],\n    \"comma-spacing\": [2, {           // http://eslint.org/docs/rules/comma-spacing\n      \"before\": false,\n      \"after\": true\n    }],\n    \"comma-style\": [2, \"last\"],      // http://eslint.org/docs/rules/comma-style\n    \"eol-last\": 2,                   // http://eslint.org/docs/rules/eol-last\n    \"func-names\": 1,                 // http://eslint.org/docs/rules/func-names\n    \"func-style\": [2, \"declaration\"], // http://eslint.org/docs/rules/func-style\n    \"key-spacing\": [2, {             // http://eslint.org/docs/rules/key-spacing\n        \"beforeColon\": false,\n        \"afterColon\": true\n    }],\n    \"new-cap\": [2, {                 // http://eslint.org/docs/rules/new-cap\n      \"newIsCap\": true\n    }],\n    \"no-multiple-empty-lines\": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines\n      \"max\": 2\n    }],\n    \"no-nested-ternary\": 2,          // http://eslint.org/docs/rules/no-nested-ternary\n    \"no-new-object\": 2,              // http://eslint.org/docs/rules/no-new-object\n    \"no-array-constructor\": 2,       // http://eslint.org/docs/rules/no-array-constructor\n    \"no-spaced-func\": 2,             // http://eslint.org/docs/rules/no-spaced-func\n    \"no-trailing-spaces\": 2,         // http://eslint.org/docs/rules/no-trailing-spaces\n    \"no-wrap-func\": 2,               // http://eslint.org/docs/rules/no-wrap-func\n    \"no-underscore-dangle\": 0,       // http://eslint.org/docs/rules/no-underscore-dangle\n    \"one-var\": [2, \"never\"],         // http://eslint.org/docs/rules/one-var\n    \"padded-blocks\": [2, \"never\"],   // http://eslint.org/docs/rules/padded-blocks\n    \"semi\": [2, \"always\"],           // http://eslint.org/docs/rules/semi\n    \"semi-spacing\": [2, {            // http://eslint.org/docs/rules/semi-spacing\n      \"before\": false,\n      \"after\": true\n    }],\n    \"space-after-keywords\": 2,       // http://eslint.org/docs/rules/space-after-keywords\n    \"space-before-blocks\": 2,        // http://eslint.org/docs/rules/space-before-blocks\n    \"space-before-function-paren\": [2, \"never\"], // http://eslint.org/docs/rules/space-before-function-paren\n    \"space-infix-ops\": 2,            // http://eslint.org/docs/rules/space-infix-ops\n    \"space-return-throw-case\": 2,    // http://eslint.org/docs/rules/space-return-throw-case\n    \"spaced-line-comment\": 2,        // http://eslint.org/docs/rules/spaced-line-comment\n  }\n}\n"
  },
  {
    "path": "scripts/admin/eslint/.gitignore",
    "content": "node_modules"
  },
  {
    "path": "scripts/admin/eslint/eslint.sh",
    "content": "#!/usr/bin/env bash\n\nORIGDIR=$(pwd)\ncd $(dirname $0)\nSCRIPTDIR=$(pwd)\ncd ../../..\nTOPDIR=$(pwd)\n\nINFINITY=10000\n\ncd \"$SCRIPTDIR\"\n${TOPDIR}/dev_bundle/bin/npm install\n\ncd \"$TOPDIR\"\n\nfiles_to_lint=\".\"\nif [ \"$1\" == \"modified\" ]; then\n  files_to_lint=$(git diff --cached --name-only --diff-filter=ACM \\\n                  | grep '\\.js$')\nfi\n\nif [ -n \"$files_to_lint\" ]; then\n  \"${TOPDIR}/dev_bundle/bin/node\" \\\n    \"${SCRIPTDIR}/node_modules/.bin/eslint\" \\\n    --quiet \\\n    -c \"${SCRIPTDIR}/.eslintrc\" \\\n    $files_to_lint\nfi\n"
  },
  {
    "path": "scripts/admin/eslint/package.json",
    "content": "{\n  \"name\": \"meteor-jsdoc\",\n  \"version\": \"0.0.0\",\n  \"description\": \"no warn\",\n  \"readme\": \"no warn\",\n  \"repository\": \"no warn\",\n  \"dependencies\": {\n    \"eslint\": \"0.22.1\",\n    \"eslint-plugin-react\": \"2.5.0\",\n    \"babel-eslint\": \"4.1.7\"\n  }\n}\n"
  },
  {
    "path": "scripts/admin/find-author-github.sh",
    "content": "#!/usr/bin/env bash\n\nexport ARG=\"$1\"\ncurl -s \"https://github.com/meteor/meteor/commit/$(git log --format=%H -1 --author \"$1\")\" | perl -nle 'm!<span class=\"author-name\"><a href=\"/([^\"]+)\"! and do { my $name = $1; $ENV{ARG} =~ /(<.+>)/; print \"GITHUB: $name $1\"; exit 0 }'\n"
  },
  {
    "path": "scripts/admin/find-new-npm-versions.sh",
    "content": "#!/usr/bin/env bash\nBASEDIR=`dirname $0`\ncat $BASEDIR/generate-dev-bundle.sh | grep \"npm install\" | sed \"s/npm install //\" | sed \"s/@.*//\" | while read PACKAGE\ndo\n  CURRENT_VERSION=`cat $BASEDIR/generate-dev-bundle.sh | grep \"npm install $PACKAGE\" | sed \"s/npm install //\" | sed \"s/.*@//\"`\n  LATEST_VERSION=`$BASEDIR/../dev_bundle/bin/npm info $PACKAGE version 2> /dev/null`\n  if [ \"$CURRENT_VERSION\" != \"$LATEST_VERSION\" ]\n  then\n    echo \"$PACKAGE -- current version: $CURRENT_VERSION, latest version: $LATEST_VERSION\"\n  fi\ndone\n"
  },
  {
    "path": "scripts/admin/git-hooks/pre-commit",
    "content": "#!/bin/sh\n\ncd $(dirname $0)\ncd ../..\n\n# If you want to allow linter errors set this variable to true.\neslint=$(git config hooks.ignore-eslint)\n\necho \"Linting Meteor tool code...\"\n\n./scripts/admin/eslint/eslint.sh modified\nlinter_exit_code=$?\n\nif [ \"$eslint\" != \"true\" ] && [ $linter_exit_code != 0 ]\nthen\n  echo \"Linter errors detected in pre-commit hook.\"\n  echo \n  echo \"Run the linter with ./scripts/admin/eslint/eslint.sh\"\n  echo\n  echo \"If you know what you are doing you can disable this\"\n  echo \"check using:\"\n  echo\n  echo \"  git config hooks.ignore-eslint true\"\n  echo\n  exit 1\nfi\n"
  },
  {
    "path": "scripts/admin/install-from-bootstrap.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\nset -u\n\nif [ $# -ne 1 ]; then\n    echo \"usage: install-from-bootstrap.sh meteor-bootstrap.tgz\" 1>&2\n    exit 1\nfi\n\nTARBALL=\"$1\"\nINSTALL_TMPDIR=\"$HOME/.meteor-install-tmp\"\n\n# Overwrite existing tropohouse/warehouse.\n[ -e \"$HOME/.meteor\" ] && rm -rf \"$HOME/.meteor\"\n\n\nrm -rf \"${INSTALL_TMPDIR}\"\nmkdir \"${INSTALL_TMPDIR}\"\ntar -xzf \"$TARBALL\" -C \"${INSTALL_TMPDIR}\"\n\n# bomb out if it didn't work\ntest -x \"${INSTALL_TMPDIR}/.meteor/meteor\"\nmv \"${INSTALL_TMPDIR}/.meteor\" \"$HOME\"\nrmdir \"${INSTALL_TMPDIR}\"\n# just double-checking :)\ntest -x \"$HOME/.meteor/meteor\"\n\"$HOME/.meteor/meteor\" help\n\necho\necho \"A Meteor packaging release has been installed in ~/.meteor.\"\necho\necho \"Run it with ~/.meteor/meteor\"\n"
  },
  {
    "path": "scripts/admin/jsdoc/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "scripts/admin/jsdoc/docdata-jsdoc-template/publish.js",
    "content": "/*global require: true */\n(function () {\n  'use strict';\n\n  // This file receives data from JSDoc via the `publish` exported function,\n  // and converts it into JSON that is written to a file.\n\n  var fs = require('jsdoc/fs');\n  var helper = require('jsdoc/util/templateHelper');\n\n  var _ = require(\"underscore\");\n  var stringify = require(\"canonical-json\");\n\n  // This is the big map of name -> data that we'll write to a file.\n  var dataContents = {};\n  // List of just the names, which we'll also write to a file.\n  var names = [];\n\n  /**\n   * Get a tag dictionary from the tags field on the object, for custom fields\n   * like package\n   * @param  {JSDocData} data The thing you get in the TaffyDB from JSDoc\n   * @return {Object}      Keys are the parameter names, values are the values.\n   */\n  var getTagDict = function (data) {\n    var tagDict = {};\n\n    if (data.tags) {\n      _.each(data.tags, function (tag) {\n        tagDict[tag.title] = tag.value;\n      });\n    }\n\n    return tagDict;\n  };\n\n  // Fix up a JSDoc entry and add it to `dataContents`.\n  var addToData = function (entry) {\n    _.extend(entry, getTagDict(entry));\n\n    // strip properties we don't want\n    entry.comment = undefined;\n    entry.___id = undefined;\n    entry.___s = undefined;\n    entry.tags = undefined;\n\n    // generate `.filepath` and `.lineno` from `.meta`\n    if (entry.meta && entry.meta.path) {\n      var packagesFolder = 'packages/';\n      var index = entry.meta.path.indexOf(packagesFolder);\n      if (index != -1) {\n        var fullFilePath = entry.meta.path.substr(index + packagesFolder.length) + '/' + entry.meta.filename;\n        entry.filepath = fullFilePath;\n        entry.lineno = entry.meta.lineno;\n      }\n    }\n\n    entry.meta = undefined;\n\n    if (!entry.importfrompackage && entry.filepath) {\n      entry.module = entry.filepath.split('/')[0];\n    } else {\n      entry.module = entry.importfrompackage;\n    }\n\n    names.push(entry.longname);\n    dataContents[entry.longname] = entry;\n  };\n\n  /**\n   Entry point where JSDoc calls us.  It passes us data in the form of\n   a TaffyDB object (which is an in-JS database of sorts that you can\n   query for records.\n\n   @param {TAFFY} taffyData See <http://taffydb.com/>.\n   @param {object} opts\n   @param {Tutorial} tutorials\n   */\n  exports.publish = function(taffyData) {\n    var data = helper.prune(taffyData);\n\n    var namespaces = helper.find(data, {kind: \"namespace\"});\n\n    // prepare all of the namespaces\n    _.each(namespaces, function (namespace) {\n      if (namespace.summary) {\n        addToData(namespace);\n      }\n    });\n\n    var properties = helper.find(data, {kind: \"member\"});\n\n    _.each(properties, function (property) {\n      if (property.summary) {\n        addToData(property);\n      }\n    });\n\n    // Callback descriptions are going to be embeded into Function descriptions\n    // when they are used as arguments, so we always attach them to reference\n    // them later.\n    var callbacks = helper.find(data, {kind: \"typedef\"});\n    _.each(callbacks, function (cb) {\n      delete cb.comment;\n      addToData(cb);\n    });\n\n    var functions = helper.find(data, {kind: \"function\"});\n    var constructors = helper.find(data, {kind: \"class\"});\n\n    // we want to do all of the same transformations to classes and functions\n    functions = functions.concat(constructors);\n\n    // insert all of the function data into the namespaces\n    _.each(functions, function (func) {\n      if (! func.summary) {\n        // we use the @summary tag to indicate that an item is documented\n        return;\n      }\n\n      func.options = [];\n      var filteredParams = [];\n\n      // Starting a param with `options.` makes it an option, not a\n      // param.  Dot (`.`) in this case binds tighter than comma, so\n      // `options.foo,bar` will create an option named `foo, bar`\n      // (representing two options in the docs).  We process pipes so\n      // that `options.foo|bar` also results in `foo, bar`.\n      _.each(func.params, function (param) {\n        param.name = param.name.replace(/,|\\|/g, \", \");\n\n        var splitName = param.name.split(\".\");\n\n        if (splitName.length < 2 || splitName[0] !== \"options\") {\n          // not an option\n          filteredParams.push(param);\n          return;\n        }\n\n        param.name = splitName[1];\n\n        func.options.push(param);\n      });\n\n      func.params = filteredParams;\n\n      // the entire unparsed doc comment.  takes up too much room in the\n      // data file.\n      delete func.comment;\n\n      addToData(func);\n    });\n\n    // write full docs JSON\n    var jsonString = stringify(dataContents, null, 2);\n    var jsString = \"DocsData = \" + jsonString + \";\";\n    jsString = \"// This file is automatically generated by JSDoc; regenerate it with scripts/admin/jsdoc/jsdoc.sh\\n\" + jsString;\n    var docsDataFilename = \"docs/client/data.js\";\n    fs.writeFileSync(docsDataFilename, jsString);\n\n    // write name tree JSON\n    jsonString = stringify(names.sort(), null, 2);\n    var nameTreeFilename= \"docs/client/names.json\";\n    fs.writeFileSync(nameTreeFilename, jsonString);\n  };\n})();\n"
  },
  {
    "path": "scripts/admin/jsdoc/jsdoc-conf.json",
    "content": "{\n  \"plugins\": [\"plugins/markdown\"],\n  \"markdown\": {\n    \"parser\": \"gfm\"\n  },\n  \"source\": {\n    \"exclude\": [\n      \"packages/ddp/sockjs-0.3.4.js\",\n      \"packages/test-in-browser/diff_match_patch_uncompressed.js\",\n      \"packages/jquery/jquery.js\",\n      \"packages/underscore/underscore.js\",\n      \"packages/json/json2.js\",\n      \"packages/minimongo/minimongo_tests.js\",\n      \"tools/node_modules\",\n      \"tools/skel-pack/package.js\"\n    ]\n  }\n}\n"
  },
  {
    "path": "scripts/admin/jsdoc/jsdoc.sh",
    "content": "#!/usr/bin/env bash\n\nORIGDIR=$(pwd)\ncd $(dirname $0)\nSCRIPTDIR=$(pwd)\ncd ../../..\nTOPDIR=$(pwd)\n\nINFINITY=10000\n\ncd \"$SCRIPTDIR\"\n${TOPDIR}/dev_bundle/bin/npm install\n\ncd \"$TOPDIR\"\n# Call git grep to find all js files with the appropriate comment tags,\n# and only then pass it to JSDoc which will parse the JS files.\n# This is a whole lot faster than calling JSDoc recursively.\ngit grep -al \"@summary\" | xargs -L ${INFINITY} -t \\\n    \"${TOPDIR}/dev_bundle/bin/node\" \\\n    \"${SCRIPTDIR}/node_modules/.bin/jsdoc\" \\\n    -t \"${TOPDIR}/scripts/admin/jsdoc/docdata-jsdoc-template\" \\\n    -c \"${TOPDIR}/scripts/admin/jsdoc/jsdoc-conf.json\" \\\n    2>&1 | grep -v 'WARNING: JSDoc does not currently handle'\n"
  },
  {
    "path": "scripts/admin/jsdoc/package.json",
    "content": "{\n  \"name\": \"meteor-jsdoc\",\n  \"version\": \"0.0.0\",\n  \"description\": \"no warn\",\n  \"readme\": \"no warn\",\n  \"repository\": \"no warn\",\n  \"dependencies\": {\n    \"jsdoc\": \"git+https://github.com/jsdoc3/jsdoc.git\",\n    \"canonical-json\": \"0.0.4\"\n  }\n}\n"
  },
  {
    "path": "scripts/admin/launch-meteor",
    "content": "#!/usr/bin/env bash\n\n# This is the script that we install somewhere in your $PATH (as \"meteor\")\n# when you run\n#   $ curl https://install.meteor.com/ | sh\n# It's the only file that we install globally on your system; each user of\n# Meteor gets their own personal package and tools repository, called the\n# warehouse (or, for 0.9.0 and newer, the \"tropohouse\"), in ~/.meteor/. This\n# means that a user can share packages among multiple apps and automatically\n# update to new releases without having to have permissions to write them to\n# anywhere global.\n#\n# All this script does is exec ~/.meteor/meteor. But what if you don't have it\n# yet? In that case, it downloads a \"bootstrap tarball\", which contains the\n# latest version of the Meteor tools, and plops it down at ~/.meteor. In fact,\n# once you've run this once, you don't even really need this script: you can put\n# ~/.meteor/ into your PATH, or a symlink to ~/.meteor/meteor into some other\n# PATH directory. No special permissions needed!\n#\n# To uninstall Meteor from your system, just delete this shell script, and\n# delete your warehouse (~/.meteor/).\n\n\nset -e\nset -u\nset -o pipefail  # so curl failure triggers the \"set -e\"\n\nBOOTSTRAP_URL='https://packages.meteor.com/bootstrap-link'\nMETEOR_WAREHOUSE_DIR=\"${METEOR_WAREHOUSE_DIR:-$HOME/.meteor}\"\n\nif [ ! -x \"$METEOR_WAREHOUSE_DIR/meteor\" ]; then\n  if [ -e \"$METEOR_WAREHOUSE_DIR\" ]; then\n    echo \"'$METEOR_WAREHOUSE_DIR' exists, but '$METEOR_WAREHOUSE_DIR/meteor' is not executable.\" 1>&2\n    echo 1>&2\n    echo \"Remove it and try again.\" 1>&2\n    exit 1\n  fi\n\n  # Bootstrap .meteor from a tarball. First, figure out our architecture.\n\n  UNAME=$(uname)\n  if [ \"$UNAME\" != \"Linux\" -a \"$UNAME\" != \"Darwin\" ] ; then\n      echo \"Sorry, this OS is not supported yet.\"\n      exit 1\n  fi\n\n  if [ \"$UNAME\" = \"Darwin\" ] ; then\n      ### OSX ###\n      if [ \"i386\" != \"$(uname -p)\" -o \"1\" != \"$(sysctl -n hw.cpu64bit_capable 2>/dev/null || echo 0)\" ] ; then\n          # Can't just test uname -m = x86_64, because Snow Leopard can\n          # return other values.\n          echo \"Only 64-bit Intel processors are supported at this time.\"\n          exit 1\n      fi\n      PLATFORM=\"os.osx.x86_64\"\n  elif [ \"$UNAME\" = \"Linux\" ] ; then\n      ### Linux ###\n      LINUX_ARCH=$(uname -m)\n      if [ \"${LINUX_ARCH}\" = \"i686\" ] ; then\n          PLATFORM=\"os.linux.x86_32\"\n      elif [ \"${LINUX_ARCH}\" = \"x86_64\" ] ; then\n          PLATFORM=\"os.linux.x86_64\"\n      else\n          echo \"Unusable architecture: ${LINUX_ARCH}\"\n          echo \"Meteor only supports i686 and x86_64 for now.\"\n          exit 1\n      fi\n  fi\n\n  # This returns something like:\n  #   https://asdfasdfasdf.cloudfront.net/packages-bootstrap/1.2.3\n  TMP_ROOT_URL=\"$(curl -s --fail $BOOTSTRAP_URL)\"\n  TARBALL_URL=\"${TMP_ROOT_URL}/meteor-bootstrap-${PLATFORM}.tar.gz\"\n\n  INSTALL_TMPDIR=\"$(dirname \"$METEOR_WAREHOUSE_DIR\")/.meteor-install-tmp\"\n  rm -rf \"$INSTALL_TMPDIR\"\n  mkdir \"$INSTALL_TMPDIR\"\n  if [ -n \"${USER-}\" ]; then\n    echo \"$USER, this is your first time using Meteor!\" 1>&2\n  else\n    echo \"This is your first time using Meteor!\" 1>&2\n  fi\n  echo \"Installing a Meteor distribution in your home directory.\" 1>&2\n\n  # Only show progress bar animations if we have a tty\n  # (Prevents tons of console junk when installing within a pipe)\n  if [[ -t 1 ]]; then\n    curl --progress-bar --fail \"$TARBALL_URL\" | tar -xzf - -C \"$INSTALL_TMPDIR\"\n  else\n    curl -s --fail \"$TARBALL_URL\" | tar -xzf - -C \"$INSTALL_TMPDIR\"\n  fi\n\n  # bomb out if it didn't work, eg no net\n  test -x \"${INSTALL_TMPDIR}/.meteor/meteor\"\n  mv \"${INSTALL_TMPDIR}/.meteor\" \"$METEOR_WAREHOUSE_DIR\"\n  rmdir \"${INSTALL_TMPDIR}\"\n  # just double-checking :)\n  test -x \"$METEOR_WAREHOUSE_DIR/meteor\"\nfi\n\nexec \"$METEOR_WAREHOUSE_DIR/meteor\" \"$@\"\n"
  },
  {
    "path": "scripts/admin/manifest.json",
    "content": "{\n    \"releases\": {\n        \"stable\": {\n            \"version\": \"1.0.1\",\n            \"banner\": \"=> Meteor 1.0 is out! Visit www.meteor.com for all the details.\\n\\n   Meteor 1.0 is being downloaded in the background. You can update to\\n   it by running 'meteor update'.\"\n        }\n    },\n    \"version\": \"1.0.0\",\n    \"deb_version\": \"1.0.0-1\",\n    \"rpm_version\": \"1.0.0-1\",\n    \"urlbase\": \"https://d3sqy0vbqsdhku.cloudfront.net\"\n}\n"
  },
  {
    "path": "scripts/admin/meteor-release-experimental.json",
    "content": "{\n \"track\": \"METEOR\",\n \"version\": \"1.3.4.1-rc.0\",\n \"recommended\": false,\n \"official\": false,\n \"description\": \"Meteor\"\n}\n"
  },
  {
    "path": "scripts/admin/meteor-release-official.json",
    "content": "{\n  \"track\": \"METEOR\",\n  \"version\": \"1.3.4.1\",\n  \"recommended\": false,\n  \"official\": true,\n  \"description\": \"The Official Meteor Distribution\"\n}\n"
  },
  {
    "path": "scripts/admin/old-banner.txt",
    "content": "# Copy this into manifest.json.\n\n=> Meteor 0.9.0: Introducing the official Meteor package system,\n   including Isobuild and the Meteor Package Server!\n\n   Starting in 0.9.0, you can publish your own packages and use any of\n   the over 1800 community packages in your app, without needing an\n   external tool such as Meteorite. Just use commands like 'meteor add\n   <packagename>', 'meteor publish', and 'meteor search <query>'.\n\n   This release is being downloaded in the background. It's a big\n   change! Once it's done downloading, then the next time you run\n   'meteor', your Meteor install will be automatically upgraded to the\n   new system. The upgrade will take a few minutes and as part of it\n   old versions of Meteor will be removed from your machine. These old\n   versions will be automatically redownloaded using the new system if\n   you work on apps that use them.\n"
  },
  {
    "path": "scripts/admin/publish-meteor-tool-on-all-platforms.sh",
    "content": "#!/usr/bin/env bash\n\n# This scripts automates the release process of Meteor Tool.\n\n# Normally, after publishing a new Meteor release from checkout, you need to ssh\n# to a machine running every supported platform and publish a build from it.\n# This script automates ssh'ing into machines and running the publish command.\n\nset -e\nset -u\n\nTEMP_PRIV_KEY=\nTEMP_KEY=\nSESSION_FILE=\n\nmain () {\n  if [ $# -ne 1 ]; then\n    echo \"usage: $0 GITSHA\" 1>&2\n    echo \"The passed commit is checked out and published from the remote machines.\" 1>&2\n    exit 1\n  fi\n  GITSHA=$1\n\n  ADMIN_DIR=\"`dirname \"$0\"`\"\n  SCRIPTS_DIR=\"`dirname \"$ADMIN_DIR\"`\"\n  CHECKOUT_DIR=\"`dirname \"$SCRIPTS_DIR\"`\"\n\n  METEOR=\"$CHECKOUT_DIR/meteor\"\n\n  trap 'echo \"${red}Login failed.${NC}\"; clean_up' EXIT\n\n  echo \"${green}Login with a meteor account belonging to MDG.\"\n  echo \"A session file will be generated in your checkout and it will be used to\"\n  echo \"publish the release from the remote machines.${NC}\"\n\n  SESSION_FILE=\"$CHECKOUT_DIR/publish-meteor-tool-session\"\n  env METEOR_SESSION_FILE=\"$SESSION_FILE\" \"$METEOR\" login\n\n  echo \"${green}Login succeeded.${NC}\"\n  echo\n  echo \"Run the following commands in separate terminal windows:\"\n  echo\n\n  # XXX there is no os.windows.x86_64 as we don't build for it at the moment\n  PLATFORMS=( os.osx.x86_64 os.linux.x86_64 os.linux.x86_32 os.windows.x86_32 )\n  for PLATFORM in ${PLATFORMS[@]}; do\n    COMMAND=\"`dirname $0`/publish-meteor-tool-on-arch.sh $GITSHA $PLATFORM $SESSION_FILE\"\n    echo $COMMAND\n  done\n\n  trap - EXIT\n}\n\nclean_up () {\n  if [[ \"x$SESSION_FILE\" != x ]]; then\n    echo \"Removing used session file.\"\n    rm \"$SESSION_FILE\"\n  fi\n\n  exit 1\n}\n\n# '|| true' so that we don't fail on terminals without colors\nred=`tput setaf 1 || true`\ngreen=`tput setaf 2 || true`\nNC=`tput sgr0 || true`\n\nmain $@\n\n"
  },
  {
    "path": "scripts/admin/publish-meteor-tool-on-arch.sh",
    "content": "#!/usr/bin/env bash\n\n# This scripts automates the release process of Meteor Tool.\n\n# Normally, after publishing a new Meteor release from checkout, you need to ssh\n# to a machine running every supported platform and publish a build from it.\n# This script automates ssh'ing into machines and running the publish command.\n\nset -e\nset -u\n\nTEMP_PRIV_KEY=\nTEMP_KEY=\nSESSION_FILE=\n\nmain () {\n  if [ $# -ne 3 ]; then\n    echo \"usage: $0 <git sha> <platform> <path to meteor session>\" 1>&2\n    echo \"The passed sha1 is checked out and published from the machines.\" 1>&2\n    echo \"Options for platform:\" 1>&2\n    echo \"  os.osx.x86_64 os.linux.x86_64 os.linux.x86_32\" 1>&2\n    echo \"  os.windows.x86_32 os.windows.x86_64\" 1>&2\n    exit 1\n  fi\n\n  GITSHA=$1\n  PLATFORM=$2\n  SESSION_FILE=$3\n\n  ADMIN_DIR=\"`dirname \"$0\"`\"\n  SCRIPTS_DIR=\"`dirname \"$ADMIN_DIR\"`\"\n  CHECKOUT_DIR=\"`dirname \"$SCRIPTS_DIR\"`\"\n\n  METEOR=\"$CHECKOUT_DIR/meteor\"\n\n  UNIX_PLATFORMS=( os.osx.x86_64 os.linux.x86_64 os.linux.x86_32 )\n  WINDOWS_PLATFORMS=( os.windows.x86_32 os.windows.x86_64 )\n\n  if [[ $PLATFORM =~ ^(os\\.linux|os\\.osx) ]] ; then\n    echo \"${green}Publishing from unixy platform.${NC}\"\n\n    parse_keys\n\n    echo \"${green}Going to ssh into machine running $PLATFORM and publish the release${NC}\"\n    trap 'echo \"${red}Failed to publish from $PLATFORM${NC}\"; clean_up' EXIT\n    # copy the meteor session file to the remote host\n    scp -oUserKnownHostsFile=\"$TEMP_KEY\" -P \"$PORT\" -i \"$TEMP_PRIV_KEY\" -q \"$SESSION_FILE\" $USERNAME@$HOST:~/session\n\n    METEOR_SESSION_FILE=\"$SESSION_FILE\" \"$METEOR\" admin get-machine --minutes 30 $PLATFORM <<'END'\nset -e\nset -u\nif [ -d meteor ]; then\n  rm -rf meteor\nfi\ngit clone https://github.com/meteor/meteor.git\ncd meteor\ngit fetch --tags\nEND\n\n    # checkout the SHA1 we want to publish\n    echo \"cd meteor; git checkout $GITSHA\" | METEOR_SESSION_FILE=\"$SESSION_FILE\" \"$METEOR\" admin get-machine \"$PLATFORM\"\n    # publish the release\n    echo \"cd meteor/packages/meteor-tool && env METEOR_SESSION_FILE=~/session ../../meteor publish --existing-version\" | METEOR_SESSION_FILE=$SESSION_FILE $METEOR admin get-machine $PLATFORM\n\n    trap - EXIT\n  else\n    echo \"${green}Publishing from Windowsy platform.${NC}\"\n\n    parse_keys\n\n    echo \"${green}Going to ssh into machine running $PLATFORM and publish the release${NC}\"\n    trap 'echo \"${red}Failed to publish from $PLATFORM${NC}\"; clean_up' EXIT\n\n    # copy the meteor session file to the remote host\n    SESSION_CONTENT=$(cat $SESSION_FILE | tr '\\n' ' ')\n    ssh $USERNAME@$HOST -oUserKnownHostsFile=\"$TEMP_KEY\" -p \"$PORT\" -i \"$TEMP_PRIV_KEY\" \"cmd /c echo $SESSION_CONTENT > C:\\\\meteor-session\" 2>/dev/null\n\n    # delete existing batch script if it exists\n    ssh $USERNAME@$HOST -oUserKnownHostsFile=\"$TEMP_KEY\" -p \"$PORT\" -i \"$TEMP_PRIV_KEY\" \"cmd /c del C:\\\\publish-tool.bat || exit 0\" 2>/dev/null\n\n    # copy batch script to windows machine, in a funky way, by splicing each\n    # line of publish-meteor-tool.bat into a Windows `echo` command, with no\n    # escaping.\n    # therefore, the lines of publish-meteor-tool.bat must already be\n    # escaped, for example `>` as `^>` and `%` as `^%`.\n\n    BAT_FILENAME=\"$ADMIN_DIR/publish-meteor-tool.bat\"\n\n    # we need to use file descriptor 10 because otherwise SSH will conflict with\n    # the while loop\n    while read -u10 -r line\n    do\n      line=\"${line/\\$GITSHA/$GITSHA}\"\n\n      # skip empty lines and comments\n      if [[ x$line == x ]] || [[ $line == \"REM \"* ]]; then\n        continue\n      fi\n\n      echo $line\n      ssh $USERNAME@$HOST -oUserKnownHostsFile=\"$TEMP_KEY\" -p \"$PORT\" -i \"$TEMP_PRIV_KEY\" \"cmd /c echo $line>> C:\\\\publish-tool.bat\" 2>/dev/null\n    done 10< \"$BAT_FILENAME\"\n\n    ssh $USERNAME@$HOST -oUserKnownHostsFile=$TEMP_KEY -p $PORT -i $TEMP_PRIV_KEY \"C:\\\\publish-tool.bat\"\n\n    trap - EXIT\n  fi\n\n  clean_up\n}\n\n# get keys from \"meteor admin get-machine\" command\n# inputs: SESSION_FILE, METEOR, PLATFORM, CHECKOUT_DIR\n# outputs: USERNAME, HOST, PORT, TEMP_KEY, TEMP_PRIV_KEY\nparse_keys () {\n  trap 'echo \"${red}Failed to parse the machine credentials${NC}\";clean_up' EXIT\n  CREDS=$(METEOR_SESSION_FILE=\"$SESSION_FILE\" \"$METEOR\" admin get-machine $PLATFORM --json)\n\n  # save host key and login private key to temp files\n  echo \"$CREDS\" | get_from_json \"key\" > \"$CHECKOUT_DIR/temp_priv_key_$PLATFORM\"\n  TEMP_PRIV_KEY=\"$CHECKOUT_DIR/temp_priv_key_$PLATFORM\"\n  chmod 600 \"$TEMP_PRIV_KEY\"\n\n  USERNAME=$(echo $CREDS | get_from_json \"username\")\n  HOST=$(echo $CREDS | get_from_json \"host\")\n  PORT=$(echo $CREDS | get_from_json \"port\")\n  echo -n \"$HOST \" > \"$CHECKOUT_DIR/temp_key_$PLATFORM\"\n  echo $CREDS | get_from_json \"hostKey\" >> \"$CHECKOUT_DIR/temp_key_$PLATFORM\"\n\n  TEMP_KEY=\"$CHECKOUT_DIR/temp_key_$PLATFORM\"\n\n  trap - EXIT\n}\n\n# print a value from a JSON file by key\nget_from_json () {\n  \"$CHECKOUT_DIR/dev_bundle/bin/node\" -e \"console.log(JSON.parse(require('fs').readFileSync('/dev/stdin').toString())['$1'])\"\n}\n\nclean_up () {\n  if [[ \"x$TEMP_KEY\" != x ]]; then\n    echo \"Removing remaining keys\"\n    rm \"$TEMP_KEY\"\n  fi\n  if [[ \"x$TEMP_PRIV_KEY\" != x ]]; then\n    rm \"$TEMP_PRIV_KEY\"\n  fi\n\n  exit 1\n}\n\n# '|| true' so that we don't fail on terminals without colors\nred=`tput setaf 1 || true`\ngreen=`tput setaf 2 || true`\nNC=`tput sgr0 || true`\n\nmain $@\n\n"
  },
  {
    "path": "scripts/admin/publish-meteor-tool.bat",
    "content": "REM This file is copied line by line by the publish-meteor-tool-on-arch.sh script\nREM Since it is copied via separate ssh commands, all special symbols here are\nREM escaped with the carat (\"^\")\nREM This script usually runs only on a build farm Windows machines, this is why\nREM it has some assumptions about having executables on certain paths\n\nREM nuke the working directory\nIF EXIST C:\\tmp ( rmdir /s /q C:\\tmp )\n\nmd C:\\tmp\ncd C:\\tmp\n\nREM get the meteor/meteor repo\nC:\\git\\bin\\git.exe clone https://github.com/meteor/meteor.git\ncd meteor\nREM force git to use original end-line characters (unixy '\\n')\nC:\\git\\bin\\git.exe config --replace-all core.autocrlf input\nC:\\git\\bin\\git.exe rm --cached -r . ^> nul\nC:\\git\\bin\\git.exe reset --hard\nC:\\git\\bin\\git.exe fetch --tags\nREM GITSHA is replaced by the script transferring this file\nC:\\git\\bin\\git.exe checkout $GITSHA\n\nREM install 7-zip, required for running meteor from checkout\nC:\\git\\bin\\curl -L http://downloads.sourceforge.net/sevenzip/7z920.msi ^> C:\\7z.msi\nmsiexec /i C:\\7z.msi /quiet /qn /norestart\nset PATH=^%PATH^%;\"C:\\Program Files\\7-Zip\"\nREM wait 3 seconds to avoid races with the 7-zip installation\nping -n 4 127.0.0.1 ^> nul\n\nREM run meteor and publish the release\npowershell \"Set-ExecutionPolicy ByPass\"\n.\\meteor.bat --help ^> nul 2^>^&^1 || echo \"First npm failure is expected\"\ncd C:\\tmp\\meteor\\packages\\meteor-tool\nREM we expect that the meteor-session file is transferred before-hand by\nREM publish-meteor-tool-on-arch.sh\nset METEOR_SESSION_FILE=C:\\meteor-session\nREM in case of failure, print the log of the operation\n..\\..\\meteor.bat publish --existing-version\n\n"
  },
  {
    "path": "scripts/admin/test-packages-with-mongo-versions.rb",
    "content": "#! /usr/bin/env ruby\n\n# This script downloads and installs any number of versions of Mongo, and runs\n# the console version of test-packages on them. The test output is stored in a\n# directory called \"mongo-test-output\" in the root of your checkout.\n\nrequire 'tmpdir'\n\nmongo_install_urls = {\n  \"3.0.5\" => \"https://fastdl.mongodb.org/osx/mongodb-osx-x86_64-3.0.5.tgz\",\n  \"2.6.10\" => \"http://downloads.mongodb.org/osx/mongodb-osx-x86_64-2.6.10.tgz\",\n  \"2.4.14\" => \"http://downloads.mongodb.org/osx/mongodb-osx-x86_64-2.4.14.tgz\"\n}\n\nmongo_port = \"12345\"\n\ndirname = File.dirname(__FILE__)\npath_to_test_in_console = File.realpath File.join dirname, \"..\", \"..\", \"packages\", \"test-in-console\", \"run.sh\"\npath_to_output = File.realpath File.join dirname, \"..\", \"..\", \"mongo-test-output\"\n\nunless Dir[path_to_output]\n  Dir.mkdir path_to_output\nend\n\nputs \"Putting output in: #{path_to_output}/\"\n\n[\"3.0.5\", \"2.6.10\", \"2.4.14\"].each do |mongo_version|\n  puts \"Installing and testing with Mongo #{mongo_version}...\"\n\n  Dir.mktmpdir \"mongo_install\" do |mongo_install_dir|\n    Dir.chdir mongo_install_dir do\n      `curl -O #{mongo_install_urls[mongo_version]}`\n      `tar -zxvf mongodb-osx-x86_64-#{mongo_version}.tgz`\n      `mkdir -p db`\n\n      pid = fork do\n        exec \"./mongodb-osx-x86_64-#{mongo_version}/bin/mongod --dbpath db --port #{mongo_port}\"\n      end\n\n      sleep(3)\n\n      mongo_env = \"MONGO_URL=mongodb://localhost:#{mongo_port}/test_db\"\n\n      puts \"Running test-in-console from: #{path_to_test_in_console}\"\n      puts \"Passing #{mongo_env}\"\n      `#{mongo_env} bash #{path_to_test_in_console} > #{path_to_output}/#{mongo_version}.txt`\n\n      # Kill Mongo\n      Process.kill \"TERM\", pid\n    end\n  end\nend\n"
  },
  {
    "path": "scripts/benchmarks/initial-start-time.sh",
    "content": "#! /bin/sh\n\nset -e\n\ncheckout_dir=\"$(dirname $0)/../../\"\ncd $checkout_dir\ncheckout_dir=$(pwd)\n\napp_dir=`mktemp -d /tmp/meteor-bench-app.XXXX`\n\ncd $app_dir\n$checkout_dir/meteor create --example todos . > /dev/null\n\n# Add a file to the app that shuts it down immediately\necho \"Meteor.startup(function(){process.exit(0)});\" > \"exit.js\"\n\n# Run once to build all of the packages\n$checkout_dir/meteor --once &> /dev/null\n\nfor i in `seq 10`; do\n  # Run again to time\n  /usr/bin/time -p $checkout_dir/meteor --once 1> /dev/null 2> out\n\n  BENCHMARK_OUTPUT=`cat out`\n\n  # Get first line\n  BENCHMARK_OUTPUT=$(echo \"$BENCHMARK_OUTPUT\" | head -n 1)\n  ARRAY=($BENCHMARK_OUTPUT)\n  NUMBER=${ARRAY[1]}\n\n  # Print output\n  echo $NUMBER\ndone\n\ncd $checkout_dir\n\n# XXX are we going to rm -rf our whole disk by accident here?\nrm -rf \"$app_dir\"\n"
  },
  {
    "path": "scripts/build-dev-bundle-common.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\nset -u\n\nUNAME=$(uname)\nARCH=$(uname -m)\nNODE_VERSION=0.10.45\nNPM_VERSION=3.9.6\n\n# save number of processors to define max parallelism for build processes\n# we call that via additional bash process to not get trapped on error\n# Linux and compatible...\nNPROCESSORS=$(/usr/bin/env bash -c \"getconf _NPROCESSORS_ONLN 2>/dev/null; exit 0\")\n# FreeBSD and compatible...\n[ -z \"$NPROCESSORS\" ] && NPROCESSORS=$(/usr/bin/env bash -c \"getconf NPROCESSORS_ONLN 2>/dev/null; exit 0\")\n# Not identifiable, set fix to minimal resources...\n[ -z \"$NPROCESSORS\" ] && NPROCESSORS=1\n\n# The METEOR_UNIVERSAL_FLAG will save the indicator how to handle unofficially\n# support environments. For armvXl boards we are support pre built binaries from\n# bintray. For all other systems we check, that there are system binries available\n# for node and mongo. If METEOR_UNIVERSAL_FLAG is not set, then this runs as same \n# as official meteor installer and starter\nMETEOR_UNIVERSAL_FLAG=\n\nif [ \"$UNAME\" == \"Linux\" ] ; then\n    if [ \"$ARCH\" != \"i686\" -a \"$ARCH\" != \"x86_64\" ] ; then\n        if [ \"$ARCH\" != \"armv6l\" -a \"$ARCH\" != \"armv7l\" ] ; then\n            # set flag that we are in universal system environment support mode\n            METEOR_UNIVERSAL_FLAG=\"env\"\n        else\n            # set flag that we are in unofficial ARM support mode\n            METEOR_UNIVERSAL_FLAG=\"arm\"\n        fi\n    fi\n\n    OS=\"linux\"\n\n    stripBinary() {\n        strip --remove-section=.comment --remove-section=.note $1\n    }\nelif [ \"$UNAME\" = \"FreeBSD\" -o \"$UNAME\" = \"OpenBSD\" -o \"$UNAME\" = \"NetBSD\" ] ; then\n    if [ \"$ARCH\" != \"i686\" -a \"$ARCH\" != \"x86_64\" -a \"$ARCH\" != \"amd64\" ] ; then\n        # set flag that we are in universal system environment support mode\n        METEOR_UNIVERSAL_FLAG=\"env\"\n    else\n        # set flag that we are in unofficial xBSD support mode\n        METEOR_UNIVERSAL_FLAG=\"bsd\"\n    fi\n\n    OS=\"bsd\"\n\n    stripBinary() {\n        strip --remove-section=.comment --remove-section=.note $1\n    }\nelif [ \"$UNAME\" == \"Darwin\" ] ; then\n    SYSCTL_64BIT=$(sysctl -n hw.cpu64bit_capable 2>/dev/null || echo 0)\n    if [ \"$ARCH\" == \"i386\" -a \"1\" != \"$SYSCTL_64BIT\" ] ; then\n        # some older macos returns i386 but can run 64 bit binaries.\n        # Probably should distribute binaries built on these machines,\n        # but it should be OK for users to run.\n        ARCH=\"x86_64\"\n    fi\n\n    if [ \"$ARCH\" != \"x86_64\" ] ; then\n        echo \"Unsupported architecture: $ARCH\"\n        echo \"Meteor only supports x86_64 for now.\"\n        exit 1\n    fi\n\n    OS=\"osx\"\n\n    # We don't strip on Mac because we don't know a safe command. (Can't strip\n    # too much because we do need node to be able to load objects like\n    # fibers.node.)\n    stripBinary() {\n        true\n    }\nelse\n    echo \"This OS not yet supported\"\n    exit 1\nfi\n\nPLATFORM=\"${UNAME}_${ARCH}\"\n\n# If using METEOR UNIVERSAL we can skip this test for NODE_TGZ\nif [ -n \"$METEOR_UNIVERSAL_FLAG\" ]\nthen\n    # create unusable setting here just as a \"Debug\" output\n    # this will be normally overriden in generate-dev-bundle.sh when\n    # separate build of node is available by build-node-for-dev-bundle.sh\n    NODE_TGZ=\"when-using-meteor-universal-you-need-to-get-node-binaries-yourself_${PLATFORM}.tar.gz\"\nelif [ \"$UNAME\" == \"Linux\" ]\nthen\n    if [ \"$ARCH\" == \"i686\" ]\n    then\n        NODE_TGZ=\"node-v${NODE_VERSION}-linux-x86.tar.gz\"\n    elif [ \"$ARCH\" == \"x86_64\" ]\n    then\n        NODE_TGZ=\"node-v${NODE_VERSION}-linux-x64.tar.gz\"\n    else\n        echo \"Unknown architecture: $UNAME $ARCH\"\n        exit 1\n    fi\nelif [ \"$UNAME\" == \"Darwin\" ]\nthen\n    NODE_TGZ=\"node-v${NODE_VERSION}-darwin-x64.tar.gz\"\nelse\n    echo \"Unknown architecture: $UNAME $ARCH\"\n    exit 1\nfi\n\nSCRIPTS_DIR=$(dirname $0)\ncd \"$SCRIPTS_DIR/..\"\nCHECKOUT_DIR=$(pwd)\n\nDIR=$(mktemp -d -t generate-dev-bundle-XXXXXXXX)\ntrap 'rm -rf \"$DIR\" >/dev/null 2>&1' 0\n\ncd \"$DIR\"\nchmod 755 .\numask 022\nmkdir build\ncd build\n"
  },
  {
    "path": "scripts/build-mongo-for-dev-bundle.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\nset -u\n\nMONGO_VERSION=\"2.6.7\"\n\nsource \"$(dirname $0)/build-dev-bundle-common.sh\"\necho CHECKOUT DIR IS \"$CHECKOUT_DIR\"\necho BUILDING MONGO \"v$MONGO_VERSION\" IN \"$DIR\"\n\n# Checkout and build mongodb.\n# We want to build a binary that includes SSL support but does not depend on a\n# particular version of openssl on the host system.\n\nOPENSSL=\"openssl-1.0.2h\"\nOPENSSL_URL=\"http://www.openssl.org/source/$OPENSSL.tar.gz\"\nwget $OPENSSL_URL || curl -O $OPENSSL_URL\ntar xzf $OPENSSL.tar.gz\n\ncd $OPENSSL\nif [ \"$UNAME\" == \"Linux\" ]; then\n    ./config --prefix=\"$DIR/build/openssl-out\" no-shared\nelse\n    # This configuration line is taken from Homebrew formula:\n    # https://github.com/mxcl/homebrew/blob/master/Library/Formula/openssl.rb\n    ./Configure no-shared zlib-dynamic --prefix=\"$DIR/build/openssl-out\" darwin64-x86_64-cc enable-ec_nistp_64_gcc_128\nfi\nmake install\n\n# To see the mongo changelog, go to http://www.mongodb.org/downloads,\n# click 'changelog' under the current version, then 'release notes' in\n# the upper right.\ncd \"$DIR/build\"\n\n# We use Meteor fork since we added some changes to the building script.\n# Our patches allow us to link most of the libraries statically.\ngit clone --branch \"ssl-r$MONGO_VERSION\" --depth 1 \\\n    git://github.com/4commerce-technologies-AG/mongo.git\ncd mongo\nrm -rf .git\n\n# Compile\n\n# check number of cores for parallelism flag\nif [ \"$NPROCESSORS\" -lt \"4\" ] ; then\n    MONGO_FLAGS=\"--ssl --release -j1 \"\nelse\n    MONGO_FLAGS=\"--ssl --release -j4 \"\nfi\n\nMONGO_FLAGS+=\"--cpppath=$DIR/build/openssl-out/include --libpath=$DIR/build/openssl-out/lib \"\n\nif [ \"$OS\" == \"osx\" ]; then\n    # NOTE: '--64' option breaks the compilation, even it is on by default on x64 mac: https://jira.mongodb.org/browse/SERVER-5575\n    MONGO_FLAGS+=\"--openssl=$DIR/build/openssl-out/lib \"\n    /usr/local/bin/scons $MONGO_FLAGS mongo mongod\nelif [ \"$OS\" == \"linux\" ]; then\n    MONGO_FLAGS+=\"--no-glibc-check --prefix=./ \"\n    if [ \"$ARCH\" == \"x86_64\" ]; then\n      MONGO_FLAGS+=\"--64\"\n    fi\n    scons $MONGO_FLAGS mongo mongod\nelse\n    echo \"We don't know how to compile mongo for this platform\"\n    exit 1\nfi\n\necho \"Done with scons build\"\n\n# Copy binaries\nmkdir -p \"$DIR/mongodb/bin\"\ncp mongo \"$DIR/mongodb/bin/\"\ncp mongod \"$DIR/mongodb/bin/\"\n\n# Copy mongodb distribution information\nfind ./distsrc -maxdepth 1 -type f -exec cp '{}' ../mongodb \\;\n\ncd \"$DIR\"\nstripBinary mongodb/bin/mongo\nstripBinary mongodb/bin/mongod\n\necho BUNDLING\n\ncd \"$DIR\"\nrm -rf build\ntar czvf \"${CHECKOUT_DIR}/mongo_${PLATFORM}_v${MONGO_VERSION}.tar.gz\" .\n\necho DONE\n"
  },
  {
    "path": "scripts/build-node-for-dev-bundle.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\nset -u\n\n# When upgrading node versions, also update the values of MIN_NODE_VERSION at\n# the top of tools/main.js and tools/server/boot.js, and the text in\n# docs/client/full-api/concepts.html and the README in tools/bundler.js.\nNODE_VERSION=0.10.45\n\nsource \"$(dirname $0)/build-dev-bundle-common.sh\"\necho CHECKOUT DIR IS \"$CHECKOUT_DIR\"\necho BUILDING NODE \"v$NODE_VERSION\" IN \"$DIR\"\n\ngit clone --branch \"v${NODE_VERSION}\" --depth 1 \\\n    https://github.com/nodejs/node.git\ncd node\nrm -rf .git\nif [ \"$ARCH\" = \"armv6l\" -o \"$ARCH\" = \"armv7l\" ] ; then\n  ./configure --without-snapshot --prefix=\"$DIR\"\nelse\n  ./configure --prefix=\"$DIR\"\nfi\n\nif [ \"$OS\" = \"bsd\" ] ; then\n    MAKE_CMD=gmake\nelse\n    MAKE_CMD=make\nfi\n\n# check number of cores for parallelism flag\nif [ \"$NPROCESSORS\" -lt \"4\" ] ; then\n    $MAKE_CMD -j1\nelse\n    $MAKE_CMD -j4\nfi\n$MAKE_CMD install PORTABLE=1\n# PORTABLE=1 is a node hack to make npm look relative to itself instead\n# of hard coding the PREFIX.\n\ncd \"$DIR\"\nstripBinary bin/node\n\n# export path so we use our new node for later builds\nPATH=\"$DIR/bin:$PATH\"\nwhich node\nwhich npm\n\necho BUNDLING\n\ncd \"$DIR\"\nrm -rf build\ntar czvf \"${CHECKOUT_DIR}/node_${PLATFORM}_v${NODE_VERSION}.tar.gz\" .\n\necho DONE\n"
  },
  {
    "path": "scripts/ci.sh",
    "content": "export TIMEOUT_SCALE_FACTOR=15\nexport TEST_PACKAGES_EXCLUDE=\"less\"\nexport SELF_TEST_EXCLUDE=\"^can't publish package with colons|^old cli tests|^logs - logged (in|out)|^mongo - logged (in|out)|^minifiers can't register non-js|^minifiers: apps can't use|^compiler plugins - addAssets\"\n\n# Don't print as many progress indicators\nexport EMACS=t\n\n# Since PhantomJS has been removed from dev_bundle/lib/node_modules\n# (#6905), but self-test still needs it, install it now.\n./meteor npm install -g phantomjs-prebuilt\n\n# run different jobs based on CicleCI parallel container index\ncase $CIRCLE_NODE_INDEX in\n0)\n  echo \"Running warehouse self-tests\"\n  ./meteor self-test --headless \\\n      --with-tag \"custom-warehouse\" \\\n      --exclude \"$SELF_TEST_EXCLUDE\"\n  ;;\n1)\n  echo \"Running self-test (1): A-Com\"\n  ./meteor self-test --headless \\\n      --file \"^[a-b]|^c[a-n]|^co[a-l]|^compiler-plugins\" \\\n      --without-tag \"custom-warehouse\" \\\n      --exclude \"$SELF_TEST_EXCLUDE\"\n  ;;\n2)\n  echo \"Running self-test (2): Con-K\"\n  ./meteor self-test --headless \\\n      --file \"^co[n-z]|^c[p-z]|^[d-k]\" \\\n      --without-tag \"custom-warehouse\" \\\n      --exclude \"$SELF_TEST_EXCLUDE\"\n  ;;\n3)\n  echo \"Running self-test (3): L-O\"\n  ./meteor self-test --headless \\\n      --file \"^[l-o]\" \\\n      --without-tag \"custom-warehouse\" \\\n      --exclude \"$SELF_TEST_EXCLUDE\"\n  ;;\n4)\n  echo \"Running self-test (4): P\"\n  ./meteor self-test --headless \\\n      --file \"^p\" \\\n      --without-tag \"custom-warehouse\" \\\n      --exclude \"$SELF_TEST_EXCLUDE\"\n  ;;\n5)\n  echo \"Running self-test (5): Run\"\n  ./meteor self-test --headless \\\n      --file \"^run\" \\\n      --without-tag \"custom-warehouse\" \\\n      --exclude \"$SELF_TEST_EXCLUDE\"\n  ;;\n6)\n  echo \"Running self-test (6): R-S\"\n  ./meteor self-test --headless \\\n      --file \"^r(?!un)|^s\" \\\n      --without-tag \"custom-warehouse\" \\\n      --exclude \"$SELF_TEST_EXCLUDE\"\n  ;;\n7)\n  echo \"Running self-test (7): Sp-Z\"\n  ./meteor self-test --headless \\\n      --file \"^[t-z]|^command-line\" \\\n      --without-tag \"custom-warehouse\" \\\n      --exclude \"$SELF_TEST_EXCLUDE\"\n  ;;\nesac\n"
  },
  {
    "path": "scripts/dev-bundle-server-package.js",
    "content": "// This file contains a package.json for the dependencies of the *BUNDLED\n// SERVER* (not the command-line tool).\n\n// We put this in a JS file so that it can contain comments. It is processed\n// into a package.json file by generate-dev-bundle.sh.\n\nvar packageJson = {\n  name: \"meteor-dev-bundle\",\n  // Version is not important but is needed to prevent warnings.\n  version: \"0.0.0\",\n  dependencies: {\n    \"meteor-promise\": \"0.7.2\",\n    fibers: \"1.0.13\",\n    promise: \"7.1.1\",\n    // Not yet upgrading Underscore from 1.5.2 to 1.7.0 (which should be done\n    // in the package too) because we should consider using lodash instead\n    // (and there are backwards-incompatible changes either way).\n    underscore: \"1.5.2\",\n    \"source-map-support\": \"https://github.com/meteor/node-source-map-support/tarball/1912478769d76e5df4c365e147f25896aee6375e\",\n    semver: \"4.1.0\"\n  },\n  // These are only used in dev mode (by shell.js) so end-users can avoid\n  // needing to install them if they use `npm install --production`.\n  devDependencies: {\n    // 2.4.0 (more or less, the package.json change isn't committed) plus our PR\n    // https://github.com/williamwicks/node-eachline/pull/4\n    eachline: \"https://github.com/meteor/node-eachline/tarball/ff89722ff94e6b6a08652bf5f44c8fffea8a21da\",\n    chalk: \"0.5.1\"\n  }\n};\n\n\nprocess.stdout.write(JSON.stringify(packageJson, null, 2) + '\\n');\n"
  },
  {
    "path": "scripts/dev-bundle-tool-package.js",
    "content": "// This file contains a package.json for the dependencies of the command-line\n// tool.\n\n// We put this in a JS file so that it can contain comments. It is processed\n// into a package.json file by generate-dev-bundle.sh.\n\nvar packageJson = {\n  name: \"meteor-dev-bundle-tool\",\n  // Version is not important but is needed to prevent warnings.\n  version: \"0.0.0\",\n  dependencies: {\n    // Explicit dependency because we are replacing it with a bundled version\n    // and we want to make sure there are no dependencies on a higher version\n    npm: \"3.9.6\",\n    \"node-gyp\": \"3.3.1\",\n    \"node-pre-gyp\": \"0.6.26\",\n    \"meteor-babel\": \"0.11.6\",\n    \"meteor-promise\": \"0.7.2\",\n    fibers: \"1.0.13\",\n    promise: \"7.1.1\",\n    // So that Babel 6 can emit require(\"babel-runtime/helpers/...\") calls.\n    \"babel-runtime\": \"6.9.2\",\n    // For various ES2015 polyfills, such as Map and Set.\n    \"meteor-ecmascript-runtime\": \"0.2.6\",\n    // Not yet upgrading Underscore from 1.5.2 to 1.7.0 (which should be done\n    // in the package too) because we should consider using lodash instead\n    // (and there are backwards-incompatible changes either way).\n    underscore: \"1.5.2\",\n    \"source-map-support\": \"https://github.com/meteor/node-source-map-support/tarball/1912478769d76e5df4c365e147f25896aee6375e\",\n    semver: \"4.1.0\",\n    request: \"2.47.0\",\n    fstream: \"https://github.com/meteor/fstream/tarball/d11b9ec4a13918447c8af7559c243c190744dd1c\",\n    tar: \"1.0.2\",\n    kexec: \"2.0.2\",\n    \"source-map\": \"0.5.3\",\n    \"browserstack-webdriver\": \"2.41.1\",\n    \"node-inspector\": \"0.7.4\",\n    chalk: \"0.5.1\",\n    sqlite3: \"3.1.3\",\n    netroute: \"1.0.2\",\n    \"http-proxy\": \"1.11.1\",\n    \"wordwrap\": \"0.0.2\",\n    \"moment\": \"2.8.4\",\n    \"rimraf\": \"2.4.3\",\n    // XXX: When we update this, see if it fixes this Github issue:\n    // https://github.com/jgm/CommonMark/issues/276 . If it does, remove the\n    // workaround from the tool.\n    \"commonmark\": \"0.15.0\",\n    escope: \"3.2.0\",\n    // 2.4.0 (more or less, the package.json change isn't committed) plus our PR\n    // https://github.com/williamwicks/node-eachline/pull/4\n    eachline: \"https://github.com/meteor/node-eachline/tarball/ff89722ff94e6b6a08652bf5f44c8fffea8a21da\",\n    pathwatcher: \"6.7.0\",\n    runas: \"3.1.1\",\n    'lru-cache': '2.6.4',\n    'cordova-lib': \"6.0.0\",\n    longjohn: '0.2.11'\n  }\n};\n\nif (process.platform === 'win32') {\n  // Remove dependencies that do not work on Windows\n  delete packageJson.dependencies.netroute;\n  delete packageJson.dependencies.kexec;\n}\n\nprocess.stdout.write(JSON.stringify(packageJson, null, 2) + '\\n');\n"
  },
  {
    "path": "scripts/doctool.js",
    "content": "#!/usr/bin/env node\n\n/// # doctool.js\n///\n/// Usage: `doctool.js ...jsfiles...`\n///\n/// Reads each `.js` file and writes a `.md` file in the same directory.\n/// The output file consists of the concatenation of the \"doc comments\"\n/// in the input file, which are assumed to contain Markdown content,\n/// including any section headings necessary to organize the file.\n///\n/// A \"doc comment\" must begin at the start of a line or after\n/// whitespace.  There are two kinds of doc comments: `/** ... */`\n/// (block) comments and `/// ...` (triple-slash) comments.\n///\n/// If a file begins with the magic string \"///!README\", the output\n/// filename is changed to `README.md`.\n///\n/// Examples:\n///\n/// ```\n/// /**\n///  * This is a block comment.  The parser strips the sequence,\n///  * [optional whitespace, `*`, optional single space] from\n///  * every line that has it.\n///  *\n/// For lines that don't, no big deal.\n///\n///     Leading whitespace will be preserved here.\n///\n///  * We can create a bullet list in here:\n///  *\n///  * * This is a bullet\n///  */\n/// ```\n///\n/// ```\n/// /** Single-line block comments are also ok. */\n/// ```\n///\n/// ```\n/// /**\n/// A block comment whose first line doesn't have a `*` receives\n/// no stripping of `*` characters on any line.\n///\n/// * This is a bullet\n///\n/// */\n/// ```\n///\n/// ```\n/// /// A triple-slash comment starts with `///` followed by an\n/// /// optional space (i.e. one space is removed if present).\n/// /// Multiple consecutive lines that start with `///` are\n/// /// treated together as a single doc comment.\n/// /** Separate doc comments get separate paragraphs. */\n/// ```\n\nvar fs = require('fs');\nvar path = require('path');\n\nprocess.argv.slice(2).forEach(function (fileName) {\n  var text = fs.readFileSync(fileName, \"utf8\");\n\n  var outFileName = fileName.replace(/\\.js$/, '') + '.md';\n  if (text.slice(0, 10) === '///!README') {\n    outFileName = path.join(path.dirname(fileName), 'README.md');\n    text = text.slice(10);\n  }\n\n  var docComments = [];\n  for (;;) {\n    // This regex breaks down as follows:\n    //\n    // 1. Start of line\n    // 2. Optional whitespace (not newline!)\n    // 3. `///` (capturing group 1) or `/**` (group 2)\n    // 4. Looking ahead, NOT `/` or `*`\n    var nextOpener = /^[ \\t]*(?:(\\/\\/\\/)|(\\/\\*\\*))(?![\\/\\*])/m.exec(text);\n    if (! nextOpener)\n      break;\n    text = text.slice(nextOpener.index + nextOpener[0].length);\n    if (nextOpener[1]) {\n      // triple-slash\n      text = text.replace(/^[ \\t]/, ''); // optional space\n      var comment = text.match(/^[^\\n]*/)[0];\n      text = text.slice(comment.length);\n      var match;\n      while ((match = /^\\n[ \\t]*\\/\\/\\/[ \\t]?/.exec(text))) {\n        // multiple lines in a row become one comment\n        text = text.slice(match[0].length);\n        var restOfLine = text.match(/^[^\\n]*/)[0];\n        text = text.slice(restOfLine.length);\n        comment += '\\n' + restOfLine;\n      }\n      if (comment.trim())\n        docComments.push(['///', comment]);\n    } else if (nextOpener[2]) {\n      // block comment\n      var rawComment = text.match(/^[\\s\\S]*?\\*\\//);\n      if ((! rawComment) || (! rawComment[0]))\n        continue;\n      rawComment = rawComment[0];\n      text = text.slice(rawComment.length);\n      rawComment = rawComment.slice(0, -2); // remove final `*/`\n      if (rawComment.slice(-1) === ' ')\n        // make that ' */' for the benefit of single-line blocks\n        rawComment = rawComment.slice(0, -1);\n\n      var lines = rawComment.split('\\n');\n\n      var stripStars = false;\n      if (lines[0].trim().length === 0) {\n        // The comment has a newline after the `/**` (with possible whitespace\n        // between).  This is like most comments, though occasionally people\n        // may write `/** foo */` on one line.  Skip the blank line.\n        lines.splice(0, 1);\n        if (! lines.length)\n          continue;\n        // Now we determine whether this is block comment with a column of\n        // asterisks running down the left side, so we can strip them.\n        stripStars = /^[ \\t]*\\*/.test(lines[1]);\n      } else {\n        // Trim beginning of line after `/**`\n        lines[0] = lines[0].replace(/^\\s*/, '');\n      }\n\n      lines = lines.map(function (s) {\n        // Strip either up to an asterisk and then an optional space,\n        // or just an optional space, depending on `stripStars`.\n        if (stripStars)\n          return s.replace(/^[ \\t]*\\* ?/, '');\n        else\n          return s;\n      });\n\n      var result = lines.join('\\n');\n\n      if (result.trim())\n        docComments.push(['/**', result]);\n    }\n  }\n\n  if (docComments.length) {\n    var output = docComments.map(function (x) { return x[1]; }).join('\\n\\n');\n    var fileShortName = path.basename(fileName);\n    output = '*This file is automatically generated from [`' +\n      fileShortName + '`](' + fileShortName + ').*\\n\\n' + output;\n    fs.writeFileSync(outFileName, output, 'utf8');\n    console.log(\"Wrote \" + docComments.length + \" comments to \" + outFileName);\n  }\n\n\n});\n"
  },
  {
    "path": "scripts/doctool.md",
    "content": "*This file is automatically generated from [`doctool.js`](doctool.js).*\n\n# doctool.js\n\nUsage: `doctool.js ...jsfiles...`\n\nReads each `.js` file and writes a `.md` file in the same directory.\nThe output file consists of the concatenation of the \"doc comments\"\nin the input file, which are assumed to contain Markdown content,\nincluding any section headings necessary to organize the file.\n\nA \"doc comment\" must begin at the start of a line or after\nwhitespace.  There are two kinds of doc comments: `/** ... */`\n(block) comments and `/// ...` (triple-slash) comments.\n\nIf a file begins with the magic string \"///!README\", the output\nfilename is changed to `README.md`.\n\nExamples:\n\n```\n/**\n * This is a block comment.  The parser strips the sequence,\n * [optional whitespace, `*`, optional single space] from\n * every line that has it.\n *\nFor lines that don't, no big deal.\n\n    Leading whitspace will be preserved here.\n\n * We can create a bullet list in here:\n *\n * * This is a bullet\n */\n```\n\n```\n/** Single-line block comments are also ok. */\n```\n\n```\n/**\nA block comment whose first line doesn't have a `*` receives\nno stripping of `*` characters on any line.\n\n* This is a bullet\n\n*/\n```\n\n```\n/// A triple-slash comment starts with `///` followed by an\n/// optional space (i.e. one space is removed if present).\n/// Multiple consecutive lines that start with `///` are\n/// treated together as a single doc comment.\n/** Separate doc comments get separate paragraphs. */\n```"
  },
  {
    "path": "scripts/doctool.md.md",
    "content": "*This file is automatically generated from [`doctool.md`](doctool.md).*\n\nThis is a block comment.  The parser strips the sequence,\n[optional whitespace, `*`, optional single space] from\nevery line that has it.\n\nFor lines that don't, no big deal.\n\n    Leading whitspace will be preserved here.\n\nWe can create a bullet list in here:\n\n* This is a bullet\n\n\nSingle-line block comments are also ok.\n\nA block comment whose first line doesn't have a `*` receives\nno stripping of `*` characters on any line.\n\n* This is a bullet\n\n\n\nA triple-slash comment starts with `///` followed by an\noptional space (i.e. one space is removed if present).\nMultiple consecutive lines that start with `///` are\ntreated together as a single doc comment.\n\nSeparate doc comments get separate paragraphs."
  },
  {
    "path": "scripts/generate-dev-bundle.ps1",
    "content": "# determine the platform\n# use 32bit by default\n$PLATFORM = \"windows_x86\"\n$MONGO_VERSION = \"2.6.7\"\n$NODE_VERSION = \"0.10.45\"\n$NPM_VERSION = \"3.9.6\"\n$PYTHON_VERSION = \"2.7.10\" # For node-gyp\n\n# take it form the environment if exists\nif (Test-Path env:PLATFORM) {\n  $PLATFORM = (Get-Item env:PLATFORM).Value\n}\n\n$script_path = Split-Path -parent $MyInvocation.MyCommand.Definition\n$CHECKOUT_DIR = Split-Path -parent $script_path\n\n# extract the bundle version from the meteor bash script\n$BUNDLE_VERSION = Select-String -Path ($CHECKOUT_DIR + \"\\meteor\") -Pattern 'BUNDLE_VERSION=(\\S+)'  | % { $_.Matches[0].Groups[1].Value } | Select-Object -First 1\n$BUNDLE_VERSION = $BUNDLE_VERSION.Trim()\n\n# generate-dev-bundle-xxxxxxxx shortly\n# convert relative path to absolute path because not all commands know how to deal with this themselves\n$DIR = $executionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"${script_path}\\..\\gdbXXX\")\necho $DIR\n\ncmd /c rmdir \"$DIR\" /s /q\nmkdir \"$DIR\"\ncd \"$DIR\"\n\nmkdir lib\nmkdir lib\\node_modules\nmkdir bin\ncd bin\n\n$webclient = New-Object System.Net.WebClient\n$shell = New-Object -com shell.application\n\n# download node\n# same node on 32bit vs 64bit?\n$node_link = \"http://nodejs.org/dist/v${NODE_VERSION}/node.exe\"\n$webclient.DownloadFile($node_link, \"$DIR\\bin\\node.exe\")\n\n# On Windows we provide a reliable version of python.exe for use by\n# node-gyp (the tool that rebuilds binary node modules). #WinPy\n$py_msi_link = \"http://www.python.org/ftp/python/${PYTHON_VERSION}/python-${PYTHON_VERSION}.msi\"\n$py_msi = \"${DIR}\\python.msi\"\n$webclient.DownloadFile($py_msi_link, $py_msi)\n$py_dir = \"${DIR}\\python\"\nmsiexec /i \"$py_msi\" TARGETDIR=\"$py_dir\" /quiet /qn /norestart\n$env:PATH = \"${py_dir};${env:PATH}\"\n\n# download initial version of npm\n$npm_zip = \"$DIR\\bin\\npm.zip\"\n\n# These dist/npm archives were only published for 1.x versions of npm, and\n# this is the most recent one.\n$npm_link = \"https://nodejs.org/dist/npm/npm-1.4.12.zip\"\n$webclient.DownloadFile($npm_link, $npm_zip)\n\n$zip = $shell.NameSpace($npm_zip)\nforeach($item in $zip.items()) {\n  $shell.Namespace(\"$DIR\\bin\").copyhere($item, 0x14) # 0x10 - overwrite, 0x4 - no dialog\n}\n\nrm -Recurse -Force $npm_zip\n\n# add bin to the front of the path so we can use our own node for building\n$env:PATH = \"${DIR}\\bin;${env:PATH}\"\n\n# Install the version of npm that we're actually going to expose from the\n# dev bundle. Note that we use npm@1.4.12 to install npm@${NPM_VERSION}.\ncd \"${DIR}\\lib\"\nnpm install npm@${NPM_VERSION}\nrm -Recurse -Force \"${DIR}\\bin\\node_modules\"\ncopy \"${CHECKOUT_DIR}\\scripts\\npm.cmd\" \"${DIR}\\bin\\npm.cmd\"\nnpm version\n\n# npm depends on a hardcoded file path to node-gyp, so we need this to be\n# un-flattened\ncd node_modules\\npm\nnpm install node-gyp\n\n# install dev-bundle-package.json\n# use short folder names\n# b for build\nmkdir \"$DIR\\b\\t\"\ncd \"$DIR\\b\\t\"\n\nnpm config set loglevel error\nnode \"${CHECKOUT_DIR}\\scripts\\dev-bundle-server-package.js\" | Out-File -FilePath package.json -Encoding ascii\nnpm install\nnpm shrinkwrap\n\nmkdir -Force \"${DIR}\\server-lib\\node_modules\"\ncmd /c robocopy \"${DIR}\\b\\t\\node_modules\" \"${DIR}\\server-lib\\node_modules\" /e /nfl /ndl\n\nmkdir -Force \"${DIR}\\etc\"\nMove-Item package.json \"${DIR}\\etc\\\"\nMove-Item npm-shrinkwrap.json \"${DIR}\\etc\\\"\n\nmkdir -Force \"${DIR}\\b\\p\"\ncd \"${DIR}\\b\\p\"\nnode \"${CHECKOUT_DIR}\\scripts\\dev-bundle-tool-package.js\" | Out-File -FilePath package.json -Encoding ascii\nnpm install\ncmd /c robocopy \"${DIR}\\b\\p\\node_modules\" \"${DIR}\\lib\\node_modules\" /e /nfl /ndl\ncd \"$DIR\"\ncmd /c rmdir \"${DIR}\\b\" /s /q\n\ncd \"$DIR\"\nmkdir \"$DIR\\mongodb\"\nmkdir \"$DIR\\mongodb\\bin\"\n\n# download Mongo\n$mongo_name = \"mongodb-win32-i386-${MONGO_VERSION}\"\nIf ($PLATFORM -eq 'windows_x86_64') {\n  # 64-bit would be mongodb-win32-x86_64-2008plus-${MONGO_VERSION}.zip\n  $mongo_name = \"mongodb-win32-x86_64-2008plus-${MONGO_VERSION}\"\n}\n$mongo_link = \"https://fastdl.mongodb.org/win32/${mongo_name}.zip\"\n$mongo_zip = \"$DIR\\mongodb\\mongo.zip\"\n\n$webclient.DownloadFile($mongo_link, $mongo_zip)\n\n$zip = $shell.NameSpace($mongo_zip)\nforeach($item in $zip.items()) {\n  $shell.Namespace(\"$DIR\\mongodb\").copyhere($item, 0x14) # 0x10 - overwrite, 0x4 - no dialog\n}\n\ncp \"$DIR\\mongodb\\$mongo_name\\bin\\mongod.exe\" $DIR\\mongodb\\bin\ncp \"$DIR\\mongodb\\$mongo_name\\bin\\mongo.exe\" $DIR\\mongodb\\bin\n\nrm -Recurse -Force $mongo_zip\nrm -Recurse -Force \"$DIR\\mongodb\\$mongo_name\"\n\nrm -Recurse -Force \"$py_msi\"\npython --version\n\ncd $DIR\n\n# mark the version\necho \"${BUNDLE_VERSION}\" | Out-File .bundle_version.txt -Encoding ascii\n\ncd \"$DIR\\..\"\n\n# rename the folder with the devbundle\ncmd /c rename \"$DIR\" \"dev_bundle_${PLATFORM}_${BUNDLE_VERSION}\"\n\ncmd /c 7z.exe a -ttar dev_bundle.tar \"dev_bundle_${PLATFORM}_${BUNDLE_VERSION}\"\ncmd /c 7z.exe a -tgzip \"${CHECKOUT_DIR}\\dev_bundle_${PLATFORM}_${BUNDLE_VERSION}.tar.gz\" dev_bundle.tar\ndel dev_bundle.tar\ncmd /c rmdir \"dev_bundle_${PLATFORM}_${BUNDLE_VERSION}\" /s /q\n\necho \"Done building Dev Bundle!\"\n"
  },
  {
    "path": "scripts/generate-dev-bundle.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\nset -u\n\n# Read the bundle version from the meteor shell script.\nBUNDLE_VERSION=$(perl -ne 'print $1 if /BUNDLE_VERSION=(\\S+)/' meteor)\nif [ -z \"$BUNDLE_VERSION\" ]; then\n    echo \"BUNDLE_VERSION not found\"\n    exit 1\nfi\n\nsource \"$(dirname $0)/build-dev-bundle-common.sh\"\necho CHECKOUT DIR IS \"$CHECKOUT_DIR\"\necho BUILDING DEV BUNDLE \"$BUNDLE_VERSION\" IN \"$DIR\"\n\ncd \"$DIR\"\n\n# Check if have to build for an universal environment on yet not\n# officially supported architectures\nif [ -z \"$METEOR_UNIVERSAL_FLAG\" ] ; then\n\n    S3_HOST=\"s3.amazonaws.com/com.meteor.jenkins\"\n\n    # Update these values after building the dev-bundle-node Jenkins project.\n    # Also make sure to update NODE_VERSION in generate-dev-bundle.ps1.\n    NODE_URL=\"https://nodejs.org/dist/v${NODE_VERSION}/${NODE_TGZ}\"\n    echo \"Downloading Node from ${NODE_URL}\"\n    curl \"${NODE_URL}\" | tar zx --strip-components 1\n\n    # Update these values after building the dev-bundle-mongo Jenkins project.\n    # Also make sure to update MONGO_VERSION in generate-dev-bundle.ps1.\n    MONGO_VERSION=2.6.7\n    MONGO_BUILD_NUMBER=6\n    MONGO_TGZ=\"mongo_${PLATFORM}_v${MONGO_VERSION}.tar.gz\"\n    if [ -f \"${CHECKOUT_DIR}/${MONGO_TGZ}\" ] ; then\n        tar zxf \"${CHECKOUT_DIR}/${MONGO_TGZ}\"\n    else\n        MONGO_URL=\"https://${S3_HOST}/dev-bundle-mongo-${MONGO_BUILD_NUMBER}/${MONGO_TGZ}\"\n        echo \"Downloading Mongo from ${MONGO_URL}\"\n        curl \"${MONGO_URL}\" | tar zx\n    fi\n\nelse\n\n    # For an universal build we can use a self compiled tarballs for\n    # node and mongo or system installed binaries\n\n    # Take the version from meteor above\n    NODE_VERSION=0.10.45\n    NODE_TGZ=\"node_${PLATFORM}_v${NODE_VERSION}.tar.gz\"\n    if [ -f \"${CHECKOUT_DIR}/${NODE_TGZ}\" ] ; then\n        tar zxf \"${CHECKOUT_DIR}/${NODE_TGZ}\"\n    else\n        # test for system installed binaries\n        if [ -z \"$(which node 2>/dev/null)\" -o -z \"$(which npm 2>/dev/null)\" ] ; then\n            echo \"To generate dev bundle with system binaries please make sure\"\n            echo \"that node (compatible to $NODE_VERSION) and npm is installed.\"\n            echo -e \"\\tnode version:\" $(which node 2>/dev/null)\n            echo -e \"\\tnpm version:\" $(which npm 2>/dev/null)\n            exit 1\n        fi\n        # link to pre-installed binaries on universal build\n        # also need etc for \"global\" npmrc\n        mkdir -p \"$DIR/bin\"\n        mkdir -p \"$DIR/etc\"\n        ln -s \"$(which node 2>/dev/null)\" \"$DIR/bin/node\"\n        ln -s \"$(which npm 2>/dev/null)\"  \"$DIR/bin/npm\"\n    fi\n\n    # Take the version from meteor above\n    MONGO_VERSION=2.6.7\n    MONGO_BUILD_NUMBER=6\n    MONGO_TGZ=\"mongo_${PLATFORM}_v${MONGO_VERSION}.tar.gz\"\n    if [ -f \"${CHECKOUT_DIR}/${MONGO_TGZ}\" ] ; then\n        tar zxf \"${CHECKOUT_DIR}/${MONGO_TGZ}\"\n    else\n        # test for system installed binaries\n        if [ -z \"$(which mongo 2>/dev/null)\" -o -z \"$(which mongod 2>/dev/null)\" ] ; then\n            echo \"To generate dev bundle with system binaries please make sure\"\n            echo \"that mongo and mongod is installed.\"\n            echo -e \"\\tmongo version:\" $(which mongo 2>/dev/null)\n            echo -e \"\\tmongod version:\" $(which mongod 2>/dev/null)\n            exit 1\n        fi\n        # link to pre-installed binaries on universal build\n        mkdir -p \"$DIR/mongodb/bin\"\n        ln -s \"$(which mongo 2>/dev/null)\"  \"$DIR/mongodb/bin/mongo\"\n        ln -s \"$(which mongod 2>/dev/null)\" \"$DIR/mongodb/bin/mongod\"\n    fi\n\nfi\n\n# export path so we use the downloaded node and npm\nexport PATH=\"$DIR/bin:$PATH\"\n\ncd \"$DIR/lib\"\n# Overwrite the bundled version with the latest version of npm.\nnpm install \"npm@$NPM_VERSION\"\n\nwhich node\nwhich npm\nnpm version\n\n# When adding new node modules (or any software) to the dev bundle,\n# remember to update LICENSE.txt! Also note that we include all the\n# packages that these depend on, so watch out for new dependencies when\n# you update version numbers.\n\n# First, we install the modules that are dependencies of tools/server/boot.js:\n# the modules that users of 'meteor bundle' will also have to install. We save a\n# shrinkwrap file with it, too.  We do this in a separate place from\n# $DIR/server-lib/node_modules originally, because otherwise 'npm shrinkwrap'\n# will get confused by the pre-existing modules.\nmkdir \"${DIR}/build/npm-server-install\"\ncd \"${DIR}/build/npm-server-install\"\nnode \"${CHECKOUT_DIR}/scripts/dev-bundle-server-package.js\" >package.json\nnpm install\nnpm shrinkwrap\n\nmkdir -p \"${DIR}/server-lib/node_modules\"\n# This ignores the stuff in node_modules/.bin, but that's OK.\ncp -R node_modules/* \"${DIR}/server-lib/node_modules/\"\n\nmkdir -p \"${DIR}/etc\"\nmv package.json npm-shrinkwrap.json \"${DIR}/etc/\"\n\n# Fibers ships with compiled versions of its C code for a dozen platforms. This\n# bloats our dev bundle. Remove all the ones other than our\n# architecture. (Expression based on build.js in fibers source.)\nshrink_fibers () {\n    FIBERS_ARCH=$(node -p -e 'process.platform + \"-\" + process.arch + \"-v8-\" + /[0-9]+\\.[0-9]+/.exec(process.versions.v8)[0]')\n    mv $FIBERS_ARCH ..\n    rm -rf *\n    mv ../$FIBERS_ARCH .\n}\n\ncd \"$DIR/server-lib/node_modules/fibers/bin\"\nshrink_fibers\n\n# Now, install the npm modules which are the dependencies of the command-line\n# tool.\nmkdir \"${DIR}/build/npm-tool-install\"\ncd \"${DIR}/build/npm-tool-install\"\nnode \"${CHECKOUT_DIR}/scripts/dev-bundle-tool-package.js\" >package.json\nnpm install\nmkdir -p \"${DIR}/lib/node_modules/\"\ncp -R node_modules/* \"${DIR}/lib/node_modules/\"\n# Also include node_modules/.bin, so that `meteor npm` can make use of\n# commands like node-gyp and node-pre-gyp.\ncp -R node_modules/.bin \"${DIR}/lib/node_modules/\"\n\ncd \"${DIR}/lib\"\n\n# Clean up some bulky stuff.\ncd node_modules\n\n# Used to delete bulky subtrees. It's not an error anymore but WARNING if they\n# don't exist, because that might mean it moved somewhere else and we should\n# update the delete line.\ndelete () {\n    if [ ! -e \"$1\" ]; then\n        echo \"WARNING! Nothing to clean anymore. Missing or moved?: $1\"\n    else\n        rm -rf \"$1\"\n    fi\n}\n\ndelete browserstack-webdriver/docs\ndelete browserstack-webdriver/lib/test\n\ndelete sqlite3/deps\ndelete wordwrap/test\ndelete moment/min\n\n# Remove esprima tests to reduce the size of the dev bundle\nfind . -path '*/esprima-fb/test' | xargs rm -rf\n\ncd \"$DIR/lib/node_modules/fibers/bin\"\nshrink_fibers\n\n# Check if have to build on universal architecture\nif [ -z \"$METEOR_UNIVERSAL_FLAG\" ] ; then\n\n    # Download BrowserStackLocal binary.\n    BROWSER_STACK_LOCAL_URL=\"https://browserstack-binaries.s3.amazonaws.com/BrowserStackLocal-07-03-14-$OS-$ARCH.gz\"\n\n    cd \"$DIR/build\"\n    curl -O $BROWSER_STACK_LOCAL_URL\n    gunzip BrowserStackLocal*\n    mv BrowserStackLocal* BrowserStackLocal\n    mv BrowserStackLocal \"$DIR/bin/\"\n\nfi\n\n# Sanity check to see if we're not breaking anything by replacing npm\nINSTALLED_NPM_VERSION=$(cat \"$DIR/lib/node_modules/npm/package.json\" |\nxargs -0 node -e \"console.log(JSON.parse(process.argv[1]).version)\")\nif [ \"$INSTALLED_NPM_VERSION\" != \"$NPM_VERSION\" ]; then\n  echo \"Unexpected NPM version in lib/node_modules: $INSTALLED_NPM_VERSION\"\n  echo \"Update this check if you know what you're doing.\"\n  exit 1\nfi\n\necho BUNDLING\n\ncd \"$DIR\"\necho \"${BUNDLE_VERSION}\" > .bundle_version.txt\nrm -rf build CHANGELOG.md ChangeLog LICENSE README.md\n\ntar czf \"${CHECKOUT_DIR}/dev_bundle_${PLATFORM}_${BUNDLE_VERSION}.tar.gz\" .\n\necho DONE\n"
  },
  {
    "path": "scripts/node.sh",
    "content": "#!/usr/bin/env bash\n\nORIGDIR=$(pwd)\ncd $(dirname $0)\ncd ..\nTOPDIR=$(pwd)\n\n# download dev bundle if we don't have it already\nif [ ! -d dev_bundle ] ; then\n    ./meteor --get-ready\nfi\n\ncd \"$ORIGDIR\"\nexport NODE_PATH=\"$TOPDIR/dev_bundle/lib/node_modules\"\n\nif [ \"$EMACS\" == t ]; then\n    # Emacs shell doesn't need readline and interprets the ANSI characters as\n    # garbage.\n    export NODE_NO_READLINE=1\nfi\n\n\"$TOPDIR/dev_bundle/bin/node\" \"$@\"\nEXITSTATUS=$?\n\n# Node sets stdin to non-blocking, which causes Emacs shell to die after it\n# exits. Work around this by setting stdin to blocking again.\nif [ \"$EMACS\" == t ]; then\n    perl -MFcntl=F_GETFL,F_SETFL,O_NONBLOCK -e \\\n        'fcntl(STDIN, F_SETFL, ~O_NONBLOCK & fcntl(STDIN, F_GETFL, 0))'\nfi\n\nexit $EXITSTATUS\n"
  },
  {
    "path": "scripts/npm.cmd",
    "content": "@\"%~dp0\\node.exe\" \"%~dp0\\..\\lib\\node_modules\\npm\\bin\\npm-cli.js\" %*\n"
  },
  {
    "path": "scripts/windows/.gitignore",
    "content": "*.tar.gz\n*.exe\n*.pdb\n*_.cs"
  },
  {
    "path": "scripts/windows/README",
    "content": "To build the Windows installer, run .\\build-installer.ps1 from within\r\nPowerShell.\r\n\r\nPrerequisites:\r\n==============\r\n\r\nInstall Visual C++ 2010 Express, which can be found here:\r\n* http://www.visualstudio.com/downloads/download-visual-studio-vs\r\n\r\nThen, install Visual Studio 2010 Service Pack 1 here:\r\n* http://www.microsoft.com/en-us/download/details.aspx?id=23691\r\n\r\nNow, install WiX Toolset 3.8 from here:\r\n* https://wix.codeplex.com/releases/view/115492\r\n\r\nNow restart your command line process before running the build script\r\nagain.\r\n"
  },
  {
    "path": "scripts/windows/build-installer.ps1",
    "content": "$ErrorActionPreference = \"Stop\"\n$script_path = (split-path -parent $MyInvocation.MyCommand.Definition) + \"\\\"\n\necho \"Compiling InstallMeteor\"\n\n$web_client = new-object System.Net.WebClient\n\n# download 7za.exe, a build dependency that we don't want to compile each time\n$7za_path = $script_path + \"installer\\WiXInstaller\\Resources\\7za.exe\"\nif (!(Test-Path $7za_path)) {\n\techo \"Downloading binary dependencies: 7za\"\n\t$7za_url = \"https://s3.amazonaws.com/meteor-windows/build-deps/7za.exe\"\n\t$web_client.DownloadFile($7za_url, $7za_path)\n}\n\nPush-Location installer\nInvoke-Expression (\"cmd /c build.bat\")\nPop-Location\n\nmove-item ($script_path + \"installer\\Release\\InstallMeteor.exe\") ($script_path + \"InstallMeteor.exe\") -Force\n\necho \"Done\"\n\n"
  },
  {
    "path": "scripts/windows/check-dev-bundle.ps1",
    "content": "$windows_scripts = split-path -parent $MyInvocation.MyCommand.Definition\n$scripts_path = split-path -parent $windows_scripts\n$CHECKOUT_DIR = split-path -parent $scripts_path\n\n# extract the bundle version from the meteor bash script\n$BUNDLE_VERSION = select-string -Path ($CHECKOUT_DIR + \"\\meteor\") -Pattern 'BUNDLE_VERSION=(\\S+)'  | % { $_.Matches[0].Groups[1].Value } | select-object -First 1\n$BUNDLE_VERSION = $BUNDLE_VERSION.Trim()\n\n# extract the bundle version we have on FS\n$CURRENT_VERSION = select-string -Path ($CHECKOUT_DIR + \"\\dev_bundle\\.bundle_version.txt\") -Pattern '(.*)' | % { $_.Matches[0].Captures[0].Value } | select-object -First 1\n\nIf ($CURRENT_VERSION -eq $BUNDLE_VERSION) {\n  exit 0\n}\n\n# fail\nexit 1\n\n"
  },
  {
    "path": "scripts/windows/download-dev-bundle.ps1",
    "content": "# XXX right now we only build 32-bit dev_bundles\n$PLATFORM = \"windows_x86\"\n\n$windows_scripts = split-path -parent $MyInvocation.MyCommand.Definition\n$scripts_path = split-path -parent $windows_scripts\n$CHECKOUT_DIR = split-path -parent $scripts_path\n\n# extract the bundle version from the meteor bash script\n$BUNDLE_VERSION = select-string -Path ($CHECKOUT_DIR + \"\\meteor\") -Pattern 'BUNDLE_VERSION=(\\S+)'  | % { $_.Matches[0].Groups[1].Value } | select-object -First 1\n$BUNDLE_VERSION = $BUNDLE_VERSION.Trim()\n\necho \"Will get you a dev_bundle for $PLATFORM version $BUNDLE_VERSION\"\n\n$TARBALL=\"dev_bundle_${PLATFORM}_${BUNDLE_VERSION}.tar.gz\"\n\necho \"Going to download the dependency kit from the Internet\"\n$ErrorActionPreference = \"Stop\"\n\n# duplicated in top-level meteor script:\n$DEV_BUNDLE_URL_ROOT=\"https://d3sqy0vbqsdhku.cloudfront.net/\"\n# If you set $USE_TEST_DEV_BUNDLE_SERVER then we will download\n# dev bundles copied by copy-dev-bundle-from-jenkins.sh without --prod.\n# It still only does this if the version number has changed\n# (setting it won't cause it to automatically delete a prod dev bundle).\nif (\"$env:USE_TEST_DEV_BUNDLE_SERVER\" -ne \"\") {\n    $DEV_BUNDLE_URL_ROOT=\"https://s3.amazonaws.com/com.meteor.static/test/\"\n}\n\n$devbundle_link = $DEV_BUNDLE_URL_ROOT + $TARBALL\n$devbundle_zip = $CHECKOUT_DIR + \"\\\" + $TARBALL\n\n$webclient = New-Object System.Net.WebClient\n$webclient.DownloadFile($devbundle_link, $devbundle_zip)\n\necho \"... downloaded\"\n\ncmd /C \"7z.exe x $devbundle_zip -so | 7z.exe x -aoa -si -ttar -o$CHECKOUT_DIR\\dev_bundle_XXX\" | out-null\n\n$downloaded_tmp = $CHECKOUT_DIR + \"\\dev_bundle_XXX\"\n$downloaded_path = $downloaded_tmp + \"\\dev_bundle_\" + $PLATFORM + \"_\" + $BUNDLE_VERSION\n$target_path = $CHECKOUT_DIR + \"\\dev_bundle\"\nMove-Item  $downloaded_path $target_path\n\nRemove-Item -Recurse -Force $downloaded_tmp\nRemove-Item -Force $devbundle_zip\n\n"
  },
  {
    "path": "scripts/windows/installer/.gitignore",
    "content": "# Build Folders (you can keep bin if you'd like, to store dlls and pdbs)\n[Bb]in/\n[Oo]bj/\n\n# mstest test results\nTestResults\n\n## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.sln.docstates\n\n# Build results\n[Dd]ebug/\n[Rr]elease/\nx64/\n*_i.c\n*_p.c\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.dll\n*.exe\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.log\n*.vspscc\n*.vssscc\n.builds\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opensdf\n*.sdf\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*\n\n# NCrunch\n*.ncrunch*\n.*crunch*.local.xml\n\n# Installshield output folder\n[Ee]xpress\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish\n\n# Publish Web Output\n*.Publish.xml\n\n# NuGet Packages Directory\npackages\n\n# Windows Azure Build Output\ncsx\n*.build.csdef\n\n# Windows Store app package directory\nAppPackages/\n\n# Others\n[Bb]in\n[Oo]bj\nsql\nTestResults\n[Tt]est[Rr]esult*\n*.Cache\nClientBin\n[Ss]tyle[Cc]op.*\n~$*\n*.dbmdl\nGenerated_Code #added for RIA/Silverlight projects\n\n# Backup & report files from converting an old project file to a newer\n# Visual Studio version. Backup files are not needed, because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\n\n"
  },
  {
    "path": "scripts/windows/installer/MeteorSetup.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 11.00\n# Visual Studio 2010\nProject(\"{930C7802-8A8C-48F9-8165-68863BCCD9DD}\") = \"MSIPackage\", \"WiXInstaller\\MSIPackage.wixproj\", \"{E053726B-937B-40C7-8F3D-25A3226979D9}\"\nEndProject\nProject(\"{930C7802-8A8C-48F9-8165-68863BCCD9DD}\") = \"SetupPackage\", \"WiXInstaller\\SetupPackage.wixproj\", \"{7B569F5B-5D73-4E7B-BE41-041A2F22A521}\"\n\tProjectSection(ProjectDependencies) = postProject\n\t\t{E053726B-937B-40C7-8F3D-25A3226979D9} = {E053726B-937B-40C7-8F3D-25A3226979D9}\n\tEndProjectSection\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tRelease|x64 = Release|x64\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{E053726B-937B-40C7-8F3D-25A3226979D9}.Release|x64.ActiveCfg = Release|x64\n\t\t{E053726B-937B-40C7-8F3D-25A3226979D9}.Release|x64.Build.0 = Release|x64\n\t\t{E053726B-937B-40C7-8F3D-25A3226979D9}.Release|x86.ActiveCfg = Release|x86\n\t\t{E053726B-937B-40C7-8F3D-25A3226979D9}.Release|x86.Build.0 = Release|x86\n\t\t{7B569F5B-5D73-4E7B-BE41-041A2F22A521}.Release|x64.ActiveCfg = Release|x64\n\t\t{7B569F5B-5D73-4E7B-BE41-041A2F22A521}.Release|x64.Build.0 = Release|x64\n\t\t{7B569F5B-5D73-4E7B-BE41-041A2F22A521}.Release|x86.ActiveCfg = Release|x86\n\t\t{7B569F5B-5D73-4E7B-BE41-041A2F22A521}.Release|x86.Build.0 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studo 2015 cache/options directory\n.vs/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding addin-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings \n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Windows Azure Build Output\ncsx/\n*.build.csdef\n\n# Windows Store app package directory\nAppPackages/\n\n# Others\n*.[Cc]ache\nClientBin/\n[Ss]tyle[Cc]op.*\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\nbower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/BalExtensionExt.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 11.00\n# Visual Studio 2010\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"wixextba\", \"wixstdba\\wixstdba.vcxproj\", \"{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}\"\nEndProject\nProject(\"{930C7802-8A8C-48F9-8165-68863BCCD9DD}\") = \"BalExtension\", \"wixlib\\BalExtension.wixproj\", \"{3444D952-F21C-496F-AB6B-56435BFD0787}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"WixBalExtensionExt\", \"wixext\\WixBalExtensionExt.csproj\", \"{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}\"\n\tProjectSection(ProjectDependencies) = postProject\n\t\t{3444D952-F21C-496F-AB6B-56435BFD0787} = {3444D952-F21C-496F-AB6B-56435BFD0787}\n\tEndProjectSection\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tDebug|Mixed Platforms = Debug|Mixed Platforms\n\t\tDebug|Win32 = Debug|Win32\n\t\tDebug|x86 = Debug|x86\n\t\tRelease|Any CPU = Release|Any CPU\n\t\tRelease|Mixed Platforms = Release|Mixed Platforms\n\t\tRelease|Win32 = Release|Win32\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Any CPU.ActiveCfg = Debug|Win32\n\t\t{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Any CPU.Build.0 = Debug|Win32\n\t\t{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32\n\t\t{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Mixed Platforms.Build.0 = Debug|Win32\n\t\t{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|x86.ActiveCfg = Debug|Win32\n\t\t{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Any CPU.ActiveCfg = Debug|Win32\n\t\t{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Mixed Platforms.ActiveCfg = Release|Win32\n\t\t{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Mixed Platforms.Build.0 = Release|Win32\n\t\t{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Win32.ActiveCfg = Debug|Win32\n\t\t{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Win32.Build.0 = Debug|Win32\n\t\t{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|x86.ActiveCfg = Debug|Win32\n\t\t{3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Any CPU.ActiveCfg = Debug|x86\n\t\t{3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Mixed Platforms.ActiveCfg = Debug|x86\n\t\t{3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Mixed Platforms.Build.0 = Debug|x86\n\t\t{3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Win32.ActiveCfg = Debug|x86\n\t\t{3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|x86.ActiveCfg = Debug|x86\n\t\t{3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|x86.Build.0 = Debug|x86\n\t\t{3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Any CPU.ActiveCfg = Release|x86\n\t\t{3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Mixed Platforms.ActiveCfg = Release|x86\n\t\t{3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Mixed Platforms.Build.0 = Release|x86\n\t\t{3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Win32.ActiveCfg = Release|x86\n\t\t{3444D952-F21C-496F-AB6B-56435BFD0787}.Release|x86.ActiveCfg = Release|x86\n\t\t{3444D952-F21C-496F-AB6B-56435BFD0787}.Release|x86.Build.0 = Release|x86\n\t\t{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU\n\t\t{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU\n\t\t{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Win32.ActiveCfg = Debug|Any CPU\n\t\t{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU\n\t\t{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Mixed Platforms.Build.0 = Release|Any CPU\n\t\t{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Win32.ActiveCfg = Release|Any CPU\n\t\t{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|x86.ActiveCfg = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/LICENSE.TXT",
    "content": "Copyright (c) 2004, Outercurve Foundation.\nThis software is released under the Microsoft Reciprocal License (MS-RL) (the \"License\"); you may not use the software except in compliance with the License.\n\nThe text of the Microsoft Reciprocal License (MS-RL) can be found online at:\n http://opensource.org/licenses/ms-rl\n\n\nMicrosoft Reciprocal License (MS-RL)\n\nThis license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.\n\n1. Definitions\n The terms \"reproduce,\" \"reproduction,\" \"derivative works,\" and \"distribution\" have the same meaning here as under U.S. copyright law.\n A \"contribution\" is the original software, or any additions or changes to the software.\n A \"contributor\" is any person that distributes its contribution under this license.\n \"Licensed patents\" are a contributor's patent claims that read directly on its contribution.\n\n2. Grant of Rights\n (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.\n (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.\n\n3. Conditions and Limitations\n (A) Reciprocal Grants- For any file you distribute that contains code from the software (in source code or binary format), you must provide recipients the source code to that file along with a copy of this license, which license will govern that file. You may license other files that are entirely your own work and do not contain code from the software under any terms you choose.\n (B) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.\n (C) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.\n (D) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.\n (E) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.\n (F) The software is licensed \"as-is.\" You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/build.bat",
    "content": "@echo off\n\nrem Configuring environment\nset MSBUILD=\"%SystemRoot%\\Microsoft.NET\\Framework\\v4.0.30319\\msbuild.exe\"\n\nset outdir=%~dp0build\n\nrem Removing release folder\nCall :DeleteDir \"%outdir%\"\nCall :DeleteDir \"ipch\"\n\n%MSBUILD% inc\\Version.proj /nologo /verbosity:quiet\n%MSBUILD% BalExtensionExt.sln /nologo /verbosity:quiet /t:Rebuild /p:Configuration=Release /p:Platform=\"Mixed Platforms\" /p:RunCodeAnalysis=false /p:DefineConstants=\"TRACE\" /p:OutDir=\"%outdir%\\\\\" /l:FileLogger,Microsoft.Build.Engine;logfile=build.log\nif %errorlevel% neq 0 (\n\techo Build failed\n\trem pause\n\tgoto :EOF\n)\n\n\nset outdir=\n\ngoto :EOF\n\nREM *****************************************************************\nREM End of Main\nREM *****************************************************************\n\n\nREM *****************************************************************\nREM Delete/create directory\nREM *****************************************************************\n:DeleteDir\nrd %1% /q/s 2>nul 1>nul\ngoto :EOF\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/inc/.gitignore",
    "content": "wixver.cs\r\nwixver.h\r\n\r\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/inc/Version.proj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"WriteVersionFiles\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\" ToolsVersion=\"4.0\">\n  <PropertyGroup>\n    <MajorBuildNumber>3</MajorBuildNumber>\n    <MinorBuildNumber>7</MinorBuildNumber>\n\n    <CppVersionFile>.\\wixver.h</CppVersionFile>\n    <CSharpVersionFile>.\\wixver.cs</CSharpVersionFile>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <Base>$([System.DateTime]::new(2000, 1, 1))</Base>\n    <BuildNumber>$([System.Convert]::ToInt32($([System.DateTime]::Now.ToUniversalTime().Subtract($(Base)).TotalDays)))</BuildNumber>\n    <BuildRevision>$([System.Convert]::ToInt32($([MSBuild]::Divide($([System.Convert]::ToInt32($([System.DateTime]::Now.ToUniversalTime().TimeOfDay.TotalSeconds))), 2))))</BuildRevision>\n\n    <FullBuildVersionString>$(MajorBuildNumber).$(MinorBuildNumber).$(BuildNumber).$(BuildRevision)</FullBuildVersionString>\n  </PropertyGroup>\n\n  <!--\n  ================================================================================================\n  VersionPrint\n\n    Displays the versions of this build.\n  ================================================================================================\n  -->\n  <Target Name=\"VersionPrint\">\n    <Message Text=\"FullBuildVersionString = $(FullBuildVersionString)\" />\n  </Target>\n\n  <!--\n  ================================================================================================\n  WriteCppVersionFile\n\n    Creates the wixver.h version file for C++ code.\n  ================================================================================================\n  -->\n  <Target Name=\"WriteCppVersionFile\"\n          Returns=\"$(CppVersionFile)\">\n    <ItemGroup>\n      <CppVersionLines Include=\"\n// &lt;auto-generated/&gt;\n#ifndef _VERSION_FILE_H_\n#define _VERSION_FILE_H_\n\n#define szVerMajorMinor &quot;$(MajorBuildNumber).$(MinorBuildNumber)&quot;\n#define szVerMajorMinorBuildRev &quot;$(FullBuildVersionString)&quot;\n#define rmj\t$(MajorBuildNumber)\n#define rmm\t$(MinorBuildNumber)\n#define rbd\t$(BuildNumber)\n#define rev\t$(BuildRevision)\n#define szVerName\t&quot;BalExtensionExt Release&quot;\n\n#endif\n\"/>\n    </ItemGroup>\n\n    <WriteLinesToFile Overwrite=\"true\"\n                File=\"$(CppVersionFile)\"\n                Lines=\"@(CppVersionLines)\" />\n    <ItemGroup>\n      <FileWrites Include=\"$(CppVersionFile)\" />\n    </ItemGroup>\n  </Target>\n\n  <!--\n  ================================================================================================\n  WriteCSharpVersionFile\n\n    Creates the wixver.cs version file for C# code.\n  ================================================================================================\n  -->\n  <Target Name=\"WriteCSharpVersionFile\"\n          Returns=\"$(CSharpVersionFile)\">\n    <ItemGroup>\n      <CSharpLines Include=\"\n// &lt;auto-generated/&gt;\nusing System.Reflection%3B\n[assembly:AssemblyVersion(&quot;$(MajorBuildNumber).0.0.0&quot;)]\n[assembly:AssemblyFileVersion(&quot;$(FullBuildVersionString)&quot;)]\n\"/>\n    </ItemGroup>\n\n    <WriteLinesToFile Overwrite=\"true\"\n                File=\"$(CSharpVersionFile)\"\n                Lines=\"@(CSharpLines)\" />\n    <ItemGroup>\n      <FileWrites Include=\"$(CSharpVersionFile)\" />\n    </ItemGroup>\n  </Target>\n\n  <!--\n  ================================================================================================\n  WriteVersionFiles\n\n    Creates the wixver.* version files.\n  ================================================================================================\n  -->\n  <Target Name=\"WriteVersionFiles\" DependsOnTargets=\"VersionPrint;WriteCppVersionFile;WriteCSharpVersionFile\" />\n\n</Project>\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/inc/WixDistribution.cs",
    "content": "using System.Reflection;\nusing System.Resources;\n\n[assembly: AssemblyCompany(\"Outercurve Foundation\")]\n[assembly: AssemblyCopyright(\"Copyright  Outercurve Foundation. All rights reserved.\")]\n[assembly: AssemblyTrademark(\"\")]\n#if DEBUG\n    [assembly: AssemblyConfiguration(\"DEBUG\")]\n#else\n    [assembly: AssemblyConfiguration(\"\")]\n#endif\n[assembly: NeutralResourcesLanguage(\"en-US\")]\n[assembly: AssemblyProduct(\"Windows Installer XML\")]\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/inc/WixDistribution.h",
    "content": "/* **************************************************************************\n * WixDistribution.h file contains disribution specific items, such as\n * Product Name.\n * \n * **************************************************************************/\n\n#pragma once\n\n#ifndef __WIXDISTRIBUTION_FILE_H_\n#define __WIXDISTRIBUTION_FILE_H_\n\n#ifdef VER_PRODUCT_NAME\n    #undef VER_PRODUCT_NAME\n#endif\n#define VER_PRODUCT_NAME \"Windows Installer XML\"\n\n#endif // __WIXDISTRIBUTION_FILE_H_\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/inc/wix.rc",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"wix.rc\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n// Common resource file for any native wix resources.\n// </summary>\n// <remarks>\n// Usage:\n//   #define VER_APP (VER_DLL, VER_TYPELIB, none)\n//   #define VER_LANG_NEUTRAL (optional)\n//   #define VER_ORIGINAL_FILENAME \"FooBar.Exe\"\n//   #define VER_INTERNAL_NAME \"FooBar\"\n//   #define VER_PRODUCT_NAME\n//   #define VER_FILE_DESCRIPTION\n//   #include \"wix.rc\"\n//\n// Optional to add before the #include (must add as a group and VER_BLOCK must match to VER_LANG and VER_CP)\n// You should not have to do this except for some extreme cases.\n//   #define VER_LANG 0x0000\n//   #define VER_CP 0x04E4\n//   #define VER_BLOCK \"000004E4\"\n// </remarks>\n//-------------------------------------------------------------------------------------------------\n\n#include <winver.h>\n#include <windows.h>\n#include \"wixver.h\"\n#include \"WixDistribution.h\"\n\n#ifdef DEBUG\n    #define VER_DEBUG                VS_FF_DEBUG\n    #define VER_PRIVATE_BUILD        VS_FF_PRIVATEBUILD\n    #define VER_PRE_RELEASE          (VS_FF_PRERELEASE | VS_FF_SPECIALBUILD)\n#else\n    #define VER_DEBUG                0\n    #define VER_PRIVATE_BUILD        0\n    #define VER_PRE_RELEASE          0\n#endif\n\n#if defined(VER_APP)\n    #define VER_FILE_TYPE            VFT_APP\n#elif defined(VER_DLL)\n    #define VER_FILE_TYPE            VFT_DLL\n#elif defined(VER_TYPELIB)\n    #define VER_FILE_TYPE            VFT_UNKNOWN\n#else\n    #define VER_FILE_TYPE            VFT_UNKNOWN\n#endif\n\n#if defined(VER_LANG_NEUTRAL)\n    #ifndef VER_LANG\n    #define VER_LANG                 0x0000\n    #endif\n    #ifndef VER_CP\n    #define VER_CP                   0x04E4\n    #endif\n    #ifndef VER_BLOCK\n    #define VER_BLOCK                \"000004E4\"\n    #endif\n#else\n    #ifndef VER_LANG\n    #define VER_LANG                 0x0409\n    #endif\n    #ifndef VER_CP\n    #define VER_CP                   0x04E4\n    #endif\n    #ifndef VER_BLOCK\n    #define VER_BLOCK                \"040904E4\"\n    #endif\n#endif\n\n#define VER_FILE_VERSION             rmj, rmm, rbd, rev\n#define VER_PRODUCT_VERSION          rmj, rmm, rbd, rev\n#define VER_FILE_VERSION_STRING      szVerMajorMinorBuildRev\n#define VER_PRODUCT_VERSION_STRING   VER_FILE_VERSION_STRING\n#define VER_FILE_FLAGS_MASK          VS_FFI_FILEFLAGSMASK\n#define VER_FILE_FLAGS               (VER_DEBUG | VER_PRIVATE_BUILD | VER_PRE_RELEASE)\n\n#define VER_FILE_OS                  VOS__WINDOWS32\n\n#define VER_COMPANY_NAME             \"Outercurve Foundation\"\n#ifndef VER_PRODUCT_NAME\n    #define VER_PRODUCT_NAME         \"Windows Installer XML (WiX)\"\n#endif\n#ifndef VER_FILE_DESCRIPTION\n    #define VER_FILE_DESCRIPTION     \"Windows Installer XML (WiX) component\"\n#endif\n\n#if defined(VER_LEGAL_COPYRIGHT)\n    #error\n#endif\n#define VER_LEGAL_COPYRIGHT          \"Copyright (c) Outercurve Foundation.\\240 All rights reserved.\"\n\n#if !defined(VER_FILE_SUBTYPE)\n    #define VER_FILE_SUBTYPE 0\n#endif\n\n#ifdef RC_INVOKED\n\nVS_VERSION_INFO VERSIONINFO\nFILEVERSION     VER_FILE_VERSION\nPRODUCTVERSION  VER_PRODUCT_VERSION\nFILEFLAGSMASK   VER_FILE_FLAGS_MASK\nFILEFLAGS       VER_FILE_FLAGS\nFILEOS          VER_FILE_OS\nFILETYPE        VER_FILE_TYPE\nFILESUBTYPE     VER_FILE_SUBTYPE\nBEGIN\nBLOCK \"StringFileInfo\"\n    BEGIN\n    BLOCK VER_BLOCK\n        BEGIN\n        VALUE \"CompanyName\",       VER_COMPANY_NAME\n        VALUE \"FileDescription\",   VER_FILE_DESCRIPTION\n        VALUE \"FileVersion\",       VER_FILE_VERSION_STRING\n        VALUE \"InternalName\",      VER_INTERNAL_NAME\n        \n        VALUE \"LegalCopyright\",    VER_LEGAL_COPYRIGHT\n\n        VALUE \"OriginalFilename\",  VER_ORIGINAL_FILENAME\n        VALUE \"ProductName\",       VER_PRODUCT_NAME\n        VALUE \"ProductVersion\",    VER_FILE_VERSION_STRING\n#if defined(DEBUG)\n        VALUE \"WiX Common Resource Format\", \"Debug Only\"\n#endif\n        END\n    END\n\nBLOCK \"VarFileInfo\"\n    BEGIN\n    VALUE \"Translation\", VER_LANG, VER_CP\n    END\nEND\n\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixext/BalCompiler.cs",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"BalCompiler.cs\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//\n// <summary>\n// The compiler for the Windows Installer XML Toolset Bal Extension.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\nnamespace Microsoft.Tools.WindowsInstallerXml.Extensions\n{\n    using System;\n    using System.Collections.Generic;\n    using System.Diagnostics;\n    using System.Globalization;\n    using System.IO;\n    using System.Reflection;\n    using System.Xml;\n    using System.Xml.Schema;\n    using Microsoft.Tools.WindowsInstallerXml;\n\n    /// <summary>\n    /// The compiler for the Windows Installer XML Toolset Bal Extension.\n    /// </summary>\n    public sealed class BalCompiler : CompilerExtension\n    {\n        private SourceLineNumberCollection addedConditionLineNumber;\n        private XmlSchema schema;\n\n        /// <summary>\n        /// Instantiate a new BalCompiler.\n        /// </summary>\n        public BalCompiler()\n        {\n            this.addedConditionLineNumber = null;\n            this.schema = LoadXmlSchemaHelper(Assembly.GetExecutingAssembly(), \"Microsoft.Tools.WindowsInstallerXml.Extensions.Xsd.bal.xsd\");\n        }\n\n        /// <summary>\n        /// Gets the schema for this extension.\n        /// </summary>\n        /// <value>Schema for this extension.</value>\n        public override XmlSchema Schema\n        {\n            get { return this.schema; }\n        }\n\n        /// <summary>\n        /// Processes an element for the Compiler.\n        /// </summary>\n        /// <param name=\"sourceLineNumbers\">Source line number for the parent element.</param>\n        /// <param name=\"parentElement\">Parent element of element to process.</param>\n        /// <param name=\"element\">Element to process.</param>\n        /// <param name=\"contextValues\">Extra information about the context in which this element is being parsed.</param>\n        public override void ParseElement(SourceLineNumberCollection sourceLineNumbers, XmlElement parentElement, XmlElement element, params string[] contextValues)\n        {\n            switch (parentElement.LocalName)\n            {\n                case \"Bundle\":\n                case \"Fragment\":\n                    switch (element.LocalName)\n                    {\n                        case \"Condition\":\n                            this.ParseConditionElement(element);\n                            break;\n                        default:\n                            this.Core.UnexpectedElement(parentElement, element);\n                            break;\n                    }\n                    break;\n                case \"BootstrapperApplicationRef\":\n                    switch (element.LocalName)\n                    {\n                        case \"WixExtendedBootstrapperApplication\":\n                            this.ParseWixExtendedBootstrapperApplicationElement(element);\n                            break;\n                        default:\n                            this.Core.UnexpectedElement(parentElement, element);\n                            break;\n                    }\n                    break;\n                default:\n                    this.Core.UnexpectedElement(parentElement, element);\n                    break;\n            }\n        }\n\n        /// <summary>\n        /// Processes an attribute for the Compiler.\n        /// </summary>\n        /// <param name=\"sourceLineNumbers\">Source line number for the parent element.</param>\n        /// <param name=\"parentElement\">Parent element of element to process.</param>\n        /// <param name=\"attribute\">Attribute to process.</param>\n        /// <param name=\"contextValues\">Extra information about the context in which this element is being parsed.</param>\n        public override void ParseAttribute(SourceLineNumberCollection sourceLineNumbers, XmlElement parentElement, XmlAttribute attribute, Dictionary<string, string> contextValues)\n        {\n            switch (parentElement.LocalName)\n            {\n                case \"Variable\":\n                    // at the time the extension attribute is parsed, the compiler might not yet have\n                    // parsed the Name attribute, so we need to get it directly from the parent element.\n                    string variableName = parentElement.GetAttribute(\"Name\");\n                    if (String.IsNullOrEmpty(variableName))\n                    {\n                        this.Core.OnMessage(WixErrors.ExpectedParentWithAttribute(sourceLineNumbers, \"Variable\", \"Overridable\", \"Name\"));\n                    }\n                    else\n                    {\n                        switch (attribute.LocalName)\n                        {\n                            case \"Overridable\":\n                                if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attribute))\n                                {\n                                    Row row = this.Core.CreateRow(sourceLineNumbers, \"WixStdbaOverridableVariable\");\n                                    row[0] = variableName;\n                                }\n                                break;\n                            default:\n                                this.Core.UnexpectedAttribute(sourceLineNumbers, attribute);\n                                break;\n                        }\n                    }\n                    break;\n                default:\n                    this.Core.UnexpectedElement(parentElement, parentElement);\n                    break;\n            }\n        }\n\n        /// <summary>\n        /// Parses a Condition element for Bundles.\n        /// </summary>\n        /// <param name=\"node\">The element to parse.</param>\n        private void ParseConditionElement(XmlNode node)\n        {\n            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);\n            string condition = CompilerCore.GetConditionInnerText(node); // condition is the inner text of the element.\n            string message = null;\n\n            foreach (XmlAttribute attrib in node.Attributes)\n            {\n                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)\n                {\n                    switch (attrib.LocalName)\n                    {\n                        case \"Message\":\n                            message = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false);\n                            break;\n                        default:\n                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);\n                            break;\n                    }\n                }\n                else\n                {\n                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);\n                }\n            }\n\n            foreach (XmlNode child in node.ChildNodes)\n            {\n                if (XmlNodeType.Element == child.NodeType)\n                {\n                    if (child.NamespaceURI == this.schema.TargetNamespace)\n                    {\n                        this.Core.UnexpectedElement(node, child);\n                    }\n                    else\n                    {\n                        this.Core.UnsupportedExtensionElement(node, child);\n                    }\n                }\n            }\n\n            // Error check the values.\n            if (String.IsNullOrEmpty(condition))\n            {\n                this.Core.OnMessage(WixErrors.ConditionExpected(sourceLineNumbers, node.Name));\n            }\n\n            if (null == message)\n            {\n                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, \"Message\"));\n            }\n\n            if (!this.Core.EncounteredError)\n            {\n                Row row = this.Core.CreateRow(sourceLineNumbers, \"WixBalCondition\");\n                row[0] = condition;\n                row[1] = message;\n\n                if (null == this.addedConditionLineNumber)\n                {\n                    this.addedConditionLineNumber = sourceLineNumbers;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Parses a WixExtendedBootstrapperApplication element for Bundles.\n        /// </summary>\n        /// <param name=\"node\">The element to parse.</param>\n        private void ParseWixExtendedBootstrapperApplicationElement(XmlNode node)\n        {\n            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);\n            string launchTarget = null;\n            string licenseFile = null;\n            string licenseUrl = null;\n            string logoFile = null;\n            string logoSideFile = null;\n            string themeFile = null;\n            string localizationFile = null;\n            YesNoType suppressOptionsUI = YesNoType.NotSet;\n            YesNoType suppressDowngradeFailure = YesNoType.NotSet;\n            YesNoType suppressRepair = YesNoType.NotSet;\n\n            foreach (XmlAttribute attrib in node.Attributes)\n            {\n                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)\n                {\n                    switch (attrib.LocalName)\n                    {\n                        case \"LaunchTarget\":\n                            launchTarget = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false);\n                            break;\n                        case \"LicenseFile\":\n                            licenseFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false);\n                            break;\n                        case \"LicenseUrl\":\n                            licenseUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib, true);\n                            break;\n                        case \"LogoFile\":\n                            logoFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false);\n                            break;\n                        case \"LogoSideFile\":\n                            logoSideFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false);\n                            break;\n                        case \"ThemeFile\":\n                            themeFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false);\n                            break;\n                        case \"LocalizationFile\":\n                            localizationFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false);\n                            break;\n                        case \"SuppressOptionsUI\":\n                            suppressOptionsUI = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);\n                            break;\n                        case \"SuppressDowngradeFailure\":\n                            suppressDowngradeFailure = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);\n                            break;\n                        case \"SuppressRepair\":\n                            suppressRepair = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);\n                            break;\n                        default:\n                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);\n                            break;\n                    }\n                }\n                else\n                {\n                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);\n                }\n            }\n\n            foreach (XmlNode child in node.ChildNodes)\n            {\n                if (XmlNodeType.Element == child.NodeType)\n                {\n                    if (child.NamespaceURI == this.schema.TargetNamespace)\n                    {\n                        this.Core.UnexpectedElement(node, child);\n                    }\n                    else\n                    {\n                        this.Core.UnsupportedExtensionElement(node, child);\n                    }\n                }\n            }\n\n            if (String.IsNullOrEmpty(licenseFile) && null == licenseUrl)\n            {\n                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, \"LicenseFile\", \"LicenseUrl\", true));\n            }\n\n            if (!this.Core.EncounteredError)\n            {\n                if (!String.IsNullOrEmpty(launchTarget))\n                {\n                    this.Core.CreateVariableRow(sourceLineNumbers, \"LaunchTarget\", launchTarget, \"string\", false, false);\n                }\n\n                if (!String.IsNullOrEmpty(licenseFile))\n                {\n                    this.Core.CreateWixVariableRow(sourceLineNumbers, \"WixExtbaLicenseRtf\", licenseFile, false);\n                }\n\n                if (null != licenseUrl)\n                {\n                    this.Core.CreateWixVariableRow(sourceLineNumbers, \"WixExtbaLicenseUrl\", licenseUrl, false);\n                }\n\n                if (!String.IsNullOrEmpty(logoFile))\n                {\n                    this.Core.CreateWixVariableRow(sourceLineNumbers, \"WixExtbaLogo\", logoFile, false);\n                }\n\n                if (!String.IsNullOrEmpty(logoSideFile))\n                {\n                    this.Core.CreateWixVariableRow(sourceLineNumbers, \"WixExtbaLogoSide\", logoSideFile, false);\n                }\n\n                if (!String.IsNullOrEmpty(themeFile))\n                {\n                    this.Core.CreateWixVariableRow(sourceLineNumbers, \"WixExtbaThemeXml\", themeFile, false);\n                }\n\n                if (!String.IsNullOrEmpty(localizationFile))\n                {\n                    this.Core.CreateWixVariableRow(sourceLineNumbers, \"WixExtbaThemeWxl\", localizationFile, false);\n                }\n\n                if (YesNoType.Yes == suppressOptionsUI || YesNoType.Yes == suppressDowngradeFailure || YesNoType.Yes == suppressRepair)\n                {\n                    Row row = this.Core.CreateRow(sourceLineNumbers, \"WixExtbaOptions\");\n                    if (YesNoType.Yes == suppressOptionsUI)\n                    {\n                        row[0] = 1;\n                    }\n\n                    if (YesNoType.Yes == suppressDowngradeFailure)\n                    {\n                        row[1] = 1;\n                    }\n\n                    if (YesNoType.Yes == suppressRepair)\n                    {\n                        row[2] = 1;\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixext/BalExtension.cs",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"BalExtension.cs\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//\n// <summary>\n// The Windows Installer XML Toolset Bal extension.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\nnamespace Microsoft.Tools.WindowsInstallerXml.Extensions\n{\n    using System;\n    using System.Reflection;\n\n    /// <summary>\n    /// The Windows Installer XML Toolset Bal Extension.\n    /// </summary>\n    public sealed class BalExtension : WixExtension\n    {\n        private BalCompiler compilerExtension;\n        private Library library;\n        private TableDefinitionCollection tableDefinitions;\n\n        private BalPreprocessorExtension preprocessorExtension;\n\n        /// <summary>\n        /// Gets the optional compiler extension.\n        /// </summary>\n        /// <value>The optional compiler extension.</value>\n        public override CompilerExtension CompilerExtension\n        {\n            get\n            {\n                if (null == this.compilerExtension)\n                {\n                    this.compilerExtension = new BalCompiler();\n                }\n\n                return this.compilerExtension;\n            }\n        }\n\n        /// <summary>\n        /// Gets the optional table definitions for this extension.\n        /// </summary>\n        /// <value>The optional table definitions for this extension.</value>\n        public override TableDefinitionCollection TableDefinitions\n        {\n            get\n            {\n                if (null == this.tableDefinitions)\n                {\n                    this.tableDefinitions = LoadTableDefinitionHelper(Assembly.GetExecutingAssembly(), \"Microsoft.Tools.WindowsInstallerXml.Extensions.Data.tables.xml\");\n                }\n\n                return this.tableDefinitions;\n            }\n        }\n\n        /// <summary>\n        /// Gets the library associated with this extension.\n        /// </summary>\n        /// <param name=\"tableDefinitions\">The table definitions to use while loading the library.</param>\n        /// <returns>The loaded library.</returns>\n        public override Library GetLibrary(TableDefinitionCollection tableDefinitions)\n        {\n            if (null == this.library)\n            {\n                this.library = LoadLibraryHelper(Assembly.GetExecutingAssembly(), \"Microsoft.Tools.WindowsInstallerXml.Extensions.Data.balExt.wixlib\", tableDefinitions);\n            }\n\n            return this.library;\n        }\n\n        /// <summary>\n        /// Gets the optional preprocessor extension.\n        /// </summary>\n        /// <value>The optional preprocessor extension.</value>\n        public override PreprocessorExtension PreprocessorExtension\n        {\n            get\n            {\n                if (null == this.preprocessorExtension)\n                {\n                    this.preprocessorExtension = new BalPreprocessorExtension();\n                }\n\n                return this.preprocessorExtension;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixext/BalPreprocessorExtension.cs",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"ValuePreprocessorExtension.cs\" company=\"\">\n// </copyright>\n//\n// <summary>\n// A WiX preprocessor extension.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\nnamespace Microsoft.Tools.WindowsInstallerXml.Extensions\n{\n    using System;\n    using Microsoft.Tools.WindowsInstallerXml;\n\n    /// <summary>\n    /// The preprocessor extension.\n    /// </summary>\n    public sealed class BalPreprocessorExtension : PreprocessorExtension\n    {\n        private static readonly string[] prefixes = {\"bal\"};\n\n        /// <summary>\n        /// Gets the variable prefixes for this extension.\n        /// </summary>\n        /// <value>The variable prefixes for this extension.</value>\n        public override string[] Prefixes\n        {\n            get { return prefixes; }\n        }\n\n        public override string EvaluateFunction(string prefix, string function, string[] args)\n        {\n            string result = null;\n\n            switch (prefix)\n            {\n                case \"bal\":\n                    switch (function)\n                    {\n                        case \"Version\":\n                            // Make sure the base version is specified\n                            if (args.Length == 0 || args[0].Length == 0)\n                            {\n                                throw new ArgumentException(\"Version template not specified\");\n                            }\n\n                            // Build = days since 1/1/2000; Revision = seconds since midnight / 2\n                            DateTime now = DateTime.Now.ToUniversalTime();\n                            double build = (now - new DateTime(2000, 1, 1)).TotalDays;\n                            double revision = now.TimeOfDay.TotalSeconds / 2;\n\n                            result = String.Format(\"{0}.{1}.{2}\", args[0], (int)build, (int)revision);\n\n                            break;\n                    }\n\n                    break;\n            }\n\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixext/Properties/AssemblyInfo.cs",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"AssemblyInfo.cs\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file LICENSE.TXT\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n// The assembly information for the Windows Installer XML Toolset Bootstrapper Application Layer Extension.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\nusing System;\nusing System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\nusing Microsoft.Tools.WindowsInstallerXml;\nusing Microsoft.Tools.WindowsInstallerXml.Extensions;\n\n[assembly: AssemblyTitle(\"WiX Toolset Bootstrapper Application Layer Extension\")]\n[assembly: AssemblyDescription(\"Windows Installer XML Toolset Bootstrapper Application Layer Extension\")]\n[assembly: AssemblyCulture(\"\")]\n[assembly: CLSCompliant(true)]\n[assembly: ComVisible(false)]\n[assembly: AssemblyDefaultWixExtension(typeof(BalExtension))]\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixext/WixBalExtensionExt.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  <copyright file=\"WixBalExtension.csproj\" company=\"Outercurve Foundation\">\n    Copyright (c) 2004, Outercurve Foundation.\n    This software is released under Microsoft Reciprocal License (MS-RL).\n    The license and further copyright text can be found in the file\n    LICENSE.TXT at the root directory of the distribution.\n  </copyright>\n-->\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\" ToolsVersion=\"4.0\">\n  <PropertyGroup>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>\n    <ProductVersion>8.0.30703</ProductVersion>\n    <SchemaVersion>2.0</SchemaVersion>\n    <ProjectGuid>{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}</ProjectGuid>\n    <OutputType>Library</OutputType>\n    <AppDesignerFolder>Properties</AppDesignerFolder>\n    <RootNamespace>Microsoft.Tools.WindowsInstallerXml.Extensions</RootNamespace>\n    <AssemblyName>WixBalExtensionExt</AssemblyName>\n    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>\n    <FileAlignment>512</FileAlignment>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' \">\n    <DebugSymbols>true</DebugSymbols>\n    <DebugType>full</DebugType>\n    <Optimize>false</Optimize>\n    <OutputPath>bin\\Debug\\</OutputPath>\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' \">\n    <DebugType>pdbonly</DebugType>\n    <Optimize>true</Optimize>\n    <OutputPath>bin\\Release\\</OutputPath>\n    <DefineConstants>TRACE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n  </PropertyGroup>\n  <ItemGroup>\n    <Reference Include=\"System\" />\n    <Reference Include=\"System.Data\" />\n    <Reference Include=\"System.Xml\" />\n    <Reference Include=\"wix, Version=3.0.0.0, Culture=neutral, PublicKeyToken=ce35f76fcda82bad, processorArchitecture=MSIL\">\n      <SpecificVersion>False</SpecificVersion>\n      <HintPath>$(WIX)bin\\wix.dll</HintPath>\n      <Private>False</Private>\n    </Reference>\n  </ItemGroup>\n  <ItemGroup>\n    <Compile Include=\"..\\inc\\WixDistribution.cs\">\n      <Link>Properties\\WixDistribution.cs</Link>\n    </Compile>\n    <Compile Include=\"..\\inc\\wixver.cs\">\n      <Link>Properties\\wixver.cs</Link>\n    </Compile>\n    <Compile Include=\"BalCompiler.cs\" />\n    <Compile Include=\"BalExtension.cs\" />\n    <Compile Include=\"Properties\\AssemblyInfo.cs\" />\n    <Compile Include=\"BalPreprocessorExtension.cs\" />\n    <MsgGenSource Include=\"Data\\messages.xml\">\n      <ResourcesLogicalName>$(RootNamespace).Data.Messages.resources</ResourcesLogicalName>\n    </MsgGenSource>\n    <EmbeddedResource Include=\"Data\\tables.xml\">\n      <LogicalName>$(RootNamespace).Data.tables.xml</LogicalName>\n    </EmbeddedResource>\n    <EmbeddedResource Include=\"Xsd\\bal.xsd\">\n      <LogicalName>$(RootNamespace).Xsd.bal.xsd</LogicalName>\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </EmbeddedResource>\n    <XsdGenSource Include=\"Xsd\\bal.xsd\">\n      <CommonNamespace>Microsoft.Tools.WindowsInstallerXml.Serialize</CommonNamespace>\n      <Namespace>Microsoft.Tools.WindowsInstallerXml.Extensions.Serialize.Bal</Namespace>\n    </XsdGenSource>\n    <EmbeddedResource Include=\"..\\build\\balExt.wixlib\">\n      <Link>Data\\balExt.wixlib</Link>\n    </EmbeddedResource>\n  </ItemGroup>\n  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSharp.targets\" />\n  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \n       Other similar extension points exist, see Microsoft.Common.targets.\n  <Target Name=\"BeforeBuild\">\n  </Target>\n  <Target Name=\"AfterBuild\">\n  </Target>\n  -->\n</Project>"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixext/Xsd/bal.xsd",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  <copyright file=\"bal.xsd\" company=\"Outercurve Foundation\">\n    Copyright (c) 2004, Outercurve Foundation.\n    This software is released under Microsoft Reciprocal License (MS-RL).\n    The license and further copyright text can be found in the file\n    LICENSE.TXT at the root directory of the distribution.\n  </copyright>\n-->\n<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n          xmlns:xse=\"http://schemas.microsoft.com/wix/2005/XmlSchemaExtension\"\n         xmlns:html=\"http://www.w3.org/1999/xhtml\"\n    targetNamespace=\"http://schemas.microsoft.com/wix/BalExtension\"\n              xmlns=\"http://schemas.microsoft.com/wix/BalExtension\">\n    <xs:annotation>\n        <xs:documentation>\n            The source code schema for the Windows Installer XML Toolset Burn User Experience Extension.\n        </xs:documentation>\n    </xs:annotation>\n\n    <xs:import namespace=\"http://schemas.microsoft.com/wix/2006/wi\" />\n\n    <xs:element name=\"Condition\">\n        <xs:annotation>\n            <xs:documentation>\n                Conditions for a bundle. The condition is specified in the inner text of the element.\n            </xs:documentation>\n            <xs:appinfo>\n                <xse:parent namespace=\"http://schemas.microsoft.com/wix/2006/wi\" ref=\"Bundle\" />\n                <xse:parent namespace=\"http://schemas.microsoft.com/wix/2006/wi\" ref=\"Fragment\" />\n            </xs:appinfo>\n        </xs:annotation>\n        <xs:complexType>\n            <xs:simpleContent>\n                <xs:extension base=\"xs:string\">\n                    <xs:annotation>\n                        <xs:documentation>\n                            The condition that must evaluate to true for the installation to continue.\n                        </xs:documentation>\n                    </xs:annotation>\n                    <xs:attribute name=\"Message\" type=\"xs:string\" use=\"required\">\n                        <xs:annotation>\n                            <xs:documentation>\n                                Set the value to the text to display when the condition fails and the installation must be terminated.\n                            </xs:documentation>\n                        </xs:annotation>\n                    </xs:attribute>\n                </xs:extension>\n            </xs:simpleContent>\n        </xs:complexType>\n    </xs:element>\n\n    <xs:element name=\"WixExtendedBootstrapperApplication\">\n        <xs:annotation>\n            <xs:documentation>\n                Configures WixExtendedBootstrapperApplication for a Bundle.\n            </xs:documentation>\n            <xs:appinfo>\n                <xse:parent namespace=\"http://schemas.microsoft.com/wix/2006/wi\" ref=\"BootstrapperApplicationRef\" />\n            </xs:appinfo>\n        </xs:annotation>\n        <xs:complexType>\n            <xs:attribute name=\"LaunchTarget\" type=\"xs:string\">\n                <xs:annotation>\n                    <xs:documentation>If set, the success page will show a Launch button the user can use to launch the application being installed. The string value can be formatted using Burn variables enclosed in brackets, to refer to installation directories and so forth.</xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"LicenseFile\" type=\"xs:string\">\n                <xs:annotation>\n                    <xs:documentation>Source file of the RTF license file. Cannot be used simultaneously with LicenseUrl.</xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"LicenseUrl\" type=\"xs:string\">\n                <xs:annotation>\n                    <xs:documentation>URL target of the license link. Cannot be used simultaneously with LicenseFile. This attribute can be empty to hide the license link completely.</xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"LogoFile\" type=\"xs:string\">\n                <xs:annotation>\n                    <xs:documentation>Source file of the logo graphic.</xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"LogoSideFile\" type=\"xs:string\">\n                <xs:annotation>\n                    <xs:documentation>Source file of the side logo graphic.</xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"ThemeFile\" type=\"xs:string\">\n                <xs:annotation>\n                    <xs:documentation>Source file of the theme XML.</xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"LocalizationFile\" type=\"xs:string\">\n                <xs:annotation>\n                    <xs:documentation>Source file of the theme localization .wxl file.</xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"SuppressOptionsUI\" type=\"YesNoType\">\n                <xs:annotation>\n                    <xs:documentation>If set to \"yes\", the Options button will not be shown and the user will not be able to choose an installation directory.</xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"SuppressDowngradeFailure\" type=\"YesNoType\">\n                <xs:annotation>\n                    <xs:documentation>If set to \"yes\", attempting to installer a downgraded version of a bundle will be treated as a successful do-nothing operation.\n                    The default behavior (or when explicitly set to \"no\") is to treat downgrade attempts as failures. </xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"SuppressRepair\" type=\"YesNoType\">\n                <xs:annotation>\n                    <xs:documentation>If set to \"yes\", the Repair button will not be shown in the maintenance-mode UI.</xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n        </xs:complexType>\n    </xs:element>\n\n    <xs:attribute name=\"Overridable\">\n        <xs:annotation>\n            <xs:documentation>\n                When set to \"yes\", lets the user override the variable's default value by specifying another value on the command line,\n                in the form Variable=Value. Otherwise, WixStdBA won't overwrite the default value and will log \n                \"Ignoring attempt to set non-overridable variable: 'BAR'.\"\n            </xs:documentation>\n            <xs:appinfo>\n                <xse:parent namespace=\"http://schemas.microsoft.com/wix/2006/wi\" ref=\"Variable\" />\n            </xs:appinfo>\n        </xs:annotation>\n    </xs:attribute>\n\n  <xs:simpleType name=\"YesNoType\">\n        <xs:annotation>\n            <xs:documentation>Values of this type will either be \"yes\" or \"no\".</xs:documentation>\n        </xs:annotation>\n        <xs:restriction base=\"xs:NMTOKEN\">\n            <xs:enumeration value=\"no\"/>\n            <xs:enumeration value=\"yes\"/>\n        </xs:restriction>\n    </xs:simpleType>\n</xs:schema>\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixext/data/messages.xml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  <copyright file=\"messages.xml\" company=\"Outercurve Foundation\">\n    Copyright (c) 2004, Outercurve Foundation.\n    This software is released under Microsoft Reciprocal License (MS-RL).\n    The license and further copyright text can be found in the file\n    LICENSE.TXT at the root directory of the distribution.\n  </copyright>\n-->\n<!--\n    The messages for the Windows Installer XML Toolset Bal Extension.\n-->\n<Messages Namespace=\"Microsoft.Tools.WindowsInstallerXml.Extensions\" Resources=\"Data.Messages\" xmlns=\"http://schemas.microsoft.com/genmsgs/2004/07/messages\">\n    <Class Name=\"BalErrors\" ContainerName=\"BalErrorEventArgs\" BaseContainerName=\"WixErrorEventArgs\">\n    </Class>\n</Messages>\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixext/data/tables.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  <copyright file=\"tables.xml\" company=\"Outercurve Foundation\">\n    Copyright (c) 2004, Outercurve Foundation.\n    This software is released under Microsoft Reciprocal License (MS-RL).\n    The license and further copyright text can be found in the file\n    LICENSE.TXT at the root directory of the distribution.\n  </copyright>\n-->\n<!--\n    The table definitions for the Windows Installer XML Toolset Bal Extension.\n-->\n<tableDefinitions xmlns=\"http://schemas.microsoft.com/wix/2006/tables\">\n    <tableDefinition name=\"WixBalCondition\" bootstrapperApplicationData=\"yes\">\n        <columnDefinition name=\"Condition\" type=\"string\" length=\"255\" primaryKey=\"yes\" localizable=\"yes\"\n                category=\"condition\" description=\"Expression which must evaluate to TRUE in order for install to commence.\"/>\n        <columnDefinition name=\"Message\" type=\"localized\" length=\"255\" escapeIdtCharacters=\"yes\"\n                category=\"formatted\" description=\"Localizable text to display when condition fails and install must abort.\"/>\n    </tableDefinition>\n\n    <tableDefinition name=\"WixExtbaOptions\" bootstrapperApplicationData=\"yes\">\n        <columnDefinition name=\"SuppressOptionsUI\" type=\"number\" length=\"2\" nullable=\"yes\"\n                maxValue=\"1\" description=\"If 1, don't show Options button during install.\"/>\n        <columnDefinition name=\"SuppressDowngradeFailure\" type=\"number\" length=\"2\" nullable=\"yes\"\n                maxValue=\"1\" description=\"If 1, attempts to downgrade are treated as a successful no-op.\"/>\n        <columnDefinition name=\"SuppressRepair\" type=\"number\" length=\"2\" nullable=\"yes\"\n                maxValue=\"1\" description=\"If 1, don't show Repair button during maintenance.\"/>\n    </tableDefinition>\n\n    <tableDefinition name=\"WixStdbaOverridableVariable\" bootstrapperApplicationData=\"yes\">\n        <columnDefinition name=\"Name\" type=\"string\" length=\"255\" primaryKey=\"yes\" \n                category=\"identifier\" description=\"Variable name user can override.\"/>\n    </tableDefinition>\n</tableDefinitions>\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixlib/BalExtension.wixproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<!--\n  <copyright file=\"BalExtension.wixproj\" company=\"Outercurve Foundation\">\n    Copyright (c) 2004, Outercurve Foundation.\n    This software is released under Microsoft Reciprocal License (MS-RL).\n    The license and further copyright text can be found in the file\n    LICENSE.TXT at the root directory of the distribution.\n  </copyright>\n-->\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\" ToolsVersion=\"4.0\">\n  <PropertyGroup>\n    <ProjectGuid>{3444d952-f21c-496f-ab6b-56435bfd0787}</ProjectGuid>\n    <OutputName>balExt</OutputName>\n    <OutputType>Library</OutputType>\n    <BindFiles>True</BindFiles>\n    <Pedantic>True</Pedantic>\n    <TreatWarningsAsErrors>True</TreatWarningsAsErrors>\n    <Cultures>en-us</Cultures>\n    <WixTargetsPath Condition=\" '$(WixTargetsPath)' == '' \">$(MSBuildExtensionsPath)\\Microsoft\\WiX\\v3.x\\Wix.targets</WixTargetsPath>\n    <OutputPath>$(Configuration)\\$(Platform)</OutputPath>\n    <LibBindFiles>True</LibBindFiles>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|x86' \">\n    <OutputPath>..\\build\\</OutputPath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|x86' \">\n    <OutputPath>..\\build\\</OutputPath>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Include=\"BalExtension.wxs\" />\n    <Compile Include=\"wixstdba.wxs\" />\n    <Compile Include=\"wixstdba_x86.wxs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Content Include=\"wixstdba_platform.wxi\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\wixstdba\\wixstdba.vcxproj\">\n      <Name>wixextba</Name>\n      <Project>{41085a22-e6aa-4e8b-ab1b-ddee0dc89dfa}</Project>\n      <Private>True</Private>\n      <DoNotHarvest>True</DoNotHarvest>\n      <RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>\n      <RefTargetDir>INSTALLFOLDER</RefTargetDir>\n    </ProjectReference>\n  </ItemGroup>\n  <Import Project=\"$(WixTargetsPath)\" />\n</Project>"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixlib/BalExtension.wxs",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  <copyright file=\"BalExtension.wxs\" company=\"Outercurve Foundation\">\n    Copyright (c) 2004, Outercurve Foundation.\n    This software is released under Microsoft Reciprocal License (MS-RL).\n    The license and further copyright text can be found in the file\n    LICENSE.TXT at the root directory of the distribution.\n  </copyright>\n-->\n<Wix xmlns=\"http://schemas.microsoft.com/wix/2006/wi\">\n  <Fragment>\n  </Fragment>\n</Wix>\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixlib/wixstdba.wxs",
    "content": "<?xml version='1.0' encoding='utf-8'?>\n<!--\n  <copyright file=\"wixstdba.wxs\" company=\"Outercurve Foundation\">\n    Copyright (c) 2004, Outercurve Foundation.\n    This software is released under Microsoft Reciprocal License (MS-RL).\n    The license and further copyright text can be found in the file\n    LICENSE.TXT at the root directory of the distribution.\n  </copyright>\n-->\n<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>\n  <!-- RTF License Payload Group -->\n  <Fragment>\n    <PayloadGroup Id='WixExtbaRtfLicensePayloads'>\n      <Payload Name='thm.xml' Compressed='yes' SourceFile='!(wix.WixExtbaThemeXml=$(var.wixextba.ProjectDir)Resources\\RtfTheme.xml)' />\n      <Payload Name='thm.wxl' Compressed='yes' SourceFile='!(wix.WixExtbaThemeWxl=$(var.wixextba.ProjectDir)Resources\\RtfTheme.wxl)' />\n      <Payload Name='Logo.png' Compressed='yes' SourceFile='!(wix.WixExtbaLogo=$(var.wixextba.ProjectDir)Resources\\Logo.png)' />\n\n      <Payload Name='!(wix.WixExtbaLicenseRtfName=license.rtf)' Compressed='yes' SourceFile='!(wix.WixExtbaLicenseRtf=$(var.wixextba.ProjectDir)Resources\\LoremIpsumLicense.rtf)' />\n    </PayloadGroup>\n\n    <CustomTable Id='WixExtbaInformation'>\n      <Row>\n        <Data Column='LicenseFile'>!(wix.WixExtbaLicenseRtfName=license.rtf)</Data>\n      </Row>\n    </CustomTable>\n  </Fragment>\n\n  <!-- Hyperlink License Payload Group -->\n  <Fragment>\n    <PayloadGroup Id='WixExtbaHyperlinkLicensePayloads'>\n      <Payload Name='thm.xml' Compressed='yes' SourceFile='!(wix.WixExtbaThemeXml=$(var.wixextba.ProjectDir)Resources\\HyperlinkTheme.xml)' />\n      <Payload Name='thm.wxl' Compressed='yes' SourceFile='!(wix.WixExtbaThemeWxl=$(var.wixextba.ProjectDir)Resources\\HyperlinkTheme.wxl)' />\n      <Payload Name='Logo.png' Compressed='yes' SourceFile='!(wix.WixExtbaLogo=$(var.wixextba.ProjectDir)Resources\\Logo.png)' />\n    </PayloadGroup>\n\n    <CustomTable Id='WixExtbaInformation'>\n      <Row>\n        <Data Column='LicenseUrl'>!(wix.WixExtbaLicenseUrl)</Data>\n      </Row>\n    </CustomTable>\n  </Fragment>\n\n  <!-- Hyperlink2 License Payload Group -->\n  <Fragment>\n    <PayloadGroup Id='WixExtbaHyperlink2LicensePayloads'>\n      <Payload Name='thm.xml' Compressed='yes' SourceFile='!(wix.WixExtbaThemeXml=$(var.wixextba.ProjectDir)Resources\\Hyperlink2Theme.xml)' />\n      <Payload Name='thm.wxl' Compressed='yes' SourceFile='!(wix.WixExtbaThemeWxl=$(var.wixextba.ProjectDir)Resources\\HyperlinkTheme.wxl)' />\n      <Payload Name='LogoSide.png' Compressed='yes' SourceFile='!(wix.WixExtbaLogoSide=$(var.wixextba.ProjectDir)Resources\\LogoSide.png)' />\n      <Payload Name='Logo.png' Compressed='yes' SourceFile='!(wix.WixExtbaLogo=$(var.wixextba.ProjectDir)Resources\\Logo.png)' />\n    </PayloadGroup>\n\n    <CustomTable Id='WixExtbaInformation'>\n      <Row>\n        <Data Column='LicenseUrl'>!(wix.WixExtbaLicenseUrl)</Data>\n      </Row>\n    </CustomTable>\n  </Fragment>\n\n  <!-- BootstrapperApplicationData tables definition -->\n  <Fragment>\n    <CustomTable Id='WixExtbaInformation' BootstrapperApplicationData='yes'>\n      <Column Id='LicenseFile' Category='Text' Type='string' Width='0' Nullable='yes' PrimaryKey='yes' />\n      <Column Id='LicenseUrl' Category='Text' Type='string' Width='0' Nullable='yes' PrimaryKey='yes' />\n    </CustomTable>\n  </Fragment>\n</Wix>\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixlib/wixstdba_platform.wxi",
    "content": "<?xml version='1.0' encoding='utf-8'?>\n<!--\n  <copyright file=\"wixstdba_platform.wxi\" company=\"Outercurve Foundation\">\n    Copyright (c) 2004, Outercurve Foundation.\n    This software is released under Microsoft Reciprocal License (MS-RL).\n    The license and further copyright text can be found in the file\n    LICENSE.TXT at the root directory of the distribution.\n  </copyright>\n-->\n<Include xmlns='http://schemas.microsoft.com/wix/2006/wi'>\n  <Fragment>\n    <BootstrapperApplication Id='WixExtendedBootstrapperApplication.RtfLicense' SourceFile='$(var.wixextba.TargetDir)wixextba.dll'>\n      <PayloadGroupRef Id='WixExtbaRtfLicensePayloads' />\n    </BootstrapperApplication>\n  </Fragment>\n\n  <Fragment>\n    <BootstrapperApplication Id='WixExtendedBootstrapperApplication.HyperlinkLicense' SourceFile='$(var.wixextba.TargetDir)wixextba.dll'>\n      <PayloadGroupRef Id='WixExtbaHyperlinkLicensePayloads' />\n    </BootstrapperApplication>\n  </Fragment>\n\n  <Fragment>\n    <BootstrapperApplication Id='WixExtendedBootstrapperApplication.Hyperlink2License' SourceFile='$(var.wixextba.TargetDir)wixextba.dll'>\n      <PayloadGroupRef Id='WixExtbaHyperlink2LicensePayloads' />\n    </BootstrapperApplication>\n  </Fragment>\n\n  <Fragment>\n    <BootstrapperApplication Id='WixExtendedBootstrapperApplication.Foundation' SourceFile='$(var.wixextba.TargetDir)wixextba.dll' />\n  </Fragment>\n</Include>\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixlib/wixstdba_x86.wxs",
    "content": "<?xml version='1.0' encoding='utf-8'?>\n<!--\n  <copyright file=\"wixstdba_x86.wxs\" company=\"Outercurve Foundation\">\n    Copyright (c) 2004, Outercurve Foundation.\n    This software is released under Microsoft Reciprocal License (MS-RL).\n    The license and further copyright text can be found in the file\n    LICENSE.TXT at the root directory of the distribution.\n  </copyright>\n-->\n<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>\n  <?define platform=x86 ?>\n  <?include wixstdba_platform.wxi ?>\n</Wix>"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/JSON.cpp",
    "content": "/*\n * File JSON.cpp part of the SimpleJSON Library - http://mjpa.in/json\n *\n * Copyright (C) 2010 Mike Anchor\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"JSON.h\"\n\n/**\n * Blocks off the public constructor\n *\n * @access private\n *\n */\nJSON::JSON()\n{\n}\n\n/**\n * Parses a complete JSON encoded string\n * This is just a wrapper around the UNICODE Parse().\n *\n * @access public\n *\n * @param char* data The JSON text\n *\n * @return JSONValue* Returns a JSON Value representing the root, or NULL on error\n */\nJSONValue *JSON::Parse(const char *data)\n{\n\tsize_t length = strlen(data) + 1;\n\twchar_t *w_data = (wchar_t*)malloc(length * sizeof(wchar_t));\n\t\n\t#if defined(WIN32) && !defined(__GNUC__)\n\t\tsize_t ret_value = 0;\n\t\tif (mbstowcs_s(&ret_value, w_data, length, data, length) != 0)\n\t\t{\n\t\t\tfree(w_data);\n\t\t\treturn NULL;\n\t\t}\n\t#elif defined(ANDROID)\n\t\t// mbstowcs seems to misbehave on android\n\t\tfor(size_t i = 0; i<length; i++)\n\t\t\tw_data[i] = (wchar_t)data[i];\n\t#else\n\t\tif (mbstowcs(w_data, data, length) == (size_t)-1)\n\t\t{\n\t\t\tfree(w_data);\n\t\t\treturn NULL;\n\t\t}\n\t#endif\n\t\n\tJSONValue *value = JSON::Parse(w_data);\n\tfree(w_data);\n\treturn value;\n}\n\n/**\n * Parses a complete JSON encoded string (UNICODE input version)\n *\n * @access public\n *\n * @param wchar_t* data The JSON text\n *\n * @return JSONValue* Returns a JSON Value representing the root, or NULL on error\n */\nJSONValue *JSON::Parse(const wchar_t *data)\n{\n\t// Skip any preceding whitespace, end of data = no JSON = fail\n\tif (!SkipWhitespace(&data))\n\t\treturn NULL;\n\n\t// We need the start of a value here now...\n\tJSONValue *value = JSONValue::Parse(&data);\n\tif (value == NULL)\n\t\treturn NULL;\n\t\n\t// Can be white space now and should be at the end of the string then...\n\tif (SkipWhitespace(&data))\n\t{\n\t\tdelete value;\n\t\treturn NULL;\n\t}\n\t\n\t// We're now at the end of the string\n\treturn value;\n}\n\n/**\n * Turns the passed in JSONValue into a JSON encode string\n *\n * @access public\n *\n * @param JSONValue* value The root value\n *\n * @return std::wstring Returns a JSON encoded string representation of the given value\n */\nstd::wstring JSON::Stringify(const JSONValue *value)\n{\n\tif (value != NULL)\n\t\treturn value->Stringify();\n\telse\n\t\treturn L\"\";\n}\n\n/**\n * Skips over any whitespace characters (space, tab, \\r or \\n) defined by the JSON spec\n *\n * @access protected\n *\n * @param wchar_t** data Pointer to a wchar_t* that contains the JSON text\n *\n * @return bool Returns true if there is more data, or false if the end of the text was reached\n */\nbool JSON::SkipWhitespace(const wchar_t **data)\n{\n\twhile (**data != 0 && (**data == L' ' || **data == L'\\t' || **data == L'\\r' || **data == L'\\n'))\n\t\t(*data)++;\n\t\n\treturn **data != 0;\n}\n\n/**\n * Extracts a JSON String as defined by the spec - \"<some chars>\"\n * Any escaped characters are swapped out for their unescaped values\n *\n * @access protected\n *\n * @param wchar_t** data Pointer to a wchar_t* that contains the JSON text\n * @param std::wstring& str Reference to a std::wstring to receive the extracted string\n *\n * @return bool Returns true on success, false on failure\n */\nbool JSON::ExtractString(const wchar_t **data, std::wstring &str)\n{\n\tstr = L\"\";\n\t\n\twhile (**data != 0)\n\t{\n\t\t// Save the char so we can change it if need be\n\t\twchar_t next_char = **data;\n\t\t\n\t\t// Escaping something?\n\t\tif (next_char == L'\\\\')\n\t\t{\n\t\t\t// Move over the escape char\n\t\t\t(*data)++;\n\t\t\t\n\t\t\t// Deal with the escaped char\n\t\t\tswitch (**data)\n\t\t\t{\n\t\t\t\tcase L'\"': next_char = L'\"'; break;\n\t\t\t\tcase L'\\\\': next_char = L'\\\\'; break;\n\t\t\t\tcase L'/': next_char = L'/'; break;\n\t\t\t\tcase L'b': next_char = L'\\b'; break;\n\t\t\t\tcase L'f': next_char = L'\\f'; break;\n\t\t\t\tcase L'n': next_char = L'\\n'; break;\n\t\t\t\tcase L'r': next_char = L'\\r'; break;\n\t\t\t\tcase L't': next_char = L'\\t'; break;\n\t\t\t\tcase L'u':\n\t\t\t\t{\n\t\t\t\t\t// We need 5 chars (4 hex + the 'u') or its not valid\n\t\t\t\t\tif (!simplejson_wcsnlen(*data, 5))\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t\n\t\t\t\t\t// Deal with the chars\n\t\t\t\t\tnext_char = 0;\n\t\t\t\t\tfor (int i = 0; i < 4; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Do it first to move off the 'u' and leave us on the\n\t\t\t\t\t\t// final hex digit as we move on by one later on\n\t\t\t\t\t\t(*data)++;\n\t\t\t\t\t\t\n\t\t\t\t\t\tnext_char <<= 4;\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Parse the hex digit\n\t\t\t\t\t\tif (**data >= '0' && **data <= '9')\n\t\t\t\t\t\t\tnext_char |= (**data - '0');\n\t\t\t\t\t\telse if (**data >= 'A' && **data <= 'F')\n\t\t\t\t\t\t\tnext_char |= (10 + (**data - 'A'));\n\t\t\t\t\t\telse if (**data >= 'a' && **data <= 'f')\n\t\t\t\t\t\t\tnext_char |= (10 + (**data - 'a'));\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Invalid hex digit = invalid JSON\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// By the spec, only the above cases are allowed\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// End of the string?\n\t\telse if (next_char == L'\"')\n\t\t{\n\t\t\t(*data)++;\n\t\t\tstr.reserve(); // Remove unused capacity\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\t// Disallowed char?\n\t\telse if (next_char < L' ' && next_char != L'\\t')\n\t\t{\n\t\t\t// SPEC Violation: Allow tabs due to real world cases\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\t// Add the next char\n\t\tstr += next_char;\n\t\t\n\t\t// Move on\n\t\t(*data)++;\n\t}\n\t\n\t// If we're here, the string ended incorrectly\n\treturn false;\n}\n\n/**\n * Parses some text as though it is an integer\n *\n * @access protected\n *\n * @param wchar_t** data Pointer to a wchar_t* that contains the JSON text\n *\n * @return double Returns the double value of the number found\n */\ndouble JSON::ParseInt(const wchar_t **data)\n{\n\tdouble integer = 0;\n\twhile (**data != 0 && **data >= '0' && **data <= '9')\n\t\tinteger = integer * 10 + (*(*data)++ - '0');\n\t\n\treturn integer;\n}\n\n/**\n * Parses some text as though it is a decimal\n *\n * @access protected\n *\n * @param wchar_t** data Pointer to a wchar_t* that contains the JSON text\n *\n * @return double Returns the double value of the decimal found\n */\ndouble JSON::ParseDecimal(const wchar_t **data)\n{\n\tdouble decimal = 0.0;\n  double factor = 0.1;\n\twhile (**data != 0 && **data >= '0' && **data <= '9')\n  {\n    int digit = (*(*data)++ - '0');\n\t\tdecimal = decimal + digit * factor;\n    factor *= 0.1;\n  }\n\treturn decimal;\n}\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/JSON.h",
    "content": "/*\n * File JSON.h part of the SimpleJSON Library - http://mjpa.in/json\n *\n * Copyright (C) 2010 Mike Anchor\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#ifndef _JSON_H_\n#define _JSON_H_\n\n// Win32 incompatibilities\n#if defined(WIN32) && !defined(__GNUC__)\n\t#define wcsncasecmp _wcsnicmp\n\tstatic inline bool isnan(double x) { return x != x; }\n\tstatic inline bool isinf(double x) { return !isnan(x) && isnan(x - x); }\n#endif\n\n#include <vector>\n#include <string>\n#include <map>\n\n// Linux compile fix - from quaker66\n#ifdef __GNUC__\n\t#include <cstring>\n\t#include <cstdlib>\n#endif\n\n// Mac compile fixes - from quaker66, Lion fix by dabrahams\n#if defined(__APPLE__) && __DARWIN_C_LEVEL < 200809L || (defined(WIN32) && defined(__GNUC__)) || defined(ANDROID)\n\t#include <wctype.h>\n\t#include <wchar.h>\n\t\n\tstatic inline int wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n)\n\t{\n\t\tint lc1  = 0;\n\t\tint lc2  = 0;\n\n\t\twhile (n--)\n\t\t{\n\t\t\tlc1 = towlower (*s1);\n\t\t\tlc2 = towlower (*s2);\n\n\t\t\tif (lc1 != lc2)\n\t\t\t\treturn (lc1 - lc2);\n\n\t\t\tif (!lc1)\n\t\t\t\treturn 0;\n\n\t\t\t++s1;\n\t\t\t++s2;\n\t\t}\n\n\t\treturn 0;\n\t}\n#endif\n\n// Simple function to check a string 's' has at least 'n' characters\nstatic inline bool simplejson_wcsnlen(const wchar_t *s, size_t n) {\n\tif (s == 0)\n\t\treturn false;\n\n\tconst wchar_t *save = s;\n\twhile (n-- > 0)\n\t{\n\t\tif (*(save++) == 0) return false;\n\t}\n\n\treturn true;\n}\n\n// Custom types\nclass JSONValue;\ntypedef std::vector<JSONValue*> JSONArray;\ntypedef std::map<std::wstring, JSONValue*> JSONObject;\n\n#include \"JSONValue.h\"\n\nclass JSON\n{\n\tfriend class JSONValue;\n\t\n\tpublic:\n\t\tstatic JSONValue* Parse(const char *data);\n\t\tstatic JSONValue* Parse(const wchar_t *data);\n\t\tstatic std::wstring Stringify(const JSONValue *value);\n\tprotected:\n\t\tstatic bool SkipWhitespace(const wchar_t **data);\n\t\tstatic bool ExtractString(const wchar_t **data, std::wstring &str);\n\t\tstatic double ParseInt(const wchar_t **data);\n\t\tstatic double ParseDecimal(const wchar_t **data);\n\tprivate:\n\t\tJSON();\n};\n\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/JSONValue.cpp",
    "content": "/*\n * File JSONValue.cpp part of the SimpleJSON Library - http://mjpa.in/json\n *\n * Copyright (C) 2010 Mike Anchor\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <vector>\n#include <string>\n#include <sstream>\n#include <iostream>\n#include <math.h>\n\n#include \"JSONValue.h\"\n\n// Macros to free an array/object\n#define FREE_ARRAY(x) { JSONArray::iterator iter; for (iter = x.begin(); iter != x.end(); iter++) { delete *iter; } }\n#define FREE_OBJECT(x) { JSONObject::iterator iter; for (iter = x.begin(); iter != x.end(); iter++) { delete (*iter).second; } }\n\n/**\n * Parses a JSON encoded value to a JSONValue object\n *\n * @access protected\n *\n * @param wchar_t** data Pointer to a wchar_t* that contains the data\n *\n * @return JSONValue* Returns a pointer to a JSONValue object on success, NULL on error\n */\nJSONValue *JSONValue::Parse(const wchar_t **data)\n{\n\t// Is it a string?\n\tif (**data == '\"')\n\t{\n\t\tstd::wstring str;\n\t\tif (!JSON::ExtractString(&(++(*data)), str))\n\t\t\treturn NULL;\n\t\telse\n\t\t\treturn new JSONValue(str);\n\t}\n\t\n\t// Is it a boolean?\n\telse if ((simplejson_wcsnlen(*data, 4) && wcsncasecmp(*data, L\"true\", 4) == 0) || (simplejson_wcsnlen(*data, 5) && wcsncasecmp(*data, L\"false\", 5) == 0))\n\t{\n\t\tbool value = wcsncasecmp(*data, L\"true\", 4) == 0;\n\t\t(*data) += value ? 4 : 5;\n\t\treturn new JSONValue(value);\n\t}\n\t\n\t// Is it a null?\n\telse if (simplejson_wcsnlen(*data, 4) && wcsncasecmp(*data, L\"null\", 4) == 0)\n\t{\n\t\t(*data) += 4;\n\t\treturn new JSONValue();\n\t}\n\t\n\t// Is it a number?\n\telse if (**data == L'-' || (**data >= L'0' && **data <= L'9'))\n\t{\n\t\t// Negative?\n\t\tbool neg = **data == L'-';\n\t\tif (neg) (*data)++;\n\n\t\tdouble number = 0.0;\n\n\t\t// Parse the whole part of the number - only if it wasn't 0\n\t\tif (**data == L'0')\n\t\t\t(*data)++;\n\t\telse if (**data >= L'1' && **data <= L'9')\n\t\t\tnumber = JSON::ParseInt(data);\n\t\telse\n\t\t\treturn NULL;\n\t\t\n\t\t// Could be a decimal now...\n\t\tif (**data == '.')\n\t\t{\n\t\t\t(*data)++;\n\n\t\t\t// Not get any digits?\n\t\t\tif (!(**data >= L'0' && **data <= L'9'))\n\t\t\t\treturn NULL;\n\t\t\t\n\t\t\t// Find the decimal and sort the decimal place out\n\t\t\t// Use ParseDecimal as ParseInt won't work with decimals less than 0.1\n\t\t\t// thanks to Javier Abadia for the report & fix\n\t\t\tdouble decimal = JSON::ParseDecimal(data);\n\t\t\t\n\t\t\t// Save the number\n\t\t\tnumber += decimal;\n\t\t}\n\n\t\t// Could be an exponent now...\n\t\tif (**data == L'E' || **data == L'e')\n\t\t{\n\t\t\t(*data)++;\n\n\t\t\t// Check signage of expo\n\t\t\tbool neg_expo = false;\n\t\t\tif (**data == L'-' || **data == L'+')\n\t\t\t{\n\t\t\t\tneg_expo = **data == L'-';\n\t\t\t\t(*data)++;\n\t\t\t}\n\t\t\t\n\t\t\t// Not get any digits?\n\t\t\tif (!(**data >= L'0' && **data <= L'9'))\n\t\t\t\treturn NULL;\n\n\t\t\t// Sort the expo out\n\t\t\tdouble expo = JSON::ParseInt(data);\n\t\t\tfor (double i = 0.0; i < expo; i++)\n\t\t\t\tnumber = neg_expo ? (number / 10.0) : (number * 10.0);\n\t\t}\n\n\t\t// Was it neg?\n\t\tif (neg) number *= -1;\n\n\t\treturn new JSONValue(number);\n\t}\n\n\t// An object?\n\telse if (**data == L'{')\n\t{\n\t\tJSONObject object;\n\t\t\n\t\t(*data)++;\n\t\n\t\twhile (**data != 0)\n\t\t{\n\t\t\t// Whitespace at the start?\n\t\t\tif (!JSON::SkipWhitespace(data))\n\t\t\t{\n\t\t\t\tFREE_OBJECT(object);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\t\n\t\t\t// Special case - empty object\n\t\t\tif (object.size() == 0 && **data == L'}')\n\t\t\t{\n\t\t\t\t(*data)++;\n\t\t\t\treturn new JSONValue(object);\n\t\t\t}\n\t\t\t\n\t\t\t// We want a string now...\n\t\t\tstd::wstring name;\n\t\t\tif (!JSON::ExtractString(&(++(*data)), name))\n\t\t\t{\n\t\t\t\tFREE_OBJECT(object);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\t\n\t\t\t// More whitespace?\n\t\t\tif (!JSON::SkipWhitespace(data))\n\t\t\t{\n\t\t\t\tFREE_OBJECT(object);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\t\n\t\t\t// Need a : now\n\t\t\tif (*((*data)++) != L':')\n\t\t\t{\n\t\t\t\tFREE_OBJECT(object);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\t\n\t\t\t// More whitespace?\n\t\t\tif (!JSON::SkipWhitespace(data))\n\t\t\t{\n\t\t\t\tFREE_OBJECT(object);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\t\n\t\t\t// The value is here\t\t\t\n\t\t\tJSONValue *value = Parse(data);\n\t\t\tif (value == NULL)\n\t\t\t{\n\t\t\t\tFREE_OBJECT(object);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\t\n\t\t\t// Add the name:value\n\t\t\tif (object.find(name) != object.end())\n\t\t\t\tdelete object[name];\n\t\t\tobject[name] = value;\n\t\t\t\n\t\t\t// More whitespace?\n\t\t\tif (!JSON::SkipWhitespace(data))\n\t\t\t{\n\t\t\t\tFREE_OBJECT(object);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\t\n\t\t\t// End of object?\n\t\t\tif (**data == L'}')\n\t\t\t{\n\t\t\t\t(*data)++;\n\t\t\t\treturn new JSONValue(object);\n\t\t\t}\n\t\t\t\n\t\t\t// Want a , now\n\t\t\tif (**data != L',')\n\t\t\t{\n\t\t\t\tFREE_OBJECT(object);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\t\n\t\t\t(*data)++;\n\t\t}\n\t\t\n\t\t// Only here if we ran out of data\n\t\tFREE_OBJECT(object);\n\t\treturn NULL;\n\t}\n\t\n\t// An array?\n\telse if (**data == L'[')\n\t{\n\t\tJSONArray array;\n\t\t\n\t\t(*data)++;\n\t\t\n\t\twhile (**data != 0)\n\t\t{\n\t\t\t// Whitespace at the start?\n\t\t\tif (!JSON::SkipWhitespace(data))\n\t\t\t{\n\t\t\t\tFREE_ARRAY(array);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\t\n\t\t\t// Special case - empty array\n\t\t\tif (array.size() == 0 && **data == L']')\n\t\t\t{\n\t\t\t\t(*data)++;\n\t\t\t\treturn new JSONValue(array);\n\t\t\t}\n\t\t\t\n\t\t\t// Get the value\n\t\t\tJSONValue *value = Parse(data);\n\t\t\tif (value == NULL)\n\t\t\t{\n\t\t\t\tFREE_ARRAY(array);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\t\n\t\t\t// Add the value\n\t\t\tarray.push_back(value);\n\t\t\t\n\t\t\t// More whitespace?\n\t\t\tif (!JSON::SkipWhitespace(data))\n\t\t\t{\n\t\t\t\tFREE_ARRAY(array);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\t\n\t\t\t// End of array?\n\t\t\tif (**data == L']')\n\t\t\t{\n\t\t\t\t(*data)++;\n\t\t\t\treturn new JSONValue(array);\n\t\t\t}\n\t\t\t\n\t\t\t// Want a , now\n\t\t\tif (**data != L',')\n\t\t\t{\n\t\t\t\tFREE_ARRAY(array);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\t\n\t\t\t(*data)++;\n\t\t}\n\t\t\n\t\t// Only here if we ran out of data\n\t\tFREE_ARRAY(array);\n\t\treturn NULL;\n\t}\n\t\n\t// Ran out of possibilites, it's bad!\n\telse\n\t{\n\t\treturn NULL;\n\t}\n}\n\n/**\n * Basic constructor for creating a JSON Value of type NULL\n *\n * @access public\n */\nJSONValue::JSONValue(/*NULL*/)\n{\n\ttype = JSONType_Null;\n}\n\n/**\n * Basic constructor for creating a JSON Value of type String\n *\n * @access public\n *\n * @param wchar_t* m_char_value The string to use as the value\n */\nJSONValue::JSONValue(const wchar_t *m_char_value)\n{\n\ttype = JSONType_String;\n\tstring_value = std::wstring(m_char_value);\n}\n\n/**\n * Basic constructor for creating a JSON Value of type String\n *\n * @access public\n *\n * @param std::wstring m_string_value The string to use as the value\n */\nJSONValue::JSONValue(const std::wstring &m_string_value)\n{\n\ttype = JSONType_String;\n\tstring_value = m_string_value;\n}\n\n/**\n * Basic constructor for creating a JSON Value of type Bool\n *\n * @access public\n *\n * @param bool m_bool_value The bool to use as the value\n */\nJSONValue::JSONValue(bool m_bool_value)\n{\n\ttype = JSONType_Bool;\n\tbool_value = m_bool_value;\n}\n\n/**\n * Basic constructor for creating a JSON Value of type Number\n *\n * @access public\n *\n * @param double m_number_value The number to use as the value\n */\nJSONValue::JSONValue(double m_number_value)\n{\n\ttype = JSONType_Number;\n\tnumber_value = m_number_value;\n}\n\n/**\n * Basic constructor for creating a JSON Value of type Array\n *\n * @access public\n *\n * @param JSONArray m_array_value The JSONArray to use as the value\n */\nJSONValue::JSONValue(const JSONArray &m_array_value)\n{\n\ttype = JSONType_Array;\n\tarray_value = m_array_value;\n}\n\n/**\n * Basic constructor for creating a JSON Value of type Object\n *\n * @access public\n *\n * @param JSONObject m_object_value The JSONObject to use as the value\n */\nJSONValue::JSONValue(const JSONObject &m_object_value)\n{\n\ttype = JSONType_Object;\n\tobject_value = m_object_value;\n}\n\n/**\n * The destructor for the JSON Value object\n * Handles deleting the objects in the array or the object value\n *\n * @access public\n */\nJSONValue::~JSONValue()\n{\n\tif (type == JSONType_Array)\n\t{\n\t\tJSONArray::iterator iter;\n\t\tfor (iter = array_value.begin(); iter != array_value.end(); iter++)\n\t\t\tdelete *iter;\n\t}\n\telse if (type == JSONType_Object)\n\t{\n\t\tJSONObject::iterator iter;\n\t\tfor (iter = object_value.begin(); iter != object_value.end(); iter++)\n\t\t{\n\t\t\tdelete (*iter).second;\n\t\t}\n\t}\n}\n\n/**\n * Checks if the value is a NULL\n *\n * @access public\n *\n * @return bool Returns true if it is a NULL value, false otherwise\n */\nbool JSONValue::IsNull() const\n{\n\treturn type == JSONType_Null;\n}\n\n/**\n * Checks if the value is a String\n *\n * @access public\n *\n * @return bool Returns true if it is a String value, false otherwise\n */\nbool JSONValue::IsString() const\n{\n\treturn type == JSONType_String;\n}\n\n/**\n * Checks if the value is a Bool\n *\n * @access public\n *\n * @return bool Returns true if it is a Bool value, false otherwise\n */\nbool JSONValue::IsBool() const\n{\n\treturn type == JSONType_Bool;\n}\n\n/**\n * Checks if the value is a Number\n *\n * @access public\n *\n * @return bool Returns true if it is a Number value, false otherwise\n */\nbool JSONValue::IsNumber() const\n{\n\treturn type == JSONType_Number;\n}\n\n/**\n * Checks if the value is an Array\n *\n * @access public\n *\n * @return bool Returns true if it is an Array value, false otherwise\n */\nbool JSONValue::IsArray() const\n{\n\treturn type == JSONType_Array;\n}\n\n/**\n * Checks if the value is an Object\n *\n * @access public\n *\n * @return bool Returns true if it is an Object value, false otherwise\n */\nbool JSONValue::IsObject() const\n{\n\treturn type == JSONType_Object;\n}\n\n/**\n * Retrieves the String value of this JSONValue\n * Use IsString() before using this method.\n *\n * @access public\n *\n * @return std::wstring Returns the string value\n */\nconst std::wstring &JSONValue::AsString() const\n{\n\treturn string_value;\n}\n\n/**\n * Retrieves the Bool value of this JSONValue\n * Use IsBool() before using this method.\n *\n * @access public\n *\n * @return bool Returns the bool value\n */\nbool JSONValue::AsBool() const\n{\n\treturn bool_value;\n}\n\n/**\n * Retrieves the Number value of this JSONValue\n * Use IsNumber() before using this method.\n *\n * @access public\n *\n * @return double Returns the number value\n */\ndouble JSONValue::AsNumber() const\n{\n\treturn number_value;\n}\n\n/**\n * Retrieves the Array value of this JSONValue\n * Use IsArray() before using this method.\n *\n * @access public\n *\n * @return JSONArray Returns the array value\n */\nconst JSONArray &JSONValue::AsArray() const\n{\n\treturn array_value;\n}\n\n/**\n * Retrieves the Object value of this JSONValue\n * Use IsObject() before using this method.\n *\n * @access public\n *\n * @return JSONObject Returns the object value\n */\nconst JSONObject &JSONValue::AsObject() const\n{\n\treturn object_value;\n}\n\n/**\n * Retrieves the number of children of this JSONValue.\n * This number will be 0 or the actual number of children\n * if IsArray() or IsObject().\n *\n * @access public\n *\n * @return The number of children.\n */\nstd::size_t JSONValue::CountChildren() const\n{\n\tswitch (type)\n\t{\n\t\tcase JSONType_Array:\n\t\t\treturn array_value.size();\n\t\tcase JSONType_Object:\n\t\t\treturn object_value.size();\n\t\tdefault:\n\t\t\treturn 0;\n\t}\n}\n\n/**\n * Checks if this JSONValue has a child at the given index.\n * Use IsArray() before using this method.\n *\n * @access public\n *\n * @return bool Returns true if the array has a value at the given index.\n */\nbool JSONValue::HasChild(std::size_t index) const\n{\n\tif (type == JSONType_Array)\n\t{\n\t\treturn index < array_value.size();\n\t}\n\telse\n\t{\n\t\treturn false;\n\t}\n}\n\n/**\n * Retrieves the child of this JSONValue at the given index.\n * Use IsArray() before using this method.\n *\n * @access public\n *\n * @return JSONValue* Returns JSONValue at the given index or NULL\n *                    if it doesn't exist.\n */\nJSONValue *JSONValue::Child(std::size_t index)\n{\n\tif (index < array_value.size())\n\t{\n\t\treturn array_value[index];\n\t}\n\telse\n\t{\n\t\treturn NULL;\n\t}\n}\n\n/**\n * Checks if this JSONValue has a child at the given key.\n * Use IsObject() before using this method.\n *\n * @access public\n *\n * @return bool Returns true if the object has a value at the given key.\n */\nbool JSONValue::HasChild(const wchar_t* name) const\n{\n\tif (type == JSONType_Object)\n\t{\n\t\treturn object_value.find(name) != object_value.end();\n\t}\n\telse\n\t{\n\t\treturn false;\n\t}\n}\n\n/**\n * Retrieves the child of this JSONValue at the given key.\n * Use IsObject() before using this method.\n *\n * @access public\n *\n * @return JSONValue* Returns JSONValue for the given key in the object\n *                    or NULL if it doesn't exist.\n */\nJSONValue* JSONValue::Child(const wchar_t* name)\n{\n\tJSONObject::const_iterator it = object_value.find(name);\n\tif (it != object_value.end())\n\t{\n\t\treturn it->second;\n\t}\n\telse\n\t{\n\t\treturn NULL;\n\t}\n}\n\n/**\n * Creates a JSON encoded string for the value with all necessary characters escaped\n *\n * @access public\n *\n * @return std::wstring Returns the JSON string\n */\nstd::wstring JSONValue::Stringify() const\n{\n\tstd::wstring ret_string;\n\t\n\tswitch (type)\n\t{\n\t\tcase JSONType_Null:\n\t\t\tret_string = L\"null\";\n\t\t\tbreak;\n\t\t\n\t\tcase JSONType_String:\n\t\t\tret_string = StringifyString(string_value);\n\t\t\tbreak;\n\t\t\n\t\tcase JSONType_Bool:\n\t\t\tret_string = bool_value ? L\"true\" : L\"false\";\n\t\t\tbreak;\n\t\t\n\t\tcase JSONType_Number:\n\t\t{\n\t\t\tif (isinf(number_value) || isnan(number_value))\n\t\t\t\tret_string = L\"null\";\n\t\t\telse\n\t\t\t{\n\t\t\t\tstd::wstringstream ss;\n\t\t\t\tss.precision(15);\n\t\t\t\tss << number_value;\n\t\t\t\tret_string = ss.str();\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase JSONType_Array:\n\t\t{\n\t\t\tret_string = L\"[\";\n\t\t\tJSONArray::const_iterator iter = array_value.begin();\n\t\t\twhile (iter != array_value.end())\n\t\t\t{\n\t\t\t\tret_string += (*iter)->Stringify();\n\t\t\t\t\n\t\t\t\t// Not at the end - add a separator\n\t\t\t\tif (++iter != array_value.end())\n\t\t\t\t\tret_string += L\",\";\n\t\t\t}\n\t\t\tret_string += L\"]\";\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase JSONType_Object:\n\t\t{\n\t\t\tret_string = L\"{\";\n\t\t\tJSONObject::const_iterator iter = object_value.begin();\n\t\t\twhile (iter != object_value.end())\n\t\t\t{\n\t\t\t\tret_string += StringifyString((*iter).first);\n\t\t\t\tret_string += L\":\";\n\t\t\t\tret_string += (*iter).second->Stringify();\n\t\t\t\t\n\t\t\t\t// Not at the end - add a separator\n\t\t\t\tif (++iter != object_value.end())\n\t\t\t\t\tret_string += L\",\";\n\t\t\t}\n\t\t\tret_string += L\"}\";\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn ret_string;\n}\n\n/**\n * Creates a JSON encoded string with all required fields escaped\n * Works from http://www.ecma-internationl.org/publications/files/ECMA-ST/ECMA-262.pdf\n * Section 15.12.3.\n *\n * @access private\n *\n * @param std::wstring str The string that needs to have the characters escaped\n *\n * @return std::wstring Returns the JSON string\n */\nstd::wstring JSONValue::StringifyString(const std::wstring &str)\n{\n\tstd::wstring str_out = L\"\\\"\";\n\t\n\tstd::wstring::const_iterator iter = str.begin();\n\twhile (iter != str.end())\n\t{\n\t\twchar_t chr = *iter;\n\n\t\tif (chr == L'\"' || chr == L'\\\\' || chr == L'/')\n\t\t{\n\t\t\tstr_out += L'\\\\';\n\t\t\tstr_out += chr;\n\t\t}\n\t\telse if (chr == L'\\b')\n\t\t{\n\t\t\tstr_out += L\"\\\\b\";\n\t\t}\n\t\telse if (chr == L'\\f')\n\t\t{\n\t\t\tstr_out += L\"\\\\f\";\n\t\t}\n\t\telse if (chr == L'\\n')\n\t\t{\n\t\t\tstr_out += L\"\\\\n\";\n\t\t}\n\t\telse if (chr == L'\\r')\n\t\t{\n\t\t\tstr_out += L\"\\\\r\";\n\t\t}\n\t\telse if (chr == L'\\t')\n\t\t{\n\t\t\tstr_out += L\"\\\\t\";\n\t\t}\n\t\telse if (chr < L' ' || chr > 126)\n\t\t{\n\t\t\tstr_out += L\"\\\\u\";\n\t\t\tfor (int i = 0; i < 4; i++)\n\t\t\t{\n\t\t\t\tint value = (chr >> 12) & 0xf;\n\t\t\t\tif (value >= 0 && value <= 9)\n\t\t\t\t\tstr_out += (wchar_t)('0' + value);\n\t\t\t\telse if (value >= 10 && value <= 15)\n\t\t\t\t\tstr_out += (wchar_t)('A' + (value - 10));\n\t\t\t\tchr <<= 4;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstr_out += chr;\n\t\t}\n\t\t\n\t\titer++;\n\t}\n\t\n\tstr_out += L\"\\\"\";\n\treturn str_out;\n}\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/JSONValue.h",
    "content": "/*\n * File JSONValue.h part of the SimpleJSON Library - http://mjpa.in/json\n *\n * Copyright (C) 2010 Mike Anchor\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#ifndef _JSONVALUE_H_\n#define _JSONVALUE_H_\n\n#include <vector>\n#include <string>\n\n#include \"JSON.h\"\n\nclass JSON;\n\nenum JSONType { JSONType_Null, JSONType_String, JSONType_Bool, JSONType_Number, JSONType_Array, JSONType_Object };\n\nclass JSONValue\n{\n\tfriend class JSON;\n\t\n\tpublic:\n\t\tJSONValue(/*NULL*/);\n\t\tJSONValue(const wchar_t *m_char_value);\n\t\tJSONValue(const std::wstring &m_string_value);\n\t\tJSONValue(bool m_bool_value);\n\t\tJSONValue(double m_number_value);\n\t\tJSONValue(const JSONArray &m_array_value);\n\t\tJSONValue(const JSONObject &m_object_value);\n\t\t~JSONValue();\n\n\t\tbool IsNull() const;\n\t\tbool IsString() const;\n\t\tbool IsBool() const;\n\t\tbool IsNumber() const;\n\t\tbool IsArray() const;\n\t\tbool IsObject() const;\n\t\t\n\t\tconst std::wstring &AsString() const;\n\t\tbool AsBool() const;\n\t\tdouble AsNumber() const;\n\t\tconst JSONArray &AsArray() const;\n\t\tconst JSONObject &AsObject() const;\n\n\t\tstd::size_t CountChildren() const;\n\t\tbool HasChild(std::size_t index) const;\n\t\tJSONValue *Child(std::size_t index);\n\t\tbool HasChild(const wchar_t* name) const;\n\t\tJSONValue *Child(const wchar_t* name);\n\n\t\tstd::wstring Stringify() const;\n\n\tprotected:\n\t\tstatic JSONValue *Parse(const wchar_t **data);\n\n\tprivate:\n\t\tstatic std::wstring StringifyString(const std::wstring &str);\n\t\n\t\tJSONType type;\n\t\tstd::wstring string_value;\n\t\tbool bool_value;\n\t\tdouble number_value;\n\t\tJSONArray array_value;\n\t\tJSONObject object_value;\n};\n\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/Resources/Hyperlink2Theme.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Theme xmlns=\"http://wixtoolset.org/schemas/thmutil/2010\">\n  <Window Width=\"600\" Height=\"450\" HexStyle=\"100a0000\" FontId=\"0\">#(loc.Caption)</Window>\n  <Font Id=\"0\" Height=\"-12\" Weight=\"500\" Foreground=\"000000\" Background=\"FFFFFF\">Segoe UI</Font>\n  <Font Id=\"1\" Height=\"-24\" Weight=\"500\" Foreground=\"000000\">Segoe UI</Font>\n  <Font Id=\"2\" Height=\"-22\" Weight=\"500\" Foreground=\"666666\">Segoe UI</Font>\n  <Font Id=\"3\" Height=\"-12\" Weight=\"500\" Foreground=\"000000\" Background=\"FFFFFF\">Segoe UI</Font>\n  <Font Id=\"4\" Height=\"-12\" Weight=\"500\" Foreground=\"ff0000\" Background=\"FFFFFF\" Underline=\"yes\">Segoe UI</Font>\n\n  <Page Name=\"Help\">\n    <Text X=\"80\" Y=\"11\" Width=\"-11\" Height=\"32\" FontId=\"1\" DisablePrefix=\"yes\">#(loc.Title)</Text>\n    <Image X=\"11\" Y=\"11\" Width=\"64\" Height=\"64\" ImageFile=\"Logo.png\"/>\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"32\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.HelpHeader)</Text>\n    <Text X=\"11\" Y=\"121\" Width=\"-11\" Height=\"-35\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.HelpText)</Text>\n    <Button Name=\"HelpCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.HelpCloseButton)</Button>\n  </Page>\n  <Page Name=\"Install\">\n    <Text X=\"185\" Y=\"11\" Width=\"-11\" Height=\"32\" FontId=\"1\" DisablePrefix=\"yes\">#(loc.Title)</Text>\n    <Image X=\"11\" Y=\"11\" Width=\"165\" Height=\"400\" ImageFile=\"LogoSide.png\"/>\n    <Text X=\"185\" Y=\"50\" Width=\"-11\" Height=\"32\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.InstallHeader)</Text>\n    <Text X=\"185\" Y=\"91\" Width=\"-11\" Height=\"64\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.InstallMessage)</Text><!-- HexStyle=\"0x800000\" -->\n    <Hypertext Name=\"EulaHyperlink\" X=\"185\" Y=\"-111\" Width=\"-11\" Height=\"17\" TabStop=\"yes\" FontId=\"3\" HideWhenDisabled=\"yes\">#(loc.InstallLicenseLinkText)</Hypertext>\n    <Text X=\"185\" Y=\"-81\" Width=\"-11\" Height=\"17\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.InstallVersion)</Text>\n    <Hypertext Name=\"UpgradeHyperlink\" X=\"185\" Y=\"-81\" Width=\"-11\" Height=\"17\" TabStop=\"yes\" FontId=\"3\" HideWhenDisabled=\"yes\">#(loc.InstallUpgradeLinkText)</Hypertext>\n    <Checkbox Name=\"EulaAcceptCheckbox\" X=\"185\" Y=\"-51\" Width=\"-11\" Height=\"17\" TabStop=\"yes\" FontId=\"3\" HideWhenDisabled=\"yes\">#(loc.InstallAcceptCheckbox)</Checkbox>\n    <Button Name=\"OptionsButton\" X=\"-171\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.InstallOptionsButton)</Button>\n    <Button Name=\"InstallButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.InstallInstallButton)</Button>\n    <Button Name=\"WelcomeCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.InstallCloseButton)</Button>\n  </Page>\n  <Page Name=\"Options\">\n    <Text X=\"80\" Y=\"11\" Width=\"-11\" Height=\"32\" FontId=\"1\" DisablePrefix=\"yes\">#(loc.Title)</Text>\n    <Image X=\"11\" Y=\"11\" Width=\"64\" Height=\"64\" ImageFile=\"Logo.png\"/>\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.OptionsHeader)</Text>\n    <Text X=\"11\" Y=\"121\" Width=\"-11\" Height=\"17\" FontId=\"3\">#(loc.OptionsLocationLabel)</Text>\n    <Editbox Name=\"FolderEditbox\" X=\"11\" Y=\"143\" Width=\"-91\" Height=\"21\" TabStop=\"yes\" FontId=\"3\" FileSystemAutoComplete=\"yes\" />\n    <Button Name=\"BrowseButton\" X=\"-11\" Y=\"142\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"3\">#(loc.OptionsBrowseButton)</Button>\n\n    <Button Name=\"OptionsOkButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.OptionsOkButton)</Button>\n    <Button Name=\"OptionsCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.OptionsCancelButton)</Button>\n  </Page>\n  <Page Name=\"Progress\">\n    <Text X=\"80\" Y=\"11\" Width=\"-11\" Height=\"32\" FontId=\"1\" DisablePrefix=\"yes\">#(loc.Title)</Text>\n    <Image X=\"11\" Y=\"11\" Width=\"64\" Height=\"64\" ImageFile=\"Logo.png\"/>\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">[varProgressHeader]</Text>\n    <Text X=\"11\" Y=\"141\" Width=\"70\" Height=\"17\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.ProgressLabel)</Text>\n    <Text Name=\"OverallProgressPackageText\" X=\"85\" Y=\"141\" Width=\"-11\" Height=\"17\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.OverallProgressPackageText)</Text>\n    <Progressbar Name=\"OverallCalculatedProgressbar\" X=\"11\" Y=\"163\" Width=\"-11\" Height=\"20\" />\n    <Button Name=\"ProgressCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.ProgressCancelButton)</Button>\n  </Page>\n  <Page Name=\"Modify\">\n    <Text X=\"185\" Y=\"11\" Width=\"-11\" Height=\"32\" FontId=\"1\" DisablePrefix=\"yes\">#(loc.Title)</Text>\n    <Image X=\"11\" Y=\"11\" Width=\"165\" Height=\"400\" ImageFile=\"LogoSide.png\"/>\n    <Text X=\"185\" Y=\"50\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.ModifyHeader)</Text>\n    <Button Name=\"RepairButton\" X=\"-171\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.ModifyRepairButton)</Button>\n    <Button Name=\"UninstallButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.ModifyUninstallButton)</Button>\n    <Button Name=\"ModifyCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.ModifyCloseButton)</Button>\n  </Page>\n  <Page Name=\"Success\">\n    <Text X=\"185\" Y=\"11\" Width=\"-11\" Height=\"32\" FontId=\"1\" DisablePrefix=\"yes\">#(loc.Title)</Text>\n    <Image X=\"11\" Y=\"11\" Width=\"165\" Height=\"400\" ImageFile=\"LogoSide.png\"/>\n    <Text X=\"185\" Y=\"50\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">[varSuccessHeader]</Text>\n    <Button Name=\"LaunchButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.SuccessLaunchButton)</Button>\n    <Text Name=\"SuccessRestartText\" X=\"185\" Y=\"-51\" Width=\"400\" Height=\"34\" FontId=\"3\" HideWhenDisabled=\"yes\" DisablePrefix=\"yes\">#(loc.SuccessRestartText)</Text>\n    <Button Name=\"SuccessRestartButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.SuccessRestartButton)</Button>\n    <Button Name=\"SuccessCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.SuccessCloseButton)</Button>\n  </Page>\n  <Page Name=\"Failure\">\n    <Text X=\"185\" Y=\"11\" Width=\"-11\" Height=\"32\" FontId=\"1\" DisablePrefix=\"yes\">#(loc.Title)</Text>\n    <Image X=\"11\" Y=\"11\" Width=\"165\" Height=\"400\" ImageFile=\"LogoSide.png\"/>\n    <Text X=\"185\" Y=\"50\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">[varFailureHeader]</Text>\n    <Hypertext Name=\"FailureLogFileLink\" X=\"185\" Y=\"121\" Width=\"-11\" Height=\"68\" FontId=\"3\" TabStop=\"yes\" HideWhenDisabled=\"yes\">#(loc.FailureHyperlinkLogText)</Hypertext>\n    <Hypertext Name=\"FailureMessageText\" X=\"185\" Y=\"-115\" Width=\"-11\" Height=\"80\" FontId=\"3\" TabStop=\"yes\" HideWhenDisabled=\"yes\" />\n    <Text Name=\"FailureRestartText\" X=\"185\" Y=\"-57\" Width=\"-11\" Height=\"80\" FontId=\"3\" HideWhenDisabled=\"yes\" DisablePrefix=\"yes\">#(loc.FailureRestartText)</Text>\n    <Button Name=\"FailureRestartButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.FailureRestartButton)</Button>\n    <Button Name=\"FailureCloseButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.FailureCloseButton)</Button>\n  </Page>\n</Theme>"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/Resources/HyperlinkTheme.wxl",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<WixLocalization Culture=\"en-us\" Language=\"1033\" xmlns=\"http://schemas.microsoft.com/wix/2006/localization\">\n  <String Id=\"Caption\">[WixBundleName] Setup</String>\n  <String Id=\"Title\">[WixBundleName]</String>\n  <String Id=\"InstallHeader\">Welcome</String>\n  <String Id=\"InstallMessage\">Setup will install [WixBundleName] on your computer. Click install to continue, options to set the install directory or Close to exit.</String>\n  <String Id=\"InstallVersion\">Version [WixBundleVersion]</String>\n  <String Id=\"InstallUpgradeLinkText\">Version [WixBundleVersion] &lt;a href=\"#\"&gt;upgrade available&lt;/a&gt;</String>\n  <String Id=\"ConfirmCancelMessage\">Are you sure you want to cancel?</String>\n  <String Id=\"HelpHeader\">Setup Help</String>\n  <String Id=\"HelpText\">/install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or\n   creates a complete local copy of the bundle in directory. Install is the default.\n\n/passive | /quiet -  displays minimal UI with no prompts or displays no UI and\n   no prompts. By default UI and all prompts are displayed.\n\n/norestart   - suppress any attempts to restart. By default UI will prompt before restart.\n/log log.txt - logs to a specific file. By default a log file is created in %TEMP%.</String>\n  <String Id=\"HelpCloseButton\">&amp;Close</String>\n  <String Id=\"InstallLicenseLinkText\">[WixBundleName] &lt;a href=\"#\"&gt;license terms&lt;/a&gt;.</String>\n  <String Id=\"InstallAcceptCheckbox\">I &amp;agree to the license terms and conditions</String>\n  <String Id=\"InstallOptionsButton\">&amp;Options</String>\n  <String Id=\"InstallInstallButton\">&amp;Install</String>\n  <String Id=\"InstallCloseButton\">&amp;Close</String>\n  <String Id=\"OptionsHeader\">Setup Options</String>\n  <String Id=\"OptionsLocationLabel\">Install location:</String>\n  <String Id=\"OptionsBrowseButton\">&amp;Browse</String>\n  <String Id=\"OptionsOkButton\">&amp;OK</String>\n  <String Id=\"OptionsCancelButton\">&amp;Cancel</String>\n  <String Id=\"ProgressHeader\">Setup Progress</String>\n  <String Id=\"ProgressHeaderRepair\">Repair Progress</String>\n  <String Id=\"ProgressHeaderUninstall\">Uninstall Progress</String>\n  <String Id=\"ProgressLabel\">Processing:</String>\n  <String Id=\"OverallProgressPackageText\">Initializing...</String>\n  <String Id=\"ProgressCancelButton\">&amp;Cancel</String>\n  <String Id=\"ModifyHeader\">Modify Setup</String>\n  <String Id=\"ModifyRepairButton\">&amp;Repair</String>\n  <String Id=\"ModifyUninstallButton\">&amp;Uninstall</String>\n  <String Id=\"ModifyCloseButton\">&amp;Close</String>\n  <String Id=\"SuccessHeader\">Setup Successful</String>\n  <String Id=\"SuccessHeaderRepair\">Repair Successful</String>\n  <String Id=\"SuccessHeaderUninstall\">Uninstall Successful</String>\n  <String Id=\"SuccessLaunchButton\">&amp;Launch</String>\n  <String Id=\"SuccessRestartText\">You must restart your computer before you can use the software.</String>\n  <String Id=\"SuccessRestartButton\">&amp;Restart</String>\n  <String Id=\"SuccessCloseButton\">&amp;Close</String>\n  <String Id=\"FailureHeader\">Setup Failed</String>\n  <String Id=\"FailureHeaderRepair\">Repair Failed</String>\n  <String Id=\"FailureHeaderUninstall\">Uninstall Failed</String>\n  <String Id=\"FailureHyperlinkLogText\">One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the &lt;a href=\"#\"&gt;log file&lt;/a&gt;.</String>\n  <String Id=\"FailureRestartText\">You must restart your computer to complete the rollback of the software.</String>\n  <String Id=\"FailureRestartButton\">&amp;Restart</String>\n  <String Id=\"FailureCloseButton\">&amp;Close</String>\n</WixLocalization>"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/Resources/HyperlinkTheme.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Theme xmlns=\"http://wixtoolset.org/schemas/thmutil/2010\">\n  <Window Width=\"500\" Height=\"390\" HexStyle=\"100a0000\" FontId=\"0\">#(loc.Caption)</Window>\n  <Font Id=\"0\" Height=\"-12\" Weight=\"500\" Foreground=\"000000\" Background=\"FFFFFF\">Segoe UI</Font>\n  <Font Id=\"1\" Height=\"-24\" Weight=\"500\" Foreground=\"000000\">Segoe UI</Font>\n  <Font Id=\"2\" Height=\"-22\" Weight=\"500\" Foreground=\"666666\">Segoe UI</Font>\n  <Font Id=\"3\" Height=\"-12\" Weight=\"500\" Foreground=\"000000\" Background=\"FFFFFF\">Segoe UI</Font>\n  <Font Id=\"4\" Height=\"-12\" Weight=\"500\" Foreground=\"ff0000\" Background=\"FFFFFF\" Underline=\"yes\">Segoe UI</Font>\n\n  <Image X=\"11\" Y=\"11\" Width=\"64\" Height=\"64\" ImageFile=\"Logo.png\" Visible=\"yes\"/>\n  <Text X=\"80\" Y=\"11\" Width=\"-11\" Height=\"64\" FontId=\"1\" Visible=\"yes\" DisablePrefix=\"yes\">#(loc.Title)</Text>\n\n  <Page Name=\"Help\">\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.HelpHeader)</Text>\n    <Text X=\"11\" Y=\"112\" Width=\"-11\" Height=\"-35\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.HelpText)</Text>\n    <Button Name=\"HelpCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.HelpCloseButton)</Button>\n  </Page>\n  <Page Name=\"Install\">\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.InstallHeader)</Text>\n    <Text X=\"11\" Y=\"121\" Width=\"-11\" Height=\"-129\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.InstallMessage)</Text>\n    <!-- HexStyle=\"0x800000\" -->\n    <Hypertext Name=\"EulaHyperlink\" X=\"11\" Y=\"-107\" Width=\"-11\" Height=\"17\" TabStop=\"yes\" FontId=\"3\" HideWhenDisabled=\"yes\">#(loc.InstallLicenseLinkText)</Hypertext>\n    <Text X=\"11\" Y=\"-73\" Width=\"246\" Height=\"17\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.InstallVersion)</Text>\n    <Hypertext Name=\"UpgradeHyperlink\" X=\"11\" Y=\"-73\" Width=\"-11\" Height=\"17\" TabStop=\"yes\" FontId=\"3\" HideWhenDisabled=\"yes\">#(loc.InstallUpgradeLinkText)</Hypertext>\n    <Checkbox Name=\"EulaAcceptCheckbox\" X=\"-11\" Y=\"-41\" Width=\"260\" Height=\"17\" TabStop=\"yes\" FontId=\"3\" HideWhenDisabled=\"yes\">#(loc.InstallAcceptCheckbox)</Checkbox>\n    <Button Name=\"OptionsButton\" X=\"-171\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.InstallOptionsButton)</Button>\n    <Button Name=\"InstallButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.InstallInstallButton)</Button>\n    <Button Name=\"WelcomeCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.InstallCloseButton)</Button>\n  </Page>\n  <Page Name=\"Options\">\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.OptionsHeader)</Text>\n    <Text X=\"11\" Y=\"121\" Width=\"-11\" Height=\"17\" FontId=\"3\">#(loc.OptionsLocationLabel)</Text>\n    <Editbox Name=\"FolderEditbox\" X=\"11\" Y=\"143\" Width=\"-91\" Height=\"21\" TabStop=\"yes\" FontId=\"3\" FileSystemAutoComplete=\"yes\" />\n    <Button Name=\"BrowseButton\" X=\"-11\" Y=\"142\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"3\">#(loc.OptionsBrowseButton)</Button>\n    <Button Name=\"OptionsOkButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.OptionsOkButton)</Button>\n    <Button Name=\"OptionsCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.OptionsCancelButton)</Button>\n  </Page>\n  <Page Name=\"Progress\">\n    <Text Name=\"ProgressHeader\" X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">[varProgressHeader]</Text>\n    <Text X=\"11\" Y=\"121\" Width=\"70\" Height=\"17\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.ProgressLabel)</Text>\n    <Text Name=\"OverallProgressPackageText\" X=\"85\" Y=\"121\" Width=\"-11\" Height=\"17\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.OverallProgressPackageText)</Text>\n    <Progressbar Name=\"OverallCalculatedProgressbar\" X=\"11\" Y=\"143\" Width=\"-11\" Height=\"15\" />\n    <Button Name=\"ProgressCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.ProgressCancelButton)</Button>\n  </Page>\n  <Page Name=\"Modify\">\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.ModifyHeader)</Text>\n    <Button Name=\"RepairButton\" X=\"-171\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.ModifyRepairButton)</Button>\n    <Button Name=\"UninstallButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.ModifyUninstallButton)</Button>\n    <Button Name=\"ModifyCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.ModifyCloseButton)</Button>\n  </Page>\n  <Page Name=\"Success\">\n    <Text Name=\"SuccessHeader\" X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">[varSuccessHeader]</Text>\n    <Button Name=\"LaunchButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.SuccessLaunchButton)</Button>\n    <Text Name=\"SuccessRestartText\" X=\"-11\" Y=\"-51\" Width=\"400\" Height=\"34\" FontId=\"3\" HideWhenDisabled=\"yes\" DisablePrefix=\"yes\">#(loc.SuccessRestartText)</Text>\n    <Button Name=\"SuccessRestartButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.SuccessRestartButton)</Button>\n    <Button Name=\"SuccessCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.SuccessCloseButton)</Button>\n  </Page>\n  <Page Name=\"Failure\">\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">[varFailureHeader]</Text>\n    <Hypertext Name=\"FailureLogFileLink\" X=\"11\" Y=\"121\" Width=\"-11\" Height=\"42\" FontId=\"3\" TabStop=\"yes\" HideWhenDisabled=\"yes\">#(loc.FailureHyperlinkLogText)</Hypertext>\n    <Hypertext Name=\"FailureMessageText\" X=\"22\" Y=\"163\" Width=\"-11\" Height=\"51\" FontId=\"3\" TabStop=\"yes\" HideWhenDisabled=\"yes\" />\n    <Text Name=\"FailureRestartText\" X=\"-11\" Y=\"-51\" Width=\"400\" Height=\"34\" FontId=\"3\" HideWhenDisabled=\"yes\" DisablePrefix=\"yes\">#(loc.FailureRestartText)</Text>\n    <Button Name=\"FailureRestartButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.FailureRestartButton)</Button>\n    <Button Name=\"FailureCloseButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.FailureCloseButton)</Button>\n  </Page>\n</Theme>"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/Resources/RtfTheme.wxl",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<WixLocalization Culture=\"en-us\" Language=\"1033\" xmlns=\"http://schemas.microsoft.com/wix/2006/localization\">\n  <String Id=\"Caption\">[WixBundleName] Setup</String>\n  <String Id=\"Title\">[WixBundleName]</String>\n  <String Id=\"ConfirmCancelMessage\">Are you sure you want to cancel?</String>\n  <String Id=\"HelpHeader\">Setup Help</String>\n  <String Id=\"HelpText\">/install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or\n   creates a complete local copy of the bundle in directory. Install is the default.\n\n/passive | /quiet -  displays minimal UI with no prompts or displays no UI and\n   no prompts. By default UI and all prompts are displayed.\n\n/norestart   - suppress any attempts to restart. By default UI will prompt before restart.\n/log log.txt - logs to a specific file. By default a log file is created in %TEMP%.</String>\n  <String Id=\"HelpCloseButton\">&amp;Close</String>\n  <String Id=\"InstallAcceptCheckbox\">I &amp;agree to the license terms and conditions</String>\n  <String Id=\"InstallOptionsButton\">&amp;Options</String>\n  <String Id=\"InstallInstallButton\">&amp;Install</String>\n  <String Id=\"InstallCloseButton\">&amp;Close</String>\n  <String Id=\"OptionsHeader\">Setup Options</String>\n  <String Id=\"OptionsLocationLabel\">Install location:</String>\n  <String Id=\"OptionsBrowseButton\">&amp;Browse</String>\n  <String Id=\"OptionsOkButton\">&amp;OK</String>\n  <String Id=\"OptionsCancelButton\">&amp;Cancel</String>\n  <String Id=\"ProgressHeader\">Setup Progress</String>\n  <String Id=\"ProgressLabel\">Processing:</String>\n  <String Id=\"OverallProgressPackageText\">Initializing...</String>\n  <String Id=\"ProgressCancelButton\">&amp;Cancel</String>\n  <String Id=\"ModifyHeader\">Modify Setup</String>\n  <String Id=\"ModifyRepairButton\">&amp;Repair</String>\n  <String Id=\"ModifyUninstallButton\">&amp;Uninstall</String>\n  <String Id=\"ModifyCloseButton\">&amp;Close</String>\n  <String Id=\"SuccessHeader\">Setup Successful</String>\n  <String Id=\"SuccessLaunchButton\">&amp;Launch</String>\n  <String Id=\"SuccessRestartText\">You must restart your computer before you can use the software.</String>\n  <String Id=\"SuccessRestartButton\">&amp;Restart</String>\n  <String Id=\"SuccessCloseButton\">&amp;Close</String>\n  <String Id=\"FailureHeader\">Setup Failed</String>\n  <String Id=\"FailureHyperlinkLogText\">One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the &lt;a href=\"#\"&gt;log file&lt;/a&gt;.</String>\n  <String Id=\"FailureRestartText\">You must restart your computer to complete the rollback of the software.</String>\n  <String Id=\"FailureRestartButton\">&amp;Restart</String>\n  <String Id=\"FailureCloseButton\">&amp;Close</String>\n</WixLocalization>\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/Resources/RtfTheme.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Theme xmlns=\"http://wixtoolset.org/schemas/thmutil/2010\">\n  <Window Width=\"500\" Height=\"390\" HexStyle=\"100a0000\" FontId=\"0\">#(loc.Caption)</Window>\n  <Font Id=\"0\" Height=\"-12\" Weight=\"500\" Foreground=\"000000\" Background=\"FFFFFF\">Segoe UI</Font>\n  <Font Id=\"1\" Height=\"-24\" Weight=\"500\" Foreground=\"000000\">Segoe UI</Font>\n  <Font Id=\"2\" Height=\"-22\" Weight=\"500\" Foreground=\"666666\">Segoe UI</Font>\n  <Font Id=\"3\" Height=\"-12\" Weight=\"500\" Foreground=\"000000\" Background=\"FFFFFF\">Segoe UI</Font>\n  <Font Id=\"4\" Height=\"-12\" Weight=\"500\" Foreground=\"ff0000\" Background=\"FFFFFF\" Underline=\"yes\">Segoe UI</Font>\n\n  <Image X=\"11\" Y=\"11\" Width=\"64\" Height=\"64\" ImageFile=\"Logo.png\" Visible=\"yes\"/>\n  <Text X=\"80\" Y=\"11\" Width=\"-11\" Height=\"64\" FontId=\"1\" Visible=\"yes\" DisablePrefix=\"yes\">#(loc.Title)</Text>\n\n  <Page Name=\"Help\">\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.HelpHeader)</Text>\n    <Text X=\"11\" Y=\"112\" Width=\"-11\" Height=\"-35\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.HelpText)</Text>\n    <Button Name=\"HelpCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.HelpCloseButton)</Button>\n  </Page>\n  <Page Name=\"Install\">\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"-70\" TabStop=\"no\" FontId=\"2\" HexStyle=\"0x800000\" DisablePrefix=\"yes\" />\n    <Richedit Name=\"EulaRichedit\" X=\"12\" Y=\"81\" Width=\"-12\" Height=\"-71\" TabStop=\"yes\" FontId=\"0\" />\n    <Checkbox Name=\"EulaAcceptCheckbox\" X=\"-11\" Y=\"-41\" Width=\"260\" Height=\"17\" TabStop=\"yes\" FontId=\"3\" HideWhenDisabled=\"yes\">#(loc.InstallAcceptCheckbox)</Checkbox>\n    <Button Name=\"OptionsButton\" X=\"-171\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.InstallOptionsButton)</Button>\n    <Button Name=\"InstallButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.InstallInstallButton)</Button>\n    <Button Name=\"WelcomeCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.InstallCloseButton)</Button>\n  </Page>\n  <Page Name=\"Options\">\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.OptionsHeader)</Text>\n    <Text X=\"11\" Y=\"121\" Width=\"-11\" Height=\"17\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.OptionsLocationLabel)</Text>\n    <Editbox Name=\"FolderEditbox\" X=\"11\" Y=\"143\" Width=\"-91\" Height=\"21\" TabStop=\"yes\" FontId=\"3\" FileSystemAutoComplete=\"yes\" />\n    <Button Name=\"BrowseButton\" X=\"-11\" Y=\"142\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"3\">#(loc.OptionsBrowseButton)</Button>\n    <Button Name=\"OptionsOkButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.OptionsOkButton)</Button>\n    <Button Name=\"OptionsCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.OptionsCancelButton)</Button>\n  </Page>\n  <Page Name=\"Progress\">\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">[varProgressHeader]</Text>\n    <Text X=\"11\" Y=\"121\" Width=\"70\" Height=\"17\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.ProgressLabel)</Text>\n    <Text Name=\"OverallProgressPackageText\" X=\"85\" Y=\"121\" Width=\"-11\" Height=\"17\" FontId=\"3\" DisablePrefix=\"yes\">#(loc.OverallProgressPackageText)</Text>\n    <Progressbar Name=\"OverallCalculatedProgressbar\" X=\"11\" Y=\"143\" Width=\"-11\" Height=\"15\" />\n    <Button Name=\"ProgressCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.ProgressCancelButton)</Button>\n  </Page>\n  <Page Name=\"Modify\">\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.ModifyHeader)</Text>\n    <Button Name=\"RepairButton\" X=\"-171\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.ModifyRepairButton)</Button>\n    <Button Name=\"UninstallButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.ModifyUninstallButton)</Button>\n    <Button Name=\"ModifyCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.ModifyCloseButton)</Button>\n  </Page>\n  <Page Name=\"Success\">\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">[varSuccessHeader]</Text>\n    <Button Name=\"LaunchButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.SuccessLaunchButton)</Button>\n    <Text Name=\"SuccessRestartText\" X=\"-11\" Y=\"-51\" Width=\"400\" Height=\"34\" FontId=\"3\" HideWhenDisabled=\"yes\" DisablePrefix=\"yes\">#(loc.SuccessRestartText)</Text>\n    <Button Name=\"SuccessRestartButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.SuccessRestartButton)</Button>\n    <Button Name=\"SuccessCancelButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.SuccessCloseButton)</Button>\n  </Page>\n  <Page Name=\"Failure\">\n    <Text X=\"11\" Y=\"80\" Width=\"-11\" Height=\"30\" FontId=\"2\" DisablePrefix=\"yes\">[varFailureHeader]</Text>\n    <Hypertext Name=\"FailureLogFileLink\" X=\"11\" Y=\"121\" Width=\"-11\" Height=\"42\" FontId=\"3\" TabStop=\"yes\" HideWhenDisabled=\"yes\">#(loc.FailureHyperlinkLogText)</Hypertext>\n    <Hypertext Name=\"FailureMessageText\" X=\"22\" Y=\"163\" Width=\"-11\" Height=\"51\" FontId=\"3\" TabStop=\"yes\" HideWhenDisabled=\"yes\" />\n    <Text Name=\"FailureRestartText\" X=\"-11\" Y=\"-51\" Width=\"400\" Height=\"34\" FontId=\"3\" HideWhenDisabled=\"yes\" DisablePrefix=\"yes\">#(loc.FailureRestartText)</Text>\n    <Button Name=\"FailureRestartButton\" X=\"-91\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.FailureRestartButton)</Button>\n    <Button Name=\"FailureCloseButton\" X=\"-11\" Y=\"-11\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.FailureCloseButton)</Button>\n  </Page>\n</Theme>"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/WixStandardBootstrapperApplication.cpp",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"WixStandardBootstrapperApplication.cpp\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//-------------------------------------------------------------------------------------------------\n\n\n#include \"precomp.h\"\n#include \"regutil.h\"\n#include \"JSON.h\"\n#include <windows.h>\n#include <string>\n#include <sstream>\n\n\nstatic const HRESULT E_WIXSTDBA_CONDITION_FAILED = MAKE_HRESULT(SEVERITY_ERROR, 500, 1);\n\nstatic const LPCWSTR WIXBUNDLE_VARIABLE_ELEVATED = L\"WixBundleElevated\";\n\nstatic const LPCWSTR WIXSTDBA_WINDOW_CLASS                = L\"WixExtBA\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_INSTALL_FOLDER     = L\"InstallFolder\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_INSTALL_REGPATH    = L\"InstallRegPath\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH = L\"LaunchTarget\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS   = L\"LaunchArguments\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_HIDDEN      = L\"LaunchHidden\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_LAUNCHAFTERINSTALL_TARGET_PATH = L\"LaunchAfterInstallTarget\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_LAUNCHAFTERINSTALL_ARGUMENTS   = L\"LaunchAfterInstallArguments\";\n\nstatic const LPCWSTR WIXSTDBA_VARIABLE_PROGRESS_HEADER = L\"varProgressHeader\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_PROGRESS_INFO   = L\"varProgressInfo\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_SUCCESS_HEADER  = L\"varSuccessHeader\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_SUCCESS_INFO    = L\"varSuccessInfo\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_FAILURE_HEADER  = L\"varFailureHeader\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_SUCCESS_ERRINF  = L\"varSuccessErrorInfoText\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_SUCCESS_ERRMSG  = L\"varSuccessErrorMessageText\";\n\nstatic const LPCWSTR WIXSTDBA_VARIABLE_PERMACHINE_INSTALL  = L\"PerMachineInstall\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_PERMACHINE_INSTALL_FOLDER  = L\"PerMachineInstallFolder\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_PERUSER_INSTALL_FOLDER     = L\"PerUserInstallFolder\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_USERMETEORSESSIONFILE      = L\"UserMeteorSessionFile\";\n\n\nstatic const LPCWSTR WIXSTDBA_VARIABLE_REG_MAIL     = L\"RegisterEmail\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_REG_USER     = L\"RegisterUser\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_REG_PASS     = L\"RegisterPass\";\n\nstatic const LPCWSTR WIXSTDBA_VARIABLE_LOG_USERNAME_OR_MAIL = L\"LoginUsernameOrEmail\";\nstatic const LPCWSTR WIXSTDBA_VARIABLE_LOG_PASS             = L\"LoginPass\";\n\n\nstatic const LPCWSTR WIXSTDBA_VARIABLE_LOGSPATH        = L\"QCInstallLogsPath\";\n\nstatic const DWORD WIXSTDBA_ACQUIRE_PERCENTAGE = 1;\n\nenum WIXSTDBA_STATE\n{\n\tWIXSTDBA_STATE_INSTALLDIR,\n\tWIXSTDBA_STATE_SVC_OPTIONS,\n\tWIXSTDBA_STATE_INITIALIZING,\n\tWIXSTDBA_STATE_INITIALIZED,\n\tWIXSTDBA_STATE_HELP,\n\tWIXSTDBA_STATE_DETECTING,\n\tWIXSTDBA_STATE_DETECTED,\n\tWIXSTDBA_STATE_PLANNING,\n\tWIXSTDBA_STATE_PLANNED,\n\tWIXSTDBA_STATE_APPLYING,\n\tWIXSTDBA_STATE_CACHING,\n\tWIXSTDBA_STATE_CACHED,\n\tWIXSTDBA_STATE_EXECUTING,\n\tWIXSTDBA_STATE_EXECUTED,\n\tWIXSTDBA_STATE_APPLIED,\n\tWIXSTDBA_STATE_FAILED,\n};\n\nenum WM_WIXSTDBA\n{\n\tWM_WIXSTDBA_SHOW_HELP = WM_APP + 100,\n\tWM_WIXSTDBA_DETECT_PACKAGES,\n\tWM_WIXSTDBA_PLAN_PACKAGES,\n\tWM_WIXSTDBA_APPLY_PACKAGES,\n\tWM_WIXSTDBA_CHANGE_STATE,\n};\n\n// This enum must be kept in the same order as the vrgwzPageNames array.\nenum WIXSTDBA_PAGE\n{\n\tWIXSTDBA_PAGE_LOADING,\n\tWIXSTDBA_PAGE_HELP,\n\tWIXSTDBA_PAGE_INSTALL,\n\tWIXSTDBA_PAGE_INSTALLDIR,\n\tWIXSTDBA_PAGE_SVC_OPTIONS,\n\tWIXSTDBA_PAGE_MODIFY,\n\tWIXSTDBA_PAGE_PROGRESS,\n\tWIXSTDBA_PAGE_PROGRESS_PASSIVE,\n\tWIXSTDBA_PAGE_SUCCESS,\n\tWIXSTDBA_PAGE_FAILURE,\n\tCOUNT_WIXSTDBA_PAGE,\n};\n\n// This array must be kept in the same order as the WIXSTDBA_PAGE enum.\nstatic LPCWSTR vrgwzPageNames[] = {\n\tL\"Loading\",\n\tL\"Help\",\n\tL\"Install\",\n\tL\"InstallDir\",\n\tL\"SvcOptions\",\n\tL\"Modify\",\n\tL\"Progress\",\n\tL\"ProgressPassive\",\n\tL\"Success\",\n\tL\"Failure\",\n};\n\nenum WIXSTDBA_CONTROL\n{\n\t// Non-paged controls\n\tWIXSTDBA_CONTROL_CLOSE_BUTTON = THEME_FIRST_ASSIGN_CONTROL_ID,\n\tWIXSTDBA_CONTROL_MINIMIZE_BUTTON,\n\n\t// Help page\n\tWIXSTDBA_CONTROL_HELP_CANCEL_BUTTON,\n\n\t// Welcome page\n\tWIXSTDBA_CONTROL_INSTALL_BUTTON,\n\tWIXSTDBA_CONTROL_OPTIONS_BUTTON,\n\tWIXSTDBA_CONTROL_EULA_RICHEDIT,\n\tWIXSTDBA_CONTROL_EULA_LINK,\n\tWIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX,\n\tWIXSTDBA_CONTROL_WELCOME_CANCEL_BUTTON,\n\tWIXSTDBA_CONTROL_VERSION_LABEL,\n\tWIXSTDBA_CONTROL_UPGRADE_LINK,\n\tWIXSTDBA_CONTROL_NEXT_BUTTON,\n\tWIXSTDBA_CONTROL_BACK_BUTTON,\n\tWIXSTDBA_CONTROL_SKIP_BUTTON,\n\n\n\t// Options page\n\tWIXSTDBA_CONTROL_PERMACHINE_RADIO,\n\tWIXSTDBA_CONTROL_PERUSER_RADIO,\n\tWIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX,\n\tWIXSTDBA_CONTROL_BROWSE_BUTTON,\n\n\tWIXSTDBA_CONTROL_REGSIGNIN_RADIO,\n\tWIXSTDBA_CONTROL_REGCREATE_RADIO,\n\tWIXSTDBA_CONTROL_REGMAIL_LABEL,\n\tWIXSTDBA_CONTROL_REGUSER_LABEL,\n\tWIXSTDBA_CONTROL_REGPASS_LABEL,\n\tWIXSTDBA_CONTROL_REGMAIL_EDIT,\n\tWIXSTDBA_CONTROL_REGUSER_EDIT,\n\tWIXSTDBA_CONTROL_REGPASS_EDIT,\n\n\tWIXSTDBA_CONTROL_LOGUSER_OR_MAIL_LABEL,\n\tWIXSTDBA_CONTROL_LOGPASS_LABEL,\n\tWIXSTDBA_CONTROL_LOGUSER_OR_MAIL_EDIT,\n\tWIXSTDBA_CONTROL_LOGPASS_EDIT,\n\n\tWIXSTDBA_CONTROL_SKIPREG_CHECKBOX,\n\n\n\tWIXSTDBA_CONTROL_OK_BUTTON,\n\tWIXSTDBA_CONTROL_CANCEL_BUTTON,\n\n\t// Modify page\n\tWIXSTDBA_CONTROL_REPAIR_BUTTON,\n\tWIXSTDBA_CONTROL_UNINSTALL_BUTTON,\n\tWIXSTDBA_CONTROL_MODIFY_CANCEL_BUTTON,\n\n\t// Progress page\n\tWIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT,\n\tWIXSTDBA_CONTROL_CACHE_PROGRESS_BAR,\n\tWIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT,\n\n\tWIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT,\n\tWIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR,\n\tWIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT,\n\tWIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT,\n\n\tWIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT,\n\tWIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR,\n\tWIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR,\n\tWIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT,\n\n\tWIXSTDBA_CONTROL_PROGRESS_INSTALLING_HEADER,\t\n\n\tWIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON,\n\n\t// Success page\n\tWIXSTDBA_CONTROL_LAUNCH_BUTTON,\n\tWIXSTDBA_CONTROL_SUCCESS_RESTART_TEXT,\n\tWIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON,\n\tWIXSTDBA_CONTROL_SUCCESS_CANCEL_BUTTON,\n\tWIXSTDBA_CONTROL_SUCCESS_ERRINF_TEXT,\n\tWIXSTDBA_CONTROL_SUCCESS_ERRMSG_TEXT,\n\n\t// Failure page\n\tWIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK,\n\tWIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT,\n\tWIXSTDBA_CONTROL_FAILURE_RESTART_TEXT,\n\tWIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON,\n\tWIXSTDBA_CONTROL_FAILURE_CANCEL_BUTTON,\n\n};\n\nstatic THEME_ASSIGN_CONTROL_ID vrgInitControls[] = {\n\t{ WIXSTDBA_CONTROL_CLOSE_BUTTON, L\"CloseButton\" },\n\t{ WIXSTDBA_CONTROL_MINIMIZE_BUTTON, L\"MinimizeButton\" },\n\n\t{ WIXSTDBA_CONTROL_HELP_CANCEL_BUTTON, L\"HelpCancelButton\" },\n\n\t{ WIXSTDBA_CONTROL_INSTALL_BUTTON, L\"InstallButton\" },\n\t{ WIXSTDBA_CONTROL_OPTIONS_BUTTON, L\"OptionsButton\" },\n\t{ WIXSTDBA_CONTROL_EULA_RICHEDIT, L\"EulaRichedit\" },\n\t{ WIXSTDBA_CONTROL_EULA_LINK, L\"EulaHyperlink\" },\n\t{ WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, L\"EulaAcceptCheckbox\" },\n\t{ WIXSTDBA_CONTROL_WELCOME_CANCEL_BUTTON, L\"WelcomeCancelButton\" },\n\t{ WIXSTDBA_CONTROL_VERSION_LABEL, L\"InstallVersion\" },\n\t{ WIXSTDBA_CONTROL_UPGRADE_LINK, L\"UpgradeHyperlink\" },\n\t{ WIXSTDBA_CONTROL_NEXT_BUTTON, L\"NextButton\" },\n\t{ WIXSTDBA_CONTROL_BACK_BUTTON, L\"BackButton\" },\n\t{ WIXSTDBA_CONTROL_SKIP_BUTTON, L\"SkipButton\" },\n\n\t{WIXSTDBA_CONTROL_PERMACHINE_RADIO, L\"PerMachineInstall\" },\n\t{WIXSTDBA_CONTROL_PERUSER_RADIO, L\"PerUserInstall\" },\n\t{ WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, L\"InstallFolderEditbox\" },\n\t{ WIXSTDBA_CONTROL_BROWSE_BUTTON, L\"BrowseButton\" },\n\n\t{WIXSTDBA_CONTROL_REGSIGNIN_RADIO, L\"SignInRButton\"},\n\t{WIXSTDBA_CONTROL_REGCREATE_RADIO, L\"CreateRButton\"},\n\t{WIXSTDBA_CONTROL_REGMAIL_LABEL, L\"RegisterEmailLabel\"},\n\t{WIXSTDBA_CONTROL_REGUSER_LABEL, L\"RegisterUserLabel\"},\n\t{WIXSTDBA_CONTROL_REGPASS_LABEL, L\"RegisterPassLabel\"},\n\t{WIXSTDBA_CONTROL_REGMAIL_EDIT, L\"RegisterEmail\"},\n\t{WIXSTDBA_CONTROL_REGUSER_EDIT, L\"RegisterUser\"},\n\t{WIXSTDBA_CONTROL_REGPASS_EDIT, L\"RegisterPass\"},\n\n\t{WIXSTDBA_CONTROL_LOGUSER_OR_MAIL_LABEL, L\"LoginUsernameOrEmailLabel\"},\n\t{WIXSTDBA_CONTROL_LOGPASS_LABEL, L\"LoginPassLabel\"},\n\t{WIXSTDBA_CONTROL_LOGUSER_OR_MAIL_EDIT, L\"LoginUsernameOrEmail\"},\n\t{WIXSTDBA_CONTROL_LOGPASS_EDIT, L\"LoginPass\"},\n\n\t{WIXSTDBA_CONTROL_SKIPREG_CHECKBOX, L\"SkipRegistration\"},\n\n\t{ WIXSTDBA_CONTROL_REPAIR_BUTTON, L\"RepairButton\" },\n\t{ WIXSTDBA_CONTROL_UNINSTALL_BUTTON, L\"UninstallButton\" },\n\t{ WIXSTDBA_CONTROL_MODIFY_CANCEL_BUTTON, L\"ModifyCancelButton\" },\n\n\t{ WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, L\"CacheProgressPackageText\" },\n\t{ WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, L\"CacheProgressbar\" },\n\t{ WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, L\"CacheProgressText\" },\n\t{ WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, L\"ExecuteProgressPackageText\" },\n\t{ WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, L\"ExecuteProgressbar\" },\n\t{ WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, L\"ExecuteProgressText\" },\n\t{ WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, L\"ExecuteProgressActionDataText\"},\n\t{ WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, L\"OverallProgressPackageText\" },\n\t{ WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, L\"OverallProgressbar\" },\n\t{ WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, L\"OverallCalculatedProgressbar\" },\n\t{ WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, L\"OverallProgressText\" },\n\t{ WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, L\"ProgressCancelButton\" },\n\t{ WIXSTDBA_CONTROL_PROGRESS_INSTALLING_HEADER, L\"InstallingHeader\" },\n\n\t{ WIXSTDBA_CONTROL_LAUNCH_BUTTON, L\"LaunchButton\" },\n\t{ WIXSTDBA_CONTROL_SUCCESS_RESTART_TEXT, L\"SuccessRestartText\" },\n\t{ WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, L\"SuccessRestartButton\" },\n\t{ WIXSTDBA_CONTROL_SUCCESS_CANCEL_BUTTON, L\"SuccessCancelButton\" },\n\t{ WIXSTDBA_CONTROL_SUCCESS_ERRINF_TEXT, L\"SuccessErrorInfoText\" },\n\t{ WIXSTDBA_CONTROL_SUCCESS_ERRMSG_TEXT, L\"SuccessErrorMessageText\" },\n\n\t{ WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, L\"FailureLogFileLink\" },\n\t{ WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, L\"FailureMessageText\" },\n\t{ WIXSTDBA_CONTROL_FAILURE_RESTART_TEXT, L\"FailureRestartText\" },\n\t{ WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, L\"FailureRestartButton\" },\n\t{ WIXSTDBA_CONTROL_FAILURE_CANCEL_BUTTON, L\"FailureCloseButton\" },\n};\n\n\nvoid ExtractActionProgressText(\n\t__in_z LPCWSTR wzActionMessage,\n\t__in_z LPCWSTR *pwzActionProgressText\n\t)\n{\n\tif (!wzActionMessage)\n\t\treturn;\n\n\tDWORD i = 0;\n\tLPCWSTR wzActionProgressText = wzActionMessage;\n\n\tLPCWSTR wz = wzActionMessage;\n\twhile (*wz)\n    {\n\t\tif (L' ' == *wz) ++i;\n\t\tif (i <= 2) wzActionProgressText++;\n\n        ++wz;\n    }\n\t*pwzActionProgressText = wzActionProgressText;\n\n\treturn;\n}\n\n\n\n\nclass CWixStandardBootstrapperApplication : public CBalBaseBootstrapperApplication\n{\npublic: // IBootstrapperApplication\n\tvirtual STDMETHODIMP OnStartup()\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tDWORD dwUIThreadId = 0;\n\n\t\t// create UI thread\n\t\tm_hUiThread = ::CreateThread(NULL, 0, UiThreadProc, this, 0, &dwUIThreadId);\n\t\tif (!m_hUiThread)\n\t\t{\n\t\t\tExitWithLastError(hr, \"Failed to create UI thread.\");\n\t\t}\n\nLExit:\n\t\treturn hr;\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnShutdown()\n\t{\n\t\tint nResult = IDNOACTION;\n\n\t\t// wait for UI thread to terminate\n\t\tif (m_hUiThread)\n\t\t{\n\t\t\t::WaitForSingleObject(m_hUiThread, INFINITE);\n\t\t\tReleaseHandle(m_hUiThread);\n\t\t}\n\n\t\t// If a restart was required.\n\t\tif (m_fRestartRequired)\n\t\t{\n\t\t\tif (m_fAllowRestart)\n\t\t\t{\n\t\t\t\tnResult = IDRESTART;\n\t\t\t}\n\n\t\t\tif (m_sczPrereqPackage)\n\t\t\t{\n\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, m_fAllowRestart ? \"The prerequisites scheduled a restart. The bootstrapper application will be reloaded after the computer is restarted.\"\n\t\t\t\t\t: \"A restart is required by the prerequisites but the user delayed it. The bootstrapper application will be reloaded after the computer is restarted.\");\n\t\t\t}\n\t\t}\n\t\telse if (m_fPrereqInstalled)\n\t\t{\n\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"The prerequisites were successfully installed. The bootstrapper application will be reloaded.\");\n\t\t\tnResult = IDRELOAD_BOOTSTRAPPER;\n\t\t}\n\t\telse if (m_fPrereqAlreadyInstalled)\n\t\t{\n\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop.\");\n\t\t}\n\t\telse if (m_fPrereq)\n\t\t{\n\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"The prerequisites were not successfully installed, error: 0x%x. The bootstrapper application will be not reloaded.\", m_hrFinal);\n\t\t}\n\n\t\treturn nResult;\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnDetectRelatedBundle(\n\t\t__in LPCWSTR wzBundleId,\n\t\t__in BOOTSTRAPPER_RELATION_TYPE relationType,\n\t\t__in LPCWSTR /*wzBundleTag*/,\n\t\t__in BOOL fPerMachine,\n\t\t__in DWORD64 /*dw64Version*/,\n\t\t__in BOOTSTRAPPER_RELATED_OPERATION operation\n\t\t)\n\t{\n\t\tBalInfoAddRelatedBundleAsPackage(&m_Bundle.packages, wzBundleId, relationType, fPerMachine);\n\t\t// If we're not doing a pre-req install, remember when our bundle would cause a downgrade.\n\t\tif (!m_sczPrereqPackage && BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE == operation)\n\t\t{\n\t\t\tm_fDowngrading = TRUE;\n\t\t}\n\n\t\tm_Operation = operation; // Save operation\n\n\t\treturn CheckCanceled() ? IDCANCEL : IDOK;\n\t}\n\n\n\tvirtual STDMETHODIMP_(void) OnDetectPackageComplete(\n\t\t__in LPCWSTR wzPackageId,\n\t\t__in HRESULT /*hrStatus*/,\n\t\t__in BOOTSTRAPPER_PACKAGE_STATE state\n\t\t)\n\t{\n\t\t// If the prereq package is already installed, remember that.\n\t\tif (m_sczPrereqPackage && BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state &&\n\t\t\tCSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczPrereqPackage, -1))\n\t\t{\n\t\t\tm_fPrereqAlreadyInstalled = TRUE;\n\t\t}\n\t}\n\n\n\t// OnDetectUpdateBegin - called when the engine begins detection for bundle update.\n\tvirtual STDMETHODIMP_(int) OnDetectUpdateBegin(\n\t\t__in_z LPCWSTR wzUpdateLocation,\n\t\t__in int nRecommendation\n\t\t)\n\t{\n\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Update location: %ls.\", wzUpdateLocation);\n\n\t\tm_wzUpdateLocation = wzUpdateLocation;\n\t\t// If there is an upgrade link, check for update on a background thread\n\t\tif (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK))\n\t\t{\n\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK, FALSE);\n\t\t\t::CreateThread(NULL, 0, ThreadProc, this, 0, NULL);\n\t\t}\n\n\t\treturn nRecommendation;\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnDetectBegin(\n\t\t__in BOOL /*fInstalled*/,\n\t\t__in DWORD /*cPackages*/\n\t\t)\n\t{\n\t\treturn IDNOACTION;\n\t}\n\n\n\tvirtual STDMETHODIMP_(void) OnDetectComplete(\n\t\t__in HRESULT hrStatus\n\t\t)\n\t{\n\t\tif (SUCCEEDED(hrStatus) && m_pBAFunction)\n\t\t{\n\t\t\tm_pBAFunction->OnDetectComplete();\n\t\t}\n\n\t\tif (SUCCEEDED(hrStatus))\n\t\t{\n\t\t\thrStatus = EvaluateConditions();\n\t\t}\n\n\t\tif (m_command.action == BOOTSTRAPPER_ACTION_UNINSTALL)\n\t\t\tthis->OnPlan(BOOTSTRAPPER_ACTION_UNINSTALL);\n\t\telse\n\t\t\tthis->OnPlan(BOOTSTRAPPER_ACTION_INSTALL);\n\n\t\t// Doing some custom vars handling\n\t\t//if (BalStringVariableExists(WIXSTDBA_VARIABLE_DETECT_POSTGRES))\n\t\t//{\n\t\t//\tLONGLONG llValue = 0;\n\t\t//\tBalGetNumericVariable(WIXSTDBA_VARIABLE_DETECT_POSTGRES, &llValue);\n\t\t//\tif (llValue == 1)\n\t\t//\t\tm_pEngine->SetVariableNumeric(WIXSTDBA_VARIABLE_INSTALL_POSTGRES, 0);\n\t\t//}\n\n\n\t\t// If we're not interacting with the user or we're doing a layout or we're just after a force restart\n\t\t// then automatically start planning.\n\t\tif (BOOTSTRAPPER_DISPLAY_FULL > m_command.display || BOOTSTRAPPER_ACTION_LAYOUT == m_command.action || BOOTSTRAPPER_RESUME_TYPE_REBOOT == m_command.resumeType)\n\t\t{\n\t\t\tif (SUCCEEDED(hrStatus))\n\t\t\t{\n\t\t\t\t::PostMessageW(m_hWnd, WM_WIXSTDBA_PLAN_PACKAGES, 0, m_command.action);\n\t\t\t}\n\t\t}\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnPlanRelatedBundle(\n\t\t__in_z LPCWSTR /*wzBundleId*/,\n\t\t__inout_z BOOTSTRAPPER_REQUEST_STATE* pRequestedState\n\t\t)\n\t{\n\t\t// If we're only installing prereq, do not touch related bundles.\n\t\tif (m_sczPrereqPackage)\n\t\t{\n\t\t\t*pRequestedState = BOOTSTRAPPER_REQUEST_STATE_NONE;\n\t\t}\n\t\telse if (BOOTSTRAPPER_RELATED_OPERATION_NONE == m_Operation &&\n\t\t\tBOOTSTRAPPER_REQUEST_STATE_NONE == *pRequestedState &&\n\t\t\tBOOTSTRAPPER_RELATION_UPGRADE != m_command.relationType)\n\t\t{\n\t\t\t// Same version upgrade detected, mark absent so the install runs\n\t\t\t*pRequestedState = BOOTSTRAPPER_REQUEST_STATE_ABSENT;\n\t\t}\n\n\t\treturn CheckCanceled() ? IDCANCEL : IDOK;\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnPlanPackageBegin(\n\t\t__in_z LPCWSTR wzPackageId,\n\t\t__inout BOOTSTRAPPER_REQUEST_STATE *pRequestState\n\t\t)\n\t{\n\t\t// If we're planning to install a pre-req, install it. The pre-req needs to be installed\n\t\t// in all cases (even uninstall!) so the BA can load next.\n\t\tif (m_sczPrereqPackage)\n\t\t{\n\t\t\tif (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczPrereqPackage, -1))\n\t\t\t{\n\t\t\t\t*pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT;\n\t\t\t}\n\t\t\telse // skip everything else.\n\t\t\t{\n\t\t\t\t*pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;\n\t\t\t}\n\t\t}\n\t\telse if (m_sczAfterForcedRestartPackage) // after force restart skip packages until after the package that caused the restart.\n\t\t{\n\t\t\t// After restart we need to finish the dependency registration for our package so allow the package\n\t\t\t// to go present.\n\t\t\tif (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczAfterForcedRestartPackage, -1))\n\t\t\t{\n\t\t\t\t// Do not allow a repair because that could put us in a perpetual restart loop.\n\t\t\t\tif (BOOTSTRAPPER_REQUEST_STATE_REPAIR == *pRequestState)\n\t\t\t\t{\n\t\t\t\t\t*pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT;\n\t\t\t\t}\n\n\t\t\t\tReleaseNullStr(m_sczAfterForcedRestartPackage); // no more skipping now.\n\t\t\t}\n\t\t\telse // not the matching package, so skip it.\n\t\t\t{\n\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Skipping package: %ls, after restart because it was applied before the restart.\", wzPackageId);\n\n\t\t\t\t*pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;\n\t\t\t}\n\t\t}\n\n\t\treturn CheckCanceled() ? IDCANCEL : IDOK;\n\t}\n\n\n\tvirtual STDMETHODIMP_(void) OnPlanComplete(\n\t\t__in HRESULT hrStatus\n\t\t)\n\t{\n\t\tif (SUCCEEDED(hrStatus) && m_pBAFunction)\n\t\t{\n\t\t\tm_pBAFunction->OnPlanComplete();\n\t\t}\n\n\t\tSetState(WIXSTDBA_STATE_PLANNED, hrStatus);\n\n\t\tif (SUCCEEDED(hrStatus))\n\t\t{\n\t\t\t::PostMessageW(m_hWnd, WM_WIXSTDBA_APPLY_PACKAGES, 0, 0);\n\t\t}\n\n\t\tm_fStartedExecution = FALSE;\n\t\tm_dwCalculatedCacheProgress = 0;\n\t\tm_dwCalculatedExecuteProgress = 0;\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnCachePackageBegin(\n\t\t__in_z LPCWSTR wzPackageId,\n\t\t__in DWORD cCachePayloads,\n\t\t__in DWORD64 dw64PackageCacheSize\n\t\t)\n\t{\n\t\tif (wzPackageId && *wzPackageId)\n\t\t{\n\t\t\tBAL_INFO_PACKAGE* pPackage = NULL;\n\t\t\tHRESULT hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);\n\t\t\tLPCWSTR wz = (SUCCEEDED(hr) && pPackage->sczDisplayName) ? pPackage->sczDisplayName : wzPackageId;\n\n\t\t\tWCHAR wzInfo[1024] = { };\n\t\t\t::StringCchPrintfW(wzInfo, countof(wzInfo), L\"Acquiring %s package...\", wz);\n\t\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, wzInfo);\n\t\t\t// If something started executing, leave it in the overall progress text.\n\t\t\tif (!m_fStartedExecution)\n\t\t\t{\n\t\t\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wzInfo);\n\t\t\t}\n\t\t}\n\n\t\treturn __super::OnCachePackageBegin(wzPackageId, cCachePayloads, dw64PackageCacheSize);\n\t}\n\n\tvirtual STDMETHODIMP_(int) OnCacheAcquireProgress(\n\t\t__in_z LPCWSTR wzPackageOrContainerId,\n\t\t__in_z_opt LPCWSTR wzPayloadId,\n\t\t__in DWORD64 dw64Progress,\n\t\t__in DWORD64 dw64Total,\n\t\t__in DWORD dwOverallPercentage\n\t\t)\n\t{\n\t\tWCHAR wzProgress[5] = { };\n\n#ifdef DEBUG\n\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"WIXSTDBA: OnCacheAcquireProgress() - container/package: %ls, payload: %ls, progress: %I64u, total: %I64u, overall progress: %u%%\", wzPackageOrContainerId, wzPayloadId, dw64Progress, dw64Total, dwOverallPercentage);\n#endif\n\n\t\t::StringCchPrintfW(wzProgress, countof(wzProgress), L\"%u%%\", dwOverallPercentage);\n\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, wzProgress);\n\t\tThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, dwOverallPercentage);\n\n\t\tBAL_INFO_PACKAGE* pPackage = NULL;\n\t\tHRESULT hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageOrContainerId, &pPackage);\n\t\tLPCWSTR wzPackageName = (SUCCEEDED(hr) && pPackage->sczDisplayName) ? pPackage->sczDisplayName : wzPackageOrContainerId;\n\n\t\tWCHAR wzInfo[1024] = { };\n\t\t::StringCchPrintfW(wzInfo, countof(wzInfo), L\"Acquiring %s package...  [ %u%% ]\", wzPackageName, dwOverallPercentage);\n\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wzInfo);\n\n\t\t// Restrict progress to 100% to hide burn engine progress bug.\n\t\t// m_dwCalculatedCacheProgress = min(dwOverallPercentage, 100) * WIXSTDBA_ACQUIRE_PERCENTAGE / 100;\n\n#ifdef DEBUG\n\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"WIXSTDBA: OnCacheAcquireProgress() - calculated progress: %u%%, displayed progress: %u%%\", m_dwCalculatedCacheProgress, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);\n#endif\n\t\tm_dwCalculatedCacheProgress = dwOverallPercentage * WIXSTDBA_ACQUIRE_PERCENTAGE / 100;\n\t\tThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);\n\n\t\tSetTaskbarButtonProgress(m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);\n\n\t\treturn __super::OnCacheAcquireProgress(wzPackageOrContainerId, wzPayloadId, dw64Progress, dw64Total, dwOverallPercentage);\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnCacheAcquireComplete(\n\t\t__in_z LPCWSTR wzPackageOrContainerId,\n\t\t__in_z_opt LPCWSTR wzPayloadId,\n\t\t__in HRESULT hrStatus,\n\t\t__in int nRecommendation\n\t\t)\n\t{\n\t\tSetProgressState(hrStatus);\n\t\treturn __super::OnCacheAcquireComplete(wzPackageOrContainerId, wzPayloadId, hrStatus, nRecommendation);\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnCacheVerifyComplete(\n\t\t__in_z LPCWSTR wzPackageId,\n\t\t__in_z LPCWSTR wzPayloadId,\n\t\t__in HRESULT hrStatus,\n\t\t__in int nRecommendation\n\t\t)\n\t{\n\t\tSetProgressState(hrStatus);\n\t\treturn __super::OnCacheVerifyComplete(wzPackageId, wzPayloadId, hrStatus, nRecommendation);\n\t}\n\n\tvirtual STDMETHODIMP_(void) OnCacheComplete(\n\t\t__in HRESULT /*hrStatus*/\n\t\t)\n\t{\n\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, L\"\");\n\t\tSetState(WIXSTDBA_STATE_CACHED, S_OK); // we always return success here and let OnApplyComplete() deal with the error.\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnError(\n\t\t__in BOOTSTRAPPER_ERROR_TYPE errorType,\n\t\t__in LPCWSTR wzPackageId,\n\t\t__in DWORD dwCode,\n\t\t__in_z LPCWSTR wzError,\n\t\t__in DWORD dwUIHint,\n\t\t__in DWORD /*cData*/,\n\t\t__in_ecount_z_opt(cData) LPCWSTR* /*rgwzData*/,\n\t\t__in int nRecommendation\n\t\t)\n\t{\n\t\tint nResult = nRecommendation;\n\t\tLPWSTR sczError = NULL;\n\n\t\tif (BOOTSTRAPPER_DISPLAY_EMBEDDED == m_command.display)\n\t\t{\n\t\t\tHRESULT hr = m_pEngine->SendEmbeddedError(dwCode, wzError, dwUIHint, &nResult);\n\t\t\tif (FAILED(hr))\n\t\t\t{\n\t\t\t\tnResult = IDERROR;\n\t\t\t}\n\t\t}\n\t\telse if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display)\n\t\t{\n\t\t\t// If this is an authentication failure, let the engine try to handle it for us.\n\t\t\tif (BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_SERVER == errorType || BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_PROXY == errorType)\n\t\t\t{\n\t\t\t\tnResult = IDTRYAGAIN;\n\t\t\t}\n\t\t\telse // show a generic error message box.\n\t\t\t{\n\t\t\t\tBalRetryErrorOccurred(wzPackageId, dwCode);\n\n\t\t\t\tif (!m_fShowingInternalUiThisPackage)\n\t\t\t\t{\n\t\t\t\t\t// If no error message was provided, use the error code to try and get an error message.\n\t\t\t\t\tif (!wzError || !*wzError || BOOTSTRAPPER_ERROR_TYPE_WINDOWS_INSTALLER != errorType)\n\t\t\t\t\t{\n\t\t\t\t\t\tHRESULT hr = StrAllocFromError(&sczError, dwCode, NULL);\n\t\t\t\t\t\tif (FAILED(hr) || !sczError || !*sczError)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStrAllocFormatted(&sczError, L\"0x%x\", dwCode);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tnResult = ::MessageBoxW(m_hWnd, sczError ? sczError : wzError, m_pTheme->sczCaption, dwUIHint);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tSetProgressState(HRESULT_FROM_WIN32(dwCode));\n\t\t}\n\t\telse // just take note of the error code and let things continue.\n\t\t{\n\t\t\tBalRetryErrorOccurred(wzPackageId, dwCode);\n\t\t}\n\n\t\tReleaseStr(sczError);\n\t\treturn nResult;\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnExecuteMsiMessage(\n\t\t__in_z LPCWSTR wzPackageId,\n\t\t__in INSTALLMESSAGE mt,\n\t\t__in UINT uiFlags,\n\t\t__in_z LPCWSTR wzMessage,\n\t\t__in DWORD cData,\n\t\t__in_ecount_z_opt(cData) LPCWSTR* rgwzData,\n\t\t__in int nRecommendation\n\t\t)\n\t{\n#ifdef DEBUG\n\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"WIXSTDBA: OnExecuteMsiMessage() - package: %ls, message: %ls\", wzPackageId, wzMessage);\n#endif\n\t\tif (BOOTSTRAPPER_DISPLAY_FULL == m_command.display && (INSTALLMESSAGE_WARNING == mt || INSTALLMESSAGE_USER == mt))\n\t\t{\n\t\t\tint nResult = ::MessageBoxW(m_hWnd, wzMessage, m_pTheme->sczCaption, uiFlags);\n\t\t\treturn nResult;\n\t\t}\n\n\t\tif (INSTALLMESSAGE_ACTIONSTART == mt)\n\t\t{\n\t\t\tLPCWSTR wzActionProgressText = NULL;\n\t\t\tExtractActionProgressText(wzMessage, &wzActionProgressText);\n\t\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, wzActionProgressText);\n\t\t}\n\n\n\t\treturn __super::OnExecuteMsiMessage(wzPackageId, mt, uiFlags, wzMessage, cData, rgwzData, nRecommendation);\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnProgress(\n\t\t__in DWORD dwProgressPercentage,\n\t\t__in DWORD dwOverallProgressPercentage\n\t\t)\n\t{\n\t\tWCHAR wzProgress[5] = { };\n\n#ifdef DEBUG\n\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"WIXSTDBA: OnProgress() - progress: %u%%, overall progress: %u%%\", dwProgressPercentage, dwOverallProgressPercentage);\n#endif\n\n\t\t::StringCchPrintfW(wzProgress, countof(wzProgress), L\"%u%%\", dwOverallProgressPercentage);\n\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, wzProgress);\n\n\t\tThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, dwOverallProgressPercentage);\n\t\tSetTaskbarButtonProgress(dwOverallProgressPercentage);\n\n\t\treturn __super::OnProgress(dwProgressPercentage, dwOverallProgressPercentage);\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnExecutePackageBegin(\n\t\t__in_z LPCWSTR wzPackageId,\n\t\t__in BOOL fExecute\n\t\t)\n\t{\n\t\tif (m_fIsUninstall) {\n\t\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_INSTALLING_HEADER, L\"Uninstalling Meteor,\\nThe JavaScript App Platform\");\n\t\t} else {\n\t\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_INSTALLING_HEADER, L\"Installing Meteor,\\nThe JavaScript App Platform\");\t\t\t\n\t\t}\n\n\t\tLPWSTR sczFormattedString = NULL;\n\n\t\tm_fStartedExecution = TRUE;\n\n\t\tif (wzPackageId && *wzPackageId)\n\t\t{\n\t\t\tBAL_INFO_PACKAGE* pPackage = NULL;\n\t\t\tBalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);\n\n\t\t\tLPCWSTR wz = wzPackageId;\n\t\t\tif (pPackage)\n\t\t\t{\n\t\t\t\tLOC_STRING* pLocString = NULL;\n\n\t\t\t\tswitch (pPackage->type)\n\t\t\t\t{\n\t\t\t\tcase BAL_INFO_PACKAGE_TYPE_BUNDLE_ADDON:\n\t\t\t\t\tLocGetString(m_pWixLoc, L\"#(loc.ExecuteAddonRelatedBundleMessage)\", &pLocString);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH:\n\t\t\t\t\tLocGetString(m_pWixLoc, L\"#(loc.ExecutePatchRelatedBundleMessage)\", &pLocString);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BAL_INFO_PACKAGE_TYPE_BUNDLE_UPGRADE:\n\t\t\t\t\tLocGetString(m_pWixLoc, L\"#(loc.ExecuteUpgradeRelatedBundleMessage)\", &pLocString);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (pLocString)\n\t\t\t\t{\n\t\t\t\t\tBalFormatString(pLocString->wzText, &sczFormattedString);\n\t\t\t\t}\n\n\t\t\t\twz = sczFormattedString ? sczFormattedString : pPackage->sczDisplayName ? pPackage->sczDisplayName : wzPackageId;\n\t\t\t}\n\n\t\t\tm_fShowingInternalUiThisPackage = pPackage && pPackage->fDisplayInternalUI;\n\n\t\t\tWCHAR wzInfo[1024] = { };\n\t\t\tif (m_fIsUninstall)\n\t\t\t\t::StringCchPrintfW(wzInfo, countof(wzInfo), L\"Uninstalling %s...\", wz);\n\t\t\telse\n\t\t\t\t::StringCchPrintfW(wzInfo, countof(wzInfo), L\"Installing %s...\", wz);\n\n\t\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, wz);\n\t\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wz);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_fShowingInternalUiThisPackage = FALSE;\n\t\t}\n\n\t\tReleaseStr(sczFormattedString);\n\t\treturn __super::OnExecutePackageBegin(wzPackageId, fExecute);\n\t}\n\n\tvirtual int __stdcall  OnExecuteProgress(\n\t\t__in_z LPCWSTR wzPackageId,\n\t\t__in DWORD dwProgressPercentage,\n\t\t__in DWORD dwOverallProgressPercentage\n\t\t)\n\t{\n\t\tWCHAR wzProgress[5] = { };\n\n#ifdef DEBUG\n\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"WIXSTDBA: OnExecuteProgress() - package: %ls, progress: %u%%, overall progress: %u%%\", wzPackageId, dwProgressPercentage, dwOverallProgressPercentage);\n#endif\n\n\t\t::StringCchPrintfW(wzProgress, countof(wzProgress), L\"%u%%\", dwOverallProgressPercentage);\n\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, wzProgress);\n\t\tThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, dwOverallProgressPercentage);\n\n\t\tBAL_INFO_PACKAGE* pPackage = NULL;\n\t\tHRESULT hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);\n\t\tLPCWSTR wzPackageName = (SUCCEEDED(hr) && pPackage->sczDisplayName) ? pPackage->sczDisplayName : wzPackageId;\n\n\t\tWCHAR wzInfo[1024] = { };\n\t\tif (m_fIsUninstall)\n\t\t\t::StringCchPrintfW(wzInfo, countof(wzInfo), L\"Uninstalling %s...\", wzPackageName, dwProgressPercentage);\n\t\telse\n\t\t\t::StringCchPrintfW(wzInfo, countof(wzInfo), L\"Installing %s...\", wzPackageName, dwProgressPercentage);\n\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wzInfo);\n\n\t\tm_dwCalculatedExecuteProgress = dwOverallProgressPercentage * (100 - WIXSTDBA_ACQUIRE_PERCENTAGE) / 100;\n#ifdef DEBUG\n\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"WIXSTDBA: OnExecuteProgress() - calculated progress: %u%%, displayed progress: %u%%\", m_dwCalculatedExecuteProgress, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);\n#endif\n\t\tThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);\n\n\t\tSetTaskbarButtonProgress(m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);\n\n\t\treturn __super::OnExecuteProgress(wzPackageId, dwProgressPercentage, dwOverallProgressPercentage);\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnExecutePackageComplete(\n\t\t__in_z LPCWSTR wzPackageId,\n\t\t__in HRESULT hrExitCode,\n\t\t__in BOOTSTRAPPER_APPLY_RESTART restart,\n\t\t__in int nRecommendation\n\t\t)\n\t{\n\t\tSetProgressState(hrExitCode);\n\n\t\tint nResult = __super::OnExecutePackageComplete(wzPackageId, hrExitCode, restart, nRecommendation);\n\n\t\tif (m_sczPrereqPackage && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczPrereqPackage, -1))\n\t\t{\n\t\t\tm_fPrereqInstalled = SUCCEEDED(hrExitCode);\n\n\t\t\t// If the pre-req required a restart (any restart) then do an immediate\n\t\t\t// restart to ensure that the bundle will get launched again post reboot.\n\t\t\tif (BOOTSTRAPPER_APPLY_RESTART_NONE != restart)\n\t\t\t{\n\t\t\t\tnResult = IDRESTART;\n\t\t\t}\n\t\t}\n\n\n\t\t/// On package install complete, if WIXSTDBA_VARIABLE_LOGSPATH is defined\n\t\t/// then will move the package installation log to the specified path.\n\t\tif (BalStringVariableExists(WIXSTDBA_VARIABLE_LOGSPATH))\n\t\t{\n\t\t\tLPWSTR wzVarPackageLog = NULL;\n\t\t\tStrAllocFormatted(&wzVarPackageLog, L\"WixBundleLog_%s\", wzPackageId);\n\t\t\tif (BalStringVariableExists(wzVarPackageLog))\n\t\t\t{\n\t\t\t\tLPWSTR wzPackageLog = NULL;\n\t\t\t\tLPWSTR wzInstallLogPath = NULL;\n\t\t\t\tLPWSTR wzDstPackageLog = NULL;\n\n\t\t\t\tif ( SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_LOGSPATH, &wzInstallLogPath)) &&\n\t\t\t\t\t SUCCEEDED(BalGetStringVariable(wzVarPackageLog, &wzPackageLog)))\n\t\t\t\t{\n\t\t\t\t\tStrAllocFormatted(&wzDstPackageLog, L\"%s\\\\%s\", wzInstallLogPath, PathFile(wzPackageLog));\n\t\t\t\t\tDirEnsureExists(wzInstallLogPath, NULL);\n\t\t\t\t\tFileEnsureMove(wzPackageLog, wzDstPackageLog, TRUE, TRUE);\n\t\t\t\t} else\n\t\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Setup was unable to copy logs to the specified installation log path.\");\n\n\t\t\t}\n\t\t}\n\n\t\treturn nResult;\n\t}\n\n\n\tvirtual STDMETHODIMP_(void) OnExecuteComplete(\n\t\t__in HRESULT hrStatus\n\t\t)\n\t{\n\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, L\"\");\n\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, L\"\");\n\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, L\"\");\n\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, FALSE); // no more cancel.\n\n\t\tSetState(WIXSTDBA_STATE_EXECUTED, S_OK); // we always return success here and let OnApplyComplete() deal with the error.\n\t\tSetProgressState(hrStatus);\n\t}\n\n\tvirtual STDMETHODIMP_(int) OnResolveSource(\n\t\t__in_z LPCWSTR wzPackageOrContainerId,\n\t\t__in_z_opt LPCWSTR wzPayloadId,\n\t\t__in_z LPCWSTR wzLocalSource,\n\t\t__in_z_opt LPCWSTR wzDownloadSource\n\t\t)\n\t{\n\t\tint nResult = IDERROR; // assume we won't resolve source and that is unexpected.\n\n\t\tif (BOOTSTRAPPER_DISPLAY_FULL == m_command.display)\n\t\t{\n\t\t\tif (wzDownloadSource)\n\t\t\t{\n\t\t\t\tnResult = IDDOWNLOAD;\n\t\t\t}\n\t\t\telse // prompt to change the source location.\n\t\t\t{\n\t\t\t\tOPENFILENAMEW ofn = { };\n\t\t\t\tWCHAR wzFile[MAX_PATH] = { };\n\n\t\t\t\t::StringCchCopyW(wzFile, countof(wzFile), wzLocalSource);\n\n\t\t\t\tofn.lStructSize = sizeof(ofn);\n\t\t\t\tofn.hwndOwner = m_hWnd;\n\t\t\t\tofn.lpstrFile = wzFile;\n\t\t\t\tofn.nMaxFile = countof(wzFile);\n\t\t\t\tofn.lpstrFilter = L\"All Files\\0*.*\\0\";\n\t\t\t\tofn.nFilterIndex = 1;\n\t\t\t\tofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;\n\t\t\t\tofn.lpstrTitle = m_pTheme->sczCaption;\n\n\t\t\t\tif (::GetOpenFileNameW(&ofn))\n\t\t\t\t{\n\t\t\t\t\tHRESULT hr = m_pEngine->SetLocalSource(wzPackageOrContainerId, wzPayloadId, ofn.lpstrFile);\n\t\t\t\t\tnResult = SUCCEEDED(hr) ? IDRETRY : IDERROR;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tnResult = IDCANCEL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (wzDownloadSource)\n\t\t{\n\t\t\t// If doing a non-interactive install and download source is available, let's try downloading the package silently\n\t\t\tnResult = IDDOWNLOAD;\n\t\t}\n\t\t// else there's nothing more we can do in non-interactive mode\n\n\t\treturn CheckCanceled() ? IDCANCEL : nResult;\n\t}\n\n\n\tvirtual STDMETHODIMP_(int) OnApplyComplete(\n\t\t__in HRESULT hrStatus,\n\t\t__in BOOTSTRAPPER_APPLY_RESTART restart\n\t\t)\n\t{\n\t\tm_restartResult = restart; // remember the restart result so we return the correct error code no matter what the user chooses to do in the UI.\n\n\t\t// If a restart was encountered and we are not suppressing restarts, then restart is required.\n\t\tm_fRestartRequired = (BOOTSTRAPPER_APPLY_RESTART_NONE != restart && BOOTSTRAPPER_RESTART_NEVER < m_command.restart);\n\t\t// If a restart is required and we're not displaying a UI or we are not supposed to prompt for restart then allow the restart.\n\t\tm_fAllowRestart = m_fRestartRequired && (BOOTSTRAPPER_DISPLAY_FULL > m_command.display || BOOTSTRAPPER_RESTART_PROMPT < m_command.restart);\n\n\t\t// If we are showing UI, wait a beat before moving to the final screen.\n\t\tif (BOOTSTRAPPER_DISPLAY_NONE < m_command.display)\n\t\t{\n\t\t\t::Sleep(250);\n\t\t}\n\n\t\tif (m_command.action == BOOTSTRAPPER_ACTION_UNINSTALL || BOOTSTRAPPER_DISPLAY_FULL > m_command.display)\n\t\t\tSetState(WIXSTDBA_STATE_APPLIED, S_OK);\n\t\telse\n\t\t\tSetState(WIXSTDBA_STATE_SVC_OPTIONS, hrStatus);\n\n\t\t// If we successfully applied an update close the window since the new Bundle should be running now.\n\t\tif (SUCCEEDED(hrStatus) && m_fUpdating)\n\t\t{\n\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Update downloaded, close bundle.\");\n\t\t\t::PostMessageW(m_hWnd, WM_CLOSE, 0, 0);\n\t\t}\n\n\t\treturn IDNOACTION;\n\t}\n\n\nprivate: // privates\n\t//\n\t// UiThreadProc - entrypoint for UI thread.\n\t//\n\tstatic DWORD WINAPI UiThreadProc(\n\t\t__in LPVOID pvContext\n\t\t)\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tCWixStandardBootstrapperApplication* pThis = (CWixStandardBootstrapperApplication*)pvContext;\n\t\tBOOL fComInitialized = FALSE;\n\t\tBOOL fRet = FALSE;\n\t\tMSG msg = { };\n\n\t\t// Initialize COM and theme.\n\t\thr = ::CoInitialize(NULL);\n\t\tBalExitOnFailure(hr, \"Failed to initialize COM.\");\n\t\tfComInitialized = TRUE;\n\n\t\thr = ThemeInitialize(pThis->m_hModule);\n\t\tBalExitOnFailure(hr, \"Failed to initialize theme manager.\");\n\n\t\thr = pThis->InitializeData();\n\t\tBalExitOnFailure(hr, \"Failed to initialize data in bootstrapper application.\");\n\n\n\t\t// Create main window.\n\t\tpThis->InitializeTaskbarButton();\n\t\thr = pThis->CreateMainWindow();\n\t\tBalExitOnFailure(hr, \"Failed to create main window.\");\n\n\t\t// Okay, we're ready for packages now.\n\t\tpThis->SetState(WIXSTDBA_STATE_INITIALIZED, hr);\n\t\t::PostMessageW(pThis->m_hWnd, BOOTSTRAPPER_ACTION_HELP == pThis->m_command.action ? WM_WIXSTDBA_SHOW_HELP : WM_WIXSTDBA_DETECT_PACKAGES, 0, 0);\n\n\t\t// message pump\n\t\twhile (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0)))\n\t\t{\n\t\t\tif (-1 == fRet)\n\t\t\t{\n\t\t\t\thr = E_UNEXPECTED;\n\t\t\t\tBalExitOnFailure(hr, \"Unexpected return value from message pump.\");\n\t\t\t}\n\t\t\telse if (!ThemeHandleKeyboardMessage(pThis->m_pTheme, msg.hwnd, &msg))\n\t\t\t{\n\t\t\t\t::TranslateMessage(&msg);\n\t\t\t\t::DispatchMessageW(&msg);\n\t\t\t}\n\t\t}\n\n\t\t// Succeeded thus far, check to see if anything went wrong while actually\n\t\t// executing changes.\n\t\tif (FAILED(pThis->m_hrFinal))\n\t\t{\n\t\t\thr = pThis->m_hrFinal;\n\t\t}\n\t\telse if (pThis->CheckCanceled())\n\t\t{\n\t\t\thr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);\n\t\t}\n\nLExit:\n\t\t// destroy main window\n\t\tpThis->DestroyMainWindow();\n\n\t\t// initiate engine shutdown\n\t\tDWORD dwQuit = HRESULT_CODE(hr);\n\t\tif (BOOTSTRAPPER_APPLY_RESTART_INITIATED == pThis->m_restartResult)\n\t\t{\n\t\t\tdwQuit = ERROR_SUCCESS_REBOOT_INITIATED;\n\t\t}\n\t\telse if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == pThis->m_restartResult)\n\t\t{\n\t\t\tdwQuit = ERROR_SUCCESS_REBOOT_REQUIRED;\n\t\t}\n\t\tpThis->m_pEngine->Quit(dwQuit);\n\n\t\tReleaseTheme(pThis->m_pTheme);\n\t\tThemeUninitialize();\n\n\t\t// uninitialize COM\n\t\tif (fComInitialized)\n\t\t{\n\t\t\t::CoUninitialize();\n\t\t}\n\n\t\treturn hr;\n\t}\n\n\n\tstatic DWORD WINAPI ThreadProc(\n\t\t__in LPVOID pvContext\n\t\t)\n\t{\n\t\tCWixStandardBootstrapperApplication* pThis = static_cast<CWixStandardBootstrapperApplication*>(pvContext);;\n\n\t\tHRESULT hr = S_OK;\n\t\tIXMLDOMDocument *pixd = NULL;\n\t\tIXMLDOMNode* pNode = NULL;\n\t\tLPWSTR sczUpdateUrl = NULL;\n\t\tDWORD64 qwSize = 0;\n\n\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Checking for update.\");\n\n\t\t// Load the update XML from a location url and parse it for an update.\n\t\t//\n\t\t// <?xml version=\"1.0\" encoding=\"utf-8\"?>\n\t\t// <Setup>\n\t\t//   <Upgrade Url=\"https://somewhere.co.uk/download/Setup.exe\" Size=\"123\" />\n\t\t// </Setup>\n\n\t\thr = XmlLoadDocumentFromFile(pThis->m_wzUpdateLocation, &pixd);\n\t\tBalExitOnFailure(hr, \"Failed to load version check XML document.\");\n\n\t\thr = XmlSelectSingleNode(pixd, L\"/Setup/Upgrade\", &pNode);\n\t\tBalExitOnFailure(hr, \"Failed to select upgrade node.\");\n\n\t\tif (S_OK == hr)\n\t\t{\n\t\t\thr = XmlGetAttributeEx(pNode, L\"Url\", &sczUpdateUrl);\n\t\t\tBalExitOnFailure(hr, \"Failed to get url attribute.\");\n\n\t\t\thr = XmlGetAttributeLargeNumber(pNode, L\"Size\", &qwSize);\n\t\t}\n\n\t\tif (sczUpdateUrl && *sczUpdateUrl)\n\t\t{\n\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Update available, url: %ls; size: %I64u.\", sczUpdateUrl, qwSize);\n\t\t\t// Show upgrade on install and modify pages\n\t\t\tif (pThis->m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == pThis->m_dwCurrentPage ||\n\t\t\t\tpThis->m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == pThis->m_dwCurrentPage)\n\t\t\t{\n\t\t\t\tpThis->m_pEngine->SetUpdate(NULL, sczUpdateUrl, qwSize, BOOTSTRAPPER_UPDATE_HASH_TYPE_NONE, NULL, 0);\n\t\t\t\tThemeControlEnable(pThis->m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK, TRUE);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"No update available.\");\n\t\t}\n\nLExit:\n\t\tReleaseObject(pixd);\n\t\tReleaseObject(pNode);\n\t\tReleaseStr(sczUpdateUrl);\n\n\t\treturn 0;\n\t}\n\n\n\t//\n\t// InitializeData - initializes all the package and prereq information.\n\t//\n\tHRESULT InitializeData()\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tLPWSTR sczModulePath = NULL;\n\t\tIXMLDOMDocument *pixdManifest = NULL;\n\n\t\thr = BalManifestLoad(m_hModule, &pixdManifest);\n\t\tBalExitOnFailure(hr, \"Failed to load bootstrapper application manifest.\");\n\n\t\thr = ParseOverridableVariablesFromXml(pixdManifest);\n\t\tBalExitOnFailure(hr, \"Failed to read overridable variables.\");\n\n\t\thr = ProcessCommandLine(&m_sczLanguage);\n\t\tExitOnFailure(hr, \"Unknown commandline parameters.\");\n\n\t\t// Override default language to correctly support UK English (this is not required in WiX 3.8)\n\t\tif (!(m_sczLanguage && *m_sczLanguage))\n\t\t{\n\t\t\thr = StrAllocFormatted(&m_sczLanguage, L\"%u\", ::GetUserDefaultLangID());\n\t\t\tBalExitOnFailure(hr, \"Failed to set language.\");\n\t\t}\n\n\t\thr = PathRelativeToModule(&sczModulePath, NULL, m_hModule);\n\t\tBalExitOnFailure(hr, \"Failed to get module path.\");\n\n\t\thr = LoadLocalization(sczModulePath, m_sczLanguage);\n\t\tExitOnFailure(hr, \"Failed to load localization.\");\n\n\t\thr = LoadTheme(sczModulePath, m_sczLanguage);\n\t\tExitOnFailure(hr, \"Failed to load theme.\");\n\n\t\thr = BalInfoParseFromXml(&m_Bundle, pixdManifest);\n\t\tBalExitOnFailure(hr, \"Failed to load bundle information.\");\n\n\t\thr = BalConditionsParseFromXml(&m_Conditions, pixdManifest, m_pWixLoc);\n\t\tBalExitOnFailure(hr, \"Failed to load conditions from XML.\");\n\n\t\tLoadBootstrapperBAFunctions();\n\n\t\thr = ParseBootrapperApplicationDataFromXml(pixdManifest);\n\t\tBalExitOnFailure(hr, \"Failed to read bootstrapper application data.\");\n\n\t\tLOC_STRING* pLocString = NULL;\n\t\tLocGetString(m_pWixLoc, L\"#(loc.ProgressHeader)\", &pLocString);\n\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_HEADER, pLocString->wzText);\n\t\tLocGetString(m_pWixLoc, L\"#(loc.ProgressInfo)\", &pLocString);\n\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_INFO, pLocString->wzText);\n\t\tLocGetString(m_pWixLoc, L\"#(loc.SuccessHeader)\", &pLocString);\n\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_HEADER, pLocString->wzText);\n\t\tLocGetString(m_pWixLoc, L\"#(loc.SuccessInfo)\", &pLocString);\n\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_INFO, pLocString->wzText);\n\t\tLocGetString(m_pWixLoc, L\"#(loc.FailureHeader)\", &pLocString);\n\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_FAILURE_HEADER, pLocString->wzText);\n\t\tif (m_fPrereq)\n\t\t{\n\t\t\thr = ParsePrerequisiteInformationFromXml(pixdManifest);\n\t\t\tBalExitOnFailure(hr, \"Failed to read prerequisite information.\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\thr = ParseBootrapperApplicationDataFromXml(pixdManifest);\n\t\t\tBalExitOnFailure(hr, \"Failed to read bootstrapper application data.\");\n\t\t}\n\n\t\tif (m_fOutputToConsole)\n\t\t{\n\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Write to console command was detected! Trying to attach to the parent console process\");\n\t\t\tBOOL bAttCons = AttachConsole(ATTACH_PARENT_PROCESS);\n\n\t\t\tif (!bAttCons)\n\t\t\t{\n\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Failed to attach to parent process.\");\n\t\t\t}\n\n\t\t\tif (bAttCons)\n\t\t\t{\n\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Successfully attached to parent console process.\");\n\t\t\t\tm_fStdConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);\n\t\t\t\tm_fAttachedToConsole = ((m_fStdConsoleHandle != NULL) && (m_fStdConsoleHandle != INVALID_HANDLE_VALUE));\n\t\t\t\tif (!m_fAttachedToConsole)\n\t\t\t\t{\n\t\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Failed to get the console handle\");\n\t\t\t\t\tFreeConsole();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!m_fAttachedToConsole)\n\t\t\t{\n\t\t\t\thr = E_UNEXPECTED;\n\t\t\t\tBalExitOnFailure(hr, \"Failed to setup console output. Setup will exit now!\");\n\t\t\t}\n\t\t}\n\n\nLExit:\n\t\tReleaseObject(pixdManifest);\n\t\tReleaseStr(sczModulePath);\n\n\t\treturn hr;\n\t}\n\n\n\t//\n\t// ProcessCommandLine - process the provided command line arguments.\n\t//\n\tHRESULT ProcessCommandLine(\n\t\t__inout LPWSTR* psczLanguage\n\t\t)\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tint argc = 0;\n\t\tLPWSTR* argv = NULL;\n\t\tLPWSTR sczVariableName = NULL;\n\t\tLPWSTR sczVariableValue = NULL;\n\n\t\tif (m_command.wzCommandLine && *m_command.wzCommandLine)\n\t\t{\n\t\t\targv = ::CommandLineToArgvW(m_command.wzCommandLine, &argc);\n\t\t\tExitOnNullWithLastError(argv, hr, \"Failed to get command line.\");\n\n\t\t\tfor (int i = 0; i < argc; ++i)\n\t\t\t{\n\t\t\t\tif (argv[i][0] == L'-' || argv[i][0] == L'/')\n\t\t\t\t{\n\t\t\t\t\tif (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L\"lang\", -1))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (i + 1 >= argc)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\thr = E_INVALIDARG;\n\t\t\t\t\t\t\tBalExitOnFailure(hr, \"Must specify a language.\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t++i;\n\n\t\t\t\t\t\thr = StrAllocString(psczLanguage, &argv[i][0], 0);\n\t\t\t\t\t\tBalExitOnFailure(hr, \"Failed to copy language.\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L\"toconsole\", -1))\n\t\t\t\t{\n\t\t\t\t\tm_fOutputToConsole = TRUE;\n\t\t\t\t\tm_command.display = BOOTSTRAPPER_DISPLAY_NONE;\n\t\t\t\t\tif (BOOTSTRAPPER_RESTART_UNKNOWN == m_command.restart)\n\t\t\t\t\t{\n\t\t\t\t\t\tm_command.restart = BOOTSTRAPPER_RESTART_AUTOMATIC;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (m_sdOverridableVariables)\n\t\t\t\t{\n\t\t\t\t\tconst wchar_t* pwc = wcschr(argv[i], L'=');\n\t\t\t\t\tif (pwc)\n\t\t\t\t\t{\n\t\t\t\t\t\thr = StrAllocString(&sczVariableName, argv[i], pwc - argv[i]);\n\t\t\t\t\t\tBalExitOnFailure(hr, \"Failed to copy variable name.\");\n\n\t\t\t\t\t\thr = DictKeyExists(m_sdOverridableVariables, sczVariableName);\n\t\t\t\t\t\tif (E_NOTFOUND == hr)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, \"Ignoring attempt to set non-overridable variable: '%ls'.\", sczVariableName);\n\t\t\t\t\t\t\thr = S_OK;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tExitOnFailure(hr, \"Failed to check the dictionary of overridable variables.\");\n\n\t\t\t\t\t\thr = StrAllocString(&sczVariableValue, ++pwc, 0);\n\t\t\t\t\t\tBalExitOnFailure(hr, \"Failed to copy variable value.\");\n\n\t\t\t\t\t\thr = m_pEngine->SetVariableString(sczVariableName, sczVariableValue);\n\t\t\t\t\t\tBalExitOnFailure(hr, \"Failed to set variable.\");\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Ignoring unknown argument: %ls\", argv[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\nLExit:\n\t\tif (argv)\n\t\t{\n\t\t\t::LocalFree(argv);\n\t\t}\n\n\t\tReleaseStr(sczVariableName);\n\t\tReleaseStr(sczVariableValue);\n\n\t\treturn hr;\n\t}\n\n\tHRESULT LoadLocalization(\n\t\t__in_z LPCWSTR wzModulePath,\n\t\t__in_z_opt LPCWSTR wzLanguage\n\t\t)\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tLPWSTR sczLocPath = NULL;\n\t\tLPCWSTR wzLocFileName = L\"thm.wxl\";\n\n\t\thr = LocProbeForFile(wzModulePath, wzLocFileName, wzLanguage, &sczLocPath);\n\t\tBalExitOnFailure2(hr, \"Failed to probe for loc file: %ls in path: %ls\", wzLocFileName, wzModulePath);\n\n\t\thr = LocLoadFromFile(sczLocPath, &m_pWixLoc);\n\t\tBalExitOnFailure1(hr, \"Failed to load loc file from path: %ls\", sczLocPath);\n\n\t\tif (WIX_LOCALIZATION_LANGUAGE_NOT_SET != m_pWixLoc->dwLangId)\n\t\t{\n\t\t\t::SetThreadLocale(m_pWixLoc->dwLangId);\n\t\t}\n\n\t\thr = StrAllocString(&m_sczConfirmCloseMessage, L\"#(loc.ConfirmCancelMessage)\", 0);\n\t\tExitOnFailure(hr, \"Failed to initialize confirm message loc identifier.\");\n\n\t\thr = LocLocalizeString(m_pWixLoc, &m_sczConfirmCloseMessage);\n\t\tBalExitOnFailure1(hr, \"Failed to localize confirm close message: %ls\", m_sczConfirmCloseMessage);\n\nLExit:\n\t\tReleaseStr(sczLocPath);\n\n\t\treturn hr;\n\t}\n\n\n\tHRESULT LoadTheme(\n\t\t__in_z LPCWSTR wzModulePath,\n\t\t__in_z_opt LPCWSTR wzLanguage\n\t\t)\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tLPWSTR sczThemePath = NULL;\n\t\tLPCWSTR wzThemeFileName = L\"thm.xml\";\n\t\tLPWSTR sczCaption = NULL;\n\n\t\thr = LocProbeForFile(wzModulePath, wzThemeFileName, wzLanguage, &sczThemePath);\n\t\tBalExitOnFailure2(hr, \"Failed to probe for theme file: %ls in path: %ls\", wzThemeFileName, wzModulePath);\n\n\t\thr = ThemeLoadFromFile(sczThemePath, &m_pTheme);\n\t\tBalExitOnFailure1(hr, \"Failed to load theme from path: %ls\", sczThemePath);\n\n\t\thr = ThemeLocalize(m_pTheme, m_pWixLoc);\n\t\tBalExitOnFailure1(hr, \"Failed to localize theme: %ls\", sczThemePath);\n\n\t\t// Update the caption if there are any formatted strings in it.\n\t\thr = BalFormatString(m_pTheme->sczCaption, &sczCaption);\n\t\tif (SUCCEEDED(hr))\n\t\t{\n\t\t\tThemeUpdateCaption(m_pTheme, sczCaption);\n\t\t}\n\nLExit:\n\t\tReleaseStr(sczCaption);\n\t\tReleaseStr(sczThemePath);\n\n\t\treturn hr;\n\t}\n\n\n\tHRESULT ParseOverridableVariablesFromXml(\n\t\t__in IXMLDOMDocument* pixdManifest\n\t\t)\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tIXMLDOMNode* pNode = NULL;\n\t\tIXMLDOMNodeList* pNodes = NULL;\n\t\tDWORD cNodes = 0;\n\t\tLPWSTR scz = NULL;\n\n\t\t// get the list of variables users can override on the command line\n\t\thr = XmlSelectNodes(pixdManifest, L\"/BootstrapperApplicationData/WixStdbaOverridableVariable\", &pNodes);\n\t\tif (S_FALSE == hr)\n\t\t{\n\t\t\tExitFunction1(hr = S_OK);\n\t\t}\n\t\tExitOnFailure(hr, \"Failed to select overridable variable nodes.\");\n\n\t\thr = pNodes->get_length((long*)&cNodes);\n\t\tExitOnFailure(hr, \"Failed to get overridable variable node count.\");\n\n\t\tif (cNodes)\n\t\t{\n\t\t\thr = DictCreateStringList(&m_sdOverridableVariables, 32, DICT_FLAG_NONE);\n\t\t\tExitOnFailure(hr, \"Failed to create the string dictionary.\");\n\n\t\t\tfor (DWORD i = 0; i < cNodes; ++i)\n\t\t\t{\n\t\t\t\thr = XmlNextElement(pNodes, &pNode, NULL);\n\t\t\t\tExitOnFailure(hr, \"Failed to get next node.\");\n\n\t\t\t\t// @Name\n\t\t\t\thr = XmlGetAttributeEx(pNode, L\"Name\", &scz);\n\t\t\t\tExitOnFailure(hr, \"Failed to get @Name.\");\n\n\t\t\t\thr = DictAddKey(m_sdOverridableVariables, scz);\n\t\t\t\tExitOnFailure1(hr, \"Failed to add \\\"%ls\\\" to the string dictionary.\", scz);\n\n\t\t\t\t// prepare next iteration\n\t\t\t\tReleaseNullObject(pNode);\n\t\t\t}\n\t\t}\n\nLExit:\n\t\tReleaseObject(pNode);\n\t\tReleaseObject(pNodes);\n\t\tReleaseStr(scz);\n\t\treturn hr;\n\t}\n\n\n\tHRESULT ParsePrerequisiteInformationFromXml(\n\t\t__in IXMLDOMDocument* pixdManifest\n\t\t)\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tIXMLDOMNode* pNode = NULL;\n\n\t\thr = XmlSelectSingleNode(pixdManifest, L\"/BootstrapperApplicationData/WixMbaPrereqInformation\", &pNode);\n\t\tif (S_FALSE == hr)\n\t\t{\n\t\t\thr = E_INVALIDARG;\n\t\t}\n\t\tBalExitOnFailure(hr, \"BootstrapperApplication.xml manifest is missing prerequisite information.\");\n\n\t\thr = XmlGetAttributeEx(pNode, L\"PackageId\", &m_sczPrereqPackage);\n\t\tBalExitOnFailure(hr, \"Failed to get prerequisite package identifier.\");\n\n\t\thr = XmlGetAttributeEx(pNode, L\"LicenseUrl\", &m_sczLicenseUrl);\n\t\tif (E_NOTFOUND == hr)\n\t\t{\n\t\t\thr = S_OK;\n\t\t}\n\t\tBalExitOnFailure(hr, \"Failed to get prerequisite license URL.\");\n\n\t\thr = XmlGetAttributeEx(pNode, L\"LicenseFile\", &m_sczLicenseFile);\n\t\tif (E_NOTFOUND == hr)\n\t\t{\n\t\t\thr = S_OK;\n\t\t}\n\t\tBalExitOnFailure(hr, \"Failed to get prerequisite license file.\");\n\nLExit:\n\t\tReleaseObject(pNode);\n\t\treturn hr;\n\t}\n\n\n\tHRESULT ParseBootrapperApplicationDataFromXml(\n\t\t__in IXMLDOMDocument* pixdManifest\n\t\t)\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tIXMLDOMNode* pNode = NULL;\n\t\tDWORD dwBool = 0;\n\n\t\thr = XmlSelectSingleNode(pixdManifest, L\"/BootstrapperApplicationData/WixExtbaInformation\", &pNode);\n\t\tif (S_FALSE == hr)\n\t\t{\n\t\t\thr = E_INVALIDARG;\n\t\t}\n\t\tBalExitOnFailure(hr, \"BootstrapperApplication.xml manifest is missing wixextba information.\");\n\n\t\thr = XmlGetAttributeEx(pNode, L\"LicenseFile\", &m_sczLicenseFile);\n\t\tif (E_NOTFOUND == hr)\n\t\t{\n\t\t\thr = S_OK;\n\t\t}\n\t\tBalExitOnFailure(hr, \"Failed to get license file.\");\n\n\t\thr = XmlGetAttributeEx(pNode, L\"LicenseUrl\", &m_sczLicenseUrl);\n\t\tif (E_NOTFOUND == hr)\n\t\t{\n\t\t\thr = S_OK;\n\t\t}\n\t\tBalExitOnFailure(hr, \"Failed to get license URL.\");\n\n\t\tReleaseObject(pNode);\n\n\t\thr = XmlSelectSingleNode(pixdManifest, L\"/BootstrapperApplicationData/WixExtbaOptions\", &pNode);\n\t\tif (S_FALSE == hr)\n\t\t{\n\t\t\tExitFunction1(hr = S_OK);\n\t\t}\n\t\tBalExitOnFailure(hr, \"Failed to read wixextba options from BootstrapperApplication.xml manifest.\");\n\n\t\thr = XmlGetAttributeNumber(pNode, L\"SuppressOptionsUI\", &dwBool);\n\t\tif (E_NOTFOUND == hr)\n\t\t{\n\t\t\thr = S_OK;\n\t\t}\n\t\telse if (SUCCEEDED(hr))\n\t\t{\n\t\t\tm_fSuppressOptionsUI = 0 < dwBool;\n\t\t}\n\t\tBalExitOnFailure(hr, \"Failed to get SuppressOptionsUI value.\");\n\n\t\tdwBool = 0;\n\t\thr = XmlGetAttributeNumber(pNode, L\"SuppressDowngradeFailure\", &dwBool);\n\t\tif (E_NOTFOUND == hr)\n\t\t{\n\t\t\thr = S_OK;\n\t\t}\n\t\telse if (SUCCEEDED(hr))\n\t\t{\n\t\t\tm_fSuppressDowngradeFailure = 0 < dwBool;\n\t\t}\n\t\tBalExitOnFailure(hr, \"Failed to get SuppressDowngradeFailure value.\");\n\n\t\tdwBool = 0;\n\t\thr = XmlGetAttributeNumber(pNode, L\"SuppressRepair\", &dwBool);\n\t\tif (E_NOTFOUND == hr)\n\t\t{\n\t\t\thr = S_OK;\n\t\t}\n\t\telse if (SUCCEEDED(hr))\n\t\t{\n\t\t\tm_fSuppressRepair = 0 < dwBool;\n\t\t}\n\t\tBalExitOnFailure(hr, \"Failed to get SuppressRepair value.\");\n\n\t\thr = XmlGetAttributeNumber(pNode, L\"ShowVersion\", &dwBool);\n\t\tif (E_NOTFOUND == hr)\n\t\t{\n\t\t\thr = S_OK;\n\t\t}\n\t\telse if (SUCCEEDED(hr))\n\t\t{\n\t\t\tm_fShowVersion = 0 < dwBool;\n\t\t}\n\t\tBalExitOnFailure(hr, \"Failed to get ShowVersion value.\");\n\nLExit:\n\t\tReleaseObject(pNode);\n\t\treturn hr;\n\t}\n\n\n\t//\n\t// CreateMainWindow - creates the main install window.\n\t//\n\tHRESULT CreateMainWindow()\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tHICON hIcon = reinterpret_cast<HICON>(m_pTheme->hIcon);\n\t\tWNDCLASSW wc = { };\n\t\tDWORD dwWindowStyle = 0;\n\t\tint x = CW_USEDEFAULT;\n\t\tint y = CW_USEDEFAULT;\n\t\tPOINT ptCursor = { };\n\t\tHMONITOR hMonitor = NULL;\n\t\tMONITORINFO mi = { };\n\n\t\t// If the theme did not provide an icon, try using the icon from the bundle engine.\n\t\tif (!hIcon)\n\t\t{\n\t\t\tHMODULE hBootstrapperEngine = ::GetModuleHandleW(NULL);\n\t\t\tif (hBootstrapperEngine)\n\t\t\t{\n\t\t\t\thIcon = ::LoadIconW(hBootstrapperEngine, MAKEINTRESOURCEW(1));\n\t\t\t}\n\t\t}\n\n\t\t// Register the window class and create the window.\n\t\twc.lpfnWndProc = CWixStandardBootstrapperApplication::WndProc;\n\t\twc.hInstance = m_hModule;\n\t\twc.hIcon = hIcon;\n\t\twc.hCursor = ::LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);\n\t\twc.hbrBackground = m_pTheme->rgFonts[m_pTheme->dwFontId].hBackground;\n\t\twc.lpszMenuName = NULL;\n\t\twc.lpszClassName = WIXSTDBA_WINDOW_CLASS;\n\t\tif (!::RegisterClassW(&wc))\n\t\t{\n\t\t\tExitWithLastError(hr, \"Failed to register window.\");\n\t\t}\n\n\t\tm_fRegistered = TRUE;\n\n\t\t// Calculate the window style based on the theme style and command display value.\n\t\tdwWindowStyle = m_pTheme->dwStyle;\n\t\tif (BOOTSTRAPPER_DISPLAY_NONE >= m_command.display)\n\t\t{\n\t\t\tdwWindowStyle &= ~WS_VISIBLE;\n\t\t}\n\n\t\t// Don't show the window if there is a splash screen (it will be made visible when the splash screen is hidden)\n\t\tif (::IsWindow(m_command.hwndSplashScreen))\n\t\t{\n\t\t\tdwWindowStyle &= ~WS_VISIBLE;\n\t\t}\n\n\t\t// Center the window on the monitor with the mouse.\n\t\tif (::GetCursorPos(&ptCursor))\n\t\t{\n\t\t\thMonitor = ::MonitorFromPoint(ptCursor, MONITOR_DEFAULTTONEAREST);\n\t\t\tif (hMonitor)\n\t\t\t{\n\t\t\t\tmi.cbSize = sizeof(mi);\n\t\t\t\tif (::GetMonitorInfoW(hMonitor, &mi))\n\t\t\t\t{\n\t\t\t\t\tx = mi.rcWork.left + (mi.rcWork.right  - mi.rcWork.left - m_pTheme->nWidth) / 2;\n\t\t\t\t\ty = mi.rcWork.top  + (mi.rcWork.bottom - mi.rcWork.top  - m_pTheme->nHeight) / 2;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tm_hWnd = ::CreateWindowExW(0, wc.lpszClassName, m_pTheme->sczCaption, dwWindowStyle, x, y, m_pTheme->nWidth, m_pTheme->nHeight, HWND_DESKTOP, NULL, m_hModule, this);\n\t\tExitOnNullWithLastError(m_hWnd, hr, \"Failed to create window.\");\n\n\t\thr = S_OK;\n\nLExit:\n\t\treturn hr;\n\t}\n\n\n\t//\n\t// InitializeTaskbarButton - initializes taskbar button for progress.\n\t//\n\tvoid InitializeTaskbarButton()\n\t{\n\t\tHRESULT hr = S_OK;\n\n\t\thr = ::CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_ALL, __uuidof(ITaskbarList3), reinterpret_cast<LPVOID*>(&m_pTaskbarList));\n\t\tif (REGDB_E_CLASSNOTREG == hr) // not supported before Windows 7\n\t\t{\n\t\t\tExitFunction1(hr = S_OK);\n\t\t}\n\t\tBalExitOnFailure(hr, \"Failed to create ITaskbarList3. Continuing.\");\n\n\t\tm_uTaskbarButtonCreatedMessage = ::RegisterWindowMessageW(L\"TaskbarButtonCreated\");\n\t\tBalExitOnNullWithLastError(m_uTaskbarButtonCreatedMessage, hr, \"Failed to get TaskbarButtonCreated message. Continuing.\");\n\nLExit:\n\t\treturn;\n\t}\n\n\t//\n\t// DestroyMainWindow - clean up all the window registration.\n\t//\n\tvoid DestroyMainWindow()\n\t{\n\t\tif (::IsWindow(m_hWnd))\n\t\t{\n\t\t\t::DestroyWindow(m_hWnd);\n\t\t\tm_hWnd = NULL;\n\t\t\tm_fTaskbarButtonOK = FALSE;\n\t\t}\n\n\t\tif (m_fRegistered)\n\t\t{\n\t\t\t::UnregisterClassW(WIXSTDBA_WINDOW_CLASS, m_hModule);\n\t\t\tm_fRegistered = FALSE;\n\t\t}\n\t}\n\n\n\t//\n\t// WndProc - standard windows message handler.\n\t//\n\tstatic LRESULT CALLBACK WndProc(\n\t\t__in HWND hWnd,\n\t\t__in UINT uMsg,\n\t\t__in WPARAM wParam,\n\t\t__in LPARAM lParam\n\t\t)\n\t{\n#pragma warning(suppress:4312)\n\t\tCWixStandardBootstrapperApplication* pBA = reinterpret_cast<CWixStandardBootstrapperApplication*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));\n\n\t\tswitch (uMsg)\n\t\t{\n\t\tcase WM_NCCREATE:\n\t\t\t{\n\t\t\t\tLPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);\n\t\t\t\tpBA = reinterpret_cast<CWixStandardBootstrapperApplication*>(lpcs->lpCreateParams);\n#pragma warning(suppress:4244)\n\t\t\t\t::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pBA));\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_NCDESTROY:\n\t\t\t{\n\t\t\t\tLRESULT lres = ThemeDefWindowProc(pBA ? pBA->m_pTheme : NULL, hWnd, uMsg, wParam, lParam);\n\t\t\t\t::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0);\n\t\t\t\treturn lres;\n\t\t\t}\n\n\t\tcase WM_CREATE:\n\t\t\tif (!pBA->OnCreate(hWnd))\n\t\t\t{\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_QUERYENDSESSION:\n\t\t\treturn IDCANCEL != pBA->OnSystemShutdown(static_cast<DWORD>(lParam), IDCANCEL);\n\n\t\tcase WM_CLOSE:\n\t\t\t// If the user chose not to close, do *not* let the default window proc handle the message.\n\t\t\tif (!pBA->OnClose())\n\t\t\t{\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_DESTROY:\n\t\t\t::PostQuitMessage(0);\n\t\t\tbreak;\n\n\t\tcase WM_WIXSTDBA_SHOW_HELP:\n\t\t\tpBA->OnShowHelp();\n\t\t\treturn 0;\n\n\t\tcase WM_WIXSTDBA_DETECT_PACKAGES:\n\t\t\tpBA->OnDetect();\n\t\t\treturn 0;\n\n\t\tcase WM_WIXSTDBA_PLAN_PACKAGES:\n\t\t\tpBA->OnPlan(static_cast<BOOTSTRAPPER_ACTION>(lParam));\n\t\t\treturn 0;\n\n\t\tcase WM_WIXSTDBA_APPLY_PACKAGES:\n\t\t\tpBA->OnApply();\n\t\t\treturn 0;\n\n\t\tcase WM_WIXSTDBA_CHANGE_STATE:\n\t\t\tpBA->OnChangeState(static_cast<WIXSTDBA_STATE>(lParam));\n\t\t\treturn 0;\n\n\t\tcase WM_COMMAND:\n\t\t\tswitch (LOWORD(wParam))\n\t\t\t{\n\t\t\tcase WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX:\n\t\t\t\tpBA->OnClickAcceptCheckbox();\n\t\t\t\treturn 0;\n\n\t\t\tcase WIXSTDBA_CONTROL_PERMACHINE_RADIO: __fallthrough;\n\t\t\tcase WIXSTDBA_CONTROL_PERUSER_RADIO:\n\t\t\t\tpBA->OnClickInstallScope();\n\t\t\t\treturn 0;\n\n\t\t\tcase WIXSTDBA_CONTROL_REGSIGNIN_RADIO: __fallthrough;\n\t\t\tcase WIXSTDBA_CONTROL_REGCREATE_RADIO: __fallthrough;\n\t\t\tcase WIXSTDBA_CONTROL_SKIPREG_CHECKBOX:\n\t\t\t\tpBA->OnClickSkipRegistrationCheckbox();\n\t\t\t\treturn 0;\n\n\n\t\t\tcase WIXSTDBA_CONTROL_OPTIONS_BUTTON:\n\t\t\t\tpBA->OnClickOptionsButton();\n\t\t\t\treturn 0;\n\n\t\t\tcase WIXSTDBA_CONTROL_BROWSE_BUTTON:\n\t\t\t\tpBA->OnClickOptionsBrowseButton(WIXSTDBA_CONTROL_BROWSE_BUTTON);\n\t\t\t\treturn 0;\n\n\t\t\tcase WIXSTDBA_CONTROL_OK_BUTTON:\n\t\t\t\tpBA->OnClickOptionsOkButton();\n\t\t\t\treturn 0;\n\n\t\t\tcase WIXSTDBA_CONTROL_CANCEL_BUTTON:\n\t\t\t\tpBA->OnClickOptionsCancelButton();\n\t\t\t\treturn 0;\n\n\t\t\tcase WIXSTDBA_CONTROL_SKIP_BUTTON:\n \t\t\t\tpBA->SetState(WIXSTDBA_STATE_APPLIED, S_OK);\n\t\t\t\treturn 0;\n\n\t\t\tcase WIXSTDBA_CONTROL_INSTALL_BUTTON:\n\t\t\t\tpBA->OnSignIn();\n\t\t\t\treturn 0;\n\n\t\t\tcase WIXSTDBA_CONTROL_REPAIR_BUTTON:\n\t\t\t\tpBA->OnClickRepairButton();\n\t\t\t\treturn 0;\n\n\t\t\tcase WIXSTDBA_CONTROL_UNINSTALL_BUTTON:\n\t\t\t\tpBA->OnClickUninstallButton();\n\t\t\t\treturn 0;\n\n\t\t\tcase WIXSTDBA_CONTROL_LAUNCH_BUTTON:\n\t\t\t\tpBA->OnClickLaunchButton();\n\t\t\t\treturn 0;\n\n\t\t\tcase WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON: __fallthrough;\n\t\t\tcase WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON:\n\t\t\t\tpBA->OnClickRestartButton();\n\t\t\t\treturn 0;\n\n\t\t\tcase WIXSTDBA_CONTROL_HELP_CANCEL_BUTTON: __fallthrough;\n\n\t\t\tcase WIXSTDBA_CONTROL_WELCOME_CANCEL_BUTTON: __fallthrough;\n\t\t\tcase WIXSTDBA_CONTROL_MODIFY_CANCEL_BUTTON: __fallthrough;\n\t\t\tcase WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON: __fallthrough;\n\t\t\tcase WIXSTDBA_CONTROL_SUCCESS_CANCEL_BUTTON: __fallthrough;\n\t\t\tcase WIXSTDBA_CONTROL_FAILURE_CANCEL_BUTTON: __fallthrough;\n\t\t\tcase WIXSTDBA_CONTROL_CLOSE_BUTTON:\n\t\t\t\tpBA->OnClickCloseButton();\n\t\t\t\treturn 0;\n\t\t\tcase WIXSTDBA_CONTROL_NEXT_BUTTON:\n\t\t\t\tpBA->OnClickNextButton();\n\t\t\t\treturn 0;\n\t\t\tcase WIXSTDBA_CONTROL_BACK_BUTTON:\n\t\t\t\tpBA->OnClickBackButton();\n\t\t\t\treturn 0;\n\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_NOTIFY:\n\t\t\tif (lParam)\n\t\t\t{\n\t\t\t\tLPNMHDR pnmhdr = reinterpret_cast<LPNMHDR>(lParam);\n\t\t\t\tswitch (pnmhdr->code)\n\t\t\t\t{\n\t\t\t\tcase NM_CLICK: __fallthrough;\n\t\t\t\tcase NM_RETURN:\n\t\t\t\t\tswitch (static_cast<DWORD>(pnmhdr->idFrom))\n\t\t\t\t\t{\n\t\t\t\t\tcase WIXSTDBA_CONTROL_EULA_LINK:\n\t\t\t\t\t\tpBA->OnClickEulaLink();\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\tcase WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK:\n\t\t\t\t\t\tpBA->OnClickLogFileLink();\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\tcase WIXSTDBA_CONTROL_UPGRADE_LINK:\n\t\t\t\t\t\tpBA->OnClickUpgradeLink();\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tif (pBA && pBA->m_pTaskbarList && uMsg == pBA->m_uTaskbarButtonCreatedMessage)\n\t\t{\n\t\t\tpBA->m_fTaskbarButtonOK = TRUE;\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn ThemeDefWindowProc(pBA ? pBA->m_pTheme : NULL, hWnd, uMsg, wParam, lParam);\n\t}\n\n\n\t//\n\t// OnCreate - finishes loading the theme.\n\t//\n\tBOOL OnCreate(\n\t\t__in HWND hWnd\n\t\t)\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tLPWSTR sczText = NULL;\n\t\tLPWSTR sczLicenseFormatted = NULL;\n\t\tLPWSTR sczLicensePath = NULL;\n\t\tLPWSTR sczLicenseDirectory = NULL;\n\t\tLPWSTR sczLicenseFilename = NULL;\n\n\t\thr = ThemeLoadControls(m_pTheme, hWnd, vrgInitControls, countof(vrgInitControls));\n\t\tBalExitOnFailure(hr, \"Failed to load theme controls.\");\n\n\t\tC_ASSERT(COUNT_WIXSTDBA_PAGE == countof(vrgwzPageNames));\n\t\tC_ASSERT(countof(m_rgdwPageIds) == countof(vrgwzPageNames));\n\n\t\tThemeGetPageIds(m_pTheme, vrgwzPageNames, m_rgdwPageIds, countof(m_rgdwPageIds));\n\n\t\t// Initialize the text on all \"application\" (non-page) controls.\n\t\tfor (DWORD i = 0; i < m_pTheme->cControls; ++i)\n\t\t{\n\t\t\tTHEME_CONTROL* pControl = m_pTheme->rgControls + i;\n\t\t\tif (!pControl->wPageId && pControl->sczText && *pControl->sczText)\n\t\t\t{\n\t\t\t\tHRESULT hrFormat = BalFormatString(pControl->sczText, &sczText);\n\t\t\t\tif (SUCCEEDED(hrFormat))\n\t\t\t\t{\n\t\t\t\t\tThemeSetTextControl(m_pTheme, pControl->wId, sczText);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Load the RTF EULA control with text if the control exists.\n\t\tif (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_RICHEDIT))\n\t\t{\n\t\t\thr = (m_sczLicenseFile && *m_sczLicenseFile) ? S_OK : E_INVALIDDATA;\n\t\t\tif (SUCCEEDED(hr))\n\t\t\t{\n\t\t\t\thr = StrAllocString(&sczLicenseFormatted, m_sczLicenseFile, 0);\n\t\t\t\tif (SUCCEEDED(hr))\n\t\t\t\t{\n\t\t\t\t\thr = LocLocalizeString(m_pWixLoc, &sczLicenseFormatted);\n\t\t\t\t\tif (SUCCEEDED(hr))\n\t\t\t\t\t{\n\t\t\t\t\t\thr = BalFormatString(sczLicenseFormatted, &sczLicenseFormatted);\n\t\t\t\t\t\tif (SUCCEEDED(hr))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\thr = PathRelativeToModule(&sczLicensePath, sczLicenseFormatted, m_hModule);\n\t\t\t\t\t\t\tif (SUCCEEDED(hr))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\thr = PathGetDirectory(sczLicensePath, &sczLicenseDirectory);\n\t\t\t\t\t\t\t\tif (SUCCEEDED(hr))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\thr = StrAllocString(&sczLicenseFilename, PathFile(sczLicenseFormatted), 0);\n\t\t\t\t\t\t\t\t\tif (SUCCEEDED(hr))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\thr = LocProbeForFile(sczLicenseDirectory, sczLicenseFilename, m_sczLanguage, &sczLicensePath);\n\t\t\t\t\t\t\t\t\t\tif (SUCCEEDED(hr))\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\thr = ThemeLoadRichEditFromFile(m_pTheme, WIXSTDBA_CONTROL_EULA_RICHEDIT, sczLicensePath, m_hModule);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (FAILED(hr))\n\t\t\t{\n\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, \"Failed to load file into license richedit control from path '%ls' manifest value: %ls\", sczLicensePath, m_sczLicenseFile);\n\t\t\t\thr = S_OK;\n\t\t\t}\n\t\t}\n\nLExit:\n\t\tReleaseStr(sczLicenseFilename);\n\t\tReleaseStr(sczLicenseDirectory);\n\t\tReleaseStr(sczLicensePath);\n\t\tReleaseStr(sczLicenseFormatted);\n\t\tReleaseStr(sczText);\n\n\t\treturn SUCCEEDED(hr);\n\t}\n\n\n\t//\n\t// OnShowHelp - display the help page.\n\t//\n\tvoid OnShowHelp()\n\t{\n\t\tSetState(WIXSTDBA_STATE_HELP, S_OK);\n\n\t\t// If the UI should be visible, display it now and hide the splash screen\n\t\tif (BOOTSTRAPPER_DISPLAY_NONE < m_command.display)\n\t\t{\n\t\t\t::ShowWindow(m_pTheme->hwndParent, SW_SHOW);\n\t\t}\n\n\t\tm_pEngine->CloseSplashScreen();\n\n\t\treturn;\n\t}\n\n\n\t//\n\t// OnDetect - start the processing of packages.\n\t//\n\tvoid OnDetect()\n\t{\n\t\tHRESULT hr = S_OK;\n\n\t\tif (m_pBAFunction)\n\t\t{\n\t\t\thr = m_pBAFunction->OnDetect();\n\t\t\tBalExitOnFailure(hr, \"Failed calling detect BA function.\");\n\t\t}\n\n\t\tSetState(WIXSTDBA_STATE_DETECTING, hr);\n\n\t\t// If the UI should be visible, display it now and hide the splash screen\n\t\tif (BOOTSTRAPPER_DISPLAY_NONE < m_command.display)\n\t\t{\n\t\t\t::ShowWindow(m_pTheme->hwndParent, SW_SHOW);\n\t\t}\n\n\t\tm_pEngine->CloseSplashScreen();\n\n\t\t// Tell the core we're ready for the packages to be processed now.\n\t\thr = m_pEngine->Detect();\n\t\tBalExitOnFailure(hr, \"Failed to start detecting chain.\");\n\nLExit:\n\t\tif (FAILED(hr))\n\t\t{\n\t\t\tSetState(WIXSTDBA_STATE_DETECTING, hr);\n\t\t}\n\n\t\treturn;\n\t}\n\n\n\t//\n\t// OnPlan - plan the detected changes.\n\t//\n\tvoid OnPlan(\n\t\t__in BOOTSTRAPPER_ACTION action\n\t\t)\n\t{\n\t\tHRESULT hr = S_OK;\n\n\t\tm_plannedAction = action;\n\n\t\tLOC_STRING* pLocString = NULL;\n\n\t\tif (m_plannedAction == BOOTSTRAPPER_ACTION_UNINSTALL)\n\t\t{\n\t\t\tm_fIsUninstall = TRUE;\n\t\t\tLocGetString(m_pWixLoc, L\"#(loc.ProgressHeaderUninstall)\", &pLocString);\n\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_HEADER, pLocString->wzText);\n\t\t\tLocGetString(m_pWixLoc, L\"#(loc.ProgressInfoUninstall)\", &pLocString);\n\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_INFO, pLocString->wzText);\n\t\t}\n\n\t\tif (m_plannedAction == BOOTSTRAPPER_ACTION_REPAIR)\n\t\t{\n\t\t\tm_fIsRepair = TRUE;\n\t\t\tLocGetString(m_pWixLoc, L\"#(loc.ProgressHeaderRepair)\", &pLocString);\n\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_HEADER, pLocString->wzText);\n\t\t\tLocGetString(m_pWixLoc, L\"#(loc.ProgressInfoRepair)\", &pLocString);\n\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_INFO, pLocString->wzText);\n\t\t}\n\n\t\t// If we are going to apply a downgrade, bail.\n\t\tif (m_fDowngrading && BOOTSTRAPPER_ACTION_UNINSTALL < action)\n\t\t{\n\t\t\tif (m_fSuppressDowngradeFailure)\n\t\t\t{\n\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"A newer version of this product is installed but downgrade failure has been suppressed; continuing...\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\thr = HRESULT_FROM_WIN32(ERROR_PRODUCT_VERSION);\n\t\t\t\tBalExitOnFailure(hr, \"Cannot install a product when a newer version is installed.\");\n\t\t\t}\n\t\t}\n\n\t\tSetState(WIXSTDBA_STATE_PLANNING, hr);\n\n\t\tif (m_pBAFunction)\n\t\t{\n\t\t\tm_pBAFunction->OnPlan();\n\t\t}\n\n\t\thr = m_pEngine->Plan(action);\n\t\tBalExitOnFailure(hr, \"Failed to start planning packages.\");\n\nLExit:\n\t\tif (FAILED(hr))\n\t\t{\n\t\t\tSetState(WIXSTDBA_STATE_PLANNING, hr);\n\t\t}\n\n\t\treturn;\n\t}\n\n\n\t//\n\t// OnApply - apply the packages.\n\t//\n\tvoid OnApply()\n\t{\n\t\tHRESULT hr = S_OK;\n\n\t\tSetState(WIXSTDBA_STATE_APPLYING, hr);\n\t\tSetProgressState(hr);\n\n\t\tif (m_fAttachedToConsole)\n\t\t{\n\t\t\tchar *szPgLine;\n\t\t\tif (m_fIsUninstall) {\n\t\t\t\tszPgLine = \"\\nInstalling...\\n\";\n\t\t\t} else {\n\t\t\t\tszPgLine = \"\\nUninstalling...\\n\";\n\t\t\t}\n\t\t\tDWORD dSzWritten;\n\t\t\tWriteConsole(m_fStdConsoleHandle, szPgLine, strlen(szPgLine), &dSzWritten, NULL);\n\t\t}\n\t\tSetTaskbarButtonProgress(0);\n\n\t\thr = m_pEngine->Apply(m_hWnd);\n\t\tBalExitOnFailure(hr, \"Failed to start applying packages.\");\n\n\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, TRUE); // ensure the cancel button is enabled before starting.\n\nLExit:\n\t\tif (FAILED(hr))\n\t\t{\n\t\t\tSetState(WIXSTDBA_STATE_APPLYING, hr);\n\t\t}\n\n\t\treturn;\n\t}\n\n\n\t//\n\t// OnChangeState - change state.\n\t//\n\tvoid OnChangeState(\n\t\t__in WIXSTDBA_STATE state\n\t\t)\n\t{\n\t\tWIXSTDBA_STATE stateOld = m_state;\n\t\tDWORD dwOldPageId = 0;\n\t\tDWORD dwNewPageId = 0;\n\t\tLPWSTR sczText = NULL;\n\t\tLPWSTR sczUnformattedText = NULL;\n\t\tLPWSTR sczControlState = NULL;\n\t\tLPWSTR sczControlName = NULL;\n\t\tLOC_STRING* pLocString = NULL;\n\t\tm_state = state;\n\n\t\t// If our install is at the end (success or failure) and we're not showing full UI or\n\t\t// we successfully installed the prerequisite then exit (prompt for restart if required).\n\t\tif ((WIXSTDBA_STATE_APPLIED <= m_state && BOOTSTRAPPER_DISPLAY_FULL > m_command.display) ||\n\t\t\t(WIXSTDBA_STATE_APPLIED == m_state && m_fPrereq))\n\t\t{\n\t\t\t// If a restart was required but we were not automatically allowed to\n\t\t\t// accept the reboot then do the prompt.\n\t\t\tif (m_fRestartRequired && !m_fAllowRestart)\n\t\t\t{\n\t\t\t\tStrAllocFromError(&sczUnformattedText, HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED), NULL);\n\n\t\t\t\tint nResult = ::MessageBoxW(m_hWnd, sczUnformattedText ? sczUnformattedText : L\"The requested operation is successful. Changes will not be effective until the system is rebooted.\", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OKCANCEL);\n\t\t\t\tm_fAllowRestart = (IDOK == nResult);\n\t\t\t}\n\n\t\t\t// Quietly exit.\n\t\t\t::PostMessageW(m_hWnd, WM_CLOSE, 0, 0);\n\t\t}\n\t\telse // try to change the pages.\n\t\t{\n\t\t\tDeterminePageId(stateOld, &dwOldPageId);\n\t\t\tDeterminePageId(m_state, &dwNewPageId);\n\n\t\t\tif (dwOldPageId != dwNewPageId)\n\t\t\t{\n\t\t\t\t// Enable disable controls per-page.\n\t\t\t\tif (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId) // on the \"Install\" page, ensure the install button is enabled/disabled correctly.\n\t\t\t\t{\n\t\t\t\t\tLONGLONG llElevated = 0;\n\t\t\t\t\tif (m_Bundle.fPerMachine)\n\t\t\t\t\t{\n\t\t\t\t\t\tBalGetNumericVariable(WIXBUNDLE_VARIABLE_ELEVATED, &llElevated);\n\t\t\t\t\t}\n\t\t\t\t\tThemeControlElevates(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, (m_Bundle.fPerMachine && !llElevated));\n\n\t\t\t\t\t// If the EULA control exists, show it only if a license URL is provided as well.\n\t\t\t\t\tif (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK))\n\t\t\t\t\t{\n\t\t\t\t\t\tBOOL fEulaLink = (m_sczLicenseUrl && *m_sczLicenseUrl);\n\t\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK, fEulaLink);\n\t\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, fEulaLink);\n\t\t\t\t\t}\n\n\t\t\t\t\tBOOL fAcceptedLicense = !ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || !ThemeControlEnabled(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX);\n\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense);\n\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_NEXT_BUTTON, fAcceptedLicense);\n\n\t\t\t\t\t// If there is an \"Options\" page, the \"Options\" button exists, and it hasn't been suppressed, then enable the button.\n\t\t\t\t\tBOOL fOptionsEnabled = m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR] && ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_BUTTON) && !m_fSuppressOptionsUI;\n\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_BUTTON, fOptionsEnabled);\n\n\t\t\t\t\t// Show/Hide the version label if it exists.\n\t\t\t\t\tif (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR] && ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_VERSION_LABEL) && !m_fShowVersion)\n\t\t\t\t\t{\n\t\t\t\t\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_VERSION_LABEL, SW_HIDE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == dwNewPageId)\n\t\t\t\t{\n\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REPAIR_BUTTON, !m_fSuppressRepair);\n\t\t\t\t}\n\t\t\t\telse if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR] == dwNewPageId)\n\t\t\t\t{\n\t\t\t\t\tHRESULT hr = BalGetStringVariable(WIXSTDBA_VARIABLE_INSTALL_FOLDER, &sczUnformattedText);\n\t\t\t\t\tif (SUCCEEDED(hr))\n\t\t\t\t\t{\n\t\t\t\t\t\tBalFormatString(sczUnformattedText, &sczText);\n\t\t\t\t\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, sczText);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (m_rgdwPageIds[WIXSTDBA_PAGE_SUCCESS] == dwNewPageId) // on the \"Success\" page, check if the restart or launch button should be enabled.\n\t\t\t\t{\n\t\t\t\t\tBOOL fShowRestartButton = FALSE;\n\t\t\t\t\tBOOL fLaunchTargetExists = FALSE;\n\n\t\t\t\t\tif (m_fIsRepair)\n\t\t\t\t\t{\n\t\t\t\t\t\tLocGetString(m_pWixLoc, L\"#(loc.SuccessHeaderRepair)\", &pLocString);\n\t\t\t\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_HEADER, pLocString->wzText);\n\t\t\t\t\t\tLocGetString(m_pWixLoc, L\"#(loc.SuccessInfoRepair)\", &pLocString);\n\t\t\t\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_INFO, pLocString->wzText);\n\t\t\t\t\t}\n\t\t\t\t\telse if (m_fIsUninstall)\n\t\t\t\t\t{\n\t\t\t\t\t\tLocGetString(m_pWixLoc, L\"#(loc.SuccessHeaderUninstall)\", &pLocString);\n\t\t\t\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_HEADER, pLocString->wzText);\n\t\t\t\t\t\tLocGetString(m_pWixLoc, L\"#(loc.SuccessInfoUninstall)\", &pLocString);\n\t\t\t\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_INFO, pLocString->wzText);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tm_fInstallSucceed = TRUE;\n\n\t\t\t\t\t\t// If we have left some kind of error message file from MSI the show that\n\t\t\t\t\t\tif (BalStringVariableExists(L\"MSICustomErrFile\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tLPWSTR sczUnFormatedErrFile = NULL;\n\t\t\t\t\t\t\tLPWSTR sczErrFile = NULL;\n\t\t\t\t\t\t\tLPWSTR sczSuccessErrMsg   = NULL;\n\t\t\t\t\t\t\tFILE_ENCODING feEncodingFound = FILE_ENCODING_UNSPECIFIED;\n\n\t\t\t\t\t\t\tBalGetStringVariable(L\"MSICustomErrFile\", &sczUnFormatedErrFile);\n\t\t\t\t\t\t\tBalFormatString(sczUnFormatedErrFile, &sczErrFile);\n\n\t\t\t\t\t\t\tif (SUCCEEDED(FileToString(sczErrFile, &sczSuccessErrMsg, &feEncodingFound)))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tLocGetString(m_pWixLoc, L\"#(loc.SuccessErrorInfoText)\", &pLocString);\n\t\t\t\t\t\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_ERRINF, pLocString->wzText);\n\t\t\t\t\t\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_ERRMSG, sczSuccessErrMsg);\n\t\t\t\t\t\t\t\tFileEnsureDelete(sczErrFile);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (m_fRestartRequired)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (BOOTSTRAPPER_RESTART_PROMPT == m_command.restart)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfShowRestartButton = TRUE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_LAUNCH_BUTTON))\n\t\t\t\t\t{\n\t\t\t\t\t\tfLaunchTargetExists = BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH);\n\t\t\t\t\t}\n\n\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_LAUNCH_BUTTON, fLaunchTargetExists && BOOTSTRAPPER_ACTION_UNINSTALL < m_plannedAction);\n\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_SUCCESS_RESTART_TEXT, fShowRestartButton);\n\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, fShowRestartButton);\n\t\t\t\t}\n\t\t\t\telse if (m_rgdwPageIds[WIXSTDBA_PAGE_FAILURE] == dwNewPageId) // on the \"Failure\" page, show error message and check if the restart button should be enabled.\n\t\t\t\t{\n\t\t\t\t\tBOOL fShowLogLink = (m_Bundle.sczLogVariable && *m_Bundle.sczLogVariable); // if there is a log file variable then we'll assume the log file exists.\n\t\t\t\t\tBOOL fShowErrorMessage = FALSE;\n\t\t\t\t\tBOOL fShowRestartButton = FALSE;\n\n\t\t\t\t\tif (m_fIsRepair)\n\t\t\t\t\t{\n\t\t\t\t\t\tLocGetString(m_pWixLoc, L\"#(loc.FailureHeaderRepair)\", &pLocString);\n\t\t\t\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_FAILURE_HEADER, pLocString->wzText);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (m_fIsUninstall)\n\t\t\t\t\t{\n\t\t\t\t\t\tLocGetString(m_pWixLoc, L\"#(loc.FailureHeaderUninstall)\", &pLocString);\n\t\t\t\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_FAILURE_HEADER, pLocString->wzText);\n\t\t\t\t\t}\n\t\t\t\t\tif (FAILED(m_hrFinal))\n\t\t\t\t\t{\n\t\t\t\t\t\t// If we know the failure message, use that.\n\t\t\t\t\t\tif (m_sczFailedMessage && *m_sczFailedMessage)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStrAllocString(&sczUnformattedText, m_sczFailedMessage, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse // try to get the error message from the error code.\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStrAllocFromError(&sczUnformattedText, m_hrFinal, NULL);\n\t\t\t\t\t\t\tif (!sczUnformattedText || !*sczUnformattedText)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tStrAllocFromError(&sczUnformattedText, E_FAIL, NULL);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tStrAllocFormatted(&sczText, L\"0x%08x - %ls\", m_hrFinal, sczUnformattedText);\n\t\t\t\t\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, sczText);\n\t\t\t\t\t\tfShowErrorMessage = TRUE;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (m_fRestartRequired)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (BOOTSTRAPPER_RESTART_PROMPT == m_command.restart)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfShowRestartButton = TRUE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, fShowLogLink);\n\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, fShowErrorMessage);\n\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_RESTART_TEXT, fShowRestartButton);\n\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, fShowRestartButton);\n\t\t\t\t}\n\n\t\t\t\t// Hide the upgrade link\n\t\t\t\tif (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK))\n\t\t\t\t{\n\t\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK, FALSE);\n\t\t\t\t}\n\n\t\t\t\t// Process each control for special handling in the new page.\n\t\t\t\tTHEME_PAGE* pPage = ThemeGetPage(m_pTheme, dwNewPageId);\n\t\t\t\tif (pPage)\n\t\t\t\t{\n\t\t\t\t\tfor (DWORD i = 0; i < pPage->cControlIndices; ++i)\n\t\t\t\t\t{\n\t\t\t\t\t\tTHEME_CONTROL* pControl = m_pTheme->rgControls + pPage->rgdwControlIndices[i];\n\n\t\t\t\t\t\t// If we are on the install, options or modify pages and this is a named control, try to set its default state.\n\t\t\t\t\t\tif ((m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId ||\n\t\t\t\t\t\t\tm_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR] == dwNewPageId ||\n\t\t\t\t\t\t\tm_rgdwPageIds[WIXSTDBA_PAGE_SVC_OPTIONS] == dwNewPageId ||\n\t\t\t\t\t\t\tm_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == dwNewPageId) &&\n\t\t\t\t\t\t\tpControl->sczName && *pControl->sczName)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// If this is a checkbox control, try to set its default state to the state of a matching named Burn variable.\n\t\t\t\t\t\t\tif (THEME_CONTROL_TYPE_CHECKBOX == pControl->type && WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX != pControl->wId)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tLONGLONG llValue = 0;\n\t\t\t\t\t\t\t\tHRESULT hr = BalGetNumericVariable(pControl->sczName, &llValue);\n\n\t\t\t\t\t\t\t\tThemeSendControlMessage(m_pTheme, pControl->wId, BM_SETCHECK, SUCCEEDED(hr) && llValue ? BST_CHECKED : BST_UNCHECKED, 0);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// If this is a button control with the BS_AUTORADIOBUTTON style, try to set its default\n\t\t\t\t\t\t\t// state to the state of a matching named Burn variable.\n\t\t\t\t\t\t\tif (THEME_CONTROL_TYPE_BUTTON == pControl->type && (BS_AUTORADIOBUTTON == (BS_AUTORADIOBUTTON & pControl->dwStyle)))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tLONGLONG llValue = 0;\n\t\t\t\t\t\t\t\tHRESULT hr = BalGetNumericVariable(pControl->sczName, &llValue);\n\n\t\t\t\t\t\t\t\t// If the control value isn't set then disable it.\n\t\t\t\t\t\t\t\tif (!SUCCEEDED(hr))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tThemeControlEnable(m_pTheme, pControl->wId, FALSE);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tThemeSendControlMessage(m_pTheme, pControl->wId, BM_SETCHECK, SUCCEEDED(hr) && llValue ? BST_CHECKED : BST_UNCHECKED, 0);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Hide or disable controls based on the control name with 'State' appended\n\t\t\t\t\t\t\tHRESULT hr = StrAllocFormatted(&sczControlName, L\"%lsState\", pControl->sczName);\n\t\t\t\t\t\t\tif (SUCCEEDED(hr))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\thr = BalGetStringVariable(sczControlName, &sczControlState);\n\t\t\t\t\t\t\t\tif (SUCCEEDED(hr) && sczControlState && *sczControlState)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, sczControlState, -1, L\"disable\", -1))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Disable control %ls\", pControl->sczName);\n\t\t\t\t\t\t\t\t\t\tThemeControlEnable(m_pTheme, pControl->wId, FALSE);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, sczControlState, -1, L\"hide\", -1))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Hide control %ls\", pControl->sczName);\n\t\t\t\t\t\t\t\t\t\t// TODO: This doesn't work\n\t\t\t\t\t\t\t\t\t\tThemeShowControl(m_pTheme, pControl->wId, SW_HIDE);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Format the text in each of the new page's controls (if they have any text).\n\t\t\t\t\t\tif (pControl->sczText && *pControl->sczText)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tHRESULT hr = BalFormatString(pControl->sczText, &sczText);\n\t\t\t\t\t\t\tif (SUCCEEDED(hr))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tThemeSetTextControl(m_pTheme, pControl->wId, sczText);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// See #Hidden\n\t\t\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_LOGUSER_OR_MAIL_LABEL, false);\n\t\t\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_LOGPASS_LABEL, false);\n\t\t\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_LOGUSER_OR_MAIL_EDIT, false);\n\t\t\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_LOGPASS_EDIT, false);\n\n\t\t\t\t// XXX why do we need this??\n\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_LOGUSER_OR_MAIL_LABEL, true);\n\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_LOGPASS_LABEL, true);\n\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_LOGUSER_OR_MAIL_EDIT, true);\n\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_LOGPASS_EDIT, true);\n\n\t\t\t\tThemeShowPage(m_pTheme, dwOldPageId, SW_HIDE);\n\t\t\t\tThemeShowPage(m_pTheme, dwNewPageId, SW_SHOW);\n\n\n\t\t\t\t// Remember current page\n\t\t\t\tm_dwCurrentPage = dwNewPageId;\n\n\t\t\t\t// On the install page set the focus to the install button or the next enabled control if install is disabled\n\t\t\t\tif (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId)\n\t\t\t\t{\n\t\t\t\t\tHWND hwndFocus = ::GetDlgItem(m_pTheme->hwndParent, WIXSTDBA_CONTROL_INSTALL_BUTTON);\n\t\t\t\t\tif (hwndFocus && !ThemeControlEnabled(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON))\n\t\t\t\t\t{\n\t\t\t\t\t\thwndFocus = ::GetNextDlgTabItem(m_pTheme->hwndParent, hwndFocus, FALSE);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (hwndFocus)\n\t\t\t\t\t{\n\t\t\t\t\t\t::SetFocus(hwndFocus);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tReleaseStr(sczText);\n\t\tReleaseStr(sczUnformattedText);\n\t\tReleaseStr(sczControlState);\n\t\tReleaseStr(sczControlName);\n\t}\n\n\n\t//\n\t// OnClose - called when the window is trying to be closed.\n\t//\n\tBOOL OnClose()\n\t{\n\t\tBOOL fClose = FALSE;\n\n\t\t// If we've already succeeded or failed or showing the help page, just close (prompts are annoying if the bootstrapper is done).\n\t\t// Also, allow people to simply close out at the signin stage\n\t\tif (WIXSTDBA_STATE_APPLIED <= m_state || WIXSTDBA_STATE_HELP == m_state || WIXSTDBA_STATE_SVC_OPTIONS == m_state)\n\t\t{\n\t\t\tfClose = TRUE;\n\t\t}\n\t\telse // prompt the user or force the cancel if there is no UI.\n\t\t{\n\t\t\tfClose = PromptCancel(m_hWnd, BOOTSTRAPPER_DISPLAY_FULL != m_command.display, m_sczConfirmCloseMessage ? m_sczConfirmCloseMessage : L\"Are you sure you want to cancel?\", m_pTheme->sczCaption);\n\t\t}\n\n\t\t// If we're doing progress then we never close, we just cancel to let rollback occur.\n\t\tif (WIXSTDBA_STATE_APPLYING <= m_state && WIXSTDBA_STATE_APPLIED > m_state)\n\t\t{\n\t\t\t// If we canceled disable cancel button since clicking it again is silly.\n\t\t\tif (fClose)\n\t\t\t{\n\t\t\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, FALSE);\n\t\t\t}\n\n\t\t\tfClose = FALSE;\n\t\t}\n\n\t\treturn fClose;\n\t}\n\n\n\t//\n\t// OnClickAcceptCheckbox - allow the install to continue.\n\t//\n\tvoid OnClickAcceptCheckbox()\n\t{\n\t\tBOOL fAcceptedLicense = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX);\n\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense);\n\t\tThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_NEXT_BUTTON, fAcceptedLicense);\n\t}\n\n\n\t//\n\t// OnClickOptionsButton - show the options page.\n\t//\n\tvoid OnClickOptionsButton()\n\t{\n\t\tSavePageSettings(WIXSTDBA_PAGE_INSTALL);\n\t\tm_stateInstallPage = m_state;\n\t\tSetState(WIXSTDBA_STATE_INSTALLDIR, S_OK);\n\t}\n\n\n\tBOOL CheckNonEmptyField(LPCWSTR wzEditVarID)\n\t{\n\t\tBOOL bRes = TRUE;\n\t\tLPWSTR sczFieldValue = NULL;\n\n\t\tif (SUCCEEDED(BalGetStringVariable(wzEditVarID, &sczFieldValue)))\n\t\t{\n\t\t\tif (StrCmpCW(sczFieldValue, L\"\") == 0)\n\t\t\t{\n\t\t\t\tLOC_STRING* pLocString = NULL;\n\t\t\t\tLPWSTR wzLoc = NULL;\n\t\t\t\tLPWSTR sczMessageText = NULL;\n\n\t\t\t\tStrAllocFormatted(&wzLoc, L\"#(loc.%s)\", wzEditVarID);\n\t\t\t\tLocGetString(m_pWixLoc, wzLoc, &pLocString);\n\t\t\t\tStrAllocFormatted(&sczMessageText, L\"The field \\\"%s\\\" cannot be blank! In order to continue with setup you should fill it.\", pLocString->wzText);\n\n\t\t\t\t::MessageBoxW(m_hWnd, sczMessageText, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK);\n\t\t\t\tbRes = FALSE;\n\t\t\t}\n\t\t}\n\t\treturn bRes;\n\t}\n\n\n\n\n\tBOOL CheckCurrentUserPassword(LPCWSTR wzPasswordVarID)\n\t{\n\t\tLPWSTR sczUserNameValue = NULL;\n\t\tLPWSTR sczDomainValue = NULL;\n\t\tLPWSTR sczPasswordValue = NULL;\n\n\t\tBOOL bRes = SUCCEEDED(BalGetStringVariable(L\"ComputerName\", &sczDomainValue)) &&\n\t\t\t\t\tSUCCEEDED(BalGetStringVariable(L\"LogonUser\", &sczUserNameValue)) &&\n\t\t\t\t\tSUCCEEDED(BalGetStringVariable(wzPasswordVarID, &sczPasswordValue));\n\n\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"CheckCurrentUserPassword. 1\");\n\n\n\t\tif (bRes)\n\t\t{\n\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"CheckCurrentUserPassword. 2\");\n\t\t\tHANDLE hToken;\n\t\t\tif (!LogonUserW(sczUserNameValue, sczDomainValue, sczPasswordValue, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken))\n\t\t\t{\n\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"CheckCurrentUserPassword. 3 - Failed\");\n\n\t\t\t\tLPWSTR sczMessageText = NULL;\n\t\t\t\tStrAllocFormatted(&sczMessageText, L\"Setup was unable to validate specified password for \\\"%s\\\\%s\\\"! Please double check it.\", sczDomainValue, sczUserNameValue);\n\n\t\t\t\t::MessageBoxW(m_hWnd, sczMessageText, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK);\n\t\t\t\tbRes = FALSE;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"CheckCurrentUserPassword. 4 - Succeed\");\n\t\t\t}\n\t\t}\n\t\treturn bRes;\n\t}\n\n\n\n\n\n\t/*\n\n\tBOOL CheckPostgreSQLConnection(LPCWSTR VAR_HOST, LPCWSTR VAR_USER, LPCWSTR VAR_PASS, LPCWSTR DB_ToCheck, BOOL DB_ShouldExists)\n\t{\n\t\tBOOL bPSQLOk = CheckNonEmptyField(VAR_HOST) && CheckNonEmptyField(VAR_USER) && CheckNonEmptyField(VAR_PASS);\n\n// \t\tif (!bPSQLOk) return FALSE;\n\n\t\tLPWSTR sczPSQLPath = NULL;\n\t\tLPWSTR sczPSQLDirectory = NULL;\n\n\t\tif (bPSQLOk && SUCCEEDED(PathRelativeToModule(&sczPSQLPath, L\"qcPSQL.exe\", m_hModule)) && SUCCEEDED(PathGetDirectory(sczPSQLPath, &sczPSQLDirectory)))\n\t\t{\n\t\t\tLPWSTR sczPSQLHost = NULL;\n\t\t\tLPWSTR sczPSQLUser = NULL;\n\t\t\tLPWSTR sczPSQLPass = NULL;\n\n\t\t\tif (SUCCEEDED(BalGetStringVariable(VAR_HOST, &sczPSQLHost)) &&\n\t\t\t\tSUCCEEDED(BalGetStringVariable(VAR_USER, &sczPSQLUser)) &&\n\t\t\t\tSUCCEEDED(BalGetStringVariable(VAR_PASS, &sczPSQLPass)) )\n\t\t\t{\n\t\t\t\tDWORD exitcode = 0;\n\t\t\t\tLPWSTR sczCmdParam = NULL;\n\t\t\t\tif (DB_ToCheck == NULL)\n\t\t\t\t\tStrAllocFormatted(&sczCmdParam, L\"\\\"%s\\\" checkconnection -H%s -U%s -P%s\", sczPSQLPath, sczPSQLHost, sczPSQLUser, sczPSQLPass);\n\t\t\t\telse\n\t\t\t\t\tStrAllocFormatted(&sczCmdParam, L\"\\\"%s\\\" checkdbexists -H%s -U%s -P%s -CKDB%s\", sczPSQLPath, sczPSQLHost, sczPSQLUser, sczPSQLPass, DB_ToCheck);\n\n\t\t\t\t_STARTUPINFOW si;\n\t\t\t\t_PROCESS_INFORMATION pi;\n\n\t\t\t\tZeroMemory( &si, sizeof(si) );\n\t\t\t\tsi.cb = sizeof(si);\n\t\t\t\tZeroMemory( &pi, sizeof(pi) );\n\n\n\t\t\t\t// Start the child process.\n\t\t\t\tif( CreateProcessW(NULL,   // No module name (use command line)\n\t\t\t\t\tsczCmdParam,    // Command line\n\t\t\t\t\tNULL,           // Process handle not inheritable\n\t\t\t\t\tNULL,           // Thread handle not inheritable\n\t\t\t\t\tFALSE,          // Set handle inheritance to FALSE\n\t\t\t\t\tCREATE_NO_WINDOW, // No creation flags\n\t\t\t\t\tNULL,           // Use parent's environment block\n\t\t\t\t\tNULL,           // Use parent's starting directory\n\t\t\t\t\t&si,            // Pointer to STARTUPINFO structure\n\t\t\t\t\t&pi )           // Pointer to PROCESS_INFORMATION structure\n\t\t\t\t\t)\n\t\t\t\t{\n\t\t\t\t\t// Wait until child process exits.\n\t\t\t\t\tWaitForSingleObject( pi.hProcess, INFINITE );\n\n\t\t\t\t\t// get the process exit code\n\t\t\t\t\tGetExitCodeProcess(pi.hProcess, (LPDWORD)&exitcode);\n\n\t\t\t\t\t// Close process and thread handles.\n\t\t\t\t\tCloseHandle( pi.hProcess );\n\t\t\t\t\tCloseHandle( pi.hThread );\n\t\t\t\t}\n\n\n\n\t\t\t\tLPWSTR sczMessageText = NULL;\n\t\t\t\tswitch (exitcode)\n\t\t\t\t{\n\t\t\t\t\tcase QCPSQL_ERROR_UNKNOWN:\n\t\t\t\t\t\tsczMessageText = L\"Setup was unable to connect to the specified database server. Unknown error.\\nWould you like to continue anyway?\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase QCPSQL_ERROR_EXECSQL:\n\t\t\t\t\t\tsczMessageText = L\"Setup was unable to execute specified command.\\nWould you like to continue anyway?\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase QCPSQL_ERROR_CONNECT:\n\t\t\t\t\t\tsczMessageText = L\"Setup was unable to connect to the specified database server.\\nWould you like to continue anyway?\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase QCPSQL_ERROR_INVALIDARGS:\n\t\t\t\t\t\tsczMessageText = L\"Setup was unable to connect to the specified database server. Invalid arguments.\\nWould you like to continue anyway?\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase QCPSQL_SUCCESS_DBNOTEXISTS:\n\t\t\t\t\t\tif ((DB_ToCheck != NULL) && (DB_ShouldExists))\n\t\t\t\t\t\t\tStrAllocFormatted(&sczMessageText, L\"The database \\\"%s\\\" does not exists on the host \\\"%s\\\".\\nWould you like to continue anyway?\", DB_ToCheck, sczPSQLHost);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase QCPSQL_SUCCESS_DBEXISTS:\n\t\t\t\t\t\tif ((DB_ToCheck != NULL) && (!DB_ShouldExists))\n\t\t\t\t\t\t\tStrAllocFormatted(&sczMessageText, L\"The database \\\"%s\\\" already exists on the host \\\"%s\\\".\\nWould you like to continue anyway?\", DB_ToCheck, sczPSQLHost);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (sczMessageText != NULL)\n\t\t\t\t\tbPSQLOk = (IDYES == ::MessageBoxW(m_hWnd, sczMessageText, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_YESNO));\n\t\t\t}\n\t\t}\n\n\t\treturn bPSQLOk;\n\t}\n\t*/\n\n\tBOOL CheckInstallPathIsValid(LPCWSTR wzInstallPath)\n\t{\n\t\tBOOL bPathIsValid = TRUE;\n\n\t\tif (StrCmpCW(wzInstallPath, L\"\") == 0)\n\t\t{\n\t\t\tbPathIsValid = FALSE;\n\t\t\t::MessageBoxW(m_hWnd, L\"The install location cannot be blank. You must enter a full path with drive letter, like:\\n\\tC:\\\\Program Files\\\\App\\n\\nor a UNC path, like\\n\\t\\\\\\\\ServerName\\\\AppShare\", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK);\n\t\t} else {\n\t\t\tDWORD i = 0;\n\t\t\tLPCWSTR wz = wzInstallPath;\n\t\t\tBOOL bInvalidCharFound = FALSE;\n\t\t\twhile (*wz)\n\t\t\t{\n\t\t\t\t++i;\n\t\t\t\tif ((L'/' == *wz) || ((L':' == *wz) && (i != 2)) || (L'*' == *wz) || (L'?' == *wz) ||\n\t\t\t\t\t(L'\"' == *wz) || (L'<' == *wz) || (L'>' == *wz) || (L'|' == *wz))\n\t\t\t\t\tbInvalidCharFound = TRUE;\n\t\t\t\t++wz;\n\t\t\t}\n\n\t\t\tif (bInvalidCharFound)\n\t\t\t{\n\t\t\t\tbPathIsValid = FALSE;\n\t\t\t\t::MessageBoxW(m_hWnd, L\"The install location cannot include any of the following characters:\\n\\n/ : * ? \\\" < > |\", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK);\n\t\t\t}\n\t\t}\n\t\treturn bPathIsValid;\n\t}\n\n\n\tBOOL CheckEmailAddressIsValid(LPCWSTR wzEmailVarID, LPCWSTR wzPassVarID = NULL, BOOL AllowBlank = TRUE)\n\t{\n\t\tBOOL bRes = TRUE;\n\t\tLPWSTR sczEmailValue = NULL;\n\t\tLPWSTR sczPassValue = NULL;\n\n\t\tif (SUCCEEDED(BalGetStringVariable(wzEmailVarID, &sczEmailValue)))\n\t\t{\n\t\t\tLOC_STRING* pLocString = NULL;\n\t\t\tLPWSTR wzLoc = NULL;\n\t\t\tLPWSTR sczMessageText = NULL;\n\n\t\t\tStrAllocFormatted(&wzLoc, L\"#(loc.%s)\", wzEmailVarID);\n\t\t\tLocGetString(m_pWixLoc, wzLoc, &pLocString);\n\n\t\t\tBOOL bIsBlank = (StrCmpCW(sczEmailValue, L\"\") == 0);\n\n\t\t\tif (bIsBlank && AllowBlank)\n\t\t\t\treturn TRUE;\n\n\t\t\tif (bIsBlank)\n\t\t\t{\n\t\t\t\tbRes = FALSE;\n\t\t\t\tStrAllocFormatted(&sczMessageText, L\"The field \\\"%s\\\" cannot be blank! In order to continue with setup you should fill it.\", pLocString->wzText);\n\t\t\t} else {\n\t\t\t\tDWORD i = 0;\n\t\t\t\tDWORD iAt = 0;\n\t\t\t\tDWORD iPt = 0;\n\n\t\t\t\tLPCWSTR wz = sczEmailValue;\n\t\t\t\twhile (*wz)\n\t\t\t\t{\n\t\t\t\t\t++i;\n\t\t\t\t\tif (L'@' == *wz) iAt = i;\n\t\t\t\t\tif (L'.' == *wz) iPt = i;\n\t\t\t\t\t++wz;\n\t\t\t\t}\n\t\t\t\tbRes =  (1 < iAt) && (iAt < iPt);\n\n\t\t\t\tif (!bRes)\n\t\t\t\t\tStrAllocFormatted(&sczMessageText, L\"The field \\\"%s\\\" dosen't seems to be a valid email address! Please double check that.\", pLocString->wzText);\n\t\t\t}\n\n\t\t\tif (!bRes)\n\t\t\t\t::MessageBoxW(m_hWnd, sczMessageText, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK);\n\t\t\telse {\n\t\t\t\tif (wzPassVarID != NULL)\n\t\t\t\t{\n\t\t\t\t\tif (SUCCEEDED(BalGetStringVariable(wzPassVarID, &sczPassValue)))\n\t\t\t\t\t\tif (StrCmpCW(sczEmailValue, L\"\") == 0) {\n\t\t\t\t\t\t\tbRes = FALSE;\n\t\t\t\t\t\t\t::MessageBoxW(m_hWnd, L\"You specified a valid email address but the account password is blank. The password is required!\", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK);\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\treturn bRes;\n\t}\n\n\n\tvoid OnClickNextButton()\n\t{\n\t\tBOOL bOkToContinue = TRUE;\n\t\tLPWSTR sczPath = NULL;\n\n\t\tswitch (m_state)\n\t\t{\n\t\t// this clause is dead code, since we cancelled the \"choose an\n\t\t// install directory\" screen. but let's leave it in, in case we\n\t\t// bring it back.\n\t\tcase WIXSTDBA_STATE_INSTALLDIR:\n\t\t\tThemeGetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, &sczPath);\n\t\t\tbOkToContinue = CheckInstallPathIsValid(sczPath);\n\n\t\t\tif (bOkToContinue) {\n\t\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_INSTALL_FOLDER, sczPath);\n\t\t\t\tSavePageSettings(WIXSTDBA_PAGE_INSTALLDIR);\n\t\t\t\tSetState(WIXSTDBA_STATE_SVC_OPTIONS, S_OK);\n\n\t\t\t\t// Display the elevation shield if perMachine installation\n\t\t\t\tLONGLONG llElevated = 0;\n\t\t\t\tif (SUCCEEDED(BalGetNumericVariable(WIXSTDBA_VARIABLE_PERMACHINE_INSTALL, &llElevated)))\n\t\t\t\t\tThemeControlElevates(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, (llElevated == 1));\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tSavePageSettings(WIXSTDBA_PAGE_INSTALL);\n\t\t\tm_stateInstallPage = m_state;\n\t\t\tSetState(WIXSTDBA_STATE_SVC_OPTIONS, S_OK);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\n\t//\n\t// OnClickInstallScope - allow user to choose between a perMachine and perUser install\n\t//\n\tvoid OnClickInstallScope()\n\t{\n\t\tLPWSTR sczPath = NULL;\n\t\tLPWSTR sczFPath = NULL;\n\t\tBOOL fPerMachineInst = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_PERMACHINE_RADIO);\n\n\n\t\tif (fPerMachineInst)\n\t\t{\n\t\t\tif (SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_PERMACHINE_INSTALL_FOLDER, &sczPath))\n\t\t\t\t&& SUCCEEDED(BalFormatString(sczPath, &sczFPath)))\n\t\t\t\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, sczFPath);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_PERUSER_INSTALL_FOLDER, &sczPath))\n\t\t\t\t&& SUCCEEDED(BalFormatString(sczPath, &sczFPath)))\n\t\t\t\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, sczFPath);\n\t\t}\n\t}\n\n\t//\n\t// OnClickInstallPostgressCheckbox - we will set defaults value and disable controls if checkbox was checked.\n\t//\n\tvoid OnClickSkipRegistrationCheckbox()\n\t{\n\t\tBOOL fSignIn = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_REGSIGNIN_RADIO);\n\n\t\t//if (fSkipReg)\n\t\t//{\n\t\t//\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_DBHOST_EDIT, L\"localhost\");\n\t\t//\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_DBUSER_EDIT, L\"postgres\");\n\t\t//\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_DBPASS_EDIT, L\"postgres\");\n\t\t//}\n\n\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_REGMAIL_LABEL, !fSignIn);\n\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_REGUSER_LABEL, !fSignIn);\n\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_REGPASS_LABEL, !fSignIn);\n\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_REGMAIL_EDIT, !fSignIn);\n\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_REGUSER_EDIT, !fSignIn);\n\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_REGPASS_EDIT, !fSignIn);\n\n\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_LOGUSER_OR_MAIL_LABEL, fSignIn);\n\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_LOGPASS_LABEL, fSignIn);\n\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_LOGUSER_OR_MAIL_EDIT, fSignIn);\n\t\tThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_LOGPASS_EDIT, fSignIn);\n\t}\n\n\n\n\tvoid OnSignIn()\n\t{\n\t\tBOOL fSignIn = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_REGSIGNIN_RADIO);\n\t\tBOOL bOkToContinue = false;\n\n\t\tSavePageSettings(WIXSTDBA_PAGE_SVC_OPTIONS);\n\n\t\tif (fSignIn)\n\t\t{\n\t\t\tLPWSTR wzUserNameOrEmail = NULL;\n\t\t\tLPWSTR wzUserPass = NULL;\n\t\t\tif (SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_LOG_USERNAME_OR_MAIL, &wzUserNameOrEmail)) &&\n\t\t\t\tSUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_LOG_PASS, &wzUserPass)))\n\t\t\t{\n\t\t\t\tbOkToContinue = REST_SignInOrRegister(true, wzUserNameOrEmail, NULL, NULL, wzUserPass);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLPWSTR wzUserName = NULL;\n\t\t\tLPWSTR wzEmail = NULL;\n\t\t\tLPWSTR wzUserPass = NULL;\n\t\t\tif (SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_REG_MAIL, &wzEmail)) &&\n\t\t\t\tSUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_REG_USER, &wzUserName)) &&\n\t\t\t\tSUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_REG_PASS, &wzUserPass)))\n\t\t\t{\n\t\t\t\tbOkToContinue = REST_SignInOrRegister(false, NULL, wzUserName, wzEmail, wzUserPass);\n\t\t\t}\n\t\t}\n\n\t\tif (bOkToContinue)\n\t\t\tthis->SetState(WIXSTDBA_STATE_APPLIED, S_OK);\n\t}\n\n\n\tvoid OnClickBackButton()\n\t{\n\t\tBOOL bOkToContinue = TRUE;\n\t\tLPWSTR sczPath = NULL;\n\n\t\tswitch (m_state)\n\t\t{\n\t\tcase WIXSTDBA_STATE_INSTALLDIR:\n\t\t\tThemeGetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, &sczPath);\n\t\t\tbOkToContinue = CheckInstallPathIsValid(sczPath);\n\n\t\t\tif (bOkToContinue) {\n\t\t\t\tm_pEngine->SetVariableString(WIXSTDBA_VARIABLE_INSTALL_FOLDER, sczPath);\n\t\t\t\tSavePageSettings(WIXSTDBA_PAGE_INSTALLDIR);\n\t\t\t\tSetState(m_stateInstallPage, S_OK);\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase WIXSTDBA_STATE_SVC_OPTIONS:\n\t\t\tSavePageSettings(WIXSTDBA_PAGE_SVC_OPTIONS);\n\t\t\tSetState(WIXSTDBA_STATE_DETECTED, S_OK);\n\t\t\tbreak;\n\t\t}\n\n\t}\n\n\n\t//\n\t// OnClickOptionsBrowseButton - browse for install folder on the options page.\n\t//\n\tvoid OnClickOptionsBrowseButton(DWORD dwControl)\n\t{\n\t\tWCHAR wzPath[MAX_PATH] = { };\n\t\tBROWSEINFOW browseInfo = { };\n\t\tPIDLIST_ABSOLUTE pidl = NULL;\n\t\tPIDLIST_ABSOLUTE pidlRoot = NULL;\n\n\t\t::SHGetFolderLocation(m_hWnd, CSIDL_DRIVES, NULL, 0, &pidlRoot);\n\n\t\tbrowseInfo.hwndOwner = m_hWnd;\n\t\tbrowseInfo.pszDisplayName = wzPath;\n\t\tbrowseInfo.lpszTitle = m_pTheme->sczCaption;\n\t\tbrowseInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;\n\t\tbrowseInfo.pidlRoot = pidlRoot;\n\t\tpidl = ::SHBrowseForFolderW(&browseInfo);\n\t\tif (pidl && ::SHGetPathFromIDListW(pidl, wzPath))\n\t\t{\n\t\t\tswitch (dwControl)\n\t\t\t{\n\t\t\tcase WIXSTDBA_CONTROL_BROWSE_BUTTON:\n\t\t\t\tThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, wzPath);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (pidl)\n\t\t{\n\t\t\t::CoTaskMemFree(pidl);\n\t\t}\n\n\t\treturn;\n\t}\n\n\t//\n\t// OnClickOptionsOkButton - accept the changes made by the options page.\n\t//\n\tvoid OnClickOptionsOkButton()\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tLPWSTR sczPath = NULL;\n\n\t\tif (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX))\n\t\t{\n\t\t\thr = ThemeGetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, &sczPath);\n\t\t\tExitOnFailure(hr, \"Failed to get text from folder edit box.\");\n\n\t\t\t// TODO: verify the path is valid.\n\n\t\t\thr = m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_INSTALL_FOLDER, sczPath);\n\t\t\tExitOnFailure(hr, \"Failed to set the install folder.\");\n\t\t}\n\n\n\t\tSavePageSettings(WIXSTDBA_PAGE_INSTALLDIR);\n\nLExit:\n\t\tSetState(m_stateInstallPage, S_OK);\n\t\treturn;\n\t}\n\n\n\t//\n\t// OnClickOptionsCancelButton - discard the changes made by the options page.\n\t//\n\tvoid OnClickOptionsCancelButton()\n\t{\n\t\tSetState(m_stateInstallPage, S_OK);\n\t}\n\n\n\t//\n\t// OnClickRepairButton - start the repair.\n\t//\n\tvoid OnClickRepairButton()\n\t{\n\t\tthis->OnPlan(BOOTSTRAPPER_ACTION_REPAIR);\n\t}\n\n\n\t//\n\t// OnClickUninstallButton - start the uninstall.\n\t//\n\tvoid OnClickUninstallButton()\n\t{\n\t\tthis->OnPlan(BOOTSTRAPPER_ACTION_UNINSTALL);\n\t}\n\n\n\n\tvoid TryLaunchAfterInstall(LPWSTR wzVarTargetPath)\n\t{\n\t\tBOOL fLaunchAfterInstallTargetExists = BalStringVariableExists(wzVarTargetPath);\n\n\t\tHRESULT hr = S_OK;\n\t\tLPWSTR sczUnformattedLaunchTarget = NULL;\n\t\tLPWSTR sczLaunchTarget = NULL;\n\t\tLPWSTR sczUnformattedArguments = NULL;\n\t\tLPWSTR sczArguments = NULL;\n\t\tLPWSTR sczRunOnceValue = NULL;\n\n\t\tint nCmdShow = SW_SHOWNORMAL;\n\n\t\tif (fLaunchAfterInstallTargetExists)\n\t\t{\n\t\t\thr = BalGetStringVariable(wzVarTargetPath, &sczUnformattedLaunchTarget);\n\t\t\thr = BalFormatString(sczUnformattedLaunchTarget, &sczLaunchTarget);\n\t\t}\n\n\t\tif (m_fInstallSucceed && fLaunchAfterInstallTargetExists)\n\t\t{\n\n\t\t\tif (!m_fRestartRequired)\n\t\t\t{\n\t\t\t\tDWORD dwAttr;\n\t\t\t\tif (FileExistsEx(sczLaunchTarget, &dwAttr))\n\t\t\t\t\tShelExec(sczLaunchTarget, sczArguments, L\"open\", NULL, nCmdShow, m_hWnd, NULL);\n\t\t\t}\n\t\t}\n\n\t\tReleaseStr(sczUnformattedLaunchTarget);\n\t\tReleaseStr(sczLaunchTarget);\n\t\tReleaseStr(sczUnformattedArguments);\n\t\tReleaseStr(sczArguments);\n\t\tReleaseStr(sczRunOnceValue);\n\n\t\treturn;\n\t}\n\n\t//\n\t// OnClickCloseButton - close the application.\n\t//\n\tvoid OnClickCloseButton()\n\t{\n\t\tTryLaunchAfterInstall(L\"Launch_IISStartServerPath\");\n\t\tTryLaunchAfterInstall(L\"Launch_EverywarePOSPath\");\n\t\t::SendMessageW(m_hWnd, WM_CLOSE, 0, 0);\n\t\treturn;\n\t}\n\n\n\t//\n\t// OnClickEulaLink - show the end user license agreement.\n\t//\n\tvoid OnClickEulaLink()\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tLPWSTR sczLicenseUrl = NULL;\n\t\tLPWSTR sczLicensePath = NULL;\n\t\tLPWSTR sczLicenseDirectory = NULL;\n\t\tURI_PROTOCOL protocol = URI_PROTOCOL_UNKNOWN;\n\n\t\thr = StrAllocString(&sczLicenseUrl, m_sczLicenseUrl, 0);\n\t\tBalExitOnFailure1(hr, \"Failed to copy license URL: %ls\", m_sczLicenseUrl);\n\n\t\thr = LocLocalizeString(m_pWixLoc, &sczLicenseUrl);\n\t\tBalExitOnFailure1(hr, \"Failed to localize license URL: %ls\", m_sczLicenseUrl);\n\n\t\thr = BalFormatString(sczLicenseUrl, &sczLicenseUrl);\n\t\tBalExitOnFailure1(hr, \"Failed to get formatted license URL: %ls\", m_sczLicenseUrl);\n\n\t\thr = UriProtocol(sczLicenseUrl, &protocol);\n\t\tif (FAILED(hr) || URI_PROTOCOL_UNKNOWN == protocol)\n\t\t{\n\t\t\t// Probe for localised license file\n\t\t\thr = PathRelativeToModule(&sczLicensePath, sczLicenseUrl, m_hModule);\n\t\t\tif (SUCCEEDED(hr))\n\t\t\t{\n\t\t\t\thr = PathGetDirectory(sczLicensePath, &sczLicenseDirectory);\n\t\t\t\tif (SUCCEEDED(hr))\n\t\t\t\t{\n\t\t\t\t\thr = LocProbeForFile(sczLicenseDirectory, PathFile(sczLicenseUrl), m_sczLanguage, &sczLicensePath);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\thr = ShelExec(sczLicensePath ? sczLicensePath : sczLicenseUrl, NULL, L\"open\", NULL, SW_SHOWDEFAULT, m_hWnd, NULL);\n\t\tBalExitOnFailure(hr, \"Failed to launch URL to EULA.\");\n\nLExit:\n\t\tReleaseStr(sczLicensePath);\n\t\tReleaseStr(sczLicenseUrl);\n\t\tReleaseStr(sczLicenseDirectory);\n\n\t\treturn;\n\t}\n\n\n\t//\n\t// OnClickUpgradeLink - download the upgrade.\n\t//\n\tvoid OnClickUpgradeLink()\n\t{\n\t\tthis->OnPlan(BOOTSTRAPPER_ACTION_UPDATE_REPLACE);\n\n\t\tm_fUpdating = TRUE;\n\n\t\treturn;\n\t}\n\n\n\t//\n\t// OnClickLaunchButton - launch the app from the success page.\n\t//\n\tvoid OnClickLaunchButton()\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tLPWSTR sczUnformattedLaunchTarget = NULL;\n\t\tLPWSTR sczLaunchTarget = NULL;\n\t\tLPWSTR sczUnformattedArguments = NULL;\n\t\tLPWSTR sczArguments = NULL;\n\t\tint nCmdShow = SW_SHOWNORMAL;\n\n\t\thr = BalGetStringVariable(WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH, &sczUnformattedLaunchTarget);\n\t\tBalExitOnFailure1(hr, \"Failed to get launch target variable '%ls'.\", WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH);\n\n\t\thr = BalFormatString(sczUnformattedLaunchTarget, &sczLaunchTarget);\n\t\tBalExitOnFailure1(hr, \"Failed to format launch target variable: %ls\", sczUnformattedLaunchTarget);\n\n\t\tif (BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS))\n\t\t{\n\t\t\thr = BalGetStringVariable(WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS, &sczUnformattedArguments);\n\t\t\tBalExitOnFailure1(hr, \"Failed to get launch arguments '%ls'.\", WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS);\n\n\t\t\thr = BalFormatString(sczUnformattedArguments, &sczArguments);\n\t\t\tBalExitOnFailure1(hr, \"Failed to format launch arguments variable: %ls\", sczUnformattedArguments);\n\t\t}\n\n\t\tif (BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_HIDDEN))\n\t\t{\n\t\t\tnCmdShow = SW_HIDE;\n\t\t}\n\n\t\thr = ShelExec(sczLaunchTarget, sczArguments, L\"open\", NULL, nCmdShow, m_hWnd, NULL);\n\t\tBalExitOnFailure1(hr, \"Failed to launch target: %ls\", sczLaunchTarget);\n\n\t\t::PostMessageW(m_hWnd, WM_CLOSE, 0, 0);\n\nLExit:\n\t\tReleaseStr(sczLaunchTarget);\n\t\tReleaseStr(sczUnformattedLaunchTarget);\n\t\tReleaseStr(sczArguments);\n\t\tReleaseStr(sczUnformattedArguments);\n\n\t\treturn;\n\t}\n\n\n\t//\n\t// OnClickRestartButton - allows the restart and closes the app.\n\t//\n\tvoid OnClickRestartButton()\n\t{\n\t\tAssertSz(m_fRestartRequired, \"Restart must be requested to be able to click on the restart button.\");\n\n\t\tm_fAllowRestart = TRUE;\n\t\t::SendMessageW(m_hWnd, WM_CLOSE, 0, 0);\n\n\t\treturn;\n\t}\n\n\n\t//\n\t// OnClickLogFileLink - show the log file.\n\t//\n\tvoid OnClickLogFileLink()\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tLPWSTR sczLogFile = NULL;\n\n\t\thr = BalGetStringVariable(m_Bundle.sczLogVariable, &sczLogFile);\n\t\tBalExitOnFailure1(hr, \"Failed to get log file variable '%ls'.\", m_Bundle.sczLogVariable);\n\n\t\thr = ShelExec(L\"notepad.exe\", sczLogFile, L\"open\", NULL, SW_SHOWDEFAULT, m_hWnd, NULL);\n\t\tBalExitOnFailure1(hr, \"Failed to open log file target: %ls\", sczLogFile);\n\nLExit:\n\t\tReleaseStr(sczLogFile);\n\n\t\treturn;\n\t}\n\n\n\t//\n\t// SetState\n\t//\n\tvoid SetState(\n\t\t__in WIXSTDBA_STATE state,\n\t\t__in HRESULT hrStatus\n\t\t)\n\t{\n\t\tif (FAILED(hrStatus))\n\t\t{\n\t\t\tm_hrFinal = hrStatus;\n\t\t}\n\n\t\tif (FAILED(m_hrFinal))\n\t\t{\n\t\t\tstate = WIXSTDBA_STATE_FAILED;\n\t\t}\n\n\t\tif (WIXSTDBA_STATE_INSTALLDIR == state || m_state < state)\n\t\t{\n\t\t\t::PostMessageW(m_hWnd, WM_WIXSTDBA_CHANGE_STATE, 0, state);\n\t\t}\n\n\t\tif (WIXSTDBA_STATE_INSTALLDIR == state || m_state < state)\n\t\t{\n\t\t\t::PostMessageW(m_hWnd, WM_WIXSTDBA_CHANGE_STATE, 0, state);\n\t\t}\n\n\t\tif (WIXSTDBA_STATE_SVC_OPTIONS == state || m_state < state)\n\t\t{\n\t\t\t::PostMessageW(m_hWnd, WM_WIXSTDBA_CHANGE_STATE, 0, state);\n\t\t}\n\t}\n\n\n\tvoid DeterminePageId(\n\t\t__in WIXSTDBA_STATE state,\n\t\t__out DWORD* pdwPageId\n\t\t)\n\t{\n\t\tif (BOOTSTRAPPER_DISPLAY_PASSIVE == m_command.display)\n\t\t{\n\t\t\tswitch (state)\n\t\t\t{\n\t\t\tcase WIXSTDBA_STATE_INITIALIZED:\n\t\t\t\t*pdwPageId = BOOTSTRAPPER_ACTION_HELP == m_command.action ? m_rgdwPageIds[WIXSTDBA_PAGE_HELP] : m_rgdwPageIds[WIXSTDBA_PAGE_LOADING];\n\t\t\t\tbreak;\n\n\t\t\tcase WIXSTDBA_STATE_HELP:\n\t\t\t\t*pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_HELP];\n\t\t\t\tbreak;\n\n\t\t\tcase WIXSTDBA_STATE_DETECTING:\n\t\t\t\t*pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_LOADING] ? m_rgdwPageIds[WIXSTDBA_PAGE_LOADING] : m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] ? m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] : m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS];\n\t\t\t\tbreak;\n\n\t\t\tcase WIXSTDBA_STATE_DETECTED: __fallthrough;\n\t\t\tcase WIXSTDBA_STATE_PLANNING: __fallthrough;\n\t\t\tcase WIXSTDBA_STATE_PLANNED: __fallthrough;\n\t\t\tcase WIXSTDBA_STATE_APPLYING: __fallthrough;\n\t\t\tcase WIXSTDBA_STATE_CACHING: __fallthrough;\n\t\t\tcase WIXSTDBA_STATE_CACHED: __fallthrough;\n\t\t\tcase WIXSTDBA_STATE_EXECUTING: __fallthrough;\n\t\t\tcase WIXSTDBA_STATE_EXECUTED:\n\t\t\t\t*pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] ? m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] : m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS];\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t*pdwPageId = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\telse if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display)\n\t\t{\n\t\t\tswitch (state)\n\t\t\t{\n\t\t\tcase WIXSTDBA_STATE_INITIALIZING:\n\t\t\t\t*pdwPageId = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase WIXSTDBA_STATE_INITIALIZED:\n\t\t\t\t*pdwPageId = BOOTSTRAPPER_ACTION_HELP == m_command.action ? m_rgdwPageIds[WIXSTDBA_PAGE_HELP] : m_rgdwPageIds[WIXSTDBA_PAGE_LOADING];\n\t\t\t\tbreak;\n\n\t\t\tcase WIXSTDBA_STATE_HELP:\n\t\t\t\t*pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_HELP];\n\t\t\t\tbreak;\n\n\t\t\tcase WIXSTDBA_STATE_DETECTING:\n\t\t\t\t*pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_LOADING];\n\t\t\t\tbreak;\n\n\t\t\tcase WIXSTDBA_STATE_DETECTED:\n\t\t\t\tswitch (m_command.action)\n\t\t\t\t{\n\t\t\t\tcase BOOTSTRAPPER_ACTION_INSTALL:\n\t\t\t\t\t*pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL];\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BOOTSTRAPPER_ACTION_MODIFY: __fallthrough;\n\t\t\t\tcase BOOTSTRAPPER_ACTION_REPAIR: __fallthrough;\n\t\t\t\tcase BOOTSTRAPPER_ACTION_UNINSTALL:\n\t\t\t\t\t*pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase WIXSTDBA_STATE_INSTALLDIR:\n\t\t\t\t*pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR];\n\t\t\t\tbreak;\n\n\t\t\tcase WIXSTDBA_STATE_SVC_OPTIONS:\n\t\t\t\t*pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_SVC_OPTIONS];\n\t\t\t\tbreak;\n\n\t\t\tcase WIXSTDBA_STATE_PLANNING: __fallthrough;\n\t\t\tcase WIXSTDBA_STATE_PLANNED: __fallthrough;\n\t\t\tcase WIXSTDBA_STATE_APPLYING: __fallthrough;\n\t\t\tcase WIXSTDBA_STATE_CACHING: __fallthrough;\n\t\t\tcase WIXSTDBA_STATE_CACHED: __fallthrough;\n\t\t\tcase WIXSTDBA_STATE_EXECUTING: __fallthrough;\n\t\t\tcase WIXSTDBA_STATE_EXECUTED:\n\t\t\t\t*pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS];\n\t\t\t\tbreak;\n\n\t\t\tcase WIXSTDBA_STATE_APPLIED:\n\t\t\t\t*pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_SUCCESS];\n\t\t\t\tCopyBundleLogToSpecifiedPath();\n\t\t\t\tbreak;\n\n\t\t\tcase WIXSTDBA_STATE_FAILED:\n\t\t\t\t*pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_FAILURE];\n\t\t\t\tCopyBundleLogToSpecifiedPath();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\n\tHRESULT EvaluateConditions()\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tBOOL fResult = FALSE;\n\n\t\tfor (DWORD i = 0; i < m_Conditions.cConditions; ++i)\n\t\t{\n\t\t\tBAL_CONDITION* pCondition = m_Conditions.rgConditions + i;\n\n\t\t\thr = BalConditionEvaluate(pCondition, m_pEngine, &fResult, &m_sczFailedMessage);\n\t\t\tBalExitOnFailure(hr, \"Failed to evaluate condition.\");\n\n\t\t\tif (!fResult)\n\t\t\t{\n\t\t\t\thr = E_WIXSTDBA_CONDITION_FAILED;\n\t\t\t\tBalExitOnFailure1(hr, \"Bundle condition evaluated to false: %ls\", pCondition->sczCondition);\n\t\t\t}\n\t\t}\n\n\t\tReleaseNullStr(m_sczFailedMessage);\n\nLExit:\n\t\treturn hr;\n\t}\n\n\n\n\tvoid CopyBundleLogToSpecifiedPath()\n\t{\n\t\t/// On package install complete, if WIXSTDBA_VARIABLE_LOGSPATH is defined\n\t\t/// then will move bundle installation log to the specified path.\n\t\tif (!m_fOverallInstallationStarted)\n\t\t\treturn;\n\n\t\tif (BalStringVariableExists(WIXSTDBA_VARIABLE_LOGSPATH))\n\t\t{\n\t\t\tLPWSTR wzBundleLog = NULL;\n\t\t\tLPWSTR wzInstallLogPath = NULL;\n\t\t\tLPWSTR wzDstBundleLog = NULL;\n\n\t\t\tif ( SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_LOGSPATH, &wzInstallLogPath)) &&\n\t\t\t\tSUCCEEDED(BalGetStringVariable(L\"WixBundleLog\", &wzBundleLog)))\n\t\t\t{\n\t\t\t\tStrAllocFormatted(&wzDstBundleLog, L\"%s\\\\%s\", wzInstallLogPath, PathFile(wzBundleLog));\n\t\t\t\tDirEnsureExists(wzInstallLogPath, NULL);\n\t\t\t\tFileEnsureCopy(wzBundleLog, wzDstBundleLog, TRUE);\n\t\t\t} else\n\t\t\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"Setup was unable to copy bundle log to the specified installation log path.\");\n\t\t}\n\n\t\treturn;\n\t}\n\n\n\n\tvoid SetTaskbarButtonProgress(\n\t\t__in DWORD dwOverallPercentage\n\t\t)\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tif (m_fAttachedToConsole)\n\t\t{\n\t\t\tCONSOLE_SCREEN_BUFFER_INFO csbiInfo;\n\t\t\tif (GetConsoleScreenBufferInfo(m_fStdConsoleHandle, &csbiInfo))\n\t\t\t{\n\t\t\t\tcsbiInfo.dwCursorPosition.X = 0;\n\t\t\t\tSetConsoleCursorPosition(m_fStdConsoleHandle, csbiInfo.dwCursorPosition);\n\t\t\t}\n\n\t\t\tint lnWidth = 79;\n\t\t\tint barWidth = 60;\n\t\t\tint pos = int(barWidth * dwOverallPercentage/100);\n\t\t\tchar  szPgLine[200] = \"[\";\n\n\t\t\tfor (int i = 0; i < barWidth; ++i)\n\t\t\t{\n\t\t\t\tif (i < pos)\n\t\t\t\t{\n\t\t\t\t\tsprintf_s(szPgLine, lnWidth, \"%s%s\", szPgLine, \"=\");\n\t\t\t\t}\n\t\t\t\telse if (i == pos)\n\t\t\t\t{\n\t\t\t\t\tsprintf_s(szPgLine, lnWidth, \"%s%s\", szPgLine, \">\");\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsprintf_s(szPgLine, lnWidth, \"%s%s\", szPgLine, \" \");\n\t\t\t\t}\n\t\t\t}\n\t\t\tsprintf_s(szPgLine, lnWidth, \"%s] %u%%\", szPgLine, dwOverallPercentage);\n\n\t\t\tDWORD dSzWritten;\n\t\t\tWriteConsole(m_fStdConsoleHandle, szPgLine, strlen(szPgLine), &dSzWritten, NULL);\n\t\t\t//\t\t\tm_fStdConsoleHandle = NULL;\n\t\t}\n\n\n\t\tif (m_fTaskbarButtonOK)\n\t\t{\n//\t\t\thr = m_pTaskbarList->SetProgressValue(m_hWnd, dwOverallPercentage, 100UL);\n\t\t\tBalExitOnFailure1(hr, \"Failed to set taskbar button progress to: %d%%.\", dwOverallPercentage);\n\t\t}\n\nLExit:\n\t\treturn;\n\t}\n\n\n\tvoid SetTaskbarButtonState(\n\t\t__in TBPFLAG tbpFlags\n\t\t)\n\t{\n\t\tHRESULT hr = S_OK;\n\n\t\tif (m_fTaskbarButtonOK)\n\t\t{\n\t\t\thr = m_pTaskbarList->SetProgressState(m_hWnd, tbpFlags);\n\t\t\tBalExitOnFailure1(hr, \"Failed to set taskbar button state.\", tbpFlags);\n\t\t}\n\nLExit:\n\t\treturn;\n\t}\n\n\n\tvoid SetProgressState(\n\t\t__in HRESULT hrStatus\n\t\t)\n\t{\n\t\tTBPFLAG flag = TBPF_NORMAL;\n\n\t\tif (IsCanceled() || HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hrStatus)\n\t\t{\n\t\t\tflag = TBPF_PAUSED;\n\t\t}\n\t\telse if (IsRollingBack() || FAILED(hrStatus))\n\t\t{\n\t\t\tflag = TBPF_ERROR;\n\t\t}\n\n\t\tSetTaskbarButtonState(flag);\n\t}\n\n\n\tvoid SavePageSettings(\n\t\t__in WIXSTDBA_PAGE page\n\t\t)\n\t{\n\t\tTHEME_PAGE* pPage = NULL;\n\n\t\tpPage = ThemeGetPage(m_pTheme, m_rgdwPageIds[page]);\n\t\tif (pPage)\n\t\t{\n\t\t\tfor (DWORD i = 0; i < pPage->cControlIndices; ++i)\n\t\t\t{\n\t\t\t\t// Loop through all the checkbox controls (or buttons with BS_AUTORADIOBUTTON) with names and set a Burn variable with that name to true or false.\n\t\t\t\tTHEME_CONTROL* pControl = m_pTheme->rgControls + pPage->rgdwControlIndices[i];\n\t\t\t\tif ((THEME_CONTROL_TYPE_CHECKBOX == pControl->type) ||\n\t\t\t\t\t(THEME_CONTROL_TYPE_BUTTON == pControl->type && (BS_AUTORADIOBUTTON == (BS_AUTORADIOBUTTON & pControl->dwStyle)) &&\n\t\t\t\t\tpControl->sczName && *pControl->sczName))\n\t\t\t\t{\n\t\t\t\t\tBOOL bChecked = ThemeIsControlChecked(m_pTheme, pControl->wId);\n\t\t\t\t\tm_pEngine->SetVariableNumeric(pControl->sczName, bChecked ? 1 : 0);\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the editbox controls with names and set a Burn variable with that name to the contents.\n\t\t\t\tif (THEME_CONTROL_TYPE_EDITBOX == pControl->type && pControl->sczName && *pControl->sczName &&\n\t\t\t\t\t(WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX != pControl->wId))\n\t\t\t\t{\n\t\t\t\t\tLPWSTR sczValue = NULL;\n\t\t\t\t\tThemeGetTextControl(m_pTheme, pControl->wId, &sczValue);\n\t\t\t\t\tm_pEngine->SetVariableString(pControl->sczName, sczValue);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\n\tHRESULT LoadBootstrapperBAFunctions()\n\t{\n\t\tHRESULT hr = S_OK;\n\t\tLPWSTR sczBafPath = NULL;\n\n\t\thr = PathRelativeToModule(&sczBafPath, L\"bafunctions.dll\", m_hModule);\n\t\tBalExitOnFailure(hr, \"Failed to get path to BA function DLL.\");\n\n#ifdef DEBUG\n\t\tBalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, \"WIXEXTBA: LoadBootstrapperBAFunctions() - BA function DLL '%ls'\", sczBafPath);\n#endif\n\n\t\tm_hBAFModule = ::LoadLibraryW(sczBafPath);\n\t\tif (m_hBAFModule)\n\t\t{\n\t\t\tPFN_BOOTSTRAPPER_BA_FUNCTION_CREATE pfnBAFunctionCreate = reinterpret_cast<PFN_BOOTSTRAPPER_BA_FUNCTION_CREATE>(::GetProcAddress(m_hBAFModule, \"CreateBootstrapperBAFunction\"));\n\t\t\tBalExitOnNullWithLastError1(pfnBAFunctionCreate, hr, \"Failed to get CreateBootstrapperBAFunction entry-point from: %ls\", sczBafPath);\n\n\t\t\thr = pfnBAFunctionCreate(m_pEngine, m_hBAFModule, &m_pBAFunction);\n\t\t\tBalExitOnFailure(hr, \"Failed to create BA function.\");\n\t\t}\n#ifdef DEBUG\n\t\telse\n\t\t{\n\t\t\tBalLogError(HRESULT_FROM_WIN32(::GetLastError()), \"WIXEXTBA: LoadBootstrapperBAFunctions() - Failed to load DLL %ls\", sczBafPath);\n\t\t}\n#endif\n\nLExit:\n\t\tif (m_hBAFModule && !m_pBAFunction)\n\t\t{\n\t\t\t::FreeLibrary(m_hBAFModule);\n\t\t\tm_hBAFModule = NULL;\n\t\t}\n\t\tReleaseStr(sczBafPath);\n\n\t\treturn hr;\n\t}\n\ntypedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);\n\nbool getWindowsUserAgent(std::string &str){\n OSVERSIONINFOEX osvi;\n SYSTEM_INFO si;\n BOOL bOsVersionInfoEx;\n ZeroMemory(&si, sizeof(SYSTEM_INFO));\n ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);\n bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi); if(bOsVersionInfoEx == 0)\n  return false;\n PGNSI pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT(\"kernel32.dll\")), \"GetNativeSystemInfo\");\n if(NULL != pGNSI)\n  pGNSI(&si);\n else GetSystemInfo(&si);\n std::stringstream os;\n os << \"Installer/wix os/win32 (Windows_NT; \";\n os << osvi.dwMajorVersion << \".\" << osvi.dwMinorVersion << \".\" << osvi.dwBuildNumber;\n os << \"; ia32;)\";\n str = os.str();\n return true; \n}\n\n\n\t#pragma comment( lib,\"Wininet.lib\")\n\n\n#define BUF_LEN 1024\n\nBOOL POSTRequest(\n\t__in LPCSTR szHost,\n\t__in LPCSTR szApiPath,\n\t__in LPSTR  szFormData,\n\t__out LPSTR *ppszResponseMessage)\n{\n\tBOOL bRes = false;\n\tStrAnsiAlloc(ppszResponseMessage, BUF_LEN);\n\n\tstd::string header = \"Content-Type: application/x-www-form-urlencoded\";\n\n\tstd::string userAgent;\n\tif (getWindowsUserAgent(userAgent)) {\n\t\theader += std::string(\"\\nUser-Agent: \");\n\t\theader += userAgent;\n\t}\n\n\tLPCSTR method = \"POST\";\n\tLPCSTR agent  = \"Mozilla/4.0 (compatible; MSIE 1.0)\";\n\n\tHINTERNET internet = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);\n\tif(internet != NULL)\n\t{\n\t\tHINTERNET connect = InternetConnectA(internet, szHost, INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);\n\t\tif(connect != NULL)\n\t\t{\n\t\t\tHINTERNET request = HttpOpenRequestA(connect, method, szApiPath, \"HTTP/1.1\", NULL, NULL,\n\t\t\t\tINTERNET_FLAG_HYPERLINK |\n\t\t\t\tINTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP  |\n\t\t\t\tINTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS |\n\t\t\t\tINTERNET_FLAG_NO_AUTH |\n\t\t\t\tINTERNET_FLAG_NO_CACHE_WRITE |\n\t\t\t\tINTERNET_FLAG_NO_UI |\n\t\t\t\tINTERNET_FLAG_PRAGMA_NOCACHE |\n\t\t\t\tINTERNET_FLAG_RELOAD |\n\t\t\t\tINTERNET_FLAG_SECURE, NULL);\n\n\t\t\tif(request != NULL)\n\t\t\t{\n\t\t\t\tint datalen = 0;\n\t\t\t\tif(szFormData != NULL) datalen = strlen(szFormData);\n\t\t\t\tint headerlen = 0;\n\t\t\t\theaderlen = (int)header.length();\n\n\t\t\t\tif(HttpSendRequestA(request, header.c_str(), headerlen, szFormData, datalen))\n\t\t\t\t{\n\t\t\t\t\t// We have succesfully sent the POST request\n\t\t\t\t\tbRes = true;\n\n\t\t\t\t\t// Now we should read the response\n\t\t\t\t\tDWORD bytesRead;\n\t\t\t\t\tchar holdBuff[4096];\n\t\t\t\t\tchar* temp = holdBuff;\n\t\t\t\t\twhile (InternetReadFile(request, temp, 1024, &bytesRead) == TRUE && bytesRead > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\ttemp += bytesRead;\n\t\t\t\t\t}\n\t\t\t\t\t*temp = '\\0';    // manually append NULL terminator\n\n\t\t\t\t\tStringCchPrintfA(*ppszResponseMessage, BUF_LEN, holdBuff);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tStringCchPrintfA(*ppszResponseMessage, BUF_LEN, \"Failed to send http request. Error code: %d\", ::GetLastError());\n\n\t\t\t\tInternetCloseHandle(request);\n\t\t\t}\n\t\t\telse\n\t\t\t\tStringCchPrintfA(*ppszResponseMessage, BUF_LEN, \"Failed to open http request.\");\n\t\t}\n\t\telse\n\t\t\tStringCchPrintfA(*ppszResponseMessage, BUF_LEN, \"Connectiong to %s failed.\", szHost);\n\n\t\tInternetCloseHandle(connect);\n\t}\n\telse\n\t\tStringCchPrintfA(*ppszResponseMessage, BUF_LEN, \"Initialize internet resources failed.\");\n\tInternetCloseHandle(internet);\n\n\treturn bRes;\n}\n\n\nBOOL REST_SignInOrRegister(\n\t__in BOOL    fSignIn,\n    __in LPCWSTR wzSignInUserNameOrEmail,\n    __in LPCWSTR wzRegisterUsername,\n    __in LPCWSTR wzRegisterEmail,\n    __in LPCWSTR wzPassword/*,\n    __out LPWSTR *ppwzErrorMessage*/\n    )\n{\n\tBOOL bRes = false;\n\twchar_t wzFormData[BUF_LEN] = L\"\";\n\n\tDWORD escapedLength;\n\n\tescapedLength = BUF_LEN;\n\twchar_t wzPasswordEscaped[BUF_LEN];\n\tUrlEscapeW(wzPassword, wzPasswordEscaped, &escapedLength, NULL);\n\n\tif (fSignIn) {\n\t\t// sign in\n\t\twchar_t *wzUsernameOrEmailKey;\n\t\tif (wcschr(wzSignInUserNameOrEmail, L'@')) {\n\t\t\twzUsernameOrEmailKey = L\"meteorAccountsLoginInfo[email]\";\n\t\t} else {\n\t\t\twzUsernameOrEmailKey = L\"meteorAccountsLoginInfo[username]\";\t\t\n\t\t}\n\n\t\tescapedLength = BUF_LEN;\n\t\twchar_t wzSignInUserNameOrEmailEscaped[BUF_LEN];\n\t\tUrlEscapeW(wzSignInUserNameOrEmail, wzSignInUserNameOrEmailEscaped, &escapedLength, NULL);\n\n\t\tStringCchPrintfW(wzFormData, BUF_LEN, L\"%s=%s&meteorAccountsLoginInfo[password]=%s\", wzUsernameOrEmailKey, wzSignInUserNameOrEmailEscaped, wzPasswordEscaped);\n\t} else {\n\t\tescapedLength = BUF_LEN;\n\t\twchar_t wzRegisterUsernameEscaped[BUF_LEN];\n\t\tUrlEscapeW(wzRegisterUsername, wzRegisterUsernameEscaped, &escapedLength, NULL);\n\n\t\tescapedLength = BUF_LEN;\n\t\twchar_t wzRegisterEmailEscaped[BUF_LEN];\n\t\tUrlEscapeW(wzRegisterEmail, wzRegisterEmailEscaped, &escapedLength, NULL);\n\n\t\t// register\n\t\tStringCchPrintfW(wzFormData, BUF_LEN, L\"username=%s&email=%s&password=%s\", wzRegisterUsernameEscaped, wzRegisterEmailEscaped, wzPasswordEscaped);\n\t}\n\n  // agentInfo part of the query\n  wchar_t aiHostW[BUF_LEN] = L\"\";\n  DWORD aiHostSize = BUF_LEN;\n  GetComputerNameW(aiHostW, &aiHostSize);\n\n  wchar_t wzAgentInfo[BUF_LEN] = L\"\";\n  StringCchPrintfW(wzAgentInfo, BUF_LEN, L\"agentInfo[host]=%s&agentInfo[agent]=%s&agentInfo[agentVersion]=%s&agentInfo[arch]=%s\",\n      aiHostW, L\"Windows Installer\", L\"0.0\", L\"os.windows.x64_32\");\n  StringCchCatW(wzFormData, BUF_LEN, L\"&\");\n  StringCchCatW(wzFormData, BUF_LEN, wzAgentInfo);\n\n  size_t i;\n  char *pMBFormData = (char *)malloc( BUF_LEN );\n  wcstombs_s(&i, pMBFormData, (size_t)BUF_LEN, wzFormData, (size_t)BUF_LEN );\n\n  char *pMBDataResponse = NULL;\n\twchar_t wzErrorMessage[BUF_LEN] = L\"\";\n\n\tchar *path = fSignIn ? \"/api/v1/private/login\"\n\t                     : \"/api/v1/private/register\";\n\n\tif (POSTRequest(\"www.meteor.com\", path, pMBFormData, &pMBDataResponse))\n\t{\n\t\tJSONValue *JSONResponse = JSON::Parse(pMBDataResponse);\n\t\tif (JSONResponse != NULL)\n\t\t{\n\t\t\tsize_t n;\n\n\t\t\t// Retrieve the main object\n\t\t\tJSONObject JSONRoot;\n\t\t\tif (JSONResponse->IsObject() == false)\n\t\t\t{\n\t\t\t\tmbstowcs_s(&n, wzErrorMessage, BUF_LEN, pMBDataResponse, BUF_LEN);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tJSONRoot = JSONResponse->AsObject();\n\t\t\t\tif (JSONRoot.find(L\"reason\") != JSONRoot.end() && JSONRoot[L\"reason\"]->IsString())\n\t\t\t\t{\n\t\t\t\t\tStringCchPrintfW(wzErrorMessage, BUF_LEN, JSONRoot[L\"reason\"]->AsString().c_str());\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbRes = true;\n\n\t\t\t\t\tLPWSTR wzUMSFilePath = NULL;\n\t\t\t\t\tLPWSTR wzUMSFileExpPath = NULL;\n\t\t\t\t\tif (SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_USERMETEORSESSIONFILE, &wzUMSFilePath)))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (SUCCEEDED(BalFormatString(wzUMSFilePath, &wzUMSFileExpPath)))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFileEnsureDelete(wzUMSFileExpPath);\n\t\t\t\t\t\t\tHANDLE hFile = CreateFileW(wzUMSFileExpPath, GENERIC_ALL, 0, 0L, 1, 0x80L, 0);\n\t\t\t\t\t\t\tif (hFile != INVALID_HANDLE_VALUE)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tstd::string innerSession = pMBDataResponse;\n\t\t\t\t\t\t\t\t// In JS this would be: innerSession.userId = innerSession.id; delete innerSession.id;\n\t\t\t\t\t\t\t\tinnerSession.replace(innerSession.find(\"\\\"id\\\":\"), strlen(\"\\\"id\\\":\"), \"\\\"userId\\\":\");\n\t\t\t\t\t\t\t\t// In JS this would be: innerSession.type = \"meteor-account\"\n\t\t\t\t\t\t\t\tinnerSession.replace(innerSession.find(\"{\"), 1, \"{\\\"type\\\": \\\"meteor-account\\\", \");\n\n\t\t\t\t\t\t\t\t// In JS this would be: sessionData = {sessions: {\"www.meteor.com\": innerSession}}\n\t\t\t\t\t\t\t\tstd::string sessionData = \"{\\\"sessions\\\": {\\\"www.meteor.com\\\": \";\n\t\t\t\t\t\t\t\tsessionData += innerSession;\n\t\t\t\t\t\t\t\tsessionData += \"}}\";\n\n\t\t\t\t\t\t\t\tchar sessionDataStr[BUF_LEN];\n\t\t\t\t\t\t\t\tstrcpy_s(sessionDataStr, BUF_LEN, sessionData.c_str());\n\n\t\t\t\t\t\t\t\tDWORD bytesWritten;\n\t\t\t\t\t\t\t\tWriteFile(hFile, sessionDataStr, strlen(sessionDataStr), &bytesWritten, NULL);\n\t\t\t\t\t\t\t\tCloseHandle(hFile);\n\t\t\t\t\t\t\t}\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\t\telse {\n\t\t\twcsncat_s(wzErrorMessage, L\"Unknown error.\", BUF_LEN-1);\n\t\t}\n\n\t\t// Clean up JSON object\n\t\tdelete JSONResponse;\n\t} else {\n\t\twcsncat_s(wzErrorMessage, L\"Network error contacting the Meteor accounts server. Please retry, or skip this step and complete your registration later.\", BUF_LEN-1);\n\t}\n\n\n\tif (bRes == false)\n\t{\n\t\twchar_t wzMessage[BUF_LEN] = L\"\";\n\t\tStringCchPrintfW(wzMessage, BUF_LEN, L\"%s\", wzErrorMessage);\n\t\tMessageBoxW(m_hWnd, wzMessage, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK);\n\t}\n\n\treturn bRes;\n}\n\n\n\tHRESULT DAPI LocGetString(\n\t\t__in const WIX_LOCALIZATION* pWixLoc,\n\t\t__in_z LPCWSTR wzId,\n\t\t__out LOC_STRING** ppLocString\n\t\t)\n\t{\n\t\tHRESULT hr = E_NOTFOUND;\n\t\tLOC_STRING* pLocString = NULL;\n\n\t\tfor (DWORD i = 0; i < pWixLoc->cLocStrings; ++i)\n\t\t{\n\t\t\tpLocString = pWixLoc->rgLocStrings + i;\n\n\t\t\tif (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pLocString->wzId, -1, wzId, -1))\n\t\t\t{\n\t\t\t\t*ppLocString = pLocString;\n\t\t\t\thr = S_OK;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn hr;\n\t}\npublic:\n\t//\n\t// Constructor - intitialize member variables.\n\t//\n\tCWixStandardBootstrapperApplication(\n\t\t__in HMODULE hModule,\n\t\t__in BOOL fPrereq,\n\t\t__in IBootstrapperEngine* pEngine,\n\t\t__in const BOOTSTRAPPER_COMMAND* pCommand\n\t\t) : CBalBaseBootstrapperApplication(pEngine, pCommand, 3, 3000)\n\t{\n\t\tm_hModule = hModule;\n\t\tmemcpy_s(&m_command, sizeof(m_command), pCommand, sizeof(BOOTSTRAPPER_COMMAND));\n\n\t\t// Pre-req BA should only show help or do an install (to launch the Managed BA which can then do the right action).\n\t\tif (fPrereq && BOOTSTRAPPER_ACTION_HELP != m_command.action && BOOTSTRAPPER_ACTION_INSTALL != m_command.action)\n\t\t{\n\t\t\tm_command.action = BOOTSTRAPPER_ACTION_INSTALL;\n\t\t}\n\t\telse // maybe modify the action state if the bundle is or is not already installed.\n\t\t{\n\t\t\tLONGLONG llInstalled = 0;\n\t\t\tHRESULT hr = BalGetNumericVariable(L\"WixBundleInstalled\", &llInstalled);\n\t\t\tif (SUCCEEDED(hr) && BOOTSTRAPPER_RESUME_TYPE_REBOOT != m_command.resumeType && 0 < llInstalled && BOOTSTRAPPER_ACTION_INSTALL == m_command.action)\n\t\t\t{\n\t\t\t\tm_command.action = BOOTSTRAPPER_ACTION_MODIFY;\n\t\t\t}\n\t\t\telse if (0 == llInstalled && (BOOTSTRAPPER_ACTION_MODIFY == m_command.action || BOOTSTRAPPER_ACTION_REPAIR == m_command.action))\n\t\t\t{\n\t\t\t\tm_command.action = BOOTSTRAPPER_ACTION_INSTALL;\n\t\t\t}\n\t\t}\n\n\t\tm_plannedAction = BOOTSTRAPPER_ACTION_UNKNOWN;\n\n\t\t// When resuming from restart doing some install-like operation, try to find the package that forced the\n\t\t// restart. We'll use this information during planning.\n\t\tm_sczAfterForcedRestartPackage = NULL;\n\n\t\tif (BOOTSTRAPPER_RESUME_TYPE_REBOOT == m_command.resumeType && BOOTSTRAPPER_ACTION_UNINSTALL < m_command.action)\n\t\t{\n\t\t\t// Ensure the forced restart package variable is null when it is an empty string.\n\t\t\tHRESULT hr = BalGetStringVariable(L\"WixBundleForcedRestartPackage\", &m_sczAfterForcedRestartPackage);\n\t\t\tif (FAILED(hr) || !m_sczAfterForcedRestartPackage || !*m_sczAfterForcedRestartPackage)\n\t\t\t{\n\t\t\t\tReleaseNullStr(m_sczAfterForcedRestartPackage);\n\t\t\t}\n\t\t}\n\n\t\tm_pWixLoc = NULL;\n\t\tmemset(&m_Bundle, 0, sizeof(m_Bundle));\n\t\tmemset(&m_Conditions, 0, sizeof(m_Conditions));\n\t\tm_sczConfirmCloseMessage = NULL;\n\t\tm_sczFailedMessage = NULL;\n\n\t\tm_sczLanguage = NULL;\n\t\tm_pTheme = NULL;\n\t\tmemset(m_rgdwPageIds, 0, sizeof(m_rgdwPageIds));\n\t\tm_dwCurrentPage = 0;\n\t\tm_hUiThread = NULL;\n\t\tm_fRegistered = FALSE;\n\t\tm_hWnd = NULL;\n\n\t\tm_state = WIXSTDBA_STATE_INITIALIZING;\n\t\tm_hrFinal = S_OK;\n\n\t\tm_fDowngrading = FALSE;\n\t\tm_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE;\n\t\tm_fRestartRequired = FALSE;\n\t\tm_fAllowRestart = FALSE;\n\n\t\tm_sczLicenseFile = NULL;\n\t\tm_sczLicenseUrl = NULL;\n\t\tm_fSuppressOptionsUI = FALSE;\n\t\tm_fSuppressDowngradeFailure = FALSE;\n\t\tm_fSuppressRepair = FALSE;\n\t\tm_fShowVersion = FALSE;\n\t\tm_fIsRepair = FALSE;\n\t\tm_fIsUninstall = FALSE;\n\t\tm_fInstallSucceed = FALSE;\n\t\tm_fIsProductCore = FALSE;\n\t\tm_sdOverridableVariables = NULL;\n\t\tm_pTaskbarList = NULL;\n\t\tm_uTaskbarButtonCreatedMessage = UINT_MAX;\n\t\tm_fTaskbarButtonOK = FALSE;\n\t\tm_fShowingInternalUiThisPackage = FALSE;\n\n\t\tm_fPrereq = fPrereq;\n\t\tm_sczPrereqPackage = NULL;\n\t\tm_fPrereqInstalled = FALSE;\n\t\tm_fPrereqAlreadyInstalled = FALSE;\n\t\tm_fOverallInstallationStarted = FALSE;\n\t\tm_fUpdating = FALSE;\n\t\tm_fOutputToConsole = FALSE;\n\t\tm_fAttachedToConsole = FALSE;\n\t\tm_fStdConsoleHandle = NULL;\n\n\t\tpEngine->AddRef();\n\t\tm_pEngine = pEngine;\n\n\t\tm_hBAFModule = NULL;\n\t\tm_pBAFunction = NULL;\n\t}\n\n\n\t//\n\t// Destructor - release member variables.\n\t//\n\t~CWixStandardBootstrapperApplication()\n\t{\n\t\tCopyBundleLogToSpecifiedPath();\n\t\tAssertSz(!::IsWindow(m_hWnd), \"Window should have been destroyed before destructor.\");\n\t\tAssertSz(!m_pTheme, \"Theme should have been released before destuctor.\");\n\n\t\tif (m_fAttachedToConsole)\n\t\t{\n\t\t\tFreeConsole();\n\t\t}\n\n\t\tReleaseObject(m_pTaskbarList);\n\t\tReleaseDict(m_sdOverridableVariables);\n\t\tReleaseStr(m_sczFailedMessage);\n\t\tReleaseStr(m_sczConfirmCloseMessage);\n\t\tBalConditionsUninitialize(&m_Conditions);\n\t\tBalInfoUninitialize(&m_Bundle);\n\t\tLocFree(m_pWixLoc);\n\n\t\tReleaseStr(m_sczLanguage);\n\t\tReleaseStr(m_sczLicenseFile);\n\t\tReleaseStr(m_sczLicenseUrl);\n\t\tReleaseStr(m_sczPrereqPackage);\n\t\tReleaseStr(m_sczAfterForcedRestartPackage);\n\t\tReleaseNullObject(m_pEngine);\n\n\t\tif (m_hBAFModule)\n\t\t{\n\t\t\t::FreeLibrary(m_hBAFModule);\n\t\t\tm_hBAFModule = NULL;\n\t\t}\n\t}\n\nprivate:\n\tHMODULE m_hModule;\n\tBOOTSTRAPPER_COMMAND m_command;\n\tIBootstrapperEngine* m_pEngine;\n\tBOOTSTRAPPER_ACTION m_plannedAction;\n\n\tLPWSTR m_sczAfterForcedRestartPackage;\n\n\tWIX_LOCALIZATION* m_pWixLoc;\n\tBAL_INFO_BUNDLE m_Bundle;\n\tBAL_CONDITIONS m_Conditions;\n\tLPWSTR m_sczFailedMessage;\n\tLPWSTR m_sczConfirmCloseMessage;\n\n\tLPWSTR m_sczLanguage;\n\tTHEME* m_pTheme;\n\tDWORD m_rgdwPageIds[countof(vrgwzPageNames)];\n\tDWORD m_dwCurrentPage;\n\tHANDLE m_hUiThread;\n\tBOOL m_fRegistered;\n\tHWND m_hWnd;\n\n\tWIXSTDBA_STATE m_state;\n\tWIXSTDBA_STATE m_stateInstallPage;\n\tHRESULT m_hrFinal;\n\n\tBOOL m_fStartedExecution;\n\tDWORD m_dwCalculatedCacheProgress;\n\tDWORD m_dwCalculatedExecuteProgress;\n\n\tBOOL m_fDowngrading;\n\tBOOTSTRAPPER_APPLY_RESTART m_restartResult;\n\tBOOL m_fRestartRequired;\n\tBOOL m_fAllowRestart;\n\n\tLPWSTR m_sczLicenseFile;\n\tLPWSTR m_sczLicenseUrl;\n\tBOOL m_fSuppressOptionsUI;\n\tBOOL m_fSuppressDowngradeFailure;\n\tBOOL m_fSuppressRepair;\n\tBOOL m_fShowVersion;\n\tBOOL m_fIsRepair;\n\tBOOL m_fIsUninstall;\n\tBOOL m_fInstallSucceed;\n\n\tBOOTSTRAPPER_RELATED_OPERATION m_Operation;\n\n\tBOOL m_fIsProductCore;\n\tBOOL m_fOverallInstallationStarted;\n\n\n\tSTRINGDICT_HANDLE m_sdOverridableVariables;\n\n\tBOOL m_fPrereq;\n\tLPWSTR m_sczPrereqPackage;\n\tBOOL m_fPrereqInstalled;\n\tBOOL m_fPrereqAlreadyInstalled;\n\tBOOL m_fOutputToConsole;\n\tBOOL m_fAttachedToConsole;\n\tHANDLE m_fStdConsoleHandle;\n\n\tITaskbarList3* m_pTaskbarList;\n\tUINT m_uTaskbarButtonCreatedMessage;\n\tBOOL m_fTaskbarButtonOK;\n\tBOOL m_fShowingInternalUiThisPackage;\n\n\tBOOL m_fUpdating;\n\tLPCWSTR m_wzUpdateLocation;\n\n\tHMODULE m_hBAFModule;\n\tIBootstrapperBAFunction* m_pBAFunction;\n};\n\n\n//\n// CreateUserExperience - creates a new IBurnUserExperience object.\n//\nHRESULT CreateBootstrapperApplication(\n\t__in HMODULE hModule,\n\t__in BOOL fPrereq,\n\t__in IBootstrapperEngine* pEngine,\n\t__in const BOOTSTRAPPER_COMMAND* pCommand,\n\t__out IBootstrapperApplication** ppApplication\n\t)\n{\n\tHRESULT hr = S_OK;\n\tCWixStandardBootstrapperApplication* pApplication = NULL;\n\n\tpApplication = new CWixStandardBootstrapperApplication(hModule, fPrereq, pEngine, pCommand);\n\tExitOnNull(pApplication, hr, E_OUTOFMEMORY, \"Failed to create new standard bootstrapper application object.\");\n\n\t*ppApplication = pApplication;\n\tpApplication = NULL;\n\nLExit:\n\tReleaseObject(pApplication);\n\treturn hr;\n}\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/precomp.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"precomp.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Precompiled header for standard bootstrapper application.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n#include <windows.h>\n#include <gdiplus.h>\n#include <msiquery.h>\n#include <objbase.h>\n#include <shlobj.h>\n#include <shlwapi.h>\n#include <stdlib.h>\n#include <strsafe.h>\n\n#include \"dutil.h\"\n#include \"memutil.h\"\n#include \"dictutil.h\"\n#include \"dirutil.h\"\n#include \"fileutil.h\"\n#include \"locutil.h\"\n#include \"logutil.h\"\n#include \"pathutil.h\"\n#include \"resrutil.h\"\n#include \"shelutil.h\"\n#include \"strutil.h\"\n#include \"thmutil.h\"\n#include \"uriutil.h\"\n#include \"xmlutil.h\"\n\n#include \"IBootstrapperEngine.h\"\n#include \"IBootstrapperApplication.h\"\n\n#include \"BalBaseBootstrapperApplication.h\"\n#include \"balinfo.h\"\n#include \"balcondition.h\"\n\nHRESULT CreateBootstrapperApplication(\n    __in HMODULE hModule,\n    __in BOOL fPrereq,\n    __in IBootstrapperEngine* pEngine,\n    __in const BOOTSTRAPPER_COMMAND* pCommand,\n    __out IBootstrapperApplication** ppApplication\n    );\n\n#include \"IBootstrapperBAFunction.h\"\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/resource.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"resource.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//-------------------------------------------------------------------------------------------------\n\n//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n//\n#define IDC_STATIC                      -1\n\n\n// Next default values for new objects\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        102\n#define _APS_NEXT_COMMAND_VALUE         40001\n#define _APS_NEXT_CONTROL_VALUE         1003\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/wixstdba.cpp",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"wixstdba.cpp\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//\n// <summary>\n// Setup chainer/bootstrapper standard UI for WiX toolset.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#include \"precomp.h\"\n\nstatic HINSTANCE vhInstance = NULL;\n\nextern \"C\" BOOL WINAPI DllMain(\n    IN HINSTANCE hInstance,\n    IN DWORD dwReason,\n    IN LPVOID /* pvReserved */\n    )\n{\n    switch(dwReason)\n    {\n    case DLL_PROCESS_ATTACH:\n        ::DisableThreadLibraryCalls(hInstance);\n        vhInstance = hInstance;\n        break;\n\n    case DLL_PROCESS_DETACH:\n        vhInstance = NULL;\n        break;\n    }\n\n    return TRUE;\n}\n\n\nextern \"C\" HRESULT WINAPI BootstrapperApplicationCreate(\n    __in IBootstrapperEngine* pEngine,\n    __in const BOOTSTRAPPER_COMMAND* pCommand,\n    __out IBootstrapperApplication** ppApplication\n    )\n{\n    HRESULT hr = S_OK;\n\n    BalInitialize(pEngine);\n\n    hr = CreateBootstrapperApplication(vhInstance, FALSE, pEngine, pCommand, ppApplication);\n    BalExitOnFailure(hr, \"Failed to create bootstrapper application interface.\");\n\nLExit:\n    return hr;\n}\n\n\nextern \"C\" void WINAPI BootstrapperApplicationDestroy()\n{\n    BalUninitialize();\n}\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/wixstdba.def",
    "content": ";-------------------------------------------------------------------------------------------------\n; <copyright file=\"wixstdba.def\" company=\"Outercurve Foundation\">\n;   Copyright (c) 2004, Outercurve Foundation.\n;   This software is released under Microsoft Reciprocal License (MS-RL).\n;   The license and further copyright text can be found in the file\n;   LICENSE.TXT at the root directory of the distribution.\n; </copyright>\n; \n; <summary>\n;    WiX Standard Bootstrapper Application DLL entry points.\n; </summary>\n;-------------------------------------------------------------------------------------------------\n\nEXPORTS\n    BootstrapperApplicationCreate\n    BootstrapperApplicationDestroy\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/wixstdba.rc",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"wixstdba.rc\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//\n// <summary>\n// WiX Extendend Bootstrapper Application resource file.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#define VER_APP\n#define VER_ORIGINAL_FILENAME \"wixextba.dll\"\n#define VER_INTERNAL_NAME \"wixextba\"\n#define VER_PRODUCT_NAME \"WiX Extendend Bootstrapper Application\"\n#define VER_FILE_DESCRIPTION \"WiX Extendend Bootstrapper Application\"\n#include \"wix.rc\"\n"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/wixstdba.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  <copyright file=\"wixstdba.vcxproj\" company=\"Outercurve Foundation\">\n    Copyright (c) 2004, Outercurve Foundation.\n    This software is released under Microsoft Reciprocal License (MS-RL).\n    The license and further copyright text can be found in the file\n    LICENSE.TXT at the root directory of the distribution.\n  </copyright>\n-->\n<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{41085a22-e6aa-4e8b-ab1b-ddee0dc89dfa}</ProjectGuid>\n    <RootNamespace>WixStdBA</RootNamespace>\n    <Keyword>Win32Proj</Keyword>\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <CharacterSet>MultiByte</CharacterSet>\n    <ProjectName>wixextba</ProjectName>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <PlatformToolset>v100</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Label=\"Configuration\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <PlatformToolset>v100</PlatformToolset>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">$(Configuration)\\</OutDir>\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">$(Configuration)\\</IntDir>\n    <GenerateManifest Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</GenerateManifest>\n    <CodeAnalysisRuleSet Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">AllRules.ruleset</CodeAnalysisRuleSet>\n    <CodeAnalysisRules Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" />\n    <CodeAnalysisRuleAssemblies Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" />\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">$(Configuration)\\</OutDir>\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">$(Configuration)\\</IntDir>\n    <GenerateManifest Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">true</GenerateManifest>\n    <CodeAnalysisRuleSet Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">AllRules.ruleset</CodeAnalysisRuleSet>\n    <CodeAnalysisRules Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" />\n    <CodeAnalysisRuleAssemblies Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" />\n  </PropertyGroup>\n  <PropertyGroup>\n    <ExtraDefinitions>\n    </ExtraDefinitions>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <AdditionalIncludeDirectories>$(WiX)SDK\\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;DEBUG;%(PreprocessorDefinitions);$(ExtraDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>true</MinimalRebuild>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>\n      <ProgramDataBaseFileName>$(IntDir)$(ProjectName).pdb</ProgramDataBaseFileName>\n      <WarningLevel>Level4</WarningLevel>\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n      <CallingConvention>StdCall</CallingConvention>\n      <TreatWarningAsError>true</TreatWarningAsError>\n      <DisableSpecificWarnings>4995</DisableSpecificWarnings>\n    </ClCompile>\n    <ResourceCompile>\n      <AdditionalIncludeDirectories>$(ProjectDir)..\\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n    </ResourceCompile>\n    <Link>\n      <AdditionalDependencies>dutil.lib;balutil.lib;comctl32.lib;msimg32.lib;gdiplus.lib;shlwapi.lib;wininet.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <AdditionalLibraryDirectories>..\\..\\WiXSDK\\VS2010\\lib\\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n      <ModuleDefinitionFile>wixstdba.def</ModuleDefinitionFile>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Windows</SubSystem>\n    </Link>\n    <PostBuildEvent>\n      <Command>\n      </Command>\n    </PostBuildEvent>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <AdditionalIncludeDirectories>..\\..\\WiXSDK\\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);$(ExtraDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>true</MinimalRebuild>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>\n      <ProgramDataBaseFileName>$(IntDir)$(ProjectName).pdb</ProgramDataBaseFileName>\n      <WarningLevel>Level4</WarningLevel>\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n      <CallingConvention>StdCall</CallingConvention>\n      <TreatWarningAsError>true</TreatWarningAsError>\n      <DisableSpecificWarnings>4995</DisableSpecificWarnings>\n    </ClCompile>\n    <ResourceCompile>\n      <AdditionalIncludeDirectories>$(ProjectDir)..\\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n    </ResourceCompile>\n    <Link>\n      <AdditionalDependencies>dutil.lib;balutil.lib;comctl32.lib;msimg32.lib;gdiplus.lib;shlwapi.lib;wininet.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <AdditionalLibraryDirectories>..\\..\\WiXSDK\\VS2010\\lib\\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n      <ModuleDefinitionFile>wixstdba.def</ModuleDefinitionFile>\n      <GenerateDebugInformation>false</GenerateDebugInformation>\n      <SubSystem>Windows</SubSystem>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"JSON.cpp\" />\n    <ClCompile Include=\"JSONValue.cpp\" />\n    <ClCompile Include=\"WixStandardBootstrapperApplication.cpp\" />\n    <ClCompile Include=\"wixstdba.cpp\">\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">Create</PrecompiledHeader>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"Resources\\logo.png\" />\n    <None Include=\"Resources\\LoremIpsumLicense.rtf\" />\n    <None Include=\"Resources\\HyperlinkTheme.wxl\" />\n    <None Include=\"Resources\\HyperlinkTheme.xml\" />\n    <None Include=\"Resources\\RtfTheme.wxl\" />\n    <None Include=\"Resources\\RtfTheme.xml\">\n      <SubType>Designer</SubType>\n    </None>\n    <None Include=\"wixstdba.def\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"wixstdba.rc\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"JSON.h\" />\n    <ClInclude Include=\"JSONValue.h\" />\n    <ClInclude Include=\"precomp.h\" />\n    <ClInclude Include=\"resource.h\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "scripts/windows/installer/WiXBalExtension/wixstdba/wixstdba.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"Resource Files\">\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"WixStandardBootstrapperApplication.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"wixstdba.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"JSON.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"JSONValue.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"wixstdba.def\">\n      <Filter>Source Files</Filter>\n    </None>\n    <None Include=\"Resources\\HyperlinkTheme.wxl\">\n      <Filter>Resource Files</Filter>\n    </None>\n    <None Include=\"Resources\\HyperlinkTheme.xml\">\n      <Filter>Resource Files</Filter>\n    </None>\n    <None Include=\"Resources\\logo.png\">\n      <Filter>Resource Files</Filter>\n    </None>\n    <None Include=\"Resources\\LoremIpsumLicense.rtf\">\n      <Filter>Resource Files</Filter>\n    </None>\n    <None Include=\"Resources\\RtfTheme.wxl\">\n      <Filter>Resource Files</Filter>\n    </None>\n    <None Include=\"Resources\\RtfTheme.xml\">\n      <Filter>Resource Files</Filter>\n    </None>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"precomp.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"resource.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"JSON.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"JSONValue.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"wixstdba.rc\">\n      <Filter>Resource Files</Filter>\n    </ResourceCompile>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "scripts/windows/installer/WiXHelper/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studo 2015 cache/options directory\n.vs/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding addin-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings \n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Windows Azure Build Output\ncsx/\n*.build.csdef\n\n# Windows Store app package directory\nAppPackages/\n\n# Others\n*.[Cc]ache\nClientBin/\n[Ss]tyle[Cc]op.*\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\nbower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n"
  },
  {
    "path": "scripts/windows/installer/WiXHelper/CustomAction.cpp",
    "content": "#include \"stdafx.h\"\n\n\n#include <string>\n\n#include <wcautil.h>\n#include <strutil.h>\n\n#include <pathutil.h>\n#include <fileutil.h>\n#include <dirutil.h>\n\n#include <urlmon.h>\n#include <wininet.h>\n#include <sys/stat.h>\n\n#define BUF_LEN 1024\n#define MAX_LONG_PATH 2048\n#define LOG true\n\n\n    \n\n\n\n\n\nHRESULT ExtractBinary(\n\t__in LPCWSTR wzBinaryId,\n\t__out BYTE** pbData,\n\t__out DWORD* pcbData\n\t)\n{\n\tHRESULT hr = S_OK;\n\tLPWSTR pwzSql = NULL;\n\tPMSIHANDLE hView;\n\tPMSIHANDLE hRec;\n\n\t// make sure we're not horked from the get-go\n\thr = WcaTableExists(L\"Binary\");\n\tif (S_OK != hr)\n\t{\n\t\tif (SUCCEEDED(hr))\n\t\t{\n\t\t\thr = E_UNEXPECTED;\n\t\t}\n\t\tExitOnFailure(hr, \"There is no Binary table.\");\n\t}\n\n\tExitOnNull(wzBinaryId, hr, E_INVALIDARG, \"Binary ID cannot be null\");\n\tExitOnNull(*wzBinaryId, hr, E_INVALIDARG, \"Binary ID cannot be empty string\");\n\n\thr = StrAllocFormatted(&pwzSql, L\"SELECT `Data` FROM `Binary` WHERE `Name`=\\'%s\\'\", wzBinaryId);\n\tExitOnFailure(hr, \"Failed to allocate Binary table query.\");\n\n\thr = WcaOpenExecuteView(pwzSql, &hView);\n\tExitOnFailure(hr, \"Failed to open view on Binary table\");\n\n\thr = WcaFetchSingleRecord(hView, &hRec);\n\tExitOnFailure(hr, \"Failed to retrieve request from Binary table\");\n\n\thr = WcaGetRecordStream(hRec, 1, pbData, pcbData);\n\tExitOnFailure(hr, \"Failed to read Binary.Data.\");\n\nLExit:\n\tReleaseStr(pwzSql);\n\treturn hr;\n}\n\n\nHRESULT ExtractBinaryToFile(\n\t__in LPCWSTR wzBinaryId,\n\t__in LPCWSTR wzFilePath\n\t)\n{\n\tHRESULT hr = S_OK;\n\tBYTE* pbData = NULL;\n\tDWORD cbData = 0;\n\tDWORD cbWritten = 0;\n\n\tHANDLE hFile = INVALID_HANDLE_VALUE;\n\n\twchar_t szTmpFile[BUF_LEN] = L\"\";\tDWORD nTmpFileLen = BUF_LEN;\n\thr = ExtractBinary(wzBinaryId, &pbData, &cbData);\n\n\thFile = CreateFile(wzFilePath, GENERIC_WRITE,FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\n\tif (hFile != INVALID_HANDLE_VALUE) {\n\t\tWriteFile(hFile, pbData, cbData, &cbWritten, NULL);\n\t\tCloseHandle(hFile);\n\t}\n\telse\n\t{\n\t\thr = HRESULT_FROM_WIN32(::GetLastError());\n\t}\n\n\treturn hr;\n}\n\n\n\n\nBOOL ExecuteCommandLine(LPWSTR CommandLine, DWORD & exitCode)\n{\n\tPROCESS_INFORMATION processInformation = {0};\n\tSTARTUPINFO startupInfo                = {0};\n\tstartupInfo.cb                         = sizeof(startupInfo);\n\n\t// Create the process\n\tBOOL result = CreateProcess(NULL, CommandLine, \n\t\tNULL, NULL, FALSE, \n\t\tNORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, \n\t\tNULL, NULL, &startupInfo, &processInformation);\n\n\tif (!result)\n\t{\n\t\t// CreateProcess() failed;   Get the error from the system\n\t\tLPVOID lpMsgBuf;\n\t\tDWORD dw = GetLastError();\n\t\tFormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, \n\t\t\tNULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);\n\n\t\t// Display the error\n\t\tLPTSTR strError = (LPTSTR) lpMsgBuf;\n\n\t\t// Free resources created by the system\n\t\tLocalFree(lpMsgBuf);\n\n\t\t// We failed.\n\t\treturn FALSE;\n\t}\n\telse\n\t{\n\t\t// Successfully created the process.  Wait for it to finish.\n\t\tWaitForSingleObject( processInformation.hProcess, INFINITE );\n\n\t\t// Get the exit code.\n\t\tresult = GetExitCodeProcess(processInformation.hProcess, &exitCode);\n\n\t\t// Close the handles.\n\t\tCloseHandle( processInformation.hProcess );\n\t\tCloseHandle( processInformation.hThread );\n\n\t\tif (!result) {\n\t\t\treturn FALSE;\n\t\t} else {\n\t\t\t// We succeeded.\n\t\t\treturn TRUE;\n\t\t}\n\t}\n}\n\n\nHRESULT UnzipToFolder(\n\tMSIHANDLE hInstall,\n\t__in LPCWSTR wzFriendlyName,\n\t__in LPCWSTR wzTarGzFileName,\n\t__in LPCWSTR wzDestPath\n\t)\n{\n\tHRESULT hr = S_OK;\n\n\tWcaLog(LOGMSG_STANDARD, \"Extract \\\"%S\\\" package initialized.\", wzFriendlyName);\n\n\twchar_t szSourceDir[BUF_LEN] = L\"\";\tDWORD nSourceDirDirLen = BUF_LEN;\n\twchar_t szTarGzFilePath[BUF_LEN] = L\"\";\n\twchar_t szTarFilePath[BUF_LEN] = L\"\";\n\tMsiGetProperty(hInstall, L\"SourceDir\", szSourceDir, &nSourceDirDirLen);\n\tStringCchPrintf(szTarGzFilePath, BUF_LEN, L\"%s%s\", szSourceDir, wzTarGzFileName);\n\tStringCchPrintf(szTarFilePath, BUF_LEN, L\"%s*.tar\", szSourceDir);\n\n\tDWORD pdwAttr;\n\tif (FileExistsEx(szTarGzFilePath, &pdwAttr) == TRUE)\n\t{\n\t\t//Extacting quality_cloud_production.sql to %TEMP% folder\n\t\twchar_t szTmpDir[BUF_LEN] = L\"\";\t\tDWORD nTmpDirLen = BUF_LEN;\n\t\twchar_t sz7Zip[BUF_LEN] = L\"\";\n\n\t\twchar_t szCommandLine1[BUF_LEN] = L\"\";\n\t\twchar_t szCommandLine2[BUF_LEN] = L\"\";\n\n\t\tMsiGetProperty(hInstall, L\"TempFolder\", szTmpDir, &nTmpDirLen);\n\t\tStringCchPrintf(sz7Zip, BUF_LEN, L\"%s%s\", szTmpDir, L\"7za.exe\");\n\n\t\tDWORD pdwAttr;\n\t\tif (FileExistsEx(sz7Zip, &pdwAttr) == FALSE)\n\t\t{\n\t\t\thr = ExtractBinaryToFile(L\"SevenZip\", sz7Zip);\n\t\t}\n\n\t\tDWORD nRes=0;\n\n\t\t// Remove old Meteor installs\n\t\twchar_t szCmdRemoveOld[BUF_LEN] = L\"\";\n\t\twchar_t szSysDir[BUF_LEN] = L\"\";\n\t\tDWORD nSysDirLen = BUF_LEN;\n\t\tMsiGetProperty(hInstall, L\"SystemFolder\", szSysDir, &nSysDirLen);\n\n\t\tLPTSTR ErrorMessage = NULL;\n\n\t\tStringCchPrintf(szCmdRemoveOld, BUF_LEN, L\"%s\\\\cmd.exe /C \\\"RD /S /Q \\\"%s\\\\.meteor\\\">NUL\\\"\", szSysDir, wzDestPath);\n\t\tStringCchPrintf(szCommandLine1, BUF_LEN, L\"\\\"%s\\\" x -o\\\"%s\\\" -y \\\"%s\\\"\", sz7Zip, szSourceDir, szTarGzFilePath);\n\t\tStringCchPrintf(szCommandLine2, BUF_LEN, L\"\\\"%s\\\" x -o\\\"%s\\\" -y \\\"%s\\\"\", sz7Zip, wzDestPath, szTarFilePath);\n\n\t\tif (! ExecuteCommandLine(szCmdRemoveOld, nRes)) {\n\t\t\tFormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, HRESULT_FROM_WIN32(nRes), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&ErrorMessage, 0, NULL);\n\t\t\tif (NULL != ErrorMessage) WcaLog(LOGMSG_STANDARD, \"Deleting old install completed with (%d): %S\", nRes, ErrorMessage);\n\t\t\treturn HRESULT_FROM_WIN32(nRes);\n\t\t}\n\n\t\tif (! ExecuteCommandLine(szCommandLine1, nRes)) {\n\t\t\tFormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, HRESULT_FROM_WIN32(nRes), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&ErrorMessage, 0, NULL);\n\t\t\tif (NULL != ErrorMessage) WcaLog(LOGMSG_STANDARD, \"Archive expanding completed with (%d): %S\", nRes, ErrorMessage);\n\t\t\treturn HRESULT_FROM_WIN32(nRes);\n\t\t}\n\n\t\tif (! ExecuteCommandLine(szCommandLine2, nRes)) {\n\t\t\tFormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, HRESULT_FROM_WIN32(nRes), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&ErrorMessage, 0, NULL);\n\t\t\tif (NULL != ErrorMessage) WcaLog(LOGMSG_STANDARD, \"Archive deployment completed with (%d): %S\", nRes, ErrorMessage);\n\t\t\treturn HRESULT_FROM_WIN32(nRes);\n\t\t}\n\t}\n\telse\n\t{\n\t\thr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);\n\t\tWcaLog(LOGMSG_STANDARD, \"Failed to extract %S files. File not found: %S\", wzFriendlyName, szTarGzFilePath); \n\t}\n\n\tWcaLog(LOGMSG_STANDARD, \"Extracting \\\"%S\\\" package completed.\", wzFriendlyName);\n\n\treturn hr;\n}\n\n\nUINT __stdcall Extract_MeteorFiles(MSIHANDLE hInstall)\n{\n\t// If cancelled, don't try to extract anything.\n\twchar_t szValueBuf[64];\n\tDWORD szValueBufSize = 64;\n\tMsiGetProperty(hInstall, L\"Cancelled\", szValueBuf, &szValueBufSize);\n\tif (szValueBuf[0] == L'Y')\n\t\treturn 0;\n\n\t// Go ahead.\n\tHRESULT hr = S_OK;\n\tUINT er = ERROR_SUCCESS;\n\n\thr = WcaInitialize(hInstall, \"Extract_MeteorFiles\");\n\tExitOnFailure(hr, \"Failed to initialize Extract_MeteorFiles\");\n\n\twchar_t szMeteorDir[BUF_LEN] = L\"\";\tDWORD nMeteorDirLen = BUF_LEN;\n\tMsiGetProperty(hInstall, L\"METEOR_DIR\", szMeteorDir, &nMeteorDirLen);\n\n\thr = UnzipToFolder(hInstall, L\"Meteor\", L\"meteor-bootstrap-os.windows.x86_32.tar.gz\", szMeteorDir);\n\tExitOnFailure(hr, \"Failed to extract Meteor files.\");\n\nLExit:\n\ter = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;\n\treturn WcaFinalize(er);\n}\n\n\n\nHRESULT Download_Package(\n\tMSIHANDLE hInstall,\n\t__in LPCWSTR wzFriendlyName,\n\t__in LPCWSTR szDwnUrl,\n\t__in LPCWSTR wzZipFile)\n{\n\tHRESULT hr = S_OK;\n\n\tWcaLog(LOGMSG_STANDARD, \"Download package \\\"%S\\\" initialized.\", wzFriendlyName);\n\n\twchar_t szSourceDir[BUF_LEN] = L\"\";\tDWORD nSourceDirDirLen = BUF_LEN;\n\twchar_t szZipFile[BUF_LEN] = L\"\";\n\n\tMsiGetProperty(hInstall, L\"SourceDir\", szSourceDir, &nSourceDirDirLen);\n\n\tStringCchPrintf(szZipFile, BUF_LEN, L\"%s%s\", szSourceDir, wzZipFile);\n\n\tHINTERNET internet = InternetOpen(\n\t\tL\"MeteorWindowsInstaller/1.0\",\n\t\tINTERNET_OPEN_TYPE_PRECONFIG,\n\t\tNULL,\n\t\tNULL,\n\t\t0);\n\n\tif (internet == NULL) {\n\t\treturn HRESULT_FROM_WIN32(::GetLastError());\n\t}\n\n\tHINTERNET request = InternetOpenUrl(\n\t\tinternet,\n\t\tszDwnUrl,\n\t\tNULL,\n\t\t0,\n\t\tINTERNET_FLAG_SECURE,\n\t\tNULL);\n\n\tif (request == NULL) {\n\t\treturn HRESULT_FROM_WIN32(::GetLastError());\n\t}\n\n    DWORD dwContentLen;\n    DWORD dwBufLen = sizeof(dwContentLen);\n\n\tBOOL result = HttpQueryInfo(\n\t\trequest,\n\t\tHTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,\n    \t(LPVOID)&dwContentLen,\n\t    &dwBufLen,\n\t    0);\n\n\tif (!request) {\n\t\treturn HRESULT_FROM_WIN32(::GetLastError());\n\t}\n\n    const int capacity = 1024*64;\n    char* buffer = new char[capacity];\n  \tDWORD bytes_downloaded = 0;\n\n    FILE* output = _wfopen(szZipFile, L\"wb\");\n    for (;;) {\n    \tDWORD bytes_read;\n\n    \tBOOL result = InternetReadFile(\n    \t\trequest,\n    \t\tbuffer,\n    \t\tcapacity,\n    \t\t&bytes_read);\n\n\t\tif (!result) {\n\t\t\treturn HRESULT_FROM_WIN32(::GetLastError());\n\t\t}\n\n\t    if (bytes_read == 0) {\n\t    \tbreak;\n\t    }\n\n\t    bytes_downloaded += bytes_read;\n\n    \tfwrite(buffer, 1, bytes_read, output);\n\n    \t// update progress bar\n   \t\tPMSIHANDLE hActionRec = MsiCreateRecord(3);\n        PMSIHANDLE hProgressRec = MsiCreateRecord(3);\n\n\t\tDWORD ulPrc = 0;\n\t\tWCHAR wzInfo[1024] = { };\n\n\t\tulPrc  = static_cast<DWORD>(100 * static_cast<double>(bytes_downloaded) / static_cast<double>(dwContentLen));\n\t\t::StringCchPrintfW(wzInfo, countof(wzInfo), L\"Downloading Meteor...  %u%%\", ulPrc);\n \n        MsiRecordSetString(hActionRec, 1, TEXT(\"Download_MeteorPackage\"));\n        MsiRecordSetString(hActionRec, 2, wzInfo);\n        MsiRecordSetString(hActionRec, 3, NULL);\n\n        UINT iResult = MsiProcessMessage(hInstall, INSTALLMESSAGE_ACTIONSTART, hActionRec);\n\n        // XXX I *thought* this should return IDCANCEL, and have verified that\n        // that's what\n        // WixStandardBootstrapperApplication.cpp::OnExecuteMsiMessage\n        // returns. But for some reason `iResult` ends up being 1.\n        if (iResult == 1) {\n        \tfclose(output);\n        \tMsiSetProperty(hInstall, L\"Cancelled\", L\"Y\"); // read from Extract_MeteorFiles\n            return ERROR_INSTALL_USEREXIT;\n        }\n\t}\n\n    fclose(output);\n\n\tWcaLog(LOGMSG_STANDARD, \"Download package \\\"%S\\\" completed.\", wzFriendlyName);\n\n\treturn hr;\n}\n\n\n// assumes content is at most 1024 characters\nUINT FetchHTTPSToShortString(wchar_t *url, char *result) {\n\tHINTERNET internet = InternetOpen(\n\t\tL\"MeteorWindowsInstaller/1.0\",\n\t\tINTERNET_OPEN_TYPE_PRECONFIG,\n\t\tNULL,\n\t\tNULL,\n\t\t0);\n\n\tif (internet == NULL) {\n\t\treturn ::GetLastError();\n\t}\n\n\tHINTERNET request = InternetOpenUrl(\n\t\tinternet,\n\t\turl,\n\t\tNULL,\n\t\t0,\n\t\tINTERNET_FLAG_SECURE,\n\t\tNULL);\n\n\tif (request == NULL) {\n\t\treturn ::GetLastError();\n\t}\n\n\tDWORD bytes_read;\n\tBOOL readResult = InternetReadFile(\n\t\trequest,\n\t\tresult,\n\t\t1023,\n\t\t&bytes_read);\n\tif (!readResult) {\n\t\treturn ::GetLastError();\n\t}\n\tresult[bytes_read] = 0;\n\n\treturn 0;\n}\n\n\nUINT __stdcall Download_MeteorPackage(MSIHANDLE hInstall)\n{\n\tHRESULT hr = S_OK;\n\tUINT er = ERROR_SUCCESS;\n\tUINT httpEr;\n\n\thr = WcaInitialize(hInstall, \"Download_MeteorPackage\");\n\tExitOnFailure(hr, \"Failed to initialize Download_MeteorPackage\");\n\n\tchar bootstrapLink[1024];\n\n\thttpEr = FetchHTTPSToShortString(L\"https://packages.meteor.com/bootstrap-link\", bootstrapLink);\n\tif (httpEr) {\n\t\thr = HRESULT_FROM_WIN32(httpEr);\n\t\tMessageBoxA(NULL, \"Failed to contact install server. Please try again later.\", NULL, NULL);\n\t\tExitOnFailure(hr, \"Couldn't get bootstap-link\"); \n\t}\n\n\t// strip trailing newline; if it's not there it's probably because we're\n\t// getting some bad response from packages.meteor.com.\n\tchar *bootstrapLinkNewline = strchr(bootstrapLink, '\\n');\n\tif (!bootstrapLinkNewline) {\n\t\tMessageBoxA(NULL, \"Malformed response from install server. Please try again later.\", NULL, NULL);\n\t\tExitOnFailure(E_FAIL, \"Couldn't parse bootstrap-link\"); \t\t\n\t}\n\n\t*bootstrapLinkNewline = '\\0';\n\n\tchar downloadUrl[1024];\n\tsprintf(downloadUrl, \"%s/meteor-bootstrap-os.windows.x86_32.tar.gz\", bootstrapLink);\n\n\twchar_t wDownloadUrl[1024];\n\tmbstowcs(wDownloadUrl, downloadUrl, 1024);\n\n\thr = Download_Package(hInstall, L\"Meteor\", wDownloadUrl, L\"meteor-bootstrap-os.windows.x86_32.tar.gz\");\n\tif (FAILED(hr)) {\n\t\tMessageBoxA(NULL, \"Failed to download Meteor installation package. Please try again later.\", NULL, NULL);\n\t}\t\n\tExitOnFailure(hr, \"Failed to download Meteor package from specified URL.\"); \n\nLExit:\n\ter = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;\n\treturn WcaFinalize(er);\n}\n\n\n\n\nUINT __stdcall BulkRemoveMeteorFiles(MSIHANDLE hInstall)\n{\n\tHRESULT hr = S_OK;\n\tUINT er = ERROR_SUCCESS;\n\n\thr = WcaInitialize(hInstall, \"BulkRemoveMeteorFiles\");\n\tExitOnFailure(hr, \"Failed to initialize BulkRemoveMeteorFiles\");\n\n\tWcaLog(LOGMSG_STANDARD, \"BulkRemoveMeteorFiles Initialized.\");\n\n\twchar_t szPathPackages[BUF_LEN] = L\"\";\tDWORD nPathPackages = BUF_LEN;\n\twchar_t szPathPkg_Meta[BUF_LEN]  = L\"\";\tDWORD nPathPkg_Meta  = BUF_LEN;\n\n\tMsiGetProperty(hInstall, L\"METEORDIR_PACKAGES\", szPathPackages, &nPathPackages);\n\tMsiGetProperty(hInstall, L\"METEORDIR_PKG_META\", szPathPkg_Meta, &nPathPkg_Meta);\n\t\n\twchar_t szSysDir[BUF_LEN] = L\"\";\tDWORD nSysDirLen = BUF_LEN;\n\twchar_t szCmd1[BUF_LEN] = L\"\";\t\t\n\twchar_t szCmd2[BUF_LEN] = L\"\";\t\n\n\tDWORD nRes=0;\n\t\n\t\n\tMsiGetProperty(hInstall, L\"SystemFolder\", szSysDir, &nSysDirLen);\n\tStringCchPrintf(szCmd1, BUF_LEN, L\"%s\\\\cmd.exe /C \\\"RD /S /Q \\\"%s\\\">NUL\\\"\", szSysDir, szPathPackages);\n\tStringCchPrintf(szCmd2, BUF_LEN, L\"%s\\\\cmd.exe /C \\\"RD /S /Q \\\"%s\\\">NUL\\\"\", szSysDir, szPathPkg_Meta);\n\n\tExecuteCommandLine(szCmd1, nRes);\n\tExecuteCommandLine(szCmd2, nRes);\n\n\tWcaLog(LOGMSG_STANDARD, \"BulkRemoveMeteorFiles done.\");\n\nLExit:\n\ter = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;\n\treturn WcaFinalize(er);\n}\n\n\n\n\n// DllMain - Initialize and cleanup WiX custom action utils.\nextern \"C\" BOOL WINAPI DllMain(\n\t__in HINSTANCE hInst,\n\t__in ULONG ulReason,\n\t__in LPVOID\n\t)\n{\n\tswitch(ulReason)\n\t{\n\tcase DLL_PROCESS_ATTACH:\n\t\tWcaGlobalInitialize(hInst);\n\t\tbreak;\n\n\tcase DLL_PROCESS_DETACH:\n\t\tWcaGlobalFinalize();\n\t\tbreak;\n\t}\n\n\treturn TRUE;\n}\n"
  },
  {
    "path": "scripts/windows/installer/WiXHelper/CustomAction.def",
    "content": "LIBRARY \"WiXHelper\"\n\nEXPORTS\n\n;  DROP_QCloudDatabase\n;  CREATE_QCloudDatabase\n\nDownload_MeteorPackage\nExtract_MeteorFiles\nBulkRemoveMeteorFiles"
  },
  {
    "path": "scripts/windows/installer/WiXHelper/WiXHelper.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{17815519-26F7-4F37-9FAC-3FC50796C25D}</ProjectGuid>\n    <RootNamespace>WiXHelper</RootNamespace>\n    <Keyword>Win32Proj</Keyword>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <CharacterSet>Unicode</CharacterSet>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <PlatformToolset>v100</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <CharacterSet>Unicode</CharacterSet>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <PlatformToolset>v100</PlatformToolset>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">bin\\$(Configuration)\\Win32\\</OutDir>\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">obj\\$(Configuration)\\Win32\\</IntDir>\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">false</LinkIncremental>\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">false</LinkIncremental>\n    <CodeAnalysisRuleSet Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">AllRules.ruleset</CodeAnalysisRuleSet>\n    <CodeAnalysisRuleSet Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">AllRules.ruleset</CodeAnalysisRuleSet>\n    <CodeAnalysisRules Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" />\n    <CodeAnalysisRules Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" />\n    <CodeAnalysisRuleAssemblies Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" />\n    <CodeAnalysisRuleAssemblies Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" />\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <OutDir>bin\\$(Configuration)\\Win64\\</OutDir>\n    <IntDir>obj\\$(Configuration)\\Win64\\</IntDir>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <Optimization>MaxSpeed</Optimization>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <AdditionalIncludeDirectories>..\\WiXSDK\\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies>msi.lib;dutil.lib;wcautil.lib;Version.lib;Urlmon.lib;Wininet.lib;Userenv.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <AdditionalLibraryDirectories>..\\WiXSDK\\VS2010\\lib\\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n      <ModuleDefinitionFile>CustomAction.def</ModuleDefinitionFile>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Windows</SubSystem>\n      <OptimizeReferences>true</OptimizeReferences>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <PostBuildEvent>\n      <Command>\n      </Command>\n    </PostBuildEvent>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <Optimization>MaxSpeed</Optimization>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <AdditionalIncludeDirectories>..\\WiXSDK\\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies>msi.lib;dutil.lib;wcautil.lib;Version.lib;Urlmon.lib;Wininet.lib;Userenv.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <AdditionalLibraryDirectories>..\\WiXSDK\\VS2010\\lib\\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n      <ModuleDefinitionFile>CustomAction.def</ModuleDefinitionFile>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Windows</SubSystem>\n      <OptimizeReferences>true</OptimizeReferences>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n    </Link>\n    <PostBuildEvent>\n      <Command>\n      </Command>\n    </PostBuildEvent>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"CustomAction.cpp\" />\n    <ClCompile Include=\"stdafx.cpp\">\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Create</PrecompiledHeader>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"CustomAction.def\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"stdafx.h\" />\n    <ClInclude Include=\"targetver.h\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "scripts/windows/installer/WiXHelper/WiXHelper.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"Resource Files\">\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"CustomAction.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"stdafx.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"CustomAction.def\">\n      <Filter>Source Files</Filter>\n    </None>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"stdafx.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"targetver.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "scripts/windows/installer/WiXHelper/stdafx.cpp",
    "content": "// stdafx.cpp : source file that includes just the standard includes\n// WiXHelper.pch will be the pre-compiled header\n// stdafx.obj will contain the pre-compiled type information\n\n#include \"stdafx.h\"\n\n// TODO: reference any additional headers you need in STDAFX.H\n// and not in this file\n"
  },
  {
    "path": "scripts/windows/installer/WiXHelper/stdafx.h",
    "content": "// stdafx.h : include file for standard system include files,\n// or project specific include files that are used frequently, but\n// are changed infrequently\n//\n\n#pragma once\n\n#include \"targetver.h\"\n\n#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers\n// Windows Header Files:\n#include <windows.h>\n#include <strsafe.h>\n#include <msiquery.h>\n\n// WiX Header Files:\n#include <wcautil.h>\n\n\n// TODO: reference additional headers your program requires here\ntypedef struct _BURN_DOWNLOAD_SOURCE\n{\n    LPWSTR sczUrl;\n    LPWSTR sczUser;\n    LPWSTR sczPassword;\n} BURN_DOWNLOAD_SOURCE;\n"
  },
  {
    "path": "scripts/windows/installer/WiXHelper/targetver.h",
    "content": "#pragma once\n\n// The following macros define the minimum required platform.  The minimum required platform\n// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run \n// your application.  The macros work by enabling all features available on platform versions up to and \n// including the version specified.\n\n// Modify the following defines if you have to target a platform prior to the ones specified below.\n// Refer to MSDN for the latest info on corresponding values for different platforms.\n#ifndef WINVER                  // Specifies that the minimum required platform is Windows 2000.\n#define WINVER 0x0500           // Change this to the appropriate value to target other versions of Windows.\n#endif\n\n#ifndef _WIN32_WINNT            // Specifies that the minimum required platform is Windows 2000.\n#define _WIN32_WINNT 0x0500     // Change this to the appropriate value to target other versions of Windows.\n#endif\n\n#ifndef _WIN32_IE               // Specifies that the minimum required platform is Internet Explorer 5.0.\n#define _WIN32_IE 0x0500        // Change this to the appropriate value to target other versions of IE.\n#endif\n\n#ifndef _WIN32_MSI              // Specifies that the minimum required MSI version is MSI 3.1\n#define _WIN32_MSI 310          // Change this to the appropriate value to target other versions of MSI.\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXInstaller/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studo 2015 cache/options directory\n.vs/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding addin-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings \n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Windows Azure Build Output\ncsx/\n*.build.csdef\n\n# Windows Store app package directory\nAppPackages/\n\n# Others\n*.[Cc]ache\nClientBin/\n[Ss]tyle[Cc]op.*\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\nbower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n"
  },
  {
    "path": "scripts/windows/installer/WiXInstaller/Configuration.wxi",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Include>\n    <?define METEOR_ProductName  = \"Meteor\" ?>\n    <?define METEOR_ProductId    = \"{1B1B4C6E-371D-4027-80AB-27922ABD7EE4}\" ?>\n    <?define METEOR_UpgradeCode  = \"{D6831580-7DD8-4088-9792-64E4D37FEDDC}\" ?>\n    <?define BUNDLE_UpgradeCode  = \"{D6F8653E-2F27-4FDD-9C92-66D7B4B21D79}\" ?>\n\n\n    <?define METEOR_Manufacturer = \"Meteor Development Group \" ?>\n    <?define METEOR_ProductUrl   = \"https://www.meteor.com/\" ?>\n    <?define METEOR_UpgradeUrl   = \"https://www.meteor.com/\" ?>\n    <?define METEOR_TermsUrl     = \"https://www.meteor.com/terms\" ?>\n    <?define METEOR_PrivacyUrl   = \"https://www.meteor.com/privacy\" ?>\n\n\n    <?define METEOR_Theme          = \"Resources\\Theme_Meteor.xml\" ?>\n    <?define METEOR_Localization   = \"Resources\\Theme_Meteor.wxl\" ?>\n\n    <?define METEOR_Background     = \"Resources\\Background.png\" ?>\n    <?define METEOR_TopHeader      = \"Resources\\TopHeader.png\" ?>\n    <?define METEOR_Logo           = \"Resources\\meteor-logo-sm.jpg\" ?>\n    <?define METEOR_License        = \"Resources\\License.htm\" ?>\n    \n    \n    <?define METEOR_PkgFileName    = \"meteor-bootstrap-os.windows.x86_32.tar.gz\"?>\n                                       \n</Include>\n"
  },
  {
    "path": "scripts/windows/installer/WiXInstaller/MSIPackage.wixproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <Platform Condition=\" '$(Platform)' == '' \">x86</Platform>\n    <ProjectGuid>{e053726b-937b-40c7-8f3d-25a3226979d9}</ProjectGuid>\n    <SchemaVersion>2.0</SchemaVersion>\n    <OutputType>Package</OutputType>\n    <WixTargetsPath Condition=\" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' \">$(MSBuildExtensionsPath32)\\Microsoft\\WiX\\v3.x\\Wix.targets</WixTargetsPath>\n    <WixTargetsPath Condition=\" '$(WixTargetsPath)' == '' \">$(MSBuildExtensionsPath)\\Microsoft\\WiX\\v3.x\\Wix.targets</WixTargetsPath>\n    <Name>MSIPackage</Name>\n    <Version>6.0.2469</Version>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|x86' \">\n    <OutputPath>bin\\$(Configuration)\\$(Platform)\\</OutputPath>\n    <IntermediateOutputPath>obj\\$(Platform)\\$(Configuration)\\</IntermediateOutputPath>\n    <DefineConstants>\n    </DefineConstants>\n    <InstallerPlatform>x86</InstallerPlatform>\n    <SuppressIces>ICE60;ICE80</SuppressIces>\n    <OutputName>SetupMeteor</OutputName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|x64' \">\n    <OutputPath>bin\\$(Configuration)\\$(Platform)\\</OutputPath>\n    <IntermediateOutputPath>obj\\$(Platform)\\$(Configuration)\\</IntermediateOutputPath>\n    <DefineConstants>\n    </DefineConstants>\n    <InstallerPlatform>x64</InstallerPlatform>\n    <SuppressIces>ICE60;ICE61;ICE69;</SuppressIces>\n    <OutputName>SetupMeteor</OutputName>\n    <SuppressSpecificWarnings>\n    </SuppressSpecificWarnings>\n  </PropertyGroup>\n  <ItemGroup>\n    <WixExtension Include=\"WixNetFxExtension\">\n      <HintPath>$(WixExtDir)\\WixNetFxExtension.dll</HintPath>\n      <Name>WixNetFxExtension</Name>\n    </WixExtension>\n    <WixExtension Include=\"WixFirewallExtension\">\n      <HintPath>$(WixExtDir)\\WixFirewallExtension.dll</HintPath>\n      <Name>WixFirewallExtension</Name>\n    </WixExtension>\n    <WixExtension Include=\"WixUtilExtension\">\n      <HintPath>$(WixExtDir)\\WixUtilExtension.dll</HintPath>\n      <Name>WixUtilExtension</Name>\n    </WixExtension>\n  </ItemGroup>\n  <ItemGroup>\n    <Compile Include=\"Meteor_Product.wxs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Content Include=\"Configuration.wxi\">\n      <Link>Configuration.wxi</Link>\n    </Content>\n  </ItemGroup>\n  <Import Project=\"$(WixTargetsPath)\" />\n  <PropertyGroup>\n    <PostBuildEvent />\n  </PropertyGroup>\n  <PropertyGroup>\n    <PreBuildEvent />\n  </PropertyGroup>\n  <!--\n\tTo modify your build process, add your task inside one of the targets below and uncomment it.\n\tOther similar extension points exist, see Wix.targets.\n\t<Target Name=\"BeforeBuild\">\n\t</Target>\n\t<Target Name=\"AfterBuild\">\n\t</Target>\n-->\n</Project>"
  },
  {
    "path": "scripts/windows/installer/WiXInstaller/Meteor_Bundle.wxs",
    "content": "<?xml version=\"1.0\"?>\n<!-- This example demonstrates the use of an external theme file to create the same UI as  Hyperlink2License built in to WixBalExtensionExt.  It also shows the use of two folder selections and radio buttons on the options page. -->\n<Wix\n    RequiredVersion=\"3.7.1224.0\"\n    xmlns=\"http://schemas.microsoft.com/wix/2006/wi\"\n    xmlns:bal=\"http://schemas.microsoft.com/wix/BalExtension\"\n    xmlns:util=\"http://schemas.microsoft.com/wix/UtilExtension\">\n\n    <?include Configuration.wxi?>\n\n    <Bundle\tName=\"$(var.METEOR_ProductName)\" Version=\"1.0\" Manufacturer=\"$(var.METEOR_Manufacturer)\"\n\t\tUpgradeCode=\"$(var.BUNDLE_UpgradeCode)\" AboutUrl=\"$(var.METEOR_ProductUrl)\"\n\t\tIconSourceFile=\"Resources\\Product.ico\" Condition=\"(VersionNT &gt;= v5.1)\" >\n\n        <Update Location=\"$(var.METEOR_UpgradeUrl)\"/>\n\n        <BootstrapperApplicationRef Id=\"WixExtendedBootstrapperApplication.HyperlinkLicense\">\n            <Payload SourceFile=\"$(var.METEOR_Background)\" />\n            <Payload SourceFile=\"$(var.METEOR_TopHeader)\" />\n            <Payload SourceFile=\"$(var.METEOR_Logo)\" />\n            <Payload SourceFile=\"$(var.METEOR_License)\" Compressed=\"yes\" />\n        </BootstrapperApplicationRef>\n\n\n        <WixVariable Id=\"WixExtbaLicenseUrl\" Value=\"License.htm\" />\n        <WixVariable Id=\"WixExtbaThemeXml\"   Value=\"$(var.METEOR_Theme)\" />\n        <WixVariable Id=\"WixExtbaThemeWxl\"   Value=\"$(var.METEOR_Localization)\" />\n        <WixVariable Id=\"WixBundleElevated\"  Value=\"1\"/>\n\t\t\n\t\t<Variable Name=\"TermsUrl\" \t\t\tType=\"string\" Value=\"$(var.METEOR_TermsUrl)\" />\n\t\t<Variable Name=\"PrivacyUrl\" \t\tType=\"string\" Value=\"$(var.METEOR_PrivacyUrl)\" />\n\n        <Variable Name=\"PerMachineInstall\"  Type=\"numeric\" Persisted=\"yes\" Value=\"0\" />\n        <Variable Name=\"PerUserInstall\"     Type=\"numeric\" Persisted=\"yes\" Value=\"1\" />\n        <Variable Name=\"CreateRButton\" \t\tType=\"numeric\" Persisted=\"yes\" Value=\"1\" />\n        <Variable Name=\"SignInRButton\" \t\tType=\"numeric\" Persisted=\"yes\" Value=\"0\" />\n        <Variable Name=\"RegisterEmail\"   \tType=\"string\"  Persisted=\"yes\" Value=\"\" Hidden=\"yes\" />\n\t\t<Variable Name=\"RegisterUser\"   \tType=\"string\"  Persisted=\"yes\" Value=\"\" Hidden=\"yes\" />\n        <Variable Name=\"RegisterPass\"    \tType=\"string\"  Persisted=\"yes\" Value=\"\" Hidden=\"yes\" />\n\t\t\n\t\t<!-- For now I disable and hide the Skip registration checkbox -->\n        <Variable Name=\"SkipRegistrationState\"\tType=\"string\"  Persisted=\"yes\" Value=\"disable\"/>\n        <Variable Name=\"SkipRegistration\"\t    Type=\"numeric\" Persisted=\"yes\" Value=\"0\"/>\n\n        <Variable Name=\"UserMeteorSessionFile\" \t    Type=\"string\" Persisted=\"yes\" Value=\"[LocalAppDataFolder]\\.meteorsession\" />\n        <Variable Name=\"PerMachineInstallFolder\"    Type=\"string\" Persisted=\"yes\" Value=\"[ProgramFilesFolder][WixBundleName]\" />\n        <Variable Name=\"PerUserInstallFolder\"       Type=\"string\" Persisted=\"yes\" Value=\"[LocalAppDataFolder]\" />\n        <Variable Name=\"InstallFolder\"              Type=\"string\" Persisted=\"yes\" Value=\"[PerUserInstallFolder]\" />\n\n        <Variable Name=\"InstallRegPath\"             Type=\"string\" Persisted=\"yes\" Value=\"SOFTWARE\\$(var.METEOR_Manufacturer)\\$(var.METEOR_ProductName)\\Install\" />\n        <Variable Name=\"MSICustomErrFile\" \t        Type=\"string\" Persisted=\"yes\" Value=\"[WixBundleLog].err\" />\n\n\n\n        <Chain DisableSystemRestore=\"yes\">\n\n            <!-- Here we set MSI propertyies if user chose perUser install -->\n            <MsiPackage Id=\"SetupMeteor_MachineInstall\" Compressed=\"yes\" InstallCondition=\"NOT Installed AND (PerMachineInstall = 1)\"\n\t\t\t\tSourceFile=\"bin\\$(var.Configuration)\\$(var.Platform)\\SetupMeteor.msi\" Vital=\"yes\" ForcePerMachine=\"yes\" >\n                <MsiProperty Name=\"METEOR_DIR\" Value=\"[InstallFolder]\" />\n                <MsiProperty Name=\"INSTALL_REG_PATH\" Value=\"[InstallRegPath]\"/>\n                <MsiProperty Name=\"MSICUSTOMERRFILE\" Value=\"[MSICustomErrFile]\" />\n                <MsiProperty Name=\"PERMACHINE_INSTALL\" Value=\"1\" />\n            </MsiPackage>\n\n            <!-- Here we set MSI propertyies if user chose perUser install -->\n            <MsiPackage Id=\"SetupMeteor_UserInstall\" Compressed=\"yes\" InstallCondition=\"NOT Installed AND (PerUserInstall = 1)\"\n\t\t\t\tSourceFile=\"bin\\$(var.Configuration)\\$(var.Platform)\\SetupMeteor.msi\" Vital=\"yes\" >\n                <MsiProperty Name=\"METEOR_DIR\" Value=\"[InstallFolder]\" />\n                <MsiProperty Name=\"INSTALL_REG_PATH\" Value=\"[InstallRegPath]\"/>\n                <MsiProperty Name=\"MSICUSTOMERRFILE\" Value=\"[MSICustomErrFile]\" />\n                <MsiProperty Name=\"PERUSER_INSTALL\" Value=\"1\" />\n            </MsiPackage>\n        </Chain>\n    </Bundle>\n</Wix>\n"
  },
  {
    "path": "scripts/windows/installer/WiXInstaller/Meteor_Product.wxs",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Wix\n    xmlns=\"http://schemas.microsoft.com/wix/2006/wi\"\n    xmlns:util=\"http://schemas.microsoft.com/wix/UtilExtension\"\n    xmlns:fire=\"http://schemas.microsoft.com/wix/FirewallExtension\"\n    xmlns:sql=\"http://schemas.microsoft.com/wix/SqlExtension\">\n\n    <?include Configuration.wxi?>\n\n    <Product Id=\"$(var.METEOR_ProductId)\" Name=\"$(var.METEOR_ProductName)\" Language=\"1033\" Version=\"1.0\" Manufacturer=\"$(var.METEOR_Manufacturer)\" UpgradeCode=\"$(var.METEOR_UpgradeCode)\">\n        <Package Description=\"This package will install Meteor on your computer.\" InstallerVersion=\"300\" Compressed=\"yes\" InstallScope=\"perUser\" InstallPrivileges=\"limited\"/>\n\n        <!-- This will allow a new msi package to upgrade an existing older version (in case patch is not used) -->\n        <MajorUpgrade DowngradeErrorMessage=\"A later version of [ProductName] is already installed. Setup will now exit.\" AllowSameVersionUpgrades=\"yes\"/>\n\n        <Media Id=\"1\" Cabinet=\"product.cab\" EmbedCab=\"yes\"/>\n\n        <Property Id=\"DiskPrompt\" Value=\"$(var.METEOR_ProductName) Installation [1]\"/>\n        <Property Id=\"ARPURLINFOABOUT\" Value=\"$(var.METEOR_ProductName)\"/>\n        <Property Id=\"ARPURLUPDATEINFO\" Value=\"$(var.METEOR_ProductName)\"/>\n        <Property Id=\"ARPHELPLINK\" Value=\"$(var.METEOR_ProductName)\"/>\n\n        <?if $(var.Platform)=\"x86\"?>\n            <Binary Id=\"WiXHelper\"        SourceFile=\"..\\WiXHelper\\bin\\Release\\Win32\\WiXHelper.dll\"/>\n        <?else?>\n            <Binary Id=\"WiXHelper\"        SourceFile=\"..\\WiXHelper\\bin\\Release\\Win64\\WiXHelper.dll\"/>\n        <?endif?>\n\n        <Binary Id=\"SevenZip\"  SourceFile=\"Resources\\7za.exe\" />\n\n\n\n        <Feature Id=\"ProductFiles\" Title=\"Meteor Product Files\" Level=\"1\">\n            <ComponentGroupRef Id=\"CG_MeteorConfiguration\"/>\n        </Feature>\n\n\n        <!-- Directory structure -->\n        <Directory Id=\"TARGETDIR\" Name=\"SourceDir\">\n            <Directory Id=\"METEOR_DIR\">\n                <Directory Id=\"P_METEOR_DIR\" Name=\".meteor\" />\n            </Directory>\n        </Directory>\n\n\n        <CustomAction Id=\"Download_MeteorPackage\" BinaryKey=\"WiXHelper\" Return=\"check\" DllEntry=\"Download_MeteorPackage\" />\n        <CustomAction Id=\"Extract_MeteorFiles\"    BinaryKey=\"WiXHelper\" Return=\"check\" DllEntry=\"Extract_MeteorFiles\" />\n        <CustomAction Id=\"BulkRemoveMeteorFiles\"  BinaryKey=\"WiXHelper\" Return=\"check\" DllEntry=\"BulkRemoveMeteorFiles\" />\n        <CustomAction Id=\"SetFolderPackages\"  Property=\"METEORDIR_PACKAGES\" Value=\"[METEOR_DIR].meteor\\packages\" />\n        <CustomAction Id=\"SetFolderPkg_Meta\"  Property=\"METEORDIR_PKG_META\" Value=\"[METEOR_DIR].meteor\\package-metadata\" />\n\n        <InstallExecuteSequence>\n            <Custom Action=\"Download_MeteorPackage\"  After=\"InstallFiles\">NOT Installed</Custom>\n            <Custom Action=\"Extract_MeteorFiles\"     After=\"Download_MeteorPackage\">NOT Installed</Custom>\n            <Custom Action=\"SetFolderPackages\"       After=\"InstallInitialize\">REMOVE~=\"ALL\"</Custom>\n            <Custom Action=\"SetFolderPkg_Meta\"       After=\"InstallInitialize\">REMOVE~=\"ALL\"</Custom>\n            <Custom Action=\"BulkRemoveMeteorFiles\"   Before=\"RemoveFiles\">REMOVE~=\"ALL\"</Custom>\n        </InstallExecuteSequence>\n\n        <UI>\n            <ProgressText Action=\"Extract_MeteorFiles\">Installing Meteor... please wait.  (This may take a minute or two.)</ProgressText>\n            <ProgressText Action=\"BulkRemoveMeteorFiles\">Removing Meteor...</ProgressText>\n        </UI>\n    </Product>\n\n\n    <Fragment>\n        <ComponentGroup Id=\"CG_MeteorConfiguration\">\n            <Component Id=\"UserEnvironmentsVar\" Guid=\"{6222C645-5576-468F-A776-9FE7BA2FF465}\" Directory=\"TARGETDIR\">\n                <Condition>PERUSER_INSTALL</Condition>\n                <Environment Id=\"UserEnvPATH\" Name=\"PATH\" Value=\"[P_METEOR_DIR]\" Separator=\";\" Action=\"set\" Part=\"last\" Permanent=\"yes\" System=\"no\" />\n            </Component>\n\n            <Component Id=\"SystemEnvironmentsVar\" Guid=\"{6222C645-5576-468F-A776-9FE7BA2FF465}\" Directory=\"TARGETDIR\">\n                <Condition>PERMACHINE_INSTALL</Condition>\n                <Environment Id=\"SystemEnvPATH\" Name=\"PATH\" Value=\"[P_METEOR_DIR]\" Separator=\";\" Action=\"set\" Part=\"last\" Permanent=\"yes\" System=\"yes\" />\n            </Component>\n\n            <Component Id=\"UninstallMeteorFilesAndFolders\" Guid=\"{989BB4D9-78CE-4230-A2AB-292998A88B82}\" Directory=\"TARGETDIR\">\n\t\t\t\t<RemoveFile   Id=\"RemoveRootBatch\" On=\"uninstall\" Directory=\"P_METEOR_DIR\" Name=\"meteor.bat\" />\n\t\t\t\t<RemoveFolder Id=\"RemoveRootFolder\" On=\"uninstall\" Directory=\"P_METEOR_DIR\" />\n            </Component>\n\n\t\t\t<Component Id=\"MeteorDir_Permission\" Guid=\"{62B0F582-C3E3-45E7-A0F9-1517773340EB}\" Directory=\"P_METEOR_DIR\">\n                <Condition>PERMACHINE_INSTALL</Condition>\n                <CreateFolder>\n                    <util:PermissionEx User=\"Everyone\" GenericAll=\"yes\"/>\n                </CreateFolder>\n            </Component>\n        </ComponentGroup>\n\n    </Fragment>\n</Wix>\n"
  },
  {
    "path": "scripts/windows/installer/WiXInstaller/Resources/License.htm",
    "content": "<html>\n\n<head>\n<meta http-equiv=Content-Type content=\"text/html; charset=windows-1252\">\n<meta name=Generator content=\"Microsoft Word 14 (filtered)\">\n<style>\n<!--\n /* Font Definitions */\n @font-face\n\t{font-family:Calibri;\n\tpanose-1:2 15 5 2 2 2 4 3 2 4;}\n@font-face\n\t{font-family:Consolas;\n\tpanose-1:2 11 6 9 2 2 4 3 2 4;}\n /* Style Definitions */\n p.MsoNormal, li.MsoNormal, div.MsoNormal\n\t{margin-top:0cm;\n\tmargin-right:0cm;\n\tmargin-bottom:10.0pt;\n\tmargin-left:0cm;\n\tline-height:115%;\n\tfont-size:11.0pt;\n\tfont-family:\"Calibri\",\"sans-serif\";}\n.MsoChpDefault\n\t{font-size:11.0pt;}\n.MsoPapDefault\n\t{margin-bottom:10.0pt;\n\tline-height:115%;}\n /* Page Definitions */\n @page WordSection1\n\t{size:612.0pt 792.0pt;\n\tmargin:72.0pt 72.0pt 72.0pt 72.0pt;}\ndiv.WordSection1\n\t{page:WordSection1;}\n-->\n</style>\n\n</head>\n\n<body lang=EN-GB style='text-justify-trim:punctuation'>\n\n<div class=WordSection1>\n\n<p class=MsoNormal style='text-autospace:none'><b><span style='font-size:20.0pt;\nline-height:115%;font-family:Consolas'>[Put Your License Agreement Here]</span></b></p>\n\n<p class=MsoNormal style='text-autospace:none'><span lang=EN-US\nstyle='font-size:9.5pt;line-height:115%;font-family:Consolas'>L</span><span\nlang=EN style='font-size:9.5pt;line-height:115%;font-family:Consolas'>orem\nipsum dolor sit amet, consectetur adipiscing elit. Donec ultricies ultricies\narcu id commodo. Ut dignissim ante nec urna elementum imperdiet. Praesent\npretium condimentum orci sit amet laoreet. Fusce condimentum tempor leo, vitae\ntempor quam interdum et. Nulla ante dui, tincidunt sed porta nec, pulvinar in\nfelis. Pellentesque pellentesque ornare nibh id accumsan. In eu arcu nibh.\nAenean ut vulputate nisl. Proin at nibh lacinia urna elementum commodo. Donec semper\nlorem quis neque fringilla quis facilisis dolor dignissim. Suspendisse a massa\nin odio viverra vehicula. Curabitur id lectus purus, non bibendum arcu. Cras\ndictum, turpis eget gravida condimentum, turpis ante varius leo, molestie\npulvinar mauris libero ut leo. Morbi libero diam, sollicitudin id interdum sit\namet, rhoncus eget turpis.</span></p>\n\n<p class=MsoNormal style='text-autospace:none'><span lang=EN style='font-size:\n9.5pt;line-height:115%;font-family:Consolas'>Vestibulum arcu dui, suscipit\nvitae suscipit laoreet, posuere eget risus. Sed vitae massa in justo vehicula\nelementum sed at arcu. Pellentesque arcu ante, accumsan sed lacinia sed,\nlacinia vel urna. Vivamus at ligula nulla, lobortis ultricies tortor. Vivamus\nsuscipit dolor non velit adipiscing venenatis. Nullam adipiscing accumsan\ncondimentum. Nullam ut lorem neque, et iaculis felis. Donec sed massa diam, et\nfeugiat velit. Pellentesque facilisis mi a odio ultrices facilisis. Nam porta,\nlorem feugiat aliquet placerat, ipsum risus accumsan sem, euismod bibendum\nvelit dolor sed turpis. Suspendisse tincidunt, lectus congue rhoncus\nsollicitudin, magna erat porttitor ante, eget sodales ante sem eu augue. Aenean\nrisus risus, mattis vitae pretium at, venenatis dictum est. Vestibulum\nconsectetur euismod magna vel sodales.</span></p>\n\n<p class=MsoNormal style='text-autospace:none'><span lang=EN style='font-size:\n9.5pt;line-height:115%;font-family:Consolas'>Quisque eu urna lacus. Nunc eget\ndictum odio. Pellentesque vel dolor leo. Praesent aliquet, erat vel fringilla\nlobortis, ante nibh dapibus augue, sed semper ligula odio vitae nulla. Nullam\ndictum gravida lectus nec lacinia. Vivamus fermentum ultricies lobortis. In\nquis magna massa, ut commodo lectus. Donec nunc velit, gravida id euismod\nluctus, luctus sed ante. Nunc elementum mollis sapien, ac interdum quam\nfringilla eu. Pellentesque habitant morbi tristique senectus et netus et\nmalesuada fames ac turpis egestas. Aliquam dui enim, tempus vel aliquam sed,\npretium sed nisi. Fusce vitae magna nec nibh aliquam suscipit vel a felis.\nEtiam gravida, lorem id laoreet gravida, nisl leo hendrerit dolor, quis porta\nmauris enim vitae justo. Maecenas congue, felis at rhoncus vestibulum, nisl\nurna pellentesque urna, id iaculis augue metus eget neque. Curabitur pretium\nrisus nec tortor vulputate et rhoncus ipsum gravida.</span></p>\n\n<p class=MsoNormal style='text-autospace:none'><span lang=EN style='font-size:\n9.5pt;line-height:115%;font-family:Consolas'>Maecenas elementum volutpat arcu,\nnec ultricies velit faucibus facilisis. Etiam sem lacus, mattis eget gravida\nut, rhoncus porta lorem. Vivamus volutpat dui sit amet risus mollis venenatis.\nQuisque velit velit, condimentum id pharetra sed, varius vitae lectus. Praesent\nnisi turpis, porttitor nec accumsan a, aliquam sit amet augue. Quisque\nfacilisis enim sed enim pretium tristique. Aliquam commodo varius mi, ut\niaculis nunc tempus non. Vivamus velit nunc, dictum a dignissim vitae, commodo\nid metus. Integer volutpat, neque at ultrices dignissim, felis nulla commodo\norci, at auctor nisl quam nec sem. Pellentesque interdum pellentesque nulla, ac\nfermentum tortor porttitor a. Etiam condimentum aliquet sapien vel adipiscing. Quisque\nest velit, vulputate a iaculis ut, tempus in nibh. Cras consectetur quam nibh,\nvel lobortis justo. Aenean a elit leo. Aenean mollis dolor a odio accumsan\nmollis. Proin blandit neque erat. Integer lectus urna, volutpat quis vulputate\net, fermentum et ante. Maecenas vitae ultricies dui.</span></p>\n\n<p class=MsoNormal style='text-autospace:none'><span lang=EN style='font-size:\n9.5pt;line-height:115%;font-family:Consolas'>Mauris accumsan varius luctus. In\nhac habitasse platea dictumst. Mauris malesuada tempus nibh, porta accumsan\ntortor tincidunt eu. Proin orci mauris, commodo id malesuada nec, adipiscing ut\nsapien. Phasellus at dui vel nisi adipiscing auctor quis vel sem. Phasellus\nfermentum, enim id sodales ullamcorper, magna sapien facilisis urna, ac\nlobortis nunc augue ut ligula. Quisque vulputate nibh sed velit pharetra\ndictum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque\nmi metus, vestibulum vitae dapibus vel, ultrices at tellus. Vivamus iaculis dui\na nisl faucibus eget congue velit gravida. Donec vel quam ligula. Nam magna\nante, vulputate id pharetra ac, dapibus commodo velit. Cras nisl nulla, congue\nsit amet laoreet eget, cursus et lorem. Mauris diam tortor, porttitor vitae\nfringilla id, iaculis sit amet eros. Donec sed enim eget felis fermentum\nposuere. Pellentesque sodales feugiat dolor, vel molestie est adipiscing non.\nMorbi tincidunt viverra felis ut hendrerit.</span></p>\n\n</div>\n\n</body>\n\n</html>\n"
  },
  {
    "path": "scripts/windows/installer/WiXInstaller/Resources/Theme_Meteor.wxl",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<WixLocalization Culture=\"en-us\" Language=\"1033\" xmlns=\"http://schemas.microsoft.com/wix/2006/localization\">\n    <String Id=\"Caption\">Install [WixBundleName]</String>\n    <String Id=\"Title\">[WixBundleName]</String>\n    <String Id=\"InstallHeader\">Welcome to the [WixBundleName] Setup</String>\n    <String Id=\"InstallMessage\">Setup will install [WixBundleName] on your computer. During the wizard, you will be able to adjust product features and settings that fit best to your needs.</String>\n    <String Id=\"InstallVersion\">Version [WixBundleVersion]</String>\n    <String Id=\"InstallLicenseLinkText\"></String>\n    <String Id=\"ConfirmCancelMessage\">Are you sure you want to cancel?</String>\n    <String Id=\"HelpHeader\">Setup Help</String>\n    <String Id=\"HelpText\">\n        /passive | /quiet -  displays minimal UI with no prompts or displays no UI and no prompts. By default UI and all prompts are displayed.\n\n        /toconsole   - similar to /quiet except that progress is redirected to console.\n\n        /log log.txt - logs to a specific file. By default a log file is created in %TEMP%.\n    </String>\n    <String Id=\"HelpCloseButton\">&amp;Close</String>\n    <String Id=\"InstallAcceptCheckbox\">I &amp;agree to the license terms and conditions</String>\n    <String Id=\"InstallOptionsButton\">&amp;Options</String>\n    <String Id=\"InstallInstallButton\">&amp;Install</String>\n    <String Id=\"InstallCloseButton\">&amp;Cancel</String>\n    <String Id=\"BackButton\">&lt; Back</String>\n    <String Id=\"NextButton\">Next &gt;</String>\n    <String Id=\"SkipButton\">Skip this step</String>\n    <String Id=\"Install\">Install</String>\n    <String Id=\"InstallMeteor\">Install Meteor</String>\n\n    <String Id=\"InstallUpgradeLinkText\">Version [WixBundleVersion] &lt;a href=\"#\"&gt;upgrade available&lt;/a&gt;</String>\n    <String Id=\"CurrentUserPass\">Current user password:</String>\n\n    <String Id=\"InstallDirHeader\">[WixBundleName] install directory</String>\n    <String Id=\"InstallDirMessage\">Please select the way you want [WixBundleName] to be installed on your computer.</String>\n    <String Id=\"InstallDirPathLabel\">Install location:</String>\n    <String Id=\"InstallScopeLabel\">Install this application for:</String>\n    <String Id=\"PerMachineInstallRButton\">For all users on this computer (recommended)</String>\n    <String Id=\"PerUserInstallRButton\">Only for me ([LogonUser])</String>\n\n    <String Id=\"RegistrationHeader\">[WixBundleName] registration</String>\n    <String Id=\"RegistrationInfo\">Sign in with your Meteor developer account or create a new one now.</String>\n    <String Id=\"CreateRButton\">Sign up for a new account</String>\n    <String Id=\"SignInRButton\">Sign in with an existing account</String>\n    <String Id=\"RegisterEmail\">Email Address</String>\n    <String Id=\"RegisterUser\">Username</String>\n    <String Id=\"RegisterUsernameOrEmail\">Username or Email</String>\n    <String Id=\"RegisterPass\">Password</String>\n    <String Id=\"SkipRegistration\">Skip [WixBundleName] registration and continue with setup</String>\n\n\n\n    <String Id=\"OptionsHeader\">Setup Options</String>\n    <String Id=\"OptionsInfo\">Adjust setup parameters in order to your needs.</String>\n    <String Id=\"OptionsLocationLabel\">Install location:</String>\n    <String Id=\"OptionsBrowseButton\">&amp;Browse...</String>\n    <String Id=\"OptionsLocationLabel2\">Database location:</String>\n    <String Id=\"OptionsBrowseButton2\">B&amp;rowse...</String>\n    <String Id=\"OptionsOkButton\">&amp;OK</String>\n    <String Id=\"OptionsCancelButton\">&amp;Cancel</String>\n\n\n\n\n    <String Id=\"ProgressHeader\">Installing [WixBundleName]</String>\n    <String Id=\"ProgressHeaderRepair\">Repairing [WixBundleName]</String>\n    <String Id=\"ProgressHeaderUninstall\">Uninstalling [WixBundleName]</String>\n    <String Id=\"ProgressInfo\">Please wait while Setup installs [WixBundleName] on your computer.</String>\n    <String Id=\"ProgressInfoRepair\">Please wait while Setup repairs [WixBundleName] installed on your computer.</String>\n    <String Id=\"ProgressInfoUninstall\">Please wait while [WixBundleName] is removed from your computer.</String>\n    <String Id=\"ProgressLabel\">Processing:</String>\n    <String Id=\"OverallProgressPackageText\">Initializing...</String>\n    <String Id=\"ExecuteProgressText\">Initializing...</String>\n    <String Id=\"OverallProgressText\">Initializing...</String>\n    <String Id=\"ExecuteProgressActionDataText\"></String>\n    <String Id=\"ProgressCancelButton\">&amp;Cancel</String>\n    <String Id=\"ModifyHeader\">[WixBundleName] Maintenance</String>\n    <String Id=\"ModifyInfo\">The setup wizard allows you to repair or remove [WixBundleName] from your computer. If you have a [WixBundleName] application currently running, it is recommended to close it.&#13;&#13;&#10;Click Repair if you want to repair [WixBundleName], Uninstall to remove it or click Cancel to close this maintenance wizard.</String>\n    <String Id=\"ModifyRepairButton\">&amp;Repair</String>\n    <String Id=\"ModifyUninstallButton\">&amp;Uninstall</String>\n    <String Id=\"ModifyCloseButton\">&amp;Close</String>\n    <String Id=\"SuccessHeader\">Meteor is now installed on your computer.</String>\n    <String Id=\"SuccessHeaderRepair\">Repair Successful</String>\n    <String Id=\"SuccessHeaderUninstall\">Meteor has been uninstalled.</String>\n    <String Id=\"SuccessInfo\">\nTo get started, open a new command prompt and type \"meteor\". If you're running Windows 8.1, you may need to restart your machine.\n\nTo learn more about Meteor, check out the &lt;a href=\"https://www.meteor.com/try\"&gt;Meteor tutorial&lt;/a&gt; and read the &lt;a href=\"https://docs.meteor.com\"&gt;official documentation&lt;/a&gt;. If you need help, ask a question on the official forums at &lt;a href=\"https://forums.meteor.com\"&gt;forums.meteor.com&lt;/a&gt; or &lt;a href=\"https://stackoverflow.com/questions/tagged/meteor\"&gt;Stack Overflow&lt;/a&gt;.\n\nCheck out the &lt;a href=\"https://github.com/meteor/meteor/wiki/Preview-of-Meteor-on-Windows\"&gt;Wiki page on GitHub&lt;/a&gt; to learn more about the Meteor Windows preview.\n    </String>\n    <String Id=\"SuccessErrorInfoText\">Following non critical errors occured:</String>\n    <String Id=\"SuccessInfoRepair\">Setup has finished repairing [WixBundleName] installed on your computer. The application may be launched by selecting the installed icons.</String>\n    <String Id=\"SuccessInfoUninstall\">We hope to see you again soon!</String>\n    <String Id=\"SuccessLaunchButton\">&amp;Launch</String>\n    <String Id=\"SuccessRestartText\">You must restart your computer before you can use the software.</String>\n    <String Id=\"SuccessRestartButton\">&amp;Restart</String>\n    <String Id=\"SuccessCloseButton\">&amp;Close</String>\n    <String Id=\"FailureHeader\">Setup Failed</String>\n    <String Id=\"FailureHeaderRepair\">Repair Failed</String>\n    <String Id=\"FailureHeaderUninstall\">Uninstall Failed</String>\n    <String Id=\"FailureHyperlinkLogText\">One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the &lt;a href=\"#\"&gt;log file&lt;/a&gt;.</String>\n    <String Id=\"FailureRestartText\">You must restart your computer to complete the rollback of the software.</String>\n    <String Id=\"FailureRestartButton\">&amp;Restart</String>\n    <String Id=\"FailureCloseButton\">&amp;Close</String>\n</WixLocalization>"
  },
  {
    "path": "scripts/windows/installer/WiXInstaller/Resources/Theme_Meteor.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Theme xmlns=\"http://wixtoolset.org/schemas/thmutil/2010\">\n\t<Window Width=\"624\" Height=\"388\" FontId=\"0\">#(loc.Caption)</Window>\n\t<Font Id=\"0\" Height=\"-12\" Weight=\"500\" Foreground=\"000000\" Background=\"FFFFFF\" >Segoe UI</Font>         <!-- Installer default font with white background-->\n\t<Font Id=\"1\" Height=\"-14\" Weight=\"500\" Foreground=\"000000\" Background=\"FFFFFF\" >Segoe UI</Font>         <!-- Installer default font with white background-->\n\t<Font Id=\"2\" Height=\"-14\" Weight=\"800\" Foreground=\"333333\" >Tahoma</Font>                               <!-- Page header big font -->\n\t<Font Id=\"3\" Height=\"-22\" Weight=\"500\" Foreground=\"252525\" >Segoe UI</Font>                             <!-- Big light font to dispaly product name in welcome and finish pages -->\n\t<Font Id=\"4\" Height=\"-11\" Weight=\"500\" Foreground=\"000000\" >Tahoma</Font>\n\t<Font Id=\"5\" Height=\"-10\" Weight=\"500\" Foreground=\"000000\" >Segoe UI</Font>                             <!-- Version number on bottom left corner of all pages -->\n\t<Font Id=\"6\" Height=\"-12\" Weight=\"500\" Foreground=\"0000FF\" Background=\"FFFFFF\" >Segoe UI</Font>         <!-- Installer default font with white background-->\n\t<Font Id=\"7\" Height=\"-12\" Weight=\"500\" Foreground=\"000000\" >Segoe UI</Font>                             <!-- Same as installer default font but transparent -->\n\n\n\n\t<Page Name=\"Install\">\n        <!--<Text X=\"178\" Y=\"20\" Width=\"-24\" Height=\"32\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.InstallHeader)</Text>-->\n        <Hypertext X=\"24\" Y=\"-100\" Width=\"-24\" Height=\"14\" TabStop=\"yes\" FontId=\"4\" HideWhenDisabled=\"yes\">#(loc.InstallLicenseLinkText)</Hypertext> -->\n        <!--<Checkbox Name=\"EulaAcceptCheckbox\" X=\"178\" Y=\"202\" Width=\"-24\" Height=\"17\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.InstallAcceptCheckbox)</Checkbox>-->\n\n\t\t<Button Name=\"NextButton\" X=\"200\" Y=\"-142\" Width=\"-200\" Height=\"44\" TabStop=\"yes\" FontId=\"3\">#(loc.InstallMeteor)</Button>\n\t</Page>\n\t<Page Name=\"InstallDir\">\n\t\t<Text X=\"24\" Y=\"20\" Width=\"-220\" Height=\"24\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.InstallDirHeader)</Text>\n\t\t<Text X=\"24\" Y=\"78\" Width=\"-24\" Height=\"32\" FontId=\"1\" DisablePrefix=\"yes\">#(loc.InstallDirMessage)</Text>\n\n        <Text X=\"64\" Y=\"130\" Width=\"-24\" Height=\"17\" FontId=\"0\">#(loc.InstallScopeLabel)</Text>\n        <Button Name=\"PerMachineInstall\" X=\"120\" Y=\"150\" Width=\"-24\" Height=\"17\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"no\" HexStyle=\"0x0000009\">#(loc.PerMachineInstallRButton)</Button>\n        <Button Name=\"PerUserInstall\" X=\"120\" Y=\"170\" Width=\"-24\" Height=\"17\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"no\" HexStyle=\"0x0000009\">#(loc.PerUserInstallRButton)</Button>\n\n        <Text X=\"64\" Y=\"218\" Width=\"92\" Height=\"17\" FontId=\"0\">#(loc.InstallDirPathLabel)</Text>\n\t\t<Editbox Name=\"InstallFolderEditbox\" X=\"164\" Y=\"216\" Width=\"-144\" Height=\"21\" TabStop=\"yes\" FontId=\"0\" FileSystemAutoComplete=\"yes\" HideWhenDisabled=\"no\" />\n\t\t<Button Name=\"BrowseButton\" X=\"-64\" Y=\"215\" Width=\"75\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"no\">#(loc.OptionsBrowseButton)</Button>\n        \n        <Button Name=\"BackButton\" X=\"-256\" Y=\"-10\" Width=\"110\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.BackButton)</Button>\n\t\t<Button Name=\"NextButton\" X=\"-140\" Y=\"-10\" Width=\"110\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.NextButton)</Button>\n\t\t<Button Name=\"CloseButton\"  X=\"-24\"  Y=\"-10\" Width=\"110\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.InstallCloseButton)</Button>\n\t</Page>\n\t<Page Name=\"Progress\">\n        <Text Name=\"InstallingHeader\" X=\"24\" Y=\"30\" Width=\"-24\" Height=\"75\" FontId=\"3\" DisablePrefix=\"yes\">\n        </Text>\n\n\t\t<Progressbar Name=\"OverallCalculatedProgressbar\" X=\"24\" Y=\"183\" Width=\"-24\" Height=\"17\" />\n\t\t<Text Name=\"ExecuteProgressActionDataText\" X=\"24\" Y=\"205\" Width=\"-24\" Height=\"52\" FontId=\"0\" DisablePrefix=\"yes\">#(loc.ExecuteProgressActionDataText)</Text>\n\n\t\t<Image X=\"25\" Y=\"-20\" Width=\"127\" Height=\"30\" ImageFile=\"meteor-logo-sm.jpg\"/>\n\t\t<Button Name=\"ProgressCancelButton\" X=\"-24\" Y=\"-18\" Width=\"110\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.ProgressCancelButton)</Button>\n\t</Page>\n\t<Page Name=\"SvcOptions\">\n\n\t\t<Text X=\"24\" Y=\"30\" Width=\"600\" Height=\"100\" FontId=\"3\" DisablePrefix=\"yes\">\nBefore getting started, please take a moment to\ncreate a Meteor developer account.</Text>\n\n\t    <Text X=\"24\" Y=\"100\" Width=\"-24\" Height=\"110\" FontId=\"1\" DisablePrefix=\"yes\">\nRegistering tells us who's using Meteor for Windows and helps us make it better.\nYou'll also need your account to publish Atmosphere packages and get\nnotified about critical security updates when they happen.\n\t\t</Text>\n\n        <Button Name=\"CreateRButton\" X=\"30\" Y=\"194\" Width=\"200\" Height=\"17\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"no\" HexStyle=\"0x0000009\">#(loc.CreateRButton)</Button>\n        <Button Name=\"SignInRButton\" X=\"30\" Y=\"214\" Width=\"200\" Height=\"17\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"no\" HexStyle=\"0x0000009\">#(loc.SignInRButton)</Button>\n\n\n        <!-- for signup: -->\n        <Text Name=\"RegisterEmailLabel\" X=\"292\" Y=\"194\" Width=\"120\" Height=\"17\" FontId=\"0\">#(loc.RegisterEmail):</Text>\n        <Text Name=\"RegisterUserLabel\" X=\"292\" Y=\"222\" Width=\"120\" Height=\"17\" FontId=\"0\">#(loc.RegisterUser):</Text>\n        <Text Name=\"RegisterPassLabel\" X=\"292\" Y=\"250\" Width=\"120\" Height=\"17\" FontId=\"0\">#(loc.RegisterPass):</Text>\n\n        <Editbox Name=\"RegisterEmail\" X=\"410\" Y=\"192\" Width=\"180\" Height=\"21\" TabStop=\"yes\" FontId=\"0\">[RegisterEmail]</Editbox>\n        <Editbox Name=\"RegisterUser\" X=\"410\" Y=\"220\" Width=\"180\" Height=\"21\" TabStop=\"yes\" FontId=\"0\">[RegisterUser]</Editbox>\n        <Editbox Name=\"RegisterPass\" X=\"410\" Y=\"248\" Width=\"180\" Height=\"21\" TabStop=\"yes\" FontId=\"0\" HexStyle=\"0x20\">[RegisterPass]</Editbox>\n\n\n        <!-- for login: -->\n        <!-- XXX For some reason, Visible=\"no\" below doesn't work.\n             instead, we set it imperatively when we switch to this\n             page. See #Hidden --> \n        <Text Name=\"LoginUsernameOrEmailLabel\" Visible=\"no\" X=\"292\" Y=\"194\" Width=\"120\" Height=\"17\" FontId=\"0\">#(loc.RegisterUsernameOrEmail):</Text>\n        <Text Name=\"LoginPassLabel\" Visible=\"no\" X=\"292\" Y=\"222\" Width=\"120\" Height=\"17\" FontId=\"0\">#(loc.RegisterPass):</Text>\n\n        <Editbox Name=\"LoginUsernameOrEmail\" Visible=\"no\" X=\"410\" Y=\"192\" Width=\"180\" Height=\"21\" TabStop=\"yes\" FontId=\"0\">[LoginUsernameOrEmail]</Editbox>\n        <Editbox Name=\"LoginPass\" Visible=\"no\" X=\"410\" Y=\"220\" Width=\"180\" Height=\"21\" TabStop=\"yes\" FontId=\"0\" HexStyle=\"0x20\">[LoginPass]</Editbox>\n\n        <Image X=\"25\" Y=\"-20\" Width=\"127\" Height=\"30\" ImageFile=\"meteor-logo-sm.jpg\"/>\n\n        <!-- bottom buttons: -->\n        <Button Name=\"SkipButton\" X=\"-140\" Y=\"-18\" Width=\"110\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.SkipButton)</Button>\n\t\t<Button Name=\"InstallButton\" X=\"-24\" Y=\"-18\" Width=\"110\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">Sign In</Button>\n\t</Page>\n\t<Page Name=\"Modify\">\n\t\t<Text X=\"24\" Y=\"20\" Width=\"-220\" Height=\"24\" FontId=\"2\" DisablePrefix=\"yes\">#(loc.ModifyHeader)</Text>\n\t\t<Text X=\"24\" Y=\"78\" Width=\"-24\" Height=\"140\" FontId=\"1\" DisablePrefix=\"yes\">#(loc.ModifyInfo)</Text>\n\t\t<Button Name=\"RepairButton\" X=\"-256\" Y=\"-10\" Width=\"110\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.ModifyRepairButton)</Button>\n\t\t<Button Name=\"UninstallButton\" X=\"-140\" Y=\"-10\" Width=\"110\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.ModifyUninstallButton)</Button>\n\t\t<Button Name=\"ModifyCancelButton\" X=\"-24\" Y=\"-10\" Width=\"110\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.ModifyCloseButton)</Button>\n\t</Page>\n\t<Page Name=\"Success\">\n\t\t<Text Name=\"SuccessHeader\" X=\"24\" Y=\"30\" Width=\"420\" Height=\"50\" FontId=\"3\" DisablePrefix=\"yes\">[varSuccessHeader]</Text>\n\t\t<Hypertext Name=\"SuccessInfo\" X=\"24\" Y=\"80\" Width=\"-24\" Height=\"160\" FontId=\"1\" TabStop=\"no\" HideWhenDisabled=\"yes\">[varSuccessInfo]</Hypertext>\n\n\t\t<Image X=\"25\" Y=\"-20\" Width=\"127\" Height=\"30\" ImageFile=\"meteor-logo-sm.jpg\"/>\n\t\t<Button Name=\"SuccessCancelButton\" X=\"-24\" Y=\"-18\" Width=\"110\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.SuccessCloseButton)</Button>\n\t</Page>\n\t<Page Name=\"Failure\">\n\t\t<Text Name=\"FailureHeader\" X=\"24\" Y=\"20\" Width=\"-220\" Height=\"24\" FontId=\"2\" DisablePrefix=\"yes\">[varFailureHeader]</Text>\n\t\t<Hypertext Name=\"FailureLogFileLink\" X=\"24\" Y=\"78\" Width=\"-24\" Height=\"48\" FontId=\"1\" TabStop=\"yes\" HideWhenDisabled=\"yes\">#(loc.FailureHyperlinkLogText)</Hypertext>\n\t\t<Hypertext Name=\"FailureMessageText\" X=\"24\" Y=\"130\" Width=\"-24\" Height=\"48\" FontId=\"0\" TabStop=\"yes\" HideWhenDisabled=\"yes\"/>\n\n\t\t<Text Name=\"FailureRestartText\" X=\"24\" Y=\"-100\" Width=\"-24\" Height=\"34\" FontId=\"0\" HideWhenDisabled=\"yes\" DisablePrefix=\"yes\">#(loc.FailureRestartText)</Text>\n\t\t<Button Name=\"FailureRestartButton\" X=\"-140\" Y=\"-10\" Width=\"110\" Height=\"23\" TabStop=\"yes\" FontId=\"0\" HideWhenDisabled=\"yes\">#(loc.FailureRestartButton)</Button>\n\t\t<Button Name=\"FailureCloseButton\" X=\"-24\" Y=\"-10\" Width=\"110\" Height=\"23\" TabStop=\"yes\" FontId=\"0\">#(loc.FailureCloseButton)</Button>\n\t</Page>\n</Theme>\n"
  },
  {
    "path": "scripts/windows/installer/WiXInstaller/Resources/dummy.file",
    "content": ""
  },
  {
    "path": "scripts/windows/installer/WiXInstaller/SetupPackage.wixproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <Platform Condition=\" '$(Platform)' == '' \">x86</Platform>\n    <ProductVersion>3.8</ProductVersion>\n    <ProjectGuid>7b569f5b-5d73-4e7b-be41-041a2f22a521</ProjectGuid>\n    <SchemaVersion>2.0</SchemaVersion>\n    <OutputType>Bundle</OutputType>\n    <WixTargetsPath Condition=\" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' \">$(MSBuildExtensionsPath32)\\Microsoft\\WiX\\v3.x\\Wix.targets</WixTargetsPath>\n    <WixTargetsPath Condition=\" '$(WixTargetsPath)' == '' \">$(MSBuildExtensionsPath)\\Microsoft\\WiX\\v3.x\\Wix.targets</WixTargetsPath>\n    <Name>SetupPackage</Name>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|x86' \">\n    <OutputPath>bin\\$(Configuration)\\$(Platform)\\</OutputPath>\n    <IntermediateOutputPath>obj\\$(Configuration)\\</IntermediateOutputPath>\n    <SuppressPdbOutput>True</SuppressPdbOutput>\n    <SuppressAllWarnings>True</SuppressAllWarnings>\n    <Pedantic>False</Pedantic>\n    <OutputName>InstallMeteor</OutputName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|x64' \">\n    <OutputPath>bin\\$(Configuration)\\$(Platform)\\</OutputPath>\n    <IntermediateOutputPath>obj\\$(Configuration)\\</IntermediateOutputPath>\n    <SuppressPdbOutput>True</SuppressPdbOutput>\n    <SuppressAllWarnings>True</SuppressAllWarnings>\n    <Pedantic>False</Pedantic>\n    <OutputName>InstallMeteor</OutputName>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Include=\"Meteor_Bundle.wxs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <WixExtension Include=\"WixNetFxExtension\">\n      <HintPath>$(WixExtDir)\\WixNetFxExtension.dll</HintPath>\n      <Name>WixNetFxExtension</Name>\n    </WixExtension>\n    <WixExtension Include=\"WixBalExtensionExt\">\n      <HintPath>..\\WiXBalExtension\\build\\WixBalExtensionExt.dll</HintPath>\n      <Name>WixBalExtensionExt</Name>\n    </WixExtension>\n    <WixExtension Include=\"WixUtilExtension\">\n      <HintPath>$(WixExtDir)\\WixUtilExtension.dll</HintPath>\n      <Name>WixUtilExtension</Name>\n    </WixExtension>\n  </ItemGroup>\n  <ItemGroup>\n    <Content Include=\"Configuration.wxi\" />\n    <Content Include=\"Resources\\Background.png\" />\n    <Content Include=\"Resources\\Theme_Meteor.xml\" />\n    <Content Include=\"Resources\\TopHeader.png\" />\n  </ItemGroup>\n  <ItemGroup>\n    <EmbeddedResource Include=\"Resources\\Theme_Meteor.wxl\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Folder Include=\"Resources\" />\n  </ItemGroup>\n  <Import Project=\"$(WixTargetsPath)\" />\n  <PropertyGroup>\n    <PostBuildEvent>copy \"$(ProjectDir)$(OutDir)$(TargetFileName)\" \"$(ProjectDir)..\\Release\\\" /Y</PostBuildEvent>\n  </PropertyGroup>\n  <!--\n\tTo modify your build process, add your task inside one of the targets below and uncomment it.\n\tOther similar extension points exist, see Wix.targets.\n\t<Target Name=\"BeforeBuild\">\n\t</Target>\n\t<Target Name=\"AfterBuild\">\n\t</Target>\n\t-->\n</Project>"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/BalBaseBootstrapperApplication.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"BalBaseBootstrapperApplication.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//-------------------------------------------------------------------------------------------------\n\n#include <windows.h>\n#include <msiquery.h>\n\n#include \"IBootstrapperEngine.h\"\n#include \"IBootstrapperApplication.h\"\n\n#include \"balutil.h\"\n#include \"balretry.h\"\n\nclass CBalBaseBootstrapperApplication : public IBootstrapperApplication\n{\npublic: // IUnknown\n    virtual STDMETHODIMP QueryInterface(\n        __in REFIID riid,\n        __out LPVOID *ppvObject\n        )\n    {\n        if (!ppvObject)\n        {\n            return E_INVALIDARG;\n        }\n\n        *ppvObject = NULL;\n\n        if (::IsEqualIID(__uuidof(IBootstrapperApplication), riid))\n        {\n            *ppvObject = static_cast<IBootstrapperApplication*>(this);\n        }\n        else if (::IsEqualIID(IID_IUnknown, riid))\n        {\n            *ppvObject = static_cast<IUnknown*>(this);\n        }\n        else // no interface for requested iid\n        {\n            return E_NOINTERFACE;\n        }\n\n        AddRef();\n        return S_OK;\n    }\n\n    virtual STDMETHODIMP_(ULONG) AddRef()\n    {\n        return ::InterlockedIncrement(&this->m_cReferences);\n    }\n\n    virtual STDMETHODIMP_(ULONG) Release()\n    {\n        long l = ::InterlockedDecrement(&this->m_cReferences);\n        if (0 < l)\n        {\n            return l;\n        }\n\n        delete this;\n        return 0;\n    }\n\npublic: // IBurnUserExperience\n    virtual STDMETHODIMP OnStartup()\n    {\n        return S_OK;\n    }\n\n    virtual STDMETHODIMP_(int) OnShutdown()\n    {\n        return IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnSystemShutdown(\n        __in DWORD dwEndSession,\n        __in int /*nRecommendation*/\n        )\n    {\n        // Allow requests to shut down when critical or not applying.\n        if (ENDSESSION_CRITICAL & dwEndSession || !m_fApplying)\n        {\n            return IDOK;\n        }\n\n        return IDCANCEL;\n    }\n\n    virtual STDMETHODIMP_(int) OnDetectBegin(\n        __in BOOL /*fInstalled*/,\n        __in DWORD /*cPackages*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnDetectForwardCompatibleBundle(\n        __in_z LPCWSTR /*wzBundleId*/,\n        __in BOOTSTRAPPER_RELATION_TYPE /*relationType*/,\n        __in_z LPCWSTR /*wzBundleTag*/,\n        __in BOOL /*fPerMachine*/,\n        __in DWORD64 /*dw64Version*/,\n        __in int nRecommendation\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : nRecommendation;\n    }\n\n    virtual STDMETHODIMP_(int) OnDetectUpdateBegin(\n        __in_z LPCWSTR /*wzUpdateLocation*/,\n        __in int nRecommendation\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : nRecommendation;\n    }\n\n    virtual STDMETHODIMP_(void) OnDetectUpdateComplete(\n        __in HRESULT /*hrStatus*/,\n        __in_z_opt LPCWSTR /*wzUpdateLocation*/\n        )\n    {\n    }\n\n    virtual STDMETHODIMP_(int) OnDetectPriorBundle(\n        __in_z LPCWSTR /*wzBundleId*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnDetectPackageBegin(\n        __in_z LPCWSTR /*wzPackageId*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnDetectRelatedBundle(\n        __in_z LPCWSTR /*wzBundleId*/,\n        __in BOOTSTRAPPER_RELATION_TYPE /*relationType*/,\n        __in_z LPCWSTR /*wzBundleTag*/,\n        __in BOOL /*fPerMachine*/,\n        __in DWORD64 /*dw64Version*/,\n        __in BOOTSTRAPPER_RELATED_OPERATION /*operation*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnDetectRelatedMsiPackage(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in_z LPCWSTR /*wzProductCode*/,\n        __in BOOL /*fPerMachine*/,\n        __in DWORD64 /*dw64Version*/,\n        __in BOOTSTRAPPER_RELATED_OPERATION /*operation*/\n        ) \n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnDetectTargetMsiPackage(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in_z LPCWSTR /*wzProductCode*/,\n        __in BOOTSTRAPPER_PACKAGE_STATE /*patchState*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnDetectMsiFeature(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in_z LPCWSTR /*wzFeatureId*/,\n        __in BOOTSTRAPPER_FEATURE_STATE /*state*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(void) OnDetectPackageComplete(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in HRESULT /*hrStatus*/,\n        __in BOOTSTRAPPER_PACKAGE_STATE /*state*/\n        )\n    {\n    }\n\n    virtual STDMETHODIMP_(void) OnDetectComplete(\n        __in HRESULT /*hrStatus*/\n        )\n    {\n    }\n\n    virtual STDMETHODIMP_(int) OnPlanBegin(\n        __in DWORD /*cPackages*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnPlanRelatedBundle(\n        __in_z LPCWSTR /*wzBundleId*/,\n        __inout BOOTSTRAPPER_REQUEST_STATE* /*pRequestedState*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnPlanPackageBegin(\n        __in_z LPCWSTR /*wzPackageId*/, \n        __inout BOOTSTRAPPER_REQUEST_STATE* /*pRequestState*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnPlanTargetMsiPackage(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in_z LPCWSTR /*wzProductCode*/,\n        __inout BOOTSTRAPPER_REQUEST_STATE* /*pRequestedState*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnPlanMsiFeature(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in_z LPCWSTR /*wzFeatureId*/,\n        __inout BOOTSTRAPPER_FEATURE_STATE* /*pRequestedState*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(void) OnPlanPackageComplete(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in HRESULT /*hrStatus*/,\n        __in BOOTSTRAPPER_PACKAGE_STATE /*state*/,\n        __in BOOTSTRAPPER_REQUEST_STATE /*requested*/,\n        __in BOOTSTRAPPER_ACTION_STATE /*execute*/,\n        __in BOOTSTRAPPER_ACTION_STATE /*rollback*/\n        )\n    {\n    }\n\n    virtual STDMETHODIMP_(void) OnPlanComplete(\n        __in HRESULT /*hrStatus*/\n        )\n    {\n    }\n\n    virtual STDMETHODIMP_(int) OnApplyBegin()\n    {\n        m_fApplying = TRUE;\n\n        m_dwProgressPercentage = 0;\n        m_dwOverallProgressPercentage = 0;\n\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnElevate()\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnRegisterBegin()\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(void) OnRegisterComplete(\n        __in HRESULT /*hrStatus*/\n        )\n    {\n        return;\n    }\n\n    virtual STDMETHODIMP_(void) OnUnregisterBegin()\n    {\n        return;\n    }\n\n    virtual STDMETHODIMP_(void) OnUnregisterComplete(\n        __in HRESULT /*hrStatus*/\n        )\n    {\n        return;\n    }\n\n    virtual STDMETHODIMP_(int) OnApplyComplete(\n        __in HRESULT /*hrStatus*/,\n        __in BOOTSTRAPPER_APPLY_RESTART restart\n        )\n    {\n        m_fApplying = FALSE;\n        return BOOTSTRAPPER_APPLY_RESTART_REQUIRED == restart ? IDRESTART : CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnCacheBegin()\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnCachePackageBegin(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in DWORD /*cCachePayloads*/,\n        __in DWORD64 /*dw64PackageCacheSize*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnCacheAcquireBegin(\n        __in_z LPCWSTR wzPackageOrContainerId,\n        __in_z_opt LPCWSTR wzPayloadId,\n        __in BOOTSTRAPPER_CACHE_OPERATION /*operation*/,\n        __in_z LPCWSTR /*wzSource*/\n        )\n    {\n        BalRetryStartPackage(BALRETRY_TYPE_CACHE, wzPackageOrContainerId, wzPayloadId);\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnCacheAcquireProgress(\n        __in_z LPCWSTR /*wzPackageOrContainerId*/,\n        __in_z_opt LPCWSTR /*wzPayloadId*/,\n        __in DWORD64 /*dw64Progress*/,\n        __in DWORD64 /*dw64Total*/,\n        __in DWORD /*dwOverallPercentage*/\n        )\n    {\n        HRESULT hr = S_OK;\n        int nResult = IDNOACTION;\n\n        // Send progress even though we don't update the numbers to at least give the caller an opportunity\n        // to cancel.\n        if (BOOTSTRAPPER_DISPLAY_EMBEDDED == m_display)\n        {\n            hr = m_pEngine->SendEmbeddedProgress(m_dwProgressPercentage, m_dwOverallProgressPercentage, &nResult);\n            BalExitOnFailure(hr, \"Failed to send embedded cache progress.\");\n        }\n\n    LExit:\n        return FAILED(hr) ? IDERROR : CheckCanceled() ? IDCANCEL : nResult;\n    }\n\n    virtual STDMETHODIMP_(int) OnCacheAcquireComplete(\n        __in_z LPCWSTR wzPackageOrContainerId,\n        __in_z_opt LPCWSTR wzPayloadId,\n        __in HRESULT hrStatus,\n        __in int nRecommendation\n        )\n    {\n        int nResult = CheckCanceled() ? IDCANCEL : BalRetryEndPackage(BALRETRY_TYPE_CACHE, wzPackageOrContainerId, wzPayloadId, hrStatus);\n        return IDNOACTION == nResult ? nRecommendation : nResult;\n    }\n\n    virtual STDMETHODIMP_(int) OnCacheVerifyBegin(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in_z LPCWSTR /*wzPayloadId*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnCacheVerifyComplete(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in_z LPCWSTR /*wzPayloadId*/,\n        __in HRESULT /*hrStatus*/,\n        __in int nRecommendation\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : nRecommendation;\n    }\n\n    virtual STDMETHODIMP_(int) OnCachePackageComplete(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in HRESULT /*hrStatus*/,\n        __in int nRecommendation\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : nRecommendation;\n    }\n\n    virtual STDMETHODIMP_(void) OnCacheComplete(\n        __in HRESULT /*hrStatus*/\n        )\n    {\n    }\n\n    virtual STDMETHODIMP_(int) OnExecuteBegin(\n        __in DWORD /*cExecutingPackages*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnExecutePackageBegin(\n        __in_z LPCWSTR wzPackageId,\n        __in BOOL fExecute\n        )\n    {\n        // Only track retry on execution (not rollback).\n        if (fExecute)\n        {\n            BalRetryStartPackage(BALRETRY_TYPE_EXECUTE, wzPackageId, NULL);\n        }\n\n        m_fRollingBack = !fExecute;\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnExecutePatchTarget(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in_z LPCWSTR /*wzTargetProductCode*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnError(\n        __in BOOTSTRAPPER_ERROR_TYPE errorType,\n        __in_z LPCWSTR wzPackageId,\n        __in DWORD dwCode,\n        __in_z LPCWSTR /*wzError*/,\n        __in DWORD /*dwUIHint*/,\n        __in DWORD /*cData*/,\n        __in_ecount_z_opt(cData) LPCWSTR* /*rgwzData*/,\n        __in int nRecommendation\n        )\n    {\n        BalRetryErrorOccurred(wzPackageId, dwCode);\n\n        if (BOOTSTRAPPER_DISPLAY_FULL == m_display)\n        {\n            if (BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_SERVER == errorType ||BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_PROXY == errorType)\n            {\n                nRecommendation = IDTRYAGAIN;\n            }\n        }\n\n        return CheckCanceled() ? IDCANCEL : nRecommendation;\n    }\n\n    virtual STDMETHODIMP_(int) OnProgress(\n        __in DWORD dwProgressPercentage,\n        __in DWORD dwOverallProgressPercentage\n        )\n    {\n        HRESULT hr = S_OK;\n        int nResult = IDNOACTION;\n\n        m_dwProgressPercentage = dwProgressPercentage;\n        m_dwOverallProgressPercentage = dwOverallProgressPercentage;\n\n        if (BOOTSTRAPPER_DISPLAY_EMBEDDED == m_display)\n        {\n            hr = m_pEngine->SendEmbeddedProgress(m_dwProgressPercentage, m_dwOverallProgressPercentage, &nResult);\n            BalExitOnFailure(hr, \"Failed to send embedded overall progress.\");\n        }\n\n    LExit:\n        return FAILED(hr) ? IDERROR : CheckCanceled() ? IDCANCEL : nResult;\n    }\n\n    virtual STDMETHODIMP_(int) OnDownloadPayloadBegin(\n        __in_z LPCWSTR /*wzPayloadId*/,\n        __in_z LPCWSTR /*wzPayloadFileName*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnDownloadPayloadComplete(\n        __in_z LPCWSTR /*wzPayloadId*/,\n        __in_z LPCWSTR /*wzPayloadFileName*/,\n        __in HRESULT /*hrStatus*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnExecuteProgress(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in DWORD /*dwProgressPercentage*/,\n        __in DWORD /*dwOverallProgressPercentage*/\n        )\n    {\n        HRESULT hr = S_OK;\n        int nResult = IDNOACTION;\n\n        // Send progress even though we don't update the numbers to at least give the caller an opportunity\n        // to cancel.\n        if (BOOTSTRAPPER_DISPLAY_EMBEDDED == m_display)\n        {\n            hr = m_pEngine->SendEmbeddedProgress(m_dwProgressPercentage, m_dwOverallProgressPercentage, &nResult);\n            BalExitOnFailure(hr, \"Failed to send embedded execute progress.\");\n        }\n\n    LExit:\n        return FAILED(hr) ? IDERROR : CheckCanceled() ? IDCANCEL : nResult;\n    }\n\n    virtual STDMETHODIMP_(int) OnExecuteMsiMessage(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in INSTALLMESSAGE /*mt*/,\n        __in UINT /*uiFlags*/,\n        __in_z LPCWSTR /*wzMessage*/,\n        __in DWORD /*cData*/,\n        __in_ecount_z_opt(cData) LPCWSTR* /*rgwzData*/,\n        __in int nRecommendation\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : nRecommendation;\n    }\n\n    virtual STDMETHODIMP_(int) OnExecuteFilesInUse(\n        __in_z LPCWSTR /*wzPackageId*/,\n        __in DWORD /*cFiles*/,\n        __in_ecount_z(cFiles) LPCWSTR* /*rgwzFiles*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\n    virtual STDMETHODIMP_(int) OnExecutePackageComplete(\n        __in_z LPCWSTR wzPackageId,\n        __in HRESULT hrExitCode,\n        __in BOOTSTRAPPER_APPLY_RESTART /*restart*/,\n        __in int nRecommendation\n        )\n    {\n        int nResult = CheckCanceled() ? IDCANCEL : CheckCanceled() ? IDCANCEL : BalRetryEndPackage(BALRETRY_TYPE_EXECUTE, wzPackageId, NULL, hrExitCode);\n        return IDNOACTION == nResult ? nRecommendation : nResult;\n    }\n\n    virtual STDMETHODIMP_(void) OnExecuteComplete(\n        __in HRESULT /*hrStatus*/\n        )\n    {\n    }\n\n    virtual STDMETHODIMP_(int) OnResolveSource(\n        __in_z LPCWSTR /*wzPackageOrContainerId*/,\n        __in_z_opt LPCWSTR /*wzPayloadId*/,\n        __in_z LPCWSTR /*wzLocalSource*/,\n        __in_z_opt LPCWSTR /*wzDownloadSource*/\n        )\n    {\n        return CheckCanceled() ? IDCANCEL : IDNOACTION;\n    }\n\nprotected:\n    //\n    // PromptCancel - prompts the user to close (if not forced).\n    //\n    virtual BOOL PromptCancel(\n        __in HWND hWnd,\n        __in BOOL fForceCancel,\n        __in_z LPCWSTR wzMessage,\n        __in_z LPCWSTR wzCaption\n        )\n    {\n        ::EnterCriticalSection(&m_csCanceled);\n\n        // Only prompt the user to close if we have not canceled already.\n        if (!m_fCanceled)\n        {\n            if (fForceCancel)\n            {\n                m_fCanceled = TRUE;\n            }\n            else\n            {\n                m_fCanceled = (IDYES == ::MessageBoxW(hWnd, wzMessage, wzCaption, MB_YESNO | MB_ICONEXCLAMATION));\n            }\n        }\n\n        ::LeaveCriticalSection(&m_csCanceled);\n\n        return m_fCanceled;\n    }\n\n    //\n    // CheckCanceled - waits if the cancel dialog is up and checks to see if the user canceled the operation.\n    //\n    BOOL CheckCanceled()\n    {\n        ::EnterCriticalSection(&m_csCanceled);\n        ::LeaveCriticalSection(&m_csCanceled);\n        return m_fRollingBack ? FALSE : m_fCanceled;\n    }\n\n    BOOL IsRollingBack()\n    {\n        return m_fRollingBack;\n    }\n\n    BOOL IsCanceled()\n    {\n        return m_fCanceled;\n    }\n\n    CBalBaseBootstrapperApplication(\n        __in IBootstrapperEngine* pEngine,\n        __in const BOOTSTRAPPER_COMMAND* pCommand,\n        __in DWORD dwRetryCount = 0,\n        __in DWORD dwRetryTimeout = 1000\n        )\n    {\n        m_cReferences = 1;\n        m_display = pCommand->display;\n        m_restart = pCommand->restart;\n\n        pEngine->AddRef();\n        m_pEngine = pEngine;\n\n        ::InitializeCriticalSection(&m_csCanceled);\n        m_fCanceled = FALSE;\n        m_fApplying = FALSE;\n        m_fRollingBack = FALSE;\n\n        BalRetryInitialize(dwRetryCount, dwRetryTimeout);\n    }\n\n    virtual ~CBalBaseBootstrapperApplication()\n    {\n        BalRetryUninitialize();\n        ::DeleteCriticalSection(&m_csCanceled);\n\n        ReleaseNullObject(m_pEngine);\n    }\n\nprivate:\n    long m_cReferences;\n    BOOTSTRAPPER_DISPLAY m_display;\n    BOOTSTRAPPER_RESTART m_restart;\n    IBootstrapperEngine* m_pEngine;\n\n    CRITICAL_SECTION m_csCanceled;\n    BOOL m_fCanceled;\n    BOOL m_fApplying;\n    BOOL m_fRollingBack;\n\n    DWORD m_dwProgressPercentage;\n    DWORD m_dwOverallProgressPercentage;\n};\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/IBootstrapperApplication.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"IBootstrapperApplication.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n// IBootstrapperApplication implemented by a bootstrapper application and used by bootstrapper engine.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n\nenum BOOTSTRAPPER_DISPLAY\n{\n    BOOTSTRAPPER_DISPLAY_UNKNOWN,\n    BOOTSTRAPPER_DISPLAY_EMBEDDED,\n    BOOTSTRAPPER_DISPLAY_NONE,\n    BOOTSTRAPPER_DISPLAY_PASSIVE,\n    BOOTSTRAPPER_DISPLAY_FULL,\n};\n\n\nenum BOOTSTRAPPER_RESTART\n{\n    BOOTSTRAPPER_RESTART_UNKNOWN,\n    BOOTSTRAPPER_RESTART_NEVER,\n    BOOTSTRAPPER_RESTART_PROMPT,\n    BOOTSTRAPPER_RESTART_AUTOMATIC,\n    BOOTSTRAPPER_RESTART_ALWAYS,\n};\n\n\nenum BOOTSTRAPPER_RESUME_TYPE\n{\n    BOOTSTRAPPER_RESUME_TYPE_NONE,\n    BOOTSTRAPPER_RESUME_TYPE_INVALID,        // resume information is present but invalid\n    BOOTSTRAPPER_RESUME_TYPE_INTERRUPTED,    // relaunched after an unexpected interruption\n    BOOTSTRAPPER_RESUME_TYPE_REBOOT_PENDING, // reboot has not taken place yet\n    BOOTSTRAPPER_RESUME_TYPE_REBOOT,         // relaunched after reboot\n    BOOTSTRAPPER_RESUME_TYPE_SUSPEND,        // relaunched after suspend\n    BOOTSTRAPPER_RESUME_TYPE_ARP,            // launched from ARP\n};\n\n\nenum BOOTSTRAPPER_ERROR_TYPE\n{\n    BOOTSTRAPPER_ERROR_TYPE_ELEVATE,            // error occurred trying to elevate.\n    BOOTSTRAPPER_ERROR_TYPE_WINDOWS_INSTALLER,  // error came from windows installer.\n    BOOTSTRAPPER_ERROR_TYPE_EXE_PACKAGE,        // error came from an exe package.\n    BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_SERVER,   // error occurred trying to authenticate with HTTP server.\n    BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_PROXY,    // error occurred trying to authenticate with HTTP proxy.\n    BOOTSTRAPPER_ERROR_TYPE_APPLY,              // error occurred during apply.\n};\n\n\nenum BOOTSTRAPPER_RELATED_OPERATION\n{\n    BOOTSTRAPPER_RELATED_OPERATION_NONE,\n    BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE,\n    BOOTSTRAPPER_RELATED_OPERATION_MINOR_UPDATE,\n    BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE,\n    BOOTSTRAPPER_RELATED_OPERATION_REMOVE,\n    BOOTSTRAPPER_RELATED_OPERATION_INSTALL,\n    BOOTSTRAPPER_RELATED_OPERATION_REPAIR,\n};\n\n\nenum BOOTSTRAPPER_CACHE_OPERATION\n{\n    BOOTSTRAPPER_CACHE_OPERATION_COPY,\n    BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD,\n    BOOTSTRAPPER_CACHE_OPERATION_EXTRACT,\n};\n\n\nenum BOOTSTRAPPER_APPLY_RESTART\n{\n    BOOTSTRAPPER_APPLY_RESTART_NONE,\n    BOOTSTRAPPER_APPLY_RESTART_REQUIRED,\n    BOOTSTRAPPER_APPLY_RESTART_INITIATED,\n};\n\n\nenum BOOTSTRAPPER_RELATION_TYPE\n{\n    BOOTSTRAPPER_RELATION_NONE,\n    BOOTSTRAPPER_RELATION_DETECT,\n    BOOTSTRAPPER_RELATION_UPGRADE,\n    BOOTSTRAPPER_RELATION_ADDON,\n    BOOTSTRAPPER_RELATION_PATCH,\n    BOOTSTRAPPER_RELATION_DEPENDENT,\n    BOOTSTRAPPER_RELATION_UPDATE,\n};\n\n\nstruct BOOTSTRAPPER_COMMAND\n{\n    BOOTSTRAPPER_ACTION action;\n    BOOTSTRAPPER_DISPLAY display;\n    BOOTSTRAPPER_RESTART restart;\n\n    LPWSTR wzCommandLine;\n    int nCmdShow;\n\n    BOOTSTRAPPER_RESUME_TYPE resumeType;\n    HWND hwndSplashScreen;\n\n    // If this was run from a related bundle, specifies the relation type\n    BOOTSTRAPPER_RELATION_TYPE relationType;\n    BOOL fPassthrough;\n\n    LPWSTR wzLayoutDirectory;\n};\n\n\nDECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, \"53C31D56-49C0-426B-AB06-099D717C67FE\")\n{\n    // OnStartup - called when the engine is ready for the bootstrapper application to start.\n    //\n    STDMETHOD(OnStartup)() = 0;\n\n    // OnShutdown - called after the bootstrapper application quits the engine.\n    //\n    // Return:\n    //  IDRESTART instructs the engine to restart. The engine will not launch again after the machine\n    //            is rebooted. Ignored if reboot was already initiated by OnExecutePackageComplete().\n    //\n    // IDRELOAD_BOOTSTRAPPER instructs the engine to unload the bootstrapper application and restart\n    //                       the engine which will load the bootstrapper application again. Typically\n    //                       used to switch from a native bootstrapper application to a managed one.\n    //\n    //  All other return codes are ignored.\n    STDMETHOD_(int, OnShutdown)() = 0;\n\n    // OnSystemShutdown - called when the operating system is instructed to shutdown the machine.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to block the shutdown of the machine.\n    //\n    //  All other return codes allow the shutdown to commence.\n    STDMETHOD_(int, OnSystemShutdown)(\n        __in DWORD dwEndSession,\n        __in int nRecommendation\n        ) = 0;\n\n    // OnDetectBegin - called when the engine begins detection.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop detection.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnDetectBegin)(\n        __in BOOL fInstalled,\n        __in DWORD cPackages\n        ) = 0;\n\n    // OnDetectForwardCompatibleBundle - called when the engine detects a forward compatible bundle.\n    //\n    // Return:\n    //  IDOK instructs the engine to use the forward compatible bundle.\n    //\n    //  IDCANCEL instructs the engine to stop detection.\n    //\n    //  IDNOACTION instructs the engine to not use the forward compatible bundle.\n    STDMETHOD_(int, OnDetectForwardCompatibleBundle)(\n        __in_z LPCWSTR wzBundleId,\n        __in BOOTSTRAPPER_RELATION_TYPE relationType,\n        __in_z LPCWSTR wzBundleTag,\n        __in BOOL fPerMachine,\n        __in DWORD64 dw64Version,\n        __in int nRecommendation\n        ) = 0;\n\n    // OnDetectUpdateBegin - called when the engine begins detection for bundle update.\n    //\n    // Return:\n    //  IDOK instructs the engine to attempt update detection.\n    //\n    //  IDCANCEL instructs the engine to stop detection.\n    //\n    //  IDNOACTION instructs the engine to skip update detection.\n    STDMETHOD_(int, OnDetectUpdateBegin)(\n        __in_z LPCWSTR wzUpdateLocation,\n        __in int nRecommendation\n        ) = 0;\n\n    // OnDetectUpdateComplete - called when the engine completes detection for bundle update.\n    //\n    // Remarks:\n    //  wzUpdateLocation is null if no update was available.\n    STDMETHOD_(void, OnDetectUpdateComplete)(\n        __in HRESULT hrStatus,\n        __in_z_opt LPCWSTR wzUpdateLocation\n        ) = 0;\n\n    // OnDetectRelatedBundle - called when the engine detects a related bundle.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop detection.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnDetectRelatedBundle)(\n        __in_z LPCWSTR wzBundleId,\n        __in BOOTSTRAPPER_RELATION_TYPE relationType,\n        __in_z LPCWSTR wzBundleTag,\n        __in BOOL fPerMachine,\n        __in DWORD64 dw64Version,\n        __in BOOTSTRAPPER_RELATED_OPERATION operation\n        ) = 0;\n\n    // OnDetectPackageBegin - called when the engine begins detecting a package.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop detection.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnDetectPackageBegin)(\n        __in_z LPCWSTR wzPackageId\n        ) = 0;\n\n    // OnDetectRelatedMsiPackage - called when the engine begins detects a related package.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop detection.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnDetectRelatedMsiPackage)(\n        __in_z LPCWSTR wzPackageId,\n        __in_z LPCWSTR wzProductCode,\n        __in BOOL fPerMachine,\n        __in DWORD64 dw64Version,\n        __in BOOTSTRAPPER_RELATED_OPERATION operation\n        ) = 0;\n\n    // OnDetectTargetMsiPackage - called when the engine detects a target MSI package for\n    //                            an MSP package.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop detection.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnDetectTargetMsiPackage)(\n        __in_z LPCWSTR wzPackageId,\n        __in_z LPCWSTR wzProductCode,\n        __in BOOTSTRAPPER_PACKAGE_STATE patchState\n        ) = 0;\n\n    // OnDetectMsiFeature - called when the engine detects a feature in an MSI package.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop detection.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnDetectMsiFeature)(\n        __in_z LPCWSTR wzPackageId,\n        __in_z LPCWSTR wzFeatureId,\n        __in BOOTSTRAPPER_FEATURE_STATE state\n        ) = 0;\n\n    // OnDetectPackageComplete - called after the engine detects a package.\n    //\n    STDMETHOD_(void, OnDetectPackageComplete)(\n        __in_z LPCWSTR wzPackageId,\n        __in HRESULT hrStatus,\n        __in BOOTSTRAPPER_PACKAGE_STATE state\n        ) = 0;\n\n    // OnDetectPackageComplete - called after the engine completes detection.\n    //\n    STDMETHOD_(void, OnDetectComplete)(\n        __in HRESULT hrStatus\n        ) = 0;\n\n    // OnPlanBegin - called when the engine begins planning.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop planning.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnPlanBegin)(\n        __in DWORD cPackages\n        ) = 0;\n\n    // OnPlanRelatedBundle - called when the engine begins planning a related bundle.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop planning.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnPlanRelatedBundle)(\n        __in_z LPCWSTR wzBundleId,\n        __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState\n        ) = 0;\n\n    // OnPlanPackageBegin - called when the engine begins planning a package.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop planning.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnPlanPackageBegin)(\n        __in_z LPCWSTR wzPackageId,\n        __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState\n        ) = 0;\n\n    // OnPlanTargetMsiPackage - called when the engine plans an MSP package\n    //                          to apply to an MSI package.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop planning.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnPlanTargetMsiPackage)(\n        __in_z LPCWSTR wzPackageId,\n        __in_z LPCWSTR wzProductCode,\n        __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState\n        ) = 0;\n\n    // OnPlanMsiFeature - called when the engine plans a feature in an\n    //                    MSI package.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop planning.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnPlanMsiFeature)(\n        __in_z LPCWSTR wzPackageId,\n        __in_z LPCWSTR wzFeatureId,\n        __inout BOOTSTRAPPER_FEATURE_STATE* pRequestedState\n        ) = 0;\n\n    // OnPlanPackageComplete - called after the engine plans a package.\n    //\n    STDMETHOD_(void, OnPlanPackageComplete)(\n        __in_z LPCWSTR wzPackageId,\n        __in HRESULT hrStatus,\n        __in BOOTSTRAPPER_PACKAGE_STATE state,\n        __in BOOTSTRAPPER_REQUEST_STATE requested,\n        __in BOOTSTRAPPER_ACTION_STATE execute,\n        __in BOOTSTRAPPER_ACTION_STATE rollback\n        ) = 0;\n\n    // OnPlanComplete - called when the engine completes planning.\n    //\n    STDMETHOD_(void, OnPlanComplete)(\n        __in HRESULT hrStatus\n        ) = 0;\n\n    // OnApplyBegin - called when the engine begins applying the plan.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop applying.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnApplyBegin)() = 0;\n\n    // OnElevate - called before the engine displays an elevation prompt.\n    //             Will only happen once per execution of the engine.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to abort elevation and stop applying.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnElevate)() = 0;\n\n    // OnProgress - called when the engine makes progress.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop applying.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnProgress)(\n        __in DWORD dwProgressPercentage,\n        __in DWORD dwOverallPercentage\n        ) = 0;\n\n    // OnError - called when the engine encounters an error.\n    //\n    // Return:\n    //  uiFlags is a combination of valid ID* return values appropriate for\n    //          the error.\n    //\n    //  IDNOACTION instructs the engine to pass the error through to default\n    //             handling which usually results in the apply failing.\n    STDMETHOD_(int, OnError)(\n        __in BOOTSTRAPPER_ERROR_TYPE errorType,\n        __in_z_opt LPCWSTR wzPackageId,\n        __in DWORD dwCode,\n        __in_z_opt LPCWSTR wzError,\n        __in DWORD uiFlags,\n        __in DWORD cData,\n        __in_ecount_z_opt(cData) LPCWSTR* rgwzData,\n        __in int nRecommendation\n        ) = 0;\n\n    // OnRegisterBegin - called when the engine registers the bundle.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop applying.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnRegisterBegin)() = 0;\n\n    // OnRegisterComplete - called when the engine registration is\n    //                      complete.\n    //\n    STDMETHOD_(void, OnRegisterComplete)(\n        __in HRESULT hrStatus\n        ) = 0;\n\n    // OnCacheBegin - called when the engine begins caching.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop caching.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnCacheBegin)() = 0;\n\n    // OnCachePackageBegin - called when the engine begins caching\n    //                       a package.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop caching.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnCachePackageBegin)(\n        __in_z LPCWSTR wzPackageId,\n        __in DWORD cCachePayloads,\n        __in DWORD64 dw64PackageCacheSize\n        )  = 0;\n\n    // OnCacheAcquireBegin - called when the engine begins copying or\n    //                       downloading a payload to the working folder.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop caching.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnCacheAcquireBegin)(\n        __in_z_opt LPCWSTR wzPackageOrContainerId,\n        __in_z_opt LPCWSTR wzPayloadId,\n        __in BOOTSTRAPPER_CACHE_OPERATION operation,\n        __in_z LPCWSTR wzSource\n        ) = 0;\n\n    // OnCacheAcquireProgress - called when the engine makes progresss copying\n    //                          or downloading a payload to the working folder.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop caching.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnCacheAcquireProgress)(\n        __in_z_opt LPCWSTR wzPackageOrContainerId,\n        __in_z_opt LPCWSTR wzPayloadId,\n        __in DWORD64 dw64Progress,\n        __in DWORD64 dw64Total,\n        __in DWORD dwOverallPercentage\n        ) = 0;\n\n    // OnResolveSource - called when a payload or container cannot be found locally.\n    //\n    // Parameters:\n    //  wzPayloadId will be NULL when resolving a container.\n    //  wzDownloadSource will be NULL if the container or payload does not provide a DownloadURL.\n    //\n    // Return:\n    //  IDRETRY instructs the engine to try the local source again.\n    //\n    //  IDDOWNLOAD instructs the engine to try the download source.\n    //\n    //  All other return codes result in an error.\n    //\n    // Notes:\n    //  It is expected the BA may call IBurnCore::SetLocalSource() or IBurnCore::SetDownloadSource()\n    //  to update the source location before returning IDRETRY or IDDOWNLOAD.\n    STDMETHOD_(int, OnResolveSource)(\n        __in_z LPCWSTR wzPackageOrContainerId,\n        __in_z_opt LPCWSTR wzPayloadId,\n        __in_z LPCWSTR wzLocalSource,\n        __in_z_opt LPCWSTR wzDownloadSource\n        ) = 0;\n\n    // OnCacheAcquireComplete - called after the engine copied or downloaded\n    //                          a payload to the working folder.\n    //\n    // Return:\n    //  IDRETRY instructs the engine to try the copy or download of the payload again.\n    //\n    //  All other return codes are ignored.\n    STDMETHOD_(int, OnCacheAcquireComplete)(\n        __in_z_opt LPCWSTR wzPackageOrContainerId,\n        __in_z_opt LPCWSTR wzPayloadId,\n        __in HRESULT hrStatus,\n        __in int nRecommendation\n        ) = 0;\n\n    // OnCacheVerifyBegin - called when the engine begins to verify then copy\n    //                      a payload or container to the package cache folder.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop caching.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnCacheVerifyBegin)(\n        __in_z_opt LPCWSTR wzPackageOrContainerId,\n        __in_z_opt LPCWSTR wzPayloadId\n        ) = 0;\n\n    // OnCacheVerifyComplete - called after the engine verifies and copies\n    //                         a payload or container to the package cache folder.\n    //\n    // Return:\n    //  IDRETRY instructs the engine to try the verification of the payload again.\n    //          Ignored if hrStatus is success.\n    //\n    //  IDTRYAGAIN instructs the engine to acquire the payload again. Ignored if\n    //             hrStatus is success.\n    //\n    //  All other return codes are ignored.\n    STDMETHOD_(int, OnCacheVerifyComplete)(\n        __in_z_opt LPCWSTR wzPackageOrContainerId,\n        __in_z_opt LPCWSTR wzPayloadId,\n        __in HRESULT hrStatus,\n        __in int nRecommendation\n        ) = 0;\n\n    // OnCachePackageComplete - called after the engine attempts to copy or download all\n    //                          payloads of a package into the package cache folder.\n    //\n    // Return:\n    //  IDIGNORE instructs the engine to ignore non-vital package failures and continue with the\n    //           caching. Ignored if hrStatus is a success or the package is vital.\n    //\n    //  IDRETRY instructs the engine to try the acquisition and verification of the package\n    //          again. Ignored if hrStatus is a success.\n    //\n    //  All other return codes are ignored.\n    STDMETHOD_(int, OnCachePackageComplete)(\n        __in_z LPCWSTR wzPackageId,\n        __in HRESULT hrStatus,\n        __in int nRecommendation\n        )  = 0;\n\n    // OnCacheComplete - called when the engine caching is complete.\n    //\n    STDMETHOD_(void, OnCacheComplete)(\n        __in HRESULT hrStatus\n        ) = 0;\n\n    // OnExecuteBegin - called when the engine begins executing the plan.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop applying.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnExecuteBegin)(\n        __in DWORD cExecutingPackages\n        ) = 0;\n\n    // OnExecuteBegin - called when the engine begins executing a package.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop applying.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnExecutePackageBegin)(\n        __in_z LPCWSTR wzPackageId,\n        __in BOOL fExecute\n        ) = 0;\n\n    // OnExecutePatchTarget - called when the engine executes one or more patches targeting\n    //                        a product.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop applying.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnExecutePatchTarget)(\n        __in_z LPCWSTR wzPackageId,\n        __in_z LPCWSTR wzTargetProductCode\n        ) = 0;\n\n    // OnExecuteProgress - called when the engine makes progress executing a package.\n    //\n    // Return:\n    //  IDCANCEL instructs the engine to stop applying.\n    //\n    //  IDNOACTION instructs the engine to continue.\n    STDMETHOD_(int, OnExecuteProgress)(\n        __in_z LPCWSTR wzPackageId,\n        __in DWORD dwProgressPercentage,\n        __in DWORD dwOverallPercentage\n        ) = 0;\n\n    // OnExecuteMsiMessage - called when the engine receives an MSI package message.\n    //\n    // Return:\n    //  uiFlags is a combination of valid ID* return values appropriate for\n    //          the message.\n    //\n    //  IDNOACTION instructs the engine to pass the message through to default\n    //             handling which usually results in the execution continuing.\n    STDMETHOD_(int, OnExecuteMsiMessage)(\n        __in_z LPCWSTR wzPackageId,\n        __in INSTALLMESSAGE mt,\n        __in UINT uiFlags,\n        __in_z LPCWSTR wzMessage,\n        __in DWORD cData,\n        __in_ecount_z_opt(cData) LPCWSTR* rgwzData,\n        __in int nRecommendation\n        ) = 0;\n\n    // OnExecuteFilesInUse - called when the engine encounters files in use while\n    //                       executing a package.\n    //\n    // Return:\n    //  IDOK instructs the engine to let the Restart Manager attempt to close the\n    //       applications to avoid a restart.\n    //\n    //  IDCANCEL instructs the engine to abort the execution and start rollback.\n    //\n    //  IDIGNORE instructs the engine to ignore the running applications. A restart will be\n    //           required.\n    //\n    //  IDRETRY instructs the engine to check if the applications are still running again.\n    //\n    //  IDNOACTION is equivalent to ignoring the running applications. A restart will be\n    //             required.\n    STDMETHOD_(int, OnExecuteFilesInUse)(\n        __in_z LPCWSTR wzPackageId,\n        __in DWORD cFiles,\n        __in_ecount_z(cFiles) LPCWSTR* rgwzFiles\n        ) = 0;\n\n    // OnExecutePackageComplete - called when a package execution is complete.\n    //\n    // Parameters:\n    //  restart will indicate whether this package requires a reboot or initiated the reboot already.\n    //\n    // Return:\n    //  IDIGNORE instructs the engine to ignore non-vital package failures and continue with the\n    //           install. Ignored if hrStatus is a success or the package is vital.\n    //\n    //  IDRETRY instructs the engine to try the execution of the package again. Ignored if hrStatus\n    //          is a success.\n    //\n    //  IDRESTART instructs the engine to stop processing the chain and restart. The engine will\n    //            launch again after the machine is restarted.\n    //\n    //  IDSUSPEND instructs the engine to stop processing the chain and suspend the current state.\n    //\n    //  All other return codes are ignored.\n    STDMETHOD_(int, OnExecutePackageComplete)(\n        __in_z LPCWSTR wzPackageId,\n        __in HRESULT hrStatus,\n        __in BOOTSTRAPPER_APPLY_RESTART restart,\n        __in int nRecommendation\n        ) = 0;\n\n    // OnExecuteComplete - called when the engine execution is complete.\n    //\n    STDMETHOD_(void, OnExecuteComplete)(\n        __in HRESULT hrStatus\n        ) = 0;\n\n    // OnUnregisterBegin - called when the engine unregisters the bundle.\n    //\n    STDMETHOD_(void, OnUnregisterBegin)() = 0;\n\n    // OnUnregisterComplete - called when the engine unregistration is complete.\n    //\n    STDMETHOD_(void, OnUnregisterComplete)(\n        __in HRESULT hrStatus\n        ) = 0;\n\n    // OnApplyComplete - called after the plan has been applied.\n    //\n    // Parameters:\n    //  restart will indicate whether any package required a reboot or initiated the reboot already.\n    //\n    // Return:\n    //  IDRESTART instructs the engine to restart. The engine will not launch again after the machine\n    //            is rebooted. Ignored if reboot was already initiated by OnExecutePackageComplete().\n    //\n    //  All other return codes are ignored.\n    STDMETHOD_(int, OnApplyComplete)(\n        __in HRESULT hrStatus,\n        __in BOOTSTRAPPER_APPLY_RESTART restart\n        ) = 0;\n};\n\n\nextern \"C\" typedef HRESULT (WINAPI *PFN_BOOTSTRAPPER_APPLICATION_CREATE)(\n    __in IBootstrapperEngine* pEngine,\n    __in const BOOTSTRAPPER_COMMAND* pCommand,\n    __out IBootstrapperApplication** ppApplication\n    );\n\nextern \"C\" typedef void (WINAPI *PFN_BOOTSTRAPPER_APPLICATION_DESTROY)();\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/IBootstrapperBAFunction.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"IBootstrapperBAFunction.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n#include <windows.h>\n\n#include \"IBootstrapperEngine.h\"\n\ninterface IBootstrapperBAFunction\n{\n    STDMETHOD(OnDetect)() = 0;\n    STDMETHOD(OnDetectComplete)() = 0;\n    STDMETHOD(OnPlan)() = 0;\n    STDMETHOD(OnPlanComplete)() = 0;\n};\n\nextern \"C\" typedef HRESULT (WINAPI *PFN_BOOTSTRAPPER_BA_FUNCTION_CREATE)(\n    __in IBootstrapperEngine* pEngine,\n    __in HMODULE hModule,\n    __out IBootstrapperBAFunction** ppBAFunction\n    );\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/IBootstrapperEngine.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"IBootstrapperEngine.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n// IBoostrapperEngine implemented by engine and used by bootstrapper application.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n#define IDERROR -1\n#define IDNOACTION 0\n\n#define IDDOWNLOAD 101 // Only valid as a return code from OnResolveSource() to instruct the engine to use the download source.\n#define IDRESTART  102\n#define IDSUSPEND  103\n#define IDRELOAD_BOOTSTRAPPER 104\n\nenum BOOTSTRAPPER_ACTION\n{\n    BOOTSTRAPPER_ACTION_UNKNOWN,\n    BOOTSTRAPPER_ACTION_HELP,\n    BOOTSTRAPPER_ACTION_LAYOUT,\n    BOOTSTRAPPER_ACTION_UNINSTALL,\n    BOOTSTRAPPER_ACTION_INSTALL,\n    BOOTSTRAPPER_ACTION_MODIFY,\n    BOOTSTRAPPER_ACTION_REPAIR,\n    BOOTSTRAPPER_ACTION_UPDATE_REPLACE,\n    BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED,\n};\n\nenum BOOTSTRAPPER_ACTION_STATE\n{\n    BOOTSTRAPPER_ACTION_STATE_NONE,\n    BOOTSTRAPPER_ACTION_STATE_UNINSTALL,\n    BOOTSTRAPPER_ACTION_STATE_INSTALL,\n    BOOTSTRAPPER_ACTION_STATE_ADMIN_INSTALL,\n    BOOTSTRAPPER_ACTION_STATE_MODIFY,\n    BOOTSTRAPPER_ACTION_STATE_REPAIR,\n    BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE,\n    BOOTSTRAPPER_ACTION_STATE_MAJOR_UPGRADE,\n    BOOTSTRAPPER_ACTION_STATE_PATCH,\n};\n\nenum BOOTSTRAPPER_PACKAGE_STATE\n{\n    BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN,\n    BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE,\n    BOOTSTRAPPER_PACKAGE_STATE_ABSENT,\n    BOOTSTRAPPER_PACKAGE_STATE_CACHED,\n    BOOTSTRAPPER_PACKAGE_STATE_PRESENT,\n    BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED,\n};\n\nenum BOOTSTRAPPER_REQUEST_STATE\n{\n    BOOTSTRAPPER_REQUEST_STATE_NONE,\n    BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT,\n    BOOTSTRAPPER_REQUEST_STATE_ABSENT,\n    BOOTSTRAPPER_REQUEST_STATE_CACHE,\n    BOOTSTRAPPER_REQUEST_STATE_PRESENT,\n    BOOTSTRAPPER_REQUEST_STATE_REPAIR,\n};\n\nenum BOOTSTRAPPER_FEATURE_STATE\n{\n    BOOTSTRAPPER_FEATURE_STATE_UNKNOWN,\n    BOOTSTRAPPER_FEATURE_STATE_ABSENT,\n    BOOTSTRAPPER_FEATURE_STATE_ADVERTISED,\n    BOOTSTRAPPER_FEATURE_STATE_LOCAL,\n    BOOTSTRAPPER_FEATURE_STATE_SOURCE,\n};\n\nenum BOOTSTRAPPER_FEATURE_ACTION\n{\n    BOOTSTRAPPER_FEATURE_ACTION_NONE,\n    BOOTSTRAPPER_FEATURE_ACTION_ADDLOCAL,\n    BOOTSTRAPPER_FEATURE_ACTION_ADDSOURCE,\n    BOOTSTRAPPER_FEATURE_ACTION_ADDDEFAULT,\n    BOOTSTRAPPER_FEATURE_ACTION_REINSTALL,\n    BOOTSTRAPPER_FEATURE_ACTION_ADVERTISE,\n    BOOTSTRAPPER_FEATURE_ACTION_REMOVE,\n};\n\nenum BOOTSTRAPPER_LOG_LEVEL\n{\n    BOOTSTRAPPER_LOG_LEVEL_NONE,      // turns off report (only valid for XXXSetLevel())\n    BOOTSTRAPPER_LOG_LEVEL_STANDARD,  // written if reporting is on\n    BOOTSTRAPPER_LOG_LEVEL_VERBOSE,   // written only if verbose reporting is on\n    BOOTSTRAPPER_LOG_LEVEL_DEBUG,     // reporting useful when debugging code\n    BOOTSTRAPPER_LOG_LEVEL_ERROR,     // always gets reported, but can never be specified\n};\n\nenum BOOTSTRAPPER_UPDATE_HASH_TYPE\n{\n    BOOTSTRAPPER_UPDATE_HASH_TYPE_NONE,\n    BOOTSTRAPPER_UPDATE_HASH_TYPE_SHA1,\n};\n\n\nDECLARE_INTERFACE_IID_(IBootstrapperEngine, IUnknown, \"6480D616-27A0-44D7-905B-81512C29C2FB\")\n{\n    STDMETHOD(GetPackageCount)(\n        __out DWORD* pcPackages\n        ) = 0;\n\n    STDMETHOD(GetVariableNumeric)(\n        __in_z LPCWSTR wzVariable,\n        __out LONGLONG* pllValue\n        ) = 0;\n\n    STDMETHOD(GetVariableString)(\n        __in_z LPCWSTR wzVariable,\n        __out_ecount_opt(*pcchValue) LPWSTR wzValue,\n        __inout DWORD* pcchValue\n        ) = 0;\n\n    STDMETHOD(GetVariableVersion)(\n        __in_z LPCWSTR wzVariable,\n        __out DWORD64* pqwValue\n        ) = 0;\n\n    STDMETHOD(FormatString)(\n        __in_z LPCWSTR wzIn,\n        __out_ecount_opt(*pcchOut) LPWSTR wzOut,\n        __inout DWORD* pcchOut\n        ) = 0;\n\n    STDMETHOD(EscapeString)(\n        __in_z LPCWSTR wzIn,\n        __out_ecount_opt(*pcchOut) LPWSTR wzOut,\n        __inout DWORD* pcchOut\n        ) = 0;\n\n    STDMETHOD(EvaluateCondition)(\n        __in_z LPCWSTR wzCondition,\n        __out BOOL* pf\n        ) = 0;\n\n    STDMETHOD(Log)(\n        __in BOOTSTRAPPER_LOG_LEVEL level,\n        __in_z LPCWSTR wzMessage\n        ) = 0;\n\n    STDMETHOD(SendEmbeddedError)(\n        __in DWORD dwErrorCode,\n        __in_z_opt LPCWSTR wzMessage,\n        __in DWORD dwUIHint,\n        __out int* pnResult\n        ) = 0;\n\n    STDMETHOD(SendEmbeddedProgress)(\n        __in DWORD dwProgressPercentage,\n        __in DWORD dwOverallProgressPercentage,\n        __out int* pnResult\n        ) = 0;\n\n    STDMETHOD(SetUpdate)(\n        __in_z_opt LPCWSTR wzLocalSource,\n        __in_z_opt LPCWSTR wzDownloadSource,\n        __in DWORD64 qwSize,\n        __in BOOTSTRAPPER_UPDATE_HASH_TYPE hashType,\n        __in_bcount_opt(cbHash) BYTE* rgbHash,\n        __in DWORD cbHash\n        ) = 0;\n\n    STDMETHOD(SetLocalSource)(\n        __in_z LPCWSTR wzPackageOrContainerId,\n        __in_z_opt LPCWSTR wzPayloadId,\n        __in_z LPCWSTR wzPath\n        ) = 0;\n\n    STDMETHOD(SetDownloadSource)(\n        __in_z LPCWSTR wzPackageOrContainerId,\n        __in_z_opt LPCWSTR wzPayloadId,\n        __in_z LPCWSTR wzUrl,\n        __in_z_opt LPWSTR wzUser,\n        __in_z_opt LPWSTR wzPassword\n        ) = 0;\n\n    STDMETHOD(SetVariableNumeric)(\n        __in_z LPCWSTR wzVariable,\n        __in LONGLONG llValue\n        ) = 0;\n\n    STDMETHOD(SetVariableString)(\n        __in_z LPCWSTR wzVariable,\n        __in_z_opt LPCWSTR wzValue\n        ) = 0;\n\n    STDMETHOD(SetVariableVersion)(\n        __in_z LPCWSTR wzVariable,\n        __in DWORD64 qwValue\n        ) = 0;\n\n    STDMETHOD(CloseSplashScreen)() = 0;\n\n    STDMETHOD(Detect)() = 0;\n\n    STDMETHOD(Plan)(\n        __in BOOTSTRAPPER_ACTION action\n        ) = 0;\n\n    STDMETHOD(Elevate)(\n        __in_opt HWND hwndParent\n        ) = 0;\n\n    STDMETHOD(Apply)(\n        __in_opt HWND hwndParent\n        ) = 0;\n\n    STDMETHOD(Quit)(\n        __in DWORD dwExitCode\n        ) = 0;\n};\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/aclutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"aclutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Access Control List helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#include <aclapi.h>\n#include <sddl.h>\n\n#define ReleaseSid(x) if (x) { AclFreeSid(x); }\n#define ReleaseNullSid(x) if (x) { AclFreeSid(x); x = NULL; }\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// structs\nstruct ACL_ACCESS\n{\n    BOOL fDenyAccess;\n    DWORD dwAccessMask;\n\n    // TODO: consider using a union\n    LPCWSTR pwzAccountName;   // NOTE: the last three items in this structure are ignored if this is not NULL\n\n    SID_IDENTIFIER_AUTHORITY sia;  // used if pwzAccountName is NULL\n    BYTE nSubAuthorityCount;\n    DWORD nSubAuthority[8];\n};\n\nstruct ACL_ACE\n{\n    DWORD dwFlags;\n    DWORD dwMask;\n    PSID psid;\n};\n\n\n// functions\nHRESULT DAPI AclCheckAccess(\n    __in HANDLE hToken, \n    __in ACL_ACCESS* paa\n    );\nHRESULT DAPI AclCheckAdministratorAccess(\n    __in HANDLE hToken\n    );\nHRESULT DAPI AclCheckLocalSystemAccess(\n    __in HANDLE hToken\n    );\n\nHRESULT DAPI AclGetWellKnownSid(\n    __in WELL_KNOWN_SID_TYPE wkst,\n    __deref_out PSID* ppsid\n    );\nHRESULT DAPI AclGetAccountSid(\n    __in_opt LPCWSTR wzSystem,\n    __in_z LPCWSTR wzAccount,\n    __deref_out PSID* ppsid\n    );\nHRESULT DAPI AclGetAccountSidString(\n    __in_z LPCWSTR wzSystem,\n    __in_z LPCWSTR wzAccount,\n    __deref_out_z LPWSTR* ppwzSid\n    );\n\nHRESULT DAPI AclCreateDacl(\n    __in_ecount(cDeny) ACL_ACE rgaaDeny[],\n    __in DWORD cDeny,\n    __in_ecount(cAllow) ACL_ACE rgaaAllow[],\n    __in DWORD cAllow,\n    __deref_out ACL** ppAcl\n    );\nHRESULT DAPI AclAddToDacl(\n    __in ACL* pAcl,\n    __in_ecount_opt(cDeny) const ACL_ACE rgaaDeny[],\n    __in DWORD cDeny,\n    __in_ecount_opt(cAllow) const ACL_ACE rgaaAllow[],\n    __in DWORD cAllow,\n    __deref_out ACL** ppAclNew\n    );\nHRESULT DAPI AclMergeDacls(\n    __in const ACL* pAcl1,\n    __in const ACL* pAcl2,\n    __deref_out ACL** ppAclNew\n    );\nHRESULT DAPI AclCreateDaclOld(\n    __in_ecount(cAclAccesses) ACL_ACCESS* paa,\n    __in DWORD cAclAccesses,\n    __deref_out ACL** ppAcl\n    );\nHRESULT DAPI AclCreateSecurityDescriptor(\n    __in_ecount(cAclAccesses) ACL_ACCESS* paa,\n    __in DWORD cAclAccesses,\n    __deref_out SECURITY_DESCRIPTOR** ppsd\n    );\nHRESULT DAPI AclCreateSecurityDescriptorFromDacl(\n    __in ACL* pACL,\n    __deref_out SECURITY_DESCRIPTOR** ppsd\n    );\nHRESULT __cdecl AclCreateSecurityDescriptorFromString(\n    __deref_out SECURITY_DESCRIPTOR** ppsd,\n    __in_z __format_string LPCWSTR wzSddlFormat,\n    ...\n    );\nHRESULT DAPI AclDuplicateSecurityDescriptor(\n    __in SECURITY_DESCRIPTOR* psd,\n    __deref_out SECURITY_DESCRIPTOR** ppsd\n    );\nHRESULT DAPI AclGetSecurityDescriptor(\n    __in_z LPCWSTR wzObject,\n    __in SE_OBJECT_TYPE sot,\n    __in SECURITY_INFORMATION securityInformation,\n    __deref_out SECURITY_DESCRIPTOR** ppsd\n    );\nHRESULT DAPI AclSetSecurityWithRetry(\n    __in_z LPCWSTR wzObject,\n    __in SE_OBJECT_TYPE sot,\n    __in SECURITY_INFORMATION securityInformation,\n    __in_opt PSID psidOwner,\n    __in_opt PSID psidGroup,\n    __in_opt PACL pDacl,\n    __in_opt PACL pSacl,\n    __in DWORD cRetry,\n    __in DWORD dwWaitMilliseconds\n    );\n\nHRESULT DAPI AclFreeSid(\n    __in PSID psid\n    );\nHRESULT DAPI AclFreeDacl(\n    __in ACL* pACL\n    );\nHRESULT DAPI AclFreeSecurityDescriptor(\n    __in SECURITY_DESCRIPTOR* psd\n    );\n\nHRESULT DAPI AclAddAdminToSecurityDescriptor(\n    __in SECURITY_DESCRIPTOR* pSecurity,\n    __deref_out SECURITY_DESCRIPTOR** ppSecurityNew\n    );\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/apuputil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"apuputil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for Application Update helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ReleaseApupChain(p) if (p) { ApupFreeChain(p); p = NULL; }\n#define ReleaseNullApupChain(p) if (p) { ApupFreeChain(p); p = NULL; }\n\n\nconst LPCWSTR APPLICATION_SYNDICATION_NAMESPACE = L\"http://appsyndication.org/2006/appsyn\";\n\nenum APUP_HASH_ALGORITHM\n{\n    APUP_HASH_ALGORITHM_UNKNOWN,\n    APUP_HASH_ALGORITHM_MD5,\n    APUP_HASH_ALGORITHM_SHA1,\n    APUP_HASH_ALGORITHM_SHA256,\n};\n\n\nstruct APPLICATION_UPDATE_ENCLOSURE\n{\n    LPWSTR wzUrl;\n    LPWSTR wzLocalName;\n    DWORD64 dw64Size;\n\n    BYTE* rgbDigest;\n    DWORD cbDigest;\n    APUP_HASH_ALGORITHM digestAlgorithm;\n\n    BOOL fInstaller;\n};\n\n\nstruct APPLICATION_UPDATE_ENTRY\n{\n    LPWSTR wzApplicationId;\n    LPWSTR wzApplicationType;\n\n    LPWSTR wzUpgradeId;\n    BOOL fUpgradeExclusive;\n    DWORD64 dw64Version;\n    DWORD64 dw64UpgradeVersion;\n\n    DWORD64 dw64TotalSize;\n\n    DWORD cEnclosures;\n    APPLICATION_UPDATE_ENCLOSURE* rgEnclosures;\n};\n\n\nstruct APPLICATION_UPDATE_CHAIN\n{\n    LPWSTR wzDefaultApplicationId;\n    LPWSTR wzDefaultApplicationType;\n\n    DWORD cEntries;\n    APPLICATION_UPDATE_ENTRY* rgEntries;\n};\n\n\nHRESULT DAPI ApupAllocChainFromAtom(\n    __in ATOM_FEED* pFeed,\n    __out APPLICATION_UPDATE_CHAIN** ppChain\n    );\n\nHRESULT DAPI ApupFilterChain(\n    __in APPLICATION_UPDATE_CHAIN* pChain,\n    __in DWORD64 dw64Version,\n    __out APPLICATION_UPDATE_CHAIN** ppFilteredChain\n    );\n\nvoid DAPI ApupFreeChain(\n    __in APPLICATION_UPDATE_CHAIN* pChain\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/atomutil.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"atomutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    ATOM helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ReleaseAtomFeed(p) if (p) { AtomFreeFeed(p); }\n#define ReleaseNullAtomFeed(p) if (p) { AtomFreeFeed(p); p = NULL; }\n\n\nstruct ATOM_UNKNOWN_ATTRIBUTE\n{\n    LPWSTR wzNamespace;\n    LPWSTR wzAttribute;\n    LPWSTR wzValue;\n\n    ATOM_UNKNOWN_ATTRIBUTE* pNext;\n};\n\nstruct ATOM_UNKNOWN_ELEMENT\n{\n    LPWSTR wzNamespace;\n    LPWSTR wzElement;\n    LPWSTR wzValue;\n\n    ATOM_UNKNOWN_ATTRIBUTE* pAttributes;\n    ATOM_UNKNOWN_ELEMENT* pNext;\n};\n\nstruct ATOM_LINK\n{\n    LPWSTR wzRel;\n    LPWSTR wzTitle;\n    LPWSTR wzType;\n    LPWSTR wzUrl;\n    LPWSTR wzValue;\n    DWORD64 dw64Length;\n\n    ATOM_UNKNOWN_ATTRIBUTE* pUnknownAttributes;\n    ATOM_UNKNOWN_ELEMENT* pUnknownElements;\n};\n\nstruct ATOM_CONTENT\n{\n    LPWSTR wzType;\n    LPWSTR wzUrl;\n    LPWSTR wzValue;\n\n    ATOM_UNKNOWN_ELEMENT* pUnknownElements;\n};\n\nstruct ATOM_AUTHOR\n{\n    LPWSTR wzName;\n    LPWSTR wzEmail;\n    LPWSTR wzUrl;\n};\n\nstruct ATOM_CATEGORY\n{\n    LPWSTR wzLabel;\n    LPWSTR wzScheme;\n    LPWSTR wzTerm;\n\n    ATOM_UNKNOWN_ELEMENT* pUnknownElements;\n};\n\nstruct ATOM_ENTRY\n{\n    LPWSTR wzId;\n    LPWSTR wzSummary;\n    LPWSTR wzTitle;\n    FILETIME ftPublished;\n    FILETIME ftUpdated;\n\n    ATOM_CONTENT* pContent;\n\n    DWORD cAuthors;\n    ATOM_AUTHOR* rgAuthors;\n\n    DWORD cCategories;\n    ATOM_CATEGORY* rgCategories;\n\n    DWORD cLinks;\n    ATOM_LINK* rgLinks;\n\n    IXMLDOMNode* pixn;\n    ATOM_UNKNOWN_ELEMENT* pUnknownElements;\n};\n\nstruct ATOM_FEED\n{\n    LPWSTR wzGenerator;\n    LPWSTR wzIcon;\n    LPWSTR wzId;\n    LPWSTR wzLogo;\n    LPWSTR wzSubtitle;\n    LPWSTR wzTitle;\n    FILETIME ftUpdated;\n\n    DWORD cAuthors;\n    ATOM_AUTHOR* rgAuthors;\n\n    DWORD cCategories;\n    ATOM_CATEGORY* rgCategories;\n\n    DWORD cEntries;\n    ATOM_ENTRY* rgEntries;\n\n    DWORD cLinks;\n    ATOM_LINK* rgLinks;\n\n    IXMLDOMNode* pixn;\n    ATOM_UNKNOWN_ELEMENT* pUnknownElements;\n};\n\nHRESULT DAPI AtomInitialize(\n    );\n\nvoid DAPI AtomUninitialize(\n    );\n\nHRESULT DAPI AtomParseFromString(\n    __in_z LPCWSTR wzAtomString,\n    __out ATOM_FEED **ppFeed\n    );\n\nHRESULT DAPI AtomParseFromFile(\n    __in_z LPCWSTR wzAtomFile,\n    __out ATOM_FEED **ppFeed\n    );\n\nHRESULT DAPI AtomParseFromDocument(\n    __in IXMLDOMDocument* pixdDocument,\n    __out ATOM_FEED **ppFeed\n    );\n\nvoid DAPI AtomFreeFeed(\n    __in_xcount(pFeed->cItems) ATOM_FEED *pFEED\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/balcondition.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"balcondition.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//\n// <summary>\n// Bootstrapper Application Layer condition utility.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct _BAL_CONDITION\n{\n    LPWSTR sczCondition;\n    LPWSTR sczMessage;\n} BAL_CONDITION;\n\n\ntypedef struct _BAL_CONDITIONS\n{\n    BAL_CONDITION* rgConditions;\n    DWORD cConditions;\n} BAL_CONDITIONS;\n\n\n/*******************************************************************\n BalConditionsParseFromXml - loads the conditions from the UX manifest.\n\n********************************************************************/\nDAPI_(HRESULT) BalConditionsParseFromXml(\n    __in BAL_CONDITIONS* pConditions,\n    __in IXMLDOMDocument* pixdManifest,\n    __in_opt WIX_LOCALIZATION* pWixLoc\n    );\n\n\n/*******************************************************************\n BalConditionEvaluate - evaluates condition against the provided IBurnCore.\n\n NOTE: psczMessage is optional.\n********************************************************************/\nDAPI_(HRESULT) BalConditionEvaluate(\n    __in BAL_CONDITION* pCondition,\n    __in IBootstrapperEngine* pEngine,\n    __out BOOL* pfResult,\n    __out_z_opt LPWSTR* psczMessage\n    );\n\n\n/*******************************************************************\n BalConditionsUninitialize - uninitializes any conditions previously loaded.\n\n********************************************************************/\nDAPI_(void) BalConditionsUninitialize(\n    __in BAL_CONDITIONS* pConditions\n    );\n\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/balinfo.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"balinfo.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//\n// <summary>\n// Bootstrapper Application Layer package utility.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nenum BAL_INFO_PACKAGE_TYPE\n{\n    BAL_INFO_PACKAGE_TYPE_UNKNOWN,\n    BAL_INFO_PACKAGE_TYPE_EXE,\n    BAL_INFO_PACKAGE_TYPE_MSI,\n    BAL_INFO_PACKAGE_TYPE_MSP,\n    BAL_INFO_PACKAGE_TYPE_MSU,\n    BAL_INFO_PACKAGE_TYPE_BUNDLE_UPGRADE,\n    BAL_INFO_PACKAGE_TYPE_BUNDLE_ADDON,\n    BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH,\n};\n\n\ntypedef struct _BAL_INFO_PACKAGE\n{\n    LPWSTR sczId;\n    LPWSTR sczDisplayName;\n    LPWSTR sczDescription;\n    BAL_INFO_PACKAGE_TYPE type;\n    BOOL fPermanent;\n    BOOL fVital;\n    BOOL fDisplayInternalUI;\n} BAL_INFO_PACKAGE;\n\n\ntypedef struct _BAL_INFO_PACKAGES\n{\n    BAL_INFO_PACKAGE* rgPackages;\n    DWORD cPackages;\n} BAL_INFO_PACKAGES;\n\n\ntypedef struct _BAL_INFO_BUNDLE\n{\n    BOOL fPerMachine;\n    LPWSTR sczName;\n    LPWSTR sczLogVariable;\n    BAL_INFO_PACKAGES packages;\n} BAL_INFO_BUNDLE;\n\n\n/*******************************************************************\n BalInfoParseFromXml - loads the bundle and package info from the UX\n                       manifest.\n\n********************************************************************/\nDAPI_(HRESULT) BalInfoParseFromXml(\n    __in BAL_INFO_BUNDLE* pBundle,\n    __in IXMLDOMDocument* pixdManifest\n    );\n\n\n/*******************************************************************\n BalInfoAddRelatedBundleAsPackage - adds a related bundle as a package.\n\n ********************************************************************/\nDAPI_(HRESULT) BalInfoAddRelatedBundleAsPackage(\n    __in BAL_INFO_PACKAGES* pPackages,\n    __in LPCWSTR wzId,\n    __in BOOTSTRAPPER_RELATION_TYPE relationType,\n    __in BOOL fPerMachine\n    );\n\n\n/*******************************************************************\n BalInfoFindPackageById - finds a package by its id.\n\n ********************************************************************/\nDAPI_(HRESULT) BalInfoFindPackageById(\n    __in BAL_INFO_PACKAGES* pPackages,\n    __in LPCWSTR wzId,\n    __out BAL_INFO_PACKAGE** ppPackage\n    );\n\n\n/*******************************************************************\n BalInfoUninitialize - uninitializes any info previously loaded.\n\n********************************************************************/\nDAPI_(void) BalInfoUninitialize(\n    __in BAL_INFO_BUNDLE* pBundle\n    );\n\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/balretry.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"balretry.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//\n// <summary>\n// Bootstrapper Application Layer retry utility.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nenum BALRETRY_TYPE\n{\n    BALRETRY_TYPE_CACHE,\n    BALRETRY_TYPE_EXECUTE,\n};\n\n/*******************************************************************\n BalRetryInitialize - initialize the retry count and timeout between\n                      retries (in milliseconds).\n********************************************************************/\nDAPI_(void) BalRetryInitialize(\n    __in DWORD dwMaxRetries,\n    __in DWORD dwTimeout\n    );\n\n/*******************************************************************\n BalRetryUninitialize - call to cleanup any memory allocated during\n                        use of the retry utility.\n********************************************************************/\nDAPI_(void) BalRetryUninitialize();\n\n/*******************************************************************\n BalRetryStartPackage - call when a package begins to be modified. If\n                        the package is being retried, the function will\n                        wait the specified timeout.\n********************************************************************/\nDAPI_(void) BalRetryStartPackage(\n    __in BALRETRY_TYPE type,\n    __in_z_opt LPCWSTR wzPackageId,\n    __in_z_opt LPCWSTR wzPayloadId\n    );\n\n/*******************************************************************\n BalRetryErrorOccured - call when an error occurs for the retry utility\n                        to consider.\n********************************************************************/\nDAPI_(void) BalRetryErrorOccurred(\n    __in_z_opt LPCWSTR wzPackageId,\n    __in DWORD dwError\n    );\n\n/*******************************************************************\n BalRetryEndPackage - returns IDRETRY is a retry is recommended or \n                      IDNOACTION if a retry is not recommended.\n********************************************************************/\nDAPI_(int) BalRetryEndPackage(\n    __in BALRETRY_TYPE type,\n    __in_z_opt LPCWSTR wzPackageId,\n    __in_z_opt LPCWSTR wzPayloadId,\n    __in HRESULT hrError\n    );\n\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/balutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"balutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//\n// <summary>\n// Burn utility library.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#include \"dutil.h\"\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define BalExitOnFailure(x, f) if (FAILED(x)) { BalLogError(x, f); ExitTrace(x, f); goto LExit; }\n#define BalExitOnFailure1(x, f, s) if (FAILED(x)) { BalLogError(x, f, s); ExitTrace1(x, f, s); goto LExit; }\n#define BalExitOnFailure2(x, f, s, t) if (FAILED(x)) { BalLogError(x, f, s, t); ExitTrace2(x, f, s, t); goto LExit; }\n#define BalExitOnFailure3(x, f, s, t, u) if (FAILED(x)) { BalLogError(x, f, s, t, u); ExitTrace3(x, f, s, t, u); goto LExit; }\n\n#define BalExitOnRootFailure(x, f) if (FAILED(x)) { BalLogError(x, f); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace(x, f); goto LExit; }\n#define BalExitOnRootFailure1(x, f, s) if (FAILED(x)) { BalLogError(x, f, s); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace1(x, f, s); goto LExit; }\n#define BalExitOnRootFailure2(x, f, s, t) if (FAILED(x)) { BalLogError(x, f, s, t); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace2(x, f, s, t); goto LExit; }\n#define BalExitOnRootFailure3(x, f, s, t, u) if (FAILED(x)) { BalLogError(x, f, s, t, u); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace3(x, f, s, t, u); goto LExit; }\n\n#define BalExitOnNullWithLastError(p, x, f) if (NULL == p) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } BalLogError(x, f); ExitTrace(x, f); goto LExit; }\n#define BalExitOnNullWithLastError1(p, x, f, s) if (NULL == p) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } BalLogError(x, f, s); ExitTrace1(x, f, s); goto LExit; }\n\n\n/*******************************************************************\n BalInitialize - remembers the engine interface to enable logging and\n                 other functions.\n\n********************************************************************/\nDAPI_(void) BalInitialize(\n    __in IBootstrapperEngine* pEngine\n    );\n\n/*******************************************************************\n BalUninitialize - cleans up utility layer internals.\n\n********************************************************************/\nDAPI_(void) BalUninitialize();\n\n/*******************************************************************\n BalManifestLoad - loads the Application manifest into an XML document.\n\n********************************************************************/\nDAPI_(HRESULT) BalManifestLoad(\n    __in HMODULE hUXModule,\n    __out IXMLDOMDocument** ppixdManifest\n    );\n\n/*******************************************************************\nBalFormatString - formats a string using variables in the engine.\n\n Note: Use StrFree() to release psczOut.\n********************************************************************/\nDAPI_(HRESULT) BalFormatString(\n    __in_z LPCWSTR wzFormat,\n    __inout LPWSTR* psczOut\n    );\n\n/*******************************************************************\nBalGetNumericVariable - gets a number from a variable in the engine.\n\n Note: Returns E_NOTFOUND if variable does not exist.\n********************************************************************/\nDAPI_(HRESULT) BalGetNumericVariable(\n    __in_z LPCWSTR wzVariable,\n    __out LONGLONG* pllValue\n    );\n\n/*******************************************************************\nBalStringVariableExists - checks if a string variable exists in the engine.\n\n********************************************************************/\nDAPI_(BOOL) BalStringVariableExists(\n    __in_z LPCWSTR wzVariable\n    );\n\n/*******************************************************************\nBalGetStringVariable - gets a string from a variable in the engine.\n\n Note: Use StrFree() to release psczValue.\n********************************************************************/\nDAPI_(HRESULT) BalGetStringVariable(\n    __in_z LPCWSTR wzVariable,\n    __inout LPWSTR* psczValue\n    );\n\n/*******************************************************************\n BalLog - logs a message with the engine.\n\n********************************************************************/\nDAPIV_(HRESULT) BalLog(\n    __in BOOTSTRAPPER_LOG_LEVEL level,\n    __in_z __format_string LPCSTR szFormat,\n    ...\n    );\n\n/*******************************************************************\n BalLogError - logs an error message with the engine.\n\n********************************************************************/\nDAPIV_(HRESULT) BalLogError(\n    __in HRESULT hr,\n    __in_z __format_string LPCSTR szFormat,\n    ...\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/buffutil.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"buffutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//\n// <summary>\n//    Binary serialization helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n// macro definitions\n\n#define ReleaseBuffer ReleaseMem\n#define ReleaseNullBuffer ReleaseNullMem\n#define BuffFree MemFree\n\n\n// function declarations\n\nHRESULT BuffReadNumber(\n    __in_bcount(cbBuffer) const BYTE* pbBuffer,\n    __in SIZE_T cbBuffer,\n    __inout SIZE_T* piBuffer,\n    __out DWORD* pdw\n    );\nHRESULT BuffReadNumber64(\n    __in_bcount(cbBuffer) const BYTE* pbBuffer,\n    __in SIZE_T cbBuffer,\n    __inout SIZE_T* piBuffer,\n    __out DWORD64* pdw64\n    );\nHRESULT BuffReadString(\n    __in_bcount(cbBuffer) const BYTE* pbBuffer,\n    __in SIZE_T cbBuffer,\n    __inout SIZE_T* piBuffer,\n    __deref_out_z LPWSTR* pscz\n    );\nHRESULT BuffReadStringAnsi(\n    __in_bcount(cbBuffer) const BYTE* pbBuffer,\n    __in SIZE_T cbBuffer,\n    __inout SIZE_T* piBuffer,\n    __deref_out_z LPSTR* pscz\n    );\nHRESULT BuffReadStream(\n    __in_bcount(cbBuffer) const BYTE* pbBuffer,\n    __in SIZE_T cbBuffer,\n    __inout SIZE_T* piBuffer,\n    __deref_out_bcount(*pcbStream) BYTE** ppbStream,\n    __out SIZE_T* pcbStream\n    );\n\nHRESULT BuffWriteNumber(\n    __deref_out_bcount(*piBuffer) BYTE** ppbBuffer,\n    __inout SIZE_T* piBuffer,\n    __in DWORD dw\n    );\nHRESULT BuffWriteNumber64(\n    __deref_out_bcount(*piBuffer) BYTE** ppbBuffer,\n    __inout SIZE_T* piBuffer,\n    __in DWORD64 dw64\n    );\nHRESULT BuffWriteString(\n    __deref_out_bcount(*piBuffer) BYTE** ppbBuffer,\n    __inout SIZE_T* piBuffer,\n    __in_z_opt LPCWSTR scz\n    );\nHRESULT BuffWriteStringAnsi(\n    __deref_out_bcount(*piBuffer) BYTE** ppbBuffer,\n    __inout SIZE_T* piBuffer,\n    __in_z_opt LPCSTR scz\n    );\nHRESULT BuffWriteStream(\n    __deref_out_bcount(*piBuffer) BYTE** ppbBuffer,\n    __inout SIZE_T* piBuffer,\n    __in_bcount(cbStream) const BYTE* pbStream,\n    __in SIZE_T cbStream\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/cabcutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"cabcutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for cabinet creation helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#include <fci.h>\n#include <fcntl.h>\n#include <msi.h>\n\n// Callback from PFNFCIGETNEXTCABINET CabCGetNextCabinet method\n// First argument is the name of splitting cabinet without extension e.g. \"cab1\"\n// Second argument is name of the new cabinet that would be formed by splitting e.g. \"cab1b.cab\"\n// Third argument is the file token of the first file present in the splitting cabinet\ntypedef void (__stdcall * FileSplitCabNamesCallback)(LPWSTR, LPWSTR, LPWSTR);\n\n#define CAB_MAX_SIZE 0x7FFFFFFF   // (see KB: Q174866)\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern const int CABC_HANDLE_BYTES;\n\n// time vs. space trade-off\nenum COMPRESSION_TYPE \n{ \n    COMPRESSION_TYPE_NONE, // fastest\n    COMPRESSION_TYPE_LOW, \n    COMPRESSION_TYPE_MEDIUM,\n    COMPRESSION_TYPE_HIGH, // smallest\n    COMPRESSION_TYPE_MSZIP\n};\n\n// functions\nHRESULT DAPI CabCBegin(\n    __in_z LPCWSTR wzCab,\n    __in_z LPCWSTR wzCabDir,\n    __in DWORD dwMaxFiles,\n    __in DWORD dwMaxSize,\n    __in DWORD dwMaxThresh,\n    __in COMPRESSION_TYPE ct,\n    __out_bcount(CABC_HANDLE_BYTES) HANDLE *phContext\n    );\nHRESULT DAPI CabCNextCab(\n    __in_bcount(CABC_HANDLE_BYTES) HANDLE hContext\n    );\nHRESULT DAPI CabCAddFile(\n    __in_z LPCWSTR wzFile,\n    __in_z_opt LPCWSTR wzToken,\n    __in_opt PMSIFILEHASHINFO pmfHash,\n    __in_bcount(CABC_HANDLE_BYTES) HANDLE hContext\n    );\nHRESULT DAPI CabCFinish(\n    __in_bcount(CABC_HANDLE_BYTES) HANDLE hContext,\n    __in_opt FileSplitCabNamesCallback fileSplitCabNamesCallback\n    );\nvoid DAPI CabCCancel(\n    __in_bcount(CABC_HANDLE_BYTES) HANDLE hContext\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/cabutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"cabutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for cabinet decompression helper functions\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#include <fdi.h>\n#include <sys\\stat.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// structs\n\n\n// callback function prototypes\ntypedef HRESULT (*CAB_CALLBACK_OPEN_FILE)(LPCWSTR wzFile, INT_PTR* ppFile);\ntypedef HRESULT (*CAB_CALLBACK_READ_FILE)(INT_PTR pFile, LPVOID pvData, DWORD cbData, DWORD* pcbRead);\ntypedef HRESULT (*CAB_CALLBACK_WRITE_FILE)(INT_PTR pFile, LPVOID pvData, DWORD cbData, DWORD* pcbRead);\ntypedef LONG (*CAB_CALLBACK_SEEK_FILE)(INT_PTR pFile, DWORD dwMove, DWORD dwMoveMethod);\ntypedef HRESULT (*CAB_CALLBACK_CLOSE_FILE)(INT_PTR pFile);\n\ntypedef HRESULT (*CAB_CALLBACK_BEGIN_FILE)(LPCWSTR wzFileId, FILETIME* pftFileTime, DWORD cbFileSize, LPVOID pvContext, INT_PTR* ppFile);\ntypedef HRESULT (*CAB_CALLBACK_END_FILE)(LPCWSTR wzFileId, LPVOID pvContext, INT_PTR pFile);\ntypedef HRESULT (*CAB_CALLBACK_PROGRESS)(BOOL fBeginFile, LPCWSTR wzFileId, LPVOID pvContext);\n\n// function type with calling convention of __stdcall that .NET 1.1 understands only\n// .NET 2.0 will not need this\ntypedef INT_PTR (FAR __stdcall *STDCALL_PFNFDINOTIFY)(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin);\n\n\n// functions\nHRESULT DAPI CabInitialize(\n    __in BOOL fDelayLoad\n    );\nvoid DAPI CabUninitialize(\n    );\n\nHRESULT DAPI CabExtract(\n    __in_z LPCWSTR wzCabinet,\n    __in_z LPCWSTR wzExtractFile,\n    __in_z LPCWSTR wzExtractDir,\n    __in_opt CAB_CALLBACK_PROGRESS pfnProgress,\n    __in_opt LPVOID pvContext,\n    __in DWORD64 dw64EmbeddedOffset\n    );\n\nHRESULT DAPI CabEnumerate(\n    __in_z LPCWSTR wzCabinet,\n    __in_z LPCWSTR wzEnumerateFile,\n    __in STDCALL_PFNFDINOTIFY pfnNotify,\n    __in DWORD64 dw64EmbeddedOffset\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/certutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"certutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Certificate helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#define ReleaseCertStore(p) if (p) { ::CertCloseStore(p, 0); p = NULL; }\n#define ReleaseCertContext(p) if (p) { ::CertFreeCertificateContext(p); p = NULL; }\n#define ReleaseCertChain(p) if (p) { ::CertFreeCertificateChain(p); p = NULL; }\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nHRESULT DAPI CertReadProperty(\n    __in PCCERT_CONTEXT pCertContext,\n    __in DWORD dwProperty,\n    __out_bcount(*pcbValue) LPVOID pvValue,\n    __out_opt DWORD* pcbValue\n    );\n\nHRESULT DAPI CertGetAuthenticodeSigningTimestamp(\n    __in CMSG_SIGNER_INFO* pSignerInfo,\n    __out FILETIME* pft\n    );\n\nHRESULT DAPI GetCryptProvFromCert(\n      __in_opt HWND hwnd,\n      __in PCCERT_CONTEXT pCert,\n      __out HCRYPTPROV *phCryptProv,\n      __out DWORD *pdwKeySpec,\n      __in BOOL *pfDidCryptAcquire,\n      __deref_opt_out LPWSTR *ppwszTmpContainer,\n      __deref_opt_out LPWSTR *ppwszProviderName,\n      __out DWORD *pdwProviderType\n      );\n\nHRESULT DAPI FreeCryptProvFromCert(\n    __in BOOL fAcquired,\n    __in HCRYPTPROV hProv,\n    __in_opt LPWSTR pwszCapiProvider,\n    __in DWORD dwProviderType,\n    __in_opt LPWSTR pwszTmpContainer\n    );\n\nHRESULT DAPI GetProvSecurityDesc(\n      __in HCRYPTPROV hProv,\n      __deref_out SECURITY_DESCRIPTOR** pSecurity\n      );\n\nHRESULT DAPI SetProvSecurityDesc(\n    __in HCRYPTPROV hProv,\n    __in SECURITY_DESCRIPTOR* pSecurity\n    );\n\nBOOL DAPI CertHasPrivateKey(\n    __in PCCERT_CONTEXT pCertContext,\n    __out_opt DWORD* pdwKeySpec\n    );\n\nHRESULT DAPI CertInstallSingleCertificate(\n    __in HCERTSTORE hStore,\n    __in PCCERT_CONTEXT pCertContext,\n    __in LPCWSTR wzName\n    );\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/conutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"conutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Console helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ConsoleExitOnFailure(x, c, f) if (FAILED(x)) { ConsoleWriteError(x, c, f); ExitTrace(x, f); goto LExit; }\n#define ConsoleExitOnFailure1(x, c, f, s) if (FAILED(x)) { ConsoleWriteError(x, c, f, s, NULL); ExitTrace1(x, f, s); goto LExit; }\n#define ConsoleExitOnFailure2(x, c, f, s, t) if (FAILED(x)) { ConsoleWriteError(x, c, f, s, t); ExitTrace2(x, f, s, t); goto LExit; }\n#define ConsoleExitOnFailure3(x, c, f, s, t, u) if (FAILED(x)) { ConsoleWriteError(x, c, f, s, t, u); ExitTrace3(x, f, s, t, u); goto LExit; }\n\n#define ConsoleExitOnLastError(x, c, f) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ConsoleWriteError(x, c, f); ExitTrace(x, f); goto LExit; } }\n#define ConsoleExitOnLastError1(x, c, f, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ConsoleWriteError(x, c, f, s, NULL); ExitTrace1(x, f, s); goto LExit; } }\n#define ConsoleExitOnLastError2(x, c, f, s, t) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ConsoleWriteError(x, c, f, s, t); ExitTrace2(x, f, s, t); goto LExit; } }\n#define ConsoleExitOnLastError3(x, c, f, s, t, u) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ConsoleWriteError(x, c, f, s, t, u); ExitTrace3(x, f, s, t, u); goto LExit; } }\n\n#define ConsoleExitOnNull(p, x, e, c, f) if (NULL == p) { x = e; ConsoleWriteError(x, c, f); ExitTrace(x, f); goto LExit; }\n#define ConsoleExitOnNull1(p, x, e, c, f, s) if (NULL == p) { x = e; ConsoleWriteError(x, c, f, s, NULL); ExitTrace1(x, f, s); goto LExit; }\n#define ConsoleExitOnNull2(p, x, e, c, f, s, t) if (NULL == p) { x = e; ConsoleWriteError(x, c, f, s, t); ExitTrace2(x, f, s, t); goto LExit; }\n#define ConsoleExitOnNull3(p, x, e, c, f, s, t, u) if (NULL == p) { x = e; ConsoleWriteError(x, c, f, s, t, u); ExitTrace2(x, f, s, t, u); goto LExit; }\n\n\n// the following macros need to go away\n#define ConsoleTrace(l, f) { ConsoleWriteLine(CONSOLE_COLOR_NORMAL, f); Trace(l, f); }\n#define ConsoleTrace1(l, f, s) { ConsoleWriteLine(CONSOLE_COLOR_NORMAL, f, s); Trace1(l, f, s); }\n#define ConsoleTrace2(l, f, s, t) { ConsoleWriteLine(CONSOLE_COLOR_NORMAL, f, s, t); Trace2(l, f, s, t); }\n#define ConsoleTrace3(l, f, s, t, u) { ConsoleWriteLine(CONSOLE_COLOR_NORMAL, f, s, t, u); Trace3(l, f, s, t, u); }\n\n#define ConsoleWarning(f) { ConsoleWriteLine(CONSOLE_COLOR_YELLOW, f); Trace(REPORT_STANDARD, f); }\n#define ConsoleWarning1(f, s) { ConsoleWriteLine(CONSOLE_COLOR_YELLOW, f, s); Trace1(REPORT_STANDARD, f, s); }\n#define ConsoleWarning2(f, s, t) { ConsoleWriteLine(CONSOLE_COLOR_YELLOW, f, s, t); Trace2(REPORT_STANDARD, f, s, t); }\n#define ConsoleWarning3(f, s, t, u) { ConsoleWriteLine(CONSOLE_COLOR_YELLOW, f, s, t, u); Trace3(REPORT_STANDARD, f, s, t, u); }\n\n#define ConsoleError(x, f) { ConsoleWriteError(x, CONSOLE_COLOR_RED, f); TraceError(x, f); }\n#define ConsoleError1(x, f, s) { ConsoleWriteError(x, CONSOLE_COLOR_RED, f, s); TraceError1(x, f, s); }\n#define ConsoleError2(x, f, s, t) { ConsoleWriteError(x, CONSOLE_COLOR_RED, f, s, t); TraceError2(x, f, s, t); }\n#define ConsoleError3(x, f, s, t, u) { ConsoleWriteError(x, CONSOLE_COLOR_RED, f, s, t, u); TraceError3(x, f, s, t, u); }\n\n\n// enums\nenum CONSOLE_COLOR { CONSOLE_COLOR_NORMAL, CONSOLE_COLOR_RED, CONSOLE_COLOR_YELLOW, CONSOLE_COLOR_GREEN };\n\n// structs\n\n// functions\nHRESULT DAPI ConsoleInitialize();\nvoid DAPI ConsoleUninitialize();\n\nvoid DAPI ConsoleGreen();\nvoid DAPI ConsoleRed();\nvoid DAPI ConsoleYellow();\nvoid DAPI ConsoleNormal();\n\nHRESULT DAPI ConsoleWrite(\n    CONSOLE_COLOR cc,\n    __in_z __format_string LPCSTR szFormat,\n    ...\n    );\nHRESULT DAPI ConsoleWriteLine(\n    CONSOLE_COLOR cc,\n    __in_z __format_string LPCSTR szFormat,\n    ...\n    );\nHRESULT DAPI ConsoleWriteError(\n    HRESULT hrError,\n    CONSOLE_COLOR cc,\n    __in_z __format_string LPCSTR szFormat,\n    ...\n    );\n\nHRESULT DAPI ConsoleReadW(\n    __deref_out_z LPWSTR* ppwzBuffer\n    );\n\nHRESULT DAPI ConsoleReadStringA(\n    __deref_out_ecount_part(cchCharBuffer,*pcchNumCharReturn) LPSTR* szCharBuffer,\n    CONST DWORD cchCharBuffer,\n    __out DWORD* pcchNumCharReturn\n    );\nHRESULT DAPI ConsoleReadStringW(\n    __deref_out_ecount_part(cchCharBuffer,*pcchNumCharReturn) LPWSTR* szCharBuffer,\n    CONST DWORD cchCharBuffer,\n    __out DWORD* pcchNumCharReturn\n    );\n\nHRESULT DAPI ConsoleReadNonBlockingW(\n    __deref_out_ecount_opt(*pcchSize) LPWSTR* ppwzBuffer,\n    __out DWORD* pcchSize,\n    BOOL fReadLine\n    );\n\nHRESULT DAPI ConsoleSetReadHidden(void);\nHRESULT DAPI ConsoleSetReadNormal(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/cryputil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"cryputil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//\n// <summary>\n//    Cryptography helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#define ReleaseCryptMsg(p) if (p) { ::CryptMsgClose(p); p = NULL; }\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n#define SHA1_HASH_LEN 20\n\n// function declarations\n\nHRESULT DAPI CrypDecodeObject(\n    __in_z LPCSTR szStructType,\n    __in_ecount(cbData) const BYTE* pbData,\n    __in DWORD cbData,\n    __in DWORD dwFlags,\n    __out LPVOID* ppvObject,\n    __out_opt DWORD* pcbObject\n    );\n\nHRESULT DAPI CrypMsgGetParam(\n    __in HCRYPTMSG hCryptMsg,\n    __in DWORD dwType,\n    __in DWORD dwIndex,\n    __out LPVOID* ppvData,\n    __out_opt DWORD* pcbData\n    );\n\nHRESULT DAPI CrypHashFile(\n    __in_z LPCWSTR wzFilePath,\n    __in DWORD dwProvType,\n    __in ALG_ID algid,\n    __out_bcount(cbHash) BYTE* pbHash,\n    __in DWORD cbHash,\n    __out_opt DWORD64* pqwBytesHashed\n    );\n\nHRESULT DAPI CrypHashFileHandle(\n    __in HANDLE hFile,\n    __in DWORD dwProvType,\n    __in ALG_ID algid,\n    __out_bcount(cbHash) BYTE* pbHash,\n    __in DWORD cbHash,\n    __out_opt DWORD64* pqwBytesHashed\n    );\n\nHRESULT DAPI CrypHashBuffer(\n    __in_bcount(cbBuffer) const BYTE* pbBuffer,\n    __in SIZE_T cbBuffer,\n    __in DWORD dwProvType,\n    __in ALG_ID algid,\n    __out_bcount(cbHash) BYTE* pbHash,\n    __in DWORD cbHash\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/custommsierrors.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"custommsierrors.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//-------------------------------------------------------------------------------------------------\n\n//---------------------------------------------------------------------------\n// Indexes for custom errors in the MSI\n// \n// Note: Custom Errors must be in the range 25000-30000, all other error\n//   codes are reserved for the Windows Installer as standard error ranges\n//   NEVER reuse an error number or you're likely to break the builds.\n//---------------------------------------------------------------------------\n\n// Instructions:\n//    1. add the index to this file\n//    2. define the error table row\n//    3. #include CustomMsiErrors to refer to the index\n//    4. Import Misc\\CustomErrors { MYDEFINE=1 };  with your errorgroup under MYDEFINE\n\n\n//---------------------------------------------------------------------------\n// GLOBAL    25501-25600\n#define GLOBAL_ERROR_BASE                 25501\n\n#define msierrSecureObjectsFailedCreateSD    25520\n#define msierrSecureObjectsFailedSet         25521\n#define msierrSecureObjectsUnknownType       25522\n\n#define msierrXmlFileFailedRead         25530\n#define msierrXmlFileFailedOpen         25531\n#define msierrXmlFileFailedSelect       25532\n#define msierrXmlFileFailedSave         25533\n\n#define msierrXmlConfigFailedRead         25540\n#define msierrXmlConfigFailedOpen         25541\n#define msierrXmlConfigFailedSelect       25542\n#define msierrXmlConfigFailedSave         25543\n\n#define msierrFirewallCannotConnect       25580\n\n//---------------------------------------------------------------------------\n// Server CustomAction Errors\n// SERVER range: 26001-26100\n#define SERVER_ERROR_BASE                      26000\n\n#define msierrIISCannotConnect                 26001\n#define msierrIISFailedReadWebSite             26002\n#define msierrIISFailedReadWebDirs             26003\n#define msierrIISFailedReadVDirs               26004\n#define msierrIISFailedReadFilters             26005\n#define msierrIISFailedReadAppPool             26006\n#define msierrIISFailedReadMimeMap             26007\n#define msierrIISFailedReadProp                26008\n#define msierrIISFailedReadWebSvcExt           26009\n#define msierrIISFailedReadWebError            26010\n#define msierrIISFailedReadHttpHeader          26011\n\n#define msierrIISFailedSchedTransaction        26031\n#define msierrIISFailedSchedInstallWebs        26032\n#define msierrIISFailedSchedInstallWebDirs     26033\n#define msierrIISFailedSchedInstallVDirs       26034\n#define msierrIISFailedSchedInstallFilters     26035\n#define msierrIISFailedSchedInstallAppPool     26036\n#define msierrIISFailedSchedInstallProp        26037\n#define msierrIISFailedSchedInstallWebSvcExt   26038\n\n#define msierrIISFailedSchedUninstallWebs      26051\n#define msierrIISFailedSchedUninstallWebDirs   26052\n#define msierrIISFailedSchedUninstallVDirs     26053\n#define msierrIISFailedSchedUninstallFilters   26054\n#define msierrIISFailedSchedUninstallAppPool   26055\n#define msierrIISFailedSchedUninstallProp      26056\n#define msierrIISFailedSchedUninstallWebSvcExt 26057\n\n#define msierrIISFailedStartTransaction        26101\n#define msierrIISFailedOpenKey                 26102\n#define msierrIISFailedCreateKey               26103\n#define msierrIISFailedWriteData               26104\n#define msierrIISFailedCreateApp               26105\n#define msierrIISFailedDeleteKey               26106\n#define msierrIISFailedDeleteApp               26107\n#define msierrIISFailedDeleteValue             26108\n#define msierrIISFailedCommitInUse             26109\n\n#define msierrSQLFailedCreateDatabase          26201\n#define msierrSQLFailedDropDatabase            26202\n#define msierrSQLFailedConnectDatabase         26203\n#define msierrSQLFailedExecString              26204\n#define msierrSQLDatabaseAlreadyExists         26205\n\n#define msierrPERFMONFailedRegisterDLL         26251\n#define msierrPERFMONFailedUnregisterDLL       26252\n#define msierrInstallPerfCounterData           26253\n#define msierrUninstallPerfCounterData         26254\n\n#define msierrSMBFailedCreate                  26301\n#define msierrSMBFailedDrop                    26302\n\n#define msierrCERTFailedOpen                   26351\n#define msierrCERTFailedAdd                    26352\n\n#define msierrUSRFailedUserCreate              26401\n#define msierrUSRFailedUserCreatePswd          26402\n#define msierrUSRFailedUserGroupAdd            26403\n#define msierrUSRFailedUserCreateExists        26404\n#define msierrUSRFailedGrantLogonAsService     26405\n\n#define msierrDependencyMissingDependencies    26451\n#define msierrDependencyHasDependents          26452\n\n//--------------------------------------------------------------------------\n// Managed code CustomAction Errors\n// MANAGED range: 27000-27100\n#define MANAGED_ERROR_BASE                     27000\n\n#define msierrDotNetRuntimeRequired            27000\n//---------------------------------------------------------------------------\n// Public CustomAction Errors\n// PUBLIC range: 28001-28100\n#define PUBLIC_ERROR_BASE                            28000\n\n#define msierrComPlusCannotConnect                   28001\n#define msierrComPlusPartitionReadFailed             28002\n#define msierrComPlusPartitionRoleReadFailed         28003\n#define msierrComPlusUserInPartitionRoleReadFailed   28004\n#define msierrComPlusPartitionUserReadFailed         28005\n#define msierrComPlusApplicationReadFailed           28006\n#define msierrComPlusApplicationRoleReadFailed       28007\n#define msierrComPlusUserInApplicationRoleReadFailed 28008\n#define msierrComPlusAssembliesReadFailed            28009\n#define msierrComPlusSubscriptionReadFailed          28010\n#define msierrComPlusPartitionDependency             28011\n#define msierrComPlusPartitionNotFound               28012\n#define msierrComPlusPartitionIdConflict             28013\n#define msierrComPlusPartitionNameConflict           28014\n#define msierrComPlusApplicationDependency           28015\n#define msierrComPlusApplicationNotFound             28016\n#define msierrComPlusApplicationIdConflict           28017\n#define msierrComPlusApplicationNameConflict         28018\n#define msierrComPlusApplicationRoleDependency       28019\n#define msierrComPlusApplicationRoleNotFound         28020\n#define msierrComPlusApplicationRoleConflict         28021\n#define msierrComPlusAssemblyDependency              28022\n#define msierrComPlusSubscriptionIdConflict          28023\n#define msierrComPlusSubscriptionNameConflict        28024\n#define msierrComPlusFailedLookupNames               28025\n\n#define msierrMsmqCannotConnect                      28101\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/dictutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"dictutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for string dict helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ReleaseDict(sdh) if (sdh) { DictDestroy(sdh); }\n#define ReleaseNullDict(sdh) if (sdh) { DictDestroy(sdh); sdh = NULL; }\n\ntypedef void* STRINGDICT_HANDLE;\ntypedef const void* C_STRINGDICT_HANDLE;\n\nextern const int STRINGDICT_HANDLE_BYTES;\n\nenum DICT_FLAG\n{\n    DICT_FLAG_NONE = 0,\n    DICT_FLAG_CASEINSENSITIVE = 1\n};\n\nHRESULT DAPI DictCreateWithEmbeddedKey(\n    __out_bcount(STRINGDICT_HANDLE_BYTES) STRINGDICT_HANDLE* psdHandle,\n    __in DWORD dwNumExpectedItems,\n    __in_opt void **ppvArray,\n    __in size_t cByteOffset,\n    __in DICT_FLAG dfFlags\n    );\nHRESULT DAPI DictCreateStringList(\n    __out_bcount(STRINGDICT_HANDLE_BYTES) STRINGDICT_HANDLE* psdHandle,\n    __in DWORD dwNumExpectedItems,\n    __in DICT_FLAG dfFlags\n    );\nHRESULT DAPI DictCreateStringListFromArray(\n    __out_bcount(STRINGDICT_HANDLE_BYTES) STRINGDICT_HANDLE* psdHandle,\n    __in_ecount(cStringArray) const LPCWSTR* rgwzStringArray,\n    __in const DWORD cStringArray,\n    __in DICT_FLAG dfFlags\n    );\nHRESULT DAPI DictCompareStringListToArray(\n    __in_bcount(STRINGDICT_HANDLE_BYTES) STRINGDICT_HANDLE sdStringList,\n    __in_ecount(cStringArray) const LPCWSTR* rgwzStringArray,\n    __in const DWORD cStringArray\n    );\nHRESULT DAPI DictAddKey(\n    __in_bcount(STRINGDICT_HANDLE_BYTES) STRINGDICT_HANDLE sdHandle,\n    __in_z LPCWSTR szString\n    );\nHRESULT DAPI DictAddValue(\n    __in_bcount(STRINGDICT_HANDLE_BYTES) STRINGDICT_HANDLE sdHandle,\n    __in void *pvValue\n    );\nHRESULT DAPI DictKeyExists(\n    __in_bcount(STRINGDICT_HANDLE_BYTES) C_STRINGDICT_HANDLE sdHandle,\n    __in_z LPCWSTR szString\n    );\nHRESULT DAPI DictGetValue(\n    __in_bcount(STRINGDICT_HANDLE_BYTES) C_STRINGDICT_HANDLE sdHandle,\n    __in_z LPCWSTR szString,\n    __out void **ppvValue\n    );\nvoid DAPI DictDestroy(\n    __in_bcount(STRINGDICT_HANDLE_BYTES) STRINGDICT_HANDLE sdHandle\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/dirutil.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"dirutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Directory helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\nenum DIR_DELETE\n{\n    DIR_DELETE_FILES = 1,\n    DIR_DELETE_RECURSE = 2,\n    DIR_DELETE_SCHEDULE = 4,\n};\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nBOOL DAPI DirExists(\n    __in_z LPCWSTR wzPath, \n    __out_opt DWORD *pdwAttributes\n    );\n\nHRESULT DAPI DirCreateTempPath(\n    __in_z LPCWSTR wzPrefix,\n    __out_ecount_z(cchPath) LPWSTR wzPath,\n    __in DWORD cchPath\n    );\n\nHRESULT DAPI DirEnsureExists(\n    __in_z LPCWSTR wzPath, \n    __in_opt LPSECURITY_ATTRIBUTES psa\n    );\n\nHRESULT DAPI DirEnsureDelete(\n    __in_z LPCWSTR wzPath,\n    __in BOOL fDeleteFiles,\n    __in BOOL fRecurse\n    );\n\nHRESULT DAPI DirEnsureDeleteEx(\n    __in_z LPCWSTR wzPath,\n    __in DWORD dwFlags\n    );\n\nHRESULT DAPI DirGetCurrent(\n    __deref_out_z LPWSTR* psczCurrentDirectory\n    );\n\nHRESULT DAPI DirSetCurrent(\n    __in_z LPCWSTR wzDirectory\n    );\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/dutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"dutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for utility layer that provides standard support for asserts, exit macros\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#define DAPI __stdcall\n#define DAPIV __cdecl // used only for functions taking variable length arguments\n\n#define DAPI_(type) EXTERN_C type DAPI\n#define DAPIV_(type) EXTERN_C type DAPIV\n\n\n// enums\nenum REPORT_LEVEL\n{\n    REPORT_NONE,      // turns off report (only valid for XXXSetLevel())\n    REPORT_WARNING,   // written if want only warnings or reporting is on in general\n    REPORT_STANDARD,  // written if reporting is on\n    REPORT_VERBOSE,   // written only if verbose reporting is on\n    REPORT_DEBUG,     // reporting useful when debugging code\n    REPORT_ERROR,     // always gets reported, but can never be specified\n};\n\n// asserts and traces\ntypedef BOOL (DAPI *DUTIL_ASSERTDISPLAYFUNCTION)(__in_z LPCSTR sz);\n\nextern \"C\" void DAPI Dutil_SetAssertModule(__in HMODULE hAssertModule);\nextern \"C\" void DAPI Dutil_SetAssertDisplayFunction(__in DUTIL_ASSERTDISPLAYFUNCTION pfn);\nextern \"C\" void DAPI Dutil_Assert(__in_z LPCSTR szFile, __in int iLine);\nextern \"C\" void DAPI Dutil_AssertSz(__in_z LPCSTR szFile, __in int iLine, __in_z LPCSTR szMsg);\n\nextern \"C\" void DAPI Dutil_TraceSetLevel(__in REPORT_LEVEL ll, __in BOOL fTraceFilenames);\nextern \"C\" REPORT_LEVEL DAPI Dutil_TraceGetLevel();\nextern \"C\" void __cdecl Dutil_Trace(__in_z LPCSTR szFile, __in int iLine, __in REPORT_LEVEL rl, __in_z __format_string LPCSTR szMessage, ...);\nextern \"C\" void __cdecl Dutil_TraceError(__in_z LPCSTR szFile, __in int iLine, __in REPORT_LEVEL rl, __in HRESULT hr, __in_z __format_string LPCSTR szMessage, ...);\nextern \"C\" void DAPI Dutil_RootFailure(__in_z LPCSTR szFile, __in int iLine, __in HRESULT hrError);\n\n#ifdef DEBUG\n\n#define AssertSetModule(m) (void)Dutil_SetAssertModule(m)\n#define AssertSetDisplayFunction(pfn) (void)Dutil_SetAssertDisplayFunction(pfn)\n#define Assert(f)          ((f)    ? (void)0 : (void)Dutil_Assert(__FILE__, __LINE__))\n#define AssertSz(f, sz)    ((f)    ? (void)0 : (void)Dutil_AssertSz(__FILE__, __LINE__, sz))\n\n#define TraceSetLevel(l, f) (void)Dutil_TraceSetLevel(l, f)\n#define TraceGetLevel() (REPORT_LEVEL)Dutil_TraceGetLevel()\n#define Trace(l, f) (void)Dutil_Trace(__FILE__, __LINE__, l, f, NULL)\n#define Trace1(l, f, s) (void)Dutil_Trace(__FILE__, __LINE__, l, f, s)\n#define Trace2(l, f, s, t) (void)Dutil_Trace(__FILE__, __LINE__, l, f, s, t)\n#define Trace3(l, f, s, t, u) (void)Dutil_Trace(__FILE__, __LINE__, l, f, s, t, u)\n\n#define TraceError(x, f) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_ERROR, x, f, NULL)\n#define TraceError1(x, f, s) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_ERROR, x, f, s)\n#define TraceError2(x, f, s, t) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_ERROR, x, f, s, t)\n#define TraceError3(x, f, s, t, u) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_ERROR, x, f, s, t, u)\n\n#define TraceErrorDebug(x, f) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_DEBUG, x, f, NULL)\n#define TraceErrorDebug1(x, f, s) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_DEBUG, x, f, s)\n#define TraceErrorDebug2(x, f, s, t) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_DEBUG, x, f, s, t)\n#define TraceErrorDebug3(x, f, s, t, u) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_DEBUG, x, f, s, t, u)\n\n#else // !DEBUG\n\n#define AssertSetModule(m)\n#define AssertSetDisplayFunction(pfn)\n#define Assert(f)\n#define AssertSz(f, sz)\n\n#define TraceSetLevel(l, f)\n#define Trace(l, f)\n#define Trace1(l, f, s)\n#define Trace2(l, f, s, t)\n#define Trace3(l, f, s, t, u)\n\n#define TraceError(x, f)\n#define TraceError1(x, f, s)\n#define TraceError2(x, f, s, t)\n#define TraceError3(x, f, s, t, u)\n\n#define TraceErrorDebug(x, f)\n#define TraceErrorDebug1(x, f, s)\n#define TraceErrorDebug2(x, f, s, t)\n#define TraceErrorDebug3(x, f, s, t, u)\n\n#endif // DEBUG\n\n\n// ExitTrace can be overriden\n#ifndef ExitTrace\n#define ExitTrace TraceError\n#endif\n#ifndef ExitTrace1\n#define ExitTrace1 TraceError1\n#endif\n#ifndef ExitTrace2\n#define ExitTrace2 TraceError2\n#endif\n#ifndef ExitTrace3\n#define ExitTrace3 TraceError3\n#endif\n\n// Exit macros\n#define ExitFunction()        { goto LExit; }\n#define ExitFunction1(x)          { x; goto LExit; }\n\n#define ExitOnLastError(x, s) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (FAILED(x)) { Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace(x, s); goto LExit; } }\n#define ExitOnLastError1(x, f, s) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (FAILED(x)) { Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace1(x, f, s); goto LExit; } }\n#define ExitOnLastError2(x, f, s, t) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (FAILED(x)) { Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace2(x, f, s, t); goto LExit; } }\n\n#define ExitOnLastErrorDebugTrace(x, s) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (FAILED(x)) { Dutil_RootFailure(__FILE__, __LINE__, x); TraceErrorDebug(x, s); goto LExit; } }\n#define ExitOnLastErrorDebugTrace1(x, f, s) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (FAILED(x)) { Dutil_RootFailure(__FILE__, __LINE__, x); TraceErrorDebug1(x, f, s); goto LExit; } }\n#define ExitOnLastErrorDebugTrace2(x, f, s, t) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (FAILED(x)) { Dutil_RootFailure(__FILE__, __LINE__, x); TraceErrorDebug2(x, f, s, t); goto LExit; } }\n\n#define ExitWithLastError(x, s) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace(x, s); goto LExit; }\n#define ExitWithLastError1(x, f, s) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace1(x, f, s); goto LExit; }\n#define ExitWithLastError2(x, f, s, t) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace2(x, f, s, t); goto LExit; }\n#define ExitWithLastError3(x, f, s, t, u) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace3(x, f, s, t, u); goto LExit; }\n\n#define ExitOnFailure(x, s)   if (FAILED(x)) { ExitTrace(x, s);  goto LExit; }\n#define ExitOnFailure1(x, f, s)   if (FAILED(x)) { ExitTrace1(x, f, s);  goto LExit; }\n#define ExitOnFailure2(x, f, s, t)   if (FAILED(x)) { ExitTrace2(x, f, s, t);  goto LExit; }\n#define ExitOnFailure3(x, f, s, t, u) if (FAILED(x)) { ExitTrace3(x, f, s, t, u);  goto LExit; }\n\n#define ExitOnRootFailure(x, s)   if (FAILED(x)) { Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace(x, s);  goto LExit; }\n#define ExitOnRootFailure1(x, f, s)   if (FAILED(x)) { Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace1(x, f, s);  goto LExit; }\n#define ExitOnRootFailure2(x, f, s, t)   if (FAILED(x)) { Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace2(x, f, s, t);  goto LExit; }\n#define ExitOnRootFailure3(x, f, s, t, u) if (FAILED(x)) { Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace3(x, f, s, t, u);  goto LExit; }\n\n#define ExitOnFailureDebugTrace(x, s)   if (FAILED(x)) { TraceErrorDebug(x, s);  goto LExit; }\n#define ExitOnFailureDebugTrace1(x, f, s)   if (FAILED(x)) { TraceErrorDebug1(x, f, s);  goto LExit; }\n#define ExitOnFailureDebugTrace2(x, f, s, t)   if (FAILED(x)) { TraceErrorDebug2(x, f, s, t);  goto LExit; }\n#define ExitOnFailureDebugTrace3(x, f, s, t, u) if (FAILED(x)) { TraceErrorDebug3(x, f, s, t, u);  goto LExit; }\n\n#define ExitOnNull(p, x, e, s)   if (NULL == p) { x = e; Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace(x, s);  goto LExit; }\n#define ExitOnNull1(p, x, e, f, s)   if (NULL == p) { x = e; Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace1(x, f, s);  goto LExit; }\n#define ExitOnNull2(p, x, e, f, s, t)   if (NULL == p) { x = e; Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace2(x, f, s, t);  goto LExit; }\n\n#define ExitOnNullWithLastError(p, x, s) if (NULL == p) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace(x, s); goto LExit; }\n#define ExitOnNullWithLastError1(p, x, f, s) if (NULL == p) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace1(x, f, s); goto LExit; }\n\n#define ExitOnNullDebugTrace(p, x, e, s)   if (NULL == p) { x = e; Dutil_RootFailure(__FILE__, __LINE__, x); TraceErrorDebug(x, s);  goto LExit; }\n#define ExitOnNullDebugTrace1(p, x, e, f, s)   if (NULL == p) { x = e; Dutil_RootFailure(__FILE__, __LINE__, x); TraceErrorDebug1(x, f, s);  goto LExit; }\n\n#define ExitOnInvalidHandleWithLastError(p, x, s) if (INVALID_HANDLE_VALUE == p) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace(x, s); goto LExit; }\n#define ExitOnInvalidHandleWithLastError1(p, x, f, s) if (INVALID_HANDLE_VALUE == p) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace1(x, f, s); goto LExit; }\n\n#define ExitOnWin32Error(e, x, s) if (ERROR_SUCCESS != e) { x = HRESULT_FROM_WIN32(e); if (!FAILED(x)) { x = E_FAIL; } Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace(x, s); goto LExit; }\n#define ExitOnWin32Error1(e, x, f, s) if (ERROR_SUCCESS != e) { x = HRESULT_FROM_WIN32(e); if (!FAILED(x)) { x = E_FAIL; } Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace1(x, f, s); goto LExit; }\n#define ExitOnWin32Error2(e, x, f, s, t) if (ERROR_SUCCESS != e) { x = HRESULT_FROM_WIN32(e); if (!FAILED(x)) { x = E_FAIL; } Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace2(x, f, s, t); goto LExit; }\n\n// release macros\n#define ReleaseObject(x) if (x) { x->Release(); }\n#define ReleaseObjectArray(prg, cel) if (prg) { for (DWORD Dutil_ReleaseObjectArrayIndex = 0; Dutil_ReleaseObjectArrayIndex < cel; ++Dutil_ReleaseObjectArrayIndex) { ReleaseObject(prg[Dutil_ReleaseObjectArrayIndex]); } ReleaseMem(prg); }\n#define ReleaseVariant(x) { ::VariantClear(&x); }\n#define ReleaseNullObject(x) if (x) { (x)->Release(); x = NULL; }\n#define ReleaseCertificate(x) if (x) { ::CertFreeCertificateContext(x); x=NULL; }\n#define ReleaseHandle(x) if (x) { ::CloseHandle(x); x = NULL; }\n\n\n// useful defines and macros\n#define Unused(x) ((void)x)\n\n#ifndef countof\n#if 1\n#define countof(ary) (sizeof(ary) / sizeof(ary[0]))\n#else\n#ifndef __cplusplus\n#define countof(ary) (sizeof(ary) / sizeof(ary[0]))\n#else\ntemplate<typename T> static char countofVerify(void const *, T) throw() { return 0; }\ntemplate<typename T> static void countofVerify(T *const, T *const *) throw() {};\n#define countof(arr) (sizeof(countofVerify(arr,&(arr))) * sizeof(arr)/sizeof(*(arr)))\n#endif\n#endif\n#endif\n\n#define roundup(x, n) roundup_typed(x, n, DWORD)\n#define roundup_typed(x, n, t) (((t)(x) + ((t)(n) - 1)) & ~((t)(n) - 1))\n\n#define HRESULT_FROM_RPC(x) ((HRESULT) ((x) | FACILITY_RPC))\n\n#ifndef MAXSIZE_T\n#define MAXSIZE_T ((SIZE_T)~((SIZE_T)0))\n#endif\n\ntypedef const BYTE* LPCBYTE;\n\n#define E_FILENOTFOUND HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)\n#define E_PATHNOTFOUND HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n#define E_INVALIDDATA HRESULT_FROM_WIN32(ERROR_INVALID_DATA)\n#define E_INVALIDSTATE HRESULT_FROM_WIN32(ERROR_INVALID_STATE)\n#define E_INSUFFICIENT_BUFFER HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)\n#define E_MOREDATA HRESULT_FROM_WIN32(ERROR_MORE_DATA)\n#define E_NOMOREITEMS HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)\n#define E_NOTFOUND HRESULT_FROM_WIN32(ERROR_NOT_FOUND)\n#define E_MODNOTFOUND HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND)\n#define E_BADCONFIGURATION HRESULT_FROM_WIN32(ERROR_BAD_CONFIGURATION)\n\n#define AddRefAndRelease(x) { x->AddRef(); x->Release(); }\n\n#define MAKEDWORD(lo, hi) ((DWORD)MAKELONG(lo, hi))\n#define MAKEQWORDVERSION(mj, mi, b, r) (((DWORD64)MAKELONG(r, b)) | (((DWORD64)MAKELONG(mi, mj)) << 32))\n\n// other functions\nextern \"C\" HRESULT DAPI LoadSystemLibrary(__in_z LPCWSTR wzModuleName, __out HMODULE *phModule);\nextern \"C\" HRESULT DAPI LoadSystemLibraryWithPath(__in_z LPCWSTR wzModuleName, __out HMODULE *phModule, __deref_out_z_opt LPWSTR* psczPath);\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/eseutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"eseutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for Extensible Storage Engine (Jetblue) helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ReleaseEseQuery(pqh) if (pqh) { EseFinishQuery(pqh); }\n#define ReleaseNullEseQuery(pqh) if (pqh) { EseFinishQuery(pqh); pqh = NULL; }\n\nstruct ESE_COLUMN_SCHEMA\n{\n    JET_COLUMNID jcColumn;\n    LPCWSTR pszName;\n    JET_COLTYP jcColumnType;\n    BOOL fKey; // If this column is part of the key of the table\n    BOOL fFixed;\n    BOOL fNullable;\n    BOOL fAutoIncrement;\n};\n\nstruct ESE_TABLE_SCHEMA\n{\n    JET_TABLEID jtTable;\n    LPCWSTR pszName;\n    DWORD dwColumns;\n    ESE_COLUMN_SCHEMA *pcsColumns;\n};\n\nstruct ESE_DATABASE_SCHEMA\n{\n    DWORD dwTables;\n    ESE_TABLE_SCHEMA *ptsTables;\n};\n\nenum ESE_QUERY_TYPE\n{\n    ESE_QUERY_EXACT,\n    ESE_QUERY_FROM_TOP,\n    ESE_QUERY_FROM_BOTTOM\n};\n\ntypedef void* ESE_QUERY_HANDLE;\n\nHRESULT DAPI EseBeginSession(\n    __out JET_INSTANCE *pjiInstance,\n    __out JET_SESID *pjsSession,\n    __in_z LPCWSTR pszInstance,\n    __in_z LPCWSTR pszPath\n    );\nHRESULT DAPI EseEndSession(\n    __in JET_INSTANCE jiInstance,\n    __in JET_SESID jsSession\n    );\nHRESULT DAPI EseEnsureDatabase(\n    __in JET_SESID jsSession,\n    __in_z LPCWSTR pszFile,\n    __in ESE_DATABASE_SCHEMA *pdsSchema,\n    __out JET_DBID* pjdbDb,\n    __in BOOL fExclusive,\n    __in BOOL fReadonly\n    );\nHRESULT DAPI EseCloseDatabase(\n    __in JET_SESID jsSession,\n    __in JET_DBID jdbDb\n    );\nHRESULT DAPI EseCreateTable(\n    __in JET_SESID jsSession,\n    __in JET_DBID jdbDb,\n    __in_z LPCWSTR pszTable,\n    __out JET_TABLEID *pjtTable\n    );\nHRESULT DAPI EseOpenTable(\n    __in JET_SESID jsSession,\n    __in JET_DBID jdbDb,\n    __in_z LPCWSTR pszTable,\n    __out JET_TABLEID *pjtTable\n    );\nHRESULT DAPI EseCloseTable(\n    __in JET_SESID jsSession,\n    __in JET_TABLEID jtTable\n    );\nHRESULT DAPI EseEnsureColumn(\n    __in JET_SESID jsSession,\n    __in JET_TABLEID jtTable,\n    __in_z LPCWSTR pszColumnName,\n    __in JET_COLTYP jcColumnType,\n    __in ULONG ulColumnSize,\n    __in BOOL fFixed,\n    __in BOOL fNullable,\n    __out_opt JET_COLUMNID *pjcColumn\n    );\nHRESULT DAPI EseGetColumn(\n    __in JET_SESID jsSession,\n    __in JET_TABLEID jtTable,\n    __in_z LPCWSTR pszColumnName,\n    __out JET_COLUMNID *pjcColumn\n    );\nHRESULT DAPI EseMoveCursor(\n    __in JET_SESID jsSession,\n    __in JET_TABLEID jtTable,\n    __in LONG lRow\n    );\nHRESULT DAPI EseDeleteRow(\n    __in JET_SESID jsSession,\n    __in JET_TABLEID jtTable\n    );\nHRESULT DAPI EseBeginTransaction(\n    __in JET_SESID jsSession\n    );\nHRESULT DAPI EseRollbackTransaction(\n    __in JET_SESID jsSession,\n    __in BOOL fAll\n    );\nHRESULT DAPI EseCommitTransaction(\n    __in JET_SESID jsSession\n    );\nHRESULT DAPI EsePrepareUpdate(\n    __in JET_SESID jsSession,\n    __in JET_TABLEID jtTable,\n    __in ULONG ulPrep\n    );\nHRESULT DAPI EseFinishUpdate(\n    __in JET_SESID jsSession,\n    __in JET_TABLEID jtTable,\n    __in BOOL fSeekToInsertedRecord\n    );\nHRESULT DAPI EseSetColumnBinary(\n    __in JET_SESID jsSession,\n    __in ESE_TABLE_SCHEMA tsTable,\n    __in DWORD dwColumn,\n    __in_bcount(cbBuffer) const BYTE* pbBuffer,\n    __in SIZE_T cbBuffer\n    );\nHRESULT DAPI EseSetColumnDword(\n    __in JET_SESID jsSession,\n    __in ESE_TABLE_SCHEMA tsTable,\n    __in DWORD dwColumn,\n    __in DWORD dwValue\n    );\nHRESULT DAPI EseSetColumnBool(\n    __in JET_SESID jsSession,\n    __in ESE_TABLE_SCHEMA tsTable,\n    __in DWORD dwColumn,\n    __in BOOL fValue\n    );\nHRESULT DAPI EseSetColumnString(\n    __in JET_SESID jsSession,\n    __in ESE_TABLE_SCHEMA tsTable,\n    __in DWORD dwColumn,\n    __in_z LPCWSTR pszValue\n    );\nHRESULT DAPI EseSetColumnEmpty(\n    __in JET_SESID jsSession,\n    __in ESE_TABLE_SCHEMA tsTable,\n    __in DWORD dwColumn\n    );\nHRESULT DAPI EseGetColumnBinary(\n    __in JET_SESID jsSession,\n    __in ESE_TABLE_SCHEMA tsTable,\n    __in DWORD dwColumn,\n    __deref_out_bcount(*piBuffer) BYTE** ppbBuffer,\n    __inout SIZE_T* piBuffer\n    );\nHRESULT DAPI EseGetColumnDword(\n    __in JET_SESID jsSession,\n    __in ESE_TABLE_SCHEMA tsTable,\n    __in DWORD dwColumn,\n    __out DWORD *pdwValue\n    );\nHRESULT DAPI EseGetColumnBool(\n    __in JET_SESID jsSession,\n    __in ESE_TABLE_SCHEMA tsTable,\n    __in DWORD dwColumn,\n    __out BOOL *pfValue\n    );\nHRESULT DAPI EseGetColumnString(\n    __in JET_SESID jsSession,\n    __in ESE_TABLE_SCHEMA tsTable,\n    __in DWORD dwColumn,\n    __out LPWSTR *ppszValue\n    );\n\n// Call this once for each key column in the table\nHRESULT DAPI EseBeginQuery(\n    __in JET_SESID jsSession,\n    __in JET_TABLEID jtTable,\n    __in ESE_QUERY_TYPE qtQueryType,\n    __out ESE_QUERY_HANDLE *peqhHandle\n    );\nHRESULT DAPI EseSetQueryColumnBinary(\n    __in ESE_QUERY_HANDLE eqhHandle,\n    __in_bcount(cbBuffer) const BYTE* pbBuffer,\n    __in SIZE_T cbBuffer,\n    __in BOOL fFinal // If this is true, all other key columns in the query will be set to \"*\"\n    );\nHRESULT DAPI EseSetQueryColumnDword(\n    __in ESE_QUERY_HANDLE eqhHandle,\n    __in DWORD dwData,\n    __in BOOL fFinal // If this is true, all other key columns in the query will be set to \"*\"\n    );\nHRESULT DAPI EseSetQueryColumnBool(\n    __in ESE_QUERY_HANDLE eqhHandle,\n    __in BOOL fValue,\n    __in BOOL fFinal // If this is true, all other key columns in the query will be set to \"*\"\n    );\nHRESULT DAPI EseSetQueryColumnString(\n    __in ESE_QUERY_HANDLE eqhHandle,\n    __in_z LPCWSTR pszString,\n    __in BOOL fFinal // If this is true, all other key columns in the query will be set to \"*\"\n    );\nHRESULT DAPI EseFinishQuery(\n    __in ESE_QUERY_HANDLE eqhHandle\n    );\n// Once all columns have been set up, call this and read the result\nHRESULT DAPI EseRunQuery(\n    __in ESE_QUERY_HANDLE eqhHandle\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/fileutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"fileutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for file helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ReleaseFile(h) if (INVALID_HANDLE_VALUE != h) { ::CloseHandle(h); h = INVALID_HANDLE_VALUE; }\n#define ReleaseFileHandle(h) if (INVALID_HANDLE_VALUE != h) { ::CloseHandle(h); h = INVALID_HANDLE_VALUE; }\n#define ReleaseFileFindHandle(h) if (INVALID_HANDLE_VALUE != h) { ::FindClose(h); h = INVALID_HANDLE_VALUE; }\n\n#define FILEMAKEVERSION(major, minor, build, revision) static_cast<DWORD64>((static_cast<DWORD64>(major & 0xFFFF) << 48) \\\n                                                                          | (static_cast<DWORD64>(minor & 0xFFFF) << 32) \\\n                                                                          | (static_cast<DWORD64>(build & 0xFFFF) << 16) \\\n                                                                          | (static_cast<DWORD64>(revision & 0xFFFF)))\n\nenum FILE_ARCHITECTURE\n{\n    FILE_ARCHITECTURE_UNKNOWN,\n    FILE_ARCHITECTURE_X86,\n    FILE_ARCHITECTURE_X64,\n    FILE_ARCHITECTURE_IA64,\n};\n\nenum FILE_ENCODING\n{\n    FILE_ENCODING_UNSPECIFIED = 0,\n    // TODO: distinguish between non-BOM utf-8 and ANSI in the future?\n    FILE_ENCODING_UTF8,\n    FILE_ENCODING_UTF8_WITH_BOM,\n    FILE_ENCODING_UTF16,\n    FILE_ENCODING_UTF16_WITH_BOM,\n};\n\n\nLPWSTR DAPI FileFromPath(\n    __in_z LPCWSTR wzPath\n    );\nHRESULT DAPI FileResolvePath(\n    __in_z LPCWSTR wzRelativePath,\n    __out LPWSTR *ppwzFullPath\n    );\nHRESULT DAPI FileStripExtension(\n    __in_z LPCWSTR wzFileName,\n    __out LPWSTR *ppwzFileNameNoExtension\n    );\nHRESULT DAPI FileChangeExtension(\n    __in_z LPCWSTR wzFileName,\n    __in_z LPCWSTR wzNewExtension,\n    __out LPWSTR *ppwzFileNameNewExtension\n    );\nHRESULT DAPI FileAddSuffixToBaseName(\n    __in_z LPCWSTR wzFileName,\n    __in_z LPCWSTR wzSuffix,\n    __out_z LPWSTR* psczNewFileName\n    );\nHRESULT DAPI FileVersionFromString(\n    __in_z LPCWSTR wzVersion, \n    __out DWORD *pdwVerMajor, \n    __out DWORD* pdwVerMinor\n    );\nHRESULT DAPI FileVersionFromStringEx(\n    __in_z LPCWSTR wzVersion,\n    __in DWORD cchVersion,\n    __out DWORD64* pqwVersion\n    );\nHRESULT DAPI FileVersionToStringEx(\n    __in DWORD64 qwVersion,\n    __out LPWSTR* psczVersion\n    );\nHRESULT DAPI FileSetPointer(\n    __in HANDLE hFile,\n    __in DWORD64 dw64Move,\n    __out_opt DWORD64* pdw64NewPosition,\n    __in DWORD dwMoveMethod\n    );\nHRESULT DAPI FileSize(\n    __in_z LPCWSTR pwzFileName,\n    __out LONGLONG* pllSize\n    );\nHRESULT DAPI FileSizeByHandle(\n    __in HANDLE hFile, \n    __out LONGLONG* pllSize\n    );\nBOOL DAPI FileExistsEx(\n    __in_z LPCWSTR wzPath, \n    __out_opt DWORD *pdwAttributes\n    );\nBOOL DAPI FileExistsAfterRestart(\n    __in_z LPCWSTR wzPath,\n    __out_opt DWORD *pdwAttributes\n    );\nHRESULT DAPI FileRemoveFromPendingRename(\n    __in_z LPCWSTR wzPath\n    );\nHRESULT DAPI FileRead(\n    __deref_out_bcount_full(*pcbDest) LPBYTE* ppbDest,\n    __out DWORD* pcbDest,\n    __in_z LPCWSTR wzSrcPath\n    );\nHRESULT DAPI FileReadUntil(\n    __deref_out_bcount_full(*pcbDest) LPBYTE* ppbDest,\n    __out_range(<=, cbMaxRead) DWORD* pcbDest,\n    __in_z LPCWSTR wzSrcPath,\n    __in DWORD cbMaxRead\n    );\nHRESULT DAPI FileReadPartial(\n    __deref_out_bcount_full(*pcbDest) LPBYTE* ppbDest,\n    __out_range(<=, cbMaxRead) DWORD* pcbDest,\n    __in_z LPCWSTR wzSrcPath,\n    __in BOOL fSeek,\n    __in DWORD cbStartPosition,\n    __in DWORD cbMaxRead,\n    __in BOOL fPartialOK\n    );\nHRESULT DAPI FileWrite(\n    __in_z LPCWSTR pwzFileName,\n    __in DWORD dwFlagsAndAttributes,\n    __in_bcount_opt(cbData) LPCBYTE pbData,\n    __in DWORD cbData,\n    __out_opt HANDLE* pHandle\n    );\nHRESULT DAPI FileWriteHandle(\n    __in HANDLE hFile,\n    __in_bcount_opt(cbData) LPCBYTE pbData,\n    __in DWORD cbData\n    );\nHRESULT DAPI FileCopyUsingHandles(\n    __in HANDLE hSource,\n    __in HANDLE hTarget,\n    __in DWORD64 cbCopy,\n    __out_opt DWORD64* pcbCopied\n    );\nHRESULT DAPI FileEnsureCopy(\n    __in_z LPCWSTR wzSource,\n    __in_z LPCWSTR wzTarget,\n    __in BOOL fOverwrite\n    );\nHRESULT DAPI FileEnsureCopyWithRetry(\n    __in LPCWSTR wzSource,\n    __in LPCWSTR wzTarget,\n    __in BOOL fOverwrite,\n    __in DWORD cRetry,\n    __in DWORD dwWaitMilliseconds\n    );\nHRESULT DAPI FileEnsureMove(\n    __in_z LPCWSTR wzSource, \n    __in_z LPCWSTR wzTarget, \n    __in BOOL fOverwrite,\n    __in BOOL fAllowCopy\n    );\nHRESULT DAPI FileEnsureMoveWithRetry(\n    __in LPCWSTR wzSource,\n    __in LPCWSTR wzTarget,\n    __in BOOL fOverwrite,\n    __in BOOL fAllowCopy,\n    __in DWORD cRetry,\n    __in DWORD dwWaitMilliseconds\n    );\nHRESULT DAPI FileCreateTemp(\n    __in_z LPCWSTR wzPrefix,\n    __in_z LPCWSTR wzExtension,\n    __deref_opt_out_z LPWSTR* ppwzTempFile,\n    __out_opt HANDLE* phTempFile\n    );\nHRESULT DAPI FileCreateTempW(\n    __in_z LPCWSTR wzPrefix,\n    __in_z LPCWSTR wzExtension,\n    __deref_opt_out_z LPWSTR* ppwzTempFile,\n    __out_opt HANDLE* phTempFile\n    );\nHRESULT DAPI FileVersion(\n    __in_z LPCWSTR wzFilename, \n    __out DWORD *pdwVerMajor, \n    __out DWORD* pdwVerMinor\n    );\nHRESULT DAPI FileIsSame(\n    __in_z LPCWSTR wzFile1,\n    __in_z LPCWSTR wzFile2,\n    __out LPBOOL lpfSameFile\n    );\nHRESULT DAPI FileEnsureDelete(\n    __in_z LPCWSTR wzFile\n    );\nHRESULT DAPI FileGetTime(\n    __in_z LPCWSTR wzFile,  \n    __out_opt  LPFILETIME lpCreationTime,\n    __out_opt  LPFILETIME lpLastAccessTime,\n    __out_opt  LPFILETIME lpLastWriteTime\n    );\nHRESULT DAPI FileSetTime(\n    __in_z LPCWSTR wzFile,\n    __in_opt  const FILETIME *lpCreationTime,\n    __in_opt  const FILETIME *lpLastAccessTime,\n    __in_opt  const FILETIME *lpLastWriteTime\n    );\nHRESULT DAPI FileResetTime(\n    __in_z LPCWSTR wzFile\n    );\nHRESULT DAPI FileExecutableArchitecture(\n    __in_z LPCWSTR wzFile,\n    __out FILE_ARCHITECTURE *pArchitecture\n    );\nHRESULT DAPI FileToString(\n    __in_z LPCWSTR wzFile,\n    __out LPWSTR *psczString,\n    __out_opt FILE_ENCODING *pfeEncoding\n    );\nHRESULT DAPI FileFromString(\n    __in_z LPCWSTR wzFile,\n    __in DWORD dwFlagsAndAttributes,\n    __in_z LPCWSTR sczString,\n    __in FILE_ENCODING feEncoding\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/gdiputil.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"gdiputil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    GDI+ helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n#define ExitOnGdipFailure(g, x, s) { x = GdipHresultFromStatus(g); if (FAILED(x)) { Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace(x, s); goto LExit; } }\n#define ExitOnGdipFailure1(g, x, f, s) { x = GdipHresultFromStatus(g); if (FAILED(x)) { Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace1(x, f, s); goto LExit; } }\n#define ExitOnGdipFailure2(g, x, f, s, t) { x = GdipHresultFromStatus(g); if (FAILED(x)) { Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace2(x, f, s, t); goto LExit; } }\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nHRESULT DAPI GdipBitmapFromResource(\n    __in_opt HINSTANCE hinst,\n    __in_z LPCSTR szId,\n    __out Gdiplus::Bitmap **ppBitmap\n    );\n\nHRESULT DAPI GdipBitmapFromFile(\n    __in_z LPCWSTR wzFileName,\n    __out Gdiplus::Bitmap **ppBitmap\n    );\n\nHRESULT DAPI GdipHresultFromStatus(\n    __in Gdiplus::Status gs\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/iis7util.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"iis7util.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//  IIS7 helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// IIS Config schema names\n#define IIS_CONFIG_ADD                      L\"add\"\n#define IIS_CONFIG_ALLOWED                  L\"allowed\"\n#define IIS_CONFIG_APPHOST_ROOT             L\"MACHINE/WEBROOT/APPHOST\"\n#define IIS_CONFIG_APPLICATION              L\"application\"\n#define IIS_CONFIG_APPPOOL                  L\"applicationPool\"\n#define IIS_CONFIG_APPPOOL_AUTO             L\"autoStart\"\n#define IIS_CONFIG_APPPOOL_SECTION          L\"system.applicationHost/applicationPools\"\n#define IIS_CONFIG_AUTOSTART                L\"serverAutoStart\"\n#define IIS_CONFIG_BINDING                  L\"binding\"\n#define IIS_CONFIG_BINDINGINFO              L\"bindingInformation\"\n#define IIS_CONFIG_BINDINGS                 L\"bindings\"\n#define IIS_CONFIG_DESC                     L\"description\"\n#define IIS_CONFIG_EXECUTABLE               L\"scriptProcessor\"\n#define IIS_CONFIG_ENABLED                  L\"enabled\"\n#define IIS_CONFIG_ENABLE32                 L\"enable32BitAppOnWin64\"\n#define IIS_CONFIG_FILEEXT                  L\"fileExtension\"\n#define IIS_CONFIG_FILTER                   L\"filter\"\n#define IIS_CONFIG_GROUPID                  L\"groupId\"\n#define IIS_CONFIG_HEADERS                  L\"customHeaders\"\n#define IIS_CONFIG_HTTPERRORS_SECTION       L\"system.webServer/httpErrors\"\n#define IIS_CONFIG_ID                       L\"id\"\n#define IIS_CONFIG_ISAPI_SECTION            L\"system.webServer/isapiFilters\"\n#define IIS_CONFIG_HTTPPROTO_SECTION        L\"system.webServer/httpProtocol\"\n#define IIS_CONFIG_LOG_SECTION              L\"system.applicationHost/log\"\n#define IIS_CONFIG_LOG_UTF8                 L\"logInUTF8\"\n#define IIS_CONFIG_LIMITS                   L\"limits\"\n#define IIS_CONFIG_PIPELINEMODE             L\"managedPipelineMode\"\n#define IIS_CONFIG_MANAGEDRUNTIMEVERSION    L\"managedRuntimeVersion\"\n#define IIS_CONFIG_WEBLOG                   L\"logFile\"\n#define IIS_CONFIG_LOGFORMAT                L\"logFormat\"\n#define IIS_CONFIG_MIMEMAP                  L\"mimeMap\"\n#define IIS_CONFIG_MIMETYPE                 L\"mimeType\"\n#define IIS_CONFIG_MODULES                  L\"modules\"\n#define IIS_CONFIG_NAME                     L\"name\"\n#define IIS_CONFIG_PATH                     L\"path\"\n#define IIS_CONFIG_PHYSPATH                 L\"physicalPath\"\n#define IIS_CONFIG_PROTOCOL                 L\"protocol\"\n#define IIS_CONFIG_RESTRICTION_SECTION      L\"system.webServer/security/isapiCgiRestriction\"\n#define IIS_CONFIG_SITE                     L\"site\"\n#define IIS_CONFIG_SITE_ID                  L\"id\"\n#define IIS_CONFIG_SITES_SECTION            L\"system.applicationHost/sites\"\n#define IIS_CONFIG_CONNECTTIMEOUT           L\"connectionTimeout\"\n#define IIS_CONFIG_VDIR                     L\"virtualDirectory\"\n#define IIS_CONFIG_VALUE                    L\"value\"\n#define IIS_CONFIG_VERBS                    L\"verb\"\n#define IIS_CONFIG_WEBLIMITS_SECTION        L\"system.applicationHost/webLimits\"\n#define IIS_CONFIG_WEBLIMITS_MAXBAND        L\"maxGlobalBandwidth\"\n#define IIS_CONFIG_TRUE                     L\"true\"\n#define IIS_CONFIG_FALSE                    L\"false\"\n#define IIS_CONFIG_ERROR                    L\"error\"\n#define IIS_CONFIG_STATUSCODE               L\"statusCode\"\n#define IIS_CONFIG_SUBSTATUS                L\"subStatusCode\"\n#define IIS_CONFIG_LANGPATH                 L\"prefixLanguageFilePath\"\n#define IIS_CONFIG_RESPMODE                 L\"responseMode\"\n#define IIS_CONFIG_CLEAR                    L\"clear\"\n#define IIS_CONFIG_RECYCLING                L\"recycling\"\n#define IIS_CONFIG_PEROIDRESTART            L\"periodicRestart\"\n#define IIS_CONFIG_TIME                     L\"time\"\n#define IIS_CONFIG_REQUESTS                 L\"requests\"\n#define IIS_CONFIG_SCHEDULE                 L\"schedule\"\n#define IIS_CONFIG_MEMORY                   L\"memory\"\n#define IIS_CONFIG_PRIVMEMORY               L\"privateMemory\"\n#define IIS_CONFIG_PROCESSMODEL             L\"processModel\"\n#define IIS_CONFIG_IDLETIMEOUT              L\"idleTimeout\"\n#define IIS_CONFIG_QUEUELENGTH              L\"queueLength\"\n#define IIS_CONFIG_IDENITITYTYPE            L\"identityType\"\n#define IIS_CONFIG_LOCALSYSTEM              L\"LocalSystem\"\n#define IIS_CONFIG_LOCALSERVICE             L\"LocalService\"\n#define IIS_CONFIG_NETWORKSERVICE           L\"NetworkService\"\n#define IIS_CONFIG_SPECIFICUSER             L\"SpecificUser\"\n#define IIS_CONFIG_APPLICATIONPOOLIDENTITY  L\"ApplicationPoolIdentity\"\n#define IIS_CONFIG_USERNAME                 L\"userName\"\n#define IIS_CONFIG_PASSWORD                 L\"password\"\n#define IIS_CONFIG_CPU                      L\"cpu\"\n#define IIS_CONFIG_LIMIT                    L\"limit\"\n#define IIS_CONFIG_CPU_ACTION               L\"action\"\n#define IIS_CONFIG_KILLW3WP                 L\"KillW3wp\"\n#define IIS_CONFIG_NOACTION                 L\"NoAction\"\n#define IIS_CONFIG_RESETINTERVAL            L\"resetInterval\"\n#define IIS_CONFIG_MAXWRKPROCESSES          L\"maxProcesses\"\n#define IIS_CONFIG_HANDLERS_SECTION         L\"system.webServer/handlers\"\n#define IIS_CONFIG_DEFAULTDOC_SECTION       L\"system.webServer/defaultDocument\"\n#define IIS_CONFIG_ASP_SECTION              L\"system.webServer/asp\"\n#define IIS_CONFIG_SCRIPTERROR              L\"scriptErrorSentToBrowser\"\n#define IIS_CONFIG_STATICCONTENT_SECTION    L\"system.webServer/staticContent\"\n#define IIS_CONFIG_HTTPEXPIRES              L\"httpExpires\"\n#define IIS_CONFIG_MAXAGE                   L\"cacheControlMaxAge\"\n#define IIS_CONFIG_CLIENTCACHE              L\"clientCache\"\n#define IIS_CONFIG_CACHECONTROLMODE         L\"cacheControlMode\"\n#define IIS_CONFIG_USEMAXAGE                L\"UseMaxAge\"\n#define IIS_CONFIG_USEEXPIRES               L\"UseExpires\"\n#define IIS_CONFIG_CACHECUST                L\"cacheControlCustom\"\n#define IIS_CONFIG_ASP_SECTION              L\"system.webServer/asp\"\n#define IIS_CONFIG_SESSION                  L\"session\"\n#define IIS_CONFIG_ALLOWSTATE               L\"allowSessionState\"\n#define IIS_CONFIG_TIMEOUT                  L\"timeout\"\n#define IIS_CONFIG_BUFFERING                L\"bufferingOn\"\n#define IIS_CONFIG_PARENTPATHS              L\"enableParentPaths\"\n#define IIS_CONFIG_SCRIPTLANG               L\"scriptLanguage\"\n#define IIS_CONFIG_SCRIPTTIMEOUT            L\"scriptTimeout\"\n#define IIS_CONFIG_LIMITS                   L\"limits\"\n#define IIS_CONFIG_ALLOWDEBUG               L\"appAllowDebugging\"\n#define IIS_CONFIG_ALLOWCLIENTDEBUG         L\"appAllowClientDebug\"\n#define IIS_CONFIG_CERTIFICATEHASH          L\"certificateHash\"\n#define IIS_CONFIG_CERTIFICATESTORENAME     L\"certificateStoreName\"\n#define IIS_CONFIG_HTTPLOGGING_SECTION      L\"system.webServer/httpLogging\"\n#define IIS_CONFIG_DONTLOG                  L\"dontLog\"\n\ntypedef BOOL (CALLBACK* ENUMAPHOSTELEMENTPROC)(IAppHostElement*, LPVOID);\ntypedef BOOL (CALLBACK* VARIANTCOMPARATORPROC)(VARIANT*, VARIANT*);\n\nHRESULT DAPI Iis7PutPropertyVariant(\n    __in IAppHostElement *pElement,\n    __in LPCWSTR wzPropName,\n    __in VARIANT vtPut\n    );\n\nHRESULT DAPI Iis7PutPropertyInteger(\n    __in IAppHostElement *pElement,\n    __in LPCWSTR wzPropName,\n    __in DWORD dValue\n    );\n\nHRESULT DAPI Iis7PutPropertyString(\n    __in IAppHostElement *pElement,\n    __in LPCWSTR wzPropName,\n    __in LPCWSTR wzString\n    );\n\nHRESULT DAPI Iis7PutPropertyBool(\n    __in IAppHostElement *pElement,\n    __in LPCWSTR wzPropName,\n    __in BOOL fValue);\n\nHRESULT DAPI Iis7GetPropertyVariant(\n    __in IAppHostElement *pElement,\n    __in LPCWSTR wzPropName,\n    __in VARIANT* vtGet\n    );\n\nHRESULT DAPI Iis7GetPropertyString(\n    __in IAppHostElement *pElement,\n    __in LPCWSTR wzPropName,\n    __in LPWSTR* psczGet\n    );\n\nstruct IIS7_APPHOSTELEMENTCOMPARISON\n{\n    LPCWSTR sczElementName;\n    LPCWSTR sczAttributeName;\n    VARIANT* pvAttributeValue;\n    VARIANTCOMPARATORPROC pComparator;\n};\n\nBOOL DAPI Iis7IsMatchingAppHostElement( \n    __in IAppHostElement *pElement,\n    __in IIS7_APPHOSTELEMENTCOMPARISON* pComparison\n    );\n\nHRESULT DAPI Iis7FindAppHostElementString( \n    __in IAppHostElementCollection *pCollection,\n    __in LPCWSTR wzElementName,\n    __in LPCWSTR wzAttributeName,\n    __in LPCWSTR wzAttributeValue,\n    __out IAppHostElement** ppElement,\n    __out DWORD* pdwIndex\n    );\n\nHRESULT DAPI Iis7FindAppHostElementPath( \n    __in IAppHostElementCollection *pCollection,\n    __in LPCWSTR wzElementName,\n    __in LPCWSTR wzAttributeName,\n    __in LPCWSTR wzAttributeValue,\n    __out IAppHostElement** ppElement,\n    __out DWORD* pdwIndex\n    );\n\nHRESULT DAPI Iis7FindAppHostElementInteger( \n    __in IAppHostElementCollection *pCollection,\n    __in LPCWSTR wzElementName,\n    __in LPCWSTR wzAttributeName,\n    __in DWORD dwAttributeValue,\n    __out IAppHostElement** ppElement,\n    __out DWORD* pdwIndex\n    );\n\nHRESULT DAPI Iis7FindAppHostElementVariant( \n    __in IAppHostElementCollection *pCollection,\n    __in LPCWSTR wzElementName,\n    __in LPCWSTR wzAttributeName,\n    __in VARIANT* pvAttributeValue,\n    __out IAppHostElement** ppElement,\n    __out DWORD* pdwIndex\n    );\n\nHRESULT DAPI Iis7EnumAppHostElements( \n    __in IAppHostElementCollection *pCollection,\n    __in ENUMAPHOSTELEMENTPROC pCallback,\n    __in LPVOID pContext,\n    __out IAppHostElement** ppElement,\n    __out DWORD* pdwIndex\n    );\n\nHRESULT DAPI Iis7FindAppHostMethod(\n    __in IAppHostMethodCollection *pCollection,\n    __in LPCWSTR wzMethodName,\n    __out IAppHostMethod** ppMethod,\n    __out DWORD* pdwIndex\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/inetutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"inetutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Internet utilites.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ReleaseInternet(h) if (h) { ::InternetCloseHandle(h); h = NULL; }\n#define ReleaseNullInternet(h) if (h) { ::InternetCloseHandle(h); h = NULL; }\n\n\n// functions\nHRESULT DAPI InternetGetSizeByHandle(\n    __in HINTERNET hiFile,\n    __out LONGLONG* pllSize\n    );\n\nHRESULT DAPI InternetGetCreateTimeByHandle(\n    __in HINTERNET hiFile,\n    __out LPFILETIME pft\n    );\n\nHRESULT DAPI InternetQueryInfoString(\n    __in HINTERNET h,\n    __in DWORD dwInfo,\n    __deref_out_z LPWSTR* psczValue\n    );\n\nHRESULT DAPI InternetQueryInfoNumber(\n    __in HINTERNET h,\n    __in DWORD dwInfo,\n    __out LONG* plInfo\n    );\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/iniutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"iniutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Ini/cfg file helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ReleaseIni(ih) if (ih) { IniUninitialize(ih); }\n#define ReleaseNullIni(ih) if (ih) { IniUninitialize(ih); ih = NULL; }\n\ntypedef void* INI_HANDLE;\ntypedef const void* C_INI_HANDLE;\n\nextern const int INI_HANDLE_BYTES;\n\nstruct INI_VALUE\n{\n    LPCWSTR wzName;\n    LPCWSTR wzValue;\n\n    DWORD dwLineNumber;\n};\n\nHRESULT DAPI IniInitialize(\n    __out_bcount(INI_HANDLE_BYTES) INI_HANDLE* piHandle\n    );\nvoid DAPI IniUninitialize(\n    __in_bcount(INI_HANDLE_BYTES) INI_HANDLE piHandle\n    );\nHRESULT DAPI IniSetOpenTag(\n    __inout_bcount(INI_HANDLE_BYTES) INI_HANDLE piHandle,\n    __in_z_opt LPCWSTR wzOpenTagPrefix,\n    __in_z_opt LPCWSTR wzOpenTagPostfix\n    );\nHRESULT DAPI IniSetValueStyle(\n    __inout_bcount(INI_HANDLE_BYTES) INI_HANDLE piHandle,\n    __in_z_opt LPCWSTR wzValuePrefix,\n    __in_z_opt LPCWSTR wzValueSeparator\n    );\nHRESULT DAPI IniSetCommentStyle(\n    __inout_bcount(INI_HANDLE_BYTES) INI_HANDLE piHandle,\n    __in_z_opt LPCWSTR wzLinePrefix\n    );\nHRESULT DAPI IniParse(\n    __inout_bcount(INI_HANDLE_BYTES) INI_HANDLE piHandle,\n    __in LPCWSTR wzPath,\n    __out_opt FILE_ENCODING *pfeEncodingFound\n    );\nHRESULT DAPI IniGetValueList(\n    __in_bcount(INI_HANDLE_BYTES) INI_HANDLE piHandle,\n    __deref_out_ecount_opt(pcValues) INI_VALUE** prgivValues,\n    __out DWORD *pcValues\n    );\nHRESULT DAPI IniGetValue(\n    __in_bcount(INI_HANDLE_BYTES) INI_HANDLE piHandle,\n    __in LPCWSTR wzValueName,\n    __deref_out_z LPWSTR* psczValue\n    );\nHRESULT DAPI IniSetValue(\n    __in_bcount(INI_HANDLE_BYTES) INI_HANDLE piHandle,\n    __in LPCWSTR wzValueName,\n    __in_z_opt LPCWSTR wzValue\n    );\nHRESULT DAPI IniWriteFile(\n    __in_bcount(INI_HANDLE_BYTES) INI_HANDLE piHandle,\n    __in_z_opt LPCWSTR wzPath,\n    __in FILE_ENCODING feOverrideEncoding\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/jsonutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"jsonutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    JavaScript Object Notation (JSON) helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nenum JSON_TOKEN\n{\n    JSON_TOKEN_NONE,\n    JSON_TOKEN_ARRAY_START,\n    JSON_TOKEN_ARRAY_VALUE,\n    JSON_TOKEN_ARRAY_END,\n    JSON_TOKEN_OBJECT_START,\n    JSON_TOKEN_OBJECT_KEY,\n    JSON_TOKEN_OBJECT_VALUE,\n    JSON_TOKEN_OBJECT_END,\n    JSON_TOKEN_VALUE,\n};\n\ntypedef struct _JSON_VALUE\n{\n} JSON_VALUE;\n\ntypedef struct _JSON_READER\n{\n    CRITICAL_SECTION cs;\n    LPWSTR sczJson;\n\n    LPWSTR pwz;\n    JSON_TOKEN token;\n} JSON_READER;\n\ntypedef struct _JSON_WRITER\n{\n    CRITICAL_SECTION cs;\n    LPWSTR sczJson;\n\n    JSON_TOKEN* rgTokenStack;\n    DWORD cTokens;\n    DWORD cMaxTokens;\n} JSON_WRITER;\n\n\nDAPI_(HRESULT) JsonInitializeReader(\n    __in_z LPCWSTR wzJson,\n    __in JSON_READER* pReader\n    );\n\nDAPI_(void) JsonUninitializeReader(\n    __in JSON_READER* pReader\n    );\n\nDAPI_(HRESULT) JsonReadNext(\n    __in JSON_READER* pReader,\n    __out JSON_TOKEN* pToken,\n    __out JSON_VALUE* pValue\n    );\n\nDAPI_(HRESULT) JsonReadValue(\n    __in JSON_READER* pReader,\n    __in JSON_VALUE* pValue\n    );\n\nDAPI_(HRESULT) JsonInitializeWriter(\n    __in JSON_WRITER* pWriter\n    );\n\nDAPI_(void) JsonUninitializeWriter(\n    __in JSON_WRITER* pWriter\n    );\n\nDAPI_(HRESULT) JsonWriteBool(\n    __in JSON_WRITER* pWriter,\n    __in BOOL fValue\n    );\n\nDAPI_(HRESULT) JsonWriteNumber(\n    __in JSON_WRITER* pWriter,\n    __in DWORD dwValue\n    );\n\nDAPI_(HRESULT) JsonWriteString(\n    __in JSON_WRITER* pWriter,\n    __in_z LPCWSTR wzValue\n    );\n\nDAPI_(HRESULT) JsonWriteArrayStart(\n    __in JSON_WRITER* pWriter\n    );\n\nDAPI_(HRESULT) JsonWriteArrayEnd(\n    __in JSON_WRITER* pWriter\n    );\n\nDAPI_(HRESULT) JsonWriteObjectStart(\n    __in JSON_WRITER* pWriter\n    );\n\nDAPI_(HRESULT) JsonWriteObjectKey(\n    __in JSON_WRITER* pWriter,\n    __in_z LPCWSTR wzKey\n    );\n\nDAPI_(HRESULT) JsonWriteObjectEnd(\n    __in JSON_WRITER* pWriter\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/locutil.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"locutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for localization helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n#pragma once\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nstruct LOC_STRING\n{\n    LPWSTR wzId;\n    LPWSTR wzText;\n    BOOL bOverridable;\n};\n\nconst int LOC_CONTROL_NOT_SET = INT_MAX;\n\nstruct LOC_CONTROL\n{\n    LPWSTR wzControl;\n    int nX;\n    int nY;\n    int nWidth;\n    int nHeight;\n    LPWSTR wzText;\n};\n\nconst int WIX_LOCALIZATION_LANGUAGE_NOT_SET = INT_MAX;\n\nstruct WIX_LOCALIZATION\n{\n    DWORD dwLangId;\n\n    DWORD cLocStrings;\n    LOC_STRING* rgLocStrings;\n\n    DWORD cLocControls;\n    LOC_CONTROL* rgLocControls;\n};\n\n/********************************************************************\n LocProbeForFile - Searches for a localization file on disk.\n\n*******************************************************************/\nHRESULT DAPI LocProbeForFile(\n    __in_z LPCWSTR wzBasePath,\n    __in_z LPCWSTR wzLocFileName,\n    __in_z_opt LPCWSTR wzLanguage,\n    __inout LPWSTR* psczPath\n    );\n\n/********************************************************************\n LocLoadFromFile - Loads a localization file\n\n*******************************************************************/\nHRESULT DAPI LocLoadFromFile(\n    __in_z LPCWSTR wzWxlFile,\n    __out WIX_LOCALIZATION** ppWixLoc\n    );\n\n/********************************************************************\n LocLoadFromResource - loads a localization file from a module's data\n                       resource.\n\n NOTE: The resource data must be UTF-8 encoded.\n*******************************************************************/\nHRESULT DAPI LocLoadFromResource(\n    __in HMODULE hModule,\n    __in_z LPCSTR szResource,\n    __out WIX_LOCALIZATION** ppWixLoc\n    );\n\n/********************************************************************\n LocFree - free memory allocated when loading a localization file\n\n*******************************************************************/\nvoid DAPI LocFree(\n    __in_opt WIX_LOCALIZATION* pWixLoc\n    );\n\n/********************************************************************\n LocLocalizeString - replace any #(loc.id) in a string with the\n                    correct sub string\n*******************************************************************/\nHRESULT DAPI LocLocalizeString(\n    __in const WIX_LOCALIZATION* pWixLoc,\n    __inout LPWSTR* psczInput\n    );\n\n/********************************************************************\n LocGetControl - returns a control's localization information\n*******************************************************************/\nHRESULT DAPI LocGetControl(\n    __in const WIX_LOCALIZATION* pWixLoc,\n    __in_z LPCWSTR wzId,\n    __out LOC_CONTROL** ppLocControl\n    );\n\n/********************************************************************\n LocGetString - returns a string's localization information\n*******************************************************************/\nextern \"C\" HRESULT DAPI LocGetString(\n    __in const WIX_LOCALIZATION* pWixLoc,\n    __in_z LPCWSTR wzId,\n    __out LOC_STRING** ppLocString\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/logutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"logutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Logging helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define LogExitOnFailure(x, i, f) if (FAILED(x)) { LogErrorId(x, i, NULL, NULL, NULL); ExitTrace(x, f); goto LExit; }\n#define LogExitOnFailure1(x, i, f, s) if (FAILED(x)) { LogErrorId(x, i, s, NULL, NULL); ExitTrace1(x, f, s); goto LExit; }\n#define LogExitOnFailure2(x, i, f, s, t) if (FAILED(x)) { LogErrorId(x, i, s, t, NULL); ExitTrace2(x, f, s, t); goto LExit; }\n#define LogExitOnFailure3(x, i, f, s, t, u) if (FAILED(x)) { LogErrorId(x, i, s, t, u); ExitTrace3(x, f, s, t, u); goto LExit; }\n\n#define LogExitOnRootFailure(x, i, f) if (FAILED(x)) { LogErrorId(x, i, NULL, NULL, NULL); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace(x, f); goto LExit; }\n#define LogExitOnRootFailure1(x, i, f, s) if (FAILED(x)) { LogErrorId(x, i, s, NULL, NULL); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace1(x, f, s); goto LExit; }\n#define LogExitOnRootFailure2(x, i, f, s, t) if (FAILED(x)) { LogErrorId(x, i, s, t, NULL); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace2(x, f, s, t); goto LExit; }\n#define LogExitOnRootFailure3(x, i, f, s, t, u) if (FAILED(x)) { LogErrorId(x, i, s, t, u); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace3(x, f, s, t, u); goto LExit; }\n\ntypedef HRESULT (DAPI *PFN_LOGSTRINGWORKRAW)(\n    __in_z LPCSTR szString,\n    __in_opt LPVOID pvContext\n    );\n\n// enums\n\n// structs\n\n// functions\nBOOL DAPI IsLogInitialized();\n\nBOOL DAPI IsLogOpen();\n\nvoid DAPI LogInitialize(\n    __in HMODULE hModule\n    );\n\nHRESULT DAPI LogOpen(\n    __in_z_opt LPCWSTR wzDirectory,\n    __in_z LPCWSTR wzLog,\n    __in_z_opt LPCWSTR wzPostfix,\n    __in_z_opt LPCWSTR wzExt,\n    __in BOOL fAppend,\n    __in BOOL fHeader,\n    __out_z_opt LPWSTR* psczLogPath\n    );\n\nvoid DAPI LogDisable();\n\nvoid DAPI LogRedirect(\n    __in_opt PFN_LOGSTRINGWORKRAW vpfLogStringWorkRaw,\n    __in_opt LPVOID pvContext\n    );\n\nHRESULT DAPI LogRename(\n    __in_z LPCWSTR wzNewPath\n    );\n\nvoid DAPI LogClose(\n    __in BOOL fFooter\n    );\n\nvoid DAPI LogUninitialize(\n    __in BOOL fFooter\n    );\n\nBOOL DAPI LogIsOpen();\n\nHRESULT DAPI LogSetSpecialParams(\n    __in_z_opt LPCWSTR wzSpecialBeginLine,\n    __in_z_opt LPCWSTR wzSpecialAfterTimeStamp,\n    __in_z_opt LPCWSTR wzSpecialEndLine\n    );\n\nREPORT_LEVEL DAPI LogSetLevel(\n    __in REPORT_LEVEL rl,\n    __in BOOL fLogChange\n    );\n\nREPORT_LEVEL DAPI LogGetLevel();\n\nHRESULT DAPI LogGetPath(\n    __out_ecount_z(cchLogPath) LPWSTR pwzLogPath, \n    __in DWORD cchLogPath\n    );\n\nHANDLE DAPI LogGetHandle();\n\nHRESULT DAPIV LogString(\n    __in REPORT_LEVEL rl,\n    __in_z __format_string LPCSTR szFormat,\n    ...\n    );\n\nHRESULT DAPI LogStringArgs(\n    __in REPORT_LEVEL rl,\n    __in_z __format_string LPCSTR szFormat,\n    __in va_list args\n    );\n\nHRESULT DAPIV LogStringLine(\n    __in REPORT_LEVEL rl,\n    __in_z __format_string LPCSTR szFormat,\n    ...\n    );\n\nHRESULT DAPI LogStringLineArgs(\n    __in REPORT_LEVEL rl,\n    __in_z __format_string LPCSTR szFormat,\n    __in va_list args\n    );\n\nHRESULT DAPI LogIdModuleArgs(\n    __in REPORT_LEVEL rl,\n    __in DWORD dwLogId,\n    __in_opt HMODULE hModule,\n    __in va_list args\n    );\n\n/* \n * Wraps LogIdModuleArgs, so inline to save the function call\n */\n\ninline HRESULT LogId(\n    __in REPORT_LEVEL rl,\n    __in DWORD dwLogId,\n    ...\n    )\n{\n    HRESULT hr = S_OK;\n    va_list args;\n\n    va_start(args, dwLogId);\n    hr = LogIdModuleArgs(rl, dwLogId, NULL, args);\n    va_end(args);\n\n    return hr;\n}\n\n\n/* \n * Wraps LogIdModuleArgs, so inline to save the function call\n */\n \ninline HRESULT LogIdArgs(\n    __in REPORT_LEVEL rl,\n    __in DWORD dwLogId,\n    __in va_list args\n    )\n{\n    return LogIdModuleArgs(rl, dwLogId, NULL, args);\n}\n\nHRESULT DAPIV LogErrorString(\n    __in HRESULT hrError,\n    __in_z __format_string LPCSTR szFormat,\n    ...\n    );\n\nHRESULT DAPI LogErrorStringArgs(\n    __in HRESULT hrError,\n    __in_z __format_string LPCSTR szFormat,\n    __in va_list args\n    );\n\nHRESULT DAPI LogErrorIdModule(\n    __in HRESULT hrError,\n    __in DWORD dwLogId,\n    __in_opt HMODULE hModule,\n    __in_z_opt LPCWSTR wzString1,\n    __in_z_opt LPCWSTR wzString2,\n    __in_z_opt LPCWSTR wzString3\n    );\n\ninline HRESULT LogErrorId(\n    __in HRESULT hrError,\n    __in DWORD dwLogId,\n    __in_z_opt LPCWSTR wzString1,\n    __in_z_opt LPCWSTR wzString2,\n    __in_z_opt LPCWSTR wzString3\n    )\n{\n    return LogErrorIdModule(hrError, dwLogId, NULL, wzString1, wzString2, wzString3);\n}\n\nHRESULT DAPI LogHeader();\n\nHRESULT DAPI LogFooter();\n\nHRESULT LogStringWorkRaw(\n    __in_z LPCSTR szLogData\n    );\n\n// begin the switch of LogXXX to LogStringXXX\n#define Log LogString\n#define LogLine LogStringLine\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/memutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"memutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for memory helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ReleaseMem(p) if (p) { MemFree(p); }\n#define ReleaseNullMem(p) if (p) { MemFree(p); p = NULL; }\n\nHRESULT DAPI MemInitialize();\nvoid DAPI MemUninitialize();\n\nLPVOID DAPI MemAlloc(\n    __in SIZE_T cbSize,\n    __in BOOL fZero\n    );\nLPVOID DAPI MemReAlloc(\n    __in LPVOID pv,\n    __in SIZE_T cbSize,\n    __in BOOL fZero\n    );\nHRESULT DAPI MemEnsureArraySize(\n    __deref_out_bcount(cArray * cbArrayType) LPVOID* ppvArray,\n    __in DWORD cArray,\n    __in SIZE_T cbArrayType,\n    __in DWORD dwGrowthCount\n    );\nHRESULT DAPI MemInsertIntoArray(\n    __deref_out_bcount((cExistingArray + cNumInsertItems) * cbArrayType) LPVOID* ppvArray,\n    __in DWORD dwInsertIndex,\n    __in DWORD cNumInsertItems,\n    __in DWORD cExistingArray,\n    __in SIZE_T cbArrayType,\n    __in DWORD dwGrowthCount\n    );\n\nHRESULT DAPI MemFree(\n    __in LPVOID pv\n    );\nSIZE_T DAPI MemSize(\n    __in LPCVOID pv\n    );\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/metautil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"metautil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    IIS Metabase helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#include <iadmw.h>\n#include <iiscnfg.h>\n#include <iwamreg.h>\n#include <mddefw.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// structs\n\n// prototypes\nHRESULT DAPI MetaFindWebBase(\n    __in IMSAdminBaseW* piMetabase, \n    __in_z LPCWSTR wzIP, \n    __in int iPort, \n    __in_z LPCWSTR wzHeader,\n    __in BOOL fSecure,\n    __out_ecount(cchWebBase) LPWSTR wzWebBase, \n    __in DWORD cchWebBase\n    );\nHRESULT DAPI MetaFindFreeWebBase(\n    __in IMSAdminBaseW* piMetabase, \n    __out_ecount(cchWebBase) LPWSTR wzWebBase, \n    __in DWORD cchWebBase\n    );\n\nHRESULT DAPI MetaOpenKey(\n    __in IMSAdminBaseW* piMetabase, \n    __in METADATA_HANDLE mhKey, \n    __in_z LPCWSTR wzKey,\n    __in DWORD dwAccess,\n    __in DWORD cRetries,\n    __out METADATA_HANDLE* pmh\n    );\nHRESULT DAPI MetaGetValue(\n    __in IMSAdminBaseW* piMetabase, \n    __in METADATA_HANDLE mhKey, \n    __in_z LPCWSTR wzKey, \n    __inout METADATA_RECORD* pmr\n    );\nvoid DAPI MetaFreeValue(\n    __in METADATA_RECORD* pmr\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/osutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"osutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Operating system helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nenum OS_VERSION\n{\n    OS_VERSION_UNKNOWN,\n    OS_VERSION_WINNT,\n    OS_VERSION_WIN2000,\n    OS_VERSION_WINXP,\n    OS_VERSION_WIN2003,\n    OS_VERSION_VISTA,\n    OS_VERSION_WIN2008,\n    OS_VERSION_WIN7,\n    OS_VERSION_WIN2008_R2,\n    OS_VERSION_FUTURE\n};\n\nvoid DAPI OsGetVersion(\n    __out OS_VERSION* pVersion,\n    __out DWORD* pdwServicePack\n    );\nHRESULT DAPI OsCouldRunPrivileged(\n    __out BOOL* pfPrivileged\n    );\nHRESULT DAPI OsIsRunningPrivileged(\n    __out BOOL* pfPrivileged\n    );\nHRESULT DAPI OsIsUacEnabled(\n    __out BOOL* pfUacEnabled\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/pathutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"pathutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for path helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nenum PATH_EXPAND\n{\n    PATH_EXPAND_ENVIRONMENT = 0x0001,\n    PATH_EXPAND_FULLPATH    = 0x0002,\n};\n\n\n/*******************************************************************\n PathCommandLineAppend - appends a command line argument on to a\n    string such that ::CommandLineToArgv() will shred them correctly\n    (i.e. quote arguments with spaces in them).\n********************************************************************/\nDAPI_(HRESULT) PathCommandLineAppend(\n    __deref_out_z LPWSTR* psczCommandLine,\n    __in_z LPCWSTR wzArgument\n    );\n\n/*******************************************************************\n PathFile -  returns a pointer to the file part of the path.\n********************************************************************/\nDAPI_(LPWSTR) PathFile(\n    __in_z LPCWSTR wzPath\n    );\n\n/*******************************************************************\n PathExtension -  returns a pointer to the extension part of the path\n                  (including the dot).\n********************************************************************/\nDAPI_(LPCWSTR) PathExtension(\n    __in_z LPCWSTR wzPath\n    );\n\n/*******************************************************************\n PathGetDirectory - extracts the directory from a path.\n********************************************************************/\nDAPI_(HRESULT) PathGetDirectory(\n    __in_z LPCWSTR wzPath,\n    __out LPWSTR *psczDirectory\n    );\n\n/*******************************************************************\n PathExpand - gets the full path to a file resolving environment\n              variables along the way.\n********************************************************************/\nDAPI_(HRESULT) PathExpand(\n    __out LPWSTR *psczFullPath,\n    __in_z LPCWSTR wzRelativePath,\n    __in DWORD dwResolveFlags\n    );\n\n/*******************************************************************\n PathPrefix - prefixes a full path with \\\\?\\ or \\\\?\\UNC as\n              appropriate.\n********************************************************************/\nDAPI_(HRESULT) PathPrefix(\n    __inout LPWSTR *psczFullPath\n    );\n\n/*******************************************************************\n PathFixedBackslashTerminate - appends a \\ if path does not have it\n                                 already, but fails if the buffer is\n                                 insufficient.\n********************************************************************/\nDAPI_(HRESULT) PathFixedBackslashTerminate(\n    __inout_ecount_z(cchPath) LPWSTR wzPath,\n    __in DWORD_PTR cchPath\n    );\n\n/*******************************************************************\n PathBackslashTerminate - appends a \\ if path does not have it\n                                 already.\n********************************************************************/\nDAPI_(HRESULT) PathBackslashTerminate(\n    __inout LPWSTR* psczPath\n    );\n\n/*******************************************************************\n PathForCurrentProcess - gets the full path to the currently executing\n                         process or (optionally) a module inside the process.\n********************************************************************/\nDAPI_(HRESULT) PathForCurrentProcess(\n    __inout LPWSTR *psczFullPath,\n    __in_opt HMODULE hModule\n    );\n\n/*******************************************************************\n PathRelativeToModule - gets the name of a file in the same \n    directory as the current process or (optionally) a module inside \n    the process\n********************************************************************/\nDAPI_(HRESULT) PathRelativeToModule(\n    __inout LPWSTR *psczFullPath,\n    __in_opt LPCWSTR wzFileName,\n    __in_opt HMODULE hModule\n    );\n\n/*******************************************************************\n PathCreateTempFile\n\n Note: if wzDirectory is null, ::GetTempPath() will be used instead.\n       if wzFileNameTemplate is null, GetTempFileName() will be used instead.\n*******************************************************************/\nDAPI_(HRESULT) PathCreateTempFile(\n    __in_opt LPCWSTR wzDirectory,\n    __in_opt __format_string LPCWSTR wzFileNameTemplate,\n    __in DWORD dwUniqueCount,\n    __in DWORD dwFileAttributes,\n    __out_opt LPWSTR* psczTempFile,\n    __out_opt HANDLE* phTempFile\n    );\n\n/*******************************************************************\n PathCreateTimeBasedTempFile - creates an empty temp file based on current\n                           system time\n********************************************************************/\nDAPI_(HRESULT) PathCreateTimeBasedTempFile(\n    __in_z_opt LPCWSTR wzDirectory,\n    __in_z LPCWSTR wzPrefix,\n    __in_z_opt LPCWSTR wzPostfix,\n    __in_z LPCWSTR wzExtension,\n    __deref_opt_out_z LPWSTR* psczTempFile,\n    __out_opt HANDLE* phTempFile\n    );\n\n/*******************************************************************\n PathCreateTempDirectory\n\n Note: if wzDirectory is null, ::GetTempPath() will be used instead.\n*******************************************************************/\nDAPI_(HRESULT) PathCreateTempDirectory(\n    __in_opt LPCWSTR wzDirectory,\n    __in __format_string LPCWSTR wzDirectoryNameTemplate,\n    __in DWORD dwUniqueCount,\n    __out LPWSTR* psczTempDirectory\n    );\n\n/*******************************************************************\n PathGetKnownFolder - returns the path to a well-known shell folder\n\n*******************************************************************/\nDAPI_(HRESULT) PathGetKnownFolder(\n    __in int csidl,\n    __out LPWSTR* psczKnownFolder\n    );\n\n/*******************************************************************\n PathIsAbsolute - returns true if the path is absolute; false \n    otherwise.\n*******************************************************************/\nDAPI_(BOOL) PathIsAbsolute(\n    __in_z LPCWSTR wzPath\n    );\n\n/*******************************************************************\n PathConcat - like .NET's Path.Combine, lets you build up a path\n    one piece -- file or directory -- at a time.\n*******************************************************************/\nDAPI_(HRESULT) PathConcat(\n    __in_opt LPCWSTR wzPath1,\n    __in_opt LPCWSTR wzPath2,\n    __deref_out_z LPWSTR* psczCombined\n    );\n\n/*******************************************************************\n PathEnsureQuoted - ensures that a path is quoted; optionally,\n     this function also terminates a directory with a backslash\n     if it is not already.\n*******************************************************************/\nDAPI_(HRESULT) PathEnsureQuoted(\n    __inout LPWSTR* ppszPath,\n    __in BOOL fDirectory\n    );\n\n/*******************************************************************\n PathCompare - compares the fully expanded path of the two paths using\n               ::CompareStringW().\n*******************************************************************/\nDAPI_(HRESULT) PathCompare(\n    __in_z LPCWSTR wzPath1,\n    __in_z LPCWSTR wzPath2,\n    __out int* pnResult\n    );\n\n/*******************************************************************\n PathCompress - sets the compression state on an existing file or \n                directory. A no-op on file systems that don't \n                support compression.\n*******************************************************************/\nDAPI_(HRESULT) PathCompress(\n    __in_z LPCWSTR wzPath\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/perfutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"perfutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Performance helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// structs\n\n\n// functions\nvoid DAPI PerfInitialize(\n    );\nvoid DAPI PerfClickTime(\n    __out_opt LARGE_INTEGER* pliElapsed\n    );\ndouble DAPI PerfConvertToSeconds(\n    __in const LARGE_INTEGER* pli\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/polcutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"polcutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for Policy utility functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/********************************************************************\nPolcReadNumber - reads a number from policy.\n\nNOTE: S_FALSE returned if policy not set.\nNOTE: out is set to default on S_FALSE or any error.\n********************************************************************/\nHRESULT DAPI PolcReadNumber(\n    __in_z LPCWSTR wzPolicyPath,\n    __in_z LPCWSTR wzPolicyName,\n    __in DWORD dwDefault,\n    __out DWORD* pdw\n    );\n\n/********************************************************************\nPolcReadString - reads a string from policy.\n\nNOTE: S_FALSE returned if policy not set.\nNOTE: out is set to default on S_FALSE or any error.\n********************************************************************/\nHRESULT DAPI PolcReadString(\n    __in_z LPCWSTR wzPolicyPath,\n    __in_z LPCWSTR wzPolicyName,\n    __in_z_opt LPCWSTR wzDefault,\n    __deref_out_z LPWSTR* pscz\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/procutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"procutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for process helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// structs\ntypedef struct _PROC_FILESYSTEMREDIRECTION\n{\n    BOOL fDisabled;\n    LPVOID pvRevertState;\n} PROC_FILESYSTEMREDIRECTION;\n\nHRESULT DAPI ProcElevated(\n    __in HANDLE hProcess,\n    __out BOOL* pfElevated\n    );\n\nHRESULT DAPI ProcWow64(\n    __in HANDLE hProcess,\n    __out BOOL* pfWow64\n    );\nHRESULT DAPI ProcDisableWowFileSystemRedirection(\n    __in PROC_FILESYSTEMREDIRECTION* pfsr\n    );\nHRESULT DAPI ProcRevertWowFileSystemRedirection(\n    __in PROC_FILESYSTEMREDIRECTION* pfsr\n    );\n\nHRESULT DAPI ProcExec(\n    __in_z LPCWSTR wzExecutablePath,\n    __in_z_opt LPCWSTR wzCommandLine,\n    __in int nCmdShow,\n    __out HANDLE *phProcess\n    );\nHRESULT DAPI ProcExecute(\n    __in_z LPWSTR wzCommand,\n    __out HANDLE *phProcess,\n    __out_opt HANDLE *phChildStdIn,\n    __out_opt HANDLE *phChildStdOutErr\n    );\nHRESULT DAPI ProcWaitForCompletion(\n    __in HANDLE hProcess,\n    __in DWORD dwTimeout,\n    __out DWORD *pReturnCode\n    );\nHRESULT DAPI ProcWaitForIds(\n    __in_ecount(cProcessIds) const DWORD* pdwProcessIds,\n    __in DWORD cProcessIds,\n    __in DWORD dwMilliseconds\n    );\nHRESULT DAPI ProcCloseIds(\n    __in_ecount(cProcessIds) const DWORD* pdwProcessIds,\n    __in DWORD cProcessIds\n    );\n\n// following code in proc2utl.cpp due to dependency on PSAPI.DLL.\nHRESULT DAPI ProcFindAllIdsFromExeName(\n    __in_z LPCWSTR wzExeName,\n    __out DWORD** ppdwProcessIds,\n    __out DWORD* pcProcessIds\n    );\n\n// following code in proc3utl.cpp due to dependency on Wtsapi32.DLL.\nHRESULT DAPI ProcExecuteAsInteractiveUser(\n    __in_z LPCWSTR wzExecutablePath,\n    __in_z LPCWSTR wzCommand,\n    __out HANDLE *phProcess\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/regutil.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"regutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Registry helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n#define ReleaseRegKey(h) if (h) { ::RegCloseKey(h); h = NULL; }\n\nenum REG_KEY_BITNESS\n{\n    REG_KEY_DEFAULT = 0,\n    REG_KEY_32BIT = 1,\n    REG_KEY_64BIT = 2\n};\n\ntypedef LSTATUS (APIENTRY *PFN_REGCREATEKEYEXW)(\n    __in HKEY hKey,\n    __in LPCWSTR lpSubKey,\n    __reserved DWORD Reserved,\n    __in_opt LPWSTR lpClass,\n    __in DWORD dwOptions,\n    __in REGSAM samDesired,\n    __in_opt CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,\n    __out PHKEY phkResult,\n    __out_opt LPDWORD lpdwDisposition\n    );\ntypedef LSTATUS (APIENTRY *PFN_REGOPENKEYEXW)(\n    __in HKEY hKey,\n    __in_opt LPCWSTR lpSubKey,\n    __reserved DWORD ulOptions,\n    __in REGSAM samDesired,\n    __out PHKEY phkResult\n    );\ntypedef LSTATUS (APIENTRY *PFN_REGDELETEKEYEXW)(\n    __in HKEY hKey,\n    __in LPCWSTR lpSubKey,\n    __in REGSAM samDesired,\n    __reserved DWORD Reserved\n    );\ntypedef LSTATUS (APIENTRY *PFN_REGDELETEKEYW)(\n    __in HKEY hKey,\n    __in LPCWSTR lpSubKey\n    );\ntypedef LSTATUS (APIENTRY *PFN_REGENUMKEYEXW)(\n    __in         HKEY hKey,\n    __in         DWORD dwIndex,\n    __out        LPWSTR lpName,\n    __inout      LPDWORD lpcName,\n    __reserved   LPDWORD lpReserved,\n    __inout      LPWSTR lpClass,\n    __inout_opt  LPDWORD lpcClass,\n    __out_opt    PFILETIME lpftLastWriteTime\n    );\ntypedef LSTATUS (APIENTRY *PFN_REGENUMVALUEW)(\n    __in         HKEY hKey,\n    __in         DWORD dwIndex,\n    __out        LPWSTR lpValueName,\n    __inout      LPDWORD lpcchValueName,\n    __reserved   LPDWORD lpReserved,\n    __out_opt    LPDWORD lpType,\n    __out_opt    LPBYTE lpData,\n    __out_opt    LPDWORD lpcbData\n    );\ntypedef LSTATUS (APIENTRY *PFN_REGQUERYINFOKEYW)(\n    __in         HKEY hKey,\n    __out        LPWSTR lpClass,\n    __inout_opt  LPDWORD lpcClass,\n    __reserved   LPDWORD lpReserved,\n    __out_opt    LPDWORD lpcSubKeys,\n    __out_opt    LPDWORD lpcMaxSubKeyLen,\n    __out_opt    LPDWORD lpcMaxClassLen,\n    __out_opt    LPDWORD lpcValues,\n    __out_opt    LPDWORD lpcMaxValueNameLen,\n    __out_opt    LPDWORD lpcMaxValueLen,\n    __out_opt    LPDWORD lpcbSecurityDescriptor,\n    __out_opt    PFILETIME lpftLastWriteTime\n    );\ntypedef LSTATUS (APIENTRY *PFN_REGQUERYVALUEEXW)(\n    __in HKEY hKey,\n    __in_opt LPCWSTR lpValueName,\n    __reserved LPDWORD lpReserved,\n    __out_opt LPDWORD lpType,\n    __out_bcount_part_opt(*lpcbData, *lpcbData) __out_data_source(REGISTRY) LPBYTE lpData,\n    __inout_opt LPDWORD lpcbData\n    );\ntypedef LSTATUS (APIENTRY *PFN_REGSETVALUEEXW)(\n    __in HKEY hKey,\n    __in_opt LPCWSTR lpValueName,\n    __reserved DWORD Reserved,\n    __in DWORD dwType,\n    __in_bcount_opt(cbData) CONST BYTE* lpData,\n    __in DWORD cbData\n    );\ntypedef LSTATUS (APIENTRY *PFN_REGDELETEVALUEW)(\n    __in HKEY hKey,\n    __in_opt LPCWSTR lpValueName\n    );\n\nHRESULT DAPI RegInitialize();\nvoid DAPI RegUninitialize();\n\nvoid DAPI RegFunctionOverride(\n    __in_opt PFN_REGCREATEKEYEXW pfnRegCreateKeyExW,\n    __in_opt PFN_REGOPENKEYEXW pfnRegOpenKeyExW,\n    __in_opt PFN_REGDELETEKEYEXW pfnRegDeleteKeyExW,\n    __in_opt PFN_REGENUMKEYEXW pfnRegEnumKeyExW,\n    __in_opt PFN_REGENUMVALUEW pfnRegEnumValueW,\n    __in_opt PFN_REGQUERYINFOKEYW pfnRegQueryInfoKeyW,\n    __in_opt PFN_REGQUERYVALUEEXW pfnRegQueryValueExW,\n    __in_opt PFN_REGSETVALUEEXW pfnRegSetValueExW,\n    __in_opt PFN_REGDELETEVALUEW pfnRegDeleteValueW\n    );\nHRESULT DAPI RegCreate(\n    __in HKEY hkRoot,\n    __in_z LPCWSTR wzSubKey,\n    __in DWORD dwAccess,\n    __out HKEY* phk\n    );\nHRESULT DAPI RegCreateEx(\n    __in HKEY hkRoot,\n    __in_z LPCWSTR wzSubKey,\n    __in DWORD dwAccess,\n    __in BOOL fVolatile,\n    __in_opt SECURITY_ATTRIBUTES* pSecurityAttributes,\n    __out HKEY* phk,\n    __out_opt BOOL* pfCreated\n    );\nHRESULT DAPI RegOpen(\n    __in HKEY hkRoot,\n    __in_z LPCWSTR wzSubKey,\n    __in DWORD dwAccess,\n    __out HKEY* phk\n    );\nHRESULT DAPI RegDelete(\n    __in HKEY hkRoot,\n    __in_z LPCWSTR wzSubKey,\n    __in REG_KEY_BITNESS kbKeyBitness,\n    __in BOOL fDeleteTree\n    );\nHRESULT DAPI RegKeyEnum(\n    __in HKEY hk,\n    __in DWORD dwIndex,\n    __deref_out_z LPWSTR* psczKey\n    );\nHRESULT DAPI RegValueEnum(\n    __in HKEY hk,\n    __in DWORD dwIndex,\n    __deref_out_z LPWSTR* psczName,\n    __out_opt DWORD *pdwType\n    );\nHRESULT DAPI RegReadBinary(\n    __in HKEY hk,\n    __in_z_opt LPCWSTR wzName,\n    __deref_out_bcount_opt(*pcbBuffer) BYTE** ppbBuffer,\n    __out SIZE_T *pcbBuffer\n     );\nHRESULT DAPI RegReadString(\n    __in HKEY hk,\n    __in_z_opt LPCWSTR wzName,\n    __deref_out_z LPWSTR* psczValue\n    );\nHRESULT DAPI RegReadStringArray(\n    __in HKEY hk,\n    __in_z_opt LPCWSTR wzName,\n    __deref_out_ecount_opt(pcStrings) LPWSTR** prgsczStrings,\n    __out DWORD *pcStrings\n    );\nHRESULT DAPI RegReadVersion(\n    __in HKEY hk,\n    __in_z_opt LPCWSTR wzName,\n    __out DWORD64* pdw64Version\n    );\nHRESULT DAPI RegReadNumber(\n    __in HKEY hk,\n    __in_z_opt LPCWSTR wzName,\n    __out DWORD* pdwValue\n    );\nHRESULT DAPI RegReadQword(\n    __in HKEY hk,\n    __in_z_opt LPCWSTR wzName,\n    __out DWORD64* pqwValue\n    );\nHRESULT DAPI RegWriteBinary(\n    __in HKEY hk,\n    __in_z_opt LPCWSTR wzName,\n    __in_bcount(cbBuffer) const BYTE *pbBuffer,\n    __in DWORD cbBuffer\n    );\nHRESULT DAPI RegWriteString(\n    __in HKEY hk,\n    __in_z_opt LPCWSTR wzName,\n    __in_z_opt LPCWSTR wzValue\n    );\nHRESULT DAPI RegWriteStringArray(\n    __in HKEY hk,\n    __in_z_opt LPCWSTR wzName,\n    __in_ecount(cValues) LPWSTR *rgwzStrings,\n    __in DWORD cStrings\n    );\nHRESULT DAPI RegWriteStringFormatted(\n    __in HKEY hk,\n    __in_z_opt LPCWSTR wzName,\n    __in __format_string LPCWSTR szFormat,\n    ...\n    );\nHRESULT DAPI RegWriteNumber(\n    __in HKEY hk,\n    __in_z_opt LPCWSTR wzName,\n    __in DWORD dwValue\n    );\nHRESULT DAPI RegWriteQword(\n    __in HKEY hk,\n    __in_z_opt LPCWSTR wzName,\n    __in DWORD64 qwValue\n    );\nHRESULT DAPI RegQueryKey(\n    __in HKEY hk,\n    __out_opt DWORD* pcSubKeys,\n    __out_opt DWORD* pcValues\n    );\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/resrutil.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"resrutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Resource read helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nHRESULT DAPI ResGetStringLangId(\n    __in_opt LPCWSTR wzPath,\n    __in UINT uID,\n    __out WORD *pwLangId\n    );\n\nHRESULT DAPI ResReadString(\n    __in HINSTANCE hinst,\n    __in UINT uID,\n    __deref_out_z LPWSTR* ppwzString\n    );\n\nHRESULT DAPI ResReadStringAnsi(\n    __in HINSTANCE hinst,\n    __in UINT uID,\n    __deref_out_z LPSTR* ppszString\n    );\n\nHRESULT DAPI ResReadData(\n    __in_opt HINSTANCE hinst,\n    __in_z LPCSTR szDataName,\n    __deref_out_bcount(*pcb) PVOID *ppv,\n    __out DWORD *pcb\n    );\n\nHRESULT DAPI ResExportDataToFile(\n    __in_z LPCSTR szDataName,\n    __in_z LPCWSTR wzTargetFile,\n    __in DWORD dwCreationDisposition\n    );\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/reswutil.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"reswutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Resource writer helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nHRESULT DAPI ResWriteString(\n    __in_z LPCWSTR wzResourceFile,\n    __in DWORD dwDataId,\n    __in_z LPCWSTR wzData,\n    __in WORD wLangId\n    );\n\nHRESULT DAPI ResWriteData(\n    __in_z LPCWSTR wzResourceFile,\n    __in_z LPCSTR szDataName,\n    __in PVOID pData,\n    __in DWORD cbData\n    );\n\nHRESULT DAPI ResImportDataFromFile(\n    __in_z LPCWSTR wzTargetFile,\n    __in_z LPCWSTR wzSourceFile,\n    __in_z LPCSTR szDataName\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/rexutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"rexutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Resource Cabinet Extract Utilities\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#include <sys\\stat.h>\n#include <fdi.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// defines\n#define FILETABLESIZE 40\n\n// structs\nstruct MEM_FILE \n{\n    LPCBYTE vpStart;\n    UINT  uiCurrent;\n    UINT  uiLength;\n};\n\nenum FAKE_FILE_TYPE { NORMAL_FILE, MEMORY_FILE };\n\ntypedef HRESULT (*REX_CALLBACK_PROGRESS)(BOOL fBeginFile, LPCWSTR wzFileId, LPVOID pvContext);\ntypedef VOID (*REX_CALLBACK_WRITE)(UINT cb);\n\n\nstruct FAKE_FILE // used __in internal file table\n{\n    BOOL fUsed;\n    FAKE_FILE_TYPE fftType;\n    MEM_FILE mfFile; // State for memory file\n    HANDLE hFile; // Handle for disk  file\n};\n\n// functions\nHRESULT RexInitialize();\nvoid RexUninitialize();\n\nHRESULT RexExtract(\n    __in_z LPCSTR szResource,\n    __in_z LPCWSTR wzExtractId,\n    __in_z LPCWSTR wzExtractDir,\n    __in_z LPCWSTR wzExtractName,\n    __in REX_CALLBACK_PROGRESS pfnProgress,\n    __in REX_CALLBACK_WRITE pfnWrite,\n    __in LPVOID pvContext\n    );\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/rmutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"rmutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for Restart Manager utility functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct _RMU_SESSION *PRMU_SESSION;\n\nHRESULT DAPI RmuJoinSession(\n    __out PRMU_SESSION *ppSession,\n    __in_z LPCWSTR wzSessionKey\n    );\n\nHRESULT DAPI RmuAddFile(\n    __in PRMU_SESSION pSession,\n    __in_z LPCWSTR wzPath\n    );\n\nHRESULT DAPI RmuAddProcessById(\n    __in PRMU_SESSION pSession,\n    __in DWORD dwProcessId\n    );\n\nHRESULT DAPI RmuAddProcessesByName(\n    __in PRMU_SESSION pSession,\n    __in_z LPCWSTR wzProcessName\n    );\n\nHRESULT DAPI RmuAddService(\n    __in PRMU_SESSION pSession,\n    __in_z LPCWSTR wzServiceName\n    );\n\nHRESULT DAPI RmuRegisterResources(\n    __in PRMU_SESSION pSession\n    );\n\nHRESULT DAPI RmuEndSession(\n    __in PRMU_SESSION pSession\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/rssutil.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"rssutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    RSS helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ReleaseRssChannel(p) if (p) { RssFreeChannel(p); }\n#define ReleaseNullRssChannel(p) if (p) { RssFreeChannel(p); p = NULL; }\n\n\nstruct RSS_UNKNOWN_ATTRIBUTE\n{\n    LPWSTR wzNamespace;\n    LPWSTR wzAttribute;\n    LPWSTR wzValue;\n\n    RSS_UNKNOWN_ATTRIBUTE* pNext;\n};\n\nstruct RSS_UNKNOWN_ELEMENT\n{\n    LPWSTR wzNamespace;\n    LPWSTR wzElement;\n    LPWSTR wzValue;\n\n    RSS_UNKNOWN_ATTRIBUTE* pAttributes;\n    RSS_UNKNOWN_ELEMENT* pNext;\n};\n\nstruct RSS_ITEM\n{\n    LPWSTR wzTitle;\n    LPWSTR wzLink;\n    LPWSTR wzDescription;\n\n    LPWSTR wzGuid;\n    FILETIME ftPublished;\n\n    LPWSTR wzEnclosureUrl;\n    DWORD dwEnclosureSize;\n    LPWSTR wzEnclosureType;\n\n    RSS_UNKNOWN_ELEMENT* pUnknownElements;\n};\n\nstruct RSS_CHANNEL\n{\n    LPWSTR wzTitle;\n    LPWSTR wzLink;\n    LPWSTR wzDescription;\n    DWORD dwTimeToLive;\n\n    RSS_UNKNOWN_ELEMENT* pUnknownElements;\n\n    DWORD cItems;\n    RSS_ITEM rgItems[1];\n};\n\nHRESULT DAPI RssInitialize(\n    );\n\nvoid DAPI RssUninitialize(\n    );\n\nHRESULT DAPI RssParseFromString(\n    __in_z LPCWSTR wzRssString,\n    __out RSS_CHANNEL **ppChannel\n    );\n\nHRESULT DAPI RssParseFromFile(\n    __in_z LPCWSTR wzRssFile,\n    __out RSS_CHANNEL **ppChannel\n    );\n\n// Adding this until we have the updated specstrings.h\n#ifndef __in_xcount\n#define __in_xcount(size) \n#endif\n\nvoid DAPI RssFreeChannel(\n    __in_xcount(pChannel->cItems) RSS_CHANNEL *pChannel\n    );\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/sceutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"sceutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for SQL Compact Edition helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <sqlce_oledb.h>\n#include <sqlce_sync.h>\n#include <sqlce_err.h>\n\ntypedef void* SCE_DATABASE_HANDLE;\ntypedef void* SCE_ROW_HANDLE;\ntypedef void* SCE_QUERY_HANDLE;\ntypedef void* SCE_QUERY_RESULTS_HANDLE;\n\nextern const int SCE_ROW_HANDLE_BYTES;\nextern const int SCE_QUERY_HANDLE_BYTES;\nextern const int SCE_QUERY_RESULTS_HANDLE_BYTES;\n\n#define ReleaseSceRow(prrh) if (prrh) { SceFreeRow(prrh); }\n#define ReleaseNullSceRow(prrh) if (prrh) { SceFreeRow(prrh); prrh = NULL; }\n#define ReleaseSceQuery(pqh) if (pqh) { SceFreeQuery(pqh); }\n#define ReleaseNullSceQuery(pqh) if (pqh) { SceFreeQuery(pqh); pqh = NULL; }\n#define ReleaseSceQueryResults(pqh) if (pqh) { SceFreeQueryResults(pqh); }\n#define ReleaseNullSceQueryResults(pqh) if (pqh) { SceFreeQueryResults(pqh); pqh = NULL; }\n\nstruct SCE_COLUMN_SCHEMA\n{\n    LPCWSTR wzName;\n    DBTYPE dbtColumnType;\n    DWORD dwLength;\n    BOOL fPrimaryKey; // If this column is the primary key\n    BOOL fNullable;\n    BOOL fAutoIncrement;\n\n    LPWSTR wzRelationName;\n    DWORD dwForeignKeyTable;\n    DWORD dwForeignKeyColumn;\n};\n\nstruct SCE_INDEX_SCHEMA\n{\n    LPWSTR wzName;\n\n    DWORD *rgColumns;\n    DWORD cColumns;\n};\n\nstruct SCE_TABLE_SCHEMA\n{\n    LPCWSTR wzName;\n    DWORD cColumns;\n    SCE_COLUMN_SCHEMA *rgColumns;\n\n    DWORD cIndexes;\n    SCE_INDEX_SCHEMA *rgIndexes;\n\n    // Internal to SCEUtil - consumers shouldn't access or modify\n    // TODO: enforce / hide in a handle of some sort?\n    IRowset *pIRowset;\n    IRowsetChange *pIRowsetChange;\n};\n\nstruct SCE_DATABASE_SCHEMA\n{\n    DWORD cTables;\n    SCE_TABLE_SCHEMA *rgTables;\n};\n\nstruct SCE_DATABASE\n{\n    SCE_DATABASE_HANDLE sdbHandle;\n    SCE_DATABASE_SCHEMA *pdsSchema;\n};\n\nHRESULT DAPI SceCreateDatabase(\n    __in_z LPCWSTR sczFile,\n    __deref_out SCE_DATABASE **ppDatabase\n    );\nHRESULT DAPI SceOpenDatabase(\n    __in_z LPCWSTR sczFile,\n    __in LPCWSTR wzSchemaType,\n    __in DWORD dwExpectedVersion,\n    __deref_out SCE_DATABASE **ppDatabase,\n    __in BOOL fReadOnly\n    );\nHRESULT DAPI SceEnsureDatabase(\n    __in_z LPCWSTR sczFile,\n    __in LPCWSTR wzSchemaType,\n    __in DWORD dwExpectedVersion,\n    __in SCE_DATABASE_SCHEMA *pdsSchema,\n    __deref_out SCE_DATABASE **ppDatabase\n    );\nHRESULT DAPI SceIsTableEmpty(\n    __in SCE_DATABASE *pDatabase,\n    __in DWORD dwTableIndex,\n    __out BOOL *pfEmpty\n    );\nHRESULT DAPI SceGetFirstRow(\n    __in SCE_DATABASE *pDatabase,\n    __in DWORD dwTableIndex,\n    __deref_out_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE *pRowHandle\n    );\nHRESULT DAPI SceGetNextRow(\n    __in SCE_DATABASE *pDatabase,\n    __in DWORD dwTableIndex,\n    __deref_out_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE *pRowHandle\n    );\nHRESULT DAPI SceBeginTransaction(\n    __in SCE_DATABASE *pDatabase\n    );\nHRESULT DAPI SceCommitTransaction(\n    __in SCE_DATABASE *pDatabase\n    );\nHRESULT DAPI SceRollbackTransaction(\n    __in SCE_DATABASE *pDatabase\n    );\nHRESULT DAPI SceDeleteRow(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE *pRowHandle\n    );\nHRESULT DAPI ScePrepareInsert(\n    __in SCE_DATABASE *pDatabase,\n    __in DWORD dwTableIndex,\n    __deref_out_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE *pRowHandle\n    );\nHRESULT DAPI SceFinishUpdate(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowHandle\n    );\nHRESULT DAPI SceSetColumnBinary(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowHandle,\n    __in DWORD dwColumnIndex,\n    __in_bcount(cbBuffer) const BYTE* pbBuffer,\n    __in SIZE_T cbBuffer\n    );\nHRESULT DAPI SceSetColumnDword(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowHandle,\n    __in DWORD dwColumnIndex,\n    __in const DWORD dwValue\n    );\nHRESULT DAPI SceSetColumnQword(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowHandle,\n    __in DWORD dwColumnIndex,\n    __in const DWORD64 qwValue\n    );\nHRESULT DAPI SceSetColumnBool(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowHandle,\n    __in DWORD dwColumnIndex,\n    __in const BOOL fValue\n    );\nHRESULT DAPI SceSetColumnString(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowHandle,\n    __in DWORD dwColumnIndex,\n    __in_z_opt LPCWSTR wzValue\n    );\nHRESULT DAPI SceSetColumnSystemTime(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowHandle,\n    __in DWORD dwColumnIndex,\n    __in const SYSTEMTIME *pst\n    );\nHRESULT DAPI SceSetColumnEmpty(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowHandle,\n    __in DWORD dwColumnIndex\n    );\nHRESULT DAPI SceGetColumnBinary(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowReadHandle,\n    __in DWORD dwColumnIndex,\n    __out_opt BYTE **ppbBuffer,\n    __inout SIZE_T *pcbBuffer\n    );\nHRESULT DAPI SceGetColumnDword(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowReadHandle,\n    __in DWORD dwColumnIndex,\n    __out DWORD *pdwValue\n    );\nHRESULT DAPI SceGetColumnQword(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowReadHandle,\n    __in DWORD dwColumnIndex,\n    __out DWORD64 *pqwValue\n    );\nHRESULT DAPI SceGetColumnBool(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowReadHandle,\n    __in DWORD dwColumnIndex,\n    __out BOOL *pfValue\n    );\nHRESULT DAPI SceGetColumnString(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowReadHandle,\n    __in DWORD dwColumnIndex,\n    __out_z LPWSTR *psczValue\n    );\nHRESULT DAPI SceGetColumnSystemTime(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowReadHandle,\n    __in DWORD dwColumnIndex,\n    __out SYSTEMTIME *pst\n    );\nHRESULT DAPI SceBeginQuery(\n    __in SCE_DATABASE *pDatabase,\n    __in DWORD dwTableIndex,\n    __in DWORD dwIndex,\n    __deref_out_bcount(SCE_QUERY_HANDLE_BYTES) SCE_QUERY_HANDLE *psqhHandle\n    );\nHRESULT DAPI SceSetQueryColumnBinary(\n    __in_bcount(SCE_QUERY_BYTES) SCE_QUERY_HANDLE sqhHandle,\n    __in_bcount(cbBuffer) const BYTE* pbBuffer,\n    __in SIZE_T cbBuffer\n    );\nHRESULT DAPI SceSetQueryColumnDword(\n    __in_bcount(SCE_QUERY_BYTES) SCE_QUERY_HANDLE sqhHandle,\n    __in const DWORD dwValue\n    );\nHRESULT DAPI SceSetQueryColumnQword(\n    __in_bcount(SCE_QUERY_BYTES) SCE_QUERY_HANDLE sqhHandle,\n    __in const DWORD64 qwValue\n    );\nHRESULT DAPI SceSetQueryColumnBool(\n    __in_bcount(SCE_QUERY_BYTES) SCE_QUERY_HANDLE sqhHandle,\n    __in const BOOL fValue\n    );\nHRESULT DAPI SceSetQueryColumnString(\n    __in_bcount(SCE_QUERY_BYTES) SCE_QUERY_HANDLE sqhHandle,\n    __in_z_opt LPCWSTR wzString\n    );\nHRESULT DAPI SceSetQueryColumnSystemTime(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowHandle,\n    __in const SYSTEMTIME *pst\n    );\nHRESULT DAPI SceSetQueryColumnEmpty(\n    __in_bcount(SCE_QUERY_BYTES) SCE_QUERY_HANDLE sqhHandle\n    );\nHRESULT DAPI SceRunQueryExact(\n    __in_bcount(SCE_QUERY_BYTES) SCE_QUERY_HANDLE *psqhHandle,\n    __deref_out_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE *pRowHandle\n    );\nHRESULT DAPI SceRunQueryRange(\n    __in_bcount(SCE_QUERY_BYTES) SCE_QUERY_HANDLE *psqhHandle,\n    __deref_out_bcount(SCE_QUERY_RESULTS_BYTES) SCE_QUERY_RESULTS_HANDLE *psqrhHandle\n    );\nHRESULT DAPI SceGetNextResultRow(\n    __in_bcount(SCE_QUERY_RESULTS_BYTES) SCE_QUERY_RESULTS_HANDLE sqrhHandle,\n    __deref_out_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE *pRowHandle\n    );\nvoid DAPI SceCloseTable(\n    __in SCE_TABLE_SCHEMA *pTable\n    );\nHRESULT DAPI SceCloseDatabase(\n    __in SCE_DATABASE *pDatabase\n    );\nvoid DAPI SceFreeRow(\n    __in_bcount(SCE_ROW_HANDLE_BYTES) SCE_ROW_HANDLE rowReadHandle\n    );\nvoid DAPI SceFreeQuery(\n    __in_bcount(SCE_QUERY_BYTES) SCE_QUERY_HANDLE sqhHandle\n    );\nvoid DAPI SceFreeQueryResults(\n    __in_bcount(SCE_QUERY_RESULTS_BYTES) SCE_QUERY_RESULTS_HANDLE sqrhHandle\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/shelutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"shelutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for shell helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifndef REFKNOWNFOLDERID\n#define REFKNOWNFOLDERID REFGUID\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef BOOL (STDAPICALLTYPE *PFN_SHELLEXECUTEEXW)(\n    __inout LPSHELLEXECUTEINFOW lpExecInfo\n    );\n\nvoid DAPI ShelFunctionOverride(\n    __in_opt PFN_SHELLEXECUTEEXW pfnShellExecuteExW\n    );\nHRESULT DAPI ShelExec(\n    __in_z LPCWSTR wzTargetPath,\n    __in_opt LPCWSTR wzParameters,\n    __in_opt LPCWSTR wzVerb,\n    __in_opt LPCWSTR wzWorkingDirectory,\n    __in int nShowCmd,\n    __in_opt HWND hwndParent,\n    __out_opt HANDLE* phProcess\n    );\nHRESULT DAPI ShelExecUnelevated(\n    __in_z LPCWSTR wzTargetPath,\n    __in_z_opt LPCWSTR wzParameters,\n    __in_z_opt LPCWSTR wzVerb,\n    __in_z_opt LPCWSTR wzWorkingDirectory,\n    __in int nShowCmd\n    );\nHRESULT DAPI ShelGetFolder(\n    __out_z LPWSTR* psczFolderPath,\n    __in int csidlFolder\n    );\nHRESULT DAPI ShelGetKnownFolder(\n    __out_z LPWSTR* psczFolderPath,\n    __in REFKNOWNFOLDERID rfidFolder\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/sqlutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"sqlutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    SQL helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#include <cguid.h>\n#include <oledberr.h>\n#include <sqloledb.h>\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// Adding this until the SQL annotations are published to specstrings.h\n#ifndef __sql_command\n#define __sql_command\n#endif\n\n// structs\nstruct SQL_FILESPEC\n{\n    WCHAR wzName[MAX_PATH];\n    WCHAR wzFilename[MAX_PATH];\n    WCHAR wzSize[MAX_PATH];\n    WCHAR wzMaxSize[MAX_PATH];\n    WCHAR wzGrow[MAX_PATH];\n};\n\n\n// functions\nHRESULT DAPI SqlConnectDatabase(\n    __in_z LPCWSTR wzServer, \n    __in_z LPCWSTR wzInstance,\n    __in_z LPCWSTR wzDatabase, \n    __in BOOL fIntegratedAuth, \n    __in_z LPCWSTR wzUser, \n    __in_z LPCWSTR wzPassword, \n    __out IDBCreateSession** ppidbSession\n    );\nHRESULT DAPI SqlStartTransaction(\n    __in IDBCreateSession* pidbSession,\n    __out IDBCreateCommand** ppidbCommand,\n    __out ITransaction** ppit\n    );\nHRESULT DAPI SqlEndTransaction(\n    __in ITransaction* pit,\n    __in BOOL fCommit\n    );\nHRESULT DAPI SqlDatabaseExists(\n    __in_z LPCWSTR wzServer,\n    __in_z LPCWSTR wzInstance,\n    __in_z LPCWSTR wzDatabase,\n    __in BOOL fIntegratedAuth,\n    __in_z LPCWSTR wzUser,\n    __in_z LPCWSTR wzPassword,\n    __out_opt BSTR* pbstrErrorDescription\n    );\nHRESULT DAPI SqlSessionDatabaseExists(\n    __in IDBCreateSession* pidbSession,\n    __in_z LPCWSTR wzDatabase,\n    __out_opt BSTR* pbstrErrorDescription\n    );\nHRESULT DAPI SqlDatabaseEnsureExists(\n    __in_z LPCWSTR wzServer,\n    __in_z LPCWSTR wzInstance,\n    __in_z LPCWSTR wzDatabase,\n    __in BOOL fIntegratedAuth,\n    __in_z LPCWSTR wzUser,\n    __in_z LPCWSTR wzPassword,\n    __in_opt const SQL_FILESPEC* psfDatabase,\n    __in_opt const SQL_FILESPEC* psfLog,\n    __out_opt BSTR* pbstrErrorDescription\n    );\nHRESULT DAPI SqlSessionDatabaseEnsureExists(\n    __in IDBCreateSession* pidbSession,\n    __in_z LPCWSTR wzDatabase,\n    __in_opt const SQL_FILESPEC* psfDatabase,\n    __in_opt const SQL_FILESPEC* psfLog,\n    __out_opt BSTR* pbstrErrorDescription\n    );\nHRESULT DAPI SqlCreateDatabase(\n    __in_z LPCWSTR wzServer,\n    __in_z LPCWSTR wzInstance,\n    __in_z LPCWSTR wzDatabase,\n    __in BOOL fIntegratedAuth,\n    __in_z LPCWSTR wzUser,\n    __in_z LPCWSTR wzPassword,\n    __in_opt const SQL_FILESPEC* psfDatabase,\n    __in_opt const SQL_FILESPEC* psfLog,\n    __out_opt BSTR* pbstrErrorDescription\n    );\nHRESULT DAPI SqlSessionCreateDatabase(\n    __in IDBCreateSession* pidbSession,\n    __in_z LPCWSTR wzDatabase,\n    __in_opt const SQL_FILESPEC* psfDatabase,\n    __in_opt const SQL_FILESPEC* psfLog,\n    __out_opt BSTR* pbstrErrorDescription\n    );\nHRESULT DAPI SqlDropDatabase(\n    __in_z LPCWSTR wzServer,\n    __in_z LPCWSTR wzInstance,\n    __in_z LPCWSTR wzDatabase,\n    __in BOOL fIntegratedAuth,\n    __in_z LPCWSTR wzUser,\n    __in_z LPCWSTR wzPassword,\n    __out_opt BSTR* pbstrErrorDescription\n    );\nHRESULT DAPI SqlSessionDropDatabase(\n    __in IDBCreateSession* pidbSession,\n    __in_z LPCWSTR wzDatabase,\n    __out_opt BSTR* pbstrErrorDescription\n    );\nHRESULT DAPI SqlSessionExecuteQuery(\n    __in IDBCreateSession* pidbSession, \n    __in __sql_command LPCWSTR wzSql, \n    __out_opt IRowset** ppirs,\n    __out_opt DBROWCOUNT* pcRows,\n    __out_opt BSTR* pbstrErrorDescription\n    );\nHRESULT DAPI SqlCommandExecuteQuery(\n    __in IDBCreateCommand* pidbCommand, \n    __in __sql_command LPCWSTR wzSql, \n    __out IRowset** ppirs,\n    __out DBROWCOUNT* pcRows\n    );\nHRESULT DAPI SqlGetErrorInfo(\n    __in IUnknown* pObjectWithError,\n    __in REFIID IID_InterfaceWithError,\n    __in DWORD dwLocaleId,\n    __out_opt BSTR* pbstrErrorSource,\n    __out_opt BSTR* pbstrErrorDescription\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/srputil.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"srputil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//\n// <summary>\n//  System restore point helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\nenum SRP_ACTION\n{\n    SRP_ACTION_UNKNOWN,\n    SRP_ACTION_UNINSTALL,\n    SRP_ACTION_INSTALL,\n    SRP_ACTION_MODIFY,\n};\n\n\n/********************************************************************\n SrpInitialize - initializes system restore point functionality.\n\n*******************************************************************/\nDAPI_(HRESULT) SrpInitialize(\n    __in BOOL fInitializeComSecurity\n    );\n\n/********************************************************************\n SrpUninitialize - uninitializes system restore point functionality.\n\n*******************************************************************/\nDAPI_(void) SrpUninitialize();\n\n/********************************************************************\n SrpCreateRestorePoint - creates a system restore point.\n\n*******************************************************************/\nDAPI_(HRESULT) SrpCreateRestorePoint(\n    __in_z LPCWSTR wzApplicationName,\n    __in SRP_ACTION action\n    );\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/strutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"strutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for string helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ReleaseStr(pwz) if (pwz) { StrFree(pwz); }\n#define ReleaseNullStr(pwz) if (pwz) { StrFree(pwz); pwz = NULL; }\n#define ReleaseBSTR(bstr) if (bstr) { ::SysFreeString(bstr); }\n#define ReleaseNullBSTR(bstr) if (bstr) { ::SysFreeString(bstr); bstr = NULL; }\n#define ReleaseStrArray(rg, c) { if (rg) { StrArrayFree(rg, c); } }\n#define ReleaseNullStrArray(rg, c) { if (rg) { StrArrayFree(rg, c); c = 0; rg = NULL; } }\n\n#define DeclareConstBSTR(bstr_const, wz) const WCHAR bstr_const[] = { 0x00, 0x00, sizeof(wz)-sizeof(WCHAR), 0x00, wz }\n#define UseConstBSTR(bstr_const) const_cast<BSTR>(bstr_const + 4)\n\nHRESULT DAPI StrAlloc(\n    __deref_out_ecount_part(cch, 0) LPWSTR* ppwz,\n    __in DWORD_PTR cch\n    );\nHRESULT DAPI StrTrimCapacity(\n    __deref_out_z LPWSTR* ppwz\n    );\nHRESULT DAPI StrTrimWhitespace(\n    __deref_out_z LPWSTR* ppwz,\n    __in_z LPCWSTR wzSource\n    );\nHRESULT DAPI StrAnsiAlloc(\n    __deref_out_ecount_part(cch, 0) LPSTR* ppz,\n    __in DWORD_PTR cch\n    );\nHRESULT DAPI StrAnsiTrimCapacity(\n    __deref_out_z LPSTR* ppz\n    );\nHRESULT DAPI StrAnsiTrimWhitespace(\n    __deref_out_z LPSTR* ppz,\n    __in_z LPCSTR szSource\n    );\nHRESULT DAPI StrAllocString(\n    __deref_out_ecount_z(cchSource+1) LPWSTR* ppwz,\n    __in_z LPCWSTR wzSource,\n    __in DWORD_PTR cchSource\n    );\nHRESULT DAPI StrAnsiAllocString(\n    __deref_out_ecount_z(cchSource+1) LPSTR* ppsz,\n    __in_z LPCWSTR wzSource,\n    __in DWORD_PTR cchSource,\n    __in UINT uiCodepage\n    );\nHRESULT DAPI StrAllocStringAnsi(\n    __deref_out_ecount_z(cchSource+1) LPWSTR* ppwz,\n    __in_z LPCSTR szSource,\n    __in DWORD_PTR cchSource,\n    __in UINT uiCodepage\n    );\nHRESULT DAPI StrAnsiAllocStringAnsi(\n    __deref_out_ecount_z(cchSource+1) LPSTR* ppsz,\n    __in_z LPCSTR szSource,\n    __in DWORD_PTR cchSource\n    );\nHRESULT DAPI StrAllocPrefix(\n    __deref_out_z LPWSTR* ppwz,\n    __in_z LPCWSTR wzPrefix,\n    __in DWORD_PTR cchPrefix\n    );\nHRESULT DAPI StrAllocConcat(\n    __deref_out_z LPWSTR* ppwz,\n    __in_z LPCWSTR wzSource,\n    __in DWORD_PTR cchSource\n    );\nHRESULT DAPI StrAnsiAllocConcat(\n    __deref_out_z LPSTR* ppz,\n    __in_z LPCSTR pzSource,\n    __in DWORD_PTR cchSource\n    );\nHRESULT __cdecl StrAllocFormatted(\n    __deref_out_z LPWSTR* ppwz,\n    __in __format_string LPCWSTR wzFormat,\n    ...\n    );\nHRESULT __cdecl StrAnsiAllocFormatted(\n    __deref_out_z LPSTR* ppsz,\n    __in __format_string LPCSTR szFormat,\n    ...\n    );\nHRESULT DAPI StrAllocFormattedArgs(\n    __deref_out_z LPWSTR* ppwz,\n    __in __format_string LPCWSTR wzFormat,\n    __in va_list args\n    );\nHRESULT DAPI StrAnsiAllocFormattedArgs(\n    __deref_out_z LPSTR* ppsz,\n    __in __format_string LPCSTR szFormat,\n    __in va_list args\n    );\nHRESULT DAPI StrAllocFromError(\n    __inout LPWSTR *ppwzMessage,\n    __in HRESULT hrError,\n    __in_opt HMODULE hModule,\n    ...\n    );\n\nHRESULT DAPI StrMaxLength(\n    __in LPCVOID p,\n    __out DWORD_PTR* pcch\n    );\nHRESULT DAPI StrSize(\n    __in LPCVOID p,\n    __out DWORD_PTR* pcb\n    );\n\nHRESULT DAPI StrFree(\n    __in LPVOID p\n    );\n\n\nHRESULT DAPI StrReplaceStringAll(\n    __inout LPWSTR* ppwzOriginal,\n    __in_z LPCWSTR wzOldSubString,\n    __in_z LPCWSTR wzNewSubString\n    );\nHRESULT DAPI StrReplaceString(\n    __inout LPWSTR* ppwzOriginal,\n    __inout DWORD* pdwStartIndex,\n    __in_z LPCWSTR wzOldSubString,\n    __in_z LPCWSTR wzNewSubString\n    );\n\nHRESULT DAPI StrHexEncode(\n    __in_ecount(cbSource) const BYTE* pbSource,\n    __in DWORD_PTR cbSource,\n    __out_ecount(cchDest) LPWSTR wzDest,\n    __in DWORD_PTR cchDest\n    );\nHRESULT DAPI StrHexDecode(\n    __in_z LPCWSTR wzSource,\n    __out_bcount(cbDest) BYTE* pbDest,\n    __in DWORD_PTR cbDest\n    );\nHRESULT DAPI StrAllocHexDecode(\n    __in_z LPCWSTR wzSource,\n    __out_bcount(*pcbDest) BYTE** ppbDest,\n    __out_opt DWORD* pcbDest\n    );\n\nHRESULT DAPI StrAllocBase85Encode(\n    __in_bcount_opt(cbSource) const BYTE* pbSource,\n    __in DWORD_PTR cbSource,\n    __deref_out_z LPWSTR* pwzDest\n    );\nHRESULT DAPI StrAllocBase85Decode(\n    __in_z LPCWSTR wzSource,\n    __deref_out_bcount(*pcbDest) BYTE** hbDest,\n    __out DWORD_PTR* pcbDest\n    );\n\nHRESULT DAPI MultiSzLen(\n    __in_ecount(*pcch) __nullnullterminated LPCWSTR pwzMultiSz,\n    __out DWORD_PTR* pcch\n    );\nHRESULT DAPI MultiSzPrepend(\n    __deref_inout_ecount(*pcchMultiSz) __nullnullterminated LPWSTR* ppwzMultiSz,\n    __inout_opt DWORD_PTR *pcchMultiSz,\n    __in __nullnullterminated LPCWSTR pwzInsert\n    );\nHRESULT DAPI MultiSzFindSubstring(\n    __in __nullnullterminated LPCWSTR pwzMultiSz,\n    __in __nullnullterminated LPCWSTR pwzSubstring,\n    __out_opt DWORD_PTR* pdwIndex,\n    __deref_opt_out_z LPCWSTR* ppwzFoundIn\n    );\nHRESULT DAPI MultiSzFindString(\n    __in __nullnullterminated LPCWSTR pwzMultiSz,\n    __in __nullnullterminated LPCWSTR pwzString,\n    __out_opt DWORD_PTR* pdwIndex,\n    __deref_opt_out __nullnullterminated LPCWSTR* ppwzFound\n    );\nHRESULT DAPI MultiSzRemoveString(\n    __deref_inout __nullnullterminated LPWSTR* ppwzMultiSz,\n    __in DWORD_PTR dwIndex\n    );\nHRESULT DAPI MultiSzInsertString(\n    __deref_inout_z LPWSTR* ppwzMultiSz,\n    __inout_opt DWORD_PTR *pcchMultiSz,\n    __in DWORD_PTR dwIndex,\n    __in_z LPCWSTR pwzInsert\n    );\nHRESULT DAPI MultiSzReplaceString(\n    __deref_inout __nullnullterminated LPWSTR* ppwzMultiSz,\n    __in DWORD_PTR dwIndex,\n    __in_z LPCWSTR pwzString\n    );\n\nLPCWSTR wcsistr(\n    __in_z LPCWSTR wzString,\n    __in_z LPCWSTR wzCharSet\n    );\n\nHRESULT DAPI StrStringToInt16(\n    __in_z LPCWSTR wzIn,\n    __in DWORD cchIn,\n    __out SHORT* psOut\n    );\nHRESULT DAPI StrStringToUInt16(\n    __in_z LPCWSTR wzIn,\n    __in DWORD cchIn,\n    __out USHORT* pusOut\n    );\nHRESULT DAPI StrStringToInt32(\n    __in_z LPCWSTR wzIn,\n    __in DWORD cchIn,\n    __out INT* piOut\n    );\nHRESULT DAPI StrStringToUInt32(\n    __in_z LPCWSTR wzIn,\n    __in DWORD cchIn,\n    __out UINT* puiOut\n    );\nHRESULT DAPI StrStringToInt64(\n    __in_z LPCWSTR wzIn,\n    __in DWORD cchIn,\n    __out LONGLONG* pllOut\n    );\nHRESULT DAPI StrStringToUInt64(\n    __in_z LPCWSTR wzIn,\n    __in DWORD cchIn,\n    __out ULONGLONG* pullOut\n    );\nvoid DAPI StrStringToUpper(\n    __inout_z LPWSTR wzIn\n    );\nvoid DAPI StrStringToLower(\n    __inout_z LPWSTR wzIn\n    );\nHRESULT DAPI StrAllocStringToUpperInvariant(\n    __deref_out_z LPWSTR* pscz,\n    __in_z LPCWSTR wzSource,\n    __in int cchSource\n    );\nHRESULT DAPI StrAllocStringToLowerInvariant(\n    __deref_out_z LPWSTR* pscz,\n    __in_z LPCWSTR wzSource,\n    __in int cchSource\n    );\n\nHRESULT DAPI StrArrayAllocString(\n    __deref_inout_ecount_opt(*pcStrArray) LPWSTR **prgsczStrArray,\n    __inout LPUINT pcStrArray,\n    __in_z LPCWSTR wzSource,\n    __in DWORD_PTR cchSource\n    );\n\nHRESULT DAPI StrArrayFree(\n    __in_ecount(cStrArray) LPWSTR *rgsczStrArray,\n    __in UINT cStrArray\n    );\n\nHRESULT DAPI StrSplitAllocArray(\n    __deref_inout_ecount_opt(*pcStrArray) LPWSTR **prgsczStrArray,\n    __inout LPUINT pcStrArray,\n    __in_z LPCWSTR wzSource,\n    __in_z LPCWSTR wzDelim\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/svcutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"svcutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for Windows service helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n#define ReleaseServiceHandle(h) if (h) { ::CloseServiceHandle(h); h = NULL; }\n\n\nHRESULT DAPI SvcQueryConfig(\n    __in SC_HANDLE sch,\n    __out QUERY_SERVICE_CONFIGW** ppConfig\n    );\n\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/thmutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"thmutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//\n// <summary>\n//  Theme helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ReleaseTheme(p) if (p) { ThemeFree(p); p = NULL; }\n\nenum THEME_CONTROL_DATA\n{\n    THEME_CONTROL_DATA_HOVER = 1,\n};\n\nenum THEME_CONTROL_TYPE\n{\n    THEME_CONTROL_TYPE_UNKNOWN,\n    THEME_CONTROL_TYPE_BILLBOARD,\n    THEME_CONTROL_TYPE_BUTTON,\n    THEME_CONTROL_TYPE_CHECKBOX,\n    THEME_CONTROL_TYPE_EDITBOX,\n    THEME_CONTROL_TYPE_HYPERLINK,\n    THEME_CONTROL_TYPE_HYPERTEXT,\n    THEME_CONTROL_TYPE_IMAGE,\n    THEME_CONTROL_TYPE_PROGRESSBAR,\n    THEME_CONTROL_TYPE_RICHEDIT,\n    THEME_CONTROL_TYPE_STATIC,\n    THEME_CONTROL_TYPE_TEXT,\n    THEME_CONTROL_TYPE_LISTVIEW,\n    THEME_CONTROL_TYPE_TREEVIEW,\n    THEME_CONTROL_TYPE_TAB,\n};\n\n\nstruct THEME_BILLBOARD\n{\n    HBITMAP hImage;\n    LPWSTR sczUrl;\n};\n\n\nstruct THEME_COLUMN\n{\n    LPWSTR pszName;\n    UINT uStringId;\n    int nWidth;\n};\n\n\nstruct THEME_TAB\n{\n    LPWSTR pszName;\n    UINT uStringId;\n};\n\n// THEME_ASSIGN_CONTROL_ID - Used to apply a specific id to a named control (usually\n//                           to set the WM_COMMAND).\nstruct THEME_ASSIGN_CONTROL_ID\n{\n    WORD wId;       // id to apply to control\n    LPCWSTR wzName; // name of control to match\n};\n\nconst DWORD THEME_FIRST_ASSIGN_CONTROL_ID = 1024; // Recommended first control id to be assigned.\n\nstruct THEME_CONTROL\n{\n    THEME_CONTROL_TYPE type;\n\n    WORD wId;\n    WORD wPageId;\n\n    LPWSTR sczName; // optional name for control, only used to apply control id.\n    LPWSTR sczText;\n    int nX;\n    int nY;\n    int nHeight;\n    int nWidth;\n    int nSourceX;\n    int nSourceY;\n    UINT uStringId;\n\n    HBITMAP hImage;\n\n    // Don't free these; it's just a handle to the central image lists stored in THEME. The handle is freed once, there.\n    HIMAGELIST rghImageList[4];\n\n    DWORD dwStyle;\n    DWORD dwExtendedStyle;\n    DWORD dwInternalStyle;\n\n    DWORD dwFontId;\n    DWORD dwFontHoverId;\n    DWORD dwFontSelectedId;\n\n    // Used by billboard controls\n    THEME_BILLBOARD* ptbBillboards;\n    DWORD cBillboards;\n    WORD wBillboardInterval;\n    WORD wBillboardUrls;\n    BOOL fBillboardLoops;\n\n    // Used by listview controls\n    THEME_COLUMN *ptcColumns;\n    DWORD cColumns;\n\n    // Used by tab controls\n    THEME_TAB *pttTabs;\n    DWORD cTabs;\n\n    // state variables that should be ignored\n    HWND hWnd;\n    DWORD dwData; // type specific data\n};\n\n\nstruct THEME_IMAGELIST\n{\n    LPWSTR sczName;\n\n    HIMAGELIST hImageList;\n};\n\nstruct THEME_PAGE\n{\n    WORD wId;\n    LPWSTR sczName;\n\n    DWORD cControlIndices;\n    DWORD* rgdwControlIndices;\n};\n\nstruct THEME_FONT\n{\n    HFONT hFont;\n    COLORREF crForeground;\n    HBRUSH hForeground;\n    COLORREF crBackground;\n    HBRUSH hBackground;\n};\n\n\nstruct THEME\n{\n    WORD wId;\n\n    DWORD dwStyle;\n    DWORD dwFontId;\n    HANDLE hIcon;\n    LPWSTR sczCaption;\n    int nHeight;\n    int nWidth;\n    int nSourceX;\n    int nSourceY;\n    UINT uStringId;\n\n    HBITMAP hImage;\n\n    DWORD cFonts;\n    THEME_FONT* rgFonts;\n\n    DWORD cPages;\n    THEME_PAGE* rgPages;\n\n    DWORD cImageLists;\n    THEME_IMAGELIST* rgImageLists;\n\n    DWORD cControls;\n    THEME_CONTROL* rgControls;\n\n    // state variables that should be ignored\n    HWND hwndParent; // parent for loaded controls\n    HWND hwndHover; // current hwnd hovered over\n};\n\n\n/********************************************************************\n ThemeInitialize - initialized theme management.\n\n*******************************************************************/\nDAPI_(HRESULT) ThemeInitialize(\n    __in_opt HMODULE hModule\n    );\n\n/********************************************************************\n ThemeUninitialize - unitialize theme management.\n\n*******************************************************************/\nDAPI_(void) ThemeUninitialize();\n\n/********************************************************************\n ThemeLoadFromFile - loads a theme from a loose file.\n\n *******************************************************************/\nDAPI_(HRESULT) ThemeLoadFromFile(\n    __in_z LPCWSTR wzThemeFile,\n    __out THEME** ppTheme\n    );\n\n/********************************************************************\n ThemeLoadFromResource - loads a theme from a module's data resource.\n\n NOTE: The resource data must be UTF-8 encoded.\n*******************************************************************/\nDAPI_(HRESULT) ThemeLoadFromResource(\n    __in_opt HMODULE hModule,\n    __in_z LPCSTR szResource,\n    __out THEME** ppTheme\n    );\n\n/********************************************************************\n ThemeFree - frees any memory associated with a theme.\n\n*******************************************************************/\nDAPI_(void) ThemeFree(\n    __in THEME* pTheme\n    );\n\n/********************************************************************\n ThemeLoadControls - creates the windows for all the theme controls.\n\n*******************************************************************/\nDAPI_(HRESULT) ThemeLoadControls(\n    __in THEME* pTheme,\n    __in HWND hwndParent,\n    __in_ecount_opt(cAssignControlIds) const THEME_ASSIGN_CONTROL_ID* rgAssignControlIds,\n    __in DWORD cAssignControlIds\n    );\n\n/********************************************************************\n ThemeUnloadControls - resets all the theme control windows so the theme\n                       controls can be reloaded.\n\n*******************************************************************/\nDAPI_(void) ThemeUnloadControls(\n    __in THEME* pTheme\n    );\n\n/********************************************************************\n ThemeLocalize - Localizes all of the strings in the them.\n\n*******************************************************************/\nDAPI_(HRESULT) ThemeLocalize(\n    __in THEME *pTheme,\n    __in const WIX_LOCALIZATION *pLocStringSet\n    );\n\nDAPI_(HRESULT) ThemeLoadStrings(\n    __in THEME* pTheme,\n    __in HMODULE hResModule\n    );\n\n/********************************************************************\n ThemeLoadRichEditFromFile - Attach a richedit control to a RTF file.\n\n *******************************************************************/\nDAPI_(HRESULT) ThemeLoadRichEditFromFile(\n    __in THEME* pTheme,\n    __in DWORD dwControl,\n    __in_z LPCWSTR wzFileName,\n    __in HMODULE hModule\n    );\n\n/********************************************************************\n ThemeLoadRichEditFromResource - Attach a richedit control to resource data.\n\n *******************************************************************/\nDAPI_(HRESULT) ThemeLoadRichEditFromResource(\n    __in THEME* pTheme,\n    __in DWORD dwControl,\n    __in_z LPCSTR szResourceName,\n    __in HMODULE hModule\n    );\n\n/********************************************************************\n ThemeLoadRichEditFromResourceToHWnd - Attach a richedit control (by \n                                       HWND) to resource data.\n\n *******************************************************************/\nDAPI_(HRESULT) ThemeLoadRichEditFromResourceToHWnd(\n    __in HWND hWnd,\n    __in_z LPCSTR szResourceName,\n    __in HMODULE hModule\n    );\n\n/********************************************************************\n ThemeHandleKeyboardMessage - will translate the message using the active\n                             accelerator table.\n\n*******************************************************************/\nDAPI_(BOOL) ThemeHandleKeyboardMessage(\n    __in_opt THEME* pTheme,\n    __in HWND hWnd,\n    __in MSG* pMsg\n    );\n\n/********************************************************************\n ThemeDefWindowProc - replacement for DefWindowProc() when using theme.\n\n*******************************************************************/\nLRESULT CALLBACK ThemeDefWindowProc(\n    __in_opt THEME* pTheme,\n    __in HWND hWnd,\n    __in UINT uMsg,\n    __in WPARAM wParam,\n    __in LPARAM lParam\n    );\n\n/********************************************************************\n ThemeGetPageIds - gets the page ids for the theme via page names.\n\n*******************************************************************/\nDAPI_(void) ThemeGetPageIds(\n    __in const THEME* pTheme,\n    __in_ecount(cGetPages) LPCWSTR* rgwzFindNames,\n    __in_ecount(cGetPages) DWORD* rgdwPageIds,\n    __in DWORD cGetPages\n    );\n\n/********************************************************************\n ThemeGetPage - gets a theme page by id.\n\n *******************************************************************/\nDAPI_(THEME_PAGE*) ThemeGetPage(\n    __in const THEME* pTheme,\n    __in DWORD dwPage\n    );\n\n/********************************************************************\n ThemeShowPage - shows or hides all of the controls in the page at one time.\n\n *******************************************************************/\nDAPI_(void) ThemeShowPage(\n    __in THEME* pTheme,\n    __in DWORD dwPage,\n    __in int nCmdShow\n    );\n\n/********************************************************************\n ThemeControlExists - check if a control with the specified id exists.\n\n *******************************************************************/\nDAPI_(BOOL) ThemeControlExists(\n    __in THEME* pTheme,\n    __in DWORD dwControl\n    );\n\n/********************************************************************\n ThemeControlEnable - enables/disables a control.\n\n *******************************************************************/\nDAPI_(void) ThemeControlEnable(\n    __in THEME* pTheme,\n    __in DWORD dwControl,\n    __in BOOL fEnable\n    );\n\n/********************************************************************\n ThemeControlEnabled - returns whether a control is enabled/disabled.\n\n *******************************************************************/\nDAPI_(BOOL) ThemeControlEnabled(\n    __in THEME* pTheme,\n    __in DWORD dwControl\n    );\n\n/********************************************************************\n ThemeControlElevates - sets/removes the shield icon on a control.\n\n *******************************************************************/\nDAPI_(void) ThemeControlElevates(\n    __in THEME* pTheme,\n    __in DWORD dwControl,\n    __in BOOL fElevates\n    );\n\n/********************************************************************\n ThemeShowControl - shows/hides a control.\n\n *******************************************************************/\nDAPI_(void) ThemeShowControl(\n    __in THEME* pTheme,\n    __in DWORD dwControl,\n    __in int nCmdShow\n    );\n\n/********************************************************************\n ThemeControlVisible - returns whether a control is visible.\n\n *******************************************************************/\nDAPI_(BOOL) ThemeControlVisible(\n    __in THEME* pTheme,\n    __in DWORD dwControl\n    );\n\nDAPI_(BOOL) ThemePostControlMessage(\n    __in THEME* pTheme,\n    __in DWORD dwControl,\n    __in UINT Msg,\n    __in WPARAM wParam,\n    __in LPARAM lParam\n    );\n\nDAPI_(LRESULT) ThemeSendControlMessage(\n    __in THEME* pTheme,\n    __in DWORD dwControl,\n    __in UINT Msg,\n    __in WPARAM wParam,\n    __in LPARAM lParam\n    );\n\n/********************************************************************\n ThemeDrawBackground - draws the theme background.\n\n*******************************************************************/\nDAPI_(HRESULT) ThemeDrawBackground(\n    __in THEME* pTheme,\n    __in PAINTSTRUCT* pps\n    );\n\n/********************************************************************\n ThemeDrawControl - draw an owner drawn control.\n\n*******************************************************************/\nDAPI_(HRESULT) ThemeDrawControl(\n    __in THEME* pTheme,\n    __in DRAWITEMSTRUCT* pdis\n    );\n\n/********************************************************************\n ThemeHoverControl - mark a control as hover.\n\n*******************************************************************/\nDAPI_(BOOL) ThemeHoverControl(\n    __in THEME* pTheme,\n    __in HWND hwndParent,\n    __in HWND hwndControl\n    );\n\n/********************************************************************\n ThemeIsControlChecked - gets whether a control is checked. Only\n                         really useful for checkbox controls.\n\n*******************************************************************/\nDAPI_(BOOL) ThemeIsControlChecked(\n    __in THEME* pTheme,\n    __in DWORD dwControl\n    );\n\n/********************************************************************\n ThemeSetControlColor - sets the color of text for a control.\n\n*******************************************************************/\nDAPI_(BOOL) ThemeSetControlColor(\n    __in THEME* pTheme,\n    __in HDC hdc,\n    __in HWND hWnd,\n    __out HBRUSH* phBackgroundBrush\n    );\n\n/********************************************************************\n ThemeStartBillboard - starts a billboard control changing images according\n                       to their interval.\n\n NOTE: iImage specifies the image to start on. If iImage is\n       greater than the number of images, the last image shown\n       will be the start image.\n*******************************************************************/\nDAPI_(HRESULT) ThemeStartBillboard(\n    __in const THEME* pTheme,\n    __in DWORD dwControl,\n    __in WORD iImage\n    );\n\n/********************************************************************\n ThemeStopBillboard - stops a billboard control from changing images.\n\n*******************************************************************/\nDAPI_(HRESULT) ThemeStopBillboard(\n    __in const THEME* pTheme,\n    __in DWORD dwControl\n    );\n\n/********************************************************************\n ThemeSetProgressControl - sets the current percentage complete in a\n                           progress bar control.\n\n*******************************************************************/\nDAPI_(HRESULT) ThemeSetProgressControl(\n    __in THEME* pTheme,\n    __in DWORD dwControl,\n    __in DWORD dwProgressPercentage\n    );\n\n/********************************************************************\n ThemeSetProgressControlColor - sets the current color of a\n                                progress bar control.\n\n*******************************************************************/\nDAPI_(HRESULT) ThemeSetProgressControlColor(\n    __in THEME* pTheme,\n    __in DWORD dwControl,\n    __in DWORD dwColorIndex\n    );\n\n/********************************************************************\n ThemeSetTextControl - sets the text of a control.\n\n*******************************************************************/\nDAPI_(HRESULT) ThemeSetTextControl(\n    __in THEME* pTheme,\n    __in DWORD dwControl,\n    __in_z LPCWSTR wzText\n    );\n\n/********************************************************************\n ThemeGetTextControl - gets the text of a control.\n\n*******************************************************************/\nDAPI_(HRESULT) ThemeGetTextControl(\n    __in const THEME* pTheme,\n    __in DWORD dwControl,\n    __out LPWSTR* psczText\n    );\n\n/********************************************************************\n ThemeUpdateCaption - updates the caption in the theme.\n\n*******************************************************************/\nDAPI_(HRESULT) ThemeUpdateCaption(\n    __in THEME* pTheme,\n    __in_z LPCWSTR wzCaption\n    );\n\n/********************************************************************\n ThemeSetFocus - set the focus to the control supplied or the next \n                 enabled control if it is disabled.\n\n*******************************************************************/\nDAPI_(void) ThemeSetFocus(\n    __in THEME* pTheme,\n    __in DWORD dwControl\n    );\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/timeutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"timeutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//  Time helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nHRESULT DAPI TimeFromString(\n    __in_z LPCWSTR wzTime,\n    __out FILETIME* pFileTime\n    );\nHRESULT DAPI TimeFromString3339(\n    __in_z LPCWSTR wzTime,\n    __out FILETIME* pFileTime\n    );\nHRESULT DAPI TimeCurrentTime(\n    __deref_out_z LPWSTR* ppwz,\n    __in BOOL fGMT\n    );\nHRESULT DAPI TimeCurrentDateTime(\n    __deref_out_z LPWSTR* ppwz,\n    __in BOOL fGMT\n    );\nHRESULT DAPI TimeSystemDateTime(\n    __deref_out_z LPWSTR* ppwz,\n    __in const SYSTEMTIME *pst,\n    __in BOOL fGMT\n    );\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/uriutil.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"uriutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    URI helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n#include \"wininet.h\"\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nenum URI_PROTOCOL\n{\n    URI_PROTOCOL_UNKNOWN,\n    URI_PROTOCOL_FILE,\n    URI_PROTOCOL_FTP,\n    URI_PROTOCOL_HTTP,\n    URI_PROTOCOL_HTTPS,\n    URI_PROTOCOL_LOCAL,\n    URI_PROTOCOL_UNC\n};\n\ntypedef struct _URI_INFO\n{\n    INTERNET_SCHEME scheme;\n    LPWSTR sczHostName;\n    INTERNET_PORT port;\n    LPWSTR sczUser;\n    LPWSTR sczPassword;\n    LPWSTR sczPath;\n    LPWSTR sczQueryString;\n} URI_INFO;\n\n\nHRESULT DAPI UriCanonicalize(\n    __inout_z LPWSTR* psczUri\n    );\n\nHRESULT DAPI UriCrack(\n    __in_z LPCWSTR wzUri,\n    __out_opt INTERNET_SCHEME* pScheme,\n    __deref_opt_out_z LPWSTR* psczHostName,\n    __out_opt INTERNET_PORT* pPort,\n    __deref_opt_out_z LPWSTR* psczUser,\n    __deref_opt_out_z LPWSTR* psczPassword,\n    __deref_opt_out_z LPWSTR* psczPath,\n    __deref_opt_out_z LPWSTR* psczQueryString\n    );\n\nHRESULT DAPI UriCrackEx(\n    __in_z LPCWSTR wzUri,\n    __in URI_INFO* pUriInfo\n    );\n\nvoid DAPI UriInfoUninitialize(\n    __in URI_INFO* pUriInfo\n    );\n\nHRESULT DAPI UriCreate(\n    __inout_z LPWSTR* psczUri,\n    __in INTERNET_SCHEME scheme,\n    __in_z_opt LPWSTR wzHostName,\n    __in INTERNET_PORT port,\n    __in_z_opt LPWSTR wzUser,\n    __in_z_opt LPWSTR wzPassword,\n    __in_z_opt LPWSTR wzPath,\n    __in_z_opt LPWSTR wzQueryString\n    );\n\nHRESULT DAPI UriCanonicalize(\n    __inout_z LPWSTR* psczUri\n    );\n\nHRESULT DAPI UriFile(\n    __deref_out_z LPWSTR* psczFile,\n    __in_z LPCWSTR wzUri\n    );\n\nHRESULT DAPI UriProtocol(\n    __in_z LPCWSTR wzUri,\n    __out URI_PROTOCOL* pProtocol\n    );\n\nHRESULT DAPI UriRoot(\n    __in_z LPCWSTR wzUri,\n    __out LPWSTR* ppwzRoot,\n    __out_opt URI_PROTOCOL* pProtocol\n    );\n\nHRESULT DAPI UriResolve(\n    __in_z LPCWSTR wzUri,\n    __in_opt LPCWSTR wzBaseUri,\n    __out LPWSTR* ppwzResolvedUri,\n    __out_opt const URI_PROTOCOL* pResolvedProtocol\n    );\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/userutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"userutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    User helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nHRESULT DAPI UserBuildDomainUserName(\n    __out_ecount_z(cchDest) LPWSTR wzDest,\n    __in int cchDest,\n    __in_z LPCWSTR pwzName,\n    __in_z LPCWSTR pwzDomain\n    );\n\nHRESULT DAPI UserCheckIsMember(\n    __in_z LPCWSTR pwzName,\n    __in_z LPCWSTR pwzDomain,\n    __in_z LPCWSTR pwzGroupName,\n    __in_z LPCWSTR pwzGroupDomain,\n    __out LPBOOL lpfMember\n    );\n\nHRESULT DAPI UserCreateADsPath(\n    __in_z LPCWSTR wzObjectDomain, \n    __in_z LPCWSTR wzObjectName,\n    __out BSTR *pbstrAdsPath\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/wcalog.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"wcalog.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Private header for internal logging functions\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nBOOL WIXAPI IsVerboseLogging();\nHRESULT WIXAPI SetVerboseLoggingAtom(BOOL bValue);\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/wcautil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"wcautil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Windows Installer XML CustomAction utility library.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define WIXAPI __stdcall\n#define ExitTrace WcaLogError\n#define ExitTrace1 WcaLogError\n#define ExitTrace2 WcaLogError\n#define ExitTrace3 WcaLogError\n\n#include \"dutil.h\"\n\n#define MessageExitOnLastError(x, e, s)      { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTrace(x, \"%s\", s); WcaErrorMessage(e, x, MB_OK, 0);  goto LExit; } }\n#define MessageExitOnLastError1(x, e, f, s)  { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTrace1(x, f, s); WcaErrorMessage(e, x, MB_OK, 1, s);  goto LExit; } }\n\n#define MessageExitOnFailure(x, e, s)           if (FAILED(x)) { ExitTrace(x, \"%s\", s); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, 0);  goto LExit; }\n#define MessageExitOnFailure1(x, e, f, s)       if (FAILED(x)) { ExitTrace1(x, f, s); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, 1, s);  goto LExit; }\n#define MessageExitOnFailure2(x, e, f, s, t)    if (FAILED(x)) { ExitTrace2(x, f, s, t); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, 2, s, t);  goto LExit; }\n#define MessageExitOnFailure3(x, e, f, s, t, u) if (FAILED(x)) { ExitTrace2(x, f, s, t, u); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, 3, s, t, u);  goto LExit; }\n\n#define MessageExitOnNullWithLastError(p, x, e, s) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace(x, \"%s\", s); WcaErrorMessage(e, x, MB_OK, 0);  goto LExit; }\n#define MessageExitOnNullWithLastError1(p, x, e, f, s) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace(x, f, s); WcaErrorMessage(e, x, MB_OK, 1, s);  goto LExit; }\n#define MessageExitOnNullWithLastError2(p, x, e, f, s, t) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace(x, f, s, t); WcaErrorMessage(e, x, MB_OK, 2, s, t);  goto LExit; }\n\n// Generic action enum.\nenum WCA_ACTION\n{\n    WCA_ACTION_NONE,\n    WCA_ACTION_INSTALL,\n    WCA_ACTION_UNINSTALL,\n};\n\nenum WCA_CASCRIPT\n{\n    WCA_CASCRIPT_SCHEDULED,\n    WCA_CASCRIPT_ROLLBACK,\n};\n\nenum WCA_CASCRIPT_CLOSE\n{\n    WCA_CASCRIPT_CLOSE_PRESERVE,\n    WCA_CASCRIPT_CLOSE_DELETE,\n};\n\nenum WCA_TODO\n{\n    WCA_TODO_UNKNOWN,\n    WCA_TODO_INSTALL,\n    WCA_TODO_UNINSTALL,\n    WCA_TODO_REINSTALL,\n};\n\ntypedef struct WCA_CASCRIPT_STRUCT\n{\n    LPWSTR pwzScriptPath;\n    HANDLE hScriptFile;\n} *WCA_CASCRIPT_HANDLE;\n\nvoid WIXAPI WcaGlobalInitialize(\n    __in HINSTANCE hInst\n    );\nvoid WIXAPI WcaGlobalFinalize();\n\nHRESULT WIXAPI WcaInitialize(\n    __in MSIHANDLE hInstall,\n    __in_z PCSTR szCustomActionLogName\n    );\nUINT WIXAPI WcaFinalize(\n    __in UINT iReturnValue\n    );\nBOOL WIXAPI WcaIsInitialized();\n\nMSIHANDLE WIXAPI WcaGetInstallHandle();\nMSIHANDLE WIXAPI WcaGetDatabaseHandle();\n\nconst char* WIXAPI WcaGetLogName();\n\nvoid WIXAPI WcaSetReturnValue(\n    __in UINT iReturnValue\n    );\nBOOL WIXAPI WcaCancelDetected();\n\nconst int LOG_BUFFER = 2048;\nenum LOGLEVEL\n{ \n    LOGMSG_TRACEONLY,  // Never written to the log file (except in DEBUG builds)\n    LOGMSG_VERBOSE,    // Written to log when LOGVERBOSE\n    LOGMSG_STANDARD    // Written to log whenever informational logging is enabled\n};\n\nvoid __cdecl WcaLog(\n    __in LOGLEVEL llv,\n    __in_z __format_string PCSTR fmt, ...\n    );\nBOOL WIXAPI WcaDisplayAssert(\n    __in LPCSTR sz\n    );\nvoid __cdecl WcaLogError(\n    __in HRESULT hr,\n    __in LPCSTR szMessage,\n    ...\n    );\n\nUINT WIXAPI WcaProcessMessage(\n    __in INSTALLMESSAGE eMessageType,\n    __in MSIHANDLE hRecord\n    );\nUINT __cdecl WcaErrorMessage(\n    __in int iError, \n    __in HRESULT hrError, \n    __in UINT uiType, \n    __in DWORD cArgs, \n    ...\n    );\nHRESULT WIXAPI WcaProgressMessage(\n    __in UINT uiCost,\n    __in BOOL fExtendProgressBar\n    );\n\nBOOL WIXAPI WcaIsInstalling(\n    __in INSTALLSTATE isInstalled,\n    __in INSTALLSTATE isAction\n    );\nBOOL WIXAPI WcaIsReInstalling(\n    __in INSTALLSTATE isInstalled,\n    __in INSTALLSTATE isAction\n    );\nBOOL WIXAPI WcaIsUninstalling(\n    __in INSTALLSTATE isInstalled,\n    __in INSTALLSTATE isAction\n    );\n\nHRESULT WIXAPI WcaSetComponentState(\n    __in_z LPCWSTR wzComponent,\n    __in INSTALLSTATE isState\n    );\n\nHRESULT WIXAPI WcaTableExists(\n    __in_z LPCWSTR wzTable\n    );\n\nHRESULT WIXAPI WcaOpenView(\n    __in_z LPCWSTR wzSql,\n    __out MSIHANDLE* phView\n    );\nHRESULT WIXAPI WcaExecuteView(\n    __in MSIHANDLE hView,\n    __in MSIHANDLE hRec\n    );\nHRESULT WIXAPI WcaOpenExecuteView(\n    __in_z LPCWSTR wzSql,\n    __out MSIHANDLE* phView\n    );\nHRESULT WIXAPI WcaFetchRecord(\n    __in MSIHANDLE hView,\n    __out MSIHANDLE* phRec\n    );\nHRESULT WIXAPI WcaFetchSingleRecord(\n    __in MSIHANDLE hView,\n    __out MSIHANDLE* phRec\n    );\n\nHRESULT WIXAPI WcaGetProperty(\n    __in_z LPCWSTR wzProperty,\n    __inout LPWSTR* ppwzData\n    );\nHRESULT WIXAPI WcaGetFormattedProperty(\n    __in_z LPCWSTR wzProperty,\n    __out LPWSTR* ppwzData\n    );\nHRESULT WIXAPI WcaGetFormattedString(\n    __in_z LPCWSTR wzString,\n    __out LPWSTR* ppwzData\n    );\nHRESULT WIXAPI WcaGetIntProperty(\n    __in_z LPCWSTR wzProperty,\n    __inout int* piData\n    );\nHRESULT WIXAPI WcaGetTargetPath(\n    __in_z LPCWSTR wzFolder,\n    __out LPWSTR* ppwzData\n    );\nHRESULT WIXAPI WcaSetProperty(\n    __in_z LPCWSTR wzPropertyName,\n    __in_z LPCWSTR wzPropertyValue\n    );\nHRESULT WIXAPI WcaSetIntProperty(\n    __in_z LPCWSTR wzPropertyName,\n    __in int nPropertyValue\n    );\nBOOL WIXAPI WcaIsPropertySet(\n    __in LPCSTR szProperty\n    );\nBOOL WIXAPI WcaIsUnicodePropertySet(\n    __in LPCWSTR wzProperty\n    );\n\nHRESULT WIXAPI WcaGetRecordInteger(\n    __in MSIHANDLE hRec,\n    __in UINT uiField,\n    __inout int* piData\n    );\nHRESULT WIXAPI WcaGetRecordString(\n    __in MSIHANDLE hRec,\n    __in UINT uiField,\n    __inout LPWSTR* ppwzData\n    );\nHRESULT WIXAPI WcaGetRecordFormattedInteger(\n    __in MSIHANDLE hRec,\n    __in UINT uiField,\n    __out int* piData\n    );\nHRESULT WIXAPI WcaGetRecordFormattedString(\n    __in MSIHANDLE hRec,\n    __in UINT uiField,\n    __inout LPWSTR* ppwzData\n    );\n\nHRESULT WIXAPI WcaAllocStream(\n    __deref_out_bcount_part(cbData, 0) BYTE** ppbData,\n    __in DWORD cbData\n    );\nHRESULT WIXAPI WcaFreeStream(\n    __in BYTE* pbData\n    );\n\nHRESULT WIXAPI WcaGetRecordStream(\n    __in MSIHANDLE hRecBinary,\n    __in UINT uiField,\n    __deref_out_bcount_full(*pcbData) BYTE** ppbData,\n    __out DWORD* pcbData\n    );\nHRESULT WIXAPI WcaSetRecordString(\n    __in MSIHANDLE hRec,\n    __in UINT uiField,\n    __in_z LPCWSTR wzData\n    );\nHRESULT WIXAPI WcaSetRecordInteger(\n    __in MSIHANDLE hRec,\n    __in UINT uiField,\n    __in int iValue\n    );\n\nHRESULT WIXAPI WcaDoDeferredAction(\n    __in_z LPCWSTR wzAction,\n    __in_z LPCWSTR wzCustomActionData,\n    __in UINT uiCost\n    );\nDWORD WIXAPI WcaCountOfCustomActionDataRecords(\n    __in_z LPCWSTR wzData\n    );\n\nHRESULT WIXAPI WcaReadStringFromCaData(\n    __deref_in LPWSTR* ppwzCustomActionData,\n    __deref_out_z LPWSTR* ppwzString\n    );\nHRESULT WIXAPI WcaReadIntegerFromCaData(\n    __deref_in LPWSTR* ppwzCustomActionData,\n    __out int* piResult\n    );\nHRESULT WIXAPI WcaReadStreamFromCaData(\n    __deref_in LPWSTR* ppwzCustomActionData,\n    __deref_out_bcount(*pcbData) BYTE** ppbData,\n    __out DWORD_PTR* pcbData\n    );\nHRESULT WIXAPI WcaWriteStringToCaData(\n    __in_z LPCWSTR wzString,\n    __deref_inout_z LPWSTR* ppwzCustomActionData\n    );\nHRESULT WIXAPI WcaWriteIntegerToCaData(\n    __in int i, \n    __deref_out_z_opt LPWSTR* ppwzCustomActionData\n    );\nHRESULT WIXAPI WcaWriteStreamToCaData(\n    __in_bcount(cbData) const BYTE* pbData,\n    __in DWORD cbData,\n    __deref_inout_z_opt LPWSTR* ppwzCustomActionData\n    );\n\nHRESULT __cdecl WcaAddTempRecord(\n    __inout MSIHANDLE* phTableView,\n    __inout MSIHANDLE* phColumns,\n    __in_z LPCWSTR wzTable,\n    __out_opt MSIDBERROR* pdbError,\n    __in UINT uiUniquifyColumn,\n    __in UINT cColumns,\n    ...\n    );\n\nHRESULT WIXAPI WcaDumpTable(\n    __in_z LPCWSTR wzTable\n    );\n\nHRESULT WIXAPI WcaDeferredActionRequiresReboot();\nBOOL WIXAPI WcaDidDeferredActionRequireReboot();\n\nHRESULT WIXAPI WcaCaScriptCreateKey(\n    __out LPWSTR* ppwzScriptKey\n    );\n\nHRESULT WIXAPI WcaCaScriptCreate(\n    __in WCA_ACTION action,\n    __in WCA_CASCRIPT script,\n    __in BOOL fImpersonated,\n    __in_z LPCWSTR wzScriptKey,\n    __in BOOL fAppend,\n    __out WCA_CASCRIPT_HANDLE* phScript\n    );\n\nHRESULT WIXAPI WcaCaScriptOpen(\n    __in WCA_ACTION action,\n    __in WCA_CASCRIPT script,\n    __in BOOL fImpersonated,\n    __in_z LPCWSTR wzScriptKey,\n    __out WCA_CASCRIPT_HANDLE* phScript\n    );\n\nvoid WIXAPI WcaCaScriptClose(\n    __in_opt WCA_CASCRIPT_HANDLE hScript,\n    __in WCA_CASCRIPT_CLOSE closeOperation\n    );\n\nHRESULT WIXAPI WcaCaScriptReadAsCustomActionData(\n    __in WCA_CASCRIPT_HANDLE hScript,\n    __out LPWSTR* ppwzCustomActionData\n    );\n\nHRESULT WIXAPI WcaCaScriptWriteString(\n    __in WCA_CASCRIPT_HANDLE hScript,\n    __in_z LPCWSTR wzValue\n    );\n\nHRESULT WIXAPI WcaCaScriptWriteNumber(\n    __in WCA_CASCRIPT_HANDLE hScript,\n    __in DWORD dwValue\n    );\n\nvoid WIXAPI WcaCaScriptFlush(\n    __in WCA_CASCRIPT_HANDLE hScript\n    );\n\nvoid WIXAPI WcaCaScriptCleanup(\n    __in_z LPCWSTR wzProductCode,\n    __in BOOL fImpersonated\n    );\n\nHRESULT WIXAPI QuietExec(\n    __inout_z LPWSTR wzCommand,\n    __in DWORD dwTimeout\n    );\n\nWCA_TODO WIXAPI WcaGetComponentToDo(\n    __in_z LPCWSTR wzComponentId\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/wcawow64.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"wcawow64.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Windows Installer XML CustomAction utility library for Wow64 API-related functionality.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#include \"wcautil.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nHRESULT WIXAPI WcaInitializeWow64();\nBOOL WIXAPI WcaIsWow64Process();\nBOOL WIXAPI WcaIsWow64Initialized();\nHRESULT WIXAPI WcaDisableWow64FSRedirection();\nHRESULT WIXAPI WcaRevertWow64FSRedirection();\nHRESULT WIXAPI WcaFinalizeWow64();\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/wcawrapquery.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"wcawrapquery.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Windows Installer XML CustomAction utility library wrappers meant to wrap an MSI view as\n//    opened by an immediate custom action and transmit it to a deferred custom action\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#include \"wcautil.h\"\n\n// Enumerations\nenum eWrapQueryAction\n{\n    wqaTableBegin = 1,\n    wqaTableFinish,\n    wqaRowBegin,\n    wqaRowFinish\n};\n\nenum eColumnDataType\n{\n    cdtString = 1,\n    cdtInt,\n    cdtStream,\n    cdtUnknown\n};\n\nenum eFormatMaskColumn\n{\n    efmcColumn1 = 1,\n    efmcColumn2 = 1 << 1,\n    efmcColumn3 = 1 << 2,\n    efmcColumn4 = 1 << 3,\n    efmcColumn5 = 1 << 4,\n    efmcColumn6 = 1 << 5,\n    efmcColumn7 = 1 << 6,\n    efmcColumn8 = 1 << 7,\n    efmcColumn9 = 1 << 8,\n    efmcColumn10 = 1 << 9,\n    efmcColumn11 = 1 << 10,\n    efmcColumn12 = 1 << 11,\n    efmcColumn13 = 1 << 12,\n    efmcColumn14 = 1 << 13,\n    efmcColumn15 = 1 << 14,\n    efmcColumn16 = 1 << 15,\n    efmcColumn17 = 1 << 16,\n    efmcColumn18 = 1 << 17,\n    efmcColumn19 = 1 << 18,\n    efmcColumn20 = 1 << 19,\n    efmcColumn21 = 1 << 20,\n    efmcColumn22 = 1 << 21,\n    efmcColumn23 = 1 << 22,\n    efmcColumn24 = 1 << 23,\n    efmcColumn25 = 1 << 24,\n    efmcColumn26 = 1 << 25,\n    efmcColumn27 = 1 << 26,\n    efmcColumn28 = 1 << 27,\n    efmcColumn29 = 1 << 28,\n    efmcColumn30 = 1 << 29,\n    efmcColumn31 = 1 << 30,\n    efmcColumn32 = 1 << 31,\n};\n\n// Keeps track of the query instance for the reading CA (deferred CA)\ntypedef struct WCA_WRAPQUERY_STRUCT\n{\n    // These are used to size our dynamic arrays below\n    DWORD dwColumns, dwRows, dwNextIndex;\n\n    // Dynamic arrays of column schema information\n    eColumnDataType *pcdtColumnType;\n    LPWSTR *ppwzColumnNames;\n\n    // Dynamic array of raw record data\n    MSIHANDLE *phRecords;\n} *WCA_WRAPQUERY_HANDLE;\n\n// Wrap a query\n// Setting the pfFormatMask enables control over which fields will be formatted, and which will be left unchanged\n// Setting dwComponentColumn to something other than 0xFFFFFFFF tells WcaWrapQuery to add two additional columns to the right side of the table\n//      - ISInstalled and ISAction - which map to the ComponentState of the component (the component is found in the column specified)\n//      Note that if a component is NULL, the component state columns will also be left null, and it will be up to the deferred CA to fail or ignore the case appropriately\n// Setting dwDirectoryColumn to something other than 0xFFFFFFFF tells WcaWrapQuery to add two more additional columns to the right side of the table\n//      - SourcePath and TargetPath - which map to the Directory's Source and Target Path (the directory is found in the column specified)\n//      Note that if a directory is NULL, the directory source/target path columns will also be left null, and it will be up to the deferred CA to fail or ignore the case appropriately\nHRESULT WIXAPI WcaWrapQuery(\n    __in_z LPCWSTR pwzQuery,\n    __inout LPWSTR * ppwzCustomActionData,\n    __in_opt DWORD dwFormatMask,\n    __in_opt DWORD dwComponentColumn,\n    __in_opt DWORD dwDirectoryColumn\n    );\n// This wraps an empty table query into the custom action data - this is a way to indicate to the deferred custom action that a necessary table doesn't exist, or its query returned no results\nHRESULT WIXAPI WcaWrapEmptyQuery(\n    __inout LPWSTR * ppwzCustomActionData\n    );\n\n// Open a new unwrap query operation, with data from the ppwzCustomActionData string\nHRESULT WIXAPI WcaBeginUnwrapQuery(\n    __out WCA_WRAPQUERY_HANDLE * phWrapQuery,\n    __inout LPWSTR * ppwzCustomActionData\n    );\n\n// Get the number of records in a query being unwrapped\nDWORD WIXAPI WcaGetQueryRecords(\n    __in const WCA_WRAPQUERY_HANDLE hWrapQuery\n    );\n\n// This function resets a query back to its first row, so that the next fetch returns the first record\nvoid WIXAPI WcaFetchWrappedReset(\n    __in WCA_WRAPQUERY_HANDLE hWrapQuery\n    );\n// Fetch the next record in this query\n// NOTE: the MSIHANDLE returned by this function should not be released, as it is the same handle used by the query object to maintain the item.\n//       so, don't use this function with PMSIHANDLE objects!\nHRESULT WIXAPI WcaFetchWrappedRecord(\n    __in WCA_WRAPQUERY_HANDLE hWrapQuery,\n    __out MSIHANDLE* phRec\n    );\n\n// Fetch the next record in the query where the string value in column dwComparisonColumn equals the value pwzExpectedValue\n// NOTE: the MSIHANDLE returned by this function should not be released, as it is the same handle used by the query object to maintain the item.\n//       so, don't use this function with PMSIHANDLE objects!\nHRESULT WIXAPI WcaFetchWrappedRecordWhereString(\n    __in WCA_WRAPQUERY_HANDLE hWrapQuery,\n    __in DWORD dwComparisonColumn,\n    __in_z LPCWSTR pwzExpectedValue,\n    __out MSIHANDLE* phRec\n    );\n\n// Release a query ID (frees memory, and frees the ID for a new query)\nvoid WIXAPI WcaFinishUnwrapQuery(\n    __in_opt WCA_WRAPQUERY_HANDLE hWrapQuery\n    );\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/wiutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"wiutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    Header for Windows Installer helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// constants\n\n#define IDNOACTION 0\n#define WIU_MB_OKIGNORECANCELRETRY 0xE\n\n#define MAX_DARWIN_KEY 73\n#define MAX_DARWIN_COLUMN 255\n\n#define WIU_LOG_DEFAULT INSTALLLOGMODE_FATALEXIT | INSTALLLOGMODE_ERROR | INSTALLLOGMODE_WARNING | \\\n                        INSTALLLOGMODE_USER | INSTALLLOGMODE_INFO | INSTALLLOGMODE_RESOLVESOURCE | \\\n                        INSTALLLOGMODE_OUTOFDISKSPACE | INSTALLLOGMODE_ACTIONSTART | \\\n                        INSTALLLOGMODE_ACTIONDATA | INSTALLLOGMODE_COMMONDATA | INSTALLLOGMODE_PROPERTYDUMP\n\n#define ReleaseMsi(h) if (h) { ::MsiCloseHandle(h); }\n#define ReleaseNullMsi(h) if (h) { ::MsiCloseHandle(h); h = NULL; }\n\n\nenum WIU_RESTART\n{\n    WIU_RESTART_NONE,\n    WIU_RESTART_REQUIRED,\n    WIU_RESTART_INITIATED,\n};\n\nenum WIU_MSI_EXECUTE_MESSAGE_TYPE\n{\n    WIU_MSI_EXECUTE_MESSAGE_NONE,\n    WIU_MSI_EXECUTE_MESSAGE_PROGRESS,\n    WIU_MSI_EXECUTE_MESSAGE_ERROR,\n    WIU_MSI_EXECUTE_MESSAGE_MSI_MESSAGE,\n    WIU_MSI_EXECUTE_MESSAGE_MSI_FILES_IN_USE,\n};\n\n\n// structures\n\ntypedef struct _WIU_MSI_EXECUTE_MESSAGE\n{\n    WIU_MSI_EXECUTE_MESSAGE_TYPE type;\n    DWORD dwAllowedResults;\n\n    DWORD cData;\n    LPCWSTR* rgwzData;\n\n    INT nResultRecommendation; // recommended return result for this message based on analysis of real world installs.\n\n    union\n    {\n        struct\n        {\n            DWORD dwPercentage;\n        } progress;\n        struct\n        {\n            DWORD dwErrorCode;\n            LPCWSTR wzMessage;\n        } error;\n        struct\n        {\n            INSTALLMESSAGE mt;\n            LPCWSTR wzMessage;\n        } msiMessage;\n        struct\n        {\n            DWORD cFiles;\n            LPCWSTR* rgwzFiles;\n        } msiFilesInUse;\n    };\n} WIU_MSI_EXECUTE_MESSAGE;\n\ntypedef struct _WIU_MSI_PROGRESS\n{\n    DWORD dwTotal;\n    DWORD dwCompleted;\n    DWORD dwStep;\n    BOOL fMoveForward;\n    BOOL fEnableActionData;\n    BOOL fScriptInProgress;\n} WIU_MSI_PROGRESS;\n\n\ntypedef int (*PFN_MSIEXECUTEMESSAGEHANDLER)(\n    __in WIU_MSI_EXECUTE_MESSAGE* pMessage,\n    __in_opt LPVOID pvContext\n    );\n\ntypedef struct _WIU_MSI_EXECUTE_CONTEXT\n{\n    BOOL fRollback;\n    PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler;\n    LPVOID pvContext;\n    WIU_MSI_PROGRESS rgMsiProgress[64];\n    DWORD dwCurrentProgressIndex;\n\n    INSTALLUILEVEL previousInstallUILevel;\n    HWND hwndPreviousParentWindow;\n    INSTALLUI_HANDLERW pfnPreviousExternalUI;\n    INSTALLUI_HANDLER_RECORD pfnPreviousExternalUIRecord;\n\n    BOOL fSetPreviousExternalUIRecord;\n    BOOL fSetPreviousExternalUI;\n} WIU_MSI_EXECUTE_CONTEXT;\n\n\n// typedefs\ntypedef UINT (WINAPI *PFN_MSIENABLELOGW)(\n    __in DWORD dwLogMode,\n    __in_z LPCWSTR szLogFile,\n    __in DWORD dwLogAttributes\n    );\ntypedef UINT (WINAPI *PFN_MSIGETPRODUCTINFOW)(\n    __in LPCWSTR szProductCode,\n    __in LPCWSTR szProperty,\n    __out_ecount_opt(*pcchValue) LPWSTR szValue,\n    __inout LPDWORD pcchValue\n    );\ntypedef INSTALLSTATE (WINAPI *PFN_MSIGETCOMPONENTPATHW)(\n    __in LPCWSTR szProduct,\n    __in LPCWSTR szComponent,\n    __out_ecount_opt(*pcchBuf) LPWSTR lpPathBuf,\n    __inout_opt LPDWORD pcchBuf\n    );\ntypedef INSTALLSTATE (WINAPI *PFN_MSILOCATECOMPONENTW)(\n    __in LPCWSTR szComponent,\n    __out_ecount_opt(*pcchBuf) LPWSTR lpPathBuf,\n    __inout_opt LPDWORD pcchBuf\n    );\ntypedef UINT (WINAPI *PFN_MSIGETPRODUCTINFOEXW)(\n    __in LPCWSTR szProductCode,\n    __in_opt LPCWSTR szUserSid,\n    __in MSIINSTALLCONTEXT dwContext,\n    __in LPCWSTR szProperty,\n    __out_ecount_opt(*pcchValue) LPWSTR szValue,\n    __inout_opt LPDWORD pcchValue\n    );\ntypedef INSTALLSTATE (WINAPI *PFN_MSIQUERYFEATURESTATEW)(\n    __in LPCWSTR szProduct,\n    __in LPCWSTR szFeature\n    );\ntypedef UINT (WINAPI *PFN_MSIGETPATCHINFOEXW)(\n    __in_z LPCWSTR wzPatchCode,\n    __in_z LPCWSTR wzProductCode,\n    __in_z_opt LPCWSTR wzUserSid,\n    __in MSIINSTALLCONTEXT dwContext,\n    __in_z LPCWSTR wzProperty,\n    __out_opt LPWSTR wzValue,\n    __inout DWORD* pcchValue\n    );\ntypedef UINT (WINAPI *PFN_MSIDETERMINEPATCHSEQUENCEW)(\n    __in_z LPCWSTR wzProductCode,\n    __in_z_opt LPCWSTR wzUserSid,\n    __in MSIINSTALLCONTEXT context,\n    __in DWORD cPatchInfo,\n    __in PMSIPATCHSEQUENCEINFOW pPatchInfo\n    );\ntypedef UINT (WINAPI *PFN_MSIINSTALLPRODUCTW)(\n    __in LPCWSTR szPackagePath,\n    __in_opt LPCWSTR szCommandLine\n    );\ntypedef UINT (WINAPI *PFN_MSICONFIGUREPRODUCTEXW)(\n    __in LPCWSTR szProduct,\n    __in int iInstallLevel,\n    __in INSTALLSTATE eInstallState,\n    __in_opt LPCWSTR szCommandLine\n    );\ntypedef UINT (WINAPI *PFN_MSIREMOVEPATCHESW)(\n    __in_z LPCWSTR wzPatchList,\n    __in_z LPCWSTR wzProductCode,\n    __in INSTALLTYPE eUninstallType,\n    __in_z_opt LPCWSTR szPropertyList\n    );\ntypedef INSTALLUILEVEL (WINAPI *PFN_MSISETINTERNALUI)(\n    __in INSTALLUILEVEL dwUILevel,\n    __inout_opt HWND *phWnd\n    );\ntypedef UINT (WINAPI *PFN_MSISETEXTERNALUIRECORD)(\n    __in_opt INSTALLUI_HANDLER_RECORD puiHandler,\n    __in DWORD dwMessageFilter,\n    __in_opt LPVOID pvContext,\n    __out_opt PINSTALLUI_HANDLER_RECORD ppuiPrevHandler\n    );\ntypedef INSTALLUI_HANDLERW (WINAPI *PFN_MSISETEXTERNALUIW)(\n    __in_opt INSTALLUI_HANDLERW puiHandler,\n    __in DWORD dwMessageFilter,\n    __in_opt LPVOID pvContext\n    );\ntypedef UINT (WINAPI *PFN_MSIENUMPRODUCTSW)(\n    __in DWORD iProductIndex,\n    __out_ecount(MAX_GUID_CHARS + 1) LPWSTR lpProductBuf\n    );\ntypedef UINT (WINAPI *PFN_MSIENUMPRODUCTSEXW)(\n    __in_z_opt LPCWSTR wzProductCode,\n    __in_z_opt LPCWSTR wzUserSid,\n    __in DWORD dwContext,\n    __in DWORD dwIndex,\n    __out_opt WCHAR wzInstalledProductCode[39],\n    __out_opt MSIINSTALLCONTEXT *pdwInstalledContext,\n    __out_opt LPWSTR wzSid,\n    __inout_opt LPDWORD pcchSid\n    );\n\ntypedef UINT (WINAPI *PFN_MSIENUMRELATEDPRODUCTSW)(\n    __in LPCWSTR lpUpgradeCode,\n    __reserved DWORD dwReserved,\n    __in DWORD iProductIndex,\n    __out_ecount(MAX_GUID_CHARS + 1) LPWSTR lpProductBuf\n    );\ntypedef UINT (WINAPI *PFN_MSISOURCELISTADDSOURCEEXW)(\n    __in LPCWSTR szProductCodeOrPatchCode,\n    __in_opt LPCWSTR szUserSid,\n    __in MSIINSTALLCONTEXT dwContext,\n    __in DWORD dwOptions,\n    __in LPCWSTR szSource,\n    __in_opt DWORD dwIndex\n    );\n\n\nHRESULT DAPI WiuInitialize(\n    );\nvoid DAPI WiuUninitialize(\n    );\nvoid DAPI WiuFunctionOverride(\n    __in_opt PFN_MSIENABLELOGW pfnMsiEnableLogW,\n    __in_opt PFN_MSIGETCOMPONENTPATHW pfnMsiGetComponentPathW,\n    __in_opt PFN_MSILOCATECOMPONENTW pfnMsiLocateComponentW,\n    __in_opt PFN_MSIQUERYFEATURESTATEW pfnMsiQueryFeatureStateW,\n    __in_opt PFN_MSIGETPRODUCTINFOW pfnMsiGetProductInfoW,\n    __in_opt PFN_MSIGETPRODUCTINFOEXW pfnMsiGetProductInfoExW,\n    __in_opt PFN_MSIINSTALLPRODUCTW pfnMsiInstallProductW,\n    __in_opt PFN_MSICONFIGUREPRODUCTEXW pfnMsiConfigureProductExW,\n    __in_opt PFN_MSISETINTERNALUI pfnMsiSetInternalUI,\n    __in_opt PFN_MSISETEXTERNALUIW pfnMsiSetExternalUIW,\n    __in_opt PFN_MSIENUMRELATEDPRODUCTSW pfnMsiEnumRelatedProductsW,\n    __in_opt PFN_MSISETEXTERNALUIRECORD pfnMsiSetExternalUIRecord,\n    __in_opt PFN_MSISOURCELISTADDSOURCEEXW pfnMsiSourceListAddSourceExW\n    );\nHRESULT DAPI WiuGetComponentPath(\n    __in_z LPCWSTR wzProductCode,\n    __in_z LPCWSTR wzComponentId,\n    __out INSTALLSTATE* pInstallState,\n    __out_z LPWSTR* psczValue\n    );\nHRESULT DAPI WiuLocateComponent(\n    __in_z LPCWSTR wzComponentId,\n    __out INSTALLSTATE* pInstallState,\n    __out_z LPWSTR* psczValue\n    );\nHRESULT DAPI WiuQueryFeatureState(\n    __in_z LPCWSTR wzProduct,\n    __in_z LPCWSTR wzFeature,\n    __out INSTALLSTATE* pInstallState\n    );\nHRESULT DAPI WiuGetProductInfo(\n    __in_z LPCWSTR wzProductCode,\n    __in_z LPCWSTR wzProperty,\n    __out LPWSTR* psczValue\n    );\nHRESULT DAPI WiuGetProductInfoEx(\n    __in_z LPCWSTR wzProductCode,\n    __in_z_opt LPCWSTR wzUserSid,\n    __in MSIINSTALLCONTEXT dwContext,\n    __in_z LPCWSTR wzProperty,\n    __out LPWSTR* psczValue\n    );\nHRESULT DAPI WiuGetProductProperty(\n    __in MSIHANDLE hProduct,\n    __in_z LPCWSTR wzProperty,\n    __out LPWSTR* psczValue\n    );\nHRESULT DAPI WiuGetPatchInfoEx(\n    __in_z LPCWSTR wzPatchCode,\n    __in_z LPCWSTR wzProductCode,\n    __in_z_opt LPCWSTR wzUserSid,\n    __in MSIINSTALLCONTEXT dwContext,\n    __in_z LPCWSTR wzProperty,\n    __out LPWSTR* psczValue\n    );\nHRESULT DAPI WiuDeterminePatchSequence(\n    __in_z LPCWSTR wzProductCode,\n    __in_z_opt LPCWSTR wzUserSid,\n    __in MSIINSTALLCONTEXT context,\n    __in PMSIPATCHSEQUENCEINFOW pPatchInfo,\n    __in DWORD cPatchInfo\n    );\nHRESULT DAPI WiuEnumProducts(\n    __in DWORD iProductIndex,\n    __out_ecount(MAX_GUID_CHARS + 1) LPWSTR wzProductCode\n    );\nHRESULT DAPI WiuEnumProductsEx(\n    __in_z_opt LPCWSTR wzProductCode,\n    __in_z_opt LPCWSTR wzUserSid,\n    __in DWORD dwContext,\n    __in DWORD dwIndex,\n    __out_opt WCHAR wzInstalledProductCode[39],\n    __out_opt MSIINSTALLCONTEXT *pdwInstalledContext,\n    __out_opt LPWSTR wzSid,\n    __inout_opt LPDWORD pcchSid\n    );\nHRESULT DAPI WiuEnumRelatedProducts(\n    __in_z LPCWSTR wzUpgradeCode,\n    __in DWORD iProductIndex,\n    __out_ecount(MAX_GUID_CHARS + 1) LPWSTR wzProductCode\n    );\nHRESULT DAPI WiuEnableLog(\n    __in DWORD dwLogMode,\n    __in_z LPCWSTR wzLogFile,\n    __in DWORD dwLogAttributes\n    );\nHRESULT DAPI WiuInitializeExternalUI(\n    __in PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler,\n    __in INSTALLUILEVEL internalUILevel,\n    __in HWND hwndParent,\n    __in LPVOID pvContext,\n    __in BOOL fRollback,\n    __in WIU_MSI_EXECUTE_CONTEXT* pExecuteContext\n    );\nvoid DAPI WiuUninitializeExternalUI(\n    __in WIU_MSI_EXECUTE_CONTEXT* pExecuteContext\n    );\nHRESULT DAPI WiuConfigureProductEx(\n    __in_z LPCWSTR wzProduct,\n    __in int iInstallLevel,\n    __in INSTALLSTATE eInstallState,\n    __in_z LPCWSTR wzCommandLine,\n    __out WIU_RESTART* pRestart\n    );\nHRESULT DAPI WiuInstallProduct(\n    __in_z LPCWSTR wzPackagPath,\n    __in_z LPCWSTR wzCommandLine,\n    __out WIU_RESTART* pRestart\n    );\nHRESULT DAPI WiuRemovePatches(\n    __in_z LPCWSTR wzPatchList,\n    __in_z LPCWSTR wzProductCode,\n    __in_z LPCWSTR wzPropertyList,\n    __out WIU_RESTART* pRestart\n    );\nHRESULT DAPI WiuSourceListAddSourceEx(\n    __in_z LPCWSTR wzProductCodeOrPatchCode,\n    __in_z_opt LPCWSTR wzUserSid,\n    __in MSIINSTALLCONTEXT dwContext,\n    __in DWORD dwCode,\n    __in_z LPCWSTR wzSource,\n    __in_opt DWORD dwIndex\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/wuautil.h",
    "content": "//-------------------------------------------------------------------------------------------------\n// <copyright file=\"wuautil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n//\n// <summary>\n//    Header for Windows Update Agent helpers.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n#pragma once\n\n\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\nHRESULT DAPI WuaPauseAutomaticUpdates();\n\nHRESULT DAPI WuaResumeAutomaticUpdates();\n\nHRESULT DAPI WuaRestartRequired(\n    __out BOOL* pfRestartRequired\n    );\n\n#if defined(__cplusplus)\n}\n#endif"
  },
  {
    "path": "scripts/windows/installer/WiXSDK/inc/xmlutil.h",
    "content": "#pragma once\n//-------------------------------------------------------------------------------------------------\n// <copyright file=\"xmlutil.h\" company=\"Outercurve Foundation\">\n//   Copyright (c) 2004, Outercurve Foundation.\n//   This software is released under Microsoft Reciprocal License (MS-RL).\n//   The license and further copyright text can be found in the file\n//   LICENSE.TXT at the root directory of the distribution.\n// </copyright>\n// \n// <summary>\n//    XML helper functions.\n// </summary>\n//-------------------------------------------------------------------------------------------------\n\n// constant XML CLSIDs and IIDs\nextern __declspec(selectany) const CLSID XmlUtil_CLSID_DOMDocument   = {0x2933BF90, 0x7B36, 0x11d2, {0xB2, 0x0E, 0x00, 0xC0, 0x4F, 0x98, 0x3E, 0x60}};\nextern __declspec(selectany) const CLSID XmlUtil_CLSID_DOMDocument20  = {0xF6D90F11, 0x9C73, 0x11D3, {0xB3, 0x2E, 0x00, 0xC0, 0x4F, 0x99, 0x0B, 0xB4}};\nextern __declspec(selectany) const CLSID XmlUtil_CLSID_DOMDocument26 = {0xf5078f1b, 0xc551, 0x11d3, {0x89, 0xb9, 0x00, 0x00, 0xf8, 0x1f, 0xe2, 0x21}};\nextern __declspec(selectany) const CLSID XmlUtil_CLSID_DOMDocument30 = {0xf5078f32, 0xc551, 0x11d3, {0x89, 0xb9, 0x00, 0x00, 0xf8, 0x1f, 0xe2, 0x21}};\nextern __declspec(selectany) const CLSID XmlUtil_CLSID_DOMDocument40 = {0x88d969c0, 0xf192, 0x11d4, {0xa6, 0x5f, 0x00, 0x40, 0x96, 0x32, 0x51, 0xe5}};\nextern __declspec(selectany) const CLSID XmlUtil_CLSID_DOMDocument50 = {0x88d969e5, 0xf192, 0x11d4, {0xa6, 0x5f, 0x00, 0x40, 0x96, 0x32, 0x51, 0xe5}};\nextern __declspec(selectany) const CLSID XmlUtil_CLSID_DOMDocument60 = {0x88d96a05, 0xf192, 0x11d4, {0xa6, 0x5f, 0x00, 0x40, 0x96, 0x32, 0x51, 0xe5}};\nextern __declspec(selectany) const CLSID XmlUtil_CLSID_XMLSchemaCache = {0x88d969c2, 0xf192, 0x11d4, {0xa6, 0x5f, 0x00, 0x40, 0x96, 0x32, 0x51, 0xe5}};\n\nextern __declspec(selectany) const IID XmlUtil_IID_IXMLDOMDocument =  {0x2933BF81, 0x7B36, 0x11D2, {0xB2, 0x0E, 0x00, 0xC0, 0x4F, 0x98, 0x3E, 0x60}};\nextern __declspec(selectany) const IID XmlUtil_IID_IXMLDOMDocument2 = {0x2933BF95, 0x7B36, 0x11D2, {0xB2, 0x0E, 0x00, 0xC0, 0x4F, 0x98, 0x3E, 0x60}};\nextern __declspec(selectany) const IID XmlUtil_IID_IXMLDOMSchemaCollection = {0x373984C8, 0xB845, 0x449B, {0x91, 0xE7, 0x45, 0xAC, 0x83, 0x03, 0x6A, 0xDE}};\n\nenum XML_LOAD_ATTRIBUTE\n{\n    XML_LOAD_PRESERVE_WHITESPACE = 1,\n};\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nHRESULT DAPI XmlInitialize();\nvoid DAPI XmlUninitialize();\n\nHRESULT DAPI XmlCreateElement(\n    __in IXMLDOMDocument *pixdDocument,\n    __in_z LPCWSTR wzElementName,\n    __out IXMLDOMElement **ppixnElement\n    );\nHRESULT DAPI XmlCreateDocument(\n    __in_opt LPCWSTR pwzElementName, \n    __out IXMLDOMDocument** ppixdDocument,\n    __out_opt IXMLDOMElement** ppixeRootElement = NULL\n    );\nHRESULT DAPI XmlLoadDocument(\n    __in_z LPCWSTR wzDocument,\n    __out IXMLDOMDocument** ppixdDocument\n    );\nHRESULT DAPI XmlLoadDocumentEx(\n    __in_z LPCWSTR wzDocument,\n    __in DWORD dwAttributes,\n    __out IXMLDOMDocument** ppixdDocument\n    );\nHRESULT DAPI XmlLoadDocumentFromFile(\n    __in_z LPCWSTR wzPath,\n    __out IXMLDOMDocument** ppixdDocument\n    );\nHRESULT DAPI XmlLoadDocumentFromBuffer(\n    __in_bcount(cbSource) const BYTE* pbSource,\n    __in DWORD cbSource,\n    __out IXMLDOMDocument** ppixdDocument\n    );\nHRESULT DAPI XmlLoadDocumentFromFileEx(\n    __in_z LPCWSTR wzPath,\n    __in DWORD dwAttributes,\n    __out IXMLDOMDocument** ppixdDocument\n    );\nHRESULT DAPI XmlSelectSingleNode(\n    __in IXMLDOMNode* pixnParent,\n    __in_z LPCWSTR wzXPath,\n    __out IXMLDOMNode **ppixnChild\n    );\nHRESULT DAPI XmlSetAttribute(\n    __in IXMLDOMNode* pixnNode,\n    __in_z LPCWSTR pwzAttribute,\n    __in_z LPCWSTR pwzAttributeValue\n    );\nHRESULT DAPI XmlCreateTextNode(\n    __in IXMLDOMDocument *pixdDocument,\n    __in_z LPCWSTR wzText,\n    __out IXMLDOMText **ppixnTextNode\n    );\nHRESULT DAPI XmlGetText(\n    __in IXMLDOMNode* pixnNode,\n    __deref_out_z BSTR* pbstrText\n    );\nHRESULT DAPI XmlGetAttribute(\n    __in IXMLDOMNode* pixnNode,\n    __in_z LPCWSTR pwzAttribute,\n    __deref_out_z BSTR* pbstrAttributeValue\n    );\nHRESULT DAPI XmlGetAttributeEx(\n    __in IXMLDOMNode* pixnNode,\n    __in_z LPCWSTR wzAttribute,\n    __deref_out_z LPWSTR* psczAttributeValue\n    );\nHRESULT DAPI XmlGetYesNoAttribute(\n    __in IXMLDOMNode* pixnNode,\n    __in_z LPCWSTR wzAttribute,\n    __out BOOL* pfYes\n    );\nHRESULT DAPI XmlGetAttributeNumber(\n    __in IXMLDOMNode* pixnNode,\n    __in_z LPCWSTR pwzAttribute,\n    __out DWORD* pdwValue\n    );\nHRESULT DAPI XmlGetAttributeNumberBase(\n    __in IXMLDOMNode* pixnNode,\n    __in_z LPCWSTR pwzAttribute,\n    __in int nBase,\n    __out DWORD* pdwValue\n    );\nHRESULT DAPI XmlGetAttributeLargeNumber(\n    __in IXMLDOMNode* pixnNode,\n    __in_z LPCWSTR pwzAttribute,\n    __out DWORD64* pdw64Value\n    );\nHRESULT DAPI XmlGetNamedItem(\n    __in IXMLDOMNamedNodeMap *pixnmAttributes, \n    __in_opt LPCWSTR wzName, \n    __out IXMLDOMNode **ppixnNamedItem\n    );\nHRESULT DAPI XmlSetText(\n    __in IXMLDOMNode* pixnNode,\n    __in_z LPCWSTR pwzText\n    );\nHRESULT DAPI XmlSetTextNumber(\n    __in IXMLDOMNode *pixnNode,\n    __in DWORD dwValue\n    );\nHRESULT DAPI XmlCreateChild(\n    __in IXMLDOMNode* pixnParent,\n    __in_z LPCWSTR pwzElementType,\n    __out IXMLDOMNode** ppixnChild\n    );\nHRESULT DAPI XmlRemoveAttribute(\n    __in IXMLDOMNode* pixnNode,\n    __in_z LPCWSTR pwzAttribute\n    );\nHRESULT DAPI XmlSelectNodes(\n    __in IXMLDOMNode* pixnParent,\n    __in_z LPCWSTR wzXPath,\n    __out IXMLDOMNodeList **ppixnChild\n    );\nHRESULT DAPI XmlNextAttribute(\n    __in IXMLDOMNamedNodeMap* pixnnm,\n    __out IXMLDOMNode** pixnAttribute,\n    __deref_opt_out_z_opt BSTR* pbstrAttribute\n    );\nHRESULT DAPI XmlNextElement(\n    __in IXMLDOMNodeList* pixnl,\n    __out IXMLDOMNode** pixnElement,\n    __deref_opt_out_z_opt BSTR* pbstrElement\n    );\nHRESULT DAPI XmlRemoveChildren(\n    __in IXMLDOMNode* pixnSource,\n    __in_z LPCWSTR pwzXPath\n    );\nHRESULT DAPI XmlSaveDocument(\n    __in IXMLDOMDocument* pixdDocument, \n    __inout LPCWSTR wzPath\n    );\nHRESULT DAPI XmlSaveDocumentToBuffer(\n    __in IXMLDOMDocument* pixdDocument,\n    __deref_out_bcount(*pcbDest) BYTE** ppbDest,\n    __out DWORD* pcbDest\n    );\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "scripts/windows/installer/build.bat",
    "content": "@echo off\n\nset MSBUILD=\"%SystemRoot%\\Microsoft.NET\\Framework\\v4.0.30319\\msbuild.exe\"\n\n\nIF \"%1\"==\"\" GOTO :BUILD\nIF \"%1\"==\"clean\" GOTO :CLEAN\n\n:BUILD\n\nif not exist Release md Release\n\necho Building WiXBalExtension...\npushd WiXBalExtension\nCall Build\npopd\n\nrem GOTO :Installer\n\necho Building custom action collection 32-bit library (WiXHelper project)\n%MSBUILD% WiXHelper\\WiXHelper.vcxproj /t:Rebuild /p:Configuration=\"Release\" /p:Platform=Win32 /p:DefineConstants=\"TRACE\" /clp:ErrorsOnly\nif %errorlevel% neq 0 (\n\techo Build failed.\n\trem pause\n\tgoto :EOF\n)\n\n\nrem We don't have a 64 bit msi package, so I will command this\nrem echo Building custom action collection 64-bit library (WiXHelper project)\nrem %MSBUILD% WiXHelper\\WiXHelper.vcxproj /t:Rebuild /p:Configuration=\"Release\" /p:Platform=x64 /p:DefineConstants=\"TRACE\" /clp:ErrorsOnly\nrem if %errorlevel% neq 0 (\nrem \techo Build failed.\nrem \tpause\nrem \tgoto :EOF\nrem )\n\n\n:Installer\n\necho Building Meteor installer package...\n%MSBUILD% MeteorSetup.sln /t:Rebuild /p:Configuration=\"Release\" /p:Platform=\"x86\" /p:DefineConstants=\"TRACE\" /clp:ErrorsOnly\nif %errorlevel% neq 0 (\n\techo Build failed\n\trem pause\n\tgoto :EOF\n)\n\n\ngoto :EOF\n\nREM *****************************************************************\nREM End of Main\nREM *****************************************************************\n\n\n:CLEAN\nIF EXIST WiXHelper\\*.sdf DEL /Q WiXHelper\\*.sdf\nIF EXIST WiXHelper\\*.suo DEL /Q /A:H WiXHelper\\*.suo\nIF EXIST WiXBalExtension\\*.sdf DEL /Q WiXBalExtension\\*.sdf\nIF EXIST WiXBalExtension\\*.suo DEL /Q /A:H WiXBalExtension\\*.suo\n\nCall :DeleteDir \"ipch\"\nCall :DeleteDir \"WiXHelper\\ipch\"\nCall :DeleteDir \"WiXHelper\\bin\"\nCall :DeleteDir \"WiXHelper\\obj\"\nCall :DeleteDir \"WiXInstaller\\bin\"\nCall :DeleteDir \"WiXInstaller\\obj\"\nCall :DeleteDir \"WiXBalExtension\\ipch\"\nCall :DeleteDir \"WiXBalExtension\\wixstdba\\Release\"\nCall :DeleteDir \"WiXBalExtension\\wixstdba\\Debug\"\nCall :DeleteDir \"WiXBalExtension\\wixlib\\obj\"\nCall :DeleteDir \"WiXBalExtension\\wixext\\obj\"\nCall :DeleteDir \"WiXBalExtension\\wixext\\bin\"\nCall :DeleteDir \"WiXBalExtension\\bafunctions\\Release\"\nCall :DeleteDir \"WiXBalExtension\\bafunctions\\Debug\"\nCall :DeleteDir \"WiXBalExtension\\build\\Xsd\"\n\nfor /f \"usebackq delims=\" %%I in (`dir /s /b WiXBalExtension\\build\\*`) do if not %%~nxI==WixBalExtensionExt.dll del /Q \"%%I\"\ngoto :EOF\n\n\n\nREM *****************************************************************\nREM Delete/create directory\nREM *****************************************************************\n:DeleteDir\nrd %1% /q/s 2>nul 1>nul\ngoto :EOF\n\n\n\n"
  },
  {
    "path": "tools/PERFORMANCE.md",
    "content": "There's a lot of interest in improving the performance of the Meteor\ncommand-line tool and build system, and if you're interesting in helping,\nthis document is meant to be a jumping off point.\n\nSooner or later, the tool will be inevitably be substantially rewritten or \nreplaced in order to achieve those sweet sub-second build times everyone loves,\nbecause it is currently too complex and reliant on the file system to get there.\nHowever, until then, there's work that can be done to make things faster.\n\nFor more on the tool, see also the README files in this directory and its\nsub-directories.\n\n## Profiling\n\nThe best way to get information about where time is going in the Meteor tool is with built-in profiler, activated with the environment variable `METEOR_PROFILE`.  The value is interpreted as a threshold in ms, so the value `1` means to report on all calls that take more than 1ms:\n\n```bash\nMETEOR_PROFILE=1 meteor ...\n```\n\nYou'll then see a report (or a series of reports) printed to the console that might look something like:\n\n```\n| (#1) Profiling: ProjectContext prepareProjectForBuild\n| ProjectContext prepareProjectForBuild..........9,207 ms (1)\n|    _initializeCatalog.............................24 ms (1)\n|       files.readFile                               7 ms (2)\n|       runJavaScript package.js                     2 ms (1)\n|       files.rm_recursive                           4 ms (4)\n|       other _initializeCatalog                    11 ms\n|    _resolveConstraints.........................6,702 ms (1)\n|       bundler.readJsImage.........................42 ms (1)\n...\n| (#1) Total: 9,544 ms (ProjectContext prepareProjectForBuild)\n```\n\nThe report is a simple top-down listing, where each entry represents a function call or other instrumented block in the code.  A dotted line is drawn for entries that have child entries, and the total time of the child entries should add up to the parent entry (though turning up the profiling threshold may mess with the math).  The number in parentheses is the number of times that function or block was called, and the time listed is the total cumulative time of all the calls.\n\nEntries in the profiler come from annotations that instrument code, and unlike what you get with sampling profilers (like `node --prof` or dtrace), the call counts are exact.  All times are measured with high-resolution wall-clock timers and only rounded for display.  However, time measurements are quite susceptible to being inflated by random acts of garbage collection; profiler overhead; competition for the CPU; and so on.  Also, if the tool were more highly parallelized, these stopwatch-type measurements might stop adding up, but so far they've been pretty accurate as far as we know.\n\nPlease see the section \"Performance Considerations\" before interpreting a profiler report.\n\n## Performance Considerations\n\nRead this section before drawing conclusions or comparing numbers online.\n\nThe Meteor build tool is complex and has several layers of caches and modes of operation.  It's not apples-to-apples to compare a rebuild time between a Meteor release and a checkout, for example, or to compare a start-up with a cold cache to one with a warm cache.  This section lists the various nuances of build tool performance.\n\n### Unreported Work\n\nNot everything is covered by the reports we generate (\"prepare project\" and \"build app\").  For example, you won't see:\n\n* Time spent in app start-up\n* Time spent creating file watchers after a rebuild\n\n### Caching\n\nThe tool saves work using various disk caches and in-memory caches.  There are caches of:\n\n* Built packages and plugins\n* Compiler plugin results - and not just on the most recent version of a file!  If you are testing rebuilds by toggling a character back and forth, you may hit cache.\n* Linker output\n* The entire server program, for client-only changes\n* Constraint solver results\n\nTherefore, app start-up will be slow if the disk caches haven't been generated or are invalid because a package needs to be rebuilt, for instance, or the constraint solver needs to run.  Rebuilds are much faster than the initial build of the app, and the second rebuild even seems to be faster than the first, at which point the time levels off.\n\nSee the section \"More About Caches\".\n\n### Release vs. Checked-Out Branch\n\nThe Meteor tool behaves differently depending on whether you are running a Meteor release, or a checked-out branch of a git repository.  Most people run a Meteor release, but if you are making any changes to the tool or core packages, you'll be running Meteor in checked-out mode for testing, debugging, and measurement, so it's important to know the discrepancies.  (See also \"More About Release vs. Branch\".)\n\nThe following are performance-related differences between running an app with\na release of Meteor vs. a checked-out branch of Meteor:\n\n* Checked-out Meteor recompiles core packages.  When you run an app using checked-out Meteor, it will compile core packages into `APP/.meteor/local/isopacks` -- that's right, into your app!  This process can take a while -- as much as a couple minutes -- but it's only done once per package per app, unless the package changes.  When the app starts up, it will read in the built packages and decide if it needs to do anything.  However, there's noticeable extra time \"preparing\" for each rebuild, because the core packages are rescanned, and the large number of files being watched for\nchanges can cause several seconds of delay after a rebuild as well.\n\n* Constraint-solver performance is different.  Core packages are constrained\nby a release and also by running from checkout, but the effect is different, \nand the constraint solver seems to have an easier time on the constraint\nproblems it gets when running from checkout, because of the way core packages\nare pinned like local packages.\n\n* Constraint-solver won't save `APP/.meteor/versions` if there's a release in \n  `APP/.meteor/release`.  Normally, when running released Meteor,\n  `APP/.meteor/versions` provide stability to your package versions between\n  runs of your app.  However, when you run `REPO/meteor`, core package versions\n  are temporarily overridden by the versions in the repo, but not saved, unless \n  `APP/.meteor/release` is set to `none`, meaning the app is not written against\n  a released version of Meteor.  This difference comes up when testing and\n  measuring the behavior of the constraint solver.\n\nTime spent rebundling and rebuilding the app seems pretty similar across\nRelease and Checkout.\n\n### App Differences\n\nDifferent apps can strain different parts of the Meteor tool, such as:\n\n* Constraint solver - lots of dependencies; large package graph\n* File watchers - lots of total files, e.g. thousands\n* Modules - as of Meteor 1.3, imports from packages and `node_modules` must be scanned and analyzed\n* CSS processing - e.g. in case of a large LESS or Sass framework in the app\n* Community plugins, including legacy plugins without caching between builds\n\n### Hardware and OS\n\nSpinning disks are much slower than SSDs.\n\nWindows has a very different file system from Mac OS X or Linux.\n\nOn OS X and Linux, we have all these nice properties:\n* Usable symlinks\n* Renaming a file is cheap\n* Overwriting a file by rename is atomic\n* An file can be deleted (\"unlinked\") while open\n* A file can be moved (renamed) while open\n\nWindows doesn't have these properties; for example, renaming a file is\na copy operation.  In addition, virus scanners and other software will\nsometimes block or postpone file operations.  And, of course, there are\nthe path separator differences.  Parts of the tool work really hard to\ntarget OS X and Linux efficiently (with symlinks and renames, for example)\nwhile doing something that behaves well on Windows, even if it's slower.\n\n## Instrumenting Code for the Profiler\n\nIf you see a large time next to \"other (function)\", that's a case where the tool needs further instrumentation.  For example, you may see something like this:\n\n```\n| ImportScanner#_readFile...............1,338 ms (329)\n|    files.readFile                       100 ms (329)\n|    sha1                                   3 ms (329)\n|    other ImportScanner#_readFile      1,235 ms\n```\n\nIn this example, some function calls under `ImportScanner#_readFile` just happen to be instrumented (`files.readFile` and `sha1`), but no other calls under `ImportScanner#_readFile` have been annotated yet.  Given how much time is spent in this call, we should seek out more calls to annotate.  You can determine by experimentation which calls are significant enough to add to the profile.\n\nTo annotate a function or block in tool code to be included in the profile, use one of the following forms:\n\n```\n// Profile(.) takes a function and wraps it, preserving arguments\n// and this.  You can often get away without introducing any extra\n// indentation in your text editor.\nvar doIt = Profile(\"doIt\", function (...) {\n  ...\n});\n\n// Wrap a method\nMyClass.prototype.doIt =\n  Profile(\"MyClass doIt\", MyClass.prototype.doIt);\n\n// Profile.time(.) invokes a block immediately and times it,\n// passing the return value through.\nfunction doIt() {\n  ...\n  var result = Profile.time(\"doIt\", () => {\n    ...\n  });\n  ...\n}\n```\n\nThe Profiler is activated using `Profile.run(.)`, which will cause a report to be generated.  Currently we generate a couple reports when `METEOR_PROFILE` is set -- one for preparing the project (including constraint solving) and one for building or rebuilding the app.\n\nIn addition to tool code, you can also use `Profile` in compiler plugins.  If you want to use `Profile` in packages that are loaded into the tool (e.g. packages depended on by compiler plugins, or specially loaded into the tool as isopackets), you should always test `(typeof Profile !== 'undefined')` before accessing `Profile`, or pass it in from the tool as an option.\n\n## Known Areas for Improvement\n\nThese are areas to improve or investigate, along with what's known, in no\nparticular order.\n\n### CSS Minification\n\nSee: https://github.com/meteor/meteor/pull/5875.\n\nMeteor's CSS minification is user-pluggable since 1.2.  What the standard\nminifier does is concatenate your CSS into one file with `import` statements\nhoisted to the top.  In production mode, this file is minified before being\nserved.  The benefit of doing the same CSS merging in development and\nproduction is that the meanings of relative paths in CSS files and the order\nof rules doesn't change.  However, reparsing and merging the CSS for a typical\napp can take anywhere from 500ms to a couple seconds or more, depending on\nthe amount of CSS.\n\nInitial profiling shows the time is split between different operations like\nparsing CSS, generating CSS, and working with source maps.  Approaches could include:\n\n* Inserting a new cache, such as around parsing files\n* Only recalculating the CSS if it changes\n* Using a faster CSS library\n\n### Source Maps\n\nThe tool spends noticeable building source maps, as do other tools such as\nWebpack, which have evolved creative mechanisms to cut down the time.\nThere's some question of whether the `source-map` library is as efficient\nas it could be, and whether we're using it as efficiently as we could be.\n\n### Linker Cache\n\nSee: https://github.com/meteor/meteor/issues/5818\n\nThe \"linker cache\" on disk at `APP/.meteor/local/bundler-cache/linker` has some\nvery large files that take a long time write, and they are apparently not\ncleaned up either.  Sometimes you will see calls to `files.writeFileAtomically`\ntaking many seconds at the top of the \"Rebuild App\" report, but somehow outside\nthe top level (probably because they are fired off asynchronously).\n\n### Constraint Solving\n\nSome initial work has been done to make constraint solving fast in the typical\ncase where a previous solution exists in `APP/.meteor/versions`, but there is\npossible room for improvement.  For example, the previous solution could be\nchecked without invoking the logic solver at all, though the manual logic would\nhave to match closely.\n\nTime spent reading from the packages database (a SQLite file) could be understood\nbetter and improved by batching queries, reading less data, or using SQLite\nbetter.\n\nSee: https://github.com/meteor/meteor/issues/6137\n\n### \"Updating package catalog...\"\n\nTalking to the package server to download new package metadata seems to take\nlonger than it should; easily 5 seconds, based on watching the progress\ndisplay, and occasionally much longer.\n\n### Hoisting Build Work\n\nYou'll find scattered through the tool code comments about how it would be\nmore efficient to do certain processing or reading in a way such that it\nwouldn't have to be done a second time in a different part of the tool, or\nit wouldn't have to be done on each rebuild.  The first one is about the flow\nof information in the tool, and the second is about making better use of \ninformation about what changed, either through caching or file-watching.\n\n### File watching\n\nIt seems like it would be great if file-watching gave the tool perfect\ninformation, so it wouldn't have to go to disk and read lots of files\neven though, in theory, if they had changed it would know.  You can\nimagine a tool that is super fast because it basically reads and writes\ndiffs of the state of the file system.  It's not clear how feasible that\nis, though.  Right now, when we're told a file has changed, we immediately\ngo to work, which includes tearing down file-watchers; we don't wait to\nget the exact list of what files have changed.  For the tool to remain\nreceptive to changes would require a different paradigm.\n\nHowever, it seems like some middle ground would be possible, where the tool\ndoes not simply merge all the lists of files it has (\"WatchSets\") and wait\nfor any change to any of them, but where rather it responds to changes to\ndifferent sets of files by rebuilding different parts and then putting them\ntogether; for example, only processing the CSS if some CSS changed.\n\nIt also might be that changing to a different file-watching library would\nhave performance benefits.\n\n## More About Caches\n\nDisk caches exist in the following locations, where `APP` is the app:\n\n* `APP/.meteor/local/isopacks`\n* `APP/.meteor/local/bundler-cache`\n* `APP/.meteor/local/plugin-cache`\n* `~/.meteor` (package storage, when running a release)\n* `REPO/.meteor` (package storage, when running a checked-out branch)\n\nYou can safely remove these directories to clear your caches, but don't remove `APP/.meteor/local` if you have data in your app's database, because the local Mongo DB resides in `APP/.meteor/local/db`.  (If you don't care about the DB, you can remove all of `local` for the ultimate clean checkout experience.)  The package storage directory holds master copies of packages that will be copied or linked into your project (like Maven's `.m2`).  There's probably no reason to clear them out, except to save some disk space.  It's sometimes nice to know where these files are located in case you want to poke around or add `console.log`s to released code for debugging.\n\n## More About Release vs. Branch\n\nMost people run a released version of the `meteor` tool, but if you are making any changes to the tool or core packages, you'll be running it in checked-out mode for testing and debugging.  Here's how the two modes work:\n\n* Release: This is when you run the installed `meteor` tool on your computer.  The tool and core packages are part of a release with a name like `METEOR@1.2.1` and were downloaded from the package server and cached in `~/.meteor` along with other Atmosphere packages.  When the tool is run, the current release is determined from `APP/.meteor/release` when running an app, or the value of `--release` on the command-line.\n\n* Checked-Out Branch: This is when you check out the `meteor/meteor` GitHub repository as `REPO` and run `REPO/meteor`.  The tool is loaded from `REPO/tools`, and core packages are loaded from `REPO/packages`.  The tool takes care of transpiling itself and rebuilding out-of-date core packages.  Core packages in the repo behave much like local packages in your app; package `foo` is treated as the only known version of `foo`, and its files are watched for hot-reload."
  },
  {
    "path": "tools/README.md",
    "content": "# Meteor Tool\n\nThis part of the code-base is Meteor's CLI tool that reads commands from the\nuser, builds the application, adds runtime code, provides an interface to Meteor\nServices ([Accounts](https://www.meteor.com/services/developer-accounts),\n[Packages](https://www.meteor.com/services/package-server),\n[Build Farms](https://www.meteor.com/services/build), deployments, etc).\n\nThe Meteor Tool is designed to be the \"minimal kernel\" as most of the\nfunctionality that goes into a typical Meteor app can pulled from core and\n3rd-party packages.\n\n## Getting set up\n\nUsing Meteor in development is very simple. If Meteor spots that it is running\nfrom a Git checkout folder (having a `.git` directory), it will run in dev mode,\ndownload `npm` dependencies dynamically and pull the latest `dev_bundle` on the\nfirst run.\n\n`dev_bundle` is a tarball with prebuilt binaries (`node`, `npm`, `mongod`, etc)\nand npm modules necessary for the Meteor tool. `dev_bundle`s are versioned and\nare built with a script in the `admin` directory. It is commonly built on\n[Jenkins](http://jenkins.meteor.io/).\n\nUsually it doesn't take long to get a new `dev_bundle` but if you are on a\nspotty network or switching between branches referencing different versions\noften, you can set the environment variable that will cache all downloaded\nversions indefinitely:\n\n```bash\nset SAVE_DEV_BUNDLE_TARBALL=t\n```\n\nYou can also run `./meteor --get-ready` to install all npm dependencies for the\ntool.\n\nUsually, the `meteor` script can download a new dev-bundle without any\ndependencies installed, but on Windows, it requires `7z` to be in the path for\nunpacking of a tarball. (Get 7-zip [here](http://www.7-zip.org/))\n\n## Testing\n\nSince the tool is a node app, it is not testable with general Meteor testing\ntools such as Tinytest. Instead the home-grown system \"self test\" is\nused.\n\n\"Self test\" is a testing library that is focused on testing the CLI interactions\nand is rather an end-to-end testing tool (not a unit-testing tool). Albeit, it\nis often used for testing individual functions.\n\nBesides monitoring the process output, \"self test\" is capable of mocking the\npackage catalog and running from template apps.\n\nThe asserting syntax of \"self test\" is rather unusual since it operates on the\nprocess's stdout/stderr output after the process has run (not in real-time).\nA lot of assertions depend on timeouts and waits.\n\nTo run all tests, run the following:\n\n```bash\n# download all npm dependencies, etc\n./meteor --get-ready\n\n# set the multiplier for time-outs\nset TIMEOUT_SCALE_FACTOR=3\n\n# run the tests\n./meteor self-test\n```\n\nNote, the scale factor for time-outs might be different depending on the\nhardware, but 3 is a safe choice for automation.\n\nTo quickly run an individual test or a group, pass a regular expression as an\nargument, it will be matched against test names:\n\n```bash\n./meteor self-test \"login.*\"\n```\n\nYou can also run a particular file, or list all tests matching certain\npattern, run with phantom or browserstack.\nSee more at `./meteor help self-test`.\n\nIf you want to learn how to write a self-test, see the `tool-testing`\nsubdirectory.\n\n\n## Profiling\n\nProfiling is done in an ad-hoc way but it works well enough to spot obvious\ndifferences in things like build performance.\n\nTo enable profiling, set the environment variable to a \"cut off\" point, which is\n100ms by default.\n\n```bash\nset METEOR_PROFILE=200\n```\n\nIn this case, the reporter will only print calls that took more than 200ms to\ncomplete.\n\nInternally, every profiled function should be wrapped into a `Profile(fn)` call.\nThe entry point should be started explicitly with the `Profile.run()`\ncall. Otherwise, it won't start measuring anything.\n\n## Debugging\n\nCurrently, to debug the tool with `node-inspector`, you can set the `\nTOOL_NODE_FLAGS` environment variable to be `--debug` or `--debug-brk`. This\nwill modify the `meteor` bash script and run the tool with debugging enabled.\nThe debugger will be listening to port 5858 by default, but it could be\nchanged using the notation `--debug=6060` or `--debug-brk=6060`. Note that\n`node-inspector` should be compatible with the `node` version in the\n`dev_bundle`.\n\nNext, start `node-inspector` from your checkout by going to\n`path/to/your/meteor/dev_bundle/lib/node_modules/node-inspector/bin` and\nrun `inspector.js`.\nThis will tell you the URL of the node inspector. If used with `--\ndebug-brk`, the script will pause on the first line.\n\nIn order to debug the test apps that `self-test` will spawn, the env\nvariable `SELF_TEST_TOOL_NODE_FLAGS` could be used the same way\n`TOOL_NODE_FLAGS` is used. If you are setting the env variable\n`SELF_TEST_TOOL_NODE_FLAGS` with `TOOL_NODE_FLAGS`, consider specifying a\ncustom port, as they could collide trying to listen to the same port.\nTo set a custom port, you could set the variable in the followind manner\n`SELF_TEST_TOOL_NODE_FLAGS=\"--debug-brk=5859\"` and the debugger will\nlisten to the port 5859 and not the default 5858.\n\n\n## Development\n\nThe entry-point of the tools code is in `index.js`.\n\n### Devel vs Prod environment\n\nThe Meteor Tool code has two modes of running:\n\n- from local checkout for development\n- from a production release installed by running\n`curl -L https://install.meteor.com | sh` or a Windows installer.\n\nThere are two different `meteor` / `meteor.bat` starting scripts in development\nand production. The production one is written by the packaging code.\n\nIn addition to that, the checkout version stores its own catalog (`.meteor` dir)\nand the production version keeps it in `~/.meteor`.\n\nWhen the release is published (with `./meteor publish-release --from-checkout`),\nthe files committed into Git are copied in a compiled form into the built\npackage (Isopack). You can find the list of copied sub-trees in\n`Isopack#_writeTool`.\n\n\n### Buildmessage\n\nThroughout the code-base, there is an extensive use of `buildmessage`, which is\na custom try/catch/finally system with recovery. See\n[`/tools/utils/buildmessage.md`](utils/buildmessage.md) for more details.\n\n\n## More information\n\nFor more information about a particular part of Meteor Tool, see subdirectories'\nREADME.md files and the top-level intro comments in the bigger files.\n"
  },
  {
    "path": "tools/cli/README.md",
    "content": "# CLI\n\nFiles in this folder define the common framework for defining and parsing CLI\ncommands, options and properties such as `inApp` or `inPackage`.\n\nIt is encouraged to split out theme sharing commands into separate files.\n\nAn example of a command:\n\n```javascript\nmain.registerCommand({\n  name: 'some-command',\n  requiresRelease: false,\n  requiresApp: true,\n  // requiresPackage: true,\n  // requiresAppOrPackage: true,\n  pretty: true, // optional\n  minArgs: 1, // optional\n  maxArgs: 10, // optional\n  options: {\n    'long-option': { type: Boolean, short: 's', default: true, required: true },\n    'with-string': { type: String, short: 'w' }\n  }\n}, function (options) {\n  var {appDir, packageDir, args} = options;\n  var longOption = options['long-option'];\n  var withString = options['with-string'];\n  ...\n});\n```\n\nThis command will handle the following examples:\n\n```bash\nmeteor some-command --long-option\nmeteor some-command -s\nmeteor some-command -s --with-string \"some value\"\nmeteor some-command -s -w \"some value\"\n```\n\nNote: don't pick a short key for an option unless it is very common to use it. \nThe commands parser makes sure the same short key for an option is used\nconsistently for the same kind of option across all commands. So two commands A\nand B can share a short option \"c\" only if it stands for the same long option in\nboth cases.\n\n## Catalog refresh policy\n\nYou might notice that some commands are marked to never refresh the catalog.\nThis is useful to make the command fast, if the command doesn't involve any\nnetwork communication to the package server, it might be a good idea to forbid\nthe preemtive refresh:\n\n```javascript\nmain.registerCommand({\n  ...\n  catalogRefresh: new catalog.Refresh.Never()\n});\n```\n\n## Command return code\n\nFor some reason there are two ways to terminate the command with a non-standard\nexit code (non-zero, unix process exit code).\n\nFirst way is just the return value of the command function, which should be a\nnumber.\n\nThe second way is to throw a special kind of exception:\n\n```javascript\nmain.registerCommand({...}, function (options) {\n  throw new main.ExitWithCode(2);\n})\n```\n\nIn case of additional options check, you can throw another special exception to\nshow the help text for the command:\n\n```javascript\nmain.registerCommand({...}, function (options) {\n  if (options.bla === 'bad-value')\n    throw new main.ShowUsage;\n})\n```\n\nThere is also `main.WaitForExit` used for terminating after the subprocesses are\ndone. (XXX more info)\n\n## help.txt\n\nThe `help.txt` file contains all the information printed to the user when the\n`meteor help` command is run. It has its own syntax where every command is\nseparated by a marker `>>>` with the name of the command.\n\nCommands are parsed so the help text for an individual command could be\nseparated from the rest.\n\nSadly, these commands need to be redocumented in the docs app as well. The docs\ntext is not shared between these two places, yet.\n\n## Admin commands\n\nGiven that `self-test` is the only reliable way to test code in Meteor Tool, you\nmight need to create special \"admin\" commands. Since \"admin\" commands don't show\nup in the help text, this namespace is abused to store all sorts of one-of\ncommands to run in automated and manual tests.\n\n"
  },
  {
    "path": "tools/cli/commands-aliases.js",
    "content": "var main = require('./main.js');\nvar catalog = require('../packaging/catalog/catalog.js');\nvar Console = require('../console/console.js').Console;\n\n///////////////////////////////////////////////////////////////////////////////\n// Command reminders for those more familiar with Rails\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'server',\n  maxArgs: Infinity,\n  requiresRelease: false,\n  requiresApp: false,\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  Console.error(\"Did you mean \" + Console.command(\"'meteor run'\") + \"?\");\n  throw new main.ExitWithCode(1);\n});\n\nmain.registerCommand({\n  name: 'console',\n  maxArgs: Infinity,\n  requiresRelease: false,\n  requiresApp: false,\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  Console.error(\"Did you mean \" + Console.command(\"'meteor shell'\") + \"?\");\n  throw new main.ExitWithCode(1);\n});\n\nmain.registerCommand({\n  name: 'new',\n  maxArgs: Infinity,\n  requiresRelease: false,\n  requiresApp: false,\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  Console.error(\"Did you mean \" + Console.command(\"'meteor create'\") + \"?\");\n  throw new main.ExitWithCode(1);\n});\n\nmain.registerCommand({\n  name: 'dbconsole',\n  maxArgs: Infinity,\n  requiresRelease: false,\n  requiresApp: false,\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  Console.error(\"Did you mean \" + Console.command(\"'meteor mongo'\") + \"?\");\n  throw new main.ExitWithCode(1);\n});\n"
  },
  {
    "path": "tools/cli/commands-cordova.js",
    "content": "import _ from 'underscore';\nimport main from './main.js';\nimport { Console } from '../console/console.js';\nimport catalog from '../packaging/catalog/catalog.js';\nimport { ProjectContext, PlatformList } from '../project-context.js';\nimport buildmessage from '../utils/buildmessage.js';\nimport files from '../fs/files.js';\n\nimport * as cordova from '../cordova';\nimport { CordovaProject } from '../cordova/project.js';\n\nfunction createProjectContext(appDir) {\n  const projectContext = new ProjectContext({\n    projectDir: appDir\n  });\n  main.captureAndExit('=> Errors while initializing project:', () => {\n    // We're just reading metadata here; we don't need to resolve constraints.\n    projectContext.readProjectMetadata();\n  });\n  return projectContext;\n}\n\n// Add one or more Cordova platforms\nmain.registerCommand({\n  name: 'add-platform',\n  options: {\n    verbose: { type: Boolean, short: \"v\" }\n  },\n  minArgs: 1,\n  maxArgs: Infinity,\n  requiresApp: true,\n  catalogRefresh: new catalog.Refresh.Never(),\n  notOnWindows: false\n}, function (options) {\n  Console.setVerbose(!!options.verbose);\n\n  const projectContext = createProjectContext(options.appDir);\n\n  const platformsToAdd = options.args;\n  let installedPlatforms = projectContext.platformList.getPlatforms();\n\n  main.captureAndExit('', 'adding platforms', () => {\n    for (platform of platformsToAdd) {\n      if (_.contains(installedPlatforms, platform)) {\n        buildmessage.error(`${platform}: platform is already added`);\n      } else if (!_.contains(cordova.CORDOVA_PLATFORMS, platform)) {\n        buildmessage.error(`${platform}: no such platform`);\n      }\n    }\n\n    if (buildmessage.jobHasMessages()) {\n      return;\n    }\n\n    const cordovaProject = new CordovaProject(projectContext);\n    if (buildmessage.jobHasMessages()) return;\n\n    installedPlatforms = installedPlatforms.concat(platformsToAdd)\n    const cordovaPlatforms = cordova.filterPlatforms(installedPlatforms);\n    cordovaProject.ensurePlatformsAreSynchronized(cordovaPlatforms);\n\n    if (buildmessage.jobHasMessages()) {\n      return;\n    }\n\n    // Only write the new platform list when we have succesfully synchronized\n    projectContext.platformList.write(installedPlatforms);\n\n    for (platform of platformsToAdd) {\n      Console.info(`${platform}: added platform`);\n      if (_.contains(cordovaPlatforms, platform)) {\n        cordovaProject.checkPlatformRequirements(platform);\n      }\n    }\n  });\n});\n\n// Remove one or more Cordova platforms\nmain.registerCommand({\n  name: 'remove-platform',\n  minArgs: 1,\n  maxArgs: Infinity,\n  requiresApp: true,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  const projectContext = createProjectContext(options.appDir);\n\n  const platformsToRemove = options.args;\n  let installedPlatforms = projectContext.platformList.getPlatforms();\n\n  main.captureAndExit('', 'removing platforms', () => {\n    for (platform of platformsToRemove) {\n      // Explain why we can't remove server or browser platforms\n      if (_.contains(PlatformList.DEFAULT_PLATFORMS, platform)) {\n        buildmessage.error(`${platform}: cannot remove platform in this \\\nversion of Meteor`);\n      } else if (!_.contains(installedPlatforms, platform)) {\n        buildmessage.error(`${platform}: platform is not in this project`);\n      }\n    }\n\n    if (buildmessage.jobHasMessages()) {\n      return;\n    }\n\n    installedPlatforms = _.without(installedPlatforms, ...platformsToRemove);\n    projectContext.platformList.write(installedPlatforms);\n\n    for (platform of platformsToRemove) {\n      Console.info(`${platform}: removed platform`);\n    }\n\n    if (process.platform !== 'win32') {\n      const cordovaProject = new CordovaProject(projectContext);\n      if (buildmessage.jobHasMessages()) return;\n      const cordovaPlatforms = cordova.filterPlatforms(installedPlatforms);\n      cordovaProject.ensurePlatformsAreSynchronized(cordovaPlatforms);\n    }\n  });\n});\n\nmain.registerCommand({\n  name: 'list-platforms',\n  requiresApp: true,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  const projectContext = createProjectContext(options.appDir);\n\n  const installedPlatforms = projectContext.platformList.getPlatforms();\n\n  Console.rawInfo(installedPlatforms.join('\\n') + '\\n');\n});\n\nmain.registerCommand({\n  name: 'install-sdk',\n  options: {\n    verbose: { type: Boolean, short: \"v\" }\n  },\n  minArgs: 0,\n  maxArgs: Infinity,\n  catalogRefresh: new catalog.Refresh.Never(),\n  hidden: true,\n  notOnWindows: true\n}, function (options) {\n  Console.setVerbose(!!options.verbose);\n\n  Console.info(\"Please follow the installation instructions in the mobile guide:\");\n  Console.info(Console.url(\"http://guide.meteor.com/mobile.html#installing-prerequisites\"));\n\n  return 0;\n});\n\nmain.registerCommand({\n  name: 'configure-android',\n  options: {\n    verbose: { type: Boolean, short: \"v\" }\n  },\n  minArgs: 0,\n  maxArgs: Infinity,\n  catalogRefresh: new catalog.Refresh.Never(),\n  hidden: true,\n  notOnWindows: true\n}, function (options) {\n  Console.setVerbose(!!options.verbose);\n\n  Console.info(`You can launch the Android SDK Manager from within Android \\\nStudio.\nSee`, Console.url(\"http://developer.android.com/tools/help/sdk-manager.html\"), `\nAlternatively, you can launch it by running the 'android' command.\n(This requires that you have set ANDROID_HOME and added ANDROID_HOME/tools \\\nto your PATH.)`);\n\n  return 0;\n});\n"
  },
  {
    "path": "tools/cli/commands-packages-query.js",
    "content": "// These commands deal with aggregating local package data with the information\n// contained in the Meteor Package Server. They also deal with presenting this\n// to the user in various human or machine-readable ways.\nvar _ = require('underscore');\nvar buildmessage = require('../utils/buildmessage.js');\nvar catalog = require('../packaging/catalog/catalog.js');\nvar Console = require('../console/console.js').Console;\nvar files = require('../fs/files.js');\nvar isopackets = require('../tool-env/isopackets.js');\nvar main = require('./main.js');\nvar packageVersionParser = require('../packaging/package-version-parser.js');\nvar projectContextModule = require('../project-context.js');\nvar utils = require('../utils/utils.js');\nvar catalogUtils = require('../packaging/catalog/catalog-utils.js');\nvar compiler = require('../isobuild/compiler.js');\n\n// We want these queries to be relatively fast, so we will only refresh the\n// catalog if it is > 15 minutes old\nvar DEFAULT_MAX_AGE_MS = 15 * 60 * 1000;\n\n// Maximum number of recent versions of a package or a release that we should\n// return to the user, unless a more complete mode is requested.\nvar MAX_RECENT_VERSIONS = 5;\n\n// XXX: Remove this if/when we do a Troposphere migration to backfill release\n// version publication times.\n// Estimate the publication date for a release. Since we have failed to keep\n// track of publication times of release versions in the past, we will try to\n// guess that the release was published at the same time as the tool.\nvar getReleaseVersionPublishedOn = function (versionRecord) {\n  if (versionRecord.published) {\n    return new Date(versionRecord.published);\n  }\n  // We don't know when the release was published. Luckily, since there is no\n  // way to use the tool outside of a release, and we always change the tool\n  // between releases, it is a good bet that the release was published on the\n  // same day as the tool.\n  var toolPackage = versionRecord.tool.split('@');\n  var toolName = toolPackage[0];\n  var toolVersion = toolPackage[1];\n  var toolRecord = catalog.official.getVersion(toolName, toolVersion);\n  if (! toolRecord || ! toolRecord.published) {\n    return null;\n  }\n  return new Date(toolRecord.published);\n};\n\n// Processes information about the versions that we hid. Returns a brief\n// human-friendly string listing the reasons why some versions of the package\n// were not shown.\nvar formatHiddenVersions = function (hiddenVersions, oldestShownVersion) {\n  // An array of strings, listing the reasons why some versions were hidden.\n  var reasons = [];\n  // Use our information about hidden versions to figure what reasons we\n  // actually want to return to the user.\n  if (! oldestShownVersion) {\n    // We did not show any versions, so presumably all existing versions of\n    // this package are either unmigrated or pre-release versions.\n    if (hiddenVersions.lastUnmigrated) {\n      reasons.push(\"unmigrated\");\n    }\n    if (hiddenVersions.lastPreRelease) {\n      reasons.push(\"pre-release\");\n    }\n  } else {\n    // If the oldest version on record is older than the oldest shown\n    // version, then it was hidden due to MAX_RECENT_VERSION number. (It\n    // might also be hidden because it is a pre-release or unmigrated, but\n    // age takes priority).\n    if (packageVersionParser.lessThan(\n        hiddenVersions.oldestVersion, oldestShownVersion)) {\n      reasons.push(\"older\");\n    }\n\n    // If the latest unmigrated/pre-release version is older than the oldest\n    // version that we are showing, then we don't care about it. If it is\n    // younger, we need to tell the user.\n    //\n    // It is certainly possible that, even though a pre-release version is older\n    // than the oldest version that we are showing, but under the limit for the\n    // MAX_RECENT_VERSIONS. So, in that case, we are eliding that version\n    // because it is a pre-release, not because of age. It is still,\n    // technically, an 'older' version though, and that explanation is more\n    // intuitive.\n    if (hiddenVersions.lastPreRelease &&\n        packageVersionParser.lessThan(\n          oldestShownVersion, hiddenVersions.lastPreRelease)) {\n      reasons.push(\"pre-release\");\n    }\n    if (hiddenVersions.lastUnmigrated &&\n        packageVersionParser.lessThan(\n          oldestShownVersion, hiddenVersions.lastUnmigrated)) {\n      reasons.push(\"unmigrated\");\n    }\n  }\n\n  // Now, we will aggregate the reasons into a human-readable string.\n  if (reasons.length === 1) {\n    return reasons[0];\n  } else if (reasons.length === 2) {\n    // There is no oxford comma if only listing two objects\n    return reasons[0] + \" and \" + reasons[1];\n  } else if (reasons.length > 2)  {\n    return reasons.slice(0, -1).join(\", \") + \", and \" + _.last(reasons);\n  } else {\n    // Did we not figure out anything to write? Did something else go wrong?\n    // This should never happen, but if it does, recover by omitting\n    // information.\n    return \"Some\";\n  }\n};\n\n// Converts an object to an EJSON string with the right spacing.\nvar formatEJSON = function (data) {\n  var EJSON = isopackets.load('ejson').ejson.EJSON;\n  return EJSON.stringify(data, { indent: true }) + \"\\n\";\n};\n\n// Takes in a string and pads it with whitespace to the length of the longest\n// possible date string.\nvar padLongformDate = function (dateStr) {\n  var numSpaces = utils.maxDateLength - dateStr.length;\n  return dateStr + Array(numSpaces + 1).join(' ');\n};\n\n// In order to get access to local package data, we need to create a local\n// package catalog. The best way to do that is to create a temporary\n// ProjectContext and let it handle catalog initialization. When we do, we need\n// to make sure that it is aware of all the local packages that we might care\n// about.\n//\n// This function returns such a ProjectContext, and takes in the following\n// options:\n//  - appDir: If we are running in the context of an app, this will contain the\n//    root of the app. We want to make sure to grab the data from the app's\n//    local packages.\n//  - packageDir: If we are running in a package directory, this will contain\n//    the source root of that package. If we are running from inside a package,\n//    we want that package to show up in our results.\nvar getTempContext = function (options) {\n  var projectContext;\n  // If we are running in an app, we will use it to create a\n  // (mostly immutable) projectContext.\n  if (options.appDir) {\n    projectContext = new projectContextModule.ProjectContext({\n      projectDir: options.appDir\n    });\n  } else {\n    // We're not in an app, so we will create a temporary app and use it to load\n    // the local catalog. If a local packageDir exists, include it manually.\n    var currentPackageDir = options.packageDir ? [options.packageDir] : [];\n    var tempProjectDir = files.mkdtemp('meteor-show');\n    projectContext = new projectContextModule.ProjectContext({\n      projectDir: tempProjectDir,\n      explicitlyAddedLocalPackageDirs: currentPackageDir\n    });\n  }\n\n  // It is possible that we can't process package.js files in our local packages\n  // and have to exit early. This is unfortunate, but we can't search local\n  // packages if we can't read them. If this turns out to be a frequent problem,\n  // we can give a warning, instead of failing in the future. For now, we want\n  // to err on the side of consistency.\n  main.captureAndExit(\"=> Errors while reading local packages:\", function () {\n    projectContext.initializeCatalog();\n  });\n  return projectContext;\n};\n\n// Print an error message if the user asks about an unknown item.\nvar itemNotFound = function (item) {\n  Console.error(item + \": not found\");\n  catalogUtils.explainIfRefreshFailed();\n  return 1;\n};\n\n// This is a base class for storing package fields that require some processing\n// to store and display correctly.\n//\n// Do NOT initialize this class by itself -- use one of the classes that\n// inherits from it.\nvar BasePkgDatum = function () {\n  var self = this;\n  self.data = null;\n};\n_.extend(BasePkgDatum.prototype, {\n  // Throws if data has not been initialized.\n  _checkInitialized: function () {\n    var self = this;\n    if (self.data === null) {\n      throw new Error(\"do not use the BasePkgDatum class by itself\");\n    }\n  },\n  // Returns true if this class does not contain any exports.\n  isEmpty : function () {\n    var self = this;\n    self._checkInitialized();\n    return _.isEmpty(self.data);\n  },\n  // Get exports as a raw object.\n  getObject : function () {\n    var self = this;\n    self._checkInitialized();\n    return self.data;\n  },\n  getConsoleStr : function () {\n    var self = this;\n    self._checkInitialized();\n    return \"\";\n  }\n});\n\n// This class stores exports from a given package.\n//\n// Stores exports for a given package and returns them to the caller in a given\n// format. Takes in the raw exports from the package.\nvar PkgExports = function (pkgExports) {\n var self = this;\n // Process and save the export data.\n self.data = _.map(pkgExports, function (exp) {\n    var arches = exp.architectures;\n    // Replace 'os' (what we store) with 'server' (what you would put in a\n    // package.js file). That's more user friendly, and avoids confusing this\n    // with different OS arches used in binary packages.\n    if ( _.indexOf(arches, \"os\") !== -1) {\n      arches = _.without(arches, \"os\");\n      arches.push(\"server\");\n    }\n    // Sort architectures alphabetically.\n    arches.sort();\n    return { name: exp.name, architectures: arches };\n  });\n  // Sort exports alphabetically by name.\n  self.data =  _.sortBy(self.data, \"name\");\n};\n// Extend BasePkgDatum.\nPkgExports.prototype = new BasePkgDatum();\n\n_.extend(PkgExports.prototype, {\n  // Convert package exports into a pretty, Console non-wrappable string. If an\n  // export is only declared for certain architectures, mentions those\n  // architectures in a user-friendly format.\n  getConsoleStr: function () {\n    var self = this;\n    var strExports = _.map(self.data, function (exp) {\n      // If this export is valid for all architectures, don't specify\n      // architectures here.\n      if (exp.architectures.length === compiler.ALL_ARCHES.length) {\n        return exp.name;\n      }\n\n      // Don't split descriptions of individual pkgExports between lines.\n      return Console.noWrap(\n        exp.name + \" (\" + exp.architectures.join(\", \") + \")\");\n    });\n    return strExports.join(\", \");\n  }\n});\n\n// This class stores implies from a given package.\n//\n// Stores implies for a given package and returns them to the caller in a given\n// format. Takes in the dependencies from the package.\nvar PkgImplies = function (pkgDeps) {\n  var self = this;\n  self.data = [];\n  // Go through all the package dependencies. If a dependency has any implied\n  // references, add it to the list.\n  _.each(pkgDeps, function (ref, name) {\n    var architectures = [];\n    // We want to select the references that are implied (instead of just used)\n    // and save their architectures. Also, we want to replace 'os' with\n    // 'server', as with exports.\n    _.each(ref.references, function (r) {\n      if (! r.implied) {\n        return;\n      }\n      var archName = (r.arch === \"os\") ? \"server\" : r.arch;\n      architectures.push(archName);\n    });\n    // Sort architecures alphabetically.\n    architectures.sort();\n    if (! _.isEmpty(architectures)) {\n      self.data.push({ name: name, architectures: architectures });\n    }\n  });\n  // Sort by name.\n  self.data =  _.sortBy(self.data, \"name\");\n};\n\n// Extend BasePkgDatum.\nPkgImplies.prototype = new BasePkgDatum();\n\n_.extend(PkgImplies.prototype, {\n  // Convert package exports into a pretty, Console non-wrappable string. If an\n  // export is only declared for certain architectures, mentions those\n  // architectures in a user-friendly format.\n  getConsoleStr: function () {\n    var self = this;\n    var strImplies = _.map(self.data, function (ref) {\n      // If an imply is valid for all architectures, don't specify it here.\n      if (ref[\"architectures\"].length === compiler.ALL_ARCHES.length) {\n        return ref.name;\n      }\n\n      // Don't split descriptions of individual implies between lines.\n      return Console.noWrap(\n        ref.name + \" (\" + ref.architectures.join(\", \") + \")\");\n    });\n    return strImplies.join(\", \");\n  }\n});\n\n// This class stores dependencies from a given package.\n//\n// Stores dependencies for a given package and returns them to the caller in a given\n// format. Takes in the raw dependencies from the package record.\nvar PkgDependencies = function (pkgDeps) {\n  var self = this;\n  self.data = _.map(\n    // The dependency on 'meteor' was almost certainly added automatically, by\n    // Isobuild. Returning this to the user will only cause confusion.\n    _.omit(pkgDeps, \"meteor\"),\n    function (dep, depName) {\n      // We will only consider this a weak dependency if all of its references\n      // are marked as weak.\n      var weak = _.every(dep.references, function (ref) {\n        return !! ref.weak;\n      });\n      return {\n        name: depName,\n        constraint: dep.constraint,\n        weak: weak\n      };\n  });\n  // Sort by name.\n  self.data =  _.sortBy(self.data, \"name\");\n};\n\n// Extend BasePkgDatum.\nPkgDependencies.prototype = new BasePkgDatum();\n\n_.extend(PkgDependencies.prototype, {\n  // Convert package exports into a pretty, Console non-wrappable string. If an\n  // export is only declared for certain architectures, mentions those\n  // architectures in a user-friendly format.\n  getConsoleStr: function () {\n    var self = this;\n    var strDeps = _.map(self.data, function (dep) {\n      var depString = dep.name;\n      if (dep.constraint && dep.constraint !== null) {\n        depString += \"@\" + dep.constraint;\n      }\n      if (dep.weak) {\n        depString += \" (weak dependency)\";\n      }\n      return Console.noWrap(depString);\n    });\n    return strDeps.join(\"\\n\");\n  }\n});\n\n\n// The two classes below collect and print relevant information about Meteor\n// packages and Meteor releases, respectively. Specifically, they query the\n// official catalog and, if applicable, relevant local sources. They also handle\n// the details of printing their data to the screen.\n//\n// A query class has:\n//  - data: an object representing the data it has collected in response to the\n//  - query.\n//  - a print method, that take options as an argument and prints the results to\n//    the terminal.\n\n\n// This class deals with information related to packages. To deal with local\n// packages, it has to interact with the projectContext.\n//\n// The constructor takes in the following options:\n//   - metaRecord: (mandatory) the meta-record for this package from the Packages\n//     collection.\n//   - projectContext: (mandatory) a projectContext that we can use to look up\n//     information on local packages.\n//   - version: query for a specific version of this package.\n//   - showArchitecturesOS: collect and process data on OS\n//     architectures that are available for different versions of this package.\n//   - showHiddenVersions: return information about all the versions of the\n//     package, including pre-releases and unmigrated versions.\n//   - showDependencies: return information about\n//     versions' dependencies.\nvar PackageQuery = function (options) {\n  var self = this;\n\n  // This is the record in the packages collection. It contains things like\n  // maintainers, and the package homepage.\n  self.metaRecord = options.metaRecord;\n  self.name = options.metaRecord.name;\n\n  // This argument is required -- we use it to look up data. If it has not been\n  // passed in, fail early.\n  if (! options.projectContext) {\n    throw Error(\"Missing required argument: projectContext\");\n  }\n  self.projectContext = options.projectContext;\n  self.localCatalog = options.projectContext.localCatalog;\n\n  // Processing per-version availability architectures & dependencies is\n  // expensive, so we don't do it unless we are asked to.\n  self.showArchitecturesOS = options.showArchitecturesOS;\n  self.showDependencies = options.showDependencies;\n\n  // We don't want to show pre-releases and un-migrated versions to the user\n  // unless they explicitly ask us about it.\n  self.showHiddenVersions = options.showHiddenVersions;\n\n  // Collect the data for this package, including looking up any specific\n  // package version that we care about.\n  if (options.version) {\n    var versionRecord = self._getVersionRecord(options.version);\n    if (! versionRecord) {\n      self.data = null;\n      return;\n    }\n    self.data =  versionRecord.local ?\n      self._getLocalVersion(versionRecord) :\n      self._getOfficialVersion(versionRecord);\n  } else {\n    self.data = self._collectPackageData();\n  }\n};\n\n_.extend(PackageQuery.prototype, {\n  // Find and return a version record for a given version. Mark the version\n  // record as local, if it is a local version of the package.\n  _getVersionRecord: function (version) {\n    var self = this;\n\n    // We allow local version to override remote versions in meteor show, so we\n    // should start by checking if this is a local version first.\n    var versionRecord = self.localCatalog.getLatestVersion(self.name);\n\n    // If we asked for \"local\" as the version number, and found any local version\n    // at all, we are done.\n    if (version === \"local\") {\n      return versionRecord && _.extend(versionRecord, { local: true });\n    }\n\n    // We have a local record, and its version matches the version that we asked\n    // for, so we are done.\n    if (versionRecord && (versionRecord.version === version)) {\n      return _.extend(versionRecord, { local: true });\n    }\n\n    // If we haven't found a local record, or if the local record that we found\n    // doesn't match the version that we asked for, then we have to go look in\n    // the server catalog.\n    versionRecord = catalog.official.getVersion(self.name, version);\n    return versionRecord;\n  },\n  // Print the query information to screen.\n  //\n  // options:\n  //   - ejson: Don't pretty-print the data. Print a machine-readable ejson\n  //     object.\n  print: function (options) {\n    var self = this;\n\n    // If we are asking for an EJSON-style output, we will only print out the\n    // relevant fields.\n    if (options.ejson) {\n      Console.rawInfo(formatEJSON(\n        self.data.version ?\n          self._generateVersionObject(self.data) :\n          self._generatePackageObject(self.data)));\n      return;\n    }\n\n    // Otherwise, display the information that we have. If we were asking about\n    // a specific version, display that. Otherwise, display package metadata in\n    // general.\n    if (self.data.version) {\n      self._displayVersion(self.data);\n      return;\n    }\n    self._displayPackage(self.data);\n  },\n  // Aggregates data about the package as a whole. Returns an object with the\n  // following keys:\n  //\n  // - name: package name\n  // - maintainers: an array of usernames of maintainers\n  // - homepage: string homepage\n  // - totalVersions: total number of versions that this package has, including\n  //   local and hidden versions.\n  // - defaultVersion: a default version: use this version to look up\n  //   per-version information that is relevant to the package as a whole, such\n  //   as git, description,etc.\n  // - versions: an array of objects representing versions of this package.\n  _collectPackageData: function () {\n    var self = this;\n    var data = {\n      name: self.metaRecord.name,\n      maintainers: _.pluck(self.metaRecord.maintainers, \"username\"),\n      homepage: self.metaRecord.homepage\n    };\n\n    // Collect surface information about available versions, starting with the\n    // versions available on the server.\n    var serverVersionRecords =\n          catalog.official.getSortedVersionRecords(self.name);\n    var totalVersions = serverVersionRecords.length;\n\n    // If we are not going to show hidden versions, then we shouldn't waste time\n    // on them. Trim the serverVersionRecords array to only have the top\n    // MAX_RECENT_VERSIONS migrated, official versions.\n    if (! self.showHiddenVersions) {\n      // We might have to hide some versions from the user. We want to explain\n      // why we hid them. Here is how we are going to explain things -- any\n      // versions older than the oldest version that we show, are hidden because\n      // of age. If, in the covered time period, there are\n      // unmigrated/pre-release versions, then we will mention those  as well.\n      //\n      // Specifically, while we filter versions, we are going to memorize the\n      // most recent version hidden for a specific reason.\n      var lastUnmigrated = \"\";\n      var lastPreRelease = \"\";\n      var oldestVersion =\n        serverVersionRecords[0] && serverVersionRecords[0].version;\n      var filteredVersionRecords =\n        _.filter(serverVersionRecords, function (vr) {\n          if (vr.unmigrated) {\n            lastUnmigrated = vr.version;\n            return false;\n          }\n\n          if (vr.version.indexOf(\"-\") !== -1) {\n            lastPreRelease = vr.version;\n            return false;\n          }\n          return true;\n        });\n     serverVersionRecords = _.last(filteredVersionRecords, MAX_RECENT_VERSIONS);\n     data[\"hiddenVersions\"] = {\n       oldestVersion: oldestVersion,\n       lastUnmigrated: lastUnmigrated,\n       lastPreRelease: lastPreRelease\n     };\n    };\n\n    // Process the catalog records into our preferred format, and look up any\n    // other per-version information that we might need.\n    data[\"versions\"] = _.map(serverVersionRecords, function (versionRecord) {\n      return self._getOfficialVersion(versionRecord);\n    });\n\n    // The local version doesn't count against the version limit. Look up relevant\n    // information about the local version.\n    var localVersion = self.localCatalog.getLatestVersion(self.name);\n    var local;\n    if (localVersion) {\n      local = self._getLocalVersion(localVersion);\n      data[\"versions\"].push(local);\n      totalVersions++;\n    }\n\n    // Record the total number of versions, including the ones we hid from the\n    // user.\n    data[\"totalVersions\"] = totalVersions;\n\n    // Some per-version information gets displayed with the rest of the package\n    // information.  We want to use the right version for that. (We don't want\n    // to display data from unofficial or un-migrated versions just because they\n    // are recent.)\n    if (local) {\n      data[\"defaultVersion\"] = {\n        version: \"local\",\n        summary: local.summary,\n        description: local.description,\n        git: local.git,\n        implies: local.implies,\n        exports: local.exports\n      };\n    } else {\n      var mainlineRecord = catalog.official.getLatestMainlineVersion(self.name);\n      if (mainlineRecord) {\n        var pkgExports = new PkgExports(mainlineRecord.exports);\n        var implies = new PkgImplies(mainlineRecord.dependencies);\n        data[\"defaultVersion\"] = {\n          version: mainlineRecord.version,\n          summary: mainlineRecord.description,\n          description: mainlineRecord.longDescription,\n          git: mainlineRecord.git,\n          exports: pkgExports,\n          implies: implies\n        };\n      } else {\n        data[\"defaultVersion\"] = _.last(data.versions);\n      }\n    }\n    return data;\n  },\n  // Takes in a version record from the official catalog and looks up extra\n  // information that's relevant to this PackageQuery.\n  //\n  // - name: package Name\n  // - version: package version\n  // - summary: version summary/short description (from Package.describe)\n  // - description: long-form description (from the README.md)\n  // - publishedBy: username of the publisher\n  // - publishedOn: date of publication\n  // - git: git URL for this version\n  // - installed: true if the package exists in warehouse, and is therefore\n  //   available for use offline.\n  // - architectures: (optional) if self.showArchitecturesOS is true, returns an\n  //   array of system architectures for which that package is available.\n  // - dependencies: (optional) if self.showDependencies is true, return an\n  //   array of objects denoting that package's dependencies. The objects have\n  //   the following keys:\n  //     - packageName: name of the dependency\n  //     - constraint: constraint for that dependency\n  //     - weak: true if this is a weak dependency.\n  _getOfficialVersion: function (versionRecord) {\n    var self = this;\n    var version = versionRecord.version;\n    var name = self.name;\n    var data = {\n      name: name,\n      version: version,\n      summary: versionRecord.description,\n      description: versionRecord.longDescription,\n      publishedBy:\n      versionRecord.publishedBy && versionRecord.publishedBy.username,\n      publishedOn: new Date(versionRecord.published),\n      git: versionRecord.git,\n      exports: versionRecord.exports\n    };\n\n    // Get the export and imply data, if the record has any.\n    data[\"exports\"] = new PkgExports(versionRecord.exports);\n    data[\"implies\"] = new PkgImplies(versionRecord.dependencies);\n\n    // Processing and formatting architectures takes time, so we don't want to\n    // do this if we don't have to.\n    if (self.showArchitecturesOS) {\n      var allBuilds = catalog.official.getAllBuilds(self.name, version);\n      var architectures = _.map(allBuilds, function (build) {\n        if (! build['buildArchitectures']) {\n          return \"unknown\";\n        }\n        var archOS =\n          _.filter(build.buildArchitectures.split('+'), function (arch) {\n             return ( arch !== \"web.browser\" ) && ( arch !== \"web.cordova\" );\n        });\n        // At this point, you can only have OS arch at a time per-build.\n        return archOS[0];\n      });\n      data[\"architecturesOS\"] = architectures;\n    }\n\n    // Processing and formatting dependencies also takes time, so we would\n    // rather not do it if we don't have to.\n    if (self.showDependencies) {\n      data[\"dependencies\"] = new PkgDependencies(versionRecord.dependencies);\n    }\n\n    // We want to figure out if we have already downloaded this package, and,\n    // therefore, can use it offline.\n    var tropohouse = self.projectContext.tropohouse;\n    try {\n      data[\"installed\"] = tropohouse.installed({\n        packageName: name,\n        version: version\n      });\n    } catch (e) {\n      // Sometimes, we might be unable to determine if the package is installed\n      // -- maybe we don't have access to the directory, or there is some sort\n      // of disk corruption. This might only extend to one version, so it would\n      // be awkward to fail 'meteor show' altogether. Print an error message (if\n      // it is a permissions error, for example, that's something the user might\n      // want to know), but don't throw.\n      Console.printError(e);\n      data[\"installed\"] = false;\n    }\n    return data;\n  },\n\n  // Takes in a version record from the local catalog and looks up extra\n  // information that's relevant to this PackageQuery. Returns an object with\n  // the following keys.\n  //\n  // - name: package Name\n  // - version: package version\n  // - summary: version summary/short description (from Package.describe)\n  // - description: long-form description (from the README.md)\n  // - git: git URL for this version\n  // - local: always true (denotes that this is a local package).\n  // - directory: source directory of this package.\n  // - dependencies: (optional) if self.showDependencies is true, return an\n  //   array of objects denoting that package's dependencies. The objects have\n  //   the following keys:\n  //     - packageName: name of the dependency\n  //     - constraint: constraint for that dependency\n  //     - weak: true if this is a weak dependency.\n  _getLocalVersion: function (localRecord) {\n    var self = this;\n    var data =  {\n      name: self.name,\n      summary: localRecord.description,\n      git: localRecord.git,\n      local: true\n    };\n\n    // Get the source directory.\n    var packageSource = self.localCatalog.getPackageSource(self.name);\n    data[\"directory\"] = packageSource.sourceRoot;\n\n    // Get the exports.\n    data[\"exports\"] = new PkgExports(packageSource.getExports());\n    data[\"implies\"] = new PkgImplies(localRecord.dependencies);\n\n    // If the version was not explicitly set by the user, the catalog backfills\n    // a placeholder version for the constraint solver. We don't want to show\n    // that version to the user.\n    data[\"version\"] = packageSource.versionExplicitlyProvided ?\n      localRecord.version : \"local\";\n\n    // Processing dependencies takes time, and we don't want to do it if we\n    // don't have to.\n    if (self.showDependencies) {\n      data[\"dependencies\"] = new PkgDependencies(localRecord.dependencies);\n    }\n\n    var readmeInfo;\n    main.captureAndExit(\n      \"=> Errors while reading local packages:\",\n      \"reading \" + data[\"directory\"],\n       function () {\n        readmeInfo = packageSource.processReadme();\n    });\n    if (readmeInfo) {\n      data[\"description\"] = readmeInfo.excerpt;\n    }\n    return data;\n  },\n  // Displays version information from this PackageQuery to the terminal in a\n  // human-friendly format. Takes in an object that contains some, but not all,\n  // of the following keys:\n  //\n  // - name: (mandatory) package Name\n  // - version: (mandatory) package version\n  // - summary: version summary/short description (from Package.describe)\n  // - publishedBy: username of the publisher\n  // - publishedOn: date of publication\n  // - description: long-form description (from the README.md)\n  // - git: git URL for this version.\n  // - local: true for a local version of a package.\n  // - directory: source directory of this package.\n  // - installed: true if the package exists in warehouse, and is therefore\n  //   available for use offline.\n  // - architectures: if self.showArchitecturesOS is true, returns an\n  //   array of system architectures for which that package is available.\n  // - exports: a PkgExports object, representing package exports.\n  // - exports: a PkgImplies object, representing package implies.\n  // - dependencies: a PkgDependencies object, representing dependencies.\n  _displayVersion: function (data) {\n    var self = this;\n    Console.info(\n        data.name + \"@\" + data.version,\n        Console.options({ bulletPoint: \"Package: \" }));\n    if (data.directory) {\n      Console.info(\"Directory: \" + Console.path(data.directory));\n    }\n    if (data.exports && ! data.exports.isEmpty()) {\n      Console.info(\n        data[\"exports\"].getConsoleStr(),\n        Console.options({ bulletPoint: \"Exports: \" }));\n    }\n    if (data.implies && ! data.implies.isEmpty()) {\n      Console.info(\n        data[\"implies\"].getConsoleStr(),\n        Console.options({ bulletPoint: \"Implies: \" }));\n    }\n    if (data.git) {\n      Console.info(\n        Console.url(data.git),\n        Console.options({ bulletPoint: \"Git: \" }));\n    }\n\n    // If we don't have a long-form description, print the summary. (If we don't\n    // have a summary, print nothing).\n    if (data.description || data.summary) {\n      Console.info();\n      Console.info(data.description || data.summary);\n    }\n\n    // Print dependency information, if the package has any dependencies.\n    if (data.dependencies && ! data.dependencies.isEmpty()) {\n      Console.info();\n      Console.info(\"Depends on:\");\n      Console.info(\n          data.dependencies.getConsoleStr(),\n          Console.options({ indent: 2 }));\n    }\n\n    // Print the 'published by' line at the very bottom.\n    if (data.publishedBy) {\n      var publisher = data.publishedBy;\n      var pubDate = utils.longformDate(data.publishedOn);\n      Console.info();\n      Console.info(\"Published by\", publisher, \"on\", pubDate + \".\");\n    }\n\n    // Sometimes, there is a server package and a local package with the same\n    // version. In this case, we prefer the local package. Explain our choice to\n    // the user.\n    if (data.local &&\n        catalog.official.getVersion(data.name, data.version)) {\n      Console.info();\n      Console.info(\n        \"This package version is built locally from source.\",\n        \"The same version of this package also exists on the package server.\",\n        \"To view its metadata, run\",\n        Console.command(\"'meteor show \" + data.name + \"@\" + data.version + \"'\"),\n        \"from outside the project.\");\n    }\n  },\n  // Returns a user-friendly object from this PackageQuery to the caller.  Takes\n  // in a data object with the same keys as _displayVersion.\n  //\n  // Returns an object with some of the following keys:\n  // - name: String. Name of the package.\n  // - version: String. Meteor version number.\n  // - description: String. Longform description.\n  // - summary: String. Short summary.\n  // - git: String. Git URL.\n  // - publishedBy: String. Username of the publisher.\n  // - publishedOn: Date. Time of publication.\n  // - local: Boolean. True if this is a local package.\n  // - directory: source directory of this package.\n  // - installed: Boolean. True if the isopack for this package has been\n  //   downloaded, or if the package is local.\n  // - dependencies: Array of objects representing package dependencies, sorted\n  //   alphabetically by package name.\n  // - OSarchitectures: Array of OS architectures on for which an isopack of\n  //   this package exists (server packages only).\n  // - exports: Array of objects representing the package exports, sorted by\n  //   name of export.\n  _generateVersionObject: function (data) {\n    var versionFields = [\n      \"name\", \"version\", \"description\", \"summary\", \"git\", \"directory\",\n      \"publishedBy\", \"publishedOn\", \"installed\", \"local\", \"architecturesOS\",\n    ];\n    var processedData = {};\n    _.each([\"exports\", \"implies\", \"dependencies\"], function (key) {\n      processedData[key] = data[key] ? data[key].getObject() : [];\n    });\n    return _.extend(processedData, _.pick(data, versionFields));\n  },\n\n  // Displays general package data from this PackageQuery to the terminal in a\n  // human-friendly format. Takes in an object that contains some, but not\n  // always all, of the following keys:\n  //\n  // - name: (mandatory) package name\n  // - maintainers: array of usernames of maintainers\n  // - homepage: string of the package homepage\n  // - defaultVersion: the default version of this package to use for looking up\n  //   per-version information that's relevant to the package in general (ex:\n  //   git).\n  // - totalVersions: the total number of versions that this package has,\n  //   including hidden versions.\n  // - versions: an ordered array of objects, representing the versions of this\n  //   package that we should return to the user. Each version should contain\n  //   some of the following keys:\n  //     - version: (mandatory) version number, or \"local\" for a version-less\n  //       local package.\n  //     - publishedOn: the date that the package was published.\n  //     - installed: true if this is a server package that has already been\n  //       downloaded to the warehouse.\n  //     - local: true for a local package.\n  //     - directory: source root directory of a local package.\n  // - hiddenVersions: an object containing some information about versions that\n  //   have been hidden from the user. Has keys:\n  //     - oldestVersion: the version of this package with the smallest Meteor\n  //       semver number that exists in our records.\n  //     - lastUnmigrated: the most recent (largest Meteor semver) version that\n  //       is marked 'unmigrated'.\n  //     - lastPreRelease: the most recent pre-release version.\n  _displayPackage: function (data) {\n    var self = this;\n    var defaultVersion = data.defaultVersion;\n\n    // Every package has a name. Some packages have a homepage.\n    var displayName = data.defaultVersion ?\n      data.name + \"@\" + data.defaultVersion.version : data.name;\n    Console.info(displayName, Console.options({ bulletPoint: \"Package: \" }));\n    if (data.homepage) {\n      Console.info(Console.url(data.homepage),\n        Console.options({ bulletPoint: \"Homepage: \" }));\n    }\n    // Local packages might not have any maintainers.\n    if (! _.isEmpty(data.maintainers)) {\n      Console.info(data.maintainers.join(\", \"),\n        Console.options({ bulletPoint: \"Maintainers: \" }));\n    }\n    // Git is per-version, so we will print the latest one, if one exists.\n    if (defaultVersion && defaultVersion.git) {\n      Console.info(Console.url(defaultVersion.git),\n        Console.options({ bulletPoint: \"Git: \" }));\n    }\n    // Print the exports.\n    if (defaultVersion && defaultVersion.exports &&\n       ! defaultVersion.exports.isEmpty()) {\n      Console.info(\n        defaultVersion[\"exports\"].getConsoleStr(),\n        Console.options({ bulletPoint: \"Exports: \" }));\n    }\n    if (defaultVersion && defaultVersion.implies &&\n        ! defaultVersion.implies.isEmpty()) {\n      Console.info(\n        defaultVersion[\"implies\"].getConsoleStr(),\n        Console.options({ bulletPoint: \"Implies: \" }));\n    }\n    Console.info();\n\n    // If we don't have a long-form description, we will use the summary. For a\n    // local package, we might not have a summary, in which case we should be\n    // careful not to print extra lines.\n    var printDescription = defaultVersion &&\n      (defaultVersion.description || defaultVersion.summary);\n    if (printDescription) {\n      Console.info(printDescription );\n      Console.info();\n    }\n\n    // If we have any versions to show, print them out now.\n    var versionRows = [];\n    if (data.versions && ! _.isEmpty(data.versions)) {\n      var versionsHeader =\n            self.showHiddenVersions ? \"Versions:\" : \"Recent versions:\";\n      Console.info(versionsHeader);\n      _.each(data.versions, function (v) {\n\n        // For a local package, we don't have a published date, and we don't\n        // need to show if it has already been downloaded (it is local, we don't\n        // need to download it). Instead of showing both of these values, let's\n        // show the directory.\n        if (v.local) {\n          versionRows.push([v.version, v.directory]);\n          return;\n        }\n\n        // Convert the date into a display-friendly format, or print nothing for\n        // a local package.\n        var publishDate = utils.longformDate(v.publishedOn);\n\n        // If there is a status that we would like to report for this package,\n        // figure it out now.\n        if (v.installed) {\n          var paddedDate = padLongformDate(publishDate);\n          versionRows.push([v.version, paddedDate + \"  \" + \"installed\"]);\n        } else {\n          versionRows.push([v.version, publishDate]);\n        }\n      });\n      // The only time that we are going to go over a reasonable character limit\n      // is with a directory for the local package. We would much rather display\n      // the full directory than trail it off.\n      Console.printTwoColumns(versionRows, { indent: 2, ignoreWidth: true });\n    }\n\n    // If we have not shown all the available versions, let the user know.\n    if (data.totalVersions > versionRows.length) {\n      var oldestShownVersion =\n        (data[\"versions\"][0] && data[\"versions\"][0].version) || \"\";\n      // A string explaining why those versions have been hidden.\n      var hiddenVersions =\n         formatHiddenVersions(data[\"hiddenVersions\"], oldestShownVersion);\n\n      // We will word things in the message in different ways, based on whether\n      // multiple versions exist/have been hidden.\n      var hiddenVersionsPluralizer =\n         (data.totalVersions - data.versions.length == 1) ?\n         \"One \" + hiddenVersions + \" version of \" + self.name + \" has\" :\n         hiddenVersions[0].toUpperCase() + hiddenVersions.slice(1) +\n         \" versions of \" + self.name + \" have\";\n      var allVersionsPluralizer =\n         (data.totalVersions === 1) ?\n         \"the hidden version\" :\n         \"all \" + data.totalVersions + \" versions\";\n\n      // Display the final message.\n      Console.info(\n        hiddenVersionsPluralizer, \"been hidden.\",\n        \"To see \" + allVersionsPluralizer + \", run\",\n        Console.command(\"'meteor show --show-all \" + self.name + \"'\") + \".\");\n    }\n  },\n  // Returns a user-friendly object from this PackageQuery to the caller.  Takes\n  // in a data object with the same keys as _displayPackage.\n  //\n  // Returns an object with some of the following keys:\n  // - name: String. Name of the package.\n  // - homepage: String. URL of the package homepage.\n  // - maintainers: Array of strings. Usernames of package maintainers.\n  // - totalVersions: Number. Total number of versions that exist for this\n  //   package.\n  // - versions: Array of objects, representing versions of this\n  //   package. Objects have the following keys:\n  //   - name: String. Name of the package.\n  //   - version: String. Meteor version number.\n  //   - description: String. Longform description.\n  //   - summary: String. Short summary.\n  //   - git: String. Git URL.\n  //   - publishedBy: String. Username of the publisher.\n  //   - publishedOn: Date. Time of publication.\n  //   - local: Boolean. True if this is a local package.\n  //   - directory: source directory of this package.\n  //   - installed: Boolean. True if the isopack for this package has been\n  //     downloaded, or if the package is local.\n  //   - exports: Array of objects representing the package exports, sorted by\n  //     name of export.\n  _generatePackageObject: function (data) {\n    var packageFields =\n          [ \"name\", \"homepage\", \"maintainers\", \"totalVersions\" ];\n    // Process the versions array. We only want some of the keys, and we want to\n    // make sure to get the right exports object.\n    var versions = _.map(data[\"versions\"], function (version) {\n      var versionFields = [\n        \"name\", \"version\", \"description\", \"summary\", \"git\", \"publishedBy\",\n        \"publishedOn\", \"installed\", \"local\", \"directory\", \"architecturesOS\"\n      ];\n      var processedData = {};\n      _.each([\"exports\", \"implies\"], function (key) {\n        processedData[key] = version[key] ? version[key].getObject() : [];\n      });\n      return _.extend(processedData, _.pick(version, versionFields));\n    });\n    return _.extend({ versions: versions }, _.pick(data, packageFields));\n  },\n\n});\n\n// This class looks up release-related information in the official catalog.\n//\n// The constructor takes in an object with the following keys:\n//   - metaRecord: (mandatory) the meta-record for this release from the\n//     Releases collection.\n//   - version: specific version of a release that we want to query.\n//   - showHiddenVersions: show experimental, pre-release & otherwise\n//     non-recommended versions of this release.\nvar ReleaseQuery = function (options) {\n  var self = this;\n\n  // This is the record in the Releases collection. Contains metadata, such as\n  // maintainers.\n  self.metaRecord = options.metaRecord;\n  self.name = options.metaRecord.name;\n\n  // We don't always want to show non-recommended release versions.\n  self.showHiddenVersions = options.showHiddenVersions;\n\n  // Aggregate the query data. If we are asking for a specific version, get data\n  // for a specific version, otherwise aggregate the data about this release\n  // track in general.\n  self.data = options.version ?\n    self._getVersionDetails(options.version) :\n    self._getReleaseData();\n};\n\n_.extend(ReleaseQuery.prototype, {\n  // Prints the data from this ReleaseQuery to the terminal. Takes the following\n  // options:\n  //   - ejson: Don't pretty-print the data. Return a machine-readable ejson\n  //     object.\n  print: function (options) {\n    var self = this;\n\n    // If we are asking for an EJSON-style output, print out the relevant fields.\n    if (options.ejson) {\n      var versionFields = [\n        \"track\", \"version\", \"description\", \"publishedBy\", \"publishedOn\",\n        \"tool\", \"packages\", \"recommended\"\n      ];\n      var packageFields = [ \"name\", \"maintainers\", \"versions\" ];\n      var fields = self.data.version ? versionFields : packageFields;\n      Console.rawInfo(formatEJSON(_.pick(self.data, fields)));\n      return;\n    }\n\n    // If we are asking for a specific version, display the information about\n    // that version.\n    if (self.data.version) {\n      self._displayVersion(self.data);\n      return;\n    }\n    // Otherwise, print the data about this release track in general.\n    self._displayRelease(self.data);\n  },\n\n  // Gets detailed data about a specific version of this release. Returns an\n  // object with the following keys:\n  //  - track: name of the release track\n  //  - version: release version\n  //  - description: description of the release version\n  //  - recommended: if this is a recommended version.\n  //  - orderKey: the orderKey of this version\n  //  - publishedBy: username of the publisher\n  //  - publishedOn: date this version was published\n  //  - packages: map of packages that go into this version\n  //  - tool: the tool package@version for this release version\n  _getVersionDetails: function (version) {\n    var self = this;\n    var versionRecord =\n       catalog.official.getReleaseVersion(self.name, version);\n    if (! versionRecord) {\n      return null;\n    }\n    var publishDate = getReleaseVersionPublishedOn(versionRecord);\n    return {\n      track: self.name,\n      version: version,\n      description: versionRecord.description,\n      recommended: versionRecord.recommended,\n      orderKey: versionRecord.orderKey,\n      publishedBy: versionRecord.publishedBy[\"username\"],\n      pubishedOn: publishDate,\n      packages: versionRecord.packages,\n      tool: versionRecord.tool\n    };\n  },\n  // Gets aggregate data about this release track in general. Returns an object\n  // with the following keys:\n  //    - track: name of the release track\n  //    - maintainers: an array of usernames of maintainers\n  //    - defaultVersion: version record for the default version of this release.\n  //    - totalVersions: total number of release versions for this track\n  //    - versions: an array of version objects. If only recommended versions\n  //      are returned, ordered by orderKey, otherwise unordered. Objects have\n  //      the following keys:\n  //         - version: version number\n  //         - description: version description\n  //         - recommended: true for recommended versions\n  //         - orderKey: (only if showHiddenVersions is true) the orderKey of\n  //           this version.\n  //         - publishedBy: username of the publisher\n  //         - publishedOn: date the version was published\n  _getReleaseData: function () {\n    var self = this;\n    var data = {\n      track: self.metaRecord.name,\n      maintainers: _.pluck(self.metaRecord.maintainers, \"username\")\n    };\n    data[\"defaultVersion\"] =\n      catalog.official.getDefaultReleaseVersionRecord(self.name);\n\n    // Collect information about versions.\n    var versions;\n    if (self.showHiddenVersions) {\n      // There is no obvious way to get an absolute ranking of all release\n      // versions, so this is unsorted. If we have to, we will deal with sorting\n      // this at display time.\n      versions = catalog.official.getReleaseVersionRecords(self.name);\n    } else {\n      versions = catalog.official.getSortedRecommendedReleaseRecords(self.name);\n      versions.reverse();\n    }\n\n    // We don't want to show the user package or tool data in general release\n    // mode (it is a lot of data). Select to show the fields that we want to\n    // return only.\n    var versionFields =\n       [ \"version\", \"description\", \"recommended\"];\n\n    // orderKey is important for dealing with experimental versions, but it is\n    // an internal system detail that we would rather not reveal at this level.\n    if (self.showHiddenVersions) {\n      versionFields.push(\"orderKey\");\n    }\n    data[\"versions\"] = _.map(versions, function (versionRecord) {\n      var data = _.pick(versionRecord, versionFields);\n      data.publishedBy = versionRecord.publishedBy[\"username\"];\n      data.publishedOn = getReleaseVersionPublishedOn(versionRecord);\n      return data;\n    });\n    data[\"totalVersions\"] = catalog.official.getNumReleaseVersions(self.name);\n    return data;\n  },\n  // Displays information about a specific release version in a human-readable\n  // format. Takes in an object with the following keys:\n  // - track: release track\n  // - version: release version\n  // - publishedBy: username of the publisher\n  // - publishedOn: date the version was published\n  // - recommended: true if this is a recommended version\n  // - description: description of the release version\n  // - tool: tool package specification for this version\n  // - packages: map of packages for this release version\n  _displayVersion: function (data) {\n    var self = this;\n    Console.info(\"Release: \" + data.track + \"@\" + data.version);\n    var isRecommended = data.recommended ? \"yes\" : \"no\";\n    Console.info(\"Recommended: \" + isRecommended);\n    Console.info(\"Tool package: \" + data.tool);\n    Console.info();\n    Console.info(data.description);\n    Console.info();\n    if (!_.isEmpty(data.packages)) {\n      Console.info(\"Packages:\");\n      _.each(data.packages, function (version, packageName) {\n          Console.info(\n            packageName + \": \" + version,\n            Console.options({ indent: 2 }));\n      });\n      Console.info();\n    }\n    Console.info(\n      \"Published by \" + data.publishedBy + \" on \" +\n      utils.longformDate(getReleaseVersionPublishedOn(data)));\n  },\n  // Displays information about this release track in general in a\n  // human-readable format. Takes in an object with the following keys:\n  //    - track: name of the release track\n  //    - maintainers: an array of usernames of maintainers\n  //    - defaultVersion: version record for the default version of this release.\n  //    - totalVersions: total number of release versions for this track\n  //    - versions: an array of version objects. If only recommended versions\n  //      are returned, ordered by orderKey, otherwise unordered. Objects have\n  //      the following keys:\n  //         - version: version number\n  //         - description: version description\n  //         - recommended: true for recommended versions\n  //         - orderKey: (only if showHiddenVersions is true) the orderKey of\n  //           this version.\n  //         - publishedBy: username of the publisher\n  //         - publishedOn: date the version was published\n  _displayRelease: function (data) {\n    var self = this;\n\n    Console.info(\"Release:\",  data.track);\n    // There is no such thing as a local release, which means all releases have\n    // a maintainer.\n    Console.info(\"Maintainers:\", data.maintainers.join(\", \"));\n    Console.info();\n\n    if (data.defaultVersion) {\n      Console.info(data.defaultVersion.description);\n      Console.info();\n    }\n\n    if (self.showHiddenVersions) {\n      self._displayAllReleaseVersions(data.versions);\n      return;\n    }\n\n    // Display the recommended versions of this release.\n    var rows = [];\n    if (!_.isEmpty(data.versions)) {\n      Console.info(\"Recommended versions:\");\n      _.each(data.versions, function (v) {\n        rows.push([v.version, utils.longformDate(v.publishedOn)]);\n      });\n      Console.printTwoColumns(rows, { indent: 2 });\n    };\n\n    // Display a warning about other release versions at the bottom.\n    if (data.totalVersions > rows.length) {\n      var versionsPluralizer =\n            (data.totalVersions > 1) ?\n            \"all \" + data.totalVersions + \" versions\" :\n            \"the hidden version\";\n      // We only hide release versions for one reason -- they are not\n      // recommended. We would have to parse version numbers to differentiate\n      // between 'pre-release' and 'deprecated' (and sort-of-experimental, like\n      // '1.0-weird-trick) and we don't want to rely on version number\n      // conventions in code.\n      var versionsHidden =\n            (data.totalVersions - rows.length > 1) ?\n            \"Non-recommended versions of \" + self.name + \" have been hidden.\" :\n            \"One non-recommended version of \" + self.name + \" has been hidden.\";\n\n      Console.info(\n        versionsHidden,\n        \"To see \" + versionsPluralizer + \", run\",\n        Console.command(\"'meteor show --show-all \" + self.name + \"'\") + \".\");\n    }\n  },\n  // Displays all the versions of a given release in a human-readable\n  // format. Includes experimental and otherwise hidden versions. Takes in an\n  // array of version objects, each of which has the following keys:\n  //  - version: version string\n  //  - orderKey: (optional) orderKey of this version. Not all versions have\n  //    orderKeys.\n  //  - publishedOn: date of publication\n  //  - recommended: true if the version is recommended.\n  _displayAllReleaseVersions: function (versions) {\n    var self = this;\n    var columnOpts = { indent: 2, ignoreWidth: true };\n    // If we don't have any versions, then there is nothing to display.\n    if (! versions) { return; }\n\n    // We are going to print versions with order key ('versions'), separately\n    // from versions without an order key ('experimental versions').\n    var versionsDivided = _.groupBy(versions, function (v) {\n      return _.has(v, \"orderKey\");\n    });\n    var experimentalVersions = versionsDivided[false];\n    var versionsWithKey = versionsDivided[true];\n\n    if (versionsWithKey) {\n      // Sort versions that have order keys by order key, so that 1.0 comes\n      // after 0.9.4.1, etc.\n      versionsWithKey = _.sortBy(versionsWithKey, function (v) {\n        return v.orderKey;\n      });\n      Console.info(\"Versions:\");\n      var rows = [];\n      _.each(versionsWithKey, function (vr) {\n        var dateStr = utils.longformDate(vr.publishedOn);\n        if (! vr.recommended) {\n          rows.push([ vr.version, dateStr ]);\n        } else {\n          var paddedDate = padLongformDate(dateStr);\n          rows.push([ vr.version, paddedDate + \"  (recommended)\" ]);\n        }\n      });\n      Console.printTwoColumns(rows, columnOpts);\n    }\n\n    if (experimentalVersions) {\n      // We can't sort by order key, so sort by order of publication.\n      experimentalVersions = _.sortBy(experimentalVersions, function (v) {\n        return v.publishedOn;\n      });\n      Console.info(\"Experimental versions:\");\n      var rows = [];\n      _.each(experimentalVersions, function (vr) {\n        // Experimental versions cannot be recommended.\n        rows.push([vr.version, utils.longformDate(vr.publishedOn)]);\n      });\n      Console.printTwoColumns(rows, columnOpts);\n    }\n  }\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// show\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'show',\n  pretty: true,\n  minArgs: 0,\n  maxArgs: 1,\n  usesPackage: true,\n  options: {\n    \"show-all\": { type: Boolean },\n    \"ejson\": { type: Boolean }\n  },\n  catalogRefresh:\n    new catalog.Refresh.OnceAtStart(\n        { maxAge: DEFAULT_MAX_AGE_MS, ignoreErrors: true })\n}, function (options) {\n  var fullName;\n  var name;\n  var version;\n  // Because of the new projectContext interface, we need to initialize the\n  // project context in order to load the local catalog. This is not ideal.\n  var projectContext = getTempContext(options);\n\n  // If the user specified a query, process it.\n  if (! _.isEmpty(options.args)) {\n    // The foo@bar API means that we have to do some string parsing to figure out\n    // if we want a particular version.\n    fullName = options.args[0];\n    var splitArgs = fullName.split('@');\n    name = splitArgs[0];\n    version = (splitArgs.length > 1) ? splitArgs[1] : null;\n    if (splitArgs.length > 2) {\n      Console.error(\"Invalid request format: \" + fullName);\n      process.exit(1);\n    }\n  } else {\n    if (! options.packageDir) {\n      // Letting the user run 'meteor show' without arguments from a package\n      // directory is a pleasant shortcut, but the default should be specifying\n      // a query.\n      Console.error(\n        \"Please specify a package or release name to show information about it.\"\n      );\n      process.exit(1);\n    }\n    // Use the projectContext to get the name of the package.\n    var currentVersion =\n          projectContext.localCatalog.getVersionBySourceRoot(options.packageDir);\n    name = currentVersion.packageName;\n    version = \"local\";\n    fullName = name + \"@local\";\n  }\n  var query = null;\n\n  // First, we need to figure out if we are dealing with a package, or a\n  // release. We don't want to rely on capitalization conventions, so we will\n  // start by checking if a package by that name exists. If it does, then we are\n  // dealing with a package. (Unlike the normal projectContext, we want to\n  // prefer the remote record, if one exists, rather than the local record. The\n  // remote record contains data like 'homepage' and 'maintainers', that the\n  // local record does not).\n  var packageRecord =\n        catalog.official.getPackage(name) ||\n        projectContext.localCatalog.getPackage(name);\n  if (packageRecord) {\n    query =  new PackageQuery({\n      metaRecord: packageRecord,\n      version: version,\n      projectContext: projectContext,\n      showHiddenVersions: options[\"show-all\"],\n      showArchitecturesOS: options.ejson,\n      showDependencies: !! version\n    });\n  }\n\n  // If this is not a package, it might be a release. Let's check if there is\n  // a release by this name. There are no local releases, so we only need to\n  // check the official catalog.\n  if (! query) {\n    var releaseRecord = catalog.official.getReleaseTrack(name);\n    if (releaseRecord) {\n      query = new ReleaseQuery({\n        metaRecord: releaseRecord,\n        version: version,\n        showHiddenVersions: options[\"show-all\"]\n      });\n    }\n  }\n  // If we have failed to create a query, or if we have created a query and it\n  // couldn't gather any data about our request, then the item that we are\n  // looking for does not exist.\n  if (! query || ! query.data) {\n    return itemNotFound(fullName);\n  }\n\n  query.print({ ejson: !! options.ejson });\n  return 0;\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// search\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'search',\n  pretty: true,\n  usesPackage: true,\n  minArgs: 0, // So we can provide specific help\n  maxArgs: 1,\n  options: {\n    maintainer: { type: String },\n    \"show-all\": { type: Boolean },\n    ejson: { type: Boolean },\n    // Undocumented debug-only option (originally added for Velocity).\n    \"debug-only\": { type: Boolean },\n    \"prod-only\": { type: Boolean },\n    \"test-only\": { type: Boolean },\n  },\n  catalogRefresh:\n    new catalog.Refresh.OnceAtStart(\n      { maxAge: DEFAULT_MAX_AGE_MS, ignoreErrors: true })\n}, function (options) {\n  if (options.args.length === 0) {\n    Console.info(\n      \"To show all packages, do\", Console.command(\"meteor search .\"));\n    return 1;\n  }\n\n  // Because of the new projectContext interface, we need to initialize the\n  // project context in order to load the local catalog.\n  var projectContext = getTempContext(options);\n\n  // XXX We should push the queries into SQLite!\n  var allPackages = _.union(\n    catalog.official.getAllPackageNames(),\n    projectContext.localCatalog.getAllPackageNames());\n  var allReleases = catalog.official.getAllReleaseTracks();\n  var matchingPackages = [];\n  var matchingReleases = [];\n\n  var selector;\n  var pattern = options.args[0];\n\n  var search;\n  try {\n    search = new RegExp(pattern);\n  } catch (err) {\n    Console.error(err + \"\");\n    return 1;\n  }\n\n  // Do not return true on broken packages, unless requested in options.\n  var filterBroken = function (match, isRelease, name) {\n    // If the package does not match, or it is not a package at all or if we\n    // don't want to filter anyway, we do not care.\n    if (!match || isRelease) {\n      return match;\n    }\n    var vr;\n    if (!options[\"show-all\"]) {\n      // If we can't find a version in the local catalog, we want to get the\n      // latest mainline (ie: non-RC) version from the official catalog.\n      vr = projectContext.localCatalog.getLatestVersion(name) ||\n        catalog.official.getLatestMainlineVersion(name);\n    } else {\n      // We want the latest version of this package, and we don't care if it is\n      // a release candidate.\n      vr = projectContext.projectCatalog.getLatestVersion(name);\n    }\n    if (!vr) {\n      return false;\n    }\n    // If we did NOT ask for unmigrated packages and this package is unmigrated,\n    // we don't care.\n    if (!options[\"show-all\"] && vr.unmigrated){\n      return false;\n    }\n    // If we asked for debug-only packages and this package is NOT debug only,\n    // we don't care.\n    if (options[\"debug-only\"] && !vr.debugOnly) {\n      return false;\n    }\n    // If we asked for prod-only packages and this package is NOT prod only,\n    // we don't care.\n    if (options[\"prod-only\"] && !vr.prodOnly) {\n      return false;\n    }\n    // If we asked for test-only packages and this package is NOT test only,\n    // we don't care.\n    if (options[\"test-only\"] && !vr.testOnly) {\n      return false;\n    }\n    return true;\n  };\n\n  if (options.maintainer) {\n    var username =  options.maintainer;\n    // In the future, we should consider checking this on the server, but I\n    // suspect the main use of this command will be to deal with the automatic\n    // migration and uncommon in everyday use. From that perspective, it makes\n    // little sense to require you to be online to find out what packages you\n    // own; and the consequence of not mentioning your group packages until\n    // you update to a new version of meteor is not that dire.\n    selector = function (name, isRelease) {\n      var record;\n      // XXX make sure search works while offline\n      if (isRelease) {\n        record = catalog.official.getReleaseTrack(name);\n      } else {\n        record = catalog.official.getPackage(name);\n      }\n      return filterBroken(\n        (name.match(search) &&\n         record && !!_.findWhere(record.maintainers, {username: username})),\n        isRelease, name);\n    };\n  } else {\n    selector = function (name, isRelease) {\n      return filterBroken(name.match(search),\n        isRelease, name);\n    };\n  }\n\n  buildmessage.enterJob({ title: 'Searching packages' }, function () {\n    _.each(allPackages, function (pack) {\n      if (selector(pack, false)) {\n        var vr;\n        if (!options['show-all']) {\n          vr =\n            projectContext.localCatalog.getLatestVersion(pack) ||\n            catalog.official.getLatestMainlineVersion(pack);\n        } else {\n          vr = projectContext.projectCatalog.getLatestVersion(pack);\n        }\n        if (vr) {\n          matchingPackages.push({\n            name: pack,\n            description: vr.description,\n            latestVersion: vr.version,\n            lastUpdated: new Date(vr.lastUpdated)\n          });\n        }\n      }\n    });\n    _.each(allReleases, function (track) {\n      if (selector(track, true)) {\n        var vr = catalog.official.getDefaultReleaseVersionRecord(track);\n        if (vr) {\n          matchingReleases.push({\n            name: track,\n            description: vr.description,\n            latestVersion: vr.version,\n            lastUpdated: new Date(vr.lastUpdated)\n          });\n        }\n      }\n    });\n  });\n\n  if (options.ejson) {\n    var ret = {\n      packages: matchingPackages,\n      releases: matchingReleases\n    };\n    Console.rawInfo(formatEJSON(ret));\n    return 0;\n  }\n\n  var output = false;\n  if (!_.isEqual(matchingPackages, [])) {\n    output = true;\n    Console.info(\"Matching packages:\");\n    utils.printPackageList(matchingPackages);\n  }\n\n  if (!_.isEqual(matchingReleases, [])) {\n    output = true;\n    Console.info(\"Matching releases:\");\n    utils.printPackageList(matchingReleases);\n  }\n\n  if (!output) {\n    Console.error(pattern + ': nothing found');\n    catalogUtils.explainIfRefreshFailed();\n  } else {\n    Console.info(\n      \"You can use\", Console.command(\"'meteor show'\"),\n      \"to get more information on a specific item.\");\n  }\n});\n"
  },
  {
    "path": "tools/cli/commands-packages.js",
    "content": "var main = require('./main.js');\nvar _ = require('underscore');\nvar files = require('../fs/files.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar auth = require('../meteor-services/auth.js');\nvar config = require('../meteor-services/config.js');\nvar utils = require('../utils/utils.js');\nvar httpHelpers = require('../utils/http-helpers.js');\nvar compiler = require('../isobuild/compiler.js');\nvar catalog = require('../packaging/catalog/catalog.js');\nvar catalogRemote = require('../packaging/catalog/catalog-remote.js');\nvar isopack = require('../isobuild/isopack.js');\nvar updater = require('../packaging/updater.js');\nvar Console = require('../console/console.js').Console;\nvar projectContextModule = require('../project-context.js');\nvar colonConverter = require('../utils/colon-converter.js');\nvar catalogUtils = require('../packaging/catalog/catalog-utils.js');\n\nvar release = require('../packaging/release.js');\nvar packageVersionParser = require('../packaging/package-version-parser.js');\nvar updater = require('../packaging/updater.js');\nvar packageMapModule = require('../packaging/package-map.js');\nvar packageClient = require('../packaging/package-client.js');\nvar tropohouse = require('../packaging/tropohouse.js');\n\nimport * as cordova from '../cordova';\n\n// For each release (or package), we store a meta-record with its name,\n// maintainers, etc. This function takes in a name, figures out if\n// it is a release or a package, and fetches the correct record.\n//\n// Specifically, it returns an object with the following keys:\n//  - record : (a package or version record)\n//  - isRelease : true if it is a release instead of a package.\nvar getReleaseOrPackageRecord = function(name) {\n  var rec = catalog.official.getPackage(name);\n  var rel = false;\n  if (!rec) {\n    // Not a package! But is it a release track?\n    rec = catalog.official.getReleaseTrack(name);\n    if (rec) {\n      rel = true;\n    }\n  }\n  return { record: rec, isRelease: rel };\n};\n\n// Seriously, this dies if it can't refresh. Only call it if you're sure you're\n// OK that the command doesn't work while offline.\nvar refreshOfficialCatalogOrDie = function (options) {\n  if (!catalog.refreshOrWarn(options)) {\n    Console.error(\n      \"This command requires an up-to-date package catalog. Exiting.\");\n    throw new main.ExitWithCode(1);\n  }\n};\n\nvar removeIfEndsWith = function (s, suffix) {\n  if (s.endsWith(suffix)) {\n    return s.substring(0, s.length - suffix.length);\n  }\n  return s;\n};\n\n// Internal use only. Makes sure that your Meteor install is totally good to go\n// (is \"airplane safe\"). Specifically, it:\n//    - Builds all local packages, even those you're not using in your current\n//      app. (If you're not in an app, it still does this even though there is\n//      no persistent IsopackCache, because this still causes npm dependencies\n//      to be downloaded.)\n//    - Ensures that all packages in your current release are downloaded, even\n//      those you're not using in your current app.\n//    - Ensures that all packages used by your app (if any) are downloaded\n// (It also ensures you have the dev bundle downloaded, just like every command\n// in a checkout.)\n//\n// The use case is, for example, cloning an app from github, running this\n// command, then getting on an airplane.\n//\n// This does NOT guarantee a *re*build of all local packages (though it will\n// download any new dependencies): we still trust the buildinfo files in your\n// app's IsopackCache. If you want to rebuild all local packages that are used\n// in your app, call meteor rebuild. That said, rebuild should only be necessary\n// if there's a bug in the build tool... otherwise, packages should be rebuilt\n// whenever necessary!\nmain.registerCommand({\n  name: '--get-ready',\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: false }),\n  options: {\n    'allow-incompatible-update': { type: Boolean }\n  }\n}, function (options) {\n  // If we're in an app, make sure that we can build the current app. Otherwise\n  // just make sure that we can build some fake app.\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: options.appDir || files.mkdtemp('meteor-get-ready'),\n    neverWriteProjectConstraintsFile: true,\n    neverWritePackageMap: true,\n    allowIncompatibleUpdate: options['allow-incompatible-update']\n  });\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    projectContext.initializeCatalog();\n  });\n\n  // Add every local package (including tests) and every release package to this\n  // project. (Hopefully they can all be built at once!)\n  var addPackages = function (packageNames) {\n    projectContext.projectConstraintsFile.addConstraints(\n      _.map(packageNames, function (p) {\n        return utils.parsePackageConstraint(p);\n      })\n    );\n  };\n  addPackages(projectContext.localCatalog.getAllPackageNames());\n  if (release.current.isProperRelease()) {\n    addPackages(_.keys(release.current.getPackages()));\n  }\n\n  // Now finish building and downloading.\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    projectContext.prepareProjectForBuild();\n  });\n  // We don't display package changes because they'd include all these packages\n  // not actually in the app!\n  // XXX Maybe we should do a first pass that only builds packages actually in\n  // the app and does display the PackageMapDelta?\n  return 0;\n});\n\n\n// Internal use only. A simpler version of --get-ready which doesn't try to also\n// build/download local and release packages that aren't currently used. Just\n// builds and downloads packages used by the current app.\nmain.registerCommand({\n  name: '--prepare-app',\n  requiresApp: true,\n  catalogRefresh: new catalog.Refresh.Never(),\n  options: {\n    'allow-incompatible-update': { type: Boolean }\n  }\n}, function (options) {\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: options.appDir,\n    allowIncompatibleUpdate: options['allow-incompatible-update']\n  });\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    projectContext.prepareProjectForBuild();\n  });\n  projectContext.packageMapDelta.displayOnConsole();\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// publish a package\n///////////////////////////////////////////////////////////////////////////////\n\n// Updates the metadata for a given package version. Prints user-friendly\n// messages if certain new values are invalid; calls to the packageClient to\n// perform the actual update.\n//\n// Takes in a packageSource and a connection to the package server. Returns 0 on\n// success and an exit code on failure.\nvar updatePackageMetadata = function (packageSource, conn) {\n    var name = packageSource.name;\n    var version = packageSource.version;\n\n    // You can't change the metadata of a record that doesn't exist.\n    var existingRecord =\n          catalog.official.getVersion(name, version);\n    if (! existingRecord) {\n      Console.error(\n        \"You can't call\",  Console.command(\"`meteor publish --update`\"),\n        \"on version \" + version + \" of \" + \"package '\" + name +\n          \"' without publishing it first.\");\n      return 1;\n    }\n\n    // Load in the user's documentation, and check that it isn't blank.\n    var readmeInfo;\n    main.captureAndExit(\n      \"=> Errors while publishing:\", \"reading documentation\",\n      function () {\n       readmeInfo = packageSource.processReadme();\n    });\n\n    // You are still not allowed to upload a blank README.md.\n    if (readmeInfo && readmeInfo.hash === files.blankHash) {\n      Console.error(\n        \"Your documentation file is blank, so users may have trouble\",\n        \"figuring out how to use your package. Please fill it out, or\",\n        \"set 'documentation: null' in your Package.describe.\");\n      return 1;\n    };\n\n    // Finally, call to the server.\n    main.captureAndExit(\n      \"=> Errors while publishing:\",\n      \"updating package metadata\",\n      function () {\n        packageClient.updatePackageMetadata({\n          packageSource: packageSource,\n          readmeInfo: readmeInfo,\n          connection: conn\n        });\n    });\n\n    Console.info(\n      \"Success. You can take a look at the new metadata by running\",\n      Console.command(\"'meteor show \" + name + \"@\" + version + \"'\"),\n      \"outside the current project directory.\");\n\n    // Refresh, so that we actually learn about the thing we just published.\n    refreshOfficialCatalogOrDie();\n    return 0;\n}\n\nmain.registerCommand({\n  name: 'publish',\n  minArgs: 0,\n  maxArgs: 0,\n  options: {\n    create: { type: Boolean },\n    update: { type: Boolean },\n    // This is similar to publish-for-arch, but uses the source code you have\n    // locally (and other local packages you may have) instead of downloading\n    // the source bundle. It does verify that the source is the same, though.\n    // Good for bootstrapping things in the core release.\n    'existing-version': { type: Boolean },\n    // This is the equivalent of \"sudo\": make sure that administrators don't\n    // accidentally put their personal packages in the top level namespace.\n    'top-level': { type: Boolean },\n    // An option to publish despite linting errors\n    'no-lint': { type: Boolean }\n  },\n  requiresPackage: true,\n  // We optimize the workflow by using up-to-date package data to weed out\n  // obviously incorrect submissions before they ever hit the wire.\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: false }),\n  'allow-incompatible-update': { type: Boolean }\n}, function (options) {\n  if (options.create && options['existing-version']) {\n    // Make up your mind!\n    Console.error(\n      \"The --create and --existing-version options cannot\",\n      \"both be specified.\");\n    return 1;\n  }\n\n  if (options.update && options.create) {\n    Console.error(\n      \"The --create and --update options cannot both be specified.\");\n    return 1;\n  }\n\n  if (options.update && options[\"existing-version\"]) {\n    Console.error(\n      \"The --update option implies that the version already exists.\",\n      \"You do not need to use the --existing-version flag with --update.\");\n    return 1;\n  }\n\n  var projectContext;\n  if (! options.appDir) {\n    // We're not in an app? OK, make a temporary app directory, and make sure\n    // that the current package directory is found by its local catalog.\n    var tempProjectDir = files.mkdtemp('meteor-package-build');\n    projectContext = new projectContextModule.ProjectContext({\n      projectDir: tempProjectDir,  // won't have a packages dir, that's OK\n      explicitlyAddedLocalPackageDirs: [options.packageDir],\n      packageMapFilename: files.pathJoin(options.packageDir, '.versions'),\n      // We always want to write our '.versions' package map, overriding a\n      // comparison against the value of a release file that doesn't exist.\n      alwaysWritePackageMap: true,\n      // When we publish, we should always include web.cordova unibuilds, even\n      // though this temporary directory does not have any cordova platforms\n      forceIncludeCordovaUnibuild: true,\n      allowIncompatibleUpdate: options['allow-incompatible-update'],\n      lintPackageWithSourceRoot: options['no-lint'] ? null : options.packageDir,\n    });\n  } else {\n    // We're in an app; let the app be our context, but make sure we don't\n    // overwrite .meteor/packages or .meteor/versions when we add some temporary\n    // constraints (which ensure that we can actually build the package and its\n    // tests).\n    projectContext = new projectContextModule.ProjectContext({\n      projectDir: options.appDir,\n      neverWriteProjectConstraintsFile: true,\n      neverWritePackageMap: true,\n      // When we publish, we should always include web.cordova unibuilds, even\n      // if this project does not have any cordova platforms\n      forceIncludeCordovaUnibuild: true,\n      allowIncompatibleUpdate: options['allow-incompatible-update'],\n      lintPackageWithSourceRoot: options['no-lint'] ? null : options.packageDir,\n    });\n  }\n\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    // Just get up to initializing the catalog. We're going to mutate the\n    // constraints file a bit before we prepare the build.\n    projectContext.initializeCatalog();\n  });\n\n  if (!process.env.METEOR_TEST_NO_PUBLISH) {\n    // Connect to the package server and log in.\n    try {\n      var conn = packageClient.loggedInPackagesConnection();\n    } catch (err) {\n      packageClient.handlePackageServerConnectionError(err);\n      return 1;\n    }\n    if (! conn) {\n      Console.error('No connection: Publish failed.');\n      return 1;\n    }\n  }\n\n  var localVersionRecord = projectContext.localCatalog.getVersionBySourceRoot(\n    options.packageDir);\n  if (! localVersionRecord) {\n    // OK, we're inside a package (ie, a directory with a package.js) and we're\n    // inside an app (ie, a directory with a file named .meteor/packages) but\n    // the package is not on the app's search path (ie, it's probably not\n    // directly inside the app's packages directory).  That's kind of\n    // weird. Let's not allow this.\n    Console.error(\n      \"The package you are in appears to be inside a Meteor app but is not \" +\n       \"in its packages directory. You may only publish packages that are \" +\n       \"entirely outside of a project or that are loaded by the project \" +\n       \"that they are inside.\");\n    return 1;\n  }\n  var packageName = localVersionRecord.packageName;\n  var packageSource = projectContext.localCatalog.getPackageSource(packageName);\n  if (! packageSource) {\n    throw Error(\"no PackageSource for \" + packageName);\n  }\n\n  // Anything published to the server must explicitly set a version.\n  if (! packageSource.versionExplicitlyProvided) {\n    Console.error(\"A version must be specified for the package. Set it with \" +\n                  \"Package.describe.\");\n    return 1;\n  }\n\n  // If we just want to update the package metadata, then we have all we\n  // need. Don't bother building the package, just update the metadata and\n  // return the result.\n  if (options.update) {\n    return updatePackageMetadata(packageSource, conn);\n  }\n\n  // Fail early if the package record exists, but we don't think that it does\n  // and are passing in the --create flag!\n  if (options.create) {\n    var packageInfo = catalog.official.getPackage(packageName);\n    if (packageInfo) {\n      Console.error(\n        \"Package already exists. To create a new version of an existing \"+\n        \"package, do not use the --create flag!\");\n      return 2;\n    }\n\n    if (!options['top-level'] && !packageName.match(/:/)) {\n      Console.error(\n        \"Only administrators can create top-level packages without an\",\n        \"account prefix. (To confirm that you wish to create a top-level\",\n        \"package with no account prefix, please run this command again\",\n        \"with the --top-level option.)\");\n      // You actually shouldn't be able to get here without being logged in, but\n      // it seems poor form to assume anything like that for the point of a\n      // brief error message.\n      if (auth.isLoggedIn()) {\n        var properName =  auth.loggedInUsername() + \":\" + packageName;\n        Console.error(\n          \"\\nDid you mean to create \" + properName + \" instead?\"\n       );\n      }\n      return 2;\n    }\n  }\n\n  // Make sure that both the package and its test (if any) are actually built.\n  _.each([packageName, packageSource.testName], function (name) {\n    if (! name) {\n      // for testName\n      return;\n    }\n\n    // If we're already using this package, that's OK; no need to override.\n    if (projectContext.projectConstraintsFile.getConstraint(name)) {\n      return;\n    }\n    projectContext.projectConstraintsFile.addConstraints(\n      [utils.parsePackageConstraint(name)]);\n  });\n\n  // Now resolve constraints and build packages.\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    projectContext.prepareProjectForBuild();\n  });\n  // We don't display the package map delta here, because it includes adding the\n  // package's test and all the test's dependencies.\n\n  if (!options['no-lint']) {\n    const warnings = projectContext.getLintingMessagesForLocalPackages();\n    if (warnings && warnings.hasMessages()) {\n      Console.arrowError(\n        \"Errors linting your package; run with --no-lint to ignore.\");\n      Console.printMessages(warnings);\n      return 1;\n    } else if (warnings) {\n      Console.arrowInfo('Linted your package. No linting errors.');\n    }\n  }\n\n  if (process.env.METEOR_TEST_NO_PUBLISH) {\n    Console.error(\n      'Would publish the package at this point, but since the ' +\n      'METEOR_TEST_NO_PUBLISH environment variable is set, just going ' +\n      'to finish here.');\n    return 0;\n  }\n\n  var isopack = projectContext.isopackCache.getIsopack(packageName);\n  if (! isopack) {\n    // This shouldn't happen; we already threw a different error if the package\n    // wasn't even in the local catalog, and we explicitly added this package to\n    // the project's constraints file, so it should have been built.\n    throw Error(\"package not built even though added to constraints?\");\n  }\n\n  // We have initialized everything, so perform the publish operation.\n  var binary = isopack.platformSpecific();\n  main.captureAndExit(\n    \"=> Errors while publishing:\",\n    \"publishing the package\",\n    function () {\n      packageClient.publishPackage({\n        projectContext: projectContext,\n        packageSource: packageSource,\n        connection: conn,\n        new: options.create,\n        existingVersion: options['existing-version'],\n        doNotPublishBuild: binary && !options['existing-version']\n      });\n    });\n\n  Console.info('Published ' + packageName + '@' + localVersionRecord.version +\n               '.');\n\n  // We are only publishing one package, so we should close the connection, and\n  // then exit with the previous error code.\n  conn.close();\n\n  // Warn the user if their package is not good for all architectures.\n  if (binary && options['existing-version']) {\n    // This is an undocumented command that you are not supposed to run! We\n    // assume that you know what you are doing, if you ran it, and are OK with\n    // overrwriting normal compatibilities.\n    Console.warn();\n    Console.labelWarn(\"Your package contains binary code.\");\n  } else if (binary) {\n    // Normal publish flow. Tell the user nicely.\n    Console.warn();\n    Console.warn(\n      \"You're not done publishing yet! This package contains binary code and\",\n      \"must be built on all of Meteor's architectures, including this\",\n      \"machine's architecture.\");\n    Console.warn();\n    Console.info(\n      \"You can access Meteor provided build machines, pre-configured to\",\n      \"support older versions of MacOS and Linux, by running:\");\n    _.each([\"os.osx.x86_64\", \"os.linux.x86_64\",\n            \"os.linux.x86_32\", \"os.windows.x86_32\"],\n      function (a) {\n        Console.info(\n          Console.command(\"meteor admin get-machine \" + a),\n          Console.options({ indent: 2 }));\n    });\n\n    Console.info();\n    Console.info(\"On each machine, run:\");\n    Console.info();\n    Console.info(\n      Console.command(\n        \"meteor publish-for-arch \" +\n        packageSource.name + \"@\" + packageSource.version),\n      Console.options({ indent: 2 }));\n    Console.info();\n    Console.info(\n      \"For more information on binary ABIs and consistent builds, see:\");\n    Console.info(\n      Console.url(\"https://github.com/meteor/meteor/wiki/Build-Machines\"),\n      Console.options({ indent: 2 })\n    );\n    Console.info();\n  }\n\n  // Refresh, so that we actually learn about the thing we just published.\n  refreshOfficialCatalogOrDie();\n\n  return 0;\n});\n\n\nmain.registerCommand({\n  name: 'publish-for-arch',\n  minArgs: 1,\n  maxArgs: 1,\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: false }),\n  // in theory, this option shouldn't be necessary, because when you run\n  // publish-for-arch you want to reproduce the exact same setup as when\n  // you ran 'publish', but support the option in case it comes up.\n  'allow-incompatible-update': { type: Boolean }\n}, function (options) {\n  // argument processing\n  var all = options.args[0].split('@');\n  if (all.length !== 2) {\n    Console.error(\n      'Incorrect argument. Please use the form of <packageName>@<version>');\n    throw new main.ShowUsage;\n  }\n  var name = all[0];\n  var versionString = all[1];\n\n  var packageInfo = catalog.official.getPackage(name);\n  if (! packageInfo) {\n    Console.error(\n      \"You can't call \" + Console.command(\"`meteor publish-for-arch`\") +\n      \"on package '\" + name + \"' without \" +\" publishing it first.\"\n    );\n    Console.error();\n    Console.error(\n      \"To publish the package, run \" +\n       Console.command(\"`meteor publish --create` \") +\n      \"from the package directory.\");\n    Console.error();\n    return 1;\n  }\n\n  var pkgVersion = catalog.official.getVersion(name, versionString);\n  if (! pkgVersion) {\n    Console.error(\n      \"You can't call\",  Console.command(\"`meteor publish-for-arch`\"),\n      \"on version \" + versionString + \" of \" + \"package '\" + name +\n      \"' without publishing it first.\");\n    Console.error();\n    Console.error(\n      \"To publish the package, run \" + Console.command(\"`meteor publish ` \") +\n      \"from the package directory.\");\n    Console.error();\n    return 1;\n  }\n\n  if (! pkgVersion.source || ! pkgVersion.source.url) {\n    Console.error(\n      \"There is no source uploaded for\",\n      name + '@' + versionString);\n    return 1;\n  }\n\n  // No releaseName (not even null): this predates the isopack-cache\n  // refactorings. Let's just springboard to Meteor 1.0 and let it deal with any\n  // further springboarding based on reading a nested json file.\n  if (! _.has(pkgVersion, 'releaseName')) {\n    if (files.inCheckout()) {\n      Console.error(\n        \"This package was published from an old version of meteor, \" +\n        \"but you are running from checkout! Consider running \" +\n        Console.command(\"`meteor --release 1.0`\"),\n        \"so we can springboard correctly.\");\n      process.exit(1);\n    }\n    throw new main.SpringboardToSpecificRelease(\"METEOR@1.0\");\n  }\n\n  if (pkgVersion.releaseName === null) {\n    if (! files.inCheckout()) {\n      Console.error(\n        \"This package was published from a checkout of meteor!\",\n        \"The tool cannot replicate that environment and will not even try.\",\n        \"Please check out meteor at the \" +\n        \"corresponding git commit and try again.\");\n      process.exit(1);\n    }\n  } else if (files.inCheckout()) {\n    Console.error(\n      \"This package was published from a built version of meteor, \" +\n      \"but you are running from checkout! Consider running from a \" +\n      \"proper Meteor release with \" +\n      Console.command(\"`meteor --release \" + pkgVersion.releaseName + \"`\"),\n      \"so we can springboard correctly.\");\n    process.exit(1);\n  } else if (pkgVersion.releaseName !== release.current.name) {\n    // We are in a built release, and so is the package, but it's a different\n    // one. Springboard!\n    throw new main.SpringboardToSpecificRelease(pkgVersion.releaseName);\n  }\n\n  // OK, either we're running from a checkout and so was the published package,\n  // or we're running from the same release as the published package.\n\n  // Download the source to the package.\n  var sourceTarball = buildmessage.enterJob(\"downloading package source\", function () {\n    return httpHelpers.getUrl({\n      url: pkgVersion.source.url,\n      encoding: null\n    });\n  });\n\n  var sourcePath = files.mkdtemp('package-source');\n  // XXX check tarballHash!\n  files.extractTarGz(sourceTarball, sourcePath);\n\n  // XXX Factor out with packageClient.bundleSource so that we don't\n  // have knowledge of the tarball structure in two places.\n  var packageDir = files.pathJoin(sourcePath, colonConverter.convert(name));\n  if (! files.exists(packageDir)) {\n    Console.error('Malformed source tarball');\n    return 1;\n  }\n\n  var tempProjectDir = files.mkdtemp('meteor-package-arch-build');\n  // Copy over a version lock file from the source tarball.\n  var versionsFile = files.pathJoin(packageDir, '.versions');\n  if (! files.exists(versionsFile)) {\n    Console.error(\n      \"This package has no valid version lock file: are you trying to use \" +\n      \"publish-for-arch on a core package? Publish-for-arch cannot \" +\n      \"guarantee safety. Please use\",\n      Console.command(\"'meteor publish --existing-version'\"), \"instead.\");\n    process.exit(1);\n  }\n  files.copyFile(files.pathJoin(packageDir, '.versions'),\n                 files.pathJoin(tempProjectDir, '.meteor', 'versions'));\n\n  // Set up the project.\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: tempProjectDir,\n    explicitlyAddedLocalPackageDirs: [packageDir],\n    // When we publish, we should always include web.cordova unibuilds, even\n    // though this temporary directory does not have any cordova platforms\n    forceIncludeCordovaUnibuild: true,\n    allowIncompatibleUpdate: options['allow-incompatible-update']\n  });\n  // Just get up to initializing the catalog. We're going to mutate the\n  // constraints file a bit before we prepare the build.\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    projectContext.initializeCatalog();\n  });\n  projectContext.projectConstraintsFile.addConstraints(\n    [utils.parsePackageConstraint(name + \"@=\" + versionString)]);\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    projectContext.prepareProjectForBuild();\n  });\n  projectContext.packageMapDelta.displayOnConsole({\n    title: \"Some package versions changed since this package was published!\"\n  });\n\n  var isopk = projectContext.isopackCache.getIsopack(name);\n  if (! isopk) {\n    throw Error(\"didn't build isopack for \" + name);\n  }\n\n  var conn;\n  try {\n    conn = packageClient.loggedInPackagesConnection();\n  } catch (err) {\n    packageClient.handlePackageServerConnectionError(err);\n    return 1;\n  }\n\n  main.captureAndExit(\n    \"=> Errors while publishing build:\",\n    (\"publishing package \" + name + \" for architecture \"\n     + isopk.buildArchitectures()),\n    function () {\n      packageClient.createAndPublishBuiltPackage(\n        conn, isopk, projectContext.isopackCache);\n    }\n  );\n\n  Console.info('Published ' + name + '@' + versionString + '.');\n\n  refreshOfficialCatalogOrDie();\n  return 0;\n});\n\nmain.registerCommand({\n  name: 'publish-release',\n  minArgs: 1,\n  maxArgs: 1,\n  options: {\n    'create-track': { type: Boolean },\n    'from-checkout': { type: Boolean }\n  },\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: false })\n}, function (options) {\n  try {\n    var conn = packageClient.loggedInPackagesConnection();\n  } catch (err) {\n    packageClient.handlePackageServerConnectionError(err);\n    return 1;\n  }\n\n  var relConf = {};\n\n  // Let's read the json release file. It should, at the very minimum contain\n  // the release track name, the release version and some short freeform\n  // description.\n  try {\n    var data = files.readFile(options.args[0], 'utf8');\n    relConf = JSON.parse(data);\n  } catch (e) {\n    Console.error(\"Could not parse release file: \" + e.message);\n    return 1;\n  }\n\n  // Fill in the order key and any other generated release.json fields.\n  main.captureAndExit(\n    \"=> Errors in release schema:\",\n    \"double-checking release schema\",\n    function () {\n      // Check that the schema is valid -- release.json contains all the\n      // required fields, does not contain contradicting information, etc.\n      // XXX Check for unknown keys?\n      if (! _.has(relConf, 'track')) {\n        buildmessage.error(\n          \"Configuration file must specify release track. (track).\");\n      }\n      if (! _.has(relConf, 'version')) {\n        buildmessage.error(\n          \"Configuration file must specify release version. (version).\");\n      }\n      if (! _.has(relConf, 'description')) {\n        buildmessage.error(\n          \"Configuration file must contain a description (description).\");\n      } else if (relConf.description.length > 100) {\n        buildmessage.error(\"Description must be under 100 characters.\");\n      }\n      if (! options['from-checkout']) {\n        if (! _.has(relConf, 'tool')) {\n          buildmessage.error(\n            \"Configuration file must specify a tool version (tool) unless in \" +\n              \"--from-checkout mode.\");\n        }\n        if (! _.has(relConf, 'packages')) {\n          buildmessage.error(\n            \"Configuration file must specify package versions (packages) \" +\n              \"unless in --from-checkout mode.\");\n        }\n      }\n\n      // If you didn't specify an orderKey and it's compatible with our\n      // conventional orderKey generation algorithm, use the algorithm. If you\n      // explicitly specify orderKey: null, don't include one.\n      if (! _.has(relConf, 'orderKey')) {\n        relConf.orderKey = utils.defaultOrderKeyForReleaseVersion(\n          relConf.version);\n      }\n      // This covers both the case of \"explicitly specified {orderKey: null}\"\n      // and \"defaultOrderKeyForReleaseVersion returned null\".\n      if (relConf.orderKey === null) {\n        delete relConf.orderKey;\n      }\n\n      if (! _.has(relConf, 'orderKey') && relConf.recommended) {\n        buildmessage.error(\"Recommended releases must have order keys.\");\n      }\n      // On the main release track, we can't name the release anything beginning\n      // with 0.8 and below, because those are taken for pre-troposphere\n      // releases.\n      if ((relConf.track === catalog.DEFAULT_TRACK)) {\n        var start = relConf.version.slice(0,4);\n        if (start === \"0.8.\" || start === \"0.7.\" ||\n            start === \"0.6.\" || start === \"0.5.\") {\n          buildmessage.error(\n            \"It looks like you are trying to publish a pre-package-server \" +\n            \"meteor release. Doing this through the package server is going \" +\n            \"to cause a lot of confusion. Please use the old release process.\");\n        }\n      }\n    }\n  );\n\n  // Let's check if this is a known release track/ a track to which we are\n  // authorized to publish before we do any complicated/long operations, and\n  // before we publish its packages.\n  if (! options['create-track']) {\n    var trackRecord = catalog.official.getReleaseTrack(relConf.track);\n    if (!trackRecord) {\n      Console.error(\n        'There is no release track named ' + relConf.track +\n        '. If you are creating a new track, use the --create-track flag.');\n      return 1;\n    }\n\n    // Check with the server to see if we're organized (we can't due this\n    // locally due to organizations).\n    if (!packageClient.amIAuthorized(relConf.track,conn,  true)) {\n      Console.error('You are not an authorized maintainer of ' +\n                    relConf.track + \".\");\n      Console.error('Only authorized maintainers may publish new versions.');\n      return 1;\n    }\n  }\n\n  // This is sort of a hidden option to just take your entire meteor checkout\n  // and make a release out of it. That's what we do now (that's what releases\n  // meant pre-0.90), and it is very convenient to do that here.\n  //\n  // If you have any unpublished packages at new versions in your checkout, this\n  // WILL PUBLISH THEM at specified versions. (If you have unpublished changes,\n  // including changes to build-time dependencies, but have not incremented the\n  // version number, this will use buildmessage to error and exit.)\n  //\n  // Without any modifications about forks and package names, this particular\n  // option is not very useful outside of MDG. Right now, to run this option on\n  // a non-MDG fork of meteor, someone would probably need to go through and\n  // change the package names to have proper prefixes, etc.\n  if (options['from-checkout']) {\n    // You must be running from checkout to bundle up your checkout as a release.\n    if (!files.inCheckout()) {\n      Console.error(\"Must run from checkout to make release from checkout.\");\n      return 1;\n    };\n\n    // You should not use a release configuration with packages&tool *and* a\n    // from checkout option, at least for now. That's potentially confusing\n    // (which ones did you mean to use) and makes it likely that you did one of\n    // these by accident. So, we will disallow it for now.\n    if (relConf.packages || relConf.tool) {\n      Console.error(\n        \"Setting the --from-checkout option will use the tool and packages \" +\n        \"in your meteor checkout. \" +\n        \"Your release configuration file should not contain that information.\");\n      return 1;\n    }\n\n    // Set up a temporary project context and build everything.\n    var tempProjectDir = files.mkdtemp('meteor-release-build');\n    var projectContext = new projectContextModule.ProjectContext({\n      projectDir: tempProjectDir,  // won't have a packages dir, that's OK\n      // seriously, we only want checkout packages\n      ignorePackageDirsEnvVar: true,\n      // When we publish, we should always include web.cordova unibuilds, even\n      // though this temporary directory does not have any cordova platforms\n      forceIncludeCordovaUnibuild: true\n    });\n\n    // Read metadata and initialize catalog.\n    main.captureAndExit(\"=> Errors while building for release:\", function () {\n      projectContext.initializeCatalog();\n    });\n\n    // Ensure that all packages and their tests are built. (We need to build\n    // tests so that we can include their sources in source tarballs.)\n    var allPackagesWithTests = projectContext.localCatalog.getAllPackageNames();\n    var allPackages = projectContext.localCatalog.getAllNonTestPackageNames();\n    projectContext.projectConstraintsFile.addConstraints(\n      _.map(allPackagesWithTests, function (p) {\n        return utils.parsePackageConstraint(p);\n      })\n    );\n\n    // Build!\n    main.captureAndExit(\"=> Errors while building for release:\", function () {\n      projectContext.prepareProjectForBuild();\n    });\n    // No need to display the PackageMapDelta here, since it would include all\n    // of the packages!\n\n    relConf.packages = {};\n    var toPublish = [];\n\n    main.captureAndExit(\"=> Errors in release packages:\", function () {\n      _.each(allPackages, function (packageName) {\n        buildmessage.enterJob(\"checking consistency of \" + packageName, function () {\n          var packageSource = projectContext.localCatalog.getPackageSource(\n            packageName);\n          if (! packageSource) {\n            throw Error(\"no PackageSource for built package \" + packageName);\n          }\n\n          if (! packageSource.versionExplicitlyProvided) {\n            buildmessage.error(\n              \"A version must be specified for the package. Set it with \" +\n                \"Package.describe.\");\n            return;\n          }\n\n          // Let's get the server version that this local package is\n          // overwriting. If such a version exists, we will need to make sure\n          // that the contents are the same.\n          var oldVersionRecord = catalog.official.getVersion(\n            packageName, packageSource.version);\n\n          // Include this package in our release.\n          relConf.packages[packageName] = packageSource.version;\n\n          // If there is no old version, then we need to publish this package.\n          if (! oldVersionRecord) {\n            // We are going to check if we are publishing an official\n            // release. If this is an experimental or pre-release, then we are\n            // not ready to commit to these package semver versions either. Any\n            // packages that we should publish as part of this release should\n            // have a -(something) at the end.\n            var newVersion = packageSource.version;\n            if (! relConf.official && newVersion.split(\"-\").length < 2) {\n              buildmessage.error(\n                \"It looks like you are building an experimental release or \" +\n                  \"pre-release. Any packages we publish here should have an \" +\n                  \"pre-release identifier at the end (eg, 1.0.0-dev). If \" +\n                  \"this is an official release, please set official to true \" +\n                  \"in the release configuration file.\");\n              return;\n            }\n            toPublish.push(packageName);\n            Console.info(\"Will publish new version for \" + packageName);\n            return;\n          } else {\n            var isopk = projectContext.isopackCache.getIsopack(packageName);\n            if (! isopk) {\n              throw Error(\"no isopack for \" + packageName);\n            }\n\n            var existingBuild =\n                  catalog.official.getBuildWithPreciseBuildArchitectures(\n                    oldVersionRecord, isopk.buildArchitectures());\n\n            var somethingChanged;\n\n            if (! existingBuild) {\n              // If the version number mentioned in package.js exists,\n              // but there's no build of this architecture, then\n              // either the old version was only semi-published, or\n              // you've added some platform-specific dependencies but\n              // haven't bumped the version number yet; either way,\n              // you should probably bump the version number.\n              somethingChanged = true;\n            } else {\n              // Save the isopack, just to get its hash.\n              var bundleBuildResult = packageClient.bundleBuild(\n                isopk,\n                projectContext.isopackCache,\n              );\n\n              somethingChanged =\n                (bundleBuildResult.treeHash !== existingBuild.build.treeHash);\n            }\n\n            if (somethingChanged) {\n              buildmessage.error(\n                \"Something changed in package \" + packageName + \"@\" +\n                  isopk.version + \". Please upgrade its version number.\");\n            }\n          }\n        });\n      });\n    });\n\n    // We now have an object of packages that have new versions on disk that\n    // don't exist in the server catalog. Publish them.\n    var unfinishedBuilds = {};\n    _.each(toPublish, function (packageName) {\n      main.captureAndExit(\n        \"=> Errors while publishing:\",\n        \"publishing package \" + packageName,\n        function () {\n          var isopk = projectContext.isopackCache.getIsopack(packageName);\n          if (! isopk) {\n            throw Error(\"no isopack for \" + packageName);\n          }\n          var packageSource = projectContext.localCatalog.getPackageSource(\n            packageName);\n          if (! packageSource) {\n            throw Error(\"no PackageSource for built package \" + packageName);\n          }\n\n          var binary = isopk.platformSpecific();\n          packageClient.publishPackage({\n            projectContext: projectContext,\n            packageSource: packageSource,\n            connection: conn,\n            new: ! catalog.official.getPackage(packageName),\n            doNotPublishBuild: binary\n          });\n          if (buildmessage.jobHasMessages()) {\n            return;\n          }\n\n          Console.info(\n            'Published ' + packageName + '@' + packageSource.version + '.');\n\n          if (binary) {\n            unfinishedBuilds[packageName] = packageSource.version;\n          }\n        });\n    });\n\n    // Set the remaining release information. For now, when we publish from\n    // checkout, we always set 'meteor-tool' as the tool. We don't include the\n    // tool in the packages list.\n    relConf.tool=\"meteor-tool@\" + relConf.packages[\"meteor-tool\"];\n    delete relConf.packages[\"meteor-tool\"];\n  }\n\n  main.captureAndExit(\n    \"=> Errors while publishing release:\",\n    \"publishing release\",\n    function () {\n      // Create the new track, if we have been told to.\n      if (options['create-track']) {\n        // XXX maybe this job title should be left on the screen too?  some sort\n        // of enterJob/progress option that lets you do that?\n        buildmessage.enterJob(\"creating a new release track\", function () {\n          packageClient.callPackageServerBM(\n            conn, 'createReleaseTrack', { name: relConf.track } );\n        });\n        if (buildmessage.jobHasMessages()) {\n          return;\n        }\n      }\n\n      buildmessage.enterJob(\"creating a new release version\", function () {\n        var record = {\n          track: relConf.track,\n          version: relConf.version,\n          orderKey: relConf.orderKey,\n          description: relConf.description,\n          recommended: !!relConf.recommended,\n          tool: relConf.tool,\n          packages: relConf.packages\n        };\n\n        if (relConf.patchFrom) {\n          packageClient.callPackageServerBM(\n            conn, 'createPatchReleaseVersion', record, relConf.patchFrom);\n        } else {\n          packageClient.callPackageServerBM(\n            conn, 'createReleaseVersion', record);\n        }\n      });\n    }\n  );\n\n  // Learn about it.\n  refreshOfficialCatalogOrDie();\n  Console.info(\"Done creating \" + relConf.track  + \"@\" + relConf.version + \"!\");\n  Console.info();\n\n  if (options['from-checkout']) {\n    // XXX maybe should discourage publishing if git status says we're dirty?\n    var gitTag = \"release/\" + relConf.track  + \"@\" + relConf.version;\n    if (config.getPackageServerFilePrefix() !== 'packages') {\n      // Only make a git tag if we're on the default branch.\n      Console.info(\"Skipping git tag: not using the main package server.\");\n    } else if (gitTag.indexOf(':') !== -1) {\n      // XXX could run `git check-ref-format --allow-onelevel $gitTag` like we\n      //     used to, instead of this simple check\n      // XXX could convert : to / ?\n      Console.info(\"Skipping git tag: bad format for git.\");\n    } else {\n      Console.info(\"Creating git tag \" + gitTag);\n      utils.runGitInCheckout('tag', gitTag);\n      var fail = false;\n      try {\n        Console.info(\n          \"Pushing git tag (this should fail if you are not from MDG)\");\n        utils.runGitInCheckout('push', 'git@github.com:meteor/meteor.git',\n                             'refs/tags/' + gitTag);\n      } catch (err) {\n        Console.error(\n          \"Failed to push git tag. Please push git tag manually!\");\n        fail = true;\n      }\n    }\n\n    // We need to warn the user that we didn't publish some of their\n    // packages. Unlike publish, this is advanced functionality, so the user\n    // should be familiar with the concept.\n    if (! _.isEmpty(unfinishedBuilds)) {\n      Console.warn();\n      Console.labelWarn(\n        \"Some packages contain binary dependencies.\");\n      Console.warn(\n          \"Builds have not been published for the following packages:\");\n      _.each(unfinishedBuilds, function (version, name) {\n        Console.warn(name + \"@\" + version);\n      });\n      // Note: we don't actually enforce the proper build machine thing. You\n      // can't use publish-for-arch for meteor-tool, for example, you need to\n      // use publish --existing-version and to do it from checkout. Setting that\n      // up on a build machine for a one-off experimental release could be a\n      // pain. In that case, I guess, you can just run publish\n      // --existing-version: presumably you don't care about compatibility\n      // etc. If it is an official release, you ought to use a build machine\n      // though.\n      Console.warn(\n        \"Please publish the builds separately, from a proper build machine.\");\n    }\n  }\n\n  return 0;\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// list\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'list',\n  requiresApp: true,\n  options: {\n    'allow-incompatible-update': { type: Boolean }\n  },\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: true })\n}, function (options) {\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: options.appDir,\n    allowIncompatibleUpdate: options['allow-incompatible-update']\n  });\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    projectContext.prepareProjectForBuild();\n  });\n  // No need to display the PackageMapDelta here, since we're about to list all\n  // of the packages anyway!\n\n\n  var items = [];\n  var newVersionsAvailable = false;\n  var anyBuiltLocally = false;\n\n  // Iterate over packages that are used directly by this app (not indirect\n  // dependencies).\n  projectContext.projectConstraintsFile.eachConstraint(function (constraint) {\n    var packageName = constraint.package;\n\n    // Skip isobuild:* pseudo-packages.\n    if (compiler.isIsobuildFeaturePackage(packageName)) {\n      return;\n    }\n\n    var mapInfo = projectContext.packageMap.getInfo(packageName);\n    if (! mapInfo) {\n      throw Error(\"no version for used package \" + packageName);\n    }\n    var versionRecord = projectContext.projectCatalog.getVersion(\n      packageName, mapInfo.version);\n    if (! versionRecord) {\n      throw Error(\"no version record for \" + packageName + \"@\" +\n                  mapInfo.version);\n    }\n\n    var versionAddendum = \" \";\n    if (mapInfo.kind === 'local') {\n      versionAddendum = \"+\";\n      anyBuiltLocally = true;\n    } else if (mapInfo.kind === 'versioned') {\n      if (getNewerVersion(packageName, mapInfo.version, catalog.official)) {\n        versionAddendum = \"*\";\n        newVersionsAvailable = true;\n      }\n    } else {\n      throw Error(\"unknown kind \" + mapInfo.kind);\n    }\n    var description = mapInfo.version + versionAddendum;\n    if (versionRecord.description) {\n      description += \" \" + versionRecord.description;\n    }\n    items.push({ name: packageName, description: description });\n  });\n\n  // Append extra information about special packages such as Cordova plugins\n  // to the list.\n  _.each(\n    projectContext.cordovaPluginsFile.getPluginVersions(),\n    function (version, name) {\n      items.push({ name: 'cordova:' + name, description: version });\n    }\n  );\n\n  utils.printPackageList(items);\n\n  if (newVersionsAvailable) {\n    Console.info();\n    Console.info(\n      \"New versions of these packages are available! Run\",\n      Console.command(\"'meteor update'\"), \"to try to update those\",\n      \"packages to their latest versions. If your packages cannot be\",\n      \"updated further, try typing\",\n      Console.command(\"`meteor add <package>@<newVersion>`\"),\n      \"to see more information.\",\n      Console.options({ bulletPoint: \"* \" }));\n  }\n  if (anyBuiltLocally) {\n    Console.info();\n    Console.info(\n      \"These packages are built locally from source.\",\n      Console.options({ bulletPoint: \"+ \" }));\n  }\n  return 0;\n});\n\nvar getNewerVersion = function (packageName, curVersion, whichCatalog) {\n  // Check to see if there are later versions available, returning the\n  // latest version if there are.\n  //\n  // If we are not using an rc for this package, then we are not going to\n  // update to an rc. But if we are using a pre-release version, then we\n  // care about other pre-release versions, and might want to update to a\n  // newer one.\n  //\n  // We depend on the fact that `curVersion` is in the database to know\n  // that we'll find something when we look in the catalog.\n  var latest;\n  if (/-/.test(curVersion)) {\n    latest = whichCatalog.getLatestVersion(packageName);\n  } else {\n    latest = whichCatalog.getLatestMainlineVersion(packageName);\n  }\n  if (! latest) {\n    // Shouldn't happen: we've chosen a published version of this package,\n    // so there has to be at least one in our database!\n    throw Error(\"no latest record for package where we have a version? \" +\n                packageName);\n  }\n\n  var latestVersion = latest.version;\n  if (curVersion !== latestVersion &&\n      // If we're currently running a prerelease, \"latest\" may be older than\n      // what we're at, so don't tell us we're outdated!\n      packageVersionParser.lessThan(curVersion, latestVersion)) {\n    return latestVersion;\n  } else {\n    return null;\n  }\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// update\n///////////////////////////////////////////////////////////////////////////////\n\n// Returns 0 if the operation went OK -- either we updated to a new release, or\n// decided not to with good reason. Returns something other than 0, if it is not\n// safe to proceed (ex: our release track is fundamentally unsafe or there is\n// weird catalog corruption).\nvar maybeUpdateRelease = function (options) {\n  // We are only updating packages, so we are not updating the release.\n  if (options[\"packages-only\"]) {\n     return 0;\n  }\n\n  // We are running from checkout, so we are not updating the release.\n  if (release.current && release.current.isCheckout()) {\n    Console.error(\n      \"You are running Meteor from a checkout, so we cannot update\",\n      \"the Meteor release. Checking to see if we can update your packages.\");\n    return 0;\n  }\n\n  // Looks like we are going to have to update the release. First, let's figure\n  // out the release track we'll end up on --- either because it's\n  // the explicitly specified (with --release) track; or because we didn't\n  // specify a release and it's the app's current release (if we're in an app\n  // dir), since non-forced updates don't change the track.\n\n  // XXX better error checking on release.current.name\n  // XXX add a method to release.current.\n  var releaseTrack = release.current ?\n        release.current.getReleaseTrack() : catalog.DEFAULT_TRACK;\n\n  // Unless --release was passed (in which case we ought to already have\n  // springboarded to that release), go get the latest release and switch to\n  // it. (We already know what the latest release is because we refreshed the\n  // catalog above.)  Note that after springboarding, we will hit this again.\n  // However, the override that's done by SpringboardToLatestRelease also sets\n  // release.forced (although it does not set release.explicit), so we won't\n  // double-springboard.  (We might miss an super recently published release,\n  // but that's probably OK.)\n  if (! release.forced) {\n    var latestRelease = release.latestKnown(releaseTrack);\n\n    // Are we on some track without ANY recommended releases at all,\n    // and the user ran 'meteor update' without specifying a release? We\n    // really can't do much here.\n    if (!latestRelease) {\n      Console.error(\n        \"There are no recommended releases on release track \" +\n          releaseTrack + \".\");\n      return 1;\n    }\n\n    if (release.current && ! release.current.isRecommended() &&\n        options.appDir && ! options.patch) {\n      var releaseVersion = release.current.getReleaseVersion();\n      var newerRecommendedReleases = getLaterReleaseVersions(\n        releaseTrack, releaseVersion);\n      if (!newerRecommendedReleases.length) {\n        // When running 'meteor update' without --release in an app,\n        // using a release that is not recommended and is newer than\n        // any recommended release, don't springboard backwards to\n        // an older, recommended release.  Don't update Meteor, or\n        // the app's release.  This makes it possible to type `meteor update`\n        // with no arguments from a new RC of Meteor, without performing\n        // the update (and subsequent constraint-solving, etc.) using\n        // the old tool.\n        //\n        // We'll still springboard forwards out of an RC, just not backwards.\n        // There still has a possibility of already on the latest.\n        if (release.current.name === latestRelease) {\n          Console.info(\"Already on the latest recommended release \" +\n                      \"(\" + latestRelease + \"). Not updating.\");\n        } else {\n          Console.info(\"Not updating the release, because this app is at a \" +\n                      \"newer release (\" + release.current.name + \") than \" +\n                      \"the latest recommended release \" +\n                      \"(\" + latestRelease + \").\");\n        }\n        return 0;\n      }\n    }\n\n    if (! release.current || release.current.name !== latestRelease) {\n      // The user asked for the latest release (well, they \"asked for it\" by not\n      // passing --release). We're not currently running the latest release on\n      // this track (we may have even just learned about it). #UpdateSpringboard\n      throw new main.SpringboardToLatestRelease(releaseTrack);\n    }\n  }\n\n  // At this point we should have a release. (If we didn't to start\n  // with, #UpdateSpringboard fixed that.) And it can't be a checkout,\n  // because we checked for that at the very beginning.\n  if (! release.current || ! release.current.isProperRelease()) {\n    throw new Error(\"don't have a proper release?\");\n  }\n\n  // If we're not in an app, then we're basically done. The only thing left to\n  // do is print out some messages explaining what happened (and advising the\n  // user to run update from an app).\n  if (! options.appDir) {\n    if (release.forced) {\n      // We get here if:\n      // 1) the user ran 'meteor update' and we found a new version\n      // 2) the user ran 'meteor update --release xyz' (regardless of\n      //    whether we found a new release)\n      //\n      // In case (1), we downloaded and installed the update and then\n      // we springboarded (at #UpdateSpringboard above), causing\n      // $METEOR_SPRINGBOARD_RELEASE to be true.\n      // XXX probably should have a better interface than looking directly\n      //     at the env var here\n      //\n      // In case (2), we downloaded, installed, and springboarded to\n      // the requested release in the initialization code, before the\n      // command even ran. They could equivalently have run 'meteor\n      // help --release xyz'.\n      Console.info(\n        \"Installed. Run\",\n        Console.command(\n          \"'meteor update --release \" +\n            release.current.getDisplayName({ noPrefix: true }) + \"'\"),\n        \"inside of a particular project directory to update that project to\",\n        release.current.getDisplayName() + \".\");\n    } else {\n      // We get here if the user ran 'meteor update' and we didn't\n      // find a new version.\n      Console.info(\n        \"The latest version of Meteor, \" + release.current.getReleaseVersion() +\n        \", is already installed on this computer. Run \" +\n        Console.command(\"'meteor update'\") + \" inside of a particular \" +\n        \"project directory to update that project to \" +\n        release.current.getDisplayName());\n    }\n    return 0;\n  }\n\n  // Otherwise, we have to upgrade the app too, if the release changed.  Read in\n  // the project metadata files.  (Don't resolve constraints yet --- if the\n  // current constraints don't resolve but we can update to a place where they\n  // do, that's great!)\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: options.appDir,\n    alwaysWritePackageMap: true,\n    allowIncompatibleUpdate: true // disregard `.meteor/versions` if necessary\n  });\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    projectContext.readProjectMetadata();\n  });\n\n  if (projectContext.releaseFile.fullReleaseName === release.current.name) {\n    // release.explicit here means that the user actually typed `--release FOO`,\n    // so they weren't trying to go to the latest release. (This is different\n    // from release.forced, which might be set due to the\n    // SpringboardToLatestRelease above.)\n    var maybeTheLatestRelease = release.explicit ? \"\" : \", the latest release\";\n    Console.info(\n      \"This project is already at \" +\n      release.current.getDisplayName() + maybeTheLatestRelease + \".\");\n    return 0;\n  }\n\n  // XXX did we have to change some package versions? we should probably\n  //     mention that fact.\n  // XXX error handling.\n\n  // Figuring out which release to use to update the app is slightly more\n  // complicated, because we have to run the constraint solver. So, we need to\n  // try multiple releases, defined by the various options passed in.\n  var releaseVersionsToTry;\n  if (options.patch) {\n    // Can't make a patch update if you are not running from a current\n    // release. In fact, you are doing something wrong, so we should tell you\n    // to stop.\n    if (! projectContext.releaseFile.normalReleaseSpecified()) {\n      Console.error(\n        \"Cannot patch update unless a release is set.\");\n      return 1;\n    }\n    var record = catalog.official.getReleaseVersion(\n      projectContext.releaseFile.releaseTrack,\n      projectContext.releaseFile.releaseVersion);\n    if (!record) {\n      Console.error(\n        \"Cannot update to a patch release from an old release.\");\n      return 1;\n    }\n    var updateTo = record.patchReleaseVersion;\n    if (!updateTo) {\n      Console.error(\n        \"You are at the latest patch version.\");\n      return 0;\n    }\n    var patchRecord = catalog.official.getReleaseVersion(\n      projectContext.releaseFile.releaseTrack, updateTo);\n    // It looks like you are not at the latest patch version,\n    // technically. But, in practice, we cannot update you to the latest patch\n    // version because something went wrong. For example, we can't find the\n    // record for your patch version (probably some sync\n    // failure). Alternatively, maybe we put out a patch release and found a\n    // bug in it -- since we tell you to always run update --patch, we should\n    // not try to patch you to an unfriendly release. So, either way, as far\n    // as we are concerned you are at the 'latest patch version'\n    if (!patchRecord || !patchRecord.recommended ) {\n      Console.error(\"You are at the latest patch version.\");\n      return 0;\n    }\n    // Great, we found a patch version. You can only have one latest patch for\n    // a string of releases, so there is just one release to try.\n    releaseVersionsToTry = [updateTo];\n  } else if (release.explicit) {\n    // You have explicitly specified a release, and we have springboarded to\n    // it. So, we will use that release to update you to itself, if we can.\n    releaseVersionsToTry = [release.current.getReleaseVersion()];\n  } else {\n    // We are not doing a patch update, or a specific release update, so we need\n    // to try all recommended releases on our track, whose order key is greater\n    // than the app's.\n    releaseVersionsToTry = getLaterReleaseVersions(\n      projectContext.releaseFile.releaseTrack,\n      projectContext.releaseFile.releaseVersion);\n\n    if (! releaseVersionsToTry.length) {\n      // We could not find any releases newer than the one that we are on, on\n      // that track, so we are done.\n      Console.info(\n        \"This project is already at \" +\n        Console.noWrap(projectContext.releaseFile.displayReleaseName) +\n        \", which is newer than the latest release.\");\n      return 0;\n    }\n  }\n\n  var didPrintMessages = false;\n  var solutionReleaseVersion = _.find(releaseVersionsToTry, function (versionToTry) {\n    var releaseRecord = catalog.official.getReleaseVersion(\n      releaseTrack, versionToTry);\n    if (!releaseRecord) {\n      throw Error(\"missing release record?\");\n    }\n\n    // Reset the project context and pretend we're using the potential release.\n    projectContext.reset({ releaseForConstraints: releaseRecord });\n    var messages = buildmessage.capture(function () {\n      projectContext.resolveConstraints();\n    });\n    if (messages.hasMessages()) {\n      // To avoid overloading the user, we only print messages for the first\n      // release version we try (which should be the latest)\n      if (!didPrintMessages) {\n        Console.info(\n          \"Update to release\", releaseTrack + \"@\" + versionToTry,\n          \"is impossible:\");\n        Console.info(messages.formatMessages());\n        didPrintMessages = true;\n      }\n      // Nope, this release didn't work.\n      return false;\n    }\n\n    // Yay, it worked!\n    return true;\n  });\n\n  var newerAvailable = false;\n  if (! solutionReleaseVersion) {\n    Console.info(\n      \"This project is at the latest release which is compatible with your \" +\n      \"current package constraints.\");\n    return 0;\n  } else if (solutionReleaseVersion !== releaseVersionsToTry[0]) {\n    newerAvailable = true;\n  }\n\n  var solutionReleaseName = releaseTrack + '@' + solutionReleaseVersion;\n\n  // We could at this point springboard to solutionRelease (which is no newer\n  // than the release we are currently running), but there's no super-clear\n  // advantage to this yet. The main reason might be if we decide to delete some\n  // backward-compatibility code which knows how to deal with an older release,\n  // but if we actually do that, we can change this code to add the extra\n  // springboard at that time.\n  var upgraders = require('../upgraders.js');\n  var upgradersToRun = upgraders.upgradersToRun(projectContext);\n\n  // Download and build packages and write the new versions to .meteor/versions.\n  // XXX It's a little weird that we do a full preparation for build\n  //     (downloading packages, building packages, etc) when we might be about\n  //     to upgrade packages and have to do it again. Maybe we shouldn't? Note\n  //     that if we change this, that changes the upgraders interface, which\n  //     expects a projectContext that is fully prepared for build.\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    projectContext.prepareProjectForBuild();\n  });\n  // Write the new release to .meteor/release.\n  projectContext.releaseFile.write(solutionReleaseName);\n  projectContext.packageMapDelta.displayOnConsole({\n    title: (\"Changes to your project's package version selections from \" +\n            \"updating the release:\")\n  });\n\n  Console.info(files.pathBasename(options.appDir) + \": updated to \" +\n               projectContext.releaseFile.displayReleaseName + \".\");\n  if (newerAvailable) {\n    Console.info(\n      \"(Newer releases are available but are not compatible with your \" +\n      \"current package constraints.)\");\n  }\n\n  // Now run the upgraders.\n  // XXX should we also run upgraders on other random commands, in case there\n  // was a crash after changing .meteor/release but before running them?\n  _.each(upgradersToRun, function (upgrader) {\n    upgraders.runUpgrader(projectContext, upgrader);\n    projectContext.finishedUpgraders.appendUpgraders([upgrader]);\n  });\n\n  // We are done, and we should pass the release that we upgraded to, to the\n  // user.\n  return 0;\n};\n\nfunction getLaterReleaseVersions(releaseTrack, releaseVersion) {\n  var releaseInfo = catalog.official.getReleaseVersion(\n    releaseTrack, releaseVersion);\n  var orderKey = (releaseInfo && releaseInfo.orderKey) || null;\n\n  return catalog.official.getSortedRecommendedReleaseVersions(\n    releaseTrack, orderKey);\n}\n\nmain.registerCommand({\n  name: 'update',\n  options: {\n    patch: { type: Boolean },\n    \"packages-only\": { type: Boolean },\n    \"allow-incompatible-update\": { type: Boolean }\n  },\n  // We have to be able to work without a release, since 'meteor\n  // update' is how you fix apps that don't have a release.\n  requiresRelease: false,\n  minArgs: 0,\n  maxArgs: Infinity,\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: true })\n}, function (options) {\n  // If you are specifying packages individually, you probably don't want to\n  // update the release.\n  if (options.args.length > 0) {\n    // In the case that user specified the package but not in a app.\n    if (! options.appDir) {\n      Console.error(\"You're not in a Meteor project directory.\");\n      return 1;\n    }\n    options[\"packages-only\"] = true;\n  }\n\n  // Some basic checks to make sure that this command is being used correctly.\n  if (options[\"packages-only\"] && options[\"patch\"]) {\n    Console.error(\n      \"The --patch option only applies to the release, not packages.\");\n    return 1;\n  }\n\n  if (release.explicit && options[\"patch\"]) {\n    Console.error(\"You cannot patch update to a specific release.\");\n    return 1;\n  }\n\n  var releaseUpdateStatus = maybeUpdateRelease(options);\n  // If we encountered an error and cannot proceed, return.\n  if (releaseUpdateStatus !== 0) {\n    return releaseUpdateStatus;\n  }\n\n  // The only thing left to do is update packages, and we don't update packages\n  // if we are making a patch update, updating specifically with a --release, or\n  // running outside a package directory. So, we are done, return.\n  if (options['patch'] || release.explicit || !options.appDir) {\n    return 0;\n  }\n\n  // Start a new project context and read in the project's release and other\n  // metadata. (We also want to make sure that we write the package map when\n  // we're done even if we're not on the matching release!)\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: options.appDir,\n    alwaysWritePackageMap: true,\n    allowIncompatibleUpdate: options[\"allow-incompatible-update\"]\n  });\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    projectContext.readProjectMetadata();\n  });\n\n  // If no packages have been specified, then we will send in a request to\n  // update all direct dependencies. If a specific list of packages has been\n  // specified, then only upgrade those.\n  var upgradePackageNames = [];\n  // If no packages have been specified (`meteor update` with no positional\n  // args), take patches to indirect dependencies.\n  var upgradeIndirectDepPatchVersions = false;\n  if (options.args.length === 0) {\n    projectContext.projectConstraintsFile.eachConstraint(function (constraint) {\n      if (! compiler.isIsobuildFeaturePackage(constraint.package)) {\n        upgradePackageNames.push(constraint.package);\n      }\n    });\n    upgradeIndirectDepPatchVersions = true;\n  } else {\n    upgradePackageNames = options.args;\n  }\n  // We want to use the project's release for constraints even if we are\n  // currently running a newer release (eg if we ran 'meteor update --patch' and\n  // updated to an older patch release).  (If the project has release 'none'\n  // because this is just 'updating packages', this can be null. Also, if we're\n  // running from a checkout this should be null even if the file doesn't say\n  // 'none'.)\n  var releaseRecordForConstraints = null;\n  if (!files.inCheckout()\n      && projectContext.releaseFile.normalReleaseSpecified()) {\n    releaseRecordForConstraints = catalog.official.getReleaseVersion(\n      projectContext.releaseFile.releaseTrack,\n      projectContext.releaseFile.releaseVersion);\n    if (! releaseRecordForConstraints) {\n      throw Error(\"unknown release \" +\n                  projectContext.releaseFile.displayReleaseName);\n    }\n  }\n\n  // Try to resolve constraints, allowing the given packages to be upgraded.\n  projectContext.reset({\n    releaseForConstraints: releaseRecordForConstraints,\n    upgradePackageNames: upgradePackageNames,\n    upgradeIndirectDepPatchVersions: upgradeIndirectDepPatchVersions\n  });\n  main.captureAndExit(\n    \"=> Errors while upgrading packages:\", \"upgrading packages\", function () {\n      projectContext.resolveConstraints();\n      if (buildmessage.jobHasMessages()) {\n        return;\n      }\n\n      // If the user explicitly mentioned some packages to upgrade, they must\n      // actually end up in our solution!\n      _.each(options.args, function (packageName) {\n        if (! projectContext.packageMap.getInfo(packageName)) {\n          buildmessage.error(packageName + ': package is not in the project');\n        }\n      });\n      if (buildmessage.jobHasMessages()) {\n        return;\n      }\n\n      // Finish preparing the project.\n      projectContext.prepareProjectForBuild();\n    }\n  );\n\n  if (projectContext.packageMapDelta.hasChanges()) {\n    projectContext.packageMapDelta.displayOnConsole({\n      title: (\"Changes to your project's package version selections from \" +\n              \"updating package versions:\")\n    });\n  } else if (options.args.length) {\n    Console.info(\n      \"The specified packages are at their latest compatible versions.\");\n  } else {\n    Console.info(\n      \"Your top-level dependencies are at their latest compatible versions.\");\n  }\n\n  if (!options.args.length) {\n    // Generate and print info about what is NOT at the latest version.\n\n    var topLevelPkgSet = {}; // direct dependencies (rather than indirect)\n    projectContext.projectConstraintsFile.eachConstraint(function (constraint) {\n      topLevelPkgSet[constraint.package] = true;\n    });\n\n    var releaseConstrainedPkgSet = {}; // pinned core packages (to skip)\n    // check releaseRecordForConstraints is not null, e.g. possible\n    // when running meteor from checkout\n    if (releaseRecordForConstraints) {\n      _.each(releaseRecordForConstraints.packages, function (v, packageName) {\n        releaseConstrainedPkgSet[packageName] = true;\n      });\n    }\n\n    var nonlatestDirectDeps = [];\n    var nonlatestIndirectDeps = [];\n    projectContext.packageMap.eachPackage(function (name, info) {\n      if (_.has(releaseConstrainedPkgSet, name)) {\n        return;\n      }\n      var selectedVersion = info.version;\n      var catalog = projectContext.projectCatalog;\n      var latestVersion = getNewerVersion(name, selectedVersion, catalog);\n      if (latestVersion) {\n        var rec = { name: name, selectedVersion: selectedVersion,\n                    latestVersion: latestVersion };\n        if (_.has(topLevelPkgSet, name)) {\n          nonlatestDirectDeps.push(rec);\n        } else {\n          nonlatestIndirectDeps.push(rec);\n        }\n      }\n    });\n    var printItem = function (rec) {\n      Console.info(\" * \" + rec.name + \" \" + rec.selectedVersion +\n                   \" (\" + rec.latestVersion + \" is available)\");\n    };\n    if (nonlatestDirectDeps.length) {\n      Console.info(\"\\nThe following top-level dependencies were not updated \" +\n                   \"to the very latest version available:\");\n      _.each(nonlatestDirectDeps, printItem);\n    }\n    if (nonlatestIndirectDeps.length) {\n      Console.info(\"\\nNewer versions of the following indirect dependencies\" +\n                   \" are available:\");\n      _.each(nonlatestIndirectDeps, printItem);\n      Console.info(\n        \"To update one or more of these packages, pass their names to \" +\n          \"`meteor update`.\");\n    }\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// admin run-upgrader\n///////////////////////////////////////////////////////////////////////////////\n\n// For testing upgraders during development.\nmain.registerCommand({\n  name: 'admin run-upgrader',\n  hidden: true,\n  minArgs: 1,\n  maxArgs: 1,\n  requiresApp: true,\n  catalogRefresh: new catalog.Refresh.Never(),\n  'allow-incompatible-update': { type: Boolean }\n}, function (options) {\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: options.appDir,\n    allowIncompatibleUpdate: options['allow-incompatible-update']\n  });\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    projectContext.prepareProjectForBuild();\n  });\n  projectContext.packageMapDelta.displayOnConsole();\n\n  var upgrader = options.args[0];\n\n  var upgraders = require('../upgraders.js');\n  console.log(\"%s: running upgrader %s.\",\n              files.pathBasename(options.appDir), upgrader);\n  upgraders.runUpgrader(projectContext, upgrader);\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// admin run-background-updater\n///////////////////////////////////////////////////////////////////////////////\n\n// For testing the background updater during development.\nmain.registerCommand({\n  name: 'admin run-background-updater',\n  hidden: true,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  updater.tryToDownloadUpdate({\n    showBanner: true,\n    printErrors: true\n  });\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// admin wipe-all-packages\n///////////////////////////////////////////////////////////////////////////////\n\n// For testing wipeAllPackages during development\nmain.registerCommand({\n  name: 'admin wipe-all-packages',\n  hidden: true,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  tropohouse.default.wipeAllPackages();\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// admin check-package-versions\n///////////////////////////////////////////////////////////////////////////////\n\n// Run before publish-release --from-checkout to make sure that all of our\n// version numbers are up to date\nmain.registerCommand({\n  name: 'admin check-package-versions',\n  hidden: true,\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: false })\n}, function (options) {\n  if (!files.inCheckout()) {\n    Console.error(\"Must run from checkout.\");\n    return 1;\n  };\n\n  // Set up a temporary project context and build everything.\n  var tempProjectDir = files.mkdtemp('meteor-release-build');\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: tempProjectDir,  // won't have a packages dir, that's OK\n    // seriously, we only want checkout packages\n    ignorePackageDirsEnvVar: true,\n    // When we publish, we should always include web.cordova unibuilds, even\n    // though this temporary directory does not have any cordova platforms\n    forceIncludeCordovaUnibuild: true\n  });\n\n  // Read metadata and initialize catalog.\n  main.captureAndExit(\"=> Errors while building for release:\", function () {\n    projectContext.initializeCatalog();\n  });\n\n  var allPackages = projectContext.localCatalog.getAllNonTestPackageNames();\n\n  Console.info(\"Listing packages where the checkout version doesn't match the\",\n    \"latest version on the package server.\");\n\n  _.each(allPackages, function (packageName) {\n    var checkoutVersion = projectContext.localCatalog.getLatestVersion(packageName).version;\n    var remoteLatestVersion = catalog.official.getLatestVersion(packageName).version;\n\n    if (checkoutVersion !== remoteLatestVersion) {\n      Console.info(packageName, checkoutVersion, remoteLatestVersion);\n    }\n  });\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// add\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'add',\n  options: {\n    \"allow-incompatible-update\": { type: Boolean }\n  },\n  minArgs: 1,\n  maxArgs: Infinity,\n  requiresApp: true,\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: true })\n}, function (options) {\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: options.appDir,\n    allowIncompatibleUpdate: options[\"allow-incompatible-update\"]\n  });\n\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    // We're just reading metadata here --- we're not going to resolve\n    // constraints until after we've made our changes.\n    projectContext.initializeCatalog();\n  });\n\n  let exitCode = 0;\n\n  // Split arguments into Cordova plugins and packages\n  const { plugins: pluginsToAdd, packages: packagesToAdd } =\n    cordova.splitPluginsAndPackages(options.args);\n\n  if (!_.isEmpty(pluginsToAdd)) {\n    let plugins = projectContext.cordovaPluginsFile.getPluginVersions();\n    let changed = false;\n\n    for (target of pluginsToAdd) {\n      let [id, version] = target.split('@');\n\n      const newId = cordova.newPluginId(id);\n\n      if (!(version && utils.isValidVersion(version, {forCordova: true}))) {\n        Console.error(`${id}: Meteor requires either an exact version \\\n(e.g. ${id}@1.0.0), a Git URL with a SHA reference, or a local path.`);\n        exitCode = 1;\n      } else if (newId) {\n        plugins[newId] = version;\n        Console.info(`Added Cordova plugin ${newId}@${version} \\\n(plugin has been renamed as part of moving to npm).`);\n        changed = true;\n      } else {\n        plugins[id] = version;\n        Console.info(`Added Cordova plugin ${id}@${version}.`);\n        changed = true;\n      }\n    }\n\n    changed && projectContext.cordovaPluginsFile.write(plugins);\n  }\n\n  if (_.isEmpty(packagesToAdd)) {\n    return exitCode;\n  }\n\n  // Messages that we should print if we make any changes, but that don't count\n  // as errors.\n  var infoMessages = [];\n  var constraintsToAdd = [];\n  // For every package name specified, add it to our list of package\n  // constraints. Don't run the constraint solver until you have added all of\n  // them -- add should be an atomic operation regardless of the package\n  // order.\n  var messages = buildmessage.capture(function () {\n    _.each(packagesToAdd, function (packageReq) {\n      buildmessage.enterJob(\"adding package \" + packageReq, function () {\n        var constraint = utils.parsePackageConstraint(packageReq, {\n          useBuildmessage: true\n        });\n        if (buildmessage.jobHasMessages()) {\n          return;\n        }\n\n        // It's OK to make errors based on looking at the catalog, because this\n        // is a OnceAtStart command.\n        var packageRecord = projectContext.projectCatalog.getPackage(\n          constraint.package);\n        if (! packageRecord) {\n          buildmessage.error(\"no such package\");\n          return;\n        }\n\n        _.each(constraint.versionConstraint.alternatives, function (subConstr) {\n          if (subConstr.versionString === null) {\n            return;\n          }\n          // Figure out if this version exists either in the official catalog or\n          // the local catalog. (This isn't the same as using the combined\n          // catalog, since it's OK to type \"meteor add foo@1.0.0\" if the local\n          // package is 1.1.0 as long as 1.0.0 exists.)\n          var versionRecord = projectContext.localCatalog.getVersion(\n            constraint.package, subConstr.versionString);\n          if (! versionRecord) {\n            // XXX #2846 here's an example of something that might require a\n            // refresh\n            versionRecord = catalog.official.getVersion(\n              constraint.package, subConstr.versionString);\n          }\n          if (! versionRecord) {\n            buildmessage.error(\"no such version \" + constraint.package + \"@\" +\n                               subConstr.versionString);\n          }\n        });\n        if (buildmessage.jobHasMessages()) {\n          return;\n        }\n\n        var current = projectContext.projectConstraintsFile.getConstraint(\n          constraint.package);\n\n        // Check that the constraint is new. If we are already using the package\n        // at the same constraint in the app, we will log an info message later\n        // (if there are no other errors), but don't fail. Rejecting the entire\n        // command because a part of it is a no-op is confusing.\n        if (! current) {\n          constraintsToAdd.push(constraint);\n        } else if (! current.constraintString &&\n                   ! constraint.constraintString) {\n          infoMessages.push(\n            constraint.package +\n              \" without a version constraint has already been added.\");\n        } else if (current.constraintString === constraint.constraintString) {\n          infoMessages.push(\n            constraint.package + \" with version constraint \" +\n              constraint.constraintString + \" has already been added.\");\n        } else {\n          // We are changing an existing constraint.\n          if (current.constraintString) {\n            infoMessages.push(\n              \"Currently using \" + constraint.package +\n                \" with version constraint \" + current.constraintString + \".\");\n          } else {\n            infoMessages.push(\n              \"Currently using \" +  constraint.package +\n                \" without any version constraint.\");\n          }\n          if (constraint.constraintString) {\n            infoMessages.push(\"The version constraint will be changed to \" +\n                              constraint.constraintString + \".\");\n          } else {\n            infoMessages.push(\"The version constraint will be removed.\");\n          }\n          constraintsToAdd.push(constraint);\n        }\n      });\n    });\n  });\n  if (messages.hasMessages()) {\n    Console.arrowError(\"Errors while parsing arguments:\", 1);\n    Console.printMessages(messages);\n    catalogUtils.explainIfRefreshFailed();  // this is why we're not using captureAndExit\n    return 1;\n  }\n\n  projectContext.projectConstraintsFile.addConstraints(constraintsToAdd);\n\n  // Run the constraint solver, download packages, etc.\n  messages = buildmessage.capture(function () {\n    projectContext.prepareProjectForBuild();\n  });\n  if (messages.hasMessages()) {\n    Console.arrowError(\"Errors while adding packages:\", 1);\n    Console.printMessages(messages);\n    catalogUtils.explainIfRefreshFailed();  // this is why we're not using captureAndExit\n    return 1;\n  }\n\n  _.each(infoMessages, function (message) {\n    Console.info(message);\n  });\n  projectContext.packageMapDelta.displayOnConsole();\n\n  // Show descriptions of directly added packages.\n  Console.info();\n  _.each(constraintsToAdd, function (constraint) {\n    var version = projectContext.packageMap.getInfo(constraint.package).version;\n    var versionRecord = projectContext.projectCatalog.getVersion(\n      constraint.package, version);\n    Console.info(\n      constraint.package +\n        (versionRecord.description ? (\": \" + versionRecord.description) : \"\"));\n  });\n\n  return exitCode;\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// remove\n///////////////////////////////////////////////////////////////////////////////\nmain.registerCommand({\n  name: 'remove',\n  options: {\n    \"allow-incompatible-update\": { type: Boolean }\n  },\n  minArgs: 1,\n  maxArgs: Infinity,\n  requiresApp: true,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: options.appDir,\n    allowIncompatibleUpdate: options[\"allow-incompatible-update\"]\n  });\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    // We're just reading metadata here --- we're not going to resolve\n    // constraints until after we've made our changes.\n    projectContext.readProjectMetadata();\n  });\n\n  let exitCode = 0;\n\n  // Split arguments into Cordova plugins and packages\n  const { plugins: pluginsToRemove, packages }  =\n    cordova.splitPluginsAndPackages(options.args);\n\n  if (!_.isEmpty(pluginsToRemove)) {\n    let plugins = projectContext.cordovaPluginsFile.getPluginVersions();\n    let changed = false;\n\n    for (id of pluginsToRemove) {\n      const newId = cordova.newPluginId(id);\n\n      if (/@/.test(id)) {\n        Console.error(`${id}: do not specify version constraints.`);\n        exitCode = 1;\n      } else if (_.has(plugins, id)) {\n        delete plugins[id];\n        Console.info(`Removed Cordova plugin ${id}.`);\n        changed = true;\n      } else if (newId && _.has(plugins, newId)) {\n        delete plugins[newId];\n        Console.info(`Removed Cordova plugin ${newId} \\\n(plugin has been renamed as part of moving to npm).`);\n        changed = true;\n      } else {\n        Console.error(`Cordova plugin ${id} is not in this project.`);\n        exitCode = 1;\n      }\n    }\n\n    changed && projectContext.cordovaPluginsFile.write(plugins);\n  }\n\n  if (_.isEmpty(packages)) {\n    return exitCode;\n  }\n\n  // For each package name specified, check if we already have it and warn the\n  // user. Because removing each package is a completely atomic operation that\n  // has no chance of failure, this is just a warning message, it doesn't cause\n  // us to stop.\n  let packagesToRemove = [];\n  _.each(packages, function (packageName) {\n    if (/@/.test(packageName)) {\n      Console.error(packageName + \": do not specify version constraints.\");\n      exitCode = 1;\n    } else if (! projectContext.projectConstraintsFile.getConstraint(packageName)) {\n      // Check that we are using the package. We don't check if the package\n      // exists. You should be able to remove non-existent packages.\n      Console.error(packageName  + \" is not a direct dependency in this project.\");\n      exitCode = 1;\n    } else {\n      packagesToRemove.push(packageName);\n    }\n  });\n  if (! packagesToRemove.length) {\n    return exitCode;\n  }\n\n  // Remove the packages from the in-memory representation of .meteor/packages.\n  projectContext.projectConstraintsFile.removePackages(packagesToRemove);\n\n  // Run the constraint solver, rebuild local packages, etc. This will write\n  // our changes to .meteor/packages if it succeeds.\n  main.captureAndExit(\"=> Errors after removing packages\", function () {\n    projectContext.prepareProjectForBuild();\n  });\n  projectContext.packageMapDelta.displayOnConsole();\n\n  // Log that we removed the constraints. It is possible that there are\n  // constraints that we officially removed that the project still 'depends' on,\n  // which is why we do this in addition to dislpaying the PackageMapDelta.\n  _.each(packagesToRemove, function (packageName) {\n    Console.info(packageName + \": removed dependency\");\n  });\n\n  return exitCode;\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// refresh\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'refresh',\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: false })\n}, function (options) {\n  // We already did it!\n  return 0;\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// admin\n///////////////////////////////////////////////////////////////////////////////\n\n// For admin commands, at least in preview0.90, we can be kind of lazy and not bother\n// to pre-check if the command will succeed client-side. That's because we both\n// don't expect them to be called often and don't expect them to be called by\n// inexperienced users, so waiting to get rejected by the server is OK.\n\nmain.registerCommand({\n  name: 'admin maintainers',\n  minArgs: 1,\n  maxArgs: 1,\n  options: {\n    add: { type: String, short: \"a\" },\n    remove: { type: String, short: \"r\" },\n    list: { type: Boolean }\n  },\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: false })\n}, function (options) {\n  var name = options.args[0];\n\n  // Yay, checking that options are correct.\n  if (options.add && options.remove) {\n    Console.error(\n      \"Sorry, you can only add or remove one user at a time.\");\n    return 1;\n  }\n  if ((options.add || options.remove) && options.list) {\n    Console.error(\n      \"Sorry, you can't change the users at the same time as you're\",\n      \"listing them.\");\n    return 1;\n  }\n\n  // Now let's get down to business! Fetching the thing.\n  var fullRecord = getReleaseOrPackageRecord(name);\n  var record = fullRecord.record;\n  if (!options.list) {\n\n    try {\n      var conn = packageClient.loggedInPackagesConnection();\n    } catch (err) {\n      packageClient.handlePackageServerConnectionError(err);\n      return 1;\n    }\n\n    try {\n      if (options.add) {\n        Console.info(\"Adding a maintainer to \" + name + \"...\");\n        if (fullRecord.release) {\n          packageClient.callPackageServer(\n            conn, 'addReleaseMaintainer', name, options.add);\n        } else {\n          packageClient.callPackageServer(\n            conn, 'addMaintainer', name, options.add);\n        }\n      } else if (options.remove) {\n        Console.info(\"Removing a maintainer from \" + name + \"...\");\n        if (fullRecord.release) {\n          packageClient.callPackageServer(\n            conn, 'removeReleaseMaintainer', name, options.remove);\n        } else {\n          packageClient.callPackageServer(\n            conn, 'removeMaintainer', name, options.remove);\n        }\n        Console.info(\"Success.\");\n      }\n    } catch (err) {\n      packageClient.handlePackageServerConnectionError(err);\n      return 1;\n    }\n    conn.close();\n\n    // Update the catalog so that we have this information, and find the record\n    // again so that the message below is correct.\n    refreshOfficialCatalogOrDie();\n    fullRecord = getReleaseOrPackageRecord(name);\n    record = fullRecord.record;\n  }\n\n  if (!record) {\n    Console.info(\n      \"Could not get list of maintainers:\",\n      \"package \" + name + \" does not exist.\");\n    return 1;\n  }\n\n  Console.info();\n  Console.info(\"The maintainers for \" + name + \" are:\");\n  _.each(record.maintainers, function (user) {\n    if (! user || !user.username) {\n      Console.rawInfo(\"<unknown>\" + \"\\n\");\n    } else {\n      Console.rawInfo(user.username + \"\\n\");\n    }\n  });\n  return 0;\n});\n\n ///////////////////////////////////////////////////////////////////////////////\n// admin make-bootstrap-tarballs\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'admin make-bootstrap-tarballs',\n  minArgs: 2,\n  maxArgs: 2,\n  hidden: true,\n\n  options: {\n    // Copy the tarball contents to the output directory instead of making a\n    // tarball (useful for testing the release process)\n    \"unpacked\": { type: Boolean },\n    // Build a tarball only for a specific arch\n    \"target-arch\": { type: String }\n  },\n\n  // In this function, we want to use the official catalog everywhere, because\n  // we assume that all packages have been published (along with the release\n  // obviously) and we want to be sure to only bundle the published versions.\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: false })\n}, function (options) {\n  var releaseNameAndVersion = options.args[0];\n\n  // We get this as an argument, so it is an OS path. Make it a standard path.\n  var outputDirectory = files.convertToStandardPath(options.args[1]);\n\n  var trackAndVersion = catalogUtils.splitReleaseName(releaseNameAndVersion);\n  var releaseTrack = trackAndVersion[0];\n  var releaseVersion = trackAndVersion[1];\n\n  var releaseRecord = catalog.official.getReleaseVersion(\n    releaseTrack, releaseVersion);\n  if (!releaseRecord) {\n    // XXX this could also mean package unknown.\n    Console.error('Release unknown: ' + releaseNameAndVersion + '');\n    return 1;\n  }\n\n  var toolPackageVersion = releaseRecord.tool &&\n        utils.parsePackageAndVersion(releaseRecord.tool);\n  if (!toolPackageVersion) {\n    throw new Error(\"bad tool in release: \" + releaseRecord.tool);\n  }\n  var toolPackage = toolPackageVersion.package;\n  var toolVersion = toolPackageVersion.version;\n\n  var toolPkgBuilds = catalog.official.getAllBuilds(\n    toolPackage, toolVersion);\n  if (!toolPkgBuilds) {\n    // XXX this could also mean package unknown.\n    Console.error('Tool version unknown: ' + releaseRecord.tool);\n    return 1;\n  }\n  if (!toolPkgBuilds.length) {\n    Console.error('Tool version has no builds: ' + releaseRecord.tool);\n    return 1;\n  }\n\n  // XXX check to make sure this is the three arches that we want? it's easier\n  // during 0.9.0 development to allow it to just decide \"ok, i just want to\n  // build the OSX tarball\" though.\n  var buildArches = _.pluck(toolPkgBuilds, 'buildArchitectures');\n  var osArches = _.map(buildArches, function (buildArch) {\n    var subArches = buildArch.split('+');\n    var osArches = _.filter(subArches, function (subArch) {\n      return subArch.substr(0, 3) === 'os.';\n    });\n    if (osArches.length !== 1) {\n      throw Error(\"build architecture \" + buildArch + \"  lacks unique os.*\");\n    }\n    return osArches[0];\n  });\n\n  if (options['target-arch']) {\n    // check if the passed arch is in the list\n    var arch = options['target-arch'];\n    if (! _.contains(osArches, arch)) {\n      throw new Error(\n        arch + \": the arch is not available for the release. Available arches: \"\n        + osArches.join(', '));\n    }\n\n    // build only for the selected arch\n    osArches = [arch];\n  }\n\n  Console.error(\n    'Building bootstrap tarballs for architectures ' + osArches.join(', '));\n\n  // Before downloading anything, check that the catalog contains everything we\n  // need for the OSes that the tool is built for.\n  main.captureAndExit(\"=> Errors finding builds:\", function () {\n    _.each(osArches, function (osArch) {\n      _.each(releaseRecord.packages, function (pkgVersion, pkgName) {\n        buildmessage.enterJob({\n          title: \"looking up \" + pkgName + \"@\" + pkgVersion + \" on \" + osArch\n        }, function () {\n          if (!catalog.official.getBuildsForArches(pkgName, pkgVersion, [osArch])) {\n            buildmessage.error(\"missing build of \" + pkgName + \"@\" + pkgVersion +\n                               \" for \" + osArch);\n          }\n        });\n      });\n    });\n  });\n\n  files.mkdir_p(outputDirectory);\n\n  // Get a copy of the data.json.\n  var dataTmpdir = files.mkdtemp();\n  var tmpDataFile = files.pathJoin(dataTmpdir, 'packages.data.db');\n\n  var tmpCatalog = new catalogRemote.RemoteCatalog();\n  tmpCatalog.initialize({\n    packageStorage: tmpDataFile\n  });\n  try {\n    packageClient.updateServerPackageData(tmpCatalog, null);\n  } catch (err) {\n    packageClient.handlePackageServerConnectionError(err);\n    return 2;\n  }\n\n  // Since we're making bootstrap tarballs, we intend to recommend this release,\n  // so we should ensure that once it is downloaded, it knows it is recommended\n  // rather than having a little identity crisis and thinking that a past\n  // release is the latest recommended until it manages to sync.\n  tmpCatalog.forceRecommendRelease(releaseTrack, releaseVersion);\n  tmpCatalog.closePermanently();\n  if (files.exists(tmpDataFile + '-wal')) {\n    throw Error(\"Write-ahead log still exists for \" + tmpDataFile\n                + \" so the data file will be incomplete!\");\n  }\n\n  var packageMap =\n        packageMapModule.PackageMap.fromReleaseVersion(releaseRecord);\n\n  _.each(osArches, function (osArch) {\n    var tmpdir = files.mkdtemp();\n    Console.info(\"Building tarball for \" + osArch);\n\n    // when building for Windows architectures, build Windows-specific\n    // tropohouse and bootstrap tarball\n    var targetPlatform;\n    if (/win/i.test(osArch)) {\n      targetPlatform = \"win32\";\n    }\n\n    // We're going to build and tar up a tropohouse in a temporary directory.\n    var tmpTropo = new tropohouse.Tropohouse(\n      files.pathJoin(tmpdir, '.meteor'),\n      { platform: targetPlatform });\n\n    main.captureAndExit(\n      \"=> Errors downloading packages for \" + osArch + \":\",\n      function () {\n        tmpTropo.downloadPackagesMissingFromMap(packageMap, {\n          serverArchitectures: [osArch]\n        });\n      }\n    );\n\n    // Install the sqlite DB file we synced earlier. We have previously\n    // confirmed that the \"-wal\" file (which could contain extra log entries\n    // that haven't been flushed to the main file yet) doesn't exist, so we\n    // don't have to copy it.\n    files.copyFile(tmpDataFile, config.getPackageStorage({\n      root: tmpTropo.root\n    }));\n\n    // Create the top-level 'meteor' symlink, which links to the latest tool's\n    // meteor shell script.\n    var toolIsopackPath =\n          tmpTropo.packagePath(toolPackage, toolVersion);\n    var toolIsopack = new isopack.Isopack;\n    toolIsopack.initFromPath(toolPackage, toolIsopackPath);\n    var toolRecord = _.findWhere(toolIsopack.toolsOnDisk, {arch: osArch});\n    if (!toolRecord) {\n      throw Error(\"missing tool for \" + osArch);\n    }\n\n    tmpTropo.linkToLatestMeteor(files.pathJoin(\n        tmpTropo.packagePath(toolPackage, toolVersion, true),\n        toolRecord.path,\n        'meteor'));\n\n    if (options.unpacked) {\n      files.cp_r(tmpTropo.root, outputDirectory);\n    } else {\n      files.createTarball(\n        tmpTropo.root,\n        files.pathJoin(outputDirectory,\n          'meteor-bootstrap-' + osArch + '.tar.gz'));\n    }\n  });\n\n  return 0;\n});\n\n// We will document how to set banners on things in a later release.\nmain.registerCommand({\n  name: 'admin set-banners',\n  minArgs: 1,\n  maxArgs: 1,\n  hidden: true,\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: false })\n}, function (options) {\n  var bannersFile = options.args[0];\n  try {\n    var bannersData = files.readFile(bannersFile, 'utf8');\n    bannersData = JSON.parse(bannersData);\n  } catch (e) {\n    Console.error(\"Could not parse banners file: \" + e.message);\n    return 1;\n  }\n  if (!bannersData.track) {\n    Console.error(\"Banners file should have a 'track' key.\");\n    return 1;\n  }\n  if (!bannersData.banners) {\n    Console.error(\"Banners file should have a 'banners' key.\");\n    return 1;\n  }\n\n  try {\n    var conn = packageClient.loggedInPackagesConnection();\n  } catch (err) {\n    packageClient.handlePackageServerConnectionError(err);\n    return 1;\n  }\n\n  try {\n    packageClient.callPackageServer(\n      conn, 'setBannersOnReleases',\n      bannersData.track, bannersData.banners);\n  } catch (e) {\n    packageClient.handlePackageServerConnectionError(e);\n    return 1;\n  }\n\n  // Refresh afterwards.\n  refreshOfficialCatalogOrDie();\n  return 0;\n});\n\nmain.registerCommand({\n  name: 'admin recommend-release',\n  minArgs: 1,\n  maxArgs: 1,\n  options: {\n    unrecommend: { type: Boolean, short: \"u\" }\n  },\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: false })\n}, function (options) {\n\n  // We want the most recent information.\n  //refreshOfficialCatalogOrDie();\n  var release = options.args[0].split('@');\n  var name = release[0];\n  var version = release[1];\n  if (!version) {\n    Console.error('Must specify release version (track@version)');\n    return 1;\n  }\n\n  // Now let's get down to business! Fetching the thing.\n  var record = catalog.official.getReleaseTrack(name);\n  if (!record) {\n    Console.error();\n    Console.error('There is no release track named ' + name);\n    return 1;\n  }\n\n  try {\n    var conn = packageClient.loggedInPackagesConnection();\n  } catch (err) {\n    packageClient.handlePackageServerConnectionError(err);\n    return 1;\n  }\n\n  try {\n    if (options.unrecommend) {\n      Console.info(\"Unrecommending \" + name + \"@\" + version + \"...\");\n      packageClient.callPackageServer(\n        conn, 'unrecommendVersion', name, version);\n      Console.info(\"Success.\");\n      Console.info(name + \"@\" + version, \"is no longer a recommended release\");\n    } else {\n      Console.info(\"Recommending \" + options.args[0] + \"...\");\n      packageClient.callPackageServer(conn, 'recommendVersion', name, version);\n      Console.info(\"Success.\");\n      Console.info(name + \"@\" + version, \"is now a recommended release\");\n    }\n  } catch (err) {\n    packageClient.handlePackageServerConnectionError(err);\n    return 1;\n  }\n  conn.close();\n  refreshOfficialCatalogOrDie();\n\n  return 0;\n});\n\n\nmain.registerCommand({\n  name: 'admin change-homepage',\n  minArgs: 2,\n  maxArgs: 2,\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: false })\n}, function (options) {\n\n  // We want the most recent information.\n  //refreshOfficialCatalogOrDie();\n  var name = options.args[0];\n  var url = options.args[1];\n\n  // Now let's get down to business! Fetching the thing.\n  var record = catalog.official.getPackage(name);\n  if (!record) {\n    Console.error();\n    Console.error('There is no package named ' + name);\n    return 1;\n  }\n\n  try {\n    var conn = packageClient.loggedInPackagesConnection();\n  } catch (err) {\n    packageClient.handlePackageServerConnectionError(err);\n    return 1;\n  }\n\n  try {\n    Console.rawInfo(\n        \"Changing homepage on \"\n          + name + \" to \" + url + \"...\");\n      packageClient.callPackageServer(conn,\n          '_changePackageHomepage', name, url);\n      Console.info(\" done\");\n  } catch (err) {\n    packageClient.handlePackageServerConnectionError(err);\n    return 1;\n  }\n  conn.close();\n  refreshOfficialCatalogOrDie();\n\n  return 0;\n});\n\n\nmain.registerCommand({\n  name: 'admin set-unmigrated',\n  minArgs: 1,\n  options: {\n    \"success\" : {type: Boolean}\n  },\n  hidden: true,\n  catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: false })\n}, function (options) {\n\n  // We don't care about having the most recent information, but we do want the\n  // option to either unmigrate a specific version, or to unmigrate an entire\n  // package. So, for an entire package, let's get all of its versions.\n  var name = options.args[0];\n  var versions = [];\n  var nSplit = name.split('@');\n  if (nSplit.length > 2) {\n    throw new main.ShowUsage;\n  } else if (nSplit.length == 2) {\n    versions = [nSplit[1]];\n    name = nSplit[0];\n  } else {\n    versions = catalog.official.getSortedVersions(name);\n  }\n\n  try {\n    var conn = packageClient.loggedInPackagesConnection();\n  } catch (err) {\n    packageClient.handlePackageServerConnectionError(err);\n    return 1;\n  }\n\n  try {\n    var status = options.success ? \"successfully\" : \"unsuccessfully\";\n    // XXX: This should probably use progress bars instead.\n    _.each(versions, function (version) {\n      Console.rawInfo(\n        \"Setting \" + name + \"@\" + version + \" as \" +\n         status + \" migrated ... \");\n      packageClient.callPackageServer(\n        conn,\n        '_changeVersionMigrationStatus',\n        name, version, !options.success);\n      Console.info(\"done.\");\n    });\n  } catch (err) {\n    packageClient.handlePackageServerConnectionError(err);\n    return 1;\n  }\n  conn.close();\n  refreshOfficialCatalogOrDie();\n\n  return 0;\n});\n"
  },
  {
    "path": "tools/cli/commands.js",
    "content": "var main = require('./main.js');\nvar _ = require('underscore');\nvar files = require('../fs/files.js');\nvar deploy = require('../meteor-services/deploy.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar auth = require('../meteor-services/auth.js');\nvar authClient = require('../meteor-services/auth-client.js');\nvar config = require('../meteor-services/config.js');\nvar runLog = require('../runners/run-log.js');\nvar utils = require('../utils/utils.js');\nvar httpHelpers = require('../utils/http-helpers.js');\nvar archinfo = require('../utils/archinfo.js');\nvar catalog = require('../packaging/catalog/catalog.js');\nvar stats = require('../meteor-services/stats.js');\nvar Console = require('../console/console.js').Console;\nvar projectContextModule = require('../project-context.js');\nvar release = require('../packaging/release.js');\n\nimport * as cordova from '../cordova';\nimport { CordovaProject } from '../cordova/project.js';\nimport { CordovaRunner } from '../cordova/runner.js';\nimport { iOSRunTarget, AndroidRunTarget } from '../cordova/run-targets.js';\n\nimport { EXAMPLE_REPOSITORIES } from './example-repositories.js';\n\n// The architecture used by MDG's hosted servers; it's the architecture used by\n// 'meteor deploy'.\nvar DEPLOY_ARCH = 'os.linux.x86_64';\n\n// The default port that the development server listens on.\nvar DEFAULT_PORT = '3000';\n\n// Valid architectures that Meteor officially supports.\nvar VALID_ARCHITECTURES = {\n  \"os.osx.x86_64\": true,\n  \"os.linux.x86_64\": true,\n  \"os.linux.x86_32\": true,\n  \"os.windows.x86_32\": true\n};\n\n\n// __dirname - the location of the current executing file\nvar __dirnameConverted = files.convertToStandardPath(__dirname);\n\n// Given a site name passed on the command line (eg, 'mysite'), return\n// a fully-qualified hostname ('mysite.meteor.com').\n//\n// This is fairly simple for now. It appends 'meteor.com' if the name\n// doesn't contain a dot, and it deletes any trailing dots (the\n// technically legal hostname 'mysite.com.' is canonicalized to\n// 'mysite.com').\n//\n// In the future, you should be able to make this default to some\n// other domain you control, rather than 'meteor.com'.\nvar qualifySitename = function (site) {\n  if (site.indexOf(\".\") === -1) {\n    site = site + \".meteor.com\";\n  }\n  while (site.length && site[site.length - 1] === \".\") {\n    site = site.substring(0, site.length - 1);\n  }\n  return site;\n};\n\n// Display a message showing valid Meteor architectures.\nvar showInvalidArchMsg = function (arch) {\n  Console.info(\"Invalid architecture: \" + arch);\n  Console.info(\"The following are valid Meteor architectures:\");\n  _.each(_.keys(VALID_ARCHITECTURES), function (va) {\n    Console.info(\n      Console.command(va),\n      Console.options({ indent: 2 }));\n  });\n};\n\n// Utility functions to parse options in run/build/test-packages commands\n\nexport function parseServerOptionsForRunCommand(options, runTargets) {\n  const parsedServerUrl = parsePortOption(options.port);\n\n  // XXX COMPAT WITH 0.9.2.2 -- the 'mobile-port' option is deprecated\n  const mobileServerOption = options['mobile-server'] || options['mobile-port'];\n  let parsedMobileServerUrl;\n  if (mobileServerOption) {\n    parsedMobileServerUrl = parseMobileServerOption(mobileServerOption);\n  } else {\n    const isRunOnDeviceRequested = _.any(runTargets,\n      runTarget => runTarget.isDevice);\n    parsedMobileServerUrl = detectMobileServerUrl(parsedServerUrl,\n      isRunOnDeviceRequested);\n  }\n\n  return { parsedServerUrl, parsedMobileServerUrl };\n}\n\nfunction parsePortOption(portOption) {\n  let parsedServerUrl = utils.parseUrl(portOption);\n\n  if (!parsedServerUrl.port) {\n    Console.error(\"--port must include a port.\");\n    throw new main.ExitWithCode(1);\n  }\n\n  return parsedServerUrl;\n}\n\nfunction parseMobileServerOption(mobileServerOption,\n  optionName = 'mobile-server') {\n  let parsedMobileServerUrl = utils.parseUrl(\n    mobileServerOption,\n    { protocol: 'http' });\n\n  if (!parsedMobileServerUrl.hostname) {\n    Console.error(`--${optionName} must include a hostname.`);\n    throw new main.ExitWithCode(1);\n  }\n\n  return parsedMobileServerUrl;\n}\n\nfunction detectMobileServerUrl(parsedServerUrl, isRunOnDeviceRequested) {\n  // Always try to use an auto-detected IP first\n  try {\n    const myIp = utils.ipAddress();\n    return {\n      protocol: 'http',\n      hostname: myIp,\n      port: parsedServerUrl.port\n    };\n  } catch (error) {\n    // Unless we are being asked to run on a device, use localhost as fallback\n    if (isRunOnDeviceRequested) {\n      Console.error(\n`Error detecting IP address for mobile app to connect to:\n${error.message}\nPlease specify the address that the mobile app should connect\nto with --mobile-server.`);\n      throw new main.ExitWithCode(1);\n    } else {\n      return {\n        protocol: 'http',\n        hostname: 'localhost',\n        port: parsedServerUrl.port\n      };\n    }\n  }\n}\n\nexport function parseRunTargets(targets) {\n  return targets.map((target) => {\n    const targetParts = target.split('-');\n    const platform = targetParts[0];\n    const isDevice = targetParts[1] === 'device';\n\n    if (platform == 'ios') {\n      return new iOSRunTarget(isDevice);\n    } else if (platform == 'android') {\n      return new AndroidRunTarget(isDevice);\n    } else {\n      Console.error(`Unknown run target: ${target}`);\n      throw new main.ExitWithCode(1);\n    }\n  });\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// options that act like commands\n///////////////////////////////////////////////////////////////////////////////\n\n// Prints the Meteor architecture name of this host\nmain.registerCommand({\n  name: '--arch',\n  requiresRelease: false,\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  Console.rawInfo(archinfo.host() + \"\\n\");\n});\n\n// Prints the current release in use. Note that if there is not\n// actually a specific release, we print to stderr and exit non-zero,\n// while if there is a release we print to stdout and exit zero\n// (making this useful to scripts).\n// XXX: What does this mean in our new release-free world?\nmain.registerCommand({\n  name: '--version',\n  requiresRelease: false,\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  if (release.current === null) {\n    if (! options.appDir) {\n      throw new Error(\"missing release, but not in an app?\");\n    }\n    Console.error(\n      \"This project was created with a checkout of Meteor, rather than an \" +\n      \"official release, and doesn't have a release number associated with \" +\n      \"it. You can set its release with \" +\n      Console.command(\"'meteor update'\") + \".\");\n    return 1;\n  }\n\n  if (release.current.isCheckout()) {\n    var gitLog = utils.runGitInCheckout(\n      'log',\n      '--format=%h%d', '-n 1').trim();\n    Console.error(\"Unreleased, running from a checkout at \" + gitLog);\n    return 1;\n  }\n\n  Console.info(release.current.getDisplayName());\n});\n\n// Internal use only. For automated testing.\nmain.registerCommand({\n  name: '--long-version',\n  requiresRelease: false,\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  if (files.inCheckout()) {\n    Console.error(\"checkout\");\n    return 1;\n  } else if (release.current === null) {\n    // .meteor/release says \"none\" but not in a checkout.\n    Console.error(\"none\");\n    return 1;\n  } else {\n    Console.rawInfo(release.current.name + \"\\n\");\n    Console.rawInfo(files.getToolsVersion() + \"\\n\");\n    return 0;\n  }\n});\n\n// Internal use only. For automated testing.\nmain.registerCommand({\n  name: '--requires-release',\n  requiresRelease: true,\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  return 0;\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// run\n///////////////////////////////////////////////////////////////////////////////\n\nvar runCommandOptions = {\n  requiresApp: true,\n  maxArgs: Infinity,\n  options: {\n    port: { type: String, short: \"p\", default: DEFAULT_PORT },\n    'mobile-server': { type: String },\n    // XXX COMPAT WITH 0.9.2.2\n    'mobile-port': { type: String },\n    'app-port': { type: String },\n    'debug-port': { type: String },\n    production: { type: Boolean },\n    'raw-logs': { type: Boolean },\n    settings: { type: String },\n    verbose: { type: Boolean, short: \"v\" },\n    // With --once, meteor does not re-run the project if it crashes\n    // and does not monitor for file changes. Intentionally\n    // undocumented: intended for automated testing (eg, cli-test.sh),\n    // not end-user use. #Once\n    once: { type: Boolean },\n    // Don't run linter on rebuilds\n    'no-lint': { type: Boolean },\n    // Allow the version solver to make breaking changes to the versions\n    // of top-level dependencies.\n    'allow-incompatible-update': { type: Boolean }\n  },\n  catalogRefresh: new catalog.Refresh.Never()\n};\n\nmain.registerCommand(_.extend(\n  { name: 'run' },\n  runCommandOptions\n), doRunCommand);\n\nfunction doRunCommand(options) {\n  Console.setVerbose(!!options.verbose);\n\n  // Additional args are interpreted as run targets\n  const runTargets = parseRunTargets(options.args);\n\n  const { parsedServerUrl, parsedMobileServerUrl } =\n    parseServerOptionsForRunCommand(options, runTargets);\n\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: options.appDir,\n    allowIncompatibleUpdate: options['allow-incompatible-update'],\n    lintAppAndLocalPackages: !options['no-lint']\n  });\n\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    // We're just reading metadata here --- we'll wait to do the full build\n    // preparation until after we've started listening on the proxy, etc.\n    projectContext.readProjectMetadata();\n  });\n\n  if (release.explicit) {\n    if (release.current.name !== projectContext.releaseFile.fullReleaseName) {\n      console.log(\"=> Using %s as requested (overriding %s)\",\n                  release.current.getDisplayName(),\n                  projectContext.releaseFile.displayReleaseName);\n      console.log();\n    }\n  }\n\n  let appHost, appPort;\n  if (options['app-port']) {\n    var appPortMatch = options['app-port'].match(/^(?:(.+):)?([0-9]+)?$/);\n    if (!appPortMatch) {\n      Console.error(\n        \"run: --app-port must be a number or be of the form 'host:port' \",\n        \"where port is a number. Try\",\n        Console.command(\"'meteor help run'\") + \" for help.\");\n      return 1;\n    }\n    appHost = appPortMatch[1] || null;\n    // It's legit to specify `--app-port host:` and still let the port be\n    // randomized.\n    appPort = appPortMatch[2] ? parseInt(appPortMatch[2]) : null;\n  }\n\n  if (options['raw-logs']) {\n    runLog.setRawLogs(true);\n  }\n\n  let webArchs = ['web.browser'];\n  let cordovaRunner;\n  if (!_.isEmpty(runTargets) || options['mobile-server']) {\n    main.captureAndExit('', 'preparing Cordova project', () => {\n      const cordovaProject = new CordovaProject(projectContext, {\n        settingsFile: options.settings,\n        mobileServerUrl: utils.formatUrl(parsedMobileServerUrl) });\n      if (buildmessage.jobHasMessages()) return;\n\n      cordovaRunner = new CordovaRunner(cordovaProject, runTargets);\n      cordovaRunner.checkPlatformsForRunTargets();\n    });\n    webArchs.push(\"web.cordova\");\n  }\n\n  var runAll = require('../runners/run-all.js');\n  return runAll.run({\n    projectContext: projectContext,\n    proxyPort: parsedServerUrl.port,\n    proxyHost: parsedServerUrl.hostname,\n    appPort: appPort,\n    appHost: appHost,\n    debugPort: options['debug-port'],\n    settingsFile: options.settings,\n    buildOptions: {\n      minifyMode: options.production ? 'production' : 'development',\n      buildMode: options.production && 'production',\n      webArchs: webArchs\n    },\n    rootUrl: process.env.ROOT_URL,\n    mongoUrl: process.env.MONGO_URL,\n    oplogUrl: process.env.MONGO_OPLOG_URL,\n    mobileServerUrl: utils.formatUrl(parsedMobileServerUrl),\n    once: options.once,\n    cordovaRunner: cordovaRunner\n  });\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// debug\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand(_.extend(\n  { name: 'debug' },\n  runCommandOptions\n), function (options) {\n  options['debug-port'] = options['debug-port'] || '5858';\n  return doRunCommand(options);\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// shell\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'shell',\n  requiresRelease: false,\n  requiresApp: true,\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  if (!options.appDir) {\n    Console.error(\n      \"The \" + Console.command(\"'meteor shell'\") + \" command must be run\",\n      \"in a Meteor app directory.\"\n    );\n  } else {\n    var projectContext = new projectContextModule.ProjectContext({\n      projectDir: options.appDir\n    });\n\n    // Convert to OS path here because shell/server.js doesn't know how to\n    // convert paths, since it exists in the app and in the tool.\n    require('../shell-client.js').connect(\n      files.convertToOSPath(projectContext.getMeteorShellDirectory())\n    );\n\n    throw new main.WaitForExit;\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// create\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'create',\n  maxArgs: 1,\n  options: {\n    list: { type: Boolean },\n    example: { type: String },\n    package: { type: Boolean }\n  },\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n\n  // Creating a package is much easier than creating an app, so if that's what\n  // we are doing, do that first. (For example, we don't springboard to the\n  // latest release to create a package if we are inside an app)\n  if (options.package) {\n    var packageName = options.args[0];\n\n    if (options.list || options.example) {\n      Console.error(\"No package examples exist at this time.\");\n      Console.error();\n      throw new main.ShowUsage;\n    }\n\n    if (!packageName) {\n      Console.error(\"Please specify the name of the package.\");\n      throw new main.ShowUsage;\n    }\n\n    utils.validatePackageNameOrExit(\n      packageName, {detailedColonExplanation: true});\n\n    // When we create a package, avoid introducing a colon into the file system\n    // by naming the directory after the package name without the prefix.\n    var fsName = packageName;\n    if (packageName.indexOf(\":\") !== -1) {\n      var split = packageName.split(\":\");\n\n      if (split.length > 2) {\n        // It may seem like this check should be inside package version parser's\n        // validatePackageName, but we decided to name test packages like this:\n        // local-test:prefix:name, so we have to support building packages\n        // with at least two colons. Therefore we will at least try to\n        // discourage people from putting a ton of colons in their package names\n        // here.\n        Console.error(packageName +\n          \": Package names may not have more than one colon.\");\n        return 1;\n      }\n\n      fsName = split[1];\n    }\n\n    var packageDir;\n    if (options.appDir) {\n      packageDir = files.pathResolve(options.appDir, 'packages', fsName);\n    } else {\n      packageDir = files.pathResolve(fsName);\n    }\n\n    var inYourApp = options.appDir ? \" in your app\" : \"\";\n\n    if (files.exists(packageDir)) {\n      Console.error(packageName + \": Already exists\" + inYourApp);\n      return 1;\n    }\n\n    var transform = function (x) {\n      var xn =\n        x.replace(/~name~/g, packageName).replace(/~fs-name~/g, fsName);\n\n      // If we are running from checkout, comment out the line sourcing packages\n      // from a release, with the latest release filled in (in case they do want\n      // to publish later). If we are NOT running from checkout, fill it out\n      // with the current release.\n      var relString;\n      if (release.current.isCheckout()) {\n        xn = xn.replace(/~cc~/g, \"//\");\n        var rel = catalog.official.getDefaultReleaseVersion();\n        // the no-release case should never happen except in tests.\n        relString = rel ? rel.version : \"no-release\";\n      } else {\n        xn = xn.replace(/~cc~/g, \"\");\n        relString = release.current.getDisplayName({noPrefix: true});\n      }\n\n      // If we are not in checkout, write the current release here.\n      return xn.replace(/~release~/g, relString);\n    };\n\n    try {\n      files.cp_r(files.pathJoin(__dirnameConverted, '..', 'static-assets', 'skel-pack'), packageDir, {\n        transformFilename: function (f) {\n          return transform(f);\n        },\n        transformContents: function (contents, f) {\n          if ((/(\\.html|\\.js|\\.css)/).test(f)) {\n            return new Buffer(transform(contents.toString()));\n          } else {\n            return contents;\n          }\n        },\n        ignore: [/^local$/]\n      });\n    } catch (err) {\n      Console.error(\"Could not create package: \" + err.message);\n      return 1;\n    }\n\n    var displayPackageDir =\n      files.convertToOSPath(files.pathRelative(files.cwd(), packageDir));\n\n    // Since the directory can't have colons, the directory name will often not\n    // match the name of the package exactly, therefore we should tell people\n    // where it was created.\n    Console.info(\n      packageName + \": created in\",\n      Console.path(displayPackageDir)\n    );\n\n    return 0;\n  }\n\n  // Suppose you have an app A, and from some directory inside that\n  // app, you run 'meteor create /my/new/app'. The new app should use\n  // the latest available Meteor release, not the release that A\n  // uses. So if we were run from inside an app directory, and the\n  // user didn't force a release with --release, we need to\n  // springboard to the correct release and tools version.\n  //\n  // (In particular, it's not sufficient to create the new app with\n  // this version of the tools, and then stamp on the correct release\n  // at the end.)\n  if (! release.current.isCheckout() && !release.forced) {\n    if (release.current.name !== release.latestKnown()) {\n      throw new main.SpringboardToLatestRelease;\n    }\n  }\n\n  if (options.list) {\n    Console.info(\"Available examples:\");\n    _.each(EXAMPLE_REPOSITORIES, function (repoInfo, name) {\n      const branchInfo = repoInfo.branch ? `#${repoInfo.branch}` : '';\n      Console.info(\n        Console.command(`${name}: ${repoInfo.repo}${branchInfo}`),\n        Console.options({ indent: 2 }));\n    });\n\n    Console.info();\n    Console.info(\"To create an example, simply\", Console.command(\"git clone\"),\n      \"the relevant repository and branch (run\", \n      Console.command(\"'meteor create --example <name>'\"),\n      \" to see the full command).\");\n    return 0;\n  };\n\n  if (options.example) {\n    const repoInfo = EXAMPLE_REPOSITORIES[options.example];\n    if (!repoInfo) {\n      Console.error(`${options.example}: no such example.`);\n      Console.error(\n        \"List available applications with\",\n        Console.command(\"'meteor create --list'\") + \".\");\n      return 1;\n    }\n\n    const branchOption = repoInfo.branch ? ` -b ${repoInfo.branch}` : '';\n    const path = options.args.length === 1 ? ` ${options.args[0]}` : '';\n\n    Console.info(`To create the ${options.example} example, please run:`)\n    Console.info(\n      Console.command(`git clone ${repoInfo.repo}${branchOption}${path}`),\n      Console.options({ indent: 2 }));\n\n    return 0;\n  }\n\n  var appPathAsEntered;\n  if (options.args.length === 1) {\n    appPathAsEntered = options.args[0];\n  } else {\n    throw new main.ShowUsage;\n  }\n  var appPath = files.pathResolve(appPathAsEntered);\n\n  if (files.findAppDir(appPath)) {\n    Console.error(\n      \"You can't create a Meteor project inside another Meteor project.\");\n    return 1;\n  }\n\n  var appName;\n  if (appPathAsEntered === \".\" || appPathAsEntered === \"./\") {\n    // If trying to create in current directory\n    appName = files.pathBasename(files.cwd());\n  } else {\n    appName = files.pathBasename(appPath);\n  }\n\n\n  var transform = function (x) {\n    return x.replace(/~name~/g, appName);\n  };\n\n  // These file extensions are usually metadata, not app code\n  var nonCodeFileExts = ['.txt', '.md', '.json', '.sh'];\n\n  var destinationHasCodeFiles = false;\n\n  // If the directory doesn't exist, it clearly doesn't have any source code\n  // inside itself\n  if (files.exists(appPath)) {\n    destinationHasCodeFiles = _.any(files.readdir(appPath),\n        function thisPathCountsAsAFile(filePath) {\n      // We don't mind if there are hidden files or directories (this includes\n      // .git) and we don't need to check for .meteor here because the command\n      // will fail earlier\n      var isHidden = /^\\./.test(filePath);\n      if (isHidden) {\n        // Not code\n        return false;\n      }\n\n      // We do mind if there are non-hidden directories, because we don't want\n      // to recursively check everything to do some crazy heuristic to see if\n      // we should try to creat an app.\n      var stats = files.stat(filePath);\n      if (stats.isDirectory()) {\n        // Could contain code\n        return true;\n      }\n\n      // Check against our file extension white list\n      var ext = files.pathExtname(filePath);\n      if (ext == '' || _.contains(nonCodeFileExts, ext)) {\n        return false;\n      }\n\n      // Everything not matched above is considered to be possible source code\n      return true;\n    });\n  }\n\n  var toIgnore = [/^local$/, /^\\.id$/]\n  if (destinationHasCodeFiles) {\n    // If there is already source code in the directory, don't copy our\n    // skeleton app code over it. Just create the .meteor folder and metadata\n    toIgnore.push(/(\\.html|\\.js|\\.css)/)\n  }\n\n  files.cp_r(files.pathJoin(__dirnameConverted, '..', 'static-assets', 'skel'), appPath, {\n    transformFilename: function (f) {\n      return transform(f);\n    },\n    transformContents: function (contents, f) {\n      if ((/(\\.html|\\.js|\\.css)/).test(f)) {\n        return new Buffer(transform(contents.toString()));\n      } else {\n        return contents;\n      }\n    },\n    ignore: toIgnore\n  });\n\n  // We are actually working with a new meteor project at this point, so\n  // set up its context.\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: appPath,\n    // Write .meteor/versions even if --release is specified.\n    alwaysWritePackageMap: true,\n    // examples come with a .meteor/versions file, but we shouldn't take it\n    // too seriously\n    allowIncompatibleUpdate: true\n  });\n\n  main.captureAndExit(\"=> Errors while creating your project\", function () {\n    projectContext.readProjectMetadata();\n    if (buildmessage.jobHasMessages()) {\n      return;\n    }\n\n    projectContext.releaseFile.write(\n      release.current.isCheckout() ? \"none\" : release.current.name);\n    if (buildmessage.jobHasMessages()) {\n      return;\n    }\n\n    // Any upgrader that is in this version of Meteor doesn't need to be run on\n    // this project.\n    var upgraders = require('../upgraders.js');\n    projectContext.finishedUpgraders.appendUpgraders(upgraders.allUpgraders());\n\n    projectContext.prepareProjectForBuild();\n  });\n  // No need to display the PackageMapDelta here, since it would include all of\n  // the packages (or maybe an unpredictable subset based on what happens to be\n  // in the template's versions file).\n\n  var appNameToDisplay = appPathAsEntered === \".\" ?\n    \"current directory\" : `'${appPathAsEntered}'`;\n\n  var message = `Created a new Meteor app in ${appNameToDisplay}`;\n\n  message += \".\";\n\n  Console.info(message + \"\\n\");\n\n  // Print a nice message telling people we created their new app, and what to\n  // do next.\n  Console.info(\"To run your new app:\");\n\n  if (appPathAsEntered !== \".\") {\n    // Wrap the app path in quotes if it contains spaces\n    const appPathWithQuotesIfSpaces = appPathAsEntered.indexOf(' ') === -1 ?\n      appPathAsEntered :\n      `'${appPathAsEntered}'`;\n\n    // Don't tell people to 'cd .'\n    Console.info(\n      Console.command(\"cd \" + appPathWithQuotesIfSpaces),\n        Console.options({ indent: 2 }));\n  }\n\n  Console.info(\n    Console.command(\"meteor\"), Console.options({ indent: 2 }));\n\n  Console.info(\"\");\n  Console.info(\"If you are new to Meteor, try some of the learning resources here:\");\n  Console.info(\n    Console.url(\"https://www.meteor.com/learn\"),\n      Console.options({ indent: 2 }));\n\n  Console.info(\"\");\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// build\n///////////////////////////////////////////////////////////////////////////////\n\nvar buildCommands = {\n  minArgs: 1,\n  maxArgs: 1,\n  requiresApp: true,\n  options: {\n    debug: { type: Boolean },\n    directory: { type: Boolean },\n    architecture: { type: String },\n    \"server-only\": { type: Boolean },\n    'mobile-settings': { type: String },\n    server: { type: String },\n    // XXX COMPAT WITH 0.9.2.2\n    \"mobile-port\": { type: String },\n    verbose: { type: Boolean, short: \"v\" },\n    'allow-incompatible-update': { type: Boolean }\n  },\n  catalogRefresh: new catalog.Refresh.Never()\n};\n\nmain.registerCommand(_.extend({ name: 'build' }, buildCommands),\n  function (options) {\n    return buildCommand(options);\n});\n\n// Deprecated -- identical functionality to 'build' with one exception: it\n// doesn't output a directory with all builds but rather only one tarball with\n// server/client programs.\n// XXX COMPAT WITH 0.9.1.1\nmain.registerCommand(_.extend({ name: 'bundle', hidden: true\n                              }, buildCommands),\n    function (options) {\n\n      Console.error(\n      \"This command has been deprecated in favor of \" +\n      Console.command(\"'meteor build'\") + \", which allows you to \" +\n      \"build for multiple platforms and outputs a directory instead of \" +\n      \"a single tarball. See \" + Console.command(\"'meteor help build'\") + \" \" +\n      \"for more information.\");\n      Console.error();\n      return buildCommand(_.extend(options, { _bundleOnly: true }));\n});\n\nvar buildCommand = function (options) {\n  Console.setVerbose(!!options.verbose);\n  // XXX output, to stderr, the name of the file written to (for human\n  // comfort, especially since we might change the name)\n\n  // XXX name the root directory in the bundle based on the basename\n  // of the file, not a constant 'bundle' (a bit obnoxious for\n  // machines, but worth it for humans)\n\n  // Error handling for options.architecture. We must pass in only one of three\n  // architectures. See archinfo.js for more information on what the\n  // architectures are, what they mean, et cetera.\n  if (options.architecture &&\n      !_.has(VALID_ARCHITECTURES, options.architecture)) {\n    showInvalidArchMsg(options.architecture);\n    return 1;\n  }\n  var bundleArch = options.architecture || archinfo.host();\n\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: options.appDir,\n    serverArchitectures: _.uniq([bundleArch, archinfo.host()]),\n    allowIncompatibleUpdate: options['allow-incompatible-update']\n  });\n\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    projectContext.prepareProjectForBuild();\n  });\n  projectContext.packageMapDelta.displayOnConsole();\n\n  // _bundleOnly implies serverOnly\n  const serverOnly = options._bundleOnly || !!options['server-only'];\n\n  // options['mobile-settings'] is used to set the initial value of\n  // `Meteor.settings` on mobile apps. Pass it on to options.settings,\n  // which is used in this command.\n  if (options['mobile-settings']) {\n    options.settings = options['mobile-settings'];\n  }\n\n  const appName = files.pathBasename(options.appDir);\n\n  let cordovaPlatforms;\n  let parsedMobileServerUrl;\n  if (!serverOnly) {\n    cordovaPlatforms = projectContext.platformList.getCordovaPlatforms();\n\n    if (process.platform !== 'darwin' && _.contains(cordovaPlatforms, 'ios')) {\n      cordovaPlatforms = _.without(cordovaPlatforms, 'ios');\n      Console.warn(\"Currently, it is only possible to build iOS apps \\\non an OS X system.\");\n    }\n\n    if (!_.isEmpty(cordovaPlatforms)) {\n      // XXX COMPAT WITH 0.9.2.2 -- the --mobile-port option is deprecated\n      const mobileServerOption = options.server || options[\"mobile-port\"];\n      if (!mobileServerOption) {\n        // For Cordova builds, require '--server'.\n        // XXX better error message?\n        Console.error(\n          \"Supply the server hostname and port in the --server option \" +\n            \"for mobile app builds.\");\n        return 1;\n      }\n      parsedMobileServerUrl = parseMobileServerOption(mobileServerOption,\n        'server');\n    }\n  } else {\n    cordovaPlatforms = [];\n  }\n\n  var buildDir = projectContext.getProjectLocalDirectory('build_tar');\n  var outputPath = files.pathResolve(options.args[0]); // get absolute path\n\n  // Warn if people try to build inside the app directory.\n  var relative = files.pathRelative(options.appDir, outputPath);\n  // We would like the output path to be outside the app directory, which\n  // means the first step to getting there is going up a level.\n  if (relative.substr(0, 2) !== '..') {\n    Console.warn();\n    Console.labelWarn(`The output directory is under your source tree.\nYour generated files may get interpreted as source code!\nConsider building into a different directory instead\n${Console.command(\"meteor build ../output\")}`,\n      Console.options({ indent: 2 }));\n    Console.warn();\n  }\n\n  var bundlePath = options.directory ?\n      (options._bundleOnly ? outputPath :\n      files.pathJoin(outputPath, 'bundle')) :\n      files.pathJoin(buildDir, 'bundle');\n\n  stats.recordPackages({\n    what: \"sdk.bundle\",\n    projectContext: projectContext\n  });\n\n  var bundler = require('../isobuild/bundler.js');\n  var bundleResult = bundler.bundle({\n    projectContext: projectContext,\n    outputPath: bundlePath,\n    buildOptions: {\n      minifyMode: options.debug ? 'development' : 'production',\n      // XXX is this a good idea, or should linux be the default since\n      //     that's where most people are deploying\n      //     default?  i guess the problem with using DEPLOY_ARCH as default\n      //     is then 'meteor bundle' with no args fails if you have any local\n      //     packages with binary npm dependencies\n      serverArch: bundleArch,\n      buildMode: options.debug ? 'development' : 'production',\n    },\n  });\n  if (bundleResult.errors) {\n    Console.error(\"Errors prevented bundling:\");\n    Console.error(bundleResult.errors.formatMessages());\n    return 1;\n  }\n\n  if (!options._bundleOnly) {\n    files.mkdir_p(outputPath);\n  }\n\n  if (!options.directory) {\n    main.captureAndExit('', 'creating server tarball', () => {\n      try {\n        var outputTar = options._bundleOnly ? outputPath :\n          files.pathJoin(outputPath, appName + '.tar.gz');\n\n        files.createTarball(files.pathJoin(buildDir, 'bundle'), outputTar);\n      } catch (err) {\n        buildmessage.exception(err);\n        files.rm_recursive(buildDir);\n      }\n    });\n  }\n\n  if (!_.isEmpty(cordovaPlatforms)) {\n    let cordovaProject;\n\n    main.captureAndExit('', () => {\n      buildmessage.enterJob({ title: \"preparing Cordova project\" }, () => {\n        cordovaProject = new CordovaProject(projectContext, {\n          settingsFile: options.settings,\n          mobileServerUrl: utils.formatUrl(parsedMobileServerUrl) });\n        if (buildmessage.jobHasMessages()) return;\n\n        const pluginVersions = cordova.pluginVersionsFromStarManifest(\n          bundleResult.starManifest);\n\n        cordovaProject.prepareFromAppBundle(bundlePath, pluginVersions);\n      });\n\n      for (platform of cordovaPlatforms) {\n        buildmessage.enterJob(\n          { title: `building Cordova app for \\\n${cordova.displayNameForPlatform(platform)}` }, () => {\n            let buildOptions = { release: !options.debug };\n            \n            const buildPath = files.pathJoin(\n              projectContext.getProjectLocalDirectory('cordova-build'),\n              'platforms', platform);\n            const platformOutputPath = files.pathJoin(outputPath, platform);\n\n            files.cp_r(buildPath,\n              files.pathJoin(platformOutputPath, 'project'));\n\n            if (platform === 'ios') {\n              cordovaProject.prepareForPlatform(platform, buildOptions);\n\n              files.writeFile(\n                files.pathJoin(platformOutputPath, 'README'),\n`This is an auto-generated XCode project for your iOS application.\n\nInstructions for publishing your iOS app to App Store can be found at:\nhttps://github.com/meteor/meteor/wiki/How-to-submit-your-iOS-app-to-App-Store\n`, \"utf8\");\n            } else if (platform === 'android') {\n              cordovaProject.buildForPlatform(platform, buildOptions);\n\n              const apkPath = files.pathJoin(buildPath, 'build/outputs/apk',\n                options.debug ? 'android-debug.apk' : 'android-release-unsigned.apk')\n\n              if (files.exists(apkPath)) {\n              files.copyFile(apkPath, files.pathJoin(platformOutputPath,\n                options.debug ? 'debug.apk' : 'release-unsigned.apk'));\n              }\n\n              files.writeFile(\n                files.pathJoin(platformOutputPath, 'README'),\n`This is an auto-generated Gradle project for your Android application.\n\nInstructions for publishing your Android app to Play Store can be found at:\nhttps://github.com/meteor/meteor/wiki/How-to-submit-your-Android-app-to-Play-Store\n`, \"utf8\");\n            }\n        });\n      }\n    });\n  }\n\n  files.rm_recursive(buildDir);\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// lint\n///////////////////////////////////////////////////////////////////////////////\nmain.registerCommand({\n  name: 'lint',\n  maxArgs: 0,\n  requiresAppOrPackage: true,\n  options: {\n    'allow-incompatible-updates': { type: Boolean }\n  },\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  const {packageDir, appDir} = options;\n\n  let projectContext = null;\n\n  // if the goal is to lint the package, don't include the whole app\n  if (packageDir) {\n    // similar to `meteor publish`, create a fake project\n    const tempProjectDir = files.mkdtemp('meteor-package-build');\n    projectContext = new projectContextModule.ProjectContext({\n      projectDir: tempProjectDir,\n      explicitlyAddedLocalPackageDirs: [packageDir],\n      packageMapFilename: files.pathJoin(packageDir, '.versions'),\n      alwaysWritePackageMap: true,\n      forceIncludeCordovaUnibuild: true,\n      allowIncompatibleUpdate: options['allow-incompatible-update'],\n      lintPackageWithSourceRoot: packageDir\n    });\n\n    main.captureAndExit(\"=> Errors while setting up package:\", () =>\n      // Read metadata and initialize catalog.\n      projectContext.initializeCatalog()\n    );\n    const versionRecord =\n        projectContext.localCatalog.getVersionBySourceRoot(packageDir);\n    if (! versionRecord) {\n      throw Error(\"explicitly added local package dir missing?\");\n    }\n    const packageName = versionRecord.packageName;\n    const constraint = utils.parsePackageConstraint(packageName);\n    projectContext.projectConstraintsFile.removeAllPackages();\n    projectContext.projectConstraintsFile.addConstraints([constraint]);\n  }\n\n  // linting the app\n  if (! projectContext && appDir) {\n    projectContext = new projectContextModule.ProjectContext({\n      projectDir: appDir,\n      serverArchitectures: [archinfo.host()],\n      allowIncompatibleUpdate: options['allow-incompatible-update'],\n      lintAppAndLocalPackages: true\n    });\n  }\n\n\n  main.captureAndExit(\"=> Errors prevented the build:\", () => {\n    projectContext.prepareProjectForBuild();\n  });\n\n  const bundlePath = projectContext.getProjectLocalDirectory('build');\n  const bundler = require('../isobuild/bundler.js');\n  const bundle = bundler.bundle({\n    projectContext: projectContext,\n    outputPath: null,\n    buildOptions: {\n      minifyMode: 'development'\n    }\n  });\n\n  const displayName = options.packageDir ? 'package' : 'app';\n  if (bundle.errors) {\n    Console.error(\n      `=> Errors building your ${displayName}:\\n\\n${bundle.errors.formatMessages()}`\n    );\n    throw new main.ExitWithCode(2);\n  }\n\n  if (bundle.warnings) {\n    Console.warn(bundle.warnings.formatMessages());\n    return 1;\n  }\n\n  return 0;\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// mongo\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'mongo',\n  maxArgs: 1,\n  options: {\n    url: { type: Boolean, short: 'U' }\n  },\n  requiresApp: function (options) {\n    return options.args.length === 0;\n  },\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  var mongoUrl;\n  var usedMeteorAccount = false;\n\n  if (options.args.length === 0) {\n    // localhost mode\n    var findMongoPort =\n      require('../runners/run-mongo.js').findMongoPort;\n    var mongoPort = findMongoPort(files.pathJoin(options.appDir, \".meteor\", \"local\", \"db\"));\n\n    // XXX detect the case where Meteor is running, but MONGO_URL was\n    // specified?\n\n    if (! mongoPort) {\n      Console.info(\"mongo: Meteor isn't running a local MongoDB server.\");\n      Console.info();\n      Console.info(`\\\nThis command only works while Meteor is running your application locally. \\\nStart your application first with 'meteor' and then run this command in a new \\\nterminal. This error will also occur if you asked Meteor to use a different \\\nMongoDB server with $MONGO_URL when you ran your application.`);\n      Console.info();\n      Console.info(`\\\nIf you're trying to connect to the database of an app you deployed with \\\n${Console.command(\"'meteor deploy'\")}, specify your site's name as an argument \\\nto this command.`);\n      return 1;\n    }\n    mongoUrl = \"mongodb://127.0.0.1:\" + mongoPort + \"/meteor\";\n\n  } else {\n    // remote mode\n    var site = qualifySitename(options.args[0]);\n\n    mongoUrl = deploy.temporaryMongoUrl(site);\n    usedMeteorAccount = true;\n\n    if (! mongoUrl) {\n      // temporaryMongoUrl() will have printed an error message\n      return 1;\n    }\n  }\n  if (options.url) {\n    console.log(mongoUrl);\n  } else {\n    if (usedMeteorAccount) {\n      auth.maybePrintRegistrationLink();\n    }\n    process.stdin.pause();\n    var runMongo = require('../runners/run-mongo.js');\n    runMongo.runMongoShell(mongoUrl);\n    throw new main.WaitForExit;\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// reset\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'reset',\n  // Doesn't actually take an argument, but we want to print an custom\n  // error message if they try to pass one.\n  maxArgs: 1,\n  requiresApp: true,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  if (options.args.length !== 0) {\n    Console.error(\"meteor reset only affects the locally stored database.\");\n    Console.error();\n    Console.error(\"To reset a deployed application use\");\n    Console.error(\n      Console.command(\"meteor deploy --delete appname\"), Console.options({ indent: 2 }));\n    Console.error(\"followed by\");\n    Console.error(\n      Console.command(\"meteor deploy appname\"), Console.options({ indent: 2 }));\n    return 1;\n  }\n  \n  if (process.env.MONGO_URL) {\n    Console.info(\"As a precaution, meteor reset only clears the local database that is \" +\n                 \"provided by meteor run for development. The database specified with \" +\n                 \"MONGO_URL will NOT be reset.\");\n  }\n\n  // XXX detect the case where Meteor is running the app, but\n  // MONGO_URL was set, so we don't see a Mongo process\n  var findMongoPort = require('../runners/run-mongo.js').findMongoPort;\n  var isRunning = !! findMongoPort(files.pathJoin(options.appDir, \".meteor\", \"local\", \"db\"));\n  if (isRunning) {\n    Console.error(\"reset: Meteor is running.\");\n    Console.error();\n    Console.error(\n      \"This command does not work while Meteor is running your application.\",\n      \"Exit the running Meteor development server.\");\n    return 1;\n  }\n\n  var localDir = files.pathJoin(options.appDir, '.meteor', 'local');\n  files.rm_recursive(localDir);\n\n  Console.info(\"Project reset.\");\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// deploy\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'deploy',\n  minArgs: 1,\n  maxArgs: 1,\n  options: {\n    'delete': { type: Boolean, short: 'D' },\n    debug: { type: Boolean },\n    settings: { type: String },\n    // No longer supported, but we still parse it out so that we can\n    // print a custom error message.\n    password: { type: String },\n    // Override architecture to deploy whatever stuff we have locally, even if\n    // it contains binary packages that should be incompatible. A hack to allow\n    // people to deploy from checkout or do other weird shit. We are not\n    // responsible for the consequences.\n    'override-architecture-with-local' : { type: Boolean },\n    'allow-incompatible-update': { type: Boolean }\n  },\n  allowUnrecognizedOptions: true,\n  requiresApp: function (options) {\n    return ! options.delete;\n  },\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options, {rawOptions}) {\n  var site = options.args[0];\n\n  if (options.delete) {\n    return deploy.deleteApp(site);\n  }\n\n  if (options.password) {\n    Console.error(\n      \"Setting passwords on apps is no longer supported. Now there are \" +\n        \"user accounts and your apps are associated with your account so \" +\n        \"that only you (and people you designate) can access them. See the \" +\n        Console.command(\"'meteor claim'\") + \" and \" +\n        Console.command(\"'meteor authorized'\") + \" commands.\");\n    return 1;\n  }\n\n  var loggedIn = auth.isLoggedIn();\n  if (! loggedIn) {\n    Console.error(\n      \"You must be logged in to deploy, just enter your email address.\");\n    Console.error();\n    if (! auth.registerOrLogIn()) {\n      return 1;\n    }\n  }\n\n  // Override architecture iff applicable.\n  var buildArch = DEPLOY_ARCH;\n  if (options['override-architecture-with-local']) {\n    Console.warn();\n    Console.labelWarn(\n      \"OVERRIDING DEPLOY ARCHITECTURE WITH LOCAL ARCHITECTURE.\",\n      \"If your app contains binary code, it may break in unexpected \" +\n      \"and terrible ways.\");\n    buildArch = archinfo.host();\n  }\n\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: options.appDir,\n    serverArchitectures: _.uniq([buildArch, archinfo.host()]),\n    allowIncompatibleUpdate: options['allow-incompatible-update']\n  });\n\n  main.captureAndExit(\"=> Errors while initializing project:\", function () {\n    projectContext.prepareProjectForBuild();\n  });\n  projectContext.packageMapDelta.displayOnConsole();\n\n  var buildOptions = {\n    minifyMode: options.debug ? 'development' : 'production',\n    buildMode: options.debug ? 'development' : 'production',\n    serverArch: buildArch\n  };\n\n  var deployResult = deploy.bundleAndDeploy({\n    projectContext: projectContext,\n    site: site,\n    settingsFile: options.settings,\n    buildOptions: buildOptions,\n    rawOptions\n  });\n\n  if (deployResult === 0) {\n    auth.maybePrintRegistrationLink({\n      leadingNewline: true,\n      // If the user was already logged in at the beginning of the\n      // deploy, then they've already been prompted to set a password\n      // at least once before, so we use a slightly different message.\n      firstTime: ! loggedIn\n    });\n  }\n\n  return deployResult;\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// logs\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'logs',\n  minArgs: 1,\n  maxArgs: 1,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  var site = qualifySitename(options.args[0]);\n\n  return deploy.logs(site);\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// authorized\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'authorized',\n  minArgs: 1,\n  maxArgs: 1,\n  options: {\n    add: { type: String, short: \"a\" },\n    transfer: { type: String, short: \"t\" },\n    remove: { type: String, short: \"r\" },\n    list: { type: Boolean }\n  },\n  pretty: function (options) {\n    // pretty if we're mutating; plain if we're listing (which is more likely to\n    // be used by scripts)\n    return options.add || options.remove || options.transfer;\n  },\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n\n  if (_.keys(_.pick(options, 'add', 'remove', 'transfer', 'list')).length > 1) {\n    Console.error(\n      \"Sorry, you can only perform one authorization operation at a time.\");\n    return 1;\n  }\n\n  auth.pollForRegistrationCompletion();\n  var site = qualifySitename(options.args[0]);\n\n  if (! auth.isLoggedIn()) {\n    Console.error(\n      \"You must be logged in for that. Try \" +\n      Console.command(\"'meteor login'\"));\n    return 1;\n  }\n\n  if (options.add) {\n    return deploy.changeAuthorized(site, \"add\", options.add);\n  } else if (options.remove) {\n    return deploy.changeAuthorized(site, \"remove\", options.remove);\n  } else if (options.transfer) {\n    return deploy.changeAuthorized(site, \"transfer\", options.transfer);\n  } else {\n    return deploy.listAuthorized(site);\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// claim\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'claim',\n  minArgs: 1,\n  maxArgs: 1,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  auth.pollForRegistrationCompletion();\n  var site = qualifySitename(options.args[0]);\n\n  if (! auth.isLoggedIn()) {\n    Console.error(\n      \"You must be logged in to claim sites. Use \" +\n      Console.command(\"'meteor login'\") + \" to log in. If you don't have a \" +\n      \"Meteor developer account yet, create one by clicking \" +\n      Console.command(\"'Sign in'\") + \" and then \" +\n      Console.command(\"'Create account'\") + \" at www.meteor.com.\");\n    Console.error();\n    return 1;\n  }\n\n  return deploy.claim(site);\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// test and test-packages\n///////////////////////////////////////////////////////////////////////////////\n\ntestCommandOptions = {\n  maxArgs: Infinity,\n  catalogRefresh: new catalog.Refresh.Never(),\n  options: {\n    port: { type: String, short: \"p\", default: DEFAULT_PORT },\n    'mobile-server': { type: String },\n    // XXX COMPAT WITH 0.9.2.2\n    'mobile-port': { type: String },\n    'debug-port': { type: String },\n    deploy: { type: String },\n    production: { type: Boolean },\n    settings: { type: String },\n    // Indicates whether these self-tests are running headless, e.g. in a\n    // continuous integration testing environment, where visual niceties\n    // like progress bars and spinners are unimportant.\n    headless: { type: Boolean },\n    verbose: { type: Boolean, short: \"v\" },\n\n    // Undocumented. See #Once\n    once: { type: Boolean },\n    // Undocumented. To ensure that QA covers both\n    // PollingObserveDriver and OplogObserveDriver, this option\n    // disables oplog for tests.  (It still creates a replset, it just\n    // doesn't do oplog tailing.)\n    'disable-oplog': { type: Boolean },\n    // Undocumented flag to use a different test driver.\n    'driver-package': { type: String },\n\n    // Sets the path of where the temp app should be created\n    'test-app-path': { type: String },\n\n    // Undocumented, runs tests under selenium\n    'selenium': { type: Boolean },\n    'selenium-browser': { type: String },\n\n    // Undocumented.  Usually we just show a banner saying 'Tests' instead of\n    // the ugly path to the temporary test directory, but if you actually want\n    // to see it you can ask for it.\n    'show-test-app-path': { type: Boolean },\n\n    // hard-coded options with all known Cordova platforms\n    ios: { type: Boolean },\n    'ios-device': { type: Boolean },\n    android: { type: Boolean },\n    'android-device': { type: Boolean },\n\n    // This could theoretically be useful/necessary in conjunction with\n    // --test-app-path.\n    'allow-incompatible-update': { type: Boolean },\n\n    // Don't print linting messages for tested packages\n    'no-lint': { type: Boolean },\n\n    // allow excluding packages when testing all packages.\n    // should be a comma-separated list of package names.\n    'exclude': { type: String },\n\n    // one of the following must be true\n    'test': { type: Boolean, 'default': false },\n    'test-packages': { type: Boolean, 'default': false },\n\n    // For 'test-packages': Run in \"full app\" mode\n    'full-app': { type: Boolean, 'default': false }\n  }\n};\n\nmain.registerCommand(_.extend({\n  name: 'test',\n  requiresApp: true\n}, testCommandOptions), function (options) {\n  options['test'] = true;\n  return doTestCommand(options);\n});\n\nmain.registerCommand(_.extend(\n  { name: 'test-packages' },\n  testCommandOptions\n), function (options) {\n  options['test-packages'] = true;\n  return doTestCommand(options);\n});\n\nfunction doTestCommand(options) {\n  // This \"metadata\" is accessed in a few places. Using a global\n  // variable here was more expedient than navigating the many layers\n  // of abstraction across the the build process.\n  //\n  // As long as the Meteor CLI runs a single command as part of each\n  // process, this should be safe.\n  global.testCommandMetadata = {};\n\n  Console.setVerbose(!!options.verbose);\n  if (options.headless) {\n    Console.setHeadless(true);\n  }\n\n  const runTargets = parseRunTargets(_.intersection(\n    Object.keys(options), ['ios', 'ios-device', 'android', 'android-device']));\n\n  const { parsedServerUrl, parsedMobileServerUrl } =\n    parseServerOptionsForRunCommand(options, runTargets);\n\n  // Make a temporary app dir (based on the test runner app). This will be\n  // cleaned up on process exit. Using a temporary app dir means that we can\n  // run multiple \"test-packages\" commands in parallel without them stomping\n  // on each other.\n  var testRunnerAppDir =\n        options['test-app-path'] || files.mkdtemp('meteor-test-run');\n\n  // Download packages for our architecture, and for the deploy server's\n  // architecture if we're deploying.\n  var serverArchitectures = [archinfo.host()];\n  if (options.deploy && DEPLOY_ARCH !== archinfo.host()) {\n    serverArchitectures.push(DEPLOY_ARCH);\n  }\n\n  var projectContextOptions = {\n    serverArchitectures: serverArchitectures,\n    allowIncompatibleUpdate: options['allow-incompatible-update'],\n    lintAppAndLocalPackages: !options['no-lint']\n  };\n  var projectContext;\n\n  if (options[\"test-packages\"]) {\n    global.testCommandMetadata.driverPackage = options['driver-package'] || 'test-in-browser';\n    projectContextOptions.projectDir = testRunnerAppDir;\n    projectContextOptions.projectDirForLocalPackages = options.appDir;\n\n    // Find any packages mentioned by a path instead of a package name. We will\n    // load them explicitly into the catalog.\n    var packagesByPath = _.filter(options.args, function (p) {\n      return p.indexOf('/') !== -1;\n    });\n    // If we're currently in an app, we still want to use the real app's\n    // packages subdirectory, not the test runner app's empty one.\n    projectContextOptions.explicitlyAddedLocalPackageDirs = packagesByPath;\n\n    // XXX Because every run uses a new app with its own IsopackCache directory,\n    //     this always does a clean build of all packages. Maybe we can speed up\n    //     repeated test-packages calls with some sort of shared or semi-shared\n    //     isopack cache that's specific to test-packages?  See #3012.\n    projectContext = new projectContextModule.ProjectContext(projectContextOptions);\n\n    main.captureAndExit(\"=> Errors while initializing project:\", function () {\n      // We're just reading metadata here --- we'll wait to do the full build\n      // preparation until after we've started listening on the proxy, etc.\n      projectContext.readProjectMetadata();\n    });\n\n    main.captureAndExit(\"=> Errors while setting up tests:\", function () {\n      // Read metadata and initialize catalog.\n      projectContext.initializeCatalog();\n    });\n\n    // Overwrite .meteor/release.\n    projectContext.releaseFile.write(\n      release.current.isCheckout() ? \"none\" : release.current.name);\n\n    var packagesToAdd = getTestPackageNames(projectContext, options.args);\n\n    // filter out excluded packages\n    var excludedPackages = options.exclude && options.exclude.split(',');\n    if (excludedPackages) {\n      packagesToAdd = _.filter(packagesToAdd, function (p) {\n        return ! _.some(excludedPackages, function (excluded) {\n          return p.replace(/^local-test:/, '') === excluded;\n        });\n      });\n    }\n\n    // Use the driver package if running `meteor test-packages`. For\n    // `meteor test`, the driver package is expected to already\n    // have been added to the app.\n    packagesToAdd.unshift(global.testCommandMetadata.driverPackage);\n\n    // Also, add `autoupdate` so that you don't have to manually refresh the tests\n    packagesToAdd.unshift(\"autoupdate\");\n\n    var constraintsToAdd = _.map(packagesToAdd, function (p) {\n      return utils.parsePackageConstraint(p);\n    });\n    // Add the packages to our in-memory representation of .meteor/packages.  (We\n    // haven't yet resolved constraints, so this will affect constraint\n    // resolution.)  This will get written to disk once we prepareProjectForBuild,\n    // either in the Cordova code below, right before deploying below, or in the\n    // app runner.  (Note that removeAllPackages removes any comments from\n    // .meteor/packages, but that's OK since this isn't a real user project.)\n    projectContext.projectConstraintsFile.removeAllPackages();\n    projectContext.projectConstraintsFile.addConstraints(constraintsToAdd);\n    // Write these changes to disk now, so that if the first attempt to prepare\n    // the project for build hits errors, we don't lose them on\n    // projectContext.reset.\n    projectContext.projectConstraintsFile.writeIfModified();\n  } else if (options[\"test\"]) {\n    if (!options['driver-package']) {\n      throw new Error(\"You must specify a driver package with --driver-package\");\n    }\n\n    global.testCommandMetadata.driverPackage = options['driver-package'];\n\n    global.testCommandMetadata.isAppTest = options['full-app'];\n    global.testCommandMetadata.isTest = !global.testCommandMetadata.isAppTest;\n    \n    projectContextOptions.projectDir = options.appDir;\n    projectContextOptions.projectLocalDir = files.pathJoin(testRunnerAppDir, '.meteor', 'local');\n\n    // Copy the existing build and isopacks to speed up the initial start\n    const copyDirIntoTestRunnerApp = (...parts) => {\n      // Depending on whether the user has run `meteor run` or other commands, they\n      // may or may not exist yet\n      const appDirPath = files.pathJoin(options.appDir, ...parts);\n      if (files.exists(appDirPath)) {\n        files.cp_r(\n          appDirPath,\n          files.pathJoin(testRunnerAppDir, ...parts),\n          {preserveSymlinks: true}\n        );\n      }\n    }\n\n    copyDirIntoTestRunnerApp('.meteor', 'local', 'build');\n    copyDirIntoTestRunnerApp('.meteor', 'local', 'bundler-cache');\n    copyDirIntoTestRunnerApp('.meteor', 'local', 'isopacks');\n    copyDirIntoTestRunnerApp('.meteor', 'local', 'plugin-cache');\n    \n    projectContext = new projectContextModule.ProjectContext(projectContextOptions);\n\n    main.captureAndExit(\"=> Errors while setting up tests:\", function () {\n      // Read metadata and initialize catalog.\n      projectContext.initializeCatalog();\n    });\n  } else {\n    throw new Error(\"Unexpected: neither test-packages nor test\");\n  }\n\n  // The rest of the projectContext preparation process will happen inside the\n  // runner, once the proxy is listening. The changes we made were persisted to\n  // disk, so projectContext.reset won't make us forget anything.\n\n  let cordovaRunner;\n\n  if (!_.isEmpty(runTargets)) {\n    main.captureAndExit('', 'preparing Cordova project', () => {\n      const cordovaProject = new CordovaProject(projectContext, {\n        settingsFile: options.settings,\n        mobileServerUrl: utils.formatUrl(parsedMobileServerUrl) });\n      if (buildmessage.jobHasMessages()) return;\n\n      cordovaRunner = new CordovaRunner(cordovaProject, runTargets);\n      projectContext.platformList.write(cordovaRunner.platformsForRunTargets);\n      cordovaRunner.checkPlatformsForRunTargets();\n    });\n  }\n\n  options.cordovaRunner = cordovaRunner;\n\n  return runTestAppForPackages(projectContext, _.extend(\n    options,\n    {\n      mobileServerUrl: utils.formatUrl(parsedMobileServerUrl),\n      proxyPort: parsedServerUrl.port,\n      proxyHost: parsedServerUrl.hostname,\n    }\n  ));\n}\n\n// Returns the \"local-test:*\" package names for the given package names (or for\n// all local packages if packageNames is empty/unspecified).\nvar getTestPackageNames = function (projectContext, packageNames) {\n  var packageNamesSpecifiedExplicitly = ! _.isEmpty(packageNames);\n  if (_.isEmpty(packageNames)) {\n    // If none specified, test all local packages. (We don't have tests for\n    // non-local packages.)\n    packageNames = projectContext.localCatalog.getAllPackageNames();\n  }\n  var testPackages = [];\n  main.captureAndExit(\"=> Errors while collecting tests:\", function () {\n    _.each(packageNames, function (p) {\n      buildmessage.enterJob(\"trying to test package `\" + p + \"`\", function () {\n        // If it's a package name, look it up the normal way.\n        if (p.indexOf('/') === -1) {\n          if (p.indexOf('@') !== -1) {\n            buildmessage.error(\n              \"You may not specify versions for local packages: \" + p );\n            return;  // recover by ignoring\n          }\n          // Check to see if this is a real local package, and if it is a real\n          // local package, if it has tests.\n          var version = projectContext.localCatalog.getLatestVersion(p);\n          if (! version) {\n            buildmessage.error(\"Not a known local package, cannot test\");\n          } else if (version.testName) {\n            testPackages.push(version.testName);\n          } else if (packageNamesSpecifiedExplicitly) {\n            // It's only an error to *ask* to test a package with no tests, not\n            // to come across a package with no tests when you say \"test all\n            // packages\".\n            buildmessage.error(\"Package has no tests\");\n          }\n        } else {\n          // Otherwise, it's a directory; find it by source root.\n          version = projectContext.localCatalog.getVersionBySourceRoot(\n            files.pathResolve(p));\n          if (! version) {\n            throw Error(\"should have been caught when initializing catalog?\");\n          }\n          if (version.testName) {\n            testPackages.push(version.testName);\n          }\n          // It is not an error to mention a package by directory that is a\n          // package but has no tests; this means you can run `meteor\n          // test-packages $APP/packages/*` without having to worry about the\n          // packages that don't have tests.\n        }\n      });\n    });\n  });\n\n  return testPackages;\n};\n\nvar runTestAppForPackages = function (projectContext, options) {\n  var buildOptions = {\n    minifyMode: options.production ? 'production' : 'development'\n  };\n  buildOptions.buildMode = \"test\";\n  \n  if (options.deploy) {\n    // Run the constraint solver and build local packages.\n    main.captureAndExit(\"=> Errors while initializing project:\", function () {\n      projectContext.prepareProjectForBuild();\n    });\n    // No need to display the PackageMapDelta here, since it would include all\n    // of the packages!\n\n    buildOptions.serverArch = DEPLOY_ARCH;\n    return deploy.bundleAndDeploy({\n      projectContext: projectContext,\n      site: options.deploy,\n      settingsFile: options.settings,\n      buildOptions: buildOptions,\n      recordPackageUsage: false\n    });\n  } else {\n    var runAll = require('../runners/run-all.js');\n    return runAll.run({\n      projectContext: projectContext,\n      proxyPort: options.proxyPort,\n      proxyHost: options.proxyHost,\n      debugPort: options['debug-port'],\n      disableOplog: options['disable-oplog'],\n      settingsFile: options.settings,\n      testMetadata: global.testCommandMetadata,\n      banner: options['show-test-app-path'] ? null : \"Tests\",\n      buildOptions: buildOptions,\n      rootUrl: process.env.ROOT_URL,\n      mongoUrl: process.env.MONGO_URL,\n      oplogUrl: process.env.MONGO_OPLOG_URL,\n      mobileServerUrl: options.mobileServerUrl,\n      once: options.once,\n      recordPackageUsage: false,\n      selenium: options.selenium,\n      seleniumBrowser: options['selenium-browser'],\n      cordovaRunner: options.cordovaRunner,\n      // On the first run, we shouldn't display the delta between \"no packages\n      // in the temp app\" and \"all the packages we're testing\". If we make\n      // changes and reload, though, it's fine to display them.\n      omitPackageMapDeltaDisplayOnFirstRun: true\n    });\n  }\n};\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// rebuild\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'rebuild',\n  maxArgs: Infinity,\n  hidden: true,\n  requiresApp: true,\n  catalogRefresh: new catalog.Refresh.Never(),\n  'allow-incompatible-update': { type: Boolean }\n}, function (options) {\n  var projectContextModule = require('../project-context.js');\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: options.appDir,\n    forceRebuildPackages: options.args.length ? options.args : true,\n    allowIncompatibleUpdate: options['allow-incompatible-update']\n  });\n\n  main.captureAndExit(\"=> Errors while rebuilding packages:\", function () {\n    projectContext.prepareProjectForBuild();\n  });\n  projectContext.packageMapDelta.displayOnConsole();\n\n  Console.info(\"Packages rebuilt.\");\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// login\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'login',\n  options: {\n    email: { type: Boolean }\n  },\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  return auth.loginCommand(_.extend({\n    overwriteExistingToken: true\n  }, options));\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// logout\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'logout',\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  return auth.logoutCommand(options);\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// whoami\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'whoami',\n  catalogRefresh: new catalog.Refresh.Never(),\n  pretty: false\n}, function (options) {\n  return auth.whoAmICommand(options);\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// organizations\n///////////////////////////////////////////////////////////////////////////////\n\nvar loggedInAccountsConnectionOrPrompt = function (action) {\n  var token = auth.getSessionToken(config.getAccountsDomain());\n  if (! token) {\n    Console.error(\"You must be logged in to \" + action + \".\");\n    auth.doUsernamePasswordLogin({ retry: true });\n    Console.info();\n  }\n\n  token = auth.getSessionToken(config.getAccountsDomain());\n  var conn = auth.loggedInAccountsConnection(token);\n  if (conn === null) {\n    // Server rejected our token.\n    Console.error(\"You must be logged in to \" + action + \".\");\n    auth.doUsernamePasswordLogin({ retry: true });\n    Console.info();\n    token = auth.getSessionToken(config.getAccountsDomain());\n    conn = auth.loggedInAccountsConnection(token);\n  }\n\n  return conn;\n};\n\n// List the organizations of which the current user is a member.\nmain.registerCommand({\n  name: 'admin list-organizations',\n  minArgs: 0,\n  maxArgs: 0,\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n\n  var token = auth.getSessionToken(config.getAccountsDomain());\n  if (! token) {\n    Console.error(\"You must be logged in to list your organizations.\");\n    auth.doUsernamePasswordLogin({ retry: true });\n    Console.info();\n  }\n\n  var url = config.getAccountsApiUrl() + \"/organizations\";\n  try {\n    var result = httpHelpers.request({\n      url: url,\n      method: \"GET\",\n      useSessionHeader: true,\n      useAuthHeader: true\n    });\n    var body = JSON.parse(result.body);\n  } catch (err) {\n    Console.error(\"Error listing organizations.\");\n    return 1;\n  }\n\n  if (result.response.statusCode === 401 &&\n      body && body.error === \"invalid_credential\") {\n    Console.error(\"You must be logged in to list your organizations.\");\n    // XXX It would be nice to do a username/password prompt here like\n    // we do for the other orgs commands.\n    return 1;\n  }\n\n  if (result.response.statusCode !== 200 ||\n      ! body || ! body.organizations) {\n    Console.error(\"Error listing organizations.\");\n    return 1;\n  }\n\n  if (body.organizations.length === 0) {\n    Console.info(\"You are not a member of any organizations.\");\n  } else {\n    Console.rawInfo(_.pluck(body.organizations, \"name\").join(\"\\n\") + \"\\n\");\n  }\n  return 0;\n});\n\nmain.registerCommand({\n  name: 'admin members',\n  minArgs: 1,\n  maxArgs: 1,\n  options: {\n    add: { type: String },\n    remove: { type: String },\n    list: { type: Boolean }\n  },\n  pretty: function (options) {\n    // pretty if we're mutating; plain if we're listing (which is more likely to\n    // be used by scripts)\n    return options.add || options.remove;\n  },\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n\n  if (options.add && options.remove) {\n    Console.error(\n      \"Sorry, you can only add or remove one member at a time.\");\n    throw new main.ShowUsage;\n  }\n\n  var username = options.add || options.remove;\n\n  var conn = loggedInAccountsConnectionOrPrompt(\n    username ? \"edit organizations\" : \"show an organization's members\");\n\n  if (username ) {\n    // Adding or removing members\n    try {\n      conn.call(\n        options.add ? \"addOrganizationMember\": \"removeOrganizationMember\",\n        options.args[0], username);\n    } catch (err) {\n      Console.error(\"Error \" +\n                    (options.add ? \"adding\" : \"removing\") +\n                    \" member: \" + err.reason);\n      return 1;\n    }\n\n    Console.info(username + \" \" +\n                         (options.add ? \"added to\" : \"removed from\") +\n                         \" organization \" + options.args[0] + \".\");\n  } else {\n    // Showing the members of an org\n    try {\n      var result = conn.call(\"showOrganization\", options.args[0]);\n    } catch (err) {\n      Console.error(\"Error showing organization: \" + err.reason);\n      return 1;\n    }\n\n    var members = _.pluck(result, \"username\");\n    Console.rawInfo(members.join(\"\\n\") + \"\\n\");\n  }\n\n  return 0;\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// self-test\n///////////////////////////////////////////////////////////////////////////////\n\n// XXX we should find a way to make self-test fully self-contained, so that it\n// ignores \"packageDirs\" (ie, it shouldn't fail just because you happen to be\n// sitting in an app with packages that don't build)\n\nmain.registerCommand({\n  name: 'self-test',\n  minArgs: 0,\n  maxArgs: 1,\n  options: {\n    changed: { type: Boolean },\n    'force-online': { type: Boolean },\n    slow: { type: Boolean },\n    galaxy: { type: Boolean },\n    browserstack: { type: Boolean },\n    // Indicates whether these self-tests are running headless, e.g. in a\n    // continuous integration testing environment, where visual niceties\n    // like progress bars and spinners are unimportant.\n    headless: { type: Boolean },\n    history: { type: Number },\n    list: { type: Boolean },\n    file: { type: String },\n    exclude: { type: String },\n    // Skip tests w/ this tag\n    'without-tag': { type: String },\n    // Only run tests with this tag\n    'with-tag': { type: String },\n  },\n  hidden: true,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  if (! files.inCheckout()) {\n    Console.error(\"self-test is only supported running from a checkout\");\n    return 1;\n  }\n\n  var selftest = require('../tool-testing/selftest.js');\n\n  // Auto-detect whether to skip 'net' tests, unless --force-online is passed.\n  var offline = false;\n  if (!options['force-online']) {\n    try {\n      require('../utils/http-helpers.js').getUrl(\"http://www.google.com/\");\n    } catch (e) {\n      if (e instanceof files.OfflineError) {\n        offline = true;\n      }\n    }\n  }\n\n  var compileRegexp = function (str) {\n    try {\n      return new RegExp(str);\n    } catch (e) {\n      if (!(e instanceof SyntaxError)) {\n        throw e;\n      }\n      Console.error(\"Bad regular expression: \" + str);\n      return null;\n    }\n  };\n\n  var testRegexp = undefined;\n  if (options.args.length) {\n    testRegexp = compileRegexp(options.args[0]);\n    if (! testRegexp) {\n      return 1;\n    }\n  }\n\n  var fileRegexp = undefined;\n  if (options.file) {\n    fileRegexp = compileRegexp(options.file);\n    if (! fileRegexp) {\n      return 1;\n    }\n  }\n\n  var excludeRegexp = undefined;\n  if (options.exclude) {\n    excludeRegexp = compileRegexp(options.exclude);\n    if (! excludeRegexp) {\n      return 1;\n    }\n  }\n\n  if (options.list) {\n    selftest.listTests({\n      onlyChanged: options.changed,\n      offline: offline,\n      includeSlowTests: options.slow,\n      galaxyOnly: options.galaxy,\n      testRegexp: testRegexp,\n      fileRegexp: fileRegexp,\n      'without-tag': options['without-tag'],\n      'with-tag': options['with-tag']\n    });\n\n    return 0;\n  }\n\n  var clients = {\n    browserstack: options.browserstack\n  };\n\n  if (options.headless) {\n    // There's no point in spinning the spinner when we're running\n    // continuous integration tests.\n    Console.setHeadless(true);\n  }\n\n  return selftest.runTests({\n    // filtering options\n    onlyChanged: options.changed,\n    offline: offline,\n    includeSlowTests: options.slow,\n    galaxyOnly: options.galaxy,\n    testRegexp: testRegexp,\n    fileRegexp: fileRegexp,\n    excludeRegexp: excludeRegexp,\n    // other options\n    historyLines: options.history,\n    clients: clients,\n    'without-tag': options['without-tag'],\n    'with-tag': options['with-tag']\n  });\n\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// list-sites\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'list-sites',\n  minArgs: 0,\n  maxArgs: 0,\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  auth.pollForRegistrationCompletion();\n  if (! auth.isLoggedIn()) {\n    Console.error(\n      \"You must be logged in for that. Try \" +\n      Console.command(\"'meteor login'\") + \".\");\n    return 1;\n  }\n\n  return deploy.listSites();\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// admin get-machine\n///////////////////////////////////////////////////////////////////////////////\n\nmain.registerCommand({\n  name: 'admin get-machine',\n  minArgs: 1,\n  maxArgs: 1,\n  options: {\n    json: { type: Boolean },\n    verbose: { type: Boolean, short: \"v\" },\n    // By default, we give you a machine for 5 minutes. You can request up to\n    // 15. (MDG can reserve machines for longer than that.)\n    minutes: { type: Number }\n  },\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n\n  // Check that we are asking for a valid architecture.\n  var arch = options.args[0];\n  if (!_.has(VALID_ARCHITECTURES, arch)){\n    showInvalidArchMsg(arch);\n    return 1;\n  }\n\n  // Set the minutes. We will check validity on the server.\n  var minutes = options.minutes || 5;\n\n  // In verbose mode, we let you know what is going on.\n  var maybeLog = function (string) {\n    if (options.verbose) {\n      Console.info(string);\n    }\n  };\n\n  try {\n    maybeLog(\"Logging into the get-machines server ...\");\n    var conn = authClient.loggedInConnection(\n      config.getBuildFarmUrl(),\n      config.getBuildFarmDomain(),\n      \"build-farm\");\n  } catch (err) {\n    authClient.handleConnectionError(err, \"get-machines server\");\n    return 1;\n  }\n\n  try {\n    maybeLog(\"Reserving machine ...\");\n\n    // The server returns to us an object with the following keys:\n    // username & sshKey : use this to log in.\n    // host: what you login into\n    // port: port you should use\n    // hostKey: RSA key to compare for safety.\n    var ret = conn.call('createBuildServer', arch, minutes);\n  } catch (err) {\n    authClient.handleConnectionError(err, \"build farm\");\n    return 1;\n  }\n  conn.close();\n\n  // Possibly, the user asked us to return a JSON of the data and is going to process it\n  // themselves. In that case, let's do that and exit.\n  if (options.json) {\n    var retJson = {\n      'username': ret.username,\n      'host' : ret.host,\n      'port' : ret.port,\n      'key' : ret.sshKey,\n      'hostKey' : ret.hostKey\n    };\n    Console.rawInfo(JSON.stringify(retJson, null, 2) + \"\\n\");\n    return 0;\n  }\n\n  // Record the SSH Key in a temporary file on disk and give it the permissions\n  // that ssh-agent requires it to have.\n  var tmpDir = files.mkdtemp('meteor-ssh-');\n  var idpath = tmpDir + '/id';\n  maybeLog(\"Writing ssh key to \" + idpath);\n  files.writeFile(idpath, ret.sshKey, {encoding: 'utf8', mode: 0o400});\n\n  // Add the known host key to a custom known hosts file.\n  var hostpath = tmpDir + '/host';\n  var addendum = ret.host + \" \" + ret.hostKey + \"\\n\";\n  maybeLog(\"Writing host key to \" + hostpath);\n  files.writeFile(hostpath, addendum, 'utf8');\n\n  // Finally, connect to the machine.\n  var login = ret.username + \"@\" + ret.host;\n  var maybeVerbose = options.verbose ? \"-v\" : \"-q\";\n\n  var connOptions = [\n    login,\n     \"-i\" + idpath,\n     \"-p\" + ret.port,\n     \"-oUserKnownHostsFile=\" + hostpath,\n     maybeVerbose];\n\n  var printOptions = connOptions.join(' ');\n  maybeLog(\"Connecting: \" + Console.command(\"ssh \" + printOptions));\n\n  var child_process = require('child_process');\n\n  if (arch.match(/win/)) {\n    // The ssh output from Windows machines is buggy, it can overlay your\n    // existing output on the top of the screen which is very ugly. Force the\n    // screen cleaning to assist.\n    Console.clear();\n  }\n\n  var sshCommand = child_process.spawn(\n    \"ssh\", connOptions,\n    { stdio: 'inherit' }); // Redirect spawn stdio to process\n\n  return new Promise(function (resolve) {\n    sshCommand.on('error', function (err) {\n      if (err.code === \"ENOENT\") {\n        if (process.platform === \"win32\") {\n          Console.error(\"Could not find the `ssh` command in your PATH.\",\n                        \"Please read this page about using the get-machine command on Windows:\",\n                        Console.url(\"https://github.com/meteor/meteor/wiki/Accessing-Meteor-provided-build-machines-from-Windows\"));\n        } else {\n          Console.error(\"Could not find the `ssh` command in your PATH.\");\n        }\n\n        resolve(1);\n      }\n    });\n\n    sshCommand.on('exit', function (code, signal) {\n      // XXX: We should process the signal in some way, but I am not sure we\n      // care right now.\n      resolve(signal ? 1 : code);\n    });\n  }).await();\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// admin progressbar-test\n///////////////////////////////////////////////////////////////////////////////\n\n// A test command to print a progressbar. Useful for manual testing.\nmain.registerCommand({\n  name: 'admin progressbar-test',\n  options: {\n    secs: { type: Number, default: 20 },\n    spinner: { type: Boolean, default: false }\n  },\n  hidden: true,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  buildmessage.enterJob({ title: \"A test progressbar\" }, function () {\n    var progress = buildmessage.getCurrentProgressTracker();\n    var totalProgress = { current: 0, end: options.secs, done: false };\n    var i = 0;\n    var n = options.secs;\n\n    if (options.spinner) {\n      totalProgress.end = undefined;\n    }\n\n    new Promise(function (resolve) {\n      function updateProgress() {\n        i++;\n        if (! options.spinner) {\n          totalProgress.current = i;\n        }\n\n        if (i === n) {\n          totalProgress.done = true;\n          progress.reportProgress(totalProgress);\n          resolve();\n        } else {\n          progress.reportProgress(totalProgress);\n          setTimeout(updateProgress, 1000);\n        }\n      }\n\n      setTimeout(updateProgress);\n    }).await();\n  });\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// dummy\n///////////////////////////////////////////////////////////////////////////////\n\n// Dummy test command. Used for automated testing of the command line\n// option parser.\n\nmain.registerCommand({\n  name: 'dummy',\n  options: {\n    ething: { type: String, short: \"e\", required: true },\n    port: { type: Number, short: \"p\", default: DEFAULT_PORT },\n    url: { type: Boolean, short: \"U\" },\n    'delete': { type: Boolean, short: \"D\" },\n    changed: { type: Boolean }\n  },\n  maxArgs: 2,\n  hidden: true,\n  pretty: false,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function (options) {\n  var p = function (key) {\n    if (_.has(options, key)) {\n      return JSON.stringify(options[key]);\n    }\n    return 'none';\n  };\n\n  Console.info(p('ething') + \" \" + p('port') + \" \" + p('changed') +\n                       \" \" + p('args'));\n  if (options.url) {\n    Console.info('url');\n  }\n  if (options['delete']) {\n    Console.info('delete');\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// throw-error\n///////////////////////////////////////////////////////////////////////////////\n\n// Dummy test command. Used to test that stack traces work from an installed\n// Meteor tool.\n\nmain.registerCommand({\n  name: 'throw-error',\n  hidden: true,\n  catalogRefresh: new catalog.Refresh.Never()\n}, function () {\n  throw new Error(\"testing stack traces!\"); // #StackTraceTest this line is found in tests/source-maps.js\n});\n"
  },
  {
    "path": "tools/cli/dev-bundle-bin-commands.js",
    "content": "// Note that this file is required before we install our Babel hooks in\n// ../tool-env/install-babel.js, so we can't use ES2015+ syntax here.\n\nvar win32Extensions = {\n  node: \".exe\",\n  npm: \".cmd\"\n};\n\n// The dev_bundle/bin command has to come immediately after the meteor\n// command, as in `meteor npm` or `meteor node`, because we don't want to\n// require(\"./main.js\") for these commands.\nvar devBundleBinCommand = process.argv[2];\n\nif (win32Extensions.hasOwnProperty(devBundleBinCommand)) {\n  var helpers = require(\"./dev-bundle-bin-helpers.js\");\n\n  if (process.platform === \"win32\") {\n    devBundleBinCommand += win32Extensions[devBundleBinCommand];\n  }\n\n  var cmd = helpers.getCommandPath(devBundleBinCommand);\n  var args = process.argv.slice(3);\n\n  exports.process = require(\"child_process\").spawn(cmd, args, {\n    stdio: \"inherit\",\n    env: helpers.getEnv()\n  });\n\n  require(\"./flush-buffers-on-exit-in-windows.js\");\n\n  exports.process.on(\"exit\", function (exitCode) {\n    process.exit(exitCode);\n  });\n}\n"
  },
  {
    "path": "tools/cli/dev-bundle-bin-helpers.js",
    "content": "var path = require(\"path\");\nvar devBundleDir = path.resolve(__dirname, \"..\", \"..\", \"dev_bundle\");\nvar binDir = path.join(devBundleDir, \"bin\");\n\nexports.getCommandPath = function (command) {\n  return path.join(binDir, command);\n};\n\nexports.getEnv = function () {\n  var env = Object.create(process.env);\n  var paths = [\n    // When npm looks for node, it must find dev_bundle/bin/node.\n    binDir,\n    // Also make available any scripts installed by packages in\n    // dev_bundle/lib/node_modules, such as node-gyp.\n    path.join(devBundleDir, \"lib\", \"node_modules\", \".bin\"),\n  ];\n\n  var PATH = env.PATH || env.Path;\n  if (PATH) {\n    paths.push(PATH);\n  }\n\n  env.PATH = paths.join(path.delimiter);\n\n  if (process.platform === \"win32\") {\n    // On Windows we provide a reliable version of python.exe for use by\n    // node-gyp (the tool that rebuilds binary node modules). #WinPy\n    env.PYTHON = env.PYTHON || path.join(\n      devBundleDir, \"python\", \"python.exe\");\n\n    // We don't try to install a compiler toolchain on the developer's\n    // behalf, but setting GYP_MSVS_VERSION helps select the right one.\n    env.GYP_MSVS_VERSION = env.GYP_MSVS_VERSION || \"2015\";\n\n    // While the original process.env object allows for case insensitive\n    // access on Windows, Object.create interferes with that behavior, so\n    // here we ensure env.PATH === env.Path on Windows.\n    env.Path = env.PATH;\n  }\n\n  return env;\n};\n"
  },
  {
    "path": "tools/cli/example-repositories.js",
    "content": "export const EXAMPLE_REPOSITORIES = {\n  clock: { repo: 'https://github.com/meteor/clock' },\n  leaderboard: { repo: 'https://github.com/meteor/leaderboard' },\n  localmarket: { repo: 'https://github.com/meteor/localmarket' },\n  'simple-todos': { repo: 'https://github.com/meteor/simple-todos' },\n  'simple-todos-react': {\n    repo: 'https://github.com/meteor/simple-todos-react'\n  },\n  'simple-todos-angular': {\n    repo: 'https://github.com/meteor/simple-todos-angular'\n  },\n  todos: { repo: 'https://github.com/meteor/todos' },\n  'todos-react': {\n    'repo': 'https://github.com/meteor/todos',\n    'branch': 'react',\n  },\n};\n"
  },
  {
    "path": "tools/cli/flush-buffers-on-exit-in-windows.js",
    "content": "// On Node 0.10 on Windows, stdout and stderr don't get flushed when calling\n// `process.exit`. We use a workaround for now, but this should be fixed on\n// Node 0.12, so when we upgrade let's remember to remove this clause, and the\n// file it requires. See https://github.com/joyent/node/issues/3584\nif (process.platform === \"win32\") {\n  require('../../packages/meteor/flush-buffers-on-exit-in-windows.js');\n}\n"
  },
  {
    "path": "tools/cli/help.txt",
    "content": ">>>\n(the first line of each entry is the summary for autogenerated command lists)\nUsage: meteor [--release <release>] [--help] <command> [args]\n       meteor help <command>\n       meteor [--version] [--arch]\n\nWith no arguments, 'meteor' runs the project in the current\ndirectory in local development mode. You can run it from the root\ndirectory of the project or from any subdirectory.\n\nUse 'meteor create <path>' to create a new Meteor project.\n\nCommands:\n{{commands}}\n\nSee 'meteor help <command>' for details on a command.\n\n\n>>> run\n[default] Run this project in local development mode.\nUsage: meteor run [target..] [options]\n\nSearches upward from the current directory for the root directory of a\nMeteor project, then runs that project in local development\nmode. You can use the application by pointing your web browser at\nlocalhost:3000. No internet connection is required.\n\nWhenever you change any of the application's source files, the changes\nare automatically detected and applied to the running application.\n\nThe application's database persists between runs. It's stored under\nthe .meteor directory in the root of the project.\n\nIf you have added a platform to your app with 'meteor add-platform', you can\npass one of the following targets as an argument to this command.\n\nTargets:\n  android          Run on the Android emulator.\n  android-device   Run on a connected Android device.\n  ios              Run on the iOS simulator.\n  ios-device       Open Xcode with the iOS project for this app, where you can\n                   run your app on a connected iOS device.\n\nOptions:\n  --port, -p       Port to listen on (instead of the default 3000). Also\n                   uses port N+1 and a port specified by --app-port.\n                   Specify as --port=host:port to bind to a specific interface.\n  --debug-port     Specify a port to enable server-side debugging. The\n                   server will be paused at startup, waiting for incoming\n                   connections from debugger clients on the specified port.\n  --mobile-server  Location where mobile builds connect to the Meteor server.\n                   Defaults to your local IP and the port that the Meteor\n                   server binds to. Can include a URL scheme (for\n                   example, --mobile-server=https://example.com:443).\n  --production     Simulate production mode. Minify and bundle CSS and JS files.\n  --raw-logs       Run without parsing logs from stdout and stderr.\n  --settings       Set optional data for Meteor.settings on the server.\n  --release        Specify the release of Meteor to use.\n  --verbose        Print all output from builds logs.\n  --no-lint        Don't run linters used by the app on every rebuild.\n  --allow-incompatible-update   Allow packages in your project to be upgraded or\n                   downgraded to versions that are potentially incompatible with\n                   the current versions, if required to satisfy all package\n                   version constraints.\n\n>>> debug\nRun the project, but suspend the server process for debugging.\n\nUsage: meteor debug [--debug-port <port>] [run options]\n       meteor run --debug-port <port> [run options]\n\nThe server process will be suspended just before the first statement of\nserver code that would normally execute. In order to continue execution of\nserver code, use either the web-based Node Inspector or the command-line\ndebugger (further instructions will be printed in the console).\n\nThe easiest way to set breakpoints is to use the `debugger` keyword:\nhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger\n\nThe options for 'meteor debug' are identical to those for 'meteor run',\nwith one addition:\n\nOptions:\n  --debug-port   Port on which the server process debugger should listen\n                 for incoming connections from debugging clients, such as\n                 node-inspector (default 5858).\n\n\n>>> create\nCreate a new project.\nUsage: meteor create [--release <release>] <path>\n       meteor create [--release <release>] --example <example_name> [<path>]\n       meteor create --list\n       meteor create --package [<package_name>]\n\nMake a subdirectory named <path> if it doesn't exist and create a new Meteor app\nthere. You can pass an absolute path, relative path, or '.' for the current\ndirectory.\n\nWith the --package option, creates a Meteor package instead of an app. If you're\nin an app, the package will go in the app's top-level 'packages' directory;\notherwise it will be created in the current directory.\n\nThe app will use the release of Meteor specified with the --release\noption, or the latest available version if the option is not specified. (A\npackage created in an app, will be created using the application's version of\nmeteor and a package created outside a meteor app will use the latest release).\n\nYou can pass --example to start off with a copy of one of the Meteor\nsample applications. Use --list to see the available examples. There are\ncurrently no package examples.\n\nOptions:\n  --package  Create a new meteor package instead of an app.\n  --example  Example template to use.\n  --list     Show list of available examples.\n\n\n>>> update\nUpgrade this project's dependencies to their latest versions.\nUsage: meteor update\n       meteor update --patch\n       meteor update --release <release>\n       meteor update --packages-only\n       meteor update [packageName packageName2 ...]\n\nUpdates the meteor release, and then, if applicable, updates the packages\nused by the app to the latest versions that don't cause dependency\nconflicts with other packages in the app.\n\nPassing the --patch argument will update to the latest patch, if such exists.\nPatch releases contain very minor changes, usually bug fixes. Updating to\nthe latest patch is always recommended. This will try to not update non-core\npackages unless strictly nessessary.\n\nPassing the --release argument will force update to a specific release of\nmeteor.  This will not update non-core packages unless strictly nessessary. It\nis also possible that some packages cannot be updated to be compatible with the\nnew release. If that happens, the app will not build until dependencies on those\npackages are removed.\n\nPassing --packages-only will try to update non-core packages to their latest\nversions. It will not update the version of meteor. To update individual\npackages (for example: 'foo:awesome') pass in their names instead, with no\noptions. ('meteor update foo:awesome').\n\nOptions:\n  --packages-only  Update the package versions only. Do not update the release.\n  --patch          Update the release to a patch release only.\n  --release        Update to a specific release of meteor.\n  --allow-incompatible-update   Allow packages in your project to be upgraded or\n                   downgraded to versions that are potentially incompatible with\n                   the current versions, if required to satisfy all package\n                   version constraints.\n\n\n>>> admin run-upgrader\nExecute a specific upgrader by name. Intended for testing.\nUsage: meteor admin run-upgrader <upgrader>\n\nRuns a specific upgrader on the current app. This is for testing\ninternal functionality of Meteor.\n\n\n>>> add\nAdd a package to this project.\nUsage: meteor add <package> [package..]\n\nAdds packages to your Meteor project. You can add multiple\npackages with one command. To query for available packages, use\nthe meteor search command.\n\nOptional version constraints can be added. Running `meteor add package@1.1.0`\nwill add the package at version 1.1.0 or higher (but not 2.0.0 or higher).\nIf you want to use version 1.1.0 exactly, use `meteor add package@=1.1.0`.\nYou can also 'or' constraints together: `meteor add 'package@=1.0.0 || =2.0.1'`\nmeans either 1.0.0 (exactly) or 2.0.1 (exactly).\n\nTo remove a version constraint for a specific package, run \"meteor add\" command\nagain without specifying a version. For example above, to stop using\nversion 1.1.0 exactly, run `meteor add package`.\n\nOptions:\n  --allow-incompatible-update   Allow packages in your project to be upgraded or\n                   downgraded to versions that are potentially incompatible with\n                   the current versions, if required to satisfy all package\n                   version constraints.\n\n\n>>> remove\nRemove a package from this project.\nUsage: meteor remove <package> [package..]\n\nRemoves a package previously added to your Meteor project. For a\nlist of the packages that your application is currently using, see\n'meteor list'.\n\nOptions:\n  --allow-incompatible-update   Allow packages in your project to be upgraded or\n                   downgraded to versions that are potentially incompatible with\n                   the current versions, if required to satisfy all package\n                   version constraints.\n\n\n>>> list\nList the packages explicitly used by your project.\nUsage: meteor list\n\nLists the packages that you have explicitly added to your project.\nThis will not list transitive dependencies.\n\n>>> add-platform\nAdd a platform to this project.\nUsage: meteor add-platform <platform> [platform..]\n\nAdds platforms to your Meteor project. You can add multiple\nplatforms with one command.\n\nAvailable platforms:\n  server\n  browser\n  android\n  ios (on OS X only)\n\nCurrently, the server and browser platforms are present in every\nMeteor project and cannot be removed.\n\n`meteor run` by default runs the server and browser platforms.\nAfter adding a mobile platform, you can use 'meteor run <mobile-platform>'\nto run on a mobile device or emulator. 'meteor build' will always build\nthe project for every added platform.\n\n>>> install-sdk\nInstalls SDKs for a platform.\nUsage: meteor install-sdk <platform>\n\nInstalls the SDK for a platform; will also verify that the platform\nrequirements are met.\n\nAvailable platforms:\n  android\n  ios (on OS X only)\n\n>>> remove-platform\nRemove a platform from this project.\nUsage: meteor remove-platform <platform> [platform..]\n\nRemoves a platform previously added to your Meteor project. For a\nlist of the platforms that your application is currently using, see\n'meteor list-platforms'.\n\n>>> list-platforms\nList the platforms added to your project.\nUsage: meteor list-platforms\n\nLists all of the platforms added to your project.\n\n>>> configure-android\nRun the Android configuration tool from Meteor's ADK environment.\nUsage: meteor configure-android\n\nRuns the Android configuration tool from Meteor's ADK environment.\nThis command can be useful to configure AVDs, HAX and update the SDK.\n\n>>> bundle\nDeprecated command. Use 'build' instead.\nUsage: meteor bundle <output_file.tar.gz>\n\nPack this project up into a tarball.\n\nThis command has been deprecated in favor of 'meteor build', which allows you to\nbuild for multiple platforms and outputs a directory instead of a single\ntarball. See 'meteor help build' for more information.\n\n\n>>> build\nBuild this project for all platforms.\nUsage: meteor build <output path> [--debug] [--directory] [--server-only]\n          [--mobile-settings settings.json] [--server http://example.com:3000]\n\nPackage this project up for deployment. The command outputs a directory with\nbuilds for all platforms in this project.\n\nIf you have added mobile platforms to your project with the\n'meteor add-platform' command, then the output directory will contain\nsubdirectories named 'android' (with the APK bundle and Android project\nsource) and/or 'ios' (with the Xcode project source).\n\nPass `--server-only` to skip building mobile apps, but still build the\n'web.cordova' client target so the server can support hot code push\nfor Cordova apps.\n\nThe output directory will contain a tarball that includes everything necessary\nto run the application server. (See README in the tarball for details.)\n\nOptions:\n  --debug             Build in debug mode (don't minify, etc).\n  --directory         Output a directory (rather than a tarball) for the\n                      application server bundle. If the output location exists,\n                      it will be recursively deleted first.\n  --server-only       Skip building mobile apps even if mobile platforms have\n                      been added.\n  --mobile-settings   Set optional data for the initial value of Meteor.settings\n                      in your mobile application. A new value for\n                      Meteor.settings can be set later by the server as part of\n                      hot code push.\n  --server            Location where mobile builds connect to the Meteor server.\n                      Defaults to localhost:3000. Can include a URL scheme\n                      (for example, --server=https://example.com:443).\n  --architecture      Builds the server for a different architecture than your\n                      developer machine's architecture. Valid architectures\n                      include os.osx.x86_64, os.linux.x86_64, and\n                      os.linux.x86_32.\n  --allow-incompatible-update   Allow packages in your project to be upgraded or\n                      downgraded to versions that are potentially incompatible\n                      with the current versions, if required to satisfy all\n                      package version constraints.\n\n\n>>> lint\nBuild this project and run the linters printing all errors and warnings.\nUsage: meteor lint\n\nRun through the whole build process for the app and run all linters the app\nuses. Outputs all build errors or linting warnings to the standard output.\n\nOptions:\n  --allow-incompatible-update   Allow packages in your project to be upgraded or\n                      downgraded to versions that are potentially incompatible\n                      with the current versions, if required to satisfy all\n                      package version constraints.\n\n\n>>> shell\nLaunch a Node REPL for interactively evaluating server-side code.\n\nUsage: meteor shell\n\nWhen `meteor shell` is executed in an application directory where a server\nis already running, it connects to the server and starts an interactive\nshell for evaluating server-side code.\n\nMultiple shells can be attached to the same server. If no server is\ncurrently available, `meteor shell` will keep trying to connect until it\nsucceeds.\n\nExiting the shell does not terminate the server. If the server restarts\nbecause a change was made in server code, or a fatal exception was\nencountered, the shell will restart along with the server. This behavior\ncan be simulated by typing `.reload` in the shell.\n\nThe shell supports tab completion for global variables like `Meteor`,\n`Mongo`, and `Package`. Try typing `Meteor.is` and then pressing tab.\n\nThe shell maintains a persistent history across sessions. Previously-run\ncommands can be accessed by pressing the up arrow.\n\n\n>>> mongo\nConnect to the Mongo database for the specified site.\nUsage: meteor mongo [--url]\n\nOpens a Mongo shell to view or manipulate collections.\n\nIf site is specified, this is the hosted Mongo database for the deployed\nMeteor site.\n\nIf no site is specified, this is the current project's local development\ndatabase. In this case, the current working directory must be a\nMeteor project directory, and the Meteor application must already be\nrunning.\n\nInstead of opening a shell, specifying --url (-U) will return a URL\nsuitable for an external program to connect to the database. For remote\ndatabases on deployed applications, the URL is valid for one hour.\n\nOptions:\n  --url, -U  return a Mongo database URL\n\n\n>>> reset\nReset the project state. Erases the local database.\nUsage: meteor reset\n\nReset the current project to a fresh state. Removes all local data.\n\n\n>>> deploy\nDeploy this project to Meteor.\nUsage: meteor deploy <site> [--settings settings.json] [--debug] [--delete]\n\nDeploys the project in your current directory to Meteor's servers.\n\nYou can deploy to any available name under 'meteor.com'\nwithout any additional configuration, for example,\n'myapp.meteor.com'. If you deploy to a custom domain, such as\n'myapp.mydomain.com', then you'll also need to configure your domain's\nDNS records. See the Meteor docs for details.\n\nThe --settings flag can be used to pass deploy-specific information to\nthe application. It will be available at runtime in Meteor.settings, but only\non the server. If the object contains a key named 'public', then\nMeteor.settings.public will also be available on the client. The argument\nis the name of a file containing the JSON data to use. The settings will\npersist across deployments until you again specify a settings file. To\nunset Meteor.settings, pass an empty settings file.\n\nThe --delete flag permanently removes a deployed application, including\nall of its stored data.\n\nOptions:\n  --delete, -D  permanently delete this deployment\n  --debug       deploy in debug mode (don't minify, etc)\n  --settings    set optional data for Meteor.settings\n  --allow-incompatible-update   Allow packages in your project to be upgraded or\n                downgraded to versions that are potentially incompatible with\n                the current versions, if required to satisfy all package version\n                constraints.\n\n\n>>> logs\nShow logs for specified site.\nUsage: meteor logs <site>\n\nRetrieves the server logs for the requested site.\n\n\n>>> authorized\nView or change authorized users and organizations for a site.\nUsage: meteor authorized <site> [--list]\n       meteor authorized <site> --add <username>\n       meteor authorized <site> --remove <username>\n       meteor authorized <site> --transfer <username>\n\nWithout an argument (or with --list), list the users and organizations that are\nadministrators for a particular site that was deployed with 'meteor deploy'\n\nFor free hosting:\n\nWith --add, add an authorized user or organization to a site. Use this to give\nyour collaborators the ability to work with your sites.\n\nWith --remove, remove an authorized user or organization from a site. You cannot\nremove yourself. (Ask someone else who is an authorized user to do it.)\n\nYou can only add or remove one authorized user at a time.\n\nFor Galaxy:\n\nWith --transfer, transfer the ownership of the application to a new user or\norganization.\n\nOptions:\n  --add         add an authorized user or organization (for free hosting)\n  --remove      remove an authorized user or organization (for free hosting)\n  --transfer    transfer the (Galaxy) app to a new user or organization\n  --list        list authorized users and organizations (the default)\n\n\n>>> claim\nClaim a site deployed with an old Meteor version.\nUsage: meteor claim <site>\n\nIf you deployed a site with an old version of Meteor that did not have\nsupport for developer accounts, you can use this command to claim that\nsite into your account. If you had set a password on the site you will\nbe prompted for it one last time.\n\n\n>>> login\nLog in to your Meteor developer account.\nUsage: meteor login [--email]\n\nPrompts for your username and password and logs you in to your Meteor\ndeveloper account. Pass --email to log in by email address rather than\nby username.\n\n\n>>> logout\nLog out of your Meteor developer account.\nUsage: meteor logout\n\nLog out of your Meteor developer account.\n\n\n>>> whoami\nPrints the username of your Meteor developer account.\nUsage: meteor whoami\n\nPrints the username of the currently logged-in Meteor developer.\n\nSee 'meteor login' to log into or 'meteor logout' to log out of your\nMeteor developer account.\n\n\n>>> test-packages\nTest one or more packages.\nUsage: meteor test-packages [--release <release>] [options] [package...]\n\nRuns unit tests for one or more packages. The results are shown in\na browser dashboard that updates whenever a relevant source file is\nmodified.\n\nPackages may be specified by name or by path. If a package argument\ncontains a '/', it is loaded from a directory of that name; otherwise,\nthe package name is resolved according to the usual package search\nalgorithm ('packages' subdirectory of the current app, $PACKAGE_DIRS\ndirectories, and core packages in that order). You can test any number\nof packages simultaneously. If you don't specify any package names\nthen all available packages will be tested.\n\nOpen the test dashboard in your browser to run the tests and see the\nresults. By default the URL is localhost:3000 but that can be changed\nwith --port.\n\nOptions:\n  --port, -p        Port to listen on (instead of the default 3000). Also\n                    uses port N+1 and N+2.\n  --debug-port      Specify a port to enable server-side debugging. The\n                    server will be paused before any tests run, waiting\n                    for incoming connections from debugger clients.\n  --mobile-server   If running tests in an emulator or on a mobile device,\n                    the location where mobile builds connect to the\n                    Meteor server. Defaults to your local IP and the\n                    port that the Meteor server binds to. Can include a\n                    URL scheme (for example,\n                    --mobile-server=https://example.com:443).\n  --production      Simulate production mode. Minify and bundle CSS, JS files.\n  --settings        Set optional data for Meteor.settings on the server\n\n  --ios,            Run tests in an emulator or on a mobile device. All of\n  --android,        the tests for client and server will run in addition to\n  --ios-device,     mobile-specific tests.\n  --android-device\n  --test-app-path   Set the directory in which to create a temporary app used\n                    for tests. Defaults to the system's temporary directory,\n                    usually /tmp.\n  --verbose         Print all output from builds logs.\n  --no-lint         Don't run linters used by the tested packages on every\n                    test app rebuild.\n>>> test\nTest the application\nUsage: meteor test --driver-package <driver> [options]\n       meteor test --full-app --driver-package <driver> [options]\n\nRuns tests against the application.\nWill start a special app based on a test driver (specified with\n--driver-package -- read more about driver packages at\nhttp://guide.meteor.com/testing.html#driver-packages) which handles the\ntask of running tests and displaying the results in the browser when you\nvisit it.\n\nIn normal test mode, no files in your application are eagerly loaded, aside\nfrom test files (files named *.test[s].* or *.spec[s].* placed anywhere\nin your application). You can import your app's modules from within your\ntests and use them as normal.\n\nIn \"full app\" test mode, your app is loaded as usual, and then made hidden,\nand your tests can inspect and effect the running state. Test files are\nloaded similarly to unit test mode, but must be called *.app-test[s].* or\n*.app-spec[s].*.\n\nOpen the test dashboard in your browser to run the tests and see the\nresults. By default the URL is localhost:3000 but that can be changed\nwith --port.\n\nRead more about testing your application in the Testing Article of the\nMeteor Guide - https://guide.meteor.com/testing.html\n\nOptions:\n  --port, -p        Port to listen on (instead of the default 3000). Also\n                    uses port N+1 and N+2.\n  --debug-port      Specify a port to enable server-side debugging. The\n                    server will be paused before any tests run, waiting\n                    for incoming connections from debugger clients.\n  --mobile-server   If running tests in an emulator or on a mobile device,\n                    the location where mobile builds connect to the\n                    Meteor server. Defaults to your local IP and the\n                    port that the Meteor server binds to. Can include a\n                    URL scheme (for example,\n                    --mobile-server=https://example.com:443).\n  --settings        Set optional data for Meteor.settings on the server\n\n  --ios,            Run tests in an emulator or on a mobile device. All of\n  --android,        the tests for client and server will run in addition to\n  --ios-device,     mobile-specific tests.\n  --android-device\n  --test-app-path   Set the directory in which to create a temporary app used\n                    for tests. Defaults to the system's temporary directory,\n                    usually /tmp.\n  --verbose         Print all output from builds logs.\n\n>>> self-test\nRun tests of the 'meteor' tool.\nUsage: meteor self-test [pattern] [--list] [--file pattern] [--changed]\n                        [--slow] [--force-online] [--history n]\n                        [--browserstack]\n\nRuns internal tests. Exits with status 0 on success.\n\nIf 'pattern' is provided, it should be a regular expression. Only\ntests that match the regular expression will be run.\n\nUse --list to list the tests that would be run according to the other\noptions, without running them.\n\nPass --file to run only tests in files that match the regular expression.\n\nPass --changed to run only tests that have changed since they last\npassed. This uses a really rough heuristic: A test has changed iff\nthere has been any change to the file in the 'selftests' subdirectory\nthat defines it. State for this is tracked in ~/.meteortest.\n\nSome tests are really slow. Test flagged as slow won't be run unless\nyou pass --slow. Remember to do this from time to time!\n\nNormally, this command detects whether you are offline and skips tests that\nrequire network access automatically. If you want to try to run them anyway,\npass --force-online.\n\nUse --history to change the number of lines of program output that are\nshown on test failure. The default is 10.\n\nPass --browserstack to enable client side tests using BrowserStack.\n--browserstack requires s3cmd credentials.\n\n\n\n>>> open-ide\nOpen mobile build project in associated IDE.\nUsage: meteor open-ide [ios]\n\nOpen mobile build project in associated IDE.\n\n\n>>> admin\nAdministrative commands.\nUsage: meteor admin <command> [args]\n       meteor help admin <command>\n\nRarely used commands for administering official Meteor services.\n\nCommands:\n{{commands}}\n\nSee 'meteor help admin <command>' for details on an admin command.\n\n>>> admin make-bootstrap-tarballs\nMakes bootstrap tarballs.\nUsage: meteor admin make-bootstrap-tarballs release@version /tmp/tarballdir\n\nFor internal use only.\n\n\n>>> dummy\nDummy command used for automated testing.\nUsage: meteor dummy [options]\n\nDummy command used for automated testing.\n\nOptions:\n  --ething, -e  A required string option.\n  --port, -p   A numeric option with a short alias.\n  --changed    A boolean option.\n\n\n>>> cordova\nRun cordova commands.\nUsage: meteor cordova <command>\n\n\n>>> list-sites\nList sites for which you are authorized.\nUsage: meteor list-sites\n\nList the sites that you have deployed with 'meteor deploy', and sites\nfor which other users have authorized you with the 'meteor authorized'\ncommand.\n\n\n>>> publish-release\nPublish a new meteor release to the package server.\n\nUsage: meteor publish-release <path to json config> [--create-track]\n\nPublishes a new release to the package server, as determined by the json\nconfiguration file, which must have the following keys:\n  track: the release track to which you are publishing (ex: METEOR)\n  version: the version of this release\n  recommended: is this a recommended release? (see below)\n  description: a brief description of the release\n  patchFrom: (Optional) releases from which this is a patch (array of strings)\n  tool: <package name>@<version> of the meteor tool that this release specifies\n  packages: object of <package name> to <version> for specified package versions\n\nSet the recommended flag to true for recommended releases (ex: METEOR@0.90)\nand false for release candidates, experimental releases, etc. You must publish\nall package versions to the package server before you can specify them in a\nrelease.\n\nUse the patchFrom flag to submit a patch release. This will automatically\nunrecommend the releases specified by the patchFrom flag.\n\nUse the --create-track to publish a new release track.\n\nOptions:\n  --create-track  publish a new release track.\n\n\n>>> publish\nPublish a new version of a package to the package server.\n\nUsage: meteor publish [--create]\n       meteor publish --update\n\nPublishes a new version of a local package to the package server. Must be run\nfrom the directory containing the package. Reads the package.js file for version\ninformation, builds the package and sends both the package source and the built\nversion of the package to the package server.\n\nThis will create at most one build of the package. If the package has an\nOS-dependent binary component, publishing will only register metadata about the\npackage. To actually publish the package builds, use `meteor admin get-machine`\nand `meteor publish-for-arch`. Packages with no published builds cannot be added\nto applications.\n\nThis will mark you as the only maintainer of the package. You can use\n'meteor admin maintainers' to change package maintainers. For more information\nabout admin commands, run 'meteor help admin'.\n\nChange the metadata for a given version of a package by running with the\n--update flag. That will set the git url, version summary, longform description\nand documentation in the database to their new values. You can use 'meteor show'\nto preview the results.\n\nPass --create to create a new package.\n\nOptions:\n  --create   publish a new package\n  --update   changed metadata of a previously published version\n  --allow-incompatible-update   Allow packages in your project to be upgraded or\n             downgraded to versions that are potentially incompatible with the\n             current versions, if required to satisfy all package version\n             constraints.\n  --no-lint  don't run linters on the published package and its local\n             dependencies before publishing\n\n\n>>> publish-for-arch\nBuilds an already-published package for a new platform.\n\nUsage: meteor publish-for-arch packageName@version\n\nWhen you publish a package with 'meteor publish' for a package which has\nplatform-specific components (eg, npm modules with native code), the package\nwill only be usable on machines of the same architecture that you are currently\non. To make your package's version usable on other architectures, you can use\nthe publish-for-arch command.  (The architectures currently supported by Meteor\nare 32-bit Linux, 64-bit Linux, and 64-bit OS X; the 'meteor deploy' servers use\n64-bit Linux.)\n\nOn a machine of the appropriate architecture, install Meteor and run\n  $ meteor publish-for-arch packageName@version\n\nYou don't need to have a copy of your package's source to do this: Meteor will\nautomatically download your package's source and dependencies from the package\nserver.\n\n\n>>> rebuild\nRebuild local packages.\nUsage: meteor rebuild [<package name>...]\n\nRebuild specified local packages. Deletes the package's build directory\nand rebuilds the package from scratch. Packages are specified by name.\n\nIf you pass no arguments, this will rebuild all local packages.\nThat includes packages found through the\nPACKAGE_DIRS environment variable, local packages in the current\napplication, and, if running Meteor from a checkout, the packages in\nthe checkout. It doesn't include any packages for which we don't have\nthe source.\n\nYou should never need to use this command. It is intended for use while\ndebugging the Meteor packaging tools themselves.\n\n\n>>> search\nSearch through the package server database.\nUsage: meteor search <regex> [--maintainer <username>] [--show-all]\n\nSearches through the Meteor package and release database for items whose names\nmatch the regular expression. You can use the --maintainer option to filter for\nitems maintained by a particular developer.\n\nBy default, this will not show packages that have no official versions\n(for example, those that have only prereleases). It will also hide packages\nthat, due to migration issues, are known to be incompatible with Meteor 0.9.0\nand later. You can use the --show-all option to see hidden packages.\n\nOptions:\n  --maintainer    filter by authorized maintainer\n  --show-all      show all matches, even prereleases\n  --ejson         show more detailed output in EJSON format\n\n\n>>> show\nShow detailed information about a release or package.\nUsage: meteor show <name> [--show-all] [--ejson]\n       meteor show <name@version> [--ejson]\n       meteor show [--ejson]\n\nShow detailed information on a specific package or release, including\na list of available versions. This works on packages built locally from source,\nas well as remote packages stored on the server.  For version-specific information,\nsuch as the list of exports, Meteor will use the local version, if one is available,\nor the latest official version.\n\nUse <name>@<version> to get more information about a specific version of a\npackage or release. Use '<name>@local' to see information from a\nlocal version. Running from a package source directory with no arguments will\nshow information for that package version.\n\nBy default, Meteor will not show more than five versions, and will not\nshow experimental release versions. Meteor will also hide packages that\nare known to not be compatible with  Meteor 0.9.0 and later. Running with the\n--show-all option will show everything.\n\nOptions:\n  --ejson         show more detailed output in EJSON format\n  --show-all      show hidden versions of packages and releases\n\n\n>>> admin maintainers\nView or change package maintainers.\nUsage: meteor admin maintainers <package name> [--list]\n       meteor admin maintainers <package name> --add <username>\n       meteor admin maintainers <package name> --remove <username>\n\nWithout options (or with --list), list the users and organizations that are\nmaintainers for a particular package.\n\nWith --add, add an authorized maintainer to a package. Use this to give your\ncollaborators the ability to work with your packages.\n\nWith --remove, remove an authorized maintainer from a package. You cannot remove\nyourself if you are the last maintainer on a package.\n\nYou can only add or remove one maintainer at a time.\n\nOptions:\n  --add         add an authorized maintainer\n  --remove      remove an authorized maintainer\n  --list        list authorized maintainers (the default)\n\n\n>>> admin recommend-release\nRecommend a previously published release.\nUsage: meteor admin recommend-release\n         <release track>@<release version> [--unrecommend]\n\nRecommend a version of a meteor release. Users can be upgraded to recommended\nreleases automatically when they run meteor update. Users will never be updated\nto unrecommended releases unless they explicitly specify that release with a\n--release argument.\n\nUse unrecommended releases for release candidates, one-of experiments, etc. Use\nrecommended releases for official supported releases.\n\nOptions:\n  --unrecommend         unrecommend a previously recommended release\n\n\n>>> admin change-homepage\nChange the homepage url of a package.\nUsage: meteor admin change-homepage <package name> <new url>\n\nChange the homepage containing package information.\n\n\n>>> admin set-unmigrated\nSet the package as unmigrated.\nUsage: meteor admin set-unmigrated <package name> [--success]\n       meteor admin set-unmigrated <package name>@<version> [--success]\n\nSet a version of a package, as unmigrated: make it invisible in search and show,\nwithout a special option. (You should use this to hide packages that have been\nrenamed in the aftermath of the 0.9.0 migration.) This will not stop the users\nfrom adding the package to their app.\n\nIf no version is passed in, all versions will be set. Use the --success option\nto mark the package version as successfully migrated, making it show up again.\n\nOptions:\n  --success         mark the package as successfully migrated.\n\n\n>>> admin set-banners\nSet banners on published releases.\nUsage: meteor admin set-banners <path to banner configuration>\n\nSet the banners on previously published releases. Banners notify the user\nwhen there is a new release available or a patch release has been published.\n\n>>> admin list-organizations\nList the organizations of which you are a member.\nUsage: meteor list-organizations\n\nList the organizations of which you are a member.\n\n>>> admin members\nView or change the members of an organization.\nUsage: meteor admin members <organization name> [--list]\n       meteor admin members <organization name> --add <username>\n       meteor admin members <organization name> --remove <username>\n\nWithout options, list the members of an organization. With --add or --remove,\nadd or remove a member of an organization.\n\nOptions:\n  --add         add a member to the organization\n  --remove      remove a member from the organization\n  --list        list members of the organization (the default)\n\n>>> admin set-latest-readme\nSet the readme on the latest version of a core meteor package.\nUsage: meteor admin set-latest-core-readme name --commit commit\n       meteor admin set-latest-core-readme name --tag tag\n\nSet the readme field on the latest published version of a core package to the\nreadme at a given git commit, or the readme at a given git tag.\n\n>>> admin get-machine\nOpen an ssh shell to a machine in the meteor build farm.\nUsage: meteor admin get-machine <arch> [--json] [--verbose] [--minutes min]\n\nAsks the meteor build farm for a build server and opens a secure shell to it.\n\nValid machine architectures are:\n  os.osx.x86_64\n  os.linux.x86_64\n  os.linux.x86_32\n  os.windows.x86_32\n\nOptions:\n  --json       return information in JSON form instead of opening a shell\n  --minutes    specify the length of the reservation\n  --verbose    print all output from commands\n"
  },
  {
    "path": "tools/cli/main.js",
    "content": "var showRequireProfile = ('METEOR_PROFILE_REQUIRE' in process.env);\nif (showRequireProfile) {\n  require('../tool-env/profile-require.js').start();\n}\n\nvar assert = require(\"assert\");\nvar _ = require('underscore');\nvar Fiber = require('fibers');\nvar Console = require('../console/console.js').Console;\nvar files = require('../fs/files.js');\nvar warehouse = require('../packaging/warehouse.js');\nvar tropohouse = require('../packaging/tropohouse.js');\nvar release = require('../packaging/release.js');\nvar projectContextModule = require('../project-context.js');\nvar catalog = require('../packaging/catalog/catalog.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar httpHelpers = require('../utils/http-helpers.js');\n\nvar main = exports;\n\nrequire('./flush-buffers-on-exit-in-windows.js');\n\n// node (v8) defaults to only recording 10 lines of stack trace. This\n// is especially insufficient when using fibers, because you get\n// proper call stacks instead of only seeing the stack up to the most\n// recent callback invocation. Increase the limit (for the `meteor` tool\n// itself, not for apps).\n//\n// http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi\nError.stackTraceLimit = Infinity;\n\n///////////////////////////////////////////////////////////////////////////////\n// Command registration\n///////////////////////////////////////////////////////////////////////////////\n\nfunction Command(options) {\n  assert.ok(this instanceof Command);\n\n  options = _.extend({\n    minArgs: 0,\n    options: {},\n    allowUnrecognizedOptions: false,\n    requiresApp: false,\n    requiresPackage: false,\n    requiresAppOrPackage: false,\n    requiresRelease: true,\n    hidden: false,\n    pretty: true,\n    notOnWindows: false\n  }, options);\n\n  if (! _.has(options, 'maxArgs')) {\n    options.maxArgs = options.minArgs;\n  }\n\n  _.each([\"name\", \"func\"], function (key) {\n    if (! _.has(options, key)) {\n      throw new Error(\"command missing '\" + key + \"'?\");\n    }\n  });\n\n  _.extend(this, options);\n\n  _.each(this.options, function (value, key) {\n    if (key === \"args\" || key === \"appDir\") {\n      throw new Error(options.name + \": bad option name \" + key);\n    }\n    if (! _.has(value, 'type')) {\n      value.type = String;\n    }\n    if (_.has(value, 'default') && _.has(value, 'required')) {\n      throw new Error(options.name + \": \" + key + \" can't be both optional \" +\n                      \"and required\");\n    }\n    if (_.has(value, 'short') && value.short.length !== 1) {\n      throw new Error(options.name + \": \" + key + \" has a bad short option\");\n    }\n  });\n};\n\n// Various registerCommand options such as requiresApp can be specified to\n// either as a constant value or as a function dependent on the parsed\n// command-line options object.\nCommand.prototype.evaluateOption = function (optionName, options) {\n  var self = this;\n  if (typeof self[optionName] === 'function') {\n    return self[optionName](options);\n  }\n  return self[optionName];\n};\n\n// map from command name to a Command, or to a subcommand map (a map\n// of subcommand names to either Commands or further submaps).\n//\n// Options that function as commands (eg, \"meteor --arch\") are treated\n// as subcommands of \"--\".\nvar commands = {};\n\n// Exception to throw from a command to bail out and show command\n// usage information.\nmain.ShowUsage = function ShowUsage() {\n  assert.ok(this instanceof ShowUsage);\n};\n\n// Exception to throw from a helper function inside a command which is identical\n// to returning the given exit code from the command.  ONLY USE THIS IN HELPERS\n// THAT ARE ONLY CALLED DIRECTLY FROM COMMANDS! DON'T BE LAZY AND PUT THROW OF\n// THIS IN RANDOM LIBRARY CODE!\nmain.ExitWithCode = function ExitWithCode(code) {\n  assert.ok(this instanceof ExitWithCode);\n  this.code = code;\n};\n\n_.extend(main.ExitWithCode.prototype, {\n  toString: function () {\n    var self = this;\n    return \"ExitWithCode:\" + self.code;\n  }\n});\n\n// Exception to throw to skip the process.exit call.\nmain.WaitForExit = function WaitForExit() {\n  assert.ok(this instanceof WaitForExit);\n};\n\n// Exception to throw from a command to exit, restart, and reinvoke\n// the command with the latest available (downloaded) Meteor release.\n// If track is specified, it uses the latest available in the given\n// track instead of the default track.\nmain.SpringboardToLatestRelease =\nfunction SpringboardToLatestRelease(track) {\n  assert.ok(this instanceof SpringboardToLatestRelease);\n  this.track = track;\n};\n\n// Exception to throw from a command to exit, restart, and reinvoke\n// the command with the given Meteor release.\nmain.SpringboardToSpecificRelease =\nfunction SpringboardToSpecificRelease(fullReleaseName, msg) {\n  assert.ok(this instanceof SpringboardToSpecificRelease);\n  this.fullReleaseName = fullReleaseName;\n  this.msg = msg;\n};\n\n// Register a command-line command.\n//\n// options:\n// - name\n//   - can be a basic command, like \"deploy\"\n//   - can be a subcommand, like \"admin grant\"\n//     (distinguished by presence of ' ')\n//   - can be an option that functions as a command, like \"--arch\"\n//     (distinguished by starting with '--')\n// - minArgs: minimum non-option arguments that can be present (default 0)\n// - maxArgs: maximum non-option arguments that can be present (defaults to\n//   whatever value you passed for minArgs; use Infinity for unlimited)\n// - catalogRefresh: strategy object specifying when to refresh the catalog.\n// - options: map from long option name to:\n//   - type: String, Number, or Boolean. default is String. a future\n//     version could support [String] and [Number] to allow the option to\n//     be passed more than once, but we don't do that yet.\n//   - short: single character short alias (eg, 'p' for 'port', to do -p 3000)\n//   - default: value to use if none supplied\n//   - required: true if required (incompatible with 'default')\n// - requiresApp: does this command work with an app? possible values\n//   (defaults to false):\n//   - true if an app is required, and command must be run inside an\n//     app. The command will be run using the app's Meteor release\n//     (unless overridden by --release or a checkout). An 'appDir'\n//     option will be passed with the absolute path to the app's\n//     top-level directory, and an error will be printed if the\n//     command isn't run from inside an app.\n//   - false if an app is not required. But if the command does happen\n//     to have been run from an app, 'appDir' will be\n//     provided. Moreover, in that case, we will still use the version\n//     of this program that goes with the Meteor release of the\n//     app. This is not ideal but is necessary for 'meteor help' to\n//     behave in a sane way in our current system. (XXX In the future\n//     we should separate the build system out into a package that is\n//     versioned with the release, and then take the CLI tool out of\n//     the release and always use the latest available version.)\n//   - function: some apps determine whether they use an app based on\n//     their arguments (eg, 'deploy' versus 'deploy --delete'). for\n//     these, set requiresApp to a function that takes 'options' (same as\n//     would be received by the actual command function) and returns\n//     true or false.\n// - requiresPackage: defaults to false.\n// - requiresAppOrPackage: a combination of two options above, true/false.\n// - requiresRelease: defaults to true. Set to false if this command\n//   doesn't need a functioning Meteor release to be available (that\n//   is, if the command does not need the ability to resolve\n//   packages). There is only one case where this comes up: if you\n//   create an app with a checkout (so that it has no release), and\n//   then run that app with released Meteor. Normally this just prints\n//   an error saying that you have to pick a release, but you can\n//   disable that by setting this flag to false. Even if you set this\n//   flag, we will still *attempt* to run the correct Meteor release\n//   just like we always do; it's just that in that one case, instead\n//   of bailing out with an error we will run your command with\n//   release.current === null.\n// - hidden: do not show in command list in help\n//\n// An error will be printed if an unrecognized option is passed on the\n// command line (eg, '--foo' when you don't have a 'foo' key in\n// options.options), or a required option is missing, or the number of\n// other arguments isn't as required by minArgs / maxArgs.\n//\n// func: function to call when the command is chosen. receives one\n// argument, an options dictionary that contains:\n// - the values of any 'options' that were provided\n// - args: an array of the other command-line arguments\n// - appDir: if run from inside an app tree, the absolute path to the\n//   app's top-level directory\n//\n// func should do one of the following:\n// - On success, return undefined (or 0). This indicates successful\n//   completion, and the program will exit with status 0.\n// - On failure, return a positive number. The program will exit with that\n//   status.\n// - If the command-line arguments aren't valid, 'throw new\n//   main.ShowUsage'. This will print usage info for the command and\n//   exit with status 1.\n// - If you have started (for example) a subprocess or worker fiber\n//   and want to wait until it's finished to exit, 'throw new\n//   main.WaitForExit'. This will skip the call to process.exit and the\n//   program will keep running until node thinks that everything is\n//   done.\n// - To quit, restart, and rerun the command with a latest available\n//   (downloaded) Meteor release, 'throw new main.SpringboardToLatestRelease'.\n//\n// Commands should never call process.exit()! They should instead\n// return an appropriate value.\n\nmain.registerCommand = function (options, func) {\n  options = _.clone(options);\n  options.func = func;\n\n  var nameParts = options.name.trim().split(/\\s+/);\n  options.name = nameParts.join(' ');\n\n  if (nameParts[0].indexOf('--') === 0) {\n    // \"--foo\" -> \"--\" \"foo\"\n    nameParts[0] = nameParts[0].substr(2);\n    nameParts.unshift('--');\n  }\n\n  var target = commands;\n  while (nameParts.length > 1) {\n    var part = nameParts.shift();\n    if (! _.has(target, part)) {\n      target[part] = {};\n    }\n    target = target[part];\n  }\n\n  if (_.has(target, nameParts[0])) {\n    throw Error(\"Duplicate command: \" + options.name);\n  }\n\n  if (!options.catalogRefresh) {\n    throw Error(\"Command does not select a catalogRefresh strategy: \" +\n                options.name);\n  }\n\n  target[nameParts[0]] = new Command(options);\n};\n\nmain.captureAndExit = function (header, title, f) {\n  var messages;\n  if (f) {\n    messages = buildmessage.capture({ title: title }, f);\n  } else {\n    messages = buildmessage.capture(title);  // title is really f\n  }\n  if (messages.hasMessages()) {\n    Console.error(header);\n    Console.printMessages(messages);\n    throw new main.ExitWithCode(1);\n  }\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Load all the commands\n///////////////////////////////////////////////////////////////////////////////\n\n// NB: files required up to this point may not define commands\n\nrequire('./commands.js');\nrequire('./commands-packages.js');\nrequire('./commands-packages-query.js');\nrequire('./commands-cordova.js');\nrequire('./commands-aliases.js');\n\n///////////////////////////////////////////////////////////////////////////////\n// Long-form help\n///////////////////////////////////////////////////////////////////////////////\n\n// Returns an array of entries with keys:\n// - name (entry name, typically a command name)\n// - body (contents of body, trimmed to end with a newline but no blank lines)\nvar loadHelp = function () {\n  var dirname = files.convertToStandardPath(__dirname);\n  var raw = files.readFile(files.pathJoin(dirname, 'help.txt'), 'utf8');\n  return _.map(raw.split(/^>>>/m).slice(1), function (r) {\n    var lines = r.split('\\n');\n    var name = lines.shift().trim();\n    return {\n      name: name,\n      body: lines.join('\\n').replace(/\\s*$/, '') + '\\n'\n    };\n  });\n};\n\nvar longHelp = exports.longHelp = function (commandName) {\n  commandName = commandName.trim();\n  var parts = commandName.length ? commandName.split(' ') : [];\n  var node = commands;\n  _.each(parts, function (part) {\n    if (! _.has(node, part)) {\n      throw new Error(\"walked off edge of command tree?\");\n    }\n    node = node[part];\n  });\n\n  var help = loadHelp();\n\n  // can use to see if there is help text for a particular command\n  var helpDict = {};\n  _.each(help, function (helpEntry) {\n    helpDict[helpEntry.name] = helpEntry;\n  });\n\n  var commandList = null;\n  if (! (node instanceof Command)) {\n    commandList = '';\n    var commandsWanted = {};\n\n    _.each(node, function (n, shortName) {\n      var fullName = commandName + (commandName.length > 0 ? \" \" : \"\") +\n        shortName;\n\n      // Use helpDict to only include commands that have help text, otherwise\n      // there is nothing to display.\n      // For now, there's no way to mark commands with subcommands (eg 'admin')\n      // as hidden.\n      if (! n.hidden && helpDict[fullName]) {\n        commandsWanted[fullName] = { name: shortName };\n      }\n    });\n\n    var maxNameLength = _.max(_.map(commandsWanted, function (c) {\n      return c.name.length;\n    }));\n\n    // Assemble help text for subcommands.. in the order they appear\n    // in the help file\n    _.each(help, function (helpEntry) {\n      if (_.has(commandsWanted, helpEntry.name)) {\n        var shortName = commandsWanted[helpEntry.name].name;\n        commandList += \"   \" + shortName +\n          new Array(maxNameLength + 1).join(' ').substr(shortName.length) +\n          \"   \" + helpEntry.body.split('\\n')[0] + \"\\n\";\n      }\n    });\n\n    // Remove trailing newline so that you can write \"{{commands}}\" on\n    // a line by itself and it does what you think it would\n    commandList = commandList.substr(0, commandList.length - 1);\n  }\n\n  var entry = _.find(help, function (c) {\n    return c.name === commandName;\n  });\n  if (! entry) {\n    throw new Error(\"help missing for \" + commandName + \"?\");\n  }\n  var ret = entry.body.split('\\n').slice(1).join('\\n');\n  if (commandList !== null) {\n    ret = ret.replace('{{commands}}', commandList);\n  }\n\n  return ret;\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Springboarding\n///////////////////////////////////////////////////////////////////////////////\n\n// Exit and restart the program, with the same arguments, but using a\n// different version of the tool and/or forcing a particular release.\n//\n// - release: required. the version of the tool to run.\n//\n// options:\n// - releaseOverride: optional. if provided, a release name to force\n//   us to use when restarting (this functions exactly like --release\n//   and will cause release.forced to be true).\n// - fromApp: this release was suggested because it is the app's\n//   release.  affects error messages.\nvar springboard = function (rel, options) {\n  options = options || {};\n  if (process.env.METEOR_DEBUG_SPRINGBOARD) {\n    console.log(\"WILL SPRINGBOARD TO\", rel.getToolsPackageAtVersion());\n  }\n\n  var archinfo = require('../utils/archinfo.js');\n  var isopack = require('../isobuild/isopack.js');\n\n  var toolsPkg = rel.getToolsPackage();\n  var toolsVersion = rel.getToolsVersion();\n  var packageMapModule = require('../packaging/package-map.js');\n  var versionMap = {};\n  versionMap[toolsPkg] = toolsVersion;\n  var packageMap = new packageMapModule.PackageMap(versionMap);\n\n  if (process.platform === \"win32\") {\n    // Make sure the tool we are trying to download has been built for Windows\n    var buildsForHostArch = catalog.official.getBuildsForArches(\n      rel.getToolsPackage(), rel.getToolsVersion(), [archinfo.host()]);\n\n    if (! buildsForHostArch) {\n      var release = catalog.official.getDefaultReleaseVersion();\n      var releaseName = release.track + \"@\" + release.version;\n\n      Console.error(\n        \"This project uses \" + rel.getDisplayName() + \", which isn't\",\n        \"available on Windows. To work with this app on all supported\",\n        \"platforms, use\", Console.command(\"meteor update --release \" + releaseName),\n        \"to pin this app to the newest Windows-compatible release.\");\n\n      process.exit(1);\n    }\n  }\n\n  // XXX split better\n  Console.withProgressDisplayVisible(function () {\n    var messages = buildmessage.capture(\n      { title: \"downloading the command-line tool\" }, function () {\n        catalog.runAndRetryWithRefreshIfHelpful(function () {\n          tropohouse.default.downloadPackagesMissingFromMap(packageMap);\n        });\n      }\n    );\n\n    if (messages.hasMessages()) {\n      // We have failed to download the tool that we are supposed to springboard\n      // to! That's bad. Let's exit.\n      if (options.fromApp) {\n        Console.error(\n          \"Sorry, this project uses \" + rel.getDisplayName() + \", which is\",\n          \"not installed and could not be downloaded. Please check to make\",\n          \"sure that you are online.\");\n      } else {\n        Console.error(\n          \"Sorry, \" + rel.getDisplayName() + \" is not installed and could not\",\n          \"be downloaded. Please check to make sure that you are online.\");\n      }\n\n      process.exit(1);\n    }\n  });\n\n  var packagePath = tropohouse.default.packagePath(toolsPkg, toolsVersion);\n  var toolIsopack = new isopack.Isopack;\n  toolIsopack.initFromPath(toolsPkg, packagePath);\n  var toolRecord = _.findWhere(toolIsopack.toolsOnDisk,\n                               {arch: archinfo.host()});\n  if (!toolRecord) {\n    throw Error(\"missing tool for \" + archinfo.host() + \" in \" +\n                toolsPkg + \"@\" + toolsVersion);\n  }\n  var executable = files.pathJoin(packagePath, toolRecord.path, 'meteor');\n\n  // Strip off the \"node\" and \"meteor.js\" from argv and replace it with the\n  // appropriate tools's meteor shell script.\n  var newArgv = process.argv.slice(2);\n\n  if (_.has(options, 'releaseOverride')) {\n    // We used to just append --release=<releaseOverride> to the arguments, and\n    // though that's probably safe in practice, it makes us worry about things\n    // like other --release options.  So now we use an environment\n    // variable. #SpringboardEnvironmentVar\n    process.env['METEOR_SPRINGBOARD_RELEASE'] = options.releaseOverride;\n  }\n\n  if (process.platform === 'win32') {\n    process.exit(new Promise(function (resolve) {\n      var batPath = files.convertToOSPath(executable + \".bat\");\n      var child = require(\"child_process\").spawn(batPath, newArgv, {\n        env: process.env,\n        stdio: 'inherit'\n      }).on('exit', resolve);\n    }).await());\n  }\n\n  // Now exec; we're not coming back.\n  require('kexec')(executable, newArgv);\n  throw Error('exec failed?');\n};\n\n// Springboard to a pre-0.9.0 release.\nvar oldSpringboard = function (toolsVersion) {\n  // Strip off the \"node\" and \"meteor.js\" from argv and replace it with the\n  // appropriate tools's meteor shell script.\n  var newArgv = process.argv.slice(2);\n  var cmd =\n    files.pathJoin(warehouse.getToolsDir(toolsVersion), 'bin', 'meteor');\n\n  // Now exec; we're not coming back.\n  require('kexec')(cmd, newArgv);\n  throw Error('exec failed?');\n};\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Main entry point\n///////////////////////////////////////////////////////////////////////////////\n\n// This is the main function that runs when you type 'meteor'.\n\n// It's mostly concerned with validating command-line arguments,\n// finding the requested command in the commands table, and making\n// sure that you're using the version of the Meteor tools that match\n// your project.\n\nFiber(function () {\n  // If running inside the Emacs shell, set stdin to be blocking,\n  // reversing node's normal setting of O_NONBLOCK on the evaluation\n  // of process.stdin (because Node unblocks stdio when forking). This\n  // fixes execution of Mongo from within Emacs shell.\n  if (process.env.EMACS == \"t\") {\n    process.stdin;\n    var child_process = require('child_process');\n    child_process.spawn('true', [], {stdio: 'inherit'});\n  }\n\n  // Check required Node version.\n  // This code is duplicated in tools/server/boot.js.\n  var MIN_NODE_VERSION = 'v0.10.41';\n  if (require('semver').lt(process.version, MIN_NODE_VERSION)) {\n    Console.error(\n      'Meteor requires Node ' + MIN_NODE_VERSION + ' or later.');\n    process.exit(1);\n  }\n\n  // Set up git hooks, but not on Windows because they don't work there and it;s\n  // not worth setting it up at the moment\n  if (files.inCheckout() && process.platform !== \"win32\") {\n    var installGitHooks = require('../tool-env/install-git-hooks.js')['default'];\n    installGitHooks();\n  }\n\n  // This is a bit of a hack, but: if we don't check this in the tool, then the\n  // first time we do a isopack.load, it will fail due to the check in the\n  // meteor package, and that'll look a lot uglier.\n  if (process.env.ROOT_URL) {\n    var parsedUrl = require('url').parse(process.env.ROOT_URL);\n    if (!parsedUrl.host) {\n      Console.error('$ROOT_URL, if specified, must be an URL.');\n      process.exit(1);\n    }\n  }\n\n  // Parse the arguments.\n  //\n  // We must first identify which options are boolean and which take\n  // arguments (which must be consistent across all defined\n  // commands). This is necessary to resolve cases like 'meteor --flag\n  // stuff thing'. Is the command 'stuff' with a boolean option\n  // 'flag', or in the command 'thing' with an option 'flag' that is\n  // set to 'stuff'? To resolve this we require that 'flag' be\n  // consistently declared as a boolean (or not a boolean) across all\n  // commands.\n  //\n  // XXX The problem with the above is that which commands are boolean\n  // may change across releases, and when we springboard, we actually\n  // have to parse the options with the *target* version's\n  // semantics. All in all, I think we might be better served to\n  // require options to come after the command, other than special\n  // options (--release, --help, and options that act as\n  // commands). Then we don't have to require consistency of boolean\n  // status between commands; we instead have to require consistency\n  // of boolean status of a particular option, for a command, across\n  // releases. Since we always start out by running the latest version\n  // of Meteor, which can have knowledge of all past versions\n  // (including the boolean status of formerly present but removed\n  // options, including options to removed commands), this should let\n  // us be 100% correct. (Of course, we could still do this if we\n  // required options to be consistent across commands as well, but I\n  // think this is a better tradeoff.) In this model, we'd do option\n  // parsing in two passes, where the first pass just pulls out the\n  // command, and the second parses the arguments with knowledge of\n  // the command. I would make this change right now but we're on a\n  // tight timetable for 1.0 and there is no advantage to doing it now\n  // rather than later. #ImprovingCrossVersionOptionParsing\n\n  var isBoolean = { \"--help\": true };\n  var walkCommands = function (node) {\n    _.each(node, function (value, key) {\n      if (value instanceof Command) {\n        _.each(value.options || {}, function (optionInfo, optionName) {\n          var names = [\"--\" + optionName];\n          if (_.has(optionInfo, 'short')) {\n            names.push(\"-\" + optionInfo.short);\n          }\n          _.each(names, function (name) {\n            var optionIsBoolean = (optionInfo.type === Boolean);\n            if (_.has(isBoolean, name)) {\n              if (isBoolean[name] !== optionIsBoolean)  {\n                throw new Error(\"conflict: option '\" + name + \"' is used \" +\n                                \"both as a boolean and as another type for \" +\n                                \"command \" + key);\n              }\n            } else {\n              isBoolean[name] = optionIsBoolean;\n            }\n          });\n        });\n      } else {\n        walkCommands(value);\n      }\n    });\n  };\n  walkCommands(commands);\n\n  // This is for things like '--arch' and '--version' which look like\n  // options, but actually function pretty much like commands. That's\n  // a little weird but it feels good and it follows a grand Unix\n  // tradition.\n  _.each(commands['--'] || {}, function (value, key) {\n    if (_.has(isBoolean, \"--\" + key)) {\n      throw new Error(\"--\" + key + \" is both an option and a command?\");\n    }\n    isBoolean[\"--\" + key] = true;\n  });\n\n  // Now parse!\n  var argv = process.argv.slice(2);\n  var rawOptions = {}; // map from '--foo' or '-f' to array of values\n  var rawArgs = [];\n  for (var i = 0; i < argv.length; i++) {\n    var term = argv[i];\n\n    // --: stop-parsing marker\n    if (term === \"--\") {\n      // Remainder is unparsed\n      rawArgs = rawArgs.concat(argv.slice(i + 1));\n      break;\n    }\n\n    // -: just an argument named '-'\n    if (term === \"-\") {\n      rawArgs.push(term);\n      continue;\n    }\n\n    if (term.match(/^--?=/)) {\n      Console.error(\"Option names cannot begin with '='.\");\n      process.exit(1);\n    }\n\n    // A single option, like --foo or -f\n    if (term.match(/^--/) || term.match(/^-.$/)) {\n      var value = undefined;\n\n      // Split the term (once only!) on an equal sign.\n      var equals = term.indexOf('=');\n      if (equals !== -1) {\n        value = term.substr(equals + 1);\n        term = term.substr(0, equals);\n      }\n\n      if (! _.has(rawOptions, term)) {\n        rawOptions[term] = [];\n      }\n\n      // Save off the value of the option. true for (known) booleans,\n      // null if value is missing, else a string. Don't try to\n      // validate or interpret it yet.\n      if (isBoolean[term]) {\n        // If we got an '=' for a boolean, this is an error, which will be\n        // printed prettily later if we push false here.\n        rawOptions[term].push(value === undefined);\n      } else if (value !== undefined) {\n        // Handle '--foo=bar' and '--foo=' (which means \"set to empty string\").\n        rawOptions[term].push(value);\n      } else if (i === argv.length - 1) {\n        rawOptions[term].push(null);\n      } else {\n        rawOptions[term].push(argv[i + 1]);\n        i ++;\n      }\n      continue;\n    }\n\n    // Compound short option ('-abc', '-p45', '-abcp45')? Rewrite it\n    // in place into '-a -b -c', '-p 45', '-a -b -c -p 45'. Not that\n    // anyone really talks this way anymore.\n    if (term.match(/^-/)) {\n      if (term.match(/^-[-=]?$/)) {\n        throw Error(\"these cases should be handled above?\");\n      }\n\n      var replacements = [];\n      for (var j = 1; j < term.length; j++) {\n        var subterm = \"-\" + term.charAt(j);\n        if (isBoolean[subterm] === false) {\n          // If we recognize this short option, and we're sure that it\n          // takes a value, and there are remaining characters in the\n          // short option, then those remaining characters are the value.\n          replacements.push(subterm);\n          var remainder = term.substr(j + 1);\n          if (remainder.length) {\n            // If there's an '=' here, don't include it in the option value. A\n            // trailing '=' *should* cause us to set the option value to ''.\n            if (remainder.charAt(0) === '=') {\n              remainder = remainder.substr(1);\n            }\n            replacements.push(remainder);\n            break;\n          }\n        } else if (isBoolean[subterm] &&\n                   j + 1 < term.length && term.charAt(j + 1) === '=') {\n          // We know it's a boolean, but we've been given an '='. This will\n          // cause a pretty error later.\n          if (! _.has(rawOptions, subterm)) {\n            rawOptions[subterm] = [];\n          }\n          rawOptions[subterm].push(false);\n          // Don't process the '=' on the next pass.\n          j ++;\n        } else {\n          // It's a boolean without an '=', or it's something we've never heard\n          // of.  (In the latter case, assume it's boolean for now, and we'll\n          // print an error later.)\n          replacements.push(subterm);\n        }\n      }\n\n      _.partial(argv.splice, i, 1).apply(argv, replacements);\n      i --;\n      continue;\n    }\n\n    // It is a plain old argument!\n    rawArgs.push(term);\n  }\n\n  // Figure out if we're running in a directory that is part of a Meteor\n  // application or package. Determine any additional directories to\n  // search for packages.\n\n  var appDir = files.findAppDir();\n  if (appDir) {\n    appDir = files.pathResolve(appDir);\n  }\n\n  require('../tool-env/isopackets.js').ensureIsopacketsLoadable();\n\n  // Initialize the server catalog. Among other things, this is where we get\n  // release information (used by springboarding). We do not at this point talk\n  // to the server and refresh it.\n  catalog.official.initialize({\n    offline: !!process.env.METEOR_OFFLINE_CATALOG\n  });\n\n  // Now before we do anything else, figure out the release to use,\n  // and if that release goes with a different version of the tools,\n  // quit and run those tools instead.\n  //\n  // Note that doing this correctly requires knowledge of which\n  // arguments are boolean (in 'meteor --option --release 1.0', is\n  // '--release' a flag or the values of '--option')? We have to use\n  // the flag definitions in the current (latest) version of meteor to\n  // decide whether to exec the other version of meteor that would\n  // interpret the flags. That's not ideal, but it should do fine in\n  // practice, and it's better than assuming that all options are or\n  // aren't boolean when interpreting --release. See\n  // #ImprovingCrossVersionOptionParsing.\n\n  var releaseOverride = null;\n  var releaseForced = false;\n  var releaseExplicit = false;\n  var releaseFromApp = false;\n  if (_.has(rawOptions, '--release')) {\n    if (rawOptions['--release'].length > 1) {\n      Console.error(\n        \"--release should only be passed once. \" +\n        \"Try 'meteor help' for help.\");\n      process.exit(1);\n    }\n    releaseOverride = rawOptions['--release'][0];\n    releaseForced = true;\n    releaseExplicit = true;\n    if (! releaseOverride) {\n      Console.error(\n        \"The --release option needs a value. \" +\n        \"Try 'meteor help' for help.\");\n      process.exit(1);\n    }\n    delete rawOptions['--release'];\n  }\n\n  if (_.has(process.env, 'METEOR_SPRINGBOARD_RELEASE')) {\n    // See #SpringboardEnvironmentVar\n    // Note that this causes release.forced to be true, but not\n    // release.explicit.  release.forced means \"we're using\n    // some sort of externally specified release, not the app\n    // release\"; release.explicit means \"the end-user typed\n    // --release\".\n    releaseOverride = process.env['METEOR_SPRINGBOARD_RELEASE'];\n    releaseForced = true;\n  }\n\n  var releaseName, appReleaseFile;\n  if (appDir) {\n    appReleaseFile = new projectContextModule.ReleaseFile({\n      projectDir: appDir\n    });\n    // This is what happens if the file exists and is empty. This really\n    // shouldn't happen unless the user did it manually.\n    if (appReleaseFile.noReleaseSpecified()) {\n      Console.error(\n        \"Problem! This project has a .meteor/release file which is empty.\",\n        \"The file should either contain the release of Meteor that you want\",\n        \"to use, or the word 'none' if you will only use the project with\",\n        \"unreleased checkouts of Meteor. Please edit the .meteor/release\",\n        \"file in the project and change it to a valid Meteor release or\",\n        \"'none'.\");\n      process.exit(1);\n    } else if (appReleaseFile.fileMissing()) {\n      Console.error(\n        \"Problem! This project does not have a .meteor/release file.\",\n        \"The file should either contain the release of Meteor that you\",\n        \"want to use, or the word 'none' if you will only use the project\",\n        \"with unreleased checkouts of Meteor. Please edit the\",\n        \".meteor/release file in the project and change it to a valid Meteor\",\n        \"release or 'none'.\");\n      process.exit(1);\n    }\n  }\n\n  if (! files.usesWarehouse()) {\n    // Running from a checkout\n    if (releaseOverride) {\n      Console.error(\n        \"Can't specify a release when running Meteor from a checkout.\");\n      process.exit(1);\n    }\n    releaseName = null;\n  } else {\n    // Running from an install\n    if (releaseOverride) {\n      // Use the release explicitly specified on the command line.\n      releaseName = releaseOverride;\n    } else if (appDir) {\n      // Running from an app directory. Use release specified by app.\n      if (appReleaseFile.isCheckout()) {\n        // Looks like we don't have a release. Leave release.current === null.\n      } else {\n        // Use the project's desired release\n        releaseName = appReleaseFile.unnormalizedReleaseName;\n        releaseFromApp = true;\n      }\n    } else {\n      // Run outside an app dir with no --release flag. Use the latest\n      // release we know about (in the default track).\n      releaseName = release.latestKnown();\n      if (!releaseName) {\n        // Somehow we have a catalog that doesn't have any releases on the\n        // default track. Try syncing, at least.  (This is a pretty unlikely\n        // error case, since you should always start with a non-empty catalog.)\n        Console.withProgressDisplayVisible(function () {\n          catalog.refreshOrWarn();\n        });\n        releaseName = release.latestKnown();\n      }\n      if (!releaseName) {\n        if (catalog.refreshFailed) {\n          Console.error(\n            \"The package catalog has no information about any Meteor\",\n            \"releases, and we had trouble connecting to the package server.\");\n        } else {\n          Console.error(\n            \"The package catalog has no information about\",\n            \"any Meteor releases.\");\n        }\n        process.exit(1);\n      }\n    }\n  }\n\n  if (releaseName !== undefined) {\n    // Yay, it's time to load releases!\n    //\n    // The release could be a modern (0.9.0+) tropohouse release or a legacy\n    // (pre-0.9.0) warehouse release.\n    //\n    // The release could be something we already know about on our local disk,\n    // or it could be something we have to ask a server about.\n    //\n    // We want to check both possibilities on disk before talking to any\n    // server. And we want to check for modern releases first in both cases.\n\n    var rel = null;\n\n    if (process.env.METEOR_TEST_FAIL_RELEASE_DOWNLOAD !== 'not-found') {\n      // ATTEMPT 1: modern release, on disk.  (For modern releases, \"on disk\"\n      // just means we have the metadata about it in our catalog; it doesn't\n      // mean we've downloaded the tool or any packages yet.)  release.load just\n      // does a single sqlite query; it doesn't refresh the catalog.\n      try {\n        rel = release.load(releaseName);\n      } catch (e) {\n        if (!(e instanceof release.NoSuchReleaseError)) {\n          throw e;\n        }\n      }\n\n      if (!rel) {\n        if (releaseName === null) {\n          throw Error(\"huh? couldn't load from-checkout release?\");\n        }\n\n        // ATTEMPT 2: legacy release, on disk. (And it's a \"real\" release, not a\n        // \"red pill\" release which has the same name as a modern release!)\n        if (warehouse.realReleaseExistsInWarehouse(releaseName)) {\n          var manifest = warehouse.ensureReleaseExistsAndReturnManifest(\n            releaseName);\n          oldSpringboard(manifest.tools);  // doesn't return\n        }\n\n        // ATTEMPT 3: modern release, troposphere sync needed.\n        Console.withProgressDisplayVisible(function () {\n          catalog.refreshOrWarn();\n        });\n\n        // Try to load the release even if the refresh failed, since it might\n        // have failed on a later page than the one we needed.\n        try {\n          rel = release.load(releaseName);\n        } catch (e) {\n          if (!(e instanceof release.NoSuchReleaseError)) {\n            throw e;\n          }\n        }\n      }\n\n      if (!rel && process.platform !== \"win32\") {\n        // ATTEMPT 4: legacy release, loading from warehouse server.\n        manifest = null;\n        try {\n          manifest = warehouse.ensureReleaseExistsAndReturnManifest(\n            releaseName);\n        } catch (e) {\n          // Note: this is WAREHOUSE's NoSuchReleaseError, not RELEASE's\n          if (e instanceof warehouse.NoSuchReleaseError) {\n            // pass ...\n          } else if (e instanceof files.OfflineError) {\n            if (!catalog.refreshFailed) {\n              // Warn if we didn't already warn.\n              Console.warn(\n                \"Unable to contact release server (are you offline?)\");\n              Console.warn();\n              Console.warn(\n                \"If you are using Meteor behind a proxy, set HTTP_PROXY and HTTPS_PROXY environment variables or see this page for more details: \",\n                Console.url(\"https://github.com/meteor/meteor/wiki/Using-Meteor-behind-a-proxy\"));\n            }\n            // Treat this like a failure to refresh the catalog\n            // (map the old world to the new world)\n            catalog.refreshFailed = true;\n          } else {\n            throw e;\n          }\n        }\n        if (manifest) {\n          // OK, it was an legacy release. We should old-springboard to it.\n          oldSpringboard(manifest.tools);  // doesn't return\n        }\n      }\n    }\n\n    if (!rel) {\n      // Nope, still have no idea about this release!\n\n      // Let's do some processing here. If the user/release file specified a\n      // track, we need to display that correctly, and if they didn't, we should\n      // make it clear that we are talking about the default track.\n      var catalogUtils = require('../packaging/catalog/catalog-utils.js');\n      var trackAndVersion = catalogUtils.splitReleaseName(releaseName);\n      var displayRelease = catalogUtils.displayRelease(\n        trackAndVersion[0], trackAndVersion[1]);\n      // Now, let's process this.\n      if (releaseOverride) {\n        if (process.platform === \"win32\") {\n          // Give a good warning if this release exists, but only in the super old\n          // warehouse.\n          var result = httpHelpers.request(\n            \"http://warehouse.meteor.com/releases/\" + releaseName + \".release.json\");\n          if(result.response.statusCode === 200) {\n            Console.error(\"Meteor on Windows does not support running any releases\",\n              \"before Meteor 1.1. Please use a newer release.\");\n            process.exit(1);\n          }\n        }\n\n        Console.error(displayRelease + \": unknown release.\");\n      } else if (appDir) {\n        if (trackAndVersion[0] !== catalog.DEFAULT_TRACK) {\n          displayRelease = \"Meteor release \" + displayRelease;\n        }\n        if (catalog.refreshFailed) {\n          Console.error(\n            \"This project says that it uses \" + displayRelease + \", but\",\n            \"you don't have that version of Meteor installed, and we were\",\n            \"unable to contact Meteor's update servers to find out about it.\",\n            \"Please edit the .meteor/release file in the project and change\",\n            \"it to a valid Meteor release, or go online.\");\n        } else {\n          Console.error(\n            \"This project says that it uses \" + displayRelease + \", but you\",\n            \"don't have that version of Meteor installed and the Meteor\",\n            \"update servers don't have it either. Please edit the\",\n            \".meteor/release file in the project and change it to a valid\",\n            \"Meteor release.\");\n        }\n      } else {\n        throw new Error(\"can't load latest release?\");\n      }\n      process.exit(1);\n    }\n\n    release.setCurrent(rel, releaseForced, releaseExplicit);\n  }\n\n  // If we're not running the correct version of the tools for this\n  // release, fetch it and re-run.\n  //\n  // This will never happen when we're springboarding as part of an\n  // update, because the correct tools version will have been chosen\n  // the first time around. It will also never happen if the current\n  // release is a checkout, because that doesn't make any sense.\n  if (release.current && release.current.isProperRelease() &&\n      release.current.getToolsPackageAtVersion() !== files.getToolsVersion()) {\n    springboard(release.current, { fromApp: releaseFromApp });\n    // Does not return!\n  }\n\n  // Check for the '--help' option.\n  var showHelp = false;\n  if (_.has(rawOptions, '--help')) {\n    showHelp = true;\n    delete rawOptions['--help'];\n  }\n\n  var commandName = '';\n  var command = null;\n\n  // Check for a command like '--arch' or '--version'. Make sure\n  // it stands alone. (And this is ignored if you've passed --help.)\n  if (! showHelp) {\n    _.each(commands['--'] || {}, function (value, key) {\n      var fullName = \"--\" + key;\n\n      if (rawOptions[fullName]) {\n        if (rawOptions[fullName].length > 1) {\n          Console.error(\"It doesn't make sense to pass \" +\n                        fullName + \" more than once.\");\n          process.exit(1);\n        }\n        if (_.size(rawOptions) > 1 || rawArgs.length !== 0 || command) {\n          Console.error(\"Can't pass anything else along with \" +\n                        value.name + \".\");\n          process.exit(1);\n        }\n        command = value;\n        commandName = command.name;\n        delete rawOptions['--' + key];\n      }\n    });\n  }\n\n  // OK, if not one of those, the first (non-'--') argument(s) should\n  // name the command.\n  if (! command) {\n    if (rawArgs.length === 0) {\n      // No arguments means 'run'. Unless it's 'meteor --help'.\n      if (! showHelp) {\n        command = commands.run\n        commandName = \"run\";\n        if (! command) {\n          throw new Error(\"no 'run' command?\");\n        }\n      }\n    } else {\n      // Find the command they specified.\n      var walk = commands;\n      for (var i = 0; i < rawArgs.length; i++) {\n        var word = rawArgs[i];\n\n        // Support \"meteor help\", \"meteor help deploy\", \"meteor help admin\",\n        // \"meteor admin help\", \"meteor admin help grant\", etc.  (But not\n        // \"meteor deploy help\" or \"meteor admin grant help\": once we find an\n        // actual command, we assume \"help\" is an argument, eg a site called\n        // 'help'!)\n        if (word === \"help\") {\n          showHelp = true;\n          continue;\n        }\n\n        commandName += (commandName.length > 0 ? \" \" : \"\") + word;\n\n        if (! _.has(walk, word)) {\n          Console.error(\n            Console.command(\"'\" + commandName + \"'\") +\n            \" is not a Meteor command. See \" +\n            Console.command(\"'meteor --help'\")+ \".\");\n          process.exit(1);\n        }\n\n        if (walk[word] instanceof Command) {\n          command = walk[word];\n          rawArgs = rawArgs.slice(i + 1); // consume arguments used\n          break;\n        }\n\n        walk = walk[word];\n      }\n    }\n  }\n\n  if (! command && ! showHelp) {\n    // They typed something like 'meteor admin' (when they were\n    // supposed to type 'meteor admin grant' or something).\n    Console.error(\n      \"Try \" + Console.command(\"'meteor \" + commandName + \" help'\") + \" \" +\n      \"for available commands.\");\n    process.exit(1);\n  }\n\n  // At this point we have a command[*]. Did they ask for help, or do\n  // they actually want to run the command? If the former, print the\n  // help and don't criticize anything else they may have given us.\n  //\n  // [*] the one exception being 'meteor --help' or 'meteor help', in\n  // which case showHelp will be true and command will be null\n\n  if (showHelp) {\n    // XXX: Until we rewrite the longHelp function to cope with the new output\n    // format, let's go with the static, painstakingly-formatted version.\n    Console.rawInfo(longHelp(commandName) + \"\\n\");\n    process.exit(0);\n  }\n\n  // They want to run the command. Interpret the options and make sure\n  // that they're valid.\n\n  var options = { args: rawArgs };\n\n  _.each(command.options, function (optionInfo, optionName) {\n    var presentLong = _.has(rawOptions, \"--\" + optionName);\n    var presentShort = _.has(optionInfo, 'short') &&\n      _.has(rawOptions, \"-\" + optionInfo.short);\n    var tryHelpMessage =\n        \"Try \" + Console.command(\"'meteor help \" + commandName + \"'\") + \" \" +\n        \"for help.\";\n\n\n    if (presentShort && presentLong) {\n      // this would get caught below, but give a clearer error message\n      Console.error(\n        commandName + \": can't pass both -\" + optionInfo.short + \" and --\" +\n        optionName + \". \" + tryHelpMessage);\n      process.exit(1);\n    }\n    var helpfulOptionName = \"--\" + optionName +\n      (presentShort ? \" (-\" + optionInfo.short + \")\" : \"\");\n\n    // Collect all values we've received for this option, across the\n    // long and short versions, and across possibly multiple\n    // occurrences of the option on the command line\n    var values = [];\n    if (presentLong) {\n      values = values.concat(rawOptions[\"--\" + optionName]);\n    }\n    if (presentShort) {\n      values = values.concat(rawOptions[\"-\" + optionInfo.short]);\n    }\n\n    if (values.length > 1) {\n      // in the future, we could support multiple values, but we don't\n      // for now since no command needs it\n      Console.error(\n        Console.command(commandName) + \": can only take one \" +\n          Console.command(helpfulOptionName) + \" option.\");\n      Console.error(tryHelpMessage);\n\n      process.exit(1);\n    } else if (values.length === 1) {\n      // OK, they provided exactly one value. Check its type and add\n      // to the output.\n      var value = values[0];\n      if (value === null) {\n        // This option requires a value and they didn't give it one\n        // (it was the last word on the command line).\n        Console.error(\n          Console.command(commandName) + \": the \" +\n            Console.command(helpfulOptionName) + \" option needs a value.\");\n        Console.error(tryHelpMessage);\n\n        process.exit(1);\n      } else if (optionInfo.type === Number) {\n        if (! value.match(/^[0-9]+$/)) {\n          Console.error(\n            Console.command(commandName) + \": \" +\n              Console.command(helpfulOptionName) + \" must be a number.\");\n          Console.error(tryHelpMessage);\n          process.exit(1);\n        }\n        value = parseInt(value);\n      } else if (optionInfo.type === Boolean) {\n        if (!value) {\n          Console.error(\n            Console.command(commandName) + \": the \" +\n              Console.command(helpfulOptionName) + \" \" +\n              \"option does not need a value.\");\n          Console.error(tryHelpMessage);\n          process.exit(1);\n        }\n        value = true;\n      } else if (optionInfo.type === String) {\n        // nothing to do, 'value' needs no parsing or validation\n      } else {\n        throw new Error(\"unknown option type?\");\n      }\n      options[optionName] = value;\n\n      // Remove from the list of input arguments so that later we can\n      // detect unrecognized arguments.\n      if (presentLong) {\n        delete rawOptions[\"--\" + optionName];\n      }\n      if (presentShort) {\n        delete rawOptions[\"-\" + optionInfo.short];\n      }\n    } else {\n      // Option not supplied. Throw an error if it was required,\n      // supply a default value if one is defined, or just leave it\n      // out.\n      if (_.has(optionInfo, 'default')) {\n        options[optionName] = optionInfo.default;\n      } else if (optionInfo.required) {\n        Console.error(\n          Console.command(commandName) + \": the --\" +\n          Console.command(optionName) + \" option is required.\");\n        Console.rawError(longHelp(commandName));\n        process.exit(1);\n      }\n    }\n  });\n\n  // Check for unrecognized options.\n  if (_.keys(rawOptions).length > 0 && !command.allowUnrecognizedOptions) {\n    Console.error(\n      Console.command(_.keys(rawOptions)[0]) + \": unknown option.\");\n    Console.rawError(\n      longHelp(commandName));\n    process.exit(1);\n  }\n\n  // Check argument count.\n  if (options.args.length < command.minArgs) {\n    Console.error(\n      Console.command(commandName) + \": not enough arguments.\");\n    Console.rawError(\n      longHelp(commandName));\n    process.exit(1);\n  }\n\n  if (options.args.length > command.maxArgs) {\n    Console.error(\n      Console.command(commandName) + \": too many arguments.\");\n    Console.rawError(\n      longHelp(commandName));\n    process.exit(1);\n  }\n\n  // We know we have a valid command and options. Now check to see if\n  // the command can only be run from an app dir, and add the appDir\n  // option if running from an app.\n  var requiresApp = command.evaluateOption('requiresApp', options);\n\n  if (appDir) {\n    options.appDir = appDir;\n  }\n\n  if (requiresApp && ! options.appDir) {\n    // This is where you end up if you type 'meteor' with no args,\n    // since you'll default to the 'run' command which requires an\n    // app. Be welcoming to our new developers!\n    Console.error(\n      Console.command(commandName) +\n      \": You're not in a Meteor project directory.\");\n    Console.error();\n    Console.error(\"To create a new Meteor project:\");\n    Console.error(\n      Console.command(\"meteor create <project name>\"),\n      Console.options({ indent: 2 }));\n    Console.error(\"For example:\");\n    Console.error(\n      Console.command(\"meteor create myapp\"),\n      Console.options({ indent: 2 }));\n    Console.error();\n    Console.error(\n      \"For more help, see \" + Console.command(\"'meteor --help'\") + \".\");\n    process.exit(1);\n  }\n\n  // Same check for commands that can only be run from a package dir.\n  // You can't specify this on a Refresh.Never command.\n  var requiresPackage = command.evaluateOption('requiresPackage', options);\n\n  var requiresAppOrPackage =\n    command.evaluateOption('requiresAppOrPackage', options);\n\n  // Some commands have different results when run from a package dir, but don't\n  // strictly require it. These commands should use 'usesPackage' instead of\n  // requiresPackage. (We want to avoid searching up the directory tree for\n  // package.js when we don’t have to. Hopefully, a unified control file will\n  // allow us better control in the future).\n  var usesPackage = command.usesPackage;\n\n  if (requiresPackage || usesPackage || requiresAppOrPackage) {\n    var packageDir = files.findPackageDir();\n    if (packageDir) {\n      packageDir = files.pathResolve(packageDir);\n    }\n    if (packageDir) {\n      options.packageDir = packageDir;\n    }\n  }\n\n  if (requiresPackage && ! options.packageDir) {\n    Console.error(\n      Console.command(commandName) +\n        \": You're not in a Meteor package directory.\");\n    process.exit(1);\n  }\n\n  if (requiresAppOrPackage && ! options.packageDir && ! options.appDir) {\n    Console.error(\n      Console.command(commandName) +\n        \": You're not in a Meteor app directory or a Meteor package directory.\");\n    process.exit(1);\n  }\n\n  if (command.requiresRelease && ! release.current) {\n    Console.error(\n      \"You must specify a Meteor version with --release when you work with\",\n      \"this project. It was created from an unreleased Meteor checkout and\",\n      \"doesn't have a version associated with it.\");\n    Console.error(\n      \"You can permanently set a release for this project with \" +\n      Console.command(\"'meteor update'\") + \".\");\n    process.exit(1);\n  }\n\n  if (command.requiresApp && release.current.isCheckout() &&\n      appReleaseFile && ! appReleaseFile.isCheckout()) {\n    // For commands that work with apps, if we have overridden the\n    // app's usual release by using a checkout, print a reminder banner.\n    Console.arrowWarn(\n      \"Running Meteor from a checkout -- overrides project version \" +\n      Console.noWrap(\"(\" + appReleaseFile.displayReleaseName + \")\"));\n  }\n\n  // Now that we're ready to start executing the command, if we are in\n  // startup time profiling mode, print the profile.\n  if (showRequireProfile) {\n    require('../tool-env/profile-require.js').printReport();\n  }\n\n  Console.setPretty(command.evaluateOption('pretty', options));\n  Console.enableProgressDisplay(true);\n\n  if (command.notOnWindows && process.platform === 'win32') {\n    Console.error('This command is not yet available on Windows.');\n    process.exit(1);\n  }\n\n  // Run the command!\n  try {\n    // Before run, do a package sync if one is configured\n    var catalogRefreshStrategy = command.catalogRefresh;\n    if (! catalog.triedToRefreshRecently &&\n        catalogRefreshStrategy.beforeCommand) {\n      buildmessage.enterJob({title: 'updating package catalog'}, function () {\n        catalogRefreshStrategy.beforeCommand();\n      });\n    }\n\n    var ret = command.func(options, {rawOptions});\n  } catch (e) {\n    Console.enableProgressDisplay(false);\n\n    if (e === main.ShowUsage || e === main.WaitForExit ||\n        e === main.SpringboardToLatestRelease ||\n        e === main.SpringboardToSpecificRelease ||\n        e === main.WaitForExit) {\n      throw new Error(\n        \"you meant 'throw new main.Foo', not 'throw main.Foo'\");\n    } else if (e instanceof main.ShowUsage) {\n      Console.rawError(longHelp(commandName) + \"\\n\");\n      process.exit(1);\n    } else if (e instanceof main.SpringboardToLatestRelease) {\n      // Load the metadata for the latest release (or at least, the latest\n      // release we know about locally). We should only do this if we know there\n      // is some latest release on this track.\n      var latestRelease = release.load(release.latestKnown(e.track));\n      springboard(latestRelease, { releaseOverride: latestRelease.name });\n      // (does not return)\n    } else if (e instanceof main.SpringboardToSpecificRelease) {\n      // Springboard to a specific release. This is only throw by\n      // publish-for-arch, which is catalog.Refresh.OnceAtStart, so we ought to\n      // have decent knowledge of the latest release.\n      var nextRelease = release.load(e.fullReleaseName);\n      springboard(nextRelease, { releaseOverride: e.fullReleaseName });\n      // (does not return)\n    } else if (e instanceof main.WaitForExit) {\n      return;\n    } else if (e instanceof main.ExitWithCode) {\n      process.exit(e.code);\n    } else {\n      throw e;\n    }\n  }\n\n  Console.enableProgressDisplay(false);\n\n  // Exit. (We will not get here if the command threw an exception\n  // such as main.WaitForExit).\n  if (ret === undefined) {\n    ret = 0;\n  }\n  if (typeof ret !== \"number\") {\n    throw new Error(\"command returned non-number?\");\n  }\n  process.exit(ret);\n}).run();\n"
  },
  {
    "path": "tools/console/README.md",
    "content": "This folder contains libs for printing output in response to CLI commands.\n\n`progress.js` defines the lib for printing a progress-bar, so the long\noperations don't look like hanging.\n\n`console.js` exposes the `Console` singleton that should be used through-out the\ntool to print messages with the right level of importance. It also knows how to\ncorrectly repaint the progress-bar, so the two don't conflict.\n"
  },
  {
    "path": "tools/console/console.js",
    "content": "///  This class provides a set of utility functions for printing to the terminal\n///  in the Meteor tool.\n///\n///  When you intend for your messages to be read by humans, you should use the\n///  following functions to print to the terminal. They will automatically line\n///  wrap output to either the width of the terminal, or 80 characters. They\n///  will also end in a new line.\n///\n////   - Console.info : Print to stdout.\n///    - Console.error: Print to stderr.\n///    - Console.warn: Prints to stderr, if warnings are enabled.\n///    - Console.debug: Prints to stdout, if debug is enabled.\n///\n/// Sometimes, there is a phrase that shouldn't be split up over multiple\n/// lines (for example, 'meteor update'). When applicable, please use the\n/// following functions (Some of them add aditional formatting, especially when\n/// pretty-print is turned on):\n///\n///    - Console.command: things to enter on the command-line, such as\n///      'meteor update' or 'cd foobar'.\n///    - Console.url: URLs, such as 'www.meteor.com'\n///    - Console.path: filepaths outside of Console.command.\n///    - Console.noWrap: anything else that you don't want line-wrapped.\n///\n/// Here is a contrived example:\n///   Console.info(\n///     \"For more information, please run\", Console.command(\"meteor show\"),\n///     \"or check out the new releases at\", Console.url(\"www.meteor.com\"),\n///     \"or look at\", Console.path(filepath), \". You are currently running\",\n///     \"Console.noWrap(\"Meteor version 1.5\") + \".\");\n///\n/// The Console.info/Console.error/Console.warn/Console.debug functions also\n/// take in Console.options, as a last (optional) argument. These allow you to\n/// set an indent or use a bulletpoint. You can check out their API below. If\n/// possible, you might also want to use one of the existing wrapper functions,\n/// such as Console.labelWarning or Console.arrowInfo.\n///\n/// Output intended for machines (or pre-formatted in specific ways) should NOT\n/// be line-wrapped. Do not wrap these things: JSON output, error stack traces,\n/// logs from other programs, etc. For those, you should use the 'raw'\n/// version of the API:\n///\n///    - Console.rawInfo: Like Console.info, but without formatting.\n///    - Console.rawError: Like Console.error, but without formatting.\n///    - Console.rawWarn: Like Console.warn, but without formatting.\n///    - Console.rawDebug: Like Console.debug, but without formatting.\n///\n/// DO NOT use Console.command/Console.url/Console.path with the raw functions!\n/// (They will change your output in ways that you probably do not want). These\n/// don't auto-linewrap, end in a newline, or take in Console.options.\n///\n/// Here is are some examples:\n///     Console.rawInfo(JSON.stringify(myData, null, 2));\n///     Console.rawError(err.stack + \"\\n\");\n///\n/// In addition to printing functions, the Console class provides progress bar\n/// support, that is mostly handled through buildmessage.js.\nvar _ = require('underscore');\nvar readline = require('readline');\nvar util = require('util');\nvar buildmessage = require('../utils/buildmessage.js');\n// XXX: Are we happy with chalk (and its sub-dependencies)?\nvar chalk = require('chalk');\nvar cleanup = require('../tool-env/cleanup.js');\nvar utils = require('../utils/utils.js');\nvar wordwrap = require('wordwrap');\n\nvar PROGRESS_DEBUG = !!process.env.METEOR_PROGRESS_DEBUG;\nvar FORCE_PRETTY=undefined;\nvar CARRIAGE_RETURN =\n  (process.platform === 'win32' && process.stdout.isTTY ? new Array(249).join('\\b') : '\\r');\n\nif (process.env.METEOR_PRETTY_OUTPUT) {\n  FORCE_PRETTY = process.env.METEOR_PRETTY_OUTPUT != '0';\n}\n\nif (! process.env.METEOR_COLOR) {\n  chalk.enabled = false;\n}\n\nvar STATUS_MAX_LENGTH = 40;\n\nvar PROGRESS_MAX_WIDTH = 40;\nvar PROGRESS_BAR_FORMAT = '[:bar] :percent :etas';\nvar TEMP_STATUS_LENGTH = STATUS_MAX_LENGTH + 12;\n\nvar STATUS_INTERVAL_MS = 50;\n\n// Message to show when we don't know what we're doing\n// XXX: ? FALLBACK_STATUS = 'Pondering';\nvar FALLBACK_STATUS = '';\n\n// If there is a part of the larger text, and we really want to make sure that\n// it doesn't get split up, we will replace the space with a utf character that\n// we are not likely to use anywhere else. This one looks like the a BLACK SUN\n// WITH RAYS. We intentionally want to NOT use a space-like character: it should\n// be obvious that something has gone wrong if this ever gets printed.\nvar SPACE_REPLACEMENT = '\\u2600';\n// In Javascript, replace only replaces the first occurance and this is the\n// proposed alternative.\nvar replaceAll = function (str, search, replace) {\n return str.split(search).join(replace);\n};\n\nvar spacesArray = new Array(200).join(' ');\nvar spacesString = function (length) {\n  if (length > spacesArray.length) {\n    spacesArray = new Array(length * 2).join(' ');\n  }\n  return spacesArray.substring(0, length);\n};\nvar ARROW = \"=> \";\n\n\nvar toFixedLength = function (text, length) {\n  text = text || \"\";\n\n  // pad or truncate `text` to length\n  var pad = length - text.length;\n  if (pad < 0) {\n    // Truncate\n    text = text.substring(0, length - 3) + \"...\";\n  } else if (pad > 0) {\n    // Pad\n    text = text + spacesString(pad);\n  }\n  return text;\n};\n\n// No-op progress display, that means we don't have to handle the 'no progress\n// display' case\nvar ProgressDisplayNone = function () {\n};\n\n_.extend(ProgressDisplayNone.prototype, {\n  depaint: function () {\n    // No-op\n  },\n\n  repaint: function () {\n    // No-op\n  }\n});\n\n// Status display only, primarily for use with emacs\n// No fancy terminal support available, but we have a TTY.\n// Print messages that will be overwritten because they\n// end in `\\r`.\n// Status message mode is where we see status messages but not the\n// fancy progress bar.  It's used when we detect a \"pseudo-TTY\"\n// of the type used by Emacs, and possibly SSH.\n//\n// XXX DELETE THIS MODE since the progress bar now uses \"\\r\".\n// But first we have to throttle progress bar updates so that\n// Emacs doesn't get overwhelemd (we should throttle them anyway).\n// There's also a bug when using the progress bar in Emacs where\n// the cursor doesn't seem to return to column 0.\nvar ProgressDisplayStatus = function (console) {\n  var self = this;\n\n  self._console = console;\n  self._stream = console._stream;\n\n  self._status = null;\n  self._wroteStatusMessage = false;\n};\n\n_.extend(ProgressDisplayStatus.prototype, {\n  depaint: function () {\n    var self = this;\n    // For the non-progress-bar status mode, we may need to\n    // clear some characters that we printed with a trailing `\\r`.\n    if (self._wroteStatusMessage) {\n      var spaces = spacesString(TEMP_STATUS_LENGTH + 1);\n      self._stream.write(spaces + CARRIAGE_RETURN);\n      self._wroteStatusMessage = false;\n    }\n  },\n\n  repaint: function () {\n    // We don't repaint after a log message (is that right?)\n  },\n\n  updateStatus: function (status) {\n    var self = this;\n\n    if (status == self._status) {\n      return;\n    }\n\n    self._status = status;\n    self._render();\n  },\n\n  _render: function () {\n    var self = this;\n\n    var text = self._status;\n    if (text) {\n      text = toFixedLength(text, STATUS_MAX_LENGTH);\n    }\n\n    if (text) {\n      // the number of characters besides `text` here must\n      // be accounted for in TEMP_STATUS_LENGTH.\n      self._stream.write('  (  ' + text + '  ... )' + CARRIAGE_RETURN);\n      self._wroteStatusMessage = true;\n    }\n  }\n});\n\nvar SpinnerRenderer = function () {\n  var self = this;\n  self.frames = ['-', '\\\\', '|', '/'];\n  self.start = +(new Date);\n  self.interval = 250;\n  //// I looked at some Unicode indeterminate progress indicators, such as:\n  ////\n  //// spinner = \"▁▃▄▅▆▇▆▅▄▃\".split('');\n  //// spinner = \"▉▊▋▌▍▎▏▎▍▌▋▊▉\".split('');\n  //// spinner = \"▏▎▍▌▋▊▉▊▋▌▍▎▏▁▃▄▅▆▇▆▅▄▃\".split('');\n  //// spinner = \"▉▊▋▌▍▎▏▎▍▌▋▊▉▇▆▅▄▃▁▃▄▅▆▇\".split('');\n  //// spinner = \"⠉⠒⠤⣀⠤⠒\".split('');\n  ////\n  //// but none of them really seemed like an improvement. I think\n  //// the case for using unicode would be stronger in a determinate\n  //// progress indicator.\n  ////\n  //// There are also some four-frame options such as ◐◓◑◒ at\n  ////   http://stackoverflow.com/a/2685827/157965\n  //// but all of the ones I tried look terrible in the terminal.\n};\n\nSpinnerRenderer.prototype.asString = function () {\n  var self = this;\n  var now = +(new Date);\n\n  var t = now - self.start;\n  var frame = Math.floor(t / self.interval) % self.frames.length;\n  return self.frames[frame];\n};\n\n// Renders a progressbar.  Based on the npm 'progress' module, but tailored to our needs (i.e. renders to string)\nvar ProgressBarRenderer = function (format, options) {\n  var self = this;\n\n  options = options || {};\n\n  self.fmt = format;\n  self.curr = 0;\n  self.total = 100;\n  self.maxWidth = options.maxWidth || self.total;\n  self.chars = {\n    complete   : '=',\n    incomplete : ' '\n  };\n};\n\n_.extend(ProgressBarRenderer.prototype, {\n  asString: function (availableSpace) {\n    var self = this;\n\n    var ratio = self.curr / self.total;\n    ratio = Math.min(Math.max(ratio, 0), 1);\n\n    var percent = ratio * 100;\n    var incomplete, complete, completeLength;\n    var elapsed = new Date - self.start;\n    var eta = (percent == 100) ? 0 : elapsed * (self.total / self.curr - 1);\n\n    /* populate the bar template with percentages and timestamps */\n    var str = self.fmt\n      .replace(':current', self.curr)\n      .replace(':total', self.total)\n      .replace(':elapsed', isNaN(elapsed) ? '0.0' : (elapsed / 1000).toFixed(1))\n      .replace(':eta', (isNaN(eta) || ! isFinite(eta)) ? '0.0' : (eta / 1000).toFixed(1))\n      .replace(':percent', percent.toFixed(0) + '%');\n\n    /* compute the available space (non-zero) for the bar */\n    var width = Math.min(self.maxWidth, availableSpace - str.replace(':bar', '').length);\n\n    /* NOTE: the following assumes the user has one ':bar' token */\n    completeLength = Math.round(width * ratio);\n    complete = Array(completeLength + 1).join(self.chars.complete);\n    incomplete = Array(width - completeLength + 1).join(self.chars.incomplete);\n\n    /* fill in the actual progress bar */\n    str = str.replace(':bar', complete + incomplete);\n\n    return str;\n  }\n});\n\n\nvar ProgressDisplayFull = function (console) {\n  var self = this;\n\n  self._console = console;\n  self._stream = console._stream;\n\n  self._status = '';\n\n  var options = {\n    complete: '=',\n    incomplete: ' ',\n    maxWidth: PROGRESS_MAX_WIDTH,\n    total: 100\n  };\n  self._progressBarRenderer = new ProgressBarRenderer(PROGRESS_BAR_FORMAT, options);\n  self._progressBarRenderer.start = new Date();\n\n  self._headless = false;\n\n  self._spinnerRenderer = new SpinnerRenderer();\n\n  self._fraction = undefined;\n\n  self._printedLength = 0;\n\n  self._lastWrittenLine = null;\n  self._lastWrittenTime = 0;\n};\n\n_.extend(ProgressDisplayFull.prototype, {\n  depaint: function () {\n    var self = this;\n\n    self._stream.write(spacesString(self._printedLength) + CARRIAGE_RETURN);\n  },\n\n  updateStatus: function (status) {\n    var self = this;\n\n    if (status == self._status) {\n      return;\n    }\n\n    self._status = status;\n    self._render();\n  },\n\n  updateProgress: function (fraction, startTime) {\n    var self = this;\n\n    self._fraction = fraction;\n    if (fraction !== undefined) {\n      self._progressBarRenderer.curr = Math.floor(fraction * self._progressBarRenderer.total);\n    }\n    if (startTime) {\n      self._progressBarRenderer.start = startTime;\n    }\n    self._render();\n  },\n\n  repaint: function () {\n    var self = this;\n    self._render();\n  },\n\n  setHeadless(headless) {\n    this._headless = !! headless;\n  },\n\n  _render: function () {\n    var self = this;\n\n    // XXX: Throttle these updates?\n    // XXX: Or maybe just jump to the correct position?\n    var progressGraphic = '';\n\n    // The cursor appears in position 0; we indent it a little to avoid this\n    // This also means it appears less important, which is good\n    var indentColumns = 3;\n\n    var streamColumns = this._console.width();\n    var statusColumns;\n    var progressColumns;\n    if (! streamColumns) {\n      statusColumns = STATUS_MAX_LENGTH;\n      progressColumns = 0;\n    } else {\n      statusColumns = Math.min(STATUS_MAX_LENGTH, streamColumns - indentColumns);\n      progressColumns = Math.min(PROGRESS_MAX_WIDTH, streamColumns - indentColumns - statusColumns);\n    }\n\n    if (self._fraction !== undefined && progressColumns > 16) {\n      // 16 is a heuristic number that allows enough space for a meaningful progress bar\n      progressGraphic = \"  \" + self._progressBarRenderer.asString(progressColumns - 2);\n\n    } else if (! self._headless && progressColumns > 3) {\n      // 3 = 2 spaces + 1 spinner character\n      progressGraphic = \"  \" + self._spinnerRenderer.asString();\n\n    } else if (new Date - self._lastWrittenTime > 5 * 60 * 1000) {\n      // Print something every five minutes, to avoid test timeouts.\n      progressGraphic = \"  [ProgressDisplayFull keepalive]\";\n      self._lastWrittenLine = null; // Force printing.\n    }\n\n    if (self._status || progressGraphic) {\n      // XXX: Just update the graphic, to avoid text flicker?\n\n      var line = spacesString(indentColumns);\n      var length = indentColumns;\n\n      if (self._status) {\n        var fixedLength = toFixedLength(self._status, statusColumns);\n        line += chalk.bold(fixedLength);\n        length += statusColumns;\n      } else {\n        line += spacesString(statusColumns);\n        length += statusColumns;\n      }\n\n      line += progressGraphic + CARRIAGE_RETURN;\n      length += progressGraphic.length;\n\n      if (self._headless &&\n          line === self._lastWrittenLine) {\n        // Don't write the exact same line twice in a row.\n        return;\n      }\n\n      self.depaint();\n\n      self._stream.write(line);\n      self._lastWrittenLine = line;\n      self._lastWrittenTime = +new Date;\n      self._printedLength = length;\n    }\n  }\n});\n\nvar StatusPoller = function (console) {\n  var self = this;\n\n  // The current progress we are watching\n  self._watching = null;\n\n  self._console = console;\n\n  self._pollPromise = null;\n  self._throttledStatusPoll = new utils.Throttled({\n    interval: STATUS_INTERVAL_MS\n  });\n  self._startPoller();\n  self._stop = false;\n};\n\n_.extend(StatusPoller.prototype, {\n  _startPoller: function () {\n    var self = this;\n\n    if (self._pollPromise) {\n      throw new Error(\"Already started\");\n    }\n\n    self._pollPromise = (async() => {\n      utils.sleepMs(STATUS_INTERVAL_MS);\n      while (! self._stop) {\n        self.statusPoll();\n        utils.sleepMs(STATUS_INTERVAL_MS);\n      }\n    })();\n  },\n\n  stop: function () {\n    var self = this;\n\n    self._stop = true;\n  },\n\n  statusPoll: function () {\n    var self = this;\n    if (self._throttledStatusPoll.isAllowed()) {\n      self._statusPoll();\n    }\n  },\n\n  _statusPoll: function () {\n    var self = this;\n\n    // XXX: Early exit here if we're not showing status at all?\n\n    var rootProgress = buildmessage.getRootProgress();\n    if (PROGRESS_DEBUG) {\n      // It can be handy for dev purposes to see all the executing tasks\n      rootProgress.dump(process.stdout, {skipDone: true});\n    }\n\n    var reportState = function (state, startTime) {\n      var progressDisplay = self._console._progressDisplay;\n      // Do the % computation, if it is going to be used\n      if (progressDisplay.updateProgress) {\n        if (state.end === undefined || state.end == 0) {\n          progressDisplay.updateProgress(undefined, startTime);\n        } else {\n          var fraction = state.done ? 1.0 : (state.current / state.end);\n\n          if (! isNaN(fraction) && fraction >= 0) {\n            progressDisplay.updateProgress(fraction, startTime);\n          } else {\n            progressDisplay.updateProgress(0, startTime);\n          }\n        }\n      }\n    };\n\n    var watching = (rootProgress ? rootProgress.getCurrentProgress() : null);\n\n    if (self._watching === watching) {\n      // We need to do this to keep the spinner spinning\n      // XXX: Should we _only_ do this when we're showing the spinner?\n      reportState(watching.getState(), watching.startTime);\n      return;\n    }\n\n    self._watching = watching;\n\n    var title = (watching != null ? watching._title : null) || FALLBACK_STATUS;\n\n    var progressDisplay = self._console._progressDisplay;\n    progressDisplay.updateStatus && progressDisplay.updateStatus(title);\n\n    if (watching) {\n      watching.addWatcher(function (state) {\n        if (watching != self._watching) {\n          // No longer active\n          // XXX: De-register with watching? (we don't bother right now because dead tasks tell no status)\n          return;\n        }\n\n        reportState(state, watching.startTime);\n      });\n    }\n  }\n});\n\nvar Console = function (options) {\n  var self = this;\n\n  options = options || {};\n\n  // The progress display we are showing on-screen\n  self._progressDisplay = new ProgressDisplayNone(self);\n\n  self._statusPoller = null;\n\n  self._throttledYield = new utils.ThrottledYield();\n\n  self.verbose = false;\n\n  // Legacy helpers\n  self.stdout = {};\n  self.stderr = {};\n\n  self._stream = process.stdout;\n\n  self._pretty = (FORCE_PRETTY !== undefined ? FORCE_PRETTY : false);\n  self._progressDisplayEnabled = false;\n\n  self._logThreshold = LEVEL_CODE_INFO;\n  var logspec = process.env.METEOR_LOG;\n  if (logspec) {\n    logspec = logspec.trim().toLowerCase();\n    if (logspec == 'debug') {\n      self._logThreshold = LEVEL_CODE_DEBUG;\n    }\n  }\n\n  cleanup.onExit(function (sig) {\n    self.enableProgressDisplay(false);\n  });\n};\n\nvar LEVEL_CODE_ERROR = 4;\nvar LEVEL_CODE_WARN = 3;\nvar LEVEL_CODE_INFO = 2;\nvar LEVEL_CODE_DEBUG = 1;\n\nvar LEVEL_ERROR = { code: LEVEL_CODE_ERROR };\nvar LEVEL_WARN = { code: LEVEL_CODE_WARN };\nvar LEVEL_INFO = { code: LEVEL_CODE_INFO };\nvar LEVEL_DEBUG = { code: LEVEL_CODE_DEBUG };\n\n// We use a special class to represent the options that we send to the Console\n// because it allows us to call 'instance of' on the last argument of variadic\n// functions. This allows us to keep the signature of our custom output\n// functions (ex: info) roughly the same as the originals.\nvar ConsoleOptions = function (o) {\n  var self = this;\n  self.options = o;\n}\n\n_.extend(Console.prototype, {\n  LEVEL_ERROR: LEVEL_ERROR,\n  LEVEL_WARN: LEVEL_WARN,\n  LEVEL_INFO: LEVEL_INFO,\n  LEVEL_DEBUG: LEVEL_DEBUG,\n\n  setPretty: function (pretty) {\n    var self = this;\n    // If we're being forced, do nothing.\n    if (FORCE_PRETTY !== undefined) {\n      return;\n    }\n    // If no change, do nothing.\n    if (self._pretty === pretty) {\n      return;\n    }\n    self._pretty = pretty;\n    self._updateProgressDisplay();\n  },\n\n  // Runs f with the progress display visible (ie, with progress display enabled\n  // and pretty). Resets both flags to their original values after f runs.\n  withProgressDisplayVisible: function (f) {\n    var self = this;\n    var originalPretty = self._pretty;\n    var originalProgressDisplayEnabled = self._progressDisplayEnabled;\n\n    // Turn both flags on.\n    self._pretty = self._progressDisplayEnabled = true;\n\n    // Update the screen if anything changed.\n    if (! originalPretty || ! originalProgressDisplayEnabled) {\n      self._updateProgressDisplay();\n    }\n\n    try {\n      return f();\n    } finally {\n      // Reset the flags.\n      self._pretty = originalPretty;\n      self._progressDisplayEnabled = originalProgressDisplayEnabled;\n      // Update the screen if anything changed.\n      if (! originalPretty || ! originalProgressDisplayEnabled) {\n        self._updateProgressDisplay();\n      }\n    }\n  },\n\n  setVerbose: function (verbose) {\n    var self = this;\n    self.verbose = verbose;\n  },\n\n  // Get the current width of the Console.\n  width: function () {\n    var width = 80;\n    var stream = process.stdout;\n    if (stream && stream.isTTY && stream.columns) {\n      width = stream.columns;\n    }\n\n    // On Windows cmd.exe splits long lines into smaller chunks by inserting the\n    // '\\r\\n' symbols into the stream, this is what cmd.exe does instead of\n    // reflowing the text. We cannot control it. For some unknown reason, even\n    // when the output line is less than number of columns (usually 80), cmd.exe\n    // would still insert new-line chars. These chars break our repainting that\n    // relies on the previous chars to be erasable with '\\b' (end-line chars\n    // can't be erased this way). This is why we report a smaller number than it\n    // is in reality, for safety.\n    if (process.platform === 'win32') {\n      width -= 5;\n    }\n\n    return width;\n  },\n\n  // This can be called during long lived operations; it will keep the spinner spinning.\n  // (This code used to be in Patience.nudge)\n  //\n  // It's frustrating when you write code that takes a while, either because it\n  // uses a lot of CPU or because it uses a lot of network/IO.  In Node,\n  // consuming lots of CPU without yielding is especially bad.\n  // Other IO/network tasks will stall, and you can't even kill the process!\n  //\n  // Within any code that may burn CPU for too long, call `Console.nudge()`.\n  // If it's been a while since your last yield, your Fiber will sleep momentarily.\n  // It will also update the spinner if there is one and it's been a while.\n  // The caller should be OK with yielding --- it has to be in a Fiber and it can't be\n  // anything that depends for correctness on not yielding.  You can also call nudge(false)\n  // if you just want to update the spinner and not yield, but you should avoid this.\n  nudge: function (canYield) {\n    var self = this;\n    if (self._statusPoller) {\n      self._statusPoller.statusPoll();\n    }\n    if (canYield === undefined || canYield === true) {\n      self._throttledYield.yield();\n    }\n  },\n\n  // Initializes and returns a new ConsoleOptions object. Takes in the following\n  // Console options to pass to _wrapText eventually.\n  //\n  //   - bulletPoint: start the first line with a given string, then offset the\n  //     subsequent lines by the length of that string. For example, if the\n  //     bulletpoint is \" => \", we would get:\n  //     \" => some long message starts here\n  //          and then continues here.\"\n  //   - indent: offset the entire string by a specific number of\n  //     characters. For example:\n  //     \"  This entire message is indented\n  //        by two characters.\"\n  //\n  // Passing in both options will offset the bulletPoint by the indentation,\n  // like so:\n  //  \"  this message is indented by two.\"\n  //  \"  => this mesage indented by two and\n  //        and also starts with an arrow.\"\n  //\n  options: function (o) {\n    // (This design pattern allows us to call 'instance of' on the\n    // ConsoleOptions in parseVariadicInput, by ensuring that the object created\n    // with Console.options is, in fact, a new object.\n    return new ConsoleOptions(o);\n  },\n\n  // Deal with the arguments to a variadic print function that also takes an\n  // optional ConsoleOptions argument at the end.\n  //\n  // Returns an object with keys:\n  //  - options: The options that were passed in, or an empty object.\n  //  - message: Arguments to the original function, parsed as a string.\n  //\n  _parseVariadicInput: function (args) {\n    var self = this;\n    var msgArgs;\n    var options;\n    // If the last argument is an instance of ConsoleOptions, then we should\n    // separate it out, and only send the first N-1 arguments to be parsed as a\n    // message.\n    if (_.last(args) instanceof ConsoleOptions) {\n      msgArgs = _.initial(args);\n      options = _.last(args).options;\n    } else {\n      msgArgs = args;\n      options = {};\n    }\n    var message = self._format(msgArgs);\n    return { message: message, options: options };\n  },\n\n  isLevelEnabled: function (levelCode) {\n    return (this.verbose || this._logThreshold <= levelCode);\n  },\n\n  isDebugEnabled: function () {\n    return this.isLevelEnabled(LEVEL_CODE_DEBUG);\n  },\n\n\n  // Don't pretty-fy this output by trying to, for example, line-wrap it. Just\n  // print it to the screen as it is.\n  rawDebug: function(...args) {\n    var self = this;\n    if (! self.isDebugEnabled()) {\n      return;\n    }\n\n    var message = self._format(args);\n    self._print(LEVEL_DEBUG, message);\n  },\n\n  // By default, Console.debug automatically line wraps the output.\n  //\n  // Takes in an optional Console.options({}) argument at the end, with the\n  // following keys:\n  //   - bulletPoint: start the first line with a given string, then offset the\n  //     subsequent lines by the length of that string. See _wrap for more details.\n  //   - indent: offset the entire string by a specific number of\n  //     characters. See _wrap for more details.\n  //\n  debug: function(...args) {\n    var self = this;\n    if (! self.isDebugEnabled()) { return; }\n\n    var message = self._prettifyMessage(args);\n    self._print(LEVEL_DEBUG, message);\n  },\n\n  isInfoEnabled: function () {\n    return this.isLevelEnabled(LEVEL_CODE_INFO);\n  },\n\n  // Don't pretty-fy this output by trying to, for example, line-wrap it. Just\n  // print it to the screen as it is.\n  rawInfo: function(...args) {\n    var self = this;\n    if (! self.isInfoEnabled()) {\n      return;\n    }\n\n    var message = self._format(args);\n    self._print(LEVEL_INFO, message);\n  },\n\n  // Generally, we want to process the output for legibility, for example, by\n  // wrapping it. For raw output (ex: stack traces, user logs, etc), use the\n  // rawInfo function. For more information about options, see: debug.\n  info: function(...args) {\n    var self = this;\n    if (! self.isInfoEnabled()) { return; }\n\n    var message = self._prettifyMessage(args);\n    self._print(LEVEL_INFO, message);\n  },\n\n  isWarnEnabled: function () {\n    return this.isLevelEnabled(LEVEL_CODE_WARN);\n  },\n\n  rawWarn: function(...args) {\n    var self = this;\n    if (! self.isWarnEnabled()) {\n      return;\n    }\n\n    var message = self._format(args);\n    self._print(LEVEL_WARN, message);\n  },\n\n  // Generally, we want to process the output for legibility, for example, by\n  // wrapping it. For raw output (ex: stack traces, user logs, etc), use the\n  // rawWarn function. For more information about options, see: debug.\n  warn: function(...args) {\n    var self = this;\n    if (! self.isWarnEnabled()) { return; }\n\n    var message = self._prettifyMessage(args);\n    self._print(LEVEL_WARN, message);\n  },\n\n  rawError: function(...args) {\n    var self = this;\n\n    var message = self._format(args);\n    self._print(LEVEL_ERROR, message);\n  },\n\n  // Generally, we want to process the output for legibility, for example, by\n  // wrapping it. For raw output (ex: stack traces, user logs, etc), use the\n  // rawError function. For more information about options, see: debug.\n  error: function(...args) {\n    var self = this;\n\n    var message = self._prettifyMessage(args);\n    self._print(LEVEL_ERROR, message);\n  },\n\n  // Prints a special ANSI sequence that \"clears\" the screen (on most terminal\n  // emulators just scrolls the contents down and resets the position).\n  // References: http://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes\n  clear: function () {\n    var self = this;\n\n    self.rawInfo('\\u001b[2J\\u001b[0;0H');\n  },\n\n  _prettifyMessage: function (msgArguments) {\n    var self = this;\n    var parsedArgs = self._parseVariadicInput(msgArguments);\n    var wrapOpts = {\n      indent: parsedArgs.options.indent,\n      bulletPoint: parsedArgs.options.bulletPoint\n    };\n\n    var wrappedMessage = self._wrapText(parsedArgs.message, wrapOpts);\n    wrappedMessage += \"\\n\";\n    return wrappedMessage;\n  },\n\n  _print: function(level, message) {\n    var self = this;\n\n    // We need to hide the progress bar/spinner before printing the message\n    var progressDisplay = self._progressDisplay;\n    progressDisplay.depaint();\n\n    // stdout/stderr is determined by the log level\n    // XXX: We should probably just implement Loggers with observers\n    var dest = process.stdout;\n    if (level) {\n      switch (level.code) {\n        case LEVEL_CODE_ERROR:\n          dest = process.stderr;\n          break;\n        case LEVEL_CODE_WARN:\n          dest = process.stderr;\n          break;\n      }\n    }\n\n    // Pick the color/weight if in pretty mode\n    var style = null;\n    if (level && self._pretty) {\n      switch (level.code) {\n        case LEVEL_CODE_ERROR:\n          style = chalk.bold.red;\n          break;\n        case LEVEL_CODE_WARN:\n          style = chalk.red;\n          break;\n      }\n    }\n\n    if (style) {\n      dest.write(style(message));\n    } else {\n      dest.write(message);\n    }\n\n    // XXX: Pause before showing the progress display, to prevent\n    // flicker/spewing messages\n    // Repaint the progress display\n    progressDisplay.repaint();\n  },\n\n  // A wrapper around Console.info. Prints the message out in green (if pretty),\n  // with the CHECKMARK as the bullet point in front of it.\n  success: function (message) {\n    var self = this;\n    var checkmark;\n\n    if (! self._pretty) {\n      return self.info(message);\n    }\n\n    if (process.platform === \"win32\") {\n      checkmark = chalk.green('SUCCESS');\n    } else {\n      checkmark = chalk.green('\\u2713'); // CHECKMARK\n    }\n\n    return self.info(\n        chalk.green(message),\n        self.options({ bulletPoint: checkmark  + \" \"}));\n  },\n\n  // Wrapper around Console.info. Prints the message out in red (if pretty)\n  // with the BALLOT X as the bullet point in front of it.\n  failInfo: function (message) {\n    var self = this;\n    return self._fail(message, \"info\");\n  },\n\n  // Wrapper around Console.warn. Prints the message out in red (if pretty)\n  // with the ascii x as the bullet point in front of it.\n  failWarn: function (message) {\n    var self = this;\n    return self._fail(message, \"warn\");\n  },\n\n  // Print the message in red (if pretty) with an x bullet point in front of it.\n  _fail: function (message, printFn) {\n    var self = this;\n\n    if (! self._pretty) {\n      return printFn(message);\n    }\n\n    var xmark = chalk.red('\\u2717');\n    return self[printFn](\n        chalk.red(message),\n        self.options({ bulletPoint: xmark + \" \" }));\n  },\n\n  // Wrapper around Console.warn that prints a large \"WARNING\" label in front.\n  labelWarn: function (message) {\n    var self = this;\n    return self.warn(message, self.options({ bulletPoint: \"WARNING: \" }));\n  },\n\n  // Wrappers around Console functions to prints an \"=> \" in front. Optional\n  // indent to indent the arrow.\n  arrowError: function (message, indent) {\n    var self = this;\n    return self._arrowPrint(\"error\", message, indent);\n  },\n  arrowWarn: function (message, indent) {\n    var self = this;\n    return self._arrowPrint(\"warn\", message, indent);\n  },\n  arrowInfo: function (message, indent) {\n    var self = this;\n    return self._arrowPrint(\"info\", message, indent);\n  },\n  _arrowPrint: function(printFn, message, indent) {\n    var self = this;\n    indent = indent || 0;\n    return self[printFn](\n      message,\n      self.options({ bulletPoint: ARROW, indent: indent }));\n  },\n\n  // A wrapper around console.error. Given an error and some background\n  // information, print out the correct set of messages depending on verbose\n  // level, etc.\n  printError: function (err, info) {\n    var self = this;\n\n    var message = err.message;\n    if (! message) {\n      message = \"Unexpected error\";\n      if (self.verbose) {\n        message += \" (\" + err.toString() + \")\";\n      }\n    }\n\n    if (info) {\n      message = info + \": \" + message;\n    }\n\n    self.error(message);\n    if (self.verbose && err.stack) {\n      self.rawInfo(err.stack + \"\\n\");\n    }\n  },\n\n  // A wrapper to print out buildmessage errors.\n  printMessages: function (messages) {\n    var self = this;\n\n    if (messages.hasMessages()) {\n      self.error(\"\\n\" + messages.formatMessages());\n    }\n  },\n\n  // Wrap commands in this function -- it ensures that commands don't get line\n  // wrapped (ie: print 'meteor' at the end of the line, and 'create --example'\n  // at the beginning of the next one).\n  //\n  // To use, wrap commands that you send into print functions with this\n  // function, like so: Console.info(text + Console.command(\"meteor create\n  // --example leaderboard\") + moretext).\n  //\n  // If pretty print is on, this will also bold the commands.\n  command: function (message) {\n    var self = this;\n    var unwrapped = self.noWrap(message);\n    return self.bold(unwrapped);\n  },\n\n  // Underline the URLs (if pretty print is on).\n  url: function (message) {\n    var self = this;\n    // If we are going to print URLs with spaces, we should turn spaces into\n    // things browsers understand.\n    var unspaced =\n          replaceAll(message, ' ', '%20');\n    // There is no need to call noWrap here, since that only handles spaces (and\n    // we have done that). If it ever handles things other than spaces, we\n    // should make sure to call it here.\n    return self.underline(unspaced);\n  },\n\n  // Format a filepath to not wrap. This does NOT automatically escape spaces\n  // (ie: add a slash in front so the user could copy paste the file path into a\n  // terminal).\n  path: function (message) {\n    var self = this;\n    // Make sure that we don't wrap this.\n    var unwrapped = self.noWrap(message);\n    return self.bold(unwrapped);\n  },\n\n  // Do not wrap this substring when you send it into a non-raw print function.\n  // DO NOT print the result of this call with a raw function.\n  noWrap: function (message) {\n    var noBlanks = replaceAll(message, ' ', SPACE_REPLACEMENT);\n    return noBlanks;\n  },\n\n  // A wrapper around the underline functionality of chalk.\n  underline: function (message) {\n    var self = this;\n\n    if (! self._pretty) {\n      return message;\n    }\n    return chalk.underline(message);\n  },\n\n  // A wrapper around the bold functionality of chalk.\n  bold: function (message) {\n    var self = this;\n\n    if (! self._pretty) {\n      return message;\n    }\n    return chalk.bold(message);\n  },\n\n  // Prints a two column table in a nice format (The first column is printed\n  // entirely, the second only as space permits).\n  //  options:\n  //      - level: Allows to print to stderr, instead of stdout. Set the print\n  //        level with Console.LEVEL_INFO, Console.LEVEL_ERROR, etc.\n  //      - ignoreWidth: ignore the width of the terminal, and go over the\n  //        character limit instead of trailing off with '...'. Useful for\n  //        printing directories, for examle.\n  //      - indent: indent the entire table by a given number of spaces.\n  printTwoColumns : function (rows, options) {\n    var self = this;\n    options = options || {};\n\n    var longest = '';\n    _.each(rows, function (row) {\n      var col0 = row[0] || '';\n      if (col0.length > longest.length) {\n        longest = col0;\n      }\n    });\n\n    var pad = longest.replace(/./g, ' ');\n    var width = self.width();\n    var indent =\n      options.indent ? Array(options.indent + 1).join(' ') : \"\";\n\n    var out = '';\n    _.each(rows, function (row) {\n      var col0 = row[0] || '';\n      var col1 = row[1] || '';\n      var line = indent + self.bold(col0) + pad.substr(col0.length);\n      line += \"  \" + col1;\n      if (! options.ignoreWidth && line.length > width) {\n        line = line.substr(0, width - 3) + '...';\n      }\n      out += line + \"\\n\";\n    });\n\n    var level = options.level || self.LEVEL_INFO;\n    out += \"\\n\";\n    self._print(level, out);\n\n    return out;\n  },\n\n  // Format logs according to the spec in utils.\n  _format: function (logArguments) {\n    return util.format.apply(util, logArguments);\n  },\n\n  // Wraps long strings to the length of user's terminal. Inserts linebreaks\n  // between words when nearing the end of the line. Returns the wrapped string\n  // and takes the following arguments:\n  //\n  // text: the text to wrap\n  // options:\n  //   - bulletPoint: (see: Console.options)\n  //   - indent: (see: Console.options)\n  //\n  _wrapText: function (text, options) {\n    var self = this;\n    options = options || {};\n\n    // Compute the maximum offset on the bulk of the message.\n    var maxIndent = 0;\n    if (options.indent && options.indent > 0) {\n      maxIndent = maxIndent + options.indent;\n    }\n    if (options.bulletPoint) {\n      maxIndent = maxIndent + options.bulletPoint.length;\n    }\n\n    // Get the maximum width, or if we are not running in a terminal (self-test,\n    // for example), default to 80 columns.\n    var max = self.width();\n\n    var wrappedText;\n    if (process.env.METEOR_NO_WORDWRAP) {\n      var indent =\n        options.indent ? Array(options.indent + 1).join(' ') : \"\";\n      if (options.bulletPoint) {\n        wrappedText = options.bulletPoint + text;\n      } else {\n        wrappedText = text;\n      }\n      wrappedText = _.map(wrappedText.split('\\n'), function (s) {\n        if (s === \"\") {\n          return \"\";\n        }\n        return indent + s;\n      }).join('\\n');\n\n    } else {\n      // Wrap the text using the npm wordwrap library.\n      wrappedText = wordwrap(maxIndent, max)(text);\n\n      // Insert the start string, if applicable.\n      if (options.bulletPoint) {\n        // Save the initial indent level.\n        var initIndent = options.indent ?\n              wrappedText.substring(0, options.indent) : \"\";\n        // Add together the initial indent (if any), the bullet point and the\n        // remainder of the message.\n        wrappedText = initIndent + options.bulletPoint +\n          wrappedText.substring(maxIndent);\n      }\n    }\n\n    // If we have previously replaces any spaces, now is the time to bring them\n    // back.\n    wrappedText = replaceAll(wrappedText, SPACE_REPLACEMENT, ' ');\n    return wrappedText;\n  },\n\n\n  // Enables the progress bar, or disables it when called with (false)\n  enableProgressDisplay: function (enabled) {\n    var self = this;\n\n    // No arg => enable\n    if (enabled === undefined) {\n      enabled = true;\n    }\n\n    if (self._progressDisplayEnabled === enabled) {\n      return;\n    }\n\n    self._progressDisplayEnabled = enabled;\n    self._updateProgressDisplay();\n  },\n\n  // In response to a change in setPretty or enableProgressDisplay,\n  // configure the appropriate progressDisplay\n  _updateProgressDisplay: function () {\n    var self = this;\n\n    var newProgressDisplay;\n\n    if (! self._progressDisplayEnabled) {\n      newProgressDisplay = new ProgressDisplayNone();\n    } else if ((! self._stream.isTTY) || (! self._pretty)) {\n      // No progress bar if not in pretty / on TTY.\n      newProgressDisplay = new ProgressDisplayNone(self);\n    } else if (self._stream.isTTY && ! self._stream.columns) {\n      // We might be in a pseudo-TTY that doesn't support\n      // clearLine() and cursorTo(...).\n      // It's important that we only enter status message mode\n      // if self._pretty, so that we don't start displaying\n      // status messages too soon.\n      // XXX See note where ProgressDisplayStatus is defined.\n      newProgressDisplay = new ProgressDisplayStatus(self);\n    } else {\n      // Otherwise we can do the full progress bar\n      newProgressDisplay = new ProgressDisplayFull(self);\n    }\n\n    // Start/stop the status poller, so we never block exit\n    if (self._progressDisplayEnabled) {\n      if (! self._statusPoller) {\n        self._statusPoller = new StatusPoller(self);\n      }\n    } else {\n      if (self._statusPoller) {\n        self._statusPoller.stop();\n        self._statusPoller = null;\n      }\n    }\n\n    self._setProgressDisplay(newProgressDisplay);\n  },\n\n  setHeadless(headless) {\n    if (typeof headless === \"undefined\") headless = true;\n    headless = !! headless;\n    if (this._progressDisplay &&\n        this._progressDisplay.setHeadless) {\n      this._progressDisplay.setHeadless(headless);\n    }\n  },\n\n  _setProgressDisplay: function (newProgressDisplay) {\n    var self = this;\n\n    // XXX: Optimize case of no-op transitions? (same mode -> same mode)\n\n    var oldProgressDisplay = self._progressDisplay;\n    oldProgressDisplay.depaint();\n\n    self._progressDisplay = newProgressDisplay;\n  }\n});\n\n// options:\n//   - echo (boolean): defaults to true\n//   - prompt (string)\n//   - stream: defaults to process.stdout (you might want process.stderr)\nConsole.prototype.readLine = function (options) {\n  var self = this;\n\n  options = _.extend({\n    echo: true,\n    stream: self._stream\n  }, options);\n\n  var silentStream = {\n    write: function () {\n    },\n    on: function () {\n    },\n    end: function () {\n    },\n    isTTY: options.stream.isTTY,\n    removeListener: function () {\n    }\n  };\n\n  var previousProgressDisplay = self._progressDisplay;\n  self._setProgressDisplay(new ProgressDisplayNone());\n\n  // Read a line, throwing away the echoed characters into our dummy stream.\n  var rl = readline.createInterface({\n    input: process.stdin,\n    output: options.echo ? options.stream : silentStream,\n    // `terminal: options.stream.isTTY` is the default, but emacs shell users\n    // don't want fancy ANSI.\n    terminal: options.stream.isTTY && process.env.EMACS !== 't'\n  });\n\n  if (! options.echo) {\n    options.stream.write(options.prompt);\n  } else {\n    rl.setPrompt(options.prompt);\n    rl.prompt();\n  }\n\n  return new Promise(function (resolve) {\n    rl.on('line', function (line) {\n      rl.close();\n      if (! options.echo) {\n        options.stream.write(\"\\n\");\n      }\n      self._setProgressDisplay(previousProgressDisplay);\n      resolve(line);\n    });\n  }).await();\n};\n\n\nexports.Console = new Console;\nexports.Console.CARRIAGE_RETURN = CARRIAGE_RETURN;\n"
  },
  {
    "path": "tools/console/progress.js",
    "content": "///\n/// utility functions for computing progress of complex tasks\n///\n/// State callback here is an object with these keys:\n///   done: bool, true if done\n///   current: number, the current progress value\n///   end: number, optional, the value of current where we expect to be done\n///\n/// If end is not set, we'll display a spinner instead of a progress bar\n///\n\nvar _ = require('underscore');\n\nvar Progress = function (options) {\n  var self = this;\n\n  options = options || {};\n\n  self._lastState = null;\n  self._parent = options.parent;\n  self._watchers = options.watchers || [];\n\n  self._title = options.title;\n  if (self._title) {\n    // Capitalize job titles when displayed in the progress bar.\n    self._title = self._title[0].toUpperCase() + self._title.slice(1);\n  }\n\n  // XXX: Should we have a strict/mdg mode that enables this test?\n  //if (!self._title && self._parent) {\n  //  throw new Error(\"No title passed\");\n  //}\n\n  self._forkJoin = options.forkJoin;\n\n  self._allTasks = [];\n\n  self._selfState = { current: 0, done: false };\n  self._state = _.clone(self._selfState);\n\n  self._isDone = false;\n\n  self.startTime = +(new Date);\n};\n\n_.extend(Progress.prototype, {\n  toString: function() {\n    var self = this;\n    return \"Progress [state=\" + JSON.stringify(self._state) + \"]\";\n  },\n\n  reportProgressDone: function () {\n    var self = this;\n\n    var state = _.clone(self._selfState);\n    state.done = true;\n    if (state.end !== undefined) {\n      if (state.current > state.end) {\n        state.end = state.current;\n      }\n      state.current = state.end;\n    }\n    self.reportProgress(state);\n  },\n\n  // Tries to determine which is the 'current' job in the tree\n  // This is very heuristical... we use some hints, like:\n  // don't descend into fork-join jobs; we know these execute concurrently,\n  // so we assume the top-level task has the title\n  // i.e. \"Downloading packages\", not \"downloading supercool-1.0\"\n  getCurrentProgress: function () {\n    var self = this;\n\n    var isRoot = !self._parent;\n\n    if (self._isDone) {\n      // A done task cannot be the active task\n      return null;\n    }\n\n    if (!self._state.done && (self._state.current != 0) && self._state.end &&\n        !isRoot) {\n      // We are not done and we have interesting state to report\n      return self;\n    }\n\n    if (self._forkJoin) {\n      // Don't descend into fork-join tasks (by choice)\n      return self;\n    }\n\n    if (self._allTasks.length) {\n      var candidates = _.map(self._allTasks, function (task) {\n        return task.getCurrentProgress();\n      });\n      var active = _.filter(candidates, function (s) {\n        return !!s;\n      });\n      if (active.length) {\n        // pick one to display, somewhat arbitrarily\n        return active[active.length - 1];\n      }\n      // No single active task, return self\n      return self;\n    }\n\n    return self;\n  },\n\n  // Creates a subtask that must be completed as part of this (bigger) task\n  addChildTask: function (options) {\n    var self = this;\n    options = _.extend({ parent: self }, options || {});\n    var child = new Progress(options);\n    self._allTasks.push(child);\n    self._reportChildState(child, child._state);\n    return child;\n  },\n\n  // Dumps the tree, for debug\n  dump: function (stream, options, prefix) {\n    var self = this;\n\n    options = options || {};\n    if (options.skipDone && self._isDone) {\n      return;\n    }\n\n    if (prefix) {\n      stream.write(prefix);\n    }\n    var end = self._state.end;\n    if (!end) {\n      end = '?';\n    }\n    stream.write(\"Task [\" + self._title + \"] \" + self._state.current + \"/\" + end\n      + (self._isDone ? \" done\" : \"\") +\"\\n\");\n    if (self._allTasks.length) {\n      _.each(self._allTasks, function (child) {\n        child.dump(stream, options, (prefix || '') + '  ');\n      });\n    }\n  },\n\n  // Receives a state report indicating progress of self\n  reportProgress: function (state) {\n    var self = this;\n\n    self._selfState = state;\n\n    self._updateTotalState();\n\n    // Nudge the spinner/progress bar, but don't yield (might not be safe to yield)\n    require('./console.js').Console.nudge(false);\n\n    self._notifyState();\n  },\n\n  // Subscribes a watcher to changes\n  addWatcher: function (watcher) {\n    var self = this;\n\n    self._watchers.push(watcher);\n  },\n\n  // Notifies watchers & parents\n  _notifyState: function () {\n    var self = this;\n\n    if (self._parent) {\n      self._parent._reportChildState(self, self._state);\n    }\n\n    if (self._watchers.length) {\n      _.each(self._watchers, function (watcher) {\n        watcher(self._state);\n      });\n    }\n  },\n\n  // Recomputes state, incorporating children's states\n  _updateTotalState: function () {\n    var self = this;\n\n    var allChildrenDone = true;\n    var state = _.clone(self._selfState);\n    _.each(self._allTasks, function (child) {\n      var childState = child._state;\n\n      if (!child._isDone) {\n        allChildrenDone = false;\n      }\n\n      state.current += childState.current;\n      if (state.end !== undefined) {\n        if (childState.done) {\n          state.end += childState.current;\n        } else if (childState.end !== undefined) {\n          state.end += childState.end;\n        } else {\n          state.end = undefined;\n        }\n      }\n    });\n    self._isDone = allChildrenDone && !!self._selfState.done;\n    if (!allChildrenDone) {\n      state.done = false;\n    }\n\n    if (!state.done && self._state.done) {\n      // This shouldn't happen\n      throw new Error(\"Progress transition from done => !done\");\n    }\n\n    self._state = state;\n  },\n\n  // Called by a child when its state changes\n  _reportChildState: function (child, state) {\n    var self = this;\n\n    self._updateTotalState();\n    self._notifyState();\n  },\n\n  getState: function() {\n    return this._state;\n  }\n});\n\nexports.Progress = Progress;\n"
  },
  {
    "path": "tools/cordova/README.md",
    "content": "# Cordova integration\n\nThe Cordova integration allows running, building and testing of Cordova projects\nfrom the CLI.\n\nIt hooks into the following commands:\n\n* `cli/commands.js`: `meteor run/test-packages/build`\n* `cli/commands-cordova.js`: `meteor add-platform/remove-platform/list-platforms`\n* `cli/commands-packages.js`: `meteor add/remove cordova:<plugin>`\n\nThese commands call into functionality provided by the classes under `cordova/`\n(`CordovaProject`, `CordovaBuilder`, `CordovaRunner`, and `CordovaRunTarget`),\nas well as some utility functions in `cordova/index.js` (generally imported\nunder the `cordova` namespace).\n\n## Project\n\n`CordovaProject` (in `project.js`) represents the generated Cordova project (in\nthe `.meteor/local/cordova-build` directory), and is the only class with a\ndirect dependency on `cordova-lib`. Its methods allow you to call into the\nprepare, build and run stages, and manage platforms and plugins.\n\nIn this version, we've switched from relying on Cordova CLI to using\n`cordova-lib` directly. This avoids multiple levels of script invocations, which\nleads to difficult to diagnose failures and makes it harder to support Windows.\n\nOld situation: Meteor CLI → Meteor Cordova wrapper scripts → Cordova CLI →\nCordova platform-specific scripts\n\nNew situation: Meteor CLI + `cordova-lib` (in-process) → Cordova\nplatform-specific scripts\n\nCommands in `cordova-lib` are invoked asynchronously (they return promises) but\nfor the most part we wait with `Promise.await`. This is abstracted away in\n`runCommands`. There is some other code in `CordovaProject` that helps with\nsetting the `cwd` and `env` and catching `CordovaError`s.\n\n### Stages\n\n* `CordovaProject#createIfNeeded()`\n\nInvoked automatically from the constructor. Makes sure the project has been\ncreated if the `cordova-build` directory does not currently exist.\n\n* `CordovaProject#prepareFromAppBundle(bundlePath, pluginVersions, options = {})`\n\nUses a builder (see `CordovaBuilder`) to generate the `www` directory,\nresources, and `config.xml` based on the app bundle result and\n`mobile-config.js`.\n\n* `CordovaProject#prepareForPlatform(platform)`\n\nSimilar to `cordova prepare <platform>`. Synchronizes the project contents\n(`www` directory and resources) with a platform directory and installs or\nupdates plugins in a platform-specific manner (modifying an Xcode project for\ninstance).\n\n* `CordovaProject#buildForPlatform(platform, options = {}, extraPaths)`\n\nSimilar to `cordova build <platform>`. Uses platform-specific build mechanisms\nto compile app. Includes everything done in the prepare stage. It is used for\n`meteor build`.\n\n* `async CordovaProject#run(platform, isDevice, options = [], extraPaths)`\n\nSimilar to `cordova run <target>`, except that it doesn't include prepare, so\nyou'll have to make sure `CordovaProject#prepareForPlatform()` is called before.\nUses platform-specific mechanisms to run the built app on a device or\nemulator/simulator. It is used for `meteor run/test-packages`.\n\n### Managing platforms\n\n* `CordovaProject#ensurePlatformsAreSynchronized(platforms =\n  this.cordovaPlatformsInApp)`\n\nEnsures the platforms installed in the Cordova project are synchronized with the\napp-level platforms (in `.meteor/platforms`). This gets invoked as part of\n`meteor add-platform/remove-platform` (from `commands-cordova.js`) and as part\nof the build process (from `CordovaBuilder`).\n\nUses methods `CordovaProject#listInstalledPlatforms()`,\n`CordovaProject#addPlatform(platform)`, and\n`CordovaProject#removePlatform(platform)` to call into Cordova.\n\n`CordovaProject#checkPlatformRequirements(platform)` uses the Cordova\nplatform-specific tools to get a list of installation requirements, whether they\nare satisfied, and if not, why. The latter can be very useful and is pretty\ndetailed (telling you for instance that `ANDROID_HOME` has been set to a\nnon-existent directory, or that the right platform tools cannot be found).\n\nWe massage the results a little and print them (only if not all requirements for\na platform are satisfied) in a list with checkmarks and crosses. This may need\nsome work. We probably want to simplify the results a little and only show the\nfull list in a verbose mode. And we definitely want to add a link to a Wiki page\nwith installation instructions.\n\nThis gets invoked from `meteor add-platform` (so we can immediately give\nfeedback about the state of the installation) and before running (from\n`runner.checkPlatformsForRunTargets()`).\n\n### Managing plugins\n\n* `CordovaProject#ensurePluginsAreSynchronized(pluginVersions,\n  pluginsConfiguration = {})`\n\nEnsures the plugins installed in the Cordova project are synchronized with the\napp-level Cordova plugins. This gets invoked as part of the build process (from\n`CordovaBuilder`) where it is passed the plugins from the star manifest in the\napp bundle (`pluginVersionsFromStarManifest`, a combination of\n`.meteor/cordova-plugins` for stand-alone plugin installs and the plugins added\nas dependencies of packages through `Cordova.depends`).\nThe `pluginsConfiguration` comes from `App.configurePlugin` calls in\n`meteor-config.js`.\n\nUses methods `CordovaProject#listInstalledPluginVersions()`,\n`CordovaProject#addPlugin(name, version, config)`,\n`CordovaProject#removePlugins(plugins)` to call into Cordova.\n\n## Running\n\n`CordovaRunner` (in `runner.js`) represents running the app on a set of run\ntargets. It holds a reference to a `cordovaProject` and an array of\n`runTargets`. It is created in `meteor run/test-packages` in `cli/commands.js`\nand gets passed to `AppRunner`.\n\nThis is a change from the previous behavior, where the Cordova build and run had\nto be completed before we could start the proxy, MongoDB, and bundle and run the\nserver app.\n\nOne of the main benefits of this is that we can now use the app bundle generated\nin `AppRunner`. Previously, we were actually doing a whole separate\n`bundler.bundle()` for Cordova, even though the one in `AppRunner` also\ngenerated the `web.cordova` architecture (which is needed to serve it to clients\nas part of Hot Code Push). We now invoke `CordovaRunner#prepareProject()` with\nthe existing bundle result right before starting the server app.\n\nMoving building/running of Cordova apps to `AppRunner` should also allow Cordova\napps to participate in the reload/fix cycle. (We will need to figure out how to\nbest do this. This may also tie in with detecting changed platforms/plugins,\nautomatically restarting the Cordova app when we add a plugin for instance).\n\n`CordovaRunTarget` (in `run-targets.js`) represents a target to run the app on.\nIt has subclasses `iOSRunTarget` and `AndroidRunTarget` that contain some\nplatform-specific behavior (this will be more when we add log tailing again).\nRight now, we only differentiate between running on a device or an\nemulator/simulator. We may want to allow specifying a specific device ID in the\nfuture (so we can select between different connected devices for instance).\n\n`CordovaRunner#startRunTargets()` is responsible for starting the app on the\nassociated run targets (while displaying build messages and a run log entry). It\ncurrently starts the targets asynchronously (in parallel). This means running\nthe app on multiple targets is a lot faster than before. Because we don't\ncurrently have a way of showing multiple progress bars, it may be confusing to\nsee 'Started app on Android emulator` while the build/run is still in progress.\n\n## Building\n\n`CordovaBuilder` (in `builder.js`) represents the process of building a Cordova\nproject from an app bundle. It contains state (`metadata`,\n`additionalConfiguration`, `accessRules`, `imagePaths`, `pluginsConfiguration`)\nthat is built-up through different stages (`initalizeDefaults()`,\n`processControlFile()`) and can be used to generate and copy the `www`\ndirectory, resources, and `config.xml`.\n\n`CordovaBuilder#processControlFile()` is responsible for running the\n`mobile-config.js` control file (passing itself as a context to `App`).\n"
  },
  {
    "path": "tools/cordova/builder.js",
    "content": "import _ from 'underscore';\nimport util from 'util';\nimport { Console } from '../console/console.js';\nimport buildmessage from '../utils/buildmessage.js';\nimport files from '../fs/files.js';\nimport bundler from '../isobuild/bundler.js';\nimport archinfo from '../utils/archinfo.js';\nimport release from '../packaging/release.js';\nimport { load as loadIsopacket } from '../tool-env/isopackets.js';\nimport utils from '../utils/utils.js';\n\nimport { CORDOVA_ARCH } from './index.js';\n\n// Hard-coded size constants\n\nconst iconsIosSizes = {\n  'iphone_2x': '120x120',\n  'iphone_3x': '180x180',\n  'ipad': '76x76',\n  'ipad_2x': '152x152',\n  'ipad_pro': '167x167',\n  'ios_settings': '29x29',\n  'ios_settings_2x': '58x58',\n  'ios_settings_3x': '87x87',\n  'ios_spotlight': '40x40',\n  'ios_spotlight_2x': '80x80'\n};\n\nconst iconsAndroidSizes = {\n  'android_mdpi': '48x48',\n  'android_hdpi': '72x72',\n  'android_xhdpi': '96x96',\n  'android_xxhdpi': '144x144',\n  'android_xxxhdpi': '192x192'\n};\n\nconst launchIosSizes = {\n  'iphone_2x': '640x960',\n  'iphone5': '640x1136',\n  'iphone6': '750x1334',\n  'iphone6p_portrait': '1242x2208',\n  'iphone6p_landscape': '2208x1242',\n  'ipad_portrait': '768x1024',\n  'ipad_portrait_2x': '1536x2048',\n  'ipad_landscape': '1024x768',\n  'ipad_landscape_2x': '2048x1536'\n};\n\nconst launchAndroidSizes = {\n  'android_mdpi_portrait': '320x470',\n  'android_mdpi_landscape': '470x320',\n  'android_hdpi_portrait': '480x640',\n  'android_hdpi_landscape': '640x480',\n  'android_xhdpi_portrait': '720x960',\n  'android_xhdpi_landscape': '960x720',\n  'android_xxhdpi_portrait': '1080x1440',\n  'android_xxhdpi_landscape': '1440x1080'\n};\n\nexport class CordovaBuilder {\n  constructor(projectContext, projectRoot, options) {\n    this.projectContext = projectContext;\n    this.projectRoot = projectRoot;\n    this.options = options;\n\n    this.resourcesPath = files.pathJoin(\n      this.projectRoot,\n      'resources');\n\n    this.initalizeDefaults();\n  }\n\n  initalizeDefaults() {\n    // Convert the appId (a base 36 string) to a number\n    const appIdAsNumber = parseInt(this.projectContext.appIdentifier, 36);\n    // We use the appId to choose a local server port between 12000-13000.\n    // This range should be large enough to avoid collisions with other\n    // Meteor apps, and has also been chosen to avoid collisions\n    // with other apps or services on the device (although this can never be\n    // guaranteed).\n    const localServerPort = 12000 + (appIdAsNumber % 1000);\n\n    this.metadata = {\n      id: 'com.id' + this.projectContext.appIdentifier,\n      version: '0.0.1',\n      buildNumber: undefined,\n      name: files.pathBasename(this.projectContext.projectDir),\n      description: 'New Meteor Mobile App',\n      author: 'A Meteor Developer',\n      email: 'n/a',\n      website: 'n/a',\n      contentUrl: `http://localhost:${localServerPort}/`\n    };\n\n    // Set some defaults different from the Cordova defaults\n    this.additionalConfiguration = {\n      global: {\n        'webviewbounce': false,\n        'DisallowOverscroll': true\n      },\n      platform: {\n          ios: {},\n          android: {}\n      }\n    };\n\n    const packageMap = this.projectContext.packageMap;\n\n    if (packageMap && packageMap.getInfo('launch-screen')) {\n      this.additionalConfiguration.global.AutoHideSplashScreen = false;\n      this.additionalConfiguration.global.SplashScreen = 'screen';\n      this.additionalConfiguration.global.SplashScreenDelay = 5000;\n      this.additionalConfiguration.global.FadeSplashScreenDuration = 250;\n      this.additionalConfiguration.global.ShowSplashScreenSpinner = false;\n    }\n\n    if (packageMap && packageMap.getInfo('mobile-status-bar')) {\n      this.additionalConfiguration.global.StatusBarOverlaysWebView = false;\n      this.additionalConfiguration.global.StatusBarStyle = 'default';\n    }\n\n    // Default access rules.\n    // Rules can be extended with App.accesRule() in mobile-config.js.\n    this.accessRules = {\n      // Allow the app to ask the system to open these types of URLs.\n      // (e.g. in the phone app or an email client)\n      'tel:*': { type: 'intent' },\n      'geo:*': { type: 'intent' },\n      'mailto:*': { type: 'intent' },\n      'sms:*': { type: 'intent' },\n      'market:*': { type: 'intent' },\n      'itms:*': { type: 'intent' },\n      'itms-apps:*': { type: 'intent' },\n\n      // Allow navigation to localhost, which is needed for the local server\n      'http://localhost': { type: 'navigation' }\n    };\n\n    const mobileServerUrl = this.options.mobileServerUrl;\n    const serverDomain = mobileServerUrl ?\n      utils.parseUrl(mobileServerUrl).hostname : null;\n\n    // If the remote server domain is known, allow access to it for XHR and DDP\n    // connections.\n    if (serverDomain) {\n      // Application Transport Security (new in iOS 9) doesn't allow you\n      // to give access to IP addresses (just domains). So we allow access to\n      // everything if we don't have a domain, which sets NSAllowsArbitraryLoads.\n      if (utils.isIPv4Address(serverDomain)) {\n        this.accessRules['*'] = { type: 'network' };\n      } else {\n        this.accessRules['*://' + serverDomain] = { type: 'network' };\n\n        // Android talks to localhost over 10.0.2.2. This config file is used for\n        // multiple platforms, so any time that we say the server is on localhost we\n        // should also say it is on 10.0.2.2.\n        if (serverDomain === 'localhost') {\n          this.accessRules['*://10.0.2.2'] = { type: 'network' };\n        }\n      }\n    }\n\n    this.imagePaths = {\n      icon: {},\n      splash: {}\n    };\n\n    // Defaults are Meteor meatball images located in tools/cordova/assets directory\n    const assetsPath = files.pathJoin(__dirname, 'assets');\n    const iconsPath = files.pathJoin(assetsPath, 'icons');\n    const launchScreensPath = files.pathJoin(assetsPath, 'launchscreens');\n\n    const setDefaultIcon = (size, name) => {\n      const imageFile = files.pathJoin(iconsPath, size + '.png');\n      if (files.exists(imageFile)) {\n        this.imagePaths.icon[name] = imageFile;\n      }\n    };\n\n    const setDefaultLaunchScreen = (size, name) => {\n      const imageFile = files.pathJoin(launchScreensPath, `${size}.png`);\n      if (files.exists(imageFile)) {\n        this.imagePaths.splash[name] = imageFile;\n      }\n    };\n\n    _.each(iconsIosSizes, setDefaultIcon);\n    _.each(iconsAndroidSizes, setDefaultIcon);\n    _.each(launchIosSizes, setDefaultLaunchScreen);\n    _.each(launchAndroidSizes, setDefaultLaunchScreen);\n\n    this.pluginsConfiguration = {};\n  }\n\n  processControlFile() {\n    const controlFilePath =\n      files.pathJoin(this.projectContext.projectDir, 'mobile-config.js');\n\n\n    if (files.exists(controlFilePath)) {\n      Console.debug('Processing mobile-config.js');\n\n      buildmessage.enterJob({ title: `processing mobile-config.js` }, () => {\n        const code = files.readFile(controlFilePath, 'utf8');\n\n        try {\n          files.runJavaScript(code, {\n            filename: 'mobile-config.js',\n            symbols: { App: createAppConfiguration(this) }\n          });\n        } catch (error) {\n          buildmessage.exception(error);\n        }\n      });\n    }\n  }\n\n  writeConfigXmlAndCopyResources(shouldCopyResources = true) {\n    const { XmlBuilder } = loadIsopacket('cordova-support')['xmlbuilder'];\n\n    let config = XmlBuilder.create('widget');\n\n    // Set the root attributes\n    _.each({\n      id: this.metadata.id,\n      version: this.metadata.version,\n      'android-versionCode': this.metadata.buildNumber,\n      'ios-CFBundleVersion': this.metadata.buildNumber,\n      xmlns: 'http://www.w3.org/ns/widgets',\n      'xmlns:cdv': 'http://cordova.apache.org/ns/1.0'\n    }, (value, key) => {\n      if (value) {\n        config.att(key, value);\n      }\n    });\n\n    // Set the metadata\n    config.element('name').txt(this.metadata.name);\n    config.element('description').txt(this.metadata.description);\n    config.element('author', {\n      href: this.metadata.website,\n      email: this.metadata.email\n    }).txt(this.metadata.author);\n\n    // Set the additional global configuration preferences\n    _.each(this.additionalConfiguration.global, (value, key) => {\n      config.element('preference', {\n        name: key,\n        value: value.toString()\n      });\n    });\n\n    config.element('content', { src: this.metadata.contentUrl });\n\n    // Copy all the access rules\n    _.each(this.accessRules, (options, pattern) => {\n      const type = options.type;\n      options = _.omit(options, 'type');\n\n      if (type === 'intent') {\n        config.element('allow-intent', { href: pattern });\n      } else if (type === 'navigation') {\n        config.element('allow-navigation', _.extend({ href: pattern }, options));\n      } else {\n        config.element('access', _.extend({ origin: pattern }, options));\n      }\n    });\n\n    const platformElement = {\n      ios: config.element('platform', {name: 'ios'}),\n      android: config.element('platform', {name: 'android'})\n    }\n\n    // Set the additional platform-specific configuration preferences\n    _.each(this.additionalConfiguration.platform, (prefs, platform) => {\n      _.each(prefs, (value, key) => {\n        platformElement[platform].element('preference', {\n          name: key,\n          value: value.toString()\n        });\n      });\n    });\n\n    if (shouldCopyResources) {\n      // Prepare the resources folder\n      files.rm_recursive(this.resourcesPath);\n      files.mkdir_p(this.resourcesPath);\n\n      Console.debug('Copying resources for mobile apps');\n\n      this.configureAndCopyImages(iconsIosSizes, platformElement.ios, 'icon');\n      this.configureAndCopyImages(iconsAndroidSizes, platformElement.android, 'icon');\n      this.configureAndCopyImages(launchIosSizes, platformElement.ios, 'splash');\n      this.configureAndCopyImages(launchAndroidSizes, platformElement.android, 'splash');\n    }\n\n    Console.debug('Writing new config.xml');\n\n    const configXmlPath = files.pathJoin(this.projectRoot, 'config.xml');\n    const formattedXmlConfig = config.end({ pretty: true });\n    files.writeFile(configXmlPath, formattedXmlConfig, 'utf8');\n  }\n\n  configureAndCopyImages(sizes, xmlElement, tag) {\n    const imageAttributes = (name, width, height, src) => {\n      const androidMatch = /android_(.?.dpi)_(landscape|portrait)/g.exec(name);\n\n      let attributes = {\n        src: src,\n        width: width,\n        height: height\n      };\n\n      // XXX special case for Android\n      if (androidMatch) {\n        attributes.density =\n          androidMatch[2].substr(0, 4) + '-' + androidMatch[1];\n      }\n\n      return attributes;\n    };\n\n    _.each(sizes, (size, name) => {\n      const [width, height] = size.split('x');\n\n      const suppliedPath = this.imagePaths[tag][name];\n      if (!suppliedPath) {\n        return;\n      }\n\n      const suppliedFilename = _.last(suppliedPath.split(files.pathSep));\n      let extension = _.last(suppliedFilename.split('.'));\n\n      // XXX special case for 9-patch png's\n      if (suppliedFilename.match(/\\.9\\.png$/)) {\n        extension = '9.png';\n      }\n\n      const filename = name + '.' + tag + '.' + extension;\n      const src = files.pathJoin('resources', filename);\n\n      // Copy the file to the build folder with a standardized name\n      files.copyFile(\n        files.pathResolve(this.projectContext.projectDir, suppliedPath),\n        files.pathJoin(this.resourcesPath, filename));\n\n      // Set it to the xml tree\n      xmlElement.element(tag, imageAttributes(name, width, height, src));\n    });\n  }\n\n  copyWWW(bundlePath) {\n    const wwwPath = files.pathJoin(this.projectRoot, 'www');\n\n    // Remove existing www\n    files.rm_recursive(wwwPath);\n\n    // Create www and www/application directories\n    const applicationPath = files.pathJoin(wwwPath, 'application');\n    files.mkdir_p(applicationPath);\n\n    // Copy Cordova arch program from bundle to www/application\n    const programPath = files.pathJoin(bundlePath, 'programs', CORDOVA_ARCH);\n    files.cp_r(programPath, applicationPath);\n\n    // Load program.json\n    const programJsonPath = files.convertToOSPath(\n      files.pathJoin(applicationPath, 'program.json'));\n    const program = JSON.parse(files.readFile(programJsonPath, 'utf8'));\n\n    // Load settings\n    const settingsFile = this.options.settingsFile;\n    const settings = settingsFile ?\n      JSON.parse(files.readFile(settingsFile, 'utf8')) : {};\n    const publicSettings = settings['public'];\n\n    // Calculate client hash and append to program\n    this.appendVersion(program, publicSettings);\n\n    // Write program.json\n    files.writeFile(programJsonPath, JSON.stringify(program), 'utf8');\n\n    const bootstrapPage = this.generateBootstrapPage(applicationPath, program, publicSettings);\n    files.writeFile(files.pathJoin(applicationPath, 'index.html'),\n      bootstrapPage, 'utf8');\n  }\n\n  appendVersion(program, publicSettings) {\n    let configDummy = {};\n    configDummy.PUBLIC_SETTINGS = publicSettings || {};\n\n    const { WebAppHashing } =\n      loadIsopacket('cordova-support')['webapp-hashing'];\n    program.version =\n      WebAppHashing.calculateClientHash(program.manifest, null, configDummy);\n  }\n\n  generateBootstrapPage(applicationPath, program, publicSettings) {\n    const meteorRelease =\n      release.current.isCheckout() ? \"none\" : release.current.name;\n\n    const manifest = program.manifest;\n    const autoupdateVersion = process.env.AUTOUPDATE_VERSION || program.version;\n\n    const mobileServerUrl = this.options.mobileServerUrl;\n\n    const runtimeConfig = {\n      meteorRelease: meteorRelease,\n      ROOT_URL: mobileServerUrl,\n      // XXX propagate it from this.options?\n      ROOT_URL_PATH_PREFIX: '',\n      DDP_DEFAULT_CONNECTION_URL: mobileServerUrl,\n      autoupdateVersionCordova: autoupdateVersion,\n      appId: this.projectContext.appIdentifier,\n      meteorEnv: {\n        NODE_ENV: process.env.NODE_ENV || \"production\",\n        TEST_METADATA: process.env.TEST_METADATA || \"{}\"\n      }\n    };\n\n    if (publicSettings) {\n      runtimeConfig.PUBLIC_SETTINGS = publicSettings;\n    }\n\n    const { Boilerplate } =\n      loadIsopacket('cordova-support')['boilerplate-generator'];\n    const boilerplate = new Boilerplate(CORDOVA_ARCH, manifest, {\n      urlMapper: _.identity,\n      pathMapper: (path) => files.convertToOSPath(\n        files.pathJoin(applicationPath, path)),\n      baseDataExtension: {\n        meteorRuntimeConfig: JSON.stringify(\n          encodeURIComponent(JSON.stringify(runtimeConfig)))\n      }\n    });\n\n    return boilerplate.toHTML();\n  }\n\n  copyBuildOverride() {\n    const buildOverridePath =\n      files.pathJoin(this.projectContext.projectDir, 'cordova-build-override');\n\n    if (files.exists(buildOverridePath) &&\n      files.stat(buildOverridePath).isDirectory()) {\n      Console.debug('Copying over the cordova-build-override directory');\n      files.cp_r(buildOverridePath, this.projectRoot);\n    }\n  }\n}\n\nfunction createAppConfiguration(builder) {\n  /**\n   * @namespace App\n   * @global\n   * @summary The App configuration object in mobile-config.js\n   */\n  return {\n    /**\n     * @summary Set your mobile app's core configuration information.\n     * @param {Object} options\n     * @param {String} [options.id,version,name,description,author,email,website]\n     * Each of the options correspond to a key in the app's core configuration\n     * as described in the [Cordova documentation](http://cordova.apache.org/docs/en/5.1.1/config_ref_index.md.html#The%20config.xml%20File_core_configuration_elements).\n     * @memberOf App\n     */\n    info: function (options) {\n      // check that every key is meaningful\n      _.each(options, function (value, key) {\n        if (!_.has(builder.metadata, key)) {\n          throw new Error(\"Unknown key in App.info configuration: \" + key);\n        }\n      });\n\n      _.extend(builder.metadata, options);\n    },\n    /**\n     * @summary Add a preference for your build as described in the\n     * [Cordova documentation](http://cordova.apache.org/docs/en/5.1.1/config_ref_index.md.html#The%20config.xml%20File_global_preferences).\n     * @param {String} name A preference name supported by Cordova's\n     * `config.xml`.\n     * @param {String} value The value for that preference.\n     * @param {String} [platform] Optional. A platform name (either `ios` or `android`) to add a platform-specific preference.\n     * @memberOf App\n     */\n    setPreference: function (key, value, platform) {\n      if (platform) {\n        if (!_.contains(['ios', 'android'], platform)) {\n          throw new Error(`Unknown platform in App.setPreference: ${platform}. \\\nValid platforms are: ios, android.`);\n        }\n\n        builder.additionalConfiguration.platform[platform][key] = value;\n      } else {\n        builder.additionalConfiguration.global[key] = value;\n      }\n    },\n\n    /**\n     * @summary Set the build-time configuration for a Cordova plugin.\n     * @param {String} id The identifier of the plugin you want to\n     * configure.\n     * @param {Object} config A set of key-value pairs which will be passed\n     * at build-time to configure the specified plugin.\n     * @memberOf App\n     */\n    configurePlugin: function (id, config) {\n      builder.pluginsConfiguration[id] = config;\n    },\n\n    /**\n     * @summary Set the icons for your mobile app.\n     * @param {Object} icons An Object where the keys are different\n     * devices and screen sizes, and values are image paths\n     * relative to the project root directory.\n     *\n     * Valid key values:\n     * - `iphone_2x` (120x120)\n     * - `iphone_3x` (180x180)\n     * - `ipad` (76x76)\n     * - `ipad_2x` (152x152)\n     * - `ipad_pro` (167x167)\n     * - `ios_settings` (29x29)\n     * - `ios_settings_2x` (58x58)\n     * - `ios_settings_3x` (87x87)\n     * - `ios_spotlight` (40x40)\n     * - `ios_spotlight_2x` (80x80)\n     * - `android_mdpi` (48x48)\n     * - `android_hdpi` (72x72)\n     * - `android_xhdpi` (96x96)\n     * - `android_xxhdpi` (144x144)\n     * - `android_xxxhdpi` (192x192)\n     * @memberOf App\n     */\n    icons: function (icons) {\n      var validDevices =\n        _.keys(iconsIosSizes).concat(_.keys(iconsAndroidSizes));\n      _.each(icons, function (value, key) {\n        if (!_.include(validDevices, key)) {\n          Console.labelWarn(`${key}: unknown key in App.icons \\\nconfiguration. The key may be deprecated.`);\n        }\n      });\n      _.extend(builder.imagePaths.icon, icons);\n    },\n\n    /**\n     * @summary Set the launch screen images for your mobile app.\n     * @param {Object} launchScreens A dictionary where keys are different\n     * devices, screen sizes, and orientations, and the values are image paths\n     * relative to the project root directory.\n     *\n     * For Android, launch screen images should\n     * be special \"Nine-patch\" image files that specify how they should be\n     * stretched. See the [Android docs](https://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch).\n     *\n     * Valid key values:\n     * - `iphone_2x` (640x960)\n     * - `iphone5` (640x1136)\n     * - `iphone6` (750x1334)\n     * - `iphone6p_portrait` (1242x2208)\n     * - `iphone6p_landscape` (2208x1242)\n     * - `ipad_portrait` (768x1024)\n     * - `ipad_portrait_2x` (1536x2048)\n     * - `ipad_landscape` (1024x768)\n     * - `ipad_landscape_2x` (2048x1536)\n     * - `android_mdpi_portrait` (320x470)\n     * - `android_mdpi_landscape` (470x320)\n     * - `android_hdpi_portrait` (480x640)\n     * - `android_hdpi_landscape` (640x480)\n     * - `android_xhdpi_portrait` (720x960)\n     * - `android_xhdpi_landscape` (960x720)\n     * - `android_xxhdpi_portrait` (1080x1440)\n     * - `android_xxhdpi_landscape` (1440x1080)\n     *\n     * @memberOf App\n     */\n    launchScreens: function (launchScreens) {\n      var validDevices =\n        _.keys(launchIosSizes).concat(_.keys(launchAndroidSizes));\n\n      _.each(launchScreens, function (value, key) {\n        if (!_.include(validDevices, key)) {\n          Console.labelWarn(`${key}: unknown key in App.launchScreens \\\nconfiguration. The key may be deprecated.`);\n        }\n      });\n      _.extend(builder.imagePaths.splash, launchScreens);\n    },\n\n    /**\n     * @summary Set a new access rule based on origin domain for your app.\n     * By default your application has a limited list of servers it can contact.\n     * Use this method to extend this list.\n     *\n     * Default access rules:\n     *\n     * - `tel:*`, `geo:*`, `mailto:*`, `sms:*`, `market:*` are allowed and\n     *   are handled by the system (e.g. opened in the phone app or an email client)\n     * - `http://localhost:*` is used to serve the app's assets from.\n     * - The domain or address of the Meteor server to connect to for DDP and\n     *   hot code push of new versions.\n     *\n     * Read more about domain patterns in [Cordova\n     * docs](http://cordova.apache.org/docs/en/6.0.0/guide_appdev_whitelist_index.md.html).\n     *\n     * Starting with Meteor 1.0.4 access rule for all domains and protocols\n     * (`<access origin=\"*\"/>`) is no longer set by default due to\n     * [certain kind of possible\n     * attacks](http://cordova.apache.org/announcements/2014/08/04/android-351.html).\n     *\n     * @param {String} pattern The pattern defining affected domains or URLs.\n     * @param {Object} [options]\n     * @param {String} options.type Possible values:\n     * - **`'intent'`**: Controls which URLs the app is allowed to ask the system to open.\n     *  (e.g. in the phone app or an email client).\n     * - **`'navigation'`**: Controls which URLs the WebView itself can be navigated to\n     *  (can also needed for iframes).\n     * - **`'network'` or undefined**: Controls which network requests (images, XHRs, etc) are allowed to be made.\n     * @param {Boolean} options.launchExternal (Deprecated, use `type: 'intent'` instead.)\n     * @memberOf App\n     */\n    accessRule: function (pattern, options) {\n      options = options || {};\n\n      if (options.launchExternal) {\n        options.type = 'intent';\n      }\n\n      builder.accessRules[pattern] = options;\n    }\n  };\n}\n"
  },
  {
    "path": "tools/cordova/index.js",
    "content": "import _ from 'underscore';\nimport assert from 'assert';\nimport utils from '../utils/utils.js';\nimport buildmessage from '../utils/buildmessage.js';\n\nimport { oldToNew as oldToNewPluginIds, newToOld as newToOldPluginIds }\n  from 'cordova-lib/node_modules/cordova-registry-mapper';\n\nexport const CORDOVA_ARCH = \"web.cordova\";\n\nexport const CORDOVA_PLATFORMS = ['ios', 'android'];\n\nexport const CORDOVA_PLATFORM_VERSIONS = {\n  'android': '5.1.1',\n  'ios': '4.1.0'\n};\n\nconst PLATFORM_TO_DISPLAY_NAME_MAP = {\n  'ios': 'iOS',\n  'android': 'Android'\n};\n\nexport function displayNameForPlatform(platform) {\n  return PLATFORM_TO_DISPLAY_NAME_MAP[platform] || platform;\n};\n\nexport function displayNamesForPlatforms(platforms) {\n  return platforms.map((platform) =>\n    displayNameForPlatform(platform)).join(', ');\n}\n\n// This filters the Cordova platforms from a list of app-level platforms.\n// Right now, the only other platforms are the default browser and server\n// platforms.\nexport function filterPlatforms(platforms) {\n  return _.intersection(platforms, CORDOVA_PLATFORMS);\n}\n\nexport function splitPluginsAndPackages(packages) {\n  let result = {\n    plugins: [],\n    packages: []\n  };\n\n  for (let pkg of packages) {\n    const [namespace, ...rest] = pkg.split(':');\n    if (namespace === 'cordova') {\n      const name = rest.join(':');\n      result.plugins.push(name);\n    } else {\n      result.packages.push(pkg);\n    }\n  }\n\n  return result;\n}\n\n// Returns the cordovaDependencies of the Cordova arch from a star manifest.\nexport function pluginVersionsFromStarManifest(star) {\n  var cordovaProgram = _.findWhere(star.programs, { arch: CORDOVA_ARCH });\n  return cordovaProgram ? cordovaProgram.cordovaDependencies : {};\n}\n\nexport function newPluginId(id) {\n  return oldToNewPluginIds[id];\n}\n\nexport function convertPluginVersions(pluginVersions) {\n  assert(pluginVersions);\n  buildmessage.assertInJob();\n\n  let newPluginVersions = {};\n\n  _.each(pluginVersions, (version, id) => {\n    if (utils.isUrlWithSha(version)) {\n      version = convertToGitUrl(version);\n      if (!version) {\n        // convertToGitUrl will add an error to buildmessage messages\n        return;\n      }\n    }\n\n    const newId = newPluginId(id);\n\n    if (newId) {\n      // If the plugin has already been added using the new ID, we do not\n      // overwrite the version.\n      if (!_.has(pluginVersions, newId)) {\n        newPluginVersions[newId] = version;\n      }\n    } else {\n      newPluginVersions[id] = version;\n    }\n  });\n\n  return newPluginVersions;\n}\n\n// Convert old-style GitHub tarball URLs to new Git URLs, and check if other\n// Git URLs contain a SHA reference.\nexport function convertToGitUrl(url) {\n  buildmessage.assertInJob();\n\n  // Matches GitHub tarball URLs, like:\n  // https://github.com/meteor/com.meteor.cordova-update/tarball/92fe99b7248075318f6446b288995d4381d24cd2\n  const match =\n    url.match(/^https?:\\/\\/github.com\\/(.+?)\\/(.+?)\\/tarball\\/([0-9a-f]{40})/);\n  if (match) {\n      const [, organization, repository, sha] = match;\n    // Convert them to a Git URL\n    return `https://github.com/${organization}/${repository}.git#${sha}`;\n  // We only support Git URLs with a SHA reference to guarantee repeatability\n  // of builds\n  } else if (/\\.git#[0-9a-f]{40}/.test(url)) {\n    return url;\n  } else {\n    buildmessage.error(`Meteor no longer supports installing Cordova plugins \\\nfrom arbitrary tarball URLs. You can either add a plugin from a Git URL with \\\na SHA reference, or from a local path. (Attempting to install from ${url}.)`);\n    return null;\n  }\n}\n\nfunction displayNameForHostPlatform(platform = process.platform) {\n  switch (platform) {\n    case 'darwin':\n      return \"Mac\";\n    case 'linux':\n      return \"Linux\";\n    case 'win32':\n      return \"Windows\";\n  }\n}\n"
  },
  {
    "path": "tools/cordova/project.js",
    "content": "import _ from 'underscore';\nimport util from 'util';\nimport assert from 'assert';\nimport chalk from 'chalk';\nimport semver from 'semver';\n\nimport files from '../fs/files.js';\nimport utils from '../utils/utils.js';\nimport { Console } from '../console/console.js';\nimport buildmessage from '../utils/buildmessage.js';\nimport main from '../cli/main.js';\nimport httpHelpers from '../utils/http-helpers.js';\nimport { execFileSync, execFileAsync } from '../utils/processes.js';\n\nimport './protect-string-proto.js'; // must always come before 'cordova-lib'\nimport { cordova as cordova_lib, events as cordova_events, CordovaError }\n  from 'cordova-lib';\nimport cordova_util from 'cordova-lib/src/cordova/util.js';\nimport superspawn from 'cordova-lib/node_modules/cordova-common/src/superspawn.js';\nimport PluginInfoProvider from 'cordova-lib/node_modules/cordova-common/src/PluginInfo/PluginInfoProvider.js';\n\nimport { CORDOVA_PLATFORMS, CORDOVA_PLATFORM_VERSIONS, displayNameForPlatform, displayNamesForPlatforms,\n  newPluginId, convertPluginVersions, convertToGitUrl } from './index.js';\nimport { CordovaBuilder } from './builder.js';\n\ncordova_events.on('verbose', logIfVerbose);\ncordova_events.on('log', logIfVerbose);\ncordova_events.on('info', logIfVerbose);\ncordova_events.on('warn', log);\ncordova_events.on('error', log);\n\ncordova_events.on('results', logIfVerbose);\n\nfunction logIfVerbose(...args) {\n  if (Console.verbose) {\n    log(...args);\n  }\n};\n\nfunction log(...args) {\n  Console.rawInfo(`%% ${util.format.apply(null, args)}\\n`);\n}\n\n// We pin platform versions ourselves instead of relying on cordova-lib\n// so we we can update them independently (e.g. use Cordova iOS 4.0.1\n// with Cordova 5.4.1)\nconst pinnedPlatformVersions = CORDOVA_PLATFORM_VERSIONS;\n\n// We pin plugin versions to make sure we do not install versions that are\n// incompatible with the current platform versions.\n// Versions are taken from cordova-lib's package.json and should be updated\n// when we update to a newer version of cordova-lib.\nconst pinnedPluginVersions = {\n  \"cordova-plugin-battery-status\": \"1.1.1\",\n  \"cordova-plugin-camera\": \"2.1.1\",\n  \"cordova-plugin-console\": \"1.0.2\",\n  \"cordova-plugin-contacts\": \"2.0.1\",\n  \"cordova-plugin-device\": \"1.1.1\",\n  \"cordova-plugin-device-motion\": \"1.2.0\",\n  \"cordova-plugin-device-orientation\": \"1.0.2\",\n  \"cordova-plugin-dialogs\": \"1.2.0\",\n  \"cordova-plugin-file\": \"4.1.1\",\n  \"cordova-plugin-file-transfer\": \"1.5.0\",\n  \"cordova-plugin-geolocation\": \"2.1.0\",\n  \"cordova-plugin-globalization\": \"1.0.3\",\n  \"cordova-plugin-inappbrowser\": \"1.3.0\",\n  \"cordova-plugin-legacy-whitelist\": \"1.1.1\",\n  \"cordova-plugin-media\": \"2.2.0\",\n  \"cordova-plugin-media-capture\": \"1.2.0\",\n  \"cordova-plugin-network-information\": \"1.2.0\",\n  \"cordova-plugin-splashscreen\": \"3.2.1\",\n  \"cordova-plugin-statusbar\": \"2.1.2\",\n  \"cordova-plugin-test-framework\": \"1.1.1\",\n  \"cordova-plugin-vibration\": \"2.1.0\",\n  \"cordova-plugin-whitelist\": \"1.2.1\"\n}\n\nexport class CordovaProject {\n  constructor(projectContext, options = {}) {\n\n    this.projectContext = projectContext;\n\n    this.projectRoot = projectContext.getProjectLocalDirectory('cordova-build');\n    this.options = options;\n\n    this.pluginsDir = files.pathJoin(this.projectRoot, 'plugins');\n\n    this.createIfNeeded();\n  }\n\n  createIfNeeded() {\n    buildmessage.assertInJob();\n\n    // Check if we have an existing Cordova project directory with outdated\n    // platforms. In that case, we remove the whole directory to avoid issues.\n    if (files.exists(this.projectRoot)) {\n      const installedPlatforms = this.listInstalledPlatforms();\n\n      const outdated = _.some(pinnedPlatformVersions, (pinnedVersion, platform) => {\n        // If the platform is not installed, it cannot be outdated\n        if (!_.contains(installedPlatforms, platform)) {\n          return false;\n        }\n\n        const installedVersion = this.installedVersionForPlatform(platform);\n        // If we cannot establish the installed version, we consider it outdated\n        if (!installedVersion) {\n          return true;\n        }\n\n        return semver.lt(installedVersion, pinnedVersion);\n      });\n\n      if (outdated) {\n        Console.debug(`Removing Cordova project directory to avoid issues with\noutdated platforms`);\n        // Remove Cordova project directory to start afresh\n        // and avoid a broken project\n        files.rm_recursive(this.projectRoot);\n      }\n    }\n\n    if (!files.exists(this.projectRoot)) {\n      // We create a temporary directory with a generated config.xml\n      // to use as a template for creating the Cordova project\n      // This way, we are not dependent on the contents of\n      // cordova-app-hello-world but we base our initial project state on\n      // our own defaults and optionally a mobile-config.js\n\n      const templatePath = files.mkdtemp('cordova-template-');\n\n      // If we don't create an empty hooks directory, cordova-lib will attempt\n      // to install one from a hardcoded path to cordova-app-hello-world\n      files.mkdir_p(files.pathJoin(templatePath, 'hooks'));\n\n      // If we don't create an empty www directory, cordova-lib will get\n      // confused\n      files.mkdir_p(files.pathJoin(templatePath, 'www'));\n\n      const builder = new CordovaBuilder(this.projectContext, templatePath,\n        { mobileServerUrl, settingsFile } = this.options);\n\n      builder.processControlFile();\n\n      if (buildmessage.jobHasMessages()) {\n        return;\n      }\n\n      // Don't copy resources (they will be copied as part of the prepare)\n      builder.writeConfigXmlAndCopyResources(false);\n\n      // Create the Cordova project root directory\n      files.mkdir_p(files.pathDirname(this.projectRoot));\n\n      const config = { lib:\n        { www: { url: files.convertToOSPath(templatePath) } } };\n\n      // Don't set cwd to project root in runCommands because it doesn't\n      // exist yet\n      this.runCommands('creating Cordova project', async () => {\n        // No need to pass in appName and appId because these are set from\n        // the generated config.xml\n        await cordova_lib.raw.create(files.convertToOSPath(this.projectRoot),\n          undefined, undefined, config);\n      }, undefined, null);\n    }\n  }\n\n  // Preparing\n\n  prepareFromAppBundle(bundlePath, pluginVersions) {\n    assert(bundlePath);\n    assert(pluginVersions);\n\n    buildmessage.assertInJob();\n\n    Console.debug('Preparing Cordova project from app bundle');\n\n    const builder = new CordovaBuilder(this.projectContext, this.projectRoot,\n      { mobileServerUrl, settingsFile } = this.options);\n\n    builder.processControlFile();\n\n    if (buildmessage.jobHasMessages()) {\n      return;\n    }\n\n    builder.writeConfigXmlAndCopyResources();\n    builder.copyWWW(bundlePath);\n\n    this.ensurePlatformsAreSynchronized();\n    this.ensurePluginsAreSynchronized(pluginVersions,\n      builder.pluginsConfiguration);\n\n    // Temporary workaround for Cordova iOS bug until\n    // https://issues.apache.org/jira/browse/CB-10885 is fixed\n    const iosBuildExtrasPath =\n      files.pathJoin(\n        this.projectRoot,\n        'platforms/ios/cordova/build-extras.xcconfig');\n\n    if (files.exists(iosBuildExtrasPath)) {\n      files.writeFile(\n        iosBuildExtrasPath,\n        'LD_RUNPATH_SEARCH_PATHS = @executable_path/Frameworks;');\n    }\n\n    builder.copyBuildOverride();\n  }\n\n  prepareForPlatform(platform) {\n    assert(platform);\n\n    const commandOptions = _.extend(this.defaultOptions,\n      { platforms: [platform] });\n\n    this.runCommands(`preparing Cordova project for platform \\\n${displayNameForPlatform(platform)}`, async () => {\n      await cordova_lib.raw.prepare(commandOptions);\n    });\n  }\n\n  // Building (includes prepare)\n\n  buildForPlatform(platform, options = {}, extraPaths) {\n    assert(platform);\n\n    const commandOptions = _.extend(this.defaultOptions,\n      { platforms: [platform], options: options });\n\n    this.runCommands(`building Cordova app for platform \\\n${displayNameForPlatform(platform)}`, async () => {\n      await cordova_lib.raw.build(commandOptions);\n    });\n  }\n\n  // Running\n\n  async run(platform, isDevice, options = [], extraPaths = []) {\n    options.push(isDevice ? '--device' : '--emulator');\n\n    let env = this.defaultEnvWithPathsAdded(...extraPaths);\n\n    let command = files.convertToOSPath(files.pathJoin(\n      this.projectRoot, 'platforms', platform, 'cordova', 'run'));\n\n    this.runCommands(`running Cordova app for platform \\\n${displayNameForPlatform(platform)} with options ${options}`,\n    execFileAsync(command, options, {\n      env: env,\n      cwd: this.projectRoot,\n      stdio: Console.verbose ? 'inherit' : 'pipe',\n      waitForClose: false\n    }), null, null);\n  }\n\n  // Platforms\n\n  // Checks to see if the requirements for building and running on the\n  // specified Cordova platform are satisfied, printing\n  // installation instructions when needed.\n  checkPlatformRequirements(platform) {\n    if (platform === 'ios' && process.platform !== 'darwin') {\n      Console.warn(\"Currently, it is only possible to build iOS apps \\\non an OS X system.\");\n      return false;\n    }\n\n    const installedPlatforms = this.listInstalledPlatforms();\n\n    const inProject = _.contains(installedPlatforms, platform);\n    if (!inProject) {\n      Console.warn(`Please add the ${displayNameForPlatform(platform)} \\\nplatform to your project first.`);\n      Console.info(`Run: ${Console.command(`meteor add-platform ${platform}`)}`);\n      return false;\n    }\n\n    const allRequirements = this.runCommands(`checking Cordova \\\nrequirements for platform ${displayNameForPlatform(platform)}`,\n      async () => {\n        return await cordova_lib.raw.requirements([platform],\n          this.defaultOptions);\n      });\n    let requirements = allRequirements && allRequirements[platform];\n    if (!requirements) {\n      Console.error(`Failed to check requirements for platform \\\n${displayNameForPlatform(platform)}`);\n      return false;\n    } else if (requirements instanceof CordovaError) {\n      Console.error(`Cordova error: ${requirements.message}`);\n      return false;\n    }\n\n    // We don't use ios-deploy, but open Xcode to run on a device instead\n    requirements = _.reject(requirements,\n      requirement => requirement.id === 'ios-deploy');\n\n    const satisfied = _.every(requirements,\n      requirement => requirement.installed);\n\n    if (!satisfied) {\n      Console.info();\n      Console.info(`Your system does not yet seem to fulfill all requirements \\\nto build apps for ${displayNameForPlatform(platform)}.`);\n\n      Console.info();\n      Console.info(\"Please follow the installation instructions in the mobile guide:\");\n      Console.info(Console.url(\"http://guide.meteor.com/mobile.html#installing-prerequisites\"));\n\n      Console.info();\n\n      Console.info(\"Status of the individual requirements:\");\n      for (requirement of requirements) {\n        const name = requirement.name;\n        if (requirement.installed) {\n          Console.success(name);\n        } else {\n          const reason = requirement.metadata && requirement.metadata.reason;\n          if (reason) {\n            Console.failInfo(`${name}: ${reason}`);\n          } else {\n            Console.failInfo(name);\n          }\n        }\n      }\n    }\n    return satisfied;\n  }\n\n  listInstalledPlatforms() {\n    return cordova_util.listPlatforms(files.convertToOSPath(this.projectRoot));\n  }\n\n  installedVersionForPlatform(platform) {\n    const command = files.convertToOSPath(files.pathJoin(\n      this.projectRoot, 'platforms', platform, 'cordova', 'version'));\n    // Make sure the command exists before trying to execute it\n    if (files.exists(command)) {\n      return this.runCommands(\n        `getting installed version for platform ${platform} in Cordova project`,\n        execFileSync(command, {\n          env: this.defaultEnvWithPathsAdded(),\n          cwd: this.projectRoot}), null, null);\n    } else {\n      return null;\n    }\n  }\n\n  updatePlatforms(platforms = this.listInstalledPlatforms()) {\n    this.runCommands(`updating Cordova project for platforms \\\n${displayNamesForPlatforms(platforms)}`, async () => {\n      await cordova_lib.raw.platform('update', platforms, this.defaultOptions);\n    });\n  }\n\n  addPlatform(platform) {\n    this.runCommands(`adding platform ${displayNameForPlatform(platform)} \\\nto Cordova project`, async () => {\n      let version = pinnedPlatformVersions[platform];\n      let platformSpec = version ? `${platform}@${version}` : platform;\n      await cordova_lib.raw.platform('add', platformSpec, this.defaultOptions);\n    });\n  }\n\n  removePlatform(platform) {\n    this.runCommands(`removing platform ${displayNameForPlatform(platform)} \\\nfrom Cordova project`, async () => {\n      await cordova_lib.raw.platform('rm', platform, this.defaultOptions);\n    });\n  }\n\n  get cordovaPlatformsInApp() {\n    return this.projectContext.platformList.getCordovaPlatforms();\n  }\n\n  // Ensures that the Cordova platforms are synchronized with the app-level\n  // platforms.\n  ensurePlatformsAreSynchronized(platforms = this.cordovaPlatformsInApp) {\n    buildmessage.assertInCapture();\n\n    const installedPlatforms = this.listInstalledPlatforms();\n\n    for (platform of platforms) {\n      if (_.contains(installedPlatforms, platform)) {\n        continue;\n      }\n\n      this.addPlatform(platform);\n    }\n\n    for (platform of installedPlatforms) {\n      if (!_.contains(platforms, platform) &&\n        _.contains(CORDOVA_PLATFORMS, platform)) {\n        this.removePlatform(platform);\n      }\n    }\n  }\n\n  // Plugins\n\n  // Because PluginInfoProvider reads in the plugin versions from\n  // their plugin.xml, that only gives us the declared version and doesn't\n  // tell us if plugins have been fetched from a Git SHA URL or a local path.\n  // So we overwrite the declared versions with versions from\n  // listFetchedPluginVersions that do contain this information.\n  listInstalledPluginVersions() {\n    const pluginInfoProvider = new PluginInfoProvider();\n    const installedPluginVersions = pluginInfoProvider.getAllWithinSearchPath(\n      files.convertToOSPath(this.pluginsDir));\n    const fetchedPluginVersions = this.listFetchedPluginVersions();\n    return _.object(installedPluginVersions.map(pluginInfo => {\n      const id = pluginInfo.id;\n      const version = fetchedPluginVersions[id] || pluginInfo.version;\n      return [id, version];\n    }));\n  }\n\n  // There is no Cordova function to get the fetched plugin versions, so we\n  // have to read in fetch.json (a file managed by plugman, a semi-independent\n  // part of cordova-lib) and parse the format ourselves into a version\n  // string suitable to be passed to targetForPlugin.\n  // Note that a plugin can be fetched but not installed, so that's why we\n  // still need a separate listInstalledPluginVersions.\n  listFetchedPluginVersions() {\n    const fetchJsonPath = files.pathJoin(this.pluginsDir, 'fetch.json');\n\n    if (!files.exists(fetchJsonPath)) {\n      return {};\n    }\n\n    const fetchedPluginsMetadata = JSON.parse(files.readFile(\n      fetchJsonPath, 'utf8'));\n    return _.object(_.map(fetchedPluginsMetadata, (metadata, id) => {\n      const source = metadata.source;\n      let version;\n      if (source.type === 'registry') {\n        version = source.id.split('@')[1];\n      } else if (source.type === 'git') {\n        version = `${source.url}#${source.ref}`;\n      } else if (source.type === 'local') {\n        version = `file://${source.path}`;\n      }\n      return [id, version];\n    }));\n  }\n\n  // Construct a target suitable for 'cordova plugin add' from an id and\n  // version, converting or resolving a URL or path where needed.\n  targetForPlugin(id, version) {\n    assert(id);\n    assert(version);\n\n    buildmessage.assertInJob();\n\n    if (utils.isUrlWithSha(version)) {\n      return convertToGitUrl(version);\n    } else if (utils.isUrlWithFileScheme(version)) {\n      // Strip file:// and resolve the path relative to the cordova-build\n      // directory\n      const pluginPath = this.resolveLocalPluginPath(version);\n      // We need to check if the directory exists ourselves because Cordova\n      // will try to install from npm (and fail with an unhelpful error message)\n      // if the directory is not found\n      const stat = files.statOrNull(pluginPath);\n      if (!(stat && stat.isDirectory())) {\n        buildmessage.error(`Couldn't find local directory \\\n'${files.convertToOSPath(pluginPath)}' \\\n(while attempting to install plugin ${id}).`);\n        return null;\n      }\n      return files.convertToOSPath(pluginPath);\n    } else {\n      return `${id}@${version}`;\n    }\n  }\n\n  // Strips file:// and resolves the path relative to the cordova-build\n  // directory\n  resolveLocalPluginPath(pluginPath) {\n    pluginPath = pluginPath.substr(\"file://\".length);\n    if (utils.isPathRelative(pluginPath)) {\n      return files.pathResolve(this.projectContext.projectDir, pluginPath);\n    } else {\n      return pluginPath;\n    }\n  }\n\n  addPlugin(id, version, config = {}) {\n    const target = this.targetForPlugin(id, version);\n    if (target) {\n      const commandOptions = _.extend(this.defaultOptions,\n        { cli_variables: config, link: utils.isUrlWithFileScheme(version) });\n\n      this.runCommands(`adding plugin ${target} \\\nto Cordova project`, async () => {\n        await cordova_lib.raw.plugin('add', [target], commandOptions);\n      });\n    }\n  }\n\n  // plugins is an array of plugin IDs.\n  removePlugins(plugins) {\n    if (_.isEmpty(plugins)) {\n      return;\n    }\n\n    this.runCommands(`removing plugins ${plugins} \\\nfrom Cordova project`, async () => {\n      await cordova_lib.raw.plugin('rm', plugins, this.defaultOptions);\n    });\n  }\n\n  // Ensures that the Cordova plugins are synchronized with the app-level\n  // plugins.\n  ensurePluginsAreSynchronized(pluginVersions, pluginsConfiguration = {}) {\n    assert(pluginVersions);\n\n    buildmessage.assertInCapture();\n\n    buildmessage.enterJob({ title: \"installing Cordova plugins\"}, () => {\n      // Cordova plugin IDs have changed as part of moving to npm.\n      // We convert old plugin IDs to new IDs in the 1.2.0-cordova-changes\n      // upgrader and when adding plugins, but packages may still depend on\n      // the old IDs.\n      // To avoid attempts at duplicate installation, we check for old IDs here\n      // and convert them to new IDs when needed. We also convert old-style GitHub\n      // tarball URLs to new Git URLs, and check if other Git URLs contain a\n      // SHA reference.\n      pluginVersions = convertPluginVersions(pluginVersions);\n\n      // To ensure we do not attempt to install plugin versions incompatible\n      // with the current platform versions, we compare them against a list of\n      // pinned versions and adjust them if necessary.\n      this.ensurePinnedPluginVersions(pluginVersions);\n\n      if (buildmessage.jobHasMessages()) {\n        return;\n      }\n\n      // Also, we warn if any App.configurePlugin calls in mobile-config.js\n      // need to be updated (and in the meantime we take care of the\n      // conversion of the plugin configuration to the new ID).\n      pluginsConfiguration = _.object(_.map(pluginsConfiguration, (config, id) => {\n        const newId = newPluginId(id);\n        if (newId) {\n          Console.warn();\n          Console.labelWarn(`Cordova plugin ${id} has been renamed to ${newId} \\\nas part of moving to npm. Please change the App.configurePlugin call in \\\nmobile-config.js accordingly.`);\n          return [newId, config];\n        } else {\n          return [id, config];\n        }\n      }));\n\n      const installedPluginVersions =\n        convertPluginVersions(this.listInstalledPluginVersions());\n\n      // Due to the dependency structure of Cordova plugins, it is impossible to\n      // upgrade the version on an individual Cordova plugin. Instead, whenever\n      // a new Cordova plugin is added or removed, or its version is changed,\n      // we just reinstall all of the plugins.\n      let shouldReinstallAllPlugins = false;\n\n      // Iterate through all of the plugins and find if any of them have a new\n      // version. Additionally, check if we have plugins installed from a local\n      // path.\n      const pluginsFromLocalPath = {};\n      _.each(pluginVersions, (version, id) => {\n        // Check if plugin is installed from a local path.\n        const isPluginFromLocalPath = utils.isUrlWithFileScheme(version);\n\n        if (isPluginFromLocalPath) {\n          pluginsFromLocalPath[id] = version;\n        } else {\n          if (!_.has(installedPluginVersions, id) ||\n            installedPluginVersions[id] !== version) {\n            // We do not have the plugin installed or the version has changed.\n            shouldReinstallAllPlugins = true;\n          }\n        }\n      });\n\n      if (!_.isEmpty(pluginsFromLocalPath)) {\n        Console.debug('Reinstalling Cordova plugins added from the local path');\n      }\n\n      // Check to see if we have any installed plugins that are not in the\n      // current set of plugins.\n      _.each(installedPluginVersions, (version, id) => {\n        if (!_.has(pluginVersions, id)) {\n          shouldReinstallAllPlugins = true;\n        }\n      });\n\n      // We either reinstall all plugins or only those fetched from a local\n      // path.\n      if (shouldReinstallAllPlugins || !_.isEmpty(pluginsFromLocalPath)) {\n        let pluginsToRemove;\n        if (shouldReinstallAllPlugins) {\n          pluginsToRemove = Object.keys(installedPluginVersions);\n        } else {\n          // Only try to remove plugins that are currently installed.\n          pluginsToRemove = _.intersection(\n            Object.keys(pluginsFromLocalPath),\n            Object.keys(installedPluginVersions));\n        }\n\n        this.removePlugins(pluginsToRemove);\n\n        // Now install the necessary plugins.\n        if (shouldReinstallAllPlugins) {\n          pluginVersionsToInstall = pluginVersions;\n        } else {\n          pluginVersionsToInstall = pluginsFromLocalPath;\n        }\n\n        const pluginsToInstallCount = _.size(pluginVersionsToInstall);\n        let installedPluginsCount = 0;\n\n        buildmessage.reportProgress({ current: 0, end: pluginsToInstallCount });\n        _.each(pluginVersionsToInstall, (version, id) => {\n          this.addPlugin(id, version, pluginsConfiguration[id]);\n\n          buildmessage.reportProgress({\n            current: ++installedPluginsCount,\n            end: pluginsToInstallCount\n          });\n        });\n      }\n    });\n  }\n\n  ensurePinnedPluginVersions(pluginVersions) {\n    assert(pluginVersions);\n\n    _.each(pluginVersions, (version, id) => {\n      // Skip plugin specs that are not actual versions\n      if (utils.isUrlWithSha(version) || utils.isUrlWithFileScheme(version)) {\n        return;\n      }\n\n      const pinnedVersion = pinnedPluginVersions[id];\n\n      if (pinnedVersion && semver.lt(version, pinnedVersion)) {\n        Console.labelWarn(`Attempting to install plugin ${id}@${version}, but \\\nit should have a minimum version of ${pinnedVersion} to ensure compatibility \\\nwith the current platform versions. Installing the minimum version for \\\nconvenience, but you should adjust your dependencies.`);\n        pluginVersions[id] = pinnedVersion;\n      }\n    });\n  }\n\n  // Cordova commands support\n\n  get defaultOptions() {\n    return { silent: !Console.verbose, verbose: Console.verbose };\n  }\n\n  defaultEnvWithPathsAdded(...extraPaths) {\n    let paths = (this.defaultPaths || []);\n    paths.unshift(...extraPaths);\n    const env = files.currentEnvWithPathsAdded(...paths);\n    return env;\n  }\n\n  get defaultPaths() {\n    const nodeBinDir = files.getCurrentNodeBinDir();\n\n    // Add the ios-sim bin path so Cordova can find it\n    const iosSimBinPath =\n      files.pathJoin(files.getDevBundle(),\n      'lib/node_modules/ios-sim/bin');\n\n    return [nodeBinDir, iosSimBinPath];\n  }\n\n  runCommands(title, promiseOrAsyncFunction, env = this.defaultEnvWithPathsAdded(),\n    cwd = this.projectRoot) {\n    // Capitalize title for debug output\n    Console.debug(title[0].toUpperCase() + title.slice(1));\n\n    const oldCwd = process.cwd();\n    if (cwd) {\n      process.chdir(files.convertToOSPath(cwd));\n    }\n\n    const oldEnv = process.env;\n    if (env) {\n      // this preserves case insensitivity for PATH on windows\n      Object.keys(env).forEach(key => {\n        process.env[key] = env[key];\n      });\n    }\n\n    try {\n      const promise = (typeof promiseOrAsyncFunction === 'function') ?\n        promiseOrAsyncFunction() : promiseOrAsyncFunction;\n      return Promise.await(promise);\n    } catch (error) {\n      Console.arrowError('Errors executing Cordova commands:');\n      Console.error();\n      const consoleOptions = Console.options({ indent: 3 });\n      Console.error(`While ${title}:`, consoleOptions);\n\n      if (error instanceof CordovaError) {\n        // Only print the message for errors thrown by cordova-lib, because\n        // these are meant for end-user consumption.\n        // But warn that they may not completely apply to our situation.\n        // (We do print the stack trace if we are in verbose mode.)\n        const errorMessage = Console.verbose ? (error.stack || error.message) :\n          error.message;\n        Console.error(`Cordova error: ${errorMessage}`, consoleOptions);\n        Console.error(chalk.green(`(If the error message contains suggestions \\\nfor a fix, note that this may not apply to the Meteor integration. You can try \\\nrunning again with the --verbose option to help diagnose the issue.)`),\n          consoleOptions);\n      } else {\n        // Print stack trace for other errors by default, because the message\n        // usually does not give us enough information to know what is going on\n        const errorMessage = error && error.stack || error;\n        Console.error(errorMessage, consoleOptions);\n      };\n      throw new main.ExitWithCode(1);\n    } finally {\n      if (cwd && oldCwd) {\n        process.chdir(oldCwd);\n      }\n      if (env && oldEnv) {\n        process.env = oldEnv;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "tools/cordova/protect-string-proto.js",
    "content": "// `cordova-lib` depends on `shelljs`, which modifies String.prototype\n// (which is BAD).  See:\n// https://github.com/arturadib/shelljs/issues/159\n//\n// The following code protects the tool environment (which is also\n// where build plugins run) from having a polluted String.prototype.\n// One JS library in particular, String.js (before v3.3.1), is\n// sensitive to String prototype pollution.\n//\n// This code can be removed when `shelljs` cleans up its act and\n// `cordova-lib` uses a new version, or when `cordova-lib` moves away\n// from `shelljs`.\n\nfunction makeDescriptor() {\n  let value;\n\n  // This descriptor allows the property to remain non-enumerable while\n  // still permitting controlled modifications of its value.\n  return {\n    enumerable: false,\n\n    get() {\n      return value;\n    },\n\n    set(newValue) {\n      if (typeof newValue === \"function\") {\n        value = function () {\n          // Ignore calls that likely originate from\n          // https://github.com/jprichardson/string.js/blob/adc2e9d1b8/lib/string.js#L726\n          if (arguments.length > 0 ||\n              this != \"teststring\") {\n            return newValue.apply(this, arguments);\n          }\n        };\n      } else {\n        value = newValue;\n      }\n\n      return newValue;\n    }\n  };\n}\n\nObject.defineProperties(String.prototype, {\n  to: makeDescriptor(),\n  toEnd: makeDescriptor()\n});\n"
  },
  {
    "path": "tools/cordova/run-targets.js",
    "content": "import _ from 'underscore';\nimport chalk from 'chalk';\nimport child_process from 'child_process';\nimport eachline from 'eachline';\n\nimport { load as loadIsopacket } from '../tool-env/isopackets.js';\nimport runLog from '../runners/run-log.js';\nimport { Console } from '../console/console.js';\nimport files from '../fs/files.js';\nimport { execFileSync, execFileAsync } from '../utils/processes.js';\n\nexport class CordovaRunTarget {\n  get title() {\n    return `app on ${this.displayName}`;\n  }\n}\n\nexport class iOSRunTarget extends CordovaRunTarget {\n  constructor(isDevice) {\n    super();\n    this.platform = 'ios';\n    this.isDevice = isDevice;\n  }\n\n  get displayName() {\n    return this.isDevice ? \"iOS Device\" : \"iOS Simulator\";\n  }\n\n  async start(cordovaProject) {\n    // ios-deploy is super buggy, so we just open Xcode and let the user\n    // start the app themselves.\n    if (this.isDevice) {\n      openXcodeProject(files.pathJoin(cordovaProject.projectRoot,\n        'platforms', 'ios'));\n    } else {\n      await cordovaProject.run(this.platform, this.isDevice, undefined);\n\n      // Bring iOS Simulator to front (it is called Simulator in Xcode 7)\n      execFileAsync('osascript', ['-e',\n`tell application \"System Events\"\n  set possibleSimulatorNames to {\"iOS Simulator\", \"Simulator\"}\n  repeat with possibleSimulatorName in possibleSimulatorNames\n    if application process possibleSimulatorName exists then\n      set frontmost of process possibleSimulatorName to true\n    end if\n  end repeat\nend tell`]);\n    }\n  }\n}\n\nfunction openXcodeProject(projectDir) {\n  const projectFilename =  files.readdir(projectDir).filter((entry) =>\n    { return entry.match(/\\.xcodeproj$/i) })[0];\n\n  if (!projectFilename) {\n    printFailure(`Couldn't find your Xcode project in directory \\\n'${files.convertToOSPath(projectDir)}'`);\n    return;\n  }\n\n  const projectFilePath = files.pathJoin(projectDir, projectFilename);\n\n  try {\n    execFileSync('open', [projectFilePath]);\n\n    Console.info();\n    Console.info(\n      chalk.green(\n        \"Your project has been opened in Xcode so that you can run your \" +\n        \"app on an iOS device. For further instructions, visit this \" +\n        \"wiki page: \") +\n      Console.url(\n        \"https://github.com/meteor/meteor/wiki/\" +\n        \"How-to-run-your-app-on-an-iOS-device\"\n    ));\n    Console.info();\n  } catch (error) {\n    printFailure(`Failed to open your project in Xcode:\n${error.message}`);\n  }\n\n  function printFailure(message) {\n    Console.error();\n    Console.error(message);\n    Console.error(\n      chalk.green(\"Instructions for running your app on an iOS device: \") +\n      Console.url(\"https://github.com/meteor/meteor/wiki/\" +\n        \"How-to-run-your-app-on-an-iOS-device\")\n    );\n    Console.error();\n  }\n}\n\nexport class AndroidRunTarget extends CordovaRunTarget {\n  constructor(isDevice) {\n    super();\n    this.platform = 'android';\n    this.isDevice = isDevice;\n  }\n\n  get displayName() {\n    return this.isDevice ? \"Android Device\" : \"Android Emulator\";\n  }\n\n  async start(cordovaProject) {\n    // XXX This only works if we have at most one device or one emulator\n    // connected. We should find a way to get the target ID from run and use\n    // it instead of -d or -e.\n    let target = this.isDevice ? \"-d\" : \"-e\";\n\n    // Clear logs\n    execFileAsync('adb', [target, 'logcat', '-c']);\n\n    await cordovaProject.run(this.platform, this.isDevice);\n\n    this.tailLogs(cordovaProject, target).done();\n  }\n\n  async checkPlatformRequirementsAndSetEnv(cordovaProject) {\n    // Cordova Android is fairly good at applying various heuristics to find\n    // suitable values for JAVA_HOME and ANDROID_HOME, and to augment the PATH\n    // with those variables.\n    // Unfortunately, this is intertwined with checking requirements, so the\n    // only way to get access to this functionality is to run check_reqs and\n    // let it modify process.env\n    var check_reqs_path = files.pathJoin(\n      cordovaProject.projectRoot, 'platforms', this.platform,\n      'cordova', 'lib', 'check_reqs');\n    check_reqs_path = files.convertToOSPath(check_reqs_path);\n    let check_reqs = require(check_reqs_path);\n    // We can't use check_reqs.run() because that will print the values of\n    // JAVA_HOME and ANDROID_HOME to stdout.\n    await Promise.all([check_reqs.check_java(),\n      check_reqs.check_android().then(check_reqs.check_android_target)]);\n  }\n\n  async tailLogs(cordovaProject, target) {\n    cordovaProject.runCommands(`tailing logs for ${this.displayName}`, async () => {\n      await this.checkPlatformRequirementsAndSetEnv(cordovaProject);\n\n      const logLevel = Console.verbose ? \"V\" : \"I\";\n\n      const filterExpressions = [`MeteorWebApp:${logLevel}`,\n        `CordovaLog:${logLevel}`, `chromium:${logLevel}`,\n        `SystemWebViewClient:${logLevel}`, '*:F'];\n\n      const { Log } =\n          loadIsopacket('cordova-support')['logging'];\n\n      const logStream = eachline((line) => {\n        const logEntry = logFromAndroidLogcatLine(Log, line);\n        if (logEntry) {\n          return `${logEntry}\\n`;\n        }\n      });\n      logStream.pipe(process.stdout);\n\n      // Asynchronously start tailing logs to stdout\n      execFileAsync('adb', [target, 'logcat',\n        ...filterExpressions],\n        { destination: logStream });\n    });\n  }\n}\n\nfunction logFromAndroidLogcatLine(Log, line) {\n  // Ignore lines indicating beginning of logging\n  if (line.match(/^--------- beginning of /)) {\n    return null;\n  }\n\n  // Matches logcat brief format\n  // \"I/Tag(  PID): message\"\n  let match =\n    line.match(/^([A-Z])\\/([^\\(]*?)\\(\\s*(\\d+)\\): (.*)$/);\n\n  if (match) {\n    [, priority, tag, pid, message] = match;\n\n    if (tag === 'chromium') {\n      // Matches Chromium log format\n      // [INFO:CONSOLE(23)] \"Bla!\", source: http://meteor.local/app/mobileapp.js (23)\n      match = message.match(/^\\[(.*):(.*)\\((\\d+)\\)\\] (.*)$/);\n\n      if (match) {\n        [, logLevel, filename, lineNumber, message] = match;\n\n        if (filename === 'CONSOLE') {\n          match = message.match(/^\\\"(.*)\\\", source: (.*) \\((\\d+)\\)$/);\n\n          if (match) {\n            [, message, filename, lineNumber] = match;\n            return logFromConsoleOutput(Log, message, filename, lineNumber);\n          }\n        }\n      }\n    } else if (tag === 'CordovaLog') {\n      // http://meteor.local/mobileappold.js?3c198a97a802ad2c6eab52da0244245e30b964ed: Line 15 : Clicked!\n\n      match = message.match(/^(.*): Line (\\d+) : (.*)$/);\n\n      if (match) {\n        [, filename, lineNumber, message] = match;\n        return logFromConsoleOutput(Log, message, filename, lineNumber);\n      }\n    }\n  }\n\n  return Log.format(Log.objFromText(line), { metaColor: 'green', color: true });\n};\n\nfunction logFromConsoleOutput(Log, message, filename, lineNumber) {\n  if (isDebugOutput(message) && !Console.verbose) {\n    return null;\n  }\n\n  filename = filename.replace(/\\?.*$/, '');\n\n  return Log.format({\n    time: new Date,\n    level: 'info',\n    file: filename,\n    line: lineNumber,\n    message: message,\n    program: 'android'\n  }, {\n    metaColor: 'green',\n    color: true\n  });\n}\n\nfunction isDebugOutput(message) {\n  // Skip the debug output produced by Meteor components.\n  return /^METEOR CORDOVA DEBUG /.test(message) ||\n    /^HTTPD DEBUG /.test(message);\n};\n"
  },
  {
    "path": "tools/cordova/runner.js",
    "content": "import _ from 'underscore';\nimport buildmessage from '../utils/buildmessage.js';\nimport runLog from '../runners/run-log.js';\nimport { Console } from '../console/console.js';\nimport main from '../cli/main.js';\n\nimport { displayNameForPlatform, prepareProjectForBuild } from './index.js';\n\nexport class CordovaRunner {\n  constructor(cordovaProject, runTargets) {\n    this.cordovaProject = cordovaProject;\n    this.runTargets = runTargets;\n\n    this.started = false;\n  }\n\n  get projectContext() {\n    return this.cordovaProject.projectContext;\n  }\n\n  get platformsForRunTargets() {\n    return _.uniq(this.runTargets.map((runTarget) => runTarget.platform));\n  }\n\n  checkPlatformsForRunTargets() {\n    this.cordovaProject.ensurePlatformsAreSynchronized();\n\n    let satisfied = true;\n    const messages = buildmessage.capture(\n      { title: `checking platform requirements` }, () => {\n      for (platform of this.platformsForRunTargets) {\n        satisfied =\n          this.cordovaProject.checkPlatformRequirements(platform) &&\n          satisfied;\n      }\n    });\n\n    if (messages.hasMessages()) {\n      Console.printMessages(messages);\n      throw new main.ExitWithCode(1);\n    } else if (!satisfied) {\n      throw new main.ExitWithCode(1);\n    };\n  }\n\n  printWarningsIfNeeded() {\n    // OAuth2 packages don't work so well with any mobile platform except the\n    // iOS Simulator. Print a warning and direct users to the wiki page for help.\n    if (this.projectContext.packageMap.getInfo('oauth2')) {\n      Console.warn();\n      Console.labelWarn(\n        \"It looks like you are using OAuth2 login in your app. \" +\n        \"Meteor's OAuth2 implementation does not currently work with \" +\n        \"mobile apps in local development mode, except in the iOS \" +\n        \"simulator. You can run the iOS simulator with 'meteor run ios'. \" +\n        \"For additional workarounds, see \" +\n        Console.url(\n          \"https://github.com/meteor/meteor/wiki/\" +\n          \"OAuth-for-mobile-Meteor-clients.\"));\n    }\n\n    // If we are targeting remote devices, warn about ports and same network.\n    if (_.findWhere(this.runTargets, { isDevice: true })) {\n      Console.warn();\n      Console.labelWarn(\n        \"You are testing your app on a remote device. \" +\n        \"For the mobile app to be able to connect to the local server, make \" +\n        \"sure your device is on the same network, and that the network \" +\n        \"configuration allows clients to talk to each other \" +\n        \"(no client isolation).\");\n    }\n  }\n\n  prepareProject(bundlePath, pluginVersions, options) {\n    buildmessage.assertInCapture();\n\n    buildmessage.enterJob({ title: \"preparing Cordova project\" }, () => {\n      this.cordovaProject.prepareFromAppBundle(bundlePath,\n        pluginVersions, options);\n\n      if (buildmessage.jobHasMessages()) {\n        return;\n      }\n\n      for (platform of this.platformsForRunTargets) {\n        this.cordovaProject.prepareForPlatform(platform);\n      }\n    });\n\n    this.pluginVersions = pluginVersions;\n  }\n\n  startRunTargets() {\n    this.started = false;\n\n    for (runTarget of this.runTargets) {\n      const messages = buildmessage.capture({ title: `starting ${runTarget.title}` }, () => {\n        Promise.await(runTarget.start(this.cordovaProject));\n      });\n      if (messages.hasMessages()) {\n        Console.printMessages(messages);\n      } else {\n        runLog.log(`Started ${runTarget.title}.`, { arrow: true });\n      }\n    }\n\n    this.started = true;\n  }\n\n  havePlatformsChangedSinceLastRun() {\n    const platformsForRunTargets = this.platformsForRunTargets;\n    if (!platformsForRunTargets) {\n      return false;\n    }\n\n    const cordovaPlatformsInApp = this.cordovaProject.cordovaPlatformsInApp;\n\n    return !_.isEqual(platformsForRunTargets,\n      _.intersection(platformsForRunTargets, cordovaPlatformsInApp));\n  }\n\n  havePluginsChangedSinceLastRun(pluginVersions) {\n    return this.pluginVersions &&\n      !_.isEqual(this.pluginVersions, pluginVersions);\n  }\n}\n"
  },
  {
    "path": "tools/fs/README.md",
    "content": "This folder contains modules that help communicating with the file-system.\n\n## `files` vs `fs` and `files.path*` vs `path`\n\nSince the Meteor tool was originally written to work on Mac OS X and Linux but\nnow is also required to work on Windows, there has been a decision to abstract\nthe file-system calls to `fs` and `path` modules and make them go through the\n`files.js` lib.\n\nAll path and files manipulations in the `tools` code assumes it is running in a\nunixy environment, where the path separator is `/` and the default line-break\nsymbol is `\\n`; calls like `rename` and `unlink` are atomic and the file-system \nalways works as you expect.\n\nThe `files.js` file tries its best to simulate this behavior on Windows,\nconverting slashes, file contents and running FS operations in a\n\"try/sleep/repeat\" loop when an `EBUSY` error is returned. Operations on Windows\nhappen to be slower, especially moving folders and symlinking (which is done by\ncopying the directory instead).\n\nIt is advised to use `files.readFile` and others instead of\n`fs.readFileSync`. The methods are Fiberized and are converted on Windows.\n\nAlso `files.pathJoin` instead of `path.join` and others to properly preserve the\nunixy feel of paths: `/C/Users/IEUser/AppData/Local` instead of\n`C:\\Users\\IEUser\\AppData\\Local`.\n\n### `mini-files`\n\nSome code is shared between the tool libs (this folder) and the code that gets\ncopied to a built bundle (`boot.js`). The shared code is stored in\n`mini-files.js`.\n\n## File watching\n\nSince node.js doesn't ship a stable library to watch a folder on all\nfile-systems, a wrapper is used. The wrapper checks if the native functionality\nworks, if not (while on Windows, or a virtualized shared file-system like in\nVirtualBox), a 5s long-polling is used.\n\nThe polling and its numbers are tweakable with the environment variables\n`METEOR_WATCH_POLLING_INTERVAL_MS` and `METEOR_WATCH_FORCE_POLLING`.\n\n## Watchset\n\nA specific data-structure that is a set of files and directories paths observed\nby the file-watcher.\n"
  },
  {
    "path": "tools/fs/files.js",
    "content": "///\n/// utility functions for files and directories. includes both generic\n/// helper functions (such as rm_recursive), and meteor-specific ones\n/// (such as testing whether an directory is a meteor app)\n///\n\nvar assert = require(\"assert\");\nvar fs = require(\"fs\");\nvar path = require('path');\nvar os = require('os');\nvar util = require('util');\nvar _ = require('underscore');\nvar Fiber = require('fibers');\nvar crypto = require('crypto');\n\nvar rimraf = require('rimraf');\nvar sourcemap = require('source-map');\nvar sourceMapRetrieverStack = require('../tool-env/source-map-retriever-stack.js');\n\nvar utils = require('../utils/utils.js');\nvar cleanup = require('../tool-env/cleanup.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar watch = require('./watch.js');\nvar fiberHelpers = require('../utils/fiber-helpers.js');\nvar colonConverter = require('../utils/colon-converter.js');\n\nvar miniFiles = require('./mini-files.js');\n\nvar Profile = require('../tool-env/profile.js').Profile;\n\n// Attach all exports of miniFiles here to avoid code duplication\nvar files = exports;\n_.extend(files, miniFiles);\n\nvar parsedSourceMaps = {};\nvar nextStackFilenameCounter = 1;\n\n// Use the source maps specified to runJavaScript\nvar useParsedSourceMap = function (pathForSourceMap) {\n  // Check our fancy source map data structure, used for isopacks\n  if (_.has(parsedSourceMaps, pathForSourceMap)) {\n    return {map: parsedSourceMaps[pathForSourceMap]};\n  }\n\n  return null;\n};\n\n// Try this source map first\nsourceMapRetrieverStack.push(useParsedSourceMap);\n\n// given a predicate function and a starting path, traverse upwards\n// from the path until we find a path that satisfies the predicate.\n//\n// returns either the path to the lowest level directory that passed\n// the test or null for none found. if starting path isn't given, use\n// cwd.\nvar findUpwards = function (predicate, startPath) {\n  var testDir = startPath || files.cwd();\n  while (testDir) {\n    if (predicate(testDir)) {\n      break;\n    }\n    var newDir = files.pathDirname(testDir);\n    if (newDir === testDir) {\n      testDir = null;\n    } else {\n      testDir = newDir;\n    }\n  }\n  if (!testDir) {\n    return null;\n  }\n\n  return testDir;\n};\n\nfiles.cwd = function () {\n  return files.convertToStandardPath(process.cwd());\n};\n\n// Determine if 'filepath' (a path, or omit for cwd) is within an app\n// directory. If so, return the top-level app directory.\nfiles.findAppDir = function (filepath) {\n  var isAppDir = function (filepath) {\n    // XXX once we are done with the transition to engine, this should\n    // change to: `return files.exists(path.join(filepath, '.meteor',\n    // 'release'))`\n\n    // .meteor/packages can be a directory, if .meteor is a warehouse\n    // directory.  since installing meteor initializes a warehouse at\n    // $HOME/.meteor, we want to make sure your home directory (and all\n    // subdirectories therein) don't count as being within a meteor app.\n    try { // use try/catch to avoid the additional syscall to files.exists\n      return files.stat(\n        files.pathJoin(filepath, '.meteor', 'packages')).isFile();\n    } catch (e) {\n      return false;\n    }\n  };\n\n  return findUpwards(isAppDir, filepath);\n};\n\nfiles.findPackageDir = function (filepath) {\n  var isPackageDir = function (filepath) {\n    try {\n      return files.stat(files.pathJoin(filepath, 'package.js')).isFile();\n    } catch (e) {\n      return false;\n    }\n  };\n\n  return findUpwards(isPackageDir, filepath);\n};\n\n// create a .gitignore file in dirPath if one doesn't exist. add\n// 'entry' to the .gitignore on its own line at the bottom of the\n// file, if the exact line does not already exist in the file.\nfiles.addToGitignore = function (dirPath, entry) {\n  var filepath = files.pathJoin(dirPath, \".gitignore\");\n  if (files.exists(filepath)) {\n    var data = files.readFile(filepath, 'utf8');\n    var lines = data.split(/\\n/);\n    if (_.any(lines, function (x) { return x === entry; })) {\n      // already there do nothing\n    } else {\n      // rewrite file w/ new entry.\n      if (data.substr(-1) !== \"\\n\") {\n        data = data + \"\\n\";\n      }\n      data = data + entry + \"\\n\";\n      files.writeFile(filepath, data, 'utf8');\n    }\n  } else {\n    // doesn't exist, just write it.\n    files.writeFile(filepath, entry + \"\\n\", 'utf8');\n  }\n};\n\n// Are we running Meteor from a git checkout?\nfiles.inCheckout = _.once(function () {\n  try {\n    if (files.exists(files.pathJoin(files.getCurrentToolsDir(), '.git'))) {\n      return true;\n    }\n  } catch (e) { console.log(e); }\n\n  return false;\n});\n\n// True if we are using a warehouse: either installed Meteor, or if\n// $METEOR_WAREHOUSE_DIR is set. Otherwise false (we're in a git checkout and\n// just using packages from the checkout).\nfiles.usesWarehouse = function () {\n  // Test hook: act like we're \"installed\" using a non-homedir warehouse\n  // directory.\n  if (process.env.METEOR_WAREHOUSE_DIR) {\n    return true;\n  } else {\n    return ! files.inCheckout();\n  }\n};\n\n// Read the '.tools_version.txt' file. If in a checkout, throw an error.\nfiles.getToolsVersion = function () {\n  if (! files.inCheckout()) {\n    var isopackJsonPath = files.pathJoin(files.getCurrentToolsDir(),\n      '..',  // get out of tool, back to package\n      'isopack.json');\n\n    var parsed;\n\n    if (files.exists(isopackJsonPath)) {\n      var isopackJson = files.readFile(isopackJsonPath);\n      parsed = JSON.parse(isopackJson);\n\n      // XXX \"isopack-1\" is duplicate of isopack.currentFormat\n      parsed = parsed[\"isopack-1\"]; // get the right format from the JSON\n      return parsed.name + '@' + parsed.version;\n    }\n\n    // XXX COMPAT WITH 0.9.3\n    var unipackageJsonPath = files.pathJoin(files.getCurrentToolsDir(),\n      '..',  // get out of tool, back to package\n      'unipackage.json');\n    var unipackageJson = files.readFile(unipackageJsonPath);\n    parsed = JSON.parse(unipackageJson);\n    return parsed.name + '@' + parsed.version;\n\n  } else {\n    throw new Error(\"Unexpected. Git checkouts don't have tools versions.\");\n  }\n};\n\n// Return the root of dev_bundle (probably /usr/local/meteor in an\n// install, or (checkout root)/dev_bundle in a checkout.).\nfiles.getDevBundle = function () {\n  return files.pathJoin(files.getCurrentToolsDir(), 'dev_bundle');\n};\n\nfiles.getCurrentNodeBinDir = function () {\n  return files.pathJoin(files.getDevBundle(), \"bin\");\n}\n\n// Return the top-level directory for this meteor install or checkout\nfiles.getCurrentToolsDir = function () {\n  var dirname = files.convertToStandardPath(__dirname);\n  return files.pathJoin(dirname, '..', '..');\n};\n\n// Read a settings file and sanity-check it. Returns a string on\n// success or null on failure (in which case buildmessages will be\n// emitted).\nfiles.getSettings = function (filename, watchSet) {\n  buildmessage.assertInCapture();\n  var absPath = files.pathResolve(filename);\n  var buffer = watch.readAndWatchFile(watchSet, absPath);\n  if (buffer === null) {\n    buildmessage.error(\"file not found (settings file)\",\n                       { file: filename });\n    return null;\n  }\n\n  if (buffer.length > 0x10000) {\n    buildmessage.error(\"settings file is too large (must be less than 64k)\",\n                       { file: filename });\n    return null;\n  }\n\n  var str = buffer.toString('utf8');\n\n  // Ensure that the string is parseable in JSON, but there's no reason to use\n  // the object value of it yet.\n  if (str.match(/\\S/)) {\n    try {\n      JSON.parse(str);\n    } catch (e) {\n      buildmessage.error(\"parse error reading settings file\",\n                         { file: filename });\n    }\n  }\n\n  return str;\n};\n\n// Try to find the prettiest way to present a path to the\n// user. Presently, the main thing it does is replace $HOME with ~.\nfiles.prettyPath = function (p) {\n  p = files.realpath(p);\n  var home = files.getHomeDir();\n  if (! home) {\n    return p;\n  }\n  var relativeToHome = files.pathRelative(home, p);\n  if (relativeToHome.substr(0, 3) === ('..' + files.pathSep)) {\n    return p;\n  }\n  return files.pathJoin('~', relativeToHome);\n};\n\n// Like statSync, but null if file not found\nfiles.statOrNull = function (path) {\n  try {\n    return files.stat(path);\n  } catch (e) {\n    if (e.code == \"ENOENT\") {\n      return null;\n    }\n    throw e;\n  }\n};\n\n// Like rm -r.\nfiles.rm_recursive = Profile(\"files.rm_recursive\", function (p) {\n  if (Fiber.current && Fiber.yield && ! Fiber.yield.disallowed) {\n    new Promise((resolve, reject) => {\n      rimraf(files.convertToOSPath(p), err => {\n        err ? reject(err) : resolve();\n      });\n    }).await();\n  } else {\n    rimraf.sync(files.convertToOSPath(p));\n  }\n});\n\n// Makes all files in a tree read-only.\nvar makeTreeReadOnly = function (p) {\n  try {\n    // the l in lstat is critical -- we want to ignore symbolic links\n    var stat = files.lstat(p);\n  } catch (e) {\n    if (e.code == \"ENOENT\") {\n      return;\n    }\n    throw e;\n  }\n\n  if (stat.isDirectory()) {\n    _.each(files.readdir(p), function (file) {\n      makeTreeReadOnly(files.pathJoin(p, file));\n    });\n  }\n  if (stat.isFile()) {\n    var permissions = stat.mode & 0o777;\n    var readOnlyPermissions = permissions & 0o555;\n    if (permissions !== readOnlyPermissions) {\n      files.chmod(p, readOnlyPermissions);\n    }\n  }\n};\n\n// Returns the base64 SHA256 of the given file.\nfiles.fileHash = function (filename) {\n  var crypto = require('crypto');\n  var hash = crypto.createHash('sha256');\n  hash.setEncoding('base64');\n  var rs = files.createReadStream(filename);\n  return new Promise(function (resolve) {\n    rs.on('end', function () {\n      rs.close();\n      resolve(hash.digest('base64'));\n    });\n    rs.pipe(hash, { end: false });\n  }).await();\n};\n\n// This is the result of running fileHash on a blank file.\nfiles.blankHash = \"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=\";\n\n// Returns a base64 SHA256 hash representing a tree on disk. It is not sensitive\n// to modtime, uid/gid, or any permissions bits other than the current-user-exec\n// bit on normal files.\nfiles.treeHash = function (root, options) {\n  options = _.extend({\n    ignore: function (relativePath) {\n      return false;\n    }\n  }, options);\n\n  var crypto = require('crypto');\n  var hash = crypto.createHash('sha256');\n\n  var hashLog = process.env.TREE_HASH_DEBUG ?\n        ['\\n\\nTREE HASH for ' + root + '\\n'] : null;\n\n  var updateHash = function (text) {\n    hashLog && hashLog.push(text);\n    hash.update(text);\n  };\n\n  var traverse = function (relativePath) {\n    if (options.ignore(relativePath)) {\n      hashLog && hashLog.push('SKIP ' + JSON.stringify(relativePath) + '\\n');\n      return;\n    }\n\n    var absPath = files.pathJoin(root, relativePath);\n    var stat = files.lstat(absPath);\n\n    if (stat.isDirectory()) {\n      if (relativePath) {\n        updateHash('dir ' + JSON.stringify(relativePath) + '\\n');\n      }\n      _.each(files.readdir(absPath), function (entry) {\n        traverse(files.pathJoin(relativePath, entry));\n      });\n    } else if (stat.isFile()) {\n      if (!relativePath) {\n        throw Error(\"must call files.treeHash on a directory\");\n      }\n      updateHash('file ' + JSON.stringify(relativePath) + ' ' +\n                  stat.size + ' ' + files.fileHash(absPath) + '\\n');\n      if (stat.mode & 0o100) {\n        updateHash('exec\\n');\n      }\n    } else if (stat.isSymbolicLink()) {\n      if (!relativePath) {\n        throw Error(\"must call files.treeHash on a directory\");\n      }\n      updateHash('symlink ' + JSON.stringify(relativePath) + ' ' +\n                 JSON.stringify(files.readlink(absPath)) + '\\n');\n    }\n    // ignore anything weirder\n  };\n\n  traverse('');\n  hashLog && files.appendFile(process.env.TREE_HASH_DEBUG, hashLog.join(''));\n  return hash.digest('base64');\n};\n\n// like mkdir -p. if it returns true, the item is a directory (even if\n// it was already created). if it returns false, the item is not a\n// directory and we couldn't make it one.\nfiles.mkdir_p = function (dir, mode) {\n  var p = files.pathResolve(dir);\n  var ps = files.pathNormalize(p).split(files.pathSep);\n\n  var stat = files.statOrNull(p);\n  if (stat) {\n    return stat.isDirectory();\n  }\n\n  // doesn't exist. recurse to build parent.\n  // Don't use files.pathJoin here because it can strip off the leading slash\n  // accidentally.\n  var parentPath = ps.slice(0, -1).join(files.pathSep);\n  var success = files.mkdir_p(parentPath, mode);\n  // parent is not a directory.\n  if (! success) { return false; }\n\n  var pathIsDirectory = function (path) {\n    var stat = files.statOrNull(path);\n    return stat && stat.isDirectory();\n  };\n\n  try {\n    files.mkdir(p, mode);\n  } catch (err) {\n    if (err.code === \"EEXIST\") {\n      if (pathIsDirectory(p)) {\n        // all good, someone else created this directory for us while we were\n        // yielding\n        return true;\n      } else {\n        return false;\n      }\n    } else {\n      throw err;\n    }\n  }\n\n  // double check we exist now\n  return pathIsDirectory(p);\n};\n\n// Roughly like cp -R. 'from' should be a directory. 'to' can either\n// be a directory, or it can not exist (in which case it will be\n// created with mkdir_p).\n//\n// The output files will be readable and writable by everyone that the umask\n// allows, and executable by everyone (modulo umask) if the original file was\n// owner-executable. Symlinks are treated transparently (ie the contents behind\n// them are copied, and it's an error if that points nowhere).\n//\n// If options.transform{Filename, Contents} is present, it should\n// be a function, and the contents (as a buffer) or filename will be\n// passed through the function. Use this to, eg, fill templates.\n//\n// If options.ignore is present, it should be a list of regexps. Any\n// file whose basename matches one of the regexps, before\n// transformation, will be skipped.\nfiles.cp_r = function (from, to, options) {\n  options = options || {};\n\n  var absFrom = files.pathResolve(from);\n  files.mkdir_p(to, 0o755);\n\n  _.each(files.readdir(from), function (f) {\n    if (_.any(options.ignore || [], function (pattern) {\n      return f.match(pattern);\n    })) {\n      return;\n    }\n\n    var fullFrom = files.pathJoin(from, f);\n    if (options.transformFilename) {\n      f = options.transformFilename(f);\n    }\n    var fullTo = files.pathJoin(to, f);\n    var stats = options.preserveSymlinks\n          ? files.lstat(fullFrom) : files.stat(fullFrom);\n    if (stats.isDirectory()) {\n      files.cp_r(fullFrom, fullTo, options);\n    } else if (stats.isSymbolicLink()) {\n      var linkText = files.readlink(fullFrom);\n      files.symlink(linkText, fullTo);\n    } else {\n      var absFullFrom = files.pathResolve(fullFrom);\n\n      // Create the file as readable and writable by everyone, and executable by\n      // everyone if the original file is executably by owner. (This mode will\n      // be modified by umask.) We don't copy the mode *directly* because this\n      // function is used by 'meteor create' which is copying from the read-only\n      // tools tree into a writable app.\n      var mode = (stats.mode & 0o100) ? 0o777 : 0o666;\n      if (!options.transformContents) {\n        copyFileHelper(fullFrom, fullTo, mode);\n      } else {\n        var contents = files.readFile(fullFrom);\n        contents = options.transformContents(contents, f);\n        files.writeFile(fullTo, contents, { mode: mode });\n      }\n    }\n  });\n};\n\n/**\n * Get every path in a directory recursively, treating symlinks as files\n * @param  {String} dir     The directory to walk, either relative to options.cwd or completely absolute\n * @param  {Object} options Some options\n * @param {String} options.cwd The directory that paths should be relative to\n * @param {String[]} options.output An array to push results to\n * @return {String[]}         All of the paths in the directory recursively\n */\nfiles.getPathsInDir = function (dir, options) {\n  // Don't let this function yield so that the file system doesn't get changed\n  // underneath us\n  return fiberHelpers.noYieldsAllowed(function () {\n    var cwd = options.cwd || files.convertToStandardPath(process.cwd());\n\n    if (! files.exists(cwd)) {\n      throw new Error(\"Specified current working directory doesn't exist: \" +\n        cwd);\n    }\n\n    var absoluteDir = files.pathResolve(cwd, dir);\n\n    if (! files.exists(absoluteDir)) {\n      // There are no paths in this dir, so don't do anything\n      return;\n    }\n\n    var output = options.output || [];\n\n    var pathIsDirectory = function (path) {\n      var stat = files.lstat(path);\n      return stat.isDirectory();\n    };\n\n    _.each(files.readdir(absoluteDir), function (entry) {\n      var newPath = files.pathJoin(dir, entry);\n      var newAbsPath = files.pathJoin(absoluteDir, entry);\n\n      output.push(newPath);\n\n      if (pathIsDirectory(newAbsPath)) {\n        files.getPathsInDir(newPath, {\n          cwd: cwd,\n          output: output\n        });\n      }\n    });\n\n    return output;\n  });\n};\n\nfiles.findPathsWithRegex = function (dir, regex, options) {\n  var allPaths = files.getPathsInDir(dir, {\n    cwd: options.cwd\n  });\n\n  return _.filter(allPaths, function (path) {\n    return path.match(regex);\n  });\n};\n\n// Copies a file, which is expected to exist. Parent directories of \"to\" do not\n// have to exist. Treats symbolic links transparently (copies the contents, not\n// the link itself, and it's an error if the link doesn't point to a file).\nfiles.copyFile = function (from, to, origMode=null) {\n  files.mkdir_p(files.pathDirname(files.pathResolve(to)), 0o755);\n\n  if (origMode === null) {\n    var stats = files.stat(from);\n    if (!stats.isFile()) {\n      throw Error(\"cannot copy non-files\");\n    }\n    origMode = stats.mode;\n  }\n\n  // Create the file as readable and writable by everyone, and executable by\n  // everyone if the original file is executably by owner. (This mode will be\n  // modified by umask.) We don't copy the mode *directly* because this function\n  // is used by 'meteor create' which is copying from the read-only tools tree\n  // into a writable app.\n  var mode = (origMode & 0o100) ? 0o777 : 0o666;\n\n  copyFileHelper(from, to, mode);\n};\nfiles.copyFile = Profile(\"files.copyFile\", files.copyFile);\n\nvar copyFileHelper = function (from, to, mode) {\n  var readStream = files.createReadStream(from);\n  var writeStream = files.createWriteStream(to, { mode: mode });\n  new Promise(function (resolve, reject) {\n    readStream.on('error', reject);\n    writeStream.on('error', reject);\n    writeStream.on('open', function () {\n      readStream.pipe(writeStream);\n    });\n    writeStream.once('finish', resolve);\n  }).await();\n};\n\n// Make a temporary directory. Returns the path to the newly created\n// directory. Only the current user is allowed to read or write the\n// files in the directory (or add files to it). The directory will\n// be cleaned up on exit.\nvar tempDirs = [];\nfiles.mkdtemp = function (prefix) {\n  var make = function () {\n    prefix = prefix || 'mt-';\n    // find /tmp\n    var tmpDir = _.first(_.map(['TMPDIR', 'TMP', 'TEMP'], function (t) {\n      return process.env[t];\n    }).filter(_.identity));\n\n    if (! tmpDir && process.platform !== 'win32') {\n      tmpDir = '/tmp';\n    }\n\n    if (! tmpDir) {\n      throw new Error(\"Couldn't create a temporary directory.\");\n    }\n\n    tmpDir = files.realpath(tmpDir);\n\n    // make the directory. give it 3 tries in case of collisions from\n    // crappy random.\n    var tries = 3;\n    while (tries > 0) {\n      var dirPath = files.pathJoin(\n        tmpDir, prefix + (Math.random() * 0x100000000 + 1).toString(36));\n      try {\n        files.mkdir(dirPath, 0o700);\n        return dirPath;\n      } catch (err) {\n        tries--;\n      }\n    }\n    throw new Error(\"failed to make temporary directory in \" + tmpDir);\n  };\n  var dir = make();\n  tempDirs.push(dir);\n  return dir;\n};\n\n// Call this if you're done using a temporary directory. It will asynchronously\n// be deleted.\nfiles.freeTempDir = function (tempDir) {\n  if (! _.contains(tempDirs, tempDir)) {\n    throw Error(\"not a tracked temp dir: \" + tempDir);\n  }\n  if (process.env.METEOR_SAVE_TMPDIRS) {\n    return;\n  }\n  setImmediate(function () {\n    // note: rm_recursive can yield, so it's possible that during this\n    // rm_recursive call, the onExit rm_recursive fires too.  (Or it could even\n    // start firing before the setImmediate handler is called.) But it should be\n    // OK for there to be overlapping rm_recursive calls, since rm_recursive\n    // ignores all ENOENT calls. And we don't remove tempDir from tempDirs until\n    // it's done, so that if mid-way through this rm_recursive the onExit one\n    // fires, it still gets removed.\n\n    try {\n      files.rm_recursive(tempDir);\n    } catch (err) {\n      // Don't crash and print a stack trace because we failed to delete a temp\n      // directory. This happens sometimes on Windows and seems to be\n      // unavoidable.\n      console.log(err);\n    }\n\n    tempDirs = _.without(tempDirs, tempDir);\n  });\n};\n\nif (! process.env.METEOR_SAVE_TMPDIRS) {\n  cleanup.onExit(function (sig) {\n    _.each(tempDirs, function (tempDir) {\n      try {\n        files.rm_recursive(tempDir);\n      } catch (err) {\n        // Don't crash and print a stack trace because we failed to delete a temp\n        // directory. This happens sometimes on Windows and seems to be\n        // unavoidable.\n        console.log(err);\n      }\n    });\n\n    tempDirs = [];\n  });\n}\n\n// Takes a buffer containing `.tar.gz` data and extracts the archive\n// into a destination directory. destPath should not exist yet, and\n// the archive should contain a single top-level directory, which will\n// be renamed atomically to destPath. The entire tree will be made\n// readonly.\nfiles.extractTarGz = function (buffer, destPath, options) {\n  var options = options || {};\n  var parentDir = files.pathDirname(destPath);\n  var tempDir = files.pathJoin(parentDir, '.tmp' + utils.randomToken());\n  files.mkdir_p(tempDir);\n\n  var tar = require(\"tar\");\n  var zlib = require(\"zlib\");\n\n  new Promise(function (resolve, reject) {\n    var gunzip = zlib.createGunzip().on('error', reject);\n\n    var extractor = new tar.Extract({\n      path: files.convertToOSPath(tempDir)\n    }).on('entry', function (e) {\n      if (process.platform === \"win32\" || options.forceConvert) {\n        // On Windows, try to convert old packages that have colons in paths\n        // by blindly replacing all of the paths. Otherwise, we can't even\n        // extract the tarball\n        e.path = colonConverter.convert(e.path);\n      }\n    }).on('error', reject)\n      .on('end', resolve);\n\n    // write the buffer to the (gunzip|untar) pipeline; these calls\n    // cause the tar to be extracted to disk.\n    gunzip.pipe(extractor);\n    gunzip.write(buffer);\n    gunzip.end();\n  }).await();\n\n  // succeed!\n  var topLevelOfArchive = files.readdir(tempDir);\n  if (topLevelOfArchive.length !== 1) {\n    throw new Error(\n      \"Extracted archive '\" + tempDir + \"' should only contain one entry\");\n  }\n\n  var extractDir = files.pathJoin(tempDir, topLevelOfArchive[0]);\n  makeTreeReadOnly(extractDir);\n  files.rename(extractDir, destPath);\n  files.rmdir(tempDir);\n};\n\n// Tar-gzips a directory, returning a stream that can then be piped as\n// needed.  The tar archive will contain a top-level directory named\n// after dirPath.\nfiles.createTarGzStream = function (dirPath, options) {\n  var tar = require(\"tar\");\n  var fstream = require('fstream');\n  var zlib = require(\"zlib\");\n\n  // Don't use `{ path: dirPath, type: 'Directory' }` as an argument to\n  // fstream.Reader. This triggers a collection of odd behaviors in fstream\n  // (which might be bugs or might just be weirdnesses).\n  //\n  // First, if we pass an object with `type: 'Directory'` as an argument, then\n  // the resulting tarball has no entry for the top-level directory, because\n  // the reader emits an entry (with just the path, no permissions or other\n  // properties) before the pipe to gzip is even set up, so that entry gets\n  // lost. Even if we pause the streams until all the pipes are set up, we'll\n  // get the entry in the tarball for the top-level directory without\n  // permissions or other properties, which is problematic. Just passing\n  // `dirPath` appears to cause `fstream` to stat the directory before emitting\n  // an entry for it, so the pipes are set up by the time the entry is emitted,\n  // and the entry has all the right permissions, etc. from statting it.\n  //\n  // The second weird behavior is that we need an entry for the top-level\n  // directory in the tarball to untar it with npm `tar`. (GNU tar, in\n  // contrast, appears to have no problems untarring tarballs without entries\n  // for the top-level directory inside them.) The problem is that, without an\n  // entry for the top-level directory, `fstream` will create the directory\n  // with the same permissions as the first file inside it. This manifests as\n  // an EACCESS when untarring if the first file inside the top-level directory\n  // is not writeable.\n  var fileStream = fstream.Reader({\n    path: files.convertToOSPath(dirPath),\n    filter: function (entry) {\n      if (process.platform !== \"win32\") {\n        return true;\n      }\n\n      // Refuse to create a directory that isn't listable. Tarballs\n      // created on Windows will have non-executable directories (since\n      // executable isn't a thing in Windows directory permissions), and\n      // so the resulting extracted directories will not be listable on\n      // Linux/Mac unless we explicitly make them executable. We think\n      // this should really be an option that you pass to node tar, but\n      // setting it in an 'entry' handler is the same strategy that npm\n      // does, so we do that here too.\n      if (entry.type === \"Directory\") {\n        entry.mode = (entry.mode || entry.props.mode) | 0o500;\n        entry.props.mode = entry.mode;\n      }\n\n      return true;\n    }\n  });\n  var tarStream = fileStream.pipe(tar.Pack({ noProprietary: true }));\n\n  return tarStream.pipe(zlib.createGzip());\n};\n\n// Tar-gzips a directory into a tarball on disk, synchronously.\n// The tar archive will contain a top-level directory named after dirPath.\nfiles.createTarball = function (dirPath, tarball, options) {\n  var out = files.createWriteStream(tarball);\n  new Promise(function (resolve, reject) {\n    out.on('error', reject);\n    out.on('close', resolve);\n    files.createTarGzStream(dirPath, options).pipe(out);\n  }).await();\n};\n\n// Use this if you'd like to replace a directory with another\n// directory as close to atomically as possible. It's better than\n// recursively deleting the target directory first and then\n// renaming. (Failure modes here include \"there's a brief moment where\n// toDir does not exist\" and \"you can end up with garbage directories\n// sitting around\", but not \"there's any time where toDir exists but\n// is in a state other than initial or final\".)\nfiles.renameDirAlmostAtomically = function (fromDir, toDir) {\n  var garbageDir = toDir + '-garbage-' + utils.randomToken();\n\n  // Get old dir out of the way, if it exists.\n  var movedOldDir = true;\n  try {\n    files.rename(toDir, garbageDir);\n  } catch (e) {\n    if (e.code !== 'ENOENT') {\n      throw e;\n    }\n    movedOldDir = false;\n  }\n\n  // Now rename the directory.\n  files.rename(fromDir, toDir);\n\n  // ... and delete the old one.\n  if (movedOldDir) {\n    files.rm_recursive(garbageDir);\n  }\n};\nfiles.renameDirAlmostAtomically = Profile(\"files.renameDirAlmostAtomically\",\n                                          files.renameDirAlmostAtomically);\n\nfiles.writeFileAtomically = function (filename, contents) {\n  var tmpFile = files.pathJoin(\n    files.pathDirname(filename),\n    '.' + files.pathBasename(filename) + '.' + utils.randomToken());\n  files.writeFile(tmpFile, contents);\n  files.rename(tmpFile, filename);\n};\nfiles.writeFileAtomically = Profile(\"files.writeFileAtomically\",\n                                    files.writeFileAtomically);\n\n// Like fs.symlinkSync, but creates a temporay link and renames it over the\n// file; this means it works even if the file already exists.\n// Do not use this function on Windows, it won't work.\nfiles.symlinkOverSync = function (linkText, file) {\n  fiberHelpers.noYieldsAllowed(function () {\n    file = files.pathResolve(file);\n    var tmpSymlink = files.pathJoin(\n      files.pathDirname(file),\n      \".\" + files.pathBasename(file) + \".tmp\" + utils.randomToken());\n    files.symlink(linkText, tmpSymlink);\n    files.rename(tmpSymlink, file);\n  });\n};\n\n// Return the result of evaluating `code` using\n// `runInThisContext`. `code` will be wrapped in a closure. You can\n// pass additional values to bind in the closure in `options.symbols`,\n// the keys being the symbols to bind and the values being their\n// values. `options.filename` is the filename to use in exceptions\n// that come from inside this code. `options.sourceMap` is an optional\n// source map that represents the file.\n//\n// The really special thing about this function is that if a parse\n// error occurs, we will raise an exception of type\n// files.FancySyntaxError, from which you may read 'message', 'file',\n// 'line', and 'column' attributes ... v8 is normally reluctant to\n// reveal this information but will write it to stderr if you pass it\n// an undocumented flag. Unforunately though node doesn't have dup2 so\n// we can't intercept the write. So instead we use a completely\n// different parser with a better error handling API. Ah well.  The\n// underlying V8 issue is:\n//   https://code.google.com/p/v8/issues/detail?id=1281\nfiles.runJavaScript = function (code, options) {\n  if (typeof code !== 'string') {\n    throw new Error(\"code must be a string\");\n  }\n\n  options = options || {};\n  var filename = options.filename || \"<anonymous>\";\n\n  return Profile.time('runJavaScript ' + filename, () => {\n\n    var keys = [], values = [];\n    // don't assume that _.keys and _.values are guaranteed to\n    // enumerate in the same order\n    _.each(options.symbols, function (value, name) {\n      keys.push(name);\n      values.push(value);\n    });\n\n    var stackFilename = filename;\n    if (options.sourceMap) {\n      // We want to generate an arbitrary filename that we use to associate the\n      // file with its source map.\n      stackFilename = \"<runJavaScript-\" + nextStackFilenameCounter++ + \">\";\n    }\n\n    var chunks = [];\n    var header = \"(function(\" + keys.join(',') + \"){\";\n    chunks.push(header);\n    if (options.sourceMap) {\n      var consumer = new sourcemap.SourceMapConsumer(options.sourceMap);\n      chunks.push(sourcemap.SourceNode.fromStringWithSourceMap(\n        code, consumer));\n    } else {\n      chunks.push(code);\n    }\n    // \\n is necessary in case final line is a //-comment\n    chunks.push(\"\\n})\");\n\n    var wrapped;\n    var parsedSourceMap = null;\n    if (options.sourceMap) {\n      var node = new sourcemap.SourceNode(null, null, null, chunks);\n      var results = node.toStringWithSourceMap({\n        file: stackFilename\n      });\n      wrapped = results.code;\n      parsedSourceMap = results.map.toJSON();\n      if (options.sourceMapRoot) {\n        // Add the specified root to any root that may be in the file.\n        parsedSourceMap.sourceRoot = files.pathJoin(\n          options.sourceMapRoot, parsedSourceMap.sourceRoot || '');\n      }\n      // source-map-support doesn't ever look at the sourcesContent field, so\n      // there's no point in keeping it in memory.\n      delete parsedSourceMap.sourcesContent;\n      parsedSourceMaps[stackFilename] = parsedSourceMap;\n    } else {\n      wrapped = chunks.join('');\n    };\n\n    try {\n      // See #runInThisContext\n      //\n      // XXX it'd be nice to runInNewContext so that the code can't mess\n      // with our globals, but objects that come out of runInNewContext\n      // have bizarro antimatter prototype chains and break 'instanceof\n      // Array'. for now, steer clear\n      //\n      // Pass 'true' as third argument if we want the parse error on\n      // stderr (which we don't).\n      var script = require('vm').createScript(wrapped, stackFilename);\n    } catch (nodeParseError) {\n      if (!(nodeParseError instanceof SyntaxError)) {\n        throw nodeParseError;\n      }\n      // Got a parse error. Unfortunately, we can't actually get the\n      // location of the parse error from the SyntaxError; Node has some\n      // hacky support for displaying it over stderr if you pass an\n      // undocumented third argument to stackFilename, but that's not\n      // what we want. See\n      //    https://github.com/joyent/node/issues/3452\n      // for more information. One thing to try (and in fact, what an\n      // early version of this function did) is to actually fork a new\n      // node to run the code and parse its output. We instead run an\n      // entirely different JS parser, from the Babel project, but\n      // which at least has a nice API for reporting errors.\n      var parse = require('meteor-babel').parse;\n      try {\n        parse(wrapped, { strictMode: false });\n      } catch (parseError) {\n        if (typeof parseError.loc !== \"object\") {\n          throw parseError;\n        }\n\n        var err = new files.FancySyntaxError;\n        err.message = parseError.message;\n\n        if (parsedSourceMap) {\n          // XXX this duplicates code in computeGlobalReferences\n          var consumer2 = new sourcemap.SourceMapConsumer(parsedSourceMap);\n          var original = consumer2.originalPositionFor(parseError.loc);\n          if (original.source) {\n            err.file = original.source;\n            err.line = original.line;\n            err.column = original.column;\n            throw err;\n          }\n        }\n\n        err.file = filename;  // *not* stackFilename\n        err.line = parseError.loc.line;\n        err.column = parseError.loc.column;\n\n        // adjust errors on line 1 to account for our header\n        if (err.line === 1) {\n          err.column -= header.length;\n        }\n\n        throw err;\n      }\n\n      // What? Node thought that this was a parse error and Babel didn't?\n      // Eh, just throw Node's error and don't care too much about the line\n      // numbers being right.\n      throw nodeParseError;\n    }\n\n    var func = script.runInThisContext();\n\n    return (buildmessage.markBoundary(func)).apply(null, values);\n  });\n};\n\n// - message: an error message from the parser\n// - file: filename\n// - line: 1-based\n// - column: 1-based\nfiles.FancySyntaxError = function () {};\n\nfiles.OfflineError = function (error) {\n  this.error = error;\n};\nfiles.OfflineError.prototype.toString = function () {\n  return \"[Offline: \" + this.error.toString() + \"]\";\n};\n\n// Like files.readdir, but skips entries whose names begin with dots, and\n// converts ENOENT to [].\nfiles.readdirNoDots = function (path) {\n  try {\n    var entries = files.readdir(path);\n  } catch (e) {\n    if (e.code === 'ENOENT') {\n      return [];\n    }\n    throw e;\n  }\n  return _.filter(entries, function (entry) {\n    return entry && entry[0] !== '.';\n  });\n};\n\n// Read a file in line by line. Returns an array of lines to be\n// processed individually. Throws if the file doesn't exist or if\n// anything else goes wrong.\nvar getLines = function (file) {\n  var buffer = files.readFile(file);\n  var lines = exports.splitBufferToLines(buffer);\n\n  // strip blank lines at the end\n  while (lines.length) {\n    var line = lines[lines.length - 1];\n    if (line.match(/\\S/)) {\n      break;\n    }\n    lines.pop();\n  }\n\n  return lines;\n};\n\nexports.getLines = getLines;\n\nexports.splitBufferToLines = function (buffer) {\n  return buffer.toString('utf8').split(/\\r*\\n\\r*/);\n};\n\n// Same as `getLines`, but returns [] if the file doesn't exist.\nexports.getLinesOrEmpty = function (file) {\n  try {\n    return getLines(file);\n  } catch (e) {\n    if (e && e.code === 'ENOENT') {\n      return [];\n    }\n    throw e;\n  }\n};\n\n// Returns null if the file does not exist, otherwise returns the parsed JSON in\n// the file. Throws on errors other than ENOENT (including JSON parse failure).\nexports.readJSONOrNull = function (file) {\n  try {\n    var raw = files.readFile(file, 'utf8');\n  } catch (e) {\n    if (e && e.code === 'ENOENT') {\n      return null;\n    }\n    throw e;\n  }\n  return JSON.parse(raw);\n};\n\n// Trims whitespace & other filler characters of a line in a project file.\nfiles.trimSpaceAndComments = function (line) {\n  var match = line.match(/^([^#]*)#/);\n  if (match) {\n    line = match[1];\n  }\n  return files.trimSpace(line);\n};\n\n// Trims leading and trailing whilespace in a project file.\nfiles.trimSpace = function (line) {\n  return line.replace(/^\\s+|\\s+$/g, '');\n};\n\n\nfiles.KeyValueFile = function (path) {\n  var self = this;\n  self.path = path;\n}\n\n_.extend(files.KeyValueFile.prototype, {\n  set: function (k, v) {\n    var self = this;\n\n    var data = self._readAll() || '';\n    var lines = data.split(/\\n/);\n\n    var found = false;\n    for (var i = 0; i < lines.length; i++) {\n      var trimmed = lines[i].trim();\n      if (trimmed.indexOf(k + '=') == 0) {\n        lines[i] = k + '=' + v;\n        found = true;\n      }\n    }\n    if (!found) {\n      lines.push(k + \"=\" + v);\n    }\n    var newdata = lines.join('\\n') + '\\n';\n    files.writeFile(self.path, newdata, 'utf8');\n  },\n\n  _readAll: function () {\n    var self = this;\n\n    if (files.exists(self.path)) {\n      return files.readFile(self.path, 'utf8');\n    } else {\n      return null;\n    }\n  }\n});\n\nfiles.getHomeDir = function () {\n  if (process.platform === \"win32\") {\n    return files.pathDirname(\n      files.convertToStandardPath(process.env.METEOR_INSTALLATION));\n  } else {\n    return process.env.HOME;\n  }\n};\n\nfiles.currentEnvWithPathsAdded = function (...paths) {\n  const env = {...process.env};\n\n  let pathPropertyName;\n  if (process.platform === \"win32\") {\n    // process.env allows for case insensitive access on Windows, but copying it\n    // creates a normal JavaScript object with case sensitive property access.\n    // This leads to problems, because we would be adding a PATH property instead\n    // of setting Path for instance.\n    // We want to make sure we're setting the right property, so we\n    // lookup the property name case insensitively ourselves.\n    pathPropertyName = _.find(Object.keys(env), (key) => {\n      return key.toUpperCase() === 'PATH';\n    });\n    if (!pathPropertyName) {\n      pathPropertyName = 'Path';\n    }\n  } else {\n    pathPropertyName = 'PATH';\n  }\n\n  const convertedPaths = paths.map(path => files.convertToOSPath(path));\n  let pathDecomposed = (env[pathPropertyName] || \"\").split(files.pathOsDelimiter);\n  pathDecomposed.unshift(...convertedPaths);\n\n  env[pathPropertyName] = pathDecomposed.join(files.pathOsDelimiter);\n  return env;\n}\n\n// add .bat extension to link file if not present\nvar ensureBatExtension = function (p) {\n  if (p.indexOf(\".bat\") !== p.length - 4) {\n    p = p + \".bat\";\n  }\n  return p;\n};\n\n// Windows-only, generates a bat script that calls the destination bat script\nfiles._generateScriptLinkToMeteorScript = function (scriptLocation) {\n  var scriptLocationIsAbsolutePath = scriptLocation.match(/^\\//);\n  var scriptLocationConverted = scriptLocationIsAbsolutePath\n    ? files.convertToWindowsPath(scriptLocation)\n    : \"%~dp0\\\\\" + files.convertToWindowsPath(scriptLocation);\n\n  var newScript = [\n    \"@echo off\",\n    \"SETLOCAL\",\n    \"SET METEOR_INSTALLATION=%~dp0%\",\n\n    // always convert to Windows path since this function can also be\n    // called on Linux or Mac when we are building bootstrap tarballs\n    \"\\\"\" + scriptLocationConverted + \"\\\" %*\",\n    \"ENDLOCAL\",\n\n    // always exit with the same exit code as the child script\n    \"EXIT /b %ERRORLEVEL%\",\n\n    // add a comment with the destination of the link, so it can be read later\n    // by files.readLinkToMeteorScript\n    \"rem \" + scriptLocationConverted,\n  ].join(os.EOL);\n\n  return newScript;\n};\n\nfiles._getLocationFromScriptLinkToMeteorScript = function (script) {\n  var lines = _.compact(script.toString().split('\\n'));\n\n  var scriptLocation = _.last(lines)\n    .replace(/^rem /g, '');\n  var isAbsolute = true;\n\n  if (scriptLocation.match(/^%~dp0/)) {\n    isAbsolute = false;\n    scriptLocation = scriptLocation.replace(/^%~dp0\\\\?/g, '');\n  }\n\n  if (! scriptLocation) {\n    throw new Error('Failed to parse script location from meteor.bat');\n  }\n\n  return files.convertToPosixPath(scriptLocation, ! isAbsolute);\n};\n\nfiles.linkToMeteorScript = function (scriptLocation, linkLocation, platform) {\n  platform = platform || process.platform;\n\n  if (platform === 'win32') {\n    // Make a meteor batch script that points to current tool\n\n    linkLocation = ensureBatExtension(linkLocation);\n    scriptLocation = ensureBatExtension(scriptLocation);\n    var script = files._generateScriptLinkToMeteorScript(scriptLocation);\n\n    files.writeFile(linkLocation, script, {encoding: \"ascii\"});\n  } else {\n    // Symlink meteor tool\n    files.symlinkOverSync(scriptLocation, linkLocation);\n  }\n};\n\nfiles.readLinkToMeteorScript = function (linkLocation, platform) {\n  platform = platform || process.platform;\n  if (platform === 'win32') {\n    linkLocation = ensureBatExtension(linkLocation);\n    var script = files.readFile(linkLocation);\n    return files._getLocationFromScriptLinkToMeteorScript(script);\n  } else {\n    return files.readlink(linkLocation);\n  }\n};\n\n// Summary of cross platform file system handling strategy\n\n// There are three main pain points for handling files on Windows: slashes in\n// paths, line endings in text files, and colons/invalid characters in paths.\n\n// 1. Slashes in file paths\n\n//   We have decided to store all paths inside the tool as unix-style paths in\n//   the style of CYGWIN. This means that all paths have forward slashes on all\n//   platforms, and C:\\ is converted to /c/ on Windows.\n\n//   All of the methods in files.js know how to convert from these unixy paths\n//   to whatever type of path the underlying system prefers.\n\n//   The reason we chose this strategy because it was easier to make sure to use\n//   files.js everywhere instead of node's fs than to make sure every part of\n//   the tool correctly uses system-specific path separators. In addition, there\n//   are some parts of the tool where it is very hard to tell which strings are\n//   used as URLs and which are used as file paths. In some cases, a string can\n//   be used as both, meaning it has to have forward slashes no matter what.\n\n// 2. Line endings in text files\n\n//   We have decided to convert all files read by the tool to Unix-style line\n//   endings for the same reasons as slashes above. In many parts of the tool,\n//   we assume that '\\n' is the line separator, and it can be hard to find all\n//   of the places and decide whether it is appropriate to use os.EOL. We do not\n//   convert anything on write. We will wait and see if anyone complains.\n\n// 3. Colons and other invalid characters in file paths\n\n//   This is not handled automatically by files.js. You need to be careful to\n//   escape any colons in package names, etc, before using a string as a file\n//   path.\n\n//   A helpful file to import for this purpose is colon-converter.js, which also\n//   knows how to convert various configuration file formats.\n\n\nfiles.fsFixPath = {};\n/**\n * Wrap a function from node's fs module to use the right slashes for this OS\n * and run in a fiber, then assign it to the \"files\" namespace. Each call\n * creates a files.func that runs asynchronously with Fibers (yielding and\n * until the call is done), unless run outside a Fiber or in noYieldsAllowed, in\n * which case it uses fs.funcSync.\n *\n * Also creates a simpler version on files.fsFixPath.* that just fixes the path\n * and fiberizes the Sync version if possible.\n *\n * @param  {String} fsFuncName         The name of the node fs function to wrap\n * @param  {Number[]} pathArgIndices Indices of arguments that have paths, these\n * arguments will be converted to the correct OS slashes\n * @param  {Object} options        Some options for lesser-used cases\n * @param {Boolean} options.noErr If true, the callback of the wrapped function\n * doesn't have a first \"error\" argument, for example in fs.exists.\n * @param {Function} options.modifyReturnValue Pass in a function to modify the\n * return value\n */\nfunction wrapFsFunc(fsFuncName, pathArgIndices, options) {\n  options = options || {};\n\n  const fsFunc = fs[fsFuncName];\n  const fsFuncSync = fs[fsFuncName + \"Sync\"];\n\n  function makeWrapper ({alwaysSync, sync}) {\n    function wrapper(...args) {\n      for (let j = pathArgIndices.length - 1; j >= 0; --j) {\n        const i = pathArgIndices[j];\n        args[i] = files.convertToOSPath(args[i]);\n      }\n\n      const canYield = Fiber.current && Fiber.yield && ! Fiber.yield.disallowed;\n      const shouldBeSync = alwaysSync || sync;\n      // There's some overhead in awaiting a Promise of an async call,\n      // vs just doing the sync call, which for a call like \"stat\"\n      // takes longer than the call itself.  Different parts of the tool\n      // may perform 1,000s or 10,000s of stats each under certain\n      // conditions, so we get a nice performance boost from making\n      // these calls sync.\n      const isQuickie = (fsFuncName === 'stat' ||\n                         fsFuncName === 'rename');\n\n      if (canYield && shouldBeSync && !isQuickie) {\n        const promise = new Promise((resolve, reject) => {\n          args.push((err, value) => {\n            if (options.noErr) {\n              resolve(err);\n            } else if (err) {\n              reject(err);\n            } else {\n              resolve(value);\n            }\n          });\n\n          fsFunc.apply(fs, args);\n        });\n\n        const result = promise.await();\n\n        return options.modifyReturnValue\n          ? options.modifyReturnValue(result)\n          : result;\n\n      } else if (shouldBeSync) {\n        // Should be sync but can't yield: we are not in a Fiber.\n        // Run the sync version of the fs.* method.\n        const result = fsFuncSync.apply(fs, args);\n        return options.modifyReturnValue ?\n               options.modifyReturnValue(result) : result;\n\n      } else if (! sync) {\n        // wrapping a plain async version\n        let cb = args[args.length - 1];\n        if (typeof cb === \"function\") {\n          args.pop();\n        } else {\n          cb = null;\n        }\n\n        new Promise((resolve, reject) => {\n          args.push((err, res) => {\n            err ? reject(err) : resolve(res);\n          });\n          fsFunc.apply(fs, args);\n        }).then(res => {\n          if (options.modifyReturnValue) {\n            res = options.modifyReturnValue(res);\n          }\n          cb && cb(null, res);\n        }, cb);\n\n        return;\n      }\n\n      throw new Error('unexpected');\n    }\n\n    wrapper.displayName = fsFuncName;\n    return wrapper;\n  }\n\n  files[fsFuncName] = Profile('files.' + fsFuncName, makeWrapper({ alwaysSync: true }));\n\n  files.fsFixPath[fsFuncName] =\n    Profile('wrapped.fs.' + fsFuncName, makeWrapper({ sync: false }));\n  files.fsFixPath[fsFuncName + 'Sync'] =\n    Profile('wrapped.fs.' + fsFuncName + 'Sync', makeWrapper({ sync: true }));\n}\n\nwrapFsFunc(\"writeFile\", [0]);\nwrapFsFunc(\"appendFile\", [0]);\nwrapFsFunc(\"readFile\", [0], {\n  modifyReturnValue: function (fileData) {\n    if (_.isString(fileData)) {\n      return files.convertToStandardLineEndings(fileData);\n    }\n\n    return fileData;\n  }\n});\nwrapFsFunc(\"stat\", [0]);\nwrapFsFunc(\"lstat\", [0]);\nwrapFsFunc(\"rename\", [0, 1]);\n\n// After the outermost files.withCache call returns, the withCacheCache is\n// reset to null so that it does not survive server restarts.\nlet withCacheCache = null;\n\nfiles.withCache = Profile(\"files.withCache\", function (fn) {\n  const oldCache = withCacheCache;\n  withCacheCache = oldCache || Object.create(null);\n  try {\n    return fn();\n  } finally {\n    withCacheCache = oldCache;\n  }\n});\n\nfunction enableCache(name) {\n  const method = files[name];\n\n  function makeCacheKey(args) {\n    var parts = [name];\n\n    for (var i = 0; i < args.length; ++i) {\n      var arg = args[i];\n\n      if (typeof arg !== \"string\") {\n        // If any of the arguments is not a string, then we won't cache\n        // the result of the corresponding file.* method invocation.\n        return null;\n      }\n\n      parts.push(arg);\n    }\n\n    return parts.join(\"\\0\");\n  }\n\n  files[name] = function (...args) {\n    if (withCacheCache) {\n      var cacheKey = makeCacheKey(args);\n      if (cacheKey && cacheKey in withCacheCache) {\n        return withCacheCache[cacheKey];\n      }\n    }\n\n    const result = method.apply(files, args);\n\n    if (withCacheCache && cacheKey !== null) {\n      // If cacheKey === null, then we called makeCacheKey above and it\n      // failed because one of the arguments was not a string, so we\n      // should not try to call makeCacheKey again.\n      withCacheCache[cacheKey || makeCacheKey(args)] = result;\n    }\n\n    return result;\n  };\n}\n\nenableCache(\"readdir\");\nenableCache(\"realpath\");\nenableCache(\"stat\");\nenableCache(\"lstat\");\n\n// The fs.exists method is deprecated in Node v4:\n// https://nodejs.org/api/fs.html#fs_fs_exists_path_callback\nfiles.exists =\nfiles.existsSync = function (path, callback) {\n  if (typeof callback === \"function\") {\n    throw new Error(\"Passing a callback to files.exists is no longer supported\");\n  }\n  return !! files.statOrNull(path);\n};\n\nif (process.platform === \"win32\") {\n  var rename = files.rename;\n\n  files.rename = function (from, to) {\n    // retries are necessarily only on Windows, because the rename call can fail\n    // with EBUSY, which means the file is \"busy\"\n    var maxTries = 10;\n    var success = false;\n    while (! success && maxTries-- > 0) {\n      try {\n        rename(from, to);\n        success = true;\n      } catch (err) {\n        if (err.code !== 'EPERM') {\n          throw err;\n        }\n      }\n    }\n    if (! success) {\n      files.cp_r(from, to);\n      files.rm_recursive(from);\n    }\n  };\n}\n\n// Warning: doesn't convert slashes in the second 'cache' arg\nwrapFsFunc(\"realpath\", [0], {\n  modifyReturnValue: files.convertToStandardPath\n});\n\nwrapFsFunc(\"readdir\", [0], {\n  modifyReturnValue: function (entries) {\n    return _.map(entries, files.convertToStandardPath);\n  }\n});\n\nwrapFsFunc(\"rmdir\", [0]);\nwrapFsFunc(\"mkdir\", [0]);\nwrapFsFunc(\"unlink\", [0]);\nwrapFsFunc(\"chmod\", [0]);\nwrapFsFunc(\"open\", [0]);\n\n// XXX this doesn't give you the second argument to the callback\nwrapFsFunc(\"read\", []);\nwrapFsFunc(\"write\", []);\nwrapFsFunc(\"close\", []);\nwrapFsFunc(\"symlink\", [0, 1]);\nwrapFsFunc(\"readlink\", [0]);\n\n// These don't need to be Fiberized\nfiles.createReadStream = function (...args) {\n  args[0] = files.convertToOSPath(args[0]);\n  return fs.createReadStream(...args);\n};\n\nfiles.createWriteStream = function (...args) {\n  args[0] = files.convertToOSPath(args[0]);\n  return fs.createWriteStream(...args);\n};\n\nfiles.watchFile = function (...args) {\n  args[0] = files.convertToOSPath(args[0]);\n  return fs.watchFile(...args);\n};\n\nfiles.unwatchFile = function (...args) {\n  args[0] = files.convertToOSPath(args[0]);\n  return fs.unwatchFile(...args);\n};\n\n// wrap pathwatcher because it works with file system paths\n// XXX we don't currently convert the path argument passed to the watch\n//     callback, but we currently don't use the argument either\nfiles.pathwatcherWatch = function (...args) {\n  args[0] = files.convertToOSPath(args[0]);\n  // don't import pathwatcher until the moment we actually need it\n  // pathwatcher has a record of keeping some global state\n  var pathwatcher = require('pathwatcher');\n  return require(\"pathwatcher\").watch(...args);\n};\n\nfiles.readBufferWithLengthAndOffset = function (filename, length, offset) {\n  var data = new Buffer(length);\n  // Read the data from disk, if it is non-empty. Avoid doing IO for empty\n  // files, because (a) unnecessary and (b) fs.readSync with length 0\n  // throws instead of acting like POSIX read:\n  // https://github.com/joyent/node/issues/5685\n  if (length > 0) {\n    var fd = files.open(filename, \"r\");\n    try {\n      var count = files.read(\n        fd, data, 0, length, offset);\n    } finally {\n      files.close(fd);\n    }\n    if (count !== length) {\n      throw new Error(\"couldn't read entire resource\");\n    }\n  }\n  return data;\n};\n"
  },
  {
    "path": "tools/fs/mini-files.js",
    "content": "var miniFiles = require('../static-assets/server/mini-files.js');\nmodule.exports = miniFiles;\n"
  },
  {
    "path": "tools/fs/safe-pathwatcher.js",
    "content": "var files = require('./files.js');\n\n// Set METEOR_WATCH_FORCE_POLLING environment variable to a truthy value to\n// force the use of files.watchFile instead of pathwatcher.watch.\n// Enabled on Mac and Linux and disabled on Windows by default.\nvar PATHWATCHER_ENABLED = !process.env.METEOR_WATCH_FORCE_POLLING;\nif (process.platform === \"win32\") {\n  PATHWATCHER_ENABLED = false;\n}\n\nvar DEFAULT_POLLING_INTERVAL =\n      ~~process.env.METEOR_WATCH_POLLING_INTERVAL_MS || 5000;\n\n\nvar NO_PATHWATCHER_POLLING_INTERVAL =\n      ~~process.env.METEOR_WATCH_POLLING_INTERVAL_MS || 500;\n\nvar suggestedRaisingWatchLimit = false;\n\nexports.watch = function watch(absPath, callback) {\n  var lastPathwatcherEventTime = 0;\n\n  function pathwatcherWrapper() {\n    // It's tempting to call files.unwatchFile(absPath, watchFileWrapper)\n    // here, but previous pathwatcher success is no guarantee of future\n    // pathwatcher reliability. For example, pathwatcher works just fine\n    // when file changes originate from within a Vagrant VM, but changes\n    // to shared files made outside the VM are invisible to pathwatcher,\n    // so our only hope of catching them is to continue polling.\n    lastPathwatcherEventTime = +new Date;\n    callback.apply(this, arguments);\n  }\n\n  var watcher = null;\n  if (PATHWATCHER_ENABLED) {\n    try {\n      watcher = files.pathwatcherWatch(absPath, pathwatcherWrapper);\n    } catch (e) {\n      // If it isn't an actual pathwatcher failure, rethrow.\n      if (e.message !== 'Unable to watch path') {\n        throw e;\n      }\n      var constants = require('constants');\n      var archinfo = require('../utils/archinfo.js');\n      if (! suggestedRaisingWatchLimit &&\n          // Note: the not-super-documented require('constants') maps from\n          // strings to SYSTEM errno values. System errno values aren't the same\n          // as the numbers used internally by libuv! Once we're upgraded\n          // to Node 0.12, we'll have the system errno as a string (on 'code'),\n          // but the support for that wasn't in Node 0.10's uv.\n          // See our PR https://github.com/atom/node-pathwatcher/pull/53\n          // (and make sure to read the final commit message, not the original\n          // proposed PR, which had a slightly different interface).\n          e.errno === constants.ENOSPC &&\n          // The only suggestion we currently have is for Linux.\n          archinfo.matches(archinfo.host(), 'os.linux')) {\n        suggestedRaisingWatchLimit = true;\n        var Console = require('../console/console.js').Console;\n        Console.arrowWarn(\n          \"It looks like a simple tweak to your system's configuration will \" +\n            \"make many tools (including this Meteor command) more efficient. \" +\n            \"To learn more, see \" +\n            Console.url(\"https://github.com/meteor/meteor/wiki/File-Change-Watcher-Efficiency\"));\n      }\n      // ... ignore the error.  We'll still have watchFile, which is good\n      // enough.\n    }\n  };\n\n  var pollingInterval = watcher\n        ? DEFAULT_POLLING_INTERVAL : NO_PATHWATCHER_POLLING_INTERVAL;\n\n  function watchFileWrapper() {\n    // If a pathwatcher event fired in the last polling interval, ignore\n    // this event.\n    if (new Date - lastPathwatcherEventTime > pollingInterval) {\n      callback.apply(this, arguments);\n    }\n  }\n\n  // We use files.watchFile in addition to pathwatcher.watch as a fail-safe to\n  // detect file changes even on network file systems.  However (unless the user\n  // disabled pathwatcher or this pathwatcher call failed), we use a relatively\n  // long default polling interval of 5000ms to save CPU cycles.\n  files.watchFile(absPath, {\n    persistent: false,\n    interval: pollingInterval\n  }, watchFileWrapper);\n\n  var polling = true;\n\n  return {\n    close: function close() {\n      if (watcher) {\n        watcher.close();\n        watcher = null;\n      }\n\n      if (polling) {\n        polling = false;\n        files.unwatchFile(absPath, watchFileWrapper);\n      }\n    }\n  };\n};\n"
  },
  {
    "path": "tools/fs/watch.js",
    "content": "import files from './files.js';\nimport _ from \"underscore\";\nimport pathwatcher from './safe-pathwatcher.js';\nimport {createHash} from \"crypto\";\nimport {coalesce} from '../utils/func-utils.js';\nimport {Profile} from '../tool-env/profile.js';\n\n// Watch for changes to a set of files, and the first time that any of\n// the files change, call a user-provided callback. (If you want a\n// second callback, you'll need to create a second Watcher.)\n//\n// You describe the structure you want to watch in a WatchSet; you then create a\n// Watcher to watch it. Watcher does not mutate WatchSet, so you can create\n// several Watchers from the same WatchSet. WatchSet can be easily converted to\n// and from JSON for serialization.\n//\n// You can set up two kinds of watches, file and directory watches.\n//\n// In a file watch, you provide an absolute path to a file and a SHA1 (encoded\n// as hex) of the contents of that file. If the file ever changes so that its\n// contents no longer match that SHA1, the callback triggers. You can also\n// provide `null` for the SHA1, which means the file should not exist.\n//\n// In a directory watch, you provide an absolute path to a directory,\n// two lists of regular expressions specifying the entries to\n// include and exclude, a list of specific names to include (which ignores\n// the exclude regexp list) and an array of which entries to expect.\n//\n// For directory watches, the regular expressions work as follows. You provide\n// two arrays of regular expressions, an include list and an exclude list. An\n// entry in the directory matches if it matches at least one regular expression\n// in the include list, and doesn't match any regular expressions in the exclude\n// list. The string that is matched against the regular expression ends with a\n// '/' if the entry is directory. There is NO IMPLICIT RECURSION here: a\n// directory watch ONLY watches the immediate children of the directory! If you\n// want a recursive watch, you need to do the recursive walk while building the\n// WatchSet and add a bunch of separate directory watches.  In addition, you\n// can provide a list of specific names to expect; these are not filtered\n// by the exclude list.  (For example, you might want to see all \"*.js\" files\n// but ignore files starting with dots (which are often temporary files), but\n// explicitly ask for \".jshintrc\".)\n//\n// There can be multiple directory watches on the same directory. There is no\n// relationship between the files found in directory watches and the files\n// watched by file watches; they are parallel mechanisms.\n//\n// Regular expressions are checked only against individual path components (the\n// actual name of the file or the subdirectory) plus the trailing '/' for\n// directories, not against the entire path.\n//\n// You can call stop() to stop watching and tear down the\n// watcher. Calling stop() guarantees that you will not receive a\n// callback (if you have not already). Calling stop() is unnecessary\n// if you've received a callback.\n//\n// To do a \"one-shot\" (to see if any files have been modified, compared to the\n// dependencies, at a particular point in time), use the isUpToDate function.\n//\n// XXX Symlinks are currently treated transparently: we treat them as the thing\n// they point to (ie, as a directory if they point to a directory, as\n// nonexistent if they point to something nonexist, etc). Not sure if this is\n// correct.\n\nexport class WatchSet {\n  constructor() {\n    var self = this;\n\n    // Set this to true if any Watcher built on this WatchSet must immediately\n    // fire (eg, if this WatchSet was given two different sha1 for the same file).\n    self.alwaysFire = false;\n\n    // Map from the absolute path to a file, to a sha1 hash, or null if the file\n    // should not exist. A Watcher created from this set fires when the file\n    // changes from that sha, or is deleted (if non-null) or created (if null).\n    //\n    // Note that Isopack.getSourceFilesUnderSourceRoot() depends on this field\n    // existing (it's not just an internal implementation detail of watch.js).\n    self.files = {};\n\n    // Array of object with keys:\n    // - 'absPath': absolute path to a directory\n    // - 'include': array of RegExps\n    // - 'exclude': array of RegExps\n    // - 'names': array of strings\n    // - 'contents': array of strings, or null if the directory should not exist\n    //\n    // This represents the assertion that 'absPath' is a directory and that\n    // 'contents' is its immediate contents, as filtered by the regular\n    // expressions.  Entries in 'contents' are file and subdirectory names;\n    // directory names end with '/'. 'contents' is sorted. An entry is in\n    // 'contents' if its value (including the slash, for directories) matches at\n    // least one regular expression in 'include' and no regular expressions in\n    // 'exclude'... or if it is in 'names'.\n    //\n    // There is no recursion here: files contained in subdirectories never appear.\n    //\n    // A directory may have multiple entries (presumably with different\n    // include/exclude filters).\n    self.directories = [];\n  }\n\n  addFile(filePath, hash) {\n    var self = this;\n    // No need to update if this is in always-fire mode already.\n    if (self.alwaysFire) {\n      return;\n    }\n    if (_.has(self.files, filePath)) {\n      // Redundant?\n      if (self.files[filePath] === hash) {\n        return;\n      }\n      // Nope, inconsistent.\n      self.alwaysFire = true;\n      return;\n    }\n    self.files[filePath] = hash;\n  }\n\n  addDirectory({absPath, include, exclude, names, contents: unsortedContents}) {\n    var self = this;\n    if (self.alwaysFire) {\n      return;\n    }\n    if (_.isEmpty(include) && _.isEmpty(names)) {\n      return;\n    }\n    const contents = _.clone(unsortedContents);\n    if (contents) {\n      contents.sort();\n    }\n\n    self.directories.push({absPath, include, exclude, names, contents});\n  }\n\n  // Merges another WatchSet into this one. This one will now fire if either\n  // WatchSet would have fired.\n  merge(other) {\n    var self = this;\n    if (self.alwaysFire) {\n      return;\n    }\n    if (other.alwaysFire) {\n      self.alwaysFire = true;\n      return;\n    }\n   _.each(other.files, function (hash, name) {\n     self.addFile(name, hash);\n   });\n    _.each(other.directories, function (dir) {\n      // XXX this doesn't deep-clone the directory, but I think these objects\n      // are never mutated #WatchSetShallowClone\n      self.directories.push(dir);\n    });\n  }\n\n  clone() {\n    var self = this;\n    var ret = new WatchSet();\n\n    // XXX doesn't bother to deep-clone the directory info\n    // #WatchSetShallowClone\n    ret.alwaysFire = self.alwaysFire;\n    ret.files = _.clone(self.files);\n    ret.directories = _.clone(self.directories);\n    return ret;\n  }\n\n  toJSON() {\n    var self = this;\n    if (self.alwaysFire) {\n      return {alwaysFire: true};\n    }\n    var ret = {files: self.files};\n\n    var reToJSON = function (r) {\n      var options = '';\n      if (r.ignoreCase) {\n        options += 'i';\n      }\n      if (r.multiline) {\n        options += 'm';\n      }\n      if (r.global) {\n        options += 'g';\n      }\n      if (options) {\n        return {$regex: r.source, $options: options};\n      }\n      return r.source;\n    };\n\n    ret.directories = _.map(self.directories, function (d) {\n      return {\n        absPath: d.absPath,\n        include: _.map(d.include, reToJSON),\n        exclude: _.map(d.exclude, reToJSON),\n        names: d.names,\n        contents: d.contents\n      };\n    });\n\n    return ret;\n  }\n\n  static fromJSON(json) {\n    var set = new WatchSet();\n\n    if (! json) {\n      return set;\n    }\n\n    if (json.alwaysFire) {\n      set.alwaysFire = true;\n      return set;\n    }\n\n    set.files = _.clone(json.files);\n\n    var reFromJSON = function (j) {\n      if (_.has(j, '$regex')) {\n        return new RegExp(j.$regex, j.$options);\n      }\n      return new RegExp(j);\n    };\n\n    set.directories = _.map(json.directories, function (d) {\n      return {\n        absPath: d.absPath,\n        include: _.map(d.include, reFromJSON),\n        exclude: _.map(d.exclude, reFromJSON),\n        names: d.names,\n        contents: d.contents\n      };\n    });\n\n    return set;\n  }\n}\n\nvar readFile = function (absPath) {\n  try {\n    return files.readFile(absPath);\n  } catch (e) {\n    // Rethrow most errors.\n    if (! e || (e.code !== 'ENOENT' && e.code !== 'EISDIR')) {\n      throw e;\n    }\n    // File does not exist (or is a directory).\n    return null;\n  }\n};\n\nexport function sha1(contents) {\n  return Profile(\"sha1\", function () {\n    var hash = createHash('sha1');\n    hash.update(contents);\n    return hash.digest('hex');\n  })();\n}\n\nexport function readDirectory({absPath, include, exclude, names}) {\n  // Read the directory.\n  try {\n    var contents = files.readdir(absPath);\n  } catch (e) {\n    // If the path is not a directory, return null; let other errors through.\n    if (e && (e.code === 'ENOENT' || e.code === 'ENOTDIR')) {\n      return null;\n    }\n    throw e;\n  }\n\n  // Add slashes to the end of directories.\n  var contentsWithSlashes = [];\n  _.each(contents, function (entry) {\n    try {\n      // We do stat instead of lstat here, so that we treat symlinks to\n      // directories just like directories themselves.\n      // XXX Does the treatment of symlinks make sense?\n      var stats = files.stat(files.pathJoin(absPath, entry));\n    } catch (e) {\n      if (e && (e.code === 'ENOENT')) {\n        // Disappeared after the readdir (or a dangling symlink)? Eh,\n        // pretend it was never there in the first place.\n        return;\n      }\n      throw e;\n    }\n    if (stats.isDirectory()) {\n      entry += '/';\n    }\n    contentsWithSlashes.push(entry);\n  });\n\n  // Filter based on regexps.\n  var filtered = contentsWithSlashes.filter((entry) => {\n    // Is it one of the names we explicitly requested?\n    if (names && names.indexOf(entry) !== -1) {\n      return true;\n    }\n    // Is it ruled out by an exclude rule?\n    if (exclude && exclude.some(re => re.test(entry))) {\n      return false;\n    }\n    // Is it ruled in by an include rule?\n    if (include && include.some(re => re.test(entry))) {\n      return true;\n    }\n    return false;\n  });\n\n  // Sort it!\n  filtered.sort();\n  return filtered;\n}\n\n// All fields are private.\nexport class Watcher {\n  constructor(options) {\n    var self = this;\n\n    // The set to watch.\n    self.watchSet = options.watchSet;\n    if (! self.watchSet) {\n      throw new Error(\"watchSet option is required\");\n    }\n\n    // Function to call when a change is detected according to one of\n    // the above.\n    self.onChange = options.onChange;\n    if (! self.onChange) {\n      throw new Error(\"onChange option is required\");\n    }\n\n    self.stopped = false;\n    self.justCheckOnce = !! options._justCheckOnce;\n\n    self.watches = {\n      // <absolute path of watched file or directory>: {\n      //   // Null until pathwatcher.watch succeeds in watching the file.\n      //   watcher: <object returned by pathwatcher.watch> | null,\n      //   // Undefined until we stat the file for the first time, then null\n      //   // if the file is observed to be missing.\n      //   lastStat: <object returned by files.stat> | null | undefined\n      // }\n    };\n\n    // Were we given an inconsistent WatchSet? Fire now and be done with it.\n    if (self.watchSet.alwaysFire) {\n      self._fire();\n      return;\n    }\n\n    self._startFileWatches();\n    self._checkDirectories();\n  }\n\n  _fireIfFileChanged(absPath) {\n    var self = this;\n\n    if (self.stopped) {\n      return true;\n    }\n\n    var oldHash = self.watchSet.files[absPath];\n\n    if (oldHash === undefined) {\n      throw new Error(\"Checking unknown file \" + absPath);\n    }\n\n    var contents = readFile(absPath);\n\n    if (contents === null) {\n      // File does not exist (or is a directory).\n      // Is this what we expected?\n      if (oldHash === null) {\n        return false;\n      }\n      // Nope, not what we expected.\n      self._fire();\n      return true;\n    }\n\n    // File exists! Is that what we expected?\n    if (oldHash === null) {\n      self._fire();\n      return true;\n    }\n\n    var newHash = sha1(contents);\n\n    // Unchanged?\n    if (newHash === oldHash) {\n      return false;\n    }\n\n    self._fire();\n    return true;\n  }\n\n  _fireIfDirectoryChanged(info) {\n    var self = this;\n\n    if (self.stopped) {\n      return true;\n    }\n\n    var newContents = readDirectory({\n      absPath: info.absPath,\n      include: info.include,\n      exclude: info.exclude,\n      names: info.names\n    });\n\n    // If the directory has changed (including being deleted or created).\n    if (! _.isEqual(info.contents, newContents)) {\n      self._fire();\n      return true;\n    }\n\n    return false;\n  }\n\n  _startFileWatches() {\n    var self = this;\n\n    // Set up a watch for each file\n    _.each(self.watchSet.files, function (hash, absPath) {\n      if (self.stopped) {\n        return;\n      }\n\n      if (! self.justCheckOnce) {\n        self._watchFileOrDirectory(absPath);\n      }\n\n      // Check for the case where by the time we created the watch,\n      // the file had already changed from the sha we were provided.\n      self._fireIfFileChanged(absPath);\n    });\n  }\n\n  _watchFileOrDirectory(absPath) {\n    var self = this;\n\n    if (! _.has(self.watches, absPath)) {\n      self.watches[absPath] = {\n        watcher: null,\n        // Initially undefined (instead of null) to indicate we have never\n        // called files.stat on this file before.\n        lastStat: undefined\n      };\n    }\n\n    var entry = self.watches[absPath];\n    if (entry.watcher) {\n      // Already watching this path.\n      return;\n    }\n\n    if (files.exists(absPath)) {\n      if (self._mustNotExist(absPath)) {\n        self._fire();\n        return;\n      }\n\n      var onWatchEvent = self._makeWatchEventCallback(absPath);\n      entry.watcher = pathwatcher.watch(absPath, onWatchEvent);\n\n      // If we successfully created the watcher, invoke the callback\n      // immediately, so that we examine this file at least once.\n      onWatchEvent();\n\n    } else {\n      if (self._mustBeAFile(absPath)) {\n        self._fire();\n        return;\n      }\n\n      var parentDir = files.pathDirname(absPath);\n      if (parentDir === absPath) {\n        throw new Error(\"Unable to watch parent directory of \" + absPath);\n      }\n\n      self._watchFileOrDirectory(parentDir);\n    }\n  }\n\n  _makeWatchEventCallback(absPath) {\n    var self = this;\n\n    // Sometimes we receive a rapid succession of change events, perhaps\n    // because several files were modified at once (e.g. by git reset\n    // --hard), or a file was deleted and then recreated by an editor like\n    // Vim. Because detecting changes can be costly, and because we care\n    // most about the settled state of the file system, we use the\n    // funcUtils.coalesce helper to delay calls to the callback by 100ms,\n    // canceling any additional calls if they happen within that window of\n    // time, so that a rapid succession of calls will tend to trigger only\n    // one inspection of the file system.\n    return coalesce(100, function onWatchEvent() {\n      if (self.stopped) {\n        return;\n      }\n\n      // This helper method will call self._fire() if the old and new stat\n      // objects have different types (missing, file, or directory), so we\n      // can assume they have the same type for the rest of this method.\n      var stat = self._updateStatForWatch(absPath);\n      if (self.stopped) {\n        return;\n      }\n\n      if (stat === null || stat.isFile()) {\n        if (_.has(self.watchSet.files, absPath)) {\n          self._fireIfFileChanged(absPath);\n          // XXX #3335 We probably should check again in a second, due to low\n          // filesystem modtime resolution.\n        }\n\n      } else if (stat.isDirectory()) {\n        try {\n          var dirFiles = files.readdir(absPath);\n        } catch (err) {\n          if (err.code === \"ENOENT\" ||\n              err.code === \"ENOTDIR\") {\n            // The directory was removed or changed type since we called\n            // self._updateStatForWatch, so we fire unconditionally.\n            self._fire();\n            return;\n          }\n          throw err;\n        }\n\n        _.each(dirFiles, function(file) {\n          var fullPath = files.pathJoin(absPath, file);\n\n          // Recursively watch new files, if we ever previously tried to\n          // watch them. Recall that when we attempt to watch a\n          // non-existent file, we actually watch the closest enclosing\n          // directory that exists, so once the file (and/or any\n          // intermediate directories) are created, we begin watching\n          // those directories in response to change events fired for\n          // directories we're already watching.\n          if (_.has(self.watches, fullPath)) {\n            self._watchFileOrDirectory(fullPath);\n          }\n        });\n\n        // If self.watchSet.directories contains any entries for the\n        // directory we are examining, call self._fireIfDirectoryChanged.\n        _.some(self.watchSet.directories, function(info) {\n          return self.stopped ||\n            (absPath === info.absPath &&\n             self._fireIfDirectoryChanged(info, true));\n          // XXX #3335 We probably should check again in a second, due to low\n          // filesystem modtime resolution.\n        });\n      }\n    });\n  }\n\n  // XXX Erk! This is wrong!  A null entry in a WatchSet means \"is not a file\",\n  // not \"does not exist\"; if you look at readAndWatchFileWithHash, \"a directory\n  // where a file was expected\" leads to the entry being null.  Right now this\n  // leads to infinite watcher refresh loops if something that needs to be a\n  // directory ends up as a file.  This all needs to be changed so that null\n  // means \"not a file\" again. A simple way to reproduce is to run\n  //    $ meteor --settings /tmp\n  // See #3854.\n  _mustNotExist(absPath) {\n    var wsFiles = this.watchSet.files;\n    if (_.has(wsFiles, absPath)) {\n      return wsFiles[absPath] === null;\n    }\n    return false;\n  }\n\n  _mustBeAFile(absPath) {\n    var wsFiles = this.watchSet.files;\n    if (_.has(wsFiles, absPath)) {\n      return _.isString(wsFiles[absPath]);\n    }\n    return false;\n  }\n\n  _updateStatForWatch(absPath) {\n    var self = this;\n    var entry = self.watches[absPath];\n    var lastStat = entry.lastStat;\n\n    try {\n      var stat = files.stat(absPath);\n    } catch (err) {\n      stat = null;\n      if (err.code !== \"ENOENT\") {\n        throw err;\n      }\n    }\n\n    var mustNotExist = self._mustNotExist(absPath);\n    var mustBeAFile = self._mustBeAFile(absPath);\n\n    if (stat && lastStat === undefined) {\n      // We have not checked for this file before, so our expectations are\n      // somewhat relaxed (namely, we don't care about lastStat), but\n      // self._fire() might still need to be called if self.watchSet.files\n      // has conflicting expectations.\n      if (stat.isFile()) {\n        if (mustNotExist) {\n          self._fire();\n        }\n      } else if (stat.isDirectory()) {\n        if (mustNotExist || mustBeAFile) {\n          self._fire();\n        }\n      } else {\n        // Neither a file nor a directory, so treat as non-existent.\n        stat = null;\n        if (mustBeAFile) {\n          self._fire();\n        }\n      }\n\n      // We have not checked for this file before, so just record the new\n      // stat object.\n      entry.lastStat = stat;\n\n    } else if (stat && stat.isFile()) {\n      entry.lastStat = stat;\n      if (! lastStat || ! lastStat.isFile()) {\n        self._fire();\n      }\n\n    } else if (stat && stat.isDirectory()) {\n      entry.lastStat = stat;\n      if (! lastStat || ! lastStat.isDirectory()) {\n        self._fire();\n      }\n\n    } else {\n      entry.lastStat = stat = null;\n      if (lastStat) {\n        self._fire();\n      }\n    }\n\n    return stat;\n  }\n\n  _checkDirectories() {\n    var self = this;\n\n    if (self.stopped) {\n      return;\n    }\n\n    _.each(self.watchSet.directories, function (info) {\n      if (self.stopped) {\n        return;\n      }\n\n      if (! self.justCheckOnce) {\n        self._watchFileOrDirectory(info.absPath);\n      }\n\n      // Check for the case where by the time we created the watch, the\n      // directory has already changed.\n      self._fireIfDirectoryChanged(info);\n    });\n  }\n\n  _fire() {\n    var self = this;\n\n    if (self.stopped) {\n      return;\n    }\n\n    self.stop();\n    self.onChange();\n  }\n\n  stop() {\n    var self = this;\n    self.stopped = true;\n\n    // Clean up file watches\n    _.each(self.watches, function (entry) {\n      if (entry.watcher) {\n        entry.watcher.close();\n        entry.watcher = null;\n      }\n    });\n    self.watches = {};\n  }\n}\n\n// Given a WatchSet, returns true if it currently describes the state of the\n// disk.\nexport function isUpToDate(watchSet) {\n  return Profile.time('watch.isUpToDate', () => {\n    var upToDate = true;\n    var watcher = new Watcher({\n      watchSet: watchSet,\n      onChange: function () {\n        upToDate = false;\n      },\n      // internal flag which prevents us from starting watches and timers that\n      // we're about to cancel anyway\n      _justCheckOnce: true\n    });\n    watcher.stop();\n    return upToDate;\n  });\n}\n\n// Options should have absPath/include/exclude/names.\nexport function readAndWatchDirectory(watchSet, options) {\n  var contents = readDirectory(options);\n  watchSet.addDirectory(_.extend({contents: contents}, options));\n  return contents;\n}\n\n// Calculating the sha hash can be expensive for large files.  By\n// returning the calculated hash along with the file contents, the\n// hash doesn't need to be calculated again for static files.\n//\n// We only calculate the hash if needed here, so callers must not\n// *rely* on the hash being returned; merely that if the hash is\n// present, it is the correct hash of the contents.\nexport function readAndWatchFileWithHash(watchSet, absPath) {\n  var contents = readFile(absPath);\n  var hash = null;\n  // Allow null watchSet, if we want to use readFile-style error handling in a\n  // context where we might not always have a WatchSet (eg, reading\n  // settings.json where we watch for \"meteor run\" but not for \"meteor deploy\").\n  if (watchSet) {\n    hash = contents === null ? null : sha1(contents);\n    watchSet.addFile(absPath, hash);\n  }\n  return {contents: contents, hash: hash};\n}\n\nexport function readAndWatchFile(watchSet, absPath) {\n  return readAndWatchFileWithHash(watchSet, absPath).contents;\n}\n"
  },
  {
    "path": "tools/index.js",
    "content": "if (! require('./cli/dev-bundle-bin-commands.js').process) {\n  // Set up the Babel transpiler\n  require('./tool-env/install-babel.js');\n\n  // Run the Meteor command line tool\n  require('./cli/main.js');\n}\n"
  },
  {
    "path": "tools/inspector.js",
    "content": "var assert = require(\"assert\");\nvar net = require(\"net\");\nvar inspector = require(\"node-inspector\");\nvar spawn = require(\"child_process\").spawn;\nvar _ = require(\"underscore\");\nvar chalk = require(\"chalk\");\nvar EOL = require(\"os\").EOL;\nvar Protocol = require(\"_debugger\").Protocol;\nvar debugEntries = [];\n\n// There can be only one debugger attached to a process at a time, and\n// detaching can leave the child process in a weird state for future\n// debugging, so the code that attaches to the child process must also\n// serve as a proxy for connections from actual debugger clients like\n// node-inspector.\n\n// This proxying system requires the child process to be invoked with\n// --debug-brk=<port> where <port> is not the same as debugPort, so that\n// we can proxy data between <port> and debugPort, as if the child process\n// were listening on debugPort (as it did before this commit).\n\n// The first time the server starts, the --debug-brk behavior of pausing\n// at the first line of the program is helpful so that the user can set\n// breakpoints. When the server restarts, however, that behavior is more\n// confusing than helpful, especially since the server can restart\n// multiple times in quick succession if the user edits and saves a file\n// multiple times. To avoid this confusion, we use the proxy to send a\n// continue command to resume execution automatically after restart.\n\n// Itercepting debugger requests, responses, events, etc. has the\n// additional benefit of allowing us to print helpful information to the\n// console, like notifying the developer that the debugger hit a\n// breakpoint, so that there is less confusion when the app is not\n// responding to requests.\n\nfunction start(debugPort, entryPoint) {\n  debugPort = +(debugPort || 5858);\n\n  var entry = debugEntries[debugPort];\n  if (entry instanceof DebugEntry) {\n    return entry.attach;\n  }\n\n  debugEntries[debugPort] = entry =\n    new DebugEntry(debugPort, entryPoint);\n\n  return entry.attach;\n}\n\nfunction DebugEntry(debugPort, entryPoint) {\n  assert.ok(this instanceof DebugEntry);\n\n  this.debugPort = debugPort;\n  this.entryPoint = entryPoint;\n  this.incomingSink = new BackloggedStreamWriter;\n  this.outgoingSink = new BackloggedStreamWriter;\n  this.inspectorProcess = null;\n  this.interceptServer = null;\n  this.debugConnection = null;\n  this.connectCount = 0;\n  this.attach = this.attach.bind(this);\n\n  // We create a connection to whatever port the child process says it's\n  // listening on, so this port is purely advisory.\n  this.attach.suggestedDebugBrkPort = debugPort + 101;\n}\n\nvar DEp = DebugEntry.prototype;\n\nDEp.attach = function attach(child) {\n  this.incomingSink.clear();\n  this.outgoingSink.clear();\n\n  this.startInterceptServer();\n  this.startInspector();\n  this.connectToChildProcess(child);\n};\n\n// The intercept server listens for connections and data from\n// node-inspector (on debugPort) and mediates communication between\n// node-inspector and the child process that we're debugging, so that we\n// can inject our own commands (e.g. \"continue\") and print helpful\n// information to the console when the debugger hits breakpoints. Note\n// that the intercept server survives server restarts, just like\n// node-inspector.\nDEp.startInterceptServer = function startInterceptServer() {\n  var self = this;\n  if (self.interceptServer) {\n    return;\n  }\n\n  self.interceptServer = net.createServer(function(socket) {\n    self.outgoingSink.setTarget(socket);\n    socket.on(\"data\", function(buffer) {\n      self.incomingSink.write(buffer);\n    });\n  }).on(\"error\", function(err) {\n    self.interceptServer = null;\n  }).listen(self.debugPort);\n};\n\nDEp.startInspector = function startInspector() {\n  var self = this;\n  if (self.inspectorProcess) {\n    return;\n  }\n\n  // Port 8080 is the default port that node-inspector uses for its web\n  // server, and port 5858 is the default port that node listens on when\n  // it receives the --debug or --debug-brk flags. Developers familiar\n  // with node-inspector may have http://localhost:8080/debug?port=5858\n  // saved in their browser history already, so let's stick with these\n  // conventions in the default case (unless of course the developer runs\n  // `meteor debug --debug-port <some other port>`).\n  var debugPort = self.debugPort;\n  var webPort = 8080 + debugPort - 5858;\n\n  var proc = spawn(process.execPath, [\n    require.resolve(\"node-inspector/bin/inspector\"),\n    \"--web-port\", \"\" + webPort,\n    \"--debug-port\", \"\" + debugPort\n  ]);\n\n  proc.url = inspector.buildInspectorUrl(\"localhost\", webPort, debugPort);\n\n  // Forward error output to process.stderr, but silence normal output.\n  // proc.stdout.pipe(process.stdout);\n  proc.stderr.pipe(process.stderr);\n\n  proc.on(\"exit\", function(code) {\n    // Restart the process if it died without us explicitly stopping it.\n    if (self.inspectorProcess === proc) {\n      self.inspectorProcess = null;\n      self.startInspector();\n    }\n  });\n\n  self.inspectorProcess = proc;\n};\n\nDEp.connectToChildProcess = function connectToChildProcess(child) {\n  var self = this;\n\n  // Wait for the child process to tell us it's listening on a certain\n  // port (not debugPort!), and create a connection to that port so that\n  // the child process can communicate with node-inspector.\n  child.stderr.on(\"data\", function onData(buffer) {\n    var match = /debugger listening on port (\\d+)/\n      .exec(buffer.toString(\"utf8\"));\n    if (match) {\n      child.stderr.removeListener(\"data\", onData);\n      connect(+match[1]);\n    }\n  });\n\n  function connect(port) {\n    disconnect();\n\n    self.debugConnection = net.createConnection(port);\n    self.debugConnection.setEncoding(\"utf8\");\n    self.debugConnection.on(\"data\", function(buffer) {\n      protocol.execute(buffer);\n      self.outgoingSink.write(buffer);\n    }).on(\"error\", disconnect);\n\n    var protocol = new Protocol;\n    protocol.onResponse = function onResponse(res) {\n      // Listen for break events so that we can either skip them or print\n      // information to the console about them.\n      if (res.body.type === \"event\" &&\n          res.body.event === \"break\") {\n        var scriptName = res.body.body.script.name;\n        var lineNumber = res.body.body.sourceLine + 1;\n\n        if (self.connectCount > 1 &&\n            scriptName === self.entryPoint) {\n          // If we've restarted the server at least once and the break\n          // event occurred in the entry point file (typically\n          // .meteor/local/build/main.js), send a continue command to skip\n          // this breakpoint automatically, so that the user does not have\n          // to keep manually continuing the debugger every time the\n          // server restarts.\n          sendContinue();\n\n        } else {\n          // Give some indication in the console that server execution has\n          // stopped at a breakpoint.\n          process.stdout.write(\n            \"Paused at \" + scriptName + \":\" + lineNumber + \"\\n\"\n          );\n        }\n      }\n    };\n\n    var sentContinue = false;\n    function sendContinue() {\n      if (! sentContinue) {\n        sentContinue = true;\n        self.incomingSink.write(protocol.serialize({\n          command: \"continue\"\n        }));\n      }\n    }\n\n    if (self.connectCount++ === 0) {\n      process.stdout.write(banner(self.debugPort));\n    } else {\n      // Sometimes (for no good reason) the protocol.onResponse handler\n      // never receives a break event at the very beginning of the\n      // program. This timeout races against that break event to make sure\n      // we send exactly one continue command.\n      setTimeout(sendContinue, 500);\n    }\n\n    self.incomingSink.setTarget(self.debugConnection);\n  }\n\n  function disconnect() {\n    if (self.debugConnection) {\n      self.debugConnection.end();\n      self.debugConnection = null;\n    }\n  }\n};\n\nDEp.stop = function stop() {\n  var proc = this.inspectorProcess;\n  if (proc && proc.kill) {\n    this.inspectorProcess = null;\n    proc.kill();\n  }\n\n  if (this.interceptServer) {\n    this.interceptServer.close();\n    this.interceptServer = null;\n  }\n\n  if (this.debugConnection) {\n    this.debugConnection.end();\n    this.debugConnection = null;\n  }\n};\n\n// A simple wrapper object for writable streams that keeps a backlog of\n// data written before the stream is available, and writes that data to the\n// stream when the stream becomes available.\nfunction BackloggedStreamWriter(target) {\n  assert.ok(this instanceof BackloggedStreamWriter);\n  this.backlog = [];\n  this.target = target || null;\n}\n\nvar BSWp = BackloggedStreamWriter.prototype;\n\nBSWp.write = function write(buffer) {\n  if (this.target) {\n    this.target.write(buffer);\n  } else {\n    this.backlog.push(buffer);\n  }\n};\n\nBSWp.setTarget = function setTarget(target) {\n  if (this.target &&\n      this.target !== target) {\n    this.clear();\n  }\n\n  this.target = target;\n\n  if (target) {\n    var clear = this.clear.bind(this);\n    target.on(\"close\", clear);\n    target.on(\"end\", clear);\n\n    if (this.backlog.length > 0) {\n      _.each(this.backlog.splice(0), this.write, this);\n    }\n  }\n\n  return target;\n};\n\nBSWp.clear = function clear() {\n  this.backlog.length = 0;\n  this.target = null;\n};\n\nfunction banner(debugPort) {\n  debugPort = +(debugPort || 5858);\n  var entry = debugEntries[debugPort];\n  var proc = entry && entry.inspectorProcess;\n  assert.strictEqual(typeof proc.url, \"string\");\n\n  return [\n    \"\",\n    chalk.green([\n      \"Your application is now paused and ready for debugging!\",\n      \"\",\n      \"To debug the server process using a graphical debugging interface, \",\n      \"visit this URL in your web browser:\"\n    ].join(EOL)),\n    chalk.cyan(proc.url),\n    EOL\n  ].join(EOL);\n}\n\nfunction stop(debugPort) {\n  debugPort = +(debugPort || 5858);\n  var entry = debugEntries[debugPort];\n  delete debugEntries[debugPort];\n  if (entry) {\n    entry.stop();\n  }\n}\n\nrequire('./tool-env/cleanup.js').onExit(function killAll() {\n  for (var debugPort in debugEntries) {\n    stop(debugPort);\n  }\n  debugEntries.length = 0;\n});\n\nexports.start = start;\nexports.stop = stop;\n"
  },
  {
    "path": "tools/isobuild/README.md",
    "content": "# Isobuild\n\nIsobuild is the build system used by the Meteor Tool. See the\n[high level description](https://www.meteor.com/isobuild) for more.\n\n## Terms\n\nThe terms Isobuild operates on often have two names: internal names and public\nconcepts.\n\n- `packageSource` - an abstract representation of a package/app source with metadata\n- `isopack` - a compiled version of a package/app\n- `unibuild` - a part of an isopack for a specific target (browser, server,\n  tool, etc)\n- `isopackCache` - an abstract representation of cached isopacks on disk\n- `build plugin` - a part of an isopack that plugs into the build process\n- `linked file` - a wrapped file by linker\n- `project context` - an object that has lots of metadata, mostly about the\n  packages, catalogs, it is responsible for catalogs refreshes, pulling the\n  relevant packages, resolving dependencies, etc.\n- `js-analyze` - some piece of software that implements a set of JS parser\n  features\n\n## How an app is built\n\nThe app is built by Bundler, \"bundling\" is the most high-level process that\nhappens to the application code once it is loaded. Here is a more detailed\ntime-line:\n\n1. Create the \"Project Context\" out of the app directory. Project Context makes\n   sure we know what package versions we need to use and prepares them for us.\n2. The Bundler is given the Project Context and now it is Bundler's job to\n   create the Package Source for the app, compile app's parts as they were\n   packages, and then put everything together.\n3. The Builder is ran to write the output files to disk.\n4. While all the building was done, a WatchSet of the whole app is collected.\n   It's returned to the caller. Also, files `star.json` and `program.json` are\n   written.\n\n### Compiler\n\nTakes care of compiling an individual package and returning an Isopack.\n\nCompiler has a dependency on Bundler, as it needs to bundle the build plugins\nused to compile the input package source.\n\nCompiler runs various compiler batch plugins and \"source handlers\" (the\nold-style build plugins) on the source. If there is a need to build any build\nplugins to use them, it would recursively build those.\n\n### Bundler\n\nBuilds an individual app or a build plugin (that appears to be just an app that\nis run in the context of the build).\n\nBundler introduces additional terms:\n\n- `JsImage` - is a representation of a built App or a build plugin.\n- `ClientTarget` and `ServerTarget` are representations of two separate types of\n  \"programs\" in a built App.\n\nThere are commonly two important entry-points for Bundler:\n\n- `buildJsImage` - build a build plugin\n- `bundle` - the main function to bundle the application from a Project Context\n\nFor the actual compilation, Bundler often calls into Compiler. Other tasks that\nBundler performs include:\n\n- initiate a Package Source for the app\n- run linters on the app\n- run the application files through Linker in a special mode that allows the use\nof global variables\n- add a special file called \"global-imports\" that explicitly puts all used\n  packages' symbols into the global namespace\n- write compiled files to the right location with multiple Builder's\n- write a `star.json` file with metadata for the \"star\" (the app) and a\n  `program.json` file for every target\n\n### Builder\n\nManages the files written to the filesystem.\n\nSince the rebuilds of an app is something that occurs over and over again (in\nthe development cycle), it makes sense to reuse the information about the files\nthat didn't change. Builder tries not to spend too much time writing files that\nremained the same over and over again.\n\nIt is even OK to do when an app process serving these files is still running, on\nUnix, the process can retain files by their inodes (not by file paths) and then\nonce the process release them, the FS will clean up unlinked files.\n\n### Linker\n\nA Meteor-specific transform. Wraps every file into a closure, creates \"package\nlocal variables\" and sets up the \"global imports\" to look like\n`var Minimongo = Package.minimongo.Minimongo;`.\n\nThe process of linking is Meteor's substitute to other module loading solutions\nlike `r.js` or `require.js`, or ES2015-style modules. Eventually, Meteor wants\nto transition to ES2015 modules for everything.\n\nThe way linker works for individual modules (packages in Meteor's case), is\nseveral things. Roughly, it can be separated into two phases \"prelink\" and\n\"link\" (both combined define \"fullLink\").\n\nPrelink is something that can be done with a package in Isolation:\n\n- create a closure around each file\n- concatenate all files\n- add comments of the original line number, file-headers - the metadata to be\nread by humans when viewed in a browser that doesn't support source-maps\n- run a JS parser and figure out all the global variables used, out of those,\n  pick the ones that are assigned in the package and form \"Package-level\" global\n  variables by adding a `var` for them.\n\nIn the second part \"link\", the linker caller already knows what versions of\nlinked module's dependencies are and what exports they provide for the module:\n\n- create import strings for globals that come from dependencies' exports:\n  `var Minimongo = Package.minimongo.Minimongo;`, if the module references\n  `Minimongo`.\n\nHistorically, Meteor used to ship \"prelinked\" files in packages and then \"link\"\nthem in the bundle time. Starting with Meteor 1.2 and Batch Plugins API, Meteor\ndistributes source files, so they are \"fullLinked\" in bunlde time together.\n\n## Batch Build Plugins\n\nIn Meteor 1.2, the new Build Plugin APIs have been introduced. You can read more\nabout them here: [wiki](https://github.com/meteor/meteor/wiki/Build-Plugins-API).\n\nThe Build Plugins APIs register compilers, minifiers and linters. All of them\nare applied on different stages of the build process. Compilers are used by\nCompiler and Isopack methods. Linters are ran per Unibuild in\n`compiler.lint` and for the App in Bundler. Minifiers are ran by Bundler on its\nlast stage.\n\nThe previous generation of build plugins (File Handlers) used to run on package\npublish (i.e., built before published). In the world of Build Plugins, they are\ncompiled as part of the bundle process.\n\n## WatchSet\n\nWatchSets are collected throughout the build process. The idea is: the WatchSet\nrepresents all the files that participate in the build process and also this\nlist is used to notice any changes for rebuilds.\n\nWorking on the Isobuild codebase, it is important to understand the common usage\npattern: the common WatchSet is passed down to functions as an argument. The\nfunctions on the bottom, add files to the WatchSet, mutating the passed\nargument.\n\nIn the end, the final WatchSet that contains merged information about every used\nfile, is returned to the caller.\n"
  },
  {
    "path": "tools/isobuild/build-plugin.js",
    "content": "var archinfo = require('../utils/archinfo.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar files = require('../fs/files.js');\nvar _ = require('underscore');\nimport utils from '../utils/utils.js';\n\nlet nextId = 1;\n\nexports.SourceProcessor = function (options) {\n  var self = this;\n  self.isopack = options.isopack;\n  self.extensions = (options.extensions || []).slice();\n  self.filenames = (options.filenames || []).slice();\n  self.archMatching = options.archMatching;\n  self.isTemplate = !! options.isTemplate;\n  self.factoryFunction = options.factoryFunction;\n  self.methodName = options.methodName;\n  self.id = `${ options.isopack.displayName() }#${ nextId++ }`;\n  self.userPlugin = null;\n};\n_.extend(exports.SourceProcessor.prototype, {\n  // Call the user's factory function to get the actual build plugin object.\n  // Note that we're supposed to have one userPlugin per project, so this\n  // assumes that each Isopack object is specific to a project.  We don't run\n  // this immediately on evaluating Plugin.registerCompiler; we instead wait\n  // until the whole plugin file has been evaluated (so that it can use things\n  // defined later in the file).\n  instantiatePlugin: function () {\n    var self = this;\n    buildmessage.assertInCapture();\n    if (self.userPlugin) {\n      throw Error(\"Called instantiatePlugin twice?\");\n    }\n    buildmessage.enterJob(\n      `running ${self.methodName} callback in package ` +\n        self.isopack.displayName(),\n      () => {\n        try {\n          self.userPlugin = buildmessage.markBoundary(self.factoryFunction)\n            .call(null);\n          // If we have a disk cache directory and the plugin wants it, use it.\n          if (self.isopack.pluginCacheDir &&\n              self.userPlugin.setDiskCacheDirectory) {\n            buildmessage.markBoundary(function () {\n              self.userPlugin.setDiskCacheDirectory(\n                files.convertToOSPath(self.isopack.pluginCacheDir)\n              );\n            })();\n          }\n        } catch (e) {\n          buildmessage.exception(e);\n        }\n      }\n    );\n  },\n  relevantForArch: function (arch) {\n    var self = this;\n    return ! self.archMatching || archinfo.matches(arch, self.archMatching);\n  }\n});\n\n// Represents a set of SourceProcessors available in a given package. They may\n// not have conflicting extensions or filenames.\nexport class SourceProcessorSet {\n  constructor(myPackageDisplayName, {\n    hardcodeJs,\n    singlePackage,\n    allowConflicts,\n  } = {}) {\n    // For error messages only.\n    this._myPackageDisplayName = myPackageDisplayName;\n    // If this represents the SourceProcessors *registered* by a single package\n    // (vs those *available* to a package), use different error messages.\n    this._singlePackage = singlePackage;\n    // If this is being used for *compilers*, we hardcode *.js. If it is being\n    // used for linters, we don't.\n    this._hardcodeJs = !! hardcodeJs;\n    // Multiple linters may be registered on the same extension or filename, but\n    // not compilers.\n    this._allowConflicts = !! allowConflicts;\n\n    // Map from extension -> [SourceProcessor]\n    this._byExtension = {};\n    // Map from basename -> [SourceProcessor]\n    this._byFilename = {};\n    // This is just an duplicate-free list of all SourceProcessors in\n    // byExtension or byFilename.\n    this.allSourceProcessors = [];\n    // extension -> { handler, packageDisplayName, isTemplate, archMatching }\n    this._legacyHandlers = {};\n  }\n\n  _conflictError(package1, package2, conflict) {\n    if (this._singlePackage) {\n      buildmessage.error(\n        `plugins in package ${ this._myPackageDisplayName } define multiple ` +\n          `handlers for ${ conflict }`);\n    } else {\n      buildmessage.error(\n        `conflict: two packages included in ${ this._myPackageDisplayName } ` +\n          `(${ package1 } and ${ package2 }) are both trying to handle ` +\n          conflict);\n    }\n  }\n\n  addSourceProcessor(sp) {\n    buildmessage.assertInJob();\n    this._addSourceProcessorHelper(sp, sp.extensions, this._byExtension, '*.');\n    this._addSourceProcessorHelper(sp, sp.filenames, this._byFilename, '');\n    // If everything conflicted, then the SourceProcessors will be in\n    // allSourceProcessors but not any of the data structures, but in that case\n    // the caller should be checking for errors anyway.\n    this.allSourceProcessors.push(sp);\n  }\n  _addSourceProcessorHelper(sp, things, byThing, errorPrefix) {\n    buildmessage.assertInJob();\n\n    things.forEach((thing) => {\n      if (byThing.hasOwnProperty(thing)) {\n        if (this._allowConflicts) {\n          byThing[thing].push(sp);\n        } else {\n          this._conflictError(sp.isopack.displayName(),\n                              byThing[thing][0].isopack.displayName(),\n                              errorPrefix + thing);\n          // recover by ignoring this one\n        }\n      } else {\n        byThing[thing] = [sp];\n      }\n    });\n  }\n\n  addLegacyHandler({ extension, handler, packageDisplayName, isTemplate,\n                     archMatching }) {\n    if (this._allowConflicts) {\n      throw Error(\"linters have no legacy handlers\");\n    }\n\n    if (this._byExtension.hasOwnProperty(extension)) {\n      this._conflictError(packageDisplayName,\n                          this._byExtension[extension].isopack.displayName(),\n                          '*.' + extension);\n      // recover by ignoring\n      return;\n    }\n    if (this._legacyHandlers.hasOwnProperty(extension)) {\n      this._conflictError(packageDisplayName,\n                          this._legacyHandlers[extension].packageDisplayName,\n                          '*.' + extension);\n      // recover by ignoring\n      return;\n    }\n    this._legacyHandlers[extension] =\n      {handler, packageDisplayName, isTemplate, archMatching};\n  }\n\n  // Adds all the source processors (and legacy handlers) from the other set to\n  // this one. Logs buildmessage errors on conflict.  Ignores packageDisplayName\n  // and singlePackage.  If arch is set, skips SourceProcessors that\n  // don't match it.\n  merge(otherSet, options = {}) {\n    const { arch } = options;\n    buildmessage.assertInJob();\n    otherSet.allSourceProcessors.forEach((sourceProcessor) => {\n      if (! arch || sourceProcessor.relevantForArch(arch)) {\n        this.addSourceProcessor(sourceProcessor);\n      }\n    });\n    _.each(otherSet._legacyHandlers, (info, extension) => {\n      const { handler, packageDisplayName, isTemplate, archMatching } = info;\n      this.addLegacyHandler(\n        {extension, handler, packageDisplayName, isTemplate, archMatching});\n    });\n  }\n\n  // Note: Only returns SourceProcessors, not legacy handlers.\n  getByExtension(extension) {\n    if (this._allowConflicts) {\n      throw Error(\"Can't call getByExtension for linters\");\n    }\n\n    if (this._byExtension.hasOwnProperty(extension)) {\n      return this._byExtension[extension][0];\n    }\n    return null;\n  }\n\n  // Note: Only returns SourceProcessors, not legacy handlers.\n  getByFilename(filename) {\n    if (this._allowConflicts) {\n      throw Error(\"Can't call getByFilename for linters\");\n    }\n\n    if (this._byFilename.hasOwnProperty(filename)) {\n      return this._byFilename[filename][0];\n    }\n    return null;\n  }\n\n  // filename, arch -> SourceClassification\n  classifyFilename(filename, arch) {\n    // First check to see if a plugin registered for this exact filename.\n    if (this._byFilename.hasOwnProperty(filename)) {\n      return new SourceClassification('filename', {\n        arch,\n        sourceProcessors: this._byFilename[filename].slice()\n      });\n    }\n\n    // Now check to see if a plugin registered for an extension. We prefer\n    // longer extensions.\n    const parts = filename.split('.');\n    // don't use iteration functions, so we can return (and start at #1)\n    for (let i = 1; i < parts.length; i++) {\n      const extension = parts.slice(i).join('.');\n\n      if (this._byExtension.hasOwnProperty(extension)) {\n        return new SourceClassification('extension', {\n          arch,\n          extension,\n          sourceProcessors: this._byExtension[extension]\n        });\n      }\n\n      if (this._hardcodeJs && extension === 'js') {\n        // If there is no special sourceProcessor for handling a .js file,\n        // we can still classify it as extension/js, only without any\n        // source processors. #HardcodeJs\n        return new SourceClassification('extension', {\n          extension,\n          usesDefaultSourceProcessor: true\n        });\n      }\n\n      if (this._legacyHandlers.hasOwnProperty(extension)) {\n        const legacy = this._legacyHandlers[extension];\n        if (legacy.archMatching &&\n            ! archinfo.matches(arch, legacy.archMatching)) {\n          return new SourceClassification('wrong-arch');\n        }\n        return new SourceClassification('legacy-handler', {\n          extension,\n          legacyHandler: legacy.handler,\n          legacyIsTemplate: legacy.isTemplate\n        });\n      }\n    }\n\n    // Nothing matches; it must be a static asset (or a non-linted file).\n    return new SourceClassification('unmatched');\n  }\n\n  isEmpty() {\n    return _.isEmpty(this._byFilename) && _.isEmpty(this._byExtension) &&\n      _.isEmpty(this._legacyHandlers);\n  }\n\n  // Returns an options object suitable for passing to\n  // `watch.readAndWatchDirectory` to find source files processed by this\n  // SourceProcessorSet.\n  appReadDirectoryOptions(arch) {\n    const include = [];\n    const names = [];\n    let addedJs = false;\n\n    function addExtension(ext) {\n      include.push(new RegExp('\\\\.' + utils.quotemeta(ext) + '$'));\n      if (ext === 'js') {\n        addedJs = true;\n      }\n    }\n\n    _.each(this._byExtension, (sourceProcessors, ext) => {\n      if (sourceProcessors.some(sp => sp.relevantForArch(arch))) {\n        addExtension(ext);\n      }\n    });\n    Object.keys(this._legacyHandlers).forEach(addExtension);\n\n    if (this._hardcodeJs && ! addedJs) {\n      // If there is no sourceProcessor for handling .js files, we still\n      // want to make sure they get picked up when we're reading the\n      // contents of app directories. #HardcodeJs\n      addExtension('js');\n    }\n\n    _.each(this._byFilename, (sourceProcessors, filename) => {\n      if (sourceProcessors.some(sp => sp.relevantForArch(arch))) {\n        names.push(filename);\n      }\n    });\n    return {include, names, exclude: []};\n  }\n}\n\nclass SourceClassification {\n  constructor(type, {\n    legacyHandler,\n    extension,\n    sourceProcessors,\n    usesDefaultSourceProcessor,\n    legacyIsTemplate,\n    arch,\n  } = {}) {\n    const knownTypes = ['extension', 'filename', 'legacy-handler', 'wrong-arch',\n                        'unmatched'];\n    if (knownTypes.indexOf(type) === -1) {\n      throw Error(`Unknown SourceClassification type ${ type }`);\n    }\n    // This is the only thing we can write to `this` before checking for\n    // wrong-arch.\n    this.type = type;\n\n    if (type === 'extension' || type === 'filename') {\n      if (sourceProcessors) {\n        if (! arch) {\n          throw Error(\"need to filter based on arch!\");\n        }\n\n        // If there's a SourceProcessor (or legacy handler) registered for this\n        // file but not for this arch, we want to ignore it instead of\n        // processing it or treating it as a static asset. (Note that prior to\n        // the batch-plugins project, files added in a package with\n        // `api.addFiles('foo.bar')` where *.bar is a web-specific legacy\n        // handler (eg) would end up adding 'foo.bar' as a static asset on\n        // non-web programs, which was unintended. This didn't happen in apps\n        // because initFromAppDir's getFiles never added them.)\n        const filteredSourceProcessors = sourceProcessors.filter(\n          (sourceProcessor) => sourceProcessor.relevantForArch(arch)\n        );\n        if (! filteredSourceProcessors.length) {\n          // Wrong architecture! Rewrite this.type and return.  (Note that we\n          // haven't written anything else to `this` so far.)\n          this.type = 'wrong-arch';\n          return;\n        }\n\n        this.sourceProcessors = filteredSourceProcessors;\n      } else if (!(type === 'extension' && extension === 'js')) {\n        // 'extension' and 'filename' classifications need to have at least one\n        // SourceProcessor, unless it's the #HardcodeJs special case.\n        throw Error(`missing sourceProcessors for ${ type }!`);\n      }\n    }\n\n    if (type === 'legacy-handler') {\n      if (! legacyHandler) {\n        throw Error('SourceClassification needs legacyHandler!');\n      }\n      if (legacyIsTemplate === undefined) {\n        throw Error('SourceClassification needs legacyIsTemplate!');\n      }\n      this.legacyHandler = legacyHandler;\n      this.legacyIsTemplate = legacyIsTemplate;\n    }\n\n    if (type === 'extension' || type === 'legacy-handler') {\n      if (! extension) {\n        throw Error('extension SourceClassification needs extension!');\n      }\n      this.extension = extension;\n    }\n\n    if (usesDefaultSourceProcessor) {\n      if (this.extension !== 'js' &&\n          this.extension !== 'css') {\n        // We only currently hard-code support for processing .js files\n        // when no source processor is registered (#HardcodeJs). Default\n        // support could conceivably be extended to .css files too, but\n        // anything else is almost certainly a mistake.\n        throw Error('non-JS/CSS file relying on default source processor?');\n      }\n      this.usesDefaultSourceProcessor = true;\n    } else {\n      this.usesDefaultSourceProcessor = false;\n    }\n  }\n\n  isNonLegacySource() {\n    return this.type === 'extension' || this.type === 'filename';\n  }\n}\n\n\n\n// This is the base class of the object presented to the user's plugin code.\nexport class InputFile {\n  /**\n   * @summary Returns the full contents of the file as a buffer.\n   * @memberof InputFile\n   * @returns {Buffer}\n   */\n  getContentsAsBuffer() {\n    throw new Error(\"Not Implemented\");\n  }\n\n  /**\n   * @summary Returns the name of the package or `null` if the file is not in a\n   * package.\n   * @memberof InputFile\n   * @returns {String}\n   */\n  getPackageName() {\n    throw new Error(\"Not Implemented\");\n  }\n\n  /**\n   * @summary Returns the relative path of file to the package or app root\n   * directory. The returned path always uses forward slashes.\n   * @memberof InputFile\n   * @returns {String}\n   */\n  getPathInPackage() {\n    throw new Error(\"Not Implemented\");\n  }\n\n  /**\n   * @summary Returns a hash string for the file that can be used to implement\n   * caching.\n   * @memberof InputFile\n   * @returns {String}\n   */\n  getSourceHash() {\n    throw new Error(\"Not Implemented\");\n  }\n\n  /**\n   * @summary Returns the architecture that is targeted while processing this\n   * file.\n   * @memberof InputFile\n   * @returns {String}\n   */\n  getArch() {\n    throw new Error(\"Not Implemented\");\n  }\n\n  /**\n   * @summary Returns the full contents of the file as a string.\n   * @memberof InputFile\n   * @returns {String}\n   */\n  getContentsAsString() {\n    var self = this;\n    return self.getContentsAsBuffer().toString('utf8');\n  }\n\n  /**\n   * @summary Returns the filename of the file.\n   * @memberof InputFile\n   * @returns {String}\n   */\n  getBasename() {\n    var self = this;\n    return files.pathBasename(self.getPathInPackage());\n  }\n\n  /**\n   * @summary Returns the directory path relative to the package or app root.\n   * The returned path always uses forward slashes.\n   * @memberof InputFile\n   * @returns {String}\n   */\n  getDirname() {\n    var self = this;\n    return files.pathDirname(self.getPathInPackage());\n  }\n\n  /**\n   * @summary Returns an object of file options such as those passed as the\n   *          third argument to api.addFiles.\n   * @memberof InputFile\n   * @returns {Object}\n   */\n  getFileOptions() {\n    throw new Error(\"Not Implemented\");\n  }\n\n  /**\n   * @summary Call this method to raise a compilation or linting error for the\n   * file.\n   * @param {Object} options\n   * @param {String} options.message The error message to display.\n   * @param {String} [options.sourcePath] The path to display in the error message.\n   * @param {Integer} options.line The line number to display in the error message.\n   * @param {String} options.func The function name to display in the error message.\n   * @memberof InputFile\n   */\n  error(options) {\n    var self = this;\n    var path = self.getPathInPackage();\n    var packageName = self.getPackageName();\n    if (packageName) {\n      path = \"packages/\" + packageName + \"/\" + path;\n    }\n\n    self._reportError(options.message || (\"error building \" + path), {\n      file: options.sourcePath || path,\n      line: options.line ? options.line : undefined,\n      column: options.column ? options.column : undefined,\n      func: options.func ? options.func : undefined\n    });\n  }\n\n  // Default implementation. May be overridden by subclasses.\n  _reportError(message, info) {\n    buildmessage.error(message, info);\n  }\n}\n"
  },
  {
    "path": "tools/isobuild/builder.js",
    "content": "import {WatchSet, readAndWatchFile, sha1} from '../fs/watch.js';\nimport files from '../fs/files.js';\nimport NpmDiscards from './npm-discards.js';\nimport {Profile} from '../tool-env/profile.js';\n\n// Builder is in charge of writing \"bundles\" to disk, which are\n// directory trees such as site archives, programs, and packages.  In\n// addition to writing data to files, it can copy or link in existing\n// files and directories (keeping track of them in a WatchSet in order\n// to trigger rebuilds appropriately).\n//\n// By default, Builder constructs the entire output directory from\n// scratch under a temporary name, and then moves it into place.\n// For efficient rebuilds, Builder can be given a `previousBuilder`,\n// in which case it will write files into the existing output directory\n// instead.\n//\n// On Windows (or when METEOR_DISABLE_BUILDER_IN_PLACE is set), Builder\n// always creates a new output directory under a temporary name rather than\n// using the old directory.  The reason is that we don't want rebuilding to\n// interfere with the running app, and we rely on the fact that on OS X and\n// Linux, if the process has opened a file for reading, it retains the file\n// by its inode, not path, so it is safe to write a new file to the same path\n// (or delete the file).\n//\n// Separate from that, Builder has a strategy of writing files under a temporary\n// name and then renaming them.  This is to achieve an \"atomic\" write, meaning\n// the server doesn't see a partially-written file that appears truncated.\n//\n// On Windows we copy files instead of symlinking them (see comments inline).\n\n\n// Whether to support writing files into the same directory as a previous\n// Builder on rebuild (rather than creating a new build directory and\n// moving it into place).\nconst ENABLE_IN_PLACE_BUILDER_REPLACEMENT =\n  (process.platform !== 'win32') &&\n  ! process.env.METEOR_DISABLE_BUILDER_IN_PLACE;\n\n\n// Options:\n//  - outputPath: Required. Path to the directory that will hold the\n//    bundle when building is complete. It should not exist (unless\n//    previousBuilder is passed). Its parents will be created if necessary.\n// - previousBuilder: Optional. An in-memory instance of Builder left\n// from the previous iteration. It is assumed that the previous builder\n// has completed its job successfully and its files are stored on the\n// file system in the exact layout as described in its usedAsFile data\n// structure; and the hashes of the contents correspond to the\n// writtenHashes data strcture.\nexport default class Builder {\n  constructor({outputPath, previousBuilder}) {\n    this.outputPath = outputPath;\n\n    // Paths already written to. Map from canonicalized relPath (no\n    // trailing slash) to true for a file, or false for a directory.\n    this.usedAsFile = { '': false, '.': false };\n    this.previousUsedAsFile = {};\n\n    this.writtenHashes = {};\n    this.previousWrittenHashes = {};\n\n    // foo/bar => foo/.build1234.bar\n    // Should we include a random number? The advantage is that multiple\n    // builds can run in parallel. The disadvantage is that stale build\n    // files hang around forever. For now, go with the former.\n    const nonce = Math.floor(Math.random() * 999999);\n    this.buildPath = files.pathJoin(files.pathDirname(this.outputPath),\n                                    '.build' + nonce + \".\" +\n                                    files.pathBasename(this.outputPath));\n\n    let resetBuildPath = true;\n\n    // If we have a previous builder and we are allowed to re-use it,\n    // let's keep all the older files on the file-system and replace\n    // only outdated ones + write the new files in the same path\n    if (previousBuilder && ENABLE_IN_PLACE_BUILDER_REPLACEMENT) {\n      if (previousBuilder.outputPath !== outputPath) {\n        throw new Error(\n          `previousBuilder option can only be set to a builder with the same output path.\nPrevious builder: ${previousBuilder.outputPath}, this builder: ${outputPath}`\n        );\n      }\n\n      if (files.exists(previousBuilder.outputPath)) {\n        // write files in-place in the output directory of the previous builder\n        this.buildPath = previousBuilder.outputPath;\n\n        this.previousWrittenHashes = previousBuilder.writtenHashes;\n        this.previousUsedAsFile = previousBuilder.usedAsFile;\n\n        resetBuildPath = false;\n      } else {\n        resetBuildPath = true;\n      }\n    }\n\n    // Build the output from scratch\n    if (resetBuildPath) {\n      files.rm_recursive(this.buildPath);\n      files.mkdir_p(this.buildPath, 0o755);\n    }\n\n    this.watchSet = new WatchSet();\n\n    // XXX cleaner error handling. don't make the humans read an\n    // exception (and, make suitable for use in automated systems)\n  }\n\n  // Like mkdir_p, but records in self.usedAsFile that we have created\n  // the directories, and takes a path relative to the bundle\n  // root. Throws an exception on failure.\n  _ensureDirectory(relPath) {\n    const parts = files.pathNormalize(relPath).split(files.pathSep);\n    if (parts.length > 1 && parts[parts.length - 1] === '') {\n      // remove trailing slash\n      parts.pop();\n    }\n\n    const partsSoFar = [];\n    parts.forEach(part => {\n      partsSoFar.push(part);\n      const partial = partsSoFar.join(files.pathSep);\n      if (! (partial in this.usedAsFile)) {\n        let needToMkdir = true;\n        if (partial in this.previousUsedAsFile) {\n          if (this.previousUsedAsFile[partial]) {\n            // was previously used as file, delete it, create a directory\n            files.unlink(partial);\n          } else {\n            // is already a directory\n            needToMkdir = false;\n          }\n        }\n\n        if (needToMkdir) {\n          // It's new -- create it\n          files.mkdir(files.pathJoin(this.buildPath, partial), 0o755);\n        }\n        this.usedAsFile[partial] = false;\n      } else if (this.usedAsFile[partial]) {\n        // Already exists and is a file. Oops.\n        throw new Error(`tried to make ${relPath} a directory but ${partial} is already a file`);\n      } else {\n        // Already exists and is a directory\n      }\n    });\n  }\n\n  // isDirectory defaults to false\n  _sanitize(relPath, isDirectory) {\n    const parts = relPath.split(files.pathSep);\n    const partsOut = [];\n    for (let i = 0; i < parts.length; i++) {\n      let part = parts[i];\n      const shouldBeFile = (i === parts.length - 1) && ! isDirectory;\n      const mustBeUnique = (i === parts.length - 1);\n\n      // Basic sanitization\n      if (part.match(/^\\.+$/)) {\n        throw new Error(`Path contains forbidden segment '${part}'`);\n      }\n\n      part = part.replace(/[^a-zA-Z0-9._\\:-]/g, '');\n\n      // If at last component, pull extension (if any) off of part\n      let ext = '';\n      if (shouldBeFile) {\n        const split = part.split('.');\n        if (split.length > 1) {\n          ext = \".\" + split.pop();\n        }\n        part = split.join('.');\n      }\n\n      // Make sure it's sufficiently unique\n      let suffix = '';\n      while (true) {\n        const candidate = files.pathJoin(partsOut.join(files.pathSep), part + suffix + ext);\n        if (candidate.length) {\n          // If we've never heard of this, then it's unique enough.\n          if (!(candidate in this.usedAsFile)) {\n            break;\n          }\n          // If we want this bit to be a directory, and we don't need it to be\n          // unique (ie, it isn't the very last bit), and it's currently a\n          // directory, then that's OK.\n          if (!(mustBeUnique || this.usedAsFile[candidate])) {\n            break;\n          }\n          // OK, either we want it to be unique and it already exists; or it is\n          // currently a file (and we want it to be either a different file or a\n          // directory).  Try a new suffix.\n        }\n\n        suffix++; // first increment will do '' -> 1\n      }\n\n      partsOut.push(part + suffix + ext);\n    }\n\n    return partsOut.join(files.pathSep);\n  }\n\n  // Write either a buffer or the contents of a file to `relPath` (a\n  // path to a file relative to the bundle root), creating it (and any\n  // enclosing directories) if it doesn't exist yet. Exactly one of\n  // `data` and or `file` must be passed.\n  //\n  // Options:\n  // - data: a Buffer to write to relPath. Overrides `file`.\n  // - file: a filename to write to relPath, as a string.\n  // - sanitize: if true, then all components of the path are stripped\n  //   of any potentially troubling characters, an exception is thrown\n  //   if any path segments consist entirely of dots (eg, '..'), and\n  //   if there is a file in the bundle with the same relPath, then\n  //   the path is changed by adding a numeric suffix.\n  // - hash: a sha1 string used to determine if the contents of the\n  //   new file written is not cached.\n  // - executable: if true, mark the file as executable.\n  // - symlink: if set to a string, create a symlink to its value\n  //\n  // Returns the final canonicalize relPath that was written to.\n  //\n  // If `file` is used then it will be added to the builder's WatchSet.\n  write(relPath, {data, file, hash, sanitize, executable, symlink}) {\n    // Ensure no trailing slash\n    if (relPath.slice(-1) === files.pathSep) {\n      relPath = relPath.slice(0, -1);\n    }\n\n    // In sanitize mode, ensure path does not contain segments like\n    // '..', does not contain forbidden characters, and is unique.\n    if (sanitize) {\n      relPath = this._sanitize(relPath);\n    }\n\n    let getData = null;\n    if (data) {\n      if (! (data instanceof Buffer)) {\n        throw new Error(\"data must be a Buffer\");\n      }\n      if (file) {\n        throw new Error(\"May only pass one of data and file, not both\");\n      }\n      getData = () => data;\n    } else if (file) {\n      // postpone reading the file into memory\n      getData = () => readAndWatchFile(this.watchSet, files.pathResolve(file));\n    } else if (! symlink) {\n      throw new Error('Builder can not write without either data or a file path or a symlink path: ' + relPath);\n    }\n\n    this._ensureDirectory(files.pathDirname(relPath));\n    const absPath = files.pathJoin(this.buildPath, relPath);\n\n    if (symlink) {\n      symlinkWithOverwrite(symlink, absPath);\n    } else {\n      hash = hash || sha1(getData());\n\n      if (this.previousWrittenHashes[relPath] !== hash) {\n        // Builder is used to create build products, which should be read-only;\n        // users shouldn't be manually editing automatically generated files and\n        // expecting the results to \"stick\".\n        atomicallyRewriteFile(absPath, getData(), {\n          mode: executable ? 0o555 : 0o444\n        });\n      }\n\n      this.writtenHashes[relPath] = hash;\n    }\n    this.usedAsFile[relPath] = true;\n\n    return relPath;\n  }\n\n  // Serialize `data` as JSON and write it to `relPath` (a path to a\n  // file relative to the bundle root), creating parent directories as\n  // necessary. Throw an exception if the file already exists.\n  writeJson(relPath, data) {\n    // Ensure no trailing slash\n    if (relPath.slice(-1) === files.pathSep) {\n      relPath = relPath.slice(0, -1);\n    }\n\n    this._ensureDirectory(files.pathDirname(relPath));\n    const absPath = files.pathJoin(this.buildPath, relPath);\n\n    atomicallyRewriteFile(\n      absPath,\n      new Buffer(JSON.stringify(data, null, 2), 'utf8'),\n      {mode: 0o444});\n\n    this.usedAsFile[relPath] = true;\n  }\n\n  // Add relPath to the list of \"already taken\" paths in the\n  // bundle. This will cause write, when in sanitize mode, to never\n  // pick this filename (and will prevent files that from being\n  // written that would conflict with paths that we are expecting to\n  // be directories). Calling this twice on the same relPath will\n  // given an exception.\n  //\n  // Returns the *current* (temporary!) path to where the file or directory\n  // lives. This is so you could use non-builder code to write into a reserved\n  // directory.\n  //\n  // options:\n  // - directory: set to true to reserve this relPath to be a\n  //   directory rather than a file.\n  reserve(relPath, {directory} = {}) {\n    // Ensure no trailing slash\n    if (relPath.slice(-1) === files.pathSep) {\n      relPath = relPath.slice(0, -1);\n    }\n\n    const parts = relPath.split(files.pathSep);\n    const partsSoFar = [];\n    for (let i = 0; i < parts.length; i ++) {\n      const part = parts[i];\n      partsSoFar.push(part);\n      const soFar = partsSoFar.join(files.pathSep);\n      if (this.usedAsFile[soFar]) {\n        throw new Error(\"Path reservation conflict: \" + relPath);\n      }\n\n      const shouldBeDirectory = (i < parts.length - 1) || directory;\n      if (shouldBeDirectory) {\n        if (! (soFar in this.usedAsFile)) {\n          let needToMkdir = true;\n          if (soFar in this.previousUsedAsFile) {\n            if (this.previousUsedAsFile[soFar]) {\n              files.unlink(soFar);\n            } else {\n              needToMkdir = false;\n            }\n          }\n          if (needToMkdir) {\n            files.mkdir(files.pathJoin(this.buildPath, soFar), 0o755);\n          }\n          this.usedAsFile[soFar] = false;\n        }\n      } else {\n        this.usedAsFile[soFar] = true;\n      }\n    }\n\n    // Return the path we reserved.\n    return files.pathJoin(this.buildPath, relPath);\n  }\n\n  // Generate and reserve a unique name for a file based on `relPath`,\n  // and return it. If `relPath` is available (there is no file with\n  // that name currently existing or reserved, it doesn't contain\n  // forbidden characters, a prefix of it is not already in use as a\n  // file rather than a directory) then the return value will be\n  // `relPath`. Otherwise relPath will be modified to get the return\n  // value, say by adding a numeric suffix to some path components\n  // (preserving the file extension however) and deleting forbidden\n  // characters. Throws an exception if relPath contains any segments\n  // that are all dots (eg, '..').\n  //\n  // options:\n  //\n  // - directory: generate (and reserve) a name for a directory,\n  //   rather than a file.\n  generateFilename(relPath, {directory} = {}) {\n    relPath = this._sanitize(relPath, directory);\n    this.reserve(relPath, { directory });\n    return relPath;\n  }\n\n  // Convenience wrapper around generateFilename and write.\n  //\n  // (Note that in the object returned by builder.enter, this method\n  // is patched through directly rather than rewriting its inputs and\n  // outputs. This is only valid because it does nothing with its inputs\n  // and outputs other than send pass them to other methods.)\n  writeToGeneratedFilename(relPath, writeOptions) {\n    const generated = this.generateFilename(relPath);\n    this.write(generated, writeOptions);\n    return generated;\n  }\n\n  // Recursively copy a directory and all of its contents into the\n  // bundle. But if the symlink option was passed to the Builder\n  // constructor, then make a symlink instead, if possible.\n  //\n  // Unlike with files.cp_r, if a symlink is found, it is copied as a symlink.\n  //\n  // This does NOT add anything to the WatchSet.\n  //\n  // Options:\n  // - from: source path on local disk to copy from\n  // - to: relative path to a directory in the bundle that will\n  //   receive the files\n  // - ignore: array of regexps of filenames (that is, basenames) to\n  //   ignore (they may still be visible in the output bundle if\n  //   symlinks are being used).  Like with WatchSets, they match against\n  //   entries that end with a slash if it's a directory.\n  // - specificFiles: just copy these paths (specified as relative to 'to').\n  // - symlink: true if the directory should be symlinked instead of copying\n  copyDirectory({\n    from, to,\n    ignore,\n    specificFiles,\n    symlink,\n    npmDiscards,\n    directoryFilter,\n  }) {\n    if (to.slice(-1) === files.pathSep) {\n      to = to.slice(0, -1);\n    }\n\n    const absPathTo = files.pathJoin(this.buildPath, to);\n\n    let canSymlink = !! symlink;\n    if (canSymlink) {\n      if (specificFiles) {\n        throw new Error(\"can't copy only specific paths with a single symlink\");\n      }\n\n      if (this.usedAsFile[to]) {\n        throw new Error(\"tried to copy a directory onto \" + to +\n                        \" but it is is already a file\");\n      }\n\n      // Symlinks don't work exactly the same way on Windows, and furthermore\n      // they request Admin permissions to set.\n      if (process.platform === 'win32') {\n        canSymlink = false;\n      }\n    }\n\n    ignore = ignore || [];\n    let specificPaths = null;\n    if (specificFiles) {\n      specificPaths = {};\n      specificFiles.forEach(f => {\n        while (f !== '.') {\n          specificPaths[files.pathJoin(to, f)] = true;\n          f = files.pathDirname(f);\n        }\n      });\n    }\n\n    let walk = (absFrom, relTo) => {\n      if (canSymlink && ! (relTo in this.usedAsFile)) {\n        this._ensureDirectory(files.pathDirname(relTo));\n        const absTo = files.pathResolve(this.buildPath, relTo);\n        symlinkWithOverwrite(absFrom, absTo);\n        return;\n      }\n\n      this._ensureDirectory(relTo);\n\n      files.readdir(absFrom).forEach(item => {\n        const thisAbsFrom = files.pathResolve(absFrom, item);\n        const thisRelTo = files.pathJoin(relTo, item);\n\n        if (specificPaths && !(thisRelTo in specificPaths)) {\n          return;\n        }\n\n        const fileStatus = files.lstat(thisAbsFrom);\n\n        let itemForMatch = item;\n        const isDirectory = fileStatus.isDirectory();\n        if (isDirectory) {\n          itemForMatch += '/';\n        }\n\n        // skip excluded files\n        if (ignore.some(pattern => itemForMatch.match(pattern))) {\n          return;\n        }\n\n        if (npmDiscards instanceof NpmDiscards &&\n            npmDiscards.shouldDiscard(thisAbsFrom, isDirectory)) {\n          return;\n        }\n\n        if (isDirectory) {\n          if (typeof directoryFilter !== \"function\" ||\n              directoryFilter(thisAbsFrom)) {\n            walk(thisAbsFrom, thisRelTo);\n          }\n\n        } else if (fileStatus.isSymbolicLink()) {\n          symlinkWithOverwrite(\n            files.readlink(thisAbsFrom),\n            files.pathResolve(this.buildPath, thisRelTo)\n          );\n\n          // A symlink counts as a file, as far as \"can you put something under\n          // it\" goes.\n          this.usedAsFile[thisRelTo] = true;\n\n        } else {\n          // XXX can't really optimize this copying without reading\n          // the file into memory to calculate the hash.\n          files.copyFile(thisAbsFrom,\n                         files.pathResolve(this.buildPath, thisRelTo),\n                         fileStatus.mode);\n\n          this.usedAsFile[thisRelTo] = true;\n        }\n      });\n    };\n\n    walk(from, to);\n  }\n\n  // Returns a new Builder-compatible object that works just like a\n  // Builder, but interprets all paths relative to 'relPath', a path\n  // relative to the bundle root which should not start with a '/'.\n  //\n  // The sub-builder returned does not have all Builder methods (for\n  // example, complete() wouldn't make sense) and you should not rely\n  // on it being instanceof Builder.\n  enter(relPath) {\n    const methods = [\"write\", \"writeJson\", \"reserve\", \"generateFilename\",\n                   \"copyDirectory\", \"enter\"];\n    const subBuilder = {};\n    const relPathWithSep = relPath + files.pathSep;\n\n    methods.forEach(method => {\n      subBuilder[method] = (...args) => {\n        if (method !== \"copyDirectory\") {\n          // Normal method (relPath as first argument)\n          args[0] = files.pathJoin(relPath, args[0]);\n        } else {\n          // with copyDirectory the path we have to fix up is inside\n          // an options hash\n          args[0].to = files.pathJoin(relPath, args[0].to);\n        }\n\n        let ret = this[method](...args);\n\n        if (method === \"generateFilename\") {\n          // fix up the returned path to be relative to the\n          // sub-bundle, not the parent bundle\n          if (ret.substr(0, 1) === '/') {\n            ret = ret.substr(1);\n          }\n          if (ret.substr(0, relPathWithSep.length) !== relPathWithSep) {\n            throw new Error(\"generateFilename returned path outside of \" +\n                            \"sub-bundle?\");\n          }\n          ret = ret.substr(relPathWithSep.length);\n        }\n\n        return ret;\n      };\n    });\n\n    // Methods that don't have to fix up arguments or return values, because\n    // they are implemented purely in terms of other methods which do.\n    const passThroughMethods = [\"writeToGeneratedFilename\"];\n    passThroughMethods.forEach(method => {\n      subBuilder[method] = this[method];\n    });\n\n    return subBuilder;\n  }\n\n  // Move the completed bundle into its final location (outputPath)\n  complete() {\n    if (this.previousUsedAsFile) {\n      // delete files and folders left-over from previous runs and not\n      // re-used in this run\n      const removed = {};\n      const paths = Object.keys(this.previousUsedAsFile);\n      paths.forEach((path) => {\n        // if the same path was re-used, leave it\n        if (this.usedAsFile.hasOwnProperty(path)) { return; }\n\n        // otherwise, remove it as it is no longer needed\n\n        // skip if already deleted\n        if (removed.hasOwnProperty(path)) { return; }\n\n        const absPath = files.pathJoin(this.buildPath, path);\n        if (this.previousUsedAsFile[path]) {\n          // file\n          files.unlink(absPath);\n          removed[path] = true;\n        } else {\n          // directory\n          files.rm_recursive(absPath);\n\n          // mark all sub-paths as removed, too\n          paths.forEach((anotherPath) => {\n            if (anotherPath.startsWith(path + '/')) {\n              removed[anotherPath] = true;\n            }\n          });\n        }\n      });\n    }\n\n    // XXX Alternatively, we could just keep buildPath around, and make\n    // outputPath be a symlink pointing to it. This doesn't work for the NPM use\n    // case of renameDirAlmostAtomically since that one is constructing files to\n    // be checked in to version control, but here we could get away with it.\n    if (this.buildPath !== this.outputPath) {\n      files.renameDirAlmostAtomically(this.buildPath, this.outputPath);\n    }\n  }\n\n  // Delete the partially-completed bundle. Do not disturb outputPath.\n  abort() {\n    files.rm_recursive(this.buildPath);\n  }\n\n  // Returns a WatchSet representing all files that were read from disk by the\n  // builder.\n  getWatchSet() {\n    return this.watchSet;\n  }\n}\n\nfunction atomicallyRewriteFile(path, data, options) {\n  // create a different file with a random name and then rename over atomically\n  const rname = '.builder-tmp-file.' + Math.floor(Math.random() * 999999);\n  const rpath = files.pathJoin(files.pathDirname(path), rname);\n  files.writeFile(rpath, data, options);\n  try {\n    files.rename(rpath, path);\n  } catch (e) {\n    if (e.code === 'EISDIR') {\n      // replacing a directory with a file; this is rare (so it can\n      // be a slow path) but can legitimately happen if e.g. a developer\n      // puts a file where there used to be a directory in their app.\n      files.rm_recursive(path);\n      files.rename(rpath, path);\n    } else {\n      throw e;\n    }\n  }\n}\n\n// create a symlink, overwriting the target link, file, or directory\n// if it exists\nfunction symlinkWithOverwrite(source, target) {\n  try {\n    files.symlink(source, target);\n  } catch (e) {\n    if (e.code === 'EEXIST') {\n      // overwrite existing link, file, or directory\n      files.rm_recursive(target);\n      files.symlink(source, target);\n    } else {\n      throw e;\n    }\n  }\n}\n\n// Wrap slow methods into Profiler calls\nconst slowBuilderMethods = [\n  '_ensureDirectory', 'write', 'enter', 'copyDirectory', 'enter', 'complete'\n];\n\nslowBuilderMethods.forEach(method => {\n  Builder.prototype[method] =\n    Profile(`Builder#${method}`, Builder.prototype[method]);\n});\n"
  },
  {
    "path": "tools/isobuild/bundler.js",
    "content": "// == Site Archive (*.star) file layout (subject to rapid change) ==\n//\n// /star.json\n//\n//  - format: \"site-archive-pre1\" for this version\n//\n//  - builtBy: human readable banner (eg, \"Meteor 0.6.0\")\n//\n//  - programs: array of programs in the star, each an object:\n//    - name: short, unique name for program, for referring to it\n//      programmatically\n//    - arch: architecture that this program targets. Something like\n//            \"os\", \"os.linux.x86_64\", or \"browser.w3c\".\n//    - path: directory (relative to star.json) containing this program\n//\n//    XXX in the future this will also contain instructions for\n//    mounting packages into the namespace of each program, and\n//    possibly for mounting programs on top of each other (this would\n//    be the principled mechanism by which a server program could read\n//    a client program so it can server it)\n//\n//  - plugins: array of plugins in the star, each an object:\n//    - name: short, unique name for plugin, for referring to it\n//      programmatically\n//    - arch: typically 'os' (for a portable plugin) or eg\n//      'os.linux.x86_64' for one that include native node_modules\n//    - path: path (relative to star.json) to the control file (eg,\n//      program.json) for this plugin\n//\n// - meteorRelease: the value used in Meteor.release for programs inside the\n//     star, or \"none\"\n//\n// /README: human readable instructions\n//\n// /main.js: script that can be run in node.js to start the site\n//   running in standalone mode (after setting appropriate environment\n//   variables as documented in README)\n//\n// /server/.bundle_version.txt: contains the dev_bundle version that the meteor\n//   deploy server reads in order to set NODE_PATH to point to arch-specific\n//   builds of binary node modules\n//\n// XXX in the future one program (which must be a server-type\n// architecture) will be designated as the 'init' program. The\n// container will call it with arguments to signal app lifecycle\n// events like 'start' and 'stop'.\n//\n//\n// Conventionally programs will be located at /programs/<name>, but\n// really the build tool can lay out the star however it wants.\n//\n//\n// == Format of a program when arch is \"web.*\" ==\n//\n// Standard:\n//\n// /program.json\n//\n//  - format: \"web-program-pre1\" for this version\n//\n//  - manifest: array of resources to serve with HTTP, each an object:\n//    - path: path of file relative to program.json\n//    - where: \"client\"\n//    - type: \"js\", \"css\", or \"asset\"\n//    - cacheable: is it safe to ask the client to cache this file (boolean)\n//    - url: relative url to download the resource, includes cache busting\n//        parameter when used\n//    - size: size of file in bytes\n//    - hash: sha1 hash of the file contents\n//    - sourceMap: optional path to source map file (relative to program.json)\n//\n//    Additionally there may be a manifest entry with where equal to\n//    \"internal\", type \"head\" or \"body\", and a path and hash. These contain\n//    chunks of HTML which should be inserted in the boilerplate HTML page's\n//    <head> or <body> respectively.\n//\n//\n// == Format of a program when arch is \"os.*\" ==\n//\n// Standard:\n//\n// /server.js: script to run inside node.js to start the program\n//\n// XXX Subject to change! This will likely change to a shell script\n// (allowing us to represent types of programs that don't use or\n// depend on node) -- or in fact, rather than have anything fixed here\n// at all, star.json just contains a path to a program to run, which\n// can be anything than can be exec()'d.\n//\n// Convention:\n//\n// /program.json:\n//\n//  - load: array with each item describing a JS file to load at startup:\n//    - path: path of file, relative to program.json\n//    - node_modules: if Npm.require is called from this file, this is\n//      the path (relative to program.json) of the directory that should\n//      be search for npm modules\n//    - assets: map from path (the argument to Assets.getText and\n//      Assets.getBinary) to path on disk (relative to program.json)\n//      of the asset\n//    - sourceMap: if present, path of a file that contains a source\n//      map for this file, relative to program.json\n//\n// /config.json:\n//\n//  - client: the client program that should be served up by HTTP,\n//    expressed as a path (relative to program.json) to the *client's*\n//    program.json.\n//\n//  - meteorRelease: the value to use for Meteor.release, if any\n//\n//\n// /app/*: source code of the (server part of the) app\n// /packages/foo.js: the (linked) source code for package foo\n// /package-tests/foo.js: the (linked) source code for foo's tests\n// /npm/foo/node_modules: node_modules for package foo. may be symlinked\n//     if developing locally.\n//\n// /node_modules: node_modules needed for server.js. omitted if\n// deploying (see .bundle_version.txt above), copied if bundling,\n// symlinked if developing locally.\n//\n//\n// == Format of a program that is to be used as a plugin ==\n//\n// /program.json:\n//  - format: \"javascript-image-pre1\" for this version\n//  - arch: the architecture that this build requires\n//  - load: array with each item describing a JS file to load, in load order:\n//    - path: path of file, relative to program.json\n//    - node_modules: if Npm.require is called from this file, this is\n//      the path (relative to program.json) of the directory that should\n//      be search for npm modules\n//\n// It's a little odd that architecture is stored twice (in both the\n// top-level star control file and in the plugin control file) but\n// it's fine and it's probably actually cleaner, because it means that\n// the plugin can be treated as a self-contained unit.\n//\n// Note that while the spec for \"os.*\" is going to change to\n// represent an arbitrary POSIX (or Windows) process rather than\n// assuming a nodejs host, these plugins will always refer to\n// JavaScript code (that potentially might be a plugin to be loaded\n// into an existing JS VM). But this seems to be a concern that is\n// somewhat orthogonal to arch (these plugins can still use packages\n// of arch \"os.*\"). There is probably a missing abstraction here\n// somewhere (decoupling target type from architecture) but it can\n// wait until later.\n\nvar assert = require('assert');\nvar util = require('util');\nvar Fiber = require('fibers');\nvar _ = require('underscore');\n\nvar compiler = require('./compiler.js');\nvar PackageSource = require('./package-source.js');\nimport Builder from './builder.js';\nvar compilerPluginModule = require('./compiler-plugin.js');\nvar meteorNpm = require('./meteor-npm.js');\n\nvar files = require('../fs/files.js');\nvar archinfo = require('../utils/archinfo.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar watch = require('../fs/watch.js');\nvar colonConverter = require('../utils/colon-converter.js');\nvar Profile = require('../tool-env/profile.js').Profile;\nvar packageVersionParser = require('../packaging/package-version-parser.js');\nvar release = require('../packaging/release.js');\nimport { load as loadIsopacket } from '../tool-env/isopackets.js';\nimport { CORDOVA_PLATFORM_VERSIONS } from '../cordova';\n\n// files to ignore when bundling. node has no globs, so use regexps\nexports.ignoreFiles = [\n    /~$/, /^\\.#/, /^#.*#$/,  // emacs swap files\n    /^\\..*\\.sw.$/,  // vim swap files\n    /^\\.DS_Store\\/?$/, /^ehthumbs\\.db$/, /^Icon.$/, /^Thumbs\\.db$/,\n    /^\\.meteor\\/$/, /* avoids scanning N^2 files when bundling all packages */\n    /^\\.git\\/$/ /* often has too many files to watch */\n];\n\nfunction rejectBadPath(p) {\n  if (p.startsWith(\"..\")) {\n    throw new Error(\"bad path: \" + p);\n  }\n}\n\nvar stripLeadingSlash = function (p) {\n  if (p.charAt(0) === '/') {\n    return p.slice(1);\n  }\n\n  return p;\n};\n\n\n// Contents of main.js in bundles. Exported for use by the bundler\n// tests.\nexports._mainJsContents = [\n  \"\",\n  \"// The debugger pauses here when you run `meteor debug`, because this is \",\n  \"// the very first code to be executed by the server process. If you have \",\n  \"// not already added any `debugger` statements to your code, feel free to \",\n  \"// do so now, wait for the server to restart, then reload this page and \",\n  \"// click the |\\u25b6 button to continue.\",\n  \"process.argv.splice(2, 0, 'program.json');\",\n  \"process.chdir(require('path').join(__dirname, 'programs', 'server'));\",\n  \"require('./programs/server/boot.js');\",\n].join(\"\\n\");\n\n///////////////////////////////////////////////////////////////////////////////\n// NodeModulesDirectory\n///////////////////////////////////////////////////////////////////////////////\n\n// Represents a node_modules directory that we need to copy into the\n// bundle or otherwise make available at runtime.\n\nexport class NodeModulesDirectory {\n  constructor({\n    packageName,\n    sourceRoot,\n    sourcePath,\n    preferredBundlePath,\n    local = false,\n    npmDiscards = null,\n  }) {\n    // Name of the package this node_modules directory belongs to, or null\n    // if it belongs to an application.\n    assert.ok(typeof packageName === \"string\" || packageName === null);\n    this.packageName = packageName;\n\n    // The absolute path of the root directory of the app or package that\n    // contains this node_modules directory.\n    assert.strictEqual(typeof sourceRoot, \"string\");\n    this.sourceRoot = sourceRoot;\n\n    // The absolute path (on local disk) to a directory that contains\n    // the built node_modules to use.\n    assert.strictEqual(typeof sourcePath, \"string\");\n    this.sourcePath = sourcePath;\n\n    // The path (relative to the bundle root) where we would preferably\n    // like the node_modules to be output.\n    this.preferredBundlePath = preferredBundlePath;\n\n    // Boolean indicating whether the node_modules directory is locally\n    // accessible from other modules in the app or package.\n    this.local = !! local;\n\n    // Optionally, files to discard.\n    this.npmDiscards = npmDiscards;\n  }\n\n  copy() {\n    return new this.constructor(this);\n  }\n\n  isPortable() {\n    return meteorNpm.dependenciesArePortable(this.sourcePath);\n  }\n\n  getPreferredBundlePath(kind) {\n    assert.ok(kind === \"bundle\" ||\n              kind === \"isopack\",\n              kind);\n\n    let relPath = files.pathRelative(this.sourceRoot, this.sourcePath);\n    rejectBadPath(relPath);\n\n    const isApp = ! this.packageName;\n    if (! isApp) {\n      const name = colonConverter.convert(this.packageName);\n      const relParts = relPath.split(files.pathSep);\n\n      if (relParts[0] === \".npm\") {\n        // Normalize .npm/package/node_modules/... paths so that they get\n        // copied into the bundle as if they were in the top-level local\n        // node_modules directory of the package.\n        if (relParts[1] === \"package\") {\n          relParts.splice(0, 2);\n        } else if (relParts[1] === \"plugin\") {\n          relParts.splice(0, 3);\n        }\n      } else if (relParts[0] === \"npm\") {\n        // The npm/ at the beginning of the relPath was probably added by\n        // a previous call to getPreferredBundlePath, so we remove it here\n        // to avoid duplication.\n        let spliceCount = 1;\n        if (relParts[1] === \"node_modules\" &&\n            relParts[2] === \"meteor\" &&\n            relParts[3] === name) {\n          // Same with node_modules/meteor/<package name>/, which was\n          // almost certainly added by the code immediately below.\n          spliceCount += 3;\n        }\n        relParts.splice(0, spliceCount);\n      }\n\n      if (kind === \"bundle\") {\n        relParts.unshift(\"node_modules\", \"meteor\", name);\n      }\n\n      let lastPart = relParts.pop();\n      if (lastPart !== \"node_modules\") {\n        // Sometimes when building an app bundle for a different\n        // architecture, the isopacket source directory ends up with\n        // different npm/node_modules directories for each architecture,\n        // distinguished by numerical suffixes (e.g. npm/node_modules1).\n        // While this is important to keep the built binary files\n        // distinct, we definitely don't want node_modules1 to show up in\n        // the final build.\n        assert.ok(lastPart.startsWith(\"node_modules\"), lastPart);\n        lastPart = \"node_modules\";\n      }\n      relParts.push(lastPart);\n\n      relPath = files.pathJoin(...relParts);\n    }\n\n    // It's important not to put node_modules at the top level, so that it\n    // will not be visible from within plugins.\n    return files.pathJoin(\"npm\", relPath);\n  }\n\n  toJSON() {\n    return {\n      packageName: this.packageName,\n      local: this.local,\n    };\n  }\n\n  // Returns an object mapping from relative bundle paths to the kind of\n  // objects returned by the toJSON method above. Note that this works\n  // even if the node_modules parameter is a string, though that will only\n  // be the case for bundles built before Meteor 1.3.\n  static readDirsFromJSON(node_modules, {\n    rebuildBinaries = false,\n    // Options consumed by readDirsFromJSON are listed above. Any other\n    // options will be passed on to NodeModulesDirectory constructor via\n    // this callerInfo object:\n    ...callerInfo,\n  }) {\n    assert.strictEqual(typeof callerInfo.sourceRoot, \"string\");\n\n    const nodeModulesDirectories = Object.create(null);\n\n    function add(moreInfo, path) {\n      const info = {\n        ...callerInfo,\n        ...moreInfo,\n      };\n\n      if (! info.packageName) {\n        const parts = path.split(\"/\");\n\n        if (parts[0] === \"npm\" &&\n            parts[1] === \"node_modules\" &&\n            parts[2] === \"meteor\") {\n          info.packageName = parts[3];\n\n        } else if (parts.length === 3 &&\n                   parts[0] === \"npm\" &&\n                   parts[2] === \"node_modules\") {\n          info.packageName = parts[1];\n\n        } else {\n          parts.some(function (part, i) {\n            if (i > 0 && part === \".npm\") {\n              if (parts[i + 1] === \"package\") {\n                info.packageName = parts[i - 1];\n                return true;\n              }\n\n              if (parts[i + 1] === \"plugin\") {\n                info.packageName = parts[i + 2];\n                return true;\n              }\n            }\n          });\n        }\n\n        if (! info.packageName) {\n          throw new Error(\"No package name inferred from \" + path);\n        }\n      }\n\n      if (files.pathIsAbsolute(path)) {\n        info.sourcePath = path;\n      } else {\n        rejectBadPath(path);\n        info.sourcePath = files.pathJoin(callerInfo.sourceRoot, path);\n      }\n\n      nodeModulesDirectories[info.sourcePath] =\n        new NodeModulesDirectory(info);\n    }\n\n    if (typeof node_modules === \"string\") {\n      // Old-style node_modules strings were only ever for\n      // .npm/package/node_modules directories, which are non-local.\n      add({ local: false }, node_modules);\n    } else if (node_modules) {\n      _.each(node_modules, add);\n    }\n\n    if (rebuildBinaries) {\n      _.each(nodeModulesDirectories, (info, path) => {\n        meteorNpm.rebuildIfNonPortable(path);\n      });\n    }\n\n    return nodeModulesDirectories;\n  }\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// File\n///////////////////////////////////////////////////////////////////////////////\n\n// Allowed options:\n// - sourcePath: path to file on disk that will provide our contents\n// - data: contents of the file as a Buffer\n// - hash: optional, sha1 hash of the file contents, if known\n// - sourceMap: if 'data' is given, can be given instead of\n//   sourcePath. a string or a JS Object. Will be stored as Object.\n// - cacheable\nclass File {\n  constructor (options) {\n    if (options.data && ! (options.data instanceof Buffer)) {\n      throw new Error('File contents must be provided as a Buffer');\n    }\n    if (! options.sourcePath && ! options.data) {\n      throw new Error(\"Must provide either sourcePath or data\");\n    }\n\n    // The absolute path in the filesystem from which we loaded (or will\n    // load) this file (null if the file does not correspond to one on\n    // disk).\n    this.sourcePath = options.sourcePath;\n\n    // info is just for help with debugging the tool; it isn't written to disk or\n    // anything.\n    this.info = options.info || '?';\n\n    // If this file was generated, a sourceMap (as a string) with debugging\n    // information, as well as the \"root\" that paths in it should be resolved\n    // against. Set with setSourceMap.\n    this.sourceMap = null;\n    this.sourceMapRoot = null;\n\n    // Where this file is intended to reside within the target's\n    // filesystem.\n    this.targetPath = null;\n\n    // The URL at which this file is intended to be served, relative to\n    // the base URL at which the target is being served (ignored if this\n    // file is not intended to be served over HTTP).\n    this.url = null;\n\n    // Is this file guaranteed to never change, so that we can let it be\n    // cached forever? Only makes sense of self.url is set.\n    this.cacheable = options.cacheable || false;\n\n    // The node_modules directories that Npm.require() should search when\n    // called from inside this file. Only includes non-local node_modules\n    // directories (e.g. .npm/package/node_modules), and only works on the\n    // server architecture.\n    this.nodeModulesDirectories = Object.create(null);\n\n    // For server JS only. Assets associated with this slice; map from the path\n    // that is the argument to Assets.getBinary, to a Buffer that is its contents.\n    this.assets = null;\n\n    this._contents = options.data || null; // contents, if known, as a Buffer\n    this._hash = options.hash || null; // hash, if known, as a hex string\n  }\n\n  toString() {\n    return `File: [info=${this.info}]`;\n  }\n\n  hash() {\n    if (! this._hash) {\n      this._hash = watch.sha1(this.contents());\n    }\n    return this._hash;\n  }\n\n  // Omit encoding to get a buffer, or provide something like 'utf8'\n  // to get a string\n  contents(encoding) {\n    if (! this._contents) {\n      if (! this.sourcePath) {\n        throw new Error(\"Have neither contents nor sourcePath for file\");\n      } else {\n        this._contents = files.readFile(this.sourcePath);\n      }\n    }\n\n    return encoding ? this._contents.toString(encoding) : this._contents;\n  }\n\n  setContents(b) {\n    if (!(b instanceof Buffer)) {\n      throw new Error(\"Must set contents to a Buffer\");\n    }\n    this._contents = b;\n    // Un-cache hash.\n    this._hash = null;\n  }\n\n  size() {\n    return this.contents().length;\n  }\n\n  // Set the URL (and target path) of this file to \"/<hash><suffix>\". suffix\n  // will typically be used to pick a reasonable extension. Also set cacheable\n  // to true, since the file's name is now derived from its contents.\n\n  // Also allow a special second suffix that will *only* be postpended to the\n  // url, useful for query parameters.\n  setUrlToHash(fileAndUrlSuffix, urlSuffix) {\n    urlSuffix = urlSuffix || \"\";\n    this.url = \"/\" + this.hash() + fileAndUrlSuffix + urlSuffix;\n    this.cacheable = true;\n    this.targetPath = this.hash() + fileAndUrlSuffix;\n  }\n\n  // Append \"?<hash>\" to the URL and mark the file as cacheable.\n  addCacheBuster() {\n    if (! this.url) {\n      throw new Error(\"File must have a URL\");\n    }\n    if (this.cacheable) {\n      // eg, already got setUrlToHash\n      return;\n    }\n    if (/\\?/.test(this.url)) {\n      throw new Error(\"URL already has a query string\");\n    }\n    this.url += \"?hash=\" + this.hash();\n    this.cacheable = true;\n  }\n\n  // Given a relative path like 'a/b/c' (where '/' is this system's\n  // path component separator), produce a URL that always starts with\n  // a forward slash and that uses a literal forward slash as the\n  // component separator.\n  setUrlFromRelPath(relPath) {\n    var url = relPath;\n\n    if (url.charAt(0) !== '/') {\n      url = '/' + url;\n    }\n\n    // XXX replacing colons with underscores as colon is hard to escape later\n    // on different targets and generally is not a good separator for web.\n    url = url.replace(/:/g, '_');\n    this.url = url;\n  }\n\n  setTargetPathFromRelPath(relPath) {\n    // XXX hack\n    if (relPath.match(/^packages\\//) || relPath.match(/^assets\\//)) {\n      this.targetPath = relPath;\n    } else {\n      this.targetPath = files.pathJoin('app', relPath);\n    }\n\n    // XXX same as in setUrlFromRelPath, we replace colons with a different\n    // separator to avoid difficulties further. E.g.: on Windows it is not a\n    // valid char in filename, Cordova also rejects it, etc.\n    this.targetPath = this.targetPath.replace(/:/g, '_');\n  }\n\n  // Set a source map for this File. sourceMap is given as a string.\n  setSourceMap(sourceMap, root) {\n    if (sourceMap === null || ['object', 'string'].indexOf(typeof sourceMap) === -1) {\n      throw new Error(\"sourceMap must be given as a string or an object\");\n    }\n\n    if (typeof sourceMap === 'string') {\n      sourceMap = JSON.parse(sourceMap);\n    }\n\n    this.sourceMap = sourceMap;\n    this.sourceMapRoot = root;\n  }\n\n  // note: this assets object may be shared among multiple files!\n  setAssets(assets) {\n    if (!_.isEmpty(assets)) {\n      this.assets = assets;\n    }\n  }\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// Target\n///////////////////////////////////////////////////////////////////////////////\n\nclass Target {\n  constructor({\n    // for resolving package dependencies\n    packageMap,\n    isopackCache,\n\n    // Path to the root source directory for this Target.\n    sourceRoot,\n\n    // the architecture to build\n    arch,\n    // projectContextModule.CordovaPluginsFile object\n    cordovaPluginsFile,\n    // 'development', 'production' or 'test'; determines whether\n    // debugOnly, prodOnly and testOnly packages are included;\n    // defaults to 'production'\n    buildMode,\n    // directory on disk where to store the cache for things like linker\n    bundlerCacheDir,\n    // ... see subclasses for additional options\n  }) {\n    this.packageMap = packageMap;\n    this.isopackCache = isopackCache;\n\n    this.sourceRoot = sourceRoot;\n\n    // Something like \"web.browser\" or \"os\" or \"os.osx.x86_64\"\n    this.arch = arch;\n\n    // All of the Unibuilds that are to go into this target, in the order\n    // that they are to be loaded.\n    this.unibuilds = [];\n\n    // JavaScript files. List of File. They will be loaded at startup in\n    // the order given.\n    this.js = [];\n\n    // On-disk dependencies of this target.\n    this.watchSet = new watch.WatchSet();\n\n    // List of all package names used in this target.\n    this.usedPackages = {};\n\n    // node_modules directories that we need to copy into the target (or\n    // otherwise make available at runtime). A map from an absolute path\n    // on disk (NodeModulesDirectory.sourcePath) to a\n    // NodeModulesDirectory object that we have created to represent it.\n    //\n    // The NodeModulesDirectory objects in this map are de-duplicated\n    // aliases to the objects in the nodeModulesDirectory fields of\n    // the File objects in this.js.\n    this.nodeModulesDirectories = Object.create(null);\n\n    // Static assets to include in the bundle. List of File.\n    // For client targets, these are served over HTTP.\n    this.asset = [];\n\n    // The project's cordova plugins file (which lists plugins used directly by\n    // the project).\n    this.cordovaPluginsFile = cordovaPluginsFile;\n\n    // A mapping from Cordova plugin name to Cordova plugin version number.\n    this.cordovaDependencies = this.cordovaPluginsFile ? {} : null;\n\n    this.buildMode = buildMode || 'production';\n\n    this.bundlerCacheDir = bundlerCacheDir;\n  }\n\n  // Top-level entry point for building a target. Generally to build a\n  // target, you create with 'new', call make() to specify its sources\n  // and build options and actually do the work of buliding the\n  // target, and finally you retrieve the build product with a\n  // target-type-dependent function such as write() or toJsImage().\n  //\n  // options\n  // - packages: packages to include (Isopack or 'foo'), per\n  //   _determineLoadOrder\n  // - minifyMode: 'development'/'production'\n  // - addCacheBusters: if true, make all files cacheable by adding\n  //   unique query strings to their URLs. unlikely to be of much use\n  //   on server targets.\n  make({packages, minifyMode, addCacheBusters, minifiers}) {\n    buildmessage.assertInCapture();\n\n    buildmessage.enterJob(\"building for \" + this.arch, () => {\n      // Populate the list of unibuilds to load\n      this._determineLoadOrder({\n        packages: packages || []\n      });\n\n      const sourceBatches = this._runCompilerPlugins();\n\n      // Link JavaScript and set up this.js, etc.\n      this._emitResources(sourceBatches);\n\n      // Add top-level Cordova dependencies, which override Cordova\n      // dependencies from packages.\n      this._addDirectCordovaDependencies();\n\n      // Minify, with mode requested.\n      // Why do we only minify in client targets?\n      // (a) CSS only exists in client targets, so we definitely shouldn't\n      //     minify CSS in server targets.\n      // (b) We don't know of a use case for standard minification on server\n      //     targets (though we could imagine wanting to do other\n      //     post-processing using this API).\n      // (c) On the server, JS files have extra metadata associated like\n      //     static assets and npm modules. We'd have to support merging\n      //     the npm modules from multiple js resources (generally 1 per\n      //     package) together. This isn't impossible, but not worth\n      //     the implementation complexity without a use case.\n      // We can always extend registerMinifier to allow server targets\n      // later!\n      if (this instanceof ClientTarget) {\n        var minifiersByExt = {};\n        ['js', 'css'].forEach(function (ext) {\n          minifiersByExt[ext] = _.find(minifiers, function (minifier) {\n            return minifier && _.contains(minifier.extensions, ext);\n          });\n        });\n\n        if (minifiersByExt.js) {\n          this.minifyJs(minifiersByExt.js, minifyMode);\n        }\n        if (minifiersByExt.css) {\n          this.minifyCss(minifiersByExt.css, minifyMode);\n        }\n      }\n\n      this.rewriteSourceMaps();\n\n      if (addCacheBusters) {\n        // Make client-side CSS and JS assets cacheable forever, by\n        // adding a query string with a cache-busting hash.\n        this._addCacheBusters(\"js\");\n        this._addCacheBusters(\"css\");\n      }\n    });\n  }\n\n  // Determine the packages to load, create Unibuilds for\n  // them, put them in load order, save in unibuilds.\n  //\n  // options include:\n  // - packages: an array of packages (or, properly speaking, unibuilds)\n  //   to include. Each element should either be a Isopack object or a\n  //   package name as a string\n  _determineLoadOrder({packages}) {\n    buildmessage.assertInCapture();\n\n    const isopackCache = this.isopackCache;\n\n    buildmessage.enterJob('linking the program', () => {\n      // Find the roots\n      const rootUnibuilds = [];\n      packages.forEach((p) => {\n        if (typeof p === 'string') {\n          p = isopackCache.getIsopack(p);\n        }\n\n        // `debugOnly` packages work with \"debug\" and \"test\" build\n        // modes.\n        if (p.debugOnly && this.buildMode === 'production') {\n          return;\n        }\n        if (p.prodOnly && this.buildMode !== 'production') {\n          return;\n        }\n        if (p.testOnly && this.buildMode !== 'test') {\n          return;\n        }\n        const unibuild = p.getUnibuildAtArch(this.arch);\n        unibuild && rootUnibuilds.push(unibuild);\n      });\n\n      if (buildmessage.jobHasMessages()) {\n        return;\n      }\n\n      // PHASE 1: Which unibuilds will be used?\n      //\n      // Figure out which unibuilds are going to be used in the target,\n      // regardless of order. We ignore weak dependencies here, because they\n      // don't actually create a \"must-use\" constraint, just an ordering\n      // constraint.\n\n      // What unibuilds will be used in the target? Built in Phase 1, read in\n      // Phase 2.\n      const usedUnibuilds = {};  // Map from unibuild.id to Unibuild.\n      this.usedPackages = {};  // Map from package name to true;\n      const addToGetsUsed = function (unibuild) {\n        if (_.has(usedUnibuilds, unibuild.id)) {\n          return;\n        }\n        usedUnibuilds[unibuild.id] = unibuild;\n        if (unibuild.kind === 'main') {\n          // Only track real packages, not plugin pseudo-packages.\n          this.usedPackages[unibuild.pkg.name] = true;\n        }\n        compiler.eachUsedUnibuild({\n          dependencies: unibuild.uses,\n          arch: this.arch,\n          isopackCache: isopackCache,\n          // in both \"development\" and \"test\" build modes we should\n          // include `debugOnly` packages.\n          skipDebugOnly: this.buildMode === 'production',\n          skipProdOnly: this.buildMode !== 'production',\n          skipTestOnly: this.buildMode !== 'test',\n        }, addToGetsUsed);\n      }.bind(this);\n\n      rootUnibuilds.forEach(addToGetsUsed);\n\n      if (buildmessage.jobHasMessages()) {\n        return;\n      }\n\n      // PHASE 2: In what order should we load the unibuilds?\n      //\n      // Set this.unibuilds to be all of the roots, plus all of their non-weak\n      // dependencies, in the correct load order. \"Load order\" means that if X\n      // depends on (uses) Y, and that relationship is not marked as unordered,\n      // Y appears before X in the ordering. Raises an exception iff there is no\n      // such ordering (due to circular dependency).\n      //\n      // The topological sort code here is similar to code in isopack-cache.js,\n      // though they do serve slightly different purposes: that one determines\n      // build order dependencies and this one determines load order\n      // dependencies.\n\n      // What unibuilds have not yet been added to this.unibuilds?\n      const needed = _.clone(usedUnibuilds);  // Map from unibuild.id to Unibuild.\n      // Unibuilds that we are in the process of adding; used to detect circular\n      // ordered dependencies.\n      const onStack = {};  // Map from unibuild.id to true.\n\n      // This helper recursively adds unibuild's ordered dependencies to\n      // this.unibuilds, then adds unibuild itself.\n      const add = function (unibuild) {\n        // If this has already been added, there's nothing to do.\n        if (!_.has(needed, unibuild.id)) {\n          return;\n        }\n\n        // Process each ordered dependency. (If we have an unordered dependency\n        // `u`, then there's no reason to add it *now*, and for all we know, `u`\n        // will depend on `unibuild` and need to be added after it. So we ignore\n        // those edge. Because we did follow those edges in Phase 1, any\n        // unordered unibuilds were at some point in `needed` and will not be\n        // left out).\n        //\n        // eachUsedUnibuild does follow weak edges (ie, they affect the\n        // ordering), but only if they point to a package in usedPackages (ie, a\n        // package that SOMETHING uses strongly).\n        var processUnibuild = function (usedUnibuild) {\n          if (onStack[usedUnibuild.id]) {\n            buildmessage.error(\n              \"circular dependency between packages \" +\n                unibuild.pkg.name + \" and \" + usedUnibuild.pkg.name);\n            // recover by not enforcing one of the depedencies\n            return;\n          }\n          onStack[usedUnibuild.id] = true;\n          add(usedUnibuild);\n          delete onStack[usedUnibuild.id];\n        };\n        compiler.eachUsedUnibuild({\n          dependencies: unibuild.uses,\n          arch: this.arch,\n          isopackCache: isopackCache,\n          skipUnordered: true,\n          acceptableWeakPackages: this.usedPackages,\n          // in both \"development\" and \"test\" build modes we should\n          // include `debugOnly` packages.\n          skipDebugOnly: this.buildMode === 'production',\n          skipProdOnly: this.buildMode !== 'production',\n          skipTestOnly: this.buildMode !== 'test',\n        }, processUnibuild);\n        this.unibuilds.push(unibuild);\n        delete needed[unibuild.id];\n      }.bind(this);\n\n      while (true) {\n        // Get an arbitrary unibuild from those that remain, or break if none\n        // remain.\n        let first = null;\n        for (first in needed) {\n          break;\n        }\n        if (! first) {\n          break;\n        }\n        // Now add it, after its ordered dependencies.\n        add(needed[first]);\n      }\n    });\n  }\n\n  // Run all the compiler plugins on all source files in the project. Returns an\n  // array of PackageSourceBatches which contain the results of this processing.\n  _runCompilerPlugins() {\n    buildmessage.assertInJob();\n    const processor = new compilerPluginModule.CompilerPluginProcessor({\n      unibuilds: this.unibuilds,\n      arch: this.arch,\n      sourceRoot: this.sourceRoot,\n      isopackCache: this.isopackCache,\n      linkerCacheDir:\n        (this.bundlerCacheDir && files.pathJoin(this.bundlerCacheDir, 'linker'))\n    });\n    return processor.runCompilerPlugins();\n  }\n\n  // Process all of the sorted unibuilds (which includes running the JavaScript\n  // linker).\n  _emitResources(sourceBatches) {\n    buildmessage.assertInJob();\n\n    const isWeb = archinfo.matches(this.arch, 'web');\n    const isOs = archinfo.matches(this.arch, 'os');\n\n    const jsOutputFilesMap = compilerPluginModule.PackageSourceBatch\n      .computeJsOutputFilesMap(sourceBatches);\n\n    // Copy their resources into the bundle in order\n    sourceBatches.forEach((sourceBatch) => {\n      const unibuild = sourceBatch.unibuild;\n\n      if (this.cordovaDependencies) {\n        _.each(unibuild.pkg.cordovaDependencies, (version, name) => {\n          this._addCordovaDependency(\n            name,\n            version,\n            // use newer version if another version has already been added\n            false\n          );\n        });\n      }\n\n      const name = unibuild.pkg.name || null;\n      const isApp = ! name;\n\n      // Emit the resources\n      const resources = sourceBatch.getResources(jsOutputFilesMap.get(name));\n\n      // First, find all the assets, so that we can associate them with each js\n      // resource (for os unibuilds).\n      const unibuildAssets = {};\n      resources.forEach((resource) => {\n        if (resource.type !== 'asset') {\n          return;\n        }\n\n        const f = new File({\n          info: 'unbuild ' + resource,\n          data: resource.data,\n          cacheable: false,\n          hash: resource.hash\n        });\n\n        const relPath = isOs\n              ? files.pathJoin('assets', resource.servePath)\n              : stripLeadingSlash(resource.servePath);\n        f.setTargetPathFromRelPath(relPath);\n\n        if (isWeb) {\n          f.setUrlFromRelPath(resource.servePath);\n        } else {\n          unibuildAssets[resource.path] = resource.data;\n        }\n\n        this.asset.push(f);\n      });\n\n      // Now look for the other kinds of resources.\n      resources.forEach((resource) => {\n        if (resource.type === 'asset') {\n          // already handled\n          return;\n        }\n\n        if (resource.type !== \"js\" &&\n            resource.lazy) {\n          // Only files that compile to JS can be imported, so any other\n          // files should be ignored here, if lazy.\n          return;\n        }\n\n        if (_.contains(['js', 'css'], resource.type)) {\n          if (resource.type === 'css' && ! isWeb) {\n            // XXX might be nice to throw an error here, but then we'd\n            // have to make it so that package.js ignores css files\n            // that appear in the server directories in an app tree\n\n            // XXX XXX can't we easily do that in the css handler in\n            // meteor.js?\n            return;\n          }\n\n          const f = new File({ info: 'resource ' + resource.servePath, data: resource.data, cacheable: false});\n\n          const relPath = stripLeadingSlash(resource.servePath);\n          f.setTargetPathFromRelPath(relPath);\n\n          if (isWeb) {\n            f.setUrlFromRelPath(resource.servePath);\n          }\n\n          if (resource.type === 'js' && isOs) {\n            // Hack, but otherwise we'll end up putting app assets on this file.\n            if (resource.servePath !== '/packages/global-imports.js') {\n              f.setAssets(unibuildAssets);\n            }\n\n            _.each(unibuild.nodeModulesDirectories, nmd => {\n              this.nodeModulesDirectories[nmd.sourcePath] = nmd;\n              f.nodeModulesDirectories[nmd.sourcePath] = nmd;\n            });\n          }\n\n          // Both CSS and JS files can have source maps\n          if (resource.sourceMap) {\n            // XXX we used to set sourceMapRoot to\n            // files.pathDirname(relPath) but it's unclear why.  With the\n            // currently generated source map file names, it works without it\n            // and doesn't work well with it... maybe?  we were getting\n            // 'packages/packages/foo/bar.js'\n            f.setSourceMap(resource.sourceMap, null);\n          }\n\n          this[resource.type].push(f);\n          return;\n        }\n\n        if (_.contains(['head', 'body'], resource.type)) {\n          if (! isWeb) {\n            throw new Error('HTML segments can only go to the client');\n          }\n          this[resource.type].push(resource.data);\n          return;\n        }\n\n        throw new Error('Unknown type ' + resource.type);\n      });\n\n      // Depend on the source files that produced these resources.\n      this.watchSet.merge(unibuild.watchSet);\n\n      // Remember the versions of all of the build-time dependencies\n      // that were used in these resources. Depend on them as well.\n      // XXX assumes that this merges cleanly\n       this.watchSet.merge(unibuild.pkg.pluginWatchSet);\n    });\n  }\n\n  // Minify the JS in this target\n  minifyJs(minifierDef, minifyMode) {\n    // Avoid circular deps from top-level import.\n    const minifierPluginModule = require('./minifier-plugin.js');\n\n    const sources = _.map(this.js, function (file) {\n      return new minifierPluginModule.JsFile(file, {\n        arch: this.arch\n      });\n    });\n    var minifier = minifierDef.userPlugin.processFilesForBundle.bind(\n      minifierDef.userPlugin);\n\n    buildmessage.enterJob('minifying app code', function () {\n      try {\n        var markedMinifier = buildmessage.markBoundary(minifier);\n        markedMinifier(sources, { minifyMode });\n      } catch (e) {\n        buildmessage.exception(e);\n      }\n    });\n\n    this.js = _.flatten(sources.map((source) => {\n      return source._minifiedFiles.map((file) => {\n        const newFile = new File({\n          info: 'minified js',\n          data: new Buffer(file.data, 'utf8')\n        });\n        if (file.sourceMap) {\n          newFile.setSourceMap(file.sourceMap, '/');\n        }\n\n        if (file.path) {\n          newFile.setUrlFromRelPath(file.path);\n          newFile.targetPath = file.path;\n        } else {\n          newFile.setUrlToHash('.js', '?meteor_js_resource=true');\n        }\n\n        return newFile;\n      });\n    }));\n  }\n\n  // For every source file we process, sets the domain name to\n  // 'meteor://[emoji]app/', so there is a separate category in Chrome DevTools\n  // with the original sources.\n  rewriteSourceMaps() {\n    const rewriteSourceMap = function (sm) {\n      sm.sources = sm.sources.map(function (path) {\n        const prefix =  'meteor://\\u{1f4bb}app';\n\n        if (path.slice(0, prefix.length) === prefix) {\n          return path;\n        }\n        // This emoji makes sure the category is always last. The character\n        // is PERSONAL COMPUTER (yay ES6 unicode escapes):\n        // http://www.fileformat.info/info/unicode/char/1f4bb/index.htm\n        return prefix + (path[0] === '/' ? '' : '/') + path;\n      });\n      return sm;\n    }.bind(this);\n\n    if (this.js) {\n      this.js.forEach(function (js) {\n        if (js.sourceMap) {\n          js.sourceMap = rewriteSourceMap(js.sourceMap);\n        }\n      });\n    }\n\n    if (this.css) {\n      this.css.forEach(function (css) {\n        if (css.sourceMap) {\n          css.sourceMap = rewriteSourceMap(css.sourceMap);\n        }\n      });\n    }\n  }\n\n  // Add a Cordova plugin dependency to the target. If the same plugin\n  // has already been added at a different version and `override` is\n  // false, use whichever version is newest. If `override` is true, then\n  // we always add the exact version specified, overriding any other\n  // version that has already been added.\n  _addCordovaDependency(name, version, override) {\n    if (! this.cordovaDependencies) {\n      return;\n    }\n\n    if (override) {\n      this.cordovaDependencies[name] = version;\n    } else {\n      if (_.has(this.cordovaDependencies, name)) {\n        var existingVersion = this.cordovaDependencies[name];\n\n        if (existingVersion === version) { return; }\n\n        this.cordovaDependencies[name] = packageVersionParser.\n          lessThan(existingVersion, version) ? version : existingVersion;\n      } else {\n        this.cordovaDependencies[name] = version;\n      }\n    }\n  }\n\n  // Add Cordova plugins that have been directly added to the project\n  // (i.e. are in .meteor/cordova-plugins).\n  // XXX The versions of these direct dependencies override any versions\n  // of the same plugins that packages are using.\n  _addDirectCordovaDependencies() {\n    if (! this.cordovaDependencies) {\n      return;\n    }\n\n    _.each(this.cordovaPluginsFile.getPluginVersions(), (version, name) => {\n      this._addCordovaDependency(\n        name, version, true /* override any existing version */);\n    });\n  }\n\n  // For each resource of the given type, make it cacheable by adding\n  // a query string to the URL based on its hash.\n  _addCacheBusters(type) {\n    this[type].forEach((file) => {\n      file.addCacheBuster();\n    });\n  }\n\n  // Return the WatchSet for this target's dependency info.\n  getWatchSet() {\n    return this.watchSet;\n  }\n\n  // Return the most inclusive architecture with which this target is\n  // compatible. For example, if we set out to build a\n  // 'os.linux.x86_64' version of this target (by passing that as\n  // the 'arch' argument to the constructor), but ended up not\n  // including anything that was specific to Linux, the return value\n  // would be 'os'.\n  mostCompatibleArch() {\n    return archinfo.leastSpecificDescription(\n      _.pluck(this.unibuilds, 'arch').filter(\n        arch => archinfo.matches(this.arch, arch)\n      )\n    );\n  }\n}\n\n// mark methods for profiling\n[\n  'make',\n  '_runCompilerPlugins',\n  '_emitResources',\n  'minifyJs',\n  'rewriteSourceMaps',\n].forEach((method) => {\n  Target.prototype[method] = Profile(`Target#${method}`, Target.prototype[method]);\n});\n\n//////////////////// ClientTarget ////////////////////\n\nclass ClientTarget extends Target {\n  constructor (options) {\n    super(options);\n\n    // CSS files. List of File. They will be loaded in the order given.\n    this.css = [];\n\n    // List of segments of additional HTML for <head>/<body>.\n    this.head = [];\n    this.body = [];\n\n    if (! archinfo.matches(this.arch, 'web')) {\n      throw new Error('ClientTarget targeting something that isn\\'t a client?');\n    }\n  }\n\n  // Minify the CSS in this target\n  minifyCss(minifierDef, minifyMode) {\n    // Avoid circular deps from top-level import.\n    const minifierPluginModule = require('./minifier-plugin.js');\n\n    const sources = this.css.map((file) => {\n      return new minifierPluginModule.CssFile(file, {\n        arch: this.arch\n      });\n    });\n    const minifier = minifierDef.userPlugin.processFilesForBundle.bind(\n      minifierDef.userPlugin);\n\n    buildmessage.enterJob('minifying app stylesheet', function () {\n      try {\n        const markedMinifier = buildmessage.markBoundary(minifier);\n        markedMinifier(sources, { minifyMode });\n      } catch (e) {\n        buildmessage.exception(e);\n      }\n    });\n\n    this.css = _.flatten(sources.map((source) => {\n      return source._minifiedFiles.map((file) => {\n        const newFile = new File({\n          info: 'minified css',\n          data: new Buffer(file.data, 'utf8')\n        });\n        if (file.sourceMap) {\n          newFile.setSourceMap(file.sourceMap, '/');\n        }\n\n        if (file.path) {\n          newFile.setUrlFromRelPath(file.path);\n          newFile.targetPath = file.path;\n        } else {\n          newFile.setUrlToHash('.css', '?meteor_css_resource=true');\n        }\n\n        return newFile;\n      });\n    }));\n  }\n\n  // Output the finished target to disk\n  //\n  // Returns an object with the following keys:\n  // - controlFile: the path (relative to 'builder') of the control file for\n  // the target\n  // - nodePath: an array of paths required to be set in the NODE_PATH\n  // environment variable.\n  write(builder, {minifyMode}) {\n    builder.reserve(\"program.json\");\n\n    // Helper to iterate over all resources that we serve over HTTP.\n    const eachResource = function (f) {\n      [\"js\", \"css\", \"asset\"].forEach((type) => {\n        this[type].forEach((file) => {\n          f(file, type);\n        });\n      });\n    }.bind(this);\n\n    // Reserve all file names from the manifest, so that interleaved\n    // generateFilename calls don't overlap with them.\n    eachResource((file, type) =>\n      builder.reserve(file.targetPath)\n    );\n\n    // Build up a manifest of all resources served via HTTP.\n    const manifest = [];\n    eachResource((file, type) => {\n      const manifestItem = {\n        path: file.targetPath,\n        where: \"client\",\n        type: type,\n        cacheable: file.cacheable,\n        url: file.url\n      };\n\n      const antiXSSIPrepend = Profile(\"anti-XSSI header for source-maps\", function (sourceMap) {\n        // Add anti-XSSI header to this file which will be served over\n        // HTTP. Note that the Mozilla and WebKit implementations differ as to\n        // what they strip: Mozilla looks for the four punctuation characters\n        // but doesn't care about the newline; WebKit only looks for the first\n        // three characters (not the single quote) and then strips everything up\n        // to a newline.\n        // https://groups.google.com/forum/#!topic/mozilla.dev.js-sourcemap/3QBr4FBng5g\n        return new Buffer(\")]}'\\n\" + sourceMap, 'utf8');\n      });\n\n      if (file.sourceMap) {\n        let mapData = null;\n\n        // don't need to do this in devel mode\n        if (minifyMode === 'production') {\n          mapData = antiXSSIPrepend(JSON.stringify(file.sourceMap));\n        } else {\n          mapData = new Buffer(JSON.stringify(file.sourceMap), 'utf8');\n        }\n\n        manifestItem.sourceMap = builder.writeToGeneratedFilename(\n          file.targetPath + '.map', {data: mapData});\n\n        // Use a SHA to make this cacheable.\n        const sourceMapBaseName = file.hash() + '.map';\n        manifestItem.sourceMapUrl = require('url').resolve(\n          file.url, sourceMapBaseName);\n      }\n\n      // Set this now, in case we mutated the file's contents.\n      manifestItem.size = file.size();\n      manifestItem.hash = file.hash();\n\n      writeFile(file, builder);\n\n      manifest.push(manifestItem);\n    });\n\n    ['head', 'body'].forEach((type) => {\n      const data = this[type].join('\\n');\n      if (data) {\n        const dataBuffer = new Buffer(data, 'utf8');\n        const dataFile = builder.writeToGeneratedFilename(\n          type + '.html', { data: dataBuffer });\n        manifest.push({\n          path: dataFile,\n          where: 'internal',\n          type: type,\n          hash: watch.sha1(dataBuffer)\n        });\n      }\n    });\n\n    // Control file\n    const program = {\n      format: \"web-program-pre1\",\n      manifest: manifest\n    }\n\n    if (this.arch === 'web.cordova') {\n      const { WebAppHashing } =\n        loadIsopacket('cordova-support')['webapp-hashing'];\n      const cordovaCompatibilityVersions =\n        _.object(_.map(CORDOVA_PLATFORM_VERSIONS, (version, platform) => {\n          const hash = WebAppHashing.calculateCordovaCompatibilityHash(\n            version,\n            this.cordovaDependencies);\n          return [platform, hash];\n        }));\n      program.cordovaCompatibilityVersions = cordovaCompatibilityVersions;\n    }\n\n    builder.writeJson('program.json', program);\n\n    return {\n      controlFile: \"program.json\",\n      nodePath: []\n    };\n  }\n}\n\n// mark methods for profiling\n[\n  'minifyCss',\n  'write'\n].forEach((method) => {\n  ClientTarget.prototype[method] = Profile(`ClientTarget#${method}`, ClientTarget.prototype[method]);\n});\n\n\n//////////////////// JsImageTarget and JsImage  ////////////////////\n\n// A JsImage (JavaScript Image) is a fully linked JavaScript program\n// that is totally ready to go. (Image is used in the sense of \"the\n// output of a linker\", as in \"executable image\", rather than in the\n// sense of \"visual picture\").\n//\n// A JsImage can be loaded into its own new JavaScript virtual\n// machine, or it can be loaded into an existing virtual machine as a\n// plugin.\n\n// In real life, JsImage is usually a representation for two things:\n// 1. A server program of an App that contains all client programs as\n// well (as they are served by the server program to the browsers).\n// 2. A built Build Plugin program - a piece of software built out of\n// a Build Plugin that is ran during the build process of other\n// targets.\n// Usually, a Build Plugin is a piece of software that is very similar\n// to a server-only app: it has some code, it uses Meteor packages,\n// and sometimes it is written in a language that compiles to JS.\nclass JsImage {\n  constructor() {\n    // Array of objects with keys:\n    // - targetPath: relative path to use if saved to disk (or for stack traces)\n    // - source: JS source code to load, as a string\n    // - nodeModulesDirectories: map from absolute node_modules directory\n    //   paths to NodeModulesDirectory objects indicating which\n    //   directories should be searched by Npm.require()\n    // - sourceMap: if set, source map for this code, as a string\n    // note: this can't be called `load` at it would shadow `load()`\n    this.jsToLoad = [];\n\n    // node_modules directories that we need to copy into the target (or\n    // otherwise make available at runtime). A map from an absolute path\n    // on disk (NodeModulesDirectory.sourcePath) to a\n    // NodeModulesDirectory object that we have created to represent it.\n    //\n    // The NodeModulesDirectory objects in this map are de-duplicated\n    // aliases to the objects in the nodeModulesDirectory fields of\n    // the objects in this.jsToLoad.\n    this.nodeModulesDirectories = Object.create(null);\n\n    // Architecture required by this image\n    this.arch = null;\n  }\n\n  // Load the image into the current process. It gets its own unique\n  // Package object containing its own private copy of every\n  // isopack that it uses. This Package object is returned.\n  //\n  // If `bindings` is provided, it is a object containing a set of\n  // variables to set in the global environment of the executed\n  // code. The keys are the variable names and the values are their\n  // values. In addition to the contents of `bindings`, Package and\n  // Npm will be provided.\n  //\n  // XXX throw an error if the image includes any \"app-style\" code\n  // that is built to put symbols in the global namespace rather than\n  // in a compartment of Package\n  load(bindings) {\n    var self = this;\n    var ret = {};\n\n    // XXX This is mostly duplicated from\n    // static-assets/server/boot.js, as is Npm.require below.\n    // Some way to avoid this?\n    var getAsset = function (assets, assetPath, encoding, callback) {\n      assetPath = files.convertToStandardPath(assetPath);\n      var promise;\n      if (! callback) {\n        if (! Fiber.current) {\n          throw new Error(\"The synchronous Assets API can \" +\n                          \"only be called from within a Fiber.\");\n        }\n\n        promise = new Promise(function (resolve, reject) {\n          callback = function (err, res) {\n            err ? reject(err) : resolve(res);\n          };\n        });\n      }\n\n      var _callback = function (err, result) {\n        if (result && ! encoding) {\n          // Sadly, this copies in Node 0.10.\n          result = new Uint8Array(result);\n        }\n        callback(err, result);\n      };\n\n      if (!assets || !_.has(assets, assetPath)) {\n        _callback(new Error(\"Unknown asset: \" + assetPath));\n      } else {\n        var buffer = assets[assetPath];\n        var result = encoding ? buffer.toString(encoding) : buffer;\n        _callback(null, result);\n      }\n\n      if (promise) {\n        return promise.await();\n      }\n    };\n\n    const nodeModulesDirsByPackageName = new Map;\n\n    _.each(self.jsToLoad, item => {\n      _.each(item.nodeModulesDirectories, nmd => {\n        if (nmd.local) {\n          // Consider only non-local node_modules directories for build\n          // plugins.\n          return;\n        }\n\n        let name = nmd.packageName;\n        if (name) {\n          name = colonConverter.convert(name);\n        }\n\n        if (nodeModulesDirsByPackageName.has(name)) {\n          nodeModulesDirsByPackageName.get(name).push(nmd.sourcePath);\n        } else {\n          nodeModulesDirsByPackageName.set(name, [nmd.sourcePath]);\n        }\n      });\n    });\n\n    // Eval each JavaScript file, providing a 'Npm' symbol in the same\n    // way that the server environment would, a 'Package' symbol\n    // so the loaded image has its own private universe of loaded\n    // packages, and an 'Assets' symbol to help the package find its\n    // static assets.\n    var failed = false;\n    _.each(self.jsToLoad, function (item) {\n      if (failed) {\n        return;\n      }\n\n      var env = _.extend({\n        Package: ret,\n        Npm: {\n          require: function (name) {\n            let fullPath;\n\n            _.some(item.nodeModulesDirectories, nmd => {\n              if (nmd.local) {\n                // Npm.require doesn't consider local node_modules\n                // directories.\n                return false;\n              }\n\n              var nodeModulesTopDir = files.pathJoin(\n                nmd.sourcePath,\n                name.split(\"/\")[0]\n              );\n\n              if (files.exists(nodeModulesTopDir)) {\n                return fullPath = files.convertToOSPath(\n                  files.pathJoin(nmd.sourcePath, name)\n                );\n              }\n            });\n\n            if (fullPath) {\n              return require(fullPath);\n            }\n\n            try {\n              return require(name);\n            } catch (e) {\n              buildmessage.error(\n                \"Can't load npm module '\" + name + \"' from \" +\n                  item.targetPath + \". Check your Npm.depends().\");\n              return undefined;\n            }\n          }\n        },\n\n        /**\n         * @summary The namespace for Assets functions, lives in the bundler.\n         * @namespace\n         * @name Assets\n         */\n        Assets: {\n\n          /**\n           * @summary Retrieve the contents of the static server asset as a UTF8-encoded string.\n           * @locus Server\n           * @memberOf Assets\n           * @param {String} assetPath The path of the asset, relative to the application's `private` subdirectory.\n           * @param {Function} [asyncCallback] Optional callback, which is called asynchronously with the error or result after the function is complete. If not provided, the function runs synchronously.\n           */\n          getText: function (assetPath, callback) {\n            return getAsset(item.assets, assetPath, \"utf8\", callback);\n          },\n\n          /**\n           * @summary Retrieve the contents of the static server asset as an [EJSON Binary](#ejson_new_binary).\n           * @locus Server\n           * @memberOf Assets\n           * @param {String} assetPath The path of the asset, relative to the application's `private` subdirectory.\n           * @param {Function} [asyncCallback] Optional callback, which is called asynchronously with the error or result after the function is complete. If not provided, the function runs synchronously.\n           */\n          getBinary: function (assetPath, callback) {\n            return getAsset(item.assets, assetPath, undefined, callback);\n          }\n        }\n      }, bindings || {});\n\n      if (item.targetPath === \"packages/modules-runtime.js\") {\n        env.npmRequire = self._makeNpmRequire(nodeModulesDirsByPackageName);\n      }\n\n      try {\n        // XXX XXX Get the actual source file path -- item.targetPath\n        // is not actually correct (it's the path in the bundle rather\n        // than in the source tree).\n        files.runJavaScript(item.source.toString('utf8'), {\n          filename: item.targetPath,\n          symbols: env,\n          sourceMap: item.sourceMap,\n          sourceMapRoot: item.sourceMapRoot\n        });\n      } catch (e) {\n        buildmessage.exception(e);\n        // Recover by skipping the rest of the load\n        failed = true;\n        return;\n      }\n    });\n\n    return ret;\n  }\n\n  // Create an npmRequire function suitable for use in the\n  // packages/modules-runtime/modules-runtime.js implementation of\n  // Module.prototype.useNode. This function accepts module identifiers of\n  // the form /node_modules/meteor/*/node_modules/... and loads the\n  // corresponding packages using Node's native require function.\n  _makeNpmRequire(nodeModulesDirsByPackageName) {\n    function npmRequire(id) {\n      return require(npmResolve(id));\n    }\n\n    const resolveCache = Object.create(null);\n\n    function npmResolve(id) {\n      if (id in resolveCache) {\n        return resolveCache[id];\n      }\n\n      const parts = id.split(\"/\");\n      let start = 0;\n      let dirs;\n\n      if (parts[start] === \"\") ++start;\n      if (parts[start] === \"node_modules\" &&\n          parts[start + 1] === \"meteor\" &&\n          parts[start + 3] === \"node_modules\") {\n        const packageName = colonConverter.convert(parts[start + 2]);\n        dirs = nodeModulesDirsByPackageName.get(packageName);\n        start += 4;\n\n      } else {\n        dirs = [];\n\n        const appDirs = nodeModulesDirsByPackageName.get(null);\n        if (appDirs) {\n          dirs.push(...appDirs);\n        }\n\n        // We usually move all node_modules from the app into the source\n        // batch for the \"modules\" package, so we need to consider those\n        // directories in addition to appDirs.\n        const modulesDirs = nodeModulesDirsByPackageName.get(\"modules\");\n        if (modulesDirs) {\n          dirs.push(...modulesDirs);\n        }\n\n        start += 1;\n      }\n\n      if (dirs && dirs.length > 0) {\n        const relativePath = parts.slice(start).join(\"/\");\n        let fullPath;\n\n        _.some(dirs, dir => {\n          const osPath = files.convertToOSPath(\n            files.pathJoin(dir, relativePath));\n\n          if (files.exists(osPath)) {\n            return fullPath = osPath;\n          }\n        });\n\n        if (fullPath) {\n          return resolveCache[id] = fullPath;\n        }\n      }\n\n      throw new Error(\"Cannot find module '\" + id + \"'\");\n    }\n\n    npmRequire.resolve = npmResolve;\n\n    return npmRequire;\n  }\n\n  // Write this image out to disk\n  //\n  // options:\n  // - includeNodeModules: falsy or 'symlink' or 'reference-directly'.\n  //   Documented on exports.bundle.\n  //\n  // Returns an object with the following keys:\n  // - controlFile: the path (relative to 'builder') of the control file for\n  // the image\n  // - nodePath: an array of paths required to be set in the NODE_PATH\n  // environment variable.\n  write(builder, options) {\n    var self = this;\n    options = options || {};\n\n    builder.reserve(\"program.json\");\n\n    // Finalize choice of paths for node_modules directories -- These\n    // paths are no longer just \"preferred\"; they are the final paths\n    // that we will use\n    var nodeModulesDirectories = Object.create(null);\n    _.each(self.nodeModulesDirectories || [], function (nmd) {\n      // We need to find the actual file system location for the node modules\n      // this JS Image uses, so that we can add it to nodeModulesDirectories\n      var modulesPhysicalLocation;\n      if (! options.includeNodeModules ||\n          options.includeNodeModules === 'symlink') {\n        modulesPhysicalLocation = nmd.getPreferredBundlePath(\"bundle\");\n      } else if (options.includeNodeModules === 'reference-directly') {\n        modulesPhysicalLocation = nmd.sourcePath;\n      } else {\n        // This is some option we didn't expect - someone has added another case\n        // to the includeNodeModules option but didn't update this if block.\n        // Fail hard.\n        throw new Error(\"Option includeNodeModules wasn't falsy, 'symlink', \" +\n          \"or 'reference-directly'. It was: \" + options.includeNodeModules);\n      }\n\n      nmd = nmd.copy();\n      nmd.preferredBundlePath = modulesPhysicalLocation;\n      nodeModulesDirectories[nmd.sourcePath] = nmd;\n    });\n\n    // If multiple load files share the same asset, only write one copy of\n    // each. (eg, for app assets).\n    var assetFilesBySha = {};\n\n    // JavaScript sources\n    var load = [];\n    _.each(self.jsToLoad, function (item) {\n      if (! item.targetPath) {\n        throw new Error(\"No targetPath?\");\n      }\n\n      var loadItem = {\n        node_modules: {}\n      };\n\n      const nodeModulesPaths = [];\n\n      _.each(item.nodeModulesDirectories, nmd => {\n        // We need to make sure to use the directory name we got from\n        // builder.generateFilename here.\n        // XXX these two parallel data structures of self.jsToLoad and\n        //     self.nodeModulesDirectories are confusing\n        const generatedNMD = nodeModulesDirectories[nmd.sourcePath];\n        if (generatedNMD) {\n          assert.strictEqual(\n            typeof generatedNMD.preferredBundlePath,\n            \"string\"\n          );\n\n          // Eventually we would prefer to write these node_modules\n          // properties with object values instead of string values, like\n          // we're doing here, but older versions of meteor-tool won't be\n          // able to load images like that, so we have to wait until\n          // everyone is using a version of the tool that knows how to\n          // read object-valued node_modules properties.\n          loadItem.node_modules[generatedNMD.preferredBundlePath] =\n            generatedNMD.toJSON();\n\n          if (nmd.local) {\n            nodeModulesPaths.push(generatedNMD.preferredBundlePath);\n          } else {\n            // Give .npm/package/node_modules directories preference in\n            // the selection of a single bundle path below.\n            nodeModulesPaths.unshift(generatedNMD.preferredBundlePath);\n          }\n        }\n      });\n\n      if (nodeModulesPaths.length > 0) {\n        // For backwards compatibility, we unfortunately can only write\n        // node_modules as a single string.\n        loadItem.node_modules = nodeModulesPaths[0];\n      } else {\n        delete loadItem.node_modules;\n      }\n\n      if (item.sourceMap) {\n        // Reference the source map in the source. Looked up later by\n        // node-inspector.\n        var sourceMapBaseName = item.targetPath + \".map\";\n\n        // Write the source map.\n        loadItem.sourceMap = builder.writeToGeneratedFilename(\n          sourceMapBaseName,\n          { data: new Buffer(JSON.stringify(item.sourceMap), 'utf8') }\n        );\n\n        var sourceMapFileName = files.pathBasename(loadItem.sourceMap);\n        // Remove any existing sourceMappingURL line. (eg, if roundtripping\n        // through JsImage.readFromDisk, don't end up with two!)\n        item.source = item.source.replace(\n            /\\n\\/\\/# sourceMappingURL=.+\\n?$/g, '');\n        item.source += \"\\n//# sourceMappingURL=\" + sourceMapFileName + \"\\n\";\n        if (item.sourceMapRoot) {\n          loadItem.sourceMapRoot = item.sourceMapRoot;\n        }\n      }\n\n      loadItem.path = builder.writeToGeneratedFilename(\n        item.targetPath,\n        { data: new Buffer(item.source, 'utf8') });\n\n      if (!_.isEmpty(item.assets)) {\n        // For package code, static assets go inside a directory inside\n        // assets/packages specific to this package. Application assets (e.g. those\n        // inside private/) go in assets/app/.\n        // XXX same hack as setTargetPathFromRelPath\n          var assetBundlePath;\n        if (item.targetPath.match(/^packages\\//)) {\n          var dir = files.pathDirname(item.targetPath);\n          var base = files.pathBasename(item.targetPath, \".js\");\n          assetBundlePath = files.pathJoin('assets', dir, base);\n        } else {\n          assetBundlePath = files.pathJoin('assets', 'app');\n        }\n\n        loadItem.assets = {};\n        _.each(item.assets, function (data, relPath) {\n          var sha = watch.sha1(data);\n          if (_.has(assetFilesBySha, sha)) {\n            loadItem.assets[relPath] = assetFilesBySha[sha];\n          } else {\n            loadItem.assets[relPath] = assetFilesBySha[sha] =\n              builder.writeToGeneratedFilename(\n                files.pathJoin(assetBundlePath, relPath), { data: data });\n          }\n        });\n      }\n\n      load.push(loadItem);\n    });\n\n    const rebuildDirs = Object.create(null);\n\n    // node_modules resources from the packages. Due to appropriate\n    // builder configuration, 'meteor bundle' and 'meteor deploy' copy\n    // them, and 'meteor run' symlinks them. If these contain\n    // arch-specific code then the target will end up having an\n    // appropriately specific arch.\n    _.each(nodeModulesDirectories, function (nmd) {\n      assert.strictEqual(typeof nmd.preferredBundlePath, \"string\");\n\n      if (! nmd.isPortable()) {\n        const parentDir = files.pathDirname(nmd.preferredBundlePath);\n        rebuildDirs[parentDir] = parentDir;\n      }\n\n      if (nmd.sourcePath !== nmd.preferredBundlePath) {\n        var copyOptions = {\n          from: nmd.sourcePath,\n          to: nmd.preferredBundlePath,\n          npmDiscards: nmd.npmDiscards,\n          symlink: (options.includeNodeModules === 'symlink')\n        };\n\n        if (nmd.local) {\n          var prodPackageNames =\n            meteorNpm.getProdPackageNames(nmd.sourcePath);\n\n          // When copying a local node_modules directory, ignore any npm\n          // package directories not in the list of production package\n          // names, as determined by meteorNpm.getProdPackageNames. Note\n          // that we always copy a package directory if any package of the\n          // same name is listed as a production dependency anywhere in\n          // nmd.sourcePath. In other words, if you list a package in your\n          // \"devDependencies\", but it also gets listed in some other\n          // package's \"dependencies\", then every copy of that package\n          // will be copied to the destination directory. A little bit of\n          // overcopying vastly simplifies the job of directoryFilter.\n          copyOptions.directoryFilter = function (dir) {\n            var base = files.pathBasename(dir);\n            var parentBase = files.pathBasename(files.pathDirname(dir));\n            return parentBase !== \"node_modules\" ||\n              _.has(prodPackageNames, base);\n          };\n        }\n\n        builder.copyDirectory(copyOptions);\n      }\n    });\n\n    // This JSON file will be read by npm-rebuild.js, which is executed to\n    // trigger rebuilds for all non-portable npm packages.\n    builder.write(\"npm-rebuilds.json\", {\n      data: new Buffer(\n        JSON.stringify(Object.keys(rebuildDirs), null, 2) + \"\\n\",\n        \"utf8\"\n      )\n    });\n\n    // Control file\n    builder.writeJson('program.json', {\n      format: \"javascript-image-pre1\",\n      arch: self.arch,\n      load: load\n    });\n\n    return {\n      controlFile: \"program.json\",\n      nodePath: []\n    };\n  }\n\n  // Create a JsImage by loading a bundle of format\n  // 'javascript-image-pre1' from disk (eg, previously written out with\n  // write()). `dir` is the path to the control file.\n  static readFromDisk (controlFilePath) {\n    var ret = new JsImage;\n    var json = JSON.parse(files.readFile(controlFilePath));\n    var dir = files.pathDirname(controlFilePath);\n\n    if (json.format !== \"javascript-image-pre1\") {\n      throw new Error(\"Unsupported plugin format: \" +\n                      JSON.stringify(json.format));\n    }\n\n    ret.arch = json.arch;\n\n    _.each(json.load, function (item) {\n      rejectBadPath(item.path);\n\n      let nodeModulesDirectories;\n      if (item.node_modules) {\n        _.extend(\n          ret.nodeModulesDirectories,\n          nodeModulesDirectories =\n            NodeModulesDirectory.readDirsFromJSON(item.node_modules, {\n              sourceRoot: dir\n            })\n        );\n      }\n\n      var loadItem = {\n        targetPath: item.path,\n        source: files.readFile(files.pathJoin(dir, item.path), 'utf8'),\n        nodeModulesDirectories,\n      };\n\n      if (item.sourceMap) {\n        // XXX this is the same code as isopack.initFromPath\n        rejectBadPath(item.sourceMap);\n        loadItem.sourceMap = JSON.parse(files.readFile(\n          files.pathJoin(dir, item.sourceMap), 'utf8'));\n        loadItem.sourceMapRoot = item.sourceMapRoot;\n      }\n\n      if (!_.isEmpty(item.assets)) {\n        loadItem.assets = {};\n        _.each(item.assets, function (filename, relPath) {\n          loadItem.assets[relPath] = files.readFile(files.pathJoin(dir, filename));\n        });\n      }\n\n      ret.jsToLoad.push(loadItem);\n    });\n\n    return ret;\n  }\n}\n\n// mark methods for profiling\n[\n  'load',\n  'write'\n].forEach((method) => {\n  JsImage.prototype[method] = Profile(`JsImage#${method}`, JsImage.prototype[method]);\n});\n\nclass JsImageTarget extends Target {\n  constructor(options) {\n    super(options);\n\n    if (! archinfo.matches(this.arch, \"os\")) {\n      // Conceivably we could support targeting the client as long as\n      // no native node modules were used.  No use case for that though.\n      throw new Error(\"JsImageTarget targeting something unusual?\");\n    }\n  }\n\n  toJsImage() {\n    var self = this;\n    var ret = new JsImage;\n\n    _.each(self.js, function (file) {\n      ret.jsToLoad.push({\n        targetPath: file.targetPath,\n        source: file.contents().toString('utf8'),\n        nodeModulesDirectories: file.nodeModulesDirectories,\n        assets: file.assets,\n        sourceMap: file.sourceMap,\n        sourceMapRoot: file.sourceMapRoot\n      });\n    });\n\n    ret.nodeModulesDirectories = self.nodeModulesDirectories;\n    ret.arch = self.mostCompatibleArch();\n\n    return ret;\n  }\n}\n\n\n//////////////////// ServerTarget ////////////////////\n\nclass ServerTarget extends JsImageTarget {\n  // options specific to this subclass:\n  // - clientTarget: the ClientTarget to serve up over HTTP as our client\n  // - releaseName: the Meteor release name (for retrieval at runtime)\n  // - appIdentifier: the app identifier (for retrieval at runtime)\n  constructor (options, ...args) {\n    super(options, ...args);\n\n    this.clientTargets = options.clientTargets;\n    this.releaseName = options.releaseName;\n    this.appIdentifier = options.appIdentifier;\n\n    if (! archinfo.matches(this.arch, \"os\")) {\n      throw new Error(\"ServerTarget targeting something that isn't a server?\");\n    }\n  }\n\n  // Output the finished target to disk\n  // options:\n  // - includeNodeModules: falsy, 'symlink' or 'reference-directly',\n  //   documented in exports.bundle\n  // - getRelativeTargetPath: a function that takes {forTarget:\n  //   Target, relativeTo: Target} and return the path of one target\n  //   in the bundle relative to another. hack to get the path of the\n  //   client target.. we'll find a better solution here eventually\n  //\n  // Returns the path (relative to 'builder') of the control file for\n  // the plugin and the required NODE_PATH.\n  write(builder, options) {\n    var self = this;\n    var nodePath = [];\n\n    // This is where the dev_bundle will be downloaded and unpacked\n    builder.reserve('dependencies');\n\n    // Mapping from arch to relative path to the client program, if we have any\n    // (hack). Ex.: { 'web.browser': '../web.browser/program.json', ... }\n    var clientTargetPaths = {};\n    if (self.clientTargets) {\n      _.each(self.clientTargets, function (target) {\n        clientTargetPaths[target.arch] = files.pathJoin(options.getRelativeTargetPath({\n          forTarget: target, relativeTo: self}), 'program.json');\n      });\n    }\n\n    // We will write out config.json, the dependency kit, and the\n    // server driver alongside the JsImage\n    builder.writeJson(\"config.json\", {\n      meteorRelease: self.releaseName || undefined,\n      appId: self.appIdentifier || undefined,\n      clientPaths: clientTargetPaths\n    });\n\n    // Write package.json and npm-shrinkwrap.json for the dependencies of\n    // boot.js.\n    const serverPkgJson = JSON.parse(files.readFile(\n      files.pathJoin(files.getDevBundle(), 'etc', 'package.json')\n    ));\n\n    serverPkgJson.scripts = serverPkgJson.scripts || {};\n    serverPkgJson.scripts.install = \"node npm-rebuild.js\";\n\n    builder.write('package.json', {\n      data: new Buffer(\n        JSON.stringify(serverPkgJson, null, 2) + \"\\n\",\n        \"utf8\"\n      )\n    });\n\n    builder.write('npm-shrinkwrap.json', {\n      file: files.pathJoin(files.getDevBundle(), 'etc', 'npm-shrinkwrap.json')\n    });\n\n    // This is a hack to make 'meteor run' faster (so you don't have to run 'npm\n    // install' using the above package.json and npm-shrinkwrap.json on every\n    // rebuild).\n    if (options.includeNodeModules === 'symlink') {\n      builder.write('node_modules', {\n        symlink: files.pathJoin(files.getDevBundle(), 'server-lib', 'node_modules')\n      });\n    } else if (options.includeNodeModules === 'reference-directly') {\n      nodePath.push(\n        files.pathJoin(files.getDevBundle(), 'server-lib', 'node_modules')\n      );\n    } else if (options.includeNodeModules) {\n      // This is some option we didn't expect - someone has added another case\n      // to the includeNodeModules option but didn't update this if block. Fail\n      // hard.\n      throw new Error(\"Option includeNodeModules wasn't falsy, 'symlink', \" +\n        \"or 'reference-directly'.\");\n    }\n\n    // Linked JavaScript image (including static assets, assuming that there are\n    // any JS files at all)\n    var jsImage = self.toJsImage();\n    jsImage.write(builder, { includeNodeModules: options.includeNodeModules });\n\n    // Server bootstrap\n    _.each([\n      \"boot.js\",\n      \"boot-utils.js\",\n      \"shell-server.js\",\n      \"server-json.js\",\n      \"mini-files.js\",\n      \"npm-require.js\",\n      \"npm-rebuild.js\",\n    ], function (filename) {\n      builder.write(filename, {\n        file: files.pathJoin(\n          files.pathDirname(files.convertToStandardPath(__dirname)),\n          'static-assets',\n          'server',\n          filename\n        )\n      });\n    });\n\n    // Script that fetches the dev_bundle and runs the server bootstrap\n    // XXX this is #GalaxyLegacy, the generated start.sh is not really used by\n    // anything anymore\n    var archToPlatform = {\n      'os.linux.x86_32': 'Linux_i686',\n      'os.linux.x86_64': 'Linux_x86_64',\n      'os.linux.armv6l': 'Linux_armv6l',\n      'os.linux.armv7l': 'Linux_armv7l',\n      'os.freebsd.x86_32': 'FreeBSD_i686',\n      'os.freebsd.x86_64': 'FreeBSD_x86_64',\n      'os.freebsd.armv6l': 'FreeBSD_armv6l',\n      'os.freebsd.armv7l': 'FreeBSD_armv7l',\n      'os.openbsd.x86_32': 'OpenBSD_i686',\n      'os.openbsd.x86_64': 'OpenBSD_x86_64',\n      'os.openbsd.armv6l': 'OpenBSD_armv6l',\n      'os.openbsd.armv7l': 'OpenBSD_armv7l',\n      'os.netbsd.x86_32': 'NetBSD_i686',\n      'os.netbsd.x86_64': 'NetBSD_x86_64',\n      'os.netbsd.armv6l': 'NetBSD_armv6l',\n      'os.netbsd.armv7l': 'NetBSD_armv7l',\n      'os.osx.x86_64': 'Darwin_x86_64',\n      'os.windows.x86_32': 'Windows_x86_32'\n    };\n    var platform = archToPlatform[self.arch];\n    if (! platform) {\n      throw new Error(\"MDG does not publish dev_bundles for arch: \" +\n                         self.arch);\n    }\n\n    // Nothing actually pays attention to the `path` field for a server program\n    // in star.json any more, so it might as well be boot.js. (It used to be\n    // start.sh, a script included for the legacy Galaxy prototype.)\n    var controlFilePath = 'boot.js';\n    return {\n      controlFile: controlFilePath,\n      nodePath: nodePath\n    };\n  }\n}\n\n// mark methods for profiling\n[\n  'write'\n].forEach((method) => {\n  ServerTarget.prototype[method] = Profile(`ServerTarget#${method}`, ServerTarget.prototype[method]);\n});\n\nvar writeFile = Profile(\"bundler writeFile\", function (file, builder) {\n  if (! file.targetPath) {\n    throw new Error(\"No targetPath?\");\n  }\n  var contents = file.contents();\n  if (! (contents instanceof Buffer)) {\n    throw new Error(\"contents not a Buffer?\");\n  }\n  // XXX should probably use sanitize: true, but that will have\n  // to wait until the server is actually driven by the manifest\n  // (rather than just serving all of the files in a certain\n  // directories)\n  builder.write(file.targetPath, { data: file.contents(), hash: file.hash() });\n});\n\n// Writes a target a path in 'programs'\nvar writeTargetToPath = Profile(\n  \"bundler writeTargetToPath\",\n  function (name, target, outputPath, {\n    includeNodeModules,\n    getRelativeTargetPath,\n    previousBuilder,\n    minifyMode\n  }) {\n    var builder = new Builder({\n      outputPath: files.pathJoin(outputPath, 'programs', name),\n      previousBuilder\n    });\n\n    var targetBuild = target.write(\n      builder, {includeNodeModules, getRelativeTargetPath, minifyMode});\n\n    builder.complete();\n\n    return {\n      name,\n      arch: target.mostCompatibleArch(),\n      path: files.pathJoin('programs', name, targetBuild.controlFile),\n      nodePath: targetBuild.nodePath,\n      cordovaDependencies: target.cordovaDependencies || undefined,\n      builder\n    };\n  });\n\n///////////////////////////////////////////////////////////////////////////////\n// writeSiteArchive\n///////////////////////////////////////////////////////////////////////////////\n\n// targets is a set of Targets to include in the bundle, as a map from\n// target name (to use in the bundle) to a Target. outputPath is the\n// path of a directory that should be created to contain the generated\n// site archive.\n//\n// Returns:\n\n// {\n//     clientWatchSet: watch.WatchSet for all files and directories that\n//                     ultimately went into all client programs\n//     serverWatchSet: watch.WatchSet for all files and directories that\n//                     ultimately went into all server programs\n//     starManifest: the JSON manifest of the star\n//     nodePath: an array of paths required to be set in NODE_PATH. It's\n//               up to the called to determine what they should be.\n// }\n//\n// options:\n// - includeNodeModules: string or falsy, documented on exports.bundle\n// - builtBy: vanity identification string to write into metadata\n// - releaseName: The Meteor release version\n// - getRelativeTargetPath: see doc at ServerTarget.write\n// - previousBuilder: previous Builder object used in previous iteration\nvar writeSiteArchive = Profile(\"bundler writeSiteArchive\", function (\n  targets, outputPath, {\n    includeNodeModules,\n    builtBy,\n    releaseName,\n    getRelativeTargetPath,\n    previousBuilders,\n    minifyMode\n  }) {\n\n  const builders = {};\n  const previousStarBuilder = previousBuilders && previousBuilders.star;\n  const builder = new Builder({outputPath,\n                               previousBuilder: previousStarBuilder});\n  builders.star = builder;\n\n  try {\n    var json = {\n      format: \"site-archive-pre1\",\n      builtBy,\n      programs: [],\n      meteorRelease: releaseName\n    };\n    var nodePath = [];\n\n    // Tell the deploy server what version of the dependency kit we're using, so\n    // it can load the right modules. (Include this even if we copied or\n    // symlinked a node_modules, since that's probably enough for it to work in\n    // spite of the presence of node_modules for the wrong arch). The place we\n    // stash this is grody for temporary reasons of backwards compatibility.\n    builder.write(files.pathJoin('server', '.bundle_version.txt'), {\n      file: files.pathJoin(files.getDevBundle(), '.bundle_version.txt')\n    });\n\n    builder.write('.node_version.txt', {\n      data: new Buffer(process.version + '\\n', 'utf8')\n    });\n\n    // Affordances for standalone use\n    if (targets.server) {\n      // add program.json as the first argument after \"node main.js\" to the boot script.\n      builder.write('main.js', {\n        data: new Buffer(exports._mainJsContents, 'utf8')\n      });\n\n      builder.write('README', { data: new Buffer(\n`This is a Meteor application bundle. It has only one external dependency:\nNode.js 0.10.40 or newer. To run the application:\n\n  $ (cd programs/server && npm install)\n  $ export MONGO_URL='mongodb://user:password@host:port/databasename'\n  $ export ROOT_URL='http://example.com'\n  $ export MAIL_URL='smtp://user:password@mailhost:port/'\n  $ node main.js\n\nUse the PORT environment variable to set the port where the\napplication will listen. The default is 80, but that will require\nroot on most systems.\n\nFind out more about Meteor at meteor.com.\n`,\n      'utf8')});\n    }\n\n    // Merge the WatchSet of everything that went into the bundle.\n    const clientWatchSet = new watch.WatchSet();\n    const serverWatchSet = new watch.WatchSet();\n    const dependencySources = [builder].concat(_.values(targets));\n    dependencySources.forEach(s => {\n      if (s instanceof ClientTarget) {\n        clientWatchSet.merge(s.getWatchSet());\n      } else {\n        serverWatchSet.merge(s.getWatchSet());\n      }\n    });\n\n    Object.keys(targets).forEach(name => {\n      const target = targets[name];\n      const previousBuilder =\n              (previousBuilders && previousBuilders[name]) ?\n              previousBuilders[name] : null;\n      const {\n        arch, path, cordovaDependencies,\n        nodePath: targetNP,\n        builder: targetBuilder\n      } =\n        writeTargetToPath(name, target, builder.buildPath, {\n          includeNodeModules,\n          builtBy,\n          releaseName,\n          getRelativeTargetPath,\n          previousBuilder,\n          minifyMode\n        });\n\n      builders[name] = targetBuilder;\n\n      json.programs.push({\n        name, arch, path, cordovaDependencies\n      });\n\n      nodePath = nodePath.concat(targetNP);\n    });\n\n    // Control file\n    builder.writeJson('star.json', json);\n\n    // We did it!\n    builder.complete();\n\n    // Now, go and \"fix up\" the outputPath properties of the sub-builders.\n    // Since the sub-builders originally were targetted at a temporary\n    // buildPath of the main builder, their outputPath properties need to\n    // be adjusted so we can later pass them as previousBuilder's\n    Object.keys(builders).forEach(name => {\n      const subBuilder = builders[name];\n      subBuilder.outputPath = builder.outputPath + subBuilder.outputPath.substring(builder.buildPath.length);\n    });\n\n    return {\n      clientWatchSet,\n      serverWatchSet,\n      starManifest: json,\n      nodePath,\n      builders\n    };\n  } catch (e) {\n    builder.abort();\n    throw e;\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// Main\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n * Builds a Meteor app.\n *\n * options are:\n *\n * - projectContext: Required. The project to build (ProjectContext object).\n *\n * - outputPath: Required. Path to the directory where the output (an\n *   untarred bundle) should go. This directory will be created if it\n *   doesn't exist, and removed first if it does exist.\n *   Nothing is written to disk if this option is null.\n *\n * - includeNodeModules: specifies how node_modules for program should be\n *   included:\n *   + false/null/undefined - don't include node_modules\n *   + 'symlink' - we create a symlink from programs/server/node_modules to the\n *   dev bundle's server-lib/node_modules.  This is a hack to make 'meteor run'\n *   faster. (It is preferred on systems with symlinks as we can't just set\n *   $NODE_PATH because then random node_modules directories above cwd take\n *   precedence.) To make it even hackier, this also means we make node_modules\n *   directories for packages symlinks instead of copies.\n *   + 'reference-directly' - don't copy the files of node modules.\n *   Instead, use paths directly to files we already have on the file-system: in\n *   package catalog, isopacks folder or the dev_bundle folder.\n *   return the NODE_PATH string with the resulting bundle that would be set as\n *   the NODE_PATH environment variable when the node process is running. (The\n *   fallback option for Windows). For isopacks (meteor packages), link to the\n *   location of the locally stored isopack build (e.g.\n *   ~/.meteor/packages/package/version/npm)\n *\n * - buildOptions: may include\n *   - minifyMode: string, type of minification for the CSS and JS assets\n *     ('development'/'production', defaults to 'development')\n *   - serverArch: the server architecture to target (string, default\n *     archinfo.host())\n *   - buildMode: string, 'development'/'production'/'test', governs inclusion\n *     of debugOnly, prodOnly and testOnly packages, default 'production'\n *   - webArchs: array of 'web.*' options to build (defaults to\n *     projectContext.platformList.getWebArchs())\n *   - warnings: a MessageSet of linting messages or null if linting\n *     wasn't performed at all (either disabled or lack of linters).\n *\n * - hasCachedBundle: true if we already have a cached bundle stored in\n *   /build. When true, we only build the new client targets in the bundle.\n *\n * Returns an object with keys:\n * - errors: A buildmessage.MessageSet, or falsy if bundling succeeded.\n * - serverWatchSet: Information about server files and paths that were\n *   inputs into the bundle and that we may wish to monitor for\n *   changes when developing interactively, as a watch.WatchSet.\n * - clientWatchSet: Like 'serverWatchSet', but for client files\n * - starManifest: The manifest of the outputted star\n *\n * On failure ('errors' is truthy), no bundle will be output (in fact,\n * outputPath will have been removed if it existed).\n *\n * The currently running version of Meteor (release.current) must\n * match the version called for by the app (unless release.forced is\n * true, meaning that the user explicitly forced us to use this\n * release).\n *\n * Note that when you run \"meteor test-packages\", appDir points to the\n * test harness, while the local package search paths in 'release'\n * will point somewhere else -- into the app (if any) whose packages\n * you are testing!\n */\n\nexports.bundle = function (options) {\n  return files.withCache(() => bundle(options));\n};\n\nfunction bundle({\n  projectContext,\n  outputPath,\n  includeNodeModules,\n  buildOptions,\n  previousBuilders,\n  hasCachedBundle,\n}) {\n  buildOptions = buildOptions || {};\n\n  var serverArch = buildOptions.serverArch || archinfo.host();\n  var webArchs;\n  if (buildOptions.webArchs) {\n    // Don't attempt to build web.cordova when platforms have been removed\n    webArchs = _.intersection(\n      buildOptions.webArchs,\n      projectContext.platformList.getWebArchs());\n  } else {\n    webArchs = projectContext.platformList.getWebArchs();\n  }\n  const minifyMode = buildOptions.minifyMode || 'development';\n  const buildMode = buildOptions.buildMode || 'production';\n\n  var releaseName =\n    release.current.isCheckout() ? \"none\" : release.current.name;\n  var builtBy = \"Meteor\" + (release.current.name ?\n                            \" \" + release.current.name : \"\");\n\n  var appIdentifier = projectContext.appIdentifier;\n\n  var success = false;\n  var serverWatchSet = new watch.WatchSet();\n  var clientWatchSet = new watch.WatchSet();\n  var starResult = null;\n  var targets = {};\n  var nodePath = [];\n  var lintingMessages = null;\n  var builders = {};\n\n  const bundlerCacheDir =\n      projectContext.getProjectLocalDirectory('bundler-cache');\n\n  if (! release.usingRightReleaseForApp(projectContext)) {\n    throw new Error(\"running wrong release for app?\");\n  }\n\n  if (! _.contains(['development', 'production', 'test'], buildMode)) {\n    throw new Error('Unrecognized build mode: ' + buildMode);\n  }\n\n  var messages = buildmessage.capture({\n    title: \"building the application\"\n  }, function () {\n    var packageSource = new PackageSource;\n    packageSource.initFromAppDir(projectContext, exports.ignoreFiles);\n\n    var makeClientTarget = Profile(\n      \"bundler.bundle..makeClientTarget\", function (app, webArch, options) {\n      var client = new ClientTarget({\n        bundlerCacheDir,\n        packageMap: projectContext.packageMap,\n        isopackCache: projectContext.isopackCache,\n        sourceRoot: packageSource.sourceRoot,\n        arch: webArch,\n        cordovaPluginsFile: (webArch === 'web.cordova'\n                             ? projectContext.cordovaPluginsFile : null),\n        buildMode: buildOptions.buildMode\n      });\n\n      client.make({\n        packages: [app],\n        minifyMode: minifyMode,\n        minifiers: options.minifiers || [],\n        addCacheBusters: true\n      });\n\n      return client;\n    });\n\n    var makeServerTarget = Profile(\n      \"bundler.bundle..makeServerTarget\", function (app, clientTargets) {\n      var targetOptions = {\n        bundlerCacheDir,\n        packageMap: projectContext.packageMap,\n        isopackCache: projectContext.isopackCache,\n        sourceRoot: packageSource.sourceRoot,\n        arch: serverArch,\n        releaseName: releaseName,\n        appIdentifier: appIdentifier,\n        buildMode: buildOptions.buildMode,\n      };\n      if (clientTargets) {\n        targetOptions.clientTargets = clientTargets;\n      }\n\n      var server = new ServerTarget(targetOptions);\n\n      server.make({\n        packages: [app]\n      });\n\n      return server;\n    });\n\n    // Create a Isopack object that represents the app\n    // XXX should this be part of prepareProjectForBuild and get cached?\n    //     at the very least, would speed up deploy after build.\n    var app = compiler.compile(packageSource, {\n      packageMap: projectContext.packageMap,\n      isopackCache: projectContext.isopackCache,\n      includeCordovaUnibuild: projectContext.platformList.usesCordova()\n    });\n\n    const mergeAppWatchSets = () => {\n      var projectAndLocalPackagesWatchSet =\n        projectContext.getProjectAndLocalPackagesWatchSet();\n\n      clientWatchSet.merge(projectAndLocalPackagesWatchSet);\n      clientWatchSet.merge(app.getClientWatchSet());\n\n      serverWatchSet.merge(projectAndLocalPackagesWatchSet);\n      serverWatchSet.merge(app.getServerWatchSet());\n    };\n\n    // If we failed to 'compile' the app (which mostly means something odd\n    // happened like clashing extension handlers, or a legacy source handler\n    // failed), restart on any relevant change, and be done.\n    if (buildmessage.jobHasMessages()) {\n      return mergeAppWatchSets();\n    }\n\n    if (! buildmessage.jobHasMessages()) {\n      lintingMessages = lintBundle(projectContext, app, packageSource);\n    }\n    // If while trying to lint, we got a compilation error (eg, an issue loading\n    // plugins in one of the linter packages), restart on any relevant change,\n    // and be done.\n    if (buildmessage.jobHasMessages()) {\n      return mergeAppWatchSets();\n    }\n\n    var minifiers = null;\n    if (! _.contains(['development', 'production'], minifyMode)) {\n      throw new Error('Unrecognized minification mode: ' + minifyMode);\n    }\n    minifiers = compiler.getMinifiers(packageSource, {\n      isopackCache: projectContext.isopackCache,\n      isopack: app\n    });\n    // If figuring out what the minifiers are failed (eg, clashing extension\n    // handlers), restart on any relevant change, and be done.\n    if (buildmessage.jobHasMessages()) {\n      return mergeAppWatchSets();\n    }\n\n    var clientTargets = [];\n    // Client\n    _.each(webArchs, function (arch) {\n      var client = makeClientTarget(app, arch, {minifiers});\n      clientTargets.push(client);\n      targets[arch] = client;\n    });\n\n    // Server\n    if (! hasCachedBundle) {\n      var server = makeServerTarget(app, clientTargets);\n      targets.server = server;\n    }\n\n    // Hack to let servers find relative paths to clients. Should find\n    // another solution eventually (probably some kind of mount\n    // directive that mounts the client bundle in the server at runtime)\n    var getRelativeTargetPath = function (options) {\n      var pathForTarget = function (target) {\n        var name;\n        _.each(targets, function (t, n) {\n          if (t === target) {\n            name = n;\n          }\n        });\n        if (! name) {\n          throw new Error(\"missing target?\");\n        }\n        return files.pathJoin('programs', name);\n      };\n\n      return files.pathRelative(pathForTarget(options.relativeTo),\n                                pathForTarget(options.forTarget));\n    };\n\n    // Write to disk\n    var writeOptions = {\n      includeNodeModules,\n      builtBy,\n      releaseName,\n      getRelativeTargetPath,\n      minifyMode: minifyMode\n    };\n\n    if (outputPath !== null) {\n      if (hasCachedBundle) {\n        // If we already have a cached bundle, just recreate the new targets.\n        // XXX This might make the contents of \"star.json\" out of date.\n        builders = _.clone(previousBuilders);\n        _.each(targets, function (target, name) {\n          const previousBuilder = previousBuilders && previousBuilders[name];\n          var targetBuild = writeTargetToPath(\n            name, target, outputPath,\n            _.extend({}, writeOptions, {previousBuilder})\n         );\n          nodePath = nodePath.concat(targetBuild.nodePath);\n          clientWatchSet.merge(target.getWatchSet());\n          builders[name] = targetBuild.builder;\n        });\n      } else {\n        starResult = writeSiteArchive(\n          targets,\n          outputPath,\n          _.extend({}, writeOptions, {previousBuilders})\n        );\n\n        nodePath = nodePath.concat(starResult.nodePath);\n        serverWatchSet.merge(starResult.serverWatchSet);\n        clientWatchSet.merge(starResult.clientWatchSet);\n        builders = starResult.builders;\n      }\n    }\n\n    success = true;\n  });\n\n  if (success && messages.hasMessages()) {\n    // there were errors\n    success = false;\n  }\n\n  return {\n    errors: success ? false : messages,\n    warnings: lintingMessages,\n    serverWatchSet,\n    clientWatchSet,\n    starManifest: starResult && starResult.starManifest,\n    nodePath,\n    builders\n  };\n};\n\n// Returns null if there are no lint warnings and the app has no linters\n// defined. Returns an empty MessageSet if the app has a linter defined but\n// there are no lint warnings (on app or packages).\nfunction lintBundle (projectContext, isopack, packageSource) {\n  buildmessage.assertInJob();\n\n  let lintedAnything = false;\n  const lintingMessages = new buildmessage._MessageSet();\n\n  if (projectContext.lintAppAndLocalPackages) {\n    const {warnings: appMessages, linted} = compiler.lint(packageSource, {\n      isopack,\n      isopackCache: projectContext.isopackCache\n    });\n    if (linted) {\n      lintedAnything = true;\n      lintingMessages.merge(appMessages);\n    }\n  }\n\n  const localPackagesMessages =\n    projectContext.getLintingMessagesForLocalPackages();\n  if (localPackagesMessages) {\n    lintedAnything = true;\n    lintingMessages.merge(localPackagesMessages);\n  }\n\n  // if there was no linting performed since there are no applicable\n  // linters for neither app nor packages, just return null\n  return lintedAnything ? lintingMessages : null;\n}\n\n// Make a JsImage object (a complete, linked, ready-to-go JavaScript\n// program). It can either be loaded into memory with load(), which\n// returns the `Package` object inside the plugin's namespace, or\n// saved to disk with write(builder).\n//\n// Returns an object with keys:\n// - image: The created JsImage object.\n// - watchSet: Source file WatchSet (see bundle()).\n// - usedPackageNames: array of names of packages that are used\n//\n// XXX return an 'errors' key for symmetry with bundle(), rather than\n// letting exceptions escape?\n//\n// options:\n// - packageMap: required. the PackageMap for resolving\n//   bundle-time dependencies\n// - isopackCache: required. IsopackCache with all dependent packages\n//   loaded\n// - name: required. a name for this image (cosmetic, but will appear\n//   in, eg, error messages) -- technically speaking, this is the name\n//   of the package created to contain the sources and package\n//   dependencies set up below\n// - use: list of packages to use in the plugin, as strings (foo or foo.bar)\n// - sources: source files to use (paths on local disk)\n// - sourceRoot: path relative to which sources should be\n//   interpreted. please set it to something reasonable so that any error\n//   messages will look pretty.\n// - npmDependencies: map from npm package name to required version\n// - npmDir: where to keep the npm cache and npm version shrinkwrap\n//   info. required if npmDependencies present.\n//\n// XXX currently any symbols exported by the plugin will get mapped\n// into 'Package.<plugin name>' within the plugin, so name should not\n// be the name of any package that is included (directly or\n// transitively) in the plugin build. obviously this is unfortunate.\n// It would be nice to have a way to say \"make this package anonymous\"\n// without also saying \"make its namespace the same as the global\n// namespace.\" It should be an easy refactor,\nexports.buildJsImage = Profile(\"bundler.buildJsImage\", function (options) {\n  buildmessage.assertInCapture();\n  if (options.npmDependencies && ! options.npmDir) {\n    throw new Error(\"Must indicate .npm directory to use\");\n  }\n  if (! options.name) {\n    throw new Error(\"Must provide a name\");\n  }\n\n  var packageSource = new PackageSource;\n\n  packageSource.initFromOptions(options.name, {\n    kind: \"plugin\",\n    use: options.use || [],\n    sourceRoot: options.sourceRoot,\n    sources: options.sources || [],\n    // it is correct to set slash and not files.pathSep because serverRoot is a\n    // url path and not a file system path\n    serveRoot: options.serveRoot || '/',\n    npmDependencies: options.npmDependencies,\n    npmDir: options.npmDir,\n    localNodeModulesDirs: options.localNodeModulesDirs,\n  });\n\n  var isopack = compiler.compile(packageSource, {\n    packageMap: options.packageMap,\n    isopackCache: options.isopackCache,\n    // There's no web.cordova unibuild here anyway, just os.\n    includeCordovaUnibuild: false\n  });\n\n  var target = new JsImageTarget({\n    packageMap: options.packageMap,\n    isopackCache: options.isopackCache,\n    sourceRoot: packageSource.sourceRoot,\n    // This function does not yet support cross-compilation (neither does\n    // initFromOptions). That's OK for now since we're only trying to support\n    // cross-bundling, not cross-package-building, and this function is only\n    // used to build plugins (during package build) and for isopack.load\n    // (which always wants to build for the current host).\n    arch: archinfo.host()\n  });\n  target.make({ packages: [isopack] });\n\n  return {\n    image: target.toJsImage(),\n    watchSet: target.getWatchSet(),\n    usedPackageNames: _.keys(target.usedPackages)\n  };\n});\n\n// Load a JsImage from disk (that was previously written by calling\n// write() on a JsImage). `controlFilePath` is the path to the control\n// file (eg, program.json).\nexports.readJsImage = Profile(\n  \"bundler.readJsImage\", function (controlFilePath) {\n  return JsImage.readFromDisk(controlFilePath);\n});\n"
  },
  {
    "path": "tools/isobuild/compiler-deprecated-compile-step.js",
    "content": "// This file contains an old definition of CompileStep, an object that is passed\n// to the package-provided file handler.\n// Since then, the newer API called \"Batch Plugins\" have replaced it but we keep\n// the functionality for the backwards-compitability.\n// @deprecated\n// XXX COMPAT WITH 1.1.0.2\n\nvar _ = require('underscore');\n\nvar archinfo = require('../utils/archinfo.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar files = require('../fs/files.js');\nvar colonConverter = require('../utils/colon-converter.js');\nvar watch = require('../fs/watch.js');\n\nvar convertSourceMapPaths = function (sourcemap, f) {\n  if (! sourcemap) {\n    // Don't try to convert it if it doesn't exist\n    return sourcemap;\n  }\n\n  var srcmap = JSON.parse(sourcemap);\n  srcmap.sources = _.map(srcmap.sources, f);\n  return JSON.stringify(srcmap);\n};\n\nexports.makeCompileStep = function (sourceItem, file, inputSourceArch, options) {\n  var resources = options.resources;\n  var addAsset = options.addAsset;\n\n  var relPath = sourceItem.relPath;\n  var fileOptions = _.clone(sourceItem.fileOptions) || {};\n  var absPath = files.pathResolve(inputSourceArch.pkg.sourceRoot, relPath);\n  var filename = files.pathBasename(relPath);\n  var hash = file.hash;\n  var contents = file.contents;\n\n  // This object is called a #CompileStep and it's the interface\n  // to plugins that define new source file handlers (eg,\n  // Coffeescript).\n  //\n  // Fields on CompileStep:\n  //\n  // - arch: the architecture for which we are building\n  // - inputSize: total number of bytes in the input file\n  // - inputPath: the filename and (relative) path of the input\n  //   file, eg, \"foo.js\". We don't provide a way to get the full\n  //   path because you're not supposed to read the file directly\n  //   off of disk. Instead you should call read(). That way we\n  //   can ensure that the version of the file that you use is\n  //   exactly the one that is recorded in the dependency\n  //   information.\n  // - pathForSourceMap: If this file is to be included in a source map,\n  //   this is the name you should use for it in the map.\n  // - rootOutputPath: on web targets, for resources such as\n  //   stylesheet and static assets, this is the root URL that\n  //   will get prepended to the paths you pick for your output\n  //   files so that you get your own namespace, for example\n  //   '/packages/foo'. null on non-web targets\n  // - fileOptions: any options passed to \"api.addFiles\"; for\n  //   use by the plugin. The built-in \"js\" plugin uses the \"bare\"\n  //   option for files that shouldn't be wrapped in a closure.\n  // - declaredExports: An array of symbols exported by this unibuild, or null\n  //   if it may not export any symbols (eg, test unibuilds). This is used by\n  //   CoffeeScript to ensure that it doesn't close over those symbols, eg.\n  // - read(n): read from the input file. If n is given it should\n  //   be an integer, and you will receive the next n bytes of the\n  //   file as a Buffer. If n is omitted you get the rest of the\n  //   file.\n  // - appendDocument({ section: \"head\", data: \"my markup\" })\n  //   Browser targets only. Add markup to the \"head\" or \"body\"\n  //   Web targets only. Add markup to the \"head\" or \"body\"\n  //   section of the document.\n  // - addStylesheet({ path: \"my/stylesheet.css\", data: \"my css\",\n  //                   sourceMap: \"stringified json sourcemap\"})\n  //   Web targets only. Add a stylesheet to the\n  //   document. 'path' is a requested URL for the stylesheet that\n  //   may or may not ultimately be honored. (Meteor will add\n  //   appropriate tags to cause the stylesheet to be loaded. It\n  //   will be subject to any stylesheet processing stages in\n  //   effect, such as minification.)\n  // - addJavaScript({ path: \"my/program.js\", data: \"my code\",\n  //                   sourcePath: \"src/my/program.js\",\n  //                   bare: true })\n  //   Add JavaScript code, which will be namespaced into this\n  //   package's environment (eg, it will see only the exports of\n  //   this package's imports), and which will be subject to\n  //   minification and so forth. Again, 'path' is merely a hint\n  //   that may or may not be honored. 'sourcePath' is the path\n  //   that will be used in any error messages generated (eg,\n  //   \"foo.js:4:1: syntax error\"). It must be present and should\n  //   be relative to the project root. Typically 'inputPath' will\n  //   do handsomely. \"bare\" means to not wrap the file in\n  //   a closure, so that its vars are shared with other files\n  //   in the module.\n  // - addAsset({ path: \"my/image.png\", data: Buffer })\n  //   Add a file to serve as-is over HTTP (web targets) or\n  //   to include as-is in the bundle (os targets).\n  //   This time `data` is a Buffer rather than a string. For\n  //   web targets, it will be served at the exact path you\n  //   request (concatenated with rootOutputPath). For server\n  //   targets, the file can be retrieved by passing path to\n  //   Assets.getText or Assets.getBinary.\n  // - error({ message: \"There's a problem in your source file\",\n  //           sourcePath: \"src/my/program.ext\", line: 12,\n  //           column: 20, func: \"doStuff\" })\n  //   Flag an error -- at a particular location in a source\n  //   file, if you like (you can even indicate a function name\n  //   to show in the error, like in stack traces). sourcePath,\n  //   line, column, and func are all optional.\n  //\n  // XXX for now, these handlers must only generate portable code\n  // (code that isn't dependent on the arch, other than 'web'\n  // vs 'os') -- they can look at the arch that is provided\n  // but they can't rely on the running on that particular arch\n  // (in the end, an arch-specific unibuild will be emitted only if\n  // there are native node modules). Obviously this should\n  // change. A first step would be a setOutputArch() function\n  // analogous to what we do with native node modules, but maybe\n  // what we want is the ability to ask the plugin ahead of time\n  // how specific it would like to force unibuilds to be.\n  //\n  // XXX we handle encodings in a rather cavalier way and I\n  // suspect we effectively end up assuming utf8. We can do better\n  // than that!\n  //\n  // XXX addAsset probably wants to be able to set MIME type and\n  // also control any manifest field we deem relevant (if any)\n  //\n  // XXX Some handlers process languages that have the concept of\n  // include files. These are problematic because we need to\n  // somehow instrument them to get the names and hashs of all of\n  // the files that they read for dependency tracking purposes. We\n  // don't have an API for that yet, so for now we provide a\n  // workaround, which is that _fullInputPath contains the full\n  // absolute path to the input files, which allows such a plugin\n  // to set up its include search path. It's then on its own for\n  // registering dependencies (for now..)\n  //\n  // XXX in the future we should give plugins an easy and clean\n  // way to return errors (that could go in an overall list of\n  // errors experienced across all files)\n  var readOffset = 0;\n\n  /**\n   * The comments for this class aren't used to generate docs right now.\n   * The docs live in the GitHub Wiki at: https://github.com/meteor/meteor/wiki/CompileStep-API-for-Build-Plugin-Source-Handlers\n   * @class CompileStep\n   * @summary The object passed into Plugin.registerSourceHandler\n   * @global\n   */\n  var compileStep = {\n\n    /**\n     * @summary The total number of bytes in the input file.\n     * @memberOf CompileStep\n     * @instance\n     * @type {Integer}\n     */\n    inputSize: contents.length,\n\n    /**\n     * @summary The filename and relative path of the input file.\n     * Please don't use this filename to read the file from disk, instead\n     * use [compileStep.read](CompileStep-read).\n     * @type {String}\n     * @instance\n     * @memberOf CompileStep\n     */\n    inputPath: files.convertToOSPath(relPath, true),\n\n    /**\n     * @summary The filename and absolute path of the input file.\n     * Please don't use this filename to read the file from disk, instead\n     * use [compileStep.read](CompileStep-read).\n     * @type {String}\n     * @instance\n     * @memberOf CompileStep\n     */\n    fullInputPath: files.convertToOSPath(absPath),\n\n    // The below is used in the less and stylus packages... so it should be\n    // public API.\n    _fullInputPath: files.convertToOSPath(absPath), // avoid, see above..\n\n    // Used for one optimization. Don't rely on this otherwise.\n    _hash: hash,\n\n    // XXX duplicates _pathForSourceMap() in linker\n    /**\n     * @summary If you are generating a sourcemap for the compiled file, use\n     * this path for the original file in the sourcemap.\n     * @type {String}\n     * @memberOf CompileStep\n     * @instance\n     */\n    pathForSourceMap: files.convertToOSPath(\n      inputSourceArch.pkg.name ?  inputSourceArch.pkg.name + \"/\" + relPath :\n                                  files.pathBasename(relPath), true),\n\n    // null if this is an app. intended to be used for the sources\n    // dictionary for source maps.\n    /**\n     * @summary The name of the package in which the file being built exists.\n     * @type {String}\n     * @memberOf CompileStep\n     * @instance\n     */\n    packageName: inputSourceArch.pkg.name,\n\n    /**\n     * @summary On web targets, this will be the root URL prepended\n     * to the paths you pick for your output files. For example,\n     * it could be \"/packages/my-package\".\n     * @type {String}\n     * @memberOf CompileStep\n     * @instance\n     */\n    rootOutputPath: files.convertToOSPath(\n      inputSourceArch.pkg.serveRoot, true),\n\n    /**\n     * @summary The architecture for which we are building. Can be \"os\",\n     * \"web.browser\", or \"web.cordova\".\n     * @type {String}\n     * @memberOf CompileStep\n     * @instance\n     */\n    arch: inputSourceArch.arch,\n\n    /**\n     * @deprecated in 0.9.4\n     * This is a duplicate API of the above, we don't need it.\n     */\n    archMatches: function (pattern) {\n      return archinfo.matches(inputSourceArch.arch, pattern);\n    },\n\n    /**\n     * @summary Any options passed to \"api.addFiles\".\n     * @type {Object}\n     * @memberOf CompileStep\n     * @instance\n     */\n    fileOptions: fileOptions,\n\n    /**\n     * @summary The list of exports that the current package has defined.\n     * Can be used to treat those symbols differently during compilation.\n     * @type {Object}\n     * @memberOf CompileStep\n     * @instance\n     */\n    declaredExports: _.pluck(inputSourceArch.declaredExports, 'name'),\n\n    /**\n     * @summary Read from the input file. If `n` is specified, returns the\n     * next `n` bytes of the file as a Buffer. XXX not sure if this actually\n     * returns a String sometimes...\n     * @param  {Integer} [n] The number of bytes to return.\n     * @instance\n     * @memberOf CompileStep\n     * @returns {Buffer}\n     */\n    read: function (n) {\n      if (n === undefined || readOffset + n > contents.length) {\n        n = contents.length - readOffset;\n      }\n      var ret = contents.slice(readOffset, readOffset + n);\n      readOffset += n;\n      return ret;\n    },\n\n    _getOption(name, options) {\n      if (options && _.has(options, name)) {\n        return options[name];\n      }\n      const fileOptions = this.fileOptions;\n      return fileOptions && fileOptions[name];\n    },\n\n    /**\n     * @summary Works in web targets only. Add markup to the `head` or `body`\n     * section of the document.\n     * @param  {Object} options\n     * @param {String} options.section Which section of the document should\n     * be appended to. Can only be \"head\" or \"body\".\n     * @param {String} options.data The content to append.\n     * @memberOf CompileStep\n     * @instance\n     */\n    addHtml: function (options) {\n      if (! archinfo.matches(inputSourceArch.arch, \"web\")) {\n        throw new Error(\"Document sections can only be emitted to \" +\n                        \"web targets\");\n      }\n      if (options.section !== \"head\" && options.section !== \"body\") {\n        throw new Error(\"'section' must be 'head' or 'body'\");\n      }\n      if (typeof options.data !== \"string\") {\n        throw new Error(\"'data' option to appendDocument must be a string\");\n      }\n      resources.push({\n        type: options.section,\n        data: new Buffer(files.convertToStandardLineEndings(options.data), 'utf8'),\n        lazy: this._getOption(\"lazy\", options),\n      });\n    },\n\n    /**\n     * @deprecated in 0.9.4\n     */\n    appendDocument: function (options) {\n      this.addHtml(options);\n    },\n\n    /**\n     * @summary Web targets only. Add a stylesheet to the document.\n     * @param {Object} options\n     * @param {String} path The requested path for the added CSS, may not be\n     * satisfied if there are path conflicts.\n     * @param {String} data The content of the stylesheet that should be\n     * added.\n     * @param {String} sourceMap A stringified JSON sourcemap, in case the\n     * stylesheet was generated from a different file.\n     * @memberOf CompileStep\n     * @instance\n     */\n    addStylesheet: function (options) {\n      if (! archinfo.matches(inputSourceArch.arch, \"web\")) {\n        throw new Error(\"Stylesheets can only be emitted to \" +\n                        \"web targets\");\n      }\n      if (typeof options.data !== \"string\") {\n        throw new Error(\"'data' option to addStylesheet must be a string\");\n      }\n      resources.push({\n        type: \"css\",\n        refreshable: true,\n        data: new Buffer(files.convertToStandardLineEndings(options.data), 'utf8'),\n        servePath: colonConverter.convert(\n          files.pathJoin(\n            inputSourceArch.pkg.serveRoot,\n            files.convertToStandardPath(options.path, true))),\n        sourceMap: convertSourceMapPaths(options.sourceMap,\n                                         files.convertToStandardPath),\n        lazy: this._getOption(\"lazy\", options),\n      });\n    },\n\n    /**\n     * @summary Add JavaScript code. The code added will only see the\n     * namespaces imported by this package as runtime dependencies using\n     * ['api.use'](#PackageAPI-use). If the file being compiled was added\n     * with the bare flag, the resulting JavaScript won't be wrapped in a\n     * closure.\n     * @param {Object} options\n     * @param {String} options.path The path at which the JavaScript file\n     * should be inserted, may not be honored in case of path conflicts.\n     * @param {String} options.data The code to be added.\n     * @param {String} options.sourcePath The path that will be used in\n     * any error messages generated by this file, e.g. `foo.js:4:1: error`.\n     * @memberOf CompileStep\n     * @instance\n     */\n    addJavaScript: function (options) {\n      if (typeof options.data !== \"string\") {\n        throw new Error(\"'data' option to addJavaScript must be a string\");\n      }\n\n      let sourcePath = this.inputPath;\n      if (_.has(options, \"sourcePath\") &&\n          typeof options.sourcePath === \"string\") {\n        sourcePath = options.sourcePath;\n      }\n\n      const targetPath = options.path || sourcePath;\n\n      if (typeof sourcePath !== \"string\") {\n        throw new Error(\"'sourcePath' option must be supplied to addJavaScript. Consider passing inputPath.\");\n      }\n\n      var data = new Buffer(\n        files.convertToStandardLineEndings(options.data), 'utf8');\n      resources.push({\n        type: \"js\",\n        data: data,\n        sourcePath,\n        targetPath,\n        servePath: colonConverter.convert(\n          files.pathJoin(\n            inputSourceArch.pkg.serveRoot,\n            files.convertToStandardPath(targetPath, true))),\n        hash: watch.sha1(data),\n        sourceMap: convertSourceMapPaths(options.sourceMap,\n                                         files.convertToStandardPath),\n        lazy: this._getOption(\"lazy\", options),\n        bare: !! this._getOption(\"bare\", options),\n        mainModule: !! this._getOption(\"mainModule\", options),\n      });\n    },\n\n    /**\n     * @summary Add a file to serve as-is to the browser or to include on\n     * the browser, depending on the target. On the web, it will be served\n     * at the exact path requested. For server targets, it can be retrieved\n     * using `Assets.getText` or `Assets.getBinary`.\n     * @param {Object} options\n     * @param {String} path The path at which to serve the asset.\n     * @param {Buffer|String} data The data that should be placed in\n     * the file.\n     * @memberOf CompileStep\n     * @instance\n     */\n    addAsset: function (options) {\n      if (! (options.data instanceof Buffer)) {\n        if (_.isString(options.data)) {\n          options.data = new Buffer(options.data);\n        } else {\n          throw new Error(\"'data' option to addAsset must be a Buffer or String.\");\n        }\n      }\n\n      addAsset(options.data, files.convertToStandardPath(options.path, true));\n    },\n\n    /**\n     * @summary Display a build error.\n     * @param  {Object} options\n     * @param {String} message The error message to display.\n     * @param {String} [sourcePath] The path to display in the error message.\n     * @param {Integer} line The line number to display in the error message.\n     * @param {String} func The function name to display in the error message.\n     * @memberOf CompileStep\n     * @instance\n     */\n    error: function (options) {\n      let sourcePath = this.inputPath;\n      if (_.has(options, \"sourcePath\") &&\n          typeof options.sourcePath === \"string\") {\n        sourcePath = options.sourcePath;\n      }\n\n      const message = options.message || (\"error building \" + relPath);\n\n      const info = { file: sourcePath };\n      if (options.line) info.line = options.line;\n      if (options.column) info.column = options.column;\n      if (options.func) info.func = options.func;\n\n      if (compileStep._getOption(\"lazy\") === true) {\n        // Because this file is lazy, it might not have been explicitly\n        // added in package.js, so we should ignore compilation errors\n        // until and unless it is ever actually imported.\n        resources.push({\n          type: \"js\",\n          sourcePath,\n          targetPath: sourcePath,\n          servePath: sourcePath,\n          data: new Buffer(\n            \"throw new Error(\" + JSON.stringify(message) + \");\\n\",\n            \"utf8\"),\n          lazy: true,\n          error: { message, info },\n        });\n\n        return;\n      }\n\n      buildmessage.error(message, info);\n    }\n  };\n\n  return compileStep;\n};\n"
  },
  {
    "path": "tools/isobuild/compiler-plugin.js",
    "content": "var archinfo = require('../utils/archinfo.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar buildPluginModule = require('./build-plugin.js');\nvar colonConverter = require('../utils/colon-converter.js');\nvar files = require('../fs/files.js');\nvar compiler = require('./compiler.js');\nvar linker = require('./linker.js');\nvar util = require('util');\nvar _ = require('underscore');\nvar Profile = require('../tool-env/profile.js').Profile;\nimport {sha1, readAndWatchFileWithHash} from  '../fs/watch.js';\nimport LRU from 'lru-cache';\nimport Fiber from 'fibers';\nimport {sourceMapLength} from '../utils/utils.js';\nimport {Console} from '../console/console.js';\nimport ImportScanner from './import-scanner.js';\nimport {cssToCommonJS} from \"./css-modules.js\";\nimport Resolver from \"./resolver.js\";\n\nimport { isTestFilePath } from './test-files.js';\n\n// This file implements the new compiler plugins added in Meteor 1.2, which are\n// registered with the Plugin.registerCompiler API.\n//\n// Unlike legacy source handlers (Plugin.registerSourceHandler), compilers run\n// in the context of an entire app. That is to say, they don't run when you run\n// `meteor publish`; whenever they run, they have access to all the files of\n// their type across all packages as well as the app. This allows them to\n// implement cross-file and cross-package inclusion, or config files in the app\n// that affect how packages are processed, among other possibilities.\n//\n// Compilers can specify which extensions or filenames they process. They only\n// process files in packages (or the app) that directly use the plugin's package\n// (or that use it indirectly via the \"imply\" directive); just because compiler\n// plugins act on multiple packages at a time doesn't mean they automatically\n// act on all packages in your app.\n//\n// The CompilerPluginProcessor is the main entry point to this file; it is used\n// by the bundler to run all plugins on a target. It doesn't have much\n// interesting state and perhaps could have just been a function.\n//\n// It receives an ordered list of unibuilds (essentially, packages) from the\n// bundler. It turns them into an ordered list of PackageSourceBatch objects,\n// each of which represents the source files in a single package. Each\n// PackageSourceBatch consists of an ordered list of ResourceSlots representing\n// the resources in that package. The idea here is that, because Meteor executes\n// all JS files in the order produced by the bundler, we need to make sure to\n// maintain the order of packages from the bundler and the order of source files\n// within a package. Each ResourceSlot represents a resource (either a 'source'\n// resource which will be processed by a compiler plugin, or something else like\n// a static asset or some JavaScript produced by a legacy source handler), and\n// when the compiler plugin calls something like `inputFile.addJavaScript` on a\n// file, we replace that source file with the resource produced by the plugin.\n//\n// InputFile is a wrapper around ResourceSlot that is the object presented to\n// the compiler in the plugin. It is part of the documented registerCompiler\n// API.\n\n// Cache the (slightly post-processed) results of linker.fullLink.\nconst CACHE_SIZE = process.env.METEOR_LINKER_CACHE_SIZE || 1024*1024*100;\nconst CACHE_DEBUG = !! process.env.METEOR_TEST_PRINT_LINKER_CACHE_DEBUG;\nconst LINKER_CACHE_SALT = 7; // Increment this number to force relinking.\nconst LINKER_CACHE = new LRU({\n  max: CACHE_SIZE,\n  // Cache is measured in bytes. We don't care about servePath.\n  // Key is JSONification of all options plus all hashes.\n  length: function (files) {\n    return files.reduce((soFar, current) => {\n      return soFar + current.data.length + sourceMapLength(current.sourceMap);\n    }, 0);\n  }\n});\n\nconst serverLibPackages = {\n  // Make sure fibers is defined, if nothing else.\n  fibers: true\n};\n\nfunction populateServerLibPackages() {\n  const devBundlePath = files.getDevBundle();\n  const nodeModulesPath = files.pathJoin(\n    devBundlePath, \"server-lib\", \"node_modules\"\n  );\n\n  files.readdir(nodeModulesPath).forEach(packageName => {\n    const packagePath = files.pathJoin(nodeModulesPath, packageName);\n    const packageStat = files.statOrNull(packagePath);\n    if (packageStat && packageStat.isDirectory()) {\n      serverLibPackages[packageName] = true;\n    }\n  });\n}\n\ntry {\n  populateServerLibPackages();\n} catch (e) {\n  // At least we tried!\n}\n\nexport class CompilerPluginProcessor {\n  constructor({\n    unibuilds,\n    arch,\n    sourceRoot,\n    isopackCache,\n    linkerCacheDir,\n  }) {\n    const self = this;\n\n    self.unibuilds = unibuilds;\n    self.arch = arch;\n    self.sourceRoot = sourceRoot;\n    self.isopackCache = isopackCache;\n\n    self.linkerCacheDir = linkerCacheDir;\n    if (self.linkerCacheDir) {\n      files.mkdir_p(self.linkerCacheDir);\n    }\n  }\n\n  runCompilerPlugins() {\n    const self = this;\n    buildmessage.assertInJob();\n\n    // plugin id -> {sourceProcessor, resourceSlots}\n    var sourceProcessorsWithSlots = {};\n\n    var sourceBatches = _.map(self.unibuilds, function (unibuild) {\n      const { pkg: { name }, arch } = unibuild;\n      const sourceRoot = name\n        && self.isopackCache.getSourceRoot(name, arch)\n        || self.sourceRoot;\n\n      return new PackageSourceBatch(unibuild, self, {\n        sourceRoot,\n        linkerCacheDir: self.linkerCacheDir\n      });\n    });\n\n    // If we failed to match sources with processors, we're done.\n    if (buildmessage.jobHasMessages()) {\n      return [];\n    }\n\n    // Find out which files go with which CompilerPlugins.\n    _.each(sourceBatches, function (sourceBatch) {\n      _.each(sourceBatch.resourceSlots, function (resourceSlot) {\n        var sourceProcessor = resourceSlot.sourceProcessor;\n        // Skip non-sources.\n        if (! sourceProcessor) {\n          return;\n        }\n\n        if (! _.has(sourceProcessorsWithSlots, sourceProcessor.id)) {\n          sourceProcessorsWithSlots[sourceProcessor.id] = {\n            sourceProcessor: sourceProcessor,\n            resourceSlots: []\n          };\n        }\n        sourceProcessorsWithSlots[sourceProcessor.id].resourceSlots.push(\n          resourceSlot);\n      });\n    });\n\n    // Now actually run the handlers.\n    _.each(sourceProcessorsWithSlots, function (data, id) {\n      var sourceProcessor = data.sourceProcessor;\n      var resourceSlots = data.resourceSlots;\n\n      var jobTitle = [\n        \"processing files with \",\n        sourceProcessor.isopack.name,\n        \" (for target \", self.arch, \")\"\n      ].join('');\n\n      Profile.time(\"plugin \"+sourceProcessor.isopack.name, () => {\n        buildmessage.enterJob({\n          title: jobTitle\n        }, function () {\n          var inputFiles = _.map(resourceSlots, function (resourceSlot) {\n            return new InputFile(resourceSlot);\n          });\n\n          var markedMethod = buildmessage.markBoundary(\n            sourceProcessor.userPlugin.processFilesForTarget.bind(\n              sourceProcessor.userPlugin));\n          try {\n            markedMethod(inputFiles);\n          } catch (e) {\n            buildmessage.exception(e);\n          }\n        });\n      });\n    });\n\n    return sourceBatches;\n  }\n}\n\nclass InputFile extends buildPluginModule.InputFile {\n  constructor(resourceSlot) {\n    super();\n    // We use underscored attributes here because this is user-visible\n    // code and we don't want users to be accessing anything that we don't\n    // document.\n    this._resourceSlot = resourceSlot;\n\n    // Map from control file names (e.g. package.json, .babelrc) to\n    // absolute paths, or null to indicate absence.\n    this._controlFileCache = Object.create(null);\n\n    // Map from imported module identifier strings (possibly relative) to\n    // fully require.resolve'd module identifiers.\n    this._resolveCache = Object.create(null);\n  }\n\n  getContentsAsBuffer() {\n    var self = this;\n    return self._resourceSlot.inputResource.data;\n  }\n\n  getPackageName() {\n    var self = this;\n    return self._resourceSlot.packageSourceBatch.unibuild.pkg.name;\n  }\n\n  isPackageFile() {\n    return !! this.getPackageName();\n  }\n\n  isApplicationFile() {\n    return ! this.getPackageName();\n  }\n\n  getSourceRoot() {\n    const sourceRoot = this._resourceSlot.packageSourceBatch.sourceRoot;\n\n    if (! _.isString(sourceRoot)) {\n      const name = this.getPackageName();\n      throw new Error(\n        \"Unknown source root for \" + (\n          name ? \"package \" + name : \"app\"));\n    }\n\n    return sourceRoot;\n  }\n\n  getPathInPackage() {\n    var self = this;\n    return self._resourceSlot.inputResource.path;\n  }\n\n  getFileOptions() {\n    var self = this;\n    // XXX fileOptions only exists on some resources (of type \"source\"). The JS\n    // resources might not have this property.\n    return self._resourceSlot.inputResource.fileOptions || {};\n  }\n\n  readAndWatchFileWithHash(path) {\n    const osPath = files.convertToOSPath(path);\n    const sourceRoot = this.getSourceRoot();\n    const relPath = files.pathRelative(sourceRoot, osPath);\n    if (relPath.startsWith(\"..\")) {\n      throw new Error(\n        `Attempting to read file outside ${\n          this.getPackageName() || \"the app\"}: ${osPath}`\n      );\n    }\n    const sourceBatch = this._resourceSlot.packageSourceBatch;\n    return readAndWatchFileWithHash(\n      sourceBatch.unibuild.watchSet,\n      osPath\n    );\n  }\n\n  readAndWatchFile(path) {\n    return this.readAndWatchFileWithHash(path).contents;\n  }\n\n  // Search ancestor directories for control files (e.g. package.json,\n  // .babelrc), and return the absolute path of the first one found, or\n  // null if the search failed.\n  findControlFile(basename) {\n    let absPath = this._controlFileCache[basename];\n    if (typeof absPath === \"string\") {\n      return absPath;\n    }\n\n    const sourceRoot = this._resourceSlot.packageSourceBatch.sourceRoot;\n    if (! _.isString(sourceRoot)) {\n      return this._controlFileCache[basename] = null;\n    }\n\n    let dir = files.pathDirname(this.getPathInPackage());\n    while (true) {\n      absPath = files.pathJoin(sourceRoot, dir, basename);\n\n      const stat = files.statOrNull(absPath);\n      if (stat && stat.isFile()) {\n        return this._controlFileCache[basename] = absPath;\n      }\n\n      if (files.pathBasename(dir) === \"node_modules\") {\n        // The search for control files should not escape node_modules.\n        return this._controlFileCache[basename] = null;\n      }\n\n      let parentDir = files.pathDirname(dir);\n      if (parentDir === dir) break;\n      dir = parentDir;\n    }\n\n    return this._controlFileCache[basename] = null;\n  }\n\n  _resolveCacheLookup(id, parentPath) {\n    const byId = this._resolveCache[id];\n    return byId && byId[parentPath];\n  }\n\n  _resolveCacheStore(id, parentPath, resolved) {\n    let byId = this._resolveCache[id];\n    if (! byId) {\n      byId = this._resolveCache[id] = Object.create(null);\n    }\n    return byId[parentPath] = resolved;\n  }\n\n  resolve(id, parentPath) {\n    const batch = this._resourceSlot.packageSourceBatch;\n\n    parentPath = parentPath || files.pathJoin(\n      batch.sourceRoot,\n      this.getPathInPackage()\n    );\n\n    let resolved = this._resolveCacheLookup(id, parentPath);\n    if (resolved) {\n      return resolved;\n    }\n\n    const parentStat = files.statOrNull(parentPath);\n    if (! parentStat ||\n        ! parentStat.isFile()) {\n      throw new Error(\"Not a file: \" + parentPath);\n    }\n\n    const resolver = batch.getResolver();\n\n    return this._resolveCacheStore(\n      id, parentPath, resolver.resolve(id, parentPath).id);\n  }\n\n  require(id, parentPath) {\n    return require(this.resolve(id, parentPath));\n  }\n\n  getArch() {\n    return this._resourceSlot.packageSourceBatch.processor.arch;\n  }\n\n  getSourceHash() {\n    return this._resourceSlot.inputResource.hash;\n  }\n\n  /**\n   * @summary Returns the extension that matched the compiler plugin.\n   * The longest prefix is preferred.\n   * @returns {String}\n   */\n  getExtension() {\n    return this._resourceSlot.inputResource.extension;\n  }\n\n  /**\n   * @summary Returns a list of symbols declared as exports in this target. The\n   * result of `api.export('symbol')` calls in target's control file such as\n   * package.js.\n   * @memberof InputFile\n   * @returns {String[]}\n   */\n  getDeclaredExports() {\n    var self = this;\n    return self._resourceSlot.packageSourceBatch.unibuild.declaredExports;\n  }\n\n  /**\n   * @summary Returns a relative path that can be used to form error messages or\n   * other display properties. Can be used as an input to a source map.\n   * @memberof InputFile\n   * @returns {String}\n   */\n  getDisplayPath() {\n    var self = this;\n    return self._resourceSlot.packageSourceBatch.unibuild.pkg._getServePath(self.getPathInPackage());\n  }\n\n  /**\n   * @summary Web targets only. Add a stylesheet to the document. Not available\n   * for linter build plugins.\n   * @param {Object} options\n   * @param {String} options.path The requested path for the added CSS, may not\n   * be satisfied if there are path conflicts.\n   * @param {String} options.data The content of the stylesheet that should be\n   * added.\n   * @param {String|Object} options.sourceMap A stringified JSON\n   * sourcemap, in case the stylesheet was generated from a different\n   * file.\n   * @memberOf InputFile\n   * @instance\n   */\n  addStylesheet(options) {\n    var self = this;\n    if (options.sourceMap && typeof options.sourceMap === 'string') {\n      // XXX remove an anti-XSSI header? \")]}'\\n\"\n      options.sourceMap = JSON.parse(options.sourceMap);\n    }\n    self._resourceSlot.addStylesheet(options);\n  }\n\n  /**\n   * @summary Add JavaScript code. The code added will only see the\n   * namespaces imported by this package as runtime dependencies using\n   * ['api.use'](#PackageAPI-use). If the file being compiled was added\n   * with the bare flag, the resulting JavaScript won't be wrapped in a\n   * closure.\n   * @param {Object} options\n   * @param {String} options.path The path at which the JavaScript file\n   * should be inserted, may not be honored in case of path conflicts.\n   * @param {String} options.data The code to be added.\n   * @param {String|Object} options.sourceMap A stringified JSON\n   * sourcemap, in case the JavaScript file was generated from a\n   * different file.\n   * @memberOf InputFile\n   * @instance\n   */\n  addJavaScript(options) {\n    var self = this;\n    if (options.sourceMap && typeof options.sourceMap === 'string') {\n      // XXX remove an anti-XSSI header? \")]}'\\n\"\n      options.sourceMap = JSON.parse(options.sourceMap);\n    }\n    self._resourceSlot.addJavaScript(options);\n  }\n\n  /**\n   * @summary Add a file to serve as-is to the browser or to include on\n   * the browser, depending on the target. On the web, it will be served\n   * at the exact path requested. For server targets, it can be retrieved\n   * using `Assets.getText` or `Assets.getBinary`.\n   * @param {Object} options\n   * @param {String} options.path The path at which to serve the asset.\n   * @param {Buffer|String} options.data The data that should be placed in the\n   * file.\n   * @param {String} [options.hash] Optionally, supply a hash for the output\n   * file.\n   * @memberOf InputFile\n   * @instance\n   */\n  addAsset(options) {\n    var self = this;\n    self._resourceSlot.addAsset(options);\n  }\n\n  /**\n   * @summary Works in web targets only. Add markup to the `head` or `body`\n   * section of the document.\n   * @param  {Object} options\n   * @param {String} options.section Which section of the document should\n   * be appended to. Can only be \"head\" or \"body\".\n   * @param {String} options.data The content to append.\n   * @memberOf InputFile\n   * @instance\n   */\n  addHtml(options) {\n    var self = this;\n    self._resourceSlot.addHtml(options);\n  }\n\n  _reportError(message, info) {\n    if (this.getFileOptions().lazy === true) {\n      // Files with fileOptions.lazy === true were not explicitly added to\n      // the source batch via api.addFiles or api.mainModule, so any\n      // compilation errors should not be fatal until the files are\n      // actually imported by the ImportScanner. Attempting compilation is\n      // still important for lazy files that might end up being imported\n      // later, which is why we defang the error here, instead of avoiding\n      // compilation preemptively. Note also that exceptions thrown by the\n      // compiler will still cause build errors.\n      this._resourceSlot.addError(message, info);\n    } else {\n      super._reportError(message, info);\n    }\n  }\n}\n\nclass ResourceSlot {\n  constructor(unibuildResourceInfo,\n              sourceProcessor,\n              packageSourceBatch) {\n    const self = this;\n    // XXX ideally this should be an classy object, but it's not.\n    self.inputResource = unibuildResourceInfo;\n    // Everything but JS.\n    self.outputResources = [];\n    // JS, which gets linked together at the end.\n    self.jsOutputResources = [];\n    self.sourceProcessor = sourceProcessor;\n    self.packageSourceBatch = packageSourceBatch;\n\n    if (self.inputResource.type === \"source\") {\n      if (sourceProcessor) {\n        // If we have a sourceProcessor, it will handle the adding of the\n        // final processed JavaScript.\n      } else if (self.inputResource.extension === \"js\") {\n        // If there is no sourceProcessor for a .js file, add the source\n        // directly to the output. #HardcodeJs\n        self.addJavaScript({\n          // XXX it's a shame to keep converting between Buffer and string, but\n          // files.convertToStandardLineEndings only works on strings for now\n          data: self.inputResource.data.toString('utf8'),\n          path: self.inputResource.path,\n          hash: self.inputResource.hash,\n          bare: self.inputResource.fileOptions &&\n            (self.inputResource.fileOptions.bare ||\n             // XXX eventually get rid of backward-compatibility \"raw\" name\n             // XXX COMPAT WITH 0.6.4\n             self.inputResource.fileOptions.raw)\n        });\n      }\n    } else {\n      if (sourceProcessor) {\n        throw Error(\"sourceProcessor for non-source? \" +\n                    JSON.stringify(unibuildResourceInfo));\n      }\n      // Any resource that isn't handled by compiler plugins just gets passed\n      // through.\n      if (self.inputResource.type === \"js\") {\n        let resource = self.inputResource;\n        if (! _.isString(resource.sourcePath)) {\n          resource.sourcePath = self.inputResource.path;\n        }\n        if (! _.isString(resource.targetPath)) {\n          resource.targetPath = resource.sourcePath;\n        }\n        self.jsOutputResources.push(resource);\n      } else {\n        self.outputResources.push(self.inputResource);\n      }\n    }\n  }\n\n  _getOption(name, options) {\n    if (options && _.has(options, name)) {\n      return options[name];\n    }\n    const fileOptions = this.inputResource.fileOptions;\n    return fileOptions && fileOptions[name];\n  }\n\n  _isLazy(options) {\n    let lazy = this._getOption(\"lazy\", options);\n\n    if (typeof lazy === \"boolean\") {\n      return lazy;\n    }\n\n    // If file.lazy was not previously defined, mark the file lazy if\n    // it is contained by an imports directory. Note that any files\n    // contained by a node_modules directory will already have been\n    // marked lazy in PackageSource#_inferFileOptions. Same for\n    // non-test files if running (non-full-app) tests (`meteor test`)\n    if (!this.packageSourceBatch.useMeteorInstall) {\n      return false;\n    }\n\n    const splitPath = this.inputResource.path.split(files.pathSep);\n    const isInImports = splitPath.indexOf(\"imports\") >= 0;\n\n    if (global.testCommandMetadata &&\n        (global.testCommandMetadata.isTest ||\n         global.testCommandMetadata.isAppTest)) {\n      // test files should always be included, if we're running app\n      // tests.\n      return isInImports && !isTestFilePath(this.inputResource.path);\n    } else {\n      return isInImports;\n    }\n  }\n\n  addStylesheet(options) {\n    const self = this;\n    if (! self.sourceProcessor) {\n      throw Error(\"addStylesheet on non-source ResourceSlot?\");\n    }\n\n    const data = files.convertToStandardLineEndings(options.data);\n    const useMeteorInstall = self.packageSourceBatch.useMeteorInstall;\n    const sourcePath = this.inputResource.path;\n    const targetPath = options.path || sourcePath;\n    const resource = {\n      refreshable: true,\n      sourcePath,\n      targetPath,\n      servePath: self.packageSourceBatch.unibuild.pkg._getServePath(targetPath),\n      hash: sha1(data),\n      lazy: this._isLazy(options),\n    };\n\n    if (useMeteorInstall && resource.lazy) {\n      // If the current packageSourceBatch supports modules, and this CSS\n      // file is lazy, add it as a lazy JS module instead of adding it\n      // unconditionally as a CSS resource, so that it can be imported\n      // when needed.\n      resource.type = \"js\";\n      resource.data =\n        new Buffer(cssToCommonJS(data, resource.hash), \"utf8\");\n\n      self.jsOutputResources.push(resource);\n\n    } else {\n      // Eager CSS is added unconditionally to a combined <style> tag at\n      // the beginning of the <head>. If the corresponding module ever\n      // gets imported, its module.exports object should be an empty stub,\n      // rather than a <style> node added dynamically to the <head>.\n      self.jsOutputResources.push({\n        ...resource,\n        type: \"js\",\n        data: new Buffer(\n          \"// These styles have already been applied to the document.\\n\",\n          \"utf8\"),\n        // If a compiler plugin calls addJavaScript with the same\n        // sourcePath, that code should take precedence over this empty\n        // stub, so this property marks the resource as disposable.\n        emtpyStub: true,\n        lazy: true,\n      });\n\n      resource.type = \"css\";\n      resource.data = new Buffer(data, 'utf8'),\n\n      // XXX do we need to call convertSourceMapPaths here like we did\n      //     in legacy handlers?\n      resource.sourceMap = options.sourceMap;\n\n      self.outputResources.push(resource);\n    }\n  }\n\n  addJavaScript(options) {\n    const self = this;\n    // #HardcodeJs this gets called by constructor in the \"js\" case\n    if (! self.sourceProcessor && self.inputResource.extension !== \"js\") {\n      throw Error(\"addJavaScript on non-source ResourceSlot?\");\n    }\n\n    let sourcePath = self.inputResource.path;\n    if (_.has(options, \"sourcePath\") &&\n        typeof options.sourcePath === \"string\") {\n      sourcePath = options.sourcePath;\n    }\n\n    const targetPath = options.path || sourcePath;\n\n    var data = new Buffer(\n      files.convertToStandardLineEndings(options.data), 'utf8');\n\n    self.jsOutputResources.push({\n      type: \"js\",\n      data: data,\n      sourcePath,\n      targetPath,\n      servePath: self.packageSourceBatch.unibuild.pkg._getServePath(targetPath),\n      // XXX should we allow users to be trusted and specify a hash?\n      hash: sha1(data),\n      // XXX do we need to call convertSourceMapPaths here like we did\n      //     in legacy handlers?\n      sourceMap: options.sourceMap,\n      // intentionally preserve a possible `undefined` value for files\n      // in apps, rather than convert it into `false` via `!!`\n      lazy: self._isLazy(options),\n      bare: !! self._getOption(\"bare\", options),\n      mainModule: !! self._getOption(\"mainModule\", options),\n    });\n  }\n\n  addAsset(options) {\n    const self = this;\n    if (! self.sourceProcessor) {\n      throw Error(\"addAsset on non-source ResourceSlot?\");\n    }\n\n    if (! (options.data instanceof Buffer)) {\n      if (_.isString(options.data)) {\n        options.data = new Buffer(options.data);\n      } else {\n        throw new Error(\"'data' option to addAsset must be a Buffer or String.\");\n      }\n    }\n\n    self.outputResources.push({\n      type: 'asset',\n      data: options.data,\n      path: options.path,\n      servePath: self.packageSourceBatch.unibuild.pkg._getServePath(\n        options.path),\n      hash: sha1(options.data),\n      lazy: self._isLazy(options),\n    });\n  }\n\n  addHtml(options) {\n    const self = this;\n    const unibuild = self.packageSourceBatch.unibuild;\n\n    if (! archinfo.matches(unibuild.arch, \"web\")) {\n      throw new Error(\"Document sections can only be emitted to \" +\n                      \"web targets: \" + self.inputResource.path);\n    }\n    if (options.section !== \"head\" && options.section !== \"body\") {\n      throw new Error(\"'section' must be 'head' or 'body': \" +\n                      self.inputResource.path);\n    }\n    if (typeof options.data !== \"string\") {\n      throw new Error(\"'data' option to appendDocument must be a string: \" +\n                      self.inputResource.path);\n    }\n\n    self.outputResources.push({\n      type: options.section,\n      data: new Buffer(files.convertToStandardLineEndings(options.data), 'utf8'),\n      lazy: self._isLazy(options),\n    });\n  }\n\n  addError(message, info) {\n    // If this file is ever actually imported, only then will we report\n    // the error. Use this.jsOutputResources because that's what the\n    // ImportScanner deals with.\n    this.jsOutputResources.push({\n      type: \"js\",\n      sourcePath: this.inputResource.path,\n      targetPath: this.inputResource.path,\n      servePath: this.inputResource.path,\n      data: new Buffer(\n        \"throw new Error(\" + JSON.stringify(message) + \");\\n\",\n        \"utf8\"),\n      lazy: true,\n      error: { message, info },\n    });\n  }\n}\n\nexport class PackageSourceBatch {\n  constructor(unibuild, processor, {\n    sourceRoot,\n    linkerCacheDir,\n  }) {\n    const self = this;\n    buildmessage.assertInJob();\n\n    self.unibuild = unibuild;\n    self.processor = processor;\n    self.sourceRoot = sourceRoot;\n    self.linkerCacheDir = linkerCacheDir;\n    self.importExtensions = [\".js\", \".json\"];\n    self._resolver = null;\n\n    var sourceProcessorSet = self._getSourceProcessorSet();\n\n    self.resourceSlots = [];\n    unibuild.resources.forEach(function (resource) {\n      let sourceProcessor = null;\n      if (resource.type === \"source\") {\n        var extension = resource.extension;\n        if (extension === null) {\n          const filename = files.pathBasename(resource.path);\n          sourceProcessor = sourceProcessorSet.getByFilename(filename);\n          if (! sourceProcessor) {\n            buildmessage.error(\n              `no plugin found for ${ resource.path } in ` +\n                `${ unibuild.pkg.displayName() }; a plugin for ${ filename } ` +\n                `was active when it was published but none is now`);\n            return;\n            // recover by ignoring\n          }\n        } else {\n          sourceProcessor = sourceProcessorSet.getByExtension(extension);\n          // If resource.extension === 'js', it's ok for there to be no\n          // sourceProcessor, since we #HardcodeJs in ResourceSlot.\n          if (! sourceProcessor && extension !== 'js') {\n            buildmessage.error(\n              `no plugin found for ${ resource.path } in ` +\n                `${ unibuild.pkg.displayName() }; a plugin for *.${ extension } ` +\n                `was active when it was published but none is now`);\n            return;\n            // recover by ignoring\n          }\n\n          self.addImportExtension(extension);\n        }\n      }\n\n      self.resourceSlots.push(new ResourceSlot(resource, sourceProcessor, self));\n    });\n\n    // Compute imports by merging the exports of all of the packages we\n    // use. Note that in the case of conflicting symbols, later packages get\n    // precedence.\n    //\n    // We don't get imports from unordered dependencies (since they\n    // may not be defined yet) or from\n    // weak/debugOnly/prodOnly/testOnly dependencies (because the\n    // meaning of a name shouldn't be affected by the non-local\n    // decision of whether or not an unrelated package in the target\n    // depends on something).\n    self.importedSymbolToPackageName = {}; // map from symbol to supplying package name\n\n    compiler.eachUsedUnibuild({\n      dependencies: self.unibuild.uses,\n      arch: self.processor.arch,\n      isopackCache: self.processor.isopackCache,\n      skipUnordered: true,\n      // don't import symbols from debugOnly, prodOnly and testOnly packages, because\n      // if the package is not linked it will cause a runtime error.\n      // the code must access them with `Package[\"my-package\"].MySymbol`.\n      skipDebugOnly: true,\n      skipProdOnly: true,\n      skipTestOnly: true,\n    }, depUnibuild => {\n      _.each(depUnibuild.declaredExports, function (symbol) {\n        // Slightly hacky implementation of test-only exports.\n        if (! symbol.testOnly || self.unibuild.pkg.isTest) {\n          self.importedSymbolToPackageName[symbol.name] = depUnibuild.pkg.name;\n        }\n      });\n    });\n\n    self.useMeteorInstall =\n      _.isString(self.sourceRoot) &&\n      self.processor.isopackCache.uses(\n        self.unibuild.pkg,\n        \"modules\",\n        self.unibuild.arch\n      );\n  }\n\n  addImportExtension(extension) {\n    extension = extension.toLowerCase();\n\n    if (! extension.startsWith(\".\")) {\n      extension = \".\" + extension;\n    }\n\n    if (this.importExtensions.indexOf(extension) < 0) {\n      this.importExtensions.push(extension);\n    }\n  }\n\n  getResolver() {\n    if (this._resolver) {\n      return this._resolver;\n    }\n\n    const nmds = this.unibuild.nodeModulesDirectories;\n    const nodeModulesPaths = [];\n\n    _.each(nmds, (nmd, path) => {\n      if (! nmd.local) {\n        nodeModulesPaths.push(\n          files.convertToOSPath(path.replace(/\\/$/g, \"\")));\n      }\n    });\n\n    return this._resolver = new Resolver({\n      sourceRoot: this.sourceRoot,\n      targetArch: this.processor.arch,\n      extensions: this.importExtensions,\n      nodeModulesPaths,\n      watchSet: this.unibuild.watchSet,\n      onMissing(id) {\n        const error = new Error(\"Cannot find module '\" + id + \"'\");\n        error.code = \"MODULE_NOT_FOUND\";\n        throw error;\n      }\n    });\n  }\n\n  _getSourceProcessorSet() {\n    const self = this;\n\n    buildmessage.assertInJob();\n\n    var isopack = self.unibuild.pkg;\n    const activePluginPackages = compiler.getActivePluginPackages(isopack, {\n      uses: self.unibuild.uses,\n      isopackCache: self.processor.isopackCache\n    });\n    const sourceProcessorSet = new buildPluginModule.SourceProcessorSet(\n      isopack.displayName(), { hardcodeJs: true });\n\n    _.each(activePluginPackages, function (otherPkg) {\n      otherPkg.ensurePluginsInitialized();\n\n      sourceProcessorSet.merge(\n        otherPkg.sourceProcessors.compiler, {arch: self.processor.arch});\n    });\n\n    return sourceProcessorSet;\n  }\n\n  // Returns a map from package names to arrays of JS output files.\n  static computeJsOutputFilesMap(sourceBatches) {\n    const map = new Map;\n\n    sourceBatches.forEach(batch => {\n      const name = batch.unibuild.pkg.name || null;\n      const inputFiles = [];\n\n      batch.resourceSlots.forEach(slot => {\n        inputFiles.push(...slot.jsOutputResources);\n      });\n\n      map.set(name, {\n        files: inputFiles,\n        importExtensions: batch.importExtensions,\n      });\n    });\n\n    if (! map.has(\"modules\")) {\n      // In the unlikely event that no package is using the modules\n      // package, then the map is already complete, and we don't need to\n      // do any import scanning.\n      return map;\n    }\n\n    // Append install(<name>) calls to the install-packages.js file in the\n    // modules package for every Meteor package name used.\n    map.get(\"modules\").files.some(file => {\n      if (file.sourcePath !== \"install-packages.js\") {\n        return false;\n      }\n\n      const meteorPackageInstalls = [];\n\n      map.forEach((info, name) => {\n        if (! name) return;\n\n        let mainModule = _.find(info.files, file => file.mainModule);\n        mainModule = mainModule ?\n          `meteor/${name}/${mainModule.targetPath}` : false;\n\n        meteorPackageInstalls.push(\n          \"install(\" + JSON.stringify(name) +\n            (mainModule ? \", \" + JSON.stringify(mainModule) : '') +\n          \");\\n\"\n        );\n      });\n\n      if (meteorPackageInstalls.length === 0) {\n        return false;\n      }\n\n      file.data = new Buffer(\n        file.data.toString(\"utf8\") + \"\\n\" +\n          meteorPackageInstalls.join(\"\"),\n        \"utf8\"\n      );\n\n      file.hash = sha1(file.data);\n\n      return true;\n    });\n\n    const allMissingNodeModules = Object.create(null);\n    // Records the subset of allMissingNodeModules that were successfully\n    // relocated to a source batch that could handle them.\n    const allRelocatedNodeModules = Object.create(null);\n    const scannerMap = new Map;\n\n    sourceBatches.forEach(batch => {\n      const name = batch.unibuild.pkg.name || null;\n      const isApp = ! name;\n\n      if (! batch.useMeteorInstall && ! isApp) {\n        // If this batch represents a package that does not use the module\n        // system, then we don't need to scan its dependencies.\n        return;\n      }\n\n      const nodeModulesPaths = [];\n      _.each(batch.unibuild.nodeModulesDirectories, (nmd, sourcePath) => {\n        if (! nmd.local) {\n          // Local node_modules directories will be found by the\n          // ImportScanner, but we need to tell it about any external\n          // node_modules directories (e.g. .npm/package/node_modules).\n          nodeModulesPaths.push(sourcePath);\n        }\n      });\n\n      const scanner = new ImportScanner({\n        name,\n        bundleArch: batch.processor.arch,\n        extensions: batch.importExtensions,\n        sourceRoot: batch.sourceRoot,\n        nodeModulesPaths,\n        watchSet: batch.unibuild.watchSet,\n      });\n\n      scanner.addInputFiles(map.get(name).files);\n\n      if (batch.useMeteorInstall) {\n        scanner.scanImports();\n        _.extend(allMissingNodeModules, scanner.allMissingNodeModules);\n      }\n\n      scannerMap.set(name, scanner);\n    });\n\n    function handleMissing(missingNodeModules) {\n      const missingMap = new Map;\n\n      _.each(missingNodeModules, (info, id) => {\n        const parts = id.split(\"/\");\n        let name = null;\n\n        if (parts[0] === \"meteor\") {\n          if (parts.length > 2) {\n            name = parts[1];\n            parts[1] = \".\";\n            id = parts.slice(1).join(\"/\");\n          } else {\n            return;\n          }\n        }\n\n        if (! scannerMap.has(name)) {\n          return;\n        }\n\n        if (! missingMap.has(name)) {\n          missingMap.set(name, {});\n        }\n\n        const missing = missingMap.get(name);\n        if (! _.has(missing, id) ||\n            ! info.possiblySpurious) {\n          // Allow any non-spurious identifier to replace an existing\n          // possibly spurious identifier.\n          missing[id] = info;\n        }\n      });\n\n      const nextMissingNodeModules = Object.create(null);\n\n      missingMap.forEach((ids, name) => {\n        const { newlyAdded, newlyMissing } =\n          scannerMap.get(name).addNodeModules(ids);\n        _.extend(allRelocatedNodeModules, newlyAdded);\n        _.extend(nextMissingNodeModules, newlyMissing);\n      });\n\n      if (! _.isEmpty(nextMissingNodeModules)) {\n        handleMissing(nextMissingNodeModules);\n      }\n    }\n\n    handleMissing(allMissingNodeModules);\n\n    _.each(allRelocatedNodeModules, (info, id) => {\n      delete allMissingNodeModules[id];\n    });\n\n    this._warnAboutMissingModules(allMissingNodeModules);\n\n    scannerMap.forEach((scanner, name) => {\n      const isApp = ! name;\n\n      if (isApp) {\n        const appFilesWithoutNodeModules = [];\n\n        scanner.getOutputFiles().forEach(file => {\n          const parts = file.installPath.split(\"/\");\n          const nodeModulesIndex = parts.indexOf(\"node_modules\");\n\n          if (nodeModulesIndex === -1 || (nodeModulesIndex === 0 &&\n                                          parts[1] === \"meteor\")) {\n            appFilesWithoutNodeModules.push(file);\n          } else {\n            // This file is going to be installed in a node_modules\n            // directory, so we move it to the modules bundle so that it\n            // can be imported by any package that uses the modules\n            // package. Note that this includes all files within any\n            // node_modules directory in the app, even though packages in\n            // client/node_modules will not be importable by Meteor\n            // packages, because it's important for all npm packages in\n            // the app to share the same limited scope (i.e. the scope of\n            // the modules package).\n            map.get(\"modules\").files.push(file);\n          }\n        });\n\n        map.get(null).files = appFilesWithoutNodeModules;\n\n      } else {\n        map.get(name).files = scanner.getOutputFiles();\n      }\n    });\n\n    return map;\n  }\n\n  static _warnAboutMissingModules(missingNodeModules) {\n    const topLevelMissingIDs = {};\n    const warnings = [];\n\n    _.each(missingNodeModules, (info, id) => {\n      if (info.packageName) {\n        // Silence warnings generated by Meteor packages, since package\n        // authors can be trusted to test their packages, and may have\n        // different/better approaches to ensuring their dependencies are\n        // available. This blanket check makes some of the checks below\n        // redundant, but I would rather create a bit of dead code than\n        // risk introducing bugs when/if this check is reverted.\n        return;\n      }\n\n      if (info.possiblySpurious) {\n        // Silence warnings for missing dependencies in Browserify/Webpack\n        // bundles, since we can reasonably conclude at this point that\n        // they are false positives.\n        return;\n      }\n\n      if (id in serverLibPackages &&\n          archinfo.matches(info.bundleArch, \"os\")) {\n        // Packages in dev_bundle/server-lib/node_modules can always be\n        // resolved at runtime on the server, so we don't need to warn\n        // about them here.\n        return;\n      }\n\n      if (id === \"meteor-node-stubs\" &&\n          info.packageName === \"modules\" &&\n          info.parentPath.endsWith(\"stubs.js\")) {\n        // Don't warn about the require(\"meteor-node-stubs\") call in\n        // packages/modules/stubs.js.\n        return;\n      }\n\n      const parts = id.split(\"/\");\n\n      if (\"./\".indexOf(id.charAt(0)) < 0) {\n        const packageDir = parts[0];\n        if (packageDir === \"meteor\") {\n          // Don't print warnings for uninstalled Meteor packages.\n          return;\n        }\n\n        if (packageDir === \"babel-runtime\") {\n          // Don't print warnings for babel-runtime/helpers/* modules,\n          // since we provide most of those.\n          return;\n        }\n\n        if (! _.has(topLevelMissingIDs, packageDir)) {\n          // This information will be used to recommend installing npm\n          // packages below.\n          topLevelMissingIDs[packageDir] = id;\n        }\n\n        if (id.startsWith(\"meteor-node-stubs/deps/\")) {\n          // Instead of printing a warning that meteor-node-stubs/deps/fs\n          // is missing, warn about the \"fs\" module, but still recommend\n          // installing meteor-node-stubs via npm below.\n          id = parts.slice(2).join(\"/\");\n        }\n\n      } else if (info.packageName) {\n        // Disable warnings about relative module resolution failures in\n        // Meteor packages, since there's not much the application\n        // developer can do about those.\n        return;\n      }\n\n      warnings.push(`  ${JSON.stringify(id)} in ${\n        info.parentPath} (${info.bundleArch})`);\n    });\n\n    if (warnings.length > 0) {\n      Console.rawWarn(\"\\nUnable to resolve some modules:\\n\\n\");\n      warnings.forEach(text => Console.warn(text));\n      Console.warn();\n\n      const topLevelKeys = Object.keys(topLevelMissingIDs);\n      if (topLevelKeys.length > 0) {\n        Console.warn(\"If you notice problems related to these missing modules, consider running:\");\n        Console.warn();\n        Console.warn(\"  meteor npm install --save \" + topLevelKeys.join(\" \"));\n        Console.warn();\n      }\n    }\n  }\n\n  // Called by bundler's Target._emitResources.  It returns the actual resources\n  // that end up in the program for this package.  By this point, it knows what\n  // its dependencies are and what their exports are, so it can set up\n  // linker-style imports and exports.\n  getResources({\n    files: jsResources,\n    importExtensions = [\".js\", \".json\"],\n  }) {\n    buildmessage.assertInJob();\n\n    function flatten(arrays) {\n      return Array.prototype.concat.apply([], arrays);\n    }\n\n    const resources = flatten(_.pluck(this.resourceSlots, 'outputResources'));\n\n    resources.push(...this._linkJS(jsResources || flatten(\n      _.pluck(this.resourceSlots, 'jsOutputResources')\n    ), this.useMeteorInstall && {\n      extensions: importExtensions\n    }));\n\n    return resources;\n  }\n\n  _linkJS(jsResources, meteorInstallOptions) {\n    const self = this;\n    buildmessage.assertInJob();\n\n    var bundleArch = self.processor.arch;\n\n    // Run the linker.\n    const isApp = ! self.unibuild.pkg.name;\n    const isWeb = archinfo.matches(self.unibuild.arch, \"web\");\n    const linkerOptions = {\n      useGlobalNamespace: isApp,\n      meteorInstallOptions,\n      // I was confused about this, so I am leaving a comment -- the\n      // combinedServePath is either [pkgname].js or [pluginName]:plugin.js.\n      // XXX: If we change this, we can get rid of source arch names!\n      combinedServePath: isApp ? \"/app.js\" :\n        \"/packages/\" + colonConverter.convert(\n          self.unibuild.pkg.name +\n            (self.unibuild.kind === \"main\" ? \"\" : (\":\" + self.unibuild.kind)) +\n            \".js\"),\n      name: self.unibuild.pkg.name || null,\n      declaredExports: _.pluck(self.unibuild.declaredExports, 'name'),\n      imports: self.importedSymbolToPackageName,\n      // XXX report an error if there is a package called global-imports\n      importStubServePath: isApp && '/packages/global-imports.js',\n      includeSourceMapInstructions: isWeb,\n      noLineNumbers: !isWeb\n    };\n\n    const cacheKey = sha1(JSON.stringify({\n      LINKER_CACHE_SALT,\n      linkerOptions,\n      files: jsResources.map((inputFile) => {\n        return {\n          hash: inputFile.hash,\n          installPath: inputFile.installPath,\n          sourceMap: !! inputFile.sourceMap,\n          mainModule: inputFile.mainModule,\n          imported: inputFile.imported,\n          lazy: inputFile.lazy,\n          bare: inputFile.bare,\n        };\n      })\n    }));\n\n    {\n      const inMemoryCached = LINKER_CACHE.get(cacheKey);\n      if (inMemoryCached) {\n        if (CACHE_DEBUG) {\n          console.log('LINKER IN-MEMORY CACHE HIT:',\n                      linkerOptions.name, bundleArch);\n        }\n        return inMemoryCached;\n      }\n    }\n\n    const cacheFilename = self.linkerCacheDir && files.pathJoin(\n      self.linkerCacheDir, cacheKey + '.cache');\n\n    // The return value from _linkJS includes Buffers, but we want everything to\n    // be JSON for writing to the disk cache. This function converts the string\n    // version to the Buffer version.\n    function bufferifyJSONReturnValue(resources) {\n      resources.forEach((r) => {\n        r.data = new Buffer(r.data, 'utf8');\n      });\n    }\n\n    if (cacheFilename) {\n      let diskCached = null;\n      try {\n        diskCached = files.readJSONOrNull(cacheFilename);\n      } catch (e) {\n        // Ignore JSON parse errors; pretend there was no cache.\n        if (!(e instanceof SyntaxError)) {\n          throw e;\n        }\n      }\n      if (diskCached && diskCached instanceof Array) {\n        // Fix the non-JSON part of our return value.\n        bufferifyJSONReturnValue(diskCached);\n        if (CACHE_DEBUG) {\n          console.log('LINKER DISK CACHE HIT:', linkerOptions.name, bundleArch);\n        }\n        // Add the bufferized value of diskCached to the in-memory LRU cache\n        // so we don't have to go to disk next time.\n        LINKER_CACHE.set(cacheKey, diskCached);\n        return diskCached;\n      }\n    }\n\n    if (CACHE_DEBUG) {\n      console.log('LINKER CACHE MISS:', linkerOptions.name, bundleArch);\n    }\n\n    // nb: linkedFiles might be aliased to an entry in LINKER_CACHE, so don't\n    // mutate anything from it.\n    let canCache = true;\n    let linkedFiles = null;\n    buildmessage.enterJob('linking', () => {\n      linkedFiles = linker.fullLink(jsResources, linkerOptions);\n      if (buildmessage.jobHasMessages()) {\n        canCache = false;\n      }\n    });\n    // Add each output as a resource\n    const ret = linkedFiles.map((file) => {\n      const sm = (typeof file.sourceMap === 'string')\n        ? JSON.parse(file.sourceMap) : file.sourceMap;\n      return {\n        type: \"js\",\n        // This is a string... but we will convert it to a Buffer\n        // before returning from the method (but after writing\n        // to cache).\n        data: file.source,\n        servePath: file.servePath,\n        sourceMap: sm\n      };\n    });\n\n    let retAsJSON;\n    if (canCache && cacheFilename) {\n      retAsJSON = JSON.stringify(ret);\n    }\n\n    // Convert strings to buffers, now that we've serialized it.\n    bufferifyJSONReturnValue(ret);\n\n    if (canCache) {\n      LINKER_CACHE.set(cacheKey, ret);\n      if (cacheFilename) {\n        // Write asynchronously.\n        Fiber(() => files.writeFileAtomically(cacheFilename, retAsJSON)).run();\n      }\n    }\n\n    return ret;\n  }\n}\n\n_.each([\n  \"getResources\",\n  \"_linkJS\",\n], method => {\n  const proto = PackageSourceBatch.prototype;\n  proto[method] = Profile(\n    \"PackageSourceBatch#\" + method,\n    proto[method]\n  );\n});\n\n// static methods to measure in profile\n_.each([\n  \"computeJsOutputFilesMap\"\n], method => {\n  PackageSourceBatch[method] = Profile(\n    \"PackageSourceBatch.\" + method,\n    PackageSourceBatch[method]);\n});\n"
  },
  {
    "path": "tools/isobuild/compiler.js",
    "content": "var _ = require('underscore');\n\nvar archinfo = require('../utils/archinfo.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar bundler = require('./bundler.js');\nvar isopack = require('./isopack.js');\nvar meteorNpm = require('./meteor-npm.js');\nvar watch = require('../fs/watch.js');\nvar Console = require('../console/console.js').Console;\nvar files = require('../fs/files.js');\nvar colonConverter = require('../utils/colon-converter.js');\nvar linterPluginModule = require('./linter-plugin.js');\nvar compileStepModule = require('./compiler-deprecated-compile-step.js');\nvar Profile = require('../tool-env/profile.js').Profile;\nimport { SourceProcessorSet } from './build-plugin.js';\n\nvar compiler = exports;\n\n// Whenever you change anything about the code that generates isopacks, bump\n// this version number. The idea is that the \"format\" field of the isopack\n// JSON file only changes when the actual specified structure of the\n// isopack/unibuild changes, but this version (which is build-tool-specific)\n// can change when the the contents (not structure) of the built output\n// changes. So eg, if we improve the linker's static analysis, this should be\n// bumped.\n//\n// You should also update this whenever you update any of the packages used\n// directly by the isopack creation process since they do not end up as watched\n// dependencies. (At least for now, packages only used in target creation (eg\n// minifiers) don't require you to update BUILT_BY, though you will need to quit\n// and rerun \"meteor run\".)\ncompiler.BUILT_BY = 'meteor/21';\n\n// This is a list of all possible architectures that a build can target. (Client\n// is expanded into 'web.browser' and 'web.cordova')\ncompiler.ALL_ARCHES = [ \"os\", \"web.browser\", \"web.cordova\" ];\n\ncompiler.compile = Profile(function (packageSource, options) {\n  return `compiler.compile(${ packageSource.name || 'the app' })`;\n}, function (packageSource, options) {\n  buildmessage.assertInCapture();\n\n  var packageMap = options.packageMap;\n  var isopackCache = options.isopackCache;\n  var includeCordovaUnibuild = options.includeCordovaUnibuild;\n\n  var pluginWatchSet = packageSource.pluginWatchSet.clone();\n  var plugins = {};\n\n  var pluginProviderPackageNames = {};\n\n  // Build plugins\n  _.each(packageSource.pluginInfo, function (info) {\n    buildmessage.enterJob({\n      title: \"building plugin `\" + info.name +\n        \"` in package `\" + packageSource.name + \"`\",\n      rootPath: packageSource.sourceRoot\n    }, function () {\n      // XXX we should probably also pass options.noLineNumbers into\n      //     buildJsImage so it can pass it back to its call to\n      //     compiler.compile\n      var buildResult = bundler.buildJsImage({\n        name: info.name,\n        packageMap: packageMap,\n        isopackCache: isopackCache,\n        use: info.use,\n        sourceRoot: packageSource.sourceRoot,\n        sources: info.sources,\n        // While we're not actually \"serving\" the file, the serveRoot is used to\n        // calculate file names in source maps.\n        serveRoot: 'packages/' + packageSource.name,\n        npmDependencies: info.npmDependencies,\n        // Plugins have their own npm dependencies separate from the\n        // rest of the package, so they need their own separate npm\n        // shrinkwrap and cache state.\n        npmDir: files.pathResolve(\n          files.pathJoin(packageSource.sourceRoot, '.npm', 'plugin', info.name))\n      });\n      // Add this plugin's dependencies to our \"plugin dependency\"\n      // WatchSet. buildResult.watchSet will end up being the merged\n      // watchSets of all of the unibuilds of the plugin -- plugins have\n      // only one unibuild and this should end up essentially being just\n      // the source files of the plugin.\n      //\n      // Note that we do this even on error, so that you can fix the error\n      // and have the runner restart.\n      pluginWatchSet.merge(buildResult.watchSet);\n\n      if (buildmessage.jobHasMessages()) {\n        return;\n      }\n\n      _.each(buildResult.usedPackageNames, function (packageName) {\n        pluginProviderPackageNames[packageName] = true;\n      });\n\n      // Register the built plugin's code.\n      if (!_.has(plugins, info.name)) {\n        plugins[info.name] = {};\n      }\n      plugins[info.name][buildResult.image.arch] = buildResult.image;\n    });\n  });\n\n  // Grab any npm dependencies. Keep them in a cache in the package\n  // source directory so we don't have to do this from scratch on\n  // every build.\n  //\n  // Go through a specialized npm dependencies update process,\n  // ensuring we don't get new versions of any (sub)dependencies. This\n  // process also runs mostly safely multiple times in parallel (which\n  // could happen if you have two apps running locally using the same\n  // package).\n  //\n  // We run this even if we have no dependencies, because we might\n  // need to delete dependencies we used to have.\n  var nodeModulesPath = null;\n  if (packageSource.npmCacheDirectory) {\n    if (meteorNpm.updateDependencies(packageSource.name,\n                                     packageSource.npmCacheDirectory,\n                                     packageSource.npmDependencies)) {\n      nodeModulesPath = files.pathJoin(\n        packageSource.npmCacheDirectory,\n        'node_modules'\n      );\n    }\n  }\n\n  // Find all the isobuild:* pseudo-packages that this package depends on. Why\n  // do we need to do this? Well, we actually load the plugins in this package\n  // before we've fully compiled the package --- plugins are loaded before the\n  // compiler builds the unibuilds in this package (because plugins are allowed\n  // to act on the package itself). But when we load plugins, we need to know if\n  // the package depends on (eg) isobuild:compiler-plugin, to know if the plugin\n  // is allowed to call Plugin.registerCompiler. At this point, the Isopack\n  // object doesn't yet have any unibuilds... but isopack.js doesn't have access\n  // to the PackageSource either (because it needs to work with both\n  // compiled-from-source and loaded-from-disk packages). So we need to make\n  // sure here that the Isopack has *some* reference to the isobuild features\n  // which the unibuilds depend on, so we do it here (and also in\n  // Isopack#initFromPath).\n  var isobuildFeatures = [];\n  packageSource.architectures.forEach((sourceArch) => {\n    sourceArch.uses.forEach((use) => {\n      if (!use.weak && isIsobuildFeaturePackage(use.package) &&\n          isobuildFeatures.indexOf(use.package) === -1) {\n        isobuildFeatures.push(use.package);\n      }\n    });\n  });\n  isobuildFeatures = _.uniq(isobuildFeatures);\n\n  var isopk = new isopack.Isopack;\n  isopk.initFromOptions({\n    name: packageSource.name,\n    metadata: packageSource.metadata,\n    version: packageSource.version,\n    isTest: packageSource.isTest,\n    plugins: plugins,\n    pluginWatchSet: pluginWatchSet,\n    cordovaDependencies: packageSource.cordovaDependencies,\n    npmDiscards: packageSource.npmDiscards,\n    includeTool: packageSource.includeTool,\n    debugOnly: packageSource.debugOnly,\n    prodOnly: packageSource.prodOnly,\n    testOnly: packageSource.testOnly,\n    pluginCacheDir: options.pluginCacheDir,\n    isobuildFeatures\n  });\n\n  _.each(packageSource.architectures, function (architecture) {\n    if (architecture.arch === 'web.cordova' && ! includeCordovaUnibuild) {\n      return;\n    }\n\n    files.withCache(() => {\n      var unibuildResult = compileUnibuild({\n        isopack: isopk,\n        sourceArch: architecture,\n        isopackCache: isopackCache,\n        nodeModulesPath: nodeModulesPath,\n        noLineNumbers: options.noLineNumbers\n      });\n\n      _.extend(pluginProviderPackageNames,\n               unibuildResult.pluginProviderPackageNames);\n    });\n  });\n\n  if (options.includePluginProviderPackageMap) {\n    isopk.setPluginProviderPackageMap(\n      packageMap.makeSubsetMap(_.keys(pluginProviderPackageNames)));\n  }\n\n  return isopk;\n});\n\n// options:\n// - isopack\n// - isopackCache\n// - includeCordovaUnibuild\ncompiler.lint = Profile(function (packageSource, options) {\n  return `compiler.lint(${ packageSource.name || 'the app' })`;\n}, function (packageSource, options) {\n  // Note: the buildmessage context of compiler.lint and lintUnibuild is a\n  // normal error message context (eg, there might be errors from initializing\n  // plugins in getLinterSourceProcessorSet).  We return the linter warnings as\n  // our return value.\n  buildmessage.assertInJob();\n\n  const warnings = new buildmessage._MessageSet;\n  let linted = false;\n  _.each(packageSource.architectures, function (architecture) {\n    // skip Cordova if not required\n    if (! options.includeCordovaUnibuild\n        && architecture.arch === 'web.cordova') {\n      return;\n    }\n\n    const unibuildWarnings = lintUnibuild({\n      isopack: options.isopack,\n      isopackCache: options.isopackCache,\n      sourceArch: architecture\n    });\n    if (unibuildWarnings) {\n      linted = true;\n      warnings.merge(unibuildWarnings);\n    }\n  });\n  return {warnings, linted};\n});\n\ncompiler.getMinifiers = function (packageSource, options) {\n  buildmessage.assertInJob();\n\n  var minifiers = [];\n  _.each(packageSource.architectures, function (architecture) {\n    var activePluginPackages = getActivePluginPackages(options.isopack, {\n      isopackCache: options.isopackCache,\n      uses: architecture.uses\n    });\n\n    _.each(activePluginPackages, function (otherPkg) {\n      otherPkg.ensurePluginsInitialized();\n\n      _.each(otherPkg.sourceProcessors.minifier.allSourceProcessors, (sp) => {\n        minifiers.push(sp);\n      });\n    });\n  });\n\n  minifiers = _.uniq(minifiers);\n  // check for extension-wise uniqness\n  _.each(['js', 'css'], function (ext) {\n    var plugins = _.filter(minifiers, function (plugin) {\n      return _.contains(plugin.extensions, ext);\n    });\n\n    if (plugins.length > 1) {\n      var packages = _.map(plugins, function (p) { return p.isopack.name; });\n      buildmessage.error(packages.join(', ') + ': multiple packages registered minifiers for extension \"' + ext + '\".');\n    }\n  });\n\n  return minifiers;\n};\n\nfunction getLinterSourceProcessorSet({isopack, activePluginPackages}) {\n  buildmessage.assertInJob();\n\n  const sourceProcessorSet = new SourceProcessorSet(\n    isopack.displayName, { allowConflicts: true });\n\n  _.each(activePluginPackages, function (otherPkg) {\n    otherPkg.ensurePluginsInitialized();\n\n    sourceProcessorSet.merge(otherPkg.sourceProcessors.linter);\n  });\n\n  return sourceProcessorSet;\n}\n\nvar lintUnibuild = function ({isopack, isopackCache, sourceArch}) {\n  // Note: the buildmessage context of compiler.lint and lintUnibuild is a\n  // normal error message context (eg, there might be errors from initializing\n  // plugins in getLinterSourceProcessorSet).  We return the linter warnings as\n  // our return value.\n  buildmessage.assertInJob();\n\n  var activePluginPackages = getActivePluginPackages(\n    isopack, {\n      isopackCache,\n      uses: sourceArch.uses\n    });\n\n  const sourceProcessorSet =\n          getLinterSourceProcessorSet({isopack, activePluginPackages});\n  // bail out early if we had trouble loading plugins or if we're not\n  // going to lint anything\n  if (buildmessage.jobHasMessages() || sourceProcessorSet.isEmpty()) {\n    return null;\n  }\n\n  const unibuild = _.find(\n    isopack.unibuilds,\n    unibuild => archinfo.matches(unibuild.arch, sourceArch.arch)\n  );\n\n  if (! unibuild) {\n    throw Error(`No ${ sourceArch.arch } unibuild for ${ isopack.name }!`);\n  }\n\n  const {sources} = sourceArch.getFiles(sourceProcessorSet, unibuild.watchSet);\n\n  const linterMessages = buildmessage.capture(() => {\n    runLinters({\n      isopackCache,\n      sources,\n      sourceProcessorSet,\n      inputSourceArch: sourceArch,\n      watchSet: unibuild.watchSet\n    });\n  });\n  return linterMessages;\n};\n\n// options.sourceArch is a SourceArch to compile.  Process all source files\n// through the appropriate legacy handlers. Create a new Unibuild and add it to\n// options.isopack.\n//\n// Returns a list of source files that were used in the compilation.\nvar compileUnibuild = Profile(function (options) {\n  return `compileUnibuild (${options.isopack.name || 'the app'})`;\n}, function (options) {\n  buildmessage.assertInCapture();\n\n  const isopk = options.isopack;\n  const inputSourceArch = options.sourceArch;\n  const isopackCache = options.isopackCache;\n  const nodeModulesPath = options.nodeModulesPath;\n  const noLineNumbers = options.noLineNumbers;\n\n  const isApp = ! inputSourceArch.pkg.name;\n  const resources = [];\n  const pluginProviderPackageNames = {};\n  const watchSet = inputSourceArch.watchSet.clone();\n\n  // *** Determine and load active plugins\n  const activePluginPackages = getActivePluginPackages(isopk, {\n    uses: inputSourceArch.uses,\n    isopackCache: isopackCache,\n    // If other package is built from source, then we need to rebuild this\n    // package if any file in the other package that could define a plugin\n    // changes.  getActivePluginPackages will add entries to this WatchSet.\n    pluginProviderWatchSet: watchSet,\n    pluginProviderPackageNames\n  });\n\n  // *** Assemble the SourceProcessorSet from the plugins. This data\n  // structure lets us decide what to do with each file: which plugin\n  // should process it in what method.\n  //\n  // We also build a SourceProcessorSet for this package's linters even\n  // though we're not linting right now. This is so we can tell the\n  // difference between an file added to a package as a linter config\n  // file (not handled by any compiler), and a file that's truly not\n  // handled by anything (which is an error unless explicitly declared\n  // as a static asset).\n  let sourceProcessorSet, linterSourceProcessorSet;\n  buildmessage.enterJob(\"determining active plugins\", () => {\n    sourceProcessorSet = new SourceProcessorSet(\n      isopk.displayName(), { hardcodeJs: true});\n\n    activePluginPackages.forEach((otherPkg) => {\n      otherPkg.ensurePluginsInitialized();\n\n      // Note that this may log a buildmessage if there are conflicts.\n      sourceProcessorSet.merge(otherPkg.sourceProcessors.compiler);\n    });\n\n    // Used to excuse functions from the \"undeclared static asset\" check.\n    linterSourceProcessorSet = getLinterSourceProcessorSet({\n      activePluginPackages,\n      isopack: isopk\n    });\n    if (buildmessage.jobHasMessages()) {\n      // Recover by not calling getFiles and pretending there are no\n      // items.\n      sourceProcessorSet = null;\n    }\n  });\n\n  // *** Determine source files\n  // Note: the getFiles function isn't expected to add its\n  // source files to watchSet; rather, the watchSet is for other\n  // things that the getFiles consulted (such as directory\n  // listings or, in some hypothetical universe, control files) to\n  // determine its source files.\n  const sourceProcessorFiles = sourceProcessorSet\n    ? inputSourceArch.getFiles(sourceProcessorSet, watchSet) : {};\n  const sources = sourceProcessorFiles.sources || [];\n  const assets = sourceProcessorFiles.assets || [];\n\n  const nodeModulesDirectories = Object.create(null);\n\n  function addNodeModulesDirectory(options) {\n    const nmd = new bundler.NodeModulesDirectory(options);\n    nodeModulesDirectories[nmd.sourcePath] = nmd;\n  }\n\n  _.each(inputSourceArch.localNodeModulesDirs, (info, dir) => {\n    addNodeModulesDirectory({\n      packageName: inputSourceArch.pkg.name,\n      sourceRoot: inputSourceArch.sourceRoot,\n      sourcePath: files.pathJoin(inputSourceArch.sourceRoot, dir),\n      // Npm.strip applies to local node_modules directories of Meteor\n      // packages, as well as .npm/package/node_modules directories.\n      npmDiscards: isopk.npmDiscards,\n      local: true,\n      // The values of inputSourceArch.localNodeModulesDirs are usually\n      // just `true`, but if `info` is an object, then we let its\n      // properties override the properties defined above.\n      ...(_.isObject(info) ? info : Object.prototype),\n    });\n  });\n\n  if (nodeModulesPath) {\n    addNodeModulesDirectory({\n      packageName: inputSourceArch.pkg.name,\n      sourceRoot: inputSourceArch.sourceRoot,\n      sourcePath: nodeModulesPath,\n      npmDiscards: isopk.npmDiscards,\n      local: false,\n    });\n\n    // If this slice has node modules, we should consider the shrinkwrap file\n    // to be part of its inputs. (This is a little racy because there's no\n    // guarantee that what we read here is precisely the version that's used,\n    // but it's better than nothing at all.)\n    //\n    // Note that this also means that npm modules used by plugins will get\n    // this npm-shrinkwrap.json in their pluginDependencies (including for all\n    // packages that depend on us)!  This is good: this means that a tweak to\n    // an indirect dependency of the coffee-script npm module used by the\n    // coffeescript package will correctly cause packages with *.coffee files\n    // to be rebuilt.\n    const shrinkwrapPath = nodeModulesPath.replace(\n        /node_modules$/, 'npm-shrinkwrap.json');\n    watch.readAndWatchFile(watchSet, shrinkwrapPath);\n  }\n\n  // This function needs to be factored out to support legacy handlers later on\n  // in the compilation process\n  function addAsset(contents, relPath, hash) {\n    // XXX hack to strip out private and public directory names from app asset\n    // paths\n    if (! inputSourceArch.pkg.name) {\n      relPath = relPath.replace(/^(private|public)\\//, '');\n    }\n\n    resources.push({\n      type: \"asset\",\n      data: contents,\n      path: relPath,\n      servePath: colonConverter.convert(\n        files.pathJoin(inputSourceArch.pkg.serveRoot, relPath)),\n      hash: hash\n    });\n  }\n\n  // Add all assets\n  _.values(assets).forEach((asset) => {\n    const relPath = asset.relPath;\n    const absPath = files.pathResolve(inputSourceArch.sourceRoot, relPath);\n\n    // readAndWatchFileWithHash returns an object carrying a buffer with the\n    // file-contents. The buffer contains the original data of the file (no EOL\n    // transforms from the tools/files.js part).\n    const file = watch.readAndWatchFileWithHash(watchSet, absPath);\n    const hash = file.hash;\n    const contents = file.contents;\n\n    addAsset(contents, relPath, hash);\n  });\n\n  // Add and compile all source files\n  _.values(sources).forEach((source) => {\n    const relPath = source.relPath;\n    const fileOptions = _.clone(source.fileOptions) || {};\n    const absPath = files.pathResolve(inputSourceArch.sourceRoot, relPath);\n    const filename = files.pathBasename(relPath);\n\n    // Find the handler for source files with this extension\n    let classification = null;\n    classification = sourceProcessorSet.classifyFilename(\n      filename, inputSourceArch.arch);\n\n    if (classification.type === 'wrong-arch') {\n      // This file is for a compiler plugin but not for this arch. Skip it,\n      // and don't even watch it.  (eg, skip CSS preprocessor files on the\n      // server.)  This `return` skips this source file and goes on to the next\n      // one.\n      return;\n    }\n\n    if (classification.type === 'unmatched') {\n      // This is not matched by any compiler plugin or legacy source handler,\n      // but it was added as a source file.\n      //\n      // Prior to the batch-plugins project, these would be implicitly treated\n      // as static assets. Now we consider this to be an error; you need to\n      // explicitly tell that you want something to be a static asset by calling\n      // addAssets or putting it in the public/private directories in an app.\n      //\n      // This is a backwards-incompatible change, but it doesn't affect\n      // previously-published packages (because the check is occuring in the\n      // compiler), and it doesn't affect apps (where random files outside of\n      // private/public never end up in the source list anyway).\n      //\n      // As one special case, if a file is unmatched by the compiler\n      // SourceProcessorSet but is matched by the linter SourceProcessorSet (ie,\n      // a linter config file), we don't report an error; this is so that you\n      // can run `api.addFiles('.jshintrc')` and have it work.  (This is only\n      // relevant for packages.)  We don't put these files in the WatchSet,\n      // though; that happens via compiler.lint.\n\n      if (isApp) {\n        // This shouldn't happen, because initFromAppDir's getFiles\n        // should only return assets or sources which match\n        // sourceProcessorSet.\n        throw Error(\"app contains non-asset files without plugin? \" +\n                    relPath + \" - \" + filename);\n      }\n\n      const linterClassification = linterSourceProcessorSet.classifyFilename(\n        filename, inputSourceArch.arch);\n      if (linterClassification.type !== 'unmatched') {\n        // The linter knows about this, so we'll just ignore it instead of\n        // throwing an error.\n        return;\n      }\n\n      buildmessage.error(\n        `No plugin known to handle file '${ relPath }'. If you want this \\\nfile to be a static asset, use addAssets instead of addFiles; eg, \\\napi.addAssets('${relPath}', 'client').`);\n      // recover by ignoring\n      return;\n    }\n\n    // readAndWatchFileWithHash returns an object carrying a buffer with the\n    // file-contents. The buffer contains the original data of the file (no EOL\n    // transforms from the tools/files.js part).\n    const file = watch.readAndWatchFileWithHash(watchSet, absPath);\n    const hash = file.hash;\n    const contents = file.contents;\n\n    Console.nudge(true);\n\n    if (contents === null) {\n      // It really sucks to put this check here, since this isn't publish\n      // code...\n      // XXX We think this code can probably be deleted at this point because\n      // people probably aren't trying to use files with colons in them any\n      // more.\n      if (source.relPath.match(/:/)) {\n        buildmessage.error(\n          \"Couldn't build this package on Windows due to the following file \" +\n          \"with a colon -- \" + source.relPath + \". Please rename and \" +\n          \"and re-publish the package.\");\n      } else {\n        buildmessage.error(\"File not found: \" + source.relPath);\n      }\n\n      // recover by ignoring (but still watching the file)\n      return;\n    }\n\n    if (classification.isNonLegacySource()) {\n      // This is source used by a new-style compiler plugin; it will be fully\n      // processed later in the bundler.\n      resources.push({\n        type: \"source\",\n        extension: classification.extension || null,\n        usesDefaultSourceProcessor:\n          !! classification.usesDefaultSourceProcessor,\n        data: contents,\n        path: relPath,\n        hash: hash,\n        fileOptions: fileOptions\n      });\n      return;\n    }\n\n    if (classification.type !== 'legacy-handler') {\n      throw Error(\"unhandled type: \" + classification.type);\n    }\n\n    // OK, time to handle legacy handlers.\n    var compileStep = compileStepModule.makeCompileStep(\n      source, file, inputSourceArch, {\n        resources: resources,\n        addAsset: addAsset\n      });\n\n    const handler = buildmessage.markBoundary(classification.legacyHandler);\n\n    try {\n      Profile.time(`legacy handler (.${classification.extension})`, () => {\n        handler(compileStep);\n      });\n    } catch (e) {\n      e.message = e.message + \" (compiling \" + relPath + \")\";\n      buildmessage.exception(e);\n\n      // Recover by ignoring this source file (as best we can -- the\n      // handler might already have emitted resources)\n    }\n  });\n\n  // *** Determine captured variables\n  var declaredExports = _.map(inputSourceArch.declaredExports, function (symbol) {\n    return _.pick(symbol, ['name', 'testOnly']);\n  });\n\n  const isPortable = process.env.METEOR_FORCE_PORTABLE ||\n    _.every(nodeModulesDirectories, nmd => nmd.isPortable());\n\n  // *** Consider npm dependencies and portability\n  var arch = inputSourceArch.arch;\n  if (arch === \"os\" && ! isPortable) {\n    // Contains non-portable compiled npm modules, so set arch correctly\n    arch = archinfo.host();\n  }\n\n  let nodeModulesDirsOrUndefined = nodeModulesDirectories;\n  if (! archinfo.matches(arch, \"os\") && ! isPortable) {\n    // non-portable npm modules only work on server architectures\n    nodeModulesDirsOrUndefined = undefined;\n  }\n\n  // *** Output unibuild object\n  isopk.addUnibuild({\n    kind: inputSourceArch.kind,\n    arch: arch,\n    uses: inputSourceArch.uses,\n    implies: inputSourceArch.implies,\n    watchSet: watchSet,\n    nodeModulesDirectories: nodeModulesDirsOrUndefined,\n    declaredExports: declaredExports,\n    resources: resources\n  });\n\n  return {\n    pluginProviderPackageNames: pluginProviderPackageNames\n  };\n});\n\nfunction runLinters({inputSourceArch, isopackCache, sources,\n                     sourceProcessorSet, watchSet}) {\n  // The buildmessage context here is for linter warnings only! runLinters\n  // should not do anything that can have a real build failure.\n  buildmessage.assertInCapture();\n\n  if (sourceProcessorSet.isEmpty()) {\n    return;\n  }\n\n  // First we calculate the symbols imported into the current package by\n  // packages we depend on. This is because most JS linters are going to want to\n  // warn about the use of unknown global variables, and the linker import\n  // system works by doing something that looks a whole lot like using\n  // undeclared globals!  That said, we don't actually know the imports that\n  // will be active when an app is built if the versions of the imported\n  // packages differ from those available at package lint time. But it's a good\n  // heuristic, at least. (If we transition from linker to ES2015 modules, we\n  // won't have the issue any more.)\n\n  // We want to look at the arch of the used packages that matches the arch\n  // we're compiling.  Normally when we call compiler.eachUsedUnibuild, we're\n  // either specifically looking at archinfo.host() because we're doing\n  // something related to plugins (which always run in the host environment), or\n  // we're in the process of building a bundler Target (a program), which has a\n  // specific arch which is never 'os'.  In this odd case, though, we're trying\n  // to run eachUsedUnibuild at package-compile time (not bundle time), so the\n  // only 'arch' we've heard of might be 'os', if we're building a portable\n  // unibuild.  In that case, we should look for imports in the host arch if it\n  // exists instead of failing because a dependency does not have an 'os'\n  // unibuild.\n  const whichArch = inputSourceArch.arch === 'os'\n          ? archinfo.host() : inputSourceArch.arch;\n\n  // For linters, figure out what are the global imports from other packages\n  // that we use directly, or are implied.\n  const globalImports = ['Package'];\n\n  if (archinfo.matches(inputSourceArch.arch, \"os\")) {\n    globalImports.push('Npm', 'Assets');\n  }\n\n  compiler.eachUsedUnibuild({\n    dependencies: inputSourceArch.uses,\n    arch: whichArch,\n    isopackCache: isopackCache,\n    skipUnordered: true,\n    // don't import symbols from debugOnly, prodOnly and testOnly\n    // packages, because if the package is not linked it will cause a\n    // runtime error.  the code must access them with\n    // `Package[\"my-package\"].MySymbol`.\n    skipDebugOnly: true,\n    skipProdOnly: true,\n    skipTestOnly: true,\n  }, (unibuild) => {\n    if (unibuild.pkg.name === inputSourceArch.pkg.name) {\n      return;\n    }\n    _.each(unibuild.declaredExports, (symbol) => {\n      if (! symbol.testOnly || inputSourceArch.isTest) {\n        globalImports.push(symbol.name);\n      }\n    });\n  });\n\n  // sourceProcessor.id -> {sourceProcessor, sources: [WrappedSourceItem]}\n  const sourceItemsForLinter = {};\n  _.values(sources).forEach((sourceItem) => {\n    const { relPath, fileOptions } = sourceItem;\n    const classification = sourceProcessorSet.classifyFilename(\n      files.pathBasename(relPath), inputSourceArch.arch);\n\n    // If we don't have a linter for this file (or we do but it's only on\n    // another arch), skip without even reading the file into a WatchSet.\n    if (classification.type === 'wrong-arch' ||\n        classification.type === 'unmatched') {\n      return;\n    }\n    // We shouldn't ever add a legacy handler and we're not hardcoding JS for\n    // linters, so we should always have SourceProcessor if anything matches.\n    if (! classification.sourceProcessors) {\n      throw Error(\n        `Unexpected classification for ${ relPath }: ${ classification.type }`);\n    }\n\n    // Read the file and add it to the WatchSet.\n    const {hash, contents} = watch.readAndWatchFileWithHash(\n      watchSet,\n      files.pathResolve(inputSourceArch.sourceRoot, relPath));\n    const wrappedSource = {\n      relPath, contents, hash, fileOptions,\n      arch: inputSourceArch.arch,\n      'package': inputSourceArch.pkg.name\n    };\n\n    // There can be multiple linters on a file.\n    classification.sourceProcessors.forEach((sourceProcessor) => {\n      if (! sourceItemsForLinter.hasOwnProperty(sourceProcessor.id)) {\n        sourceItemsForLinter[sourceProcessor.id] = {\n          sourceProcessor,\n          sources: []\n        };\n      }\n      sourceItemsForLinter[sourceProcessor.id].sources.push(wrappedSource);\n    });\n  });\n\n  // Run linters on files. This skips linters that don't have any files.\n  _.each(sourceItemsForLinter, ({sourceProcessor, sources}) => {\n    const sourcesToLint = sources.map(\n      wrappedSource => new linterPluginModule.LintingFile(wrappedSource)\n    );\n\n    const linter = sourceProcessor.userPlugin.processFilesForPackage;\n\n    function archToString(arch) {\n      if (arch.match(/web\\.cordova/)) {\n        return \"Cordova\";\n      }\n      if (arch.match(/web\\..*/)) {\n        return \"Client\";\n      }\n      if (arch.match(/os.*/)) {\n        return \"Server\";\n      }\n      throw new Error(\"Don't know how to display the arch: \" + arch);\n    }\n\n    buildmessage.enterJob({\n      title: \"linting files with \" +\n        sourceProcessor.isopack.name +\n        \" for \" +\n        inputSourceArch.pkg.displayName() +\n        \" (\" + archToString(inputSourceArch.arch) + \")\"\n    }, () => {\n      try {\n        var markedLinter = buildmessage.markBoundary(linter.bind(\n          sourceProcessor.userPlugin));\n        markedLinter(sourcesToLint, { globals: globalImports });\n      } catch (e) {\n        buildmessage.exception(e);\n      }\n    });\n  });\n};\n\n// takes an isopack and returns a list of packages isopack depends on,\n// containing at least one plugin\nexport function getActivePluginPackages(isopk, {\n  uses,\n  isopackCache,\n  pluginProviderPackageNames,\n  pluginProviderWatchSet\n}) {\n  // XXX we used to include our own plugins only if we were the\n  // \"use\" role. now we include them everywhere because we don't have\n  // a special \"use\" role anymore. it's not totally clear to me what\n  // the correct behavior should be -- we need to resolve whether we\n  // think about plugins as being global to a package or particular\n  // to a unibuild.\n\n  // (there's also some weirdness here with handling implies, because\n  // the implies field is on the target unibuild, but we really only care\n  // about packages.)\n  var activePluginPackages = [isopk];\n  if (pluginProviderPackageNames) {\n    pluginProviderPackageNames[isopk.name] = true;\n  }\n\n  // We don't use plugins from weak dependencies, because the ability\n  // to compile a certain type of file shouldn't depend on whether or\n  // not some unrelated package in the target has a dependency. And we\n  // skip unordered dependencies, because it's not going to work to\n  // have circular build-time dependencies.\n  //\n  // eachUsedUnibuild takes care of pulling in implied dependencies for us (eg,\n  // templating from standard-app-packages).\n  //\n  // We pass archinfo.host here, not self.arch, because it may be more specific,\n  // and because plugins always have to run on the host architecture.\n  compiler.eachUsedUnibuild({\n    dependencies: uses,\n    arch: archinfo.host(),\n    isopackCache: isopackCache,\n    skipUnordered: true\n    // implicitly skip weak deps by not specifying acceptableWeakPackages option\n  }, function (unibuild) {\n    if (unibuild.pkg.name === isopk.name) {\n      return;\n    }\n    if (pluginProviderPackageNames) {\n      pluginProviderPackageNames[unibuild.pkg.name] = true;\n    }\n    if (pluginProviderWatchSet) {\n      pluginProviderWatchSet.merge(unibuild.pkg.pluginWatchSet);\n    }\n    if (_.isEmpty(unibuild.pkg.plugins)) {\n      return;\n    }\n    activePluginPackages.push(unibuild.pkg);\n  });\n\n  activePluginPackages = _.uniq(activePluginPackages);\n  return activePluginPackages;\n}\n\n// Iterates over each in options.dependencies as well as unibuilds implied by\n// them. The packages in question need to already be built and in\n// options.isopackCache.\n//\n// Skips isobuild:* pseudo-packages.\ncompiler.eachUsedUnibuild = function (\n  options, callback) {\n  buildmessage.assertInCapture();\n  var dependencies = options.dependencies;\n  var arch = options.arch;\n  var isopackCache = options.isopackCache;\n\n  var acceptableWeakPackages = options.acceptableWeakPackages || {};\n\n  var processedUnibuildId = {};\n  var usesToProcess = [];\n  _.each(dependencies, function (use) {\n    if (options.skipUnordered && use.unordered) {\n      return;\n    }\n    if (use.weak && !_.has(acceptableWeakPackages, use.package)) {\n      return;\n    }\n    usesToProcess.push(use);\n  });\n\n  while (! _.isEmpty(usesToProcess)) {\n    var use = usesToProcess.shift();\n\n    // We only care about real packages, not isobuild:* psuedo-packages.\n    if (isIsobuildFeaturePackage(use.package)) {\n      continue;\n    }\n\n    var usedPackage = isopackCache.getIsopack(use.package);\n\n    // Ignore this package if we were told to skip debug-only packages and it is\n    // debug-only.\n    if (usedPackage.debugOnly && options.skipDebugOnly) {\n      continue;\n    }\n    // Ditto prodOnly.\n    if (usedPackage.prodOnly && options.skipProdOnly) {\n      continue;\n    }\n    // Ditto testOnly.\n    if (usedPackage.testOnly && options.skipTestOnly) {\n      continue;\n    }\n\n    var unibuild = usedPackage.getUnibuildAtArch(arch);\n    if (!unibuild) {\n      // The package exists but there's no unibuild for us. A buildmessage has\n      // already been issued. Recover by skipping.\n      continue;\n    }\n\n    if (_.has(processedUnibuildId, unibuild.id)) {\n      continue;\n    }\n    processedUnibuildId[unibuild.id] = true;\n\n    callback(unibuild, {\n      unordered: !!use.unordered,\n      weak: !!use.weak\n    });\n\n    _.each(unibuild.implies, function (implied) {\n      usesToProcess.push(implied);\n    });\n  }\n};\n\n// Note: this code is duplicated in packages/constraint-solver/solver.js\nexport function isIsobuildFeaturePackage(packageName) {\n  return packageName.startsWith('isobuild:');\n}\n\n// If you update this data structure to add more feature packages, you should\n// update the wiki page here:\n// https://github.com/meteor/meteor/wiki/Isobuild-Feature-Packages\nexport const KNOWN_ISOBUILD_FEATURE_PACKAGES = {\n  // This package directly calls Plugin.registerCompiler. Package authors\n  // must explicitly depend on this feature package to use the API.\n  'isobuild:compiler-plugin': ['1.0.0'],\n\n  // This package directly calls Plugin.registerMinifier. Package authors\n  // must explicitly depend on this feature package to use the API.\n  'isobuild:minifier-plugin': ['1.0.0'],\n\n  // This package directly calls Plugin.registerLinter. Package authors\n  // must explicitly depend on this feature package to use the API.\n  'isobuild:linter-plugin': ['1.0.0'],\n\n  // This package is only published in the isopack-2 format, not isopack-1 or\n  // older. ie, it contains \"source\" files for compiler plugins, not just\n  // JS/CSS/static assets/head/body.\n  // This is implicitly added at publish time to any such package; package\n  // authors don't have to add it explicitly. It isn't relevant for local\n  // packages, which can be rebuilt if possible by the older tool.\n  //\n  // Specifically, this is to avoid the case where a package is published with a\n  // dependency like `api.use('less@1.0.0 || 2.0.0')` and the publication\n  // selects the newer compiler plugin version to generate the isopack. The\n  // published package (if this feature package wasn't implicitly included)\n  // could still be selected by the Version Solver to be used with an old\n  // Isobuild... just because less@2.0.0 depends on isobuild:compiler-plugin\n  // doesn't mean it couldn't choose less@1.0.0, which is not actually\n  // compatible with this published package.  (Constraints of the form described\n  // above are not very helpful, but at least we can prevent old Isobuilds from\n  // choking on confusing packages.)\n  //\n  // (Why not isobuild:isopack@2.0.0? Well, that would imply that Version Solver\n  // would have to choose only one isobuild:isopack feature version, which\n  // doesn't make sense here.)\n  'isobuild:isopack-2': ['1.0.0'],\n\n  // This package uses the `prodOnly` metadata flag, which causes it to\n  // automatically depend on the `isobuild:prod-only` feature package.\n  'isobuild:prod-only': ['1.0.0'],\n\n  // This package depends on a specific version of Cordova. Package authors must\n  // explicitly depend on this feature package to indicate that they are not\n  // compatible with earlier Cordova versions, which is most likely a result of\n  // the Cordova plugins they depend on.\n  // One scenario is a package depending on a Cordova plugin or version\n  // that is only available on npm, which means downloading the plugin is not\n  // supported on versions of Cordova below 5.0.0.\n  'isobuild:cordova': ['5.4.0']\n};\n"
  },
  {
    "path": "tools/isobuild/css-modules.js",
    "content": "export function cssToCommonJS(css) {\n  return [\n    'module.exports = require(\"meteor/modules\").addStyles(',\n    \"  \" + JSON.stringify(css),\n    \");\",\n    \"\"\n  ].join(\"\\n\");\n}\n"
  },
  {
    "path": "tools/isobuild/import-scanner.js",
    "content": "import assert from \"assert\";\nimport {inspect} from \"util\";\nimport {Script} from \"vm\";\nimport {\n  isString, isEmpty, has, keys, each, map, omit,\n} from \"underscore\";\nimport {sha1, readAndWatchFileWithHash} from \"../fs/watch.js\";\nimport {matches as archMatches} from \"../utils/archinfo.js\";\nimport {findImportedModuleIdentifiers} from \"./js-analyze.js\";\nimport {cssToCommonJS} from \"./css-modules.js\";\nimport buildmessage from \"../utils/buildmessage.js\";\nimport LRU from \"lru-cache\";\nimport {Profile} from \"../tool-env/profile.js\";\nimport {SourceNode, SourceMapConsumer} from \"source-map\";\nimport {\n  pathJoin,\n  pathRelative,\n  pathNormalize,\n  pathDirname,\n  pathBasename,\n  pathExtname,\n  pathIsAbsolute,\n  statOrNull as realStatOrNull,\n  convertToOSPath,\n  convertToPosixPath,\n} from \"../fs/files.js\";\n\nimport Resolver from \"./resolver.js\";\n\nconst fakeFileStat = {\n  isFile() {\n    return true;\n  },\n\n  isDirectory() {\n    return false;\n  }\n};\n\n// Default handlers for well-known file extensions.\n// Note that these function expect strings, not Buffer objects.\nconst defaultExtensionHandlers = {\n  \".js\"(dataString) {\n    // Strip any #! line from the beginning of the file.\n    return dataString.replace(/^#![^\\n]*/, \"\");\n  },\n\n  \".json\"(dataString) {\n    return \"module.exports = \" +\n      JSON.stringify(JSON.parse(dataString), null, 2) +\n      \";\\n\";\n  },\n\n  \".css\"(dataString, hash) {\n    return cssToCommonJS(dataString, hash);\n  }\n};\n\n// This is just a map from hashes to booleans, so it doesn't need full LRU\n// eviction logic.\nconst scriptParseCache = Object.create(null);\n\nfunction canBeParsedAsPlainJS(dataString, hash) {\n  if (hash && has(scriptParseCache, hash)) {\n    return scriptParseCache[hash];\n  }\n\n  try {\n    var result = !! new Script(dataString);\n  } catch (e) {\n    result = false;\n  }\n\n  if (hash) {\n    scriptParseCache[hash] = result;\n  }\n\n  return result;\n}\n\n// Map from SHA (which is already calculated, so free for us)\n// to the results of calling findImportedModuleIdentifiers.\n// Each entry is an array of strings, and this is a case where\n// the computation is expensive but the output is very small.\n// The cache can be global because findImportedModuleIdentifiers\n// is a pure function, and that way it applies across instances\n// of ImportScanner (which do not persist across builds).\nconst IMPORT_SCANNER_CACHE = new LRU({\n  max: 1024*1024,\n  length(ids) {\n    let total = 40; // size of key\n    each(ids, (info, id) => { total += id.length; });\n    return total;\n  }\n});\n\nexport default class ImportScanner {\n  constructor({\n    name,\n    bundleArch,\n    extensions,\n    sourceRoot,\n    nodeModulesPaths = [],\n    watchSet,\n  }) {\n    const scanner = this;\n    assert.ok(isString(sourceRoot));\n\n    this.name = name;\n    this.bundleArch = bundleArch;\n    this.sourceRoot = sourceRoot;\n    this.nodeModulesPaths = nodeModulesPaths;\n    this.watchSet = watchSet;\n    this.absPathToOutputIndex = Object.create(null);\n    this.allMissingNodeModules = Object.create(null);\n    this.outputFiles = [];\n\n    this.resolver = new Resolver({\n      sourceRoot,\n      targetArch: bundleArch,\n      extensions,\n      nodeModulesPaths,\n      watchSet,\n\n      onPackageJson(path, pkg) {\n        return scanner._addPkgJsonToOutput(path, pkg);\n      },\n\n      onMissing(id, parentPath) {\n        return scanner._onMissing(id, parentPath);\n      },\n\n      statOrNull(absPath) {\n        const file = scanner._getFile(absPath);\n        if (file) {\n          return fakeFileStat;\n        }\n        return realStatOrNull(absPath);\n      }\n    });\n  }\n\n  _getFile(absPath) {\n    absPath = absPath.toLowerCase();\n    if (has(this.absPathToOutputIndex, absPath)) {\n      return this.outputFiles[this.absPathToOutputIndex[absPath]];\n    }\n  }\n\n  _addFile(absPath, file) {\n    absPath = absPath.toLowerCase();\n    const old = this.absPathToOutputIndex[absPath];\n\n    if (old) {\n      // If the old file is just an empty stub, let the new file take\n      // precedence over it.\n      if (old.emptyStub === true) {\n        return this.absPathToOutputIndex[absPath] = file;\n      }\n\n      // If the new file is just an empty stub, pretend the _addFile\n      // succeeded by returning the old file, so that we won't try to call\n      // _combineFiles needlessly.\n      if (file.emptyStub === true) {\n        return old;\n      }\n\n    } else {\n      this.absPathToOutputIndex[absPath] =\n        this.outputFiles.push(file) - 1;\n\n      return file;\n    }\n  }\n\n  addInputFiles(files) {\n    files.forEach(file => {\n      this._checkSourceAndTargetPaths(file);\n\n      // Note: this absolute path may not necessarily exist on the file\n      // system, but any import statements or require calls in file.data\n      // will be interpreted relative to this path, so it needs to be\n      // something plausible. #6411 #6383\n      const absPath = pathJoin(this.sourceRoot, file.sourcePath);\n\n      const dotExt = \".\" + file.type;\n      const dataString = file.data.toString(\"utf8\");\n      file.dataString = defaultExtensionHandlers[dotExt](\n        dataString, file.hash);\n\n      if (! (file.data instanceof Buffer) ||\n          file.dataString !== dataString) {\n        file.data = new Buffer(file.dataString, \"utf8\");\n      }\n\n      // Files that are not eagerly evaluated (lazy) will only be included\n      // in the bundle if they are actually imported. Files that are\n      // eagerly evaluated are effectively \"imported\" as entry points.\n      file.imported = ! file.lazy;\n\n      file.installPath = file.installPath || this._getInstallPath(absPath);\n\n      if (! this._addFile(absPath, file)) {\n        // Collisions can happen if a compiler plugin calls addJavaScript\n        // multiple times with the same sourcePath. #6422\n        this._combineFiles(this._getFile(absPath), file);\n      }\n    });\n\n    return this;\n  }\n\n  // Make sure file.sourcePath is defined, and handle the possibility that\n  // file.targetPath differs from file.sourcePath.\n  _checkSourceAndTargetPaths(file) {\n    file.sourcePath = this._getSourcePath(file);\n\n    if (! isString(file.targetPath)) {\n      return;\n    }\n\n    file.targetPath = pathNormalize(pathJoin(\".\", file.targetPath));\n\n    if (file.targetPath !== file.sourcePath) {\n      const absSourcePath = pathJoin(this.sourceRoot, file.sourcePath);\n      const absTargetPath = pathJoin(this.sourceRoot, file.targetPath);\n\n      // If file.targetPath differs from file.sourcePath, generate a new\n      // file object with that .sourcePath that imports the original file.\n      // This allows either the .sourcePath or the .targetPath to be used\n      // when importing the original file, and also allows multiple files\n      // to have the same .sourcePath but different .targetPaths.\n      let sourceFile = this._getFile(absSourcePath);\n      if (! sourceFile) {\n        const installPath = this._getInstallPath(absSourcePath);\n        sourceFile = this._addFile(absSourcePath, {\n          type: file.type,\n          sourcePath: file.sourcePath,\n          servePath: installPath,\n          installPath,\n          dataString: \"\",\n          deps: {},\n          lazy: true,\n        });\n      }\n\n      // Make sure the original file gets installed at the target path\n      // instead of the source path.\n      file.installPath = this._getInstallPath(absTargetPath);\n      file.sourcePath = file.targetPath;\n\n      let relativeId = convertToPosixPath(pathRelative(\n        pathDirname(absSourcePath),\n        absTargetPath\n      ));\n\n      // If the result of pathRelative does not already start with a \".\"\n      // or a \"/\", prepend a \"./\" to make it a valid relative identifier\n      // according to CommonJS syntax.\n      if (\"./\".indexOf(relativeId.charAt(0)) < 0) {\n        relativeId = \"./\" + relativeId;\n      }\n\n      // Set the contents of the source module to import the target\n      // module(s). Note that module.exports will be set to the exports of\n      // the last target module. This is not perfect, but (1) it's better\n      // than trying to merge exports, (2) it does the right thing when\n      // there's only one target module, (3) the plugin author can easily\n      // control which file comes last, and (4) it's always possible to\n      // import the target modules individually.\n      sourceFile.dataString += \"module.exports = require(\" +\n        JSON.stringify(relativeId) + \");\\n\";\n      sourceFile.data = new Buffer(sourceFile.dataString, \"utf8\");\n      sourceFile.hash = sha1(sourceFile.data);\n      sourceFile.deps[relativeId] = {};\n    }\n  }\n\n  // Concatenate the contents of oldFile and newFile, combining source\n  // maps and updating all other properties appropriately. Once this\n  // combination is done, oldFile should be kept and newFile discarded.\n  _combineFiles(oldFile, newFile) {\n    function checkProperty(name) {\n      if (has(oldFile, name)) {\n        if (! has(newFile, name)) {\n          newFile[name] = oldFile[name];\n        }\n      } else if (has(newFile, name)) {\n        oldFile[name] = newFile[name];\n      }\n\n      if (oldFile[name] !== newFile[name]) {\n        throw new Error(\n          \"Attempting to combine different files:\\n\" +\n            inspect(omit(oldFile, \"dataString\")) + \"\\n\" +\n            inspect(omit(newFile, \"dataString\")) + \"\\n\"\n        );\n      }\n    }\n\n    // Since we're concatenating the files together, they must be either\n    // both lazy or both eager. Same for bareness.\n    checkProperty(\"lazy\");\n    checkProperty(\"bare\");\n\n    function getChunk(file) {\n      const consumer = file.sourceMap &&\n        new SourceMapConsumer(file.sourceMap);\n      const node = consumer &&\n        SourceNode.fromStringWithSourceMap(file.dataString, consumer);\n      return node || file.dataString;\n    }\n\n    const {\n      code: combinedDataString,\n      map: combinedSourceMap,\n    } = new SourceNode(null, null, null, [\n      getChunk(oldFile),\n      \"\\n\\n\",\n      getChunk(newFile)\n    ]).toStringWithSourceMap({\n      file: oldFile.servePath || newFile.servePath\n    });\n\n    oldFile.dataString = combinedDataString;\n    oldFile.data = new Buffer(oldFile.dataString, \"utf8\");\n    oldFile.hash = sha1(oldFile.data);\n    oldFile.imported = oldFile.imported || newFile.imported;\n    oldFile.sourceMap = combinedSourceMap.toJSON();\n    if (! oldFile.sourceMap.mappings) {\n      oldFile.sourceMap = null;\n    }\n  }\n\n  scanImports() {\n    this.outputFiles.forEach(file => {\n      if (! file.lazy || file.imported) {\n        this._scanFile(file);\n      }\n    });\n\n    return this;\n  }\n\n  addNodeModules(identifiers) {\n    assert.ok(identifiers);\n    assert.ok(typeof identifiers === \"object\");\n    assert.ok(! Array.isArray(identifiers));\n\n    const newlyMissing = Object.create(null);\n    const newlyAdded = Object.create(null);\n\n    if (! isEmpty(identifiers)) {\n      const previousAllMissingNodeModules = this.allMissingNodeModules;\n      this.allMissingNodeModules = newlyMissing;\n\n      try {\n        this._scanFile({\n          sourcePath: \"fake.js\",\n          // By specifying the .deps property of this fake file ahead of\n          // time, we can avoid calling findImportedModuleIdentifiers in the\n          // _scanFile method.\n          deps: identifiers,\n        });\n\n      } finally {\n        this.allMissingNodeModules = previousAllMissingNodeModules;\n\n        each(identifiers, (info, id) => {\n          if (! has(newlyMissing, id)) {\n            newlyAdded[id] = info;\n          }\n        });\n\n        // Remove previously seen missing module identifiers from\n        // newlyMissing and merge the new identifiers back into\n        // this.allMissingNodeModules.\n        each(keys(newlyMissing), key => {\n          if (has(previousAllMissingNodeModules, key)) {\n            delete newlyMissing[key];\n          } else {\n            previousAllMissingNodeModules[key] =\n              newlyMissing[key];\n          }\n        });\n      }\n    }\n\n    return {\n      newlyAdded,\n      newlyMissing,\n    };\n  }\n\n  getOutputFiles(options) {\n    // Return all installable output files that are either eager or\n    // imported by another module.\n    return this.outputFiles.filter(file => {\n      return file.installPath && (! file.lazy || file.imported);\n    });\n  }\n\n  _getSourcePath(file) {\n    let sourcePath = file.sourcePath;\n    if (sourcePath) {\n      if (pathIsAbsolute(sourcePath)) {\n        try {\n          var relPath = pathRelative(this.sourceRoot, sourcePath);\n\n        } finally {\n          if (! relPath || relPath.startsWith(\"..\")) {\n            if (this.resolver._joinAndStat(this.sourceRoot, sourcePath)) {\n              // If sourcePath exists as a path relative to this.sourceRoot,\n              // strip away the leading / that made it look absolute.\n              return pathNormalize(pathJoin(\".\", sourcePath));\n            }\n\n            if (relPath) {\n              throw new Error(\"sourcePath outside sourceRoot: \" + sourcePath);\n            }\n\n            // If pathRelative threw an exception above, and we were not\n            // able to handle the problem, it will continue propagating\n            // from this finally block.\n          }\n        }\n\n        sourcePath = relPath;\n      }\n\n    } else if (file.servePath) {\n      sourcePath = convertToOSPath(file.servePath.replace(/^\\//, \"\"));\n\n    } else if (file.path) {\n      sourcePath = file.path;\n    }\n\n    return pathNormalize(pathJoin(\".\", sourcePath));\n  }\n\n  _findImportedModuleIdentifiers(file) {\n    if (IMPORT_SCANNER_CACHE.has(file.hash)) {\n      return IMPORT_SCANNER_CACHE.get(file.hash);\n    }\n\n    const result = findImportedModuleIdentifiers(\n      file.dataString,\n      file.hash,\n    );\n\n    // there should always be file.hash, but better safe than sorry\n    if (file.hash) {\n      IMPORT_SCANNER_CACHE.set(file.hash, result);\n    }\n\n    return result;\n  }\n\n  _scanFile(file) {\n    const absPath = pathJoin(this.sourceRoot, file.sourcePath);\n\n    try {\n      file.deps = file.deps || this._findImportedModuleIdentifiers(file);\n    } catch (e) {\n      if (e.$ParseError) {\n        buildmessage.error(e.message, {\n          file: file.sourcePath,\n          line: e.loc.line,\n          column: e.loc.column,\n        });\n        return;\n      }\n      throw e;\n    }\n\n    each(file.deps, (info, id) => {\n      const resolved = this.resolver.resolve(id, absPath);\n      if (! resolved) {\n        return;\n      }\n\n      const absImportedPath = resolved.path;\n\n      let depFile = this._getFile(absImportedPath);\n      if (depFile) {\n        // Avoid scanning files that we've scanned before, but mark them\n        // as imported so we know to include them in the bundle if they\n        // are lazy. Eager files and files that we have imported before do\n        // not need to be scanned again. Lazy files that we have not\n        // imported before still need to be scanned, however.\n        const alreadyScanned = ! depFile.lazy || depFile.imported;\n\n        // Whether the file is eager or lazy, mark it as imported. For\n        // lazy files, this makes the difference between being included in\n        // or omitted from the bundle. For eager files, this just ensures\n        // we won't scan them again.\n        depFile.imported = true;\n\n        if (! alreadyScanned) {\n          if (depFile.error) {\n            // Since this file is lazy, it might never have been imported,\n            // so any errors reported to InputFile#error were saved but\n            // not reported at compilation time. Now that we know the file\n            // has been imported, it's time to report those errors.\n            buildmessage.error(depFile.error.message,\n                               depFile.error.info);\n          } else {\n            this._scanFile(depFile);\n          }\n        }\n\n        return;\n      }\n\n      const installPath = this._getInstallPath(absImportedPath);\n      if (! installPath) {\n        // The given path cannot be installed on this architecture.\n        return;\n      }\n\n      // If the module is not readable, _readModule may return\n      // null. Otherwise it will return an object with .data, .dataString,\n      // and .hash properties.\n      depFile = this._readModule(absImportedPath);\n      if (! depFile) {\n        return;\n      }\n\n      depFile.type = \"js\"; // TODO Is this correct?\n      depFile.sourcePath = pathRelative(this.sourceRoot, absImportedPath);\n      depFile.installPath = installPath;\n      depFile.servePath = installPath;\n      depFile.lazy = true;\n      depFile.imported = true;\n\n      // Append this file to the output array and record its index.\n      this._addFile(absImportedPath, depFile);\n\n      this._scanFile(depFile);\n    });\n  }\n\n  _readFile(absPath) {\n    let { contents, hash } =\n      readAndWatchFileWithHash(this.watchSet, absPath);\n\n    return {\n      data: contents,\n      dataString: contents.toString(\"utf8\"),\n      hash\n    };\n  }\n\n  _readModule(absPath) {\n    const info = this._readFile(absPath);\n    const dataString = info.dataString;\n\n    // Same logic/comment as stripBOM in node/lib/module.js:\n    // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)\n    // because the buffer-to-string conversion in `fs.readFileSync()`\n    // translates it to FEFF, the UTF-16 BOM.\n    if (info.dataString.charCodeAt(0) === 0xfeff) {\n      info.dataString = info.dataString.slice(1);\n    }\n\n    let ext = pathExtname(absPath).toLowerCase();\n    if (! has(defaultExtensionHandlers, ext)) {\n      if (canBeParsedAsPlainJS(dataString)) {\n        ext = \".js\";\n      } else {\n        return null;\n      }\n    }\n\n    info.dataString = defaultExtensionHandlers[ext](\n      info.dataString,\n      info.hash,\n    );\n\n    if (info.dataString !== dataString) {\n      info.data = new Buffer(info.dataString, \"utf8\");\n    }\n\n    return info;\n  }\n\n  // Returns a relative path indicating where to install the given file\n  // via meteorInstall. May return undefined if the file should not be\n  // installed on the current architecture.\n  _getInstallPath(absPath) {\n    let path =\n      this._getNodeModulesInstallPath(absPath) ||\n      this._getSourceRootInstallPath(absPath);\n\n    if (! path) {\n      return;\n    }\n\n    if (this.name) {\n      // If we're bundling a package, prefix path with\n      // node_modules/<package name>/.\n      path = pathJoin(\"node_modules\", \"meteor\", this.name, path);\n    }\n\n    // Install paths should always be delimited by /.\n    return convertToPosixPath(path);\n  }\n\n  _getNodeModulesInstallPath(absPath) {\n    let installPath;\n\n    this.nodeModulesPaths.some(path => {\n      const relPathWithinNodeModules = pathRelative(path, absPath);\n\n      if (relPathWithinNodeModules.startsWith(\"..\")) {\n        // absPath is not a subdirectory of path.\n        return;\n      }\n\n      // Install the module into the local node_modules directory within\n      // this app or package.\n      return installPath = pathJoin(\n        \"node_modules\",\n        relPathWithinNodeModules\n      );\n    });\n\n    return installPath;\n  }\n\n  _getSourceRootInstallPath(absPath) {\n    const installPath = pathRelative(this.sourceRoot, absPath);\n\n    if (installPath.startsWith(\"..\")) {\n      // absPath is not a subdirectory of this.sourceRoot.\n      return;\n    }\n\n    const dirs = this._splitPath(pathDirname(installPath));\n    const isApp = ! this.name;\n    const bundlingForWeb = archMatches(this.bundleArch, \"web\");\n\n    const topLevelDir = dirs[0];\n    if (topLevelDir === \"private\" ||\n        topLevelDir === \"packages\" ||\n        topLevelDir === \"programs\" ||\n        topLevelDir === \"cordova-build-override\") {\n      // Don't load anything from these special top-level directories\n      return;\n    }\n\n    for (let dir of dirs) {\n      if (dir.charAt(0) === \".\") {\n        // Files/directories whose names start with a dot are never loaded\n        return;\n      }\n\n      if (isApp) {\n        if (bundlingForWeb) {\n          if (dir === \"server\") {\n            // If we're bundling an app for a client architecture, any files\n            // contained by a server-only directory that is not contained by\n            // a node_modules directory must be ignored.\n            return;\n          }\n        } else if (dir === \"client\") {\n          // If we're bundling an app for a server architecture, any files\n          // contained by a client-only directory that is not contained by\n          // a node_modules directory must be ignored.\n          return;\n        }\n      }\n\n      if (dir === \"node_modules\") {\n        // Accept any file within a node_modules directory.\n        return installPath;\n      }\n    }\n\n    return installPath;\n  }\n\n  _splitPath(path) {\n    const partsInReverse = [];\n    for (let dir; (dir = pathDirname(path)) !== path; path = dir) {\n      partsInReverse.push(pathBasename(path));\n    }\n    return partsInReverse.reverse();\n  }\n\n  // Called by this.resolver when a module identifier cannot be resolved.\n  _onMissing(id, absParentPath) {\n    const isApp = ! this.name;\n    const parentFile = this._getFile(absParentPath);\n\n    if (isApp &&\n        Resolver.isNative(id) &&\n        archMatches(this.bundleArch, \"web\")) {\n      // To ensure the native module can be evaluated at runtime, register\n      // a dependency on meteor-node-stubs/deps/<id>.js.\n      const stubId = Resolver.getNativeStubId(id);\n      if (isString(stubId) && stubId !== id) {\n        if (parentFile &&\n            parentFile.deps) {\n          parentFile.deps[stubId] = parentFile.deps[id];\n        }\n        return this.resolver.resolve(stubId, absParentPath);\n      }\n    }\n\n    const possiblySpurious =\n      parentFile &&\n      parentFile.deps &&\n      has(parentFile.deps, id) &&\n      parentFile.deps[id].possiblySpurious;\n\n    const info = {\n      packageName: this.name,\n      parentPath: absParentPath,\n      bundleArch: this.bundleArch,\n      possiblySpurious,\n    };\n\n    // If the imported identifier is neither absolute nor relative, but\n    // top-level, then it might be satisfied by a package installed in\n    // the top-level node_modules directory, and we should record the\n    // missing dependency so that we can include it in the app bundle.\n    if (parentFile) {\n      const missing =\n        parentFile.missingNodeModules ||\n        Object.create(null);\n      missing[id] = info;\n      parentFile.missingNodeModules = missing;\n    }\n\n    if (! has(this.allMissingNodeModules, id) ||\n        ! info.possiblySpurious) {\n      // Allow any non-spurious identifier to replace an existing\n      // possibly spurious identifier.\n      this.allMissingNodeModules[id] = info;\n    }\n  }\n\n  _addPkgJsonToOutput(pkgJsonPath, pkg) {\n    if (! this._getFile(pkgJsonPath)) {\n      const data = new Buffer(map(pkg, (value, key) => {\n        return `exports.${key} = ${JSON.stringify(value)};\\n`;\n      }).join(\"\"));\n\n      const relPkgJsonPath = pathRelative(this.sourceRoot, pkgJsonPath);\n\n      const pkgFile = {\n        type: \"js\", // We represent the JSON module with JS.\n        data,\n        deps: {}, // Avoid accidentally re-scanning this file.\n        sourcePath: relPkgJsonPath,\n        installPath: this._getInstallPath(pkgJsonPath),\n        servePath: relPkgJsonPath,\n        hash: sha1(data),\n        lazy: true,\n        imported: true,\n      };\n\n      this._addFile(pkgJsonPath, pkgFile);\n    }\n  }\n}\n\neach([\"_readFile\", \"_findImportedModuleIdentifiers\",\n      \"_getInstallPath\"], funcName => {\n  ImportScanner.prototype[funcName] = Profile(\n    `ImportScanner#${funcName}`, ImportScanner.prototype[funcName]);\n});\n"
  },
  {
    "path": "tools/isobuild/isopack-cache.js",
    "content": "var _ = require('underscore');\n\nvar buildmessage = require('../utils/buildmessage.js');\nvar compiler = require('./compiler.js');\nvar files = require('../fs/files.js');\nvar isopackModule = require('./isopack.js');\nvar watch = require('../fs/watch.js');\nvar colonConverter = require('../utils/colon-converter.js');\nvar Profile = require('../tool-env/profile.js').Profile;\nvar archinfo = require('../utils/archinfo.js');\n\nexport class IsopackCache {\n  constructor(options) {\n    var self = this;\n    options = options || {};\n\n    // cacheDir may be null; in this case, we just don't ever save things to disk.\n    self.cacheDir = options.cacheDir;\n\n    // Root directory for caches used by build plugins.  Can be null, in which\n    // case we never give the build plugins a cache.  The directory structure is:\n    // <pluginCacheDirRoot>/<escapedPackageName>/<version>, where <version> is\n    // either the package's version if it's a versioned package, or \"local\" if\n    // it's a local package.  In the latter case, we make sure to empty it any\n    // time we rebuild the package.\n    self._pluginCacheDirRoot = options.pluginCacheDirRoot;\n\n    // This is a bit of a hack, but basically: we really don't want to spend time\n    // building web.cordova unibuilds in a project that doesn't have any Cordova\n    // platforms. (Note that we need to be careful with 'meteor publish' to still\n    // publish a web.cordova unibuild!)\n    self._includeCordovaUnibuild = !! options.includeCordovaUnibuild;\n\n    // Defines the versions of packages that we build. Must be set.\n    self._packageMap = options.packageMap;\n\n    // tropohouse may be null; in this case, we can't load versioned packages.\n    // eg, for building isopackets.\n    self._tropohouse = options.tropohouse;\n\n    // If provided, this is another IsopackCache for the same cache dir; when\n    // loading Isopacks, if they are definitely unchanged we can load the\n    // in-memory objects from this cache instead of recompiling.\n    self._previousIsopackCache = options.previousIsopackCache;\n    if (self._previousIsopackCache &&\n        self._previousIsopackCache.cacheDir !== self.cacheDir) {\n      throw Error(\"previousIsopackCache has different cacheDir!\");\n    }\n\n    // Map from package name to Isopack.\n    self._isopacks = Object.create(null);\n\n    self._noLineNumbers = !! options.noLineNumbers;\n\n    self._lintLocalPackages = !! options.lintLocalPackages;\n    self._lintPackageWithSourceRoot = options.lintPackageWithSourceRoot;\n\n    self.allLoadedLocalPackagesWatchSet = new watch.WatchSet;\n  }\n\n  buildLocalPackages(rootPackageNames) {\n    var self = this;\n    buildmessage.assertInCapture();\n\n    if (self.cacheDir) {\n      files.mkdir_p(self.cacheDir);\n    }\n\n    var onStack = {};\n    if (rootPackageNames) {\n      _.each(rootPackageNames, function (name) {\n        self._ensurePackageLoaded(name, onStack);\n      });\n    } else {\n      self._packageMap.eachPackage(function (name, packageInfo) {\n        self._ensurePackageLoaded(name, onStack);\n      });\n    }\n  }\n\n  wipeCachedPackages(packages) {\n    var self = this;\n    if (packages) {\n      // Wipe specific packages.\n      _.each(packages, function (packageName) {\n        if (self.cacheDir) {\n          files.rm_recursive(self._isopackDir(packageName));\n        }\n        if (self._pluginCacheDirRoot) {\n          files.rm_recursive(self._pluginCacheDirForPackage(packageName));\n        }\n      });\n    } else {\n      // Wipe all packages.\n      if (self.cacheDir) {\n        files.rm_recursive(self.cacheDir);\n      }\n      if (self._pluginCacheDirRoot) {\n        files.rm_recursive(self._pluginCacheDirRoot);\n      }\n    }\n  }\n\n  // Returns the isopack (already loaded in memory) for a given name. It is an\n  // error to call this if it's not already loaded! So it should only be called\n  // after buildLocalPackages has returned, or in the process of building a\n  // package whose dependencies have all already been built.\n  getIsopack(name) {\n    var self = this;\n    if (! _.has(self._isopacks, name)) {\n      throw Error(\"isopack \" + name + \" not yet loaded?\");\n    }\n    return self._isopacks[name];\n  }\n\n  eachBuiltIsopack(iterator) {\n    var self = this;\n    _.each(self._isopacks, function (isopack, packageName) {\n      iterator(packageName, isopack);\n    });\n  }\n\n  getSourceRoot(name, arch) {\n    const packageInfo = this._packageMap.getInfo(name);\n\n    if (packageInfo) {\n      if (packageInfo.kind === \"local\") {\n        return packageInfo.packageSource.sourceRoot;\n      }\n\n      if (packageInfo.kind === \"versioned\") {\n        const isopackPath = this._tropohouse.packagePath(\n          name,\n          packageInfo.version\n        );\n\n        return files.realpath(files.pathJoin(isopackPath, arch));\n      }\n    }\n\n    return null;\n  }\n\n  uses(isopack, name, arch) {\n    if (! isopack) {\n      return false;\n    }\n\n    if (isopack.name === name) {\n      // Packages use themselves.\n      return true;\n    }\n\n    arch = arch && archinfo.withoutSpecificOs(arch);\n\n    return _.some(isopack.unibuilds, u => {\n      if (arch && ! archinfo.matches(u.arch, arch)) {\n        return false;\n      }\n\n      return _.some(u.uses, use => {\n        return this.implies(\n          this._isopacks[use.package],\n          name,\n          arch,\n        );\n      });\n    });\n  }\n\n  implies(isopack, name, arch) {\n    if (! isopack) {\n      return false;\n    }\n\n    if (isopack.name === name) {\n      // Packages imply themselves.\n      return true;\n    }\n\n    arch = arch && archinfo.withoutSpecificOs(arch);\n\n    return _.some(isopack.unibuilds, u => {\n      if (arch && ! archinfo.matches(u.arch, arch)) {\n        return false;\n      }\n\n      return _.some(u.implies, imp => {\n        return this.implies(\n          this._isopacks[imp.package],\n          name,\n          arch,\n        );\n      });\n    });\n  }\n\n  _ensurePackageLoaded(name, onStack) {\n    var self = this;\n    buildmessage.assertInCapture();\n    if (_.has(self._isopacks, name)) {\n      return;\n    }\n\n    var ensureLoaded = function (depName) {\n      if (_.has(onStack, depName)) {\n        buildmessage.error(\"circular dependency between packages \" +\n                           name + \" and \" + depName);\n        // recover by not enforcing one of the dependencies\n        return;\n      }\n      onStack[depName] = true;\n      self._ensurePackageLoaded(depName, onStack);\n      delete onStack[depName];\n    };\n\n    var packageInfo = self._packageMap.getInfo(name);\n    if (! packageInfo) {\n      throw Error(\"Depend on unknown package \" + name + \"?\");\n    }\n    var previousIsopack = null;\n    if (self._previousIsopackCache &&\n        _.has(self._previousIsopackCache._isopacks, name)) {\n      var previousInfo = self._previousIsopackCache._packageMap.getInfo(name);\n      if ((packageInfo.kind === 'versioned' &&\n           previousInfo.kind === 'versioned' &&\n           packageInfo.version === previousInfo.version) ||\n          (packageInfo.kind === 'local' &&\n           previousInfo.kind === 'local' &&\n           (packageInfo.packageSource.sourceRoot ===\n            previousInfo.packageSource.sourceRoot))) {\n        previousIsopack = self._previousIsopackCache._isopacks[name];\n      }\n    }\n\n    if (packageInfo.kind === 'local') {\n      var packageNames =\n            packageInfo.packageSource.getPackagesToLoadFirst(self._packageMap);\n      buildmessage.enterJob(\"preparing to build package \" + name, function () {\n        _.each(packageNames, function (depName) {\n          ensureLoaded(depName);\n        });\n        // If we failed to load something that this package depends on, don't\n        // load it.\n        if (buildmessage.jobHasMessages()) {\n          return;\n        }\n        Profile.time('IsopackCache Build local isopack', () => {\n          self._loadLocalPackage(name, packageInfo, previousIsopack);\n        });\n      });\n    } else if (packageInfo.kind === 'versioned') {\n      // We don't have to build this package, and we don't have to build its\n      // dependencies either! Just load it from disk.\n\n      if (!self._tropohouse) {\n        throw Error(\"Can't load versioned packages without a tropohouse!\");\n      }\n\n      var isopack = null, packagesToLoad = [];\n\n      Profile.time('IsopackCache Load local isopack', () => {\n        if (previousIsopack) {\n          // We can always reuse a previous Isopack for a versioned package, since\n          // we assume that it never changes.  (Admittedly, this means we won't\n          // notice if we download an additional build for the package.)\n          isopack = previousIsopack;\n          packagesToLoad = isopack.getStrongOrderedUsedAndImpliedPackages();\n        }\n        if (! isopack) {\n          // Load the isopack from disk.\n          buildmessage.enterJob(\n            \"loading package \" + name + \"@\" + packageInfo.version,\n            function () {\n              var pluginCacheDir;\n              if (self._pluginCacheDirRoot) {\n                pluginCacheDir = self._pluginCacheDirForVersion(\n                  name, packageInfo.version);\n                files.mkdir_p(pluginCacheDir);\n              }\n              var isopackPath = self._tropohouse.packagePath(\n                name, packageInfo.version);\n\n              var Isopack = isopackModule.Isopack;\n              isopack = new Isopack();\n              isopack.initFromPath(name, isopackPath, {\n                pluginCacheDir: pluginCacheDir\n              });\n              // If loading the isopack fails, then we don't need to look for more\n              // packages to load, but we should still recover by putting it in\n              // self._isopacks.\n              if (buildmessage.jobHasMessages()) {\n                return;\n              }\n              packagesToLoad = isopack.getStrongOrderedUsedAndImpliedPackages();\n            });\n        }\n      });\n\n      self._isopacks[name] = isopack;\n      // Also load its dependencies. This is so that if this package is being\n      // built as part of a plugin, all the transitive dependencies of the\n      // plugin are loaded.\n      _.each(packagesToLoad, function (packageToLoad) {\n        ensureLoaded(packageToLoad);\n      });\n    } else {\n      throw Error(\"unknown packageInfo kind?\");\n    }\n  }\n\n  _loadLocalPackage(name, packageInfo, previousIsopack) {\n    var self = this;\n    buildmessage.assertInCapture();\n    buildmessage.enterJob(\"building package \" + name, function () {\n      var isopack;\n      if (previousIsopack && self._checkUpToDatePreloaded(previousIsopack)) {\n        isopack = previousIsopack;\n        // We don't need to call self._lintLocalPackage here, because\n        // lintingMessages is saved on the isopack.\n      } else {\n        var pluginCacheDir;\n        if (self._pluginCacheDirRoot) {\n          pluginCacheDir = self._pluginCacheDirForLocal(name);\n        }\n\n        // Do we have an up-to-date package on disk?\n        var isopackBuildInfoJson = self.cacheDir && files.readJSONOrNull(\n          self._isopackBuildInfoPath(name));\n        var upToDate = self._checkUpToDate(isopackBuildInfoJson);\n\n        if (upToDate) {\n          // Reuse existing plugin cache dir\n          pluginCacheDir && files.mkdir_p(pluginCacheDir);\n\n          isopack = new isopackModule.Isopack();\n          isopack.initFromPath(name, self._isopackDir(name), {\n            isopackBuildInfoJson: isopackBuildInfoJson,\n            pluginCacheDir: pluginCacheDir\n          });\n          // _checkUpToDate already verified that\n          // isopackBuildInfoJson.pluginProviderPackageMap is a subset of\n          // self._packageMap, so this operation is correct. (It can't be done\n          // by isopack.initFromPath, because Isopack doesn't have access to\n          // the PackageMap, and specifically to the local catalog it knows\n          // about.)\n          isopack.setPluginProviderPackageMap(\n            self._packageMap.makeSubsetMap(\n              _.keys(isopackBuildInfoJson.pluginProviderPackageMap)));\n          // Because we don't save linter messages to disk, we have to relint\n          // this package.\n          // XXX save linter messages to disk?\n          self._lintLocalPackage(packageInfo.packageSource, isopack);\n        } else {\n          // Nope! Compile it again. Give it a fresh plugin cache.\n          if (pluginCacheDir) {\n            files.rm_recursive(pluginCacheDir);\n            files.mkdir_p(pluginCacheDir);\n          }\n          isopack = compiler.compile(packageInfo.packageSource, {\n            packageMap: self._packageMap,\n            isopackCache: self,\n            noLineNumbers: self._noLineNumbers,\n            includeCordovaUnibuild: self._includeCordovaUnibuild,\n            includePluginProviderPackageMap: true,\n            pluginCacheDir: pluginCacheDir\n          });\n          // Accept the compiler's result, even if there were errors (since it\n          // at least will have a useful WatchSet and will allow us to keep\n          // going and compile other packages that depend on this one). However,\n          // only lint it and save it to disk if there were no errors.\n          if (! buildmessage.jobHasMessages()) {\n            // Lint the package. We do this before saving so that the linter can\n            // augment the saved-to-disk WatchSet with linter-specific files.\n            self._lintLocalPackage(packageInfo.packageSource, isopack);\n            if (self.cacheDir) {\n              // Save to disk, for next time!\n              isopack.saveToPath(self._isopackDir(name), {\n                includeIsopackBuildInfo: true,\n                isopackCache: self,\n              });\n            }\n          }\n        }\n      }\n\n      self.allLoadedLocalPackagesWatchSet.merge(isopack.getMergedWatchSet());\n      self._isopacks[name] = isopack;\n    });\n  }\n\n  // Runs appropriate linters on a package. It also augments their unibuilds'\n  // WatchSets with files used by the linter.\n  _lintLocalPackage(packageSource, isopack) {\n    buildmessage.assertInJob();\n    if (!this._shouldLintPackage(packageSource)) {\n      return;\n    }\n    const {warnings, linted} = compiler.lint(packageSource, {\n      isopackCache: this,\n      isopack: isopack,\n      includeCordovaUnibuild: this._includeCordovaUnibuild\n    });\n    // Empty lintingMessages means we ran linters and everything was OK.\n    // lintingMessages left null means there were no linters to run.\n    if (linted) {\n      isopack.lintingMessages = warnings;\n    }\n  }\n\n  _checkUpToDate(isopackBuildInfoJson) {\n    var self = this;\n    // If there isn't an isopack-buildinfo.json file, then we definitely aren't\n    // up to date!\n    if (! isopackBuildInfoJson) {\n      return false;\n    }\n\n    // If we include Cordova but this Isopack doesn't, or via versa, then we're\n    // not up to date.\n    if (self._includeCordovaUnibuild !==\n        isopackBuildInfoJson.includeCordovaUnibuild) {\n      return false;\n    }\n\n    // Was the package built by a different compiler version?\n    if (isopackBuildInfoJson.builtBy !== compiler.BUILT_BY) {\n      return false;\n    }\n\n    // If any of the direct dependencies changed their version or location, we\n    // aren't up to date.\n    if (!self._packageMap.isSupersetOfJSON(\n      isopackBuildInfoJson.pluginProviderPackageMap)) {\n      return false;\n    }\n    // Merge in the watchsets for all unibuilds and plugins in the package, then\n    // check it once.\n    var watchSet = watch.WatchSet.fromJSON(\n      isopackBuildInfoJson.pluginDependencies);\n\n    _.each(isopackBuildInfoJson.unibuildDependencies, function (deps) {\n      watchSet.merge(watch.WatchSet.fromJSON(deps));\n    });\n    return watch.isUpToDate(watchSet);\n  }\n\n  _checkUpToDatePreloaded(previousIsopack) {\n    var self = this;\n\n    // If we include Cordova but this Isopack doesn't, or via versa, then we're\n    // not up to date.\n    if (self._includeCordovaUnibuild !== previousIsopack.hasCordovaUnibuild()) {\n      return false;\n    }\n\n    // We don't have to check builtBy because we don't change BUILT_BY without\n    // restarting the process.\n\n    // If any of the direct dependencies changed their version or location, we\n    // aren't up to date.\n    if (!self._packageMap.isSupersetOfJSON(\n      previousIsopack.pluginProviderPackageMap.toJSON())) {\n      return false;\n    }\n    // Merge in the watchsets for all unibuilds and plugins in the package, then\n    // check it once.\n    var watchSet = previousIsopack.getMergedWatchSet();\n    return watch.isUpToDate(watchSet);\n  }\n\n  _isopackDir(packageName) {\n    var self = this;\n    return files.pathJoin(self.cacheDir, colonConverter.convert(packageName));\n  }\n\n  _pluginCacheDirForPackage(packageName) {\n    var self = this;\n    return files.pathJoin(self._pluginCacheDirRoot,\n                          colonConverter.convert(packageName));\n  }\n\n  _pluginCacheDirForVersion(packageName, version) {\n    var self = this;\n    return files.pathJoin(\n      self._pluginCacheDirForPackage(packageName), version);\n  }\n\n  _pluginCacheDirForLocal(packageName) {\n    var self = this;\n    // assumes that `local` is not a valid package version.\n    return files.pathJoin(\n      self._pluginCacheDirForPackage(packageName), 'local');\n  }\n\n  _isopackBuildInfoPath(packageName) {\n    var self = this;\n    return files.pathJoin(\n      self._isopackDir(packageName), 'isopack-buildinfo.json');\n  }\n\n  forgetPreviousIsopackCache() {\n    var self = this;\n    self._previousIsopackCache = null;\n  }\n\n  _shouldLintPackage(packageSource) {\n    if (this._lintLocalPackages) {\n      return true;\n    }\n    if (! this._lintPackageWithSourceRoot) {\n      return false;\n    }\n    return this._lintPackageWithSourceRoot === packageSource.sourceRoot;\n  }\n\n  getLintingMessagesForLocalPackages() {\n    const messages = new buildmessage._MessageSet();\n    let anyLinters = false;\n\n    this._packageMap.eachPackage((name, packageInfo) => {\n      const isopack = this._isopacks[name];\n      if (packageInfo.kind === 'local') {\n        if (!this._shouldLintPackage(packageInfo.packageSource)) {\n          return;\n        }\n        const isopackMessages = isopack.lintingMessages;\n        if (isopackMessages) {\n          anyLinters = true;\n          messages.merge(isopackMessages);\n        }\n      }\n    });\n\n    // return null if no linters were ever run\n    if (! anyLinters) { return null; }\n\n    return messages;\n  }\n}\n"
  },
  {
    "path": "tools/isobuild/isopack.js",
    "content": "var assert = require('assert');\nvar compiler = require('./compiler.js');\nvar archinfo = require('../utils/archinfo.js');\nvar _ = require('underscore');\nvar linker = require('./linker.js');\nvar buildmessage = require('../utils/buildmessage.js');\nimport Builder from './builder.js';\nvar bundler = require('./bundler.js');\nvar watch = require('../fs/watch.js');\nvar files = require('../fs/files.js');\nvar isopackets = require('../tool-env/isopackets.js');\nvar colonConverter = require('../utils/colon-converter.js');\nvar utils = require('../utils/utils.js');\nvar buildPluginModule = require('./build-plugin.js');\nvar Console = require('../console/console.js').Console;\nvar Profile = require('../tool-env/profile.js').Profile;\n\nvar rejectBadPath = function (p) {\n  if (p.match(/\\.\\./)) {\n    throw new Error(\"bad path: \" + p);\n  }\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Unibuild\n///////////////////////////////////////////////////////////////////////////////\n\n// Options:\n// - kind [required] (main/plugin/app)\n// - arch [required]\n// - uses\n// - implies\n// - watchSet\n// - nodeModulesDirectories\n// - declaredExports\n// - resources\n\nvar nextBuildId = 1;\nvar Unibuild = function (isopack, options) {\n  var self = this;\n  options = options || {};\n  self.pkg = isopack;\n\n  self.kind = options.kind;\n  self.arch = options.arch;\n\n  self.uses = options.uses;\n  self.implies = options.implies || [];\n\n  // This WatchSet will end up having the watch items from the\n  // SourceArch (such as package.js or .meteor/packages), plus all of\n  // the actual source files for the unibuild (including items that we\n  // looked at to find the source files, such as directories we\n  // scanned).\n  self.watchSet = options.watchSet || new watch.WatchSet();\n\n  // Each Unibuild is given a unique id when it's loaded (it is\n  // not saved to disk). This is just a convenience to make it easier\n  // to keep track of Unibuilds in a map; it's used by bundler\n  // and compiler. We put some human readable info in here too to make\n  // debugging easier.\n  self.id = self.pkg.name + \".\" + self.kind + \"@\" + self.arch + \"#\" +\n    (nextBuildId ++);\n\n  // 'declaredExports' are the variables which are exported from this package.\n  // A list of objects with keys 'name' (required) and 'testOnly' (boolean,\n  // defaults to false).\n  self.declaredExports = options.declaredExports;\n\n  // All of the data provided for eventual inclusion in the bundle,\n  // other than JavaScript that still needs to be fed through the\n  // final link stage. A list of objects with these keys:\n  //\n  // type: \"source\", \"head\", \"body\", \"asset\". (resources produced by\n  // legacy source handlers can also be \"js\" or \"css\".\n  //\n  // data: The contents of this resource, as a Buffer. For example,\n  // for \"head\", the data to insert in <head>; for \"js\", the\n  // JavaScript source code (which may be subject to further\n  // processing such as minification); for \"asset\", the contents of a\n  // static resource such as an image.\n  //\n  // servePath: The (absolute) path at which the resource would prefer\n  // to be served. Interpretation varies by type. For example, always\n  // honored for \"asset\", ignored for \"head\" and \"body\", sometimes\n  // honored for CSS but ignored if we are concatenating.\n  //\n  // sourceMap: Allowed only for \"js\". If present, a string.\n  //\n  // fileOptions: for \"source\", the options passed to `api.addFiles`.\n  // plugin-specific.\n  //\n  // extension: for \"source\", the file extension that this matched\n  // against at build time. null if matched against a specific filename.\n  self.resources = options.resources;\n\n  // Map from absolute paths of node_modules directories to\n  // NodeModulesDirectory objects.\n  self.nodeModulesDirectories = options.nodeModulesDirectories;\n\n  // Provided for backwards compatibility; please use\n  // unibuild.nodeModulesDirectories instead!\n  _.some(self.nodeModulesDirectories, (nmd, nodeModulesPath) => {\n    if (! nmd.local) {\n      self.nodeModulesPath = nodeModulesPath;\n      return true;\n    }\n  });\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Isopack\n///////////////////////////////////////////////////////////////////////////////\n\n// Meteor has a packaging system called \"Isobuild\". Isobuild knows how to\n// compile the same JavaScript code-base to different architectures: browser,\n// node.js-like server environment (could be Rhino or other) or a webview in a\n// Cordova mobile app.\n//\n// Each package used by Isobuild forms an Isopack. Isopack is a package format\n// containing source code for each architecture it can be ran on.\n// Each separate part built for a separate architecture is called \"Unibuild\".\n//\n// There are multiple reasons why we can't call it just \"build\" and historically\n// the name \"Unibuild\" has been associated with parts of Isopacks. We also can't\n// call it \"Isobuild\" because this is the brand-name of the whole\n// build/packaging system.\nvar Isopack = function () {\n  var self = this;\n\n  // These have the same meaning as in PackageSource.\n  self.name = null;\n  self.metadata = {};\n  self.version = null;\n  self.isTest = false;\n  self.debugOnly = false;\n  self.prodOnly = false;\n  self.testOnly = false;\n\n  // Unibuilds, an array of class Unibuild.\n  self.unibuilds = [];\n\n  // Plugins in this package. Map from plugin name to {arch -> JsImage}.\n  // Plugins are package-supplied classes and functions that can change the\n  // build process: introduce a new source processor (compiler, minifier,\n  // linter)\n  self.plugins = {};\n\n  self.cordovaDependencies = {};\n\n  // isobuild:* pseudo-packages which this package depends on.\n  self.isobuildFeatures = [];\n\n  // -- Information for up-to-date checks --\n  // Data in this section is only set if the Isopack was directly created by\n  // compiler.compile or read from a package compiled by IsopackCache (with its\n  // isopack-buildinfo.json file). They are not set for Isopacks read from\n  // the tropohouse.\n\n  // XXX this is likely to change once we have build versions\n  //\n  // A WatchSet for the full transitive dependencies for all plugins in this\n  // package, as well as this package's package.js. If any of these dependencies\n  // change, our plugins need to be rebuilt... but also, any package that\n  // directly uses this package needs to be rebuilt in case the change to\n  // plugins affected compilation.\n  self.pluginWatchSet = new watch.WatchSet();\n\n  // -- Loaded plugin state --\n\n  // True if plugins have been initialized (if ensurePluginsInitialized has\n  // been called)\n  self._pluginsInitialized = false;\n\n  // The SourceProcessors registered by plugins defined by this package.  Each\n  // value is a SourceProcessorSet. sourceProcessors.compiler includes the\n  // legacy source handlers as well.\n  // Valid when self._pluginsInitialized is true.\n  self.sourceProcessors = {\n    compiler: null,\n    linter: null,\n    minifier: null\n  };\n\n  // See description in PackageSource. If this is set, then we include a copy of\n  // our own source, in addition to any other tools that were originally in the\n  // isopack.\n  self.includeTool = false;\n\n  // This is tools to copy from trees on disk. This is used by the\n  // isopack-merge code in tropohouse.\n  self.toolsOnDisk = [];\n\n  // A map of package dependencies that can provide a plugin for this isopack.\n  // In practice, it is every direct dependency and implied packages.\n  self.pluginProviderPackageMap = null;\n\n  // A directory on disk that plugins can use for caching. Should be created\n  // by the code that initializes the Isopack. If not provided, plugins don't\n  // get a disk cache.\n  self.pluginCacheDir = null;\n\n  // An in-memory only buildmessage.MessageSet object that is printed by the\n  // build tool when the app is linted. Is also printed when a package\n  // represented by Isopack is published.\n  self.lintingMessages = null;\n};\n\nIsopack.knownFormats = [\"unipackage-pre2\", \"isopack-1\", \"isopack-2\"];\n\n// These functions are designed to convert isopack metadata between\n// versions. They were designed to convert between unipackage-pre2 and\n// isopack-1. The differences between these formats are essentially syntactical,\n// not semantic, and occur entirely in the isopack.json file, not in the\n// individual unibuild json files. These functions are written assuming those\n// constraints, and were not actually useful in the isopack-1/isopack-2\n// transition,where most of the changes are in the unibuild level, and there's\n// actual semantic changes involved. So they are not actually used as much as\n// they were before.\nIsopack.convertOneStepForward = function (data, fromFormat) {\n  var convertedData = _.clone(data);\n  // XXX COMPAT WITH 0.9.3\n  if (fromFormat === \"unipackage-pre2\") {\n    convertedData.builds = convertedData.unibuilds;\n    delete convertedData.unibuilds;\n    return convertedData;\n  }\n  if (fromFormat === \"isopack-1\") {\n    // For now, there's no difference in this direction at the isopack level.\n    return convertedData;\n  }\n};\nIsopack.convertOneStepBackward = function (data, fromFormat) {\n  var convertedData = _.clone(data);\n  if (fromFormat === \"isopack-1\") {\n    convertedData.unibuilds = convertedData.builds;\n    convertedData.format = \"unipackage-pre2\";\n    delete convertedData.builds;\n    return convertedData;\n  }\n  if (fromFormat === \"isopack-2\") {\n    // The conversion from isopack-2 requires converting the nested\n    // unibuild data as well.  This shouldn't happen.\n    throw Error(\"Can't automatically convert backwards from isopack-2\");\n  }\n};\nIsopack.convertIsopackFormat = Profile(\n  \"Isopack.convertIsopackFormat\", function (data, fromFormat, toFormat) {\n  var fromPos = _.indexOf(Isopack.knownFormats, fromFormat);\n  var toPos = _.indexOf(Isopack.knownFormats, toFormat);\n  var step = fromPos < toPos ? 1 : -1;\n\n  if (fromPos === -1) {\n    throw new Error(\"Can't convert from unknown Isopack format: \" + fromFormat);\n  }\n  if (toPos === -1) {\n    throw new Error(\"Can't convert to unknown Isopack format: \" + toFormat);\n  }\n\n  while (fromPos !== toPos) {\n    if (step > 0) {\n      data = Isopack.convertOneStepForward(data, fromFormat);\n    } else {\n      data = Isopack.convertOneStepBackward(data, fromFormat);\n    }\n\n    fromPos += step;\n    fromFormat = Isopack.knownFormats[fromPos];\n  }\n\n  return data;\n});\n\n// Read the correct file from isopackDirectory and convert to current format\n// of the isopack metadata. Returns null if there is no package here.\nIsopack.readMetadataFromDirectory =\n  Profile(\"Isopack.readMetadataFromDirectory\", function (isopackDirectory) {\n  var metadata = null;\n  let originalVersion = null;\n\n  // deal with different versions of \"isopack.json\", backwards compatible\n  var isopackJsonPath = files.pathJoin(isopackDirectory, \"isopack.json\");\n  var unipackageJsonPath = files.pathJoin(isopackDirectory, \"unipackage.json\");\n\n  if (files.exists(isopackJsonPath)) {\n    var isopackJson = JSON.parse(files.readFile(isopackJsonPath));\n\n    if (isopackJson['isopack-2']) {\n      metadata = isopackJson['isopack-2'];\n      originalVersion = 'isopack-2';\n    } else if (isopackJson['isopack-1']) {\n      metadata = Isopack.convertIsopackFormat(\n        isopackJson['isopack-1'], 'isopack-1', 'isopack-2');\n      originalVersion = 'isopack-1';\n    } else {\n      // This file is from the future and no longer supports this version\n      throw new Error(\"Could not find isopack data supported any supported format (isopack-1 or isopack-2).\\n\" +\n        \"This isopack was likely built with a much newer version of Meteor.\");\n    }\n  } else if (files.exists(unipackageJsonPath)) {\n    // super old version with different file name\n    // XXX COMPAT WITH 0.9.3\n    if (files.exists(unipackageJsonPath)) {\n      metadata = JSON.parse(files.readFile(unipackageJsonPath));\n\n      metadata = Isopack.convertIsopackFormat(metadata,\n        \"unipackage-pre2\", \"isopack-2\");\n      originalVersion = 'unipackage-pre2';\n    }\n\n    if (metadata.format !== \"unipackage-pre2\") {\n      // We don't support pre-0.9.0 isopacks, but we do know enough to delete\n      // them if we find them in an isopack cache somehow (rather than crash).\n      if (metadata.format === \"unipackage-pre1\") {\n        throw new exports.OldIsopackFormatError();\n      }\n\n      throw new Error(\"Unsupported isopack format: \" +\n                      JSON.stringify(metadata.format));\n    }\n  }\n\n  return {metadata, originalVersion};\n});\n\n_.extend(Isopack.prototype, {\n  // Make a dummy (empty) package that contains nothing of interest.\n  // XXX used?\n  initEmpty: function (name) {\n    var self = this;\n    self.name = name;\n  },\n\n  // This is primarily intended to be used by the compiler. After\n  // calling this, call addUnibuild to add the unibuilds.\n  initFromOptions: function (options) {\n    var self = this;\n    self.name = options.name;\n    self.metadata = options.metadata;\n    self.version = options.version;\n    self.isTest = options.isTest;\n    self.plugins = options.plugins;\n    self.cordovaDependencies = options.cordovaDependencies;\n    self.pluginWatchSet = options.pluginWatchSet;\n    self.npmDiscards = options.npmDiscards;\n    self.includeTool = options.includeTool;\n    self.debugOnly = options.debugOnly;\n    self.prodOnly = options.prodOnly;\n    self.testOnly = options.testOnly;\n    self.pluginCacheDir = options.pluginCacheDir || null;\n    self.isobuildFeatures = options.isobuildFeatures;\n  },\n\n  // Programmatically add a unibuild to this Isopack. Should only be\n  // called as part of building up a new Isopack using\n  // initFromOptions. 'options' are the options to the Unibuild\n  // constructor.\n  addUnibuild: function (options) {\n    var self = this;\n    self.unibuilds.push(new Unibuild(self, options));\n  },\n\n  setPluginProviderPackageMap: function (pluginProviderPackageMap) {\n    var self = this;\n    self.pluginProviderPackageMap = pluginProviderPackageMap;\n  },\n\n  getSourceFilesUnderSourceRoot: Profile(\n    \"Isopack#getSourceFilesUnderSourceRoot\", function (sourceRoot) {\n    var self = this;\n    var sourceFiles = {};\n    var anySourceFiles = false;\n    var addSourceFilesFromWatchSet = function (watchSet) {\n      _.each(watchSet.files, function (hash, filename) {\n        if (! hash) {\n          // If a file has a falsy hash, that means the file does/should\n          // not exist.\n          return;\n        }\n\n        anySourceFiles = true;\n        var relativePath = files.pathRelative(sourceRoot, filename);\n        // We only want files that are actually under sourceRoot.\n        if (relativePath.substr(0, 3) === '..' + files.pathSep) {\n          return;\n        }\n        sourceFiles[relativePath] = true;\n      });\n    };\n    addSourceFilesFromWatchSet(self.pluginWatchSet);\n    _.each(self.unibuilds, function (u) {\n      addSourceFilesFromWatchSet(u.watchSet);\n    });\n\n    // Were we actually built from source or loaded from an IsopackCache? If so\n    // then there should be at least one source file in some WatchSet. If not,\n    // return null.\n    if (! anySourceFiles) {\n      return null;\n    }\n    return _.keys(sourceFiles);\n  }),\n\n  // An sorted array of all the architectures included in this package.\n  architectures: Profile(\"Isopack#architectures\", function () {\n    var self = this;\n    var archSet = {};\n    _.each(self.unibuilds, function (unibuild) {\n      archSet[unibuild.arch] = true;\n    });\n    _.each(self._toolArchitectures(), function (arch) {\n      archSet[arch] = true;\n    });\n    _.each(self.plugins, function (plugin, name) {\n      _.each(plugin, function (plug, arch) {\n        archSet[arch] = true;\n      });\n    });\n    var arches = _.keys(archSet).sort();\n    // Ensure that our buildArchitectures string does not look like\n    //    web+os+os.osx.x86_64\n    // This would happen if there is an 'os' unibuild but a platform-specific\n    // tool (eg, in meteor-tool).  This would confuse catalog.getBuildsForArches\n    // into thinking that it would work for Linux, since the 'os' means\n    // 'works on any Node server'.\n    if (_.any(arches, function (a) { return a.match(/^os\\./); })) {\n      arches = _.without(arches, 'os');\n    }\n    return arches;\n  }),\n\n  // A sorted plus-separated string of all the architectures included in this\n  // package.\n  buildArchitectures: function () {\n    var self = this;\n    return self.architectures().join('+');\n  },\n\n  // Returns true if we think that this isopack is platform specific (contains\n  // binary builds)\n  platformSpecific: function () {\n    var self = this;\n    return _.any(self.architectures(), function (arch) {\n      return arch.match(/^os\\./);\n    });\n  },\n\n  tarballName: function () {\n    var self = this;\n    return colonConverter.convert(self.name) + '-' + self.version;\n  },\n\n  _toolArchitectures: function () {\n    var self = this;\n    var toolArches = _.pluck(self.toolsOnDisk, 'arch');\n    self.includeTool && toolArches.push(archinfo.host());\n    return _.uniq(toolArches).sort();\n  },\n\n  // Return the unibuild of the package to use for a given target architecture\n  // (eg, 'os.linux.x86_64' or 'web'), or throw an exception if that\n  // packages can't be loaded under these circumstances.\n  getUnibuildAtArch: Profile(\"Isopack#getUnibuildAtArch\", function (arch) {\n    var self = this;\n\n    let chosenArch = archinfo.mostSpecificMatch(\n      arch, _.pluck(self.unibuilds, 'arch'));\n    if (! chosenArch && arch.match(/^os\\./)) {\n      // Special-case: we're looking for a specific server platform and\n      // it's not available. (eg, we're deploying from a Mac to Linux and\n      // are processing a local package with binary npm deps).  Search\n      // again for the host version, which might find the Mac version.\n      chosenArch =\n        archinfo.mostSpecificMatch(archinfo.host(), _.pluck(self.unibuilds, 'arch'));\n    }\n    if (! chosenArch) {\n      buildmessage.error(\n        (self.name || \"this app\") +\n          \" is not compatible with architecture '\" + arch + \"'\",\n        { secondary: true });\n      // recover by returning by no unibuilds\n      return null;\n    }\n    return _.findWhere(self.unibuilds, { arch: chosenArch });\n  }),\n\n  _checkPluginsInitialized: function () {\n    var self = this;\n    if (self._pluginsInitialized) {\n      return;\n    }\n    throw Error(\"plugins not yet initialized?\");\n  },\n\n  // If this package has plugins, initialize them (run the startup\n  // code in them so that they register their extensions). Idempotent.\n  ensurePluginsInitialized: Profile(\"Isopack#ensurePluginsInitialized\", function () {\n    var self = this;\n\n    buildmessage.assertInJob();\n\n    if (self._pluginsInitialized) {\n      return;\n    }\n\n    self.sourceProcessors.compiler = new buildPluginModule.SourceProcessorSet(\n      self.displayName(), { hardcodeJs: true, singlePackage: true });\n    self.sourceProcessors.linter = new buildPluginModule.SourceProcessorSet(\n      self.displayName(), { singlePackage: true, allowConflicts: true });\n    self.sourceProcessors.minifier = new buildPluginModule.SourceProcessorSet(\n      self.displayName(), { singlePackage: true });\n\n    _.each(self.plugins, function (pluginsByArch, name) {\n      var arch = archinfo.mostSpecificMatch(\n        archinfo.host(), _.keys(pluginsByArch));\n      if (! arch) {\n        buildmessage.error(\"package `\" + name + \"` is built for incompatible \" +\n                           \"architecture\");\n        // Recover by ignoring plugin\n        // XXX does this recovery work?\n        return;\n      }\n\n      var plugin = pluginsByArch[arch];\n      buildmessage.enterJob({\n        title: \"loading plugin `\" + name +\n          \"` from package `\" + self.name + \"`\"\n        // don't necessarily have rootPath anymore\n        // (XXX we do, if the isopack was locally built, which is\n        // the important case for debugging. it'd be nice to get this\n        // case right.)\n      }, function () {\n        // Make a new Plugin API object for this plugin.\n        var Plugin = self._makePluginApi();\n        plugin.load({ Plugin: Plugin, Profile: Profile });\n      });\n    });\n\n    // Instantiate each of the registered batch plugins.  Note that we don't\n    // do this directly in the registerCompiler (etc) call, because we want\n    // to allow people to do something like:\n    //   Plugin.registerCompiler({...}, function () { return new C; });\n    //   var C = function () {...}\n    // and so we want to wait for C to be defined.\n    _.each(self.sourceProcessors, (sourceProcessorSet) => {\n      _.each(sourceProcessorSet.allSourceProcessors, (sourceProcessor) => {\n        sourceProcessor.instantiatePlugin();\n      });\n    });\n\n    self._pluginsInitialized = true;\n  }),\n\n  _makePluginApi: function () {\n    var isopack = this;\n\n    /**\n     * @global\n     * @namespace Plugin\n     * @summary The namespace that is exposed inside build plugin files.\n     */\n    var Plugin = {\n      // 'extension' is a file extension without the separation dot\n      // (eg 'js', 'coffee', 'coffee.md')\n      //\n      // 'options' can be omitted. The only known option is 'isTemplate', which\n      // is a bit of a hack meaning \"in an app, these files should be loaded\n      // before non-templates\".\n      //\n      // 'handler' is a function that takes a single argument, a\n      // CompileStep (#CompileStep)\n\n      /**\n       * @summary Inside a build plugin source file specified in\n       * [Package.registerBuildPlugin](#Package-registerBuildPlugin),\n       * add a handler to compile files with a certain file extension.\n       * @param  {String} fileExtension The file extension that this plugin\n       * should handle, without the first dot.\n       * Examples: `\"coffee\"`, `\"coffee.md\"`.\n       * @param  {Function} handler  A function that takes one argument,\n       * a CompileStep object.\n       *\n       * Documentation for CompileStep is available [on the GitHub Wiki](https://github.com/meteor/meteor/wiki/CompileStep-API-for-Build-Plugin-Source-Handlers).\n       * @memberOf Plugin\n       * @locus Build Plugin\n       * @deprecated since 1.2\n       * XXX COMPAT WITH 1.1\n       */\n      registerSourceHandler: function (extension, options, handler) {\n        if (!handler) {\n          handler = options;\n          options = {};\n        }\n\n        // The popular package mquandalle:bower has a call to\n        // `registerSourceHandler('json', null)` for some reason, to\n        // work around some behavior of Meteor believed to be a bug. We\n        // think that new features of registerCompiler like being able\n        // to register for filenames will allow them to drop that line,\n        // but in the meantime we might as well not choke on it. (The\n        // old implementation coincidentally didn't choke.)\n        if (!handler) {\n          handler = function () {};\n        }\n\n        isopack.sourceProcessors.compiler.addLegacyHandler({\n          extension,\n          handler,\n          packageDisplayName: isopack.displayName(),\n          isTemplate: !!options.isTemplate,\n          archMatching: options.archMatching\n        });\n      },\n\n      _registerSourceProcessor: function (\n        {extensions, filenames, archMatching, isTemplate},\n        factory,\n        {sourceProcessorSet, methodName, featurePackage}) {\n        if (!isopack.featureEnabled(featurePackage)) {\n          // This error is OK because we only define 1.0.0 for each of these\n          // feature packages (in compiler.KNOWN_ISOBUILD_FEATURE_PACKAGES).\n          buildmessage.error(\n            `your package must \\`api.use('${ featurePackage }@1.0.0')\\` in ` +\n              `order for its plugins to call Plugin.${ methodName }`);\n          return;\n        }\n\n        const hasExtensions = (extensions &&\n                               extensions instanceof Array &&\n                               extensions.length > 0);\n        const hasFilenames = (filenames &&\n                              filenames instanceof Array &&\n                              filenames.length > 0);\n        if (! (hasExtensions || hasFilenames)) {\n          buildmessage.error(\"Plugin.\" + methodName + \" must specify a \" +\n                             \"non-empty array of extensions or filenames\",\n                             { useMyCaller: 3 });\n          // recover by ignoring\n          return;\n        }\n\n        // Don't let extensions or filenames try to look for directories (in the\n        // way that WatchSet expresses them).\n        if (extensions && extensions.some(e => e.endsWith('/'))) {\n          buildmessage.error(\n            `Plugin.${methodName}: extensions may not end in /`);\n          // recover by ignoring\n          return;\n        }\n        if (filenames && filenames.some(f => f.endsWith('/'))) {\n          buildmessage.error(\n            `Plugin.${methodName}: filenames may not end in /`);\n          // recover by ignoring\n          return;\n        }\n\n        if (typeof factory !== 'function') {\n          buildmessage.error(methodName + \" call must \"\n                             + \"specify a factory function\",\n                             { useMyCaller: 3 });\n          // recover by ignoring\n          return;\n        }\n\n        const sp = new buildPluginModule.SourceProcessor({\n          isopack: isopack,\n          extensions: extensions,\n          filenames: filenames,\n          archMatching: archMatching,\n          isTemplate: isTemplate,\n          factoryFunction: factory,\n          methodName: methodName\n        });\n        // This logs a buildmessage on conflicts.\n        sourceProcessorSet.addSourceProcessor(sp);\n      },\n\n      // Compilers are part of the Batch Plugins API.\n      //\n      // A compiler plugin is provided by packages to participate in\n      // the build process. A compiler can register file extensions and\n      // filenames it handles and the build tool will call the compiler's\n      // `processFilesForTarget` method once for each target (eg, the server\n      // or client program) with all of the files in the target.\n      //\n      // Compilers are run on application bundling (in bundle.js).\n      // This is different from the legacy registerSourceHandler API,\n      // which runs on a single file at a time when a *package* is built.\n      // Published Isopack packages contain the original sources of\n      // files handled by registerCompiler, not the generated output,\n      // so compilers can be involved in the very end, when the app is bundled\n      // (not in package publish time).  (Note that this requires a new\n      // Isopack format, 'isopack-2'; versions of packages published with new\n      // compilers cannot be used with previous releases of Meteor, but\n      // Version Solver knows this and will select an older compatible\n      // version if possible.\n      //\n      // Unlike the legacy API called \"source handlers\" (deprecated in\n      // Meteor 1.2), compiler plugins can handle all files for the target,\n      // making independent decisions about caching and dependencies resolution.\n      //\n      // The factory function must return an instance of a compiler.\n      //\n      // Note: It's important to ensure that all plugins that want to call\n      // plugin compiler use the isobuild:compiler-plugin fake package, so that\n      // Version Solver will not let you use registerCompiler plugins with old\n      // versions of the tool.\n\n      /**\n       * @summary Inside a build plugin source file specified in\n       * [Package.registerBuildPlugin](#Package-registerBuildPlugin),\n       * add a compiler that will handle files with certain extensions or\n       * filenames.\n       * @param {Object} options\n       * @param {String[]} options.extensions The file extensions that this\n       * plugin should handle, without the first dot.\n       * Examples: `[\"coffee\", \"coffee.md\"]`.\n       * @param {String[]} options.filenames The list of filenames\n       * that this plugin should handle. Examples: `[\"config.json\"]`.\n       * @param {Function} factory A function that returns an instance\n       * of a compiler class.\n       *\n       * More detailed documentation for build plugins is available [on the GitHub Wiki](https://github.com/meteor/meteor/wiki/Build-Plugins-API).\n       * @memberOf Plugin\n       * @locus Build Plugin\n       */\n      registerCompiler: function (options, factory) {\n        Plugin._registerSourceProcessor(options || {}, factory, {\n          sourceProcessorSet: isopack.sourceProcessors.compiler,\n          methodName: \"registerCompiler\",\n          featurePackage: \"isobuild:compiler-plugin\"\n        });\n      },\n\n      // Linters are part of the Batch Plugin API.\n      //\n      // A linter plugin provides a Linter instance. The linter is\n      // given a batch of source files for the target according to\n      // linter's declared file extensions and filenames (e.g.: '*.js',\n      // '.jshintrc').\n      //\n      // Linters don't output any files. They can only raise an error\n      // message on one of the source files to force the build tool to\n      // print a linting message.\n      //\n      // The factory function must return an instance of the linter.\n      // The linter must have the `processFilesForPackage` method that\n      // has two arguments:\n      // - inputFiles - LinterFile - sources instances\n      // - options - Object\n      //   - globals - a list of strings - global variables that can be\n      //     used in the target's scope as they are dependencies of the\n      //     package or the app. e.g.: \"Minimongo\" or \"Webapp\".\n      //\n      // Unlike compilers and minifiers, linters run on one package\n      // at a time.  Linters are run by `meteor run`, `meteor publish`,\n      // and `meteor lint`.\n\n      /**\n       * @summary Inside a build plugin source file specified in\n       * [Package.registerBuildPlugin](#Package-registerBuildPlugin),\n       * add a linter that will handle files with certain extensions or\n       * filenames.\n       * @param {Object} options\n       * @param {String[]} options.extensions The file extensions that this\n       * plugin should handle, without the first dot.\n       * Examples: `[\"js\", \"es6\", \"jsx\"]`.\n       * @param {Function} factory A function that returns an instance\n       * of a linter class.\n       *\n       * More detailed documentation for build plugins is available [on the GitHub Wiki](https://github.com/meteor/meteor/wiki/Build-Plugins-API).\n       * @memberOf Plugin\n       * @locus Build Plugin\n       */\n      registerLinter: function (options, factory) {\n        Plugin._registerSourceProcessor(options || {}, factory, {\n          sourceProcessorSet: isopack.sourceProcessors.linter,\n          methodName: \"registerLinter\",\n          featurePackage: \"isobuild:linter-plugin\"\n        });\n      },\n\n      // Minifiers are part of the Batch Plugin API.\n      //\n      // The minifiers are applied in the very end of the bundling\n      // process, after the linters and compilers. Unlike linters and\n      // compilers, minifiers are given the output of compilers and not\n      // the source files the application developer supplied.\n      //\n      // The minifier plugins can fill into 2 types of minifiers: CSS or JS.\n      // When the minifier is added to an app, it is used during \"bundling\" to\n      // compress the app code and each package's code separately.\n      // Only minifier packages directly used by an app (or implied by a package\n      // directly used by the app) are active: using a minifer's package in\n      // another package does nothing.\n      //\n      // So far, the minifiers are only run on client targets such as\n      // web.browser and web.cordova.\n      //\n      // The factory function must return an instance of a\n      // minifier. The method `processFilesForBundle` is passed a list of\n      // files, possibly a linked file per target (for JavaScript files).\n      //\n      // - files - processed files to minify\n      // - options - Object\n      //   - minifyMode - string - 'development' or 'production', based\n      //     on the bundling mode\n\n      /**\n       * @summary Inside a build plugin source file specified in\n       * [Package.registerBuildPlugin](#Package-registerBuildPlugin),\n       * add a linter that will handle files with certain extensions or\n       * filenames.\n       * @param {Object} options\n       * @param {String[]} options.extensions The file extensions that this\n       * plugin should handle, without the first dot. Can only be \"js\" or \"css\".\n       * Examples: `[\"js\", \"css\"]`.\n       * @param {String[]} options.filenames The list of filenames\n       * that this plugin should handle. Examples: `[\"config.json\"]`.\n       * @param {Function} factory A function that returns an instance\n       * of a minifier class.\n       *\n       * More detailed documentation for build plugins is available [on the GitHub Wiki](https://github.com/meteor/meteor/wiki/Build-Plugins-API).\n       * @memberOf Plugin\n       * @locus Build Plugin\n       */\n      registerMinifier: function (options, factory) {\n        var badUsedExtension = _.find(options.extensions, function (ext) {\n          return ! _.contains(['js', 'css'], ext);\n        });\n\n        if (badUsedExtension !== undefined) {\n          buildmessage.error(badUsedExtension + ': Minifiers are only allowed to register \"css\" or \"js\" extensions.');\n          return;\n        }\n\n        if (options.filenames) {\n          buildmessage.error(\"Plugin.registerMinifier does not accept `filenames`\");\n          return;\n        }\n\n        Plugin._registerSourceProcessor(options || {}, factory, {\n          sourceProcessorSet: isopack.sourceProcessors.minifier,\n          methodName: \"registerMinifier\",\n          featurePackage: \"isobuild:minifier-plugin\"\n        });\n      },\n\n      nudge: function () {\n        Console.nudge(true);\n      },\n\n      convertToOSPath: files.convertToOSPath,\n      convertToStandardPath: files.convertToStandardPath,\n      path: {\n        join: files.pathJoin,\n        normalize: files.pathNormalize,\n        relative: files.pathRelative,\n        resolve: files.pathResolve,\n        dirname: files.pathDirname,\n        basename: files.pathBasename,\n        extname: files.pathExtname,\n        sep: files.pathSep\n      },\n      fs: files.fsFixPath\n    };\n    return Plugin;\n  },\n\n  // Load a Isopack on disk.\n  //\n  // options:\n  // - isopackBuildInfoJson: parsed isopack-buildinfo.json object,\n  //   if loading from an IsopackCache.\n  initFromPath: Profile(\n    \"Isopack#initFromPath\", function (name, dir, options) {\n    var self = this;\n    options = _.clone(options || {});\n    options.firstIsopack = true;\n\n    if (options.pluginCacheDir) {\n      self.pluginCacheDir = options.pluginCacheDir;\n    }\n\n    return self._loadUnibuildsFromPath(name, dir, options);\n  }),\n\n  _loadUnibuildsFromPath: function (name, dir, options) {\n    var self = this;\n    options = options || {};\n\n    // In the tropohouse, isopack paths are symlinks (which can be updated if\n    // more unibuilds are merged in). For any given call to\n    // _loadUnibuildsFromPath, let's ensure we see a consistent isopack by\n    // realpath'ing dir.\n    dir = files.realpath(dir);\n\n    var {metadata: mainJson} = Isopack.readMetadataFromDirectory(dir);\n    if (! mainJson) {\n      throw new Error(\"No metadata files found for isopack at: \" + dir);\n    }\n\n    // isopacks didn't used to know their name, but they should.\n    if (_.has(mainJson, 'name') && name !== mainJson.name) {\n      throw new Error(\"isopack \" + name + \" thinks its name is \" +\n                      mainJson.name);\n    }\n\n    // If we're loading from an IsopackCache, we need to load the WatchSets\n    // which will be used by the bundler.  (builtBy is only used by\n    // IsopackCache._checkUpToDate. pluginProviderPackageMap will actually be\n    // set by IsopackCache afterwards, because it has access to an appropriate\n    // PackageMap which can be subset to create a new PackageMap object.)\n    var unibuildWatchSets = {};\n    if (options.isopackBuildInfoJson) {\n      if (! options.firstIsopack) {\n        throw Error(\"can't merge isopacks with buildinfo\");\n      }\n\n      // XXX should comprehensively sanitize (eg, typecheck) everything\n      // read from json files\n\n      // Read the watch sets for each unibuild\n      _.each(\n        options.isopackBuildInfoJson.unibuildDependencies,\n        function (watchSetJSON, unibuildTag) {\n          unibuildWatchSets[unibuildTag] =\n            watch.WatchSet.fromJSON(watchSetJSON);\n        });\n\n      // Read pluginWatchSet. (In the multi-sub-isopack case, these are\n      // guaranteed to be trivial (since we check that there's no\n      // isopackBuildInfoJson), so no need to merge.)\n      self.pluginWatchSet = watch.WatchSet.fromJSON(\n        options.isopackBuildInfoJson.pluginDependencies);\n    }\n\n    // If we are loading multiple isopacks, only take this stuff from the\n    // first one.\n    if (options.firstIsopack) {\n      self.name = name;\n      self.metadata = {\n        summary: mainJson.summary\n      };\n      self.version = mainJson.version;\n      self.isTest = mainJson.isTest;\n      self.debugOnly = !!mainJson.debugOnly;\n      self.prodOnly = !!mainJson.prodOnly;\n      self.testOnly = !!mainJson.testOnly;\n    }\n    _.each(mainJson.plugins, function (pluginMeta) {\n      rejectBadPath(pluginMeta.path);\n\n      var plugin = bundler.readJsImage(files.pathJoin(dir, pluginMeta.path));\n\n      if (!_.has(self.plugins, pluginMeta.name)) {\n        self.plugins[pluginMeta.name] = {};\n      }\n      // If we already loaded a plugin of this name/arch, just ignore this one.\n      if (!_.has(self.plugins[pluginMeta.name], plugin.arch)) {\n        self.plugins[pluginMeta.name][plugin.arch] = plugin;\n      }\n    });\n    self.pluginsBuilt = true;\n    _.each(mainJson.builds, function (unibuildMeta) {\n      // aggressively sanitize path (don't let it escape to parent\n      // directory)\n      rejectBadPath(unibuildMeta.path);\n\n      // Skip unibuilds we already have.\n      var alreadyHaveUnibuild = _.find(self.unibuilds, function (unibuild) {\n        return unibuild.arch === unibuildMeta.arch;\n      });\n      if (alreadyHaveUnibuild) {\n        return;\n      }\n\n      var unibuildJson = JSON.parse(\n        files.readFile(files.pathJoin(dir, unibuildMeta.path)));\n\n      var unibuildBasePath =\n        files.pathDirname(files.pathJoin(dir, unibuildMeta.path));\n\n      if (unibuildJson.format !== \"unipackage-unibuild-pre1\" &&\n          unibuildJson.format !== \"isopack-2-unibuild\") {\n        throw new Error(\"Unsupported isopack unibuild format: \" +\n                        JSON.stringify(unibuildJson.format));\n      }\n\n      // Is this unibuild the legacy pre-\"compiler plugin\" format which contains\n      // \"prelink\" resources of pre-processed JS files (as well as the\n      // \"packageVariables\" field) instead of individual \"source\" resources (and\n      // a \"declaredExports\" field)?\n      var unibuildHasPrelink =\n            unibuildJson.format === \"unipackage-unibuild-pre1\";\n\n      var resources = [];\n\n      _.each(unibuildJson.resources, function (resource) {\n        rejectBadPath(resource.file);\n        var data = files.readBufferWithLengthAndOffset(\n          files.pathJoin(unibuildBasePath, resource.file),\n          resource.length, resource.offset);\n\n        if (resource.type === \"prelink\") {\n          if (! unibuildHasPrelink) {\n            throw Error(\"Unexpected prelink resource in \" +\n                        unibuildJson.format + \" at \" + dir);\n          }\n          // We found a \"prelink\" resource, because we're processing a package\n          // published with an older version of Meteor which did not create\n          // isopack-2 isopacks and which always preprocessed and linked all JS\n          // files instead of leaving that until bundle time.  Let's pretend it\n          // was just a single js source file, but leave a \"legacyPrelink\" field\n          // on it so we can not re-link that part (and not re-analyze for\n          // assigned variables).\n          var prelinkResource = {\n            type: \"source\",\n            extension: \"js\",\n            data: data,\n            path: resource.servePath,\n            // It's a shame to have to calculate the hash here instead of having\n            // it on disk, but this only runs for legacy packages anyway.\n            hash: watch.sha1(data),\n            // Legacy prelink files definitely don't have a source processor!\n            // They were created by an Isobuild that didn't even know about\n            // source processors!\n            usesDefaultSourceProcessor: true,\n            legacyPrelink: {\n              packageVariables: unibuildJson.packageVariables || []\n            }\n          };\n          if (resource.sourceMap) {\n            rejectBadPath(resource.sourceMap);\n            prelinkResource.legacyPrelink.sourceMap = files.readFile(\n              files.pathJoin(unibuildBasePath, resource.sourceMap), 'utf8');\n          }\n          resources.push(prelinkResource);\n        } else if (resource.type === \"source\") {\n          resources.push({\n            type: \"source\",\n            extension: resource.extension,\n            usesDefaultSourceProcessor:\n              !! resource.usesDefaultSourceProcessor,\n            data: data,\n            path: resource.path,\n            hash: resource.hash,\n            fileOptions: resource.fileOptions\n          });\n        } else if (_.contains([\"head\", \"body\", \"css\", \"js\", \"asset\"],\n                              resource.type)) {\n          resources.push({\n            type: resource.type,\n            data: data,\n            servePath: resource.servePath || undefined,\n            path: resource.path || undefined\n          });\n        } else {\n          throw new Error(\"bad resource type in isopack: \" +\n                          JSON.stringify(resource.type));\n        }\n      });\n\n      var declaredExports;\n      if (unibuildHasPrelink) {\n        // Legacy unibuild; it stores packageVariables and says some of them\n        // are exports.\n        declaredExports = [];\n        _.each(unibuildJson.packageVariables, function (pv) {\n          if (pv.export) {\n            declaredExports.push({\n              name: pv.name,\n              testOnly: pv.export === 'tests'\n            });\n          }\n        });\n      } else {\n        declaredExports = unibuildJson.declaredExports || [];\n      }\n\n      unibuildJson.uses && unibuildJson.uses.forEach((use) => {\n        if (!use.weak && compiler.isIsobuildFeaturePackage(use.package) &&\n            self.isobuildFeatures.indexOf(use.package) === -1) {\n          self.isobuildFeatures.push(use.package);\n        }\n      });\n\n      const nodeModulesDirectories = bundler.NodeModulesDirectory\n        .readDirsFromJSON(unibuildJson.node_modules, {\n          packageName: self.name,\n          sourceRoot: unibuildBasePath,\n          // Rebuild binaries if unibuild arch matches host arch.\n          rebuildBinaries: archinfo.matches(\n            archinfo.host(), unibuildMeta.arch)\n        });\n\n      self.unibuilds.push(new Unibuild(self, {\n        // At some point we stopped writing 'kind's to the metadata file, so\n        // default to main.\n        kind: unibuildMeta.kind || 'main',\n        arch: unibuildMeta.arch,\n        uses: unibuildJson.uses,\n        implies: unibuildJson.implies,\n        watchSet: unibuildWatchSets[unibuildMeta.path],\n        nodeModulesDirectories,\n        declaredExports: declaredExports,\n        resources: resources\n      }));\n    });\n\n    self.cordovaDependencies = mainJson.cordovaDependencies || null;\n\n    _.each(mainJson.tools, function (toolMeta) {\n      toolMeta.rootDir = dir;\n      // XXX check for overlap\n      self.toolsOnDisk.push(toolMeta);\n    });\n\n    return true;\n  },\n\n  hasCordovaUnibuild: function () {\n    var self = this;\n    return _.any(self.unibuilds, function (unibuild) {\n      return unibuild.arch === 'web.cordova';\n    });\n  },\n\n  canWriteLegacyBuilds() {\n    function isResourceSafeForLegacyBuilds(resource) {\n      // The only new kind of resource is \"source\"; other resources are\n      // unchanged from legacy builds.\n      if (resource.type !== \"source\") {\n        return true;\n      }\n\n      // CSS is safe for legacy builds. (We assume everyone is using the\n      // SourceProcessor from the 'meteor' package.)\n      if (resource.extension === \"css\") {\n        return true;\n      }\n\n      // If this JS resource uses hard-coded support for plain old ES5, then it\n      // is safe to write as part of a legacy Isopack.\n      if (resource.extension === \"js\" && resource.usesDefaultSourceProcessor) {\n        return true;\n      }\n\n      // Nope, this package cannot be represented as an isopack-1 Isopack\n      // because it uses a file implemented by registerCompiler other than the\n      // very basic JS and CSS types.\n      return false;\n    }\n\n    return this.unibuilds.every(\n      unibuild => unibuild.resources.every(isResourceSafeForLegacyBuilds)\n    );\n  },\n\n  // options:\n  //\n  // - includeIsopackBuildInfo: If set, write an isopack-buildinfo.json file.\n  // - includePreCompilerPluginIsopackVersions: By default, saveToPath only\n  //   creates an isopack of format 'isopack-2', with unibuilds of format\n  //   'isopack-2-unibuild'.  These isopacks may contain \"source\" resources,\n  //   which are processed at *bundle* time by compiler plugins.  They cannot be\n  //   properly processed by older tools.  If this flag is set, saveToPath also\n  //   tries to save data for older formats (isopack-1 and unipackage-pre2),\n  //   converting JS and CSS \"source\" resources into \"prelink\" and \"css\"\n  //   resources.  This is not possible if there are \"source\" resources other\n  //   than JS or CSS; however, such packages must indirectly depend on the\n  //   \"isobuild:compiler-plugin\" pseudo-package which is not compatible with\n  //   older releases.  For packages that can't be converted to the older\n  //   format, this function silently only saves the newer format.  (The point\n  //   of this flag is allow us to optimize cases that never need to write the\n  //   older format, such as the per-app isopack cache.)\n  // - isopackCache: isopack cache in which this isopack is registered\n  saveToPath: Profile(\"Isopack#saveToPath\", function (outputDir, {\n    includePreCompilerPluginIsopackVersions,\n    includeIsopackBuildInfo,\n    isopackCache = null,\n  } = {}) {\n    var self = this;\n    var outputPath = outputDir;\n\n    var builder = new Builder({ outputPath: outputPath });\n    try {\n      var mainJson = {\n        name: self.name,\n        summary: self.metadata.summary,\n        version: self.version,\n        isTest: self.isTest,\n        builds: [],\n        plugins: []\n      };\n\n      if (self.debugOnly) {\n        mainJson.debugOnly = true;\n      }\n      if (self.prodOnly) {\n        mainJson.prodOnly = true;\n      }\n      if (self.testOnly) {\n        mainJson.testOnly = true;\n      }\n      if (! _.isEmpty(self.cordovaDependencies)) {\n        mainJson.cordovaDependencies = self.cordovaDependencies;\n      }\n\n      const writeLegacyBuilds = (\n        includePreCompilerPluginIsopackVersions\n          && self.canWriteLegacyBuilds());\n\n      var isopackBuildInfoJson = null;\n      if (includeIsopackBuildInfo) {\n        isopackBuildInfoJson = {\n          builtBy: compiler.BUILT_BY,\n          unibuildDependencies: {},\n          // pluginDependencies defines a WatchSet that any package that could\n          // use this package as a plugin needs to watch. So it always contains\n          // our package.js (because modifications to package.js could add a new\n          // plugin), as well as any files making up plugins in our package.\n          pluginDependencies: self.pluginWatchSet.toJSON(),\n          pluginProviderPackageMap: self.pluginProviderPackageMap.toJSON(),\n          includeCordovaUnibuild: self.hasCordovaUnibuild()\n        };\n      }\n\n      // XXX COMPAT WITH 0.9.3\n      builder.reserve(\"unipackage.json\");\n\n      builder.reserve(\"isopack.json\");\n      // Reserve this even if includeIsopackBuildInfo is not set, to ensure\n      // nothing else writes it somehow.\n      builder.reserve(\"isopack-buildinfo.json\");\n\n      builder.reserve(\"head\");\n      builder.reserve(\"body\");\n\n      // Map from absolute path to npm directory in the unibuild, to the\n      // generated filename in the isopack we're writing.  Multiple builds\n      // can use the same npm modules (though maybe not any more, since tests\n      // have been separated?), but also there can be different sets of\n      // directories as well (eg, for a isopack merged with from multiple\n      // isopacks with _loadUnibuildsFromPath).\n      const npmDirsToCopy = Object.create(null);\n\n      // Pre-linker versions of Meteor expect all packages in the warehouse to\n      // contain a file called \"package.js\"; they use this as part of deciding\n      // whether or not they need to download a new package. Because packages\n      // are downloaded by the *existing* version of the tools, we need to\n      // include this file until we're comfortable breaking \"meteor update\" from\n      // 0.6.4.  (Specifically, warehouse.packageExistsInWarehouse used to check\n      // to see if package.js exists instead of just looking for the package\n      // directory.)\n      // XXX Remove this once we can.\n      builder.write(\"package.js\", {\n        data: new Buffer(\n          (\"// This file is included for compatibility with the Meteor \" +\n           \"0.6.4 package downloader.\\n\"),\n          \"utf8\")\n      });\n\n      var unibuildInfos = [];\n\n      // Unibuilds\n      _.each(self.unibuilds, function (unibuild) {\n        // Make up a filename for this unibuild\n        var baseUnibuildName = unibuild.arch;\n        var unibuildDir =\n          builder.generateFilename(baseUnibuildName, { directory: true });\n        var unibuildJsonFile =\n          builder.generateFilename(baseUnibuildName + \".json\");\n        mainJson.builds.push({\n          kind: unibuild.kind,\n          arch: unibuild.arch,\n          path: unibuildJsonFile\n        });\n\n        var jsResourcesForLegacyPrelink = [];\n\n        // Save unibuild dependencies. Keyed by the json path rather than thinking\n        // too hard about how to encode pair (name, arch).\n        if (isopackBuildInfoJson) {\n          isopackBuildInfoJson.unibuildDependencies[unibuildJsonFile] =\n            unibuild.watchSet.toJSON();\n        }\n\n        // Figure out where the npm dependencies go.\n        let node_modules = {};\n        const nodeModulesPaths = [];\n        _.each(unibuild.nodeModulesDirectories, nmd => {\n          const bundlePath = _.has(npmDirsToCopy, nmd.sourcePath)\n            // We already have this npm directory from another unibuild.\n            ? npmDirsToCopy[nmd.sourcePath]\n            : npmDirsToCopy[nmd.sourcePath] = builder.generateFilename(\n              nmd.getPreferredBundlePath(\"isopack\"),\n              { directory: true }\n            );\n\n          // Eventually we would prefer to write these node_modules\n          // properties with object values instead of string values, like\n          // we're doing here, but older versions of meteor-tool won't be\n          // able to load unibuilds like that, so we have to wait until\n          // everyone is using a version of the tool that knows how to\n          // read object-valued node_modules properties.\n          node_modules[bundlePath] = nmd.toJSON();\n\n          if (nmd.local) {\n            nodeModulesPaths.push(bundlePath);\n          } else {\n            // Give .npm/package/node_modules directories preference in\n            // the selection of a single bundle path below.\n            nodeModulesPaths.unshift(bundlePath);\n          }\n        });\n\n        if (nodeModulesPaths.length > 0) {\n          // For backwards compatibility, we unfortunately can only write\n          // node_modules as a single string.\n          node_modules = nodeModulesPaths[0];\n        } else {\n          node_modules = undefined;\n        }\n\n        // Construct unibuild metadata\n        var unibuildJson = {\n          format: \"isopack-2-unibuild\",\n          declaredExports: unibuild.declaredExports,\n          uses: _.map(unibuild.uses, function (u) {\n            return {\n              'package': u.package,\n              // For cosmetic value, leave false values for these options out of\n              // the JSON file.\n              constraint: u.constraint || undefined,\n              unordered: u.unordered || undefined,\n              weak: u.weak || undefined\n            };\n          }),\n          implies: (_.isEmpty(unibuild.implies) ? undefined : unibuild.implies),\n          node_modules,\n          resources: []\n        };\n\n        const usesModules = ! isopackCache ||\n          isopackCache.uses(self, \"modules\", unibuild.arch);\n\n        // Output 'head', 'body' resources nicely\n        var concat = { head: [], body: [] };\n        var offset = { head: 0, body: 0 };\n        _.each(unibuild.resources, function (resource) {\n          if (_.contains([\"head\", \"body\"], resource.type)) {\n            if (concat[resource.type].length) {\n              concat[resource.type].push(new Buffer(\"\\n\", \"utf8\"));\n              offset[resource.type]++;\n            }\n            if (! (resource.data instanceof Buffer)) {\n              throw new Error(\"Resource data must be a Buffer\");\n            }\n\n            if (! usesModules &&\n                resource.fileOptions &&\n                resource.fileOptions.lazy) {\n              // Omit lazy resources from the unibuild JSON file.\n              return;\n            }\n\n            unibuildJson.resources.push({\n              type: resource.type,\n              file: files.pathJoin(unibuildDir, resource.type),\n              length: resource.data.length,\n              offset: offset[resource.type]\n            });\n\n            concat[resource.type].push(resource.data);\n            offset[resource.type] += resource.data.length;\n          }\n        });\n\n        _.each(concat, function (parts, type) {\n          if (parts.length) {\n            builder.write(files.pathJoin(unibuildDir, type), {\n              data: Buffer.concat(concat[type], offset[type])\n            });\n          }\n        });\n\n        // Output other resources each to their own file\n        _.each(unibuild.resources, function (resource) {\n          if (_.contains([\"head\", \"body\"], resource.type)) {\n            // already did this one\n            return;\n          }\n\n          const generatedFilename =\n            builder.writeToGeneratedFilename(\n              files.pathJoin(unibuildDir,\n                             resource.servePath || resource.path),\n              { data: resource.data });\n\n          if (! usesModules &&\n              resource.fileOptions &&\n              resource.fileOptions.lazy) {\n            // Omit lazy resources from the unibuild JSON file, but only\n            // after they are copied into the bundle (immediately above).\n            return;\n          }\n\n          // If we're going to write a legacy prelink file later, track the\n          // original form of the resource object (with the source in a Buffer,\n          // etc) instead of the later version.  #HardcodeJs\n          if (writeLegacyBuilds &&\n              resource.type === \"source\" &&\n              resource.extension == \"js\") {\n            jsResourcesForLegacyPrelink.push({\n              data: resource.data,\n              hash: resource.hash,\n              servePath: unibuild.pkg._getServePath(resource.path),\n              bare: resource.fileOptions && resource.fileOptions.bare,\n              sourceMap: resource.sourceMap,\n              // If this file was actually read from a legacy isopack and is\n              // itself prelinked, this will be an object with some metadata\n              // about it, and we can skip re-running prelink later.\n              legacyPrelink: resource.legacyPrelink\n            });\n          }\n\n          unibuildJson.resources.push({\n            type: resource.type,\n            extension: resource.extension,\n            file: generatedFilename,\n            length: resource.data.length,\n            offset: 0,\n            usesDefaultSourceProcessor:\n              resource.usesDefaultSourceProcessor || undefined,\n            servePath: resource.servePath || undefined,\n            path: resource.path || undefined,\n            hash: resource.hash || undefined,\n            fileOptions: resource.fileOptions || undefined\n          });\n        });\n\n        // Control file for unibuild\n        builder.writeJson(unibuildJsonFile, unibuildJson);\n        unibuildInfos.push({\n          unibuild: unibuild,\n          unibuildJson: unibuildJson,\n          jsResourcesForLegacyPrelink: jsResourcesForLegacyPrelink\n        });\n      });\n\n      // If unibuilds included node_modules, copy them in.\n      _.each(npmDirsToCopy, (bundlePath, sourcePath) => {\n        builder.copyDirectory({\n          from: sourcePath,\n          to: bundlePath,\n          npmDiscards: self.npmDiscards,\n          symlink: false\n        });\n      });\n\n      // Plugins\n      _.each(self.plugins, function (pluginsByArch, name) {\n        _.each(pluginsByArch, function (plugin) {\n          // XXX the name of the plugin doesn't typically contain a colon, but\n          // escape it just in case.\n          var pluginDir = builder.generateFilename(\n            'plugin.' + colonConverter.convert(name) + '.' + plugin.arch,\n            { directory: true });\n          var pluginBuild = plugin.write(builder.enter(pluginDir));\n          var pluginEntry = {\n            name: name,\n            arch: plugin.arch,\n            path: files.pathJoin(pluginDir, pluginBuild.controlFile)\n          };\n          mainJson.plugins.push(pluginEntry);\n        });\n      });\n\n      // Tools\n      // First, are we supposed to include our own source as a tool?\n      if (self.includeTool) {\n        var toolsJson = self._writeTool(builder);\n        mainJson.tools = toolsJson;\n      }\n      // Next, what about other tools we may be merging from other isopacks?\n      // XXX check for overlap\n      _.each(self.toolsOnDisk, function (toolMeta) {\n        toolMeta = _.clone(toolMeta);\n        var rootDir = toolMeta.rootDir;\n        delete toolMeta.rootDir;\n        builder.copyDirectory({\n          from: files.pathJoin(rootDir, toolMeta.path),\n          to: toolMeta.path,\n          symlink: false\n        });\n        if (!mainJson.tools) {\n          mainJson.tools = [];\n        }\n        mainJson.tools.push(toolMeta);\n      });\n\n      var mainLegacyJson = null;\n      if (writeLegacyBuilds) {\n        mainLegacyJson = _.clone(mainJson);\n        mainLegacyJson.builds = [];\n\n        _.each(unibuildInfos, function (unibuildInfo) {\n          var unibuild = unibuildInfo.unibuild;\n          var unibuildJson = unibuildInfo.unibuildJson;\n          var jsResourcesForLegacyPrelink =\n                unibuildInfo.jsResourcesForLegacyPrelink;\n          var legacyFilename = builder.generateFilename(\n            unibuild.arch + '-legacy.json');\n          var legacyDir = unibuild.arch + '-legacy';\n          mainLegacyJson.builds.push({\n            kind: unibuild.kind,\n            arch: unibuild.arch,\n            path: legacyFilename\n          });\n\n          unibuildJson.format = 'unipackage-unibuild-pre1';\n          var newResources = [];\n          _.each(unibuildJson.resources, function (resource) {\n            if (resource.type !== 'source') {\n              newResources.push(resource);\n            } else if (resource.extension === 'css') {\n              // Convert this resource from a new-style \"source\" to an\n              // old-style \"css\".\n              newResources.push({\n                type: 'css',\n                file: resource.file,\n                length: resource.length,\n                offset: resource.offset,\n                servePath: self._getServePath(resource.path)\n              });\n            } else if (resource.extension === 'js') {\n              // Skip; we saved this in jsResourcesForLegacyPrelink above\n              // already, in the format that linker.prelink understands.\n            } else {\n              throw Error(\n                \"shouldn't write legacy builds for non-JS/CSS source \"\n                  + JSON.stringify(resource));\n            }\n          });\n\n          var prelinkFile, prelinkData, packageVariables;\n          if (jsResourcesForLegacyPrelink.length === 1 &&\n              jsResourcesForLegacyPrelink[0].legacyPrelink) {\n            // Aha!  This isopack was actually a legacy isopack in the first\n            // place! So this source file is already the output of prelink,\n            // and we don't need to reprocess it.\n            prelinkFile = jsResourcesForLegacyPrelink[0];\n            // XXX It's weird that the type of object going in and out of\n            // linker.prelink is different (so that this prelinkData\n            // assignment differs from that below), ah well.\n            prelinkData = prelinkFile.data;\n            packageVariables =\n              jsResourcesForLegacyPrelink[0].legacyPrelink.packageVariables;\n          } else {\n            // Determine captured variables, legacy way. First, start with the\n            // exports. We'll add the package variables after running prelink.\n            packageVariables = [];\n            var packageVariableNames = {};\n            _.each(unibuild.declaredExports, function (symbol) {\n              if (_.has(packageVariableNames, symbol.name)) {\n                return;\n              }\n              packageVariables.push({\n                name: symbol.name,\n                export: symbol.testOnly? \"tests\" : true\n              });\n              packageVariableNames[symbol.name] = true;\n            });\n\n            if (jsResourcesForLegacyPrelink.length) {\n              // Not originally legacy; let's run prelink to make it legacy.\n              var results = linker.prelink({\n                inputFiles: jsResourcesForLegacyPrelink,\n                // I was confused about this, so I am leaving a comment -- the\n                // combinedServePath is either [pkgname].js or [pluginName]:plugin.js.\n                // XXX: If we change this, we can get rid of source arch names!\n                combinedServePath: (\n                  \"/packages/\" + colonConverter.convert(\n                    unibuild.pkg.name +\n                      (unibuild.kind === \"main\" ? \"\" : (\":\" + unibuild.kind)) +\n                      \".js\")),\n                name: unibuild.pkg.name\n              });\n              if (results.files.length !== 1) {\n                throw Error(\"prelink should return 1 file, not \" +\n                            results.files.length);\n              }\n              prelinkFile = results.files[0];\n              prelinkData = new Buffer(prelinkFile.source, 'utf8');\n\n              _.each(results.assignedVariables, function (name) {\n                if (_.has(packageVariableNames, name)) {\n                  return;\n                }\n                packageVariables.push({\n                  name: name\n                });\n                packageVariableNames[name] = true;\n              });\n            }\n          }\n\n          if (prelinkFile && prelinkData) {\n            var prelinkResource = {\n              type: 'prelink',\n              file: builder.writeToGeneratedFilename(\n                files.pathJoin(legacyDir, prelinkFile.servePath),\n                { data: prelinkData }),\n              length: prelinkData.length,\n              offset: 0,\n              servePath: prelinkFile.servePath || undefined\n            };\n            if (prelinkFile.sourceMap) {\n              // Write the source map.\n\n              if (typeof prelinkFile.sourceMap !== \"string\") {\n                prelinkFile.sourceMap = JSON.stringify(prelinkFile.sourceMap);\n              }\n\n              prelinkResource.sourceMap = builder.writeToGeneratedFilename(\n                files.pathJoin(legacyDir, prelinkFile.servePath + '.map'),\n                { data: new Buffer(prelinkFile.sourceMap, 'utf8') }\n              );\n            }\n            newResources.push(prelinkResource);\n          }\n\n          if (packageVariables.length) {\n            unibuildJson.packageVariables = packageVariables;\n          }\n\n          unibuildJson.resources = newResources;\n          delete unibuildJson.declaredExports;\n          builder.writeJson(legacyFilename, unibuildJson);\n        });\n\n        // old unipackage.json format/filename.  no point to save this if\n        // we can't even support isopack-1.\n        // XXX COMPAT WITH 0.9.3\n        builder.writeJson(\n          \"unipackage.json\",\n          Isopack.convertIsopackFormat(\n            // Note that mainLegacyJson is isopack-1 (has no \"source\" resources)\n            // rather than isopack-2.\n            mainLegacyJson, \"isopack-1\", \"unipackage-pre2\"));\n      }\n\n      var isopackJson = {};\n      isopackJson['isopack-2'] = mainJson;\n      if (writeLegacyBuilds) {\n        isopackJson['isopack-1'] = mainLegacyJson;\n      }\n\n      // writes one file with all of the new formats, so that it is possible\n      // to invent a new format and have old versions of meteor still read the\n      // old format\n      //\n      // This looks something like:\n      // {\n      //   isopack-1: {... data ...},\n      //   isopack-2: {... data ...}\n      // }\n      builder.writeJson(\"isopack.json\", isopackJson);\n\n      if (isopackBuildInfoJson) {\n        builder.writeJson(\"isopack-buildinfo.json\", isopackBuildInfoJson);\n      }\n      builder.complete();\n    } catch (e) {\n      builder.abort();\n      throw e;\n    }\n  }),\n\n  _writeTool: Profile(\"Isopack#_writeTool\", function (builder) {\n    var self = this;\n\n    var pathsToCopy = utils.runGitInCheckout(\n      'ls-tree',\n      '-r',\n      '--name-only',\n      '--full-tree',\n      'HEAD',\n      // The actual trees to copy!\n      'tools', 'examples', 'LICENSE.txt', 'LICENSES',\n      'meteor', 'meteor.bat', 'scripts/admin/launch-meteor',\n      'packages/package-version-parser/package-version-parser.js',\n      'packages/meteor/flush-buffers-on-exit-in-windows.js');\n\n    // Trim blank line and unnecessary examples.\n    pathsToCopy = _.filter(pathsToCopy.split('\\n'), function (f) {\n      return f && !f.match(/^examples\\/other/) &&\n        !f.match(/^examples\\/unfinished/);\n    });\n\n    // Regexes matching paths to transpile using babel\n    var transpileRegexes = [\n      /^tools\\/[^\\/]+\\.js$/, // General tools files\n      /^tools\\/isobuild\\/[^\\/]+\\.js$/, // Isobuild files\n      /^tools\\/cli\\/[^\\/]+\\.js$/, // CLI files\n      /^tools\\/tool-env\\/[^\\/]+\\.js$/, // Tool initiation and clean up\n      /^tools\\/runners\\/[^\\/]+\\.js$/, // Parts of tool process\n      /^tools\\/packaging\\/[^\\/]+\\.js$/,\n      /^tools\\/packaging\\/catalog\\/[^\\/]+\\.js$/,\n      /^tools\\/utils\\/[^\\/]+\\.js$/,\n      /^tools\\/fs\\/[^\\/]+\\.js$/,\n      /^tools\\/meteor-services\\/[^\\/]+\\.js$/,\n      /^tools\\/tool-testing\\/[^\\/]+\\.js$/,\n      /^tools\\/console\\/[^\\/]+\\.js$/,\n      /^tools\\/cordova\\/[^\\/]+\\.js$/,\n      // We don't support running self-test from an install anymore\n    ];\n\n    // Split pathsToCopy into two arrays - one of files that should be copied\n    // directly, and one of files that should be transpiled with Babel\n    var pathsToTranspile = [];\n    var pathsToCopyStraight = [];\n    pathsToCopy.forEach((path) => {\n      var shouldTranspile =\n        _.some(transpileRegexes, (regex) => path.match(regex));\n\n      if (shouldTranspile) {\n        pathsToTranspile.push(path);\n      } else {\n        pathsToCopyStraight.push(path);\n      }\n    });\n\n    // Set up builder to write to the correct directory\n    var toolPath = 'mt-' + archinfo.host();\n    builder = builder.enter(toolPath);\n\n    // Transpile the files we selected\n    var babel = require(\"meteor-babel\");\n    pathsToTranspile.forEach((path) => {\n      var fullPath = files.convertToOSPath(\n        files.pathJoin(files.getCurrentToolsDir(), path));\n\n      var inputFileContents = files.readFile(fullPath, \"utf-8\");\n\n      // #RemoveInProd\n      // We don't actually want to load the babel auto-transpiler when we are\n      // in a Meteor installation where everything is already transpiled for us.\n      // Therefore, strip out that line in main.js\n      if (path === \"tools/tool-env/install-babel.js\" ||\n          path === \"tools/tool-env/source-map-retriever-stack.js\") {\n        inputFileContents = inputFileContents.replace(/^.*#RemoveInProd.*$/mg, \"\");\n      }\n\n      var babelOptions = babel.getDefaultOptions();\n\n      _.extend(babelOptions, {\n        filename: path,\n        sourceFileName: \"/\" + path,\n        sourceMapTarget: path + \".map\",\n        sourceMap: true\n      });\n\n      var transpiled = babel.compile(inputFileContents, babelOptions);\n\n      var sourceMapUrlComment = \"//# sourceMappingURL=\" + files.pathBasename(path + \".map\");\n\n      builder.write(path, {\n        data: new Buffer(transpiled.code + \"\\n\" + sourceMapUrlComment, 'utf8')\n      });\n\n      builder.write(path + \".map\", {\n        data: new Buffer(JSON.stringify(transpiled.map), 'utf8')\n      });\n    });\n\n    var gitSha = utils.runGitInCheckout('rev-parse', 'HEAD');\n    builder.reserve('isopackets', {directory: true});\n    builder.write('.git_version.txt', {data: new Buffer(gitSha, 'utf8')});\n\n    builder.copyDirectory({\n      from: files.getCurrentToolsDir(),\n      to: '',\n      specificFiles: pathsToCopyStraight,\n      symlink: false\n    });\n\n    // Include the dev bundle, but drop a few things that are only used by\n    // self-test (which isn't supported from release).\n    var devBundleIgnore = _.clone(bundler.ignoreFiles);\n    devBundleIgnore.push(/BrowserStackLocal/, /browserstack-webdriver/);\n    builder.copyDirectory({\n      from: files.pathJoin(files.getDevBundle()),\n      to: 'dev_bundle',\n      ignore: devBundleIgnore,\n      symlink: false\n    });\n\n    // Build all of the isopackets now, so that no build step is required when\n    // you're actually running meteor from a release in order to load packages.\n    var isopacketBuildContext = isopackets.makeIsopacketBuildContext();\n\n    var messages = buildmessage.capture(function () {\n      // We rebuild them in the order listed in ISOPACKETS. This is not strictly\n      // necessary here, since any isopackets loaded as part of the build\n      // process are going to be the current tool's isopackets, not the\n      // isopackets that we're writing out.\n      _.each(isopackets.ISOPACKETS, function (packages, isopacketName) {\n        buildmessage.enterJob({\n          title: \"compiling \" + isopacketName + \" packages for the tool\"\n        }, function () {\n          isopacketBuildContext.isopackCache.buildLocalPackages(packages);\n          if (buildmessage.jobHasMessages()) {\n            return;\n          }\n\n          var image = bundler.buildJsImage({\n            name: \"isopacket-\" + isopacketName,\n            packageMap: isopacketBuildContext.packageMap,\n            isopackCache: isopacketBuildContext.isopackCache,\n            use: packages\n          }).image;\n          if (buildmessage.jobHasMessages()) {\n            return;\n          }\n\n          image.write(\n            builder.enter(files.pathJoin('isopackets', isopacketName)));\n        });\n      });\n    });\n    // This is a build step ... but it's one that only happens in development,\n    // and similar to a isopacket load failure, it can just crash the app\n    // instead of being handled nicely.\n    if (messages.hasMessages()) {\n      Console.error(\"Errors prevented tool build:\");\n      Console.error(messages.formatMessages());\n      throw new Error(\"tool build failed?\");\n    }\n\n    return [{\n      name: 'meteor',\n      arch: archinfo.host(),\n      path: toolPath\n    }];\n  }),\n\n  getMergedWatchSet: Profile(\"Isopack#getMergedWatchSet\", function () {\n    var self = this;\n    var watchSet = self.pluginWatchSet.clone();\n    _.each(self.unibuilds, function (unibuild) {\n      watchSet.merge(unibuild.watchSet);\n    });\n    return watchSet;\n  }),\n\n  getClientWatchSet: Profile(\"Isopack#getClientWatchSet\", function () {\n    var watchSet = this.pluginWatchSet.clone();\n    _.each(this.unibuilds, function (unibuild) {\n      if (/^web\\./.test(unibuild.arch)) {\n        watchSet.merge(unibuild.watchSet);\n      }\n    });\n    return watchSet;\n  }),\n\n  getServerWatchSet: Profile(\"Isopack#getServerWatchSet\", function () {\n    var watchSet = this.pluginWatchSet.clone();\n    _.each(this.unibuilds, function (unibuild) {\n      if (! /^web\\./.test(unibuild.arch)) {\n        watchSet.merge(unibuild.watchSet);\n      }\n    });\n    return watchSet;\n  }),\n\n  // Similar to PackageSource.getPackagesToLoadFirst, but doesn't include\n  // packages used by plugins, because plugin dependencies are already\n  // statically included in this built Isopack. Used by\n  // IsopackCache._ensurePackageLoaded.\n  //\n  // Like getPackagesToLoadFirst, it filters out isobuild:* pseudo-packages and\n  // should not be used to create input to Version Solver.\n  getStrongOrderedUsedAndImpliedPackages: Profile(\n    \"Isopack#getStrongOrderedUsedAndImpliedPackages\", function () {\n    var self = this;\n    var packages = {};\n    var processUse = function (use) {\n      if (use.weak || use.unordered) {\n        return;\n      }\n      // Only include real packages, not isobuild:* pseudo-packages.\n      if (compiler.isIsobuildFeaturePackage(use.package)) {\n        return;\n      }\n      packages[use.package] = true;\n    };\n\n    _.each(self.unibuilds, function (unibuild) {\n      _.each(unibuild.uses, processUse);\n      _.each(unibuild.implies, processUse);\n    });\n    return _.keys(packages);\n  }),\n\n  featureEnabled(featurePackageName) {\n    return this.isobuildFeatures.indexOf(featurePackageName) !== -1;\n  },\n\n  _getServePath: function (pathInPackage) {\n    var self = this;\n    var serveRoot;\n    if (self.name) {\n      serveRoot = files.pathJoin('/packages/', self.name);\n    } else {\n      serveRoot = '/';\n    }\n\n    return colonConverter.convert(\n      files.pathJoin(\n        serveRoot,\n        // XXX or should everything in this API use slash already?\n        files.convertToStandardPath(pathInPackage, true)));\n  },\n\n  displayName() {\n    return this.name === null ? 'the app' : this.name;\n  }\n});\n\nexports.Isopack = Isopack;\n\nexports.OldIsopackFormatError = function () {\n  // This should always be caught anywhere where it can appear (ie, anywhere\n  // that isn't definitely loading something from the tropohouse).\n  this.toString = function () { return \"old isopack format!\" };\n};\n"
  },
  {
    "path": "tools/isobuild/js-analyze.js",
    "content": "import { parse } from 'meteor-babel';\nimport { analyze as analyzeScope } from 'escope';\nimport LRU from \"lru-cache\";\n\nconst hasOwn = Object.prototype.hasOwnProperty;\n\nvar AST_CACHE = new LRU({\n  max: Math.pow(2, 12),\n  length(ast) {\n    return ast.loc.end.line;\n  }\n});\n\n// Like babel.parse, but annotates any thrown error with $ParseError = true.\nfunction tryToParse(source, hash) {\n  if (hash && AST_CACHE.has(hash)) {\n    return AST_CACHE.get(hash);\n  }\n\n  let ast;\n\n  try {\n    ast = parse(source);\n  } catch (e) {\n    if (typeof e.loc === 'object') {\n      e.$ParseError = true;\n    }\n    throw e;\n  }\n\n  if (hash) {\n    AST_CACHE.set(hash, ast);\n  }\n\n  return ast;\n}\n\nvar dependencyKeywordPattern = /\\b(require|import|export)\\b/g;\n\n/**\n * The `findImportedModuleIdentifiers` function takes a string of module\n * source code and returns a map from imported module identifiers to AST\n * nodes. The keys of this map are used in ./import-scanner.js to traverse\n * the module dependency graph. The AST nodes are generally ignored.\n *\n * The implementation uses a regular expression to scan quickly for\n * possible locations of certain tokens (`require`, `import`, `export`),\n * then uses that location information to steer the AST traversal, so that\n * it visits only subtrees that contain interesting tokens, saving a lot\n * of time by ignoring the rest of the AST. The AST traversal determines\n * if the tokens were actually what we thought they were (a `require`\n * function call, or an `import` or `export` statement).\n */\nexport function findImportedModuleIdentifiers(source, hash) {\n  const identifiers = {};\n  const possibleIndexes = [];\n  let match;\n\n  dependencyKeywordPattern.lastIndex = 0;\n  while ((match = dependencyKeywordPattern.exec(source))) {\n    possibleIndexes.push(match.index);\n  }\n\n  if (!possibleIndexes.length) {\n    return {};\n  }\n\n  const ast = tryToParse(source, hash);\n\n  function walk(node, left, right, requireIsBound) {\n    if (left >= right) {\n      // The window of possible indexes is empty, so we can ignore\n      // the entire subtree rooted at this node.\n    } else if (Array.isArray(node)) {\n      for (var i = 0, len = node.length; i < len; ++i) {\n        walk(node[i], left, right, requireIsBound);\n      }\n    } else if (isNode(node)) {\n      const start = node.start;\n      const end = node.end;\n\n      // Narrow the left-right window to exclude possible indexes\n      // that fall outside of the current node.\n      while (left < right && possibleIndexes[left] < start) ++left;\n      while (left < right && end < possibleIndexes[right - 1]) --right;\n\n      if (left < right) {\n        if (! requireIsBound &&\n            isFunctionWithParameter(node, \"require\")) {\n          requireIsBound = true;\n        }\n\n        let id = getRequiredModuleId(node);\n        if (typeof id === \"string\") {\n          return addIdentifier(id, \"require\", requireIsBound);\n        }\n\n        id = getImportedModuleId(node);\n        if (typeof id === \"string\") {\n          return addIdentifier(id, \"import\", requireIsBound);\n        }\n\n        // Continue traversing the children of this node.\n        for (const key of Object.keys(node)) {\n          switch (key) {\n          case \"type\":\n          case \"loc\":\n          case \"start\":\n          case \"end\":\n            // Ignore common keys that are never nodes.\n            continue;\n          }\n\n          walk(node[key], left, right, requireIsBound);\n        }\n      }\n    }\n  }\n\n  function addIdentifier(id, type, requireIsBound) {\n    const entry = hasOwn.call(identifiers, id)\n      ? identifiers[id]\n      : identifiers[id] = { possiblySpurious: true };\n\n    if (type === \"require\") {\n      // If the identifier comes from a require call, but require is not a\n      // free variable, then this dependency might be spurious.\n      entry.possiblySpurious =\n        entry.possiblySpurious && requireIsBound;\n    } else {\n      // The import keyword can't be shadowed, so any dependencies\n      // registered by import statements should be trusted absolutely.\n      entry.possiblySpurious = false;\n    }\n  }\n\n  walk(ast, 0, possibleIndexes.length, false);\n\n  return identifiers;\n}\n\nfunction isNode(value) {\n  return value\n    && typeof value === \"object\"\n    && typeof value.type === \"string\"\n    && typeof value.start === \"number\"\n    && typeof value.end === \"number\";\n}\n\nfunction isIdWithName(node, name) {\n  return node &&\n    node.type === \"Identifier\" &&\n    node.name === name;\n}\n\nfunction isFunctionWithParameter(node, name) {\n  if (node.type === \"FunctionExpression\" ||\n      node.type === \"FunctionDeclaration\" ||\n      node.type === \"ArrowFunctionExpression\") {\n    return node.params.some(param => isIdWithName(param, name));\n  }\n}\n\nfunction getRequiredModuleId(node) {\n  if (node.type === \"CallExpression\" &&\n      isIdWithName(node.callee, \"require\")) {\n    const args = node.arguments;\n    const argc = args.length;\n    if (argc > 0) {\n      const arg = args[0];\n      if (isStringLiteral(arg)) {\n        return arg.value;\n      }\n    }\n  }\n}\n\nfunction isStringLiteral(node) {\n  return node && (\n    node.type === \"StringLiteral\" ||\n    (node.type === \"Literal\" &&\n     typeof node.value === \"string\"));\n}\n\nfunction getImportedModuleId(node) {\n  if (node.type === \"CallExpression\" &&\n      node.callee.type === \"MemberExpression\" &&\n      isIdWithName(node.callee.object, \"module\") &&\n      isIdWithName(node.callee.property, \"import\")) {\n    const args = node.arguments;\n    const argc = args.length;\n    if (argc > 0) {\n      const arg = args[0];\n      if (isStringLiteral(arg)) {\n        return arg.value;\n      }\n    }\n  }\n\n  if (node.type === \"ImportDeclaration\" ||\n      node.type === \"ExportAllDeclaration\" ||\n      node.type === \"ExportNamedDeclaration\") {\n    // The .source of an ImportDeclaration or Export{Named,All}Declaration\n    // is always a string-valued Literal node, if not null.\n    if (isNode(node.source)) {\n      return node.source.value;\n    }\n  }\n}\n\n// Analyze the JavaScript source code `source` and return a dictionary of all\n// globals which are assigned to in the package. The values in the dictionary\n// are all `true`.\n//\n// This is intended for use in detecting package-scope variables in Meteor\n// packages, where the linker needs to add a \"var\" statement to prevent them\n// from staying as globals.\n//\n// It only cares about assignments to variables; an assignment to a field on an\n// object (`Foo.Bar = true`) neither causes `Foo` nor `Foo.Bar` to be returned.\nexport function findAssignedGlobals(source, hash) {\n  const ast = tryToParse(source, hash);\n\n  // We have to pass ignoreEval; otherwise, the existence of a direct eval call\n  // causes escope to not bother to resolve references in the eval's scope.\n  // This is because an eval can pull references inward:\n  //\n  //   function outer() {\n  //     var i = 42;\n  //     function inner() {\n  //       eval('var i = 0');\n  //       i;  // 0, not 42\n  //     }\n  //   }\n  //\n  // But it can't pull references outward, so for our purposes it is safe to\n  // ignore.\n  const scopeManager = analyzeScope(ast, {\n    ecmaVersion: 6,\n    sourceType: \"module\",\n    ignoreEval: true,\n    // Ensures we don't treat top-level var declarations as globals.\n    nodejsScope: true,\n  });\n\n  const program = ast.type === \"File\" ? ast.program : ast;\n  const programScope = scopeManager.acquire(program);\n  const assignedGlobals = {};\n\n  // Passing {sourceType: \"module\"} to analyzeScope leaves this list\n  // strangely empty, but {sourceType: \"script\"} forbids ImportDeclaration\n  // nodes (because they are only legal in modules.\n  programScope.implicit.variables.forEach(variable => {\n    assignedGlobals[variable.name] = true;\n  });\n\n  // Fortunately, even with {sourceType: \"module\"}, the .implicit.left\n  // array still has all the information we need, as long as we ignore\n  // global variable references that are not assignments.\n  programScope.implicit.left.forEach(entry => {\n    if (entry.identifier &&\n        entry.identifier.type === \"Identifier\" &&\n        // Only consider identifers that are assigned a value.\n        entry.writeExpr) {\n      assignedGlobals[entry.identifier.name] = true;\n    }\n  });\n\n  return assignedGlobals;\n}\n"
  },
  {
    "path": "tools/isobuild/linker.js",
    "content": "var _ = require('underscore');\nvar sourcemap = require('source-map');\nvar buildmessage = require('../utils/buildmessage.js');\nvar watch = require('../fs/watch.js');\nvar Profile = require('../tool-env/profile.js').Profile;\nimport assert from 'assert';\nimport LRU from 'lru-cache';\nimport {sourceMapLength} from '../utils/utils.js';\nimport files from '../fs/files.js';\nimport {findAssignedGlobals} from './js-analyze.js';\n\n// A rather small cache size, assuming only one module is being linked\n// most of the time.\nconst CACHE_SIZE = process.env.METEOR_APP_PRELINK_CACHE_SIZE || 1024*1024*20;\n\n// Cache individual files prelinked\nconst APP_PRELINK_CACHE = new LRU({\n  max: CACHE_SIZE,\n  length: function (prelinked) {\n    return prelinked.source.length + sourceMapLength(prelinked.sourceMap);\n  }\n});\n\nvar packageDot = function (name) {\n  if (/^[a-zA-Z][a-zA-Z0-9]*$/.exec(name)) {\n    return \"Package.\" + name;\n  } else {\n    return \"Package['\" + name + \"']\";\n  }\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Module\n///////////////////////////////////////////////////////////////////////////////\n\n// options include name, imports, exports, useGlobalNamespace,\n// combinedServePath, all of which have the same meaning as they do when passed\n// to import().\nvar Module = function (options) {\n  var self = this;\n\n  // module name or null\n  self.name = options.name || null;\n\n  // files in the module. array of File\n  self.files = [];\n\n  // options\n  self.meteorInstallOptions = options.meteorInstallOptions;\n  self.useGlobalNamespace = options.useGlobalNamespace;\n  self.combinedServePath = options.combinedServePath;\n  self.noLineNumbers = options.noLineNumbers;\n};\n\n_.extend(Module.prototype, {\n  // source: the source code\n  // servePath: the path where it would prefer to be served if possible\n  addFile: function (inputFile) {\n    var self = this;\n    self.files.push(new File(inputFile, self));\n  },\n\n\n  maxLineLength: function (ignoreOver) {\n    var self = this;\n\n    var maxInFile = [];\n    _.each(self.files, function (file) {\n      var m = 0;\n      _.each(file.source.split('\\n'), function (line) {\n        if (line.length <= ignoreOver && line.length > m) {\n          m = line.length;\n        }\n      });\n      maxInFile.push(m);\n    });\n\n    return _.max(maxInFile);\n  },\n\n  // Figure out which vars need to be specifically put in the module\n  // scope.\n  computeAssignedVariables: Profile(\"linker Module#computeAssignedVariables\", function () {\n    var self = this;\n\n    // The assigned variables in the app aren't actually used for anything:\n    // we're using the global namespace, so there's no header where we declare\n    // all of the assigned variables as vars.  So there's no use wasting time\n    // running static analysis on app code.\n    if (self.useGlobalNamespace) {\n      return [];\n    }\n\n    // Find all global references in any files\n    var assignedVariables = [];\n    _.each(self.files, function (file) {\n      assignedVariables = assignedVariables.concat(\n        file.computeAssignedVariables());\n    });\n    assignedVariables = _.uniq(assignedVariables);\n\n    return assignedVariables;\n  }),\n\n  // Output is a list of objects with keys 'source', 'servePath', 'sourceMap',\n  // 'sourcePath'\n  getPrelinkedFiles: Profile(\"linker Module#getPrelinkedFiles\", function () {\n    var self = this;\n\n    // If we don't want to create a separate scope for this module,\n    // then our job is much simpler. And we can get away with\n    // preserving the line numbers.\n    if (self.useGlobalNamespace &&\n        ! self.meteorInstallOptions) {\n      // Ignore lazy files unless we have a module system.\n      const eagerFiles = _.filter(self.files, file => ! file.lazy);\n\n      return _.map(eagerFiles, function (file) {\n        const cacheKey = JSON.stringify([\n          file.sourceHash, file.bare, file.servePath]);\n\n        if (APP_PRELINK_CACHE.has(cacheKey)) {\n          return APP_PRELINK_CACHE.get(cacheKey);\n        }\n\n        const node = file.getPrelinkedOutput({ preserveLineNumbers: true });\n        const results = Profile.time(\n          \"toStringWithSourceMap (app)\", () => {\n            return node.toStringWithSourceMap({\n              file: file.servePath\n            }); // results has 'code' and 'map' attributes\n          }\n        );\n\n        let sourceMap = results.map.toJSON();\n        if (! sourceMap.mappings) {\n          sourceMap = null;\n        }\n\n        const prelinked = {\n          source: results.code,\n          sourcePath: file.sourcePath,\n          servePath: file.servePath,\n          sourceMap: sourceMap\n        };\n\n        APP_PRELINK_CACHE.set(cacheKey, prelinked);\n        return prelinked;\n      });\n    }\n\n    // Otherwise..\n\n    // Find the maximum line length.\n    var sourceWidth = _.max([68, self.maxLineLength(120 - 2)]);\n\n    const result = {\n      // This object will be populated with .source, .servePath,\n      // .sourceMap, and (optionally) .exportsName properties before being\n      // returned from this method in a singleton array.\n      servePath: self.combinedServePath,\n    };\n\n    // An array of strings and SourceNode objects.\n    let chunks = [];\n    let fileCount = 0;\n\n    // Emit each file\n    if (self.meteorInstallOptions) {\n      const tree = self._buildModuleTree();\n      fileCount = self._chunkifyModuleTree(tree, chunks, sourceWidth);\n      result.exportsName =\n        self._chunkifyEagerRequires(chunks, fileCount, sourceWidth);\n\n    } else {\n      _.each(self.files, function (file) {\n        if (file.lazy) {\n          // Ignore lazy files unless we have a module system.\n          return;\n        }\n\n        if (!_.isEmpty(chunks)) {\n          chunks.push(\"\\n\\n\\n\\n\\n\\n\");\n        }\n\n        chunks.push(file.getPrelinkedOutput({\n          sourceWidth: sourceWidth,\n          noLineNumbers: self.noLineNumbers\n        }));\n\n        ++fileCount;\n      });\n    }\n\n    var node = new sourcemap.SourceNode(null, null, null, chunks);\n\n    Profile.time(\n      'getPrelinkedFiles toStringWithSourceMap',\n      function () {\n        if (fileCount > 0) {\n          var swsm = node.toStringWithSourceMap({\n            file: self.combinedServePath\n          });\n          result.source = swsm.code;\n          result.sourceMap = swsm.map.toJSON();\n          if (! result.sourceMap.mappings) {\n            result.sourceMap = null;\n          }\n        } else {\n          // If there were no files in this bundle, we do not need to\n          // generate a source map.\n          result.source = node.toString();\n          result.sourceMap = null;\n        }\n      }\n    );\n\n    return [result];\n  }),\n\n  // Builds a tree of nested objects where the properties are names of\n  // files or directories, and the values are either nested objects\n  // (representing directories) or File objects (representing modules).\n  // Bare files and lazy files that are never imported are ignored.\n  _buildModuleTree() {\n    assert.ok(this.meteorInstallOptions);\n\n    const tree = {};\n\n    _.each(this.files, function (file) {\n      if (file.bare) {\n        // Bare files will be added in between the synchronous require\n        // calls in _chunkifyEagerRequires.\n        return;\n      }\n\n      if (file.lazy && ! file.imported) {\n        // If the file is not eagerly evaluated, and no other files\n        // import or require it, then it need not be included in the\n        // bundle.\n        return;\n      }\n\n      const parts = file.installPath.split(\"/\");\n      let t = tree;\n      _.each(parts, function (part, i) {\n        const isLastPart = i === parts.length - 1;\n        t = _.has(t, part)\n          ? t[part]\n          : t[part] = isLastPart ? file : {};\n      });\n    });\n\n    return tree;\n  },\n\n  // Takes the tree generated by _buildModuleTree and populates the chunks\n  // array with strings and SourceNode objects that can be combined into a\n  // single SourceNode object. Returns the count of modules in the tree.\n  _chunkifyModuleTree(tree, chunks, sourceWidth) {\n    const self = this;\n\n    assert.ok(self.meteorInstallOptions);\n    assert.ok(_.isArray(chunks));\n    assert.ok(_.isNumber(sourceWidth));\n\n    let moduleCount = 0;\n\n    function walk(t) {\n      if (t instanceof File) {\n        ++moduleCount;\n        chunks.push(t.getPrelinkedOutput({\n          sourceWidth,\n          noLineNumbers: self.noLineNumbers\n        }));\n      } else if (_.isObject(t)) {\n        chunks.push(\"{\");\n        const keys = _.keys(t);\n        _.each(keys, (key, i) => {\n          chunks.push(JSON.stringify(key), \":\");\n          walk(t[key]);\n          if (i < keys.length - 1) {\n            chunks.push(\",\");\n          }\n        });\n        chunks.push(\"}\");\n      }\n    }\n\n    const chunksLengthBeforeWalk = chunks.length;\n\n    // The tree of nested directories and module functions built above\n    // allows us to call meteorInstall just once to install everything.\n    chunks.push(\"var require = meteorInstall(\");\n    walk(tree);\n    chunks.push(\",\", JSON.stringify(self.meteorInstallOptions), \");\");\n\n    if (moduleCount === 0) {\n      // If no files were actually added to the chunks array, roll back\n      // to before the `var require = meteorInstall(` chunk.\n      chunks.length = chunksLengthBeforeWalk;\n    }\n\n    return moduleCount;\n  },\n\n  // Adds require calls to the chunks array for all modules that should be\n  // eagerly evaluated, and also includes bare files in the appropriate\n  // order with respect to the require calls. Returns the name of the\n  // variable that holds the main exports object, if api.mainModule was\n  // used to define a main module.\n  _chunkifyEagerRequires(chunks, moduleCount, sourceWidth) {\n    assert.ok(_.isArray(chunks));\n    assert.ok(_.isNumber(moduleCount));\n    assert.ok(_.isNumber(sourceWidth));\n\n    let exportsName;\n\n    // Now that we have installed everything in this package or\n    // application, immediately require the non-lazy modules and\n    // evaluate the bare files.\n    _.each(this.files, file => {\n      if (file.bare) {\n        chunks.push(\"\\n\", file.getPrelinkedOutput({\n          sourceWidth,\n          noLineNumbers: this.noLineNumbers\n        }));\n      } else if (moduleCount > 0 && ! file.lazy) {\n        if (file.mainModule) {\n          exportsName = \"exports\";\n        }\n\n        chunks.push(\n          file.mainModule ? \"\\nvar \" + exportsName + \" = \" : \"\\n\",\n          \"require(\",\n          JSON.stringify(\"./\" + file.installPath),\n          \");\"\n        );\n      }\n    });\n\n    return exportsName;\n  }\n});\n\n// Given 'symbolMap' like {Foo: 's1', 'Bar.Baz': 's2', 'Bar.Quux.A': 's3', 'Bar.Quux.B': 's4'}\n// return something like\n// {Foo: 's1', Bar: {Baz: 's2', Quux: {A: 's3', B: 's4'}}}\n//\n// If the value of a symbol in symbolMap is set null, then we just\n// ensure that its parents exist. For example, {'A.B.C': null} means\n// to make sure that symbol tree contains at least {A: {B: {}}}.\nvar buildSymbolTree = function (symbolMap) {\n  var ret = {};\n\n  _.each(symbolMap, function (value, symbol) {\n    var parts = symbol.split('.');\n    var lastPart = parts.pop();\n\n    var walk = ret;\n    _.each(parts, function (part) {\n      if (! (part in walk)) {\n        walk[part] = {};\n      }\n      walk = walk[part];\n    });\n\n    if (value) {\n      walk[lastPart] = value;\n    }\n  });\n\n  return ret;\n};\n\n// Given something like {Foo: 's1', Bar: {Baz: 's2', Quux: {A: 's3', B: 's4'}}}\n// construct a string like {Foo: s1, Bar: {Baz: s2, Quux: {A: s3, B: s4}}}\n// except with pretty indentation.\nvar writeSymbolTree = function (symbolTree, indent) {\n  var put = function (node, indent) {\n    if (typeof node === \"string\") {\n      return node;\n    }\n    if (_.keys(node).length === 0) {\n      return '{}';\n    }\n    var spacing = new Array(indent + 1).join(' ');\n    // XXX prettyprint!\n    return \"{\\n\" +\n      _.map(node, function (value, key) {\n        return spacing + \"  \" + key + \": \" + put(value, indent + 2);\n      }).join(',\\n') + \"\\n\" + spacing + \"}\";\n  };\n\n  return put(symbolTree, indent || 0);\n};\n\n\n///////////////////////////////////////////////////////////////////////////////\n// File\n///////////////////////////////////////////////////////////////////////////////\n\nvar File = function (inputFile, module) {\n  var self = this;\n\n  // source code for this file (a string)\n  self.source = inputFile.data.toString('utf8');\n\n  // hash of source (precalculated for *.js files, calculated here for files\n  // produced by plugins)\n  self.sourceHash = inputFile.hash || watch.sha1(self.source);\n\n  // The path of the source file, relative to the root directory of the\n  // package or application.\n  self.sourcePath = inputFile.sourcePath;\n\n  // Absolute module identifier to use when installing this file via\n  // meteorInstall. If the inputFile has no .installPath, then this file\n  // cannot be installed as a module.\n  self.installPath = inputFile.installPath || null;\n\n  // the path where this file would prefer to be served if possible\n  self.servePath = inputFile.servePath;\n\n  // Module identifiers imported or required by this module, if any.\n  if (Array.isArray(inputFile.deps)) {\n    self.deps = inputFile.deps;\n  } else if (inputFile.deps && typeof inputFile.deps === \"object\") {\n    self.deps = Object.keys(inputFile.deps);\n  } else {\n    self.deps = [];\n  }\n\n  // True if the input file should not be evaluated eagerly.\n  self.lazy = inputFile.lazy; // could be `true`, `false` or `undefined` <sigh>\n\n  // True if the file is an eagerly evaluated entry point, or if some\n  // other file imports or requires it.\n  self.imported = !!inputFile.imported;\n\n  // Boolean indicating whether this file is the main entry point module\n  // for its package.\n  self.mainModule = !!inputFile.mainModule;\n\n  // If true, don't wrap this individual file in a closure.\n  self.bare = !!inputFile.bare;\n\n  // A source map (generated by something like CoffeeScript) for the input file.\n  // Is an Object, not a string.\n  self.sourceMap = inputFile.sourceMap;\n\n  // The Module containing this file.\n  self.module = module;\n};\n\n// findAssignedGlobals is somewhat slow, and we often compute assigned variables\n// on the same file multiple times in one process (notably, a single file is\n// often processed for two or three different unibuilds, and is processed again\n// when rebuilding a package when another file has changed). We cache the\n// calculated variables under the source file's hash (calculating the source\n// file's hash is faster than running findAssignedGlobals, and in the case of\n// *.js files we have the hash already anyway).\nvar ASSIGNED_GLOBALS_CACHE = {};\n\n_.extend(File.prototype, {\n  // Return the globals in this file as an array of symbol names.  For\n  // example: if the code references 'Foo.bar.baz' and 'Quux', and\n  // neither are declared in a scope enclosing the point where they're\n  // referenced, then globalReferences would include [\"Foo\", \"Quux\"].\n  computeAssignedVariables: Profile(\"linker File#computeAssignedVariables\", function () {\n    var self = this;\n\n    if (_.has(ASSIGNED_GLOBALS_CACHE, self.sourceHash)) {\n      return ASSIGNED_GLOBALS_CACHE[self.sourceHash];\n    }\n\n    try {\n      return ASSIGNED_GLOBALS_CACHE[self.sourceHash] =\n        _.keys(findAssignedGlobals(self.source, self.sourceHash));\n    } catch (e) {\n      if (!e.$ParseError) {\n        throw e;\n      }\n\n      var errorOptions = {\n        file: self.servePath,\n        line: e.lineNumber,\n        column: e.column\n      };\n      if (self.sourceMap) {\n        var parsed = new sourcemap.SourceMapConsumer(self.sourceMap);\n        var original = parsed.originalPositionFor(\n          {line: e.lineNumber, column: e.column - 1});\n        if (original.source) {\n          errorOptions.file = original.source;\n          errorOptions.line = original.line;\n          errorOptions.column = original.column + 1;\n        }\n      }\n\n      buildmessage.error(e.message, errorOptions);\n\n      // Recover by pretending that this file is empty (which\n      // includes replacing its source code with '' in the output)\n      self.source = \"\";\n      self.sourceHash = watch.sha1(self.source);\n      self.sourceMap = null;\n      return [];\n    }\n  }),\n\n  _useMeteorInstall() {\n    return this.module.meteorInstallOptions;\n  },\n\n  _getClosureHeader() {\n    if (this._useMeteorInstall()) {\n      var header = \"\";\n\n      if (this.deps.length > 0) {\n        header += \"[\";\n        _.each(this.deps, dep => {\n          header += JSON.stringify(dep) + \",\";\n        });\n      }\n\n      const headerParts = [\n        header,\n        \"function(\"\n      ];\n\n      if (this.source.match(/\\b__dirname\\b/)) {\n        headerParts.push(\"require,exports,module,__filename,__dirname\");\n      } else if (this.source.match(/\\b__filename\\b/)) {\n        headerParts.push(\"require,exports,module,__filename\");\n      } else if (this.source.match(/\\bmodule\\b/)) {\n        headerParts.push(\"require,exports,module\");\n      } else if (this.source.match(/\\bexports\\b/)) {\n        headerParts.push(\"require,exports\");\n      } else if (this.source.match(/\\brequire\\b/)) {\n        headerParts.push(\"require\");\n      }\n\n      headerParts.push(\"){\");\n\n      return headerParts.join(\"\");\n    }\n\n    return \"(function(){\";\n  },\n\n  _getClosureFooter() {\n    if (this._useMeteorInstall()) {\n      var footer = \"}\";\n      if (this.deps.length > 0) {\n        footer += \"]\";\n      }\n      return footer;\n    }\n    return \"}).call(this);\\n\";\n  },\n\n  // Options:\n  // - preserveLineNumbers: if true, decorate minimally so that line\n  //   numbers don't change between input and output. In this case,\n  //   sourceWidth is ignored.\n  // - noLineNumbers: We still include the banners and such, but\n  //   no line number suffix.\n  // - sourceWidth: width in columns to use for the source code\n  //\n  // Returns a SourceNode.\n  getPrelinkedOutput: Profile(\"linker File#getPrelinkedOutput\", function (options) {\n    var self = this;\n    var width = options.sourceWidth || 70;\n    var bannerWidth = width + 3;\n    var noLineNumbers = options.noLineNumbers;\n    var preserveLineNumbers = options.preserveLineNumbers;\n    var result;\n\n    if (self.sourceMap) {\n      // If we have a source map, it is also important to annotate line\n      // numbers using that source map, since not all browsers support\n      // source maps.\n      noLineNumbers = false;\n\n      // Honoring options.preserveLineNumbers is likely impossible if we\n      // have a source map, since self.source has probably already been\n      // transformed in a way that does not preserve line numbers. That's\n      // ok, though, because we have a source map, and we also annotate\n      // line numbers using comments (see above), just in case source maps\n      // are not supported.\n      preserveLineNumbers = false;\n    } else if (preserveLineNumbers) {\n      // If we don't have a source map, and we're supposed to be preserving line\n      // numbers (ie, we are not linking multiple files into one file, because\n      // we're the app), then we can get away without annotating line numbers\n      // (or making a source map), because they won't add any helpful\n      // information.\n      noLineNumbers = true;\n    }\n\n    let consumer;\n    let lines;\n\n    if (self.sourceMap) {\n      result = {\n        code: self.source,\n        map: self.sourceMap\n      };\n\n      consumer = new sourcemap.SourceMapConsumer(result.map);\n\n    } else if (noLineNumbers && preserveLineNumbers) {\n      // No need to generate a source map if we don't want line numbers.\n      result = {\n        code: self.source,\n        map: null\n      };\n\n    } else {\n      // If we're planning to annotate the source with line number\n      // comments (e.g. because we're combining this file with others in a\n      // package), and we don't already have a source map, then we need to\n      // generate one, but it doesn't have to be very detailed, since we\n      // we can use a dumb implementation of originalPositionFor.\n      const smg = new sourcemap.SourceMapGenerator({\n        file: self.servePath\n      });\n\n      lines = self.source.split(/\\r?\\n/);\n\n      function addIdentityMapping(pos) {\n        smg.addMapping({\n          original: pos,\n          generated: pos,\n          source: self.servePath,\n        });\n      }\n\n      for (var line = 1; line <= lines.length; ++line) {\n        addIdentityMapping({ line, column: 0 });\n      }\n\n      smg.setSourceContent(self.servePath, self.source);\n\n      result = {\n        code: self.source,\n        map: smg.toJSON(),\n      };\n\n      // Generating line number comments for really big files is not\n      // really worth it when there's no meaningful self.sourceMap.\n      if (self.source.length < 500000) {\n        consumer = {\n          originalPositionFor(pos) {\n            return pos;\n          }\n        };\n      }\n    }\n\n    if (consumer && ! noLineNumbers) {\n      var padding = bannerPadding(bannerWidth);\n\n      // We might have already done this split above.\n      lines = lines || result.code.split(/\\r?\\n/);\n\n      // Use the SourceMapConsumer object to compute the original line\n      // number for each line of result.code.\n      for (var i = 0, lineCount = lines.length; i < lineCount; ++i) {\n        var line = lines[i];\n        var len = line.length;\n        if (len < width &&\n            line[len - 1] !== \"\\\\\") {\n          var pos = consumer.originalPositionFor({\n            line: i + 1,\n            column: 0\n          });\n\n          if (pos) {\n            line += padding.slice(len, width) + \" //\";\n            // Not all source maps define a mapping for every line in the\n            // output. This is perfectly normal.\n            if (typeof pos.line === \"number\") {\n              line += \" \" + pos.line;\n            }\n            lines[i] = line;\n          }\n        }\n      }\n\n      result.code = lines.join(\"\\n\");\n    }\n\n    var chunks = [];\n    var pathNoSlash = self.servePath.replace(/^\\//, \"\");\n\n    if (! self.bare) {\n      var closureHeader = self._getClosureHeader();\n      chunks.push(\n        closureHeader,\n        preserveLineNumbers ? \"\" : \"\\n\\n\"\n      );\n    }\n\n    if (! preserveLineNumbers) {\n      // Banner\n      var bannerLines = [pathNoSlash];\n\n      if (self.bare) {\n        bannerLines.push(\n          \"This file is in bare mode and is not in its own closure.\");\n      }\n\n      chunks.push(banner(bannerLines, bannerWidth));\n\n      var blankLine = new Array(width + 1).join(' ') + \" //\\n\";\n      chunks.push(blankLine);\n    }\n\n    if (result.code) {\n      // If we have a source map for result.code, push a SourceNode onto\n      // the chunks array that encapsulates that source map. If we don't\n      // have a source map, just push result.code.\n\n      let chunk = result.code;\n\n      if (consumer instanceof sourcemap.SourceMapConsumer) {\n        chunk = sourcemap.SourceNode.fromStringWithSourceMap(\n          result.code, consumer);\n\n      } else if (consumer && result.map) {\n        chunk = sourcemap.SourceNode.fromStringWithSourceMap(\n          result.code,\n          new sourcemap.SourceMapConsumer(result.map),\n        );\n      }\n\n      chunks.push(chunk);\n\n      // It's important for the code to end with a newline, so that a\n      // trailing // comment can't snarf code appended after it.\n      if (result.code[result.code - 1] !== \"\\n\") {\n        chunks.push(\"\\n\");\n      }\n    }\n\n    // Footer\n    if (self.bare) {\n      if (! preserveLineNumbers) {\n        chunks.push(dividerLine(bannerWidth), \"\\n\");\n      }\n    } else {\n      const closureFooter = self._getClosureFooter();\n      if (preserveLineNumbers) {\n        chunks.push(closureFooter);\n      } else {\n        chunks.push(\n          dividerLine(bannerWidth),\n          \"\\n\",\n          closureFooter\n        );\n      }\n    }\n\n    return new sourcemap.SourceNode(null, null, null, chunks);\n  })\n});\n\n// Given a list of lines (not newline-terminated), returns a string placing them\n// in a pretty banner of width bannerWidth. All lines must have length at most\n// (bannerWidth - 6); if bannerWidth is not provided, the smallest width that\n// fits is used.\nvar banner = function (lines, bannerWidth) {\n  if (!bannerWidth) {\n    bannerWidth = 6 + _.max(lines, function (x) { return x.length; }).length;\n  }\n\n  var divider = dividerLine(bannerWidth);\n  var spacer = \"// \" + new Array(bannerWidth - 6 + 1).join(' ') + \" //\\n\";\n  var padding = bannerPadding(bannerWidth);\n\n  var buf = divider + spacer;\n  _.each(lines, function (line) {\n    buf += \"// \" + (line + padding).slice(0, bannerWidth - 6) + \" //\\n\";\n  });\n  buf += spacer + divider;\n  return buf;\n};\nvar dividerLine = function (bannerWidth) {\n  return new Array(bannerWidth + 1).join('/') + \"\\n\";\n};\nvar bannerPadding = function (bannerWidth) {\n  return new Array(bannerWidth + 1).join(' ');\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Top-level entry points\n///////////////////////////////////////////////////////////////////////////////\n\n// Prior to the \"batch-plugins\" project, linker.prelink was the first phase of\n// linking. It got performed at package compile time, to be followed up with a\n// function that used to exist called linker.link at app bundle time. We now do\n// far less processing at package compile time and simply run linker.fullLink at\n// app bundle time, which is effectively the old prelink+link combined. However,\n// we keep linker.prelink around now in order to allow new published packages\n// that don't use the new build plugin APIs to be used by older Isobuilds.\n// It only gets called on packages, not on apps.\n//\n// This does about half of the of the linking process. It does not require\n// knowledge of your imports. It returns the module's exports, plus a set of\n// partially linked files which you must pass to link() along with your import\n// list to get your final linked files.\n//\n// options include:\n//\n// name: the name of this module (for stashing exports to be later\n// read by the imports of other modules); null if the module has no\n// name (in that case exports will not work properly)\n//\n// inputFiles: an array of objects representing input files.\n//  - source: the source code\n//  - servePath: the path where it would prefer to be served if\n//    possible. still allowed on non-browser targets, where it\n//    represent as hint as to what the file should be named on disk in\n//    the bundle (this will only be seen by someone looking at the\n//    bundle, not in error messages, but it's still nice to make it\n//    look good)\n//  - sourceMap: an optional source map (as string) for the input file\n//\n// combinedServePath: if we end up combining all of the files into\n// one, use this as the servePath.\n//\n// Output is an object with keys:\n// - files: is an array of output files in the same format as inputFiles\n//   - EXCEPT THAT, for now, sourcePath is omitted and is replaced with\n//     sourceMap (a string) (XXX)\n// - assignedPackageVariables: an array of variables assigned to without\n//   being declared\nexport var prelink = Profile(\"linker.prelink\", function (options) {\n  var module = new Module({\n    name: options.name,\n    combinedServePath: options.combinedServePath,\n    noLineNumbers: options.noLineNumbers\n  });\n\n  _.each(options.inputFiles, function (inputFile) {\n    module.addFile(inputFile);\n  });\n\n  // Do static analysis to compute module-scoped variables. Error recovery from\n  // the static analysis mutates the sources, so this has to be done before\n  // concatenation.\n  var assignedVariables = module.computeAssignedVariables();\n  var files = module.getPrelinkedFiles();\n\n  return {\n    files: files,\n    assignedVariables: assignedVariables\n  };\n});\n\nvar SOURCE_MAP_INSTRUCTIONS_COMMENT = banner([\n  \"This is a generated file. You can view the original\",\n  \"source in your browser if your browser supports source maps.\",\n  \"Source maps are supported by all recent versions of Chrome, Safari, \",\n  \"and Firefox, and by Internet Explorer 11.\"\n]);\n\nvar getHeader = function (options) {\n  var chunks = [];\n\n  chunks.push(\n    \"(function () {\\n\\n\",\n    getImportCode(options.imports, \"/* Imports */\\n\", false),\n  );\n\n  const packageVariables = _.filter(\n    options.packageVariables,\n    name => ! _.has(options.imports, name),\n  );\n\n  if (!_.isEmpty(packageVariables)) {\n    chunks.push(\n      \"/* Package-scope variables */\\n\",\n      \"var \",\n      packageVariables.join(', '),\n      \";\\n\\n\",\n    );\n  }\n\n  return chunks.join('');\n};\n\nvar getImportCode = function (imports, header, omitvar) {\n  var self = this;\n\n  if (_.isEmpty(imports)) {\n    return \"\";\n  }\n\n  // Imports\n  var scratch = {};\n  _.each(imports, function (name, symbol) {\n    scratch[symbol] = packageDot(name) + \".\" + symbol;\n  });\n  var tree = buildSymbolTree(scratch);\n\n  // Generate output\n  var buf = header;\n  _.each(tree, function (node, key) {\n    buf += (omitvar ? \"\" : \"var \" ) +\n      key + \" = \" + writeSymbolTree(node) + \";\\n\";\n  });\n  buf += \"\\n\";\n\n  return buf;\n};\n\nvar getFooter = function ({\n  name,\n  exported,\n  exportsName,\n}) {\n  var chunks = [];\n\n  if (name && exported) {\n    chunks.push(\"\\n\\n/* Exports */\\n\");\n    chunks.push(\"if (typeof Package === 'undefined') Package = {};\\n\");\n    const pkgInit = packageDot(name) + \" = \" + (exportsName || \"{}\");\n    if (_.isEmpty(exported)) {\n      // Even if there are no exports, we need to define Package.foo,\n      // because the existence of Package.foo is how another package\n      // (e.g., one that weakly depends on foo) can tell if foo is loaded.\n      chunks.push(pkgInit, \";\\n\");\n    } else {\n      const scratch = {};\n      _.each(exported, symbol => scratch[symbol] = symbol);\n      const symbolTree = writeSymbolTree(buildSymbolTree(scratch));\n      chunks.push(\"(function (pkg, symbols) {\\n\",\n                  \"  for (var s in symbols)\\n\",\n                  \"    (s in pkg) || (pkg[s] = symbols[s]);\\n\",\n                  \"})(\", pkgInit, \", \", symbolTree, \");\\n\");\n    }\n  }\n\n  chunks.push(\"\\n})();\\n\");\n  return chunks.join('');\n};\n\n// This is the real entry point that's still used to produce Meteor apps.  It\n// takes in information about the files in the package including imports and\n// exports, and returns an array of linked source files.\n//\n// inputFiles: an array of objects representing input files.\n//  - source: the source code\n//  - hash: the hash of the source code (optional, will be calculated\n//    if not given)\n//  - servePath: the path where it would prefer to be served if\n//    possible. still allowed on non-browser targets, where it\n//    represent as hint as to what the file should be named on disk in\n//    the bundle (this will only be seen by someone looking at the\n//    bundle, not in error messages, but it's still nice to make it\n//    look good)\n//  - bare: if true, don't wrap this file in a closure\n//  - sourceMap: an optional source map (as object) for the input file\n//\n// Output is an array of output files: objects with keys source, servePath,\n// sourceMap.\nexport var fullLink = Profile(\"linker.fullLink\", function (inputFiles, {\n  // If true, make the top level namespace be the same as the global\n  // namespace, so that symbols are accessible from the console, and don't\n  // actually combine files into a single file. used when linking apps (as\n  // opposed to packages).\n  useGlobalNamespace,\n  // Options to pass as the second argument to meteorInstall. Falsy if\n  // meteorInstall is disabled.\n  meteorInstallOptions,\n  // If we end up combining all of the files into one, use this as the\n  // servePath.\n  combinedServePath,\n  // The name of this module (for stashing exports to be later read by the\n  // imports of other modules); null if the module has no name (in that\n  // case exports will not work properly)\n  name,\n  // An array of symbols that the module exports. Symbols are\n  // {name,testOnly} pairs.\n  declaredExports,\n  // a map from imported symbol to the name of the package that it is\n  // imported from\n  imports,\n  // If useGlobalNamespace is set, this is the name of the file to create\n  // with imports into the global namespace.\n  importStubServePath,\n  // True if JS files with source maps should have a comment explaining\n  // how to use them in a browser.\n  includeSourceMapInstructions,\n  noLineNumbers,\n}) {\n  buildmessage.assertInJob();\n\n  var module = new Module({\n    name,\n    meteorInstallOptions,\n    useGlobalNamespace,\n    combinedServePath,\n    noLineNumbers\n  });\n\n  _.each(inputFiles, file => module.addFile(file));\n\n  var prelinkedFiles = module.getPrelinkedFiles();\n\n  // If we're in the app, then we just add the import code as its own file in\n  // the front.\n  if (useGlobalNamespace) {\n    if (!_.isEmpty(imports)) {\n      prelinkedFiles.unshift({\n        source: getImportCode(imports,\n                              \"/* Imports for global scope */\\n\\n\", true),\n        servePath: importStubServePath\n      });\n    }\n    return prelinkedFiles;\n  }\n\n  // Do static analysis to compute module-scoped variables. Error recovery from\n  // the static analysis mutates the sources, so this has to be done before\n  // concatenation.\n  let assignedVariables;\n  const failed = buildmessage.enterJob('computing assigned variables', () => {\n    assignedVariables = module.computeAssignedVariables();\n    return buildmessage.jobHasMessages();\n  });\n  if (failed) {\n    // recover by pretending there are no files\n    return [];\n  }\n\n  // Otherwise we're making a package and we have to actually combine the files\n  // into a single scope.\n  var header = getHeader({\n    imports,\n    packageVariables: _.union(assignedVariables, declaredExports)\n  });\n\n  let exportsName;\n  _.each(prelinkedFiles, file => {\n    if (file.exportsName) {\n      exportsName = file.exportsName;\n    }\n  });\n\n  var footer = getFooter({\n    exported: declaredExports,\n    exportsName,\n    name\n  });\n\n  return _.map(prelinkedFiles, function (file) {\n    if (file.sourceMap) {\n      if (includeSourceMapInstructions) {\n        header = SOURCE_MAP_INSTRUCTIONS_COMMENT + \"\\n\\n\" + header;\n      }\n\n      // Bias the source map by the length of the header without\n      // (fully) parsing and re-serializing it. (We used to do this\n      // with the source-map library, but it was incredibly slow,\n      // accounting for over half of bundling time.) It would be nice\n      // if we could use \"index maps\" for this (the 'sections' key),\n      // as that would let us avoid even JSON-parsing the source map,\n      // but that doesn't seem to be supported by Firefox yet.\n      if (header.charAt(header.length - 1) !== \"\\n\") {\n        // make sure it's a whole number of lines\n        header += \"\\n\";\n      }\n      var headerLines = header.split('\\n').length - 1;\n      var sourceMap = file.sourceMap;\n      sourceMap.mappings = (new Array(headerLines + 1).join(';')) +\n        sourceMap.mappings;\n      return {\n        source: header + file.source + footer,\n        sourcePath: file.sourcePath,\n        servePath: file.servePath,\n        sourceMap: sourceMap\n      };\n    } else {\n      return {\n        source: header + file.source + footer,\n        sourcePath: file.sourcePath,\n        servePath: file.servePath\n      };\n    }\n  });\n});\n"
  },
  {
    "path": "tools/isobuild/linter-plugin.js",
    "content": "import { InputFile } from \"./build-plugin.js\";\n\nexport class LinterPlugin {\n  constructor(pluginDefinition, userPlugin) {\n    this.pluginDefinition = pluginDefinition;\n    this.userPlugin = userPlugin;\n  }\n}\n\nexport class LintingFile extends InputFile {\n  constructor(source) {\n    super();\n    this._source = source;\n  }\n\n  getContentsAsBuffer() {\n    return this._source.contents;\n  }\n\n  getPathInPackage() {\n    return this._source.relPath;\n  }\n\n  getPackageName() {\n    return this._source[\"package\"];\n  }\n\n  getSourceHash() {\n    return this._source.hash;\n  }\n\n  getArch() {\n    return this._source.arch;\n  }\n\n  getFileOptions() {\n    return this._source.fileOptions || {};\n  }\n}\n"
  },
  {
    "path": "tools/isobuild/meteor-npm-userconfig",
    "content": "# This file intentionally left empty to ensure consistent npm\n# configuration.\n"
  },
  {
    "path": "tools/isobuild/meteor-npm.js",
    "content": "/// Implements the process of managing a package's .npm directory,\n/// in which we call `npm install` to install npm dependencies,\n/// and a variety of related commands. Notably, we use `npm shrinkwrap`\n/// to ensure we get consistent versions of npm sub-dependencies.\n\nvar assert = require('assert');\nvar cleanup = require('../tool-env/cleanup.js');\nvar fs = require('fs');\nvar files = require('../fs/files.js');\nvar os = require('os');\nvar _ = require('underscore');\nvar httpHelpers = require('../utils/http-helpers.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar utils = require('../utils/utils.js');\nvar runLog = require('../runners/run-log.js');\nvar Profile = require('../tool-env/profile.js').Profile;\n\nvar meteorNpm = exports;\n\n// if a user exits meteor while we're trying to create a .npm\n// directory, we will have temporary directories that we clean up\nvar tmpDirs = [];\ncleanup.onExit(function () {\n  _.each(tmpDirs, function (dir) {\n    if (files.exists(dir)) {\n      files.rm_recursive(dir);\n    }\n  });\n});\n\n// Exception used internally to gracefully bail out of a npm run if\n// something goes wrong\nvar NpmFailure = function () {};\n\n// Creates a temporary directory in which the new contents of the\n// package's .npm directory will be assembled. If all is successful,\n// renames that directory back to .npm. Returns true if there are NPM\n// dependencies and they are installed without error.\n//\n// @param npmDependencies {Object} dependencies that should be\n//     installed, eg {tar: '0.1.6', gcd: '0.0.0'}. If falsey or empty,\n//     will remove the .npm directory instead.\nmeteorNpm.updateDependencies = function (packageName,\n                                         packageNpmDir,\n                                         npmDependencies,\n                                         quiet) {\n  // we make sure to put it beside the original package dir so that\n  // we can then atomically rename it. we also make sure to\n  // randomize the name, in case we're bundling this package\n  // multiple times in parallel.\n  var newPackageNpmDir = packageNpmDir + '-new-' + utils.randomToken();\n\n  if (! npmDependencies || _.isEmpty(npmDependencies)) {\n    // No NPM dependencies? Delete the .npm directory if it exists (because,\n    // eg, we used to have NPM dependencies but don't any more).  We'd like to\n    // do this in as atomic a way as possible in case multiple meteor\n    // instances are trying to make this update in parallel, so we rename the\n    // directory to something before doing the rm -rf.\n    try {\n      files.rename(packageNpmDir, newPackageNpmDir);\n    } catch (e) {\n      if (e.code !== 'ENOENT') {\n        throw e;\n      }\n      // It didn't exist, which is exactly what we wanted.\n      return false;\n    }\n    files.rm_recursive(newPackageNpmDir);\n    return false;\n  }\n\n  try {\n    // v0.6.0 had a bug that could cause .npm directories to be\n    // created without npm-shrinkwrap.json\n    // (https://github.com/meteor/meteor/pull/927). Running your app\n    // in that state causes consistent \"Corrupted .npm directory\"\n    // errors.\n    //\n    // If you've reached that state, delete the empty directory and\n    // proceed.\n    if (files.exists(packageNpmDir) &&\n        ! files.exists(files.pathJoin(packageNpmDir, 'npm-shrinkwrap.json'))) {\n      files.rm_recursive(packageNpmDir);\n    }\n\n    if (files.exists(packageNpmDir)) {\n      // we already nave a .npm directory. update it appropriately with some\n      // ceremony involving:\n      // `npm install`, `npm install name@version`, `npm shrinkwrap`\n      updateExistingNpmDirectory(\n        packageName, newPackageNpmDir, packageNpmDir, npmDependencies, quiet);\n    } else {\n      // create a fresh .npm directory with `npm install\n      // name@version` and `npm shrinkwrap`\n      createFreshNpmDirectory(\n        packageName, newPackageNpmDir, packageNpmDir, npmDependencies, quiet);\n    }\n  } catch (e) {\n    if (e instanceof NpmFailure) {\n      // Something happened that was out of our control, but wasn't\n      // exactly unexpected (eg, no such npm package, no internet\n      // connection). Handle it gracefully.\n      return false;\n    }\n\n    // Some other exception -- let it propagate.\n    throw e;\n  } finally {\n    if (files.exists(newPackageNpmDir)) {\n      files.rm_recursive(newPackageNpmDir);\n    }\n    tmpDirs = _.without(tmpDirs, newPackageNpmDir);\n  }\n\n  return true;\n};\n\n// Returns a flattened list of npm package names used in production.\nmeteorNpm.getProdPackageNames = function (nodeModulesDir) {\n  var names = Object.create(null);\n  var lsResult = runNpmCommand([\n    \"ls\", \"--json\", \"--production\"\n  ], nodeModulesDir);\n\n  function walk(deps) {\n    if (! deps) {\n      return;\n    }\n\n    Object.keys(deps).forEach(function (name) {\n      names[name] = true;\n      walk(deps[name].dependencies);\n    });\n  }\n\n  walk(JSON.parse(lsResult.stdout).dependencies);\n\n  return names;\n};\n\nconst lastRebuildJSONFilename = \".meteor-last-rebuild-version.json\";\nconst currentVersionsJSON =\n  JSON.stringify(process.versions, null, 2) + \"\\n\";\n\nfunction recordLastRebuildVersions(pkgDir) {\n  // Record the current process.versions so that we can avoid\n  // copying/rebuilding/renaming next time.\n  files.writeFile(\n    files.pathJoin(pkgDir, lastRebuildJSONFilename),\n    currentVersionsJSON,\n    \"utf8\"\n  );\n}\n\n// Rebuilds any binary dependencies in the given node_modules directory,\n// and returns true iff anything was rebuilt.\nmeteorNpm.rebuildIfNonPortable =\nProfile(\"meteorNpm.rebuildIfNonPortable\", function (nodeModulesDir) {\n  const dirsToRebuild = [];\n\n  files.readdir(nodeModulesDir).forEach(function (pkg) {\n    const pkgPath = files.pathJoin(nodeModulesDir, pkg);\n\n    if (isPortable(pkgPath, true)) {\n      return;\n    }\n\n    const versionFile =\n      files.pathJoin(pkgPath, lastRebuildJSONFilename);\n\n    try {\n      var versions = JSON.parse(files.readFile(versionFile));\n    } catch (e) {\n      if (! (e instanceof SyntaxError ||\n             e.code === \"ENOENT\")) {\n        throw e;\n      }\n    }\n\n    if (_.isEqual(versions, process.versions)) {\n      return;\n    }\n\n    dirsToRebuild.push(pkgPath);\n  });\n\n  if (dirsToRebuild.length === 0) {\n    return false;\n  }\n\n  const tempDir = files.pathJoin(\n    nodeModulesDir,\n    \".temp-\" + utils.randomToken()\n  );\n\n  // There's a chance the basename of the original nodeModulesDir isn't\n  // actually \"node_modules\", which will confuse the `npm rebuild`\n  // command, but fortunately we can ensure this temporary directory has\n  // exactly that basename.\n  const tempNodeModules = files.pathJoin(tempDir, \"node_modules\");\n  files.mkdir_p(tempNodeModules);\n\n  // Map from original package directory paths to temporary package\n  // directory paths.\n  const tempPkgDirs = {};\n\n  dirsToRebuild.forEach(function (pkgPath) {\n    const tempPkgDir = tempPkgDirs[pkgPath] = files.pathJoin(\n      tempNodeModules,\n      files.pathBasename(pkgPath)\n    );\n\n    // Copy instead of rename so that the original package directories\n    // will be left untouched if the rebuild fails.\n    files.cp_r(pkgPath, tempPkgDir);\n\n    // Record the current process.versions so that we can avoid\n    // copying/rebuilding/renaming next time.\n    recordLastRebuildVersions(tempPkgDir);\n  });\n\n  // The `npm rebuild` command must be run in the parent directory of the\n  // relevant node_modules directory, which in this case is tempDir.\n  const rebuildResult = runNpmCommand([\"rebuild\"], tempDir);\n  if (! rebuildResult.success) {\n    buildmessage.error(rebuildResult.error);\n    files.rm_recursive(tempDir);\n    return false;\n  }\n\n  // If the `npm rebuild` command succeeded, overwrite the original\n  // package directories with the rebuilt package directories.\n  dirsToRebuild.forEach(function (pkgPath) {\n    files.renameDirAlmostAtomically(tempPkgDirs[pkgPath], pkgPath);\n  });\n\n  files.rm_recursive(tempDir);\n\n  return true;\n});\n\nfunction isPortable(dir, shouldCache) {\n  if (! files.lstat(dir).isDirectory()) {\n    return true;\n  }\n\n  return files.readdir(dir).every(itemName => {\n    const item = files.pathJoin(dir, itemName);\n\n    if (! files.lstat(item).isDirectory()) {\n      // Non-directory files are portable unless they end with .node.\n      return ! itemName.endsWith(\".node\");\n    }\n\n    if (! shouldCache) {\n      // Once we stop caching, we keep calling isPortable recursively\n      // without caching.\n      return isPortable(item);\n    }\n\n    // Cache previous results by writing a boolean value to a hidden\n    // file called .meteor-portable. Although it's tempting to write\n    // this file once for the whole node_modules directory, it's\n    // important that we put separate files in the individual top-level\n    // package directories so that they will get cleared away the next\n    // time those packages are (re)installed.\n\n    const portableFile = files.pathJoin(item, \".meteor-portable\");\n    try {\n      return JSON.parse(files.readFile(portableFile));\n    } catch (e) {\n      if (! (e instanceof SyntaxError ||\n             e.code === \"ENOENT\")) {\n        throw e;\n      }\n    }\n\n    const result = isPortable(item);\n\n    // Write the .meteor-portable file asynchronously, and don't worry\n    // if it fails, e.g. because the file system is read-only (#6591).\n    // Failing to write the file only means more work next time.\n    fs.writeFile(\n      portableFile,\n      JSON.stringify(result) + \"\\n\",\n      (error) => {}\n    );\n\n    return result;\n  });\n}\n\n// Return true if all of a package's npm dependencies are portable\n// (that is, if the node_modules can be copied anywhere and we'd\n// expect it to work, rather than containing native extensions that\n// were built just for our architecture), else\n// false. updateDependencies should first be used to bring\n// nodeModulesDir up to date.\nmeteorNpm.dependenciesArePortable = function (nodeModulesDir) {\n  // We use a simple heuristic: we check to see if a package (or any\n  // of its transitive dependencies) contains any *.node files. .node\n  // is the extension that signals to Node that it should load a file\n  // as a shared object rather than as JavaScript, so this should work\n  // in the vast majority of cases.\n\n  assert.ok(\n    files.pathBasename(nodeModulesDir).startsWith(\"node_modules\"),\n    \"Bad node_modules directory: \" + nodeModulesDir,\n  );\n\n  // Only check/write .meteor-portable files in each of the top-level\n  // package directories.\n  return isPortable(nodeModulesDir, true);\n};\n\nvar makeNewPackageNpmDir = function (newPackageNpmDir) {\n  // keep track so that we can remove them on process exit\n  tmpDirs.push(newPackageNpmDir);\n  files.mkdir_p(newPackageNpmDir);\n\n  // create node_modules -- prevent npm install from installing\n  // to an existing node_modules dir higher up in the filesystem\n  files.mkdir(files.pathJoin(newPackageNpmDir, 'node_modules'));\n\n  // create .gitignore -- node_modules shouldn't be in git since we\n  // recreate it as needed by using `npm install`. since we use `npm\n  // shrinkwrap` we're guaranteed to have the same version installed\n  // each time.\n  files.writeFile(\n    files.pathJoin(newPackageNpmDir, '.gitignore'),\n    ['node_modules',\n     ''/*git diff complains without trailing newline*/].join('\\n'));\n};\n\nvar updateExistingNpmDirectory = function (packageName, newPackageNpmDir,\n                                           packageNpmDir, npmDependencies,\n                                           quiet) {\n  // sanity check on contents of .npm directory\n  if (!files.stat(packageNpmDir).isDirectory()) {\n    throw new Error(\"Corrupted .npm directory -- should be a directory: \" +\n                    packageNpmDir);\n  }\n  if (!files.exists(files.pathJoin(packageNpmDir, 'npm-shrinkwrap.json'))) {\n    throw new Error(\n      \"Corrupted .npm directory -- can't find npm-shrinkwrap.json in \" +\n        packageNpmDir);\n  }\n\n  // We need to rebuild all node modules when the Node version\n  // changes, in case there are some binary ones. Technically this is\n  // racey, but it shouldn't fail very often.\n  var nodeModulesDir = files.pathJoin(packageNpmDir, 'node_modules');\n  if (files.exists(nodeModulesDir)) {\n    var oldNodeVersion;\n    try {\n      oldNodeVersion = files.readFile(\n        files.pathJoin(packageNpmDir, 'node_modules', '.node_version'), 'utf8');\n    } catch (e) {\n      if (e.code !== 'ENOENT') {\n        throw e;\n      }\n      // Use the Node version from the last release where we didn't\n      // drop this file.\n      oldNodeVersion = 'v0.8.24';\n    }\n\n    if (oldNodeVersion !== currentNodeCompatibilityVersion()) {\n      files.rm_recursive(nodeModulesDir);\n    }\n  }\n\n  // Make sure node_modules is present (fix for #1761). Prevents npm install\n  // from installing to an existing node_modules dir higher up in the\n  // filesystem.  node_modules may be absent due to a change in Node version or\n  // when `meteor add`ing a cloned package for the first time (node_modules is\n  // excluded by .gitignore)\n  if (! files.exists(nodeModulesDir)) {\n    files.mkdir(nodeModulesDir);\n  }\n\n  var installedDependenciesTree = getInstalledDependenciesTree(packageNpmDir);\n  var shrinkwrappedDependenciesTree =\n    getShrinkwrappedDependenciesTree(packageNpmDir);\n\n  const npmTree = { dependencies: {} };\n  _.each(npmDependencies, (version, name) => {\n    npmTree.dependencies[name] = { version };\n  });\n\n  const minInstalledTree =\n    minimizeDependencyTree(installedDependenciesTree);\n  const minShrinkwrapTree =\n    minimizeDependencyTree(shrinkwrappedDependenciesTree);\n\n  if (isSubtreeOf(npmTree, minInstalledTree) &&\n      isSubtreeOf(minShrinkwrapTree, minInstalledTree)) {\n    return;\n  }\n\n  if (! quiet) {\n    logUpdateDependencies(packageName, npmDependencies);\n  }\n\n  let preservedShrinkwrap;\n\n  if (_.isEmpty(npmDependencies)) {\n    // If there are no npmDependencies, make sure nothing is installed.\n    preservedShrinkwrap = { dependencies: {} };\n  } else if (isSubtreeOf(npmTree, minShrinkwrapTree)) {\n    // If the top-level npm dependencies are already encompassed by the\n    // npm-shrinkwrap.json file, then reuse that file.\n    preservedShrinkwrap = shrinkwrappedDependenciesTree;\n  } else {\n    // Otherwise install only the required npm packages and their\n    // dependencies.\n    preservedShrinkwrap = npmTree;\n  }\n\n  makeNewPackageNpmDir(newPackageNpmDir);\n\n  if (!_.isEmpty(preservedShrinkwrap.dependencies)) {\n    const newShrinkwrapFile = files.pathJoin(\n      newPackageNpmDir,\n      'npm-shrinkwrap.json'\n    );\n\n    // There are some unchanged packages here. Install from shrinkwrap.\n    files.writeFile(\n      newShrinkwrapFile,\n      JSON.stringify(preservedShrinkwrap, null, 2)\n    );\n\n    // `npm install`\n    installFromShrinkwrap(newPackageNpmDir);\n\n    files.unlink(newShrinkwrapFile);\n  }\n\n  completeNpmDirectory(packageName, newPackageNpmDir, packageNpmDir,\n                       npmDependencies);\n};\n\nfunction isSubtreeOf(subsetTree, supersetTree) {\n  if (subsetTree === supersetTree) {\n    return true;\n  }\n\n  return _.isObject(subsetTree) &&\n    _.isObject(supersetTree) &&\n    _.every(subsetTree, (value, key) => {\n      return isSubtreeOf(value, supersetTree[key]);\n    });\n}\n\nvar createFreshNpmDirectory = function (packageName, newPackageNpmDir,\n                                        packageNpmDir, npmDependencies, quiet) {\n  if (! quiet) {\n    logUpdateDependencies(packageName, npmDependencies);\n  }\n\n  makeNewPackageNpmDir(newPackageNpmDir);\n  // install dependencies\n  _.each(npmDependencies, function (version, name) {\n    installNpmModule(name, version, newPackageNpmDir);\n  });\n\n  completeNpmDirectory(packageName, newPackageNpmDir, packageNpmDir,\n                       npmDependencies);\n};\n\n// Shared code for updateExistingNpmDirectory and createFreshNpmDirectory.\nvar completeNpmDirectory = function (packageName, newPackageNpmDir,\n                                     packageNpmDir, npmDependencies) {\n  // Create a shrinkwrap file.\n  shrinkwrap(newPackageNpmDir);\n\n  // And stow a copy of npm-shrinkwrap too.\n  files.copyFile(\n    files.pathJoin(newPackageNpmDir, 'npm-shrinkwrap.json'),\n    files.pathJoin(newPackageNpmDir, 'node_modules', '.npm-shrinkwrap.json'));\n\n  createReadme(newPackageNpmDir);\n  createNodeVersion(newPackageNpmDir);\n  files.renameDirAlmostAtomically(newPackageNpmDir, packageNpmDir);\n};\n\nvar createReadme = function (newPackageNpmDir) {\n  // This file gets checked in to version control by users, so resist the\n  // temptation to make unnecessary tweaks to it.\n  files.writeFile(\n    files.pathJoin(newPackageNpmDir, 'README'),\n\"This directory and the files immediately inside it are automatically generated\\n\" +\n\"when you change this package's NPM dependencies. Commit the files in this\\n\" +\n\"directory (npm-shrinkwrap.json, .gitignore, and this README) to source control\\n\" +\n\"so that others run the same versions of sub-dependencies.\\n\" +\n\"\\n\" +\n\"You should NOT check in the node_modules directory that Meteor automatically\\n\" +\n\"creates; if you are using git, the .gitignore file tells git to ignore it.\\n\"\n  );\n};\n\nvar createNodeVersion = function (newPackageNpmDir) {\n  files.writeFile(\n    files.pathJoin(newPackageNpmDir, 'node_modules', '.node_version'),\n    currentNodeCompatibilityVersion());\n};\n\n// This value should change whenever we think that the Node C ABI has changed\n// (ie, when we need to be sure to reinstall npm packages because they might\n// have native components that need to be rebuilt). It does not need to change\n// for every patch release of Node! Notably, it needed to change between 0.8.*\n// and 0.10.*.  If Node does make a patch release of 0.10 that breaks\n// compatibility, you can just change this from \"0.10.*\" to \"0.10.35\" or\n// whatever.\nvar currentNodeCompatibilityVersion = function () {\n  var version = process.version;\n  version = version.replace(/\\.(\\d+)$/, '.*');\n  return version + '\\n';\n};\n\nconst npmUserConfigFile = files.pathJoin(\n  __dirname,\n  \"meteor-npm-userconfig\"\n);\n\nvar runNpmCommand = meteorNpm.runNpmCommand =\nProfile(\"meteorNpm.runNpmCommand\", function (args, cwd) {\n  const nodeBinDir = files.getCurrentNodeBinDir();\n  const isWindows = process.platform === \"win32\";\n  var npmPath;\n\n  if (isWindows) {\n    npmPath = files.convertToOSPath(\n      files.pathJoin(nodeBinDir, \"npm.cmd\"));\n  } else {\n    npmPath = files.pathJoin(nodeBinDir, \"npm\");\n  }\n\n  if (meteorNpm._printNpmCalls) {\n    // only used by test-bundler.js\n    process.stdout.write('cd ' + cwd + ' && ' + npmPath + ' ' +\n                         args.join(' ') + ' ...\\n');\n  }\n\n  if (cwd) {\n    cwd = files.convertToOSPath(cwd);\n  }\n\n  const env = require(\"../cli/dev-bundle-bin-helpers.js\").getEnv();\n\n  // Make sure we don't honor any user-provided configuration files.\n  env.npm_config_userconfig = npmUserConfigFile;\n\n  var opts = { cwd: cwd, env: env, maxBuffer: 10 * 1024 * 1024 };\n\n  return new Promise(function (resolve) {\n    require('child_process').execFile(\n      npmPath, args, opts, function (err, stdout, stderr) {\n        if (meteorNpm._printNpmCalls) {\n          process.stdout.write(err ? 'failed\\n' : 'done\\n');\n        }\n\n        resolve({\n          success: ! err,\n          error: (err ? `${err.message}${stderr}` : stderr),\n          stdout: stdout,\n          stderr: stderr\n        });\n      }\n    );\n  }).await();\n});\n\n// Gets a JSON object from `npm ls --json` (getInstalledDependenciesTree) or\n// `npm-shrinkwrap.json` (getShrinkwrappedDependenciesTree).\n//\n// @returns {Object} eg {\n//   \"name\": \"packages\",\n//   \"version\": \"0.0.0\",\n//   \"dependencies\": {\n//     \"sockjs\": {\n//       \"version\": \"0.3.4\",\n//       \"dependencies\": {\n//         \"node-uuid\": {\n//           \"version\": \"1.3.3\"\n//         }\n//       }\n//     }\n//   }\n// }\nfunction getInstalledDependenciesTree(dir) {\n  function ls(nodeModulesDir) {\n    let contents;\n    try {\n      contents = files.readdir(nodeModulesDir).sort();\n    } finally {\n      if (! contents) return;\n    }\n\n    const result = {};\n\n    contents.forEach(item => {\n      if (item.startsWith(\".\")) {\n        return;\n      }\n\n      const pkgDir = files.pathJoin(nodeModulesDir, item);\n      const pkgJsonPath = files.pathJoin(pkgDir, \"package.json\");\n\n      let pkg;\n      try {\n        pkg = JSON.parse(files.readFile(pkgJsonPath));\n      } finally {\n        if (! pkg) return;\n      }\n\n      const info = result[item] = {\n        version: pkg.version\n      };\n\n      const resolved = pkg._resolved || pkg.resolved;\n      if (resolved) {\n        info.resolved = resolved;\n      }\n\n      const from = pkg._from || pkg.from;\n      if (from) {\n        info.from = from;\n      }\n\n      const deps = ls(files.pathJoin(pkgDir, \"node_modules\"));\n      if (deps && ! _.isEmpty(deps)) {\n        info.dependencies = deps;\n      }\n    });\n\n    return result;\n  }\n\n  return {\n    dependencies: ls(files.pathJoin(dir, \"node_modules\"))\n  };\n}\n\nvar getShrinkwrappedDependenciesTree = function (dir) {\n  var shrinkwrapFile = files.readFile(files.pathJoin(dir, 'npm-shrinkwrap.json'));\n  return JSON.parse(shrinkwrapFile);\n};\n\n// Maps a \"dependency object\" (a thing you find in `npm ls --json` or\n// npm-shrinkwrap.json with keys like \"version\" and \"from\") to the\n// canonical version that matches what users put in the `Npm.depends`\n// clause.  ie, either the version or the tarball URL.\n//\n// If more logic is added here, it should probably go in minimizeModule too.\nvar canonicalVersion = function (depObj) {\n  if (utils.isNpmUrl(depObj.from)) {\n    return depObj.from;\n  } else {\n    return depObj.version;\n  }\n};\n\n// map the structure returned from `npm ls` or shrinkwrap.json into\n// the structure of npmDependencies (e.g. {gcd: '0.0.0'}), so that\n// they can be diffed. This only returns top-level dependencies.\nvar treeToDependencies = function (tree) {\n  return _.object(\n    _.map(\n      tree.dependencies, function (properties, name) {\n        return [name, canonicalVersion(properties)];\n      }));\n};\n\nvar getInstalledDependencies = function (dir) {\n  return treeToDependencies(getInstalledDependenciesTree(dir));\n};\n\n// (appears to not be called)\nvar getShrinkwrappedDependencies = function (dir) {\n  return treeToDependencies(getShrinkwrappedDependenciesTree(dir));\n};\n\nvar installNpmModule = function (name, version, dir) {\n  ensureConnected();\n\n  var installArg = utils.isNpmUrl(version)\n    ? version : (name + \"@\" + version);\n\n  // We don't use npm.commands.install since we couldn't figure out\n  // how to silence all output (specifically the installed tree which\n  // is printed out with `console.log`)\n  //\n  // We used to use --force here, because the NPM cache is broken! See\n  // https://github.com/npm/npm/issues/3265 Basically, switching\n  // back and forth between a tarball fork of version X and the real\n  // version X could confuse NPM. But the main reason to use tarball\n  // URLs is to get a fork of the latest version with some fix, so\n  // it was easy to trigger this!\n  //\n  // We now use a forked version of npm with our PR\n  // https://github.com/npm/npm/pull/5137 to work around this.\n  var result = runNpmCommand([\"install\", installArg], dir);\n\n  if (! result.success) {\n    var pkgNotFound = \"404 '\" + utils.quotemeta(name) +\n          \"' is not in the npm registry\";\n    var versionNotFound = \"version not found: \" + utils.quotemeta(name) +\n          '@' + utils.quotemeta(version);\n    if (result.stderr.match(new RegExp(pkgNotFound))) {\n      buildmessage.error(\"there is no npm package named '\" + name + \"'\");\n    } else if (result.stderr.match(new RegExp(versionNotFound))) {\n      buildmessage.error(name + \" version \" + version + \" \" +\n                         \"is not available in the npm registry\");\n    } else {\n      buildmessage.error(`couldn't install npm package ${name}@${version}: ${result.error}`);\n    }\n\n    // Recover by returning false from updateDependencies\n    throw new NpmFailure;\n  }\n\n  const pkgDir = files.pathJoin(dir, \"node_modules\", name);\n  if (! isPortable(pkgDir, true)) {\n    recordLastRebuildVersions(pkgDir);\n  }\n\n  if (process.platform !== \"win32\") {\n    // If we are on a unixy file system, we should not build a package that\n    // can't be used on Windows.\n\n    var pathsWithColons = files.findPathsWithRegex(\".\", new RegExp(\":\"),\n      { cwd: files.pathJoin(dir, \"node_modules\") });\n\n    if (pathsWithColons.length) {\n      var firstTen = pathsWithColons.slice(0, 10);\n      if (pathsWithColons.length > 10) {\n        firstTen.push(\"... \" + (pathsWithColons.length - 10) +\n          \" paths omitted.\");\n      }\n\n      buildmessage.error(\n\"Some filenames in your package have invalid characters.\\n\" +\n\"The following file paths in the NPM module '\" + name + \"' have colons, ':', which won't work on Windows:\\n\" +\nfirstTen.join(\"\\n\"));\n\n      throw new NpmFailure;\n    }\n  }\n};\n\nvar installFromShrinkwrap = function (dir) {\n  if (! files.exists(files.pathJoin(dir, \"npm-shrinkwrap.json\"))) {\n    throw new Error(\n      \"Can't call `npm install` without a npm-shrinkwrap.json file present\");\n  }\n\n  ensureConnected();\n\n  // `npm install`, which reads npm-shrinkwrap.json.\n  var result = runNpmCommand([\"install\"], dir);\n\n  if (! result.success) {\n    buildmessage.error(`couldn't install npm packages from npm-shrinkwrap: ${result.error}`);\n    // Recover by returning false from updateDependencies\n    throw new NpmFailure;\n  }\n\n  const nodeModulesDir = files.pathJoin(dir, \"node_modules\");\n  files.readdir(nodeModulesDir).forEach(function (name) {\n    const pkgDir = files.pathJoin(nodeModulesDir, name);\n    if (! isPortable(pkgDir, true)) {\n      recordLastRebuildVersions(pkgDir);\n    }\n  });\n};\n\n// ensure we can reach http://npmjs.org before we try to install\n// dependencies. `npm install` times out after more than a minute.\nvar ensureConnected = function () {\n  try {\n    httpHelpers.getUrl(process.env.NPM_CONFIG_REGISTRY || \"http://registry.npmjs.org\");\n  } catch (e) {\n    buildmessage.error(\"Can't install npm dependencies. \" +\n                       \"Are you connected to the internet?\");\n    // Recover by returning false from updateDependencies\n    throw new NpmFailure;\n  }\n};\n\n// `npm shrinkwrap`\nfunction shrinkwrap(dir) {\n  const tree = getInstalledDependenciesTree(dir);\n\n  files.writeFile(\n    files.pathJoin(dir, \"npm-shrinkwrap.json\"),\n    JSON.stringify(tree, null, 2) + \"\\n\"\n  );\n\n  return tree;\n}\n\n// Reduces a dependency tree (as read from a just-made npm-shrinkwrap.json or\n// from npm ls --json) to just the versions we want. Returns an object that does\n// not share state with its input\nvar minimizeDependencyTree = function (tree) {\n  var minimizeModule = function (module) {\n    var version;\n    if (module.resolved &&\n        !module.resolved.match(/^https?:\\/\\/registry.npmjs.org\\//)) {\n      version = module.resolved;\n    } else if (utils.isNpmUrl(module.from)) {\n      version = module.from;\n    } else {\n      version = module.version;\n    }\n    var minimized = {version: version};\n\n    if (module.dependencies) {\n      minimized.dependencies = {};\n      _.each(module.dependencies, function (subModule, name) {\n        minimized.dependencies[name] = minimizeModule(subModule);\n      });\n    }\n    return minimized;\n  };\n\n  var newTopLevelDependencies = {};\n  _.each(tree.dependencies, function (module, name) {\n    newTopLevelDependencies[name] = minimizeModule(module);\n  });\n  return {dependencies: newTopLevelDependencies};\n};\n\nvar logUpdateDependencies = function (packageName, npmDependencies) {\n  runLog.log(packageName + ': updating npm dependencies -- ' +\n             _.keys(npmDependencies).join(', ') + '...');\n};\n"
  },
  {
    "path": "tools/isobuild/minifier-plugin.js",
    "content": "import buildmessage from '../utils/buildmessage.js';\nconst buildPluginModule = require('./build-plugin.js');\n\nclass InputFile extends buildPluginModule.InputFile {\n  constructor(source, options = {}) {\n    super();\n\n    this._source = source;\n    this._arch = options.arch;\n    this._minifiedFiles = [];\n  }\n\n  getContentsAsBuffer() {\n    return this._source.contents();\n  }\n  getPathInPackage() {\n    throw new Error(\"Compiled files don't belong to any package\");\n  }\n  getPackageName() {\n    throw new Error(\"Compiled files don't belong to any package\");\n  }\n  getSourceHash() {\n    return this._source.hash();\n  }\n  getArch() {\n    return this._arch;\n  }\n\n  error({message, sourcePath, line, column, func}) {\n    const relPath = this.getPathInBundle();\n    buildmessage.error(message || ('error minifying ' + relPath), {\n      file: sourcePath || relPath,\n      line: line ? line : undefined,\n      column: column ? column : undefined,\n      func: func ? func : undefined\n    });\n  }\n\n  /**\n   * @summary Returns the path of the compiled file in the bundle.\n   * @memberof InputFile\n   * @returns {String}\n   */\n  getPathInBundle() {\n    return this._source.targetPath;\n  }\n\n  /**\n   * @summary Returns the source-map associated with the file.\n   * @memberof InputFile\n   * @returns {String}\n   */\n  getSourceMap() {\n    return this._source.sourceMap;\n  }\n}\n\nexport class JsFile extends InputFile {\n  // - data\n  // - sourceMap\n  // - path\n  // - hash?\n  addJavaScript(options) {\n    const self = this;\n    self._minifiedFiles.push({\n      data: options.data,\n      sourceMap: options.sourceMap,\n      path: options.path\n    });\n  }\n}\n\nexport class CssFile extends InputFile {\n  // - data\n  // - sourceMap\n  // - path\n  // - hash?\n  addStylesheet(options) {\n    this._minifiedFiles.push({\n      data: options.data,\n      sourceMap: options.sourceMap,\n      path: options.path\n    });\n  }\n}\n\n"
  },
  {
    "path": "tools/isobuild/npm-discards.js",
    "content": "var assert = require(\"assert\");\nvar files = require('../fs/files.js');\nvar _ = require(\"underscore\");\n\n// This class encapsulates a structured specification of files and\n// directories that should be stripped from the node_modules directories\n// of Meteor packages during `meteor build`, as requested by calling\n// `Npm.discard` in package.js files.\nfunction NpmDiscards() {\n  assert.ok(this instanceof NpmDiscards);\n  this.discards = {};\n}\n\nvar NDp = NpmDiscards.prototype;\n\n// Update the current specification of discarded files with additional\n// patterns that should be discarded. See the comment in package-source.js\n// about `Npm.strip` for an explanation of what should be passed for the\n// `discards` parameter.\nNDp.merge = function(discards) {\n  merge(this.discards, discards);\n};\n\nfunction merge(into, from) {\n  _.each(from, function(fromValue, packageName) {\n    var intoValue = _.has(into, packageName) && into[packageName];\n    if (_.isString(fromValue) ||\n        _.isRegExp(fromValue)) {\n      if (intoValue) {\n        intoValue.push(fromValue);\n      } else {\n        into[packageName] = [fromValue];\n      }\n    } else if (_.isArray(fromValue)) {\n      if (intoValue) {\n        intoValue.push.apply(intoValue, fromValue);\n      } else {\n        // Make a defensive copy of any arrays passed to `Npm.strip`.\n        into[packageName] = fromValue.slice(0);\n      }\n    }\n  });\n}\n\nNDp.shouldDiscard = function shouldDiscard(candidatePath, isDirectory) {\n  if (typeof isDirectory === \"undefined\") {\n    isDirectory = files.lstat(candidatePath).isDirectory();\n  }\n\n  for (var currentPath = candidatePath, parentPath;\n       (parentPath = files.pathDirname(currentPath)) !== currentPath;\n       currentPath = parentPath) {\n    if (files.pathBasename(parentPath) === \"node_modules\") {\n      var packageName = files.pathBasename(currentPath);\n\n      if (_.has(this.discards, packageName)) {\n        var relPath = files.pathRelative(currentPath, candidatePath);\n\n        if (isDirectory) {\n          relPath = files.pathJoin(relPath, files.pathSep);\n        }\n\n        return this.discards[packageName].some(function(pattern) {\n          return matches(pattern, relPath);\n        });\n      }\n\n      // Stop at the first ancestor node_modules directory we find.\n      break;\n    }\n  }\n\n  return false;\n};\n\n// TODO Improve this. For example we don't currently support wildcard\n// string patterns (just use a RegExp if you need that flexibility).\nfunction matches(pattern, relPath) {\n  if (_.isRegExp(pattern)) {\n    return relPath.match(pattern);\n  }\n\n  assert.ok(_.isString(pattern));\n\n  if (pattern.charAt(0) === files.pathSep) {\n    return relPath.indexOf(pattern.slice(1)) === 0;\n  }\n\n  return relPath.indexOf(pattern) !== -1;\n}\n\nmodule.exports = NpmDiscards;\n"
  },
  {
    "path": "tools/isobuild/package-api.js",
    "content": "var assert = require(\"assert\");\nvar _ = require(\"underscore\");\nvar buildmessage = require('../utils/buildmessage.js');\nvar utils = require('../utils/utils.js');\nvar compiler = require('./compiler.js');\nvar archinfo = require('../utils/archinfo.js');\nvar files = require('../fs/files.js');\nvar catalog = require('../packaging/catalog/catalog.js');\n\nfunction toArray (x) {\n  if (_.isArray(x)) {\n    return x;\n  }\n  return x ? [x] : [];\n}\n\nfunction toArchArray (arch) {\n  if (! _.isArray(arch)) {\n    arch = arch ? [arch] : compiler.ALL_ARCHES;\n  }\n  arch = _.uniq(arch);\n  arch = _.map(arch, mapWhereToArch);\n\n  // avoid using _.each so as to not add more frames to skip\n  for (var i = 0; i < arch.length; ++i) {\n    var inputArch = arch[i];\n    var isMatch = _.any(_.map(compiler.ALL_ARCHES, function (actualArch) {\n      return archinfo.matches(actualArch, inputArch);\n    }));\n    if (! isMatch) {\n      buildmessage.error(\n        \"Invalid 'where' argument: '\" + inputArch + \"'\",\n        // skip toArchArray in addition to the actual API function\n        {useMyCaller: 1});\n    }\n  }\n  return arch;\n}\n\n// We currently have a 1 to 1 mapping between 'where' and 'arch'.\n// 'client' -> 'web'\n// 'server' -> 'os'\n// '*' -> '*'\nfunction mapWhereToArch (where) {\n  if (where === 'server') {\n    return 'os';\n  } else if (where === 'client') {\n    return 'web';\n  } else {\n    return where;\n  }\n}\n\n// Iterates over the list of target archs and calls f(arch) for all archs\n// that match an element of self.allarchs.\nfunction forAllMatchingArchs (archs, f) {\n  _.each(archs, function (arch) {\n    _.each(compiler.ALL_ARCHES, function (matchArch) {\n      if (archinfo.matches(matchArch, arch)) {\n        f(matchArch);\n      }\n    });\n  });\n}\n\n/**\n * @name  PackageAPI\n * @class PackageAPI\n * @instanceName api\n * @global\n * @summary Type of the API object passed into the `Package.onUse` function.\n */\nfunction PackageAPI (options) {\n  var self = this;\n  assert.ok(self instanceof PackageAPI);\n\n  options = options || {};\n\n  self.buildingIsopackets = !!options.buildingIsopackets;\n\n  // source files used.\n  // It's a multi-level map structured as:\n  //   arch -> sources|assets -> relPath -> {relPath, fileOptions}\n  self.files = {};\n\n  // symbols exported\n  self.exports = {};\n\n  // packages used and implied (keys are 'package', 'unordered', and\n  // 'weak').  an \"implied\" package is a package that will be used by a unibuild\n  // which uses us.\n  self.uses = {};\n  self.implies = {};\n\n  _.each(compiler.ALL_ARCHES, function (arch) {\n    self.files[arch] = {\n      assets: [],\n      sources: [],\n      main: null,\n    };\n\n    self.exports[arch] = [];\n    self.uses[arch] = [];\n    self.implies[arch] = [];\n  });\n\n  self.releaseRecords = [];\n}\n\n_.extend(PackageAPI.prototype, {\n  // Called when this package wants to make another package be\n  // used. Can also take literal package objects, if you have\n  // anonymous packages you want to use (eg, app packages)\n  //\n  // @param arch 'web', 'web.browser', 'web.cordova', 'server',\n  // or an array of those.\n  // The default is ['web', 'server'].\n  //\n  // options can include:\n  //\n  // - unordered: if true, don't require this package to load\n  //   before us -- just require it to be loaded anytime. Also\n  //   don't bring this package's imports into our\n  //   namespace. If false, override a true value specified in\n  //   a previous call to use for this package name. (A\n  //   limitation of the current implementation is that this\n  //   flag is not tracked per-environment or per-role.)  This\n  //   option can be used to resolve circular dependencies in\n  //   exceptional circumstances, eg, the 'meteor' package\n  //   depends on 'handlebars', but all packages (including\n  //   'handlebars') have an implicit dependency on\n  //   'meteor'. Internal use only -- future support of this\n  //   is not guaranteed. #UnorderedPackageReferences\n  //\n  // - weak: if true, don't require this package to load at all, but if\n  //   it's going to load, load it before us.  Don't bring this\n  //   package's imports into our namespace and don't allow us to use\n  //   its plugins. (Has the same limitation as \"unordered\" that this\n  //   flag is not tracked per-environment or per-role; this may\n  //   change.)\n\n  /**\n   * @memberOf PackageAPI\n   * @instance\n   * @summary Depend on package `packagename`.\n   * @locus package.js\n   * @param {String|String[]} packageNames Packages being depended on.\n   * Package names may be suffixed with an @version tag.\n   *\n   * In general, you must specify a package's version (e.g.,\n   * `'accounts@1.0.0'` to use version 1.0.0 or a higher\n   * compatible version (ex: 1.0.1, 1.5.0, etc.)  of the\n   * `accounts` package). If you are sourcing core\n   * packages from a Meteor release with `versionsFrom`, you may leave\n   * off version names for core packages. You may also specify constraints,\n   * such as `my:forms@=1.0.0` (this package demands `my:forms` at `1.0.0` exactly),\n   * or `my:forms@1.0.0 || =2.0.1` (`my:forms` at `1.x.y`, or exactly `2.0.1`).\n   * @param {String|String[]} [architecture] If you only use the package on the\n   * server (or the client), you can pass in the second argument (e.g.,\n   * `'server'`, `'client'`, `'web.browser'`, `'web.cordova'`) to specify\n   * what architecture the package is used with. You can specify multiple\n   * architectures by passing in an array, for example `['web.cordova', 'os.linux']`.\n   * @param {Object} [options]\n   * @param {Boolean} options.weak Establish a weak dependency on a\n   * package. If package A has a weak dependency on package B, it means\n   * that including A in an app does not force B to be included too — but,\n   * if B is included or by another package, then B will load before A.\n   * You can use this to make packages that optionally integrate with or\n   * enhance other packages if those packages are present.\n   * When you weakly depend on a package you don't see its exports.\n   * You can detect if the possibly-present weakly-depended-on package\n   * is there by seeing if `Package.foo` exists, and get its exports\n   * from the same place.\n   * @param {Boolean} options.unordered It's okay to load this dependency\n   * after your package. (In general, dependencies specified by `api.use`\n   * are loaded before your package.) You can use this option to break\n   * circular dependencies.\n   */\n  use: function (names, arch, options) {\n    var self = this;\n\n    // Support `api.use(package, {weak: true})` without arch.\n    if (_.isObject(arch) && !_.isArray(arch) && !options) {\n      options = arch;\n      arch = null;\n    }\n    options = options || {};\n\n    names = toArray(names);\n    arch = toArchArray(arch);\n\n    // A normal dependency creates an ordering constraint and a \"if I'm\n    // used, use that\" constraint. Unordered dependencies lack the\n    // former; weak dependencies lack the latter. There's no point to a\n    // dependency that lacks both!\n    if (options.unordered && options.weak) {\n      buildmessage.error(\n        \"A dependency may not be both unordered and weak.\",\n        { useMyCaller: true });\n      // recover by ignoring\n      return;\n    }\n\n    // using for loop rather than underscore to help with useMyCaller\n    for (var i = 0; i < names.length; ++i) {\n      var name = names[i];\n      try {\n        var parsed = utils.parsePackageConstraint(name);\n      } catch (e) {\n        if (!e.versionParserError) {\n          throw e;\n        }\n        buildmessage.error(e.message, {useMyCaller: true});\n        // recover by ignoring\n        continue;\n      }\n\n      forAllMatchingArchs(arch, function (a) {\n        self.uses[a].push({\n          package: parsed.package,\n          constraint: parsed.constraintString,\n          unordered: options.unordered || false,\n          weak: options.weak || false\n        });\n      });\n    }\n  },\n\n  // Called when this package wants packages using it to also use\n  // another package.  eg, for umbrella packages which want packages\n  // using them to also get symbols or plugins from their components.\n\n  /**\n   *\n   * @memberOf PackageAPI\n   * @summary Give users of this package access to another package (by passing\n   * in the string `packagename`) or a collection of packages (by passing in\n   * an array of strings [`packagename1`, `packagename2`]\n   * @locus package.js\n   * @instance\n   * @param {String|String[]} packageNames Name of a package, or array of\n   * package names, with an optional @version component for each.\n   * @param {String|String[]} [architecture] If you only use the package on\n   * the server (or the client), you can pass in the second argument (e.g.,\n   * `'server'`, `'client'`, `'web.browser'`, `'web.cordova'`) to specify what\n   * architecture the package is used with. You can specify multiple\n   * architectures by passing in an array, for example `['web.cordova',\n   * 'os.linux']`.\n   */\n  imply: function (names, arch) {\n    var self = this;\n\n    // We currently disallow build plugins in\n    // debugOnly/prodOnly/testOnly packages; but if you could use\n    // imply in a debugOnly package, you could pull in the build\n    // plugin from an implied package, which would have the same\n    // problem as allowing build plugins directly in the package. So\n    // no imply either!\n    if (self.debugOnly || self.prodOnly || self.testOnly) {\n      buildmessage.error(\"can't use imply in packages that are debugOnly, prodOnly or testOnly\");\n      // recover by ignoring\n      return;\n    }\n\n    names = toArray(names);\n    arch = toArchArray(arch);\n\n    // using for loop rather than underscore to help with useMyCaller\n    for (var i = 0; i < names.length; ++i) {\n      var name = names[i];\n      try {\n        var parsed = utils.parsePackageConstraint(name);\n      } catch (e) {\n        if (!e.versionParserError) {\n          throw e;\n        }\n        buildmessage.error(e.message, {useMyCaller: true});\n        // recover by ignoring\n        continue;\n      }\n\n      // api.imply('isobuild:compiler-plugin') doesn't really make any sense. If\n      // we change our mind and think it makes sense, we can always implement it\n      // later...\n      if (compiler.isIsobuildFeaturePackage(parsed.package)) {\n        buildmessage.error(\n          `to declare that your package requires the build tool feature ` +\n            `'{parsed.package}', use 'api.use', not 'api.imply'`);\n        // recover by ignoring\n        continue;\n      }\n\n      forAllMatchingArchs(arch, function (a) {\n        // We don't allow weak or unordered implies, since the main\n        // purpose of imply is to provide imports and plugins.\n        self.implies[a].push({\n          package: parsed.package,\n          constraint: parsed.constraintString\n        });\n      });\n    }\n  },\n\n  // Top-level call to add a source file to a package. It will\n  // be processed according to its extension (eg, *.coffee\n  // files will be compiled to JavaScript).\n\n  /**\n   * @memberOf PackageAPI\n   * @instance\n   * @summary Specify source code files for your package.\n   * @locus package.js\n   * @param {String|String[]} filenames Paths to the source files.\n   * @param {String|String[]} [architecture] If you only want to use the file\n   * on the server (or the client), you can pass this argument\n   * (e.g., 'server', 'client', 'web.browser', 'web.cordova') to specify\n   * what architecture the file is used with. You can specify multiple\n   * architectures by passing in an array, for example\n   * `['web.cordova', 'os.linux']`. By default, the file will be loaded on both\n   * server and client.\n   * @param {Object} [options] Options that will be passed to build\n   * plugins.\n   * @param {Boolean} [options.bare] If this file is JavaScript code or will\n   * be compiled into JavaScript code by a build plugin, don't wrap the\n   * resulting file in a closure. Has the same effect as putting a file into the\n   * `client/compatibility` directory in an app.\n   */\n  addFiles: function (paths, arch, fileOptions) {\n    if (fileOptions && fileOptions.isAsset) {\n      // XXX it would be great to print a warning here, see the issue:\n      // https://github.com/meteor/meteor/issues/5495\n      this._addFiles(\"assets\", paths, arch);\n      return;\n    }\n\n    // Watch out - we rely on the levels of stack traces inside this\n    // function so don't wrap it in another function without changing that logic\n    this._addFiles(\"sources\", paths, arch, fileOptions);\n  },\n\n  mainModule(path, arch) {\n    arch = toArchArray(arch);\n    forAllMatchingArchs(arch, a => {\n      const filesForArch = this.files[a];\n      const source = {\n        relPath: files.pathRelative(\".\", path),\n        fileOptions: {\n          mainModule: true\n        }\n      };\n\n      const oldMain = filesForArch.main;\n      if (oldMain) {\n        // It's not an error to call api.mainModule multiple times, but\n        // the last call takes precedence over the earlier calls.\n        oldMain.fileOptions.mainModule = false;\n      }\n\n      filesForArch.main = source;\n      filesForArch.sources.push(source);\n    });\n  },\n\n  /**\n   * @memberOf PackageAPI\n   * @instance\n   * @summary Specify asset files for your package. They can be accessed via\n   * the [Assets API](#assets) from the server, or at the URL\n   * `/packages/username_package-name/file-name` from the client, depending on the\n   * architecture passed.\n   * @locus package.js\n   * @param {String|String[]} filenames Paths to the asset files.\n   * @param {String|String[]} architecture Specify where this asset should be\n   * available (e.g., 'server', 'client', 'web.browser', 'web.cordova'). You can\n   * specify multiple architectures by passing in an array, for example\n   * `['web.cordova', 'os.linux']`.\n   */\n  addAssets(paths, arch) {\n    if(!arch) {\n      buildmessage.error('addAssets requires a second argument specifying ' +\n        'where the asset should be available. For example: \"client\", ' +\n        '\"server\", or [\"client\", \"server\"].', { useMyCaller: true });\n      return;\n    }\n\n    // Watch out - we rely on the levels of stack traces inside this\n    // function so don't wrap it in another function without changing that logic\n    this._addFiles(\"assets\", paths, arch);\n  },\n\n  /**\n   * Internal method used by addFiles and addAssets.\n   */\n  _addFiles(type, paths, arch, fileOptions) {\n    if (type !== \"sources\" && type !== \"assets\") {\n      throw new Error(`Can only handle sources and assets, not '${type}'.`);\n    }\n\n    var self = this;\n\n    paths = toArray(paths);\n    arch = toArchArray(arch);\n\n    // Convert Dos-style paths to Unix-style paths.\n    // XXX it is possible to convert an already Unix-style path by mistake\n    // and break it. e.g.: 'some\\folder/anotherFolder' is a valid path\n    // consisting of two components. #WindowsPathApi\n    paths = _.map(paths, function (p) {\n      // Normalize ./foo.js to foo.js.\n      p = files.pathRelative(\".\", p);\n\n      if (p.indexOf('/') !== -1) {\n        // it is already a Unix-style path most likely\n        return p;\n      }\n\n      return files.convertToPosixPath(p, true);\n    });\n\n    var errors = [];\n    _.each(paths, function (path) {\n      forAllMatchingArchs(arch, function (a) {\n        const filesOfType = self.files[a][type];\n\n        // Check if we have already added a file at this path\n        if (_.has(filesOfType, path)) {\n          // We want the singular form of the file type\n          const typeName = {\n            sources: 'source',\n            assets: 'asset'\n          }[type];\n\n          errors.push(`Duplicate ${typeName} file: ${path}`);\n          return;\n        }\n\n        const source = {\n          relPath: path\n        };\n\n        if (fileOptions) {\n          source.fileOptions = fileOptions;\n        }\n\n        filesOfType.push(source);\n      });\n    });\n\n    // Spit out all the errors at the end, where the number of stack frames to\n    // skip is just 2 (this function and its callers) instead of something like\n    // 7 from forAllMatchingArchs and _.each.  Avoid using _.each here to keep\n    // stack predictable.\n    for (var i = 0; i < errors.length; ++i) {\n      buildmessage.error(errors[i], { useMyCaller: 1 });\n    }\n  },\n\n  // Use this release to resolve unclear dependencies for this package. If\n  // you don't fill in dependencies for some of your implies/uses, we will\n  // look at the packages listed in the release to figure that out.\n\n  /**\n   * @memberOf PackageAPI\n   * @instance\n   * @summary Use versions of core packages from a release. Unless provided,\n   * all packages will default to the versions released along with\n   * `meteorRelease`. This will save you from having to figure out the exact\n   * versions of the core packages you want to use. For example, if the newest\n   * release of meteor is `METEOR@0.9.0` and it includes `jquery@1.0.0`, you\n   * can write `api.versionsFrom('METEOR@0.9.0')` in your package, and when you\n   * later write `api.use('jquery')`, it will be equivalent to\n   * `api.use('jquery@1.0.0')`. You may specify an array of multiple releases,\n   * in which case the default value for constraints will be the \"or\" of the\n   * versions from each release: `api.versionsFrom(['METEOR@0.9.0',\n   * 'METEOR@0.9.5'])` may cause `api.use('jquery')` to be interpreted as\n   * `api.use('jquery@1.0.0 || 2.0.0')`.\n   * @locus package.js\n   * @param {String | String[]} meteorRelease Specification of a release:\n   * track@version. Just 'version' (e.g. `\"0.9.0\"`) is sufficient if using the\n   * default release track `METEOR`. Can be an array of specifications.\n   */\n  versionsFrom: function (releases) {\n    var self = this;\n\n    // Packages in isopackets really ought to be in the core release, by\n    // definition, so saying that they should use versions from another\n    // release doesn't make sense. Moreover, if we're running from a\n    // checkout, we build isopackets before we initialize catalog.official\n    // (since we may need the ddp isopacket to refresh catalog.official),\n    // so we wouldn't actually be able to interpret the release name\n    // anyway.\n    if (self.buildingIsopackets) {\n      buildmessage.error(\n        \"packages in isopackets may not use versionsFrom\");\n      // recover by ignoring\n      return;\n    }\n\n    releases = toArray(releases);\n\n    // using for loop rather than underscore to help with useMyCaller\n    for (var i = 0; i < releases.length; ++i) {\n      var release = releases[i];\n\n      // If you don't specify a track, use our default.\n      if (release.indexOf('@') === -1) {\n        release = catalog.DEFAULT_TRACK + \"@\" + release;\n      }\n\n      var relInf = release.split('@');\n      if (relInf.length !== 2) {\n        buildmessage.error(\"Release names in versionsFrom may not contain '@'.\",\n                           { useMyCaller: true });\n        return;\n      }\n      var releaseRecord = catalog.official.getReleaseVersion(\n        relInf[0], relInf[1]);\n      if (!releaseRecord) {\n        buildmessage.error(\"Unknown release \"+ release,\n                           { tags: { refreshCouldHelp: true } });\n      } else {\n        self.releaseRecords.push(releaseRecord);\n      }\n    }\n  },\n\n  // Export symbols from this package.\n  //\n  // @param symbols String (eg \"Foo\") or array of String\n  // @param arch 'web', 'server', 'web.browser', 'web.cordova'\n  // or an array of those.\n  // The default is ['web', 'server'].\n  // @param options 'testOnly', boolean.\n\n  /**\n   *\n   * @memberOf PackageAPI\n   * @instance\n   * @summary Export package-level variables in your package. The specified\n   * variables (declared without `var` in the source code) will be available\n   * to packages that use your package. If your package sets the `debugOnly`,\n   * `prodOnly` or `testOnly` options to `true` when it calls\n   * `Package.describe()`, then packages that use your package will need to use\n   * `Package[\"package-name\"].ExportedVariableName` to access the value of an\n   * exported variable.\n   * @locus package.js\n   * @param {String|String[]} exportedObjects Name of the object to export, or\n   * an array of object names.\n   * @param {String|String[]} [architecture] If you only want to export the\n   * object on the server (or the client), you can pass in the second argument\n   * (e.g., 'server', 'client', 'web.browser', 'web.cordova') to specify what\n   * architecture the export is used with. You can specify multiple\n   * architectures by passing in an array, for example `['web.cordova',\n   * 'os.linux']`.\n   * @param {Object} [exportOptions]\n   * @param {Boolean} exportOptions.testOnly If true, this symbol will only be\n   * exported when running tests for this package.\n   */\n  export: function (symbols, arch, options) {\n    var self = this;\n\n    // Support `api.export(\"FooTest\", {testOnly: true})` without\n    // arch.\n    if (_.isObject(arch) && !_.isArray(arch) && !options) {\n      options = arch;\n      arch = null;\n    }\n    options = options || {};\n\n    symbols = toArray(symbols);\n    arch = toArchArray(arch);\n\n    _.each(symbols, function (symbol) {\n      // XXX be unicode-friendlier\n      if (!symbol.match(/^([_$a-zA-Z][_$a-zA-Z0-9]*)$/)) {\n        buildmessage.error(\"Bad exported symbol: \" + symbol,\n                           { useMyCaller: true });\n        // recover by ignoring\n        return;\n      }\n      forAllMatchingArchs(arch, function (w) {\n        self.exports[w].push({name: symbol, testOnly: !!options.testOnly});\n      });\n    });\n  }\n});\n\n// XXX COMPAT WITH 0.8.x\nPackageAPI.prototype.add_files = PackageAPI.prototype.addFiles;\n\nexports.PackageAPI = PackageAPI;\n"
  },
  {
    "path": "tools/isobuild/package-source.js",
    "content": "var _ = require('underscore');\nvar sourcemap = require('source-map');\n\nvar files = require('../fs/files.js');\nvar utils = require('../utils/utils.js');\nvar watch = require('../fs/watch.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar meteorNpm = require('./meteor-npm.js');\nvar NpmDiscards = require('./npm-discards.js');\nimport Builder from './builder.js';\nvar archinfo = require('../utils/archinfo.js');\nvar catalog = require('../packaging/catalog/catalog.js');\nvar packageVersionParser = require('../packaging/package-version-parser.js');\nvar compiler = require('./compiler.js');\nvar packageAPIModule = require('./package-api.js');\nvar Profile = require('../tool-env/profile.js').Profile;\n\nimport SourceArch from './source-arch.js';\n\nimport {\n  TEST_FILENAME_REGEXPS,\n  APP_TEST_FILENAME_REGEXPS,\n  isTestFilePath } from './test-files.js';\n\n// XXX: This is a medium-term hack, to avoid having the user set a package name\n// & test-name in package.describe. We will change this in the new control file\n// world in some way.\nvar AUTO_TEST_PREFIX = \"local-test:\";\nvar isTestName = function (name) {\n  var nameStart = name.slice(0, AUTO_TEST_PREFIX.length);\n  return nameStart === AUTO_TEST_PREFIX;\n};\nvar genTestName = function (name) {\n  return AUTO_TEST_PREFIX + name;\n};\n\n// Returns a sort comparator to order files into load order.\nvar loadOrderSort = function (sourceProcessorSet, arch) {\n  const isTemplate = _.memoize((filename) => {\n    const classification = sourceProcessorSet.classifyFilename(filename, arch);\n    switch (classification.type) {\n    case 'extension':\n    case 'filename':\n      if (! classification.sourceProcessors) {\n        // This is *.js, not a template. #HardcodeJs\n        return false;\n      }\n      if (classification.sourceProcessors.length > 1) {\n        throw Error(\"conflicts in compiler?\");\n      }\n      return classification.sourceProcessors[0].isTemplate;\n\n    case 'legacy-handler':\n      return classification.legacyIsTemplate;\n\n    case 'wrong-arch':\n    case 'unmatched':\n      return false;\n\n    default:\n      throw Error(`surprising type ${classification.type} for ${filename}`);\n    }\n  });\n\n  return function (a, b) {\n    // XXX MODERATELY SIZED HACK --\n    // push template files ahead of everything else. this is\n    // important because the user wants to be able to say\n    //   Template.foo.events = { ... }\n    // in a JS file and not have to worry about ordering it\n    // before the corresponding .html file.\n    //\n    // maybe all of the templates should go in one file?\n    var isTemplate_a = isTemplate(files.pathBasename(a));\n    var isTemplate_b = isTemplate(files.pathBasename(b));\n    if (isTemplate_a !== isTemplate_b) {\n      return (isTemplate_a ? -1 : 1);\n    }\n\n    // main.* loaded last\n    var ismain_a = (files.pathBasename(a).indexOf('main.') === 0);\n    var ismain_b = (files.pathBasename(b).indexOf('main.') === 0);\n    if (ismain_a !== ismain_b) {\n      return (ismain_a ? 1 : -1);\n    }\n\n    // /lib/ loaded first\n    var islib_a = (a.indexOf(files.pathSep + 'lib' + files.pathSep) !== -1 ||\n                   a.indexOf('lib' + files.pathSep) === 0);\n    var islib_b = (b.indexOf(files.pathSep + 'lib' + files.pathSep) !== -1 ||\n                   b.indexOf('lib' + files.pathSep) === 0);\n    if (islib_a !== islib_b) {\n      return (islib_a ? -1 : 1);\n    }\n\n    var a_parts = a.split(files.pathSep);\n    var b_parts = b.split(files.pathSep);\n\n    // deeper paths loaded first.\n    var len_a = a_parts.length;\n    var len_b = b_parts.length;\n    if (len_a < len_b) {\n      return 1;\n    }\n    if (len_b < len_a) {\n      return -1;\n    }\n\n    // Otherwise compare path components lexicographically.\n    for (var i = 0; i < len_a; ++i) {\n      var a_part = a_parts[i];\n      var b_part = b_parts[i];\n      if (a_part < b_part) {\n        return -1;\n      }\n      if (b_part < a_part) {\n        return 1;\n      }\n    }\n\n    // Never reached unless there are somehow duplicate paths.\n    return 0;\n  };\n};\n\nvar splitConstraint = function (c) {\n  // XXX print error better (w/ buildmessage?)?\n  var parsed = utils.parsePackageConstraint(c);\n  return { package: parsed.package,\n           constraint: parsed.constraintString || null };\n};\n\n// Given the text of a README.md file, excerpts the text between the first and\n// second heading.\n//\n// Specifically - if there is text between the document name, and the first\n// subheading, it will take that text. If there is no text there, and only text\n// after the first subheading, it will take that text. It won't look any deeper\n// than that (in case the user intentionally wants to leave the section blank\n// for some reason). Skips lines that start with an exclamation point.\nvar getExcerptFromReadme = function (text) {\n  // Don't waste time parsing if the document is empty.\n  if (! text) {\n    return \"\";\n  }\n\n  // Split into lines with Commonmark.\n  var commonmark = require('commonmark');\n  var reader = new commonmark.DocParser();\n  var parsed = reader.parse(text);\n\n  // Commonmark will parse the Markdown into an array of nodes. These are the\n  // nodes that represent the text between the first and second heading.\n  var relevantNodes = [];\n\n  // Go through the document until we get the nodes that we are looking for,\n  // then stop.\n  _.any(parsed.children, function (child) {\n    var isHeader = (child.t === \"Header\");\n    // Don't excerpt anything before the first header.\n    if (! isHeader) {\n      // If we are currently in the middle of excerpting, continue doing that\n      // until we hit hit a header (and this is not a header). Otherwise, if\n      // this is text, we should begin to excerpt it.\n      relevantNodes.push(child);\n    } else if (! _.isEmpty(relevantNodes) && isHeader) {\n      // We have been excerpting, and came across a header. That means\n      // that we are done.\n      return true;\n    }\n    return false;\n  });\n\n  // If we have not found anything, we are done.\n  if (_.isEmpty(relevantNodes)) {\n    return \"\";\n  }\n\n  // For now, we will do the simple thing of just taking the raw markdown from\n  // the start of the excerpt to the end.\n  var textLines = text.split(\"\\n\");\n  var start = relevantNodes[0].start_line - 1;\n  var stop = _.last(relevantNodes).end_line;\n  // XXX: There is a bug in commonmark that happens when processing the last\n  // node in the document. Here is the github issue:\n  // https://github.com/jgm/CommonMark/issues/276\n  // Remove this workaround when the issue is fixed.\n  if (stop === _.last(parsed.children).end_line) {\n    stop++;\n  }\n  var excerpt = textLines.slice(start, stop).join(\"\\n\");\n\n  // Strip the preceeding and trailing new lines.\n  return excerpt.replace(/^\\n+|\\n+$/g, \"\");\n};\n\nclass SymlinkLoopChecker {\n  constructor(sourceRoot) {\n    this.sourceRoot = sourceRoot;\n    this._seenPaths = {};\n    this._realpathCache = {};\n  }\n\n  check(relDir, quietly = true) {\n    const absPath = files.pathJoin(this.sourceRoot, relDir);\n\n    try {\n      var realPath = files.realpath(absPath, this._realpathCache);\n    } catch (e) {\n      if (!e || e.code !== 'ELOOP') {\n        throw e;\n      }\n      // else leave realPath undefined\n    }\n\n    if (! realPath || _.has(this._seenPaths, realPath)) {\n      if (! quietly) {\n        buildmessage.error(\"Symlink cycle detected at \" + relDir);\n      }\n\n      return true;\n    }\n\n    this._seenPaths[realPath] = true;\n\n    return false;\n  }\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// PackageSource\n///////////////////////////////////////////////////////////////////////////////\n\nvar PackageSource = function () {\n  var self = this;\n\n  // The name of the package, or null for an app pseudo-package or\n  // collection. The package's exports will reside in Package.<name>.\n  // When it is null it is linked like an application instead of like\n  // a package.\n  self.name = null;\n\n  // The path relative to which all source file paths are interpreted\n  // in this package. Also used to compute the location of the\n  // package's .npm directory (npm shrinkwrap state).\n  self.sourceRoot = null;\n\n  // Path that will be prepended to the URLs of all resources emitted\n  // by this package (assuming they don't end up getting\n  // concatenated). For non-web targets, the only effect this will\n  // have is to change the actual on-disk paths of the files in the\n  // bundle, for those that care to open up the bundle and look (but\n  // it's still nice to get it right).\n  self.serveRoot = null;\n\n  // Package metadata. Keys are 'summary', 'git' and 'documentation'. Currently\n  // all of these are optional.\n  self.metadata = {};\n  self.docsExplicitlyProvided = false;\n\n  // Package version as a meteor-version string. Optional; not all packages\n  // (for example, the app) have versions.\n  // XXX when we have names, maybe we want to say that all packages\n  // with names have versions? certainly the reverse is true\n  self.version = null;\n  self.versionExplicitlyProvided = false;\n\n  // Available architectures of this package. Array of SourceArch.\n  self.architectures = [];\n\n  // The information necessary to build the plugins in this\n  // package. Map from plugin name to object with keys 'name', 'use',\n  // 'sources', and 'npmDependencies'.\n  self.pluginInfo = {};\n\n  // Analogous to watchSet in SourceArch but for plugins. At this\n  // stage will typically contain just 'package.js'.\n  self.pluginWatchSet = new watch.WatchSet;\n\n  // npm packages used by this package (on os.* architectures only).\n  // Map from npm package name to the required version of the package\n  // as a string.\n  self.npmDependencies = {};\n\n  // Files to be stripped from the installed NPM dependency tree. See the\n  // Npm.strip comment below for further usage information.\n  self.npmDiscards = new NpmDiscards;\n\n  // Absolute path to a directory on disk that serves as a cache for\n  // the npm dependencies, so we don't have to fetch them on every\n  // build. Required not just if we have npmDependencies, but if we\n  // ever could have had them in the past.\n  self.npmCacheDirectory = null;\n\n  // cordova plugins used by this package (on os.* architectures only).\n  // Map from cordova plugin name to the required version of the package\n  // as a string.\n  self.cordovaDependencies = {};\n\n  // If this package has a corresponding test package (for example,\n  // underscore-test), defined in the same package.js file, store its value\n  // here.\n  self.testName = null;\n\n  // Test packages are dealt with differently in the linker (and not published\n  // to the catalog), so we need to keep track of them.\n  self.isTest = false;\n\n  // Some packages belong to a test framework and should never be bundled into\n  // production. A package with this flag should not be picked up by the bundler\n  // for production builds.\n  self.debugOnly = false;\n\n  // A package marked prodOnly is ONLY picked up by the bundler for production\n  // builds.\n  self.prodOnly = false;\n\n  // A package marked testOnly is ONLY picked up by the bundler as\n  // part of the `meteor test` command.\n  self.testOnly = false;\n\n  // If this is set, we will take the currently running git checkout and bundle\n  // the meteor tool from it inside this package as a tool. We will include\n  // built copies of all known isopackets.\n  self.includeTool = false;\n\n  // Is this a core package? Core packages don't record version files, because\n  // core packages are only ever run from checkout. For the preview release,\n  // core packages do not need to specify their versions at publication (since\n  // there isn't likely to be any exciting version skew yet), but we will\n  // specify the correct restrictions at 0.90.\n  // XXX: 0.90 package versions.\n  self.isCore = false;\n};\n\n\n_.extend(PackageSource.prototype, {\n  // Make a dummy (empty) packageSource that contains nothing of interest.\n  // XXX: Do we need this\n  initEmpty: function (name) {\n    var self = this;\n    self.name = name;\n  },\n\n  // Programmatically initialize a PackageSource from scratch.\n  //\n  // Unlike user-facing methods of creating a package\n  // (initFromPackageDir, initFromAppDir) this does not implicitly add\n  // a dependency on the 'meteor' package. If you want such a\n  // dependency then you must add it yourself.\n  //\n  // If called inside a buildmessage job, it will keep going if things\n  // go wrong. Be sure to call jobHasMessages to see if it actually\n  // succeeded.\n  //\n  // The architecture is hardcoded to be \"os\".\n  //\n  // Note that this does not set a version on the package!\n  //\n  // Options:\n  // - sourceRoot (required if sources present)\n  // - serveRoot (required if sources present)\n  // - use\n  // - sources (array of paths or relPath/fileOptions objects), note that this\n  // doesn't support assets at this time. If you want to pass assets here, you\n  // should add a new option to this function called `assets`.\n  // - npmDependencies\n  // - cordovaDependencies\n  // - npmDir\n  // - localNodeModulesDirs\n  initFromOptions: function (name, options) {\n    var self = this;\n    self.name = name;\n\n    if (options.sources && ! _.isEmpty(options.sources) &&\n        (! options.sourceRoot || ! options.serveRoot)) {\n      throw new Error(\"When source files are given, sourceRoot and \" +\n                      \"serveRoot must be specified\");\n    }\n\n    // sourceRoot is a relative file system path, one slash identifies a root\n    // relative to some starting location\n    self.sourceRoot = options.sourceRoot || files.pathSep;\n    // serveRoot is actually a part of a url path, root here is a forward slash\n    self.serveRoot = options.serveRoot || '/';\n\n    utils.ensureOnlyValidVersions(options.npmDependencies, {forCordova: false});\n    self.npmDependencies = options.npmDependencies;\n    self.npmCacheDirectory = options.npmDir;\n\n    utils.ensureOnlyValidVersions(options.cordovaDependencies, {forCordova: true});\n    self.cordovaDependencies = options.cordovaDependencies;\n\n    const sources = options.sources.map((source) => {\n      if (typeof source === \"string\") {\n        return {\n          relPath: source\n        };\n      }\n\n      return source;\n    });\n\n    const sourceArch = new SourceArch(self, {\n      kind: options.kind,\n      arch: \"os\",\n      sourceRoot: self.sourceRoot,\n      uses: _.map(options.use, splitConstraint),\n      getFiles() {\n        return {\n          sources: sources\n        }\n      }\n    });\n\n    if (options.localNodeModulesDirs) {\n      _.extend(sourceArch.localNodeModulesDirs,\n               options.localNodeModulesDirs);\n    }\n\n    self.architectures.push(sourceArch);\n\n    if (! self._checkCrossUnibuildVersionConstraints()) {\n      throw new Error(\"only one unibuild, so how can consistency check fail?\");\n    }\n  },\n\n  // Initialize a PackageSource from a package.js-style package directory. Uses\n  // the name field provided and the name/test fields in the package.js file to\n  // figre out if this is a test package (load from onTest) or a use package\n  // (load from onUse).\n  //\n  // name: name of the package.\n  // dir: location of directory on disk.\n  // options:\n  // - name: override the name of this package with a different name.\n  // - buildingIsopackets: true if this is being scanned in the process\n  //   of building isopackets\n  initFromPackageDir: function (dir, options) {\n    var self = this;\n    buildmessage.assertInCapture();\n    var isPortable = true;\n    options = options || {};\n    var initFromPackageDirOptions = options;\n\n    // If we know what package we are initializing, we pass in a\n    // name. Otherwise, we are intializing the base package specified by 'name:'\n    // field in Package.Describe. In that case, it is clearly not a test\n    // package. (Though we could be initializing a specific package without it\n    // being a test, for a variety of reasons).\n    if (options.name) {\n      self.isTest = isTestName(options.name);\n      self.name = options.name;\n    }\n\n    // Give the package a default version. We do not set\n    // versionExplicitlyProvided unless the package configuration file actually\n    // sets a version.\n    self.version = \"0.0.0\";\n\n    // To make the transition to using README.md files in Isobuild easier, we\n    // initialize the documentation directory to README.md by default.\n    self.metadata.documentation = \"README.md\";\n\n    self.sourceRoot = dir;\n\n    // If we are running from checkout we may be looking at a core package. If\n    // we are, let's remember this for things like not recording version files.\n    if (files.inCheckout()) {\n      var packDir = files.pathJoin(files.getCurrentToolsDir(), 'packages');\n      if (files.pathDirname(self.sourceRoot) === packDir) {\n        self.isCore = true;\n      }\n    }\n    if (! files.exists(self.sourceRoot)) {\n      throw new Error(\"putative package directory \" + dir + \" doesn't exist?\");\n    }\n\n    var fileAndDepLoader = null;\n    var npmDependencies = null;\n    var cordovaDependencies = null;\n\n    const packageFileHashes = Object.create(null);\n    const packageJsPath = files.pathJoin(self.sourceRoot, 'package.js');\n    const packageJsCode = files.readFile(packageJsPath);\n    packageFileHashes[packageJsPath] = watch.sha1(packageJsCode);\n\n    const pkgJsonPath = files.pathJoin(self.sourceRoot, 'package.json');\n    const pkgJsonStat = files.statOrNull(pkgJsonPath);\n    if (pkgJsonStat &&\n        pkgJsonStat.isFile()) {\n      packageFileHashes[pkgJsonPath] =\n        watch.sha1(files.readFile(pkgJsonPath));\n    }\n\n    function watchPackageFiles(watchSet) {\n      _.each(packageFileHashes, (hash, path) => {\n        watchSet.addFile(path, hash);\n      });\n    }\n\n    // Any package that depends on us needs to be rebuilt if our package.js file\n    // changes, because a change to package.js might add or remove a plugin,\n    // which could change a file from being handled by plugin vs treated as\n    // an asset.\n    watchPackageFiles(self.pluginWatchSet);\n\n    var hasTests = false;\n\n    // == 'Package' object visible in package.js ==\n\n    /**\n     * @global\n     * @name  Package\n     * @summary The Package object in package.js\n     * @namespace\n     * @locus package.js\n     */\n    var Package = {\n      // Set package metadata. Options:\n      // - summary: for 'meteor list' & package server\n      // - version: package version string\n      // There used to be a third option documented here,\n      // 'environments', but it was never implemented and no package\n      // ever used it.\n\n      /**\n       * @summary Provide basic package information.\n       * @locus package.js\n       * @memberOf Package\n       * @param {Object} options\n       * @param {String} options.summary A concise 1-2 sentence description of\n       * the package, required for publication.\n       * @param {String} options.version The (extended)\n       * [semver](http://www.semver.org) version for your package. Additionally,\n       * Meteor allows a wrap number: a positive integer that follows the\n       * version number. If you are porting another package that uses semver\n       * versioning, you may want to use the original version, postfixed with\n       * `_wrapnumber`. For example, `1.2.3_1` or `2.4.5-rc1_4`. Wrap numbers\n       * sort after the original numbers: `1.2.3` < `1.2.3_1` < `1.2.3_2` <\n       * `1.2.4-rc.0`. If no version is specified, this field defaults to\n       * `0.0.0`. If you want to publish your package to the package server, you\n       * must specify a version.\n       * @param {String} options.name Optional name override. By default, the\n       * package name comes from the name of its directory.\n       * @param {String} options.git Optional Git URL to the source repository.\n       * @param {String} options.documentation Optional Filepath to\n       * documentation. Set to 'README.md' by default. Set this to null to submit\n       * no documentation.\n       * @param {Boolean} options.debugOnly A package with this flag set to true\n       * will not be bundled into production builds. This is useful for packages\n       * meant to be used in development only.\n       * @param {Boolean} options.prodOnly A package with this flag set to true\n       * will ONLY be bundled into production builds.\n       * @param {Boolean} options.testOnly A package with this flag set to true\n       * will ONLY be bundled as part of `meteor test`.\n       */\n      describe: function (options) {\n        _.each(options, function (value, key) {\n          if (key === \"summary\" ||\n              key === \"git\") {\n            self.metadata[key] = value;\n          } else if (key === \"documentation\") {\n            self.metadata[key] = value;\n            self.docsExplicitlyProvided = true;\n          } else if (key === \"version\") {\n            if (typeof(value) !== \"string\") {\n              buildmessage.error(\"The package version (specified with \"\n                                 + \"Package.describe) must be a string.\");\n              // Recover by pretending that version was not set.\n            } else {\n              var goodVersion = true;\n              try {\n                var parsedVersion = packageVersionParser.getValidServerVersion(\n                  value);\n              } catch (e) {\n                if (!e.versionParserError) {\n                  throw e;\n                }\n                buildmessage.error(\n                  \"The package version \" + value + \" (specified with Package.describe) \"\n                    + \"is not a valid Meteor package version.\\n\"\n                    + \"Valid package versions are semver (see http://semver.org/), \"\n                    + \"optionally followed by '_' and an integer greater or equal to 1.\");\n                goodVersion = false;\n              }\n              // Recover by pretending that the version was not set.\n            }\n            if (goodVersion && parsedVersion !== value) {\n              buildmessage.error(\n                \"The package version (specified with Package.describe) may not \"\n                  + \"contain a plus-separated build ID.\");\n              // Recover by pretending that the version was not set.\n              goodVersion = false;\n            }\n            if (goodVersion) {\n              self.version = value;\n              self.versionExplicitlyProvided = true;\n            }\n          } else if (key === \"name\" && !self.isTest) {\n            if (!self.name) {\n              self.name = value;\n            } else if (self.name !== value) {\n              // Woah, so we requested a non-test package by name, and it is not\n              // the name that we find inside. That's super weird.\n              buildmessage.error(\n                \"trying to initialize a nonexistent base package \" + value);\n            }\n            // `debugOnly`, `prodOnly` and `testOnly` are boolean\n            // flags you can put on a package, currently undocumented.\n            // when set to true, they cause a package's code to be\n            // only included (i.e. linked into the bundle) in dev\n            // mode, prod mode (`meteor --production`) or app tests\n            // (`meteor test`), and excluded otherwise.\n            //\n            // Notes:\n            //\n            // * These flags do not affect which packages or which versions are\n            //   are selected by the version solver.\n            //\n            // * When you use a debugOnly, prodOnly or testOnly\n            //   package, its exports are not imported for you.  You\n            //   have to access them using\n            //   `Package[\"my-package\"].MySymbol`.\n            //\n            // * These flags CAN cause different package load orders in\n            //   development and production!  We should probably fix this.\n            //   Basically, packages that are excluded from the build using\n            //   these flags are also excluded fro the build order calculation,\n            //   and that's the problem\n            //\n            // * We should consider publicly documenting these flags, since they\n            //   are effectively part of the public API.\n          } else if (key === \"debugOnly\") {\n            self.debugOnly = !!value;\n          } else if (key === \"prodOnly\") {\n            self.prodOnly = !!value;\n          } else if (key === \"testOnly\") {\n            self.testOnly = !!value;\n          } else {\n            // Do nothing. We might want to add some keys later, and we should err\n            // on the side of backwards compatibility.\n          }\n          if (_.size(_.compact([self.debugOnly, self.prodOnly, self.testOnly])) > 1) {\n            buildmessage.error(\n              \"Package can't have more than one of: debugOnly, prodOnly, testOnly.\");\n          }\n        });\n      },\n\n      /**\n       * @summary Define package dependencies and expose package methods.\n       * @locus package.js\n       * @memberOf Package\n       * @param {Function} func A function that takes in the package control `api` object, which keeps track of dependencies and exports.\n       */\n      onUse: function (f) {\n        if (!self.isTest) {\n          if (fileAndDepLoader) {\n            buildmessage.error(\"duplicate onUse handler; a package may have \" +\n                               \"only one\", { useMyCaller: true });\n            // Recover by ignoring the duplicate\n            return;\n          }\n          fileAndDepLoader = f;\n        }\n      },\n\n      /**\n       * @deprecated in 0.9.0\n       */\n      on_use: function (f) {\n        this.onUse(f);\n      },\n\n      /**\n       * @summary Define dependencies and expose package methods for unit tests.\n       * @locus package.js\n       * @memberOf Package\n       * @param {Function} func A function that takes in the package control 'api' object, which keeps track of dependencies and exports.\n       */\n      onTest: function (f) {\n        // If we are not initializing the test package, then we are initializing\n        // the normal package and have now noticed that it has tests. So, let's\n        // register the test. This is a medium-length hack until we have new\n        // control files.\n        if (!self.isTest) {\n          hasTests = true;\n          return;\n        }\n\n        // We are initializing the test, so proceed as normal.\n        if (self.isTest) {\n          if (fileAndDepLoader) {\n            buildmessage.error(\"duplicate onTest handler; a package may have \" +\n                               \"only one\", { useMyCaller: true });\n            // Recover by ignoring the duplicate\n            return;\n          }\n          fileAndDepLoader = f;\n        }\n      },\n\n      /**\n       * @deprecated in 0.9.0\n       */\n      on_test: function (f) {\n        this.onTest(f);\n      },\n\n      // Define a plugin. A plugin extends the build process for\n      // targets that use this package. For example, a Coffeescript\n      // compiler would be a plugin. A plugin is its own little\n      // program, with its own set of source files, used packages, and\n      // npm dependencies.\n      //\n      // This is an experimental API and for now you should assume\n      // that it will change frequently and radically (thus the\n      // '_transitional_'). For maximum R&D velocity and for the good\n      // of the platform, we will push changes that break your\n      // packages that use this API. You've been warned.\n      //\n      // Options:\n      // - name: a name for this plugin. required (cosmetic -- string)\n      // - use: package to use for the plugin (names, as strings)\n      // - sources: sources for the plugin (array of string)\n      // - npmDependencies: map from npm package name to required\n      //   version (string)\n\n      /**\n       * @summary Define a build plugin. A build plugin extends the build\n       * process for apps and packages that use this package. For example,\n       * the `coffeescript` package uses a build plugin to compile CoffeeScript\n       * source files into JavaScript.\n       * @param  {Object} [options]\n       * @param {String} options.name A cosmetic name, must be unique in the\n       * package.\n       * @param {String|String[]} options.use Meteor packages that this\n       * plugin uses, independent of the packages specified in\n       * [api.onUse](#pack_onUse).\n       * @param {String[]} options.sources The source files that make up the\n       * build plugin, independent from [api.addFiles](#pack_addFiles).\n       * @param {Object} options.npmDependencies An object where the keys\n       * are NPM package names, and the values are the version numbers of\n       * required NPM packages, just like in [Npm.depends](#Npm-depends).\n       * @memberOf Package\n       * @locus package.js\n       */\n      registerBuildPlugin: function (options) {\n        // Tests don't have plugins; plugins initialized in the control file\n        // belong to the package and not to the test. (This will be less\n        // confusing in the new control file format).\n        if (self.isTest) {\n          return;\n        }\n\n        if (! ('name' in options)) {\n          buildmessage.error(\"build plugins require a name\",\n                             { useMyCaller: true });\n          // recover by ignoring plugin\n          return;\n        }\n\n        if (options.name in self.pluginInfo) {\n          buildmessage.error(\"this package already has a plugin named '\" +\n                             options.name + \"'\",\n                             { useMyCaller: true });\n          // recover by ignoring plugin\n          return;\n        }\n\n        if (options.name.match(/\\.\\./) || options.name.match(/[\\\\\\/]/)) {\n          buildmessage.error(\"bad plugin name\", { useMyCaller: true });\n          // recover by ignoring plugin\n          return;\n        }\n\n        // XXX probably want further type checking\n        self.pluginInfo[options.name] = options;\n      },\n\n      /**\n       * @deprecated in 0.9.4\n       */\n      _transitional_registerBuildPlugin: function (options) {\n        this.registerBuildPlugin(options);\n      },\n\n      includeTool: function () {\n        if (!files.inCheckout()) {\n          buildmessage.error(\"Package.includeTool() can only be used with a \" +\n                             \"checkout of meteor\");\n        } else if (self.includeTool) {\n          buildmessage.error(\"Duplicate includeTool call\");\n        } else {\n          self.includeTool = true;\n        }\n      }\n    };\n\n    // == 'Npm' object visible in package.js ==\n\n    /**\n     * @namespace Npm\n     * @global\n     * @summary The Npm object in package.js and package source files.\n     */\n    var Npm = {\n      /**\n       * @summary Specify which [NPM](https://www.npmjs.org/) packages\n       * your Meteor package depends on.\n       * @param  {Object} dependencies An object where the keys are package\n       * names and the values are one of:\n       *   1. Version numbers in string form\n       *   2. Http(s) URLs to a git commit by SHA.   \n       *   3. Git URLs in the format described [here](https://docs.npmjs.com/files/package.json#git-urls-as-dependencies)\n       *\n       * Https URL example:\n       *\n       * ```js\n       * Npm.depends({\n       *   moment: \"2.8.3\",\n       *   async: \"https://github.com/caolan/async/archive/71fa2638973dafd8761fa5457c472a312cc820fe.tar.gz\"\n       * });\n       * ```\n       *\n       * Git URL example:\n       *\n       * ```js\n       * Npm.depends({\n       *   moment: \"2.8.3\",\n       *   async: \"git+https://github.com/caolan/async#master\"\n       * });\n       * ```\n       * @locus package.js\n       * @memberOf  Npm\n       */\n      depends: function (_npmDependencies) {\n        // XXX make npmDependencies be separate between use and test, so that\n        // production doesn't have to ship all of the npm modules used by test\n        // code\n        if (npmDependencies) {\n          buildmessage.error(\"Npm.depends may only be called once per package\",\n                             { useMyCaller: true });\n          // recover by ignoring the Npm.depends line\n          return;\n        }\n        if (typeof _npmDependencies !== 'object') {\n          buildmessage.error(\"the argument to Npm.depends should be an \" +\n                             \"object, like this: {gcd: '0.0.0'}\",\n                             { useMyCaller: true });\n          // recover by ignoring the Npm.depends line\n          return;\n        }\n\n        // don't allow npm fuzzy versions so that there is complete\n        // consistency when deploying a meteor app\n        //\n        // XXX use something like seal or lockdown to have *complete*\n        // confidence we're running the same code?\n        try {\n          utils.ensureOnlyValidVersions(_npmDependencies, {forCordova: false});\n        } catch (e) {\n          buildmessage.error(e.message, { useMyCaller: true, downcase: true });\n          // recover by ignoring the Npm.depends line\n          return;\n        }\n\n        npmDependencies = _npmDependencies;\n      },\n\n      // The `Npm.strip` method makes up for packages that have missing\n      // or incomplete .npmignore files by telling the bundler to strip out\n      // certain unnecessary files and/or directories during `meteor build`.\n      //\n      // The `discards` parameter should be an object whose keys are\n      // top-level package names and whose values are arrays of strings\n      // (or regular expressions) that match paths in that package's\n      // directory that should be stripped before installation. For\n      // example:\n      //\n      //   Npm.strip({\n      //     connect: [/*\\.wmv$/],\n      //     useragent: [\"tests/\"]\n      //   });\n      //\n      // This means (1) \"remove any files with the `.wmv` extension from\n      // the 'connect' package directory\" and (2) \"remove the 'tests'\n      // directory from the 'useragent' package directory.\"\n      strip: function(discards) {\n        self.npmDiscards.merge(discards);\n      },\n\n      require: function (name) {\n        try {\n          return require(name); // from the dev bundle\n        } catch (e) {\n          buildmessage.error(\n            \"can't find npm module '\" + name +\n              \"'. In package.js, Npm.require can only find built-in modules.\",\n            { useMyCaller: true });\n          // recover by, uh, returning undefined, which is likely to\n          // have some knock-on effects\n          return undefined;\n        }\n      }\n    };\n\n    // == 'Cordova' object visible in package.js ==\n\n    /**\n     * @namespace Cordova\n     * @global\n     * @summary The Cordova object in package.js.\n     */\n    var Cordova = {\n      /**\n       * @summary Specify which [Cordova / PhoneGap](http://cordova.apache.org/)\n       * plugins your Meteor package depends on.\n       *\n       * Plugins are installed from\n       * [plugins.cordova.io](http://plugins.cordova.io/), so the plugins and\n       * versions specified must exist there. Alternatively, the version\n       * can be replaced with a GitHub tarball URL as described in the\n       * [Cordova](https://github.com/meteor/meteor/wiki/Meteor-Cordova-integration#meteor-packages-with-cordova-dependencies)\n       * page of the Meteor wiki on GitHub.\n       * @param  {Object} dependencies An object where the keys are plugin\n       * names and the values are version numbers or GitHub tarball URLs\n       * in string form.\n       * Example:\n       *\n       * ```js\n       * Cordova.depends({\n       *   \"org.apache.cordova.camera\": \"0.3.0\"\n       * });\n       * ```\n       *\n       * Alternatively, with a GitHub URL:\n       *\n       * ```js\n       * Cordova.depends({\n       *   \"org.apache.cordova.camera\":\n       *     \"https://github.com/apache/cordova-plugin-camera/tarball/d84b875c449d68937520a1b352e09f6d39044fbf\"\n       * });\n       * ```\n       *\n       * @locus package.js\n       * @memberOf  Cordova\n       */\n      depends: function (_cordovaDependencies) {\n        // XXX make cordovaDependencies be separate between use and test, so that\n        // production doesn't have to ship all of the npm modules used by test\n        // code\n        if (cordovaDependencies) {\n          buildmessage.error(\"Cordova.depends may only be called once per package\",\n                             { useMyCaller: true });\n          // recover by ignoring the Cordova.depends line\n          return;\n        }\n        if (typeof _cordovaDependencies !== 'object') {\n          buildmessage.error(\"the argument to Cordova.depends should be an \" +\n                             \"object, like this: {gcd: '0.0.0'}\",\n                             { useMyCaller: true });\n          // recover by ignoring the Cordova.depends line\n          return;\n        }\n\n        // don't allow cordova fuzzy versions so that there is complete\n        // consistency when deploying a meteor app\n        //\n        // XXX use something like seal or lockdown to have *complete*\n        // confidence we're running the same code?\n        try {\n          utils.ensureOnlyValidVersions(_cordovaDependencies, {forCordova: true});\n        } catch (e) {\n          buildmessage.error(e.message, { useMyCaller: true, downcase: true });\n          // recover by ignoring the Npm.depends line\n          return;\n        }\n\n        cordovaDependencies = _cordovaDependencies;\n      },\n    };\n\n    try {\n      files.runJavaScript(packageJsCode.toString('utf8'), {\n        filename: 'package.js',\n        symbols: { Package: Package, Npm: Npm, Cordova: Cordova }\n      });\n    } catch (e) {\n      buildmessage.exception(e);\n\n      // Could be a syntax error or an exception. Recover by\n      // continuing as if package.js is empty. (Pressing on with\n      // whatever handlers were registered before the exception turns\n      // out to feel pretty disconcerting -- definitely violates the\n      // principle of least surprise.) Leave the metadata if we have\n      // it, though.\n      fileAndDepLoader = null;\n      self.pluginInfo = {};\n      npmDependencies = null;\n      cordovaDependencies = null;\n    }\n\n    // In the past, we did not require a Package.Describe.name field. So, it is\n    // possible that we are initializing a package that doesn't use it and\n    // expects us to be implicit about it.\n    if (!self.name) {\n      // For backwards-compatibility, we will take the package name from the\n      // directory of the package. That was what we used to do: in fact, we used\n      // to only do that.\n      self.name = files.pathBasename(dir);\n    }\n\n    // Check to see if our name is valid.\n\n    try {\n      utils.validatePackageName(self.name);\n    } catch (e) {\n      if (!e.versionParserError) {\n        throw e;\n      }\n      buildmessage.error(e.message);\n      // recover by ignoring\n    }\n\n    // We want the \"debug mode\" to be a property of the *bundle* operation\n    // (turning a set of packages, including the app, into a star), not the\n    // *compile* operation (turning a package source into an isopack). This is\n    // so we don't have to publish two versions of each package. But we have no\n    // way to mark a file in an isopack as being the result of running a plugin\n    // from a debugOnly dependency, and so there is no way to tell which files\n    // to exclude in production mode from a published package. Eventually, we'll\n    // add such a flag to the isopack format, but until then we'll sidestep the\n    // issue by disallowing build plugins in debugOnly packages.\n    if ((self.debugOnly || self.prodOnly || self.testOnly) && !_.isEmpty(self.pluginInfo)) {\n      buildmessage.error(\n        \"can't register build plugins in debugOnly, prodOnly or testOnly packages\");\n      // recover by ignoring\n    }\n\n    // For this old-style, onUse/onTest/where-based package, figure\n    // out its dependencies by calling its on_xxx functions and seeing\n    // what it does.\n    //\n    // We have a simple strategy. Call its on_xxx handler with no\n    // 'where', which is what happens when the package is added\n    // directly to an app, and see what files it adds to the client\n    // and the server. When a package is used, include it in both the client\n    // and the server by default. This simple strategy doesn't capture even\n    // 10% of the complexity possible with onUse, onTest, and where, but\n    // probably is sufficient for virtually all packages that actually\n    // exist in the field, if not every single one. #OldStylePackageSupport\n\n    var api = new packageAPIModule.PackageAPI({\n      buildingIsopackets: !!initFromPackageDirOptions.buildingIsopackets\n    });\n\n    if (fileAndDepLoader) {\n      try {\n        buildmessage.markBoundary(fileAndDepLoader)(api);\n      } catch (e) {\n        console.log(e.stack); // XXX should we keep this here -- or do we want broken\n                              // packages to fail silently?\n        buildmessage.exception(e);\n\n        // Recover by ignoring all of the source files in the\n        // packages and any remaining handlers. It violates the\n        // principle of least surprise to half-run a handler\n        // and then continue.\n        api.files = {};\n        _.each(compiler.ALL_ARCHES, function (arch) {\n          api.files[arch] = {\n            sources: [],\n            assets: []\n          };\n        });\n\n        fileAndDepLoader = null;\n        self.pluginInfo = {};\n        npmDependencies = null;\n        cordovaDependencies = null;\n      }\n    }\n\n    // By the way, you can't depend on yourself.\n    var doNotDepOnSelf = function (dep) {\n      if (dep.package === self.name) {\n        buildmessage.error(\"Circular dependency found: \"\n                           + self.name +\n                           \" depends on itself.\\n\");\n      }\n    };\n    _.each(compiler.ALL_ARCHES, function (label) {\n      _.each(api.uses[label], doNotDepOnSelf);\n      _.each(api.implies[label], doNotDepOnSelf);\n    });\n\n    // Cause packages that use `prodOnly` to automatically depend on the\n    // `isobuild:prod-only` feature package, which will cause an error\n    // when a package using `prodOnly` is run by a version of the tool\n    // that doesn't support the feature.  The choice of 'os' architecture\n    // is arbitrary, as the version solver combines the dependencies of all\n    // arches.\n    if (self.prodOnly) {\n      api.uses['os'].push({\n        package: 'isobuild:prod-only', constraint: '1.0.0'\n      });\n    }\n\n    // If we have specified some release, then we should go through the\n    // dependencies and fill in the unspecified constraints with the versions in\n    // the releases (if possible).\n    if (!_.isEmpty(api.releaseRecords)) {\n\n      // Given a dependency object with keys package (the name of the package)\n      // and constraint (the version constraint), if the constraint is null,\n      // look in the packages field in the release record and fill in from\n      // there.\n      var setFromRel = function (dep) {\n        if (dep.constraint) {\n          return dep;\n        }\n        var newConstraint = [];\n        _.each(api.releaseRecords, function (releaseRecord) {\n          var packages = releaseRecord.packages;\n          if(_.has(packages, dep.package)) {\n            newConstraint.push(packages[dep.package]);\n          }\n        });\n        if (_.isEmpty(newConstraint)) {\n          return dep;\n        }\n        dep.constraint = _.reduce(newConstraint,\n          function(x, y) {\n            return x + \" || \" + y;\n          });\n        return dep;\n      };\n\n      // For all api.implies and api.uses, fill in the unspecified dependencies from the\n      // release.\n      _.each(compiler.ALL_ARCHES, function (label) {\n        api.uses[label] = _.map(api.uses[label], setFromRel);\n        api.implies[label] = _.map(api.implies[label], setFromRel);\n      });\n     };\n\n    // Make sure that if a dependency was specified in multiple\n    // unibuilds, the constraint is exactly the same.\n    if (! self._checkCrossUnibuildVersionConstraints()) {\n      // A build error was written. Recover by ignoring the\n      // fact that we have differing constraints.\n    }\n\n    // Save information about npm dependencies. To keep metadata\n    // loading inexpensive, we won't actually fetch them until build\n    // time.\n\n    // We used to put the cache directly in .npm, but in linker-land,\n    // the package's own NPM dependencies go in .npm/package and build\n    // plugin X's goes in .npm/plugin/X. Notably, the former is NOT an\n    // ancestor of the latter, so that a build plugin does NOT see the\n    // package's node_modules.  XXX maybe there should be separate NPM\n    // dirs for use vs test?\n    self.npmCacheDirectory =\n      files.pathResolve(files.pathJoin(self.sourceRoot, '.npm', 'package'));\n    self.npmDependencies = npmDependencies;\n\n    self.cordovaDependencies = cordovaDependencies;\n\n    // Create source architectures, one for the server and one for each web\n    // arch.\n    _.each(compiler.ALL_ARCHES, function (arch) {\n      // Everything depends on the package 'meteor', which sets up\n      // the basic environment) (except 'meteor' itself).\n      if (self.name !== \"meteor\" && !process.env.NO_METEOR_PACKAGE) {\n        // Don't add the dependency if one already exists. This allows the\n        // package to create an unordered dependency and override the one that\n        // we'd add here. This is necessary to resolve the circular dependency\n        // between meteor and underscore (underscore has an unordered\n        // dependency on meteor dating from when the .js extension handler was\n        // in the \"meteor\" package).\n        var alreadyDependsOnMeteor =\n              !! _.find(api.uses[arch], function (u) {\n                return u.package === \"meteor\";\n              });\n        if (! alreadyDependsOnMeteor) {\n          api.uses[arch].unshift({ package: \"meteor\" });\n        }\n      }\n\n      // Each unibuild has its own separate WatchSet. This is so that, eg, a test\n      // unibuild's dependencies doesn't end up getting merged into the\n      // pluginWatchSet of a package that uses it: only the use unibuild's\n      // dependencies need to go there!\n      var watchSet = new watch.WatchSet();\n      watchPackageFiles(watchSet);\n\n      self.architectures.push(new SourceArch(self, {\n        kind: \"main\",\n        arch: arch,\n        sourceRoot: self.sourceRoot,\n        uses: api.uses[arch],\n        implies: api.implies[arch],\n        getFiles(sourceProcessorSet, watchSet) {\n          const result = api.files[arch];\n          const relPathToSourceObj = {};\n          const sources = result.sources;\n\n          // Files explicitly passed to api.addFiles remain at the\n          // beginning of api.files[arch].sources in their given order.\n          sources.forEach(sourceObj => {\n            relPathToSourceObj[sourceObj.relPath] = sourceObj;\n          });\n\n          self._findSources({\n            sourceProcessorSet,\n            watchSet,\n            sourceArch: this,\n            isApp: false\n          }).forEach(relPath => {\n            if (! _.has(relPathToSourceObj, relPath)) {\n              const fileOptions = self._inferFileOptions(relPath, {\n                arch,\n                isApp: false,\n              });\n\n              // Since this file was not explicitly added with\n              // api.addFiles, it should not be evaluated eagerly.\n              fileOptions.lazy = true;\n\n              sources.push(relPathToSourceObj[relPath] = {\n                relPath,\n                fileOptions,\n              });\n            }\n          });\n\n          return result;\n        },\n        declaredExports: api.exports[arch],\n        watchSet: watchSet\n      }));\n    });\n\n    // Serve root of the package.\n    self.serveRoot = files.pathJoin('/packages/', self.name);\n\n    // Name of the test.\n    if (hasTests) {\n      self.testName = genTestName(self.name);\n    }\n  },\n\n  _readAndWatchDirectory(relDir, watchSet, {include, exclude, names}) {\n    return watch.readAndWatchDirectory(watchSet, {\n      absPath: files.pathJoin(this.sourceRoot, relDir),\n      include, exclude, names\n    }).map(name => files.pathJoin(relDir, name));\n  },\n\n  // Initialize a package from an application directory (has .meteor/packages).\n  initFromAppDir: Profile(\"initFromAppDir\", function (projectContext, ignoreFiles) {\n    var self = this;\n    var appDir = projectContext.projectDir;\n    self.name = null;\n    self.sourceRoot = appDir;\n    self.serveRoot = '/';\n\n    // Determine used packages. Note that these are the same for all arches,\n    // because there's no way to specify otherwise in .meteor/packages.\n    var uses = [];\n    projectContext.projectConstraintsFile.eachConstraint(function (constraint) {\n      uses.push({ package: constraint.package,\n                  constraint: constraint.constraintString });\n    });\n\n    var projectWatchSet = projectContext.getProjectWatchSet();\n\n    _.each(compiler.ALL_ARCHES, function (arch) {\n      // We don't need to build a Cordova SourceArch if there are no Cordova\n      // platforms.\n      if (arch === 'web.cordova' &&\n          _.isEmpty(projectContext.platformList.getCordovaPlatforms())) {\n        return;\n      }\n\n      // XXX what about /web.browser/* etc, these directories could also\n      // be for specific client targets.\n\n      // Create unibuild\n      var sourceArch = new SourceArch(self, {\n        kind: 'app',\n        arch: arch,\n        sourceRoot: self.sourceRoot,\n        uses: uses,\n        getFiles(sourceProcessorSet, watchSet) {\n          sourceProcessorSet.watchSet = watchSet;\n\n          const findOptions = {\n            sourceProcessorSet,\n            watchSet,\n            sourceArch: this,\n            ignoreFiles,\n            isApp: true,\n            loopChecker: new SymlinkLoopChecker(self.sourceRoot)\n          };\n\n          return {\n            sources: self._findSources(findOptions).sort(\n              loadOrderSort(sourceProcessorSet, arch)\n            ).map(relPath => {\n              return {\n                relPath,\n                fileOptions: self._inferFileOptions(relPath, {\n                  arch,\n                  isApp: true,\n                }),\n              };\n            }),\n\n            assets: self._findAssets(findOptions),\n          };\n        }\n      });\n\n      const origAppDir = projectContext.getOriginalAppDirForTestPackages();\n\n      const origNodeModulesDir = origAppDir &&\n        files.pathJoin(origAppDir, \"node_modules\");\n\n      const origNodeModulesStat = origNodeModulesDir &&\n        files.statOrNull(origNodeModulesDir);\n\n      if (origNodeModulesStat &&\n          origNodeModulesStat.isDirectory()) {\n        sourceArch.localNodeModulesDirs[\"node_modules\"] = {\n          // Override these properties when calling\n          // addNodeModulesDirectory in compileUnibuild.\n          sourceRoot: origAppDir,\n          sourcePath: origNodeModulesDir,\n          local: false,\n        };\n      }\n\n      self.architectures.push(sourceArch);\n\n      // sourceArch's WatchSet should include all the project metadata files\n      // read by the ProjectContext.\n      sourceArch.watchSet.merge(projectWatchSet);\n    });\n\n    if (! self._checkCrossUnibuildVersionConstraints()) {\n      // should never happen since we created the unibuilds from\n      // .meteor/packages, which doesn't have a way to express\n      // different constraints for different unibuilds\n      throw new Error(\"conflicting constraints in a package?\");\n    }\n  }),\n\n  _inferFileOptions(relPath, {arch, isApp}) {\n    const fileOptions = {};\n    const isAnyTest = global.testCommandMetadata &&\n      (global.testCommandMetadata.isTest ||\n       global.testCommandMetadata.isAppTest);\n\n    if (isAnyTest) {\n      if (isTestFilePath(relPath)) {\n        // When running tests, test files should not be loaded lazily.\n        return fileOptions;\n      }\n\n      // If running in test mode (`meteor test`), all files other than\n      // test files should be loaded lazily.\n      if (global.testCommandMetadata.isTest) {\n        fileOptions.lazy = true;\n      }\n    }\n\n    const dirs = files.pathDirname(relPath).split(files.pathSep);\n\n    for (var i = 0; i < dirs.length; ++i) {\n      let dir = dirs[i];\n\n      if (dir === \"node_modules\") {\n        fileOptions.lazy = true;\n        fileOptions.transpile = false;\n\n        // Return immediately so that we don't apply special meanings to\n        // client or server directories inside node_modules directories.\n        return fileOptions;\n      }\n\n      if (isApp && dir === \"imports\") {\n        fileOptions.lazy = true;\n      }\n\n      // If the file is restricted to the opposite architecture, make sure\n      // it is not evaluated eagerly.\n      if (archinfo.matches(arch, \"os\")) {\n        if (dir === \"client\") {\n          fileOptions.lazy = true;\n        }\n      } else if (dir === \"server\") {\n        fileOptions.lazy = true;\n      }\n\n      // Special case: in app code on the client, JavaScript files in a\n      // `client/compatibility` directory don't get wrapped in a closure.\n      if (i > 0 &&\n          dirs[i - 1] === \"client\" &&\n          dir === \"compatibility\" &&\n          isApp && // Skip this check for packages.\n          archinfo.matches(arch, \"web\") &&\n          relPath.endsWith(\".js\")) {\n        fileOptions.bare = true;\n      }\n    }\n\n    return fileOptions;\n  },\n\n  // This cache survives for the duration of the process, and stores the\n  // complete list of source files for directories within node_modules.\n  _findSourcesCache: Object.create(null),\n\n  _findSources({\n    sourceProcessorSet,\n    watchSet,\n    isApp,\n    sourceArch,\n    loopChecker = new SymlinkLoopChecker(this.sourceRoot),\n    ignoreFiles = []\n  }) {\n    const self = this;\n    const arch = sourceArch.arch;\n    const sourceReadOptions =\n      sourceProcessorSet.appReadDirectoryOptions(arch);\n\n    // Ignore files starting with dot (unless they are explicitly in\n    // 'names').\n    sourceReadOptions.exclude.push(/^\\./);\n    // Ignore the usual ignorable files.\n    sourceReadOptions.exclude.push(...ignoreFiles);\n\n    // Unless we're running tests, ignore all test filenames and if we are, ignore the\n    // type of file we *aren't* running\n    if (!global.testCommandMetadata || global.testCommandMetadata.isTest) {\n      Array.prototype.push.apply(sourceReadOptions.exclude, APP_TEST_FILENAME_REGEXPS);\n    }\n    if (!global.testCommandMetadata || global.testCommandMetadata.isAppTest) {\n      Array.prototype.push.apply(sourceReadOptions.exclude, TEST_FILENAME_REGEXPS);\n    }\n\n    // Read top-level source files, excluding control files that were not\n    // explicitly included.\n    const controlFiles = ['mobile-config.js'];\n\n    if (! isApp) {\n      controlFiles.push('package.js');\n    }\n\n    const anyLevelExcludes = [\n      /^tests\\/$/,\n      archinfo.matches(arch, \"os\")\n        ? /^client\\/$/\n        : /^server\\/$/,\n      ...sourceReadOptions.exclude,\n    ];\n\n    const topLevelExcludes = isApp ? [\n      ...anyLevelExcludes,\n      /^packages\\/$/,\n      /^programs\\/$/,\n      /^public\\/$/, /^private\\/$/,\n      /^cordova-build-override\\/$/,\n      /^acceptance-tests\\/$/,\n    ] : anyLevelExcludes;\n\n    const nodeModulesReadOptions = {\n      ...sourceReadOptions,\n      // When we're in a node_modules directory, we can avoid collecting\n      // .js and .json files, because (unlike .less or .coffee files) they\n      // are allowed to be imported later by the ImportScanner, as they do\n      // not require custom processing by compiler plugins.\n      exclude: sourceReadOptions.exclude.concat(/\\.js(on)?$/i),\n    };\n\n    const baseCacheKey = JSON.stringify({\n      isApp,\n      arch,\n      sourceRoot: self.sourceRoot,\n      excludes: anyLevelExcludes,\n    }, (key, value) => {\n      if (_.isRegExp(value)) {\n        return [value.source, value.flags];\n      }\n      return value;\n    });\n\n    function makeCacheKey(dir) {\n      return baseCacheKey + \"\\0\" + dir;\n    }\n\n    function find(dir, depth, inNodeModules) {\n      // Remove trailing slash.\n      dir = dir.replace(/\\/$/, \"\");\n\n      // If we're in a node_modules directory, cache the results of the\n      // find function for the duration of the process.\n      const cacheKey = inNodeModules && makeCacheKey(dir);\n      if (cacheKey &&\n          cacheKey in self._findSourcesCache) {\n        return self._findSourcesCache[cacheKey];\n      }\n\n      if (loopChecker.check(dir)) {\n        // Pretend we found no files.\n        return [];\n      }\n\n      const readOptions = inNodeModules\n        ? nodeModulesReadOptions\n        : sourceReadOptions;\n\n      const sources = _.difference(\n        self._readAndWatchDirectory(dir, watchSet, readOptions),\n        depth > 0 ? [] : controlFiles\n      );\n\n      const subdirectories = self._readAndWatchDirectory(dir, watchSet, {\n        include: [/\\/$/],\n        exclude: depth > 0\n          ? anyLevelExcludes\n          : topLevelExcludes\n      });\n\n      let nodeModulesDir;\n\n      subdirectories.forEach(subdir => {\n        if (/(^|\\/)node_modules\\/$/.test(subdir)) {\n          if (! inNodeModules) {\n            sourceArch.localNodeModulesDirs[subdir] = true;\n          }\n\n          // Defer handling node_modules until after we handle all other\n          // subdirectories, so that we know whether we need to descend\n          // further. If sources is still empty after we handle everything\n          // else in dir, then nothing in this node_modules subdir can be\n          // imported by anthing outside of it, so we can ignore it.\n          nodeModulesDir = subdir;\n\n        } else {\n          sources.push(...find(subdir, depth + 1, inNodeModules));\n        }\n      });\n\n      if (isApp &&\n          nodeModulesDir &&\n          (! inNodeModules || sources.length > 0)) {\n        // If we found a node_modules subdirectory above, and either we\n        // are not already inside another node_modules directory or we\n        // found source files elsewhere in this directory or its other\n        // subdirectories, and we're building an app (as opposed to a\n        // Meteor package), continue searching this node_modules\n        // directory, so that any non-.js(on) files it contains can be\n        // imported by the app (#6037).\n        sources.push(...find(nodeModulesDir, depth + 1, true));\n      }\n\n      if (cacheKey) {\n        self._findSourcesCache[cacheKey] = sources;\n      }\n\n      return sources;\n    }\n\n    return files.withCache(() => find(\"\", 0, false));\n  },\n\n  _findAssets({\n    sourceProcessorSet,\n    watchSet,\n    isApp,\n    sourceArch,\n    loopChecker = new SymlinkLoopChecker(this.sourceRoot),\n    ignoreFiles = [],\n  }) {\n    // Now look for assets for this unibuild.\n    const arch = sourceArch.arch;\n    const assetDir = archinfo.matches(arch, \"web\") ? \"public/\" : \"private/\";\n    var assetDirs = this._readAndWatchDirectory('', watchSet, {\n      names: [assetDir]\n    });\n\n    const assets = [];\n\n    if (!_.isEmpty(assetDirs)) {\n      if (!_.isEqual(assetDirs, [assetDir])) {\n        throw new Error(\"Surprising assetDirs: \" + JSON.stringify(assetDirs));\n      }\n\n      while (!_.isEmpty(assetDirs)) {\n        dir = assetDirs.shift();\n        // remove trailing slash\n        dir = dir.substr(0, dir.length - 1);\n\n        if (loopChecker.check(dir)) {\n          // pretend we found no files\n          return [];\n        }\n\n        // Find asset files in this directory.\n        var assetsAndSubdirs = this._readAndWatchDirectory(dir, watchSet, {\n          include: [/.?/],\n          // we DO look under dot directories here\n          exclude: ignoreFiles\n        });\n\n        _.each(assetsAndSubdirs, function (item) {\n          if (item[item.length - 1] === '/') {\n            // Recurse on this directory.\n            assetDirs.push(item);\n          } else {\n            // This file is an asset.\n            assets.push({\n              relPath: item\n            });\n          }\n        });\n      }\n    }\n\n    return assets;\n  },\n\n  // True if the package defines any plugins.\n  containsPlugins: function () {\n    var self = this;\n    return ! _.isEmpty(self.pluginInfo);\n  },\n\n  // Return dependency metadata for all unibuilds, in the format needed\n  // by the package catalog.\n  //\n  // This *DOES* include isobuild:* pseudo-packages!\n  //\n  // Options:\n  // - logError: if true, if something goes wrong, log a buildmessage\n  //   and return null rather than throwing an exception.\n  // - skipWeak: omit weak dependencies\n  // - skipUnordered: omit unordered dependencies\n  getDependencyMetadata: function (options) {\n    var self = this;\n    options = options || {};\n    var ret = self._computeDependencyMetadata(options);\n    if (! ret) {\n      if (options.logError) {\n        return null;\n      } else {\n        throw new Error(\"inconsistent dependency constraint across unibuilds?\");\n      }\n    }\n    return ret;\n  },\n\n  // Returns a list of package names which should be loaded before building this\n  // package. This is all the packages that we directly depend on in a unibuild\n  // or from a plugin.\n  //\n  // (It's possible that we could do something slightly fancier where we only\n  // need to load those dependencies (including implied dependencies) which we\n  // know contain plugins first, plus the transitive closure of all the packages\n  // we depend on which contain a plugin. This seems good enough, though.)\n  //\n  // Note that this method filters out isobuild:* pseudo-packages, so it is NOT\n  // to be used to create input to Version Solver (see\n  // _computeDependencyMetadata for that).\n  //\n  // Note also that \"load\" here specifically means \"load into the IsopackCache\n  // at build time\", not \"load into a running Meteor app at run\n  // time\". Specifically, weak constraints do create a run-time load order\n  // dependency (if the package is in the app at all) but they do not create a\n  // build-time IsopackCache load order dependency (because weak dependencies do\n  // not provide plugins).\n  getPackagesToLoadFirst: function (packageMap) {\n    var self = this;\n    var packages = {};\n    var processUse = function (use) {\n      // We don't have to build weak or unordered deps first (eg they can't\n      // contribute to a plugin).\n      if (use.weak || use.unordered) {\n        return;\n      }\n      // Only include real packages, not isobuild:* pseudo-packages.\n      if (compiler.isIsobuildFeaturePackage(use.package)) {\n        return;\n      }\n\n      var packageInfo = packageMap.getInfo(use.package);\n      if (! packageInfo) {\n        throw Error(\"Depending on unknown package \" + use.package);\n      }\n      packages[use.package] = true;\n    };\n\n    _.each(self.architectures, function (arch) {\n      // We need to iterate over both uses and implies, since implied packages\n      // also constitute dependencies. We don't have to include the dependencies\n      // of implied packages directly here, since their own\n      // getPackagesToLoadFirst will include those.\n      _.each(arch.uses, processUse);\n      _.each(arch.implies, processUse);\n    });\n\n    _.each(self.pluginInfo, function (info) {\n      // info.use is currently just an array of strings, and there's\n      // no way to specify weak/unordered. Much like an app.\n      _.each(info.use, function (spec) {\n        var parsedSpec = splitConstraint(spec);\n        if (! compiler.isIsobuildFeaturePackage(parsedSpec.package)) {\n          packages[parsedSpec.package] = true;\n        }\n      });\n    });\n    return _.keys(packages);\n  },\n\n  // Returns an array of objects, representing this package's public\n  // exports. Each object has the following keys:\n  //  - name: export name (ex: \"Accounts\")\n  //  - arch: an array of strings representing architectures for which this\n  //    export is declared.\n  //\n  // This ignores testOnly exports.\n  getExports: function () {\n    var self = this;\n    var ret = {};\n    // Go over all of the architectures, and aggregate the exports together.\n    _.each(self.architectures, function (arch) {\n      _.each(arch.declaredExports, function (exp) {\n        // Skip testOnly exports -- the flag is intended for use in testing\n        // only, so it is not of any interest outside this package.\n        if (exp.testOnly) {\n          return;\n        }\n        // Add the export to the export map.\n        if (! _.has(ret, exp.name)) {\n          ret[exp.name] = [arch.arch];\n        } else {\n          ret[exp.name].push(arch.arch);\n        }\n     });\n    });\n    return _.map(ret, function (arches, name) {\n      return { name: name, architectures: arches };\n    });\n   },\n\n  // Processes the documentation provided in Package.describe. Returns an object\n  // with the following keys:\n  //   - path: full filepath to the Readme file\n  //   - excerpt: the subsection between the first and second heading of the\n  //     Readme, to be used as a longform package description.\n  //   - hash: hash of the full text of this Readme, or \"\" if the Readme is\n  //     blank.\n  //\n  // Returns null if the documentation is marked as null, or throws a\n  // buildmessage error if the documentation could not be read.\n  //\n  // This function reads and performs string operations on a (potentially) long\n  // file. We do not call it unless we actually need this information.\n  processReadme: function () {\n    var self = this;\n    buildmessage.assertInJob();\n    if (! self.metadata.documentation) {\n      return null;\n    }\n\n    // To ensure atomicity, we want to copy the README to a temporary file.\n    var ret = {};\n    ret.path =\n      files.pathJoin(self.sourceRoot, self.metadata.documentation);\n    // Read in the text of the Readme.\n    try {\n      var fullReadme = files.readFile(ret.path);\n    } catch (err) {\n      var errorMessage = \"\";\n      if (err.code === \"ENOENT\") {\n        // This is the most likely and common case, especially when we are\n        // inferring the docs as a default value.\n        errorMessage = \"Documentation not found: \" + self.metadata.documentation;\n      } else {\n        // This is weird, and we don't usually protect the user from errors like\n        // this, but maybe we should.\n        errorMessage =\n          \"Documentation couldn't be read: \" + self.metadata.documentation + \" \";\n        errorMessage += \"(Error: \" + err.message + \")\";\n      }\n\n      // The user might not understand that we are automatically inferring\n      // README.md as the docs! If they want to avoid pushing anything, explain\n      // how to do that.\n      if (! self.docsExplicitlyProvided) {\n        errorMessage += \"\\n\" +\n          \"If you don't want to publish any documentation, \" +\n          \"please set 'documentation: null' in Package.describe\";\n      }\n      buildmessage.error(errorMessage);\n      // Recover by returning null\n      return null;\n    }\n\n    var text = fullReadme.toString();\n    return {\n      contents: text,\n      hash: utils.sha256(text),\n      excerpt: getExcerptFromReadme(text)\n    };\n  },\n\n  // If dependencies aren't consistent across unibuilds, return false and\n  // also log a buildmessage error if inside a buildmessage job. Else\n  // return true.\n  // XXX: Check that this is used when refactoring is done.\n  _checkCrossUnibuildVersionConstraints: function () {\n    var self = this;\n    return !! self._computeDependencyMetadata({ logError: true });\n  },\n\n  // Compute the return value for getDependencyMetadata, or return\n  // null if there is a dependency that doesn't have the same\n  // constraint across all unibuilds (and, if logError is true, log a\n  // buildmessage error).\n  //\n  // This *DOES* include isobuild:* pseudo-packages!\n  //\n  // For options, see getDependencyMetadata.\n  _computeDependencyMetadata: function (options) {\n    var self = this;\n    options = options || {};\n\n    var dependencies = {};\n    var allConstraints = {}; // for error reporting. package name to array\n    var failed = false;\n\n    _.each(self.architectures, function (arch) {\n      // We need to iterate over both uses and implies, since implied packages\n      // also constitute dependencies.\n      var processUse = function (implied, use) {\n        // We can't really have a weak implies (what does that even mean?) but\n        // we check for that elsewhere.\n        if ((use.weak && options.skipWeak) ||\n            (use.unordered && options.skipUnordered)) {\n          return;\n        }\n\n        if (!_.has(dependencies, use.package)) {\n          dependencies[use.package] = {\n            constraint: null,\n            references: []\n          };\n          allConstraints[use.package] = [];\n        }\n        var d = dependencies[use.package];\n\n        if (use.constraint) {\n          allConstraints[use.package].push(use.constraint);\n\n          if (d.constraint === null) {\n            d.constraint = use.constraint;\n          } else if (d.constraint !== use.constraint) {\n            failed = true;\n          }\n        }\n\n        var reference = {\n          arch: archinfo.withoutSpecificOs(arch.arch)\n        };\n        if (use.weak) {\n          reference.weak = true;\n        }\n        if (use.unordered) {\n          reference.unordered = true;\n        }\n        if (implied) {\n          reference.implied = true;\n        }\n        d.references.push(reference);\n      };\n      _.each(arch.uses, _.partial(processUse, false));\n      _.each(arch.implies, _.partial(processUse, true));\n    });\n\n    _.each(self.pluginInfo, function (info) {\n      _.each(info.use, function (spec) {\n        var parsedSpec = splitConstraint(spec);\n        if (!_.has(dependencies, parsedSpec.package)) {\n          dependencies[parsedSpec.package] = {\n            constraint: null,\n            references: []\n          };\n          allConstraints[parsedSpec.package] = [];\n        }\n        var d = dependencies[parsedSpec.package];\n\n        if (parsedSpec.constraint) {\n          allConstraints[parsedSpec.package].push(parsedSpec.constraint);\n          if (d.constraint === null) {\n            d.constraint = parsedSpec.constraint;\n          } else if (d.constraint !== parsedSpec.constraint) {\n            failed = true;\n          }\n        }\n        d.references.push({arch: 'plugin'});\n      });\n    });\n\n    if (failed && options.logError) {\n      _.each(allConstraints, function (constraints, name) {\n        constraints = _.uniq(constraints);\n        if (constraints.length > 1) {\n          buildmessage.error(\n            \"The version constraint for a dependency must be the same \" +\n              \"at every place it is mentioned in a package. \" +\n              \"'\" + name + \"' is constrained both as \"  +\n              constraints.join(' and ') + \". Change them to match.\");\n          // recover by returning false (the caller had better detect\n          // this and use its own recovery logic)\n        }\n      });\n    }\n\n    return failed ? null : dependencies;\n  },\n\n  displayName() {\n    return this.name === null ? 'the app' : this.name;\n  }\n});\n\nmodule.exports = PackageSource;\n"
  },
  {
    "path": "tools/isobuild/resolver.js",
    "content": "import {\n  isString,\n  isFunction,\n  each,\n  has,\n} from \"underscore\";\n\nimport { readAndWatchFileWithHash } from \"../fs/watch.js\";\nimport { matches as archMatches } from \"../utils/archinfo.js\";\nimport {\n  pathJoin,\n  pathRelative,\n  pathNormalize,\n  pathDirname,\n  statOrNull as realStatOrNull,\n  convertToOSPath,\n  convertToPosixPath,\n} from \"../fs/files.js\";\n\nconst nativeModulesMap = Object.create(null);\nconst nativeNames = Object.keys(process.binding(\"natives\"));\n\n// Node 0.10 does not include process as a built-in module, but later\n// versions of Node do, and we provide a stub for it on the client.\nnativeNames.push(\"process\");\n\nnativeNames.forEach(id => {\n  if (id === \"freelist\" ||\n      id.startsWith(\"internal/\")) {\n    return;\n  }\n\n  // When a native Node module is imported, we register a dependency on a\n  // meteor-node-stubs/deps/* module of the same name, so that the\n  // necessary stub modules will be included in the bundle. This alternate\n  // identifier will not be imported at runtime, but the modules it\n  // depends on are necessary for the original import to succeed.\n  nativeModulesMap[id] =  \"meteor-node-stubs/deps/\" + id;\n});\n\nexport default class Resolver {\n  constructor({\n    sourceRoot,\n    targetArch,\n    extensions = [\".js\", \".json\"],\n    nodeModulesPaths = [],\n    watchSet = null,\n    onPackageJson,\n    onMissing,\n    statOrNull = realStatOrNull,\n  }) {\n    this.sourceRoot = sourceRoot;\n    this.extensions = extensions;\n    this.targetArch = targetArch;\n    this.nodeModulesPaths = nodeModulesPaths;\n    this.watchSet = watchSet;\n    this.onPackageJson = onPackageJson;\n    this.onMissing = onMissing;\n    this.statOrNull = statOrNull;\n\n    this._resolveCache = new Map;\n    this._statCache = new Map;\n    this._pkgJsonCache = new Map;\n  }\n\n  static isTopLevel(id) {\n    return \"./\".indexOf(id.charAt(0)) < 0;\n  }\n\n  static isNative(id) {\n    return has(nativeModulesMap, id);\n  }\n\n  static getNativeStubId(id) {\n    return nativeModulesMap[id] || null;\n  }\n\n  // Resolve the given module identifier to an object { path, stat } or\n  // null, relative to an absolute parent path. The _seenDirPaths\n  // parameter is for internal use only and should be ommitted.\n  resolve(id, absParentPath, _seenDirPaths) {\n    if (! this._resolveCache.has(id)) {\n      this._resolveCache.set(id, Object.create(null));\n    }\n\n    const byParentDir = this._resolveCache.get(id);\n    const absParentDir = pathDirname(absParentPath);\n    if (has(byParentDir, absParentDir)) {\n      return byParentDir[absParentDir];\n    }\n\n    let resolved =\n      this._resolveAbsolute(id, absParentPath) ||\n      this._resolveRelative(id, absParentPath) ||\n      this._resolveNodeModule(id, absParentPath);\n\n    while (resolved && resolved.stat.isDirectory()) {\n      let dirPath = resolved.path;\n      _seenDirPaths = _seenDirPaths || new Set;\n\n      // If the \"main\" field of a package.json file resolves to a\n      // directory we've already considered, then we should not attempt to\n      // read the same package.json file again.\n      if (! _seenDirPaths.has(dirPath)) {\n        _seenDirPaths.add(dirPath);\n        resolved = this._resolvePkgJsonMain(dirPath, _seenDirPaths);\n        if (resolved) {\n          // The _resolvePkgJsonMain call above may have returned a\n          // directory, so continue the loop to make sure we fully resolve\n          // it to a non-directory.\n          continue;\n        }\n      }\n\n      // If we didn't find a `package.json` file, or it didn't have a\n      // resolvable `.main` property, the only possibility left to\n      // consider is that this directory contains an `index.js` module.\n      // This assignment almost always terminates the while loop, because\n      // there's very little chance an `index.js` file will be a\n      // directory. However, in principle it is remotely possible that a\n      // file called `index.js` could be a directory instead of a file.\n      resolved = this._joinAndStat(dirPath, \"index.js\");\n    }\n\n    if (resolved) {\n      resolved.id = convertToPosixPath(\n        convertToOSPath(resolved.path),\n        true\n      );\n    }\n\n    return byParentDir[absParentDir] = resolved;\n  }\n\n  _joinAndStat(...joinArgs) {\n    const joined = pathJoin(...joinArgs);\n    if (this._statCache.has(joined)) {\n      return this._statCache.get(joined);\n    }\n\n    const path = pathNormalize(joined);\n    const exactStat = this.statOrNull(path);\n    const exactResult = exactStat && { path, stat: exactStat };\n    let result = null;\n    if (exactResult && exactStat.isFile()) {\n      result = exactResult;\n    }\n\n    if (! result) {\n      this.extensions.some(ext => {\n        const pathWithExt = path + ext;\n        const stat = this.statOrNull(pathWithExt);\n        if (stat) {\n          return result = { path: pathWithExt, stat };\n        }\n      });\n    }\n\n    if (! result && exactResult && exactStat.isDirectory()) {\n      // After trying all available file extensions, fall back to the\n      // original result if it was a directory.\n      result = exactResult;\n    }\n\n    this._statCache.set(joined, result);\n    return result;\n  }\n\n  _resolveAbsolute(id, absParentPath) {\n    return id.charAt(0) === \"/\" &&\n      this._joinAndStat(this.sourceRoot, id.slice(1));\n  }\n\n  _resolveRelative(id, absParentPath) {\n    if (id.charAt(0) === \".\") {\n      return this._joinAndStat(absParentPath, \"..\", id);\n    }\n  }\n\n  _resolveNodeModule(id, absParentPath) {\n    let resolved = null;\n\n    if (Resolver.isNative(id) &&\n        archMatches(this.targetArch, \"os\")) {\n      // Forbid installing any server module with the same name as a\n      // native Node module.\n      return null;\n    }\n\n    let sourceRoot;\n    const relParentPath = pathRelative(this.sourceRoot, absParentPath);\n    if (! relParentPath.startsWith(\"..\")) {\n      // If the file is contained by this.sourceRoot, then it's safe to\n      // use this.sourceRoot as the limiting ancestor directory in the\n      // while loop below, but we're still going to check whether the file\n      // resides in an external node_modules directory, since \"external\"\n      // .npm/package/node_modules directories are technically contained\n      // within the root directory of their packages.\n      sourceRoot = this.sourceRoot;\n    }\n\n    this.nodeModulesPaths.some(path => {\n      if (! pathRelative(path, absParentPath).startsWith(\"..\")) {\n        // If the file is inside an external node_modules directory,\n        // consider the rootDir to be the parent directory of that\n        // node_modules directory, rather than this.sourceRoot.\n        return sourceRoot = pathDirname(path);\n      }\n    });\n\n    if (sourceRoot) {\n      let dir = absParentPath; // It's ok for absParentPath to be a directory!\n      let info = this._joinAndStat(dir);\n      if (! info || ! info.stat.isDirectory()) {\n        dir = pathDirname(dir);\n      }\n\n      while (! (resolved = this._joinAndStat(dir, \"node_modules\", id))) {\n        if (dir === sourceRoot) {\n          break;\n        }\n\n        const parentDir = pathDirname(dir);\n        if (dir === parentDir) {\n          // We've reached the root of the file system??\n          break;\n        }\n\n        dir = parentDir;\n      }\n    }\n\n    if (! resolved) {\n      // After checking any local node_modules directories, fall back to\n      // the package NPM directory, if one was specified.\n      this.nodeModulesPaths.some(path => {\n        return resolved = this._joinAndStat(path, id);\n      });\n    }\n\n    if (! resolved && isFunction(this.onMissing)) {\n      return this.onMissing(id, absParentPath);\n    }\n\n    // If the dependency is still not resolved, it might be handled by the\n    // fallback function defined in meteor/packages/modules/modules.js, or\n    // it might be imported in code that will never run on this platform,\n    // so there is always the possibility that its absence is not actually\n    // a problem. As much as we might like to issue warnings about missing\n    // dependencies here, we just don't have enough information to make\n    // that determination until the code actually runs.\n\n    return resolved;\n  }\n\n  _readPkgJson(path) {\n    if (this._pkgJsonCache.has(path)) {\n      return this._pkgJsonCache.get(path);\n    }\n\n    let result = null;\n    try {\n      result = JSON.parse(\n        readAndWatchFileWithHash(this.watchSet, path).contents);\n    } catch (e) {\n      if (! (e instanceof SyntaxError ||\n             e.code === \"ENOENT\")) {\n        throw e;\n      }\n    }\n\n    this._pkgJsonCache.set(path, result);\n    return result;\n  }\n\n  _resolvePkgJsonMain(dirPath, _seenDirPaths) {\n    const pkgJsonPath = pathJoin(dirPath, \"package.json\");\n    const pkg = this._readPkgJson(pkgJsonPath);\n    if (! pkg) {\n      return null;\n    }\n\n    let main = pkg.main;\n\n    if (archMatches(this.targetArch, \"web\") &&\n        isString(pkg.browser)) {\n      main = pkg.browser;\n    }\n\n    // Output a JS module that exports just the \"name\", \"version\", and\n    // \"main\" properties defined in the package.json file.\n    const pkgSubset = {\n      name: pkg.name,\n    };\n\n    if (has(pkg, \"version\")) {\n      pkgSubset.version = pkg.version;\n    }\n\n    if (isString(main)) {\n      pkgSubset.main = main;\n    }\n\n    if (isFunction(this.onPackageJson)) {\n      this.onPackageJson(pkgJsonPath, pkgSubset);\n    }\n\n    if (isString(main)) {\n      // The \"main\" field of package.json does not have to begin with ./\n      // to be considered relative, so first we try simply appending it to\n      // the directory path before falling back to a full resolve, which\n      // might return a package from a node_modules directory.\n      return this._joinAndStat(dirPath, main) ||\n        // The _tryToResolveImportedPath method takes a file object as its\n        // first parameter, but only the .sourcePath and .deps properties\n        // are ever used, so we can get away with passing a fake file\n        // object with only those properties.\n        this.resolve(\n          main,\n          pkgJsonPath,\n          _seenDirPaths\n        );\n    }\n\n    return null;\n  }\n};\n\nimport { Profile } from \"../tool-env/profile.js\";\neach(Resolver.prototype, (value, key) => {\n  if (key === \"constructor\") return;\n  Resolver.prototype[key] = Profile(\n    `Resolver#${key}`,\n    Resolver.prototype[key]\n  );\n});\n"
  },
  {
    "path": "tools/isobuild/source-arch.js",
    "content": "import {isString, isFunction} from 'underscore';\nimport {WatchSet} from '../fs/watch.js';\n\nfunction reportMissingOption(name) {\n  throw new Error(`must provide options.${name} when creating SourceArch`);\n}\n\n/**\n * SourceArch\n *\n * Used in ./package-source.js.\n */\nexport default class SourceArch {\n  constructor(pkg, {\n    kind, // required\n    arch, // required\n    sourceRoot, // required\n    getFiles, // required\n    uses = [],\n    implies = [],\n    declaredExports = null,\n    // Do not include the source files in watchSet. They will be added at\n    // compile time when the sources are actually read.\n    watchSet = new WatchSet(),\n  }) {\n    isString(kind) || reportMissingOption('kind');\n    isString(arch) || reportMissingOption('arch');\n    isString(sourceRoot) || reportMissingOption('sourceRoot');\n    isFunction(getFiles) || reportMissingOption('getFiles');\n\n    this.pkg = pkg;\n\n    // Kind of this sourceArchitecture. At the moment, there are really\n    // three options -- package, plugin, and app. We use these in linking.\n    this.kind = kind;\n\n    // The architecture (fully or partially qualified) that can use this\n    // unibuild.\n    this.arch = arch;\n\n    // Absolute path of the root directory of this package or application.\n    this.sourceRoot = sourceRoot;\n\n    // Packages used. The ordering is significant only for determining\n    // import symbol priority (it doesn't affect load order), and a given\n    // package could appear more than once in the list, so code that\n    // consumes this value will need to guard appropriately. Each element\n    // in the array has keys:\n    // - package: the package name\n    // - constraint: the constraint on the version of the package to use,\n    //   as a string (may be null)\n    // - unordered: If true, we don't want the package's imports and we\n    //   don't want to force the package to load before us. We just want\n    //   to ensure that it loads if we load.\n    // - weak: If true, we don't *need* to load the other package, but\n    //   if the other package ends up loaded in the target, it must\n    //   be forced to load before us. We will not get its imports\n    //   or plugins.\n    // It is an error for both unordered and weak to be true, because such\n    // a dependency would have no effect.\n    //\n    // In most places, instead of using 'uses' directly, you want to use\n    // something like compiler.eachUsedUnibuild so you also take into\n    // account implied packages.\n    //\n    // Note that if `package` starts with 'isobuild:', it actually\n    // represents a dependency on a feature of the Isobuild build tool,\n    // not a real package. You need to be aware of this when processing a\n    // `uses` array, which is another reason to use eachUsedUnibuild\n    // instead.\n    this.uses = uses;\n\n    // Packages which are \"implied\" by using this package. If a unibuild X\n    // uses this unibuild Y, and Y implies Z, then X will effectively use\n    // Z as well (and get its imports and plugins).  An array of objects\n    // of the same type as the elements of this.uses (although for now\n    // unordered and weak are not allowed).\n    this.implies = implies;\n\n    // A function that returns the source files for this\n    // architecture. Object with keys `sources` and `assets`, where each\n    // is an array of objects with keys \"relPath\" and \"fileOptions\". Null\n    // if loaded from isopack.\n    //\n    // fileOptions is optional and represents arbitrary options passed to\n    // \"api.addFiles\"; they are made available on to the plugin as\n    // compileStep.fileOptions.\n    //\n    // This is a function rather than a literal array because for an app,\n    // we need to know the file extensions registered by the plugins in\n    // order to compute the sources list, so we have to wait until build\n    // time (after we have loaded any plugins, including local plugins in\n    // this package) to compute this.\n    this.getFiles = getFiles;\n\n    // Object whose keys are relative paths of local node_modules\n    // directories in this package or application, for the given\n    // architecture. Does not include the .npm/package/node_modules\n    // directory installed by Npm.depends. Should be populated when\n    // getFiles is called.\n    this.localNodeModulesDirs = Object.create(null);\n\n    // Symbols that this architecture should export. List of symbols (as\n    // strings).\n    this.declaredExports = declaredExports;\n\n    // Files and directories that we want to monitor for changes in\n    // development mode, as a watch.WatchSet. In the latest refactoring of\n    // the code, this does not include source files or directories, but\n    // only control files such as package.js and .meteor/packages, since\n    // the rest are not determined until compile time.\n    this.watchSet = watchSet;\n  }\n}\n"
  },
  {
    "path": "tools/isobuild/test-files.js",
    "content": "import _ from 'underscore';\nimport { pathSep } from '../fs/files';\n\n// We have two things \"tests\" and \"app-tests\".\nexport const TEST_FILENAME_REGEXPS = [\n  // \"*.test[s].*\" or \"*.spec[s].*\"\n  /\\.tests?./,\n  /\\.specs?./,\n];\n\nexport const APP_TEST_FILENAME_REGEXPS = [\n  // \"*.app-tests.*\" or \"*.app-specs.*\"\n  /\\.app-tests?./,\n  /\\.app-specs?./,\n];\n\n// Given a path to a file in an app (relative to the app root\n// directory), is this file a test file?\nexport function isTestFilePath(path) {\n  const splitPath = path.split(pathSep);\n\n  // Does the filename match one of the test filename forms?\n  return _.any(\n    [...TEST_FILENAME_REGEXPS, ...APP_TEST_FILENAME_REGEXPS],\n    regexp => regexp.test(_.last(splitPath)));\n}\n"
  },
  {
    "path": "tools/meteor-services/README.md",
    "content": "# Meteor Services\n\nFiles in this folder implement the features related to the Meteor-provided\nservices, such as:\n\n- Meteor Developer Accounts\n- Meteor's Free Deployments\n- Package Server\n- Build Farms\n\nAll of the services are connected to through DDP from tool.\n"
  },
  {
    "path": "tools/meteor-services/auth-client.js",
    "content": "var auth = require('./auth.js');\nvar Console = require('../console/console.js').Console;\nvar ServiceConnection = require('./service-connection.js');\nvar httpHelpers = require('../utils/http-helpers.js');\n\nexports.AlreadyPrintedMessageError = function () {};\n\n// Opens a DDP connection to a package server. Loads the packages needed for a\n// DDP connection, then calls DDP connect to the package server URL in config,\n// using a current user-agent header composed by http-helpers.js.\nexports.openServiceConnection = function (serverUrl) {\n  return new ServiceConnection(\n    serverUrl,\n    {headers: {\"User-Agent\": httpHelpers.getUserAgent()},\n     _dontPrintErrors: true});\n};\n\n\n// Handle an error thrown on attempting to connect. Print a message if it is a\n// known error type, else throw the error.\n//\n// err: error\n// label: name of the service that we are trying to use (ex: \"package server\")\nexports.handleConnectionError = function (error, label) {\n  if (error instanceof exports.AlreadyPrintedMessageError) {\n    // do nothing\n  } else if (error.errorType === 'Meteor.Error') {\n    var errorMsg = \"Error from \" + label;\n    if (error.message) {\n      errorMsg += \": \" + error.message;\n    }\n    Console.warn(errorMsg);\n  } else if (error.errorType === \"DDP.ConnectionError\") {\n    Console.warn(\"Error connecting to \" + label + \": \"\n                 + error.message);\n  } else {\n    throw error;\n  }\n};\n\n// Returns a logged-in DDP connection to the given URL, or null if\n// we cannot log in. If an error unrelated to login occurs\n// (e.g. connection to package server times out), then it will be\n// thrown.\n//\n//  url: the url of the connection (ex: config.getPackageServerUrl)\n//  domain: the domain (ex: packages.meteor.com)\n//  sessionType: the name of the connection (ex: \"package-server\")\n//\nexports.loggedInConnection = function (url, domain, sessionType) {\n  // Make sure that we are logged in with Meteor Accounts so that we can\n  // do an OAuth flow.\n  if (auth.maybePrintRegistrationLink({onlyAllowIfRegistered: true})) {\n    // Oops, we're logged in but with a deferred-registration account.\n    // Message has already been printed.\n    throw new exports.AlreadyPrintedMessageError;\n  }\n\n  if (! auth.isLoggedIn()) {\n    // XXX we should have a better account signup page.\n    Console.error(\n      \"Please log in with your Meteor developer account.\",\n      \"If you don't have one,\",\n      \"you can quickly create one at www.meteor.com.\");\n    auth.doUsernamePasswordLogin({ retry: true });\n  }\n\n  var conn = exports.openServiceConnection(url);\n  var accountsConfiguration = auth.getAccountsConfiguration(conn);\n  try {\n    auth.loginWithTokenOrOAuth(\n      conn,\n      accountsConfiguration,\n      url,\n      domain,\n      sessionType\n    );\n  } catch (err) {\n    if (err.message === \"access-denied\") {\n      // Maybe we thought we were logged in, but our token had been\n      // revoked.\n      Console.error(\n        \"It looks like you have been logged out!\",\n        \"Please log in with your Meteor developer account. If you don't have\",\n        \"one, you can quickly create one at www.meteor.com.\");\n      auth.doUsernamePasswordLogin({ retry: true });\n      auth.loginWithTokenOrOAuth(\n        conn,\n        accountsConfiguration,\n        url,\n        domain,\n        sessionType\n      );\n    } else {\n      throw err;\n    }\n  }\n  return conn;\n};\n"
  },
  {
    "path": "tools/meteor-services/auth.js",
    "content": "var _ = require('underscore');\nvar utils = require('../utils/utils.js');\nvar files = require('../fs/files.js');\nvar config = require('./config.js');\nvar httpHelpers = require('../utils/http-helpers.js');\nvar fiberHelpers = require('../utils/fiber-helpers.js');\nvar querystring = require('querystring');\nvar url = require('url');\nvar isopackets = require('../tool-env/isopackets.js');\nvar Console = require('../console/console.js').Console;\n\nvar auth = exports;\n\nvar getLoadedPackages = function () {\n  return isopackets.load('ddp');\n};\n\n// Opens and returns a DDP connection to the accounts server. Remember\n// to close it when you're done with it!\nvar openAccountsConnection = function () {\n  var DDP = getLoadedPackages()['ddp-client'].DDP;\n  return DDP.connect(config.getAuthDDPUrl(), {\n    headers: { 'User-Agent': httpHelpers.getUserAgent() }\n  });\n};\n\n// Returns a function that runs `f`, appending an additional argument\n// that is a connection to the accounts server, which gets closed when\n// `f` returns or throws.\nvar withAccountsConnection = function (f) {\n  return function (...args) {\n    var self = this;\n    var conn = openAccountsConnection();\n    args.push(conn);\n    try {\n      var result = f.apply(self, args);\n    } finally {\n      conn.close();\n    }\n    return result;\n  };\n};\n\n// Open a DDP connection to the accounts server and log in using the\n// provided token. Returns the connection, or null if login fails.\n//\n// XXX if we reconnect we won't reauthenticate. Fix that before using\n// this for long-lived connections.\nvar loggedInAccountsConnection = function (token) {\n  var connection = getLoadedPackages()['ddp-client'].DDP.connect(\n    config.getAuthDDPUrl()\n  );\n\n  return new Promise(function (resolve, reject) {\n    connection.apply(\n      'login',\n      [{ resume: token }],\n      { wait: true },\n      function (err) {\n        err ? reject(err) : resolve(connection);\n      }\n    );\n\n  }).catch(function (err) {\n    connection.close();\n\n    if (err.error === 403) {\n      // This is not an ideal value for the error code, but it means\n      // \"server rejected our access token\". For example, it expired\n      // or we revoked it from the web.\n      return null;\n    }\n\n    // Something else went wrong\n    throw err;\n\n  }).await();\n};\n\n// The accounts server has some wrapped methods that take and return\n// session identifiers. To call these methods, we add our current\n// session identifier (or null, if we don't have one) as the last\n// argument to the method. The accounts server returns an object with\n// keys 'result' (the actual method result) and 'session' (the new\n// session identifier we should use, if it created a new session for\n// us).\n// options can include:\n//  - timeout: a timeout after which an exception will be thrown if the\n//    method hasn't returned yet\n//  - connection: an open connection to the accounts server. If not\n//    provided, one will be opened and then closed before returning.\nvar sessionMethodCaller = function (methodName, options) {\n  options = options || {};\n  return function (...args) {\n    args.push({\n      session: auth.getSessionId(config.getAccountsDomain()) || null\n    });\n\n    var timer;\n    var conn = options.connection || openAccountsConnection();\n\n    function cleanUp() {\n      timer && clearTimeout(timer);\n      options.connection || conn.close();\n    }\n\n    return new Promise(function (resolve, reject) {\n      conn.apply(methodName, args, function (err, res) {\n        err ? reject(err) : resolve(res);\n      });\n\n      if (options.timeout !== undefined) {\n        timer = setTimeout(function () {\n          reject(new Error('Method call timed out'));\n        }, options.timeout);\n      }\n\n    }).then(function (result) {\n      cleanUp();\n\n      if (result) {\n        if (result.session) {\n          // The bindEnvironment call above ensures the file IO operations\n          // that happen in auth.setSessionId take place in a Fiber.\n          auth.setSessionId(config.getAccountsDomain(), result.session);\n        }\n        result = result.result;\n      }\n\n      return result;\n\n    }, function (err) {\n      cleanUp();\n      throw err;\n\n    }).await();\n  };\n};\n\nvar readSessionData = function () {\n  var sessionPath = config.getSessionFilePath();\n  if (! files.exists(sessionPath)) {\n    return {};\n  }\n  return JSON.parse(files.readFile(sessionPath, { encoding: 'utf8' }));\n};\n\nvar writeSessionData = function (data) {\n  var sessionPath = config.getSessionFilePath();\n\n  var tries = 0;\n  while (true) {\n    if (tries++ > 10) {\n      throw new Error(\"can't find a unique name for temporary file?\");\n    }\n\n    // Create a temporary file in the same directory where we\n    // ultimately want to write the session file. Use the exclusive\n    // flag to atomically ensure that the file doesn't exist, create\n    // it, and make it readable and writable only by the current\n    // user (mode 0600).\n    var tempPath =\n          files.pathJoin(files.pathDirname(sessionPath), '.meteorsession.' +\n                    Math.floor(Math.random() * 999999));\n    try {\n      var fd = files.open(tempPath, 'wx', 0o600);\n    } catch (e) {\n      continue;\n    }\n\n    try {\n      // Write `data` to the file.\n      var buf = new Buffer(JSON.stringify(data, undefined, 2), 'utf8');\n      files.write(fd, buf, 0, buf.length, 0);\n    } finally {\n      files.close(fd);\n    }\n\n    // Atomically remove the old file (if any) and replace it with\n    // the temporary file we just created.\n    files.rename(tempPath, sessionPath);\n    return;\n  }\n};\n\nvar getSession = function (sessionData, domain) {\n  if (typeof (sessionData.sessions) !== \"object\") {\n    sessionData.sessions = {};\n  }\n  if (typeof (sessionData.sessions[domain]) !== \"object\") {\n    sessionData.sessions[domain] = {};\n  }\n  return sessionData.sessions[domain];\n};\n\n// types:\n// - \"meteor-account\": a login to your Meteor Account\n// We previously used:\n// - \"galaxy\": a login to a legacy Galaxy prototype server\nvar ensureSessionType = function (session, type) {\n  if (! _.has(session, 'type')) {\n    session.type = type;\n  } else if (session.type !== type) {\n    // Blow away whatever was there. We lose pendingRevokes but that's\n    // OK since this should never happen in normal operation. (It\n    // would happen if the Meteor Accounts server mode somewhere else\n    // and a Galaxy was deployed at its old address, for example).\n    _.each(_.keys(session), function (key) {\n      delete session[key];\n    });\n    session.type = type;\n  }\n};\n\nvar writeMeteorAccountsUsername = function (username) {\n  var data = readSessionData();\n  var session = getSession(data, config.getAccountsDomain());\n  session.username = username;\n  writeSessionData(data);\n};\n\n// Given an object 'data' in the format returned by readSessionData,\n// modify it to make the user logged out.\nvar logOutAllSessions = function (data) {\n  _.each(data.sessions, function (session, domain) {\n    logOutSession(session);\n  });\n};\n\n// As logOutAllSessions, but for a session on a particular domain\n// rather than all sessions.\nvar logOutSession = function (session) {\n  var crypto = require('crypto');\n\n  delete session.username;\n  delete session.userId;\n  delete session.registrationUrl;\n\n  if (_.has(session, 'token')) {\n    if (! (session.pendingRevoke instanceof Array)) {\n      session.pendingRevoke = [];\n    }\n\n    // Delete the auth token itself, but save the tokenId, which is\n    // useless for authentication. The next time we're online, we'll\n    // send the tokenId to the server to revoke the token on the\n    // server side too.\n    if (typeof session.tokenId === \"string\") {\n      session.pendingRevoke.push(session.tokenId);\n    }\n    delete session.token;\n    delete session.tokenId;\n  }\n};\n\n// Given an object 'data' in the format returned by readSessionData,\n// return true if logged in, else false.\nvar loggedIn = function (data) {\n  return !! getSession(data, config.getAccountsDomain()).userId;\n};\n\n// Given an object 'data' in the format returned by readSessionData,\n// return the currently logged in user, or null if not logged in or if\n// the logged in user doesn't have a username.\nvar currentUsername = function (data) {\n  var sessionData = getSession(data, config.getAccountsDomain());\n  return sessionData.username || null;\n};\n\nvar removePendingRevoke = function (domain, tokenIds) {\n  var data = readSessionData();\n  var session = getSession(data, domain);\n  session.pendingRevoke = _.difference(session.pendingRevoke, tokenIds);\n  if (! session.pendingRevoke.length) {\n    delete session.pendingRevoke;\n  }\n  writeSessionData(data);\n};\n\n// If there are any logged out (pendingRevoke) tokens that haven't\n// been sent to the server for revocation yet, try to send\n// them. Reads the session file and then writes it back out to\n// disk. If the server can't be contacted, fail silently (and leave\n// the pending invalidations in the session file for next time).\n//\n// options:\n//  - timeout: request timeout in milliseconds\n//  - firstTry: cosmetic. set to true if we recently logged out a\n//    session. just changes the error message.\n//  - connection: an open connection to the accounts server. If not\n//    provided, this function will open one itself.\nvar tryRevokeOldTokens = function (options) {\n  options = _.extend({\n    timeout: 5000\n  }, options || {});\n\n  var warned = false;\n  var domainsWithRevokedTokens = [];\n  _.each(readSessionData().sessions || {}, function (session, domain) {\n    if (session.pendingRevoke &&\n        session.pendingRevoke.length) {\n      domainsWithRevokedTokens.push(domain);\n    }\n  });\n\n  var logoutFailWarning = function (domain) {\n    if (! warned) {\n      // This isn't ideal but is probably better that saying nothing at all\n      Console.error(\"warning: \" +\n                    (options.firstTry ?\n                    \"couldn't\" : \"still trying to\") +\n                     \" confirm logout with \" + domain);\n      warned = true;\n    }\n  };\n\n  _.each(domainsWithRevokedTokens, function (domain) {\n    var data = readSessionData();\n    var session = data.sessions[domain] || {};\n    var tokenIds = session.pendingRevoke || [];\n    if (! tokenIds.length) {\n      return;\n    }\n\n    var url;\n\n\n    if (session.type === \"meteor-account\") {\n      try {\n        sessionMethodCaller('revoke', {\n          timeout: options.timeout,\n          connection: options.connection\n        })(tokenIds);\n        removePendingRevoke(domain, tokenIds);\n      } catch (err) {\n        logoutFailWarning(domain);\n      }\n      return;\n    } else if (session.type === \"galaxy\") {\n      // These are tokens from a legacy Galaxy prototype, which cannot be\n      // revoked (because the prototype no longer exists), but we can at least\n      // remove them from the file.\n      removePendingRevoke(domain, tokenIds);\n    } else {\n      // don't know how to revoke tokens of this type\n      logoutFailWarning(domain);\n      return;\n    }\n  });\n};\n\nvar sendAuthorizeRequest = function (clientId, redirectUri, state) {\n  var authCodeUrl = config.getOauthUrl() + \"/authorize?\" +\n        querystring.stringify({\n          state: state,\n          response_type: \"code\",\n          client_id: clientId,\n          redirect_uri: redirectUri\n        });\n\n  // It's very important that we don't have request follow the\n  // redirect for us, but instead issue the second request ourselves,\n  // since request would pass our credentials along to the redirected\n  // URL. See comments in http-helpers.js.\n  var codeResult = httpHelpers.request({\n    url: authCodeUrl,\n    method: 'POST',\n    strictSSL: true,\n    useAuthHeader: true\n  });\n\n  var response = codeResult.response;\n  if (response.statusCode !== 302 || ! response.headers.location) {\n    throw new Error('access-denied');\n  }\n\n  if (url.parse(response.headers.location).hostname !==\n      url.parse(redirectUri).hostname) {\n    // If we didn't get an immediate redirect to the redirectUri then\n    // presumably the oauth server is trying to interact with us (make\n    // us log in, authorize the client, or something like that). We're\n    // not a web browser so we can't participate in such things.\n    throw new Error('access-denied');\n  }\n\n  return { location: response.headers.location };\n};\n\n// Do an OAuth flow with the Meteor developer accounts server to log in\n// to an OAuth client. `conn` is expected to be a DDP connection to the\n// OAuth client app. Options are:\n//  - clientId: OAuth client id parameter\n//  - redirectUri: OAuth redirect_uri parameter\n//  - domain: the domain for saving the received login token on success\n//    in the Meteor session file\n//  - sessionType: the value of the 'type' field for the session saved\n//    in the Meteor session file on success\n// All options are required.\n//\n// Throws an error if the login is not successful.\nvar oauthFlow = function (conn, options) {\n  var crypto = require('crypto');\n  var credentialToken = crypto.randomBytes(16).toString('hex');\n\n  var authorizeResult = sendAuthorizeRequest(\n    options.clientId,\n    options.redirectUri,\n    credentialToken\n  );\n\n  // XXX We're using a test-only flag here to just get the raw\n  // credential secret (instead of a bunch of code that communicates the\n  // credential secret somewhere else); this should be temporary until\n  // we give this a nicer name and make it not just test only.\n  var redirectResult = httpHelpers.request({\n    url: authorizeResult.location + '&only_credential_secret_for_test=1',\n    method: 'GET',\n    strictSSL: true\n  });\n\n  var response = redirectResult.response;\n  // 'access-denied' isn't exactly right because it's possible that the server\n  // went down since our last request, but close enough.\n\n  if (response.statusCode !== 200) {\n    throw new Error('access-denied');\n  }\n\n  // XXX tokenId???\n  var loginResult = conn.apply('login', [{\n    oauth: {\n      credentialToken: credentialToken,\n      credentialSecret: response.body\n    }\n  }], { wait: true });\n\n  if (loginResult.token && loginResult.id) {\n    var data = readSessionData();\n    var session = getSession(data, options.domain);\n    ensureSessionType(session, options.sessionType);\n    session.token = loginResult.token;\n    writeSessionData(data);\n    return true;\n  } else {\n    throw new Error('login-failed');\n  }\n};\n\n// Prompt the user for a password, and then log in. Returns true if a\n// successful login was accomplished, else false.\n//\n// Options should include either 'email' or 'username', and may also\n// include:\n// - retry: if true, then if the user gets the password wrong,\n//   reprompt.\n// - suppressErrorMessage: true if the function should not print an\n//   error message to stderr if the login fails\n// - connection: an open connection to the accounts server. If not\n//   provided, this function will open its own connection.\nvar doInteractivePasswordLogin = function (options) {\n  var loginData = {};\n\n  if (_.has(options, 'username')) {\n    loginData.username = options.username;\n  } else if (_.has(options, 'email')) {\n    loginData.email = options.email;\n  } else {\n    throw new Error(\"Need username or email\");\n  }\n\n  if (_.has(options, 'password')) {\n    loginData.password = options.password;\n  }\n\n  var loginFailed = function () {\n    if (! options.suppressErrorMessage) {\n      Console.error(\"Login failed.\");\n    }\n  };\n\n  var conn = options.connection || openAccountsConnection();\n\n  var maybeCloseConnection = function () {\n    if (! options.connection) {\n      conn.close();\n    }\n  };\n\n  while (true) {\n    if (! _.has(loginData, 'password')) {\n      loginData.password = Console.readLine({\n        echo: false,\n        prompt: \"Password: \",\n        stream: process.stderr\n      });\n    }\n\n    try {\n      var result = conn.call('login', {\n        session: auth.getSessionId(config.getAccountsDomain()),\n        meteorAccountsLoginInfo: loginData,\n        clientInfo: utils.getAgentInfo()\n      });\n    } catch (err) {\n    }\n    if (result && result.token) {\n      break;\n    } else {\n      loginFailed();\n      if (options.retry) {\n        Console.error();\n        continue;\n      } else {\n        maybeCloseConnection();\n        return false;\n      }\n    }\n  }\n\n  if (result.session) {\n    auth.setSessionId(config.getAccountsDomain(), result.session);\n  }\n\n  var data = readSessionData();\n  logOutAllSessions(data);\n  var session = getSession(data, config.getAccountsDomain());\n  ensureSessionType(session, \"meteor-account\");\n  session.username = result.username;\n  session.userId = result.id;\n  session.token = result.token;\n  session.tokenId = result.tokenId;\n  writeSessionData(data);\n  maybeCloseConnection();\n  return true;\n};\n\n// options are the same as for doInteractivePasswordLogin, except without\n// username and email.\nexports.doUsernamePasswordLogin = function (options) {\n  var username;\n\n  do {\n    username = Console.readLine({\n      prompt: \"Username: \",\n      stream: process.stderr\n    }).trim();\n  } while (username.length === 0);\n\n  return doInteractivePasswordLogin(_.extend({}, options, {\n    username: username\n  }));\n};\n\nexports.doInteractivePasswordLogin = doInteractivePasswordLogin;\n\nexports.loginCommand = withAccountsConnection(function (options,\n                                                        connection) {\n  var data = readSessionData();\n\n  if (! getSession(data, config.getAccountsDomain()).token ||\n       options.overwriteExistingToken) {\n    var loginOptions = {};\n\n    if (options.email) {\n      loginOptions.email = Console.readLine({\n        prompt: \"Email: \",\n        stream: process.stderr\n      });\n    } else {\n      loginOptions.username = Console.readLine({\n        prompt: \"Username: \",\n        stream: process.stderr\n      });\n    }\n\n    loginOptions.connection = connection;\n\n    if (! doInteractivePasswordLogin(loginOptions)) {\n      return 1;\n    }\n  }\n\n  tryRevokeOldTokens({ firstTry: true, connection: connection });\n\n  data = readSessionData();\n  Console.error();\n  Console.error(\"Logged in\" +\n                (currentUsername(data) ? \" as \" + currentUsername(data) : \"\") +\n                \". Thanks for being a Meteor developer!\");\n  return 0;\n});\n\nexports.logoutCommand = function (options) {\n  var data = readSessionData();\n  var wasLoggedIn = !! loggedIn(data);\n  logOutAllSessions(data);\n  writeSessionData(data);\n\n  tryRevokeOldTokens({ firstTry: true });\n\n  if (wasLoggedIn) {\n    Console.error(\"Logged out.\");\n  } else {\n    // We called logOutAllSessions/writeSessionData anyway, out of an\n    // abundance of caution.\n    Console.error(\"Not logged in.\");\n  }\n};\n\n// If this is fully set up account (with a username and password), or\n// if not logged in, do nothing. If it is an account without a\n// username, contact the server and see if the user finished setting\n// it up, and if so grab and save the username. But contact the server\n// only once per run of the program. Options:\n//  - noLogout: boolean. Set to true if you don't want this function to\n//    log out the session if wehave an invalid credential (for example,\n//    if a caller wants to do its own error handling for invalid\n//    credentials). Defaults to false.\nvar alreadyPolledForRegistration = false;\nexports.pollForRegistrationCompletion = function (options) {\n  if (alreadyPolledForRegistration) {\n    return;\n  }\n  alreadyPolledForRegistration = true;\n\n  options = options || {};\n\n  var data = readSessionData();\n  var session = getSession(data, config.getAccountsDomain());\n  if (session.username || ! session.token) {\n    return;\n  }\n\n  // We are logged in but we don't yet have a username. Ask the server\n  // if a username was chosen since we last checked.\n  var username = null;\n  var connection = loggedInAccountsConnection(session.token);\n  var timer;\n\n  if (! connection) {\n    // Server says our credential isn't any good anymore! Get rid of\n    // it. Note that, out of an abundance of caution, this also will\n    // enqueue the credential for invalidation (on a future run, we\n    // will try to explicitly revoke the credential ourselves).\n    if (! options.noLogout) {\n      logOutSession(session);\n      writeSessionData(data);\n    }\n    return;\n  }\n\n  new Promise(function (resolve) {\n    connection.call('getUsername', function (err, username) {\n      // If anything went wrong, return null just as we would have if we\n      // hadn't bothered to ask the server.\n      resolve(err ? null : username);\n    });\n\n    timer = setTimeout(function () {\n      resolve(null);\n    }, 5000);\n\n  // Intentionally calling bindEnvironment on the .then callback rather\n  // than the function that calls resolve.\n  }).then(fiberHelpers.bindEnvironment(function (username) {\n    connection.close();\n    clearTimeout(timer);\n\n    if (username) {\n      writeMeteorAccountsUsername(username);\n    }\n\n  // We don't actually care about the result, just that the side-effects\n  // of writeMeteorAccountsUsername happen.\n  })).await();\n};\n\nexports.registrationUrl = function () {\n  var data = readSessionData();\n  var url = getSession(data, config.getAccountsDomain()).registrationUrl;\n  return url;\n};\n\nexports.whoAmICommand = function (options) {\n  auth.pollForRegistrationCompletion();\n\n  var data = readSessionData();\n  if (! loggedIn(data)) {\n    Console.error(\n      \"Not logged in. \" + Console.command(\"'meteor login'\") + \" to log in.\");\n    return 1;\n  }\n\n  var username = currentUsername(data);\n  if (username) {\n    Console.rawInfo(username + \"\\n\");\n    return 0;\n  }\n\n  var url = getSession(data, config.getAccountsDomain()).registrationUrl;\n  if (url) {\n    Console.error(\"You haven't chosen your username yet. To pick it, go here:\");\n    Console.error();\n    Console.error(Console.url(url));\n  } else {\n    // Won't happen in normal operation\n    Console.error(\"You haven't chosen your username yet.\");\n  }\n\n  return 1;\n};\n\n// Prompt for an email address. If it doesn't belong to a user, create\n// a new deferred registration account and log in as it. If it does,\n// try to log the user into it. Returns true on success (user is now\n// logged in) or false on failure (user gave up, can't talk to\n// network..)\nexports.registerOrLogIn = withAccountsConnection(function (connection) {\n  var result;\n  // Get their email\n  while (true) {\n    var email = Console.readLine({\n      prompt: \"Email: \",\n      stream: process.stderr\n    });\n\n    // Try to register\n    try {\n      var methodCaller = sessionMethodCaller(\n        'tryRegister',\n        { connection: connection }\n      );\n      result = methodCaller(email, utils.getAgentInfo());\n      break;\n    } catch (err) {\n      if (err.error === 400 && ! utils.validEmail(email)) {\n        if (email.trim().length) {\n          Console.error(\"Please double-check that address.\");\n          Console.error();\n        }\n      } else {\n        Console.error(\"\\nCouldn't connect to server. \" +\n                             \"Check your internet connection.\");\n        return false;\n      }\n    }\n  }\n\n  var loginResult;\n\n  if (! result.alreadyExisted) {\n    var data = readSessionData();\n    logOutAllSessions(data);\n    var session = getSession(data, config.getAccountsDomain());\n    ensureSessionType(session, \"meteor-account\");\n    session.token = result.token;\n    session.tokenId = result.tokenId;\n    session.userId = result.userId;\n    session.registrationUrl = result.registrationUrl;\n    writeSessionData(data);\n    return true;\n  } else if (result.alreadyExisted && result.sentRegistrationEmail) {\n    Console.error();\n    Console.error(\n      \"You need to pick a password for your account so that you can log in.\",\n      \"An email has been sent to you with the link.\");\n    Console.error();\n\n    var animationFrame = 0;\n    var lastLinePrinted = \"\";\n    var timer = setInterval(function () {\n      var spinner = ['-', '\\\\', '|', '/'];\n      lastLinePrinted = \"Waiting for you to register on the web... \" +\n        spinner[animationFrame];\n      Console.rawError(lastLinePrinted + Console.CARRIAGE_RETURN);\n      animationFrame = (animationFrame + 1) % spinner.length;\n    }, 200);\n    var stopSpinner = function () {\n      Console.rawError(new Array(lastLinePrinted.length + 1).join(' ') +\n                       Console.CARRIAGE_RETURN);\n      clearInterval(timer);\n    };\n\n    try {\n      var waitForRegistrationResult = connection.call(\n        'waitForRegistration',\n        email\n      );\n    } catch (e) {\n      stopSpinner();\n      if (e.errorType !== \"Meteor.Error\") {\n        throw e;\n      }\n      Console.error(\n        \"When you've picked your password, run \" +\n        Console.command(\"'meteor login'\") + \" to log in.\");\n      return false;\n    }\n\n    stopSpinner();\n    Console.error(\"Username: \" + waitForRegistrationResult.username);\n    loginResult = doInteractivePasswordLogin({\n      username: waitForRegistrationResult.username,\n      retry: true,\n      connection: connection\n    });\n    return loginResult;\n  } else if (result.alreadyExisted && result.username) {\n    Console.error(\"\\nLogging in as \" + Console.command(result.username) + \".\");\n\n    loginResult = doInteractivePasswordLogin({\n      username: result.username,\n      retry: true,\n      connection: connection\n    });\n    return loginResult;\n  } else {\n    // Hmm, got an email we don't understand.\n    Console.error(\n      \"\\nThere was a problem. Please log in with \" +\n      Console.command(\"'meteor login'\") + \".\");\n    return false;\n  }\n});\n\n// options: firstTime, leadingNewline\n// returns true if it printed something\nexports.maybePrintRegistrationLink = function (options) {\n  options = options || {};\n\n  auth.pollForRegistrationCompletion();\n\n  var data = readSessionData();\n  var session = getSession(data, config.getAccountsDomain());\n\n  if (session.userId && ! session.username && session.registrationUrl) {\n    if (options.leadingNewline) {\n      Console.error();\n    }\n    if (options.onlyAllowIfRegistered) {\n      // A stronger message: we're going to not allow whatever they were trying\n      // to do!\n      Console.error(\n        \"You need to claim a username and set a password on your Meteor\",\n        \"developer account to run this command. It takes about a minute at:\",\n        session.registrationUrl);\n      Console.error();\n    } else if (! options.firstTime) {\n      // If they've already been prompted to set a password then this\n      // is more of a friendly reminder, so we word it slightly\n      // differently than the first time they're being shown a\n      // registration url.\n      Console.error(\n        \"You should set a password on your Meteor developer account.\",\n        \"It takes about a minute at:\", session.registrationUrl);\n      Console.error();\n    } else {\n      Console.error(\n        \"You can set a password on your account or change your email\",\n        \"address at:\", session.registrationUrl);\n      Console.error();\n    }\n    return true;\n  }\n  return false;\n};\n\nexports.tryRevokeOldTokens = tryRevokeOldTokens;\n\nexports.getSessionId = function (domain, sessionData) {\n  sessionData = sessionData || readSessionData();\n  return getSession(sessionData, domain).session;\n};\n\nexports.setSessionId = function (domain, sessionId) {\n  var data = readSessionData();\n  getSession(data, domain).session = sessionId;\n  writeSessionData(data);\n};\n\nexports.getSessionToken = function (domain) {\n  return getSession(readSessionData(), domain).token;\n};\n\nexports.isLoggedIn = function () {\n  return loggedIn(readSessionData());\n};\n\n// Return the username of the currently logged in user, or false if\n// not logged in, or null if the logged in user doesn't have a\n// username.\nexports.loggedInUsername = function () {\n  var data = readSessionData();\n  return loggedIn(data) ? currentUsername(data) : false;\n};\n\nexports.getAccountsConfiguration = function (conn) {\n  // Subscribe to the package server's service configurations so that we\n  // can get the OAuth client ID to kick off the OAuth flow.\n  var accountsConfiguration = null;\n\n  // We avoid the overhead of creating a 'ddp-and-mongo' isopacket (or\n  // always loading mongo whenever we load ddp) by just using the low-level\n  // DDP client API here.\n  conn.connection.registerStore('meteor_accounts_loginServiceConfiguration', {\n    update: function (msg) {\n      if (msg.msg === 'added' && msg.fields &&\n          msg.fields.service === 'meteor-developer') {\n        // Note that this doesn't include the _id (which we'd have to parse),\n        // but that's OK.\n        accountsConfiguration = msg.fields;\n      }\n    }\n  });\n\n  var serviceConfigurationsSub = conn.subscribeAndWait(\n    'meteor.loginServiceConfiguration');\n  if (! accountsConfiguration || ! accountsConfiguration.clientId) {\n    throw new Error('no-accounts-configuration');\n  }\n\n  return accountsConfiguration;\n};\n\n// Given a ServiceConnection, log in with OAuth using Meteor developer\n// accounts. Assumes the user is already logged in to the developer\n// accounts server.\nexports.loginWithTokenOrOAuth = function (conn, accountsConfiguration,\n                                          url, domain, sessionType) {\n  var setUpOnReconnect = function () {\n    conn.onReconnect = function () {\n      conn.apply('login', [{\n        resume: auth.getSessionToken(domain)\n      }], { wait: true }, function () { });\n    };\n  };\n\n  var clientId = accountsConfiguration.clientId;\n  var loginResult;\n\n  // Try to log in with an existing login token, if we have one.\n  var existingToken = auth.getSessionToken(domain);\n  if (existingToken) {\n    try {\n      loginResult = conn.apply('login', [{\n        resume: existingToken\n      }], { wait: true });\n    } catch (err) {\n      // If we get a Meteor.Error, then we swallow it and go on to\n      // attempt an OAuth flow and get a new token. If it's not a\n      // Meteor.Error, then we leave it to the caller to handle.\n      if (err.errorType !== \"Meteor.Error\") {\n        throw err;\n      }\n    }\n\n    if (loginResult && loginResult.token && loginResult.id) {\n      // Success!\n      setUpOnReconnect();\n      return;\n    }\n  }\n\n  // Either we didn't have an existing token, or it didn't work. Do an\n  // OAuth flow to log in.\n  var redirectUri = url + '/_oauth/meteor-developer';\n\n  // Duplicate code from packages/oauth/oauth_common.js. In Meteor 0.9.1, we\n  // switched to a new URL style for Oauth that no longer has the \"?close\"\n  // parameter at the end. However, we need all of our backend services to be\n  // compatible with old Meteor tools which were written before 0.9.1. These old\n  // meteor tools only know how to deal with oauth URLs that have the \"?close\"\n  // query parameter, so our services (packages.meteor.com, etc) have to use the\n  // old-style URL. This means that all new Meteor tools also need to use the\n  // old-style URL to be compatible with the new servers which are backwards-\n  // compatible with the old tool.\n  if (! accountsConfiguration.loginStyle) {\n    redirectUri = redirectUri + \"?close\";\n  }\n  loginResult = oauthFlow(conn, {\n    clientId: clientId,\n    redirectUri: redirectUri,\n    domain: domain,\n    sessionType: sessionType\n  });\n\n  setUpOnReconnect();\n};\n\nexports.loggedInAccountsConnection = loggedInAccountsConnection;\nexports.withAccountsConnection = withAccountsConnection;\n"
  },
  {
    "path": "tools/meteor-services/config.js",
    "content": "var url = require('url');\nvar files = require('../fs/files.js');\nvar _ = require('underscore');\nvar tropohouse = require('../packaging/tropohouse.js');\n\n// A few functions in the `meteor` tool talk to MDG servers: primarily\n// checking for updates, logging into your Meteor account, and\n// deploying apps to the MDG free hosting sandbox, publishing packages,\n// getting an ssh access to a build farm. These functions need\n// configuration.\n\nvar config = exports;\n_.extend(exports, {\n  // Base URL for Meteor Accounts OAuth services. Endpoints include /authorize\n  // and /token.\n  getOauthUrl: function () {\n    return \"https://www.meteor.com/oauth2\";\n  },\n\n  // Base URL for Meteor Accounts API. Endpoints include '/login' and\n  // '/logoutById'.\n  getAccountsApiUrl: function () {\n    return \"https://www.meteor.com/api/v1\";\n  },\n\n  // URL for the DDP interface to Meteor Accounts.\n  getAuthDDPUrl: function () {\n    return \"https://www.meteor.com/auth\";\n  },\n\n  // URL for the DDP interface to the meteor build farm, typically\n  // \"https://build.meteor.com\".\n  getBuildFarmUrl: function () {\n    return process.env.METEOR_BUILD_FARM_URL || \"https://build.meteor.com\";\n  },\n\n  getBuildFarmDomain: function () {\n    return url.parse(config.getBuildFarmUrl()).host;\n  },\n\n  // URL for the DDP interface to the package server, typically\n  // \"https://packages.meteor.com\".\n  getPackageServerUrl: function () {\n    return process.env.METEOR_PACKAGE_SERVER_URL ||\n      \"https://packages.meteor.com\";\n  },\n\n  getPackageServerDomain: function () {\n    return url.parse(config.getPackageServerUrl()).host;\n  },\n\n  getPackageStatsServerUrl: function () {\n    return process.env.METEOR_PACKAGE_STATS_SERVER_URL ||\n      \"https://activity.meteor.com\";\n  },\n\n  getPackageStatsServerDomain: function () {\n    return url.parse(config.getPackageStatsServerUrl()).host;\n  },\n\n  // Note: this is NOT guaranteed to return a distinct prefix for every\n  // conceivable URL.  But it sure ought to return a distinct prefix for every\n  // server we actually use.\n  getPackageServerFilePrefix: function (serverUrl) {\n    var self = this;\n    if (!serverUrl) {\n      serverUrl = self.getPackageServerUrl();\n    }\n\n    // Chop off http:// and https:// and trailing slashes.\n    serverUrl = serverUrl.replace(/^\\https:\\/\\//, '');\n    serverUrl = serverUrl.replace(/^\\http:\\/\\//, '');\n    serverUrl = serverUrl.replace(/\\/+$/, '');\n\n    // Chop off meteor.com.\n    serverUrl = serverUrl.replace(/\\.meteor\\.com$/, '');\n\n    // Replace other weird stuff with X.\n    serverUrl = serverUrl.replace(/[^a-zA-Z0-9.-]/g, 'X');\n\n    return serverUrl;\n  },\n\n  getPackagesDirectoryName: function (serverUrl) {\n    var self = this;\n\n    var prefix = config.getPackageServerFilePrefix(serverUrl);\n    if (prefix !== 'packages') {\n      prefix = files.pathJoin('packages-from-server', prefix);\n    }\n\n    return prefix;\n  },\n\n  getLocalPackageCacheFilename: function (serverUrl) {\n    var self = this;\n    var prefix = self.getPackageServerFilePrefix(serverUrl);\n\n    // Should look like 'packages.data.db' in the default case\n    // (packages.data.json before 0.9.4).\n    return prefix + \".data.db\";\n  },\n\n  getPackageStorage: function (options) {\n    var self = this;\n    options = options || {};\n    var root = options.root || tropohouse.default.root;\n    return files.pathJoin(root, \"package-metadata\", \"v2.0.1\",\n                     self.getLocalPackageCacheFilename(options.serverUrl));\n  },\n\n  getIsopacketRoot: function () {\n    if (files.inCheckout()) {\n      return files.pathJoin(files.getCurrentToolsDir(), '.meteor', 'isopackets');\n    } else {\n      return files.pathJoin(files.getCurrentToolsDir(), 'isopackets');\n    }\n  },\n\n  // Return the domain name of the current Meteor Accounts server in\n  // use. This is used as a key for storing your Meteor Accounts\n  // login token.\n  getAccountsDomain: function () {\n    return \"www.meteor.com\";\n  },\n\n  // Path to file that contains our credentials for any services that\n  // we're logged in to. Typically .meteorsession in the user's home\n  // directory.\n  getSessionFilePath: function () {\n    // METEOR_SESSION_FILE is for automated testing purposes only.\n    return process.env.METEOR_SESSION_FILE ||\n      files.pathJoin(files.getHomeDir(), '.meteorsession');\n  }\n});\n"
  },
  {
    "path": "tools/meteor-services/deploy.js",
    "content": "// URL parsing and validation\n// RPC to server (endpoint, arguments)\n// see if RPC requires password\n// prompt for password\n// send RPC with or without password as required\n\nvar files = require('../fs/files.js');\nvar httpHelpers = require('../utils/http-helpers.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar config = require('./config.js');\nvar auth = require('./auth.js');\nvar _ = require('underscore');\nvar stats = require('./stats.js');\nvar Console = require('../console/console.js').Console;\n\nconst CAPABILITIES = ['showDeployMessages', 'canTransferAuthorization'];\n\n// Make a synchronous RPC to the \"classic\" MDG deploy API. The deploy\n// API has the following contract:\n//\n// - Parameters are always sent in the query string.\n// - A tarball can be sent in the body (when deploying an app).\n// - On success, all calls return HTTP 200. Those that return a value\n//   either return a JSON payload or a plaintext payload and the\n//   Content-Type header is set appropriately.\n// - On failure, calls return some non-200 HTTP status code and\n//   provide a human-readable error message in the body.\n// - URLs are of the form \"/[operation]/[site]\".\n// - Body encodings are always utf8.\n// - Meteor Accounts auth is possible using first-party MDG cookies\n//   (rather than OAuth).\n//\n// Options include:\n// - method: GET, POST, or DELETE. default GET\n// - operation: \"info\", \"logs\", \"mongo\", \"deploy\", \"authorized-apps\"\n// - site: site name\n// - expectPayload: an array of key names. if present, then we expect\n//   the server to return JSON content on success and to return an\n//   object with all of these key names.\n// - expectMessage: if true, then we expect the server to return text\n//   content on success.\n// - bodyStream: if provided, a stream to use as the request body\n// - any other parameters accepted by the node 'request' module, for example\n//   'qs' to set query string parameters\n// - printDeployURL: provided if we should show the deploy URL; set this\n//   for the first RPC of any user command\n//\n// Waits until server responds, then returns an object with the\n// following keys:\n//\n// - statusCode: HTTP status code, or null if the server couldn't be\n//   contacted\n// - payload: if successful, and the server returned a JSON body, the\n//   parsed JSON body\n// - message: if successful, and the server returned a text body, the\n//   body as a string\n// - errorMessage: if unsuccessful, a human-readable error message,\n//   derived from either a transport-level exception, the response\n//   body, or a generic 'try again later' message, as appropriate\n\nvar deployRpc = function (options) {\n  var genericError = \"Server error (please try again later)\";\n\n  options = _.clone(options);\n  options.headers = _.clone(options.headers || {});\n  if (options.headers.cookie) {\n    throw new Error(\"sorry, can't combine cookie headers yet\");\n  }\n  options.qs = _.extend({}, options.qs, {capabilities: CAPABILITIES});\n\n  const deployURLBase = getDeployURL(options.site).await();\n\n  if (options.printDeployURL) {\n    Console.info(\"Talking to Galaxy servers at \" + deployURLBase);\n  }\n\n  // XXX: Reintroduce progress for upload\n  try {\n    var result = httpHelpers.request(_.extend(options, {\n      url: deployURLBase + '/' + options.operation +\n        (options.site ? ('/' + options.site) : ''),\n      method: options.method || 'GET',\n      bodyStream: options.bodyStream,\n      useAuthHeader: true,\n      encoding: 'utf8' // Hack, but good enough for the deploy server..\n    }));\n  } catch (e) {\n    return {\n      statusCode: null,\n      errorMessage: \"Connection error (\" + e.message + \")\"\n    };\n  }\n\n  var response = result.response;\n  var body = result.body;\n  var ret = { statusCode: response.statusCode };\n\n  if (response.statusCode !== 200) {\n    ret.errorMessage = body.length > 0 ? body : genericError;\n    return ret;\n  }\n\n  var contentType = response.headers[\"content-type\"] || '';\n  if (contentType === \"application/json; charset=utf-8\") {\n    try {\n      ret.payload = JSON.parse(body);\n    } catch (e) {\n      ret.errorMessage = genericError;\n      return ret;\n    }\n  } else if (contentType === \"text/plain; charset=utf-8\") {\n    ret.message = body;\n  }\n\n  var hasAllExpectedKeys = _.all(_.map(\n    options.expectPayload || [], function (key) {\n      return ret.payload && _.has(ret.payload, key);\n    }));\n\n  if ((options.expectPayload && ! _.has(ret, 'payload')) ||\n      (options.expectMessage && ! _.has(ret, 'message')) ||\n      ! hasAllExpectedKeys) {\n    delete ret.payload;\n    delete ret.message;\n\n    ret.errorMessage = genericError;\n  }\n\n  return ret;\n};\n\n// Just like deployRpc, but also presents authentication. It will\n// prompt the user for a password, or use a Meteor Accounts\n// credential, as necessary.\n//\n// Additional options (beyond deployRpc):\n//\n// - preflight: if true, do everything but the actual RPC. The only\n//   other necessary option is 'site'. On failure, returns an object\n//   with errorMessage (just like deployRpc). On success, returns an\n//   object without an errorMessage key and with possible keys\n//   'protection' (value either 'password' or 'account') and\n//   'authorized' (true if the current user is an authorized user on\n//   this app).\n// - promptIfAuthFails: if true, then we think we are logged in with the\n//   accounts server but our authentication actually fails, then prompt\n//   the user to log in with a username and password and then resend the\n//   RPC.\nvar authedRpc = function (options) {\n  var rpcOptions = _.clone(options);\n  var preflight = rpcOptions.preflight;\n  delete rpcOptions.preflight;\n\n  // Fetch auth info\n  var infoResult = deployRpc({\n    operation: 'info',\n    site: rpcOptions.site,\n    expectPayload: [],\n    qs: options.qs,\n    printDeployURL: options.printDeployURL\n  });\n  delete rpcOptions.printDeployURL;\n\n  if (infoResult.statusCode === 401 && rpcOptions.promptIfAuthFails) {\n    // Our authentication didn't validate, so prompt the user to log in\n    // again, and resend the RPC if the login succeeds.\n    var username = Console.readLine({\n      prompt: \"Username: \",\n      stream: process.stderr\n    });\n    var loginOptions = {\n      username: username,\n      suppressErrorMessage: true\n    };\n    if (auth.doInteractivePasswordLogin(loginOptions)) {\n      return authedRpc(options);\n    } else {\n      return {\n        statusCode: 403,\n        errorMessage: \"login failed.\"\n      };\n    }\n  }\n\n  if (infoResult.statusCode === 404) {\n    // Doesn't exist, therefore not protected.\n    return preflight ? { } : deployRpc(rpcOptions);\n  }\n\n  if (infoResult.errorMessage) {\n    return infoResult;\n  }\n  var info = infoResult.payload;\n\n  if (! _.has(info, 'protection')) {\n    // Not protected.\n    //\n    // XXX should prompt the user to claim the app (only if deploying?)\n    return preflight ? { } : deployRpc(rpcOptions);\n  }\n\n  if (info.protection === \"password\") {\n    if (preflight) {\n      return { protection: info.protection };\n    }\n    // Password protected. Read a password, hash it, and include the\n    // hashed password as a query parameter when doing the RPC.\n    var password;\n    password = Console.readLine({\n      echo: false,\n      prompt: \"Password: \",\n      stream: process.stderr\n    });\n\n    // Hash the password so we never send plaintext over the\n    // wire. Doesn't actually make us more secure, but it means we\n    // won't leak a user's password, which they might use on other\n    // sites too.\n    var crypto = require('crypto');\n    var hash = crypto.createHash('sha1');\n    hash.update('S3krit Salt!');\n    hash.update(password);\n    password = hash.digest('hex');\n\n    rpcOptions = _.clone(rpcOptions);\n    rpcOptions.qs = _.clone(rpcOptions.qs || {});\n    rpcOptions.qs.password = password;\n\n    return deployRpc(rpcOptions);\n  }\n\n  if (info.protection === \"account\") {\n    if (! _.has(info, 'authorized')) {\n      // Absence of this implies that we are not an authorized user on\n      // this app\n      if (preflight) {\n        return { protection: info.protection };\n      } else {\n        return {\n          statusCode: null,\n          errorMessage: auth.isLoggedIn() ?\n            // XXX better error message (probably need to break out of\n            // the 'errorMessage printed with brief prefix' pattern)\n            \"Not an authorized user on this site\" :\n            \"Not logged in\"\n        };\n      }\n    }\n\n    // Sweet, we're an authorized user.\n    if (preflight) {\n      return {\n        protection: info.protection,\n        authorized: info.authorized\n      };\n    } else {\n      return deployRpc(rpcOptions);\n    }\n  }\n\n  return {\n    statusCode: null,\n    errorMessage: \"You need a newer version of Meteor to work with this site\"\n  };\n};\n\n// When the user is trying to do something with a legacy\n// password-protected app, instruct them to claim it with 'meteor\n// claim'.\nvar printLegacyPasswordMessage = function (site) {\n  Console.error(\n    \"\\nThis site was deployed with an old version of Meteor that used \" +\n    \"site passwords instead of user accounts. Now we have a much better \" +\n    \"system, Meteor developer accounts.\");\n  Console.error();\n  Console.error(\"If this is your site, please claim it into your account with\");\n  Console.error(\n    Console.command(\"meteor claim \" + site),\n    Console.options({ indent: 2 }));\n};\n\n// When the user is trying to do something with an app that they are not\n// authorized for, instruct them to get added via 'meteor authorized\n// --add' or switch accounts.\nvar printUnauthorizedMessage = function () {\n  var username = auth.loggedInUsername();\n  Console.error(\"Sorry, that site belongs to a different user.\");\n  if (username) {\n    Console.error(\"You are currently logged in as \" + username + \".\");\n  }\n  Console.error();\n  Console.error(\n    \"Either have the site owner use \" +\n    Console.command(\"'meteor authorized --add'\") + \" to add you as an \" +\n    \"authorized developer for the site, or switch to an authorized account \" +\n    \"with \" + Console.command(\"'meteor login'\") + \".\");\n};\n\n// Take a proposed sitename for deploying to. If it looks\n// syntactically good, canonicalize it (this essentially means\n// stripping 'http://' or a trailing '/' if present) and return it. If\n// not, print an error message to stderr and return null.\nvar canonicalizeSite = function (site) {\n  // There are actually two different bugs here. One is that the meteor deploy\n  // server does not support apps whose total site length is greater than 63\n  // (because of how it generates Mongo database names); that can be fixed on\n  // the server. After that, this check will be too strong, but we still will\n  // want to check that each *component* of the hostname is at most 63\n  // characters (url.parse will do something very strange if a component is\n  // larger than 63, which is the maximum legal length).\n  if (site.length > 63) {\n    Console.error(\n      \"The maximum hostname length currently supported is 63 characters: \" +\n      site + \" is too long. \" +\n      \"Please try again with a shorter URL for your site.\");\n    return false;\n  }\n\n  var url = site;\n  if (!url.match(':\\/\\/')) {\n    url = 'http://' + url;\n  }\n\n  var parsed = require('url').parse(url);\n\n  if (! parsed.hostname) {\n    Console.info(\n      \"Please specify a domain to connect to, such as www.example.com or \" +\n      \"http://www.example.com/\");\n    return false;\n  }\n\n  if (parsed.pathname != '/' || parsed.hash || parsed.query) {\n    Console.info(\n      \"Sorry, Meteor does not yet support specific path URLs, such as \" +\n      Console.url(\"http://www.example.com/blog\") + \" .  Please specify the root of a domain.\");\n    return false;\n  }\n\n  return parsed.hostname;\n};\n\n// Run the bundler and deploy the result. Print progress\n// messages. Return a command exit code.\n//\n// Options:\n// - projectContext: the ProjectContext for the app\n// - site: site to deploy as\n// - settingsFile: file from which to read deploy settings (undefined\n//   to leave unchanged from previous deploy of the app, if any)\n// - recordPackageUsage: (defaults to true) if set to false, don't\n//   send information about packages used by this app to the package\n//   stats server.\n// - buildOptions: the 'buildOptions' argument to the bundler\n// - rawOptions: any unknown options that were passed to the command line tool\nvar bundleAndDeploy = function (options) {\n  if (options.recordPackageUsage === undefined) {\n    options.recordPackageUsage = true;\n  }\n\n  var site = canonicalizeSite(options.site);\n  if (! site) {\n    return 1;\n  }\n\n  // We should give a username/password prompt if the user was logged in\n  // but the credentials are expired, unless the user is logged in but\n  // doesn't have a username (in which case they should hit the email\n  // prompt -- a user without a username shouldn't be given a username\n  // prompt). There's an edge case where things happen in the following\n  // order: user creates account, user sets username, credential expires\n  // or is revoked, user comes back to deploy again. In that case,\n  // they'll get an email prompt instead of a username prompt because\n  // the command-line tool didn't have time to learn about their\n  // username before the credential was expired.\n  auth.pollForRegistrationCompletion({\n    noLogout: true\n  });\n  var promptIfAuthFails = (auth.loggedInUsername() !== null);\n\n  // Check auth up front, rather than after the (potentially lengthy)\n  // bundling process.\n  var preflight = authedRpc({\n    site: site,\n    preflight: true,\n    promptIfAuthFails: promptIfAuthFails,\n    qs: options.rawOptions,\n    printDeployURL: true\n  });\n\n  if (preflight.errorMessage) {\n    Console.error(\"Error deploying application: \" + preflight.errorMessage);\n    return 1;\n  }\n\n  if (preflight.protection === \"password\") {\n    printLegacyPasswordMessage(site);\n    Console.error(\"If it's not your site, please try a different name!\");\n    return 1;\n\n  } else if (preflight.protection === \"account\" &&\n             ! preflight.authorized) {\n    printUnauthorizedMessage();\n    return 1;\n  }\n\n  var buildDir = files.mkdtemp('build_tar');\n  var bundlePath = files.pathJoin(buildDir, 'bundle');\n\n  Console.info('Deploying your app...');\n\n  var settings = null;\n  var messages = buildmessage.capture({\n    title: \"preparing to deploy\",\n    rootPath: process.cwd()\n  }, function () {\n    if (options.settingsFile) {\n      settings = files.getSettings(options.settingsFile);\n    }\n  });\n\n  if (! messages.hasMessages()) {\n    var bundler = require('../isobuild/bundler.js');\n\n    var bundleResult = bundler.bundle({\n      projectContext: options.projectContext,\n      outputPath: bundlePath,\n      buildOptions: options.buildOptions,\n    });\n\n    if (bundleResult.errors) {\n      messages = bundleResult.errors;\n    }\n  }\n\n  if (messages.hasMessages()) {\n    Console.info(\"\\nErrors prevented deploying:\");\n    Console.info(messages.formatMessages());\n    return 1;\n  }\n\n  if (options.recordPackageUsage) {\n    stats.recordPackages({\n      what: \"sdk.deploy\",\n      projectContext: options.projectContext,\n      site: site\n    });\n  }\n\n  var result = buildmessage.enterJob({ title: \"uploading\" }, function () {\n    return authedRpc({\n      method: 'POST',\n      operation: 'deploy',\n      site: site,\n      qs: _.extend({}, options.rawOptions, settings !== null ? {settings: settings} : {}),\n      bodyStream: files.createTarGzStream(files.pathJoin(buildDir, 'bundle')),\n      expectPayload: ['url'],\n      preflightPassword: preflight.preflightPassword,\n      // Disable the HTTP timeout for this POST request.\n      timeout: null,\n    });\n  });\n\n  if (result.errorMessage) {\n    Console.error(\"\\nError deploying application: \" + result.errorMessage);\n    return 1;\n  }\n\n  if (result.payload.message) {\n    Console.info(result.payload.message);\n  } else {\n    var deployedAt = require('url').parse(result.payload.url);\n    var hostname = deployedAt.hostname;\n\n    Console.info('Now serving at http://' + hostname);\n\n    if (! hostname.match(/meteor\\.com$/)) {\n      var dns = require('dns');\n      dns.resolve(hostname, 'CNAME', function (err, cnames) {\n        if (err || cnames[0] !== 'origin.meteor.com') {\n          dns.resolve(hostname, 'A', function (err, addresses) {\n            if (err || addresses[0] !== '107.22.210.133') {\n              Console.info('-------------');\n              Console.info(\n                \"You've deployed to a custom domain.\",\n                \"Please be sure to CNAME your hostname\",\n                \"to origin.meteor.com, or set an A record to 107.22.210.133.\");\n              Console.info('-------------');\n            }\n          });\n        }\n      });\n    }\n  }\n\n  return 0;\n};\n\nvar deleteApp = function (site) {\n  site = canonicalizeSite(site);\n  if (! site) {\n    return 1;\n  }\n\n  var result = authedRpc({\n    method: 'DELETE',\n    operation: 'deploy',\n    site: site,\n    promptIfAuthFails: true,\n    printDeployURL: true\n  });\n\n  if (result.errorMessage) {\n    Console.error(\"Couldn't delete application: \" + result.errorMessage);\n    return 1;\n  }\n\n  Console.info(\"Deleted.\");\n  return 0;\n};\n\n// Helper that does a preflight request to check auth, and prints the\n// appropriate error message if auth fails or if this is a legacy\n// password-protected app. If auth succeeds, then it runs the actual\n// RPC. 'site' and 'operation' are the site and operation for the\n// RPC. 'what' is a string describing the operation, for use in error\n// messages.  Returns the result of the RPC if successful, or null\n// otherwise (including if auth failed or if the user is not authorized\n// for this site).\nvar checkAuthThenSendRpc = function (site, operation, what) {\n  var preflight = authedRpc({\n    operation: operation,\n    site: site,\n    preflight: true,\n    promptIfAuthFails: true,\n    printDeployURL: true\n  });\n\n  if (preflight.errorMessage) {\n    Console.error(\"Couldn't \" + what + \": \" + preflight.errorMessage);\n    return null;\n  }\n\n  if (preflight.protection === \"password\") {\n    printLegacyPasswordMessage(site);\n    return null;\n  } else if (preflight.protection === \"account\" &&\n             ! preflight.authorized) {\n    if (! auth.isLoggedIn()) {\n      // Maybe the user is authorized for this app but not logged in\n      // yet, so give them a login prompt.\n      var loginResult = auth.doUsernamePasswordLogin({ retry: true });\n      if (loginResult) {\n        // Once we've logged in, retry the whole operation. We need to\n        // do the preflight request again instead of immediately moving\n        // on to the real RPC because we don't yet know if the newly\n        // logged-in user is authorized for this app, and if they\n        // aren't, then we want to print the nice unauthorized error\n        // message.\n        return checkAuthThenSendRpc(site, operation, what);\n      } else {\n        // Shouldn't ever get here because we set the retry flag on the\n        // login, but just in case.\n        Console.error(\n          \"\\nYou must be logged in to \" + what + \" for this app. Use \" +\n           Console.command(\"'meteor login'\") + \"to log in.\");\n        Console.error();\n        Console.error(\n          \"If you don't have a Meteor developer account yet, you can quickly \" +\n          \"create one at www.meteor.com.\");\n        return null;\n      }\n    } else { // User is logged in but not authorized for this app\n      Console.error();\n      printUnauthorizedMessage();\n      return null;\n    }\n  }\n\n  // User is authorized for the app; go ahead and do the actual RPC.\n\n  var result = authedRpc({\n    operation: operation,\n    site: site,\n    expectMessage: true,\n    promptIfAuthFails: true\n  });\n\n  if (result.errorMessage) {\n    Console.error(\"Couldn't \" + what + \": \" + result.errorMessage);\n    return null;\n  }\n\n  return result;\n};\n\n// On failure, prints a message to stderr and returns null. Otherwise,\n// returns a temporary authenticated Mongo URL allowing access to this\n// site's database.\nvar temporaryMongoUrl = function (site) {\n  site = canonicalizeSite(site);\n  if (! site) {\n    // canonicalizeSite printed an error\n    return null;\n  }\n\n  var result = checkAuthThenSendRpc(site, 'mongo', 'open a mongo connection');\n\n  if (result !== null) {\n    return result.message;\n  } else {\n    return null;\n  }\n};\n\nvar logs = function (site) {\n  site = canonicalizeSite(site);\n  if (! site) {\n    return 1;\n  }\n\n  var result = checkAuthThenSendRpc(site, 'logs', 'view logs');\n\n  if (result === null) {\n    return 1;\n  } else {\n    Console.info(result.message);\n    auth.maybePrintRegistrationLink({ leadingNewline: true });\n    return 0;\n  }\n};\n\nvar listAuthorized = function (site) {\n  site = canonicalizeSite(site);\n  if (! site) {\n    return 1;\n  }\n\n  var result = deployRpc({\n    operation: 'info',\n    site: site,\n    expectPayload: [],\n    printDeployURL: true\n  });\n  if (result.errorMessage) {\n    Console.error(\"Couldn't get authorized users list: \" + result.errorMessage);\n    return 1;\n  }\n  var info = result.payload;\n\n  if (! _.has(info, 'protection')) {\n    Console.info(\"<anyone>\");\n    return 0;\n  }\n\n  if (info.protection === \"password\") {\n    Console.info(\"<password>\");\n    return 0;\n  }\n\n  if (info.protection === \"account\") {\n    if (! _.has(info, 'authorized')) {\n      Console.error(\"Couldn't get authorized users list: \" +\n                    \"You are not authorized\");\n      return 1;\n    }\n\n    Console.info((auth.loggedInUsername() || \"<you>\"));\n    _.each(info.authorized, function (username) {\n      if (username) {\n        // Current username rules don't let you register anything that we might\n        // want to split over multiple lines (ex: containing a space), but we\n        // don't want confusion if we ever change some implementation detail.\n        Console.rawInfo(username + \"\\n\");\n      }\n    });\n    return 0;\n  }\n};\n\n// action is \"add\", \"transfer\" or \"remove\"\nvar changeAuthorized = function (site, action, username) {\n  site = canonicalizeSite(site);\n  if (! site) {\n    // canonicalizeSite will have already printed an error\n    return 1;\n  }\n\n  var result = authedRpc({\n    method: 'POST',\n    operation: 'authorized',\n    site: site,\n    qs: {[action]: username},\n    promptIfAuthFails: true,\n    printDeployURL: true\n  });\n\n  if (result.errorMessage) {\n    Console.error(\"Couldn't change authorized users: \" + result.errorMessage);\n    return 1;\n  }\n\n  const verbs = {\n    add: \"added\",\n    remove: \"removed\",\n    transfer: \"transferred\"\n  };\n  Console.info(`${site}: ${verbs[action]} ${username}`);\n  return 0;\n};\n\nvar claim = function (site) {\n  site = canonicalizeSite(site);\n  if (! site) {\n    // canonicalizeSite will have already printed an error\n    return 1;\n  }\n\n  // Check to see if it's even a claimable site, so that we can print\n  // a more appropriate message than we'd get if we called authedRpc\n  // straight away (at a cost of an extra REST call)\n  var infoResult = deployRpc({\n    operation: 'info',\n    site: site,\n    printDeployURL: true\n  });\n  if (infoResult.statusCode === 404) {\n    Console.error(\n      \"There isn't a site deployed at that address. Use \" +\n      Console.command(\"'meteor deploy'\") + \" \" +\n      \"if you'd like to deploy your app here.\");\n    return 1;\n  }\n\n  if (infoResult.payload && infoResult.payload.protection === \"account\") {\n    if (infoResult.payload.authorized) {\n      Console.error(\"That site already belongs to you.\\n\");\n    } else {\n      Console.error(\"Sorry, that site belongs to someone else.\\n\");\n    }\n    return 1;\n  }\n\n  if (infoResult.payload &&\n      infoResult.payload.protection === \"password\") {\n    Console.info(\n      \"To claim this site and transfer it to your account, enter the\",\n      \"site password one last time.\");\n    Console.info();\n  }\n\n  var result = authedRpc({\n    method: 'POST',\n    operation: 'claim',\n    site: site,\n    promptIfAuthFails: true\n  });\n\n  if (result.errorMessage) {\n    auth.pollForRegistrationCompletion();\n    if (! auth.loggedInUsername() &&\n        auth.registrationUrl()) {\n      Console.error(\n        \"You need to set a password on your Meteor developer account before\",\n        \"you can claim sites. You can do that here in under a minute:\");\n      Console.error(Console.url(auth.registrationUrl()));\n      Console.error();\n    } else {\n      Console.error(\"Couldn't claim site: \" + result.errorMessage);\n    }\n    return 1;\n  }\n\n  Console.info(site + \": \" + \"successfully transferred to your account.\");\n  Console.info();\n  Console.info(\"Show authorized users with:\");\n  Console.info(\n    Console.command(\"meteor authorized \" + site),\n    Console.options({ indent: 2 }));\n  Console.info();\n  Console.info(\"Add authorized users with:\");\n  Console.info(\n    Console.command(\"meteor authorized \" + site + \" --add <username>\"),\n    Console.options({ indent: 2 }));\n  Console.info();\n  Console.info(\"Remove authorized users with:\");\n  Console.info(\n    Console.command(\"meteor authorized \" + site + \" --remove <username>\"),\n    Console.options({ indent: 2 }));\n  Console.info();\n  return 0;\n};\n\nvar listSites = function () {\n  var result = deployRpc({\n    method: \"GET\",\n    operation: \"authorized-apps\",\n    promptIfAuthFails: true,\n    expectPayload: [\"sites\"]\n  });\n\n  if (result.errorMessage) {\n    Console.error(\"Couldn't list sites: \" + result.errorMessage);\n    return 1;\n  }\n\n  if (! result.payload ||\n      ! result.payload.sites ||\n      ! result.payload.sites.length) {\n    Console.info(\"You don't have any sites yet.\");\n  } else {\n    result.payload.sites.sort();\n    _.each(result.payload.sites, function (site) {\n      Console.info(site);\n    });\n  }\n  return 0;\n};\n\n// Given a hostname, add \"http://\" or \"https://\" as\n// appropriate. (localhost gets http; anything else is always https.)\nfunction addScheme(hostOrURL) {\n  if (hostOrURL.match(/^http/)) {\n    return hostOrURL;\n  } else if (hostOrURL.match(/^localhost(:\\d+)?$/)) {\n    return \"http://\" + hostOrURL;\n  } else {\n    return \"https://\" + hostOrURL;\n  }\n};\n\n// Maps from \"site\" to Promise<deploy URL>, so we don't have to re-ping on each\n// RPC (even if the calls to getDeployURL overlap).\nconst galaxyDiscoveryCache = new Map;\n\n// getDeployURL returns the a Promise for the base deploy URL for the given app.\n// \"app\" may be falsey for certain RPCs (eg meteor list-sites).\nfunction getDeployURL(site) {\n  // Always trust explicitly configuration via env.\n  if (process.env.DEPLOY_HOSTNAME) {\n    return Promise.resolve(addScheme(process.env.DEPLOY_HOSTNAME));\n  }\n\n  const defaultURL = \"https://us-east-1.galaxy-deploy.meteor.com\";\n\n  // No site? Just use the default.\n  if (!site) {\n    return Promise.resolve(defaultURL);\n  }\n\n  // If we have a site, we can try to do Galaxy discovery.\n\n  // Do we already have an answer?\n  if (galaxyDiscoveryCache.has(site)) {\n    return galaxyDiscoveryCache.get(site);\n  }\n\n  // Otherwise, try https first, then http, then just use the default.\n  const p = discoverGalaxy(site, \"https\")\n          .catch(() => discoverGalaxy(site, \"http\"))\n          .catch(() => defaultURL);\n  galaxyDiscoveryCache.set(site, p);\n  return p;\n}\n\n// discoverGalaxy returns the URL to use for Galaxy discovery, or an error if it\n// couldn't be fetched.\nasync function discoverGalaxy(site, scheme) {\n  const discoveryURL =\n          scheme + \"://\" + site + \"/.well-known/meteor/deploy-url\";\n  // If httpHelpers.request throws, the returned Promise will reject, which is\n  // fine.\n  const { response, body } = httpHelpers.request({\n    url: discoveryURL,\n    json: true,\n    strictSSL: true,\n    // We don't want to be confused by, eg, a non-Galaxy-hosted site which\n    // redirects to a Galaxy-hosted site.\n    followRedirect: false\n  });\n  if (response.statusCode !== 200) {\n    throw new Error(\"bad status code: \" + response.statusCode);\n  }\n  if (!body) {\n    throw new Error(\"response had no body\");\n  }\n  if (body.galaxyDiscoveryVersion !== \"galaxy-1\") {\n    throw new Error(\n      \"unexpected galaxyDiscoveryVersion: \" + body.galaxyDiscoveryVersion);\n  }\n  if (!_.has(body, \"deployURL\")) {\n    throw new Error(\"no deployURL\");\n  }\n  return body.deployURL;\n}\n\nexports.bundleAndDeploy = bundleAndDeploy;\nexports.deleteApp = deleteApp;\nexports.temporaryMongoUrl = temporaryMongoUrl;\nexports.logs = logs;\nexports.listAuthorized = listAuthorized;\nexports.changeAuthorized = changeAuthorized;\nexports.claim = claim;\nexports.listSites = listSites;\n"
  },
  {
    "path": "tools/meteor-services/service-connection.js",
    "content": "var _ = require(\"underscore\");\nvar isopackets = require('../tool-env/isopackets.js');\nvar files = require('../fs/files.js');\nvar fiberHelpers = require(\"../utils/fiber-helpers.js\");\n\n// Wrapper to manage a connection to a DDP service. The main difference between\n// it and a raw DDP connection is that the constructor blocks until a successful\n// connection is made; you can't call methods or subscribe asynchronously (ie,\n// there's always a wait); and if the connection disconnects (with or without\n// error) while we're waiting on a method call or subscription, the\n// apply/subscribeAndWait call throws the given error. This functionality should\n// eventually end up in the DDP client in one form or another.\n//\n// ServiceConnections never reconnect once they have successfully negotiated the\n// DDP protocol: other than perhaps some initial attempts with the wrong\n// protocol selected, they use just one underlying TCP connection, and fail\n// fast.\n//\n// - endpointUrl: the url to connect to\n// - options:\n//   - headers: an object containing extra headers to use when opening the\n//              DDP connection\n//   - _dontPrintErrors: boolean\n//   ...and anything else you'd normally pass as options to DDP.connect\n//\nvar ServiceConnection = function (endpointUrl, options) {\n  var self = this;\n\n  var Package = isopackets.load('ddp');\n\n  // ServiceConnection never should retry connections: just one TCP connection\n  // is enough, and any errors on it should be detected promptly.\n  options = _.extend({}, options, {\n    // We found that this was likely to time out with the DDP default of 10s,\n    // especially if the CPU is churning on bundling (eg, for the stats\n    // connection which we start in parallel with bundling).\n    connectTimeoutMs: 30000,\n    // Disable client->server heartbeats for service connections.  Users with\n    // slow internet connections were seeing heartbeat timeouts because the\n    // heartbeats were buried behind large responses (eg\n    // https://github.com/meteor/meteor/issues/2777).\n    heartbeatInterval: 0,\n    retry: false,\n    onConnected: function () {\n      self.connected = true;\n      if (! self.currentPromise) {\n        throw Error(\"nobody waiting for connection?\");\n      }\n      if (self.currentPromise !== connectPromise) {\n        throw Error(\"waiting for something that isn't connection?\");\n      }\n      self.currentPromise = null;\n      connectPromise.resolve();\n      connectPromise.resolve = null;\n    }\n  });\n  if (process.env.CAFILE) {\n    options.npmFayeOptions = {\n      ca: files.readFile(process.env.CAFILE)\n    }\n  }\n\n  self.connection = Package['ddp-client'].DDP.connect(endpointUrl, options);\n\n  // Wait until we have some sort of initial connection or error (including the\n  // 10-second timeout built into our DDP client).\n\n  var connectPromise = self.currentPromise =\n    fiberHelpers.makeFulfillablePromise();\n\n  self.connection._stream.on('disconnect', function (error) {\n    self.connected = false;\n    if (error && error.errorType === \"DDP.ForcedReconnectError\") {\n      // OK, we requested this, probably due to version negotation failure.\n      //\n      // This ought to have happened before we successfully connect, unless\n      // somebody adds other calls to forced reconnect to Meteor...\n      if (! connectPromise.resolve) {\n        throw Error(\"disconnect before connect?\");\n      }\n      // Otherwise, ignore this error. We're going to reconnect!\n      return;\n    }\n    // Are we waiting to connect or for the result of a method apply or a\n    // subscribeAndWait? If so, disconnecting is a problem.\n    if (self.currentPromise) {\n      var promise = self.currentPromise;\n      self.currentPromise = null;\n      promise.reject(\n        error || new Package['ddp-client'].DDP.ConnectionError(\n          \"DDP disconnected while connection in progress\")\n      );\n    } else if (error) {\n      // We got some sort of error with nobody listening for it; handle it.\n      // XXX probably have a better way to handle it than this\n      throw error;\n    }\n  });\n\n  connectPromise.await();\n};\n\n_.extend(ServiceConnection.prototype, {\n  call: function (name, ...args) {\n    return this.apply(name, args);\n  },\n\n  apply: function (...args) {\n    var self = this;\n\n    if (self.currentPromise) {\n      throw Error(\"Can't wait on two things at once!\");\n    }\n    self.currentPromise = fiberHelpers.makeFulfillablePromise();\n\n    args.push(function (err, result) {\n      if (!self.currentPromise) {\n        // We're not still waiting? That means we had a disconnect event. But\n        // then how did we actually get this result?\n        throw Error(\"nobody listening for result?\");\n      }\n      var promise = self.currentPromise;\n      self.currentPromise = null;\n      if (err) {\n        promise.reject(err);\n      } else {\n        promise.resolve(result);\n      }\n    });\n\n    self.connection.apply(...args);\n\n    return self.currentPromise.await();\n  },\n\n  // XXX derived from _subscribeAndWait in ddp_connection.js\n  // -- but with a different signature..\n  subscribeAndWait: function (...args) {\n    var self = this;\n\n    if (self.currentPromise) {\n      throw Error(\"Can't wait on two things at once!\");\n    }\n    var subPromise = self.currentPromise = fiberHelpers.makeFulfillablePromise();\n\n    args.push({\n      onReady: function () {\n        if (!self.currentPromise) {\n          // We're not still waiting? That means we had a disconnect event. But\n          // then how did we actually get this result?\n          throw Error(\"nobody listening for subscribe result?\");\n        }\n        var promise = self.currentPromise;\n        self.currentPromise = null;\n        promise.resolve();\n      },\n      onError: function (e) {\n        if (self.currentPromise === subPromise) {\n          // Error while waiting for this sub to become ready? Throw it.\n          self.currentPromise = null;\n          subPromise.reject(e);\n        }\n        // ... ok, this is a late error on the sub.\n        // XXX handle it somehow better\n        throw e;\n      }\n    });\n\n    var sub = self.connection.subscribe(...args);\n    subPromise.await();\n    return sub;\n  },\n\n  close: function () {\n    var self = this;\n    if (self.connection) {\n      self.connection.close();\n      self.connection = null;\n    }\n  }\n});\n\nmodule.exports = ServiceConnection;\n"
  },
  {
    "path": "tools/meteor-services/stats.js",
    "content": "var Fiber = require(\"fibers\");\nvar _ = require(\"underscore\");\n\nvar config = require('./config.js');\nvar files = require('../fs/files.js');\nvar auth = require('./auth.js');\nvar ServiceConnection = require('./service-connection.js');\nvar httpHelpers = require('../utils/http-helpers.js');\nvar Console = require('../console/console.js').Console;\n\n// The name of the package that you add to your app to opt out of\n// sending stats.\nvar OPT_OUT_PACKAGE_NAME = \"package-stats-opt-out\";\n\n// Return a list of packages used by this app, both directly and\n// indirectly. Formatted as a list of objects with 'name', 'version'\n// and 'direct', which is how the `recordAppPackages` method on the\n// stats server expects to get this list.\nvar packageList = function (projectContext) {\n  var versions = [];\n  projectContext.packageMap.eachPackage(function (name, info) {\n    versions.push({\n      name: name,\n      version: info.version,\n      local: info.kind === 'local',\n      direct: !! projectContext.projectConstraintsFile.getConstraint(name)\n    });\n  });\n  return versions;\n};\n\n// Options:\n// - what: one of \"sdk.bundle\", \"sdk.deploy\", \"sdk.run\".\n// - projectContext: the ProjectContext. prepareProjectForBuild\n//   must have run successfully. We must extract all necessary data\n//   from this before yielding.\n// - site: If it's a deploy, the name of the site (\"foo.meteor.com\") that we're\n//   deploying to.\nvar recordPackages = function (options) {\n  // Before doing anything, look at the app's dependencies to see if the\n  // opt-out package is there; if present, we don't record any stats.\n  var packages = packageList(options.projectContext);\n  if (_.findWhere(packages, { name: OPT_OUT_PACKAGE_NAME })) {\n    // Print some output for the 'report-stats' self-test.\n    if (process.env.METEOR_PACKAGE_STATS_TEST_OUTPUT) {\n      process.stdout.write(\"PACKAGE STATS NOT SENT\\n\");\n    }\n    return;\n  }\n\n  var appIdentifier = options.projectContext.appIdentifier;\n\n  // We do this inside a new fiber to avoid blocking anything on talking\n  // to the package stats server. If we can't connect, for example, we\n  // don't care; we'll just miss out on recording these packages.\n  // This also gives it its own buildmessage state.\n  // However, we do make sure to have already extracted the package list from\n  // projectContext, since it might mutate out from under us otherwise.\n  Fiber(function () {\n\n    var details = {\n      what: options.what,\n      userAgent: httpHelpers.getUserAgent(),\n      sessionId: auth.getSessionId(config.getAccountsDomain()),\n      site: options.site\n    };\n\n    try {\n      var conn = connectToPackagesStatsServer();\n      var accountsConfiguration = auth.getAccountsConfiguration(conn);\n\n      if (auth.isLoggedIn()) {\n        try {\n          auth.loginWithTokenOrOAuth(\n            conn,\n            accountsConfiguration,\n            config.getPackageStatsServerUrl(),\n            config.getPackageStatsServerDomain(),\n            \"package-stats-server\"\n          );\n        } catch (err) {\n          // Do nothing. If we can't log in, we should continue and report\n          // stats anonymously.\n          //\n          // We log other errors with `logErrorIfInCheckout`, but login\n          // errors can happen in normal operation when nothing is wrong\n          // (e.g. login token expired or revoked) so we don't log them.\n        }\n      }\n\n      var result = conn.call(\"recordAppPackages\",\n                             appIdentifier,\n                             packages,\n                             details);\n\n      // If the stats server sent us a new session, save it for use on\n      // subsequent requests.\n      if (result && result.newSessionId) {\n        auth.setSessionId(config.getAccountsDomain(), result.newSessionId);\n      }\n\n      if (process.env.METEOR_PACKAGE_STATS_TEST_OUTPUT) {\n        // Print some output for the 'report-stats' self-test.\n        process.stdout.write(\"PACKAGE STATS SENT\\n\");\n      }\n    } catch (err) {\n      logErrorIfInCheckout(err);\n      // Do nothing. A failure to record package stats shouldn't be\n      // visible to the end user and shouldn't affect whatever command\n      // they are running.\n    } finally {\n      conn && conn.close();\n    }\n  }).run();\n};\n\nvar logErrorIfInCheckout = function (err) {\n  if (files.inCheckout() || process.env.METEOR_PACKAGE_STATS_TEST_OUTPUT) {\n    Console.warn(\"Failed to record package usage.\");\n    Console.warn(\n      \"(This error is hidden when you are not running Meteor from a\",\n      \"checkout.)\");\n    var printErr = err.stack || err;\n    Console.rawWarn(printErr + \"\\n\");\n    Console.warn();\n    Console.warn();\n  }\n};\n\n// Used in a test (and can only be used against the testing packages\n// server) to fetch one package stats entry for a given application.\nvar getPackagesForAppIdInTest = function (projectContext) {\n  var conn = connectToPackagesStatsServer();\n  var result;\n  try {\n    result = conn.call(\n      \"getPackagesForAppId\",\n      projectContext.appIdentifier);\n    if (result && result.details) {\n      result.details.packages = _.sortBy(result.details.packages, \"name\");\n    }\n  } finally {\n    conn.close();\n  }\n\n  return result;\n};\n\nvar connectToPackagesStatsServer = function () {\n  return new ServiceConnection(\n    config.getPackageStatsServerUrl(),\n    {_dontPrintErrors: true}\n  );\n};\n\nexports.recordPackages = recordPackages;\nexports.packageList = packageList; // for use in the \"stats\" self-test.\nexports.getPackagesForAppIdInTest = getPackagesForAppIdInTest;\n"
  },
  {
    "path": "tools/packaging/README.md",
    "content": "Files in this folder work with the package server and download the necessary\nversions to the local file-system.\n\n## Names\n\n- Atmosphere - the packaging server UI, available at <https://atmospherejs.com/>.\n- Troposphere - the actual package server that manages, stores and serves the\n  binaries built for different architectures. It exposes an API that can be used\n  by other front-ends (meteor tool, fastosphere, etc).\n\n  _lore_: \"Troposphere is the name of atmosphere's inner-most layer!\"\n\n- Warehouse - the name of the older downloaded packages layout that was used in\n  pre-0.9.0 versions of Meteor before the official package server. Warehouse\n  wasn't suitable for the new needs, so it was deprecated, but its\n  ~~soul is still around~~ code is still used for backwards-compatibility.\n- Tropohouse - the cross of \"Troposphere\" and \"Warehouse\" - a new file-system\n  layout that is used in the post-0.9.0 world. Tropohouse stores compiled\n  Isopacks on disk by package, by version, by architecture, by build.\n- \"The Red Pill\" - a fake pre-0.9.0 format release that upgrades the Warehouse\n  to Tropohouse: [repo](https://github.com/meteor/meteor-red-pill).\n\n  _lore_: \"You take the blue pill—the story ends, you wake up in your bed and\n  believe whatever you want to believe. You take the red pill—you stay in\n  Wonderland, and I show you how deep the rabbit hole goes.\" - Morpheus to Neo,\n  Matrix.\n\n## The historical background\n\nIn the pre-0.9.0 world, the world was simple. The grass was greener, the trees\nwere taller. We were younger. 3rd party packages were none of our concern. All\n3rd party packages used to be distributed by a community-built tool called\n\"Meteorite\" or `mrt`. The packages catalog was on Atmosphere.\n\nEvery package used to be versioned with the release. Individual packages didn't\nhave a version at all. Springboarding worked by loading a different release of\nMeteor entirely from a Warehouse folder.\n\nIn the newer world that happened with the release 0.9.0 on Aug 26 2014, MDG\nrevealed the new package server that was optimized for serving tarballs, had\nversioning per package and was keeping track of builds for different\narchitectures for packages with binary dependencies.\n\nWith that, the new set of commands in CLI came along for searching packages and\nviewing the individual info (`meteor search bla` and `meteor show <bla@1.2.3>`).\n\nInternally, the on-disk storage switched to Tropohouse. Atmosphere started\nserving the packaging metadata based on Troposhere's API.\n\nMeteor Tool changed the distribution from being the central piece every release\nis tied to, to a regular package with a special architecture `meteor-tool`\n(as opposed to `server` or `web.browser`).\n\nEach package has a separate versioning line (although still optionally tied to\nreleases).\n"
  },
  {
    "path": "tools/packaging/catalog/catalog-local.js",
    "content": "var _ = require('underscore');\nvar buildmessage = require('../../utils/buildmessage.js');\nvar files = require('../../fs/files.js');\nvar watch = require('../../fs/watch.js');\nvar PackageSource = require('../../isobuild/package-source.js');\nimport { KNOWN_ISOBUILD_FEATURE_PACKAGES } from '../../isobuild/compiler.js';\n\n// LocalCatalog represents packages located in the application's\n// package directory, other package directories specified via an\n// environment variable, and core packages in the repo if meteor is\n// being run from a git checkout.\nvar LocalCatalog = function (options) {\n  var self = this;\n  options = options || {};\n\n  // Package server data.  Maps package name to a {packageSource, packageRecord,\n  // versionRecord} object.\n  self.packages = {};\n\n  self.initialized = false;\n\n    // Local directories to search for package source trees\n  self.localPackageSearchDirs = null;\n\n  // Package source trees added explicitly through a directory (not through a\n  // parent search directory). We mainly use this to allow the user to run\n  // test-packages against a package in a specific directory.\n  self.explicitlyAddedLocalPackageDirs = [];\n\n  // All packages found either by localPackageSearchDirs or\n  // explicitlyAddedLocalPackageDirs. There is a hierarchy of packages, as\n  // detailed below and there can only be one local version of a package at a\n  // time. This refers to the package by the specific package directory that we\n  // need to process.\n  self.effectiveLocalPackageDirs = [];\n\n  // A WatchSet that detects when the set of packages and their locations\n  // changes. ie, the listings of 'packages' directories, and the contents of\n  // package.js files underneath.  It does NOT track the rest of the source of\n  // the packages: that wouldn't be helpful to the runner since it would be too\n  // coarse to tell if a change is client-only or not.  (But any change to the\n  // layout of where packages live counts as a non-client-only change.)\n  self.packageLocationWatchSet = new watch.WatchSet;\n\n  self._nextId = 1;\n};\n\n_.extend(LocalCatalog.prototype, {\n  toString: function () {\n    var self = this;\n    return \"LocalCatalog [localPackageSearchDirs=\"\n      + self.localPackageSearchDirs + \"]\";\n  },\n\n  // Initialize the Catalog. This must be called before any other\n  // Catalog function.\n\n  // options:\n  //  - localPackageSearchDirs: an array of paths on local disk, that contain\n  //    subdirectories, that each contain a source tree for a package that\n  //    should override the packages on the package server. For example, if\n  //    there is a package 'foo' that we find through localPackageSearchDirs,\n  //    then we will ignore all versions of 'foo' that we find through the\n  //    package server. Directories that don't exist (or paths that aren't\n  //    directories) will be silently ignored.\n  //  - explicitlyAddedLocalPackageDirs: an array of paths which THEMSELVES\n  //    are package source trees.  Takes precedence over packages found\n  //    via localPackageSearchDirs.\n  //  - buildingIsopackets: true if we are building isopackets\n  initialize: function (options) {\n    var self = this;\n    buildmessage.assertInCapture();\n\n    options = options || {};\n\n    self.localPackageSearchDirs = _.map(\n      options.localPackageSearchDirs, function (p) {\n        return files.pathResolve(p);\n      });\n    self.explicitlyAddedLocalPackageDirs = _.map(\n      options.explicitlyAddedLocalPackageDirs, function (p) {\n        return files.pathResolve(p);\n      });\n\n    self._computeEffectiveLocalPackages();\n    self._loadLocalPackages(options.buildingIsopackets);\n    self.initialized = true;\n  },\n\n  // Throw if the catalog's self.initialized value has not been set to true.\n  _requireInitialized: function () {\n    var self = this;\n\n    if (! self.initialized)\n      throw new Error(\"catalog not initialized yet?\");\n  },\n\n  // Return an array with the names of all of the packages that we know about,\n  // in no particular order.\n  getAllPackageNames: function (options) {\n    var self = this;\n    self._requireInitialized();\n\n    return _.keys(self.packages);\n  },\n\n  // Return an array with the names of all of the non-test packages that we know\n  // about, in no particular order.\n  getAllNonTestPackageNames: function (options) {\n    var self = this;\n    self._requireInitialized();\n\n    var ret = [];\n    _.each(self.packages, function (record, name) {\n      record.versionRecord.isTest || ret.push(name);\n    });\n    return ret;\n  },\n\n  // Returns general (non-version-specific) information about a\n  // package, or null if there is no such package.\n  getPackage: function (name, options) {\n    var self = this;\n    self._requireInitialized();\n    options = options || {};\n\n    if (!_.has(self.packages, name))\n      return null;\n    return self.packages[name].packageRecord;\n  },\n\n  // Given a package, returns an array of the versions available (ie, the one\n  // version we have, or an empty array).\n  getSortedVersions: function (name) {\n    var self = this;\n    self._requireInitialized();\n\n    if (!_.has(self.packages, name))\n      return [];\n    return [self.packages[name].versionRecord.version];\n  },\n\n  // Given a package, returns an array of the version records available (ie, the\n  // one version we have, or an empty array). This method is intended for use by\n  // Version Solver's CatalogLoader.\n  //\n  // As a special case, if name is an isobuild:* pseudo-package, returns\n  // (minimal) information about it as well.\n  getSortedVersionRecords: function (name) {\n    var self = this;\n    self._requireInitialized();\n\n    if (_.has(KNOWN_ISOBUILD_FEATURE_PACKAGES, name)) {\n      return KNOWN_ISOBUILD_FEATURE_PACKAGES[name].map(\n        version => ({version, packageName: name, dependencies: {}})\n      );\n    }\n\n    if (!_.has(self.packages, name))\n      return [];\n    return [self.packages[name].versionRecord];\n  },\n\n  // Return information about a particular version of a package, or\n  // null if there is no such package or version.\n  getVersion: function (name, version) {\n    var self = this;\n    self._requireInitialized();\n\n    if (!_.has(self.packages, name))\n      return null;\n    var versionRecord = self.packages[name].versionRecord;\n    if (versionRecord.version !== version)\n      return null;\n    return versionRecord;\n  },\n\n  // As getVersion, but returns info on the latest version of the\n  // package, or null if the package doesn't exist or has no versions.\n  getLatestVersion: function (name) {\n    var self = this;\n\n    if (!_.has(self.packages, name))\n      return null;\n    return self.packages[name].versionRecord;\n  },\n\n  getVersionBySourceRoot: function (sourceRoot) {\n    var self = this;\n    var packageObj = _.find(self.packages, function (p) {\n      return p.packageSource.sourceRoot === sourceRoot;\n    });\n    if (! packageObj)\n      return null;\n    return packageObj.versionRecord;\n  },\n\n  // Compute self.effectiveLocalPackageDirs from self.localPackageSearchDirs and\n  // self.explicitlyAddedLocalPackageDirs.\n  _computeEffectiveLocalPackages: function () {\n    var self = this;\n    buildmessage.assertInCapture();\n\n    self.effectiveLocalPackageDirs = [];\n\n    buildmessage.enterJob(\"looking for packages\", function () {\n      _.each(self.explicitlyAddedLocalPackageDirs, function (explicitDir) {\n        var packageJs = watch.readAndWatchFile(\n          self.packageLocationWatchSet,\n          files.pathJoin(explicitDir, 'package.js'));\n        // We asked specifically for this directory, but it has no package!\n        if (packageJs === null) {\n          buildmessage.error(\"package has no package.js file\", {\n            file: explicitDir\n          });\n          return;  // recover by ignoring\n        }\n        self.effectiveLocalPackageDirs.push(explicitDir);\n      });\n\n      _.each(self.localPackageSearchDirs, function (searchDir) {\n        var possiblePackageDirs = watch.readAndWatchDirectory(\n          self.packageLocationWatchSet, {\n            absPath: searchDir,\n            include: [/\\/$/]\n          });\n        // Not a directory? Ignore.\n        if (possiblePackageDirs === null)\n          return;\n\n        _.each(possiblePackageDirs, function (subdir) {\n          // readAndWatchDirectory adds a slash to the end of directory names to\n          // differentiate them from filenames. Remove it.\n          subdir = subdir.substr(0, subdir.length - 1);\n          var absPackageDir = files.pathJoin(searchDir, subdir);\n\n          // Consider a directory to be a package source tree if it contains\n          // 'package.js'. (We used to support isopacks in\n          // localPackageSearchDirs, but no longer.)\n          var packageJs = watch.readAndWatchFile(\n            self.packageLocationWatchSet,\n            files.pathJoin(absPackageDir, 'package.js'));\n          if (packageJs !== null) {\n            // Let earlier package directories override later package\n            // directories.\n\n            // We don't know the name of the package, so we can't deal with\n            // duplicates yet. We are going to have to rely on the fact that we\n            // are putting these in in order, to be processed in order.\n            self.effectiveLocalPackageDirs.push(absPackageDir);\n          }\n        });\n      });\n    });\n  },\n\n  _loadLocalPackages: function (buildingIsopackets) {\n    var self = this;\n    buildmessage.assertInCapture();\n\n    // Load the package source from a directory. We don't know the names of our\n    // local packages until we do this.\n    //\n    // THIS MUST BE RUN IN LOAD ORDER. Let's say that we have two directories\n    // for mongo-livedata. The first one processed by this function will be\n    // canonical.  The second one will be ignored.\n    //\n    // (note: this is the behavior that we want for overriding things in\n    //  checkout.  It is not clear that you get good UX if you have two packages\n    //  with the same name in your app. We don't check that.)\n    var initSourceFromDir = function (packageDir, definiteName) {\n      var packageSource = new PackageSource;\n      buildmessage.enterJob({\n        title: \"reading package from `\" + packageDir + \"`\",\n        rootPath: packageDir\n      }, function () {\n        var initFromPackageDirOptions = {\n          buildingIsopackets: !! buildingIsopackets\n        };\n        // If we specified a name, then we know what we want to get and should\n        // pass that into the options. Otherwise, we will use the 'name'\n        // attribute from package-source.js.\n        if (definiteName) {\n          initFromPackageDirOptions.name = definiteName;\n        }\n        packageSource.initFromPackageDir(packageDir, initFromPackageDirOptions);\n        if (buildmessage.jobHasMessages())\n          return;  // recover by ignoring\n\n        // Now that we have initialized the package from package.js, we know its\n        // name.\n        var name = packageSource.name;\n\n        // We should only have one package dir for each name; in this case, we\n        // are going to take the first one we get (since we preserved the order\n        // in which we loaded local package dirs when running this function.)\n        if (_.has(self.packages, name))\n          return;\n\n        self.packages[name] = {\n          packageSource: packageSource,\n          packageRecord: {\n            _id: \"PID\" + self._nextId++,\n            name: name,\n            maintainers: null,\n            lastUpdated: null\n          },\n          versionRecord: {\n            _id: \"VID\" + self._nextId++,\n            packageName: name,\n            testName: packageSource.testName,\n            version: packageSource.version,\n            publishedBy: null,\n            description: packageSource.metadata.summary,\n            git: packageSource.metadata.git,\n            dependencies: packageSource.getDependencyMetadata(),\n            source: null,\n            lastUpdated: null,\n            published: null,\n            isTest: packageSource.isTest,\n            debugOnly: packageSource.debugOnly,\n            prodOnly: packageSource.prodOnly,\n            testOnly: packageSource.testOnly,\n            containsPlugins: packageSource.containsPlugins()\n          }\n        };\n\n        // If this is NOT a test package AND it has tests (tests will be\n        // marked as test packages by package source, so we will not recurse\n        // infinitely), then process that too.\n        if (!packageSource.isTest && packageSource.testName) {\n          initSourceFromDir(packageSource.sourceRoot, packageSource.testName);\n        }\n      });\n    };\n\n    // Load the package sources for packages and their tests into\n    // self.packages.\n    //\n    // XXX We should make this work with parallel: true; right now it seems to\n    // hit node problems.\n    buildmessage.forkJoin(\n      { 'title': 'initializing packages', parallel: false },\n      self.effectiveLocalPackageDirs,\n      function (dir) {\n        initSourceFromDir(dir);\n      });\n  },\n\n  getPackageSource: function (name) {\n    var self = this;\n    if (! _.has(self.packages, name))\n      return null;\n    return self.packages[name].packageSource;\n  }\n});\n\nexports.LocalCatalog = LocalCatalog;\n"
  },
  {
    "path": "tools/packaging/catalog/catalog-remote.js",
    "content": "var _ = require('underscore');\nvar sqlite3 = require('sqlite3');\n\nvar files = require('../../fs/files.js');\nvar utils = require('../../utils/utils.js');\nvar buildmessage = require('../../utils/buildmessage.js');\nvar config = require('../../meteor-services/config.js');\nvar archinfo = require('../../utils/archinfo.js');\nvar Console = require('../../console/console.js').Console;\n\nvar tropohouse = require('../tropohouse.js');\nvar packageClient = require('../package-client.js');\nvar VersionParser = require('../package-version-parser.js');\nvar Profile = require('../../tool-env/profile.js').Profile;\n\n// XXX: Rationalize these flags.  Maybe use the logger?\nvar DEBUG_SQL = !!process.env.METEOR_DEBUG_SQL;\n\nvar SYNCTOKEN_ID = \"1\";\n\nvar METADATA_LAST_SYNC = \"lastsync\";\n\nvar BUSY_RETRY_ATTEMPTS = 10;\nvar BUSY_RETRY_INTERVAL = 1000;\n\nvar Mutex = function () {\n  var self = this;\n\n  self._locked = false;\n\n  self._resolvers = [];\n};\n\n_.extend(Mutex.prototype, {\n  lock: function () {\n    var self = this;\n\n    while (true) {\n      if (!self._locked) {\n        self._locked = true;\n        return;\n      }\n\n      new Promise(function (resolve) {\n        self._resolvers.push(resolve);\n      }).await();\n    }\n  },\n\n  unlock: function () {\n    var self = this;\n\n    if (!self._locked) {\n      throw new Error(\"unlock called on unlocked mutex\");\n    }\n\n    self._locked = false;\n    var resolve = self._resolvers.shift();\n    if (resolve) {\n      resolve();\n    }\n  }\n});\n\nvar Txn = function (db) {\n  var self = this;\n  self.db = db;\n  self.closed = false;\n  self.committed = false;\n  self.started = false;\n};\n\n_.extend(Txn.prototype, {\n  // Runs a SQL query and returns the rows\n  query: function (sql, params) {\n    var self = this;\n    return self.db._query(sql, params);\n  },\n\n  // Runs a SQL statement, returning no rows\n  execute: function (sql, params) {\n    var self = this;\n    return self.db._execute(sql, params);\n  },\n\n  // Start a transaction\n  begin: function (mode) {\n    var self = this;\n\n    // XXX: Use DEFERRED mode?\n    mode = mode || \"IMMEDIATE\";\n\n    if (self.started) {\n      throw new Error(\"Transaction already started\");\n    }\n\n    self.db._execute(\"BEGIN \" + mode + \" TRANSACTION\");\n    self.started = true;\n  },\n\n  // Releases resources from the transaction; Rollback if commit not already called.\n  close: function () {\n    var self = this;\n\n    if (self.closed) {\n      return;\n    }\n\n    if (!self.started) {\n      return;\n    }\n\n    self.db._execute(\"ROLLBACK TRANSACTION\");\n    self.committed = false;\n    self.closed = true;\n  },\n\n  // Commits the transaction.  close() will then be a no-op\n  commit: function () {\n    var self = this;\n\n    self.db._execute(\"END TRANSACTION\");\n    self.committed = true;\n    self.closed = true;\n  }\n});\n\nvar Db = function (dbFile, options) {\n  var self = this;\n\n  self._dbFile = dbFile;\n\n  self._autoPrepare = true;\n  self._prepared = {};\n\n  self._transactionMutex = new Mutex();\n\n  self._db = self._retry(function () {\n    return self.open(dbFile);\n  });\n\n  // WAL mode copes much better with (multi-process) concurrency\n  self._retry(function () {\n    self._execute('PRAGMA journal_mode=WAL');\n  });\n};\n\n_.extend(Db.prototype, {\n\n  // TODO: Move to utils?\n  _retry: function (f, options) {\n    options = _.extend({ maxAttempts: 3, delay: 500}, options || {});\n\n    for (var attempt = 1; attempt <= options.maxAttempts; attempt++) {\n      try {\n        return f();\n      } catch (err) {\n        if (attempt < options.maxAttempts) {\n          Console.warn(\"Retrying after error\", err);\n        } else {\n          throw err;\n        }\n      }\n\n      if (options.delay) {\n        utils.sleepMs(options.delay);\n      }\n    }\n  },\n\n  // Runs functions serially, in a mutex\n  _serialize: function (f) {\n    var self = this;\n\n    try {\n      self._transactionMutex.lock();\n      return f();\n    } finally {\n      self._transactionMutex.unlock();\n    }\n  },\n\n  // Do not call any other methods on this object after calling this one.\n  // This yields.\n  closePermanently: function () {\n    var self = this;\n    self._closePreparedStatements();\n    var db = self._db;\n    self._db = null;\n    new Promise((resolve, reject) => {\n      db.close(err => err ? reject(err) : resolve());\n    }).await();\n  },\n\n  // Runs the function inside a transaction block\n  runInTransaction: function (action) {\n    var self = this;\n\n    var runOnce = Profile(\"sqlite query\", function () {\n      var txn = new Txn(self);\n\n      var t1 = Date.now();\n\n      var rollback = true;\n      var result = null;\n      var resultError = null;\n\n      txn.begin();\n      try {\n        result = action(txn);\n        txn.commit();\n      } catch (err) {\n        resultError = err;\n      } finally {\n        try {\n          txn.close();\n        } catch (e) {\n          // We don't have a lot of options here...\n          Console.warn(\"Error closing transaction\", e);\n        }\n      }\n\n      //self._closePreparedStatements();\n\n      if (DEBUG_SQL) {\n        var t2 = Date.now();\n        // XXX: Hack around not having loggers\n        Console.info(\"Transaction took: \", (t2 - t1));\n      }\n\n      if (resultError) {\n        throw resultError;\n      }\n\n      return result;\n    });\n\n    for (var attempt = 0; ; attempt++) {\n      try {\n        return self._serialize(runOnce);\n      } catch (err) {\n        var retry = false;\n        // Grr... doesn't expose error code; must string-match\n        if (err.message\n            && (   err.message == \"SQLITE_BUSY: database is locked\"\n                || err.message == \"SQLITE_BUSY: cannot commit transaction - SQL statements in progress\")) {\n          if (attempt < BUSY_RETRY_ATTEMPTS) {\n            retry = true;\n          }\n        }\n        if (!retry) {\n          throw err;\n        }\n      }\n\n      // Wait on average BUSY_RETRY_INTERVAL, but randomize to avoid thundering herd\n      var t = (Math.random() + 0.5) * BUSY_RETRY_INTERVAL;\n      utils.sleepMs(t);\n    }\n  },\n\n  open: function (dbFile) {\n    var self = this;\n\n    if ( !files.exists(files.pathDirname(dbFile)) ) {\n      Console.debug(\"Creating database directory\", dbFile);\n\n      var folder = files.pathDirname(dbFile);\n      if ( !files.mkdir_p(folder) )\n        throw new Error(\"Could not create folder at \" + folder);\n    }\n\n    Console.debug(\"Opening db file\", dbFile);\n    return new sqlite3.Database(files.convertToOSPath(dbFile));\n  },\n\n  // Runs a query synchronously, returning all rows\n  // Hidden to enforce transaction usage\n  _query: function (sql, params) {\n    var self = this;\n\n    var prepared = null;\n    var prepare = self._autoPrepare && !_.isEmpty(params);\n    if (prepare) {\n      prepared = self._prepareWithCache(sql);\n    }\n\n    if (DEBUG_SQL) {\n      var t1 = Date.now();\n    }\n\n    //Console.debug(\"Executing SQL \", sql, params);\n\n    var rows = new Promise((resolve, reject) => {\n      function callback(err, rows) {\n        err ? reject(err) : resolve(rows);\n      }\n\n      if (prepared) {\n        prepared.all(params, callback);\n      } else {\n        self._db.all(sql, params, callback);\n      }\n    }).await();\n\n    if (DEBUG_SQL) {\n      var t2 = Date.now();\n      if ((t2 - t1) > 10) {\n        // XXX: Hack around not having log levels\n        Console.info(\"SQL statement \", sql, \" took \", (t2 - t1));\n      }\n    }\n\n    return rows;\n  },\n\n  // Runs a query synchronously, returning no rows\n  // Hidden to enforce transaction usage\n  _execute: function (sql, params) {\n    var self = this;\n\n    var prepared = null;\n    // We don't prepare non-parametrized statements, because (a) there's not\n    // that much of a win from doing so, since we don't tend to run them in bulk\n    // and (b) doing so can trigger\n    // https://github.com/mapbox/node-sqlite3/pull/355 .  (We can avoid that bug\n    // by being careful to pass in an empty array or no argument for params to\n    // prepared.run instead of undefined, but we can also just avoid the issue\n    // entirely.)\n    var prepare = self._autoPrepare && !_.isEmpty(params);\n    if (prepare) {\n      prepared = self._prepareWithCache(sql);\n    }\n\n    if (DEBUG_SQL) {\n      var t1 = Date.now();\n    }\n\n    //Console.debug(\"Executing SQL \", sql, params);\n\n    var ret = new Promise(function (resolve, reject) {\n      function callback(err) {\n        err ? reject(err) : resolve({\n          // Yes, lastID & changes are on this(!)\n          lastID: this.lastID,\n          changes: this.changes\n        });\n      }\n\n      if (prepared) {\n        prepared.run(params, callback);\n      } else {\n        self._db.run(sql, params, callback);\n      }\n    }).await();\n\n    if (DEBUG_SQL) {\n      var t2 = Date.now();\n      if ((t2 - t1) > 10) {\n        Console.info(\"SQL statement \", sql, \" took \", (t2 - t1));\n      }\n    }\n\n    return ret;\n  },\n\n  // Prepares the statement, caching the result\n  _prepareWithCache: function (sql) {\n    var self = this;\n\n    var prepared = self._prepared[sql];\n    if (!prepared) {\n      //Console.debug(\"Preparing statement: \", sql);\n      new Promise(function (resolve, reject) {\n        prepared = self._db.prepare(sql, function (err) {\n          err ? reject(err) : resolve();\n        });\n      }).await();\n\n      self._prepared[sql] = prepared;\n    }\n\n    return prepared;\n  },\n\n\n  // Close any cached prepared statements\n  _closePreparedStatements: function () {\n    var self = this;\n\n    var prepared = self._prepared;\n    self._prepared = {};\n\n    _.each(prepared, function (statement) {\n      var err = new Promise(function (resolve) {\n        // We resolve the promise with an error instead of rejecting it,\n        // because we don't want to throw.\n        statement.finalize(resolve);\n      }).await();\n\n      if (err) {\n        Console.warn(\"Error finalizing statement \", err);\n      }\n    });\n  }\n\n});\n\n\nvar Table = function (name, jsonFields, options) {\n  var self = this;\n  options = options || {};\n\n  self.name = name;\n  self.jsonFields = jsonFields;\n  self.noContentColumn = options.noContentColumn;\n\n  self._buildStatements();\n};\n\n_.extend(Table.prototype, {\n  _buildStatements: function () {\n    var self = this;\n\n    var queryParams = self._generateQuestionMarks(\n      self.jsonFields.length + (self.noContentColumn ? 0 : 1));\n    self._selectQuery = \"SELECT * FROM \" + self.name + \" WHERE _id=?\";\n    self._insertQuery = \"INSERT INTO \" + self.name + \" VALUES \" + queryParams;\n    self._deleteQuery = \"DELETE FROM \" + self.name + \" WHERE _id=?\";\n  },\n\n  // Generate a string of the form (?, ?) where the n is the number of question\n  // mark.\n  _generateQuestionMarks: function (n) {\n    return \"(\" + _.times(n, function () { return \"?\" }).join(\",\") + \")\";\n  },\n\n  find: function (txn, id) {\n    var self = this;\n    var rows = txn.query(self._selectQuery, [ id ]);\n    if (rows.length !== 0) {\n      if (rows.length !== 1) {\n        throw new Error(\"Corrupt database (PK violation)\");\n      }\n      return rows[0];\n    }\n    return undefined;\n  },\n\n  upsert: function (txn, objects) {\n    var self = this;\n\n    // XXX: Use sqlite upsert\n    // XXX: Speculative insert\n    // XXX: Fix transaction logic so we always roll back\n    _.each(objects, function (o) {\n      var id = o._id;\n      var rows = txn.query(self._selectQuery, [ id ]);\n      if (rows.length !== 0) {\n        var deleteResults = txn.execute(self._deleteQuery, [ id ]);\n        if (deleteResults.changes !== 1) {\n          throw new Error(\"Unable to delete row: \" + id);\n        }\n      }\n      var row = [];\n      _.each(self.jsonFields, function (jsonField) {\n        row.push(o[jsonField]);\n      });\n      if (! self.noContentColumn) {\n        row.push(JSON.stringify(o));\n      }\n      txn.execute(self._insertQuery, row);\n    });\n  },\n\n  createTable: function (txn) {\n    var self = this;\n\n    var sql = 'CREATE TABLE IF NOT EXISTS ' + self.name + '(';\n    for (var i = 0; i < self.jsonFields.length; i++) {\n      var jsonField = self.jsonFields[i];\n      var sqlColumn = jsonField;\n      if (i != 0) sql += \", \";\n      sql += sqlColumn + \" STRING\";\n      if (sqlColumn === '_id') {\n        sql += \" PRIMARY KEY\";\n      }\n    }\n    if (! self.noContentColumn) {\n      sql += \", content STRING\";\n    }\n    sql += \")\";\n    txn.execute(sql);\n\n    //sql = \"CREATE INDEX IF NOT EXISTS idx_\" + self.name + \"_id ON \" + self.name + \"(_id)\";\n    //txn.execute(sql);\n  }\n});\n\n\n// A RemoteCatalog is a local cache of the content of troposphere.\n// A default instance of this catalog is registered by the layered catalog and is available\n// under the variable \"official\" from the catalog.js\n//\n// The remote catalog is backed by a db to make things easier on the memory and for faster queries\nvar RemoteCatalog = function () {\n  var self = this;\n\n  // Set this to true if we are not going to connect to the remote package\n  // server, and will only use the cached data for our package information\n  // This means that the catalog might be out of date on the latest developments.\n  self.offline = null;\n\n  self.db = null;\n};\n\n_.extend(RemoteCatalog.prototype, {\n  toString: function () {\n    var self = this;\n    return \"RemoteCatalog\";\n  },\n\n  // Used for special cases that want to ensure that all connections to the DB\n  // are closed (eg to ensure that all writes have been flushed from the '-wal'\n  // file to the main DB file). Most methods on this class will stop working\n  // after you call this method. Note that this yields.\n  closePermanently: function () {\n    var self = this;\n    self.db.closePermanently();\n    self.db = null;\n  },\n\n  getVersion: function (name, version) {\n    var result = this._contentQuery(\n      \"SELECT content FROM versions WHERE packageName=? AND version=?\",\n      [name, version]);\n    if(!result || result.length === 0) {\n      return null;\n    }\n    return result[0];\n  },\n\n  // As getVersion, but returns info on the latest version of the\n  // package, or null if the package doesn't exist or has no versions.\n  getLatestVersion: function (name) {\n    var self = this;\n\n    var versions = self.getSortedVersions(name);\n    return self.getVersion(name, _.last(versions));\n  },\n\n  getSortedVersions: function (name) {\n    var self = this;\n    var match = this._columnsQuery(\n      \"SELECT version FROM versions WHERE packageName=?\", name);\n    if (match === null)\n      return [];\n    var pvParse = _.memoize(VersionParser.parse);\n    return _.pluck(match, 'version').sort(function (a, b) {\n      return VersionParser.compare(pvParse(a), pvParse(b));\n    });\n  },\n\n  // Just getVersion mapped over getSortedVersions, but only makes one round\n  // trip to sqlite.\n  getSortedVersionRecords: function (name) {\n    var self = this;\n    var versionRecords = this._contentQuery(\n      \"SELECT content FROM versions WHERE packageName=?\", [name]);\n    if (! versionRecords)\n      return [];\n\n    var pvParse = _.memoize(VersionParser.parse);\n    versionRecords.sort(function (a, b) {\n      return VersionParser.compare(pvParse(a.version),\n                                   pvParse(b.version));\n    });\n    return versionRecords;\n  },\n\n  getLatestMainlineVersion: function (name) {\n    var self = this;\n    var versions = self.getSortedVersions(name);\n    versions.reverse();\n    var latest = _.find(versions, function (version) {\n      return !/-/.test(version);\n    });\n    if (!latest)\n      return null;\n    return self.getVersion(name, latest);\n  },\n\n  getPackage: function (name, options) {\n    var result = this._contentQuery(\n      \"SELECT content FROM packages WHERE name=?\", name);\n    if (!result || result.length === 0)\n      return null;\n    if (result.length !== 1) {\n      throw new Error(\"Found multiple packages matching name: \" + name);\n    }\n    return result[0];\n  },\n\n  getAllBuilds: function (name, version) {\n    var result = this._contentQuery(\n      \"SELECT content FROM builds WHERE builds.versionId = \" +\n        \"(SELECT _id FROM versions WHERE versions.packageName=? AND \" +\n        \"versions.version=?)\",\n      [name, version]);\n    if (!result || result.length === 0)\n      return null;\n    return result;\n  },\n\n  // If this package has any builds at this version, return an array of builds\n  // which cover all of the required arches, or null if it is impossible to\n  // cover them all (or if the version does not exist).\n  // Note that this method is specific to RemoteCatalog.\n  getBuildsForArches: function (name, version, arches) {\n    var self = this;\n\n    var solution = null;\n    var allBuilds = self.getAllBuilds(name, version) || [];\n\n    utils.generateSubsetsOfIncreasingSize(allBuilds, function (buildSubset) {\n      // This build subset works if for all the arches we need, at least one\n      // build in the subset satisfies it. It is guaranteed to be minimal,\n      // because we look at subsets in increasing order of size.\n      var satisfied = _.all(arches, function (neededArch) {\n        return _.any(buildSubset, function (build) {\n          var buildArches = build.buildArchitectures.split('+');\n          return !!archinfo.mostSpecificMatch(neededArch, buildArches);\n        });\n      });\n      if (satisfied) {\n        solution = buildSubset;\n        return true;  // stop the iteration\n      }\n    });\n    return solution;  // might be null!\n  },\n\n  // Returns general (non-version-specific) information about a\n  // release track, or null if there is no such release track.\n  getReleaseTrack: function (name) {\n    var self = this;\n    var result = self._contentQuery(\n      \"SELECT content FROM releaseTracks WHERE name=?\", name);\n    if (!result || result.length === 0)\n      return null;\n    return result[0];\n  },\n\n  getReleaseVersion: function (track, version) {\n    var self = this;\n    var result = self._contentQuery(\n      \"SELECT content FROM releaseVersions WHERE track=? AND version=?\",\n      [track, version]);\n    if (!result || result.length === 0)\n      return null;\n    return result[0];\n  },\n\n  // Used by make-bootstrap-tarballs. Only should be used on catalogs that are\n  // specially constructed for bootstrap tarballs.\n  forceRecommendRelease: function (track, version) {\n    var self = this;\n    var releaseVersionData = self.getReleaseVersion(track, version);\n    if (!releaseVersionData) {\n      throw Error(\"Can't force-recommend unknown release \" + track + \"@\"\n                  + version);\n    }\n    releaseVersionData.recommended = true;\n    self._insertReleaseVersions([releaseVersionData]);\n  },\n\n  getAllReleaseTracks: function () {\n    return _.pluck(this._columnsQuery(\"SELECT name FROM releaseTracks\"),\n                   'name');\n  },\n\n  getAllPackageNames: function () {\n    return _.pluck(this._columnsQuery(\"SELECT name FROM packages\"), 'name');\n  },\n\n  initialize: function (options) {\n    var self = this;\n\n    options = options || {};\n    // We should to figure out if we are intending to connect to the package server.\n    self.offline = options.offline ? options.offline : false;\n\n    var dbFile = options.packageStorage || config.getPackageStorage();\n    self.db = new Db(dbFile);\n\n    self.tableVersions = new Table('versions', ['packageName', 'version', '_id']);\n    self.tableBuilds = new Table('builds', ['versionId', '_id']);\n    self.tableReleaseTracks = new Table('releaseTracks', ['name', '_id']);\n    self.tableReleaseVersions = new Table('releaseVersions', ['track', 'version', '_id']);\n    self.tablePackages = new Table('packages', ['name', '_id']);\n    self.tableSyncToken = new Table('syncToken', ['_id']);\n    self.tableMetadata = new Table('metadata', ['_id']);\n    self.tableBannersShown = new Table(\n      'bannersShown', ['_id', 'lastShown'], { noContentColumn: true });\n\n    self.allTables = [\n      self.tableVersions,\n      self.tableBuilds,\n      self.tableReleaseTracks,\n      self.tableReleaseVersions,\n      self.tablePackages,\n      self.tableSyncToken,\n      self.tableMetadata,\n      self.tableBannersShown\n    ];\n    return self.db.runInTransaction(function(txn) {\n      _.each(self.allTables, function (table) {\n        table.createTable(txn);\n      });\n\n      // Extra indexes for the most expensive queries\n      // These are non-unique indexes\n      // XXX We used to have a versionsNamesIdx here on versions(packageName);\n      //     we no longer create it but we don't waste time dropping it either.\n      txn.execute(\"CREATE INDEX IF NOT EXISTS versionsIdx ON \" +\n                  \"versions(packageName, version)\");\n      txn.execute(\"CREATE INDEX IF NOT EXISTS buildsVersionsIdx ON \" +\n                  \"builds(versionId)\");\n      txn.execute(\"CREATE INDEX IF NOT EXISTS packagesIdx ON \" +\n                  \"packages(name)\");\n      txn.execute(\"CREATE INDEX IF NOT EXISTS releaseTracksIdx ON \" +\n                  \"releaseTracks(name)\");\n      txn.execute(\"CREATE INDEX IF NOT EXISTS releaseVersionsIdx ON \" +\n                  \"releaseVersions(track, version)\");\n    });\n  },\n\n  // This function empties the DB. This is called from the package-client.\n  reset: function () {\n    var self = this;\n    return self.db.runInTransaction(function (txn) {\n      _.each(self.allTables, function (table) {\n        txn.execute(\"DELETE FROM \" + table.name);\n      });\n    });\n  },\n\n  refresh: function (options) {\n    var self = this;\n    options = options || {};\n\n    Console.debug(\"In remote catalog refresh\");\n\n    if (process.env.METEOR_TEST_FAIL_RELEASE_DOWNLOAD === 'offline') {\n      var e = new Error;\n      e.errorType = 'DDP.ConnectionError';\n      throw e;\n    }\n\n    if (self.offline)\n      return false;\n\n    if (options.maxAge) {\n      var lastSync = self.getMetadata(METADATA_LAST_SYNC);\n      Console.debug(\"lastSync = \", lastSync);\n      if (lastSync && lastSync.timestamp) {\n        if ((Date.now() - lastSync.timestamp) < options.maxAge) {\n          Console.debug(\"Package catalog is sufficiently up-to-date; not updating\\n\");\n          return false;\n        }\n      }\n    }\n\n    var updateResult = {};\n    // XXX This buildmessage.enterJob only exists for showing progress.\n    buildmessage.enterJob({ title: 'updating package catalog' }, function () {\n      updateResult = packageClient.updateServerPackageData(self);\n    });\n\n    if (updateResult.resetData) {\n      tropohouse.default.wipeAllPackages();\n    }\n\n    return true;\n  },\n\n  // Given a release track, returns all recommended versions for this track,\n  // sorted by their orderKey. Returns the empty array if the release track does\n  // not exist or does not have any recommended versions.\n  getSortedRecommendedReleaseVersions: function (track, laterThanOrderKey) {\n    var self = this;\n    var versions =\n          self.getSortedRecommendedReleaseRecords(track, laterThanOrderKey);\n    return _.pluck(versions, \"version\");\n  },\n\n  // Given a release track, returns all recommended version *records* for this\n  // track, sorted by their orderKey. Returns the empty array if the release\n  // track does not exist or does not have any recommended versions.\n  getSortedRecommendedReleaseRecords: function (track, laterThanOrderKey) {\n    var self = this;\n    // XXX releaseVersions content objects are kinda big; if we put\n    // 'recommended' and 'orderKey' in their own columns this could be faster\n    var result = self._contentQuery(\n      \"SELECT content FROM releaseVersions WHERE track=?\", track);\n\n    var recommended = _.filter(result, function (v) {\n      if (!v.recommended)\n        return false;\n      return !laterThanOrderKey || v.orderKey > laterThanOrderKey;\n    });\n\n    var recSort = _.sortBy(recommended, function (rec) {\n      return rec.orderKey;\n    });\n    recSort.reverse();\n    return recSort;\n  },\n\n  // Given a release track, returns all version records for this track.\n  getReleaseVersionRecords: function (track) {\n    var self = this;\n    var result = self._contentQuery(\n      \"SELECT content FROM releaseVersions WHERE track=?\", track);\n    return result;\n  },\n\n  // For a given track, returns the total number of release versions on that\n  // track.\n  getNumReleaseVersions: function (track) {\n    var self = this;\n    var result = self._columnsQuery(\n      \"SELECT count(*) FROM releaseVersions WHERE track=?\", track);\n    return result[0][\"count(*)\"];\n  },\n\n  // Returns the default release version on the DEFAULT_TRACK, or for a\n  // given release track.\n  getDefaultReleaseVersion: function (track) {\n    var self = this;\n    var versionRecord = self.getDefaultReleaseVersionRecord(track);\n    if (! versionRecord)\n      throw new Error(\"Can't get default release version for track \" + track);\n    return _.pick(versionRecord, [\"track\", \"version\" ]);\n  },\n\n  // Returns the default release version record for the DEFAULT_TRACK, or for a\n  // given release track.\n  getDefaultReleaseVersionRecord: function (track) {\n    var self = this;\n\n    if (!track)\n      track = exports.DEFAULT_TRACK;\n\n    var versions = self.getSortedRecommendedReleaseRecords(track);\n    if (!versions.length)\n      return null;\n    return  versions[0];\n  },\n\n  getBuildWithPreciseBuildArchitectures: function (versionRecord, buildArchitectures) {\n    var self = this;\n    var matchingBuilds = this._contentQuery(\n      \"SELECT content FROM builds WHERE versionId=?\", versionRecord._id);\n    return _.findWhere(matchingBuilds, { buildArchitectures: buildArchitectures });\n  },\n\n  // Executes a query, returning an array of each content column parsed as JSON\n  _contentQuery: function (query, params) {\n    var self = this;\n    var rows = self._columnsQuery(query, params);\n    return _.map(rows, function(entity) {\n      return JSON.parse(entity.content);\n    });\n  },\n\n  // Executes a query, returning an array of maps from column name to data.\n  // No JSON parsing is performed.\n  _columnsQuery: function (query, params) {\n    var self = this;\n    var rows = self.db.runInTransaction(function (txn) {\n      return txn.query(query, params);\n    });\n    return rows;\n  },\n\n  _insertReleaseVersions: function(releaseVersions) {\n    var self = this;\n    return self.db.runInTransaction(function (txn) {\n      self.tableReleaseVersions.upsert(txn, releaseVersions);\n    });\n  },\n\n  //Given data from troposphere, add it into the local store\n  insertData: function(serverData, syncComplete) {\n    var self = this;\n    return self.db.runInTransaction(function (txn) {\n      self.tablePackages.upsert(txn, serverData.collections.packages);\n      self.tableBuilds.upsert(txn, serverData.collections.builds);\n      self.tableVersions.upsert(txn, serverData.collections.versions);\n      self.tableReleaseTracks.upsert(txn, serverData.collections.releaseTracks);\n      self.tableReleaseVersions.upsert(txn, serverData.collections.releaseVersions);\n\n      var syncToken = serverData.syncToken;\n      Console.debug(\"Adding syncToken: \", JSON.stringify(syncToken));\n      syncToken._id = SYNCTOKEN_ID; //Add fake _id so it fits the pattern\n      self.tableSyncToken.upsert(txn, [syncToken]);\n\n      if (syncComplete) {\n        var lastSync = {timestamp: Date.now()};\n        self._setMetadata(txn, METADATA_LAST_SYNC, lastSync);\n      }\n    });\n  },\n\n  getSyncToken: function() {\n    var self = this;\n    var result = self._contentQuery(\"SELECT content FROM syncToken WHERE _id=?\",\n                                    [ SYNCTOKEN_ID ]);\n    if (!result || result.length === 0) {\n      Console.debug(\"No sync token found\");\n      return null;\n    }\n    if (result.length !== 1) {\n      throw new Error(\"Unexpected number of sync tokens found\");\n    }\n    delete result[0]._id;\n    Console.debug(\"Returning sync token: \" + JSON.stringify(result[0]));\n    return result[0];\n  },\n\n  getMetadata: function(key) {\n    var self = this;\n    var row = self.db.runInTransaction(function (txn) {\n      return self.tableMetadata.find(txn, key);\n    });\n    if (row) {\n      return JSON.parse(row['content']);\n    }\n    return undefined;\n  },\n\n  setMetadata: function(key, value) {\n    var self = this;\n    self.db.runInTransaction(function (txn) {\n      self._setMetadata(txn, key, value);\n    });\n  },\n\n  _setMetadata: function(txn, key, value) {\n    var self = this;\n    value._id = key;\n    self.tableMetadata.upsert(txn, [value]);\n  },\n\n  shouldShowBanner: function (releaseName, bannerDate) {\n    var self = this;\n    var row = self.db.runInTransaction(function (txn) {\n      return self.tableBannersShown.find(txn, releaseName);\n    });\n    // We've never printed a banner for this release.\n    if (! row)\n      return true;\n    try {\n      var lastShown = new Date(JSON.parse(row.lastShown));\n      return lastShown < bannerDate;\n    } catch (e) {\n      // Probably an error in JSON.parse or something. Just show the banner.\n      return true;\n    }\n  },\n\n  setBannerShownDate: function (releaseName, bannerShownDate) {\n    var self = this;\n    self.db.runInTransaction(function (txn) {\n      self.tableBannersShown.upsert(txn, [{\n        _id: releaseName,\n        // XXX For now, there's no way to tell this file to make a non-string\n        // column in a sqlite table, but this should probably change to a\n        // 'timestamp with time zone' or whatever.\n        lastShown: JSON.stringify(bannerShownDate)\n      }]);\n    });\n  }\n});\n\nexports.RemoteCatalog = RemoteCatalog;\n\n// We put this constant here because we don't have any better place that would otherwise cause a cycle\nexports.DEFAULT_TRACK = 'METEOR';\n\n// The catalog as provided by troposhere (aka atomospherejs.com)\nexports.official = new RemoteCatalog();\n"
  },
  {
    "path": "tools/packaging/catalog/catalog-utils.js",
    "content": "exports.splitReleaseName = function (releaseName) {\n  var parts = releaseName.split('@');\n  var track, version;\n  if (parts.length === 1) {\n    var catalog = require('./catalog.js');\n    track = catalog.DEFAULT_TRACK;\n    version = parts[0];\n  } else {\n    track = parts[0];\n    // Do we forbid '@' sign in release versions? I sure hope so, but let's\n    // be careful.\n    version = parts.slice(1).join(\"@\");\n  }\n  return [track, version];\n};\n\n// Options: noPrefix: do not display 'Meteor ' in front of the version number.\nexports.displayRelease = function (track, version, options) {\n  var catalog = require('./catalog.js');\n  options = options || {};\n  var prefix = options.noPrefix ? \"\" : \"Meteor \";\n\n  if (track === catalog.DEFAULT_TRACK) {\n    return prefix + version;\n  } else {\n    return track + '@' + version;\n  }\n};\n\n// If we have failed to update the catalog, informs the user and advises them to\n// go online for up to date inforation.\nexports.explainIfRefreshFailed = function () {\n  var Console = require('../../console/console.js').Console;\n  var catalog = require('./catalog.js');\n  if (catalog.official.offline || catalog.refreshFailed) {\n    Console.info(\"Your package catalog may be out of date.\\n\" +\n      \"Please connect to the internet and try again.\");\n  }\n};\n"
  },
  {
    "path": "tools/packaging/catalog/catalog.js",
    "content": "var _ = require('underscore');\nvar remoteCatalog = require('./catalog-remote.js');\nvar Console = require('../../console/console.js').Console;\nvar buildmessage = require('../../utils/buildmessage.js');\n\nvar catalog = exports;\n\ncatalog.refreshFailed = undefined;\ncatalog.triedToRefreshRecently = false;\n\ncatalog.Refresh = {};\n\n// Refresh strategy: once at program start\ncatalog.Refresh.OnceAtStart = function (options) {\n  var self = this;\n  self.options = _.extend({}, options);\n};\n\ncatalog.Refresh.OnceAtStart.prototype.beforeCommand = function () {\n  var self = this;\n  if (!catalog.refreshOrWarn(self.options)) {\n    if (self.options.ignoreErrors) {\n      Console.debug(\"Failed to update package catalog, but will continue.\");\n    } else {\n      Console.printError(catalog.refreshError);\n      Console.error(\"This command requires an up-to-date package catalog.  Exiting.\");\n      // Avoid circular dependency.\n      throw new (require('../../cli/main.js').ExitWithCode)(1);\n    }\n  }\n};\n\n// Refresh strategy: never (we don't use the package catalog)\ncatalog.Refresh.Never = function (options) {\n  var self = this;\n  self.options = _.extend({}, options);\n};\n\n// Refreshes the catalog. Returns true on success.\n// On network error, warns and returns false.\n// Throws other errors (ie, programming errors in the tool).\n//\n// THIS IS A HIGH-LEVEL UI COMMAND. DO NOT CALL IT FROM LOW-LEVEL CODE (ie, call\n// it only from main.js or command implementations).\ncatalog.refreshOrWarn = function (options) {\n  catalog.triedToRefreshRecently = true;\n  try {\n    catalog.official.refresh(options);\n    catalog.refreshFailed = false;\n    return true;\n  } catch (err) {\n    // Example errors:\n\n    // Offline, with name-based host:\n    //   Network error: ws://packages.meteor.com/websocket: getaddrinfo ENOTFOUND\n\n    // Offline, with IP-based host:\n    //   Network error: ws://8.8.8.8/websocket: connect ENETUNREACH\n\n    // Online, bad port:\n    //    Network error: wss://packages.meteor.com:8888/websocket: connect ECONNREFUSED\n\n    // Online, socket hangup:\n    //   Network error: wss://packages.meteor.com:80/websocket: socket hang up\n\n    if (err.errorType !== 'DDP.ConnectionError')\n      throw err;\n\n    // XXX is throwing correct for SQLite errors too? probably.\n\n    Console.warn(\"Unable to update package catalog (are you offline?)\");\n    Console.warn();\n    Console.warn(\n      \"If you are using Meteor behind a proxy, set HTTP_PROXY and HTTPS_PROXY environment variables or see this page for more details: \",\n      Console.url(\"https://github.com/meteor/meteor/wiki/Using-Meteor-behind-a-proxy\"));\n\n    // XXX: Make this Console.debug(err)\n    if (Console.isDebugEnabled()) {\n      Console.printError(err);\n    }\n\n    Console.warn();\n\n    catalog.refreshFailed = true;\n    catalog.refreshError = err;\n    return false;\n  }\n};\n\n// Runs 'attempt'; if it fails in a way that can be fixed by refreshing the\n// official catalog, does that and tries again.\ncatalog.runAndRetryWithRefreshIfHelpful = function (attempt) {\n  buildmessage.assertInJob();\n\n  var canRetry = ! (catalog.triedToRefreshRecently ||\n                    catalog.official.offline);\n\n  // Run `attempt` in a nested buildmessage context.\n  var messages = buildmessage.capture(function () {\n    attempt(canRetry);\n  });\n\n  // Did it work? Great.\n  if (! messages.hasMessages()) {\n    return;\n  }\n\n  // Is refreshing unlikely to be useful, either because the error wasn't\n  // related to that, or because we tried to refresh recently, or because we're\n  // not allowed to refresh? Fail, merging the result of these errors into the\n  // current job.\n  if (! (messages.hasMessageWithTag('refreshCouldHelp') && canRetry)) {\n    buildmessage.mergeMessagesIntoCurrentJob(messages);\n    return;\n  }\n\n  // Refresh!\n  // XXX This is a little hacky, as it shares a bunch of code with\n  // catalog.refreshOrWarn, which is a higher-level function that's allowed to\n  // log.\n  catalog.triedToRefreshRecently = true;\n  try {\n    catalog.official.refresh();\n    catalog.refreshFailed = false;\n  } catch (err) {\n    if (err.errorType !== 'DDP.ConnectionError')\n      throw err;\n    // First place the previous errors in the capture.\n    buildmessage.mergeMessagesIntoCurrentJob(messages);\n    // Then put an error representing this DDP error.\n    buildmessage.enterJob(\n      \"refreshing package catalog to resolve previous errors\",\n      function () {\n        buildmessage.error(err.message);\n      }\n    );\n    return;\n  }\n\n  // Try again, this time directly in the current buildmessage job.\n  attempt(false); // canRetry = false\n};\n\n// As a work-around for [] !== [], we use a function to check whether values are acceptable\nvar ACCEPT_NON_EMPTY = function (result) {\n  // null, undefined\n  if (result === null || result === undefined) {\n    return false;\n  }\n  // []\n  if (result.length === 0) {\n    return false;\n  }\n  return true;\n};\n\n// The LayeredCatalog provides a way to query multiple catalogs in a uniform way\n// A LayeredCatalog contains:\n//  - a local catalog referencing the packages of the project\n//  - a reference to the official catalog\nvar LayeredCatalog = function (localCatalog, otherCatalog) {\n  var self = this;\n\n  self.localCatalog = localCatalog;\n  self.otherCatalog = otherCatalog;\n};\n\n_.extend(LayeredCatalog.prototype, {\n  toString: function () {\n    var self = this;\n    return \"LayeredCatalog []\";\n  },\n\n  getLatestVersion: function (...args) {\n    var self = this;\n    return self._returnFirst(\"getLatestVersion\", args, ACCEPT_NON_EMPTY);\n  },\n\n  getAllPackageNames: function () {\n    var self = this;\n    return _.union(self.localCatalog.getAllPackageNames(), self.otherCatalog.getAllPackageNames());\n  },\n\n  _returnFirst: function(f, args, validityOracle) {\n    var self = this;\n    var result = self.localCatalog[f](...args);\n    if (validityOracle(result)) {\n      return result;\n    }\n    return self.otherCatalog[f](...args);\n  },\n\n  getPackage: function (...args) {\n    return this._returnFirst(\"getPackage\", args, ACCEPT_NON_EMPTY);\n  },\n\n  getSortedVersions: function (...args) {\n    return this._returnFirst(\"getSortedVersions\", args, ACCEPT_NON_EMPTY);\n  },\n\n  getSortedVersionRecords: function (...args) {\n    return this._returnFirst(\n      \"getSortedVersionRecords\", args, ACCEPT_NON_EMPTY);\n  },\n\n  getVersion: function (name, version) {\n    var self = this;\n    var result = self.localCatalog.getVersion(name, version);\n    if (!result) {\n      if (/\\+/.test(version)) {\n        return null;\n      }\n      result = self.otherCatalog.getVersion(name, version);\n    }\n    return result;\n  },\n\n  // As getVersion, but returns info on the latest version of the\n  // package, or null if the package doesn't exist or has no versions.\n  // It does not include prereleases (with dashes in the version);\n  getLatestMainlineVersion: function (name) {\n    var self = this;\n\n    var versions = self.getSortedVersions(name);\n    versions.reverse();\n    var latest = _.find(versions, function (version) {\n      return !/-/.test(version);\n    });\n    if (!latest)\n      return null;\n    return self.getVersion(name, latest);\n  }\n});\n\nexports.DEFAULT_TRACK = remoteCatalog.DEFAULT_TRACK;\nexports.official = remoteCatalog.official;\n\n// This is the catalog that's used to actually drive the constraint solver: it\n// contains local packages, and since local packages always beat server\n// packages, it doesn't contain any information about the server version of\n// local packages.\nexports.LayeredCatalog = LayeredCatalog;\n"
  },
  {
    "path": "tools/packaging/package-client.js",
    "content": "var _ = require('underscore');\n\nvar config = require('../meteor-services/config.js');\nvar httpHelpers = require('../utils/http-helpers.js');\nvar release = require('./release.js');\nvar files = require('../fs/files.js');\nvar utils = require('../utils/utils.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar compiler = require('../isobuild/compiler.js');\nvar authClient = require('../meteor-services/auth-client.js');\nvar catalog = require('./catalog/catalog.js');\nvar projectContextModule = require('../project-context.js');\nvar colonConverter = require('../utils/colon-converter.js');\nvar Profile = require('../tool-env/profile.js').Profile;\n\n// Opens a DDP connection to a package server. Loads the packages needed for a\n// DDP connection, then calls DDP connect to the package server URL in config,\n// using a current user-agent header composed by http-helpers.js.\nvar openPackageServerConnection = function (packageServerUrl) {\n  var serverUrl = packageServerUrl || config.getPackageServerUrl();\n  return authClient.openServiceConnection(serverUrl);\n};\n\n// We don't let the user upload a blank README for UX reasons, but we would\n// prefer that the server move to a world with 'readme' files for everything in\n// the future. As a way to breach these interfaces, for now, we are going to\n// upload blank documentation files when null docs are requested.\n//\n// This function generates a Readme object for a blank readme file, as well as\n// the file itself.\nvar generateBlankReadme = function () {\n  return {\n    contents: \"\",\n    excerpt: \"\",\n    hash: files.blankHash\n  };\n};\n\n// Save a readme file to a temporary path.\nvar saveReadmeToTmp = function (readmeInfo) {\n  var tempReadmeDir = files.mkdtemp('readme');\n  var readmePath = files.pathJoin(tempReadmeDir, \"Readme.md\");\n  files.writeFileAtomically(readmePath, readmeInfo.contents);\n  return readmePath;\n};\n\n// Given a connection, makes a call to the package server.  (Checks to see if\n// the connection is connected, and reconnects if needed -- a workaround for\n// the fact that connections in the tool do not reconnect)\nexports.callPackageServer = function (conn, ...args) {\n  // XXX This is broken since it doesn't actually replace the conn in the\n  // caller, so it'll happen on every subsequent call\n  if (!conn.connected) {\n    conn.close();\n    conn = exports.loggedInPackagesConnection();\n  }\n  return conn.call(...args);\n};\n\nvar callPackageServerBM = exports.callPackageServerBM = function (...args) {\n  buildmessage.assertInJob();\n  try {\n    return exports.callPackageServer.apply(null, args);\n  } catch (e) {\n    buildmessage.error(e.reason || e.message);\n    return null;\n  }\n};\n\n// Requests and returns one page of new package data that we haven't cached on\n// disk. We assume that data is cached chronologically, so essentially, we are\n// asking for a diff from the last time that we did this.\n// Takes in:\n// - conn: the connection to use (does not have to be logged in)\n// - syncToken: a syncToken object to be sent to the server that\n//   represents the last time that we talked to the server.\n// - options:\n//    - useShortPages (Boolean). Ask the server for pages of ~3 records\n//      instead of ~100, for testing pagination.\n//\n// Returns an object, containing the following fields:\n//  - syncToken: a new syncToken object, that we can pass to the server in the future.\n//  - collections: an object keyed by the name of server collections, with the\n//    records as an array of javascript objects.\nvar loadRemotePackageData = function (conn, syncToken, options) {\n  options = options || {};\n\n  // Did we get disconnected between retries somehow? Then we should open a new\n  // connection. We shouldn't use the callPackageServer method here though,\n  // since we don't need to authenticate.\n  if (!conn.connected) {\n    conn.close();\n    conn =  openPackageServerConnection();\n  }\n\n  var syncOpts = {};\n  if (options && options.useShortPages) {\n    syncOpts.shortPagesForTest = options.useShortPages;\n  }\n  if (options && options.compressCollections) {\n    syncOpts.compressCollections = options.compressCollections;\n  }\n  return conn.call('syncNewPackageData', syncToken, syncOpts);\n};\n\n// Contacts the package server to get the latest diff and writes changes to\n// disk.\n//\n// Takes in the dataStore, which is an example of the remote catalog. Contacts\n// the package server and updates the sql database with the most recent\n// information.\n//\n// Returns null if contacting the server times out, or an object with the\n// following keys:\n//     resetData : true if we should reset the database, otherwise false.\n//     connectionFailed: true if we failed to connect to the server.\n//\n// options can include:\n//  - packageStorageFile: String. The file to write the data to (overrides\n//    `config.getPackageStorage()`)\n//  - packageServerUrl: String. The package server (overrides\n//    `config.getPackageServerUrl()`)\n//  - useShortPages: Boolean. Request short pages of ~3 records from the\n//    server, instead of ~100 that it would send otherwise\nexports.updateServerPackageData = function (dataStore, options) {\n  return buildmessage.enterJob('updating package catalog', function () {\n    return _updateServerPackageData(dataStore, options);\n  });\n};\n\nvar _updateServerPackageData = function (dataStore, options) {\n  var self = this;\n  options = options || {};\n  if (dataStore === null) {\n    throw Error(\"Data store expected\");\n  }\n\n  var done = false;\n  var ret = {resetData: false};\n\n  // For now, we don't have a great progress metric, so just use a spinner\n  var useProgressbar = false;\n\n  var start = undefined;\n  // Guess that we're about an hour behind, as an opening guess\n  var state = { current: 0, end: 60 * 60 * 1000, done: false};\n  useProgressbar && buildmessage.reportProgress(state);\n\n  var conn = openPackageServerConnection(options.packageServerUrl);\n\n  // Provide some progress indication for connection\n  // XXX though it is just a hack\n  state.current = 1;\n  useProgressbar && buildmessage.reportProgress(state);\n\n  var getSomeData = function () {\n    var syncToken = dataStore.getSyncToken() || {format: \"1.1\"};\n\n    if (!start) {\n      start = {};\n      start.builds = syncToken.builds;\n      start.versions = syncToken.versions;\n      state.end = (Date.now() - start.builds) + (Date.now() - start.versions);\n    }\n    // XXX: This is a hack... syncToken should have a % done\n    state.current =\n      (syncToken.builds - start.builds) +\n      (syncToken.versions - start.versions);\n    useProgressbar && buildmessage.reportProgress(state);\n\n    var compress = !!process.env.METEOR_CATALOG_COMPRESS_RPCS;\n\n    // (loadRemotePackageData may throw)\n    var remoteData = loadRemotePackageData(conn, syncToken, {\n      useShortPages: options.useShortPages,\n      compressCollections: compress\n    });\n\n    // Is the remote server telling us to ignore everything we've heard before?\n    // OK, we can do that.\n    if (remoteData.resetData) {\n      dataStore.reset();\n      // The caller may want to take this as a cue to delete packages from the\n      // tropohouse.\n      ret.resetData = true;\n    }\n\n    if (remoteData.collectionsCompressed) {\n      var zlib = require('zlib');\n      var colsGzippedBuffer = new Buffer(\n        remoteData.collectionsCompressed, 'base64');\n      var colsJSON = new Promise((resolve, reject) => {\n        zlib.gunzip(colsGzippedBuffer, (err, res) => {\n          err ? reject(err) : resolve(res);\n        });\n      }).await();\n      remoteData.collections = JSON.parse(colsJSON);\n      delete remoteData.collectionsCompressed;\n    }\n\n    // We always write to the data store; the fact there is no data is itself\n    // data!  e.g. the last-refresh timestamp\n    var syncComplete =\n          _.isEqual(remoteData.collections, {}) || remoteData.upToDate;\n    dataStore.insertData(remoteData, syncComplete);\n\n    // If there is no new data from the server, don't bother writing things to\n    // disk (unless we were just told to reset everything).\n    if (!remoteData.resetData && _.isEqual(remoteData.collections, {})) {\n      done = true;\n      return;\n    }\n\n    if (remoteData.upToDate) {\n      done = true;\n    }\n  };\n\n  try {\n    while (!done) {\n      getSomeData();\n    }\n  } finally {\n    conn.close();\n  }\n\n  return ret;\n};\n\n_updateServerPackageData = Profile('package-client _updateServerPackageData',\n                                   _updateServerPackageData);\n\n// Returns a logged-in DDP connection to the package server, or null if\n// we cannot log in. If an error unrelated to login occurs\n// (e.g. connection to package server times out), then it will be\n// thrown.\nexports.loggedInPackagesConnection = function () {\n  return authClient.loggedInConnection(\n    config.getPackageServerUrl(),\n    config.getPackageServerDomain(),\n    \"package-server\"\n  );\n};\n\n// XXX this is missing a few things. In retrospect a better approach here might\n//     be to actually make \"save source somewhere else\" or perhaps \"add source\n//     to tarball\" be part of the package build itself...\nvar bundleSource = function (isopack, includeSources, packageDir) {\n  buildmessage.assertInJob();\n\n  var name = isopack.name;\n\n  var tempDir = files.mkdtemp('build-source-package-');\n  var packageTarName = name + '-' + isopack.version + '-source';\n  var dirToTar = files.pathJoin(tempDir, 'source',\n    colonConverter.convert(packageTarName));\n  // XXX name probably needs to be escaped for windows?\n  // XXX note that publish-for-arch thinks it knows how this tarball is laid\n  //     out, which is a bit of a shame\n  var sourcePackageDir = files.pathJoin(dirToTar, colonConverter.convert(name));\n  if (! files.mkdir_p(sourcePackageDir)) {\n    buildmessage.error('Failed to create temporary source directory: ' +\n                       sourcePackageDir);\n    return null;\n  }\n\n  // We copy source files into a temp directory and then tar up the temp\n  // directory. It would be great if we could avoid the copy, but as far\n  // as we can tell, this is the only way to get a tarball with the\n  // directory structure that we want (<package name>-<version-source/\n  // at the top level).\n  _.each(includeSources, function (f) {\n    const from = files.pathJoin(packageDir, f);\n    const to = files.pathJoin(sourcePackageDir, f);\n    if (files.exists(from)) {\n      files.copyFile(from, to);\n    }\n  });\n\n  // Write a package map to `.versions` inside the source tarball.  Note that\n  // this differs in two ways from the `.versions` file that is maintained\n  // inside standalone packages by 'meteor publish':\n  //  (a) It only contains the direct, directly implied, and linked-into-plugin\n  //      dependencies of the package, not all transitive dependencies.\n  //  (b) It is ALWAYS put into the source tarball, even if the package came\n  //      from inside an app, whereas the package-source-tree .versions file\n  //      is only used for standalone packages\n  var packageMapFilename = files.pathJoin(sourcePackageDir, '.versions');\n  if (files.exists(packageMapFilename)) {\n    throw Error(\".versions file already exists? \" + packageMapFilename);\n  }\n  var pluginProviderPackageMap = isopack.pluginProviderPackageMap;\n  if (! pluginProviderPackageMap) {\n    throw Error(\"no pluginProviderPackageMap on isopack?\");\n  }\n  var packageMapFile = new projectContextModule.PackageMapFile({\n    filename: packageMapFilename\n  });\n  packageMapFile.write(pluginProviderPackageMap);\n\n  // We put this inside the temp dir because mkdtemp makes sure that the\n  // temp dir gets cleaned up on process exit, so we don't have to worry\n  // about cleaning up our tarball (or our copied source files)\n  // ourselves.\n  var sourceTarball = files.pathJoin(tempDir, packageTarName + '.tgz');\n  files.createTarball(dirToTar, sourceTarball);\n\n  var tarballHash = files.fileHash(sourceTarball);\n  var treeHash = files.treeHash(dirToTar);\n\n  return {\n    sourceTarball: sourceTarball,\n    tarballHash: tarballHash,\n    treeHash: treeHash\n  };\n};\n\n// Uploads a file at a filepath to the HTTP put URL.\n//\n// Returns true on success and false on failure.\nvar uploadFile = function (putUrl, filepath) {\n  buildmessage.assertInJob();\n  var size = files.stat(filepath).size;\n  var rs = files.createReadStream(filepath);\n  try {\n    // Use getUrl instead of request, to throw on 4xx/5xx.\n    httpHelpers.getUrl({\n      method: 'PUT',\n      url: putUrl,\n      headers: {\n        'content-length': size,\n        'content-type': 'application/octet-stream',\n        'x-amz-acl': 'public-read'\n      },\n      bodyStream: rs,\n      bodyStreamLength: size\n    });\n  } catch (err) {\n    // XXX: getUrl's error handling is terrible and we should fix it there.\n    buildmessage.error(typeof err === \"string\" ? err : err.error.toString());\n    return false;\n  } finally {\n    rs.close();\n  }\n  return true;\n};\n\nexports.uploadFile = uploadFile;\n\nexport function bundleBuild(isopack, isopackCache) {\n  buildmessage.assertInJob();\n\n  var tempDir = files.mkdtemp('bp-');\n  var packageTarName = isopack.tarballName();\n  var tarInputDir = files.pathJoin(tempDir, packageTarName);\n\n  // Note that we do need to do this even though we already have the isopack on\n  // disk in an IsopackCache, because we don't want to include\n  // isopack-buildinfo.json. (We don't include it because we're not passing\n  // includeIsopackBuildInfo to saveToPath here.)\n  isopack.saveToPath(tarInputDir, {\n    // When publishing packages that don't use new registerCompiler plugins,\n    // make sure that old Meteors can use it too\n    includePreCompilerPluginIsopackVersions: true,\n    isopackCache,\n  });\n\n  var buildTarball = files.pathJoin(tempDir, packageTarName + '.tgz');\n\n  files.createTarball(tarInputDir, buildTarball);\n\n  var tarballHash = files.fileHash(buildTarball);\n  var treeHash = files.treeHash(tarInputDir, {\n    // We don't include any package.json from an npm module in the tree hash,\n    // because npm isn't super consistent about what it puts in there (eg, does\n    // it include the \"readme\" field)? This ends up leading to spurious\n    // differences. The tree hash will still notice any actual CODE changes in\n    // the npm packages.\n    ignore: function (relativePath) {\n      var pieces = relativePath.split(files.pathSep);\n      return pieces.length && _.last(pieces) === 'package.json'\n        && _.contains(pieces, 'npm');\n    }\n  });\n\n  return {\n    buildTarball: buildTarball,\n    tarballHash: tarballHash,\n    treeHash: treeHash\n  };\n}\n\nfunction createBuiltPackage(isopack, isopackCache) {\n  buildmessage.assertInJob();\n  var name = isopack.name;\n\n  // Note: we really want to do this before createPackageBuild, because the URL\n  // we get from createPackageBuild will expire!\n  var bundleResult;\n  buildmessage.enterJob(\"bundling build for \" + name, function () {\n    bundleResult = bundleBuild(isopack, isopackCache);\n  });\n  if (buildmessage.jobHasMessages()) {\n    return;\n  }\n\n  return bundleResult;\n}\n\nvar publishBuiltPackage = function (conn, isopack, bundleResult) {\n  buildmessage.assertInJob();\n  var name = isopack.name;\n\n  var uploadInfo;\n  buildmessage.enterJob('creating package build for ' + name, function () {\n    uploadInfo = callPackageServerBM(conn, 'createPackageBuild', {\n      packageName: isopack.name,\n      version: isopack.version,\n      buildArchitectures: isopack.buildArchitectures()\n    });\n  });\n  if (buildmessage.jobHasMessages()) {\n    return;\n  }\n\n  buildmessage.enterJob(\"uploading build\", function () {\n    uploadFile(uploadInfo.uploadUrl,\n               bundleResult.buildTarball);\n  });\n  if (buildmessage.jobHasMessages()) {\n    return;\n  }\n\n  buildmessage.enterJob('publishing package build for ' + name, function () {\n    callPackageServerBM(conn, 'publishPackageBuild',\n                        uploadInfo.uploadToken,\n                        bundleResult.tarballHash,\n                        bundleResult.treeHash);\n  });\n  if (buildmessage.jobHasMessages()) {\n    return;\n  }\n};\n\nexport function createAndPublishBuiltPackage(conn, isopack, isopackCache) {\n  publishBuiltPackage(\n    conn,\n    isopack,\n    createBuiltPackage(isopack, isopackCache),\n  );\n}\n\n// Handle an error thrown on trying to connect to the package server.\nexports.handlePackageServerConnectionError = function (error) {\n  authClient.handleConnectionError(error, \"package server\");\n};\n\n\n// Update the package metdata in the server catalog. Chane the docs,\n// descriptions and the Git URL to new values.\n//\n// options:\n// - packageSource: the packageSource for this package.\n// - readmeInfo: null, or an object containing docs information for this package.\n// - connection: the open, logged-in connection over which we should talk to the\n//   package server. DO NOT CLOSE this connection here.\n//\n// Return true on success and an error code otherwise.\nexports.updatePackageMetadata = function (options) {\n  buildmessage.assertInJob();\n\n  var packageSource = options.packageSource;\n  var conn = options.connection;\n  var readmeInfo = options.readmeInfo;\n\n  var name = packageSource.name;\n  var version = packageSource.version;\n\n  if (! version) {\n    buildmessage.error(\n      \"Package cannot be updated because it doesn't have a version\");\n    return;\n  }\n\n  // For now, documentation is optional on the client, so we have to give people\n  // a way to remove it with 'documentation: null'.\n  if (! readmeInfo) {\n    readmeInfo = generateBlankReadme();\n  }\n\n  var dataToUpdate = {\n    git: packageSource.metadata.git || \"\",\n    description: packageSource.metadata.summary,\n    longDescription: readmeInfo.excerpt\n  };\n\n  // Check that the metadata fits under the established limits, and give helpful\n  // feedback.\n  if (! dataToUpdate[\"description\"]) {\n    buildmessage.error(\"Please provide a short description to use in 'meteor search'\");\n    return;\n  }\n\n  if (dataToUpdate[\"description\"] &&\n      dataToUpdate[\"description\"].length > 100) {\n    buildmessage.error(\"Summary must be under 100 chars.\");\n    return;\n  }\n\n  if (dataToUpdate[\"longDescription\"].length > 1500) {\n    buildmessage.error(\n      \"Longform package description is too long. Meteor uses the section of \" +\n      \"the Markdown documentation file between the first and second \" +\n      \"headings. That section must be less than 1500 characters long.\");\n    return;\n  }\n\n  // Update the general metadata.\n  var versionIdentifier = { packageName: name, version: version };\n  buildmessage.enterJob('updating metadata', function () {\n    callPackageServerBM(\n      conn, \"changeVersionMetadata\", versionIdentifier, dataToUpdate);\n  });\n  if (buildmessage.jobHasMessages()) {\n    return;\n  }\n\n  // Upload the new Readme.\n  buildmessage.enterJob('uploading documentation', function () {\n    var readmePath = saveReadmeToTmp(readmeInfo);\n    var uploadInfo =\n          callPackageServerBM(conn, \"createReadme\", versionIdentifier);\n    if (! uploadInfo) {\n      return;\n    }\n    if (! uploadFile(uploadInfo.url, readmePath)) {\n      return;\n    }\n    callPackageServerBM(\n      conn, \"publishReadme\", uploadInfo.uploadToken, { hash: readmeInfo.hash });\n  });\n  if (buildmessage.jobHasMessages()) {\n    return;\n  }\n\n\n};\n\n// Publish the package information into the server catalog. Create new records\n// for the package (if needed), the version and the build; upload source and\n// isopack.\n//\n// options:\n// - packageSource: the packageSource for this package.\n// - connection: the open, logged-in connection over which we should talk to the\n//   package server. DO NOT CLOSE this connection here.\n// - projectContext: the (probably temporary) ProjectContext to use. Must have\\\n//   already built local packages\n// - new: this package is new, we should call createPackage to create a new\n//   package record.\n// - existingVersion: we expect the version to exist already, and for us\n//   to merely be providing a new build of the same source\n// - doNotPublishBuild: do not publish the build of this package.\n//\n// Return true on success and an error code otherwise.\nexports.publishPackage = function (options) {\n  buildmessage.assertInJob();\n  var packageSource = options.packageSource;\n  var conn = options.connection;\n  var projectContext = options.projectContext;\n\n  var name = packageSource.name;\n  var version = packageSource.version;\n\n  if (options.new && options.existingVersion) {\n    throw Error(\"is it new or does it exist?!?\");\n  }\n\n  // Check that the package name is valid.\n  utils.validatePackageName(name, { useBuildmessage: true });\n  if (buildmessage.jobHasMessages()) {\n    return;\n  }\n\n  // Check that we have a version.\n  if (! version) {\n    buildmessage.error(\n      \"Package cannot be published because it doesn't have a version\");\n    return;\n  }\n\n  // Check that the version description is under the character limit. (We check\n  // all string limits on the server, but this is the one that is mostly likely\n  // to be wrong)\n  if (! packageSource.metadata.summary) {\n    buildmessage.error(\n      \"Please describe what your package does. Set a summary \" +\n        \"in Package.describe in package.js.\");\n    return;\n  }\n\n  if (packageSource.metadata.summary.length > 100) {\n    buildmessage.error(\"Summary must be under 100 chars.\");\n    return;\n  }\n\n  // Check that we are an authorized maintainer of this package.\n  if (!options['new']) {\n    var packRecord = catalog.official.getPackage(name);\n    if (! packRecord) {\n      buildmessage.error(\n        'There is no package named ' + name +\n          '. If you are creating a new package, use the --create flag.');\n      return;\n    }\n\n    if (!exports.amIAuthorized(name, conn, false)) {\n      buildmessage.error(\n        'You are not an authorized maintainer of ' + name + '.  Only ' +\n          'authorized maintainers may publish new versions.');\n    }\n  }\n\n  // Check that our documentation exists (or we know that it doesn't) and has\n  // been filled out.\n  var readmeInfo = buildmessage.enterJob(\n    \"processing documentation\",\n    function () {\n      return packageSource.processReadme();\n  });\n  if (buildmessage.jobHasMessages()) {\n    return;\n  }\n  if (readmeInfo && (readmeInfo.hash === files.blankHash)) {\n    buildmessage.error(\n      \"Your documentation file is blank, so users may have trouble figuring \" +\n      \"out how to use your package. Please fill it out, or \" +\n      \"set 'documentation: null' in your Package.describe\");\n    return;\n  }\n\n  if (readmeInfo && readmeInfo.excerpt.length > 1500) {\n    buildmessage.error(\n      \"Longform package description is too long. Meteor uses the section of \" +\n      \"the Markdown documentation file between the first and second \" +\n      \"headings. That section must be less than 1500 characters long.\");\n    return;\n  }\n\n  // We don't let the user upload a blank README for UX reasons, but we would\n  // prefer that the server move to a world with 'readme' files for everything\n  // in the future. This helps unite these interfaces, and makes our code easier\n  // to reason about in the future.\n  if (! readmeInfo) {\n    readmeInfo = generateBlankReadme();\n  }\n  var readmePath = saveReadmeToTmp(readmeInfo);\n\n  var packageDeps = packageSource.getDependencyMetadata();\n\n  // Check that the package does not have any unconstrained references.\n  _.each(packageDeps, function(refs, label) {\n    if (refs.constraint == null) {\n      if (packageSource.isCore && files.inCheckout() &&\n          projectContext.localCatalog.getPackage(label)) {\n        // Core package is using or implying another core package,\n        // without a version number.  We fill in the version number.\n        // (Well, we're assuming that the other package is core and\n        // not some other sort of local package.)\n        var versionString =\n              projectContext.localCatalog.getLatestVersion(label).version;\n        // modify the constraint on this dep that will be sent to troposphere\n        refs.constraint = versionString;\n      } else if (label === \"meteor\") {\n        // HACK: We are willing to publish a package with a \"null\"\n        // constraint on the \"meteor\" package to troposphere.  This\n        // happens for non-core packages when not running from a\n        // checkout, because all packages implicitly depend on the\n        // \"meteor\" package, but do not necessarily specify an\n        // explicit version for it, and we don't have a great way to\n        // choose one here.\n        // XXX come back to this, especially if we are incrementing the\n        // major version of \"meteor\".  hopefully we will have more data\n        // about the package system by then.\n      } else {\n        buildmessage.error(\n          \"You must specify a version constraint for package \" + label);\n      }\n    }\n  });\n  if (buildmessage.jobHasMessages()) {\n    return;\n  }\n\n  var isopack = projectContext.isopackCache.getIsopack(name);\n  if (! isopack) {\n    throw Error(\"no isopack \" + name);\n  }\n\n  // If we aren't able to include legacy builds in this version, make sure that\n  // it has a fake dependency on isobuild:isopack-2 so that old versions of\n  // Isobuild won't accidentally use it.\n  if (!isopack.canWriteLegacyBuilds()\n      && !_.has(packageDeps, 'isobuild:isopack-2')) {\n    packageDeps['isobuild:isopack-2'] = {\n      constraint: '1.0.0',\n      // Arbitrary arch here; nothing other than meteor show really pays\n      // attention to reference arch anymore, because we no longer pay attention\n      // to the arch with the constraint in Version Solver.\n      references: [{arch: 'os'}],\n    };\n  }\n\n  var sourceFiles = isopack.getSourceFilesUnderSourceRoot(\n    packageSource.sourceRoot);\n  if (! sourceFiles) {\n    throw Error(\"isopack doesn't know what its source files are?\");\n  }\n\n  // We need to have built the test package to get all of its sources, even\n  // though we're not publishing a BUILD for the test package.\n  if (packageSource.testName) {\n    var testIsopack = projectContext.isopackCache.getIsopack(\n      packageSource.testName);\n    if (! testIsopack) {\n      throw Error(\"no testIsopack \" + packageSource.testName);\n    }\n    var testSourceFiles = testIsopack.getSourceFilesUnderSourceRoot(\n      packageSource.sourceRoot);\n    if (! testSourceFiles) {\n      throw Error(\"test isopack doesn't know what its source files are?\");\n    }\n    sourceFiles = _.union(sourceFiles, testSourceFiles);\n  }\n\n  var sourceBundleResult;\n  buildmessage.enterJob(\"bundling source for \" + name, function () {\n    sourceBundleResult = bundleSource(\n      isopack, sourceFiles, packageSource.sourceRoot);\n  });\n  if (buildmessage.jobHasMessages()) {\n    return;\n  }\n\n  // Create the package. Check that the metadata exists.\n  if (options.new) {\n    buildmessage.enterJob(\"creating package \" + name, function () {\n      callPackageServerBM(conn, 'createPackage', {\n        name: packageSource.name\n      });\n    });\n    if (buildmessage.jobHasMessages()) {\n      return;\n    }\n  }\n\n  if (options.existingVersion) {\n    var existingRecord = catalog.official.getVersion(name, version);\n    if (! existingRecord) {\n      buildmessage.error(\"Version does not exist.\");\n      return;\n    }\n    if (existingRecord.source.treeHash !== sourceBundleResult.treeHash) {\n      buildmessage.error(\"Package source differs from the existing version.\");\n      return;\n    }\n\n    if (! options.doNotPublishBuild) {\n      createAndPublishBuiltPackage(\n        conn, isopack, projectContext.isopackCache);\n\n      if (buildmessage.jobHasMessages()) {\n        return;\n      }\n    }\n\n    // XXX check that we're actually providing something new?\n  } else {\n    var uploadInfo;\n    buildmessage.enterJob(\"pre-publishing package \" + name, function () {\n      var uploadRec = {\n        packageName: packageSource.name,\n        version: version,\n        description: packageSource.metadata.summary,\n        longDescription: readmeInfo.excerpt,\n        git: packageSource.metadata.git,\n        compilerVersion: compiler.BUILT_BY,\n        containsPlugins: packageSource.containsPlugins(),\n        debugOnly: packageSource.debugOnly,\n        prodOnly: packageSource.prodOnly,\n        testOnly: packageSource.testOnly,\n        exports: packageSource.getExports(),\n        releaseName: release.current.name,\n        dependencies: packageDeps\n      };\n      uploadInfo = callPackageServerBM(conn, 'createPackageVersion', uploadRec);\n    });\n    if (buildmessage.jobHasMessages()) {\n      return;\n    }\n\n    // XXX If package version already exists, print a nice error message\n    // telling them to try 'meteor publish-for-arch' if they want to\n    // publish a new build.\n\n    // Documentation is smaller than the source. Upload it first, to minimize\n    // the chances of PUT URLs expiring. (XXX: in the far future, parallelize this)\n    buildmessage.enterJob(\"uploading documentation\", function () {\n      uploadFile(uploadInfo.readmeUrl, readmePath);\n    });\n    if (buildmessage.jobHasMessages()) {\n      return;\n    }\n\n    buildmessage.enterJob(\"uploading source\", function () {\n      uploadFile(uploadInfo.uploadUrl, sourceBundleResult.sourceTarball);\n    });\n    if (buildmessage.jobHasMessages()) {\n      return;\n    }\n\n    if (! options.doNotPublishBuild) {\n      var bundleResult = createBuiltPackage(\n        isopack,\n        projectContext.isopackCache,\n      );\n\n      if (buildmessage.jobHasMessages()) {\n        return;\n      }\n    }\n\n    var hashes = {\n      tarballHash: sourceBundleResult.tarballHash,\n      treeHash: sourceBundleResult.treeHash,\n      readmeHash: readmeInfo.hash\n    };\n    buildmessage.enterJob(\"publishing package version\", function () {\n      callPackageServerBM(\n        conn, 'publishPackageVersion', uploadInfo.uploadToken, hashes);\n    });\n    if (buildmessage.jobHasMessages()) {\n      return;\n    }\n\n    if (! options.doNotPublishBuild) {\n      publishBuiltPackage(conn, isopack, bundleResult);\n      if (buildmessage.jobHasMessages()) {\n        return;\n      }\n    }\n  }\n\n  return;\n};\n\n  // Call the server to ask if we are authorized to update this release or\n// package. This is a way to save time before sending data to the server. It\n// will mostly ignore most errors (just in case we have a flaky network connection or\n// something) and let the method deal with those.\n//\n// If this returns FALSE, then we are NOT authorized.\n// Otherwise, return true.\nexports.amIAuthorized = function (name, conn, isRelease) {\n  var methodName = \"amIAuthorized\" +\n    (isRelease ? \"Release\" : \"Package\");\n\n  try {\n    exports.callPackageServer(conn, methodName, name);\n  } catch (err) {\n    if (err.error === 401) {\n      return false;\n    }\n\n    // We don't know what this error is. Probably we can't contact the server,\n    // or the like. It would be a pity to fail all operations with the server\n    // just because a preliminary check fails, so return true for now.\n    return true;\n  }\n  return true;\n};\n"
  },
  {
    "path": "tools/packaging/package-map.js",
    "content": "var _ = require('underscore');\nvar packageVersionParser = require('./package-version-parser.js');\nvar utils = require('../utils/utils.js');\nimport { isIsobuildFeaturePackage } from '../isobuild/compiler.js';\n\n// PackageMap: Represents the choices of package versions being used for a\n// project. It knows all the packages that are used (direct and indirect\n// dependencies), their versions, whether they are local or versioned packages,\n// and the PackageSource object for any local packages.  Prefer using this\n// function over arbitrary JSON representations when possible.  (A related class\n// is projectContextModule.PackageMapFile which specifically represents the\n// .meteor/packages file on disk.)\n//\n// It has a corresponding JSON format (used, eg, inside buildinfo files).\n//\n// If you specify the localCatalog option to the constructor, any package in\n// that localCatalog will be considered to be local, and all others will be\n// considered to be prebuilt versioned packages from troposphere.  If you do not\n// specify the localCatalog option, all packages will be considered to prebuilt\n// versioned packages.\nexports.PackageMap = function (versions, options) {\n  var self = this;\n  options = options || {};\n  self._map = {};\n  self._localCatalog = options.localCatalog || null;\n\n  _.each(versions, function (version, packageName) {\n    // If the constraint solver told us that we needed an isobuild feature,\n    // that's fine, but it's not a real package.\n    if (isIsobuildFeaturePackage(packageName)) {\n      return;\n    }\n\n    var packageSource = self._localCatalog &&\n          self._localCatalog.getPackageSource(packageName);\n    if (packageSource) {\n      self._map[packageName] =\n        { kind: 'local', version: version, packageSource: packageSource };\n    } else {\n      self._map[packageName] =\n        { kind: 'versioned', version: version, packageSource: null };\n    }\n  });\n};\n\n_.extend(exports.PackageMap.prototype, {\n  eachPackage: function (iterator) {\n    var self = this;\n    _.each(self._map, function (info, packageName) {\n      // For reasons that are super unclear, if this `_.clone` is inlined into\n      // the `iterator` call, the value produced can mysteriously turn into\n      // undefined on the way into `iterator`. Presumably some sort of memory\n      // corruption, maybe Fiber-related?  Trying to minimize has been an\n      // exercise in nondeterminism. But this does seem to be a sure-fire way to\n      // fix it, for now. Who knows why, and who knows when it will recur again.\n      var infoClone = _.clone(info);\n      iterator(packageName, infoClone);\n    });\n  },\n  getInfo: function (packageName) {\n    var self = this;\n    if (_.has(self._map, packageName)) {\n      return self._map[packageName];\n    }\n    return null;\n  },\n  makeSubsetMap: function (packageNames) {\n    var self = this;\n    var subsetVersions = {};\n    _.each(packageNames, function (packageName) {\n      var info = self.getInfo(packageName);\n      if (!info) {\n        throw Error(\"not a subset: \" + packageName);\n      }\n      subsetVersions[packageName] = info.version;\n    });\n    return new exports.PackageMap(subsetVersions, {\n      localCatalog: self._localCatalog\n    });\n  },\n\n  toJSON: function () {\n    var self = this;\n    var ret = {};\n    _.each(self._map, function (info, packageName) {\n      if (info.kind === 'local') {\n        ret[packageName] = {\n          kind: 'local',\n          sourceRoot: info.packageSource.sourceRoot\n        };\n      } else {\n        ret[packageName] = {\n          kind: 'versioned',\n          version: info.version\n        };\n      }\n    });\n    return ret;\n  },\n  // Returns a map from package name to version. In most cases, this is a far\n  // worse representation than PackageMap... avoid using it!\n  toVersionMap: function () {\n    var self = this;\n    var ret = {};\n    _.each(self._map, function (info, packageName) {\n      ret[packageName] = info.version;\n    });\n    return ret;\n  },\n\n  // Given some JSON as returned from toJSON, returns true if every package in\n  // the JSON has the same mapping as in this map.\n  isSupersetOfJSON: function (mapJSON) {\n    var self = this;\n    return _.all(mapJSON, function (jsonInfo, packageName) {\n      var thisInfo = self.getInfo(packageName);\n      if (! thisInfo) {\n        return false;\n      }\n      if (jsonInfo.kind !== thisInfo.kind) {\n        return false;\n      }\n      if (thisInfo.kind === 'local') {\n        return thisInfo.packageSource.sourceRoot === jsonInfo.sourceRoot;\n      } else {\n        return thisInfo.version === jsonInfo.version;\n      }\n    });\n  }\n});\n\n// Static method: returns a PackageMap that represents a (catalog)\n// ReleaseVersion entry (including its tool).  Note that this function assumes\n// that all packages will be prebuilt versioned, not local. This is mostly used\n// to create PackageMaps to pass to tropohouse.downloadPackagesMissingFromMap;\n// it should not be used as part of a ProjectContext because it does not allow\n// you to override release packages with local packages.\nexports.PackageMap.fromReleaseVersion = function (releaseVersion) {\n  var toolPackageVersion = releaseVersion.tool &&\n        utils.parsePackageAndVersion(releaseVersion.tool);\n  if (!toolPackageVersion) {\n    throw new Error(\"bad tool in release: \" + releaseVersion.tool);\n  }\n  var toolPackage = toolPackageVersion.package;\n  var toolVersion = toolPackageVersion.version;\n\n  var versionMap = _.clone(releaseVersion.packages || {});\n  versionMap[toolPackage] = toolVersion;\n\n  // As described in this function's description, all packages in this map are\n  // versioned, so we do not specify a localCatalog.\n  return new exports.PackageMap(versionMap);\n};\n\n\n\n// PackageMapDelta: represents the change in a PackageMap between two constraint\n// solver runs.\nexports.PackageMapDelta = function (options) {\n  var self = this;\n  self._changedPackages = {};\n\n  options.packageMap.eachPackage(function (packageName, info) {\n    var oldVersion = _.has(options.cachedVersions, packageName)\n          ? options.cachedVersions[packageName] : null;\n    self._storeAddOrChange(\n      packageName, info, oldVersion, options.anticipatedPrereleases,\n      options.neededToUseUnanticipatedPrereleases);\n  });\n\n  _.each(options.cachedVersions, function (oldVersion, packageName) {\n    if (! options.packageMap.getInfo(packageName)) {\n      self._storeRemove(packageName, oldVersion);\n    }\n  });\n};\n\n_.extend(exports.PackageMapDelta.prototype, {\n  _storeAddOrChange: function (packageName, newInfo, oldVersion,\n                               anticipatedPrereleases,\n                               neededToUseUnanticipatedPrereleases) {\n    var self = this;\n\n    // Store nothing if nothing has changed.\n    if (newInfo.version === oldVersion) {\n      return;\n    }\n\n    var backwardsIncompatible =\n          oldVersion !== null &&\n          (packageVersionParser.majorVersion(newInfo.version) !==\n           packageVersionParser.majorVersion(oldVersion));\n\n    var isPrerelease = /-/.test(newInfo.version);\n    var isAnticipatedPrerelease = _.has(anticipatedPrereleases, packageName) &&\n          _.has(anticipatedPrereleases[packageName], newInfo.version);\n    self._changedPackages[packageName] = {\n      oldVersion: oldVersion,\n      newVersion: newInfo.version,\n      isBackwardsIncompatible: backwardsIncompatible,\n      isUnanticipatedPrerelease: (neededToUseUnanticipatedPrereleases &&\n                                  isPrerelease && !isAnticipatedPrerelease)\n    };\n  },\n\n  _storeRemove: function (packageName, oldVersion) {\n    var self = this;\n    self._changedPackages[packageName] = {\n      oldVersion: oldVersion,\n      newVersion: null\n    };\n  },\n\n  eachChangedPackage: function (iterator) {\n    var self = this;\n    _.each(self._changedPackages, function (info, packageName) {\n      iterator(packageName, _.clone(info));\n    });\n  },\n\n  hasChanges: function () {\n    var self = this;\n    return ! _.isEmpty(self._changedPackages);\n  },\n\n  displayOnConsole: function (options) {\n    var self = this;\n    options = _.extend({\n      title: \"Changes to your project's package version selections:\"\n    }, options);\n\n    // Print nothing at all if nothing changed.\n    if (! self.hasChanges()) {\n      return;\n    }\n\n    var displayItems = [];\n    var anyBackwardsIncompatible = false;\n    var anyUnanticipatedPrerelease = false;\n    self.eachChangedPackage(function (packageName, info) {\n      if (info.newVersion === null) {\n        displayItems.push({\n          name: packageName,\n          description: \"removed from your project\"\n        });\n        return;\n      }\n\n      var name = packageName;\n      if (info.isBackwardsIncompatible) {\n        name += '*';\n        anyBackwardsIncompatible = true;\n      }\n      if (info.isUnanticipatedPrerelease) {\n        name += '+';\n        anyUnanticipatedPrerelease = true;\n      }\n\n      var description;\n      if (info.oldVersion === null) {\n        description = \"added, version \" + info.newVersion;\n      } else if (packageVersionParser.lessThan(info.oldVersion,\n                                               info.newVersion)) {\n        description =\n          \"upgraded from \" + info.oldVersion + \" to \" + info.newVersion;\n      } else {\n        description =\n          \"downgraded from \" + info.oldVersion + \" to \" + info.newVersion;\n      }\n      displayItems.push({ name: name, description: description });\n    });\n\n    var Console = require('../console/console.js').Console;\n\n    Console.info();\n    Console.info(options.title);\n    Console.info();\n    utils.printPackageList(displayItems);\n    if (anyBackwardsIncompatible) {\n      Console.info(\"\\n\" +\n\"* These packages have been updated to new versions that are not backwards\\n\" +\n\"  compatible.\");\n    }\n    if (anyUnanticipatedPrerelease) {\n      Console.info(\"\\n\" +\n\"+ In order to resolve constraints, we had to use experimental versions of these\\n\" +\n\"  packages.\");\n    }\n  }\n});\n"
  },
  {
    "path": "tools/packaging/package-version-parser.js",
    "content": "module.exports = require('../../packages/package-version-parser/package-version-parser.js');\n"
  },
  {
    "path": "tools/packaging/release.js",
    "content": "var _ = require('underscore');\n\nvar files = require('../fs/files.js');\nvar catalog = require('./catalog/catalog.js');\n\nvar release = exports;\n\nvar Release = function (options) {\n  var self = this;\n\n  // If an actual, proper, \"released\" release, the name of the\n  // release, eg, \"METEOR@1.0\". If not a proper release, null.\n  self.name = options.name;\n\n  if (self.name === null) {\n    // Running from checkout.\n    self._manifest = null;\n  } else {\n    // Running a proper release\n    self._manifest = options.manifest;\n  }\n};\n\n_.extend(Release.prototype, {\n  // True if an actual, proper, \"released\" release. If so, this.name\n  // will have the name of the release, eg, \"1.0\".\n  isProperRelease: function () {\n    return this.name !== null;\n  },\n\n  // True if this \"release\" is actually a checkout on disk. It is\n  // defined by the packages in the checkout rather than by a\n  // manifest. this.name will be null.\n  isCheckout: function () {\n    return this.name === null;\n  },\n\n  isRecommended: function () {\n    return this._manifest.recommended;\n  },\n\n  getReleaseTrack: function () {\n    var self = this;\n    if (! self.isProperRelease()) {\n      throw new Error(\"not a proper release?\");\n    }\n    return self.name.split('@')[0];\n  },\n\n  getReleaseVersion: function () {\n    var self = this;\n    if (! self.isProperRelease()) {\n      throw new Error(\"not a proper release?\");\n    }\n    return self.name.split('@')[1];\n  },\n\n  // Return the package name for the command-line tools that this release\n  // uses. Valid only for proper releases.\n  getToolsPackage: function () {\n    var self = this;\n\n    if (! self.isProperRelease()) {\n      throw new Error(\"not a proper release?\");\n    }\n    // XXX validate\n    return self._manifest.tool.split('@')[0];\n  },\n\n  // Return the version of the command-line tools that this release\n  // uses. Valid only for proper releases.\n  getToolsVersion: function () {\n    var self = this;\n\n    if (! self.isProperRelease()) {\n      throw new Error(\"not a proper release?\");\n    }\n    // XXX validate\n    return self._manifest.tool.split('@')[1];\n  },\n\n  // Return the package name and version of the command-line tools that this\n  // release uses. Valid only for proper releases.\n  getToolsPackageAtVersion: function () {\n    var self = this;\n\n    if (! self.isProperRelease()) {\n      throw new Error(\"not a proper release?\");\n    }\n    return self._manifest.tool;\n  },\n\n  // Return the tool that we are using. If this is a proper release, return the\n  // tool package listed in the manifest, otherwise return the version of the\n  // meteor-tool package in checkout.\n  getCurrentToolsVersion: function () {\n    var self = this;\n\n    if (release.current.name) {\n      return self._manifest.tool;\n    } else {\n      return \"meteor-tool@CHECKOUT\";\n    }\n  },\n\n  // Return a list of the upgraders (project migrations) for this\n  // release, an (ordered!) array of strings. Valid only for proper\n  // releases.\n  getUpgraders: function () {\n    var self = this;\n\n    if (! self.isProperRelease()) {\n      throw new Error(\"not a proper release?\");\n    }\n    return self._manifest.upgraders || [];\n  },\n\n  getPackages: function () {\n    var self = this;\n\n    if (! self.isProperRelease()) {\n      throw new Error(\"not a proper release?\");\n    }\n    return self._manifest.packages;\n  },\n\n  getCatalogReleaseData: function () {\n    var self = this;\n    if (! self.isProperRelease()) {\n      throw new Error(\"not a proper release?\");\n    }\n    return self._manifest;\n  },\n\n  getDisplayName: function (options) {\n    var self = this;\n    const catalogUtils = require('./catalog/catalog-utils.js');\n    return catalogUtils.displayRelease(\n      self.getReleaseTrack(),\n      self.getReleaseVersion(),\n      options);\n  }\n});\n\n// The current release. Once set, this does not change for the\n// lifetime of the process.\n//\n// It is possible that we don't have a release. Currently this only\n// comes up in one case: an app was created with a checkout version of\n// Meteor, and then run with a release version of Meteor. In this case\n// release.current will be null. (It will also be null during startup,\n// until setRelease has been called.)\n//\n// (If you want to change the current release, you have to\n// springboard, the same as if you want to change the current tools\n// version. Besides being simpler to reason about, this helps to\n// prepare us for a future where the 'meteor' tool itself is a Meteor\n// app, running against a particular Meteor release.)\nrelease.current = null;\n\n// True if we are using release.current because we were forced to do that by the\n// '--release' command line option or via throwing SpringboardToLatestRelease,\n// else false. (It is true anytime --release was passed, even if it's the same\n// release we would have used anyway. It is false anytime the current release is\n// a checkin.) null if release.current is null.\nrelease.forced = null;\n\n// True if the release was explicitly specified by the user with the --release\n// flag. Unlike release.forced, this is false when the release is overridden via\n// SpringboardToLatestRelease.\nrelease.explicit = null;\n\n// True if release.current is the release we'd use if we wanted to run the app\n// in the current project. (taking into account release.forced and whether we're\n// currently running from a checkout).\nrelease.usingRightReleaseForApp = function (projectContext) {\n  if (release.current === null) {\n    throw new Error(\"no release?\");\n  }\n\n  if (! files.usesWarehouse() || release.forced) {\n    return true;\n  }\n\n  return release.current.name === projectContext.releaseFile.fullReleaseName;\n};\n\n// Return the name of the latest release that is downloaded and ready\n// for use. May not be called when running from a checkout.\n// 'track' is optional (it defaults to the default track).\nrelease.latestKnown = function (track) {\n  if (! files.usesWarehouse()) {\n    throw new Error(\"called from checkout?\");\n  }\n  // For self-test only.\n  if (process.env.METEOR_TEST_LATEST_RELEASE) {\n    return process.env.METEOR_TEST_LATEST_RELEASE;\n  }\n\n\n  var defaultRelease = catalog.official.getDefaultReleaseVersion(track);\n\n  if (!defaultRelease) {\n    return null;\n  }\n  return defaultRelease.track + '@' + defaultRelease.version;\n};\n\n// Load a release and return it as a Release object without setting\n// release.current to that release. Unlike release.setCurrent(), this\n// may be called as many times as you like.\n//\n// This will fetch the release from the server if it isn't cached\n// locally. If that happens it will print progress messages.\n//\n// Arguments:\n// - name: release name to use. Or pass 'null' to use a checkout\n// - options:\n//   - quiet: if the release has to be downloaded, don't print\n//     progress messages.\n//\n// Throws:\n// - files.OfflineError if it was not possible to load the\n//   release because it's not locally cached and we're not online.\n// - warehouse.NoSuchReleaseError if no release called 'name' exists\n//   in the world (confirmed with server).\nrelease.load = function (name, options) {\n  options = options || {};\n\n  if (! name) {\n    return new Release({ name: null });\n  }\n\n  var parts = name.split('@');\n  if (parts.length > 2) {\n    // XXX #Pre090 better error handling\n    throw Error(\"too many @s in release name\");\n  }\n  var track, version;\n  if (parts.length == 2) {\n    track = parts[0];\n    version = parts[1];\n  } else {\n    track = catalog.DEFAULT_TRACK;\n    version = parts[0];\n    name = track + '@' + version;\n  }\n\n  var releaseVersion = catalog.official.getReleaseVersion(track, version);\n  if (releaseVersion === null) {\n    throw new release.NoSuchReleaseError;\n  }\n\n  return new Release({\n    name: name,\n    manifest: releaseVersion  // XXX rename from manifest?\n  });\n};\n\n// Called by the startup code to set release.current. May only be\n// called once.\n//\n// - releaseObject: a Release as returned from release.load()\n// - forced: true if the chosen release was forced from the command\n//   line (by the user or by the update springboard).\n// - explicit: true if the release was specifically requested by the user.\nrelease.setCurrent = function (releaseObject, forced, explicit) {\n  if (release.current) {\n    throw new Error(\"release set twice?\");\n  }\n\n  release.current = releaseObject;\n  release.forced = !! forced;\n  release.explicit = !! explicit;\n};\n\n// An exception meaning that you asked for a release that doesn't exist in the\n// new packaging world.  (It may still exist in the pre-0.9.0 packaging world.)\nrelease.NoSuchReleaseError = function () {\n};\n"
  },
  {
    "path": "tools/packaging/tropohouse.js",
    "content": "var _ = require(\"underscore\");\nvar files = require('../fs/files.js');\nvar utils = require('../utils/utils.js');\nvar httpHelpers = require('../utils/http-helpers.js');\nvar archinfo = require('../utils/archinfo.js');\nvar catalog = require('./catalog/catalog.js');\nvar Isopack = require('../isobuild/isopack.js').Isopack;\nvar config = require('../meteor-services/config.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar Console = require('../console/console.js').Console;\nvar colonConverter = require('../utils/colon-converter.js');\n\nexports.Tropohouse = function (root, options) {\n  var self = this;\n  options = options || {};\n\n  self.root = root;\n  self.platform = options.platform || process.platform;\n};\n\n// Return the directory containing our loaded collection of tools, releases and\n// packages. If we're running an installed version, found at $HOME/.meteor, if\n// we are running form a checkout, probably at $CHECKOUT_DIR/.meteor.\nvar defaultWarehouseDir = function () {\n  // a hook for tests, or i guess for users.\n  if (process.env.METEOR_WAREHOUSE_DIR) {\n    return process.env.METEOR_WAREHOUSE_DIR;\n  }\n\n  var warehouseBase = files.inCheckout()\n     ? files.getCurrentToolsDir() : files.getHomeDir();\n  // XXX This will be `.meteor` soon, once we've written the code to make the\n  // tropohouse and warehouse live together in harmony (eg, allowing tropohouse\n  // tools to springboard to warehouse tools).\n  return files.pathJoin(warehouseBase, \".meteor\");\n};\n\n// The default tropohouse is on disk at defaultWarehouseDir(); you can make your\n// own Tropohouse to override these things.\nexports.default = new exports.Tropohouse(defaultWarehouseDir());\n\n/**\n * Extract a package tarball, and on Windows convert file paths and metadata\n * @param  {String} packageTarball path to tarball\n * @param {Boolean} forceConvert Convert paths even on unix, for testing\n * @return {String}                Temporary directory with contents of package\n */\nexports._extractAndConvert = function (packageTarball, forceConvert) {\n  var targetDirectory = files.mkdtemp();\n  files.extractTarGz(packageTarball, targetDirectory, {\n    forceConvert: forceConvert\n  });\n\n  if (process.platform === \"win32\" || forceConvert) {\n    // Packages published before the Windows release might have colons or\n    // other unsavory characters in path names. In hopes of making most of\n    // these packages work on Windows, we will try to automatically convert\n    // them.\n    //\n    // At this location in the code, the metadata inside the isopack is\n    // inconsistent with the actual file paths, since we convert some file\n    // paths inside extractTarGz. Now we need to convert the metadata to match\n    // the files.\n\n    // Step 1. Load the metadata from isopack.json and convert colons in the\n    // file paths. We have already converted the colons in the actual files\n    // while untarring.\n    var {metadata, originalVersion} =\n          Isopack.readMetadataFromDirectory(targetDirectory);\n\n    // By the time that isopack-2 came out (around Meteor 1.2) nobody should be\n    // making colon packages anyway, so let's not waste effort converting (and\n    // moreover, not bother to make sure the code below works for isopack-2).\n    if (originalVersion === 'unipackage-pre2' ||\n        originalVersion === 'isopack-1') {\n      var convertedMetadata = colonConverter.convertIsopack(metadata);\n\n      // Step 2. Write the isopack.json file.  Keep it as isopack-1;\n      // _saveIsopack later will upgrade to isopack-2.\n      var isopackFileData = {};\n      isopackFileData['isopack-1'] = convertedMetadata;\n\n      var isopackJsonPath = files.pathJoin(targetDirectory, \"isopack.json\");\n\n      if (files.exists(isopackJsonPath)) {\n        files.chmod(isopackJsonPath, 0o777);\n      }\n\n      files.writeFile(\n        isopackJsonPath,\n        new Buffer(JSON.stringify(isopackFileData, null, 2), 'utf8'),\n        {mode: 0o444});\n\n      // Step 3. Clean up old unipackage.json file if it exists\n      files.unlink(files.pathJoin(targetDirectory, \"unipackage.json\"));\n\n      // Result: Now we are in a state where the isopack.json file paths are\n      // consistent with the paths in the downloaded tarball.\n\n      // Now, we have to convert the unibuild files in the same way.\n      _.each(convertedMetadata.builds, function (unibuildMeta) {\n        var unibuildJsonPath = files.pathJoin(targetDirectory,\n                                              unibuildMeta.path);\n        var unibuildJson = JSON.parse(files.readFile(unibuildJsonPath));\n\n        if (unibuildJson.format !== \"unipackage-unibuild-pre1\") {\n          throw new Error(\"Unsupported isopack unibuild format: \" +\n                          JSON.stringify(unibuildJson.format));\n        }\n\n        var convertedUnibuild = colonConverter.convertUnibuild(unibuildJson);\n\n        files.chmod(unibuildJsonPath, 0o777);\n        files.writeFile(\n          unibuildJsonPath,\n          new Buffer(JSON.stringify(convertedUnibuild, null, 2), 'utf8'),\n          {mode: 0o444});\n        // Result: Now we are in a state where the unibuild file paths are\n        // consistent with the paths in the downloaded tarball.\n      });\n\n      // Lastly, convert the build plugins, which are in the JSImage format\n      _.each(convertedMetadata.plugins, function (pluginMeta) {\n        var programJsonPath = files.pathJoin(targetDirectory, pluginMeta.path);\n        var programJson = JSON.parse(files.readFile(programJsonPath));\n\n        if (programJson.format !== \"javascript-image-pre1\") {\n          throw new Error(\"Unsupported plugin format: \" +\n                          JSON.stringify(programJson.format));\n        }\n\n        var convertedPlugin = colonConverter.convertJSImage(programJson);\n\n        files.chmod(programJsonPath, 0o777);\n        files.writeFile(\n          programJsonPath,\n          new Buffer(JSON.stringify(convertedPlugin, null, 2), 'utf8'),\n          {mode: 0o444});\n        // Result: Now we are in a state where the build plugin file paths are\n        // consistent with the paths in the downloaded tarball.\n      });\n    }\n  }\n\n  return targetDirectory;\n};\n\n_.extend(exports.Tropohouse.prototype, {\n  // Returns the load path where one can expect to find the package, at a given\n  // version, if we have already downloaded from the package server. Does not\n  // check for contents.\n  //\n  // Returns null if the package name is lexographically invalid.\n  packagePath: function (packageName, version, relative) {\n    var self = this;\n    if (! utils.isValidPackageName(packageName)) {\n      return null;\n    }\n\n    var relativePath = files.pathJoin(\n      config.getPackagesDirectoryName(),\n      colonConverter.convert(packageName),\n      version);\n\n    return relative ? relativePath : files.pathJoin(self.root, relativePath);\n  },\n\n  // Pretty extreme! We call this when we learn that something has changed on\n  // the server in a way that our sync protocol doesn't understand well.\n  wipeAllPackages: function () {\n    var self = this;\n    var packagesDirectoryName = config.getPackagesDirectoryName();\n    var packageRootDir = files.pathJoin(self.root, packagesDirectoryName);\n    var escapedPackages;\n\n    try {\n      // XXX this variable actually can't be accessed from outside this\n      // line, this is definitely a bug\n      escapedPackages = files.readdir(packageRootDir);\n    } catch (e) {\n      // No packages at all? We're done.\n      if (e.code === 'ENOENT') {\n        return;\n      }\n      throw e;\n    }\n\n    // We want to be careful not to break the 'meteor' symlink inside the\n    // tropohouse. Hopefully nobody deleted/modified that package!\n    var latestToolPackageEscaped = null;\n    var latestToolVersion = null;\n    var currentToolPackageEscaped = null;\n    var currentToolVersion = null;\n    // Warning: we can't examine release.current here, because we might be\n    // currently processing release.load!\n    if (!files.inCheckout()) {\n      // toolsDir is something like:\n      // /home/user/.meteor/packages/meteor-tool/.1.0.17.ut200e++os.osx.x86_64+web.browser+web.cordova/meteor-tool-os.osx.x86_64\n      // or /C/Users/user/AppData/Local/Temp/mt-17618kk/tropohouse/packages/meteor-tool/33.0.1/mt-os.windows.x86_32 on Windows\n      var toolsDir = files.getCurrentToolsDir();\n      // eg, 'meteor-tool'\n      currentToolPackageEscaped =\n        files.pathBasename(files.pathDirname(files.pathDirname(toolsDir)));\n      // eg, '.1.0.17-xyz1.2.ut200e++os.osx.x86_64+web.browser+web.cordova' on Unix\n      // or '33.0.1' on Windows\n      var toolVersionDir = files.pathBasename(files.pathDirname(toolsDir));\n\n      if (process.platform !== 'win32') {\n        var toolVersionWithDotAndRandomBit = toolVersionDir.split('++')[0];\n        var pieces = toolVersionWithDotAndRandomBit.split('.');\n        pieces.shift();\n        pieces.pop();\n        currentToolVersion = pieces.join('.');\n      } else {\n        currentToolVersion = toolVersionDir;\n      }\n\n      var latestMeteorSymlink = self.latestMeteorSymlink();\n      if (latestMeteorSymlink.startsWith(packagesDirectoryName +\n                                         files.pathSep)) {\n        var rest = latestMeteorSymlink.substr(\n          packagesDirectoryName.length + files.pathSep.length);\n\n        pieces = rest.split(files.pathSep);\n        latestToolPackageEscaped = pieces[0];\n        latestToolVersion = pieces[1];\n      }\n    }\n\n    _.each(escapedPackages, function (packageEscaped) {\n      var packageDir = files.pathJoin(packageRootDir, packageEscaped);\n      var versions;\n\n      try {\n        versions = files.readdir(packageDir);\n      } catch (e) {\n        // Somebody put a file in here or something? Whatever, ignore.\n        if (e.code === 'ENOENT' || e.code === 'ENOTDIR') {\n          return;\n        }\n        throw e;\n      }\n      _.each(versions, function (version) {\n        // Is this a pre-0.9.0 \"warehouse\" version with a hash name?\n        if (/^[a-f0-9]{3,}$/.test(version)) {\n          return;\n        }\n\n        // Skip the currently-latest tool (ie, don't break top-level meteor\n        // symlink). This includes both the symlink with its name and the thing\n        // it points to.\n        if (packageEscaped === latestToolPackageEscaped &&\n            (version === latestToolVersion ||\n             version.startsWith('.' + latestToolVersion + '.'))) {\n          return;\n        }\n\n        // Skip the currently-executing tool (ie, don't break the current\n        // operation).\n        if (packageEscaped === currentToolPackageEscaped &&\n            (version === currentToolVersion ||\n             version.startsWith('.' + currentToolVersion + '.'))) {\n          return;\n        }\n\n        files.rm_recursive(files.pathJoin(packageDir, version));\n      });\n    });\n  },\n  // Returns true if the given package at the given version exists on disk, or\n  // false otherwise. Takes in the following:\n  //  - packageName: name of the package\n  //  - version: version\n  //  - architectures: (optional) array of architectures. Defaults to\n  //    archinfo.host().\n  installed: function (options) {\n    var self = this;\n    if (!options.packageName) {\n      throw Error(\"Missing required argument: packageName\");\n    }\n    if (!options.version) {\n      throw Error(\"Missing required argument: version\");\n    }\n    var architectures = options.architectures || [archinfo.host()];\n\n    var downloaded = self._alreadyDownloaded({\n      packageName: options.packageName,\n      version: options.version\n    });\n\n    return _.every(architectures, function (requiredArch) {\n      return archinfo.mostSpecificMatch(requiredArch, downloaded);\n    });\n  },\n\n  // Contacts the package server, downloads and extracts a tarball for a given\n  // buildRecord into a temporary directory, whose path is returned.\n  //\n  // XXX: Error handling.\n  _downloadBuildToTempDir: function (versionInfo, buildRecord) {\n    var url = buildRecord.build.url;\n\n    // XXX: We use one progress for download & untar; this isn't ideal:\n    // it relies on extractTarGz being fast and not reporting any progress.\n    // Really, we should create two subtasks\n    // (and, we should stream the download to the tar extractor)\n    var packageTarball = httpHelpers.getUrl({\n      url: url,\n      encoding: null,\n      progress: buildmessage.getCurrentProgressTracker(),\n      wait: false\n    });\n\n    return exports._extractAndConvert(packageTarball);\n  },\n\n  // Given a package name and version, returns the architectures for\n  // which we have downloaded this package\n  //\n  // Throws if the symlink cannot be read for any reason other than\n  // ENOENT/\n  _alreadyDownloaded: function (options) {\n    var self = this;\n    var packageName = options.packageName;\n    var version = options.version;\n    if (!options.packageName) {\n      throw Error(\"Missing required argument: packageName\");\n    }\n    if (!options.version) {\n      throw Error(\"Missing required argument: version\");\n    }\n\n\n    // Figure out what arches (if any) we have loaded for this package version\n    // already.\n    var packagePath = self.packagePath(packageName, version);\n    var downloadedArches = [];\n\n    // Find out which arches we have by reading the isopack metadata\n    var {metadata: packageMetadata} =\n          Isopack.readMetadataFromDirectory(packagePath);\n\n    // packageMetadata is null if there is no package at packagePath\n    if (packageMetadata) {\n      downloadedArches = _.pluck(packageMetadata.builds, \"arch\");\n    }\n\n    return downloadedArches;\n  },\n\n  _saveIsopack: function (isopack, packageName) {\n    // XXX does this actually need the name as an argument or can we just get\n    // it from isopack?\n\n    var self = this;\n\n    if (self.platform === \"win32\") {\n      isopack.saveToPath(self.packagePath(packageName, isopack.version), {\n        includePreCompilerPluginIsopackVersions: true\n      });\n    } else {\n      // Note: wipeAllPackages depends on this filename structure\n      // On Mac and Linux, we used to use a filename structure that used the\n      // names of symlinks to determine which builds we have downloaded. We no\n      // longer need this because we now parse package metadata, but we still\n      // need to write the symlinks correctly so that old meteor tools can\n      // still read newly downloaded packages.\n      var newPackageLinkTarget = '.' + isopack.version + '.' +\n        utils.randomToken() + '++' + isopack.buildArchitectures();\n\n      var combinedDirectory = self.packagePath(\n        packageName, newPackageLinkTarget);\n\n      isopack.saveToPath(combinedDirectory, {\n        includePreCompilerPluginIsopackVersions: true\n      });\n\n      files.symlinkOverSync(newPackageLinkTarget,\n        self.packagePath(packageName, isopack.version));\n    }\n  },\n\n  // Given a package name, version, and required architectures, checks to make\n  // sure that we have the package downloaded at the requested arch. If we do,\n  // returns null.\n  //\n  // Otherwise, if the catalog has no information about appropriate builds,\n  // registers a buildmessage error and returns null.\n  //\n  // Otherwise, returns a 'downloader' object with keys packageName, version,\n  // and download; download is a method which should be called in a buildmessage\n  // capture which actually downloads the package (registering any errors with\n  // buildmessage).\n  _makeDownloader: function (options) {\n    var self = this;\n    buildmessage.assertInJob();\n\n    if (!options.packageName) {\n      throw Error(\"Missing required argument: packageName\");\n    }\n    if (!options.version) {\n      throw Error(\"Missing required argument: version\");\n    }\n    if (!options.architectures) {\n      throw Error(\"Missing required argument: architectures\");\n    }\n\n    var packageName = options.packageName;\n    var version = options.version;\n\n    // Look up which arches we have already downloaded\n    var downloadedArches = self._alreadyDownloaded({\n      packageName: packageName,\n      version: version\n    });\n\n    var archesToDownload = _.filter(options.architectures, function (requiredArch) {\n      return !archinfo.mostSpecificMatch(requiredArch, downloadedArches);\n    });\n\n    // Have everything we need? Great.\n    if (!archesToDownload.length) {\n      Console.debug(\"Local package version is up-to-date:\", packageName + \"@\" + version);\n      return null;\n    }\n\n    // Since we are downloading from the server (and we've already done the\n    // local package check), we can use the official catalog here. (This is\n    // important, since springboarding calls this function before the complete\n    // catalog is ready!)\n    var buildsToDownload = catalog.official.getBuildsForArches(\n      packageName, version, archesToDownload);\n    if (! buildsToDownload) {\n      buildmessage.error(\n        \"No compatible binary build found for this package. \" +\n        \"Contact the package author and ask them to publish it \" +\n        \"for your platform.\", {tags: { refreshCouldHelp: true }});\n      return null;\n    }\n\n    var packagePath = self.packagePath(packageName, version);\n    var download = function download () {\n      buildmessage.assertInCapture();\n\n      Console.debug(\"Downloading missing local versions of package\",\n                    packageName + \"@\" + version, \":\", archesToDownload);\n\n      buildmessage.enterJob({\n        title: \"downloading \" + packageName + \"@\" + version + \"...\"\n      }, function() {\n        var buildInputDirs = [];\n        var buildTempDirs = [];\n        var packageLinkTarget = null;\n\n        // Find the previous actual directory of the package\n        if (self.platform === \"win32\") {\n          // On Windows, we don't use symlinks.\n          // If there's already a package in the tropohouse, start with it.\n          if (files.exists(packagePath)) {\n            buildInputDirs.push(packagePath);\n          }\n        } else {\n          // On posix, we have a symlink structure. Get the target of the\n          // symlink so that we can delete it later.\n          try {\n            packageLinkTarget = files.readlink(packagePath);\n          } catch (e) {\n            // Complain about anything other than \"we don't have it at all\".\n            // This includes \"not a symlink\": The main reason this would not be\n            // a symlink is if it's a directory containing a pre-0.9.0 package\n            // (ie, this is a warehouse package not a tropohouse package). But\n            // the versions should not overlap: warehouse versions are truncated\n            // SHAs whereas tropohouse versions should be semver-like.\n            if (e.code !== 'ENOENT') {\n              throw e;\n            }\n          }\n\n          // If there's already a package in the tropohouse, start with it.\n          if (packageLinkTarget) {\n            buildInputDirs.push(\n              files.pathResolve(files.pathDirname(packagePath),\n                                packageLinkTarget));\n          }\n        }\n\n        // XXX how does concurrency work here?  we could just get errors if we\n        // try to rename over the other thing?  but that's the same as in\n        // warehouse?\n        _.each(buildsToDownload, function (build) {\n          buildmessage.enterJob({\n            title: \"downloading \" + packageName + \"@\" + version + \"...\"\n          }, function() {\n            try {\n              var buildTempDir = self._downloadBuildToTempDir(\n                { packageName: packageName, version: version }, build);\n            } catch (e) {\n              if (!(e instanceof files.OfflineError)) {\n                throw e;\n              }\n              buildmessage.error(e.error.message);\n            }\n            buildInputDirs.push(buildTempDir);\n            buildTempDirs.push(buildTempDir);\n          });\n        });\n        if (buildmessage.jobHasMessages()) {\n          return;\n        }\n\n        // We need to turn our builds into a single isopack.\n        var isopack = new Isopack();\n        _.each(buildInputDirs, function (buildTempDir, i) {\n          isopack._loadUnibuildsFromPath(packageName, buildTempDir, {\n            firstIsopack: i === 0,\n          });\n        });\n\n        self._saveIsopack(isopack, packageName, version);\n\n        // Delete temp directories now (asynchronously).\n        _.each(buildTempDirs, function (buildTempDir) {\n          files.freeTempDir(buildTempDir);\n        });\n\n        // Clean up old version.\n        if (packageLinkTarget) {\n          files.rm_recursive(self.packagePath(packageName, packageLinkTarget));\n        }\n      });\n    };\n\n    return {\n      packageName: packageName,\n      version: version,\n      download: download\n    };\n  },\n\n\n  // Takes in a PackageMap object. Downloads any versioned packages we don't\n  // already have.\n  //\n  // Reports errors via buildmessage.\n  downloadPackagesMissingFromMap: function (packageMap, options) {\n    var self = this;\n    buildmessage.assertInCapture();\n    options = options || {};\n    var serverArchs = options.serverArchitectures || [archinfo.host()];\n\n    var downloader;\n    var downloaders = [];\n    packageMap.eachPackage(function (packageName, info) {\n      if (info.kind !== 'versioned') {\n        return;\n      }\n      buildmessage.enterJob(\n        \"checking for \" + packageName + \"@\" + info.version,\n        function () {\n          downloader = self._makeDownloader({\n            packageName: packageName,\n            version: info.version,\n            architectures: serverArchs\n          });\n          if (buildmessage.jobHasMessages()) {\n            downloaders = null;\n            return;\n          }\n          if (downloader && downloaders) {\n            downloaders.push(downloader);\n          }\n        }\n      );\n    });\n\n    // Did anything fail? Don't download anything.\n    if (! downloaders) {\n      return;\n    }\n\n    // Nothing to download? Great.\n    if (! downloaders.length) {\n      return;\n    }\n\n    // Just one package to download? Use a good message.\n    if (downloaders.length === 1) {\n      downloader = downloaders[0];\n      buildmessage.enterJob(\n        \"downloading \" + downloader.packageName + \"@\" + downloader.version,\n        function () {\n          downloader.download();\n        }\n      );\n      return;\n    }\n\n    // Download multiple packages in parallel.\n    // XXX use a better progress bar that shows how many you've\n    // finished downloading.\n    buildmessage.forkJoin({\n      title: 'downloading ' + downloaders.length + ' packages',\n      parallel: true\n    }, downloaders, function (downloader) {\n      downloader.download();\n    });\n  },\n\n  latestMeteorSymlink: function () {\n    var self = this;\n    var linkPath = files.pathJoin(self.root, 'meteor');\n    return files.readLinkToMeteorScript(linkPath, self.platform);\n  },\n\n  linkToLatestMeteor: function (scriptLocation) {\n    var self = this;\n    var linkPath = files.pathJoin(self.root, 'meteor');\n    files.linkToMeteorScript(scriptLocation, linkPath, self.platform);\n  },\n\n  _getPlatform: function () {\n    return this.platform;\n  }\n});\n"
  },
  {
    "path": "tools/packaging/updater.js",
    "content": "var _ = require('underscore');\n\nvar runLog = require('../runners/run-log.js');\nvar catalog = require('./catalog/catalog.js');\nvar archinfo = require('../utils/archinfo.js');\nvar isopack = require('../isobuild/isopack.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar Console = require('../console/console.js').Console;\nvar auth = require('../meteor-services/auth.js');\nvar files = require('../fs/files.js');\n\nvar tropohouse = require('./tropohouse.js');\nvar release = require('./release.js');\nvar packageMapModule = require('./package-map.js');\n\n/**\n * Check to see if an update is available. If so, download and install\n * it before returning.\n *\n * options: showBanner\n */\nvar checkInProgress = false;\nexports.tryToDownloadUpdate = function (options) {\n  options = options || {};\n  // Don't run more than one check simultaneously. It should be\n  // harmless but having two downloads happening simultaneously (and\n  // two sets of messages being printed) would be confusing.\n  if (checkInProgress) {\n    return;\n  }\n  checkInProgress = true;\n  checkForUpdate(!! options.showBanner, !! options.printErrors);\n  checkInProgress = false;\n};\n\nvar firstCheck = true;\n\nvar checkForUpdate = function (showBanner, printErrors) {\n  // While we're doing background stuff, try to revoke any old tokens in our\n  // session file.\n  auth.tryRevokeOldTokens({ timeout: 15 * 1000 });\n\n  if (firstCheck) {\n    // We want to avoid a potential race condition here, because we run an\n    // update almost immediately at run.  We don't want to drop the resolver\n    // cache; that would be slow.  \"meteor run\" itself should have run a refresh\n    // anyway.  So, the first time, we just skip the remote catalog sync.  But\n    // we do want to do the out-of-date release checks, so we can't just delay\n    // the first update cycle.\n    firstCheck = false;\n  } else {\n    try {\n      catalog.official.refresh();\n    } catch (err) {\n      Console.debug(\"Failed to refresh catalog, ignoring error\", err);\n      return;\n    }\n  }\n\n  if (!release.current.isProperRelease()) {\n    return;\n  }\n\n  updateMeteorToolSymlink(printErrors);\n\n  maybeShowBanners();\n};\n\nvar lastShowTimes = {};\n\nvar shouldShow = function (key, maxAge) {\n  var now = +(new Date);\n\n  if (maxAge === undefined) {\n    maxAge = 12 * 60 * 60 * 1000;\n  }\n\n  var lastShow = lastShowTimes[key];\n  if (lastShow !== undefined) {\n    var age = now - lastShow;\n    if (age < maxAge) {\n      return false;\n    }\n  }\n\n  lastShowTimes[key] = now;\n  return true;\n};\n\nvar maybeShowBanners = function () {\n  var releaseData = release.current.getCatalogReleaseData();\n\n  var banner = releaseData.banner;\n  if (banner) {\n    var bannerDate =\n          banner.lastUpdated ? new Date(banner.lastUpdated) : new Date;\n    if (catalog.official.shouldShowBanner(release.current.name, bannerDate)) {\n      // This banner is new; print it!\n      runLog.log(\"\");\n      runLog.log(banner.text);\n      runLog.log(\"\");\n      catalog.official.setBannerShownDate(release.current.name, bannerDate);\n      return;\n    }\n  }\n\n  // We now consider printing some simpler banners, if this isn't the latest\n  // release. But if the user specified a release manually with --release, we\n  // don't bother: we only want to tell users about ways to update *their app*.\n  if (release.forced) {\n    return;\n  }\n\n  const catalogUtils = require('./catalog/catalog-utils.js');\n\n  // Didn't print a banner? Maybe we have a patch release to recommend.\n  var track = release.current.getReleaseTrack();\n  var patchReleaseVersion = releaseData.patchReleaseVersion;\n  if (patchReleaseVersion) {\n    var patchRelease = catalog.official.getReleaseVersion(\n      track, patchReleaseVersion);\n    if (patchRelease && patchRelease.recommended) {\n      var patchKey = \"patchrelease-\" + track + \"-\" + patchReleaseVersion;\n      if (shouldShow(patchKey)) {\n        runLog.log(\n          \"=> A patch (\" +\n          catalogUtils.displayRelease(track, patchReleaseVersion) +\n          \") for your current release is available!\");\n        runLog.log(\"   Update this project now with 'meteor update --patch'.\");\n      }\n      return;\n    }\n  }\n\n  // There's no patch (so no urgent exclamation!) but there may be something\n  // worth mentioning.\n  // XXX maybe run constraint solver to change the message depending on whether\n  //     or not it will actually work?\n  var currentReleaseOrderKey = releaseData.orderKey || null;\n  var futureReleases = catalog.official.getSortedRecommendedReleaseVersions(\n    track, currentReleaseOrderKey);\n  if (futureReleases.length) {\n    var futureReleaseKey = \"futurerelease-\" + track + \"-\" + futureReleases[0];\n    if (shouldShow(futureReleaseKey)) {\n      runLog.log(\n        \"=> \" + catalogUtils.displayRelease(track, futureReleases[0]) +\n        \" is available. Update this project with 'meteor update'.\");\n    }\n    return;\n  }\n};\n\n// Update ~/.meteor/meteor to point to the tool binary from the tools of the\n// latest recommended release on the default release track.\nvar updateMeteorToolSymlink = function (printErrors) {\n  // Get the latest release version of METEOR. (*Always* of the default\n  // track, not of whatever we happen to be running: we always want the tool\n  // symlink to go to the default track.)\n  var latestReleaseVersion = catalog.official.getDefaultReleaseVersion();\n  // Maybe you're on some random track with nothing recommended. That's OK.\n  if (!latestReleaseVersion) {\n    return;\n  }\n\n  var latestRelease = catalog.official.getReleaseVersion(\n    latestReleaseVersion.track, latestReleaseVersion.version);\n  if (!latestRelease) {\n    throw Error(\"latest release doesn't exist?\");\n  }\n  if (!latestRelease.tool) {\n    throw Error(\"latest release doesn't have a tool?\");\n  }\n\n  var latestReleaseToolParts = latestRelease.tool.split('@');\n  var latestReleaseToolPackage = latestReleaseToolParts[0];\n  var latestReleaseToolVersion = latestReleaseToolParts[1];\n  var relativeToolPath = tropohouse.default.packagePath(\n    latestReleaseToolPackage, latestReleaseToolVersion, true);\n\n  var localLatestReleaseLink = tropohouse.default.latestMeteorSymlink();\n\n  if (! localLatestReleaseLink.startsWith(relativeToolPath + files.pathSep)) {\n    // The latest release from the catalog is not where the ~/.meteor/meteor\n    // symlink points to. Let's make sure we have that release on disk,\n    // and then update the symlink.\n    var packageMap =\n          packageMapModule.PackageMap.fromReleaseVersion(latestRelease);\n    var messages = buildmessage.capture(function () {\n      tropohouse.default.downloadPackagesMissingFromMap(packageMap);\n    });\n    if (messages.hasMessages()) {\n      // Ignore errors because we are running in the background, uness we\n      // specifically requested to print errors because we are testing this\n      // feature.\n      if (printErrors) {\n        Console.printMessages(messages);\n      }\n      return;\n    }\n\n    var toolIsopack = new isopack.Isopack;\n    toolIsopack.initFromPath(\n      latestReleaseToolPackage,\n      tropohouse.default.packagePath(latestReleaseToolPackage,\n                                     latestReleaseToolVersion));\n    var toolRecord = _.findWhere(toolIsopack.toolsOnDisk,\n                                 {arch: archinfo.host()});\n\n    // XXX maybe we shouldn't throw from this background thing\n    // counter: this is super weird and should never ever happen.\n    if (!toolRecord) {\n      throw Error(\"latest release has no tool?\");\n    }\n\n    tropohouse.default.linkToLatestMeteor(files.pathJoin(\n      relativeToolPath, toolRecord.path, 'meteor'));\n  }\n};\n"
  },
  {
    "path": "tools/packaging/warehouse.js",
    "content": "// This file is used to access the \"warehouse\" of pre-0.9.0 releases. This code\n// is now legacy, but we keep it around so that you can still use the same\n// `meteor` entry point to run pre-0.9.0 and post-0.9.0 releases, for now. All\n// it knows how to do is download old releases and explain to main.js how to\n// exec them.\n//\n// Because of this, we do have to be careful that the files used by this code\n// and the files used by tropohouse.js (the modern version of the warehouse)\n// don't overlap. tropohouse does not use tools or releases directorys, and\n// while they both have packages directories with similar structures, the\n// version names should not overlap: warehouse versions are SHAs and tropohouse\n// versions are semvers.  Additionally, while they do both use the 'meteor'\n// symlink at the top level, there's no actual code in this file to write that\n// symlink (it was just created by the bootstrap tarball release process).\n\n\n/// We store a \"warehouse\" of tools, releases and packages on\n/// disk. This warehouse is populated from our servers, as needed.\n///\n/// Directory structure:\n///\n///     meteor (relative path symlink to tools/latest/bin/meteor)\n///     tools/ (not in checkout, since we run against checked-out code)\n///       latest/ (relative path symlink to latest VERSION/ tools directory)\n///       VERSION/\n///     releases/\n///       latest (relative path symlink to latest x.y.z.release.json)\n///       x.y.z.release.json\n///       x.y.z.notices.json\n///     packages/\n///       foo/\n///         VERSION/\n///\n/// The warehouse is not used at all when running from a\n/// checkout. Only local packages will be loaded (from\n/// CHECKOUT/packages or within a directory in the PACKAGE_DIRS\n/// environment variable). The setup of that is handled by release.js.\n\nvar os = require(\"os\");\nvar _ = require(\"underscore\");\n\nvar files = require('../fs/files.js');\nvar httpHelpers = require('../utils/http-helpers.js');\nvar fiberHelpers = require('../utils/fiber-helpers.js');\n\n// Use `METEOR_WAREHOUSE_URLBASE` to override the default warehouse\n// url base. \nvar WAREHOUSE_URLBASE = process.env.METEOR_WAREHOUSE_URLBASE || 'https://warehouse.meteor.com';\n\nvar warehouse = exports;\n_.extend(warehouse, {\n  // An exception meaning that you asked for a release that doesn't\n  // exist.\n  NoSuchReleaseError: function () {\n  },\n\n  // Return our loaded collection of tools, releases and\n  // packages. If we're running an installed version, found at\n  // $HOME/.meteor.\n  getWarehouseDir: function () {\n    // a hook for tests, or i guess for users.\n    if (process.env.METEOR_WAREHOUSE_DIR) {\n      return files.convertToStandardPath(process.env.METEOR_WAREHOUSE_DIR);\n    }\n\n    // This function should never be called unless we have a warehouse\n    // (an installed version, or with process.env.METEOR_WAREHOUSE_DIR\n    // set)\n    if (!files.usesWarehouse()) {\n      throw new Error(\"There's no warehouse in a git checkout\");\n    }\n\n    return files.pathJoin(files.getHomeDir(), '.meteor');\n  },\n\n  getToolsDir: function (version) {\n    return files.pathJoin(warehouse.getWarehouseDir(), 'tools', version);\n  },\n\n  getToolsFreshFile: function (version) {\n    return files.pathJoin(warehouse.getWarehouseDir(), 'tools', version, '.fresh');\n  },\n\n  _latestReleaseSymlinkPath: function () {\n    return files.pathJoin(warehouse.getWarehouseDir(), 'releases', 'latest');\n  },\n\n  _latestToolsSymlinkPath: function () {\n    return files.pathJoin(warehouse.getWarehouseDir(), 'tools', 'latest');\n  },\n\n  // Ensure the passed release version is stored in the local\n  // warehouse and return its parsed manifest.\n  //\n  // If 'quiet' is true, don't print anything as we do it.\n  //\n  // Throws:\n  // - files.OfflineError if the release isn't cached locally and we\n  //   are offline.\n  // - warehouse.NoSuchReleaseError if we talked to the server and it\n  //   told us that no release named 'release' exists.\n  ensureReleaseExistsAndReturnManifest: function (release, quiet) {\n    if (!files.usesWarehouse()) {\n      throw new Error(\"Not in a warehouse but requesting a manifest!\");\n    }\n\n    return warehouse._populateWarehouseForRelease(release, !quiet);\n  },\n\n  packageExistsInWarehouse: function (name, version) {\n    // A package exists if its directory exists. (We used to look for a\n    // particular file name (\"package.js\") inside the directory, but since we\n    // always install packages by untarring to a temporary directory and\n    // renaming atomically, we shouldn't worry about partial packages.)\n    return files.exists(\n      files.pathJoin(warehouse.getWarehouseDir(), 'packages', name, version));\n  },\n\n  getPackageFreshFile: function (name, version) {\n    return files.pathJoin(\n      warehouse.getWarehouseDir(),\n      'packages', name, version, '.fresh');\n  },\n\n  toolsExistsInWarehouse: function (version) {\n    return files.exists(warehouse.getToolsDir(version));\n  },\n\n  // Returns true if we already have the release file on disk, and it's not a\n  // fake \"red pill\" release --- we should never springboard to those!\n  realReleaseExistsInWarehouse: function (version) {\n    var releasesDir = files.pathJoin(warehouse.getWarehouseDir(), 'releases');\n    var releaseManifestPath = files.pathJoin(releasesDir,\n                                        version + '.release.json');\n    try {\n      var manifest = JSON.parse(files.readFile(releaseManifestPath, 'utf8'));\n      return !manifest.redPill;\n    } catch (e) {\n      return false;\n    }\n  },\n\n  _calculateNewPiecesForRelease: function (releaseManifest) {\n    // newPieces.tools and newPieces.packages[PACKAGE] are either falsey (if\n    // nothing is new), or an object with keys \"version\" and bool\n    // \"needsDownload\". \"needsDownload\" is true if the piece is not in the\n    // warehouse, and is false if it's in the warehouse but has never been used.\n    var newPieces = {\n      tools: null,\n      packages: {}\n    };\n\n    // populate warehouse with tools version for this release\n    var toolsVersion = releaseManifest.tools;\n    if (!warehouse.toolsExistsInWarehouse(toolsVersion)) {\n      newPieces.tools = {version: toolsVersion, needsDownload: true};\n    } else if (files.exists(warehouse.getToolsFreshFile(toolsVersion))) {\n      newPieces.tools = {version: toolsVersion, needsDownload: false};\n    }\n\n    _.each(releaseManifest.packages, function (version, name) {\n      if (!warehouse.packageExistsInWarehouse(name, version)) {\n        newPieces.packages[name] = {version: version, needsDownload: true};\n      } else if (files.exists(warehouse.getPackageFreshFile(name, version))) {\n        newPieces.packages[name] = {version: version, needsDownload: false};\n      }\n    });\n    if (newPieces.tools || !_.isEmpty(newPieces.packages)) {\n      return newPieces;\n    }\n    return null;\n  },\n\n  _packageUpdatesMessage: function (packageNames) {\n    var lines = [];\n    var width = 80;  // see utils.printPackageList for why we hardcode this\n    var currentLine = ' * Package updates:';\n    _.each(packageNames, function (name) {\n      if (currentLine.length + 1 + name.length <= width) {\n        currentLine += ' ' + name;\n      } else {\n        lines.push(currentLine);\n        currentLine = '   ' + name;\n      }\n    });\n    lines.push(currentLine);\n    return lines.join('\\n');\n  },\n\n  // fetches the manifest file for the given release version. also fetches\n  // all of the missing versioned packages referenced from the release manifest\n  // @param releaseVersion {String} eg \"0.1\"\n  _populateWarehouseForRelease: function (releaseVersion, showInstalling) {\n    var releasesDir = files.pathJoin(warehouse.getWarehouseDir(), 'releases');\n    files.mkdir_p(releasesDir, 0o755);\n    var releaseManifestPath = files.pathJoin(releasesDir,\n                                             releaseVersion + '.release.json');\n\n    // If the release already exists, we don't have to do anything, except maybe\n    // print a message if this release has never been used before (and we only\n    // have it due to a background download).\n    var releaseAlreadyExists = true;\n    try {\n      var releaseManifestText = files.readFile(releaseManifestPath);\n    } catch (e) {\n      releaseAlreadyExists = false;\n    }\n\n    // Now get release manifest if we don't already have it, but only write it\n    // after we're done writing packages\n    if (!releaseAlreadyExists) {\n\n      // For automated self-test. If METEOR_TEST_FAIL_RELEASE_DOWNLOAD\n      // is 'offline' or 'not-found', make release downloads fail.\n      if (process.env.METEOR_TEST_FAIL_RELEASE_DOWNLOAD === \"offline\") {\n        throw new files.OfflineError(new Error(\"scripted failure for tests\"));\n      }\n      if (process.env.METEOR_TEST_FAIL_RELEASE_DOWNLOAD === \"not-found\") {\n        throw new warehouse.NoSuchReleaseError;\n      }\n\n      try {\n        var result = httpHelpers.request(\n          WAREHOUSE_URLBASE + \"/releases/\" + releaseVersion + \".release.json\");\n      } catch (e) {\n        throw new files.OfflineError(e);\n      }\n\n      if (result.response.statusCode !== 200) {\n        // We actually got some response, so we're probably online and we\n        // just can't find the release.\n        throw new warehouse.NoSuchReleaseError;\n      }\n\n      releaseManifestText = result.body;\n    }\n\n    var releaseManifest = JSON.parse(releaseManifestText);\n\n    var newPieces = warehouse._calculateNewPiecesForRelease(releaseManifest);\n\n    if (releaseAlreadyExists && !newPieces) {\n      return releaseManifest;\n    }\n\n    if (newPieces && showInstalling) {\n      console.log(\"Installing Meteor %s:\", releaseVersion);\n      if (newPieces.tools) {\n        console.log(\" * 'meteor' build tool (version %s)\",\n                    newPieces.tools.version);\n      }\n      if (!_.isEmpty(newPieces.packages)) {\n        console.log(warehouse._packageUpdatesMessage(\n          _.keys(newPieces.packages).sort()));\n      }\n      console.log();\n    }\n\n    if (!releaseAlreadyExists) {\n      if (newPieces && newPieces.tools && newPieces.tools.needsDownload) {\n        try {\n          warehouse.downloadToolsToWarehouse(\n            newPieces.tools.version,\n            warehouse._platform(),\n            warehouse.getWarehouseDir());\n        } catch (e) {\n          if (showInstalling) {\n            console.error(\"Failed to load tools for release \" + releaseVersion);\n          }\n          throw e;\n        }\n\n        // If the 'tools/latest' symlink doesn't exist, this must be the first\n        // legacy tools we've downloaded into this warehouse. Add the symlink,\n        // so that the tools doesn't get confused when it tries to readlink it.\n        if (!files.exists(warehouse._latestToolsSymlinkPath())) {\n          files.symlink(newPieces.tools.version,\n                         warehouse._latestToolsSymlinkPath());\n        }\n      }\n\n      var packagesToDownload = {};\n      _.each(newPieces && newPieces.packages, function (packageInfo, name) {\n        if (packageInfo.needsDownload) {\n          packagesToDownload[name] = packageInfo.version;\n        }\n      });\n      if (!_.isEmpty(packagesToDownload)) {\n        try {\n          warehouse.downloadPackagesToWarehouse(packagesToDownload,\n                                                warehouse._platform(),\n                                                warehouse.getWarehouseDir());\n        } catch (e) {\n          if (showInstalling) {\n            console.error(\"Failed to load packages for release \" +\n                          releaseVersion);\n          }\n          throw e;\n        }\n      }\n\n      // try getting the releases's notices. only blessed releases have one, so\n      // if we can't find it just proceed.\n      try {\n        var notices = httpHelpers.getUrl(\n          WAREHOUSE_URLBASE + \"/releases/\" + releaseVersion + \".notices.json\");\n\n        // Real notices are valid JSON.\n        JSON.parse(notices);\n\n        files.writeFile(\n          files.pathJoin(releasesDir, releaseVersion + '.notices.json'),\n          notices);\n      } catch (e) {\n        // no notices, proceed\n      }\n\n      // Now that we have written all packages, it's safe to write the\n      // release manifest.\n      files.writeFile(releaseManifestPath, releaseManifestText);\n\n      // If the 'releases/latest' symlink doesn't exist, this must be the first\n      // legacy release manifest we've downloaded into this warehouse. Add the\n      // symlink, so that the tools doesn't get confused when it tries to\n      // readlink it.\n      if (!files.exists(warehouse._latestReleaseSymlinkPath())) {\n        files.symlink(releaseVersion + '.release.json',\n                       warehouse._latestReleaseSymlinkPath());\n      }\n    }\n\n    // Finally, clear the \"fresh\" files for all the things we just printed\n    // (whether or not we just downloaded them). (Don't do this if we didn't\n    // print the installing message!)\n    if (newPieces && showInstalling) {\n      var unlinkIfExists = function (file) {\n        try {\n          files.unlink(file);\n        } catch (e) {\n          // If two processes populate the warehouse in parallel, the other\n          // process may have deleted the fresh file. That's OK!\n          if (e.code === \"ENOENT\") {\n            return;\n          }\n          throw e;\n        }\n      };\n\n      if (newPieces.tools) {\n        unlinkIfExists(warehouse.getToolsFreshFile(newPieces.tools.version));\n      }\n      _.each(newPieces.packages, function (packageInfo, name) {\n        unlinkIfExists(\n          warehouse.getPackageFreshFile(name, packageInfo.version));\n      });\n    }\n\n    return releaseManifest;\n  },\n\n  // this function is also used by bless-release.js\n  downloadToolsToWarehouse: function (\n      toolsVersion, platform, warehouseDirectory, dontWriteFreshFile) {\n    // XXX this sucks. We store all the tarballs in memory. This is huge.\n    // We should instead stream packages in parallel. Since the node stream\n    // API is in flux, we should probably wait a bit.\n    // http://blog.nodejs.org/2012/12/20/streams2/\n\n    var toolsTarballFilename =\n          \"meteor-tools-\" + toolsVersion + \"-\" + platform + \".tar.gz\";\n    var toolsTarballPath = \"/tools/\" + toolsVersion + \"/\"\n          + toolsTarballFilename;\n    var toolsTarball = httpHelpers.getUrl({\n      url: WAREHOUSE_URLBASE + toolsTarballPath,\n      encoding: null\n    });\n    files.extractTarGz(\n      toolsTarball, files.pathJoin(warehouseDirectory, 'tools', toolsVersion));\n    if (!dontWriteFreshFile) {\n      files.writeFile(warehouse.getToolsFreshFile(toolsVersion), '');\n    }\n  },\n\n  // this function is also used by bless-release.js\n  downloadPackagesToWarehouse: function (packagesToDownload,\n                                         platform,\n                                         warehouseDirectory,\n                                         dontWriteFreshFile) {\n    fiberHelpers.parallelEach(\n      packagesToDownload, function (version, name) {\n        var packageDir = files.pathJoin(\n          warehouseDirectory, 'packages', name, version);\n        var packageUrl = WAREHOUSE_URLBASE + \"/packages/\" + name +\n              \"/\" + version +\n              \"/\" + name + '-' + version + \"-\" + platform + \".tar.gz\";\n\n        var tarball = httpHelpers.getUrl({url: packageUrl, encoding: null});\n        files.extractTarGz(tarball, packageDir);\n        if (!dontWriteFreshFile) {\n          files.writeFile(warehouse.getPackageFreshFile(name, version), '');\n        }\n      });\n  },\n\n  _platform: function () {\n    // Normalize from Node \"os.arch()\" to \"uname -m\".\n    var arch = os.arch();\n    if (arch === \"ia32\") {\n      arch = \"i686\";\n    } else if (arch === \"x64\") {\n      arch = \"x86_64\";\n    } else {\n      throw new Error(\"Unsupported architecture \" + arch);\n    }\n    return os.type() + \"_\" + arch;\n  }\n});\n"
  },
  {
    "path": "tools/project-context.js",
    "content": "var assert = require(\"assert\");\nvar _ = require('underscore');\n\nvar archinfo = require('./utils/archinfo.js');\nvar buildmessage = require('./utils/buildmessage.js');\nvar catalog = require('./packaging/catalog/catalog.js');\nvar catalogLocal = require('./packaging/catalog/catalog-local.js');\nvar Console = require('./console/console.js').Console;\nvar files = require('./fs/files.js');\nvar isopackCacheModule = require('./isobuild/isopack-cache.js');\nvar isopackets = require('./tool-env/isopackets.js');\nvar packageMapModule = require('./packaging/package-map.js');\nvar release = require('./packaging/release.js');\nvar tropohouse = require('./packaging/tropohouse.js');\nvar utils = require('./utils/utils.js');\nvar watch = require('./fs/watch.js');\nvar Profile = require('./tool-env/profile.js').Profile;\nimport { KNOWN_ISOBUILD_FEATURE_PACKAGES } from './isobuild/compiler.js';\n\n// The ProjectContext represents all the context associated with an app:\n// metadata files in the `.meteor` directory, the choice of package versions\n// used by it, etc.  Any time you want to work with an app, create a\n// ProjectContext and call prepareProjectForBuild on it (in a buildmessage\n// context).\n//\n// Note that this should only be used by parts of the code that truly require a\n// full project to exist; you won't find any reference to ProjectContext in\n// compiler.js or isopack.js, which work on individual files (though they will\n// get references to some of the objects which can be stored in a ProjectContext\n// such as PackageMap and IsopackCache).  Parts of the code that should deal\n// with ProjectContext include command implementations, the parts of bundler.js\n// that deal with creating a full project, PackageSource.initFromAppDir, stats\n// reporting, etc.\n//\n// Classes in this file follow the standard protocol where names beginning with\n// _ should not be externally accessed.\nfunction ProjectContext(options) {\n  var self = this;\n  assert.ok(self instanceof ProjectContext);\n\n  if (!options.projectDir)\n    throw Error(\"missing projectDir!\");\n\n  self.originalOptions = options;\n  self.reset();\n}\nexports.ProjectContext = ProjectContext;\n\n// The value is the name of the method to call to continue.\nvar STAGE = {\n  INITIAL: '_readProjectMetadata',\n  READ_PROJECT_METADATA: '_initializeCatalog',\n  INITIALIZE_CATALOG: '_resolveConstraints',\n  RESOLVE_CONSTRAINTS: '_downloadMissingPackages',\n  DOWNLOAD_MISSING_PACKAGES: '_buildLocalPackages',\n  BUILD_LOCAL_PACKAGES: '_saveChangedMetadata',\n  SAVE_CHANGED_METADATA: 'DONE'\n};\n\n_.extend(ProjectContext.prototype, {\n  reset: function (moreOptions, resetOptions) {\n    var self = this;\n    // Allow overriding some options until the next call to reset; used by\n    // 'meteor update' code to try various values of releaseForConstraints.\n    var options = _.extend({}, self.originalOptions, moreOptions);\n    // This is options that are actually directed at reset itself.\n    resetOptions = resetOptions || {};\n\n    self.projectDir = options.projectDir;\n    self.tropohouse = options.tropohouse || tropohouse.default;\n\n    self._packageMapFilename = options.packageMapFilename ||\n      files.pathJoin(self.projectDir, '.meteor', 'versions');\n\n    self._serverArchitectures = options.serverArchitectures || [];\n    // We always need to download host versions of packages, at least for\n    // plugins.\n    self._serverArchitectures.push(archinfo.host());\n    self._serverArchitectures = _.uniq(self._serverArchitectures);\n\n    // test-packages overrides this to load local packages from your real app\n    // instead of from test-runner-app.\n    self._projectDirForLocalPackages = options.projectDirForLocalPackages ||\n      options.projectDir;\n    self._explicitlyAddedLocalPackageDirs =\n      options.explicitlyAddedLocalPackageDirs;\n\n    // Used to override the directory that Meteor's build process\n    // writes to; used by `meteor test` so that you can test your\n    // app in parallel to writing it, with an isolated database.\n    // You can override the default .meteor/local by specifying\n    // METEOR_LOCAL_DIR.\n    self.projectLocalDir = process.env.METEOR_LOCAL_DIR ?\n      process.env.METEOR_LOCAL_DIR : (options.projectLocalDir ||\n      files.pathJoin(self.projectDir, '.meteor', 'local'));\n\n    // Used by 'meteor rebuild'; true to rebuild all packages, or a list of\n    // package names.  Deletes the isopacks and their plugin caches.\n    self._forceRebuildPackages = options.forceRebuildPackages;\n\n    // Set in a few cases where we really want to only get packages from\n    // checkout.\n    self._ignorePackageDirsEnvVar = options.ignorePackageDirsEnvVar;\n\n    // Set by some tests where we want to pretend that we don't have packages in\n    // the git checkout (because they're using a fake warehouse).\n    self._ignoreCheckoutPackages = options.ignoreCheckoutPackages;\n\n    // Set by some tests to override the official catalog.\n    self._officialCatalog = options.officialCatalog || catalog.official;\n\n    if (options.alwaysWritePackageMap && options.neverWritePackageMap)\n      throw Error(\"always or never?\");\n\n    // Set by 'meteor create' and 'meteor update' to ensure that\n    // .meteor/versions is always written even if release.current does not match\n    // the project's release.\n    self._alwaysWritePackageMap = options.alwaysWritePackageMap;\n\n    // Set by a few special-case commands that call\n    // projectConstraintsFile.addConstraints for internal reasons without\n    // intending to actually write .meteor/packages and .meteor/versions (eg,\n    // 'publish' wants to make sure making sure the test is built, and\n    // --get-ready wants to build every conceivable package).\n    self._neverWriteProjectConstraintsFile =\n      options.neverWriteProjectConstraintsFile;\n    self._neverWritePackageMap = options.neverWritePackageMap;\n\n    // Set by 'meteor update' to specify which packages may be updated. Array of\n    // package names.\n    self._upgradePackageNames = options.upgradePackageNames;\n    // Set by 'meteor update' to mean that we should upgrade the\n    // \"patch\" (and wrapNum, etc.) parts of indirect dependencies.\n    self._upgradeIndirectDepPatchVersions =\n      options.upgradeIndirectDepPatchVersions;\n\n    // Set by publishing commands to ensure that published packages always have\n    // a web.cordova slice (because we aren't yet smart enough to just default\n    // to using the web.browser slice instead or make a common 'web' slice).\n    self._forceIncludeCordovaUnibuild = options.forceIncludeCordovaUnibuild;\n\n    // If explicitly specified as null, use no release for constraints.\n    // If specified non-null, should be a release version catalog record.\n    // If not specified, defaults to release.current.\n    //\n    // Note that NONE of these cases are \"use the release from\n    // self.releaseFile\"; after all, if you are explicitly running `meteor\n    // --release foo` it will override what is found in .meteor/releases.\n    if (_.has(options, 'releaseForConstraints')) {\n      self._releaseForConstraints = options.releaseForConstraints || null;\n    } else if (release.current.isCheckout()) {\n      self._releaseForConstraints = null;\n    } else {\n      self._releaseForConstraints = release.current.getCatalogReleaseData();\n    }\n\n    if (resetOptions.preservePackageMap && self.packageMap) {\n      self._cachedVersionsBeforeReset = self.packageMap.toVersionMap();\n      // packageMapFile should always exist if packageMap does\n      self._oldPackageMapFileHash = self.packageMapFile.fileHash;\n    } else {\n      self._cachedVersionsBeforeReset = null;\n      self._oldPackageMapFileHash = null;\n    }\n\n    // The --allow-incompatible-update command-line switch, which allows\n    // the version solver to choose versions of root dependencies that are\n    // incompatible with the previously chosen versions (i.e. to downgrade\n    // them or change their major version).\n    self._allowIncompatibleUpdate = options.allowIncompatibleUpdate;\n\n    // If set, we run the linter on the app and local packages.  Set by 'meteor\n    // lint', and the runner commands (run/test-packages/debug) when --no-lint\n    // is not passed.\n    self.lintAppAndLocalPackages = options.lintAppAndLocalPackages;\n\n    // If set, we run the linter on just one local package, with this\n    // source root. Set by 'meteor lint' in a package, and 'meteor publish'.\n    self._lintPackageWithSourceRoot = options.lintPackageWithSourceRoot;\n\n    // Initialized by readProjectMetadata.\n    self.releaseFile = null;\n    self.projectConstraintsFile = null;\n    self.packageMapFile = null;\n    self.platformList = null;\n    self.cordovaPluginsFile = null;\n    self.appIdentifier = null;\n    self.finishedUpgraders = null;\n\n    // Initialized by initializeCatalog.\n    self.projectCatalog = null;\n    self.localCatalog = null;\n    // Once the catalog is read and the names of the \"explicitly\n    // added\" packages are determined, they will be listed here.\n    // (See explicitlyAddedLocalPackageDirs.)\n    // \"Explicitly added\" packages are typically present in non-app\n    // projects, like the one created by `meteor publish`.  This list\n    // is used to avoid pinning such packages to their previous\n    // versions when we run the version solver, which prevents an\n    // error telling you to pass `--allow-incompatible-update` when\n    // you publish your package after bumping the major version.\n    self.explicitlyAddedPackageNames = null;\n\n    // Initialized by _resolveConstraints.\n    self.packageMap = null;\n    self.packageMapDelta = null;\n\n    if (resetOptions.softRefreshIsopacks && self.isopackCache) {\n      // Make sure we only hold on to one old isopack cache, not a linked list\n      // of all of them.\n      self.isopackCache.forgetPreviousIsopackCache();\n      self._previousIsopackCache = self.isopackCache;\n    } else {\n      self._previousIsopackCache = null;\n    }\n    // Initialized by _buildLocalPackages.\n    self.isopackCache = null;\n\n    self._completedStage = STAGE.INITIAL;\n\n    // The resolverResultCache is used by the constraint solver; to\n    // us it's just an opaque object.  If we pass it into repeated\n    // calls to the constraint solver, the constraint solver can be\n    // more efficient by caching or memoizing its work.  We choose not\n    // to reset this when reset() is called more than once.\n    self._resolverResultCache = (self._resolverResultCache || {});\n  },\n\n  readProjectMetadata: function () {\n    // don't generate a profiling report for this stage (Profile.run),\n    // because all we do here is read a handful of files.\n    this._completeStagesThrough(STAGE.READ_PROJECT_METADATA);\n  },\n  initializeCatalog: function () {\n    Profile.run('ProjectContext initializeCatalog', () => {\n      this._completeStagesThrough(STAGE.INITIALIZE_CATALOG);\n    });\n  },\n  resolveConstraints: function () {\n    Profile.run('ProjectContext resolveConstraints', () => {\n      this._completeStagesThrough(STAGE.RESOLVE_CONSTRAINTS);\n    });\n  },\n  downloadMissingPackages: function () {\n    Profile.run('ProjectContext downloadMissingPackages', () => {\n      this._completeStagesThrough(STAGE.DOWNLOAD_MISSING_PACKAGES);\n    });\n  },\n  buildLocalPackages: function () {\n    Profile.run('ProjectContext buildLocalPackages', () => {\n      this._completeStagesThrough(STAGE.BUILD_LOCAL_PACKAGES);\n    });\n  },\n  saveChangedMetadata: function () {\n    Profile.run('ProjectContext saveChangedMetadata', () => {\n      this._completeStagesThrough(STAGE.SAVE_CHANGED_METADATA);\n    });\n  },\n  prepareProjectForBuild: function () {\n    // This is the same as saveChangedMetadata, but if we insert stages after\n    // that one it will continue to mean \"fully finished\".\n    Profile.run('ProjectContext prepareProjectForBuild', () => {\n      this._completeStagesThrough(STAGE.SAVE_CHANGED_METADATA);\n    });\n  },\n\n  _completeStagesThrough: function (targetStage) {\n    var self = this;\n    buildmessage.assertInCapture();\n\n    buildmessage.enterJob('preparing project', function () {\n      while (self._completedStage !== targetStage) {\n        // This error gets thrown if you request to go to a stage that's earlier\n        // than where you started. Note that the error will be mildly confusing\n        // because the key of STAGE does not match the value.\n        if (self.completedStage === STAGE.SAVE_CHANGED_METADATA)\n          throw Error(\"can't find requested stage \" + targetStage);\n\n        // The actual value of STAGE.FOO is the name of the method that takes\n        // you to the next step after FOO.\n        self[self._completedStage]();\n        if (buildmessage.jobHasMessages())\n          return;\n      }\n    });\n  },\n\n  getProjectLocalDirectory: function (subdirectory) {\n    var self = this;\n    return files.pathJoin(self.projectLocalDir, subdirectory);\n  },\n\n  getMeteorShellDirectory: function(projectDir) {\n    return this.getProjectLocalDirectory(\"shell\");\n  },\n\n  // You can call this manually (that is, the public version without\n  // an `_`) if you want to do some work before resolving constraints,\n  // or you can let prepareProjectForBuild do it for you.\n  //\n  // This should be pretty fast --- for example, we shouldn't worry about\n  // needing to wait for it to be done before we open the runner proxy.\n  _readProjectMetadata: Profile('_readProjectMetadata', function () {\n    var self = this;\n    buildmessage.assertInCapture();\n\n    buildmessage.enterJob('reading project metadata', function () {\n      // Ensure this is actually a project directory.\n      self._ensureProjectDir();\n      if (buildmessage.jobHasMessages())\n        return;\n\n      // Read .meteor/release.\n      self.releaseFile = new exports.ReleaseFile({\n        projectDir: self.projectDir\n      });\n      if (buildmessage.jobHasMessages())\n        return;\n\n      // Read .meteor/packages.\n      self.projectConstraintsFile = new exports.ProjectConstraintsFile({\n        projectDir: self.projectDir\n      });\n      if (buildmessage.jobHasMessages())\n        return;\n\n      // Read .meteor/versions.\n      self.packageMapFile = new exports.PackageMapFile({\n        filename: self._packageMapFilename\n      });\n      if (buildmessage.jobHasMessages())\n        return;\n\n      // Read .meteor/cordova-plugins.\n      self.cordovaPluginsFile = new exports.CordovaPluginsFile({\n        projectDir: self.projectDir\n      });\n      if (buildmessage.jobHasMessages())\n        return;\n\n      // Read .meteor/platforms, creating it if necessary.\n      self.platformList = new exports.PlatformList({\n        projectDir: self.projectDir\n      });\n      if (buildmessage.jobHasMessages())\n        return;\n\n      // Read .meteor/.id, creating it if necessary.\n      self._ensureAppIdentifier();\n      if (buildmessage.jobHasMessages())\n        return;\n\n      // Set up an object that knows how to read and write\n      // .meteor/.finished-upgraders.\n      self.finishedUpgraders = new exports.FinishedUpgraders({\n        projectDir: self.projectDir\n      });\n      if (buildmessage.jobHasMessages())\n        return;\n    });\n\n    self._completedStage = STAGE.READ_PROJECT_METADATA;\n  }),\n\n  _ensureProjectDir: function () {\n    var self = this;\n    files.mkdir_p(files.pathJoin(self.projectDir, '.meteor'));\n\n    // This file existing is what makes a project directory a project directory,\n    // so let's make sure it exists!\n    var constraintFilePath = files.pathJoin(self.projectDir, '.meteor', 'packages');\n    if (! files.exists(constraintFilePath)) {\n      files.writeFileAtomically(constraintFilePath, '');\n    }\n\n    // Let's also make sure we have a minimal gitignore.\n    var gitignorePath = files.pathJoin(self.projectDir, '.meteor', '.gitignore');\n    if (! files.exists(gitignorePath)) {\n      files.writeFileAtomically(gitignorePath, 'local\\n');\n    }\n  },\n\n  // This is a WatchSet that ends up being the WatchSet for the app's\n  // initFromAppDir PackageSource. Changes to this will cause the whole app to\n  // be rebuilt (client and server).\n  getProjectWatchSet: function () {\n    // We don't cache a projectWatchSet on this object, since some of the\n    // metadata files can be written by us (eg .meteor/versions\n    // post-constraint-solve).\n    var self = this;\n    var watchSet = new watch.WatchSet;\n    _.each(\n      [self.releaseFile, self.projectConstraintsFile, self.packageMapFile,\n       self.platformList, self.cordovaPluginsFile],\n      function (metadataFile) {\n        metadataFile && watchSet.merge(metadataFile.watchSet);\n      });\n\n    if (self.localCatalog) {\n      watchSet.merge(self.localCatalog.packageLocationWatchSet);\n    }\n\n    return watchSet;\n  },\n\n  // This WatchSet encompasses everything that users can change to restart an\n  // app. We only watch this for failed bundles; for successful bundles, we have\n  // more precise server-specific and client-specific WatchSets that add up to\n  // this one.\n  getProjectAndLocalPackagesWatchSet: function () {\n    var self = this;\n    var watchSet = self.getProjectWatchSet();\n\n    // Include the loaded local packages (ie, the non-metadata files) but only\n    // if we've actually gotten to the buildLocalPackages step.\n    if (self.isopackCache) {\n      watchSet.merge(self.isopackCache.allLoadedLocalPackagesWatchSet);\n    }\n    return watchSet;\n  },\n\n  getLintingMessagesForLocalPackages: function () {\n    var self = this;\n    return self.isopackCache.getLintingMessagesForLocalPackages();\n  },\n\n  _ensureAppIdentifier: function () {\n    var self = this;\n    var identifierFile = files.pathJoin(self.projectDir, '.meteor', '.id');\n\n    // Find the first non-empty line, ignoring comments. We intentionally don't\n    // put this in a WatchSet, since changing this doesn't affect the built app\n    // much (and there's no real reason to update it anyway).\n    var lines = files.getLinesOrEmpty(identifierFile);\n    var appId = _.find(_.map(lines, files.trimSpaceAndComments), _.identity);\n\n    // If the file doesn't exist or has no non-empty lines, regenerate the\n    // token.\n    if (!appId) {\n      appId = utils.randomToken() + utils.randomToken() + utils.randomToken();\n\n      var comment = (\n\"# This file contains a token that is unique to your project.\\n\" +\n\"# Check it into your repository along with the rest of this directory.\\n\" +\n\"# It can be used for purposes such as:\\n\" +\n\"#   - ensuring you don't accidentally deploy one app on top of another\\n\" +\n\"#   - providing package authors with aggregated statistics\\n\" +\n\"\\n\");\n      files.writeFileAtomically(identifierFile, comment + appId + '\\n');\n    }\n\n    self.appIdentifier = appId;\n  },\n\n  _resolveConstraints: Profile('_resolveConstraints', function () {\n    var self = this;\n    buildmessage.assertInJob();\n\n    var depsAndConstraints = self._getRootDepsAndConstraints();\n    // If this is in the runner and we have reset this ProjectContext for a\n    // rebuild, use the versions we calculated last time in this process (which\n    // may not have been written to disk if our release doesn't match the\n    // project's release on disk)... unless the actual file on disk has changed\n    // out from under us. Otherwise use the versions from .meteor/versions.\n    var cachedVersions;\n    if (self._cachedVersionsBeforeReset &&\n        self._oldPackageMapFileHash === self.packageMapFile.fileHash) {\n      // The file on disk hasn't change; reuse last time's results.\n      cachedVersions = self._cachedVersionsBeforeReset;\n    } else {\n      // We don't have a last time, or the file has changed; use\n      // .meteor/versions.\n      cachedVersions = self.packageMapFile.getCachedVersions();\n    }\n\n    var anticipatedPrereleases = self._getAnticipatedPrereleases(\n      depsAndConstraints.constraints, cachedVersions);\n\n    if (self.explicitlyAddedPackageNames.length) {\n      cachedVersions = _.clone(cachedVersions);\n      _.each(self.explicitlyAddedPackageNames, function (p) {\n        delete cachedVersions[p];\n      });\n    }\n\n    var resolverRunCount = 0;\n\n    // Nothing before this point looked in the official or project catalog!\n    // However, the resolver does, so it gets run in the retry context.\n    catalog.runAndRetryWithRefreshIfHelpful(function (canRetry) {\n      buildmessage.enterJob(\"selecting package versions\", function () {\n        var resolver = self._buildResolver();\n\n        var resolveOptions = {\n          previousSolution: cachedVersions,\n          anticipatedPrereleases: anticipatedPrereleases,\n          allowIncompatibleUpdate: self._allowIncompatibleUpdate,\n          // Not finding an exact match for a previous version in the catalog\n          // is considered an error if we haven't refreshed yet, and will\n          // trigger a refresh and another attempt.  That way, if a previous\n          // version exists, you'll get it, even if we don't have a record\n          // of it yet.  It's not actually fatal, though, for previousSolution\n          // to refer to package versions that we don't have access to or don't\n          // exist.  They'll end up getting changed or removed if possible.\n          missingPreviousVersionIsError: canRetry,\n          supportedIsobuildFeaturePackages: KNOWN_ISOBUILD_FEATURE_PACKAGES,\n        };\n        if (self._upgradePackageNames) {\n          resolveOptions.upgrade = self._upgradePackageNames;\n        }\n        if (self._upgradeIndirectDepPatchVersions) {\n          resolveOptions.upgradeIndirectDepPatchVersions = true;\n        }\n\n        resolverRunCount++;\n\n        var solution;\n        try {\n          Profile.time(\n            \"Select Package Versions\" +\n              (resolverRunCount > 1 ? (\" (Try \" + resolverRunCount + \")\") : \"\"),\n            function () {\n              solution = resolver.resolve(\n                depsAndConstraints.deps, depsAndConstraints.constraints,\n                resolveOptions);\n            });\n        } catch (e) {\n          if (!e.constraintSolverError && !e.versionParserError)\n            throw e;\n          // If the contraint solver gave us an error, refreshing\n          // might help to get new packages (see the comment on\n          // missingPreviousVersionIsError above).  If it's a\n          // package-version-parser error, print a nice message,\n          // but don't bother refreshing.\n          buildmessage.error(\n            e.message,\n            { tags: { refreshCouldHelp: !!e.constraintSolverError }});\n        }\n\n        if (buildmessage.jobHasMessages())\n          return;\n\n        self.packageMap = new packageMapModule.PackageMap(solution.answer, {\n          localCatalog: self.localCatalog\n        });\n\n        self.packageMapDelta = new packageMapModule.PackageMapDelta({\n          cachedVersions: cachedVersions,\n          packageMap: self.packageMap,\n          usedRCs: solution.usedRCs,\n          neededToUseUnanticipatedPrereleases:\n          solution.neededToUseUnanticipatedPrereleases,\n          anticipatedPrereleases: anticipatedPrereleases\n        });\n\n        self._completedStage = STAGE.RESOLVE_CONSTRAINTS;\n      });\n    });\n  }),\n\n  // When running test-packages for an app with local packages, this\n  // method will return the original app dir, as opposed to the temporary\n  // testRunnerAppDir created for the tests.\n  getOriginalAppDirForTestPackages() {\n    const appDir = this._projectDirForLocalPackages;\n    if (_.isString(appDir) && appDir !== this.projectDir) {\n      return appDir;\n    }\n  },\n\n  _localPackageSearchDirs: function () {\n    var self = this;\n    var searchDirs = [files.pathJoin(self._projectDirForLocalPackages, 'packages')];\n\n    if (! self._ignorePackageDirsEnvVar && process.env.PACKAGE_DIRS) {\n      // User can provide additional package directories to search in\n      // PACKAGE_DIRS (colon-separated).\n      _.each(process.env.PACKAGE_DIRS.split(':'), function (p) {\n        searchDirs.push(files.pathResolve(p));\n      });\n    }\n\n    if (! self._ignoreCheckoutPackages && files.inCheckout()) {\n      // Running from a checkout, so use the Meteor core packages from the\n      // checkout.\n      searchDirs.push(files.pathJoin(files.getCurrentToolsDir(), 'packages'));\n    }\n    return searchDirs;\n  },\n\n  // Returns a layered catalog with information about the packages that can be\n  // used in this project. Processes the package.js file from all local packages\n  // but does not compile the packages.\n  //\n  // Must be run in a buildmessage context. On build error, returns null.\n  _initializeCatalog: Profile('_initializeCatalog', function () {\n    var self = this;\n    buildmessage.assertInJob();\n\n    catalog.runAndRetryWithRefreshIfHelpful(function () {\n      buildmessage.enterJob(\n        \"scanning local packages\",\n        function () {\n          self.localCatalog = new catalogLocal.LocalCatalog;\n          self.projectCatalog = new catalog.LayeredCatalog(\n            self.localCatalog, self._officialCatalog);\n\n          var searchDirs = self._localPackageSearchDirs();\n          self.localCatalog.initialize({\n            localPackageSearchDirs: searchDirs,\n            explicitlyAddedLocalPackageDirs: self._explicitlyAddedLocalPackageDirs\n          });\n\n          if (buildmessage.jobHasMessages()) {\n            // Even if this fails, we want to leave self.localCatalog assigned,\n            // so that it gets counted included in the projectWatchSet.\n            return;\n          }\n\n          self.explicitlyAddedPackageNames = [];\n          _.each(self._explicitlyAddedLocalPackageDirs, function (dir) {\n            var localVersionRecord =\n                  self.localCatalog.getVersionBySourceRoot(dir);\n            if (localVersionRecord) {\n              self.explicitlyAddedPackageNames.push(localVersionRecord.packageName);\n            }\n          });\n\n          self._completedStage = STAGE.INITIALIZE_CATALOG;\n        }\n      );\n    });\n  }),\n\n  _getRootDepsAndConstraints: function () {\n    var self = this;\n\n    var depsAndConstraints = {deps: [], constraints: []};\n\n    self._addAppConstraints(depsAndConstraints);\n    self._addLocalPackageConstraints(depsAndConstraints);\n    self._addReleaseConstraints(depsAndConstraints);\n    return depsAndConstraints;\n  },\n\n  _addAppConstraints: function (depsAndConstraints) {\n    var self = this;\n\n    self.projectConstraintsFile.eachConstraint(function (constraint) {\n      // Add a dependency (\"this package must be used\") and a constraint\n      // (\"... at this version (maybe 'any reasonable')\").\n      depsAndConstraints.deps.push(constraint.package);\n      depsAndConstraints.constraints.push(constraint);\n    });\n  },\n\n  _addLocalPackageConstraints: function (depsAndConstraints) {\n    var self = this;\n    _.each(self.localCatalog.getAllPackageNames(), function (packageName) {\n      var versionRecord = self.localCatalog.getLatestVersion(packageName);\n      var constraint = utils.parsePackageConstraint(\n        packageName + \"@=\" + versionRecord.version);\n      // Add a constraint (\"this is the only version available\") but no\n      // dependency (we don't automatically use all local packages!)\n      depsAndConstraints.constraints.push(constraint);\n    });\n  },\n\n  _addReleaseConstraints: function (depsAndConstraints) {\n    var self = this;\n    if (! self._releaseForConstraints)\n      return;\n    _.each(self._releaseForConstraints.packages, function (version, packageName) {\n      var constraint = utils.parsePackageConstraint(\n        packageName + \"@=\" + version);\n      // Add a constraint (\"this is the only version available\") but no\n      // dependency (we don't automatically use all local packages!)\n      depsAndConstraints.constraints.push(constraint);\n    });\n  },\n\n  _getAnticipatedPrereleases: function (rootConstraints, cachedVersions) {\n    var self = this;\n\n    var anticipatedPrereleases = {};\n    var add = function (packageName, version) {\n      if (! /-/.test(version)) {\n        return;\n      }\n      if (! _.has(anticipatedPrereleases, packageName)) {\n        anticipatedPrereleases[packageName] = {};\n      }\n      anticipatedPrereleases[packageName][version] = true;\n    };\n\n    // Pre-release versions that are root constraints (in .meteor/packages, in\n    // the release, or the version of a local package) are anticipated.\n    _.each(rootConstraints, function (constraintObject) {\n      _.each(constraintObject.versionConstraint.alternatives, function (alt) {\n        var version = alt.versionString;\n        version && add(constraintObject.package, version);\n      });\n    });\n\n    // Pre-release versions we decided to use in the past are anticipated.\n    _.each(cachedVersions, function (version, packageName) {\n      add(packageName, version);\n    });\n\n    return anticipatedPrereleases;\n  },\n\n  _buildResolver: function () {\n    var self = this;\n\n    var constraintSolverPackage =\n          isopackets.load('constraint-solver')['constraint-solver'];\n    var resolver =\n          new constraintSolverPackage.ConstraintSolver.PackagesResolver(\n            self.projectCatalog, {\n              nudge: function () {\n                Console.nudge(true);\n              },\n              Profile: Profile,\n              resultCache: self._resolverResultCache\n            });\n    return resolver;\n  },\n\n  _downloadMissingPackages: Profile('_downloadMissingPackages', function () {\n    var self = this;\n    buildmessage.assertInJob();\n    if (!self.packageMap)\n      throw Error(\"which packages to download?\");\n\n    catalog.runAndRetryWithRefreshIfHelpful(function () {\n      buildmessage.enterJob(\"downloading missing packages\", function () {\n        self.tropohouse.downloadPackagesMissingFromMap(self.packageMap, {\n          serverArchitectures: self._serverArchitectures\n        });\n        if (buildmessage.jobHasMessages())\n          return;\n        self._completedStage = STAGE.DOWNLOAD_MISSING_PACKAGES;\n      });\n    });\n  }),\n\n  _buildLocalPackages: Profile('_buildLocalPackages', function () {\n    var self = this;\n    buildmessage.assertInCapture();\n\n    self.isopackCache = new isopackCacheModule.IsopackCache({\n      packageMap: self.packageMap,\n      includeCordovaUnibuild: (self._forceIncludeCordovaUnibuild\n                               || self.platformList.usesCordova()),\n      cacheDir: self.getProjectLocalDirectory('isopacks'),\n      pluginCacheDirRoot: self.getProjectLocalDirectory('plugin-cache'),\n      tropohouse: self.tropohouse,\n      previousIsopackCache: self._previousIsopackCache,\n      lintLocalPackages: self.lintAppAndLocalPackages,\n      lintPackageWithSourceRoot: self._lintPackageWithSourceRoot\n    });\n\n    if (self._forceRebuildPackages) {\n      self.isopackCache.wipeCachedPackages(\n        self._forceRebuildPackages === true\n          ? null : self._forceRebuildPackages);\n    }\n\n    buildmessage.enterJob('building local packages', function () {\n      self.isopackCache.buildLocalPackages();\n    });\n    self._completedStage = STAGE.BUILD_LOCAL_PACKAGES;\n  }),\n\n  _saveChangedMetadata: Profile('_saveChangedMetadata', function () {\n    var self = this;\n\n    // Save any changes to .meteor/packages.\n    if (! self._neverWriteProjectConstraintsFile)\n      self.projectConstraintsFile.writeIfModified();\n\n    // Write .meteor/versions if the command always wants to (create/update),\n    // or if the release of the app matches the release of the process.\n    if (! self._neverWritePackageMap &&\n        (self._alwaysWritePackageMap ||\n         (release.current.isCheckout() && self.releaseFile.isCheckout()) ||\n         (! release.current.isCheckout() &&\n          release.current.name === self.releaseFile.fullReleaseName))) {\n\n      self.packageMapFile.write(self.packageMap);\n    }\n\n    self._completedStage = STAGE.SAVE_CHANGED_METADATA;\n  })\n});\n\n\n// Represents .meteor/packages.\nexports.ProjectConstraintsFile = function (options) {\n  var self = this;\n  buildmessage.assertInCapture();\n\n  self.filename = files.pathJoin(options.projectDir, '.meteor', 'packages');\n  self.watchSet = null;\n\n  // Have we modified the in-memory representation since reading from disk?\n  self._modified = null;\n  // List of each line in the file; object with keys:\n  // - leadingSpace (string of spaces before the constraint)\n  // - constraint (as returned by utils.parsePackageConstraint)\n  // - trailingSpaceAndComment (string of spaces/comments after the constraint)\n  // This allows us to rewrite the file preserving comments.\n  self._constraintLines = null;\n  // Maps from package name to entry in _constraintLines.\n  self._constraintMap = null;\n  self._readFile();\n};\n\n_.extend(exports.ProjectConstraintsFile.prototype, {\n  _readFile: function () {\n    var self = this;\n    buildmessage.assertInCapture();\n\n    self.watchSet = new watch.WatchSet;\n    self._modified = false;\n    self._constraintMap = {};\n    self._constraintLines = [];\n    var contents = watch.readAndWatchFile(self.watchSet, self.filename);\n\n    // No .meteor/packages? This isn't a very good project directory. In fact,\n    // that's the definition of a project directory! (And that should have been\n    // fixed by _ensureProjectDir!)\n    if (contents === null)\n      throw Error(\"packages file missing: \" + self.filename);\n\n    var lines = files.splitBufferToLines(contents);\n    // Don't keep a record for the space at the end of the file.\n    if (lines.length && _.last(lines) === '')\n      lines.pop();\n\n    _.each(lines, function (line) {\n      var lineRecord =\n            { leadingSpace: '', constraint: null, trailingSpaceAndComment: '' };\n      self._constraintLines.push(lineRecord);\n      // Strip comment.\n      var match = line.match(/^([^#]*)(#.*)$/);\n      if (match) {\n        line = match[1];\n        lineRecord.trailingSpaceAndComment = match[2];\n      }\n      // Strip trailing space.\n      match = line.match(/^((?:.*\\S)?)(\\s*)$/);\n      line = match[1];\n      lineRecord.trailingSpaceAndComment =\n        match[2] + lineRecord.trailingSpaceAndComment;\n      // Strip leading space.\n      match = line.match(/^(\\s*)((?:\\S.*)?)$/);\n      lineRecord.leadingSpace = match[1];\n      line = match[2];\n\n      // No constraint? Leave lineRecord.constraint null and continue.\n      if (line === '')\n        return;\n      lineRecord.constraint = utils.parsePackageConstraint(line, {\n        useBuildmessage: true,\n        buildmessageFile: self.filename\n      });\n      if (! lineRecord.constraint)\n        return;  // recover by ignoring\n\n      if (_.has(self._constraintMap, lineRecord.constraint.package)) {\n        buildmessage.error(\n          \"Package name appears twice: \" + lineRecord.constraint.package, {\n            // XXX should this be relative?\n            file: self.filename\n          });\n        return;  // recover by ignoring\n      }\n      self._constraintMap[lineRecord.constraint.package] = lineRecord;\n    });\n  },\n\n  writeIfModified: function () {\n    var self = this;\n    self._modified && self._write();\n  },\n\n  _write: function () {\n    var self = this;\n    var lines = _.map(self._constraintLines, function (lineRecord) {\n      var lineParts = [lineRecord.leadingSpace];\n      if (lineRecord.constraint) {\n        lineParts.push(lineRecord.constraint.package);\n        if (lineRecord.constraint.constraintString) {\n          lineParts.push('@', lineRecord.constraint.constraintString);\n        }\n      }\n      lineParts.push(lineRecord.trailingSpaceAndComment, '\\n');\n      return lineParts.join('');\n    });\n    files.writeFileAtomically(self.filename, lines.join(''));\n    var messages = buildmessage.capture(\n      { title: 're-reading .meteor/packages' },\n      function () {\n        self._readFile();\n      });\n    // We shouldn't choke on something we just wrote!\n    if (messages.hasMessages())\n      throw Error(\"wrote bad .meteor/packages: \" + messages.formatMessages());\n  },\n\n  // Iterates over all constraints, in the format returned by\n  // utils.parsePackageConstraint.\n  eachConstraint: function (iterator) {\n    var self = this;\n    _.each(self._constraintLines, function (lineRecord) {\n      if (lineRecord.constraint)\n        iterator(lineRecord.constraint);\n    });\n  },\n\n  // Returns the constraint in the format returned by\n  // utils.parsePackageConstraint, or null.\n  getConstraint: function (name) {\n    var self = this;\n    if (_.has(self._constraintMap, name))\n      return self._constraintMap[name].constraint;\n    return null;\n  },\n\n  // Adds constraints, an array of objects as returned from\n  // utils.parsePackageConstraint.\n  // Does not write to disk immediately; changes are written to disk by\n  // writeIfModified() which is called in the _saveChangedMetadata step\n  // of project preparation.\n  addConstraints: function (constraintsToAdd) {\n    var self = this;\n    _.each(constraintsToAdd, function (constraintToAdd) {\n      if (! constraintToAdd.package) {\n        throw new Error(\"Expected PackageConstraint: \" + constraintToAdd);\n      }\n\n      var lineRecord;\n      if (! _.has(self._constraintMap, constraintToAdd.package)) {\n        lineRecord = {\n          leadingSpace: '',\n          constraint: constraintToAdd,\n          trailingSpaceAndComment: ''\n        };\n        self._constraintLines.push(lineRecord);\n        self._constraintMap[constraintToAdd.package] = lineRecord;\n        self._modified = true;\n        return;\n      }\n      lineRecord = self._constraintMap[constraintToAdd.package];\n      if (_.isEqual(constraintToAdd, lineRecord.constraint))\n        return;  // nothing changed\n      lineRecord.constraint = constraintToAdd;\n      self._modified = true;\n    });\n  },\n\n  // Like addConstraints, but takes an array of package name strings\n  // to add with no version constraint\n  addPackages: function (packagesToAdd) {\n    this.addConstraints(_.map(packagesToAdd, function (packageName) {\n      // make sure packageName is valid (and doesn't, for example,\n      // contain an '@' sign)\n      utils.validatePackageName(packageName);\n      return utils.parsePackageConstraint(packageName);\n    }));\n  },\n\n  // The packages in packagesToRemove are expected to actually be in the file;\n  // if you want to provide different output for packages in the file vs not,\n  // you should have already done that.\n  // Does not write to disk immediately; changes are written to disk by\n  // writeIfModified() which is called in the _saveChangedMetadata step\n  // of project preparation.\n  removePackages: function (packagesToRemove) {\n    var self = this;\n    self._constraintLines = _.filter(\n      self._constraintLines, function (lineRecord) {\n        return ! (lineRecord.constraint &&\n                  _.contains(packagesToRemove, lineRecord.constraint.package));\n      });\n    _.each(packagesToRemove, function (p) {\n      delete self._constraintMap[p];\n    });\n    self._modified = true;\n  },\n\n  // Removes all constraints. Generally this should only be used in situations\n  // where the project is not a real user app: while you can use\n  // removeAllPackages followed by addConstraints to fully replace the\n  // constraints in a project, this will also lose all user comments and\n  // (cosmetic) ordering from the file.\n  removeAllPackages: function () {\n    var self = this;\n    self._constraintLines = [];\n    self._constraintMap = {};\n    self._modified = true;\n  }\n});\n\n\n\n// Represents .meteor/versions.\nexports.PackageMapFile = function (options) {\n  var self = this;\n  buildmessage.assertInCapture();\n\n  self.filename = options.filename;\n  self.watchSet = new watch.WatchSet;\n  self.fileHash = null;\n  self._versions = {};\n\n  self._readFile();\n};\n\n_.extend(exports.PackageMapFile.prototype, {\n  _readFile: function () {\n    var self = this;\n\n    var fileInfo = watch.readAndWatchFileWithHash(self.watchSet, self.filename);\n    var contents = fileInfo.contents;\n    self.fileHash = fileInfo.hash;\n    // No .meteor/versions? That's OK, you just get to start your calculation\n    // from scratch.\n    if (contents === null)\n      return;\n\n    buildmessage.assertInCapture();\n    var lines = files.splitBufferToLines(contents);\n    _.each(lines, function (line) {\n      // We don't allow comments here, since it's cruel to allow comments in a\n      // file when you're going to overwrite them anyway.\n      line = files.trimSpace(line);\n      if (line === '')\n        return;\n      var packageVersion = utils.parsePackageAndVersion(line, {\n        useBuildmessage: true,\n        buildmessageFile: self.filename\n      });\n      if (!packageVersion)\n        return;  // recover by ignoring\n\n      // If a package appears multiple times in .meteor/versions, we just ignore\n      // the second one. This file is more meteor-controlled than\n      // .meteor/packages and people shouldn't be surprised to see it\n      // automatically fixed.\n      if (_.has(self._versions, packageVersion.package))\n        return;\n\n      self._versions[packageVersion.package] = packageVersion.version;\n    });\n  },\n\n  // Note that this is really specific to wanting to know what versions are in\n  // the .meteor/versions file on disk, which is a slightly different question\n  // from \"so, what versions should I be building with?\"  Usually you want the\n  // PackageMap produced by resolving constraints instead! Returns a map from\n  // package name to version.\n  getCachedVersions: function () {\n    var self = this;\n    return _.clone(self._versions);\n  },\n\n  write: function (packageMap) {\n    var self = this;\n    var newVersions = packageMap.toVersionMap();\n\n    // Only write the file if some version changed. (We don't need to do no-op\n    // writes, even if they fix sorting in the file.)\n    if (_.isEqual(self._versions, newVersions))\n      return;\n\n    self._versions = newVersions;\n    var packageNames = _.keys(self._versions);\n    packageNames.sort();\n    var lines = [];\n    _.each(packageNames, function (packageName) {\n      lines.push(packageName + \"@\" + self._versions[packageName] + \"\\n\");\n    });\n    var fileContents = new Buffer(lines.join(''));\n    files.writeFileAtomically(self.filename, fileContents);\n\n    // Replace our watchSet with one for the new contents of the file.\n    var hash = watch.sha1(fileContents);\n    self.watchSet = new watch.WatchSet;\n    self.watchSet.addFile(self.filename, hash);\n  }\n});\n\n\n\n// Represents .meteor/platforms. We take no effort to maintain comments or\n// spacing here.\nexports.PlatformList = function (options) {\n  var self = this;\n\n  self.filename = files.pathJoin(options.projectDir, '.meteor', 'platforms');\n  self.watchSet = null;\n  self._platforms = null;\n\n  self._readFile();\n};\n\n// These platforms are always present and can be neither added or removed\nexports.PlatformList.DEFAULT_PLATFORMS = ['browser', 'server'];\n\n_.extend(exports.PlatformList.prototype, {\n  _readFile: function () {\n    var self = this;\n\n    // Reset the WatchSet.\n    self.watchSet = new watch.WatchSet;\n    var contents = watch.readAndWatchFile(self.watchSet, self.filename);\n\n    var platforms = contents ? files.splitBufferToLines(contents) : [];\n    // We don't allow comments here, since it's cruel to allow comments in a\n    // file when you're going to overwrite them anyway.\n    platforms = _.uniq(_.compact(_.map(platforms, files.trimSpace)));\n    platforms.sort();\n\n    // Missing some of the default platforms (or the whole file)? Add them and\n    // try again.\n    if (_.difference(exports.PlatformList.DEFAULT_PLATFORMS,\n                     platforms).length) {\n      // Write the platforms to disk (automatically adding DEFAULT_PLATFORMS and\n      // sorting), which automatically calls this function recursively to\n      // re-reads them.\n      self.write(platforms);\n      return;\n    }\n\n    self._platforms = platforms;\n  },\n\n  // Replaces the current platform file with the given list and resets this\n  // object (and its WatchSet) to track the new value.\n  write: function (platforms) {\n    var self = this;\n    self._platforms = null;\n    platforms = _.uniq(\n      platforms.concat(exports.PlatformList.DEFAULT_PLATFORMS));\n    platforms.sort();\n    files.writeFileAtomically(self.filename, platforms.join('\\n') + '\\n');\n    self._readFile();\n  },\n\n  getPlatforms: function () {\n    var self = this;\n    return _.clone(self._platforms);\n  },\n\n  getCordovaPlatforms: function () {\n    var self = this;\n    return _.difference(self._platforms,\n                        exports.PlatformList.DEFAULT_PLATFORMS);\n  },\n\n  usesCordova: function () {\n    var self = this;\n    return ! _.isEmpty(self.getCordovaPlatforms());\n  },\n\n  getWebArchs: function () {\n    var self = this;\n    var archs = [ \"web.browser\" ];\n    if (self.usesCordova()) {\n      archs.push(\"web.cordova\");\n    }\n    return archs;\n  }\n});\n\n\n// Represents .meteor/cordova-plugins.\nexports.CordovaPluginsFile = function (options) {\n  var self = this;\n  buildmessage.assertInCapture();\n\n  self.filename = files.pathJoin(options.projectDir, '.meteor', 'cordova-plugins');\n  self.watchSet = null;\n  // Map from plugin name to version.\n  self._plugins = null;\n\n  self._readFile();\n};\n\n_.extend(exports.CordovaPluginsFile.prototype, {\n  _readFile: function () {\n    var self = this;\n    buildmessage.assertInCapture();\n\n    self.watchSet = new watch.WatchSet;\n    self._plugins = {};\n    var contents = watch.readAndWatchFile(self.watchSet, self.filename);\n    // No file?  No plugins.\n    if (contents === null)\n      return;\n\n    var lines = files.splitBufferToLines(contents);\n    _.each(lines, function (line) {\n      line = files.trimSpace(line);\n      if (line === '')\n        return;\n\n      // We just do a standard split here, not utils.parsePackageConstraint,\n      // since cordova plugins don't necessary obey the same naming conventions\n      // as Meteor packages.\n      var parts = line.split('@');\n      if (parts.length !== 2) {\n        buildmessage.error(\"Cordova plugin must specify version: \" + line, {\n          // XXX should this be relative?\n          file: self.filename\n        });\n        return;  // recover by ignoring\n      }\n      if (_.has(self._plugins, parts[0])) {\n        buildmessage.error(\"Plugin name appears twice: \" + parts[0], {\n          // XXX should this be relative?\n          file: self.filename\n        });\n        return;  // recover by ignoring\n      }\n      self._plugins[parts[0]] = parts[1];\n    });\n  },\n\n  getPluginVersions: function () {\n    var self = this;\n    return _.clone(self._plugins);\n  },\n\n  write: function (plugins) {\n    var self = this;\n    var pluginNames = _.keys(plugins);\n    pluginNames.sort();\n    var lines = _.map(pluginNames, function (pluginName) {\n      return pluginName + '@' + plugins[pluginName] + '\\n';\n    });\n    files.writeFileAtomically(self.filename, lines.join(''));\n    var messages = buildmessage.capture(\n      { title: 're-reading .meteor/cordova-plugins' },\n      function () {\n        self._readFile();\n      });\n    // We shouldn't choke on something we just wrote!\n    if (messages.hasMessages())\n      throw Error(\"wrote bad .meteor/packages: \" + messages.formatMessages());\n  }\n});\n\n\n\n// Represents .meteor/release.\nexports.ReleaseFile = function (options) {\n  var self = this;\n\n  self.filename = files.pathJoin(options.projectDir, '.meteor', 'release');\n  self.watchSet = null;\n  // The release name actually written in the file.  Null if no fill.  Empty if\n  // the file is empty.\n  self.unnormalizedReleaseName = null;\n  // The full release name (with METEOR@ if it's missing in\n  // unnormalizedReleaseName).\n  self.fullReleaseName = null;\n  // FOO@bar unless FOO === \"METEOR\" in which case \"Meteor bar\".\n  self.displayReleaseName = null;\n  // Just the track.\n  self.releaseTrack = null;\n  self.releaseVersion = null;\n  self._readFile();\n};\n\n_.extend(exports.ReleaseFile.prototype, {\n  fileMissing: function () {\n    var self = this;\n    return self.unnormalizedReleaseName === null;\n  },\n  noReleaseSpecified: function () {\n    var self = this;\n    return self.unnormalizedReleaseName === '';\n  },\n  isCheckout: function () {\n    var self = this;\n    return self.unnormalizedReleaseName === 'none';\n  },\n  normalReleaseSpecified: function () {\n    var self = this;\n    return ! (self.fileMissing() || self.noReleaseSpecified()\n              || self.isCheckout());\n  },\n\n  _readFile: function () {\n    var self = this;\n\n    // Start a new watchSet, in case we just overwrote this.\n    self.watchSet = new watch.WatchSet;\n    var contents = watch.readAndWatchFile(self.watchSet, self.filename);\n    // If file doesn't exist, leave unnormalizedReleaseName empty; fileMissing\n    // will be true.\n    if (contents === null)\n      return;\n\n    var lines = _.compact(_.map(files.splitBufferToLines(contents),\n                                files.trimSpaceAndComments));\n    // noReleaseSpecified will be true.\n    if (!lines.length) {\n      self.unnormalizedReleaseName = '';\n      return;\n    }\n\n    self.unnormalizedReleaseName = lines[0];\n\n    const catalogUtils = require('./packaging/catalog/catalog-utils.js');\n    var parts = catalogUtils.splitReleaseName(self.unnormalizedReleaseName);\n    self.fullReleaseName = parts[0] + '@' + parts[1];\n    self.displayReleaseName = catalogUtils.displayRelease(parts[0], parts[1]);\n    self.releaseTrack = parts[0];\n    self.releaseVersion = parts[1];\n  },\n\n  write: function (releaseName) {\n    var self = this;\n    files.writeFileAtomically(self.filename, releaseName + '\\n');\n    self._readFile();\n  }\n});\n\n\n// Represents .meteor/.finished-upgraders.\n// This is only used in a few places, so we don't cache its value in memory;\n// we just read it when we need it. There's also no need to add it to a\n// watchSet because we don't need to rebuild when it changes.\nexports.FinishedUpgraders = function (options) {\n  var self = this;\n\n  self.filename = files.pathJoin(\n    options.projectDir, '.meteor', '.finished-upgraders');\n};\n\n_.extend(exports.FinishedUpgraders.prototype, {\n  readUpgraders: function () {\n    var self = this;\n    var upgraders = [];\n    var lines = files.getLinesOrEmpty(self.filename);\n    _.each(lines, function (line) {\n      line = files.trimSpaceAndComments(line);\n      if (line === '')\n        return;\n      upgraders.push(line);\n    });\n    return upgraders;\n  },\n\n  appendUpgraders: function (upgraders) {\n    var self = this;\n\n    var current = null;\n    try {\n      current = files.readFile(self.filename, 'utf8');\n    } catch (e) {\n      if (e.code !== 'ENOENT')\n        throw e;\n    }\n\n    var appendText = '';\n    if (current === null) {\n      // We're creating this file for the first time. Include a helpful comment.\n      appendText =\n\"# This file contains information which helps Meteor properly upgrade your\\n\" +\n\"# app when you run 'meteor update'. You should check it into version control\\n\" +\n\"# with your project.\\n\" +\n\"\\n\";\n    } else if (current.length && current[current.length - 1] !== '\\n') {\n      // File has an unterminated last line. Let's terminate it.\n      appendText = '\\n';\n    }\n\n    _.each(upgraders, function (upgrader) {\n      appendText += upgrader + '\\n';\n    });\n\n    files.appendFile(self.filename, appendText);\n  }\n});\n"
  },
  {
    "path": "tools/runners/README.md",
    "content": "# Runners\n\nThe Meteor tool process would run multiple big \"parts\" that should be managed:\nstarted, stopped, restarted, monitored for crashes, etc.\n\nThe interface that Meteor tool uses is called a \"runner\".\n\nSome of the runners run sub-processes. The main runner is called `run-all`, it\nhas sub-runners such as `run-app`, `run-mongo` and `run-proxy`. Other runners\nare used for different CLI commands.\n\n## Run Log\n\nThe output of the runners (compilation errors, state change, etc), should be\nreported through the Run Log. Run Log is also something that users see in their\nbrowsers, when their app breaks.\n"
  },
  {
    "path": "tools/runners/run-all.js",
    "content": "const _ = require('underscore');\n\nconst files = require('../fs/files.js');\nconst buildmessage = require('../utils/buildmessage.js');\nconst utils = require('../utils/utils.js');\nconst runLog = require('./run-log.js');\nconst release = require('../packaging/release.js');\n\nconst Console = require('../console/console.js').Console;\n\nconst Proxy = require('./run-proxy.js').Proxy;\nconst Selenium = require('./run-selenium.js').Selenium;\nconst AppRunner = require('./run-app.js').AppRunner;\nconst MongoRunner = require('./run-mongo.js').MongoRunner;\nconst Updater = require('./run-updater.js').Updater;\n\nclass Runner {\n  constructor({\n    appHost,\n    appPort,\n    banner,\n    disableOplog,\n    cordovaRunner,\n    mongoUrl,\n    onFailure,\n    oplogUrl,\n    projectContext,\n    proxyHost,\n    proxyPort,\n    quiet,\n    rootUrl,\n    selenium,\n    seleniumBrowser,\n    ...optionsForAppRunner\n  }) {\n    const self = this;\n    self.projectContext = projectContext;\n\n    if (typeof proxyPort === 'undefined') {\n      throw new Error('no proxyPort?');\n    }\n\n    const listenPort = proxyPort;\n    const mongoPort = parseInt(listenPort, 10) + 1;\n    self.specifiedAppPort = appPort;\n    self.regenerateAppPort();\n\n    self.stopped = false;\n    self.quiet = quiet;\n    self.banner = banner || files.convertToOSPath(\n      files.prettyPath(self.projectContext.projectDir)\n    );\n\n    if (rootUrl) {\n      self.rootUrl = rootUrl;\n    } else {\n      self.rootUrl = utils.formatUrl({\n        protocol: 'http',\n        hostname: proxyHost || \"localhost\",\n        port: listenPort,\n      });\n    }\n\n    self.proxy = new Proxy({\n      listenPort,\n      listenHost: proxyHost,\n      proxyToPort: self.appPort,\n      proxyToHost: appHost,\n      onFailure\n    });\n\n    self.mongoRunner = null;\n    if (mongoUrl) {\n      oplogUrl = disableOplog ? null : oplogUrl;\n    } else {\n      self.mongoRunner = new MongoRunner({\n        projectLocalDir: self.projectContext.projectLocalDir,\n        port: mongoPort,\n        onFailure,\n        // For testing mongod failover, run with 3 mongod if the env var is\n        // set. Note that data is not preserved from one run to the next.\n        multiple: !!process.env.METEOR_TEST_MULTIPLE_MONGOD_REPLSET\n      });\n\n      mongoUrl = self.mongoRunner.mongoUrl();\n      oplogUrl = disableOplog ? null : self.mongoRunner.oplogUrl();\n    }\n\n    self.updater = new Updater();\n\n    self.appRunner = new AppRunner({\n      ...optionsForAppRunner,\n      projectContext: self.projectContext,\n      port: self.appPort,\n      listenHost: appHost,\n      mongoUrl,\n      oplogUrl,\n      rootUrl: self.rootUrl,\n      proxy: self.proxy,\n      noRestartBanner: self.quiet,\n      cordovaRunner: cordovaRunner\n    });\n\n    self.selenium = null;\n    if (selenium) {\n      self.selenium = new Selenium({\n        runner: self,\n        browser: seleniumBrowser\n      });\n    }\n  }\n\n  // XXX leave a pidfile and check if we are already running\n  start() {\n    const self = this;\n\n    self.proxy.start();\n\n    // print the banner only once we've successfully bound the port\n    if (! self.quiet && ! self.stopped) {\n      runLog.log(\"[[[[[ \" + self.banner + \" ]]]]]\\n\");\n      runLog.log(\"Started proxy.\",  { arrow: true });\n    }\n\n    var unblockAppRunner = self.appRunner.makeBeforeStartPromise();\n    self._startMongoAsync().then(unblockAppRunner);\n\n    if (! self.stopped) {\n      self.updater.start();\n    }\n\n    if (! self.stopped) {\n      buildmessage.enterJob({ title: \"starting your app\" }, function () {\n        self.appRunner.start();\n      });\n      if (! self.quiet && ! self.stopped) {\n        runLog.log(\"Started your app.\",  { arrow: true });\n      }\n    }\n\n    if (! self.stopped && ! self.quiet) {\n      runLog.log(\"\");\n      runLog.log(\"App running at: \" + self.rootUrl,  { arrow: true });\n\n      if (process.platform === \"win32\") {\n        runLog.log(\"   Type Control-C twice to stop.\");\n        runLog.log(\"\");\n      }\n    }\n\n    if (self.selenium && ! self.stopped) {\n      buildmessage.enterJob({ title: \"starting Selenium\" }, function () {\n        self.selenium.start();\n      });\n      if (! self.quiet && ! self.stopped) {\n        runLog.log(\"Started Selenium.\", { arrow: true });\n      }\n    }\n\n    // XXX It'd be nice to (cosmetically) handle failure better. Right\n    // now we overwrite the \"starting foo...\" message with the\n    // error. It'd be better to overwrite it with \"failed to start\n    // foo\" and then print the error.\n  }\n\n  async _startMongoAsync() {\n    if (! this.stopped && this.mongoRunner) {\n      this.mongoRunner.start();\n      if (! this.stopped && ! this.quiet) {\n        runLog.log(\"Started MongoDB.\", { arrow: true });\n      }\n    }\n  }\n\n  // Idempotent\n  stop() {\n    const self = this;\n    if (self.stopped) {\n      return;\n    }\n\n    self.stopped = true;\n    self.proxy.stop();\n    self.updater.stop();\n    self.mongoRunner && self.mongoRunner.stop();\n    self.appRunner.stop();\n    self.selenium && self.selenium.stop();\n    // XXX does calling this 'finish' still make sense now that runLog is a\n    // singleton?\n    runLog.finish();\n  }\n\n  // Call this whenever you want to regenerate the app's port (if it is not\n  // explicitly specified by the user).\n  //\n  // Rationale: if we randomly chose a port that's in use and the app failed to\n  // listen on it, we should try a different port when we restart the app!\n  regenerateAppPort() {\n    const self = this;\n    if (self.specifiedAppPort) {\n      self.appPort = self.specifiedAppPort;\n    } else {\n      self.appPort = require('../utils/utils.js').randomPort();\n    }\n    if (self.proxy) {\n      self.proxy.proxyToPort = self.appPort;\n    }\n    if (self.appRunner) {\n      self.appRunner.port = self.appPort;\n    }\n  }\n}\n\n// Run the app and all of its associated processes. Runs (and does not\n// return) until an unrecoverable failure happens. Logs to\n// stdout. Returns a suggested exit code.\n//\n// If 'once' is set, run the app process exactly once and pass through\n// its exit code. Return an exit code of 255 if the app process was\n// killed by a signal and 254 if the app process could not start\n// (build failure, invalid program name, database couldn't start, and\n// so on).\n//\n// If the 'once' option is not set, the default, restart the app\n// process if it crashes or if source files change. (Non-app\n// processes, such as the database, are always restarted as\n// necessary.) The function will only return if there is an\n// unrecoverable error, which generally means an error that could not\n// be fixed by source code changes (such as the database refusing to\n// run), but also currently includes Meteor version mismatches. So the\n// exit code will always be 254 because in all other cases we'll\n// persevere.\n//\n// Options:\n//\n// - proxyPort: the port to connect to to access the application (we will\n//   run a proxy here that proxies to the actual app process). required\n// - buildOptions: 'buildOptions' argument to bundler.bundle()\n// - settingsFile: path to file containing deploy-time settings\n// - once: see above\n// - banner: replace the application path that is normally printed on\n//   startup with an arbitrary string (eg, 'Tests')\n// - rootUrl: tell the app that traffic at this URL will be routed to\n//   it at '/' (used by the app to construct absolute URLs)\n// - disableOplog: don't use oplog tailing\n// - mongoUrl: don't start a mongo process; instead use the mongo at\n//   this mongo URL\n// - oplogUrl: URL of the mongo oplog to use. if mongoUrl isn't\n//   set (we're starting a mongo) a default will be provided, but can\n//   be overridden. if mongoUrl is set, you must set this or you don't\n//   get oplog tailing.\n// - recordPackageUsage: (default true) if set to false, don't send\n//   information about packages used by this app to the package stats\n//   server.\nexports.run = function (options) {\n  var runOptions = _.clone(options);\n  var once = runOptions.once;\n  delete runOptions.once;\n\n  var promise = new Promise(function (resolve) {\n    runOptions.onFailure = function () {\n      // Ensure that runner stops now. You might think this is unnecessary\n      // because the runner is stopped immediately after promise.await(), but if\n      // the failure happens while runner.start() is still running, we want the\n      // rest of start to stop, and it's not like resolve() magically makes\n      // us jump to a promise.await() that hasn't happened yet!.\n      runner.stop();\n      resolve({ outcome: 'failure' });\n    };\n\n    runOptions.onRunEnd = function (result) {\n      if (once ||\n          result.outcome === \"conflicting-versions\" ||\n          result.outcome === \"wrong-release\" ||\n          result.outcome === \"outdated-cordova-platforms\" ||\n          result.outcome === \"outdated-cordova-plugins\" ||\n          (result.outcome === \"terminated\" &&\n           result.signal === undefined && result.code === undefined)) {\n        resolve(result);\n        return false;  // stop restarting\n      }\n      runner.regenerateAppPort();\n      return true;  // restart it\n    };\n  });\n\n  runOptions.watchForChanges = ! once;\n  runOptions.quiet = false;\n\n  // Ensure process.env.NODE_ENV matches the build mode, with the following precedence:\n  // 1. Passed in build mode (if development or production)\n  // 2. Existing process.env.NODE_ENV (if it's valid)\n  // 3. Default to development (in both cases) otherwise\n\n  // NOTE: because this code only runs when using `meteor run` or `meteor test[-packages`,\n  // We *don't* end up defaulting NODE_ENV in this way when bundling/deploying.\n  // In those cases, it will default to \"production\" in packages/meteor/*_env.js\n\n  // We *override* NODE_ENV if build mode is one of these values\n  let buildMode = runOptions.buildOptions.buildMode;\n  if (buildMode === \"development\" || buildMode === \"production\") {\n    process.env.NODE_ENV = buildMode;\n  }\n\n  let nodeEnv = process.env.NODE_ENV;\n  // We *never* override buildMode (it can be \"test\")\n  if (!buildMode) {\n    if (nodeEnv === \"development\" || nodeEnv === \"production\") {\n      runOptions.buildOptions.buildMode = nodeEnv;\n    } else {\n      runOptions.buildOptions.buildMode = \"development\";\n    }\n  }\n\n  if (!nodeEnv) {\n    process.env.NODE_ENV = \"development\";\n  }\n\n  var runner = new Runner(runOptions);\n  runner.start();\n  var result = promise.await();\n  runner.stop();\n\n  if (result.outcome === \"conflicting-versions\") {\n    Console.error(\n      \"The constraint solver could not find a set of package versions to\",\n      \"use that would satisfy the constraints of .meteor/versions and\",\n      \".meteor/packages. This could be caused by conflicts in\",\n      \".meteor/versions, conflicts in .meteor/packages, and/or\",\n      \"inconsistent changes to the dependencies in local packages.\");\n    return 254;\n  }\n\n  if (result.outcome === \"outdated-cordova-plugins\") {\n    Console.error(\"Your app's Cordova plugins have changed.\");\n    Console.error(\"Restart meteor to use the new set of plugins.\");\n    return 254;\n  }\n\n  if (result.outcome === \"outdated-cordova-platforms\") {\n    Console.error(\"Your app's platforms have changed.\");\n    Console.error(\"Restart meteor to use the new set of platforms.\");\n    return 254;\n  }\n\n  if (result.outcome === \"wrong-release\") {\n    if (once) {\n      // We lost a race where the user ran 'meteor update' and 'meteor\n      // run --once' simultaneously.\n      throw new Error(\"wrong release?\");\n    }\n\n    // If the user did not specify a --release on the command line,\n    // and simultaneously runs `meteor update` during this run, just\n    // exit and let them restart the run. (We can do something fancy\n    // like allowing this to work if the tools version didn't change,\n    // or even springboarding if the tools version does change, but\n    // this (which prevents weird errors) is a start.)\n    var from = release.current.getDisplayName();\n    var to = result.displayReleaseNeeded;\n    Console.error(\n      \"Your app has been updated to \" + to + \" from \" + from + \".\",\n      \"Restart meteor to use the new release.\");\n    return 254;\n  }\n\n  if (result.outcome === \"failure\" ||\n      (result.outcome === \"terminated\" &&\n       result.signal === undefined && result.code === undefined)) {\n    // Fatal problem with something other than the app process. An\n    // explanation should already have been logged.\n    return 254;\n  }\n\n  if (once && result.outcome === \"bundle-fail\") {\n    Console.arrowError(\"Build failed:\\n\\n\" +\n                       result.errors.formatMessages());\n    return 254;\n  }\n\n  if (once && result.outcome === \"terminated\") {\n    if (result.signal) {\n      Console.error(\"Killed (\" + result.signal + \")\");\n      return 255;\n    } else if (typeof result.code === \"number\") {\n      // We used to print 'Your application is exiting' here, but that\n      // seems unnecessarily chatty? once mode is otherwise silent\n      return result.code;\n    } else {\n      // If there is neither a code nor a signal, it means that we\n      // failed to start the process. We logged the reason. Probably a\n      // bad program name.\n      return 254;\n    }\n  }\n\n  throw new Error(\"unexpected outcome \" + result.outcome);\n};\n"
  },
  {
    "path": "tools/runners/run-app.js",
    "content": "var _ = require('underscore');\nvar Fiber = require('fibers');\nvar fiberHelpers = require('../utils/fiber-helpers.js');\nvar files = require('../fs/files.js');\nvar watch = require('../fs/watch.js');\nvar bundler = require('../isobuild/bundler.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar runLog = require('./run-log.js');\nvar stats = require('../meteor-services/stats.js');\nvar Console = require('../console/console.js').Console;\nvar catalog = require('../packaging/catalog/catalog.js');\nvar Profile = require('../tool-env/profile.js').Profile;\nvar release = require('../packaging/release.js');\nimport * as cordova from '../cordova';\nimport { CordovaBuilder } from '../cordova/builder.js';\n\n// Parse out s as if it were a bash command line.\nvar bashParse = function (s) {\n  if (s.search(\"\\\"\") !== -1 || s.search(\"'\") !== -1) {\n    throw new Error(\"Meteor cannot currently handle quoted NODE_OPTIONS\");\n  }\n  return _.without(s.split(/\\s+/), '');\n};\n\nvar getNodeOptionsFromEnvironment = function () {\n  return bashParse(process.env.NODE_OPTIONS || \"\");\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// AppProcess\n///////////////////////////////////////////////////////////////////////////////\n\n// Given a bundle, run a program in the bundle. Report when it dies.\n//\n// Call start() to start the process. You will then eventually receive\n// a call to onExit(code, signal): code is the numeric exit code of a\n// normal exit, signal is the string signal name if killed, and if\n// both are undefined it means something went wrong in invoking the\n// program and it was logged.\n//\n// If the app successfully starts up, you will also receive onListen()\n// once the app says it's ready to receive connections.\n//\n// Call stop() at any time after start() returns to terminate the\n// process if it is running. You will get an onExit callback if this\n// resulted in the process dying. stop() is idempotent.\n//\n// Required options: bundlePath, port, rootUrl, mongoUrl, oplogUrl\n// Optional options: onExit, onListen, nodeOptions, settings\n\nvar AppProcess = function (options) {\n  var self = this;\n\n  self.projectContext = options.projectContext;\n  self.bundlePath = options.bundlePath;\n  self.port = options.port;\n  self.listenHost = options.listenHost;\n  self.rootUrl = options.rootUrl;\n  self.mongoUrl = options.mongoUrl;\n  self.oplogUrl = options.oplogUrl;\n  self.mobileServerUrl = options.mobileServerUrl;\n\n  self.onExit = options.onExit;\n  self.onListen = options.onListen;\n  self.nodeOptions = options.nodeOptions || [];\n  self.nodePath = options.nodePath || [];\n  self.debugPort = options.debugPort;\n  self.settings = options.settings;\n  self.testMetadata = options.testMetadata;\n\n  self.proc = null;\n  self.madeExitCallback = false;\n  self.ipcPipe = options.ipcPipe;\n};\n\n_.extend(AppProcess.prototype, {\n  // Call to start the process.\n  start: function () {\n    var self = this;\n\n    if (self.proc) {\n      throw new Error(\"already started?\");\n    }\n\n    // Start the app!\n    self.proc = self._spawn();\n\n    // Send stdout and stderr to the runLog\n    var realEachline = require('eachline');\n    function eachline(stream, encoding, callback) {\n      realEachline(stream, encoding, (...args) => void(callback(...args)));\n    }\n\n    eachline(self.proc.stdout, 'utf8', async function (line) {\n      if (line.match(/^LISTENING\\s*$/)) {\n        // This is the child process telling us that it's ready to receive\n        // connections.  (It does this because we told it to with\n        // $METEOR_PRINT_ON_LISTEN.)\n        self.onListen && self.onListen();\n\n      } else {\n        runLog.logAppOutput(line);\n      }\n    });\n\n    eachline(self.proc.stderr, 'utf8', async function (line) {\n      if (self.debugPort &&\n          line.indexOf(\"debugger listening on port \") >= 0) {\n        Console.enableProgressDisplay(false);\n        return;\n      }\n\n      runLog.logAppOutput(line, true);\n    });\n\n    // Watch for exit and for stdio to be fully closed (so that we don't miss\n    // log lines).\n    self.proc.on('close', async function (code, signal) {\n      self._maybeCallOnExit(code, signal);\n    });\n\n    self.proc.on('error', async function (err) {\n      // if the error is the result of .send command over ipc pipe, ignore it\n      if (self._refreshing) {\n        return;\n      }\n\n      runLog.log(\"Couldn't spawn process: \" + err.message,  { arrow: true });\n\n      // node docs say that it might make both an 'error' and a\n      // 'close' callback, so we use a guard to make sure we only call\n      // onExit once.\n      self._maybeCallOnExit();\n    });\n\n    // This happens sometimes when we write a keepalive after the app\n    // is dead. If we don't register a handler, we get a top level\n    // exception and the whole app dies.\n    // http://stackoverflow.com/questions/2893458/uncatchable-errors-in-node-js\n    self.proc.stdin.on('error', function () {});\n\n    // When the parent process exits (i.e. the server is shutting down and\n    // not merely restarting), make sure to disconnect any still-connected\n    // shell clients.\n    require('../tool-env/cleanup.js').onExit(function() {\n      require('../static-assets/server/shell-server.js').disable(\n        self.projectContext.getMeteorShellDirectory()\n      );\n    });\n  },\n\n  _maybeCallOnExit: function (code, signal) {\n    var self = this;\n    if (self.madeExitCallback) {\n      return;\n    }\n    self.madeExitCallback = true;\n    self.onExit && self.onExit(code, signal);\n  },\n\n  // Idempotent. Once stop() returns it is guaranteed that you will\n  // receive no more callbacks from this AppProcess.\n  stop: function () {\n    var self = this;\n\n    if (self.proc && self.proc.pid) {\n      self.proc.removeAllListeners('close');\n      self.proc.removeAllListeners('error');\n      self.proc.kill();\n    }\n    self.proc = null;\n\n    self.onListen = null;\n    self.onExit = null;\n  },\n\n  _computeEnvironment: function () {\n    var self = this;\n    var env = _.extend({}, process.env);\n\n    env.PORT = self.port;\n    env.ROOT_URL = self.rootUrl;\n    env.MONGO_URL = self.mongoUrl;\n    if (self.mobileServerUrl) {\n      env.MOBILE_DDP_URL = self.mobileServerUrl;\n      env.MOBILE_ROOT_URL = self.mobileServerUrl;\n    }\n\n    if (self.oplogUrl) {\n      env.MONGO_OPLOG_URL = self.oplogUrl;\n    }\n    if (self.settings) {\n      env.METEOR_SETTINGS = self.settings;\n    } else {\n      delete env.METEOR_SETTINGS;\n    }\n    if (self.testMetadata) {\n      env.TEST_METADATA = JSON.stringify(self.testMetadata);\n    } else {\n      delete env.TEST_METADATA; \n    }\n    if (self.listenHost) {\n      env.BIND_IP = self.listenHost;\n    } else {\n      delete env.BIND_IP;\n    }\n    env.APP_ID = self.projectContext.appIdentifier;\n\n    // We run the server behind our own proxy, so we need to increment\n    // the HTTP forwarded count.\n    env.HTTP_FORWARDED_COUNT =\n      \"\" + ((parseInt(process.env['HTTP_FORWARDED_COUNT']) || 0) + 1);\n\n    var shellDir = self.projectContext.getMeteorShellDirectory();\n    files.mkdir_p(shellDir);\n\n    // We need to convert to OS path here because the running app doesn't\n    // have access to path translation functions\n    env.METEOR_SHELL_DIR = files.convertToOSPath(shellDir);\n\n    env.METEOR_PARENT_PID =\n      process.env.METEOR_BAD_PARENT_PID_FOR_TEST ? \"foobar\" : process.pid;\n\n    env.METEOR_PRINT_ON_LISTEN = 'true';\n\n    // use node's path module and not 'files.js' because NODE_PATH is an\n    // environment variable passed to an external process and needs to be\n    // constructed in the OS-style.\n    var path = require('path');\n    env.NODE_PATH =\n      self.nodePath.join(path.delimiter);\n\n    return env;\n  },\n\n  // Spawn the server process and return the handle from child_process.spawn.\n  _spawn: function () {\n    var self = this;\n\n    // Path conversions\n    var nodePath = process.execPath; // This path is an OS path already\n    var entryPoint = files.convertToOSPath(\n      files.pathJoin(self.bundlePath, 'main.js'));\n\n    // Setting options\n    var opts = _.clone(self.nodeOptions);\n\n    var attach;\n    if (self.debugPort) {\n      attach = require('../inspector.js').start(self.debugPort, entryPoint);\n\n      // If you do opts.push(\"--debug-brk\", port) it doesn't work on Windows\n      // for some reason\n      opts.push(\"--debug-brk=\" + attach.suggestedDebugBrkPort);\n    }\n\n    opts.push(entryPoint);\n\n    // Call node\n    var child_process = require('child_process');\n    // setup the 'ipc' pipe if further communication between app and proxy is\n    // expected\n    var ioOptions = self.ipcPipe ? ['pipe', 'pipe', 'pipe', 'ipc'] : 'pipe';\n    var child = child_process.spawn(nodePath, opts, {\n      env: self._computeEnvironment(),\n      stdio: ioOptions\n    });\n\n    // Attach inspector\n    if (attach) {\n      attach(child);\n    }\n\n    return child;\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// AppRunner\n///////////////////////////////////////////////////////////////////////////////\n\n// Given an app, bundle and run the app. If the app's source changes,\n// kill, rebundle, and rerun it. If the app dies, restart it, unless\n// it dies repeatedly immediately after being started, in which case\n// wait for source changes to restart.\n//\n// Communicates with a Proxy to tell it when the app is up,\n// temporarily down, or crashing.\n//\n// Options include:\n//\n// - onRunEnd(result): If provided, called after each run of the program (or\n//   attempted run, if, say, bundling fails). Blocks restarting until it\n//   returns. See below for the format of 'result'. Return truthy to continue;\n//   return falsey to give up (without logging any more status messages). Do not\n//   call stop() from onRunEnd as that would necessarily deadlock.\n//\n// - watchForChanges: If true, the default, then (a) the program will\n//   be killed and restarted if its source files change; (b) if\n//   something goes really wrong (bundling fails, the program crashes\n//   constantly) such that we give up, we will start trying again if\n//   the source files change. If false, then we don't do (a) and if\n//   (b) happens we just give up permanently.\n//\n// - noRestartBanner: Set to true to skip the banner that is normally\n//   printed after each restart of the app once it is ready to listen\n//   for connections.\n//\n// - Other options: port, mongoUrl, oplogUrl, buildOptions, rootUrl,\n//   settingsFile, program, proxy, recordPackageUsage\n//\n// To use, construct an instance of AppRunner, and then call start() to start it\n// running. To stop it, either return false from onRunEnd, or call stop().  (But\n// don't call stop() from inside onRunEnd: that causes a deadlock.)\n//\n// The 'result' argument to onRunEnd is an object with keys:\n//\n// - outcome: the reason the run ended. One of:\n//\n//   - 'terminated': the process exited. Additionally, a 'code'\n//     attribute will be set of the process exited on its own accord,\n//     a 'signal' attribute will be set if the process was killed on a\n//     signal, or neither will be set if the process could not be\n//     spawned (spawn call failed, or no such program in bundle) -- in\n//     this last case an explanation will have been written to the run\n//     log, and you may assume that it will take more than source code\n//     changes to fix the problem.\n//\n//   - 'bundle-fail': bundling failed.\n//\n//   - 'changed': watchForChanges was true and a source file changed.\n//\n//   - 'wrong-release': the release that this app targets does not\n//     match the currently running version of Meteor (eg, the user\n//     typed 'meteor update' in another window). An 'displayReleaseNeeded'\n//     attribute will be present giving the app's release name.\n//\n//   - 'conflicting-versions': the constraint solver could not find a set of\n//     package versions to use that would satisfy the constraints of\n//     .meteor/versions and .meteor/packages. This could be caused by conflicts\n//     in .meteor/versions, conflicts in .meteor/packages, and/or inconsistent\n//     changes to the dependencies in local packages.\n//\n//   - 'stopped': stop() was called while a run was in progress.\n//\n// - errors: for 'bundle-fail', the buildmessage messages object corresponding\n//      to the error\n//\n// - watchSet: for runs in which there's a reason to wait for file changes\n//      ('bundle-fail' and 'terminated'), the WatchSet to wait on.\nvar AppRunner = function (options) {\n  var self = this;\n\n  self.projectContext = options.projectContext;\n\n  // note: run-all.js updates port directly\n  self.port = options.port;\n  self.listenHost = options.listenHost;\n  self.mongoUrl = options.mongoUrl;\n  self.oplogUrl = options.oplogUrl;\n  self.buildOptions = options.buildOptions;\n  self.rootUrl = options.rootUrl;\n  self.mobileServerUrl = options.mobileServerUrl;\n  self.cordovaRunner = options.cordovaRunner;\n  self.settingsFile = options.settingsFile;\n  self.testMetadata = options.testMetadata;\n  self.debugPort = options.debugPort;\n  self.proxy = options.proxy;\n  self.watchForChanges =\n    options.watchForChanges === undefined ? true : options.watchForChanges;\n  self.onRunEnd = options.onRunEnd;\n  self.noRestartBanner = options.noRestartBanner;\n  self.recordPackageUsage =\n    options.recordPackageUsage === undefined ? true : options.recordPackageUsage;\n  self.omitPackageMapDeltaDisplayOnFirstRun =\n    options.omitPackageMapDeltaDisplayOnFirstRun;\n\n  self.fiber = null;\n  self.startPromise = null;\n  self.runPromise = null;\n  self.exitPromise = null;\n  self.watchPromise = null;\n  self._promiseResolvers = {};\n\n  // If this promise is set with self.makeBeforeStartPromise, then for the first\n  // run, we will wait on it just before self.appProcess.start() is called.\n  self._beforeStartPromise = null;\n  // A hacky state variable that indicates that the proxy process (this process)\n  // is communicating to the app process over ipc. If an error in communication\n  // occurs, we can distinguish it in a callback handling the 'error' event.\n  self._refreshing = false;\n\n  // Builders saved across rebuilds, so that targets can be re-written in\n  // place instead of created again from scratch.\n  self.builders = {};\n};\n\n_.extend(AppRunner.prototype, {\n  // Start the app running, and restart it as necessary. Returns\n  // immediately.\n  start: function () {\n    var self = this;\n\n    if (self.fiber) {\n      throw new Error(\"already started?\");\n    }\n\n    self.startPromise = self._makePromise(\"start\");\n\n    self.fiber = Fiber(function () {\n      self._fiber();\n    });\n    self.fiber.run();\n\n    self.startPromise.await();\n    self.startPromise = null;\n  },\n\n  _makePromise: function (name) {\n    var self = this;\n    return new Promise(function (resolve) {\n      self._promiseResolvers[name] = resolve;\n    });\n  },\n\n  _resolvePromise: function (name, value) {\n    var resolve = this._promiseResolvers[name];\n    if (resolve) {\n      this._promiseResolvers[name] = null;\n      resolve(value);\n    }\n  },\n\n  _cleanUpPromises: function () {\n    if (this._promiseResolvers) {\n      _.each(this._promiseResolvers, function (resolve) {\n        resolve && resolve();\n      });\n      this._promiseResolvers = null;\n    }\n  },\n\n  // Shut down the app. stop() will block until the app is shut\n  // down. This may involve waiting for bundling to\n  // finish. Idempotent, however only one thread may be in stop() at a\n  // time.\n  stop: function () {\n    var self = this;\n\n    if (! self.fiber) {\n      // nothing to do\n      return;\n    }\n\n    if (self.exitPromise) {\n      throw new Error(\"another fiber already stopping?\");\n    }\n\n    // The existence of this promise makes the fiber break out of its loop.\n    self.exitPromise = self._makePromise(\"exit\");\n\n    self._resolvePromise(\"run\", { outcome: 'stopped' });\n    self._resolvePromise(\"watch\");\n\n    if (self._beforeStartPromise) {\n      // If we stopped before mongod started (eg, due to mongod startup\n      // failure), unblock the runner fiber from waiting for mongod to start.\n      self._resolvePromise(\"beforeStart\", true);\n    }\n\n    self.exitPromise.await();\n    self.exitPromise = null;\n  },\n\n  // Returns a function that can be called to resolve _beforeStartPromise.\n  makeBeforeStartPromise: function () {\n    if (this._beforeStartPromise) {\n      throw new Error(\"makeBeforeStartPromise called twice?\");\n    }\n    this._beforeStartPromise = this._makePromise(\"beforeStart\");\n    return this._promiseResolvers[\"beforeStart\"];\n  },\n\n  // Run the program once, wait for it to exit, and then return. The\n  // return value is same as onRunEnd.\n  _runOnce: function (options) {\n    var self = this;\n    options = options || {};\n    var firstRun = options.firstRun;\n\n    Console.enableProgressDisplay(true);\n\n    runLog.clearLog();\n    self.proxy.setMode(\"hold\");\n\n    // Bundle up the app\n    var bundlePath = self.projectContext.getProjectLocalDirectory('build');\n\n    // Cache the server target because the server will not change inside\n    // a single invocation of _runOnce().\n    var cachedServerWatchSet;\n\n    var bundleApp = function () {\n      if (! firstRun) {\n        // If the build fails in a way that could be fixed by a refresh, allow\n        // it even if we refreshed previously, since that might have been a\n        // little while ago.\n        catalog.triedToRefreshRecently = false;\n\n        // If this isn't the first time we've run, we need to reset the project\n        // context since everything we have cached may have changed.\n        // XXX We can try to be a little less conservative here:\n        // - Don't re-build the whole local catalog if we know which local\n        //   packages have changed.  (This one might be a little trickier due\n        //   to how the WatchSets are laid out.  Might be possible to avoid\n        //   re-building the local catalog at all if packages didn't change\n        //   at all, though.)\n        self.projectContext.reset({}, {\n          // Don't forget all Isopack objects; just make sure to check that they\n          // are up to date.\n          softRefreshIsopacks: true,\n          // Don't forget the package map we calculated last time, even if we\n          // didn't write it to disk (because, eg, we're not running with a\n          // release that matches the app's release).  While we will still check\n          // our constraints, we will use the map we calculated last time as the\n          // previous solution (not what's on disk). Package deltas should be\n          // shown from the previous solution.\n          preservePackageMap: true\n        });\n        var messages = buildmessage.capture(function () {\n          self.projectContext.readProjectMetadata();\n        });\n        if (messages.hasMessages()) {\n          return {\n            runResult: {\n              outcome: 'bundle-fail',\n              errors: messages,\n              watchSet: self.projectContext.getProjectAndLocalPackagesWatchSet()\n            }\n          };\n        }\n      }\n\n      // Check to make sure we're running the right version of Meteor.\n      var wrongRelease = ! release.usingRightReleaseForApp(self.projectContext);\n      if (wrongRelease) {\n        return {\n          runResult: {\n            outcome: 'wrong-release',\n            displayReleaseNeeded:\n              self.projectContext.releaseFile.displayReleaseName\n          }\n        };\n      }\n\n      messages = buildmessage.capture(function () {\n        self.projectContext.prepareProjectForBuild();\n      });\n      if (messages.hasMessages()) {\n        return {\n          runResult: {\n            outcome: 'bundle-fail',\n            errors: messages,\n            watchSet: self.projectContext.getProjectAndLocalPackagesWatchSet()\n          }\n        };\n      }\n\n      // Show package changes... unless it's the first time in test-packages.\n      if (!(self.omitPackageMapDeltaDisplayOnFirstRun && firstRun)) {\n        self.projectContext.packageMapDelta.displayOnConsole();\n      }\n\n      if (self.recordPackageUsage) {\n        stats.recordPackages({\n          what: \"sdk.run\",\n          projectContext: self.projectContext\n        });\n      }\n\n      var bundleResult = Profile.run((firstRun?\"B\":\"Reb\")+\"uild App\", () => {\n        var includeNodeModules = 'symlink';\n\n        // On Windows we cannot symlink node_modules. Copying them is too slow.\n        // Instead receive the NODE_PATH env that we need to set and set it\n        // later on running.\n        if (process.platform === 'win32') {\n          includeNodeModules = 'reference-directly';\n        }\n\n        var bundleResult = bundler.bundle({\n          projectContext: self.projectContext,\n          outputPath: bundlePath,\n          includeNodeModules: includeNodeModules,\n          buildOptions: self.buildOptions,\n          hasCachedBundle: !! cachedServerWatchSet,\n          previousBuilders: self.builders\n        });\n\n        // save new builders with their caches\n        self.builders = bundleResult.builders;\n\n        return bundleResult;\n      });\n\n      // Keep the server watch set from the initial bundle, because subsequent\n      // bundles will not contain a server target.\n      if (cachedServerWatchSet) {\n        bundleResult.serverWatchSet = cachedServerWatchSet;\n      } else {\n        cachedServerWatchSet = bundleResult.serverWatchSet;\n      }\n\n      if (bundleResult.errors) {\n        return {\n          runResult: {\n            outcome: 'bundle-fail',\n            errors: bundleResult.errors,\n            watchSet: combinedWatchSetForBundleResult(bundleResult)\n          }\n        };\n      } else {\n        return { bundleResult: bundleResult };\n      }\n    };\n\n    var combinedWatchSetForBundleResult = function (br) {\n      var watchSet = br.serverWatchSet.clone();\n      watchSet.merge(br.clientWatchSet);\n      return watchSet;\n    };\n\n    var bundleResult;\n    var bundleResultOrRunResult = bundleApp();\n    if (bundleResultOrRunResult.runResult) {\n      return bundleResultOrRunResult.runResult;\n    }\n    bundleResult = bundleResultOrRunResult.bundleResult;\n\n    firstRun = false;\n\n    // Read the settings file, if any\n    var settings = null;\n    var settingsWatchSet = new watch.WatchSet;\n    var settingsMessages = buildmessage.capture({\n      title: \"preparing to run\",\n      rootPath: process.cwd()\n    }, function () {\n      if (self.settingsFile) {\n        settings = files.getSettings(self.settingsFile, settingsWatchSet);\n      }\n    });\n    if (settingsMessages.hasMessages()) {\n      return {\n        outcome: 'bundle-fail',\n        errors: settingsMessages,\n        watchSet: settingsWatchSet\n      };\n    }\n\n    var serverWatchSet = bundleResult.serverWatchSet;\n    serverWatchSet.merge(settingsWatchSet);\n\n    // We only can refresh the client without restarting the server if the\n    // client contains the 'autoupdate' package.\n    var canRefreshClient = self.projectContext.packageMap &&\n          self.projectContext.packageMap.getInfo('autoupdate');\n\n    if (! canRefreshClient) {\n      // Restart server on client changes if we can't refresh the client.\n      serverWatchSet = combinedWatchSetForBundleResult(bundleResult);\n    }\n\n    const cordovaRunner = self.cordovaRunner;\n    if (cordovaRunner) {\n      const pluginVersions =\n        cordova.pluginVersionsFromStarManifest(bundleResult.starManifest);\n\n      if (!cordovaRunner.started) {\n        const { settingsFile, mobileServerUrl } = self;\n        const messages = buildmessage.capture(() => {\n          cordovaRunner.prepareProject(bundlePath, pluginVersions,\n            { settingsFile, mobileServerUrl });\n        });\n\n        if (messages.hasMessages()) {\n          return {\n            outcome: 'bundle-fail',\n            errors: messages,\n            watchSet: combinedWatchSetForBundleResult(bundleResult)\n          };\n        }\n        cordovaRunner.printWarningsIfNeeded();\n      } else {\n        // If the set of Cordova platforms or plugins changes from one run\n        // to the next, we just exit, because we don't yet have a way to,\n        // for example, get the new plugins to the mobile clients or stop a\n        // running client on a platform that has been removed.\n\n        if (cordovaRunner.havePlatformsChangedSinceLastRun()) {\n          return { outcome: 'outdated-cordova-platforms' };\n        }\n\n        if (cordovaRunner.havePluginsChangedSinceLastRun(pluginVersions)) {\n          return { outcome: 'outdated-cordova-plugins' };\n        }\n      }\n    }\n\n    // Atomically (1) see if we've been stop()'d, (2) if not, create a\n    // promise that can be used to stop() us once we start running.\n    if (self.exitPromise) {\n      return { outcome: 'stopped' };\n    }\n\n    if (self.runPromise) {\n      throw new Error(\"already have promise?\");\n    }\n\n    var runPromise = self.runPromise = self._makePromise(\"run\");\n\n    // Run the program\n    options.beforeRun && options.beforeRun();\n    var appProcess = new AppProcess({\n      projectContext: self.projectContext,\n      bundlePath: bundlePath,\n      port: self.port,\n      listenHost: self.listenHost,\n      rootUrl: self.rootUrl,\n      mongoUrl: self.mongoUrl,\n      oplogUrl: self.oplogUrl,\n      mobileServerUrl: self.mobileServerUrl,\n      onExit: function (code, signal) {\n        self._resolvePromise(\"run\", {\n          outcome: 'terminated',\n          code: code,\n          signal: signal,\n          watchSet: combinedWatchSetForBundleResult(bundleResult)\n        });\n      },\n      debugPort: self.debugPort,\n      onListen: function () {\n        self.proxy.setMode(\"proxy\");\n        options.onListen && options.onListen();\n        self._resolvePromise(\"start\");\n      },\n      nodeOptions: getNodeOptionsFromEnvironment(),\n      nodePath: _.map(bundleResult.nodePath, files.convertToOSPath),\n      settings: settings,\n      testMetadata: self.testMetadata,\n      ipcPipe: self.watchForChanges\n    });\n\n    if (options.firstRun && self._beforeStartPromise) {\n      var stopped = self._beforeStartPromise.await();\n      if (stopped) {\n        return true;\n      }\n    }\n\n    appProcess.start();\n    function maybePrintLintWarnings(bundleResult) {\n      if (! (self.projectContext.lintAppAndLocalPackages &&\n             bundleResult.warnings)) {\n        return;\n      }\n      if (bundleResult.warnings.hasMessages()) {\n        const formattedMessages = bundleResult.warnings.formatMessages();\n        runLog.log(\n          `Linted your app.\\n\\n${ formattedMessages }`,\n          { arrow: true });\n      } else {\n        runLog.log('Linted your app. No linting errors.',\n                   { arrow: true });\n      }\n    }\n    maybePrintLintWarnings(bundleResult);\n\n    if (cordovaRunner && !cordovaRunner.started) {\n      cordovaRunner.startRunTargets();\n    }\n\n    // Start watching for changes for files if requested. There's no\n    // hurry to do this, since clientWatchSet contains a snapshot of the\n    // state of the world at the time of bundling, in the form of\n    // hashes and lists of matching files in each directory.\n    var serverWatcher;\n    var clientWatcher;\n\n    if (self.watchForChanges) {\n      serverWatcher = new watch.Watcher({\n        watchSet: serverWatchSet,\n        onChange: function () {\n          self._resolvePromise(\"run\", {\n            outcome: 'changed'\n          });\n        }\n      });\n    }\n\n    var setupClientWatcher = function () {\n      clientWatcher && clientWatcher.stop();\n      clientWatcher = new watch.Watcher({\n         watchSet: bundleResult.clientWatchSet,\n         onChange: function () {\n          var outcome = watch.isUpToDate(serverWatchSet)\n                      ? 'changed-refreshable' // only a client asset has changed\n                      : 'changed'; // both a client and server asset changed\n          self._resolvePromise('run', { outcome: outcome });\n         }\n      });\n    };\n    if (self.watchForChanges && canRefreshClient) {\n      setupClientWatcher();\n    }\n\n    Console.enableProgressDisplay(false);\n\n    // Wait for either the process to exit, or (if watchForChanges) a\n    // source file to change. Or, for stop() to be called.\n    var ret = runPromise.await();\n\n    try {\n      while (ret.outcome === 'changed-refreshable') {\n        if (! canRefreshClient) {\n          throw Error(\"Can't refresh client?\");\n        }\n\n        // We stay in this loop as long as only refreshable assets have changed.\n        // When ret.refreshable becomes false, we restart the server.\n        bundleResultOrRunResult = bundleApp();\n        if (bundleResultOrRunResult.runResult) {\n          return bundleResultOrRunResult.runResult;\n        }\n        bundleResult = bundleResultOrRunResult.bundleResult;\n\n        maybePrintLintWarnings(bundleResult);\n\n        runLog.logClientRestart();\n\n        var oldPromise = self.runPromise = self._makePromise(\"run\");\n\n        // Notify the server that new client assets have been added to the\n        // build.\n        self._refreshing = true;\n        appProcess.proc.send({ refresh: 'client' });\n        self._refreshing = false;\n\n        // Establish a watcher on the new files.\n        setupClientWatcher();\n\n        // Wait until another file changes.\n        ret = oldPromise.await();\n      }\n    } finally {\n      self.runPromise = null;\n\n      if (ret.outcome === 'changed') {\n        runLog.logTemporary(\"=> Server modified -- restarting...\");\n      }\n\n      self.proxy.setMode(\"hold\");\n      appProcess.stop();\n\n      serverWatcher && serverWatcher.stop();\n      clientWatcher && clientWatcher.stop();\n    }\n\n    return ret;\n  },\n\n  _fiber: function () {\n    var self = this;\n\n    var crashCount = 0;\n    var crashTimer = null;\n    var firstRun = true;\n\n    while (true) {\n\n      var resetCrashCount = function () {\n        crashTimer = setTimeout(function () {\n          crashCount = 0;\n        }, 8000);\n      };\n\n      var runResult = self._runOnce({\n        onListen: function () {\n          if (! self.noRestartBanner && ! firstRun) {\n            runLog.logRestart();\n            Console.enableProgressDisplay(false);\n          }\n        },\n        beforeRun: resetCrashCount,\n        firstRun: firstRun\n      });\n      firstRun = false;\n\n      clearTimeout(crashTimer);\n      if (runResult.outcome !== \"terminated\") {\n        crashCount = 0;\n      }\n\n      var wantExit = self.onRunEnd ? !self.onRunEnd(runResult) : false;\n      if (wantExit || self.exitPromise || runResult.outcome === \"stopped\") {\n        break;\n      }\n\n      if (runResult.outcome === \"wrong-release\" ||\n          runResult.outcome === \"conflicting-versions\") {\n        // Since the only implementation of onRunEnd sets wantExit on these\n        // outcomes, we will never get here currently. Moreover, it's not\n        // actually possible for us to handle these cases correctly, because our\n        // contract says that we should wait for changes, but runResult doesn't\n        // actually contain a watchset. Oops. Just throw an exception for now.\n        throw new Error(\"can't handle outcome \" + runResult.outcome);\n      }\n\n      else if (runResult.outcome === \"bundle-fail\") {\n        runLog.log(\"Errors prevented startup:\\n\\n\" +\n                        runResult.errors.formatMessages(),  { arrow: true });\n        if (self.watchForChanges) {\n          runLog.log(\"Your application has errors. \" +\n                     \"Waiting for file change.\",  { arrow: true });\n          Console.enableProgressDisplay(false);\n        }\n      }\n\n      else if (runResult.outcome === \"changed\") {\n        continue;\n      } else if (runResult.outcome === \"terminated\") {\n        if (runResult.signal) {\n          runLog.log('Exited from signal: ' + runResult.signal, { arrow: true });\n        } else if (runResult.code !== undefined) {\n          runLog.log('Exited with code: ' + runResult.code, { arrow: true });\n        } else {\n          // explanation should already have been logged\n        }\n\n        crashCount ++;\n        if (crashCount < 3) {\n          continue;\n        }\n\n        if (self.watchForChanges) {\n          runLog.log(\"Your application is crashing. \" +\n                     \"Waiting for file change.\",\n                     { arrow: true });\n          Console.enableProgressDisplay(false);\n        }\n      }\n\n      else {\n        throw new Error(\"unknown run outcome?\");\n      }\n\n      if (self.watchForChanges) {\n        self.watchPromise = self._makePromise(\"watch\");\n\n        if (!runResult.watchSet) {\n          throw Error(\"watching for changes with no watchSet?\");\n        }\n        // XXX reference to watcher is lost later?\n        var watcher = new watch.Watcher({\n          watchSet: runResult.watchSet,\n          onChange: function () {\n            self._resolvePromise(\"watch\");\n          }\n        });\n        self.proxy.setMode(\"errorpage\");\n        // If onChange wasn't called synchronously (clearing watchPromise), wait\n        // on it.\n        self.watchPromise && self.watchPromise.await();\n        // While we were waiting, did somebody stop() us?\n        if (self.exitPromise) {\n          break;\n        }\n        runLog.log(\"Modified -- restarting.\",  { arrow: true });\n        Console.enableProgressDisplay(true);\n        continue;\n      }\n\n      break;\n    }\n\n    // Giving up for good.\n    self._cleanUpPromises();\n\n    self.fiber = null;\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n\nexports.AppRunner = AppRunner;\n"
  },
  {
    "path": "tools/runners/run-log.js",
    "content": "var _ = require('underscore');\nvar isopackets = require('../tool-env/isopackets.js');\nvar Console = require('../console/console.js').Console;\nvar fiberHelpers = require('../utils/fiber-helpers.js');\n\n// runLog is primarily used by the parts of the tool which run apps locally. It\n// writes to standard output (and standard error, if rawLogs is set), and allows\n// special output forms like \"write this line, but let the next line overwrite\n// it\". It also makes its output available to the proxy, to be displayed to web\n// browsers if the app fails to run.\n//\n// It's not the only mechanism used for gathering messages! buildmessage is a\n// more structured way of gathering messages, but unlike log, it does not print\n// messages immediately.\n//\n// Some other parts of the code (eg commands and warehouse) write directly to\n// process.std{out,err} or to console.log; we should be careful to not do that\n// anywhere that may overlap with use of runLog.\n\nlet _Log;\nfunction getLoggingPackage() {\n  if (! _Log) {\n    _Log = isopackets.load('logging').logging.Log;\n  }\n\n  // Since no other process will be listening to stdout and parsing it,\n  // print directly in the same format as log messages from other apps\n  _Log.outputFormat = 'colored-text';\n\n  return _Log;\n};\n\nvar RunLog = function () {\n  var self = this;\n\n  self.rawLogs = false;\n\n  self.messages = []; // list of log objects\n  self.maxLength = 100;\n\n  // If non-null, the last thing logged was \"server restarted\"\n  // message, and the value will be the number of consecutive such\n  // messages that have been logged with no other intervening messages\n  self.consecutiveRestartMessages = null;\n  self.consecutiveClientRestartMessages = null;\n\n  // If non-null, the last thing that was logged was a temporary\n  // message (with a carriage return but no newline), and this is its\n  // length.\n  self.temporaryMessageLength = null;\n};\n\n_.extend(RunLog.prototype, {\n  _record: function (msg) {\n    var self = this;\n\n    self.messages.push(msg);\n    if (self.messages.length > self.maxLength) {\n      self.messages.shift();\n    }\n  },\n\n  _clearSpecial: function () {\n    var self = this;\n\n    if (self.consecutiveRestartMessages) {\n      self.consecutiveRestartMessages = null;\n      Console.info();\n    }\n\n    if (self.consecutiveClientRestartMessages) {\n      self.consecutiveClientRestartMessages = null;\n      Console.info();\n    }\n\n    if (self.temporaryMessageLength) {\n      var spaces = new Array(self.temporaryMessageLength + 1).join(' ');\n      process.stdout.write(spaces + Console.CARRIAGE_RETURN);\n      self.temporaryMessageLength = null;\n    }\n  },\n\n  setRawLogs: function (rawLogs) {\n    this.rawLogs = !!rawLogs;\n  },\n\n  logAppOutput: function (line, isStderr) {\n    var self = this;\n\n    var Log = getLoggingPackage();\n\n    var obj = (isStderr ?\n               Log.objFromText(line, { level: 'warn', stderr: true }) :\n               Log.parse(line) || Log.objFromText(line));\n    self._record(obj);\n\n    self._clearSpecial();\n    if (self.rawLogs) {\n      Console[isStderr ? \"rawError\" : \"rawInfo\"](line + \"\\n\");\n    } else {\n      // XXX deal with test server logging differently?!\n      return fiberHelpers.noYieldsAllowed(function() {\n        Console.rawInfo(Log.format(obj, { color: true }) + \"\\n\");\n      });\n    }\n  },\n\n  // Log the message.\n  //  msg: message\n  //  options:\n  //    - arrow: if true, preface with => and wrap accordingly.\n  log: function (msg, options) {\n    var self = this;\n    options = options || {};\n    var obj = {\n      time: new Date,\n      message: msg\n      // in the future, might want to add something else to\n      // distinguish messages from runner from message from the app,\n      // but for now, nothing would use it, so we'll keep it simple\n    };\n    self._record(obj);\n\n    self._clearSpecial();\n\n    // Process the options. By default, we want to wordwrap the message with\n    // Console.info. If we ask for raw output, then we don't want to do that. If\n    // we ask for an arrow, we want to wrap around with => as the bulletPoint.\n    Console[options.arrow ? 'arrowInfo' : 'info'](msg);\n  },\n\n  // Write a message to the terminal that will get overwritten by the\n  // next message logged. (Don't put it in the log that getLog\n  // returns.)\n  // XXX Maybe this should return an object that you have to pass to the\n  //     subsequent log call, and only such a log call will overwrite it (and an\n  //     intervening log call will cause this to stay on the screen)?\n  //     eg, a log call from the updater can interweave with the logTemporary\n  //     calls in run-all.js\n  logTemporary: function (msg) {\n    var self = this;\n\n    self._clearSpecial();\n    process.stdout.write(msg + Console.CARRIAGE_RETURN);\n    self.temporaryMessageLength = msg.length;\n  },\n\n  logRestart: function () {\n    var self = this;\n\n    if (self.consecutiveRestartMessages) {\n      // replace old message in place. this assumes that the new restart message\n      // is not shorter than the old one.\n      process.stdout.write(Console.CARRIAGE_RETURN);\n      self.messages.pop();\n      self.consecutiveRestartMessages ++;\n    } else {\n      self._clearSpecial();\n      self.consecutiveRestartMessages = 1;\n    }\n\n    var message = \"=> Meteor server restarted\";\n    if (self.consecutiveRestartMessages > 1) {\n      message += \" (x\" + self.consecutiveRestartMessages + \")\";\n    }\n    // no newline, so that we can overwrite it if we get another\n    // restart message right after this one\n    process.stdout.write(message);\n\n    self._record({\n      time: new Date,\n      message: message\n    });\n  },\n\n  logClientRestart: function () {\n    var self = this;\n\n    if (self.consecutiveClientRestartMessages) {\n      // replace old message in place. this assumes that the new restart message\n      // is not shorter than the old one.\n      process.stdout.write(Console.CARRIAGE_RETURN);\n      self.messages.pop();\n      self.consecutiveClientRestartMessages ++;\n    } else {\n      self._clearSpecial();\n      self.consecutiveClientRestartMessages = 1;\n    }\n\n    var message = \"=> Client modified -- refreshing\";\n    if (self.consecutiveClientRestartMessages > 1) {\n      message += \" (x\" + self.consecutiveClientRestartMessages + \")\";\n    }\n    // no newline, so that we can overwrite it if we get another\n    // restart message right after this one\n    process.stdout.write(message);\n\n    self._record({\n      time: new Date,\n      message: message\n    });\n  },\n\n  finish: function () {\n    var self = this;\n\n    self._clearSpecial();\n  },\n\n  clearLog: function () {\n    var self = this;\n    self.messages = [];\n  },\n\n  getLog: function () {\n    var self = this;\n    return self.messages;\n  }\n});\n\n// Create a singleton instance of RunLog. Expose its public methods on the\n// object you get with require('./run-log.js').\nvar runLogInstance = new RunLog;\n_.each(\n  ['log', 'logTemporary', 'logRestart', 'logClientRestart', 'logAppOutput',\n   'setRawLogs', 'finish', 'clearLog', 'getLog'],\n  function (method) {\n    exports[method] = _.bind(runLogInstance[method], runLogInstance);\n  });\n"
  },
  {
    "path": "tools/runners/run-mongo.js",
    "content": "var files = require('../fs/files.js');\nvar utils = require('../utils/utils.js');\nvar mongoExitCodes = require('../utils/mongo-exit-codes.js');\nvar fiberHelpers = require('../utils/fiber-helpers.js');\nvar runLog = require('./run-log.js');\nvar child_process = require('child_process');\n\nvar _ = require('underscore');\nvar isopackets = require('../tool-env/isopackets.js');\n\n// Given a Mongo URL, open an interative Mongo shell on this terminal\n// on that database.\nvar runMongoShell = function (url) {\n  var mongoPath = files.pathJoin(files.getDevBundle(), 'mongodb', 'bin', 'mongo');\n  // XXX mongo URLs are not real URLs (notably, the comma-separation for\n  // multiple hosts). We've had a little better luck using the mongodb-uri npm\n  // package.\n  var mongoUrl = require('url').parse(url);\n  var auth = mongoUrl.auth && mongoUrl.auth.split(':');\n  var ssl = require('querystring').parse(mongoUrl.query).ssl === \"true\";\n\n  var args = [];\n  if (ssl) {\n    args.push('--ssl');\n  }\n  if (auth) {\n    args.push('-u', auth[0]);\n  }\n  if (auth) {\n    args.push('-p', auth[1]);\n  }\n  args.push(mongoUrl.hostname + ':' + mongoUrl.port + mongoUrl.pathname);\n\n  child_process.spawn(files.convertToOSPath(mongoPath),\n    args, { stdio: 'inherit' });\n};\n\n// Start mongod with a dummy replSet and wait for it to listen.\nvar spawnMongod = function (mongodPath, port, dbPath, replSetName) {\n  var child_process = require('child_process');\n\n  mongodPath = files.convertToOSPath(mongodPath);\n  dbPath = files.convertToOSPath(dbPath);\n\n  return child_process.spawn(mongodPath, [\n      // nb: cli-test.sh and findMongoPids make strong assumptions about the\n      // order of the arguments! Check them before changing any arguments.\n      '--bind_ip', '127.0.0.1',\n      '--smallfiles',\n      '--port', port,\n      '--dbpath', dbPath,\n      // Use an 8MB oplog rather than 256MB. Uses less space on disk and\n      // initializes faster. (Not recommended for production!)\n      '--oplogSize', '8',\n      '--replSet', replSetName\n  ], {\n    // Apparently in some contexts, Mongo crashes if your locale isn't set up\n    // right. I wasn't able to reproduce it, but many people on #4019\n    // were. Let's default a couple environment variables to English UTF-8 if\n    // they aren't set already. If these few aren't good enough, we'll at least\n    // detect the locale error and print a link to #4019 (look for\n    // `detectedErrors.badLocale` below).\n    env: _.extend({\n      LANG: 'en_US.UTF-8',\n      LC_ALL: 'en_US.UTF-8'\n    }, process.env)\n  });\n};\n\n// Find all running Mongo processes that were started by this program\n// (even by other simultaneous runs of this program). If passed,\n// dbDir and port act as filters on the list of running mongos.\n//\n// Yields. Returns an array of objects with keys pid, port, dbDir.\nvar findMongoPids;\nif (process.platform === 'win32') {\n  // Windows doesn't have a ps equivalent that (reliably) includes the command\n  // line, so approximate using the combined output of tasklist and netstat.\n  findMongoPids = function (dbDir_unused, port) {\n    var promise = fiberHelpers.makeFulfillablePromise();\n\n    child_process.exec('tasklist /fi \"IMAGENAME eq mongod.exe\"',\n      function (error, stdout, stderr) {\n        if (error) {\n          var additionalInfo = JSON.stringify(error);\n          if (error.code === 'ENOENT') {\n            additionalInfo = \"tasklist wasn't found on your system, it usually can be found at C:\\\\Windows\\\\System32\\\\.\";\n          }\n          promise.reject(\n            new Error(\"Couldn't run tasklist.exe: \" + additionalInfo)\n          );\n          return;\n        } else {\n          // Find the pids of all mongod processes\n          var mongo_pids = [];\n          _.each(stdout.split('\\n'), function (line) {\n            var m = line.match(/^mongod.exe\\s+(\\d+) /);\n            if (m) {\n              mongo_pids[m[1]] = true;\n            }\n          });\n\n          // Now get the corresponding port numbers\n          child_process.exec(\n            'netstat -ano',\n            {maxBuffer: 1024 * 1024 * 10},\n            function (error, stdout, stderr) {\n            if (error) {\n              promise.reject(\n                new Error(\"Couldn't run netstat -ano: \" +\n                          JSON.stringify(error))\n              );\n              return;\n            } else {\n              var pids = [];\n              _.each(stdout.split('\\n'), function (line) {\n                var m = line.match(/^\\s*TCP\\s+\\S+:(\\d+)\\s+\\S+\\s+LISTENING\\s+(\\d+)/);\n                if (m) {\n                  var found_pid =  parseInt(m[2], 10);\n                  var found_port = parseInt(m[1], 10);\n\n                  // We can't check the path app_dir so assume it always matches\n                  if (mongo_pids[found_pid] && (!port || port === found_port)) {\n                    // Note that if the mongo rest interface is enabled the\n                    // initial port + 1000 is also likely to be open.\n                    // So remove the pid so we only match it once.\n                    delete mongo_pids[found_pid];\n                    pids.push({\n                      pid: found_pid,\n                      port: found_port,\n                      app_dir: null});\n                  }\n                }\n              });\n\n              promise.resolve(pids);\n            }\n          });\n        }\n      });\n\n    return promise.await();\n  };\n} else {\n  findMongoPids = function (dbDir, port) {\n    var promise = fiberHelpers.makeFulfillablePromise();\n\n    // 'ps ax' should be standard across all MacOS and Linux.\n    // However, ps on OS X corrupts some non-ASCII characters in arguments,\n    // such as т (CYRILLIC SMALL LETTER TE), leading to this function\n    // failing to properly match pathnames with those characters.  #3999\n    //\n    // pgrep appears to do a better job (and has output that is roughly\n    // similar; it lacks a few fields that we don't care about).  Plus,\n    // it can do some of the grepping for us.\n    //\n    // However, 'pgrep' only started shipping with OS X 10.8 (and may be less\n    // common on Linux too), so we check to see if it exists and fall back to\n    // 'ps' if we can't find it.\n    //\n    // We avoid using pgrep on Linux, because some versions of Linux pgrep\n    // require you to pass -a/--list-full to include the arguments in the\n    // output, and other versions fail if you pass that option. We have not\n    // observed the Unicode corruption on Linux, so using ps ax there is fine.\n    var psScript = 'ps ax';\n    if (process.platform === 'darwin') {\n      psScript =\n        'if type pgrep >/dev/null 2>&1; then ' +\n        // -lf means to display and match against full argument lists.\n        // pgrep exits 1 if no processes match the argument; we're OK\n        // considering this as a success, but we don't want other errors\n        // to be ignored.  Note that this is sh not bash, so we can't use\n        // [[.\n        'pgrep -lf mongod; test \"$?\" -eq 0 -o \"$?\" -eq 1;' +\n        'else ps ax; fi';\n    }\n\n    child_process.exec(\n      psScript,\n      // we don't want this to randomly fail just because you're running lots of\n      // processes. 10MB should be more than ps ax will ever spit out; the default\n      // is 200K, which at least one person hit (#2158).\n      {maxBuffer: 1024 * 1024 * 10},\n      function (error, stdout, stderr) {\n        if (error) {\n          promise.reject(\n            new Error(\"Couldn't run ps ax: \" +\n                      JSON.stringify(error) + \"; \" +\n                      error.message)\n          );\n          return;\n        }\n\n        var ret = [];\n        _.each(stdout.split('\\n'), function (line) {\n          // Matches mongos we start. Note that this matches\n          // 'fake-mongod' (our mongod stub for automated tests) as well\n          // as 'mongod'.\n          var m = line.match(/^\\s*(\\d+).+mongod .+--port (\\d+) --dbpath (.+(?:\\/|\\\\)db)/);\n          if (m && m.length === 4) {\n            var foundPid =  parseInt(m[1], 10);\n            var foundPort = parseInt(m[2], 10);\n            var foundPath = m[3];\n\n            if ( (! port || port === foundPort) &&\n                 (! dbDir || dbDir === foundPath)) {\n              ret.push({\n                pid: foundPid,\n                port: foundPort,\n                dbDir: foundPath\n              });\n            }\n          }\n        });\n\n        promise.resolve(ret);\n      });\n\n    return promise.await();\n  };\n}\n\n// See if mongo is running already. Yields. Returns the port that\n// mongo is running on or null if mongo is not running.\nvar findMongoPort = function (dbDir) {\n  var pids = findMongoPids(dbDir);\n\n  if (pids.length !== 1) {\n    return null;\n  }\n\n  var pid = pids[0].pid;\n  try {\n    process.kill(pid, 0); // make sure it is still alive\n  } catch (e) {\n    return null;\n  }\n\n  return pids[0].port;\n};\n\n// XXX actually -- the code below is probably more correct than the code we\n// have above for non-Windows platforms (since that code relies on\n// `findMongoPids`). But changing this a few days before the 1.1 release\n// seemed too bold. But if you're changing code around here, consider using\n// the implementation below on non-Windows platforms as well.\nif (process.platform === 'win32') {\n  // On Windows, finding the Mongo pid, checking it and extracting the port\n  // is often unreliable (XXX reliable in what specific way?). There is an\n  // easier way to find the port of running Mongo: look it up in a METEOR-\n  // PORT file that we generate when running. This may result into problems\n  // where we try to connect to a mongod that is not running, or a wrong\n  // mongod if our current app is not running but there is a left-over file\n  // lying around. This still can be better than always failing to connect.\n  findMongoPort = function (dbPath) {\n    var mongoPort = null;\n\n    var portFile = files.pathJoin(dbPath, 'METEOR-PORT');\n    if (files.exists(portFile)) {\n      mongoPort = files.readFile(portFile, 'utf8').replace(/\\s/g, '');\n    }\n\n    // Now, check if there really is a Mongo server running on this port.\n    // (The METEOR-PORT file may point to an old Mongo server that's now\n    // stopped)\n    var net = require('net');\n\n    return new Promise(resolve => {\n      var client = net.connect({\n        port: mongoPort\n      }, () => {\n        // The server is running.\n        client.end();\n        resolve(mongoPort);\n      });\n      client.on('error', () => resolve(null));\n    }).await();\n  }\n}\n\n\n// Kill any mongos running on 'port'. Yields, and returns once they\n// are all dead. Throws an exception on failure.\n//\n// This is a big hammer for dealing with still running mongos, but\n// smaller hammers have failed before and it is getting tiresome.\nvar findMongoAndKillItDead = function (port, dbPath) {\n  var pids = findMongoPids(null, port);\n\n  // Go through the list serially. There really should only ever be\n  // at most one but we're not taking any chances.\n  _.each(pids, function (processInfo) {\n    var pid = processInfo.pid;\n\n    // Send kill attempts and wait. First a SIGINT, then if it isn't\n    // dead within 2 sec, SIGKILL. Check every 100ms to see if it's\n    // dead.\n    for (var attempts = 1; attempts <= 40; attempts ++) {\n      var signal = 0;\n      if (attempts === 1) {\n        signal = 'SIGINT';\n      } else if (attempts === 20 || attempts === 30) {\n        signal = 'SIGKILL';\n      }\n\n      try {\n        process.kill(pid, signal);\n      } catch (e) {\n        // it's dead. on to the next one\n        return;\n      }\n\n      utils.sleepMs(100);\n    }\n\n    // give up after 4 seconds.\n    // XXX should actually catch this higher up and print a nice\n    // error. foreseeable conditions should never result in exceptions\n    // for the user.\n    throw new Error(\"Can't kill running mongo (pid \" + pid + \").\");\n  });\n\n  // If we had to kill mongod with SIGKILL, or on Windows where all calls to\n  // `process.kill` work like SIGKILL, mongod will not have the opportunity to\n  // close gracefully. Delete a lock file that may have been left over.\n  var mongodLockFile = files.pathJoin(dbPath, \"mongod.lock\");\n  if (files.exists(mongodLockFile)) {\n    files.unlink(mongodLockFile)\n  }\n};\n\nvar StoppedDuringLaunch = function () {};\n\n// Starts a single instance of mongod, and configures it properly as a singleton\n// replica set. Yields.  Returns once the mongod is successfully listening (or\n// the process exited).\n//\n// Takes an onExit handler, which will be invoked when the process exits (which\n// may be before or after this function returns depending on whether or not it\n// ever successfully started).\n//\n// If the 'multiple' option is set, it actually sets up three mongod instances\n// (launching the second and third on the next two ports after the specified\n// port). In this case, if any of the three instances exit for any reason, all\n// are killed (and onExit is then invoked). Also, the entirety of all three\n// databases is deleted before starting up.  This is mode intended for testing\n// mongo failover, not for normal development or production use.\nvar launchMongo = function (options) {\n  var onExit = options.onExit || function () {};\n\n  var noOplog = false;\n  var mongod_path = files.pathJoin(\n    files.getDevBundle(), 'mongodb', 'bin', 'mongod');\n  var replSetName = 'meteor';\n\n  // Automated testing: If this is set, instead of starting mongod, we\n  // start our stub (fake-mongod) which can then be remote-controlled\n  // by the test.\n  if (process.env.METEOR_TEST_FAKE_MONGOD_CONTROL_PORT) {\n    if (options.multiple) {\n      throw Error(\"Can't specify multiple with fake mongod\");\n    }\n\n    var fakeMongodCommand =\n      process.platform === \"win32\" ? \"fake-mongod.bat\" : \"fake-mongod\";\n    mongod_path = files.pathJoin(\n      files.getCurrentToolsDir(), 'tools',\n      'tests', 'fake-mongod', fakeMongodCommand);\n\n    // oplog support requires sending admin commands to mongod, so\n    // it'd be hard to make fake-mongod support it.\n    noOplog = true;\n  }\n\n  var subHandles = [];\n  var stopped = false;\n  var handle = {};\n  var stopPromise = new Promise((resolve, reject) => {\n    handle.stop = function () {\n      if (stopped) {\n        return;\n      }\n      stopped = true;\n      _.each(subHandles, function (handle) {\n        handle.stop();\n      });\n\n      if (options.onStopped) {\n        options.onStopped();\n      }\n\n      reject(new StoppedDuringLaunch);\n    };\n  });\n\n  var yieldingMethod = function (object, methodName, ...args) {\n    return Promise.race([\n      stopPromise,\n      new Promise((resolve, reject) => {\n        object[methodName](...args, (err, res) => {\n          err ? reject(err) : resolve(res);\n        });\n      })\n    ]).await();\n  };\n\n  var launchOneMongoAndWaitForReadyForInitiate = function (dbPath, port,\n                                                           portFile) {\n    files.mkdir_p(dbPath, 0o755);\n\n    var proc = null;\n\n    if (options.allowKilling) {\n      findMongoAndKillItDead(port, dbPath);\n    }\n\n    if (options.multiple) {\n      // This is only for testing, so we're OK with incurring the replset\n      // setup on each startup.\n      files.rm_recursive(dbPath);\n      files.mkdir_p(dbPath, 0o755);\n    } else if (portFile) {\n      var portFileExists = false;\n      var matchingPortFileExists = false;\n      try {\n        matchingPortFileExists = +(files.readFile(portFile)) === port;\n        portFileExists = true;\n      } catch (e) {\n        if (!e || e.code !== 'ENOENT') {\n          throw e;\n        }\n      }\n\n      // If this is the first time we're using this DB, or we changed port since\n      // the last time, then we want to destroy any existing replSet\n      // configuration and create a new one. First we delete the \"local\"\n      // database if it exists. (It's a pain and slow to change the port in an\n      // existing replSet configuration. It's also a little slow to initiate a\n      // new replSet, thus the attempt to not do it unless the port changes.)\n      //\n      // In the \"multiple\" case, we just wipe out the entire database and incur\n      // the cost, because this won't affect normal users running meteor.\n      if (!matchingPortFileExists) {\n        // Delete the port file if it exists, so we don't mistakenly believe\n        // that the DB is still configured.\n        if (portFileExists) {\n          files.unlink(portFile);\n        }\n\n        try {\n          var dbFiles = files.readdir(dbPath);\n        } catch (e) {\n          if (!e || e.code !== 'ENOENT') {\n            throw e;\n          }\n        }\n        _.each(dbFiles, function (dbFile) {\n          if (/^local\\./.test(dbFile)) {\n            files.unlink(files.pathJoin(dbPath, dbFile));\n          }\n        });\n      }\n    }\n\n    // Let's not actually start a process if we yielded (eg during\n    // findMongoAndKillItDead) and we decided to stop in the middle (eg, because\n    // we're in multiple mode and another process exited).\n    if (stopped) {\n      return;\n    }\n\n    proc = spawnMongod(mongod_path, port, dbPath, replSetName);\n\n    subHandles.push({\n      stop: function () {\n        if (proc) {\n          proc.removeListener('exit', procExitHandler);\n          proc.kill('SIGINT');\n          proc = null;\n        }\n      }\n    });\n\n    var procExitHandler = fiberHelpers.bindEnvironment(function (code, signal) {\n      // Defang subHandle.stop().\n      proc = null;\n\n      // Kill any other processes too. This will also remove\n      // procExitHandler from the other processes, so onExit will only be called\n      // once.\n      handle.stop();\n\n      // Invoke the outer onExit callback.\n      onExit(code, signal, stderrOutput, detectedErrors);\n    });\n    proc.on('exit', procExitHandler);\n\n    var listening = false;\n    var replSetReadyToBeInitiated = false;\n    var replSetReady = false;\n\n    var maybeReadyToTalk;\n    var readyToTalkPromise = new Promise(function (resolve) {\n      maybeReadyToTalk = function () {\n        if (resolve &&\n            listening &&\n            (noOplog || replSetReadyToBeInitiated || replSetReady)) {\n          proc.stdout.removeListener('data', stdoutOnData);\n          resolve();\n          resolve = null;\n        }\n      };\n    });\n\n    var stopOrReadyPromise = Promise.race([\n      stopPromise,\n      readyToTalkPromise,\n    ]);\n\n    var detectedErrors = {};\n    var stdoutOnData = fiberHelpers.bindEnvironment(function (data) {\n      // note: don't use \"else ifs\" in this, because 'data' can have multiple\n      // lines\n      if (/config from self or any seed \\(EMPTYCONFIG\\)/.test(data)) {\n        replSetReadyToBeInitiated = true;\n        maybeReadyToTalk();\n      }\n\n      if (/ \\[initandlisten\\] waiting for connections on port/.test(data)) {\n        listening = true;\n        maybeReadyToTalk();\n      }\n\n      if (/ \\[rsMgr\\] replSet (PRIMARY|SECONDARY)/.test(data)) {\n        replSetReady = true;\n        maybeReadyToTalk();\n      }\n\n      if (/Insufficient free space/.test(data)) {\n        detectedErrors.freeSpace = true;\n      }\n\n      if (/Invalid or no user locale set/.test(data)) {\n        detectedErrors.badLocale = true;\n      }\n    });\n    proc.stdout.setEncoding('utf8');\n    proc.stdout.on('data', stdoutOnData);\n\n    var stderrOutput = '';\n    proc.stderr.setEncoding('utf8');\n    proc.stderr.on('data', function (data) {\n      stderrOutput += data;\n    });\n\n    stopOrReadyPromise.await();\n  };\n\n\n  var initiateReplSetAndWaitForReady = function () {\n    try {\n      // Load mongo so we'll be able to talk to it.\n      var mongoNpmModule =\n            isopackets.load('mongo')['npm-mongo'].NpmModuleMongodb;\n\n      // Connect to the intended primary and start a replset.\n      var db = new mongoNpmModule.Db(\n        'meteor',\n        new mongoNpmModule.Server('127.0.0.1', options.port, {poolSize: 1}),\n        {safe: true});\n      yieldingMethod(db, 'open');\n      if (stopped) {\n        return;\n      }\n      var configuration = {\n        _id: replSetName,\n        members: [{_id: 0, host: '127.0.0.1:' + options.port, priority: 100}]\n      };\n      if (options.multiple) {\n        // Add two more members: one of which should start as secondary but\n        // could in theory become primary, and one of which can never be\n        // primary.\n        configuration.members.push({\n          _id: 1, host: '127.0.0.1:' + (options.port + 1), priority: 5\n        });\n        configuration.members.push({\n          _id: 2, host: '127.0.0.1:' + (options.port + 2), priority: 0\n        });\n      }\n\n      var initiateResult = yieldingMethod(\n        db.admin(), 'command', {replSetInitiate: configuration});\n      if (stopped) {\n        return;\n      }\n      // why this isn't in the error is unclear.\n      if (initiateResult && initiateResult.documents\n          && initiateResult.documents[0]\n          && initiateResult.documents[0].errmsg) {\n        var err = initiateResult.documents[0].errmsg;\n        if (err !== \"already initialized\") {\n          throw Error(\"rs.initiate error: \" +\n                      initiateResult.documents[0].errmsg);\n        }\n      }\n      // XXX timeout eventually?\n      while (!stopped) {\n        var status = yieldingMethod(db.admin(), 'command',\n                                    {replSetGetStatus: 1});\n        if (!(status && status.documents && status.documents[0])) {\n          throw status;\n        }\n        status = status.documents[0];\n        if (!status.ok) {\n          if (status.startupStatus === 6) {  // \"SOON\"\n            utils.sleepMs(20);\n            continue;\n          }\n          throw status.errmsg;\n        }\n        // See http://docs.mongodb.org/manual/reference/replica-states/\n        // for information about the various states.\n\n        // Are any of the members starting up or recovering?\n        if (_.any(status.members, function (member) {\n          return member.stateStr === 'STARTUP' ||\n            member.stateStr === 'STARTUP2' ||\n            member.stateStr === 'RECOVERING';\n        })) {\n          utils.sleepMs(20);\n          continue;\n        }\n\n        // Is the intended primary currently a secondary? (It passes through\n        // that phase briefly.)\n\n        if (status.members[0].stateStr === 'SECONDARY') {\n          utils.sleepMs(20);\n          continue;\n        }\n\n        // Anything else for the intended primary is probably an error.\n        if (status.members[0].stateStr !== 'PRIMARY') {\n          throw Error(\"Unexpected Mongo status: \" + JSON.stringify(status));\n        }\n\n        // Anything but secondary for the other members is probably an error.\n        for (var i = 1; i < status.members.length; ++i) {\n          if (status.members[i].stateStr !== 'SECONDARY') {\n            throw Error(\"Unexpected Mongo secondary status: \" +\n                        JSON.stringify(status));\n          }\n        }\n\n        break;\n      }\n\n      db.close(true /* means \"the app is closing the connection\" */);\n    } catch (e) {\n      // If the process has exited, we're doing another form of error\n      // handling. No need to throw random low-level errors farther.\n      if (!stopped || (e instanceof StoppedDuringLaunch)) {\n        throw e;\n      }\n    }\n  };\n\n  try {\n    if (options.multiple) {\n      var dbBasePath = files.pathJoin(options.projectLocalDir, 'dbs');\n      _.each(_.range(3), function (i) {\n        // Did we get stopped (eg, by one of the processes exiting) by now? Then\n        // don't start anything new.\n        if (stopped) {\n          return;\n        }\n        var dbPath = files.pathJoin(options.projectLocalDir, 'dbs', ''+i);\n        launchOneMongoAndWaitForReadyForInitiate(dbPath, options.port + i);\n      });\n      if (!stopped) {\n        initiateReplSetAndWaitForReady();\n      }\n    } else {\n      var dbPath = files.pathJoin(options.projectLocalDir, 'db');\n      var portFile = !noOplog && files.pathJoin(dbPath, 'METEOR-PORT');\n      launchOneMongoAndWaitForReadyForInitiate(dbPath, options.port, portFile);\n      if (!stopped && !noOplog) {\n        initiateReplSetAndWaitForReady();\n        if (!stopped) {\n          // Write down that we configured the database properly.\n          files.writeFile(portFile, options.port);\n        }\n      }\n    }\n  } catch (e) {\n    if (!(e instanceof StoppedDuringLaunch)) {\n      throw e;\n    }\n  }\n\n  if (stopped) {\n    return null;\n  }\n\n  return handle;\n};\n\n// This runs a Mongo process and restarts it whenever it fails. If it\n// restarts too often, we give up on restarting it, diagnostics are\n// logged, and onFailure is called.\n//\n// options: projectLocalDir, port, onFailure, multiple\nvar MongoRunner = function (options) {\n  var self = this;\n  self.projectLocalDir = options.projectLocalDir;\n  self.port = options.port;\n  self.onFailure = options.onFailure;\n  self.multiple = options.multiple;\n\n  self.handle = null;\n  self.shuttingDown = false;\n  self.resolveStartupPromise = null;\n\n  self.errorCount = 0;\n  self.errorTimer = null;\n  self.restartTimer = null;\n  self.firstStart = true;\n  self.suppressExitMessage = false;\n};\n\nvar MRp = MongoRunner.prototype;\n\n_.extend(MRp, {\n  // Blocks (yields) until the server has started for the first time and\n  // is accepting connections. (It might subsequently die and be\n  // restarted; we won't tell you about that.)\n  //\n  // If the server fails to start for the first time (after a few\n  // restarts), we'll print a message and give up.\n  start: function () {\n    var self = this;\n\n    if (self.handle) {\n      throw new Error(\"already running?\");\n    }\n\n    self._startOrRestart();\n\n    // Did we properly start up? Great!\n    if (self.handle) {\n      return;\n    }\n\n    // Are we shutting down? OK.\n    if (self.shuttingDown) {\n      return;\n    }\n\n    // Otherwise, wait for a successful _startOrRestart, or a failure.\n    if (! self.resolveStartupPromise) {\n      new Promise(function (resolve) {\n        self.resolveStartupPromise = resolve;\n      }).await();\n    }\n  },\n\n  // Tries to launch Mongo once.  It returns when either (a) Mongo is listening\n  // or (b) mongod exited before it got to the point of listening.\n  //\n  // (To be specific: in non-multiple mode, this means that the single mongod is\n  // listening and the primary, or that the single mongod died. In multiple\n  // mode, it means that the first mongod is listening and is primary and the\n  // other mongods are listening and are secondary, or that any mongod died (and\n  // it tried to kill the others).)\n  //\n  // In case (a), self.handle will be the handle returned from launchMongo; in\n  // case (b) self.handle will be null.\n  _startOrRestart: function () {\n    var self = this;\n\n    if (self.handle) {\n      throw new Error(\"already running?\");\n    }\n\n    var allowKilling = self.multiple || self.firstStart;\n    self.firstStart = false;\n    if (! allowKilling) {\n      // If we're not going to try to kill an existing mongod first, then we\n      // shouldn't annoy the user by telling it that we couldn't start up.\n      self.suppressExitMessage = true;\n    }\n\n    self.handle = launchMongo({\n      projectLocalDir: self.projectLocalDir,\n      port: self.port,\n      multiple: self.multiple,\n      allowKilling: allowKilling,\n      onExit: _.bind(self._exited, self),\n      onStopped() {\n        self.suppressExitMessage = false;\n      },\n    });\n\n    // It has successfully started up, so if it exits after this point, that\n    // actually is an interesting fact and we shouldn't suppress it.\n    self.suppressExitMessage = false;\n\n    if (self.handle) {\n      self._allowStartupToReturn();\n    }\n  },\n\n  _exited: function (code, signal, stderr, detectedErrors) {\n    var self = this;\n\n    self.handle = null;\n\n    // If Mongo exited because (or rather, anytime after) we told it\n    // to exit, great, nothing to do. Otherwise, we'll print an error\n    // and try to restart.\n    if (self.shuttingDown) {\n      return;\n    }\n\n    // Only print an error if we tried to kill Mongo and something went\n    // wrong. If we didn't try to kill Mongo, we'll do that on the next\n    // restart. Not killing it on the first try is important for speed,\n    // since findMongoAndKillItDead is a very slow operation.\n    if (! self.suppressExitMessage) {\n      // Print the last 20 lines of stderr.\n      runLog.log(\n        stderr.split('\\n').slice(-20).join('\\n') +\n          \"Unexpected mongo exit code \" + code +\n          (self.multiple ? \".\" : \". Restarting.\"));\n    }\n\n    // If we're in multiple mode, we never try to restart. That's to keep the\n    // test-only multiple code simple.\n    if (self.multiple) {\n      self._fail();\n      return;\n    }\n\n    // We'll restart it up to 3 times in a row. The counter is reset\n    // when 5 seconds goes without a restart. (Note that by using a\n    // timer instead of looking at the current date, we avoid getting\n    // confused by time changes.)\n    self.errorCount ++;\n    if (self.errorTimer) {\n      clearTimeout(self.errorTimer);\n    }\n    self.errorTimer = setTimeout(function () {\n      self.errorTimer = null;\n      self.errorCount = 0;\n    }, 5000);\n\n    if (self.errorCount < 3) {\n      // Wait a second, then restart.\n      self.restartTimer = setTimeout(fiberHelpers.bindEnvironment(function () {\n        self.restartTimer = null;\n        self._startOrRestart();\n      }), 1000);\n      return;\n    }\n\n    // Too many restarts, too quicky. It's dead. Print friendly\n    // diagnostics and give up.\n    var explanation = mongoExitCodes.Codes[code];\n    var message = \"Can't start Mongo server.\";\n\n    if (explanation && explanation.symbol === 'EXIT_UNCAUGHT' &&\n        detectedErrors.freeSpace) {\n      message += \"\\n\\n\" +\n        \"Looks like you are out of free disk space under .meteor/local.\";\n    } else if (explanation) {\n      message += \"\\n\" + explanation.longText;\n    }\n\n    if (explanation === mongoExitCodes.EXIT_NET_ERROR) {\n      message += \"\\n\\n\" +\n\"Check for other processes listening on port \" + self.port + \"\\n\" +\n\"or other Meteor instances running in the same project.\";\n    }\n\n    if (! explanation && /GLIBC/i.test(stderr)) {\n      message += \"\\n\\n\" +\n\"Looks like you are trying to run Meteor on an old Linux distribution.\\n\" +\n\"Meteor on Linux requires glibc version 2.9 or above. Try upgrading your\\n\" +\n\"distribution to the latest version.\";\n    }\n\n    if (detectedErrors.badLocale) {\n      message += \"\\n\\n\" +\n\"Looks like MongoDB doesn't understand your locale settings. See\\n\" +\n\"https://github.com/meteor/meteor/issues/4019 for more details.\";\n    }\n\n    runLog.log(message);\n    self._fail();\n  },\n\n  // Idempotent\n  stop: function () {\n    var self = this;\n\n    if (self.shuttingDown) {\n      return;\n    }\n\n    self.shuttingDown = true;\n\n    self.errorTimer && clearTimeout(self.errorTimer);\n    self.restartTimer && clearTimeout(self.restartTimer);\n\n    if (self.handle) {\n      self.handle.stop();\n      self.handle = null;\n    }\n  },\n\n  _allowStartupToReturn: function () {\n    var self = this;\n    if (self.resolveStartupPromise) {\n      var resolve = self.resolveStartupPromise;\n      self.resolveStartupPromise = null;\n      resolve();\n    }\n  },\n\n  _fail: function () {\n    var self = this;\n    self.stop();\n    self.onFailure && self.onFailure();\n    self._allowStartupToReturn();\n  },\n\n  _mongoHosts: function () {\n    var self = this;\n    var ports = [self.port];\n    if (self.multiple) {\n      ports.push(self.port + 1, self.port + 2);\n    }\n    return _.map(ports, function (port) {\n      return \"127.0.0.1:\" + port;\n    }).join(\",\");\n  },\n\n  mongoUrl: function () {\n    var self = this;\n    return \"mongodb://\" + self._mongoHosts() + \"/meteor\";\n  },\n\n  oplogUrl: function () {\n    var self = this;\n    return \"mongodb://\" + self._mongoHosts() + \"/local\";\n  }\n});\n\n\nexports.runMongoShell = runMongoShell;\nexports.findMongoPort = findMongoPort;\nexports.MongoRunner = MongoRunner;\nexports.findMongoAndKillItDead = findMongoAndKillItDead;\n"
  },
  {
    "path": "tools/runners/run-proxy.js",
    "content": "var _ = require('underscore');\nvar runLog = require('./run-log.js');\n\n// options: listenPort, proxyToPort, proxyToHost, onFailure\nvar Proxy = function (options) {\n  var self = this;\n\n  self.listenPort = options.listenPort;\n  self.listenHost = options.listenHost;\n  // note: run-all.js updates proxyToPort directly\n  self.proxyToPort = options.proxyToPort;\n  self.proxyToHost = options.proxyToHost || '127.0.0.1';\n  self.onFailure = options.onFailure || function () {};\n\n  self.mode = \"hold\";\n  self.httpQueue = []; // keys: req, res\n  self.websocketQueue = []; // keys: req, socket, head\n\n  self.proxy = null;\n  self.server = null;\n};\n\n_.extend(Proxy.prototype, {\n  // Start the proxy server, block (yield) until it is ready to go\n  // (actively listening on outer and proxying to inner), and then\n  // return.\n  start: function () {\n    var self = this;\n\n    if (self.server) {\n      throw new Error(\"already running?\");\n    }\n\n    self.started = false;\n\n    var http = require('http');\n    var net = require('net');\n    var httpProxy = require('http-proxy');\n\n    self.proxy = httpProxy.createProxyServer({\n      // agent is required to handle keep-alive, and http-proxy 1.0 is a little\n      // buggy without it: https://github.com/nodejitsu/node-http-proxy/pull/488\n      agent: new http.Agent({ maxSockets: 100 }),\n      xfwd: true\n    });\n\n    var server = self.server = http.createServer(function (req, res) {\n      // Normal HTTP request\n      self.httpQueue.push({ req: req, res: res });\n      self._tryHandleConnections();\n    });\n\n    self.server.on('upgrade', function (req, socket, head) {\n      // Websocket connection\n      self.websocketQueue.push({ req: req, socket: socket, head: head });\n      self._tryHandleConnections();\n    });\n\n    var allowStart;\n    var promise = new Promise(function (resolve) {\n      allowStart = resolve;\n    });\n\n    self.server.on('error', function (err) {\n      if (err.code === 'EADDRINUSE') {\n        var port = self.listenPort;\n        runLog.log(\n\"Can't listen on port \" + port + \". Perhaps another Meteor is running?\\n\" +\n\"\\n\" +\n\"Running two copies of Meteor in the same application directory\\n\" +\n\"will not work. If something else is using port \" + port + \", you can\\n\" +\n\"specify an alternative port with --port <port>.\");\n      } else if (self.listenHost &&\n                 (err.code === 'ENOTFOUND' || err.code === 'EADDRNOTAVAIL')) {\n        // This handles the case of \"entered a DNS name that's unknown\"\n        // (ENOTFOUND from getaddrinfo) and \"entered some random IP that we\n        // can't bind to\" (EADDRNOTAVAIL from listen).\n        runLog.log(\n\"Can't listen on host \" + self.listenHost + \" (\" + err.code + \" from \" +\n            err.syscall + \").\");\n\n      } else {\n        runLog.log('' + err);\n      }\n      self.onFailure();\n      allowStart();\n    });\n\n    // Don't crash if the app doesn't respond. instead return an error\n    // immediately. This shouldn't happen much since we try to not\n    // send requests if the app is down.\n    //\n    // Currently, this error is emitted if the proxy->server connection has an\n    // error (whether in HTTP or websocket proxying).  It is not emitted if the\n    // client->proxy connection has an error, though this may change; see\n    // discussion at https://github.com/nodejitsu/node-http-proxy/pull/488\n    self.proxy.on('error', function (err, req, resOrSocket) {\n      if (resOrSocket instanceof http.ServerResponse) {\n        if (!resOrSocket.headersSent) {\n          // Return a 503, but only if we haven't already written headers (or\n          // we'll get an ugly crash about rendering headers twice).  end()\n          // doesn't crash if called twice so we don't have to conditionalize\n          // that call.\n          resOrSocket.writeHead(503, {\n            'Content-Type': 'text/plain'\n          });\n        }\n        resOrSocket.end('Unexpected error.');\n      } else if (resOrSocket instanceof net.Socket) {\n        resOrSocket.end();\n      }\n    });\n\n    self.server.listen(self.listenPort, self.listenHost || '0.0.0.0', function () {\n      if (self.server) {\n        self.started = true;\n      } else {\n        // stop() got called while we were invoking listen! Close the server (we\n        // still have the var server). The rest of the cleanup shouldn't be\n        // necessary.\n        server.close();\n      }\n      allowStart();\n    });\n\n    promise.await();\n  },\n\n  // Idempotent.\n  stop: function () {\n    var self = this;\n\n    if (! self.server) {\n      return;\n    }\n\n    if (! self.started) {\n      // This probably means that we failed to listen. However, there could be a\n      // race condition and we could be in the middle of starting to listen! In\n      // that case, the listen callback will notice that we nulled out server\n      // here.\n      self.server = null;\n      return;\n    }\n\n    // This stops listening but allows existing connections to\n    // complete gracefully.\n    self.server.close();\n    self.server = null;\n\n    // It doesn't seem to be necessary to do anything special to\n    // destroy an httpProxy proxyserver object.\n    self.proxy = null;\n\n    // Drop any held connections.\n    _.each(self.httpQueue, function (c) {\n      c.res.statusCode = 500;\n      c.res.end();\n    });\n    self.httpQueue = [];\n\n    _.each(self.websocketQueue, function (c) {\n      c.socket.destroy();\n    });\n    self.websocketQueue = [];\n\n    self.mode = \"hold\";\n  },\n\n  _tryHandleConnections: function () {\n    var self = this;\n\n    function attempt(resOrSocket, fn) {\n      try {\n        return fn();\n      } catch (e) {\n        resOrSocket.writeHead(400, {\n          'Content-Type': 'text/plain'\n        });\n        resOrSocket.end(\"Bad request\\n\");\n      }\n    }\n\n    while (self.httpQueue.length) {\n      if (self.mode !== \"errorpage\" && self.mode !== \"proxy\") {\n        break;\n      }\n\n      var c = self.httpQueue.shift();\n      if (self.mode === \"errorpage\") {\n        showErrorPage(c.res);\n      } else {\n        attempt(c.res, () => self.proxy.web(c.req, c.res, {\n          target: 'http://' + self.proxyToHost + ':' + self.proxyToPort\n        }));\n      }\n    }\n\n    while (self.websocketQueue.length) {\n      if (self.mode !== \"proxy\") {\n        break;\n      }\n\n      var c = self.websocketQueue.shift();\n      attempt(c.socket, () => self.proxy.ws(c.req, c.socket, c.head, {\n        target: 'http://' + self.proxyToHost + ':' + self.proxyToPort\n      }));\n    }\n  },\n\n  // The proxy can be in one of three modes:\n  // - \"hold\": hold connections until the mode changes\n  // - \"proxy\": connections are proxied to the configured port\n  // - \"errorpage\": an error page is served to HTTP connections, and\n  //   websocket connections are held\n  //\n  // The initial mode is \"hold\".\n  setMode: function (mode) {\n    var self = this;\n    self.mode = mode;\n    self._tryHandleConnections();\n  }\n});\n\nfunction showErrorPage(res) {\n  // XXX serve an app that shows the logs nicely and that also\n  // knows how to reload when the server comes back up\n  res.writeHead(200, {'Content-Type': 'text/html'});\n  res.write(`\n<!DOCTYPE html>\n<html>\n  <head>\n    <title>App crashing</title>\n    <style type='text/css'>\n      body { margin: 0; }\n      h3 {\n        margin: 0;\n        font-family: sans-serif;\n        padding: 20px 10px 10px 10px;\n        background: #eee;\n      }\n      pre { margin: 20px; }\n    </style>\n  </head>\n\n  <body>\n    <h3>Your app is crashing. Here's the latest log:</h3>\n\n    <pre>`);\n\n      _.each(runLog.getLog(), function (item) {\n        res.write(escapeEntities(item.message) + \"\\n\");\n      });\n\n      res.write(`</pre>\n  </body>\n</html>`)\n\n  res.end();\n}\n\n// Copied from packages/blaze/preamble.js\nfunction escapeEntities(str) {\n  const escapeMap = {\n    \"<\": \"&lt;\",\n    \">\": \"&gt;\",\n    '\"': \"&quot;\",\n    \"'\": \"&#x27;\",\n    \"`\": \"&#x60;\", /* IE allows backtick-delimited attributes?? */\n    \"&\": \"&amp;\"\n  };\n\n  const escapeChar = function(c) {\n    return escapeMap[c];\n  };\n\n  return str.replace(/[&<>\"'`]/g, escapeChar);\n}\n\nexports.Proxy = Proxy;\n"
  },
  {
    "path": "tools/runners/run-selenium.js",
    "content": "var _ = require('underscore');\nvar Fiber = require('fibers');\nvar files = require('../fs/files.js');\nvar runLog = require('./run-log.js');\nvar utils = require('../utils/utils.js');\n\n// options: runner url browserId xunitOutputFile\nvar Selenium = function (options) {\n  var self = this;\n  options = options || {};\n\n  self.driver = null;\n  self.server = null;\n\n  self.browserId = options.browserId || 'xunit';\n  self.url = options.url || 'http://localhost:3000/' + self.browserId;\n  self.xunitOutputFile = options.xunitOutputFile || 'test-results.xml';\n\n  self.runner = options.runner;\n  self.browser = options.browser || 'chrome';\n\n  self.xunitLines = null;\n};\n\n\n// The magic prefix for special log output\n// Must match packages/test-in-console/driver.js\nvar MAGIC_PREFIX = '##_meteor_magic##';\n\n// For some reason, we can't see the console.log output\n// unless we 'flush' it by sending another console.log via execute()\n// Note that this is actually a magic message, so we get it echoed back to us;\n// that's not necessary for this to work, but it keeps the output clean for users.\nvar DUMMY_FLUSH = MAGIC_PREFIX + \"flush: flush\";\n\n_.extend(Selenium.prototype, {\n  // Start the selenium server, block (yield) until it is ready to go\n  // (actively listening on outer and proxying to inner), and then\n  // return.\n  start: function () {\n    var self = this;\n\n    if (self.server) {\n      throw new Error(\"already running?\");\n    }\n\n    self.xunitLines = [];\n\n    var webdriver = require('selenium-webdriver');\n\n    var capabilities;\n    var loggingPrefs;\n    if (self.browser === 'chrome') {\n      capabilities = webdriver.Capabilities.chrome();\n      loggingPrefs = {'browser': 'ALL'};\n    } else if (self.browser === 'firefox') {\n      capabilities = webdriver.Capabilities.firefox();\n      loggingPrefs = {'browser': 'ALL'};\n    } else {\n      throw new Error(\"Unhandled browser: \" + self.browser);\n    }\n\n    if (loggingPrefs) {\n      capabilities = capabilities.set('loggingPrefs', loggingPrefs);\n    }\n\n    var builder = new webdriver.Builder().withCapabilities(capabilities);\n    self.driver = builder.build();\n\n    Promise.await(self.driver.getSession());\n    Promise.await(self.driver.get(self.url));\n\n    Fiber(function () {\n      try {\n        self._pollLogs();\n      } catch (err) {\n        runLog.log(\"Log polling exited unexpectedly: \" + err);\n      }\n    }).run();\n  },\n\n  stop: function () {\n    var self = this;\n\n    if (! self.driver) {\n      return;\n    }\n\n    Promise.await(self.driver.close());\n    Promise.await(self.driver.quit());\n\n    self.driver = null;\n  },\n\n  _flushLogs: function () {\n    var self = this;\n    Promise.await(\n      self.driver.executeScript(\"console.log('\" + DUMMY_FLUSH + \"');\", [])\n    );\n  },\n\n  _getLogs: function () {\n    var self = this;\n\n    Promise.await(self.driver.manage().logs().get('browser'));\n  },\n\n  _gotStateDone: function () {\n    var self = this;\n\n    if (self.xunitOutputFile) {\n      runLog.log(\"Writing xunit output to: \" + self.xunitOutputFile);\n      files.writeFile(self.xunitOutputFile, self.xunitLines.join('\\n'));\n    }\n\n    if (self.runner) {\n      runLog.log(\"Shutting down in response to 'done' state\");\n      self.runner.stop();\n      process.exit(0);\n    }\n  },\n\n  _gotState: function (state) {\n    var self = this;\n\n    runLog.log(\"State -> \" + state);\n\n    if (state === \"done\") {\n      self._gotStateDone();\n    }\n  },\n\n  _gotMagicLog: function (facility, msg) {\n    var self = this;\n\n    if (facility === 'xunit') {\n      self.xunitLines.push(msg);\n    } else if (facility === 'state') {\n      self._gotState(msg);\n    } else if (facility === 'flush') {\n      // Ignore\n    } else {\n      runLog.log(\"Unknown magic: \" + facility + \": \" + msg);\n    }\n  },\n\n  _pollLogsOnce: function () {\n    var self = this;\n\n    self._flushLogs();\n    var logs = self._getLogs();\n    _.each(logs, function (log) {\n      var msg = log.message;\n      var regex = /([^\\s]*)\\s*([^\\s]*)\\s*(.*)/i;\n      var match = regex.exec(msg);\n      if (!match) {\n        runLog.log(\"Unknown console.log message format: \" + JSON.stringify(log));\n        return;\n      }\n      msg = match[3];\n      if (msg === DUMMY_FLUSH) {\n        return;\n      }\n      if (msg.indexOf(MAGIC_PREFIX) === 0) {\n        msg = msg.substring(MAGIC_PREFIX.length);\n        var colonIndex = msg.indexOf(': ');\n        if (colonIndex === -1) {\n          self._gotMagicLog('', msg);\n        } else {\n          var facility = msg.substring(0, colonIndex);\n          msg = msg.substring(colonIndex + 2);\n          self._gotMagicLog(facility, msg);\n        }\n      } else {\n        runLog.log(msg);\n      }\n    });\n  },\n\n  _pollLogs: function () {\n    var self = this;\n\n    while (self.driver) {\n      try {\n        self._pollLogsOnce();\n      } catch (err) {\n        runLog.log(\"Error reading console log: \" + err);\n      }\n      utils.sleepMs(1000);\n    }\n  },\n});\n\nexports.Selenium = Selenium;\n"
  },
  {
    "path": "tools/runners/run-updater.js",
    "content": "var _ = require('underscore');\nvar Fiber = require('fibers');\nvar fiberHelpers = require('../utils/fiber-helpers.js');\nvar Console = require('../console/console.js').Console;\n\nvar Updater = function () {\n  var self = this;\n  self.timer = null;\n};\n\n// XXX make it take a runLog?\n// XXX need to deal with updater writing messages (bypassing old\n// stdout interception.. maybe it should be global after all..)\n_.extend(Updater.prototype, {\n  start: function () {\n    var self = this;\n\n    if (self.timer) {\n      throw new Error(\"already running?\");\n    }\n\n    // Check every 3 hours. (Should not share buildmessage state with\n    // the main fiber.)\n    async function check() {\n      self._check();\n    }\n\n    self.timer = setInterval(check, 3 * 60 * 60 * 1000);\n\n    // Also start a check now, but don't block on it. (This should\n    // not share buildmessage state with the main fiber.)\n    check();\n  },\n\n  _check: function () {\n    var self = this;\n    var updater = require('../packaging/updater.js');\n    try {\n      updater.tryToDownloadUpdate({showBanner: true});\n    } catch (e) {\n      // oh well, this was the background. Only show errors if we are in debug\n      // mode.\n      Console.debug(\"Error inside updater.\");\n      Console.debug(e.stack);\n      return;\n    }\n  },\n\n  // Returns immediately. However if an update check is currently\n  // running it will complete in the background. Idempotent.\n  stop: function () {\n    var self = this;\n\n    if (self.timer) {\n      return;\n    }\n    clearInterval(self.timer);\n    self.timer = null;\n  }\n});\n\n\nexports.Updater = Updater;\n"
  },
  {
    "path": "tools/shell-client.js",
    "content": "var assert = require(\"assert\");\nvar fs = require(\"fs\");\nvar net = require(\"net\");\nvar eachline = require(\"eachline\");\nvar chalk = require(\"chalk\");\nvar EOL = require(\"os\").EOL;\nvar server = require('./static-assets/server/shell-server.js');\nvar EXITING_MESSAGE = server.EXITING_MESSAGE;\nvar getInfoFile = server.getInfoFile;\n\n// Invoked by the process running `meteor shell` to attempt to connect to\n// the server via the socket file.\nexports.connect = function connect(shellDir) {\n  new Client(shellDir).connect();\n};\n\nfunction Client(shellDir) {\n  var self = this;\n  assert.ok(self instanceof Client);\n\n  self.shellDir = shellDir;\n  self.exitOnClose = false;\n  self.firstTimeConnecting = true;\n  self.connected = false;\n  self.reconnectCount = 0;\n}\n\nvar Cp = Client.prototype;\n\nCp.reconnect = function reconnect(delay) {\n  var self = this;\n\n  // Display the \"Server unavailable\" warning only on the third attempt\n  // to reconnect, so it doesn't get shown for successful reconnects.\n  if (++self.reconnectCount === 3) {\n    console.error(chalk.yellow(\n      \"Server unavailable (waiting to reconnect)\"\n    ));\n  }\n\n  if (!self.reconnectTimer) {\n    self.reconnectTimer = setTimeout(function() {\n      delete self.reconnectTimer;\n      self.connect();\n    }, delay || 100);\n  }\n};\n\nCp.connect = function connect() {\n  var self = this;\n  var infoFile = getInfoFile(self.shellDir);\n\n  fs.readFile(infoFile, \"utf8\", function(err, json) {\n    if (err) {\n      return self.reconnect();\n    }\n\n    try {\n      var info = JSON.parse(json);\n    } catch (err) {\n      return self.reconnect();\n    }\n\n    if (info.status !== \"enabled\") {\n      if (self.firstTimeConnecting) {\n        return self.reconnect();\n      }\n\n      if (info.reason) {\n        console.error(info.reason);\n      }\n\n      console.error(EXITING_MESSAGE);\n      process.exit(0);\n    }\n\n    self.setUpSocket(\n      net.connect(info.port, \"127.0.0.1\"),\n      info.key\n    );\n  });\n};\n\nCp.setUpSocketForSingleUse = function (sock, key) {\n  sock.on(\"connect\", function () {\n    const inputBuffers = [];\n    process.stdin.on(\"data\", buffer => inputBuffers.push(buffer));\n    process.stdin.on(\"end\", () => {\n      sock.write(JSON.stringify({\n        evaluateAndExit: {\n          // Make sure the entire command is written as a string within a\n          // JSON object, so that the server can easily tell when it has\n          // received the whole command.\n          command: Buffer.concat(inputBuffers).toString(\"utf8\")\n        },\n        terminal: false,\n        key: key\n      }) + \"\\n\");\n    });\n  });\n\n  const outputBuffers = [];\n  sock.on(\"data\", buffer => outputBuffers.push(buffer));\n  sock.on(\"close\", function () {\n    var output = JSON.parse(Buffer.concat(outputBuffers));\n    if (output.error) {\n      console.error(output.error);\n      process.exit(output.code);\n    } else {\n      process.stdout.write(JSON.stringify(output.result) + \"\\n\");\n      process.exit(0);\n    }\n  });\n};\n\nCp.setUpSocket = function setUpSocket(sock, key) {\n  const self = this;\n\n  if (! process.stdin.isTTY) {\n    return self.setUpSocketForSingleUse(sock, key);\n  }\n\n  // Put STDIN into \"flowing mode\":\n  // http://nodejs.org/api/stream.html#stream_compatibility_with_older_node_versions\n  process.stdin.resume();\n\n  function onConnect() {\n    self.firstTimeConnecting = false;\n    self.reconnectCount = 0;\n    self.connected = true;\n\n    // Sending a JSON-stringified options object (even just an empty\n    // object) over the socket is required to start the REPL session.\n    sock.write(JSON.stringify({\n      terminal: ! process.env.EMACS,\n      key: key\n    }));\n\n    process.stderr.write(shellBanner());\n    process.stdin.pipe(sock);\n    if (process.stdin.setRawMode) { // https://github.com/joyent/node/issues/8204\n      process.stdin.setRawMode(true);\n    }\n  }\n\n  function onClose() {\n    tearDown();\n\n    // If we received the special EXITING_MESSAGE just before the socket\n    // closed, then exit the shell instead of reconnecting.\n    if (self.exitOnClose) {\n      process.exit(0);\n    } else {\n      self.reconnect();\n    }\n  }\n\n  function onError(err) {\n    tearDown();\n    self.reconnect();\n  }\n\n  function tearDown() {\n    self.connected = false;\n    if (process.stdin.setRawMode) { // https://github.com/joyent/node/issues/8204\n      process.stdin.setRawMode(false);\n    }\n    process.stdin.unpipe(sock);\n    sock.unpipe(process.stdout);\n    sock.removeListener(\"connect\", onConnect);\n    sock.removeListener(\"close\", onClose);\n    sock.removeListener(\"error\", onError);\n    sock.end();\n  }\n\n  sock.pipe(process.stdout);\n\n  eachline(sock, \"utf8\", function(line) {\n    self.exitOnClose = line.indexOf(EXITING_MESSAGE) >= 0;\n  });\n\n  sock.on(\"connect\", onConnect);\n  sock.on(\"close\", onClose);\n  sock.on(\"error\", onError);\n};\n\nfunction shellBanner() {\n  var bannerLines = [\n    \"\",\n    \"Welcome to the server-side interactive shell!\"\n  ];\n\n  if (! process.env.EMACS) {\n    // Tab completion sadly does not work in Emacs.\n    bannerLines.push(\n      \"\",\n      \"Tab completion is enabled for global variables.\"\n    );\n  }\n\n  bannerLines.push(\n    \"\",\n    \"Type .reload to restart the server and the shell.\",\n    \"Type .exit to disconnect from the server and leave the shell.\",\n    \"Type .help for additional help.\",\n    EOL\n  );\n\n  return chalk.green(bannerLines.join(EOL));\n}\n"
  },
  {
    "path": "tools/static-assets/README.md",
    "content": "# Isobuild Static Assets\n\nFiles here are designed to be copied to the output destination of a Meteor CLI\ncommand.\n\nSometimes, for code sharing, the JS files can be imported by parts of the tool\n(like `mini-files.js` - it is shared between built apps and tool).\n\n## skel - App Skeleton\n\n`skel` is a folder that is the skeleton of a new fresh app. It is copied to the\ndestination on `meteor create` command. The important part of the skeleton is\nthe packages it includes by default.\n\n## skel-pack - Package Skeleton\n\nSimilar to `skel`, `skel-pack` is copied on `meteor create --package` command.\n\n## server - Bundled App's Bootstrap\n\nThe `server` folder is copied by Isobuild when the app is bundled (on\n`meteor run` or `meteor build`). The `boot.js` file is the default entry point\nof any built Meteor app, it loads the server program and runs the files from the\nmanifest. It also sets up the source-maps and a backdoor for `meteor shell`.\n"
  },
  {
    "path": "tools/static-assets/server/boot-utils.js",
    "content": "// Separated from boot.js for testing.\n\n// Check that we have a pid that looks like an integer (non-decimal\n// integer is okay).\nexports.validPid = function (pid) {\n  return ! isNaN(+pid);\n};\n"
  },
  {
    "path": "tools/static-assets/server/boot.js",
    "content": "var Fiber = require(\"fibers\");\nvar fs = require(\"fs\");\nvar path = require(\"path\");\nvar Future = require(\"fibers/future\");\nvar _ = require('underscore');\nvar sourcemap_support = require('source-map-support');\n\nvar bootUtils = require('./boot-utils.js');\nvar files = require('./mini-files.js');\nvar npmRequire = require('./npm-require.js').require;\n\n// This code is duplicated in tools/main.js.\nvar MIN_NODE_VERSION = 'v0.10.41';\n\nif (require('semver').lt(process.version, MIN_NODE_VERSION)) {\n  process.stderr.write(\n    'Meteor requires Node ' + MIN_NODE_VERSION + ' or later.\\n');\n  process.exit(1);\n}\n\n// read our control files\nvar serverJsonPath = path.resolve(process.argv[2]);\nvar serverDir = path.dirname(serverJsonPath);\nvar serverJson = require(\"./server-json.js\");\nvar configJson =\n  JSON.parse(fs.readFileSync(path.resolve(serverDir, 'config.json'), 'utf8'));\n\n// Set up environment\n__meteor_bootstrap__ = {\n  startupHooks: [],\n  serverDir: serverDir,\n  configJson: configJson };\n__meteor_runtime_config__ = { meteorRelease: configJson.meteorRelease };\n\nif (!process.env.APP_ID) {\n  process.env.APP_ID = configJson.appId;\n}\n\n// Map from load path to its source map.\nvar parsedSourceMaps = {};\n\n// Read all the source maps into memory once.\n_.each(serverJson.load, function (fileInfo) {\n  if (fileInfo.sourceMap) {\n    var rawSourceMap = fs.readFileSync(\n      path.resolve(serverDir, fileInfo.sourceMap), 'utf8');\n    // Parse the source map only once, not each time it's needed. Also remove\n    // the anti-XSSI header if it's there.\n    var parsedSourceMap = JSON.parse(rawSourceMap.replace(/^\\)\\]\\}'/, ''));\n    // source-map-support doesn't ever look at the sourcesContent field, so\n    // there's no point in keeping it in memory.\n    delete parsedSourceMap.sourcesContent;\n    var url;\n    if (fileInfo.sourceMapRoot) {\n      // Add the specified root to any root that may be in the file.\n      parsedSourceMap.sourceRoot = path.join(\n        fileInfo.sourceMapRoot, parsedSourceMap.sourceRoot || '');\n    }\n    parsedSourceMaps[path.resolve(__dirname, fileInfo.path)] = parsedSourceMap;\n  }\n});\n\nvar retrieveSourceMap = function (pathForSourceMap) {\n  if (_.has(parsedSourceMaps, pathForSourceMap))\n    return { map: parsedSourceMaps[pathForSourceMap] };\n  return null;\n};\n\nvar origWrapper = sourcemap_support.wrapCallSite;\nvar wrapCallSite = function (frame) {\n  var frame = origWrapper(frame);\n  var wrapGetter = function (name) {\n    var origGetter = frame[name];\n    frame[name] = function (arg) {\n      // replace a custom location domain that we set for better UX in Chrome\n      // DevTools (separate domain group) in source maps.\n      var source = origGetter(arg);\n      if (! source)\n        return source;\n      return source.replace(/(^|\\()meteor:\\/\\/..app\\//, '$1');\n    };\n  };\n  wrapGetter('getScriptNameOrSourceURL');\n  wrapGetter('getEvalOrigin');\n\n  return frame;\n};\nsourcemap_support.install({\n  // Use the source maps specified in program.json instead of parsing source\n  // code for them.\n  retrieveSourceMap: retrieveSourceMap,\n  // For now, don't fix the source line in uncaught exceptions, because we\n  // haven't fixed handleUncaughtExceptions in source-map-support to properly\n  // locate the source files.\n  handleUncaughtExceptions: false,\n  wrapCallSite: wrapCallSite\n});\n\n// Only enabled by default in development.\nif (process.env.METEOR_SHELL_DIR) {\n  require('./shell-server.js').listen(process.env.METEOR_SHELL_DIR);\n}\n\n// As a replacement to the old keepalives mechanism, check for a running\n// parent every few seconds. Exit if the parent is not running.\n//\n// Two caveats to this strategy:\n// * Doesn't catch the case where the parent is CPU-hogging (but maybe we\n//   don't want to catch that case anyway, since the bundler not yielding\n//   is what caused #2536).\n// * Could be fooled by pid re-use, i.e. if another process comes up and\n//   takes the parent process's place before the child process dies.\nvar startCheckForLiveParent = function (parentPid) {\n  if (parentPid) {\n    if (! bootUtils.validPid(parentPid)) {\n      console.error(\"METEOR_PARENT_PID must be a valid process ID.\");\n      process.exit(1);\n    }\n\n    setInterval(function () {\n      try {\n        process.kill(parentPid, 0);\n      } catch (err) {\n        console.error(\"Parent process is dead! Exiting.\");\n        process.exit(1);\n      }\n    }, 3000);\n  }\n};\n\n\nFiber(function () {\n  _.each(serverJson.load, function (fileInfo) {\n    var code = fs.readFileSync(path.resolve(serverDir, fileInfo.path));\n    var nonLocalNodeModulesPaths = [];\n\n    function addNodeModulesPath(path) {\n      nonLocalNodeModulesPaths.push(\n        files.pathResolve(serverDir, path)\n      );\n    }\n\n    if (typeof fileInfo.node_modules === \"string\") {\n      addNodeModulesPath(fileInfo.node_modules);\n    } else if (fileInfo.node_modules) {\n      _.each(fileInfo.node_modules, function (info, path) {\n        if (! info.local) {\n          addNodeModulesPath(path);\n        }\n      });\n    }\n\n    function statOrNull(path) {\n      try {\n        return fs.statSync(path);\n      } catch (e) {\n        return null;\n      }\n    }\n\n    var Npm = {\n      /**\n       * @summary Require a package that was specified using\n       * `Npm.depends()`.\n       * @param  {String} name The name of the package to require.\n       * @locus Server\n       * @memberOf Npm\n       */\n      require: function (name) {\n        if (nonLocalNodeModulesPaths.length === 0) {\n          return require(name);\n        }\n\n        var fullPath;\n\n        nonLocalNodeModulesPaths.some(function (nodeModuleBase) {\n          var packageBase = files.convertToOSPath(files.pathResolve(\n            nodeModuleBase,\n            name.split(\"/\", 1)[0]\n          ));\n\n          if (statOrNull(packageBase)) {\n            return fullPath = files.convertToOSPath(\n              files.pathResolve(nodeModuleBase, name)\n            );\n          }\n        });\n\n        if (fullPath) {\n          return require(fullPath);\n        }\n\n        try {\n          return require(name);\n        } catch (e) {\n          // Try to guess the package name so we can print a nice\n          // error message\n          // fileInfo.path is a standard path, use files.pathSep\n          var filePathParts = fileInfo.path.split(files.pathSep);\n          var packageName = filePathParts[1].replace(/\\.js$/, '');\n\n          // XXX better message\n          throw new Error(\n            \"Can't find npm module '\" + name +\n              \"'. Did you forget to call 'Npm.depends' in package.js \" +\n              \"within the '\" + packageName + \"' package?\");\n          }\n      }\n    };\n    var getAsset = function (assetPath, encoding, callback) {\n      var fut;\n      if (! callback) {\n        fut = new Future();\n        callback = fut.resolver();\n      }\n      // This assumes that we've already loaded the meteor package, so meteor\n      // itself can't call Assets.get*. (We could change this function so that\n      // it doesn't call bindEnvironment if you don't pass a callback if we need\n      // to.)\n      var _callback = Package.meteor.Meteor.bindEnvironment(function (err, result) {\n        if (result && ! encoding)\n          // Sadly, this copies in Node 0.10.\n          result = new Uint8Array(result);\n        callback(err, result);\n      }, function (e) {\n        console.log(\"Exception in callback of getAsset\", e.stack);\n      });\n\n      // Convert a DOS-style path to Unix-style in case the application code was\n      // written on Windows.\n      assetPath = files.convertToStandardPath(assetPath);\n\n      if (!fileInfo.assets || !_.has(fileInfo.assets, assetPath)) {\n        _callback(new Error(\"Unknown asset: \" + assetPath));\n      } else {\n        var filePath = path.join(serverDir, fileInfo.assets[assetPath]);\n        fs.readFile(files.convertToOSPath(filePath), encoding, _callback);\n      }\n      if (fut)\n        return fut.wait();\n    };\n\n    var Assets = {\n      getText: function (assetPath, callback) {\n        return getAsset(assetPath, \"utf8\", callback);\n      },\n      getBinary: function (assetPath, callback) {\n        return getAsset(assetPath, undefined, callback);\n      },\n      /**\n       * @summary Get the absolute path to the static server asset. Note that assets are read-only.\n       * @locus Server [Not in build plugins]\n       * @memberOf Assets\n       * @param {String} assetPath The path of the asset, relative to the application's `private` subdirectory.\n       */\n      absoluteFilePath: function (assetPath) {\n        if (!fileInfo.assets || !_.has(fileInfo.assets, assetPath)) {\n          throw new Error(\"Unknown asset: \" + assetPath);\n        }\n\n        assetPath = files.convertToStandardPath(assetPath);\n        var filePath = path.join(serverDir, fileInfo.assets[assetPath]);\n        return files.convertToOSPath(filePath);\n      },\n    };\n\n    var isModulesRuntime =\n      fileInfo.path === \"packages/modules-runtime.js\";\n\n    var wrapParts = [\"(function(Npm,Assets\"];\n    if (isModulesRuntime) {\n      wrapParts.push(\",npmRequire\");\n    }\n    // \\n is necessary in case final line is a //-comment\n    wrapParts.push(\"){\", code, \"\\n})\");\n    var wrapped = wrapParts.join(\"\");\n\n    // It is safer to use the absolute path when source map is present as\n    // different tooling, such as node-inspector, can get confused on relative\n    // urls.\n\n    // fileInfo.path is a standard path, convert it to OS path to join with\n    // __dirname\n    var fileInfoOSPath = files.convertToOSPath(fileInfo.path);\n    var absoluteFilePath = path.resolve(__dirname, fileInfoOSPath);\n\n    var scriptPath =\n      parsedSourceMaps[absoluteFilePath] ? absoluteFilePath : fileInfoOSPath;\n    // The final 'true' is an undocumented argument to runIn[Foo]Context that\n    // causes it to print out a descriptive error message on parse error. It's\n    // what require() uses to generate its errors.\n    var func = require('vm').runInThisContext(wrapped, scriptPath, true);\n    var args = [Npm, Assets];\n    if (isModulesRuntime) {\n      args.push(npmRequire);\n    }\n    func.apply(global, args);\n  });\n\n  // run the user startup hooks.  other calls to startup() during this can still\n  // add hooks to the end.\n  while (__meteor_bootstrap__.startupHooks.length) {\n    var hook = __meteor_bootstrap__.startupHooks.shift();\n    hook();\n  }\n  // Setting this to null tells Meteor.startup to call hooks immediately.\n  __meteor_bootstrap__.startupHooks = null;\n\n  // find and run main()\n  // XXX hack. we should know the package that contains main.\n  var mains = [];\n  var globalMain;\n  if ('main' in global) {\n    mains.push(main);\n    globalMain = main;\n  }\n  typeof Package !== 'undefined' && _.each(Package, function (p, n) {\n    if ('main' in p && p.main !== globalMain) {\n      mains.push(p.main);\n    }\n  });\n  if (! mains.length) {\n    process.stderr.write(\"Program has no main() function.\\n\");\n    process.exit(1);\n  }\n  if (mains.length > 1) {\n    process.stderr.write(\"Program has more than one main() function?\\n\");\n    process.exit(1);\n  }\n  var exitCode = mains[0].call({}, process.argv.slice(3));\n  // XXX hack, needs a better way to keep alive\n  if (exitCode !== 'DAEMON')\n    process.exit(exitCode);\n\n  if (process.env.METEOR_PARENT_PID) {\n    startCheckForLiveParent(process.env.METEOR_PARENT_PID);\n  }\n}).run();\n"
  },
  {
    "path": "tools/static-assets/server/mini-files.js",
    "content": "var _ = require(\"underscore\");\nvar os = require(\"os\");\nvar path = require(\"path\");\n\n// All of these functions are attached to files.js for the tool;\n// they live here because we need them in boot.js as well to avoid duplicating\n// a lot of the code.\n//\n// Note that this file does NOT contain any of the \"perform I/O maybe\n// synchronously\" functions from files.js; this is intentional, because we want\n// to make it very hard to accidentally use fs.*Sync functions in the app server\n// after bootup (since they block all concurrency!)\nvar files = module.exports;\n\nvar toPosixPath = function (p, partialPath) {\n  // Sometimes, you can have a path like \\Users\\IEUser on windows, and this\n  // actually means you want C:\\Users\\IEUser\n  if (p[0] === \"\\\\\" && (! partialPath)) {\n    p = process.env.SystemDrive + p;\n  }\n\n  p = p.replace(/\\\\/g, '/');\n  if (p[1] === ':' && ! partialPath) {\n    // transform \"C:/bla/bla\" to \"/c/bla/bla\"\n    p = '/' + p[0] + p.slice(2);\n  }\n\n  return p;\n};\n\nvar toDosPath = function (p, partialPath) {\n  if (p[0] === '/' && ! partialPath) {\n    if (! /^\\/[A-Za-z](\\/|$)/.test(p))\n      throw new Error(\"Surprising path: \" + p);\n    // transform a previously windows path back\n    // \"/C/something\" to \"c:/something\"\n    p = p[1] + \":\" + p.slice(2);\n  }\n\n  p = p.replace(/\\//g, '\\\\');\n  return p;\n};\n\n\nvar convertToOSPath = function (standardPath, partialPath) {\n  if (process.platform === \"win32\") {\n    return toDosPath(standardPath, partialPath);\n  }\n\n  return standardPath;\n};\n\nvar convertToStandardPath = function (osPath, partialPath) {\n  if (process.platform === \"win32\") {\n    return toPosixPath(osPath, partialPath);\n  }\n\n  return osPath;\n}\n\nvar convertToOSLineEndings = function (fileContents) {\n  return fileContents.replace(/\\n/g, os.EOL);\n};\n\nvar convertToStandardLineEndings = function (fileContents) {\n  // Convert all kinds of end-of-line chars to linuxy \"\\n\".\n  return fileContents.replace(new RegExp(\"\\r\\n\", \"g\"), \"\\n\")\n                     .replace(new RegExp(\"\\r\", \"g\"), \"\\n\");\n};\n\n\n// wrappings for path functions that always run as they were on unix (using\n// forward slashes)\nvar wrapPathFunction = function (name, partialPaths) {\n  var f = path[name];\n  return function (/* args */) {\n    if (process.platform === 'win32') {\n      var args = _.toArray(arguments);\n      args = _.map(args, function (p, i) {\n        // if partialPaths is turned on (for path.join mostly)\n        // forget about conversion of absolute paths for Windows\n        return toDosPath(p, partialPaths);\n      });\n      return toPosixPath(f.apply(path, args), partialPaths);\n    } else {\n      return f.apply(path, arguments);\n    }\n  };\n};\n\nfiles.pathJoin = wrapPathFunction(\"join\", true);\nfiles.pathNormalize = wrapPathFunction(\"normalize\");\nfiles.pathRelative = wrapPathFunction(\"relative\");\nfiles.pathResolve = wrapPathFunction(\"resolve\");\nfiles.pathDirname = wrapPathFunction(\"dirname\");\nfiles.pathBasename = wrapPathFunction(\"basename\");\nfiles.pathExtname = wrapPathFunction(\"extname\");\nfiles.pathSep = '/';\nfiles.pathDelimiter = ':';\nfiles.pathOsDelimiter = path.delimiter;\nfiles.pathIsAbsolute = function (path) {\n  return toPosixPath(path).charAt(0) === '/';\n};\n\nfiles.convertToStandardPath = convertToStandardPath;\nfiles.convertToOSPath = convertToOSPath;\nfiles.convertToWindowsPath = toDosPath;\nfiles.convertToPosixPath = toPosixPath;\n\nfiles.convertToStandardLineEndings = convertToStandardLineEndings;\nfiles.convertToOSLineEndings = convertToOSLineEndings;\n"
  },
  {
    "path": "tools/static-assets/server/npm-rebuild.js",
    "content": "// If a developer wants to go to the trouble of building on exactly the\n// same architecture as the production machine, then it should be possible\n// to skip running `npm rebuild`.\nif (process.env.METEOR_SKIP_NPM_REBUILD) {\n  process.exit(0);\n}\n\nvar path = require(\"path\");\nvar spawn = require(\"child_process\").spawn;\n\ntry {\n  // This JSON file gets written in meteor/tools/isobuild/bundler.js.\n  var rebuilds = require(\"./npm-rebuilds.json\");\n} catch (e) {\n  if (e.code !== \"MODULE_NOT_FOUND\") {\n    throw e;\n  }\n\n  // If npm-rebuilds.json was not written, assume there is nothing that\n  // needs to be rebuilt.\n  process.exit(0);\n}\n\n// Make sure the npm finds this exact version of node in its $PATH.\nvar PATH = path.dirname(process.execPath) + \":\" + process.env.PATH;\nvar env = Object.create(process.env, {\n  PATH: { value: PATH }\n});\n\nfunction rebuild(i) {\n  var dir = rebuilds && rebuilds[i];\n\n  if (! dir) {\n    // Print Node/V8/etc. versions for diagnostic purposes.\n    spawn(\"npm\", [\"version\", \"--json\"], {\n      stdio: \"inherit\",\n      env: env\n    });\n\n    return;\n  }\n\n  spawn(\"npm\", [\"rebuild\"], {\n    cwd: path.join(__dirname, dir),\n    stdio: \"inherit\",\n    env: env\n  }).on(\"exit\", function (code) {\n    if (code !== 0) {\n      process.exit(code);\n    } else {\n      rebuild(i + 1);\n    }\n  });\n}\n\nrebuild(0);\n"
  },
  {
    "path": "tools/static-assets/server/npm-require.js",
    "content": "var assert = require(\"assert\");\nvar fs = require(\"fs\");\nvar path = require(\"path\");\nvar _ = require('underscore');\nvar files = require('./mini-files.js');\nvar serverJson = require(\"./server-json.js\");\nvar topLevelIdPattern = /^[^./]/;\n\nfunction statOrNull(path) {\n  try {\n    return fs.statSync(path);\n  } catch (e) {\n    return null;\n  }\n}\n\nfunction findAppDirHelper(absOSPath) {\n  if (fs.statSync(absOSPath).isDirectory() &&\n      statOrNull(path.join(absOSPath, \".meteor\"))) {\n    return absOSPath;\n  }\n\n  var parentDir = path.dirname(absOSPath);\n  if (parentDir !== absOSPath) {\n    return findAppDirHelper(parentDir);\n  }\n\n  throw new Error(\"Cannot find application root directory\");\n}\n\nfunction findAppDir(absPath) {\n  return files.convertToPosixPath(\n    findAppDirHelper(files.convertToOSPath(absPath)));\n}\n\n// Map from virtual module identifiers for node_modules directories (like\n// \"/node_modules/meteor/blaze/node_modules\") to the absolute paths of the\n// read node_modules directories on disk. The npmRequire function below\n// needs to look up absolute paths using virtual identifiers as input.\nvar nodeModulesRegistry = Object.create(null);\n\n_.each(serverJson.load, function (fileInfo) {\n  if (fileInfo.node_modules) {\n    var match = /^(packages|app)\\/(\\S+)?\\.js/.exec(fileInfo.path);\n    if (match) {\n      if (match[1] === \"packages\") {\n        registerNodeModules(match[2], fileInfo.node_modules);\n      } else if (match[1] === \"app\") {\n        registerNodeModules(null, fileInfo.node_modules);\n      }\n    }\n  }\n});\n\nfunction registerNodeModules(name, node_modules) {\n  if (typeof node_modules === \"string\") {\n    addByPath(node_modules);\n  } else {\n    Object.keys(node_modules).forEach(addByPath);\n  }\n\n  function addByPath(node_modules) {\n    assert.strictEqual(typeof node_modules, \"string\");\n\n    var parts = node_modules.split(files.pathSep);\n    if (parts[0] === \"\") parts.shift();\n\n    if (files.pathIsAbsolute(node_modules)) {\n      if (! name) {\n        var appDir = findAppDir(node_modules);\n        var relPathWithinApp = files.pathRelative(appDir, node_modules);\n        addByParts(relPathWithinApp.split(files.pathSep), node_modules);\n        return;\n      }\n\n      parts.forEach(function (part, i) {\n        if (part === \"npm\") {\n          addByParts(parts.slice(i + 1), node_modules);\n        } else if (part === \".npm\") {\n          if (parts[i + 1] === \"package\") {\n            addByParts(parts.slice(i + 2), node_modules);\n          } else if (parts[i + 1] === \"plugin\") {\n            assert.strictEqual(parts[i + 2], name);\n            addByParts(parts.slice(i + 3), node_modules);\n          }\n        }\n      });\n\n    } else if (parts[0] === \"npm\") {\n      var absPath = files.pathResolve(__dirname, parts.join(files.pathSep));\n      addByParts(parts.slice(1), absPath);\n\n    } else {\n      throw new Error(\"unknown node_modules path: \" + node_modules);\n    }\n  }\n\n  function addByParts(parts, absPath) {\n    assert.ok(parts.length > 0);\n    assert.notEqual(parts[0], \"\");\n    assert.notEqual(parts[0], \"..\");\n\n    if (name) {\n      parts.unshift(\"node_modules\", \"meteor\", name);\n    }\n\n    // Ensure a leading / character.\n    parts.unshift(\"\");\n\n    nodeModulesRegistry[parts.join(\"/\")] = absPath;\n  }\n}\n\nfunction getRelID(id) {\n  assert.strictEqual(id.charAt(0), \"/\");\n  return \"./npm\" + id.replace(/:/g, \"_\");\n}\n\n// Sort the keys in reverse alphabetical order so that longer paths will\n// come before their prefixes.\nvar sortedNodeModulesPaths =\n  Object.keys(nodeModulesRegistry).sort(function (a, b) {\n    if (a < b) return 1;\n    if (b < a) return -1;\n    return 0;\n  });\n\nfunction npmRequire(id) {\n  return require(resolve(id));\n}\n\nvar resolveCache = Object.create(null);\n\nfunction resolve(id) {\n  var res = resolveCache[id];\n\n  if (typeof res === \"string\") {\n    return res;\n  }\n\n  if (res === null) {\n    var idParts = id.split(\"/\");\n    var meteorAddTip = \"\";\n    // If it looks like `meteor/xxx`, the user may forgot to add the \n    // package before importing it.\n    if (idParts.length === 2 &&\n        idParts[0] === \"meteor\") {\n          meteorAddTip = \". Try `meteor add \" + idParts[1] + \"` \" +\n          \"as it looks like you tried to import it without adding \" +\n          \"to the project.\";\n    }\n    res = new Error(\"Cannot find module '\" + id + \"'\" + meteorAddTip);\n    res.code = \"MODULE_NOT_FOUND\";\n    throw res;\n  }\n\n  resolveCache[id] =\n    resolveInLocalBuild(id) ||\n    resolveInNodeModules(id) ||\n    resolveInDevBundle(id) ||\n    null;\n\n  return resolve(id);\n}\n\nfunction resolveInLocalBuild(id) {\n  return tryResolve(getRelID(id));\n}\n\nfunction resolveInNodeModules(id) {\n  var absId;\n\n  sortedNodeModulesPaths.some(function (prefix) {\n    var relId = files.pathRelative(\n      files.pathJoin(\".\", prefix),\n      files.pathJoin(\".\", id)\n    );\n\n    if (relId.slice(0, 2) !== \"..\") {\n      return absId =\n        files.pathJoin(nodeModulesRegistry[prefix], relId);\n    }\n  });\n\n  return absId && tryResolve(files.convertToOSPath(absId));\n}\n\nfunction resolveInDevBundle(id) {\n  // Fall back to dev_bundle/lib/node_modules and built-in modules.\n  return topLevelIdPattern.test(id) && tryResolve(id);\n}\n\nfunction tryResolve(id) {\n  try {\n    return require.resolve(id);\n  } catch (e) {\n    return null;\n  }\n}\n\nexports.require = npmRequire;\nexports.resolve = npmRequire.resolve = resolve;\n"
  },
  {
    "path": "tools/static-assets/server/server-json.js",
    "content": "var fs = require(\"fs\");\nvar path = require(\"path\");\nvar serverJsonPath = path.resolve(process.argv[2]);\nmodule.exports = JSON.parse(fs.readFileSync(serverJsonPath, 'utf8'));\n"
  },
  {
    "path": "tools/static-assets/server/shell-server.js",
    "content": "var assert = require(\"assert\");\nvar path = require(\"path\");\nvar stream = require(\"stream\");\nvar fs = require(\"fs\");\nvar net = require(\"net\");\nvar tty = require(\"tty\");\nvar vm = require(\"vm\");\nvar _ = require(\"underscore\");\nvar INFO_FILE_MODE = parseInt(\"600\", 8); // Only the owner can read or write.\nvar EXITING_MESSAGE =\n  // Exported so that ./client.js can know what to expect.\n  exports.EXITING_MESSAGE = \"Shell exiting...\";\n\nvar Promise = require(\"promise/lib/es6-extensions\");\nrequire(\"meteor-promise\").makeCompatible(Promise, require(\"fibers\"));\n\n// Invoked by the server process to listen for incoming connections from\n// shell clients. Each connection gets its own REPL instance.\nexports.listen = function listen(shellDir) {\n  function callback() {\n    new Server(shellDir).listen();\n  }\n\n  // If the server is still in the very early stages of starting up,\n  // Meteor.startup may not available yet.\n  if (typeof Meteor === \"object\") {\n    Meteor.startup(callback);\n  } else if (typeof __meteor_bootstrap__ === \"object\") {\n    var hooks = __meteor_bootstrap__.startupHooks;\n    if (hooks) {\n      hooks.push(callback);\n    } else {\n      // As a fallback, just call the callback asynchronously.\n      setImmediate(callback);\n    }\n  }\n};\n\n// Disabling the shell causes all attached clients to disconnect and exit.\nexports.disable = function disable(shellDir) {\n  try {\n    // Replace info.json with a file that says the shell server is\n    // disabled, so that any connected shell clients will fail to\n    // reconnect after the server process closes their sockets.\n    fs.writeFileSync(\n      getInfoFile(shellDir),\n      JSON.stringify({\n        status: \"disabled\",\n        reason: \"Shell server has shut down.\"\n      }) + \"\\n\",\n      { mode: INFO_FILE_MODE }\n    );\n  } catch (ignored) {}\n};\n\nfunction Server(shellDir) {\n  var self = this;\n  assert.ok(self instanceof Server);\n\n  self.shellDir = shellDir;\n  self.key = Math.random().toString(36).slice(2);\n\n  self.server = net.createServer(function(socket) {\n    self.onConnection(socket);\n  }).on(\"error\", function(err) {\n    console.error(err.stack);\n  });\n}\n\nvar Sp = Server.prototype;\n\nSp.listen = function listen() {\n  var self = this;\n  var infoFile = getInfoFile(self.shellDir);\n\n  fs.unlink(infoFile, function() {\n    self.server.listen(0, \"127.0.0.1\", function() {\n      fs.writeFileSync(infoFile, JSON.stringify({\n        status: \"enabled\",\n        port: self.server.address().port,\n        key: self.key\n      }) + \"\\n\", {\n        mode: INFO_FILE_MODE\n      });\n    });\n  });\n};\n\nfunction readJSONFromStream(inputStream, callback) {\n  var outputStream = new stream.PassThrough;\n  var dataSoFar = \"\";\n\n  function onData(buffer) {\n    var lines = buffer.toString(\"utf8\").split(\"\\n\");\n\n    while (lines.length > 0) {\n      dataSoFar += lines.shift();\n\n      try {\n        var json = JSON.parse(dataSoFar);\n      } catch (error) {\n        if (error instanceof SyntaxError) {\n          continue;\n        }\n\n        return finish(error);\n      }\n\n      if (lines.length > 0) {\n        outputStream.write(lines.join(\"\\n\"));\n      }\n\n      inputStream.pipe(outputStream);\n\n      return finish(null, json);\n    }\n  }\n\n  function onClose() {\n    finish(new Error(\"stream unexpectedly closed\"));\n  }\n\n  var finished = false;\n  function finish(error, json) {\n    if (! finished) {\n      finished = true;\n      inputStream.removeListener(\"data\", onData);\n      inputStream.removeListener(\"error\", finish);\n      inputStream.removeListener(\"close\", onClose);\n      callback(error, json, outputStream);\n    }\n  }\n\n  inputStream.on(\"data\", onData);\n  inputStream.on(\"error\", finish);\n  inputStream.on(\"close\", onClose);\n}\n\nSp.onConnection = function onConnection(socket) {\n  var self = this;\n\n  // Make sure this function doesn't try to write anything to the socket\n  // after it has been closed.\n  socket.on(\"close\", function() {\n    socket = null;\n  });\n\n  // If communication is not established within 1000ms of the first\n  // connection, forcibly close the socket.\n  var timeout = setTimeout(function() {\n    if (socket) {\n      socket.removeAllListeners(\"data\");\n      socket.end(EXITING_MESSAGE + \"\\n\");\n    }\n  }, 1000);\n\n  // Let connecting clients configure certain REPL options by sending a\n  // JSON object over the socket. For example, only the client knows\n  // whether it's running a TTY or an Emacs subshell or some other kind of\n  // terminal, so the client must decide the value of options.terminal.\n  readJSONFromStream(socket, function (error, options, replInputSocket) {\n    clearTimeout(timeout);\n\n    if (options.key !== self.key) {\n      if (socket) {\n        socket.end(EXITING_MESSAGE + \"\\n\");\n      }\n      return;\n    }\n    delete options.key;\n\n    if (options.evaluateAndExit) {\n      evalCommand(\n        \"(\" + options.evaluateAndExit.command + \")\",\n        null, // evalCommand ignores the context parameter, anyway\n        options.evaluateAndExit.filename || \"<meteor shell>\",\n        function (error, result) {\n          if (socket) {\n            var message = error ? {\n              error: error + \"\",\n              code: 1\n            } : {\n              result: result\n            };\n\n            // Sending back a JSON payload allows the client to\n            // distinguish between errors and successful results.\n            socket.end(JSON.stringify(message) + \"\\n\");\n          }\n        }\n      );\n      return;\n    }\n    delete options.evaluateAndExit;\n\n    // Immutable options.\n    _.extend(options, {\n      input: replInputSocket,\n      output: socket,\n      eval: evalCommand\n    });\n\n    // Overridable options.\n    _.defaults(options, {\n      prompt: \"> \",\n      terminal: true,\n      useColors: true,\n      useGlobal: true,\n      ignoreUndefined: true,\n    });\n\n    self.startREPL(options);\n  });\n};\n\nSp.startREPL = function startREPL(options) {\n  var self = this;\n\n  if (! options.output.columns) {\n    // The REPL's tab completion logic assumes process.stdout is a TTY,\n    // and while that isn't technically true here, we can get tab\n    // completion to behave correctly if we fake the .columns property.\n    options.output.columns = getTerminalWidth();\n  }\n\n  // Make sure this function doesn't try to write anything to the output\n  // stream after it has been closed.\n  options.output.on(\"close\", function() {\n    options.output = null;\n  });\n\n  var repl = self.repl = require(\"repl\").start(options);\n\n  // History persists across shell sessions!\n  self.initializeHistory();\n\n  // Save the global `_` object in the server.  This is probably defined by the\n  // underscore package.  It is unlikely to be the same object as the `var _ =\n  // require('underscore')` in this file!\n  var originalUnderscore = repl.context._;\n\n  Object.defineProperty(repl.context, \"_\", {\n    // Force the global _ variable to remain bound to underscore.\n    get: function () { return originalUnderscore; },\n\n    // Expose the last REPL result as __ instead of _.\n    set: function(lastResult) {\n      repl.context.__ = lastResult;\n    },\n\n    enumerable: true,\n\n    // Allow this property to be (re)defined more than once (e.g. each\n    // time the server restarts).\n    configurable: true\n  });\n\n  if (Package.modules) {\n    // Use the same `require` function and `module` object visible to the\n    // application.\n    var toBeInstalled = {};\n    var shellModuleName = \"meteor-shell-\" +\n      Math.random().toString(36).slice(2) + \".js\";\n\n    toBeInstalled[shellModuleName] = function (require, exports, module) {\n      repl.context.module = module;\n      repl.context.require = require;\n    };\n\n    // This populates repl.context.{module,require} by evaluating the\n    // module defined above.\n    Package.modules.meteorInstall(toBeInstalled)(\"./\" + shellModuleName);\n  }\n\n  repl.context.repl = repl;\n\n  // Some improvements to the existing help messages.\n  function addHelp(cmd, helpText) {\n    var info = repl.commands[cmd] || repl.commands[\".\" + cmd];\n    if (info) {\n      info.help = helpText;\n    }\n  }\n  addHelp(\"break\", \"Terminate current command input and display new prompt\");\n  addHelp(\"exit\", \"Disconnect from server and leave shell\");\n  addHelp(\"help\", \"Show this help information\");\n\n  // When the REPL exits, signal the attached client to exit by sending it\n  // the special EXITING_MESSAGE.\n  repl.on(\"exit\", function() {\n    if (options.output) {\n      options.output.write(EXITING_MESSAGE + \"\\n\");\n      options.output.end();\n    }\n  });\n\n  // When the server process exits, end the output stream but do not\n  // signal the attached client to exit.\n  process.on(\"exit\", function() {\n    if (options.output) {\n      options.output.end();\n    }\n  });\n\n  // This Meteor-specific shell command rebuilds the application as if a\n  // change was made to server code.\n  repl.defineCommand(\"reload\", {\n    help: \"Restart the server and the shell\",\n    action: function() {\n      process.exit(0);\n    }\n  });\n};\n\nfunction getInfoFile(shellDir) {\n  return path.join(shellDir, \"info.json\");\n}\nexports.getInfoFile = getInfoFile;\n\nfunction getHistoryFile(shellDir) {\n  return path.join(shellDir, \"history\");\n}\n\nfunction getTerminalWidth() {\n  try {\n    // Inspired by https://github.com/TooTallNate/ttys/blob/master/index.js\n    var fd = fs.openSync(\"/dev/tty\", \"r\");\n    assert.ok(tty.isatty(fd));\n    var ws = new tty.WriteStream(fd);\n    ws.end();\n    return ws.columns;\n  } catch (fancyApproachWasTooFancy) {\n    return 80;\n  }\n}\n\n// Shell commands need to be executed in a Fiber in case they call into\n// code that yields. Using a Promise is an even better idea, since it runs\n// its callbacks in Fibers drawn from a pool, so the Fibers are recycled.\nvar evalCommandPromise = Promise.resolve();\n\nfunction evalCommand(command, context, filename, callback) {\n  if (Package.ecmascript) {\n    var noParens = stripParens(command);\n    if (noParens !== command) {\n      var classMatch = /^\\s*class\\s+(\\w+)/.exec(noParens);\n      if (classMatch && classMatch[1] !== \"extends\") {\n        // If the command looks like a named ES2015 class, we remove the\n        // extra layer of parentheses added by the REPL so that the\n        // command will be evaluated as a class declaration rather than as\n        // a named class expression. Note that you can still type (class A\n        // {}) explicitly to evaluate a named class expression. The REPL\n        // code that calls evalCommand handles named function expressions\n        // similarly (first with and then without parentheses), but that\n        // code doesn't know about ES2015 classes, which is why we have to\n        // handle them here.\n        command = noParens;\n      }\n    }\n\n    try {\n      command = Package.ecmascript.ECMAScript.compileForShell(command);\n    } catch (error) {\n      callback(error);\n      return;\n    }\n  }\n\n  try {\n    var script = new vm.Script(command, {\n      filename: filename,\n      displayErrors: false\n    });\n  } catch (parseError) {\n    callback(parseError);\n    return;\n  }\n\n  evalCommandPromise.then(function () {\n    callback(null, script.runInThisContext());\n  }).catch(callback);\n}\n\nfunction stripParens(command) {\n  if (command.charAt(0) === \"(\" &&\n      command.charAt(command.length - 1) === \")\") {\n    return command.slice(1, command.length - 1);\n  }\n  return command;\n}\n\n// This function allows a persistent history of shell commands to be saved\n// to and loaded from .meteor/local/shell-history.\nSp.initializeHistory = function initializeHistory() {\n  var self = this;\n  var rli = self.repl.rli;\n  var historyFile = getHistoryFile(self.shellDir);\n  var historyFd = fs.openSync(historyFile, \"a+\");\n  var historyLines = fs.readFileSync(historyFile, \"utf8\").split(\"\\n\");\n  var seenLines = Object.create(null);\n\n  if (! rli.history) {\n    rli.history = [];\n    rli.historyIndex = -1;\n  }\n\n  while (rli.history && historyLines.length > 0) {\n    var line = historyLines.pop();\n    if (line && /\\S/.test(line) && ! seenLines[line]) {\n      rli.history.push(line);\n      seenLines[line] = true;\n    }\n  }\n\n  rli.addListener(\"line\", function(line) {\n    if (historyFd >= 0 && /\\S/.test(line)) {\n      fs.writeSync(historyFd, line + \"\\n\");\n    }\n  });\n\n  self.repl.on(\"exit\", function() {\n    fs.closeSync(historyFd);\n    historyFd = -1;\n  });\n};\n"
  },
  {
    "path": "tools/static-assets/skel/.gitignore",
    "content": "node_modules/"
  },
  {
    "path": "tools/static-assets/skel/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/static-assets/skel/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n# Check this file (and the other files in this directory) into your repository.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base             # Packages every Meteor app needs to have\nmobile-experience       # Packages for a great mobile UX\nmongo                   # The database Meteor supports right now\nblaze-html-templates    # Compile .html files into Meteor Blaze views\nreactive-var            # Reactive variable for tracker\njquery                  # Helpful client-side library\ntracker                 # Meteor's client-side reactive programming library\n\nstandard-minifier-css   # CSS minifier run for production mode\nstandard-minifier-js    # JS minifier run for production mode\nes5-shim                # ECMAScript 5 compatibility for older browsers.\necmascript              # Enable ECMAScript2015+ syntax in app code\n\nautopublish             # Publish all data to the clients (for prototyping)\ninsecure                # Allow all DB writes from clients (for prototyping)\n"
  },
  {
    "path": "tools/static-assets/skel/.meteor/platforms",
    "content": "server\nbrowser\n"
  },
  {
    "path": "tools/static-assets/skel/client/main.css",
    "content": "/* CSS declarations go here */\n"
  },
  {
    "path": "tools/static-assets/skel/client/main.html",
    "content": "<head>\n  <title>~name~</title>\n</head>\n\n<body>\n  <h1>Welcome to Meteor!</h1>\n\n  {{> hello}}\n  {{> info}}\n</body>\n\n<template name=\"hello\">\n  <button>Click Me</button>\n  <p>You've pressed the button {{counter}} times.</p>\n</template>\n\n<template name=\"info\">\n  <h2>Learn Meteor!</h2>\n  <ul>\n    <li><a href=\"https://www.meteor.com/try\" target=\"_blank\">Do the Tutorial</a></li>\n    <li><a href=\"http://guide.meteor.com\" target=\"_blank\">Follow the Guide</a></li>\n    <li><a href=\"https://docs.meteor.com\" target=\"_blank\">Read the Docs</a></li>\n    <li><a href=\"https://forums.meteor.com\" target=\"_blank\">Discussions</a></li>\n  </ul>\n</template>\n"
  },
  {
    "path": "tools/static-assets/skel/client/main.js",
    "content": "import { Template } from 'meteor/templating';\nimport { ReactiveVar } from 'meteor/reactive-var';\n\nimport './main.html';\n\nTemplate.hello.onCreated(function helloOnCreated() {\n  // counter starts at 0\n  this.counter = new ReactiveVar(0);\n});\n\nTemplate.hello.helpers({\n  counter() {\n    return Template.instance().counter.get();\n  },\n});\n\nTemplate.hello.events({\n  'click button'(event, instance) {\n    // increment the counter when button is clicked\n    instance.counter.set(instance.counter.get() + 1);\n  },\n});\n"
  },
  {
    "path": "tools/static-assets/skel/package.json",
    "content": "{\n  \"name\": \"~name~\",\n  \"private\": true,\n  \"scripts\": {\n    \"start\": \"meteor run\"\n  },\n  \"dependencies\": {\n    \"meteor-node-stubs\": \"~0.2.0\"\n  }\n}\n"
  },
  {
    "path": "tools/static-assets/skel/server/main.js",
    "content": "import { Meteor } from 'meteor/meteor';\n\nMeteor.startup(() => {\n  // code to run on server at startup\n});\n"
  },
  {
    "path": "tools/static-assets/skel-pack/README.md",
    "content": ""
  },
  {
    "path": "tools/static-assets/skel-pack/package.js",
    "content": "Package.describe({\n  name: '~name~',\n  version: '0.0.1',\n  // Brief, one-line summary of the package.\n  summary: '',\n  // URL to the Git repository containing the source code for this package.\n  git: '',\n  // By default, Meteor will default to using README.md for documentation.\n  // To avoid submitting documentation, set this field to null.\n  documentation: 'README.md'\n});\n\nPackage.onUse(function(api) {\n~cc~  api.versionsFrom('~release~');\n  api.use('ecmascript');\n  api.mainModule('~fs-name~.js');\n});\n\nPackage.onTest(function(api) {\n  api.use('ecmascript');\n  api.use('tinytest');\n  api.use('~name~');\n  api.mainModule('~fs-name~-tests.js');\n});\n"
  },
  {
    "path": "tools/static-assets/skel-pack/~fs-name~-tests.js",
    "content": "// Import Tinytest from the tinytest Meteor package.\nimport { Tinytest } from \"meteor/tinytest\";\n\n// Import and rename a variable exported by ~fs-name~.js.\nimport { name as packageName } from \"meteor/~name~\";\n\n// Write your tests here!\n// Here is an example.\nTinytest.add('~fs-name~ - example', function (test) {\n  test.equal(packageName, \"~fs-name~\");\n});\n"
  },
  {
    "path": "tools/static-assets/skel-pack/~fs-name~.js",
    "content": "// Write your package code here!\n\n// Variables exported by this module can be imported by other packages and\n// applications. See ~fs-name~-tests.js for an example of importing.\nexport const name = '~fs-name~';\n"
  },
  {
    "path": "tools/tests/apps/app-prints-pid/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/app-prints-pid/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\n"
  },
  {
    "path": "tools/tests/apps/app-prints-pid/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/app-prints-pid/print.js",
    "content": "if (Meteor.isServer) {\n  Meteor.startup(function () {\n    console.log(\"My pid is \" + process.pid);\n  });\n}\n"
  },
  {
    "path": "tools/tests/apps/app-throws-error/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/app-throws-error/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nthrowing-package\necmascript\n"
  },
  {
    "path": "tools/tests/apps/app-throws-error/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/app-throws-error/packages/throwing-package/package.js",
    "content": "Package.onUse(function (api) {\n  api.use('ecmascript');\n  api.addFiles('thrower.js', 'server');\n});\n"
  },
  {
    "path": "tools/tests/apps/app-throws-error/packages/throwing-package/thrower.js",
    "content": "process.env.THROW_FROM_PACKAGE && Meteor.startup(function () {\n  throw new Error(\"Should be line 2!\");\n});\n"
  },
  {
    "path": "tools/tests/apps/app-throws-error/throw.js",
    "content": "if (Meteor.isServer) {\n  process.env.THROW_FROM_PACKAGE || Meteor.startup(function () {\n    throw new Error(\"Should be line 3!\");\n  });\n}\n"
  },
  {
    "path": "tools/tests/apps/app-using-stylus/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/app-using-stylus/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nmy-package\nstylus\nstatic-html\n"
  },
  {
    "path": "tools/tests/apps/app-using-stylus/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/app-using-stylus/body.html",
    "content": "<body>\n  <div class=\"package-level\">package-level</div>\n  <div class=\"package-level-local-export\">package-level-local-export</div>\n  <div class=\"package-level-imported-to-app\">package-level-imported-to-app</div>\n  <div class=\"app-level\">app-level</div>\n  <div class=\"app-level-export\">app-level-export</div>\n</body>\n\n"
  },
  {
    "path": "tools/tests/apps/app-using-stylus/client/app-export.import.styl",
    "content": ".app-level-export {\n  background-color: aqua\n}\n\n"
  },
  {
    "path": "tools/tests/apps/app-using-stylus/client/app.styl",
    "content": "@import '{my-package}/package-export.styl'\n@import '{}/client/app-export.import.styl'\n\n.app-level {\n  background-color: chocolate\n}\n\n"
  },
  {
    "path": "tools/tests/apps/app-using-stylus/main.js",
    "content": "if (Meteor.isClient) {\n  Meteor.startup(function () {\n    var classes = ['app-level', 'app-level-export', 'package-level', 'package-level-local-export', 'package-level-imported-to-app'];\n    var colors = ['chocolate', 'cyan', 'salmon', 'red', 'blue'];\n    for (var i in classes) {\n      var selector = '.' + classes[i];\n      Meteor.call('print', getComputedStyle(document.querySelector(selector))['background-color'] === colorToRGBString(colors[i]));\n    }\n  });\n\n  function colorToRGBString(color) {\n    d = document.createElement(\"div\");\n    d.style.color = color;\n    document.body.appendChild(d);\n    var str = getComputedStyle(d).color;\n    document.body.removeChild(d);\n    return str;\n  }\n} else {\n  Meteor.methods({\n    print: function (str) {\n      console.log(str);\n    }\n  });\n}\n\n"
  },
  {
    "path": "tools/tests/apps/app-using-stylus/packages/my-package/package-export.styl",
    "content": ".package-level-imported-to-app {\n  background-color: blue\n}\n\n"
  },
  {
    "path": "tools/tests/apps/app-using-stylus/packages/my-package/package-file.main.styl",
    "content": ".package-level {\n  background-color: salmon\n}\n\n@import 'package-local-export.styl'\n\n"
  },
  {
    "path": "tools/tests/apps/app-using-stylus/packages/my-package/package-local-export.styl",
    "content": ".package-level-local-export {\n  background-color: red\n}\n\n"
  },
  {
    "path": "tools/tests/apps/app-using-stylus/packages/my-package/package.js",
    "content": "Package.describe({\n  summary: \"test local package for using stylus\"\n});\n\nPackage.onUse(function (api) {\n  api.addFiles('package-file.main.styl');\n  api.addFiles(['package-local-export.styl', 'package-export.styl'], 'client',\n               {isImport: true});\n\n  api.use('stylus');\n});\n"
  },
  {
    "path": "tools/tests/apps/app-with-atmosphere-package/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/app-with-atmosphere-package/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nglasser:package-for-selftest\n"
  },
  {
    "path": "tools/tests/apps/app-with-atmosphere-package/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/app-with-atmosphere-package/.meteor/versions",
    "content": "glasser:package-for-selftest@0.0.1\n"
  },
  {
    "path": "tools/tests/apps/app-with-unimported-lazy-file/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/app-with-unimported-lazy-file/.meteor/.id",
    "content": "# This file contains a token that is unique to your project.\n# Check it into your repository along with the rest of this directory.\n# It can be used for purposes such as:\n#   - ensuring you don't accidentally deploy one app on top of another\n#   - providing package authors with aggregated statistics\n\nic2o9oh3h8qt12iy9x7\n"
  },
  {
    "path": "tools/tests/apps/app-with-unimported-lazy-file/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base             # Packages every Meteor app needs to have\necmascript              # Enable ECMAScript2015+ syntax in app code\n"
  },
  {
    "path": "tools/tests/apps/app-with-unimported-lazy-file/.meteor/platforms",
    "content": "browser\nserver\n"
  },
  {
    "path": "tools/tests/apps/app-with-unimported-lazy-file/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/app-with-unimported-lazy-file/.meteor/versions",
    "content": "allow-deny@1.0.1-modules.2\nautopublish@1.0.4\nautoupdate@1.2.5-modules.2\nbabel-compiler@5.8.25-modules.3\nbabel-runtime@0.1.5-modules.2\nbase64@1.0.5-modules.2\nbinary-heap@1.0.5-modules.2\nblaze@2.1.4-modules.2\nblaze-html-templates@1.0.1\nblaze-tools@1.0.5-modules.2\nboilerplate-generator@1.0.5-modules.2\ncaching-compiler@1.0.1-modules.2\ncaching-html-compiler@1.0.3-modules.2\ncallback-hook@1.0.5-modules.2\ncheck@1.1.1-modules.2\nddp@1.2.2\nddp-client@1.2.2-modules.2\nddp-common@1.2.2\nddp-server@1.2.3-modules.2\ndeps@1.0.9\ndiff-sequence@1.0.2-modules.2\necmascript@0.3.1-modules.2\necmascript-runtime@0.2.7-modules.2\nejson@1.0.8-modules.2\nes5-shim@4.3.2-modules.2\nfastclick@1.0.8-modules.2\ngeojson-utils@1.0.5-modules.2\nhot-code-push@1.0.1-modules.2\nhtml-tools@1.0.6-modules.2\nhtmljs@1.0.6-modules.2\nhttp@1.1.2-modules.2\nid-map@1.0.4\ninsecure@1.0.4\njquery@1.11.5-modules.2\nlaunch-screen@1.0.5-modules.2\nlivedata@1.0.15\nlogging@1.0.9-modules.2\nmeteor@1.1.11-modules.2\nmeteor-base@1.0.1\nmeteor-env-dev@0.0.1-modules.2\nmeteor-env-prod@0.0.1-modules.2\nminifiers-css@1.1.8-modules.2\nminifiers-js@1.1.8-modules.2\nminimongo@1.0.11-modules.2\nmobile-experience@1.0.1\nmobile-status-bar@1.0.6\nmodules@0.4.1-modules.2\nmongo@1.1.4-modules.2\nmongo-id@1.0.1\nnpm-mongo@1.4.40-modules.2\nobserve-sequence@1.0.8-modules.2\nordered-dict@1.0.4\npromise@0.5.2-modules.2\nrandom@1.0.6-modules.2\nreactive-dict@1.1.4-modules.2\nreactive-var@1.0.6\nreload@1.1.5-modules.2\nretry@1.0.4\nroutepolicy@1.0.7-modules.2\nsession@1.1.2-modules.2\nspacebars@1.0.8-modules.2\nspacebars-compiler@1.0.8-modules.2\nstandard-minifiers@1.0.3-modules.2\nstandard-minifiers-css@1.0.3-modules.2\nstandard-minifiers-js@1.0.3-modules.2\ntemplating@1.1.6-modules.2\ntemplating-tools@1.0.1-modules.2\ntracker@1.0.10-modules.2\nui@1.0.8\nunderscore@1.0.5-modules.2\nurl@1.0.6-modules.2\nwebapp@1.2.4-modules.2\nwebapp-hashing@1.0.6-modules.2\n"
  },
  {
    "path": "tools/tests/apps/app-with-unimported-lazy-file/imports/file.js",
    "content": "console.log(\"This file shouldn't be loaded\");\n"
  },
  {
    "path": "tools/tests/apps/app-with-unimported-lazy-file/main.js",
    "content": "Meteor.startup(function() {\n  process.exit(1);\n});\n"
  },
  {
    "path": "tools/tests/apps/build-errors/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/build-errors/.meteor/packages",
    "content": "with-colon-plugin\n"
  },
  {
    "path": "tools/tests/apps/build-errors/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/build-errors/foo.awesome",
    "content": ""
  },
  {
    "path": "tools/tests/apps/build-errors/packages/with-colon-plugin/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "tools/tests/apps/build-errors/packages/with-colon-plugin/package.js",
    "content": "Package.describe({\n  summary: \"contains a plugin with colon in name\",\n  version: \"1.0.0\"\n});\n\nPackage.registerBuildPlugin({\n  name: \"with:colon\",\n  use: [],\n  sources: [\n    'plugin.js'\n  ]\n});\n"
  },
  {
    "path": "tools/tests/apps/build-errors/packages/with-colon-plugin/plugin.js",
    "content": "Plugin.registerSourceHandler(\"awesome\", function (compileStep) {\n  throw Error(\"crash in plugin\");\n});\n"
  },
  {
    "path": "tools/tests/apps/build-plugin-throws-error/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/build-plugin-throws-error/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n# Check this file (and the other files in this directory) into your repository.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nbuild-plugin\n"
  },
  {
    "path": "tools/tests/apps/build-plugin-throws-error/.meteor/release",
    "content": "METEOR@1.1.0.2\n"
  },
  {
    "path": "tools/tests/apps/build-plugin-throws-error/file.extension",
    "content": "Hello!"
  },
  {
    "path": "tools/tests/apps/build-plugin-throws-error/packages/build-plugin/README.md",
    "content": ""
  },
  {
    "path": "tools/tests/apps/build-plugin-throws-error/packages/build-plugin/build-plugin.js",
    "content": "Plugin.registerSourceHandler(\"extension\", function () {\n  throw new Error(\"Error inside a source handler!\");\n});"
  },
  {
    "path": "tools/tests/apps/build-plugin-throws-error/packages/build-plugin/package.js",
    "content": "Package.describe({\n  name: 'build-plugin',\n  version: '0.0.1',\n  // Brief, one-line summary of the package.\n  summary: '',\n  // URL to the Git repository containing the source code for this package.\n  git: '',\n  // By default, Meteor will default to using README.md for documentation.\n  // To avoid submitting documentation, set this field to null.\n  documentation: 'README.md'\n});\n\nPackage.registerBuildPlugin({\n  name: \"build-plugin-itself\",\n  sources: [\"build-plugin.js\"],\n  use: [\"ecmascript\"]\n});\n"
  },
  {
    "path": "tools/tests/apps/caching-coffee/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/caching-coffee/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\ncoffeescript\nlocal-pack\nstandard-minifiers\n"
  },
  {
    "path": "tools/tests/apps/caching-coffee/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/caching-coffee/f1.coffee",
    "content": "share.X = 'X is 2'\n"
  },
  {
    "path": "tools/tests/apps/caching-coffee/f2.coffee",
    "content": "share.Y = 'Y is 1'\n"
  },
  {
    "path": "tools/tests/apps/caching-coffee/f3.coffee",
    "content": "console.log 'Coffeescript', share.X, share.Y, FromPackage\n"
  },
  {
    "path": "tools/tests/apps/caching-coffee/packages/local-pack/p.coffee",
    "content": "FromPackage = 'FromPackage is 4'\n"
  },
  {
    "path": "tools/tests/apps/caching-coffee/packages/local-pack/package.js",
    "content": "Package.onUse(function (api) {\n  api.use(['coffeescript']);\n  api.addFiles(['p.coffee']);\n  api.export('FromPackage');\n});\n"
  },
  {
    "path": "tools/tests/apps/caching-less/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/caching-less/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nless\nlocal-pack\nstandard-minifiers\n"
  },
  {
    "path": "tools/tests/apps/caching-less/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/caching-less/imports/dotdot.less",
    "content": "@el3-style: groove;\n"
  },
  {
    "path": "tools/tests/apps/caching-less/output.js",
    "content": "console.log(\"Hello world\");\n"
  },
  {
    "path": "tools/tests/apps/caching-less/packages/local-pack/p.less",
    "content": "@el4-style: ridge;\n"
  },
  {
    "path": "tools/tests/apps/caching-less/packages/local-pack/package.js",
    "content": "Package.onUse(function (api) {\n  api.use(['less']);\n  api.addFiles('p.less', 'client', {isImport: true});\n});\n"
  },
  {
    "path": "tools/tests/apps/caching-less/subdir/foo.import.less",
    "content": "@el2-style: solid;\n@import \"../imports/dotdot.less\";\n"
  },
  {
    "path": "tools/tests/apps/caching-less/subdir/nested-root.less",
    "content": "@first-style: dashed;\n\n.el0 { border-style: @first-style; }\n"
  },
  {
    "path": "tools/tests/apps/caching-less/top.less",
    "content": "@first-style: dotted;\n@import \"subdir/foo.import.less\";\n\n.el1 { border-style: @first-style; }\n.el2 { border-style: @el2-style; }\n.el3 { border-style: @el3-style; }\n\n@import \"{local-pack}/p.less\";\n.el4 { border-style: @el4-style; }\n"
  },
  {
    "path": "tools/tests/apps/caching-stylus/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/caching-stylus/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nstylus\nlocal-pack\nstandard-minifiers\n"
  },
  {
    "path": "tools/tests/apps/caching-stylus/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/caching-stylus/imports/dotdot.styl",
    "content": "$el3-style = groove\n"
  },
  {
    "path": "tools/tests/apps/caching-stylus/output.js",
    "content": "console.log(\"Hello world\");\n"
  },
  {
    "path": "tools/tests/apps/caching-stylus/packages/local-pack/p.styl",
    "content": "$el4-style = ridge\n"
  },
  {
    "path": "tools/tests/apps/caching-stylus/packages/local-pack/package.js",
    "content": "Package.onUse(function (api) {\n  api.use(['stylus']);\n  api.addFiles('p.styl', 'client', {isImport: true});\n});\n"
  },
  {
    "path": "tools/tests/apps/caching-stylus/subdir/foo.import.styl",
    "content": "$el2-style = solid\n@import \"../imports/dotdot.styl\"\n"
  },
  {
    "path": "tools/tests/apps/caching-stylus/subdir/nested-root.styl",
    "content": "$first-style = dashed\n\n.el0 { border-style: $first-style; }\n"
  },
  {
    "path": "tools/tests/apps/caching-stylus/top.styl",
    "content": "$first-style = dotted\n@import \"subdir/foo.import.styl\"\n\n.el1 { border-style: $first-style; }\n.el2 { border-style: $el2-style; }\n.el3 { border-style: $el3-style; }\n\n@import \"{local-pack}/p.styl\"\n.el4 { border-style: $el4-style; }\n"
  },
  {
    "path": "tools/tests/apps/circular-deps/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/circular-deps/.meteor/packages",
    "content": ""
  },
  {
    "path": "tools/tests/apps/circular-deps/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/circular-deps/packages/first/package.js",
    "content": "Package.onUse(function(api) {\n  api.use('second');\n});\n"
  },
  {
    "path": "tools/tests/apps/circular-deps/packages/first-imply/package.js",
    "content": "Package.onUse(function(api) {\n  api.use('second-imply');\n});\n"
  },
  {
    "path": "tools/tests/apps/circular-deps/packages/first-unordered/package.js",
    "content": "Package.onUse(function(api) {\n  api.use('second-unordered');\n});\n"
  },
  {
    "path": "tools/tests/apps/circular-deps/packages/first-weak/package.js",
    "content": "Package.onUse(function(api) {\n  api.use('second-weak');\n});\n"
  },
  {
    "path": "tools/tests/apps/circular-deps/packages/second/package.js",
    "content": "Package.onUse(function(api) {\n  api.use('first');\n});\n"
  },
  {
    "path": "tools/tests/apps/circular-deps/packages/second-imply/package.js",
    "content": "Package.onUse(function(api) {\n  api.imply('first-imply');\n});\n"
  },
  {
    "path": "tools/tests/apps/circular-deps/packages/second-unordered/package.js",
    "content": "Package.onUse(function(api) {\n  api.use('first-unordered', {unordered: true});\n});\n"
  },
  {
    "path": "tools/tests/apps/circular-deps/packages/second-weak/package.js",
    "content": "Package.onUse(function(api) {\n  api.use('first-weak', {weak: true});\n});\n"
  },
  {
    "path": "tools/tests/apps/circular-deps/server/exit123.js",
    "content": "process.exit(123);\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-add-asset/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-add-asset/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\nlocal-plugin\nmeteor-base\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-add-asset/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-add-asset/foo.printme",
    "content": "Print out foo\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-add-asset/packages/local-plugin/package.js",
    "content": "Package.registerBuildPlugin({\n  name: \"compilePrintme\",\n  sources: ['plugin.js']\n});\n\nPackage.onUse(function (api) {\n  api.use('isobuild:compiler-plugin@1.0.0');\n});\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-add-asset/packages/local-plugin/plugin.js",
    "content": "Plugin.registerCompiler({\n  filenames: ['foo.printme']\n}, function () {\n  return new PrintmeCompiler();\n});\n\nvar PrintmeCompiler = function () {\n};\nPrintmeCompiler.prototype.processFilesForTarget = function (inputFiles) {\n  inputFiles.forEach(function (inputFile) {\n    console.log(\"extension is\", inputFile.getExtension());\n    inputFile.addAsset({\n      path: inputFile.getPathInPackage(),\n      data: inputFile.getContentsAsString()\n    });\n  });\n};\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-add-asset/use-asset.js",
    "content": "console.log(\"Asset says\", Assets.getText(\"foo.printme\"));\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-asset-and-source/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-asset-and-source/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n# Check this file (and the other files in this directory) into your repository.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nasset-and-source\necmascript\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-asset-and-source/.meteor/release",
    "content": "METEOR@1.1.0.3\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-asset-and-source/packages/asset-and-source/asset-and-source.js",
    "content": "if (Meteor.isServer) {\n  // Printing out my own source code!\n  console.log(Assets.getText(\"asset-and-source.js\"));\n}\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-asset-and-source/packages/asset-and-source/package.js",
    "content": "Package.describe({\n  name: 'asset-and-source',\n  version: '0.0.1'\n});\n\nPackage.onUse(function(api) {\n  api.addFiles('asset-and-source.js');\n  api.addAssets('asset-and-source.js', ['client', 'server']);\n});\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html/.meteor/.id",
    "content": "# This file contains a token that is unique to your project.\n# Check it into your repository along with the rest of this directory.\n# It can be used for purposes such as:\n#   - ensuring you don't accidentally deploy one app on top of another\n#   - providing package authors with aggregated statistics\n\no2vi6w1m82bge9k2mhb\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\nmeteor-base\nstatic-html\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html/.meteor/platforms",
    "content": "browser\nserver\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html/.meteor/versions",
    "content": "autoupdate@1.2.2-plugins.0\nbabel-compiler@5.8.3-plugins.0_5\nbabel-runtime@0.1.2\nbase64@1.0.4-plugins.0\nbinary-heap@1.0.4-plugins.0\nblaze@2.1.3-plugins.0\nblaze-tools@1.0.4-plugins.0\nboilerplate-generator@1.0.4-plugins.0\ncaching-compiler@1.0.0-plugins.1\ncaching-html-compiler@1.0.0\ncallback-hook@1.0.4-plugins.0\ncheck@1.0.6-plugins.0\nddp@1.2.0-plugins.0\nddp-client@1.2.0-plugins.0\nddp-common@1.2.0-plugins.0\nddp-server@1.2.0-plugins.1\ndeps@1.0.8-plugins.0\ndiff-sequence@1.0.0-plugins.0\necmascript@0.1.3-plugins.1\nejson@1.0.7-plugins.0\ngeojson-utils@1.0.4-plugins.0\nhtml-tools@1.0.5-plugins.0\nhtmljs@1.0.5-plugins.0\nhttp@1.1.1-plugins.0\nid-map@1.0.4-plugins.0\njquery@1.11.3-plugins.0_3\njson@1.0.4-plugins.0\nlogging@1.0.8-plugins.0\nmeteor@1.1.7-plugins.1\nminifiers@1.1.6-plugins.0\nminimongo@1.0.9-plugins.0\nmongo@1.1.1-plugins.0\nmongo-id@1.0.0-plugins.0\nnpm-mongo@1.4.32-plugins.0_1\nobserve-sequence@1.0.7-plugins.0\nordered-dict@1.0.4-plugins.0\npromise@0.4.2-plugins.0\nrandom@1.0.4-plugins.0\nreactive-var@1.0.6-plugins.0\nreload@1.1.4-plugins.0\nretry@1.0.4-plugins.0\nroutepolicy@1.0.6-plugins.0\nspacebars@1.0.7-plugins.0\nspacebars-compiler@1.0.7-plugins.1\nstatic-html@0.0.1\ntemplating@1.1.2-plugins.1\ntemplating-tools@0.0.1\ntracker@1.0.8-plugins.0\nui@1.0.7-plugins.0\nunderscore@1.0.4-plugins.0\nurl@1.0.5-plugins.0\nwebapp@1.2.1-plugins.0\nwebapp-hashing@1.0.4-plugins.0\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html/static.html",
    "content": "<head>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n</head>\n\n<body>\n  <div>I have a body, yet no Blaze!</div>\n</body>\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html-error/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html-error/.meteor/.id",
    "content": "# This file contains a token that is unique to your project.\n# Check it into your repository along with the rest of this directory.\n# It can be used for purposes such as:\n#   - ensuring you don't accidentally deploy one app on top of another\n#   - providing package authors with aggregated statistics\n\no2vi6w1m82bge9k2mhb\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html-error/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\nmeteor-base\nstatic-html\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html-error/.meteor/platforms",
    "content": "browser\nserver\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html-error/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html-error/.meteor/versions",
    "content": "autoupdate@1.2.2-plugins.0\nbabel-compiler@5.8.3-plugins.0_5\nbabel-runtime@0.1.2\nbase64@1.0.4-plugins.0\nbinary-heap@1.0.4-plugins.0\nblaze@2.1.3-plugins.0\nblaze-tools@1.0.4-plugins.0\nboilerplate-generator@1.0.4-plugins.0\ncaching-compiler@1.0.0-plugins.1\ncaching-html-compiler@1.0.0\ncallback-hook@1.0.4-plugins.0\ncheck@1.0.6-plugins.0\nddp@1.2.0-plugins.0\nddp-client@1.2.0-plugins.0\nddp-common@1.2.0-plugins.0\nddp-server@1.2.0-plugins.1\ndeps@1.0.8-plugins.0\ndiff-sequence@1.0.0-plugins.0\necmascript@0.1.3-plugins.1\nejson@1.0.7-plugins.0\ngeojson-utils@1.0.4-plugins.0\nhtml-tools@1.0.5-plugins.0\nhtmljs@1.0.5-plugins.0\nhttp@1.1.1-plugins.0\nid-map@1.0.4-plugins.0\njquery@1.11.3-plugins.0_3\njson@1.0.4-plugins.0\nlogging@1.0.8-plugins.0\nmeteor@1.1.7-plugins.1\nminifiers@1.1.6-plugins.0\nminimongo@1.0.9-plugins.0\nmongo@1.1.1-plugins.0\nmongo-id@1.0.0-plugins.0\nnpm-mongo@1.4.32-plugins.0_1\nobserve-sequence@1.0.7-plugins.0\nordered-dict@1.0.4-plugins.0\npromise@0.4.2-plugins.0\nrandom@1.0.4-plugins.0\nreactive-var@1.0.6-plugins.0\nreload@1.1.4-plugins.0\nretry@1.0.4-plugins.0\nroutepolicy@1.0.6-plugins.0\nspacebars@1.0.7-plugins.0\nspacebars-compiler@1.0.7-plugins.1\nstatic-html@0.0.1\ntemplating@1.1.2-plugins.1\ntemplating-tools@0.0.1\ntracker@1.0.8-plugins.0\nui@1.0.7-plugins.0\nunderscore@1.0.4-plugins.0\nurl@1.0.5-plugins.0\nwebapp@1.2.1-plugins.0\nwebapp-hashing@1.0.4-plugins.0\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-static-html-error/static.html",
    "content": "<head attr=\"not allowed\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n</head>\n\n<body>\n  <div>I have a body, yet no Blaze!</div>\n</body>\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-throws-on-instantiate/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-throws-on-instantiate/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-throws-on-instantiate/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-throws-on-instantiate/foo.printme",
    "content": "Print out foo\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-throws-on-instantiate/packages/local-plugin/package.js",
    "content": "Package.registerBuildPlugin({\n  name: \"compilePrintme\",\n  sources: ['plugin.js']\n});\n\nPackage.onUse(function (api) {\n  api.use('isobuild:compiler-plugin@1.0.0');\n});\n"
  },
  {
    "path": "tools/tests/apps/compiler-plugin-throws-on-instantiate/packages/local-plugin/plugin.js",
    "content": "Plugin.registerCompiler({\n  extensions: ['printme'],\n  archMatching: 'os'\n}, function () {\n  throw new Error(\"Error in my registerCompiler callback!\");\n});\n"
  },
  {
    "path": "tools/tests/apps/css-injection-test/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/css-injection-test/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\njquery\n"
  },
  {
    "path": "tools/tests/apps/css-injection-test/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/css-injection-test/css-injection-test.js",
    "content": "if (Meteor.isClient) {\n  var backgroundColor = function () {\n    return $(document.body).css('background-color');\n  };\n\n  var linkHref = function () {\n    var links = document.getElementsByTagName('link');\n    if (links.length > 0) {\n      return links[0].href;\n    } else {\n      return null;\n    }\n  }\n\n  Meteor.startup(function () {\n    Meteor.call(\"clientLoad\");\n    var numCssChanges = 0;\n    var oldBackgroundColor = backgroundColor();\n    var oldLinkHref = linkHref();\n    Meteor.call(\"newStylesheet\", numCssChanges, oldBackgroundColor);\n    var waitingForCssReloadToComplete = false;\n    Meteor.setInterval(function () {\n      if (waitingForCssReloadToComplete)\n        return;\n\n      var newBackgroundColor = backgroundColor();\n      if (oldBackgroundColor !== newBackgroundColor) {\n        waitingForCssReloadToComplete = true;\n\n        // give the client some time to load the new css\n        var handle = Meteor.setInterval(function () {\n          var newLinkHref = linkHref();\n          if (newLinkHref !== oldLinkHref) {\n            oldBackgroundColor = backgroundColor();\n            oldLinkHref = newLinkHref;\n            Meteor.call(\"newStylesheet\", ++numCssChanges, oldBackgroundColor);\n            waitingForCssReloadToComplete = false;\n            Meteor.clearInterval(handle);\n          }\n        }, 500);\n      }\n    }, 500);\n  });\n}\n\nif (Meteor.isServer) {\n  Meteor.methods({\n    clientLoad: function () {\n      console.log(\"client connected\");\n    },\n\n    newStylesheet: function (numCssChanges, backgroundColor) {\n      console.log(\"numCssChanges: \" + numCssChanges);\n      console.log(\"background-color: \" + backgroundColor);\n    }\n  });\n}\n"
  },
  {
    "path": "tools/tests/apps/css-injection-test/packages/my-package/foo.css",
    "content": ""
  },
  {
    "path": "tools/tests/apps/css-injection-test/packages/my-package/package.js",
    "content": "Package.describe({\n  summary: \"test local package reloading\"\n});\n\nPackage.onUse(function (api) {\n  api.addFiles('foo.css', 'client');\n});"
  },
  {
    "path": "tools/tests/apps/custom-minifier/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/custom-minifier/.meteor/packages",
    "content": "meteor-base\ncustom-minifier\nblaze-html-templates\n"
  },
  {
    "path": "tools/tests/apps/custom-minifier/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/custom-minifier/body.html",
    "content": "<body>\n  <div class=\"production_css\">Text for prod</div>\n  <div class=\"development_css\">Text for devel</div>\n</body>\n"
  },
  {
    "path": "tools/tests/apps/custom-minifier/code.js",
    "content": "if (Meteor.isClient) {\n  Meteor.startup(function () {\n    _.each(['production_css', 'development_css'], function (cls) {\n      var color = getComputedStyle(document.querySelectorAll('.' + cls)[0]).color;\n      Meteor.call('print', cls + ': ' + color);\n    });\n\n    // this log is expected to be transformed by minifier\n    Meteor.call('print', 'Message (client): foo');\n  });\n} else {\n  Meteor.startup(function () {\n    // since we don't run minifiers for server targets, this is going\n    // to be printed as \"foo\" and not as \"production_js\" or\n    // \"development_js\"\n    console.log('Message: foo');\n  });\n\n  Meteor.methods({\n    print: function (message) {\n      console.log(message);\n    }\n  });\n}\n"
  },
  {
    "path": "tools/tests/apps/custom-minifier/packages/custom-minifier/package.js",
    "content": "Package.describe({\n  name: 'custom-minifier',\n  version: '0.0.1',\n  documentation: null\n});\n\nPackage.registerBuildPlugin({\n  name: \"minifyCustom\",\n  sources: [\n    'plugin/minify.js'\n  ]\n});\n\nPackage.onUse(function(api) {\n  api.use('isobuild:minifier-plugin@1.0.0');\n});\n"
  },
  {
    "path": "tools/tests/apps/custom-minifier/packages/custom-minifier/plugin/minify.js",
    "content": "Plugin.registerMinifier({\n  extensions: [\"js\"]\n}, function () {\n  var minifier = new CustomMinifier('js');\n  return minifier;\n});\n\nPlugin.registerMinifier({\n  extensions: [\"css\"]\n}, function () {\n  var minifier = new CustomMinifier('css');\n  return minifier;\n});\n\nfunction CustomMinifier(type) {\n  this.type = type;\n};\n\nCustomMinifier.prototype.processFilesForBundle = function (files, options) {\n  var self = this;\n  var mode = options.minifyMode;\n\n  files.forEach(function (file) {\n    var contents =\n      file.getContentsAsString().replace(/foo/g, mode + '_' + self.type);\n\n    if (self.type === 'js') {\n      file.addJavaScript({\n        data: contents\n      });\n    } else {\n      file.addStylesheet({\n        data: contents\n      });\n    }\n\n    Plugin.nudge();\n  });\n};\n\n\n"
  },
  {
    "path": "tools/tests/apps/custom-minifier/styles.css",
    "content": ".foo {\n  color: red\n}\n"
  },
  {
    "path": "tools/tests/apps/ddp-heartbeat/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/ddp-heartbeat/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nunderscore\n"
  },
  {
    "path": "tools/tests/apps/ddp-heartbeat/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/ddp-heartbeat/server/heartbeat_test.js",
    "content": "var Fiber = Npm.require(\"fibers\");\nvar Future = Npm.require(\"fibers/future\");\n\n// XXX Deps isn't supported on the server... but we need a way to\n// capture client connection status transitions.\n\nvar waitReactive = function (fn) {\n  var future = new Future();\n  var timeoutHandle = Meteor.setTimeout(\n    function () {\n      future.throw(new Error(\"timeout\"));\n    },\n    60000\n  );\n  Deps.autorun(function (c) {\n    var ret = fn();\n    if (ret) {\n      c.stop();\n      Meteor.clearTimeout(timeoutHandle);\n\n      // We need to run in a fiber for `defer`.\n      Fiber(function () {\n        // Use `defer` because yields are blocked inside of autorun.\n        Meteor.defer(function () {\n          future.return(ret);\n        })\n      }).run();\n    }\n  });\n  return future.wait();\n};\n\nvar waitForClientConnectionStatus = function (connection, status) {\n  waitReactive(function () {\n    return connection.status().status === status;\n  });\n};\n\n\n// Expect to connect, and then to reconnect (presumably because of a\n// timeout).\n\nvar expectConnectAndReconnect = function (clientConnection) {\n  console.log(\"client is connecting\");\n  waitForClientConnectionStatus(clientConnection, \"connected\");\n\n  console.log(\"client is connected, expecting ping timeout and reconnect\");\n  waitForClientConnectionStatus(clientConnection, \"connecting\");\n\n  console.log(\"client is reconnecting\");\n};\n\n\nvar testClientTimeout = function () {\n  console.log(\"Test client timeout\");\n\n  var savedServerOptions = _.clone(Meteor.server.options);\n  Meteor.server.options.heartbeatInterval = 0;\n  Meteor.server.options.respondToPings = false;\n\n  var clientConnection = DDP.connect(Meteor.absoluteUrl());\n\n  expectConnectAndReconnect(clientConnection);\n\n  clientConnection.close();\n\n  Meteor.server.options = savedServerOptions;\n\n  console.log(\"test successful\\n\");\n};\n\n\nvar testServerTimeout = function () {\n  console.log(\"Test server timeout\");\n\n  var clientConnection = DDP.connect(\n    Meteor.absoluteUrl(),\n    {\n      heartbeatInterval: 0,\n      respondToPings: false\n    }\n  );\n\n  expectConnectAndReconnect(clientConnection);\n\n  clientConnection.close();\n  console.log(\"test successful\\n\");\n};\n\nFiber(function () {\n  Meteor._printReceivedDDP = true;\n  Meteor._printSentDDP = true;\n  testClientTimeout();\n  testServerTimeout();\n  process.exit(0);\n}).run();\n"
  },
  {
    "path": "tools/tests/apps/debug-only-test/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n# Check this file (and the other files in this directory) into your repository.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base             # Packages every Meteor app needs to have\nmobile-experience       # Packages for a great mobile UX\nmongo                   # The database Meteor supports right now\nblaze-html-templates    # Compile .html files into Meteor Blaze views\nsession                 # Client-side reactive dictionary for your app\njquery                  # Helpful client-side library\ntracker                 # Meteor's client-side reactive programming library\n\nstandard-minifiers      # JS/CSS minifiers run for production mode\nes5-shim                # ECMAScript 5 compatibility for older browsers.\necmascript              # Enable ECMAScript2015+ syntax in app code\n\nautopublish             # Publish all data to the clients (for prototyping)\ninsecure                # Allow all DB writes from clients (for prototyping)\n"
  },
  {
    "path": "tools/tests/apps/debug-only-test/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/debug-only-test/packages/debug-only-prod-only/package.js",
    "content": "Package.describe({\n  name: 'debug-only-prod-only',\n  debugOnly: true\n});\n\n// Test setting debugOnly and prodOnly in two different Package.describe calls,\n// because if this is caught, then setting them in the same Package.describe\n// call will definitely be caught!\nPackage.describe({\n  name: 'debug-only-prod-only',\n  prodOnly: true\n});\n\nPackage.onUse(function(api) {\n  // nothing\n});\n"
  },
  {
    "path": "tools/tests/apps/dev-bundle-bin-commands/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/dev-bundle-bin-commands/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n# Check this file (and the other files in this directory) into your repository.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base             # Packages every Meteor app needs to have\necmascript\n"
  },
  {
    "path": "tools/tests/apps/dev-bundle-bin-commands/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/dev-bundle-bin-commands/package.json",
    "content": "{\n  \"name\": \"dev-bundle-bin-commands\",\n  \"private\": true,\n  \"scripts\": {\n    \"start\": \"meteor run\",\n    \"exit-with-status\": \"echo \\\"This script has an exit status\\\" && exit 1\",\n    \"exit-normally\": \"echo \\\"This script will exit normally\\\" && exit 0\"\n  },\n  \"dependencies\": {\n    \"meteor-node-stubs\": \"~0.2.0\"\n  }\n}\n"
  },
  {
    "path": "tools/tests/apps/duplicate-compiler-extensions/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/duplicate-compiler-extensions/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nlocal-plugin\nanother-local-plugin\n"
  },
  {
    "path": "tools/tests/apps/duplicate-compiler-extensions/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/duplicate-compiler-extensions/bar.printme",
    "content": "Print out bar\n"
  },
  {
    "path": "tools/tests/apps/duplicate-compiler-extensions/foo.printme",
    "content": "Print out foo\n"
  },
  {
    "path": "tools/tests/apps/duplicate-compiler-extensions/packages/another-local-plugin/package.js",
    "content": "Package.registerBuildPlugin({\n  name: \"anotherCompiler\",\n  sources: ['plugin.js']\n});\n\nPackage.onUse(function (api) {\n  api.use('isobuild:compiler-plugin@1.0.0');\n});\n"
  },
  {
    "path": "tools/tests/apps/duplicate-compiler-extensions/packages/another-local-plugin/plugin.js",
    "content": "Plugin.registerCompiler({\n  extensions: ['myext']\n}, function () {\n  return { processFilesForTarget: function () {} };\n});\n"
  },
  {
    "path": "tools/tests/apps/duplicate-compiler-extensions/packages/local-plugin/package.js",
    "content": "Package.registerBuildPlugin({\n  name: \"somePlugin\",\n  sources: ['plugin.js']\n});\n\nPackage.onUse(function (api) {\n  api.use('isobuild:compiler-plugin@1.0.0');\n});\n"
  },
  {
    "path": "tools/tests/apps/duplicate-compiler-extensions/packages/local-plugin/plugin.js",
    "content": "Plugin.registerCompiler({\n  extensions: ['myext']\n}, function () {\n  return { processFilesForTarget: function () {} };\n});\n"
  },
  {
    "path": "tools/tests/apps/empty/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/empty/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n"
  },
  {
    "path": "tools/tests/apps/empty/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/failover-test/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/failover-test/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor\nmongo-livedata\nunderscore\nrandom\n"
  },
  {
    "path": "tools/tests/apps/failover-test/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/failover-test/server/failover-test.js",
    "content": "// Tests that an observeChanges created before a failover continues to work\n// after the failover. Doesn't test anything in particular about writes that\n// occur immediately before the failover, but does ensure that a write after the\n// failover is observed.\n//\n// Prints various things. On success, prints SUCCESS and exits 0. On failure,\n// exits non-0.\n\nvar C = new Mongo.Collection(Random.id());\n\nvar steps = {};\nvar nextStepTimeout = null;\n\nvar setNextStepTimeout = function () {\n  nextStepTimeout = Meteor.setTimeout(function () {\n    console.log('Waited too long and no next step happened.');\n    process.exit(1);\n  }, 30*1000);\n};\n\nvar originalMasterName = null;\n\nsteps.initialized = function () {\n  // Great, we got the first thing. Let's get another thing.\n  C.insert({step: 'next'});\n  var master = C.rawDatabase().serverConfig._state.master;\n  if (!master) {\n    console.log(\"No master in initialized?\");\n    process.exit(1);\n  }\n  originalMasterName = master.name;\n  console.log(\"Master starts as\", originalMasterName);\n};\n\nsteps.next = function () {\n  // Great, we can continue to add things. Now trigger a failover.\n  C.rawDatabase().admin().command({replSetStepDown: 60, force: true});\n  while (true) {\n    try {\n      console.log(\"trying to insert\");\n      C.insert({step: 'steppedDown'});\n      console.log(\"inserted\");\n      return;\n    } catch (e) {\n      console.log(\"failed to insert\", e);\n    }\n  }\n};\n\nsteps.steppedDown = function () {\n  console.log(\"Write succeeded after stepdown.\");\n  var master = C.rawDatabase().serverConfig._state.master;\n  if (!master) {\n    console.log(\"No master in steppedDown?\");\n    process.exit(1);\n  }\n  if (master.name === originalMasterName) {\n    console.log(\"Master didn't change?\");\n    process.exit(1);\n  }\n  console.log(\"Master ended as\", master.name);\n  console.log(\"SUCCESS\");\n  process.exit(0);\n};\n\nC.find().observeChanges({\n  added: function (id, fields) {\n    if (nextStepTimeout) {\n      Meteor.clearTimeout(nextStepTimeout);\n      nextStepTimeout = null;\n    }\n    if (!fields.step && _.has(steps, fields.step)) {\n      console.log('Unexpected step:', fields.step);\n      process.exit(1);\n    }\n    console.log(\"Step\", fields.step);\n    steps[fields.step]();\n    setNextStepTimeout();\n  }\n});\n\nsetNextStepTimeout();\n\nC.insert({step: 'initialized'});\n"
  },
  {
    "path": "tools/tests/apps/hot-code-push-test/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/hot-code-push-test/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nblaze-html-templates\nsession\n"
  },
  {
    "path": "tools/tests/apps/hot-code-push-test/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/hot-code-push-test/hot-code-push-test.html",
    "content": "<head><title>bla</title></head>\n"
  },
  {
    "path": "tools/tests/apps/hot-code-push-test/hot-code-push-test.js",
    "content": "if (Meteor.isClient) {\n  var sessionVar = Session.get(\"sessionVar\");\n\n  var maybeCall = function () {\n    var A = Package.autoupdate.Autoupdate;\n    if (A._ClientVersions.findOne() && ! A.newClientAvailable()) {\n      Meteor.call(\"clientLoad\",\n                  typeof jsVar === 'undefined' ? 'undefined' : jsVar,\n                  typeof packageVar === 'undefined' ? 'undefined' : packageVar,\n                  sessionVar);\n    } else {\n      setTimeout(maybeCall, 100);\n    }\n  };\n  // Wait a little to \"ensure\" that \"client modified\" messages (etc) appear\n  // before our messages\n  setTimeout(maybeCall, 300);\n\n  Session.setDefault(\"sessionVar\", true);\n}\n\nif (Meteor.isServer) {\n  var clientConnections = 0;\n\n  Meteor.methods({\n    clientLoad: function (jsVar, packageVar, sessionVar) {\n      // Make sure that the process still has the correct working directory.\n      process.cwd();\n      console.log(\"client connected: \" + clientConnections++);\n      console.log(\"jsVar: \" + jsVar);\n      console.log(\"packageVar: \" + packageVar);\n      console.log(\"sessionVar: \" + sessionVar);\n    }\n  });\n}\n"
  },
  {
    "path": "tools/tests/apps/hot-code-push-test/packages/my-package/foo.js",
    "content": "packageVar = 'foo';"
  },
  {
    "path": "tools/tests/apps/hot-code-push-test/packages/my-package/package.js",
    "content": "Package.describe({\n  summary: \"test local package reloading\"\n});\n\nPackage.onUse(function (api) {\n  api.export('packageVar');\n  api.addFiles('foo.js', 'client');\n});"
  },
  {
    "path": "tools/tests/apps/lint-on-publish/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/lint-on-publish/.meteor/.id",
    "content": "# This file contains a token that is unique to your project.\n# Check it into your repository along with the rest of this directory.\n# It can be used for purposes such as:\n#   - ensuring you don't accidentally deploy one app on top of another\n#   - providing package authors with aggregated statistics\n\npx4xdo1uz1w7npyqxfr\n"
  },
  {
    "path": "tools/tests/apps/lint-on-publish/.meteor/packages",
    "content": "meteor-base\njshint\n"
  },
  {
    "path": "tools/tests/apps/lint-on-publish/.meteor/platforms",
    "content": "server\nbrowser\n"
  },
  {
    "path": "tools/tests/apps/lint-on-publish/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/lint-on-publish/a.js",
    "content": "AppVariable = {};\n"
  },
  {
    "path": "tools/tests/apps/lint-on-publish/packages/dep-package/dep-package.js",
    "content": "DepPackageVar = {};\n"
  },
  {
    "path": "tools/tests/apps/lint-on-publish/packages/dep-package/package.js",
    "content": "Package.describe({\n  name: 'dep-package',\n  version: '0.0.1',\n  documentation: null\n});\n\nPackage.onUse(function(api) {\n  api.addFiles('dep-package.js');\n  api.use('jshint');\n});\n"
  },
  {
    "path": "tools/tests/apps/lint-on-publish/packages/my-package/.versions",
    "content": "jshint@0.0.1\nmeteor@1.1.6\nmy-package@0.0.1\nunderscore@1.0.3\n"
  },
  {
    "path": "tools/tests/apps/lint-on-publish/packages/my-package/my-package.js",
    "content": "PackageVar = {};\n"
  },
  {
    "path": "tools/tests/apps/lint-on-publish/packages/my-package/package.js",
    "content": "Package.describe({\n  name: 'my-package',\n  version: '0.0.1',\n  documentation: null\n});\n\nPackage.onUse(function(api) {\n  api.addFiles('my-package.js');\n  api.use('jshint');\n  api.use('dep-package'); // local dependency\n});\n\n"
  },
  {
    "path": "tools/tests/apps/linting-app/.jshintrc",
    "content": "{\n  \"undef\": true\n}\n"
  },
  {
    "path": "tools/tests/apps/linting-app/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/linting-app/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nmy-package\njshint\n"
  },
  {
    "path": "tools/tests/apps/linting-app/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/linting-app/a.html",
    "content": "<body>\n  no content\n</body>\n"
  },
  {
    "path": "tools/tests/apps/linting-app/client/client.js",
    "content": "GlobalVar = {};\n"
  },
  {
    "path": "tools/tests/apps/linting-app/packages/my-package/.jshintrc",
    "content": "{\n  \"undef\": true\n}\n"
  },
  {
    "path": "tools/tests/apps/linting-app/packages/my-package/.versions",
    "content": "jshint@0.0.1\nlinter-plugin@1.0.0\nmeteor@1.1.6\nmy-package@0.0.0\nunderscore@1.0.3\n"
  },
  {
    "path": "tools/tests/apps/linting-app/packages/my-package/package-client.js",
    "content": "PackageGlobalVar = {};\n"
  },
  {
    "path": "tools/tests/apps/linting-app/packages/my-package/package-server.js",
    "content": "PackageGlobalVar = {};\nPermittedGlobal = {};\nPackage.minimongo.accessPackageVarInMeteor = \"is OK\";\n"
  },
  {
    "path": "tools/tests/apps/linting-app/packages/my-package/package.js",
    "content": "Package.describe({\n  summary: \"test local package for using linting\"\n});\n\nPackage.onUse(function (api) {\n  api.addFiles('package-client.js', 'client');\n  api.addFiles('package-server.js', 'server');\n  api.addFiles('.jshintrc');\n\n  api.use(['jshint', 'minimongo']);\n});\n"
  },
  {
    "path": "tools/tests/apps/linting-app/server/server.js",
    "content": "GlobalVar = {};\n"
  },
  {
    "path": "tools/tests/apps/local-compiler-plugin/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/local-compiler-plugin/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nlocal-plugin\n"
  },
  {
    "path": "tools/tests/apps/local-compiler-plugin/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/local-compiler-plugin/bar.printme",
    "content": "Print out bar\n"
  },
  {
    "path": "tools/tests/apps/local-compiler-plugin/foo.printme",
    "content": "Print out foo\n"
  },
  {
    "path": "tools/tests/apps/local-compiler-plugin/packages/local-plugin/package.js",
    "content": "Package.registerBuildPlugin({\n  name: \"compilePrintme\",\n  sources: ['plugin.js']\n});\n\nPackage.onUse(function (api) {\n  api.use('isobuild:compiler-plugin@1.0.0');\n});\n"
  },
  {
    "path": "tools/tests/apps/local-compiler-plugin/packages/local-plugin/plugin.js",
    "content": "var fs = Plugin.fs;\nvar path = Plugin.path;\n\nPlugin.registerCompiler({\n  extensions: ['printme'],\n  archMatching: 'os'\n}, function () {\n  return new PrintmeCompiler();\n});\n\nvar PrintmeCompiler = function () {\n  var self = this;\n  self.runCount = 0;\n  self.diskCache = null;\n};\nPrintmeCompiler.prototype.processFilesForTarget = function (inputFiles) {\n  var self = this;\n  inputFiles.forEach(function (inputFile) {\n    var source = inputFile.getContentsAsString();\n    inputFile.addJavaScript({\n      path: inputFile.getPathInPackage() + \".js\",\n      sourcePath: inputFile.getPathInPackage(),\n      data: \"console.log('PMC: ' + \" + JSON.stringify(source) + \");\\n\"\n    });\n  });\n  console.log(\"PrintmeCompiler invocation\", ++self.runCount);\n  if (self.diskCache) {\n    fs.writeFileSync(self.diskCache, self.runCount + '\\n');\n  }\n};\nPrintmeCompiler.prototype.setDiskCacheDirectory = function (diskCacheDir) {\n  var self = this;\n  self.diskCache = path.join(diskCacheDir, 'cache');\n  try {\n    var data = fs.readFileSync(self.diskCache, 'utf8');\n  } catch (e) {\n    if (e.code !== 'ENOENT')\n      throw e;\n    return;\n  }\n  self.runCount = parseInt(data, 10);\n};\n"
  },
  {
    "path": "tools/tests/apps/minification-css-splitting/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/minification-css-splitting/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nstandard-minifiers\nstylus\nautoupdate\nblaze-html-templates\n"
  },
  {
    "path": "tools/tests/apps/minification-css-splitting/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/minification-css-splitting/body.html",
    "content": "<body>\n  <div class=\"class-1\"></div>\n  <div class=\"class-1024\"></div>\n  <div class=\"class-4096\"></div>\n  <div class=\"class-4097\">some inner text</div>\n</body>\n"
  },
  {
    "path": "tools/tests/apps/minification-css-splitting/client/lots-of-styles.main.styl",
    "content": "for row in 1..4097\n  .class-{row}::before\n    content: '\"' + row + '\"'\n\n.class-4097\n  color: green\n"
  },
  {
    "path": "tools/tests/apps/minification-css-splitting/code.js",
    "content": "if (Meteor.isClient) {\n  function report () {\n    Meteor.call(\n      'output',\n      'the number of stylesheets: <' +\n      document.querySelectorAll('link[rel=stylesheet]').length + '>');\n\n    Meteor.call(\n      'output',\n      'the color of the tested 4097th property: <' +\n      getComputedStyle(document.querySelectorAll('.class-4097')[0]).color +\n      '>');\n  };\n  function linkHref (prev) {\n    var links = document.getElementsByTagName('link');\n    if (links.length === 2) {\n      return JSON.stringify(_.pluck(links, 'href'));\n    } else if (links.length > 0 && links.length > 2) {\n      // this is the period of time when we have both new and old\n      // stylesheets, just count this as \"nothing changed\"\n      return prev;\n    } else {\n      return null;\n    }\n  }\n\n  Meteor.startup(function () {\n    Meteor.call(\"clientLoad\");\n    var numCssChanges = 0;\n    var oldLinkHref = linkHref();\n    report();\n    var waitingForCssReloadToComplete = false;\n\n    // give the client some time to load the new css\n    var handle = Meteor.setInterval(function () {\n      var newLinkHref = linkHref(oldLinkHref);\n      if (newLinkHref !== oldLinkHref) {\n        oldLinkHref = newLinkHref;\n        report();\n      }\n    }, 500);\n  });\n} else {\n  Meteor.methods({\n    output: function (text) {\n      console.log(text);\n    },\n    clientLoad: function () {\n      console.log('client connected');\n    }\n  });\n}\n"
  },
  {
    "path": "tools/tests/apps/minifier-plugin-bad-extension/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/minifier-plugin-bad-extension/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nlocal-plugin\n"
  },
  {
    "path": "tools/tests/apps/minifier-plugin-bad-extension/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/minifier-plugin-bad-extension/packages/local-plugin/package.js",
    "content": "Package.registerBuildPlugin({\n  name: \"bad-minifier\",\n  sources: ['plugin.js']\n});\n\nPackage.onUse(function (api) {\n  api.use('isobuild:minifier-plugin@1.0.0');\n});\n"
  },
  {
    "path": "tools/tests/apps/minifier-plugin-bad-extension/packages/local-plugin/plugin.js",
    "content": "Plugin.registerMinifier({\n  extensions: [\"foo\"]\n}, function () {\n  var minifier = new Minifier();\n  return minifier;\n});\n\nfunction Minifier () {};\n\nMinifier.prototype.processFilesForBundle = function (files) { };\n\n"
  },
  {
    "path": "tools/tests/apps/minifier-plugin-multiple-minifiers-for-js/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/minifier-plugin-multiple-minifiers-for-js/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nblaze-html-templates\nlocal-plugin\nlocal-plugin-2\n"
  },
  {
    "path": "tools/tests/apps/minifier-plugin-multiple-minifiers-for-js/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/minifier-plugin-multiple-minifiers-for-js/packages/local-plugin/package.js",
    "content": "Package.registerBuildPlugin({\n  name: \"bad-minifier\",\n  sources: ['plugin.js']\n});\n\nPackage.onUse(function (api) {\n  api.use('isobuild:minifier-plugin@1.0.0');\n});\n"
  },
  {
    "path": "tools/tests/apps/minifier-plugin-multiple-minifiers-for-js/packages/local-plugin/plugin.js",
    "content": "Plugin.registerMinifier({\n  extensions: [\"js\"],\n}, function () {\n  var minifier = new Minifier();\n  return minifier;\n});\n\nfunction Minifier () {};\n\nMinifier.prototype.processFilesForBundle = function (files) { };\n\n"
  },
  {
    "path": "tools/tests/apps/minifier-plugin-multiple-minifiers-for-js/packages/local-plugin-2/package.js",
    "content": "Package.registerBuildPlugin({\n  name: \"bad-minifier-2\",\n  sources: ['plugin.js']\n});\n\nPackage.onUse(function (api) {\n  api.use('isobuild:minifier-plugin@1.0.0');\n});\n"
  },
  {
    "path": "tools/tests/apps/minifier-plugin-multiple-minifiers-for-js/packages/local-plugin-2/plugin.js",
    "content": "Plugin.registerMinifier({\n  extensions: [\"js\"],\n}, function () {\n  var minifier = new Minifier();\n  return minifier;\n});\n\nfunction Minifier () {};\n\nMinifier.prototype.processFilesForBundle = function (files) { };\n\n"
  },
  {
    "path": "tools/tests/apps/mobile-platforms/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/mobile-platforms/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n# Check this file (and the other files in this directory) into your repository.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\n"
  },
  {
    "path": "tools/tests/apps/mobile-platforms/.meteor/platforms",
    "content": "server\nbrowser\nandroid\nios\n"
  },
  {
    "path": "tools/tests/apps/mobile-platforms/.meteor/release",
    "content": "METEOR@1.0.3.1\n"
  },
  {
    "path": "tools/tests/apps/modules/.gitignore",
    "content": "/node_modules\n"
  },
  {
    "path": "tools/tests/apps/modules/.meteor/.finished-upgraders",
    "content": "# This file contains information which helps Meteor properly upgrade your\n# app when you run 'meteor update'. You should check it into version control\n# with your project.\n\nnotices-for-0.9.0\nnotices-for-0.9.1\n0.9.4-platform-file\nnotices-for-facebook-graph-api-2\n1.2.0-standard-minifiers-package\n1.2.0-meteor-platform-split\n1.2.0-cordova-changes\n1.2.0-breaking-changes\n1.3.0-split-minifiers-package\n"
  },
  {
    "path": "tools/tests/apps/modules/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/modules/.meteor/.id",
    "content": "# This file contains a token that is unique to your project.\n# Check it into your repository along with the rest of this directory.\n# It can be used for purposes such as:\n#   - ensuring you don't accidentally deploy one app on top of another\n#   - providing package authors with aggregated statistics\n\ndpey3716n44ug18al7gu\n"
  },
  {
    "path": "tools/tests/apps/modules/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n# Check this file (and the other files in this directory) into your repository.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base             # Packages every Meteor app needs to have\nmobile-experience       # Packages for a great mobile UX\nmongo                   # The database Meteor supports right now\nblaze-html-templates    # Compile .html files into Meteor Blaze views\nsession                 # Client-side reactive dictionary for your app\njquery                  # Helpful client-side library\ntracker                 # Meteor's client-side reactive programming library\n\nes5-shim                # ECMAScript 5 compatibility for older browsers.\necmascript              # Enable ECMAScript2015+ syntax in app code\n\ncoffeescript\nmodules-test-package\navital:mocha\nstandard-minifier-css\nstandard-minifier-js\nclient-only-ecmascript\nmodules-test-plugin\n"
  },
  {
    "path": "tools/tests/apps/modules/.meteor/platforms",
    "content": "server\nbrowser\n"
  },
  {
    "path": "tools/tests/apps/modules/.meteor/release",
    "content": "METEOR@1.3.3\n"
  },
  {
    "path": "tools/tests/apps/modules/.meteor/versions",
    "content": "allow-deny@1.0.5\nautoupdate@1.2.10\navital:mocha@2.1.0_10\nbabel-compiler@6.8.0\nbabel-runtime@0.1.9\nbase64@1.0.9\nbinary-heap@1.0.9\nblaze@2.1.8\nblaze-html-templates@1.0.4\nblaze-tools@1.0.9\nboilerplate-generator@1.0.9\ncaching-compiler@1.0.5\ncaching-html-compiler@1.0.6\ncallback-hook@1.0.9\ncheck@1.2.2\nclient-only-ecmascript@0.0.1\ncoffeescript@1.1.0\nddp@1.2.5\nddp-client@1.2.8\nddp-common@1.2.6\nddp-server@1.2.7\ndeps@1.0.12\ndiff-sequence@1.0.6\necmascript@0.4.4\necmascript-runtime@0.2.11\nejson@1.0.12\nes5-shim@4.5.11\nfastclick@1.0.12\ngeojson-utils@1.0.9\nhot-code-push@1.0.4\nhtml-tools@1.0.10\nhtmljs@1.0.10\nhttp@1.1.6\nid-map@1.0.8\njquery@1.11.9\nlaunch-screen@1.0.12\nlivedata@1.0.18\nlogging@1.0.13\nmeteor@1.1.15\nmeteor-base@1.0.4\nminifier-css@1.1.12\nminifier-js@1.1.12\nminimongo@1.0.17\nmobile-experience@1.0.4\nmobile-status-bar@1.0.12\nmodules@0.6.2\nmodules-runtime@0.6.4\nmodules-test-package@0.0.1\nmodules-test-plugin@0.0.1\nmongo@1.1.8\nmongo-id@1.0.5\nnpm-mongo@1.4.44\nobserve-sequence@1.0.12\nordered-dict@1.0.8\npracticalmeteor:chai@2.1.0_1\npracticalmeteor:loglevel@1.2.0_2\npracticalmeteor:mocha-core@0.1.4\npracticalmeteor:sinon@1.14.1_2\npromise@0.7.2\nrandom@1.0.9\nreactive-dict@1.1.8\nreactive-var@1.0.10\nreload@1.1.9\nretry@1.0.8\nroutepolicy@1.0.11\nsession@1.1.6\nspacebars@1.0.12\nspacebars-compiler@1.0.12\nstandard-minifier-css@1.0.7\nstandard-minifier-js@1.0.7\ntemplating@1.1.10\ntemplating-tools@1.0.4\ntmeasday:test-reporter-helpers@0.2.0\ntracker@1.0.14\nui@1.0.11\nunderscore@1.0.9\nurl@1.0.10\nwebapp@1.2.9\nwebapp-hashing@1.0.9\n"
  },
  {
    "path": "tools/tests/apps/modules/README.md",
    "content": "# modules\n\nTo run the tests, first install the npm dependencies, then run the app:\n\n```sh\nnpm install\nnpm test # just does `meteor run`\n```\n\nthen visit [localhost:3000](//localhost:3000) in your browser.\n"
  },
  {
    "path": "tools/tests/apps/modules/client/compatibility/bare.js",
    "content": "// Because this file is contained by a client/compatibility directory, it\n// should be evaluated as a bare file instead of as a module, so this\n// variable declaration should take effect in the scope of the app, and\n// thus be visible to other modules in the app.\nvar topLevelVariable = 1234;\n"
  },
  {
    "path": "tools/tests/apps/modules/client/only.js",
    "content": "export default module.id;\n"
  },
  {
    "path": "tools/tests/apps/modules/eager-coffee.coffee",
    "content": "exports.extension = \".coffee\";\nrequire(\"./imports/shared\").default[module.id] = \"eager coffee\";\n"
  },
  {
    "path": "tools/tests/apps/modules/eager-jsx.jsx",
    "content": "import shared from \"./imports/shared\";\nexport const extension = \".jsx\";\nshared[module.id] = \"eager jsx\";\n"
  },
  {
    "path": "tools/tests/apps/modules/eager.css",
    "content": ".app-eager-css {\n  display: none;\n}\n\n.app-lazy-css {\n  padding: 0;\n}\n"
  },
  {
    "path": "tools/tests/apps/modules/imports/dir/index.js",
    "content": "exports.fellBackTo = module.id;\n"
  },
  {
    "path": "tools/tests/apps/modules/imports/dir/package.json",
    "content": "{\n  \"name\": \"package-json-with-no-main\",\n  \"version\": \"1.2.3\",\n  \"description\": \"https://github.com/meteor/meteor/issues/6589\"\n}\n"
  },
  {
    "path": "tools/tests/apps/modules/imports/lazy.css",
    "content": ".app-lazy-css {\n  padding: 10px;\n}\n"
  },
  {
    "path": "tools/tests/apps/modules/imports/lazy.html",
    "content": "<body>\n  {{> lazy}}\n</body>\n\n<template name=\"lazy\">\n  lazy\n</template>\n"
  },
  {
    "path": "tools/tests/apps/modules/imports/lazy1.js",
    "content": "import shared from \"./shared\";\nimport \"./lazy2\";\n\nshared[module.id] = 1;\n\nexport function reset() {\n  delete shared[module.id];\n  delete module.exports;\n}\n"
  },
  {
    "path": "tools/tests/apps/modules/imports/lazy2.js",
    "content": "import shared from \"../imports/shared\";\nimport \"./lazy1\";\n\nshared[module.id] = 2;\n\nexport function reset() {\n  delete shared[module.id];\n  delete module.exports;\n}\n"
  },
  {
    "path": "tools/tests/apps/modules/imports/plain.es5.js",
    "content": "// The use of `let` as an identifier would be illegal if this file were\n// transpiled as ECMAScript 2015.\nvar let = \"ok\";\nexports.let = let;\n"
  },
  {
    "path": "tools/tests/apps/modules/imports/return.js",
    "content": "export let a = 1234;\nreturn;\nexport let b = 5678;\n"
  },
  {
    "path": "tools/tests/apps/modules/imports/shared.js",
    "content": "// This module exists so that other modules can modify this shared object\n// to communicate during tests.\nexport default Object.create(null);\n"
  },
  {
    "path": "tools/tests/apps/modules/lazy-css.html",
    "content": "<body>\n  <div class=\"app-lazy-css\"></div>\n  <div class=\"app-eager-css\"></div>\n  <div class=\"pkg-lazy-css imported\"></div>\n  <div class=\"pkg-lazy-css not-imported\"></div>\n</body>\n"
  },
  {
    "path": "tools/tests/apps/modules/lib/a/index.js",
    "content": "export const main = module.id;\n"
  },
  {
    "path": "tools/tests/apps/modules/lib/a/package.json",
    "content": "{\n  \"name\": \"a\",\n  \"main\": \"../b\"\n}\n"
  },
  {
    "path": "tools/tests/apps/modules/lib/b/package.json",
    "content": "{\n  \"name\": \"b\",\n  \"main\": \"../a\"\n}\n"
  },
  {
    "path": "tools/tests/apps/modules/lib/index.js",
    "content": "export {main as aMain} from \"./a\";\n"
  },
  {
    "path": "tools/tests/apps/modules/package.json",
    "content": "{\n  \"name\": \"modules-test-app\",\n  \"author\": \"Ben Newman <ben@meteor.com>\",\n  \"description\": \"Test app exercising many aspects of the Meteor module system.\",\n  \"private\": true,\n  \"dependencies\": {\n    \"aws-sdk\": \"^2.2.41\",\n    \"github\": \"^0.2.4\",\n    \"meteor-node-stubs\": \"^0.2.0\",\n    \"moment\": \"2.11.1\",\n    \"mssql\": \"^3.1.1\",\n    \"regenerator-runtime\": \"^0.9.5\",\n    \"stripe\": \"^4.4.0\",\n    \"winston\": \"^2.2.0\"\n  },\n  \"scripts\": {\n    \"test\": \"METEOR_PROFILE=100 ../../../../meteor test --full-app --driver-package avital:mocha\"\n  }\n}\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/client-only-ecmascript/README.md",
    "content": "Test package for issue https://github.com/meteor/meteor/issues/6877.\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/client-only-ecmascript/client.js",
    "content": "export { name as imported } from \"./imported.js\";\nexport const name = 'client-only-ecmascript';\nexport const ClientTypeof = {\n  require: typeof require,\n  exports: typeof exports\n};\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/client-only-ecmascript/imported.js",
    "content": "export const name = module.id;\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/client-only-ecmascript/package.js",
    "content": "Package.describe({\n  name: \"client-only-ecmascript\",\n  version: \"0.0.1\",\n  summary: \"\",\n  documentation: null\n});\n\nPackage.onUse(function(api) {\n  api.use(\"ecmascript\", \"client\");\n  api.mainModule(\"client.js\", \"client\");\n  api.addFiles(\"server.js\", \"server\");\n  api.export(\"ServerTypeof\", \"server\");\n});\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/client-only-ecmascript/server.js",
    "content": "ServerTypeof = {\n  require: typeof require,\n  exports: typeof exports\n};\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-package/README.md",
    "content": ""
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-package/client.js",
    "content": "import assert from \"assert\";\n\nimport {checkPackageVars} from \"./common\";\n\n// This verifies that Meteor packages can import native Node modules on\n// the client that are not implemented by meteor-node-stubs, in case the\n// app has a custom stub installed that takes precedence.\nimport {notEmpty} from \"repl\";\nassert.strictEqual(notEmpty, true);\n\nexport const where = \"client\";\nexport * from \"./common\";\n\nvar style = require(\"./css/imported.css\");\nif (! style) {\n  require(\"./css/not-imported.css\");\n}\n\nClientPackageVar = \"client\";\ncheckPackageVars();\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-package/common.js",
    "content": "import assert from \"assert\";\nimport \"regenerator-runtime/runtime\";\nexport const ModulesTestPackage = \"loaded\";\n\nexport function checkPackageVars() {\n  if (Meteor.isClient) {\n    assert.strictEqual(ClientPackageVar, \"client\");\n    try {\n      console.log(ServerPackageVar);\n    } catch (e) {\n      if (e instanceof ReferenceError) {\n        // ok\n      } else {\n        throw e;\n      }\n    }\n  } else {\n    assert.strictEqual(ServerPackageVar, \"server\");\n    try {\n      console.log(ClientPackageVar);\n    } catch (e) {\n      if (e instanceof ReferenceError) {\n        // ok\n      } else {\n        throw e;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-package/css/imported.css",
    "content": ".pkg-lazy-css.imported {\n  padding: 20px;\n}\n\n.not-imported {\n  padding: 0px;\n}\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-package/css/not-imported.css",
    "content": ".pkg-lazy-css.not-imported {\n  padding: 20px;\n}\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-package/illegal.html",
    "content": "<div>This is not a valid template file!</div>\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-package/os-stub.js",
    "content": "export {platform} from \"os-browserify/browser\";\nexport const name = module.id;\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-package/package.js",
    "content": "Package.describe({\n  name: 'modules-test-package',\n  version: '0.0.1',\n  summary: 'local test package',\n  documentation: 'README.md'\n});\n\nNpm.depends({\n  \"os-browserify\": \"0.2.0\",\n  \"assert\": \"1.3.0\"\n});\n\nPackage.onUse(function(api) {\n  api.use('ecmascript');\n  api.use('templating');\n  api.mainModule(\"client.js\", \"client\");\n  api.mainModule(\"server.js\", \"server\");\n  api.export(\"ModulesTestPackage\");\n});\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-package/server.js",
    "content": "import assert from \"assert\";\n\nimport * as common from \"./common\";\nassert.strictEqual(common.ModulesTestPackage, \"loaded\");\n\nexport {ModulesTestPackage} from \"./common\";\n\nexport const where = \"server\";\n\nServerPackageVar = \"server\";\ncommon.checkPackageVars();\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-plugin/.babelrc",
    "content": "{\n  \"plugins\": [\n    \"babel-plugin-transform-class-properties\",\n    [\"transform-strict-mode\", { \"strict\": true }],\n    \"./oyez-transform\",\n    \"intentionally-unresolvable\"\n  ]\n}\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-plugin/README.md",
    "content": "Test package for the following compiler plugin InputFile methods:\n\n  - `InputFile.prototype.getPackageJson`\n  - `InputFile.prototype.resolve`\n  - `InputFile.prototype.require`\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-plugin/array.arson",
    "content": "[\n  [1, 0, -4],\n  \"asdf\"\n]\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-plugin/modules-test-plugin.js",
    "content": "import { strictEqual } from \"assert\";\n\n// This tests the ./oyez-transform.js plugin, which replaces any \"OYEZ\"\n// string literal with \"ASDF\".\nstrictEqual(\"OYEZ\", \"ASDF\");\n\nexport { default as one } from \"./one\";\nexport { default as array } from \"./array\";\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-plugin/one.arson",
    "content": "[\n  {\n    \"string\": 1,\n    \"number\": 2\n  },\n  \"one\",\n  1\n]\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-plugin/oyez-transform.js",
    "content": "module.exports = function () {\n  return {\n    visitor: {\n      StringLiteral: function (path) {\n        if (path.node.value === \"OYEZ\") {\n          path.node.value = \"ASDF\";\n        }\n      }\n    }\n  };\n};\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-plugin/package.js",
    "content": "Package.describe({\n  name: \"modules-test-plugin\",\n  version: \"0.0.1\",\n  summary: \"\",\n  // By default, Meteor will default to using README.md for documentation.\n  // To avoid submitting documentation, set this field to null.\n  documentation: null\n});\n\nPackage.registerBuildPlugin({\n  name: \"compile-arson\",\n  use: [\"ecmascript\"],\n  sources: [\"plugin.js\"],\n  npmDependencies: {\n    // TODO Figure out what to do about the duplication between this list\n    // and the Npm.depends list below.\n    \"babel-plugin-transform-class-properties\": \"6.9.0\",\n    \"babel-plugin-transform-strict-mode\": \"6.8.0\"\n  }\n});\n\nNpm.depends({\n  arson: \"0.2.3\",\n  \"babel-plugin-transform-class-properties\": \"6.9.0\",\n  \"babel-plugin-transform-strict-mode\": \"6.8.0\"\n});\n\nPackage.onUse(function(api) {\n  api.use(\"ecmascript\");\n  api.use(\"isobuild:compiler-plugin@1.0.0\")\n  api.mainModule(\"modules-test-plugin.js\");\n});\n"
  },
  {
    "path": "tools/tests/apps/modules/packages/modules-test-plugin/plugin.js",
    "content": "import assert from \"assert\";\n\n// This verifies that babel-plugin-transform-strict-mode is enabled.\nlet expected;\ntry {\n  console.log(arguments.callee.toString());\n} catch (e) {\n  expected = e;\n}\nassert.ok(expected instanceof TypeError);\nassert.ok(/callee/.test(expected.message));\n\nPlugin.registerCompiler({\n  extensions: [\"arson\"]\n}, () => new ArsonCompiler);\n\nclass ArsonCompiler {\n  // This verifies that the babel-plugin-transform-class-properties plugin\n  // enabled by package.json is respected.\n  expectedName = \"compile-arson\";\n\n  processFilesForTarget(inputFiles) {\n    assert.strictEqual(this.expectedName, \"compile-arson\");\n\n    inputFiles.forEach(file => {\n      const arson = file.require(\"arson\");\n      let encoded = file.getContentsAsString();\n      const decoded = arson.decode(encoded);\n      decoded.self = decoded;\n      encoded = arson.encode(decoded);\n\n      file.addJavaScript({\n        path: file.getPathInPackage(),\n        data: 'module.exports = require(\"arson\").decode(' +\n          '  ' + JSON.stringify(encoded) + \");\",\n        hash: file.getSourceHash()\n      });\n    });\n  }\n}\n"
  },
  {
    "path": "tools/tests/apps/modules/server/only.js",
    "content": "import assert from \"assert\";\n\nimport \"github\";\nimport \"aws-sdk\";\nimport \"stripe\";\nimport \"winston\";\nimport \"mssql\";\n\nassert.strictEqual(Meteor.isServer, true);\nassert.strictEqual(Meteor.isClient, false);\n\nexport default module.id;\n"
  },
  {
    "path": "tools/tests/apps/modules/tests.js",
    "content": "import assert from \"assert\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport moment from \"moment\";\nimport shared from \"./imports/shared\";\nimport {Meteor as ImportedMeteor} from \"meteor/meteor\";\n\ndescribe(\"app modules\", () => {\n  it(\"can be imported using absolute identifiers\", () => {\n    assert.strictEqual(require(\"/tests\"), exports);\n  });\n\n  it(\"can have different file extensions\", () => {\n    assert.strictEqual(\n      require(\"./eager-jsx\").extension,\n      \".jsx\"\n    );\n\n    assert.strictEqual(\n      require(\"./eager-coffee\").extension,\n      \".coffee\"\n    );\n\n    assert.strictEqual(\n      require(\"/eager-jsx\").extension,\n      \".jsx\"\n    );\n\n    assert.strictEqual(\n      require(\"/eager-coffee\").extension,\n      \".coffee\"\n    );\n  });\n\n  it(\"are eagerly evaluated if outside imports/\", () => {\n    assert.strictEqual(shared[\"/eager-jsx.jsx\"], \"eager jsx\");\n    assert.strictEqual(shared[\"/eager-coffee.coffee.js\"], \"eager coffee\");\n  });\n\n  it(\"are lazily evaluated if inside imports/\", (done) => {\n    const delayMs = 200;\n\n    setTimeout(() => {\n      assert.strictEqual(shared[\"/imports/lazy1.js\"], void 0);\n      assert.strictEqual(shared[\"/imports/lazy2.js\"], void 0);\n\n      var reset1 = require(\"./imports/lazy1\").reset;\n\n      assert.strictEqual(shared[\"/imports/lazy1.js\"], 1);\n      assert.strictEqual(shared[\"/imports/lazy2.js\"], 2);\n\n      // Make sure this test can run again without starting a new process.\n      require(\"./imports/lazy2\").reset();\n      reset1();\n\n      done();\n    }, delayMs);\n  });\n\n  it(\"cannot import server modules on client\", () => {\n    let error;\n    let result;\n    try {\n      result = require(\"./server/only\").default;\n    } catch (expectedOnClient) {\n      error = expectedOnClient;\n    }\n\n    if (Meteor.isServer) {\n      assert.strictEqual(typeof error, \"undefined\");\n      assert.strictEqual(result, \"/server/only.js\");\n      assert.strictEqual(require(\"./server/only\"),\n                         require(\"/server/only\"));\n    }\n\n    if (Meteor.isClient) {\n      assert.ok(error instanceof Error);\n    }\n  });\n\n  it(\"cannot import client modules on server\", () => {\n    let error;\n    let result;\n    try {\n      result = require(\"./client/only\").default;\n    } catch (expectedOnServer) {\n      error = expectedOnServer;\n    }\n\n    if (Meteor.isClient) {\n      assert.strictEqual(typeof error, \"undefined\");\n      assert.strictEqual(result, \"/client/only.js\");\n      assert.strictEqual(require(\"./client/only\"),\n                         require(\"/client/only\"));\n    }\n\n    if (Meteor.isServer) {\n      assert.ok(error instanceof Error);\n    }\n  });\n\n  it(\"should not be parsed in strictMode\", () => {\n    let foo = 1234;\n    delete foo;\n  });\n\n  it(\"should have access to filename and dirname\", () => {\n    assert.strictEqual(require(__filename), exports);\n    assert.strictEqual(\n      require(\"path\").relative(__dirname, __filename),\n      \"tests.js\"\n    );\n  });\n\n  it(\"can be implemented by directories\", () => {\n    assert.strictEqual(\n      require(\"./imports/dir\").fellBackTo,\n      \"/imports/dir/index.js\"\n    );\n  });\n});\n\ndescribe(\"template modules\", () => {\n  Meteor.isClient &&\n  it(\"should be importable on the client\", () => {\n    assert.strictEqual(typeof Template, \"function\");\n    assert.ok(! _.has(Template, \"lazy\"));\n    require(\"./imports/lazy.html\");\n    assert.ok(_.has(Template, \"lazy\"));\n    assert.ok(Template.lazy instanceof Template);\n  });\n\n  Meteor.isServer &&\n  it(\"should not be importable on the server\", () => {\n    let error;\n    try {\n      require(\"./imports/lazy.html\");\n    } catch (expected) {\n      error = expected;\n    }\n    assert.ok(error instanceof Error);\n  });\n});\n\nMeteor.isClient &&\ndescribe(\"css modules\", () => {\n  it(\"should be loaded eagerly unless lazy\", () => {\n    assert.strictEqual(\n      $(\".app-eager-css\").css(\"display\"),\n      \"none\"\n    );\n\n    // Eager CSS is added unconditionally to a combined <style> tag at the\n    // beginning of the <head>. If the corresponding module ever gets\n    // imported, its module.exports object should be an empty stub, rather\n    // than a <style> node added dynamically to the <head>.\n    assert.deepEqual(require(\"./eager.css\"), {});\n  });\n\n  it(\"should be importable by an app\", () => {\n    assert.strictEqual($(\".app-lazy-css\").css(\"padding\"), \"0px\");\n    require(\"./imports/lazy.css\");\n    assert.strictEqual($(\".app-lazy-css\").css(\"padding\"), \"10px\");\n  });\n\n  it(\"should be importable by a package\", () => {\n    assert.strictEqual(\n      $(\".pkg-lazy-css.imported\").css(\"padding\"),\n      \"20px\"\n    );\n\n    assert.strictEqual(\n      $(\".pkg-lazy-css.not-imported\").css(\"padding\"),\n      \"0px\"\n    );\n  });\n});\n\ndescribe(\"native node_modules\", () => {\n  Meteor.isServer &&\n  it(\"can be imported on the server\", () => {\n    assert.strictEqual(typeof require(\"fs\").readFile, \"function\");\n  });\n\n  Meteor.isClient &&\n  it(\"are imported as stubs on the client\", () => {\n    const inherits = require(\"util\").inherits;\n    assert.strictEqual(typeof inherits, \"function\");\n  });\n\n  Meteor.isServer &&\n  it(\"cannot be overridden on the server\", () => {\n    assert.strictEqual(typeof require(\"repl\").start, \"function\");\n  });\n\n  Meteor.isClient &&\n  it(\"can be overridden on the client\", () => {\n    assert.strictEqual(require(\"repl\").notEmpty, true);\n  });\n\n  it(\"can be implemented by wrapper npm packages\", () => {\n    const Stream = require(\"stream\");\n    assert.strictEqual(typeof Stream, \"function\");\n    assert.strictEqual(typeof Stream.Readable, \"function\");\n  });\n\n  it(\"can all be imported\", () => {\n    require(\"_stream_duplex\");\n    require(\"_stream_passthrough\");\n    require(\"_stream_readable\");\n    require(\"_stream_transform\");\n    require(\"_stream_writable\");\n    require(\"assert\");\n    require(\"buffer\");\n    require(\"child_process\");\n    require(\"cluster\");\n    require(\"console\");\n    require(\"constants\");\n    require(\"crypto\");\n    require(\"dgram\");\n    require(\"dns\");\n    require(\"domain\");\n    require(\"events\");\n    require(\"fs\");\n    require(\"http\");\n    require(\"https\");\n    require(\"module\");\n    require(\"net\");\n    require(\"os\");\n    require(\"path\");\n    require(\"process\");\n    require(\"punycode\");\n    require(\"querystring\");\n    require(\"readline\");\n    require(\"repl\");\n    require(\"stream\");\n    require(\"string_decoder\");\n    require(\"sys\");\n    require(\"timers\");\n    require(\"tls\");\n    require(\"tty\");\n    require(\"url\");\n    require(\"util\");\n    require(\"vm\");\n    require(\"zlib\");\n  });\n});\n\ndescribe(\"local node_modules\", () => {\n  it(\"should be importable\", () => {\n    assert.strictEqual(require(\"moment\"), moment);\n    const cal = moment().calendar();\n    assert.ok(cal.match(/\\bat\\b/));\n  });\n\n  it(\"can be imported using absolute identifiers\", () => {\n    assert.strictEqual(\n      require(\"moment\"),\n      require(\"/node_modules/moment\")\n    );\n  });\n\n  it(\"should be importable by packages\", () => {\n    // Defined in packages/modules-test-package/common.js.\n    assert.strictEqual(typeof regeneratorRuntime, \"object\");\n  });\n\n  it('should expose \"version\" field of package.json', () => {\n    const pkg = require(\"moment/package.json\");\n    assert.strictEqual(pkg.version, \"2.11.1\");\n  });\n});\n\ndescribe(\"Meteor packages\", () => {\n  it(\"api.export should create named exports\", () => {\n    assert.strictEqual(typeof ImportedMeteor, \"object\");\n    assert.strictEqual(Meteor, ImportedMeteor);\n  });\n\n  it(\"should be importable\", () => {\n    assert.strictEqual(require(\"meteor/underscore\")._, _);\n\n    const Blaze = require(\"meteor/blaze\").Blaze;\n    assert.strictEqual(typeof Blaze, \"object\");\n\n    let error;\n    try {\n      require(\"meteor/nonexistent\");\n    } catch (expected) {\n      error = expected;\n    }\n    assert.ok(error instanceof Error);\n  });\n\n  it(\"can be local\", () => {\n    assert.strictEqual(ModulesTestPackage, \"loaded\");\n    const mtp = require(\"meteor/modules-test-package\");\n    assert.strictEqual(mtp.where, Meteor.isServer ? \"server\" : \"client\");\n  });\n\n  it(\"should expose their files for import\", () => {\n    const osStub = require(\"meteor/modules-test-package/os-stub\");\n\n    assert.strictEqual(\n      osStub.platform(),\n      \"browser\"\n    );\n\n    assert.strictEqual(\n      osStub.name,\n      \"/node_modules/meteor/modules-test-package/os-stub.js\"\n    );\n  });\n\n  it(\"should only include lazy files if platform uses modules\", function () {\n    if (Meteor.isServer) {\n      const clientOnlyIsopackPath = path.join(\n        // Currently process.cwd is .meteor/local/build/programs/server.\n        \"..\", \"..\", \"..\", \"isopacks\", \"client-only-ecmascript\"\n      );\n\n      const webJsonPath = path.join(\n        clientOnlyIsopackPath,\n        \"web.browser.json\"\n      );\n\n      const osJsonPath = path.join(\n        clientOnlyIsopackPath,\n        \"os.json\"\n      );\n\n      const web = JSON.parse(fs.readFileSync(webJsonPath));\n      assert.deepEqual(web.resources.map(function (res) {\n        return res.path;\n      }), [\"client.js\", \"imported.js\", \"server.js\"]);\n      assert.strictEqual(web.resources[0].fileOptions.mainModule, true);\n      assert.strictEqual(web.resources[1].fileOptions.lazy, true);\n      assert.strictEqual(web.resources[2].fileOptions.lazy, true);\n\n      const os = JSON.parse(fs.readFileSync(osJsonPath));\n      assert.deepEqual(os.resources.map(function (res) {\n        return res.path;\n      }), [\"server.js\"]);\n      assert.deepEqual(os.resources[0].fileOptions, {});\n\n      assert.deepEqual(ServerTypeof, {\n        require: \"undefined\",\n        exports: \"undefined\"\n      });\n\n    } else {\n      assert.deepEqual(require(\"meteor/client-only-ecmascript\"), {\n        __esModule: true,\n        name: \"client-only-ecmascript\",\n        imported: \"/node_modules/meteor/client-only-ecmascript/imported.js\",\n        ClientTypeof: {\n          require: \"function\",\n          exports: \"object\"\n        }\n      });\n    }\n  });\n\n  it(\"can define complex compiler plugins\", () => {\n    const { one, array } = require(\"meteor/modules-test-plugin\");\n\n    assert.strictEqual(one.string, \"one\");\n    assert.strictEqual(one.number, 1);\n    assert.strictEqual(one.self, one)\n\n    assert.strictEqual(array[0], \"asdf\");\n    assert.strictEqual(array[1], array);\n    assert.strictEqual(array[2], Infinity);\n  });\n});\n\ndescribe(\"ecmascript miscellany\", () => {\n  it(\"JSX should work in .js files on both client and server\", () => {\n    const React = {\n      createElement: function (name, attrs, children) {\n        assert.strictEqual(name, \"div\");\n        assert.strictEqual(attrs, null);\n        assert.strictEqual(children, \"hi\");\n        return \"all good\";\n      }\n    };\n\n    assert.strictEqual(<div>hi</div>, \"all good\");\n  });\n\n  it(\"async functions should work on the client and server\", async () => {\n    assert.strictEqual(\n      await 2 + 2,\n      await new Promise(resolve => resolve(4))\n    );\n  });\n\n  it(\"rest paramters in inner arrow functions (#6312)\", () => {\n    const rev = (...args) => args.reverse();\n    assert.deepEqual(rev(1, 2, 3), [3, 2, 1]);\n    assert.ok(rev.toString().match(/\\barguments\\b/));\n  });\n\n  it(\"rest parameters in property arrow functions (#6514)\", () => {\n    const obj = {\n      method: (a, b, ...rest) => {\n        rest.push(a, b);\n        return rest.reverse();\n      }\n    };\n\n    assert.deepEqual(\n      obj.method(1, 2, 3, 4),\n      [2, 1, 4, 3]\n    );\n  });\n});\n\nMeteor.isClient &&\ndescribe(\"client/compatibility directories\", () => {\n  it(\"should contain bare files\", () => {\n    assert.strictEqual(topLevelVariable, 1234);\n  });\n});\n\ndescribe(\".es5.js files\", () => {\n  it(\"should not be transpiled\", () => {\n    assert.strictEqual(require(\"./imports/plain.es5.js\").let, \"ok\");\n  });\n});\n\ndescribe(\"return statements at top level\", () => {\n  it(\"should be legal\", () => {\n    var ret = require(\"./imports/return.js\");\n    assert.strictEqual(ret.a, 1234);\n    assert.strictEqual(ret.b, void 0);\n  });\n});\n\ndescribe(\"circular package.json resolution chains\", () => {\n  it(\"should be broken appropriately\", () => {\n    assert.strictEqual(\n      require(\"./lib\").aMain,\n      \"/lib/a/index.js\"\n    );\n  });\n});\n"
  },
  {
    "path": "tools/tests/apps/npmtest/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/npmtest/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nnpm-test\n"
  },
  {
    "path": "tools/tests/apps/npmtest/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/npmtest/packages/npm-test/npmtest.js",
    "content": "// This will execute a shell script, print its output, and process.exit(0).\nNpm.require('meteor-test-executable').doIt();\n"
  },
  {
    "path": "tools/tests/apps/npmtest/packages/npm-test/package.js",
    "content": "Npm.depends({\"meteor-test-executable\": \"0.0.3\"});\n\nPackage.describe({\n  version: \"1.0.0\",\n  summary: \"test npm\"\n});\n\nPackage.onUse(function (api) {\n  api.addFiles(\"npmtest.js\", \"server\");\n});\n"
  },
  {
    "path": "tools/tests/apps/once/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/once/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nstandard-minifiers\nmongo\n"
  },
  {
    "path": "tools/tests/apps/once/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/once/once.js",
    "content": "process.stdout.write(\"once test\\n\");\n\nif (process.env.RUN_ONCE_OUTCOME === \"exit\")\n  process.exit(123);\n\nif (process.env.RUN_ONCE_OUTCOME === \"kill\") {\n  process.kill(process.pid, 'SIGKILL');\n}\n\nif (process.env.RUN_ONCE_OUTCOME === \"hang\") {\n  // The outstanding timeout will prevent node from exiting\n  setTimeout(function () {}, 365 * 24 * 60 * 60);\n}\n\nif (process.env.RUN_ONCE_OUTCOME === \"mongo\") {\n  var test = new Mongo.Collection('test');\n  test.insert({ value: 86 });\n  process.exit(test.findOne().value);\n}\n"
  },
  {
    "path": "tools/tests/apps/package-stats-tests/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/package-stats-tests/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\nlocal-package\n"
  },
  {
    "path": "tools/tests/apps/package-stats-tests/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/package-stats-tests/package-stats-tests.js",
    "content": "// This app functions with no packages loaded, so it's good for testing releases\n// with no packages.  All it does is print \"RUNNING\" and run forever.\nmain = function () {\n  // Tell the runner we're up.\n  console.log(\"LISTENING\");\n  // Ensure Node doesn't kill us.\n  process.stdin.resume();\n  // Ensure boot.js doesn't kill us.\n  return 'DAEMON';\n};\n"
  },
  {
    "path": "tools/tests/apps/package-stats-tests/packages/local-package/blah.js",
    "content": "console.log(\"BLAH\");\n"
  },
  {
    "path": "tools/tests/apps/package-stats-tests/packages/local-package/package.js",
    "content": "Package.describe({\n  summary: \"a package\",\n  version: \"1.0.0\"\n});\n\nPackage.onUse(function (api) {\n  api.addFiles(\"blah.js\");\n});\n"
  },
  {
    "path": "tools/tests/apps/package-stats-tests/packages/package-stats-opt-out/package.js",
    "content": "// This is a replica of the core package-stats-opt-out package. It\n// exists to make it so that we can add package-stats-opt-out to this\n// app without needing to be using a release that has core packages in\n// it (such as using a sandbox created with a `warehouse` argument).\n\nPackage.describe({\n  summary: \"a replica of a core package\",\n  version: \"1.0.0\"\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/package-tests/.meteor/identifier",
    "content": "32t5gt1m39x2tmc1zkd"
  },
  {
    "path": "tools/tests/apps/package-tests/.meteor/packages",
    "content": "meteor-base\n"
  },
  {
    "path": "tools/tests/apps/package-tests/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/package-tests/mobile-config.js",
    "content": "App.configurePlugin(\"com.phonegap.plugins.facebookconnect\", {\n  \"APP_ID\": 123,\n  \"APP_NAME\": \"foo\"\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/contains-camera-cordova-plugin/package.js",
    "content": "Package.describe({\n  summary: \"contains a cordova plugin\",\n  version: \"1.1.0\"\n});\n\nPackage.onUse(function(api) {\n  Cordova.depends({\n    'cordova-plugin-camera': '1.2.0',\n  });\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/contains-cordova-plugin/package.js",
    "content": "Package.describe({\n  summary: \"contains a cordova plugin\",\n  version: \"1.1.0\"\n});\n\nPackage.onUse(function(api) {\n  Cordova.depends({\n    'cordova-plugin-camera': '1.2.0',\n    'com.phonegap.plugins.facebookconnect':\n      'https://github.com/Wizcorp/phonegap-facebook-plugin/tarball/3d52b1eb8a55ebcf8ad10c75d99deedeca0c0fdd'\n\n  });\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/contains-cordova-plugin/package2.js",
    "content": "Package.describe({\n  summary: \"contains a cordova plugin\",\n  version: \"1.1.0\"\n});\n\nPackage.onUse(function(api) {\n  Cordova.depends({\n    'cordova-plugin-camera': '1.0.0',\n    'com.phonegap.plugins.facebookconnect':\n      'https://github.com/Wizcorp/phonegap-facebook-plugin/tarball/3d52b1eb8a55ebcf8ad10c75d99deedeca0c0fdd'\n  });\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/contains-cordova-plugin/package3.js",
    "content": "Package.describe({\n  summary: \"contains a cordova plugin\",\n  version: \"1.1.0\"\n});\n\nPackage.onUse(function(api) {\n  Cordova.depends({\n    'cordova-plugin-camera': null,\n    'com.phonegap.plugins.facebookconnect':\n      'https://github.com/Wizcorp/phonegap-facebook-plugin/tarball/3d52b1eb8a55ebcf8ad10c75d99deedeca0c0fdd'\n  });\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/contains-old-cordova-plugin/package.js",
    "content": "Package.describe({\n  summary: \"contains a cordova plugin\",\n  version: \"1.1.0\"\n});\n\nPackage.onUse(function(api) {\n  Cordova.depends({\n    'cordova-plugin-camera': '1.0.0'\n  });\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/contains-plugin/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/contains-plugin/.npm/plugin/compileCoffeescript/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/contains-plugin/.npm/plugin/compileCoffeescript/README",
    "content": "This directory and the files immediately inside it are automatically generated\nwhen you change this package's NPM dependencies. Commit the files in this\ndirectory (npm-shrinkwrap.json, .gitignore, and this README) to source control\nso that others run the same versions of sub-dependencies.\n\nYou should NOT check in the node_modules directory that Meteor automatically\ncreates; if you are using git, the .gitignore file tells git to ignore it.\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/contains-plugin/.npm/plugin/compileCoffeescript/npm-shrinkwrap.json",
    "content": "{\n  \"dependencies\": {\n    \"coffee-script\": {\n      \"version\": \"1.7.1\",\n      \"dependencies\": {\n        \"mkdirp\": {\n          \"version\": \"0.3.5\"\n        }\n      }\n    },\n    \"source-map\": {\n      \"version\": \"0.1.32\",\n      \"dependencies\": {\n        \"amdefine\": {\n          \"version\": \"0.1.0\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/contains-plugin/package.js",
    "content": "Package.describe({\n  summary: \"contains a plugin\",\n  version: \"1.1.0\"\n});\n\nPackage.registerBuildPlugin({\n  name: \"myPlugin\",\n  use: [],\n  sources: [\n    'plugin/plugin.js'\n  ],\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/contains-plugin/package2.js",
    "content": "Package.describe({\n  summary: \"contains a plugin\",\n  version: \"1.1.0\"\n});\n\nPackage.registerBuildPlugin({\n  name: \"myPlugin\",\n  use: [],\n  sources: [\n    'plugin/plugin.js'\n  ],\n});\n\nPackage.onUse(function (api) {\n  api.use('accounts-base');\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/contains-plugin/plugin/plugin.js",
    "content": "console.log('plugin!');\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/debug-only/debug-only.js",
    "content": "Debug = 5;\nglobal.DEBUG_ONLY_LOADED = true;\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/debug-only/package.js",
    "content": "Package.describe({\n  name: 'debug-only',\n  debugOnly: true\n});\n\nPackage.onUse(function(api) {\n  api.addFiles('debug-only.js');\n  api.export('Debug');\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/depends-on-plugin/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/depends-on-plugin/foo.js",
    "content": "console.log('foobar!');\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/depends-on-plugin/package.js",
    "content": "Package.describe({\n  version: \"1.0.0\",\n  summary: \"depend on and watch a plugin\"\n});\n\nPackage.onUse(function (api) {\n  api.addFiles('foo.js');\n  api.use('contains-plugin');\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/empty-cordova-plugin/package.js",
    "content": "Package.describe({\n  version: \"1.0.0\",\n  summary: \"contains an empty cordova plugin\"\n});\n\nPackage.onUse(function(api) {\n  Cordova.depends({\n    // In the test \"meteor reinstalls only local cordova plugins on consecutive\n    // builds/runs\" (test in file cordova-plugin.js) the \"plugin\"\n    // directory from this package is copied one level up from the meteor project.\n    // Cordova local plugins must have an absolute or relative path to\n    // meteor project, so in this case the plugin will be one level up from it.\n    'com.cordova.empty': 'file://../cordova-local-plugin'\n  });\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/empty-cordova-plugin/plugin/plugin.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<plugin xmlns=\"http://apache.org/cordova/ns/plugins/1.0\"\n        id=\"com.cordova.empty\" version=\"0.2.3\">\n    <name>Empty</name>\n    <description>Cordova Empty Plugin</description>\n    <keywords>cordova,empty</keywords>\n    <repo>https://github.com</repo>\n\n    <js-module src=\"www/Empty.js\" name=\"Empty\">\n        <clobbers target=\"cordova.plugins.Empty\" />\n    </js-module>\n\n\n     <platform name=\"android\">\n        <config-file target=\"res/xml/config.xml\" parent=\"/*\">\n            <feature name=\"Empty\" >\n                <param name=\"android-package\" value=\"com.cordova.empty.Empty\"/>\n            </feature>\n        </config-file>\n\n        <source-file src=\"src/android/Empty.java\" target-dir=\"src/com/cordova/empty\" />\n    </platform>\n\n</plugin>"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/empty-cordova-plugin/plugin/src/android/Empty.java",
    "content": "package com.cordova.empty;\n\nimport org.apache.cordova.CallbackContext;\nimport org.apache.cordova.CordovaPlugin;\n\nimport org.json.JSONArray;\nimport org.json.JSONException;\n\npublic class Empty extends CordovaPlugin {\n    public Object onMessage(String id, Object data) {\n        return null;\n    }\n    @Override\n    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {\n        return false;\n    }\n}\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/empty-cordova-plugin/plugin/src/android/Empty_changed.java",
    "content": "package com.cordova.empty;\n\nimport org.apache.cordova.CallbackContext;\nimport org.apache.cordova.CordovaPlugin;\n\nimport org.json.JSONArray;\nimport org.json.JSONException;\n\npublic class Empty extends CordovaPlugin {\n    public Object onMessage(String id, Object data) {\n        System.out.println(\"change\");\n        return null;\n    }\n    @Override\n    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {\n        return false;\n    }\n}\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/empty-cordova-plugin/plugin/www/Empty.js",
    "content": "var Empty = {\n};\nmodule.exports = Empty;\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/no-description/package.js",
    "content": "Package.describe({\n  version: \"1.0.0\"\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/prod-only/package.js",
    "content": "Package.describe({\n  name: 'prod-only',\n  prodOnly: true\n});\n\nPackage.onUse(function(api) {\n  api.addFiles('prod-only.js');\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/prod-only/prod-only.js",
    "content": "global.PROD_ONLY_LOADED = true;\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/say-something/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/say-something/foo.js",
    "content": "console.log(\"initial statement\");\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/say-something/package.js",
    "content": "Package.describe({\n  version: \"1.0.0\",\n  summary: \"print to console\"\n});\n\nPackage.onUse(function (api) {\n  api.addFiles('foo.js');\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/say-something-client-targets/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/say-something-client-targets/all-clients.js",
    "content": "Meteor.call('log', 'all clients');\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/say-something-client-targets/browser-client.js",
    "content": "Meteor.call('log', 'browser client');"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/say-something-client-targets/cordova-client.js",
    "content": "Meteor.call('log', 'cordova client');"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/say-something-client-targets/package.js",
    "content": "Package.describe({\n  version: \"1.0.0\",\n  summary: \"prints to console, depending on which client arch we build for\"\n});\n\nPackage.onUse(function (api) {\n  api.use(\"ddp\");\n  api.addFiles('all-clients.js', ['client']);\n  api.addFiles('browser-client.js', ['web.browser']);\n  api.addFiles('cordova-client.js', ['web.cordova']);\n  api.addFiles('server.js', ['server']);\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/say-something-client-targets/server.js",
    "content": "var logNum = 0;\n\nMeteor.methods({\n  log: function (msg) {\n    console.log(msg + \" \" + logNum);\n    logNum++;\n  }\n});"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/with-add-files/package.js",
    "content": "Package.describe({\n  name: 'with-add-files',\n  version: '0.0.1'\n});\n\nPackage.onUse(function(api) {\n  api.versionsFrom('1.3.2.4');\n  api.use('ecmascript');\n  api.addFiles('with-add-files.js');\n  api.export('name');\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/with-add-files/with-add-files.js",
    "content": "name = 'with-add-files';\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/with-main-module/package.js",
    "content": "Package.describe({\n  name: 'with-main-module',\n  version: '0.0.1'\n});\n\nPackage.onUse(function(api) {\n  api.versionsFrom('1.3.2.4');\n  api.use('ecmascript');\n  api.mainModule('with-main-module.js');\n});\n"
  },
  {
    "path": "tools/tests/apps/package-tests/packages/with-main-module/with-main-module.js",
    "content": "export const name = 'with-main-module';\n"
  },
  {
    "path": "tools/tests/apps/packageless/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/packageless/.meteor/.id",
    "content": "# This file contains a token that is unique to your project.\n# Check it into your repository along with the rest of this directory.\n# It can be used for purposes such as:\n#   - ensuring you don't accidentally deploy one app on top of another\n#   - providing package authors with aggregated statistics\n\n1wehy3x1n3lcvy1v8vllm\n"
  },
  {
    "path": "tools/tests/apps/packageless/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n"
  },
  {
    "path": "tools/tests/apps/packageless/.meteor/platforms",
    "content": "browser\nserver\n"
  },
  {
    "path": "tools/tests/apps/packageless/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/packageless/packageless.js",
    "content": "// This app functions with no packages loaded, so it's good for testing releases\n// with no packages.  All it does is print \"RUNNING\" and run forever.\nmain = function () {\n  // Tell the runner we're up.\n  console.log(\"LISTENING\");\n  // Ensure Node doesn't kill us.\n  process.stdin.resume();\n  // Ensure boot.js doesn't kill us.\n  return 'DAEMON';\n};\n"
  },
  {
    "path": "tools/tests/apps/simple-app/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/simple-app/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base             # Packages every Meteor app needs to have\nmobile-experience       # Packages for a great mobile UX\nmongo                   # The database Meteor supports right now\nblaze-html-templates    # Compile .html files into Meteor Blaze views\nsession                 # Client-side reactive dictionary for your app\njquery                  # Helpful client-side library\ntracker                 # Meteor's client-side reactive programming library\n\nstandard-minifiers      # JS/CSS minifiers run for production mode\nes5-shim                # ECMAScript 5 compatibility for older browsers.\necmascript              # Enable ECMAScript2015+ syntax in app code\n\nautopublish             # Publish all data to the clients (for prototyping)\ninsecure                # Allow all DB writes from clients (for prototyping)\n"
  },
  {
    "path": "tools/tests/apps/simple-app/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/simple-app/simple.html",
    "content": "<head>\n  <title>Hello</title>\n</head>\n\n<body>\n  <h1>Welcome to Meteor!</h1>\n</body>\n"
  },
  {
    "path": "tools/tests/apps/standard-app/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/standard-app/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nstandard-minifiers\n"
  },
  {
    "path": "tools/tests/apps/standard-app/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/uses-published-package-with-inactive-source/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/apps/uses-published-package-with-inactive-source/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nmeteor-base\nlocal-plugin\nglasser:use-sourcish@=0.0.1\n"
  },
  {
    "path": "tools/tests/apps/uses-published-package-with-inactive-source/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/apps/uses-published-package-with-inactive-source/packages/local-plugin/package.js",
    "content": "Package.describe({\n  version: '1.0.0'\n});\n"
  },
  {
    "path": "tools/tests/autoupdate.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar config = require('../meteor-services/config.js');\nvar catalogRemote = require('../packaging/catalog/catalog-remote.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar Sandbox = selftest.Sandbox;\n\nvar DEFAULT_RELEASE_TRACK = catalogRemote.DEFAULT_TRACK;\n\nvar getCatalog = function (sandbox) {\n  var dataFile = config.getPackageStorage({ root: sandbox.warehouse });\n  var catalog = new catalogRemote.RemoteCatalog();\n  catalog.initialize( {packageStorage: dataFile});\n  return catalog;\n};\n\nvar setBanner = function (sandbox, version, banner) {\n  var messages = buildmessage.capture(function () {\n    var catalog = getCatalog(sandbox);\n    var release = catalog.getReleaseVersion(DEFAULT_RELEASE_TRACK, version);\n    release.banner = { text: banner, lastUpdated: new Date };\n    catalog._insertReleaseVersions([release]); //This is a hack\n  });\n};\n\nvar recommend = function (sandbox, version) {\n  var messages = buildmessage.capture(function () {\n    var catalog = getCatalog(sandbox);\n    var release = catalog.getReleaseVersion(DEFAULT_RELEASE_TRACK, version);\n    release.recommended = true;\n    catalog._insertReleaseVersions([release]);\n  });\n};\n\nselftest.define(\"autoupdate\", ['checkout', 'custom-warehouse'], function () {\n  var s = new Sandbox({\n    warehouse: {\n      v1: { recommended: true},\n      v2: { recommended: true },\n      v3: { },\n      v4: { }\n    }\n  });\n  var run;\n\n  // These tests involve running an app, but only because we want to\n  // exercise the autoupdater, not because we actually care if the app\n  // manages to run. So stop mongo from starting so that it goes faster.\n  s.set(\"MONGO_URL\", \"whatever\");\n\n  s.createApp('myapp', 'packageless', { release: DEFAULT_RELEASE_TRACK + '@v2' });\n  s.cd('myapp', function () {\n    setBanner(s, \"v2\", \"=> New hotness v2 being downloaded.\\n\");\n\n    // console.log(\"WE ARE READY NOW\", s.warehouse, s.cwd)\n    // require('../utils/utils.js').sleepMs(1000*10000)\n\n    // Run it and see the banner for the current version.\n    run = s.run(\"--port\", \"21000\");\n    run.waitSecs(30);\n    run.match(\"New hotness v2 being downloaded\");\n    run.match(\"running at\");\n    require('../utils/utils.js').sleepMs(500);\n    run.stop();\n\n    // We won't see the banner a second time, or any other message about\n    // updating since we are at the latest recommended release.\n    run = s.run(\"--port\", \"21000\");\n    run.waitSecs(5);\n    run.match(\"running at\");\n    run.forbidAll(\"hotness\");\n    run.forbidAll(\"meteor update\");\n    run.stop();\n\n    // If we are not at the latest version of Meteor, at startup, we get a\n    // boring prompt to update (not a banner since we didn't set one for v1).\n    s.write('.meteor/release', DEFAULT_RELEASE_TRACK + '@v1');\n\n    // We don't see any information if we run a simple command like list.\n    run = s.run(\"list\");\n    run.forbidAll(\"New hotness v2 being downloaded\");\n    run.expectExit(0);\n    run.stop();\n\n    run = s.run(\"--version\");\n    run.read(\"Meteor v1\\n\");\n    run.expectEnd();\n    run.expectExit(0);\n\n    // We do see a boring prompt though.\n    run = s.run(\"--port\", \"22000\");\n    run.waitSecs(5);\n    run.match(\"v2\");\n    run.forbidAll(\"hotness\");\n    run.match(\"meteor update\");\n    run.stop();\n\n    // .. unless we explicitly forced this release. Then, no prompt.\n    s.write('.meteor/release', DEFAULT_RELEASE_TRACK + '@somethingelse');\n    run = s.run(\"--release\", \"v1\", \"--port\", \"23000\");\n    run.waitSecs(5);\n    run.match(\"running at\");\n    run.forbidAll(\"hotness\");\n    run.forbidAll(\"meteor update\");\n    run.stop();\n\n    // XXX figure out about the UI of being offline. the old warehouse\n    //     banner code actually printed out that it was downloading stuff,\n    //     not just that it was available. we aren't quite as subtle now.\n\n    // // OK, now say there actually is a new version available. (Use a\n    // // version that we will fail to download, just so we have a chance\n    // // to see what it happens if we restart before the download\n    // // finishes)\n    // s.write('.meteor/release', 'v2');\n    // s.set('METEOR_TEST_FAIL_RELEASE_DOWNLOAD', 'offline');\n    // setManifest(s, \"test-junk\", \"=> New hotness test-junk being downloaded.\\n\");\n    // run = s.run(\"--port\", \"24000\");\n    // run.match(\"New hotness test-junk\");\n    // run.stop();\n\n    // // But we only print the banner once.\n    // run = s.run(\"--port\", \"25000\");\n    // run.match(\"Meteor test-junk is being downloaded\");\n    // run.stop();\n    // run.forbidAll(\"hotness\");\n\n    // OK, now use a version that we already have, so that the update\n    // will succeed (we don't currently have facilities for stubbing out\n    // the release download itself, but that's OK -- the updater only\n    // checks if our latest version is not equal to the one in the\n    // manifest, not if we actually have the version in the manifest;\n    // and the downloading code turns out to be a noop if we already\n    // have that version).\n    recommend(s, \"v3\");\n    s.write('.meteor/release', DEFAULT_RELEASE_TRACK + '@v2');\n    run = s.run(\"--port\", \"26000\");\n    run.match(\"Meteor v3 is available\");\n    run.match(\"meteor update\");\n    run.stop();\n\n    run = s.run(\"update\");\n    run.match(\"myapp: updated to Meteor v3.\\n\");\n    run.match(\"Your top-level dependencies are at their latest compatible \" +\n              \"versions.\\n\");\n    run.expectExit(0);\n\n    run = s.run(\"--version\");\n    run.read(\"Meteor v3\\n\");\n    run.expectEnd();\n    run.expectExit(0);\n\n    run = s.run(\"update\");\n    run.match(\"already at Meteor v3, the latest release\");\n    run.expectExit(0);\n\n    // Update the app back to an older version.\n    run = s.run(\"update\", \"--release\", \"v2\");\n    run.read(\"myapp: updated to Meteor v2.\\n\");\n    run.expectEnd();\n    run.expectExit(0);\n\n    run = s.run(\"--version\");\n    run.read(\"Meteor v2\\n\");\n    run.expectEnd();\n    run.expectExit(0);\n\n    run = s.run(\"update\", \"--release\", \"v2\");\n    run.match(\"already at Meteor v2\");\n    run.forbidAll(\"the latest release\");\n    run.expectExit(0);\n\n    // Update explicitly to v3.\n    run = s.run(\"update\", \"--release\", \"v3\");\n    run.read(\"myapp: updated to Meteor v3.\\n\");\n    // We *don't* print \"All your package dependencies are already up to date\"\n    // here, because we don't try to additionally update packages when you\n    // request a specific release.\n    run.expectEnd();\n    run.expectExit(0);\n  });\n\n  // The latest version has been updated globally too.\n  run = s.run(\"--version\");\n  run.read(\"Meteor v3\\n\");\n  run.expectEnd();\n  run.expectExit(0);\n\n  // Recommend v4 and watch --version update.\n  // XXX: Not sure if this is desired behavior.\n  recommend(s, \"v4\");\n  run = s.run(\"--version\");\n  run.match(\"Meteor v4\\n\");\n  run.expectEnd();\n  run.expectExit(0);\n\n});\n"
  },
  {
    "path": "tools/tests/boot-tests.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\n\nselftest.define(\"boot utils\", function (options) {\n  var bootUtils = require('../static-assets/server/boot-utils.js');\n  selftest.expectTrue(bootUtils.validPid(123));\n  selftest.expectTrue(bootUtils.validPid(\"123\"));\n  selftest.expectTrue(bootUtils.validPid(0x123));\n  selftest.expectTrue(bootUtils.validPid(\"0x123\"));\n\n  selftest.expectFalse(bootUtils.validPid(\"foo123\"));\n  selftest.expectFalse(bootUtils.validPid(\"foobar\"));\n  selftest.expectFalse(bootUtils.validPid(\"123foo\"));\n});\n"
  },
  {
    "path": "tools/tests/build-errors.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\n\n// This test was originally written to test the behavior of parse-stack.js when\n// there's a colon in a filename. We now try a lot harder to avoid putting\n// colons in filenames. But it's still a decent test that errors in legacy\n// source handlers work.\nselftest.define(\"build errors - legacy handler error\", function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"build-errors\");\n  s.cd(\"myapp\");\n  run = s.run(\"build\", \"myapp.tgz\");\n  run.waitSecs(60);\n  run.matchErr(\"crash in plugin (compiling foo.awesome)\");\n  run.expectExit(1);\n  run.forbidAll(\"Couldn't parse stack\");\n});\n"
  },
  {
    "path": "tools/tests/bundle.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar files = require('../fs/files.js');\n\nselftest.define(\"bundle\", [\"slow\"], function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"standard-app\");\n  s.cd(\"myapp\");\n  run = s.run(\"bundle\", \"myapp.tgz\");\n  run.waitSecs(60);\n  run.expectExit(0);\n\n  var tarball = files.pathJoin(s.cwd, \"myapp.tgz\");\n  selftest.expectEqual(files.exists(tarball), true);\n});\n"
  },
  {
    "path": "tools/tests/colon-converter-tests.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar files = require('../fs/files.js');\nvar testUtils = require('../tool-testing/test-utils.js');\nvar utils = require('../utils/utils.js');\nvar _ = require('underscore');\nvar tropohouse = require('../packaging/tropohouse.js');\n\nvar username = \"test\";\nvar password = \"testtest\";\n\n\n// This file tests Windows compatibility code. The main problem we are solving\n// is that the Windows file system can't handle files with certain characters\n// such as colons in file paths.\n\n// Here is the solution we reached:\n\n// 1. All packages published from Meteor 1.1 onwards will work the same way on\n// windows and posix. This means we will just not let you publish or build a\n// package if some of the file paths have colons.\n\n// 2. For packages published before 1.1:\n\n// On mac/linux: downloaded and used as-is\n\n// On Windows: downloaded and converted to contain only valid file paths.\n// The result is that some old packages might not work on Windows because of\n// bad file paths. Unfortunately, this is unavoidable since we have no way\n// of automatically converting those packages to work. In this case, users\n// should fix and republish their packages with Meteor 1.1 or above.\n\n// We need to test three things:\n\n// 1. You can't publish or build a package whose built tarball has colons in the\n// file paths.\n\n// 2. On mac/linux, a downloaded package that has colons in the file paths is\n// saved as-is, with no modifications\n\n// 3. On Windows, a downloaded package that has colons in the file paths is\n// converted to have no colons, and the metadata files are converted properly as\n// well.\n\n\n// Tests step 1: publishing tarball with colons\n\n// Returns a random package name.\nvar randomizedPackageName = function (username, start) {\n  // We often use package names in long, wrapped string output, so having them\n  // be a consistent length is very useful.\n  var startStr = start ? start + \"-\" : \"\";\n  return username + \":\" + startStr + utils.randomToken().substring(0, 6);\n};\n\n// On Mac and Linux, we can add NPM libraries with colons in filenames, but we\n// test that they shouldn't build (since they can later never run on Windows).\n// But we can't run these tests on Windows since when you call `npm install`\n// on a module that has filenames with colons -- the module gets added, but\n// without the colon filenames.\nif (process.platform !== \"win32\") {\n  selftest.define(\"can't build local packages with colons\", function () {\n    var s = new Sandbox();\n\n    var appName = \"test\";\n    var packageName = \"package-with-colons\";\n\n    s.createApp(appName, \"standard-app\");\n\n    s.cd(appName, function () {\n      s.mkdir(\"packages\");\n      s.cd(\"packages\", function () {\n        s.createPackage(\"package-with-colons\", packageName, \"package-with-colons\");\n      });\n\n      var run = s.run(\"add\", packageName);\n      run.matchErr(\"colons\");\n    });\n  });\n}\n\n// Tests step 2: old packages downloaded as-is\n\n// This test is only for unixy platforms\nif (process.platform !== \"win32\") {\n  selftest.define(\"package with colons is unpacked as-is on unix\", function () {\n    // We have a built package tarball in the git repo\n    var tarballPath = files.pathJoin(files.convertToStandardPath(__dirname),\n      \"built-packages\", \"has-colons.tgz\");\n\n    // Use regular tar to unpack the archive\n    var extractPath = files.mkdtemp();\n    utils.execFileSync(\"tar\",\n      [\"-xzf\", tarballPath, \"-C\", extractPath, \"--strip\", \"1\"]);\n\n    // Next, unpack it using our tropohouse code\n    var tarball = files.readFile(tarballPath);\n    var targetDirectory = tropohouse._extractAndConvert(tarball);\n\n    // Now, compare all of the filepaths and file contents\n    var startingTreeHash = files.treeHash(extractPath);\n    var finalTreeHash = files.treeHash(targetDirectory);\n\n    // Nothing should be different\n    selftest.expectEqual(finalTreeHash, startingTreeHash);\n  });\n}\n\n// Tests step 3: check if old packages are converted properly to have no weird\n// paths for Windows\n\nselftest.define(\"package with colons is converted on Windows\", function () {\n  // We have a built package tarball in the git repo\n  var tarballPath = files.pathJoin(files.convertToStandardPath(__dirname),\n    \"built-packages\", \"has-colons.tgz\");\n\n  // Unpack it using our tropohouse code\n  var tarball = files.readFile(tarballPath);\n\n  // Force conversion of file paths with second argument\n  var targetDirectory = tropohouse._extractAndConvert(tarball, true);\n\n  // Uncomment below to check results\n  // console.log(files.getPathsInDir(targetDirectory, {\n  //   cwd: targetDirectory\n  // }));\n\n  var expectedHash;\n  if (process.platform === \"win32\") {\n    expectedHash = \"Ayya11T8Zef16+F7C/sZSwRxIiGiBbBFIwUC88Weaqs=\";\n  } else {\n    expectedHash = \"AQX/7h0fXwHT9rNQvlBTvIZAE2g8krlnkEQMc9lTuMI=\";\n  }\n\n  // Saved tree hash of the correct result\n  selftest.expectEqual(files.treeHash(targetDirectory), expectedHash);\n});\n"
  },
  {
    "path": "tools/tests/command-line.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar archinfo = require('../utils/archinfo.js');\nvar release = require('../packaging/release.js');\nvar _ = require('underscore');\nvar files = require('../fs/files.js');\nvar utils = require('../utils/utils.js');\nvar runMongo = require('../runners/run-mongo.js');\n\nselftest.define(\"argument parsing\", function () {\n  var s = new Sandbox;\n  var run;\n\n  // bad command\n  run = s.run(\"aoeuasdf\");\n  run.matchErr(\"not a Meteor command\");\n  run.expectExit(1);\n\n  // bad subcommand\n  run = s.run(\"admin\", \"aoeuasdf\");\n  run.matchErr(\"not a Meteor command\");\n  run.expectExit(1);\n\n  // missing subcommand\n  run = s.run(\"admin\");\n  run.matchErr(\"for available commands\");\n  run.expectExit(1);\n\n  // conflicting command-like options\n  run = s.run(\"aoeuasdf\", \"--version\");\n  run.waitSecs(5);\n  run.matchErr(\"pass anything else along with --version\");\n  run.expectExit(1);\n\n  run = s.run(\"--arch\", \"--version\");\n  run.matchErr(\"pass anything else\");\n  run.expectExit(1);\n\n  run = s.run(\"run\", \"--version\");\n  run.matchErr(\"pass anything else\");\n  run.expectExit(1);\n\n  run = s.run(\"--arch\", \"--arch\");\n  run.matchErr(\"more than once\");\n  run.expectExit(1);\n\n  // --release takes exactly one value\n  run = s.run(\"--release\");\n  run.matchErr(\"needs a value\");\n  run.expectExit(1);\n\n  run = s.run(\"--release\", \"abc\", \"--release\", \"def\");\n  run.matchErr(\"should only be passed once\");\n  run.expectExit(1);\n\n  // required option missing\n  run = s.run(\"dummy\");\n  run.matchErr(\"option is required\");\n  run.matchErr(\"Usage: meteor dummy\");\n  run.expectExit(1);\n\n  // successful command invocation, correct parsing of arguments\n  run = s.run(\"dummy\", \"--ething\", \"x\");\n  run.read('\"x\" \"3000\" none []\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  // The tests below fail on Windows. There is a bug in Node about empty\n  // arguments that was fixed recently:\n  // https://github.com/joyent/node/issues/7138\n  if (process.platform !== \"win32\") {\n    run = s.run(\"dummy\", \"--ething\", \"\");\n    run.read('\"\" \"3000\" none []\\n');\n    run.expectEnd();\n    run.expectExit(0);\n\n    run = s.run(\"dummy\", \"--ething\", \"x\", \"\", \"\");\n    run.read('\"x\" \"3000\" none [\"\",\"\"]\\n');\n    run.expectEnd();\n    run.expectExit(0);\n  }\n\n  run = s.run(\"dummy\", \"--ething=\");\n  run.read('\"\" \"3000\" none []\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"-e=\");\n  run.read('\"\" \"3000\" none []\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-\");\n  run.read('\"x\" \"3000\" none [\"-\"]\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"-e\", \"x\");\n  run.read('\"x\" \"3000\" none []\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  // See comment above about empty arguments\n  if (process.platform !== \"win32\") {\n    run = s.run(\"dummy\", \"-e\", \"\");\n    run.read('\"\" \"3000\" none []\\n');\n    run.expectEnd();\n    run.expectExit(0);\n  }\n\n  run = s.run(\"dummy\", \"-exxx\");\n  run.read('\"xxx\" \"3000\" none []\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething\", \"-\");\n  run.read('\"-\" \"3000\" none []\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"--port\", \"1234\", \"--changed\");\n  run.read('\"x\" 1234 true []\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"--port\", \"0\", \"true\");\n  run.read('\"x\" 0 none [\"true\"]\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"--port\", \"01234\", \"12\", \"0013\");\n  run.read('\"x\" 1234 none [\"12\",\"0013\"]\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething\", \"--port\", \"1234\", \"--changed\");\n  run.read('\"--port\" \"3000\" true [\"1234\"]\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething=x=y=z\", \"-Up=3000\");\n  run.read('\"x=y=z\" 3000 none []\\nurl\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  // bad option\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"--foo\");\n  run.matchErr(\"--foo: unknown option\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-z\");\n  run.matchErr(\"-z: unknown option\");\n  run.expectExit(1);\n\n  // passing short and long options\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-p\", \"2000\", \"--port\", \"2000\");\n  run.matchErr(\"can't pass both -p and --port\");\n  run.expectExit(1);\n\n  // multiple values for an option\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"--port\", \"2000\", \"--port\", \"3000\");\n  run.matchErr(\"can only take one --port option\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-p\", \"2000\", \"-p\", \"2000\");\n  run.matchErr(\"can only take one --port (-p) option\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"--changed\", \"--changed\");\n  run.matchErr(\"can only take one --changed option\");\n  run.expectExit(1);\n\n  // missing option value\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"--port\");\n  run.matchErr(\"the --port option needs a value\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"--ething\");\n  run.matchErr(\"--ething option needs a value\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"-e\");\n  run.matchErr(\"--ething (-e) option needs a value\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"--changed\", \"-p\");\n  run.matchErr(\"the --port (-p) option needs a value\");\n  run.expectExit(1);\n\n  // non-numeric value for numeric option\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"--port\", \"kitten\");\n  run.matchErr(\"--port must be a number\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-p\", \"1234k\");\n  run.matchErr(\"--port (-p) must be a number\");\n  run.expectExit(1);\n\n  // bad use of =\n  run = s.run(\"dummy\", \"--=\");\n  run.readErr(\"Option names cannot begin with '='.\\n\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"--=asdf\");\n  run.readErr(\"Option names cannot begin with '='.\\n\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"-=\");\n  run.readErr(\"Option names cannot begin with '='.\\n\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"-ex\", \"--changed=foo\");\n  run.matchErr(\"the --changed option does not need a value.\\n\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"-ex\", \"-D=foo\");\n  run.matchErr(\"the --delete (-D) option does not need a value.\\n\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"-ex\", \"-UD=foo\");\n  run.matchErr(\"the --delete (-D) option does not need a value.\\n\");\n  run.expectExit(1);\n\n  // incorrect number of arguments\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"1\", \"2\", \"3\");\n  run.matchErr(\"too many arguments\");\n  run.matchErr(\"Usage: meteor dummy\");\n  run.expectExit(1);\n\n  run = s.run(\"bundle\");\n  run.matchErr(\"not enough arguments\");\n  run.matchErr(\"This command has been deprecated\");\n  run.expectExit(1);\n\n  run = s.run(\"bundle\", \"a\", \"b\");\n  run.matchErr(\"too many arguments\");\n  run.matchErr(\"This command has been deprecated\");\n  run.expectExit(1);\n\n\n  run = s.run(\"build\");\n  run.matchErr(\"not enough arguments\");\n  run.matchErr(\"Usage: meteor build\");\n  run.expectExit(1);\n\n  run = s.run(\"build\", \"a\", \"b\");\n  run.matchErr(\"too many arguments\");\n  run.matchErr(\"Usage: meteor build\");\n  run.expectExit(1);\n\n  // '--' to end parsing\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"--\", \"-p\", \"4000\");\n  run.read('\"x\" \"3000\" none [\"-p\",\"4000\"]\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"--\", \"--changed\", \"--changed\");\n  run.read('\"x\" \"3000\" none [\"--changed\",\"--changed\"]\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"--\");\n  run.read('\"x\" \"3000\" none []\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  // compact short options\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-p4000\", \"--changed\");\n  run.read('\"x\" 4000 true []\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-UD\", \"--changed\");\n  run.read('\"x\" \"3000\" true []\\nurl\\n\\delete\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-UDp4000\", \"--changed\");\n  run.read('\"x\" 4000 true []\\nurl\\ndelete\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-UDp4000\", \"--changed\");\n  run.read('\"x\" 4000 true []\\nurl\\ndelete\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-UDp4000\");\n  run.read('\"x\" 4000 none []\\nurl\\ndelete\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-UDkp4000\", \"--changed\");\n  run.matchErr(\"-k: unknown option\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-UDp4000k\", \"--changed\");\n  run.matchErr(\"--port (-p) must be a number\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-UD4000k\", \"--changed\");\n  run.matchErr(\"-4: unknown option\");\n  run.expectExit(1);\n\n  run = s.run(\"dummy\", \"--ething\", \"x\", \"-UDDp4000\", \"--changed\");\n  run.matchErr(\"one --delete (-D) option\");\n  run.expectExit(1);\n\n  // requiring an app dir\n  run = s.run(\"list\");\n  run.matchErr(\"not in a Meteor project\");\n  run.matchErr(\"meteor create\"); // new user help\n  run.expectExit(1);\n\n  s.createApp('myapp', 'standard-app');\n  s.cd('myapp', function () {\n    run = s.run(\"list\");\n    run.expectExit(0);\n  });\n});\n\n\nselftest.define(\"command-like options\", function () {\n  var s = new Sandbox;\n  var run;\n\n  run = s.run(\"--version\");\n  if (release.current.isCheckout()) {\n    run.matchErr(\"Unreleased\");\n    run.expectExit(1);\n  } else {\n    run.read(release.current.getDisplayName() + \"\\n\");\n    run.expectEnd();\n    run.expectExit(0);\n  }\n\n  run = s.run(\"--arch\");\n  run.read(archinfo.host() + \"\\n\");\n  run.expectEnd();\n  run.expectExit(0);\n});\n\nselftest.define(\"rails reminders\", function () {\n  var s = new Sandbox;\n  var run;\n\n  run = s.run(\"server\");\n  run.matchErr(\"Did you mean 'meteor run'?\");\n  run.expectExit(1);\n  run = s.run(\"console\");\n  run.matchErr(\"Did you mean 'meteor shell'?\");\n  run.expectExit(1);\n  run = s.run(\"new\");\n  run.matchErr(\"Did you mean 'meteor create'?\");\n  run.expectExit(1);\n  run = s.run(\"dbconsole\");\n  run.matchErr(\"Did you mean 'meteor mongo'?\");\n  run.expectExit(1);\n\n  // It should ignore args\n  run = s.run(\"server\", \"ignoredArg\");\n  run.matchErr(\"Did you mean 'meteor run'?\");\n  run.expectExit(1);\n  run = s.run(\"console\", \"ignoredArg\");\n  run.matchErr(\"Did you mean 'meteor shell'?\");\n  run.expectExit(1);\n  run = s.run(\"new\", \"ignoredArg\");\n  run.matchErr(\"Did you mean 'meteor create'?\");\n  run.expectExit(1);\n  run = s.run(\"dbconsole\", \"ignoredArg\");\n  run.matchErr(\"Did you mean 'meteor mongo'?\");\n  run.expectExit(1);\n});\n\nselftest.define(\"old cli tests (converted)\", function () {\n  var s = new Sandbox;\n  var run;\n\n  run = s.run(\"--help\");\n  run.match(\"List the packages explicitly used\");\n  run = s.run(\"run\", \"--help\");\n  run.match(\"Port to listen\");\n  run = s.run(\"test-packages\", \"--help\");\n  run.match(\"Port to listen\");\n  run = s.run(\"create\", \"--help\");\n  run.match(\"Make a subdirectory\");\n  run = s.run(\"update\", \"--help\");\n  run.match(\"Updates the meteor release\");\n  run = s.run(\"add\", \"--help\");\n  run.match(\"Adds packages\");\n  run = s.run(\"remove\", \"--help\");\n  run.match(\"Removes a package\");\n  run = s.run(\"list\", \"--help\");\n  run.match(\"This will not list transitive dependencies\");\n  run = s.run(\"bundle\", \"--help\");\n  run.match(\"command has been deprecated\");\n  run = s.run(\"build\", \"--help\");\n  run.match(\"Package this project\");\n  run = s.run(\"mongo\", \"--help\");\n  run.match(\"Opens a Mongo\");\n  run = s.run(\"deploy\", \"--help\");\n  run.match(\"Deploys the project\");\n  run = s.run(\"logs\", \"--help\");\n  run.match(\"Retrieves the\");\n  run = s.run(\"reset\", \"--help\");\n  run.match(\"Reset the current\");\n  run = s.run(\"test-packages\", \"--help\");\n  run.match(\"Runs unit tests\");\n\n  run = s.run();\n  run.matchErr(\"run: You're not in\");\n  run.expectExit(1);\n  run = s.run(\"run\");\n  run.matchErr(\"run: You're not in\");\n  run.expectExit(1);\n  run = s.run(\"add\", \"foo\");\n  run.matchErr(\"add: You're not in\");\n  run.expectExit(1);\n  run = s.run(\"remove\", \"foo\");\n  run.matchErr(\"remove: You're not in\");\n  run.expectExit(1);\n  run = s.run(\"list\");\n  run.matchErr(\"list: You're not in\");\n  run.expectExit(1);\n  run = s.run(\"bundle\", \"foo.tar.gz\");\n  run.matchErr(\"bundle: You're not in\");\n  run.expectExit(1);\n  run = s.run(\"build\", \"foo.tar.gz\");\n  run.matchErr(\"build: You're not in\");\n  run.expectExit(1);\n  run = s.run(\"mongo\");\n  run.matchErr(\"mongo: You're not in\");\n  run.expectExit(1);\n  run = s.run(\"deploy\", \"automated-test\");\n  run.matchErr(\"deploy: You're not in\");\n  run.expectExit(1);\n  run = s.run(\"reset\");\n  run.matchErr(\"reset: You're not in\");\n  run.expectExit(1);\n\n  var dir = \"skel with spaces\";\n  run = s.run(\"create\", dir);\n  run.expectExit(0);\n\n  selftest.expectTrue(files.stat(files.pathJoin(s.home, dir)).isDirectory());\n\n  s.cd(dir);\n\n  // add/remove/list\n  run = s.run('search', 'backbone');\n  run.match('backbone');\n\n  run = s.run('list');\n  run.expectExit(0);\n  run.forbid('backbone');\n\n  run = s.run('add', 'backbone');\n  run.match('backbone:');\n  run.expectExit(0);\n  run.forbidErr('no such package');\n\n  run = s.run('list');\n  run.match('backbone');\n\n  selftest.expectTrue(files.readFile(files.pathJoin(s.cwd, '.meteor', 'packages'), 'utf8').match(/backbone/));\n\n  // bundle\n  run = s.run('bundle', 'foo.tar.gz');\n  run.matchErr(/This command has been deprecated/);\n\n  run = s.run('build', '.');\n  run.expectExit(0);\n\n  if (process.platform !== 'win32') {\n    tar_tvzf = utils.execFileSync('tar', ['tvzf', files.pathJoin(s.cwd, dir + '.tar.gz')]);\n    selftest.expectTrue(tar_tvzf.success);\n  }\n  files.unlink(files.pathJoin(s.cwd, dir + '.tar.gz'));\n\n  // test-packages\n  var dieNow = files.pathJoin(s.home, 'local-packages', 'die-now');\n  files.mkdir_p(dieNow);\n  files.writeFile(files.pathJoin(dieNow, 'package.js'), [\n'Package.describe({',\n'  summary: \"die-now\",',\n'  version: \"1.0.0\"',\n'});',\n'Package.onTest(function (api) {',\n'  api.use(\"deps\"); // try to use a core package',\n'  api.addFiles([\"die-now.js\"], \"server\");',\n'});'\n  ].join('\\n'));\n  files.writeFile(files.pathJoin(dieNow, 'die-now.js'), [\n'if (Meteor.isServer) {',\n'  console.log(\"Dying\");',\n'  process.exit(0);',\n'}'\n  ].join('\\n'));\n\n  var port = 9100;\n  run = s.run('test-packages', '--once', '-p', port, dieNow);\n  run.match('Dying');\n  // since the server process was killed via 'process.exit', mongo is still running.\n  // the second argument is a dummy since it is hard to know the dbpath of mongo\n  // running for a test-runner\n  runMongo.findMongoAndKillItDead(port + 1, s.cwd);\n  utils.sleepMs(2000);\n\n\n  // settings\n  files.writeFile(files.pathJoin(s.cwd, 'settings.json'), JSON.stringify({ foo: \"bar\", baz: \"quux\" }));\n  files.writeFile(files.pathJoin(s.cwd, 'settings.js'), [\n'if (Meteor.isServer) {',\n'  Meteor.startup(function () {',\n'    if (!Meteor.settings) process.exit(1);',\n'    if (Meteor.settings.foo !== \"bar\") process.exit(1);',\n'    process.exit(0);',\n'  });',\n'}'\n  ].join('\\n'));\n\n  run = s.run('-p', port, '--settings', 'settings.json', '--once');\n  run.expectExit(0);\n  files.unlink(files.pathJoin(s.cwd, 'settings.js'));\n});\n"
  },
  {
    "path": "tools/tests/compiler-plugins.js",
    "content": "var _ = require('underscore');\nvar selftest = require('../tool-testing/selftest.js');\nvar files = require('../fs/files.js');\nimport { getUrl } from '../utils/http-helpers.js';\nimport { sleepMs } from '../utils/utils.js';\n\nvar Sandbox = selftest.Sandbox;\n\nvar MONGO_LISTENING =\n  { stdout: \" [initandlisten] waiting for connections on port\" };\n\nfunction startRun(sandbox) {\n  var run = sandbox.run();\n  run.match(\"myapp\");\n  run.match(\"proxy\");\n  run.tellMongo(MONGO_LISTENING);\n  run.match(\"MongoDB\");\n  return run;\n};\n\n// Tests the actual cache logic used by coffeescript.\nselftest.define(\"compiler plugin caching - coffee\", () => {\n  var s = new Sandbox({ fakeMongo: true });\n\n  s.createApp(\"myapp\", \"caching-coffee\");\n  s.cd(\"myapp\");\n  // Ask them to print out when they build a file (instead of using it from the\n  // cache) as well as when they load cache from disk.\n  s.set('METEOR_COFFEESCRIPT_CACHE_DEBUG', 't');\n  var run = startRun(s);\n\n  // First program built (server or web.browser) compiles everything.\n  run.match('CACHE(coffeescript): Ran (#1) on: ' + JSON.stringify(\n    ['/f1.coffee', '/f2.coffee', '/f3.coffee', '/packages/local-pack/p.coffee']\n  ));\n  // Second program doesn't need to compile anything because compilation works\n  // the same on both programs.\n  run.match(\"CACHE(coffeescript): Ran (#2) on: []\");\n  // App prints this:\n  run.match(\"Coffeescript X is 2 Y is 1 FromPackage is 4\");\n\n  s.write(\"f2.coffee\", \"share.Y = 'Y is 3'\\n\");\n  // Only recompiles f2.\n  run.match('CACHE(coffeescript): Ran (#3) on: [\"/f2.coffee\"]');\n  // And other program doesn't even need to do f2.\n  run.match(\"CACHE(coffeescript): Ran (#4) on: []\");\n  // Program prints this:\n  run.match(\"Coffeescript X is 2 Y is 3 FromPackage is 4\");\n\n  // Force a rebuild of the local package without actually changing the\n  // coffeescript file in it. This should not require us to coffee.compile\n  // anything (for either program).\n  s.append(\"packages/local-pack/package.js\", \"\\n// foo\\n\");\n  run.match(\"CACHE(coffeescript): Ran (#5) on: []\");\n  run.match(\"CACHE(coffeescript): Ran (#6) on: []\");\n  run.match(\"Coffeescript X is 2 Y is 3 FromPackage is 4\");\n\n  // But writing to the actual source file in the local package should\n  // recompile.\n  s.write(\"packages/local-pack/p.coffee\", \"FromPackage = 'FromPackage is 5'\");\n  run.match('CACHE(coffeescript): Ran (#7) on: [\"/packages/local-pack/p.coffee\"]');\n  run.match('CACHE(coffeescript): Ran (#8) on: []');\n  run.match(\"Coffeescript X is 2 Y is 3 FromPackage is 5\");\n\n  // We never should have loaded cache from disk, since we only made\n  // each compiler once and there were no cache files at this point.\n  run.forbid('CACHE(coffeescript): Loaded');\n\n  // Kill the run. Change one coffee file and re-run.\n  run.stop();\n  s.write(\"f2.coffee\", \"share.Y = 'Y is edited'\\n\");\n  run = startRun(s);\n\n  // This time there's a cache to load!\n  run.match('CACHE(coffeescript): Loaded /packages/local-pack/p.coffee');\n  run.match('CACHE(coffeescript): Loaded /f1.coffee');\n  run.match('CACHE(coffeescript): Loaded /f3.coffee');\n  // And we only need to re-compiler the changed file, even though we restarted.\n  run.match('CACHE(coffeescript): Ran (#1) on: [\"/f2.coffee\"]');\n  run.match('CACHE(coffeescript): Ran (#2) on: []');\n\n  run.match('Coffeescript X is 2 Y is edited FromPackage is 5');\n\n  run.stop();\n});\n\n// Tests the actual cache logic used by less and stylus.\n['less', 'stylus'].forEach((packageName) => {\n  const extension = packageName === 'stylus' ? 'styl' : packageName;\n\n  selftest.define(\"compiler plugin caching - \" + packageName, () => {\n    var s = new Sandbox({ fakeMongo: true });\n\n    s.createApp(\"myapp\", \"caching-\" + packageName);\n    s.cd(\"myapp\");\n    // Ask them to print out when they build a file (instead of using it from\n    // the cache) as well as when they load cache from disk.\n    s.set(`METEOR_${ packageName.toUpperCase() }_CACHE_DEBUG`, \"t\");\n    var run = startRun(s);\n\n    const cacheMatch = selftest.markStack((message) => {\n      run.match(`CACHE(${ packageName }): ${ message }`);\n    });\n\n    // First program built (web.browser) compiles everything.\n    cacheMatch('Ran (#1) on: ' + JSON.stringify([\n      // Though files in imports directories are compiled, they are marked\n      // as lazy so they will not be loaded unless imported.\n      \"/imports/dotdot.\" + extension,\n      \"/subdir/nested-root.\" + extension,\n      \"/top.\" + extension\n    ]));\n    // There is no render execution in the server program, because it has\n    // archMatching:'web'.  We'll see this more clearly when the next call later\n    // is \"#2\" --- we didn't miss a call!\n    // App prints this:\n    run.match(\"Hello world\");\n\n    // Check that the CSS is what we expect.\n    var checkCSS = selftest.markStack((borderStyleMap) => {\n      var builtBrowserProgramDir = files.pathJoin(\n        s.cwd, '.meteor', 'local', 'build', 'programs', 'web.browser');\n      var cssFile = _.find(\n        files.readdir(\n          files.pathJoin(s.cwd, '.meteor/local/build/programs/web.browser')),\n        path => path.match(/\\.css$/)\n      );\n      selftest.expectTrue(cssFile);\n      var actual = s.read(\n        files.pathJoin('.meteor/local/build/programs/web.browser', cssFile));\n      actual = actual.replace(/\\s+/g, ' ');  // simplify whitespace\n      var expected = _.map(borderStyleMap, (style, className) => {\n        return '.' + className + \" { border-style: \" + style + \"; }\";\n      }).join(' ');\n      selftest.expectEqual(actual, expected);\n    });\n    var expectedBorderStyles = {\n      el0: \"dashed\", el1: \"dotted\", el2: \"solid\", el3: \"groove\", el4: \"ridge\"};\n    checkCSS(expectedBorderStyles);\n\n    // Force a rebuild of the local package without actually changing the\n    // preprocessor file in it. This should not require us to render anything.\n    s.append(\"packages/local-pack/package.js\", \"\\n// foo\\n\");\n    cacheMatch('Ran (#2) on: []');\n    run.match(\"Hello world\");\n\n    function setVariable(variableName, value) {\n      switch (packageName) {\n      case 'less':\n        return `@${ variableName }: ${ value };\\n`;\n      case 'stylus':\n        return `$${ variableName } = ${ value }\\n`;\n      }\n    }\n    function importLine(fileWithoutExtension) {\n      switch (packageName) {\n      case 'less':\n        return `@import \"${ fileWithoutExtension }.less\";\\n`;\n      case 'stylus':\n        return `@import \"${ fileWithoutExtension }.styl\"\\n`;\n      }\n    }\n\n    // Writing to a single file only re-renders the root that depends on it.\n    s.write('packages/local-pack/p.' + extension,\n            setVariable('el4-style', 'inset'));\n    expectedBorderStyles.el4 = 'inset';\n    cacheMatch(`Ran (#3) on: [\"/top.${ extension }\"]`);\n    run.match(\"Client modified -- refreshing\");\n    checkCSS(expectedBorderStyles);\n\n    // This works for changing a root too.\n    s.write('subdir/nested-root.' + extension,\n            '.el0 { border-style: double; }\\n');\n    expectedBorderStyles.el0 = 'double';\n    cacheMatch(`Ran (#4) on: [\"/subdir/nested-root.${ extension }\"]`);\n    run.match(\"Client modified -- refreshing\");\n    checkCSS(expectedBorderStyles);\n\n    // Adding a new root works too.\n    s.write('yet-another-root.' + extension,\n            '.el6 { border-style: solid; }\\n');\n    expectedBorderStyles.el6 = 'solid';\n    cacheMatch(`Ran (#5) on: [\"/yet-another-root.${ extension }\"]`);\n    run.match(\"Client modified -- refreshing\");\n    checkCSS(expectedBorderStyles);\n\n    // We never should have loaded cache from disk, since we only made\n    // each compiler once and there were no cache files at this point.\n    run.forbid('CACHE(${ packageName }): Loaded');\n\n    // Kill the run. Change one file and re-run.\n    run.stop();\n    s.write('packages/local-pack/p.' + extension,\n            setVariable('el4-style', 'double'));\n    expectedBorderStyles.el4 = 'double';\n    run = startRun(s);\n\n    // This time there's a cache to load!  Note that for\n    // MultiFileCachingCompiler we load all the cache entries, even for the\n    // not-up-to-date file 'top', because we only key off of filename, not off\n    // of cache key.\n    cacheMatch('Loaded {}/subdir/nested-root.' + extension);\n    cacheMatch('Loaded {}/top.' + extension);\n    cacheMatch('Loaded {}/yet-another-root.' + extension);\n    cacheMatch(`Ran (#1) on: [\"/top.${ extension }\"]`);\n    run.match('Hello world');\n    checkCSS(expectedBorderStyles);\n\n    s.write('bad-import.' + extension, importLine('/foo/bad'));\n    run.match('Errors prevented startup');\n    switch (packageName) {\n    case 'less':\n      run.match('bad-import.less:1: Unknown import: /foo/bad.less');\n      break;\n    case 'stylus':\n      run.match('bad-import.styl: Stylus compiler error: bad-import.styl:1');\n      run.match('failed to locate @import file /foo/bad.styl');\n      break;\n    }\n    run.match('Waiting for file change');\n\n    run.stop();\n  });\n});\n\n// Tests that rebuilding a compiler plugin re-instantiates the source processor,\n// but other changes don't.\nselftest.define(\"compiler plugin caching - local plugin\", function () {\n  var s = new Sandbox({ fakeMongo: true });\n\n  s.createApp(\"myapp\", \"local-compiler-plugin\");\n  s.cd(\"myapp\");\n\n  var run = startRun(s);\n\n  // The compiler gets used the first time...\n  run.match(\"PrintmeCompiler invocation 1\");\n  // ... and the program runs the generated code.\n  run.match(\"PMC: Print out bar\");\n  run.match(\"PMC: Print out foo\");\n\n  s.write(\"quux.printme\", \"And print out quux\");\n  // PrintmeCompiler gets reused.\n  run.match(\"PrintmeCompiler invocation 2\");\n  // And the right output prints out\n  run.match(\"PMC: Print out bar\");\n  run.match(\"PMC: Print out foo\");\n  run.match(\"PMC: And print out quux\");\n\n  // Restart meteor; see that the disk cache gets used.\n  run.stop();\n  run = startRun(s);\n  // Disk cache gets us up to 3.\n  run.match(\"PrintmeCompiler invocation 3\");\n  // And the right output prints out\n  run.match(\"PMC: Print out bar\");\n  run.match(\"PMC: Print out foo\");\n  run.match(\"PMC: And print out quux\");\n\n  // Edit the compiler itself.\n  s.write('packages/local-plugin/plugin.js',\n          s.read('packages/local-plugin/plugin.js').replace(/PMC/, 'pmc'));\n  // New PrintmeCompiler object, and empty disk cache dir.\n  run.match(\"PrintmeCompiler invocation 1\");\n  // And the right output prints out (lower case now)\n  run.match(\"pmc: Print out bar\");\n  run.match(\"pmc: Print out foo\");\n  run.match(\"pmc: And print out quux\");\n\n  run.stop();\n});\n\n// Test error on duplicate compiler plugins.\nselftest.define(\"compiler plugins - duplicate extension\", () => {\n  const s = new Sandbox({ fakeMongo: true });\n\n  s.createApp(\"myapp\", \"duplicate-compiler-extensions\");\n  s.cd(\"myapp\");\n\n  let run = startRun(s);\n  run.match('Errors prevented startup');\n  run.match('conflict: two packages');\n  run.match('trying to handle *.myext');\n\n  // Fix it by changing one extension.\n  s.write('packages/local-plugin/plugin.js',\n          s.read('packages/local-plugin/plugin.js').replace('myext', 'xext'));\n  run.match('Modified -- restarting');\n\n  run.stop();\n});\n\n// Test error when a source file no longer has an active plugin.\nselftest.define(\"compiler plugins - inactive source\", () => {\n  const s = new Sandbox({ fakeMongo: true });\n\n  // This app depends on the published package 'glasser:uses-sourcish', and\n  // contains a local package 'local-plugin'.\n  //\n  // glasser:uses-sourcish depends on local-plugin and contains a file\n  // 'foo.sourcish'. When glasser:uses-sourcish@0.0.1 was published, a local\n  // copy of 'local-plugin' had a plugin which called registerCompiler for the\n  // extension '*.sourcish', and so 'foo.sourcish' is in the published isopack\n  // as a source file. However, the copy of 'local-plugin' currently in the test\n  // app contains no plugins. So we hit this weird error.\n  s.createApp('myapp', 'uses-published-package-with-inactive-source');\n  s.cd('myapp');\n\n  let run = startRun(s);\n  run.match('Errors prevented startup');\n  run.match('no plugin found for foo.sourcish in glasser:use-sourcish');\n  run.match('none is now');\n\n  run.stop();\n});\n\n// Test error when the registerCompiler callback throws.\nselftest.define(\"compiler plugins - compiler throws\", () => {\n  const s = new Sandbox({ fakeMongo: true });\n\n  s.createApp('myapp', 'compiler-plugin-throws-on-instantiate');\n  s.cd('myapp');\n\n  const run = s.run('add', 'local-plugin');\n  run.matchErr('Errors while adding packages');\n  run.matchErr(\n    'While running registerCompiler callback in package local-plugin');\n  // XXX This is wrong! The path on disk is packages/local-plugin/plugin.js, but\n  // at some point we switched to the servePath which is based on the *plugin*'s\n  // \"package\" name.\n  run.matchErr('packages/compilePrintme/plugin.js:5:1: Error in my ' +\n               'registerCompiler callback!');\n  run.expectExit(1);\n});\n\n// Test that compiler plugins can add static assets. Also tests `filenames`\n// option to registerCompiler.\nselftest.define(\"compiler plugins - compiler addAsset\", () => {\n  const s = new Sandbox({ fakeMongo: true });\n\n  s.createApp('myapp', 'compiler-plugin-add-asset');\n  s.cd('myapp');\n\n  const run = startRun(s);\n  // Test server-side asset.\n  run.match(\"extension is null\");  // test getExtension -> null\n  run.match(\"Asset says Print out foo\");\n\n  // Test client-side asset.\n  const body = getUrl('http://localhost:3000/foo.printme');\n  selftest.expectEqual(body, 'Print out foo\\n');\n\n  run.stop();\n});\n\n\n// Test that a package can have a single file that is both source code and an\n// asset\nselftest.define(\"compiler plugins - addAssets\", () => {\n  const s = new Sandbox({ fakeMongo: true });\n\n  s.createApp('myapp', 'compiler-plugin-asset-and-source');\n  s.cd('myapp');\n\n  const run = startRun(s);\n\n  // Test server-side asset.\n  run.match(\"Printing out my own source code!\");\n\n  // Test client-side asset.\n  let body = getUrl('http://localhost:3000/packages/' +\n    'asset-and-source/asset-and-source.js');\n  selftest.expectTrue(body.indexOf('Printing out my own source code!') !== -1);\n\n  // Test that deprecated API still works (added in 1.2.1 in response to people\n  // having trouble upgrading to 1.2)\n  s.write(\"packages/asset-and-source/package.js\", `Package.describe({\n      name: 'asset-and-source',\n      version: '0.0.1'\n    });\n\n    Package.onUse(function(api) {\n      api.addFiles('asset-and-source.js');\n      api.addFiles('asset-and-source.js',\n        ['client', 'server'], { isAsset: true });\n    });\n  `);\n\n  // Test server-side asset.\n  run.match(\"Printing out my own source code!\");\n\n  // Test client-side asset.\n  body = getUrl('http://localhost:3000/packages/' +\n    'asset-and-source/asset-and-source.js');\n  selftest.expectTrue(body.indexOf('Printing out my own source code!') !== -1);\n\n  // Test error messages for malformed package files\n  s.write(\"packages/asset-and-source/package.js\", `Package.describe({\n      name: 'asset-and-source',\n      version: '0.0.1'\n    });\n\n    Package.onUse(function(api) {\n      api.addFiles('asset-and-source.js');\n      api.addAssets('asset-and-source.js', ['client', 'server']);\n      api.addFiles('asset-and-source.js');\n    });\n  `);\n\n  run.match(/Duplicate source file/);\n\n  s.write(\"packages/asset-and-source/package.js\", `Package.describe({\n      name: 'asset-and-source',\n      version: '0.0.1'\n    });\n\n    Package.onUse(function(api) {\n      api.addFiles('asset-and-source.js');\n      api.addAssets('asset-and-source.js', ['client', 'server']);\n      api.addAssets('asset-and-source.js', ['client', 'server']);\n    });\n  `);\n\n  run.match(/Duplicate asset file/);\n\n  s.write(\"packages/asset-and-source/package.js\", `Package.describe({\n      name: 'asset-and-source',\n      version: '0.0.1'\n    });\n\n    Package.onUse(function(api) {\n      api.addAssets('asset-and-source.js');\n    });\n  `);\n\n  run.match(/requires a second argument/);\n\n  run.stop();\n});\n"
  },
  {
    "path": "tools/tests/constraint-solver.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar files = require('../fs/files.js');\nvar _= require('underscore');\n\n// Runs all of the constraint-solver tests, including ones that tie up the CPU\n// for too long to safely run in the normal test-packages run.\n// Only run from checkouts, because test-packages only works on local packages.\nselftest.define('constraint solver benchmark', ['slow', 'checkout'], function () {\n  var s = new Sandbox();\n  s.set('CONSTRAINT_SOLVER_BENCHMARK', 't');\n  var run = s.run(\"test-packages\",\n                  \"--driver-package=test-server-tests-in-console-once\",\n                  \"--once\",\n                  \"constraint-solver\");\n\n  run.waitSecs(60*4);\n  run.match(\"ALL TESTS PASSED\");\n  run.expectExit(0);\n});\n"
  },
  {
    "path": "tools/tests/cordova-builds.js",
    "content": "var files = require('../fs/files.js');\nvar selftest = require('../tool-testing/selftest.js');\nvar testUtils = require('../tool-testing/test-utils.js');\nvar Sandbox = selftest.Sandbox;\n\nvar checkMobileServer = selftest.markStack(function (s, expected) {\n  var output = s.read(\"android/project/assets/www/application/index.html\");\n  var mrc = testUtils.getMeteorRuntimeConfigFromHTML(output);\n  selftest.expectEqual(mrc.DDP_DEFAULT_CONNECTION_URL, expected);\n});\n\nvar cleanUpBuild = function (s) {\n  files.rm_recursive(files.pathJoin(s.cwd, \"android\"));\n  files.unlink(files.pathJoin(s.cwd, \"myapp.tar.gz\"));\n};\n\nselftest.define(\"cordova builds with server options\", [\"cordova\", \"slow\"], function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"standard-app\");\n  s.cd(\"myapp\");\n\n  run = s.run(\"add-platform\", \"android\");\n  run.match(\"added\");\n  run.expectExit(0);\n\n  run = s.run(\"build\", \".\");\n  run.waitSecs(90);\n  run.matchErr(\n    \"Supply the server hostname and port in the --server option\");\n  run.expectExit(1);\n\n  run = s.run(\"build\", \".\", \"--server\", \"5000\");\n  run.waitSecs(90);\n  run.matchErr(\"--server must include a hostname\");\n  run.expectExit(1);\n\n  run = s.run(\"build\", \".\", \"--server\", \"https://example.com:5000\");\n  run.waitSecs(300);\n  run.expectExit(0);\n  checkMobileServer(s, \"https://example.com:5000/\");\n  cleanUpBuild(s);\n\n  run = s.run(\"build\", \".\", \"--server\", \"example.com:5000\");\n  run.waitSecs(90);\n  run.expectExit(0);\n  checkMobileServer(s, \"http://example.com:5000/\");\n  cleanUpBuild(s);\n\n  run = s.run(\"build\", \".\", \"--server\", \"example.com\");\n  run.waitSecs(90);\n  run.expectExit(0);\n  checkMobileServer(s, \"http://example.com/\");\n  cleanUpBuild(s);\n\n  run = s.run(\"build\", \".\", \"--server\", \"https://example.com\");\n  run.waitSecs(90);\n  run.expectExit(0);\n  checkMobileServer(s, \"https://example.com/\");\n  cleanUpBuild(s);\n\n  // XXX COMPAT WITH 0.9.2.2\n  run = s.run(\"build\", \".\", \"--mobile-port\", \"example.com:5000\");\n  run.waitSecs(90);\n  run.expectExit(0);\n  checkMobileServer(s, \"http://example.com:5000/\");\n  cleanUpBuild(s);\n});\n"
  },
  {
    "path": "tools/tests/cordova-hcp.js",
    "content": "var _ = require('underscore');\nvar selftest = require('../tool-testing/selftest.js');\nvar httpHelpers = require('../utils/http-helpers.js');\nvar Sandbox = selftest.Sandbox;\nvar testUtils = require('../tool-testing/test-utils.js');\nvar config = require('../meteor-services/config.js');\n\n// This is not an end-to-end test for Cordova hot code push, but this test\n// is for the issue that we observed where the value of the\n// --mobile-server argument would get lost across hot code pushes. That\n// is: the initial Cordova app (before receiving any hot code pushes)\n// would connect to the server specified by --mobile-server, but after\n// it receives a hot code push, it would be connected to whatever\n// ROOT_URL is on the server.\nselftest.define(\n  \"cordova --mobile-server argument persists across hot code pushes\", [\"cordova\", \"slow\"], function () {\n    var s = new Sandbox();\n    var run;\n\n    s.createApp(\"myapp\", \"standard-app\");\n    s.cd(\"myapp\");\n\n    // Add 'android' to the .meteor/platforms file, just so that the\n    // Cordova boilerplate will be generated and served, without having\n    // to download the whole Android sdk.\n    var platforms = s.read(\".meteor/platforms\");\n    s.write(\".meteor/platforms\", platforms + \"\\nandroid\\n\");\n\n    run = s.run(\"run\", \"android\", \"--mobile-server\", \"example.com\");\n    run.waitSecs(30);\n    run.match(\"Started your app\");\n\n    var result = httpHelpers.getUrl(\n      \"http://localhost:3000/__cordova/index.html\");\n\n    var mrc = testUtils.getMeteorRuntimeConfigFromHTML(result);\n    selftest.expectEqual(mrc.DDP_DEFAULT_CONNECTION_URL, \"http://example.com/\");\n    selftest.expectEqual(mrc.ROOT_URL, \"http://example.com/\");\n\n    run.stop();\n});\n"
  },
  {
    "path": "tools/tests/cordova-platforms.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar files = require('../fs/files.js');\n\nselftest.define(\"add cordova platforms\", [\"cordova\"], function () {\n  var s = new Sandbox();\n  var run;\n\n  // Starting a run\n  s.createApp(\"myapp\", \"package-tests\");\n  s.cd(\"myapp\");\n\n  run = s.run(\"run\", \"android\");\n  run.matchErr(\"Please add the Android platform to your project first\");\n  run.match(\"meteor add-platform android\");\n  run.expectExit(1);\n\n  var run = s.run(\"add-platform\", \"android\");\n  // Cordova may need to download cordova-android if it's not already\n  // cached (in ~/.cordova).\n  run.waitSecs(30);\n  run.match(\"added platform\");\n  run.expectExit(0);\n\n  run = s.run(\"remove-platform\", \"foo\");\n  run.matchErr(\"foo: platform is not\");\n  run.expectExit(1);\n\n  run = s.run(\"remove-platform\", \"android\");\n  run.match(\"removed\");\n  run = s.run(\"run\", \"android\");\n  run.matchErr(\"Please add the Android platform to your project first\");\n  run.match(\"meteor add-platform android\");\n  run.expectExit(1);\n});\n"
  },
  {
    "path": "tools/tests/cordova-plugins.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar files = require('../fs/files.js');\nvar _ = require('underscore');\n\n// Copy the contents of one file to another.  In these series of tests, we often\n// want to switch contents of package.js files. It is more legible to copy in\n// the backup file rather than trying to write into it manually.\n//\n// XXX: Surely there is a function for this in fs?\n// XXX: In which case, perhaps move this to sandbox.\nvar copyFile = function(from, to, sand) {\n  var contents = sand.read(from);\n  if (!contents) {\n    throw new Error(\"File \" + from + \" does not exist.\");\n  };\n  sand.write(to, contents);\n};\n\n// Given a sandbox, that has the app as its currend cwd, read the versions file\n// and read the plugins list.\n//\n// sand: a sandbox, that has the main app directory as its cwd.\nvar getCordovaPluginsList = function(sand) {\n  var env = files.currentEnvWithPathsAdded(files.getCurrentNodeBinDir());\n  env.METEOR_WAREHOUSE_DIR = sand.warehouse;\n\n  var lines = selftest.execFileSync('cordova', ['plugins'],\n    {\n      cwd: files.pathJoin(sand.cwd, '.meteor', 'local', 'cordova-build'),\n      env: env\n    }).split(\"\\n\");\n  if (lines[0].match(/No plugins/)) {\n    lines = [];\n  }\n  lines.sort();\n  return lines;\n}\n\n// Given a sandbox, that has the app as its currend cwd, read the versions file\n// and check that it contains the plugins that we are looking for. We don't\n// check the order, we just want to make sure that the right dependencies are\n// in.\n//\n// sand: a sandbox, that has the main app directory as its cwd.\n// plugins: an array of plugins in order.\nvar checkCordovaPlugins = selftest.markStack(function(sand, plugins) {\n  var cordovaPlugins = getCordovaPluginsList(sand);\n\n  plugins = _.clone(plugins).sort();\n\n  var i = 0;\n  _.each(cordovaPlugins, function(line) {\n    if (!line || line === '') {\n      return;\n    }\n    // XXX should check for the version as well?\n    selftest.expectEqual(line.split(' ')[0], plugins[i]);\n    i++;\n  });\n  selftest.expectEqual(plugins.length, i);\n});\n\n// Like the function above but only looks if a certain plugin is on the list\nvar checkCordovaPluginExists = selftest.markStack(function(sand, plugin) {\n  var cordovaPlugins = getCordovaPluginsList(sand);\n  var found = false;\n  cordovaPlugins = cordovaPlugins.map(function (line) {\n    if (line && line !== '') {\n      return line.split(' ')[0];\n    }\n  });\n  selftest.expectTrue(_.contains(cordovaPlugins, plugin));\n});\n\n// Given a sandbox, that has the app as its cwd, read the cordova plugins\n// file and check that it contains exactly the plugins specified, in order.\n//\n// sand: a sandbox, that has the main app directory as its cwd.\n// plugins: an array of plugins in order. Plugins can be of the form:\n//\n//    standard-app-plugins (ie: name), in which case this will match any\n//    version of that plugin as long as it is included.\n//\n//    awesome-plugin@1.0.0 (ie: name@version) to match that name at that\n//    version explicitly. This is for plugins that we included at a specific\n//    version.\nvar checkUserPlugins = function(sand, plugins) {\n  var lines = sand.read(\".meteor/cordova-plugins\").split(\"\\n\");\n  var depend = {};\n  _.each(lines, function(line) {\n    if (!line) {\n      return;\n    }\n    // plugins are stored of the form foo@1.0.0, so this should give us an\n    // array [foo, 1.0.0].\n    var split = line.split('@');\n    var plugins = split[0];\n    depend[plugins] = split[1];\n  });\n  var i = 0;\n\n  _.each(plugins, function (plugins) {\n    var split = plugins.split('@');\n    if (split.length > 1) {\n      selftest.expectEqual(depend[split[0]], split[1]);\n    } else {\n      var exists = _.has(depend, split[0]);\n      selftest.expectEqual(exists, true);\n    }\n    i++;\n  });\n  selftest.expectEqual(plugins.length, i);\n};\n\nvar startAppOnAndroidEmulator = function (s) {\n  var run = s.run(\"run\", \"android\");\n  // Building and running the app on the Android Emulator can take a long time.\n  run.waitSecs(60);\n  run.match(\"Started app on Android Emulator\");\n  return run;\n}\n\nvar addPlatform = function (s, platform) {\n  var run = s.run(\"add-platform\", \"android\");\n  // Cordova may need to download cordova-android if it's not already\n  // cached (in ~/.cordova).\n  run.waitSecs(30);\n  run.match(\"added platform\");\n}\n\n// Add plugins to an app. Change the contents of the plugins and their\n// dependencies, make sure that the app still refreshes.\nselftest.define(\"change cordova plugins\", [\"cordova\"], function () {\n  var s = new Sandbox();\n  var run;\n\n  // Starting a run\n  s.createApp(\"myapp\", \"package-tests\");\n  s.cd(\"myapp\");\n  run = s.run();\n  run.match(\"myapp\");\n  run.match(\"proxy\");\n  run.match(\"MongoDB\");\n  run.match(\"your app\");\n  run.match(\"running at\");\n  run.match(\"localhost\");\n\n  // Add a local package contains-cordova-plugin.\n  s.write(\".meteor/packages\", \"meteor-base \\n contains-cordova-plugin\");\n  run.match(\"restarted\");\n\n  // Change something in the plugin.\n  s.cp('packages/contains-cordova-plugin/package2.js', 'packages/contains-cordova-plugin/package.js');\n  run.match(\"restarted\");\n\n  // Introduce an error.\n  s.cp('packages/contains-cordova-plugin/package3.js', 'packages/contains-cordova-plugin/package.js');\n  run.match(\"valid version\");\n\n  // Fix the error.\n  s.cp('packages/contains-cordova-plugin/package2.js', 'packages/contains-cordova-plugin/package.js');\n  run.match(\"restarted\");\n});\n\n// Add plugins through the command line, and make sure that the correct set of\n// changes is reflected in .meteor/packages, .meteor/versions and list\nselftest.define(\"add cordova plugins\", [\"slow\", \"cordova\"], function () {\n  var s = new Sandbox();\n  var run;\n\n  // Starting a run\n  s.createApp(\"myapp\", \"package-tests\");\n  s.cd(\"myapp\");\n  s.set(\"METEOR_OFFLINE_CATALOG\", \"t\");\n\n  run = s.run(\"remove\", \"meteor-base\");\n  run.match(\"removed\");\n\n  run = s.run(\"run\", \"android\");\n  run.matchErr(\"Please add the Android platform to your project first\");\n  run.match(\"meteor add-platform \");\n\n  run = addPlatform(s, 'android');\n\n  run = s.run(\"add\", \"cordova:cordova-plugin-camera@1.2.0\");\n  run.match(\"Added Cordova plugin cordova-plugin-camera\");\n  run.expectExit(0);\n\n  run = s.run(\"add\", \"cordova:cordova-plugin-file\");\n  run.matchErr(\"exact version\");\n  run.expectExit(1);\n\n  // The current behavior doesn't fail if a plugin is not in the registry until\n  // build time.\n  run = s.run(\"add\", \"cordova:foo@1.0.0\");\n  run.match(\"Added Cordova plugin foo\");\n  run.expectExit(0);\n\n  run = s.run(\"remove\", \"cordova:foo\");\n  run.match(\"Removed Cordova plugin foo\");\n  run.expectExit(0);\n\n  checkUserPlugins(s, [\"cordova-plugin-camera\"]);\n\n  run = s.run(\"add\", \"contains-cordova-plugin\");\n  run.match(\"added,\");\n  run.match(\"contains a cordova plugin\");\n  run.expectExit(0);\n\n  checkUserPlugins(s, [\"cordova-plugin-camera\"]);\n\n  run = s.run(\"list\");\n  run.match(\"cordova-plugin-camera\");\n\n  run = s.run(\"list-platforms\");\n  run.match(\"android\");\n\n  run = s.run(\"build\", '../a', \"--server\", \"localhost:3000\");\n  run.waitSecs(60);\n  run.expectExit(0);\n\n  checkCordovaPlugins(s, [\"cordova-plugin-camera\",\n    \"com.phonegap.plugins.facebookconnect\"]);\n\n  // Remove a plugin\n  run = s.run(\"remove\", \"contains-cordova-plugin\");\n  run.match(\"removed\");\n\n  run = s.run(\"build\", '../a', \"--server\", \"localhost:3000\");\n  run.waitSecs(60);\n  run.expectExit(0);\n\n  run = s.run(\"remove\", \"cordova:cordova-plugin-camera\");\n  run.match(\"Removed\");\n  run.expectExit(0);\n\n  run = s.run(\"build\", '../a', \"--server\", \"localhost:3000\");\n  run.waitSecs(60);\n  run.expectExit(0);\n\n  checkCordovaPlugins(s, []);\n\n  run = s.run(\"add\", \"cordova:cordova-plugin-device@1.0.1\");\n  run.match(\"Added\");\n  run.expectExit(0);\n\n  run = s.run(\"build\", '../a', \"--server\", \"localhost:3000\");\n  run.waitSecs(60);\n  run.expectExit(0);\n  checkCordovaPlugins(s, [\"cordova-plugin-device\"]);\n\n  run = s.run(\"remove\", \"cordova:cordova-plugin-device\");\n  run.match(\"Removed\");\n  run.expectExit(0);\n\n  run = s.run(\"add\", \"cordova:com.example.plugin@file://\");\n  run.matchErr(\"exact version\");\n  run.expectExit(1);\n\n  run = s.run(\"add\", \"cordova:com.example.plugin@file://../../plugin_directory\");\n  run.match(\"Added Cordova plugin com.example.plugin\");\n  run.expectExit(0);\n\n  checkUserPlugins(s, [\"com.example.plugin\"]);\n\n  // This should fail beacuse the plugin does not exists at the specified path\n  run = s.run(\"build\", '../a', \"--server\", \"localhost:3000\");\n  run.waitSecs(30);\n  run.expectExit(1);\n\n  checkCordovaPlugins(s, []);\n\n  // Add a package with Cordova.depends with local plugin (added from path)\n  run = s.run(\"add\", \"empty-cordova-plugin\");\n  run.match(\"added,\");\n  run.match(\"contains an empty cordova plugin\");\n  run.expectExit(0);\n});\n\nselftest.define(\"remove cordova plugins\", ['cordova'], function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"package-tests\");\n  s.cd(\"myapp\");\n  run = s.run(\"add\", \"cordova:cordova-plugin-camera@0.3.0\");\n  run.expectExit(0);\n\n  checkUserPlugins(s, [\"cordova-plugin-camera\"]);\n\n  // Removing a plugin that hasn't been added should say that it isn't\n  // in this project.\n  run = s.run(\"remove\", \"cordova:blahblah\");\n  run.matchErr(\"not in this project\");\n  run.forbidAll(\"Removed\");\n  run.expectExit(1);\n\n  run = s.run(\"remove\", \"cordova:blahblah\",\n              \"cordova:cordova-plugin-camera\");\n  run.matchErr(\"not in this project\");\n  run.match(\"Removed\");\n  run.expectExit(1);\n  checkUserPlugins(s, []);\n\n  run = s.run(\"add\", \"cordova:com.example.plugin@file://../../plugin_directory\");\n  run.match(\"Added Cordova plugin com.example.plugin\");\n  run.expectExit(0);\n  checkUserPlugins(s, [\"com.example.plugin\"]);\n\n  run = s.run(\"remove\", \"cordova:com.example.plugin\");\n  run.match(\"Removed\");\n  run.expectExit(0);\n  checkUserPlugins(s, []);\n\n});\n\nselftest.define(\"meteor exits when cordova platforms it is currently running \\\nare removed\", [\"slow\", \"cordova\"], function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"package-tests\");\n  s.cd(\"myapp\");\n\n  addPlatform(s, \"android\");\n\n  run = startAppOnAndroidEmulator(s);\n\n  // Remove a platform via command line\n  platformRun = s.run(\"remove-platform\", \"android\");\n  platformRun.match(\"removed platform\");\n\n  run.waitSecs(60);\n  run.matchErr(\"Your app's platforms have changed\");\n  run.matchErr(\"Restart meteor\");\n  run.expectExit(254);\n\n  addPlatform(s, \"android\");\n\n  // Remove a platform in .meteor/platforms\n  run = startAppOnAndroidEmulator(s);\n\n  platforms = s.read(files.pathJoin(\".meteor\", \"platforms\"));\n  platforms = platforms.replace(/android/g, \"\");\n  s.write(files.pathJoin(\".meteor\", \"platforms\"), platforms);\n\n  run.waitSecs(60);\n  run.matchErr(\"Your app's platforms have changed\");\n  run.matchErr(\"Restart meteor\");\n  run.expectExit(254);\n});\n\nselftest.define(\"meteor reinstalls only local cordova plugins on consecutive builds/runs\", [\"slow\", \"cordova\"], function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"package-tests\");\n  s.cd(\"myapp\");\n\n  run = addPlatform(s, 'android');\n\n  var\n    pluginPath          = '../cordova-local-plugin',\n    pluginSource        = \"packages/empty-cordova-plugin/plugin\",\n    androidPluginSource = \".meteor/local/cordova-build/platforms/android/src\";\n\n\n  // Copy fake cordova plugin to ../cordova-local-plugin\n  s.mkdir(pluginPath);\n  s.cp(pluginSource + '/plugin.xml', pluginPath + '/plugin.xml');\n  s.mkdir(pluginPath + '/www');\n  s.mkdir(pluginPath + '/src');\n  s.mkdir(pluginPath + '/src/android');\n  s.cp(pluginSource + '/www/Empty.js', pluginPath +'/www/Empty.js');\n  s.cp(\n    pluginSource + '/src/android/Empty.java',\n    pluginPath + '/src/android/Empty.java'\n  );\n\n  // Add the local cordova plugin\n  run = s.run(\"add\", \"cordova:com.cordova.empty@file://../cordova-local-plugin\");\n  run.match(\"Added Cordova plugin com.cordova.empty\");\n  run.expectExit(0);\n\n  checkUserPlugins(s, [\"com.cordova.empty\"]);\n\n  // Run meteor and check if the cordova android build have the plugin file.\n  run = startAppOnAndroidEmulator(s);\n  run.stop();\n\n  selftest.expectTrue(\n    s.read(\n      androidPluginSource + \"/com/cordova/empty/Empty.java\"\n    ).indexOf('change') === -1\n  );\n  selftest.expectTrue(\n    s.read(\n      androidPluginSource + \"/com/cordova/empty/Empty.java\"\n    ).indexOf('CordovaPlugin') > -1\n  );\n\n  // Copy changed file to the plugin\n  s.cp(\n    pluginSource + '/src/android/Empty_changed.java',\n    pluginPath + '/src/android/Empty.java'\n  );\n\n  // Check if the local plugin will be refreshed\n  run = startAppOnAndroidEmulator(s);\n  run.stop();\n\n  selftest.expectTrue(\n    s.read(\n      androidPluginSource + \"/com/cordova/empty/Empty.java\"\n    ).indexOf('change') > -1\n  );\n\n  // Now test the same scenario but with builds\n  s.cp(\n    pluginSource + '/src/android/Empty.java',\n    pluginPath + '/src/android/Empty.java'\n  );\n\n  run = s.run(\"build\", '../a', \"--server\", \"localhost:3000\");\n  run.waitSecs(60);\n  run.expectExit(0);\n\n  selftest.expectTrue(\n    s.read(\n      '../a/android/project/src/com/cordova/empty/Empty.java'\n    ).indexOf('change') === -1\n  );\n\n  checkCordovaPluginExists(s, \"com.cordova.empty\");\n\n  s.cp(\n    pluginSource + '/src/android/Empty_changed.java',\n    pluginPath + '/src/android/Empty.java'\n  );\n\n  run = s.run(\"build\", '../a', \"--server\", \"localhost:3000\");\n  run.waitSecs(60);\n  run.expectExit(0);\n\n  selftest.expectTrue(\n    s.read(\n      '../a/android/project/src/com/cordova/empty/Empty.java'\n    ).indexOf('change') > -1\n  );\n});\n\nselftest.define(\"meteor exits when cordova plugins change\", [\"slow\", \"cordova\"], function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"package-tests\");\n  s.cd(\"myapp\");\n\n  addPlatform(s, \"android\");\n\n  run = startAppOnAndroidEmulator(s);\n\n  // First add a plugin directly.\n  var pluginRun = s.run(\"add\", \"cordova:cordova-plugin-camera@1.0.0\");\n  pluginRun.expectExit(0);\n\n  run.waitSecs(60);\n  run.matchErr(\"Your app's Cordova plugins have changed\");\n  run.matchErr(\"Restart meteor\");\n  run.expectExit(254);\n\n  run = startAppOnAndroidEmulator(s);\n\n  // This shouldn't cause an exit because it contains the same plugin\n  // that we're already using.\n  pluginRun = s.run(\"add\", \"contains-old-cordova-plugin\");\n  pluginRun.expectExit(0);\n  run.waitSecs(60);\n  run.match(\"restarted\");\n\n  pluginRun = s.run(\"remove\", \"contains-old-cordova-plugin\");\n  pluginRun.expectExit(0);\n  run.waitSecs(60);\n  run.match(\"restarted\");\n\n  // This exits because it contains a new plugin, facebookconnect.\n  pluginRun = s.run(\"add\", \"contains-cordova-plugin\");\n  pluginRun.expectExit(0);\n  run.waitSecs(60);\n  run.matchErr(\"Your app's Cordova plugins have changed\");\n  run.matchErr(\"Restart meteor\");\n  run.expectExit(254);\n\n  run = startAppOnAndroidEmulator(s);\n\n  pluginRun = s.run(\"remove\", \"contains-cordova-plugin\");\n  pluginRun.expectExit(0);\n  run.waitSecs(60);\n  run.matchErr(\"Your app's Cordova plugins have changed\");\n  run.matchErr(\"Restart meteor\");\n  run.expectExit(254);\n\n  run = startAppOnAndroidEmulator(s);\n\n  pluginRun = s.run(\"remove\", \"cordova:cordova-plugin-camera\");\n  pluginRun.expectExit(0);\n  run.waitSecs(60);\n  run.matchErr(\"Your app's Cordova plugins have changed\");\n  run.matchErr(\"Restart meteor\");\n  run.expectExit(254);\n\n  // Adding and removing just a Meteor package that contains plugins\n  // should also cause the tool to exit.\n  run = startAppOnAndroidEmulator(s);\n\n  pluginRun = s.run(\"add\", \"contains-cordova-plugin\");\n  pluginRun.expectExit(0);\n  run.waitSecs(60);\n  run.matchErr(\"Your app's Cordova plugins have changed\");\n  run.matchErr(\"Restart meteor\");\n  run.expectExit(254);\n\n  run = startAppOnAndroidEmulator(s);\n\n  pluginRun = s.run(\"remove\", \"contains-cordova-plugin\");\n  pluginRun.expectExit(0);\n  run.waitSecs(60);\n  run.matchErr(\"Your app's Cordova plugins have changed\");\n  run.matchErr(\"Restart meteor\");\n  run.expectExit(254);\n\n  // Adding a package with a newer version of a plugin that we're\n  // already using should also cause us to restart.\n  pluginRun = s.run(\"add\", \"contains-old-cordova-plugin\");\n  pluginRun.expectExit(0);\n\n  run = startAppOnAndroidEmulator(s);\n\n  pluginRun = s.run(\"add\", \"contains-camera-cordova-plugin\");\n  pluginRun.expectExit(0);\n\n  run.matchErr(\"Your app's Cordova plugins have changed\");\n  run.matchErr(\"Restart meteor\");\n  run.expectExit(254);\n});\n\nvar buildAndCheckPluginInStar = selftest.markStack(function (s, name, version) {\n  var run = s.run(\n    \"build\", '../a', \"--server\", \"localhost:3000\", \"--directory\");\n  run.waitSecs(60);\n  run.expectExit(0);\n\n  var starJson = JSON.parse(s.read('../a/bundle/star.json'));\n  var program = _.findWhere(starJson.programs, { name: \"web.cordova\" });\n  if (! program) {\n    selftest.fail(\"No cordova program in star.json?\");\n    return;\n  }\n  var plugins = program.cordovaDependencies;\n  selftest.expectEqual(plugins[name], version);\n});\n\nselftest.define(\"cordova plugins in star.json, direct and transitive\", [\"slow\", \"cordova\"], function () {\n  var s = new Sandbox();\n  var run;\n\n  // Starting a run\n  s.createApp(\"myapp\", \"package-tests\");\n  s.cd(\"myapp\");\n  s.set(\"METEOR_OFFLINE_CATALOG\", \"t\");\n\n  run = addPlatform(s, 'android');\n\n  // Add a direct dependency: it should appear in star.json after we\n  // build.\n  run = s.run(\"add\", \"cordova:cordova-plugin-camera@1.0.0\");\n  run.expectExit(0);\n\n  buildAndCheckPluginInStar(s, \"cordova-plugin-camera\", \"1.0.0\");\n\n  // Add a Cordova dependency from a package, at a newer version: the\n  // plugin should appear in star.json at the version added in the\n  // direct dependency, even though it's older than the version that the\n  // package uses.\n  run = s.run(\"add\", \"contains-camera-cordova-plugin\");\n  run.expectExit(0);\n\n  buildAndCheckPluginInStar(s, \"cordova-plugin-camera\", \"1.0.0\");\n\n  // After removing the direct dependency, star.json should contain\n  // camera@1.2.0, the version used by the package.\n  run = s.run(\"remove\", \"cordova:cordova-plugin-camera\");\n  run.expectExit(0);\n\n  buildAndCheckPluginInStar(s, \"cordova-plugin-camera\", \"1.2.0\");\n\n  // If we add another package that uses an older version of the plugin,\n  // the version in star.json shouldn't change.\n  run = s.run(\"add\", \"contains-old-cordova-plugin\");\n  run.expectExit(0);\n\n  buildAndCheckPluginInStar(s, \"cordova-plugin-camera\", \"1.2.0\");\n\n  // If we remove the package that uses a newer version, the version in\n  // star.json should change.\n  run = s.run(\"remove\", \"contains-camera-cordova-plugin\");\n  run.expectExit(0);\n\n  buildAndCheckPluginInStar(s, \"cordova-plugin-camera\", \"1.0.0\");\n});\n"
  },
  {
    "path": "tools/tests/cordova-run.js",
    "content": "import selftest from '../tool-testing/selftest.js';\nimport utils from '../utils/utils.js';\nimport { parseServerOptionsForRunCommand, parseRunTargets } from '../cli/commands.js';\n\nselftest.define('get mobile server argument for meteor run', ['cordova'], function () {\n  // meteor run -p 3000\n  // => mobile server should be <detected ip>:3000\n  selftest.expectEqual(parseServerOptionsForRunCommand({\n    port: \"3000\"\n  }).parsedMobileServerUrl, { hostname: utils.ipAddress(), port: \"3000\", protocol: \"http\" });\n\n  // meteor run -p example.com:3000\n  // => mobile server should be <detected ip>:3000\n  selftest.expectEqual(parseServerOptionsForRunCommand({\n    port: \"example.com:3000\"\n  }).parsedMobileServerUrl, { hostname: utils.ipAddress(), port: \"3000\", protocol: \"http\" });\n\n  // meteor run -p example.com:3000 --mobile-server 4000 => error, mobile\n  // server must include a hostname\n  selftest.expectThrows(() => {\n    parseServerOptionsForRunCommand({\n      port: \"example.com:3000\",\n      \"mobile-server\": \"4000\"\n    });\n  });\n\n  // meteor run -p example.com:3000 --mobile-server example.com =>\n  // mobile server should be example.com\n  selftest.expectEqual(parseServerOptionsForRunCommand({\n    port: \"example.com:3000\",\n    \"mobile-server\": \"example.com\"\n  }).parsedMobileServerUrl, { protocol: \"http\", hostname: \"example.com\", port: undefined });\n\n  // meteor run -p example.com:3000 --mobile-server https://example.com =>\n  // mobile server should be https://example.com\n  selftest.expectEqual(parseServerOptionsForRunCommand({\n    port: \"example.com:3000\",\n    \"mobile-server\": \"https://example.com\"\n  }).parsedMobileServerUrl, { hostname: \"example.com\", protocol: \"https\", port: undefined });\n\n  // meteor run -p example.com:3000 --mobile-server http://example.com:4000 =>\n  // mobile server should be http://example.com:4000\n  selftest.expectEqual(parseServerOptionsForRunCommand({\n    port: \"example.com:3000\",\n    \"mobile-server\": \"http://example.com:4000\"\n  }).parsedMobileServerUrl, { hostname: \"example.com\", port: \"4000\", protocol: \"http\" });\n});\n"
  },
  {
    "path": "tools/tests/create.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\n\nselftest.define(\"create\", function () {\n  var s = new Sandbox;\n\n  // Can we create an app? Yes!\n  var run = s.run(\"create\", \"foobar\");\n  run.waitSecs(60);\n  run.match(\"Created a new Meteor app in 'foobar'.\");\n  run.match(\"To run your new app\");\n  run.expectExit(0);\n\n  // Now, can we run it?\n  s.cd(\"foobar\");\n  run = s.run();\n  run.waitSecs(15);\n  run.match(\"foobar\");\n  run.match(\"proxy.\");\n  // Do not print out the changes to the versions file!\n  run.read(\"\\n=>\");\n  run.match(\"MongoDB\");\n  run.waitSecs(5);\n  run.match(\"your app\");\n  run.waitSecs(5);\n  run.match(\"running at\");\n  run.match(\"localhost\");\n  run.stop();\n\n  run = s.run(\"create\", \"--list\");\n  run.waitSecs(5);\n  run.read('Available');\n  run.match('leaderboard');\n  run.expectExit(0);\n  // XXX test that --list always gives you the examples of the current\n  // release!\n\n  // XXX XXX more more\n});\n"
  },
  {
    "path": "tools/tests/custom-minifier.js",
    "content": "import selftest, {Sandbox} from '../tool-testing/selftest.js';\n\nselftest.define('custom minifier - devel vs prod', function (options) {\n  const s = new Sandbox({\n    clients: options.clients\n  });\n\n  s.createApp('myapp', 'custom-minifier');\n  s.cd('myapp');\n\n  s.testWithAllClients(function (run) {\n    run.waitSecs(5);\n    run.match('myapp');\n    run.match('proxy');\n    run.match('MongoDB');\n\n    run.connectClient();\n    run.waitSecs(20);\n\n    // XXX when minifiers start getting applied to server target, this\n    // outcome would change\n    run.match('Message: foo');\n\n    run.match('production_css: rgb(255, 0, 0)');\n    run.match('development_css: rgb(0, 0, 0)');\n    run.match('Message (client): production_js');\n\n    run.stop();\n  }, '--production');\n\n  s.testWithAllClients(function (run) {\n    run.waitSecs(5);\n    run.match('myapp');\n    run.match('proxy');\n    run.match('MongoDB');\n\n    run.connectClient();\n    run.waitSecs(20);\n\n    // XXX when minifiers start getting applied to server target, this\n    // outcome would change\n    run.match('Message: foo');\n\n    run.match('production_css: rgb(0, 0, 0)');\n    run.match('development_css: rgb(255, 0, 0)');\n    run.match('Message (client): development_js');\n\n    run.stop();\n  }/*, development*/);\n});\n"
  },
  {
    "path": "tools/tests/ddp-heartbeat.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\n\nvar MONGO_LISTENING =\n  { stdout: \" [initandlisten] waiting for connections on port\" };\n\nselftest.define(\"ddp-heartbeat\", [\"slow\"], function () {\n  var s = new Sandbox({ fakeMongo: true });\n  var run;\n\n  s.createApp(\"ddpapp\", \"ddp-heartbeat\");\n  s.cd(\"ddpapp\");\n\n  var run = s.run(\"--once\", \"--raw-logs\");\n  run.tellMongo(MONGO_LISTENING);\n  run.waitSecs(120);\n  run.expectExit(0);\n});\n"
  },
  {
    "path": "tools/tests/dev-bundle-bin-commands.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\n\nselftest.define(\"meteor npm run some-script-name - error returns exit status to shell\", function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"dev-bundle-bin-commands\");\n  s.cd(\"myapp\");\n  run = s.run(\"npm\", \"run\", \"exit-with-status\");\n  run.matchErr(\"This script has an exit status\");\n  run.expectExit(1);\n});\n\nselftest.define(\"meteor npm some-script-name - normal exit returns normal to shell\", function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"dev-bundle-bin-commands\");\n  s.cd(\"myapp\");\n  run = s.run(\"npm\", \"run\", \"exit-normally\");\n  run.match(\"This script will exit normally\");\n  run.expectExit(0);\n});"
  },
  {
    "path": "tools/tests/fake-mongod/fake-mongod",
    "content": "#!/usr/bin/env bash\n\n# Get the path to this script in SCRIPT_DIR, preserving cwd\nORIG_DIR=$(pwd)\ncd \"$(dirname \"$0\")\"\nSCRIPT_DIR=$(pwd -P)\ncd \"$ORIG_DIR\"\n\n# Find the top of the tools tree (not to be confused with the 'tools'\n# directory in that tree)\nTOOLS_DIR=\"$SCRIPT_DIR/../../..\"\n\n# Find our binary dependencies (node).\nDEV_BUNDLE=\"$TOOLS_DIR/dev_bundle\"\n\n# Have at it!\nexport NODE_PATH=\"$DEV_BUNDLE/lib/node_modules\"\nexec \"$DEV_BUNDLE/bin/node\" \"$SCRIPT_DIR/fake-mongod.js\" \"$@\"\n"
  },
  {
    "path": "tools/tests/fake-mongod/fake-mongod.bat",
    "content": "REM Find the top of the tools tree (not to be confused with the 'tools'\nREM directory in that tree)\nSETLOCAL\nSET TOOLS_DIR=\"%~dp0\\..\\..\\..\"\n\nREM Find our binary dependencies (node).\nSET DEV_BUNDLE=\"%TOOLS_DIR%\\dev_bundle\"\n\nREM Have at it!\nSET NODE_PATH=\"%DEV_BUNDLE%\\lib\\node_modules\"\n\n\"%DEV_BUNDLE%\\bin\\node\" \"%~dp0\\fake-mongod.js\" %*\nexit /b %errorlevel%\nENDLOCAL\n"
  },
  {
    "path": "tools/tests/fake-mongod/fake-mongod.js",
    "content": "var net = require('net');\n\n// In the process table, make the process name look like 'fake-mongod'\n// rather than 'node fake-mongod.js', so that when the tool greps the\n// process table for mongod it will find us.\n\nprocess.title = [\"fake-mongod\"].concat(process.argv.slice(2)).join(' ');\n\n// We listen on METEOR_TEST_FAKE_MONGOD_CONTROL_PORT for\n// commands. Commands can tell us to print a string to stdout or\n// stderr, or to exit.\nvar port = parseInt(process.env.METEOR_TEST_FAKE_MONGOD_CONTROL_PORT);\nif (! port)\n  throw new Error(\"must set METEOR_TEST_FAKE_MONGOD_CONTROL_PORT\");\n\nvar server = net.createServer(function (c) {\n  c.setEncoding('utf8');\n\n  var buf = \"\";\n  c.on('data', function (data) {\n    buf += data;\n\n    while (true) {\n      var i = buf.indexOf(\"\\n\");\n      if (i === -1)\n        break;\n      var command = JSON.parse(buf.substr(0, i));\n      buf = buf.substr(i + 1);\n      if (command.stdout)\n        process.stdout.write(command.stdout);\n      if (command.stderr)\n        process.stderr.write(command.stderr);\n      if (command.exit) {\n        process.exit(parseInt(command.exit));\n      }\n    }\n  });\n});\n\nserver.listen(port, function () {\n  // (called when we're successfully listening)\n});\n"
  },
  {
    "path": "tools/tests/galaxy.js",
    "content": "var _ = require('underscore');\nvar selftest = require('../tool-testing/selftest.js');\nvar testUtils = require('../tool-testing/test-utils.js');\nvar galaxyUtils = require('../tool-testing/galaxy-utils.js');\nvar Sandbox = selftest.Sandbox;\n\n// XXX: There is currently no cleanup function in self-test, but it would be\n// nice to have.\n\n// Check if a given app is running. Curl that appname and see that it returns\n// some text.\n//\n//  - appUrl: the URL at which the app is (theoretically) running. For example\n//    \"xxx.galaxy.meteor.com\"\n//  - checks: what to check for. Following options:\n//    - text: text in the HTTP response of the app\n//    - containerCount: number of containers GalaxyAPI thinks is running\nvar checkAppIsRunning = selftest.markStack(function (appUrl, checks) {\n  var containerCount = checks.containerCount || 1;\n  var text = checks.text;\n\n  // Check that GalaxyAPI thinks that we are running the correct containers.\n  var appRecord = galaxyUtils.getAppRecordByName(appUrl);\n  selftest.expectEqual(appRecord.containerCount, containerCount);\n\n  // Ignore HTTP checks, and that's what this is.\n  if (! galaxyUtils.ignoreHttpChecks()) {\n    // Test that the app is actually running on Galaxy.\n    var run = galaxyUtils.curlToGalaxy(appUrl);\n    run.waitSecs(5);\n    run.matchErr(galaxyUtils.httpOK);\n    run.match(text);\n    run.expectExit(0);\n  }\n});\n\n// Deploy a simple app to Galaxy.\nselftest.define('galaxy deploy - simple', ['galaxy'], function () {\n  galaxyUtils.sanityCheck();\n  var s = new Sandbox;\n\n  // Login with a valid Galaxy account\n  galaxyUtils.loginToGalaxy(s);\n\n  // Deploy an app.\n   var appName = galaxyUtils.createAndDeployApp(s);\n\n  // Test that the app is actually running on Galaxy.\n  checkAppIsRunning(appName, { text: \"Hello\" });\n\n  // Edit the app. Use words that are unlikely to show up in (for example)\n  // boilerplate 404 text.\n  var newText =\n    \"<head> second </head>\" + \"\\n\" +\n    \"<body> deploying rocks! </body>\";\n  s.write(\"simple.html\", newText);\n\n  // Let's use normal deploy here.\n  var run = s.run(\"deploy\", appName);\n  run.waitSecs(15);\n  run.expectExit(0);\n  galaxyUtils.waitForContainers();\n  checkAppIsRunning(appName, { text: \"second\" });\n\n  // Delete our deployed app.\n  galaxyUtils.cleanUpApp(s, appName);\n\n  // Test that the app is no longer running.\n  // Check that GalaxyAPI thinks that we are running the correct containers.\n  if (! galaxyUtils.ignoreHttpChecks()) {\n    run = galaxyUtils.curlToGalaxy(appName);\n    run.waitSecs(5);\n    run.matchErr(\"404\");\n    run.expectExit(0);\n  }\n\n  testUtils.logout(s);\n});\n\n// Deploy an app with some public settings to galaxy, check that everything works.\nselftest.define('galaxy deploy - settings', ['galaxy'], function () {\n  galaxyUtils.sanityCheck();\n  var s = new Sandbox;\n\n  // Login with a valid Galaxy account\n  galaxyUtils.loginToGalaxy(s);\n\n  // Create sample settings.\n  var settings = {\n    'public': { a: 'b' }\n  };\n\n  // Deploy an app with settings and check that the public settings\n  // appear in the HTTP response body.\n  var appName = galaxyUtils.createAndDeployApp(s, {\n    settings: settings\n  });\n\n  // Test that the app is actually running on Galaxy.\n  checkAppIsRunning(appName, { text: \"Hello\" });\n\n  // Test that the public settins appear in the HTTP response body.\n  if (! galaxyUtils.ignoreHttpChecks()) {\n    testUtils.checkForSettings(appName, settings, 10);\n  }\n\n  // Re-deploy without settings and check that the settings still\n  // appear.\n  s.cd('..');\n  galaxyUtils.createAndDeployApp(s, {\n    templateApp: 'standard-app',\n    appName: appName,\n    useOldSettings: true\n  });\n  if (! galaxyUtils.ignoreHttpChecks()) {\n    testUtils.checkForSettings(appName, settings, 10);\n  }\n\n  // Re-deploy with new settings and check that the settings get\n  // updated.\n  settings['public'].a = 'c';\n  s.cd('..');\n  galaxyUtils.createAndDeployApp(s, {\n    templateApp: 'simple-app',\n    appName: appName,\n    settings: settings\n  });\n  checkAppIsRunning(appName, { text: \"Hello\" });\n\n  galaxyUtils.cleanUpApp(s, appName);\n  testUtils.logout(s);\n});\n\n\n// Rescale the app and check status.\nselftest.define('galaxy deploy - rescale', ['galaxy'], function () {\n  galaxyUtils.sanityCheck();\n  var s = new Sandbox;\n\n  // Login with a valid Galaxy account\n  galaxyUtils.loginToGalaxy(s);\n\n  // Deploy an app.\n  var appName = galaxyUtils.createAndDeployApp(s);\n  checkAppIsRunning(appName, { text: \"Hello\" });\n\n  // Call into the Galaxy API DDP methods to rescale containers. The method\n  // signature is:\n  //    setContainerCount: function(appId, containerCount)\n  var conn = galaxyUtils.loggedInGalaxyAPIConnection();\n  var appRecord = galaxyUtils.getAppRecordByName(appName);\n  galaxyUtils.callGalaxyAPI(conn, \"setContainerCount\", appRecord._id, 5);\n  galaxyUtils.waitForContainers();\n  checkAppIsRunning(appName, { text: \"Hello\", containerCount : 5 });\n\n  // More throughly: check that as far as we know, containers are actually\n  // running (or the scheduler is lying to GalaxyAPI and claiming that they are\n  // running). This API is even more internal, but it is unlikely to change for\n  // now.\n  // XXX: This subscription is not yet worth checking on staging, when it is, uncomment.\n  /// var containers = galaxyUtils.getAppContainerStatuses(appRecord._id, appName);\n  // selftest.equals(containers.length, 5);\n\n  // Now, scale down the app.\n  galaxyUtils.callGalaxyAPI(conn, \"setContainerCount\", appRecord._id, 1);\n  galaxyUtils.waitForContainers();\n  checkAppIsRunning(appName, { text: \"Hello\", containerCount : 1 });\n\n  // Delete the app.\n  galaxyUtils.cleanUpApp(s, appName);\n\n  // Check that no containers are running.\n  conn = galaxyUtils.renewConnection(conn);\n  // XXX: This subscription is not yet worth checking on staging, when it is, uncomment.\n  // containers = galaxyUtils.getAppContainerStatuses(appRecord._id, appName);\n  // selftest.expectEqual(0, containers.length);\n\n  // Logout.\n  galaxyUtils.closeGalaxyConnection(conn);\n  testUtils.logout(s);\n});\n\n// Upload an app, allocate it a self-signed cert, check that we get https\n// redirection.\nselftest.define('galaxy self-signed cert', ['galaxy'], function () {\n  galaxyUtils.sanityCheck();\n  var s = new Sandbox;\n\n  // Login with a valid Galaxy account\n  galaxyUtils.loginToGalaxy(s);\n\n  // Deploy an app. Check that it is running.\n  var appName = galaxyUtils.createAndDeployApp(s);\n  checkAppIsRunning(appName, { text: \"Hello\" });\n\n  // Force SSL.\n  var run = s.run(\"add\", \"force-ssl\");\n  run.waitSecs(5);\n  run.expectExit(0);\n  run = s.run(\"deploy\", appName);\n  run.waitSecs(30);\n  run.expectExit(0);\n  galaxyUtils.waitForContainers();\n\n  // Create a signed certificate for the app.\n  //  createSelfSignedCertificateForApp: function (appId, options) {\n  var appRecord = galaxyUtils.getAppRecordByName(appName);\n  var conn = galaxyUtils.loggedInGalaxyAPIConnection();\n  var certIds = _.map(_.range(0, 15), function () {\n    return galaxyUtils.callGalaxyAPI(\n      conn, \"createSelfSignedCertificateForApp\", appRecord._id);\n  });\n\n  // Activate a certificate in the middle -- not the first or the last.\n  galaxyUtils.callGalaxyAPI(\n    conn, \"activateCertificateForApp\", certIds[3], appRecord._id);\n  // Check that we are getting a re-direct.\n  galaxyUtils.waitForContainers();\n  appRecord = galaxyUtils.getAppRecordByName(appName);\n  selftest.expectEqual(appRecord.containerCount, 1);\n  var activeCert = appRecord[\"activeCertificateId\"];\n  selftest.expectEqual(activeCert, certIds[3]);\n  if (! galaxyUtils.ignoreHttpChecks()) {\n    run = galaxyUtils.curlToGalaxy(appName);\n    run.waitSecs(5);\n    run.matchErr(\"SSL\");\n    run.expectExit(60);\n  }\n\n  // Remove the un-activated certificates\n  _.each(_.range(0, 15), function (i) {\n    if (i !== 3) {\n      galaxyUtils.callGalaxyAPI(\n        conn, \"removeCertificateFromApp\", certIds[i], appRecord._id);\n    }\n  });\n  // Check that we are still getting a re-direct and GalaxyAPI thinks that we\n  // are using the same cert.\n  appRecord = galaxyUtils.getAppRecordByName(appName);\n  selftest.expectEqual(appRecord[\"activeCertificateId\"], activeCert);\n  if (! galaxyUtils.ignoreHttpChecks()) {\n    run = galaxyUtils.curlToGalaxy(appName);\n    run.waitSecs(5);\n    run.matchErr(\"SSL\");\n    run.expectExit(60);\n  }\n\n  // Clean up.\n  galaxyUtils.cleanUpApp(s, appName);\n  testUtils.logout(s);\n  galaxyUtils.closeGalaxyConnection(conn);\n});\n\n// Unauthorized users cannot deploy to Galaxy.\nselftest.define('unauthorized deploy', ['galaxy'], function () {\n  var sandbox = new Sandbox;\n  // This is the test user. The test user is not currently authorized to deploy\n  // to Galaxy. Sorry, test user! :( Hopefully, someday.\n  testUtils.login(sandbox, 'test', 'testtest');\n\n  var appName = testUtils.randomAppName();\n  sandbox.createApp(appName, 'empty');\n  sandbox.cd(appName);\n  var run = sandbox.run(\"deploy\", appName);\n  run.waitSecs(90);\n  run.matchErr(\"Error deploying\");\n  run.matchErr(\"is not authorized\");\n  run.expectExit(1);\n});\n"
  },
  {
    "path": "tools/tests/help.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\n\nselftest.define(\"help\", function () {\n  var s = new Sandbox;\n\n  // Top-level help\n  var checkTopLevelHelp = function (run) {\n    run.read(\"Usage: meteor\");\n    run.match(\"Commands:\");\n    run.match(/create\\s*Create a new project/);\n    run.match(/\\s*admin\\s/);\n    run.expectExit(0);\n    run.forbidAll(/^\\s*maintainers\\s/); // no subcommands\n    run.forbidAll(/^\\s*dummy\\s/); // no hidden commands\n  };\n\n  checkTopLevelHelp(s.run(\"help\"));\n  checkTopLevelHelp(s.run(\"--help\"));\n\n  // Command help\n  var checkCommandHelp = function (run) {\n    run.read(\"Usage: meteor create\");\n    run.match(\"create a new Meteor app\");\n    run.match(\"Options:\");\n    run.match(/--list\\s*Show list/);\n    run.expectExit(0);\n  };\n\n  checkCommandHelp(s.run(\"help\", \"create\"));\n  checkCommandHelp(s.run(\"create\", \"--help\"));\n  checkCommandHelp(s.run(\"--help\", \"create\"));\n\n  // List of subcommands\n  var checkSubcommandList = function (run) {\n    run.read(\"Usage: meteor admin <command>\");\n    run.match(\"Commands:\");\n    run.match(/recommend-release\\s*Recommend a previously published/);\n    run.expectExit(0);\n  };\n  checkSubcommandList(s.run(\"help\", \"admin\"));\n  checkSubcommandList(s.run(\"admin\", \"help\"));\n  checkSubcommandList(s.run(\"admin\", \"--help\"));\n  checkSubcommandList(s.run(\"--help\", \"admin\"));\n\n  // Subcommand help\n  var checkSubcommandHelp = function (run) {\n    run.match(\"Usage: meteor admin make-bootstrap-tarballs\");\n    run.match(\"For internal use only.\");\n    run.expectExit(0);\n  };\n\n  var comm = \"make-bootstrap-tarballs\";\n  checkSubcommandHelp(s.run(\"help\", \"admin\", comm));\n  checkSubcommandHelp(s.run(\"admin\", \"help\", comm));\n  checkSubcommandHelp(s.run(\"admin\", comm, \"--help\"));\n  checkSubcommandHelp(s.run(\"--help\", \"admin\", comm));\n});\n"
  },
  {
    "path": "tools/tests/hot-code-push.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar utils = require('../utils/utils.js');\n\nselftest.define(\"css hot code push\", function (options) {\n  var s = new Sandbox({\n    clients: options.clients\n  });\n\n  s.createApp(\"myapp\", \"css-injection-test\");\n  s.cd(\"myapp\");\n  s.testWithAllClients(function (run) {\n    run.match(\"myapp\");\n    run.match(\"proxy\");\n    run.match(\"MongoDB\");\n    run.match(\"running at\");\n    run.match(\"localhost\");\n\n    run.connectClient();\n\n    run.waitSecs(20);\n    run.match(\"client connected\");\n\n    // 'numCssChanges' variable is set to 0 on a client refresh.\n    // Since CSS changes should not trigger a client refresh, numCssChanges\n    // should never reset.\n\n    // The css file is initially empty.\n    run.match(\"numCssChanges: 0\");\n\n    // Some browsers represent no background as 'transparent', others use\n    // rgba(0, 0, 0, 0).\n    run.match(/background-color: (transparent|rgba\\(0, 0, 0, 0\\))/);\n\n    // The server does NOT restart if a new css file is added.\n    s.write(\"test.css\", \"body { background-color: red; }\");\n    run.waitSecs(30);\n    run.match(\"Client modified -- refreshing\");\n    run.match(\"numCssChanges: 1\");\n    run.match(/background-color: (red|rgb\\(255, 0, 0\\))/);\n\n    s.write(\"test.css\", \"body { background-color: blue; }\");\n    run.match(\"Client modified -- refreshing\");\n    run.match(\"numCssChanges: 2\");\n    run.match(/background-color: (blue|rgb\\(0, 0, 255\\))/);\n\n    // The server does NOT restart if a css file is removed.\n    s.unlink(\"test.css\");\n    run.match(\"Client modified -- refreshing\");\n    run.match(\"numCssChanges: 3\");\n    run.match(/background-color: (transparent|rgba\\(0, 0, 0, 0\\))/);\n\n    s.write(\".meteor/packages\", `meteor-base\njquery\nmy-package`);\n    run.match(/my-package.*added,/);\n    run.match(\"client connected\");\n    run.match(\"numCssChanges: 0\");\n\n    s.write(\"packages/my-package/foo.css\", \"body { background-color: blue; }\");\n    run.match(\"numCssChanges: 1\");\n    run.match(/background-color: (blue|rgb\\(0, 0, 255\\))/);\n\n    // Add appcache and ensure that the browser still reloads.\n    s.write(\".meteor/packages\", `meteor-base\njquery\nmy-package\nappcache`);\n    run.match(/appcache.*added,/);\n    run.match(\"server restarted\");\n    run.match(\"numCssChanges: 0\");\n    run.match(/background-color: (blue|rgb\\(0, 0, 255\\))/);\n\n    s.write(\"packages/my-package/foo.css\", \"body { background-color: red; }\");\n    run.match(\"Client modified -- refreshing\");\n    run.match(\"numCssChanges: 1\");\n    run.match(/background-color: (red|rgb\\(255, 0, 0\\))/);\n\n    // XXX: Remove me.  This shouldn't be needed, but sometimes\n    // if we run too quickly on fast (or Linux?) machines, it looks\n    // like there's a race and we see a weird state\n    utils.sleepMs(10000);\n\n    s.write(\".meteor/packages\", `meteor-base\njquery`);\n    run.match(/my-package.*removed from your project/);\n    run.match(\"numCssChanges: 0\");\n    run.match(/background-color: (transparent|rgba\\(0, 0, 0, 0\\))/);\n\n    run.stop();\n  });\n});\n\nselftest.define(\"versioning hot code push\", function (options) {\n  var s = new Sandbox();\n\n  s.set(\"AUTOUPDATE_VERSION\", \"1.0\");\n  s.createApp(\"myapp\", \"hot-code-push-test\");\n  s.cd(\"myapp\");\n\n  s.testWithAllClients(function (run) {\n    run.baseTimeout = 20;\n    run.match(\"myapp\");\n    run.match(\"proxy\");\n    run.match(\"MongoDB\");\n    run.match(\"running at\");\n    run.match(\"localhost\");\n    run.connectClient();\n    run.waitSecs(20);\n\n    run.match(\"client connected: 0\");\n\n    run.forbidAll(\"Error listening\");\n\n    run.stop();\n  });\n});\n\nselftest.define(\"javascript hot code push\", function (options) {\n  var s = new Sandbox({\n    clients: options.clients\n  });\n\n  s.createApp(\"myapp\", \"hot-code-push-test\");\n  s.cd(\"myapp\");\n  s.testWithAllClients(function (run) {\n    run.match(\"myapp\");\n    run.match(\"proxy\");\n    run.match(\"MongoDB\");\n    run.match(\"running at\");\n    run.match(\"localhost\");\n\n    run.connectClient();\n    run.waitSecs(40);\n\n    // There is initially no JavaScript file.\n    run.match(\"client connected: 0\");\n    run.match(\"jsVar: undefined\");\n    run.match(\"sessionVar: null\");\n\n    // The server and client both restart if a shared js file is added\n    // or removed.\n    s.write(\"test.js\", \"jsVar = 'foo'\");\n    run.match(\"server restarted\");\n    run.match(\"client connected: 0\");\n    run.match(\"jsVar: foo\");\n    run.match(\"sessionVar: true\");\n\n    s.unlink(\"test.js\");\n    run.match(\"server restarted\");\n    run.match(\"client connected: 0\");\n    run.match(\"jsVar: undefined\");\n\n\n    // Only the client should refresh if a client js file is added. Thus,\n    // \"client connected\" variable will be incremented.\n    s.mkdir(\"client\");\n\n    s.write(\"client/test.js\", \"jsVar = 'bar'\");\n    run.match(\"client connected: 1\");\n    run.match(\"jsVar: bar\");\n\n    s.unlink(\"client/test.js\");\n    run.match(\"client connected: 2\");\n    run.match(\"jsVar: undefined\");\n\n    // When we change a server file the client should not refresh. We observe\n    // this by changing a server file and then a client file and verifying\n    // that the client has only connected once.\n    s.mkdir(\"server\");\n    s.write(\"server/test.js\", \"jsVar = 'bar'\");\n    run.match(\"server restarted\");\n\n    s.write(\"client/empty.js\", \"\");\n    run.match(\"client connected: 0\");\n    // We should not be able to access a server variable from the client.\n    run.match(\"jsVar: undefined\");\n\n    s.unlink(\"client/empty.js\");\n    run.waitSecs(5);\n    run.match(\"client connected: 1\");\n    run.match(\"jsVar: undefined\");\n\n    // Break the HTML file. This should kill the server, and print errors.\n    // (It would be reasonable behavior for this to NOT kill the server, since\n    // it only affects the client. But this is a regression test for a bug where\n    // fixing the HTML file wouldn't actually restart the server; that's the\n    // important part of this test.)\n    s.write(\"hot-code-push-test.html\", \">\");\n    run.match(\"Errors prevented startup\");\n    run.match(\"Expected one of: <body>, <head>, <template>\");\n    // Fix it. It should notice, and restart. The client will restart too.\n    s.write(\"hot-code-push-test.html\", \"\");\n    run.match(\"server restarted\");\n    run.match(\"client connected: 0\");\n    // Write something else to it. The client should restart.\n    s.write(\"hot-code-push-test.html\", \"<head><title>foo</title></head>\");\n    run.match(\"Client modified -- refreshing\");\n    run.match(\"client connected: 1\");\n    run.match(\"jsVar: undefined\");\n\n    s.write(\".meteor/packages\", `meteor-base\nsession\nmy-package`);\n    run.match(/my-package.*added,/);\n    run.match(\"server restarted\");\n    run.match(\"client connected: 0\");\n    run.match(\"jsVar: undefined\");\n    run.match(\"packageVar: foo\");\n\n    s.write(\"packages/my-package/foo.js\", \"packageVar = 'bar'\");\n    run.match(\"client connected: 0\");\n    run.match(\"jsVar: undefined\");\n    run.match(\"packageVar: bar\");\n\n    // Add appcache and ensure that the browser still reloads.\n    s.write(\".meteor/packages\", `meteor-base\nsession\nappcache`);\n    run.match(/appcache.*added,/);\n    run.match(\"server restarted\");\n    run.match(\"client connected: 0\");\n    run.match(\"jsVar: undefined\");\n\n    s.write(\"client/test.js\", \"jsVar = 'bar'\");\n    run.match(\"client connected: 1\");\n    run.match(\"jsVar: bar\");\n\n    // Remove appcache and ensure that the browser still reloads.\n    s.write(\".meteor/packages\", `meteor-base\nsession`);\n    run.match(/appcache.*removed from your project/);\n    run.match(\"server restarted\");\n    run.match(\"client connected: 0\");\n\n    s.write(\"client/test.js\", \"jsVar = 'baz'\");\n    run.match(\"client connected: 1\");\n    run.match(\"jsVar: baz\");\n\n    s.unlink(\"client/test.js\");\n\n    // Setting the autoupdateVersion to a different string should also\n    // force the client to restart.\n    s.write(\"server/test.js\",\n            \"Package.autoupdate.Autoupdate.autoupdateVersion = 'random'\");\n    run.match(\"server restarted\");\n    run.match(\"client connected: 0\");\n    run.match(\"jsVar: undefined\");\n\n    s.unlink(\"server/test.js\");\n    run.match(\"server restarted\");\n\n    run.stop();\n  });\n});\n"
  },
  {
    "path": "tools/tests/js-analyze.js",
    "content": "import selftest from '../tool-testing/selftest.js';\nimport { findAssignedGlobals } from '../isobuild/js-analyze.js';\n\nselftest.define('findAssignedGlobals', () => {\n  function run(source, expected) {\n    selftest.expectEqual(findAssignedGlobals(source), expected);\n  };\n\n  run('x', {});\n  run('x + y', {});\n  run('x = y', {x: true});\n  run('var x; x = y', {});\n  run('var y; x = y', {x: true});\n  run('var x,y; x = y', {});\n  run('for (x in y);', {x: true});\n  run('for (var x in y);', {});\n  // Update operators cause ReferenceError if the left-hand is not defined.\n  run('x++', {});\n  run('x += 5', {x: true});\n  run('var x = y', {});\n  run('a.b[c.d]', {});\n  run('foo.bar[baz][c.d].z = 3', {});\n  run('foo.bar(baz)[c.d].z = 3', {});\n  run('var x = y.z; x.a = y; z.b;', {});\n  run('Foo.Bar', {});\n  run('Foo.Bar = 3', {});\n  run(\n    '(function (a, d) { var b = a, c; return f(a.z, b.z, c.z, d.z, e.z); })()',\n    {});\n  // catch clause declares a name\n  run('try { Foo } catch (e) { e = 5 }', {});\n  run('try { Foo } catch (e) { Foo }', {});\n  run('try { Foo } catch (Foo) { Foo }', {});\n  run('try { e } catch (Foo) { Foo }', {});\n  run('var x = function y () { return String(y); }', {});\n  run('a[b=c] = d', {b: true});\n  run('a.a.a[b.b.b=c.c.c] = d.d.d', {});\n  // esprima ignores parentheses\n  run('((((x)))) = 5', {x: true});\n  // esprima ignores comments\n  run('x /* foo */ = 5', {x: true});\n\n  // Without ignoreEval, this thinks J is global.\n  run('function x(){var J;J=3;eval(\"foo\");}', {});\n\n  let threw = true;\n  try {\n    findAssignedGlobals(\"x = \");\n    threw = false;\n  } catch (e) {\n    selftest.expectTrue(e.$ParseError);\n  }\n  selftest.expectTrue(threw);\n});\n"
  },
  {
    "path": "tools/tests/linter-plugins.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar files = require('../fs/files.js');\n\nvar Sandbox = selftest.Sandbox;\n\nvar MONGO_LISTENING =\n  { stdout: \" [initandlisten] waiting for connections on port\" };\n\nfunction startRun(sandbox, ...args) {\n  var run = sandbox.run(...args);\n  run.match('myapp');\n  run.match('proxy');\n  run.tellMongo(MONGO_LISTENING);\n  run.match(\"MongoDB\");\n  return run;\n};\n\nfunction matchLintingMessages(run, messages, initial) {\n  run.match('Linted your app.');\n  messages.forEach(message => run.match(message));\n  if (initial) {\n    run.match('Started your app.');\n    run.match('App running at');\n  } else {\n    run.match('Meteor server restarted');\n  }\n}\n\nselftest.define('linter plugins - linting app with local packages', () => {\n  const s = new Sandbox({ fakeMongo: true });\n\n  // Create an app that uses coffeescript and less.\n  s.createApp('myapp', 'linting-app');\n  s.cd('myapp');\n\n  const run = startRun(s);\n\n  matchLintingMessages(run, [\n    /While linting files .* app .*Server/,\n    /server\\.js:1:1: 'GlobalVar'/,\n    /While linting files .* app .*Client/,\n    /client\\.js:1:1: 'GlobalVar'/,\n    /While linting files .* my-package .*Server/,\n    /package-server\\.js:1:1: 'PackageGlobalVar'/,\n    /package-server\\.js:2:1: 'PermittedGlobal'/,\n    /While linting files .* my-package .*Client/,\n    /package-client\\.js:1:1: 'PackageGlobalVar'/\n  ], true);\n\n  s.write('.jshintrc', JSON.stringify({\n    undef: false\n  }));\n\n  matchLintingMessages(run, [\n    /While linting files .* my-package .*Server/,\n    /package-server\\.js:1:1: 'PackageGlobalVar'/,\n    /package-server\\.js:2:1: 'PermittedGlobal'/,\n    /While linting files .* my-package .*Client/,\n    /package-client\\.js:1:1: 'PackageGlobalVar'/\n  ]);\n\n  s.write('packages/my-package/.jshintrc', JSON.stringify({\n    undef: true,\n    predef: ['PermittedGlobal']\n  }));\n\n  // no warnings should be printed\n  matchLintingMessages(run, [\n    /While linting files .* my-package .*Server/,\n    /package-server\\.js:1:1: 'PackageGlobalVar'/,\n    /While linting files .* my-package .*Client/,\n    /package-client\\.js:1:1: 'PackageGlobalVar'/\n  ]);\n\n  run.stop();\n});\n\n\nselftest.define('linter plugins - linting app with local packages with `meteor lint`', () => {\n  const s = new Sandbox({ fakeMongo: true });\n\n  // Create an app that uses coffeescript and less.\n  s.createApp('myapp', 'linting-app');\n  s.cd('myapp');\n\n  const run = s.run('lint');\n\n  const messages = [\n    /While linting files .* app .*Server/,\n    /server\\.js:1:1: 'GlobalVar'/,\n    /While linting files .* app .*Client/,\n    /client\\.js:1:1: 'GlobalVar'/,\n    /While linting files .* my-package .*Server/,\n    /package-server\\.js:1:1: 'PackageGlobalVar'/,\n    /package-server\\.js:2:1: 'PermittedGlobal'/,\n    /While linting files .* my-package .*Client/,\n    /package-client\\.js:1:1: 'PackageGlobalVar'/\n  ];\n\n  messages.forEach(message => run.matchErr(message));\n  run.expectExit(1);\n});\n\nselftest.define('linter plugins - linting package with `meteor lint`', () => {\n  const s = new Sandbox({ fakeMongo: true });\n\n  // Create an app that uses coffeescript and less.\n  s.createApp('myapp', 'linting-app');\n  s.cd('myapp/packages/my-package');\n\n  const run = s.run('lint');\n\n  const messages = [\n    /While linting files .* my-package .*Server/,\n    /package-server\\.js:1:1: 'PackageGlobalVar'/,\n    /package-server\\.js:2:1: 'PermittedGlobal'/,\n    /While linting files .* my-package .*Client/,\n    /package-client\\.js:1:1: 'PackageGlobalVar'/,\n    /While linting files .* my-package .*Cordova/,\n    /package-client\\.js:1:1: 'PackageGlobalVar'/\n  ];\n\n  messages.forEach(message => run.matchErr(message));\n\n  run.forbid('app');\n\n  run.expectExit(1);\n});\n\nselftest.define('linter plugins - running with --no-lint', () => {\n  const s = new Sandbox({ fakeMongo: true });\n\n  // Create an app that uses coffeescript and less.\n  s.createApp('myapp', 'linting-app');\n  s.cd('myapp');\n\n  const run = startRun(s, '--no-lint');\n\n  run.forbid('Linting');\n  run.forbid('linting');\n  run.forbid('is not defined');\n\n  run.match('Started your app');\n\n  run.stop();\n});\n\nselftest.define('linter plugins - lint package on `meteor publish`', () => {\n  const s = new Sandbox({ fakeMongo: true });\n\n  // create an app that contains a package we want to publish\n  s.createApp('myapp', 'lint-on-publish');\n  s.cd('myapp/packages/my-package');\n  s.set('METEOR_TEST_NO_PUBLISH', 't');\n\n  {\n    const run = s.run('publish');\n\n    // expected messages from my-package package...\n    const messages = [\n        /While linting files .* my-package .*Server/,\n        /my-package.js:1:1: 'PackageVar'/,\n        /While linting files .* my-package .*Client/,\n        /my-package.js:1:1: 'PackageVar'/,\n        /While linting files .* my-package .*Cordova/,\n        /my-package.js:1:1: 'PackageVar'/\n    ];\n\n    messages.forEach(message => run.matchErr(message));\n    // but not from the app or dependent package\n    run.forbid('app');\n    run.forbid('dep-package');\n\n    run.expectExit(1);\n  }\n\n  {\n    // Try again with --no-lint.\n    const run = s.run('publish', '--no-lint');\n\n    // advances further and stops due to METEOR_TEST_NO_PUBLISH\n    run.matchErr(/Would publish the package at this point/);\n    run.forbid('linting');\n\n    run.expectExit(0);\n  }\n});\n"
  },
  {
    "path": "tools/tests/login.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar testUtils = require('../tool-testing/test-utils.js');\n\nvar commandTimeoutSecs = testUtils.accountsCommandTimeoutSecs;\nvar loginTimeoutSecs = 2;\n\nselftest.define(\"login\", ['net'], function () {\n  var s = new Sandbox;\n\n  var run = s.run(\"whoami\");\n  run.matchErr(\"Not logged in\");\n  run.expectExit(1);\n\n  // Username and password prompts happen on stderr so that scripts can\n  // run commands that do login interactively and still save the command\n  // output with the login prompts appearing in it.\n  //\n  // Do this twice to confirm that the login command prints a prompt\n  // even if you are already logged in.\n  for (var i = 0; i < 2; i++) {\n    run = s.run(\"login\");\n    run.waitSecs(loginTimeoutSecs);\n    run.matchErr(\"Username:\");\n    run.write(\"test\\n\");\n    run.matchErr(\"Password:\");\n    run.write(\"testtest\\n\");\n    run.waitSecs(commandTimeoutSecs);\n    run.matchErr(\"Logged in as test.\");\n    run.expectExit(0);\n  }\n\n  // Leaving username blank, or getting the password wrong, doesn't\n  // reprompt. It also doesn't log you out.\n  run = s.run(\"login\");\n  run.waitSecs(loginTimeoutSecs);\n  run.matchErr(\"Username:\");\n  run.write(\"\\n\");\n  run.matchErr(\"Password:\");\n  run.write(\"whatever\\n\");\n  run.waitSecs(commandTimeoutSecs);\n  run.matchErr(\"failed\");\n  run.expectExit(1);\n\n  run = s.run(\"login\");\n  run.waitSecs(loginTimeoutSecs);\n  run.matchErr(\"Username:\");\n  run.write(\"test\\n\");\n  run.matchErr(\"Password:\");\n  run.write(\"whatever\\n\");\n  run.waitSecs(commandTimeoutSecs);\n  run.matchErr(\"failed\");\n  run.expectExit(1);\n\n  run = s.run('login');\n  run.waitSecs(loginTimeoutSecs);\n  run.matchErr(\"Username:\");\n  run.write(\"test\\n\");\n  run.matchErr(\"Password:\");\n  run.write(\"testtest\\n\");\n  run.waitSecs(commandTimeoutSecs);\n  run.matchErr(\"Logged in as test.\");\n  run.expectExit(0);\n\n  // XXX test login by email\n\n  run = s.run(\"whoami\");\n  run.read(\"test\\n\");\n  run.expectExit(0);\n\n  run = s.run(\"logout\");\n  run.waitSecs(commandTimeoutSecs);\n  run.matchErr(\"Logged out\");\n  run.expectExit(0);\n\n  run = s.run(\"logout\");\n  run.waitSecs(commandTimeoutSecs);\n  run.matchErr(\"Not logged in\");\n  run.expectExit(0);\n\n  run = s.run(\"whoami\");\n  run.matchErr(\"Not logged in\");\n  run.expectExit(1);\n\n  // Test login failure\n  run = s.run(\"login\");\n  run.waitSecs(loginTimeoutSecs);\n  run.matchErr(\"Username:\");\n  run.write(\"test\\n\");\n  run.matchErr(\"Password:\");\n  run.write(\"badpassword\\n\");\n  run.waitSecs(commandTimeoutSecs);\n  run.matchErr(\"Login failed\");\n  run.expectExit(1);\n\n  // Logging in with a capitalized username should work (usernames are\n  // case-insensitive).\n  run = s.run(\"login\");\n  run.waitSecs(loginTimeoutSecs);\n  run.matchErr(\"Username:\");\n  run.write(\"TeSt\\n\");\n  run.matchErr(\"Password:\");\n  run.write(\"testtest\\n\");\n  run.waitSecs(commandTimeoutSecs);\n  run.matchErr(\"Logged in as test.\");\n  run.expectExit(0);\n\n  run = s.run(\"logout\");\n  run.waitSecs(commandTimeoutSecs);\n  run.matchErr(\"Logged out\");\n  run.expectExit(0);\n\n  // Logging in with a capitalized password should NOT work (can't be\n  // too safe...)\n  run = s.run(\"login\");\n  run.waitSecs(loginTimeoutSecs);\n  run.matchErr(\"Username:\");\n  run.write(\"test\\n\");\n  run.matchErr(\"Password:\");\n  run.write(\"TesTTesT\\n\");\n  run.waitSecs(commandTimeoutSecs);\n  run.matchErr(\"Login failed\");\n  run.expectExit(1);\n});\n"
  },
  {
    "path": "tools/tests/meteor-script-link-tests.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar files = require('../fs/files.js');\n\nselftest.define(\"linking to meteor script works correctly on Windows\", function () {\n  var location =\n    '/C/some obscure/location/on disk/with some unicode/Вот тебе и юникод/';\n  var script = files._generateScriptLinkToMeteorScript(location);\n  var parsedLocation = files._getLocationFromScriptLinkToMeteorScript(script);\n  selftest.expectEqual(parsedLocation, location);\n});\n\nselftest.define(\"linking to meteor script works correctly on Windows not absolute\", function () {\n  var location =\n    'some obscure/location/on disk/with some unicode/Вот тебе и юникод/';\n  var script = files._generateScriptLinkToMeteorScript(location);\n  var parsedLocation = files._getLocationFromScriptLinkToMeteorScript(script);\n  selftest.expectEqual(parsedLocation, location);\n});\n\n\n"
  },
  {
    "path": "tools/tests/minifier-bad-plugins.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\n\nselftest.define(\"minifiers can't register non-js/non-css extensions\", [], function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"minifier-plugin-bad-extension\", { dontPrepareApp: true });\n  s.cd(\"myapp\");\n\n  run = s.run();\n  run.match(\"foo: Minifiers are only allowed to register \\\"css\\\" or \\\"js\\\" extensions.\");\n  run.stop();\n});\n\nselftest.define(\"minifiers: apps can't use more than one package providing a minifier for the same extension\", [], function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"minifier-plugin-multiple-minifiers-for-js\", { dontPrepareApp: true });\n  s.cd(\"myapp\");\n\n  run = s.run(\"--production\");\n  run.match(\"local-plugin, local-plugin-2: multiple packages registered minifiers for extension \\\"js\\\".\");\n  run.stop();\n});\n\n"
  },
  {
    "path": "tools/tests/modules.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar utils = require('../utils/utils.js');\nimport { getUrl } from '../utils/http-helpers.js';\n\nvar MONGO_LISTENING =\n  { stdout: \" [initandlisten] waiting for connections on port\" };\n\nfunction startRun(sandbox) {\n  var run = sandbox.run();\n  run.match(\"myapp\");\n  run.match(\"proxy\");\n  run.tellMongo(MONGO_LISTENING);\n  run.match(\"MongoDB\");\n  return run;\n};\n\nselftest.define(\"modules - unimported lazy files\", function() {\n  const s = new Sandbox();\n  s.createApp(\"myapp\", \"app-with-unimported-lazy-file\");\n  s.cd(\"myapp\", function() {\n    const run = s.run(\"--once\");\n    run.waitSecs(30);\n    run.expectExit(1);\n    run.forbid(\"This file shouldn't be loaded\");\n  });\n});\n\n// Checks that `import X from 'meteor/package'` will import (and re-export) the\n// mainModule if one exists, otherwise will simply export Package['package'].\n// Overlaps with compiler-plugin.js's \"install-packages.js\" code.\nselftest.define(\"modules - import chain for packages\", () => {\n  const s = new Sandbox({ fakeMongo: true });\n\n  s.createApp(\"myapp\", \"package-tests\");\n  s.cd(\"myapp\");\n  s.write(\".meteor/packages\",\n    \"meteor-base \\n modules \\n with-add-files \\n with-main-module\");\n  s.write(\"main.js\", `\n    var packageNameA = require('meteor/with-add-files').name;\n    var packageNameB = require('meteor/with-main-module').name;\n\n    console.log('with-add-files: ' + packageNameA);\n    console.log('with-main-module: ' + packageNameB);\n  `);\n\n  const run = startRun(s);\n\n  // On the server, we just check that importing *works*, not *how* it works\n  run.match(\"with-add-files: with-add-files\");\n  run.match(\"with-main-module: with-main-module\");\n\n  // On the client, we just check that install() is called correctly\n  const modules = getUrl(\"http://localhost:3000/packages/modules.js\");\n  selftest.expectTrue(modules.includes('\\ninstall(\"with-add-files\");'));\n  selftest.expectTrue(modules.includes('\\n' +\n    'install(\"with-main-module\", \"meteor/with-main-module/with-main-module.js\");'\n  ));\n\n  run.stop();\n});\n"
  },
  {
    "path": "tools/tests/mongo.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar utils = require('../utils/utils.js');\nvar net = require('net');\nvar Future = require('fibers/future');\nvar _ = require('underscore');\nvar files = require('../fs/files.js');\n\n// Tests that observeChanges continues to work even over a mongo failover.\nselftest.define(\"mongo failover\", [\"slow\"], function () {\n  var s = new Sandbox();\n  s.set('METEOR_TEST_MULTIPLE_MONGOD_REPLSET', 't');\n  s.createApp(\"failover-test\", \"failover-test\");\n  s.cd(\"failover-test\");\n\n  var run = s.run(\"--once\", \"--raw-logs\");\n  run.waitSecs(120);\n  run.match(\"SUCCESS\\n\");\n  run.expectEnd();\n  run.expectExit(0);\n});\n\nvar testMeteorMongo = function (appDir) {\n  var s = new Sandbox();\n  s.createApp(appDir, 'standard-app');\n  s.cd(appDir);\n\n  var run = s.run();\n  run.waitSecs(15);\n  run.match(appDir);\n  run.match('proxy');\n  run.match('Started MongoDB');\n\n  var mongoRun = s.run('mongo');\n  mongoRun.match('MongoDB shell');\n  mongoRun.match('connecting to: 127.0.0.1');\n  // Note: when mongo shell's input is not a tty, there is no prompt.\n  mongoRun.write('db.version()\\n');\n  mongoRun.match(/2\\.6\\.\\d+/);\n  mongoRun.stop();\n\n  run.stop();\n};\n\nselftest.define(\"meteor mongo\", function () {\n  testMeteorMongo('asdfzasdf');\n});\n\n// Regression test for #3999.  Note the Cyrillic character in the pathname.\n//\n// XXX This test fails on Windows for two different reasons:\n// - With the Unicode directory name, `meteor run` fails to start mongod\n// - If you change appDir to not have the Unicode character, the reads\n//   from the mongo shell process seem to be randomly corrupted\n// https://github.com/meteor/windows-preview/issues/145\nselftest.define(\"meteor mongo in unicode dir\", function () {\n  testMeteorMongo('asdf\\u0442asdf');\n});\n"
  },
  {
    "path": "tools/tests/npm.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar _ = require('underscore');\n\nvar MONGO_LISTENING =\n  { stdout: \" [initandlisten] waiting for connections on port\" };\n\nselftest.define(\"npm\", [\"net\"], function () {\n  var s = new Sandbox({ fakeMongo: true });\n  var run;\n\n  s.createApp(\"npmtestapp\", \"npmtest\", { dontPrepareApp: true });\n  s.cd(\"npmtestapp\");\n\n  // Ensure that we don't lose the executable bits of npm modules.\n  // Regression test for https://github.com/meteor/meteor/pull/1808\n  // Before this fix, the module would work on the first execution but not on a\n  // subsequent one.\n  _.times(2, function (i) {\n    run = s.run(\"--once\", \"--raw-logs\");\n    run.tellMongo(MONGO_LISTENING);\n    if (i === 0) {\n      run.waitSecs(2);\n      // use match instead of read because on a built release we can\n      // also get an update message here.\n      run.match(\n        \"npm-test: updating npm dependencies -- meteor-test-executable...\\n\");\n    }\n    run.waitSecs(15);\n    run.match(\"null; From shell script\\n\");\n    run.expectExit(0);\n  });\n});\n"
  },
  {
    "path": "tools/tests/old/app-with-package/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/old/app-with-package/.meteor/.id",
    "content": "1c31k1pav6i1etz3yfx"
  },
  {
    "path": "tools/tests/old/app-with-package/.meteor/packages",
    "content": "test-package\nstandard-app-packages\n"
  },
  {
    "path": "tools/tests/old/app-with-package/packages/test-package/dummy.js",
    "content": "// We need at least one server file to ensure that we actually install npm\n// modules.\n// XXX really?\n"
  },
  {
    "path": "tools/tests/old/app-with-package/packages/test-package/package.js",
    "content": "Package.describe({version: '1.0.0'});\n\nNpm.depends({});\n\nPackage.onUse(function (api) { api.addFiles('dummy.js', 'server'); });\n"
  },
  {
    "path": "tools/tests/old/app-with-private/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/old/app-with-private/.meteor/.id",
    "content": "1j3g9zflbqmlt1wjoa05"
  },
  {
    "path": "tools/tests/old/app-with-private/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nautopublish\ninsecure\ntest-package\nstandard-app-packages\n"
  },
  {
    "path": "tools/tests/old/app-with-private/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/old/app-with-private/packages/test-package/.gitignore",
    "content": ".build*\n"
  },
  {
    "path": "tools/tests/old/app-with-private/packages/test-package/package.js",
    "content": "Package.describe({\n  version: \"1.0.0\"\n});\n\nPackage.registerBuildPlugin({\n  name: 'addTxt',\n  use: [],\n  sources: ['plugin.js']\n});\n\nPackage.onUse(function (api) {\n  api.export('TestAsset', 'server');\n  api.addFiles(['test-package.js', 'test-package.txt'],'server');\n  api.addAssets(['test.notregistered'], 'server');\n});\n"
  },
  {
    "path": "tools/tests/old/app-with-private/packages/test-package/plugin.js",
    "content": "Plugin.registerSourceHandler('txt', function (compileStep) {\n  compileStep.addAsset({\n    path: compileStep.inputPath,\n    data: compileStep.read()\n  });\n});\n"
  },
  {
    "path": "tools/tests/old/app-with-private/packages/test-package/test-package.js",
    "content": "TestAsset = {};\n\nif (Meteor.isServer) {\n  TestAsset.convert = function (b) {\n    return (new Buffer(b)).toString();\n  };\n\n  TestAsset.go = function (exit) {\n    var expectText = \"Package\\n\";\n    if (Assets.getText(\"test-package.txt\") !== expectText)\n      throw new Error(\"getText test-package.txt does not match\");\n    if (TestAsset.convert(Assets.getBinary(\"test-package.txt\"))\n        !== expectText)\n      throw new Error(\"getBinary test-package.txt does not match\");\n    if (Assets.getText(\"test.notregistered\") !== \"No extension handler\\n\")\n      throw new Error(\"File with unregistered extension does not match\");\n\n    Assets.getText(\"test-package.txt\", function (err, result) {\n      if (err || result !== expectText)\n        throw new Error(\"async getText test-package.txt does not match\");\n      Assets.getBinary(\"test-package.txt\", function (err, result) {\n        if (err || TestAsset.convert(result) !== expectText)\n          throw new Error(\"async getBinary test-package.txt does not match\");\n        if (exit)\n          process.exit(0);\n      });\n    });\n  };\n}\n"
  },
  {
    "path": "tools/tests/old/app-with-private/packages/test-package/test-package.txt",
    "content": "Package\n"
  },
  {
    "path": "tools/tests/old/app-with-private/packages/test-package/test.notregistered",
    "content": "No extension handler\n"
  },
  {
    "path": "tools/tests/old/app-with-private/private/nested/test.txt",
    "content": "Nested\n"
  },
  {
    "path": "tools/tests/old/app-with-private/private/test.txt",
    "content": "Test\n"
  },
  {
    "path": "tools/tests/old/app-with-private/test.js",
    "content": "if (Meteor.isServer) {\n  var passed = true;\n  var expectText = \"Test\\n\";\n\n  if (Assets.getText(\"test.txt\") !== expectText)\n    throw new Error(\"getText test.txt does not match\");\n  if (TestAsset.convert(Assets.getBinary(\"test.txt\"))\n      !== expectText)\n    throw new Error(\"getBinary test.txt does not match\");\n\n  Assets.getText(\"test.txt\", function (err, result) {\n    if (err || result !== expectText)\n      throw new Error(\"async getText test.txt does not match\");\n    Assets.getBinary(\"test.txt\", function (err, result) {\n      if (err || TestAsset.convert(result) !== expectText)\n        throw new Error(\"async getBinary test.txt does not match\");\n      TestAsset.go(true /* exit when done */);\n    });\n  });\n}\n"
  },
  {
    "path": "tools/tests/old/app-with-public/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/old/app-with-public/.meteor/.id",
    "content": "1cugp537mjpx0gb4qri"
  },
  {
    "path": "tools/tests/old/app-with-public/.meteor/packages",
    "content": "# Meteor packages used by this project, one per line.\n#\n# 'meteor add' and 'meteor remove' will edit this file for you,\n# but you can also edit it by hand.\n\nautopublish\ninsecure\npreserve-inputs\nstandard-app-packages\n"
  },
  {
    "path": "tools/tests/old/app-with-public/.meteor/release",
    "content": "none\n"
  },
  {
    "path": "tools/tests/old/app-with-public/public/nested/nested.txt",
    "content": "Nested\n"
  },
  {
    "path": "tools/tests/old/app-with-public/public/test.txt",
    "content": "Test\n"
  },
  {
    "path": "tools/tests/old/cli-test.sh",
    "content": "#!/usr/bin/env bash\n\n# This used to be run standalone, but now it's intended to always be\n# invoked by 'meteor self-test' (and eventually we should port the\n# whole thing to JavaScript, or at least the parts that don't\n# duplicate our existing JS-based test coverage).\n#\n# To run it, set METEOR_TOOL_PATH to the 'meteor' script to use, plus,\n# as usual, METEOR_WAREHOUSE_DIR if you want to stub out the\n# warehouse.\n\nset -e -x\n\ncd \"`dirname \"$0\"`\"/../../..\n\n# METEOR_TOOL_PATH is the path to the 'meteor' that we will use for\n# our tests. There is a vestigal capability to default to running the\n# 'meteor' that sets next to this script in a checkout, but we should\n# probably just take that out.\nif [ -z \"$METEOR_TOOL_PATH\" ]; then\n    METEOR=\"`pwd`/meteor\"\nelse\n    METEOR=\"$METEOR_TOOL_PATH\"\nfi\n\nif [ -z \"$NODE\" ]; then\n    NODE=\"$(pwd)/scripts/node.sh\"\nfi\n\n# Ensure that $NODE is set properly. Note that $NODE may not have access to\n# modules from the dev bundle.\n$NODE --version\n\nTEST_TMPDIR=`mktemp -d -t meteor-cli-test-XXXXXXXX`\nOUTPUT=\"$TEST_TMPDIR/output\"\ntrap 'echo \"[...]\"; tail -25 $OUTPUT; echo FAILED ; rm -rf \"$TEST_TMPDIR\" >/dev/null 2>&1' EXIT\n\ncd \"$TEST_TMPDIR\"\n\nDIR=\"skel with spaces\"\n$METEOR create \"$DIR\"\ntest -d \"$DIR\"\ntest -f \"$DIR/$DIR.js\"\n\n## Tests in a meteor project\ncd \"$DIR\"\n\nMONGOMARK='--bind_ip 127.0.0.1 --smallfiles --port 9101'\n# kill any old test meteor\n# there is probably a better way to do this, but it is at least portable across macos and linux\n# (the || true is needed on linux, whose xargs will invoke kill even with no args)\n\n## Begin actual tests\n\nps ax | grep -e 'meteor.js -p 9100' | grep -v grep | awk '{print $1}' | xargs kill || true\n\n! $METEOR mongo >> $OUTPUT 2>&1\n$METEOR reset >> $OUTPUT 2>&1\n\ntest ! -d .meteor/local\n! ps ax | grep -e \"$MONGOMARK\" | grep -v grep >> $OUTPUT\n\nPORT=9100\n$METEOR -p $PORT >> $OUTPUT 2>&1 &\nMETEOR_PID=$!\n\nsleep 5 # XXX XXX lame\n\ntest -d .meteor/local/db\nps ax | grep -e \"$MONGOMARK\" | grep -v grep >> $OUTPUT\ncurl -s \"http://localhost:$PORT\" >> $OUTPUT\n\necho \"show collections\" | $METEOR mongo\n\n# kill meteor, see mongo is still running\nkill $METEOR_PID\n\nsleep 10 # XXX XXX lame. have to wait for inner app to die via keepalive!\n\n! ps ax | grep \"$METEOR_PID\" | grep -v grep >> $OUTPUT\nps ax | grep -e \"$MONGOMARK\"  | grep -v grep >> $OUTPUT\n\n\necho \"... rerun\"\n\n$METEOR -p $PORT >> $OUTPUT 2>&1 &\nMETEOR_PID=$!\n\nsleep 10 # XXX XXX lame\n\nps ax | grep -e \"$MONGOMARK\" | grep -v grep >> $OUTPUT\ncurl -s \"http://localhost:$PORT\" >> $OUTPUT\n\nkill $METEOR_PID\nsleep 10 # XXX XXX lame. have to wait for inner app to die via keepalive!\n\nps ax | grep -e \"$MONGOMARK\" | grep -v grep | awk '{print $1}' | xargs kill || true\nsleep 2 # need to make sure these kills take effect\n\n\n\n$METEOR test-packages -p $PORT >> $OUTPUT 2>&1 &\n\nMETEOR_PID=$!\n\nsleep 10 # XXX XXX lame\n\nps ax | grep -e \"$MONGOMARK\" | grep -v grep >> $OUTPUT\ncurl -s \"http://localhost:$PORT\" >> $OUTPUT\n\nkill $METEOR_PID\nsleep 10 # XXX XXX lame. have to wait for inner app to die via keepalive!\n\nps ax | grep -e \"$MONGOMARK\" | grep -v grep | awk '{print $1}' | xargs kill || true\nsleep 2 # need to make sure these kills take effect\n\necho \"... mongo message\"\n\n# Run a server on the same port as mongod, so that mongod fails to start up. Rig\n# it so that a single connection will cause it to exit.\n$NODE -e 'require(\"net\").createServer(function(){process.exit(0)}).listen('$PORT'+1, \"127.0.0.1\")' &\n\nsleep 1\n\n$METEOR -p $PORT > error.txt || true\n\ngrep 'port was closed' error.txt >> $OUTPUT\n\n# Kill the server by connecting to it.\n$NODE -e 'require(\"net\").connect({host:\"127.0.0.1\",port:'$PORT'+1},function(){process.exit(0);})'\n\n# prepare die.js so that we have a server that loads packages and dies\ncat > die.js <<EOF\nif (Meteor.isServer)\n  process.exit(1);\nEOF\n\n\necho \"... local-package-sets -- new package\"\n\nmkdir -p \"$TEST_TMPDIR/local-packages/a-package-named-bar/\"\ncat > \"$TEST_TMPDIR/local-packages/a-package-named-bar/package.js\" <<EOF\nPackage.describe({\n  summary: 'a-package-named-bar',\n  version: '1.0.0'\n});\nNpm.depends({gcd: '0.0.0'});\n\nPackage.onUse(function(api) {\n  api.addFiles(['call_gcd.js'], 'server');\n});\nEOF\n\ncat > \"$TEST_TMPDIR/local-packages/a-package-named-bar/call_gcd.js\" <<EOF\nconsole.log(\"loaded a-package-named-bar\");\n\nvar gcd = Npm.require('gcd');\nconsole.log(\"gcd(4,6)=\" + gcd(4,6));\nEOF\n\n! $METEOR add a-package-named-bar >> $OUTPUT\nPACKAGE_DIRS=\"$TEST_TMPDIR/local-packages\" $METEOR add a-package-named-bar >> $OUTPUT\n$METEOR -p $PORT --once 2>&1 | grep \"unknown package .* a-package-named-bar\" >> $OUTPUT\nPACKAGE_DIRS=\"$TEST_TMPDIR/local-packages\" $METEOR -p $PORT --once | grep \"loaded a-package-named-bar\" >> $OUTPUT\nPACKAGE_DIRS=\"$TEST_TMPDIR/local-packages\" $METEOR bundle $TEST_TMPDIR/bundle.tar.gz >> $OUTPUT\ntar tvzf $TEST_TMPDIR/bundle.tar.gz >>$OUTPUT\nPACKAGE_DIRS=\"$TEST_TMPDIR/local-packages\" $METEOR build $TEST_TMPDIR/bundle >> $OUTPUT\ntar tvzf \"$TEST_TMPDIR/bundle/$DIR.tar.gz\" >>$OUTPUT\nPACKAGE_DIRS=\"$TEST_TMPDIR/local-packages\" $METEOR -p $PORT --once | grep \"gcd(4,6)=2\" >> $OUTPUT\n\n\necho \"... local-package-sets -- overridden package\"\n\nmkdir -p \"$TEST_TMPDIR/local-packages/accounts-ui/\"\ncat > \"$TEST_TMPDIR/local-packages/accounts-ui/package.js\" <<EOF\nPackage.describe({\n  summary: \"accounts-ui - overridden\",\n  version: \"1.0.0\"\n});\n\nEOF\n\n# Remove a-package-named-bar so that the local accounts-ui package is\n# the only thing that determines whether we need to set PACKAGE_DIRS. If\n# we were to leave a-package-named-bar in the app, then we would need to\n# specify PACKAGE_DIRS to get output from 'meteor list', even before\n# adding the local accounts-ui package, and we want to be able to run\n# 'meteor list' without PACKAGE_DIRS set to see that it picks up the\n# core accounts-ui package, not the local one.\nPACKAGE_DIRS=\"$TEST_TMPDIR/local-packages\" $METEOR remove a-package-named-bar >> $OUTPUT\n\n! $METEOR add accounts-ui 2>&1 | grep \"accounts-ui - overridden\" >> $OUTPUT\n$METEOR remove accounts-ui 2>&1 >> $OUTPUT\nPACKAGE_DIRS=\"$TEST_TMPDIR/local-packages\" $METEOR add accounts-ui 2>&1 | grep \"accounts-ui - overridden\" >> $OUTPUT\n! $METEOR list | grep \"accounts-ui - overridden\" >> $OUTPUT\nPACKAGE_DIRS=\"$TEST_TMPDIR/local-packages\" $METEOR list | grep \"accounts-ui - overridden\" >> $OUTPUT\n\n\n# remove die.js, we're done with package tests.\nrm die.js\n\n\n\n\n## Cleanup\ntrap - EXIT\nrm -rf \"$DIR\"\necho PASSED\n"
  },
  {
    "path": "tools/tests/old/empty-app/.meteor/.gitignore",
    "content": "local\n"
  },
  {
    "path": "tools/tests/old/empty-app/.meteor/.id",
    "content": "1n5fh06qwmxvw11mbbzf"
  },
  {
    "path": "tools/tests/old/empty-app/.meteor/packages",
    "content": "# no packages\n\nmeteor-base\nstandard-minifiers\n"
  },
  {
    "path": "tools/tests/old/test-bundler-assets.js",
    "content": "require('../../tool-env/install-babel.js');\n\nvar _ = require('underscore');\nvar assert = require('assert');\nvar Future = require('fibers/future');\nvar files = require('../../fs/files.js');\nvar bundler = require('../../isobuild/bundler.js');\nvar isopackets = require('../../tool-env/isopackets.js');\nvar release = require('../../packaging/release.js');\nvar catalog = require('../../packaging/catalog/catalog.js');\nvar buildmessage = require('../../utils/buildmessage.js');\nvar projectContextModule = require('../../project-context.js');\n\nvar lastTmpDir = null;\nvar tmpDir = function () {\n  return (lastTmpDir = files.mkdtemp());\n};\n\nvar makeProjectContext = function (appName) {\n  var projectDir = files.mkdtemp(\"test-bundler-assets\");\n  files.cp_r(files.pathJoin(files.convertToStandardPath(__dirname), appName),\n    projectDir);\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: projectDir\n  });\n  doOrThrow(function () {\n    projectContext.prepareProjectForBuild();\n  });\n\n  return projectContext;\n};\n\nvar doOrThrow = function (f) {\n  var ret;\n  var messages = buildmessage.capture(function () {\n    ret = f();\n  });\n  if (messages.hasMessages()) {\n    throw Error(messages.formatMessages());\n  }\n  return ret;\n};\n\n// These tests make some assumptions about the structure of stars: that there\n// are client and server programs inside programs/.\n\nvar runTest = function () {\n  // As preparation, we need to initialize the official catalog, which serves\n  // as our sql data store.\n  catalog.official.initialize();\n\n  console.log(\"Bundle app with public/ directory\");\n  assert.doesNotThrow(function () {\n    var projectContext = makeProjectContext(\"app-with-public\");\n\n    var tmpOutputDir = tmpDir();\n    var result = bundler.bundle({\n      projectContext: projectContext,\n      outputPath: tmpOutputDir\n    });\n    var clientManifest = JSON.parse(\n      files.readFile(\n        files.pathJoin(tmpOutputDir, \"programs\", \"web.browser\", \"program.json\")\n      )\n    );\n\n    var testCases = [[\"/test.txt\", \"Test\\n\"],\n                     [\"/nested/nested.txt\", \"Nested\\n\"]];\n    _.each(testCases, function (file) {\n      var manifestItem = _.find(clientManifest.manifest, function (m) {\n        return m.url === file[0];\n      });\n      assert(manifestItem);\n      var diskPath = files.pathJoin(tmpOutputDir, \"programs\", \"web.browser\",\n                               manifestItem.path);\n      assert(files.exists(diskPath));\n      assert.strictEqual(files.readFile(diskPath, \"utf8\"), file[1]);\n    });\n  });\n\n  console.log(\"Bundle app with private/ directory and package asset\");\n  assert.doesNotThrow(function () {\n    var projectContext = makeProjectContext(\"app-with-private\");\n\n    var tmpOutputDir = tmpDir();\n\n    var result = bundler.bundle({\n      projectContext: projectContext,\n      outputPath: tmpOutputDir\n    });\n\n    var serverManifest = JSON.parse(\n      files.readFile(\n        files.pathJoin(tmpOutputDir, \"programs\", \"server\",\n                  \"program.json\")\n      )\n    );\n    var testTxtPath;\n    var nestedTxtPath;\n    var packageTxtPath;\n    var unregisteredExtensionPath;\n    _.each(serverManifest.load, function (item) {\n      if (item.path === \"packages/test-package.js\") {\n        packageTxtPath = files.pathJoin(\n          tmpOutputDir, \"programs\", \"server\", item.assets['test-package.txt']);\n        unregisteredExtensionPath = files.pathJoin(\n          tmpOutputDir, \"programs\", \"server\", item.assets[\"test.notregistered\"]);\n      }\n      if (item.path === \"app/test.js\") {\n        testTxtPath = files.pathJoin(\n          tmpOutputDir, \"programs\", \"server\", item.assets['test.txt']);\n        nestedTxtPath = files.pathJoin(\n          tmpOutputDir, \"programs\", \"server\", item.assets[\"nested/test.txt\"]);\n      }\n    });\n    // check that the files are where the manifest says they are\n    assert.strictEqual(result.errors, false, result.errors && result.errors[0]);\n    assert(files.exists(testTxtPath));\n    assert(files.exists(nestedTxtPath));\n    assert(files.exists(packageTxtPath));\n    assert(files.exists(unregisteredExtensionPath));\n    assert.strictEqual(files.readFile(testTxtPath, \"utf8\"), \"Test\\n\");\n    assert.strictEqual(files.readFile(nestedTxtPath, \"utf8\"), \"Nested\\n\");\n    assert.strictEqual(files.readFile(packageTxtPath, \"utf8\"), \"Package\\n\");\n    assert.strictEqual(files.readFile(unregisteredExtensionPath, \"utf8\"),\n                       \"No extension handler\\n\");\n\n    // Run the app to check that Assets.getText/Binary do the right things.\n    var meteorToolPath = files.convertToOSPath(process.env.METEOR_TOOL_PATH);\n    var fut = new Future();\n    require('child_process').execFile(\n      meteorToolPath,\n      // use a non-default port so we don't fail if someone is running an app\n      // now\n      [\"--once\", \"--port\", \"4123\"], {\n        cwd: files.convertToOSPath(projectContext.projectDir),\n        stdio: 'inherit'\n      },\n      fut.resolver()\n    );\n    fut.wait();  // would throw if command failed\n  });\n};\n\nvar Fiber = require('fibers');\nFiber(function () {\n  if (! files.inCheckout()) {\n    throw Error(\"This old test doesn't support non-checkout\");\n  }\n\n  try {\n    release.setCurrent(release.load(null));\n    isopackets.ensureIsopacketsLoadable();\n    runTest();\n  } catch (err) {\n    console.log(err.stack);\n    console.log('\\nBundle can be found at ' + lastTmpDir);\n    process.exit(1);\n  }\n}).run();\n"
  },
  {
    "path": "tools/tests/old/test-bundler-npm.js",
    "content": "require('../../tool-env/install-babel.js');\n\nvar _ = require('underscore');\nvar assert = require('assert');\nvar Fiber = require('fibers');\nvar files = require('../../fs/files.js');\nvar bundler = require('../../isobuild/bundler.js');\nvar release = require('../../packaging/release.js');\nvar catalog = require('../../packaging/catalog/catalog.js');\nvar buildmessage = require('../../utils/buildmessage.js');\nvar meteorNpm = require('../../isobuild/meteor-npm.js');\nvar isopackets = require('../../tool-env/isopackets.js');\nvar projectContextModule = require('../../project-context.js');\n\nvar lastTmpDir = null;\nvar tmpDir = function () {\n  return (lastTmpDir = files.mkdtemp());\n};\n\nvar makeProjectContext = function (appName) {\n  var projectDir = files.mkdtemp(\"test-bundler-assets\");\n  files.cp_r(files.pathJoin(files.convertToStandardPath(__dirname), appName),\n    projectDir);\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: projectDir\n  });\n  doOrThrow(function () {\n    projectContext.prepareProjectForBuild();\n  });\n\n  return projectContext;\n};\n\nvar doOrThrow = function (f) {\n  var ret;\n  var messages = buildmessage.capture(function () {\n    ret = f();\n  });\n  if (messages.hasMessages()) {\n    throw Error(messages.formatMessages());\n  }\n  return ret;\n};\n\nvar getTestPackageDir = function (projectContext) {\n  return files.pathJoin(projectContext.projectDir, 'packages', 'test-package');\n};\n\nvar reloadPackages = function (projectContext) {\n  projectContext.reset();\n  doOrThrow(function () {\n    projectContext.prepareProjectForBuild();\n  });\n};\n\nvar updateTestPackage = function (projectContext, npmDependencies, options) {\n  options = options || {};\n  files.writeFile(\n    files.pathJoin(getTestPackageDir(projectContext), 'package.js'),\n    \"Package.describe({version: '1.0.0'});\\n\"\n      + \"\\n\"\n      + \"Npm.depends(\" + JSON.stringify(npmDependencies) + \");\"\n      + \"\\n\"\n      + \"Package.onUse(function (api) { api.addFiles('dummy.js', 'server'); });\");\n  if (! options.noReload)\n    reloadPackages(projectContext);\n};\n\n///\n/// HELPERS\n///\n\nvar _assertCorrectPackageNpmDir = function (projectContext, deps) {\n  // test-package/.npm was generated\n\n  // sort of a weird way to do it, but i don't want to have to look up\n  // all subdependencies to write these tests, so just transplant that\n  // information\n  var actualMeteorNpmShrinkwrapDependencies = JSON.parse(\n    files.readFile(files.pathJoin(getTestPackageDir(projectContext), \".npm\",\n                                  \"package\", \"npm-shrinkwrap.json\"),\n                    'utf8')).dependencies;\n  var expectedMeteorNpmShrinkwrapDependencies = _.object(_.map(deps, function (version, name) {\n    var expected = {};\n    if (/tarball/.test(version)) {\n      expected.from = version;\n    } else {\n      expected.version = version;\n    }\n\n    // copy fields with values generated by shrinkwrap that can't be\n    // known to the test author. We set keys on val always in this\n    // order so that comparison works well.\n    var val = {};\n    _.each(['version', 'dependencies'], function (key) {\n      if (expected[key])\n        val[key] = expected[key];\n      else if (actualMeteorNpmShrinkwrapDependencies[name] && actualMeteorNpmShrinkwrapDependencies[name][key])\n        val[key] = actualMeteorNpmShrinkwrapDependencies[name][key];\n    });\n\n    return [name, val];\n  }));\n\n  var testPackageDir = getTestPackageDir(projectContext);\n  var actual = files.readFile(files.pathJoin(testPackageDir, \".npm\", \"package\", \"npm-shrinkwrap.json\"), 'utf8');\n  var expected = JSON.stringify({\n    dependencies: expectedMeteorNpmShrinkwrapDependencies}, null, /*indentation, the way npm does it*/2) + '\\n';\n\n  assert.equal(actual, expected, actual + \" == \" + expected);\n\n  assert.equal(\n    files.readFile(files.pathJoin(testPackageDir, \".npm\", \"package\", \".gitignore\"), 'utf8'),\n    \"node_modules\\n\");\n  assert(files.exists(files.pathJoin(testPackageDir, \".npm\", \"package\", \"README\")));\n\n  // verify the contents of the `node_modules` dir\n  var nodeModulesDir = files.pathJoin(testPackageDir, \".npm\", \"package\", \"node_modules\");\n\n  // all expected dependencies are installed correctly, with the correct version\n  _.each(deps, function (version, name) {\n    assert(looksInstalled(nodeModulesDir, name));\n\n    if (!/tarball/.test(version)) { // 'version' in package.json from a tarball won't be correct\n      assert.equal(JSON.parse(\n        files.readFile(\n          files.pathJoin(nodeModulesDir, name, \"package.json\"),\n          'utf8')).version,\n        version);\n    }\n  });\n\n  // all installed dependencies were expected to be found there,\n  // meaning we correctly removed unused node_modules directories\n  _.each(\n    files.readdir(nodeModulesDir),\n    function (installedNodeModule) {\n      if (files.exists(files.pathJoin(nodeModulesDir, installedNodeModule, \"package.json\")))\n        assert(installedNodeModule in deps);\n    });\n};\n\nvar _assertCorrectBundleNpmContents = function (bundleDir, deps) {\n  // sanity check -- main.js has expected contents.\n  assert.strictEqual(files.readFile(files.pathJoin(bundleDir, \"main.js\"), \"utf8\"),\n                     bundler._mainJsContents);\n\n  var bundledPackageNodeModulesDir = files.pathJoin(\n    bundleDir, 'programs', 'server', 'npm', 'test-package', 'node_modules');\n\n  // bundle actually has the npm modules\n  _.each(deps, function (version, name) {\n    assert(looksInstalled(bundledPackageNodeModulesDir, name));\n\n    if (!/tarball/.test(version)) { // 'version' in package.json from a tarball won't be correct\n      assert.equal(JSON.parse(\n        files.readFile(files.pathJoin(bundledPackageNodeModulesDir, name, 'package.json'), 'utf8'))\n                   .version,\n                   version);\n    }\n  });\n};\n\nvar looksInstalled = function (nodeModulesDir, name) {\n  // All of the packages in this test have one of these two files, so presumably\n  // if one of these files is here we have correctly installed the package.\n  return files.exists(files.pathJoin(nodeModulesDir, name, 'README.md')) ||\n    files.exists(files.pathJoin(nodeModulesDir, name, 'LICENSE'));\n};\n\n///\n/// TESTS\n///\n\nvar runTest = function () {\n  // As preparation, we need to initialize the official catalog, which serves as\n  // our sql data store.\n  catalog.official.initialize();\n\n  var projectContext = makeProjectContext('app-with-package');\n  var testPackageDir = getTestPackageDir(projectContext);\n\n  // XXX this is a huge nasty hack. see release.js,\n  // #HandlePackageDirsDifferently\n  console.log(\"app that uses gcd - clean run\");\n  assert.doesNotThrow(function () {\n    updateTestPackage(projectContext, {gcd: '0.0.0'});\n    var tmpOutputDir = tmpDir();\n    var result = bundler.bundle({\n      projectContext: projectContext,\n      outputPath: tmpOutputDir\n    });\n    assert.strictEqual(result.errors, false, result.errors && result.errors[0]);\n    _assertCorrectPackageNpmDir(projectContext, {gcd: '0.0.0'});\n    _assertCorrectBundleNpmContents(tmpOutputDir, {gcd: '0.0.0'});\n  });\n\n  console.log(\"app that uses gcd - no changes, running again\");\n  assert.doesNotThrow(function () {\n    var tmpOutputDir = tmpDir();\n    var result = bundler.bundle({\n      projectContext: projectContext,\n      outputPath: tmpOutputDir\n    });\n    assert.strictEqual(result.errors, false, result.errors && result.errors[0]);\n    _assertCorrectPackageNpmDir(projectContext, {gcd: '0.0.0'});\n    _assertCorrectBundleNpmContents(tmpOutputDir, {gcd: '0.0.0'});\n  });\n\n  console.log(\"app that uses gcd - as would be in a 3rd party repository (no .npm/package/node_modules)\");\n  assert.doesNotThrow(function () {\n    var tmpOutputDir = tmpDir();\n\n    // rm -rf .npm\n    var nodeModulesDir = files.pathJoin(testPackageDir, \".npm\",\n                                        \"package\", \"node_modules\");\n    assert(files.exists(nodeModulesDir));\n    files.rm_recursive(nodeModulesDir);\n    // We also have to change something in the package or else we won't rebuild\n    // at all.\n    files.appendFile(files.pathJoin(testPackageDir, 'package.js'), '\\n');\n    reloadPackages(projectContext);\n\n    // while bundling, verify that we don't call `npm install\n    // name@version unnecessarily` -- calling `npm install` is enough,\n    // and installing each package separately could unintentionally bump\n    // subdependency versions. (to intentionally bump subdependencies,\n    // just remove all of the .npm directory)\n    var bareRunNpmCommand = meteorNpm.runNpmCommand;\n    meteorNpm.runNpmCommand = function (file, args, opts) {\n      if (args.length > 1 && args[0] === 'install')\n        assert.fail(\"shouldn't be installing specific npm packages: \" + args[1]);\n      return bareRunNpmCommand(file, args, opts);\n    };\n    var result = bundler.bundle({\n      projectContext: projectContext,\n      outputPath: tmpOutputDir\n    });\n    meteorNpm.runNpmCommand = bareRunNpmCommand;\n\n    assert.strictEqual(result.errors, false, result.errors && result.errors[0]);\n    _assertCorrectPackageNpmDir(projectContext, {gcd: '0.0.0'});\n    _assertCorrectBundleNpmContents(tmpOutputDir, {gcd: '0.0.0'});\n  });\n\n  console.log(\"app that uses gcd - add mime and semver\");\n  assert.doesNotThrow(function () {\n    updateTestPackage(projectContext,\n                      {gcd: '0.0.0', mime: '1.2.7', semver: '1.1.0'});\n    var tmpOutputDir = tmpDir();\n    var result = bundler.bundle({\n      projectContext: projectContext,\n      outputPath: tmpOutputDir\n    });\n    assert.strictEqual(result.errors, false, result.errors && result.errors[0]);\n    _assertCorrectPackageNpmDir(\n      projectContext, {gcd: '0.0.0', mime: '1.2.7', semver: '1.1.0'});\n    _assertCorrectBundleNpmContents(\n      tmpOutputDir, {gcd: '0.0.0', mime: '1.2.7', semver: '1.1.0'});\n  });\n\n  console.log(\"app that uses gcd - add mime, as it would happen if you pulled in this change (updated npm-shrinkwrap.json but not node_modules)\");\n  assert.doesNotThrow(function () {\n    var tmpOutputDir = tmpDir();\n\n    // rm -rf .npm/package/node_modules/mime\n    var nodeModulesMimeDir = files.pathJoin(\n      testPackageDir, \".npm\", \"package\", \"node_modules\", \"mime\");\n    assert(files.exists(files.pathJoin(nodeModulesMimeDir)));\n    files.rm_recursive(nodeModulesMimeDir);\n    // We also have to change something in the package or we won't rebuild at\n    // all.\n    files.appendFile(files.pathJoin(testPackageDir, 'package.js'), '\\n');\n    reloadPackages(projectContext);\n\n    var result = bundler.bundle({\n      projectContext: projectContext,\n      outputPath: tmpOutputDir\n    });\n    assert.strictEqual(result.errors, false, result.errors && result.errors[0]);\n    _assertCorrectPackageNpmDir(\n      projectContext, {gcd: '0.0.0', mime: '1.2.7', semver: '1.1.0'});\n    _assertCorrectBundleNpmContents(\n      tmpOutputDir, {gcd: '0.0.0', mime: '1.2.7', semver: '1.1.0'});\n  });\n\n  console.log(\"app that uses gcd - upgrade mime, remove semver\");\n  assert.doesNotThrow(function () {\n    updateTestPackage(projectContext, {gcd: '0.0.0', mime: '1.2.8'});\n    var tmpOutputDir = tmpDir();\n    var result = bundler.bundle({\n      projectContext: projectContext,\n      outputPath: tmpOutputDir\n    });\n    assert.strictEqual(result.errors, false, result.errors && result.errors[0]);\n    _assertCorrectPackageNpmDir(projectContext, {gcd: '0.0.0', mime: '1.2.8'});\n    _assertCorrectBundleNpmContents(\n      tmpOutputDir, {gcd: '0.0.0', mime: '1.2.8'});\n  });\n\n  console.log(\"app that uses gcd - try downgrading mime to non-existant version\");\n  assert.doesNotThrow(function () {\n    updateTestPackage(\n      projectContext, {gcd: '0.0.0', mime: '0.1.2'}, {noReload: true});\n    projectContext.reset();\n    var messages = buildmessage.capture(function () {\n      projectContext.prepareProjectForBuild();\n    });\n    assert(messages.hasMessages());\n    var job = _.find(messages.jobs, function (job) {\n      return job.title === \"building package test-package\";\n    });\n    assert(job);\n    assert(/mime version 0.1.2 is not available/.test(job.messages[0].message));\n    _assertCorrectPackageNpmDir(\n      projectContext, {gcd: '0.0.0', mime: '1.2.8'}); // shouldn't've changed\n  });\n\n  console.log(\"app that uses gcd - downgrade mime to an existant version\");\n  assert.doesNotThrow(function () {\n    updateTestPackage(projectContext, {gcd: '0.0.0', mime: '1.2.7'});\n    var tmpOutputDir = tmpDir();\n    var result = bundler.bundle({\n      projectContext: projectContext,\n      outputPath: tmpOutputDir\n    });\n    assert.strictEqual(result.errors, false, result.errors && result.errors[0]);\n\n    _assertCorrectPackageNpmDir(projectContext, {gcd: '0.0.0', mime: '1.2.7'});\n    _assertCorrectBundleNpmContents(\n      tmpOutputDir, {gcd: '0.0.0', mime: '1.2.7'});\n  });\n\n  console.log(\"app that uses gcd - install gzippo via tarball\");\n  assert.doesNotThrow(function () {\n    var deps = {gzippo: 'https://github.com/meteor/gzippo/tarball/1e4b955439abc643879ae264b28a761521818f3b'};\n    updateTestPackage(projectContext, deps);\n    var tmpOutputDir = tmpDir();\n    var result = bundler.bundle({\n      projectContext: projectContext,\n      outputPath: tmpOutputDir\n    });\n    assert.strictEqual(result.errors, false, result.errors && result.errors[0]);\n    _assertCorrectPackageNpmDir(projectContext, deps);\n    _assertCorrectBundleNpmContents(tmpOutputDir, deps);\n    // Check that a string introduced by our fork is in the source.\n    assert(/clientMaxAge = 604800000/.test(\n      files.readFile(\n        files.pathJoin(testPackageDir, \".npm\", \"package\", \"node_modules\",\n                       \"gzippo\", \"lib\", \"staticGzip.js\"), \"utf8\")));\n  });\n};\n\n\nFiber(function () {\n  if (! files.inCheckout()) {\n    throw Error(\"This old test doesn't support non-checkout\");\n  }\n\n  meteorNpm._printNpmCalls = true;\n\n  try {\n    release.setCurrent(release.load(null));\n    isopackets.ensureIsopacketsLoadable();\n    runTest();\n  } catch (err) {\n    console.log(err.stack);\n    console.log('\\nBundle can be found at ' + lastTmpDir);\n    process.exit(1);\n  }\n}).run();\n"
  },
  {
    "path": "tools/tests/old/test-bundler-options.js",
    "content": "require('../../tool-env/install-babel.js');\n\nvar _ = require('underscore');\nvar assert = require('assert');\nvar bundler = require('../../isobuild/bundler.js');\nvar release = require('../../packaging/release.js');\nvar files = require('../../fs/files.js');\nvar catalog = require('../../packaging/catalog/catalog.js');\nvar buildmessage = require('../../utils/buildmessage.js');\nvar isopackets = require('../../tool-env/isopackets.js');\nvar projectContextModule = require('../../project-context.js');\n\n\nvar lastTmpDir = null;\nvar tmpDir = function () {\n  return (lastTmpDir = files.mkdtemp());\n};\n\nvar makeProjectContext = function (appName) {\n  var projectDir = files.mkdtemp(\"test-bundler-options\");\n  files.cp_r(files.pathJoin(files.convertToStandardPath(__dirname), appName),\n    projectDir);\n  var projectContext = new projectContextModule.ProjectContext({\n    projectDir: projectDir\n  });\n  doOrThrow(function () {\n    projectContext.prepareProjectForBuild();\n  });\n\n  return projectContext;\n};\n\nvar doOrThrow = function (f) {\n  var ret;\n  var messages = buildmessage.capture(function () {\n    ret = f();\n  });\n  if (messages.hasMessages()) {\n    throw Error(messages.formatMessages());\n  }\n  return ret;\n};\n\nvar runTest = function () {\n  // As preparation, let's initialize the official catalog. It servers as our\n  // data store, so we will probably need it.\n  catalog.official.initialize();\n\n  var readManifest = function (tmpOutputDir) {\n    return JSON.parse(files.readFile(\n      files.pathJoin(tmpOutputDir, \"programs\", \"web.browser\", \"program.json\"),\n      \"utf8\")).manifest;\n  };\n\n  // an empty app. notably this app has no .meteor/release file.\n  var projectContext = makeProjectContext('empty-app');\n\n  console.log(\"basic version\");\n  assert.doesNotThrow(function () {\n    var tmpOutputDir = tmpDir();\n    var result = bundler.bundle({\n      projectContext: projectContext,\n      outputPath: tmpOutputDir,\n      buildOptions: { minifyMode: 'production' }\n    });\n    assert.strictEqual(result.errors, false, result.errors && result.errors[0]);\n\n    // sanity check -- main.js has expected contents.\n    assert.strictEqual(\n      files.readFile(files.pathJoin(tmpOutputDir, \"main.js\"), \"utf8\"),\n      bundler._mainJsContents);\n    // no top level node_modules directory\n    assert(!files.exists(files.pathJoin(tmpOutputDir,\n                                        \"programs\", \"server\", \"node_modules\")));\n    // yes package node_modules directory\n    assert(files.lstat(files.pathJoin(\n      tmpOutputDir, \"programs\", \"server\", \"npm\", \"node_modules\", \"meteor\", \"ddp-server\"))\n           .isDirectory());\n\n    // verify that contents are minified\n    var manifest = readManifest(tmpOutputDir);\n    _.each(manifest, function (item) {\n      if (item.type !== 'js')\n        return;\n      // Just a hash, and no \"packages/\".\n      assert(/^[0-9a-f]{40,40}\\.js$/.test(item.path), item.path);\n    });\n  });\n\n  console.log(\"no minify\");\n  assert.doesNotThrow(function () {\n    var tmpOutputDir = tmpDir();\n    var result = bundler.bundle({\n      projectContext: projectContext,\n      outputPath: tmpOutputDir,\n      buildOptions: { minifyMode: 'development' }\n    });\n    assert.strictEqual(result.errors, false);\n\n    // sanity check -- main.js has expected contents.\n    assert.strictEqual(files.readFile(files.pathJoin(tmpOutputDir, \"main.js\"), \"utf8\"),\n                       bundler._mainJsContents);\n\n    // verify that contents are not minified\n    var manifest = readManifest(tmpOutputDir);\n    var foundMeteor = false;\n    var foundTracker = false;\n    _.each(manifest, function (item) {\n      if (item.type !== 'js')\n        return;\n      // No minified hash.\n      assert(!/^[0-9a-f]{40,40}\\.js$/.test(item.path));\n      // No tests.\n      assert(!/:tests/.test(item.path));\n      if (item.path === 'packages/meteor.js')\n        foundMeteor = true;\n      if (item.path === 'packages/tracker.js')\n        foundTracker = true;\n    });\n    assert(foundMeteor);\n    assert(foundTracker);\n  });\n\n  if (process.platform !== \"win32\") { // Windows doesn't have symlinks\n    console.log(\"includeNodeModules\");\n    assert.doesNotThrow(function () {\n      var tmpOutputDir = tmpDir();\n      var result = bundler.bundle({\n        projectContext: projectContext,\n        outputPath: tmpOutputDir,\n        includeNodeModules: 'symlink'\n      });\n      assert.strictEqual(result.errors, false);\n\n      // sanity check -- main.js has expected contents.\n      assert.strictEqual(files.readFile(files.pathJoin(tmpOutputDir, \"main.js\"), \"utf8\"),\n                         bundler._mainJsContents);\n      // node_modules directory exists and is a symlink\n      assert(files.lstat(files.pathJoin(tmpOutputDir, \"programs\", \"server\", \"node_modules\")).isSymbolicLink());\n      // node_modules contains fibers\n      assert(files.exists(files.pathJoin(tmpOutputDir, \"programs\", \"server\", \"node_modules\", \"fibers\")));\n      // package node_modules directory also a symlink\n      // XXX might be breaking this\n      assert(files.lstat(files.pathJoin(\n        tmpOutputDir, \"programs\", \"server\", \"npm\", \"node_modules\", \"meteor\", \"ddp-server\", \"node_modules\"))\n             .isSymbolicLink());\n    });\n  }\n};\n\n\nvar Fiber = require('fibers');\nFiber(function () {\n  if (! files.inCheckout()) {\n    throw Error(\"This old test doesn't support non-checkout\");\n  }\n\n  release.setCurrent(release.load(null));\n  isopackets.ensureIsopacketsLoadable();\n\n  try {\n    runTest();\n  } catch (err) {\n    console.log(err.stack);\n    console.log('\\nBundle can be found at ' + lastTmpDir);\n    process.exit(1);\n  }\n}).run();\n"
  },
  {
    "path": "tools/tests/old/test-watch.js",
    "content": "require('../../tool-env/install-babel.js');\n\nvar _ = require('underscore');\nvar assert = require('assert');\nvar crypto = require('crypto');\nvar Fiber = require('fibers');\nvar Future = require('fibers/future');\nvar watch = require('../../fs/watch.js');\nvar files = require('../../fs/files.js');\n\nvar tmp = files.mkdtemp('test_watch');\nvar serial = 0;\n\nvar touchFile = function (filePath, contents) {\n  filePath = files.pathJoin(tmp, filePath);\n  files.mkdir_p(files.pathDirname(filePath));\n  files.writeFile(filePath, contents || ('' + serial));\n  serial++;\n};\n\nvar touchDir = function (dirPath) {\n  dirPath = files.pathJoin(tmp, dirPath);\n  files.mkdir_p(dirPath);\n};\n\nvar remove = function (fileOrDirPath) {\n  fileOrDirPath = files.pathJoin(tmp, fileOrDirPath);\n  files.rm_recursive(fileOrDirPath);\n};\n\nvar theWatcher;\nvar fired;\nvar firedFuture;\nvar lastOptions;\nvar go = function (options) {\n  options = options || lastOptions;\n  lastOptions = options;\n  if (theWatcher) {\n    theWatcher.stop();\n    theWatcher = null;\n  }\n  fired = false;\n\n  var watchSet = new watch.WatchSet();\n\n  _.each(options.files, function (value, file) {\n    file = files.pathJoin(tmp, file);\n    if (value !== null && typeof value !== \"string\") {\n      if (files.exists(file)) {\n        var hash = crypto.createHash('sha1');\n        hash.update(files.readFile(file));\n        value = hash.digest('hex');\n      } else {\n        value = 'dummyhash';\n      }\n    }\n    watchSet.addFile(file, value);\n  });\n\n  _.each(options.directories, function (dir) {\n    // don't mutate options.directories, since we may reuse it with a no-arg\n    // go() call\n    var realDir = {\n      absPath: files.pathJoin(tmp, dir.absPath),\n      include: dir.include,\n      exclude: dir.exclude,\n      names: dir.names\n    };\n    realDir.contents = dir.contents || watch.readDirectory(realDir);\n    watchSet.addDirectory(realDir);\n  });\n\n  theWatcher = new watch.Watcher({\n    watchSet: watchSet,\n    onChange: function () {\n      fired = true;\n      if (firedFuture)\n        firedFuture.return(true);\n    }\n  });\n}\n\nvar fires = function (waitDuration) {\n  if (! theWatcher)\n    throw new Error(\"No watcher?\");\n  if (fired)\n    return true;\n  // Wait up to a second for it to fire\n  var timeout = setTimeout(function () {\n    firedFuture.return(false);\n  }, waitDuration || 1000);\n  if (firedFuture)\n    throw new Error(\"Already have a future\");\n  firedFuture = new Future;\n  var ret = firedFuture.wait();\n  clearTimeout(timeout);\n  firedFuture = null;\n  return ret;\n};\n\nvar waitForTopOfSecond = function () {\n  while (true) {\n    var msPastSecond = +(new Date) % 1000;\n    if (msPastSecond < 100) {\n      return;\n    }\n    delay(25);\n  }\n};\n\nvar delay = function (duration) {\n  var f = new Future;\n  setTimeout(function () {\n    f.return();\n  }, duration);\n  f.wait();\n};\n\nFiber(function () {\n  console.log(\"Test Watcher\");\n\n  console.log(\"... one file\");\n  touchFile('/aa/b', 'kitten');\n  go({\n    files: { '/aa/b': true }\n  });\n  assert(!fires());\n  touchFile('/aa/b', 'kitten');\n  assert(!fires());\n  touchFile('/aa/b', 'puppy');\n  assert(fires());\n  go();\n  touchFile('/aa/b', 'puppy');\n  assert(!fires());\n  touchFile('/aa/b', 'kitten');\n  assert(fires());\n  go();\n  remove('/aa/b');\n  assert(fires());\n  touchFile('/aa/b');\n  go({\n    files: { '/aa/b': true, '/aa/c': true }\n  });\n  assert(fires()); // look like /aa/c was removed\n  go({\n    files: { '/aa/b': true, '/aa/c': null }\n  });\n  assert(!fires());  // assert that /aa/c doesn't exist\n\n  console.log(\"... directories\");\n  go({\n    files: {'/aa/b': true },\n    directories: [\n      {absPath: '/aa',\n       include: [/yes/, /maybe/, /aa/],\n       exclude: [/not/, /never/],\n       contents: []\n      },\n      {absPath: '/bb',\n       include: [/.?/],\n       contents: []\n      }\n    ]\n  });\n  assert(fires());  // because /bb doesn't exist\n  touchDir('/bb');\n  go();\n  assert(!fires());\n  touchFile('/aa/c');\n  assert(!fires());\n  touchFile('/aa/maybe-not');\n  assert(!fires());\n  touchFile('/aa/never-yes');\n  assert(!fires());\n  touchFile('/aa/never');\n  assert(!fires());\n  touchFile('/aa/yes-for-sure');\n  assert(fires());\n\n  go();\n  touchFile('/aa/nope');\n  assert(fires());  // because yes-for-sure isn't in 'contents'\n  remove('/aa/yes-for-sure');\n  go();\n  assert(!fires());\n  touchFile('/aa/maybe-this-time');\n  assert(fires());\n  go();\n  assert(fires()); // maybe-this-time is still there\n  go({\n    files: {'/aa/b': true},\n    directories: [\n      {absPath: '/aa',\n       include: [/yes/, /maybe/, /aa/],\n       exclude: [/not/, /never/],\n       contents: ['maybe-this-time']\n      },\n      {absPath: '/bb',\n       include: [/.?/],\n       contents: []\n      }\n    ]\n  });\n  go();\n  assert(!fires()); // maybe-this-time is now in the expected file list\n  touchFile('/aa/maybe-yes');\n  assert(fires());\n  remove('/aa/maybe-yes');\n  remove('/aa/maybe-this-time');\n  go();\n  assert(fires()); // maybe-this-time is missing\n  touchFile('/aa/maybe-this-time');\n  touchDir('/aa/yes-i-said-yes-i-will-yes');\n  go({\n    directories: [\n      {absPath: '/aa',\n       include: [/yes/, /maybe/, /aa/],\n       exclude: [/not/, /never/],\n       contents: ['maybe-this-time']\n      }\n    ]\n  });\n  assert(fires());  // yes-i-said-yes-i-will-yes/ is missing\n  go({\n    directories: [\n      {absPath: '/aa',\n       include: [/yes/, /maybe/, /aa/],\n       exclude: [/not/, /never/],\n       contents: ['maybe-this-time', 'yes-i-said-yes-i-will-yes']\n      }\n    ]\n  });\n  assert(fires());  // yes-i-said-yes-i-will-yes is a dir, not a file\n  go({\n    directories: [\n      {absPath: '/aa',\n       include: [/yes/, /maybe/, /aa/],\n       exclude: [/not/, /never/],\n       contents: ['maybe-this-time', 'yes-i-said-yes-i-will-yes/']\n      }\n    ]\n  });\n  assert(!fires());\n  // same directory, different filters\n  go({\n    directories: [\n      // dirs\n      {absPath: '/aa',\n       include: [/\\/$/],\n       contents: ['yes-i-said-yes-i-will-yes/']\n      },\n      // files\n      {absPath: '/aa',\n       include: [/.?/],\n       exclude: [/\\/$/],\n       contents: ['b', 'c', 'maybe-not', 'maybe-this-time', 'never',\n                  'never-yes', 'nope']\n      }\n    ]\n  });\n  assert(!fires());\n  touchFile('/aa/bla');\n  assert(fires());\n\n  touchDir('/cc');\n  go({\n    directories: [\n      {absPath: '/cc',\n       names: ['abc-foo', 'def-bar'],\n       exclude: [/foo/],\n       contents: []\n      }\n    ]\n  });\n  assert(!fires());\n  touchFile('/cc/abc-foo');\n  // See that names overrides exclude.\n  assert(fires());\n\n  // nb: these are supposed to verify that the \"wait a second and try again\"\n  // logic works, but I couldn't get them to fail even when I turned that logic\n  // off.\n  console.log(\"... rapid changes to file\");\n  touchFile('/aa/x');\n  waitForTopOfSecond();\n  go({\n    files: {'/aa/x': true }});\n  touchFile('/aa/x');\n  assert(fires(2000));\n\n  go({\n    directories: [\n      {absPath: '/aa',\n       include: [/yes/, /maybe/, /aa/],\n       exclude: [/not/, /never/]\n      }\n    ]\n  });\n  assert(!fires());\n\n  waitForTopOfSecond();\n  touchFile('/aa/wtf');\n  delay(600);\n  touchFile('/aa/yes-indeed');\n  assert(fires(2000));\n  remove('/aa');\n\n  console.log(\"Watcher test passed\");\n  theWatcher.stop();\n\n}).run();\n\n\n"
  },
  {
    "path": "tools/tests/old.js",
    "content": "var _ = require('underscore');\nvar Future = require('fibers/future');\nvar selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar Run = selftest.Run;\nvar files = require('../fs/files.js');\nvar release = require('../packaging/release.js');\n\n// old tests don't get to test --release, and always run this release\nvar maybeFixRelease = function (env) {\n  if (release.current && release.current.isProperRelease()) {\n    env.METEOR_SPRINGBOARD_RELEASE = release.current.name;\n  }\n  return env;\n};\n\n// This runs an old-style unit test. These are just .js files that\n// require() whatever bits of the tool they want to test and have at\n// them. They exit with 0 on success or something else on failure, and\n// they are very chatty about logging their progress to stdout/stderr.\n//\n// filename is interpreted relative to tools/selftests/old.\nvar runOldTest = function (filename, extraEnv) {\n  var s = new Sandbox;\n\n  // 'Run' assumes that the first argument is a standard path,\n  var run = new Run(files.convertToStandardPath(process.execPath), {\n    // 'args' are treated as-is, so need to be converted before passing into\n    // 'Run'\n    args: [files.convertToOSPath(files.pathResolve(\n      files.convertToStandardPath(__dirname), 'old', filename))],\n    env: maybeFixRelease(_.extend({\n      METEOR_TOOL_PATH: s.execPath\n    }, extraEnv))\n  });\n  run.waitSecs(120);\n  run.expectExit(0);\n};\n\n// XXX Why are these tests from checkout?\n//\n// Most of the self-test framework works by calling a meteor command and waiting\n// for something to happen. Instead, the old tests call isolated functions (ex:\n// bundler.bundle) and skip the (now, somewhat complicated) initialization\n// process that would usually happen before these functions are called. We have\n// managed to hack together some stuff to tide this over when running from\n// checkout, but dealing with release overrides in not-checkout has mostly been\n// a failure.\n//\n// It would be nice if these tests were to work from release, and maybe ekate\n// will take another look at them later, but it is not worth that much more time\n// before 0.9.0.\n//\nselftest.define(\"watch\", [\"slow\"], function () {\n  var runFuture = runOldTest.future();\n  var futures = [\n    // Run with pathwatcher (if possible)\n    runFuture('test-watch.js'),\n    // Run with fs.watchFile fallback\n    runFuture('test-watch.js', {\n      METEOR_WATCH_FORCE_POLLING: 1\n    })\n  ];\n  Future.wait(futures);\n  // Throw if any threw.\n  _.each(futures, function (f) {\n    f.get();\n  });\n});\n\nselftest.define(\"bundler-assets\", [\"checkout\"], function () {\n  runOldTest('test-bundler-assets.js');\n});\n\nselftest.define(\"bundler-options\", [\"checkout\"], function () {\n  runOldTest('test-bundler-options.js');\n});\n\nselftest.define(\"bundler-npm\", [\"slow\", \"net\", \"checkout\"], function () {\n  runOldTest('test-bundler-npm.js');\n});\n\n// This last one's is a shell script!\n// XXX pardon the hacky glue to make it work with a sandbox\n\n// If we're running from a checkout, run it both in checkout mode and\n// in release mode. If we're not running from a checkout, just run it\n// against the installed copy.\n\nselftest.define(\"old cli tests (bash)\", [\"slow\", \"net\", \"yet-unsolved-windows-failure\"], function () {\n  var s = new Sandbox;\n  var scriptToRun = files.pathJoin(files.convertToStandardPath(__dirname),\n    'old', 'cli-test.sh');\n  var run = new Run(scriptToRun, {\n    env: maybeFixRelease({\n      METEOR_TOOL_PATH: s.execPath,\n      NODE: process.execPath\n    })\n  });\n  run.waitSecs(1000);\n  run.match(\"PASSED\\n\");\n  run.expectExit(0);\n});\n"
  },
  {
    "path": "tools/tests/organizations.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar testUtils = require('../tool-testing/test-utils.js');\nvar Sandbox = selftest.Sandbox;\n\nvar commandTimeoutSecs = testUtils.accountsCommandTimeoutSecs;\n\n// XXX tests for missing args for all commands\n\nselftest.define(\"organizations - logged out\", function () {\n  var s = new Sandbox;\n\n  var orgName = testUtils.randomOrgName();\n\n  var run = s.run(\"admin\", \"members\", orgName, \"--add\", \"testtest\");\n  run.waitSecs(commandTimeoutSecs);\n  run.matchErr(\"You must be logged in\");\n  run.matchErr(\"Username:\");\n  run.stop();\n\n  run = s.run(\"admin\", \"members\", orgName, \"--remove\", \"testtest\");\n  run.waitSecs(commandTimeoutSecs);\n  run.matchErr(\"You must be logged in\");\n  run.matchErr(\"Username:\");\n  run.stop();\n\n  run = s.run(\"admin\", \"members\", orgName);\n  run.waitSecs(commandTimeoutSecs);\n  run.matchErr(\"You must be logged in\");\n  run.matchErr(\"Username:\");\n  run.stop();\n\n  run = s.run(\"admin\", \"list-organizations\");\n  run.waitSecs(commandTimeoutSecs);\n  run.matchErr(\"You must be logged in\");\n  run.matchErr(\"Username:\");\n  run.stop();\n\n});\n"
  },
  {
    "path": "tools/tests/package-tests.js",
    "content": "var _= require('underscore');\n\nvar selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar files = require('../fs/files.js');\nvar testUtils = require('../tool-testing/test-utils.js');\nvar utils = require('../utils/utils.js');\nvar packageClient = require('../packaging/package-client.js');\nvar catalog = require('../packaging/catalog/catalog.js');\n\nvar username = \"test\";\n\n// Returns a random package name.\nvar randomizedPackageName = function (username, start) {\n  // We often use package names in long, wrapped string output, so having them\n  // be a consistent length is very useful.\n  var startStr = start ? start + \"-\" : \"\";\n  return username + \":\" + startStr + utils.randomToken().substring(0, 6);\n}\n\n// Given a sandbox, that has the app as its currend cwd, read the packages file\n// and check that it contains exactly the packages specified, in order.\n//\n// sand: a sandbox, that has the main app directory as its cwd.\n// packages: an array of packages in order. Packages can be of the form:\n//\n//    meteor-base (ie: name), in which case this will match any\n//    version of that package as long as it is included.\n//\n//    awesome-pack@1.0.0 (ie: name@version) to match that name at that\n//    version explicitly. This is for packages that we included at a specific\n//    version.\nvar checkPackages = selftest.markStack(function(sand, packages) {\n  var lines = sand.read(\".meteor/packages\").split(\"\\n\");\n  var i = 0;\n  _.each(lines, function(line) {\n    if (!line) {\n      return;\n    }\n    // If the specified package contains an @ sign, then it has a version\n    // number, so we should match everything.\n    if (packages[i].split('@').length > 1) {\n      selftest.expectEqual(line, packages[i]);\n    } else {\n      var pack = line.split('@')[0];\n      selftest.expectEqual(pack, packages[i]);\n    }\n    i++;\n  });\n  selftest.expectEqual(packages.length, i);\n});\n\n// Given a sandbox, that has the app as its currend cwd, read the versions file\n// and check that it contains the packages that we are looking for. We don't\n// check the order, we just want to make sure that the right dependencies are\n// in.\n//\n// sand: a sandbox, that has the main app directory as its cwd.\n// packages: an array of packages in order. Packages can be of the form:\n//\n//    meteor-base (ie: name), in which case this will match any\n//    version of that package as long as it is included. This is for packages\n//    external to the app, since we don't want this test to fail when we push a\n//    new version.\n//\n//    awesome-pack@1.0.0 (ie: name@version) to match that name at that\n//    version explicitly. This is for packages that only exist for the purpose\n//    of this test (for example, packages local to this app), so we know exactly\n//    what version we expect.\nvar checkVersions = selftest.markStack(function(sand, packages) {\n  var lines = sand.read(\".meteor/versions\").split(\"\\n\");\n  var depend = {};\n  _.each(lines, function(line) {\n    if (!line) {\n      return;\n    }\n    // Packages are stored of the form foo@1.0.0, so this should give us an\n    // array [foo, 1.0.0].\n    var split = line.split('@');\n    var pack = split[0];\n    depend[pack] = split[1];\n  });\n  var i = 0;\n  _.each(packages, function (pack) {\n    var split = pack.split('@');\n    if (split.length > 1) {\n      selftest.expectEqual(depend[split[0]], split[1]);\n    } else {\n      var exists = _.has(depend, split[0]);\n      selftest.expectEqual(exists, true);\n    }\n    i++;\n  });\n  selftest.expectEqual(packages.length, i);\n});\n\n// Add packages to an app. Change the contents of the packages and their\n// dependencies, make sure that the app still refreshes.\nselftest.define(\"change packages during hot code push\", [], function () {\n  var s = new Sandbox();\n  var run;\n\n  // Starting a run\n  s.createApp(\"myapp\", \"package-tests\");\n  s.cd(\"myapp\");\n  run = s.run();\n  run.waitSecs(5);\n  run.match(\"myapp\");\n  run.match(\"proxy\");\n  run.match(\"MongoDB\");\n  run.waitSecs(5);\n  run.match(\"your app\");\n  run.waitSecs(5);\n  run.match(\"running at\");\n  run.match(\"localhost\");\n  // Add the local package 'say-something'. It should print a message.\n  s.write(\".meteor/packages\", \"meteor-base \\n say-something\");\n  run.waitSecs(3);\n  run.match(\"initial\");\n\n  // Modify the local package 'say-something'.\n  s.cd(\"packages/say-something\", function () {\n    s.write(\"foo.js\", \"console.log(\\\"another\\\");\");\n  });\n  run.waitSecs(12);\n  run.match(\"another\");\n\n  // Add a local package depends-on-plugin.\n  s.write(\".meteor/packages\", \"meteor-base \\n depends-on-plugin\");\n  run.waitSecs(2);\n  run.match(\"foobar\");\n\n  // Change something in the plugin.\n  s.cd(\"packages/contains-plugin/plugin\", function () {\n    s.write(\"plugin.js\", \"console.log(\\\"edit\\\");\");\n  });\n  run.waitSecs(2);\n  run.match(\"edit\");\n  run.match(\"foobar!\");\n\n  // Check that we are watching the versions file, as well as the packages file.\n  s.unlink('.meteor/versions');\n  run.waitSecs(10);\n  run.match(\"restarted\");\n\n  // Switch back to say-something for a moment.\n  s.write(\".meteor/packages\", \"meteor-base \\n say-something\");\n  run.waitSecs(3);\n  run.match(\"another\");\n  run.stop();\n\n  s.rename('packages/say-something', 'packages/shout-something');\n  s.write(\".meteor/packages\", \"meteor-base \\n shout-something\");\n  s.cd(\"packages/shout-something\", function () {\n    s.write(\"foo.js\", \"console.log(\\\"louder\\\");\");\n  });\n\n  run = s.run();\n  run.waitSecs(5);\n  run.match(\"myapp\");\n  run.match(\"proxy\");\n  run.match(\"MongoDB\");\n  run.waitSecs(5);\n  run.match(\"louder\");  // the package actually loaded\n\n  // How about breaking and fixing a package.js?\n  s.cd(\"packages/shout-something\", function () {\n    var packageJs = s.read(\"package.js\");\n    s.write(\"package.js\", \"]\");\n    run.waitSecs(3);\n    run.match(\"=> Errors prevented startup\");\n    run.match(\"package.js:1: Unexpected token\");\n    run.match(\"Waiting for file change\");\n\n    s.write(\"package.js\", packageJs);\n    run.waitSecs(3);\n    run.match(\"restarting\");\n    run.match(\"restarted\");\n  });\n  run.stop();\n});\n\n// Add packages through the command line. Make sure that the correct set of\n// changes is reflected in .meteor/packages, .meteor/versions and list.\nselftest.define(\"add packages to app\", [], function () {\n  var s = new Sandbox();\n  var run;\n\n  // Starting a run\n  s.createApp(\"myapp\", \"package-tests\");\n  s.cd(\"myapp\");\n  s.set(\"METEOR_OFFLINE_CATALOG\", \"t\");\n\n  // This has legit version syntax, but accounts-base started with 1.0.0 and is\n  // unlikely to backtrack.\n  run = s.run(\"add\", \"accounts-base@0.123.123\");\n  run.matchErr(\"no such version\");\n  run.expectExit(1);\n\n  // Adding a nonexistent package at a nonexistent version should print\n  // only one error message, not two. (We used to print \"no such\n  // package\" and \"no such version\".)\n  run = s.run(\"add\", \"not-a-real-package-and-never-will-be@1.0.0\");\n  run.matchErr(\"no such package\");\n  run.expectExit(1);\n  run.forbidAll(\"no such version\");\n\n  run = s.run(\"add\", \"accounts-base\");\n\n  run.match(\"accounts-base: A user account system\");\n  run.expectExit(0);\n\n  checkPackages(s,\n                [\"meteor-base\", \"accounts-base\"]);\n\n  // Adding the nonexistent version now should still say \"no such\n  // version\". Regression test for\n  // https://github.com/meteor/meteor/issues/2898.\n  run = s.run(\"add\", \"accounts-base@0.123.123\");\n  run.matchErr(\"no such version\");\n  run.expectExit(1);\n  run.forbidAll(\"Currently using accounts-base\");\n  run.forbidAll(\"will be changed to\");\n\n  run = s.run(\"--once\");\n\n  run = s.run(\"add\", \"say-something@1.0.0\");\n  run.match(\"say-something: print to console\");\n  run.expectExit(0);\n\n  checkPackages(s,\n                [\"meteor-base\", \"accounts-base\",  \"say-something@1.0.0\"]);\n\n  run = s.run(\"add\", \"depends-on-plugin\");\n  run.match(/depends-on-plugin.*added,/);\n  run.expectExit(0);\n\n  checkPackages(s,\n                [\"meteor-base\", \"accounts-base\",\n                 \"say-something@1.0.0\", \"depends-on-plugin\"]);\n\n  checkVersions(s,\n                [\"accounts-base\",  \"depends-on-plugin\",\n                 \"say-something\",  \"meteor-base\",\n                 \"contains-plugin@1.1.0\"]);\n\n  run = s.run(\"remove\", \"say-something\");\n  run.match(\"say-something: removed dependency\");\n  checkVersions(s,\n                [\"accounts-base\",  \"depends-on-plugin\",\n                 \"meteor-base\",\n                 \"contains-plugin\"]);\n\n  run = s.run(\"remove\", \"depends-on-plugin\");\n  run.match(/contains-plugin.*removed from your project/);\n  run.match(/depends-on-plugin.*removed from your project/);\n  run.match(\"depends-on-plugin: removed dependency\");\n\n  checkVersions(s,\n                [\"accounts-base\",\n                 \"meteor-base\"]);\n  run = s.run(\"list\");\n  run.match(\"accounts-base\");\n  run.match(\"meteor-base\");\n\n  // Add a description-less package. Check that no weird things get\n  // printed (like \"added no-description: undefined\").\n  run = s.run(\"add\", \"no-description\");\n  run.match(\"no-description\\n\");\n  run.expectEnd();\n  run.expectExit(0);\n});\n\nselftest.define(\"add debugOnly and prodOnly packages\", [], function () {\n  var s = new Sandbox();\n  var run;\n\n  // Starting a run\n  s.createApp(\"myapp\", \"package-tests\");\n  s.cd(\"myapp\");\n  s.set(\"METEOR_OFFLINE_CATALOG\", \"t\");\n\n    // Add a debugOnly package. It should work during a normal run, but print\n  // nothing in production mode.\n  run = s.run(\"add\", \"debug-only\");\n  run.match(\"debug-only\");\n  run.expectExit(0);\n\n  s.mkdir(\"server\");\n  s.write(\"server/exit-test.js\",\n          \"process.exit(global.DEBUG_ONLY_LOADED ? 234 : 235)\");\n\n  run = s.run(\"--once\");\n  run.waitSecs(15);\n  run.expectExit(234);\n\n  run = s.run(\"--once\", \"--production\");\n  run.waitSecs(15);\n  run.expectExit(235);\n\n  // Add prod-only package, which sets GLOBAL.PROD_ONLY_LOADED.\n  run = s.run(\"add\", \"prod-only\");\n  run.match(\"prod-only\");\n  run.expectExit(0);\n\n  s.mkdir(\"server\");\n  s.write(\"server/exit-test.js\", // overwrite\n          \"process.exit(global.PROD_ONLY_LOADED ? 234 : 235)\");\n\n  run = s.run(\"--once\");\n  run.waitSecs(15);\n  run.expectExit(235);\n\n  run = s.run(\"--once\", \"--production\");\n  run.waitSecs(15);\n  run.expectExit(234);\n});\n\nselftest.define(\"add package with both debugOnly and prodOnly\", [], function () {\n  var s = new Sandbox();\n  var run;\n\n  // Add an app with a package with prodOnly and debugOnly set (an error)\n  s.createApp(\"myapp\", \"debug-only-test\", {dontPrepareApp: true});\n  s.cd(\"myapp\");\n  run = s.run(\"--prepare-app\");\n  run.waitSecs(20);\n  run.matchErr(\"can't have more than one of: debugOnly, prodOnly, testOnly\");\n  run.expectExit(1);\n});\n\n\n// Add a package that adds files to specific client architectures.\nselftest.define(\"add packages client archs\", function (options) {\n  var runTestWithArgs = function (clientType, args, port) {\n    var s = new Sandbox({\n      clients: _.extend(options.clients, { port: port })\n    });\n\n    // Starting a run\n    s.createApp(\"myapp\", \"package-tests\");\n    s.cd(\"myapp\");\n      s.set(\"METEOR_OFFLINE_CATALOG\", \"t\");\n\n    var outerRun = s.run(\"add\", \"say-something-client-targets\");\n    outerRun.match(/say-something-client-targets.*added,/);\n    outerRun.expectExit(0);\n    checkPackages(s, [\"meteor-base\", \"say-something-client-targets\"]);\n\n    var expectedLogNum = 0;\n    s.testWithAllClients(function (run) {\n      run.waitSecs(5);\n      run.match(\"myapp\");\n      run.match(\"proxy\");\n      run.waitSecs(5);\n      run.match(\"MongoDB\");\n      run.waitSecs(5);\n      run.match(\"running at\");\n      run.match(\"localhost\");\n\n      run.connectClient();\n      run.waitSecs(20);\n      run.match(\"all clients \" + (expectedLogNum++));\n      run.match(clientType + \" client \" + (expectedLogNum++));\n      run.stop();\n    }, args);\n  };\n\n  runTestWithArgs(\"browser\", [], 3000);\n});\n\n// `packageName` should be a full package name (i.e. <username>:<package\n// name>), and the sandbox should be logged in as that username.\nvar createAndPublishPackage = selftest.markStack(function (s, packageName) {\n  var packageDirName = \"package-of-two-versions\";\n  s.createPackage(packageDirName, packageName, \"package-of-two-versions\");\n  s.cd(packageDirName, function (){\n    var run = s.run(\"publish\", \"--create\");\n    run.waitSecs(25);\n    run.expectExit(0);\n  });\n  return packageDirName;\n});\n\nselftest.define(\"add package with no builds\", [\"net\"], function () {\n  var s = new Sandbox();\n  // This depends on glasser:binary-package-with-no-builds@1.0.0 existing with\n  // no published builds.\n\n  s.createApp(\"myapp\", \"empty\");\n  s.cd(\"myapp\");\n\n  var run = s.run(\"add\", \"glasser:binary-package-with-no-builds\");\n  run.waitSecs(10);\n  run.matchErr(\"glasser:binary-package-with-no-builds@1.0.0\");\n  run.matchErr(\"No compatible binary build found\");\n  run.expectExit(1);\n});\n\nselftest.define(\"package skeleton creates correct versionsFrom\", ['custom-warehouse'], function () {\n  var s = new Sandbox({ warehouse: { v1: { recommended: true } } });\n  var token = utils.randomToken();\n  var fullPackageName = \"test:\" + token;\n  var fsPackageName = token;\n\n  var run = s.run(\"create\", \"--package\", fullPackageName);\n  run.waitSecs(15);\n  run.match(fullPackageName);\n  run.expectExit(0);\n\n  s.cd(fsPackageName);\n  var packageJs = s.read(\"package.js\");\n  if (! packageJs.match(/api.versionsFrom\\('v1'\\);/)) {\n    selftest.fail(\"package.js missing correct 'api.versionsFrom':\\n\" +\n                  packageJs);\n  }\n});\n\nselftest.define(\"show unknown version of package\", function () {\n  var s = new Sandbox();\n\n  // This version doesn't exist and is unlikely to exist.\n  var run = s.run(\"show\", \"meteor-base@0.123.456\");\n  run.waitSecs(5);\n  run.matchErr(\"meteor-base@0.123.456: not found\");\n  run.expectExit(1);\n\n  // This package exists in the server (we need it to publish the tool), but is\n  // not a local package.\n  run = s.run(\"show\", \"npm-bcrypt@local\");\n  run.waitSecs(5);\n  run.matchErr(\"npm-bcrypt@local: not found\");\n  run.expectExit(1);\n\n});\n\nselftest.define(\"circular dependency errors\", function () {\n  var s = new Sandbox();\n  // meteor add refreshes, but we don't need anything from the official catalog\n  // here.\n  s.set('METEOR_OFFLINE_CATALOG', 't');\n  var run;\n\n  // This app contains some pairs of packages with circular dependencies The app\n  // currently *uses* no packages, so it can be created successfully.\n  s.createApp(\"myapp\", \"circular-deps\");\n  s.cd(\"myapp\");\n\n  // Try to add one of a pair of circularly-depending packages. See an error.\n  run = s.run('add', 'first');\n  run.matchErr('error: circular dependency');\n  run.expectExit(1);\n\n  // Note that the app still builds fine because 'first' didn't actually get\n  // added.\n  run = s.run('--prepare-app');\n  run.expectExit(0);\n\n\n  // This pair has first-imply uses second-imply, second-imply implies\n  // first-imply.\n  run = s.run('add', 'first-imply');\n  run.matchErr('error: circular dependency');\n  run.expectExit(1);\n\n  // This pair has first-weak uses second-weak, second-weak uses first-weak\n  // weakly.  Currently, it's possible to add a weak cycle to an app (ie, the\n  // prepare-app step passes), but not to run the bundler. We don't want to\n  // write a test that prevents us from making the weak cycle an error at\n  // prepare-time, so let's skip straight to bundling.\n  s.write('.meteor/packages', 'first-weak');\n  run = s.run('--once');\n  run.matchErr('error: circular dependency');\n  run.expectExit(254);\n\n  // ... but we can add second-weak, which just doesn't pull in first-weak at\n  // all.\n  s.write('.meteor/packages', 'second-weak');\n  run = s.run('--once');\n  run.match(/first-weak.*removed from your project/);\n  run.expectExit(123);  // the app immediately calls process.exit(123)\n\n  // This pair has first-unordered uses second-unordered, second-unordered uses\n  // first-unordered unorderedly.  This should work just fine: that's why\n  // unordered exists!\n  s.write('.meteor/packages', 'first-unordered');\n  run = s.run('--once');\n  run.match(/first-unordered.*added/);\n  run.match(/second-unordered.*added/);\n  run.match(/second-weak.*removed from your project/);\n  run.expectExit(123);  // the app immediately calls process.exit(123)\n});\n\n// Runs 'meteor show <fullPackageName>' without a specified version and checks\n// that the output is correct.\n//\n// - s: sandbox in which to run commands\n// - fullPackageName: name of the package to show.\n// - options:\n//   - summary: Expected summary of the latest version.\n//   - description: longform description of the latest version\n//   - maintainers: the string of maintainers\n//   - homepage: Homepage url, if one was set.\n//   - git:  Git url, if one was set.\n//   - exports: exports string\n//   - implies: implies string\n//   - defaultVersion: version that git/exports/etc come from\n//   - versions: array of objects representing versions that we have\n//     published, with keys:\n//     - version: version number (ex: 0.9.9)\n//     - date: string we expect to see as the date.\n//     - label: string that we expect to see as the label. (ex: \"installed\")\n//   - addendum: a message to display at the bottom.\n//   - all: run 'meteor show' with the 'show-all' option.\nvar testShowPackage =  selftest.markStack(function (s, fullPackageName, options) {\n  var run;\n  if (options.all) {\n    run = s.run(\"show\", \"--show-all\", fullPackageName);\n  } else {\n    run = s.run(\"show\", fullPackageName);\n  }\n  var packageName = options.defaultVersion ?\n    fullPackageName + \"@\" + options.defaultVersion : fullPackageName;\n  run.match(\"Package: \" + packageName + \"\\n\");\n  if (options.homepage) {\n    run.read(\"Homepage: \" + options.homepage + \"\\n\");\n  }\n  if (options.maintainers) {\n    run.read(\"Maintainers: \" + options.maintainers + \"\\n\");\n  }\n  if (options.git) {\n    run.read(\"Git: \" + options.git + \"\\n\");\n  }\n  if (options.exports) {\n    run.read(\"Exports: \" + options.exports + \"\\n\");\n  }\n  if (options.implies) {\n    run.read(\"Implies: \" + options.implies + \"\\n\");\n  }\n  run.read(\"\\n\");\n  if (_.has(options, \"description\")) {\n    run.read(options.description + \"\\n\");\n  } else if (_.has(options, \"summary\")) {\n    run.read(options.summary + \"\\n\");\n  }\n  if (options.versions) {\n    if (options.all) {\n      run.match(\"Versions:\");\n    } else {\n      run.match(\"Recent versions:\");\n    }\n    _.each(options.versions, function (version) {\n      run.match(version.version);\n      if (version.directory) {\n        run.match(version.directory + \"\\n\");\n      } else {\n        run.match(version.date);\n        if (version.label) {\n          run.match(version.label + \"\\n\");\n        } else {\n          run.match(\"\\n\");\n        }\n     }\n    });\n    run.read(\"\\n\");\n  }\n  if (options.addendum) {\n    run.read(options.addendum);\n  }\n  run.expectExit(0);\n});\n\n// Runs 'meteor show <name>@<version> and checks that the output is correct.\n//\n// - s: sandbox\n// - options:\n//  - packageName: name of the package.\n//  - version: version string.\n//  - summary: summary string of the package.\n//  - description: long-form description of the package\n//  - publishedBy: username of the publisher.\n//  - publishedOn: string of the publication time.\n//  - git: (optional) URL of the git repository.\n//  - dependencies: (optional) an array of objects representing dependencies:\n//    - name: package name\n//    - constraint: constraint, such as \"1.0.0\" or \"=1.0.0\" or null.\n//    - weak: true if this is a weak dependency.\n//  - addendum: a message that we expect to display at the very bottom.\nvar testShowPackageVersion =  selftest.markStack(function (s, options) {\n  var name = options.packageName;\n  var version = options.version;\n  var run = s.run(\"show\", name + \"@\" + version);\n  run.match(\"Package: \" + name + \"@\" + version + \"\\n\");\n  if (options.directory) {\n    run.match(\"Directory: \" + options.directory + \"\\n\");\n  }\n  if (options.exports) {\n    run.read(\"Exports: \" + options.exports + \"\\n\");\n  }\n  if (options.implies) {\n    run.read(\"Implies: \" + options.implies + \"\\n\");\n  }\n  if (options.git) {\n    run.match(\"Git: \" + options.git + \"\\n\");\n  }\n  if (_.has(options, \"description\")) {\n    run.read(\"\\n\");\n    run.read(options.description + \"\\n\");\n  } else if (_.has(options, \"summary\")) {\n    run.read(\"\\n\");\n    run.read(options.summary + \"\\n\");\n  }\n  if (options.dependencies) {\n    run.read(\"\\n\");\n    run.read(\"Depends on:\\n\");\n    // Use 'read' to ensure that these are the only dependencies listed.\n    _.each(options.dependencies, function (dep) {\n      var depStr = dep.name;\n      if (dep.constraint) {\n        depStr += \"@\" + dep.constraint;\n      }\n      if (dep.weak) {\n        depStr += \" (weak dependency)\";\n      }\n      run.read(\"  \" + depStr + \"\\n\");\n    });\n  }\n  if (options.publishedBy) {\n    run.match(\"\\n\");\n    run.match(\n      \"Published by \" + options.publishedBy +\n      \" on \" + options.publishedOn + \".\\n\");\n  }\n  if (options.addendum) {\n    run.read(\"\\n\" + options.addendum + \"\\n\");\n  }\n  // Make sure that we exit without printing anything else.\n  run.expectEnd(0);\n});\n\n\n// For local packages without a version, we want to replace version information\n// with the string \"local\". We also want to make sure that querying for\n// 'name@local' gives that local version.\nselftest.define(\"show local package w/o version\",  function () {\n  var s = new Sandbox();\n  var name = \"my-local-package\" + utils.randomToken();\n\n  // Create a package without version or summary; check that we can show its\n  // information without crashing.\n  s.createPackage(name, name, \"package-for-show\");\n  var packageDir = files.pathJoin(s.root, \"home\", name);\n\n  s.cd(name, function () {\n    s.cp(\"package-completely-empty.js\", \"package.js\");\n    testShowPackage(s, name, {\n      defaultVersion: \"local\",\n      versions: [{ version: \"local\", directory: packageDir }]\n    });\n\n    testShowPackageVersion(s, {\n      packageName: name,\n      version: \"local\",\n      directory: packageDir\n    });\n\n    // Test that running without any arguments also shows this package.\n    var run = s.run(\"show\");\n    run.match(\"Package: \" + name + \"@local\\n\");\n    run.match(\"Directory: \" + packageDir + \"\\n\");\n    run.expectExit(0);\n  });\n\n  // Test that running without any arguments outside of a package does not\n  // work.\n  var run = s.run(\"show\");\n  run.matchErr(\"specify a package or release name\");\n  run.expectExit(1);\n});\n\n// Make sure that a local-only package shows up correctly in show and search\n// results.\nselftest.define(\"show and search local package\",  function () {\n  // Setup: create an app, containing a package. This local package should show\n  // up in the results of `meteor show` and `meteor search`.\n  var s = new Sandbox();\n  var name = \"my-local-package\" + utils.randomToken();\n  s.createApp(\"myapp\", \"empty\");\n  s.cd(\"myapp\");\n  s.mkdir(\"packages\");\n  s.cd(\"packages\", function () {\n    s.createPackage(name, name, \"package-for-show\");\n  });\n\n  var packageDir = files.pathJoin(s.root, \"home\", \"myapp\", \"packages\", name);\n  s.cd(packageDir, function () {\n    s.cp(\"package-with-git.js\", \"package.js\");\n  });\n\n  var summary = 'This is a test package';\n  // Run `meteor show`, but don't add the package to the app yet. We should know\n  // that the package exists, even though it hasn't been added to the app.\n  testShowPackage(s, name, {\n    summary: summary,\n    defaultVersion: \"local\",\n    git: 'www.github.com/meteor/meteor',\n    versions: [{ version: \"1.0.0\", directory: packageDir }]\n  });\n\n  // Add the package to the app.\n  var run = s.run(\"add\", name);\n  run.waitSecs(5);\n  run.expectExit(0);\n  testShowPackage(s, name, {\n    summary: summary,\n    git: 'www.github.com/meteor/meteor',\n    defaultVersion: \"local\",\n    versions: [{ version: \"1.0.0\", directory: packageDir }]\n  });\n\n  // When we run `meteor search`, we should be able to see the results for this\n  // package, even though it does not exist on the server.\n  run = s.run(\"search\", name);\n  run.waitSecs(15);\n  run.match(name);\n  run.match(\"You can use\");\n  run.expectExit(0);\n\n  // We can see exports on local packages.\n  s.cd(\"packages\");\n  summary = \"This is a test package\";\n  name = \"my-local-exports\";\n  packageDir = files.pathJoin(s.root, \"home\", \"myapp\", \"packages\", name);\n  s.createPackage(name, name, \"package-for-show\");\n  s.cd(name, function () {\n    s.cp(\"package-with-exports.js\", \"package.js\");\n  });\n\n  var exportStr =\n    \"A, B (server), C (web.browser, web.cordova), D (web.browser), E (web.cordova), G (server, web.cordova)\";\n  var description = \"Test package.\";\n\n  testShowPackage(s, name, {\n    summary: summary,\n    git: \"www.github.com/meteor/meteor\",\n    exports: exportStr,\n    description: description,\n    defaultVersion: \"local\",\n    versions: [{ version: \"1.0.1\", directory: packageDir }]\n  });\n  testShowPackageVersion(s, {\n    packageName: name,\n    version: \"1.0.1\",\n    directory: packageDir,\n    git: \"www.github.com/meteor/meteor\",\n    summary: summary,\n    exports: exportStr,\n    description: description\n  });\n\n  // Test showing implies. Since we are not going to build the package, we don't\n  // have to publish any of the things that we imply.\n  var impRaw = {\n    A: \"\",\n    B: \"server\",\n    C: \"web.browser, web.cordova\",\n    D: \"web.browser\",\n    E: \"web.cordova\",\n    G: \"server, web.cordova\"\n  };\n  var impliesData = _.sortBy(_.map(impRaw, function (label, placeholder) {\n    var name =  randomizedPackageName(username, placeholder.toLowerCase());\n    return { placeholder: placeholder, name: name, label: label};\n  }), 'name');\n  s.cd(name, function () {\n    s.cp(\"package-with-implies.js\", \"package.js\");\n    var packOpen = s.read(\"package.js\");\n    _.each(impliesData, function (d) {\n      var repReg = new RegExp(\"~\" + d.placeholder + \"~\", \"g\");\n      packOpen = packOpen.replace(repReg, d.name);\n    });\n    s.write(\"package.js\", packOpen);\n  });\n\n  summary = \"This is a test package\";\n  description = \"Test package.\";\n  var impArr = _.map(impliesData, function (d) {\n    return d.label ? d.name + \" (\" + d.label + \")\" : d.name;\n  });\n  var impStr =\n    impArr[0] + \", \" + impArr[1] + \", \" +\n    impArr[2] + \", \" + impArr[3] + \", \" +\n    impArr[4] + \", \" + impArr[5];\n\n  testShowPackage(s, name, {\n    summary: summary,\n    description: description,\n    implies: impStr,\n    directory: packageDir,\n    defaultVersion: \"local\",\n    git: \"www.github.com/meteor/meteor\",\n    versions: [{ version: \"1.2.1\", directory: packageDir }]\n  });\n\n  // Implies are also dependencies.\n  var deps = _.map(impliesData, function (d) {\n    return { name: d.name, constraint: \"1.0.0\" };\n  });\n  testShowPackageVersion(s, {\n    packageName: name,\n    version: \"1.2.1\",\n    directory: packageDir,\n    description: description,\n    summary: summary,\n    git: \"www.github.com/meteor/meteor\",\n    implies: impStr,\n    dependencies: deps\n  });\n});\n\n// This tests that we get the right excerpt out of the Readme.md in different\n// combinations. It doesn't test publication, because publishing is slow --\n// that's covered in a different test.\nselftest.define(\"show readme excerpt\",  function () {\n  var s = new Sandbox();\n  var name = \"my-local-package\" + utils.randomToken();\n\n  // Create a package without version or summary; check that we can show its\n  // information without crashing.\n  s.createPackage(name, name, \"package-for-show\");\n  var packageDir = files.pathJoin(s.root, \"home\", name);\n\n  // We are just going to change the description in the Readme. Some things\n  // about this package are not going to change, and our test will be more\n  // legible to factor them out here.\n  var basePackageInfo = {\n    summary: \"This is a test package\",\n    defaultVersion: \"local\",\n    versions: [{ version: \"0.9.9\", directory: packageDir }]\n  };\n  var baseVersionInfo = {\n    summary: \"This is a test package\",\n    packageName: name,\n    version: \"0.9.9\",\n    directory: packageDir\n  };\n\n  s.cd(name);\n\n  // By default, we will use the README.md file for documentation.\n  // Start with a blank file. Nothing should show up!\n  s.write(\"README.md\", \"\");\n  testShowPackage(s, name, basePackageInfo);\n  testShowPackageVersion(s, baseVersionInfo);\n\n  // An example of a standard readme.\n  var readme =\n        \"Heading\" + \"\\n\" +\n        \"========\" + \"\\n\" +\n        \"foobar1\" + \"\\n\" +\n        \"\\n\" +\n        \"## Subheading\" + \"\\n\" +\n        \"You should not see this line!\";\n  s.write(\"README.md\", readme);\n  testShowPackage(\n    s, name, _.extend({ description: \"foobar1\" }, basePackageInfo));\n  testShowPackageVersion(\n    s, _.extend({ description: \"foobar1\" }, baseVersionInfo));\n\n  // Another example -- we have hidden the excerpt under a different subheading.\n  readme =\n    \"Heading\" + \"\\n\" +\n    \"========\" + \"\\n\" +\n    \"## Subheading\" + \"\\n\" +\n    \"foobar2\" + \"\\n\" +\n    \"## Another subheading\" + \"\\n\" +\n    \"You should not see this line!\";\n  s.write(\"README.md\", readme);\n  testShowPackage(\n    s, name, _.extend({ description: \"foobar2\" }, basePackageInfo));\n  testShowPackageVersion(\n    s, _.extend({ description: \"foobar2\" }, baseVersionInfo));\n\n  // Generally, people skip a line between the header and the text, and\n  // sometimes, even between headers. (It is part of markdown, in fact.) Let's\n  // make sure that we handle that correctly.\n  readme =\n    \"Heading\" + \"\\n\" +\n    \"========\" + \"\\n\" + \"\\n\" +\n    \"## Subheading\" + \"\\n\" + \"\\n\" +\n    \"foobaz\" + \"\\n\" + \"\\n\" +\n    \"## Another subheading\" + \"\\n\" + \"\\n\" +\n    \"You should not see this line!\";\n  s.write(\"README.md\", readme);\n  testShowPackage(\n    s, name, _.extend({ description: \"foobaz\" }, basePackageInfo));\n  testShowPackageVersion(\n    s, _.extend({ description: \"foobaz\" }, baseVersionInfo));\n\n  // Some formatting in the text.\n  var excerpt =\n        \"Here is a code sample:\" + \"\\n\\n\" +\n        \"```foobar and foobar```\";\n  readme =\n    \"Heading\" + \"\\n\" +\n    \"========\" + \"\\n\" + \"\\n\" +\n    excerpt + \"\\n\\n\" +\n    \"# Subheading\" + \"\\n\" + \"\\n\" +\n    \"## Another subheading\" + \"\\n\" + \"\\n\" +\n    \"You should not see this line!\";\n  s.write(\"README.md\", readme);\n  testShowPackage(\n    s, name, _.extend({ description: excerpt }, basePackageInfo));\n  testShowPackageVersion(\n    s, _.extend({ description: excerpt }, baseVersionInfo));\n\n  // Now, let's try different file specifications for the documentation.\n  var git = \"https:ilovegit.git\";\n  var summary = \"Test summary\";\n  var staging = s.read(\"package-customizable.js\");\n  staging = staging.replace(/~version~/g, \"1.0.0\");\n  staging = staging.replace(/~git~/g, git);\n  staging = staging.replace(/~summary~/g, summary);\n\n  // If we specify null, we have no docs.\n  s.write(\"package.js\", staging.replace(/~documentation~/g, \"null\"));\n  baseVersionInfo = {\n    summary: summary,\n    git: git,\n    packageName: name,\n    version: \"1.0.0\",\n    directory: packageDir\n  };\n  basePackageInfo = {\n    git: git,\n    summary: summary,\n    defaultVersion: \"local\",\n    versions: [{ version: \"1.0.0\", directory: packageDir }]\n  };\n  testShowPackageVersion(s, baseVersionInfo);\n  testShowPackage(s, name, basePackageInfo);\n\n  // If we specify a different file, read that file.\n  s.write(\"package.js\",\n          staging.replace(/~documentation~/g, \"'Meteor-Readme.md'\"));\n  readme = \"A special Readme, just for Meteor.\";\n  s.write(\"Meteor-Readme.md\", \"Title\\n==\\n\" + readme);\n  testShowPackageVersion(s,\n    _.extend({ description: readme }, baseVersionInfo));\n  testShowPackage(s, name,\n    _.extend({ description: readme }, basePackageInfo));\n\n  // If we specify a non-existent file, tell us.\n  s.write(\"package.js\",\n          staging.replace(/~documentation~/g, \"'NOTHING'\"));\n  var run = s.run(\"show\", name);\n  run.matchErr(\"Documentation not found\");\n  run.expectExit(1);\n  run = s.run(\"show\", name + \"@1.0.0\");\n  run.matchErr(\"Documentation not found\");\n  run.expectExit(1);\n});\n"
  },
  {
    "path": "tools/tests/packages/fake-accounts-base/fake-accounts-base-tests.js",
    "content": "// Write your tests here!\n// Here is an example.\nTinytest.add('example', function (test) {\n  test.equal(true, true);\n});\n"
  },
  {
    "path": "tools/tests/packages/fake-accounts-base/fake-accounts-base.js",
    "content": "// Write your package code here!\nconsole.log(\"overriding accounts-base!\");\n"
  },
  {
    "path": "tools/tests/packages/fake-accounts-base/package.js",
    "content": "// This package overrides the accounts-base package\n// by using the name attribute in Package.describe.\n\nPackage.describe({\n  name: \"accounts-base\",\n  documentation: null\n});\n\nPackage.onUse(function(api) {\n//  api.versionsFrom('METEOR@0.9.0-rc9');\n  api.addFiles('fake-accounts-base.js');\n});\n\nPackage.onTest(function(api) {\n  api.use('tinytest');\n  api.use('accounts-base');\n  api.addFiles('fake-accounts-base-tests.js');\n});\n"
  },
  {
    "path": "tools/tests/packages/package-for-show/README.md",
    "content": "## Package for show\n\nTest package.\n\n# First heading\n\nSomething here, but we should never see it.\n\n# second heading\n\nSomething here too, but we do not care."
  },
  {
    "path": "tools/tests/packages/package-for-show/package-completely-empty.js",
    "content": "Package.describe({\n  documentation: null\n});\n"
  },
  {
    "path": "tools/tests/packages/package-for-show/package-customizable.js",
    "content": "Package.describe({\n  name: \"~package-name~\", // replaced via `Sandbox.prototype.createPackage`\n  summary: '~summary~',\n  version: '~version~',\n  git: '~git~',\n  documentation: ~documentation~\n});\n"
  },
  {
    "path": "tools/tests/packages/package-for-show/package-rc-version.js",
    "content": "Package.describe({\n  name: \"~package-name~\", // replaced via `Sandbox.prototype.createPackage`\n  summary: 'This is a pre-release version of this package!',\n  version: '1.3.0-rc.1',\n  git: 'www.github.com/fake-user/meteor',\n  documentation: null\n});\n"
  },
  {
    "path": "tools/tests/packages/package-for-show/package-with-deps.js",
    "content": "Package.describe({\n  name: \"~package-name~\", // replaced via `Sandbox.prototype.createPackage`\n  summary: 'This is a test package with dependencies',\n  version: '1.2.0',\n  git: 'www.github.com/meteor/meteor',\n  documentation: null\n});\n\nPackage.onUse(function(api) {\n  // Test that dependencies show up.\n  api.use(\"~baseDependency~@1.0.0\");\n  // Test that constraints and weak dependencies show up correctly.\n  api.use(\"~weakDependency~@=1.0.0\", { weak: true });\n});\n"
  },
  {
    "path": "tools/tests/packages/package-for-show/package-with-exports.js",
    "content": "Package.describe({\n  name: \"~package-name~\", // replaced via `Sandbox.prototype.createPackage`\n  summary: 'This is a test package',\n  version: '1.0.1',\n  git: 'www.github.com/meteor/meteor'\n});\n\nPackage.onUse(function(api) {\n  api.export(\"A\");\n  api.export(\"B\", 'server');\n  api.export(\"C\", 'client');\n  api.export(\"D\", \"web.browser\");\n  api.export(\"E\", \"web.cordova\");\n  api.export(\"G\", \"web.cordova\");\n  api.export(\"G\", \"server\");\n});\n"
  },
  {
    "path": "tools/tests/packages/package-for-show/package-with-git.js",
    "content": "Package.describe({\n  name: \"~package-name~\", // replaced via `Sandbox.prototype.createPackage`\n  summary: 'This is a test package',\n  version: '1.0.0',\n  git: 'www.github.com/meteor/meteor',\n  documentation: null\n});\n"
  },
  {
    "path": "tools/tests/packages/package-for-show/package-with-implies.js",
    "content": "Package.describe({\n  name: \"~package-name~\", // replaced via `Sandbox.prototype.createPackage`\n  summary: 'This is a test package',\n  version: '1.2.1',\n  git: 'www.github.com/meteor/meteor'\n});\n\nPackage.onUse(function(api) {\n  api.imply(\"~A~@1.0.0\");\n  api.imply(\"~B~@1.0.0\", 'server');\n  api.imply(\"~C~@1.0.0\", 'client');\n  api.imply(\"~D~@1.0.0\", 'web.browser');\n  api.imply(\"~E~@1.0.0\", 'web.cordova');\n  api.imply(\"~G~@1.0.0\", 'web.cordova');\n  api.imply(\"~G~@1.0.0\", 'server');\n});\n"
  },
  {
    "path": "tools/tests/packages/package-for-show/package.js",
    "content": "Package.describe({\n  name: \"~package-name~\", // replaced via `Sandbox.prototype.createPackage`\n  summary: 'This is a test package',\n  version: '0.9.9'\n});\n"
  },
  {
    "path": "tools/tests/packages/package-of-two-versions/package-version.js",
    "content": "Package.describe({\n  name: \"~package-name~\", // replaced via `Sandbox.prototype.createPackage`\n  summary: \"Test package.\",\n  version: \"~version~\",\n  documentation: null\n});\n"
  },
  {
    "path": "tools/tests/packages/package-of-two-versions/package.js",
    "content": "Package.describe({\n  name: \"~package-name~\", // replaced via `Sandbox.prototype.createPackage`\n  summary: \"Test package.\",\n  version: \"1.0.0\",\n  documentation: null\n});\n"
  },
  {
    "path": "tools/tests/packages/package-with-colons/package.js",
    "content": "Package.describe({\n  name: \"~package-name~\", // replaced via `Sandbox.prototype.createPackage`\n  summary: ' /* Fill me in! */ ',\n  version: '1.0.19',\n  git: ' /* Fill me in! */ ',\n  documentation: null\n});\n\nNpm.depends({\n  // An npm package published by sashko that has some colons in the paths\n  // if you would like to edit it, download it with `npm install` and then\n  // publish a new version\n  \"test-colons2\": \"1.0.2\"\n});\n"
  },
  {
    "path": "tools/tests/packages/package-with-npm/package.js",
    "content": "Package.describe({\n  name: \"~package-name~\", // replaced via `Sandbox.prototype.createPackage`\n  summary: \"Test package with a binary npm dependency\",\n  version: \"1.0.0\",\n  documentation: null\n});\n\n// bcrypt is an npm package that\n// has different binaries for differnet architectures.\nNpm.depends({\n  bcrypt: '0.7.7'\n});\n"
  },
  {
    "path": "tools/tests/parse-stack-test.js",
    "content": "import selftest from '../tool-testing/selftest.js';\nimport { parse, markBottom } from '../utils/parse-stack.js';\nimport _ from 'underscore';\nimport Fiber from 'fibers';\nimport Future from 'fibers/future';\nimport files from '../fs/files.js';\n\nselftest.define(\"parse-stack - parse stack traces without fibers\", () => {\n  const err = new Error();\n  const parsedStack = parse(err).outsideFiber;\n\n  const firstFilePath = files.convertToStandardPath(parsedStack[0].file);\n  selftest.expectEqual(_.last(firstFilePath.split(\"/\")), \"parse-stack-test.js\");\n\n  const lastFilePath = files.convertToStandardPath(_.last(parsedStack).file);\n  selftest.expectEqual(_.last(lastFilePath.split(\"/\")), \"selftest.js\");\n\n  markBottom(() => {\n    const markedErr = new Error();\n\n    const {\n      outsideFiber,\n      insideFiber\n    } = parse(markedErr);\n\n    // Don't return an empty array\n    selftest.expectEqual(insideFiber, undefined);\n\n    // The stack trace should only contain this one function since we marked the\n    // bottom\n    selftest.expectEqual(outsideFiber.length, 1);\n\n    const firstOutsideFiberPath =\n      files.convertToStandardPath(outsideFiber[0].file);\n    selftest.expectEqual(_.last(firstOutsideFiberPath.split(\"/\")),\n      \"parse-stack-test.js\");\n  })();\n});\n\nselftest.define(\"parse-stack - parse stack traces with fibers\", () => {\n  const parsedStack = parse({ stack: exampleStackTrace });\n\n  selftest.expectEqual(parsedStack.insideFiber[0].file, \"template-compiler.js\");\n  selftest.expectEqual(_.last(parsedStack.outsideFiber).file, \"template-compiler.js\");\n});\n\n// XXX I don't know how to actually create one of the crazy fiber stack traces\n// inside this test environment, so I have a copy-pasted one below that I\n// actually encountered.\nconst exampleStackTrace = `TypeError: object is not a function\n    at Object.Future.wait (/Users/sashko/git/meteor/dev_bundle/lib/node_modules/fibers/future.js:395:16)\n    at TemplateCompiler.processFilesForTarget (caching-compiler.js:312:12)\n    at TemplateCompiler.processFilesForTarget (template-compiler.js:28:32)\n    at __bottom_mark__ (/Users/sashko/git/meteor/tools/parse-stack.js:92:14)\n    at /Users/sashko/git/meteor/tools/isobuild/compiler-plugin.js:141:13\n    at /Users/sashko/git/meteor/tools/buildmessage.js:356:18\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:349:34\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:347:23\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at Object.enterJob (/Users/sashko/git/meteor/tools/buildmessage.js:321:26)\n    at /Users/sashko/git/meteor/tools/isobuild/compiler-plugin.js:130:22\n    at Function.time (/Users/sashko/git/meteor/tools/profile.js:232:28)\n    at /Users/sashko/git/meteor/tools/isobuild/compiler-plugin.js:129:15\n    at Function._.each._.forEach (/Users/sashko/git/meteor/dev_bundle/lib/node_modules/underscore/underscore.js:87:22)\n    at [object Object]._.extend.runCompilerPlugins (/Users/sashko/git/meteor/tools/isobuild/compiler-plugin.js:118:7)\n    at [object Object]._.extend._runCompilerPlugins (/Users/sashko/git/meteor/tools/isobuild/bundler.js:702:22)\n    at /Users/sashko/git/meteor/tools/isobuild/bundler.js:504:34\n    at /Users/sashko/git/meteor/tools/buildmessage.js:356:18\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:349:34\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:347:23\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at Object.enterJob (/Users/sashko/git/meteor/tools/buildmessage.js:321:26)\n    at [object Object]._.extend.make (/Users/sashko/git/meteor/tools/isobuild/bundler.js:498:18)\n    at /Users/sashko/git/meteor/tools/isobuild/bundler.js:2044:14\n    at /Users/sashko/git/meteor/tools/isobuild/bundler.js:2126:20\n    at Array.forEach (native)\n    at Function._.each._.forEach (/Users/sashko/git/meteor/dev_bundle/lib/node_modules/underscore/underscore.js:79:11)\n    at /Users/sashko/git/meteor/tools/isobuild/bundler.js:2125:7\n    at /Users/sashko/git/meteor/tools/buildmessage.js:268:13\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:261:29\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:259:18\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:250:23\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at Object.capture (/Users/sashko/git/meteor/tools/buildmessage.js:249:19)\n    at Object.exports.bundle (/Users/sashko/git/meteor/tools/isobuild/bundler.js:2029:31)\n    at /Users/sashko/git/meteor/tools/run-app.js:557:36\n    at time (/Users/sashko/git/meteor/tools/profile.js:232:28)\n    at Function.run (/Users/sashko/git/meteor/tools/profile.js:377:12)\n    at bundleApp (/Users/sashko/git/meteor/tools/run-app.js:547:34)\n    at [object Object]._.extend._runOnce (/Users/sashko/git/meteor/tools/run-app.js:600:35)\n    at [object Object]._.extend._fiber (/Users/sashko/git/meteor/tools/run-app.js:848:28)\n    at /Users/sashko/git/meteor/tools/run-app.js:402:12\n    - - - - -\n    at TemplateCompiler.compileOneFile (template-compiler.js:43:23)\n    at caching-compiler.js:292:32\n    at /Users/sashko/git/meteor/packages/caching-compiler/.npm/package/node_modules/async/lib/async.js:182:20\n    at replenish (/Users/sashko/git/meteor/packages/caching-compiler/.npm/package/node_modules/async/lib/async.js:317:21)\n    at /Users/sashko/git/meteor/packages/caching-compiler/.npm/package/node_modules/async/lib/async.js:328:15\n    at Object.async.forEachLimit.async.eachLimit (/Users/sashko/git/meteor/packages/caching-compiler/.npm/package/node_modules/async/lib/async.js:221:35)\n    at TemplateCompiler.processFilesForTarget (caching-compiler.js:277:11)\n    at TemplateCompiler.processFilesForTarget (template-compiler.js:28:32)\n    at __bottom_mark__ (/Users/sashko/git/meteor/tools/parse-stack.js:92:14)\n    at /Users/sashko/git/meteor/tools/isobuild/compiler-plugin.js:141:13\n    at /Users/sashko/git/meteor/tools/buildmessage.js:356:18\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:349:34\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:347:23\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at Object.enterJob (/Users/sashko/git/meteor/tools/buildmessage.js:321:26)\n    at /Users/sashko/git/meteor/tools/isobuild/compiler-plugin.js:130:22\n    at Function.time (/Users/sashko/git/meteor/tools/profile.js:232:28)\n    at /Users/sashko/git/meteor/tools/isobuild/compiler-plugin.js:129:15\n    at Function._.each._.forEach (/Users/sashko/git/meteor/dev_bundle/lib/node_modules/underscore/underscore.js:87:22)\n    at [object Object]._.extend.runCompilerPlugins (/Users/sashko/git/meteor/tools/isobuild/compiler-plugin.js:118:7)\n    at [object Object]._.extend._runCompilerPlugins (/Users/sashko/git/meteor/tools/isobuild/bundler.js:702:22)\n    at /Users/sashko/git/meteor/tools/isobuild/bundler.js:504:34\n    at /Users/sashko/git/meteor/tools/buildmessage.js:356:18\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:349:34\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:347:23\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at Object.enterJob (/Users/sashko/git/meteor/tools/buildmessage.js:321:26)\n    at [object Object]._.extend.make (/Users/sashko/git/meteor/tools/isobuild/bundler.js:498:18)\n    at /Users/sashko/git/meteor/tools/isobuild/bundler.js:2044:14\n    at /Users/sashko/git/meteor/tools/isobuild/bundler.js:2126:20\n    at Array.forEach (native)\n    at Function._.each._.forEach (/Users/sashko/git/meteor/dev_bundle/lib/node_modules/underscore/underscore.js:79:11)\n    at /Users/sashko/git/meteor/tools/isobuild/bundler.js:2125:7\n    at /Users/sashko/git/meteor/tools/buildmessage.js:268:13\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:261:29\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:259:18\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at /Users/sashko/git/meteor/tools/buildmessage.js:250:23\n    at [object Object]._.extend.withValue (/Users/sashko/git/meteor/tools/fiber-helpers.js:114:14)\n    at Object.capture (/Users/sashko/git/meteor/tools/buildmessage.js:249:19)\n    at Object.exports.bundle (/Users/sashko/git/meteor/tools/isobuild/bundler.js:2029:31)\n    at /Users/sashko/git/meteor/tools/run-app.js:557:36\n    at time (/Users/sashko/git/meteor/tools/profile.js:232:28)\n    at Function.run (/Users/sashko/git/meteor/tools/profile.js:377:12)\n    at bundleApp (/Users/sashko/git/meteor/tools/run-app.js:547:34)\n    at [object Object]._.extend._runOnce (/Users/sashko/git/meteor/tools/run-app.js:600:35)\n    at [object Object]._.extend._fiber (/Users/sashko/git/meteor/tools/run-app.js:848:28)\n    at /Users/sashko/git/meteor/tools/run-app.js:402:12`;\n"
  },
  {
    "path": "tools/tests/releases.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar files = require('../fs/files.js');\nvar catalog = require('../packaging/catalog/catalog.js');\n\nvar DEFAULT_RELEASE_TRACK = catalog.DEFAULT_TRACK;\n\n// XXX: Why is this an internet using test? Because our warehouse is a\n// hackhackhack. If we clean up the hackhackhackhack, then this does not need\n// the internets. (Or, to be more specific: our warehouse code tries to fetch\n// the packages from the internet. If we could fool it into using local packages\n// instead, or think that it alreayd has the packages, it would be ok). (This is\n// because it calls 'create' from a warehouse, to be specific).\nselftest.define(\"springboard\", ['checkout', 'net', 'custom-warehouse'], function () {\n  var s = new Sandbox({\n    warehouse: {\n      v1: { },\n      v2: { recommended: true }\n    }\n  });\n  var run;\n\n  // If run not in an app dir, runs the latest version ...\n  run = s.run(\"--version\");\n  run.read('Meteor v2\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  // ... unless you asked for a different one.\n  run = s.run(\"--version\", \"--release\", DEFAULT_RELEASE_TRACK + \"@v1\");\n  run.read('Meteor v1\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  // Apps are created with the latest release ...\n  run = s.run(\"create\", \"myapp\");\n  run.waitSecs(5);\n  run.expectExit(0);\n  s.cd('myapp', function () {\n    run = s.run(\"--version\");\n    run.read('Meteor v2\\n');\n    run.expectExit(0);\n  });\n\n  // ... unless you asked for a different one.\n  run = s.run(\"create\", \"myapp2\", \"--release\", DEFAULT_RELEASE_TRACK + \"@v1\").expectExit(0);\n  s.cd('myapp2', function () {\n    run = s.run(\"--version\");\n    run.read('Meteor v1\\n');\n    run.expectExit(0);\n  });\n\n  // Suppose you ask for a release that doesn't exist.\n  s.set('METEOR_TEST_FAIL_RELEASE_DOWNLOAD', 'not-found');\n  run = s.run(\"--release\", \"weird\");\n  run.readErr(\"Meteor weird: unknown release.\\n\");\n  run.expectEnd();\n  run.expectExit(1);\n\n  // Suppose you're offline and you ask for a release you don't have\n  // cached.\n  // XXX On the refreshpolicy branch, we removed some of the support\n  // code for this test. Make sure we get it to pass before merging.\n  s.set('METEOR_TEST_FAIL_RELEASE_DOWNLOAD', 'offline');\n  run = s.run(\"--release\", \"weird\");\n  run.matchErr(\"offline\");\n  run.matchErr(\"weird: unknown release\");\n  run.expectExit(1);\n\n  // Project asking for nonexistent release.\n  s.cd('myapp2', function () {\n    s.write(\".meteor/release\", \"strange\");\n    s.set('METEOR_TEST_FAIL_RELEASE_DOWNLOAD', 'not-found');\n    run = s.run();\n    run.matchErr(\"uses Meteor strange\");\n\n    run.matchErr(/don't\\s+have\\s+it\\s+either/);\n    run.expectExit(1);\n\n    // You're offline and project asks for non-cached release.\n    s.set('METEOR_TEST_FAIL_RELEASE_DOWNLOAD', 'offline');\n    run = s.run();\n    run.matchErr(\"offline\");\n    run.matchErr(/it\\s+uses\\s+Meteor\\s+strange/);\n    run.matchErr(/don't have that version/);\n    run.matchErr(/of Meteor installed/);\n    run.matchErr(/update servers/);\n    run.expectExit(1);\n\n    // You create an app from a checkout, and then try to use it from an\n    // install without setting a release on it.\n    s.unset('METEOR_TEST_FAIL_RELEASE_DOWNLOAD');\n    s.write(\".meteor/release\", \"none\");\n    run = s.run(\"--requires-release\");\n    run.matchErr(\"must specify\");\n    run.matchErr(\"permanently set\");\n    run.expectExit(1);\n\n    // As previous, but you pass --release to manually pick a release.\n    run = s.run(\"--version\", \"--release\", \"v1\");\n    run.expectExit(0);\n    run.forbidAll(\"must specify\");\n    run.forbidAll(\"permanently set\");\n\n    // You use modern Meteor with a super old release from the dark ages\n    // before the .meteor/release file. You get an error.\n    s.unlink('.meteor/release');\n    run = s.run(\"--version\");\n    run.matchErr(\"does not have a .meteor/release file\");\n    run.matchErr(\"edit the .meteor/release file\");\n    run.expectExit(1);\n\n    // .meteor/release exists but is empty. You get an error.\n    s.write(\".meteor/release\", \"\\n\");\n    run = s.run(\"--version\");\n    run.matchErr(\"release file which is empty\");\n    run.expectExit(1);\n\n    // XXX Test springboard to pre-0.9.0 release\n  });\n});\n\n// XXX: Why is this an internet using test? Because our warehouse is a\n// hackhackhack. If we clean up the hackhackhackhack, then this does not need\n// the internets. (Or, to be more specific: our warehouse code tries to fetch\n// the packages from the internet. If we could fool it into using local packages\n// instead, or think that it already has the packages, it would be ok).\nselftest.define(\"writing versions file\", ['checkout', 'net', 'custom-warehouse'], function () {\n  var s = new Sandbox({\n    warehouse: {\n      v1: { recommended: true},\n      v2: { recommended: true }\n    }\n  });\n  var run;\n\n  // Create an app with the latest release.\n  run = s.run(\"create\", \"myapp\");\n  run.waitSecs(15);\n  run.expectExit(0);\n  s.cd('myapp');\n  run = s.run(\"--version\");\n  run.read('Meteor v2\\n');\n  run.expectExit(0);\n\n  // Check the contents of the versions file.\n  var versions = s.read('.meteor/versions');\n  if (!versions) {\n    selftest.fail(\"Versions file NOT written in new app.\");\n  }\n\n  // Remove the versions file.\n  s.unlink('.meteor/versions');\n\n  // Run with --release, do not change versions file.\n  run = s.run(\"list\", \"--release\", \"v1\");\n  run.expectExit(0);\n  versions = s.read('.meteor/versions');\n  if (versions) {\n    selftest.fail(\"Versions file written with --release.\");\n  }\n\n  // Update with --release.\n  run = s.run(\"update\", \"--release\", \"v1\");\n  run.expectExit(0);\n\n  // version file should exist.\n  versions = s.read('.meteor/versions');\n  if (!versions) {\n    selftest.fail(\"Versions file NOT written after update\");\n  }\n\n});\n\n\nselftest.define(\"checkout\", ['checkout'], function () {\n  var s = new Sandbox;\n  var run;\n\n  // Can't specify a release when running Meteor from a checkout\n  run = s.run(\"--release\", \"v1\");\n  run.waitSecs(5);\n  run.matchErr(\"Can't specify\");\n  run.expectExit(1);\n\n  // You get a warning banner when the checkout overrides the release\n  // that an app is pinned to\n  s.createApp('myapp', 'standard-app');\n  s.cd('myapp', function () {\n    s.write(\".meteor/release\", \"something\");\n    run = s.run(\"list\");\n    run.readErr(\"=> Running Meteor from a checkout\");\n    run.matchErr(\"project version\");\n    run.matchErr(\"(Meteor something)\\n\");\n    run.expectExit(0);\n  });\n});\n\n\nselftest.define(\"download and springboard to pre-0.9.0 release\", ['net', 'slow', 'custom-warehouse'], function () {\n  var s, run;\n\n  if (files.inCheckout()) {\n    s = new Sandbox({ warehouse: { v1: { tools: 'tools1', latest: true } } });\n  } else {\n    s = new Sandbox;\n  }\n\n  // End-to-end, online test of downloading and springboarding. This\n  // release was built from the\n  // 'release/release-used-to-test-springboarding' tag in GitHub. All\n  // it does is print this string and exit.\n  run = s.run(\"--release\", \"release-used-to-test-springboarding\");\n  run.waitSecs(1000);\n\n  if (process.platform === \"win32\") {\n    run.matchErr(\"Meteor on Windows does not support\");\n  } else {\n    run.match(\"THIS IS A FAKE RELEASE ONLY USED TO TEST ENGINE SPRINGBOARDING\");\n  }\n\n  run.expectExit();\n});\n\n\nselftest.define(\"unknown release\", ['custom-warehouse'], function () {\n  var s = new Sandbox({\n    warehouse: {\n      v2: { recommended: true }\n    }\n  });\n s.set(\"METEOR_OFFLINE_CATALOG\", \"t\");\n  var run;\n\n  s.createApp('myapp', 'packageless', { dontPrepareApp: true });\n  s.cd('myapp');\n  run = s.run(\"--release\", \"bad\");\n  run.matchErr(\"Meteor bad: unknown release\");\n\n  // METEOR in the release file.\n  s.write('.meteor/release', DEFAULT_RELEASE_TRACK + \"@0.9-bad\");\n  run = s.run();\n  run.matchErr(\n    /This\\s+project\\s+says\\s+that\\s+it\\s+uses\\s+Meteor\\s+0.9-bad,\\s+but/);\n\n  // No METEOR in the release file.\n  s.write('.meteor/release', \"0.9.x-bad\");\n  run = s.run();\n  run.matchErr(\n    /This\\s+project\\s+says\\s+that\\s+it\\s+uses\\s+Meteor\\s+0.9.x-bad,\\s+but/);\n\n  // Non-standard track\n  s.write('.meteor/release', \"FOO@bad\");\n  run = s.run();\n  run.matchErr(\n    /This\\s+project\\s+says\\s+that\\s+it\\s+uses\\s+Meteor\\s+release\\s+FOO@bad,\\s+but/);\n\n});\n"
  },
  {
    "path": "tools/tests/run.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar utils = require('../utils/utils.js');\nvar net = require('net');\nvar Future = require('fibers/future');\nvar _ = require('underscore');\nvar files = require('../fs/files.js');\nvar catalog = require('../packaging/catalog/catalog.js');\n\nvar DEFAULT_RELEASE_TRACK = catalog.DEFAULT_TRACK;\n\nvar MONGO_LISTENING =\n  { stdout: \" [initandlisten] waiting for connections on port\" };\n\nvar SIMPLE_WAREHOUSE = {\n  v1: { },\n  v2: { recommended: true },\n  v3: { }\n};\n\nselftest.define(\"run\", function () {\n  var s = new Sandbox({ fakeMongo: true });\n  var run;\n\n  // Starting a run\n  s.createApp(\"myapp\", \"standard-app\");\n  s.cd(\"myapp\");\n  s.set(\"METEOR_TEST_TMP\", files.convertToOSPath(files.mkdtemp()));\n  run = s.run();\n  run.match(\"myapp\");\n  run.match(\"proxy\");\n  run.tellMongo(MONGO_LISTENING);\n  run.match(\"MongoDB\");\n  run.match(\"your app\");\n  run.waitSecs(5);\n  run.match(\"running at\");\n  run.match(\"localhost\");\n\n  // File change\n  s.write(\"empty.js\", \"\");\n  run.waitSecs(2);\n  run.match(\"restarted\");\n  s.write(\"empty.js\", \" \");\n  run.waitSecs(2);\n  run.match(\"restarted\");\n  // XXX want app to generate output so that we can see restart counter reset\n\n  // Crashes\n  s.write(\"crash.js\", \"process.exit(42);\");\n  run.waitSecs(5);\n  run.match(\"with code: 42\");\n  run.waitSecs(5);\n  run.match(\"is crashing\");\n  s.unlink(\"crash.js\");\n  run.waitSecs(5);\n  run.match(\"Modified\");\n  run.waitSecs(5);\n  run.match(\"restarted\");\n  s.write(\"empty.js\", \"\");\n  run.waitSecs(5);\n  // We used to see the restart counter reset but right now restart messages\n  // don't coalesce due to intermediate use of the progress bar.\n  run.match(\"restarted\");\n  s.write(\"crash.js\", \"process.kill(process.pid, 'SIGKILL');\");\n  run.waitSecs(5);\n  run.match(\"Exited\");\n  run.match(\"is crashing\");\n\n  // Bundle failure\n  s.unlink(\"crash.js\");\n  s.write(\"junk.css\", \"/*\");\n  run.waitSecs(5);\n  run.match(\"Modified\");\n  run.match(\"prevented startup\");\n  run.match(\"End of comment missing\");\n  run.match(\"file change\");\n\n  // Back to working\n  s.unlink(\"junk.css\");\n  run.waitSecs(5);\n  run.match(\"restarted\");\n\n  // Crash just once, then restart successfully\n  s.write(\"crash.js\", `\nvar fs = Npm.require('fs');\nvar path = Npm.require('path');\nvar crashmark = path.join(process.env.METEOR_TEST_TMP, 'crashed');\ntry {\n  fs.readFileSync(crashmark);\n} catch (e) {\n  fs.writeFileSync(crashmark);\n  process.exit(137);\n}`);\n  run.waitSecs(5);\n  run.match(\"with code: 137\");\n  run.waitSecs(5);\n  run.match(\"restarted\");\n  run.stop();\n  s.unlink(\"crash.js\");\n\n  run = s.run('--settings', 's.json');\n  run.waitSecs(5);\n  run.match('s.json: file not found (settings file)');\n  run.match('Waiting for file change');\n  s.write('s.json', '}');\n  run.match('s.json: parse error reading settings file');\n  run.match('Waiting for file change');\n  s.write('s.json', '{}');\n  run.match('App running at');\n  run.stop();\n\n  // How about a bundle failure right at startup\n  s.write(\"junk.css\", \"/*\");\n  run = s.run();\n  run.tellMongo(MONGO_LISTENING);\n  run.waitSecs(5);\n  run.match(\"prevented startup\");\n  run.match(\"End of comment missing\");\n  run.match(\"file change\");\n  s.unlink(\"junk.css\");\n  run.waitSecs(5);\n  run.match(\"restarted\");\n  run.stop();\n\n// XXX --port, --production, --raw-logs, --settings, --program\n});\n\nselftest.define(\"run --once\", [\"yet-unsolved-windows-failure\"], function () {\n  var s = new Sandbox({ fakeMongo: true });\n  var run;\n\n  s.createApp(\"onceapp\", \"once\");\n  s.cd(\"onceapp\");\n\n  // Basic run --once\n  s.set(\"RUN_ONCE_OUTCOME\", \"exit\");\n  run = s.run(\"--once\");\n  run.tellMongo(MONGO_LISTENING);\n  run.waitSecs(5);\n  run.match(\"once test\\n\");\n  run.expectExit(123);\n\n  // run --once, exit on signal\n  s.set(\"RUN_ONCE_OUTCOME\", \"kill\");\n  run = s.run(\"--once\");\n  run.tellMongo(MONGO_LISTENING);\n  run.waitSecs(5);\n  run.match(\"once test\\n\");\n  run.matchErr(\"Killed (SIGKILL)\\n\");\n  run.expectExit(255);\n\n  // run --once, bundle failure\n  s.set(\"RUN_ONCE_OUTCOME\", \"exit\");\n  s.write(\"junk.css\", \"/*\");\n  run = s.run(\"--once\");\n  run.waitSecs(5);\n  run.matchErr(\"Build failed\");\n  run.matchErr(\"End of comment missing\");\n  run.expectExit(254);\n  s.unlink(\"junk.css\");\n\n  // file changes don't make it restart\n  s.set(\"RUN_ONCE_OUTCOME\", \"hang\");\n  run = s.run(\"--once\");\n  run.tellMongo(MONGO_LISTENING);\n  run.waitSecs(5);\n  run.match(\"once test\\n\");\n  s.write('empty.js', 'null');\n  var originalRelease = s.read('.meteor/release');\n  s.write('.meteor/release', 'v1');\n  utils.sleepMs(2000); // sorry, hard to avoid\n  run.stop();\n  run.forbidAll(\"updated\");\n  s.unlink('empty.js');\n  s.write('.meteor/release', originalRelease);\n\n  // Try it with a real Mongo. Make sure that it actually starts one.\n  s = new Sandbox;\n  s.createApp(\"onceapp\", \"once\");\n  s.cd(\"onceapp\");\n  s.set(\"RUN_ONCE_OUTCOME\", \"mongo\");\n  run = s.run(\"--once\");\n  run.waitSecs(30);\n  run.expectExit(86);\n});\n\nselftest.define(\"run errors\", function () {\n  var s = new Sandbox;\n  s.createApp(\"myapp\", \"standard-app\");\n  s.cd(\"myapp\");\n\n  // Prevent mongod from starting up.  (Note that \"127.0.0.1\" matches the\n  // interface that mongo uses.)\n  var proxyPort = utils.randomPort();\n  var mongoPort = proxyPort + 1;\n  var f = new Future;\n  var server = net.createServer().listen(mongoPort, \"127.0.0.1\", f.resolver());\n  f.wait();\n\n  var run = s.run(\"-p\", proxyPort);\n  _.times(2, function () {\n    run.waitSecs(30);\n    run.match(\"Unexpected mongo exit code 48. Restarting.\");\n  });\n  run.waitSecs(3);\n  run.match(\"Can't start Mongo server\");\n  run.match(\"MongoDB exited because its port was closed\");\n  run.match(\"running in the same project.\\n\");\n  run.expectEnd();\n  run.forbid(\"Started MongoDB\");\n  run.expectExit(254);\n\n  f = new Future;\n  server.close(f.resolver());\n  f.wait();\n\n  // This time, prevent the proxy from starting. (This time, leaving out the\n  // interface name matches.)\n  f = new Future;\n  server = net.createServer().listen(proxyPort, f.resolver());\n  f.wait();\n\n  run = s.run(\"-p\", proxyPort);\n  run.waitSecs(3);\n  run.match(/Can't listen on port.*another Meteor/);\n  run.expectExit(254);\n\n  f = new Future;\n  server.close(f.resolver());\n  f.wait();\n});\n\nselftest.define(\"update during run\", [\"checkout\", 'custom-warehouse'], function () {\n  var s = new Sandbox({\n    warehouse: SIMPLE_WAREHOUSE,\n    fakeMongo: true\n  });\n  var run;\n\n  s.createApp(\"myapp\", \"packageless\", { release: DEFAULT_RELEASE_TRACK + '@v1' });\n  s.cd(\"myapp\");\n\n  // If the app version changes, we exit with an error message.\n  run = s.run();\n  run.tellMongo(MONGO_LISTENING);\n  run.waitSecs(10);\n  run.match('localhost:3000');\n  s.write('.meteor/release', DEFAULT_RELEASE_TRACK + '@v2');\n  run.matchErr('to Meteor v2 from Meteor v1');\n  run.expectExit(254);\n\n  // But not if the release was forced (case 1)\n  s.write('.meteor/release', DEFAULT_RELEASE_TRACK + '@v1');\n  run = s.run(\"--release\", DEFAULT_RELEASE_TRACK + \"@v3\");\n  run.tellMongo(MONGO_LISTENING);\n  run.waitSecs(2);\n  run.match('localhost:3000');\n  s.write('.meteor/release', DEFAULT_RELEASE_TRACK + '@v2');\n  s.write('empty.js', '');\n  run.waitSecs(2);\n  run.match('restarted');\n  run.stop();\n  run.forbidAll(\"updated\");\n\n  // But not if the release was forced (case 2)\n  s.write('.meteor/release', DEFAULT_RELEASE_TRACK + '@v1');\n  run = s.run(\"--release\", DEFAULT_RELEASE_TRACK + \"@v1\");\n  run.tellMongo(MONGO_LISTENING);\n  run.waitSecs(2);\n  run.match('localhost:3000');\n  s.write('.meteor/release', DEFAULT_RELEASE_TRACK + '@v2');\n  s.write('empty.js', '');\n  run.waitSecs(2);\n  run.match('restarted');\n  run.stop();\n  run.forbidAll(\"updated\");\n\n  // Nor do we do it if you're running from a checkout\n  s = new Sandbox({ fakeMongo: true });\n  s.createApp(\"myapp\", \"standard-app\");\n  s.cd(\"myapp\");\n\n  s.write('.meteor/release', DEFAULT_RELEASE_TRACK + '@v1');\n  run = s.run();\n  run.tellMongo(MONGO_LISTENING);\n  run.waitSecs(2);\n  run.match('localhost:3000');\n  s.write('.meteor/release', DEFAULT_RELEASE_TRACK + '@v2');\n  s.write('empty.js', '');\n  run.waitSecs(2);\n  run.match('restarted');\n  run.stop();\n  run.forbidAll(\"updated\");\n});\n\nselftest.define(\"run with mongo crash\", [\"checkout\"], function () {\n  var s = new Sandbox({ fakeMongo: true });\n  var run;\n\n  s.createApp(\"myapp\", \"standard-app\");\n  s.cd(\"myapp\");\n\n  // Kill mongod three times.  See that it gives up and quits.\n  run = s.run();\n  run.tellMongo(MONGO_LISTENING);\n  run.waitSecs(2);\n  run.match('localhost:3000/\\n');\n\n  if (process.platform === \"win32\") {\n    run.match('Type Control-C twice to stop.\\n\\n');\n  }\n\n  run.tellMongo({exit: 23});\n  run.read('Unexpected mongo exit code 23. Restarting.\\n');\n  run.tellMongo({exit: 46});\n  run.read('Unexpected mongo exit code 46. Restarting.\\n');\n  run.tellMongo({exit: 47});\n  run.read('Unexpected mongo exit code 47. Restarting.\\n');\n  run.read(\"Can't start Mongo server.\\n\");\n  run.read(\"MongoDB exited due to excess clock skew\\n\");\n  run.expectEnd();\n  run.expectExit(254);\n\n  // Now create a build failure. Make sure that killing mongod three times\n  // *also* successfully quits even if we're waiting on file change.\n  s.write('bad.css', '/*');\n  run = s.run();\n  run.tellMongo(MONGO_LISTENING);\n  run.waitSecs(2);\n  run.match(\"prevented startup\");\n  run.match(\"file change.\\n\");\n  run.tellMongo({exit: 23});\n  run.match('Unexpected mongo exit code 23. Restarting.\\n');\n  run.tellMongo({exit: 46});\n  run.read('Unexpected mongo exit code 46. Restarting.\\n');\n  run.tellMongo({exit: 47});\n  run.read('Unexpected mongo exit code 47. Restarting.\\n');\n  run.read(\"Can't start Mongo server.\\n\");\n  run.read(\"MongoDB exited due to excess clock skew\\n\");\n  run.expectEnd();\n  run.expectExit(254);\n});\n\n// Test that when the parent runner process is SIGKILLed, the child\n// process exits also.\nselftest.define(\"run and SIGKILL parent process\", [\"yet-unsolved-windows-failure\"], function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"app-prints-pid\");\n  s.cd(\"myapp\");\n\n  run = s.run();\n  run.waitSecs(30);\n  var match = run.match(/My pid is (\\d+)/);\n  var childPid;\n  if (! match || ! match[1]) {\n    selftest.fail(\"No pid printed\");\n  }\n  childPid = match[1];\n\n  process.kill(run.proc.pid, \"SIGKILL\");\n  // This sleep should be a little more time than the interval at which\n  // the child checks if the parent is still alive, in\n  // packages/webapp/webapp_server.js.\n  utils.sleepMs(3500);\n\n  // Send the child process a signal of 0. If there is no error, it\n  // means that the process is still running, which is not what we\n  // expect.\n  var caughtError;\n  try {\n    process.kill(childPid, 0);\n  } catch (err) {\n    caughtError = err;\n  }\n\n  if (! caughtError) {\n    selftest.fail(\"Child process \" + childPid + \" is still running\");\n  }\n\n  run.stop();\n\n  // Test that passing a bad pid in $METEOR_PARENT_PID logs an error and exits\n  // immediately.\n  s.set(\"METEOR_BAD_PARENT_PID_FOR_TEST\", \"t\");\n  run = s.run();\n  run.waitSecs(120);\n  run.match(\"must be a valid process ID\");\n  run.match(\"Your application is crashing\");\n  run.stop();\n});\n\nselftest.define(\"'meteor run --port' accepts/rejects proper values\", function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"standard-app\");\n  s.cd(\"myapp\");\n\n  run = s.run(\"run\", \"--port\", \"example.com\");\n  run.waitSecs(30);\n  run.matchErr(\"--port must include a port\");\n  run.expectExit(1);\n\n  run = s.run(\"run\", \"--port\", \"http://example.com\");\n  run.waitSecs(30);\n  run.matchErr(\"--port must include a port\");\n  run.expectExit(1);\n\n  run = s.run(\"run\", \"--port\", \"3500\");\n  run.match('App running at: http://localhost:3500/');\n  run.stop();\n\n  run = s.run(\"run\", \"--port\", \"127.0.0.1:3500\");\n  run.match('App running at: http://127.0.0.1:3500/');\n  run.stop();\n});\n\n// Regression test for #3582.  Previously, meteor run would ignore changes to\n// .meteor/versions that originate outside of the process.\nselftest.define(\"update package during run\", function () {\n  var s = new Sandbox();\n\n  s.createApp(\"myapp\", \"app-with-atmosphere-package\");\n  s.cd(\"myapp\", function () {\n    // The app starts with this package at 0.0.1 (based on its\n    // .meteor/versions).  0.0.2 exists too.  (These are on the real atmosphere\n    // server.)\n    var listRun = s.run(\"list\");\n    listRun.waitSecs(3);\n    listRun.match(/glasser:package-for-selftest.*0.0.1\\*/);\n    listRun.match(/\\* New versions/);\n    listRun.expectExit(0);\n\n    var runRun = s.run();\n    runRun.waitSecs(3);\n    runRun.match(\"App running at:\");\n\n    var updateRun = s.run(\"update\", \"glasser:package-for-selftest\");\n    updateRun.match(\n        /glasser:package-for-selftest.*upgraded from 0.0.1 to 0.0.2/);\n    updateRun.expectExit(0);\n\n    runRun.match(\"restarted\");\n\n    listRun = s.run(\"list\");\n    // When #3582 existed, the `meteor run` would revert this back to 0.0.1\n    // before it restarted.\n    listRun.match(/glasser:package-for-selftest.*0.0.2 /);\n    listRun.expectExit(0);\n\n    runRun.stop();\n  });\n});\n\nselftest.define(\"run logging in order\", function () {\n  var s = new Sandbox({ fakeMongo: true });\n  var run;\n\n  // Starting a run\n  s.createApp(\"myapp\", \"standard-app\");\n  s.cd(\"myapp\");\n  s.write('packageless.js', `\n    Meteor.startup(function() {\n      for (var i = 0; i < 100000; i++) {\n        console.log('line: ' + i + '.');\n      }\n    });\n  `);\n  run = s.run();\n  run.match(\"myapp\");\n  run.match(\"proxy\");\n  run.tellMongo(MONGO_LISTENING);\n  run.match(\"MongoDB\");\n  run.waitSecs(5);\n  for (var i = 0; i < 100000; i++) {\n    run.match(`line: ${i}.`);\n  }\n});\n"
  },
  {
    "path": "tools/tests/source-maps.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar files = require('../fs/files.js');\nvar catalog = require('../packaging/catalog/catalog.js');\n\nfunction matchPath (text, doubleBS) {\n  if (process.platform === 'win32') {\n    return text.replace(/\\//g, doubleBS ? '\\\\\\\\' : '\\\\');\n  }\n  return text;\n }\n function matchPathRegexp (regexp) {\n  return new RegExp(matchPath(regexp, true));\n }\n\nselftest.define(\"source maps from checkout\", ['checkout'], function () {\n  try {\n    throw new Error();\n  } catch (e) {\n    var index = (process.platform === 'win32') ? 2 : 1;\n    selftest.expectEqual(e.stack.split(\":\")[index], \"18\");\n  }\n});\n\nselftest.define(\"source maps from an app\", ['checkout', 'custom-warehouse'], function () {\n  var s = new Sandbox({\n    warehouse: {\n      v1: { recommended: true }\n    }\n  });\n\n  // If run not in an app dir, runs the latest version ...\n  var run = s.run(\"--version\");\n  run.read('Meteor v1\\n');\n  run.expectEnd();\n  run.expectExit(0);\n\n  // Starting a run\n  s.createApp(\"myapp\", \"app-throws-error\", {\n    release: \"v1\"\n  });\n\n  s.cd(\"myapp\");\n  s.set(\"METEOR_TEST_TMP\", files.convertToOSPath(files.mkdtemp()));  // XXX why?\n  run = s.run(\"run\");\n  run.waitSecs(10);\n  run.match(matchPathRegexp('at throw\\\\.js:3\\\\b'));\n  run.stop();\n\n  s.set('THROW_FROM_PACKAGE', 't');\n  run = s.run('run');\n  run.waitSecs(10);\n  run.match(matchPathRegexp('packages/throwing-package/thrower\\\\.js:2\\\\b'));\n  run.stop();\n});\n\nselftest.define(\"source maps from built meteor tool\", ['checkout', 'custom-warehouse'], function () {\n  var s = new Sandbox({\n    warehouse: {\n      v1: { recommended: true }\n    }\n  });\n\n  // Find the line number that is supposed to throw an error\n  var commandsJs = files.readFile(files.pathJoin(\n    files.convertToStandardPath(__dirname), '../cli/commands.js'), \"utf8\");\n\n  var lineNumber = 0;\n  commandsJs.split(\"\\n\").some((line, index) => {\n    if (line.indexOf(\"#StackTraceTest\") != -1) {\n      // Lines aren't zero-indexed\n      lineNumber = index + 1;\n\n      // Short-circuit the some\n      return true;\n    }\n  });\n\n  if (lineNumber === 0) {\n    throw new Error(\"Couldn't find the right line. This test is broken.\");\n  }\n\n  var run = s.run(\"throw-error\");\n  run.matchErr(matchPathRegexp('\\\\(/tools/cli/commands\\\\.js:' + lineNumber));\n  run.expectExit(8);\n});\n\nselftest.define(\"source maps from a build plugin implementation\", ['checkout', 'custom-warehouse'], function () {\n  var s = new Sandbox({\n    warehouse: {\n      v1: { recommended: true }\n    }\n  });\n\n  // Starting a run\n  s.createApp(\"myapp\", \"build-plugin-throws-error\", {\n    release: \"v1\"\n  });\n\n  s.cd(\"myapp\");\n  var run = s.run(\"run\");\n  run.waitSecs(10);\n  // XXX This is wrong! The path on disk is\n  // packages/build-plugin/build-plugin.js, but at some point we switched to the\n  // servePath which is based on the *plugin*'s \"package\" name.\n  run.match(matchPathRegexp('packages/build-plugin-itself/build-plugin\\\\.js:2:'));\n  run.stop();\n});\n"
  },
  {
    "path": "tools/tests/standard-minification.js",
    "content": "import selftest, {Sandbox} from '../tool-testing/selftest.js';\n\nselftest.define('standard-minifiers - CSS splitting', function (options) {\n  const s = new Sandbox({\n    clients: options.clients\n  });\n\n  s.createApp('myapp', 'minification-css-splitting');\n  s.cd('myapp');\n\n  s.testWithAllClients(function (run) {\n    run.waitSecs(5);\n    run.match('myapp');\n    run.match('proxy');\n    run.match('MongoDB');\n    run.match('your app');\n    run.match('running at');\n    run.match('localhost');\n\n    run.connectClient();\n    run.waitSecs(20);\n    run.match('client connected');\n\n    run.match('the number of stylesheets: <2>');\n    run.match('the color of the tested 4097th property: <rgb(0, 128, 0)>');\n\n    s.append('client/lots-of-styles.main.styl', `\n.class-4097\n  color: blue\n`);\n\n    run.waitSecs(60);\n    run.match('Client modified -- refreshing');\n    run.match('the number of stylesheets: <2>');\n    run.match('the color of the tested 4097th property: <rgb(0, 0, 255)>');\n\n    run.stop();\n  }, '--production');\n});\n"
  },
  {
    "path": "tools/tests/static-html.js",
    "content": "var _ = require('underscore');\nvar selftest = require('../tool-testing/selftest.js');\nvar files = require('../fs/files.js');\nimport { getUrl } from '../utils/http-helpers.js';\nimport { sleepMs } from '../utils/utils.js';\n\nvar Sandbox = selftest.Sandbox;\n\nvar MONGO_LISTENING =\n  { stdout: \" [initandlisten] waiting for connections on port\" };\n\nfunction startRun(sandbox) {\n  var run = sandbox.run();\n  run.waitSecs(90); // Running from checkout can take a _long_ time\n  run.match(\"myapp\");\n  run.match(\"proxy\");\n  run.tellMongo(MONGO_LISTENING);\n  run.match(\"MongoDB\");\n  return run;\n};\n\n// Test that the static-html package works. It's hard to do this from a unit\n// test.\nselftest.define(\"static-html - add static content to head and body\", () => {\n  const s = new Sandbox({ fakeMongo: true });\n\n  s.createApp('myapp', 'compiler-plugin-static-html');\n  s.cd('myapp');\n\n  const run = startRun(s);\n\n  // Test that static content is present in HTML response.\n  const html = getUrl('http://localhost:3000/');\n  selftest.expectTrue(\n    html.indexOf(\n      `<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">`\n    ) !== -1\n  );\n\n  selftest.expectTrue(\n    html.indexOf(\n      `<div>I have a body, yet no Blaze!</div>`\n    ) !== -1\n  );\n\n  run.stop();\n});\n\n// Test that the static-html package throws the right error\nselftest.define(\"static-html - throws error\", () => {\n  const s = new Sandbox({ fakeMongo: true });\n\n  s.createApp('myapp', 'compiler-plugin-static-html-error');\n  s.cd('myapp');\n\n  const run = startRun(s);\n  run.match(\"Attributes on <head> not supported\");\n\n  run.stop();\n});\n"
  },
  {
    "path": "tools/tests/stylus-cross-packages.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar utils = require('../utils/utils.js');\n\nselftest.define(\"can import stylus across packages\", function (options) {\n  var s = new Sandbox({\n    clients: options.clients\n  });\n\n  s.createApp(\"myapp\", \"app-using-stylus\");\n  s.cd(\"myapp\");\n  s.testWithAllClients(function (run) {\n    run.match(\"myapp\");\n    run.match(\"proxy\");\n    run.match(\"MongoDB\");\n    run.match(\"running at\");\n    run.match(\"localhost\");\n\n    run.connectClient();\n    run.waitSecs(40);\n\n    run.match(\"true\");\n    run.match(\"true\");\n    run.match(\"true\");\n    run.match(\"true\");\n    run.match(\"true\");\n\n    run.stop();\n  });\n});\n"
  },
  {
    "path": "tools/tests/tarball.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar files = require('../fs/files.js');\nvar expectEqual = selftest.expectEqual;\n\nselftest.define(\"create and extract tarball with long paths\", function () {\n  var STAMP = \"stamp\";\n\n  // Create a directory with a single file in a long subdirectory, to\n  // be turned into a tarball.\n  var tarballInputDir = files.mkdtemp(\"tarball-input\");\n  var longDir = tarballInputDir;\n  while (longDir.length < 300) {\n    longDir = files.pathJoin(longDir, \"subdirectory\");\n  }\n  files.mkdir_p(longDir);\n  var inputStampedFile = files.pathJoin(longDir, \"file\");\n  files.writeFile(inputStampedFile, STAMP);\n\n  // Make the tarball\n  var tarballOutputDir = files.mkdtemp(\"tarball\");\n  var tarballOutputFile = files.pathJoin(tarballOutputDir, \"out.tar.gz\");\n  files.createTarball(tarballInputDir, tarballOutputFile);\n\n  // Extract the tarball and verify that the single file we created is\n  // present with the expected contents.\n  var tarballExtractedDir = files.mkdtemp(\"tarball-extracted\");\n  files.extractTarGz(files.readFile(tarballOutputFile), tarballExtractedDir);\n  var extractedStampedFile = inputStampedFile.replace(tarballInputDir, tarballExtractedDir);\n  expectEqual(files.readFile(extractedStampedFile, \"utf-8\"), STAMP);\n});\n"
  },
  {
    "path": "tools/tests/test-modes.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\n\nselftest.define(\"'meteor test --port' accepts/rejects proper values\", function () {\n  var s = new Sandbox();\n  var run;\n\n  s.createApp(\"myapp\", \"standard-app\");\n  s.cd(\"myapp\");\n\n  var runAddPackage = s.run(\"add\", \"practicalmeteor:mocha\");\n  runAddPackage.waitSecs(30);\n  runAddPackage.match(/practicalmeteor:mocha\\b.*?added/)\n  runAddPackage.expectExit(0);\n\n  run = s.run(\"test\", \"--port\", \"3700\", \"--driver-package\", \"practicalmeteor:mocha\");\n  run.waitSecs(60);\n  run.match('App running at: http://localhost:3700/');\n  run.stop();\n\n  run = s.run(\"test\", \"--port\", \"127.0.0.1:3700\", \"--driver-package\", \"practicalmeteor:mocha\");\n  run.waitSecs(60);\n  run.match('App running at: http://127.0.0.1:3700/');\n  run.stop();\n  \n  run = s.run(\"test\", \"--port\", \"[::]:3700\", \"--driver-package\", \"practicalmeteor:mocha\");\n  run.waitSecs(60);\n  run.match('App running at: http://[::]:3700/');\n  run.stop();\n});\n"
  },
  {
    "path": "tools/tests/utils-tests.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar utils = require('../utils/utils.js');\n\nselftest.define('subset generator', function () {\n  var out = [];\n  utils.generateSubsetsOfIncreasingSize(['a', 'b', 'c'], function (x) {\n    out.push(x);\n  });\n  selftest.expectEqual(out, [\n    [],\n    [ 'a' ],\n    [ 'b' ],\n    [ 'c' ],\n    [ 'a', 'b' ],\n    [ 'a', 'c' ],\n    [ 'b', 'c' ],\n    [ 'a', 'b', 'c' ]\n  ]);\n  out = [];\n  utils.generateSubsetsOfIncreasingSize(['a', 'b', 'c'], function (x) {\n    out.push(x);\n    if (x[1] === 'c') {\n      // stop iterating\n      return true;\n    }\n  });\n  selftest.expectEqual(out, [\n    [],\n    [ 'a' ],\n    [ 'b' ],\n    [ 'c' ],\n    [ 'a', 'b' ],\n    [ 'a', 'c' ]\n  ]);\n});\n\nselftest.define(\"url has scheme\", function () {\n  // URL scheme must start with a letter, and then can be followed by\n  // any number of alphanumerics, +, -, . RFC 2396 Appendix A.\n  selftest.expectEqual(utils.hasScheme(\"http://example.com\"), true);\n  selftest.expectEqual(utils.hasScheme(\"https://example.com\"), true);\n  selftest.expectEqual(utils.hasScheme(\"ddp://example.com\"), true);\n  selftest.expectEqual(utils.hasScheme(\"http://example.com:80\"), true);\n  selftest.expectEqual(utils.hasScheme(\"https://example.com:443\"), true);\n  selftest.expectEqual(utils.hasScheme(\"ddp://example.com:443\"), true);\n  selftest.expectEqual(utils.hasScheme(\"ddp://example\"), true);\n  selftest.expectEqual(utils.hasScheme(\"ddp://\"), true);\n  selftest.expectEqual(utils.hasScheme(\"example.comhttp://\"), true);\n  selftest.expectEqual(utils.hasScheme(\"example+com+http://\"), true);\n  selftest.expectEqual(utils.hasScheme(\"example-com+http://\"), true);\n\n  selftest.expectEqual(utils.hasScheme(\"example\"), false);\n  selftest.expectEqual(utils.hasScheme(\"example.com\"), false);\n  selftest.expectEqual(utils.hasScheme(\"example.com:443\"), false);\n  selftest.expectEqual(utils.hasScheme(\"http:/example\"), false);\n  selftest.expectEqual(utils.hasScheme(\"http:example\"), false);\n  selftest.expectEqual(utils.hasScheme(\"example_com+http://\"), false);\n});\n\nselftest.define(\"parse url\", function () {\n  selftest.expectEqual(utils.parseUrl(\"http://localhost:3000\"), {\n    hostname: \"localhost\",\n    port: \"3000\",\n    protocol: \"http\"\n  });\n  selftest.expectEqual(utils.parseUrl(\"https://localhost:3000\"), {\n    hostname: \"localhost\",\n    port: \"3000\",\n    protocol: \"https\"\n  });\n  selftest.expectEqual(utils.parseUrl(\"localhost:3000\"), {\n    hostname: \"localhost\",\n    port: \"3000\",\n    protocol: undefined\n  });\n  selftest.expectEqual(utils.parseUrl(\"3000\"), {\n    hostname: undefined,\n    port: \"3000\",\n    protocol: undefined\n  });\n  selftest.expectEqual(utils.parseUrl(\"3000example.com:3000\"), {\n    hostname: \"3000example.com\",\n    port: \"3000\",\n    protocol: undefined\n  });\n  selftest.expectEqual(utils.parseUrl(\"http://example.com:3000\"), {\n    hostname: \"example.com\",\n    port: \"3000\",\n    protocol: \"http\"\n  });\n  selftest.expectEqual(utils.parseUrl(\"https://example.com:3000\"), {\n    hostname: \"example.com\",\n    port: \"3000\",\n    protocol: \"https\"\n  });\n  selftest.expectEqual(utils.parseUrl(\"example.com:3000\"), {\n    hostname: \"example.com\",\n    port: \"3000\",\n    protocol: undefined\n  });\n  selftest.expectEqual(utils.parseUrl(\"127.0.0.1:3000\"), {\n    hostname: \"127.0.0.1\",\n    port: \"3000\",\n    protocol: undefined\n  });\n  selftest.expectEqual(utils.parseUrl(\"[::]:3000\"), {\n    hostname: \"::\",\n    port: \"3000\",\n    protocol: undefined\n  });\n  selftest.expectEqual(utils.parseUrl(\"http://[::]:3000\"), {\n    hostname: \"::\",\n    port: \"3000\",\n    protocol: \"http\"\n  });\n  selftest.expectEqual(utils.parseUrl(\"https://[::]:3000\"), {\n    hostname: \"::\",\n    port: \"3000\",\n    protocol: \"https\"\n  });\n  selftest.expectEqual(utils.parseUrl(\"[0000:0000:0000:0000:0000:0000:0000:0001]:3000\"), {\n    hostname: \"0000:0000:0000:0000:0000:0000:0000:0001\",\n    port: \"3000\",\n    protocol: undefined\n  });\n\n  // tests for defaults\n  selftest.expectEqual(utils.parseUrl(\"http://example.com:3000\", {\n    hostname: \"foo.com\",\n    port: \"4000\",\n    protocol: \"https\"\n  }), {\n    hostname: \"example.com\",\n    port: \"3000\",\n    protocol: \"http\"\n  });\n  selftest.expectEqual(utils.parseUrl(\"example.com:3000\", {\n    port: \"4000\",\n    protocol: \"https\"\n  }), {\n    hostname: \"example.com\",\n    port: \"3000\",\n    protocol: \"https\"\n  });\n  selftest.expectEqual(utils.parseUrl(\"3000\", {\n    port: \"4000\",\n    protocol: \"https\",\n    hostname: \"example.com\"\n  }), {\n    hostname: \"example.com\",\n    port: \"3000\",\n    protocol: \"https\"\n  });\n});\n"
  },
  {
    "path": "tools/tests/version-parser.js",
    "content": "var _ = require('underscore');\nvar utils = require('../utils/utils.js');\nvar selftest = require('../tool-testing/selftest.js');\n\n\nselftest.define(\"release management - default orderKey\", function () {\n  var t = function (cases) {\n    _.each(cases, function (c) {\n      var version = c[0];\n      var expectedOrderKey = c[1];\n      var actualOrderKey = utils.defaultOrderKeyForReleaseVersion(version);\n      selftest.expectEqual(actualOrderKey, expectedOrderKey);\n    });\n  };\n\n  t([\n    ['1', '0001$'],\n    ['0', '0000$'],\n    ['01', null],\n    ['', null],\n    ['1.2.3', '0001.0002.0003$'],\n    ['42.123', '0042.0123$'],\n    ['1234', '1234$'],\n    ['12345', null],\n    ['123.012', null],\n    ['1.2.3-preview', '0001.0002.0003!preview!!!!!!!!$'],\n    ['1.2.3.4-AbCdEfG-HiJkLmO', '0001.0002.0003.0004!AbCdEfG-HiJkLmO$'],\n    ['1.2.3.4-AbCdEfG-HiJkLmOp', null],\n    ['1.2.3.4-AbCdEfG-HiJkLmO0', '0001.0002.0003.0004!AbCdEfG-HiJkLmO0000$'],\n    ['1.2.3.4-AbCdEfG-HiJkLmO01', null],\n    ['1.2.3.4-AbCdEfG-HiJkLmO12345', null],\n    ['1.2.3.4-AbCdEfG-HiJkLmO15', '0001.0002.0003.0004!AbCdEfG-HiJkLmO0015$'],\n    ['1.2.3.4-rc2', '0001.0002.0003.0004!rc!!!!!!!!!!!!!0002$'],\n    ['1.2.3.4-2rc', null],\n    ['1.2.3.4r', null]\n  ]);\n\n  var ordered = [\n    '1.2',\n    '1.2.0',\n    '1.2.1',\n    '1.2.1.4',\n    '1.2.2',\n    '1.2.15',\n    '1.15.2',\n    '1.15.3-preview',\n    '1.15.3-preview2',\n    '1.15.3-preview15',\n    '1.15.3-rc',\n    '1.15.3-rc2',\n    '1.15.3-rc15',\n    '1.15.3-rd15',\n    '1.15.3-rda15',\n    '1.15.3',\n    '2'\n  ];\n\n  for (var i = 0; i < ordered.length - 1; ++i) {\n    var first = utils.defaultOrderKeyForReleaseVersion(ordered[i]);\n    var next = utils.defaultOrderKeyForReleaseVersion(ordered[i + 1]);\n    selftest.expectEqual(first !== null, true);\n    selftest.expectEqual(next !== null, true);\n    selftest.expectEqual(first < next, true);\n  }\n});\n"
  },
  {
    "path": "tools/tests/wipe-all-packages.js",
    "content": "var selftest = require('../tool-testing/selftest.js');\nvar Sandbox = selftest.Sandbox;\nvar files = require('../fs/files.js');\nvar utils = require('../utils/utils.js');\nvar archinfo = require('../utils/archinfo.js');\nvar _ = require('underscore');\n\nselftest.define(\"wipe all packages\", ['slow', 'custom-warehouse'], function () {\n  var s = new Sandbox({\n    warehouse: {\n      v1: { tool: \"meteor-tool@33.0.1\", recommended: true },\n      v2: { tool: \"meteor-tool@33.0.2\", recommended: true },\n      v3: { tool: \"meteor-tool@33.0.3\", recommended: true }\n    }\n  });\n  var meteorToolVersion = function (v) {\n    return {\n      _id: 'VID' + v.replace(/\\./g, ''),\n      packageName: 'meteor-tool',\n      testName: null,\n      version: v,\n      publishedBy: null,\n      description: 'The Meteor command-line tool',\n      git: undefined,\n      dependencies: { meteor: { constraint: null, references: [{ arch: 'os' }, { arch: 'web.browser' }, { arch: 'web.cordova' }] } },\n      source: null,\n      lastUpdated: null,\n      published: null,\n      isTest: false,\n      debugOnly: false,\n      prodOnly: false,\n      testOnly: false,\n      containsPlugins: false\n    };\n  };\n  var meteorToolBuild = function (v) {\n    return {\n      buildArchitectures: archinfo.host(),\n      versionId: 'VID' + v.replace(/\\./g, ''),\n      _id: utils.randomToken()\n    };\n  };\n\n  // insert the new tool versions into the catalog\n  s.warehouseOfficialCatalog.insertData({\n    syncToken: {},\n    formatVersion: \"1.0\",\n    collections: {\n      packages: [],\n      versions: [meteorToolVersion('33.0.1'), meteorToolVersion('33.0.2'), meteorToolVersion('33.0.3')],\n      builds: [meteorToolBuild('33.0.1'), meteorToolBuild('33.0.2'), meteorToolBuild('33.0.3')],\n      releaseTracks: [],\n      releaseVersions: []\n    }\n  });\n\n  // help warehouse faking by copying the meteor-tool 3 times and introducing 3\n  // fake versions (identical in code to the one we are running)\n  var latestMeteorToolVersion =\n    files.readLinkToMeteorScript(files.pathJoin(s.warehouse, 'meteor')).split('/');\n  latestMeteorToolVersion = latestMeteorToolVersion[latestMeteorToolVersion.length - 3];\n\n  var prefix = files.pathJoin(s.warehouse, 'packages', 'meteor-tool');\n  var copyTool = function (srcVersion, dstVersion) {\n    if (process.platform === 'win32') {\n      // just copy the files\n      files.cp_r(\n        files.pathJoin(prefix, srcVersion),\n        files.pathJoin(prefix, dstVersion), {\n          preserveSymlinks: true\n        });\n    } else {\n      // figure out what the symlink links to and copy the folder *and* the\n      // symlink\n      var srcFullVersion = files.readlink(files.pathJoin(prefix, srcVersion));\n      var dstFullVersion = srcFullVersion.replace(srcVersion, dstVersion);\n\n      // copy the hidden folder\n      files.cp_r(\n        files.pathJoin(prefix, srcFullVersion),\n        files.pathJoin(prefix, dstFullVersion), {\n          preserveSymlinks: true\n        });\n\n      // link to it\n      files.symlink(\n        dstFullVersion,\n        files.pathJoin(prefix, dstVersion));\n    }\n\n    var replaceVersionInFile = function (filename) {\n      var filePath = files.pathJoin(prefix, dstVersion, filename);\n      files.writeFile(\n        filePath,\n        files.readFile(filePath, 'utf8')\n          .replace(new RegExp(srcVersion, 'g'), dstVersion));\n    };\n\n    // \"fix\" the isopack.json and unibuild.json files (they contain the versions)\n    replaceVersionInFile('isopack.json');\n    replaceVersionInFile('unipackage.json');\n  };\n\n  copyTool(latestMeteorToolVersion, '33.0.3');\n  copyTool(latestMeteorToolVersion, '33.0.2');\n  copyTool(latestMeteorToolVersion, '33.0.1');\n\n  // since the warehouse faking system is weak and under-developed, add more\n  // faking, such as making the v3 the latest version\n  files.linkToMeteorScript(\n    files.pathJoin('packages', 'meteor-tool', '33.0.3', 'mt-' + archinfo.host(), 'meteor'),\n    files.pathJoin(s.warehouse, 'meteor'));\n\n\n  var run;\n\n  run = s.run('--release', 'v1', 'admin', 'wipe-all-packages');\n  run.waitSecs(15);\n  run.expectExit(0);\n\n  // OK, wiped all packages, now let's go and check that everything is removed\n  // except for the tool we are running right now and the latest tool. i.e. v1\n  // and v3\n  var notHidden = function (f) { return f[0] !== '.'; };\n  var meteorToolDirs = _.filter(files.readdir(prefix), notHidden);\n  selftest.expectTrue(meteorToolDirs.length === 2);\n  _.each(meteorToolDirs, function (f) {\n    var fPath = files.pathJoin(prefix, f);\n    if (process.platform === 'win32') {\n      // this is a dir\n      selftest.expectTrue(files.lstat(fPath).isDirectory());\n    } else {\n      // this is a symlink to a dir and this dir exists\n      selftest.expectTrue(files.lstat(fPath).isSymbolicLink());\n      selftest.expectTrue(files.exists(files.pathJoin(prefix, files.readlink(fPath))));\n    }\n\n    // check that the version is either the running one, or the latest one\n    selftest.expectTrue(_.contains(['33.0.1', '33.0.3'], f));\n  });\n\n  // Check that all other packages are wiped\n  _.each(files.readdir(files.pathJoin(s.warehouse, 'packages')), function (p) {\n    if (p[0] === '.') {\n      return;\n    }\n    if (p === 'meteor-tool') {\n      return;\n    }\n    var contents = files.readdir(files.pathJoin(s.warehouse, 'packages', p));\n    contents = _.filter(contents, notHidden);\n    selftest.expectTrue(contents.length === 0);\n  });\n});\n"
  },
  {
    "path": "tools/tool-env/README.md",
    "content": "Uninteresting files that run on tool's startup (set up profilers, transpilers,\netc) and exit (clean up code, flush the output).\n\n\n## ES2015 compilation for tool\n\nThere are two different configurations of Babel for the tools code:\n\n- local development from git checkout\n- running in production from a release\n\nIn the first case, it is enough to register Babel's hook for `require`. For the\nlatter, this hook should be removed (`#RemoveInProd`) and the files should be\nexplicitly compiled.\n\nThe listing of Babel-compiled files can be found in `isopack.js`, the\n`Isopack#_writeTool` method runs all the preprocessing when tools files are\ncopied for a release package.\n"
  },
  {
    "path": "tools/tool-env/cleanup.js",
    "content": "/// A simple interface to register functions to be called when the process\n/// exits.\n\nvar _ = require('underscore');\n\nvar fiberHelpers = require('../utils/fiber-helpers.js');\n\nvar cleanup = exports;\n_.extend(exports, {\n  _exitHandlers: [],\n\n  // register a function that will be called on SIGINT (e.g. Cmd-C on\n  // mac)\n  onExit: function (func) {\n    this._exitHandlers.push(func);\n  }\n});\n\nvar runHandlers = function () {\n  fiberHelpers.noYieldsAllowed(function () {\n    var handlers = cleanup._exitHandlers;\n    cleanup._exitHandlers = [];\n    _.each(handlers, function (f) {\n      f();\n    });\n  });\n};\n\nprocess.on('exit', runHandlers);\n_.each(['SIGINT', 'SIGHUP', 'SIGTERM'], function (sig) {\n  process.once(sig, function () {\n    runHandlers();\n    process.kill(process.pid, sig);\n  });\n});\n"
  },
  {
    "path": "tools/tool-env/install-babel.js",
    "content": "// This file exists because it is the file in the tool that is not automatically\n// transpiled by Babel\n\nfunction babelRegister() {\n  var meteorBabel = require(\"meteor-babel\");\n  var path = require(\"path\");\n  var toolsPath = path.dirname(__dirname);\n  var meteorPath = path.dirname(toolsPath);\n  var cacheDir = path.join(meteorPath, \".babel-cache\");\n\n  meteorBabel.setCacheDir(cacheDir);\n\n  require('meteor-babel/register')\n    .allowDirectory(toolsPath)\n    .setSourceMapRootPath(meteorPath);\n}\n\nbabelRegister(); // #RemoveInProd this line is removed in isopack.js\n\nrequire(\"./install-runtime.js\");\n"
  },
  {
    "path": "tools/tool-env/install-git-hooks.js",
    "content": "import files from '../fs/files.js';\n\nconst hookDestination =\n  files.pathJoin(files.getCurrentToolsDir(), '.git', 'hooks');\n\nconst hookSource =\n  files.pathJoin(files.getCurrentToolsDir(),\n    'scripts', 'admin', 'git-hooks');\n\nconst allPossibleHooks = [\n  'applypatch-msg',\n  'pre-applypatch',\n  'post-applypatch',\n  'pre-commit',\n  'prepare-commit-msg',\n  'commit-msg',\n  'post-commit',\n  'pre-rebase',\n  'post-checkout',\n  'post-merge',\n  'pre-receive',\n  'update',\n  'post-update',\n  'pre-auto-gc',\n  'post-rewrite',\n];\n\n// A suffix that we append to our hook scripts\nconst METEOR_HOOK_SUFFIX = '.meteor-hook';\n\n// Matches the whole line we inject into the user's hook\nconst METEOR_HOOK_LINE_REGEX = /.*meteor-hook.*/;\n\nexport default function installGitHooks() {\n\n  if (!files.exists(hookDestination)) {\n    // Don't do anything if the hook destination does not exist, eg.,\n    // we are not running from a git clone.\n    return;\n  }\n\n  allPossibleHooks.map((hookName) => {\n    const hookFile = files.pathJoin(hookDestination, hookName);\n    const sourceFile = files.pathJoin(hookSource, hookName);\n    const meteorHookFile = hookFile + METEOR_HOOK_SUFFIX;\n\n    if (!files.exists(sourceFile) && !files.exists(hookFile)) {\n      // Don't do anything if this hook isn't in either list\n      return;\n    }\n\n    if (!files.exists(sourceFile)) {\n      // If the user has this hook, but Meteor doesn't, make sure that we remove\n      // any hooks that we added previously\n      removeMeteorInjectedHook(hookFile);\n      return;\n    }\n\n    /* eslint-disable max-len */\n    const METEOR_HOOK_INJECTED_LINE = `exec \"$(dirname $0)/${hookName}${METEOR_HOOK_SUFFIX}\" # Inserted by Meteor tool\\n`;\n    /* eslint-enable */\n\n    if (!files.exists(hookFile)) {\n      // If the user doesn't have this hook, but we want to add it, just insert\n      // a new file and a line that calls it\n      files.writeFile(hookFile,\n        `#!/bin/sh\n${METEOR_HOOK_INJECTED_LINE}`,\n        { encoding: 'utf8', mode: 0o755 });\n\n      // Copy the hook from the scripts dir\n      files.writeFile(meteorHookFile, files.readFile(sourceFile),\n        { mode: 0o755 });\n      return;\n    }\n\n    // Now we have arrived at the case where the user already has a hook\n\n    // Has Meteor already installed a hook here? If not, add a line to the hook\n    if (!files.exists(meteorHookFile)) {\n      files.appendFile(hookFile, METEOR_HOOK_INJECTED_LINE);\n    }\n\n    // Copy the hook from the scripts dir again in case it updated\n    files.writeFile(meteorHookFile, files.readFile(sourceFile),\n      { mode: 0o755 });\n    return;\n  });\n}\n\nfunction removeMeteorInjectedHook(hookFile) {\n  // Remove the script added by Meteor\n  try {\n    files.unlink(hookFile + METEOR_HOOK_SUFFIX);\n  } catch (err) {\n    // Ignore errors about file not found\n    if (err.code !== 'ENOENT') {\n      throw err;\n    }\n  }\n\n  // Remove the line added to the file\n  files.writeFile(hookFile,\n    files.readFile(hookFile, 'utf8').replace(METEOR_HOOK_LINE_REGEX, ''),\n    'utf8');\n}\n"
  },
  {
    "path": "tools/tool-env/install-runtime.js",
    "content": "// Install ES2015-complaint polyfills for Object, Array, String, Function,\n// Symbol, Map, and Set, patching the native implementations if available.\nrequire(\"meteor-ecmascript-runtime\");\n\n// Install a global ES2015-compliant Promise constructor that knows how to\n// run all its callbacks in Fibers.\nvar Promise = global.Promise = global.Promise ||\n  require(\"promise/lib/es6-extensions\");\nrequire(\"meteor-promise\").makeCompatible(Promise, require(\"fibers\"));\n\n// Verify that the babel-runtime package is available to be required.\n// The .join(\"/\") prevents babel-plugin-transform-runtime from\n// \"intelligently\" converting this to an import statement.\nvar regenerator = require([\n  \"babel-runtime\",\n  \"regenerator\"\n].join(\"/\"));\n\n// Use Promise.asyncApply to wrap calls to runtime.async so that the\n// entire async function will run in its own Fiber, not just the code that\n// comes after the first await.\nvar realAsync = regenerator.async;\nregenerator.async = function () {\n  return Promise.asyncApply(realAsync, regenerator, arguments);\n};\n\n// Install global.meteorBabelHelpers so that the compiler doesn't need to\n// add boilerplate at the top of every file.\nrequire(\"meteor-babel\").defineHelpers();\n\n// Installs source map support with a hook to add functions to look for\n// source maps in custom places.\nrequire('./source-map-retriever-stack.js');\n"
  },
  {
    "path": "tools/tool-env/isopackets.js",
    "content": "var _ = require('underscore');\n\nvar bundler = require('../isobuild/bundler.js');\nimport Builder from '../isobuild/builder.js';\nvar compiler = require('../isobuild/compiler.js');\nvar isopackCacheModule = require('../isobuild/isopack-cache.js');\n\nvar buildmessage = require('../utils/buildmessage.js');\nvar files = require('../fs/files.js');\nvar config = require('../meteor-services/config.js');\nvar watch = require('../fs/watch.js');\nvar Console = require('../console/console.js').Console;\nvar fiberHelpers = require('../utils/fiber-helpers.js');\nvar packageMapModule = require('../packaging/package-map.js');\nvar Profile = require('./profile.js').Profile;\n\n// TL;DR: Isopacket is a set of isopacks. Isopackets are used only inside\n// meteor-tool.\n\n// An isopacket is a predefined set of isopackages which the meteor command-line\n// tool can load into its process. This is how we use the DDP client and many\n// other packages inside the tool. The isopackets are listed below in the\n// ISOPACKETS constant.\n//\n// All packages that are in isopackets and all of their transitive dependencies\n// must be part of the core Meteor git checkout (not loaded from troposphere).\n//\n// The requested packages will be loaded together with all of their\n// dependencies. If you request to load the same isopacket more than once, you\n// will efficiently get the same pre-loaded isopacket. On the other hand, two\n// different loaded isopackets contain distinct copies of all of their packages\n// copy of all of the packages. The return value is an object that maps package\n// name to package exports (that is, it is the Package object from inside the\n// sandbox created for the newly loaded packages).\n//\n// For built releases, all of the isopackets are pre-compiled (as JsImages,\n// similar to a plugin or a server program) into the tool.\n//\n// When run from a checkout, all isopackets are re-compiled early in the startup\n// process if any of their sources have changed.\n//\n// Example usage:\n//   var DDP = require('./isopackets.js').load('ddp')['ddp-client'].DDP;\n//   var reverse = DDP.connect('reverse.meteor.com');\n//   Console.info(reverse.call('reverse', 'hello world'));\n\n\n// All of the defined isopackets. Whenever they are being built, they will be\n// built in the order listed here.\nexport const ISOPACKETS = {\n  'ddp': ['ddp-client'],\n  'mongo': ['npm-mongo'],\n  'ejson': ['ejson'],\n  'constraint-solver': ['constraint-solver'],\n  'cordova-support': ['boilerplate-generator', 'logging', 'webapp-hashing',\n                      'xmlbuilder'],\n  'logging': ['logging']\n};\n\n// Caches isopackets in memory (each isopacket only needs to be loaded\n// once).  This is a map from isopacket name to either:\n//\n//  - The 'Package' dictionary, if the isopacket has already been loaded\n//    into memory\n//  - null, if the isopacket hasn't been loaded into memory but its on-disk\n//    instance is known to be ready\n//\n// The subtlety here is that when running from a checkout, we don't want to\n// accidentally load an isopacket before ensuring that it doesn't need to be\n// rebuilt. We used to need to load a \"js-analyze\" isopacket as part\n// of building other isopackets in ensureIsopacketsLoadable which made this\n// more important, though we've simplified it now by moving that code into\n// the tool itself.\nvar loadedIsopackets = {};\n\n// The main entry point: loads and returns an isopacket from cache or from\n// disk. Does not do a build step: ensureIsopacketsLoadable must be called\n// first!\nexport function load(isopacketName) {\n  return fiberHelpers.noYieldsAllowed(function () {\n    if (_.has(loadedIsopackets, isopacketName)) {\n      if (loadedIsopackets[isopacketName]) {\n        return loadedIsopackets[isopacketName];\n      }\n\n      // This is the case where the isopacket is up to date on disk but not\n      // loaded.\n      var isopacket = loadIsopacketFromDisk(isopacketName);\n      loadedIsopackets[isopacketName] = isopacket;\n      return isopacket;\n    }\n\n    if (_.has(ISOPACKETS, isopacketName)) {\n      throw Error(\"Can't load isopacket before it has been verified: \"\n                  + isopacketName);\n    }\n\n    throw Error(\"Unknown isopacket: \" + isopacketName);\n  });\n}\n\nvar isopacketPath = function (isopacketName) {\n  return files.pathJoin(config.getIsopacketRoot(), isopacketName);\n};\n\n// ensureIsopacketsLoadable is called at startup and ensures that all isopackets\n// exist on disk as up-to-date loadable programs.\nvar calledEnsure = false;\nexport function ensureIsopacketsLoadable() {\n  if (calledEnsure) {\n    throw Error(\"can't ensureIsopacketsLoadable twice!\");\n  }\n  calledEnsure = true;\n\n  // If we're not running from checkout, then there's nothing to build and we\n  // can declare that all isopackets are loadable.\n  if (! files.inCheckout()) {\n    _.each(ISOPACKETS, function (packages, name) {\n      loadedIsopackets[name] = null;\n    });\n    return;\n  }\n\n  // We make this object lazily later.\n  var isopacketBuildContext = null;\n\n  var failedPackageBuild = false;\n  // Look at each isopacket. Check to see if it's on disk and up to date. If\n  // not, build it. We rebuild them in the order listed in ISOPACKETS.\n  var messages = Console.withProgressDisplayVisible(function () {\n    return buildmessage.capture(function () {\n      _.each(ISOPACKETS, function (packages, isopacketName) {\n        if (failedPackageBuild) {\n          return;\n        }\n\n        var isopacketRoot = isopacketPath(isopacketName);\n        var existingBuildinfo = files.readJSONOrNull(\n          files.pathJoin(isopacketRoot, 'isopacket-buildinfo.json'));\n        var needRebuild = ! existingBuildinfo;\n        if (! needRebuild && existingBuildinfo.builtBy !== compiler.BUILT_BY) {\n          needRebuild = true;\n        }\n        if (! needRebuild) {\n          var watchSet = watch.WatchSet.fromJSON(existingBuildinfo.watchSet);\n          if (! watch.isUpToDate(watchSet)) {\n            needRebuild = true;\n          }\n        }\n        if (! needRebuild) {\n          // Great, it's loadable without a rebuild.\n          loadedIsopackets[isopacketName] = null;\n          return;\n        }\n\n        // We're going to need to build! Make a catalog and loader if we haven't\n        // yet.\n        if (! isopacketBuildContext) {\n          isopacketBuildContext = makeIsopacketBuildContext();\n        }\n\n        buildmessage.enterJob({\n          title: \"bundling \" + isopacketName + \" packages for the tool\"\n        }, function () {\n          // Build the packages into the in-memory IsopackCache.\n          isopacketBuildContext.isopackCache.buildLocalPackages(packages);\n          if (buildmessage.jobHasMessages()) {\n            return;\n          }\n\n          // Now bundle them into a program.\n          var built = bundler.buildJsImage({\n            name: \"isopacket-\" + isopacketName,\n            packageMap: isopacketBuildContext.packageMap,\n            isopackCache: isopacketBuildContext.isopackCache,\n            use: packages\n          });\n          if (buildmessage.jobHasMessages()) {\n            return;\n          }\n\n          var builder = new Builder({outputPath: isopacketRoot});\n          builder.writeJson('isopacket-buildinfo.json', {\n            builtBy: compiler.BUILT_BY,\n            watchSet: built.watchSet.toJSON()\n          });\n          built.image.write(builder);\n          builder.complete();\n          // It's loadable now.\n          loadedIsopackets[isopacketName] = null;\n        });\n      });\n    });\n  });\n\n  // This is a build step ... but it's one that only happens in development, so\n  // it can just crash the app instead of being handled nicely.\n  if (messages.hasMessages()) {\n    Console.error(\"Errors prevented isopacket build:\");\n    Console.printMessages(messages);\n    throw new Error(\"isopacket build failed?\");\n  }\n}\n\n// Returns a new all-local-packages catalog to be used for building isopackets.\nvar newIsopacketBuildingCatalog = function () {\n  if (! files.inCheckout()) {\n    throw Error(\"No need to build isopackets unless in checkout!\");\n  }\n\n  var catalogLocal = require('../packaging/catalog/catalog-local.js');\n  var isopacketCatalog = new catalogLocal.LocalCatalog;\n  var messages = buildmessage.capture(\n    { title: \"scanning local core packages\" },\n    function () {\n      // When running from a checkout, isopacket building does use local\n      // packages, but *ONLY THOSE FROM THE CHECKOUT*: not app packages or\n      // $PACKAGE_DIRS packages.  One side effect of this: we really really\n      // expect them to all build, and we're fine with dying if they don't\n      // (there's no worries about needing to springboard).\n      isopacketCatalog.initialize({\n        localPackageSearchDirs: [files.pathJoin(\n          files.getCurrentToolsDir(), 'packages')],\n        buildingIsopackets: true\n      });\n    });\n  if (messages.hasMessages()) {\n    Console.arrowError(\"Errors while scanning core packages:\");\n    Console.printMessages(messages);\n    throw new Error(\"isopacket scan failed?\");\n  }\n  return isopacketCatalog;\n};\n\nexport function makeIsopacketBuildContext() {\n  var context = {};\n  var catalog = newIsopacketBuildingCatalog();\n  var versions = {};\n  _.each(catalog.getAllPackageNames(), function (packageName) {\n    versions[packageName] = catalog.getLatestVersion(packageName).version;\n  });\n  context.packageMap = new packageMapModule.PackageMap(versions, {\n    localCatalog: catalog\n  });\n  // Make an isopack cache that doesn't save isopacks to disk and has no\n  // access to versioned packages.\n  context.isopackCache = new isopackCacheModule.IsopackCache({\n    packageMap: context.packageMap,\n    includeCordovaUnibuild: false,\n    // When linking JS files, don't include the padding spaces and line number\n    // comments. Since isopackets are loaded as part of possibly very short\n    // 'meteor' tool command invocations, we care more about startup time than\n    // legibility, and the difference is actually observable (eg 25% speedup\n    // loading constraint-solver).\n    noLineNumbers: true\n  });\n  return context;\n}\n\n// Loads a built isopacket from disk. Always loads (the cache is in 'load', not\n// this function). Does not run a build process; it must already be built.\nvar loadIsopacketFromDisk = function (isopacketName) {\n  var image = bundler.readJsImage(\n    files.pathJoin(isopacketPath(isopacketName), 'program.json'));\n\n  // An incredibly minimalist version of the environment from\n  // tools/server/boot.js.  Kind of a hack.\n  var env = {\n    __meteor_bootstrap__: { startupHooks: [] },\n    __meteor_runtime_config__: { meteorRelease: \"ISOPACKET\" }\n  };\n  env.Profile = Profile;\n\n  var ret;\n  var messages = buildmessage.capture({\n    title: \"loading isopacket `\" + isopacketName + \"`\"\n  }, function () {\n    ret = image.load(env);\n  });\n\n  // This is a build step ... but it's one that only happens in development, so\n  // it can just crash the app instead of being handled nicely.\n  if (messages.hasMessages()) {\n    Console.error(\"Errors prevented isopacket load:\");\n    Console.printMessages(messages);\n    throw new Error(\"isopacket load failed?\");\n  }\n\n  // Run any user startup hooks.\n  while (env.__meteor_bootstrap__.startupHooks.length) {\n    var hook = env.__meteor_bootstrap__.startupHooks.shift();\n    hook();\n  }\n  // Setting this to null tells Meteor.startup to call hooks immediately.\n  env.__meteor_bootstrap__.startupHooks = null;\n\n  return ret;\n};\n\n// Support `import isopackets from \"../path/to/isopackets.js\"`.\nexport default exports;\n"
  },
  {
    "path": "tools/tool-env/profile-require.js",
    "content": "// Use path instead of files.js here because we are explicitly trying to\n// track requires, and files.js is often a culprit of slow requires.\nvar path = require('path');\n\n// seconds since epoch\nvar now = function () {\n  return (+ new Date)/1000;\n};\n\nvar currentInvocation;\nvar RequireInvocation = function (name, filename) {\n  var self = this;\n  self.name = name; // module required\n  self.filename = filename; // file doing the requiring, if known\n  self.timeStarted = now();\n  self.timeFinished = null;\n  self.parent = currentInvocation;\n  self.children = []; // array of RequireInvocation\n\n  self.selfTime = null;\n  self.totalTime = null;\n};\n\nRequireInvocation.prototype.isOurCode = function () {\n  var self = this;\n\n  if (! self.filename) {\n    return self.name === 'TOP';\n  }\n\n  if (! self.name.match(/\\//)) {\n    // we always require our stuff via a path\n    return false;\n  }\n\n  var ourSource = path.resolve(__dirname);\n  var required = path.resolve(path.dirname(self.filename), self.name);\n  if (ourSource.length > required.length) {\n    return false;\n  }\n  return required.substr(0, ourSource.length) === ourSource;\n};\n\nRequireInvocation.prototype.why = function () {\n  var self = this;\n  var walk = self;\n  var last = null;\n\n  while (walk && ! walk.isOurCode()) {\n    last = walk;\n    walk = walk.parent;\n  }\n\n  if (! walk) {\n    return \"???\";\n  }\n  if (last) {\n    return path.basename(walk.name) + \":\" + path.basename(last.name);\n  }\n  return path.basename(walk.name);\n};\n\nexports.start = function () {\n  var moduleModule = require('module');\n  currentInvocation = new RequireInvocation('TOP');\n\n  var realLoader = moduleModule._load;\n  moduleModule._load = function (...args) {\n    var [id, { filename }] = args;\n    var inv = new RequireInvocation(id, filename);\n    var parent = currentInvocation;\n    currentInvocation.children.push(inv);\n    currentInvocation = inv;\n\n    try {\n      return realLoader.apply(this, args);\n    } finally {\n      inv.timeFinished = now();\n      currentInvocation = parent;\n    }\n  };\n};\n\nexports.printReport = function () {\n  currentInvocation.timeFinished = now();\n  var _ = require('underscore');\n\n  var computeTimes = function (inv) {\n    inv.totalTime = inv.timeFinished - inv.timeStarted;\n\n    var childTime = 0;\n    _.each(inv.children, function (child) {\n      computeTimes(child);\n      childTime += child.totalTime;\n    });\n\n    if (inv.totalTime !== null) {\n      inv.selfTime = inv.totalTime - childTime;\n    }\n  };\n  computeTimes(currentInvocation);\n\n  var summary = {};\n  var summarize = function (inv, depth) {\n    // var padding = (new Array(depth*2 + 1)).join(' ');\n    // console.log(padding + inv.name + \" [\" + inv.selfTime + \"]\");\n    if (! (inv.name in summary)) {\n      summary[inv.name] = { name: inv.name, time: 0, ours: inv.isOurCode(),\n                            via: {} };\n    }\n    summary[inv.name].time += inv.selfTime;\n    if (! inv.isOurCode()) {\n      summary[inv.name].via[inv.why()] = true;\n    }\n\n    _.each(inv.children, function (inv) {\n      summarize(inv, depth + 1);\n    });\n  };\n  summarize(currentInvocation, 0);\n\n  var times = _.sortBy(_.values(summary), 'time').reverse();\n  var ourTotal = 0, otherTotal = 0;\n  _.each(times, function (item) {\n    var line = (item.time * 1000).toFixed(2) + \" \" + item.name;\n    if (! item.ours) {\n      line += \" [via \" + _.keys(item.via).join(\", \") + \"]\";\n    }\n    console.log(line);\n    if (item.ours) {\n      ourTotal += item.time;\n    } else {\n      otherTotal += item.time;\n    }\n  });\n\n\n  var grandTotal = currentInvocation.totalTime;\n  if (grandTotal - ourTotal - otherTotal > 1/1000) {\n    throw new Error(\"Times don't add up\");\n  }\n  console.log(\"TOTAL: ours \" + (ourTotal * 1000).toFixed(2) +\n              \", other \" + (otherTotal * 1000).toFixed(2) +\n              \", grand total \" + (grandTotal * 1000).toFixed(2));\n};\n"
  },
  {
    "path": "tools/tool-env/profile.js",
    "content": "// Tiny profiler\n//\n// Enable by setting the environment variable `METEOR_PROFILE`.\n//\n// The main entry point is `Profile`, which wraps an existing function\n// and returns a new function which, when called, calls the original\n// function and profiles it.\n//\n// before:\n//\n//     foo: function (a) {\n//       return a + this.b;\n//     },\n//\n// after:\n//\n//     foo: Profile(\"foo\", function (a) {\n//       return a + this.b;\n//     }),\n//\n// The advantage of this form is that it doesn't change the\n// indentation of the wrapped code, which makes merging changes from\n// other code branches easier.\n//\n// If profiling is disabled (if `METEOR_PROFILE` isn't set), `Profile`\n// simply returns the original function.\n//\n// To run a profiling session and print the report, call `Profile.run`:\n//\n//     var createBundle = function () {\n//       Profile.run(\"bundle\", function () {\n//         ...code to create the bundle which includes calls to `Profile`.\n//       });\n//     };\n//\n// Code is not profiled when called outside of a `Profile.run`, so the\n// times in the report only include the time spent inside of the call\n// to `Profile.run`.\n//\n// Sometimes you'll want to use a name for the profile bucket which\n// depends on the arguments passed to the function or the value of\n// `this`.  In this case you can pass a function for the bucket\n// argument, which will be called to get the bucket name.\n//\n// before:\n//     build: function (target) {\n//       ... build target ...\n//     },\n//\n// after:\n//     build: Profile(\n//       function (target) { return \"build \" + target; },\n//       function (target) {\n//         ... build target ...\n//       }),\n//\n// But if it's easier, you can use `Profile.time` instead, which\n// immediately calls the passed function with no arguments and\n// profiles it, and returns what the function returns.\n//\n//     foo: function (a) {\n//       var self = this;\n//       return Profile.time(\"foo\", function () {\n//         return a + self.b;\n//       });\n//     },\n//\n//     build: function (target) {\n//       var self = this;\n//       self.doSomeSetup();\n//       Profile.time(\"build \" + target, function () {\n//         ... build target ...\n//       });\n//       self.doSomeCleanup();\n//     },\n//\n// The disadvantage is that you end up changing the indentation of the\n// profiled code, which makes merging branches more painful.  But you\n// can profile anywhere in the code; you don't have to just profile at\n// function boundaries.\n//\n// Note profiling code will itself add a bit of execution time.\n// If you profile in a tight loop and your total execution time is\n// going up, you're probably starting to profile how long it takes to\n// profile things :).\n//\n// If another profile (such as \"compile js\") is called while the first\n// function is currently being profiled, this creates an entry like\n// this:\n//\n//    build client : compile js\n//\n// which can continue to be nested, e.g.,\n//\n//    build client : compile js : read source files\n//\n// The total time reported for a bucket such as \"build client\" doesn't\n// change regardless of whether it has child entries or not.  However,\n// if an entry has child entries, it automatically gets an \"other\"\n// entry:\n//\n//     build client: 400.0\n//       compile js: 300.0\n//         read source files: 20.0\n//         other compile js: 280.0\n//       other build client: 100.0\n//\n// The \"other\" entry reports how much time was spent in the \"build\n// client\" entry not spent in the other child entries.\n//\n// The are two reports displayed: the hierarchical report and the\n// leaf time report.  The hierarchical report looks like the example\n// above and shows how much time was spent in each entry within its\n// parent entry.\n//\n// The primary purpose of the hierarchical report is to be able to see\n// where times are unaccounted for.  If you see a lot of time being\n// spent in an \"other\" bucket, and you don't know what it is, you can\n// add more profiling to dig deeper.\n//\n// The leaf time report shows the total time spent within leaf\n// buckets.  For example, if if multiple steps have \"read source\n// files\", the leaf time reports shows the total amount of time spent\n// in \"read source files\" across all calls.\n//\n// Once you see in the hierarchical report that you have a good handle\n// on accounting for most of the time, the leaf report shows you which\n// buckets are the most expensive.\n//\n// By only including leaf buckets, the times in the leaf report are\n// non-overlapping.  (The total of the times equals the elapsed time\n// being profiled).\n//\n// For example, suppose \"A\" is profiled for a total time of 200ms, and\n// that includes a call to \"B\" of 150ms:\n//\n//     B: 150\n//     A (without B): 50\n//\n// and suppose there's another call to \"A\" which *doesn't* include a\n// call to \"B\":\n//\n//     A: 300\n//\n// and there's a call to \"B\" directly:\n//\n//     B: 100\n//\n// All for a total time of 600ms.  In the hierarchical report, this\n// looks like:\n//\n//     A: 500.0\n//       B: 150.0\n//       other A: 350.0\n//     B: 100.0\n//\n// and in the leaf time report:\n//\n//     other A: 350.0\n//     B: 250.0\n//\n// In both reports the grand total is 600ms.\n\nvar _ = require('underscore');\nvar Fiber = require('fibers');\n\nvar enabled = !! process.env['METEOR_PROFILE'];\nvar filter = parseFloat(process.env['METEOR_PROFILE']); // ms\nif (isNaN(filter)) {\n  filter = 100; // ms\n}\n\nvar bucketStats = {};\n\nvar SPACES_STR = ' ';\n// return a string of `x` spaces\nvar spaces = function (x) {\n  while (SPACES_STR.length < x) {\n    SPACES_STR = SPACES_STR + SPACES_STR;\n  }\n  return SPACES_STR.slice(0, x);\n};\n\nvar DOTS_STR = '.';\n// return a string of `x` dots\nvar dots = function (x) {\n  while (DOTS_STR.length < x) {\n    DOTS_STR = DOTS_STR + DOTS_STR;\n  }\n  return DOTS_STR.slice(0, x);\n};\n\n\nvar leftAlign = function (str, len) {\n  if (str.length < len) {\n    str = str + spaces(len - str.length);\n  }\n  return str;\n};\n\nvar rightAlign = function (str, len) {\n  if (str.length < len) {\n    str = spaces(len - str.length) + str;\n  }\n  return str;\n};\n\nvar leftRightAlign = function (str1, str2, len) {\n  var middle = Math.max(1, len - str1.length - str2.length);\n  return str1 + spaces(middle) + str2;\n};\n\nvar leftRightDots = function (str1, str2, len) {\n  var middle = Math.max(1, len - str1.length - str2.length);\n  return str1 + dots(middle) + str2;\n};\n\nvar printIndentation = function (isLastLeafStack) {\n  if (_.isEmpty(isLastLeafStack)) {\n    return '';\n  }\n\n  var init = _.map(_.initial(isLastLeafStack), function(isLastLeaf) {\n    return isLastLeaf ? '   ' : '│  ';\n  }).join('');\n  var last = _.last(isLastLeafStack) ? '└─ ' : '├─ ';\n  return init + last;\n};\n\nvar formatMs = function (n) {\n  // integer with thousands separators\n  return String(Math.round(n)).replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\") + \" ms\";\n};\n\nvar encodeEntryKey = function (entry) {\n  return entry.join('\\t');\n};\n\nvar decodeEntryKey = function (key) {\n  return key.split('\\t');\n};\n\nvar globalEntry = [];\n\nvar running = false;\nvar runningName;\n\nvar start = function () {\n  bucketStats = {};\n  running = true;\n};\n\nvar Profile = function (bucketName, f) {\n  if (! enabled) {\n    return f;\n  }\n\n  return function (...args) {\n    if (! running) {\n      return f.apply(this, args);\n    }\n\n    var name;\n    if (_.isFunction(bucketName)) {\n      name = bucketName.apply(this, args);\n    } else {\n      name = bucketName;\n    }\n\n    var currentEntry;\n    if (Fiber.current) {\n      currentEntry =\n        Fiber.current.profilerEntry || (Fiber.current.profilerEntry = []);\n    } else {\n      currentEntry = globalEntry;\n    }\n\n    currentEntry.push(name);\n    var key = encodeEntryKey(currentEntry);\n    var start = process.hrtime();\n    var err = null;\n    try {\n      return f.apply(this, args);\n    }\n    catch (e) {\n      err = e;\n    }\n    finally {\n      var elapsed = process.hrtime(start);\n      var stats = (bucketStats[key] || (bucketStats[key] = {\n        time: 0.0, count: 0\n      }));\n      stats.time += (elapsed[0] * 1000 + elapsed[1] / 1000000);\n      stats.count++;\n      currentEntry.pop();\n    }\n\n    if (err) {\n      throw err;\n    }\n  };\n};\n\nvar time = function (bucket, f) {\n  return Profile(bucket, f)();\n};\n\nvar entries = null;\n\nvar prefix = \"| \";\n\nvar entryName = function (entry) {\n  return _.last(entry);\n};\n\nvar entryStats = function (entry) {\n  return bucketStats[encodeEntryKey(entry)];\n};\n\nvar entryTime = function (entry) {\n  return entryStats(entry).time;\n};\n\nvar isTopLevelEntry = function (entry) {\n  return entry.length === 1;\n};\n\nvar topLevelEntries = function () {\n  return _.filter(entries, isTopLevelEntry);\n};\n\nvar print = function (text) {\n  console.log(prefix + text);\n};\n\nvar isChild = function (entry1, entry2) {\n  if (entry2.length !== entry1.length + 1) {\n    return false;\n  }\n  for (var i = entry1.length-1; i >= 0; i--) {\n    if (entry1[i] !== entry2[i]) {\n      return false;\n    }\n  }\n\n  return true;\n};\n\nvar children = function (entry1) {\n  return _.filter(entries, function (entry2) {\n    return isChild(entry1, entry2);\n  });\n}\n\nvar hasChildren = function (entry) {\n  return children(entry).length !== 0;\n};\n\nvar hasSignificantChildren = function (entry) {\n  return _.some(children(entry), function (entry) {\n    return (entryTime(entry) >= filter);\n  });\n};\n\nvar isLeaf = function (entry) {\n  return ! hasChildren(entry);\n};\n\nvar otherTime = function (entry) {\n  var total = 0;\n  _.each(children(entry), function (child) {\n    total += entryTime(child);\n  });\n  return entryTime(entry) - total;\n};\n\nvar injectOtherTime = function (entry) {\n  var name = \"other \" + entryName(entry);\n  var other = _.clone(entry);\n  other.push(name);\n  bucketStats[encodeEntryKey(other)] = {\n    time: otherTime(entry),\n    count: entryStats(entry).count,\n    isOther: true\n  };\n  entries.push(other);\n};\n\nvar reportOn = function (entry, isLastLeafStack = []) {\n  var stats = entryStats(entry);\n  var isParent = hasSignificantChildren(entry);\n  var name = entryName(entry);\n  print((isParent ? leftRightDots : leftRightAlign)\n        (printIndentation(isLastLeafStack) + name, formatMs(stats.time), 70)\n        + (stats.isOther ? \"\" : (\" (\" + stats.count + \")\")));\n\n  if (isParent) {\n    var childrenList = _.filter(children(entry), function(entry) {\n      var stats = entryStats(entry);\n      return stats.time > filter;\n    });\n    _.each(childrenList, function (child, i) {\n      var isLastLeaf = i === childrenList.length - 1;\n      reportOn(child, isLastLeafStack.concat(isLastLeaf));\n    });\n  }\n};\n\nvar reportHierarchy = function () {\n  _.each(topLevelEntries(), function (entry) {\n    reportOn(entry);\n  });\n};\n\nvar allLeafs = function () {\n  return _.union(_.map(_.filter(entries, isLeaf), entryName));\n};\n\nvar leafTotals = function (leafName) {\n  var time = 0;\n  var count = 0;\n  _.each(\n    _.filter(entries, function (entry) {\n      return entryName(entry) === leafName && isLeaf(entry);\n    }),\n    function (leaf) {\n      var stats = entryStats(leaf);\n      time += stats.time;\n      count += stats.count;\n    }\n  );\n  return {time, count};\n};\n\nvar reportHotLeaves = function () {\n  print('Top leaves:');\n  var totals = [];\n  _.each(allLeafs(), function (leaf) {\n    var info = leafTotals(leaf);\n    totals.push({name: leaf, time: info.time, count: info.count});\n  });\n  totals.sort(function (a, b) {\n    return a.time === b.time ? 0 : a.time > b.time ? -1 : 1;\n  });\n  _.each(totals, function (total) {\n    if (total.time < 100) { // hard-coded larger filter to quality as \"hot\" here\n      return;\n    }\n    print(leftRightDots(total.name, formatMs(total.time), 65) +\n          ` (${total.count})`);\n  });\n};\n\nvar getTopLevelTotal = function () {\n  var topTotal = 0;\n  _.each(topLevelEntries(), function (entry) {\n    topTotal += entryTime(entry);\n  });\n  return topTotal;\n};\n\nvar setupReport = function () {\n  entries = _.map(_.keys(bucketStats), decodeEntryKey);\n  _.each(_.filter(entries, hasSignificantChildren), function (parent) {\n    injectOtherTime(parent);\n  });\n};\n\nvar reportNum = 1;\n\nvar report = function () {\n  if (! enabled) {\n    return;\n  }\n  running = false;\n  print('');\n  setupReport();\n  reportHierarchy();\n  print('');\n  reportHotLeaves();\n  print('');\n  print(`(#${reportNum}) Total: ${formatMs(getTopLevelTotal())}` +\n        ` (${runningName})`);\n  print('');\n};\n\nvar run = function (bucketName, f) {\n  if (! enabled) {\n    return f();\n  } else if (running) {\n    // We've kept the calls to Profile.run in the tool disjoint so far,\n    // and should probably keep doing so, but if we mess up, warn and continue.\n    console.log(\"Warning: Nested Profile.run at \" + bucketName);\n    return time(bucketName, f);\n  } else {\n    runningName = bucketName;\n    print(`(#${reportNum}) Profiling: ${runningName}`);\n    start();\n    try {\n      return time(bucketName, f);\n    }\n    finally {\n      report();\n      reportNum++;\n    }\n  }\n};\n\nProfile.time = time;\nProfile.run = run;\n\nexports.Profile = Profile;\n"
  },
  {
    "path": "tools/tool-env/source-map-retriever-stack.js",
    "content": "import sourceMapSupport from 'source-map-support';\n\n// Why this file exists:\n// We have two places in the tool where we need to do source maps:\n// 1. Loaded isopacks, which use a special custom source map cache\n// 2. Transpiled tool code from Babel\n//\n// In order to avoid crazy bootstrapping, it would be nice to be able to add\n// functions to look for source maps, so that we can call\n// sourceMapSupport.install as early as possible, and not worry about having\n// the right data structures around.\n//\n// This module maintains a stack of source map retrieval functions, which are\n// called in reverse order until one returns a truthy value.\n\nconst stack = [];\n\n// Add a function to locate source maps; all of the functions are executed in\n// reverse order\nexport function push(func) {\n  stack.push(func);\n}\n\nfunction tryAllSourceMapRetrievers(filename) {\n  for (let i = stack.length - 1; i >= 0; i--) {\n    const sourceMapData = stack[i](filename);\n\n    if (sourceMapData) {\n      return sourceMapData;\n    }\n  }\n\n  return null;\n}\n\nfunction wrapCallSite(unwrappedFrame) {\n  const frame = sourceMapSupport.wrapCallSite(unwrappedFrame);\n  function wrapGetter(name) {\n    const origGetter = frame[name];\n    frame[name] = function(arg) {\n      // replace a custom location domain that we set for better UX in Chrome\n      // DevTools (separate domain group) in source maps.\n      const source = origGetter(arg);\n      if (!source) {\n        return source;\n      }\n      return source.replace(/(^|\\()meteor:\\/\\/..app\\//, '$1');\n    };\n  }\n  wrapGetter('getScriptNameOrSourceURL');\n  wrapGetter('getEvalOrigin');\n\n  return frame;\n}\n\n\nsourceMapSupport.install({\n  retrieveSourceMap: tryAllSourceMapRetrievers,\n  // Disable the feature of source-map-support that shows an accurate snippet\n  // of source code on uncaught exception, because we haven't fixed it to\n  // be able to locate the proper source code to display.  (Note that the\n  // stack trace of an uncaught exception will be correctly source-mapped\n  // independent of this option.)\n  handleUncaughtExceptions: false,\n  wrapCallSite\n});\n\n// Save the correct prepareStackTrace so that if third-party code overwrites\n// it (ahem, coffeescript), we can restore it.\nError.METEOR_prepareStackTrace = Error.prepareStackTrace;\n\n// Default retrievers\n\n// Always fall back to the default in the end\npush(sourceMapSupport.retrieveSourceMap);\n\n/* eslint-disable max-len */\npush(require('meteor-babel/register').retrieveSourceMap); // #RemoveInProd this line is removed in isopack.js\n/* eslint-enable max-len */\n"
  },
  {
    "path": "tools/tool-testing/README.md",
    "content": "# Tools testing\n\nRunning end-to-end tests happens through the Self-Test. To run the tests:\n\n```bash\n./meteor self-test <regexp>\n```\n\nA very-very useful environment variable to set, in case you are running on a\nslow machine:\n\n```bash\n# set the multiplier for time-outs\nset TIMEOUT_SCALE_FACTOR=3\n```\n\n## Writing tests\n\nAll tests are currently stored at `/tools/tests/`, each JS file can register a\nself-test. Example:\n\n```javascript\nselftest.define(\"mongo failover\", [/* tags */], function () {\n  var s = new Sandbox();\n  s.set('METEOR_TEST_MULTIPLE_MONGOD_REPLSET', 't');\n  s.createApp(\"failover-test\", \"failover-test\");\n  s.cd(\"failover-test\");\n\n  var run = s.run(\"--once\", \"--raw-logs\");\n  run.waitSecs(120);\n  run.match(\"SUCCESS\\n\");\n  run.expectEnd();\n  run.expectExit(0);\n});\n```\n\nThe example above demonstrates how to define a test, create a Sandbox, create an\napp from a template and run the Meteor commands.\n\nTemplates for apps and packages are kept in `/tools/tests`, too.\n\n## Testing with Phantom/Browserstack\n\nThe sandbox has a `testWithAllClients` method that runs the clients like Phantom\nor Browserstack pointed to the page of the app (`localhost:3000` by default).\n\n## Tags\n\nTags are arbitrary. To make tags do anything, you should edit the `selftest.js`\ncode.\n\nExamples of some tags that exist today:\n\n- `slow` - the test is skipped, unless the `--slow` flag is passed\n- `windows` - the test is not run unless on Windows\n- `net` - the test is talking to external Internet services, thus requires an\nInternet connection to run\n\nThere are others.\n\n## Self-test gotchas\n\n- The docs for self-test is reading the code of self-test\n- `run.forbid(regexp)` forbids the regexp from the entire output, not from the\n  point it was called. It happens, because the output is matched asynchronously.\n"
  },
  {
    "path": "tools/tool-testing/galaxy-utils.js",
    "content": "var _ = require('underscore');\nvar selftest = require('../tool-testing/selftest.js');\nvar Run = selftest.Run;\nvar testUtils = require('../tool-testing/test-utils.js');\nvar files = require('../fs/files.js');\nvar utils = require('../utils/utils.js');\nvar authClient = require('../meteor-services/auth-client.js');\nvar auth = require('../meteor-services/auth.js');\n\n// Run curl with the given specifications. Return an instance of Run.\nvar runCurl = function (/*args*/) {\n  var curl = \"/usr/bin/curl\";\n  return new Run(curl, {\n    args: _.toArray(arguments)\n  });\n};\n\n// Some constants.\nvar GALAXY_USERNAME = process.env.GALAXY_USERNAME;\nvar GALAXY_PASSWORD = process.env.GALAXY_PASSWORD;\nvar GALAXY_URL = process.env.DEPLOY_HOSTNAME;\nvar GALAXY_MOCK_MODE = process.env.GALAXY_MOCK_MODE;\n\n// Fail if the test is obviously not set up for using Galaxy.\n//\n// Make sure that we have at least set all of the variables that we need to run\n// against a Galaxy (GALAXY_URL, username & password). An extra safety\n// check to avoid strange errors, deploying/calling random methods on Mother,\n// etc.\nexports.sanityCheck = selftest.markStack(function () {\n  if (! GALAXY_URL ) {\n    selftest.fail(\"Please specify a GALAXY_URL to test against Galaxy.\\n\");\n  }\n  if (! GALAXY_USERNAME ||\n      ! GALAXY_PASSWORD) {\n    selftest.fail(\n      \"Can't use test account with Galaxy. \" +\n       \"Please specify GALAXY_USERNAME and GALAXY_PASSWORD.\\n\");\n  }\n  if (! process.env.APP_MONGO) {\n    selftest.fail(\n      \"Please provide an APP_MONGO url to use for deployed apps.\\n\");\n   }\n});\n\n// Login to Galaxy with environment-variable credentials passed in by the user.\n//\n// Unlike the normal `meteor deploy` Galaxy is not yet publically available, so\n// we don't want to use the publically-accessible test account here.\nexports.loginToGalaxy = selftest.markStack(function (sandbox) {\n  var user = GALAXY_USERNAME;\n  var pass = GALAXY_PASSWORD;\n  testUtils.login(sandbox, user, pass);\n});\n\n// Curl an app running on Galaxy. Automatically follow redirects.\n//\n// Dealing with DNS on Galaxy can be complicated. The standard way to ensure\n// that we hit the right app on the right Galaxy is to curl the galaxy origin,\n// with the host header set to our query app.\nexports.curlToGalaxy = selftest.markStack(function (url) {\n  var hostHeader = \"host: \" + url;\n  var galaxyOrigin = GALAXY_URL;\n  return runCurl(\"-vLH\", hostHeader, galaxyOrigin);\n});\n\n// String we expect to hit on 200 OK.\nexports.httpOK = \"HTTP/1.1 200 OK\";\n\n// String we expect to hit when using SSL.\nexports.httpRedirect = \"HTTP/1.1 307 Temporary Redirect\";\n\n// We expect containers to take some time to startup.\n//\n// In the future, we can use this function to poll whether the containers have\n// started and maybe our tests will be faster.\nexports.waitForContainers = selftest.markStack(function () {\n  // We are not spinning up any containers in mock mode, so don't wait too long.\n  var waitTime = GALAXY_MOCK_MODE ? 1000 : 1000 * 10 * utils.timeoutScaleFactor;\n  utils.sleepMs(waitTime);\n});\n\n// Deploy an app against a Galaxy\n//\n// When we deploy to Galaxy, we need to specify a Mongo URL and wait a little\n// longer for the app to spin up.\n//\n// Options:\n//   - settings: app settings, NOT including mandatory galaxy settings\n//     such as MONGO_URL\n//   - appName: app name to use; will be generated randomly if not\n//     provided\n//   - templateApp: the name of the template app to use. defaults to\n//    'simple-app'\n//   - useOldSettings: don't make a new settings object this app! This is a\n//     redeploy, so reuse the settings that Galaxy has saved.\n//\nexports.createAndDeployApp =  selftest.markStack(function (sandbox, options) {\n  options = options || {};\n  var settings = options.settings;\n  var appName = options.appName || testUtils.randomAppName();\n\n  // The simple app contains standart app packages and some small bits of code\n  // so that we can check that it is being served correctly. Let's use that as\n  // our default.\n  var templateApp = options.templateApp || 'simple-app';\n\n  // Create the new galaxy settings.\n  var galaxySettings = {\n    \"galaxy.meteor.com\" : {\n      env: {\n        // XXX: Right now, all the galaxy test apps use the same mongo. This is\n        // actually kind of super awkward... but generating and destroying new DBs\n        // seems like it is introducing a bit too much complexity at this stage.\n        \"MONGO_URL\": process.env.APP_MONGO\n      }\n    }\n  };\n\n  var fullAppName;\n  if (! options.useOldSettings) {\n    // Add all the settings together and write them out. Let user settings\n    // override ours.\n    var allSettings = _.extend(galaxySettings, settings);\n    var settingsFile = \"settings-\" + appName + \".json\";\n    sandbox.write(settingsFile, JSON.stringify(allSettings));\n\n    fullAppName = testUtils.createAndDeployApp(sandbox, {\n      settingsFile: \"../\" + settingsFile,\n      appName: appName,\n      templateApp: templateApp\n    });\n  } else {\n    fullAppName = testUtils.createAndDeployApp(sandbox, {\n      appName: appName,\n      templateApp: templateApp\n    });\n  }\n\n  // Galaxy might take a while to spin up an app.\n  exports.waitForContainers();\n\n  return fullAppName;\n\n});\n\n// Cleanup the app by deleting it from Galaxy.\n//\n// XXX: We should also clean out its Mongo, but we don't, since, currently, none\n// of our apps actually put any records into it.\nexports.cleanUpApp = selftest.markStack(function (sandbox, appName) {\n  testUtils.cleanUpApp(sandbox, appName);\n\n  // Galaxy might take a while to spin up an app, though it should be fairly\n  // quick.\n  exports.waitForContainers();\n});\n\n//////////////////////////////////////////////////////////////////////////////\n//  We want to test some of the server-side functionality that doesn't actually\n//  have a command-line API right now. Below functionas are going to use the\n//  tool's ability to make a DDP client and connect to the server to call\n//  methods directly.\n////////////////////////////////////////////////////////////////////////////////\n\n// Returns a logged in connection to GalaxyAPI\nexports.loggedInGalaxyAPIConnection = selftest.markStack(function () {\n  // The credentials of the user might not be the credentials of the galaxytester.\n  auth.doInteractivePasswordLogin({\n    username: GALAXY_USERNAME,\n    password: GALAXY_PASSWORD\n  });\n  var galaxyDomain = GALAXY_URL;\n  var galaxyUrl = (GALAXY_MOCK_MODE ? \"http://\" : \"https://\") + galaxyDomain;\n  return authClient.loggedInConnection(\n    galaxyUrl,\n    galaxyDomain,\n    \"galaxy-api\"\n  );\n});\n\n// If the connection has disconnected, close it and open a new one. (workaround\n// for the fact that connections in the tool do not reconnect)\nexports.renewConnection = selftest.markStack(function (conn) {\n  if (!conn.connected) {\n    conn.close();\n    conn = exports.loggedInGalaxyAPIConnection();\n  }\n  return conn;\n});\n\n// Given a connection, makes a call to Galaxy API.\nexports.callGalaxyAPI = function (conn, ...args) {\n  conn = exports.renewConnection(conn);\n  return conn.call(...args);\n};\n\n// Gets app record from Galaxy API by name.\n//\n// This method will create and manage its own connection.\nexports.getAppRecordByName = selftest.markStack(function (appName) {\n  var conn = exports.loggedInGalaxyAPIConnection();\n  var appRecord = {};\n  conn.connection.registerStore('app', {\n    update: function (msg) {\n      if (msg.msg === 'added' && msg.fields &&\n          msg.fields.hostname === appName) {\n        appRecord = _.extend({ _id: msg.id }, msg.fields);\n      }\n    }\n  });\n  conn.subscribeAndWait(\"/app\", appName);\n  // If we can't find the app, fail the test right now.\n  if (_.isEmpty(appRecord)) {\n    selftest.fail(\"Cannot find app: \", appName);\n  }\n  conn.close();\n  return appRecord;\n});\n\n\n// Get container statuses for the given app ID.\n//\n// This method will create and manage its own connection.\nexports.getAppContainerStatuses = selftest.markStack(function (appId, appName) {\n  var conn = exports.loggedInGalaxyAPIConnection();\n\n  var containers = [];\n  var statuses = \"/app/containerStatuses\";\n  conn.connection.registerStore(statuses, {\n    update: function (msg) {\n      if (msg.msg === 'added' && msg.fields &&\n          msg.fields.appId === appId) {\n        containers.push(_.extend({ _id: msg.id }, msg.fields));\n      }\n    }\n  });\n  conn.subscribeAndWait(statuses, appName);\n  conn.close();\n  return containers;\n});\n\n// Close and logout.\nexports.closeGalaxyConnection = selftest.markStack(function (conn) {\n  auth.logoutCommand();\n  conn.close();\n});\n\n\n// Ignore HTTP checks in mock mode\nexports.ignoreHttpChecks = selftest.markStack(function () {\n  return !! GALAXY_MOCK_MODE;\n});\n"
  },
  {
    "path": "tools/tool-testing/phantom/open-url.js",
    "content": "var system = require('system');\nvar webpage = require('webpage');\n\nif (system.args.length < 2) {\n  throw new Error(\"Must pass URL argument to this script.\");\n}\n\nconsole.log(\"opening webpage\", system.args[1]);\n\nwebpage.create().open(system.args[1]);"
  },
  {
    "path": "tools/tool-testing/selftest.js",
    "content": "var _ = require('underscore');\nvar util = require('util');\nvar Future = require('fibers/future');\nvar fiberHelpers = require('../utils/fiber-helpers.js');\nvar child_process = require('child_process');\nvar webdriver = require('browserstack-webdriver');\n\nvar files = require('../fs/files.js');\nvar utils = require('../utils/utils.js');\nvar parseStack = require('../utils/parse-stack.js');\nvar Console = require('../console/console.js').Console;\nvar archinfo = require('../utils/archinfo.js');\nvar config = require('../meteor-services/config.js');\nvar buildmessage = require('../utils/buildmessage.js');\nvar execFileSync = require('../utils/processes.js').execFileSync;\nvar Builder = require('../isobuild/builder.js').default;\n\nvar catalog = require('../packaging/catalog/catalog.js');\nvar catalogRemote = require('../packaging/catalog/catalog-remote.js');\nvar isopackCacheModule = require('../isobuild/isopack-cache.js');\nvar isopackets = require('../tool-env/isopackets.js');\n\nvar tropohouseModule = require('../packaging/tropohouse.js');\nvar packageMapModule = require('../packaging/package-map.js');\nvar release = require('../packaging/release.js');\n\nvar projectContextModule = require('../project-context.js');\nvar upgraders = require('../upgraders.js');\n\ntry {\n  var phantomjs = require('phantomjs-prebuilt');\n} catch (e) {\n  throw new Error([\n    \"Please install PhantomJS by running the following command:\",\n    \"\",\n    \"  meteor npm install -g phantomjs-prebuilt\",\n    \"\"\n  ].join(\"\\n\"));\n}\n\n// To allow long stack traces that cross async boundaries\nrequire('longjohn');\n\n// Exception representing a test failure\nvar TestFailure = function (reason, details) {\n  var self = this;\n  self.reason = reason;\n  self.details = details || {};\n  self.stack = (new Error).stack;\n};\n\n// Use this to decorate functions that throw TestFailure. Decorate the\n// first function that should not be included in the call stack shown\n// to the user.\nvar markStack = function (f) {\n  return parseStack.markTop(f);\n};\n\n// Call from a test to throw a TestFailure exception and bail out of the test\nvar fail = markStack(function (reason) {\n  throw new TestFailure(reason);\n});\n\n// Call from a test to assert that 'actual' is equal to 'expected',\n// with 'actual' being the value that the test got and 'expected'\n// being the expected value\nvar expectEqual = markStack(function (actual, expected) {\n  var Package = isopackets.load('ejson');\n  if (! Package.ejson.EJSON.equals(actual, expected)) {\n    throw new TestFailure(\"not-equal\", {\n      expected: expected,\n      actual: actual\n    });\n  }\n});\n\n// Call from a test to assert that 'actual' is truthy.\nvar expectTrue = markStack(function (actual) {\n  if (! actual) {\n    throw new TestFailure('not-true');\n  }\n});\n// Call from a test to assert that 'actual' is falsey.\nvar expectFalse = markStack(function (actual) {\n  if (actual) {\n    throw new TestFailure('not-false');\n  }\n});\n\nvar expectThrows = markStack(function (f) {\n  var threw = false;\n  try {\n    f();\n  } catch (e) {\n    threw = true;\n  }\n\n  if (! threw) {\n    throw new TestFailure(\"expected-exception\");\n  }\n});\n\nvar doOrThrow = function (f) {\n  var ret;\n  var messages = buildmessage.capture(function () {\n    ret = f();\n  });\n  if (messages.hasMessages()) {\n    throw Error(messages.formatMessages());\n  }\n  return ret;\n};\n\n// Our current strategy for running tests that need warehouses is to build all\n// packages from the checkout into this temporary tropohouse directory, and for\n// each test that need a fake warehouse, copy the built packages into the\n// test-specific warehouse directory.  This isn't particularly fast, but it'll\n// do for now. We build the packages during the first test that needs them.\nvar builtPackageTropohouseDir = null;\nvar tropohouseLocalCatalog = null;\nvar tropohouseIsopackCache = null;\n\n// Let's build a minimal set of packages that's enough to get self-test\n// working.  (And that doesn't need us to download any Atmosphere packages.)\nvar ROOT_PACKAGES_TO_BUILD_IN_SANDBOX = [\n  // We need the tool in order to run from the fake warehouse at all.\n  \"meteor-tool\",\n\n  // We need the packages in the skeleton app in order to test 'meteor create'.\n  'meteor-base',\n  'mobile-experience',\n  'mongo',\n  'blaze-html-templates',\n  'session',\n  'jquery',\n  'tracker',\n  \"autopublish\",\n  \"insecure\",\n  \"standard-minifier-css\",\n  \"standard-minifier-js\",\n  \"es5-shim\"\n];\n\nvar setUpBuiltPackageTropohouse = function () {\n  if (builtPackageTropohouseDir) {\n    return;\n  }\n  builtPackageTropohouseDir = files.mkdtemp('built-package-tropohouse');\n\n  if (config.getPackagesDirectoryName() !== 'packages') {\n    throw Error(\"running self-test with METEOR_PACKAGE_SERVER_URL set?\");\n  }\n\n  var tropohouse = new tropohouseModule.Tropohouse(builtPackageTropohouseDir);\n  tropohouseLocalCatalog = newSelfTestCatalog();\n  var versions = {};\n  _.each(\n    tropohouseLocalCatalog.getAllNonTestPackageNames(),\n    function (packageName) {\n      versions[packageName] =\n        tropohouseLocalCatalog.getLatestVersion(packageName).version;\n  });\n  var packageMap = new packageMapModule.PackageMap(versions, {\n    localCatalog: tropohouseLocalCatalog\n  });\n  // Make an isopack cache that doesn't automatically save isopacks to disk and\n  // has no access to versioned packages.\n  tropohouseIsopackCache = new isopackCacheModule.IsopackCache({\n    packageMap: packageMap,\n    includeCordovaUnibuild: true\n  });\n  doOrThrow(function () {\n    buildmessage.enterJob(\"building self-test packages\", function () {\n      // Build the packages into the in-memory IsopackCache.\n      tropohouseIsopackCache.buildLocalPackages(\n        ROOT_PACKAGES_TO_BUILD_IN_SANDBOX);\n    });\n  });\n\n  // Save all the isopacks into builtPackageTropohouseDir/packages.  (Note that\n  // we are always putting them into the default 'packages' (assuming\n  // $METEOR_PACKAGE_SERVER_URL is not set in the self-test process itself) even\n  // though some tests will want them to be under\n  // 'packages-for-server/test-packages'; we'll fix this in _makeWarehouse.\n  tropohouseIsopackCache.eachBuiltIsopack(function (name, isopack) {\n    tropohouse._saveIsopack(isopack, name);\n  });\n};\n\nvar newSelfTestCatalog = function () {\n  if (! files.inCheckout()) {\n    throw Error(\"Only can build packages from a checkout\");\n  }\n\n  var catalogLocal = require('../packaging/catalog/catalog-local.js');\n  var selfTestCatalog = new catalogLocal.LocalCatalog;\n  var messages = buildmessage.capture(\n    { title: \"scanning local core packages\" },\n    function () {\n      // When building a fake warehouse from a checkout, we use local packages,\n      // but *ONLY THOSE FROM THE CHECKOUT*: not app packages or $PACKAGE_DIRS\n      // packages.  One side effect of this: we really really expect them to all\n      // build, and we're fine with dying if they don't (there's no worries\n      // about needing to springboard).\n      selfTestCatalog.initialize({\n        localPackageSearchDirs: [files.pathJoin(\n          files.getCurrentToolsDir(), 'packages')]\n      });\n    });\n  if (messages.hasMessages()) {\n    Console.arrowError(\"Errors while scanning core packages:\");\n    Console.printMessages(messages);\n    throw new Error(\"scan failed?\");\n  }\n  return selfTestCatalog;\n};\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Matcher\n///////////////////////////////////////////////////////////////////////////////\n\n// Handles the job of waiting until text is seen that matches a\n// regular expression.\n\nvar Matcher = function (run) {\n  var self = this;\n  self.buf = \"\";\n  self.ended = false;\n  self.matchPattern = null;\n  self.matchPromise = null;\n  self.matchStrict = null;\n  self.run = run; // used only to set a field on exceptions\n};\n\n_.extend(Matcher.prototype, {\n  write: function (data) {\n    var self = this;\n    self.buf += data;\n    self._tryMatch();\n  },\n\n  match: function (pattern, timeout, strict) {\n    var self = this;\n    if (self.matchPromise) {\n      throw new Error(\"already have a match pending?\");\n    }\n    self.matchPattern = pattern;\n    self.matchStrict = strict;\n    var mp = self.matchPromise = fiberHelpers.makeFulfillablePromise();\n    self._tryMatch(); // could clear self.matchPromise\n\n    var timer = null;\n    if (timeout) {\n      timer = setTimeout(function () {\n        var pattern = self.matchPattern;\n        self.matchPattern = null;\n        self.matchStrict = null;\n        self.matchPromise = null;\n        mp.reject(new TestFailure('match-timeout', {\n          run: self.run,\n          pattern: pattern\n        }));\n      }, timeout * 1000);\n    }\n\n    try {\n      return mp.await();\n    } finally {\n      if (timer) {\n        clearTimeout(timer);\n      }\n    }\n  },\n\n  end: function () {\n    var self = this;\n    self.ended = true;\n    self._tryMatch();\n  },\n\n  matchEmpty: function () {\n    var self = this;\n\n    if (self.buf.length > 0) {\n      Console.info(\"Extra junk is :\", self.buf);\n      throw new TestFailure('junk-at-end', { run: self.run });\n    }\n  },\n\n  _tryMatch: function () {\n    var self = this;\n\n    var mp = self.matchPromise;\n    if (! mp) {\n      return;\n    }\n\n    var ret = null;\n\n    if (self.matchPattern instanceof RegExp) {\n      var m = self.buf.match(self.matchPattern);\n      if (m) {\n        if (self.matchStrict && m.index !== 0) {\n          self.matchPromise = null;\n          self.matchStrict = null;\n          self.matchPattern = null;\n          Console.info(\"Extra junk is: \", self.buf.substr(0, m.index));\n          mp.reject(new TestFailure('junk-before', {\n            run: self.run,\n            pattern: self.matchPattern\n          }));\n          return;\n        }\n        ret = m;\n        self.buf = self.buf.slice(m.index + m[0].length);\n      }\n    } else {\n      var i = self.buf.indexOf(self.matchPattern);\n      if (i !== -1) {\n        if (self.matchStrict && i !== 0) {\n          self.matchPromise = null;\n          self.matchStrict = null;\n          self.matchPattern = null;\n          Console.info(\"Extra junk is: \", self.buf.substr(0, i));\n          mp.reject(new TestFailure('junk-before', {\n            run: self.run,\n            pattern: self.matchPattern\n          }));\n          return;\n        }\n        ret = self.matchPattern;\n        self.buf = self.buf.slice(i + self.matchPattern.length);\n      }\n    }\n\n    if (ret !== null) {\n      self.matchPromise = null;\n      self.matchStrict = null;\n      self.matchPattern = null;\n      mp.resolve(ret);\n      return;\n    }\n\n    if (self.ended) {\n      var failure = new TestFailure('no-match', { run: self.run,\n                                                  pattern: self.matchPattern });\n      self.matchPromise = null;\n      self.matchStrict = null;\n      self.matchPattern = null;\n      mp.reject(failure);\n      return;\n    }\n  }\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// OutputLog\n///////////////////////////////////////////////////////////////////////////////\n\n// Maintains a line-by-line merged log of multiple output channels\n// (eg, stdout and stderr).\n\nvar OutputLog = function (run) {\n  var self = this;\n\n  // each entry is an object with keys 'channel', 'text', and if it is\n  // the last entry and there was no newline terminator, 'bare'\n  self.lines = [];\n\n  // map from a channel name to an object representing a partially\n  // read line of text on that channel. That object has keys 'text'\n  // (text read), 'offset' (cursor position, equal to text.length\n  // unless a '\\r' has been read).\n  self.buffers = {};\n\n  // a Run, exclusively for inclusion in exceptions\n  self.run = run;\n};\n\n_.extend(OutputLog.prototype, {\n  write: function (channel, text) {\n    var self = this;\n\n    if (! _.has(self.buffers, 'channel')) {\n      self.buffers[channel] = { text: '', offset: 0};\n    }\n    var b = self.buffers[channel];\n\n    while (text.length) {\n      var m = text.match(/^[^\\n\\r]+/);\n      if (m) {\n        // A run of non-control characters.\n        b.text = b.text.substr(0, b.offset) +\n          m[0] + b.text.substr(b.offset + m[0].length);\n        b.offset += m[0].length;\n        text = text.substr(m[0].length);\n        continue;\n      }\n\n      if (text[0] === '\\r') {\n        b.offset = 0;\n        text = text.substr(1);\n        continue;\n      }\n\n      if (text[0] === '\\n') {\n        self.lines.push({ channel: channel, text: b.text });\n        b.text = '';\n        b.offset = 0;\n        text = text.substr(1);\n        continue;\n      }\n\n      throw new Error(\"conditions should have been exhaustive?\");\n    }\n  },\n\n  end: function () {\n    var self = this;\n\n    _.each(_.keys(self.buffers), function (channel) {\n      if (self.buffers[channel].text.length) {\n        self.lines.push({ channel: channel,\n                          text: self.buffers[channel].text,\n                          bare: true });\n        self.buffers[channel] = { text: '', offset: 0};\n      }\n    });\n  },\n\n  forbid: function (pattern, channel) {\n    var self = this;\n    _.each(self.lines, function (line) {\n      if (channel && channel !== line.channel) {\n        return;\n      }\n\n      var match = (pattern instanceof RegExp) ?\n        (line.text.match(pattern)) : (line.text.indexOf(pattern) !== -1);\n      if (match) {\n        throw new TestFailure('forbidden-string-present', { run: self.run });\n      }\n    });\n  },\n\n  get: function () {\n    var self = this;\n    return self.lines;\n  }\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Sandbox\n///////////////////////////////////////////////////////////////////////////////\n\n// Represents an install of the tool. Creating this creates a private\n// sandbox with its own state, separate from the state of the current\n// meteor install or checkout, from the user's homedir, and from the\n// state of any other sandbox. It also creates an empty directory\n// which will be, by default, the cwd for runs created inside the\n// sandbox (you can change this with the cd() method).\n//\n// This will throw TestFailure if it has to build packages to set up\n// the sandbox and the build fails. So, only call it from inside\n// tests.\n//\n// options:\n// - warehouse: set to sandbox the warehouse too. If you don't do\n//   this, the tests are run in the same context (checkout or\n//   warehouse) as the actual copy of meteor you're running (the\n//   meteor in 'meteor self-test'. This may only be set when you're\n//   running 'meteor self-test' from a checkout. If it is set, it\n//   should look something like this:\n//   {\n//     version1: { tools: 'tools1', notices: (...) },\n//     version2: { tools: 'tools2', upgraders: [\"a\"],\n//     notices: (...), latest: true }\n//   }\n//   This would set up a simulated warehouse with two releases in it,\n//   one called 'version1' and having a tools version of 'tools1', and\n//   similarly with 'version2'/'tools2', with the latter being marked\n//   as the latest release, and the latter also having a single\n//   upgrader named \"a\". The releases are made by building the\n//   checkout into a release, and are identical except for their\n//   version names. If you pass 'notices' (which is optional), set it\n//   to the verbatim contents of the notices.json file for the\n//   release, as an object.\n// - fakeMongo: if set, set an environment variable that causes our\n//   'fake-mongod' stub process to be started instead of 'mongod'. The\n//   tellMongo method then becomes available on Runs for controlling\n//   the stub.\n// - clients\n//   - browserstack: true if browserstack clients should be used\n//   - port: the port that the clients should run on\n\nvar Sandbox = function (options) {\n  var self = this;\n  // default options\n  options = _.extend({ clients: {} }, options);\n\n  self.root = files.mkdtemp();\n  self.warehouse = null;\n\n  self.home = files.pathJoin(self.root, 'home');\n  files.mkdir(self.home, 0o755);\n  self.cwd = self.home;\n  self.env = {};\n  self.fakeMongo = options.fakeMongo;\n\n  if (_.has(options, 'warehouse')) {\n    if (!files.inCheckout()) {\n      throw Error(\"make only use a fake warehouse in a checkout\");\n    }\n    self.warehouse = files.pathJoin(self.root, 'tropohouse');\n    self._makeWarehouse(options.warehouse);\n  }\n\n  self.clients = [new PhantomClient({\n    host: 'localhost',\n    port: options.clients.port || 3000\n  })];\n\n  if (options.clients && options.clients.browserstack) {\n    var browsers = [\n      { browserName: 'firefox' },\n      { browserName: 'chrome' },\n      { browserName: 'internet explorer',\n        browserVersion: '11' },\n      { browserName: 'internet explorer',\n        browserVersion: '8',\n        timeout: 60 },\n      { browserName: 'safari' },\n      { browserName: 'android' }\n    ];\n\n    _.each(browsers, function (browser) {\n      self.clients.push(new BrowserStackClient({\n        host: 'localhost',\n        port: 3000,\n        browserName: browser.browserName,\n        browserVersion: browser.browserVersion,\n        timeout: browser.timeout\n      }));\n    });\n  }\n\n  var meteorScript = process.platform === \"win32\" ? \"meteor.bat\" : \"meteor\";\n\n  // Figure out the 'meteor' to run\n  if (self.warehouse) {\n    self.execPath = files.pathJoin(self.warehouse, meteorScript);\n  } else {\n    self.execPath = files.pathJoin(files.getCurrentToolsDir(), meteorScript);\n  }\n};\n\n_.extend(Sandbox.prototype, {\n  // Create a new test run of the tool in this sandbox.\n  run: function (...args) {\n    var self = this;\n\n    return new Run(self.execPath, {\n      sandbox: self,\n      args: args,\n      cwd: self.cwd,\n      env: self._makeEnv(),\n      fakeMongo: self.fakeMongo\n    });\n  },\n\n  // Tests a set of clients with the argument function. Each call to f(run)\n  // instantiates a Run with a different client.\n  // Use:\n  // sandbox.testWithAllClients(function (run) {\n  //   // pre-connection checks\n  //   run.connectClient();\n  //   // post-connection checks\n  // });\n  testWithAllClients: function (f, ...args) {\n    var self = this;\n    args = _.compact(args);\n\n    console.log(\"running test with \" + self.clients.length + \" client(s).\");\n\n    _.each(self.clients, function (client) {\n      console.log(\"testing with \" + client.name + \"...\");\n      var run = new Run(self.execPath, {\n        sandbox: self,\n        args: args,\n        cwd: self.cwd,\n        env: self._makeEnv(),\n        fakeMongo: self.fakeMongo,\n        client: client\n      });\n      run.baseTimeout = client.timeout;\n      f(run);\n    });\n  },\n\n  // Copy an app from a template into the current directory in the\n  // sandbox. 'to' is the subdirectory to put the app in, and\n  // 'template' is a subdirectory of tools/tests/apps to copy.\n  //\n  // Note that the arguments are the opposite order from 'cp'. That\n  // seems more intuitive to me -- if you disagree, my apologies.\n  //\n  // For example:\n  //   s.createApp('myapp', 'empty');\n  //   s.cd('myapp');\n  createApp: function (to, template, options) {\n    var self = this;\n    options = options || {};\n    var absoluteTo = files.pathJoin(self.cwd, to);\n    files.cp_r(files.pathJoin(\n      files.convertToStandardPath(__dirname), '..', 'tests', 'apps', template),\n        absoluteTo, { ignore: [/^local$/] });\n    // If the test isn't explicitly managing a mock warehouse, ensure that apps\n    // run with our release by default.\n    if (options.release) {\n      self.write(files.pathJoin(to, '.meteor/release'), options.release);\n    } else if (!self.warehouse && release.current.isProperRelease()) {\n      self.write(files.pathJoin(to, '.meteor/release'), release.current.name);\n    }\n\n    // Make sure the apps don't run any upgraders, unless they intentionally\n    // have a partial upgraders file\n    var upgradersFile =\n      new projectContextModule.FinishedUpgraders({projectDir: absoluteTo});\n    if (_.isEmpty(upgradersFile.readUpgraders())) {\n      upgradersFile.appendUpgraders(upgraders.allUpgraders());\n    }\n\n    if (options.dontPrepareApp) {\n      return;\n    }\n\n    // Prepare the app (ie, build or download packages). We give this a nice\n    // long timeout, which allows the next command to not need a bloated\n    // timeout. (meteor create does this anyway.)\n    self.cd(to, function () {\n      var run = self.run(\"--prepare-app\");\n      // XXX Can we cache the output of running this once somewhere, so that\n      // multiple calls to createApp with the same template get the same cache?\n      // This is a little tricky because isopack-buildinfo.json uses absolute\n      // paths.\n      run.waitSecs(120);\n      run.expectExit(0);\n    });\n  },\n\n  // Same as createApp, but with a package.\n  //\n  // @param packageDir  {String} The directory in which to create the package\n  // @param packageName {String} The package name to create. This string will\n  //                             replace all appearances of ~package-name~\n  //                             in any package*.js files in the template\n  // @param template    {String} The package template to use. Found as a\n  //                             subdirectory in tests/packages/\n  //\n  // For example:\n  //   s.createPackage('me_mypack', me:mypack', 'empty');\n  //   s.cd('me_mypack');\n  createPackage: function (packageDir, packageName, template) {\n    var self = this;\n    var packagePath = files.pathJoin(self.cwd, packageDir);\n    var templatePackagePath = files.pathJoin(\n      files.convertToStandardPath(__dirname), '..', 'tests', 'packages', template);\n    files.cp_r(templatePackagePath, packagePath);\n\n    _.each(files.readdir(packagePath), function (file) {\n      if (file.match(/^package.*\\.js$/)) {\n        var packageJsFile = files.pathJoin(packagePath, file);\n        files.writeFile(\n          packageJsFile,\n          files.readFile(packageJsFile, \"utf8\")\n            .replace(\"~package-name~\", packageName));\n      }\n    });\n  },\n\n  // Change the cwd to be used for subsequent runs. For example:\n  //   s.run('create', 'myapp').expectExit(0);\n  //   s.cd('myapp');\n  //   s.run('add', 'somepackage') ...\n  // If you provide a callback, it will invoke the callback and then\n  // change the cwd back to the previous value.  eg:\n  //   s.cd('app1', function () {\n  //     s.run('add', 'somepackage');\n  //   });\n  //   s.cd('app2', function () {\n  //     s.run('add', 'somepackage');\n  //   });\n  cd: function (relativePath, callback) {\n    var self = this;\n    var previous = self.cwd;\n    self.cwd = files.pathResolve(self.cwd, relativePath);\n    if (callback) {\n      callback();\n      self.cwd = previous;\n    }\n  },\n\n  // Set an environment variable for subsequent runs.\n  set: function (name, value) {\n    var self = this;\n    self.env[name] = value;\n  },\n\n  // Undo set().\n  unset: function (name) {\n    var self = this;\n    delete self.env[name];\n  },\n\n  // Write to a file in the sandbox, overwriting its current contents\n  // if any. 'filename' is a path intepreted relative to the Sandbox's\n  // cwd. 'contents' is a string (utf8 is assumed).\n  write: function (filename, contents) {\n    var self = this;\n    files.writeFile(files.pathJoin(self.cwd, filename), contents, 'utf8');\n  },\n\n  // Like writeFile, but appends rather than writes.\n  append: function (filename, contents) {\n    var self = this;\n    files.appendFile(files.pathJoin(self.cwd, filename), contents, 'utf8');\n  },\n\n  // Reads a file in the sandbox as a utf8 string. 'filename' is a\n  // path intepreted relative to the Sandbox's cwd.  Returns null if\n  // file does not exist.\n  read: function (filename) {\n    var self = this;\n    var file = files.pathJoin(self.cwd, filename);\n    if (!files.exists(file)) {\n      return null;\n    } else {\n      return files.readFile(files.pathJoin(self.cwd, filename), 'utf8');\n    }\n  },\n\n  // Copy the contents of one file to another.  In these series of tests, we often\n  // want to switch contents of package.js files. It is more legible to copy in\n  // the backup file rather than trying to write into it manually.\n  cp: function(from, to) {\n    var self = this;\n    var contents = self.read(from);\n    if (!contents) {\n      throw new Error(\"File \" + from + \" does not exist.\");\n    };\n    self.write(to, contents);\n  },\n\n  // Delete a file in the sandbox. 'filename' is as in write().\n  unlink: function (filename) {\n    var self = this;\n    files.unlink(files.pathJoin(self.cwd, filename));\n  },\n\n  // Make a directory in the sandbox. 'filename' is as in write().\n  mkdir: function (dirname) {\n    var self = this;\n    var dirPath = files.pathJoin(self.cwd, dirname);\n    if (! files.exists(dirPath)) {\n      files.mkdir(dirPath);\n    }\n  },\n\n  // Rename something in the sandbox. 'oldName' and 'newName' are as in write().\n  rename: function (oldName, newName) {\n    var self = this;\n    files.rename(files.pathJoin(self.cwd, oldName),\n                 files.pathJoin(self.cwd, newName));\n  },\n\n  // Return the current contents of .meteorsession in the sandbox.\n  readSessionFile: function () {\n    var self = this;\n    return files.readFile(files.pathJoin(self.root, '.meteorsession'), 'utf8');\n  },\n\n  // Overwrite .meteorsession in the sandbox with 'contents'. You\n  // could use this in conjunction with readSessionFile to save and\n  // restore authentication states.\n  writeSessionFile: function (contents) {\n    var self = this;\n    return files.writeFile(files.pathJoin(self.root, '.meteorsession'),\n                           contents, 'utf8');\n  },\n\n  _makeEnv: function () {\n    var self = this;\n    var env = _.clone(self.env);\n    env.METEOR_SESSION_FILE = files.convertToOSPath(\n      files.pathJoin(self.root, '.meteorsession'));\n\n    if (self.warehouse) {\n      // Tell it where the warehouse lives.\n      env.METEOR_WAREHOUSE_DIR = files.convertToOSPath(self.warehouse);\n\n      // Don't ever try to refresh the stub catalog we made.\n      env.METEOR_OFFLINE_CATALOG = \"t\";\n    }\n\n    // By default (ie, with no mock warehouse and no --release arg) we should be\n    // testing the actual release this is built in, so we pretend that it is the\n    // latest release.\n    if (!self.warehouse && release.current.isProperRelease()) {\n      env.METEOR_TEST_LATEST_RELEASE = release.current.name;\n    }\n\n    // Allow user to set TOOL_NODE_FLAGS for self-test app.\n    if (process.env.TOOL_NODE_FLAGS && ! process.env.SELF_TEST_TOOL_NODE_FLAGS)\n      console.log('Consider setting SELF_TEST_TOOL_NODE_FLAGS to configure ' +\n                  'self-test test applicaion spawns');\n    env.TOOL_NODE_FLAGS = process.env.SELF_TEST_TOOL_NODE_FLAGS || '';\n\n    return env;\n  },\n\n  // Writes a stub warehouse (really a tropohouse) to the directory\n  // self.warehouse. This warehouse only contains a meteor-tool package and some\n  // releases containing that tool only (and no packages).\n  //\n  // packageServerUrl indicates which package server we think we are using. Use\n  // the default, if we do not pass this in; you should pass it in any case that\n  // you will be specifying $METEOR_PACKAGE_SERVER_URL in the environment of a\n  // command you are running in this sandbox.\n  _makeWarehouse: function (releases) {\n    var self = this;\n\n    // Ensure we have a tropohouse to copy stuff out of.\n    setUpBuiltPackageTropohouse();\n\n    var serverUrl = self.env.METEOR_PACKAGE_SERVER_URL;\n    var packagesDirectoryName = config.getPackagesDirectoryName(serverUrl);\n\n    var builder = new Builder({outputPath: self.warehouse});\n    builder.copyDirectory({\n      from: files.pathJoin(builtPackageTropohouseDir, 'packages'),\n      to: packagesDirectoryName,\n      symlink: true\n    });\n    builder.complete();\n\n    var stubCatalog = {\n      syncToken: {},\n      formatVersion: \"1.0\",\n      collections: {\n        packages: [],\n        versions: [],\n        builds: [],\n        releaseTracks: [],\n        releaseVersions: []\n      }\n    };\n\n    var packageVersions = {};\n    var toolPackageVersion = null;\n\n    tropohouseIsopackCache.eachBuiltIsopack(function (packageName, isopack) {\n      var packageRec = tropohouseLocalCatalog.getPackage(packageName);\n      if (! packageRec) {\n        throw Error(\"no package record for \" + packageName);\n      }\n      stubCatalog.collections.packages.push(packageRec);\n\n      var versionRec = tropohouseLocalCatalog.getLatestVersion(packageName);\n      if (! versionRec) {\n        throw Error(\"no version record for \" + packageName);\n      }\n      stubCatalog.collections.versions.push(versionRec);\n\n      stubCatalog.collections.builds.push({\n        buildArchitectures: isopack.buildArchitectures(),\n        versionId: versionRec._id,\n        _id: utils.randomToken()\n      });\n\n      if (packageName === \"meteor-tool\") {\n        toolPackageVersion = versionRec.version;\n      } else {\n        packageVersions[packageName] = versionRec.version;\n      }\n    });\n\n    if (! toolPackageVersion) {\n      throw Error(\"no meteor-tool?\");\n    }\n\n    stubCatalog.collections.releaseTracks.push({\n      name: catalog.DEFAULT_TRACK,\n      _id: utils.randomToken()\n    });\n\n    // Now create each requested release.\n    _.each(releases, function (configuration, releaseName) {\n      // Release info\n      stubCatalog.collections.releaseVersions.push({\n        track: catalog.DEFAULT_TRACK,\n        _id: Math.random().toString(),\n        version: releaseName,\n        orderKey: releaseName,\n        description: \"test release \" + releaseName,\n        recommended: !!configuration.recommended,\n        tool: configuration.tool || \"meteor-tool@\" + toolPackageVersion,\n        packages: packageVersions\n      });\n    });\n\n    var dataFile = config.getPackageStorage({\n      root: self.warehouse,\n      serverUrl: serverUrl\n    });\n    self.warehouseOfficialCatalog = new catalogRemote.RemoteCatalog();\n    self.warehouseOfficialCatalog.initialize({\n      packageStorage: dataFile\n    });\n    self.warehouseOfficialCatalog.insertData(stubCatalog);\n\n    // And a cherry on top\n    // XXX this is hacky\n    files.linkToMeteorScript(\n      files.pathJoin(self.warehouse, packagesDirectoryName, \"meteor-tool\", toolPackageVersion,\n        'mt-' + archinfo.host(), 'meteor'),\n      files.pathJoin(self.warehouse, 'meteor'));\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// Client\n///////////////////////////////////////////////////////////////////////////////\n\nvar Client = function (options) {\n  var self = this;\n\n  self.host = options.host;\n  self.port = options.port;\n  self.url = \"http://\" + self.host + \":\" + self.port + '/' +\n    (Math.random() * 0x100000000 + 1).toString(36);\n  self.timeout = options.timeout || 40;\n\n  if (! self.connect || ! self.stop) {\n    console.log(\"Missing methods in subclass of Client.\");\n  }\n};\n\n// PhantomClient\nvar PhantomClient = function (options) {\n  var self = this;\n  Client.apply(this, arguments);\n\n  self.name = \"phantomjs\";\n  self.process = null;\n\n  self._logError = true;\n};\n\nutil.inherits(PhantomClient, Client);\n\n_.extend(PhantomClient.prototype, {\n  connect: function () {\n    var self = this;\n\n    var phantomPath = phantomjs.path;\n\n    var scriptPath = files.pathJoin(files.getCurrentToolsDir(), \"tools\",\n      \"tool-testing\", \"phantom\", \"open-url.js\");\n    self.process = child_process.execFile(phantomPath, [\"--load-images=no\",\n      files.convertToOSPath(scriptPath), self.url],\n      {}, function (error, stdout, stderr) {\n        if (self._logError && error) {\n          console.log(\"PhantomJS exited with error \", error, \"\\nstdout:\\n\", stdout, \"\\nstderr:\\n\", stderr);\n        }\n      });\n  },\n\n  stop: function() {\n    var self = this;\n    // Suppress the expected SIGTERM exit 'failure'\n    self._logError = false;\n    self.process && self.process.kill();\n    self.process = null;\n  }\n});\n\n// BrowserStackClient\nvar browserStackKey = null;\n\nvar BrowserStackClient = function (options) {\n  var self = this;\n  Client.apply(this, arguments);\n\n  self.tunnelProcess = null;\n  self.driver = null;\n\n  self.browserName = options.browserName;\n  self.browserVersion = options.browserVersion;\n\n  self.name = \"BrowserStack - \" + self.browserName;\n  if (self.browserVersion) {\n    self.name += \" \" + self.browserVersion;\n  }\n};\n\nutil.inherits(BrowserStackClient, Client);\n\n_.extend(BrowserStackClient.prototype, {\n  connect: function () {\n    var self = this;\n\n    // memoize the key\n    if (browserStackKey === null) {\n      browserStackKey = self._getBrowserStackKey();\n    }\n    if (! browserStackKey) {\n      throw new Error(\"BrowserStack key not found. Ensure that you \" +\n        \"have installed your S3 credentials.\");\n    }\n\n    var capabilities = {\n      'browserName' : self.browserName,\n      'browserstack.user' : 'meteor',\n      'browserstack.local' : 'true',\n      'browserstack.key' : browserStackKey\n    };\n\n    if (self.browserVersion) {\n      capabilities.browserVersion = self.browserVersion;\n    }\n\n    self._launchBrowserStackTunnel(function (error) {\n      if (error) {\n        throw error;\n      }\n\n      self.driver = new webdriver.Builder().\n        usingServer('http://hub.browserstack.com/wd/hub').\n        withCapabilities(capabilities).\n        build();\n      self.driver.get(self.url);\n    });\n  },\n\n  stop: function() {\n    var self = this;\n    self.tunnelProcess && self.tunnelProcess.kill();\n    self.tunnelProcess = null;\n\n    self.driver && self.driver.quit();\n    self.driver = null;\n  },\n\n  _getBrowserStackKey: function () {\n    var outputDir = files.pathJoin(files.mkdtemp(), \"key\");\n\n    try {\n      execFileSync(\"s3cmd\", [\"get\",\n        \"s3://meteor-browserstack-keys/browserstack-key\",\n        outputDir\n      ]);\n\n      return files.readFile(outputDir, \"utf8\").trim();\n    } catch (e) {\n      return null;\n    }\n  },\n\n  _launchBrowserStackTunnel: function (callback) {\n    var self = this;\n    var browserStackPath =\n      files.pathJoin(files.getDevBundle(), 'bin', 'BrowserStackLocal');\n    files.chmod(browserStackPath, 0o755);\n\n    var args = [\n      browserStackPath,\n      browserStackKey,\n      [self.host, self.port, 0].join(','),\n      // Disable Live Testing and Screenshots, just test with Automate.\n      '-onlyAutomate',\n      // Do not wait for the server to be ready to spawn the process.\n      '-skipCheck'\n    ];\n    self.tunnelProcess = child_process.execFile(\n      '/usr/bin/env',\n      ['bash', '-c', args.join(' ')]\n    );\n\n    // Called when the SSH tunnel is established.\n    self.tunnelProcess.stdout.on('data', function(data) {\n      if (data.toString().match(/You can now access your local server/)) {\n        callback();\n      }\n    });\n  }\n});\n\n///////////////////////////////////////////////////////////////////////////////\n// Run\n///////////////////////////////////////////////////////////////////////////////\n\n// Represents a test run of the tool (except we also use it in\n// tests/old.js to run Node scripts). Typically created through the\n// run() method on Sandbox, but can also be created directly, say if\n// you want to do something other than invoke the 'meteor' command in\n// a nice sandbox.\n//\n// Options: args, cwd, env\n//\n// The 'execPath' argument and the 'cwd' option are assumed to be standard\n// paths.\n//\n// Arguments in the 'args' option are not assumed to be standard paths, so\n// calling any of the 'files.*' methods on them is not safe.\nvar Run = function (execPath, options) {\n  var self = this;\n\n  self.execPath = execPath;\n  self.cwd = options.cwd || files.convertToStandardPath(process.cwd());\n  // default env variables\n  self.env = _.extend({ SELFTEST: \"t\", METEOR_NO_WORDWRAP: \"t\" }, options.env);\n  self._args = [];\n  self.proc = null;\n  self.baseTimeout = 20;\n  self.extraTime = 0;\n  self.client = options.client;\n\n  self.stdoutMatcher = new Matcher(self);\n  self.stderrMatcher = new Matcher(self);\n  self.outputLog = new OutputLog(self);\n\n  self.exitStatus = undefined; // 'null' means failed rather than exited\n  self.exitPromiseResolvers = [];\n  var opts = options.args || [];\n  self.args.apply(self, opts || []);\n\n  self.fakeMongoPort = null;\n  self.fakeMongoConnection = null;\n  if (options.fakeMongo) {\n    self.fakeMongoPort = require('../utils/utils.js').randomPort();\n    self.env.METEOR_TEST_FAKE_MONGOD_CONTROL_PORT = self.fakeMongoPort;\n  }\n\n  runningTest.onCleanup(function () {\n    self._stopWithoutWaiting();\n  });\n};\n\n_.extend(Run.prototype, {\n  // Set command-line arguments. This may be called multiple times as\n  // long as the run has not yet started (the run starts after the\n  // first call to a function that requires it, like match()).\n  //\n  // Pass as many arguments as you want. Non-object values will be\n  // cast to string, and object values will be treated as maps from\n  // option names to values.\n  args: function (...args) {\n    var self = this;\n\n    if (self.proc) {\n      throw new Error(\"already started?\");\n    }\n\n    _.each(args, function (a) {\n      if (typeof a !== \"object\") {\n        self._args.push('' + a);\n      } else {\n        _.each(a, function (value, key) {\n          self._args.push(\"--\" + key);\n          self._args.push('' + value);\n        });\n      }\n    });\n\n  },\n\n  connectClient: function () {\n    var self = this;\n    if (! self.client) {\n      throw new Error(\"Must create Run with a client to use connectClient().\");\n    }\n\n    self._ensureStarted();\n    self.client.connect();\n  },\n\n  _exited: function (status) {\n    var self = this;\n\n    if (self.exitStatus !== undefined) {\n      throw new Error(\"already exited?\");\n    }\n\n    self.client && self.client.stop();\n\n    self.exitStatus = status;\n    var exitPromiseResolvers = self.exitPromiseResolvers;\n    self.exitPromiseResolvers = null;\n    _.each(exitPromiseResolvers, function (resolve) {\n      resolve();\n    });\n\n    self.stdoutMatcher.end();\n    self.stderrMatcher.end();\n  },\n\n  _ensureStarted: function () {\n    var self = this;\n\n    if (self.proc) {\n      return;\n    }\n\n    var env = _.clone(process.env);\n    _.extend(env, self.env);\n\n    self.proc = child_process.spawn(files.convertToOSPath(self.execPath),\n      self._args, {\n        cwd: files.convertToOSPath(self.cwd),\n        env: env\n      });\n\n    self.proc.on('close', function (code, signal) {\n      if (self.exitStatus === undefined) {\n        self._exited({ code: code, signal: signal });\n      }\n    });\n\n    self.proc.on('exit', function (code, signal) {\n      if (self.exitStatus === undefined) {\n        self._exited({ code: code, signal: signal });\n      }\n    });\n\n    self.proc.on('error', function (err) {\n      if (self.exitStatus === undefined) {\n        self._exited(null);\n      }\n    });\n\n    self.proc.stdout.setEncoding('utf8');\n    self.proc.stdout.on('data', function (data) {\n      self.outputLog.write('stdout', data);\n      self.stdoutMatcher.write(data);\n    });\n\n    self.proc.stderr.setEncoding('utf8');\n    self.proc.stderr.on('data', function (data) {\n      self.outputLog.write('stderr', data);\n      self.stderrMatcher.write(data);\n    });\n  },\n\n  // Wait until we get text on stdout that matches 'pattern', which\n  // may be a regular expression or a string. Consume stdout up to\n  // that point. If this pattern does not appear after a timeout (or\n  // the program exits before emitting the pattern), fail.\n  match: markStack(function (pattern, _strict) {\n    var self = this;\n    self._ensureStarted();\n\n    var timeout = self.baseTimeout + self.extraTime;\n    timeout *= utils.timeoutScaleFactor;\n    self.extraTime = 0;\n    return self.stdoutMatcher.match(pattern, timeout, _strict);\n  }),\n\n  // As expect(), but for stderr instead of stdout.\n  matchErr: markStack(function (pattern, _strict) {\n    var self = this;\n    self._ensureStarted();\n\n    var timeout = self.baseTimeout + self.extraTime;\n    timeout *= utils.timeoutScaleFactor;\n    self.extraTime = 0;\n    return self.stderrMatcher.match(pattern, timeout, _strict);\n  }),\n\n  // Like match(), but won't skip ahead looking for a match. It must\n  // follow immediately after the last thing we matched or read.\n  read: markStack(function (pattern) {\n    return this.match(pattern, true);\n  }),\n\n  // As read(), but for stderr instead of stdout.\n  readErr: markStack(function (pattern) {\n    return this.matchErr(pattern, true);\n  }),\n\n  // Assert that 'pattern' (again, a regexp or string) has not\n  // occurred on stdout at any point so far in this run. Currently\n  // this works on complete lines, so unlike match() and read(),\n  // 'pattern' cannot span multiple lines, and furthermore if it is\n  // called before the end of the program, it may not see text on a\n  // partially read line. We could lift these restrictions easily, but\n  // there may not be any benefit since the usual way to use this is\n  // to call it after expectExit or expectEnd.\n  //\n  // Example:\n  // run = s.run(\"--help\");\n  // run.expectExit(1);  // <<-- improtant to actually run the command\n  // run.forbidErr(\"unwanted string\"); // <<-- important to run **after** the\n  //                                   // command ran the process.\n  forbid: markStack(function (pattern) {\n    this._ensureStarted();\n    this.outputLog.forbid(pattern, 'stdout');\n  }),\n\n  // As forbid(), but for stderr instead of stdout.\n  forbidErr: markStack(function (pattern) {\n    this._ensureStarted();\n    this.outputLog.forbid(pattern, 'stderr');\n  }),\n\n  // Combination of forbid() and forbidErr(). Forbids the pattern on\n  // both stdout and stderr.\n  forbidAll: markStack(function (pattern) {\n    this._ensureStarted();\n    this.outputLog.forbid(pattern);\n  }),\n\n  // Expect the program to exit without anything further being\n  // printed on either stdout or stderr.\n  expectEnd: markStack(function () {\n    var self = this;\n    self._ensureStarted();\n\n    var timeout = self.baseTimeout + self.extraTime;\n    timeout *= utils.timeoutScaleFactor;\n    self.extraTime = 0;\n    self.expectExit();\n\n    self.stdoutMatcher.matchEmpty();\n    self.stderrMatcher.matchEmpty();\n  }),\n\n  // Expect the program to exit with the given (numeric) exit\n  // status. Fail if the process exits with a different code, or if\n  // the process does not exit after a timeout. You can also omit the\n  // argument to simply wait for the program to exit.\n  expectExit: markStack(function (code) {\n    var self = this;\n    self._ensureStarted();\n\n    if (self.exitStatus === undefined) {\n      var timeout = self.baseTimeout + self.extraTime;\n      timeout *= utils.timeoutScaleFactor;\n      self.extraTime = 0;\n\n      var timer;\n      var promise = new Promise(function (resolve, reject) {\n        self.exitPromiseResolvers.push(resolve);\n        timer = setTimeout(function () {\n          self.exitPromiseResolvers = _.without(self.exitPromiseResolvers, resolve);\n          reject(new TestFailure('exit-timeout', { run: self }));\n        }, timeout * 1000);\n      });\n\n      try {\n        promise.await();\n      } finally {\n        clearTimeout(timer);\n      }\n    }\n\n    if (! self.exitStatus) {\n      throw new TestFailure('spawn-failure', { run: self });\n    }\n    if (code !== undefined && self.exitStatus.code !== code) {\n      throw new TestFailure('wrong-exit-code', {\n        expected: { code: code },\n        actual: self.exitStatus,\n        run: self\n      });\n    }\n  }),\n\n  // Extend the timeout for the next operation by 'secs' seconds.\n  waitSecs: function (secs) {\n    var self = this;\n    self.extraTime += secs;\n  },\n\n  // Send 'string' to the program on its stdin.\n  write: function (string) {\n    var self = this;\n    self._ensureStarted();\n    self.proc.stdin.write(string);\n  },\n\n  // Kill the program and then wait for it to actually exit.\n  stop: markStack(function () {\n    var self = this;\n    if (self.exitStatus === undefined) {\n      self._ensureStarted();\n      self.client && self.client.stop();\n      self._killProcess();\n      self.expectExit();\n    }\n  }),\n\n  // Like stop, but doesn't wait for it to exit.\n  _stopWithoutWaiting: function () {\n    var self = this;\n    if (self.exitStatus === undefined && self.proc) {\n      self.client && self.client.stop();\n      self._killProcess();\n    }\n  },\n\n  // Kills the running process and it's child processes\n  _killProcess: function () {\n    if (!this.proc) {\n      throw new Error(\"Unexpected: `this.proc` undefined when calling _killProcess\");\n    }\n\n    if (process.platform === \"win32\") {\n      // looks like in Windows `self.proc.kill()` doesn't kill child\n      // processes.\n      utils.execFileSync(\"taskkill\", [\"/pid\", this.proc.pid, '/f', '/t']);\n    } else {\n      this.proc.kill();\n    }\n  },\n\n  // If the fakeMongo option was set, sent a command to the stub\n  // mongod. Available commands currently are:\n  //\n  // - { stdout: \"xyz\" } to make fake-mongod write \"xyz\" to stdout\n  // - { stderr: \"xyz\" } likewise for stderr\n  // - { exit: 123 } to make fake-mongod exit with code 123\n  //\n  // Blocks until a connection to fake-mongod can be\n  // established. Throws a TestFailure if it cannot be established.\n  tellMongo: markStack(function (command) {\n    var self = this;\n\n    if (! self.fakeMongoPort) {\n      throw new Error(\"fakeMongo option on sandbox must be set\");\n    }\n\n    self._ensureStarted();\n\n    // If it's the first time we've called tellMongo on this sandbox,\n    // open a connection to fake-mongod. Wait up to 60 seconds for it\n    // to accept the connection, retrying every 100ms.\n    //\n    // XXX we never clean up this connection. Hopefully once\n    // fake-mongod has dropped its end of the connection, and we hold\n    // no reference to our end, it will get gc'd. If not, that's not\n    // great, but it probably doesn't actually create any practical\n    // problems since this is only for testing.\n    if (! self.fakeMongoConnection) {\n      var net = require('net');\n\n      var lastStartTime = 0;\n      for (var attempts = 0; ! self.fakeMongoConnection && attempts < 600;\n           attempts ++) {\n        // Throttle attempts to one every 100ms\n        utils.sleepMs((lastStartTime + 100) - (+ new Date));\n        lastStartTime = +(new Date);\n\n        new Promise(function (resolve) {\n          // This is all arranged so that if a previous attempt\n          // belatedly succeeds, somehow, we ignore it.\n          var conn = net.connect(self.fakeMongoPort, function () {\n            if (resolve) {\n              self.fakeMongoConnection = conn;\n              resolve(true);\n              resolve = null;\n            }\n          });\n          conn.setNoDelay();\n          function fail() {\n            if (resolve) {\n              resolve(false);\n              resolve = null;\n            }\n          }\n          conn.on('error', fail);\n          setTimeout(fail, 100); // 100ms connection timeout\n        }).await();\n      }\n\n      if (! self.fakeMongoConnection) {\n        throw new TestFailure(\"mongo-not-running\", { run: self });\n      }\n    }\n\n    self.fakeMongoConnection.write(JSON.stringify(command) + \"\\n\");\n    // If we told it to exit, then we should close our end and connect again if\n    // asked to send more.\n    if (command.exit) {\n      self.fakeMongoConnection.end();\n      self.fakeMongoConnection = null;\n    }\n  })\n});\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Defining tests\n///////////////////////////////////////////////////////////////////////////////\n\nvar Test = function (options) {\n  var self = this;\n  self.name = options.name;\n  self.file = options.file;\n  self.fileHash = options.fileHash;\n  self.tags = options.tags || [];\n  self.f = options.func;\n  self.cleanupHandlers = [];\n};\n\n_.extend(Test.prototype, {\n  onCleanup: function (cleanupHandler) {\n    this.cleanupHandlers.push(cleanupHandler);\n  },\n  cleanup: function () {\n    var self = this;\n    _.each(self.cleanupHandlers, function (cleanupHandler) {\n      cleanupHandler();\n    });\n    self.cleanupHandlers = [];\n  }\n});\n\nvar allTests = null;\nvar fileBeingLoaded = null;\nvar fileBeingLoadedHash = null;\nvar runningTest = null;\nvar getAllTests = function () {\n  if (allTests) {\n    return allTests;\n  }\n  allTests = [];\n\n  // Load all files in the 'tests' directory that end in .js. They\n  // are supposed to then call define() to register their tests.\n  var testdir = files.pathJoin(__dirname, '..', 'tests');\n  var filenames = files.readdir(testdir);\n  _.each(filenames, function (n) {\n    if (! n.match(/^[^.].*\\.js$/)) {\n      // ends in '.js', doesn't start with '.'\n      return;\n    }\n    try {\n      if (fileBeingLoaded) {\n        throw new Error(\"called recursively?\");\n      }\n      fileBeingLoaded = files.pathBasename(n, '.js');\n\n      var fullPath = files.pathJoin(testdir, n);\n      var contents = files.readFile(fullPath, 'utf8');\n      fileBeingLoadedHash =\n        require('crypto').createHash('sha1').update(contents).digest('hex');\n\n      require(files.pathJoin(testdir, n));\n    } finally {\n      fileBeingLoaded = null;\n      fileBeingLoadedHash = null;\n    }\n  });\n\n  return allTests;\n};\n\nvar define = function (name, tagsList, f) {\n  if (typeof tagsList === \"function\") {\n    // tagsList is optional\n    f = tagsList;\n    tagsList = [];\n  }\n\n  var tags = tagsList.slice();\n  tags.sort();\n\n  allTests.push(new Test({\n    name: name,\n    tags: tags,\n    file: fileBeingLoaded,\n    fileHash: fileBeingLoadedHash,\n    func: f\n  }));\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Choosing tests\n///////////////////////////////////////////////////////////////////////////////\n\nvar tagDescriptions = {\n  checkout: 'can only run from checkouts',\n  net: 'require an internet connection',\n  slow: 'take quite a long time; use --slow to include',\n  galaxy: 'galaxy-specific test testing galaxy integration',\n  cordova: 'requires Cordova support in tool (eg not on Windows)',\n  windows: 'runs only on Windows',\n  // these are pseudo-tags, assigned to tests when you specify\n  // --changed, --file, or a pattern argument\n  unchanged: 'unchanged since last pass',\n  'non-matching': \"don't match specified pattern\",\n  'in other files': \"\",\n  // These tests require a setup step which can be amortized across multiple\n  // similar tests, so it makes sense to segregate them\n  'custom-warehouse': \"requires a custom warehouse\"\n};\n\n// Returns a TestList object representing a filtered list of tests,\n// according to the options given (which are based closely on the\n// command-line arguments).  Used as the first step of both listTests\n// and runTests.\n//\n// Options: testRegexp, fileRegexp, onlyChanged, offline, includeSlowTests, galaxyOnly\nvar getFilteredTests = function (options) {\n  options = options || {};\n  var allTests = getAllTests();\n\n  if (allTests.length) {\n    var testState = readTestState();\n\n    // Add pseudo-tags 'non-matching', 'unchanged', 'non-galaxy' and 'in other\n    // files' (but only so that we can then skip tests with those tags)\n    allTests = allTests.map(function (test) {\n      var newTags = [];\n\n      if (options.fileRegexp && ! options.fileRegexp.test(test.file)) {\n        newTags.push('in other files');\n      } else if (options.testRegexp && ! options.testRegexp.test(test.name)) {\n        newTags.push('non-matching');\n      } else if (options.onlyChanged &&\n                 test.fileHash === testState.lastPassedHashes[test.file]) {\n        newTags.push('unchanged');\n      } else if (options.excludeRegexp &&\n                 options.excludeRegexp.test(test.name)) {\n        newTags.push('excluded');\n      }\n\n      // We make sure to not run galaxy tests unless the user explicitly asks us\n      // to. Someday, this might not be the case.\n      if ( _.indexOf(test.tags, \"galaxy\") === -1) {\n        newTags.push('non-galaxy');\n      }\n\n      if (! newTags.length) {\n        return test;\n      }\n\n      return _.extend({}, test, { tags: test.tags.concat(newTags) });\n    });\n  }\n\n  // (order of tags is significant to the \"skip counts\" that are displayed)\n  var tagsToSkip = [];\n  if (options.fileRegexp) {\n    tagsToSkip.push('in other files');\n  }\n  if (options.testRegexp) {\n    tagsToSkip.push('non-matching');\n  }\n  if (options.excludeRegexp) {\n    tagsToSkip.push('excluded');\n  }\n  if (options.onlyChanged) {\n    tagsToSkip.push('unchanged');\n  }\n  if (! files.inCheckout()) {\n    tagsToSkip.push('checkout');\n  }\n  if (options.galaxyOnly) {\n    // We consider `galaxy` to imply `slow` and `net` since almost all galaxy\n    // tests involve deploying an app to a (probably) remote server.\n    tagsToSkip.push('non-galaxy');\n  } else {\n    tagsToSkip.push('galaxy');\n    if (options.offline) {\n      tagsToSkip.push('net');\n    }\n    if (! options.includeSlowTests) {\n      tagsToSkip.push('slow');\n    }\n  }\n\n  if (options['without-tag']) {\n    tagsToSkip.push(options['without-tag']);\n  }\n\n  if (process.platform === \"win32\") {\n    tagsToSkip.push(\"cordova\");\n    tagsToSkip.push(\"yet-unsolved-windows-failure\");\n  } else {\n    tagsToSkip.push(\"windows\");\n  }\n\n  var tagsToMatch = options['with-tag'] ? [options['with-tag']] : [];\n  return new TestList(allTests, tagsToSkip, tagsToMatch, testState);\n};\n\n// A TestList is the result of getFilteredTests.  It holds the original\n// list of all tests, the filtered list, and stats on how many tests\n// were skipped (see generateSkipReport).\n//\n// TestList also has code to save the hashes of files where all tests\n// ran and passed (for the `--changed` option).  If a testState is\n// provided, the notifyFailed and saveTestState can be used to modify\n// the testState appropriately and write it out.\nvar TestList = function (allTests, tagsToSkip, tagsToMatch, testState) {\n  tagsToSkip = (tagsToSkip || []);\n  testState = (testState || null); // optional\n\n  var self = this;\n  self.allTests = allTests;\n  self.skippedTags = tagsToSkip;\n  self.skipCounts = {};\n  self.testState = testState;\n\n  _.each(tagsToSkip, function (tag) {\n    self.skipCounts[tag] = 0;\n  });\n\n  self.fileInfo = {}; // path -> {hash, hasSkips, hasFailures}\n\n  self.filteredTests = _.filter(allTests, function (test) {\n\n    if (! self.fileInfo[test.file]) {\n      self.fileInfo[test.file] = {\n        hash: test.fileHash,\n        hasSkips: false,\n        hasFailures: false\n      };\n    }\n    var fileInfo = self.fileInfo[test.file];\n\n    if (tagsToMatch.length) {\n      var matches = _.any(tagsToMatch, function(tag) {\n        return _.contains(test.tags, tag);\n      })\n      if (!matches) {\n        return false;\n      }\n    }\n\n    // We look for tagsToSkip *in order*, and when we decide to\n    // skip a test, we don't keep looking at more tags, and we don't\n    // add the test to any further \"skip counts\".\n    return !_.any(tagsToSkip, function (tag) {\n      if (_.contains(test.tags, tag)) {\n        self.skipCounts[tag]++;\n        fileInfo.hasSkips = true;\n        return true;\n      } else {\n        return false;\n      }\n    });\n  });\n};\n\n// Mark a test's file as having failures.  This prevents\n// saveTestState from saving its hash as a potentially\n// \"unchanged\" file to be skipped in a future run.\nTestList.prototype.notifyFailed = function (test) {\n  this.fileInfo[test.file].hasFailures = true;\n};\n\n// If this TestList was constructed with a testState,\n// modify it and write it out based on which tests\n// were skipped and which tests had failures.\nTestList.prototype.saveTestState = function () {\n  var self = this;\n  var testState = self.testState;\n  if (! (testState && self.filteredTests.length)) {\n    return;\n  }\n\n  _.each(self.fileInfo, function (info, f) {\n    if (info.hasFailures) {\n      delete testState.lastPassedHashes[f];\n    } else if (! info.hasSkips) {\n      testState.lastPassedHashes[f] = info.hash;\n    }\n  });\n\n  writeTestState(testState);\n};\n\n// Return a string like \"Skipped 1 foo test\\nSkipped 5 bar tests\\n\"\nTestList.prototype.generateSkipReport = function () {\n  var self = this;\n  var result = '';\n\n  _.each(self.skippedTags, function (tag) {\n    var count = self.skipCounts[tag];\n    if (count) {\n      var noun = \"test\" + (count > 1 ? \"s\" : \"\"); // \"test\" or \"tests\"\n      // \"non-matching tests\" or \"tests in other files\"\n      var nounPhrase = (/ /.test(tag) ?\n                        (noun + \" \" + tag) : (tag + \" \" + noun));\n      // \" (foo)\" or \"\"\n      var parenthetical = (tagDescriptions[tag] ? \" (\" +\n                           tagDescriptions[tag] + \")\" : '');\n      result += (\"Skipped \" + count + \" \" + nounPhrase + parenthetical + '\\n');\n    }\n  });\n\n  return result;\n};\n\nvar getTestStateFilePath = function () {\n  return files.pathJoin(files.getHomeDir(), '.meteortest');\n};\n\nvar readTestState = function () {\n  var testStateFile = getTestStateFilePath();\n  var testState;\n  if (files.exists(testStateFile)) {\n    testState = JSON.parse(files.readFile(testStateFile, 'utf8'));\n  }\n  if (! testState || testState.version !== 1) {\n    testState = { version: 1, lastPassedHashes: {} };\n  }\n  return testState;\n};\n\nvar writeTestState = function (testState) {\n  var testStateFile = getTestStateFilePath();\n  files.writeFile(testStateFile, JSON.stringify(testState), 'utf8');\n};\n\n// Same options as getFilteredTests.  Writes to stdout and stderr.\nvar listTests = function (options) {\n  var testList = getFilteredTests(options);\n\n  if (! testList.allTests.length) {\n    Console.error(\"No tests defined.\\n\");\n    return;\n  }\n\n  _.each(_.groupBy(testList.filteredTests, 'file'), function (tests, file) {\n    Console.rawInfo(file + ':\\n');\n    _.each(tests, function (test) {\n      Console.rawInfo('  - ' + test.name +\n                      (test.tags.length ? ' [' + test.tags.join(' ') + ']'\n                      : '') + '\\n');\n    });\n  });\n\n  Console.error();\n  Console.error(testList.filteredTests.length + \" tests listed.\");\n  Console.error(testList.generateSkipReport());\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Running tests\n///////////////////////////////////////////////////////////////////////////////\n\n// options: onlyChanged, offline, includeSlowTests, historyLines, testRegexp,\n//          fileRegexp,\n//          clients:\n//             - browserstack (need s3cmd credentials)\nvar runTests = function (options) {\n  var testList = getFilteredTests(options);\n\n  if (! testList.allTests.length) {\n    Console.error(\"No tests defined.\");\n    return 0;\n  }\n\n  var totalRun = 0;\n  var failedTests = [];\n\n  _.each(testList.filteredTests, function (test) {\n    totalRun++;\n    Console.error(test.file + \": \" + test.name + \" ... \");\n\n    var failure = null;\n    try {\n      runningTest = test;\n      var startTime = +(new Date);\n      // ensure we mark the bottom of the stack each time we start a new test\n      parseStack.markBottom(() => {\n        test.f(options);\n      })();\n    } catch (e) {\n      failure = e;\n    } finally {\n      runningTest = null;\n      test.cleanup();\n    }\n\n    if (failure) {\n      Console.error(\"... fail!\", Console.options({ indent: 2 }));\n      failedTests.push(test);\n      testList.notifyFailed(test);\n\n      if (failure instanceof TestFailure) {\n        var frames = parseStack.parse(failure).outsideFiber;\n        var relpath = files.pathRelative(files.getCurrentToolsDir(),\n                                         frames[0].file);\n        Console.rawError(\"  => \" + failure.reason + \" at \" +\n                         relpath + \":\" + frames[0].line + \"\\n\");\n        if (failure.reason === 'no-match' || failure.reason === 'junk-before' ||\n            failure.reason === 'match-timeout') {\n          Console.arrowError(\"Pattern: \" + failure.details.pattern, 2);\n        }\n        if (failure.reason === \"wrong-exit-code\") {\n          var s = function (status) {\n            return status.signal || ('' + status.code) || \"???\";\n          };\n\n          Console.rawError(\n            \"  => \" + \"Expected: \" + s(failure.details.expected) +\n              \"; actual: \" + s(failure.details.actual) + \"\\n\");\n        }\n        if (failure.reason === 'expected-exception') {\n        }\n        if (failure.reason === 'not-equal') {\n          Console.rawError(\n            \"  => \" + \"Expected: \" + JSON.stringify(failure.details.expected) +\n              \"; actual: \" + JSON.stringify(failure.details.actual) + \"\\n\");\n        }\n\n        if (failure.details.run) {\n          failure.details.run.outputLog.end();\n          var lines = failure.details.run.outputLog.get();\n          if (! lines.length) {\n            Console.arrowError(\"No output\", 2);\n          } else {\n            var historyLines = options.historyLines || 100;\n\n            Console.arrowError(\"Last \" + historyLines + \" lines:\", 2);\n            _.each(lines.slice(-historyLines), function (line) {\n              Console.rawError(\"  \" +\n                               (line.channel === \"stderr\" ? \"2| \" : \"1| \") +\n                               line.text +\n                               (line.bare ? \"%\" : \"\") + \"\\n\");\n            });\n          }\n        }\n\n        if (failure.details.messages) {\n          Console.arrowError(\"Errors while building:\", 2);\n          Console.rawError(failure.details.messages.formatMessages() + \"\\n\");\n        }\n      } else {\n        Console.rawError(\"  => Test threw exception: \" + failure.stack + \"\\n\");\n      }\n    } else {\n      var durationMs = +(new Date) - startTime;\n      Console.error(\n        \"... ok (\" + durationMs + \" ms)\",\n        Console.options({ indent: 2 }));\n    }\n  });\n\n  testList.saveTestState();\n\n  if (totalRun > 0) {\n    Console.error();\n  }\n\n  Console.error(testList.generateSkipReport());\n\n  if (testList.filteredTests.length === 0) {\n    Console.error(\"No tests run.\");\n    return 0;\n  } else if (failedTests.length === 0) {\n    var disclaimers = '';\n    if (testList.filteredTests.length < testList.allTests.length) {\n      disclaimers += \" other\";\n    }\n    Console.error(\"All\" + disclaimers + \" tests passed.\");\n    return 0;\n  } else {\n    var failureCount = failedTests.length;\n    Console.error(failureCount + \" failure\" +\n                  (failureCount > 1 ? \"s\" : \"\") + \":\");\n    _.each(failedTests, function (test) {\n      Console.rawError(\"  - \" + test.file + \": \" + test.name + \"\\n\");\n    });\n    return 1;\n  }\n};\n\n// To create self-tests:\n//\n// Create a new .js file in the tests directory. It will be picked\n// up automatically.\n//\n// Start your file with something like:\n//   var selftest = require('./selftest.js');\n//   var Sandbox = selftest.Sandbox;\n//\n// Define tests with:\n//   selftest.define(\"test-name\", ['tag1', 'tag2'], function () {\n//     ...\n//   });\n//\n// The tags are used to group tests. Currently used tags:\n//   - 'checkout': should only be run when we're running from a\n//     checkout as opposed to a released copy.\n//   - 'net': test requires an internet connection. Not going to work\n//     if you're on a plane; will be skipped if we appear to be\n//     offline unless run with 'self-test --force-online'.\n//   - 'slow': test is slow enough that you don't want to run it\n//     except on purpose. Won't run unless you say 'self-test --slow'.\n//\n// If you don't want to set any tags, you can omit that parameter\n// entirely.\n//\n// Inside your test function, first create a Sandbox object, then call\n// the run() method on the sandbox to set up a new run of meteor with\n// arguments of your choice, and then use functions like match(),\n// write(), and expectExit() to script that run.\n\n_.extend(exports, {\n  runTests: runTests,\n  listTests: listTests,\n  markStack: markStack,\n  define: define,\n  Sandbox: Sandbox,\n  Run: Run,\n  fail: fail,\n  expectEqual: expectEqual,\n  expectThrows: expectThrows,\n  expectTrue: expectTrue,\n  expectFalse: expectFalse,\n  execFileSync: execFileSync,\n  doOrThrow: doOrThrow\n});\n"
  },
  {
    "path": "tools/tool-testing/test-utils.js",
    "content": "var isopackets = require('../tool-env/isopackets.js');\nvar config = require('../meteor-services/config.js');\nvar utils = require('../utils/utils.js');\nvar auth = require('../meteor-services/auth.js');\nvar selftest = require('./selftest.js');\nvar httpHelpers = require('../utils/http-helpers.js');\nvar _ = require('underscore');\n\nvar randomString = function (charsCount) {\n  var chars = 'abcdefghijklmnopqrstuvwxyz';\n  var str = '';\n  for (var i = 0; i < charsCount; i++) {\n    str = str + chars.charAt(Math.floor(Math.random() * chars.length));\n  }\n  return str;\n};\n\nexports.accountsCommandTimeoutSecs = 15 * utils.timeoutScaleFactor;\n\nexports.randomString = randomString;\n\nvar randomAppName = function () {\n  return 'selftest-app-' + randomString(10);\n};\n\nexports.randomAppName = randomAppName;\n\nexports.randomUserEmail = function () {\n  return 'selftest-user-' + randomString(15) + '@guerrillamail.com';\n};\n\nexports.login = function (s, username, password) {\n  var run = s.run('login');\n  run.waitSecs(15);\n  run.matchErr('Username:');\n  run.write(username + '\\n');\n  run.matchErr('Password:');\n  run.write(password + '\\n');\n  run.waitSecs(15);\n  run.matchErr('Logged in as ' + username + \".\");\n  run.expectExit(0);\n};\n\nexports.logout = function (s) {\n  var run = s.run('logout');\n  run.waitSecs(15);\n  run.matchErr('Logged out');\n  run.expectExit(0);\n};\n\nvar registrationUrlRegexp =\n      /https:\\/\\/www\\.meteor\\.com\\/setPassword\\?([a-zA-Z0-9\\+\\/]+)/;\nexports.registrationUrlRegexp = registrationUrlRegexp;\n\nvar getLoadedPackages = function () {\n  return isopackets.load('ddp');\n};\n\nvar ddpConnect = function (url) {\n  var DDP = getLoadedPackages()['ddp-client'].DDP;\n  return DDP.connect(url);\n};\n\nexports.ddpConnect = ddpConnect;\n\n// Given a registration token created by doing a deferred registration\n// with `email`, makes a DDP connection to the accounts server and\n// finishes the registration process.\nexports.registerWithToken = function (token, username, password, email) {\n  // XXX It might make more sense to hard-code the DDP url to\n  // https://www.meteor.com, since that's who the sandboxes are talking\n  // to.\n  var accountsConn = ddpConnect(config.getAuthDDPUrl());\n  var registrationTokenInfo = accountsConn.call('registrationTokenInfo',\n                                                token);\n  var registrationCode = registrationTokenInfo.code;\n  accountsConn.call('register', {\n    username: username,\n    password: password,\n    emails: [email],\n    token: token,\n    code: registrationCode\n  });\n  accountsConn.close();\n};\n\nexports.randomOrgName = function () {\n  return \"selftestorg\" + exports.randomString(10);\n};\n\n// Logs in as the specified user and creates a randomly named\n// organization. Returns the organization name. Calls selftest.fail if\n// the organization can't be created.\nexports.createOrganization = function (username, password) {\n  var orgName = exports.randomOrgName();\n  auth.withAccountsConnection(function (conn) {\n    try {\n      conn.call(\"login\", {\n        meteorAccountsLoginInfo: { username: username, password: password },\n        clientInfo: {}\n      });\n    } catch (err) {\n      selftest.fail(\"Failed to log in to Meteor developer accounts\\n\" +\n                    \"with test user: \" + err);\n    }\n\n    try {\n      conn.call(\"createOrganization\", orgName);\n    } catch (err) {\n      selftest.fail(\"Failed to create organization: \" + err);\n    }\n  })();\n\n  return orgName;\n};\n\nexports.getMeteorRuntimeConfigFromHTML = function (html) {\n  var m = html.match(/__meteor_runtime_config__ = JSON.parse\\(decodeURIComponent\\(\"([^\"]+?)\"\\)\\)/);\n  if (! m) {\n    selftest.fail(\"Can't find __meteor_runtime_config__\");\n  }\n  return JSON.parse(decodeURIComponent(m[1]));\n};\n\n\n// Poll the given app looking for the correct settings. Throws an error\n// if the settings aren't found after a timeout.\nexports.checkForSettings = selftest.markStack(function (appName, settings, timeoutSecs) {\n  var timeoutDate = new Date(new Date().valueOf() + timeoutSecs * 1000);\n  while (true) {\n    if (new Date() >= timeoutDate) {\n      selftest.fail('Expected settings not found on app ' + appName);\n    }\n\n    var result = httpHelpers.request('http://' + appName);\n\n    // XXX This is brittle; the test will break if we start formatting the\n    // __meteor_runtime_config__ JS differently. Ideally we'd do something\n    // like point a phantom at the deployed app and actually evaluate\n    // Meteor.settings.\n    try {\n      var mrc = exports.getMeteorRuntimeConfigFromHTML(result.body);\n    } catch (e) {\n      // ignore\n      continue;\n    }\n\n    if (_.isEqual(mrc.PUBLIC_SETTINGS, settings['public'])) {\n      return;\n    }\n  }\n});\n"
  },
  {
    "path": "tools/upgraders.js",
    "content": "/* eslint no-console: 0 */\n\nvar _ = require('underscore');\nvar files = require('./fs/files.js');\nvar Console = require('./console/console.js').Console;\nimport main from './cli/main.js';\nimport buildmessage from './utils/buildmessage.js';\nimport * as cordova from './cordova';\n\n// This file implements \"upgraders\" --- functions which upgrade a Meteor app to\n// a new version. Each upgrader has a name (registered in upgradersByName).\n//\n// You can test upgraders by running \"meteor admin run-upgrader myupgradername\".\n//\n// Upgraders are run automatically by \"meteor update\". It looks at the\n// .meteor/.finished-upgraders file in the app and runs every upgrader listed\n// here that is not in that file; then it appends their names to that file.\n// Upgraders are run in the order they are listed in upgradersByName below.\n//\n// Upgraders receive a projectContext that has been fully prepared for build.\n\nvar printedNoticeHeaderThisProcess = false;\nvar maybePrintNoticeHeader = function () {\n  if (printedNoticeHeaderThisProcess)\n    return;\n  Console.info();\n  Console.info(\"-- Notice --\");\n  Console.info();\n  printedNoticeHeaderThisProcess = true;\n};\n\n// How to do package-specific notices:\n// (a) A notice that occurs if a package is used indirectly or directly.\n//     if (projectContext.packageMap.getInfo('accounts-ui')) {\n//       console.log(\n// \"\\n\" +\n// \"       Accounts UI has totally changed, yo.\");\n//     }\n//\n// (b) A notice that occurs if a package is used directly.\n//     if (projectContext.projectConstraintsFile.getConstraint('accounts-ui')) {\n//       console.log(\n// \"\\n\" +\n// \"       Accounts UI has totally changed, yo.\");\n//     }\n\nvar upgradersByName = {\n   \"notices-for-0.9.0\": function (projectContext) {\n     maybePrintNoticeHeader();\n\n     var smartJsonPath =\n       files.pathJoin(projectContext.projectDir, 'smart.json');\n\n     if (files.exists(smartJsonPath)) {\n       // Meteorite apps:\n       console.log(\n\"0.9.0: Welcome to the new Meteor package system! You can now add any Meteor\\n\" +\n\"       package to your app (from more than 1800 packages available on the\\n\" +\n\"       Meteor Package Server) just by typing 'meteor add <packagename>', no\\n\" +\n\"       Meteorite required.\\n\" +\n\"\\n\" +\n\"       It looks like you have been using Meteorite with this project. To\\n\" +\n\"       migrate your project automatically to the new system:\\n\" +\n\"         (1) upgrade your Meteorite with 'npm install -g meteorite', then\\n\" +\n\"         (2) run 'mrt migrate-app' inside the project.\\n\" +\n\"       Having done this, you no longer need 'mrt' and can just use 'meteor'.\\n\");\n     } else {\n       // Non-Meteorite apps:\n       console.log(\n\"0.9.0: Welcome to the new Meteor package system! You can now add any Meteor\\n\" +\n\"       package to your app (from more than 1800 packages available on the\\n\" +\n\"       Meteor Package Server) just by typing 'meteor add <packagename>'. Check\\n\" +\n\"       out the available packages by typing 'meteor search <term>' or by\\n\" +\n\"       visiting atmospherejs.com.\\n\");\n     }\n    console.log();\n  },\n\n  \"notices-for-0.9.1\": function () {\n    maybePrintNoticeHeader();\n    console.log(\n\"0.9.1: Meteor 0.9.1 includes changes to the Blaze API, in preparation for 1.0.\\n\" +\n\"       Many previously undocumented APIs are now public and documented. Most\\n\" +\n\"       changes are backwards compatible, except that templates can no longer\\n\" +\n\"       be named \\\"body\\\" or \\\"instance\\\".\\n\");\n    console.log();\n  },\n\n  // In 0.9.4, the platforms file contains \"server\" and \"browser\" as platforms,\n  // and before it only had \"ios\" and/or \"android\". We auto-fix that in\n  // PlatformList anyway, but we also need to pull platforms from the old\n  // cordova-platforms filename.\n  \"0.9.4-platform-file\": function (projectContext) {\n    var oldPlatformsPath =\n      files.pathJoin(projectContext.projectDir, \".meteor\", \"cordova-platforms\");\n\n    try {\n      var oldPlatformsFile = files.readFile(oldPlatformsPath);\n    } catch (e) {\n      // If the file doesn't exist, there's no transition to do.\n      if (e && e.code === 'ENOENT')\n        return;\n      throw e;\n    }\n    var oldPlatforms = _.compact(_.map(\n      files.splitBufferToLines(oldPlatformsFile), files.trimSpaceAndComments));\n    // This method will automatically add \"server\" and \"browser\" and sort, etc.\n    projectContext.platformList.write(oldPlatforms);\n    files.unlink(oldPlatformsPath);\n  },\n\n  \"notices-for-facebook-graph-api-2\": function (projectContext) {\n    // Note: this will print if the app has facebook as a dependency, whether\n    // direct or indirect. (This is good, since most apps will be pulling it in\n    // indirectly via accounts-facebook.)\n    if (projectContext.packageMap.getInfo('facebook')) {\n      maybePrintNoticeHeader();\n      Console.info(\n        \"This version of Meteor now uses version 2.2 of the Facebook API\",\n        \"for authentication, instead of 1.0. If you use additional Facebook\",\n        \"API methods beyond login, you may need to request new\",\n        \"permissions.\\n\\n\",\n        \"Facebook will automatically switch all apps to API\",\n        \"version 2.0 on April 30th, 2015. Please make sure to update your\",\n        \"application's permissions and API calls by that date.\\n\\n\",\n        \"For more details, see\",\n        \"https://github.com/meteor/meteor/wiki/Facebook-Graph-API-Upgrade\",\n        Console.options({ bulletPoint: \"1.0.5: \" })\n      );\n    }\n  },\n\n  \"1.2.0-standard-minifiers-package\": function (projectContext) {\n    // Minifiers are extracted into a new package called \"standard-minifiers\"\n    projectContext.projectConstraintsFile.addPackages(\n      ['standard-minifiers']);\n    projectContext.projectConstraintsFile.writeIfModified();\n  },\n\n  \"1.2.0-meteor-platform-split\": function (projectContext) {\n    const packagesFile = projectContext.projectConstraintsFile;\n    // meteor-platform is split into a series of smaller umbrella packages\n    // Only run this upgrader if the app has meteor-platform\n    if (packagesFile.getConstraint('meteor-platform')) {\n      packagesFile.removePackages(['meteor-platform']);\n\n      packagesFile.addPackages([\n        // These packages replace meteor-platform in newly created apps\n        'meteor-base',\n        'mobile-experience',\n        'mongo',\n        'blaze-html-templates',\n        'session',\n        'jquery',\n        'tracker',\n\n        // These packages are not in newly created apps, but were in\n        // meteor-platform so we need to add them just in case\n        'logging',\n        'reload',\n        'random',\n        'ejson',\n        'spacebars',\n        'check',\n      ]);\n\n      packagesFile.writeIfModified();\n    }\n  },\n\n  \"1.2.0-cordova-changes\": function (projectContext) {\n    // Remove Cordova project directory to start afresh\n    // and avoid a broken project\n    files.rm_recursive(projectContext.getProjectLocalDirectory(\n       'cordova-build'));\n\n    // Cordova plugin IDs have changed as part of moving to npm, so we convert\n    // old plugin IDs to new IDs. We also convert old-style GitHub tarball URLs\n    // to new Git URLs, and check if other Git URLs contain a SHA reference.\n    const pluginsFile = projectContext.cordovaPluginsFile;\n    let messages;\n    if (files.exists(pluginsFile.filename)) {\n      messages = buildmessage.capture(\n        { title: `converting Cordova plugins` }, () => {\n        let pluginVersions = pluginsFile.getPluginVersions();\n        pluginVersions = cordova.convertPluginVersions(pluginVersions);\n        pluginsFile.write(pluginVersions);\n      });\n    }\n\n    // Don't display notice if the project has no Cordova platforms added\n    if (_.isEmpty(projectContext.platformList.getCordovaPlatforms())) return;\n\n    maybePrintNoticeHeader();\n\n    // Print error messages generated during plugin conversion, if any\n    if (messages && messages.hasMessages()) {\n      Console.printMessages(messages);\n    }\n  },\n\n  \"1.2.0-breaking-changes\": function () {\n    maybePrintNoticeHeader();\n    Console.info(\n`Meteor 1.2 includes many changes and improvements to the build system, \\\nsome of which might require small changes to apps and packages. Please read \\\nthe guide about breaking changes here:`,\n      Console.url(\"https://github.com/meteor/meteor/wiki/Breaking-changes-in-Meteor-1.2\"),\n      Console.options({ bulletPoint: \"1.2: \" })\n    );\n  },\n\n  \"1.3.0-split-minifiers-package\": function (projectContext) {\n    const packagesFile = projectContext.projectConstraintsFile;\n\n    // Minifiers are extracted into a new package called \"standard-minifiers\"\n\n    if (packagesFile.getConstraint('standard-minifiers')) {\n      packagesFile.removePackages(['standard-minifiers']);\n\n      packagesFile.addPackages([\n        // These packages replace meteor-platform in newly created apps\n        'standard-minifier-css',\n        'standard-minifier-js',\n      ]);\n    }\n    packagesFile.writeIfModified();\n  },\n\n  ////////////\n  // PLEASE. When adding new upgraders that print mesasges, follow the\n  // examples for 0.9.0 and 0.9.1 above. Specifically, formatting\n  // should be:\n  //\n  // 1.x.y: Lorem ipsum messages go here...\n  //        ...and linewrapped on the right column\n  //\n  // (Or just use Console.info with bulletPoint)\n  ////////////\n};\n\nexports.runUpgrader = function (projectContext, upgraderName) {\n  // This should only be called from the hidden run-upgrader command or by\n  // \"meteor update\" with an upgrader from one of our releases, so it's OK if\n  // error handling is just an exception.\n  if (! _.has(upgradersByName, upgraderName))\n    throw new Error(\"Unknown upgrader: \" + upgraderName);\n  upgradersByName[upgraderName](projectContext);\n};\n\nexports.upgradersToRun = function (projectContext) {\n  var ret = [];\n  var finishedUpgraders = projectContext.finishedUpgraders.readUpgraders();\n  // This relies on the fact that Node guarantees object iteration ordering.\n  _.each(upgradersByName, function (func, name) {\n    if (! _.contains(finishedUpgraders, name)) {\n      ret.push(name);\n    }\n  });\n  return ret;\n};\n\nexports.allUpgraders = function () {\n  return _.keys(upgradersByName);\n};\n"
  },
  {
    "path": "tools/utils/archinfo.js",
    "content": "var _ = require('underscore');\nvar os = require('os');\n\nvar utils = require('./utils.js');\n\n/* Meteor's current architecture scheme defines the following virtual\n * machine types, which are defined by specifying what is promised by\n * the host enviroment:\n *\n * browser.w3c\n *   A web browser compliant with modern standards. This is\n *   intentionally a broad definition. In the coming years, as web\n *   standards evolve, we will likely tighten it up.\n *\n * browser.ie[678]\n *   Old versions of Internet Explorer (not sure yet exactly which\n *   versions to distinguish -- maybe 6 and 8?)\n *\n * os.linux.x86_32\n * os.linux.x86_64\n *   Linux on Intel x86 architecture. x86_64 means a system that can\n *   run 64-bit images, furnished with 64-bit builds of shared\n *   libraries (there is no guarantee that 32-bit builds of shared\n *   libraries will be available). x86_32 means a system that can run\n *   32-bit images, furnished with 32-bit builds of shared libraries.\n *   Additionally, if a package contains shared libraries (for use by\n *   other packages), then if the package is built for x86_64, it\n *   should contain a 64-bit version of the library, and likewise for\n *   32-bit.\n *\n *   Operationally speaking, if you worked at it, under this\n *   definition it would be possible to build a Linux system that can\n *   run both x86_64 and x86_32 images (eg, by using a 64-bit kernel\n *   and making sure that both versions of all relevant libraries were\n *   installed). But we require such a host to decide whether it is\n *   x86_64 or x86_32, and stick with it. You can't load a combination\n *   of packages from each and expect them to work together, because\n *   if they contain shared libraries they all need to have the same\n *   architecture.\n *\n *   Basically the punchline is: if you installed the 32-bit version\n *   of Ubuntu, you've got a os.linux.x86_32 system and you will\n *   use exclusively os.linux.x86_32 packages, and likewise\n *   64-bit. They are two parallel universes and which one you're in\n *   is determined by which version of Red Hat or Ubuntu you\n *   installed.\n *\n * os.osx.x86_64\n *   OS X (technically speaking, Darwin) on Intel x86 architecture,\n *   with a kernel capable of loading 64-bit images, and 64-bit builds\n *   of shared libraries available.  If a os.osx.x86_64 package\n *   contains a shared library, it is only required to provide a\n *   64-bit version of the library (it is not required to provide a\n *   fat binary with both 32-bit and 64-bit builds).\n *\n *   Note that in modern Darwin, both the 32 and 64 bit versions of\n *   the kernel can load 64-bit images, and the Apple-supplied shared\n *   libraries are fat binaries that include both 32-bit and 64-bit\n *   builds in a single file. So it is technically fine (but\n *   discouraged) for a os.osx.x86_64 to include a 32-bit\n *   executable, if it only uses the system's shared libraries, but\n *   you'll run into problems if shared libraries from other packages\n *   are used.\n *\n *   There is no os.osx.x86_32. Our experience is that such\n *   hardware is virtually extinct. Meteor has never supported it and\n *   nobody has asked for it.\n *\n * os.windows.x86_32\n *   This is 32 and 64 bit Windows. It seems like there is not much of\n *   a benefit to using 64 bit Node on Windows, and 32 bit works properly\n *   even on 64 bit systems.\n *\n * To be (more but far from completely) precise, the ABI for os.*\n * architectures includes a CPU type, a mode in which the code will be\n * run (eg, 64 bit), an executable file format (eg, ELF), a promise to\n * make any shared libraries available in a particular architecture,\n * and promise to set up the shared library search path\n * \"appropriately\". In the future it will also include some guarantees\n * about the directory layout in the environment, eg, location of a\n * directory where temporary files may be freely written. It does not\n * include any syscalls (beyond those used by code that customarily is\n * statically linked into every executable built on a platform, eg,\n * exit(2)). It does not guarantee the presence of any particular\n * shared libraries or programs (including any particular shell or\n * traditional tools like 'grep' or 'find').\n *\n * To model the shared libraries that are required on a system (and\n * the particular versions that are required), and to model\n * dependencies on command-line programs like 'bash' and 'grep', the\n * idea is to have a package named something like 'posix-base' that\n * rolls up a reasonable base environment (including such modern\n * niceties as libopenssl) and is supplied by the container. This\n * allows it to be versioned, unlike architectures, which we hope to\n * avoid versioning.\n *\n * Q: What does \"x86\" mean?\n * A: It refers to the traditional Intel architecture, which\n * originally surfaced in CPUs such as the 8086 and the 80386. Those\n * of us who are older should remember that the last time that Intel\n * used this branding was the 80486, introduced in 1989, and that\n * today, parts that use this architecture bear names like \"Core\",\n * \"Atom\", and \"Phenom\", with no \"86\" it sight. We use it in the\n * architecture name anyway because we don't want to depart too far\n * from Linux's architecture names.\n *\n * Q: Why do we call it \"x86_32\" instead of the customary \"i386\" or\n * \"i686\"?\n * A: We wanted to have one name for 32-bit and one name for 64-bit,\n * rather than several names for each that are virtual synonyms for\n * each (eg, x86_64 vs amd64 vs ia64, i386 vs i686 vs x86). For the\n * moment anyway, we're willing to adopt a \"one size fits all\"\n * attitude to get there (no ability to have separate builds for 80386\n * CPUs that don't support Pentium Pro extensions, for example --\n * you'll have to do runtime detection if you need that). And as long\n * as we have to pick a name, we wanted to pick one that was super\n * clear (it is not obvious to many people that \"i686\" means \"32-bit\n * Intel\", because why should it be?) and didn't imply too close of an\n * equivalence to the precise meanings that other platforms may assign\n * to some of these strings.\n */\n\n\n// Returns the fully qualified arch of this host -- something like\n// \"os.linux.x86_32\" or \"os.osx.x86_64\". Must be called inside\n// a fiber. Throws an error if it's not a supported architecture.\n//\n// If you change this, also change scripts/admin/launch-meteor\nvar _host = null; // memoize\nvar host = function () {\n  if (! _host) {\n    var run = function (...args) {\n      var result = utils.execFileSync(args[0], args.slice(1)).stdout;\n      if (! result) {\n        throw new Error(\"can't get arch with \" + args.join(\" \") + \"?\");\n      }\n      return result.replace(/\\s*$/, ''); // trailing whitespace\n    };\n\n    var platform = os.platform();\n\n    if (platform === \"darwin\") {\n      // Can't just test uname -m = x86_64, because Snow Leopard can\n      // return other values.\n      if (run('uname', '-p') !== \"i386\" ||\n          run('sysctl', '-n', 'hw.cpu64bit_capable') !== \"1\") {\n        throw new Error(\"Only 64-bit Intel processors are supported on OS X\");\n      }\n      _host  = \"os.osx.x86_64\";\n    }\n\n    else if (_.contains([\"linux\", \"freebsd\", \"openbsd\", \"netbsd\"], platform)) {\n      var machine = run('uname', '-m');\n      if (_.contains([\"i386\", \"i686\", \"x86\"], machine)) {\n        _host = \"os.\" + platform + \".x86_32\";\n      } else if (_.contains([\"x86_64\", \"amd64\", \"ia64\"], machine)) {\n        _host = \"os.\" + platform + \".x86_64\";\n      } else if (_.contains([\"armv6l\"], machine)) {\n        _host = \"os.\" + platform + \".armv6l\";\n      } else if (_.contains([\"armv7l\"], machine)) {\n        _host = \"os.\" + platform + \".armv7l\";\n      } else {\n        throw new Error(\"Unsupported architecture: \" + machine);\n      }\n    }\n\n    else if (platform === \"win32\") {\n      // We also use 32 bit builds on 64 bit Windows architectures.\n      _host = \"os.windows.x86_32\";\n    } else {\n      throw new Error(\"Unsupported operating system: \" + platform);\n    }\n  }\n\n  return _host;\n};\n\n// True if `host` (an architecture name such as 'os.linux.x86_64') can run\n// programs of architecture `program` (which might be something like 'os',\n// 'os.linux', or 'os.linux.x86_64').\n//\n// `host` and `program` are just mnemonics -- `host` does not\n// necessariy have to be a fully qualified architecture name. This\n// function just checks to see if `program` describes a set of\n// enviroments that is a (non-strict) superset of `host`.\nvar matches = function (host, program) {\n  return host.substr(0, program.length) === program &&\n    (host.length === program.length ||\n     host.substr(program.length, 1) === \".\");\n};\n\n// Like `supports`, but instead taken an array of possible\n// architectures as its second argument. Returns the most specific\n// match, or null if none match. Throws an error if `programs`\n// contains exact duplicates.\nvar mostSpecificMatch = function (host, programs) {\n  var seen = {};\n  var best = null;\n\n  _.each(programs, function (p) {\n    if (seen[p]) {\n      throw new Error(\"Duplicate architecture: \" + p);\n    }\n    seen[p] = true;\n    if (archinfo.matches(host, p) &&\n        (! best || p.length > best.length)) {\n      best = p;\n    }\n  });\n\n  return best;\n};\n\n// `programs` is a set of architectures (as an array of string, which\n// may contain duplicates). Determine if there exists any architecture\n// that is compatible with all of the architectures in the set. If so,\n// returns the least specific such architecture. Otherwise (the\n// architectures are disjoin) raise an exception.\n//\n// For example, for 'os' and 'os.osx', return 'os.osx'. For 'os' and\n// 'os.linux.x86_64', return 'os.linux.x86_64'. For 'os' and 'browser', throw an\n// exception.\nvar leastSpecificDescription = function (programs) {\n  if (programs.length === 0) {\n    return '';\n  }\n\n  // Find the longest string\n  var longest = _.max(programs, function (p) { return p.length; });\n\n  // If everything else in the list is compatible with the longest,\n  // then it must be the most specific, and if everything is\n  // compatible with the most specific then it must be the least\n  // specific compatible description.\n  _.each(programs, function (p) {\n    if (! archinfo.matches(longest, p)) {\n      throw new Error(\"Incompatible architectures: '\" + p + \"' and '\" +\n                      longest + \"'\");\n    }\n  });\n\n  return longest;\n};\n\nvar withoutSpecificOs = function (arch) {\n  if (arch.substr(0, 3) === 'os.') {\n    return 'os';\n  }\n  return arch;\n};\n\nvar archinfo = exports;\n_.extend(archinfo, {\n  host: host,\n  matches: matches,\n  mostSpecificMatch: mostSpecificMatch,\n  leastSpecificDescription: leastSpecificDescription,\n  withoutSpecificOs: withoutSpecificOs\n});\n"
  },
  {
    "path": "tools/utils/buildmessage.js",
    "content": "var _ = require('underscore');\nvar files = require('../fs/files.js');\nvar parseStack = require('./parse-stack.js');\nvar fiberHelpers = require('./fiber-helpers.js');\nvar Progress = require('../console/progress.js').Progress;\n\nvar debugBuild = !!process.env.METEOR_DEBUG_BUILD;\n\n// A job is something like \"building package foo\". It contains the set\n// of messages generated by tha job. A given build run could contain\n// several jobs. Each job has an (absolute) path associated with\n// it. Filenames in messages within a job are to be interpreted\n// relative to that path.\n//\n// Jobs are used both for error handling (via buildmessage.capture) and to set\n// the progress bar title (via progress.js).\n//\n// Job titles should begin with a lower-case letter (unless they begin with a\n// proper noun), so that they look correct in error messages which say \"While\n// jobbing the job\".  The first letter will be capitalized automatically for the\n// progress bar.\nvar Job = function (options) {\n  var self = this;\n  self.messages = [];\n\n  // Should be something like \"building package 'foo'\"\n  // Should look good in \"While $title:\\n[messages]\"\n  self.title = options.title;\n  self.rootPath = options.rootPath;\n\n  // Array of Job (jobs created inside this job)\n  self.children = [];\n};\n\n_.extend(Job.prototype, {\n  // options may include type (\"error\"), message, func, file, line,\n  // column, stack (in the format returned by parseStack.parse())\n  addMessage: function (options) {\n    var self = this;\n    self.messages.push(options);\n  },\n\n  hasMessages: function () {\n    var self = this;\n    return self.messages.length > 0;\n  },\n\n  hasMessageWithTag: function (tagName) {\n    var self = this;\n    return _.any(self.messages, function (message) {\n      return message.tags && _.has(message.tags, tagName);\n    });\n  },\n\n  // Returns a multi-line string suitable for displaying to the user\n  formatMessages: function (indent) {\n    var self = this;\n    var out = \"\";\n    var already = {};\n    indent = new Array((indent || 0) + 1).join(' ');\n\n    _.each(self.messages, function (message) {\n      var stack = message.stack || [];\n\n      var line = indent;\n      if (message.file) {\n        line+= message.file;\n        if (message.line) {\n          line += \":\" + message.line;\n          if (message.column) {\n            // XXX maybe exclude unless specifically requested (eg,\n            // for an automated tool that's parsing our output?)\n            line += \":\" + message.column;\n          }\n        }\n        line += \": \";\n      } else {\n        // not sure how to display messages without a filenanme.. try this?\n        line += \"error: \";\n      }\n      // XXX line wrapping would be nice..\n      line += message.message;\n      if (message.func && stack.length <= 1) {\n        line += \" (at \" + message.func + \")\";\n      }\n      line += \"\\n\";\n\n      if (stack.length > 1) {\n        _.each(stack, function (frame) {\n          // If a nontrivial stack trace (more than just the file and line\n          // we already complained about), print it.\n          var where = \"\";\n          if (frame.file) {\n            where += frame.file;\n            if (frame.line) {\n              where += \":\" + frame.line;\n              if (frame.column) {\n                where += \":\" + frame.column;\n              }\n            }\n          }\n\n          if (! frame.func && ! where) {\n            // that's a pretty lame stack frame\n            return;\n          }\n\n          line += \"  at \";\n          if (frame.func) {\n            line += frame.func + \" (\" + where + \")\\n\";\n          } else {\n            line += where + \"\\n\";\n          }\n        });\n        line += \"\\n\";\n      }\n\n      // Deduplicate messages (only when exact duplicates, including stack)\n      if (! (line in already)) {\n        out += line;\n        already[line] = true;\n      }\n    });\n\n    return out;\n  }\n\n});\n\n// A MessageSet contains a set of jobs, which in turn each contain a\n// set of messages.\nvar MessageSet = function (messageSet) {\n  var self = this;\n  self.jobs = [];\n\n  if (messageSet) {\n    self.jobs = _.clone(messageSet.jobs);\n  }\n};\n\n_.extend(MessageSet.prototype, {\n  formatMessages: function () {\n    var self = this;\n\n    var jobsWithMessages = _.filter(self.jobs, function (job) {\n      return job.hasMessages();\n    });\n\n    return _.map(jobsWithMessages, function (job) {\n      var out = '';\n      out += \"While \" + job.title + \":\\n\";\n      out += job.formatMessages(0);\n      return out;\n    }).join('\\n'); // blank line between jobs\n  },\n\n  hasMessages: function () {\n    var self = this;\n    return _.any(self.jobs, function (job) {\n      return job.hasMessages();\n    });\n  },\n\n  hasMessageWithTag: function (tagName) {\n    var self = this;\n    return _.any(self.jobs, function (job) {\n      return job.hasMessageWithTag(tagName);\n    });\n  },\n\n  // Copy all of the messages in another MessageSet into this\n  // MessageSet. If the other MessageSet is subsequently mutated,\n  // results are undefined.\n  //\n  // XXX rather than this, the user should be able to create a\n  // MessageSet and pass it into capture(), and functions such as\n  // bundle() should take and mutate, rather than return, a\n  // MessageSet.\n  merge: function (messageSet) {\n    var self = this;\n    _.each(messageSet.jobs, function (j) {\n      self.jobs.push(j);\n    });\n  }\n});\n\nvar spaces = function (n) {\n  return _.times(n, function() { return ' ' }).join('');\n};\n\n// XXX: This is now a little bit silly... ideas:\n// Can we just have one hierarchical state?\n// Can we combined job & messageSet\n// Can we infer nesting level?\nvar currentMessageSet = new fiberHelpers.EnvironmentVariable;\nvar currentJob = new fiberHelpers.EnvironmentVariable;\nvar currentNestingLevel = new fiberHelpers.EnvironmentVariable(0);\nvar currentProgress = new fiberHelpers.EnvironmentVariable;\n\nvar rootProgress = new Progress();\n\nvar getRootProgress = function () {\n  return rootProgress;\n};\n\nvar reportProgress = function (state) {\n  var progress = currentProgress.get();\n  if (progress) {\n    progress.reportProgress(state);\n  }\n};\n\nvar reportProgressDone = function () {\n  var progress = currentProgress.get();\n  if (progress) {\n    progress.reportProgressDone();\n  }\n};\n\nvar getCurrentProgressTracker = function () {\n  var progress = currentProgress.get();\n  return progress ? progress : rootProgress;\n};\n\nvar addChildTracker = function (title) {\n  var options = {};\n  if (title !== undefined) {\n    options.title = title;\n  }\n  return getCurrentProgressTracker().addChildTask(options);\n};\n\n// Create a new MessageSet, run `f` with that as the current\n// MessageSet for the purpose of accumulating and recovering from\n// errors (see error()), and then discard the return value of `f` and\n// return the MessageSet.\n//\n// Note that you must also create a job (with enterJob) to actually\n// begin capturing errors. Alternately you may pass `options`\n// (otherwise optional) and a job will be created for you based on\n// `options`.\nvar capture = function (options, f) {\n  var messageSet = new MessageSet;\n  var parentMessageSet = currentMessageSet.get();\n\n  var title;\n  if (typeof options === \"object\" && options.title) {\n    title = options.title;\n  }\n  var progress = addChildTracker(title);\n\n  currentProgress.withValue(progress, function () {\n    currentMessageSet.withValue(messageSet, function () {\n      var job = null;\n      if (typeof options === \"object\") {\n        job = new Job(options);\n        messageSet.jobs.push(job);\n      } else {\n        f = options; // options not actually provided\n      }\n\n      currentJob.withValue(job, function () {\n        var nestingLevel = currentNestingLevel.get();\n        currentNestingLevel.withValue(nestingLevel + 1, function () {\n          var start;\n          if (debugBuild) {\n            start = Date.now();\n            console.log(spaces(nestingLevel * 2), \"START CAPTURE\", nestingLevel, options.title, \"took \" + (end - start));\n          }\n          try {\n            f();\n          } finally {\n            progress.reportProgressDone();\n\n            if (debugBuild) {\n              var end = Date.now();\n              console.log(spaces(nestingLevel * 2), \"END CAPTURE\", nestingLevel, options.title, \"took \" + (end - start));\n            }\n          }\n        });\n      });\n    });\n  });\n  return messageSet;\n};\n\n// Called from inside capture(), creates a new Job inside the current\n// MessageSet and run `f` inside of it, so that any messages emitted\n// by `f` are logged in the Job. Returns the return value of `f`. May\n// be called recursively.\n//\n// Called not from inside capture(), does nothing (except call f).\n//\n// options:\n// - title: a title for the job (required)\n// - rootPath: the absolute path relative to which paths in messages\n//   in this job should be interpreted (omit if there is no way to map\n//   files that this job talks about back to files on disk)\nvar enterJob = function (options, f) {\n  if (typeof options === \"function\") {\n    f = options;\n    options = {};\n  }\n\n  if (typeof options === \"string\") {\n    options = {title: options};\n  }\n\n  var progress;\n  {\n    var progressOptions = {};\n    // XXX: Just pass all the options?\n    if (typeof options === \"object\") {\n      if (options.title) {\n        progressOptions.title = options.title;\n      }\n      if (options.forkJoin) {\n        progressOptions.forkJoin = options.forkJoin;\n      }\n    }\n    progress = getCurrentProgressTracker().addChildTask(progressOptions);\n  }\n\n  return currentProgress.withValue(progress, function () {\n    if (!currentMessageSet.get()) {\n      var nestingLevel = currentNestingLevel.get();\n      var start;\n      if (debugBuild) {\n        start = Date.now();\n        console.log(spaces(nestingLevel * 2), \"START\", nestingLevel, options.title);\n      }\n      try {\n        return currentNestingLevel.withValue(nestingLevel + 1, function () {\n          return f();\n        });\n      } finally {\n        progress.reportProgressDone();\n        if (debugBuild) {\n          var end = Date.now();\n          console.log(spaces(nestingLevel * 2), \"DONE\", nestingLevel, options.title, \"took \" + (end - start));\n        }\n      }\n    }\n\n    var job = new Job(options);\n    var originalJob = currentJob.get();\n    originalJob && originalJob.children.push(job);\n    currentMessageSet.get().jobs.push(job);\n\n    return currentJob.withValue(job, function () {\n      var nestingLevel = currentNestingLevel.get();\n      return currentNestingLevel.withValue(nestingLevel + 1, function () {\n        var start;\n        if (debugBuild) {\n          start = Date.now();\n          console.log(spaces(nestingLevel * 2), \"START\", nestingLevel, options.title);\n        }\n        try {\n          return f();\n        } finally {\n          progress.reportProgressDone();\n          if (debugBuild) {\n            var end = Date.now();\n            console.log(spaces(nestingLevel * 2), \"DONE\", nestingLevel, options.title, \"took \" + (end - start));\n          }\n        }\n      });\n    });\n  });\n};\n\n// If not inside a job, return false. Otherwise, return true if any\n// messages (presumably errors) have been recorded for this job\n// (including subjobs created inside this job), else false.\nvar jobHasMessages = function () {\n  var search = function (job) {\n    if (job.hasMessages()) {\n      return true;\n    }\n    return !! _.find(job.children, search);\n  };\n\n  return currentJob.get() ? search(currentJob.get()) : false;\n};\n\n// Given a function f, return a \"marked\" version of f. The mark\n// indicates that stack traces should stop just above f. So if you\n// mark a user-supplied callback function before calling it, you'll be\n// able to show the user just the \"user portion\" of the stack trace\n// (the part inside their own code, and not all of the innards of the\n// code that called it).\nvar markBoundary = function (f) {\n  return parseStack.markBottom(f);\n};\n\n// Record a build error. If inside a job, add the error to the current\n// job and return (caller should do its best to recover and\n// continue). Otherwise, throws an exception based on the error.\n//\n// options may include\n// - file: the file containing the error, relative to the root of the build\n//   (this must be agreed upon out of band)\n// - line: the (1-indexed) line in the file that contains the error\n// - column: the (1-indexed) column in that line where the error begins\n// - func: the function containing the code that triggered the error\n// - useMyCaller: true to capture information the caller (function\n//   name, file, and line). It captures not the information of the\n//   caller of error(), but that caller's caller. It saves them in\n//   'file', 'line', and 'column' (overwriting any values passed in\n//   for those). It also captures the user portion of the stack,\n//   starting at and including the caller's caller.\n//   If this is a number instead of 'true', skips that many stack frames.\n// - downcase: if true, the first character of `message` will be\n//   converted to lower case.\n// - secondary: ignore this error if there are are already other\n//   errors in this job (the implication is that it's probably\n//   downstream of the other error, ie, a consequence of our attempt\n//   to continue past other errors)\n// - tags: object with other error-specific data; there is a method\n//   on MessageSet which can search for errors with a specific named\n//   tag.\nvar error = function (message, options) {\n  options = options || {};\n\n  if (options.downcase) {\n    message = message.slice(0,1).toLowerCase() + message.slice(1);\n  }\n\n  if (! currentJob.get()) {\n    throw new Error(\"Error: \" + message);\n  }\n\n  if (options.secondary && jobHasMessages()) {\n    // skip it\n    return;\n  }\n\n  var info = _.extend({\n    message: message\n  }, options);\n\n  if ('useMyCaller' in info) {\n    if (info.useMyCaller) {\n      const {\n        insideFiber,\n        outsideFiber\n      } = parseStack.parse(new Error());\n\n      // Concatenate and get rid of lines about Future and buildmessage\n      info.stack = outsideFiber.concat(insideFiber || []).slice(2);\n      if (typeof info.useMyCaller === 'number') {\n        info.stack = info.stack.slice(info.useMyCaller);\n      }\n      var caller = info.stack[0];\n      info.func = caller.func;\n      info.file = caller.file;\n      info.line = caller.line;\n      info.column = caller.column;\n    }\n    delete info.useMyCaller;\n  }\n\n  currentJob.get().addMessage(info);\n};\n\n// Record an exception. The message as well as any file and line\n// information be read directly out of the exception. If not in a job,\n// throws the exception instead. Also capture the user portion of the stack.\n//\n// There is special handling for files.FancySyntaxError exceptions. We\n// will grab the file and location information where the syntax error\n// actually occurred, rather than the place where the exception was\n// thrown.\nvar exception = function (error) {\n  if (! currentJob.get()) {\n    // XXX this may be the wrong place to do this, but it makes syntax errors in\n    // files loaded via isopack.load have context.\n    if (error instanceof files.FancySyntaxError) {\n      error = new Error(\"Syntax error: \" + error.message + \" at \" +\n        error.file + \":\" + error.line + \":\" + error.column);\n    }\n    throw error;\n  }\n\n  var message = error.message;\n\n  if (error instanceof files.FancySyntaxError) {\n    // No stack, because FancySyntaxError isn't a real Error and has no stack\n    // property!\n    currentJob.get().addMessage({\n      message: message,\n      file: error.file,\n      line: error.line,\n      column: error.column\n    });\n  } else {\n    var parsed = parseStack.parse(error);\n\n    // If there is a part inside the fiber, that's the one we want. Otherwise,\n    // use the one outside.\n    var stack = parsed.insideFiber || parsed.outsideFiber;\n    if (stack && stack.length > 0) {\n      var locus = stack[0];\n      currentJob.get().addMessage({\n        message: message,\n        stack: stack,\n        func: locus.func,\n        file: locus.file,\n        line: locus.line,\n        column: locus.column\n      });\n    } else {\n      currentJob.get().addMessage({\n        message: message\n      });\n    }\n  }\n};\n\nvar assertInJob = function () {\n  if (! currentJob.get()) {\n    throw new Error(\"Expected to be in a buildmessage job\");\n  }\n};\n\nvar assertInCapture = function () {\n  if (! currentMessageSet.get()) {\n    throw new Error(\"Expected to be in a buildmessage capture\");\n  }\n};\n\nvar mergeMessagesIntoCurrentJob = function (innerMessages) {\n  var outerMessages = currentMessageSet.get();\n  if (! outerMessages) {\n    throw new Error(\"Expected to be in a buildmessage capture\");\n  }\n  var outerJob = currentJob.get();\n  if (! outerJob) {\n    throw new Error(\"Expected to be in a buildmessage job\");\n  }\n  _.each(innerMessages.jobs, function (j) {\n    outerJob.children.push(j);\n  });\n  outerMessages.merge(innerMessages);\n};\n\n// Like _.each, but runs each operation in a separate job\nvar forkJoin = function (options, iterable, fn) {\n  if (!_.isFunction(fn)) {\n    fn = iterable;\n    iterable = options;\n    options = {};\n  }\n\n  options.forkJoin = true;\n\n  function enterJobAsync(options) {\n    return new Promise((resolve, reject) => {\n      enterJob(options, err => {\n        err ? reject(err) : resolve();\n      });\n    });\n  }\n\n  const parallel = (options.parallel !== undefined) ? options.parallel : true;\n\n  return enterJobAsync(options).then(() => {\n    const errors = [];\n    let results = _.map(iterable, (...args) => {\n      const promise = enterJobAsync({\n        title: (options.title || \"\") + \" child\"\n      }).then(() => fn(...args))\n        // Collect any errors thrown (and later re-throw the first one),\n        // but don't stop processing remaining jobs.\n        .catch(error => (errors.push(error), null));\n\n      if (parallel) {\n        // If the jobs are intended to run in parallel, return each\n        // promise without awaiting it, so that Promise.all can wait for\n        // them all to be fulfilled.\n        return promise;\n      }\n\n      // By awaiting the promise during each iteration, we effectively\n      // serialize the execution of the jobs.\n      return promise.await();\n    });\n\n    if (parallel) {\n      // If the jobs ran in parallel, then results is an array of Promise\n      // objects that still need to be resolved.\n      results = Promise.all(results).await();\n    }\n\n    if (errors.length > 0) {\n      // If any errors were thrown, re-throw the first one. Note that this\n      // allows jobs to complete successfully (and have whatever\n      // side-effects they should have) after the first error is thrown,\n      // though the final results will not be returned below.\n      throw errors[0];\n    }\n\n    return results;\n  }).await();\n};\n\n\nvar buildmessage = exports;\n_.extend(exports, {\n  capture: capture,\n  enterJob: enterJob,\n  markBoundary: markBoundary,\n  error: error,\n  exception: exception,\n  jobHasMessages: jobHasMessages,\n  assertInJob: assertInJob,\n  assertInCapture: assertInCapture,\n  mergeMessagesIntoCurrentJob: mergeMessagesIntoCurrentJob,\n  forkJoin: forkJoin,\n  getRootProgress: getRootProgress,\n  reportProgress: reportProgress,\n  reportProgressDone: reportProgressDone,\n  getCurrentProgressTracker: getCurrentProgressTracker,\n  addChildTracker: addChildTracker,\n  _MessageSet: MessageSet\n});\n"
  },
  {
    "path": "tools/utils/buildmessage.md",
    "content": "# Build Message\n\nWe have a build process that does a lot of nested things. The build system\nshould report errors in the process to the user: compilation problems, incorrect\npackages, etc.\n\nWe could have used exceptions but not only it would be hard to pass exceptions\naround, it also wouldn't be correct because users making mistakes is part of the\nexpected use.\n\nAlso BuildMessage knows how to report errors better, recover on errors to\ncollect as many errors in one pass as possible. For example, if several files\nfail to be parsed, we want to report all of them.\n\ntry/catch usually marks a code call and says \"everything called from this try\nblock, dynamically, is handled by this catch block\". Build Message also has such\nproperty.\n\n`buildmessage.capture` - takes a function and runs it in a buildmessage\n\"context\" and returns a message set (a set of errors). When the code is running\ninside that \"capture\", the errors from it go to this message set.\n\nYou can check if there were any errors by checking `messages.hasMessages()`.\n\nThere are different applications of `capture`, a lot of parts of the code wrap\nit. There is `captureAndExit` that exits immediately after printing. In catalog\nwe have a wrapper that tries to run a function, if it has messages, refreshes\nthe catalog and tries again.\n\nIn the lower-level code you usually never print the messages, you pass them up\nalong the stack to be handled by something else (printing by cli or displaying\nby gui, etc).\n\n`capture` is not useful without jobs. You use `buildmessage.enterJob` to create\na new job. It has a title.\n\n`buildmessage.error` is the function you use to say \"something bad happened\".\nThe innermost job will provide more information to the error.\nEx.: \"While building package X: an error happened\"\n\nIt should always be called inside a job. It will throw an exception if it is not\ninside, but you should not do this.\n\nThere is also a `buildmessage.exception`, the idea is, you use it to report the\nactual exceptions. Usually you use it to rethrow exceptions from a user package\nor a build plugin. It has some fancy stack-trace parsing and formatting.\nEx.: \"An exception while running your package.js file: TypeError ...\".\n\nAnother function that you would run a lot is `job.hasMessages()`. Unlike\nexceptions, when you notify the buildmessage of errors, it doesn't stop the\nexecution, it keeps going. This gives you an opportunity to recover and go on to\nget more errors. But if you don't want to keep going, you can check if there are\nany errors in the current job by calling `job.hasMessages()`. This call also\nincludes messages from nested jobs.\n\nInitially buildmessage was used only for error reporting, but now it is also\nused for the progress bars. It doesn't hurt the error reporting, it gives the\nerror messages better locality (assuming it is useful).\n\n## Quick recap:\n\n- `buildmessage.capture` - the same as a `try-catch` block\n- `buildmessage.error` - is like throwing an exception (except it doesn't stop there)\n- `buildmessage.enterJob` - is a concept similar to a stack-frame\n- `capture.messages()` - get all errors\n- `job.hasMessages()` - check if there are any errors so far\n\n\n## Misc\n\nHelpers for asserting the code structure:\n\n- `assertInJob`\n- `assertInCapture`\n\nA helper to run the user code:\n\n- `files.runJavascript` - a helper to run the user code\n- `buildmessage.markBoundary` - a helper that marks the entry point of the user\n  code (like a build plugin), later when an `buildmessage.exception` is called,\n  the buildmessage will remove unnecessary stack-frames from the stack-trace so\n  the error displayed to the user doesn't contain any frames from tool.\n\nEx.:\n\n```\nvar result = null;\nf = function () { user provided code };\ntry {\n  var markedF = buildmessage.markBoundary(f);\n  result = markedF();\n} catch (e) {\n  buildmessage.exception(e);\n  // clean up\n  ...\n  // pretend nothing happened so we can recover and move on to find other errors\n  result = { name: \"dummy\" };\n}\n```\n\n"
  },
  {
    "path": "tools/utils/colon-converter.js",
    "content": "var _ = require('underscore');\n\n// schema - Object, representing paths to correct. Ex.:\n// {\n//   format: false,\n//   arch: false,\n//   load: [\n//     {\n//       node_modulus: true,\n//       sourceMap: true,\n//       sourceMapRoot: true,\n//       path: true\n//     }\n//   ]\n// }\nvar convertBySchema = function (val, schema) {\n  if (schema === true) {\n    return convert(val);\n  } else if (schema === false) {\n    return val;\n  }\n\n  if (_.isArray(schema)) {\n    if (schema.length !== 1) {\n      throw new Error(\"Expected an array with one element in schema\");\n    }\n\n    if (! _.isArray(val)) {\n      throw new Error(\"Expected an array in value, got \" + typeof val);\n    }\n\n    return _.map(val, function (subval) {\n      return convertBySchema(subval, schema[0]);\n    });\n  }\n\n  if (! _.isObject(schema)) {\n    throw new Error(\"Unexpected type of schema: \" + typeof(schema));\n  }\n\n  var ret = _.clone(val);\n  _.each(schema, function (subschema, key) {\n    if (_.has(ret, key)) {\n      ret[key] = convertBySchema(val[key], subschema);\n    }\n  });\n\n  return ret;\n};\n\nvar convert = function (path) {\n  return path.replace(/:/g, '_');\n};\n\nvar ISOPACK_SCHEME = {\n  builds: [{\n    path: true\n  }],\n  plugins: [{\n    path: true\n  }]\n};\n\nvar UNIBUILD_SCHEME = {\n  node_modules: true,\n  resources: [{\n    file: true,\n    sourceMap: true,\n    servePath: true\n  }]\n};\n\nvar JAVASCRIPT_IMAGE_SCHEME = {\n  load: [{\n    sourceMap: true,\n    sourceMapRoot: true,\n    path: true,\n    node_modules: true\n  }]\n};\n\nexports.convertIsopack = function (data) {\n  return convertBySchema(data, ISOPACK_SCHEME);\n};\n\nexports.convertUnibuild = function (data) {\n  return convertBySchema(data, UNIBUILD_SCHEME);\n};\n\nexports.convertJSImage = function (data) {\n  return convertBySchema(data, JAVASCRIPT_IMAGE_SCHEME);\n};\n\nexports.convert = convert;\n\n"
  },
  {
    "path": "tools/utils/fiber-helpers.js",
    "content": "var _ = require(\"underscore\");\nvar Fiber = require(\"fibers\");\n\nexports.parallelEach = function (collection, callback, context) {\n  const errors = [];\n  context = context || null;\n\n  const results = Promise.all(_.map(collection, (...args) => {\n    async function run() {\n      return callback.apply(context, args);\n    }\n\n    return run().catch(error => {\n      // Collect the errors but do not propagate them so that we can\n      // re-throw the first error after all iterations have completed.\n      errors.push(error);\n    });\n  })).await();\n\n  if (errors.length > 0) {\n    throw errors[0];\n  }\n\n  return results;\n};\n\nfunction disallowedYield() {\n  throw new Error(\"Can't call yield in a noYieldsAllowed block!\");\n}\n// Allow testing Fiber.yield.disallowed.\ndisallowedYield.disallowed = true;\n\nexports.noYieldsAllowed = function (f, context) {\n  var savedYield = Fiber.yield;\n  Fiber.yield = disallowedYield;\n  try {\n    return f.call(context || null);\n  } finally {\n    Fiber.yield = savedYield;\n  }\n};\n\n// Borrowed from packages/meteor/dynamics_nodejs.js\n// Used by buildmessage\n\nexports.nodeCodeMustBeInFiber = function () {\n  if (!Fiber.current) {\n    throw new Error(\"Meteor code must always run within a Fiber. \" +\n                    \"Try wrapping callbacks that you pass to non-Meteor \" +\n                    \"libraries with Meteor.bindEnvironment.\");\n  }\n};\n\nvar nextSlot = 0;\nexports.EnvironmentVariable = function (defaultValue) {\n  var self = this;\n  self.slot = 'slot' + nextSlot++;\n  self.defaultValue = defaultValue;\n};\n\n_.extend(exports.EnvironmentVariable.prototype, {\n  get: function () {\n    var self = this;\n    exports.nodeCodeMustBeInFiber();\n\n    if (!Fiber.current._meteorDynamics) {\n      return self.defaultValue;\n    }\n    if (!_.has(Fiber.current._meteorDynamics, self.slot)) {\n      return self.defaultValue;\n    }\n    return Fiber.current._meteorDynamics[self.slot];\n  },\n\n  withValue: function (value, func) {\n    var self = this;\n    exports.nodeCodeMustBeInFiber();\n\n    if (!Fiber.current._meteorDynamics) {\n      Fiber.current._meteorDynamics = {};\n    }\n    var currentValues = Fiber.current._meteorDynamics;\n\n    var saved = _.has(currentValues, self.slot)\n          ? currentValues[self.slot] : self.defaultValue;\n    currentValues[self.slot] = value;\n\n    try {\n      return func();\n    } finally {\n      currentValues[self.slot] = saved;\n    }\n  }\n});\n\n// This is like Meteor.bindEnvironment.\n// Experimentally, we are NOT including onException or _this in this version.\nexports.bindEnvironment = function (func) {\n  exports.nodeCodeMustBeInFiber();\n\n  var boundValues = _.clone(Fiber.current._meteorDynamics || {});\n\n  return function (...args) {\n    var self = this;\n\n    var runWithEnvironment = function () {\n      var savedValues = Fiber.current._meteorDynamics;\n      try {\n        // Need to clone boundValues in case two fibers invoke this\n        // function at the same time\n        Fiber.current._meteorDynamics = _.clone(boundValues);\n        return func.apply(self, args);\n      } finally {\n        Fiber.current._meteorDynamics = savedValues;\n      }\n    };\n\n    if (Fiber.current) {\n      return runWithEnvironment();\n    }\n    Fiber(runWithEnvironment).run();\n  };\n};\n\n// Returns a Promise that supports .resolve(result) and .reject(error).\nexports.makeFulfillablePromise = function () {\n  var resolve, reject;\n  var promise = new Promise(function (res, rej) {\n    resolve = res;\n    reject = rej;\n  });\n  promise.resolve = resolve;\n  promise.reject = reject;\n  return promise;\n};\n"
  },
  {
    "path": "tools/utils/func-utils.js",
    "content": "// Return a function that coalesceses calls to fn that occur within delay\n// milliseconds of each other, and prevents overlapping invocations of fn\n// by postponing the next invocation until after fn's fiber finishes.\nexports.coalesce = function(delayMs, callback, context) {\n  var pending = false;\n  var inProgress = 0;\n\n  delayMs = delayMs || 100;\n\n  function coalescingWrapper() {\n    var self = context || this;\n\n    if (inProgress) {\n      // Indicate that coalescingWrapper should be called again after the\n      // callback is no longer in progress.\n      ++inProgress;\n      return;\n    }\n\n    if (pending) {\n      // Defer to the already-pending timer.\n      return;\n    }\n\n    new Promise(\n      resolve => setTimeout(resolve, delayMs)\n    ).then(function thenCallback() {\n      // Now that the timeout has fired, set inProgress to 1 so that\n      // (until the callback is complete and we set inProgress to 0 again)\n      // any calls to coalescingWrapper will increment inProgress to\n      // indicate that at least one other caller wants fiberCallback to be\n      // called again when the original callback is complete.\n      pending = false;\n      inProgress = 1;\n\n      try {\n        callback.call(self);\n      } finally {\n        if (inProgress > 1) {\n          Promise.resolve().then(thenCallback);\n          pending = true;\n        }\n        inProgress = 0;\n      }\n    });\n  }\n\n  return wrap(coalescingWrapper, callback);\n};\n\nfunction wrap(wrapper, wrapped) {\n  // Allow the wrapper to be used as a constructor function, just in case\n  // the wrapped function was meant to be used as a constructor.\n  wrapper.prototype = wrapped.prototype;\n\n  // https://medium.com/@cramforce/on-the-awesomeness-of-fn-displayname-9511933a714a\n  var name = wrapped.displayName || wrapped.name;\n  if (name) {\n    wrapper.displayName = name;\n  }\n\n  return wrapper;\n}\n"
  },
  {
    "path": "tools/utils/http-helpers.js",
    "content": "///\n/// utility functions for dealing with urls and http\n///\n\nvar os = require('os');\nvar util = require('util');\n\nvar _ = require('underscore');\n\nvar files = require('../fs/files.js');\nvar auth = require('../meteor-services/auth.js');\nvar config = require('../meteor-services/config.js');\nvar release = require('../packaging/release.js');\nvar Console = require('../console/console.js').Console;\nvar timeoutScaleFactor = require('./utils.js').timeoutScaleFactor;\n\n\n// Helper that tracks bytes written to a writable\nvar WritableWithProgress = function (writable, listener) {\n  var self = this;\n  self._inner = writable;\n  self._listener = listener;\n};\n\n_.extend(WritableWithProgress.prototype, {\n  write: function (chunk, encoding, callback) {\n    var self = this;\n    self._listener(chunk.length, false);\n    return self._inner.write(chunk, encoding);\n  },\n\n  end: function (chunk, encoding, callback) {\n    var self = this;\n    self._listener(chunk ? chunk.length : 0, true);\n    return self._inner.end(chunk, encoding);\n  },\n\n  _progress: function (n, done) {\n    var self = this;\n\n    var state = self._state;\n    state.current += n;\n    if (done) {\n      state.current.done = true;\n    }\n    self.progress.reportProgress(state);\n  },\n\n  on: function (name, callback) {\n    return this._inner.on(name, callback);\n  },\n\n  once: function () {\n    return this._inner.once(...arguments);\n  },\n\n  emit: function () {\n    return this._inner.emit(...arguments);\n  }\n});\n\n\n// Compose a User-Agent header.\nvar getUserAgent = function () {\n  var version;\n\n  if (release.current) {\n    version = release.current.isCheckout() ? 'checkout' : release.current.name;\n  } else {\n    // This happens when we haven't finished starting up yet (say, the\n    // user passed --release 1.2.3 and we have to download 1.2.3\n    // before we can get going), or if we are using an installed copy\n    // of Meteor to 'meteor update'ing a project that was created by a\n    // checkout and doesn't have a version yet.\n    version = files.inCheckout() ? 'checkout' : files.getToolsVersion();\n  }\n\n  return util.format('Meteor/%s OS/%s (%s; %s; %s;)', version,\n                     os.platform(), os.type(), os.release(), os.arch());\n};\n\n\nvar httpHelpers = exports;\n_.extend(exports, {\n  getUserAgent: getUserAgent,\n\n  // A wrapper around request with the following improvements:\n  //\n  // - It will respect proxy environment variables if present\n  //   (HTTP_PROXY or HTTPS_PROXY as appropriate).\n  //\n  // - It will set a reasonable User-Agent header.\n  //\n  // - If you omit the callback it will run synchronously. The return\n  //   value will be an object with keys 'response' and 'body' (with\n  //   the same meaning as the arguments to request's normal\n  //   callback), or it will throw.\n  //\n  // - If Set-Cookie headers are present on the response, *and* you\n  //   are using a callback, it will parse the cookies and include\n  //   them as a setCookie attribute on the object passed to the\n  //   callback. setCookie is a simple map from cookie name to cookie\n  //   value. If you want expiration time and attributes you'll have\n  //   to parse it yourself. If there are multiple Set-Cookie headers\n  //   for the same cookie it is unspecified which one you'll get.\n  //\n  // - You can provide a 'bodyStream' option which is a stream that\n  //   will be used for the body of the request.\n  //\n  // - For authenticated MDG services, you can set the\n  //   'useSessionHeader' and/or 'useAuthHeader' options (to true) to\n  //   send X-Meteor-Session/X-Meteor-Auth headers using values from\n  //   the session file.\n  //\n  // - forceSSL is always set to true. Always. And followRedirect is\n  //   set to false since it doesn't understand origins (see comment\n  //   in implementation).\n  //\n  // NB: With useSessionHeader and useAuthHeader, this function will\n  // read *and possibly write to* the session file, so if you are\n  // writing auth code (in auth.js) and you call it, be sure to reread\n  // the session file afterwards.\n  request: function (urlOrOptions, callback) {\n    var options;\n    if (!_.isObject(urlOrOptions)) {\n      options = { url: urlOrOptions };\n    } else {\n      options = _.clone(urlOrOptions);\n    }\n\n    var bodyStream;\n    if (_.has(options, 'bodyStream')) {\n      bodyStream = options.bodyStream;\n      delete options.bodyStream;\n    }\n\n    // Body stream length for progress\n    var bodyStreamLength = 0;\n    if (_.has(options, 'bodyStream')) {\n      bodyStreamLength = options.bodyStreamLength;\n      delete options.bodyStreamLength;\n    } else {\n      // Guess the body stream length as 1MB\n      // Hopefully if it's much bigger the caller will set it\n      // If it is much small, we will pleasantly surprise the user!\n      if (bodyStream) {\n        bodyStreamLength = 1024 * 1024;\n      }\n    }\n\n    // Response length for progress\n    var responseLength = 128 * 1024;\n    if (_.has(options, 'responseLength')) {\n      responseLength = options.responseLength;\n      delete options.responseLength;\n    }\n\n    var progress = null;\n    if (_.has(options, 'progress')) {\n      progress = options.progress;\n      delete options.progress;\n\n      if (callback) {\n        throw new Error(\"Not safe to use progress with callback\");\n      }\n    }\n\n    options.headers = _.extend({\n      'User-Agent': getUserAgent()\n    }, options.headers || {});\n\n    // This should never, ever be false, or else why are you using SSL?\n    options.forceSSL = true;\n    if (process.env.CAFILE) {\n      options.ca = files.readFile(process.env.CAFILE);\n    }\n\n    // followRedirect is very dangerous because request does not\n    // appear to segregate cookies by origin, so any cookies (and\n    // apparently headers as well, eg X-Meteor-Auth) sent on the\n    // original request could get forwarded to an unexpected domain in\n    // a redirect. This is almost certainly not something you ever\n    // want.\n    options.followRedirect = false;\n\n    var useSessionHeader = options.useSessionHeader;\n    delete options.useSessionHeader;\n    var useAuthHeader = options.useAuthHeader;\n    delete options.useAuthHeader;\n    if (useSessionHeader || useAuthHeader) {\n      var sessionHeader = auth.getSessionId(config.getAccountsDomain());\n      if (sessionHeader) {\n        options.headers['X-Meteor-Session'] = sessionHeader;\n      }\n      if (callback) {\n        throw new Error(\"session header can't be used with callback\");\n      }\n    }\n    if (useAuthHeader) {\n      var authHeader = auth.getSessionToken(config.getAccountsDomain());\n      if (authHeader) {\n        options.headers['X-Meteor-Auth'] = authHeader;\n      }\n    }\n\n    var promise;\n    if (! callback) {\n      promise = new Promise(function (resolve, reject) {\n        callback = function (err, response, body) {\n          if (err) {\n            reject(err);\n            return;\n          }\n\n          var setCookie = {};\n          _.each(response.headers[\"set-cookie\"] || [], function (h) {\n            var match = h.match(/^([^=\\s]+)=([^;\\s]+)/);\n            if (match) {\n              setCookie[match[1]] = match[2];\n            }\n          });\n\n          if (useSessionHeader && _.has(response.headers, \"x-meteor-session\")) {\n            auth.setSessionId(config.getAccountsDomain(),\n                              response.headers['x-meteor-session']);\n          }\n\n          resolve({\n            response: response,\n            body: body,\n            setCookie: setCookie\n          });\n        };\n      });\n    }\n\n    // try to get proxy from environment.\n    // similar code is in packages/ddp/stream_client_nodejs.js\n    var proxy = process.env.HTTP_PROXY || process.env.http_proxy || null;\n    // if we're going to an https url, try the https_proxy env variable first.\n    if (/^https/i.test(options.url)) {\n      proxy = process.env.HTTPS_PROXY || process.env.https_proxy || proxy;\n    }\n    if (proxy && !options.proxy) {\n      options.proxy = proxy;\n    }\n\n    if (! _.has(options, \"timeout\")) {\n      // 60 seconds for timeout between initial response headers and data,\n      // and between chunks of data while reading the rest of the response.\n      options.timeout = 60 * 1000 * timeoutScaleFactor;\n    } else if (! (typeof options.timeout === \"number\" &&\n                  options.timeout > 0)) {\n      // The timeout can be disabled by passing anything other than a\n      // positive number, e.g. { timeout: null }.\n      delete options.timeout;\n    }\n\n    // request is the most heavy-weight of the tool's npm dependencies; don't\n    // require it until we definitely need it.\n    Console.debug(\"Doing HTTP request: \", options.method || 'GET', options.url);\n    var request = require('request');\n    var req = request(options, callback);\n\n\n    var totalProgress = { current: 0, end: bodyStreamLength + responseLength, done: false };\n\n    if (bodyStream) {\n      var dest = req;\n      if (progress) {\n        dest = new WritableWithProgress(dest, function (n, done) {\n          if (!totalProgress.done) {\n            totalProgress.current += n;\n            progress.reportProgress(totalProgress);\n          }\n        });\n      }\n      bodyStream.pipe(dest);\n    }\n\n    if (progress) {\n      httpHelpers._addProgressEvents(req);\n      req.on('progress', function (state) {\n        if (!totalProgress.done) {\n          totalProgress.current = bodyStreamLength + state.current;\n          totalProgress.end = bodyStreamLength + state.end;\n          totalProgress.done = state.done;\n\n          progress.reportProgress(totalProgress);\n        }\n      });\n    }\n\n    if (promise) {\n      try {\n        return promise.await();\n      } finally {\n        if (progress) {\n          progress.reportProgressDone();\n        }\n      }\n    } else {\n      return req;\n    }\n  },\n\n  // Adds progress callbacks to a request\n  // Based on request-progress\n  _addProgressEvents: function (request) {\n    var state;\n\n    var emitProgress = function () {\n      request.emit('progress', state);\n    };\n\n    request\n      .on('response', function (response) {\n        state = {};\n        state.end = undefined;\n        state.done = false;\n        state.current = 0;\n        var contentLength = response.headers['content-length'];\n        if (contentLength) {\n          state.end = Number(contentLength);\n        }\n        emitProgress();\n      })\n      .on('data', function (data) {\n        state.current += data.length;\n        emitProgress();\n      })\n      .on('end', function (data) {\n        state.done = true;\n        emitProgress();\n      });\n  },\n\n  // A synchronous wrapper around request(...) that returns the response \"body\"\n  // or throws.\n  //\n  // (This has gone through a few refactors and it might be possible\n  // to fully roll it into httpHelpers.request() at this point.)\n  getUrl: function (urlOrOptions) {\n    try {\n      var result = httpHelpers.request(urlOrOptions);\n    } catch (e) {\n      throw new files.OfflineError(e);\n    }\n\n    const response = result.response;\n    const body = result.body;\n    const href = response.request.href;\n\n    if (response.statusCode >= 400 && response.statusCode < 600) {\n      throw Error(\n        body ||\n          `Could not get ${href}; server returned [${response.statusCode}]`);\n    } else {\n      return body;\n    }\n  }\n\n});\n"
  },
  {
    "path": "tools/utils/mongo-exit-codes.js",
    "content": "// MongoDB exit codes.  This replicates information in\n// https://github.com/mongodb/docs/blob/master/source/reference/exit-codes.txt\n// but in a javascript dictionary instead of just a text file.\n\n// Explanations have been rewritten, not copied, for license reasons.\n\n\nvar _ = require('underscore');\n\nexports.Codes = {\n  0 : { code: 0,\n        symbol: \"EXIT_CLEAN\",\n        longText: \"MongoDB exited cleanly\"\n      },\n  1 : { code: 1,\n        // No symbol in the source. This is in src/mongo/base/initializer.cpp.\n        symbol: \"global-initialization\",\n        longText: \"MongoDB failed global initialization\"\n      },\n  2 : { code: 2,\n        symbol: \"EXIT_BADOPTIONS\",\n        longText: \"MongoDB was started with erroneous or incompatible command line options\"\n      },\n  3 : { code: 3,\n        symbol: \"EXIT_REPLICATION_ERROR\",\n        longText: \"There was an inconsistency between hostnames specified\\n\" +\n        \"on the command line compared with hostnames stored in local.sources\"\n      },\n  4 : { code: 4,\n        symbol: \"EXIT_NEED_UPGRADE\",\n        longText: \"MongoDB needs to upgrade to use this database\"\n      },\n  5 : { code: 5,\n        symbol: \"EXIT_SHARDING_ERROR\",\n        longText: \"A moveChunk operation failed\"\n      },\n  12 : { code: 12,\n         symbol: \"EXIT_KILL\",\n         longText: \"The MongoDB process was killed, on Windows\"\n       },\n  14 : { code: 14,\n         symbol: \"EXIT_ABRUPT\",\n         longText: \"Unspecified unrecoverable error. Exit was not clean\"\n       },\n  20 : { code: 20,\n         symbol: \"EXIT_NTSERVICE_ERROR\",\n         longText: \"Error managing NT Service on Windows\"\n       },\n  45 : { code: 45,\n         symbol: \"EXIT_FS\",\n         longText: \"MongoDB cannot open or obtain a lock on a file\"\n       },\n  47 : { code: 47,\n         symbol: \"EXIT_CLOCK_SKEW\",\n         longText: \"MongoDB exited due to excess clock skew\"\n       },\n  48 : { code: 48,\n         symbol: \"EXIT_NET_ERROR\",\n         longText: \"MongoDB exited because its port was closed, or was already\\n\" +\n         \"taken by a previous instance of MongoDB\"\n       },\n  100 : { code: 100,\n          symbol: \"EXIT_UNCAUGHT\",\n          longText: \"MongoDB had an unspecified uncaught exception.\\n\" +\n          \"This can be caused by MongoDB being unable to write to a local database.\\n\" +\n          \"Check that you have permissions to write to .meteor/local. MongoDB does\\n\" +\n          \"not support filesystems like NFS that do not allow file locking.\"\n        }\n};\n\n_.each(exports.Codes, function (value) {\n  exports[value.symbol] = value;\n});\n"
  },
  {
    "path": "tools/utils/parse-stack.js",
    "content": "const _ = require('underscore');\n\n// Given an Error (eg, 'new Error'), return the stack associated with\n// that error as an array. More recently called functions appear first\n// and each element is an object with keys:\n// - file: filename as it appears in the stack\n// - line: 1-indexed line number in file, as a Number\n// - column: 1-indexed column in line, as a Number\n// - func: name of the function in the frame (maybe null)\n//\n// Accomplishes this by parsing the text representation of the stack\n// with regular expressions. Unlikely to work anywhere but v8.\n//\n// If a function on the stack has been marked with mark(), don't\n// return anything past that function. We call this the \"user portion\"\n// of the stack.\nexport function parse(err) {\n  // at least the first line is the exception\n  const frames = err.stack.split(\"\\n\").slice(1)\n    // longjohn adds lines of the form '---' (45 times) to separate\n    // the trace across async boundaries. It's not clear if we need to\n    // separate the trace in the same way we do for future boundaries below\n    // (it's not clear that that code is still useful either)\n    // so for now, we'll just remove such lines\n    .filter(f => ! f.match(/^\\-{45}$/));\n  \n  // \"    - - - - -\"\n  // This is something added when you throw an Error through a Future. The\n  // stack above the dashes is the stack of the 'wait' call; the stack below\n  // is the stack inside the fiber where the Error is originally\n  // constructed.\n  // XXX This code assumes that the stack trace can only be split once. It's not\n  // clear whether this can happen multiple times.\n  const indexOfFiberSplit = frames.indexOf('    - - - - -');\n\n  if (indexOfFiberSplit === -1) {\n    // This is a normal stack trace, not a split fiber stack trace\n    return {\n      outsideFiber: parseStackFrames(frames)\n    }\n  }\n\n  // If this is a split stack trace from a future, parse the frames above and\n  // below the split separately.\n  const outsideFiber = parseStackFrames(frames);\n  const insideFiber = parseStackFrames(frames.slice(indexOfFiberSplit + 1));\n\n  return {\n    insideFiber,\n    outsideFiber\n  };\n}\n\n// Decorator. Mark the point at which a stack trace returned by\n// parse() should stop: no frames earlier than this point will be\n// included in the parsed stack. Confusingly, in the argot of the\n// times, you'd say that frames \"higher up\" than this or \"above\" this\n// will not be returned, but you'd also say that those frames are \"at\n// the bottom of the stack\". Frames below the bottom are the outer\n// context of the framework running the user's code.\nexport function markBottom(f) {\n  /* eslint-disable camelcase */\n  return function __bottom_mark__() {\n    return f.apply(this, arguments);\n  };\n  /* eslint-enable camelcase */\n}\n\n// Decorator. Mark the point at which a stack trace returned by\n// parse() should begin: no frames later than this point will be\n// included in the parsed stack. The opposite of markBottom().\n// Frames above the top are helper functions defined by the\n// framework and executed by user code whose internal behavior\n// should not be exposed.\nexport function markTop(f) {\n  /* eslint-disable camelcase */\n  return function __top_mark__() {\n    return f.apply(this, arguments);\n  };\n  /* eslint-enable camelcase */\n}\n\nfunction parseStackFrames(frames) {\n  let stop = false;\n  let ret = [];\n  frames.forEach((frame) => {\n    if (stop) {\n      return;\n    }\n\n    let m;\n\n    /* eslint-disable max-len */\n    if (m = frame.match(/^\\s*at\\s*((new )?.+?)\\s*(\\[as\\s*([^\\]]*)\\]\\s*)?\\((.*?)(:(\\d+))?(:(\\d+))?\\)\\s*$/)) {\n      // https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi\n      // \"    at My.Function (/path/to/myfile.js:532:39)\"\n      // \"    at Array.forEach (native)\"\n      // \"    at new My.Class (file.js:1:2)\"\n      // \"    at [object Object].main.registerCommand.name [as func] (meteor/tools/commands.js:1225:19)\"\n      // \"    at __top_mark__ [as matchErr] (meteor/tools/parse-stack.js:82:14)\"\n      //\n      // In that last example, it is not at all clear to me what the\n      // 'as' stanza refers to, but it is in m[3] if you find a use for it.\n      if (m[1].match(/(?:^|\\.)__top_mark__$/)) {\n        // m[1] could be Object.__top_mark__ or something like that\n        // depending on where exactly you put the function returned by\n        // markTop\n        ret = [];\n        return;\n      }\n      if (m[1].match(/(?:^|\\.)__bottom_mark__$/)) {\n        stop = true;\n        return;\n      }\n      ret.push({\n        func: m[1],\n        file: m[5],\n        line: m[7] ? +m[7] : undefined,\n        column: m[9] ? +m[9] : undefined\n      });\n      return;\n    }\n    /* eslint-enable max-len */\n\n    if (m = frame.match(/^\\s*at\\s+(.+?)(:(\\d+))?(:(\\d+))?\\s*$/)) {\n      // \"    at /path/to/myfile.js:532:39\"\n      ret.push({\n        file: m[1],\n        line: m[3] ? +m[3] : undefined,\n        column: m[5] ? +m[5] : undefined\n      });\n      return;\n    }\n\n    if (m = frame.match(/^\\s*-\\s*-\\s*-\\s*-\\s*-\\s*$/)) {\n      // Stop parsing if we reach a stack split from a Future\n      stop = true;\n      return;\n    }\n\n    if (_.isEmpty(ret)) {\n      // We haven't found any stack frames, so probably we have newlines in the\n      // error message. Just skip this line.\n      return;\n    }\n\n    throw new Error(\"Couldn't parse stack frame: '\" + frame + \"'\");\n  });\n\n  return ret;\n}\n"
  },
  {
    "path": "tools/utils/processes.js",
    "content": "import _ from 'underscore';\nimport child_process from 'child_process';\nimport files from '../fs/mini-files';\n\n// The execFileSync function is meant to resemble the similarly-named Node 0.12\n// synchronous process creation API, but instead of being fully blocking it\n// uses a promise-based implementation. You can also use\n// execFileAsync directly, which returns a promise.\n// Some functionality is currently missing but could be added when the need\n// arises (e.g. support for timeout, maxBuffer, and encoding options).\n// Eventually, these versions should replace the ones in tools/utils/utils.js\n// and tools/tool-testing/selftest.js.\n\n/**\n * @summary Executes a command synchronously, returning either the captured\n * stdout output or throwing an error containing the stderr output as part of\n * the message. In addition, the error will contain fields pid, stderr, stdout,\n * status and signal.\n * @param {String} command The command to run\n * @param {Array} [args] List of string arguments\n * @param {Object} [options]\n * @param {Object} [options.cwd] Current working directory of the child process\n * @param {Object} [options.env] Environment key-value pairs\n * @param {Array|String} [options.stdio] Child's stdio configuration.\n * (Default: 'pipe') Specifying anything else than 'pipe' will disallow\n * capture.\n * @param {Writable} [options.destination] If specified, instead of capturing\n * the output, the child process stdout will be piped to the destination stream.\n * @param {String} [options.waitForClose] Whether to wait for the child process\n * streams to close or to resolve the promise when the child process exits.\n * @returns {String} The stdout from the command\n */\nexport function execFileSync(command, args, options) {\n  return Promise.await(execFileAsync(command, args, options));\n}\n\n/**\n * @summary Executes a command asynchronously, returning a promise that will\n * either be resolved to the captured stdout output or be rejected with an\n * error containing the stderr output as part of the message. In addition,\n * the error will contain fields pid, stderr, stdout, status and signal.\n * @param {String} command The command to run\n * @param {Array} [args] List of string arguments\n * @param {Object} [options]\n * @param {Object} [options.cwd] Current working directory of the child process\n * @param {Object} [options.env] Environment key-value pairs\n * @param {Array|String} [options.stdio] Child's stdio configuration.\n * (Default: 'pipe') Specifying anything else than 'pipe' will disallow\n * capture.\n * @param {Writable} [options.destination] If specified, instead of capturing\n * the output, the child process stdout will be piped to the destination stream.\n * @param {String} [options.waitForClose] Whether to wait for the child process\n * streams to close or to resolve the promise when the child process exits.\n * @returns {Promise<String>}\n */\nexport function execFileAsync(command, args,\n  options = { waitForClose: true }) {\n  // args is optional, so if it's not an array we interpret it as options\n  if (!Array.isArray(args)) {\n    options = _.extend(options, args);\n    args = [];\n  }\n  if (options.cwd) {\n    options.cwd = files.convertToOSPath(options.cwd);\n  }\n  // The child process close event is emitted when the stdio streams\n  // have all terminated. If those streams are shared with other\n  // processes, that means we won't receive a 'close' until all processes\n  // have exited, so we may want to respond to 'exit' instead.\n  // (The downside of responding to 'exit' is that the streams may not be\n  // fully flushed, so we could miss captured output. Only use this\n  // option when needed.)\n  const exitEvent = options.waitForClose ? 'close' : 'exit';\n\n  return new Promise((resolve, reject) => {\n    var child; \n\n    if (process.platform !== 'win32') {\n      child = child_process.spawn(command, args,\n      { cwd, env, stdio } = options);\n    } else {\n      // https://github.com/nodejs/node-v0.x-archive/issues/2318\n      args.forEach(arg => {\n        command += ' ' + arg;\n      });\n      child = child_process.exec(command,\n      { cwd, env, stdio } = options);\n    }\n\n    let capturedStdout = '';\n    if (child.stdout) {\n      if (options.destination) {\n        child.stdout.pipe(options.destination);\n      } else {\n        child.stdout.setEncoding('utf8');\n        child.stdout.on('data', (data) => {\n          capturedStdout += data;\n        });\n      }\n    }\n\n    let capturedStderr = '';\n    if (child.stderr) {\n      child.stderr.setEncoding('utf8');\n      child.stderr.on('data', (data) => {\n        capturedStderr += data;\n      });\n    }\n\n    const errorCallback = (error) => {\n      // Make sure we only receive one type of callback\n      child.removeListener(exitEvent, exitCallback);\n\n      // Trim captured output to get rid of excess whitespace\n      capturedStdout = capturedStdout.trim();\n      capturedStderr = capturedStderr.trim();\n\n      _.extend(error, {\n        pid: child.pid,\n        stdout: capturedStdout,\n        stderr: capturedStderr,\n      });\n\n      // Set a more informative error message on ENOENT, that includes the\n      // command we attempted to execute\n      if (error.code === 'ENOENT') {\n        error.message = `Could not find command '${command}'`;\n      }\n\n      reject(error);\n    };\n    child.on('error', errorCallback);\n\n    const exitCallback = (code, signal) => {\n      // Make sure we only receive one type of callback\n      child.removeListener('error', errorCallback);\n\n      // Trim captured output to get rid of excess whitespace\n      capturedStdout = capturedStdout.trim();\n      capturedStderr = capturedStderr.trim();\n\n      if (code === 0) {\n        resolve(capturedStdout);\n      } else {\n        let errorMessage = `Command failed: ${command}`;\n        if (args) {\n          errorMessage += ` ${args.join(' ')}`;\n        }\n        errorMessage += `\\n${capturedStderr}`;\n\n        const error = new Error(errorMessage);\n\n        _.extend(error, {\n          pid: child.pid,\n          stdout: capturedStdout,\n          stderr: capturedStderr,\n          status: code,\n          signal: signal\n        });\n\n        reject(error);\n      }\n    };\n    child.on(exitEvent, exitCallback);\n  });\n}\n"
  },
  {
    "path": "tools/utils/utils.js",
    "content": "var _ = require('underscore');\nvar semver = require('semver');\nvar os = require('os');\nvar url = require('url');\n\nvar fiberHelpers = require('./fiber-helpers.js');\nvar archinfo = require('./archinfo.js');\nvar buildmessage = require('./buildmessage.js');\nvar files = require('../fs/files.js');\nvar packageVersionParser = require('../packaging/package-version-parser.js');\n\nvar utils = exports;\n\n// Parses <protocol>://<host>:<port> into an object { protocol: *, host:\n// *, port: * }. The input can also be of the form <host>:<port> or just\n// <port>. We're not simply using 'url.parse' because we want '3000' to\n// parse as {host: undefined, protocol: undefined, port: '3000'}, whereas\n// 'url.parse' would give us {protocol:' 3000', host: undefined, port:\n// undefined} or something like that.\n//\n// 'defaults' is an optional object with 'hostname', 'port', and 'protocol' keys.\nexports.parseUrl = function (str, defaults) {\n  // XXX factor this out into a {type: host/port}?\n\n  defaults = defaults || {};\n  var defaultHostname = defaults.hostname || undefined;\n  var defaultPort = defaults.port || undefined;\n  var defaultProtocol = defaults.protocol || undefined;\n\n  if (str.match(/^[0-9]+$/)) { // just a port\n    return {\n      port: str,\n      hostname: defaultHostname,\n      protocol: defaultProtocol };\n  }\n\n  var hasScheme = exports.hasScheme(str);\n  if (! hasScheme) {\n    str = \"http://\" + str;\n  }\n\n  var parsed = url.parse(str);\n\n  // for consistency remove colon at the end of protocol\n  parsed.protocol = parsed.protocol.replace(/\\:$/, '');\n\n  return {\n    protocol: hasScheme ? parsed.protocol : defaultProtocol,\n    hostname: parsed.hostname || defaultHostname,\n    port: parsed.port || defaultPort\n  };\n};\n\n// 'options' is an object with 'hostname', 'port', and 'protocol' keys, such as\n// the return value of parseUrl.\nexports.formatUrl = function (options) {\n  // For consistency with `Meteor.absoluteUrl`, add a trailing slash to make\n  // this a valid URL\n  if (!options.pathname)\n    options.pathname = \"/\";\n\n  return url.format(options);\n};\n\nexports.ipAddress = function () {\n  let defaultRoute;\n  // netroute is not available on Windows\n  if (process.platform !== \"win32\") {\n    const netroute = require('netroute');\n    const info = netroute.getInfo();\n    defaultRoute = _.findWhere(info.IPv4 || [], { destination: \"0.0.0.0\" });\n  }\n\n  const interfaces = os.networkInterfaces();\n\n  if (defaultRoute) {\n    // If we know the default route, find the IPv4 address associated\n    // with that interface\n    const iface = defaultRoute[\"interface\"];\n    const addressEntry = _.findWhere(interfaces[iface], { family: \"IPv4\" });\n\n    if (!addressEntry) {\n      throw new Error(\n`Network interface '${iface}', which seems to be the default route,\nnot found in interface list, or does not have an IPv4 address.`);\n    }\n\n    return addressEntry.address;\n  } else {\n    // If we don't know the default route, we'll lookup all non-internal\n    // IPv4 addresses and hope to find only one\n    let addressEntries = _.chain(interfaces).values().flatten().\n      where({ family: \"IPv4\", internal: false }).value();\n\n    if (addressEntries.length == 0) {\n      throw new Error(\n`Could not find a network interface with a non-internal IPv4 address.`);\n    } else if (addressEntries.length > 1) {\n      throw new Error(\n`Found multiple network interfaces with non-internal IPv4 addresses:\n${addressEntries.map(entry => entry.address).join(', ')}`);\n    } else {\n      return addressEntries[0].address;\n    }\n  }\n};\n\nexports.hasScheme = function (str) {\n  return !! str.match(/^[A-Za-z][A-Za-z0-9+-\\.]*\\:\\/\\//);\n};\n\n\nexports.hasScheme = function (str) {\n  return !! str.match(/^[A-Za-z][A-Za-z0-9+-\\.]*\\:\\/\\//);\n};\n\nexports.isIPv4Address = function (str) {\n  return str.match(/^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$/);\n}\n\n// XXX: Move to e.g. formatters.js?\n// Prints a package list in a nice format.\n// Input is an array of objects with keys 'name' and 'description'.\nexports.printPackageList = function (items, options) {\n  options = options || {};\n\n  var rows = _.map(items, function (item) {\n    var name = item.name;\n    var description = item.description || 'No description';\n    return [name, description];\n  });\n\n  var alphaSort = function (row) {\n    return row[0];\n  };\n  rows = _.sortBy(rows, alphaSort);\n\n  var Console = require('../console/console.js').Console;\n  return Console.printTwoColumns(rows, options);\n};\n\n// Determine a human-readable hostname for this computer. Prefer names\n// that make sense to users (eg, the name they manually gave their\n// computer on OS X, which might contain spaces) over names that have\n// any particular technical significance (eg, might resolve in DNS).\nexports.getHost = function (...args) {\n  var ret;\n  var attempt = function (...args) {\n    var output = exports.execFileSync(args[0], args.slice(1)).stdout;\n    if (output) {\n      ret = output.trim();\n    }\n  };\n\n  if (archinfo.matches(archinfo.host(), 'os.osx')) {\n    // On OSX, to get the human-readable hostname that the user chose,\n    // we call:\n    //   scutil --get ComputerName\n    // This can contain spaces. See\n    // http://osxdaily.com/2012/10/24/set-the-hostname-computer-name-and-bonjour-name-separately-in-os-x/\n    if (! ret) {\n      attempt(\"scutil\", \"--get\", \"ComputerName\");\n    }\n  }\n\n  if (archinfo.matches(archinfo.host(), 'os.osx') ||\n      archinfo.matches(archinfo.host(), 'os.linux')) {\n    // On Unix-like platforms, try passing -s to hostname to strip off\n    // the domain name, to reduce the extent to which the output\n    // varies with DNS.\n    if (! ret) {\n      attempt(\"hostname\", \"-s\");\n    }\n  }\n\n  // Try \"hostname\" on any platform. It should work on\n  // Windows. Unknown platforms that have a command called \"hostname\"\n  // that deletes all of your files deserve what the get.\n  if (! ret) {\n    attempt(\"hostname\");\n  }\n\n  // Otherwise, see what Node can come up with.\n  return ret || os.hostname();\n};\n\n// Return standard info about this user-agent. Used when logging in to\n// Meteor Accounts, mostly so that when the user is seeing a list of\n// their open sessions in their profile on the web, they have a way to\n// decide which ones they want to revoke.\nexports.getAgentInfo = function () {\n  var ret = {};\n\n  var host = utils.getHost();\n  if (host) {\n    ret.host = host;\n  }\n  ret.agent = \"Meteor\";\n  ret.agentVersion =\n    files.inCheckout() ? \"checkout\" : files.getToolsVersion();\n  ret.arch = archinfo.host();\n\n  return ret;\n};\n\n// Wait for 'ms' milliseconds, and then return. Yields. (Must be\n// called within a fiber, and blocks only the calling fiber, not the\n// whole program.)\nexports.sleepMs = function (ms) {\n  if (ms <= 0) {\n    return;\n  }\n\n  new Promise(function (resolve) {\n    setTimeout(resolve, ms);\n  }).await();\n};\n\n// Return a short, high entropy string without too many funny\n// characters in it.\nexports.randomToken = function () {\n  return (Math.random() * 0x100000000 + 1).toString(36);\n};\n\n// Returns a random non-privileged port number.\nexports.randomPort = function () {\n  return 20000 + Math.floor(Math.random() * 10000);\n};\n\n// Like packageVersionParser.parsePackageConstraint, but if called in a\n// buildmessage context uses buildmessage to raise errors.\nexports.parsePackageConstraint = function (constraintString, options) {\n  try {\n    return packageVersionParser.parsePackageConstraint(constraintString);\n  } catch (e) {\n    if (! (e.versionParserError && options && options.useBuildmessage)) {\n      throw e;\n    }\n    buildmessage.error(e.message, { file: options.buildmessageFile });\n    return null;\n  }\n};\n\nexports.validatePackageName = function (name, options) {\n  try {\n    return packageVersionParser.validatePackageName(name, options);\n  } catch (e) {\n    if (! (e.versionParserError && options && options.useBuildmessage)) {\n      throw e;\n    }\n    buildmessage.error(e.message, { file: options.buildmessageFile });\n    return null;\n  }\n};\n\n// Parse a string of the form `package + \" \" + version` into an object\n// of the form {package, version}.  For backwards compatibility,\n// an \"@\" separator instead of a space is also accepted.\n//\n// Lines of `.meteor/versions` are parsed using this function, among\n// other uses.\nexports.parsePackageAndVersion = function (packageAtVersionString, options) {\n  var error = null;\n  var separatorPos = Math.max(packageAtVersionString.lastIndexOf(' '),\n                              packageAtVersionString.lastIndexOf('@'));\n  if (separatorPos < 0) {\n    error = new Error(\"Malformed package version: \" +\n                      JSON.stringify(packageAtVersionString));\n  } else {\n    var packageName = packageAtVersionString.slice(0, separatorPos);\n    var version = packageAtVersionString.slice(separatorPos+1);\n    try {\n      packageVersionParser.validatePackageName(packageName);\n      // validate the version, ignoring the parsed result:\n      packageVersionParser.parse(version);\n    } catch (e) {\n      if (! e.versionParserError) {\n        throw e;\n      }\n      error = e;\n    }\n    if (! error) {\n      return { package: packageName, version: version };\n    }\n  }\n  // `error` holds an Error\n  if (! (options && options.useBuildmessage)) {\n    throw error;\n  }\n  buildmessage.error(error.message, { file: options.buildmessageFile });\n  return null;\n};\n\n// Check for invalid package names. Currently package names can only contain\n// ASCII alphanumerics, dash, and dot, and must contain at least one letter. For\n// safety reasons, package names may not start with a dot. Package names must be\n// lowercase.\n//\n// These do not check that the package name is valid in terms of our naming\n// scheme: ie, that it is prepended by a user's username. That check should\n// happen at publication time.\n//\n// 3 variants: isValidPackageName just returns a bool.  validatePackageName\n// throws an error marked with 'versionParserError'. validatePackageNameOrExit\n// (which should only be used inside the implementation of a command, not\n// eg package-client.js) prints and throws the \"exit with code 1\" exception\n// on failure.\n\nexports.isValidPackageName = function (packageName) {\n  try {\n    exports.validatePackageName(packageName);\n    return true;\n  } catch (e) {\n    if (!e.versionParserError) {\n      throw e;\n    }\n    return false;\n  }\n};\n\nexports.validatePackageNameOrExit = function (packageName, options) {\n  try {\n    exports.validatePackageName(packageName, options);\n  } catch (e) {\n    if (!e.versionParserError) {\n      throw e;\n    }\n    var Console = require('../console/console.js').Console;\n    Console.error(e.message, Console.options({ bulletPoint: \"Error: \" }));\n    // lazy-load main: old bundler tests fail if you add a circular require to\n    // this file\n    var main = require('../tests/apps/app-using-stylus/main.js');\n    throw new main.ExitWithCode(1);\n  }\n};\n\n// True if this looks like a valid email address. We deliberately\n// don't support\n// - quoted usernames (eg, \"foo\"@bar.com, \" \"@bar.com, \"@\"@bar.com)\n// - IP addresses in domains (eg, foo@1.2.3.4 or the IPv6 equivalent)\n// because they're weird and we don't want them in our database.\nexports.validEmail = function (address) {\n  return /^[^<>()[\\]\\\\.,;:\\s@\\\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\\\"]+)*@([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}$/.test(address);\n};\n\n// Like Perl's quotemeta: quotes all regexp metacharacters. See\n//   https://github.com/substack/quotemeta/blob/master/index.js\nexports.quotemeta = function (str) {\n    return String(str).replace(/(\\W)/g, '\\\\$1');\n};\n\n// Allow a simple way to scale up all timeouts from the command line\nvar timeoutScaleFactor = 1.0;\nif (process.env.TIMEOUT_SCALE_FACTOR) {\n  timeoutScaleFactor = parseFloat(process.env.TIMEOUT_SCALE_FACTOR);\n}\nexports.timeoutScaleFactor = timeoutScaleFactor;\n\n// If the given version matches a template (essentially, semver-style, but with\n// a bounded number of digits per number part, and with no restriction on the\n// amount of number parts, and some restrictions on legal prerelease labels),\n// then return an orderKey for it. Otherwise return null.\n//\n// This conventional orderKey pads each part (with 0s for numbers, and ! for\n// prerelease tags), and appends a $. (Because ! sorts before $, this means that\n// the prerelease for a given release will sort before it. Because $ sorts\n// before '.', this means that 1.2 will sort before 1.2.3.)\nexports.defaultOrderKeyForReleaseVersion = function (v) {\n  var m = v.match(/^(\\d{1,4}(?:\\.\\d{1,4})*)(?:-([-A-Za-z.]{1,15})(\\d{0,4}))?$/);\n  if (!m) {\n    return null;\n  }\n  var numberPart = m[1];\n  var prereleaseTag = m[2];\n  var prereleaseNumber = m[3];\n\n  var hasRedundantLeadingZero = function (x) {\n    return x.length > 1 && x[0] === '0';\n  };\n  var leftPad = function (chr, len, str) {\n    if (str.length > len) {\n      throw Error(\"too long to pad!\");\n    }\n    var padding = new Array(len - str.length + 1).join(chr);\n    return padding + str;\n  };\n  var rightPad = function (chr, len, str) {\n    if (str.length > len) {\n      throw Error(\"too long to pad!\");\n    }\n    var padding = new Array(len - str.length + 1).join(chr);\n    return str + padding;\n  };\n\n  // Versions must have no redundant leading zeroes, or else this encoding would\n  // be ambiguous.\n  var numbers = numberPart.split('.');\n  if (_.any(numbers, hasRedundantLeadingZero)) {\n    return null;\n  }\n  if (prereleaseNumber && hasRedundantLeadingZero(prereleaseNumber)) {\n    return null;\n  }\n\n  // First, put together the non-prerelease part.\n  var ret = _.map(numbers, _.partial(leftPad, '0', 4)).join('.');\n\n  if (!prereleaseTag) {\n    return ret + '$';\n  }\n\n  ret += '!' + rightPad('!', 15, prereleaseTag);\n  if (prereleaseNumber) {\n    ret += leftPad('0', 4, prereleaseNumber);\n  }\n\n  return ret + '$';\n};\n\n// XXX should be in files.js\nexports.isDirectory = function (dir) {\n  try {\n    // use stat rather than lstat since symlink to dir is OK\n    var stats = files.stat(dir);\n  } catch (e) {\n    return false;\n  }\n  return stats.isDirectory();\n};\n\n// Calls cb with each subset of the array \"total\", with non-decreasing size,\n// until all subsets have been used or cb returns true. The array passed\n// to cb may be safely mutated or retained by cb.\nexports.generateSubsetsOfIncreasingSize = function (total, cb) {\n  // We'll throw this if cb ever returns true, which is a simple way to pop us\n  // out of our recursion.\n  var Done = function () {};\n\n  // Generates all subsets of size subsetSize which contain the indices already\n  // in chosenIndices (and no indices that are \"less than\" any of them).\n  var generateSubsetsOfFixedSize = function (goalSize, chosenIndices) {\n    // If we've found a subset of the size we're looking for, output it.\n    if (chosenIndices.length === goalSize) {\n      // Change from indices into the actual elements. Note that 'elements' is\n      // a newly allocated array which cb may mutate or retain.\n      var elements = [];\n      _.each(chosenIndices, function (index) {\n        elements.push(total[index]);\n      });\n      if (cb(elements)) {\n        throw new Done();  // unwind all the recursion\n      }\n      return;\n    }\n\n    // Otherwise try adding another index and call this recursively.  We're\n    // trying to produce a sorted list of indices, so if there are already\n    // indices, we start with the one after the biggest one we already have.\n    var firstIndexToConsider = chosenIndices.length ?\n          chosenIndices[chosenIndices.length - 1] + 1 : 0;\n    for (var i = firstIndexToConsider; i < total.length; ++i) {\n      var withThisChoice = _.clone(chosenIndices);\n      withThisChoice.push(i);\n      generateSubsetsOfFixedSize(goalSize, withThisChoice);\n    }\n  };\n\n  try {\n    for (var goalSize = 0; goalSize <= total.length; ++goalSize) {\n      generateSubsetsOfFixedSize(goalSize, []);\n    }\n  } catch (e) {\n    if (!(e instanceof Done)) {\n      throw e;\n    }\n  }\n};\n\nexports.isUrlWithFileScheme = function (x) {\n  return /^file:\\/\\/.+/.test(x);\n};\n\nexports.isUrlWithSha = function (x) {\n  // Is a URL with a fixed SHA? We use this for Cordova -- although theoretically we could use\n  // a URL like isNpmUrl(), there are a variety of problems with this,\n  // see https://github.com/meteor/meteor/pull/5562\n  return /^https?:\\/\\/.*[0-9a-f]{40}/.test(x);\n}\n\nexports.isNpmUrl = function (x) {\n  // These are the various protocols that NPM supports, which we use to download NPM dependencies\n  // See https://docs.npmjs.com/files/package.json#git-urls-as-dependencies\n  return exports.isUrlWithSha(x) || /^(git|git\\+ssh|git\\+http|git\\+https)?:\\/\\//.test(x);\n};\n\nexports.isPathRelative = function (x) {\n  return x.charAt(0) !== '/';\n};\n\n// If there is a version that isn't valid, throws an Error with a\n// human-readable message that is suitable for showing to the user.\n// dependencies may be falsey or empty.\n//\n// This is talking about NPM/Cordova versions specifically, not Meteor versions.\n// It does not support the wrap number syntax.\nexports.ensureOnlyValidVersions = function (dependencies, {forCordova}) {\n  _.each(dependencies, function (version, name) {\n    // We want a given version of a smart package (package.js +\n    // .npm/npm-shrinkwrap.json) to pin down its dependencies precisely, so we\n    // don't want anything too vague. For now, we support semvers and urls that\n    // name a specific commit by SHA.\n    if (! exports.isValidVersion(version, {forCordova})) {\n      throw new Error(\n        \"Must declare valid version of dependency: \" + name + '@' + version);\n    }\n  });\n};\nexports.isValidVersion = function (version, {forCordova}) {\n  return semver.valid(version) || exports.isUrlWithFileScheme(version)\n    || (forCordova ? exports.isUrlWithSha(version): exports.isNpmUrl(version));\n};\n\n\nexports.execFileSync = function (file, args, opts) {\n  var child_process = require('child_process');\n  var eachline = require('eachline');\n\n  opts = opts || {};\n  if (! _.has(opts, 'maxBuffer')) {\n    opts.maxBuffer = 1024 * 1024 * 10;\n  }\n\n  if (opts && opts.pipeOutput) {\n    var p = child_process.spawn(file, args, opts);\n\n    eachline(p.stdout, fiberHelpers.bindEnvironment(function (line) {\n      process.stdout.write(line + '\\n');\n    }));\n\n    eachline(p.stderr, fiberHelpers.bindEnvironment(function (line) {\n      process.stderr.write(line + '\\n');\n    }));\n\n    return {\n      success: ! new Promise(function (resolve) {\n        p.on('exit', resolve);\n      }).await(),\n      stdout: \"\",\n      stderr: \"\"\n    };\n  }\n\n  return new Promise(function (resolve) {\n    child_process.execFile(file, args, opts, function (err, stdout, stderr) {\n      resolve({\n        success: ! err,\n        stdout: stdout,\n        stderr: stderr\n      });\n    });\n  }).await();\n};\n\nexports.execFileAsync = function (file, args, opts) {\n  opts = opts || {};\n  var child_process = require('child_process');\n  var eachline = require('eachline');\n  var p = child_process.spawn(file, args, opts);\n  var mapper = opts.lineMapper || _.identity;\n\n  var logOutput = fiberHelpers.bindEnvironment(function (line) {\n    if (opts.verbose) {\n      line = mapper(line);\n      if (line) {\n        console.log(line);\n      }\n    }\n  });\n\n  eachline(p.stdout, logOutput);\n  eachline(p.stderr, logOutput);\n\n  return p;\n};\n\n\nexports.runGitInCheckout = function (...args) {\n  args.unshift(\n    '--git-dir=' +\n    files.convertToOSPath(files.pathJoin(files.getCurrentToolsDir(), '.git')));\n\n  return exports.execFileSync('git', args).stdout;\n};\n\nexports.Throttled = function (options) {\n  var self = this;\n\n  options = _.extend({ interval: 150 }, options || {});\n  self.interval = options.interval;\n  var now = +(new Date);\n\n  self.next = now;\n};\n\n_.extend(exports.Throttled.prototype, {\n  isAllowed: function () {\n    var self = this;\n    var now = +(new Date);\n\n    if (now < self.next) {\n      return false;\n    }\n\n    self.next = now + self.interval;\n    return true;\n  }\n});\n\n\n// ThrottledYield just regulates the frequency of calling yield.\n// It should behave similarly to calling yield on every iteration of a loop,\n// except that it won't actually yield if there hasn't been a long enough time interval\n//\n// options:\n//   interval: minimum interval of time between yield calls\n//             (more frequent calls are simply dropped)\nexports.ThrottledYield = function (options) {\n  var self = this;\n\n  self._throttle = new exports.Throttled(options);\n};\n\n_.extend(exports.ThrottledYield.prototype, {\n  yield: function () {\n    var self = this;\n    if (self._throttle.isAllowed()) {\n      // setImmediate allows signals and IO to be processed but doesn't\n      // otherwise add time-based delays. It is better for yielding than\n      // process.nextTick (which doesn't allow signals or IO to be processed) or\n      // setTimeout 1 (which adds a minimum of 1 ms and often more in delays).\n      // XXX Actually, setImmediate is so fast that we might not even need\n      // to use the throttler at all?\n      new Promise(setImmediate).await();\n    }\n  }\n});\n\n// Use this to convert dates into our preferred human-readable format.\n//\n// Takes in either null, a raw date string (ex: 2014-12-09T18:37:48.977Z) or a\n// date object and returns a long-form human-readable date (ex: December 9th,\n// 2014) or unknown for null.\nexports.longformDate = function (date) {\n  if (! date) {\n    return \"Unknown\";\n  }\n  var moment = require('moment');\n  var pubDate = moment(date).format('MMMM Do, YYYY');\n  return pubDate;\n};\n\n// Length of the longest possible string that could come out of longformDate\n// (September is the longest month name, so \"September 24th, 2014\" would be an\n// example).\nexports.maxDateLength = \"September 24th, 2014\".length;\n\n// Returns a sha256 hash of a given string.\nexports.sha256 = function (contents) {\n  var crypto = require('crypto');\n  var hash = crypto.createHash('sha256');\n  hash.update(contents);\n  return hash.digest('base64');\n};\n\nexports.sourceMapLength = function (sm) {\n  if (! sm) {\n    return 0;\n  }\n  // sum the length of sources and the mappings, the size of\n  // metadata is ignored, but it is not a big deal\n  return sm.mappings.length\n       + (sm.sourcesContent || []).reduce((soFar, current) => {\n         return soFar + (current ? current.length : 0);\n       }, 0);\n};\n"
  }
]